mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-11-16 01:21:16 +01:00
Merge branch 'V2' into add_eslint_plugins_20250928
This commit is contained in:
commit
ff958a283e
15
.github/workflows/frontend-licenses-update.yml
vendored
15
.github/workflows/frontend-licenses-update.yml
vendored
@ -12,6 +12,7 @@ on:
|
||||
branches:
|
||||
- V2
|
||||
paths:
|
||||
- ".github/workflows/frontend-licenses-update.yml"
|
||||
- "frontend/package.json"
|
||||
- "frontend/package-lock.json"
|
||||
- "frontend/scripts/generate-licenses.js"
|
||||
@ -28,12 +29,12 @@ jobs:
|
||||
repository-projects: write # Required for enabling automerge
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2
|
||||
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Checkout PR head (default)
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
@ -48,7 +49,7 @@ jobs:
|
||||
|
||||
- name: Checkout BASE branch (safe script)
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.base.sha }}
|
||||
path: base
|
||||
@ -56,9 +57,9 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
|
||||
with:
|
||||
node-version: '18'
|
||||
node-version: '22'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: frontend/package-lock.json
|
||||
|
||||
@ -114,7 +115,7 @@ jobs:
|
||||
# PR Event: Check licenses and comment on PR
|
||||
- name: Delete previous license check comments
|
||||
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
with:
|
||||
github-token: ${{ steps.setup-bot.outputs.token }}
|
||||
script: |
|
||||
@ -167,7 +168,7 @@ jobs:
|
||||
|
||||
- name: Comment on PR - License Check Results
|
||||
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
with:
|
||||
github-token: ${{ steps.setup-bot.outputs.token }}
|
||||
script: |
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { Suspense } from "react";
|
||||
import { Suspense } from "react";
|
||||
import { RainbowThemeProvider } from "./components/shared/RainbowThemeProvider";
|
||||
import { FileContextProvider } from "./contexts/FileContext";
|
||||
import { NavigationProvider } from "./contexts/NavigationContext";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import {
|
||||
Modal,
|
||||
Text,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useRef } from "react";
|
||||
import { useRef } from "react";
|
||||
import { FileButton, Button } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { Flex } from '@mantine/core';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useCookieConsent } from '../../hooks/useCookieConsent';
|
||||
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import { Box, Group, Text, Button } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
@ -37,7 +36,7 @@ const MultiSelectControls = ({
|
||||
>
|
||||
{t("fileManager.clearSelection", "Clear Selection")}
|
||||
</Button>
|
||||
|
||||
|
||||
{onAddToUpload && (
|
||||
<Button
|
||||
size="xs"
|
||||
@ -47,7 +46,7 @@ const MultiSelectControls = ({
|
||||
{t("fileManager.addToUpload", "Add to Upload")}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
|
||||
{onOpenInFileEditor && (
|
||||
<Button
|
||||
size="xs"
|
||||
@ -58,7 +57,7 @@ const MultiSelectControls = ({
|
||||
{t("fileManager.openInFileEditor", "Open in File Editor")}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
|
||||
{onOpenInPageEditor && (
|
||||
<Button
|
||||
size="xs"
|
||||
@ -69,7 +68,7 @@ const MultiSelectControls = ({
|
||||
{t("fileManager.openInPageEditor", "Open in Page Editor")}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
|
||||
{onDeleteAll && (
|
||||
<Button
|
||||
size="xs"
|
||||
@ -85,4 +84,4 @@ const MultiSelectControls = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default MultiSelectControls;
|
||||
export default MultiSelectControls;
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import { Modal, Text, Button, Group, Stack } from '@mantine/core';
|
||||
import { useNavigationGuard } from '../../contexts/NavigationContext';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@ -41,10 +41,10 @@ const QuickAccessBar = forwardRef<HTMLDivElement>((_, ref) => {
|
||||
// Helper function to render navigation buttons with URL support
|
||||
const renderNavButton = (config: ButtonConfig, index: number) => {
|
||||
const isActive = isNavButtonActive(config, activeButton, isFilesModalOpen, configModalOpen, selectedToolKey, leftPanelView);
|
||||
|
||||
|
||||
// Check if this button has URL navigation support
|
||||
const navProps = config.type === 'navigation' && (config.id === 'read' || config.id === 'automate')
|
||||
? getToolNavigation(config.id)
|
||||
const navProps = config.type === 'navigation' && (config.id === 'read' || config.id === 'automate')
|
||||
? getToolNavigation(config.id)
|
||||
: null;
|
||||
|
||||
const handleClick = (e?: React.MouseEvent) => {
|
||||
@ -59,7 +59,7 @@ const QuickAccessBar = forwardRef<HTMLDivElement>((_, ref) => {
|
||||
return (
|
||||
<div key={config.id} className="flex flex-col items-center gap-1" style={{ marginTop: index === 0 ? '0.5rem' : "0rem" }}>
|
||||
<ActionIcon
|
||||
{...(navProps ? {
|
||||
{...(navProps ? {
|
||||
component: "a" as const,
|
||||
href: navProps.href,
|
||||
onClick: (e: React.MouseEvent) => handleClick(e),
|
||||
@ -249,4 +249,6 @@ const QuickAccessBar = forwardRef<HTMLDivElement>((_, ref) => {
|
||||
);
|
||||
});
|
||||
|
||||
QuickAccessBar.displayName = 'QuickAccessBar';
|
||||
|
||||
export default QuickAccessBar;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { createContext, useContext, ReactNode } from 'react';
|
||||
import { createContext, useContext, ReactNode } from 'react';
|
||||
import { MantineProvider } from '@mantine/core';
|
||||
import { useRainbowTheme } from '../../hooks/useRainbowTheme';
|
||||
import { mantineTheme } from '../../theme/mantineTheme';
|
||||
|
||||
@ -107,3 +107,5 @@ export const TextInput = forwardRef<HTMLInputElement, TextInputProps>(({
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
TextInput.displayName = 'TextInput';
|
||||
|
||||
@ -32,7 +32,7 @@ const ToolChain: React.FC<ToolChainProps> = ({
|
||||
|
||||
const getToolName = (toolId: ToolId) => {
|
||||
return t(`home.${toolId}.title`, toolId);
|
||||
}
|
||||
};
|
||||
|
||||
// Create full tool chain for tooltip
|
||||
const fullChainDisplay = displayStyle === 'badges' ? (
|
||||
|
||||
@ -15,7 +15,7 @@ const viewOptionStyle = {
|
||||
gap: 6,
|
||||
whiteSpace: 'nowrap',
|
||||
paddingTop: '0.3rem',
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Build view options showing text always
|
||||
|
||||
@ -50,7 +50,7 @@ const ActiveToolButton: React.FC<ActiveToolButtonProps> = ({ setActiveButton })
|
||||
const animTimeoutRef = useRef<number | null>(null);
|
||||
const replayRafRef = useRef<number | null>(null);
|
||||
|
||||
const isSwitchingToNewTool = () => { return prevKeyRef.current && prevKeyRef.current !== selectedToolKey };
|
||||
const isSwitchingToNewTool = () => { return prevKeyRef.current && prevKeyRef.current !== selectedToolKey; };
|
||||
|
||||
const clearTimers = () => {
|
||||
if (collapseTimeoutRef.current) {
|
||||
@ -81,7 +81,7 @@ const ActiveToolButton: React.FC<ActiveToolButtonProps> = ({ setActiveButton })
|
||||
setReplayAnim(false);
|
||||
animTimeoutRef.current = null;
|
||||
}, 500);
|
||||
}
|
||||
};
|
||||
|
||||
const firstShow = () => {
|
||||
clearTimers();
|
||||
@ -91,7 +91,7 @@ const ActiveToolButton: React.FC<ActiveToolButtonProps> = ({ setActiveButton })
|
||||
animTimeoutRef.current = window.setTimeout(() => {
|
||||
animTimeoutRef.current = null;
|
||||
}, 500);
|
||||
}
|
||||
};
|
||||
|
||||
const triggerCollapse = () => {
|
||||
clearTimers();
|
||||
@ -101,7 +101,7 @@ const ActiveToolButton: React.FC<ActiveToolButtonProps> = ({ setActiveButton })
|
||||
prevKeyRef.current = null;
|
||||
collapseTimeoutRef.current = null;
|
||||
}, 500); // match CSS transition duration
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (indicatorShouldShow) {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import { useToast } from './ToastContext';
|
||||
import { ToastInstance, ToastLocation } from './types';
|
||||
import { LocalIcon } from '../shared/LocalIcon';
|
||||
@ -66,7 +65,7 @@ export default function ToastRenderer() {
|
||||
<LocalIcon icon={`material-symbols:${getDefaultIconName(t)}`} width={20} height={20} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
{/* Title + count badge */}
|
||||
<div className="toast-title-container">
|
||||
<span>{t.title}</span>
|
||||
@ -74,7 +73,7 @@ export default function ToastRenderer() {
|
||||
<span className="toast-count-badge">{t.count}</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
{/* Controls */}
|
||||
<div className="toast-controls">
|
||||
{t.expandable && (
|
||||
@ -101,20 +100,20 @@ export default function ToastRenderer() {
|
||||
{/* Progress bar - always show when present */}
|
||||
{typeof t.progress === 'number' && (
|
||||
<div className="toast-progress-container">
|
||||
<div
|
||||
<div
|
||||
className={getProgressBarClass(t)}
|
||||
style={{ width: `${t.progress}%` }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
{/* Body content - only show when expanded */}
|
||||
{(t.isExpanded || !t.expandable) && (
|
||||
<div className="toast-body">
|
||||
{t.body}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
{/* Button - always show when present, positioned below body */}
|
||||
{t.buttonText && t.buttonCallback && (
|
||||
<div className="toast-action-container">
|
||||
|
||||
@ -10,5 +10,5 @@ export default function ToolLoadingFallback({ toolName }: { toolName?: string })
|
||||
</Text>
|
||||
</Stack>
|
||||
</Center>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { Suspense } from "react";
|
||||
import { Suspense } from "react";
|
||||
import { useToolWorkflow } from "../../contexts/ToolWorkflowContext";
|
||||
import { BaseToolProps } from "../../types/tool";
|
||||
import ToolLoadingFallback from "./ToolLoadingFallback";
|
||||
@ -26,7 +26,7 @@ const ToolRenderer = ({
|
||||
|
||||
// Wrap lazy-loaded component with Suspense
|
||||
return (
|
||||
<Suspense fallback={<ToolLoadingFallback toolName={selectedTool.name} />}>
|
||||
<Suspense fallback={<ToolLoadingFallback toolName={selectedTool.name} />}>
|
||||
<ToolComponent
|
||||
onPreviewFile={onPreviewFile}
|
||||
onComplete={onComplete}
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
/**
|
||||
* AddWatermarkSingleStepSettings - Used for automation only
|
||||
*
|
||||
*
|
||||
* This component combines all watermark settings into a single step interface
|
||||
* for use in the automation system. It includes type selection and all relevant
|
||||
* settings in one unified component.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { Stack } from "@mantine/core";
|
||||
import { AddWatermarkParameters } from "../../../hooks/tools/addWatermark/useAddWatermarkParameters";
|
||||
import WatermarkTypeSettings from "./WatermarkTypeSettings";
|
||||
@ -67,4 +66,4 @@ const AddWatermarkSingleStepSettings = ({ parameters, onParameterChange, disable
|
||||
);
|
||||
};
|
||||
|
||||
export default AddWatermarkSingleStepSettings;
|
||||
export default AddWatermarkSingleStepSettings;
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import { Stack, Checkbox, Group } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { AddWatermarkParameters } from "../../../hooks/tools/addWatermark/useAddWatermarkParameters";
|
||||
@ -80,4 +79,4 @@ const WatermarkFormatting = ({ parameters, onParameterChange, disabled = false }
|
||||
);
|
||||
};
|
||||
|
||||
export default WatermarkFormatting;
|
||||
export default WatermarkFormatting;
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import { Stack } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { AddWatermarkParameters } from "../../../hooks/tools/addWatermark/useAddWatermarkParameters";
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import { Stack, Text, NumberInput } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { AddWatermarkParameters } from "../../../hooks/tools/addWatermark/useAddWatermarkParameters";
|
||||
@ -60,4 +59,4 @@ const WatermarkStyleSettings = ({ parameters, onParameterChange, disabled = fals
|
||||
);
|
||||
};
|
||||
|
||||
export default WatermarkStyleSettings;
|
||||
export default WatermarkStyleSettings;
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import { Stack, Text, Select, ColorInput } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { AddWatermarkParameters } from "../../../hooks/tools/addWatermark/useAddWatermarkParameters";
|
||||
@ -27,7 +26,7 @@ const WatermarkTextStyle = ({ parameters, onParameterChange, disabled = false }:
|
||||
format="hex"
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
|
||||
<Stack gap="xs">
|
||||
<Text size="xs" fw={500}>
|
||||
{t("watermark.settings.alphabet", "Alphabet")}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Title, Stack, Divider } from "@mantine/core";
|
||||
import AddCircleOutline from "@mui/icons-material/AddCircleOutline";
|
||||
@ -19,11 +18,11 @@ interface AutomationSelectionProps {
|
||||
toolRegistry: Record<string, ToolRegistryEntry>;
|
||||
}
|
||||
|
||||
export default function AutomationSelection({
|
||||
export default function AutomationSelection({
|
||||
savedAutomations,
|
||||
onCreateNew,
|
||||
onRun,
|
||||
onEdit,
|
||||
onCreateNew,
|
||||
onRun,
|
||||
onEdit,
|
||||
onDelete,
|
||||
onCopyFromSuggested,
|
||||
toolRegistry
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Stack, Text, Divider, Collapse, Button, NumberInput } from "@mantine/core";
|
||||
import { BookletImpositionParameters } from "../../../hooks/tools/bookletImposition/useBookletImpositionParameters";
|
||||
@ -176,4 +176,4 @@ const BookletImpositionSettings = ({ parameters, onParameterChange, disabled = f
|
||||
);
|
||||
};
|
||||
|
||||
export default BookletImpositionSettings;
|
||||
export default BookletImpositionSettings;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { Stack, Text, NumberInput, Select, Divider } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { CompressParameters } from "../../../hooks/tools/compress/useCompressParameters";
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import { Stack, Text, NumberInput, Checkbox } from '@mantine/core';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ConvertParameters } from '../../../hooks/tools/convert/useConvertParameters';
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import { Stack, Text, Select, Switch } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { COLOR_TYPES, FIT_OPTIONS } from "../../../constants/convertConstants";
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import { Stack, Text, NumberInput, Slider } from '@mantine/core';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ConvertParameters } from '../../../hooks/tools/convert/useConvertParameters';
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useMemo } from "react";
|
||||
import { useMemo } from "react";
|
||||
import { Stack, Text, Group, Divider, UnstyledButton, useMantineTheme, useMantineColorScheme } from "@mantine/core";
|
||||
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import { Stack, Text, Select, NumberInput, Group } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { COLOR_TYPES, OUTPUT_OPTIONS } from "../../../constants/convertConstants";
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import { Stack, Text, Select, Alert } from '@mantine/core';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ConvertParameters } from '../../../hooks/tools/convert/useConvertParameters';
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useState, useMemo } from "react";
|
||||
import { useState, useMemo } from "react";
|
||||
import { Stack, Text, Group, Button, Box, Popover, UnstyledButton, useMantineTheme, useMantineColorScheme } from "@mantine/core";
|
||||
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
|
||||
|
||||
@ -34,14 +34,14 @@ const GroupedFormatDropdown = ({
|
||||
|
||||
const groupedOptions = useMemo(() => {
|
||||
const groups: Record<string, FormatOption[]> = {};
|
||||
|
||||
|
||||
options.forEach(option => {
|
||||
if (!groups[option.group]) {
|
||||
groups[option.group] = [];
|
||||
}
|
||||
groups[option.group].push(option);
|
||||
});
|
||||
|
||||
|
||||
return groups;
|
||||
}, [options]);
|
||||
|
||||
@ -77,14 +77,14 @@ const GroupedFormatDropdown = ({
|
||||
padding: '0.5rem 0.75rem',
|
||||
border: `0.0625rem solid ${theme.colors.gray[4]}`,
|
||||
borderRadius: theme.radius.sm,
|
||||
backgroundColor: disabled
|
||||
? theme.colors.gray[1]
|
||||
: colorScheme === 'dark'
|
||||
? theme.colors.dark[6]
|
||||
backgroundColor: disabled
|
||||
? theme.colors.gray[1]
|
||||
: colorScheme === 'dark'
|
||||
? theme.colors.dark[6]
|
||||
: theme.white,
|
||||
cursor: disabled ? 'not-allowed' : 'pointer',
|
||||
width: '100%',
|
||||
color: disabled
|
||||
color: disabled
|
||||
? colorScheme === 'dark' ? theme.colors.dark[1] : theme.colors.dark[7]
|
||||
: colorScheme === 'dark' ? theme.colors.dark[0] : theme.colors.dark[9]
|
||||
}}
|
||||
@ -93,19 +93,19 @@ const GroupedFormatDropdown = ({
|
||||
<Text size="sm" c={value ? undefined : 'dimmed'}>
|
||||
{selectedLabel}
|
||||
</Text>
|
||||
<KeyboardArrowDownIcon
|
||||
style={{
|
||||
<KeyboardArrowDownIcon
|
||||
style={{
|
||||
fontSize: '1rem',
|
||||
transform: dropdownOpened ? 'rotate(180deg)' : 'rotate(0deg)',
|
||||
transition: 'transform 0.2s ease',
|
||||
color: colorScheme === 'dark' ? theme.colors.dark[2] : theme.colors.gray[6]
|
||||
}}
|
||||
}}
|
||||
/>
|
||||
</Group>
|
||||
</UnstyledButton>
|
||||
</Popover.Target>
|
||||
<Popover.Dropdown
|
||||
style={{
|
||||
<Popover.Dropdown
|
||||
style={{
|
||||
minWidth: Math.min(350, parseInt(minWidth.replace('rem', '')) * 16),
|
||||
maxWidth: '90vw',
|
||||
maxHeight: '40vh',
|
||||
@ -117,10 +117,10 @@ const GroupedFormatDropdown = ({
|
||||
<Stack gap="md">
|
||||
{Object.entries(groupedOptions).map(([groupName, groupOptions]) => (
|
||||
<Box key={groupName}>
|
||||
<Text
|
||||
size="sm"
|
||||
fw={600}
|
||||
c={colorScheme === 'dark' ? 'dark.2' : 'gray.6'}
|
||||
<Text
|
||||
size="sm"
|
||||
fw={600}
|
||||
c={colorScheme === 'dark' ? 'dark.2' : 'gray.6'}
|
||||
mb="xs"
|
||||
>
|
||||
{groupName}
|
||||
@ -153,4 +153,4 @@ const GroupedFormatDropdown = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default GroupedFormatDropdown;
|
||||
export default GroupedFormatDropdown;
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import { Divider, Select, Stack, Switch } from '@mantine/core';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PageLayoutParameters } from '../../../hooks/tools/pageLayout/usePageLayoutParameters';
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import { Divider, Select, Stack, TextInput } from '@mantine/core';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ReorganizePagesParameters } from '../../../hooks/tools/reorganizePages/useReorganizePagesParameters';
|
||||
@ -31,7 +30,7 @@ export default function ReorganizePagesSettings({
|
||||
disabled={disabled}
|
||||
/>
|
||||
{selectedMode && (
|
||||
<div
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: 'var(--information-text-bg)',
|
||||
color: 'var(--information-text-color)',
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import { Stack, Text, Select, ColorInput } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { ReplaceColorParameters } from "../../../hooks/tools/replaceColor/useReplaceColorParameters";
|
||||
@ -105,4 +104,4 @@ const ReplaceColorSettings = ({ parameters, onParameterChange, disabled = false
|
||||
);
|
||||
};
|
||||
|
||||
export default ReplaceColorSettings;
|
||||
export default ReplaceColorSettings;
|
||||
|
||||
@ -30,6 +30,6 @@ const ErrorNotification = ({
|
||||
{error}
|
||||
</Notification>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default ErrorNotification;
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import { Stack, Text } from '@mantine/core';
|
||||
import { formatFileSize, getFileDate } from '../../../utils/fileUtils';
|
||||
|
||||
@ -24,4 +23,4 @@ const FileMetadata = ({ file }: FileMetadataProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default FileMetadata;
|
||||
export default FileMetadata;
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import { Stack, Group, ActionIcon, Text } from '@mantine/core';
|
||||
import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
|
||||
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { Stack, Text, NumberInput } from "@mantine/core";
|
||||
|
||||
interface NumberInputWithUnitProps {
|
||||
@ -11,14 +11,14 @@ interface NumberInputWithUnitProps {
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const NumberInputWithUnit = ({
|
||||
label,
|
||||
value,
|
||||
onChange,
|
||||
unit,
|
||||
min,
|
||||
max,
|
||||
disabled = false
|
||||
const NumberInputWithUnit = ({
|
||||
label,
|
||||
value,
|
||||
onChange,
|
||||
unit,
|
||||
min,
|
||||
max,
|
||||
disabled = false
|
||||
}: NumberInputWithUnitProps) => {
|
||||
const [localValue, setLocalValue] = useState<number | string>(value);
|
||||
|
||||
@ -54,4 +54,4 @@ const NumberInputWithUnit = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default NumberInputWithUnit;
|
||||
export default NumberInputWithUnit;
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import { Button } from '@mantine/core';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@ -52,6 +51,6 @@ const OperationButton = ({
|
||||
}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default OperationButton;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { Box, Text, Loader, Stack, Center, Flex } from '@mantine/core';
|
||||
import FilePreview from '../../shared/FilePreview';
|
||||
import FileMetadata from './FileMetadata';
|
||||
|
||||
@ -149,7 +149,7 @@ const ToolStep = ({
|
||||
<Divider style={{ color: '#E2E8F0', marginLeft: '1rem', marginRight: '-0.5rem' }} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// ToolStepFactory for creating numbered steps
|
||||
export function createToolSteps() {
|
||||
@ -164,13 +164,16 @@ export function createToolSteps() {
|
||||
const isVisible = props.isVisible !== false;
|
||||
const currentStepNumber = isVisible ? stepNumber++ : undefined;
|
||||
|
||||
const step = React.createElement(ToolStep, {
|
||||
...props,
|
||||
title,
|
||||
_stepNumber: currentStepNumber,
|
||||
children,
|
||||
key: `step-${title.toLowerCase().replace(/\s+/g, '-')}`
|
||||
});
|
||||
const step = React.createElement(
|
||||
ToolStep,
|
||||
{
|
||||
...props,
|
||||
title,
|
||||
_stepNumber: currentStepNumber,
|
||||
key: `step-${title.toLowerCase().replace(/\s+/g, '-')}`
|
||||
},
|
||||
children
|
||||
);
|
||||
|
||||
steps.push(step);
|
||||
return step;
|
||||
@ -186,9 +189,9 @@ export function createToolSteps() {
|
||||
|
||||
const getVisibleCount = () => {
|
||||
return steps.filter(step => {
|
||||
const props = step.props as ToolStepProps;
|
||||
const isVisible = props.isVisible !== false;
|
||||
const excludeFromCount = props._excludeFromCount === true;
|
||||
const stepProps = step.props as ToolStepProps;
|
||||
const isVisible = stepProps.isVisible !== false;
|
||||
const excludeFromCount = stepProps._excludeFromCount === true;
|
||||
return isVisible && !excludeFromCount;
|
||||
}).length;
|
||||
};
|
||||
@ -203,9 +206,9 @@ export function ToolStepProvider({ children, forceStepNumbers }: { children: Rea
|
||||
let count = 0;
|
||||
React.Children.forEach(children, (child) => {
|
||||
if (React.isValidElement(child) && child.type === ToolStep) {
|
||||
const props = child.props as ToolStepProps;
|
||||
const isVisible = props.isVisible !== false;
|
||||
const excludeFromCount = props._excludeFromCount === true;
|
||||
const stepProps = child.props as ToolStepProps;
|
||||
const isVisible = stepProps.isVisible !== false;
|
||||
const excludeFromCount = stepProps._excludeFromCount === true;
|
||||
if (isVisible && !excludeFromCount) count++;
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Stack, Button, Text, Alert, Tabs } from '@mantine/core';
|
||||
import { SignParameters } from "../../../hooks/tools/sign/useSignParameters";
|
||||
@ -256,4 +256,4 @@ const SignSettings = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default SignSettings;
|
||||
export default SignSettings;
|
||||
|
||||
@ -158,6 +158,6 @@ const SplitSettings = ({
|
||||
{parameters.method === SPLIT_METHODS.BY_PAGE_DIVIDER && renderByPageDividerForm()}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default SplitSettings;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useState, useRef, useEffect, useMemo } from "react";
|
||||
import { useState, useRef, useEffect, useMemo } from "react";
|
||||
import { Stack, Button, Text } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import LocalIcon from '../../shared/LocalIcon';
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect, useMemo } from 'react';
|
||||
import { useState, useEffect, useMemo } from 'react';
|
||||
import { useSearch } from '@embedpdf/plugin-search/react';
|
||||
import { useViewer } from '../../contexts/ViewerContext';
|
||||
import { SEARCH_CONSTANTS } from './constants/search';
|
||||
@ -24,9 +24,9 @@ interface SearchResultState {
|
||||
activeResultIndex?: number;
|
||||
}
|
||||
|
||||
export function CustomSearchLayer({
|
||||
pageIndex,
|
||||
scale,
|
||||
export function CustomSearchLayer({
|
||||
pageIndex,
|
||||
scale,
|
||||
highlightColor = SEARCH_CONSTANTS.HIGHLIGHT_COLORS.BACKGROUND,
|
||||
activeHighlightColor = SEARCH_CONSTANTS.HIGHLIGHT_COLORS.ACTIVE_BACKGROUND,
|
||||
opacity = SEARCH_CONSTANTS.HIGHLIGHT_COLORS.OPACITY,
|
||||
@ -42,17 +42,17 @@ export function CustomSearchLayer({
|
||||
if (!searchProvides) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const unsubscribe = searchProvides.onSearchResultStateChange?.((state: SearchResultState) => {
|
||||
// Auto-scroll to active search result
|
||||
if (state?.results && state.activeResultIndex !== undefined && state.activeResultIndex >= 0) {
|
||||
const activeResult = state.results[state.activeResultIndex];
|
||||
if (activeResult) {
|
||||
if (activeResult) {
|
||||
const pageNumber = activeResult.pageIndex + 1; // Convert to 1-based page number
|
||||
scrollActions.scrollToPage(pageNumber);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
setSearchResultState(state);
|
||||
});
|
||||
|
||||
@ -69,7 +69,7 @@ export function CustomSearchLayer({
|
||||
const filtered = searchResultState.results
|
||||
.map((result, originalIndex) => ({ result, originalIndex }))
|
||||
.filter(({ result }) => result.pageIndex === pageIndex);
|
||||
|
||||
|
||||
return filtered;
|
||||
}, [searchResultState, pageIndex]);
|
||||
|
||||
@ -78,7 +78,7 @@ export function CustomSearchLayer({
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
<div style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
@ -117,4 +117,4 @@ export function CustomSearchLayer({
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { createPluginRegistration } from '@embedpdf/core';
|
||||
import { EmbedPDF } from '@embedpdf/core/react';
|
||||
import { usePdfiumEngine } from '@embedpdf/engines/react';
|
||||
@ -312,4 +312,4 @@ export function LocalEmbedPDFWithAnnotations({
|
||||
</EmbedPDF>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Button, Paper, Group, NumberInput } from '@mantine/core';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useViewer } from '../../contexts/ViewerContext';
|
||||
@ -14,11 +14,11 @@ interface PdfViewerToolbarProps {
|
||||
currentPage?: number;
|
||||
totalPages?: number;
|
||||
onPageChange?: (page: number) => void;
|
||||
|
||||
|
||||
// Dual page toggle (placeholder for now)
|
||||
dualPage?: boolean;
|
||||
onDualPageToggle?: () => void;
|
||||
|
||||
|
||||
// Zoom controls (connected via ViewerContext)
|
||||
currentZoom?: number;
|
||||
}
|
||||
@ -33,7 +33,7 @@ export function PdfViewerToolbar({
|
||||
}: PdfViewerToolbarProps) {
|
||||
const { t } = useTranslation();
|
||||
const { getScrollState, getZoomState, scrollActions, zoomActions, registerImmediateZoomUpdate, registerImmediateScrollUpdate } = useViewer();
|
||||
|
||||
|
||||
const scrollState = getScrollState();
|
||||
const zoomState = getZoomState();
|
||||
const [pageInput, setPageInput] = useState(scrollState.currentPage || currentPage);
|
||||
@ -151,7 +151,7 @@ export function PdfViewerToolbar({
|
||||
input: { width: 48, textAlign: "center", fontWeight: 500, fontSize: 16 },
|
||||
}}
|
||||
/>
|
||||
|
||||
|
||||
<span style={{ fontWeight: 500, fontSize: 16 }}>
|
||||
/ {scrollState.totalPages}
|
||||
</span>
|
||||
@ -229,4 +229,4 @@ export function PdfViewerToolbar({
|
||||
</Group>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Box, ScrollArea } from '@mantine/core';
|
||||
import { useViewer } from '../../contexts/ViewerContext';
|
||||
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import EmbedPdfViewer from './EmbedPdfViewer';
|
||||
|
||||
export interface ViewerProps {
|
||||
@ -13,4 +12,4 @@ const Viewer = (props: ViewerProps) => {
|
||||
return <EmbedPdfViewer {...props} />;
|
||||
};
|
||||
|
||||
export default Viewer;
|
||||
export default Viewer;
|
||||
|
||||
@ -22,7 +22,7 @@ export const ENDPOINTS = {
|
||||
export type SplitMethod = typeof SPLIT_METHODS[keyof typeof SPLIT_METHODS];
|
||||
export const isSplitMethod = (value: string | null): value is SplitMethod => {
|
||||
return Object.values(SPLIT_METHODS).includes(value as SplitMethod);
|
||||
}
|
||||
};
|
||||
|
||||
import { CardOption } from '../components/shared/CardSelector';
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
* Memory management handled by FileLifecycleManager (PDF.js cleanup, blob URL revocation).
|
||||
*/
|
||||
|
||||
import React, { useReducer, useCallback, useEffect, useRef, useMemo } from 'react';
|
||||
import { useReducer, useCallback, useEffect, useRef, useMemo } from 'react';
|
||||
import {
|
||||
FileContextProviderProps,
|
||||
FileContextSelectors,
|
||||
@ -76,7 +76,7 @@ function FileContextInner({
|
||||
const currentSelection = stateRef.current.ui.selectedFileIds;
|
||||
const newFileIds = stirlingFiles.map(stirlingFile => stirlingFile.fileId);
|
||||
dispatch({ type: 'SET_SELECTED_FILES', payload: { fileIds: [...currentSelection, ...newFileIds] } });
|
||||
}
|
||||
};
|
||||
|
||||
// File operations using unified addFiles helper with persistence
|
||||
const addRawFiles = useCallback(async (files: File[], options?: { insertAfterPageId?: string; selectFiles?: boolean }): Promise<StirlingFile[]> => {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { createContext, useContext, useState, useRef, useMemo } from 'react';
|
||||
import { createContext, useContext, useState, useRef, useMemo } from 'react';
|
||||
import { SidebarState, SidebarRefs, SidebarContextValue, SidebarProviderProps } from '../types/sidebar';
|
||||
|
||||
const SidebarContext = createContext<SidebarContextValue | undefined>(undefined);
|
||||
@ -7,7 +7,7 @@ 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);
|
||||
@ -44,4 +44,4 @@ export function useSidebarContext(): SidebarContextValue {
|
||||
throw new Error('useSidebarContext must be used within a SidebarProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ import SignSettings from "../components/tools/sign/SignSettings";
|
||||
import CropSettings from "../components/tools/crop/CropSettings";
|
||||
import RemoveAnnotations from "../tools/RemoveAnnotations";
|
||||
import RemoveAnnotationsSettings from "../components/tools/removeAnnotations/RemoveAnnotationsSettings";
|
||||
import PageLayoutSettings from "../components/tools/pageLayout/PageLayoutSettings"
|
||||
import PageLayoutSettings from "../components/tools/pageLayout/PageLayoutSettings";
|
||||
import ExtractImages from "../tools/ExtractImages";
|
||||
import ExtractImagesSettings from "../components/tools/extractImages/ExtractImagesSettings";
|
||||
import ReplaceColorSettings from "../components/tools/replaceColor/ReplaceColorSettings";
|
||||
|
||||
@ -11,7 +11,7 @@ interface CompressedObject {
|
||||
|
||||
const getData = (zipEntry: JSZipObject): CompressedObject | undefined => {
|
||||
return (zipEntry as any)._data as CompressedObject;
|
||||
}
|
||||
};
|
||||
|
||||
export interface ZipExtractionResult {
|
||||
success: boolean;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import '@testing-library/jest-dom'
|
||||
import { vi } from 'vitest'
|
||||
import '@testing-library/jest-dom';
|
||||
import { vi } from 'vitest';
|
||||
|
||||
// Mock i18next for tests
|
||||
vi.mock('react-i18next', () => ({
|
||||
@ -27,8 +27,8 @@ vi.mock('i18next-http-backend', () => ({
|
||||
}));
|
||||
|
||||
// Mock window.URL.createObjectURL and revokeObjectURL for tests
|
||||
global.URL.createObjectURL = vi.fn(() => 'mocked-url')
|
||||
global.URL.revokeObjectURL = vi.fn()
|
||||
global.URL.createObjectURL = vi.fn(() => 'mocked-url');
|
||||
global.URL.revokeObjectURL = vi.fn();
|
||||
|
||||
// Mock File and Blob API methods that aren't available in jsdom
|
||||
if (!globalThis.File.prototype.arrayBuffer) {
|
||||
@ -88,21 +88,21 @@ global.Worker = vi.fn().mockImplementation(() => ({
|
||||
removeEventListener: vi.fn(),
|
||||
onmessage: null,
|
||||
onerror: null,
|
||||
}))
|
||||
}));
|
||||
|
||||
// Mock ResizeObserver for Mantine components
|
||||
global.ResizeObserver = vi.fn().mockImplementation(() => ({
|
||||
observe: vi.fn(),
|
||||
unobserve: vi.fn(),
|
||||
disconnect: vi.fn(),
|
||||
}))
|
||||
}));
|
||||
|
||||
// Mock IntersectionObserver for components that might use it
|
||||
global.IntersectionObserver = vi.fn().mockImplementation(() => ({
|
||||
observe: vi.fn(),
|
||||
unobserve: vi.fn(),
|
||||
disconnect: vi.fn(),
|
||||
}))
|
||||
}));
|
||||
|
||||
// Mock matchMedia for responsive components
|
||||
Object.defineProperty(window, 'matchMedia', {
|
||||
@ -117,7 +117,7 @@ Object.defineProperty(window, 'matchMedia', {
|
||||
removeEventListener: vi.fn(),
|
||||
dispatchEvent: vi.fn(),
|
||||
})),
|
||||
})
|
||||
});
|
||||
|
||||
// Set global test timeout to prevent hangs
|
||||
vi.setConfig({ testTimeout: 5000, hookTimeout: 5000 })
|
||||
vi.setConfig({ testTimeout: 5000, hookTimeout: 5000 });
|
||||
|
||||
@ -452,7 +452,7 @@ describe('Convert Tool Integration Tests', () => {
|
||||
const files = [
|
||||
createPDFFile(),
|
||||
createTestStirlingFile('test2.pdf', '%PDF-1.4...', 'application/pdf')
|
||||
]
|
||||
];
|
||||
const parameters: ConvertParameters = {
|
||||
fromExtension: 'pdf',
|
||||
toExtension: 'png',
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useEndpointEnabled } from "../hooks/useEndpointConfig";
|
||||
import { useFileSelection } from "../contexts/FileContext";
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { createToolFlow } from "../components/tools/shared/createToolFlow";
|
||||
import { BaseToolProps, ToolComponent } from "../types/tool";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { createToolFlow } from "../components/tools/shared/createToolFlow";
|
||||
import { BaseToolProps, ToolComponent } from "../types/tool";
|
||||
|
||||
@ -66,8 +66,3 @@ export interface SuggestedAutomation {
|
||||
updatedAt: string;
|
||||
icon: any; // MUI Icon component
|
||||
}
|
||||
|
||||
// Export the AutomateParameters interface that was previously defined inline
|
||||
export interface AutomateParameters extends AutomationExecutionCallbacks {
|
||||
automationConfig?: AutomationConfig;
|
||||
}
|
||||
@ -17,7 +17,7 @@ export function firePixel(pathname: string): void {
|
||||
lastFiredTime = now;
|
||||
|
||||
const url = 'https://static.scarf.sh/a.png?x-pxid=3c1d68de-8945-4e9f-873f-65320b6fabf7'
|
||||
+ '&path=' + encodeURIComponent(pathname)
|
||||
+ '&path=' + encodeURIComponent(pathname);
|
||||
|
||||
const img = new Image();
|
||||
img.referrerPolicy = "no-referrer-when-downgrade";
|
||||
|
||||
@ -63,11 +63,11 @@ module.exports = {
|
||||
background: 'rgb(var(--background) / <alpha-value>)',
|
||||
border: 'rgb(var(--border) / <alpha-value>)',
|
||||
},
|
||||
|
||||
|
||||
// Z-index scale
|
||||
zIndex: {
|
||||
'dropdown': '1000',
|
||||
'sticky': '1020',
|
||||
'sticky': '1020',
|
||||
'fixed': '1030',
|
||||
'modal-backdrop': '1040',
|
||||
'modal': '1050',
|
||||
@ -81,4 +81,4 @@ module.exports = {
|
||||
corePlugins: {
|
||||
preflight: true,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
import { defineConfig } from 'vitest/config';
|
||||
import react from '@vitejs/plugin-react-swc';
|
||||
|
||||
export default defineConfig({
|
||||
@ -37,4 +37,4 @@ export default defineConfig({
|
||||
'@': '/src'
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
@ -6,4 +6,4 @@ export default defineConfig({
|
||||
testTimeout: 5000,
|
||||
include: ['src/utils/convertUtils.test.ts']
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user