feat: Integrate Mantine UI library, establish a theme provider, and refactor core UI components.

This commit is contained in:
Firman Ramdhani
2026-02-27 15:00:17 +07:00
parent 8181bd61ec
commit 1d38a188b7
23 changed files with 646 additions and 344 deletions
+33 -15
View File
@@ -1,5 +1,6 @@
import { lazy, Suspense } from 'react'; import { lazy, Suspense, useState } from 'react';
import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom'; import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
import { ThemeProvider, ColorSchemeType, DensityType } from '@repo/ui/provider';
import { NotFound } from '@repo/ui/components/system-pages/not-found'; import { NotFound } from '@repo/ui/components/system-pages/not-found';
import { Forbidden } from '@repo/ui/components/system-pages/forbidden'; import { Forbidden } from '@repo/ui/components/system-pages/forbidden';
import { Maintenance } from '@repo/ui/components/system-pages/maintenance'; import { Maintenance } from '@repo/ui/components/system-pages/maintenance';
@@ -7,22 +8,39 @@ import { ComingSoon } from '@repo/ui/components/system-pages/coming-soon';
const AuthModule = lazy(() => import('./auth')); const AuthModule = lazy(() => import('./auth'));
const AppModule = lazy(() => import('./modules')); const AppModule = lazy(() => import('./modules'));
const ShowcaseView = lazy(() => import('./showcase/showcase-view'));
export default function App() { export default function App() {
const [colorScheme, setColorScheme] = useState<ColorSchemeType>('light');
const [density, setDensity] = useState<DensityType>('standard');
return ( return (
<BrowserRouter> <ThemeProvider colorScheme={colorScheme} density={density}>
<Suspense fallback={<div>Loading...</div>}> <BrowserRouter>
<Routes> <Suspense fallback={<div>Loading...</div>}>
<Route path="/auth/*" element={<AuthModule />} /> <Routes>
<Route path="/app/*" element={<AppModule />} /> <Route path="/auth/*" element={<AuthModule />} />
<Route path="/404" element={<NotFound />} /> <Route path="/app/*" element={<AppModule />} />
<Route path="/403" element={<Forbidden />} /> <Route
<Route path="/maintenance" element={<Maintenance />} /> path="/showcase"
<Route path="/coming-soon" element={<ComingSoon />} /> element={
<Route path="/" element={<Navigate to="/app" />} /> <ShowcaseView
<Route path="*" element={<Navigate to="/404" />} /> colorScheme={colorScheme}
</Routes> setColorScheme={setColorScheme}
</Suspense> density={density}
</BrowserRouter> setDensity={setDensity}
/>
}
/>
<Route path="/404" element={<NotFound />} />
<Route path="/403" element={<Forbidden />} />
<Route path="/maintenance" element={<Maintenance />} />
<Route path="/coming-soon" element={<ComingSoon />} />
<Route path="/" element={<Navigate to="/showcase" />} />
<Route path="*" element={<Navigate to="/404" />} />
</Routes>
</Suspense>
</BrowserRouter>
</ThemeProvider>
); );
} }
@@ -0,0 +1,84 @@
import { ColorSchemeType, DensityType } from '@repo/ui/provider';
import { Button } from '@repo/ui/components/button';
import { Card } from '@repo/ui/components/card';
import { Container } from '@repo/ui/components/container';
import { Select } from '@repo/ui/components/select';
import { Group, Stack } from '@repo/ui/components/group';
import { Text, Title } from '@repo/ui/components/text';
import { TextInput } from '@repo/ui/components/input';
import { Checkbox } from '@repo/ui/components/checkbox';
interface ShowcaseViewProps {
colorScheme: ColorSchemeType;
setColorScheme: (val: ColorSchemeType) => void;
density: DensityType;
setDensity: (val: DensityType) => void;
}
export default function ShowcaseView({ colorScheme, setColorScheme, density, setDensity }: ShowcaseViewProps) {
return (
<Container size="md" py="xl">
<Stack gap="xl">
<Title order={1}>UI Gateway Showcase</Title>
{/* Control Panel */}
<Card withBorder shadow="sm" radius="md" p="md">
<Title order={3} mb="md">Control Panel</Title>
<Group grow align="flex-end">
<Select
label="Color Scheme"
value={colorScheme}
onChange={(val: string | null) => setColorScheme((val as ColorSchemeType) || 'light')}
data={[
{ value: 'light', label: 'Light' },
{ value: 'dark', label: 'Dark' },
{ value: 'dracula', label: 'Dracula' },
{ value: 'blue', label: 'Blue' },
]}
/>
<Select
label="Density"
value={density}
onChange={(val: string | null) => setDensity((val as DensityType) || 'standard')}
data={[
{ value: 'compact', label: 'Compact' },
{ value: 'standard', label: 'Standard' },
{ value: 'spacious', label: 'Spacious' },
]}
/>
</Group>
</Card>
{/* Showcase Area */}
<Card withBorder shadow="sm" radius="md" p="md">
<Stack gap="lg">
<div>
<Title order={3} mb="sm">Typography</Title>
<Text size="sm" c="dimmed">This is dimmed small text.</Text>
<Text>This is standard text describing the components below.</Text>
</div>
<div>
<Title order={3} mb="sm">Buttons</Title>
<Group>
<Button variant="filled">Filled Button</Button>
<Button variant="outline">Outline Button</Button>
<Button variant="light">Light Button</Button>
<Button variant="subtle">Subtle Button</Button>
</Group>
</div>
<div>
<Title order={3} mb="md">Form Elements</Title>
<Group grow>
<TextInput label="First Name" placeholder="John" />
<TextInput label="Last Name" placeholder="Doe" />
</Group>
<Checkbox label="I agree to the terms and conditions" mt="md" defaultChecked />
</div>
</Stack>
</Card>
</Stack>
</Container>
);
}
+6 -2
View File
@@ -3,9 +3,11 @@
"version": "0.0.0", "version": "0.0.0",
"exports": { "exports": {
"./theme.css": "./src/theme.css", "./theme.css": "./src/theme.css",
"./components/*": "./src/components/*.tsx", "./components/system-pages/*": "./src/components/system-pages/*.tsx",
"./components/*": "./src/components/*.ts",
"./hooks/*": "./src/hooks/*.ts", "./hooks/*": "./src/hooks/*.ts",
"./utils/*": "./src/utils/*.ts" "./utils/*": "./src/utils/*.ts",
"./provider": "./src/provider/index.ts"
}, },
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
@@ -18,6 +20,8 @@
"react-dom": "^19.2.3" "react-dom": "^19.2.3"
}, },
"dependencies": { "dependencies": {
"@mantine/core": "^8.3.15",
"@mantine/hooks": "^8.3.15",
"@repo/utils": "workspace:*", "@repo/utils": "workspace:*",
"dayjs": "^1.11.19", "dayjs": "^1.11.19",
"tailwind-merge": "^3.4.0", "tailwind-merge": "^3.4.0",
+1
View File
@@ -0,0 +1 @@
export { Button, type ButtonProps } from '@mantine/core';
+1
View File
@@ -0,0 +1 @@
export { Card, type CardProps } from '@mantine/core';
+1
View File
@@ -0,0 +1 @@
export { Checkbox, type CheckboxProps } from '@mantine/core';
+1
View File
@@ -0,0 +1 @@
export { Container, type ContainerProps } from '@mantine/core';
+1
View File
@@ -0,0 +1 @@
export { Group, type GroupProps, Stack, type StackProps } from '@mantine/core';
+1
View File
@@ -0,0 +1 @@
export { TextInput, type TextInputProps } from '@mantine/core';
+1
View File
@@ -0,0 +1 @@
export { Select, type SelectProps } from '@mantine/core';
@@ -2,35 +2,32 @@ interface ComingSoonProps {
showActions?: boolean; showActions?: boolean;
} }
export function ComingSoon(props: ComingSoonProps) { import { Title, Text, Button, Container, Stack, Center } from '@mantine/core';
const { showActions = false } = props;
export function ComingSoon({ showActions = false }: ComingSoonProps) {
return ( return (
<div className="flex min-h-screen items-center justify-center bg-white px-4"> <Container size="sm" h="100vh" pos="relative">
<div className="w-full max-w-md text-center"> <Center h="100%">
{/* Code */} <Stack align="center" ta="center" gap="md">
<p className="text-sm font-medium uppercase tracking-widest text-gray-400">Coming Soon</p> <Text size="sm" fw={500} tt="uppercase" c="dimmed" lts="var(--mantine-spacing-xs)">
Coming Soon
</Text>
{/* Title */} <Title order={1} fw={900} c="brand">
<h1 className="mt-3 text-6xl font-extrabold text-brand-900">Feature in Progress</h1> Feature in Progress
</Title>
{/* Description */} <Text size="md" c="dimmed">
<p className="mt-4 text-base text-gray-500"> This feature is currently under development. Stay tuned! We'll have it ready for you very soon.
This feature is currently under development. Stay tuned! We'll have it ready for you very soon. </Text>
</p>
{/* Actions */} {showActions && (
{showActions && ( <Button component="a" href="/" color="brand" size="md" mt="xl">
<div className="mt-8 flex justify-center gap-3">
<a
href="/"
className="rounded-md bg-brand-500 px-5 py-2.5 text-sm font-medium text-white hover:bg-brand-400"
>
Back to Home Back to Home
</a> </Button>
</div> )}
)} </Stack>
</div> </Center>
</div> </Container>
); );
} }
@@ -3,47 +3,43 @@ interface ForbiddenProps {
showActionsHome?: boolean; showActionsHome?: boolean;
} }
export function Forbidden(props: ForbiddenProps) { import { Title, Text, Button, Container, Stack, Group, Center } from '@mantine/core';
const { showActionsBack = true, showActionsHome = true } = props;
export function Forbidden({ showActionsBack = true, showActionsHome = true }: ForbiddenProps) {
return ( return (
<div className="flex min-h-screen items-center justify-center bg-white px-4"> <Container size="sm" h="100vh" pos="relative">
<div className="w-full max-w-md text-center"> <Center h="100%">
{/* Code */} <Stack align="center" ta="center" gap="md">
<p className="text-sm font-medium uppercase tracking-widest text-gray-400">403 Error</p> <Text size="sm" fw={500} tt="uppercase" c="dimmed" lts="var(--mantine-spacing-xs)">
403 Error
</Text>
{/* Title */} <Title order={1} fw={900} c="brand">
<h1 className="mt-3 text-6xl font-extrabold text-brand-900">Access Denied</h1> Access Denied
</Title>
{/* Description */} <Text size="md" c="dimmed">
<p className="mt-4 text-base text-gray-500"> Sorry, you dont have permission to access this page. Please contact your administrator if you believe this
Sorry, you dont have permission to access this page. Please contact your administrator if you believe this is is a mistake.
a mistake. </Text>
</p>
{/* Actions */} {(showActionsBack || showActionsHome) && (
{(showActionsBack || showActionsHome) && ( <Group mt="xl" justify="center">
<div className="mt-8 flex justify-center gap-3"> {showActionsBack && (
{showActionsBack && ( <Button variant="default" size="md" onClick={() => window.history.back()}>
<button Go Back
onClick={() => window.history.back()} </Button>
className="rounded-md border border-gray-300 px-5 py-2.5 text-sm font-medium text-gray-700 hover:bg-gray-100 cursor-pointer" )}
>
Go Back
</button>
)}
{showActionsHome && ( {showActionsHome && (
<a <Button component="a" href="/" color="brand" size="md">
href="/" Back to Home
className="rounded-md bg-brand-500 px-5 py-2.5 text-sm font-medium text-white hover:bg-brand-400" </Button>
> )}
Back to Home </Group>
</a> )}
)} </Stack>
</div> </Center>
)} </Container>
</div>
</div>
); );
} }
@@ -2,36 +2,33 @@ interface MaintenanceProps {
showActions?: boolean; showActions?: boolean;
} }
export function Maintenance(props: MaintenanceProps) { import { Title, Text, Button, Container, Stack, Center } from '@mantine/core';
const { showActions = false } = props;
export function Maintenance({ showActions = false }: MaintenanceProps) {
return ( return (
<div className="flex min-h-screen items-center justify-center bg-white px-4"> <Container size="sm" h="100vh" pos="relative">
<div className="w-full max-w-md text-center"> <Center h="100%">
{/* Code */} <Stack align="center" ta="center" gap="md">
<p className="text-sm font-medium uppercase tracking-widest text-gray-400">Maintenance</p> <Text size="sm" fw={500} tt="uppercase" c="dimmed" lts="var(--mantine-spacing-xs)">
Maintenance
</Text>
{/* Title */} <Title order={1} fw={900} c="brand">
<h1 className="mt-3 text-6xl font-extrabold text-brand-900">We'll Be Back Soon</h1> We'll Be Back Soon
</Title>
{/* Description */} <Text size="md" c="dimmed">
<p className="mt-4 text-base text-gray-500"> Our system is currently undergoing scheduled maintenance. We are working hard to bring it back online as
Our system is currently undergoing scheduled maintenance. We are working hard to bring it back online as soon soon as possible.
as possible. </Text>
</p>
{/* Optional Actions */} {showActions && (
{showActions && ( <Button component="a" href="/" color="brand" size="md" mt="xl">
<div className="mt-8 flex justify-center gap-3">
<a
href="/"
className="rounded-md bg-brand-500 px-5 py-2.5 text-sm font-medium text-white hover:bg-brand-400"
>
Back to Home Back to Home
</a> </Button>
</div> )}
)} </Stack>
</div> </Center>
</div> </Container>
); );
} }
@@ -3,42 +3,42 @@ interface NotFoundProps {
showActionsHome?: boolean; showActionsHome?: boolean;
} }
export function NotFound(props: NotFoundProps) { import { Title, Text, Button, Container, Stack, Group, Center } from '@mantine/core';
const { showActionsBack = true, showActionsHome = true } = props;
export function NotFound({ showActionsBack = true, showActionsHome = true }: NotFoundProps) {
return ( return (
<div className="flex min-h-screen items-center justify-center bg-white px-4"> <Container size="sm" h="100vh" pos="relative">
<div className="w-full max-w-md text-center"> <Center h="100%">
<p className="text-sm font-medium uppercase tracking-widest text-gray-400">404 Error</p> <Stack align="center" ta="center" gap="md">
<Text size="sm" fw={500} tt="uppercase" c="dimmed" lts="var(--mantine-spacing-xs)">
404 Error
</Text>
<h1 className="mt-3 text-6xl font-extrabold text-brand-900">Page Not Found</h1> <Title order={1} fw={900} c="brand">
Page Not Found
</Title>
<p className="mt-4 text-base text-gray-500"> <Text size="md" c="dimmed">
Sorry, the page youre looking for doesnt exist or has been moved. Sorry, the page youre looking for doesnt exist or has been moved.
</p> </Text>
{(showActionsBack || showActionsHome) && ( {(showActionsBack || showActionsHome) && (
<div className="mt-8 flex justify-center gap-3"> <Group mt="xl" justify="center">
{showActionsBack && ( {showActionsBack && (
<button <Button variant="default" size="md" onClick={() => window.history.back()}>
onClick={() => window.history.back()} Go Back
className="rounded-md border border-gray-300 px-5 py-2.5 text-sm font-medium text-gray-700 hover:bg-gray-100 cursor-pointer" </Button>
> )}
Go Back
</button>
)}
{showActionsHome && ( {showActionsHome && (
<a <Button component="a" href="/" color="brand" size="md">
href="/" Back to Home
className="rounded-md bg-brand-500 px-5 py-2.5 text-sm font-medium text-white hover:bg-brand-400" </Button>
> )}
Back to Home </Group>
</a> )}
)} </Stack>
</div> </Center>
)} </Container>
</div>
</div>
); );
} }
+1
View File
@@ -0,0 +1 @@
export { Text, type TextProps, Title, type TitleProps } from '@mantine/core';
+1
View File
@@ -0,0 +1 @@
export * from './theme-provider';
@@ -0,0 +1,70 @@
import { MantineProvider, createTheme, MantineThemeOverride } from '@mantine/core';
import React from 'react';
import { brandColors, errorColors, warningColors, successColors, infoColors, draculaColors, blueColors } from '../theme/tokens/colors';
import { typography } from '../theme/tokens/typography';
import { radius } from '../theme/tokens/radius';
export type ColorSchemeType = 'light' | 'dark' | 'dracula' | 'blue';
export type DensityType = 'compact' | 'standard' | 'spacious';
interface ThemeProviderProps {
children: React.ReactNode;
colorScheme?: ColorSchemeType;
density?: DensityType;
}
export function ThemeProvider({ children, colorScheme = 'light', density = 'standard' }: ThemeProviderProps) {
const densityStyles = {
compact: {
spacing: { xs: '0.25rem', sm: '0.5rem', md: '0.75rem', lg: '1rem', xl: '1.25rem' },
},
standard: {
spacing: { xs: '0.5rem', sm: '0.75rem', md: '1rem', lg: '1.5rem', xl: '2rem' },
},
spacious: {
spacing: { xs: '0.75rem', sm: '1rem', md: '1.5rem', lg: '2rem', xl: '3rem' },
}
};
const baseTheme = createTheme({
colors: {
brand: brandColors,
error: errorColors,
warning: warningColors,
success: successColors,
info: infoColors,
dracula: draculaColors,
bluetheme: blueColors,
},
primaryColor: 'brand',
fontFamily: typography.fontFamily,
headings: typography.headings,
spacing: densityStyles[density].spacing,
radius: radius,
});
let mantineColorScheme: 'light' | 'dark' = 'light';
let themeOverride: MantineThemeOverride = baseTheme;
if (colorScheme === 'dark') {
mantineColorScheme = 'dark';
} else if (colorScheme === 'dracula') {
mantineColorScheme = 'dark';
themeOverride = createTheme({
...baseTheme,
primaryColor: 'dracula',
});
} else if (colorScheme === 'blue') {
mantineColorScheme = 'light';
themeOverride = createTheme({
...baseTheme,
primaryColor: 'bluetheme',
});
}
return (
<MantineProvider theme={themeOverride} forceColorScheme={mantineColorScheme} defaultColorScheme={mantineColorScheme}>
{children}
</MantineProvider>
);
}
+6 -208
View File
@@ -1,219 +1,17 @@
@import 'tailwindcss';
@source "../src";
/* ========================================= /* =========================================
THEME VARIABLES (CENTRALIZED) MANTINE BASE STYLES
========================================= */ ========================================= */
@theme { @import '@mantine/core/styles.css';
/* -------------------------------
COLORS: PALETTE
------------------------------- */
/* Brand (Purple based on your code) */
--color-brand-50: #f5f3fd;
--color-brand-100: #e6dbfb;
--color-brand-200: #d0b6f8;
--color-brand-300: #b78ff5;
--color-brand-400: #9f64f1;
--color-brand-500: #7d39ed; /* Primary */
--color-brand-600: #652ed9;
--color-brand-700: #4a23a5;
--color-brand-800: #321a7a;
--color-brand-900: #1b0f4a;
/* Neutrals */
--color-gray-50: #f5f6f7;
--color-gray-100: #eceff1;
--color-gray-200: #e0e3e7;
--color-gray-300: #d1d5db;
--color-gray-400: #9ca3af;
--color-gray-500: #6b7280;
--color-gray-600: #4b5563;
--color-gray-700: #374151;
--color-gray-800: #1f2937;
--color-gray-900: #111827;
/* -------------------------------
COLORS: SEMANTICS (COMPLETED)
------------------------------- */
/* Error (Red) */
--color-error-50: #fef2f2;
--color-error-100: #fee2e2;
--color-error-200: #fecaca;
--color-error-300: #fca5a5;
--color-error-400: #f87171;
--color-error-500: #ef4444;
--color-error-600: #dc2626;
--color-error-700: #b91c1c;
--color-error-800: #991b1b;
--color-error-900: #7f1d1d;
/* Warning (Amber/Orange) */
--color-warning-50: #fffbeb;
--color-warning-100: #fef3c7;
--color-warning-200: #fde68a;
--color-warning-300: #fcd34d;
--color-warning-400: #fbbf24;
--color-warning-500: #f59e0b;
--color-warning-600: #d97706;
--color-warning-700: #b45309;
--color-warning-800: #92400e;
--color-warning-900: #78350f;
/* Success (Green) */
--color-success-50: #f0fdf4;
--color-success-100: #dcfce7;
--color-success-200: #bbf7d0;
--color-success-300: #86efac;
--color-success-400: #4ade80;
--color-success-500: #22c55e;
--color-success-600: #16a34a;
--color-success-700: #15803d;
--color-success-800: #166534;
--color-success-900: #14532d;
/* Info (Blue/Sky) */
--color-info-50: #f0f9ff;
--color-info-100: #e0f2fe;
--color-info-200: #bae6fd;
--color-info-300: #7dd3fc;
--color-info-400: #38bdf8;
--color-info-500: #0ea5e9;
--color-info-600: #0284c7;
--color-info-700: #0369a1;
--color-info-800: #075985;
--color-info-900: #0c4a6e;
/* -------------------------------
BASE FONT & TYPOGRAPHY
------------------------------- */
--base-font-size: 13px;
/* Scale */
--text-xs: calc(var(--base-font-size) * 0.846); /* ~11px */
--text-sm: calc(var(--base-font-size) * 0.923); /* ~12px */
--text-base: var(--base-font-size); /* 13px */
--text-lg: calc(var(--base-font-size) * 1.154); /* ~15px */
--text-xl: calc(var(--base-font-size) * 1.385); /* ~18px */
--text-2xl: calc(var(--base-font-size) * 1.692); /* ~22px */
/* Weights */
--font-weight-normal: 400;
--font-weight-medium: 500;
--font-weight-semibold: 600;
--font-weight-bold: 700;
/* -------------------------------
SHAPE & DEPTH
------------------------------- */
--radius-sm: 0.125rem; /* 2px */
--radius-md: 0.25rem; /* 4px */
--radius-lg: 0.5rem; /* 8px */
--radius-xl: 0.75rem; /* 12px */
/* -------------------------------
FORM ITEM SPECIFICS
------------------------------- */
/* Form Item Spacing */
--form-item-margin-bottom: 1.25rem; /* 20px */
/* Label Configuration */
--form-label-font-size: var(--text-sm); /* Uses scale text-sm (~12px) */
--form-label-color: var(--color-gray-700);
--form-label-font-weight: var(--font-weight-medium);
--form-label-margin-bottom: 0.375rem; /* ~6px */
/* Error/Warning Message Configuration */
--form-msg-font-size: var(--text-xs); /* Uses scale text-xs (~11px) */
--form-msg-margin-top: 0.375rem; /* ~6px */
--input-height: 2.6rem; /* ~34px */
--input-font-size: var(--text-base);
--input-padding-x: 0.92rem; /* ~12px */
--input-padding-y: 0.62rem; /* ~8px */
--input-radius: 0.375rem; /* 6px */
/* Input Number Specific */
--input-handler-width: 1.5rem; /* 24px (Slightly wider for better clickable) */
/* Textarea Specific */
--textarea-min-height: 6.15rem; /* 80px */
--textarea-padding-x: 0.92rem; /* 12px */
--textarea-padding-y: 0.62rem; /* 8px */
/* Input Colors */
--input-bg: #ffffff;
--input-border: var(--color-gray-300);
--input-border-hover: var(--color-brand-400);
--input-text: var(--color-gray-800);
--input-placeholder: var(--color-gray-400);
--focus-ring-color: var(--color-brand-100);
--focus-border-color: var(--color-brand-500);
--disabled-bg: #f3f4f6;
--disabled-text: var(--color-gray-400);
--disabled-border: #e5e7eb;
/* CHECKBOX & RADIO COMPONENT VARIABLES*/
/* 16px is a perfect fit for a 13px font size.
It's easier to read than 14px, but not overpowering. */
--checkbox-size: 16px; /* ~16px (relative to 13px base) */
--checkbox-radius: var(--radius-md);
/* * Position the check mark icon precisely in the center of the 16px box */
--checkbox-check-width: 5px;
--checkbox-check-height: 9px;
--checkbox-check-top: 1.5px; /* Fine-tuning vertical position */
--checkbox-check-left: 4.5px; /* Fine-tuning horizontal position */
/* SWITCH COMPONENT VARIABLES */
/* Using pixels (px) for Switch is often safer
to avoid sub-pixel rendering artifacts (circles becoming oval)
on low screen resolutions, while still maintaining proportion to the rest scale. */
/* A height of 20px fits with a line-height of 13px text,
A width of 36px provides a compact and modern ratio. */
--switch-width: 36px;
--switch-height: 20px;
/* Handle (lingkaran) = Height - (Padding * 2) */
/* 20px - (2px * 2) = 16px */
--switch-handle-size: 16px;
--switch-padding: 2px; /* Distance between handle and edge */
/* Calculate active position (Checked) */
/* 36px - 16px - 2px = 18px */
--switch-checked-pos: calc(var(--switch-width) - var(--switch-handle-size) - var(--switch-padding));
/* Additional variable for label inside switch (ON/OFF text) if any */
--switch-inner-margin-left: 6px;
--switch-inner-margin-right: 20px;
/* Margin Calculation for Inner Text */
/* Handle edge spacing: Handle size (16px) + Padding (2px) + Gap (4px) = 22px */
--switch-inner-indent-handle: 22px;
/* Empty edge spacing: Padding (2px) + Gap (4px) = 6px */
--switch-inner-indent-edge: 6px;
}
/* ========================================= /* =========================================
BASE RESETS BASE RESETS (Minimal, let Mantine handle most)
========================================= */ ========================================= */
@layer base { @layer base {
body { body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
background-color: #ffffff;
color: var(--color-gray-800);
font-size: var(--base-font-size);
line-height: var(--text-base--line-height);
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
input,
textarea,
select,
button {
font-family: inherit;
font-size: inherit;
color: inherit;
}
} }
+50
View File
@@ -0,0 +1,50 @@
import { MantineColorsTuple } from '@mantine/core';
export const brandColors: MantineColorsTuple = [
'#f5f3fd', // 50
'#e6dbfb', // 100
'#d0b6f8', // 200
'#b78ff5', // 300
'#9f64f1', // 400
'#7d39ed', // 500 (Primary)
'#652ed9', // 600
'#4a23a5', // 700
'#321a7a', // 800
'#1b0f4a', // 900
];
export const errorColors: MantineColorsTuple = [
'#fef2f2', '#fee2e2', '#fecaca', '#fca5a5', '#f87171',
'#ef4444', '#dc2626', '#b91c1c', '#991b1b', '#7f1d1d',
];
export const warningColors: MantineColorsTuple = [
'#fffbeb', '#fef3c7', '#fde68a', '#fcd34d', '#fbbf24',
'#f59e0b', '#d97706', '#b45309', '#92400e', '#78350f',
];
export const successColors: MantineColorsTuple = [
'#f0fdf4', '#dcfce7', '#bbf7d0', '#86efac', '#4ade80',
'#22c55e', '#16a34a', '#15803d', '#166534', '#14532d',
];
export const infoColors: MantineColorsTuple = [
'#f0f9ff', '#e0f2fe', '#bae6fd', '#7dd3fc', '#38bdf8',
'#0ea5e9', '#0284c7', '#0369a1', '#075985', '#0c4a6e',
];
export const draculaColors: MantineColorsTuple = [
'#f8f8f2', '#f1fa8c', '#8be9fd', '#50fa7b', '#ffb86c',
'#ff79c6', '#bd93f9', '#6272a4', '#44475a', '#282a36',
]; // Reusing standard dracula palette as a tuple for simplicity,
// usually this would be mapped to specific grays/primary.
export const blueColors: MantineColorsTuple = [
'#e3f2fd', '#bbdefb', '#90caf9', '#64b5f6', '#42a5f5',
'#2196f3', '#1e88e5', '#1976d2', '#1565c0', '#0d47a1',
];
export const grayColors: MantineColorsTuple = [
'#f5f6f7', '#eceff1', '#e0e3e7', '#d1d5db', '#9ca3af',
'#6b7280', '#4b5563', '#374151', '#1f2937', '#111827',
];
+3
View File
@@ -0,0 +1,3 @@
export * from './colors';
export * from './typography';
export * from './radius';
+7
View File
@@ -0,0 +1,7 @@
export const radius = {
xs: '0.125rem', // 2px
sm: '0.25rem', // 4px
md: '0.375rem', // 6px (Input radius)
lg: '0.5rem', // 8px
xl: '0.75rem', // 12px
};
@@ -0,0 +1,28 @@
export const typography = {
fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif",
fontSizes: {
xs: 'calc(13px * 0.846)',
sm: 'calc(13px * 0.923)',
md: '13px',
lg: 'calc(13px * 1.154)',
xl: 'calc(13px * 1.385)',
},
lineHeights: {
xs: '1.4',
sm: '1.45',
md: '1.5',
lg: '1.55',
xl: '1.6',
},
headings: {
fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif",
sizes: {
h1: { fontSize: 'calc(13px * 2.5)' },
h2: { fontSize: 'calc(13px * 2)' },
h3: { fontSize: 'calc(13px * 1.75)' },
h4: { fontSize: 'calc(13px * 1.5)' },
h5: { fontSize: 'calc(13px * 1.25)' },
h6: { fontSize: '13px' },
},
},
};
+244 -3
View File
@@ -161,6 +161,12 @@ importers:
packages/ui: packages/ui:
dependencies: dependencies:
'@mantine/core':
specifier: ^8.3.15
version: 8.3.15(@mantine/hooks@8.3.15)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3)
'@mantine/hooks':
specifier: ^8.3.15
version: 8.3.15(react@19.2.3)
'@repo/utils': '@repo/utils':
specifier: workspace:* specifier: workspace:*
version: link:../utils version: link:../utils
@@ -392,7 +398,6 @@ packages:
/@babel/runtime@7.28.4: /@babel/runtime@7.28.4:
resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dev: true
/@babel/template@7.27.2: /@babel/template@7.27.2:
resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
@@ -899,6 +904,47 @@ packages:
resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
/@floating-ui/core@1.7.4:
resolution: {integrity: sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==}
dependencies:
'@floating-ui/utils': 0.2.10
dev: false
/@floating-ui/dom@1.7.5:
resolution: {integrity: sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==}
dependencies:
'@floating-ui/core': 1.7.4
'@floating-ui/utils': 0.2.10
dev: false
/@floating-ui/react-dom@2.1.7(react-dom@19.2.3)(react@19.2.3):
resolution: {integrity: sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg==}
peerDependencies:
react: '>=16.8.0'
react-dom: '>=16.8.0'
dependencies:
'@floating-ui/dom': 1.7.5
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
dev: false
/@floating-ui/react@0.27.18(react-dom@19.2.3)(react@19.2.3):
resolution: {integrity: sha512-xJWJxvmy3a05j643gQt+pRbht5XnTlGpsEsAPnMi5F5YTOEEJymA90uZKBD8OvIv5XvZ1qi4GcccSlqT3Bq44Q==}
peerDependencies:
react: '>=17.0.0'
react-dom: '>=17.0.0'
dependencies:
'@floating-ui/react-dom': 2.1.7(react-dom@19.2.3)(react@19.2.3)
'@floating-ui/utils': 0.2.10
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
tabbable: 6.4.0
dev: false
/@floating-ui/utils@0.2.10:
resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==}
dev: false
/@humanwhocodes/config-array@0.13.0: /@humanwhocodes/config-array@0.13.0:
resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==}
engines: {node: '>=10.10.0'} engines: {node: '>=10.10.0'}
@@ -989,6 +1035,34 @@ packages:
'@jridgewell/resolve-uri': 3.1.2 '@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/sourcemap-codec': 1.5.5
/@mantine/core@8.3.15(@mantine/hooks@8.3.15)(@types/react@19.2.7)(react-dom@19.2.3)(react@19.2.3):
resolution: {integrity: sha512-wBn/GogB4x7a2Uj7Ztt3amRaApjED+9XqfE4wyCLh88R7KV55k9vnTdCx+irI/GLOOu9tXNUGm3a4t5sTajwkQ==}
peerDependencies:
'@mantine/hooks': 8.3.15
react: ^18.x || ^19.x
react-dom: ^18.x || ^19.x
dependencies:
'@floating-ui/react': 0.27.18(react-dom@19.2.3)(react@19.2.3)
'@mantine/hooks': 8.3.15(react@19.2.3)
clsx: 2.1.1
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
react-number-format: 5.4.4(react-dom@19.2.3)(react@19.2.3)
react-remove-scroll: 2.7.2(@types/react@19.2.7)(react@19.2.3)
react-textarea-autosize: 8.5.9(@types/react@19.2.7)(react@19.2.3)
type-fest: 4.41.0
transitivePeerDependencies:
- '@types/react'
dev: false
/@mantine/hooks@8.3.15(react@19.2.3):
resolution: {integrity: sha512-AUSnpUlzttHzJht3CJ1YWi16iy6NWRwtyWO5RLGHHsmiW05DyG0qOPKF8+R5dLHuOCnl3XOu4roI2Y1ku9U04Q==}
peerDependencies:
react: ^18.x || ^19.x
dependencies:
react: 19.2.3
dev: false
/@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.3): /@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.3):
resolution: {integrity: sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==} resolution: {integrity: sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==}
peerDependencies: peerDependencies:
@@ -2137,7 +2211,6 @@ packages:
resolution: {integrity: sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==} resolution: {integrity: sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==}
dependencies: dependencies:
csstype: 3.2.3 csstype: 3.2.3
dev: true
/@types/resolve@1.20.6: /@types/resolve@1.20.6:
resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==} resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==}
@@ -3182,6 +3255,11 @@ packages:
is-wsl: 2.2.0 is-wsl: 2.2.0
dev: true dev: true
/clsx@2.1.1:
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
engines: {node: '>=6'}
dev: false
/color-convert@2.0.1: /color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'} engines: {node: '>=7.0.0'}
@@ -3253,7 +3331,6 @@ packages:
/csstype@3.2.3: /csstype@3.2.3:
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
dev: true
/damerau-levenshtein@1.0.8: /damerau-levenshtein@1.0.8:
resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
@@ -3388,6 +3465,10 @@ packages:
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dev: false dev: false
/detect-node-es@1.1.0:
resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==}
dev: false
/devlop@1.1.0: /devlop@1.1.0:
resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
dependencies: dependencies:
@@ -4335,6 +4416,11 @@ packages:
hasown: 2.0.2 hasown: 2.0.2
math-intrinsics: 1.1.0 math-intrinsics: 1.1.0
/get-nonce@1.0.1:
resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==}
engines: {node: '>=6'}
dev: false
/get-proto@1.0.1: /get-proto@1.0.1:
resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@@ -6049,11 +6135,56 @@ packages:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
dev: false dev: false
/react-number-format@5.4.4(react-dom@19.2.3)(react@19.2.3):
resolution: {integrity: sha512-wOmoNZoOpvMminhifQYiYSTCLUDOiUbBunrMrMjA+dV52sY+vck1S4UhR6PkgnoCquvvMSeJjErXZ4qSaWCliA==}
peerDependencies:
react: ^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
dependencies:
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
dev: false
/react-refresh@0.18.0: /react-refresh@0.18.0:
resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
dev: true dev: true
/react-remove-scroll-bar@2.3.8(@types/react@19.2.7)(react@19.2.3):
resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==}
engines: {node: '>=10'}
peerDependencies:
'@types/react': '*'
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
peerDependenciesMeta:
'@types/react':
optional: true
dependencies:
'@types/react': 19.2.7
react: 19.2.3
react-style-singleton: 2.2.3(@types/react@19.2.7)(react@19.2.3)
tslib: 2.8.1
dev: false
/react-remove-scroll@2.7.2(@types/react@19.2.7)(react@19.2.3):
resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==}
engines: {node: '>=10'}
peerDependencies:
'@types/react': '*'
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
dependencies:
'@types/react': 19.2.7
react: 19.2.3
react-remove-scroll-bar: 2.3.8(@types/react@19.2.7)(react@19.2.3)
react-style-singleton: 2.2.3(@types/react@19.2.7)(react@19.2.3)
tslib: 2.8.1
use-callback-ref: 1.3.3(@types/react@19.2.7)(react@19.2.3)
use-sidecar: 1.1.3(@types/react@19.2.7)(react@19.2.3)
dev: false
/react-router-dom@7.11.0(react-dom@19.2.3)(react@19.2.3): /react-router-dom@7.11.0(react-dom@19.2.3)(react@19.2.3):
resolution: {integrity: sha512-e49Ir/kMGRzFOOrYQBdoitq3ULigw4lKbAyKusnvtDu2t4dBX4AGYPrzNvorXmVuOyeakai6FUPW5MmibvVG8g==} resolution: {integrity: sha512-e49Ir/kMGRzFOOrYQBdoitq3ULigw4lKbAyKusnvtDu2t4dBX4AGYPrzNvorXmVuOyeakai6FUPW5MmibvVG8g==}
engines: {node: '>=20.0.0'} engines: {node: '>=20.0.0'}
@@ -6082,6 +6213,36 @@ packages:
set-cookie-parser: 2.7.2 set-cookie-parser: 2.7.2
dev: false dev: false
/react-style-singleton@2.2.3(@types/react@19.2.7)(react@19.2.3):
resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==}
engines: {node: '>=10'}
peerDependencies:
'@types/react': '*'
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
dependencies:
'@types/react': 19.2.7
get-nonce: 1.0.1
react: 19.2.3
tslib: 2.8.1
dev: false
/react-textarea-autosize@8.5.9(@types/react@19.2.7)(react@19.2.3):
resolution: {integrity: sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A==}
engines: {node: '>=10'}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
dependencies:
'@babel/runtime': 7.28.4
react: 19.2.3
use-composed-ref: 1.4.0(@types/react@19.2.7)(react@19.2.3)
use-latest: 1.3.0(@types/react@19.2.7)(react@19.2.3)
transitivePeerDependencies:
- '@types/react'
dev: false
/react@19.2.3: /react@19.2.3:
resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==} resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@@ -6780,6 +6941,10 @@ packages:
'@pkgr/core': 0.2.9 '@pkgr/core': 0.2.9
dev: false dev: false
/tabbable@6.4.0:
resolution: {integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==}
dev: false
/tailwind-merge@3.4.0: /tailwind-merge@3.4.0:
resolution: {integrity: sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==} resolution: {integrity: sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==}
dev: false dev: false
@@ -6976,6 +7141,11 @@ packages:
engines: {node: '>=14.16'} engines: {node: '>=14.16'}
dev: false dev: false
/type-fest@4.41.0:
resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==}
engines: {node: '>=16'}
dev: false
/typed-array-buffer@1.0.3: /typed-array-buffer@1.0.3:
resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@@ -7181,6 +7351,77 @@ packages:
dependencies: dependencies:
punycode: 2.3.1 punycode: 2.3.1
/use-callback-ref@1.3.3(@types/react@19.2.7)(react@19.2.3):
resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==}
engines: {node: '>=10'}
peerDependencies:
'@types/react': '*'
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
dependencies:
'@types/react': 19.2.7
react: 19.2.3
tslib: 2.8.1
dev: false
/use-composed-ref@1.4.0(@types/react@19.2.7)(react@19.2.3):
resolution: {integrity: sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==}
peerDependencies:
'@types/react': '*'
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
peerDependenciesMeta:
'@types/react':
optional: true
dependencies:
'@types/react': 19.2.7
react: 19.2.3
dev: false
/use-isomorphic-layout-effect@1.2.1(@types/react@19.2.7)(react@19.2.3):
resolution: {integrity: sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==}
peerDependencies:
'@types/react': '*'
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
peerDependenciesMeta:
'@types/react':
optional: true
dependencies:
'@types/react': 19.2.7
react: 19.2.3
dev: false
/use-latest@1.3.0(@types/react@19.2.7)(react@19.2.3):
resolution: {integrity: sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==}
peerDependencies:
'@types/react': '*'
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
peerDependenciesMeta:
'@types/react':
optional: true
dependencies:
'@types/react': 19.2.7
react: 19.2.3
use-isomorphic-layout-effect: 1.2.1(@types/react@19.2.7)(react@19.2.3)
dev: false
/use-sidecar@1.1.3(@types/react@19.2.7)(react@19.2.3):
resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==}
engines: {node: '>=10'}
peerDependencies:
'@types/react': '*'
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
dependencies:
'@types/react': 19.2.7
detect-node-es: 1.1.0
react: 19.2.3
tslib: 2.8.1
dev: false
/util-deprecate@1.0.2: /util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
dev: false dev: false