@ehfuse/mui-virtual-data-table 1.4.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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", "../src/CssSpinner.tsx"],
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 TableFooter as MuiTableFooter,\n TableRow as MuiTableRow,\n TableSortLabel,\n Menu,\n MenuItem,\n Divider,\n SvgIcon,\n Paper,\n Typography,\n useTheme,\n type SxProps,\n type Theme,\n} from \"@mui/material\";\nimport { TableVirtuoso } from \"react-virtuoso\";\nimport type { TableComponents } from \"react-virtuoso\";\nimport { LoadingProgress } from \"@ehfuse/mui-fadeout-loading-progress\";\nimport { CssSpinner } from \"./CssSpinner\";\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: \"default\" as const, // \uC61B \uAC12 \"right\" \uB294 1.7 \uD0C0\uC785\uC5D0\uC11C \uC0AC\uB77C\uC84C\uB2E4 \u2014 \uB3D9\uC791\uC740 \uAC19\uB2E4(\"outside\" \uAC00 \uC544\uB2C8\uBA74 \uC548\uCABD \uC815\uB82C)\n margin: 0,\n radius: 0,\n};\nconst ROW_CLICK_DRAG_THRESHOLD_PX = 5;\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 */\n/**\n * \uB178\uC158\uD48D(variant=\"notion\") \uC0C9 \u2014 @ehfuse/taskbox \uC758 \uBAA9\uB85D\uD45C \uD314\uB808\uD2B8(light: border/borderStrong/textSecondary/surfaceHover,\n * dark: \uAC19\uC740 \uC774\uB984\uC758 \uB2E4\uD06C \uAC12)\uB97C \uADF8\uB300\uB85C \uC62E\uAE34 \uAC83\uC774\uB2E4. \uB450 \uD328\uD0A4\uC9C0\uAC00 \uC11C\uB85C\uB97C \uCC38\uC870\uD558\uC9C0 \uC54A\uC544 \uAC12\uC744 \uBCA0\uAEF4 \uB454\uB2E4 \u2014 \uADF8\uCABD\uC774 \uBC14\uB00C\uBA74 \uC5EC\uAE30\uB3C4 \uB9DE\uCD98\uB2E4.\n */\nconst NOTION_LIGHT = {\n bg: \"#ffffff\",\n border: \"#e6e6e3\",\n borderStrong: \"#dedddb\",\n headerColor: \"#787774\",\n hoverBg: \"#f8f8f7\",\n emptyColor: \"#9b9a97\",\n selectedBg: \"#dbeafe\",\n selectedBar: \"#3b82f6\",\n};\n/** \uB178\uC158\uD48D \uC885\uC774 \uC704\uC544\uB798 \uC5EC\uBC31 \u2014 \uC88C\uC6B0 \uAE30\uBCF8(12px)\uACFC \uAC19\uB2E4. */\nconst NOTION_PADDING_Y = \"12px\";\nconst NOTION_DARK = {\n bg: \"#1e1e1e\",\n border: \"#2c333c\",\n borderStrong: \"#3b434e\",\n headerColor: \"#a3adbb\",\n hoverBg: \"#272d36\",\n emptyColor: \"#7d8590\",\n selectedBg: \"rgba(59, 130, 246, 0.22)\",\n selectedBar: \"#60a5fa\",\n};\n\n/** \uBA38\uB9AC \uC6B0\uD074\uB9AD \uBA54\uB274\uC758 \uC544\uC774\uCF58(Material \uC544\uC774\uCF58 \uACBD\uB85C) \u2014 @mui/icons-material \uC744 \uC758\uC874\uC131\uC73C\uB85C \uB4E4\uC774\uC9C0 \uC54A\uC73C\uB824\uACE0 \uACBD\uB85C\uB9CC \uC62E\uACA8 \uB454\uB2E4. */\nconst ICON_PATHS = {\n asc: \"M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z\",\n desc: \"M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z\",\n checked: \"M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\",\n unchecked: \"M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z\",\n check: \"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\",\n filter: \"M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z\",\n};\n\nfunction PathIcon({ d, size = 18, color }: { d: string; size?: number; color?: string }) {\n return (\n <SvgIcon sx={{ fontSize: size, flexShrink: 0, color }}>\n <path d={d} />\n </SvgIcon>\n );\n}\n\n/** \uC774 \uC5F4\uC774 \uBA38\uB9AC \uBA54\uB274\uC5D0 \uAC70\uB974\uAE30 \uBAA9\uB85D\uC744 \uAC16\uB294\uC9C0 \u2014 \uAC12 \uBAA9\uB85D\uACFC \uBC14\uB01C \uC54C\uB9BC\uC774 \uB458 \uB2E4 \uC788\uC5B4\uC57C \uD55C\uB2E4. */\nfunction hasColumnFilter<T>(col: DataColumn<T>): boolean {\n return Boolean(col.filterOptions && col.onFilterChange);\n}\n\nfunction VirtualDataTableComponent<T>({\n data,\n loading = false,\n columns,\n onRowClick,\n getRowId,\n selectedRowId,\n selectedRowSx: selectedRowSxProp,\n rowHeight: rowHeightProp,\n columnHeight: columnHeightProp,\n striped,\n rowDivider = true,\n onSort,\n onSortClear,\n onHeaderContextMenu,\n onLoadMore,\n sortBy,\n sortDirection,\n showPaper = true,\n paddingX: paddingXProp,\n paddingTop = 0,\n paddingBottom = 0,\n rowHoverColor: rowHoverColorProp,\n rowHoverOpacity: rowHoverOpacityProp,\n viewportBuffer,\n overscan,\n scrollbars,\n emptyMessage = \"NO DATA\",\n autoHeight = false,\n LoadingComponent,\n showFooter,\n footerHeight,\n footerSx,\n variant = \"default\",\n framed = true,\n headerTopBorder = false,\n rowHeightMode = \"fixed\",\n tableLayout = \"fixed\",\n renderFullWidthRow,\n fullWidthRowSx,\n onRowContextMenu,\n pinnedRows,\n pinnedRowsMaxHeight,\n pinnedRowsSx,\n resetScrollOnDataChange = true,\n rowKeyFromId = false,\n onEndReached,\n colorMode,\n}: VirtualDataTableProps<T>) {\n // \uB178\uC158\uD48D(variant=\"notion\") \u2014 @ehfuse/taskbox \uBAA9\uB85D\uD45C\uC640 \uAC19\uC740 \uAC12\uC774\uB2E4. \uAE30\uBCF8\uAC12\uB9CC \uBC14\uAFB8\uACE0 \uC9C1\uC811 \uC900 prop \uC774 \uC774\uAE34\uB2E4.\n const notion = variant === \"notion\";\n const muiTheme = useTheme();\n // colorMode \uB97C \uC8FC\uBA74 \uC571 \uD14C\uB9C8\uC640 \uB2EC\uB9AC \uC774 \uD45C\uB9CC \uADF8 \uBAA8\uB4DC\uB85C \uCE60\uD55C\uB2E4(\uC571\uC740 \uBC1D\uC740\uB370 \uC5C5\uBB34\uD568\uB9CC \uC5B4\uB450\uC6B4 \uACBD\uC6B0).\n const notionTokens = (colorMode ?? muiTheme.palette.mode) === \"dark\" ? NOTION_DARK : NOTION_LIGHT;\n const hasPinnedRows = (pinnedRows?.length ?? 0) > 0;\n const columnHeight = columnHeightProp ?? (notion ? 40 : 56);\n // \uB178\uC158\uD48D \uC904 \uB192\uC774 \uAE30\uBCF8 48 \u2014 \uC5C5\uBB34\uD568 \uBAA9\uB85D \uD45C \u00B7 \uC804\uC790\uACB0\uC7AC \uD45C\uAC00 \uC4F0\uB294 \uAC12\uC774\uB2E4.\n const rowHeight = rowHeightProp ?? (notion ? 48 : 50);\n // \uD2C0 \uC5C6\uC774(framed=false) \uADF8\uB9B4 \uB54C\uB294 \uBC14\uAE65 \uC0C1\uC790\uAC00 \uC774\uBBF8 \uD14C\uB450\uB9AC\uB97C \uB458\uB800\uB2E4 \u2014 \uC88C\uC6B0 \uC5EC\uBC31 \uC5C6\uC774 \uD45C\uAC00 \uC0C1\uC790\uC5D0 \uAF49 \uCC2C\uB2E4.\n const paddingX = framed ? (paddingXProp ?? (notion ? \"12px\" : \"1rem\")) : 0;\n const autoRowHeight = rowHeightMode === \"auto\";\n // \uD638\uBC84\uB294 \uB2E8\uC0C9(\uBD88\uD22C\uBA85) \u2014 \uAE30\uBCF8 \uBAA8\uC591\uC758 \uBC18\uD22C\uBA85 \uAC80\uC815\uC740 \uD770 \uC885\uC774 \uC704\uC5D0\uC11C \uD68C\uC0C9\uC774 \uC544\uB2C8\uB77C \uD0C1\uD55C \uC0C9\uC73C\uB85C \uBCF4\uC778\uB2E4.\n const rowHoverColor = rowHoverColorProp ?? (notion ? notionTokens.hoverBg : undefined);\n const rowHoverOpacity = rowHoverOpacityProp ?? (notion ? 1 : undefined);\n const defaultViewportBufferTop = Math.max(rowHeight * 12, 480);\n const defaultViewportBufferBottom = Math.max(rowHeight * 12, 480);\n const viewportBufferTop =\n typeof viewportBuffer === \"number\"\n ? viewportBuffer\n : (viewportBuffer?.top ?? defaultViewportBufferTop);\n const viewportBufferBottom =\n typeof viewportBuffer === \"number\"\n ? viewportBuffer\n : (viewportBuffer?.bottom ?? defaultViewportBufferBottom);\n const defaultOverscanMain = Math.max(rowHeight * 8, 420);\n const defaultOverscanReverse = Math.max(rowHeight * 10, 520);\n const virtuosoOverscan =\n typeof overscan === \"number\"\n ? overscan\n : {\n main: overscan?.main ?? defaultOverscanMain,\n reverse: overscan?.reverse ?? defaultOverscanReverse,\n };\n const estimatedItemHeight = rowHeight + (rowDivider ? 1 : 0);\n\n // \uC120\uD0DD \uD589 \uD558\uC774\uB77C\uC774\uD2B8\uB294 selectedRowSx \uAC00 \uAC1D\uCCB4(\uB610\uB294 \uBBF8\uC9C0\uC815)\uBA74 CSS \uC140\uB809\uD130\uB85C \uCC98\uB9AC\uD55C\uB2E4.\n // \uCEE8\uD14C\uC774\uB108 sx \uC5D0 `tr[data-row-id=\"...\"]` \uADDC\uCE59\uC744 \uB123\uC73C\uBA74 selectedRowId \uBCC0\uACBD \uC2DC components/\uD589\uC744\n // \uC7AC\uB80C\uB354\uD558\uC9C0 \uC54A\uACE0(\uCEE8\uD14C\uC774\uB108 1\uAC1C\uB9CC \uAC31\uC2E0) CSS \uB85C\uB9CC \uAC15\uC870\uB3FC row \uD074\uB9AD \uBC18\uC751\uC774 \uC989\uAC01\uC801\uC774\uB2E4.\n // \uD568\uC218\uD615 selectedRowSx(\uD589\uB9C8\uB2E4 \uB3D9\uC801)\uB294 CSS \uB85C \uD45C\uD604 \uBD88\uAC00\uD558\uBBC0\uB85C \uAE30\uC874 per-row \uACBD\uB85C\uB97C \uC720\uC9C0\uD55C\uB2E4.\n // \uB178\uC158\uD48D\uC740 \uC120\uD0DD \uC904 \uBAA8\uC591\uC744 \uAE30\uBCF8\uC73C\uB85C \uAC16\uB294\uB2E4 \u2014 \uC605\uC740 \uD30C\uB780 \uBC14\uD0D5 + \uC67C\uCABD \uD30C\uB780 \uB760 3px(\uBAA9\uB85D \uD45C\uC758 \"\uC9C0\uAE08 \uC5F4\uC5B4 \uB454 \uC904\").\n // \uB760\uB294 \uC904(tr)\uC758 \uADF8\uB9BC\uC790\uAC00 \uBE0C\uB77C\uC6B0\uC800\uB9C8\uB2E4 \uADF8\uB824\uC9C0\uC9C0 \uC54A\uC544 \uCCAB \uCE78 \uC548\uCABD \uADF8\uB9BC\uC790\uB85C \uAE0B\uB294\uB2E4. \uACE0\uC815 \uC5F4 \uCE78\uC740 \uC81C \uBC14\uD0D5\uC744 \uCE60\uD558\uBBC0\uB85C \uAC19\uC740 \uC0C9\uC744 \uC900\uB2E4.\n const notionSelectedSx = useMemo(\n () =>\n notion\n ? {\n backgroundColor: notionTokens.selectedBg,\n \"& > td:first-of-type\": { boxShadow: `inset 3px 0 0 ${notionTokens.selectedBar}` },\n \"& > td[data-vdt-pinned]\": { backgroundColor: notionTokens.selectedBg },\n }\n : undefined,\n [notion, notionTokens],\n );\n const selectedRowSx = selectedRowSxProp ?? notionSelectedSx;\n const useCssRowHighlight = !selectedRowSx || typeof selectedRowSx !== \"function\";\n const selectedRowCssSx = useMemo<Record<string, unknown> | null>(() => {\n if (\n !useCssRowHighlight ||\n selectedRowId === null ||\n selectedRowId === undefined ||\n !selectedRowSx\n ) {\n return null;\n }\n const escaped = String(selectedRowId).replace(/[\"\\\\]/g, \"\\\\$&\");\n return {\n [`& tbody tr[data-row-id=\"${escaped}\"]`]: selectedRowSx,\n };\n }, [useCssRowHighlight, selectedRowId, selectedRowSx]);\n\n const isDev =\n typeof window !== \"undefined\" &&\n (window.location.hostname === \"localhost\" ||\n window.location.hostname === \"127.0.0.1\");\n\n const [perfDebugEnabled] = useState(() => {\n if (typeof window === \"undefined\") {\n return false;\n }\n return window.localStorage.getItem(\"vdt-perf-debug\") === \"1\";\n });\n const perfStatsRef = useRef({\n wheelEvents: 0,\n wheelInputPx: 0,\n wheelHandlerMs: 0,\n wheelRafFlushes: 0,\n wheelRafMs: 0,\n rangeChangedCalls: 0,\n rangeChangedMs: 0,\n rowContentCalls: 0,\n rowContentMs: 0,\n rowContentMaxMs: 0,\n cellRenderCalls: 0,\n cellRenderMs: 0,\n cellRenderMaxMs: 0,\n });\n\n // \uB204\uC801\uB41C \uC131\uB2A5 \uD1B5\uACC4\uB97C \uCF58\uC194\uC5D0 \uC8FC\uAE30\uC801\uC73C\uB85C \uCD9C\uB825\uD55C\uB2E4.\n const flushPerfStats = useCallback(\n (reason: string) => {\n if (!perfDebugEnabled) {\n return;\n }\n const stats = perfStatsRef.current;\n const hasData =\n stats.wheelEvents > 0 ||\n stats.rangeChangedCalls > 0 ||\n stats.rowContentCalls > 0 ||\n stats.cellRenderCalls > 0;\n if (!hasData) {\n return;\n }\n\n const rowAvgMs =\n stats.rowContentCalls > 0\n ? stats.rowContentMs / stats.rowContentCalls\n : 0;\n const cellAvgMs =\n stats.cellRenderCalls > 0\n ? stats.cellRenderMs / stats.cellRenderCalls\n : 0;\n\n console.log(\"[VDT perf]\", {\n reason,\n wheel: {\n events: stats.wheelEvents,\n inputPx: Math.round(stats.wheelInputPx),\n handlerMs: Number(stats.wheelHandlerMs.toFixed(2)),\n rafFlushes: stats.wheelRafFlushes,\n rafMs: Number(stats.wheelRafMs.toFixed(2)),\n },\n rangeChanged: {\n calls: stats.rangeChangedCalls,\n totalMs: Number(stats.rangeChangedMs.toFixed(2)),\n },\n rowContent: {\n calls: stats.rowContentCalls,\n totalMs: Number(stats.rowContentMs.toFixed(2)),\n avgMs: Number(rowAvgMs.toFixed(3)),\n maxMs: Number(stats.rowContentMaxMs.toFixed(3)),\n },\n cellRender: {\n calls: stats.cellRenderCalls,\n totalMs: Number(stats.cellRenderMs.toFixed(2)),\n avgMs: Number(cellAvgMs.toFixed(3)),\n maxMs: Number(stats.cellRenderMaxMs.toFixed(3)),\n },\n });\n\n perfStatsRef.current = {\n wheelEvents: 0,\n wheelInputPx: 0,\n wheelHandlerMs: 0,\n wheelRafFlushes: 0,\n wheelRafMs: 0,\n rangeChangedCalls: 0,\n rangeChangedMs: 0,\n rowContentCalls: 0,\n rowContentMs: 0,\n rowContentMaxMs: 0,\n cellRenderCalls: 0,\n cellRenderMs: 0,\n cellRenderMaxMs: 0,\n };\n },\n [perfDebugEnabled],\n );\n\n useEffect(() => {\n if (!perfDebugEnabled || typeof window === \"undefined\") {\n return;\n }\n\n console.log(\"[VDT perf] enabled (localStorage vdt-perf-debug=1)\");\n\n const intervalId = window.setInterval(() => {\n flushPerfStats(\"interval\");\n }, 1500);\n\n return () => {\n window.clearInterval(intervalId);\n flushPerfStats(\"cleanup\");\n };\n }, [flushPerfStats, perfDebugEnabled]);\n\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 const wheelDeltaRef = useRef(0);\n const wheelRafRef = useRef<number | null>(null);\n\n // \uD720 \uC774\uBCA4\uD2B8\uB97C \uC9C1\uC811 \uC81C\uC5B4\uD574 \uBE0C\uB77C\uC6B0\uC800 smooth-scroll \uBCF4\uAC04 \uC5C6\uC774 \uC989\uC2DC scrollTop \uBC18\uC601\n useEffect(() => {\n const el = scrollContainerRef.current;\n if (!el) return;\n\n // \uD720 \uB378\uD0C0\uB97C \uD504\uB808\uC784 \uB2E8\uC704\uB85C \uD569\uC0B0 \uBC18\uC601\uD574 \uACFC\uB3C4\uD55C scrollTop \uAC31\uC2E0\uC744 \uC904\uC778\uB2E4.\n const handleWheel = (e: WheelEvent) => {\n const wheelStart = perfDebugEnabled\n ? performance.now()\n : 0;\n // \uAC00\uB85C \uD720(\uD2B8\uB799\uD328\uB4DC \uC606 \uBC00\uAE30 \u00B7 Shift+\uD720)\uC740 \uBE0C\uB77C\uC6B0\uC800\uC5D0 \uB9E1\uAE34\uB2E4 \u2014 \uC544\uB798\uC5D0\uC11C \uC138\uB85C\uB85C\uB9CC \uC62E\uAE30\uBBC0\uB85C \uB9C9\uC73C\uBA74\n // \uC5F4\uC774 \uB9CE\uC740 \uD45C(tableLayout=\"auto\")\uB97C \uC606\uC73C\uB85C \uBC00 \uC218 \uC5C6\uB2E4.\n if (e.shiftKey || Math.abs(e.deltaX) > Math.abs(e.deltaY)) {\n return;\n }\n // \uBA38\uB9AC \uC544\uB798 \uACE0\uC815 \uC904 \uC601\uC5ED(pinnedRows)\uCC98\uB7FC \uC548\uC5D0\uC11C \uB530\uB85C \uAD74\uB9AC\uB294 \uC0C1\uC790 \uC704\uC5D0\uC11C\uB294 \uADF8 \uC0C1\uC790\uB97C \uBA3C\uC800 \uAD74\uB9B0\uB2E4 \u2014\n // \uC5EC\uAE30\uC11C \uB9C9\uC73C\uBA74 \uADF8 \uC601\uC5ED\uC758 6\uBC88\uC9F8 \uC904\uBD80\uD130\uB294 \uBCFC \uBC29\uBC95\uC774 \uC5C6\uB2E4. \uB05D\uC5D0 \uB2FF\uC558\uC73C\uBA74 \uBCF8\uBB38\uC744 \uAD74\uB9B0\uB2E4.\n const inner = (e.target as HTMLElement | null)?.closest?.(\"[data-vdt-inner-scroll]\") as HTMLElement | null;\n if (inner && el.contains(inner)) {\n const canScroll =\n e.deltaY < 0\n ? inner.scrollTop > 0\n : inner.scrollTop + inner.clientHeight < inner.scrollHeight - 1;\n if (canScroll) return;\n }\n e.preventDefault();\n let delta = e.deltaY;\n // deltaMode 1 = \uB77C\uC778 \uB2E8\uC704, 2 = \uD398\uC774\uC9C0 \uB2E8\uC704 \uBCC0\uD658\n if (e.deltaMode === 1) {\n delta *= 40;\n } else if (e.deltaMode === 2) {\n delta *= el.clientHeight;\n }\n\n if (perfDebugEnabled) {\n perfStatsRef.current.wheelEvents += 1;\n perfStatsRef.current.wheelInputPx += delta;\n }\n\n wheelDeltaRef.current += delta;\n if (wheelRafRef.current !== null) {\n return;\n }\n\n wheelRafRef.current = requestAnimationFrame(() => {\n const rafStart = perfDebugEnabled\n ? performance.now()\n : 0;\n const maxStep = Math.max(\n el.clientHeight * 0.4,\n 160,\n );\n const batchedDelta = Math.max(\n -maxStep,\n Math.min(maxStep, wheelDeltaRef.current),\n );\n wheelDeltaRef.current = 0;\n wheelRafRef.current = null;\n if (batchedDelta !== 0) {\n el.scrollTop += batchedDelta;\n }\n if (perfDebugEnabled) {\n perfStatsRef.current.wheelRafFlushes += 1;\n perfStatsRef.current.wheelRafMs +=\n performance.now() - rafStart;\n }\n });\n\n if (perfDebugEnabled) {\n perfStatsRef.current.wheelHandlerMs +=\n performance.now() - wheelStart;\n }\n };\n\n el.addEventListener(\"wheel\", handleWheel, {\n passive: false,\n });\n return () => {\n el.removeEventListener(\"wheel\", handleWheel);\n if (wheelRafRef.current !== null) {\n cancelAnimationFrame(wheelRafRef.current);\n wheelRafRef.current = null;\n }\n wheelDeltaRef.current = 0;\n };\n }, []);\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 // \uB178\uC158\uD48D\uC740 \uC88C\uC6B0 \uC5EC\uBC31\uC744 \uC885\uC774(Paper/Box) \uCABD\uC5D0 \uC900\uB2E4 \u2014 \uD14C\uB450\uB9AC\uAC00 \uC5EC\uBC31 \uC548\uCABD\uC5D0 \uADF8\uB824\uC838\uC57C \uD55C\uB2E4.\n paddingRight: notion ? 0 : 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, notion \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 // \uC9C1\uC804\uC5D0 loadMore \uB97C \uC694\uCCAD\uD55C \uC2DC\uC810\uC758 \uB370\uC774\uD130 \uAE38\uC774. \uC694\uCCAD \uD6C4 \uAE38\uC774\uAC00 \uB298\uC9C0 \uC54A\uC558\uB2E4\uBA74\n // (= \uC11C\uBC84\uC5D0 \uB354 \uC774\uC0C1 \uB370\uC774\uD130 \uC5C6\uC74C) \uAC19\uC740 \uAE38\uC774\uB85C\uB294 \uB2E4\uC2DC \uC694\uCCAD\uD558\uC9C0 \uC54A\uC544, \uBC14\uB2E5\uC5D0\uC11C\n // endReached \u2194 onLoadMore \uAC00 \uBB34\uD55C \uBC18\uBCF5\uB418\uB294 \uAC83\uC744 \uB9C9\uB294\uB2E4.\n const lastLoadMoreLengthRef = useRef<number>(-1);\n const virtuosoRef = useRef<any>(null); // TableVirtuoso ref\n // \uC904\uB4E4\uC774 \uC2A4\uD06C\uB864 \uC601\uC5ED\uBCF4\uB2E4 \uAE34\uAC00 \u2014 \uAE38\uBA74 \uB9E8 \uB05D \uC904\uC774 \uD2C0 \uBC14\uB2E5\uC5D0 \uB2FF\uC73C\uBBC0\uB85C \uADF8 \uC904\uC758 \uC544\uB798\uC120\uC744 \uBE80\uB2E4(\uC544\uB798 \uB178\uC158 \uC2A4\uD0C0\uC77C).\n const scrollerElRef = useRef<HTMLElement | null>(null);\n const [listOverflows, setListOverflows] = useState(false);\n const checkListOverflow = useCallback(() => {\n const el = scrollerElRef.current;\n if (el) setListOverflows(el.scrollHeight > el.clientHeight + 1);\n }, []);\n useEffect(() => {\n const el = scrollerElRef.current;\n if (!el || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(() => checkListOverflow());\n observer.observe(el);\n return () => observer.disconnect();\n }, [checkListOverflow, autoHeight]);\n\n // \uC18C\uBE44\uCC98\uAC00 \uC778\uB77C\uC778\uC73C\uB85C \uB118\uAE30\uB294 \uCF5C\uBC31(onRowClick/getRowId)\uC740 \uB9E4 \uB80C\uB354\uB9C8\uB2E4 identity \uAC00 \uBC14\uB010\uB2E4.\n // \uC774\uB97C ref \uB85C \uC7A1\uC544 \uB450\uBA74 VirtuosoTableComponents(memo)\uB97C \uC7AC\uC0DD\uC131\uD558\uC9C0 \uC54A\uC544\uB3C4 \uCD5C\uC2E0 \uCF5C\uBC31\uC744 \uC4F8 \uC218 \uC788\uC5B4,\n // \uAC80\uC0C9/\uD544\uD130\uB85C \uBD80\uBAA8\uAC00 \uB9AC\uB80C\uB354\uB3FC\uB3C4 \uD589(\uBC0F \uC774\uBBF8\uC9C0)\uC774 \uB9AC\uB9C8\uC6B4\uD2B8\uB418\uC9C0 \uC54A\uB294\uB2E4(\uC0AC\uC9C4 \uAE5C\uBE61\uC784 \uBC29\uC9C0).\n const onRowClickRef = useRef(onRowClick);\n onRowClickRef.current = onRowClick;\n const getRowIdRef = useRef(getRowId);\n getRowIdRef.current = getRowId;\n const onRowContextMenuRef = useRef(onRowContextMenu);\n onRowContextMenuRef.current = onRowContextMenu;\n const onEndReachedRef = useRef(onEndReached);\n onEndReachedRef.current = onEndReached;\n // \uACE0\uC815 \uC904(pinnedRows)\uC740 \uBA38\uB9AC \uC548\uC5D0 \uADF8\uB9AC\uB294\uB370 \uBA38\uB9AC \uB0B4\uC6A9\uC774 \uC904 \uBD80\uD488\uBCF4\uB2E4 \uBA3C\uC800 \uB9CC\uB4E4\uC5B4\uC9C4\uB2E4 \u2014 \uC904 \uBD80\uD488\uC740 ref \uB85C \uB2A6\uAC8C \uC7A1\uB294\uB2E4.\n const rowComponentRef = useRef<React.ComponentType<any> | null>(null);\n\n // \uACE0\uC815 \uC5F4(pinned: \"left\")\uC774 \uBD99\uC744 \uC67C\uCABD \uC790\uB9AC \u2014 \uC55E\uCABD \uACE0\uC815 \uC5F4 \uD3ED\uC758 \uD569. \uACE0\uC815 \uC5F4\uC774 \uC544\uB2C8\uBA74 \uC5C6\uB2E4.\n const pinnedLeft = useMemo(() => {\n const map = new Map<string, number>();\n let left = 0;\n columns.forEach((col) => {\n if (col.pinned !== \"left\") return;\n map.set(String(col.id), left);\n left += typeof col.width === \"number\" ? col.width : 0;\n });\n return map;\n }, [columns]);\n // \uD45C \uCD5C\uC18C \uD3ED \u2014 minWidth \uB97C \uC900 \uC5F4\uC774 \uC788\uC744 \uB54C\uB9CC. \uC5F4\uB9C8\uB2E4 width(\uC22B\uC790) \uB610\uB294 minWidth \uC758 \uD569\uC774\uACE0, \uD2C0\uC774 \uC881\uC73C\uBA74 \uAC00\uB85C\uB85C \uBBFC\uB2E4.\n const tableMinWidth = useMemo(() => {\n if (!columns.some((col) => typeof col.minWidth === \"number\")) return undefined;\n return columns.reduce(\n (sum, col) =>\n sum + (typeof col.width === \"number\" ? col.width : typeof col.minWidth === \"number\" ? col.minWidth : 0),\n 0,\n );\n }, [columns]);\n /** \uACE0\uC815 \uC5F4 \uCE78\uC758 sticky \uC790\uB9AC. \uBA38\uB9AC \uCE78\uC740 \uBCF8\uBB38 \uACE0\uC815 \uCE78\uBCF4\uB2E4 \uC704(zIndex 3)\uC5D0 \uC120\uB2E4. */\n const pinnedStyle = useCallback(\n (col: DataColumn<T>, head: boolean): React.CSSProperties => {\n const left = pinnedLeft.get(String(col.id));\n if (left === undefined) return {};\n return { position: \"sticky\", left, zIndex: head ? 3 : 1 };\n },\n [pinnedLeft],\n );\n // truthiness \uAC00 \uBC14\uB00C\uBA74(\uD074\uB9AD \uAC00\uB2A5 \uC5EC\uBD80) hover/cursor \uC2A4\uD0C0\uC77C\uC774 \uB2EC\uB77C\uC9C0\uBBC0\uB85C deps \uC5D0\uB294 boolean \uB9CC \uB123\uB294\uB2E4.\n const hasRowClick = !!onRowClick;\n\n // \uC2A4\uD06C\uB864 \uCEE8\uD14C\uC774\uB108 \uCC38\uC870 (OverlayScrollbar\uC6A9)\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\n useEffect(() => {\n const handleDocumentMouseMove = (event: MouseEvent) => {\n const dx = event.clientX - mouseDownPositionRef.current.x;\n const dy = event.clientY - mouseDownPositionRef.current.y;\n if (Math.sqrt(dx * dx + dy * dy) > ROW_CLICK_DRAG_THRESHOLD_PX) {\n isScrollDraggingRef.current = true;\n }\n };\n\n document.addEventListener(\"mousemove\", handleDocumentMouseMove);\n return () => {\n document.removeEventListener(\"mousemove\", handleDocumentMouseMove);\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 /**\n * \uBA38\uB9AC \uC6B0\uD074\uB9AD \uBA54\uB274(1.4.0). \uC5F4\uC740 \uC694\uC18C\uAC00 \uC544\uB2C8\uB77C id \uB85C \uC954\uB2E4 \u2014 \uAC12\uC744 \uACE0\uB974\uBA74 \uC18C\uBE44\uCC98\uAC00 columns \uB97C \uC0C8\uB85C \uB9CC\uB4E4\uC5B4 \uBA38\uB9AC \uCE78\uC774 \uB2E4\uC2DC \uADF8\uB824\uC9C0\uB294\uB370,\n * \uC694\uC18C\uB97C \uC950\uBA74 \uC61B \uC694\uC18C\uC5D0 \uBD99\uC5B4 \uBA54\uB274\uAC00 \uC5C9\uB6B1\uD55C \uB370\uB85C \uAC00\uAC70\uB098 \uB2EB\uD78C\uB2E4. \uC790\uB9AC\uB3C4 \uC88C\uD45C\uB85C \uB454\uB2E4(\uB204\uB978 x \u00B7 \uBA38\uB9AC \uCE78 \uBC14\uB2E5 y).\n */\n const [headerMenu, setHeaderMenu] = useState<{ colId: string; x: number; y: number } | null>(null);\n const onHeaderContextMenuRef = useRef(onHeaderContextMenu);\n onHeaderContextMenuRef.current = onHeaderContextMenu;\n const onSortRef = useRef(onSort);\n onSortRef.current = onSort;\n\n /**\n * \uBA38\uB9AC \uCE78 \uC6B0\uD074\uB9AD \u2014 \uBE0C\uB77C\uC6B0\uC800 \uBA54\uB274\uB294 \uB298 \uB9C9\uB294\uB2E4(\uBA38\uB9AC\uC5D0\uC11C \"\uB4A4\uB85C \u00B7 \uC0C8\uB85C\uACE0\uCE68\" \uBA54\uB274\uB294 \uC4F8 \uB370\uAC00 \uC5C6\uACE0, \uC815\uB82C \u00B7 \uAC70\uB974\uAE30 \uBA54\uB274\uC640 \uACB9\uCCD0 \uB72C\uB2E4).\n * \uC18C\uBE44\uCC98 \uCC98\uB9AC(headerProps.onContextMenu \u00B7 onHeaderContextMenu)\uAC00 \uBA3C\uC800\uB2E4 \u2014 \uADF8\uCABD\uC774 preventDefault \uD588\uAC70\uB098 true \uB97C \uB3CC\uB824\uC8FC\uBA74 \uAE30\uBCF8 \uBA54\uB274\uB97C \uB744\uC6B0\uC9C0 \uC54A\uB294\uB2E4.\n * \uADF8\uB798\uC11C \uB9C9\uB294 preventDefault \uB294 \uC18C\uBE44\uCC98\uB97C \uBD80\uB978 \uB4A4\uC5D0 \uD55C\uB2E4(\uBA3C\uC800 \uB9C9\uC73C\uBA74 \"\uCC98\uB9AC\uD588\uB2E4\" \uB97C \uAC00\uB824\uB0BC \uC218 \uC5C6\uB2E4).\n */\n const handleHeaderContextMenu = useCallback(\n (col: DataColumn<T> | null, event: React.MouseEvent<HTMLTableCellElement>) => {\n if (!col) {\n event.preventDefault();\n return;\n }\n col.headerProps?.onContextMenu?.(event);\n let handled = event.defaultPrevented;\n if (!handled) handled = onHeaderContextMenuRef.current?.(col, event) === true || event.defaultPrevented;\n event.preventDefault();\n if (handled || col.headerMenu === false) return;\n const canSort = Boolean(col.sortable && onSortRef.current);\n if (!canSort && !hasColumnFilter(col)) return;\n const rect = event.currentTarget.getBoundingClientRect();\n setHeaderMenu({ colId: String(col.id), x: event.clientX, y: rect.bottom });\n },\n [],\n );\n\n /** \uBA38\uB9AC\uAE00 \u2014 \uAC70\uB974\uAE30\uAC00 \uAC78\uB9B0 \uC5F4\uC740 \uAC15\uC870\uC0C9 + \uAC70\uB974\uAE30 \uC544\uC774\uCF58(HeadSortFilter \uC640 \uAC19\uC740 \uD45C\uC2DC). */\n const renderHeaderText = useCallback(\n (col: DataColumn<T>) => {\n if (!(col.filterValues && col.filterValues.length > 0)) return col.text;\n return (\n <Box\n component=\"span\"\n sx={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 0.5,\n maxWidth: \"100%\",\n color: \"primary.main\",\n fontWeight: 600,\n verticalAlign: \"middle\",\n }}\n >\n <Box component=\"span\" sx={{ overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }}>\n {col.text}\n </Box>\n <PathIcon d={ICON_PATHS.filter} size={16} />\n </Box>\n );\n },\n [],\n );\n\n // \uC2A4\uD06C\uB864 \uB05D \uADFC\uCC98\uC5D0\uC11C\uB9CC \uCD94\uAC00 \uB85C\uB4DC\uB97C \uC2E4\uD589\uD574 scroll \uD56B\uD328\uC2A4 \uBD80\uB2F4\uC744 \uC904\uC778\uB2E4.\n const handleEndReached = useCallback(\n (endIndex: number) => {\n const rangeStart = perfDebugEnabled ? performance.now() : 0;\n onEndReachedRef.current?.();\n if (!onLoadMore) {\n if (perfDebugEnabled) {\n perfStatsRef.current.rangeChangedCalls += 1;\n perfStatsRef.current.rangeChangedMs +=\n performance.now() - rangeStart;\n }\n return;\n }\n\n if (loading && data.length === 0) {\n if (perfDebugEnabled) {\n perfStatsRef.current.rangeChangedCalls += 1;\n perfStatsRef.current.rangeChangedMs +=\n performance.now() - rangeStart;\n }\n return;\n }\n\n const hasMinimumData = data.length >= 30;\n const nearEnd = endIndex >= data.length - 1;\n\n // \uC9C1\uC804 \uC694\uCCAD \uC774\uD6C4 \uAE38\uC774\uAC00 \uADF8\uB300\uB85C\uBA74(\uC11C\uBC84\uC5D0 \uB354 \uC774\uC0C1 \uB370\uC774\uD130 \uC5C6\uC74C) \uC7AC\uC694\uCCAD\uD558\uC9C0 \uC54A\uB294\uB2E4.\n const alreadyRequestedAtThisLength =\n lastLoadMoreLengthRef.current === data.length;\n\n if (\n nearEnd &&\n hasMinimumData &&\n !isLoadingMoreRef.current &&\n !alreadyRequestedAtThisLength\n ) {\n isLoadingMoreRef.current = true;\n lastLoadMoreLengthRef.current = data.length;\n const offset = data.length;\n const limit = 50;\n onLoadMore(offset, limit);\n }\n\n if (perfDebugEnabled) {\n perfStatsRef.current.rangeChangedCalls += 1;\n perfStatsRef.current.rangeChangedMs +=\n performance.now() - rangeStart;\n }\n },\n [data.length, loading, onLoadMore, perfDebugEnabled],\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 const resetScrollOnDataChangeRef = useRef(resetScrollOnDataChange);\n resetScrollOnDataChangeRef.current = resetScrollOnDataChange;\n // \uC774\uC804 \uB370\uC774\uD130 \uAE38\uC774 / \uCCAB \uD589 \uC2DD\uBCC4\uC790\uB97C \uCD94\uC801\n const prevDataLengthRef = useRef(data.length);\n const prevFirstRowKeyRef = useRef<unknown>(undefined);\n\n // \uB370\uC774\uD130\uAC00 '\uC9C4\uC9DC\uB85C \uAD50\uCCB4'\uB41C \uACBD\uC6B0(\uC815\uB82C/\uD544\uD130/\uC7AC\uC870\uD68C)\uC5D0\uB9CC \uC2A4\uD06C\uB864\uC744 \uB9E8 \uC704\uB85C \uC774\uB3D9\uD55C\uB2E4.\n // \uB2E8\uC21C\uD788 \uAC19\uC740 \uBAA9\uB85D\uC758 \uD56D\uBAA9\uC774 in-place \uB85C \uBC14\uB00C\uC5C8\uC744 \uBFD0(\uCCB4\uD06C\uBC15\uC2A4 \uD1A0\uAE00, \uBB34\uD55C \uC2A4\uD06C\uB864\n // \uBE48 \uACB0\uACFC, \uBD80\uBAA8 \uB9AC\uB80C\uB354\uB85C \uC778\uD55C \uC0C8 \uBC30\uC5F4 \uCC38\uC870 \uB4F1)\uC778\uB370\uB3C4 \uB9E8 \uC704\uB85C \uD280\uB358 \uBB38\uC81C\uB97C \uB9C9\uB294\uB2E4.\n // \u2192 \uCCAB \uD589 \uC2DD\uBCC4\uC790(getRowId)\uC640 \uAE38\uC774\uB85C '\uAD50\uCCB4' \uC5EC\uBD80\uB97C \uD310\uBCC4\uD55C\uB2E4.\n useEffect(() => {\n const prevLength = prevDataLengthRef.current;\n const currentLength = data.length;\n\n // \uCCAB \uD589 \uD0A4: getRowId \uAC00 \uC788\uC73C\uBA74 \uAC12 \uAE30\uBC18(\uCC38\uC870\uAC00 \uB9E4\uBC88 \uBC14\uB00C\uC5B4\uB3C4 \uC548\uC815), \uC5C6\uC73C\uBA74 \uAC1D\uCCB4 \uCC38\uC870.\n const firstRowKey =\n currentLength > 0\n ? getRowIdRef.current\n ? getRowIdRef.current(data[0], 0)\n : (data[0] as unknown)\n : undefined;\n const prevFirstRowKey = prevFirstRowKeyRef.current;\n\n // \uB370\uC774\uD130 \uAE38\uC774\uAC00 \uC99D\uAC00\uD55C \uACBD\uC6B0 (\uBB34\uD55C \uC2A4\uD06C\uB864) - \uC2A4\uD06C\uB864 \uC704\uCE58 \uC720\uC9C0\n if (currentLength > prevLength && prevLength > 0) {\n prevDataLengthRef.current = currentLength;\n prevFirstRowKeyRef.current = firstRowKey;\n return;\n }\n\n // '\uAD50\uCCB4'\uB85C \uD310\uB2E8: \uAE38\uC774\uAC00 \uC904\uC5C8\uAC70\uB098, \uCCAB \uD589 \uC2DD\uBCC4\uC790\uAC00 \uBC14\uB010 \uACBD\uC6B0\uC5D0\uB9CC \uB9E8 \uC704\uB85C.\n // (\uAC19\uC740 \uAE38\uC774 + \uAC19\uC740 \uCCAB \uD589 = in-place \uC5C5\uB370\uC774\uD2B8 \u2192 \uC2A4\uD06C\uB864 \uC720\uC9C0)\n const dataReplaced =\n currentLength < prevLength ||\n (prevLength > 0 && firstRowKey !== prevFirstRowKey);\n\n // \uBAA9\uB85D\uC774 \uAD50\uCCB4(\uC815\uB82C/\uAC80\uC0C9/\uD544\uD130\uB85C 1\uD398\uC774\uC9C0 \uC7AC\uC870\uD68C)\uB418\uBA74 \uB354\uBCF4\uAE30 \uB798\uCE58\uB97C \uD480\uC5B4 \uBB34\uD55C \uC2A4\uD06C\uB864\uC774\n // \uB2E4\uC2DC \uB3D9\uC791\uD558\uAC8C \uD55C\uB2E4. \uB798\uCE58\uB294 \"\uC694\uCCAD\uD55C \uAE38\uC774\uC5D0\uC11C \uC548 \uB298\uBA74 \uC11C\uBC84 \uC18C\uC9C4\"\uC774\uB77C\uB294 \uC804\uC81C\uC778\uB370,\n // \uAD50\uCCB4\uB85C \uAE38\uC774\uAC00 \uC6B0\uC5F0\uD788 \uAC19\uC544\uC9C0\uBA74(\uC608: 100\u219250 \uC774 \uC544\uB2C8\uB77C \uC18C\uC9C4 \uD6C4 \uB2E4\uB978 \uAC80\uC0C9\uC774 50) \uADF8 \uC804\uC81C\uAC00\n // \uAE68\uC838 onLoadMore \uAC00 \uC601\uAD6C\uD788 \uBA48\uCD98\uB2E4. append/\uBE48\uC751\uB2F5\uC740 \uC704 early-return\u00B7\uB3D9\uC77C firstRowKey \uB85C\n // \uAC78\uB7EC\uC9C0\uBBC0\uB85C(=dataReplaced=false) 1.1.29 \uAC00 \uACE0\uCE5C \"\uBC14\uB2E5 \uB5A8\uB9BC\"\uC740 \uB418\uC0B4\uC544\uB098\uC9C0 \uC54A\uB294\uB2E4.\n if (dataReplaced) {\n lastLoadMoreLengthRef.current = -1;\n }\n\n if (virtuosoRef.current && currentLength > 0 && dataReplaced && resetScrollOnDataChangeRef.current) {\n virtuosoRef.current.scrollToIndex({\n index: 0,\n align: \"start\",\n behavior: \"auto\",\n });\n }\n\n prevDataLengthRef.current = currentLength;\n prevFirstRowKeyRef.current = firstRowKey;\n }, [data]);\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 headerRowsContent = 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 {...col.headerProps}\n onContextMenu={(e: React.MouseEvent<HTMLTableCellElement>) => handleHeaderContextMenu(col, e)}\n style={{\n width: col.width,\n minWidth: col.width ?? col.minWidth,\n ...col.style,\n fontWeight: \"bold\",\n position: \"sticky\",\n top: 0,\n zIndex: 2,\n padding: \"16px\",\n ...pinnedStyle(col, true),\n ...col.headerProps?.style,\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 {renderHeaderText(col)}\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 renderHeaderText(col)\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 {...col.headerProps}\n onContextMenu={(e: React.MouseEvent<HTMLTableCellElement>) => handleHeaderContextMenu(col, e)}\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 ...pinnedStyle(col, true),\n ...col.headerProps?.style,\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 {renderHeaderText(col)}\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 renderHeaderText(col)\n )}\n </TableCell>\n )),\n ...Object.entries(groupMap).map(([group, cols]) => (\n <TableCell\n key={group}\n align=\"center\"\n colSpan={cols.length}\n onContextMenu={(e: React.MouseEvent<HTMLTableCellElement>) => handleHeaderContextMenu(null, e)}\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 {...col.headerProps}\n onContextMenu={(e: React.MouseEvent<HTMLTableCellElement>) => handleHeaderContextMenu(col, e)}\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 ...pinnedStyle(col, true),\n ...col.headerProps?.style,\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 {renderHeaderText(col)}\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 renderHeaderText(col)\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, pinnedStyle, handleHeaderContextMenu, renderHeaderText]);\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 const rowStart = perfDebugEnabled ? performance.now() : 0;\n // console.log(\"rowContent \uB80C\uB354\uB9C1:\", { index, item: item ? \"\uC788\uC74C\" : \"\uC5C6\uC74C\" });\n\n if (!item) {\n if (perfDebugEnabled) {\n perfStatsRef.current.rowContentCalls += 1;\n const rowDuration = performance.now() - rowStart;\n perfStatsRef.current.rowContentMs += rowDuration;\n perfStatsRef.current.rowContentMaxMs = Math.max(\n perfStatsRef.current.rowContentMaxMs,\n rowDuration,\n );\n }\n return null;\n }\n\n // \uD55C \uCE78 \uC904(\uBB36\uC74C \uBA38\uB9AC \uB4F1) \u2014 \uBAA8\uB4E0 \uC5F4\uC744 \uD569\uCE5C \uCE78 \uD558\uB098. \uC5EC\uBC31 \u00B7 \uBC14\uD0D5\uC740 fullWidthRowSx \uAC00 \uC815\uD55C\uB2E4.\n const fullWidth = renderFullWidthRow\n ? renderFullWidthRow(item, index)\n : null;\n if (fullWidth !== null && fullWidth !== undefined) {\n return (\n <TableCell\n colSpan={columns.length}\n data-vdt-pad=\"\"\n sx={[\n { padding: notion ? \"0 14px\" : \"8px 16px\" },\n ...(Array.isArray(fullWidthRowSx)\n ? fullWidthRowSx\n : fullWidthRowSx\n ? [fullWidthRowSx]\n : []),\n ]}\n >\n {fullWidth}\n </TableCell>\n );\n }\n\n // \uC624\uB978\uCABD\uC73C\uB85C \uD569\uCE5C \uCE78(colSpan)\uC5D0 \uB36E\uC778 \uC5F4 \uC218 \u2014 \uADF8\uB9CC\uD07C \uB2E4\uC74C \uC5F4\uB4E4\uC758 \uCE78\uC744 \uADF8\uB9AC\uC9C0 \uC54A\uB294\uB2E4.\n let coveredByColSpan = 0;\n const cells = columns.map((column, columnIndex) => {\n if (coveredByColSpan > 0) {\n coveredByColSpan -= 1;\n return null;\n }\n const colSpan = column.colSpan\n ? Math.max(1, Math.min(column.colSpan(item, index), columns.length - columnIndex))\n : 1;\n coveredByColSpan = colSpan - 1;\n const cellStart = perfDebugEnabled ? performance.now() : 0;\n const cellValue = column.render\n ? column.render(item, index)\n : String((item as any)[column.id] || \"\");\n\n if (perfDebugEnabled) {\n const cellDuration = performance.now() - cellStart;\n perfStatsRef.current.cellRenderCalls += 1;\n perfStatsRef.current.cellRenderMs += cellDuration;\n perfStatsRef.current.cellRenderMaxMs = Math.max(\n perfStatsRef.current.cellRenderMaxMs,\n cellDuration,\n );\n }\n\n const pinned = pinnedLeft.has(String(column.id));\n const customPadding = column.cellPadding !== undefined;\n // \uC544\uB798\uB85C \uD569\uCE5C \uCE78\uC5D0 \uB36E\uC778 \uC904\uC740 \uCE78\uC744 \uADF8\uB9AC\uC9C0 \uC54A\uB294\uB2E4.\n const span = column.rowSpan ? column.rowSpan(item, index) : 1;\n if (span <= 0) return null;\n const onCellClick = column.onCellClick;\n return (\n <TableCell\n key={String(column.id)}\n align={column.align || \"left\"}\n rowSpan={span > 1 ? span : undefined}\n colSpan={colSpan > 1 ? colSpan : undefined}\n data-vdt-pad={customPadding ? \"\" : undefined}\n data-vdt-pinned={pinned ? \"\" : undefined}\n data-vdt-cell-click={onCellClick ? \"\" : undefined}\n onClick={\n onCellClick\n ? (e: React.MouseEvent) => {\n // \uB04C\uC5B4\uC11C \uBBFC \uB4A4\uC758 \uD074\uB9AD\uC740 \uCE78 \uB204\uB984\uC73C\uB85C \uCE58\uC9C0 \uC54A\uB294\uB2E4(\uC904 \uD074\uB9AD\uACFC \uAC19\uC740 \uAE30\uC900).\n const dx = e.clientX - mouseDownPositionRef.current.x;\n const dy = e.clientY - mouseDownPositionRef.current.y;\n e.stopPropagation();\n if (Math.sqrt(dx * dx + dy * dy) > ROW_CLICK_DRAG_THRESHOLD_PX) return;\n onCellClick(item, index, e);\n }\n : undefined\n }\n style={{\n // \uD569\uCE5C \uCE78\uC740 \uD3ED\uC744 \uBC15\uC9C0 \uC54A\uB294\uB2E4 \u2014 \uC5F4 \uD3ED\uC740 \uBA38\uB9AC \uC904\uC774 \uC815\uD558\uACE0, \uBC15\uC73C\uBA74 \uD569\uCE5C \uD3ED\uC774 \uD55C \uC5F4 \uD3ED\uC73C\uB85C \uC904\uC5B4\uB4E0\uB2E4.\n ...(colSpan > 1 ? {} : { width: column.width, minWidth: column.width ?? column.minWidth }),\n ...(column.primary ? { fontSize: 15 } : {}),\n ...column.style,\n ...(column.cellStyle ? column.cellStyle(item, index) : {}),\n padding: customPadding ? column.cellPadding : \"8px 16px\",\n ...pinnedStyle(column, false),\n }}\n >\n {cellValue}\n </TableCell>\n );\n });\n\n if (perfDebugEnabled) {\n perfStatsRef.current.rowContentCalls += 1;\n const rowDuration = performance.now() - rowStart;\n perfStatsRef.current.rowContentMs += rowDuration;\n perfStatsRef.current.rowContentMaxMs = Math.max(\n perfStatsRef.current.rowContentMaxMs,\n rowDuration,\n );\n }\n\n return <>{cells}</>;\n },\n [columns, perfDebugEnabled, renderFullWidthRow, fullWidthRowSx, notion, pinnedLeft, pinnedStyle],\n );\n\n /**\n * \uBA38\uB9AC \uB0B4\uC6A9 = \uBA38\uB9AC \uC904 + (\uC788\uC73C\uBA74) \uACE0\uC815 \uC904 \uC601\uC5ED. \uACE0\uC815 \uC904\uC740 \uBA38\uB9AC(thead)\uC640 \uD568\uAED8 \uC704\uC5D0 \uBD99\uC5B4 \uBCF8\uBB38 \uC2A4\uD06C\uB864\uACFC \uBB34\uAD00\uD558\uAC8C \uBCF4\uC778\uB2E4.\n * \uBA38\uB9AC \uC548\uC5D0 \uBCF8\uBB38 \uCE78\uC744 \uADF8\uB9AC\uB824\uBA74 \uD55C \uCE78(colSpan \uC804\uCCB4) \uC548\uC5D0 \uAC19\uC740 \uC5F4 \uAD6C\uC131\uC758 \uD45C\uB97C \uD558\uB098 \uB354 \uB454\uB2E4 \u2014 \uC5F4 \uD3ED\uC740 colgroup \uC73C\uB85C \uBC14\uAE65 \uD45C\uC640 \uB9DE\uCD94\uACE0\n * (\uCCAB \uC904\uC774 \uBB36\uC74C \uB760 \uC904\uC774\uBA74 \uADF8 \uC904\uB85C\uB294 \uC5F4 \uD3ED\uC744 \uBABB \uC815\uD55C\uB2E4), \uAC00\uB85C\uB85C \uBC00\uBA74 \uBC14\uAE65 \uD45C\uC640 \uD568\uAED8 \uC6C0\uC9C1\uC778\uB2E4.\n * \uC548\uCABD tbody \uB97C MUI TableBody \uB85C \uAC10\uC2F8\uC57C \uCE78\uC774 \uBA38\uB9AC \uCE78(th)\uC774 \uC544\uB2C8\uB77C \uBCF8\uBB38 \uCE78(td)\uC73C\uB85C \uADF8\uB824\uC9C4\uB2E4.\n */\n const fixedHeaderContent = useCallback(() => {\n const headerRows = headerRowsContent();\n if (!pinnedRows || pinnedRows.length === 0) return headerRows;\n const RowComponent = rowComponentRef.current;\n return (\n <>\n {headerRows}\n <tr data-vdt-pinned-area=\"\">\n <td colSpan={columns.length} style={{ padding: 0, border: 0 }}>\n <Box\n data-vdt-inner-scroll=\"\"\n sx={[\n {\n maxHeight: pinnedRowsMaxHeight,\n overflowY: pinnedRowsMaxHeight ? \"auto\" : \"visible\",\n overflowX: \"hidden\",\n scrollbarWidth: \"thin\",\n borderBottom: `1px solid ${notion ? notionTokens.borderStrong : \"rgba(224, 224, 224, 1)\"}`,\n // \uC601\uC5ED \uC544\uB7AB\uC120\uC774 \uACBD\uACC4\uB97C \uB9E1\uB294\uB2E4 \u2014 \uB9C8\uC9C0\uB9C9 \uC904 \uC544\uB798\uC120\uAE4C\uC9C0 \uADF8\uC73C\uBA74 \uC774\uC911\uC120\uC774\uB2E4.\n \"& tbody tr:last-of-type > td\": { borderBottom: \"none\" },\n },\n ...(Array.isArray(pinnedRowsSx) ? pinnedRowsSx : pinnedRowsSx ? [pinnedRowsSx] : []),\n ]}\n >\n <table\n style={{\n width: \"100%\",\n tableLayout,\n borderCollapse: \"separate\",\n borderSpacing: 0,\n }}\n >\n <colgroup>\n {columns.map((col) => (\n <col key={String(col.id)} style={{ width: col.width, minWidth: col.width ?? col.minWidth }} />\n ))}\n </colgroup>\n <MuiTableBody>\n {pinnedRows.map((item, index) =>\n RowComponent ? (\n <RowComponent\n key={getRowId ? String(getRowId(item, index)) : `p${index}`}\n item={item}\n data-index={index}\n data-vdt-pinned-row=\"\"\n >\n {rowContent(index, item)}\n </RowComponent>\n ) : null,\n )}\n </MuiTableBody>\n </table>\n </Box>\n </td>\n </tr>\n </>\n );\n }, [headerRowsContent, pinnedRows, pinnedRowsMaxHeight, pinnedRowsSx, columns, rowContent, tableLayout, getRowId, notion, notionTokens]);\n\n // \uCEEC\uB7FC\uC5D0 footer \uB80C\uB354\uB7EC\uAC00 \uD558\uB098\uB77C\uB3C4 \uC788\uAC70\uB098 showFooter \uAC00 \uBA85\uC2DC\uB418\uBA74 \uD558\uB2E8 \uD569\uACC4 \uD589\uC744 \uD45C\uC2DC\uD55C\uB2E4.\n const hasFooter =\n showFooter ?? columns.some((col) => typeof col.footer === \"function\");\n\n /**\n * \uD14C\uC774\uBE14 \uD558\uB2E8 \uACE0\uC815 \uD569\uACC4 \uD589(tfoot) \uCEE8\uD150\uCE20 \uC815\uC758\n * \uAC01 \uCEEC\uB7FC\uC758 footer(data) \uACB0\uACFC\uB97C \uC140\uB85C \uB80C\uB354\uB9C1\uD55C\uB2E4. (footer \uC5C6\uB294 \uCEEC\uB7FC\uC740 \uBE48 \uC140)\n * tableLayout: fixed \uB77C \uD5E4\uB354/\uBC14\uB514\uC640 \uB3D9\uC77C\uD55C \uCEEC\uB7FC \uB108\uBE44\uB85C \uC790\uB3D9 \uC815\uB82C\uB41C\uB2E4.\n */\n const fixedFooterContent = useCallback(() => {\n if (!hasFooter) {\n return null;\n }\n\n // footerColSpan \uC73C\uB85C \uC140\uC744 \uBCD1\uD569\uD55C\uB2E4. \uC55E \uCEEC\uB7FC\uC774 colSpan \uC73C\uB85C \uB36E\uC740 \uCEEC\uB7FC\uC740 \uC140\uC744 \uC0DD\uB7B5\uD55C\uB2E4.\n const cells: React.ReactNode[] = [];\n for (let i = 0; i < columns.length; i += 1) {\n const col = columns[i];\n const colSpan =\n col.footerColSpan && col.footerColSpan > 1\n ? Math.min(col.footerColSpan, columns.length - i)\n : 1;\n\n cells.push(\n <TableCell\n key={String(col.id)}\n align={col.align || \"left\"}\n colSpan={colSpan > 1 ? colSpan : undefined}\n style={{\n // \uBCD1\uD569 \uC2DC \uB108\uBE44 \uACE0\uC815\uC744 \uD480\uC5B4 colSpan \uC774 \uC2E4\uC81C\uB85C \uB298\uC5B4\uB098\uAC8C \uD55C\uB2E4.\n ...(colSpan > 1\n ? {}\n : { width: col.width, minWidth: col.width }),\n ...col.style,\n fontWeight: \"bold\",\n // \uB178\uC158\uD48D\uC740 \uBCF8\uBB38 \uCE78\uACFC \uAC19\uC740 \uC88C\uC6B0 \uC5EC\uBC31 \u00B7 \uC138\uB85C 0(\uC904 \uB192\uC774\uB85C \uAC00\uC6B4\uB370) \u2014 16px \uC774\uBA74 \uD569\uACC4 \uC904\uB9CC \uB192\uACE0 \uAE00\uC790\uAC00 \uCE78\uACFC \uC5B4\uAE0B\uB0AC\uB2E4.\n padding: notion ? \"0 14px\" : \"16px\",\n }}\n >\n {col.footer ? col.footer(data) : null}\n </TableCell>,\n );\n\n // colSpan \uC73C\uB85C \uB36E\uC778 \uB4A4 \uCEEC\uB7FC\uC740 \uAC74\uB108\uB6F4\uB2E4.\n i += colSpan - 1;\n }\n\n return <MuiTableRow>{cells}</MuiTableRow>;\n }, [hasFooter, columns, data, notion]);\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,\n ...(tableMinWidth ? { minWidth: tableMinWidth } : {}),\n // \uD2C0 \uC5C6\uC774 \uADF8\uB9B4 \uB54C\uB294 \uC624\uB978\uCABD \uB367\uC5EC\uBC31\uC774 \uAC00\uB85C \uB118\uCE68(\uAC00\uB85C \uB9C9\uB300)\uC744 \uB9CC\uB4E0\uB2E4 \u2014 \uD45C\uAC00 \uC0C1\uC790 \uD3ED\uC5D0 \uAF2D \uB9DE\uAC8C \uB454\uB2E4.\n marginRight: framed ? \"16px\" : 0,\n // \uD558\uB2E8 \uD569\uACC4 \uD589\uC774 \uC788\uC73C\uBA74 \uB370\uC774\uD130\uAC00 \uC801\uC5B4\uB3C4 \uD14C\uC774\uBE14\uC774 \uCEE8\uD14C\uC774\uB108\uB97C \uCC44\uC6B0\uAC8C \uD55C\uB2E4.\n // (\uC2E4\uC81C \uBC14\uB2E5 \uC815\uB82C\uC740 tbody \uAC00 \uB298\uC5B4\uB098\uBA70 \uCC98\uB9AC \u2014 \uD589 \uB192\uC774\uB294 \uADF8\uB300\uB85C \uC720\uC9C0)\n ...(hasFooter ? { height: \"100%\" } : {}),\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 // \uBC14\uB85C \uC544\uB798 \uC904(\uBA38\uB9AC \uC904)\uB9CC \u2014 \uBA38\uB9AC \uC548 \uACE0\uC815 \uC904 \uC601\uC5ED(pinnedRows)\uC758 \uC904\uAE4C\uC9C0 \uBA38\uB9AC \uB192\uC774 \u00B7 \uAD75\uAE30\uB97C \uBC1B\uC73C\uBA74 \uC548 \uB41C\uB2E4.\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 {\n item,\n selected: _selected,\n \"aria-selected\": _ariaSelected,\n className,\n ...rest\n } = 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 const rowId =\n item && getRowIdRef.current\n ? getRowIdRef.current(item, rowIndex)\n : rowIndex;\n // CSS \uD558\uC774\uB77C\uC774\uD2B8 \uBAA8\uB4DC\uC5D0\uC11C\uB294 \uD589 \uC790\uCCB4\uC5D0\uC11C \uC120\uD0DD\uC744 \uACC4\uC0B0\uD558\uC9C0 \uC54A\uB294\uB2E4(\uCEE8\uD14C\uC774\uB108 CSS \uAC00 \uCC98\uB9AC).\n // \u2192 selectedRowId \uBCC0\uACBD\uC774 \uD589 \uC7AC\uB80C\uB354\uB85C \uC774\uC5B4\uC9C0\uC9C0 \uC54A\uB294\uB2E4.\n const isSelected =\n !useCssRowHighlight &&\n selectedRowId !== null &&\n selectedRowId !== undefined &&\n rowId === selectedRowId;\n const resolvedSelectedRowSx =\n isSelected && selectedRowSx\n ? typeof selectedRowSx === \"function\"\n ? selectedRowSx(item, rowIndex)\n : selectedRowSx\n : undefined;\n const sanitizedClassName = String(className ?? \"\")\n .split(/\\s+/)\n .filter(\n (token) =>\n token !== \"Mui-selected\" &&\n token !== \"Mui-focusVisible\",\n )\n .join(\" \");\n\n return (\n <MuiTableRow\n {...rest}\n data-row-id={rowId !== null && rowId !== undefined ? String(rowId) : undefined}\n className={sanitizedClassName || undefined}\n selected={isSelected}\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 onContextMenu={(e: React.MouseEvent) => {\n if (item && onRowContextMenuRef.current) {\n onRowContextMenuRef.current(item, rowIndex, e);\n }\n }}\n onClick={(e: React.MouseEvent) => {\n // mousedown \uC2DC\uC791 \uC704\uCE58\uC640 click \uC704\uCE58 \uCC28\uC774\uB85C \uB4DC\uB798\uADF8 \uC5EC\uBD80 \uD310\uBCC4\n const dx =\n e.clientX - mouseDownPositionRef.current.x;\n const dy =\n e.clientY - mouseDownPositionRef.current.y;\n const wasDrag =\n Math.sqrt(dx * dx + dy * dy) >\n ROW_CLICK_DRAG_THRESHOLD_PX ||\n isScrollDraggingRef.current;\n if (wasDrag) {\n e.preventDefault();\n e.stopPropagation();\n isScrollDraggingRef.current = false;\n return;\n }\n if (item && onRowClickRef.current) {\n onRowClickRef.current(item, rowIndex);\n }\n isScrollDraggingRef.current = false;\n }}\n sx={[\n {\n userSelect: \"none\",\n // \uD589 \uB192\uC774\uB97C estimatedItemHeight(=rowHeight + divider) \uB85C \uC815\uD655\uD788\n // \uACE0\uC815\uD55C\uB2E4. react-virtuoso \uB294 fixedItemHeight \uB97C \uC918\uB3C4\n // ResizeObserver \uB85C \uC2E4\uC81C \uD589 \uB192\uC774\uB97C \uC7AC\uCE21\uC815\uD574 \uBC18\uC601\uD558\uB294\uB370, \uC140\n // \uD3F0\uD2B8/\uB77C\uC778\uC758 \uC11C\uBE0C\uD53D\uC140 \uB54C\uBB38\uC5D0 \uCE21\uC815\uAC12\uC774 \uC815\uC218\uC5D0\uC11C \uC5B4\uAE0B\uB098\uBA74\n // \uD558\uB2E8 filler row \uB192\uC774(offsetBottom)\uAC00 \uC2A4\uD06C\uB864\uB9C8\uB2E4 \uC18C\uC218\uC810\uC73C\uB85C\n // \uD754\uB4E4\uB9AC\uACE0, \uADF8 \uC704\uC5D0 sticky \uB85C \uBD99\uC740 <tfoot> \uD569\uACC4\uD589\uC774 1px \uB5A8\uB9B0\uB2E4.\n // height/maxHeight \uB97C \uC815\uC218\uB85C \uBC15\uACE0 overflow:hidden \uC73C\uB85C \uB9C9\uC544\n // \uCE21\uC815\uAC12\uC774 \uD56D\uC0C1 estimatedItemHeight \uAC00 \uB418\uAC8C \uD55C\uB2E4.\n // \uC904 \uB192\uC774 \"auto\" \uB294 \uB0B4\uC6A9\uB9CC\uD07C \uB298\uC5B4\uB09C\uB2E4 \u2014 \uCE78 \uB192\uC774(rowHeight)\uAC00 \uCD5C\uC18C \uB192\uC774\uB85C \uB3D9\uC791\uD55C\uB2E4.\n ...(autoRowHeight\n ? { \"& > td\": { height: estimatedItemHeight } }\n : {\n height: estimatedItemHeight,\n maxHeight: estimatedItemHeight,\n }),\n boxSizing: \"border-box\",\n backgroundColor:\n isOddRow && stripedRowColor\n ? stripedRowColor\n : \"transparent\",\n // \uC5EC\uBC31\uC744 \uB530\uB85C \uBC1B\uC740 \uCE78(cellPadding \u00B7 \uD55C \uCE78 \uC904)\uC740 \uAE30\uBCF8 \uC5EC\uBC31\uC5D0\uC11C \uBE80\uB2E4.\n \"& td:not([data-vdt-pad])\": {\n padding: \"8px 16px\",\n },\n \"& td\": {\n boxSizing: \"border-box\",\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\":\n hasRowClick && !isSelected\n ? {\n backgroundColor: (theme) => {\n const isDark =\n theme.palette.mode ===\n \"dark\";\n const defaultColor =\n \"#000000\";\n const color =\n rowHoverColor ??\n defaultColor;\n const opacity =\n rowHoverOpacity ?? 0.06;\n\n if (!rowHoverColor) {\n return isDark\n ? `rgba(255, 255, 255, ${opacity})`\n : `rgba(0, 0, 0, ${opacity})`;\n }\n\n const hex = color\n .replace(\"#\", \"\")\n .trim();\n if (hex.length !== 6) {\n return color;\n }\n\n const r = parseInt(\n hex.substring(0, 2),\n 16,\n );\n const g = parseInt(\n hex.substring(2, 4),\n 16,\n );\n const b = parseInt(\n hex.substring(4, 6),\n 16,\n );\n\n return `rgba(${r}, ${g}, ${b}, ${opacity})`;\n },\n }\n : undefined,\n cursor: hasRowClick ? \"pointer\" : undefined,\n },\n resolvedSelectedRowSx,\n ]}\n />\n );\n },\n // \uD14C\uC774\uBE14 \uBC14\uB514 \u2014 \uD558\uB2E8 \uD569\uACC4 \uD589\uC774 \uC788\uC73C\uBA74 row-group \uC744 \uB298\uB824 \uBE48 \uACF5\uAC04\uC774 \uB9C8\uC9C0\uB9C9 \uD589 '\uC544\uB798'\uB85C \uAC00\uAC8C \uD55C\uB2E4.\n // (\uAC1C\uBCC4 \uD589 \uB192\uC774\uB294 \uADF8\uB300\uB85C \uC720\uC9C0\uB418\uACE0, tfoot \uC740 \uADF8 \uC544\uB798 \uBC14\uB2E5\uC5D0 \uBD99\uB294\uB2E4)\n TableBody: forwardRef<HTMLTableSectionElement>((props, ref) => {\n const { children, ...rest } =\n props as React.HTMLAttributes<HTMLTableSectionElement>;\n return (\n <MuiTableBody\n {...rest}\n ref={ref}\n sx={hasFooter ? { height: \"100%\" } : undefined}\n >\n {children}\n {/* fill \uBAA8\uB4DC(hasFooter)\uC5D0\uC11C table/tbody \uC758 height:100% \uB54C\uBB38\uC5D0 \uB0A8\uB294 \uB192\uC774\uAC00\n \uB370\uC774\uD130 <tr> \uC5D0 \uBD84\uBC30\uB418\uC5B4 \uD589\uC774 rowHeight \uBCF4\uB2E4 \uCEE4\uC9C0\uB294 \uBB38\uC81C\uB97C \uB9C9\uB294 spacer.\n \uC720\uC5F0\uD55C \uBE48 \uD589\uC774 \uB0A8\uB294 \uACF5\uAC04\uC744 \uD761\uC218 \u2192 \uB370\uC774\uD130 \uD589\uC740 rowHeight \uB85C \uACE0\uC815\uB418\uACE0,\n sticky footer \uB294 \uADF8 \uC544\uB798 \uBC14\uB2E5\uC5D0 \uBD99\uB294\uB2E4. \uC2A4\uD06C\uB864\uC774 \uC0DD\uAE30\uBA74 0 \uC73C\uB85C \uC811\uD78C\uB2E4. */}\n {hasFooter && (\n <tr aria-hidden style={{ height: \"100%\" }}>\n <td\n colSpan={columns.length}\n style={{ padding: 0, border: 0 }}\n />\n </tr>\n )}\n </MuiTableBody>\n );\n }),\n // \uD14C\uC774\uBE14 \uD558\uB2E8 \uD569\uACC4 \uD589(tfoot) \u2014 \uBC14\uB2E5\uC5D0 \uACE0\uC815\n TableFoot: forwardRef<HTMLTableSectionElement, any>(\n (props, ref) => (\n <MuiTableFooter\n {...props}\n ref={ref}\n sx={[\n {\n // \uB5A8\uB9BC\uC758 \uADFC\uBCF8 \uC6D0\uC778(\uB370\uC774\uD130 \uD589 \uCE21\uC815 \uB192\uC774\uC758 \uC11C\uBE0C\uD53D\uC140)\uC740 TableRow\n // \uC5D0\uC11C height/maxHeight \uC815\uC218 \uACE0\uC815\uC73C\uB85C \uC7A1\uB294\uB2E4. \uC5EC\uAE30\uC11C\uB294 \uD569\uACC4\uD589\n // \uC140 \uC2A4\uD0C0\uC77C\uB9CC \uB454\uB2E4(virtuoso \uAC00 <tfoot> \uC5D0 \uC9C1\uC811 sticky \uB97C \uAC74\uB2E4).\n // \uD569\uACC4\uD589 \uB192\uC774\uB97C footerHeight(\uBBF8\uC9C0\uC815 \uC2DC rowHeight) \uB85C \uC815\uD655\uD788\n // \uACE0\uC815\uD55C\uB2E4. \uADF8\uB798\uC57C \uB85C\uB529 \uC624\uBC84\uB808\uC774\uC758 \uD558\uB2E8 \uCEF7\uC624\uD504(bottom:\n // footerHeight ?? rowHeight)\uC640 \uC2E4\uC81C footer \uB192\uC774\uAC00 \uC77C\uCE58\uD574\n // \uC624\uBC84\uB808\uC774\uAC00 footer \uC704\uAE4C\uC9C0\uB9CC \uB0B4\uB824\uC624\uACE0 footer \uB97C \uB36E\uC9C0 \uC54A\uB294\uB2E4.\n \"& tr\": {\n height: footerHeight ?? rowHeight,\n maxHeight: footerHeight ?? rowHeight,\n boxSizing: \"border-box\",\n },\n \"& td\": {\n height: footerHeight ?? rowHeight,\n boxSizing: \"border-box\",\n backgroundColor: (theme) =>\n theme.palette.mode === \"dark\"\n ? \"#1e1e1e\"\n : \"#ffffff\",\n // \uC138\uB85C padding \uC744 0 \uC73C\uB85C \uB450\uACE0 \uD589 \uB192\uC774\uB85C \uC815\uB82C\uC744 \uB9E1\uAE34\uB2E4.\n // (\uAC00\uB85C 16px \uC720\uC9C0) \u2014 16px \uC138\uB85C padding \uC774\uBA74 \uC2E4\uC81C footer \uAC00\n // footerHeight \uBCF4\uB2E4 \uCEE4\uC838 \uC624\uBC84\uB808\uC774 \uCEF7\uC624\uD504\uC640 \uC5B4\uAE0B\uB09C\uB2E4.\n padding: \"0 16px\",\n color: \"inherit\",\n fontSize: \"0.875rem\",\n // \uAD6C\uBD84\uC120\uC740 \uC2E4\uC81C border \uB300\uC2E0 inset box-shadow \uB85C \uADF8\uB9B0\uB2E4.\n // collapsed-border \uD53D\uC140 \uACBD\uACC4 \uACF5\uC720\uB85C \uC778\uD55C \uAE5C\uBE61\uC784\uC744 \uD53C\uD55C\uB2E4.\n border: \"none\",\n // \uB178\uC158\uD48D\uC740 \uBA38\uB9AC \uC544\uB798 \uC120\uACFC \uAC19\uC740 \uC9C4\uD55C \uD68C\uC0C9 \uC120 \u2014 \uAC80\uC740 \uC120\uC740 \uC605\uC740 \uD45C\uC5D0\uC11C \uD63C\uC790 \uD280\uC5C8\uB2E4.\n boxShadow: `inset 0 1px 0 0 ${notion ? notionTokens.borderStrong : \"#000000\"}`,\n },\n },\n ...(Array.isArray(footerSx)\n ? footerSx\n : footerSx\n ? [footerSx]\n : []),\n ]}\n />\n ),\n ),\n }),\n [\n // onRowClick/getRowId \uB294 ref \uB85C \uCC98\uB9AC\uD558\uBBC0\uB85C deps \uC5D0\uC11C \uC81C\uC678(\uC778\uB77C\uC778 \uCF5C\uBC31\uC774\uC5B4\uB3C4 \uD589 \uB9AC\uB9C8\uC6B4\uD2B8 \uC548 \uB428).\n hasRowClick,\n // CSS \uD558\uC774\uB77C\uC774\uD2B8 \uBAA8\uB4DC\uC5D0\uC11C\uB294 selectedRowId \uAC00 components \uB97C \uC7AC\uC0DD\uC131\uD558\uC9C0 \uC54A\uAC8C \uD55C\uB2E4(\uD589 \uC7AC\uB80C\uB354 \uBC29\uC9C0).\n // \uD568\uC218\uD615 selectedRowSx(per-row) \uC77C \uB54C\uB9CC selectedRowId \uBCC0\uACBD\uC73C\uB85C components \uB97C \uAC31\uC2E0\uD55C\uB2E4.\n useCssRowHighlight ? null : selectedRowId,\n selectedRowSx,\n rowHeight,\n stripedRowColor,\n rowDivider,\n columnHeight,\n rowHoverColor,\n rowHoverOpacity,\n VirtuosoScroller,\n footerHeight,\n footerSx,\n hasFooter,\n notion,\n notionTokens,\n // spacer \uD589\uC758 colSpan \uACC4\uC0B0\uC5D0 \uC0AC\uC6A9 (\uCEEC\uB7FC \uAD6C\uC870 \uBCC0\uACBD \uC2DC components \uC7AC\uC0DD\uC131)\n columns,\n tableLayout,\n framed,\n autoRowHeight,\n tableMinWidth,\n ],\n );\n rowComponentRef.current = (VirtuosoTableComponents as Record<string, unknown>).TableRow as React.ComponentType<any>;\n\n const resolvedVirtuosoComponents = VirtuosoTableComponents;\n // autoHeight \uB294 \uAC19\uC740 \uD45C \uBD80\uD488(\uBA38\uB9AC \u00B7 \uC904 \u00B7 \uD569\uACC4)\uC744 \uAC00\uC0C1\uD654 \uC5C6\uC774 \uADF8\uB300\uB85C \uC4F4\uB2E4 \u2014 \uCE78 \uBAA8\uC591\uC774 \uAC00\uC0C1 \uD45C\uC640 \uAC19\uB2E4.\n const autoParts = VirtuosoTableComponents as Record<string, unknown>;\n const AutoTable = autoParts.Table as React.ComponentType<any>;\n const AutoTableHead = autoParts.TableHead as React.ComponentType<any>;\n const AutoTableBody = autoParts.TableBody as React.ComponentType<any>;\n const AutoTableRow = autoParts.TableRow as React.ComponentType<any>;\n const AutoTableFoot = autoParts.TableFoot as React.ComponentType<any>;\n\n // \uBA38\uB9AC \uC6B0\uD074\uB9AD \uBA54\uB274 \u2014 \uC5F4\uC740 \uB9E4 \uB80C\uB354 columns \uC5D0\uC11C \uB2E4\uC2DC \uCC3E\uB294\uB2E4(\uACE0\uB978 \uAC12 \u00B7 \uC815\uB82C \uD45C\uC2DC\uAC00 \uBC14\uB85C \uB530\uB77C\uC624\uAC8C). \uC5F4\uC774 \uC0AC\uB77C\uC84C\uC73C\uBA74 \uADF8\uB9AC\uC9C0 \uC54A\uB294\uB2E4.\n const menuColumn = headerMenu ? columns.find((col) => String(col.id) === headerMenu.colId) : undefined;\n const closeHeaderMenu = () => setHeaderMenu(null);\n let headerMenuNode: React.ReactNode = null;\n if (headerMenu && menuColumn) {\n const colId = String(menuColumn.id);\n const canSort = Boolean(menuColumn.sortable && onSort);\n const canFilter = hasColumnFilter(menuColumn);\n const activeSort = sortBy === colId ? sortDirection : undefined;\n const picked = menuColumn.filterValues ?? [];\n const multiple = menuColumn.filterMultiple !== false;\n // 14px \uD56D\uBAA9 \u2014 \uC571\uC758 \uBA38\uB9AC \uBA54\uB274(HeadSortFilter)\uC640 \uAC19\uC740 \uD06C\uAE30 \u00B7 \uC544\uC774\uCF58 18px.\n const itemSx = { gap: 1, fontSize: 14, minHeight: 36 };\n // \uC815\uB82C\uC740 \uD55C \uBC88 \uACE0\uB974\uBA74 \uB05D\uC774\uB77C \uB2EB\uB294\uB2E4. \uAC19\uC740 \uBC29\uD5A5\uC744 \uB2E4\uC2DC \uACE0\uB974\uBA74 \uD480\uAE30(onSortClear \uAC00 \uC788\uC744 \uB54C).\n const pickSort = (direction: SortDirection) => {\n closeHeaderMenu();\n if (activeSort === direction) {\n onSortClear?.();\n return;\n }\n onSort?.(colId, direction);\n };\n // \uC5EC\uB7EC \uAC12 \uACE0\uB974\uAE30\uB294 \uC5F0\uB2EC\uC544 \uACE0\uB974\uBBC0\uB85C \uC5F4\uC5B4 \uB454\uB2E4. \uD558\uB098\uB9CC \uACE0\uB974\uB294 \uC5F4\uC740 \uACE0\uB974\uBA74 \uB2EB\uB294\uB2E4.\n const toggleValue = (value: string) => {\n const on = picked.includes(value);\n if (multiple) {\n menuColumn.onFilterChange?.(on ? picked.filter((item) => item !== value) : [...picked, value]);\n return;\n }\n closeHeaderMenu();\n menuColumn.onFilterChange?.(on ? [] : [value]);\n };\n const items: React.ReactNode[] = [];\n if (canSort) {\n items.push(\n <MenuItem key=\"asc\" selected={activeSort === \"asc\"} onClick={() => pickSort(\"asc\")} sx={itemSx}>\n <PathIcon d={ICON_PATHS.asc} color=\"text.secondary\" />\n \uC624\uB984\uCC28\uC21C \uC815\uB82C\n </MenuItem>,\n <MenuItem key=\"desc\" selected={activeSort === \"desc\"} onClick={() => pickSort(\"desc\")} sx={itemSx}>\n <PathIcon d={ICON_PATHS.desc} color=\"text.secondary\" />\n \uB0B4\uB9BC\uCC28\uC21C \uC815\uB82C\n </MenuItem>,\n );\n if (activeSort && onSortClear) {\n items.push(\n <MenuItem\n key=\"sort-clear\"\n onClick={() => {\n closeHeaderMenu();\n onSortClear();\n }}\n sx={{ ...itemSx, color: \"text.secondary\" }}\n >\n \uC815\uB82C \uD480\uAE30\n </MenuItem>,\n );\n }\n }\n if (canSort && canFilter) items.push(<Divider key=\"div-sort\" />);\n if (canFilter) {\n (menuColumn.filterOptions ?? []).forEach((option) => {\n const on = picked.includes(option.value);\n items.push(\n <MenuItem key={`f:${option.value}`} selected={!multiple && on} onClick={() => toggleValue(option.value)} sx={itemSx}>\n {multiple ? (\n <PathIcon d={on ? ICON_PATHS.checked : ICON_PATHS.unchecked} color={on ? \"primary.main\" : \"text.disabled\"} />\n ) : (\n // \uD558\uB098\uB9CC \uACE0\uB974\uB294 \uC5F4 \u2014 \uACE0\uB978 \uAC12\uC5D0\uB9CC \uCCB4\uD06C, \uB098\uBA38\uC9C0\uB294 \uAC19\uC740 \uD3ED\uC744 \uBE44\uC6CC \uAE00\uC790 \uC904\uC744 \uB9DE\uCD98\uB2E4.\n <Box component=\"span\" sx={{ display: \"inline-flex\", width: 18, flexShrink: 0, color: \"primary.main\" }}>\n {on ? <PathIcon d={ICON_PATHS.check} /> : null}\n </Box>\n )}\n {option.label}\n </MenuItem>,\n );\n });\n // \uAC78\uB824 \uC788\uC744 \uB54C\uB9CC \u2014 \uD558\uB098\uC529 \uB044\uC9C0 \uC54A\uACE0 \uD55C \uBC88\uC5D0 \uD47C\uB2E4.\n if (picked.length > 0) {\n items.push(\n <Divider key=\"div-filter\" />,\n <MenuItem\n key=\"filter-clear\"\n onClick={() => {\n closeHeaderMenu();\n menuColumn.onFilterChange?.([]);\n }}\n sx={{ ...itemSx, color: \"text.secondary\" }}\n >\n \uAC70\uB974\uAE30 \uD480\uAE30\n </MenuItem>,\n );\n }\n }\n headerMenuNode = (\n // \uB204\uB978 \uC790\uB9AC\uC5D0\uC11C \uBC14\uB85C \uB72C\uB2E4 \u2014 \uD3BC\uCE68 \uC560\uB2C8\uBA54\uC774\uC158\uC740 \uBA54\uB274\uAC00 \uB2A6\uAC8C \uB530\uB77C\uC624\uB294 \uAC83\uCC98\uB7FC \uBCF4\uC778\uB2E4(\uC6B0\uD074\uB9AD \uBA54\uB274 \uACF5\uD1B5 \uADDC\uCE59).\n <Menu\n open\n anchorReference=\"anchorPosition\"\n anchorPosition={{ left: headerMenu.x, top: headerMenu.y }}\n onClose={closeHeaderMenu}\n transitionDuration={0}\n // \uBA54\uB274 \uC704\uC5D0\uC11C \uB2E4\uC2DC \uC6B0\uD074\uB9AD\uD574\uB3C4 \uBE0C\uB77C\uC6B0\uC800 \uBA54\uB274\uAC00 \uB728\uC9C0 \uC54A\uAC8C.\n onContextMenu={(event) => event.preventDefault()}\n slotProps={{ paper: { sx: { maxHeight: 420, minWidth: 180 } } }}\n >\n {items}\n </Menu>\n );\n }\n\n // \uACF5\uD1B5 \uD14C\uC774\uBE14 \uB0B4\uC6A9\n const tableContent = (\n <Box\n sx={\n {\n position: \"relative\",\n height: autoHeight ? \"auto\" : \"100%\",\n width: \"100%\",\n \"& .MuiTableHead-root\": {\n backgroundColor: (theme: Theme) =>\n notion\n ? `${notionTokens.bg} !important`\n : theme.palette.mode === \"dark\"\n ? \"#1e1e1e !important\"\n : \"#ffffff !important\",\n },\n // \uC120\uD0DD \uD589 CSS \uD558\uC774\uB77C\uC774\uD2B8 (selectedRowId \uBCC0\uACBD \uC2DC \uC774 \uCEE8\uD14C\uC774\uB108\uB9CC \uAC31\uC2E0, \uD589 \uC7AC\uB80C\uB354 \uC5C6\uC74C).\n ...(selectedRowCssSx ?? {}),\n // \uACE0\uC815 \uC5F4 \uCE78\uC740 \uB4A4\uB85C \uC9C0\uB098\uAC00\uB294 \uCE78\uC744 \uAC00\uB824\uC57C \uD574 \uBC14\uD0D5\uC744 \uCE60\uD55C\uB2E4. \uC904 \uD638\uBC84 \uC0C9\uC740 \uC904(tr)\uC5D0 \uCE60\uD574\uC9C0\uBBC0\uB85C \uACE0\uC815 \uCE78\uC5D0\uB3C4 \uAC19\uC740 \uC0C9\uC744 \uC900\uB2E4.\n \"& tbody td[data-vdt-pinned]\": {\n backgroundColor: notion\n ? notionTokens.bg\n : muiTheme.palette.background.paper,\n },\n // \uCE78 \uB2E8\uC704\uB85C \uB204\uB974\uB294 \uCE78 \u2014 \uCE78\uC5D0\uB9CC \uD638\uBC84 \uBC14\uD0D5.\n \"& tbody td[data-vdt-cell-click]\": { cursor: \"pointer\" },\n \"& tbody td[data-vdt-cell-click]:hover\": {\n backgroundColor: notion\n ? notionTokens.hoverBg\n : muiTheme.palette.mode === \"dark\"\n ? \"rgba(255, 255, 255, 0.06)\"\n : \"rgba(0, 0, 0, 0.04)\",\n },\n ...(notion && hasRowClick\n ? {\n \"& tbody tr:hover td[data-vdt-pinned]\": {\n backgroundColor: notionTokens.hoverBg,\n },\n }\n : {}),\n // \uB178\uC158\uD48D \u2014 \uBA38\uB9AC\u00B7\uCE78\uC758 \uC778\uB77C\uC778 style(padding\u00B7fontWeight)\uC744 \uB36E\uC5B4\uC57C \uD574\uC11C !important \uB2E4.\n // \uC140\uB809\uD130\uB97C \uCEE8\uD14C\uC774\uB108\uC5D0\uC11C \uB0B4\uB9AC\uB294 \uAC83\uC740 \uD589 \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uAC74\uB4DC\uB9AC\uC9C0 \uC54A\uAE30 \uC704\uD574\uC11C\uB2E4(\uD589 \uC7AC\uB80C\uB354 \uBE44\uC6A9).\n ...(notion\n ? {\n // \uBC14\uAE65 \uD14C\uB450\uB9AC \u2014 \uC5C5\uBB34\uD568 \uD45C(border 1px + radius 4px)\uC640 \uAC19\uB2E4. \uAC00\uC0C1\uD654\uB77C \uB0B4\uC6A9 \uB192\uC774\uC5D0 \uB9DE\uCDB0 \uC904\uC774\uC9C0 \uBABB\uD558\uACE0\n // \uC885\uC774 \uC548\uCABD \uC5EC\uBC31 \uC548\uC5D0\uC11C \uC138\uB85C\uB97C \uAF49 \uCC44\uC6B4\uB2E4. \uBA38\uB9AC\uC758 \uC717\uC120\u00B7\uC88C\uC6B0\uC120\uC740 \uC774 \uD14C\uB450\uB9AC\uAC00 \uB300\uC2E0\uD55C\uB2E4.\n ...(framed\n ? {\n border: `1px solid ${notionTokens.borderStrong}`,\n borderRadius: \"4px\",\n }\n : {\n // \uD2C0 \uC5C6\uC774 \u2014 \uBC14\uAE65 \uC0C1\uC790 \uBC14\uD0D5\uC774 \uBE44\uCE58\uC9C0 \uC54A\uAC8C \uD45C\uB97C \uC885\uC774 \uC0C9\uC73C\uB85C \uCE60\uD55C\uB2E4.\n \"& table\": { backgroundColor: notionTokens.bg },\n }),\n overflow: \"hidden\",\n \"& thead tr th\": {\n height: columnHeight,\n boxSizing: \"border-box\",\n padding: \"0 14px !important\",\n fontSize: 13,\n fontWeight: \"500 !important\",\n color: notionTokens.headerColor,\n backgroundColor: `${notionTokens.bg} !important`,\n // \uD2C0 \uC5C6\uB294 \uD45C\uB97C \uB3C4\uAD6C \uC904\uACFC \uD55C \uC0C1\uC790\uC5D0 \uB123\uC73C\uBA74 \uBA38\uB9AC \uC704 \uACBD\uACC4\uAC00 \uC5C6\uB2E4 \u2014 \uADF8\uB54C\uB9CC \uC717\uC120(headerTopBorder).\n borderTop: !framed && headerTopBorder ? `1px solid ${notionTokens.borderStrong}` : \"none\",\n borderBottom: `1px solid ${notionTokens.borderStrong}`,\n // \uCE78 \uC0AC\uC774 \uC138\uB85C\uC120 \u2014 \uB9C8\uC9C0\uB9C9 \uCE78 \uB4A4\uC5D0\uB294 \uAE0B\uC9C0 \uC54A\uB294\uB2E4(\uBC14\uAE65 \uD14C\uB450\uB9AC\uC640 \uACB9\uCCD0 \uB450 \uC904\uB85C \uBCF4\uC778\uB2E4).\n borderRight: `1px solid ${notionTokens.border}`,\n \"&:last-of-type\": { borderRight: \"none\" },\n },\n \"& tbody tr td:not([data-vdt-pad])\": {\n padding: \"0 14px !important\",\n },\n \"& tbody tr td\": {\n fontSize: 14,\n borderBottom: `1px solid ${notionTokens.border}`,\n },\n // \uB9C8\uC9C0\uB9C9 \uC904 \uC544\uB798\uC120 \u2014 \uD2C0 \uBC14\uB2E5(\uB610\uB294 \uD569\uACC4 \uC904\uC758 \uC717\uC120)\uACFC \uB9DE\uB2FF\uC73C\uBA74 \uAE0B\uC9C0 \uC54A\uB294\uB2E4. \uB450 \uC120\uC774 \uACB9\uCCD0 \uAD75\uC740 \uC774\uC911\uC120\uC73C\uB85C \uBCF4\uC600\uB2E4(2026-10-17).\n // \uB9DE\uB2FF\uB294 \uACBD\uC6B0: \uB0B4\uC6A9 \uB192\uC774\uB9CC\uD07C \uC11C\uB294 \uD45C(autoHeight), \uC904\uC774 \uC601\uC5ED\uBCF4\uB2E4 \uAE38\uC5B4 \uB05D\uAE4C\uC9C0 \uB0B4\uB9AC\uBA74 \uBC14\uB2E5\uC5D0 \uB2FF\uB294 \uD45C, \uD569\uACC4 \uC904\uC774 \uC788\uB294 \uD45C.\n // \uC904\uC774 \uC801\uC5B4 \uC544\uB798\uAC00 \uBE44\uB294 \uD45C\uB294 \uADF8\uB300\uB85C \uAE0B\uB294\uB2E4 \u2014 \uC904\uC774 \uC5B4\uB514\uC11C \uB05D\uB098\uB294\uC9C0 \uBCF4\uC5EC\uC57C \uD55C\uB2E4.\n ...(data.length > 0 && (autoHeight || listOverflows || hasFooter)\n ? { [`& tbody tr[data-index=\"${data.length - 1}\"]:not([data-vdt-pinned-row]) td`]: { borderBottom: \"none\" } }\n : {}),\n }\n : {}),\n } as SxProps<Theme>\n }\n >\n {/* \uD14C\uC774\uBE14 \u2014 autoHeight \uBA74 \uAC00\uC0C1\uD654 \uC5C6\uC774 \uBAA8\uB4E0 \uC904\uC744 \uADF8\uB9AC\uACE0 \uB192\uC774\uB294 \uB0B4\uC6A9\uC744 \uB530\uB978\uB2E4(\uD398\uC774\uC9C0\uAC00 \uAD74\uB9B0\uB2E4). */}\n {autoHeight ? (\n <Box sx={{ overflowX: \"auto\", width: \"100%\" }}>\n <AutoTable>\n <AutoTableHead>{fixedHeaderContent()}</AutoTableHead>\n <AutoTableBody>\n {data.map((item, index) => (\n <AutoTableRow\n key={getRowId ? String(getRowId(item, index)) : index}\n item={item}\n data-index={index}\n >\n {rowContent(index, item)}\n </AutoTableRow>\n ))}\n </AutoTableBody>\n {hasFooter ? <AutoTableFoot>{fixedFooterContent()}</AutoTableFoot> : null}\n </AutoTable>\n </Box>\n ) : (\n <TableVirtuoso\n key={tableKey}\n ref={virtuosoRef}\n data={data}\n totalCount={onLoadMore ? data.length + 1 : data.length}\n defaultItemHeight={estimatedItemHeight}\n fixedItemHeight={autoRowHeight ? undefined : estimatedItemHeight}\n fixedHeaderContent={fixedHeaderContent}\n fixedFooterContent={hasFooter ? fixedFooterContent : undefined}\n itemContent={rowContent}\n // \uD0A4 \uD568\uC218\uB294 \uC4F8 \uB54C\uB9CC \uB118\uAE34\uB2E4 \u2014 computeItemKey={undefined} \uB97C \uADF8\uB300\uB85C \uB118\uAE30\uBA74 react-virtuoso \uC758 \uAE30\uBCF8 \uD0A4 \uD568\uC218\uAC00 undefined \uB85C \uB36E\uC5EC\n // \"n is not a function\" \uC73C\uB85C \uD45C \uC804\uCCB4\uAC00 \uADF8\uB824\uC9C0\uC9C0 \uC54A\uC558\uB2E4(1.3.0, 2026-10-18).\n {...(rowKeyFromId && getRowId\n ? { computeItemKey: (index: number, item: T) => (item ? getRowId(item, index) : `vdt-${index}`) }\n : {})}\n endReached={handleEndReached}\n scrollerRef={(el) => {\n scrollerElRef.current = el instanceof HTMLElement ? el : null;\n checkListOverflow();\n }}\n totalListHeightChanged={checkListOverflow}\n style={{ height: \"100%\" }}\n increaseViewportBy={{\n top: viewportBufferTop,\n bottom: viewportBufferBottom,\n }}\n overscan={virtuosoOverscan}\n followOutput={false}\n components={resolvedVirtuosoComponents}\n />\n )}\n\n {/* \uBE48 \uB370\uC774\uD130 \uD45C\uC2DC \u2014 \uB178\uC158\uD48D\uC740 \uBA38\uB9AC \uC544\uB798\uC5D0 \uC605\uC740 \uAE00 \uD55C \uC904(\uC5C5\uBB34\uD568 \uBAA9\uB85D \uD45C\uC758 \uBE48 \uBAA9\uB85D\uACFC \uAC19\uC740 \uBAA8\uC591). */}\n {data.length === 0 && !loading && !hasPinnedRows && notion && typeof emptyMessage === \"string\" && (\n <Box\n sx={{\n position: autoHeight ? \"static\" : \"absolute\",\n top: columnHeight,\n left: 0,\n right: 0,\n py: 6,\n textAlign: \"center\",\n fontSize: 14,\n color: notionTokens.emptyColor,\n }}\n >\n {emptyMessage}\n </Box>\n )}\n {data.length === 0 && !loading && !hasPinnedRows && !(notion && typeof emptyMessage === \"string\") && (\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 {headerMenuNode}\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 indicator={<CssSpinner />}\n sx={{\n top: `${\n columns.some((col) => col.group)\n ? columnHeight * 2\n : columnHeight\n }px`,\n // \uD478\uD130(\uD569\uACC4 \uD589)\uAC00 \uC788\uC73C\uBA74 \uADF8 \uB192\uC774\uB9CC\uD07C \uC544\uB798\uB97C \uC798\uB77C, \uD5E4\uB354~\uD478\uD130 \uC0AC\uC774 \uB0B4\uC6A9 \uC601\uC5ED \uC911\uC559\uC5D0 \uC2A4\uD53C\uB108\uB97C \uB454\uB2E4.\n bottom: `${hasFooter ? footerHeight ?? rowHeight : 0}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 // \uB178\uC158\uD48D\uC740 \uC0AC\uBC29 \uC5EC\uBC31 \u2014 \uC5C5\uBB34\uD568\uCC98\uB7FC \uD45C\uAC00 \uC885\uC774 \uAC00\uC7A5\uC790\uB9AC\uC5D0 \uBD99\uC9C0 \uC54A\uB294\uB2E4(\uC88C\uC6B0 paddingX, \uC0C1\uD558 NOTION_PADDING_Y).\n const notionFramePadding = notion && framed\n ? { paddingRight: paddingX, paddingTop: NOTION_PADDING_Y, paddingBottom: NOTION_PADDING_Y }\n : {};\n\n return showPaper ? (\n <Paper\n className=\"grow\"\n elevation={1}\n sx={{\n padding: 0,\n paddingLeft: paddingX,\n ...notionFramePadding,\n boxSizing: \"border-box\",\n height: autoHeight ? \"auto\" : \"100%\",\n minHeight: 0,\n flex: autoHeight ? \"none\" : 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 ...notionFramePadding,\n boxSizing: \"border-box\",\n height: autoHeight ? \"auto\" : \"100%\",\n minHeight: 0,\n flex: autoHeight ? \"none\" : 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 * \uC21C\uC218 CSS \uB85C\uB529 \uC2A4\uD53C\uB108. MUI CircularProgress \uB300\uC2E0 LoadingProgress \uC758 indicator \uB85C \uC8FC\uC785\uD55C\uB2E4.\n *\n * \uC2A4\uD0C0\uC77C\uC740 \uC790\uCCB4 <style> \uD074\uB798\uC2A4\uB85C \uC8FC\uC785\uD55C\uB2E4(\uC678\uBD80 \uC2A4\uD0C0\uC77C \uC758\uC874 \uC5C6\uC74C). \uBC30\uACBD \uB9C1(\uC5F0\uD55C \uD2B8\uB799)\uACFC\n * \uD68C\uC804 \uD638(\uC0C1\uB2E8 \uC0C9)\uB97C \uD55C \uD074\uB798\uC2A4\uC5D0 \uB2F4\uB294\uB2E4. \uC571 \uCD08\uAE30 \uC2A4\uD53C\uB108 \uBC0F \uB300\uC2DC\uBCF4\uB4DC \uB808\uC774\uC544\uC6C3 \uC2A4\uD53C\uB108\uC640 \uB3D9\uC77C\uD55C \uBAA8\uC591.\n */\nexport interface CssSpinnerProps {\n /** \uC2A4\uD53C\uB108 \uC9C0\uB984(px). \uAE30\uBCF8 54 */\n size?: number;\n}\n\nconst SPINNER_CSS = `\n.vdt-css-spinner{box-sizing:border-box;border-radius:50%;border:4px solid rgba(28,64,125,0.14);border-top-color:#1c407d;animation:vdt-css-spinner-spin .75s linear infinite}\n@keyframes vdt-css-spinner-spin{to{transform:rotate(360deg)}}\n`;\n\nexport function CssSpinner({ size = 54 }: CssSpinnerProps) {\n return (\n <>\n <style>{SPINNER_CSS}</style>\n <span\n className=\"vdt-css-spinner\"\n role=\"progressbar\"\n aria-label=\"loading\"\n style={{ display: \"inline-block\", width: size, height: size }}\n />\n </>\n );\n}\n\nexport default CssSpinner;\n"],
5
- "mappings": "AA0BA,OACI,cAAAA,GACA,eAAAC,EACA,WAAAC,EACA,UAAAC,EACA,aAAAC,EACA,QAAAC,GACA,YAAAC,OACG,QACP,OACI,OAAAC,EACA,SAAAC,GACA,aAAaC,GACb,aAAAC,EACA,kBAAAC,GACA,aAAAC,GACA,eAAeC,GACf,YAAYC,GACZ,kBAAAC,GACA,QAAAC,GACA,YAAAC,GACA,WAAAC,GACA,WAAAC,GACA,SAAAC,GACA,cAAAC,GACA,YAAAC,OAGG,gBACP,OAAS,iBAAAC,OAAqB,qLCxBvB,IAAIC,GAAW,UAAW,CAC7B,OAAAA,GAAW,OAAO,QAAU,SAAkBC,EAAG,CAC7C,QAAS,EAAGC,EAAI,EAAGC,EAAI,UAAU,OAAQD,EAAIC,EAAGD,IAAK,CACjD,EAAI,UAAUA,CAAC,EACf,QAASE,KAAK,EAAO,OAAO,UAAU,eAAe,KAAK,EAAGA,CAAC,IAAGH,EAAEG,CAAC,EAAI,EAAEA,CAAC,EAC/E,CACA,OAAOH,CACX,EACOD,GAAS,MAAM,KAAM,SAAS,CACzC,ECMc,SAAUK,GAAgBC,EAejB,CAdnB,IAAAC,EAAOD,EAAA,QACPE,EAAUF,EAAA,WACVG,EAAAH,EAAA,gBAAAI,EAAeD,IAAA,OAAG,IAAGA,EACrBE,EAAAL,EAAA,UAAAM,GAASD,IAAA,OAAG,EAACA,EACbE,GAAAP,EAAA,KAAAQ,GAAID,KAAA,OAAG,GAAEA,GACTE,EAAST,EAAA,UACTU,GAAKV,EAAA,MACLW,EAAEX,EAAA,GACFY,EAASZ,EAAA,UACTa,GAAAb,EAAA,WAAAc,EAAUD,KAAA,OAAG,CACT,KAAM,GACN,MAAO,gBACP,QAAS,IACZA,GAEKE,EAAiBC,GAA4B,MAAS,EACtDC,EAASD,GAAuB,IAAI,EACpCE,GAAkCC,GAASlB,CAAO,EAAjDmB,GAAYF,GAAA,CAAA,EAAEG,GAAeH,GAAA,CAAA,EAIhCI,GAGAR,EAAU,KAHJS,GAAcD,KAAA,OAAG,GAAIA,GAC3BE,GAEAV,EAAU,MAFHW,EAAeD,KAAA,OAAG,gBAAeA,GACxCE,EACAZ,EAAU,QADDa,GAAiBD,IAAA,OAAG,GAAGA,EA6BpC,GA1BAE,GAAU,UAAA,CACN,IAAMC,GAAcd,EAAe,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,EAAS,CAClC,MAAWL,IAAY,KAEnBoB,GAAgB,EAAI,EAChBJ,EAAO,UACPA,EAAO,QAAQ,MAAM,QAAU,MAKvCF,EAAe,QAAUd,CAC7B,EAAG,CAACA,EAASC,EAAYE,EAAiBE,EAAS,CAAC,EAEhD,CAACc,GACD,OAAO,KAIX,IAAMW,EAAkB,UAAA,CAEpB,OAAI,OAAOnB,GAAc,SAEjBoB,GAAAA,MAAAA,CACI,IAAKpB,EACL,IAAI,UACJ,MAAO,CAAE,MAAOJ,GAAM,OAAQA,EAAI,CAAE,CAAA,EAK5CI,GAIGoB,GAACC,GAAgB,CAAC,KAAMzB,EAAI,CAAA,CACvC,EAGM0B,EAAqB,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,EAAK,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,EAAkB,CAAE,EACpBvB,CAAE,EAAA,SAGRoB,EAAe,CAAE,CAAA,CAG9B,CC5KQ,mBAAAM,GACI,OAAAC,GADJ,QAAAC,OAAA,oBAPR,IAAMC,GAAc;AAAA;AAAA;AAAA,EAKb,SAASC,GAAW,CAAE,KAAAC,EAAO,EAAG,EAAoB,CACvD,OACIH,GAAAF,GAAA,CACI,UAAAC,GAAC,SAAO,SAAAE,GAAY,EACpBF,GAAC,QACG,UAAU,kBACV,KAAK,cACL,aAAW,UACX,MAAO,CAAE,QAAS,eAAgB,MAAOI,EAAM,OAAQA,CAAK,EAChE,GACJ,CAER,CHgCA,OAAOC,OAAsB,4BAsDjB,OA+jCA,YAAAC,GA/jCA,OAAAC,EA2kBI,QAAAC,MA3kBJ,oBAlDZ,IAAMC,GAAiC,CACnC,UAAW,UACX,OAAQ,EACR,OAAQ,CACZ,EACMC,GAA8B,EAS9BC,GAAe,CACjB,GAAI,UACJ,OAAQ,UACR,aAAc,UACd,YAAa,UACb,QAAS,UACT,WAAY,UACZ,WAAY,UACZ,YAAa,SACjB,EAEMC,GAAmB,OACnBC,GAAc,CAChB,GAAI,UACJ,OAAQ,UACR,aAAc,UACd,YAAa,UACb,QAAS,UACT,WAAY,UACZ,WAAY,2BACZ,YAAa,SACjB,EAGMC,GAAa,CACf,IAAK,8DACL,KAAM,iEACN,QAAS,sIACT,UAAW,6FACX,MAAO,oDACP,OAAQ,gDACZ,EAEA,SAASC,GAAS,CAAE,EAAAC,EAAG,KAAAC,EAAO,GAAI,MAAAC,CAAM,EAAiD,CACrF,OACIX,EAACY,GAAA,CAAQ,GAAI,CAAE,SAAUF,EAAM,WAAY,EAAG,MAAAC,CAAM,EAChD,SAAAX,EAAC,QAAK,EAAGS,EAAG,EAChB,CAER,CAGA,SAASI,GAAmBC,EAA6B,CACrD,MAAO,GAAQA,EAAI,eAAiBA,EAAI,eAC5C,CAEA,SAASC,GAA6B,CAClC,KAAAC,EACA,QAAAC,EAAU,GACV,QAAAC,EACA,WAAAC,EACA,SAAAC,EACA,cAAAC,EACA,cAAeC,GACf,UAAWC,GACX,aAAcC,GACd,QAAAC,EACA,WAAAC,GAAa,GACb,OAAAC,EACA,YAAAC,EACA,oBAAAC,GACA,WAAAC,EACA,OAAAC,EACA,cAAAC,EACA,UAAAC,GAAY,GACZ,SAAUC,GACV,WAAAC,GAAa,EACb,cAAAC,GAAgB,EAChB,cAAeC,GACf,gBAAiBC,GACjB,eAAAC,EACA,SAAAC,EACA,WAAAC,GACA,aAAAC,EAAe,UACf,WAAAC,EAAa,GACb,iBAAAC,GACA,WAAAC,GACA,aAAAC,GACA,SAAAC,GACA,QAAAC,GAAU,UACV,OAAAC,EAAS,GACT,gBAAAC,GAAkB,GAClB,cAAAC,GAAgB,QAChB,YAAAC,GAAc,QACd,mBAAAC,GACA,eAAAC,GACA,iBAAAC,GACA,WAAAC,GACA,oBAAAC,GACA,aAAAC,GACA,wBAAAC,GAA0B,GAC1B,aAAAC,GAAe,GACf,aAAAC,GACA,UAAAC,EACJ,EAA6B,CAEzB,IAAMC,EAASf,KAAY,SACrBgB,GAAWC,GAAS,EAEpBC,GAAgBJ,IAAaE,GAAS,QAAQ,QAAU,OAAS1D,GAAcF,GAC/E+D,IAAiBX,IAAY,QAAU,GAAK,EAC5CY,EAAe5C,KAAqBuC,EAAS,GAAK,IAElDM,EAAY9C,KAAkBwC,EAAS,GAAK,IAE5CO,GAAWrB,EAAUf,KAAiB6B,EAAS,OAAS,QAAW,EACnEQ,GAAgBpB,KAAkB,OAElCqB,GAAgBnC,KAAsB0B,EAASG,EAAa,QAAU,QACtEO,GAAkBnC,KAAwByB,EAAS,EAAI,QACvDW,GAA2B,KAAK,IAAIL,EAAY,GAAI,GAAG,EACvDM,GAA8B,KAAK,IAAIN,EAAY,GAAI,GAAG,EAC1DO,GACF,OAAOrC,GAAmB,SACpBA,EACCA,GAAgB,KAAOmC,GAC5BG,GACF,OAAOtC,GAAmB,SACpBA,EACCA,GAAgB,QAAUoC,GAC/BG,GAAsB,KAAK,IAAIT,EAAY,EAAG,GAAG,EACjDU,GAAyB,KAAK,IAAIV,EAAY,GAAI,GAAG,EACrDW,GACF,OAAOxC,GAAa,SACdA,EACA,CACI,KAAMA,GAAU,MAAQsC,GACxB,QAAStC,GAAU,SAAWuC,EAClC,EACJE,GAAsBZ,GAAa3C,GAAa,EAAI,GAQpDwD,GAAmBC,EACrB,IACIpB,EACM,CACI,gBAAiBG,EAAa,WAC9B,uBAAwB,CAAE,UAAW,iBAAiBA,EAAa,WAAW,EAAG,EACjF,0BAA2B,CAAE,gBAAiBA,EAAa,UAAW,CAC1E,EACA,OACV,CAACH,EAAQG,CAAY,CACzB,EACMkB,EAAgB9D,IAAqB4D,GACrCG,GAAqB,CAACD,GAAiB,OAAOA,GAAkB,WAChEE,GAAmBH,EAAwC,IAEzD,CAACE,IACDhE,IAAkB,MAClBA,IAAkB,QAClB,CAAC+D,EAEM,KAGJ,CACH,CAAC,2BAFW,OAAO/D,CAAa,EAAE,QAAQ,SAAU,MAAM,CAEvB,IAAI,EAAG+D,CAC9C,EACD,CAACC,GAAoBhE,EAAe+D,CAAa,CAAC,EAE/CG,GACF,OAAO,OAAW,MACjB,OAAO,SAAS,WAAa,aAC1B,OAAO,SAAS,WAAa,aAE/B,CAACC,CAAgB,EAAIC,GAAS,IAC5B,OAAO,OAAW,IACX,GAEJ,OAAO,aAAa,QAAQ,gBAAgB,IAAM,GAC5D,EACKC,EAAeC,EAAO,CACxB,YAAa,EACb,aAAc,EACd,eAAgB,EAChB,gBAAiB,EACjB,WAAY,EACZ,kBAAmB,EACnB,eAAgB,EAChB,gBAAiB,EACjB,aAAc,EACd,gBAAiB,EACjB,gBAAiB,EACjB,aAAc,EACd,gBAAiB,CACrB,CAAC,EAGKC,GAAiBC,EAClBC,GAAmB,CAChB,GAAI,CAACN,EACD,OAEJ,IAAMO,EAAQL,EAAa,QAM3B,GAAI,EAJAK,EAAM,YAAc,GACpBA,EAAM,kBAAoB,GAC1BA,EAAM,gBAAkB,GACxBA,EAAM,gBAAkB,GAExB,OAGJ,IAAMC,EACFD,EAAM,gBAAkB,EAClBA,EAAM,aAAeA,EAAM,gBAC3B,EACJE,EACFF,EAAM,gBAAkB,EAClBA,EAAM,aAAeA,EAAM,gBAC3B,EAEV,QAAQ,IAAI,aAAc,CACtB,OAAAD,EACA,MAAO,CACH,OAAQC,EAAM,YACd,QAAS,KAAK,MAAMA,EAAM,YAAY,EACtC,UAAW,OAAOA,EAAM,eAAe,QAAQ,CAAC,CAAC,EACjD,WAAYA,EAAM,gBAClB,MAAO,OAAOA,EAAM,WAAW,QAAQ,CAAC,CAAC,CAC7C,EACA,aAAc,CACV,MAAOA,EAAM,kBACb,QAAS,OAAOA,EAAM,eAAe,QAAQ,CAAC,CAAC,CACnD,EACA,WAAY,CACR,MAAOA,EAAM,gBACb,QAAS,OAAOA,EAAM,aAAa,QAAQ,CAAC,CAAC,EAC7C,MAAO,OAAOC,EAAS,QAAQ,CAAC,CAAC,EACjC,MAAO,OAAOD,EAAM,gBAAgB,QAAQ,CAAC,CAAC,CAClD,EACA,WAAY,CACR,MAAOA,EAAM,gBACb,QAAS,OAAOA,EAAM,aAAa,QAAQ,CAAC,CAAC,EAC7C,MAAO,OAAOE,EAAU,QAAQ,CAAC,CAAC,EAClC,MAAO,OAAOF,EAAM,gBAAgB,QAAQ,CAAC,CAAC,CAClD,CACJ,CAAC,EAEDL,EAAa,QAAU,CACnB,YAAa,EACb,aAAc,EACd,eAAgB,EAChB,gBAAiB,EACjB,WAAY,EACZ,kBAAmB,EACnB,eAAgB,EAChB,gBAAiB,EACjB,aAAc,EACd,gBAAiB,EACjB,gBAAiB,EACjB,aAAc,EACd,gBAAiB,CACrB,CACJ,EACA,CAACF,CAAgB,CACrB,EAEAU,EAAU,IAAM,CACZ,GAAI,CAACV,GAAoB,OAAO,OAAW,IACvC,OAGJ,QAAQ,IAAI,oDAAoD,EAEhE,IAAMW,EAAa,OAAO,YAAY,IAAM,CACxCP,GAAe,UAAU,CAC7B,EAAG,IAAI,EAEP,MAAO,IAAM,CACT,OAAO,cAAcO,CAAU,EAC/BP,GAAe,SAAS,CAC5B,CACJ,EAAG,CAACA,GAAgBJ,CAAgB,CAAC,EAGrC,IAAMY,GAAmBjB,EACrB,IACIkB,GAAgC,CAACC,EAAOC,IAAQ,CAC5C,IAAMC,EAAqBb,EAA2B,IAAI,EACpDc,EAAgBd,EAAO,CAAC,EACxBe,EAAcf,EAAsB,IAAI,EAG9C,OAAAO,EAAU,IAAM,CACZ,IAAMS,EAAKH,EAAmB,QAC9B,GAAI,CAACG,EAAI,OAGT,IAAMC,EAAeC,GAAkB,CACnC,IAAMC,EAAatB,EACb,YAAY,IAAI,EAChB,EAGN,GAAIqB,EAAE,UAAY,KAAK,IAAIA,EAAE,MAAM,EAAI,KAAK,IAAIA,EAAE,MAAM,EACpD,OAIJ,IAAME,EAASF,EAAE,QAA+B,UAAU,yBAAyB,EACnF,GAAIE,GAASJ,EAAG,SAASI,CAAK,IAEtBF,EAAE,OAAS,EACLE,EAAM,UAAY,EAClBA,EAAM,UAAYA,EAAM,aAAeA,EAAM,aAAe,GACvD,OAEnBF,EAAE,eAAe,EACjB,IAAIG,EAAQH,EAAE,OAEVA,EAAE,YAAc,EAChBG,GAAS,GACFH,EAAE,YAAc,IACvBG,GAASL,EAAG,cAGZnB,IACAE,EAAa,QAAQ,aAAe,EACpCA,EAAa,QAAQ,cAAgBsB,GAGzCP,EAAc,SAAWO,EACrBN,EAAY,UAAY,OAI5BA,EAAY,QAAU,sBAAsB,IAAM,CAC9C,IAAMO,EAAWzB,EACX,YAAY,IAAI,EAChB,EACA0B,EAAU,KAAK,IACjBP,EAAG,aAAe,GAClB,GACJ,EACMQ,EAAe,KAAK,IACtB,CAACD,EACD,KAAK,IAAIA,EAAST,EAAc,OAAO,CAC3C,EACAA,EAAc,QAAU,EACxBC,EAAY,QAAU,KAClBS,IAAiB,IACjBR,EAAG,WAAaQ,GAEhB3B,IACAE,EAAa,QAAQ,iBAAmB,EACxCA,EAAa,QAAQ,YACjB,YAAY,IAAI,EAAIuB,EAEhC,CAAC,EAEGzB,IACAE,EAAa,QAAQ,gBACjB,YAAY,IAAI,EAAIoB,GAEhC,EAEA,OAAAH,EAAG,iBAAiB,QAASC,EAAa,CACtC,QAAS,EACb,CAAC,EACM,IAAM,CACTD,EAAG,oBAAoB,QAASC,CAAW,EACvCF,EAAY,UAAY,OACxB,qBAAqBA,EAAY,OAAO,EACxCA,EAAY,QAAU,MAE1BD,EAAc,QAAU,CAC5B,CACJ,EAAG,CAAC,CAAC,EAGDzG,EAACF,GAAA,CACG,kBAAmB,GACnB,MAAOI,GACN,GAAGuC,GAEJ,SAAAzC,EAACoH,GAAA,CACG,UAAWC,EACV,GAAGf,EACJ,IAAMgB,GAAS,CACXd,EAAmB,QACfc,EACA,OAAOf,GAAQ,WACfA,EAAIe,CAAsB,EACnBf,IACPA,EAAI,QAAUe,EAEtB,EACA,GAAI,CACA,WAAY,OACZ,iBAAkB,OAClB,SAAU,WACV,MAAO,OACP,OAAQ,OACR,SAAU,OACV,QAAS,OACT,cAAe,SACf,eAAgB,OAChB,gBAAiB,OAEjB,UAAW,gBACX,mBAAoB,SACpB,WAAY,kBACZ,uBAAwB,CACpB,QAAS,MACb,EACA,mBAAoB,CAEhB,aAAcvD,EAAS,EAAIO,GAC3B,WAAYnC,GACZ,cAAeC,EACnB,CACJ,EACJ,EACJ,CAER,CAAC,EAEL,CAAC,CACL,EAGMmF,GAAkBpC,EAAQ,IAAM,CAClC,GAAI1D,IAAY,GACZ,MAAO,UACJ,GAAI,OAAOA,GAAY,SAC1B,OAAOA,CAGf,EAAG,CAACA,CAAO,CAAC,EAGN,CAAC+F,GAAiBC,EAAkB,EAAIhC,GAASxE,CAAO,EAGxD,CAACyG,GAAUC,EAAW,EAAIlC,GAAS,CAAC,EAG1CS,EAAU,IAAM,CACRjF,GAEAwG,GAAmB,EAAI,CAI/B,EAAG,CAACxG,CAAO,CAAC,EAGZ,IAAM2G,GAAwB/B,EAAY,IAAM,CAC5C4B,GAAmB,EAAK,CAC5B,EAAG,CAAC,CAAC,EAGCI,GAAoBL,GAGpBM,GAAoB7G,GAAWD,EAAK,OAAS,EAG7C+G,GAAmBpC,EAAO,EAAK,EAI/BqC,GAAwBrC,EAAe,EAAE,EACzCsC,GAActC,EAAY,IAAI,EAE9BuC,GAAgBvC,EAA2B,IAAI,EAC/C,CAACwC,GAAeC,EAAgB,EAAI3C,GAAS,EAAK,EAClD4C,GAAoBxC,EAAY,IAAM,CACxC,IAAMc,EAAKuB,GAAc,QACrBvB,GAAIyB,GAAiBzB,EAAG,aAAeA,EAAG,aAAe,CAAC,CAClE,EAAG,CAAC,CAAC,EACLT,EAAU,IAAM,CACZ,IAAMS,EAAKuB,GAAc,QACzB,GAAI,CAACvB,GAAM,OAAO,eAAmB,IAAa,OAClD,IAAM2B,EAAW,IAAI,eAAe,IAAMD,GAAkB,CAAC,EAC7D,OAAAC,EAAS,QAAQ3B,CAAE,EACZ,IAAM2B,EAAS,WAAW,CACrC,EAAG,CAACD,GAAmB1F,CAAU,CAAC,EAKlC,IAAM4F,GAAgB5C,EAAOxE,CAAU,EACvCoH,GAAc,QAAUpH,EACxB,IAAMqH,GAAc7C,EAAOvE,CAAQ,EACnCoH,GAAY,QAAUpH,EACtB,IAAMqH,GAAsB9C,EAAOpC,EAAgB,EACnDkF,GAAoB,QAAUlF,GAC9B,IAAMmF,GAAkB/C,EAAO9B,EAAY,EAC3C6E,GAAgB,QAAU7E,GAE1B,IAAM8E,GAAkBhD,EAAwC,IAAI,EAG9DiD,GAAazD,EAAQ,IAAM,CAC7B,IAAM0D,EAAM,IAAI,IACZC,EAAO,EACX,OAAA5H,EAAQ,QAASJ,GAAQ,CACjBA,EAAI,SAAW,SACnB+H,EAAI,IAAI,OAAO/H,EAAI,EAAE,EAAGgI,CAAI,EAC5BA,GAAQ,OAAOhI,EAAI,OAAU,SAAWA,EAAI,MAAQ,EACxD,CAAC,EACM+H,CACX,EAAG,CAAC3H,CAAO,CAAC,EAEN6H,GAAgB5D,EAAQ,IAAM,CAChC,GAAKjE,EAAQ,KAAMJ,GAAQ,OAAOA,EAAI,UAAa,QAAQ,EAC3D,OAAOI,EAAQ,OACX,CAAC8H,EAAKlI,IACFkI,GAAO,OAAOlI,EAAI,OAAU,SAAWA,EAAI,MAAQ,OAAOA,EAAI,UAAa,SAAWA,EAAI,SAAW,GACzG,CACJ,CACJ,EAAG,CAACI,CAAO,CAAC,EAEN+H,EAAcpD,EAChB,CAAC/E,EAAoBoI,IAAuC,CACxD,IAAMJ,EAAOF,GAAW,IAAI,OAAO9H,EAAI,EAAE,CAAC,EAC1C,OAAIgI,IAAS,OAAkB,CAAC,EACzB,CAAE,SAAU,SAAU,KAAAA,EAAM,OAAQI,EAAO,EAAI,CAAE,CAC5D,EACA,CAACN,EAAU,CACf,EAEMO,GAAc,CAAC,CAAChI,EAGhBiI,GAAsBzD,EAAO,EAAK,EAClC0D,EAAuB1D,EAAO,CAAE,EAAG,EAAG,EAAG,CAAE,CAAC,EAElDO,EAAU,IAAM,CACZ,IAAMoD,EAA2BC,GAAsB,CACnD,IAAMC,EAAKD,EAAM,QAAUF,EAAqB,QAAQ,EAClDI,EAAKF,EAAM,QAAUF,EAAqB,QAAQ,EACpD,KAAK,KAAKG,EAAKA,EAAKC,EAAKA,CAAE,EAAItJ,KAC/BiJ,GAAoB,QAAU,GAEtC,EAEA,gBAAS,iBAAiB,YAAaE,CAAuB,EACvD,IAAM,CACT,SAAS,oBAAoB,YAAaA,CAAuB,CACrE,CACJ,EAAG,CAAC,CAAC,EAGLpD,EAAU,IAAM,CAEZ,IAAMwD,EAAiB,SAAS,cAC5B,mCACJ,EACIA,GACmBA,EAAe,iBAC9B,yBACJ,EACW,QAASC,GAAU,CAE1B,IAAMC,EAAkB,IAAI,WAAW,aAAc,CACjD,QAAS,GACT,WAAY,EAChB,CAAC,EACDD,EAAM,cAAcC,CAAe,CACvC,CAAC,CAET,EAAG,CAAC7H,CAAM,CAAC,EAGX,IAAM8H,GAAahE,EACdiE,GAAqB,CAClB,GAAI,CAACnI,EAAQ,OAKbA,EAAOmI,EAFH/H,IAAW+H,GAAY9H,IAAkB,MAAQ,OAAS,KAEjC,CACjC,EACA,CAACL,EAAQI,EAAQC,CAAa,CAClC,EAMM,CAAC+H,GAAYC,EAAa,EAAIvE,GAAyD,IAAI,EAC3FwE,GAAyBtE,EAAO9D,EAAmB,EACzDoI,GAAuB,QAAUpI,GACjC,IAAMqI,GAAYvE,EAAOhE,CAAM,EAC/BuI,GAAU,QAAUvI,EAOpB,IAAMwI,GAA0BtE,EAC5B,CAAC/E,EAA2ByI,IAAkD,CAC1E,GAAI,CAACzI,EAAK,CACNyI,EAAM,eAAe,EACrB,MACJ,CACAzI,EAAI,aAAa,gBAAgByI,CAAK,EACtC,IAAIa,EAAUb,EAAM,iBAKpB,GAJKa,IAASA,EAAUH,GAAuB,UAAUnJ,EAAKyI,CAAK,IAAM,IAAQA,EAAM,kBACvFA,EAAM,eAAe,EACjBa,GAAWtJ,EAAI,aAAe,IAE9B,CADY,GAAQA,EAAI,UAAYoJ,GAAU,UAClC,CAACrJ,GAAgBC,CAAG,EAAG,OACvC,IAAMuJ,EAAOd,EAAM,cAAc,sBAAsB,EACvDS,GAAc,CAAE,MAAO,OAAOlJ,EAAI,EAAE,EAAG,EAAGyI,EAAM,QAAS,EAAGc,EAAK,MAAO,CAAC,CAC7E,EACA,CAAC,CACL,EAGMC,EAAmBzE,EACpB/E,GACSA,EAAI,cAAgBA,EAAI,aAAa,OAAS,EAEhDb,EAACoH,EAAA,CACG,UAAU,OACV,GAAI,CACA,QAAS,cACT,WAAY,SACZ,IAAK,GACL,SAAU,OACV,MAAO,eACP,WAAY,IACZ,cAAe,QACnB,EAEA,UAAArH,EAACqH,EAAA,CAAI,UAAU,OAAO,GAAI,CAAE,SAAU,SAAU,aAAc,WAAY,WAAY,QAAS,EAC1F,SAAAvG,EAAI,KACT,EACAd,EAACQ,GAAA,CAAS,EAAGD,GAAW,OAAQ,KAAM,GAAI,GAC9C,EAlB2DO,EAAI,KAqBvE,CAAC,CACL,EAGMyJ,GAAmB1E,EACpB2E,GAAqB,CAClB,IAAMC,EAAajF,EAAmB,YAAY,IAAI,EAAI,EAE1D,GADAkD,GAAgB,UAAU,EACtB,CAAC5G,EAAY,CACT0D,IACAE,EAAa,QAAQ,mBAAqB,EAC1CA,EAAa,QAAQ,gBACjB,YAAY,IAAI,EAAI+E,GAE5B,MACJ,CAEA,GAAIxJ,GAAWD,EAAK,SAAW,EAAG,CAC1BwE,IACAE,EAAa,QAAQ,mBAAqB,EAC1CA,EAAa,QAAQ,gBACjB,YAAY,IAAI,EAAI+E,GAE5B,MACJ,CAEA,IAAMC,EAAiB1J,EAAK,QAAU,GAChC2J,EAAUH,GAAYxJ,EAAK,OAAS,EAGpC4J,EACF5C,GAAsB,UAAYhH,EAAK,OAE3C,GACI2J,GACAD,GACA,CAAC3C,GAAiB,SAClB,CAAC6C,EACH,CACE7C,GAAiB,QAAU,GAC3BC,GAAsB,QAAUhH,EAAK,OACrC,IAAM6J,EAAS7J,EAAK,OAEpBc,EAAW+I,EADG,EACU,CAC5B,CAEIrF,IACAE,EAAa,QAAQ,mBAAqB,EAC1CA,EAAa,QAAQ,gBACjB,YAAY,IAAI,EAAI+E,EAEhC,EACA,CAACzJ,EAAK,OAAQC,EAASa,EAAY0D,CAAgB,CACvD,EAGAU,EAAU,IAAM,CACPjF,IACD8G,GAAiB,QAAU,GAEnC,EAAG,CAAC9G,CAAO,CAAC,EAGZiF,EAAU,IAAM,CACRlF,EAAK,SAAW,GAChB2G,GAAamD,GAASA,EAAO,CAAC,CAEtC,EAAG,CAAC9J,EAAK,MAAM,CAAC,EAEhB,IAAM+J,GAA6BpF,EAAOhC,EAAuB,EACjEoH,GAA2B,QAAUpH,GAErC,IAAMqH,GAAoBrF,EAAO3E,EAAK,MAAM,EACtCiK,GAAqBtF,EAAgB,MAAS,EAMpDO,EAAU,IAAM,CACZ,IAAMgF,EAAaF,GAAkB,QAC/BG,EAAgBnK,EAAK,OAGrBoK,EACFD,EAAgB,EACV3C,GAAY,QACRA,GAAY,QAAQxH,EAAK,CAAC,EAAG,CAAC,EAC7BA,EAAK,CAAC,EACX,OACJqK,EAAkBJ,GAAmB,QAG3C,GAAIE,EAAgBD,GAAcA,EAAa,EAAG,CAC9CF,GAAkB,QAAUG,EAC5BF,GAAmB,QAAUG,EAC7B,MACJ,CAIA,IAAME,EACFH,EAAgBD,GACfA,EAAa,GAAKE,IAAgBC,EAOnCC,IACAtD,GAAsB,QAAU,IAGhCC,GAAY,SAAWkD,EAAgB,GAAKG,GAAgBP,GAA2B,SACvF9C,GAAY,QAAQ,cAAc,CAC9B,MAAO,EACP,MAAO,QACP,SAAU,MACd,CAAC,EAGL+C,GAAkB,QAAUG,EAC5BF,GAAmB,QAAUG,CACjC,EAAG,CAACpK,CAAI,CAAC,EAMT,IAAMuK,GAAoB1F,EAAY,IAAM,CAExC,IAAM2F,EAAiD,CAAC,EAClDC,EAAkC,CAAC,EAgBzC,GAdAvK,EAAQ,QAASJ,GAAQ,CACjBA,EAAI,OACC0K,EAAS1K,EAAI,KAAK,IACnB0K,EAAS1K,EAAI,KAAK,EAAI,CAAC,GAE3B0K,EAAS1K,EAAI,KAAK,EAAE,KAAKA,CAAG,GAE5B2K,EAAe,KAAK3K,CAAG,CAE/B,CAAC,EAKG,EAFc,OAAO,KAAK0K,CAAQ,EAAE,OAAS,GAI7C,OACIxL,EAAC0L,GAAA,CACI,SAAAxK,EAAQ,IAAKJ,GACVd,EAAC2L,EAAA,CAEG,MAAO7K,EAAI,OAAS,OACnB,GAAGA,EAAI,YACR,cAAgB+F,GAA8CsD,GAAwBrJ,EAAK+F,CAAC,EAC5F,MAAO,CACH,MAAO/F,EAAI,MACX,SAAUA,EAAI,OAASA,EAAI,SAC3B,GAAGA,EAAI,MACP,WAAY,OACZ,SAAU,SACV,IAAK,EACL,OAAQ,EACR,QAAS,OACT,GAAGmI,EAAYnI,EAAK,EAAI,EACxB,GAAGA,EAAI,aAAa,KACxB,EAEC,SAAAA,EAAI,SACDd,EAAC,OACG,MAAO,CACH,QAAS,OACT,WAAY,SACZ,eACIc,EAAI,QAAU,SACR,SACAA,EAAI,QAAU,QACZ,WACA,aACZ,SAAU,WACV,MAAO,MACX,EAEA,SAAAb,EAACoH,EAAA,CACG,GAAI,CACA,SAAU,WACV,OAAQ,UACR,kCAAmC,CAC/B,QAAS,eACT,qBAAsB,CAClB,MAAO,OACP,QAAS,cACb,CACJ,CACJ,EACA,QAAS,IACLwC,GAAW,OAAO/I,EAAI,EAAE,CAAC,EAG5B,UAAAwJ,EAAiBxJ,CAAG,EACrBd,EAAC4L,GAAA,CACG,OAAQ7J,IAAWjB,EAAI,GACvB,UACIiB,IAAWjB,EAAI,GACTkB,EACA,OAEV,GAAI,CACA,SAAU,WACV,KAAM,OACN,IAAK,MACL,UAAW,mBACX,WAAY,MACZ,SAAU,OACV,MAAO,OACP,OAAQ,OACR,OAAQ,UACR,QACID,IAAWjB,EAAI,GAAK,EAAI,EAC5B,WAAY,oBACZ,4BAA6B,CACzB,SAAU,WACV,WAAY,EACZ,YAAa,EACb,QAAS,EACT,WACI,iBACR,EACA,wCACI,CACI,UACI,gBACR,EACJ,yCACI,CACI,UACI,cACR,CACR,EACJ,GACJ,EACJ,EAEAwJ,EAAiBxJ,CAAG,GA5FnB,OAAOA,EAAI,EAAE,CA8FtB,CACH,EACL,EAKR,IAAM+K,EAAgB,CAClB,GAAGJ,EAAe,IAAK3K,GACnBd,EAAC2L,EAAA,CAEG,QAAS,EACT,MAAO7K,EAAI,OAAS,OACnB,GAAGA,EAAI,YACR,cAAgB+F,GAA8CsD,GAAwBrJ,EAAK+F,CAAC,EAC5F,MAAO,CACH,MAAO/F,EAAI,MACX,SAAUA,EAAI,MACd,GAAGA,EAAI,MACP,WAAY,OACZ,SAAU,SACV,IAAK,EACL,OAAQ,EACR,QAAS,OACT,GAAGmI,EAAYnI,EAAK,EAAI,EACxB,GAAGA,EAAI,aAAa,KACxB,EAEC,SAAAA,EAAI,UAAYa,EACb3B,EAAC,OACG,MAAO,CACH,QAAS,OACT,WAAY,SACZ,eACIc,EAAI,QAAU,SACR,SACAA,EAAI,QAAU,QACZ,WACA,aACZ,SAAU,WACV,MAAO,MACX,EAEA,SAAAb,EAACoH,EAAA,CACG,GAAI,CACA,SAAU,WACV,OAAQ,UACR,kCAAmC,CAC/B,QAAS,eACT,qBAAsB,CAClB,MAAO,OACP,QAAS,cACb,CACJ,CACJ,EACA,QAAS,IAAMwC,GAAW,OAAO/I,EAAI,EAAE,CAAC,EAEvC,UAAAwJ,EAAiBxJ,CAAG,EACrBd,EAAC4L,GAAA,CACG,OAAQ7J,IAAWjB,EAAI,GACvB,UACIiB,IAAWjB,EAAI,GACTkB,EACA,OAEV,GAAI,CACA,SAAU,WACV,KAAM,OACN,IAAK,MACL,UAAW,mBACX,WAAY,MACZ,SAAU,OACV,MAAO,OACP,OAAQ,OACR,OAAQ,UACR,QAASD,IAAWjB,EAAI,GAAK,EAAI,EACjC,WAAY,oBACZ,UAAW,CACP,QAAS,eACT,qBAAsB,CAClB,MAAO,OACP,QAAS,cACb,CACJ,EACA,4BAA6B,CACzB,SAAU,WACV,WAAY,EACZ,YAAa,EACb,QAAS,EACT,WAAY,iBAChB,EACA,wCACI,CACI,UAAW,gBACf,EACJ,yCACI,CACI,UAAW,cACf,CACR,EACJ,GACJ,EACJ,EAEAwJ,EAAiBxJ,CAAG,GA9FnB,OAAOA,EAAI,EAAE,CAgGtB,CACH,EACD,GAAG,OAAO,QAAQ0K,CAAQ,EAAE,IAAI,CAAC,CAACM,EAAOC,CAAI,IACzC/L,EAAC2L,EAAA,CAEG,MAAM,SACN,QAASI,EAAK,OACd,cAAgBlF,GAA8CsD,GAAwB,KAAMtD,CAAC,EAC7F,MAAO,CACH,WAAY,OACZ,SAAU,SACV,IAAK,EACL,OAAQ,EACR,QAAS,MACb,EAEC,SAAAiF,GAZIA,CAaT,CACH,CACL,EAEME,EAAiB,CACnB,GAAG,OAAO,OAAOR,CAAQ,EACpB,KAAK,EACL,IAAK1K,GACFd,EAAC2L,EAAA,CAEG,MAAO7K,EAAI,OAAS,OACnB,GAAGA,EAAI,YACR,cAAgB+F,GAA8CsD,GAAwBrJ,EAAK+F,CAAC,EAC5F,MAAO,CACH,MAAO/F,EAAI,MACX,SAAUA,EAAI,MACd,GAAGA,EAAI,MACP,WAAY,OACZ,SAAU,SACV,IAAK,EACL,OAAQ,EACR,QAAS,OACT,GAAGmI,EAAYnI,EAAK,EAAI,EACxB,GAAGA,EAAI,aAAa,KACxB,EAEC,SAAAA,EAAI,UAAYa,EACb3B,EAAC,OACG,MAAO,CACH,QAAS,OACT,WAAY,SACZ,eACIc,EAAI,QAAU,SACR,SACAA,EAAI,QAAU,QACZ,WACA,aACZ,SAAU,WACV,MAAO,MACX,EAEA,SAAAb,EAACoH,EAAA,CACG,GAAI,CACA,SAAU,WACV,OAAQ,UACR,kCAAmC,CAC/B,QAAS,eACT,qBAAsB,CAClB,MAAO,OACP,QAAS,cACb,CACJ,CACJ,EACA,QAAS,IAAMwC,GAAW,OAAO/I,EAAI,EAAE,CAAC,EAEvC,UAAAwJ,EAAiBxJ,CAAG,EACrBd,EAAC4L,GAAA,CACG,OAAQ7J,IAAWjB,EAAI,GACvB,UACIiB,IAAWjB,EAAI,GACTkB,EACA,OAEV,GAAI,CACA,SAAU,WACV,KAAM,OACN,IAAK,MACL,UAAW,mBACX,WAAY,MACZ,SAAU,OACV,MAAO,OACP,OAAQ,OACR,OAAQ,UACR,QAASD,IAAWjB,EAAI,GAAK,EAAI,EACjC,WAAY,oBACZ,UAAW,CACP,QAAS,eACT,qBAAsB,CAClB,MAAO,OACP,QAAS,cACb,CACJ,EACA,4BAA6B,CACzB,SAAU,WACV,WAAY,EACZ,YAAa,EACb,QAAS,EACT,WAAY,iBAChB,EACA,wCACI,CACI,UAAW,cACf,EACJ,yCACI,CACI,UAAW,gBACf,CACR,EACJ,GACJ,EACJ,EAEAwJ,EAAiBxJ,CAAG,GA7FnB,OAAOA,EAAI,EAAE,CA+FtB,CACH,CACT,EAEA,OACIb,EAAAF,GAAA,CACI,UAAAC,EAAC0L,GAAA,CAAa,SAAAG,EAAc,EAC5B7L,EAAC0L,GAAA,CAAa,SAAAM,EAAe,GACjC,CAER,EAAG,CAAC9K,EAASa,EAAQC,EAAe6H,GAAYlI,EAAQyC,EAAc6E,EAAakB,GAAyBG,CAAgB,CAAC,EAMvH2B,GAAapG,EACf,CAACqG,EAAeC,IAAY,CACxB,IAAMC,EAAW5G,EAAmB,YAAY,IAAI,EAAI,EAGxD,GAAI,CAAC2G,EAAM,CACP,GAAI3G,EAAkB,CAClBE,EAAa,QAAQ,iBAAmB,EACxC,IAAM2G,EAAc,YAAY,IAAI,EAAID,EACxC1G,EAAa,QAAQ,cAAgB2G,EACrC3G,EAAa,QAAQ,gBAAkB,KAAK,IACxCA,EAAa,QAAQ,gBACrB2G,CACJ,CACJ,CACA,OAAO,IACX,CAGA,IAAMC,EAAYjJ,GACZA,GAAmB8I,EAAMD,CAAK,EAC9B,KACN,GAAII,GAAc,KACd,OACItM,EAAC2L,EAAA,CACG,QAASzK,EAAQ,OACjB,eAAa,GACb,GAAI,CACA,CAAE,QAAS6C,EAAS,SAAW,UAAW,EAC1C,GAAI,MAAM,QAAQT,EAAc,EAC1BA,GACAA,GACE,CAACA,EAAc,EACf,CAAC,CACb,EAEC,SAAAgJ,EACL,EAKR,IAAIC,EAAmB,EACjBC,EAAQtL,EAAQ,IAAI,CAACuL,EAAQC,IAAgB,CAC/C,GAAIH,EAAmB,EACnB,OAAAA,GAAoB,EACb,KAEX,IAAMI,EAAUF,EAAO,QACjB,KAAK,IAAI,EAAG,KAAK,IAAIA,EAAO,QAAQN,EAAMD,CAAK,EAAGhL,EAAQ,OAASwL,CAAW,CAAC,EAC/E,EACNH,EAAmBI,EAAU,EAC7B,IAAMC,EAAYpH,EAAmB,YAAY,IAAI,EAAI,EACnDqH,EAAYJ,EAAO,OACnBA,EAAO,OAAON,EAAMD,CAAK,EACzB,OAAQC,EAAaM,EAAO,EAAE,GAAK,EAAE,EAE3C,GAAIjH,EAAkB,CAClB,IAAMsH,EAAe,YAAY,IAAI,EAAIF,EACzClH,EAAa,QAAQ,iBAAmB,EACxCA,EAAa,QAAQ,cAAgBoH,EACrCpH,EAAa,QAAQ,gBAAkB,KAAK,IACxCA,EAAa,QAAQ,gBACrBoH,CACJ,CACJ,CAEA,IAAMC,EAASnE,GAAW,IAAI,OAAO6D,EAAO,EAAE,CAAC,EACzCO,EAAgBP,EAAO,cAAgB,OAEvCQ,EAAOR,EAAO,QAAUA,EAAO,QAAQN,EAAMD,CAAK,EAAI,EAC5D,GAAIe,GAAQ,EAAG,OAAO,KACtB,IAAMC,EAAcT,EAAO,YAC3B,OACIzM,EAAC2L,EAAA,CAEG,MAAOc,EAAO,OAAS,OACvB,QAASQ,EAAO,EAAIA,EAAO,OAC3B,QAASN,EAAU,EAAIA,EAAU,OACjC,eAAcK,EAAgB,GAAK,OACnC,kBAAiBD,EAAS,GAAK,OAC/B,sBAAqBG,EAAc,GAAK,OACxC,QACIA,EACOrG,GAAwB,CAErB,IAAM2C,GAAK3C,EAAE,QAAUwC,EAAqB,QAAQ,EAC9CI,EAAK5C,EAAE,QAAUwC,EAAqB,QAAQ,EACpDxC,EAAE,gBAAgB,EACd,OAAK,KAAK2C,GAAKA,GAAKC,EAAKA,CAAE,EAAItJ,KACnC+M,EAAYf,EAAMD,EAAOrF,CAAC,CAC9B,EACA,OAEV,MAAO,CAEH,GAAI8F,EAAU,EAAI,CAAC,EAAI,CAAE,MAAOF,EAAO,MAAO,SAAUA,EAAO,OAASA,EAAO,QAAS,EACxF,GAAIA,EAAO,QAAU,CAAE,SAAU,EAAG,EAAI,CAAC,EACzC,GAAGA,EAAO,MACV,GAAIA,EAAO,UAAYA,EAAO,UAAUN,EAAMD,CAAK,EAAI,CAAC,EACxD,QAASc,EAAgBP,EAAO,YAAc,WAC9C,GAAGxD,EAAYwD,EAAQ,EAAK,CAChC,EAEC,SAAAI,GA7BI,OAAOJ,EAAO,EAAE,CA8BzB,CAER,CAAC,EAED,GAAIjH,EAAkB,CAClBE,EAAa,QAAQ,iBAAmB,EACxC,IAAM2G,EAAc,YAAY,IAAI,EAAID,EACxC1G,EAAa,QAAQ,cAAgB2G,EACrC3G,EAAa,QAAQ,gBAAkB,KAAK,IACxCA,EAAa,QAAQ,gBACrB2G,CACJ,CACJ,CAEA,OAAOrM,EAAAD,GAAA,CAAG,SAAAyM,EAAM,CACpB,EACA,CAACtL,EAASsE,EAAkBnC,GAAoBC,GAAgBS,EAAQ6E,GAAYK,CAAW,CACnG,EAQMkE,GAAqBtH,EAAY,IAAM,CACzC,IAAMuH,EAAa7B,GAAkB,EACrC,GAAI,CAAC/H,IAAcA,GAAW,SAAW,EAAG,OAAO4J,EACnD,IAAMC,EAAe1E,GAAgB,QACrC,OACI1I,EAAAF,GAAA,CACK,UAAAqN,EACDpN,EAAC,MAAG,uBAAqB,GACrB,SAAAA,EAAC,MAAG,QAASkB,EAAQ,OAAQ,MAAO,CAAE,QAAS,EAAG,OAAQ,CAAE,EACxD,SAAAlB,EAACqH,EAAA,CACG,wBAAsB,GACtB,GAAI,CACA,CACI,UAAW5D,GACX,UAAWA,GAAsB,OAAS,UAC1C,UAAW,SACX,eAAgB,OAChB,aAAc,aAAaM,EAASG,EAAa,aAAe,wBAAwB,GAExF,+BAAgC,CAAE,aAAc,MAAO,CAC3D,EACA,GAAI,MAAM,QAAQR,EAAY,EAAIA,GAAeA,GAAe,CAACA,EAAY,EAAI,CAAC,CACtF,EAEA,SAAAzD,EAAC,SACG,MAAO,CACH,MAAO,OACP,YAAAmD,GACA,eAAgB,WAChB,cAAe,CACnB,EAEA,UAAApD,EAAC,YACI,SAAAkB,EAAQ,IAAKJ,GACVd,EAAC,OAAyB,MAAO,CAAE,MAAOc,EAAI,MAAO,SAAUA,EAAI,OAASA,EAAI,QAAS,GAA/E,OAAOA,EAAI,EAAE,CAAqE,CAC/F,EACL,EACAd,EAACsN,GAAA,CACI,SAAA9J,GAAW,IAAI,CAAC2I,EAAMD,IACnBmB,EACIrN,EAACqN,EAAA,CAEG,KAAMlB,EACN,aAAYD,EACZ,sBAAoB,GAEnB,SAAAD,GAAWC,EAAOC,CAAI,GALlB/K,EAAW,OAAOA,EAAS+K,EAAMD,CAAK,CAAC,EAAI,IAAIA,CAAK,EAM7D,EACA,IACR,EACJ,GACJ,EACJ,EACJ,EACJ,GACJ,CAER,EAAG,CAACX,GAAmB/H,GAAYC,GAAqBC,GAAcxC,EAAS+K,GAAY7I,GAAahC,EAAU2C,EAAQG,CAAY,CAAC,EAGjIqJ,EACF1K,IAAc3B,EAAQ,KAAMJ,GAAQ,OAAOA,EAAI,QAAW,UAAU,EAOlE0M,GAAqB3H,EAAY,IAAM,CACzC,GAAI,CAAC0H,EACD,OAAO,KAIX,IAAMf,EAA2B,CAAC,EAClC,QAASiB,EAAI,EAAGA,EAAIvM,EAAQ,OAAQuM,GAAK,EAAG,CACxC,IAAM3M,EAAMI,EAAQuM,CAAC,EACfd,EACF7L,EAAI,eAAiBA,EAAI,cAAgB,EACnC,KAAK,IAAIA,EAAI,cAAeI,EAAQ,OAASuM,CAAC,EAC9C,EAEVjB,EAAM,KACFxM,EAAC2L,EAAA,CAEG,MAAO7K,EAAI,OAAS,OACpB,QAAS6L,EAAU,EAAIA,EAAU,OACjC,MAAO,CAEH,GAAIA,EAAU,EACR,CAAC,EACD,CAAE,MAAO7L,EAAI,MAAO,SAAUA,EAAI,KAAM,EAC9C,GAAGA,EAAI,MACP,WAAY,OAEZ,QAASiD,EAAS,SAAW,MACjC,EAEC,SAAAjD,EAAI,OAASA,EAAI,OAAOE,CAAI,EAAI,MAd5B,OAAOF,EAAI,EAAE,CAetB,CACJ,EAGA2M,GAAKd,EAAU,CACnB,CAEA,OAAO3M,EAAC0L,GAAA,CAAa,SAAAc,EAAM,CAC/B,EAAG,CAACe,EAAWrM,EAASF,EAAM+C,CAAM,CAAC,EAG/B2J,GAA8CvI,EAChD,KAAO,CAEH,SAAUiB,GAEV,MAAQE,GACJtG,EAAC2N,GAAA,CACI,GAAGrH,EACJ,GAAI,CACA,eAAgB,WAChB,YAAAlD,GACA,GAAI2F,GAAgB,CAAE,SAAUA,EAAc,EAAI,CAAC,EAEnD,YAAa9F,EAAS,OAAS,EAG/B,GAAIsK,EAAY,CAAE,OAAQ,MAAO,EAAI,CAAC,CAC1C,EACJ,EAGJ,UAAWlH,GACP,CAACC,EAAOC,IACJvG,EAAC4N,GAAA,CACI,GAAGtH,EACJ,IAAKC,EACL,GAAI,CACA,WAAY,OAEZ,SAAU,CACN,OAAQnC,EACR,SAAU,CACN,QAAS,OACT,SAAU,SACV,IAAK,EACL,OAAQ,EACR,WAAY,MAChB,CACJ,CACJ,EACJ,CAER,EAGA,SAAWkC,GAAe,CACtB,GAAM,CACF,KAAA6F,EACA,SAAU0B,EACV,gBAAiBC,EACjB,UAAAC,EACA,GAAGC,CACP,EAAI1H,EAEE2H,EAAWD,EAAK,YAAY,GAAK,EACjCE,EAAWD,EAAW,IAAM,EAC5BE,EACFhC,GAAQ3D,GAAY,QACdA,GAAY,QAAQ2D,EAAM8B,CAAQ,EAClCA,EAGJG,EACF,CAAC/I,IACDhE,IAAkB,MAClBA,IAAkB,QAClB8M,IAAU9M,EACRgN,EACFD,GAAchJ,EACR,OAAOA,GAAkB,WACrBA,EAAc+G,EAAM8B,CAAQ,EAC5B7I,EACJ,OACJkJ,EAAqB,OAAOP,GAAa,EAAE,EAC5C,MAAM,KAAK,EACX,OACIQ,GACGA,IAAU,gBACVA,IAAU,kBAClB,EACC,KAAK,GAAG,EAEb,OACIvO,EAAC0L,GAAA,CACI,GAAGsC,EACJ,cAAaG,GAAU,KAA8B,OAAOA,CAAK,EAAI,OACrE,UAAWG,GAAsB,OACjC,SAAUF,EACV,YAAcvH,GAAW,CAErBuC,GAAoB,QAAU,GAC9BC,EAAqB,QAAU,CAC3B,EAAGxC,EAAE,QACL,EAAGA,EAAE,OACT,CACJ,EACA,cAAgBA,GAAwB,CAChCsF,GAAQ1D,GAAoB,SAC5BA,GAAoB,QAAQ0D,EAAM8B,EAAUpH,CAAC,CAErD,EACA,QAAUA,GAAwB,CAE9B,IAAM2C,EACF3C,EAAE,QAAUwC,EAAqB,QAAQ,EACvCI,EACF5C,EAAE,QAAUwC,EAAqB,QAAQ,EAK7C,GAHI,KAAK,KAAKG,EAAKA,EAAKC,EAAKA,CAAE,EACvBtJ,IACJiJ,GAAoB,QACX,CACTvC,EAAE,eAAe,EACjBA,EAAE,gBAAgB,EAClBuC,GAAoB,QAAU,GAC9B,MACJ,CACI+C,GAAQ5D,GAAc,SACtBA,GAAc,QAAQ4D,EAAM8B,CAAQ,EAExC7E,GAAoB,QAAU,EAClC,EACA,GAAI,CACA,CACI,WAAY,OAUZ,GAAI7E,GACE,CAAE,SAAU,CAAE,OAAQU,EAAoB,CAAE,EAC5C,CACI,OAAQA,GACR,UAAWA,EACf,EACN,UAAW,aACX,gBACIiJ,GAAY3G,GACNA,GACA,cAEV,2BAA4B,CACxB,QAAS,UACb,EACA,OAAQ,CACJ,UAAW,aACX,aAAc7F,GACR,mCACA,MACV,EACA,OAAQ,CACJ,QAAS,WACT,aAAc,MAClB,EACA,UACIyH,IAAe,CAACiF,EACV,CACI,gBAAkBI,GAAU,CACxB,IAAMC,EACFD,EAAM,QAAQ,OACd,OAGE7N,EACF6D,IAFA,UAIEkK,GACFjK,IAAmB,IAEvB,GAAI,CAACD,GACD,OAAOiK,EACD,uBAAuBC,EAAO,IAC9B,iBAAiBA,EAAO,IAGlC,IAAMC,EAAMhO,EACP,QAAQ,IAAK,EAAE,EACf,KAAK,EACV,GAAIgO,EAAI,SAAW,EACf,OAAOhO,EAGX,IAAMiO,GAAI,SACND,EAAI,UAAU,EAAG,CAAC,EAClB,EACJ,EACME,GAAI,SACNF,EAAI,UAAU,EAAG,CAAC,EAClB,EACJ,EACMG,GAAI,SACNH,EAAI,UAAU,EAAG,CAAC,EAClB,EACJ,EAEA,MAAO,QAAQC,EAAC,KAAKC,EAAC,KAAKC,EAAC,KAAKJ,EAAO,GAC5C,CACJ,EACA,OACV,OAAQvF,GAAc,UAAY,MACtC,EACAkF,CACJ,EACJ,CAER,EAGA,UAAWhI,GAAoC,CAACC,EAAOC,IAAQ,CAC3D,GAAM,CAAE,SAAAwI,EAAU,GAAGf,CAAK,EACtB1H,EACJ,OACIrG,EAACqN,GAAA,CACI,GAAGU,EACJ,IAAKzH,EACL,GAAIgH,EAAY,CAAE,OAAQ,MAAO,EAAI,OAEpC,UAAAwB,EAKAxB,GACGvN,EAAC,MAAG,cAAW,GAAC,MAAO,CAAE,OAAQ,MAAO,EACpC,SAAAA,EAAC,MACG,QAASkB,EAAQ,OACjB,MAAO,CAAE,QAAS,EAAG,OAAQ,CAAE,EACnC,EACJ,GAER,CAER,CAAC,EAED,UAAWmF,GACP,CAACC,EAAOC,IACJvG,EAACgP,GAAA,CACI,GAAG1I,EACJ,IAAKC,EACL,GAAI,CACA,CAQI,OAAQ,CACJ,OAAQzD,IAAgBuB,EACxB,UAAWvB,IAAgBuB,EAC3B,UAAW,YACf,EACA,OAAQ,CACJ,OAAQvB,IAAgBuB,EACxB,UAAW,aACX,gBAAkBmK,GACdA,EAAM,QAAQ,OAAS,OACjB,UACA,UAIV,QAAS,SACT,MAAO,UACP,SAAU,WAGV,OAAQ,OAER,UAAW,mBAAmBzK,EAASG,EAAa,aAAe,SAAS,EAChF,CACJ,EACA,GAAI,MAAM,QAAQnB,EAAQ,EACpBA,GACAA,GACE,CAACA,EAAQ,EACT,CAAC,CACb,EACJ,CAER,CACJ,GACA,CAEIoG,GAGA9D,GAAqB,KAAOhE,EAC5B+D,EACAf,EACAkD,GACA7F,GACA0C,EACAI,GACAC,GACA2B,GACAtD,GACAC,GACAwK,EACAxJ,EACAG,EAEAhD,EACAkC,GACAH,EACAsB,GACAwE,EACJ,CACJ,EACAJ,GAAgB,QAAW+E,GAAoD,SAE/E,IAAMuB,GAA6BvB,GAE7BwB,GAAYxB,GACZyB,GAAYD,GAAU,MACtBE,GAAgBF,GAAU,UAC1BG,GAAgBH,GAAU,UAC1BI,GAAeJ,GAAU,SACzBK,GAAgBL,GAAU,UAG1BM,EAAazF,GAAa7I,EAAQ,KAAMJ,GAAQ,OAAOA,EAAI,EAAE,IAAMiJ,GAAW,KAAK,EAAI,OACvF0F,GAAkB,IAAMzF,GAAc,IAAI,EAC5C0F,GAAkC,KACtC,GAAI3F,IAAcyF,EAAY,CAC1B,IAAMG,EAAQ,OAAOH,EAAW,EAAE,EAC5BI,EAAU,GAAQJ,EAAW,UAAY7N,GACzCkO,EAAYhP,GAAgB2O,CAAU,EACtCM,EAAa/N,IAAW4N,EAAQ3N,EAAgB,OAChD+N,EAASP,EAAW,cAAgB,CAAC,EACrCQ,EAAWR,EAAW,iBAAmB,GAEzCS,EAAS,CAAE,IAAK,EAAG,SAAU,GAAI,UAAW,EAAG,EAE/CC,EAAYC,GAA6B,CAE3C,GADAV,GAAgB,EACZK,IAAeK,EAAW,CAC1BvO,IAAc,EACd,MACJ,CACAD,IAASgO,EAAOQ,CAAS,CAC7B,EAEMC,EAAeC,GAAkB,CACnC,IAAMC,EAAKP,EAAO,SAASM,CAAK,EAChC,GAAIL,EAAU,CACVR,EAAW,iBAAiBc,EAAKP,EAAO,OAAQ5D,GAASA,IAASkE,CAAK,EAAI,CAAC,GAAGN,EAAQM,CAAK,CAAC,EAC7F,MACJ,CACAZ,GAAgB,EAChBD,EAAW,iBAAiBc,EAAK,CAAC,EAAI,CAACD,CAAK,CAAC,CACjD,EACME,EAA2B,CAAC,EAC9BX,IACAW,EAAM,KACFtQ,EAACuQ,GAAA,CAAmB,SAAUV,IAAe,MAAO,QAAS,IAAMI,EAAS,KAAK,EAAG,GAAID,EACpF,UAAAjQ,EAACQ,GAAA,CAAS,EAAGD,GAAW,IAAK,MAAM,iBAAiB,EAAE,0CAD5C,KAGd,EACAN,EAACuQ,GAAA,CAAoB,SAAUV,IAAe,OAAQ,QAAS,IAAMI,EAAS,MAAM,EAAG,GAAID,EACvF,UAAAjQ,EAACQ,GAAA,CAAS,EAAGD,GAAW,KAAM,MAAM,iBAAiB,EAAE,0CAD7C,MAGd,CACJ,EACIuP,GAAclO,GACd2O,EAAM,KACFvQ,EAACwQ,GAAA,CAEG,QAAS,IAAM,CACXf,GAAgB,EAChB7N,EAAY,CAChB,EACA,GAAI,CAAE,GAAGqO,EAAQ,MAAO,gBAAiB,EAC5C,sCANO,YAQR,CACJ,GAGJL,GAAWC,GAAWU,EAAM,KAAKvQ,EAACyQ,GAAA,GAAY,UAAW,CAAE,EAC3DZ,KACCL,EAAW,eAAiB,CAAC,GAAG,QAASkB,GAAW,CACjD,IAAMJ,EAAKP,EAAO,SAASW,EAAO,KAAK,EACvCH,EAAM,KACFtQ,EAACuQ,GAAA,CAAmC,SAAU,CAACR,GAAYM,EAAI,QAAS,IAAMF,EAAYM,EAAO,KAAK,EAAG,GAAIT,EACxG,UAAAD,EACGhQ,EAACQ,GAAA,CAAS,EAAG8P,EAAK/P,GAAW,QAAUA,GAAW,UAAW,MAAO+P,EAAK,eAAiB,gBAAiB,EAG3GtQ,EAACqH,EAAA,CAAI,UAAU,OAAO,GAAI,CAAE,QAAS,cAAe,MAAO,GAAI,WAAY,EAAG,MAAO,cAAe,EAC/F,SAAAiJ,EAAKtQ,EAACQ,GAAA,CAAS,EAAGD,GAAW,MAAO,EAAK,KAC9C,EAEHmQ,EAAO,QATG,KAAKA,EAAO,KAAK,EAUhC,CACJ,CACJ,CAAC,EAEGX,EAAO,OAAS,GAChBQ,EAAM,KACFvQ,EAACyQ,GAAA,GAAY,YAAa,EAC1BzQ,EAACwQ,GAAA,CAEG,QAAS,IAAM,CACXf,GAAgB,EAChBD,EAAW,iBAAiB,CAAC,CAAC,CAClC,EACA,GAAI,CAAE,GAAGS,EAAQ,MAAO,gBAAiB,EAC5C,4CANO,cAQR,CACJ,GAGRP,GAEI1P,EAAC2Q,GAAA,CACG,KAAI,GACJ,gBAAgB,iBAChB,eAAgB,CAAE,KAAM5G,GAAW,EAAG,IAAKA,GAAW,CAAE,EACxD,QAAS0F,GACT,mBAAoB,EAEpB,cAAgBlG,GAAUA,EAAM,eAAe,EAC/C,UAAW,CAAE,MAAO,CAAE,GAAI,CAAE,UAAW,IAAK,SAAU,GAAI,CAAE,CAAE,EAE7D,SAAAgH,EACL,CAER,CAGA,IAAMK,GACF3Q,EAACoH,EAAA,CACG,GACI,CACI,SAAU,WACV,OAAQ1E,EAAa,OAAS,OAC9B,MAAO,OACP,uBAAwB,CACpB,gBAAkB6L,GACdzK,EACM,GAAGG,EAAa,EAAE,cAClBsK,EAAM,QAAQ,OAAS,OACrB,qBACA,oBAChB,EAEA,GAAIlJ,IAAoB,CAAC,EAEzB,8BAA+B,CAC3B,gBAAiBvB,EACXG,EAAa,GACbF,GAAS,QAAQ,WAAW,KACtC,EAEA,kCAAmC,CAAE,OAAQ,SAAU,EACvD,wCAAyC,CACrC,gBAAiBD,EACXG,EAAa,QACbF,GAAS,QAAQ,OAAS,OACxB,4BACA,qBACZ,EACA,GAAID,GAAUoF,GACR,CACI,uCAAwC,CACpC,gBAAiBjF,EAAa,OAClC,CACJ,EACA,CAAC,EAGP,GAAIH,EACE,CAGI,GAAId,EACE,CACI,OAAQ,aAAaiB,EAAa,YAAY,GAC9C,aAAc,KAClB,EACA,CAEI,UAAW,CAAE,gBAAiBA,EAAa,EAAG,CAClD,EACN,SAAU,SACV,gBAAiB,CACb,OAAQE,EACR,UAAW,aACX,QAAS,oBACT,SAAU,GACV,WAAY,iBACZ,MAAOF,EAAa,YACpB,gBAAiB,GAAGA,EAAa,EAAE,cAEnC,UAAW,CAACjB,GAAUC,GAAkB,aAAagB,EAAa,YAAY,GAAK,OACnF,aAAc,aAAaA,EAAa,YAAY,GAEpD,YAAa,aAAaA,EAAa,MAAM,GAC7C,iBAAkB,CAAE,YAAa,MAAO,CAC5C,EACA,oCAAqC,CACjC,QAAS,mBACb,EACA,gBAAiB,CACb,SAAU,GACV,aAAc,aAAaA,EAAa,MAAM,EAClD,EAIA,GAAIlD,EAAK,OAAS,IAAM2B,GAAcwF,IAAiBoF,GACjD,CAAE,CAAC,0BAA0BvM,EAAK,OAAS,CAAC,kCAAkC,EAAG,CAAE,aAAc,MAAO,CAAE,EAC1G,CAAC,CACX,EACA,CAAC,CACX,EAIH,UAAA2B,EACG3C,EAACqH,EAAA,CAAI,GAAI,CAAE,UAAW,OAAQ,MAAO,MAAO,EACxC,SAAApH,EAACkP,GAAA,CACG,UAAAnP,EAACoP,GAAA,CAAe,SAAAjC,GAAmB,EAAE,EACrCnN,EAACqP,GAAA,CACI,SAAArO,EAAK,IAAI,CAACmL,EAAMD,IACblM,EAACsP,GAAA,CAEG,KAAMnD,EACN,aAAYD,EAEX,SAAAD,GAAWC,EAAOC,CAAI,GAJlB/K,EAAW,OAAOA,EAAS+K,EAAMD,CAAK,CAAC,EAAIA,CAKpD,CACH,EACL,EACCqB,EAAYvN,EAACuP,GAAA,CAAe,SAAA/B,GAAmB,EAAE,EAAmB,MACzE,EACJ,EAEAxN,EAAC6Q,GAAA,CAEG,IAAK5I,GACL,KAAMjH,EACN,WAAYc,EAAad,EAAK,OAAS,EAAIA,EAAK,OAChD,kBAAmBiE,GACnB,gBAAiBV,GAAgB,OAAYU,GAC7C,mBAAoBkI,GACpB,mBAAoBI,EAAYC,GAAqB,OACrD,YAAavB,GAGZ,GAAIrI,IAAgBxC,EACf,CAAE,eAAgB,CAAC8K,EAAeC,IAAaA,EAAO/K,EAAS+K,EAAMD,CAAK,EAAI,OAAOA,CAAK,EAAI,EAC9F,CAAC,EACP,WAAY3B,GACZ,YAAc5D,GAAO,CACjBuB,GAAc,QAAUvB,aAAc,YAAcA,EAAK,KACzD0B,GAAkB,CACtB,EACA,uBAAwBA,GACxB,MAAO,CAAE,OAAQ,MAAO,EACxB,mBAAoB,CAChB,IAAKzD,GACL,OAAQC,EACZ,EACA,SAAUG,GACV,aAAc,GACd,WAAYiK,IA3BPvH,EA4BT,EAIH1G,EAAK,SAAW,GAAK,CAACC,GAAW,CAACkD,IAAiBJ,GAAU,OAAOrB,GAAiB,UAClF1C,EAACqH,EAAA,CACG,GAAI,CACA,SAAU1E,EAAa,SAAW,WAClC,IAAKyB,EACL,KAAM,EACN,MAAO,EACP,GAAI,EACJ,UAAW,SACX,SAAU,GACV,MAAOF,EAAa,UACxB,EAEC,SAAAxB,EACL,EAEH1B,EAAK,SAAW,GAAK,CAACC,GAAW,CAACkD,IAAiB,EAAEJ,GAAU,OAAOrB,GAAiB,WACpF1C,EAACqH,EAAA,CACG,GAAI,CACA,SAAU,WACV,IAAK,EACL,KAAM,EACN,MAAO,EACP,OAAQ,EACR,QAAS,OACT,cAAe,SACf,WAAY,SACZ,eAAgB,SAChB,IAAK,CACT,EAEC,gBAAO3E,GAAiB,SACrBzC,EAAAF,GAAA,CACI,UAAAC,EAACqH,EAAA,CACG,GAAI,CACA,MAAO,GACP,OAAQ,GACR,QAAS,OACT,WAAY,SACZ,eAAgB,SAChB,aAAc,MACd,gBAAiB,UACjB,MAAO,MACX,EACH,qBAED,EACArH,EAAC8Q,GAAA,CACG,QAAQ,QACR,GAAI,CAAE,MAAO,gBAAiB,EAE7B,SAAApO,EACL,GACJ,EAEAA,EAER,EAGHgN,GAGA7H,IACG7H,EAAAD,GAAA,CACK,SAAA6C,GACG5C,EAAC4C,GAAA,CACG,QAAS3B,EACT,WAAY2G,GAChB,EAEA5H,EAAC+Q,GAAA,CACG,QAAS9P,EACT,WAAY2G,GACZ,KAAM,GACN,UAAW5H,EAACgR,GAAA,EAAW,EACvB,GAAI,CACA,IAAK,GACD9P,EAAQ,KAAMJ,GAAQA,EAAI,KAAK,EACzBsD,EAAe,EACfA,CACV,KAEA,OAAQ,GAAGmJ,EAAYzK,IAAgBuB,EAAY,CAAC,IACxD,EACA,WAAY,CACR,KAAMrD,EAAK,SAAW,EACtB,QAAS,EACb,EACJ,EAER,GAER,EAIEiQ,GAAqBlN,GAAUd,EAC/B,CAAE,aAAcqB,GAAU,WAAYjE,GAAkB,cAAeA,EAAiB,EACxF,CAAC,EAEP,OAAO4B,GACHjC,EAACkR,GAAA,CACG,UAAU,OACV,UAAW,EACX,GAAI,CACA,QAAS,EACT,YAAa5M,GACb,GAAG2M,GACH,UAAW,aACX,OAAQtO,EAAa,OAAS,OAC9B,UAAW,EACX,KAAMA,EAAa,OAAS,EAC5B,QAAS,OACT,cAAe,QACnB,EAEC,SAAAiO,GACL,EAEA5Q,EAACqH,EAAA,CACG,UAAU,OACV,MAAO,CACH,QAAS,EACT,YAAa/C,GACb,GAAG2M,GACH,UAAW,aACX,OAAQtO,EAAa,OAAS,OAC9B,UAAW,EACX,KAAMA,EAAa,OAAS,EAC5B,QAAS,OACT,cAAe,QACnB,EAEC,SAAAiO,GACL,CAER,CAEO,IAAMO,GAAmBC,GAAKrQ,EAAyB",
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 TableFooter as MuiTableFooter,\n TableRow as MuiTableRow,\n TableSortLabel,\n Menu,\n MenuItem,\n Divider,\n SvgIcon,\n Paper,\n Typography,\n useTheme,\n type SxProps,\n type Theme,\n} from \"@mui/material\";\nimport { TableVirtuoso } from \"react-virtuoso\";\nimport type { TableComponents } from \"react-virtuoso\";\nimport { LoadingProgress } from \"@ehfuse/mui-fadeout-loading-progress\";\nimport { CssSpinner } from \"./CssSpinner\";\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: \"default\" as const, // \uC61B \uAC12 \"right\" \uB294 1.7 \uD0C0\uC785\uC5D0\uC11C \uC0AC\uB77C\uC84C\uB2E4 \u2014 \uB3D9\uC791\uC740 \uAC19\uB2E4(\"outside\" \uAC00 \uC544\uB2C8\uBA74 \uC548\uCABD \uC815\uB82C)\n margin: 0,\n radius: 0,\n};\nconst ROW_CLICK_DRAG_THRESHOLD_PX = 5;\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 */\n/**\n * \uB178\uC158\uD48D(variant=\"notion\") \uC0C9 \u2014 @ehfuse/taskbox \uC758 \uBAA9\uB85D\uD45C \uD314\uB808\uD2B8(light: border/borderStrong/textSecondary/surfaceHover,\n * dark: \uAC19\uC740 \uC774\uB984\uC758 \uB2E4\uD06C \uAC12)\uB97C \uADF8\uB300\uB85C \uC62E\uAE34 \uAC83\uC774\uB2E4. \uB450 \uD328\uD0A4\uC9C0\uAC00 \uC11C\uB85C\uB97C \uCC38\uC870\uD558\uC9C0 \uC54A\uC544 \uAC12\uC744 \uBCA0\uAEF4 \uB454\uB2E4 \u2014 \uADF8\uCABD\uC774 \uBC14\uB00C\uBA74 \uC5EC\uAE30\uB3C4 \uB9DE\uCD98\uB2E4.\n */\nconst NOTION_LIGHT = {\n bg: \"#ffffff\",\n border: \"#e6e6e3\",\n borderStrong: \"#dedddb\",\n headerColor: \"#787774\",\n hoverBg: \"#f8f8f7\",\n emptyColor: \"#9b9a97\",\n selectedBg: \"#dbeafe\",\n selectedBar: \"#3b82f6\",\n};\n/** \uB178\uC158\uD48D \uC885\uC774 \uC704\uC544\uB798 \uC5EC\uBC31 \u2014 \uC88C\uC6B0 \uAE30\uBCF8(12px)\uACFC \uAC19\uB2E4. */\nconst NOTION_PADDING_Y = \"12px\";\nconst NOTION_DARK = {\n bg: \"#1e1e1e\",\n border: \"#2c333c\",\n borderStrong: \"#3b434e\",\n headerColor: \"#a3adbb\",\n hoverBg: \"#272d36\",\n emptyColor: \"#7d8590\",\n selectedBg: \"rgba(59, 130, 246, 0.22)\",\n selectedBar: \"#60a5fa\",\n};\n\n/** \uBA38\uB9AC \uC6B0\uD074\uB9AD \uBA54\uB274\uC758 \uC544\uC774\uCF58(Material \uC544\uC774\uCF58 \uACBD\uB85C) \u2014 @mui/icons-material \uC744 \uC758\uC874\uC131\uC73C\uB85C \uB4E4\uC774\uC9C0 \uC54A\uC73C\uB824\uACE0 \uACBD\uB85C\uB9CC \uC62E\uACA8 \uB454\uB2E4. */\nconst ICON_PATHS = {\n asc: \"M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z\",\n desc: \"M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z\",\n checked: \"M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\",\n unchecked: \"M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z\",\n check: \"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\",\n filter: \"M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z\",\n};\n\nfunction PathIcon({ d, size = 18, color }: { d: string; size?: number; color?: string }) {\n return (\n <SvgIcon sx={{ fontSize: size, flexShrink: 0, color }}>\n <path d={d} />\n </SvgIcon>\n );\n}\n\n/** \uC774 \uC5F4\uC774 \uBA38\uB9AC \uBA54\uB274\uC5D0 \uAC70\uB974\uAE30 \uBAA9\uB85D\uC744 \uAC16\uB294\uC9C0 \u2014 \uAC12 \uBAA9\uB85D\uACFC \uBC14\uB01C \uC54C\uB9BC\uC774 \uB458 \uB2E4 \uC788\uC5B4\uC57C \uD55C\uB2E4. */\nfunction hasColumnFilter<T>(col: DataColumn<T>): boolean {\n return Boolean(col.filterOptions && col.onFilterChange);\n}\n\nfunction VirtualDataTableComponent<T>({\n data,\n loading = false,\n columns,\n onRowClick,\n getRowId,\n selectedRowId,\n selectedRowSx: selectedRowSxProp,\n rowHeight: rowHeightProp,\n columnHeight: columnHeightProp,\n striped,\n rowDivider = true,\n onSort,\n onSortClear,\n onHeaderContextMenu,\n onLoadMore,\n sortBy,\n sortDirection,\n showPaper = true,\n paddingX: paddingXProp,\n paddingTop = 0,\n paddingBottom = 0,\n rowHoverColor: rowHoverColorProp,\n rowHoverOpacity: rowHoverOpacityProp,\n viewportBuffer,\n overscan,\n scrollbars,\n emptyMessage = \"NO DATA\",\n autoHeight = false,\n LoadingComponent,\n showFooter,\n footerHeight,\n footerSx,\n variant = \"default\",\n framed = true,\n headerTopBorder = false,\n rowHeightMode = \"fixed\",\n tableLayout = \"fixed\",\n renderFullWidthRow,\n fullWidthRowSx,\n onRowContextMenu,\n pinnedRows,\n pinnedRowsMaxHeight,\n pinnedRowsSx,\n resetScrollOnDataChange = true,\n rowKeyFromId = false,\n onEndReached,\n colorMode,\n}: VirtualDataTableProps<T>) {\n // \uB178\uC158\uD48D(variant=\"notion\") \u2014 @ehfuse/taskbox \uBAA9\uB85D\uD45C\uC640 \uAC19\uC740 \uAC12\uC774\uB2E4. \uAE30\uBCF8\uAC12\uB9CC \uBC14\uAFB8\uACE0 \uC9C1\uC811 \uC900 prop \uC774 \uC774\uAE34\uB2E4.\n const notion = variant === \"notion\";\n const muiTheme = useTheme();\n // colorMode \uB97C \uC8FC\uBA74 \uC571 \uD14C\uB9C8\uC640 \uB2EC\uB9AC \uC774 \uD45C\uB9CC \uADF8 \uBAA8\uB4DC\uB85C \uCE60\uD55C\uB2E4(\uC571\uC740 \uBC1D\uC740\uB370 \uC5C5\uBB34\uD568\uB9CC \uC5B4\uB450\uC6B4 \uACBD\uC6B0).\n const notionTokens = (colorMode ?? muiTheme.palette.mode) === \"dark\" ? NOTION_DARK : NOTION_LIGHT;\n const hasPinnedRows = (pinnedRows?.length ?? 0) > 0;\n const columnHeight = columnHeightProp ?? (notion ? 40 : 56);\n // \uB178\uC158\uD48D \uC904 \uB192\uC774 \uAE30\uBCF8 48 \u2014 \uC5C5\uBB34\uD568 \uBAA9\uB85D \uD45C \u00B7 \uC804\uC790\uACB0\uC7AC \uD45C\uAC00 \uC4F0\uB294 \uAC12\uC774\uB2E4.\n const rowHeight = rowHeightProp ?? (notion ? 48 : 50);\n // \uD2C0 \uC5C6\uC774(framed=false) \uADF8\uB9B4 \uB54C\uB294 \uBC14\uAE65 \uC0C1\uC790\uAC00 \uC774\uBBF8 \uD14C\uB450\uB9AC\uB97C \uB458\uB800\uB2E4 \u2014 \uC88C\uC6B0 \uC5EC\uBC31 \uC5C6\uC774 \uD45C\uAC00 \uC0C1\uC790\uC5D0 \uAF49 \uCC2C\uB2E4.\n const paddingX = framed ? (paddingXProp ?? (notion ? \"12px\" : \"1rem\")) : 0;\n const autoRowHeight = rowHeightMode === \"auto\";\n // \uD638\uBC84\uB294 \uB2E8\uC0C9(\uBD88\uD22C\uBA85) \u2014 \uAE30\uBCF8 \uBAA8\uC591\uC758 \uBC18\uD22C\uBA85 \uAC80\uC815\uC740 \uD770 \uC885\uC774 \uC704\uC5D0\uC11C \uD68C\uC0C9\uC774 \uC544\uB2C8\uB77C \uD0C1\uD55C \uC0C9\uC73C\uB85C \uBCF4\uC778\uB2E4.\n const rowHoverColor = rowHoverColorProp ?? (notion ? notionTokens.hoverBg : undefined);\n const rowHoverOpacity = rowHoverOpacityProp ?? (notion ? 1 : undefined);\n const defaultViewportBufferTop = Math.max(rowHeight * 12, 480);\n const defaultViewportBufferBottom = Math.max(rowHeight * 12, 480);\n const viewportBufferTop =\n typeof viewportBuffer === \"number\"\n ? viewportBuffer\n : (viewportBuffer?.top ?? defaultViewportBufferTop);\n const viewportBufferBottom =\n typeof viewportBuffer === \"number\"\n ? viewportBuffer\n : (viewportBuffer?.bottom ?? defaultViewportBufferBottom);\n const defaultOverscanMain = Math.max(rowHeight * 8, 420);\n const defaultOverscanReverse = Math.max(rowHeight * 10, 520);\n const virtuosoOverscan =\n typeof overscan === \"number\"\n ? overscan\n : {\n main: overscan?.main ?? defaultOverscanMain,\n reverse: overscan?.reverse ?? defaultOverscanReverse,\n };\n const estimatedItemHeight = rowHeight + (rowDivider ? 1 : 0);\n\n // \uC120\uD0DD \uD589 \uD558\uC774\uB77C\uC774\uD2B8\uB294 selectedRowSx \uAC00 \uAC1D\uCCB4(\uB610\uB294 \uBBF8\uC9C0\uC815)\uBA74 CSS \uC140\uB809\uD130\uB85C \uCC98\uB9AC\uD55C\uB2E4.\n // \uCEE8\uD14C\uC774\uB108 sx \uC5D0 `tr[data-row-id=\"...\"]` \uADDC\uCE59\uC744 \uB123\uC73C\uBA74 selectedRowId \uBCC0\uACBD \uC2DC components/\uD589\uC744\n // \uC7AC\uB80C\uB354\uD558\uC9C0 \uC54A\uACE0(\uCEE8\uD14C\uC774\uB108 1\uAC1C\uB9CC \uAC31\uC2E0) CSS \uB85C\uB9CC \uAC15\uC870\uB3FC row \uD074\uB9AD \uBC18\uC751\uC774 \uC989\uAC01\uC801\uC774\uB2E4.\n // \uD568\uC218\uD615 selectedRowSx(\uD589\uB9C8\uB2E4 \uB3D9\uC801)\uB294 CSS \uB85C \uD45C\uD604 \uBD88\uAC00\uD558\uBBC0\uB85C \uAE30\uC874 per-row \uACBD\uB85C\uB97C \uC720\uC9C0\uD55C\uB2E4.\n // \uB178\uC158\uD48D\uC740 \uC120\uD0DD \uC904 \uBAA8\uC591\uC744 \uAE30\uBCF8\uC73C\uB85C \uAC16\uB294\uB2E4 \u2014 \uC605\uC740 \uD30C\uB780 \uBC14\uD0D5 + \uC67C\uCABD \uD30C\uB780 \uB760 3px(\uBAA9\uB85D \uD45C\uC758 \"\uC9C0\uAE08 \uC5F4\uC5B4 \uB454 \uC904\").\n // \uB760\uB294 \uC904(tr)\uC758 \uADF8\uB9BC\uC790\uAC00 \uBE0C\uB77C\uC6B0\uC800\uB9C8\uB2E4 \uADF8\uB824\uC9C0\uC9C0 \uC54A\uC544 \uCCAB \uCE78 \uC548\uCABD \uADF8\uB9BC\uC790\uB85C \uAE0B\uB294\uB2E4. \uACE0\uC815 \uC5F4 \uCE78\uC740 \uC81C \uBC14\uD0D5\uC744 \uCE60\uD558\uBBC0\uB85C \uAC19\uC740 \uC0C9\uC744 \uC900\uB2E4.\n const notionSelectedSx = useMemo(\n () =>\n notion\n ? {\n backgroundColor: notionTokens.selectedBg,\n \"& > td:first-of-type\": { boxShadow: `inset 3px 0 0 ${notionTokens.selectedBar}` },\n \"& > td[data-vdt-pinned]\": { backgroundColor: notionTokens.selectedBg },\n }\n : undefined,\n [notion, notionTokens],\n );\n const selectedRowSx = selectedRowSxProp ?? notionSelectedSx;\n const useCssRowHighlight = !selectedRowSx || typeof selectedRowSx !== \"function\";\n const selectedRowCssSx = useMemo<Record<string, unknown> | null>(() => {\n if (\n !useCssRowHighlight ||\n selectedRowId === null ||\n selectedRowId === undefined ||\n !selectedRowSx\n ) {\n return null;\n }\n const escaped = String(selectedRowId).replace(/[\"\\\\]/g, \"\\\\$&\");\n return {\n [`& tbody tr[data-row-id=\"${escaped}\"]`]: selectedRowSx,\n };\n }, [useCssRowHighlight, selectedRowId, selectedRowSx]);\n\n const isDev =\n typeof window !== \"undefined\" &&\n (window.location.hostname === \"localhost\" ||\n window.location.hostname === \"127.0.0.1\");\n\n const [perfDebugEnabled] = useState(() => {\n if (typeof window === \"undefined\") {\n return false;\n }\n return window.localStorage.getItem(\"vdt-perf-debug\") === \"1\";\n });\n const perfStatsRef = useRef({\n wheelEvents: 0,\n wheelInputPx: 0,\n wheelHandlerMs: 0,\n wheelRafFlushes: 0,\n wheelRafMs: 0,\n rangeChangedCalls: 0,\n rangeChangedMs: 0,\n rowContentCalls: 0,\n rowContentMs: 0,\n rowContentMaxMs: 0,\n cellRenderCalls: 0,\n cellRenderMs: 0,\n cellRenderMaxMs: 0,\n });\n\n // \uB204\uC801\uB41C \uC131\uB2A5 \uD1B5\uACC4\uB97C \uCF58\uC194\uC5D0 \uC8FC\uAE30\uC801\uC73C\uB85C \uCD9C\uB825\uD55C\uB2E4.\n const flushPerfStats = useCallback(\n (reason: string) => {\n if (!perfDebugEnabled) {\n return;\n }\n const stats = perfStatsRef.current;\n const hasData =\n stats.wheelEvents > 0 ||\n stats.rangeChangedCalls > 0 ||\n stats.rowContentCalls > 0 ||\n stats.cellRenderCalls > 0;\n if (!hasData) {\n return;\n }\n\n const rowAvgMs =\n stats.rowContentCalls > 0\n ? stats.rowContentMs / stats.rowContentCalls\n : 0;\n const cellAvgMs =\n stats.cellRenderCalls > 0\n ? stats.cellRenderMs / stats.cellRenderCalls\n : 0;\n\n console.log(\"[VDT perf]\", {\n reason,\n wheel: {\n events: stats.wheelEvents,\n inputPx: Math.round(stats.wheelInputPx),\n handlerMs: Number(stats.wheelHandlerMs.toFixed(2)),\n rafFlushes: stats.wheelRafFlushes,\n rafMs: Number(stats.wheelRafMs.toFixed(2)),\n },\n rangeChanged: {\n calls: stats.rangeChangedCalls,\n totalMs: Number(stats.rangeChangedMs.toFixed(2)),\n },\n rowContent: {\n calls: stats.rowContentCalls,\n totalMs: Number(stats.rowContentMs.toFixed(2)),\n avgMs: Number(rowAvgMs.toFixed(3)),\n maxMs: Number(stats.rowContentMaxMs.toFixed(3)),\n },\n cellRender: {\n calls: stats.cellRenderCalls,\n totalMs: Number(stats.cellRenderMs.toFixed(2)),\n avgMs: Number(cellAvgMs.toFixed(3)),\n maxMs: Number(stats.cellRenderMaxMs.toFixed(3)),\n },\n });\n\n perfStatsRef.current = {\n wheelEvents: 0,\n wheelInputPx: 0,\n wheelHandlerMs: 0,\n wheelRafFlushes: 0,\n wheelRafMs: 0,\n rangeChangedCalls: 0,\n rangeChangedMs: 0,\n rowContentCalls: 0,\n rowContentMs: 0,\n rowContentMaxMs: 0,\n cellRenderCalls: 0,\n cellRenderMs: 0,\n cellRenderMaxMs: 0,\n };\n },\n [perfDebugEnabled],\n );\n\n useEffect(() => {\n if (!perfDebugEnabled || typeof window === \"undefined\") {\n return;\n }\n\n console.log(\"[VDT perf] enabled (localStorage vdt-perf-debug=1)\");\n\n const intervalId = window.setInterval(() => {\n flushPerfStats(\"interval\");\n }, 1500);\n\n return () => {\n window.clearInterval(intervalId);\n flushPerfStats(\"cleanup\");\n };\n }, [flushPerfStats, perfDebugEnabled]);\n\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 const wheelDeltaRef = useRef(0);\n const wheelRafRef = useRef<number | null>(null);\n\n // \uD720 \uC774\uBCA4\uD2B8\uB97C \uC9C1\uC811 \uC81C\uC5B4\uD574 \uBE0C\uB77C\uC6B0\uC800 smooth-scroll \uBCF4\uAC04 \uC5C6\uC774 \uC989\uC2DC scrollTop \uBC18\uC601\n useEffect(() => {\n const el = scrollContainerRef.current;\n if (!el) return;\n\n // \uD720 \uB378\uD0C0\uB97C \uD504\uB808\uC784 \uB2E8\uC704\uB85C \uD569\uC0B0 \uBC18\uC601\uD574 \uACFC\uB3C4\uD55C scrollTop \uAC31\uC2E0\uC744 \uC904\uC778\uB2E4.\n const handleWheel = (e: WheelEvent) => {\n const wheelStart = perfDebugEnabled\n ? performance.now()\n : 0;\n // \uAC00\uB85C \uD720(\uD2B8\uB799\uD328\uB4DC \uC606 \uBC00\uAE30 \u00B7 Shift+\uD720)\uC740 \uBE0C\uB77C\uC6B0\uC800\uC5D0 \uB9E1\uAE34\uB2E4 \u2014 \uC544\uB798\uC5D0\uC11C \uC138\uB85C\uB85C\uB9CC \uC62E\uAE30\uBBC0\uB85C \uB9C9\uC73C\uBA74\n // \uC5F4\uC774 \uB9CE\uC740 \uD45C(tableLayout=\"auto\")\uB97C \uC606\uC73C\uB85C \uBC00 \uC218 \uC5C6\uB2E4.\n if (e.shiftKey || Math.abs(e.deltaX) > Math.abs(e.deltaY)) {\n return;\n }\n // \uBA38\uB9AC \uC544\uB798 \uACE0\uC815 \uC904 \uC601\uC5ED(pinnedRows)\uCC98\uB7FC \uC548\uC5D0\uC11C \uB530\uB85C \uAD74\uB9AC\uB294 \uC0C1\uC790 \uC704\uC5D0\uC11C\uB294 \uADF8 \uC0C1\uC790\uB97C \uBA3C\uC800 \uAD74\uB9B0\uB2E4 \u2014\n // \uC5EC\uAE30\uC11C \uB9C9\uC73C\uBA74 \uADF8 \uC601\uC5ED\uC758 6\uBC88\uC9F8 \uC904\uBD80\uD130\uB294 \uBCFC \uBC29\uBC95\uC774 \uC5C6\uB2E4. \uB05D\uC5D0 \uB2FF\uC558\uC73C\uBA74 \uBCF8\uBB38\uC744 \uAD74\uB9B0\uB2E4.\n const inner = (e.target as HTMLElement | null)?.closest?.(\"[data-vdt-inner-scroll]\") as HTMLElement | null;\n if (inner && el.contains(inner)) {\n const canScroll =\n e.deltaY < 0\n ? inner.scrollTop > 0\n : inner.scrollTop + inner.clientHeight < inner.scrollHeight - 1;\n if (canScroll) return;\n }\n e.preventDefault();\n let delta = e.deltaY;\n // deltaMode 1 = \uB77C\uC778 \uB2E8\uC704, 2 = \uD398\uC774\uC9C0 \uB2E8\uC704 \uBCC0\uD658\n if (e.deltaMode === 1) {\n delta *= 40;\n } else if (e.deltaMode === 2) {\n delta *= el.clientHeight;\n }\n\n if (perfDebugEnabled) {\n perfStatsRef.current.wheelEvents += 1;\n perfStatsRef.current.wheelInputPx += delta;\n }\n\n wheelDeltaRef.current += delta;\n if (wheelRafRef.current !== null) {\n return;\n }\n\n wheelRafRef.current = requestAnimationFrame(() => {\n const rafStart = perfDebugEnabled\n ? performance.now()\n : 0;\n const maxStep = Math.max(\n el.clientHeight * 0.4,\n 160,\n );\n const batchedDelta = Math.max(\n -maxStep,\n Math.min(maxStep, wheelDeltaRef.current),\n );\n wheelDeltaRef.current = 0;\n wheelRafRef.current = null;\n if (batchedDelta !== 0) {\n el.scrollTop += batchedDelta;\n }\n if (perfDebugEnabled) {\n perfStatsRef.current.wheelRafFlushes += 1;\n perfStatsRef.current.wheelRafMs +=\n performance.now() - rafStart;\n }\n });\n\n if (perfDebugEnabled) {\n perfStatsRef.current.wheelHandlerMs +=\n performance.now() - wheelStart;\n }\n };\n\n el.addEventListener(\"wheel\", handleWheel, {\n passive: false,\n });\n return () => {\n el.removeEventListener(\"wheel\", handleWheel);\n if (wheelRafRef.current !== null) {\n cancelAnimationFrame(wheelRafRef.current);\n wheelRafRef.current = null;\n }\n wheelDeltaRef.current = 0;\n };\n }, []);\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 // \uB178\uC158\uD48D\uC740 \uC88C\uC6B0 \uC5EC\uBC31\uC744 \uC885\uC774(Paper/Box) \uCABD\uC5D0 \uC900\uB2E4 \u2014 \uD14C\uB450\uB9AC\uAC00 \uC5EC\uBC31 \uC548\uCABD\uC5D0 \uADF8\uB824\uC838\uC57C \uD55C\uB2E4.\n paddingRight: notion ? 0 : 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, notion \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 // \uC9C1\uC804\uC5D0 loadMore \uB97C \uC694\uCCAD\uD55C \uC2DC\uC810\uC758 \uB370\uC774\uD130 \uAE38\uC774. \uC694\uCCAD \uD6C4 \uAE38\uC774\uAC00 \uB298\uC9C0 \uC54A\uC558\uB2E4\uBA74\n // (= \uC11C\uBC84\uC5D0 \uB354 \uC774\uC0C1 \uB370\uC774\uD130 \uC5C6\uC74C) \uAC19\uC740 \uAE38\uC774\uB85C\uB294 \uB2E4\uC2DC \uC694\uCCAD\uD558\uC9C0 \uC54A\uC544, \uBC14\uB2E5\uC5D0\uC11C\n // endReached \u2194 onLoadMore \uAC00 \uBB34\uD55C \uBC18\uBCF5\uB418\uB294 \uAC83\uC744 \uB9C9\uB294\uB2E4.\n const lastLoadMoreLengthRef = useRef<number>(-1);\n const virtuosoRef = useRef<any>(null); // TableVirtuoso ref\n // \uC904\uB4E4\uC774 \uC2A4\uD06C\uB864 \uC601\uC5ED\uBCF4\uB2E4 \uAE34\uAC00 \u2014 \uAE38\uBA74 \uB9E8 \uB05D \uC904\uC774 \uD2C0 \uBC14\uB2E5\uC5D0 \uB2FF\uC73C\uBBC0\uB85C \uADF8 \uC904\uC758 \uC544\uB798\uC120\uC744 \uBE80\uB2E4(\uC544\uB798 \uB178\uC158 \uC2A4\uD0C0\uC77C).\n const scrollerElRef = useRef<HTMLElement | null>(null);\n const [listOverflows, setListOverflows] = useState(false);\n const checkListOverflow = useCallback(() => {\n const el = scrollerElRef.current;\n if (el) setListOverflows(el.scrollHeight > el.clientHeight + 1);\n }, []);\n useEffect(() => {\n const el = scrollerElRef.current;\n if (!el || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(() => checkListOverflow());\n observer.observe(el);\n return () => observer.disconnect();\n }, [checkListOverflow, autoHeight]);\n\n // \uC18C\uBE44\uCC98\uAC00 \uC778\uB77C\uC778\uC73C\uB85C \uB118\uAE30\uB294 \uCF5C\uBC31(onRowClick/getRowId)\uC740 \uB9E4 \uB80C\uB354\uB9C8\uB2E4 identity \uAC00 \uBC14\uB010\uB2E4.\n // \uC774\uB97C ref \uB85C \uC7A1\uC544 \uB450\uBA74 VirtuosoTableComponents(memo)\uB97C \uC7AC\uC0DD\uC131\uD558\uC9C0 \uC54A\uC544\uB3C4 \uCD5C\uC2E0 \uCF5C\uBC31\uC744 \uC4F8 \uC218 \uC788\uC5B4,\n // \uAC80\uC0C9/\uD544\uD130\uB85C \uBD80\uBAA8\uAC00 \uB9AC\uB80C\uB354\uB3FC\uB3C4 \uD589(\uBC0F \uC774\uBBF8\uC9C0)\uC774 \uB9AC\uB9C8\uC6B4\uD2B8\uB418\uC9C0 \uC54A\uB294\uB2E4(\uC0AC\uC9C4 \uAE5C\uBE61\uC784 \uBC29\uC9C0).\n const onRowClickRef = useRef(onRowClick);\n onRowClickRef.current = onRowClick;\n const getRowIdRef = useRef(getRowId);\n getRowIdRef.current = getRowId;\n const onRowContextMenuRef = useRef(onRowContextMenu);\n onRowContextMenuRef.current = onRowContextMenu;\n const onEndReachedRef = useRef(onEndReached);\n onEndReachedRef.current = onEndReached;\n // \uACE0\uC815 \uC904(pinnedRows)\uC740 \uBA38\uB9AC \uC548\uC5D0 \uADF8\uB9AC\uB294\uB370 \uBA38\uB9AC \uB0B4\uC6A9\uC774 \uC904 \uBD80\uD488\uBCF4\uB2E4 \uBA3C\uC800 \uB9CC\uB4E4\uC5B4\uC9C4\uB2E4 \u2014 \uC904 \uBD80\uD488\uC740 ref \uB85C \uB2A6\uAC8C \uC7A1\uB294\uB2E4.\n const rowComponentRef = useRef<React.ComponentType<any> | null>(null);\n\n // \uACE0\uC815 \uC5F4(pinned: \"left\")\uC774 \uBD99\uC744 \uC67C\uCABD \uC790\uB9AC \u2014 \uC55E\uCABD \uACE0\uC815 \uC5F4 \uD3ED\uC758 \uD569. \uACE0\uC815 \uC5F4\uC774 \uC544\uB2C8\uBA74 \uC5C6\uB2E4.\n const pinnedLeft = useMemo(() => {\n const map = new Map<string, number>();\n let left = 0;\n columns.forEach((col) => {\n if (col.pinned !== \"left\") return;\n map.set(String(col.id), left);\n left += typeof col.width === \"number\" ? col.width : 0;\n });\n return map;\n }, [columns]);\n // \uD45C \uCD5C\uC18C \uD3ED \u2014 minWidth \uB97C \uC900 \uC5F4\uC774 \uC788\uC744 \uB54C\uB9CC. \uC5F4\uB9C8\uB2E4 width(\uC22B\uC790) \uB610\uB294 minWidth \uC758 \uD569\uC774\uACE0, \uD2C0\uC774 \uC881\uC73C\uBA74 \uAC00\uB85C\uB85C \uBBFC\uB2E4.\n const tableMinWidth = useMemo(() => {\n if (!columns.some((col) => typeof col.minWidth === \"number\")) return undefined;\n return columns.reduce(\n (sum, col) =>\n sum + (typeof col.width === \"number\" ? col.width : typeof col.minWidth === \"number\" ? col.minWidth : 0),\n 0,\n );\n }, [columns]);\n /** \uACE0\uC815 \uC5F4 \uCE78\uC758 sticky \uC790\uB9AC. \uBA38\uB9AC \uCE78\uC740 \uBCF8\uBB38 \uACE0\uC815 \uCE78\uBCF4\uB2E4 \uC704(zIndex 3)\uC5D0 \uC120\uB2E4. */\n const pinnedStyle = useCallback(\n (col: DataColumn<T>, head: boolean): React.CSSProperties => {\n const left = pinnedLeft.get(String(col.id));\n if (left === undefined) return {};\n return { position: \"sticky\", left, zIndex: head ? 3 : 1 };\n },\n [pinnedLeft],\n );\n // truthiness \uAC00 \uBC14\uB00C\uBA74(\uD074\uB9AD \uAC00\uB2A5 \uC5EC\uBD80) hover/cursor \uC2A4\uD0C0\uC77C\uC774 \uB2EC\uB77C\uC9C0\uBBC0\uB85C deps \uC5D0\uB294 boolean \uB9CC \uB123\uB294\uB2E4.\n const hasRowClick = !!onRowClick;\n\n // \uC2A4\uD06C\uB864 \uCEE8\uD14C\uC774\uB108 \uCC38\uC870 (OverlayScrollbar\uC6A9)\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\n useEffect(() => {\n const handleDocumentMouseMove = (event: MouseEvent) => {\n const dx = event.clientX - mouseDownPositionRef.current.x;\n const dy = event.clientY - mouseDownPositionRef.current.y;\n if (Math.sqrt(dx * dx + dy * dy) > ROW_CLICK_DRAG_THRESHOLD_PX) {\n isScrollDraggingRef.current = true;\n }\n };\n\n document.addEventListener(\"mousemove\", handleDocumentMouseMove);\n return () => {\n document.removeEventListener(\"mousemove\", handleDocumentMouseMove);\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 /**\n * \uBA38\uB9AC \uC6B0\uD074\uB9AD \uBA54\uB274(1.4.0). \uC5F4\uC740 \uC694\uC18C\uAC00 \uC544\uB2C8\uB77C id \uB85C \uC954\uB2E4 \u2014 \uAC12\uC744 \uACE0\uB974\uBA74 \uC18C\uBE44\uCC98\uAC00 columns \uB97C \uC0C8\uB85C \uB9CC\uB4E4\uC5B4 \uBA38\uB9AC \uCE78\uC774 \uB2E4\uC2DC \uADF8\uB824\uC9C0\uB294\uB370,\n * \uC694\uC18C\uB97C \uC950\uBA74 \uC61B \uC694\uC18C\uC5D0 \uBD99\uC5B4 \uBA54\uB274\uAC00 \uC5C9\uB6B1\uD55C \uB370\uB85C \uAC00\uAC70\uB098 \uB2EB\uD78C\uB2E4. \uC790\uB9AC\uB3C4 \uC88C\uD45C\uB85C \uB454\uB2E4(\uB204\uB978 x \u00B7 \uBA38\uB9AC \uCE78 \uBC14\uB2E5 y).\n */\n const [headerMenu, setHeaderMenu] = useState<{ colId: string; x: number; y: number } | null>(null);\n const onHeaderContextMenuRef = useRef(onHeaderContextMenu);\n onHeaderContextMenuRef.current = onHeaderContextMenu;\n const onSortRef = useRef(onSort);\n onSortRef.current = onSort;\n\n /**\n * \uBA38\uB9AC \uCE78 \uC6B0\uD074\uB9AD \u2014 \uBE0C\uB77C\uC6B0\uC800 \uBA54\uB274\uB294 \uB298 \uB9C9\uB294\uB2E4(\uBA38\uB9AC\uC5D0\uC11C \"\uB4A4\uB85C \u00B7 \uC0C8\uB85C\uACE0\uCE68\" \uBA54\uB274\uB294 \uC4F8 \uB370\uAC00 \uC5C6\uACE0, \uC815\uB82C \u00B7 \uAC70\uB974\uAE30 \uBA54\uB274\uC640 \uACB9\uCCD0 \uB72C\uB2E4).\n * \uC18C\uBE44\uCC98 \uCC98\uB9AC(headerProps.onContextMenu \u00B7 onHeaderContextMenu)\uAC00 \uBA3C\uC800\uB2E4 \u2014 \uADF8\uCABD\uC774 preventDefault \uD588\uAC70\uB098 true \uB97C \uB3CC\uB824\uC8FC\uBA74 \uAE30\uBCF8 \uBA54\uB274\uB97C \uB744\uC6B0\uC9C0 \uC54A\uB294\uB2E4.\n * \uADF8\uB798\uC11C \uB9C9\uB294 preventDefault \uB294 \uC18C\uBE44\uCC98\uB97C \uBD80\uB978 \uB4A4\uC5D0 \uD55C\uB2E4(\uBA3C\uC800 \uB9C9\uC73C\uBA74 \"\uCC98\uB9AC\uD588\uB2E4\" \uB97C \uAC00\uB824\uB0BC \uC218 \uC5C6\uB2E4).\n */\n const handleHeaderContextMenu = useCallback(\n (col: DataColumn<T> | null, event: React.MouseEvent<HTMLTableCellElement>) => {\n if (!col) {\n event.preventDefault();\n return;\n }\n col.headerProps?.onContextMenu?.(event);\n let handled = event.defaultPrevented;\n if (!handled) handled = onHeaderContextMenuRef.current?.(col, event) === true || event.defaultPrevented;\n event.preventDefault();\n if (handled || col.headerMenu === false) return;\n const canSort = Boolean((col.sortMenu ?? col.sortable) && onSortRef.current);\n if (!canSort && !hasColumnFilter(col)) return;\n const rect = event.currentTarget.getBoundingClientRect();\n setHeaderMenu({ colId: String(col.id), x: event.clientX, y: rect.bottom });\n },\n [],\n );\n\n /** \uBA38\uB9AC\uAE00 \u2014 \uAC70\uB974\uAE30\uAC00 \uAC78\uB9B0 \uC5F4\uC740 \uAC15\uC870\uC0C9 + \uAC70\uB974\uAE30 \uC544\uC774\uCF58(HeadSortFilter \uC640 \uAC19\uC740 \uD45C\uC2DC). */\n const renderHeaderText = useCallback(\n (col: DataColumn<T>) => {\n if (!(col.filterValues && col.filterValues.length > 0)) return col.text;\n return (\n <Box\n component=\"span\"\n sx={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 0.5,\n maxWidth: \"100%\",\n color: \"primary.main\",\n fontWeight: 600,\n verticalAlign: \"middle\",\n }}\n >\n <Box component=\"span\" sx={{ overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }}>\n {col.text}\n </Box>\n <PathIcon d={ICON_PATHS.filter} size={16} />\n </Box>\n );\n },\n [],\n );\n\n // \uC2A4\uD06C\uB864 \uB05D \uADFC\uCC98\uC5D0\uC11C\uB9CC \uCD94\uAC00 \uB85C\uB4DC\uB97C \uC2E4\uD589\uD574 scroll \uD56B\uD328\uC2A4 \uBD80\uB2F4\uC744 \uC904\uC778\uB2E4.\n const handleEndReached = useCallback(\n (endIndex: number) => {\n const rangeStart = perfDebugEnabled ? performance.now() : 0;\n onEndReachedRef.current?.();\n if (!onLoadMore) {\n if (perfDebugEnabled) {\n perfStatsRef.current.rangeChangedCalls += 1;\n perfStatsRef.current.rangeChangedMs +=\n performance.now() - rangeStart;\n }\n return;\n }\n\n if (loading && data.length === 0) {\n if (perfDebugEnabled) {\n perfStatsRef.current.rangeChangedCalls += 1;\n perfStatsRef.current.rangeChangedMs +=\n performance.now() - rangeStart;\n }\n return;\n }\n\n const hasMinimumData = data.length >= 30;\n const nearEnd = endIndex >= data.length - 1;\n\n // \uC9C1\uC804 \uC694\uCCAD \uC774\uD6C4 \uAE38\uC774\uAC00 \uADF8\uB300\uB85C\uBA74(\uC11C\uBC84\uC5D0 \uB354 \uC774\uC0C1 \uB370\uC774\uD130 \uC5C6\uC74C) \uC7AC\uC694\uCCAD\uD558\uC9C0 \uC54A\uB294\uB2E4.\n const alreadyRequestedAtThisLength =\n lastLoadMoreLengthRef.current === data.length;\n\n if (\n nearEnd &&\n hasMinimumData &&\n !isLoadingMoreRef.current &&\n !alreadyRequestedAtThisLength\n ) {\n isLoadingMoreRef.current = true;\n lastLoadMoreLengthRef.current = data.length;\n const offset = data.length;\n const limit = 50;\n onLoadMore(offset, limit);\n }\n\n if (perfDebugEnabled) {\n perfStatsRef.current.rangeChangedCalls += 1;\n perfStatsRef.current.rangeChangedMs +=\n performance.now() - rangeStart;\n }\n },\n [data.length, loading, onLoadMore, perfDebugEnabled],\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 const resetScrollOnDataChangeRef = useRef(resetScrollOnDataChange);\n resetScrollOnDataChangeRef.current = resetScrollOnDataChange;\n // \uC774\uC804 \uB370\uC774\uD130 \uAE38\uC774 / \uCCAB \uD589 \uC2DD\uBCC4\uC790\uB97C \uCD94\uC801\n const prevDataLengthRef = useRef(data.length);\n const prevFirstRowKeyRef = useRef<unknown>(undefined);\n\n // \uB370\uC774\uD130\uAC00 '\uC9C4\uC9DC\uB85C \uAD50\uCCB4'\uB41C \uACBD\uC6B0(\uC815\uB82C/\uD544\uD130/\uC7AC\uC870\uD68C)\uC5D0\uB9CC \uC2A4\uD06C\uB864\uC744 \uB9E8 \uC704\uB85C \uC774\uB3D9\uD55C\uB2E4.\n // \uB2E8\uC21C\uD788 \uAC19\uC740 \uBAA9\uB85D\uC758 \uD56D\uBAA9\uC774 in-place \uB85C \uBC14\uB00C\uC5C8\uC744 \uBFD0(\uCCB4\uD06C\uBC15\uC2A4 \uD1A0\uAE00, \uBB34\uD55C \uC2A4\uD06C\uB864\n // \uBE48 \uACB0\uACFC, \uBD80\uBAA8 \uB9AC\uB80C\uB354\uB85C \uC778\uD55C \uC0C8 \uBC30\uC5F4 \uCC38\uC870 \uB4F1)\uC778\uB370\uB3C4 \uB9E8 \uC704\uB85C \uD280\uB358 \uBB38\uC81C\uB97C \uB9C9\uB294\uB2E4.\n // \u2192 \uCCAB \uD589 \uC2DD\uBCC4\uC790(getRowId)\uC640 \uAE38\uC774\uB85C '\uAD50\uCCB4' \uC5EC\uBD80\uB97C \uD310\uBCC4\uD55C\uB2E4.\n useEffect(() => {\n const prevLength = prevDataLengthRef.current;\n const currentLength = data.length;\n\n // \uCCAB \uD589 \uD0A4: getRowId \uAC00 \uC788\uC73C\uBA74 \uAC12 \uAE30\uBC18(\uCC38\uC870\uAC00 \uB9E4\uBC88 \uBC14\uB00C\uC5B4\uB3C4 \uC548\uC815), \uC5C6\uC73C\uBA74 \uAC1D\uCCB4 \uCC38\uC870.\n const firstRowKey =\n currentLength > 0\n ? getRowIdRef.current\n ? getRowIdRef.current(data[0], 0)\n : (data[0] as unknown)\n : undefined;\n const prevFirstRowKey = prevFirstRowKeyRef.current;\n\n // \uB370\uC774\uD130 \uAE38\uC774\uAC00 \uC99D\uAC00\uD55C \uACBD\uC6B0 (\uBB34\uD55C \uC2A4\uD06C\uB864) - \uC2A4\uD06C\uB864 \uC704\uCE58 \uC720\uC9C0\n if (currentLength > prevLength && prevLength > 0) {\n prevDataLengthRef.current = currentLength;\n prevFirstRowKeyRef.current = firstRowKey;\n return;\n }\n\n // '\uAD50\uCCB4'\uB85C \uD310\uB2E8: \uAE38\uC774\uAC00 \uC904\uC5C8\uAC70\uB098, \uCCAB \uD589 \uC2DD\uBCC4\uC790\uAC00 \uBC14\uB010 \uACBD\uC6B0\uC5D0\uB9CC \uB9E8 \uC704\uB85C.\n // (\uAC19\uC740 \uAE38\uC774 + \uAC19\uC740 \uCCAB \uD589 = in-place \uC5C5\uB370\uC774\uD2B8 \u2192 \uC2A4\uD06C\uB864 \uC720\uC9C0)\n const dataReplaced =\n currentLength < prevLength ||\n (prevLength > 0 && firstRowKey !== prevFirstRowKey);\n\n // \uBAA9\uB85D\uC774 \uAD50\uCCB4(\uC815\uB82C/\uAC80\uC0C9/\uD544\uD130\uB85C 1\uD398\uC774\uC9C0 \uC7AC\uC870\uD68C)\uB418\uBA74 \uB354\uBCF4\uAE30 \uB798\uCE58\uB97C \uD480\uC5B4 \uBB34\uD55C \uC2A4\uD06C\uB864\uC774\n // \uB2E4\uC2DC \uB3D9\uC791\uD558\uAC8C \uD55C\uB2E4. \uB798\uCE58\uB294 \"\uC694\uCCAD\uD55C \uAE38\uC774\uC5D0\uC11C \uC548 \uB298\uBA74 \uC11C\uBC84 \uC18C\uC9C4\"\uC774\uB77C\uB294 \uC804\uC81C\uC778\uB370,\n // \uAD50\uCCB4\uB85C \uAE38\uC774\uAC00 \uC6B0\uC5F0\uD788 \uAC19\uC544\uC9C0\uBA74(\uC608: 100\u219250 \uC774 \uC544\uB2C8\uB77C \uC18C\uC9C4 \uD6C4 \uB2E4\uB978 \uAC80\uC0C9\uC774 50) \uADF8 \uC804\uC81C\uAC00\n // \uAE68\uC838 onLoadMore \uAC00 \uC601\uAD6C\uD788 \uBA48\uCD98\uB2E4. append/\uBE48\uC751\uB2F5\uC740 \uC704 early-return\u00B7\uB3D9\uC77C firstRowKey \uB85C\n // \uAC78\uB7EC\uC9C0\uBBC0\uB85C(=dataReplaced=false) 1.1.29 \uAC00 \uACE0\uCE5C \"\uBC14\uB2E5 \uB5A8\uB9BC\"\uC740 \uB418\uC0B4\uC544\uB098\uC9C0 \uC54A\uB294\uB2E4.\n if (dataReplaced) {\n lastLoadMoreLengthRef.current = -1;\n }\n\n if (virtuosoRef.current && currentLength > 0 && dataReplaced && resetScrollOnDataChangeRef.current) {\n virtuosoRef.current.scrollToIndex({\n index: 0,\n align: \"start\",\n behavior: \"auto\",\n });\n }\n\n prevDataLengthRef.current = currentLength;\n prevFirstRowKeyRef.current = firstRowKey;\n }, [data]);\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 headerRowsContent = 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 {...col.headerProps}\n onContextMenu={(e: React.MouseEvent<HTMLTableCellElement>) => handleHeaderContextMenu(col, e)}\n style={{\n width: col.width,\n minWidth: col.width ?? col.minWidth,\n ...col.style,\n fontWeight: \"bold\",\n position: \"sticky\",\n top: 0,\n zIndex: 2,\n padding: \"16px\",\n ...pinnedStyle(col, true),\n ...col.headerProps?.style,\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 {renderHeaderText(col)}\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 renderHeaderText(col)\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 {...col.headerProps}\n onContextMenu={(e: React.MouseEvent<HTMLTableCellElement>) => handleHeaderContextMenu(col, e)}\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 ...pinnedStyle(col, true),\n ...col.headerProps?.style,\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 {renderHeaderText(col)}\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 renderHeaderText(col)\n )}\n </TableCell>\n )),\n ...Object.entries(groupMap).map(([group, cols]) => (\n <TableCell\n key={group}\n align=\"center\"\n colSpan={cols.length}\n onContextMenu={(e: React.MouseEvent<HTMLTableCellElement>) => handleHeaderContextMenu(null, e)}\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 {...col.headerProps}\n onContextMenu={(e: React.MouseEvent<HTMLTableCellElement>) => handleHeaderContextMenu(col, e)}\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 ...pinnedStyle(col, true),\n ...col.headerProps?.style,\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 {renderHeaderText(col)}\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 renderHeaderText(col)\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, pinnedStyle, handleHeaderContextMenu, renderHeaderText]);\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 const rowStart = perfDebugEnabled ? performance.now() : 0;\n // console.log(\"rowContent \uB80C\uB354\uB9C1:\", { index, item: item ? \"\uC788\uC74C\" : \"\uC5C6\uC74C\" });\n\n if (!item) {\n if (perfDebugEnabled) {\n perfStatsRef.current.rowContentCalls += 1;\n const rowDuration = performance.now() - rowStart;\n perfStatsRef.current.rowContentMs += rowDuration;\n perfStatsRef.current.rowContentMaxMs = Math.max(\n perfStatsRef.current.rowContentMaxMs,\n rowDuration,\n );\n }\n return null;\n }\n\n // \uD55C \uCE78 \uC904(\uBB36\uC74C \uBA38\uB9AC \uB4F1) \u2014 \uBAA8\uB4E0 \uC5F4\uC744 \uD569\uCE5C \uCE78 \uD558\uB098. \uC5EC\uBC31 \u00B7 \uBC14\uD0D5\uC740 fullWidthRowSx \uAC00 \uC815\uD55C\uB2E4.\n const fullWidth = renderFullWidthRow\n ? renderFullWidthRow(item, index)\n : null;\n if (fullWidth !== null && fullWidth !== undefined) {\n return (\n <TableCell\n colSpan={columns.length}\n data-vdt-pad=\"\"\n sx={[\n { padding: notion ? \"0 14px\" : \"8px 16px\" },\n ...(Array.isArray(fullWidthRowSx)\n ? fullWidthRowSx\n : fullWidthRowSx\n ? [fullWidthRowSx]\n : []),\n ]}\n >\n {fullWidth}\n </TableCell>\n );\n }\n\n // \uC624\uB978\uCABD\uC73C\uB85C \uD569\uCE5C \uCE78(colSpan)\uC5D0 \uB36E\uC778 \uC5F4 \uC218 \u2014 \uADF8\uB9CC\uD07C \uB2E4\uC74C \uC5F4\uB4E4\uC758 \uCE78\uC744 \uADF8\uB9AC\uC9C0 \uC54A\uB294\uB2E4.\n let coveredByColSpan = 0;\n const cells = columns.map((column, columnIndex) => {\n if (coveredByColSpan > 0) {\n coveredByColSpan -= 1;\n return null;\n }\n const colSpan = column.colSpan\n ? Math.max(1, Math.min(column.colSpan(item, index), columns.length - columnIndex))\n : 1;\n coveredByColSpan = colSpan - 1;\n const cellStart = perfDebugEnabled ? performance.now() : 0;\n const cellValue = column.render\n ? column.render(item, index)\n : String((item as any)[column.id] || \"\");\n\n if (perfDebugEnabled) {\n const cellDuration = performance.now() - cellStart;\n perfStatsRef.current.cellRenderCalls += 1;\n perfStatsRef.current.cellRenderMs += cellDuration;\n perfStatsRef.current.cellRenderMaxMs = Math.max(\n perfStatsRef.current.cellRenderMaxMs,\n cellDuration,\n );\n }\n\n const pinned = pinnedLeft.has(String(column.id));\n const customPadding = column.cellPadding !== undefined;\n // \uC544\uB798\uB85C \uD569\uCE5C \uCE78\uC5D0 \uB36E\uC778 \uC904\uC740 \uCE78\uC744 \uADF8\uB9AC\uC9C0 \uC54A\uB294\uB2E4.\n const span = column.rowSpan ? column.rowSpan(item, index) : 1;\n if (span <= 0) return null;\n const onCellClick = column.onCellClick;\n return (\n <TableCell\n key={String(column.id)}\n align={column.align || \"left\"}\n rowSpan={span > 1 ? span : undefined}\n colSpan={colSpan > 1 ? colSpan : undefined}\n data-vdt-pad={customPadding ? \"\" : undefined}\n data-vdt-pinned={pinned ? \"\" : undefined}\n data-vdt-cell-click={onCellClick ? \"\" : undefined}\n onClick={\n onCellClick\n ? (e: React.MouseEvent) => {\n // \uB04C\uC5B4\uC11C \uBBFC \uB4A4\uC758 \uD074\uB9AD\uC740 \uCE78 \uB204\uB984\uC73C\uB85C \uCE58\uC9C0 \uC54A\uB294\uB2E4(\uC904 \uD074\uB9AD\uACFC \uAC19\uC740 \uAE30\uC900).\n const dx = e.clientX - mouseDownPositionRef.current.x;\n const dy = e.clientY - mouseDownPositionRef.current.y;\n e.stopPropagation();\n if (Math.sqrt(dx * dx + dy * dy) > ROW_CLICK_DRAG_THRESHOLD_PX) return;\n onCellClick(item, index, e);\n }\n : undefined\n }\n style={{\n // \uD569\uCE5C \uCE78\uC740 \uD3ED\uC744 \uBC15\uC9C0 \uC54A\uB294\uB2E4 \u2014 \uC5F4 \uD3ED\uC740 \uBA38\uB9AC \uC904\uC774 \uC815\uD558\uACE0, \uBC15\uC73C\uBA74 \uD569\uCE5C \uD3ED\uC774 \uD55C \uC5F4 \uD3ED\uC73C\uB85C \uC904\uC5B4\uB4E0\uB2E4.\n ...(colSpan > 1 ? {} : { width: column.width, minWidth: column.width ?? column.minWidth }),\n ...(column.primary ? { fontSize: 15 } : {}),\n ...column.style,\n ...(column.cellStyle ? column.cellStyle(item, index) : {}),\n padding: customPadding ? column.cellPadding : \"8px 16px\",\n ...pinnedStyle(column, false),\n }}\n >\n {cellValue}\n </TableCell>\n );\n });\n\n if (perfDebugEnabled) {\n perfStatsRef.current.rowContentCalls += 1;\n const rowDuration = performance.now() - rowStart;\n perfStatsRef.current.rowContentMs += rowDuration;\n perfStatsRef.current.rowContentMaxMs = Math.max(\n perfStatsRef.current.rowContentMaxMs,\n rowDuration,\n );\n }\n\n return <>{cells}</>;\n },\n [columns, perfDebugEnabled, renderFullWidthRow, fullWidthRowSx, notion, pinnedLeft, pinnedStyle],\n );\n\n /**\n * \uBA38\uB9AC \uB0B4\uC6A9 = \uBA38\uB9AC \uC904 + (\uC788\uC73C\uBA74) \uACE0\uC815 \uC904 \uC601\uC5ED. \uACE0\uC815 \uC904\uC740 \uBA38\uB9AC(thead)\uC640 \uD568\uAED8 \uC704\uC5D0 \uBD99\uC5B4 \uBCF8\uBB38 \uC2A4\uD06C\uB864\uACFC \uBB34\uAD00\uD558\uAC8C \uBCF4\uC778\uB2E4.\n * \uBA38\uB9AC \uC548\uC5D0 \uBCF8\uBB38 \uCE78\uC744 \uADF8\uB9AC\uB824\uBA74 \uD55C \uCE78(colSpan \uC804\uCCB4) \uC548\uC5D0 \uAC19\uC740 \uC5F4 \uAD6C\uC131\uC758 \uD45C\uB97C \uD558\uB098 \uB354 \uB454\uB2E4 \u2014 \uC5F4 \uD3ED\uC740 colgroup \uC73C\uB85C \uBC14\uAE65 \uD45C\uC640 \uB9DE\uCD94\uACE0\n * (\uCCAB \uC904\uC774 \uBB36\uC74C \uB760 \uC904\uC774\uBA74 \uADF8 \uC904\uB85C\uB294 \uC5F4 \uD3ED\uC744 \uBABB \uC815\uD55C\uB2E4), \uAC00\uB85C\uB85C \uBC00\uBA74 \uBC14\uAE65 \uD45C\uC640 \uD568\uAED8 \uC6C0\uC9C1\uC778\uB2E4.\n * \uC548\uCABD tbody \uB97C MUI TableBody \uB85C \uAC10\uC2F8\uC57C \uCE78\uC774 \uBA38\uB9AC \uCE78(th)\uC774 \uC544\uB2C8\uB77C \uBCF8\uBB38 \uCE78(td)\uC73C\uB85C \uADF8\uB824\uC9C4\uB2E4.\n */\n const fixedHeaderContent = useCallback(() => {\n const headerRows = headerRowsContent();\n if (!pinnedRows || pinnedRows.length === 0) return headerRows;\n const RowComponent = rowComponentRef.current;\n return (\n <>\n {headerRows}\n <tr data-vdt-pinned-area=\"\">\n <td colSpan={columns.length} style={{ padding: 0, border: 0 }}>\n <Box\n data-vdt-inner-scroll=\"\"\n sx={[\n {\n maxHeight: pinnedRowsMaxHeight,\n overflowY: pinnedRowsMaxHeight ? \"auto\" : \"visible\",\n overflowX: \"hidden\",\n scrollbarWidth: \"thin\",\n borderBottom: `1px solid ${notion ? notionTokens.borderStrong : \"rgba(224, 224, 224, 1)\"}`,\n // \uC601\uC5ED \uC544\uB7AB\uC120\uC774 \uACBD\uACC4\uB97C \uB9E1\uB294\uB2E4 \u2014 \uB9C8\uC9C0\uB9C9 \uC904 \uC544\uB798\uC120\uAE4C\uC9C0 \uADF8\uC73C\uBA74 \uC774\uC911\uC120\uC774\uB2E4.\n \"& tbody tr:last-of-type > td\": { borderBottom: \"none\" },\n },\n ...(Array.isArray(pinnedRowsSx) ? pinnedRowsSx : pinnedRowsSx ? [pinnedRowsSx] : []),\n ]}\n >\n <table\n style={{\n width: \"100%\",\n tableLayout,\n borderCollapse: \"separate\",\n borderSpacing: 0,\n }}\n >\n <colgroup>\n {columns.map((col) => (\n <col key={String(col.id)} style={{ width: col.width, minWidth: col.width ?? col.minWidth }} />\n ))}\n </colgroup>\n <MuiTableBody>\n {pinnedRows.map((item, index) =>\n RowComponent ? (\n <RowComponent\n key={getRowId ? String(getRowId(item, index)) : `p${index}`}\n item={item}\n data-index={index}\n data-vdt-pinned-row=\"\"\n >\n {rowContent(index, item)}\n </RowComponent>\n ) : null,\n )}\n </MuiTableBody>\n </table>\n </Box>\n </td>\n </tr>\n </>\n );\n }, [headerRowsContent, pinnedRows, pinnedRowsMaxHeight, pinnedRowsSx, columns, rowContent, tableLayout, getRowId, notion, notionTokens]);\n\n // \uCEEC\uB7FC\uC5D0 footer \uB80C\uB354\uB7EC\uAC00 \uD558\uB098\uB77C\uB3C4 \uC788\uAC70\uB098 showFooter \uAC00 \uBA85\uC2DC\uB418\uBA74 \uD558\uB2E8 \uD569\uACC4 \uD589\uC744 \uD45C\uC2DC\uD55C\uB2E4.\n const hasFooter =\n showFooter ?? columns.some((col) => typeof col.footer === \"function\");\n\n /**\n * \uD14C\uC774\uBE14 \uD558\uB2E8 \uACE0\uC815 \uD569\uACC4 \uD589(tfoot) \uCEE8\uD150\uCE20 \uC815\uC758\n * \uAC01 \uCEEC\uB7FC\uC758 footer(data) \uACB0\uACFC\uB97C \uC140\uB85C \uB80C\uB354\uB9C1\uD55C\uB2E4. (footer \uC5C6\uB294 \uCEEC\uB7FC\uC740 \uBE48 \uC140)\n * tableLayout: fixed \uB77C \uD5E4\uB354/\uBC14\uB514\uC640 \uB3D9\uC77C\uD55C \uCEEC\uB7FC \uB108\uBE44\uB85C \uC790\uB3D9 \uC815\uB82C\uB41C\uB2E4.\n */\n const fixedFooterContent = useCallback(() => {\n if (!hasFooter) {\n return null;\n }\n\n // footerColSpan \uC73C\uB85C \uC140\uC744 \uBCD1\uD569\uD55C\uB2E4. \uC55E \uCEEC\uB7FC\uC774 colSpan \uC73C\uB85C \uB36E\uC740 \uCEEC\uB7FC\uC740 \uC140\uC744 \uC0DD\uB7B5\uD55C\uB2E4.\n const cells: React.ReactNode[] = [];\n for (let i = 0; i < columns.length; i += 1) {\n const col = columns[i];\n const colSpan =\n col.footerColSpan && col.footerColSpan > 1\n ? Math.min(col.footerColSpan, columns.length - i)\n : 1;\n\n cells.push(\n <TableCell\n key={String(col.id)}\n align={col.align || \"left\"}\n colSpan={colSpan > 1 ? colSpan : undefined}\n style={{\n // \uBCD1\uD569 \uC2DC \uB108\uBE44 \uACE0\uC815\uC744 \uD480\uC5B4 colSpan \uC774 \uC2E4\uC81C\uB85C \uB298\uC5B4\uB098\uAC8C \uD55C\uB2E4.\n ...(colSpan > 1\n ? {}\n : { width: col.width, minWidth: col.width }),\n ...col.style,\n fontWeight: \"bold\",\n // \uB178\uC158\uD48D\uC740 \uBCF8\uBB38 \uCE78\uACFC \uAC19\uC740 \uC88C\uC6B0 \uC5EC\uBC31 \u00B7 \uC138\uB85C 0(\uC904 \uB192\uC774\uB85C \uAC00\uC6B4\uB370) \u2014 16px \uC774\uBA74 \uD569\uACC4 \uC904\uB9CC \uB192\uACE0 \uAE00\uC790\uAC00 \uCE78\uACFC \uC5B4\uAE0B\uB0AC\uB2E4.\n padding: notion ? \"0 14px\" : \"16px\",\n }}\n >\n {col.footer ? col.footer(data) : null}\n </TableCell>,\n );\n\n // colSpan \uC73C\uB85C \uB36E\uC778 \uB4A4 \uCEEC\uB7FC\uC740 \uAC74\uB108\uB6F4\uB2E4.\n i += colSpan - 1;\n }\n\n return <MuiTableRow>{cells}</MuiTableRow>;\n }, [hasFooter, columns, data, notion]);\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,\n ...(tableMinWidth ? { minWidth: tableMinWidth } : {}),\n // \uD2C0 \uC5C6\uC774 \uADF8\uB9B4 \uB54C\uB294 \uC624\uB978\uCABD \uB367\uC5EC\uBC31\uC774 \uAC00\uB85C \uB118\uCE68(\uAC00\uB85C \uB9C9\uB300)\uC744 \uB9CC\uB4E0\uB2E4 \u2014 \uD45C\uAC00 \uC0C1\uC790 \uD3ED\uC5D0 \uAF2D \uB9DE\uAC8C \uB454\uB2E4.\n marginRight: framed ? \"16px\" : 0,\n // \uD558\uB2E8 \uD569\uACC4 \uD589\uC774 \uC788\uC73C\uBA74 \uB370\uC774\uD130\uAC00 \uC801\uC5B4\uB3C4 \uD14C\uC774\uBE14\uC774 \uCEE8\uD14C\uC774\uB108\uB97C \uCC44\uC6B0\uAC8C \uD55C\uB2E4.\n // (\uC2E4\uC81C \uBC14\uB2E5 \uC815\uB82C\uC740 tbody \uAC00 \uB298\uC5B4\uB098\uBA70 \uCC98\uB9AC \u2014 \uD589 \uB192\uC774\uB294 \uADF8\uB300\uB85C \uC720\uC9C0)\n ...(hasFooter ? { height: \"100%\" } : {}),\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 // \uBC14\uB85C \uC544\uB798 \uC904(\uBA38\uB9AC \uC904)\uB9CC \u2014 \uBA38\uB9AC \uC548 \uACE0\uC815 \uC904 \uC601\uC5ED(pinnedRows)\uC758 \uC904\uAE4C\uC9C0 \uBA38\uB9AC \uB192\uC774 \u00B7 \uAD75\uAE30\uB97C \uBC1B\uC73C\uBA74 \uC548 \uB41C\uB2E4.\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 {\n item,\n selected: _selected,\n \"aria-selected\": _ariaSelected,\n className,\n ...rest\n } = 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 const rowId =\n item && getRowIdRef.current\n ? getRowIdRef.current(item, rowIndex)\n : rowIndex;\n // CSS \uD558\uC774\uB77C\uC774\uD2B8 \uBAA8\uB4DC\uC5D0\uC11C\uB294 \uD589 \uC790\uCCB4\uC5D0\uC11C \uC120\uD0DD\uC744 \uACC4\uC0B0\uD558\uC9C0 \uC54A\uB294\uB2E4(\uCEE8\uD14C\uC774\uB108 CSS \uAC00 \uCC98\uB9AC).\n // \u2192 selectedRowId \uBCC0\uACBD\uC774 \uD589 \uC7AC\uB80C\uB354\uB85C \uC774\uC5B4\uC9C0\uC9C0 \uC54A\uB294\uB2E4.\n const isSelected =\n !useCssRowHighlight &&\n selectedRowId !== null &&\n selectedRowId !== undefined &&\n rowId === selectedRowId;\n const resolvedSelectedRowSx =\n isSelected && selectedRowSx\n ? typeof selectedRowSx === \"function\"\n ? selectedRowSx(item, rowIndex)\n : selectedRowSx\n : undefined;\n const sanitizedClassName = String(className ?? \"\")\n .split(/\\s+/)\n .filter(\n (token) =>\n token !== \"Mui-selected\" &&\n token !== \"Mui-focusVisible\",\n )\n .join(\" \");\n\n return (\n <MuiTableRow\n {...rest}\n data-row-id={rowId !== null && rowId !== undefined ? String(rowId) : undefined}\n className={sanitizedClassName || undefined}\n selected={isSelected}\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 onContextMenu={(e: React.MouseEvent) => {\n if (item && onRowContextMenuRef.current) {\n onRowContextMenuRef.current(item, rowIndex, e);\n }\n }}\n onClick={(e: React.MouseEvent) => {\n // mousedown \uC2DC\uC791 \uC704\uCE58\uC640 click \uC704\uCE58 \uCC28\uC774\uB85C \uB4DC\uB798\uADF8 \uC5EC\uBD80 \uD310\uBCC4\n const dx =\n e.clientX - mouseDownPositionRef.current.x;\n const dy =\n e.clientY - mouseDownPositionRef.current.y;\n const wasDrag =\n Math.sqrt(dx * dx + dy * dy) >\n ROW_CLICK_DRAG_THRESHOLD_PX ||\n isScrollDraggingRef.current;\n if (wasDrag) {\n e.preventDefault();\n e.stopPropagation();\n isScrollDraggingRef.current = false;\n return;\n }\n if (item && onRowClickRef.current) {\n onRowClickRef.current(item, rowIndex);\n }\n isScrollDraggingRef.current = false;\n }}\n sx={[\n {\n userSelect: \"none\",\n // \uD589 \uB192\uC774\uB97C estimatedItemHeight(=rowHeight + divider) \uB85C \uC815\uD655\uD788\n // \uACE0\uC815\uD55C\uB2E4. react-virtuoso \uB294 fixedItemHeight \uB97C \uC918\uB3C4\n // ResizeObserver \uB85C \uC2E4\uC81C \uD589 \uB192\uC774\uB97C \uC7AC\uCE21\uC815\uD574 \uBC18\uC601\uD558\uB294\uB370, \uC140\n // \uD3F0\uD2B8/\uB77C\uC778\uC758 \uC11C\uBE0C\uD53D\uC140 \uB54C\uBB38\uC5D0 \uCE21\uC815\uAC12\uC774 \uC815\uC218\uC5D0\uC11C \uC5B4\uAE0B\uB098\uBA74\n // \uD558\uB2E8 filler row \uB192\uC774(offsetBottom)\uAC00 \uC2A4\uD06C\uB864\uB9C8\uB2E4 \uC18C\uC218\uC810\uC73C\uB85C\n // \uD754\uB4E4\uB9AC\uACE0, \uADF8 \uC704\uC5D0 sticky \uB85C \uBD99\uC740 <tfoot> \uD569\uACC4\uD589\uC774 1px \uB5A8\uB9B0\uB2E4.\n // height/maxHeight \uB97C \uC815\uC218\uB85C \uBC15\uACE0 overflow:hidden \uC73C\uB85C \uB9C9\uC544\n // \uCE21\uC815\uAC12\uC774 \uD56D\uC0C1 estimatedItemHeight \uAC00 \uB418\uAC8C \uD55C\uB2E4.\n // \uC904 \uB192\uC774 \"auto\" \uB294 \uB0B4\uC6A9\uB9CC\uD07C \uB298\uC5B4\uB09C\uB2E4 \u2014 \uCE78 \uB192\uC774(rowHeight)\uAC00 \uCD5C\uC18C \uB192\uC774\uB85C \uB3D9\uC791\uD55C\uB2E4.\n ...(autoRowHeight\n ? { \"& > td\": { height: estimatedItemHeight } }\n : {\n height: estimatedItemHeight,\n maxHeight: estimatedItemHeight,\n }),\n boxSizing: \"border-box\",\n backgroundColor:\n isOddRow && stripedRowColor\n ? stripedRowColor\n : \"transparent\",\n // \uC5EC\uBC31\uC744 \uB530\uB85C \uBC1B\uC740 \uCE78(cellPadding \u00B7 \uD55C \uCE78 \uC904)\uC740 \uAE30\uBCF8 \uC5EC\uBC31\uC5D0\uC11C \uBE80\uB2E4.\n \"& td:not([data-vdt-pad])\": {\n padding: \"8px 16px\",\n },\n \"& td\": {\n boxSizing: \"border-box\",\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\":\n hasRowClick && !isSelected\n ? {\n backgroundColor: (theme) => {\n const isDark =\n theme.palette.mode ===\n \"dark\";\n const defaultColor =\n \"#000000\";\n const color =\n rowHoverColor ??\n defaultColor;\n const opacity =\n rowHoverOpacity ?? 0.06;\n\n if (!rowHoverColor) {\n return isDark\n ? `rgba(255, 255, 255, ${opacity})`\n : `rgba(0, 0, 0, ${opacity})`;\n }\n\n const hex = color\n .replace(\"#\", \"\")\n .trim();\n if (hex.length !== 6) {\n return color;\n }\n\n const r = parseInt(\n hex.substring(0, 2),\n 16,\n );\n const g = parseInt(\n hex.substring(2, 4),\n 16,\n );\n const b = parseInt(\n hex.substring(4, 6),\n 16,\n );\n\n return `rgba(${r}, ${g}, ${b}, ${opacity})`;\n },\n }\n : undefined,\n cursor: hasRowClick ? \"pointer\" : undefined,\n },\n resolvedSelectedRowSx,\n ]}\n />\n );\n },\n // \uD14C\uC774\uBE14 \uBC14\uB514 \u2014 \uD558\uB2E8 \uD569\uACC4 \uD589\uC774 \uC788\uC73C\uBA74 row-group \uC744 \uB298\uB824 \uBE48 \uACF5\uAC04\uC774 \uB9C8\uC9C0\uB9C9 \uD589 '\uC544\uB798'\uB85C \uAC00\uAC8C \uD55C\uB2E4.\n // (\uAC1C\uBCC4 \uD589 \uB192\uC774\uB294 \uADF8\uB300\uB85C \uC720\uC9C0\uB418\uACE0, tfoot \uC740 \uADF8 \uC544\uB798 \uBC14\uB2E5\uC5D0 \uBD99\uB294\uB2E4)\n TableBody: forwardRef<HTMLTableSectionElement>((props, ref) => {\n const { children, ...rest } =\n props as React.HTMLAttributes<HTMLTableSectionElement>;\n return (\n <MuiTableBody\n {...rest}\n ref={ref}\n sx={hasFooter ? { height: \"100%\" } : undefined}\n >\n {children}\n {/* fill \uBAA8\uB4DC(hasFooter)\uC5D0\uC11C table/tbody \uC758 height:100% \uB54C\uBB38\uC5D0 \uB0A8\uB294 \uB192\uC774\uAC00\n \uB370\uC774\uD130 <tr> \uC5D0 \uBD84\uBC30\uB418\uC5B4 \uD589\uC774 rowHeight \uBCF4\uB2E4 \uCEE4\uC9C0\uB294 \uBB38\uC81C\uB97C \uB9C9\uB294 spacer.\n \uC720\uC5F0\uD55C \uBE48 \uD589\uC774 \uB0A8\uB294 \uACF5\uAC04\uC744 \uD761\uC218 \u2192 \uB370\uC774\uD130 \uD589\uC740 rowHeight \uB85C \uACE0\uC815\uB418\uACE0,\n sticky footer \uB294 \uADF8 \uC544\uB798 \uBC14\uB2E5\uC5D0 \uBD99\uB294\uB2E4. \uC2A4\uD06C\uB864\uC774 \uC0DD\uAE30\uBA74 0 \uC73C\uB85C \uC811\uD78C\uB2E4. */}\n {hasFooter && (\n <tr aria-hidden style={{ height: \"100%\" }}>\n <td\n colSpan={columns.length}\n style={{ padding: 0, border: 0 }}\n />\n </tr>\n )}\n </MuiTableBody>\n );\n }),\n // \uD14C\uC774\uBE14 \uD558\uB2E8 \uD569\uACC4 \uD589(tfoot) \u2014 \uBC14\uB2E5\uC5D0 \uACE0\uC815\n TableFoot: forwardRef<HTMLTableSectionElement, any>(\n (props, ref) => (\n <MuiTableFooter\n {...props}\n ref={ref}\n sx={[\n {\n // \uB5A8\uB9BC\uC758 \uADFC\uBCF8 \uC6D0\uC778(\uB370\uC774\uD130 \uD589 \uCE21\uC815 \uB192\uC774\uC758 \uC11C\uBE0C\uD53D\uC140)\uC740 TableRow\n // \uC5D0\uC11C height/maxHeight \uC815\uC218 \uACE0\uC815\uC73C\uB85C \uC7A1\uB294\uB2E4. \uC5EC\uAE30\uC11C\uB294 \uD569\uACC4\uD589\n // \uC140 \uC2A4\uD0C0\uC77C\uB9CC \uB454\uB2E4(virtuoso \uAC00 <tfoot> \uC5D0 \uC9C1\uC811 sticky \uB97C \uAC74\uB2E4).\n // \uD569\uACC4\uD589 \uB192\uC774\uB97C footerHeight(\uBBF8\uC9C0\uC815 \uC2DC rowHeight) \uB85C \uC815\uD655\uD788\n // \uACE0\uC815\uD55C\uB2E4. \uADF8\uB798\uC57C \uB85C\uB529 \uC624\uBC84\uB808\uC774\uC758 \uD558\uB2E8 \uCEF7\uC624\uD504(bottom:\n // footerHeight ?? rowHeight)\uC640 \uC2E4\uC81C footer \uB192\uC774\uAC00 \uC77C\uCE58\uD574\n // \uC624\uBC84\uB808\uC774\uAC00 footer \uC704\uAE4C\uC9C0\uB9CC \uB0B4\uB824\uC624\uACE0 footer \uB97C \uB36E\uC9C0 \uC54A\uB294\uB2E4.\n \"& tr\": {\n height: footerHeight ?? rowHeight,\n maxHeight: footerHeight ?? rowHeight,\n boxSizing: \"border-box\",\n },\n \"& td\": {\n height: footerHeight ?? rowHeight,\n boxSizing: \"border-box\",\n backgroundColor: (theme) =>\n theme.palette.mode === \"dark\"\n ? \"#1e1e1e\"\n : \"#ffffff\",\n // \uC138\uB85C padding \uC744 0 \uC73C\uB85C \uB450\uACE0 \uD589 \uB192\uC774\uB85C \uC815\uB82C\uC744 \uB9E1\uAE34\uB2E4.\n // (\uAC00\uB85C 16px \uC720\uC9C0) \u2014 16px \uC138\uB85C padding \uC774\uBA74 \uC2E4\uC81C footer \uAC00\n // footerHeight \uBCF4\uB2E4 \uCEE4\uC838 \uC624\uBC84\uB808\uC774 \uCEF7\uC624\uD504\uC640 \uC5B4\uAE0B\uB09C\uB2E4.\n padding: \"0 16px\",\n color: \"inherit\",\n fontSize: \"0.875rem\",\n // \uAD6C\uBD84\uC120\uC740 \uC2E4\uC81C border \uB300\uC2E0 inset box-shadow \uB85C \uADF8\uB9B0\uB2E4.\n // collapsed-border \uD53D\uC140 \uACBD\uACC4 \uACF5\uC720\uB85C \uC778\uD55C \uAE5C\uBE61\uC784\uC744 \uD53C\uD55C\uB2E4.\n border: \"none\",\n // \uB178\uC158\uD48D\uC740 \uBA38\uB9AC \uC544\uB798 \uC120\uACFC \uAC19\uC740 \uC9C4\uD55C \uD68C\uC0C9 \uC120 \u2014 \uAC80\uC740 \uC120\uC740 \uC605\uC740 \uD45C\uC5D0\uC11C \uD63C\uC790 \uD280\uC5C8\uB2E4.\n boxShadow: `inset 0 1px 0 0 ${notion ? notionTokens.borderStrong : \"#000000\"}`,\n },\n },\n ...(Array.isArray(footerSx)\n ? footerSx\n : footerSx\n ? [footerSx]\n : []),\n ]}\n />\n ),\n ),\n }),\n [\n // onRowClick/getRowId \uB294 ref \uB85C \uCC98\uB9AC\uD558\uBBC0\uB85C deps \uC5D0\uC11C \uC81C\uC678(\uC778\uB77C\uC778 \uCF5C\uBC31\uC774\uC5B4\uB3C4 \uD589 \uB9AC\uB9C8\uC6B4\uD2B8 \uC548 \uB428).\n hasRowClick,\n // CSS \uD558\uC774\uB77C\uC774\uD2B8 \uBAA8\uB4DC\uC5D0\uC11C\uB294 selectedRowId \uAC00 components \uB97C \uC7AC\uC0DD\uC131\uD558\uC9C0 \uC54A\uAC8C \uD55C\uB2E4(\uD589 \uC7AC\uB80C\uB354 \uBC29\uC9C0).\n // \uD568\uC218\uD615 selectedRowSx(per-row) \uC77C \uB54C\uB9CC selectedRowId \uBCC0\uACBD\uC73C\uB85C components \uB97C \uAC31\uC2E0\uD55C\uB2E4.\n useCssRowHighlight ? null : selectedRowId,\n selectedRowSx,\n rowHeight,\n stripedRowColor,\n rowDivider,\n columnHeight,\n rowHoverColor,\n rowHoverOpacity,\n VirtuosoScroller,\n footerHeight,\n footerSx,\n hasFooter,\n notion,\n notionTokens,\n // spacer \uD589\uC758 colSpan \uACC4\uC0B0\uC5D0 \uC0AC\uC6A9 (\uCEEC\uB7FC \uAD6C\uC870 \uBCC0\uACBD \uC2DC components \uC7AC\uC0DD\uC131)\n columns,\n tableLayout,\n framed,\n autoRowHeight,\n tableMinWidth,\n ],\n );\n rowComponentRef.current = (VirtuosoTableComponents as Record<string, unknown>).TableRow as React.ComponentType<any>;\n\n const resolvedVirtuosoComponents = VirtuosoTableComponents;\n // autoHeight \uB294 \uAC19\uC740 \uD45C \uBD80\uD488(\uBA38\uB9AC \u00B7 \uC904 \u00B7 \uD569\uACC4)\uC744 \uAC00\uC0C1\uD654 \uC5C6\uC774 \uADF8\uB300\uB85C \uC4F4\uB2E4 \u2014 \uCE78 \uBAA8\uC591\uC774 \uAC00\uC0C1 \uD45C\uC640 \uAC19\uB2E4.\n const autoParts = VirtuosoTableComponents as Record<string, unknown>;\n const AutoTable = autoParts.Table as React.ComponentType<any>;\n const AutoTableHead = autoParts.TableHead as React.ComponentType<any>;\n const AutoTableBody = autoParts.TableBody as React.ComponentType<any>;\n const AutoTableRow = autoParts.TableRow as React.ComponentType<any>;\n const AutoTableFoot = autoParts.TableFoot as React.ComponentType<any>;\n\n // \uBA38\uB9AC \uC6B0\uD074\uB9AD \uBA54\uB274 \u2014 \uC5F4\uC740 \uB9E4 \uB80C\uB354 columns \uC5D0\uC11C \uB2E4\uC2DC \uCC3E\uB294\uB2E4(\uACE0\uB978 \uAC12 \u00B7 \uC815\uB82C \uD45C\uC2DC\uAC00 \uBC14\uB85C \uB530\uB77C\uC624\uAC8C). \uC5F4\uC774 \uC0AC\uB77C\uC84C\uC73C\uBA74 \uADF8\uB9AC\uC9C0 \uC54A\uB294\uB2E4.\n const menuColumn = headerMenu ? columns.find((col) => String(col.id) === headerMenu.colId) : undefined;\n const closeHeaderMenu = () => setHeaderMenu(null);\n let headerMenuNode: React.ReactNode = null;\n if (headerMenu && menuColumn) {\n const colId = String(menuColumn.id);\n const canSort = Boolean((menuColumn.sortMenu ?? menuColumn.sortable) && onSort);\n const canFilter = hasColumnFilter(menuColumn);\n const activeSort = sortBy === colId ? sortDirection : undefined;\n const picked = menuColumn.filterValues ?? [];\n const multiple = menuColumn.filterMultiple !== false;\n // 14px \uD56D\uBAA9 \u2014 \uC571\uC758 \uBA38\uB9AC \uBA54\uB274(HeadSortFilter)\uC640 \uAC19\uC740 \uD06C\uAE30 \u00B7 \uC544\uC774\uCF58 18px.\n const itemSx = { gap: 1, fontSize: 14, minHeight: 36 };\n // \uC815\uB82C\uC740 \uD55C \uBC88 \uACE0\uB974\uBA74 \uB05D\uC774\uB77C \uB2EB\uB294\uB2E4. \uAC19\uC740 \uBC29\uD5A5\uC744 \uB2E4\uC2DC \uACE0\uB974\uBA74 \uD480\uAE30(onSortClear \uAC00 \uC788\uC744 \uB54C).\n const pickSort = (direction: SortDirection) => {\n closeHeaderMenu();\n if (activeSort === direction) {\n onSortClear?.();\n return;\n }\n onSort?.(colId, direction);\n };\n // \uC5EC\uB7EC \uAC12 \uACE0\uB974\uAE30\uB294 \uC5F0\uB2EC\uC544 \uACE0\uB974\uBBC0\uB85C \uC5F4\uC5B4 \uB454\uB2E4. \uD558\uB098\uB9CC \uACE0\uB974\uB294 \uC5F4\uC740 \uACE0\uB974\uBA74 \uB2EB\uB294\uB2E4.\n const toggleValue = (value: string) => {\n const on = picked.includes(value);\n if (multiple) {\n menuColumn.onFilterChange?.(on ? picked.filter((item) => item !== value) : [...picked, value]);\n return;\n }\n closeHeaderMenu();\n menuColumn.onFilterChange?.(on ? [] : [value]);\n };\n const items: React.ReactNode[] = [];\n if (canSort) {\n items.push(\n <MenuItem key=\"asc\" selected={activeSort === \"asc\"} onClick={() => pickSort(\"asc\")} sx={itemSx}>\n <PathIcon d={ICON_PATHS.asc} color=\"text.secondary\" />\n \uC624\uB984\uCC28\uC21C \uC815\uB82C\n </MenuItem>,\n <MenuItem key=\"desc\" selected={activeSort === \"desc\"} onClick={() => pickSort(\"desc\")} sx={itemSx}>\n <PathIcon d={ICON_PATHS.desc} color=\"text.secondary\" />\n \uB0B4\uB9BC\uCC28\uC21C \uC815\uB82C\n </MenuItem>,\n );\n if (activeSort && onSortClear) {\n items.push(\n <MenuItem\n key=\"sort-clear\"\n onClick={() => {\n closeHeaderMenu();\n onSortClear();\n }}\n sx={{ ...itemSx, color: \"text.secondary\" }}\n >\n \uC815\uB82C \uD480\uAE30\n </MenuItem>,\n );\n }\n }\n if (canSort && canFilter) items.push(<Divider key=\"div-sort\" />);\n if (canFilter) {\n (menuColumn.filterOptions ?? []).forEach((option) => {\n const on = picked.includes(option.value);\n items.push(\n <MenuItem key={`f:${option.value}`} selected={!multiple && on} onClick={() => toggleValue(option.value)} sx={itemSx}>\n {multiple ? (\n <PathIcon d={on ? ICON_PATHS.checked : ICON_PATHS.unchecked} color={on ? \"primary.main\" : \"text.disabled\"} />\n ) : (\n // \uD558\uB098\uB9CC \uACE0\uB974\uB294 \uC5F4 \u2014 \uACE0\uB978 \uAC12\uC5D0\uB9CC \uCCB4\uD06C, \uB098\uBA38\uC9C0\uB294 \uAC19\uC740 \uD3ED\uC744 \uBE44\uC6CC \uAE00\uC790 \uC904\uC744 \uB9DE\uCD98\uB2E4.\n <Box component=\"span\" sx={{ display: \"inline-flex\", width: 18, flexShrink: 0, color: \"primary.main\" }}>\n {on ? <PathIcon d={ICON_PATHS.check} /> : null}\n </Box>\n )}\n {option.label}\n </MenuItem>,\n );\n });\n // \uAC78\uB824 \uC788\uC744 \uB54C\uB9CC \u2014 \uD558\uB098\uC529 \uB044\uC9C0 \uC54A\uACE0 \uD55C \uBC88\uC5D0 \uD47C\uB2E4.\n if (picked.length > 0) {\n items.push(\n <Divider key=\"div-filter\" />,\n <MenuItem\n key=\"filter-clear\"\n onClick={() => {\n closeHeaderMenu();\n menuColumn.onFilterChange?.([]);\n }}\n sx={{ ...itemSx, color: \"text.secondary\" }}\n >\n \uAC70\uB974\uAE30 \uD480\uAE30\n </MenuItem>,\n );\n }\n }\n headerMenuNode = (\n // \uB204\uB978 \uC790\uB9AC\uC5D0\uC11C \uBC14\uB85C \uB72C\uB2E4 \u2014 \uD3BC\uCE68 \uC560\uB2C8\uBA54\uC774\uC158\uC740 \uBA54\uB274\uAC00 \uB2A6\uAC8C \uB530\uB77C\uC624\uB294 \uAC83\uCC98\uB7FC \uBCF4\uC778\uB2E4(\uC6B0\uD074\uB9AD \uBA54\uB274 \uACF5\uD1B5 \uADDC\uCE59).\n <Menu\n open\n anchorReference=\"anchorPosition\"\n anchorPosition={{ left: headerMenu.x, top: headerMenu.y }}\n onClose={closeHeaderMenu}\n transitionDuration={0}\n // \uBA54\uB274 \uC704\uC5D0\uC11C \uB2E4\uC2DC \uC6B0\uD074\uB9AD\uD574\uB3C4 \uBE0C\uB77C\uC6B0\uC800 \uBA54\uB274\uAC00 \uB728\uC9C0 \uC54A\uAC8C.\n onContextMenu={(event) => event.preventDefault()}\n slotProps={{ paper: { sx: { maxHeight: 420, minWidth: 180 } } }}\n >\n {items}\n </Menu>\n );\n }\n\n // \uACF5\uD1B5 \uD14C\uC774\uBE14 \uB0B4\uC6A9\n const tableContent = (\n <Box\n sx={\n {\n position: \"relative\",\n height: autoHeight ? \"auto\" : \"100%\",\n width: \"100%\",\n \"& .MuiTableHead-root\": {\n backgroundColor: (theme: Theme) =>\n notion\n ? `${notionTokens.bg} !important`\n : theme.palette.mode === \"dark\"\n ? \"#1e1e1e !important\"\n : \"#ffffff !important\",\n },\n // \uC120\uD0DD \uD589 CSS \uD558\uC774\uB77C\uC774\uD2B8 (selectedRowId \uBCC0\uACBD \uC2DC \uC774 \uCEE8\uD14C\uC774\uB108\uB9CC \uAC31\uC2E0, \uD589 \uC7AC\uB80C\uB354 \uC5C6\uC74C).\n ...(selectedRowCssSx ?? {}),\n // \uACE0\uC815 \uC5F4 \uCE78\uC740 \uB4A4\uB85C \uC9C0\uB098\uAC00\uB294 \uCE78\uC744 \uAC00\uB824\uC57C \uD574 \uBC14\uD0D5\uC744 \uCE60\uD55C\uB2E4. \uC904 \uD638\uBC84 \uC0C9\uC740 \uC904(tr)\uC5D0 \uCE60\uD574\uC9C0\uBBC0\uB85C \uACE0\uC815 \uCE78\uC5D0\uB3C4 \uAC19\uC740 \uC0C9\uC744 \uC900\uB2E4.\n \"& tbody td[data-vdt-pinned]\": {\n backgroundColor: notion\n ? notionTokens.bg\n : muiTheme.palette.background.paper,\n },\n // \uCE78 \uB2E8\uC704\uB85C \uB204\uB974\uB294 \uCE78 \u2014 \uCE78\uC5D0\uB9CC \uD638\uBC84 \uBC14\uD0D5.\n \"& tbody td[data-vdt-cell-click]\": { cursor: \"pointer\" },\n \"& tbody td[data-vdt-cell-click]:hover\": {\n backgroundColor: notion\n ? notionTokens.hoverBg\n : muiTheme.palette.mode === \"dark\"\n ? \"rgba(255, 255, 255, 0.06)\"\n : \"rgba(0, 0, 0, 0.04)\",\n },\n ...(notion && hasRowClick\n ? {\n \"& tbody tr:hover td[data-vdt-pinned]\": {\n backgroundColor: notionTokens.hoverBg,\n },\n }\n : {}),\n // \uB178\uC158\uD48D \u2014 \uBA38\uB9AC\u00B7\uCE78\uC758 \uC778\uB77C\uC778 style(padding\u00B7fontWeight)\uC744 \uB36E\uC5B4\uC57C \uD574\uC11C !important \uB2E4.\n // \uC140\uB809\uD130\uB97C \uCEE8\uD14C\uC774\uB108\uC5D0\uC11C \uB0B4\uB9AC\uB294 \uAC83\uC740 \uD589 \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uAC74\uB4DC\uB9AC\uC9C0 \uC54A\uAE30 \uC704\uD574\uC11C\uB2E4(\uD589 \uC7AC\uB80C\uB354 \uBE44\uC6A9).\n ...(notion\n ? {\n // \uBC14\uAE65 \uD14C\uB450\uB9AC \u2014 \uC5C5\uBB34\uD568 \uD45C(border 1px + radius 4px)\uC640 \uAC19\uB2E4. \uAC00\uC0C1\uD654\uB77C \uB0B4\uC6A9 \uB192\uC774\uC5D0 \uB9DE\uCDB0 \uC904\uC774\uC9C0 \uBABB\uD558\uACE0\n // \uC885\uC774 \uC548\uCABD \uC5EC\uBC31 \uC548\uC5D0\uC11C \uC138\uB85C\uB97C \uAF49 \uCC44\uC6B4\uB2E4. \uBA38\uB9AC\uC758 \uC717\uC120\u00B7\uC88C\uC6B0\uC120\uC740 \uC774 \uD14C\uB450\uB9AC\uAC00 \uB300\uC2E0\uD55C\uB2E4.\n ...(framed\n ? {\n border: `1px solid ${notionTokens.borderStrong}`,\n borderRadius: \"4px\",\n }\n : {\n // \uD2C0 \uC5C6\uC774 \u2014 \uBC14\uAE65 \uC0C1\uC790 \uBC14\uD0D5\uC774 \uBE44\uCE58\uC9C0 \uC54A\uAC8C \uD45C\uB97C \uC885\uC774 \uC0C9\uC73C\uB85C \uCE60\uD55C\uB2E4.\n \"& table\": { backgroundColor: notionTokens.bg },\n }),\n overflow: \"hidden\",\n \"& thead tr th\": {\n height: columnHeight,\n boxSizing: \"border-box\",\n padding: \"0 14px !important\",\n fontSize: 13,\n fontWeight: \"500 !important\",\n color: notionTokens.headerColor,\n backgroundColor: `${notionTokens.bg} !important`,\n // \uD2C0 \uC5C6\uB294 \uD45C\uB97C \uB3C4\uAD6C \uC904\uACFC \uD55C \uC0C1\uC790\uC5D0 \uB123\uC73C\uBA74 \uBA38\uB9AC \uC704 \uACBD\uACC4\uAC00 \uC5C6\uB2E4 \u2014 \uADF8\uB54C\uB9CC \uC717\uC120(headerTopBorder).\n borderTop: !framed && headerTopBorder ? `1px solid ${notionTokens.borderStrong}` : \"none\",\n borderBottom: `1px solid ${notionTokens.borderStrong}`,\n // \uCE78 \uC0AC\uC774 \uC138\uB85C\uC120 \u2014 \uB9C8\uC9C0\uB9C9 \uCE78 \uB4A4\uC5D0\uB294 \uAE0B\uC9C0 \uC54A\uB294\uB2E4(\uBC14\uAE65 \uD14C\uB450\uB9AC\uC640 \uACB9\uCCD0 \uB450 \uC904\uB85C \uBCF4\uC778\uB2E4).\n borderRight: `1px solid ${notionTokens.border}`,\n \"&:last-of-type\": { borderRight: \"none\" },\n },\n \"& tbody tr td:not([data-vdt-pad])\": {\n padding: \"0 14px !important\",\n },\n \"& tbody tr td\": {\n fontSize: 14,\n borderBottom: `1px solid ${notionTokens.border}`,\n },\n // \uB9C8\uC9C0\uB9C9 \uC904 \uC544\uB798\uC120 \u2014 \uD2C0 \uBC14\uB2E5(\uB610\uB294 \uD569\uACC4 \uC904\uC758 \uC717\uC120)\uACFC \uB9DE\uB2FF\uC73C\uBA74 \uAE0B\uC9C0 \uC54A\uB294\uB2E4. \uB450 \uC120\uC774 \uACB9\uCCD0 \uAD75\uC740 \uC774\uC911\uC120\uC73C\uB85C \uBCF4\uC600\uB2E4(2026-10-17).\n // \uB9DE\uB2FF\uB294 \uACBD\uC6B0: \uB0B4\uC6A9 \uB192\uC774\uB9CC\uD07C \uC11C\uB294 \uD45C(autoHeight), \uC904\uC774 \uC601\uC5ED\uBCF4\uB2E4 \uAE38\uC5B4 \uB05D\uAE4C\uC9C0 \uB0B4\uB9AC\uBA74 \uBC14\uB2E5\uC5D0 \uB2FF\uB294 \uD45C, \uD569\uACC4 \uC904\uC774 \uC788\uB294 \uD45C.\n // \uC904\uC774 \uC801\uC5B4 \uC544\uB798\uAC00 \uBE44\uB294 \uD45C\uB294 \uADF8\uB300\uB85C \uAE0B\uB294\uB2E4 \u2014 \uC904\uC774 \uC5B4\uB514\uC11C \uB05D\uB098\uB294\uC9C0 \uBCF4\uC5EC\uC57C \uD55C\uB2E4.\n ...(data.length > 0 && (autoHeight || listOverflows || hasFooter)\n ? { [`& tbody tr[data-index=\"${data.length - 1}\"]:not([data-vdt-pinned-row]) td`]: { borderBottom: \"none\" } }\n : {}),\n }\n : {}),\n } as SxProps<Theme>\n }\n >\n {/* \uD14C\uC774\uBE14 \u2014 autoHeight \uBA74 \uAC00\uC0C1\uD654 \uC5C6\uC774 \uBAA8\uB4E0 \uC904\uC744 \uADF8\uB9AC\uACE0 \uB192\uC774\uB294 \uB0B4\uC6A9\uC744 \uB530\uB978\uB2E4(\uD398\uC774\uC9C0\uAC00 \uAD74\uB9B0\uB2E4). */}\n {autoHeight ? (\n <Box sx={{ overflowX: \"auto\", width: \"100%\" }}>\n <AutoTable>\n <AutoTableHead>{fixedHeaderContent()}</AutoTableHead>\n <AutoTableBody>\n {data.map((item, index) => (\n <AutoTableRow\n key={getRowId ? String(getRowId(item, index)) : index}\n item={item}\n data-index={index}\n >\n {rowContent(index, item)}\n </AutoTableRow>\n ))}\n </AutoTableBody>\n {hasFooter ? <AutoTableFoot>{fixedFooterContent()}</AutoTableFoot> : null}\n </AutoTable>\n </Box>\n ) : (\n <TableVirtuoso\n key={tableKey}\n ref={virtuosoRef}\n data={data}\n totalCount={onLoadMore ? data.length + 1 : data.length}\n defaultItemHeight={estimatedItemHeight}\n fixedItemHeight={autoRowHeight ? undefined : estimatedItemHeight}\n fixedHeaderContent={fixedHeaderContent}\n fixedFooterContent={hasFooter ? fixedFooterContent : undefined}\n itemContent={rowContent}\n // \uD0A4 \uD568\uC218\uB294 \uC4F8 \uB54C\uB9CC \uB118\uAE34\uB2E4 \u2014 computeItemKey={undefined} \uB97C \uADF8\uB300\uB85C \uB118\uAE30\uBA74 react-virtuoso \uC758 \uAE30\uBCF8 \uD0A4 \uD568\uC218\uAC00 undefined \uB85C \uB36E\uC5EC\n // \"n is not a function\" \uC73C\uB85C \uD45C \uC804\uCCB4\uAC00 \uADF8\uB824\uC9C0\uC9C0 \uC54A\uC558\uB2E4(1.3.0, 2026-10-18).\n {...(rowKeyFromId && getRowId\n ? { computeItemKey: (index: number, item: T) => (item ? getRowId(item, index) : `vdt-${index}`) }\n : {})}\n endReached={handleEndReached}\n scrollerRef={(el) => {\n scrollerElRef.current = el instanceof HTMLElement ? el : null;\n checkListOverflow();\n }}\n totalListHeightChanged={checkListOverflow}\n style={{ height: \"100%\" }}\n increaseViewportBy={{\n top: viewportBufferTop,\n bottom: viewportBufferBottom,\n }}\n overscan={virtuosoOverscan}\n followOutput={false}\n components={resolvedVirtuosoComponents}\n />\n )}\n\n {/* \uBE48 \uB370\uC774\uD130 \uD45C\uC2DC \u2014 \uB178\uC158\uD48D\uC740 \uBA38\uB9AC \uC544\uB798\uC5D0 \uC605\uC740 \uAE00 \uD55C \uC904(\uC5C5\uBB34\uD568 \uBAA9\uB85D \uD45C\uC758 \uBE48 \uBAA9\uB85D\uACFC \uAC19\uC740 \uBAA8\uC591). */}\n {data.length === 0 && !loading && !hasPinnedRows && notion && typeof emptyMessage === \"string\" && (\n <Box\n sx={{\n position: autoHeight ? \"static\" : \"absolute\",\n top: columnHeight,\n left: 0,\n right: 0,\n py: 6,\n textAlign: \"center\",\n fontSize: 14,\n color: notionTokens.emptyColor,\n // \uAE00 \uD55C \uC904\uBFD0\uC774\uB77C \uB204\uB97C \uAC83\uC774 \uC5C6\uB2E4 \u2014 \uBA38\uB9AC \uCE78 \uD074\uB9AD \u00B7 \uC6B0\uD074\uB9AD\uC744 \uAC00\uB85C\uCC44\uC9C0 \uC54A\uAC8C.\n pointerEvents: \"none\",\n }}\n >\n {emptyMessage}\n </Box>\n )}\n {data.length === 0 && !loading && !hasPinnedRows && !(notion && typeof emptyMessage === \"string\") && (\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 // \uD45C \uC804\uCCB4(\uBA38\uB9AC \uD3EC\uD568)\uB97C \uB36E\uB294 \uC0C1\uC790\uB77C \uBE48 \uBAA9\uB85D\uC5D0\uC11C \uBA38\uB9AC \uCE78 \uC815\uB82C \u00B7 \uC6B0\uD074\uB9AD \uBA54\uB274\uAC00 \uBA39\uC9C0 \uC54A\uC558\uB2E4(1.4.2) \u2014\n // \uC0C1\uC790\uB294 \uD1B5\uACFC\uC2DC\uD0A4\uACE0 \uAC00\uC6B4\uB370 \uB0B4\uC6A9(\uC548\uB0B4 \u00B7 \uB2E8\uCD94)\uB9CC \uB20C\uB9AC\uAC8C \uD55C\uB2E4.\n pointerEvents: \"none\",\n \"& > *\": { pointerEvents: \"auto\" },\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 {headerMenuNode}\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 indicator={<CssSpinner />}\n sx={{\n top: `${\n columns.some((col) => col.group)\n ? columnHeight * 2\n : columnHeight\n }px`,\n // \uD478\uD130(\uD569\uACC4 \uD589)\uAC00 \uC788\uC73C\uBA74 \uADF8 \uB192\uC774\uB9CC\uD07C \uC544\uB798\uB97C \uC798\uB77C, \uD5E4\uB354~\uD478\uD130 \uC0AC\uC774 \uB0B4\uC6A9 \uC601\uC5ED \uC911\uC559\uC5D0 \uC2A4\uD53C\uB108\uB97C \uB454\uB2E4.\n bottom: `${hasFooter ? footerHeight ?? rowHeight : 0}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 // \uB178\uC158\uD48D\uC740 \uC0AC\uBC29 \uC5EC\uBC31 \u2014 \uC5C5\uBB34\uD568\uCC98\uB7FC \uD45C\uAC00 \uC885\uC774 \uAC00\uC7A5\uC790\uB9AC\uC5D0 \uBD99\uC9C0 \uC54A\uB294\uB2E4(\uC88C\uC6B0 paddingX, \uC0C1\uD558 NOTION_PADDING_Y).\n const notionFramePadding = notion && framed\n ? { paddingRight: paddingX, paddingTop: NOTION_PADDING_Y, paddingBottom: NOTION_PADDING_Y }\n : {};\n\n return showPaper ? (\n <Paper\n className=\"grow\"\n elevation={1}\n sx={{\n padding: 0,\n paddingLeft: paddingX,\n ...notionFramePadding,\n boxSizing: \"border-box\",\n height: autoHeight ? \"auto\" : \"100%\",\n minHeight: 0,\n flex: autoHeight ? \"none\" : 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 ...notionFramePadding,\n boxSizing: \"border-box\",\n height: autoHeight ? \"auto\" : \"100%\",\n minHeight: 0,\n flex: autoHeight ? \"none\" : 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 * \uC21C\uC218 CSS \uB85C\uB529 \uC2A4\uD53C\uB108. MUI CircularProgress \uB300\uC2E0 LoadingProgress \uC758 indicator \uB85C \uC8FC\uC785\uD55C\uB2E4.\n *\n * \uC2A4\uD0C0\uC77C\uC740 \uC790\uCCB4 <style> \uD074\uB798\uC2A4\uB85C \uC8FC\uC785\uD55C\uB2E4(\uC678\uBD80 \uC2A4\uD0C0\uC77C \uC758\uC874 \uC5C6\uC74C). \uBC30\uACBD \uB9C1(\uC5F0\uD55C \uD2B8\uB799)\uACFC\n * \uD68C\uC804 \uD638(\uC0C1\uB2E8 \uC0C9)\uB97C \uD55C \uD074\uB798\uC2A4\uC5D0 \uB2F4\uB294\uB2E4. \uC571 \uCD08\uAE30 \uC2A4\uD53C\uB108 \uBC0F \uB300\uC2DC\uBCF4\uB4DC \uB808\uC774\uC544\uC6C3 \uC2A4\uD53C\uB108\uC640 \uB3D9\uC77C\uD55C \uBAA8\uC591.\n */\nexport interface CssSpinnerProps {\n /** \uC2A4\uD53C\uB108 \uC9C0\uB984(px). \uAE30\uBCF8 54 */\n size?: number;\n}\n\nconst SPINNER_CSS = `\n.vdt-css-spinner{box-sizing:border-box;border-radius:50%;border:4px solid rgba(28,64,125,0.14);border-top-color:#1c407d;animation:vdt-css-spinner-spin .75s linear infinite}\n@keyframes vdt-css-spinner-spin{to{transform:rotate(360deg)}}\n`;\n\nexport function CssSpinner({ size = 54 }: CssSpinnerProps) {\n return (\n <>\n <style>{SPINNER_CSS}</style>\n <span\n className=\"vdt-css-spinner\"\n role=\"progressbar\"\n aria-label=\"loading\"\n style={{ display: \"inline-block\", width: size, height: size }}\n />\n </>\n );\n}\n\nexport default CssSpinner;\n"],
5
+ "mappings": "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",
6
6
  "names": ["forwardRef", "useCallback", "useMemo", "useRef", "useEffect", "memo", "useState", "Box", "Table", "MuiTableBody", "TableCell", "TableContainer", "TableHead", "MuiTableFooter", "MuiTableRow", "TableSortLabel", "Menu", "MenuItem", "Divider", "SvgIcon", "Paper", "Typography", "useTheme", "TableVirtuoso", "__assign", "t", "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", "Fragment", "jsx", "jsxs", "SPINNER_CSS", "CssSpinner", "size", "OverlayScrollbar", "Fragment", "jsx", "jsxs", "OVERLAY_SCROLLBAR_TRACK_CONFIG", "ROW_CLICK_DRAG_THRESHOLD_PX", "NOTION_LIGHT", "NOTION_PADDING_Y", "NOTION_DARK", "ICON_PATHS", "PathIcon", "d", "size", "color", "SvgIcon", "hasColumnFilter", "col", "VirtualDataTableComponent", "data", "loading", "columns", "onRowClick", "getRowId", "selectedRowId", "selectedRowSxProp", "rowHeightProp", "columnHeightProp", "striped", "rowDivider", "onSort", "onSortClear", "onHeaderContextMenu", "onLoadMore", "sortBy", "sortDirection", "showPaper", "paddingXProp", "paddingTop", "paddingBottom", "rowHoverColorProp", "rowHoverOpacityProp", "viewportBuffer", "overscan", "scrollbars", "emptyMessage", "autoHeight", "LoadingComponent", "showFooter", "footerHeight", "footerSx", "variant", "framed", "headerTopBorder", "rowHeightMode", "tableLayout", "renderFullWidthRow", "fullWidthRowSx", "onRowContextMenu", "pinnedRows", "pinnedRowsMaxHeight", "pinnedRowsSx", "resetScrollOnDataChange", "rowKeyFromId", "onEndReached", "colorMode", "notion", "muiTheme", "useTheme", "notionTokens", "hasPinnedRows", "columnHeight", "rowHeight", "paddingX", "autoRowHeight", "rowHoverColor", "rowHoverOpacity", "defaultViewportBufferTop", "defaultViewportBufferBottom", "viewportBufferTop", "viewportBufferBottom", "defaultOverscanMain", "defaultOverscanReverse", "virtuosoOverscan", "estimatedItemHeight", "notionSelectedSx", "useMemo", "selectedRowSx", "useCssRowHighlight", "selectedRowCssSx", "isDev", "perfDebugEnabled", "useState", "perfStatsRef", "useRef", "flushPerfStats", "useCallback", "reason", "stats", "rowAvgMs", "cellAvgMs", "useEffect", "intervalId", "VirtuosoScroller", "forwardRef", "props", "ref", "scrollContainerRef", "wheelDeltaRef", "wheelRafRef", "el", "handleWheel", "e", "wheelStart", "inner", "delta", "rafStart", "maxStep", "batchedDelta", "TableContainer", "Box", "node", "stripedRowColor", "internalLoading", "setInternalLoading", "tableKey", "setTableKey", "handleLoadingComplete", "shouldShowLoading", "isLoadMoreLoading", "isLoadingMoreRef", "lastLoadMoreLengthRef", "virtuosoRef", "scrollerElRef", "listOverflows", "setListOverflows", "checkListOverflow", "observer", "onRowClickRef", "getRowIdRef", "onRowContextMenuRef", "onEndReachedRef", "rowComponentRef", "pinnedLeft", "map", "left", "tableMinWidth", "sum", "pinnedStyle", "head", "hasRowClick", "isScrollDraggingRef", "mouseDownPositionRef", "handleDocumentMouseMove", "event", "dx", "dy", "tableContainer", "label", "mouseLeaveEvent", "handleSort", "columnId", "headerMenu", "setHeaderMenu", "onHeaderContextMenuRef", "onSortRef", "handleHeaderContextMenu", "handled", "rect", "renderHeaderText", "handleEndReached", "endIndex", "rangeStart", "hasMinimumData", "nearEnd", "alreadyRequestedAtThisLength", "offset", "prev", "resetScrollOnDataChangeRef", "prevDataLengthRef", "prevFirstRowKeyRef", "prevLength", "currentLength", "firstRowKey", "prevFirstRowKey", "dataReplaced", "headerRowsContent", "groupMap", "noGroupColumns", "MuiTableRow", "TableCell", "TableSortLabel", "firstRowCells", "group", "cols", "secondRowCells", "rowContent", "index", "item", "rowStart", "rowDuration", "fullWidth", "coveredByColSpan", "cells", "column", "columnIndex", "colSpan", "cellStart", "cellValue", "cellDuration", "pinned", "customPadding", "span", "onCellClick", "fixedHeaderContent", "headerRows", "RowComponent", "MuiTableBody", "hasFooter", "fixedFooterContent", "i", "VirtuosoTableComponents", "Table", "TableHead", "_selected", "_ariaSelected", "className", "rest", "rowIndex", "isOddRow", "rowId", "isSelected", "resolvedSelectedRowSx", "sanitizedClassName", "token", "theme", "isDark", "opacity", "hex", "r", "g", "b", "children", "MuiTableFooter", "resolvedVirtuosoComponents", "autoParts", "AutoTable", "AutoTableHead", "AutoTableBody", "AutoTableRow", "AutoTableFoot", "menuColumn", "closeHeaderMenu", "headerMenuNode", "colId", "canSort", "canFilter", "activeSort", "picked", "multiple", "itemSx", "pickSort", "direction", "toggleValue", "value", "on", "items", "MenuItem", "Divider", "option", "Menu", "tableContent", "TableVirtuoso", "Typography", "LoadingProgress", "CssSpinner", "notionFramePadding", "Paper", "VirtualDataTable", "memo"]
7
7
  }