From b4579340ffb0eb584416ca545e61cebfe9a1cef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8C=D1=8F=D1=81=20=D0=A1=D1=83=D0=BB=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=D0=B2?= Date: Sun, 6 Sep 2026 23:31:43 +0300 Subject: [PATCH] =?UTF-8?q?DI2:=20=D0=BC=D0=BE=D1=81=D1=82=20=D1=82=D0=B5?= =?UTF-8?q?=D0=BC/=D1=81=D0=BA=D0=B8=D0=BD=D0=BE=D0=B2=20iistwin=20?= =?UTF-8?q?=E2=80=94=20Di2ThemeProvider,=20=D0=BE=D0=B1=D1=89=D0=B8=D0=B9?= =?UTF-8?q?=20generated-skins.css,=20=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D1=8B?= =?UTF-8?q?=20=D0=B2=20=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=82=D0=B5=20=D0=BE?= =?UTF-8?q?=D1=81=D0=BD=D0=BE=D0=B2=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=BA=D0=BB?= =?UTF-8?q?=D0=B8=D0=B5=D0=BD=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - vite.config.di2.ts + client-di2/tsconfig.json: алиас @skin → client/src/themes (tokens, skins, generated-skins.css — единый источник токенов) - client-di2/src/themes/Di2ThemeProvider.tsx: порт логики ThemeProvider основного клиента (localStorage['skin'] → скин организации → 'iistwin'; runtime CSS кастомных скинов через generateSkinCss; data-skin/data-theme/class light|dark на ; контекст с toggleTheme). Ключи 'skin'/'theme' общие с iistwin — выбор синхронизируется между приложениями - main.tsx: обёртка вокруг App - tailwind.config.ts DI2: цвета hsl(var(--x) / ) → var(--x), радиусы → var(--radius) с каскадом calc, добавлены warning/success/info - client-di2/src/index.css: собственные HSL-тройки заменены fallback-блоками основного клиента (до гидратации), первой строкой @import общего generated-skins.css; DI2-only переменные (--card-border, --popover-border, *-border, --button-outline, --badge-outline) переопределены через color-mix от семантических токенов; удалены --opaque-button-border-intensity и hsl(from ...) relative-color вычисления; жёсткие --font-sans: Open Sans убраны (шрифты эмитит generateSkinCss из токенов скина) - client-di2/index.html: lang=ru, viewport без maximum-scale + interactive-widget=resizes-content, мега-link Google Fonts (23 семейства) заменён на Inter + DM Mono как в основном клиенте - Alpha-модификаторы семантических цветов (166 мест: bg-muted/50, border-primary/30 и т.п.) заменены на arbitrary values color-mix(in oklab, var(--x) NN%, transparent) — Tailwind v3 молча не генерирует /NN для var()-цветов; палитровые цвета (green-500/10 и т.п.) не тронуты --- client-di2/index.html | 12 +- .../components/category-override-dialog.tsx | 10 +- client-di2/src/components/database-error.tsx | 2 +- .../src/components/draggable-column-list.tsx | 4 +- client-di2/src/components/ui/alert.tsx | 2 +- client-di2/src/components/ui/calendar.tsx | 4 +- client-di2/src/components/ui/chart.tsx | 4 +- .../src/components/ui/navigation-menu.tsx | 2 +- client-di2/src/components/ui/sidebar.tsx | 2 +- client-di2/src/components/ui/table.tsx | 4 +- client-di2/src/components/ui/toast.tsx | 4 +- client-di2/src/index.css | 285 +++++++++--------- client-di2/src/main.tsx | 5 +- client-di2/src/pages/audit.tsx | 4 +- client-di2/src/pages/calculations.tsx | 34 +-- client-di2/src/pages/dashboard.tsx | 8 +- client-di2/src/pages/debt.tsx | 16 +- client-di2/src/pages/expense-categories.tsx | 22 +- client-di2/src/pages/expenses-overview.tsx | 22 +- client-di2/src/pages/expenses.tsx | 10 +- client-di2/src/pages/heatmap.tsx | 16 +- client-di2/src/pages/income-categories.tsx | 28 +- client-di2/src/pages/income-overview.tsx | 24 +- client-di2/src/pages/income.tsx | 10 +- client-di2/src/pages/planning.tsx | 10 +- client-di2/src/pages/profitability.tsx | 6 +- client-di2/src/pages/salary.tsx | 34 +-- client-di2/src/pages/settings.tsx | 10 +- client-di2/src/themes/Di2ThemeProvider.tsx | 227 ++++++++++++++ client-di2/tailwind.config.ts | 95 +++--- client-di2/tsconfig.json | 4 +- vite.config.di2.ts | 2 + 32 files changed, 581 insertions(+), 341 deletions(-) create mode 100644 client-di2/src/themes/Di2ThemeProvider.tsx diff --git a/client-di2/index.html b/client-di2/index.html index 77b6691..713c2d9 100644 --- a/client-di2/index.html +++ b/client-di2/index.html @@ -1,15 +1,15 @@ - + - + - - - + +
- \ No newline at end of file + diff --git a/client-di2/src/components/category-override-dialog.tsx b/client-di2/src/components/category-override-dialog.tsx index cb690e1..b939237 100644 --- a/client-di2/src/components/category-override-dialog.tsx +++ b/client-di2/src/components/category-override-dialog.tsx @@ -162,7 +162,7 @@ function TreeNode({ cat, depth, expanded, onToggle, onSelect, currentOverrideCat return (
{hasChildren ? ( @@ -241,7 +241,7 @@ function RootGroupRow({ group, expanded, onToggle, onSelect, currentOverrideCate return (
onToggle(group.id)} data-testid={`root-group-${group.id}`} > @@ -251,11 +251,11 @@ function RootGroupRow({ group, expanded, onToggle, onSelect, currentOverrideCate : } {isExpanded - ? - : } + ? + : } {group.name} {isContext && ( - текущий + текущий )}
{(isExpanded || searchActive) && ( diff --git a/client-di2/src/components/database-error.tsx b/client-di2/src/components/database-error.tsx index 883c11a..fda117b 100644 --- a/client-di2/src/components/database-error.tsx +++ b/client-di2/src/components/database-error.tsx @@ -9,7 +9,7 @@ export function DatabaseError({ error }: { error?: Error | null }) { return (
{message} diff --git a/client-di2/src/components/draggable-column-list.tsx b/client-di2/src/components/draggable-column-list.tsx index 4437acb..9e0b999 100644 --- a/client-di2/src/components/draggable-column-list.tsx +++ b/client-di2/src/components/draggable-column-list.tsx @@ -86,10 +86,10 @@ export function DraggableColumnList({ onDragEnd={handleDragEnd} className={`flex items-center gap-1.5 cursor-grab active:cursor-grabbing text-sm rounded px-1 py-1 select-none transition-colors ${ dragIdx === idx ? "opacity-40 bg-muted" : "" - } ${overIdx === idx && dragIdx !== idx ? "border-t-2 border-primary" : ""} hover:bg-muted/50`} + } ${overIdx === idx && dragIdx !== idx ? "border-t-2 border-primary" : ""} hover:bg-[color-mix(in_oklab,var(--muted)_50%,transparent)]`} data-testid={`draggable-col-${col.key}`} > - + onToggle(col.key)} diff --git a/client-di2/src/components/ui/alert.tsx b/client-di2/src/components/ui/alert.tsx index 41fa7e0..083d39d 100644 --- a/client-di2/src/components/ui/alert.tsx +++ b/client-di2/src/components/ui/alert.tsx @@ -10,7 +10,7 @@ const alertVariants = cva( variant: { default: "bg-background text-foreground", destructive: - "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive", + "border-[color-mix(in_oklab,var(--destructive)_50%,transparent)] text-destructive dark:border-destructive [&>svg]:text-destructive", }, }, defaultVariants: { diff --git a/client-di2/src/components/ui/calendar.tsx b/client-di2/src/components/ui/calendar.tsx index 2174f71..d711607 100644 --- a/client-di2/src/components/ui/calendar.tsx +++ b/client-di2/src/components/ui/calendar.tsx @@ -34,7 +34,7 @@ function Calendar({ head_cell: "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]", row: "flex w-full mt-2", - cell: "h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20", + cell: "h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-[color-mix(in_oklab,var(--accent)_50%,transparent)] [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20", day: cn( buttonVariants({ variant: "ghost" }), "h-9 w-9 p-0 font-normal aria-selected:opacity-100" @@ -44,7 +44,7 @@ function Calendar({ "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground", day_today: "bg-accent text-accent-foreground", day_outside: - "day-outside text-muted-foreground aria-selected:bg-accent/50 aria-selected:text-muted-foreground", + "day-outside text-muted-foreground aria-selected:bg-[color-mix(in_oklab,var(--accent)_50%,transparent)] aria-selected:text-muted-foreground", day_disabled: "text-muted-foreground opacity-50", day_range_middle: "aria-selected:bg-accent aria-selected:text-accent-foreground", diff --git a/client-di2/src/components/ui/chart.tsx b/client-di2/src/components/ui/chart.tsx index 39fba6d..8502e04 100644 --- a/client-di2/src/components/ui/chart.tsx +++ b/client-di2/src/components/ui/chart.tsx @@ -52,7 +52,7 @@ const ChartContainer = React.forwardRef< data-chart={chartId} ref={ref} className={cn( - "flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none", + "flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-[color-mix(in_oklab,var(--border)_50%,transparent)] [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none", className )} {...props} @@ -179,7 +179,7 @@ const ChartTooltipContent = React.forwardRef<
diff --git a/client-di2/src/components/ui/navigation-menu.tsx b/client-di2/src/components/ui/navigation-menu.tsx index 411f519..89fbf02 100644 --- a/client-di2/src/components/ui/navigation-menu.tsx +++ b/client-di2/src/components/ui/navigation-menu.tsx @@ -41,7 +41,7 @@ NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName const NavigationMenuItem = NavigationMenuPrimitive.Item const navigationMenuTriggerStyle = cva( - "group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[state=open]:text-accent-foreground data-[state=open]:bg-accent/50 data-[state=open]:hover:bg-accent data-[state=open]:focus:bg-accent" + "group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[state=open]:text-accent-foreground data-[state=open]:bg-[color-mix(in_oklab,var(--accent)_50%,transparent)] data-[state=open]:hover:bg-accent data-[state=open]:focus:bg-accent" ) const NavigationMenuTrigger = React.forwardRef< diff --git a/client-di2/src/components/ui/sidebar.tsx b/client-di2/src/components/ui/sidebar.tsx index 41362f6..c1e57f7 100644 --- a/client-di2/src/components/ui/sidebar.tsx +++ b/client-di2/src/components/ui/sidebar.tsx @@ -406,7 +406,7 @@ function SidebarGroupLabel({ data-slot="sidebar-group-label" data-sidebar="group-label" className={cn( - "text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:h-4 [&>svg]:w-4 [&>svg]:shrink-0", + "text-[color-mix(in_oklab,var(--sidebar-foreground)_70%,transparent)] ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:h-4 [&>svg]:w-4 [&>svg]:shrink-0", "group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0", className )} diff --git a/client-di2/src/components/ui/table.tsx b/client-di2/src/components/ui/table.tsx index 7f3502f..95cb988 100644 --- a/client-di2/src/components/ui/table.tsx +++ b/client-di2/src/components/ui/table.tsx @@ -43,7 +43,7 @@ const TableFooter = React.forwardRef< tr]:last:border-b-0", + "border-t bg-[color-mix(in_oklab,var(--muted)_50%,transparent)] font-medium [&>tr]:last:border-b-0", className )} {...props} @@ -58,7 +58,7 @@ const TableRow = React.forwardRef< - + + + ); diff --git a/client-di2/src/pages/audit.tsx b/client-di2/src/pages/audit.tsx index be6611f..926c092 100644 --- a/client-di2/src/pages/audit.tsx +++ b/client-di2/src/pages/audit.tsx @@ -81,7 +81,7 @@ function DirectionCard({ title, data }: { title: string; data: DirectionAudit }) - + Всего в БД {data.dbCount} 100% @@ -232,7 +232,7 @@ export default function AuditPage() { {latestAudit && ( <> - +
diff --git a/client-di2/src/pages/calculations.tsx b/client-di2/src/pages/calculations.tsx index 1299ad0..36ac3cc 100644 --- a/client-di2/src/pages/calculations.tsx +++ b/client-di2/src/pages/calculations.tsx @@ -180,7 +180,7 @@ function CategoryTree({ cats, selected, onChange, label, treeConfigs }: { return (
@@ -198,7 +198,7 @@ function CategoryTree({ cats, selected, onChange, label, treeConfigs }: { data-testid={`checkbox-cat-${node.id}`} /> { if (hasChildren) toggleExpand(node.id); }} > {node.name} @@ -233,7 +233,7 @@ function CategoryTree({ cats, selected, onChange, label, treeConfigs }: { return (
-
+
{([["month", "Месяц"], ["quarter", "Квартал"], ["year", "Год"]] as const).map(([key, label]) => (
@@ -1316,8 +1316,8 @@ function ProfitTab({ data, taxRate, onTaxRateChange, incCats, expCats, onIncCats
{data.excludedExpenseCategories.map((cat: { name: string; total: number }, i: number) => (
- {cat.name} - {formatCurrency(cat.total)} + {cat.name} + {formatCurrency(cat.total)}
))}
diff --git a/client-di2/src/pages/dashboard.tsx b/client-di2/src/pages/dashboard.tsx index c7c75d6..70a6dc5 100644 --- a/client-di2/src/pages/dashboard.tsx +++ b/client-di2/src/pages/dashboard.tsx @@ -228,7 +228,7 @@ export default function Dashboard() {

Общая сводка по финансам

-
+
@@ -590,7 +590,7 @@ export default function Dashboard() { {flatIncome.map(({ cat, depth }) => (