This commit is contained in:
Reece 2025-10-28 18:09:55 +00:00
parent 3bd1c9f83a
commit c6c986ade2
5 changed files with 107 additions and 69 deletions

View File

@ -2,6 +2,11 @@ import React, { useRef, useEffect, useState, useCallback, useMemo } from 'react'
import { Box } from '@mantine/core';
import { useVirtualizer } from '@tanstack/react-virtual';
import { GRID_CONSTANTS } from './constants';
import {
Z_INDEX_SELECTION_BOX,
Z_INDEX_DROP_INDICATOR,
Z_INDEX_DRAG_BADGE,
} from '../../styles/zIndex';
import {
DndContext,
DragEndEvent,
@ -564,7 +569,7 @@ const DragDropGrid = <T extends DragDropItem>({
border: '2px dashed #3b82f6',
backgroundColor: 'rgba(59, 130, 246, 0.1)',
pointerEvents: 'none' as const,
zIndex: 1000,
zIndex: Z_INDEX_SELECTION_BOX,
} : null;
// Calculate drop indicator position
@ -592,7 +597,7 @@ const DragDropGrid = <T extends DragDropItem>({
height: `${height}px`,
backgroundColor: 'rgba(96, 165, 250, 0.8)',
borderRadius: '2px',
zIndex: 1001,
zIndex: Z_INDEX_DROP_INDICATOR,
pointerEvents: 'none' as const,
};
}, [hoveredItemId, dropSide, activeId, itemGap, zoomLevel]);
@ -738,7 +743,7 @@ const DragDropGrid = <T extends DragDropItem>({
fontSize: '14px',
fontWeight: 'bold',
boxShadow: '0 2px 8px rgba(0,0,0,0.2)',
zIndex: 1001
zIndex: Z_INDEX_DRAG_BADGE
}}
>
{boxSelectedPageIds.length}

View File

@ -31,6 +31,7 @@ import { usePageEditorState } from './hooks/usePageEditorState';
import { parseSelection } from "@app/utils/bulkselection/parseSelection";
import { usePageEditorRightRailButtons } from "@app/components/pageEditor/pageEditorRightRailButtons";
import { useFileColorMap } from "@app/components/pageEditor/hooks/useFileColorMap";
import { useWheelZoom } from "@app/hooks/useWheelZoom";
export interface PageEditorProps {
onFunctionsReady?: (functions: PageEditorFunctions) => void;
@ -981,39 +982,12 @@ const PageEditor = ({
selectionMode, selectedPageIds, splitPositions, displayDocument?.pages.length, closePdf
]);
// Handle scroll wheel zoom with accumulator for smooth trackpad pinch
useEffect(() => {
let accumulator = 0;
const handleWheel = (event: WheelEvent) => {
// Check if Ctrl (Windows/Linux) or Cmd (Mac) is pressed
if (event.ctrlKey || event.metaKey) {
event.preventDefault();
event.stopPropagation();
accumulator += event.deltaY;
const threshold = 10;
if (accumulator <= -threshold) {
// Accumulated scroll up - zoom in
zoomIn();
accumulator = 0;
} else if (accumulator >= threshold) {
// Accumulated scroll down - zoom out
zoomOut();
accumulator = 0;
}
}
};
const container = containerRef.current;
if (container) {
container.addEventListener('wheel', handleWheel, { passive: false });
return () => {
container.removeEventListener('wheel', handleWheel);
};
}
}, [zoomIn, zoomOut]);
useWheelZoom({
ref: containerRef,
onZoomIn: zoomIn,
onZoomOut: zoomOut,
enabled: !!displayDocument,
});
// Handle keyboard zoom shortcuts
useEffect(() => {

View File

@ -14,6 +14,7 @@ import { createStirlingFilesAndStubs } from '@app/services/fileStubHelpers';
import NavigationWarningModal from '@app/components/shared/NavigationWarningModal';
import { isStirlingFile } from '@app/types/fileContext';
import { useViewerRightRailButtons } from '@app/components/viewer/useViewerRightRailButtons';
import { useWheelZoom } from '@app/hooks/useWheelZoom';
export interface EmbedPdfViewerProps {
sidebarsVisible: boolean;
@ -124,39 +125,11 @@ const EmbedPdfViewerContent = ({
}
}, [previewFile, fileWithUrl]);
// Handle scroll wheel zoom with accumulator for smooth trackpad pinch
useEffect(() => {
let accumulator = 0;
const handleWheel = (event: WheelEvent) => {
// Check if Ctrl (Windows/Linux) or Cmd (Mac) is pressed
if (event.ctrlKey || event.metaKey) {
event.preventDefault();
event.stopPropagation();
accumulator += event.deltaY;
const threshold = 10;
if (accumulator <= -threshold) {
// Accumulated scroll up - zoom in
zoomActions.zoomIn();
accumulator = 0;
} else if (accumulator >= threshold) {
// Accumulated scroll down - zoom out
zoomActions.zoomOut();
accumulator = 0;
}
}
};
const viewerElement = viewerRef.current;
if (viewerElement) {
viewerElement.addEventListener('wheel', handleWheel, { passive: false });
return () => {
viewerElement.removeEventListener('wheel', handleWheel);
};
}
}, [zoomActions]);
useWheelZoom({
ref: viewerRef,
onZoomIn: zoomActions.zoomIn,
onZoomOut: zoomActions.zoomOut,
});
// Handle keyboard zoom shortcuts
useEffect(() => {

View File

@ -0,0 +1,82 @@
import { RefObject, useEffect } from 'react';
interface UseWheelZoomOptions {
/**
* Element the wheel listener should be bound to.
*/
ref: RefObject<Element | null>;
/**
* Callback executed when the hook decides to zoom in.
*/
onZoomIn: () => void;
/**
* Callback executed when the hook decides to zoom out.
*/
onZoomOut: () => void;
/**
* Whether the wheel listener should be active.
*/
enabled?: boolean;
/**
* How much delta needs to accumulate before a zoom action is triggered.
* Defaults to 10 which matches the previous implementations.
*/
threshold?: number;
/**
* Whether a Ctrl/Cmd modifier is required for zooming. Defaults to true so
* we only react to pinch gestures and intentional ctrl+wheel zooming.
*/
requireModifierKey?: boolean;
}
/**
* Shared hook for handling wheel-based zoom across components.
* It normalises accumulated delta behaviour, prevents default scrolling when
* zoom is triggered, and keeps the handler detached when disabled.
*/
export function useWheelZoom({
ref,
onZoomIn,
onZoomOut,
enabled = true,
threshold = 10,
requireModifierKey = true,
}: UseWheelZoomOptions) {
useEffect(() => {
if (!enabled) {
return;
}
const element = ref.current;
if (!element) {
return;
}
let accumulator = 0;
const handleWheel = (event: WheelEvent) => {
const hasModifier = event.ctrlKey || event.metaKey;
if (requireModifierKey && !hasModifier) {
return;
}
event.preventDefault();
event.stopPropagation();
accumulator += event.deltaY;
if (accumulator <= -threshold) {
onZoomIn();
accumulator = 0;
} else if (accumulator >= threshold) {
onZoomOut();
accumulator = 0;
}
};
element.addEventListener('wheel', handleWheel, { passive: false });
return () => {
element.removeEventListener('wheel', handleWheel);
};
}, [ref, onZoomIn, onZoomOut, enabled, threshold, requireModifierKey]);
}

View File

@ -10,5 +10,9 @@ export const Z_INDEX_OVER_FILE_MANAGER_MODAL = 1300;
export const Z_INDEX_AUTOMATE_MODAL = 1100;
export const Z_INDEX_SELECTION_BOX = 1000;
export const Z_INDEX_DROP_INDICATOR = 1001;
export const Z_INDEX_DRAG_BADGE = 1001;