From 9a3e83fd8526f8ae2c463593cb10cee93715d076 Mon Sep 17 00:00:00 2001 From: Mark Saroufim Date: Tue, 24 Feb 2026 22:38:38 -0800 Subject: [PATCH] =?UTF-8?q?Revert=20"CodeBlock:=20Virtualize=20syntax=20hi?= =?UTF-8?q?ghlighting=20for=20long=20code=20submissions=20(=E2=80=A6"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 22ed83e0bd80395068abe962adcdff6a62f2f0be. --- frontend/package-lock.json | 69 ++++----- frontend/package.json | 2 - .../components/codeblock/CodeBlock.test.tsx | 84 +---------- .../src/components/codeblock/CodeBlock.tsx | 133 +----------------- frontend/src/lib/hooks/useContainerHeight.ts | 35 ----- .../components/SubmissionCodeSidebar.tsx | 5 +- 6 files changed, 34 insertions(+), 294 deletions(-) delete mode 100644 frontend/src/lib/hooks/useContainerHeight.ts diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 4d3fa6c..bfac60a 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -24,7 +24,6 @@ "react-markdown": "^10.1.0", "react-router-dom": "^7.13.0", "react-syntax-highlighter": "^16.1.0", - "react-window": "^1.8.11", "rehype-katex": "^7.0.1", "rehype-raw": "^7.0.0", "rehype-slug": "^6.0.0", @@ -41,7 +40,6 @@ "@types/node": "^24.0.3", "@types/react": "^19.1.2", "@types/react-dom": "^19.1.2", - "@types/react-window": "^1.8.8", "@vitejs/plugin-react": "^4.5.2", "eslint": "^9.25.0", "eslint-plugin-react-hooks": "^5.2.0", @@ -120,6 +118,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", "dev": true, + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", @@ -445,6 +444,7 @@ "url": "https://opencollective.com/csstools" } ], + "peer": true, "engines": { "node": ">=18" }, @@ -467,6 +467,7 @@ "url": "https://opencollective.com/csstools" } ], + "peer": true, "engines": { "node": ">=18" } @@ -523,6 +524,7 @@ "version": "11.14.0", "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", + "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -563,6 +565,7 @@ "version": "11.14.1", "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz", "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", + "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -1293,6 +1296,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@mui/material/-/material-7.2.0.tgz", "integrity": "sha512-NTuyFNen5Z2QY+I242MDZzXnFIVIR6ERxo7vntFi9K1wCgSwvIl0HcAO2OOydKqqKApE6omRiYhpny1ZhGuH7Q==", + "peer": true, "dependencies": { "@babel/runtime": "^7.27.6", "@mui/core-downloads-tracker": "^7.2.0", @@ -1893,8 +1897,7 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "dev": true, - "peer": true + "dev": true }, "node_modules/@types/babel__core": { "version": "7.20.5", @@ -2018,6 +2021,7 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.13.tgz", "integrity": "sha512-Qm9OYVOFHFYg3wJoTSrz80hoec5Lia/dPp84do3X7dZvLikQvM1YpmvTBEdIr/e+U8HTkFjLHLnl78K/qjf+jQ==", "dev": true, + "peer": true, "dependencies": { "undici-types": "~7.8.0" } @@ -2042,6 +2046,7 @@ "version": "19.1.8", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz", "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==", + "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -2051,6 +2056,7 @@ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.6.tgz", "integrity": "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==", "dev": true, + "peer": true, "peerDependencies": { "@types/react": "^19.0.0" } @@ -2072,16 +2078,6 @@ "@types/react": "*" } }, - "node_modules/@types/react-window": { - "version": "1.8.8", - "resolved": "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.8.tgz", - "integrity": "sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -2130,6 +2126,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.36.0.tgz", "integrity": "sha512-FuYgkHwZLuPbZjQHzJXrtXreJdFMKl16BFYyRrLxDhWr6Qr7Kbcu2s1Yhu8tsiMXw1S0W1pjfFfYEt+R604s+Q==", "dev": true, + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.36.0", "@typescript-eslint/types": "8.36.0", @@ -2481,6 +2478,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2527,7 +2525,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -2641,6 +2638,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001726", "electron-to-chromium": "^1.5.173", @@ -2997,8 +2995,7 @@ "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", - "dev": true, - "peer": true + "dev": true }, "node_modules/dom-helpers": { "version": "5.2.1", @@ -3013,6 +3010,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/echarts/-/echarts-6.0.0.tgz", "integrity": "sha512-Tte/grDQRiETQP4xz3iZWSvoHrkCQtwqd6hs+mifXcjrCuo2iKWbajFObuLJVBlDIJlOzgQPd1hsaKt/3+OMkQ==", + "peer": true, "dependencies": { "tslib": "2.3.0", "zrender": "6.0.0" @@ -3128,6 +3126,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.31.0.tgz", "integrity": "sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==", "dev": true, + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", @@ -4066,6 +4065,7 @@ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", "dev": true, + "peer": true, "dependencies": { "cssstyle": "^4.2.1", "data-urls": "^5.0.0", @@ -4271,7 +4271,6 @@ "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, - "peer": true, "bin": { "lz-string": "bin/bin.js" } @@ -4589,12 +4588,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/memoize-one": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", - "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", - "license": "MIT" - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -5478,7 +5471,6 @@ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, - "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -5493,7 +5485,6 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, - "peer": true, "engines": { "node": ">=10" }, @@ -5505,8 +5496,7 @@ "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true, - "peer": true + "dev": true }, "node_modules/prismjs": { "version": "1.30.0", @@ -5574,6 +5564,7 @@ "version": "19.1.0", "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -5582,6 +5573,7 @@ "version": "19.1.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", + "peer": true, "dependencies": { "scheduler": "^0.26.0" }, @@ -5710,23 +5702,6 @@ "react-dom": ">=16.6.0" } }, - "node_modules/react-window": { - "version": "1.8.11", - "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.11.tgz", - "integrity": "sha512-+SRbUVT2scadgFSWx+R1P754xHPEqvcfSfVX10QYg6POOz+WNgkN48pS+BtZNIMGiL1HYrSEiCkwsMS15QogEQ==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.0.0", - "memoize-one": ">=3.1.1 <6" - }, - "engines": { - "node": ">8.0.0" - }, - "peerDependencies": { - "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, "node_modules/redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", @@ -6251,6 +6226,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, + "peer": true, "engines": { "node": ">=12" }, @@ -6391,6 +6367,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "dev": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6620,6 +6597,7 @@ "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -6730,6 +6708,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, + "peer": true, "engines": { "node": ">=12" }, diff --git a/frontend/package.json b/frontend/package.json index 161f637..d547712 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -28,7 +28,6 @@ "react-markdown": "^10.1.0", "react-router-dom": "^7.13.0", "react-syntax-highlighter": "^16.1.0", - "react-window": "^1.8.11", "rehype-katex": "^7.0.1", "rehype-raw": "^7.0.0", "rehype-slug": "^6.0.0", @@ -45,7 +44,6 @@ "@types/node": "^24.0.3", "@types/react": "^19.1.2", "@types/react-dom": "^19.1.2", - "@types/react-window": "^1.8.8", "@vitejs/plugin-react": "^4.5.2", "eslint": "^9.25.0", "eslint-plugin-react-hooks": "^5.2.0", diff --git a/frontend/src/components/codeblock/CodeBlock.test.tsx b/frontend/src/components/codeblock/CodeBlock.test.tsx index 777cbe0..0a71d78 100644 --- a/frontend/src/components/codeblock/CodeBlock.test.tsx +++ b/frontend/src/components/codeblock/CodeBlock.test.tsx @@ -1,5 +1,5 @@ -import { render, screen, fireEvent, waitFor, act } from "@testing-library/react"; -import { describe, it, expect, vi, beforeEach } from "vitest"; +import { render, screen, fireEvent, waitFor } from "@testing-library/react"; +import { describe, it, expect, vi } from "vitest"; import CodeBlock from "./CodeBlock"; // Mock clipboard API @@ -9,30 +9,6 @@ Object.assign(navigator, { }, }); -// Mock ResizeObserver (jsdom doesn't implement it) -beforeEach(() => { - window.ResizeObserver = vi.fn().mockImplementation((callback) => ({ - observe: vi.fn((element: Element) => { - // Simulate measurement on next microtask - Promise.resolve().then(() => - callback( - [{ target: element, contentRect: { height: 600, width: 800 } }], - {} as ResizeObserver, - ), - ); - }), - unobserve: vi.fn(), - disconnect: vi.fn(), - })) as unknown as typeof ResizeObserver; -}); - -function generateLongCode(lines: number): string { - return Array.from( - { length: lines }, - (_, i) => `x = ${i} # line ${i + 1}`, - ).join("\n"); -} - describe("CodeBlock", () => { const sampleCode = `function hello() { console.log("Hello, world!"); @@ -74,60 +50,4 @@ describe("CodeBlock", () => { render(); expect(screen.getByText(/Hello/)).toBeInTheDocument(); }); - - describe("virtualization", () => { - it("does not virtualize short code", async () => { - render(); - // Wait for rAF - await act(async () => { - await new Promise((r) => setTimeout(r, 50)); - }); - // Short code should use a
 or standard SyntaxHighlighter, not FixedSizeList
-      expect(document.querySelector("pre")).toBeInTheDocument();
-    });
-
-    it("virtualizes code with more than 200 lines", async () => {
-      const longCode = generateLongCode(300);
-      render();
-
-      // Wait for rAF + ResizeObserver
-      await act(async () => {
-        await new Promise((r) => setTimeout(r, 50));
-      });
-
-      // FixedSizeList renders a container with explicit height
-      await waitFor(() => {
-        const listContainer = document.querySelector(
-          '[style*="height: 600px"]',
-        );
-        expect(listContainer).toBeInTheDocument();
-      });
-    });
-
-    it("does not virtualize when bordered is true", async () => {
-      const longCode = generateLongCode(300);
-      render();
-
-      await act(async () => {
-        await new Promise((r) => setTimeout(r, 50));
-      });
-
-      // Should not have a FixedSizeList container
-      const listContainer = document.querySelector(
-        '[style*="height: 600px"]',
-      );
-      expect(listContainer).not.toBeInTheDocument();
-    });
-
-    it("copy button works with virtualized code", async () => {
-      const longCode = generateLongCode(300);
-      const writeTextSpy = vi.spyOn(navigator.clipboard, "writeText");
-      render();
-
-      const copyButton = screen.getByRole("button");
-      fireEvent.click(copyButton);
-
-      expect(writeTextSpy).toHaveBeenCalledWith(longCode);
-    });
-  });
 });
