@ehfuse/mui-virtual-data-table 1.0.9 → 1.0.10
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/dist/index.esm.js +2 -2
- package/dist/index.esm.js.map +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +2 -2
- package/package.json +1 -1
package/dist/index.esm.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/VirtualDataTable.tsx", "../node_modules/@ehfuse/mui-fadeout-loading-progress/node_modules/tslib/tslib.es6.js", "../node_modules/@ehfuse/mui-fadeout-loading-progress/src/LoadingProgress.tsx", "../node_modules/@ehfuse/overlay-scrollbar/src/OverlayScrollbar.tsx", "../node_modules/@ehfuse/overlay-scrollbar/src/utils/dragScrollUtils.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * VirtualDataTable.tsx\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 React, {\n forwardRef,\n useCallback,\n useMemo,\n useRef,\n useEffect,\n memo,\n useState,\n} from \"react\";\nimport {\n Box,\n Table,\n TableBody as MuiTableBody,\n TableCell,\n TableContainer,\n TableHead,\n TableRow as MuiTableRow,\n TableSortLabel,\n Paper,\n Typography,\n} from \"@mui/material\";\nimport { TableVirtuoso } from \"react-virtuoso\";\nimport type { TableComponents } from \"react-virtuoso\";\nimport { LoadingProgress } from \"@ehfuse/mui-fadeout-loading-progress\";\n\nimport OverlayScrollbar from \"@ehfuse/overlay-scrollbar\";\nimport type { DataColumn, SortDirection, VirtualDataTableProps } from \"./types\";\n\n// OverlayScrollbar \uC124\uC815\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 OVERLAY_SCROLLBAR_TRACK_CONFIG = {\n alignment: \"right\" as const,\n margin: 0,\n radius: 0,\n};\n\n/**\n * \uB370\uC774\uD130 \uAE30\uBC18 \uBB34\uD55C \uC2A4\uD06C\uB864 \uBC0F \uAC00\uC0C1\uD654\uB97C \uC9C0\uC6D0\uD558\uB294 \uD14C\uC774\uBE14 \uCEF4\uD3EC\uB10C\uD2B8\n */\nfunction VirtualDataTableComponent<T>({\n data,\n loading = false,\n columns,\n onRowClick,\n rowHeight = 50,\n columnHeight = 56,\n striped,\n rowDivider = true,\n onSort,\n onLoadMore,\n sortBy,\n sortDirection,\n showPaper = true,\n paddingX = \"1rem\",\n paddingTop = 0,\n paddingBottom = 0,\n rowHoverColor,\n rowHoverOpacity,\n scrollbars,\n emptyMessage = \"NO DATA\",\n LoadingComponent,\n}: VirtualDataTableProps<T>) {\n // \uAC01 \uD14C\uC774\uBE14 \uC778\uC2A4\uD134\uC2A4\uBCC4\uB85C Scroller \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131 (scrollbars, paddingX\uB97C \uCD08\uAE30\uAC12\uC73C\uB85C \uACE0\uC815)\n const VirtuosoScroller = useMemo(\n () =>\n forwardRef<HTMLDivElement, any>((props, ref) => {\n const scrollContainerRef = useRef<HTMLElement | null>(null);\n\n return (\n <OverlayScrollbar\n detectInnerScroll={true}\n track={OVERLAY_SCROLLBAR_TRACK_CONFIG}\n {...scrollbars}\n >\n <TableContainer\n component={Box}\n {...props}\n ref={(node) => {\n scrollContainerRef.current =\n node as HTMLElement;\n if (typeof ref === \"function\") {\n ref(node as HTMLDivElement);\n } else if (ref) {\n ref.current = node as HTMLDivElement;\n }\n }}\n sx={{\n userSelect: \"auto\",\n WebkitUserSelect: \"auto\",\n position: \"relative\",\n width: \"100%\",\n height: \"100%\",\n overflow: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n scrollbarWidth: \"none\",\n msOverflowStyle: \"none\",\n // \uAE5C\uBC15\uC784 \uBC29\uC9C0\uB97C \uC704\uD55C GPU \uAC00\uC18D\n transform: \"translateZ(0)\",\n backfaceVisibility: \"hidden\",\n willChange: \"scroll-position\",\n \"&::-webkit-scrollbar\": {\n display: \"none\",\n },\n \"& .MuiTable-root\": {\n paddingRight: paddingX,\n paddingTop: paddingTop,\n paddingBottom: paddingBottom,\n },\n }}\n />\n </OverlayScrollbar>\n );\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [] // \uBE48 \uBC30\uC5F4: \uCD5C\uCD08 \uB9C8\uC6B4\uD2B8 \uC2DC\uC5D0\uB9CC \uC0DD\uC131, scrollbars, paddingX, paddingTop, paddingBottom\uC740 \uD074\uB85C\uC800\uB85C \uACE0\uC815\n );\n\n // Striped row \uBC30\uACBD\uC0C9 \uACC4\uC0B0\n const stripedRowColor = useMemo(() => {\n if (striped === true) {\n return \"#f5f5f5\"; // \uAE30\uBCF8 \uD68C\uC0C9\n } else if (typeof striped === \"string\") {\n return striped; // \uC0AC\uC6A9\uC790 \uC9C0\uC815 \uC0C9\uC0C1\n }\n return undefined; // \uBC30\uACBD\uC0C9 \uC5C6\uC74C\n }, [striped]);\n\n // \uB85C\uB529 \uC0C1\uD0DC \uAD00\uB9AC (\uC6D0\uBCF8 \uBC29\uC2DD)\n const [internalLoading, setInternalLoading] = useState(loading);\n\n // \uD14C\uC774\uBE14 \uC7AC\uB9C8\uC6B4\uD2B8\uB97C \uC704\uD55C \uD0A4 (\uB370\uC774\uD130\uAC00 \uBE44\uC6CC\uC9C0\uBA74 \uC7AC\uB9C8\uC6B4\uD2B8)\n const [tableKey, setTableKey] = useState(0);\n\n // \uB85C\uB529 \uC0C1\uD0DC \uBCC0\uACBD \uAC10\uC9C0\n useEffect(() => {\n if (loading) {\n // \uB85C\uB529\uC774 \uC2DC\uC791\uB418\uBA74 \uC989\uC2DC \uD45C\uC2DC\n setInternalLoading(true);\n }\n // \uB85C\uB529\uC774 \uB05D\uB098\uB3C4 internalLoading\uC740 handleLoadingComplete\uC5D0\uC11C\uB9CC false\uB85C \uC124\uC815\n // LoadingProgress\uC5D0\uC11C\uB294 visible={false}\uB85C \uD398\uC774\uB4DC\uC544\uC6C3\uC744 \uC2DC\uC791\uD568\n }, [loading]);\n\n // \uB85C\uB529 \uC644\uB8CC \uD578\uB4E4\uB7EC - LoadingProgress\uC758 \uD398\uC774\uB4DC\uC544\uC6C3\uC774 \uC644\uB8CC\uB41C \uD6C4 \uD638\uCD9C\uB428\n const handleLoadingComplete = useCallback(() => {\n setInternalLoading(false);\n }, []);\n\n // \uB85C\uB529 \uC624\uBC84\uB808\uC774 \uD45C\uC2DC \uC870\uAC74\n const shouldShowLoading = internalLoading;\n\n // \uB354\uBCF4\uAE30 \uB85C\uB529 \uC5EC\uBD80 (\uB370\uC774\uD130\uAC00 \uC788\uACE0 \uB85C\uB529 \uC911\uC774\uBA74 \uB354\uBCF4\uAE30 \uB85C\uB529)\n const isLoadMoreLoading = loading && data.length > 0;\n\n // \uBB34\uD55C \uC2A4\uD06C\uB864 \uB85C\uB529 \uC0C1\uD0DC (\uAE30\uC874 VirtualDataTable \uBC29\uC2DD)\n const isLoadingMoreRef = useRef(false);\n const virtuosoRef = useRef<any>(null); // TableVirtuoso ref\n\n // \uC2A4\uD06C\uB864 \uCEE8\uD14C\uC774\uB108 \uCC38\uC870 (OverlayScrollbar\uC6A9)\n const scrollContainerRef = useRef<HTMLElement | null>(null); // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uC0C1\uD0DC (OverlayScrollbar \uC0AC\uC6A9\uC2DC\uC5D0\uB294 \uBE44\uD65C\uC131\uD654)\n const isDraggingRef = useRef(false);\n const dragStartRef = useRef({ x: 0, y: 0, scrollTop: 0 });\n const isMouseDownRef = useRef(false);\n const initialScrollTopRef = useRef(0);\n const totalDragDistanceRef = useRef(0);\n const isScrollDraggingRef = useRef(false); // OverlayScrollbar \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uAC10\uC9C0\uC6A9\n const mouseDownPositionRef = useRef({ x: 0, y: 0 }); // \uB9C8\uC6B0\uC2A4 \uB2E4\uC6B4 \uC2DC\uC791 \uC704\uCE58\n const scrollDragTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n /**\n * \uB9C8\uC6B0\uC2A4 \uBC84\uD2BC \uB204\uB984 \uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC\n * OverlayScrollbar \uC0AC\uC6A9\uC2DC\uC5D0\uB294 \uAE30\uBCF8 \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864\uC744 \uBE44\uD65C\uC131\uD654\n */\n const handleMouseDown = useCallback(\n (e: React.MouseEvent<HTMLDivElement>) => {\n // OverlayScrollbar\uB97C \uC0AC\uC6A9\uD558\uBBC0\uB85C \uAE30\uBCF8 \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uBE44\uD65C\uC131\uD654\n // OverlayScrollbar\uAC00 \uC790\uCCB4\uC801\uC73C\uB85C \uC2A4\uD06C\uB864\uC744 \uCC98\uB9AC\uD568\n return;\n },\n []\n );\n\n /**\n * \uB9C8\uC6B0\uC2A4 \uC774\uB3D9 \uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC\n * \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uAE30\uB2A5\uC758 \uD575\uC2EC \uB85C\uC9C1\n */\n const handleMouseMove = useCallback((e: MouseEvent) => {\n if (!isMouseDownRef.current || !scrollContainerRef.current) return;\n\n const deltaY = e.clientY - dragStartRef.current.y;\n const threshold = 5; // \uB4DC\uB798\uADF8 \uAC10\uC9C0 \uC784\uACC4\uAC12\n\n // \uC784\uACC4\uAC12\uC744 \uB118\uC5B4\uC57C \uB4DC\uB798\uADF8\uB85C \uC778\uC2DD\n if (!isDraggingRef.current && Math.abs(deltaY) > threshold) {\n isDraggingRef.current = true;\n\n // DOM \uC2A4\uD0C0\uC77C \uC9C1\uC811 \uBCC0\uACBD (\uB9AC\uB80C\uB354\uB9C1 \uBC29\uC9C0)\n if (scrollContainerRef.current) {\n scrollContainerRef.current.style.userSelect = \"none\";\n }\n }\n\n if (isDraggingRef.current) {\n // \uB4DC\uB798\uADF8 \uAC70\uB9AC \uB204\uC801\n const dragDelta = deltaY * 2; // \uAC10\uB3C4 \uC870\uC808\n totalDragDistanceRef.current += -dragDelta; // \uB4DC\uB798\uADF8 \uBC29\uD5A5\uACFC \uBC18\uB300\n\n // \uC2A4\uD06C\uB864 \uC704\uCE58 \uACC4\uC0B0 (\uCD08\uAE30 \uC704\uCE58 + \uB204\uC801 \uB4DC\uB798\uADF8 \uAC70\uB9AC)\n const scrollContainer = scrollContainerRef.current;\n const newScrollTop = Math.max(\n 0,\n initialScrollTopRef.current + totalDragDistanceRef.current\n );\n\n // \uC2A4\uD06C\uB864 \uC704\uCE58 \uC124\uC815\n scrollContainer.scrollTop = newScrollTop;\n\n // \uB4DC\uB798\uADF8 \uC2DC\uC791\uC810 \uC5C5\uB370\uC774\uD2B8 (\uC5F0\uC18D\uC801\uC778 \uB4DC\uB798\uADF8\uB97C \uC704\uD574)\n dragStartRef.current.y = e.clientY;\n e.preventDefault();\n }\n }, []);\n\n /**\n * \uB9C8\uC6B0\uC2A4 \uBC84\uD2BC \uD574\uC81C \uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC\n * \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uC885\uB8CC \uBC0F \uC0C1\uD0DC \uCD08\uAE30\uD654\n */\n const handleMouseUp = useCallback(() => {\n isMouseDownRef.current = false;\n\n // \uB4DC\uB798\uADF8\uAC00 \uC9C4\uD589\uB418\uC5C8\uB2E4\uBA74 \uCD5C\uC885 \uC2A4\uD06C\uB864 \uC704\uCE58 \uACC4\uC0B0 \uBC0F \uC124\uC815\n if (isDraggingRef.current && scrollContainerRef.current) {\n const finalScrollTop = Math.max(\n 0,\n initialScrollTopRef.current + totalDragDistanceRef.current\n );\n\n // \uC2A4\uD06C\uB864 \uC704\uCE58\uB97C \uC5EC\uB7EC \uBC88 \uAC15\uC81C\uB85C \uC124\uC815\uD558\uC5EC \uD655\uC2E4\uD788 \uACE0\uC815\n const setScrollPosition = () => {\n if (scrollContainerRef.current) {\n scrollContainerRef.current.scrollTop = finalScrollTop;\n }\n };\n\n // \uC989\uC2DC \uC124\uC815 \uBC0F \uC9C0\uC5F0 \uC124\uC815 (\uC2A4\uD06C\uB864 \uC548\uC815\uD654)\n setScrollPosition();\n setTimeout(setScrollPosition, 1);\n setTimeout(setScrollPosition, 5);\n setTimeout(setScrollPosition, 10);\n }\n\n // \uB4DC\uB798\uADF8 \uC0C1\uD0DC \uCD08\uAE30\uD654 (\uB9AC\uB80C\uB354\uB9C1 \uBC29\uC9C0\uB97C \uC704\uD574 ref\uB9CC \uC0AC\uC6A9)\n isDraggingRef.current = false;\n totalDragDistanceRef.current = 0;\n\n // DOM \uC2A4\uD0C0\uC77C \uCD08\uAE30\uD654\n if (scrollContainerRef.current) {\n scrollContainerRef.current.style.userSelect = \"auto\";\n }\n }, []);\n\n // \uC815\uB82C\uC774 \uBCC0\uACBD\uB420 \uB54C \uBAA8\uB4E0 TableSortLabel\uC758 hover \uC0C1\uD0DC \uCD08\uAE30\uD654\n useEffect(() => {\n // sortBy\uAC00 \uBCC0\uACBD\uB418\uBA74 \uBAA8\uB4E0 TableSortLabel \uC694\uC18C\uC758 hover \uC0C1\uD0DC\uB97C \uAC15\uC81C\uB85C \uCD08\uAE30\uD654\n const tableContainer = document.querySelector(\n '[data-testid=\"virtuoso-scroller\"]'\n );\n if (tableContainer) {\n const sortLabels = tableContainer.querySelectorAll(\n \".MuiTableSortLabel-root\"\n );\n sortLabels.forEach((label) => {\n // \uB9C8\uC6B0\uC2A4 \uC774\uBCA4\uD2B8\uB97C \uC2DC\uBBAC\uB808\uC774\uC158\uD558\uC5EC hover \uC0C1\uD0DC \uD574\uC81C\n const mouseLeaveEvent = new MouseEvent(\"mouseleave\", {\n bubbles: true,\n cancelable: true,\n });\n label.dispatchEvent(mouseLeaveEvent);\n });\n }\n }, [sortBy]);\n\n // \uC815\uB82C \uD578\uB4E4\uB7EC\n const handleSort = useCallback(\n (columnId: string) => {\n if (!onSort) return;\n\n const newDirection: SortDirection =\n sortBy === columnId && sortDirection === \"asc\" ? \"desc\" : \"asc\";\n\n onSort(columnId, newDirection);\n },\n [onSort, sortBy, sortDirection]\n );\n\n // \uAC00\uC0C1\uD654 \uC2A4\uD06C\uB864 \uBC94\uC704 \uBCC0\uACBD \uAC10\uC9C0 \uD578\uB4E4\uB7EC (\uAE30\uC874 VirtualDataTable \uBC29\uC2DD)\n const handleRangeChange = useCallback(\n (range: { startIndex: number; endIndex: number }) => {\n // onLoadMore\uAC00 \uC5C6\uC73C\uBA74 \uBB34\uD55C \uC2A4\uD06C\uB864 \uBE44\uD65C\uC131\uD654\n if (!onLoadMore) {\n return;\n }\n\n // \uC774\uBBF8 \uB85C\uB529 \uC911\uC774\uBA74 \uC911\uB2E8 (\uCD08\uAE30 \uB85C\uB529\uB9CC \uCCB4\uD06C, \uB354 \uAC00\uC838\uC624\uAE30 \uB85C\uB529\uC740 \uD5C8\uC6A9)\n if (loading && data.length === 0) {\n return;\n }\n\n // \uCD94\uAC00 \uC548\uC804\uC7A5\uCE58: \uB108\uBB34 \uBE60\uB978 \uC5F0\uC18D \uD638\uCD9C \uBC29\uC9C0 (100ms \uB0B4 \uC911\uBCF5 \uD638\uCD9C \uBB34\uC2DC)\n const now = Date.now();\n const lastTime = (window as any).lastRangeChangeTime || 0;\n if (now - lastTime < 100) {\n return;\n }\n (window as any).lastRangeChangeTime = now;\n\n // \uB354 \uBCF4\uC218\uC801\uC778 \uC870\uAC74: 90% \uC9C0\uC810\uC5D0\uC11C \uB85C\uB4DC (\uAE30\uC874 VirtualDataTable \uBC29\uC2DD)\n const bufferSize = Math.max(10, Math.floor(data.length * 0.1)); // \uB370\uC774\uD130\uC758 10% \uB610\uB294 \uCD5C\uC18C 10\uAC1C\n const shouldLoadMore = range.endIndex >= data.length - bufferSize;\n\n // \uCD94\uAC00 \uC870\uAC74: \uCD5C\uC18C 30\uAC1C \uC774\uC0C1\uC758 \uB370\uC774\uD130\uC5D0\uC11C\uB9CC \uB354 \uAC00\uC838\uC624\uAE30 \uC2E4\uD589\n const hasMinimumData = data.length >= 30;\n\n if (\n shouldLoadMore &&\n hasMinimumData &&\n onLoadMore &&\n !isLoadingMoreRef.current\n ) {\n isLoadingMoreRef.current = true;\n const offset = data.length;\n const limit = 50;\n\n // console.log(\">>> loadMore \uD638\uCD9C \uC9C1\uC804\", {\n // offset,\n // limit,\n // range,\n // dataLength: data.length,\n // bufferSize,\n // endIndex: range.endIndex,\n // threshold: data.length - bufferSize,\n // timestamp: new Date().toISOString(),\n // });\n\n onLoadMore(offset, limit);\n\n // console.log(\">>> loadMore \uD638\uCD9C \uC644\uB8CC\");\n }\n },\n [data.length, loading, onLoadMore]\n );\n\n // \uB85C\uB529 \uC0C1\uD0DC\uAC00 \uBCC0\uACBD\uB418\uBA74 isLoadingMoreRef \uC5C5\uB370\uC774\uD2B8 (\uAE30\uC874 VirtualDataTable \uBC29\uC2DD)\n useEffect(() => {\n if (!loading) {\n isLoadingMoreRef.current = false;\n }\n }, [loading]);\n\n // \uB370\uC774\uD130\uAC00 \uBE44\uC6CC\uC9C0\uBA74 \uD14C\uC774\uBE14\uC744 \uC7AC\uB9C8\uC6B4\uD2B8\uD558\uC5EC \uC2A4\uD06C\uB864\uC744 \uB9E8 \uC704\uB85C \uC774\uB3D9\n useEffect(() => {\n if (data.length === 0) {\n setTableKey((prev) => prev + 1);\n }\n }, [data.length]);\n\n /**\n * \uC804\uC5ED \uB9C8\uC6B0\uC2A4 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uC124\uC815\n * \uB4DC\uB798\uADF8\uAC00 \uD14C\uC774\uBE14 \uC601\uC5ED\uC744 \uBC97\uC5B4\uB098\uB3C4 \uB3D9\uC791\uD558\uB3C4\uB85D document\uC5D0 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uB4F1\uB85D\n */\n useEffect(() => {\n document.addEventListener(\"mousemove\", handleMouseMove);\n document.addEventListener(\"mouseup\", handleMouseUp);\n\n return () => {\n document.removeEventListener(\"mousemove\", handleMouseMove);\n document.removeEventListener(\"mouseup\", handleMouseUp);\n };\n }, [handleMouseMove, handleMouseUp]);\n\n /**\n * \uD14C\uC774\uBE14 \uACE0\uC815 \uD5E4\uB354 \uCEE8\uD150\uCE20 \uC815\uC758 (\uAE30\uC874 VirtualDataTable \uC2A4\uD0C0\uC77C)\n * \uC815\uB82C \uAE30\uB2A5\uC774 \uD3EC\uD568\uB41C \uCEEC\uB7FC \uD5E4\uB354\uB97C \uB80C\uB354\uB9C1\n */\n const fixedHeaderContent = useCallback(() => {\n // 1. \uADF8\uB8F9 \uC815\uBCF4 \uCD94\uCD9C\n const groupMap: { [group: string]: DataColumn<T>[] } = {};\n const noGroupColumns: DataColumn<T>[] = [];\n\n columns.forEach((col) => {\n if (col.group) {\n if (!groupMap[col.group]) {\n groupMap[col.group] = [];\n }\n groupMap[col.group].push(col);\n } else {\n noGroupColumns.push(col);\n }\n });\n\n // \uADF8\uB8F9\uC774 \uC788\uB294 \uACBD\uC6B0 2\uC904 \uD5E4\uB354, \uC5C6\uB294 \uACBD\uC6B0 1\uC904 \uD5E4\uB354\n const hasGroups = Object.keys(groupMap).length > 0;\n\n if (!hasGroups) {\n // \uB2E8\uC77C \uD589 \uD5E4\uB354\n return (\n <MuiTableRow>\n {columns.map((col) => (\n <TableCell\n key={String(col.id)}\n align={col.align || \"left\"}\n style={{\n width: col.width,\n minWidth: col.width,\n ...col.style,\n fontWeight: \"bold\",\n position: \"sticky\",\n top: 0,\n zIndex: 2,\n padding: \"16px\",\n }}\n >\n {col.sortable ? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent:\n col.align === \"center\"\n ? \"center\"\n : col.align === \"right\"\n ? \"flex-end\"\n : \"flex-start\",\n position: \"relative\",\n width: \"100%\",\n }}\n >\n <Box\n sx={{\n position: \"relative\",\n cursor: \"default\",\n \"&:hover .MuiTableSortLabel-root\": {\n opacity: \"1 !important\",\n \"& .MuiSvgIcon-root\": {\n color: \"#000\",\n opacity: \"1 !important\",\n },\n },\n }}\n onClick={() =>\n handleSort(String(col.id))\n }\n >\n {col.text}\n <TableSortLabel\n active={sortBy === col.id}\n direction={\n sortBy === col.id\n ? sortDirection\n : \"desc\"\n }\n sx={{\n position: \"absolute\",\n left: \"100%\",\n top: \"50%\",\n transform: \"translateY(-50%)\",\n marginLeft: \"4px\",\n minWidth: \"auto\",\n width: \"16px\",\n height: \"16px\",\n cursor: \"default\",\n opacity:\n sortBy === col.id ? 1 : 0,\n transition: \"opacity 0.2s ease\",\n \"& .MuiTableSortLabel-icon\": {\n position: \"relative\",\n marginLeft: 0,\n marginRight: 0,\n opacity: 1,\n transition:\n \"color 0.2s ease\",\n },\n \"& .MuiTableSortLabel-iconDirectionAsc\":\n {\n transform:\n \"rotate(180deg)\",\n },\n \"& .MuiTableSortLabel-iconDirectionDesc\":\n {\n transform:\n \"rotate(0deg)\",\n },\n }}\n />\n </Box>\n </div>\n ) : (\n col.text\n )}\n </TableCell>\n ))}\n </MuiTableRow>\n );\n }\n\n // 2\uC904 \uD5E4\uB354 (\uADF8\uB8F9\uC774 \uC788\uB294 \uACBD\uC6B0)\n const firstRowCells = [\n ...noGroupColumns.map((col) => (\n <TableCell\n key={String(col.id)}\n rowSpan={2}\n align={col.align || \"left\"}\n style={{\n width: col.width,\n minWidth: col.width,\n ...col.style,\n fontWeight: \"bold\",\n position: \"sticky\",\n top: 0,\n zIndex: 2,\n padding: \"16px\",\n }}\n >\n {col.sortable && onSort ? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent:\n col.align === \"center\"\n ? \"center\"\n : col.align === \"right\"\n ? \"flex-end\"\n : \"flex-start\",\n position: \"relative\",\n width: \"100%\",\n }}\n >\n <Box\n sx={{\n position: \"relative\",\n cursor: \"default\",\n \"&:hover .MuiTableSortLabel-root\": {\n opacity: \"1 !important\",\n \"& .MuiSvgIcon-root\": {\n color: \"#000\",\n opacity: \"1 !important\",\n },\n },\n }}\n onClick={() => handleSort(String(col.id))}\n >\n {col.text}\n <TableSortLabel\n active={sortBy === col.id}\n direction={\n sortBy === col.id\n ? sortDirection\n : \"desc\"\n }\n sx={{\n position: \"absolute\",\n left: \"100%\",\n top: \"50%\",\n transform: \"translateY(-50%)\",\n marginLeft: \"4px\",\n minWidth: \"auto\",\n width: \"16px\",\n height: \"16px\",\n cursor: \"default\",\n opacity: sortBy === col.id ? 1 : 0,\n transition: \"opacity 0.2s ease\",\n \"&:hover\": {\n opacity: \"1 !important\",\n \"& .MuiSvgIcon-root\": {\n color: \"#000\",\n opacity: \"1 !important\",\n },\n },\n \"& .MuiTableSortLabel-icon\": {\n position: \"relative\",\n marginLeft: 0,\n marginRight: 0,\n opacity: 1,\n transition: \"color 0.2s ease\",\n },\n \"& .MuiTableSortLabel-iconDirectionAsc\":\n {\n transform: \"rotate(180deg)\",\n },\n \"& .MuiTableSortLabel-iconDirectionDesc\":\n {\n transform: \"rotate(0deg)\",\n },\n }}\n />\n </Box>\n </div>\n ) : (\n col.text\n )}\n </TableCell>\n )),\n ...Object.entries(groupMap).map(([group, cols]) => (\n <TableCell\n key={group}\n align=\"center\"\n colSpan={cols.length}\n style={{\n fontWeight: \"bold\",\n position: \"sticky\",\n top: 0,\n zIndex: 2,\n padding: \"16px\",\n }}\n >\n {group}\n </TableCell>\n )),\n ];\n\n const secondRowCells = [\n ...Object.values(groupMap)\n .flat()\n .map((col) => (\n <TableCell\n key={String(col.id)}\n align={col.align || \"left\"}\n style={{\n width: col.width,\n minWidth: col.width,\n ...col.style,\n fontWeight: \"bold\",\n position: \"sticky\",\n top: 0,\n zIndex: 2,\n padding: \"16px\",\n }}\n >\n {col.sortable && onSort ? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent:\n col.align === \"center\"\n ? \"center\"\n : col.align === \"right\"\n ? \"flex-end\"\n : \"flex-start\",\n position: \"relative\",\n width: \"100%\",\n }}\n >\n <Box\n sx={{\n position: \"relative\",\n cursor: \"default\",\n \"&:hover .MuiTableSortLabel-root\": {\n opacity: \"1 !important\",\n \"& .MuiSvgIcon-root\": {\n color: \"#000\",\n opacity: \"1 !important\",\n },\n },\n }}\n onClick={() => handleSort(String(col.id))}\n >\n {col.text}\n <TableSortLabel\n active={sortBy === col.id}\n direction={\n sortBy === col.id\n ? sortDirection\n : \"desc\"\n }\n sx={{\n position: \"absolute\",\n left: \"100%\",\n top: \"50%\",\n transform: \"translateY(-50%)\",\n marginLeft: \"4px\",\n minWidth: \"auto\",\n width: \"16px\",\n height: \"16px\",\n cursor: \"default\",\n opacity: sortBy === col.id ? 1 : 0,\n transition: \"opacity 0.2s ease\",\n \"&:hover\": {\n opacity: \"1 !important\",\n \"& .MuiSvgIcon-root\": {\n color: \"#000\",\n opacity: \"1 !important\",\n },\n },\n \"& .MuiTableSortLabel-icon\": {\n position: \"relative\",\n marginLeft: 0,\n marginRight: 0,\n opacity: 1,\n transition: \"color 0.2s ease\",\n },\n \"& .MuiTableSortLabel-iconDirectionAsc\":\n {\n transform: \"rotate(0deg)\",\n },\n \"& .MuiTableSortLabel-iconDirectionDesc\":\n {\n transform: \"rotate(180deg)\",\n },\n }}\n />\n </Box>\n </div>\n ) : (\n col.text\n )}\n </TableCell>\n )),\n ];\n\n return (\n <>\n <MuiTableRow>{firstRowCells}</MuiTableRow>\n <MuiTableRow>{secondRowCells}</MuiTableRow>\n </>\n );\n }, [columns, sortBy, sortDirection, handleSort, onSort, columnHeight]);\n\n /**\n * \uD14C\uC774\uBE14 \uD589 \uCEE8\uD150\uCE20 \uB80C\uB354\uB9C1 \uD568\uC218 (\uAE30\uC874 VirtualDataTable \uC2A4\uD0C0\uC77C)\n * \uAC01 \uB370\uC774\uD130 \uD56D\uBAA9\uC5D0 \uB300\uD55C \uC140 \uB0B4\uC6A9\uC744 \uC815\uC758\n */\n const rowContent = useCallback(\n (index: number, item: T) => {\n // console.log(\"rowContent \uB80C\uB354\uB9C1:\", { index, item: item ? \"\uC788\uC74C\" : \"\uC5C6\uC74C\" });\n\n if (!item) {\n console.log(\"rowContent - \uC544\uC774\uD15C \uC5C6\uC74C, \uC778\uB371\uC2A4:\", index);\n return null;\n }\n\n return (\n <>\n {columns.map((column) => (\n <TableCell\n key={String(column.id)}\n align={column.align || \"left\"}\n style={{\n width: column.width,\n minWidth: column.width,\n ...column.style,\n padding: \"8px 16px\",\n }}\n >\n {column.render\n ? column.render(item, index)\n : String((item as any)[column.id] || \"\")}\n </TableCell>\n ))}\n </>\n );\n },\n [columns]\n );\n\n // \uD14C\uC774\uBE14 \uCEF4\uD3EC\uB10C\uD2B8 \uC815\uC758 (\uAE30\uC874 VirtualDataTable \uC2A4\uD0C0\uC77C)\n const VirtuosoTableComponents: TableComponents<T> = useMemo(\n () => ({\n // \uC2A4\uD06C\uB864 \uCEE8\uD14C\uC774\uB108 (\uC678\uBD80\uC5D0\uC11C \uD55C \uBC88\uB9CC \uC0DD\uC131\uB41C \uC548\uC815\uC801\uC778 \uCEF4\uD3EC\uB10C\uD2B8 \uC0AC\uC6A9)\n Scroller: VirtuosoScroller,\n // \uD14C\uC774\uBE14 \uCEF4\uD3EC\uB10C\uD2B8\n Table: (props) => (\n <Table\n {...props}\n sx={{\n borderCollapse: \"separate\",\n tableLayout: \"fixed\",\n marginRight: \"16px\",\n }}\n />\n ),\n // \uD14C\uC774\uBE14 \uD5E4\uB354 (\uACE0\uC815 \uC704\uCE58)\n TableHead: forwardRef<HTMLTableSectionElement, any>(\n (props, ref) => (\n <TableHead\n {...props}\n ref={ref}\n sx={{\n userSelect: \"none\",\n \"& tr\": {\n height: columnHeight,\n \"& th\": {\n padding: \"16px\",\n position: \"sticky\",\n top: 0,\n zIndex: 2,\n fontWeight: \"bold\",\n },\n },\n }}\n />\n )\n ),\n // \uD14C\uC774\uBE14 \uD589 (\uD074\uB9AD \uC774\uBCA4\uD2B8 \uBC0F \uD638\uBC84 \uD6A8\uACFC \uD3EC\uD568)\n // \uD14C\uC774\uBE14 \uD589 (\uD074\uB9AD \uC774\uBCA4\uD2B8 \uBC0F \uD638\uBC84 \uD6A8\uACFC \uD3EC\uD568)\n TableRow: (props: any) => {\n const { item, ...rest } = props as any;\n // react-virtuoso\uB294 'data-index' \uC18D\uC131\uC73C\uB85C index\uB97C \uC804\uB2EC\uD569\uB2C8\uB2E4\n const rowIndex = rest[\"data-index\"] ?? 0;\n const isOddRow = rowIndex % 2 === 1;\n\n return (\n <MuiTableRow\n {...rest}\n onMouseDown={(e: any) => {\n // \uB9C8\uC6B0\uC2A4 \uB2E4\uC6B4 \uC2DC \uB4DC\uB798\uADF8 \uD50C\uB798\uADF8 \uCD08\uAE30\uD654 \uBC0F \uC2DC\uC791 \uC704\uCE58 \uC800\uC7A5\n isScrollDraggingRef.current = false;\n mouseDownPositionRef.current = {\n x: e.clientX,\n y: e.clientY,\n };\n }}\n onMouseMove={(e: any) => {\n // \uB9C8\uC6B0\uC2A4\uAC00 5px \uC774\uC0C1 \uC6C0\uC9C1\uC600\uC744 \uB54C\uB9CC \uB4DC\uB798\uADF8\uB85C \uAC04\uC8FC\n const deltaX = Math.abs(\n e.clientX - mouseDownPositionRef.current.x\n );\n const deltaY = Math.abs(\n e.clientY - mouseDownPositionRef.current.y\n );\n const dragThreshold = 5; // 5px \uC784\uACC4\uAC12\n\n if (\n deltaX > dragThreshold ||\n deltaY > dragThreshold\n ) {\n isScrollDraggingRef.current = true;\n }\n }}\n onClick={() => {\n // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864\uC774 \uC544\uB2C8\uACE0, \uC544\uC774\uD15C\uC774 \uC788\uACE0, onRowClick\uC774 \uC788\uC744 \uB54C\uB9CC \uC2E4\uD589\n if (\n !isScrollDraggingRef.current &&\n !isDraggingRef.current &&\n item &&\n onRowClick\n ) {\n onRowClick(item, rowIndex);\n }\n // \uD074\uB9AD \uD6C4 \uD50C\uB798\uADF8 \uB9AC\uC14B\n isScrollDraggingRef.current = false;\n }}\n sx={{\n userSelect: \"none\",\n height: rowHeight,\n backgroundColor:\n isOddRow && stripedRowColor\n ? stripedRowColor\n : \"transparent\",\n \"& td\": {\n padding: \"8px 16px\",\n borderBottom: rowDivider\n ? \"1px solid rgba(224, 224, 224, 1)\"\n : \"none\",\n },\n \"& th\": {\n padding: \"8px 16px\",\n borderBottom: \"none\",\n },\n \"&:hover\": onRowClick\n ? {\n backgroundColor: (theme) => {\n const isDark =\n theme.palette.mode === \"dark\";\n const defaultColor = \"#000000\";\n const color =\n rowHoverColor ?? defaultColor;\n const opacity =\n rowHoverOpacity ?? 0.06;\n\n // hex\uB97C rgb\uB85C \uBCC0\uD658\n const hex = color.replace(\"#\", \"\");\n let r =\n parseInt(\n hex.substring(0, 2),\n 16\n ) / 255;\n let g =\n parseInt(\n hex.substring(2, 4),\n 16\n ) / 255;\n let b =\n parseInt(\n hex.substring(4, 6),\n 16\n ) / 255;\n\n // \uB2E4\uD06C \uBAA8\uB4DC\uC77C \uB54C \uBC1D\uAE30\uB9CC \uBC18\uC804 (HSL \uBCC0\uD658)\n if (isDark) {\n // RGB to HSL\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n let h = 0,\n s = 0,\n l = (max + min) / 2;\n\n if (max !== min) {\n const d = max - min;\n s =\n l > 0.5\n ? d / (2 - max - min)\n : d / (max + min);\n\n switch (max) {\n case r:\n h =\n ((g - b) / d +\n (g < b\n ? 6\n : 0)) /\n 6;\n break;\n case g:\n h =\n ((b - r) / d +\n 2) /\n 6;\n break;\n case b:\n h =\n ((r - g) / d +\n 4) /\n 6;\n break;\n }\n }\n\n // \uBC1D\uAE30\uB9CC \uBC18\uC804 (0.0 <-> 1.0)\n l = 1 - l;\n\n // HSL to RGB\n const hue2rgb = (\n p: number,\n q: number,\n t: number\n ) => {\n if (t < 0) t += 1;\n if (t > 1) t -= 1;\n if (t < 1 / 6)\n return (\n p + (q - p) * 6 * t\n );\n if (t < 1 / 2) return q;\n if (t < 2 / 3)\n return (\n p +\n (q - p) *\n (2 / 3 - t) *\n 6\n );\n return p;\n };\n\n if (s === 0) {\n r = g = b = l;\n } else {\n const q =\n l < 0.5\n ? l * (1 + s)\n : l + s - l * s;\n const p = 2 * l - q;\n r = hue2rgb(p, q, h + 1 / 3);\n g = hue2rgb(p, q, h);\n b = hue2rgb(p, q, h - 1 / 3);\n }\n }\n\n return `rgba(${Math.round(\n r * 255\n )}, ${Math.round(\n g * 255\n )}, ${Math.round(\n b * 255\n )}, ${opacity})`;\n },\n transition: \"background-color 0.2s ease\",\n }\n : {},\n }}\n />\n );\n },\n // \uD14C\uC774\uBE14 \uBC14\uB514\n TableBody: forwardRef<HTMLTableSectionElement>((props, ref) => (\n <MuiTableBody {...props} ref={ref} />\n )),\n }),\n [\n onRowClick,\n rowHeight,\n handleMouseDown,\n stripedRowColor,\n rowDivider,\n columnHeight,\n rowHoverColor,\n rowHoverOpacity,\n VirtuosoScroller,\n ]\n );\n\n // \uACF5\uD1B5 \uD14C\uC774\uBE14 \uB0B4\uC6A9\n const tableContent = (\n <Box\n sx={{\n position: \"relative\",\n height: \"100%\",\n width: \"100%\",\n \"& .MuiTableHead-root\": {\n backgroundColor: (theme) =>\n theme.palette.mode === \"dark\"\n ? \"#1e1e1e !important\"\n : \"#ffffff !important\",\n },\n }}\n >\n {/* \uD14C\uC774\uBE14 */}\n <TableVirtuoso\n key={tableKey}\n ref={virtuosoRef}\n data={data}\n totalCount={onLoadMore ? data.length + 1 : data.length}\n fixedHeaderContent={fixedHeaderContent}\n itemContent={rowContent}\n rangeChanged={handleRangeChange}\n components={VirtuosoTableComponents}\n style={{ height: \"100%\" }}\n increaseViewportBy={{ top: 100, bottom: 300 }}\n overscan={5}\n followOutput={false}\n />\n\n {/* \uBE48 \uB370\uC774\uD130 \uD45C\uC2DC */}\n {data.length === 0 && !loading && (\n <Box\n sx={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: 2,\n }}\n >\n {typeof emptyMessage === \"string\" ? (\n <>\n <Box\n sx={{\n width: 48,\n height: 48,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n borderRadius: \"50%\",\n backgroundColor: \"#f5f5f5\",\n color: \"#999\",\n }}\n >\n \uD83D\uDCC4\n </Box>\n <Typography\n variant=\"body1\"\n sx={{ color: \"text.secondary\" }}\n >\n {emptyMessage}\n </Typography>\n </>\n ) : (\n emptyMessage\n )}\n </Box>\n )}\n\n {/* \uB85C\uB529 \uC2A4\uD53C\uB108 */}\n {shouldShowLoading && (\n <>\n {LoadingComponent ? (\n <LoadingComponent\n visible={loading}\n onComplete={handleLoadingComplete}\n />\n ) : (\n <LoadingProgress\n visible={loading}\n onComplete={handleLoadingComplete}\n size={40}\n sx={{\n top: `${\n columns.some((col) => col.group)\n ? columnHeight * 2\n : columnHeight\n }px`,\n }}\n background={{\n show: data.length === 0, // \uCD5C\uCD08 \uB85C\uB529\uC5D0\uB9CC \uBC30\uACBD \uD45C\uC2DC\n opacity: 0.8,\n }}\n />\n )}\n </>\n )}\n </Box>\n );\n\n return showPaper ? (\n <Paper\n className=\"grow\"\n elevation={1}\n sx={{\n padding: 0,\n paddingLeft: paddingX,\n height: \"100%\",\n minHeight: 0,\n flex: 1,\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n {tableContent}\n </Paper>\n ) : (\n <Box\n className=\"grow\"\n style={{\n padding: 0,\n paddingLeft: paddingX,\n height: \"100%\",\n minHeight: 0,\n flex: 1,\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n {tableContent}\n </Box>\n );\n}\n\nexport const VirtualDataTable = memo(VirtualDataTableComponent) as <T>(\n props: VirtualDataTableProps<T>\n) => React.JSX.Element;\n", "/******************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise, SuppressedError, Symbol, Iterator */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n if (typeof b !== \"function\" && b !== null)\r\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\r\n function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\r\n var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\r\n var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\r\n var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\r\n var _, done = false;\r\n for (var i = decorators.length - 1; i >= 0; i--) {\r\n var context = {};\r\n for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\r\n for (var p in contextIn.access) context.access[p] = contextIn.access[p];\r\n context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\r\n var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\r\n if (kind === \"accessor\") {\r\n if (result === void 0) continue;\r\n if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\r\n if (_ = accept(result.get)) descriptor.get = _;\r\n if (_ = accept(result.set)) descriptor.set = _;\r\n if (_ = accept(result.init)) initializers.unshift(_);\r\n }\r\n else if (_ = accept(result)) {\r\n if (kind === \"field\") initializers.unshift(_);\r\n else descriptor[key] = _;\r\n }\r\n }\r\n if (target) Object.defineProperty(target, contextIn.name, descriptor);\r\n done = true;\r\n};\r\n\r\nexport function __runInitializers(thisArg, initializers, value) {\r\n var useValue = arguments.length > 2;\r\n for (var i = 0; i < initializers.length; i++) {\r\n value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\r\n }\r\n return useValue ? value : void 0;\r\n};\r\n\r\nexport function __propKey(x) {\r\n return typeof x === \"symbol\" ? x : \"\".concat(x);\r\n};\r\n\r\nexport function __setFunctionName(f, name, prefix) {\r\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\r\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\r\n};\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === \"function\" ? Iterator : Object).prototype);\r\n return g.next = verb(0), g[\"throw\"] = verb(1), g[\"return\"] = verb(2), typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n var desc = Object.getOwnPropertyDescriptor(m, k);\r\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\r\n desc = { enumerable: true, get: function() { return m[k]; } };\r\n }\r\n Object.defineProperty(o, k2, desc);\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n ar[i] = from[i];\r\n }\r\n }\r\n return to.concat(ar || Array.prototype.slice.call(from));\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = Object.create((typeof AsyncIterator === \"function\" ? AsyncIterator : Object).prototype), verb(\"next\"), verb(\"throw\"), verb(\"return\", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }\r\n function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nvar ownKeys = function(o) {\r\n ownKeys = Object.getOwnPropertyNames || function (o) {\r\n var ar = [];\r\n for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;\r\n return ar;\r\n };\r\n return ownKeys(o);\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== \"default\") __createBinding(result, mod, k[i]);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n\r\nexport function __classPrivateFieldIn(state, receiver) {\r\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\r\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\r\n}\r\n\r\nexport function __addDisposableResource(env, value, async) {\r\n if (value !== null && value !== void 0) {\r\n if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\r\n var dispose, inner;\r\n if (async) {\r\n if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\r\n dispose = value[Symbol.asyncDispose];\r\n }\r\n if (dispose === void 0) {\r\n if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\r\n dispose = value[Symbol.dispose];\r\n if (async) inner = dispose;\r\n }\r\n if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\r\n if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };\r\n env.stack.push({ value: value, dispose: dispose, async: async });\r\n }\r\n else if (async) {\r\n env.stack.push({ async: true });\r\n }\r\n return value;\r\n\r\n}\r\n\r\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\r\n var e = new Error(message);\r\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\r\n};\r\n\r\nexport function __disposeResources(env) {\r\n function fail(e) {\r\n env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\r\n env.hasError = true;\r\n }\r\n var r, s = 0;\r\n function next() {\r\n while (r = env.stack.pop()) {\r\n try {\r\n if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);\r\n if (r.dispose) {\r\n var result = r.dispose.call(r.value);\r\n if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\r\n }\r\n else s |= 1;\r\n }\r\n catch (e) {\r\n fail(e);\r\n }\r\n }\r\n if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();\r\n if (env.hasError) throw env.error;\r\n }\r\n return next();\r\n}\r\n\r\nexport function __rewriteRelativeImportExtension(path, preserveJsx) {\r\n if (typeof path === \"string\" && /^\\.\\.?\\//.test(path)) {\r\n return path.replace(/\\.(tsx)$|((?:\\.d)?)((?:\\.[^./]+?)?)\\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {\r\n return tsx ? preserveJsx ? \".jsx\" : \".js\" : d && (!ext || !cm) ? m : (d + ext + \".\" + cm.toLowerCase() + \"js\");\r\n });\r\n }\r\n return path;\r\n}\r\n\r\nexport default {\r\n __extends: __extends,\r\n __assign: __assign,\r\n __rest: __rest,\r\n __decorate: __decorate,\r\n __param: __param,\r\n __esDecorate: __esDecorate,\r\n __runInitializers: __runInitializers,\r\n __propKey: __propKey,\r\n __setFunctionName: __setFunctionName,\r\n __metadata: __metadata,\r\n __awaiter: __awaiter,\r\n __generator: __generator,\r\n __createBinding: __createBinding,\r\n __exportStar: __exportStar,\r\n __values: __values,\r\n __read: __read,\r\n __spread: __spread,\r\n __spreadArrays: __spreadArrays,\r\n __spreadArray: __spreadArray,\r\n __await: __await,\r\n __asyncGenerator: __asyncGenerator,\r\n __asyncDelegator: __asyncDelegator,\r\n __asyncValues: __asyncValues,\r\n __makeTemplateObject: __makeTemplateObject,\r\n __importStar: __importStar,\r\n __importDefault: __importDefault,\r\n __classPrivateFieldGet: __classPrivateFieldGet,\r\n __classPrivateFieldSet: __classPrivateFieldSet,\r\n __classPrivateFieldIn: __classPrivateFieldIn,\r\n __addDisposableResource: __addDisposableResource,\r\n __disposeResources: __disposeResources,\r\n __rewriteRelativeImportExtension: __rewriteRelativeImportExtension,\r\n};\r\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 { CSSProperties, ReactNode, useEffect, useRef, useState } from \"react\";\nimport { Box, CircularProgress, SxProps, Theme } from \"@mui/material\";\n\nexport interface BackgroundConfig {\n show?: boolean;\n color?: string; // Any CSS color: hex (#fff, #ffffff), rgb(255,255,255), rgba(), named colors, or RGB string \"255, 255, 255\"\n opacity?: number; // Applied to background (0.0 ~ 1.0). If color is already rgba, this is ignored\n}\n\nexport interface LoadingProgressProps {\n visible: boolean;\n onComplete?: () => void;\n fadeoutDuration?: number;\n exitDelay?: number;\n size?: number;\n className?: string;\n style?: CSSProperties;\n sx?: SxProps<Theme>;\n indicator?: ReactNode | string;\n background?: BackgroundConfig;\n}\n\nexport default function LoadingProgress({\n visible,\n onComplete,\n fadeoutDuration = 200,\n exitDelay = 0,\n size = 40,\n className,\n style,\n sx,\n indicator,\n background = {\n show: true,\n color: \"255, 255, 255\",\n opacity: 0.9,\n },\n}: LoadingProgressProps) {\n const prevVisibleRef = useRef<boolean | undefined>(undefined);\n const boxRef = useRef<HTMLDivElement>(null);\n const [shouldRender, setShouldRender] = useState(visible);\n\n // 배경 설정 기본값 처리\n const {\n show: showBackground = true,\n color: backgroundColor = \"255, 255, 255\",\n opacity: backgroundOpacity = 0.9,\n } = background;\n\n useEffect(() => {\n const prevVisible = prevVisibleRef.current;\n\n // visible이 true에서 false로 변경될 때 페이드아웃 후 onComplete 호출\n if (prevVisible === true && visible === false && boxRef.current) {\n // CSS transition으로 페이드아웃 시작\n const box = boxRef.current;\n box.style.opacity = \"0\";\n\n // fadeoutDuration + exitDelay 후 onComplete 호출 및 언마운트\n setTimeout(() => {\n setShouldRender(false); // 페이드아웃 완료 후 언마운트\n onComplete?.();\n }, fadeoutDuration + exitDelay);\n } else if (visible === true) {\n // visible이 true가 되면 다시 렌더링하고 opacity 복원\n setShouldRender(true);\n if (boxRef.current) {\n boxRef.current.style.opacity = \"1\";\n }\n }\n\n // 현재 visible 값을 ref에 저장\n prevVisibleRef.current = visible;\n }, [visible, onComplete, fadeoutDuration, exitDelay]);\n\n if (!shouldRender) {\n return null;\n }\n\n // indicator 렌더링 로직\n const renderIndicator = () => {\n // string이면 이미지 URL로 간주\n if (typeof indicator === \"string\") {\n return (\n <img\n src={indicator}\n alt=\"Loading\"\n style={{ width: size, height: size }}\n />\n );\n }\n // ReactNode가 제공되면 그대로 렌더링\n if (indicator) {\n return indicator;\n }\n // 기본값: MUI CircularProgress\n return <CircularProgress size={size} />;\n };\n\n // 배경색 처리: 다양한 색상 형식 지원\n const getBackgroundStyle = () => {\n if (!showBackground) {\n return { backgroundColor: \"transparent\" };\n }\n\n // 이미 rgba 형식이면 그대로 사용\n if (backgroundColor.startsWith(\"rgba\")) {\n return { backgroundColor };\n }\n\n // RGB 문자열 형식 (예: \"255, 255, 255\")\n if (/^\\d+,\\s*\\d+,\\s*\\d+$/.test(backgroundColor)) {\n return {\n backgroundColor: `rgba(${backgroundColor}, ${backgroundOpacity})`,\n };\n }\n\n // hex, rgb(), named color 등의 경우\n // CSS에서 color와 opacity를 함께 사용\n if (backgroundOpacity !== 1) {\n return {\n backgroundColor: backgroundColor,\n // 배경에만 opacity를 적용하기 위해 before pseudo-element 사용하거나\n // 직접 rgba로 변환하는 대신 CSS custom property 사용\n \"&::before\": {\n content: '\"\"',\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundColor: backgroundColor,\n opacity: backgroundOpacity,\n zIndex: -1,\n },\n };\n }\n\n // opacity가 1이면 그냥 색상만\n return { backgroundColor };\n };\n\n return (\n <Box\n ref={boxRef}\n className={className}\n style={{ ...style }}\n sx={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 1000,\n opacity: visible ? 1 : 0,\n transition: `opacity ${fadeoutDuration}ms ease-out`,\n ...getBackgroundStyle(),\n ...sx,\n }}\n >\n {renderIndicator()}\n </Box>\n );\n}\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\" | \"right\"; // \uD2B8\uB799 \uB0B4\uBD80 \uC815\uB82C (\uAE30\uBCF8\uAC00: \"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\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}\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 // \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 }),\n [autoHide]\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 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 (!finalAutoHideConfig.enabled) {\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(\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 findScrollableElement,\n clearHideTimer,\n showArrows,\n finalThumbWidth,\n thumbMinHeight,\n finalAutoHideConfig.enabled,\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 // \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 )\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\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 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 // \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 = 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 clearHideTimer();\n\n // \uD720 \uC774\uBCA4\uD2B8 \uC2DC 50ms \uB514\uBC14\uC6B4\uC2A4 \uC801\uC6A9 (\uBBF8\uC138\uD55C \uD720 \uC6C0\uC9C1\uC784 \uBB34\uC2DC)\n clearWheelShowTimer();\n wheelShowTimeoutRef.current = setTimeout(() => {\n setScrollbarVisible(true);\n wheelShowTimeoutRef.current = null;\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 ]);\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 // \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 (!finalAutoHideConfig.enabled && isScrollable()) {\n setScrollbarVisible(true);\n }\n }, [isScrollable, updateScrollbar, finalAutoHideConfig.enabled]);\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 .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 === \"right\"\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 === \"right\"\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 === \"right\"\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 === \"right\"\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 </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": "AA0BA,OACI,cAAAA,GACA,eAAAC,GACA,WAAAC,GACA,UAAAC,EACA,aAAAC,GACA,QAAAC,GACA,YAAAC,OACG,QACP,OACI,OAAAC,GACA,SAAAC,GACA,aAAaC,GACb,aAAAC,GACA,kBAAAC,GACA,aAAAC,GACA,YAAYC,GACZ,kBAAAC,GACA,SAAAC,GACA,cAAAC,OACG,gBACP,OAAS,iBAAAC,OAAqB,qLChBvB,IAAIC,GAAW,UAAW,CAC7B,OAAAA,GAAW,OAAO,QAAU,SAAkBC,EAAG,CAC7C,QAASC,EAAGC,EAAI,EAAGC,EAAI,UAAU,OAAQD,EAAIC,EAAGD,IAAK,CACjDD,EAAI,UAAUC,CAAC,EACf,QAASE,KAAKH,EAAO,OAAO,UAAU,eAAe,KAAKA,EAAGG,CAAC,IAAGJ,EAAEI,CAAC,EAAIH,EAAEG,CAAC,EAC/E,CACA,OAAOJ,CACX,EACOD,GAAS,MAAM,KAAM,SAAS,CACzC,ECMc,SAAUM,GAAgBC,EAejB,CAdnB,IAAAC,EAAOD,EAAA,QACPE,EAAUF,EAAA,WACVG,EAAAH,EAAA,gBAAAI,EAAeD,IAAA,OAAG,IAAGA,EACrBE,EAAAL,EAAA,UAAAM,EAASD,IAAA,OAAG,EAACA,EACbE,EAAAP,EAAA,KAAAQ,EAAID,IAAA,OAAG,GAAEA,EACTE,EAAST,EAAA,UACTU,EAAKV,EAAA,MACLW,EAAEX,EAAA,GACFY,EAASZ,EAAA,UACTa,EAAAb,EAAA,WAAAc,GAAUD,IAAA,OAAG,CACT,KAAM,GACN,MAAO,gBACP,QAAS,IACZA,EAEKE,GAAiBC,GAA4B,MAAS,EACtDC,EAASD,GAAuB,IAAI,EACpCE,EAAkCC,GAASlB,CAAO,EAAjDmB,GAAYF,EAAA,CAAA,EAAEG,GAAeH,EAAA,CAAA,EAIhCI,EAGAR,GAAU,KAHJS,GAAcD,IAAA,OAAG,GAAIA,EAC3BE,EAEAV,GAAU,MAFHW,EAAeD,IAAA,OAAG,gBAAeA,EACxCE,GACAZ,GAAU,QADDa,GAAiBD,KAAA,OAAG,GAAGA,GA6BpC,GA1BAE,GAAU,UAAA,CACN,IAAMC,GAAcd,GAAe,QAGnC,GAAIc,KAAgB,IAAQ5B,IAAY,IAASgB,EAAO,QAAS,CAE7D,IAAMa,GAAMb,EAAO,QACnBa,GAAI,MAAM,QAAU,IAGpB,WAAW,UAAA,CACPT,GAAgB,EAAK,EACrBnB,IAAU,CACd,EAAGE,EAAkBE,CAAS,CAClC,MAAWL,IAAY,KAEnBoB,GAAgB,EAAI,EAChBJ,EAAO,UACPA,EAAO,QAAQ,MAAM,QAAU,MAKvCF,GAAe,QAAUd,CAC7B,EAAG,CAACA,EAASC,EAAYE,EAAiBE,CAAS,CAAC,EAEhD,CAACc,GACD,OAAO,KAIX,IAAMW,GAAkB,UAAA,CAEpB,OAAI,OAAOnB,GAAc,SAEjBoB,GAAAA,MAAAA,CACI,IAAKpB,EACL,IAAI,UACJ,MAAO,CAAE,MAAOJ,EAAM,OAAQA,CAAI,CAAE,CAAA,EAK5CI,GAIGoB,GAACC,GAAgB,CAAC,KAAMzB,CAAI,CAAA,CACvC,EAGM0B,GAAqB,UAAA,CACvB,OAAKX,GAKDE,EAAgB,WAAW,MAAM,EAC1B,CAAE,gBAAeA,CAAA,EAIxB,sBAAsB,KAAKA,CAAe,EACnC,CACH,gBAAiB,QAAA,OAAQA,EAAe,IAAA,EAAA,OAAKE,GAAiB,GAAA,GAMlEA,KAAsB,EACf,CACH,gBAAiBF,EAGjB,YAAa,CACT,QAAS,KACT,SAAU,WACV,IAAK,EACL,KAAM,EACN,MAAO,EACP,OAAQ,EACR,gBAAiBA,EACjB,QAASE,GACT,OAAQ,EACX,GAKF,CAAE,gBAAeF,CAAA,EArCb,CAAE,gBAAiB,aAAa,CAsC/C,EAEA,OACIO,GAACG,GAAG,CACA,IAAKlB,EACL,UAAWR,EACX,MAAK2B,GAAA,CAAA,EAAO1B,CAAK,EACjB,GAAE0B,GAAAA,GAAA,CACE,SAAU,WACV,IAAK,EACL,KAAM,EACN,MAAO,EACP,OAAQ,EACR,QAAS,OACT,WAAY,SACZ,eAAgB,SAChB,OAAQ,IACR,QAASnC,EAAU,EAAI,EACvB,WAAY,WAAA,OAAWG,EAAe,aAAA,CAAa,EAChD8B,GAAkB,CAAE,EACpBvB,CAAE,EAAA,SAGRoB,GAAe,CAAE,CAAA,CAG9B,CCtKA,OACI,UAAAM,EACA,aAAAC,EACA,YAAAC,EACA,eAAAC,EACA,WAAAC,GAEA,cAAAC,GACA,uBAAAC,GACA,mBAAAC,OACG,QAopCa,OAAA,OAAAC,GAiBA,QAAAC,OAjBA,oBC3pCpB,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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",
|
|
4
|
+
"sourcesContent": ["/**\n * VirtualDataTable.tsx\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 React, {\n forwardRef,\n useCallback,\n useMemo,\n useRef,\n useEffect,\n memo,\n useState,\n} from \"react\";\nimport {\n Box,\n Table,\n TableBody as MuiTableBody,\n TableCell,\n TableContainer,\n TableHead,\n TableRow as MuiTableRow,\n TableSortLabel,\n Paper,\n Typography,\n} from \"@mui/material\";\nimport { TableVirtuoso } from \"react-virtuoso\";\nimport type { TableComponents } from \"react-virtuoso\";\nimport { LoadingProgress } from \"@ehfuse/mui-fadeout-loading-progress\";\n\nimport OverlayScrollbar from \"@ehfuse/overlay-scrollbar\";\nimport type { DataColumn, SortDirection, VirtualDataTableProps } from \"./types\";\n\n// OverlayScrollbar \uC124\uC815\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 OVERLAY_SCROLLBAR_TRACK_CONFIG = {\n alignment: \"right\" as const,\n margin: 0,\n radius: 0,\n};\n\n/**\n * \uB370\uC774\uD130 \uAE30\uBC18 \uBB34\uD55C \uC2A4\uD06C\uB864 \uBC0F \uAC00\uC0C1\uD654\uB97C \uC9C0\uC6D0\uD558\uB294 \uD14C\uC774\uBE14 \uCEF4\uD3EC\uB10C\uD2B8\n */\nfunction VirtualDataTableComponent<T>({\n data,\n loading = false,\n columns,\n onRowClick,\n rowHeight = 50,\n columnHeight = 56,\n striped,\n rowDivider = true,\n onSort,\n onLoadMore,\n sortBy,\n sortDirection,\n showPaper = true,\n paddingX = \"1rem\",\n paddingTop = 0,\n paddingBottom = 0,\n rowHoverColor,\n rowHoverOpacity,\n scrollbars,\n emptyMessage = \"NO DATA\",\n LoadingComponent,\n}: VirtualDataTableProps<T>) {\n // \uAC01 \uD14C\uC774\uBE14 \uC778\uC2A4\uD134\uC2A4\uBCC4\uB85C Scroller \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131 (scrollbars, paddingX\uB97C \uCD08\uAE30\uAC12\uC73C\uB85C \uACE0\uC815)\n const VirtuosoScroller = useMemo(\n () =>\n forwardRef<HTMLDivElement, any>((props, ref) => {\n const scrollContainerRef = useRef<HTMLElement | null>(null);\n\n return (\n <OverlayScrollbar\n detectInnerScroll={true}\n track={OVERLAY_SCROLLBAR_TRACK_CONFIG}\n {...scrollbars}\n >\n <TableContainer\n component={Box}\n {...props}\n ref={(node) => {\n scrollContainerRef.current =\n node as HTMLElement;\n if (typeof ref === \"function\") {\n ref(node as HTMLDivElement);\n } else if (ref) {\n ref.current = node as HTMLDivElement;\n }\n }}\n sx={{\n userSelect: \"auto\",\n WebkitUserSelect: \"auto\",\n position: \"relative\",\n width: \"100%\",\n height: \"100%\",\n overflow: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n scrollbarWidth: \"none\",\n msOverflowStyle: \"none\",\n // \uAE5C\uBC15\uC784 \uBC29\uC9C0\uB97C \uC704\uD55C GPU \uAC00\uC18D\n transform: \"translateZ(0)\",\n backfaceVisibility: \"hidden\",\n willChange: \"scroll-position\",\n \"&::-webkit-scrollbar\": {\n display: \"none\",\n },\n \"& .MuiTable-root\": {\n paddingRight: paddingX,\n paddingTop: paddingTop,\n paddingBottom: paddingBottom,\n },\n }}\n />\n </OverlayScrollbar>\n );\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [] // \uBE48 \uBC30\uC5F4: \uCD5C\uCD08 \uB9C8\uC6B4\uD2B8 \uC2DC\uC5D0\uB9CC \uC0DD\uC131, scrollbars, paddingX, paddingTop, paddingBottom\uC740 \uD074\uB85C\uC800\uB85C \uACE0\uC815\n );\n\n // Striped row \uBC30\uACBD\uC0C9 \uACC4\uC0B0\n const stripedRowColor = useMemo(() => {\n if (striped === true) {\n return \"#f5f5f5\"; // \uAE30\uBCF8 \uD68C\uC0C9\n } else if (typeof striped === \"string\") {\n return striped; // \uC0AC\uC6A9\uC790 \uC9C0\uC815 \uC0C9\uC0C1\n }\n return undefined; // \uBC30\uACBD\uC0C9 \uC5C6\uC74C\n }, [striped]);\n\n // \uB85C\uB529 \uC0C1\uD0DC \uAD00\uB9AC (\uC6D0\uBCF8 \uBC29\uC2DD)\n const [internalLoading, setInternalLoading] = useState(loading);\n\n // \uD14C\uC774\uBE14 \uC7AC\uB9C8\uC6B4\uD2B8\uB97C \uC704\uD55C \uD0A4 (\uB370\uC774\uD130\uAC00 \uBE44\uC6CC\uC9C0\uBA74 \uC7AC\uB9C8\uC6B4\uD2B8)\n const [tableKey, setTableKey] = useState(0);\n\n // \uB85C\uB529 \uC0C1\uD0DC \uBCC0\uACBD \uAC10\uC9C0\n useEffect(() => {\n if (loading) {\n // \uB85C\uB529\uC774 \uC2DC\uC791\uB418\uBA74 \uC989\uC2DC \uD45C\uC2DC\n setInternalLoading(true);\n }\n // \uB85C\uB529\uC774 \uB05D\uB098\uB3C4 internalLoading\uC740 handleLoadingComplete\uC5D0\uC11C\uB9CC false\uB85C \uC124\uC815\n // LoadingProgress\uC5D0\uC11C\uB294 visible={false}\uB85C \uD398\uC774\uB4DC\uC544\uC6C3\uC744 \uC2DC\uC791\uD568\n }, [loading]);\n\n // \uB85C\uB529 \uC644\uB8CC \uD578\uB4E4\uB7EC - LoadingProgress\uC758 \uD398\uC774\uB4DC\uC544\uC6C3\uC774 \uC644\uB8CC\uB41C \uD6C4 \uD638\uCD9C\uB428\n const handleLoadingComplete = useCallback(() => {\n setInternalLoading(false);\n }, []);\n\n // \uB85C\uB529 \uC624\uBC84\uB808\uC774 \uD45C\uC2DC \uC870\uAC74\n const shouldShowLoading = internalLoading;\n\n // \uB354\uBCF4\uAE30 \uB85C\uB529 \uC5EC\uBD80 (\uB370\uC774\uD130\uAC00 \uC788\uACE0 \uB85C\uB529 \uC911\uC774\uBA74 \uB354\uBCF4\uAE30 \uB85C\uB529)\n const isLoadMoreLoading = loading && data.length > 0;\n\n // \uBB34\uD55C \uC2A4\uD06C\uB864 \uB85C\uB529 \uC0C1\uD0DC (\uAE30\uC874 VirtualDataTable \uBC29\uC2DD)\n const isLoadingMoreRef = useRef(false);\n const virtuosoRef = useRef<any>(null); // TableVirtuoso ref\n\n // \uC2A4\uD06C\uB864 \uCEE8\uD14C\uC774\uB108 \uCC38\uC870 (OverlayScrollbar\uC6A9)\n const scrollContainerRef = useRef<HTMLElement | null>(null); // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uC0C1\uD0DC (OverlayScrollbar \uC0AC\uC6A9\uC2DC\uC5D0\uB294 \uBE44\uD65C\uC131\uD654)\n const isDraggingRef = useRef(false);\n const dragStartRef = useRef({ x: 0, y: 0, scrollTop: 0 });\n const isMouseDownRef = useRef(false);\n const initialScrollTopRef = useRef(0);\n const totalDragDistanceRef = useRef(0);\n const isScrollDraggingRef = useRef(false); // OverlayScrollbar \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uAC10\uC9C0\uC6A9\n const mouseDownPositionRef = useRef({ x: 0, y: 0 }); // \uB9C8\uC6B0\uC2A4 \uB2E4\uC6B4 \uC2DC\uC791 \uC704\uCE58\n const scrollDragTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n /**\n * \uB9C8\uC6B0\uC2A4 \uBC84\uD2BC \uB204\uB984 \uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC\n * OverlayScrollbar \uC0AC\uC6A9\uC2DC\uC5D0\uB294 \uAE30\uBCF8 \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864\uC744 \uBE44\uD65C\uC131\uD654\n */\n const handleMouseDown = useCallback(\n (e: React.MouseEvent<HTMLDivElement>) => {\n // OverlayScrollbar\uB97C \uC0AC\uC6A9\uD558\uBBC0\uB85C \uAE30\uBCF8 \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uBE44\uD65C\uC131\uD654\n // OverlayScrollbar\uAC00 \uC790\uCCB4\uC801\uC73C\uB85C \uC2A4\uD06C\uB864\uC744 \uCC98\uB9AC\uD568\n return;\n },\n []\n );\n\n /**\n * \uB9C8\uC6B0\uC2A4 \uC774\uB3D9 \uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC\n * \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uAE30\uB2A5\uC758 \uD575\uC2EC \uB85C\uC9C1\n */\n const handleMouseMove = useCallback((e: MouseEvent) => {\n if (!isMouseDownRef.current || !scrollContainerRef.current) return;\n\n const deltaY = e.clientY - dragStartRef.current.y;\n const threshold = 5; // \uB4DC\uB798\uADF8 \uAC10\uC9C0 \uC784\uACC4\uAC12\n\n // \uC784\uACC4\uAC12\uC744 \uB118\uC5B4\uC57C \uB4DC\uB798\uADF8\uB85C \uC778\uC2DD\n if (!isDraggingRef.current && Math.abs(deltaY) > threshold) {\n isDraggingRef.current = true;\n\n // DOM \uC2A4\uD0C0\uC77C \uC9C1\uC811 \uBCC0\uACBD (\uB9AC\uB80C\uB354\uB9C1 \uBC29\uC9C0)\n if (scrollContainerRef.current) {\n scrollContainerRef.current.style.userSelect = \"none\";\n }\n }\n\n if (isDraggingRef.current) {\n // \uB4DC\uB798\uADF8 \uAC70\uB9AC \uB204\uC801\n const dragDelta = deltaY * 2; // \uAC10\uB3C4 \uC870\uC808\n totalDragDistanceRef.current += -dragDelta; // \uB4DC\uB798\uADF8 \uBC29\uD5A5\uACFC \uBC18\uB300\n\n // \uC2A4\uD06C\uB864 \uC704\uCE58 \uACC4\uC0B0 (\uCD08\uAE30 \uC704\uCE58 + \uB204\uC801 \uB4DC\uB798\uADF8 \uAC70\uB9AC)\n const scrollContainer = scrollContainerRef.current;\n const newScrollTop = Math.max(\n 0,\n initialScrollTopRef.current + totalDragDistanceRef.current\n );\n\n // \uC2A4\uD06C\uB864 \uC704\uCE58 \uC124\uC815\n scrollContainer.scrollTop = newScrollTop;\n\n // \uB4DC\uB798\uADF8 \uC2DC\uC791\uC810 \uC5C5\uB370\uC774\uD2B8 (\uC5F0\uC18D\uC801\uC778 \uB4DC\uB798\uADF8\uB97C \uC704\uD574)\n dragStartRef.current.y = e.clientY;\n e.preventDefault();\n }\n }, []);\n\n /**\n * \uB9C8\uC6B0\uC2A4 \uBC84\uD2BC \uD574\uC81C \uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC\n * \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uC885\uB8CC \uBC0F \uC0C1\uD0DC \uCD08\uAE30\uD654\n */\n const handleMouseUp = useCallback(() => {\n isMouseDownRef.current = false;\n\n // \uB4DC\uB798\uADF8\uAC00 \uC9C4\uD589\uB418\uC5C8\uB2E4\uBA74 \uCD5C\uC885 \uC2A4\uD06C\uB864 \uC704\uCE58 \uACC4\uC0B0 \uBC0F \uC124\uC815\n if (isDraggingRef.current && scrollContainerRef.current) {\n const finalScrollTop = Math.max(\n 0,\n initialScrollTopRef.current + totalDragDistanceRef.current\n );\n\n // \uC2A4\uD06C\uB864 \uC704\uCE58\uB97C \uC5EC\uB7EC \uBC88 \uAC15\uC81C\uB85C \uC124\uC815\uD558\uC5EC \uD655\uC2E4\uD788 \uACE0\uC815\n const setScrollPosition = () => {\n if (scrollContainerRef.current) {\n scrollContainerRef.current.scrollTop = finalScrollTop;\n }\n };\n\n // \uC989\uC2DC \uC124\uC815 \uBC0F \uC9C0\uC5F0 \uC124\uC815 (\uC2A4\uD06C\uB864 \uC548\uC815\uD654)\n setScrollPosition();\n setTimeout(setScrollPosition, 1);\n setTimeout(setScrollPosition, 5);\n setTimeout(setScrollPosition, 10);\n }\n\n // \uB4DC\uB798\uADF8 \uC0C1\uD0DC \uCD08\uAE30\uD654 (\uB9AC\uB80C\uB354\uB9C1 \uBC29\uC9C0\uB97C \uC704\uD574 ref\uB9CC \uC0AC\uC6A9)\n isDraggingRef.current = false;\n totalDragDistanceRef.current = 0;\n\n // DOM \uC2A4\uD0C0\uC77C \uCD08\uAE30\uD654\n if (scrollContainerRef.current) {\n scrollContainerRef.current.style.userSelect = \"auto\";\n }\n }, []);\n\n // \uC815\uB82C\uC774 \uBCC0\uACBD\uB420 \uB54C \uBAA8\uB4E0 TableSortLabel\uC758 hover \uC0C1\uD0DC \uCD08\uAE30\uD654\n useEffect(() => {\n // sortBy\uAC00 \uBCC0\uACBD\uB418\uBA74 \uBAA8\uB4E0 TableSortLabel \uC694\uC18C\uC758 hover \uC0C1\uD0DC\uB97C \uAC15\uC81C\uB85C \uCD08\uAE30\uD654\n const tableContainer = document.querySelector(\n '[data-testid=\"virtuoso-scroller\"]'\n );\n if (tableContainer) {\n const sortLabels = tableContainer.querySelectorAll(\n \".MuiTableSortLabel-root\"\n );\n sortLabels.forEach((label) => {\n // \uB9C8\uC6B0\uC2A4 \uC774\uBCA4\uD2B8\uB97C \uC2DC\uBBAC\uB808\uC774\uC158\uD558\uC5EC hover \uC0C1\uD0DC \uD574\uC81C\n const mouseLeaveEvent = new MouseEvent(\"mouseleave\", {\n bubbles: true,\n cancelable: true,\n });\n label.dispatchEvent(mouseLeaveEvent);\n });\n }\n }, [sortBy]);\n\n // \uC815\uB82C \uD578\uB4E4\uB7EC\n const handleSort = useCallback(\n (columnId: string) => {\n if (!onSort) return;\n\n const newDirection: SortDirection =\n sortBy === columnId && sortDirection === \"asc\" ? \"desc\" : \"asc\";\n\n onSort(columnId, newDirection);\n },\n [onSort, sortBy, sortDirection]\n );\n\n // \uAC00\uC0C1\uD654 \uC2A4\uD06C\uB864 \uBC94\uC704 \uBCC0\uACBD \uAC10\uC9C0 \uD578\uB4E4\uB7EC (\uAE30\uC874 VirtualDataTable \uBC29\uC2DD)\n const handleRangeChange = useCallback(\n (range: { startIndex: number; endIndex: number }) => {\n // onLoadMore\uAC00 \uC5C6\uC73C\uBA74 \uBB34\uD55C \uC2A4\uD06C\uB864 \uBE44\uD65C\uC131\uD654\n if (!onLoadMore) {\n return;\n }\n\n // \uC774\uBBF8 \uB85C\uB529 \uC911\uC774\uBA74 \uC911\uB2E8 (\uCD08\uAE30 \uB85C\uB529\uB9CC \uCCB4\uD06C, \uB354 \uAC00\uC838\uC624\uAE30 \uB85C\uB529\uC740 \uD5C8\uC6A9)\n if (loading && data.length === 0) {\n return;\n }\n\n // \uCD94\uAC00 \uC548\uC804\uC7A5\uCE58: \uB108\uBB34 \uBE60\uB978 \uC5F0\uC18D \uD638\uCD9C \uBC29\uC9C0 (100ms \uB0B4 \uC911\uBCF5 \uD638\uCD9C \uBB34\uC2DC)\n const now = Date.now();\n const lastTime = (window as any).lastRangeChangeTime || 0;\n if (now - lastTime < 100) {\n return;\n }\n (window as any).lastRangeChangeTime = now;\n\n // \uB354 \uBCF4\uC218\uC801\uC778 \uC870\uAC74: 90% \uC9C0\uC810\uC5D0\uC11C \uB85C\uB4DC (\uAE30\uC874 VirtualDataTable \uBC29\uC2DD)\n const bufferSize = Math.max(10, Math.floor(data.length * 0.1)); // \uB370\uC774\uD130\uC758 10% \uB610\uB294 \uCD5C\uC18C 10\uAC1C\n const shouldLoadMore = range.endIndex >= data.length - bufferSize;\n\n // \uCD94\uAC00 \uC870\uAC74: \uCD5C\uC18C 30\uAC1C \uC774\uC0C1\uC758 \uB370\uC774\uD130\uC5D0\uC11C\uB9CC \uB354 \uAC00\uC838\uC624\uAE30 \uC2E4\uD589\n const hasMinimumData = data.length >= 30;\n\n if (\n shouldLoadMore &&\n hasMinimumData &&\n onLoadMore &&\n !isLoadingMoreRef.current\n ) {\n isLoadingMoreRef.current = true;\n const offset = data.length;\n const limit = 50;\n\n // console.log(\">>> loadMore \uD638\uCD9C \uC9C1\uC804\", {\n // offset,\n // limit,\n // range,\n // dataLength: data.length,\n // bufferSize,\n // endIndex: range.endIndex,\n // threshold: data.length - bufferSize,\n // timestamp: new Date().toISOString(),\n // });\n\n onLoadMore(offset, limit);\n\n // console.log(\">>> loadMore \uD638\uCD9C \uC644\uB8CC\");\n }\n },\n [data.length, loading, onLoadMore]\n );\n\n // \uB85C\uB529 \uC0C1\uD0DC\uAC00 \uBCC0\uACBD\uB418\uBA74 isLoadingMoreRef \uC5C5\uB370\uC774\uD2B8 (\uAE30\uC874 VirtualDataTable \uBC29\uC2DD)\n useEffect(() => {\n if (!loading) {\n isLoadingMoreRef.current = false;\n }\n }, [loading]);\n\n // \uB370\uC774\uD130\uAC00 \uBE44\uC6CC\uC9C0\uBA74 \uD14C\uC774\uBE14\uC744 \uC7AC\uB9C8\uC6B4\uD2B8\uD558\uC5EC \uC2A4\uD06C\uB864\uC744 \uB9E8 \uC704\uB85C \uC774\uB3D9\n useEffect(() => {\n if (data.length === 0) {\n setTableKey((prev) => prev + 1);\n }\n }, [data.length]);\n\n // \uB370\uC774\uD130\uAC00 \uBCC0\uACBD\uB418\uBA74(\uC815\uB82C, \uD544\uD130 \uB4F1) \uC2A4\uD06C\uB864\uC744 \uB9E8 \uC704\uB85C \uC774\uB3D9\n useEffect(() => {\n if (virtuosoRef.current && data.length > 0) {\n virtuosoRef.current.scrollToIndex({\n index: 0,\n align: \"start\",\n behavior: \"auto\",\n });\n }\n }, [data]);\n\n /**\n * \uC804\uC5ED \uB9C8\uC6B0\uC2A4 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uC124\uC815\n * \uB4DC\uB798\uADF8\uAC00 \uD14C\uC774\uBE14 \uC601\uC5ED\uC744 \uBC97\uC5B4\uB098\uB3C4 \uB3D9\uC791\uD558\uB3C4\uB85D document\uC5D0 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uB4F1\uB85D\n */\n useEffect(() => {\n document.addEventListener(\"mousemove\", handleMouseMove);\n document.addEventListener(\"mouseup\", handleMouseUp);\n\n return () => {\n document.removeEventListener(\"mousemove\", handleMouseMove);\n document.removeEventListener(\"mouseup\", handleMouseUp);\n };\n }, [handleMouseMove, handleMouseUp]);\n\n /**\n * \uD14C\uC774\uBE14 \uACE0\uC815 \uD5E4\uB354 \uCEE8\uD150\uCE20 \uC815\uC758 (\uAE30\uC874 VirtualDataTable \uC2A4\uD0C0\uC77C)\n * \uC815\uB82C \uAE30\uB2A5\uC774 \uD3EC\uD568\uB41C \uCEEC\uB7FC \uD5E4\uB354\uB97C \uB80C\uB354\uB9C1\n */\n const fixedHeaderContent = useCallback(() => {\n // 1. \uADF8\uB8F9 \uC815\uBCF4 \uCD94\uCD9C\n const groupMap: { [group: string]: DataColumn<T>[] } = {};\n const noGroupColumns: DataColumn<T>[] = [];\n\n columns.forEach((col) => {\n if (col.group) {\n if (!groupMap[col.group]) {\n groupMap[col.group] = [];\n }\n groupMap[col.group].push(col);\n } else {\n noGroupColumns.push(col);\n }\n });\n\n // \uADF8\uB8F9\uC774 \uC788\uB294 \uACBD\uC6B0 2\uC904 \uD5E4\uB354, \uC5C6\uB294 \uACBD\uC6B0 1\uC904 \uD5E4\uB354\n const hasGroups = Object.keys(groupMap).length > 0;\n\n if (!hasGroups) {\n // \uB2E8\uC77C \uD589 \uD5E4\uB354\n return (\n <MuiTableRow>\n {columns.map((col) => (\n <TableCell\n key={String(col.id)}\n align={col.align || \"left\"}\n style={{\n width: col.width,\n minWidth: col.width,\n ...col.style,\n fontWeight: \"bold\",\n position: \"sticky\",\n top: 0,\n zIndex: 2,\n padding: \"16px\",\n }}\n >\n {col.sortable ? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent:\n col.align === \"center\"\n ? \"center\"\n : col.align === \"right\"\n ? \"flex-end\"\n : \"flex-start\",\n position: \"relative\",\n width: \"100%\",\n }}\n >\n <Box\n sx={{\n position: \"relative\",\n cursor: \"default\",\n \"&:hover .MuiTableSortLabel-root\": {\n opacity: \"1 !important\",\n \"& .MuiSvgIcon-root\": {\n color: \"#000\",\n opacity: \"1 !important\",\n },\n },\n }}\n onClick={() =>\n handleSort(String(col.id))\n }\n >\n {col.text}\n <TableSortLabel\n active={sortBy === col.id}\n direction={\n sortBy === col.id\n ? sortDirection\n : \"desc\"\n }\n sx={{\n position: \"absolute\",\n left: \"100%\",\n top: \"50%\",\n transform: \"translateY(-50%)\",\n marginLeft: \"4px\",\n minWidth: \"auto\",\n width: \"16px\",\n height: \"16px\",\n cursor: \"default\",\n opacity:\n sortBy === col.id ? 1 : 0,\n transition: \"opacity 0.2s ease\",\n \"& .MuiTableSortLabel-icon\": {\n position: \"relative\",\n marginLeft: 0,\n marginRight: 0,\n opacity: 1,\n transition:\n \"color 0.2s ease\",\n },\n \"& .MuiTableSortLabel-iconDirectionAsc\":\n {\n transform:\n \"rotate(180deg)\",\n },\n \"& .MuiTableSortLabel-iconDirectionDesc\":\n {\n transform:\n \"rotate(0deg)\",\n },\n }}\n />\n </Box>\n </div>\n ) : (\n col.text\n )}\n </TableCell>\n ))}\n </MuiTableRow>\n );\n }\n\n // 2\uC904 \uD5E4\uB354 (\uADF8\uB8F9\uC774 \uC788\uB294 \uACBD\uC6B0)\n const firstRowCells = [\n ...noGroupColumns.map((col) => (\n <TableCell\n key={String(col.id)}\n rowSpan={2}\n align={col.align || \"left\"}\n style={{\n width: col.width,\n minWidth: col.width,\n ...col.style,\n fontWeight: \"bold\",\n position: \"sticky\",\n top: 0,\n zIndex: 2,\n padding: \"16px\",\n }}\n >\n {col.sortable && onSort ? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent:\n col.align === \"center\"\n ? \"center\"\n : col.align === \"right\"\n ? \"flex-end\"\n : \"flex-start\",\n position: \"relative\",\n width: \"100%\",\n }}\n >\n <Box\n sx={{\n position: \"relative\",\n cursor: \"default\",\n \"&:hover .MuiTableSortLabel-root\": {\n opacity: \"1 !important\",\n \"& .MuiSvgIcon-root\": {\n color: \"#000\",\n opacity: \"1 !important\",\n },\n },\n }}\n onClick={() => handleSort(String(col.id))}\n >\n {col.text}\n <TableSortLabel\n active={sortBy === col.id}\n direction={\n sortBy === col.id\n ? sortDirection\n : \"desc\"\n }\n sx={{\n position: \"absolute\",\n left: \"100%\",\n top: \"50%\",\n transform: \"translateY(-50%)\",\n marginLeft: \"4px\",\n minWidth: \"auto\",\n width: \"16px\",\n height: \"16px\",\n cursor: \"default\",\n opacity: sortBy === col.id ? 1 : 0,\n transition: \"opacity 0.2s ease\",\n \"&:hover\": {\n opacity: \"1 !important\",\n \"& .MuiSvgIcon-root\": {\n color: \"#000\",\n opacity: \"1 !important\",\n },\n },\n \"& .MuiTableSortLabel-icon\": {\n position: \"relative\",\n marginLeft: 0,\n marginRight: 0,\n opacity: 1,\n transition: \"color 0.2s ease\",\n },\n \"& .MuiTableSortLabel-iconDirectionAsc\":\n {\n transform: \"rotate(180deg)\",\n },\n \"& .MuiTableSortLabel-iconDirectionDesc\":\n {\n transform: \"rotate(0deg)\",\n },\n }}\n />\n </Box>\n </div>\n ) : (\n col.text\n )}\n </TableCell>\n )),\n ...Object.entries(groupMap).map(([group, cols]) => (\n <TableCell\n key={group}\n align=\"center\"\n colSpan={cols.length}\n style={{\n fontWeight: \"bold\",\n position: \"sticky\",\n top: 0,\n zIndex: 2,\n padding: \"16px\",\n }}\n >\n {group}\n </TableCell>\n )),\n ];\n\n const secondRowCells = [\n ...Object.values(groupMap)\n .flat()\n .map((col) => (\n <TableCell\n key={String(col.id)}\n align={col.align || \"left\"}\n style={{\n width: col.width,\n minWidth: col.width,\n ...col.style,\n fontWeight: \"bold\",\n position: \"sticky\",\n top: 0,\n zIndex: 2,\n padding: \"16px\",\n }}\n >\n {col.sortable && onSort ? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent:\n col.align === \"center\"\n ? \"center\"\n : col.align === \"right\"\n ? \"flex-end\"\n : \"flex-start\",\n position: \"relative\",\n width: \"100%\",\n }}\n >\n <Box\n sx={{\n position: \"relative\",\n cursor: \"default\",\n \"&:hover .MuiTableSortLabel-root\": {\n opacity: \"1 !important\",\n \"& .MuiSvgIcon-root\": {\n color: \"#000\",\n opacity: \"1 !important\",\n },\n },\n }}\n onClick={() => handleSort(String(col.id))}\n >\n {col.text}\n <TableSortLabel\n active={sortBy === col.id}\n direction={\n sortBy === col.id\n ? sortDirection\n : \"desc\"\n }\n sx={{\n position: \"absolute\",\n left: \"100%\",\n top: \"50%\",\n transform: \"translateY(-50%)\",\n marginLeft: \"4px\",\n minWidth: \"auto\",\n width: \"16px\",\n height: \"16px\",\n cursor: \"default\",\n opacity: sortBy === col.id ? 1 : 0,\n transition: \"opacity 0.2s ease\",\n \"&:hover\": {\n opacity: \"1 !important\",\n \"& .MuiSvgIcon-root\": {\n color: \"#000\",\n opacity: \"1 !important\",\n },\n },\n \"& .MuiTableSortLabel-icon\": {\n position: \"relative\",\n marginLeft: 0,\n marginRight: 0,\n opacity: 1,\n transition: \"color 0.2s ease\",\n },\n \"& .MuiTableSortLabel-iconDirectionAsc\":\n {\n transform: \"rotate(0deg)\",\n },\n \"& .MuiTableSortLabel-iconDirectionDesc\":\n {\n transform: \"rotate(180deg)\",\n },\n }}\n />\n </Box>\n </div>\n ) : (\n col.text\n )}\n </TableCell>\n )),\n ];\n\n return (\n <>\n <MuiTableRow>{firstRowCells}</MuiTableRow>\n <MuiTableRow>{secondRowCells}</MuiTableRow>\n </>\n );\n }, [columns, sortBy, sortDirection, handleSort, onSort, columnHeight]);\n\n /**\n * \uD14C\uC774\uBE14 \uD589 \uCEE8\uD150\uCE20 \uB80C\uB354\uB9C1 \uD568\uC218 (\uAE30\uC874 VirtualDataTable \uC2A4\uD0C0\uC77C)\n * \uAC01 \uB370\uC774\uD130 \uD56D\uBAA9\uC5D0 \uB300\uD55C \uC140 \uB0B4\uC6A9\uC744 \uC815\uC758\n */\n const rowContent = useCallback(\n (index: number, item: T) => {\n // console.log(\"rowContent \uB80C\uB354\uB9C1:\", { index, item: item ? \"\uC788\uC74C\" : \"\uC5C6\uC74C\" });\n\n if (!item) {\n console.log(\"rowContent - \uC544\uC774\uD15C \uC5C6\uC74C, \uC778\uB371\uC2A4:\", index);\n return null;\n }\n\n return (\n <>\n {columns.map((column) => (\n <TableCell\n key={String(column.id)}\n align={column.align || \"left\"}\n style={{\n width: column.width,\n minWidth: column.width,\n ...column.style,\n padding: \"8px 16px\",\n }}\n >\n {column.render\n ? column.render(item, index)\n : String((item as any)[column.id] || \"\")}\n </TableCell>\n ))}\n </>\n );\n },\n [columns]\n );\n\n // \uD14C\uC774\uBE14 \uCEF4\uD3EC\uB10C\uD2B8 \uC815\uC758 (\uAE30\uC874 VirtualDataTable \uC2A4\uD0C0\uC77C)\n const VirtuosoTableComponents: TableComponents<T> = useMemo(\n () => ({\n // \uC2A4\uD06C\uB864 \uCEE8\uD14C\uC774\uB108 (\uC678\uBD80\uC5D0\uC11C \uD55C \uBC88\uB9CC \uC0DD\uC131\uB41C \uC548\uC815\uC801\uC778 \uCEF4\uD3EC\uB10C\uD2B8 \uC0AC\uC6A9)\n Scroller: VirtuosoScroller,\n // \uD14C\uC774\uBE14 \uCEF4\uD3EC\uB10C\uD2B8\n Table: (props) => (\n <Table\n {...props}\n sx={{\n borderCollapse: \"separate\",\n tableLayout: \"fixed\",\n marginRight: \"16px\",\n }}\n />\n ),\n // \uD14C\uC774\uBE14 \uD5E4\uB354 (\uACE0\uC815 \uC704\uCE58)\n TableHead: forwardRef<HTMLTableSectionElement, any>(\n (props, ref) => (\n <TableHead\n {...props}\n ref={ref}\n sx={{\n userSelect: \"none\",\n \"& tr\": {\n height: columnHeight,\n \"& th\": {\n padding: \"16px\",\n position: \"sticky\",\n top: 0,\n zIndex: 2,\n fontWeight: \"bold\",\n },\n },\n }}\n />\n )\n ),\n // \uD14C\uC774\uBE14 \uD589 (\uD074\uB9AD \uC774\uBCA4\uD2B8 \uBC0F \uD638\uBC84 \uD6A8\uACFC \uD3EC\uD568)\n // \uD14C\uC774\uBE14 \uD589 (\uD074\uB9AD \uC774\uBCA4\uD2B8 \uBC0F \uD638\uBC84 \uD6A8\uACFC \uD3EC\uD568)\n TableRow: (props: any) => {\n const { item, ...rest } = props as any;\n // react-virtuoso\uB294 'data-index' \uC18D\uC131\uC73C\uB85C index\uB97C \uC804\uB2EC\uD569\uB2C8\uB2E4\n const rowIndex = rest[\"data-index\"] ?? 0;\n const isOddRow = rowIndex % 2 === 1;\n\n return (\n <MuiTableRow\n {...rest}\n onMouseDown={(e: any) => {\n // \uB9C8\uC6B0\uC2A4 \uB2E4\uC6B4 \uC2DC \uB4DC\uB798\uADF8 \uD50C\uB798\uADF8 \uCD08\uAE30\uD654 \uBC0F \uC2DC\uC791 \uC704\uCE58 \uC800\uC7A5\n isScrollDraggingRef.current = false;\n mouseDownPositionRef.current = {\n x: e.clientX,\n y: e.clientY,\n };\n }}\n onMouseMove={(e: any) => {\n // \uB9C8\uC6B0\uC2A4\uAC00 5px \uC774\uC0C1 \uC6C0\uC9C1\uC600\uC744 \uB54C\uB9CC \uB4DC\uB798\uADF8\uB85C \uAC04\uC8FC\n const deltaX = Math.abs(\n e.clientX - mouseDownPositionRef.current.x\n );\n const deltaY = Math.abs(\n e.clientY - mouseDownPositionRef.current.y\n );\n const dragThreshold = 5; // 5px \uC784\uACC4\uAC12\n\n if (\n deltaX > dragThreshold ||\n deltaY > dragThreshold\n ) {\n isScrollDraggingRef.current = true;\n }\n }}\n onClick={() => {\n // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864\uC774 \uC544\uB2C8\uACE0, \uC544\uC774\uD15C\uC774 \uC788\uACE0, onRowClick\uC774 \uC788\uC744 \uB54C\uB9CC \uC2E4\uD589\n if (\n !isScrollDraggingRef.current &&\n !isDraggingRef.current &&\n item &&\n onRowClick\n ) {\n onRowClick(item, rowIndex);\n }\n // \uD074\uB9AD \uD6C4 \uD50C\uB798\uADF8 \uB9AC\uC14B\n isScrollDraggingRef.current = false;\n }}\n sx={{\n userSelect: \"none\",\n height: rowHeight,\n backgroundColor:\n isOddRow && stripedRowColor\n ? stripedRowColor\n : \"transparent\",\n \"& td\": {\n padding: \"8px 16px\",\n borderBottom: rowDivider\n ? \"1px solid rgba(224, 224, 224, 1)\"\n : \"none\",\n },\n \"& th\": {\n padding: \"8px 16px\",\n borderBottom: \"none\",\n },\n \"&:hover\": onRowClick\n ? {\n backgroundColor: (theme) => {\n const isDark =\n theme.palette.mode === \"dark\";\n const defaultColor = \"#000000\";\n const color =\n rowHoverColor ?? defaultColor;\n const opacity =\n rowHoverOpacity ?? 0.06;\n\n // hex\uB97C rgb\uB85C \uBCC0\uD658\n const hex = color.replace(\"#\", \"\");\n let r =\n parseInt(\n hex.substring(0, 2),\n 16\n ) / 255;\n let g =\n parseInt(\n hex.substring(2, 4),\n 16\n ) / 255;\n let b =\n parseInt(\n hex.substring(4, 6),\n 16\n ) / 255;\n\n // \uB2E4\uD06C \uBAA8\uB4DC\uC77C \uB54C \uBC1D\uAE30\uB9CC \uBC18\uC804 (HSL \uBCC0\uD658)\n if (isDark) {\n // RGB to HSL\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n let h = 0,\n s = 0,\n l = (max + min) / 2;\n\n if (max !== min) {\n const d = max - min;\n s =\n l > 0.5\n ? d / (2 - max - min)\n : d / (max + min);\n\n switch (max) {\n case r:\n h =\n ((g - b) / d +\n (g < b\n ? 6\n : 0)) /\n 6;\n break;\n case g:\n h =\n ((b - r) / d +\n 2) /\n 6;\n break;\n case b:\n h =\n ((r - g) / d +\n 4) /\n 6;\n break;\n }\n }\n\n // \uBC1D\uAE30\uB9CC \uBC18\uC804 (0.0 <-> 1.0)\n l = 1 - l;\n\n // HSL to RGB\n const hue2rgb = (\n p: number,\n q: number,\n t: number\n ) => {\n if (t < 0) t += 1;\n if (t > 1) t -= 1;\n if (t < 1 / 6)\n return (\n p + (q - p) * 6 * t\n );\n if (t < 1 / 2) return q;\n if (t < 2 / 3)\n return (\n p +\n (q - p) *\n (2 / 3 - t) *\n 6\n );\n return p;\n };\n\n if (s === 0) {\n r = g = b = l;\n } else {\n const q =\n l < 0.5\n ? l * (1 + s)\n : l + s - l * s;\n const p = 2 * l - q;\n r = hue2rgb(p, q, h + 1 / 3);\n g = hue2rgb(p, q, h);\n b = hue2rgb(p, q, h - 1 / 3);\n }\n }\n\n return `rgba(${Math.round(\n r * 255\n )}, ${Math.round(\n g * 255\n )}, ${Math.round(\n b * 255\n )}, ${opacity})`;\n },\n transition: \"background-color 0.2s ease\",\n }\n : {},\n }}\n />\n );\n },\n // \uD14C\uC774\uBE14 \uBC14\uB514\n TableBody: forwardRef<HTMLTableSectionElement>((props, ref) => (\n <MuiTableBody {...props} ref={ref} />\n )),\n }),\n [\n onRowClick,\n rowHeight,\n handleMouseDown,\n stripedRowColor,\n rowDivider,\n columnHeight,\n rowHoverColor,\n rowHoverOpacity,\n VirtuosoScroller,\n ]\n );\n\n // \uACF5\uD1B5 \uD14C\uC774\uBE14 \uB0B4\uC6A9\n const tableContent = (\n <Box\n sx={{\n position: \"relative\",\n height: \"100%\",\n width: \"100%\",\n \"& .MuiTableHead-root\": {\n backgroundColor: (theme) =>\n theme.palette.mode === \"dark\"\n ? \"#1e1e1e !important\"\n : \"#ffffff !important\",\n },\n }}\n >\n {/* \uD14C\uC774\uBE14 */}\n <TableVirtuoso\n key={tableKey}\n ref={virtuosoRef}\n data={data}\n totalCount={onLoadMore ? data.length + 1 : data.length}\n fixedHeaderContent={fixedHeaderContent}\n itemContent={rowContent}\n rangeChanged={handleRangeChange}\n components={VirtuosoTableComponents}\n style={{ height: \"100%\" }}\n increaseViewportBy={{ top: 100, bottom: 300 }}\n overscan={5}\n followOutput={false}\n />\n\n {/* \uBE48 \uB370\uC774\uD130 \uD45C\uC2DC */}\n {data.length === 0 && !loading && (\n <Box\n sx={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: 2,\n }}\n >\n {typeof emptyMessage === \"string\" ? (\n <>\n <Box\n sx={{\n width: 48,\n height: 48,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n borderRadius: \"50%\",\n backgroundColor: \"#f5f5f5\",\n color: \"#999\",\n }}\n >\n \uD83D\uDCC4\n </Box>\n <Typography\n variant=\"body1\"\n sx={{ color: \"text.secondary\" }}\n >\n {emptyMessage}\n </Typography>\n </>\n ) : (\n emptyMessage\n )}\n </Box>\n )}\n\n {/* \uB85C\uB529 \uC2A4\uD53C\uB108 */}\n {shouldShowLoading && (\n <>\n {LoadingComponent ? (\n <LoadingComponent\n visible={loading}\n onComplete={handleLoadingComplete}\n />\n ) : (\n <LoadingProgress\n visible={loading}\n onComplete={handleLoadingComplete}\n size={40}\n sx={{\n top: `${\n columns.some((col) => col.group)\n ? columnHeight * 2\n : columnHeight\n }px`,\n }}\n background={{\n show: data.length === 0, // \uCD5C\uCD08 \uB85C\uB529\uC5D0\uB9CC \uBC30\uACBD \uD45C\uC2DC\n opacity: 0.8,\n }}\n />\n )}\n </>\n )}\n </Box>\n );\n\n return showPaper ? (\n <Paper\n className=\"grow\"\n elevation={1}\n sx={{\n padding: 0,\n paddingLeft: paddingX,\n height: \"100%\",\n minHeight: 0,\n flex: 1,\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n {tableContent}\n </Paper>\n ) : (\n <Box\n className=\"grow\"\n style={{\n padding: 0,\n paddingLeft: paddingX,\n height: \"100%\",\n minHeight: 0,\n flex: 1,\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n {tableContent}\n </Box>\n );\n}\n\nexport const VirtualDataTable = memo(VirtualDataTableComponent) as <T>(\n props: VirtualDataTableProps<T>\n) => React.JSX.Element;\n", "/******************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise, SuppressedError, Symbol, Iterator */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n if (typeof b !== \"function\" && b !== null)\r\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\r\n function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\r\n var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\r\n var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\r\n var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\r\n var _, done = false;\r\n for (var i = decorators.length - 1; i >= 0; i--) {\r\n var context = {};\r\n for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\r\n for (var p in contextIn.access) context.access[p] = contextIn.access[p];\r\n context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\r\n var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\r\n if (kind === \"accessor\") {\r\n if (result === void 0) continue;\r\n if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\r\n if (_ = accept(result.get)) descriptor.get = _;\r\n if (_ = accept(result.set)) descriptor.set = _;\r\n if (_ = accept(result.init)) initializers.unshift(_);\r\n }\r\n else if (_ = accept(result)) {\r\n if (kind === \"field\") initializers.unshift(_);\r\n else descriptor[key] = _;\r\n }\r\n }\r\n if (target) Object.defineProperty(target, contextIn.name, descriptor);\r\n done = true;\r\n};\r\n\r\nexport function __runInitializers(thisArg, initializers, value) {\r\n var useValue = arguments.length > 2;\r\n for (var i = 0; i < initializers.length; i++) {\r\n value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\r\n }\r\n return useValue ? value : void 0;\r\n};\r\n\r\nexport function __propKey(x) {\r\n return typeof x === \"symbol\" ? x : \"\".concat(x);\r\n};\r\n\r\nexport function __setFunctionName(f, name, prefix) {\r\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\r\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\r\n};\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === \"function\" ? Iterator : Object).prototype);\r\n return g.next = verb(0), g[\"throw\"] = verb(1), g[\"return\"] = verb(2), typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n var desc = Object.getOwnPropertyDescriptor(m, k);\r\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\r\n desc = { enumerable: true, get: function() { return m[k]; } };\r\n }\r\n Object.defineProperty(o, k2, desc);\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n ar[i] = from[i];\r\n }\r\n }\r\n return to.concat(ar || Array.prototype.slice.call(from));\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = Object.create((typeof AsyncIterator === \"function\" ? AsyncIterator : Object).prototype), verb(\"next\"), verb(\"throw\"), verb(\"return\", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }\r\n function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nvar ownKeys = function(o) {\r\n ownKeys = Object.getOwnPropertyNames || function (o) {\r\n var ar = [];\r\n for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;\r\n return ar;\r\n };\r\n return ownKeys(o);\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== \"default\") __createBinding(result, mod, k[i]);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n\r\nexport function __classPrivateFieldIn(state, receiver) {\r\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\r\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\r\n}\r\n\r\nexport function __addDisposableResource(env, value, async) {\r\n if (value !== null && value !== void 0) {\r\n if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\r\n var dispose, inner;\r\n if (async) {\r\n if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\r\n dispose = value[Symbol.asyncDispose];\r\n }\r\n if (dispose === void 0) {\r\n if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\r\n dispose = value[Symbol.dispose];\r\n if (async) inner = dispose;\r\n }\r\n if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\r\n if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };\r\n env.stack.push({ value: value, dispose: dispose, async: async });\r\n }\r\n else if (async) {\r\n env.stack.push({ async: true });\r\n }\r\n return value;\r\n\r\n}\r\n\r\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\r\n var e = new Error(message);\r\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\r\n};\r\n\r\nexport function __disposeResources(env) {\r\n function fail(e) {\r\n env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\r\n env.hasError = true;\r\n }\r\n var r, s = 0;\r\n function next() {\r\n while (r = env.stack.pop()) {\r\n try {\r\n if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);\r\n if (r.dispose) {\r\n var result = r.dispose.call(r.value);\r\n if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\r\n }\r\n else s |= 1;\r\n }\r\n catch (e) {\r\n fail(e);\r\n }\r\n }\r\n if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();\r\n if (env.hasError) throw env.error;\r\n }\r\n return next();\r\n}\r\n\r\nexport function __rewriteRelativeImportExtension(path, preserveJsx) {\r\n if (typeof path === \"string\" && /^\\.\\.?\\//.test(path)) {\r\n return path.replace(/\\.(tsx)$|((?:\\.d)?)((?:\\.[^./]+?)?)\\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {\r\n return tsx ? preserveJsx ? \".jsx\" : \".js\" : d && (!ext || !cm) ? m : (d + ext + \".\" + cm.toLowerCase() + \"js\");\r\n });\r\n }\r\n return path;\r\n}\r\n\r\nexport default {\r\n __extends: __extends,\r\n __assign: __assign,\r\n __rest: __rest,\r\n __decorate: __decorate,\r\n __param: __param,\r\n __esDecorate: __esDecorate,\r\n __runInitializers: __runInitializers,\r\n __propKey: __propKey,\r\n __setFunctionName: __setFunctionName,\r\n __metadata: __metadata,\r\n __awaiter: __awaiter,\r\n __generator: __generator,\r\n __createBinding: __createBinding,\r\n __exportStar: __exportStar,\r\n __values: __values,\r\n __read: __read,\r\n __spread: __spread,\r\n __spreadArrays: __spreadArrays,\r\n __spreadArray: __spreadArray,\r\n __await: __await,\r\n __asyncGenerator: __asyncGenerator,\r\n __asyncDelegator: __asyncDelegator,\r\n __asyncValues: __asyncValues,\r\n __makeTemplateObject: __makeTemplateObject,\r\n __importStar: __importStar,\r\n __importDefault: __importDefault,\r\n __classPrivateFieldGet: __classPrivateFieldGet,\r\n __classPrivateFieldSet: __classPrivateFieldSet,\r\n __classPrivateFieldIn: __classPrivateFieldIn,\r\n __addDisposableResource: __addDisposableResource,\r\n __disposeResources: __disposeResources,\r\n __rewriteRelativeImportExtension: __rewriteRelativeImportExtension,\r\n};\r\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 { CSSProperties, ReactNode, useEffect, useRef, useState } from \"react\";\nimport { Box, CircularProgress, SxProps, Theme } from \"@mui/material\";\n\nexport interface BackgroundConfig {\n show?: boolean;\n color?: string; // Any CSS color: hex (#fff, #ffffff), rgb(255,255,255), rgba(), named colors, or RGB string \"255, 255, 255\"\n opacity?: number; // Applied to background (0.0 ~ 1.0). If color is already rgba, this is ignored\n}\n\nexport interface LoadingProgressProps {\n visible: boolean;\n onComplete?: () => void;\n fadeoutDuration?: number;\n exitDelay?: number;\n size?: number;\n className?: string;\n style?: CSSProperties;\n sx?: SxProps<Theme>;\n indicator?: ReactNode | string;\n background?: BackgroundConfig;\n}\n\nexport default function LoadingProgress({\n visible,\n onComplete,\n fadeoutDuration = 200,\n exitDelay = 0,\n size = 40,\n className,\n style,\n sx,\n indicator,\n background = {\n show: true,\n color: \"255, 255, 255\",\n opacity: 0.9,\n },\n}: LoadingProgressProps) {\n const prevVisibleRef = useRef<boolean | undefined>(undefined);\n const boxRef = useRef<HTMLDivElement>(null);\n const [shouldRender, setShouldRender] = useState(visible);\n\n // 배경 설정 기본값 처리\n const {\n show: showBackground = true,\n color: backgroundColor = \"255, 255, 255\",\n opacity: backgroundOpacity = 0.9,\n } = background;\n\n useEffect(() => {\n const prevVisible = prevVisibleRef.current;\n\n // visible이 true에서 false로 변경될 때 페이드아웃 후 onComplete 호출\n if (prevVisible === true && visible === false && boxRef.current) {\n // CSS transition으로 페이드아웃 시작\n const box = boxRef.current;\n box.style.opacity = \"0\";\n\n // fadeoutDuration + exitDelay 후 onComplete 호출 및 언마운트\n setTimeout(() => {\n setShouldRender(false); // 페이드아웃 완료 후 언마운트\n onComplete?.();\n }, fadeoutDuration + exitDelay);\n } else if (visible === true) {\n // visible이 true가 되면 다시 렌더링하고 opacity 복원\n setShouldRender(true);\n if (boxRef.current) {\n boxRef.current.style.opacity = \"1\";\n }\n }\n\n // 현재 visible 값을 ref에 저장\n prevVisibleRef.current = visible;\n }, [visible, onComplete, fadeoutDuration, exitDelay]);\n\n if (!shouldRender) {\n return null;\n }\n\n // indicator 렌더링 로직\n const renderIndicator = () => {\n // string이면 이미지 URL로 간주\n if (typeof indicator === \"string\") {\n return (\n <img\n src={indicator}\n alt=\"Loading\"\n style={{ width: size, height: size }}\n />\n );\n }\n // ReactNode가 제공되면 그대로 렌더링\n if (indicator) {\n return indicator;\n }\n // 기본값: MUI CircularProgress\n return <CircularProgress size={size} />;\n };\n\n // 배경색 처리: 다양한 색상 형식 지원\n const getBackgroundStyle = () => {\n if (!showBackground) {\n return { backgroundColor: \"transparent\" };\n }\n\n // 이미 rgba 형식이면 그대로 사용\n if (backgroundColor.startsWith(\"rgba\")) {\n return { backgroundColor };\n }\n\n // RGB 문자열 형식 (예: \"255, 255, 255\")\n if (/^\\d+,\\s*\\d+,\\s*\\d+$/.test(backgroundColor)) {\n return {\n backgroundColor: `rgba(${backgroundColor}, ${backgroundOpacity})`,\n };\n }\n\n // hex, rgb(), named color 등의 경우\n // CSS에서 color와 opacity를 함께 사용\n if (backgroundOpacity !== 1) {\n return {\n backgroundColor: backgroundColor,\n // 배경에만 opacity를 적용하기 위해 before pseudo-element 사용하거나\n // 직접 rgba로 변환하는 대신 CSS custom property 사용\n \"&::before\": {\n content: '\"\"',\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundColor: backgroundColor,\n opacity: backgroundOpacity,\n zIndex: -1,\n },\n };\n }\n\n // opacity가 1이면 그냥 색상만\n return { backgroundColor };\n };\n\n return (\n <Box\n ref={boxRef}\n className={className}\n style={{ ...style }}\n sx={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 1000,\n opacity: visible ? 1 : 0,\n transition: `opacity ${fadeoutDuration}ms ease-out`,\n ...getBackgroundStyle(),\n ...sx,\n }}\n >\n {renderIndicator()}\n </Box>\n );\n}\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\" | \"right\"; // \uD2B8\uB799 \uB0B4\uBD80 \uC815\uB82C (\uAE30\uBCF8\uAC00: \"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\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}\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 // \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 }),\n [autoHide]\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 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 (!finalAutoHideConfig.enabled) {\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(\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 findScrollableElement,\n clearHideTimer,\n showArrows,\n finalThumbWidth,\n thumbMinHeight,\n finalAutoHideConfig.enabled,\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 // \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 )\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\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 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 // \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 = 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 clearHideTimer();\n\n // \uD720 \uC774\uBCA4\uD2B8 \uC2DC 50ms \uB514\uBC14\uC6B4\uC2A4 \uC801\uC6A9 (\uBBF8\uC138\uD55C \uD720 \uC6C0\uC9C1\uC784 \uBB34\uC2DC)\n clearWheelShowTimer();\n wheelShowTimeoutRef.current = setTimeout(() => {\n setScrollbarVisible(true);\n wheelShowTimeoutRef.current = null;\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 ]);\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 // \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 (!finalAutoHideConfig.enabled && isScrollable()) {\n setScrollbarVisible(true);\n }\n }, [isScrollable, updateScrollbar, finalAutoHideConfig.enabled]);\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 .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 === \"right\"\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 === \"right\"\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 === \"right\"\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 === \"right\"\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 </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": "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,eAAAC,EACA,WAAAC,GAEA,cAAAC,GACA,uBAAAC,GACA,mBAAAC,OACG,QAopCa,OAAA,OAAAC,GAiBA,QAAAC,OAjBA,oBC3pCpB,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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",
|
|
6
6
|
"names": ["forwardRef", "useCallback", "useMemo", "useRef", "useEffect", "memo", "useState", "Box", "Table", "MuiTableBody", "TableCell", "TableContainer", "TableHead", "MuiTableRow", "TableSortLabel", "Paper", "Typography", "TableVirtuoso", "__assign", "t", "s", "i", "n", "p", "LoadingProgress", "_a", "visible", "onComplete", "_b", "fadeoutDuration", "_c", "exitDelay", "_d", "size", "className", "style", "sx", "indicator", "_e", "background", "prevVisibleRef", "useRef", "boxRef", "_f", "useState", "shouldRender", "setShouldRender", "_g", "showBackground", "_h", "backgroundColor", "_j", "backgroundOpacity", "useEffect", "prevVisible", "box", "renderIndicator", "_jsx", "CircularProgress", "getBackgroundStyle", "Box", "__assign", "useRef", "useEffect", "useState", "useCallback", "useMemo", "forwardRef", "useImperativeHandle", "useLayoutEffect", "jsx", "jsxs", "DEFAULT_EXCLUDE_CLASSES", "isTextInputElement", "element", "config", "tagName", "inputTypes", "type", "selector", "checkElementAndParents", "allExcludeClasses", "currentElement", "depth", "maxDepth", "cls", "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", "isDragScrolling", "setIsDragScrolling", "dragScrollStart", "setDragScrollStart", "activeArrow", "setActiveArrow", "hoveredArrow", "setHoveredArrow", "isInitialized", "setIsInitialized", "wheelTimeoutRef", "isWheelScrolling", "setIsWheelScrolling", "hideTimeoutRef", "hoverEnterTimeoutRef", "wheelShowTimeoutRef", "finalThumbConfig", "baseColor", "finalTrackConfig", "finalArrowsConfig", "finalDragScrollConfig", "finalAutoHideConfig", "finalThumbWidth", "finalTrackWidth", "thumbMinHeight", "showArrows", "arrowStep", "maintainFocus", "activeElement", "options", "findScrollableElement", "cached", "childScrollableElements", "child", "parent", "isNestedInAnotherScrollbar", "isScrollable", "clearHideTimer", "clearHoverEnterTimer", "clearWheelShowTimer", "setHideTimer", "delay", "updateScrollbar", "scrollableElement", "containerHeight", "contentHeight", "scrollTop", "wrapperPaddingTopBottom", "computedStyle", "paddingTop", "paddingBottom", "arrowSpace", "availableHeight", "scrollRatio", "calculatedThumbHeight", "scrollableHeight", "thumbScrollableHeight", "calculatedThumbTop", "handleThumbMouseDown", "event", "actualScrollContainer", "handleMouseMove", "deltaY", "scrollDelta", "newScrollTop", "handleMouseUp", "handleTrackClick", "rect", "clickY", "handleUpArrowClick", "handleDownArrowClick", "container", "maxScrollTop", "handleDragScrollStart", "target", "handleDragScrollMove", "deltaX", "handleDragScrollEnd", "handleScroll", "handleWheel", "elementsToWatch", "handleKeyDown", "key", "scrollHeight", "clientHeight", "lineScrollStep", "newThumbTop", "timer", "resizeObserver", "elementsToObserve", "observer", "adjustedTrackWidth", "styleId", "existingStyle", "styleToRemove", "e", "OverlayScrollbar_default", "Fragment", "jsx", "jsxs", "OVERLAY_SCROLLBAR_TRACK_CONFIG", "VirtualDataTableComponent", "data", "loading", "columns", "onRowClick", "rowHeight", "columnHeight", "striped", "rowDivider", "onSort", "onLoadMore", "sortBy", "sortDirection", "showPaper", "paddingX", "paddingTop", "paddingBottom", "rowHoverColor", "rowHoverOpacity", "scrollbars", "emptyMessage", "LoadingComponent", "VirtuosoScroller", "useMemo", "forwardRef", "props", "ref", "scrollContainerRef", "useRef", "De", "TableContainer", "Box", "node", "stripedRowColor", "internalLoading", "setInternalLoading", "useState", "tableKey", "setTableKey", "useEffect", "handleLoadingComplete", "useCallback", "shouldShowLoading", "isLoadMoreLoading", "isLoadingMoreRef", "virtuosoRef", "isDraggingRef", "dragStartRef", "isMouseDownRef", "initialScrollTopRef", "totalDragDistanceRef", "isScrollDraggingRef", "mouseDownPositionRef", "scrollDragTimeoutRef", "handleMouseDown", "e", "handleMouseMove", "deltaY", "dragDelta", "scrollContainer", "newScrollTop", "handleMouseUp", "finalScrollTop", "setScrollPosition", "tableContainer", "label", "mouseLeaveEvent", "handleSort", "columnId", "handleRangeChange", "range", "now", "lastTime", "bufferSize", "shouldLoadMore", "hasMinimumData", "offset", "prev", "fixedHeaderContent", "groupMap", "noGroupColumns", "col", "MuiTableRow", "TableCell", "TableSortLabel", "firstRowCells", "group", "cols", "secondRowCells", "rowContent", "index", "item", "column", "VirtuosoTableComponents", "Table", "TableHead", "rest", "rowIndex", "isOddRow", "deltaX", "dragThreshold", "theme", "isDark", "color", "opacity", "hex", "r", "g", "b", "max", "min", "h", "s", "l", "d", "hue2rgb", "p", "q", "t", "MuiTableBody", "tableContent", "TableVirtuoso", "Typography", "LoadingProgress", "Paper", "VirtualDataTable", "memo"]
|
|
7
7
|
}
|