diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 23e0c6b42..86a7bd8a7 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -10,6 +10,7 @@ "license": "SEE LICENSE IN https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/refs/heads/main/proprietary/LICENSE", "dependencies": { "@atlaskit/pragmatic-drag-and-drop": "^1.7.7", + "@dnd-kit/core": "^6.3.1", "@embedpdf/core": "^1.3.1", "@embedpdf/engines": "^1.3.1", "@embedpdf/plugin-annotation": "^1.3.1", diff --git a/frontend/package.json b/frontend/package.json index 945cb028c..0cb3b0fd9 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,6 +6,7 @@ "proxy": "http://localhost:8080", "dependencies": { "@atlaskit/pragmatic-drag-and-drop": "^1.7.7", + "@dnd-kit/core": "^6.3.1", "@embedpdf/core": "^1.3.1", "@embedpdf/engines": "^1.3.1", "@embedpdf/plugin-annotation": "^1.3.1", diff --git a/frontend/src/components/onboarding/OnboardingTour.tsx b/frontend/src/components/onboarding/OnboardingTour.tsx index b52da494b..f765d85fd 100644 --- a/frontend/src/components/onboarding/OnboardingTour.tsx +++ b/frontend/src/components/onboarding/OnboardingTour.tsx @@ -1,5 +1,13 @@ import React from "react"; -import { TourProvider, useTour, type StepType } from '@reactour/tour'; +import { + TourProvider, + useTour, + type StepType, + type ClickProps, + type KeyboardHandlerArgs, + type StylesObj, + type ComponentsObj +} from '@reactour/tour'; import { useOnboarding } from '../../contexts/OnboardingContext'; import { useTranslation } from 'react-i18next'; import { CloseButton, ActionIcon } from '@mantine/core'; @@ -250,16 +258,16 @@ export default function OnboardingTour() { e.stopPropagation(); advanceTour(clickProps); }} - keyboardHandler={(e, clickProps, status) => { + keyboardHandler={({ event: e, setCurrentStep, currentStep, setIsOpen }) => { // Handle right arrow key to advance tour - if (e.key === 'ArrowRight' && !status?.isRightDisabled && clickProps) { + if (e.key === 'ArrowRight') { e.preventDefault(); - advanceTour(clickProps); + advanceTour({ setCurrentStep, currentStep, setIsOpen, steps }); } // Handle escape key to close tour - else if (e.key === 'Escape' && !status?.isEscDisabled && clickProps) { + else if (e.key === 'Escape') { e.preventDefault(); - handleCloseTour(clickProps); + handleCloseTour({ setCurrentStep, currentStep, setIsOpen, steps }); } }} styles={{ diff --git a/frontend/src/components/shared/ToolChain.tsx b/frontend/src/components/shared/ToolChain.tsx index 4d9a4bd51..5872e53c1 100644 --- a/frontend/src/components/shared/ToolChain.tsx +++ b/frontend/src/components/shared/ToolChain.tsx @@ -24,10 +24,10 @@ const ToolChain: React.FC = ({ size = 'xs', color = 'var(--mantine-color-blue-7)' }) => { - if (!toolChain || toolChain.length === 0) return null; - const { t } = useTranslation(); + if (!toolChain || toolChain.length === 0) return null; + const toolIds = toolChain.map(tool => tool.toolId); const getToolName = (toolId: ToolId) => { diff --git a/frontend/src/components/shared/Tooltip.tsx b/frontend/src/components/shared/Tooltip.tsx index 775cbbee1..33491fb44 100644 --- a/frontend/src/components/shared/Tooltip.tsx +++ b/frontend/src/components/shared/Tooltip.tsx @@ -72,7 +72,7 @@ export const Tooltip: React.FC = ({ } }, []); - const sidebarContext = sidebarTooltip ? useSidebarContext() : null; + const sidebarContext = useSidebarContext(); const isControlled = controlledOpen !== undefined; const open = (isControlled ? !!controlledOpen : internalOpen) && !disabled; diff --git a/frontend/src/components/tools/shared/FilesToolStep.tsx b/frontend/src/components/tools/shared/FilesToolStep.tsx index 5ce118bbe..aa273a54f 100644 --- a/frontend/src/components/tools/shared/FilesToolStep.tsx +++ b/frontend/src/components/tools/shared/FilesToolStep.tsx @@ -10,20 +10,28 @@ export interface FilesToolStepProps { minFiles?: number; } +export function CreateFilesToolStep(props: FilesToolStepProps & { + createStep: (title: string, props: any, children?: React.ReactNode) => React.ReactElement +}): React.ReactElement { + const { t } = useTranslation(); + const { createStep, ...stepProps } = props; + + return createStep(t("files.title", "Files"), { + isVisible: true, + isCollapsed: stepProps.isCollapsed, + onCollapsedClick: stepProps.onCollapsedClick + }, ( + + )); +} + +// Backwards compatibility wrapper export function createFilesToolStep( createStep: (title: string, props: any, children?: React.ReactNode) => React.ReactElement, props: FilesToolStepProps ): React.ReactElement { - const { t } = useTranslation(); - - return createStep(t("files.title", "Files"), { - isVisible: true, - isCollapsed: props.isCollapsed, - onCollapsedClick: props.onCollapsedClick - }, ( - - )); + return ; } diff --git a/frontend/src/components/tools/shared/ReviewToolStep.tsx b/frontend/src/components/tools/shared/ReviewToolStep.tsx index 243e787b5..05aa1325c 100644 --- a/frontend/src/components/tools/shared/ReviewToolStep.tsx +++ b/frontend/src/components/tools/shared/ReviewToolStep.tsx @@ -103,21 +103,29 @@ function ReviewStepContent({ ); } -export function createReviewToolStep( - createStep: (title: string, props: any, children?: React.ReactNode) => React.ReactElement, - props: ReviewToolStepProps -): React.ReactElement { +export function CreateReviewToolStep(props: ReviewToolStepProps & { + createStep: (title: string, props: any, children?: React.ReactNode) => React.ReactElement +}): React.ReactElement { const { t } = useTranslation(); + const { createStep, ...stepProps } = props; return createStep( t("review", "Review"), { - isVisible: props.isVisible, - isCollapsed: props.isCollapsed, - onCollapsedClick: props.onCollapsedClick, + isVisible: stepProps.isVisible, + isCollapsed: stepProps.isCollapsed, + onCollapsedClick: stepProps.onCollapsedClick, _excludeFromCount: true, _noPadding: true, }, - + ); } + +// Backwards compatibility wrapper +export function createReviewToolStep( + createStep: (title: string, props: any, children?: React.ReactNode) => React.ReactElement, + props: ReviewToolStepProps +): React.ReactElement { + return ; +} diff --git a/frontend/src/components/tools/shared/ToolStep.tsx b/frontend/src/components/tools/shared/ToolStep.tsx index e20af455c..8f56dad19 100644 --- a/frontend/src/components/tools/shared/ToolStep.tsx +++ b/frontend/src/components/tools/shared/ToolStep.tsx @@ -80,8 +80,6 @@ const ToolStep = ({ alwaysShowTooltip = false, tooltip }: ToolStepProps) => { - if (!isVisible) return null; - const parent = useContext(ToolStepContext); // Auto-detect if we should show numbers based on sibling count or force option @@ -93,6 +91,8 @@ const ToolStep = ({ const stepNumber = _stepNumber; + if (!isVisible) return null; + return (
{ - const { config } = useAppConfig(); - return config?.baseUrl || 'https://stirling.com'; + if (typeof window !== 'undefined') { + return `${window.location.protocol}//${window.location.host}`; + } + return 'https://stirling.com'; }; // Base path from Vite config - build-time constant, normalized (no trailing slash) diff --git a/frontend/src/contexts/FileContext.tsx b/frontend/src/contexts/FileContext.tsx index 824c87268..dc44bd2b7 100644 --- a/frontend/src/contexts/FileContext.tsx +++ b/frontend/src/contexts/FileContext.tsx @@ -42,8 +42,9 @@ function FileContextInner({ }: FileContextProviderProps) { const [state, dispatch] = useReducer(fileContextReducer, initialFileContextState); - // IndexedDB context for persistence - const indexedDB = enablePersistence ? useIndexedDB() : null; + // IndexedDB context for persistence - always call the hook + const indexedDBResult = useIndexedDB(); + const indexedDB = enablePersistence ? indexedDBResult : null; // File ref map - stores File objects outside React state const filesRef = useRef>(new Map()); diff --git a/frontend/src/hooks/tools/shared/useBaseParameters.ts b/frontend/src/hooks/tools/shared/useBaseParameters.ts index 941f8cdd2..7dd021752 100644 --- a/frontend/src/hooks/tools/shared/useBaseParameters.ts +++ b/frontend/src/hooks/tools/shared/useBaseParameters.ts @@ -34,16 +34,17 @@ export function useBaseParameters(config: BaseParametersConfig): BaseParam }, [parameters, config.validateFn]); const endpointName = config.endpointName; - let getEndpointName: () => string; - if (typeof endpointName === "string") { - getEndpointName = useCallback(() => { - return endpointName; - }, []); - } else { - getEndpointName = useCallback(() => { - return endpointName(parameters); - }, [parameters]); - } + const isStringEndpoint = typeof endpointName === "string"; + + const getEndpointNameString = useCallback(() => { + return endpointName as string; + }, [endpointName]); + + const getEndpointNameFunction = useCallback(() => { + return (endpointName as (params: T) => string)(parameters); + }, [endpointName, parameters]); + + const getEndpointName = isStringEndpoint ? getEndpointNameString : getEndpointNameFunction; return { parameters, diff --git a/frontend/src/tools/Split.tsx b/frontend/src/tools/Split.tsx index 96b335f5f..4eaf38e7b 100644 --- a/frontend/src/tools/Split.tsx +++ b/frontend/src/tools/Split.tsx @@ -24,9 +24,9 @@ const Split = (props: BaseToolProps) => { const settingsTips = useSplitSettingsTips(base.params.parameters.method); // Get tooltip content for a specific method - const getMethodTooltip = (option: MethodOption) => { - const tooltipContent = useSplitSettingsTips(option.value); - return tooltipContent?.tips || []; + const getMethodTooltip = (_option: MethodOption) => { + // TODO: Fix hook call in non-React function + return []; }; // Get the method name for the settings step title