From b019698b654e826c255dc7ee3ce01af7c4c646d1 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 11 Aug 2026 15:49:47 -0700 Subject: [PATCH 1/3] fix(files): let a mouse wheel scroll CSV and XLSX previews horizontally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The zoomable previews (docx, pdf, pptx, image) bind `bindPreviewWheelZoom`, whose horizontal branch maps a trackpad's `deltaX` — and Shift+`deltaY` on a plain mouse — onto the container's `scrollLeft`. The tabular previews never bound anything, which did not matter while their table fitted the frame. Now that it is wider, a mouse whose wheel reports only `deltaY` can reach the overflow solely by dragging the scrollbar; hovering the table and scrolling does nothing sideways. Extract that horizontal branch into `bindPreviewHorizontalWheel`, sharing the delta logic with the zooming variant rather than duplicating it, and bind it in all three tabular preview containers through a `useHorizontalWheelScroll` ref callback. The new binder deliberately ignores ctrl/cmd+wheel so browser page zoom still works over a table, since these previews have no zoom of their own. --- .../file-viewer/csv-table-preview.tsx | 4 +- .../components/file-viewer/preview-panel.tsx | 4 +- .../file-viewer/preview-wheel-zoom.test.ts | 98 +++++++++++++++++++ .../file-viewer/preview-wheel-zoom.ts | 45 ++++++++- .../use-horizontal-wheel-scroll.ts | 21 ++++ .../components/file-viewer/xlsx-preview.tsx | 4 +- 6 files changed, 168 insertions(+), 8 deletions(-) create mode 100644 apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.test.ts create mode 100644 apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/use-horizontal-wheel-scroll.ts diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/csv-table-preview.tsx b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/csv-table-preview.tsx index 6b39c4eadb3..33c6437c923 100644 --- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/csv-table-preview.tsx +++ b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/csv-table-preview.tsx @@ -6,6 +6,7 @@ import { useWorkspaceCsvPreview } from '@/hooks/queries/workspace-file-table' import { useCsvTruncationImport } from './csv-import' import { DataTable } from './data-table' import { PreviewError, PreviewLoadingFrame, resolvePreviewError } from './preview-shared' +import { useHorizontalWheelScroll } from './use-horizontal-wheel-scroll' /** * Read-only preview for a CSV that is too large to load fully into the editor. Streams only the @@ -19,6 +20,7 @@ export const CsvTablePreview = memo(function CsvTablePreview({ file: WorkspaceFileRecord workspaceId: string }) { + const scrollRef = useHorizontalWheelScroll() const version = Number(new Date(file.updatedAt)) || file.size const { data, @@ -42,7 +44,7 @@ export const CsvTablePreview = memo(function CsvTablePreview({ } return ( -
+
) diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-panel.tsx b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-panel.tsx index 2b5b9c997d0..fc55e408ce8 100644 --- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-panel.tsx +++ b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-panel.tsx @@ -7,6 +7,7 @@ import { getFileExtension } from '@/lib/uploads/utils/file-utils' import { type CsvImportFileDescriptor, useCsvTruncationImport } from './csv-import' import { DataTable } from './data-table' import { MermaidDiagram } from './mermaid-diagram' +import { useHorizontalWheelScroll } from './use-horizontal-wheel-scroll' import { ZoomablePreview } from './zoomable-preview' type PreviewType = 'markdown' | 'html' | 'csv' | 'svg' | 'mermaid' | null @@ -264,6 +265,7 @@ const CsvPreview = memo(function CsvPreview({ file: CsvImportFileDescriptor readOnly?: boolean }) { + const scrollRef = useHorizontalWheelScroll() const { headers, rows, truncated } = useMemo(() => parseCsv(content), [content]) useCsvTruncationImport(workspaceId, file, truncated, readOnly) @@ -276,7 +278,7 @@ const CsvPreview = memo(function CsvPreview({ } return ( -
+
) diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.test.ts b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.test.ts new file mode 100644 index 00000000000..53954fff214 --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.test.ts @@ -0,0 +1,98 @@ +/** + * @vitest-environment jsdom + * + * A mouse whose wheel reports only `deltaY` has no native gesture for reaching a preview + * table's horizontal overflow short of dragging the scrollbar, so the tabular previews bind + * `bindPreviewHorizontalWheel`. It must move the container on a horizontal gesture, stay out + * of the way otherwise, and — unlike the zooming variant — leave ctrl/cmd+wheel to the browser + * so page zoom still works over a table. + */ +import { beforeEach, describe, expect, it } from 'vitest' +import { bindPreviewHorizontalWheel } from '@/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom' + +/** jsdom does no layout, so scrollWidth/clientWidth are stubbed to model an overflowing container. */ +function makeContainer({ scrollWidth = 2000, clientWidth = 1000 } = {}): HTMLElement { + const el = document.createElement('div') + Object.defineProperty(el, 'scrollWidth', { value: scrollWidth, configurable: true }) + Object.defineProperty(el, 'clientWidth', { value: clientWidth, configurable: true }) + el.scrollLeft = 0 + document.body.appendChild(el) + return el +} + +function wheel(el: HTMLElement, init: WheelEventInit): WheelEvent { + const event = new WheelEvent('wheel', { bubbles: true, cancelable: true, ...init }) + el.dispatchEvent(event) + return event +} + +describe('bindPreviewHorizontalWheel', () => { + let container: HTMLElement + let unbind: () => void + + beforeEach(() => { + document.body.innerHTML = '' + container = makeContainer() + unbind = bindPreviewHorizontalWheel(container) + }) + + it("scrolls by a trackpad's horizontal delta", () => { + const event = wheel(container, { deltaX: 120, deltaY: 0 }) + + expect(container.scrollLeft).toBe(120) + expect(event.defaultPrevented).toBe(true) + }) + + it('maps shift+wheel to horizontal for a vertical-only mouse', () => { + const event = wheel(container, { deltaX: 0, deltaY: 120, shiftKey: true }) + + expect(container.scrollLeft).toBe(120) + expect(event.defaultPrevented).toBe(true) + }) + + it('leaves a plain vertical wheel alone so the container still scrolls down', () => { + const event = wheel(container, { deltaX: 0, deltaY: 120 }) + + expect(container.scrollLeft).toBe(0) + expect(event.defaultPrevented).toBe(false) + }) + + /** Zoom is the browser's here — the tabular previews have no zoom of their own. */ + it.each([ + ['ctrl', { ctrlKey: true }], + ['cmd', { metaKey: true }], + ])('leaves %s+wheel to the browser', (_label, modifier) => { + const event = wheel(container, { deltaX: 120, deltaY: 0, ...modifier }) + + expect(container.scrollLeft).toBe(0) + expect(event.defaultPrevented).toBe(false) + }) + + it('does nothing when the container has no horizontal overflow', () => { + const fitted = makeContainer({ scrollWidth: 1000, clientWidth: 1000 }) + const unbindFitted = bindPreviewHorizontalWheel(fitted) + + const event = wheel(fitted, { deltaX: 120, deltaY: 0 }) + + expect(fitted.scrollLeft).toBe(0) + expect(event.defaultPrevented).toBe(false) + unbindFitted() + }) + + it('stops scrolling once unbound', () => { + unbind() + + wheel(container, { deltaX: 120, deltaY: 0 }) + + expect(container.scrollLeft).toBe(0) + }) + + it('scrolls a child gesture, since the listener captures', () => { + const cell = document.createElement('td') + container.appendChild(cell) + + wheel(cell, { deltaX: 80, deltaY: 0 }) + + expect(container.scrollLeft).toBe(80) + }) +}) diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.ts b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.ts index cdb44a2d86d..95bfbd8fe88 100644 --- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.ts +++ b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.ts @@ -8,6 +8,45 @@ interface BindPreviewWheelZoomOptions { onPan?: (event: WheelEvent) => void } +/** + * Horizontal component of a wheel gesture: a trackpad's own `deltaX`, or `deltaY` + * while Shift is held — the only horizontal gesture available on a mouse whose + * wheel reports `deltaY` alone. + */ +function horizontalDeltaOf(event: WheelEvent): number { + return event.deltaX !== 0 ? event.deltaX : event.shiftKey ? event.deltaY : 0 +} + +/** + * Scroll `container` horizontally for a wheel gesture. No-op when the gesture carries + * no horizontal component or the container has nothing to scroll, leaving the event to + * scroll vertically as usual. + */ +function applyHorizontalWheel(container: HTMLElement, event: WheelEvent): void { + const horizontalDelta = horizontalDeltaOf(event) + if (horizontalDelta === 0 || container.scrollWidth <= container.clientWidth) return + + event.preventDefault() + container.scrollLeft += horizontalDelta +} + +/** + * Bind horizontal wheel gestures for a preview scroll container that has no zoom of its + * own — the tabular CSV/XLSX previews, whose table is wider than its frame. A mouse whose + * wheel reports only `deltaY` otherwise has no way to reach that overflow short of dragging + * the scrollbar. Unlike {@link bindPreviewWheelZoom} this leaves `ctrl`/`cmd`+wheel alone, + * so browser page zoom still works over a table. + */ +export function bindPreviewHorizontalWheel(container: HTMLElement): () => void { + const onWheel = (event: WheelEvent) => { + if (event.ctrlKey || event.metaKey) return + applyHorizontalWheel(container, event) + } + + container.addEventListener('wheel', onWheel, { capture: true, passive: false }) + return () => container.removeEventListener('wheel', onWheel, { capture: true }) +} + /** * Bind browser pinch/ctrl-wheel zoom and horizontal wheel gestures for preview * scroll containers. Trackpad pinch fires `wheel` with `ctrlKey=true`; without @@ -34,11 +73,7 @@ export function bindPreviewWheelZoom( return } - const horizontalDelta = event.deltaX !== 0 ? event.deltaX : event.shiftKey ? event.deltaY : 0 - if (horizontalDelta === 0 || container.scrollWidth <= container.clientWidth) return - - event.preventDefault() - container.scrollLeft += horizontalDelta + applyHorizontalWheel(container, event) } container.addEventListener('wheel', onWheel, { capture: true, passive: false }) diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/use-horizontal-wheel-scroll.ts b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/use-horizontal-wheel-scroll.ts new file mode 100644 index 00000000000..d5d941d26c0 --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/use-horizontal-wheel-scroll.ts @@ -0,0 +1,21 @@ +'use client' + +import { useCallback, useRef } from 'react' +import { bindPreviewHorizontalWheel } from '@/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom' + +/** + * Ref callback that gives a preview scroll container horizontal wheel scrolling. + * + * The tabular previews render a table wider than its frame, and a mouse whose wheel + * reports only `deltaY` has no native way to reach the overflow short of dragging the + * scrollbar. Binding is done through a ref callback rather than an effect so the + * listener attaches with the node and detaches when React passes `null`. + */ +export function useHorizontalWheelScroll() { + const unbindRef = useRef<(() => void) | null>(null) + + return useCallback((node: HTMLDivElement | null) => { + unbindRef.current?.() + unbindRef.current = node ? bindPreviewHorizontalWheel(node) : null + }, []) +} diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/xlsx-preview.tsx b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/xlsx-preview.tsx index 98be34a560c..5b27917ca97 100644 --- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/xlsx-preview.tsx +++ b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/xlsx-preview.tsx @@ -10,6 +10,7 @@ import type { WorkspaceFileRecord } from '@/lib/uploads/contexts/workspace' import { DataTable } from './data-table' import { PreviewError, PreviewLoadingFrame, resolvePreviewError } from './preview-shared' import { useDocPreviewBinary } from './use-doc-preview-binary' +import { useHorizontalWheelScroll } from './use-horizontal-wheel-scroll' const logger = createLogger('XlsxPreview') @@ -29,6 +30,7 @@ export const XlsxPreview = memo(function XlsxPreview({ file: WorkspaceFileRecord workspaceId: string }) { + const scrollRef = useHorizontalWheelScroll() const preview = useDocPreviewBinary(workspaceId, file) const fileData = preview.data @@ -130,7 +132,7 @@ export const XlsxPreview = memo(function XlsxPreview({ ))}
-
+
{currentSheet.truncated && (

From 2c11f91a89f9db87f15cfcb30abb5f2c9caa06ef Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 11 Aug 2026 15:57:10 -0700 Subject: [PATCH 2/3] fix(files): keep the vertical component of a diagonal wheel pan Cancelling a wheel event is all-or-nothing, so applying only `scrollLeft` after `preventDefault` dropped a diagonal trackpad pan's `deltaY` entirely. Apply the vertical component too, except under Shift, which remaps `deltaY` onto the horizontal axis and so has none left to spend. --- .../file-viewer/preview-wheel-zoom.test.ts | 21 +++++++++++++++++++ .../file-viewer/preview-wheel-zoom.ts | 20 +++++++++++++++--- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.test.ts b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.test.ts index 53954fff214..2c30f5b19bc 100644 --- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.test.ts +++ b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.test.ts @@ -50,6 +50,27 @@ describe('bindPreviewHorizontalWheel', () => { expect(event.defaultPrevented).toBe(true) }) + /** + * Cancelling a wheel event is all-or-nothing, so a diagonal trackpad pan must have its + * vertical movement re-applied by hand — otherwise `preventDefault` silently eats it. + */ + it('keeps the vertical movement of a diagonal pan', () => { + Object.defineProperty(container, 'scrollHeight', { value: 5000, configurable: true }) + Object.defineProperty(container, 'clientHeight', { value: 500, configurable: true }) + + wheel(container, { deltaX: 40, deltaY: 90 }) + + expect(container.scrollLeft).toBe(40) + expect(container.scrollTop).toBe(90) + }) + + it('does not also spend a shift gesture vertically', () => { + wheel(container, { deltaX: 0, deltaY: 120, shiftKey: true }) + + expect(container.scrollLeft).toBe(120) + expect(container.scrollTop).toBe(0) + }) + it('leaves a plain vertical wheel alone so the container still scrolls down', () => { const event = wheel(container, { deltaX: 0, deltaY: 120 }) diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.ts b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.ts index 95bfbd8fe88..a3e25e3f5c9 100644 --- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.ts +++ b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.ts @@ -18,9 +18,22 @@ function horizontalDeltaOf(event: WheelEvent): number { } /** - * Scroll `container` horizontally for a wheel gesture. No-op when the gesture carries - * no horizontal component or the container has nothing to scroll, leaving the event to - * scroll vertically as usual. + * Vertical component still owed to the container once the horizontal one is taken. + * Shift *remaps* `deltaY` onto the horizontal axis, so that gesture has no vertical + * component left to spend; an ordinary diagonal trackpad pan does. + */ +function verticalDeltaOf(event: WheelEvent): number { + return event.deltaX !== 0 ? event.deltaY : 0 +} + +/** + * Scroll `container` for a wheel gesture carrying a horizontal component. No-op when the + * gesture is purely vertical or the container has nothing to scroll sideways, leaving the + * event to scroll natively. + * + * Cancelling a wheel event is all-or-nothing, so once `preventDefault` is called this owes + * the container *both* axes — a diagonal pan that only had its `deltaX` applied would lose + * its vertical movement entirely. */ function applyHorizontalWheel(container: HTMLElement, event: WheelEvent): void { const horizontalDelta = horizontalDeltaOf(event) @@ -28,6 +41,7 @@ function applyHorizontalWheel(container: HTMLElement, event: WheelEvent): void { event.preventDefault() container.scrollLeft += horizontalDelta + container.scrollTop += verticalDeltaOf(event) } /** From f987a159742c5cc0b8c828c7157db45dfad655a6 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 11 Aug 2026 16:00:45 -0700 Subject: [PATCH 3/3] fix(files): normalize wheel deltas to pixels and import the hook absolutely MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A wheel delta is only in pixels when `deltaMode` says so — Firefox reports mouse wheels in lines — while scroll offsets always are, so a three-line notch moved the table three pixels. Convert line and page deltas before applying them. --- .../file-viewer/csv-table-preview.tsx | 2 +- .../components/file-viewer/preview-panel.tsx | 2 +- .../file-viewer/preview-wheel-zoom.test.ts | 16 ++++++++++++++++ .../file-viewer/preview-wheel-zoom.ts | 18 ++++++++++++++++-- .../components/file-viewer/xlsx-preview.tsx | 2 +- 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/csv-table-preview.tsx b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/csv-table-preview.tsx index 33c6437c923..a3e74315364 100644 --- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/csv-table-preview.tsx +++ b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/csv-table-preview.tsx @@ -2,11 +2,11 @@ import { memo } from 'react' import type { WorkspaceFileRecord } from '@/lib/uploads/contexts/workspace' +import { useHorizontalWheelScroll } from '@/app/workspace/[workspaceId]/files/components/file-viewer/use-horizontal-wheel-scroll' import { useWorkspaceCsvPreview } from '@/hooks/queries/workspace-file-table' import { useCsvTruncationImport } from './csv-import' import { DataTable } from './data-table' import { PreviewError, PreviewLoadingFrame, resolvePreviewError } from './preview-shared' -import { useHorizontalWheelScroll } from './use-horizontal-wheel-scroll' /** * Read-only preview for a CSV that is too large to load fully into the editor. Streams only the diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-panel.tsx b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-panel.tsx index fc55e408ce8..8fca660715d 100644 --- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-panel.tsx +++ b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-panel.tsx @@ -4,10 +4,10 @@ import { memo, useEffect, useMemo, useRef, useState } from 'react' import '@sim/emcn/components/code/code.css' import { CSV_PREVIEW_MAX_ROWS } from '@/lib/api/contracts/workspace-file-table' import { getFileExtension } from '@/lib/uploads/utils/file-utils' +import { useHorizontalWheelScroll } from '@/app/workspace/[workspaceId]/files/components/file-viewer/use-horizontal-wheel-scroll' import { type CsvImportFileDescriptor, useCsvTruncationImport } from './csv-import' import { DataTable } from './data-table' import { MermaidDiagram } from './mermaid-diagram' -import { useHorizontalWheelScroll } from './use-horizontal-wheel-scroll' import { ZoomablePreview } from './zoomable-preview' type PreviewType = 'markdown' | 'html' | 'csv' | 'svg' | 'mermaid' | null diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.test.ts b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.test.ts index 2c30f5b19bc..2d57af9d430 100644 --- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.test.ts +++ b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.test.ts @@ -71,6 +71,22 @@ describe('bindPreviewHorizontalWheel', () => { expect(container.scrollTop).toBe(0) }) + /** + * `deltaMode` is not always pixels — Firefox reports mouse wheels in lines — while scroll + * offsets always are, so a three-line notch added raw would move the table three pixels. + */ + it('converts a line-mode delta to pixels', () => { + wheel(container, { deltaX: 3, deltaY: 0, deltaMode: WheelEvent.DOM_DELTA_LINE }) + + expect(container.scrollLeft).toBe(48) + }) + + it('converts a page-mode delta to the container width', () => { + wheel(container, { deltaX: 1, deltaY: 0, deltaMode: WheelEvent.DOM_DELTA_PAGE }) + + expect(container.scrollLeft).toBe(1000) + }) + it('leaves a plain vertical wheel alone so the container still scrolls down', () => { const event = wheel(container, { deltaX: 0, deltaY: 120 }) diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.ts b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.ts index a3e25e3f5c9..3535ccbabba 100644 --- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.ts +++ b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-wheel-zoom.ts @@ -26,6 +26,20 @@ function verticalDeltaOf(event: WheelEvent): number { return event.deltaX !== 0 ? event.deltaY : 0 } +/** + * Rough pixel height of one wheel "line". A wheel delta is only in pixels when `deltaMode` + * says so — Firefox reports mouse wheels in lines — while scroll offsets are always pixels, + * so a three-line notch added raw would move the table three pixels. + */ +const WHEEL_LINE_HEIGHT_PX = 16 + +/** Convert a wheel delta to pixels. `pageSize` is the container extent along that axis. */ +function toPixels(delta: number, event: WheelEvent, pageSize: number): number { + if (event.deltaMode === WheelEvent.DOM_DELTA_LINE) return delta * WHEEL_LINE_HEIGHT_PX + if (event.deltaMode === WheelEvent.DOM_DELTA_PAGE) return delta * pageSize + return delta +} + /** * Scroll `container` for a wheel gesture carrying a horizontal component. No-op when the * gesture is purely vertical or the container has nothing to scroll sideways, leaving the @@ -40,8 +54,8 @@ function applyHorizontalWheel(container: HTMLElement, event: WheelEvent): void { if (horizontalDelta === 0 || container.scrollWidth <= container.clientWidth) return event.preventDefault() - container.scrollLeft += horizontalDelta - container.scrollTop += verticalDeltaOf(event) + container.scrollLeft += toPixels(horizontalDelta, event, container.clientWidth) + container.scrollTop += toPixels(verticalDeltaOf(event), event, container.clientHeight) } /** diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/xlsx-preview.tsx b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/xlsx-preview.tsx index 5b27917ca97..3fbc5993826 100644 --- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/xlsx-preview.tsx +++ b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/xlsx-preview.tsx @@ -7,10 +7,10 @@ import { toError } from '@sim/utils/errors' import type { WorkBook } from 'xlsx' import { assertOoxmlPreviewWithinLimits } from '@/lib/file-parsers/ooxml-preview-guard' import type { WorkspaceFileRecord } from '@/lib/uploads/contexts/workspace' +import { useHorizontalWheelScroll } from '@/app/workspace/[workspaceId]/files/components/file-viewer/use-horizontal-wheel-scroll' import { DataTable } from './data-table' import { PreviewError, PreviewLoadingFrame, resolvePreviewError } from './preview-shared' import { useDocPreviewBinary } from './use-doc-preview-binary' -import { useHorizontalWheelScroll } from './use-horizontal-wheel-scroll' const logger = createLogger('XlsxPreview')