This commit is contained in:
Reece 2025-10-20 17:24:16 +01:00
parent 472fc2939e
commit 23d7f38100
12 changed files with 79 additions and 51 deletions

View File

@ -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",

View File

@ -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",

View File

@ -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={{

View File

@ -24,10 +24,10 @@ const ToolChain: React.FC<ToolChainProps> = ({
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) => {

View File

@ -72,7 +72,7 @@ export const Tooltip: React.FC<TooltipProps> = ({
}
}, []);
const sidebarContext = sidebarTooltip ? useSidebarContext() : null;
const sidebarContext = useSidebarContext();
const isControlled = controlledOpen !== undefined;
const open = (isControlled ? !!controlledOpen : internalOpen) && !disabled;

View File

@ -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
}, (
<FileStatusIndicator
selectedFiles={stepProps.selectedFiles}
minFiles={stepProps.minFiles}
/>
));
}
// 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
}, (
<FileStatusIndicator
selectedFiles={props.selectedFiles}
minFiles={props.minFiles}
/>
));
return <CreateFilesToolStep createStep={createStep} {...props} />;
}

View File

@ -103,21 +103,29 @@ function ReviewStepContent<TParams = unknown>({
);
}
export function createReviewToolStep<TParams = unknown>(
createStep: (title: string, props: any, children?: React.ReactNode) => React.ReactElement,
props: ReviewToolStepProps<TParams>
): React.ReactElement {
export function CreateReviewToolStep<TParams = unknown>(props: ReviewToolStepProps<TParams> & {
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,
},
<ReviewStepContent operation={props.operation} onFileClick={props.onFileClick} onUndo={props.onUndo} />
<ReviewStepContent operation={stepProps.operation} onFileClick={stepProps.onFileClick} onUndo={stepProps.onUndo} />
);
}
// Backwards compatibility wrapper
export function createReviewToolStep<TParams = unknown>(
createStep: (title: string, props: any, children?: React.ReactNode) => React.ReactElement,
props: ReviewToolStepProps<TParams>
): React.ReactElement {
return <CreateReviewToolStep createStep={createStep} {...props} />;
}

View File

@ -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 (
<div>
<div

View File

@ -1,9 +1,9 @@
import { useAppConfig } from '../hooks/useAppConfig';
// Get base URL from app config with fallback
// Get base URL from window location
export const getBaseUrl = (): string => {
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)

View File

@ -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<Map<FileId, File>>(new Map());

View File

@ -34,16 +34,17 @@ export function useBaseParameters<T>(config: BaseParametersConfig<T>): 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,

View File

@ -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