diff --git a/frontend/src/components/codeblock/CodeBlock.tsx b/frontend/src/components/codeblock/CodeBlock.tsx
index d8a729a..958f08f 100644
--- a/frontend/src/components/codeblock/CodeBlock.tsx
+++ b/frontend/src/components/codeblock/CodeBlock.tsx
@@ -1,50 +1,9 @@
-import React, { useState, useEffect, useMemo } from "react";
+import React, { useState, useEffect } from "react";
 import { Box, IconButton, Tooltip, useTheme } from "@mui/material";
 import ContentCopyIcon from "@mui/icons-material/ContentCopy";
 import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
 import { oneLight } from "react-syntax-highlighter/dist/esm/styles/prism";
 import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism";
-import { FixedSizeList } from "react-window";
-import { useContainerHeight } from "../../lib/hooks/useContainerHeight";
-import type { rendererNode } from "react-syntax-highlighter";
-
-function renderNode(
-  node: rendererNode,
-  stylesheet: { [key: string]: React.CSSProperties },
-  useInlineStyles: boolean,
-  key: React.Key,
-): React.ReactNode {
-  if (node.type === "text") return node.value;
-  if (!node.tagName) return null;
-
-  const classNames = node.properties?.className ?? [];
-  let props: Record;
-  if (useInlineStyles) {
-    const nonToken = classNames.filter((c: string) => c !== "token");
-    const style: React.CSSProperties = {};
-    for (const cls of nonToken) {
-      if (stylesheet[cls]) Object.assign(style, stylesheet[cls]);
-    }
-    // Handle compound selectors (e.g. "keyword.control")
-    if (nonToken.length >= 2) {
-      const a = nonToken.join(".");
-      if (stylesheet[a]) Object.assign(style, stylesheet[a]);
-      const b = nonToken.slice().reverse().join(".");
-      if (stylesheet[b]) Object.assign(style, stylesheet[b]);
-    }
-    props = { key, style };
-  } else {
-    props = { key, className: classNames.join(" ") };
-  }
-
-  const children = node.children?.map((child, i) =>
-    renderNode(child, stylesheet, useInlineStyles, `${key}-${i}`),
-  );
-  return React.createElement(node.tagName, props, children);
-}
-
-const VIRTUALIZATION_LINE_THRESHOLD = 200;
-const LINE_HEIGHT_PX = 20;
 
 interface CodeBlockProps {
   code: string;
@@ -74,7 +33,6 @@ export default function CodeBlock({ code, bordered = false }: CodeBlockProps) {
   const [highlighted, setHighlighted] = useState(false);
   const theme = useTheme();
   const syntaxTheme = theme.palette.mode === "dark" ? oneDark : oneLight;
-  const { containerRef, height: containerHeight } = useContainerHeight();
 
   useEffect(() => {
     setHighlighted(false);
@@ -82,18 +40,6 @@ export default function CodeBlock({ code, bordered = false }: CodeBlockProps) {
     return () => cancelAnimationFrame(id);
   }, [code]);
 
-  const lineCount = useMemo(() => {
-    let count = 1;
-    for (let i = 0; i < code.length; i++) {
-      if (code[i] === "\n") count++;
-    }
-    return count;
-  }, [code]);
-
-  const canVirtualize =
-    !bordered && lineCount > VIRTUALIZATION_LINE_THRESHOLD;
-  const shouldVirtualize = canVirtualize && containerHeight > 0;
-
   const handleCopy = () => {
     navigator.clipboard.writeText(code).then(() => {
       setCopied(true);
@@ -101,66 +47,8 @@ export default function CodeBlock({ code, bordered = false }: CodeBlockProps) {
     });
   };
 
-  const virtualizedRenderer = useMemo(() => {
-    if (!shouldVirtualize) return undefined;
-
-    return ({
-      rows,
-      stylesheet,
-      useInlineStyles,
-    }: {
-      rows: rendererNode[];
-      stylesheet: { [key: string]: React.CSSProperties };
-      useInlineStyles: boolean;
-    }): React.ReactNode => (
-      
-        {({
-          index,
-          style,
-        }: {
-          index: number;
-          style: React.CSSProperties;
-        }) => (
-          
- {renderNode( - rows[index], - stylesheet, - useInlineStyles, - `line-${index}`, - )} -
- )} -
- ); - }, [shouldVirtualize, containerHeight]); - return ( - + {/* Copy Button */} @@ -172,11 +60,8 @@ export default function CodeBlock({ code, bordered = false }: CodeBlockProps) { {/* Scrollable Code with Syntax Highlighting */} - {highlighted && (!canVirtualize || shouldVirtualize) ? ( + {highlighted ? ( {code} diff --git a/frontend/src/lib/hooks/useContainerHeight.ts b/frontend/src/lib/hooks/useContainerHeight.ts deleted file mode 100644 index 1f47c79..0000000 --- a/frontend/src/lib/hooks/useContainerHeight.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { useRef, useState, useCallback, useEffect } from "react"; - -export function useContainerHeight(): { - containerRef: React.RefCallback; - height: number; -} { - const [height, setHeight] = useState(0); - const observerRef = useRef(null); - - const containerRef = useCallback((node: T | null) => { - if (observerRef.current) { - observerRef.current.disconnect(); - observerRef.current = null; - } - - if (node) { - observerRef.current = new ResizeObserver((entries) => { - const entry = entries[0]; - if (entry) { - const newHeight = Math.floor(entry.contentRect.height); - setHeight((prev) => (prev !== newHeight ? newHeight : prev)); - } - }); - observerRef.current.observe(node); - } - }, []); - - useEffect(() => { - return () => { - observerRef.current?.disconnect(); - }; - }, []); - - return { containerRef, height }; -} diff --git a/frontend/src/pages/leaderboard/components/SubmissionCodeSidebar.tsx b/frontend/src/pages/leaderboard/components/SubmissionCodeSidebar.tsx index 77a44a1..cfa550b 100644 --- a/frontend/src/pages/leaderboard/components/SubmissionCodeSidebar.tsx +++ b/frontend/src/pages/leaderboard/components/SubmissionCodeSidebar.tsx @@ -273,11 +273,8 @@ export default function SubmissionCodeSidebar({ {isLoadingCodes ? (