diff --git a/tests/test_ds_contract.py b/tests/test_ds_contract.py index 24205bd..0164286 100644 --- a/tests/test_ds_contract.py +++ b/tests/test_ds_contract.py @@ -2,7 +2,6 @@ from __future__ import annotations import json -import os import re from pathlib import Path @@ -12,7 +11,11 @@ WEB = ROOT / "web" SRC = WEB / "src" UI = SRC / "components" / "ui" -DS_RELEASE = "2.4.8" +DS_RELEASE = "2.4.10" +# The compliance checker's own version, deliberately pinned separately from +# DS_RELEASE in the workflow: it is the binary that runs the gates, not the +# pin the app renders, and moving it moves no pixel. +DS_CHECKER_VERSION = "2.4.8" RAW_CONTROL = re.compile(r"<(button|input|select|textarea)(?:\s|>|/)") ARBITRARY_VALUE = re.compile(r"\b[a-z][a-z-]*-\[[^\]]+\]") @@ -26,29 +29,10 @@ SHADOW_CLASS = re.compile(r"(? list[Path]: @@ -101,7 +85,7 @@ def test_app_owned_source_has_no_visual_or_primitive_drift() -> None: def test_theme_switch_is_only_a_controller_for_the_adopted_component() -> None: controller = (SRC / "components" / "ThemeSwitch.tsx").read_text() - assert "@/components/ui/theme-switch" in controller + assert "@4242labs/design-system/components/theme-switch" in controller assert " None: sidebar = (SRC / "components" / "AppSidebar.tsx").read_text() assert "buymeacoffee.com" in sidebar assert 'className="band-dark"' in sidebar - assert "@/components/brand-mark" in sidebar + assert "@4242labs/design-system/components/brand-mark" in sidebar assert "@/components/Brand" not in sidebar @@ -159,7 +143,7 @@ def test_alfred_build_contract_is_exact_and_uses_npm_ci() -> None: def test_ci_pins_exact_ds_release_and_runs_provenance_and_browser_gates() -> None: workflow = (ROOT / ".github" / "workflows" / "ds-compliance.yml").read_text() - assert f"@4242labs/design-system@{DS_RELEASE}" in workflow + assert f"@4242labs/design-system@{DS_CHECKER_VERSION}" in workflow # The pin is read out of package.json, so a bump moves one file and goes green alone. assert '--expect "$PIN"' in workflow assert "--ui-dir src/components/ui" in workflow @@ -193,16 +177,3 @@ def test_tokens_come_from_the_package_and_not_from_a_copy() -> None: assert '@import "@4242labs/design-system/tailwind.css";' in css -def test_local_candidate_adopted_sources_are_byte_identical() -> None: - candidate = os.environ.get("DS_CANDIDATE") - if not candidate: - pytest.skip("set DS_CANDIDATE to byte-check the local design-system candidate") - ds_src = Path(candidate) / "src" - pairs = [(UI / name, ds_src / "components" / "ui" / name) for name in ADOPTED_UI] - pairs.append((SRC / "components" / "brand-mark.tsx", ds_src / "components" / "brand-mark.tsx")) - mismatches = [ - str(local.relative_to(ROOT)) - for local, canonical in pairs - if not canonical.is_file() or local.read_bytes() != canonical.read_bytes() - ] - assert mismatches == [] diff --git a/web/package-lock.json b/web/package-lock.json index e0724dd..6cff182 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -8,7 +8,7 @@ "name": "ff3e-web", "version": "0.1.0", "dependencies": { - "@4242labs/design-system": "2.4.8", + "@4242labs/design-system": "2.4.10", "@fontsource-variable/geist-mono": "5.3.0", "@fontsource-variable/ibm-plex-sans": "5.3.0", "@fontsource-variable/space-grotesk": "5.3.0", @@ -17,7 +17,6 @@ "@radix-ui/react-select": "^2.1.6", "@radix-ui/react-separator": "^1.1.2", "@radix-ui/react-slot": "^1.1.2", - "@radix-ui/react-tabs": "^1.1.3", "@radix-ui/react-tooltip": "^1.1.8", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", @@ -51,9 +50,9 @@ } }, "node_modules/@4242labs/design-system": { - "version": "2.4.8", - "resolved": "https://registry.npmjs.org/@4242labs/design-system/-/design-system-2.4.8.tgz", - "integrity": "sha512-U/PCq4ZqFNNX30XiEsaapGY80VOpdcr31kxfqDQXuS7jdUZSEdkBci41rdoZEzpHqYb4Is/NEAgtTWeYS5gWNw==", + "version": "2.4.10", + "resolved": "https://registry.npmjs.org/@4242labs/design-system/-/design-system-2.4.10.tgz", + "integrity": "sha512-J7ZMv2ZkHNN1pp+dkyt59WIPndkHUTONS6nMMYBtMMO3gXPvXmLPBL0PY1JEHL623MS3AryRGlHOSILuHxzfuw==", "license": "MIT", "dependencies": { "@fontsource-variable/geist-mono": "5.3.0", diff --git a/web/package.json b/web/package.json index a591296..868fe4c 100644 --- a/web/package.json +++ b/web/package.json @@ -14,7 +14,7 @@ "preview": "vite preview" }, "dependencies": { - "@4242labs/design-system": "2.4.8", + "@4242labs/design-system": "2.4.10", "@fontsource-variable/geist-mono": "5.3.0", "@fontsource-variable/ibm-plex-sans": "5.3.0", "@fontsource-variable/space-grotesk": "5.3.0", @@ -23,7 +23,6 @@ "@radix-ui/react-select": "^2.1.6", "@radix-ui/react-separator": "^1.1.2", "@radix-ui/react-slot": "^1.1.2", - "@radix-ui/react-tabs": "^1.1.3", "@radix-ui/react-tooltip": "^1.1.8", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", diff --git a/web/src/App.tsx b/web/src/App.tsx index d183826..b121318 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -3,7 +3,7 @@ import { useState } from 'react' import { AppSidebar } from '@/components/AppSidebar' import { ForecastPage } from '@/components/ForecastPage' import { ReportsPage } from '@/components/ReportsPage' -import { SidebarInset, SidebarProvider } from '@/components/ui/sidebar' +import { SidebarInset, SidebarProvider } from '@4242labs/design-system/components/sidebar' import type { AppView } from '@/lib/types' const VIEW_KEY = 'entropy:view' diff --git a/web/src/components/AppSidebar.tsx b/web/src/components/AppSidebar.tsx index 280753b..1516a98 100644 --- a/web/src/components/AppSidebar.tsx +++ b/web/src/components/AppSidebar.tsx @@ -1,10 +1,10 @@ import { CalendarClock, ChevronRight, Github } from 'lucide-react' -import { BrandMark } from '@/components/brand-mark' +import { BrandMark } from '@4242labs/design-system/components/brand-mark' import { ThemeSwitch } from '@/components/ThemeSwitch' import { Wordmark } from '@/components/Wordmark' -import { Button } from '@/components/ui/button' -import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible' +import { Button } from '@4242labs/design-system/components/button' +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@4242labs/design-system/components/collapsible' import { Sidebar, SidebarContent, @@ -20,7 +20,7 @@ import { SidebarMenuSubItem, SidebarRail, useSidebar, -} from '@/components/ui/sidebar' +} from '@4242labs/design-system/components/sidebar' import type { AppView } from '@/lib/types' const VIEWS: { key: AppView; label: string }[] = [ diff --git a/web/src/components/ChartCard.tsx b/web/src/components/ChartCard.tsx index 906a197..414a642 100644 --- a/web/src/components/ChartCard.tsx +++ b/web/src/components/ChartCard.tsx @@ -1,9 +1,9 @@ import { useState, type ReactNode } from 'react' import { Maximize2 } from 'lucide-react' -import { Button } from '@/components/ui/button' -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' -import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog' +import { Button } from '@4242labs/design-system/components/button' +import { Card, CardContent, CardHeader, CardTitle } from '@4242labs/design-system/components/card' +import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@4242labs/design-system/components/dialog' export interface ChartCardProps { title: string diff --git a/web/src/components/DateRangePicker.tsx b/web/src/components/DateRangePicker.tsx index 4173154..2d80db0 100644 --- a/web/src/components/DateRangePicker.tsx +++ b/web/src/components/DateRangePicker.tsx @@ -1,8 +1,8 @@ import { useState } from 'react' -import { Button } from '@/components/ui/button' -import { Calendar } from '@/components/ui/calendar' -import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' +import { Button } from '@4242labs/design-system/components/button' +import { Calendar } from '@4242labs/design-system/components/calendar' +import { Popover, PopoverContent, PopoverTrigger } from '@4242labs/design-system/components/popover' import { formatDate } from '@/lib/format' import { anchorToDate, toISO } from '@/lib/range' diff --git a/web/src/components/ErrorState.tsx b/web/src/components/ErrorState.tsx index bc71844..fd4aea4 100644 --- a/web/src/components/ErrorState.tsx +++ b/web/src/components/ErrorState.tsx @@ -1,6 +1,6 @@ import { RotateCw } from 'lucide-react' -import { Button } from '@/components/ui/button' +import { Button } from '@4242labs/design-system/components/button' export function ErrorState({ message, diff --git a/web/src/components/FacetedFilter.tsx b/web/src/components/FacetedFilter.tsx index 6b4bd14..a32da0f 100644 --- a/web/src/components/FacetedFilter.tsx +++ b/web/src/components/FacetedFilter.tsx @@ -1,7 +1,7 @@ import { useState } from 'react' import { Check, ChevronDown } from 'lucide-react' -import { Button } from '@/components/ui/button' +import { Button } from '@4242labs/design-system/components/button' import { Command, CommandEmpty, @@ -10,8 +10,8 @@ import { CommandItem, CommandList, CommandSeparator, -} from '@/components/ui/command' -import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' +} from '@4242labs/design-system/components/command' +import { Popover, PopoverContent, PopoverTrigger } from '@4242labs/design-system/components/popover' import { cn } from '@/lib/utils' export interface FacetOption { diff --git a/web/src/components/FilterBar.tsx b/web/src/components/FilterBar.tsx index 062d624..1a75045 100644 --- a/web/src/components/FilterBar.tsx +++ b/web/src/components/FilterBar.tsx @@ -1,6 +1,6 @@ import { X } from 'lucide-react' -import { Button } from '@/components/ui/button' +import { Button } from '@4242labs/design-system/components/button' import { FacetedFilter } from '@/components/FacetedFilter' import { EMPTY_FILTERS, hasActiveFilters, type FilterOptions } from '@/lib/filters' import type { ActiveFilters, ItemType } from '@/lib/types' diff --git a/web/src/components/PeriodNav.tsx b/web/src/components/PeriodNav.tsx index b18a986..915b710 100644 --- a/web/src/components/PeriodNav.tsx +++ b/web/src/components/PeriodNav.tsx @@ -3,9 +3,9 @@ import { AlertTriangle, ChevronLeft, ChevronRight, RefreshCw } from 'lucide-reac import { FacetedFilter } from '@/components/FacetedFilter' import { FilterBar } from '@/components/FilterBar' import { PeriodPicker } from '@/components/PeriodPicker' -import { Button } from '@/components/ui/button' -import { SidebarTrigger } from '@/components/ui/sidebar' -import { TopBar, TopBarActions, TopBarRailLead } from '@/components/ui/top-bar' +import { Button } from '@4242labs/design-system/components/button' +import { SidebarTrigger } from '@4242labs/design-system/components/sidebar' +import { TopBar, TopBarActions, TopBarRailLead } from '@4242labs/design-system/components/top-bar' import type { FilterOptions } from '@/lib/filters' import { isCumulativeMode, diff --git a/web/src/components/PeriodPicker.tsx b/web/src/components/PeriodPicker.tsx index 62f8470..230e3e2 100644 --- a/web/src/components/PeriodPicker.tsx +++ b/web/src/components/PeriodPicker.tsx @@ -1,9 +1,9 @@ import { useEffect, useState } from 'react' import { ChevronLeft, ChevronRight } from 'lucide-react' -import { Button } from '@/components/ui/button' -import { Calendar } from '@/components/ui/calendar' -import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' +import { Button } from '@4242labs/design-system/components/button' +import { Calendar } from '@4242labs/design-system/components/calendar' +import { Popover, PopoverContent, PopoverTrigger } from '@4242labs/design-system/components/popover' import { anchorToDate, toISO } from '@/lib/range' import type { Granularity } from '@/lib/types' diff --git a/web/src/components/PeriodTable.tsx b/web/src/components/PeriodTable.tsx index acd1abd..5f633f3 100644 --- a/web/src/components/PeriodTable.tsx +++ b/web/src/components/PeriodTable.tsx @@ -1,5 +1,5 @@ -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table' +import { Card, CardContent, CardHeader, CardTitle } from '@4242labs/design-system/components/card' +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@4242labs/design-system/components/table' import { StatusBadge } from '@/components/StatusBadge' import { FlagBadges } from '@/components/FlagBadges' import { EmptyState } from '@/components/EmptyState' diff --git a/web/src/components/ReportChart.tsx b/web/src/components/ReportChart.tsx index 530569e..1e5bc22 100644 --- a/web/src/components/ReportChart.tsx +++ b/web/src/components/ReportChart.tsx @@ -1,8 +1,8 @@ import { Fragment, useEffect, useState } from 'react' import { ChevronLeft, ChevronRight } from 'lucide-react' -import { Button } from '@/components/ui/button' -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' +import { Button } from '@4242labs/design-system/components/button' +import { Card, CardContent, CardHeader, CardTitle } from '@4242labs/design-system/components/card' import { formatMoney } from '@/lib/format' import { FLOW_LABEL, pageCount, pageOf, type Flow, type ReportCard } from '@/lib/reports' diff --git a/web/src/components/ReportsNav.tsx b/web/src/components/ReportsNav.tsx index 1a20ff4..5ed45b6 100644 --- a/web/src/components/ReportsNav.tsx +++ b/web/src/components/ReportsNav.tsx @@ -4,9 +4,9 @@ import { DateRangePicker } from '@/components/DateRangePicker' import { FacetedFilter } from '@/components/FacetedFilter' import { FilterBar } from '@/components/FilterBar' import { PeriodPicker } from '@/components/PeriodPicker' -import { Button } from '@/components/ui/button' -import { SidebarTrigger } from '@/components/ui/sidebar' -import { TopBar, TopBarActions, TopBarRailLead } from '@/components/ui/top-bar' +import { Button } from '@4242labs/design-system/components/button' +import { SidebarTrigger } from '@4242labs/design-system/components/sidebar' +import { TopBar, TopBarActions, TopBarRailLead } from '@4242labs/design-system/components/top-bar' import type { FilterOptions } from '@/lib/filters' import { isCustomPeriod, diff --git a/web/src/components/SummaryCards.tsx b/web/src/components/SummaryCards.tsx index c4fed9c..7a96443 100644 --- a/web/src/components/SummaryCards.tsx +++ b/web/src/components/SummaryCards.tsx @@ -1,4 +1,4 @@ -import { Card, CardContent } from '@/components/ui/card' +import { Card, CardContent } from '@4242labs/design-system/components/card' import { formatMoney } from '@/lib/format' import type { ProjectionsResponse } from '@/lib/types' diff --git a/web/src/components/ThemeSwitch.tsx b/web/src/components/ThemeSwitch.tsx index ec2a5b0..a05931e 100644 --- a/web/src/components/ThemeSwitch.tsx +++ b/web/src/components/ThemeSwitch.tsx @@ -3,7 +3,7 @@ import { useEffect, useState } from 'react' import { ThemeSwitch as CanonicalThemeSwitch, type ThemeSwitchTheme, -} from '@/components/ui/theme-switch' +} from '@4242labs/design-system/components/theme-switch' const STORAGE_KEY = 'entropy-theme' diff --git a/web/src/components/brand-mark.tsx b/web/src/components/brand-mark.tsx deleted file mode 100644 index 79cb9df..0000000 --- a/web/src/components/brand-mark.tsx +++ /dev/null @@ -1,37 +0,0 @@ -// The 42labs asterisk, on its own — tight rails, avatars, favicons, app chrome. -// -// This is the ONE copy. Consuming apps install it from the registry -// (`npx shadcn@latest add @42labs/brand-mark`) rather than re-tracing the vector -// or pasting the path, so the mark can never drift between products. -// -// Contract: `fill=currentColor`, so the mark takes its colour from `text-*`. -// It defaults to the brand token (`text-logo`, which flips orange→mint with the -// theme) and to a 1:1 box; pass `className` to size it like any other icon. - -import * as React from "react" - -import { cn } from "@/lib/utils" - -function BrandMark({ className, ...props }: React.ComponentProps<"svg">) { - return ( - - ) -} - -export { BrandMark } diff --git a/web/src/components/ui/alert.tsx b/web/src/components/ui/alert.tsx deleted file mode 100644 index f99164e..0000000 --- a/web/src/components/ui/alert.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import * as React from "react" -import { cva, type VariantProps } from "class-variance-authority" - -import { cn } from "@/lib/utils" - -const alertVariants = cva( - "relative grid w-full grid-cols-[0_1fr] items-start gap-y-0.5 rounded-lg border px-4 py-3 text-sm has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] has-[>svg]:gap-x-3 [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current", - { - variants: { - variant: { - default: "bg-card text-card-foreground", - destructive: - "bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 [&>svg]:text-current", - }, - }, - defaultVariants: { - variant: "default", - }, - } -) - -function Alert({ - className, - variant, - ...props -}: React.ComponentProps<"div"> & VariantProps) { - return ( -
- ) -} - -function AlertTitle({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -function AlertDescription({ - className, - ...props -}: React.ComponentProps<"div">) { - return ( -
- ) -} - -export { Alert, AlertTitle, AlertDescription } diff --git a/web/src/components/ui/badge.tsx b/web/src/components/ui/badge.tsx deleted file mode 100644 index e346c52..0000000 --- a/web/src/components/ui/badge.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import * as React from "react" -import { Slot } from "radix-ui" -import { cva, type VariantProps } from "class-variance-authority" - -import { cn } from "@/lib/utils" - -const badgeVariants = cva( - "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", - { - variants: { - variant: { - default: - "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90", - secondary: - "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90", - destructive: - "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", - // DS retheme: shadcn's `outline` hover uses bg-accent/text-accent-foreground, - // which collide with the DS brand `accent`. Point them at the neutral muted - // surface instead, matching the vendored button/alert convention. - outline: - "text-foreground [a&]:hover:bg-muted [a&]:hover:text-foreground", - }, - }, - defaultVariants: { - variant: "default", - }, - } -) - -function Badge({ - className, - variant, - asChild = false, - ...props -}: React.ComponentProps<"span"> & - VariantProps & { asChild?: boolean }) { - const Comp = asChild ? Slot.Root : "span" - - return ( - - ) -} - -export { Badge, badgeVariants } diff --git a/web/src/components/ui/button.tsx b/web/src/components/ui/button.tsx deleted file mode 100644 index 820d1a5..0000000 --- a/web/src/components/ui/button.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import * as React from "react" -import { cva, type VariantProps } from "class-variance-authority" -import { Slot } from "radix-ui" - -import { cn } from "@/lib/utils" - -const buttonVariants = cva( - "inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", - { - variants: { - variant: { - default: "bg-primary text-primary-foreground hover:bg-primary/90", - destructive: - "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40", - // DS theming: border-input (= border-control) on BOTH modes. Upstream - // uses --border on light and --input on dark; that asymmetry left the - // light outline at 1.38:1 while dark cleared 3:1 for the same control. - outline: - "border border-input bg-background shadow-xs hover:bg-muted hover:text-foreground dark:bg-input/30 dark:hover:bg-input/50", - secondary: - "bg-secondary text-secondary-foreground hover:bg-secondary/80", - ghost: - "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50", - link: "text-primary underline-offset-4 hover:underline", - }, - size: { - default: "h-9 px-4 py-2 has-[>svg]:px-3", - xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3", - sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5", - lg: "h-10 rounded-md px-6 has-[>svg]:px-4", - icon: "size-9", - "icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3", - "icon-sm": "size-8", - "icon-lg": "size-10", - }, - }, - defaultVariants: { - variant: "default", - size: "default", - }, - } -) - -function Button({ - className, - variant = "default", - size = "default", - asChild = false, - ...props -}: React.ComponentProps<"button"> & - VariantProps & { - asChild?: boolean - }) { - const Comp = asChild ? Slot.Root : "button" - - return ( - - ) -} - -export { Button, buttonVariants } diff --git a/web/src/components/ui/calendar.tsx b/web/src/components/ui/calendar.tsx deleted file mode 100644 index 2aa97bf..0000000 --- a/web/src/components/ui/calendar.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { ChevronLeft, ChevronRight } from 'lucide-react' -import { DayPicker } from 'react-day-picker' - -import { buttonVariants } from '@/components/ui/button' -import { cn } from '@/lib/utils' - -export type CalendarProps = React.ComponentProps - -/** shadcn Calendar over react-day-picker v10, styled from design tokens only. */ -export function Calendar({ className, classNames, showOutsideDays = true, ...props }: CalendarProps) { - return ( - - orientation === 'left' ? ( - - ) : ( - - ), - }} - {...props} - /> - ) -} diff --git a/web/src/components/ui/card.tsx b/web/src/components/ui/card.tsx deleted file mode 100644 index d22c44a..0000000 --- a/web/src/components/ui/card.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import * as React from "react" - -import { cn } from "@/lib/utils" - -function Card({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -function CardHeader({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -function CardTitle({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -function CardDescription({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -function CardAction({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -function CardContent({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -function CardFooter({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -export { - Card, - CardHeader, - CardFooter, - CardTitle, - CardAction, - CardDescription, - CardContent, -} diff --git a/web/src/components/ui/collapsible.tsx b/web/src/components/ui/collapsible.tsx deleted file mode 100644 index 2f7a4e7..0000000 --- a/web/src/components/ui/collapsible.tsx +++ /dev/null @@ -1,33 +0,0 @@ -"use client" - -import { Collapsible as CollapsiblePrimitive } from "radix-ui" - -function Collapsible({ - ...props -}: React.ComponentProps) { - return -} - -function CollapsibleTrigger({ - ...props -}: React.ComponentProps) { - return ( - - ) -} - -function CollapsibleContent({ - ...props -}: React.ComponentProps) { - return ( - - ) -} - -export { Collapsible, CollapsibleTrigger, CollapsibleContent } diff --git a/web/src/components/ui/command.tsx b/web/src/components/ui/command.tsx deleted file mode 100644 index 2c48e66..0000000 --- a/web/src/components/ui/command.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import * as React from 'react' -import { Command as CommandPrimitive } from 'cmdk' -import { Search } from 'lucide-react' - -import { cn } from '@/lib/utils' - -const Command = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -Command.displayName = CommandPrimitive.displayName - -const CommandInput = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( -
- - -
-)) -CommandInput.displayName = CommandPrimitive.Input.displayName - -const CommandList = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -CommandList.displayName = CommandPrimitive.List.displayName - -const CommandEmpty = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->((props, ref) => ( - -)) -CommandEmpty.displayName = CommandPrimitive.Empty.displayName - -const CommandGroup = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -CommandGroup.displayName = CommandPrimitive.Group.displayName - -const CommandSeparator = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -CommandSeparator.displayName = CommandPrimitive.Separator.displayName - -const CommandItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -CommandItem.displayName = CommandPrimitive.Item.displayName - -export { - Command, - CommandInput, - CommandList, - CommandEmpty, - CommandGroup, - CommandItem, - CommandSeparator, -} diff --git a/web/src/components/ui/dialog.tsx b/web/src/components/ui/dialog.tsx deleted file mode 100644 index 0281c1c..0000000 --- a/web/src/components/ui/dialog.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import * as React from "react" -import { XIcon } from "lucide-react" -import { Dialog as DialogPrimitive } from "radix-ui" - -import { cn } from "@/lib/utils" - -function Dialog({ ...props }: React.ComponentProps) { - return -} - -function DialogPortal({ ...props }: React.ComponentProps) { - return -} - -function DialogOverlay({ className, ...props }: React.ComponentProps) { - return ( - - ) -} - -function DialogContent({ - className, - children, - showCloseButton = true, - ...props -}: React.ComponentProps & { showCloseButton?: boolean }) { - return ( - - - - {children} - {showCloseButton && ( - - - Close - - )} - - - ) -} - -function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -function DialogTitle({ className, ...props }: React.ComponentProps) { - return ( - - ) -} - -export { Dialog, DialogContent, DialogHeader, DialogTitle } diff --git a/web/src/components/ui/input.tsx b/web/src/components/ui/input.tsx deleted file mode 100644 index f1124ae..0000000 --- a/web/src/components/ui/input.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import * as React from "react" - -import { cn } from "@/lib/utils" - -function Input({ className, type, ...props }: React.ComponentProps<"input">) { - return ( - - ) -} - -export { Input } diff --git a/web/src/components/ui/pagination.tsx b/web/src/components/ui/pagination.tsx deleted file mode 100644 index 7f110d9..0000000 --- a/web/src/components/ui/pagination.tsx +++ /dev/null @@ -1,101 +0,0 @@ -"use client" - -import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from "lucide-react" - -import { Button } from "@/components/ui/button" -import { cn } from "@/lib/utils" - -const ALIGN = { - start: "justify-start", - center: "justify-center", - end: "justify-end", -} as const - -const STRIP = "flex items-center overflow-hidden rounded-sm border border-border [&_svg]:text-fg-muted" - -/** - * Where the pager sits on the row is the PRODUCT's call, not the canon's. - * - * It shipped hard-wired to the trailing edge, which reads on a wide table whose last - * column already ends there and reads as an orphan under a centred lane or a card grid. - * There is no house rule to appeal to here — the Swiss style governs what the control - * looks like, not where a page puts it — so the DS offers the three answers and takes - * none. `end` stays the default because that is what every current consumer renders. - * - * How many rows to a page is the READER's call, but only where it changes something. - * Pass `sizes` and `onLimitChange` together and a second strip appears beside the pager; - * leave them out and there is none, which is right for a fixed card grid, where the size - * changes nothing but how far you scroll. Picking a size returns to the first page: the - * rows under the reader are about to be different rows either way, and page 7 of 10 has - * no honest equivalent at the new size. - */ -export function Pagination({ - offset, - limit, - total, - onOffsetChange, - sizes, - onLimitChange, - align = "end", - className, -}: { - offset: number - limit: number - total: number - onOffsetChange: (offset: number) => void - sizes?: number[] - onLimitChange?: (limit: number) => void - align?: "start" | "center" | "end" - className?: string -}) { - const resizable = sizes && sizes.length > 0 && onLimitChange - const pages = Math.max(1, Math.ceil(total / limit)) - const page = Math.min(pages, Math.floor(offset / limit) + 1) - // Nothing to page through and nothing to resize — the controls would only be furniture. - if (total <= (resizable ? Math.min(...sizes) : limit)) return null - - const go = (next: number) => onOffsetChange((Math.min(pages, Math.max(1, next)) - 1) * limit) - return ( -
- - {resizable ? ( - - ) : null} -
- ) -} - -function PageCell({ label, className, ...props }: React.ComponentProps & { label: string }) { - return ( - - ) -} - -function SidebarRail({ className, ...props }: React.ComponentProps<"button">) { - const { toggleSidebar } = useSidebar() - - return ( -