mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-08-26 14:19:24 +00:00
use refs rather than document query selection to find tooltip position (or just to find sidebar rect for furture features that require it)
This commit is contained in:
parent
aff93c4008
commit
eee931e4a2
@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useRef } from "react";
|
import React, { useState, useRef, forwardRef } from "react";
|
||||||
import { ActionIcon, Stack, Tooltip, Divider } from "@mantine/core";
|
import { ActionIcon, Stack, Tooltip, Divider } from "@mantine/core";
|
||||||
import MenuBookIcon from "@mui/icons-material/MenuBookRounded";
|
import MenuBookIcon from "@mui/icons-material/MenuBookRounded";
|
||||||
import AppsIcon from "@mui/icons-material/AppsRounded";
|
import AppsIcon from "@mui/icons-material/AppsRounded";
|
||||||
@ -8,32 +8,12 @@ import FolderIcon from "@mui/icons-material/FolderRounded";
|
|||||||
import PersonIcon from "@mui/icons-material/PersonRounded";
|
import PersonIcon from "@mui/icons-material/PersonRounded";
|
||||||
import NotificationsIcon from "@mui/icons-material/NotificationsRounded";
|
import NotificationsIcon from "@mui/icons-material/NotificationsRounded";
|
||||||
import { useRainbowThemeContext } from "./RainbowThemeProvider";
|
import { useRainbowThemeContext } from "./RainbowThemeProvider";
|
||||||
import rainbowStyles from '../../styles/rainbow.module.css';
|
|
||||||
import AppConfigModal from './AppConfigModal';
|
import AppConfigModal from './AppConfigModal';
|
||||||
import { useIsOverflowing } from '../../hooks/useIsOverflowing';
|
import { useIsOverflowing } from '../../hooks/useIsOverflowing';
|
||||||
import { useFilesModalContext } from '../../contexts/FilesModalContext';
|
import { useFilesModalContext } from '../../contexts/FilesModalContext';
|
||||||
|
import { QuickAccessBarProps, ButtonConfig } from '../../types/sidebar';
|
||||||
import './QuickAccessBar.css';
|
import './QuickAccessBar.css';
|
||||||
|
|
||||||
interface QuickAccessBarProps {
|
|
||||||
onToolsClick: () => void;
|
|
||||||
onReaderToggle: () => void;
|
|
||||||
selectedToolKey?: string;
|
|
||||||
toolRegistry: any;
|
|
||||||
leftPanelView: 'toolPicker' | 'toolContent';
|
|
||||||
readerMode: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ButtonConfig {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
icon: React.ReactNode;
|
|
||||||
tooltip: string;
|
|
||||||
isRound?: boolean;
|
|
||||||
size?: 'sm' | 'md' | 'lg' | 'xl';
|
|
||||||
onClick: () => void;
|
|
||||||
type?: 'navigation' | 'modal' | 'action'; // navigation = main nav, modal = triggers modal, action = other actions
|
|
||||||
}
|
|
||||||
|
|
||||||
function NavHeader({
|
function NavHeader({
|
||||||
activeButton,
|
activeButton,
|
||||||
setActiveButton,
|
setActiveButton,
|
||||||
@ -104,14 +84,10 @@ function NavHeader({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const QuickAccessBar = ({
|
const QuickAccessBar = forwardRef<HTMLDivElement, QuickAccessBarProps>(({
|
||||||
onToolsClick,
|
onToolsClick,
|
||||||
onReaderToggle,
|
onReaderToggle,
|
||||||
selectedToolKey,
|
}, ref) => {
|
||||||
toolRegistry,
|
|
||||||
leftPanelView,
|
|
||||||
readerMode,
|
|
||||||
}: QuickAccessBarProps) => {
|
|
||||||
const { isRainbowMode } = useRainbowThemeContext();
|
const { isRainbowMode } = useRainbowThemeContext();
|
||||||
const { openFilesModal, isFilesModalOpen } = useFilesModalContext();
|
const { openFilesModal, isFilesModalOpen } = useFilesModalContext();
|
||||||
const [configModalOpen, setConfigModalOpen] = useState(false);
|
const [configModalOpen, setConfigModalOpen] = useState(false);
|
||||||
@ -234,6 +210,7 @@ const QuickAccessBar = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
ref={ref}
|
||||||
data-sidebar="quick-access"
|
data-sidebar="quick-access"
|
||||||
className={`h-screen flex flex-col w-20 quick-access-bar-main ${isRainbowMode ? 'rainbow-mode' : ''}`}
|
className={`h-screen flex flex-col w-20 quick-access-bar-main ${isRainbowMode ? 'rainbow-mode' : ''}`}
|
||||||
>
|
>
|
||||||
@ -336,6 +313,6 @@ const QuickAccessBar = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
export default QuickAccessBar;
|
export default QuickAccessBar;
|
@ -3,6 +3,7 @@ import { createPortal } from 'react-dom';
|
|||||||
import { isClickOutside, addEventListenerWithCleanup } from '../../utils/genericUtils';
|
import { isClickOutside, addEventListenerWithCleanup } from '../../utils/genericUtils';
|
||||||
import { useTooltipPosition } from '../../hooks/useTooltipPosition';
|
import { useTooltipPosition } from '../../hooks/useTooltipPosition';
|
||||||
import { TooltipContent, TooltipTip } from './tooltip/TooltipContent';
|
import { TooltipContent, TooltipTip } from './tooltip/TooltipContent';
|
||||||
|
import { useSidebarContext } from '../../contexts/SidebarContext';
|
||||||
import styles from './tooltip/Tooltip.module.css'
|
import styles from './tooltip/Tooltip.module.css'
|
||||||
|
|
||||||
export interface TooltipProps {
|
export interface TooltipProps {
|
||||||
@ -43,6 +44,9 @@ export const Tooltip: React.FC<TooltipProps> = ({
|
|||||||
const tooltipRef = useRef<HTMLDivElement>(null);
|
const tooltipRef = useRef<HTMLDivElement>(null);
|
||||||
const hoverTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
const hoverTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||||
|
|
||||||
|
// Get sidebar context for tooltip positioning
|
||||||
|
const sidebarContext = sidebarTooltip ? useSidebarContext() : null;
|
||||||
|
|
||||||
// Always use controlled mode - if no controlled props provided, use internal state
|
// Always use controlled mode - if no controlled props provided, use internal state
|
||||||
const isControlled = controlledOpen !== undefined;
|
const isControlled = controlledOpen !== undefined;
|
||||||
const open = isControlled ? controlledOpen : internalOpen;
|
const open = isControlled ? controlledOpen : internalOpen;
|
||||||
@ -80,7 +84,9 @@ export const Tooltip: React.FC<TooltipProps> = ({
|
|||||||
position,
|
position,
|
||||||
gap,
|
gap,
|
||||||
triggerRef,
|
triggerRef,
|
||||||
tooltipRef
|
tooltipRef,
|
||||||
|
sidebarRefs: sidebarContext?.sidebarRefs,
|
||||||
|
sidebarState: sidebarContext?.sidebarState
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add document click listener for unpinning
|
// Add document click listener for unpinning
|
||||||
|
@ -217,5 +217,7 @@ Links automatically get proper styling with hover states and open in new tabs wh
|
|||||||
### Sidebar Tooltips
|
### Sidebar Tooltips
|
||||||
- When `sidebarTooltip={true}`, horizontal positioning is locked to the right of the sidebar
|
- When `sidebarTooltip={true}`, horizontal positioning is locked to the right of the sidebar
|
||||||
- Vertical positioning follows the trigger but clamps to viewport
|
- Vertical positioning follows the trigger but clamps to viewport
|
||||||
- Automatically detects sidebar width or falls back to 240px
|
- **Smart sidebar detection**: Uses `getSidebarInfo()` to determine which sidebar is active (tool panel vs quick access bar) and gets its exact position
|
||||||
|
- **Dynamic positioning**: Adapts to whether the tool panel is expanded or collapsed
|
||||||
|
- **Conditional display**: Only shows tooltips when the tool panel is active (`sidebarInfo.isToolPanelActive`)
|
||||||
- **No arrows** - sidebar tooltips don't show arrows
|
- **No arrows** - sidebar tooltips don't show arrows
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { TooltipContent } from './types';
|
import { TooltipContent } from '../../types/tips';
|
||||||
|
|
||||||
export const CompressTips = (): TooltipContent => {
|
export const CompressTips = (): TooltipContent => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { TooltipContent } from './types';
|
import { TooltipContent } from '../../types/tips';
|
||||||
|
|
||||||
export const OcrTips = (): TooltipContent => {
|
export const OcrTips = (): TooltipContent => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
47
frontend/src/contexts/SidebarContext.tsx
Normal file
47
frontend/src/contexts/SidebarContext.tsx
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import React, { createContext, useContext, useState, useRef } from 'react';
|
||||||
|
import { SidebarState, SidebarRefs, SidebarContextValue, SidebarProviderProps } from '../types/sidebar';
|
||||||
|
|
||||||
|
const SidebarContext = createContext<SidebarContextValue | undefined>(undefined);
|
||||||
|
|
||||||
|
export function SidebarProvider({ children }: SidebarProviderProps) {
|
||||||
|
// All sidebar state management
|
||||||
|
const quickAccessRef = useRef<HTMLDivElement>(null);
|
||||||
|
const toolPanelRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const [sidebarsVisible, setSidebarsVisible] = useState(true);
|
||||||
|
const [leftPanelView, setLeftPanelView] = useState<'toolPicker' | 'toolContent'>('toolPicker');
|
||||||
|
const [readerMode, setReaderMode] = useState(false);
|
||||||
|
|
||||||
|
const sidebarState: SidebarState = {
|
||||||
|
sidebarsVisible,
|
||||||
|
leftPanelView,
|
||||||
|
readerMode,
|
||||||
|
};
|
||||||
|
|
||||||
|
const sidebarRefs: SidebarRefs = {
|
||||||
|
quickAccessRef,
|
||||||
|
toolPanelRef,
|
||||||
|
};
|
||||||
|
|
||||||
|
const contextValue: SidebarContextValue = {
|
||||||
|
sidebarState,
|
||||||
|
sidebarRefs,
|
||||||
|
setSidebarsVisible,
|
||||||
|
setLeftPanelView,
|
||||||
|
setReaderMode,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SidebarContext.Provider value={contextValue}>
|
||||||
|
{children}
|
||||||
|
</SidebarContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useSidebarContext(): SidebarContextValue {
|
||||||
|
const context = useContext(SidebarContext);
|
||||||
|
if (context === undefined) {
|
||||||
|
throw new Error('useSidebarContext must be used within a SidebarProvider');
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import { useState, useEffect, useMemo } from 'react';
|
import { useState, useEffect, useMemo } from 'react';
|
||||||
import { clamp } from '../utils/genericUtils';
|
import { clamp } from '../utils/genericUtils';
|
||||||
import { getSidebarRect } from '../utils/sidebarUtils';
|
import { getSidebarInfo } from '../utils/sidebarUtils';
|
||||||
|
import { SidebarRefs, SidebarState } from '../types/sidebar';
|
||||||
|
|
||||||
type Position = 'right' | 'left' | 'top' | 'bottom';
|
type Position = 'right' | 'left' | 'top' | 'bottom';
|
||||||
|
|
||||||
@ -51,7 +52,9 @@ export function useTooltipPosition({
|
|||||||
position,
|
position,
|
||||||
gap,
|
gap,
|
||||||
triggerRef,
|
triggerRef,
|
||||||
tooltipRef
|
tooltipRef,
|
||||||
|
sidebarRefs,
|
||||||
|
sidebarState
|
||||||
}: {
|
}: {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
sidebarTooltip: boolean;
|
sidebarTooltip: boolean;
|
||||||
@ -59,6 +62,8 @@ export function useTooltipPosition({
|
|||||||
gap: number;
|
gap: number;
|
||||||
triggerRef: React.RefObject<HTMLElement | null>;
|
triggerRef: React.RefObject<HTMLElement | null>;
|
||||||
tooltipRef: React.RefObject<HTMLDivElement | null>;
|
tooltipRef: React.RefObject<HTMLDivElement | null>;
|
||||||
|
sidebarRefs?: SidebarRefs;
|
||||||
|
sidebarState?: SidebarState;
|
||||||
}): PositionState {
|
}): PositionState {
|
||||||
const [coords, setCoords] = useState<{ top: number; left: number; arrowOffset: number | null }>({
|
const [coords, setCoords] = useState<{ top: number; left: number; arrowOffset: number | null }>({
|
||||||
top: 0,
|
top: 0,
|
||||||
@ -67,12 +72,8 @@ export function useTooltipPosition({
|
|||||||
});
|
});
|
||||||
const [positionReady, setPositionReady] = useState(false);
|
const [positionReady, setPositionReady] = useState(false);
|
||||||
|
|
||||||
// Memoize sidebar position for performance
|
// Fallback sidebar position (only used as last resort)
|
||||||
const sidebarLeft = useMemo(() => {
|
const sidebarLeft = 240;
|
||||||
if (!sidebarTooltip) return 0;
|
|
||||||
const sidebarInfo = getSidebarRect();
|
|
||||||
return sidebarInfo.rect ? sidebarInfo.rect.right : 240;
|
|
||||||
}, [sidebarTooltip]);
|
|
||||||
|
|
||||||
const updatePosition = () => {
|
const updatePosition = () => {
|
||||||
if (!triggerRef.current || !open) return;
|
if (!triggerRef.current || !open) return;
|
||||||
@ -84,18 +85,24 @@ export function useTooltipPosition({
|
|||||||
let arrowOffset: number | null = null;
|
let arrowOffset: number | null = null;
|
||||||
|
|
||||||
if (sidebarTooltip) {
|
if (sidebarTooltip) {
|
||||||
// Get fresh sidebar position each time
|
// Require sidebar refs and state for proper positioning
|
||||||
const sidebarInfo = getSidebarRect();
|
if (!sidebarRefs || !sidebarState) {
|
||||||
const currentSidebarRight = sidebarInfo.rect ? sidebarInfo.rect.right : sidebarLeft;
|
console.warn('⚠️ Sidebar tooltip requires sidebarRefs and sidebarState props');
|
||||||
|
|
||||||
// Only show tooltip if we have the correct sidebar (ToolPanel)
|
|
||||||
if (!sidebarInfo.isCorrectSidebar) {
|
|
||||||
console.log('🚫 Not showing tooltip - wrong sidebar detected');
|
|
||||||
setPositionReady(false);
|
setPositionReady(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Position to the right of correct sidebar with 20px gap
|
const sidebarInfo = getSidebarInfo(sidebarRefs, sidebarState);
|
||||||
|
const currentSidebarRight = sidebarInfo.rect ? sidebarInfo.rect.right : sidebarLeft;
|
||||||
|
|
||||||
|
// Only show tooltip if we have the tool panel active
|
||||||
|
if (!sidebarInfo.isToolPanelActive) {
|
||||||
|
console.log('🚫 Not showing tooltip - tool panel not active');
|
||||||
|
setPositionReady(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Position to the right of active sidebar with 20px gap
|
||||||
left = currentSidebarRight + 20;
|
left = currentSidebarRight + 20;
|
||||||
top = triggerRect.top; // Align top of tooltip with trigger element
|
top = triggerRect.top; // Align top of tooltip with trigger element
|
||||||
|
|
||||||
|
@ -2,11 +2,13 @@ import React, { useState, useCallback, useEffect, useRef } from "react";
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useFileContext } from "../contexts/FileContext";
|
import { useFileContext } from "../contexts/FileContext";
|
||||||
import { FileSelectionProvider, useFileSelection } from "../contexts/FileSelectionContext";
|
import { FileSelectionProvider, useFileSelection } from "../contexts/FileSelectionContext";
|
||||||
|
import { SidebarProvider, useSidebarContext } from "../contexts/SidebarContext";
|
||||||
import { useToolManagement } from "../hooks/useToolManagement";
|
import { useToolManagement } from "../hooks/useToolManagement";
|
||||||
import { useFileHandler } from "../hooks/useFileHandler";
|
import { useFileHandler } from "../hooks/useFileHandler";
|
||||||
import { Group, Box, Button } from "@mantine/core";
|
import { Group, Box, Button } from "@mantine/core";
|
||||||
import { useRainbowThemeContext } from "../components/shared/RainbowThemeProvider";
|
import { useRainbowThemeContext } from "../components/shared/RainbowThemeProvider";
|
||||||
import { PageEditorFunctions } from "../types/pageEditor";
|
import { PageEditorFunctions } from "../types/pageEditor";
|
||||||
|
import { SidebarRefs, SidebarState } from "../types/sidebar";
|
||||||
import rainbowStyles from '../styles/rainbow.module.css';
|
import rainbowStyles from '../styles/rainbow.module.css';
|
||||||
|
|
||||||
import ToolPicker from "../components/tools/ToolPicker";
|
import ToolPicker from "../components/tools/ToolPicker";
|
||||||
@ -20,9 +22,20 @@ import QuickAccessBar from "../components/shared/QuickAccessBar";
|
|||||||
import LandingPage from "../components/shared/LandingPage";
|
import LandingPage from "../components/shared/LandingPage";
|
||||||
import FileUploadModal from "../components/shared/FileUploadModal";
|
import FileUploadModal from "../components/shared/FileUploadModal";
|
||||||
|
|
||||||
|
|
||||||
function HomePageContent() {
|
function HomePageContent() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { isRainbowMode } = useRainbowThemeContext();
|
const { isRainbowMode } = useRainbowThemeContext();
|
||||||
|
const {
|
||||||
|
sidebarState,
|
||||||
|
sidebarRefs,
|
||||||
|
setSidebarsVisible,
|
||||||
|
setLeftPanelView,
|
||||||
|
setReaderMode
|
||||||
|
} = useSidebarContext();
|
||||||
|
|
||||||
|
const { sidebarsVisible, leftPanelView, readerMode } = sidebarState;
|
||||||
|
const { quickAccessRef, toolPanelRef } = sidebarRefs;
|
||||||
|
|
||||||
const fileContext = useFileContext();
|
const fileContext = useFileContext();
|
||||||
const { activeFiles, currentView, setCurrentView } = fileContext;
|
const { activeFiles, currentView, setCurrentView } = fileContext;
|
||||||
@ -37,9 +50,6 @@ function HomePageContent() {
|
|||||||
clearToolSelection,
|
clearToolSelection,
|
||||||
} = useToolManagement();
|
} = useToolManagement();
|
||||||
|
|
||||||
const [sidebarsVisible, setSidebarsVisible] = useState(true);
|
|
||||||
const [leftPanelView, setLeftPanelView] = useState<'toolPicker' | 'toolContent'>('toolPicker');
|
|
||||||
const [readerMode, setReaderMode] = useState(false);
|
|
||||||
const [pageEditorFunctions, setPageEditorFunctions] = useState<PageEditorFunctions | null>(null);
|
const [pageEditorFunctions, setPageEditorFunctions] = useState<PageEditorFunctions | null>(null);
|
||||||
const [previewFile, setPreviewFile] = useState<File | null>(null);
|
const [previewFile, setPreviewFile] = useState<File | null>(null);
|
||||||
|
|
||||||
@ -92,16 +102,14 @@ function HomePageContent() {
|
|||||||
>
|
>
|
||||||
{/* Quick Access Bar */}
|
{/* Quick Access Bar */}
|
||||||
<QuickAccessBar
|
<QuickAccessBar
|
||||||
|
ref={quickAccessRef}
|
||||||
onToolsClick={handleQuickAccessTools}
|
onToolsClick={handleQuickAccessTools}
|
||||||
onReaderToggle={handleReaderToggle}
|
onReaderToggle={handleReaderToggle}
|
||||||
selectedToolKey={selectedToolKey}
|
|
||||||
toolRegistry={toolRegistry}
|
|
||||||
leftPanelView={leftPanelView}
|
|
||||||
readerMode={readerMode}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Left: Tool Picker or Selected Tool Panel */}
|
{/* Left: Tool Picker or Selected Tool Panel */}
|
||||||
<div
|
<div
|
||||||
|
ref={toolPanelRef}
|
||||||
data-sidebar="tool-panel"
|
data-sidebar="tool-panel"
|
||||||
className={`h-screen flex flex-col overflow-hidden bg-[var(--bg-toolbar)] border-r border-[var(--border-subtle)] transition-all duration-300 ease-out ${isRainbowMode ? rainbowStyles.rainbowPaper : ''}`}
|
className={`h-screen flex flex-col overflow-hidden bg-[var(--bg-toolbar)] border-r border-[var(--border-subtle)] transition-all duration-300 ease-out ${isRainbowMode ? rainbowStyles.rainbowPaper : ''}`}
|
||||||
style={{
|
style={{
|
||||||
@ -280,7 +288,9 @@ function HomePageContent() {
|
|||||||
export default function HomePage() {
|
export default function HomePage() {
|
||||||
return (
|
return (
|
||||||
<FileSelectionProvider>
|
<FileSelectionProvider>
|
||||||
<HomePageContent />
|
<SidebarProvider>
|
||||||
|
<HomePageContent />
|
||||||
|
</SidebarProvider>
|
||||||
</FileSelectionProvider>
|
</FileSelectionProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
46
frontend/src/types/sidebar.ts
Normal file
46
frontend/src/types/sidebar.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
export interface SidebarState {
|
||||||
|
sidebarsVisible: boolean;
|
||||||
|
leftPanelView: 'toolPicker' | 'toolContent';
|
||||||
|
readerMode: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SidebarRefs {
|
||||||
|
quickAccessRef: React.RefObject<HTMLDivElement | null>;
|
||||||
|
toolPanelRef: React.RefObject<HTMLDivElement | null>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SidebarInfo {
|
||||||
|
rect: DOMRect | null;
|
||||||
|
isToolPanelActive: boolean;
|
||||||
|
sidebarState: SidebarState;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Context-related interfaces
|
||||||
|
export interface SidebarContextValue {
|
||||||
|
sidebarState: SidebarState;
|
||||||
|
sidebarRefs: SidebarRefs;
|
||||||
|
setSidebarsVisible: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
setLeftPanelView: React.Dispatch<React.SetStateAction<'toolPicker' | 'toolContent'>>;
|
||||||
|
setReaderMode: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SidebarProviderProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QuickAccessBar related interfaces
|
||||||
|
export interface QuickAccessBarProps {
|
||||||
|
onToolsClick: () => void;
|
||||||
|
onReaderToggle: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ButtonConfig {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
icon: React.ReactNode;
|
||||||
|
tooltip: string;
|
||||||
|
isRound?: boolean;
|
||||||
|
size?: 'sm' | 'md' | 'lg' | 'xl';
|
||||||
|
onClick: () => void;
|
||||||
|
type?: 'navigation' | 'modal' | 'action';
|
||||||
|
}
|
@ -1,50 +1,34 @@
|
|||||||
|
import { SidebarRefs, SidebarState, SidebarInfo } from '../types/sidebar';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the All tools sidebar
|
* Gets the All tools sidebar information using React refs and state
|
||||||
* @returns Object containing the sidebar rect and whether it's the correct sidebar
|
* @param refs - Object containing refs to sidebar elements
|
||||||
|
* @param state - Current sidebar state
|
||||||
|
* @returns Object containing the sidebar rect and whether the tool panel is active
|
||||||
*/
|
*/
|
||||||
export function getSidebarRect(): { rect: DOMRect | null, isCorrectSidebar: boolean } {
|
export function getSidebarInfo(refs: SidebarRefs, state: SidebarState): SidebarInfo {
|
||||||
// Find the rightmost sidebar - this will be the "All Tools" expanded panel
|
const { quickAccessRef, toolPanelRef } = refs;
|
||||||
const allSidebars = [];
|
const { sidebarsVisible, readerMode } = state;
|
||||||
|
|
||||||
// Find the QuickAccessBar (narrow left bar)
|
// Determine if tool panel should be active based on state
|
||||||
const quickAccessBar = document.querySelector('[data-sidebar="quick-access"]');
|
const isToolPanelActive = sidebarsVisible && !readerMode;
|
||||||
if (quickAccessBar) {
|
|
||||||
const rect = quickAccessBar.getBoundingClientRect();
|
|
||||||
if (rect.width > 0) {
|
|
||||||
allSidebars.push({
|
|
||||||
element: 'QuickAccessBar',
|
|
||||||
selector: '[data-sidebar="quick-access"]',
|
|
||||||
rect
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the tool panel (the expanded "All Tools" panel)
|
let rect: DOMRect | null = null;
|
||||||
const toolPanel = document.querySelector('[data-sidebar="tool-panel"]');
|
|
||||||
if (toolPanel) {
|
|
||||||
const rect = toolPanel.getBoundingClientRect();
|
|
||||||
if (rect.width > 0) {
|
|
||||||
allSidebars.push({
|
|
||||||
element: 'ToolPanel',
|
|
||||||
selector: '[data-sidebar="tool-panel"]',
|
|
||||||
rect
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the rightmost sidebar (which should be the tool panel when expanded)
|
if (isToolPanelActive && toolPanelRef.current) {
|
||||||
if (allSidebars.length > 0) {
|
// Tool panel is expanded: use its rect
|
||||||
const rightmostSidebar = allSidebars.reduce((rightmost, current) => {
|
rect = toolPanelRef.current.getBoundingClientRect();
|
||||||
return current.rect.right > rightmost.rect.right ? current : rightmost;
|
} else if (quickAccessRef.current) {
|
||||||
});
|
// Fall back to quick access bar
|
||||||
|
// This probably isn't needed but if we ever have tooltips or modals that need to be positioned relative to the quick access bar, we can use this
|
||||||
// Only consider it correct if we're using the ToolPanel (expanded All Tools sidebar)
|
rect = quickAccessRef.current.getBoundingClientRect();
|
||||||
const isCorrectSidebar = rightmostSidebar.element === 'ToolPanel';
|
|
||||||
return { rect: rightmostSidebar.rect, isCorrectSidebar };
|
|
||||||
}
|
|
||||||
|
|
||||||
console.warn('⚠️ No sidebars found, using fallback positioning');
|
|
||||||
// Final fallback
|
|
||||||
return { rect: new DOMRect(0, 0, 280, window.innerHeight), isCorrectSidebar: false };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
rect,
|
||||||
|
isToolPanelActive,
|
||||||
|
sidebarState: state
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user