mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-06-14 11:21:36 +00:00
Compare commits
24 Commits
shadcn/nex
...
v3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0826d58d3a | ||
|
|
995b6fd1a8 | ||
|
|
410998525b | ||
|
|
0f18c2775a | ||
|
|
b84c990e42 | ||
|
|
2773f9e2e2 | ||
|
|
c41c6ece86 | ||
|
|
11267f2fed | ||
|
|
9ad24d6a16 | ||
|
|
e8468793fc | ||
|
|
6f702f5fbf | ||
|
|
d0306774fe | ||
|
|
f1e5cc4666 | ||
|
|
e3ca257f6e | ||
|
|
d1a36d3e17 | ||
|
|
617483fe9c | ||
|
|
6d2728db2e | ||
|
|
625be136f4 | ||
|
|
1bd209a4db | ||
|
|
812e2300f1 | ||
|
|
b52fa4559c | ||
|
|
2fade2326a | ||
|
|
a6034127f9 | ||
|
|
eaf8156fc0 |
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": minor
|
||||
---
|
||||
|
||||
add support for TanStack Start
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": patch
|
||||
---
|
||||
|
||||
support for version detection in monorepo
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": patch
|
||||
---
|
||||
|
||||
upgrade @antfu/ni
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": patch
|
||||
---
|
||||
|
||||
allow silent mode with npm
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": patch
|
||||
---
|
||||
|
||||
do not add ring for v3
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": minor
|
||||
---
|
||||
|
||||
add theme vars support
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": minor
|
||||
---
|
||||
|
||||
add tailwind version detection
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": minor
|
||||
---
|
||||
|
||||
add --base-color flag
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": minor
|
||||
---
|
||||
|
||||
add support for tailwind v4
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": minor
|
||||
---
|
||||
|
||||
default to css vars. add --no-css-variables
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": patch
|
||||
---
|
||||
|
||||
cache registry calls
|
||||
5
.changeset/honest-humans-invite.md
Normal file
5
.changeset/honest-humans-invite.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"shadcn": patch
|
||||
---
|
||||
|
||||
resolved prefixing issue for Tailwind CSS v4 compatibility
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": minor
|
||||
---
|
||||
|
||||
replace tailwindcss-animate with tw-animate-css
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": patch
|
||||
---
|
||||
|
||||
add --template flag
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": minor
|
||||
---
|
||||
|
||||
default for new-york for v4
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": minor
|
||||
---
|
||||
|
||||
fix handling of sidebar colors
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": patch
|
||||
---
|
||||
|
||||
do not overwrite user defined vars
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": patch
|
||||
---
|
||||
|
||||
fix cn import bug in monorepo
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": patch
|
||||
---
|
||||
|
||||
filter out deprecated from --all
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": minor
|
||||
---
|
||||
|
||||
add oklch base color
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": minor
|
||||
---
|
||||
|
||||
hotswap style for v4
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": patch
|
||||
---
|
||||
|
||||
check for empty css vars
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": patch
|
||||
---
|
||||
|
||||
only show deprecated for new projects
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": minor
|
||||
---
|
||||
|
||||
add warning for deprecated components
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": patch
|
||||
---
|
||||
|
||||
fix tanstack check
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": minor
|
||||
---
|
||||
|
||||
add support for route install for react-router and laravel
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"shadcn": minor
|
||||
---
|
||||
|
||||
add theme prop to registry-item schema
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
import * as React from "react"
|
||||
import {
|
||||
closestCenter,
|
||||
DndContext,
|
||||
KeyboardSensor,
|
||||
MouseSensor,
|
||||
TouchSensor,
|
||||
closestCenter,
|
||||
useSensor,
|
||||
useSensors,
|
||||
type DragEndEvent,
|
||||
@@ -14,8 +14,8 @@ import {
|
||||
} from "@dnd-kit/core"
|
||||
import { restrictToVerticalAxis } from "@dnd-kit/modifiers"
|
||||
import {
|
||||
SortableContext,
|
||||
arrayMove,
|
||||
SortableContext,
|
||||
useSortable,
|
||||
verticalListSortingStrategy,
|
||||
} from "@dnd-kit/sortable"
|
||||
@@ -37,9 +37,6 @@ import {
|
||||
import {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
Row,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getFacetedRowModel,
|
||||
@@ -47,7 +44,10 @@ import {
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
Row,
|
||||
SortingState,
|
||||
useReactTable,
|
||||
VisibilityState,
|
||||
} from "@tanstack/react-table"
|
||||
import { Area, AreaChart, CartesianGrid, XAxis } from "recharts"
|
||||
import { toast } from "sonner"
|
||||
|
||||
@@ -8,6 +8,7 @@ import { Toaster } from "@/registry/new-york-v4/ui/sonner"
|
||||
import { siteConfig } from "@/www/config/site"
|
||||
|
||||
import "./globals.css"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { ActiveThemeProvider } from "@/components/active-theme"
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
ReactNode,
|
||||
createContext,
|
||||
ReactNode,
|
||||
useContext,
|
||||
useEffect,
|
||||
useState,
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
"react-resizable-panels": "^2.1.7",
|
||||
"recharts": "2.15.1",
|
||||
"rimraf": "^6.0.1",
|
||||
"shadcn": "2.3.0",
|
||||
"shadcn": "2.5.0",
|
||||
"sonner": "^2.0.0",
|
||||
"tailwind-merge": "^3.0.1",
|
||||
"tailwindcss": "^4.0.7",
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
"name": "index",
|
||||
"type": "registry:style",
|
||||
"dependencies": [
|
||||
"tw-animate-css",
|
||||
"class-variance-authority",
|
||||
"lucide-react"
|
||||
],
|
||||
"devDependencies": [
|
||||
"tw-animate-css"
|
||||
],
|
||||
"registryDependencies": [
|
||||
"utils"
|
||||
],
|
||||
@@ -27,37 +29,7 @@
|
||||
"path": "registry/new-york-v4/ui/accordion.tsx",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
"tailwind": {
|
||||
"config": {
|
||||
"theme": {
|
||||
"extend": {
|
||||
"keyframes": {
|
||||
"accordion-down": {
|
||||
"from": {
|
||||
"height": "0"
|
||||
},
|
||||
"to": {
|
||||
"height": "var(--radix-accordion-content-height)"
|
||||
}
|
||||
},
|
||||
"accordion-up": {
|
||||
"from": {
|
||||
"height": "var(--radix-accordion-content-height)"
|
||||
},
|
||||
"to": {
|
||||
"height": "0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation": {
|
||||
"accordion-down": "accordion-down 0.2s ease-out",
|
||||
"accordion-up": "accordion-up 0.2s ease-out"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "alert",
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
import * as React from "react"
|
||||
import {
|
||||
closestCenter,
|
||||
DndContext,
|
||||
KeyboardSensor,
|
||||
MouseSensor,
|
||||
TouchSensor,
|
||||
closestCenter,
|
||||
useSensor,
|
||||
useSensors,
|
||||
type DragEndEvent,
|
||||
@@ -14,8 +14,8 @@ import {
|
||||
} from "@dnd-kit/core"
|
||||
import { restrictToVerticalAxis } from "@dnd-kit/modifiers"
|
||||
import {
|
||||
SortableContext,
|
||||
arrayMove,
|
||||
SortableContext,
|
||||
useSortable,
|
||||
verticalListSortingStrategy,
|
||||
} from "@dnd-kit/sortable"
|
||||
@@ -37,9 +37,6 @@ import {
|
||||
import {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
Row,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getFacetedRowModel,
|
||||
@@ -47,7 +44,10 @@ import {
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
Row,
|
||||
SortingState,
|
||||
useReactTable,
|
||||
VisibilityState,
|
||||
} from "@tanstack/react-table"
|
||||
import { Area, AreaChart, CartesianGrid, XAxis } from "recharts"
|
||||
import { toast } from "sonner"
|
||||
|
||||
@@ -39,7 +39,7 @@ function ResizableHandle({
|
||||
<ResizablePrimitive.PanelResizeHandle
|
||||
data-slot="resizable-handle"
|
||||
className={cn(
|
||||
"bg-border focus-visible:ring-ring relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90",
|
||||
"bg-border focus-visible:ring-ring relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:translate-x-0 data-[panel-group-direction=vertical]:after:-translate-y-1/2 [&[data-panel-group-direction=vertical]>div]:rotate-90",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import * as React from "react"
|
||||
import { Slot } from "@radix-ui/react-slot"
|
||||
import { VariantProps, cva } from "class-variance-authority"
|
||||
import { cva, VariantProps } from "class-variance-authority"
|
||||
import { PanelLeftIcon } from "lucide-react"
|
||||
|
||||
import { useIsMobile } from "@/registry/new-york-v4/hooks/use-mobile"
|
||||
|
||||
@@ -20,11 +20,8 @@ const registry = {
|
||||
{
|
||||
name: "index",
|
||||
type: "registry:style",
|
||||
dependencies: [
|
||||
"tw-animate-css",
|
||||
"class-variance-authority",
|
||||
"lucide-react",
|
||||
],
|
||||
dependencies: ["class-variance-authority", "lucide-react"],
|
||||
devDependencies: ["tw-animate-css"],
|
||||
registryDependencies: ["utils"],
|
||||
cssVars: {},
|
||||
files: [],
|
||||
@@ -78,6 +75,11 @@ const registry = {
|
||||
if (item.name === "dashboard-01") {
|
||||
item.dependencies?.push("@tabler/icons-react")
|
||||
}
|
||||
|
||||
if (item.name === "accordion" && "tailwind" in item) {
|
||||
delete item.tailwind
|
||||
}
|
||||
|
||||
return item
|
||||
})
|
||||
),
|
||||
|
||||
@@ -7,7 +7,8 @@ import {
|
||||
PageHeaderDescription,
|
||||
PageHeaderHeading,
|
||||
} from "@/components/page-header"
|
||||
import { ThemeCustomizer } from "@/components/theme-customizer"
|
||||
import { Customizer } from "@/components/theme-customizer"
|
||||
import { Button } from "@/registry/new-york/ui/button"
|
||||
|
||||
const title = "Add colors. Make it yours."
|
||||
const description =
|
||||
@@ -48,10 +49,17 @@ export default function ThemesLayout({
|
||||
<Announcement />
|
||||
<PageHeaderHeading>{title}</PageHeaderHeading>
|
||||
<PageHeaderDescription>{description}</PageHeaderDescription>
|
||||
<PageActions>
|
||||
<ThemeCustomizer />
|
||||
</PageActions>
|
||||
<div className="mt-2 rounded-full bg-blue-600 px-3 py-1 text-xs text-white">
|
||||
New Theme Editor coming soon
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div id="themes" className="border-grid scroll-mt-24 border-b">
|
||||
<div className="container-wrapper">
|
||||
<div className="container flex items-center py-4">
|
||||
<Customizer />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="container-wrapper">
|
||||
<div className="container py-6">
|
||||
<section id="themes" className="scroll-mt-20">
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import "@/styles/globals.css"
|
||||
import { Metadata, Viewport } from "next"
|
||||
import Link from "next/link"
|
||||
import { ArrowRightIcon } from "lucide-react"
|
||||
|
||||
import { META_THEME_COLORS, siteConfig } from "@/config/site"
|
||||
import { fontMono, fontSans } from "@/lib/fonts"
|
||||
@@ -91,7 +93,7 @@ export default function RootLayout({ children }: RootLayoutProps) {
|
||||
</head>
|
||||
<body
|
||||
className={cn(
|
||||
"min-h-svh bg-background font-sans antialiased",
|
||||
"bg-background min-h-svh font-sans antialiased",
|
||||
fontSans.variable,
|
||||
fontMono.variable
|
||||
)}
|
||||
@@ -104,7 +106,16 @@ export default function RootLayout({ children }: RootLayoutProps) {
|
||||
enableColorScheme
|
||||
>
|
||||
<div vaul-drawer-wrapper="">
|
||||
<div className="relative flex min-h-svh flex-col bg-background">
|
||||
<div className="bg-background relative flex min-h-svh flex-col">
|
||||
<div className="bg-muted text-muted-foreground sticky top-0 z-[100] flex h-10 items-center justify-center gap-2 px-4 text-sm">
|
||||
You are viewing the v3 docs.{" "}
|
||||
<Link
|
||||
href="https://ui.shadcn.com"
|
||||
className="text-primary flex items-center gap-1 underline"
|
||||
>
|
||||
Switch to latest <ArrowRightIcon className="size-3" />
|
||||
</Link>
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import * as React from "react"
|
||||
import template from "lodash/template"
|
||||
import { Check, Copy, Moon, Repeat, Sun } from "lucide-react"
|
||||
import { Check, ClipboardIcon, Copy } from "lucide-react"
|
||||
import { useTheme } from "next-themes"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
@@ -21,6 +21,9 @@ import {
|
||||
import {
|
||||
Drawer,
|
||||
DrawerContent,
|
||||
DrawerDescription,
|
||||
DrawerHeader,
|
||||
DrawerTitle,
|
||||
DrawerTrigger,
|
||||
} from "@/registry/new-york/ui/drawer"
|
||||
import { Label } from "@/registry/new-york/ui/label"
|
||||
@@ -29,15 +32,28 @@ import {
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/registry/new-york/ui/popover"
|
||||
import { Separator } from "@/registry/new-york/ui/separator"
|
||||
import { Skeleton } from "@/registry/new-york/ui/skeleton"
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/registry/new-york/ui/tooltip"
|
||||
import { BaseColor, baseColors } from "@/registry/registry-base-colors"
|
||||
BaseColor,
|
||||
baseColors,
|
||||
baseColorsOKLCH,
|
||||
} from "@/registry/registry-base-colors"
|
||||
|
||||
import "@/styles/mdx.css"
|
||||
import { toast } from "sonner"
|
||||
|
||||
import {
|
||||
Tabs,
|
||||
TabsContent,
|
||||
TabsList,
|
||||
TabsTrigger,
|
||||
} from "@/registry/new-york/ui/tabs"
|
||||
|
||||
interface BaseColorOKLCH {
|
||||
light: Record<string, string>
|
||||
dark: Record<string, string>
|
||||
}
|
||||
|
||||
export function ThemeCustomizer() {
|
||||
const [config, setConfig] = useConfig()
|
||||
@@ -78,9 +94,9 @@ export function ThemeCustomizer() {
|
||||
)
|
||||
}
|
||||
|
||||
function Customizer() {
|
||||
export function Customizer() {
|
||||
const [mounted, setMounted] = React.useState(false)
|
||||
const { setTheme: setMode, resolvedTheme: mode } = useTheme()
|
||||
const { resolvedTheme: mode } = useTheme()
|
||||
const [config, setConfig] = useConfig()
|
||||
|
||||
React.useEffect(() => {
|
||||
@@ -88,39 +104,11 @@ function Customizer() {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<ThemeWrapper
|
||||
defaultTheme="zinc"
|
||||
className="flex flex-col space-y-4 md:space-y-6"
|
||||
>
|
||||
<div className="flex items-start pt-4 md:pt-0">
|
||||
<div className="space-y-1 pr-2">
|
||||
<div className="font-semibold leading-none tracking-tight">
|
||||
Theme Customizer
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Customize your components colors.
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="ml-auto rounded-[0.5rem]"
|
||||
onClick={() => {
|
||||
setConfig({
|
||||
...config,
|
||||
theme: "zinc",
|
||||
radius: 0.5,
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Repeat />
|
||||
<span className="sr-only">Reset</span>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex flex-1 flex-col space-y-4 md:space-y-6">
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs">Color</Label>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<ThemeWrapper defaultTheme="zinc">
|
||||
<div className="grid w-full flex-1 grid-cols-2 flex-wrap items-start gap-2 sm:flex sm:items-center md:gap-6">
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label className="sr-only text-xs">Color</Label>
|
||||
<div className="flex flex-wrap gap-1 md:gap-2">
|
||||
{baseColors
|
||||
.filter(
|
||||
(theme) =>
|
||||
@@ -131,7 +119,7 @@ function Customizer() {
|
||||
|
||||
return mounted ? (
|
||||
<Button
|
||||
variant={"outline"}
|
||||
variant="outline"
|
||||
size="sm"
|
||||
key={theme.name}
|
||||
onClick={() => {
|
||||
@@ -141,8 +129,8 @@ function Customizer() {
|
||||
})
|
||||
}}
|
||||
className={cn(
|
||||
"justify-start",
|
||||
isActive && "border-2 border-primary"
|
||||
"w-[32px] rounded-lg lg:px-2.5 xl:w-[86px]",
|
||||
isActive && "border-primary/50 ring-[2px] ring-primary/30"
|
||||
)}
|
||||
style={
|
||||
{
|
||||
@@ -154,22 +142,28 @@ function Customizer() {
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
"mr-1 flex h-5 w-5 shrink-0 -translate-x-1 items-center justify-center rounded-full bg-[--theme-primary]"
|
||||
"flex h-4 w-4 shrink-0 items-center justify-center rounded-full bg-[--theme-primary]"
|
||||
)}
|
||||
>
|
||||
{isActive && <Check className="h-4 w-4 text-white" />}
|
||||
{isActive && <Check className="!size-2.5 text-white" />}
|
||||
</span>
|
||||
<span className="hidden xl:block">
|
||||
{theme.label === "Zinc" ? "Default" : theme.label}
|
||||
</span>
|
||||
{theme.label}
|
||||
</Button>
|
||||
) : (
|
||||
<Skeleton className="h-8 w-full" key={theme.name} />
|
||||
<Skeleton
|
||||
className="h-8 w-[32px] xl:w-[86px]"
|
||||
key={theme.name}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs">Radius</Label>
|
||||
<div className="grid grid-cols-5 gap-2">
|
||||
<Separator orientation="vertical" className="hidden h-6 sm:block" />
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label className="sr-only text-xs">Radius</Label>
|
||||
<div className="flex flex-wrap gap-1 md:gap-2">
|
||||
{["0", "0.3", "0.5", "0.75", "1.0"].map((value) => {
|
||||
return (
|
||||
<Button
|
||||
@@ -183,8 +177,9 @@ function Customizer() {
|
||||
})
|
||||
}}
|
||||
className={cn(
|
||||
"w-[40px] rounded-lg",
|
||||
config.radius === parseFloat(value) &&
|
||||
"border-2 border-primary"
|
||||
"border-primary/50 ring-[2px] ring-primary/30"
|
||||
)}
|
||||
>
|
||||
{value}
|
||||
@@ -193,81 +188,50 @@ function Customizer() {
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs">Mode</Label>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
{mounted ? (
|
||||
<>
|
||||
<Button
|
||||
variant={"outline"}
|
||||
size="sm"
|
||||
onClick={() => setMode("light")}
|
||||
className={cn(mode === "light" && "border-2 border-primary")}
|
||||
>
|
||||
<Sun className="mr-1 -translate-x-1" />
|
||||
Light
|
||||
</Button>
|
||||
<Button
|
||||
variant={"outline"}
|
||||
size="sm"
|
||||
onClick={() => setMode("dark")}
|
||||
className={cn(mode === "dark" && "border-2 border-primary")}
|
||||
>
|
||||
<Moon className="mr-1 -translate-x-1" />
|
||||
Dark
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Skeleton className="h-8 w-full" />
|
||||
<Skeleton className="h-8 w-full" />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex gap-2 sm:ml-auto">
|
||||
<CopyCodeButton />
|
||||
</div>
|
||||
</div>
|
||||
</ThemeWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
function CopyCodeButton({
|
||||
export function CopyCodeButton({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof Button>) {
|
||||
const [config] = useConfig()
|
||||
const activeTheme = baseColors.find((theme) => theme.name === config.theme)
|
||||
const [hasCopied, setHasCopied] = React.useState(false)
|
||||
|
||||
React.useEffect(() => {
|
||||
setTimeout(() => {
|
||||
setHasCopied(false)
|
||||
}, 2000)
|
||||
}, [hasCopied])
|
||||
|
||||
return (
|
||||
<>
|
||||
{activeTheme && (
|
||||
<Button
|
||||
onClick={() => {
|
||||
copyToClipboardWithMeta(getThemeCode(activeTheme, config.radius), {
|
||||
name: "copy_theme_code",
|
||||
properties: {
|
||||
theme: activeTheme.name,
|
||||
radius: config.radius,
|
||||
},
|
||||
})
|
||||
setHasCopied(true)
|
||||
}}
|
||||
className={cn("md:hidden", className)}
|
||||
{...props}
|
||||
>
|
||||
{hasCopied ? <Check /> : <Copy />}
|
||||
Copy code
|
||||
</Button>
|
||||
)}
|
||||
<Drawer>
|
||||
<DrawerTrigger asChild>
|
||||
<Button
|
||||
className={cn("h-8 rounded-lg shadow-none sm:hidden", className)}
|
||||
{...props}
|
||||
>
|
||||
Copy
|
||||
</Button>
|
||||
</DrawerTrigger>
|
||||
<DrawerContent>
|
||||
<DrawerHeader>
|
||||
<DrawerTitle>Theme</DrawerTitle>
|
||||
<DrawerDescription>
|
||||
Copy and paste the following code into your CSS file.
|
||||
</DrawerDescription>
|
||||
</DrawerHeader>
|
||||
<ThemeWrapper defaultTheme="zinc" className="relative px-6">
|
||||
<CustomizerCode />
|
||||
</ThemeWrapper>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button className={cn("hidden md:flex", className)} {...props}>
|
||||
<Button
|
||||
className={cn(
|
||||
"hidden h-8 rounded-lg shadow-none sm:flex",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
Copy code
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
@@ -280,28 +244,6 @@ function CopyCodeButton({
|
||||
</DialogHeader>
|
||||
<ThemeWrapper defaultTheme="zinc" className="relative">
|
||||
<CustomizerCode />
|
||||
{activeTheme && (
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
copyToClipboardWithMeta(
|
||||
getThemeCode(activeTheme, config.radius),
|
||||
{
|
||||
name: "copy_theme_code",
|
||||
properties: {
|
||||
theme: activeTheme.name,
|
||||
radius: config.radius,
|
||||
},
|
||||
}
|
||||
)
|
||||
setHasCopied(true)
|
||||
}}
|
||||
className="absolute right-4 top-4 bg-muted text-muted-foreground hover:bg-muted hover:text-muted-foreground"
|
||||
>
|
||||
{hasCopied ? <Check /> : <Copy />}
|
||||
Copy
|
||||
</Button>
|
||||
)}
|
||||
</ThemeWrapper>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
@@ -311,168 +253,269 @@ function CopyCodeButton({
|
||||
|
||||
function CustomizerCode() {
|
||||
const [config] = useConfig()
|
||||
const activeTheme = baseColors.find((theme) => theme.name === config.theme)
|
||||
const [hasCopied, setHasCopied] = React.useState(false)
|
||||
const [themeVersion, setThemeVersion] = React.useState("v4")
|
||||
const activeTheme = React.useMemo(
|
||||
() => baseColors.find((theme) => theme.name === config.theme),
|
||||
[config.theme]
|
||||
)
|
||||
const activeThemeOKLCH = React.useMemo(
|
||||
() => baseColorsOKLCH[config.theme as keyof typeof baseColorsOKLCH],
|
||||
[config.theme]
|
||||
)
|
||||
|
||||
React.useEffect(() => {
|
||||
if (hasCopied) {
|
||||
setTimeout(() => {
|
||||
setHasCopied(false)
|
||||
}, 2000)
|
||||
}
|
||||
}, [hasCopied])
|
||||
|
||||
return (
|
||||
<ThemeWrapper defaultTheme="zinc" className="relative space-y-4">
|
||||
<div data-rehype-pretty-code-fragment="">
|
||||
<pre className="max-h-[450px] overflow-x-auto rounded-lg border bg-zinc-950 py-4 dark:bg-zinc-900">
|
||||
<code className="relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm">
|
||||
<span className="line text-white">@layer base {</span>
|
||||
<span className="line text-white"> :root {</span>
|
||||
<span className="line text-white">
|
||||
--background:{" "}
|
||||
{activeTheme?.cssVars.light["background"]};
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--foreground:{" "}
|
||||
{activeTheme?.cssVars.light["foreground"]};
|
||||
</span>
|
||||
{[
|
||||
"card",
|
||||
"popover",
|
||||
"primary",
|
||||
"secondary",
|
||||
"muted",
|
||||
"accent",
|
||||
"destructive",
|
||||
].map((prefix) => (
|
||||
<>
|
||||
<span className="line text-white">
|
||||
--{prefix}:{" "}
|
||||
{
|
||||
activeTheme?.cssVars.light[
|
||||
prefix as keyof typeof activeTheme.cssVars.light
|
||||
]
|
||||
}
|
||||
;
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--{prefix}-foreground:{" "}
|
||||
{
|
||||
activeTheme?.cssVars.light[
|
||||
`${prefix}-foreground` as keyof typeof activeTheme.cssVars.light
|
||||
]
|
||||
}
|
||||
;
|
||||
</span>
|
||||
</>
|
||||
))}
|
||||
<span className="line text-white">
|
||||
--border:{" "}
|
||||
{activeTheme?.cssVars.light["border"]};
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--input:{" "}
|
||||
{activeTheme?.cssVars.light["input"]};
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--ring:{" "}
|
||||
{activeTheme?.cssVars.light["ring"]};
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--radius: {config.radius}rem;
|
||||
</span>
|
||||
{["chart-1", "chart-2", "chart-3", "chart-4", "chart-5"].map(
|
||||
(prefix) => (
|
||||
<>
|
||||
<span className="line text-white">
|
||||
--{prefix}:{" "}
|
||||
{
|
||||
activeTheme?.cssVars.light[
|
||||
prefix as keyof typeof activeTheme.cssVars.light
|
||||
]
|
||||
}
|
||||
;
|
||||
</span>
|
||||
</>
|
||||
<Tabs value={themeVersion} onValueChange={setThemeVersion}>
|
||||
<div className="flex items-center justify-between">
|
||||
<TabsList>
|
||||
<TabsTrigger value="v4">Tailwind v4</TabsTrigger>
|
||||
<TabsTrigger value="v3">v3</TabsTrigger>
|
||||
</TabsList>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
copyToClipboardWithMeta(
|
||||
themeVersion === "v3"
|
||||
? getThemeCode(activeTheme, config.radius)
|
||||
: getThemeCodeOKLCH(activeThemeOKLCH, config.radius),
|
||||
{
|
||||
name: "copy_theme_code",
|
||||
properties: {
|
||||
theme: config.theme,
|
||||
radius: config.radius,
|
||||
},
|
||||
}
|
||||
)
|
||||
)}
|
||||
<span className="line text-white"> }</span>
|
||||
<span className="line text-white"> </span>
|
||||
<span className="line text-white"> .dark {</span>
|
||||
<span className="line text-white">
|
||||
--background:{" "}
|
||||
{activeTheme?.cssVars.dark["background"]};
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--foreground:{" "}
|
||||
{activeTheme?.cssVars.dark["foreground"]};
|
||||
</span>
|
||||
{[
|
||||
"card",
|
||||
"popover",
|
||||
"primary",
|
||||
"secondary",
|
||||
"muted",
|
||||
"accent",
|
||||
"destructive",
|
||||
].map((prefix) => (
|
||||
<>
|
||||
setHasCopied(true)
|
||||
}}
|
||||
className="absolute right-0 top-0 shadow-none"
|
||||
>
|
||||
{hasCopied ? <Check /> : <ClipboardIcon />}
|
||||
Copy
|
||||
</Button>
|
||||
</div>
|
||||
<TabsContent value="v4">
|
||||
<div data-rehype-pretty-code-fragment="">
|
||||
<pre className="max-h-[450px] overflow-x-auto rounded-lg border bg-zinc-950 py-4 dark:bg-zinc-900">
|
||||
<code className="relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm">
|
||||
<span className="line text-white"> :root {</span>
|
||||
<span className="line text-white">
|
||||
--{prefix}:{" "}
|
||||
{
|
||||
activeTheme?.cssVars.dark[
|
||||
prefix as keyof typeof activeTheme.cssVars.dark
|
||||
]
|
||||
}
|
||||
;
|
||||
--radius: {config.radius}rem;
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--{prefix}-foreground:{" "}
|
||||
{
|
||||
activeTheme?.cssVars.dark[
|
||||
`${prefix}-foreground` as keyof typeof activeTheme.cssVars.dark
|
||||
]
|
||||
}
|
||||
;
|
||||
</span>
|
||||
</>
|
||||
))}
|
||||
<span className="line text-white">
|
||||
--border:{" "}
|
||||
{activeTheme?.cssVars.dark["border"]};
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--input:{" "}
|
||||
{activeTheme?.cssVars.dark["input"]};
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--ring:{" "}
|
||||
{activeTheme?.cssVars.dark["ring"]};
|
||||
</span>
|
||||
{["chart-1", "chart-2", "chart-3", "chart-4", "chart-5"].map(
|
||||
(prefix) => (
|
||||
<>
|
||||
<span className="line text-white">
|
||||
--{prefix}:{" "}
|
||||
{
|
||||
activeTheme?.cssVars.dark[
|
||||
prefix as keyof typeof activeTheme.cssVars.dark
|
||||
]
|
||||
}
|
||||
;
|
||||
{Object.entries(activeThemeOKLCH?.light).map(([key, value]) => (
|
||||
<span className="line text-white" key={key}>
|
||||
--{key}: {value};
|
||||
</span>
|
||||
</>
|
||||
)
|
||||
)}
|
||||
<span className="line text-white"> }</span>
|
||||
<span className="line text-white">}</span>
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
))}
|
||||
<span className="line text-white"> }</span>
|
||||
<span className="line text-white"> </span>
|
||||
<span className="line text-white"> .dark {</span>
|
||||
{Object.entries(activeThemeOKLCH?.dark).map(([key, value]) => (
|
||||
<span className="line text-white" key={key}>
|
||||
--{key}: {value};
|
||||
</span>
|
||||
))}
|
||||
<span className="line text-white"> }</span>
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent value="v3">
|
||||
<div data-rehype-pretty-code-fragment="">
|
||||
<pre className="max-h-[450px] overflow-x-auto rounded-lg border bg-zinc-950 py-4 dark:bg-zinc-900">
|
||||
<code className="relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm">
|
||||
<span className="line text-white">@layer base {</span>
|
||||
<span className="line text-white">
|
||||
:root {
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--background:{" "}
|
||||
{activeTheme?.cssVars.light["background"]};
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--foreground:{" "}
|
||||
{activeTheme?.cssVars.light["foreground"]};
|
||||
</span>
|
||||
{[
|
||||
"card",
|
||||
"popover",
|
||||
"primary",
|
||||
"secondary",
|
||||
"muted",
|
||||
"accent",
|
||||
"destructive",
|
||||
].map((prefix) => (
|
||||
<>
|
||||
<span className="line text-white">
|
||||
--{prefix}:{" "}
|
||||
{
|
||||
activeTheme?.cssVars.light[
|
||||
prefix as keyof typeof activeTheme.cssVars.light
|
||||
]
|
||||
}
|
||||
;
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--{prefix}-foreground:{" "}
|
||||
{
|
||||
activeTheme?.cssVars.light[
|
||||
`${prefix}-foreground` as keyof typeof activeTheme.cssVars.light
|
||||
]
|
||||
}
|
||||
;
|
||||
</span>
|
||||
</>
|
||||
))}
|
||||
<span className="line text-white">
|
||||
--border:{" "}
|
||||
{activeTheme?.cssVars.light["border"]};
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--input:{" "}
|
||||
{activeTheme?.cssVars.light["input"]};
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--ring:{" "}
|
||||
{activeTheme?.cssVars.light["ring"]};
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--radius: {config.radius}rem;
|
||||
</span>
|
||||
{["chart-1", "chart-2", "chart-3", "chart-4", "chart-5"].map(
|
||||
(prefix) => (
|
||||
<>
|
||||
<span className="line text-white">
|
||||
--{prefix}:{" "}
|
||||
{
|
||||
activeTheme?.cssVars.light[
|
||||
prefix as keyof typeof activeTheme.cssVars.light
|
||||
]
|
||||
}
|
||||
;
|
||||
</span>
|
||||
</>
|
||||
)
|
||||
)}
|
||||
<span className="line text-white"> }</span>
|
||||
<span className="line text-white"> </span>
|
||||
<span className="line text-white">
|
||||
.dark {
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--background:{" "}
|
||||
{activeTheme?.cssVars.dark["background"]};
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--foreground:{" "}
|
||||
{activeTheme?.cssVars.dark["foreground"]};
|
||||
</span>
|
||||
{[
|
||||
"card",
|
||||
"popover",
|
||||
"primary",
|
||||
"secondary",
|
||||
"muted",
|
||||
"accent",
|
||||
"destructive",
|
||||
].map((prefix) => (
|
||||
<>
|
||||
<span className="line text-white">
|
||||
--{prefix}:{" "}
|
||||
{
|
||||
activeTheme?.cssVars.dark[
|
||||
prefix as keyof typeof activeTheme.cssVars.dark
|
||||
]
|
||||
}
|
||||
;
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--{prefix}-foreground:{" "}
|
||||
{
|
||||
activeTheme?.cssVars.dark[
|
||||
`${prefix}-foreground` as keyof typeof activeTheme.cssVars.dark
|
||||
]
|
||||
}
|
||||
;
|
||||
</span>
|
||||
</>
|
||||
))}
|
||||
<span className="line text-white">
|
||||
--border:{" "}
|
||||
{activeTheme?.cssVars.dark["border"]};
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--input:{" "}
|
||||
{activeTheme?.cssVars.dark["input"]};
|
||||
</span>
|
||||
<span className="line text-white">
|
||||
--ring:{" "}
|
||||
{activeTheme?.cssVars.dark["ring"]};
|
||||
</span>
|
||||
{["chart-1", "chart-2", "chart-3", "chart-4", "chart-5"].map(
|
||||
(prefix) => (
|
||||
<>
|
||||
<span className="line text-white">
|
||||
--{prefix}:{" "}
|
||||
{
|
||||
activeTheme?.cssVars.dark[
|
||||
prefix as keyof typeof activeTheme.cssVars.dark
|
||||
]
|
||||
}
|
||||
;
|
||||
</span>
|
||||
</>
|
||||
)
|
||||
)}
|
||||
<span className="line text-white"> }</span>
|
||||
<span className="line text-white">}</span>
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</ThemeWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
function getThemeCode(theme: BaseColor, radius: number) {
|
||||
function getThemeCodeOKLCH(theme: BaseColorOKLCH | undefined, radius: number) {
|
||||
if (!theme) {
|
||||
return ""
|
||||
}
|
||||
|
||||
const rootSection =
|
||||
":root {\n --radius: " +
|
||||
radius +
|
||||
"rem;\n" +
|
||||
Object.entries(theme.light)
|
||||
.map((entry) => " --" + entry[0] + ": " + entry[1] + ";")
|
||||
.join("\n") +
|
||||
"\n}\n\n.dark {\n" +
|
||||
Object.entries(theme.dark)
|
||||
.map((entry) => " --" + entry[0] + ": " + entry[1] + ";")
|
||||
.join("\n") +
|
||||
"\n}\n"
|
||||
|
||||
return rootSection
|
||||
}
|
||||
|
||||
function getThemeCode(theme: BaseColor | undefined, radius: number) {
|
||||
if (!theme) {
|
||||
return ""
|
||||
}
|
||||
|
||||
return template(BASE_STYLES_WITH_VARIABLES)({
|
||||
colors: theme.cssVars,
|
||||
radius,
|
||||
radius: radius.toString(),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -433,6 +433,11 @@ export const docsConfig: DocsConfig = {
|
||||
href: "/docs/registry/getting-started",
|
||||
items: [],
|
||||
},
|
||||
{
|
||||
title: "Examples",
|
||||
href: "/docs/registry/examples",
|
||||
items: [],
|
||||
},
|
||||
{
|
||||
title: "Open in v0",
|
||||
href: "/docs/registry/open-in-v0",
|
||||
|
||||
@@ -321,7 +321,7 @@ I've been working on a new CLI for the past few weeks. It's a complete rewrite.
|
||||
### `init`
|
||||
|
||||
```bash
|
||||
npx shadcn-ui@latest init
|
||||
npx shadcn@latest init
|
||||
```
|
||||
|
||||
When you run the `init` command, you will be asked a few questions to configure `components.json`:
|
||||
@@ -363,7 +363,7 @@ This means you can now use the CLI with any directory structure including `src`
|
||||
### `add`
|
||||
|
||||
```bash
|
||||
npx shadcn-ui@latest add
|
||||
npx shadcn@latest add
|
||||
```
|
||||
|
||||
The `add` command is now much more capable. You can now add UI components but also import more complex components (coming soon).
|
||||
@@ -373,7 +373,7 @@ The CLI will automatically resolve all components and dependencies, format them
|
||||
### `diff` (experimental)
|
||||
|
||||
```bash
|
||||
npx shadcn-ui diff
|
||||
npx shadcn diff
|
||||
```
|
||||
|
||||
We're also introducing a new `diff` command to help you keep track of upstream updates.
|
||||
@@ -383,7 +383,7 @@ You can use this command to see what has changed in the upstream repository and
|
||||
Run the `diff` command to get a list of components that have updates available:
|
||||
|
||||
```bash
|
||||
npx shadcn-ui diff
|
||||
npx shadcn diff
|
||||
```
|
||||
|
||||
```txt
|
||||
@@ -398,7 +398,7 @@ The following components have updates available:
|
||||
Then run `diff [component]` to see the changes:
|
||||
|
||||
```bash
|
||||
npx shadcn-ui diff alert
|
||||
npx shadcn diff alert
|
||||
```
|
||||
|
||||
```diff /pl-12/
|
||||
|
||||
@@ -79,7 +79,7 @@ export const onCreateWebpackConfig = ({ actions }) => {
|
||||
|
||||
### Run the CLI
|
||||
|
||||
Run the `shadcn-ui` init command to setup your project:
|
||||
Run the `shadcn` init command to setup your project:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init
|
||||
|
||||
@@ -13,7 +13,7 @@ npx create-react-router@latest my-app
|
||||
|
||||
### Run the CLI
|
||||
|
||||
Run the `shadcn-ui` init command to setup your project:
|
||||
Run the `shadcn` init command to setup your project:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init
|
||||
|
||||
@@ -26,7 +26,7 @@ npx create-remix@latest my-app
|
||||
|
||||
### Run the CLI
|
||||
|
||||
Run the `shadcn-ui` init command to setup your project:
|
||||
Run the `shadcn` init command to setup your project:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init
|
||||
|
||||
356
apps/www/content/docs/registry/examples.mdx
Normal file
356
apps/www/content/docs/registry/examples.mdx
Normal file
@@ -0,0 +1,356 @@
|
||||
---
|
||||
title: Examples
|
||||
description: "Examples of registry items: styles, components, css vars, etc."
|
||||
---
|
||||
|
||||
## registry:style
|
||||
|
||||
### Custom style that extends shadcn/ui
|
||||
|
||||
The following registry item is a custom style that extends shadcn/ui. On `npx shadcn init`, it will:
|
||||
|
||||
- Install `@tabler/icons-react` as a dependency.
|
||||
- Add the `login-01` block and `calendar` component to the project.
|
||||
- Add the `editor` from a remote registry.
|
||||
- Set the `font-sans` variable to `Inter, sans-serif`.
|
||||
- Install a `brand` color in light and dark mode.
|
||||
|
||||
```json title="example-style.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||
"name": "example-style",
|
||||
"type": "registry:style",
|
||||
"dependencies": ["@tabler/icons-react"],
|
||||
"registryDependencies": [
|
||||
"login-01",
|
||||
"calendar",
|
||||
"https://example.com/r/editor.json"
|
||||
],
|
||||
"cssVars": {
|
||||
"theme": {
|
||||
"font-sans": "Inter, sans-serif"
|
||||
},
|
||||
"light": {
|
||||
"brand": "20 14.3% 4.1%"
|
||||
},
|
||||
"dark": {
|
||||
"brand": "20 14.3% 4.1%"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Custom style from scratch
|
||||
|
||||
The following registry item is a custom style that doesn't extend shadcn/ui. See the `extends: none` field.
|
||||
|
||||
It can be used to create a new style from scratch i.e custom components, css vars, dependencies, etc.
|
||||
|
||||
On `npx shadcn add`, the following will:
|
||||
|
||||
- Install `tailwind-merge` and `clsx` as dependencies.
|
||||
- Add the `utils` registry item from the shadcn/ui registry.
|
||||
- Add the `button`, `input`, `label`, and `select` components from a remote registry.
|
||||
- Install new css vars: `main`, `bg`, `border`, `text`, `ring`.
|
||||
|
||||
```json title="example-style.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||
"extends": "none",
|
||||
"name": "new-style",
|
||||
"type": "registry:style",
|
||||
"dependencies": ["tailwind-merge", "clsx"],
|
||||
"registryDependencies": [
|
||||
"utils",
|
||||
"https://example.com/r/button.json",
|
||||
"https://example.com/r/input.json",
|
||||
"https://example.com/r/label.json",
|
||||
"https://example.com/r/select.json"
|
||||
],
|
||||
"cssVars": {
|
||||
"theme": {
|
||||
"font-sans": "Inter, sans-serif",
|
||||
}
|
||||
"light": {
|
||||
"main": "#88aaee",
|
||||
"bg": "#dfe5f2",
|
||||
"border": "#000",
|
||||
"text": "#000",
|
||||
"ring": "#000",
|
||||
},
|
||||
"dark": {
|
||||
"main": "#88aaee",
|
||||
"bg": "#272933",
|
||||
"border": "#000",
|
||||
"text": "#e6e6e6",
|
||||
"ring": "#fff",
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## registry:theme
|
||||
|
||||
### Custom theme
|
||||
|
||||
```json title="example-theme.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||
"name": "custom-theme",
|
||||
"type": "registry:theme",
|
||||
"cssVars": {
|
||||
"light": {
|
||||
"background": "oklch(1 0 0)",
|
||||
"foreground": "oklch(0.141 0.005 285.823)",
|
||||
"primary": "oklch(0.546 0.245 262.881)",
|
||||
"primary-foreground": "oklch(0.97 0.014 254.604)",
|
||||
"ring": "oklch(0.746 0.16 232.661)",
|
||||
"sidebar-primary": "oklch(0.546 0.245 262.881)",
|
||||
"sidebar-primary-foreground": "oklch(0.97 0.014 254.604)",
|
||||
"sidebar-ring": "oklch(0.746 0.16 232.661)"
|
||||
},
|
||||
"dark": {
|
||||
"background": "oklch(1 0 0)",
|
||||
"foreground": "oklch(0.141 0.005 285.823)",
|
||||
"primary": "oklch(0.707 0.165 254.624)",
|
||||
"primary-foreground": "oklch(0.97 0.014 254.604)",
|
||||
"ring": "oklch(0.707 0.165 254.624)",
|
||||
"sidebar-primary": "oklch(0.707 0.165 254.624)",
|
||||
"sidebar-primary-foreground": "oklch(0.97 0.014 254.604)",
|
||||
"sidebar-ring": "oklch(0.707 0.165 254.624)"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Custom colors
|
||||
|
||||
The following style will init using shadcn/ui defaults and then add a custom `brand` color.
|
||||
|
||||
```json title="example-style.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||
"name": "custom-style",
|
||||
"type": "registry:style",
|
||||
"cssVars": {
|
||||
"light": {
|
||||
"brand": "oklch(0.99 0.00 0)"
|
||||
},
|
||||
"dark": {
|
||||
"brand": "oklch(0.14 0.00 286)"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## registry:block
|
||||
|
||||
### Custom block
|
||||
|
||||
This blocks installs the `login-01` block from the shadcn/ui registry.
|
||||
|
||||
```json title="login-01.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||
"name": "login-01",
|
||||
"type": "registry:block",
|
||||
"description": "A simple login form.",
|
||||
"registryDependencies": ["button", "card", "input", "label"],
|
||||
"files": [
|
||||
{
|
||||
"path": "blocks/login-01/page.tsx",
|
||||
"content": "import { LoginForm } ...",
|
||||
"type": "registry:page",
|
||||
"target": "app/login/page.tsx"
|
||||
},
|
||||
{
|
||||
"path": "blocks/login-01/components/login-form.tsx",
|
||||
"content": "...",
|
||||
"type": "registry:component"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Install a block and override primitives
|
||||
|
||||
You can install a block fromt the shadcn/ui registry and override the primitives using your custom ones.
|
||||
|
||||
On `npx shadcn add`, the following will:
|
||||
|
||||
- Add the `login-01` block from the shadcn/ui registry.
|
||||
- Override the `button`, `input`, and `label` primitives with the ones from the remote registry.
|
||||
|
||||
```json title="example-style.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||
"name": "custom-login",
|
||||
"type": "registry:block",
|
||||
"registryDependencies": [
|
||||
"login-01",
|
||||
"https://example.com/r/button.json",
|
||||
"https://example.com/r/input.json",
|
||||
"https://example.com/r/label.json"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## CSS Variables
|
||||
|
||||
### Custom Theme Variables
|
||||
|
||||
Add custom theme variables to the `theme` object.
|
||||
|
||||
```json title="example-theme.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||
"name": "custom-theme",
|
||||
"type": "registry:theme",
|
||||
"cssVars": {
|
||||
"theme": {
|
||||
"font-heading": "Inter, sans-serif",
|
||||
"shadow-card": "0 0 0 1px rgba(0, 0, 0, 0.1)"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Override Tailwind CSS variables
|
||||
|
||||
```json title="example-theme.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||
"name": "custom-theme",
|
||||
"type": "registry:theme",
|
||||
"cssVars": {
|
||||
"theme": {
|
||||
"spacing": "0.2rem",
|
||||
"breakpoint-sm": "640px",
|
||||
"breakpoint-md": "768px",
|
||||
"breakpoint-lg": "1024px",
|
||||
"breakpoint-xl": "1280px",
|
||||
"breakpoint-2xl": "1536px"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Add custom CSS
|
||||
|
||||
### Base styles
|
||||
|
||||
```json title="example-base.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||
"name": "custom-style",
|
||||
"type": "registry:style",
|
||||
"css": {
|
||||
"@layer base": {
|
||||
"h1": {
|
||||
"font-size": "var(--text-2xl)"
|
||||
},
|
||||
"h2": {
|
||||
"font-size": "var(--text-xl)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Components
|
||||
|
||||
```json title="example-card.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||
"name": "custom-card",
|
||||
"type": "registry:component",
|
||||
"css": {
|
||||
"@layer components": {
|
||||
"card": {
|
||||
"background-color": "var(--color-white)",
|
||||
"border-radius": "var(--rounded-lg)",
|
||||
"padding": "var(--spacing-6)",
|
||||
"box-shadow": "var(--shadow-xl)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Add custom utilities
|
||||
|
||||
### Simple utility
|
||||
|
||||
```json title="example-component.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||
"name": "custom-component",
|
||||
"type": "registry:component",
|
||||
"css": {
|
||||
"@utility content-auto": {
|
||||
"content-visibility": "auto"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Complex utility
|
||||
|
||||
```json title="example-utility.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||
"name": "custom-component",
|
||||
"type": "registry:component",
|
||||
"css": {
|
||||
"@utility scrollbar-hidden": {
|
||||
"scrollbar-hidden": {
|
||||
"&::-webkit-scrollbar": {
|
||||
"display": "none"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Functional utilities
|
||||
|
||||
```json title="example-functional.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||
"name": "custom-component",
|
||||
"type": "registry:component",
|
||||
"css": {
|
||||
"@utility tab-*": {
|
||||
"tab-size": "var(--tab-size-*)"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Add custom animations
|
||||
|
||||
Note: you need to define both `@keyframes` in css and `theme` in cssVars to use animations.
|
||||
|
||||
```json title="example-component.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||
"name": "custom-component",
|
||||
"type": "registry:component",
|
||||
"cssVars": {
|
||||
"theme": {
|
||||
"--animate-wiggle": "wiggle 1s ease-in-out infinite"
|
||||
}
|
||||
},
|
||||
"css": {
|
||||
"@keyframes wiggle": {
|
||||
"0%, 100%": {
|
||||
"transform": "rotate(-3deg)"
|
||||
},
|
||||
"50%": {
|
||||
"transform": "rotate(3deg)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -36,6 +36,10 @@ The `registry-item.json` schema is used to define your custom registry items.
|
||||
}
|
||||
```
|
||||
|
||||
<div className="flex gap-2 items-center mt-6">
|
||||
<Link href="/docs/registry/examples">See more examples</Link>
|
||||
</div>
|
||||
|
||||
## Definitions
|
||||
|
||||
You can see the JSON Schema for `registry-item.json` [here](https://ui.shadcn.com/schema/registry-item.json).
|
||||
@@ -254,6 +258,41 @@ Use to define CSS variables for your registry item.
|
||||
}
|
||||
```
|
||||
|
||||
### css
|
||||
|
||||
Use `css` to add new rules to the project's CSS file eg. `@layer base`, `@layer components`, `@utility`, `@keyframes`, etc.
|
||||
|
||||
```json title="registry-item.json" showLineNumbers
|
||||
{
|
||||
"css": {
|
||||
"@layer base": {
|
||||
"body": {
|
||||
"font-size": "var(--text-base)",
|
||||
"line-height": "1.5"
|
||||
}
|
||||
},
|
||||
"@layer components": {
|
||||
"button": {
|
||||
"background-color": "var(--color-primary)",
|
||||
"color": "var(--color-white)"
|
||||
}
|
||||
},
|
||||
"@utility text-magic": {
|
||||
"font-size": "var(--text-base)",
|
||||
"line-height": "1.5"
|
||||
},
|
||||
"@keyframes wiggle": {
|
||||
"0%, 100%": {
|
||||
"transform": "rotate(-3deg)"
|
||||
},
|
||||
"50%": {
|
||||
"transform": "rotate(3deg)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### docs
|
||||
|
||||
Use `docs` to show custom documentation or message when installing your registry item via the CLI.
|
||||
|
||||
@@ -113,7 +113,7 @@ export default makeSource({
|
||||
[
|
||||
rehypePrettyCode,
|
||||
{
|
||||
theme: "github-dark",
|
||||
theme: "github-dark-default",
|
||||
getHighlighter,
|
||||
onVisitLine(node) {
|
||||
// Prevent lines from collapsing in `display: grid` mode, and allow empty
|
||||
|
||||
@@ -2,6 +2,12 @@ import { createContentlayerPlugin } from "next-contentlayer2"
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
eslint: {
|
||||
ignoreDuringBuilds: true,
|
||||
},
|
||||
typescript: {
|
||||
ignoreBuildErrors: true,
|
||||
},
|
||||
experimental: {
|
||||
outputFileTracingIncludes: {
|
||||
"/blocks/*": ["./registry/**/*"],
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
"react-resizable-panels": "^2.0.22",
|
||||
"react-wrap-balancer": "^0.4.1",
|
||||
"recharts": "2.12.7",
|
||||
"shadcn": "2.3.0",
|
||||
"shadcn": "2.5.0",
|
||||
"sharp": "^0.32.6",
|
||||
"sonner": "^1.2.3",
|
||||
"swr": "2.2.6-beta.3",
|
||||
|
||||
@@ -11,35 +11,5 @@
|
||||
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\"\nimport { ChevronDownIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Accordion({\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Root>) {\n return <AccordionPrimitive.Root data-slot=\"accordion\" {...props} />\n}\n\nfunction AccordionItem({\n className,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Item>) {\n return (\n <AccordionPrimitive.Item\n data-slot=\"accordion-item\"\n className={cn(\"border-b last:border-b-0\", className)}\n {...props}\n />\n )\n}\n\nfunction AccordionTrigger({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n data-slot=\"accordion-trigger\"\n className={cn(\n \"focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronDownIcon className=\"text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n )\n}\n\nfunction AccordionContent({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Content>) {\n return (\n <AccordionPrimitive.Content\n data-slot=\"accordion-content\"\n className=\"data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm\"\n {...props}\n >\n <div className={cn(\"pt-0 pb-4\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n )\n}\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
"tailwind": {
|
||||
"config": {
|
||||
"theme": {
|
||||
"extend": {
|
||||
"keyframes": {
|
||||
"accordion-down": {
|
||||
"from": {
|
||||
"height": "0"
|
||||
},
|
||||
"to": {
|
||||
"height": "var(--radix-accordion-content-height)"
|
||||
}
|
||||
},
|
||||
"accordion-up": {
|
||||
"from": {
|
||||
"height": "var(--radix-accordion-content-height)"
|
||||
},
|
||||
"to": {
|
||||
"height": "0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation": {
|
||||
"accordion-down": "accordion-down 0.2s ease-out",
|
||||
"accordion-up": "accordion-up 0.2s ease-out"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3,10 +3,12 @@
|
||||
"name": "index",
|
||||
"type": "registry:style",
|
||||
"dependencies": [
|
||||
"tw-animate-css",
|
||||
"class-variance-authority",
|
||||
"lucide-react"
|
||||
],
|
||||
"devDependencies": [
|
||||
"tw-animate-css"
|
||||
],
|
||||
"registryDependencies": [
|
||||
"utils"
|
||||
],
|
||||
|
||||
@@ -78,7 +78,8 @@
|
||||
"registry:hook",
|
||||
"registry:theme",
|
||||
"registry:page",
|
||||
"registry:file"
|
||||
"registry:file",
|
||||
"registry:style"
|
||||
],
|
||||
"description": "The type of the file. This is used to determine the type of the file when resolved for a project."
|
||||
},
|
||||
@@ -156,6 +157,38 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"css": {
|
||||
"type": "object",
|
||||
"description": "CSS definitions to be added to the project's CSS file. Supports at-rules, selectors, nested rules, utilities, layers, and more.",
|
||||
"additionalProperties": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Direct CSS string (e.g., 'font-family: sans-serif; line-height: 1.5;')"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"description": "CSS properties or nested selectors",
|
||||
"additionalProperties": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "CSS property value (e.g., 'blue', 'var(--color-primary)')"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"description": "Nested selector or rule with properties",
|
||||
"additionalProperties": {
|
||||
"type": "string",
|
||||
"description": "CSS property value for nested rule"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"type": "object",
|
||||
"description": "Additional metadata for the registry item. This is an object with any key value pairs.",
|
||||
|
||||
@@ -1102,3 +1102,550 @@ export const baseColorsV4 = {
|
||||
},
|
||||
},
|
||||
} as const
|
||||
|
||||
export const baseColorsOKLCH = {
|
||||
zinc: {
|
||||
light: {
|
||||
background: "oklch(1 0 0)", // --color-zinc-50
|
||||
foreground: "oklch(0.141 0.005 285.823)", // --color-zinc-950
|
||||
card: "oklch(1 0 0)", // --color-zinc-50
|
||||
"card-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950
|
||||
popover: "oklch(1 0 0)", // --color-zinc-50
|
||||
"popover-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950
|
||||
primary: "oklch(0.21 0.006 285.885)", // --color-zinc-900
|
||||
"primary-foreground": "oklch(0.985 0 0)", // --color-zinc-50
|
||||
secondary: "oklch(0.967 0.001 286.375)", // --color-zinc-100
|
||||
"secondary-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900
|
||||
muted: "oklch(0.967 0.001 286.375)", // --color-zinc-100
|
||||
"muted-foreground": "oklch(0.552 0.016 285.938)", // --color-zinc-500
|
||||
accent: "oklch(0.967 0.001 286.375)", // --color-zinc-100
|
||||
"accent-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900
|
||||
destructive: "oklch(0.577 0.245 27.325)", // --color-red-600
|
||||
border: "oklch(0.92 0.004 286.32)", // --color-zinc-200
|
||||
input: "oklch(0.92 0.004 286.32)", // --color-zinc-200
|
||||
ring: "oklch(0.705 0.015 286.067)", // --color-zinc-400
|
||||
"chart-1": "oklch(0.646 0.222 41.116)", // --color-orange-600
|
||||
"chart-2": "oklch(0.6 0.118 184.704)", // --color-teal-600
|
||||
"chart-3": "oklch(0.398 0.07 227.392)", // --color-cyan-900
|
||||
"chart-4": "oklch(0.828 0.189 84.429)", // --color-amber-400
|
||||
"chart-5": "oklch(0.769 0.188 70.08)", // --color-amber-500
|
||||
sidebar: "oklch(0.985 0 0)", // --color-zinc-50
|
||||
"sidebar-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950
|
||||
"sidebar-primary": "oklch(0.21 0.006 285.885)", // --color-zinc-900
|
||||
"sidebar-primary-foreground": "oklch(0.985 0 0)", // --color-zinc-50
|
||||
"sidebar-accent": "oklch(0.967 0.001 286.375)", // --color-zinc-100
|
||||
"sidebar-accent-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900
|
||||
"sidebar-border": "oklch(0.92 0.004 286.32)", // --color-zinc-200
|
||||
"sidebar-ring": "oklch(0.705 0.015 286.067)", // --color-zinc-400
|
||||
},
|
||||
dark: {
|
||||
background: "oklch(0.141 0.005 285.823)", // --color-zinc-950
|
||||
foreground: "oklch(0.985 0 0)", // --color-zinc-50
|
||||
card: "oklch(0.21 0.006 285.885)", // --color-zinc-900
|
||||
"card-foreground": "oklch(0.985 0 0)", // --color-zinc-50
|
||||
popover: "oklch(0.21 0.006 285.885)", // --color-zinc-900
|
||||
"popover-foreground": "oklch(0.985 0 0)", // --color-zinc-50
|
||||
primary: "oklch(0.92 0.004 286.32)", // --color-zinc-200
|
||||
"primary-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900
|
||||
secondary: "oklch(0.274 0.006 286.033)", // --color-zinc-800
|
||||
"secondary-foreground": "oklch(0.985 0 0)", // --color-zinc-50
|
||||
muted: "oklch(0.274 0.006 286.033)", // --color-zinc-800
|
||||
"muted-foreground": "oklch(0.705 0.015 286.067)", // --color-zinc-400
|
||||
accent: "oklch(0.274 0.006 286.033)", // --color-zinc-800
|
||||
"accent-foreground": "oklch(0.985 0 0)", // --color-zinc-50
|
||||
destructive: "oklch(0.704 0.191 22.216)", // --color-red-400
|
||||
border: "oklch(1 0 0 / 10%)", // --color-white
|
||||
input: "oklch(1 0 0 / 15%)", // --color-white
|
||||
ring: "oklch(0.552 0.016 285.938)", // --color-zinc-500
|
||||
"chart-1": "oklch(0.488 0.243 264.376)", // --color-blue-700
|
||||
"chart-2": "oklch(0.696 0.17 162.48)", // --color-emerald-500
|
||||
"chart-3": "oklch(0.769 0.188 70.08)", // --color-amber-500
|
||||
"chart-4": "oklch(0.627 0.265 303.9)", // --color-purple-500
|
||||
"chart-5": "oklch(0.645 0.246 16.439)", // --color-rose-500
|
||||
sidebar: "oklch(0.21 0.006 285.885)", // --color-zinc-900
|
||||
"sidebar-foreground": "oklch(0.985 0 0)", // --color-zinc-50
|
||||
"sidebar-primary": "oklch(0.488 0.243 264.376)", // --color-blue-700
|
||||
"sidebar-primary-foreground": "oklch(0.985 0 0)", // --color-zinc-50
|
||||
"sidebar-accent": "oklch(0.274 0.006 286.033)", // --color-zinc-800
|
||||
"sidebar-accent-foreground": "oklch(0.985 0 0)", // --color-zinc-50
|
||||
"sidebar-border": "oklch(1 0 0 / 10%)", // --color-white
|
||||
"sidebar-ring": "oklch(0.552 0.016 285.938)", // --color-zinc-500
|
||||
},
|
||||
},
|
||||
red: {
|
||||
light: {
|
||||
background: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
foreground: "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
card: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
"card-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
popover: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
"popover-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
primary: "oklch(0.637 0.237 25.331)", // --color-red-500 (approx HSL 0 72.2% 50.6%)
|
||||
"primary-foreground": "oklch(0.971 0.013 17.38)", // --color-red-50 (approx HSL 0 85.7% 97.3%)
|
||||
secondary: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"secondary-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
muted: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"muted-foreground": "oklch(0.552 0.016 285.938)", // --color-zinc-500 (from zinc)
|
||||
accent: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"accent-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
destructive: "oklch(0.577 0.245 27.325)", // --color-red-600 (from zinc)
|
||||
border: "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
input: "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
ring: "oklch(0.637 0.237 25.331)", // --color-red-500 (approx HSL 0 72.2% 50.6%)
|
||||
"chart-1": "oklch(0.646 0.222 41.116)", // --color-orange-600 (from zinc)
|
||||
"chart-2": "oklch(0.6 0.118 184.704)", // --color-teal-600 (from zinc)
|
||||
"chart-3": "oklch(0.398 0.07 227.392)", // --color-cyan-900 (from zinc)
|
||||
"chart-4": "oklch(0.828 0.189 84.429)", // --color-amber-400 (from zinc)
|
||||
"chart-5": "oklch(0.769 0.188 70.08)", // --color-amber-500 (from zinc)
|
||||
sidebar: "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
"sidebar-primary": "oklch(0.637 0.237 25.331)", // --color-red-500 (approx HSL 0 72.2% 50.6%)
|
||||
"sidebar-primary-foreground": "oklch(0.971 0.013 17.38)", // --color-red-50 (approx HSL 0 85.7% 97.3%)
|
||||
"sidebar-accent": "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"sidebar-accent-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"sidebar-border": "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
"sidebar-ring": "oklch(0.637 0.237 25.331)", // --color-red-500 (approx HSL 0 72.2% 50.6%)
|
||||
},
|
||||
dark: {
|
||||
background: "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
foreground: "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
card: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"card-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
popover: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"popover-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
primary: "oklch(0.637 0.237 25.331)", // --color-red-500 (approx HSL 0 72.2% 50.6%)
|
||||
"primary-foreground": "oklch(0.971 0.013 17.38)", // --color-red-50 (approx HSL 0 85.7% 97.3%)
|
||||
secondary: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"secondary-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
muted: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"muted-foreground": "oklch(0.705 0.015 286.067)", // --color-zinc-400 (from zinc)
|
||||
accent: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"accent-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
destructive: "oklch(0.704 0.191 22.216)", // --color-red-400 (from zinc)
|
||||
border: "oklch(1 0 0 / 10%)", // --color-white (from zinc)
|
||||
input: "oklch(1 0 0 / 15%)", // --color-white (from zinc)
|
||||
ring: "oklch(0.637 0.237 25.331)", // --color-red-500 (approx HSL 0 72.2% 50.6%)
|
||||
"chart-1": "oklch(0.488 0.243 264.376)", // --color-blue-700 (from zinc)
|
||||
"chart-2": "oklch(0.696 0.17 162.48)", // --color-emerald-500 (from zinc)
|
||||
"chart-3": "oklch(0.769 0.188 70.08)", // --color-amber-500 (from zinc)
|
||||
"chart-4": "oklch(0.627 0.265 303.9)", // --color-purple-500 (from zinc)
|
||||
"chart-5": "oklch(0.645 0.246 16.439)", // --color-rose-500 (from zinc)
|
||||
sidebar: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"sidebar-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-primary": "oklch(0.637 0.237 25.331)", // --color-red-500 (approx HSL 0 72.2% 50.6%)
|
||||
"sidebar-primary-foreground": "oklch(0.971 0.013 17.38)", // --color-red-50 (approx HSL 0 85.7% 97.3%)
|
||||
"sidebar-accent": "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"sidebar-accent-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-border": "oklch(1 0 0 / 10%)", // --color-white (from zinc)
|
||||
"sidebar-ring": "oklch(0.637 0.237 25.331)", // --color-red-500 (approx HSL 0 72.2% 50.6%)
|
||||
},
|
||||
},
|
||||
rose: {
|
||||
light: {
|
||||
background: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
foreground: "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
card: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
"card-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
popover: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
"popover-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
primary: "oklch(0.645 0.246 16.439)", // --color-rose-500 (approx HSL 346.8 77.2% 49.8%)
|
||||
"primary-foreground": "oklch(0.969 0.015 12.422)", // --color-rose-50 (approx HSL 355.7 100% 97.3%)
|
||||
secondary: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"secondary-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
muted: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"muted-foreground": "oklch(0.552 0.016 285.938)", // --color-zinc-500 (from zinc)
|
||||
accent: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"accent-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
destructive: "oklch(0.577 0.245 27.325)", // --color-red-600 (from zinc)
|
||||
border: "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
input: "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
ring: "oklch(0.645 0.246 16.439)", // --color-rose-500 (approx HSL 346.8 77.2% 49.8%)
|
||||
"chart-1": "oklch(0.646 0.222 41.116)", // --color-orange-600 (from zinc)
|
||||
"chart-2": "oklch(0.6 0.118 184.704)", // --color-teal-600 (from zinc)
|
||||
"chart-3": "oklch(0.398 0.07 227.392)", // --color-cyan-900 (from zinc)
|
||||
"chart-4": "oklch(0.828 0.189 84.429)", // --color-amber-400 (from zinc)
|
||||
"chart-5": "oklch(0.769 0.188 70.08)", // --color-amber-500 (from zinc)
|
||||
sidebar: "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
"sidebar-primary": "oklch(0.645 0.246 16.439)", // --color-rose-500 (approx HSL 346.8 77.2% 49.8%)
|
||||
"sidebar-primary-foreground": "oklch(0.969 0.015 12.422)", // --color-rose-50 (approx HSL 355.7 100% 97.3%)
|
||||
"sidebar-accent": "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"sidebar-accent-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"sidebar-border": "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
"sidebar-ring": "oklch(0.645 0.246 16.439)", // --color-rose-500 (approx HSL 346.8 77.2% 49.8%)
|
||||
},
|
||||
dark: {
|
||||
background: "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
foreground: "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
card: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"card-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
popover: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"popover-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
primary: "oklch(0.645 0.246 16.439)", // --color-rose-500 (approx HSL 346.8 77.2% 49.8%)
|
||||
"primary-foreground": "oklch(0.969 0.015 12.422)", // --color-rose-50 (approx HSL 355.7 100% 97.3%)
|
||||
secondary: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"secondary-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
muted: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"muted-foreground": "oklch(0.705 0.015 286.067)", // --color-zinc-400 (from zinc)
|
||||
accent: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"accent-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
destructive: "oklch(0.704 0.191 22.216)", // --color-red-400 (from zinc)
|
||||
border: "oklch(1 0 0 / 10%)", // --color-white (from zinc)
|
||||
input: "oklch(1 0 0 / 15%)", // --color-white (from zinc)
|
||||
ring: "oklch(0.645 0.246 16.439)", // --color-rose-500 (approx HSL 346.8 77.2% 49.8%)
|
||||
"chart-1": "oklch(0.488 0.243 264.376)", // --color-blue-700 (from zinc)
|
||||
"chart-2": "oklch(0.696 0.17 162.48)", // --color-emerald-500 (from zinc)
|
||||
"chart-3": "oklch(0.769 0.188 70.08)", // --color-amber-500 (from zinc)
|
||||
"chart-4": "oklch(0.627 0.265 303.9)", // --color-purple-500 (from zinc)
|
||||
"chart-5": "oklch(0.645 0.246 16.439)", // --color-rose-500 (from zinc)
|
||||
sidebar: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"sidebar-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-primary": "oklch(0.645 0.246 16.439)", // --color-rose-500 (approx HSL 346.8 77.2% 49.8%)
|
||||
"sidebar-primary-foreground": "oklch(0.969 0.015 12.422)", // --color-rose-50 (approx HSL 355.7 100% 97.3%)
|
||||
"sidebar-accent": "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"sidebar-accent-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-border": "oklch(1 0 0 / 10%)", // --color-white (from zinc)
|
||||
"sidebar-ring": "oklch(0.645 0.246 16.439)", // --color-rose-500 (approx HSL 346.8 77.2% 49.8%)
|
||||
},
|
||||
},
|
||||
orange: {
|
||||
light: {
|
||||
background: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
foreground: "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
card: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
"card-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
popover: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
"popover-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
primary: "oklch(0.705 0.213 47.604)", // --color-orange-500 (approx HSL 24.6 95% 53.1%)
|
||||
"primary-foreground": "oklch(0.98 0.016 73.684)", // --color-orange-50 (approx HSL 60 9.1% 97.8%)
|
||||
secondary: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"secondary-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
muted: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"muted-foreground": "oklch(0.552 0.016 285.938)", // --color-zinc-500 (from zinc)
|
||||
accent: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"accent-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
destructive: "oklch(0.577 0.245 27.325)", // --color-red-600 (from zinc)
|
||||
border: "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
input: "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
ring: "oklch(0.705 0.213 47.604)", // --color-orange-500 (approx HSL 24.6 95% 53.1%)
|
||||
"chart-1": "oklch(0.646 0.222 41.116)", // --color-orange-600 (from zinc)
|
||||
"chart-2": "oklch(0.6 0.118 184.704)", // --color-teal-600 (from zinc)
|
||||
"chart-3": "oklch(0.398 0.07 227.392)", // --color-cyan-900 (from zinc)
|
||||
"chart-4": "oklch(0.828 0.189 84.429)", // --color-amber-400 (from zinc)
|
||||
"chart-5": "oklch(0.769 0.188 70.08)", // --color-amber-500 (from zinc)
|
||||
sidebar: "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
"sidebar-primary": "oklch(0.705 0.213 47.604)", // --color-orange-500 (approx HSL 24.6 95% 53.1%)
|
||||
"sidebar-primary-foreground": "oklch(0.98 0.016 73.684)", // --color-orange-50 (approx HSL 60 9.1% 97.8%)
|
||||
"sidebar-accent": "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"sidebar-accent-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"sidebar-border": "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
"sidebar-ring": "oklch(0.705 0.213 47.604)", // --color-orange-500 (approx HSL 24.6 95% 53.1%)
|
||||
},
|
||||
dark: {
|
||||
background: "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
foreground: "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
card: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"card-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
popover: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"popover-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
primary: "oklch(0.646 0.222 41.116)", // --color-orange-600 (approx HSL 20.5 90.2% 48.2%)
|
||||
"primary-foreground": "oklch(0.98 0.016 73.684)", // --color-orange-50 (approx HSL 60 9.1% 97.8%)
|
||||
secondary: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"secondary-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
muted: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"muted-foreground": "oklch(0.705 0.015 286.067)", // --color-zinc-400 (from zinc)
|
||||
accent: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"accent-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
destructive: "oklch(0.704 0.191 22.216)", // --color-red-400 (from zinc)
|
||||
border: "oklch(1 0 0 / 10%)", // --color-white (from zinc)
|
||||
input: "oklch(1 0 0 / 15%)", // --color-white (from zinc)
|
||||
ring: "oklch(0.646 0.222 41.116)", // --color-orange-600 (approx HSL 20.5 90.2% 48.2%)
|
||||
"chart-1": "oklch(0.488 0.243 264.376)", // --color-blue-700 (from zinc)
|
||||
"chart-2": "oklch(0.696 0.17 162.48)", // --color-emerald-500 (from zinc)
|
||||
"chart-3": "oklch(0.769 0.188 70.08)", // --color-amber-500 (from zinc)
|
||||
"chart-4": "oklch(0.627 0.265 303.9)", // --color-purple-500 (from zinc)
|
||||
"chart-5": "oklch(0.645 0.246 16.439)", // --color-rose-500 (from zinc)
|
||||
sidebar: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"sidebar-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-primary": "oklch(0.646 0.222 41.116)", // --color-orange-600 (approx HSL 20.5 90.2% 48.2%)
|
||||
"sidebar-primary-foreground": "oklch(0.98 0.016 73.684)", // --color-orange-50 (approx HSL 60 9.1% 97.8%)
|
||||
"sidebar-accent": "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"sidebar-accent-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-border": "oklch(1 0 0 / 10%)", // --color-white (from zinc)
|
||||
"sidebar-ring": "oklch(0.646 0.222 41.116)", // --color-orange-600 (approx HSL 20.5 90.2% 48.2%)
|
||||
},
|
||||
},
|
||||
green: {
|
||||
light: {
|
||||
background: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
foreground: "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
card: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
"card-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
popover: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
"popover-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
primary: "oklch(0.723 0.219 149.579)", // --color-green-500 (approx HSL 142.1 76.2% 36.3%)
|
||||
"primary-foreground": "oklch(0.982 0.018 155.826)", // --color-green-50 (approx HSL 355.7 100% 97.3%)
|
||||
secondary: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"secondary-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
muted: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"muted-foreground": "oklch(0.552 0.016 285.938)", // --color-zinc-500 (from zinc)
|
||||
accent: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"accent-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
destructive: "oklch(0.577 0.245 27.325)", // --color-red-600 (from zinc)
|
||||
border: "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
input: "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
ring: "oklch(0.723 0.219 149.579)", // --color-green-500 (approx HSL 142.1 76.2% 36.3%)
|
||||
"chart-1": "oklch(0.646 0.222 41.116)", // --color-orange-600 (from zinc)
|
||||
"chart-2": "oklch(0.6 0.118 184.704)", // --color-teal-600 (from zinc)
|
||||
"chart-3": "oklch(0.398 0.07 227.392)", // --color-cyan-900 (from zinc)
|
||||
"chart-4": "oklch(0.828 0.189 84.429)", // --color-amber-400 (from zinc)
|
||||
"chart-5": "oklch(0.769 0.188 70.08)", // --color-amber-500 (from zinc)
|
||||
sidebar: "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
"sidebar-primary": "oklch(0.723 0.219 149.579)", // --color-green-500 (approx HSL 142.1 76.2% 36.3%)
|
||||
"sidebar-primary-foreground": "oklch(0.982 0.018 155.826)", // --color-green-50 (approx HSL 355.7 100% 97.3%)
|
||||
"sidebar-accent": "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"sidebar-accent-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"sidebar-border": "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
"sidebar-ring": "oklch(0.723 0.219 149.579)", // --color-green-500 (approx HSL 142.1 76.2% 36.3%)
|
||||
},
|
||||
dark: {
|
||||
background: "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
foreground: "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
card: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"card-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
popover: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"popover-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
primary: "oklch(0.696 0.17 162.48)", // --color-emerald-500 (approx HSL 142.1 70.6% 45.3%)
|
||||
"primary-foreground": "oklch(0.393 0.095 152.535)", // --color-green-900 (approx HSL 144.9 80.4% 10%)
|
||||
secondary: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"secondary-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
muted: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"muted-foreground": "oklch(0.705 0.015 286.067)", // --color-zinc-400 (from zinc)
|
||||
accent: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"accent-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
destructive: "oklch(0.704 0.191 22.216)", // --color-red-400 (from zinc)
|
||||
border: "oklch(1 0 0 / 10%)", // --color-white (from zinc)
|
||||
input: "oklch(1 0 0 / 15%)", // --color-white (from zinc)
|
||||
ring: "oklch(0.527 0.154 150.069)", // --color-green-700 (approx HSL 142.4 71.8% 29.2%)
|
||||
"chart-1": "oklch(0.488 0.243 264.376)", // --color-blue-700 (from zinc)
|
||||
"chart-2": "oklch(0.696 0.17 162.48)", // --color-emerald-500 (from zinc)
|
||||
"chart-3": "oklch(0.769 0.188 70.08)", // --color-amber-500 (from zinc)
|
||||
"chart-4": "oklch(0.627 0.265 303.9)", // --color-purple-500 (from zinc)
|
||||
"chart-5": "oklch(0.645 0.246 16.439)", // --color-rose-500 (from zinc)
|
||||
sidebar: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"sidebar-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-primary": "oklch(0.696 0.17 162.48)", // --color-emerald-500 (approx HSL 142.1 70.6% 45.3%)
|
||||
"sidebar-primary-foreground": "oklch(0.393 0.095 152.535)", // --color-green-900 (approx HSL 144.9 80.4% 10%)
|
||||
"sidebar-accent": "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"sidebar-accent-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-border": "oklch(1 0 0 / 10%)", // --color-white (from zinc)
|
||||
"sidebar-ring": "oklch(0.527 0.154 150.069)", // --color-green-700 (approx HSL 142.4 71.8% 29.2%)
|
||||
},
|
||||
},
|
||||
blue: {
|
||||
light: {
|
||||
background: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
foreground: "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
card: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
"card-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
popover: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
"popover-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
primary: "oklch(0.623 0.214 259.815)", // --color-blue-500 (approx HSL 221.2 83.2% 53.3%)
|
||||
"primary-foreground": "oklch(0.97 0.014 254.604)", // --color-blue-50 (approx HSL 210 40% 98%)
|
||||
secondary: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"secondary-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
muted: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"muted-foreground": "oklch(0.552 0.016 285.938)", // --color-zinc-500 (from zinc)
|
||||
accent: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"accent-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
destructive: "oklch(0.577 0.245 27.325)", // --color-red-600 (from zinc)
|
||||
border: "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
input: "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
ring: "oklch(0.623 0.214 259.815)", // --color-blue-500 (approx HSL 221.2 83.2% 53.3%)
|
||||
"chart-1": "oklch(0.646 0.222 41.116)", // --color-orange-600 (from zinc)
|
||||
"chart-2": "oklch(0.6 0.118 184.704)", // --color-teal-600 (from zinc)
|
||||
"chart-3": "oklch(0.398 0.07 227.392)", // --color-cyan-900 (from zinc)
|
||||
"chart-4": "oklch(0.828 0.189 84.429)", // --color-amber-400 (from zinc)
|
||||
"chart-5": "oklch(0.769 0.188 70.08)", // --color-amber-500 (from zinc)
|
||||
sidebar: "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
"sidebar-primary": "oklch(0.623 0.214 259.815)", // --color-blue-500 (approx HSL 221.2 83.2% 53.3%)
|
||||
"sidebar-primary-foreground": "oklch(0.97 0.014 254.604)", // --color-blue-50 (approx HSL 210 40% 98%)
|
||||
"sidebar-accent": "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"sidebar-accent-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"sidebar-border": "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
"sidebar-ring": "oklch(0.623 0.214 259.815)", // --color-blue-500 (approx HSL 221.2 83.2% 53.3%)
|
||||
},
|
||||
dark: {
|
||||
background: "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
foreground: "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
card: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"card-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
popover: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"popover-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
primary: "oklch(0.546 0.245 262.881)", // --color-blue-600 (approx HSL 217.2 91.2% 59.8%)
|
||||
"primary-foreground": "oklch(0.379 0.146 265.522)", // --color-blue-900 (approx HSL 222.2 47.4% 11.2%)
|
||||
secondary: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"secondary-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
muted: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"muted-foreground": "oklch(0.705 0.015 286.067)", // --color-zinc-400 (from zinc)
|
||||
accent: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"accent-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
destructive: "oklch(0.704 0.191 22.216)", // --color-red-400 (from zinc)
|
||||
border: "oklch(1 0 0 / 10%)", // --color-white (from zinc)
|
||||
input: "oklch(1 0 0 / 15%)", // --color-white (from zinc)
|
||||
ring: "oklch(0.488 0.243 264.376)", // --color-blue-700 (approx HSL 224.3 76.3% 48%)
|
||||
"chart-1": "oklch(0.488 0.243 264.376)", // --color-blue-700 (from zinc)
|
||||
"chart-2": "oklch(0.696 0.17 162.48)", // --color-emerald-500 (from zinc)
|
||||
"chart-3": "oklch(0.769 0.188 70.08)", // --color-amber-500 (from zinc)
|
||||
"chart-4": "oklch(0.627 0.265 303.9)", // --color-purple-500 (from zinc)
|
||||
"chart-5": "oklch(0.645 0.246 16.439)", // --color-rose-500 (from zinc)
|
||||
sidebar: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"sidebar-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-primary": "oklch(0.546 0.245 262.881)", // --color-blue-600 (approx HSL 217.2 91.2% 59.8%)
|
||||
"sidebar-primary-foreground": "oklch(0.379 0.146 265.522)", // --color-blue-900 (approx HSL 222.2 47.4% 11.2%)
|
||||
"sidebar-accent": "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"sidebar-accent-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-border": "oklch(1 0 0 / 10%)", // --color-white (from zinc)
|
||||
"sidebar-ring": "oklch(0.488 0.243 264.376)", // --color-blue-700 (approx HSL 224.3 76.3% 48%)
|
||||
},
|
||||
},
|
||||
yellow: {
|
||||
light: {
|
||||
background: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
foreground: "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
card: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
"card-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
popover: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
"popover-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
primary: "oklch(0.795 0.184 86.047)", // --color-yellow-500 (approx HSL 47.9 95.8% 53.1%)
|
||||
"primary-foreground": "oklch(0.421 0.095 57.708)", // --color-yellow-900 (approx HSL 26 83.3% 14.1%)
|
||||
secondary: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"secondary-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
muted: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"muted-foreground": "oklch(0.552 0.016 285.938)", // --color-zinc-500 (from zinc)
|
||||
accent: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"accent-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
destructive: "oklch(0.577 0.245 27.325)", // --color-red-600 (from zinc)
|
||||
border: "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
input: "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
ring: "oklch(0.795 0.184 86.047)", // --color-yellow-500 (approx HSL 47.9 95.8% 53.1%)
|
||||
"chart-1": "oklch(0.646 0.222 41.116)", // --color-orange-600 (from zinc)
|
||||
"chart-2": "oklch(0.6 0.118 184.704)", // --color-teal-600 (from zinc)
|
||||
"chart-3": "oklch(0.398 0.07 227.392)", // --color-cyan-900 (from zinc)
|
||||
"chart-4": "oklch(0.828 0.189 84.429)", // --color-amber-400 (from zinc)
|
||||
"chart-5": "oklch(0.769 0.188 70.08)", // --color-amber-500 (from zinc)
|
||||
sidebar: "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
"sidebar-primary": "oklch(0.795 0.184 86.047)", // --color-yellow-500 (approx HSL 47.9 95.8% 53.1%)
|
||||
"sidebar-primary-foreground": "oklch(0.421 0.095 57.708)", // --color-yellow-900 (approx HSL 26 83.3% 14.1%)
|
||||
"sidebar-accent": "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"sidebar-accent-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"sidebar-border": "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
"sidebar-ring": "oklch(0.795 0.184 86.047)", // --color-yellow-500 (approx HSL 47.9 95.8% 53.1%)
|
||||
},
|
||||
dark: {
|
||||
background: "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
foreground: "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
card: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"card-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
popover: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"popover-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
primary: "oklch(0.795 0.184 86.047)", // --color-yellow-500 (approx HSL 47.9 95.8% 53.1%)
|
||||
"primary-foreground": "oklch(0.421 0.095 57.708)", // --color-yellow-900 (approx HSL 26 83.3% 14.1%)
|
||||
secondary: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"secondary-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
muted: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"muted-foreground": "oklch(0.705 0.015 286.067)", // --color-zinc-400 (from zinc)
|
||||
accent: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"accent-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
destructive: "oklch(0.704 0.191 22.216)", // --color-red-400 (from zinc)
|
||||
border: "oklch(1 0 0 / 10%)", // --color-white (from zinc)
|
||||
input: "oklch(1 0 0 / 15%)", // --color-white (from zinc)
|
||||
ring: "oklch(0.554 0.135 66.442)", // --color-yellow-700 (approx HSL 35.5 91.7% 32.9%)
|
||||
"chart-1": "oklch(0.488 0.243 264.376)", // --color-blue-700 (from zinc)
|
||||
"chart-2": "oklch(0.696 0.17 162.48)", // --color-emerald-500 (from zinc)
|
||||
"chart-3": "oklch(0.769 0.188 70.08)", // --color-amber-500 (from zinc)
|
||||
"chart-4": "oklch(0.627 0.265 303.9)", // --color-purple-500 (from zinc)
|
||||
"chart-5": "oklch(0.645 0.246 16.439)", // --color-rose-500 (from zinc)
|
||||
sidebar: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"sidebar-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-primary": "oklch(0.795 0.184 86.047)", // --color-yellow-500 (approx HSL 47.9 95.8% 53.1%)
|
||||
"sidebar-primary-foreground": "oklch(0.421 0.095 57.708)", // --color-yellow-900 (approx HSL 26 83.3% 14.1%)
|
||||
"sidebar-accent": "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"sidebar-accent-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-border": "oklch(1 0 0 / 10%)", // --color-white (from zinc)
|
||||
"sidebar-ring": "oklch(0.554 0.135 66.442)", // --color-yellow-700 (approx HSL 35.5 91.7% 32.9%)
|
||||
},
|
||||
},
|
||||
violet: {
|
||||
light: {
|
||||
background: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
foreground: "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
card: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
"card-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
popover: "oklch(1 0 0)", // --color-zinc-50 (from zinc)
|
||||
"popover-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
primary: "oklch(0.606 0.25 292.717)", // --color-violet-500 (approx HSL 262.1 83.3% 57.8%)
|
||||
"primary-foreground": "oklch(0.969 0.016 293.756)", // --color-violet-50 (approx HSL 210 20% 98%)
|
||||
secondary: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"secondary-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
muted: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"muted-foreground": "oklch(0.552 0.016 285.938)", // --color-zinc-500 (from zinc)
|
||||
accent: "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"accent-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
destructive: "oklch(0.577 0.245 27.325)", // --color-red-600 (from zinc)
|
||||
border: "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
input: "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
ring: "oklch(0.606 0.25 292.717)", // --color-violet-500 (approx HSL 262.1 83.3% 57.8%)
|
||||
"chart-1": "oklch(0.646 0.222 41.116)", // --color-orange-600 (from zinc)
|
||||
"chart-2": "oklch(0.6 0.118 184.704)", // --color-teal-600 (from zinc)
|
||||
"chart-3": "oklch(0.398 0.07 227.392)", // --color-cyan-900 (from zinc)
|
||||
"chart-4": "oklch(0.828 0.189 84.429)", // --color-amber-400 (from zinc)
|
||||
"chart-5": "oklch(0.769 0.188 70.08)", // --color-amber-500 (from zinc)
|
||||
sidebar: "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-foreground": "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
"sidebar-primary": "oklch(0.606 0.25 292.717)", // --color-violet-500 (approx HSL 262.1 83.3% 57.8%)
|
||||
"sidebar-primary-foreground": "oklch(0.969 0.016 293.756)", // --color-violet-50 (approx HSL 210 20% 98%)
|
||||
"sidebar-accent": "oklch(0.967 0.001 286.375)", // --color-zinc-100 (from zinc)
|
||||
"sidebar-accent-foreground": "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"sidebar-border": "oklch(0.92 0.004 286.32)", // --color-zinc-200 (from zinc)
|
||||
"sidebar-ring": "oklch(0.606 0.25 292.717)", // --color-violet-500 (approx HSL 262.1 83.3% 57.8%)
|
||||
},
|
||||
dark: {
|
||||
background: "oklch(0.141 0.005 285.823)", // --color-zinc-950 (from zinc)
|
||||
foreground: "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
card: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"card-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
popover: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"popover-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
primary: "oklch(0.541 0.281 293.009)", // --color-violet-600 (approx HSL 263.4 70% 50.4%)
|
||||
"primary-foreground": "oklch(0.969 0.016 293.756)", // --color-violet-50 (approx HSL 210 20% 98%)
|
||||
secondary: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"secondary-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
muted: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"muted-foreground": "oklch(0.705 0.015 286.067)", // --color-zinc-400 (from zinc)
|
||||
accent: "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"accent-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
destructive: "oklch(0.704 0.191 22.216)", // --color-red-400 (from zinc)
|
||||
border: "oklch(1 0 0 / 10%)", // --color-white (from zinc)
|
||||
input: "oklch(1 0 0 / 15%)", // --color-white (from zinc)
|
||||
ring: "oklch(0.541 0.281 293.009)", // --color-violet-600 (approx HSL 263.4 70% 50.4%)
|
||||
"chart-1": "oklch(0.488 0.243 264.376)", // --color-blue-700 (from zinc)
|
||||
"chart-2": "oklch(0.696 0.17 162.48)", // --color-emerald-500 (from zinc)
|
||||
"chart-3": "oklch(0.769 0.188 70.08)", // --color-amber-500 (from zinc)
|
||||
"chart-4": "oklch(0.627 0.265 303.9)", // --color-purple-500 (from zinc)
|
||||
"chart-5": "oklch(0.645 0.246 16.439)", // --color-rose-500 (from zinc)
|
||||
sidebar: "oklch(0.21 0.006 285.885)", // --color-zinc-900 (from zinc)
|
||||
"sidebar-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-primary": "oklch(0.541 0.281 293.009)", // --color-violet-600 (approx HSL 263.4 70% 50.4%)
|
||||
"sidebar-primary-foreground": "oklch(0.969 0.016 293.756)", // --color-violet-50 (approx HSL 210 20% 98%)
|
||||
"sidebar-accent": "oklch(0.274 0.006 286.033)", // --color-zinc-800 (from zinc)
|
||||
"sidebar-accent-foreground": "oklch(0.985 0 0)", // --color-zinc-50 (from zinc)
|
||||
"sidebar-border": "oklch(1 0 0 / 10%)", // --color-white (from zinc)
|
||||
"sidebar-ring": "oklch(0.541 0.281 293.009)", // --color-violet-600 (approx HSL 263.4 70% 50.4%)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,5 +1,81 @@
|
||||
# @shadcn/ui
|
||||
|
||||
## 2.5.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#7220](https://github.com/shadcn-ui/ui/pull/7220) [`d0306774fe0ecc1eae9ef1e918bf7862e866a9e8`](https://github.com/shadcn-ui/ui/commit/d0306774fe0ecc1eae9ef1e918bf7862e866a9e8) Thanks [@shadcn](https://github.com/shadcn)! - resolve imports from anywhere
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#6985](https://github.com/shadcn-ui/ui/pull/6985) [`f1e5cc4666ced2166a859660d769ccee16cde46e`](https://github.com/shadcn-ui/ui/commit/f1e5cc4666ced2166a859660d769ccee16cde46e) Thanks [@nrjdalal](https://github.com/nrjdalal)! - move tw-animate-css to devDependencies
|
||||
|
||||
- [#6899](https://github.com/shadcn-ui/ui/pull/6899) [`6f702f5fbf2b82a388e7da6ea08bcc84c2ec19c6`](https://github.com/shadcn-ui/ui/commit/6f702f5fbf2b82a388e7da6ea08bcc84c2ec19c6) Thanks [@justjavac](https://github.com/justjavac)! - add deno support
|
||||
|
||||
## 2.4.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#7196](https://github.com/shadcn-ui/ui/pull/7196) [`617483fe9c26d607665fcaf79ee26e35d9825d7c`](https://github.com/shadcn-ui/ui/commit/617483fe9c26d607665fcaf79ee26e35d9825d7c) Thanks [@shadcn](https://github.com/shadcn)! - do not throw if empty dir
|
||||
|
||||
## 2.4.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#6507](https://github.com/shadcn-ui/ui/pull/6507) [`5234c46722750f964d69c92ccbef2c4d260c211d`](https://github.com/shadcn-ui/ui/commit/5234c46722750f964d69c92ccbef2c4d260c211d) Thanks [@shadcn](https://github.com/shadcn)! - add support for TanStack Start
|
||||
|
||||
- [#6487](https://github.com/shadcn-ui/ui/pull/6487) [`5ef2bc5f455dfc394116267788c0514b696e13b0`](https://github.com/shadcn-ui/ui/commit/5ef2bc5f455dfc394116267788c0514b696e13b0) Thanks [@shadcn](https://github.com/shadcn)! - add theme vars support
|
||||
|
||||
- [#6478](https://github.com/shadcn-ui/ui/pull/6478) [`8f6a64f176defdb1f9c493598d952fb4e9844cd0`](https://github.com/shadcn-ui/ui/commit/8f6a64f176defdb1f9c493598d952fb4e9844cd0) Thanks [@shadcn](https://github.com/shadcn)! - add tailwind version detection
|
||||
|
||||
- [#6864](https://github.com/shadcn-ui/ui/pull/6864) [`19665adeeddc4ddb34e91fca219753d15bd46480`](https://github.com/shadcn-ui/ui/commit/19665adeeddc4ddb34e91fca219753d15bd46480) Thanks [@shadcn](https://github.com/shadcn)! - add --base-color flag
|
||||
|
||||
- [#6490](https://github.com/shadcn-ui/ui/pull/6490) [`9a14c1d0925d3df2c8f57a3381d212cc3e54f4a6`](https://github.com/shadcn-ui/ui/commit/9a14c1d0925d3df2c8f57a3381d212cc3e54f4a6) Thanks [@shadcn](https://github.com/shadcn)! - add support for tailwind v4
|
||||
|
||||
- [#6707](https://github.com/shadcn-ui/ui/pull/6707) [`3db8a07b3f132d396d7fb2e50da96156efcb4138`](https://github.com/shadcn-ui/ui/commit/3db8a07b3f132d396d7fb2e50da96156efcb4138) Thanks [@shadcn](https://github.com/shadcn)! - default to css vars. add --no-css-variables
|
||||
|
||||
- [#6968](https://github.com/shadcn-ui/ui/pull/6968) [`205bfc637e093717908ebd2c591b215672950558`](https://github.com/shadcn-ui/ui/commit/205bfc637e093717908ebd2c591b215672950558) Thanks [@shadcn](https://github.com/shadcn)! - replace tailwindcss-animate with tw-animate-css
|
||||
|
||||
- [#6574](https://github.com/shadcn-ui/ui/pull/6574) [`1e357cb20d6024b2bc9766fb15f61cb989eb7024`](https://github.com/shadcn-ui/ui/commit/1e357cb20d6024b2bc9766fb15f61cb989eb7024) Thanks [@shadcn](https://github.com/shadcn)! - default for new-york for v4
|
||||
|
||||
- [#6515](https://github.com/shadcn-ui/ui/pull/6515) [`d1eb24e23a973646d78cf101fa1e0a22861ac9fd`](https://github.com/shadcn-ui/ui/commit/d1eb24e23a973646d78cf101fa1e0a22861ac9fd) Thanks [@shadcn](https://github.com/shadcn)! - fix handling of sidebar colors
|
||||
|
||||
- [#6693](https://github.com/shadcn-ui/ui/pull/6693) [`3740373f99e39943514a45f5808ecb5f17faf700`](https://github.com/shadcn-ui/ui/commit/3740373f99e39943514a45f5808ecb5f17faf700) Thanks [@shadcn](https://github.com/shadcn)! - add oklch base color
|
||||
|
||||
- [#6571](https://github.com/shadcn-ui/ui/pull/6571) [`c74a094f14a6e338124709547932dbb20c8d1324`](https://github.com/shadcn-ui/ui/commit/c74a094f14a6e338124709547932dbb20c8d1324) Thanks [@shadcn](https://github.com/shadcn)! - hotswap style for v4
|
||||
|
||||
- [#6576](https://github.com/shadcn-ui/ui/pull/6576) [`9f4d65fc8fe72f632706fafd4036f63fd9317780`](https://github.com/shadcn-ui/ui/commit/9f4d65fc8fe72f632706fafd4036f63fd9317780) Thanks [@shadcn](https://github.com/shadcn)! - add warning for deprecated components
|
||||
|
||||
- [#6811](https://github.com/shadcn-ui/ui/pull/6811) [`bc7df68620f242ce6aa640839c80ddc8afc7e091`](https://github.com/shadcn-ui/ui/commit/bc7df68620f242ce6aa640839c80ddc8afc7e091) Thanks [@shadcn](https://github.com/shadcn)! - add support for route install for react-router and laravel
|
||||
|
||||
- [#7016](https://github.com/shadcn-ui/ui/pull/7016) [`b3b2fe2755e0ec1271c41a2a61b1a6933af42bc6`](https://github.com/shadcn-ui/ui/commit/b3b2fe2755e0ec1271c41a2a61b1a6933af42bc6) Thanks [@shadcn](https://github.com/shadcn)! - add theme prop to registry-item schema
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#6724](https://github.com/shadcn-ui/ui/pull/6724) [`a3fe5074c1375cbd92e1ccdaab38d6808bfec696`](https://github.com/shadcn-ui/ui/commit/a3fe5074c1375cbd92e1ccdaab38d6808bfec696) Thanks [@Kaikaikaifang](https://github.com/Kaikaikaifang)! - support for version detection in monorepo
|
||||
|
||||
- [#6414](https://github.com/shadcn-ui/ui/pull/6414) [`202131cd7bf8829b962ae4027545afbdfe79e688`](https://github.com/shadcn-ui/ui/commit/202131cd7bf8829b962ae4027545afbdfe79e688) Thanks [@palmithor](https://github.com/palmithor)! - upgrade @antfu/ni
|
||||
|
||||
- [#6965](https://github.com/shadcn-ui/ui/pull/6965) [`69fc8e23cc0631aac6b708ba0481509f1125d3d7`](https://github.com/shadcn-ui/ui/commit/69fc8e23cc0631aac6b708ba0481509f1125d3d7) Thanks [@jherr](https://github.com/jherr)! - allow silent mode with npm
|
||||
|
||||
- [#6814](https://github.com/shadcn-ui/ui/pull/6814) [`8539dd6eec948e7a6218c7ca3372d2b1f349d7c0`](https://github.com/shadcn-ui/ui/commit/8539dd6eec948e7a6218c7ca3372d2b1f349d7c0) Thanks [@shadcn](https://github.com/shadcn)! - do not add ring for v3
|
||||
|
||||
- [#6732](https://github.com/shadcn-ui/ui/pull/6732) [`839afa714f61e2c0f83e9417354ea6ba8246c177`](https://github.com/shadcn-ui/ui/commit/839afa714f61e2c0f83e9417354ea6ba8246c177) Thanks [@shadcn](https://github.com/shadcn)! - cache registry calls
|
||||
|
||||
- [#6863](https://github.com/shadcn-ui/ui/pull/6863) [`c16c58d0f9e672edddd554269fdd0eb0d412cb9d`](https://github.com/shadcn-ui/ui/commit/c16c58d0f9e672edddd554269fdd0eb0d412cb9d) Thanks [@shadcn](https://github.com/shadcn)! - add --template flag
|
||||
|
||||
- [#6721](https://github.com/shadcn-ui/ui/pull/6721) [`a5122f9029c91963f493e7348ef7681dad4834e5`](https://github.com/shadcn-ui/ui/commit/a5122f9029c91963f493e7348ef7681dad4834e5) Thanks [@shadcn](https://github.com/shadcn)! - do not overwrite user defined vars
|
||||
|
||||
- [#6530](https://github.com/shadcn-ui/ui/pull/6530) [`d6159023ed0817adf14b4398874b1f5f05a73b02`](https://github.com/shadcn-ui/ui/commit/d6159023ed0817adf14b4398874b1f5f05a73b02) Thanks [@zwarunek](https://github.com/zwarunek)! - fix cn import bug in monorepo
|
||||
|
||||
- [#6617](https://github.com/shadcn-ui/ui/pull/6617) [`bd8533bd265de7765831d398f4db687483a0e53a`](https://github.com/shadcn-ui/ui/commit/bd8533bd265de7765831d398f4db687483a0e53a) Thanks [@shadcn](https://github.com/shadcn)! - filter out deprecated from --all
|
||||
|
||||
- [#6733](https://github.com/shadcn-ui/ui/pull/6733) [`779517a1d46f567c8e3fa8fcdea4c75c65ad4eb4`](https://github.com/shadcn-ui/ui/commit/779517a1d46f567c8e3fa8fcdea4c75c65ad4eb4) Thanks [@shadcn](https://github.com/shadcn)! - check for empty css vars
|
||||
|
||||
- [#6967](https://github.com/shadcn-ui/ui/pull/6967) [`9eae13639c10f0219872b5fd28f523a4c25f40df`](https://github.com/shadcn-ui/ui/commit/9eae13639c10f0219872b5fd28f523a4c25f40df) Thanks [@shadcn](https://github.com/shadcn)! - only show deprecated for new projects
|
||||
|
||||
- [#6590](https://github.com/shadcn-ui/ui/pull/6590) [`16d4d38f564c75d4187977275f04d5999ee9e2f4`](https://github.com/shadcn-ui/ui/commit/16d4d38f564c75d4187977275f04d5999ee9e2f4) Thanks [@prateekkumarweb](https://github.com/prateekkumarweb)! - fix tanstack check
|
||||
|
||||
## 2.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "shadcn",
|
||||
"version": "2.3.0",
|
||||
"version": "2.5.0",
|
||||
"description": "Add components to your apps.",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import path from "path"
|
||||
import { runInit } from "@/src/commands/init"
|
||||
import { preFlightAdd } from "@/src/preflights/preflight-add"
|
||||
import { getRegistryIndex } from "@/src/registry/api"
|
||||
import { getRegistryIndex, getRegistryItem, isUrl } from "@/src/registry/api"
|
||||
import { registryItemTypeSchema } from "@/src/registry/schema"
|
||||
import { addComponents } from "@/src/utils/add-components"
|
||||
import { createProject } from "@/src/utils/create-project"
|
||||
import * as ERRORS from "@/src/utils/errors"
|
||||
@@ -78,23 +79,31 @@ export const add = new Command()
|
||||
...opts,
|
||||
})
|
||||
|
||||
// Confirm if user is installing themes.
|
||||
// For now, we assume a theme is prefixed with "theme-".
|
||||
const isTheme = options.components?.some((component) =>
|
||||
component.includes("theme-")
|
||||
)
|
||||
if (!options.yes && isTheme) {
|
||||
let itemType: z.infer<typeof registryItemTypeSchema> | undefined
|
||||
|
||||
if (components.length > 0 && isUrl(components[0])) {
|
||||
const item = await getRegistryItem(components[0], "")
|
||||
itemType = item?.type
|
||||
}
|
||||
|
||||
if (
|
||||
!options.yes &&
|
||||
(itemType === "registry:style" || itemType === "registry:theme")
|
||||
) {
|
||||
logger.break()
|
||||
const { confirm } = await prompts({
|
||||
type: "confirm",
|
||||
name: "confirm",
|
||||
message: highlighter.warn(
|
||||
"You are about to install a new theme. \nExisting CSS variables will be overwritten. Continue?"
|
||||
`You are about to install a new ${itemType.replace(
|
||||
"registry:",
|
||||
""
|
||||
)}. \nExisting CSS variables and components will be overwritten. Continue?`
|
||||
),
|
||||
})
|
||||
if (!confirm) {
|
||||
logger.break()
|
||||
logger.log("Theme installation cancelled.")
|
||||
logger.log(`Installation cancelled.`)
|
||||
logger.break()
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
getRegistryBaseColors,
|
||||
getRegistryItem,
|
||||
getRegistryStyles,
|
||||
isUrl,
|
||||
} from "@/src/registry/api"
|
||||
import { addComponents } from "@/src/utils/add-components"
|
||||
import { TEMPLATES, createProject } from "@/src/utils/create-project"
|
||||
@@ -127,13 +128,15 @@ export const init = new Command()
|
||||
// We need to check if we're initializing with a new style.
|
||||
// We fetch the payload of the first item.
|
||||
// This is okay since the request is cached and deduped.
|
||||
const item = await getRegistryItem(components[0], "")
|
||||
if (components.length > 0 && isUrl(components[0])) {
|
||||
const item = await getRegistryItem(components[0], "")
|
||||
|
||||
// Skip base color if style.
|
||||
// We set a default and let the style override it.
|
||||
if (item?.type === "registry:style") {
|
||||
options.baseColor = "neutral"
|
||||
options.style = item.extends ?? "index"
|
||||
// Skip base color if style.
|
||||
// We set a default and let the style override it.
|
||||
if (item?.type === "registry:style") {
|
||||
options.baseColor = "neutral"
|
||||
options.style = item.extends ?? "index"
|
||||
}
|
||||
}
|
||||
|
||||
await runInit(options)
|
||||
|
||||
@@ -98,7 +98,7 @@ export async function migrateIcons(config: Config) {
|
||||
}
|
||||
|
||||
if (targetLibrary.package) {
|
||||
await updateDependencies([targetLibrary.package], config, {
|
||||
await updateDependencies([targetLibrary.package], [], config, {
|
||||
silent: false,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -307,6 +307,11 @@ export async function registryResolveItemsTree(
|
||||
cssVars = deepmerge(cssVars, item.cssVars ?? {})
|
||||
})
|
||||
|
||||
let css = {}
|
||||
payload.forEach((item) => {
|
||||
css = deepmerge(css, item.css ?? {})
|
||||
})
|
||||
|
||||
let docs = ""
|
||||
payload.forEach((item) => {
|
||||
if (item.docs) {
|
||||
@@ -324,6 +329,7 @@ export async function registryResolveItemsTree(
|
||||
files: deepmerge.all(payload.map((item) => item.files ?? [])),
|
||||
tailwind,
|
||||
cssVars,
|
||||
css,
|
||||
docs,
|
||||
})
|
||||
} catch (error) {
|
||||
@@ -467,7 +473,7 @@ function getRegistryUrl(path: string) {
|
||||
return `${REGISTRY_URL}/${path}`
|
||||
}
|
||||
|
||||
function isUrl(path: string) {
|
||||
export function isUrl(path: string) {
|
||||
try {
|
||||
new URL(path)
|
||||
return true
|
||||
|
||||
@@ -51,6 +51,19 @@ export const registryItemCssVarsSchema = z.object({
|
||||
dark: z.record(z.string(), z.string()).optional(),
|
||||
})
|
||||
|
||||
export const registryItemCssSchema = z.record(
|
||||
z.string(),
|
||||
z.lazy(() =>
|
||||
z.union([
|
||||
z.string(),
|
||||
z.record(
|
||||
z.string(),
|
||||
z.union([z.string(), z.record(z.string(), z.string())])
|
||||
),
|
||||
])
|
||||
)
|
||||
)
|
||||
|
||||
export const registryItemSchema = z.object({
|
||||
$schema: z.string().optional(),
|
||||
extends: z.string().optional(),
|
||||
@@ -65,6 +78,7 @@ export const registryItemSchema = z.object({
|
||||
files: z.array(registryItemFileSchema).optional(),
|
||||
tailwind: registryItemTailwindSchema.optional(),
|
||||
cssVars: registryItemCssVarsSchema.optional(),
|
||||
css: registryItemCssSchema.optional(),
|
||||
meta: z.record(z.string(), z.any()).optional(),
|
||||
docs: z.string().optional(),
|
||||
categories: z.array(z.string()).optional(),
|
||||
@@ -111,5 +125,6 @@ export const registryResolvedItemsTreeSchema = registryItemSchema.pick({
|
||||
files: true,
|
||||
tailwind: true,
|
||||
cssVars: true,
|
||||
css: true,
|
||||
docs: true,
|
||||
})
|
||||
|
||||
@@ -19,6 +19,7 @@ import { getProjectTailwindVersionFromConfig } from "@/src/utils/get-project-inf
|
||||
import { handleError } from "@/src/utils/handle-error"
|
||||
import { logger } from "@/src/utils/logger"
|
||||
import { spinner } from "@/src/utils/spinner"
|
||||
import { updateCss } from "@/src/utils/updaters/update-css"
|
||||
import { updateCssVars } from "@/src/utils/updaters/update-css-vars"
|
||||
import { updateDependencies } from "@/src/utils/updaters/update-dependencies"
|
||||
import { updateFiles } from "@/src/utils/updaters/update-files"
|
||||
@@ -97,7 +98,12 @@ async function addProjectComponents(
|
||||
initIndex: options.style ? options.style === "index" : false,
|
||||
})
|
||||
|
||||
await updateDependencies(tree.dependencies, config, {
|
||||
// Add CSS updater
|
||||
await updateCss(tree.css, config, {
|
||||
silent: options.silent,
|
||||
})
|
||||
|
||||
await updateDependencies(tree.dependencies, tree.devDependencies, config, {
|
||||
silent: options.silent,
|
||||
})
|
||||
await updateFiles(tree.files, config, {
|
||||
@@ -196,12 +202,27 @@ async function addWorkspaceComponents(
|
||||
)
|
||||
}
|
||||
|
||||
// 3. Update dependencies.
|
||||
await updateDependencies(component.dependencies, targetConfig, {
|
||||
silent: true,
|
||||
})
|
||||
// 3. Update CSS
|
||||
if (component.css) {
|
||||
await updateCss(component.css, targetConfig, {
|
||||
silent: true,
|
||||
})
|
||||
filesUpdated.push(
|
||||
path.relative(workspaceRoot, targetConfig.resolvedPaths.tailwindCss)
|
||||
)
|
||||
}
|
||||
|
||||
// 4. Update files.
|
||||
// 4. Update dependencies.
|
||||
await updateDependencies(
|
||||
component.dependencies,
|
||||
component.devDependencies,
|
||||
targetConfig,
|
||||
{
|
||||
silent: true,
|
||||
}
|
||||
)
|
||||
|
||||
// 5. Update files.
|
||||
const files = await updateFiles(component.files, targetConfig, {
|
||||
overwrite: options.overwrite,
|
||||
silent: true,
|
||||
|
||||
@@ -154,7 +154,7 @@ export async function getTailwindVersion(
|
||||
cwd: string
|
||||
): Promise<ProjectInfo["tailwindVersion"]> {
|
||||
const [packageInfo, config] = await Promise.all([
|
||||
getPackageInfo(cwd),
|
||||
getPackageInfo(cwd, false),
|
||||
getConfig(cwd),
|
||||
])
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { Transformer } from "@/src/utils/transformers"
|
||||
import { SyntaxKind } from "ts-morph"
|
||||
|
||||
import {
|
||||
TailwindVersion,
|
||||
getProjectTailwindVersionFromConfig,
|
||||
} from "../get-project-info"
|
||||
import { splitClassName } from "./transform-css-vars"
|
||||
|
||||
export const transformTwPrefixes: Transformer = async ({
|
||||
@@ -10,6 +14,7 @@ export const transformTwPrefixes: Transformer = async ({
|
||||
if (!config.tailwind?.prefix) {
|
||||
return sourceFile
|
||||
}
|
||||
const tailwindVersion = await getProjectTailwindVersionFromConfig(config)
|
||||
|
||||
// Find the cva function calls.
|
||||
sourceFile
|
||||
@@ -23,7 +28,8 @@ export const transformTwPrefixes: Transformer = async ({
|
||||
defaultClassNames.replaceWithText(
|
||||
`"${applyPrefix(
|
||||
defaultClassNames.getText()?.replace(/"|'/g, ""),
|
||||
config.tailwind.prefix
|
||||
config.tailwind.prefix,
|
||||
tailwindVersion
|
||||
)}"`
|
||||
)
|
||||
}
|
||||
@@ -47,7 +53,8 @@ export const transformTwPrefixes: Transformer = async ({
|
||||
classNames?.replaceWithText(
|
||||
`"${applyPrefix(
|
||||
classNames.getText()?.replace(/"|'/g, ""),
|
||||
config.tailwind.prefix
|
||||
config.tailwind.prefix,
|
||||
tailwindVersion
|
||||
)}"`
|
||||
)
|
||||
}
|
||||
@@ -66,7 +73,8 @@ export const transformTwPrefixes: Transformer = async ({
|
||||
value.replaceWithText(
|
||||
`"${applyPrefix(
|
||||
value.getText()?.replace(/"|'/g, ""),
|
||||
config.tailwind.prefix
|
||||
config.tailwind.prefix,
|
||||
tailwindVersion
|
||||
)}"`
|
||||
)
|
||||
}
|
||||
@@ -92,7 +100,8 @@ export const transformTwPrefixes: Transformer = async ({
|
||||
node.replaceWithText(
|
||||
`"${applyPrefix(
|
||||
node.getText()?.replace(/"|'/g, ""),
|
||||
config.tailwind.prefix
|
||||
config.tailwind.prefix,
|
||||
tailwindVersion
|
||||
)}"`
|
||||
)
|
||||
})
|
||||
@@ -102,7 +111,8 @@ export const transformTwPrefixes: Transformer = async ({
|
||||
node.replaceWithText(
|
||||
`"${applyPrefix(
|
||||
node.getText()?.replace(/"|'/g, ""),
|
||||
config.tailwind.prefix
|
||||
config.tailwind.prefix,
|
||||
tailwindVersion
|
||||
)}"`
|
||||
)
|
||||
}
|
||||
@@ -131,7 +141,8 @@ export const transformTwPrefixes: Transformer = async ({
|
||||
node.replaceWithText(
|
||||
`"${applyPrefix(
|
||||
node.getText()?.replace(/"|'/g, ""),
|
||||
config.tailwind.prefix
|
||||
config.tailwind.prefix,
|
||||
tailwindVersion
|
||||
)}"`
|
||||
)
|
||||
})
|
||||
@@ -141,7 +152,8 @@ export const transformTwPrefixes: Transformer = async ({
|
||||
arg.replaceWithText(
|
||||
`"${applyPrefix(
|
||||
arg.getText()?.replace(/"|'/g, ""),
|
||||
config.tailwind.prefix
|
||||
config.tailwind.prefix,
|
||||
tailwindVersion
|
||||
)}"`
|
||||
)
|
||||
}
|
||||
@@ -156,7 +168,8 @@ export const transformTwPrefixes: Transformer = async ({
|
||||
classNames.replaceWithText(
|
||||
`"${applyPrefix(
|
||||
classNames.getText()?.replace(/"|'/g, ""),
|
||||
config.tailwind.prefix
|
||||
config.tailwind.prefix,
|
||||
tailwindVersion
|
||||
)}"`
|
||||
)
|
||||
}
|
||||
@@ -170,30 +183,49 @@ export const transformTwPrefixes: Transformer = async ({
|
||||
return sourceFile
|
||||
}
|
||||
|
||||
export function applyPrefix(input: string, prefix: string = "") {
|
||||
const classNames = input.split(" ")
|
||||
const prefixed: string[] = []
|
||||
for (let className of classNames) {
|
||||
const [variant, value, modifier] = splitClassName(className)
|
||||
if (variant) {
|
||||
modifier
|
||||
? prefixed.push(`${variant}:${prefix}${value}/${modifier}`)
|
||||
: prefixed.push(`${variant}:${prefix}${value}`)
|
||||
} else {
|
||||
modifier
|
||||
? prefixed.push(`${prefix}${value}/${modifier}`)
|
||||
: prefixed.push(`${prefix}${value}`)
|
||||
}
|
||||
export function applyPrefix(
|
||||
input: string,
|
||||
prefix: string = "",
|
||||
tailwindVersion: TailwindVersion
|
||||
) {
|
||||
if (tailwindVersion === "v3") {
|
||||
return input
|
||||
.split(" ")
|
||||
.map((className) => {
|
||||
const [variant, value, modifier] = splitClassName(className)
|
||||
if (variant) {
|
||||
return modifier
|
||||
? `${variant}:${prefix}${value}/${modifier}`
|
||||
: `${variant}:${prefix}${value}`
|
||||
} else {
|
||||
return modifier
|
||||
? `${prefix}${value}/${modifier}`
|
||||
: `${prefix}${value}`
|
||||
}
|
||||
})
|
||||
.join(" ")
|
||||
}
|
||||
return prefixed.join(" ")
|
||||
|
||||
return input
|
||||
.split(" ")
|
||||
.map((className) =>
|
||||
className.indexOf(`${prefix}:`) === 0
|
||||
? className
|
||||
: `${prefix}:${className.trim()}`
|
||||
)
|
||||
.join(" ")
|
||||
}
|
||||
|
||||
export function applyPrefixesCss(css: string, prefix: string) {
|
||||
export function applyPrefixesCss(
|
||||
css: string,
|
||||
prefix: string,
|
||||
tailwindVersion: TailwindVersion
|
||||
) {
|
||||
const lines = css.split("\n")
|
||||
for (let line of lines) {
|
||||
if (line.includes("@apply")) {
|
||||
const originalTWCls = line.replace("@apply", "").trim()
|
||||
const prefixedTwCls = applyPrefix(originalTWCls, prefix)
|
||||
const prefixedTwCls = applyPrefix(originalTWCls, prefix, tailwindVersion)
|
||||
css = css.replace(originalTWCls, prefixedTwCls)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ export async function updateCssVars(
|
||||
cssFilepath
|
||||
)
|
||||
const cssVarsSpinner = spinner(
|
||||
`Updating ${highlighter.info(cssFilepathRelative)}`,
|
||||
`Updating CSS variables in ${highlighter.info(cssFilepathRelative)}`,
|
||||
{
|
||||
silent: options.silent,
|
||||
}
|
||||
|
||||
324
packages/shadcn/src/utils/updaters/update-css.ts
Normal file
324
packages/shadcn/src/utils/updaters/update-css.ts
Normal file
@@ -0,0 +1,324 @@
|
||||
import { promises as fs } from "fs"
|
||||
import path from "path"
|
||||
import { registryItemCssSchema } from "@/src/registry/schema"
|
||||
import { Config } from "@/src/utils/get-config"
|
||||
import { highlighter } from "@/src/utils/highlighter"
|
||||
import { spinner } from "@/src/utils/spinner"
|
||||
import postcss from "postcss"
|
||||
import AtRule from "postcss/lib/at-rule"
|
||||
import Declaration from "postcss/lib/declaration"
|
||||
import Root from "postcss/lib/root"
|
||||
import Rule from "postcss/lib/rule"
|
||||
import { z } from "zod"
|
||||
|
||||
export async function updateCss(
|
||||
css: z.infer<typeof registryItemCssSchema> | undefined,
|
||||
config: Config,
|
||||
options: {
|
||||
silent?: boolean
|
||||
}
|
||||
) {
|
||||
if (
|
||||
!config.resolvedPaths.tailwindCss ||
|
||||
!css ||
|
||||
Object.keys(css).length === 0
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
options = {
|
||||
silent: false,
|
||||
...options,
|
||||
}
|
||||
|
||||
const cssFilepath = config.resolvedPaths.tailwindCss
|
||||
const cssFilepathRelative = path.relative(
|
||||
config.resolvedPaths.cwd,
|
||||
cssFilepath
|
||||
)
|
||||
const cssSpinner = spinner(
|
||||
`Updating ${highlighter.info(cssFilepathRelative)}`,
|
||||
{
|
||||
silent: options.silent,
|
||||
}
|
||||
).start()
|
||||
|
||||
const raw = await fs.readFile(cssFilepath, "utf8")
|
||||
let output = await transformCss(raw, css)
|
||||
await fs.writeFile(cssFilepath, output, "utf8")
|
||||
cssSpinner.succeed()
|
||||
}
|
||||
|
||||
export async function transformCss(
|
||||
input: string,
|
||||
css: z.infer<typeof registryItemCssSchema>
|
||||
) {
|
||||
const plugins = [updateCssPlugin(css)]
|
||||
|
||||
const result = await postcss(plugins).process(input, {
|
||||
from: undefined,
|
||||
})
|
||||
|
||||
let output = result.css
|
||||
output = output.replace(/\/\* ---break--- \*\//g, "")
|
||||
output = output.replace(/(\n\s*\n)+/g, "\n\n")
|
||||
output = output.trimEnd()
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
function updateCssPlugin(css: z.infer<typeof registryItemCssSchema>) {
|
||||
return {
|
||||
postcssPlugin: "update-css",
|
||||
Once(root: Root) {
|
||||
for (const [selector, properties] of Object.entries(css)) {
|
||||
if (selector.startsWith("@")) {
|
||||
// Handle at-rules (@layer, @utility, etc.)
|
||||
const atRuleMatch = selector.match(/@([a-zA-Z-]+)\s*(.*)/)
|
||||
if (!atRuleMatch) continue
|
||||
|
||||
const [, name, params] = atRuleMatch
|
||||
|
||||
// Special handling for keyframes - place them under @theme inline
|
||||
if (name === "keyframes") {
|
||||
let themeInline = root.nodes?.find(
|
||||
(node): node is AtRule =>
|
||||
node.type === "atrule" &&
|
||||
node.name === "theme" &&
|
||||
node.params === "inline"
|
||||
) as AtRule | undefined
|
||||
|
||||
if (!themeInline) {
|
||||
themeInline = postcss.atRule({
|
||||
name: "theme",
|
||||
params: "inline",
|
||||
raws: { semicolon: true, between: " ", before: "\n" },
|
||||
})
|
||||
root.append(themeInline)
|
||||
root.insertBefore(
|
||||
themeInline,
|
||||
postcss.comment({ text: "---break---" })
|
||||
)
|
||||
}
|
||||
|
||||
const keyframesRule = postcss.atRule({
|
||||
name: "keyframes",
|
||||
params,
|
||||
raws: { semicolon: true, between: " ", before: "\n " },
|
||||
})
|
||||
|
||||
themeInline.append(keyframesRule)
|
||||
|
||||
if (typeof properties === "object") {
|
||||
for (const [step, stepProps] of Object.entries(properties)) {
|
||||
processRule(keyframesRule, step, stepProps)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Special handling for utility classes to preserve property values
|
||||
else if (name === "utility") {
|
||||
const utilityAtRule = root.nodes?.find(
|
||||
(node): node is AtRule =>
|
||||
node.type === "atrule" &&
|
||||
node.name === name &&
|
||||
node.params === params
|
||||
) as AtRule | undefined
|
||||
|
||||
if (!utilityAtRule) {
|
||||
const atRule = postcss.atRule({
|
||||
name,
|
||||
params,
|
||||
raws: { semicolon: true, between: " ", before: "\n" },
|
||||
})
|
||||
|
||||
root.append(atRule)
|
||||
root.insertBefore(
|
||||
atRule,
|
||||
postcss.comment({ text: "---break---" })
|
||||
)
|
||||
|
||||
// Add declarations with their values preserved
|
||||
if (typeof properties === "object") {
|
||||
for (const [prop, value] of Object.entries(properties)) {
|
||||
if (typeof value === "string") {
|
||||
const decl = postcss.decl({
|
||||
prop,
|
||||
value: value,
|
||||
raws: { semicolon: true, before: "\n " },
|
||||
})
|
||||
atRule.append(decl)
|
||||
} else if (typeof value === "object") {
|
||||
processRule(atRule, prop, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Update existing utility class
|
||||
if (typeof properties === "object") {
|
||||
for (const [prop, value] of Object.entries(properties)) {
|
||||
if (typeof value === "string") {
|
||||
const existingDecl = utilityAtRule.nodes?.find(
|
||||
(node): node is Declaration =>
|
||||
node.type === "decl" && node.prop === prop
|
||||
)
|
||||
|
||||
const decl = postcss.decl({
|
||||
prop,
|
||||
value: value,
|
||||
raws: { semicolon: true, before: "\n " },
|
||||
})
|
||||
|
||||
existingDecl
|
||||
? existingDecl.replaceWith(decl)
|
||||
: utilityAtRule.append(decl)
|
||||
} else if (typeof value === "object") {
|
||||
processRule(utilityAtRule, prop, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Handle other at-rules normally
|
||||
processAtRule(root, name, params, properties)
|
||||
}
|
||||
} else {
|
||||
// Handle regular CSS rules
|
||||
processRule(root, selector, properties)
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function processAtRule(
|
||||
root: Root | AtRule,
|
||||
name: string,
|
||||
params: string,
|
||||
properties: any
|
||||
) {
|
||||
// Find or create the at-rule
|
||||
let atRule = root.nodes?.find(
|
||||
(node): node is AtRule =>
|
||||
node.type === "atrule" && node.name === name && node.params === params
|
||||
) as AtRule | undefined
|
||||
|
||||
if (!atRule) {
|
||||
atRule = postcss.atRule({
|
||||
name,
|
||||
params,
|
||||
raws: { semicolon: true, between: " ", before: "\n" },
|
||||
})
|
||||
root.append(atRule)
|
||||
root.insertBefore(atRule, postcss.comment({ text: "---break---" }))
|
||||
}
|
||||
|
||||
// Process children of this at-rule
|
||||
if (typeof properties === "object") {
|
||||
for (const [childSelector, childProps] of Object.entries(properties)) {
|
||||
if (childSelector.startsWith("@")) {
|
||||
// Nested at-rule
|
||||
const nestedMatch = childSelector.match(/@([a-zA-Z-]+)\s*(.*)/)
|
||||
if (nestedMatch) {
|
||||
const [, nestedName, nestedParams] = nestedMatch
|
||||
processAtRule(atRule, nestedName, nestedParams, childProps)
|
||||
}
|
||||
} else {
|
||||
// CSS rule within at-rule
|
||||
processRule(atRule, childSelector, childProps)
|
||||
}
|
||||
}
|
||||
} else if (typeof properties === "string") {
|
||||
// Direct string content for the at-rule
|
||||
try {
|
||||
// Parse the CSS string with PostCSS
|
||||
const parsed = postcss.parse(`.temp{${properties}}`)
|
||||
const tempRule = parsed.first as Rule
|
||||
|
||||
if (tempRule && tempRule.nodes) {
|
||||
// Create a rule for the at-rule if needed
|
||||
const rule = postcss.rule({
|
||||
selector: "temp",
|
||||
raws: { semicolon: true, between: " ", before: "\n " },
|
||||
})
|
||||
|
||||
// Copy all declarations from the temp rule to our actual rule
|
||||
tempRule.nodes.forEach((node) => {
|
||||
if (node.type === "decl") {
|
||||
const clone = node.clone()
|
||||
clone.raws.before = "\n "
|
||||
rule.append(clone)
|
||||
}
|
||||
})
|
||||
|
||||
// Only add the rule if it has declarations
|
||||
if (rule.nodes?.length) {
|
||||
atRule.append(rule)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error parsing at-rule content:", properties, error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processRule(parent: Root | AtRule, selector: string, properties: any) {
|
||||
let rule = parent.nodes?.find(
|
||||
(node): node is Rule => node.type === "rule" && node.selector === selector
|
||||
) as Rule | undefined
|
||||
|
||||
if (!rule) {
|
||||
rule = postcss.rule({
|
||||
selector,
|
||||
raws: { semicolon: true, between: " ", before: "\n " },
|
||||
})
|
||||
parent.append(rule)
|
||||
}
|
||||
|
||||
if (typeof properties === "object") {
|
||||
for (const [prop, value] of Object.entries(properties)) {
|
||||
if (typeof value === "string") {
|
||||
const decl = postcss.decl({
|
||||
prop,
|
||||
value: value,
|
||||
raws: { semicolon: true, before: "\n " },
|
||||
})
|
||||
|
||||
// Replace existing property or add new one
|
||||
const existingDecl = rule.nodes?.find(
|
||||
(node): node is Declaration =>
|
||||
node.type === "decl" && node.prop === prop
|
||||
)
|
||||
|
||||
existingDecl ? existingDecl.replaceWith(decl) : rule.append(decl)
|
||||
} else if (typeof value === "object") {
|
||||
// Nested selector (including & selectors)
|
||||
const nestedSelector = prop.startsWith("&")
|
||||
? selector.replace(/^([^:]+)/, `$1${prop.substring(1)}`)
|
||||
: prop // Use the original selector for other nested elements
|
||||
processRule(parent, nestedSelector, value)
|
||||
}
|
||||
}
|
||||
} else if (typeof properties === "string") {
|
||||
// Direct string content for the rule
|
||||
try {
|
||||
// Parse the CSS string with PostCSS
|
||||
const parsed = postcss.parse(`.temp{${properties}}`)
|
||||
const tempRule = parsed.first as Rule
|
||||
|
||||
if (tempRule && tempRule.nodes) {
|
||||
// Copy all declarations from the temp rule to our actual rule
|
||||
tempRule.nodes.forEach((node) => {
|
||||
if (node.type === "decl") {
|
||||
const clone = node.clone()
|
||||
clone.raws.before = "\n "
|
||||
rule?.append(clone)
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error parsing rule content:", selector, properties, error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,13 +9,16 @@ import prompts from "prompts"
|
||||
|
||||
export async function updateDependencies(
|
||||
dependencies: RegistryItem["dependencies"],
|
||||
devDependencies: RegistryItem["devDependencies"],
|
||||
config: Config,
|
||||
options: {
|
||||
silent?: boolean
|
||||
}
|
||||
) {
|
||||
dependencies = Array.from(new Set(dependencies))
|
||||
if (!dependencies?.length) {
|
||||
devDependencies = Array.from(new Set(devDependencies))
|
||||
|
||||
if (!dependencies?.length && !devDependencies?.length) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -59,23 +62,44 @@ export async function updateDependencies(
|
||||
|
||||
dependenciesSpinner?.start()
|
||||
|
||||
await execa(
|
||||
packageManager,
|
||||
[
|
||||
packageManager === "npm" ? "install" : "add",
|
||||
...(packageManager === "npm" && flag ? [`--${flag}`] : []),
|
||||
...dependencies,
|
||||
],
|
||||
{
|
||||
cwd: config.resolvedPaths.cwd,
|
||||
}
|
||||
)
|
||||
if (dependencies?.length) {
|
||||
await execa(
|
||||
packageManager,
|
||||
[
|
||||
packageManager === "npm" ? "install" : "add",
|
||||
...(packageManager === "npm" && flag ? [`--${flag}`] : []),
|
||||
...(packageManager === "deno"
|
||||
? dependencies.map((dep) => `npm:${dep}`)
|
||||
: dependencies),
|
||||
],
|
||||
{
|
||||
cwd: config.resolvedPaths.cwd,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (devDependencies?.length) {
|
||||
await execa(
|
||||
packageManager,
|
||||
[
|
||||
packageManager === "npm" ? "install" : "add",
|
||||
...(packageManager === "npm" && flag ? [`--${flag}`] : []),
|
||||
"-D",
|
||||
...(packageManager === "deno"
|
||||
? devDependencies.map((dep) => `npm:${dep}`)
|
||||
: devDependencies),
|
||||
],
|
||||
{
|
||||
cwd: config.resolvedPaths.cwd,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
dependenciesSpinner?.succeed()
|
||||
}
|
||||
|
||||
function isUsingReact19(config: Config) {
|
||||
const packageInfo = getPackageInfo(config.resolvedPaths.cwd)
|
||||
const packageInfo = getPackageInfo(config.resolvedPaths.cwd, false)
|
||||
|
||||
if (!packageInfo?.dependencies?.react) {
|
||||
return false
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { existsSync, promises as fs } from "fs"
|
||||
import { tmpdir } from "os"
|
||||
import path, { basename } from "path"
|
||||
import { getRegistryBaseColor } from "@/src/registry/api"
|
||||
import { RegistryItem, registryItemFileSchema } from "@/src/registry/schema"
|
||||
@@ -6,6 +7,7 @@ import { Config } from "@/src/utils/get-config"
|
||||
import { ProjectInfo, getProjectInfo } from "@/src/utils/get-project-info"
|
||||
import { highlighter } from "@/src/utils/highlighter"
|
||||
import { logger } from "@/src/utils/logger"
|
||||
import { resolveImport } from "@/src/utils/resolve-import"
|
||||
import { spinner } from "@/src/utils/spinner"
|
||||
import { transform } from "@/src/utils/transformers"
|
||||
import { transformCssVars } from "@/src/utils/transformers/transform-css-vars"
|
||||
@@ -14,6 +16,8 @@ import { transformImport } from "@/src/utils/transformers/transform-import"
|
||||
import { transformRsc } from "@/src/utils/transformers/transform-rsc"
|
||||
import { transformTwPrefixes } from "@/src/utils/transformers/transform-tw-prefix"
|
||||
import prompts from "prompts"
|
||||
import { Project, ScriptKind } from "ts-morph"
|
||||
import { loadConfig } from "tsconfig-paths"
|
||||
import { z } from "zod"
|
||||
|
||||
export async function updateFiles(
|
||||
@@ -50,9 +54,9 @@ export async function updateFiles(
|
||||
getRegistryBaseColor(config.tailwind.baseColor),
|
||||
])
|
||||
|
||||
const filesCreated = []
|
||||
const filesUpdated = []
|
||||
const filesSkipped = []
|
||||
let filesCreated: string[] = []
|
||||
let filesUpdated: string[] = []
|
||||
let filesSkipped: string[] = []
|
||||
|
||||
for (const file of files) {
|
||||
if (!file.content) {
|
||||
@@ -153,11 +157,25 @@ export async function updateFiles(
|
||||
: filesCreated.push(path.relative(config.resolvedPaths.cwd, filePath))
|
||||
}
|
||||
|
||||
const allFiles = [...filesCreated, ...filesUpdated, ...filesSkipped]
|
||||
const updatedFiles = await resolveImports(allFiles, config)
|
||||
|
||||
// Let's update filesUpdated with the updated files.
|
||||
filesUpdated.push(...updatedFiles)
|
||||
|
||||
// If a file is in filesCreated and filesUpdated, we should remove it from filesUpdated.
|
||||
filesUpdated = filesUpdated.filter((file) => !filesCreated.includes(file))
|
||||
|
||||
const hasUpdatedFiles = filesCreated.length || filesUpdated.length
|
||||
if (!hasUpdatedFiles && !filesSkipped.length) {
|
||||
filesCreatedSpinner?.info("No files updated.")
|
||||
}
|
||||
|
||||
// Remove duplicates.
|
||||
filesCreated = Array.from(new Set(filesCreated))
|
||||
filesUpdated = Array.from(new Set(filesUpdated))
|
||||
filesSkipped = Array.from(new Set(filesSkipped))
|
||||
|
||||
if (filesCreated.length) {
|
||||
filesCreatedSpinner?.succeed(
|
||||
`Created ${filesCreated.length} ${
|
||||
@@ -371,3 +389,227 @@ export function resolvePageTarget(
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
async function resolveImports(filePaths: string[], config: Config) {
|
||||
const project = new Project({
|
||||
compilerOptions: {},
|
||||
})
|
||||
const projectInfo = await getProjectInfo(config.resolvedPaths.cwd)
|
||||
const tsConfig = await loadConfig(config.resolvedPaths.cwd)
|
||||
const updatedFiles = []
|
||||
|
||||
if (!projectInfo || tsConfig.resultType === "failed") {
|
||||
return []
|
||||
}
|
||||
|
||||
for (const filepath of filePaths) {
|
||||
const resolvedPath = path.resolve(config.resolvedPaths.cwd, filepath)
|
||||
|
||||
// Check if the file exists.
|
||||
if (!existsSync(resolvedPath)) {
|
||||
continue
|
||||
}
|
||||
|
||||
const content = await fs.readFile(resolvedPath, "utf-8")
|
||||
|
||||
const dir = await fs.mkdtemp(path.join(tmpdir(), "shadcn-"))
|
||||
const sourceFile = project.createSourceFile(
|
||||
path.join(dir, basename(resolvedPath)),
|
||||
content,
|
||||
{
|
||||
scriptKind: ScriptKind.TSX,
|
||||
}
|
||||
)
|
||||
|
||||
const importDeclarations = sourceFile.getImportDeclarations()
|
||||
for (const importDeclaration of importDeclarations) {
|
||||
const moduleSpecifier = importDeclaration.getModuleSpecifierValue()
|
||||
|
||||
// Filter out non-local imports.
|
||||
if (
|
||||
projectInfo?.aliasPrefix &&
|
||||
!moduleSpecifier.startsWith(`${projectInfo.aliasPrefix}/`)
|
||||
) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Find the probable import file path.
|
||||
// This is where we expect to find the file on disk.
|
||||
const probableImportFilePath = await resolveImport(
|
||||
moduleSpecifier,
|
||||
tsConfig
|
||||
)
|
||||
|
||||
if (!probableImportFilePath) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Find the actual import file path.
|
||||
// This is the path where the file has been installed.
|
||||
const resolvedImportFilePath = resolveModuleByProbablePath(
|
||||
probableImportFilePath,
|
||||
filePaths,
|
||||
config
|
||||
)
|
||||
|
||||
if (!resolvedImportFilePath) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Convert the resolved import file path to an aliased import.
|
||||
const newImport = toAliasedImport(
|
||||
resolvedImportFilePath,
|
||||
config,
|
||||
projectInfo
|
||||
)
|
||||
|
||||
if (!newImport || newImport === moduleSpecifier) {
|
||||
continue
|
||||
}
|
||||
|
||||
importDeclaration.setModuleSpecifier(newImport)
|
||||
|
||||
// Write the updated content to the file.
|
||||
await fs.writeFile(resolvedPath, sourceFile.getFullText(), "utf-8")
|
||||
|
||||
// Track the updated file.
|
||||
updatedFiles.push(filepath)
|
||||
}
|
||||
}
|
||||
|
||||
return updatedFiles
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an absolute "probable" import path (no ext),
|
||||
* plus an array of absolute file paths you already know about,
|
||||
* return 0–N matches (best match first), and also check disk for any missing ones.
|
||||
*/
|
||||
export function resolveModuleByProbablePath(
|
||||
probableImportFilePath: string,
|
||||
files: string[],
|
||||
config: Config,
|
||||
extensions: string[] = [".tsx", ".ts", ".js", ".jsx", ".css"]
|
||||
) {
|
||||
const cwd = path.normalize(config.resolvedPaths.cwd)
|
||||
|
||||
// 1) Build a set of POSIX-normalized, project-relative files
|
||||
const relativeFiles = files.map((f) => f.split(path.sep).join(path.posix.sep))
|
||||
const fileSet = new Set(relativeFiles)
|
||||
|
||||
// 2) Strip any existing extension off the absolute base path
|
||||
const extInPath = path.extname(probableImportFilePath)
|
||||
const hasExt = extInPath !== ""
|
||||
const absBase = hasExt
|
||||
? probableImportFilePath.slice(0, -extInPath.length)
|
||||
: probableImportFilePath
|
||||
|
||||
// 3) Compute the project-relative "base" directory for strong matching
|
||||
const relBaseRaw = path.relative(cwd, absBase)
|
||||
const relBase = relBaseRaw.split(path.sep).join(path.posix.sep)
|
||||
|
||||
// 4) Decide which extensions to try
|
||||
const tryExts = hasExt ? [extInPath] : extensions
|
||||
|
||||
// 5) Collect candidates
|
||||
const candidates = new Set<string>()
|
||||
|
||||
// 5a) Fast‑path: [base + ext] and [base/index + ext]
|
||||
for (const e of tryExts) {
|
||||
const absCand = absBase + e
|
||||
const relCand = path.posix.normalize(path.relative(cwd, absCand))
|
||||
if (fileSet.has(relCand) || existsSync(absCand)) {
|
||||
candidates.add(relCand)
|
||||
}
|
||||
|
||||
const absIdx = path.join(absBase, `index${e}`)
|
||||
const relIdx = path.posix.normalize(path.relative(cwd, absIdx))
|
||||
if (fileSet.has(relIdx) || existsSync(absIdx)) {
|
||||
candidates.add(relIdx)
|
||||
}
|
||||
}
|
||||
|
||||
// 5b) Fallback: scan known files by basename
|
||||
const name = path.basename(absBase)
|
||||
for (const f of relativeFiles) {
|
||||
if (tryExts.some((e) => f.endsWith(`/${name}${e}`))) {
|
||||
candidates.add(f)
|
||||
}
|
||||
}
|
||||
|
||||
// 6) If no matches, bail
|
||||
if (candidates.size === 0) return null
|
||||
|
||||
// 7) Sort by (1) extension priority, then (2) "strong" base match
|
||||
const sorted = Array.from(candidates).sort((a, b) => {
|
||||
// a) extension order
|
||||
const aExt = path.posix.extname(a)
|
||||
const bExt = path.posix.extname(b)
|
||||
const ord = tryExts.indexOf(aExt) - tryExts.indexOf(bExt)
|
||||
if (ord !== 0) return ord
|
||||
// b) strong match if path starts with relBase
|
||||
const aStrong = relBase && a.startsWith(relBase) ? -1 : 1
|
||||
const bStrong = relBase && b.startsWith(relBase) ? -1 : 1
|
||||
return aStrong - bStrong
|
||||
})
|
||||
|
||||
// 8) Return the first (best) candidate
|
||||
return sorted[0]
|
||||
}
|
||||
|
||||
export function toAliasedImport(
|
||||
filePath: string,
|
||||
config: Config,
|
||||
projectInfo: ProjectInfo
|
||||
): string | null {
|
||||
const abs = path.normalize(path.join(config.resolvedPaths.cwd, filePath))
|
||||
|
||||
// 1️⃣ Find the longest matching alias root in resolvedPaths
|
||||
// e.g. key="ui", root="/…/components/ui" beats key="components"
|
||||
const matches = Object.entries(config.resolvedPaths)
|
||||
.filter(
|
||||
([, root]) => root && abs.startsWith(path.normalize(root + path.sep))
|
||||
)
|
||||
.sort((a, b) => b[1].length - a[1].length)
|
||||
|
||||
if (matches.length === 0) {
|
||||
return null
|
||||
}
|
||||
const [aliasKey, rootDir] = matches[0]
|
||||
|
||||
// 2️⃣ Compute the path UNDER that root
|
||||
let rel = path.relative(rootDir, abs)
|
||||
// force POSIX-style separators
|
||||
rel = rel.split(path.sep).join("/") // e.g. "button/index.tsx"
|
||||
|
||||
// 3️⃣ Strip code-file extensions, keep others (css, json, etc.)
|
||||
const ext = path.posix.extname(rel)
|
||||
const codeExts = [".ts", ".tsx", ".js", ".jsx"]
|
||||
const keepExt = codeExts.includes(ext) ? "" : ext
|
||||
let noExt = rel.slice(0, rel.length - ext.length)
|
||||
|
||||
// 4️⃣ Collapse "/index" to its directory
|
||||
if (noExt.endsWith("/index")) {
|
||||
noExt = noExt.slice(0, -"/index".length)
|
||||
}
|
||||
|
||||
// 5️⃣ Build the aliased path
|
||||
// config.aliases[aliasKey] is e.g. "@/components/ui"
|
||||
const aliasBase =
|
||||
aliasKey === "cwd"
|
||||
? projectInfo.aliasPrefix
|
||||
: config.aliases[aliasKey as keyof typeof config.aliases]
|
||||
if (!aliasBase) {
|
||||
return null
|
||||
}
|
||||
// if noExt is empty (i.e. file was exactly at the root), we import the root
|
||||
let suffix = noExt === "" ? "" : `/${noExt}`
|
||||
|
||||
// Rremove /src from suffix.
|
||||
// Alias will handle this.
|
||||
suffix = suffix.replace("/src", "")
|
||||
|
||||
// 6️⃣ Prepend the prefix from projectInfo (e.g. "@") if needed
|
||||
// but usually config.aliases already include it.
|
||||
return `${aliasBase}${suffix}${keepExt}`
|
||||
}
|
||||
|
||||
1
packages/shadcn/test/fixtures/project-deno/deno.json
vendored
Normal file
1
packages/shadcn/test/fixtures/project-deno/deno.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
0
packages/shadcn/test/fixtures/project-deno/deno.lock
generated
vendored
Normal file
0
packages/shadcn/test/fixtures/project-deno/deno.lock
generated
vendored
Normal file
13
packages/shadcn/test/fixtures/project-npm-react19/package-lock.json
generated
vendored
Normal file
13
packages/shadcn/test/fixtures/project-npm-react19/package-lock.json
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "test-cli-npm-project",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "npm-project",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
}
|
||||
10
packages/shadcn/test/fixtures/project-npm-react19/package.json
vendored
Normal file
10
packages/shadcn/test/fixtures/project-npm-react19/package.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "test-cli-project-npm",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"author": "shadcn",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"react": "19.0.0"
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
exports[`transform tailwind prefix 1`] = `
|
||||
"import * as React from "react"
|
||||
export function Foo() {
|
||||
return <div className="tw-bg-background hover:tw-bg-muted tw-text-primary-foreground sm:focus:tw-text-accent-foreground">foo</div>
|
||||
return <div className="tw:bg-background hover:tw:bg-muted tw:text-primary-foreground sm:focus:tw:text-accent-foreground">foo</div>
|
||||
}
|
||||
"
|
||||
`;
|
||||
@@ -11,7 +11,7 @@ exports[`transform tailwind prefix 1`] = `
|
||||
exports[`transform tailwind prefix 2`] = `
|
||||
"import * as React from "react"
|
||||
export function Foo() {
|
||||
return <div className="tw-bg-white hover:tw-bg-stone-100 tw-text-stone-50 sm:focus:tw-text-stone-900 dark:tw-bg-stone-950 dark:hover:tw-bg-stone-800 dark:tw-text-stone-900 dark:sm:focus:tw-text-stone-50">foo</div>
|
||||
return <div className="tw:bg-white hover:tw:bg-stone-100 tw:text-stone-50 sm:focus:tw:text-stone-900 dark:tw:bg-stone-950 dark:hover:tw:bg-stone-800 dark:tw:text-stone-900 dark:sm:focus:tw:text-stone-50">foo</div>
|
||||
}
|
||||
"
|
||||
`;
|
||||
@@ -19,7 +19,7 @@ export function Foo() {
|
||||
exports[`transform tailwind prefix 3`] = `
|
||||
"import * as React from "react"
|
||||
export function Foo() {
|
||||
return <div className={cn("tw-bg-white hover:tw-bg-stone-100 dark:tw-bg-stone-950 dark:hover:tw-bg-stone-800", true && "tw-text-stone-50 sm:focus:tw-text-stone-900 dark:tw-text-stone-900 dark:sm:focus:tw-text-stone-50")}>foo</div>
|
||||
return <div className={cn("tw:bg-white hover:tw:bg-stone-100 dark:tw:bg-stone-950 dark:hover:tw:bg-stone-800", true && "tw:text-stone-50 sm:focus:tw:text-stone-900 dark:tw:text-stone-900 dark:sm:focus:tw:text-stone-50")}>foo</div>
|
||||
}
|
||||
"
|
||||
`;
|
||||
@@ -27,7 +27,7 @@ export function Foo() {
|
||||
exports[`transform tailwind prefix 4`] = `
|
||||
"import * as React from "react"
|
||||
export function Foo() {
|
||||
return <div className={cn("tw-bg-background hover:tw-bg-muted", true && "tw-text-primary-foreground sm:focus:tw-text-accent-foreground")}>foo</div>
|
||||
return <div className={cn("tw:bg-background hover:tw:bg-muted", true && "tw:text-primary-foreground sm:focus:tw:text-accent-foreground")}>foo</div>
|
||||
}
|
||||
"
|
||||
`;
|
||||
@@ -105,10 +105,10 @@ exports[`transform tailwind prefix 5`] = `
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply tw-border-border;
|
||||
@apply tw::border-border;
|
||||
}
|
||||
body {
|
||||
@apply tw-bg-background tw-text-foreground;
|
||||
@apply tw::bg-background tw::text-foreground;
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { describe, expect, test } from "vitest"
|
||||
|
||||
import { applyPrefix } from "../../src/utils/transformers/transform-tw-prefix"
|
||||
|
||||
describe("apply tailwind prefix", () => {
|
||||
describe("apply tailwind prefix v3", () => {
|
||||
test.each([
|
||||
{
|
||||
input: "bg-slate-800 text-gray-500",
|
||||
@@ -37,6 +37,45 @@ describe("apply tailwind prefix", () => {
|
||||
"tw-absolute tw-right-4 tw-top-4 tw-bg-primary tw-rounded-sm tw-opacity-70 tw-ring-offset-background tw-transition-opacity hover:tw-opacity-100 focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-ring focus:tw-ring-offset-2 disabled:tw-pointer-events-none data-[state=open]:tw-bg-secondary",
|
||||
},
|
||||
])(`applyTwPrefix($input) -> $output`, ({ input, output }) => {
|
||||
expect(applyPrefix(input, "tw-")).toBe(output)
|
||||
expect(applyPrefix(input, "tw-", "v3")).toBe(output)
|
||||
})
|
||||
})
|
||||
|
||||
describe("apply tailwind prefix v4", () => {
|
||||
test.each([
|
||||
{
|
||||
input: "bg-slate-800 text-gray-500",
|
||||
output: "tw:bg-slate-800 tw:text-gray-500",
|
||||
},
|
||||
{
|
||||
input: "hover:dark:bg-background dark:text-foreground",
|
||||
output: "tw:hover:dark:bg-background tw:dark:text-foreground",
|
||||
},
|
||||
{
|
||||
input:
|
||||
"rounded-lg border border-slate-200 bg-white text-slate-950 shadow-sm dark:border-slate-800 dark:bg-slate-950 dark:text-slate-50",
|
||||
output:
|
||||
"tw:rounded-lg tw:border tw:border-slate-200 tw:bg-white tw:text-slate-950 tw:shadow-sm tw:dark:border-slate-800 tw:dark:bg-slate-950 tw:dark:text-slate-50",
|
||||
},
|
||||
{
|
||||
input:
|
||||
"text-red-500 border-red-500/50 dark:border-red-500 [&>svg]:text-red-500 text-red-500 dark:text-red-900 dark:border-red-900/50 dark:dark:border-red-900 dark:[&>svg]:text-red-900 dark:text-red-900",
|
||||
output:
|
||||
"tw:text-red-500 tw:border-red-500/50 tw:dark:border-red-500 tw:[&>svg]:text-red-500 tw:text-red-500 tw:dark:text-red-900 tw:dark:border-red-900/50 tw:dark:dark:border-red-900 tw:dark:[&>svg]:text-red-900 tw:dark:text-red-900",
|
||||
},
|
||||
{
|
||||
input:
|
||||
"flex h-full w-full items-center justify-center rounded-full bg-muted",
|
||||
output:
|
||||
"tw:flex tw:h-full tw:w-full tw:items-center tw:justify-center tw:rounded-full tw:bg-muted",
|
||||
},
|
||||
{
|
||||
input:
|
||||
"absolute right-4 top-4 bg-primary rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary",
|
||||
output:
|
||||
"tw:absolute tw:right-4 tw:top-4 tw:bg-primary tw:rounded-sm tw:opacity-70 tw:ring-offset-background tw:transition-opacity tw:hover:opacity-100 tw:focus:outline-none tw:focus:ring-2 tw:focus:ring-ring tw:focus:ring-offset-2 tw:disabled:pointer-events-none tw:data-[state=open]:bg-secondary",
|
||||
},
|
||||
])(`applyTwPrefix($input) -> $output`, ({ input, output }) => {
|
||||
expect(applyPrefix(input, "tw", "v4")).toBe(output)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
exports[`registryResolveItemTree > should resolve index 1`] = `
|
||||
{
|
||||
"css": {},
|
||||
"cssVars": {
|
||||
"dark": {},
|
||||
"light": {
|
||||
@@ -87,6 +88,7 @@ export { Label }
|
||||
|
||||
exports[`registryResolveItemTree > should resolve items tree 1`] = `
|
||||
{
|
||||
"css": {},
|
||||
"cssVars": {},
|
||||
"dependencies": [
|
||||
"@radix-ui/react-slot",
|
||||
@@ -164,6 +166,7 @@ export { Button, buttonVariants }
|
||||
|
||||
exports[`registryResolveItemTree > should resolve multiple items tree 1`] = `
|
||||
{
|
||||
"css": {},
|
||||
"cssVars": {},
|
||||
"dependencies": [
|
||||
"@radix-ui/react-slot",
|
||||
|
||||
@@ -16,7 +16,7 @@ test("transform tailwind prefix", async () => {
|
||||
config: {
|
||||
tailwind: {
|
||||
baseColor: "stone",
|
||||
prefix: "tw-",
|
||||
prefix: "tw:",
|
||||
},
|
||||
aliases: {
|
||||
components: "@/components",
|
||||
@@ -39,7 +39,7 @@ export function Foo() {
|
||||
tailwind: {
|
||||
baseColor: "stone",
|
||||
cssVariables: false,
|
||||
prefix: "tw-",
|
||||
prefix: "tw:",
|
||||
},
|
||||
aliases: {
|
||||
components: "@/components",
|
||||
@@ -62,7 +62,7 @@ export function Foo() {
|
||||
tailwind: {
|
||||
baseColor: "stone",
|
||||
cssVariables: false,
|
||||
prefix: "tw-",
|
||||
prefix: "tw:",
|
||||
},
|
||||
aliases: {
|
||||
components: "@/components",
|
||||
@@ -85,7 +85,7 @@ export function Foo() {
|
||||
tailwind: {
|
||||
baseColor: "stone",
|
||||
cssVariables: false,
|
||||
prefix: "tw-",
|
||||
prefix: "tw:",
|
||||
},
|
||||
aliases: {
|
||||
components: "@/components",
|
||||
@@ -99,7 +99,8 @@ export function Foo() {
|
||||
expect(
|
||||
applyPrefixesCss(
|
||||
"@tailwind base;\n@tailwind components;\n@tailwind utilities;\n \n@layer base {\n :root {\n --background: 0 0% 100%;\n --foreground: 224 71.4% 4.1%;\n \n --muted: 220 14.3% 95.9%;\n --muted-foreground: 220 8.9% 46.1%;\n \n --popover: 0 0% 100%;\n --popover-foreground: 224 71.4% 4.1%;\n \n --card: 0 0% 100%;\n --card-foreground: 224 71.4% 4.1%;\n \n --border: 220 13% 91%;\n --input: 220 13% 91%;\n \n --primary: 220.9 39.3% 11%;\n --primary-foreground: 210 20% 98%;\n \n --secondary: 220 14.3% 95.9%;\n --secondary-foreground: 220.9 39.3% 11%;\n \n --accent: 220 14.3% 95.9%;\n --accent-foreground: 220.9 39.3% 11%;\n \n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 210 20% 98%;\n \n --ring: 217.9 10.6% 64.9%;\n \n --radius: 0.5rem;\n }\n \n .dark {\n --background: 224 71.4% 4.1%;\n --foreground: 210 20% 98%;\n \n --muted: 215 27.9% 16.9%;\n --muted-foreground: 217.9 10.6% 64.9%;\n \n --popover: 224 71.4% 4.1%;\n --popover-foreground: 210 20% 98%;\n \n --card: 224 71.4% 4.1%;\n --card-foreground: 210 20% 98%;\n \n --border: 215 27.9% 16.9%;\n --input: 215 27.9% 16.9%;\n \n --primary: 210 20% 98%;\n --primary-foreground: 220.9 39.3% 11%;\n \n --secondary: 215 27.9% 16.9%;\n --secondary-foreground: 210 20% 98%;\n \n --accent: 215 27.9% 16.9%;\n --accent-foreground: 210 20% 98%;\n \n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 0 85.7% 97.3%;\n \n --ring: 215 27.9% 16.9%;\n }\n}\n \n@layer base {\n * {\n @apply border-border;\n }\n body {\n @apply bg-background text-foreground;\n }\n}",
|
||||
"tw-"
|
||||
"tw:",
|
||||
"v4"
|
||||
)
|
||||
).toMatchSnapshot()
|
||||
})
|
||||
|
||||
331
packages/shadcn/test/utils/updaters/update-css.test.ts
Normal file
331
packages/shadcn/test/utils/updaters/update-css.test.ts
Normal file
@@ -0,0 +1,331 @@
|
||||
import { describe, expect, test } from "vitest"
|
||||
|
||||
import { transformCss } from "../../../src/utils/updaters/update-css"
|
||||
|
||||
describe("transformCss", () => {
|
||||
test("should add utility classes", async () => {
|
||||
const input = `@import "tailwindcss";`
|
||||
|
||||
const result = await transformCss(input, {
|
||||
"@utility content-auto": {
|
||||
"content-visibility": "auto",
|
||||
},
|
||||
})
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
"@import "tailwindcss";
|
||||
|
||||
@utility content-auto {
|
||||
content-visibility: auto;
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
test("should add utility classes with pseudo-selectors", async () => {
|
||||
const input = `@import "tailwindcss";`
|
||||
|
||||
const result = await transformCss(input, {
|
||||
"@utility scrollbar-hidden": {
|
||||
"&::-webkit-scrollbar": {
|
||||
display: "none",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
"@import "tailwindcss";
|
||||
|
||||
@utility scrollbar-hidden {
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
test("should add parameterized utility classes", async () => {
|
||||
const input = `@import "tailwindcss";`
|
||||
|
||||
const result = await transformCss(input, {
|
||||
"@utility tab-*": {
|
||||
"tab-size": "--value([integer])",
|
||||
},
|
||||
})
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
"@import "tailwindcss";
|
||||
|
||||
@utility tab-* {
|
||||
tab-size: --value([integer]);
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
test("should add component styles", async () => {
|
||||
const input = `@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;`
|
||||
|
||||
const result = await transformCss(input, {
|
||||
"@layer components": {
|
||||
".card": {
|
||||
"background-color": "var(--color-white)",
|
||||
"border-radius": "var(--rounded-lg)",
|
||||
padding: "var(--spacing-6)",
|
||||
"box-shadow": "var(--shadow-xl)",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
"@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.card {
|
||||
background-color: var(--color-white);
|
||||
border-radius: var(--rounded-lg);
|
||||
padding: var(--spacing-6);
|
||||
box-shadow: var(--shadow-xl);
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
test("should add base styles", async () => {
|
||||
const input = `@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;`
|
||||
|
||||
const result = await transformCss(input, {
|
||||
"@layer base": {
|
||||
h1: {
|
||||
"font-size": "var(--text-2xl)",
|
||||
},
|
||||
h2: {
|
||||
"font-size": "var(--text-xl)",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
"@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
h1 {
|
||||
font-size: var(--text-2xl);
|
||||
}
|
||||
h2 {
|
||||
font-size: var(--text-xl);
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
test("should update existing rules", async () => {
|
||||
const input = `@import "tailwindcss";
|
||||
|
||||
@layer components {
|
||||
.card {
|
||||
background-color: white;
|
||||
padding: 1rem;
|
||||
}
|
||||
}`
|
||||
|
||||
const result = await transformCss(input, {
|
||||
"@layer components": {
|
||||
".card": {
|
||||
"background-color": "var(--color-white)",
|
||||
"border-radius": "var(--rounded-lg)",
|
||||
"box-shadow": "var(--shadow-xl)",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
"@import "tailwindcss";
|
||||
|
||||
@layer components {
|
||||
.card {
|
||||
background-color: var(--color-white);
|
||||
padding: 1rem;
|
||||
border-radius: var(--rounded-lg);
|
||||
box-shadow: var(--shadow-xl);
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
test("should add multiple rules and types", async () => {
|
||||
const input = `@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;`
|
||||
|
||||
const result = await transformCss(input, {
|
||||
"@utility content-auto": {
|
||||
"content-visibility": "auto",
|
||||
},
|
||||
"@layer components": {
|
||||
".card": {
|
||||
"background-color": "var(--color-white)",
|
||||
"border-radius": "var(--rounded-lg)",
|
||||
},
|
||||
},
|
||||
"@layer base": {
|
||||
h1: {
|
||||
"font-size": "var(--text-2xl)",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
"@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@utility content-auto {
|
||||
content-visibility: auto;
|
||||
}
|
||||
|
||||
@layer components {
|
||||
.card {
|
||||
background-color: var(--color-white);
|
||||
border-radius: var(--rounded-lg);
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
h1 {
|
||||
font-size: var(--text-2xl);
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
test("should handle nested selectors with &", async () => {
|
||||
const input = `@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;`
|
||||
|
||||
const result = await transformCss(input, {
|
||||
"@layer components": {
|
||||
".button": {
|
||||
"background-color": "var(--color-primary)",
|
||||
"&:hover": {
|
||||
"background-color": "var(--color-primary-dark)",
|
||||
},
|
||||
"&:active": {
|
||||
"background-color": "var(--color-primary-darker)",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
"@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.button {
|
||||
background-color: var(--color-primary);
|
||||
}
|
||||
.button:hover {
|
||||
background-color: var(--color-primary-dark);
|
||||
}
|
||||
.button:active {
|
||||
background-color: var(--color-primary-darker);
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
test("should handle direct string content", async () => {
|
||||
const input = `@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;`
|
||||
|
||||
const result = await transformCss(input, {
|
||||
"@layer base": {
|
||||
body: "font-family: var(--font-sans); line-height: 1.5;",
|
||||
},
|
||||
})
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
"@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
body {
|
||||
font-family: var(--font-sans);
|
||||
line-height: 1.5;
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
test("should handle nested at-rules", async () => {
|
||||
const input = `@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;`
|
||||
|
||||
const result = await transformCss(input, {
|
||||
"@layer components": {
|
||||
"@media (min-width: 768px)": {
|
||||
".card": {
|
||||
padding: "2rem",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
"@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.card {
|
||||
padding: 2rem;
|
||||
}
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
test("should place keyframes under @theme inline directive", async () => {
|
||||
const input = `@import "tailwindcss";`
|
||||
|
||||
const result = await transformCss(input, {
|
||||
"@keyframes spin": {
|
||||
"0%": {
|
||||
transform: "rotate(0deg)",
|
||||
},
|
||||
"100%": {
|
||||
transform: "rotate(360deg)",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
"@import "tailwindcss";
|
||||
|
||||
@theme inline {
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
})
|
||||
139
packages/shadcn/test/utils/updaters/update-dependencies.test.ts
Normal file
139
packages/shadcn/test/utils/updaters/update-dependencies.test.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
import { vi, describe, afterEach, test, expect } from "vitest"
|
||||
import { execa } from "execa"
|
||||
import prompts from "prompts"
|
||||
import { updateDependencies } from "../../../src/utils/updaters/update-dependencies"
|
||||
import path from "path"
|
||||
|
||||
vi.mock("execa")
|
||||
vi.mock("prompts")
|
||||
|
||||
describe("updateDependencies", () => {
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks()
|
||||
})
|
||||
|
||||
test.each([
|
||||
{
|
||||
description: "npm without react 19 includes no additional flags",
|
||||
options: { silent: true },
|
||||
dependencies: ["first", "second", "third"],
|
||||
devDependencies: ["fourth"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-npm")
|
||||
}
|
||||
},
|
||||
expectedPackageManager: "npm",
|
||||
expectedArgs: ["install", "first", "second", "third"],
|
||||
expectedDevArgs: ["install", "-D", "fourth"]
|
||||
},
|
||||
{
|
||||
description: "npm with react 19 applies force prompt when silent",
|
||||
options: { silent: true },
|
||||
dependencies: ["first", "second", "third"],
|
||||
devDependencies: ["fourth"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-npm-react19")
|
||||
}
|
||||
},
|
||||
expectedPackageManager: "npm",
|
||||
expectedArgs: ["install", "--force", "first", "second", "third"],
|
||||
expectedDevArgs: ["install", "--force", "-D", "fourth"]
|
||||
},
|
||||
{
|
||||
description: "npm with react 19 prompts for flag when not silent",
|
||||
flagPrompt: "legacy-peer-deps",
|
||||
dependencies: ["first", "second", "third"],
|
||||
devDependencies: ["fourth"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-npm-react19")
|
||||
}
|
||||
},
|
||||
expectedPackageManager: "npm",
|
||||
expectedArgs: ["install", "--legacy-peer-deps", "first", "second", "third"],
|
||||
expectedDevArgs: ["install", "--legacy-peer-deps", "-D", "fourth"]
|
||||
},
|
||||
{
|
||||
description: "deno uses npm: package prefix",
|
||||
dependencies: ["first", "second", "third"],
|
||||
devDependencies: ["fourth"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-deno")
|
||||
}
|
||||
},
|
||||
expectedPackageManager: "deno",
|
||||
expectedArgs: ["add", "npm:first", "npm:second", "npm:third"],
|
||||
expectedDevArgs: ["add", "-D", "npm:fourth"]
|
||||
},
|
||||
{
|
||||
description: "bun uses bun",
|
||||
dependencies: ["first", "second", "third"],
|
||||
devDependencies: ["fourth"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-bun")
|
||||
}
|
||||
},
|
||||
expectedPackageManager: "bun",
|
||||
expectedArgs: ["add", "first", "second", "third"],
|
||||
expectedDevArgs: ["add", "-D", "fourth"]
|
||||
},
|
||||
{
|
||||
description: "pnpm uses pnpm",
|
||||
dependencies: ["first", "second", "third"],
|
||||
devDependencies: ["fourth"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-pnpm")
|
||||
}
|
||||
},
|
||||
expectedPackageManager: "pnpm",
|
||||
expectedArgs: ["add", "first", "second", "third"],
|
||||
expectedDevArgs: ["add", "-D", "fourth"]
|
||||
},
|
||||
{
|
||||
description: "deduplicates input dependencies",
|
||||
options: { silent: true },
|
||||
dependencies: ["first", "first"],
|
||||
devDependencies: ["second", "second"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-npm")
|
||||
}
|
||||
},
|
||||
expectedPackageManager: "npm",
|
||||
expectedArgs: ["install", "first"],
|
||||
expectedDevArgs: ["install", "-D", "second"]
|
||||
}
|
||||
])("$description", async ({ options, flagPrompt, config, dependencies, devDependencies, expectedPackageManager, expectedArgs, expectedDevArgs }) => {
|
||||
|
||||
vi.mocked(prompts).mockResolvedValue({ flag: flagPrompt })
|
||||
|
||||
await updateDependencies(
|
||||
dependencies,
|
||||
devDependencies,
|
||||
config,
|
||||
options ?? {}
|
||||
)
|
||||
|
||||
if (flagPrompt) {
|
||||
expect(prompts).toHaveBeenCalled()
|
||||
}
|
||||
|
||||
|
||||
expect(execa).toHaveBeenCalledWith(
|
||||
expectedPackageManager,
|
||||
expectedArgs,
|
||||
{ cwd: config?.resolvedPaths.cwd }
|
||||
)
|
||||
|
||||
expect(execa).toHaveBeenCalledWith(
|
||||
expectedPackageManager,
|
||||
expectedDevArgs,
|
||||
{ cwd: config?.resolvedPaths.cwd }
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,3 +1,4 @@
|
||||
import { existsSync } from "fs"
|
||||
import path from "path"
|
||||
import { afterAll, afterEach, describe, expect, test, vi } from "vitest"
|
||||
|
||||
@@ -5,7 +6,9 @@ import { getConfig } from "../../../src/utils/get-config"
|
||||
import {
|
||||
findCommonRoot,
|
||||
resolveFilePath,
|
||||
resolveModuleByProbablePath,
|
||||
resolveNestedFilePath,
|
||||
toAliasedImport,
|
||||
updateFiles,
|
||||
} from "../../../src/utils/updaters/update-files"
|
||||
|
||||
@@ -809,3 +812,340 @@ return <div>Hello World</div>
|
||||
`)
|
||||
})
|
||||
})
|
||||
|
||||
describe("resolveModuleByProbablePath", () => {
|
||||
test("should resolve exact file match in provided files list", () => {
|
||||
const files = [
|
||||
"components/button.tsx",
|
||||
"components/card.tsx",
|
||||
"lib/utils.ts",
|
||||
]
|
||||
const config = {
|
||||
resolvedPaths: {
|
||||
cwd: "/foo/bar",
|
||||
},
|
||||
}
|
||||
expect(
|
||||
resolveModuleByProbablePath("/foo/bar/components/button", files, config)
|
||||
).toBe("components/button.tsx")
|
||||
})
|
||||
|
||||
test("should resolve index file", () => {
|
||||
const files = ["components/button/index.tsx", "components/card.tsx"]
|
||||
const config = {
|
||||
resolvedPaths: {
|
||||
cwd: "/foo/bar",
|
||||
},
|
||||
}
|
||||
expect(
|
||||
resolveModuleByProbablePath("/foo/bar/components/button", files, config)
|
||||
).toBe("components/button/index.tsx")
|
||||
})
|
||||
|
||||
test("should try different extensions", () => {
|
||||
const files = ["components/button.jsx", "components/card.tsx"]
|
||||
const config = {
|
||||
resolvedPaths: {
|
||||
cwd: "/foo/bar",
|
||||
},
|
||||
}
|
||||
expect(
|
||||
resolveModuleByProbablePath("/foo/bar/components/button", files, config)
|
||||
).toBe("components/button.jsx")
|
||||
})
|
||||
|
||||
test("should fallback to basename matching", () => {
|
||||
const files = ["components/ui/button.tsx", "components/card.tsx"]
|
||||
const config = {
|
||||
resolvedPaths: {
|
||||
cwd: "/foo/bar",
|
||||
},
|
||||
}
|
||||
expect(
|
||||
resolveModuleByProbablePath("/foo/bar/components/button", files, config)
|
||||
).toBe("components/ui/button.tsx")
|
||||
})
|
||||
|
||||
test("should return null when file not found", () => {
|
||||
const files = ["components/card.tsx", "lib/utils.ts"]
|
||||
const config = {
|
||||
resolvedPaths: {
|
||||
cwd: "/foo/bar",
|
||||
},
|
||||
}
|
||||
expect(
|
||||
resolveModuleByProbablePath("/foo/bar/components/button", files, config)
|
||||
).toBeNull()
|
||||
})
|
||||
|
||||
test("should sort by extension priority", () => {
|
||||
const files = [
|
||||
"components/button.jsx",
|
||||
"components/button.tsx",
|
||||
"components/button.js",
|
||||
]
|
||||
const config = {
|
||||
resolvedPaths: {
|
||||
cwd: "/foo/bar",
|
||||
},
|
||||
}
|
||||
expect(
|
||||
resolveModuleByProbablePath("/foo/bar/components/button", files, config, [
|
||||
".tsx",
|
||||
".jsx",
|
||||
".js",
|
||||
])
|
||||
).toBe("components/button.tsx")
|
||||
})
|
||||
|
||||
test("should preserve extension if specified in path", () => {
|
||||
const files = ["components/button.tsx", "components/button.css"]
|
||||
const config = {
|
||||
resolvedPaths: {
|
||||
cwd: "/foo/bar",
|
||||
},
|
||||
}
|
||||
expect(
|
||||
resolveModuleByProbablePath(
|
||||
"/foo/bar/components/button.css",
|
||||
files,
|
||||
config
|
||||
)
|
||||
).toBe("components/button.css")
|
||||
})
|
||||
})
|
||||
|
||||
describe("toAliasedImport", () => {
|
||||
test("should convert components path to aliased import", () => {
|
||||
const filePath = "components/button.tsx"
|
||||
const config = {
|
||||
resolvedPaths: {
|
||||
cwd: "/foo/bar",
|
||||
components: "/foo/bar/components",
|
||||
ui: "/foo/bar/components/ui",
|
||||
lib: "/foo/bar/lib",
|
||||
},
|
||||
aliases: {
|
||||
components: "@/components",
|
||||
ui: "@/components/ui",
|
||||
lib: "@/lib",
|
||||
},
|
||||
}
|
||||
const projectInfo = {
|
||||
aliasPrefix: "@",
|
||||
}
|
||||
expect(toAliasedImport(filePath, config, projectInfo)).toBe(
|
||||
"@/components/button"
|
||||
)
|
||||
})
|
||||
|
||||
test("should convert ui path to aliased import", () => {
|
||||
const filePath = "components/ui/button.tsx"
|
||||
const config = {
|
||||
resolvedPaths: {
|
||||
cwd: "/foo/bar",
|
||||
components: "/foo/bar/components",
|
||||
ui: "/foo/bar/components/ui",
|
||||
lib: "/foo/bar/lib",
|
||||
},
|
||||
aliases: {
|
||||
components: "@/components",
|
||||
ui: "@/components/ui",
|
||||
lib: "@/lib",
|
||||
},
|
||||
}
|
||||
const projectInfo = {
|
||||
aliasPrefix: "@",
|
||||
}
|
||||
expect(toAliasedImport(filePath, config, projectInfo)).toBe(
|
||||
"@/components/ui/button"
|
||||
)
|
||||
})
|
||||
|
||||
test("should collapse index files", () => {
|
||||
const filePath = "components/ui/button/index.tsx"
|
||||
const config = {
|
||||
resolvedPaths: {
|
||||
cwd: "/foo/bar",
|
||||
components: "/foo/bar/components",
|
||||
ui: "/foo/bar/components/ui",
|
||||
lib: "/foo/bar/lib",
|
||||
},
|
||||
aliases: {
|
||||
components: "@/components",
|
||||
ui: "@/components/ui",
|
||||
lib: "@/lib",
|
||||
},
|
||||
}
|
||||
const projectInfo = {
|
||||
aliasPrefix: "@",
|
||||
}
|
||||
expect(toAliasedImport(filePath, config, projectInfo)).toBe(
|
||||
"@/components/ui/button"
|
||||
)
|
||||
})
|
||||
|
||||
test("should return null when no matching alias found", () => {
|
||||
const filePath = "src/pages/index.tsx"
|
||||
const config = {
|
||||
resolvedPaths: {
|
||||
cwd: "/foo/bar",
|
||||
components: "/foo/bar/components",
|
||||
ui: "/foo/bar/components/ui",
|
||||
lib: "/foo/bar/lib",
|
||||
},
|
||||
aliases: {
|
||||
components: "@/components",
|
||||
ui: "@/components/ui",
|
||||
lib: "@/lib",
|
||||
},
|
||||
}
|
||||
const projectInfo = {
|
||||
aliasPrefix: "@",
|
||||
}
|
||||
expect(toAliasedImport(filePath, config, projectInfo)).toBe("@/pages")
|
||||
})
|
||||
|
||||
test("should handle nested directories", () => {
|
||||
const filePath = "components/forms/inputs/text-input.tsx"
|
||||
const config = {
|
||||
resolvedPaths: {
|
||||
cwd: "/foo/bar",
|
||||
components: "/foo/bar/components",
|
||||
ui: "/foo/bar/components/ui",
|
||||
lib: "/foo/bar/lib",
|
||||
},
|
||||
aliases: {
|
||||
components: "@/components",
|
||||
ui: "@/components/ui",
|
||||
lib: "@/lib",
|
||||
},
|
||||
}
|
||||
const projectInfo = {
|
||||
aliasPrefix: "@",
|
||||
}
|
||||
expect(toAliasedImport(filePath, config, projectInfo)).toBe(
|
||||
"@/components/forms/inputs/text-input"
|
||||
)
|
||||
})
|
||||
|
||||
test("should keep non-code file extensions", () => {
|
||||
const filePath = "components/styles/theme.css"
|
||||
const config = {
|
||||
resolvedPaths: {
|
||||
cwd: "/foo/bar",
|
||||
components: "/foo/bar/components",
|
||||
ui: "/foo/bar/components/ui",
|
||||
lib: "/foo/bar/lib",
|
||||
},
|
||||
aliases: {
|
||||
components: "@/components",
|
||||
ui: "@/components/ui",
|
||||
lib: "@/lib",
|
||||
},
|
||||
}
|
||||
const projectInfo = {
|
||||
aliasPrefix: "@",
|
||||
}
|
||||
expect(toAliasedImport(filePath, config, projectInfo)).toBe(
|
||||
"@/components/styles/theme.css"
|
||||
)
|
||||
})
|
||||
|
||||
test("should prefer longer matching paths", () => {
|
||||
const filePath = "components/ui/button.tsx"
|
||||
const config = {
|
||||
resolvedPaths: {
|
||||
cwd: "/foo/bar",
|
||||
components: "/foo/bar/components",
|
||||
ui: "/foo/bar/components/ui",
|
||||
},
|
||||
aliases: {
|
||||
components: "@/components",
|
||||
ui: "@/ui",
|
||||
},
|
||||
}
|
||||
const projectInfo = {
|
||||
aliasPrefix: "@",
|
||||
}
|
||||
expect(toAliasedImport(filePath, config, projectInfo)).toBe("@/ui/button")
|
||||
})
|
||||
|
||||
test("should support tilde (~) alias prefix", () => {
|
||||
const filePath = "components/button.tsx"
|
||||
const config = {
|
||||
resolvedPaths: {
|
||||
cwd: "/foo/bar",
|
||||
components: "/foo/bar/components",
|
||||
},
|
||||
aliases: {
|
||||
components: "~components",
|
||||
},
|
||||
}
|
||||
const projectInfo = {
|
||||
aliasPrefix: "~",
|
||||
}
|
||||
expect(toAliasedImport(filePath, config, projectInfo)).toBe(
|
||||
"~components/button"
|
||||
)
|
||||
})
|
||||
|
||||
test("should support @shadcn alias prefix", () => {
|
||||
const filePath = "components/ui/button.tsx"
|
||||
const config = {
|
||||
resolvedPaths: {
|
||||
cwd: "/foo/bar",
|
||||
components: "/foo/bar/components",
|
||||
ui: "/foo/bar/components/ui",
|
||||
},
|
||||
aliases: {
|
||||
components: "@shadcn/components",
|
||||
ui: "@shadcn/ui",
|
||||
},
|
||||
}
|
||||
const projectInfo = {
|
||||
aliasPrefix: "@shadcn",
|
||||
}
|
||||
expect(toAliasedImport(filePath, config, projectInfo)).toBe(
|
||||
"@shadcn/ui/button"
|
||||
)
|
||||
})
|
||||
|
||||
test("should support ~cn alias prefix", () => {
|
||||
const filePath = "lib/utils/index.tsx"
|
||||
const config = {
|
||||
resolvedPaths: {
|
||||
cwd: "/foo/bar",
|
||||
lib: "/foo/bar/lib",
|
||||
},
|
||||
aliases: {
|
||||
lib: "~cn/lib",
|
||||
},
|
||||
}
|
||||
const projectInfo = {
|
||||
aliasPrefix: "~cn",
|
||||
}
|
||||
expect(toAliasedImport(filePath, config, projectInfo)).toBe("~cn/lib/utils")
|
||||
})
|
||||
|
||||
test("should use project alias prefix when aliasKey is cwd", () => {
|
||||
const filePath = "src/pages/home.tsx"
|
||||
const config = {
|
||||
resolvedPaths: {
|
||||
cwd: "/foo/bar",
|
||||
components: "/foo/bar/components",
|
||||
ui: "/foo/bar/components/ui",
|
||||
lib: "/foo/bar/lib",
|
||||
},
|
||||
aliases: {
|
||||
components: "@/components",
|
||||
ui: "@/components/ui",
|
||||
lib: "@/lib",
|
||||
},
|
||||
}
|
||||
const projectInfo = {
|
||||
aliasPrefix: "@",
|
||||
}
|
||||
expect(toAliasedImport(filePath, config, projectInfo)).toBe("@/pages/home")
|
||||
})
|
||||
})
|
||||
|
||||
171
pnpm-lock.yaml
generated
171
pnpm-lock.yaml
generated
@@ -58,7 +58,7 @@ importers:
|
||||
version: 7.37.4(eslint@8.57.1)
|
||||
eslint-plugin-tailwindcss:
|
||||
specifier: 3.13.1
|
||||
version: 3.13.1(tailwindcss@3.4.6(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.7.3)))
|
||||
version: 3.13.1(tailwindcss@3.4.6(ts-node@10.9.2(@types/node@20.17.16)(typescript@5.7.3)))
|
||||
postcss:
|
||||
specifier: ^8.4.24
|
||||
version: 8.5.1
|
||||
@@ -73,10 +73,10 @@ importers:
|
||||
version: 23.11.1(typescript@5.7.3)
|
||||
tailwindcss:
|
||||
specifier: 3.4.6
|
||||
version: 3.4.6(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.7.3))
|
||||
version: 3.4.6(ts-node@10.9.2(@types/node@20.17.16)(typescript@5.7.3))
|
||||
tailwindcss-animate:
|
||||
specifier: ^1.0.5
|
||||
version: 1.0.7(tailwindcss@3.4.6(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.7.3)))
|
||||
version: 1.0.7(tailwindcss@3.4.6(ts-node@10.9.2(@types/node@20.17.16)(typescript@5.7.3)))
|
||||
tsx:
|
||||
specifier: ^4.1.4
|
||||
version: 4.19.2
|
||||
@@ -283,7 +283,7 @@ importers:
|
||||
specifier: ^6.0.1
|
||||
version: 6.0.1
|
||||
shadcn:
|
||||
specifier: 2.3.0
|
||||
specifier: 2.5.0
|
||||
version: link:../../packages/shadcn
|
||||
sonner:
|
||||
specifier: ^2.0.0
|
||||
@@ -542,7 +542,7 @@ importers:
|
||||
specifier: 2.12.7
|
||||
version: 2.12.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
shadcn:
|
||||
specifier: 2.3.0
|
||||
specifier: 2.5.0
|
||||
version: link:../../packages/shadcn
|
||||
sharp:
|
||||
specifier: ^0.32.6
|
||||
@@ -689,7 +689,7 @@ importers:
|
||||
version: 4.1.5
|
||||
msw:
|
||||
specifier: ^2.7.1
|
||||
version: 2.7.1(@types/node@20.17.16)(typescript@4.9.5)
|
||||
version: 2.7.1(@types/node@22.13.0)(typescript@4.9.5)
|
||||
node-fetch:
|
||||
specifier: ^3.3.0
|
||||
version: 3.3.2
|
||||
@@ -738,7 +738,7 @@ importers:
|
||||
version: 6.0.1
|
||||
tsup:
|
||||
specifier: ^6.6.3
|
||||
version: 6.7.0(postcss@8.5.1)(ts-node@10.9.2(@types/node@20.17.16)(typescript@4.9.5))(typescript@4.9.5)
|
||||
version: 6.7.0(postcss@8.5.1)(ts-node@10.9.2(@types/node@22.13.0)(typescript@4.9.5))(typescript@4.9.5)
|
||||
type-fest:
|
||||
specifier: ^3.8.0
|
||||
version: 3.13.1
|
||||
@@ -8813,7 +8813,7 @@ snapshots:
|
||||
lodash.merge: 4.6.2
|
||||
lodash.uniq: 4.5.0
|
||||
resolve-from: 5.0.0
|
||||
ts-node: 10.9.2(@types/node@20.17.16)(typescript@5.7.3)
|
||||
ts-node: 10.9.2(@types/node@20.5.1)(typescript@5.7.3)
|
||||
typescript: 5.7.3
|
||||
transitivePeerDependencies:
|
||||
- '@swc/core'
|
||||
@@ -9595,6 +9595,14 @@ snapshots:
|
||||
'@inquirer/type': 3.0.4(@types/node@20.17.16)
|
||||
optionalDependencies:
|
||||
'@types/node': 20.17.16
|
||||
optional: true
|
||||
|
||||
'@inquirer/confirm@5.1.6(@types/node@22.13.0)':
|
||||
dependencies:
|
||||
'@inquirer/core': 10.1.7(@types/node@22.13.0)
|
||||
'@inquirer/type': 3.0.4(@types/node@22.13.0)
|
||||
optionalDependencies:
|
||||
'@types/node': 22.13.0
|
||||
|
||||
'@inquirer/core@10.1.7(@types/node@20.17.16)':
|
||||
dependencies:
|
||||
@@ -9608,12 +9616,31 @@ snapshots:
|
||||
yoctocolors-cjs: 2.1.2
|
||||
optionalDependencies:
|
||||
'@types/node': 20.17.16
|
||||
optional: true
|
||||
|
||||
'@inquirer/core@10.1.7(@types/node@22.13.0)':
|
||||
dependencies:
|
||||
'@inquirer/figures': 1.0.10
|
||||
'@inquirer/type': 3.0.4(@types/node@22.13.0)
|
||||
ansi-escapes: 4.3.2
|
||||
cli-width: 4.1.0
|
||||
mute-stream: 2.0.0
|
||||
signal-exit: 4.1.0
|
||||
wrap-ansi: 6.2.0
|
||||
yoctocolors-cjs: 2.1.2
|
||||
optionalDependencies:
|
||||
'@types/node': 22.13.0
|
||||
|
||||
'@inquirer/figures@1.0.10': {}
|
||||
|
||||
'@inquirer/type@3.0.4(@types/node@20.17.16)':
|
||||
optionalDependencies:
|
||||
'@types/node': 20.17.16
|
||||
optional: true
|
||||
|
||||
'@inquirer/type@3.0.4(@types/node@22.13.0)':
|
||||
optionalDependencies:
|
||||
'@types/node': 22.13.0
|
||||
|
||||
'@isaacs/cliui@8.0.2':
|
||||
dependencies:
|
||||
@@ -12610,7 +12637,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/node': 20.5.1
|
||||
cosmiconfig: 8.3.6(typescript@5.7.3)
|
||||
ts-node: 10.9.2(@types/node@20.17.16)(typescript@5.7.3)
|
||||
ts-node: 10.9.2(@types/node@20.5.1)(typescript@5.7.3)
|
||||
typescript: 5.7.3
|
||||
|
||||
cosmiconfig@8.3.6(typescript@4.9.5):
|
||||
@@ -13329,7 +13356,7 @@ snapshots:
|
||||
debug: 4.3.7
|
||||
enhanced-resolve: 5.16.1
|
||||
eslint: 8.57.1
|
||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.61.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.61.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1)
|
||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.61.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1)
|
||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.61.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1)
|
||||
fast-glob: 3.3.3
|
||||
get-tsconfig: 4.7.5
|
||||
@@ -13346,7 +13373,7 @@ snapshots:
|
||||
debug: 4.3.7
|
||||
enhanced-resolve: 5.16.1
|
||||
eslint: 9.19.0(jiti@2.4.2)
|
||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.61.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.61.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@9.19.0(jiti@2.4.2)))(eslint@9.19.0(jiti@2.4.2))
|
||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.61.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@9.19.0(jiti@2.4.2))
|
||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.61.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.6.1)(eslint@9.19.0(jiti@2.4.2))
|
||||
fast-glob: 3.3.3
|
||||
get-tsconfig: 4.7.5
|
||||
@@ -13358,7 +13385,7 @@ snapshots:
|
||||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
|
||||
eslint-module-utils@2.12.0(@typescript-eslint/parser@5.61.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.61.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1):
|
||||
eslint-module-utils@2.12.0(@typescript-eslint/parser@5.61.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1):
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
optionalDependencies:
|
||||
@@ -13369,7 +13396,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-module-utils@2.12.0(@typescript-eslint/parser@5.61.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.61.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@9.19.0(jiti@2.4.2)))(eslint@9.19.0(jiti@2.4.2)):
|
||||
eslint-module-utils@2.12.0(@typescript-eslint/parser@5.61.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@9.19.0(jiti@2.4.2)):
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
optionalDependencies:
|
||||
@@ -13391,7 +13418,7 @@ snapshots:
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.57.1
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.61.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.61.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1)
|
||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.61.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1)
|
||||
hasown: 2.0.2
|
||||
is-core-module: 2.16.1
|
||||
is-glob: 4.0.3
|
||||
@@ -13420,7 +13447,7 @@ snapshots:
|
||||
doctrine: 2.1.0
|
||||
eslint: 9.19.0(jiti@2.4.2)
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.61.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.61.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@9.19.0(jiti@2.4.2)))(eslint@9.19.0(jiti@2.4.2))
|
||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.61.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@9.19.0(jiti@2.4.2))
|
||||
hasown: 2.0.2
|
||||
is-core-module: 2.16.1
|
||||
is-glob: 4.0.3
|
||||
@@ -13528,11 +13555,11 @@ snapshots:
|
||||
string.prototype.matchall: 4.0.12
|
||||
string.prototype.repeat: 1.0.0
|
||||
|
||||
eslint-plugin-tailwindcss@3.13.1(tailwindcss@3.4.6(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.7.3))):
|
||||
eslint-plugin-tailwindcss@3.13.1(tailwindcss@3.4.6(ts-node@10.9.2(@types/node@20.17.16)(typescript@5.7.3))):
|
||||
dependencies:
|
||||
fast-glob: 3.3.3
|
||||
postcss: 8.5.1
|
||||
tailwindcss: 3.4.6(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.7.3))
|
||||
tailwindcss: 3.4.6(ts-node@10.9.2(@types/node@20.17.16)(typescript@5.7.3))
|
||||
|
||||
eslint-plugin-turbo@1.13.4(eslint@8.57.1):
|
||||
dependencies:
|
||||
@@ -15636,31 +15663,6 @@ snapshots:
|
||||
|
||||
ms@2.1.3: {}
|
||||
|
||||
msw@2.7.1(@types/node@20.17.16)(typescript@4.9.5):
|
||||
dependencies:
|
||||
'@bundled-es-modules/cookie': 2.0.1
|
||||
'@bundled-es-modules/statuses': 1.0.1
|
||||
'@bundled-es-modules/tough-cookie': 0.1.6
|
||||
'@inquirer/confirm': 5.1.6(@types/node@20.17.16)
|
||||
'@mswjs/interceptors': 0.37.6
|
||||
'@open-draft/deferred-promise': 2.2.0
|
||||
'@open-draft/until': 2.1.0
|
||||
'@types/cookie': 0.6.0
|
||||
'@types/statuses': 2.0.5
|
||||
graphql: 16.10.0
|
||||
headers-polyfill: 4.0.3
|
||||
is-node-process: 1.2.0
|
||||
outvariant: 1.4.3
|
||||
path-to-regexp: 6.3.0
|
||||
picocolors: 1.1.1
|
||||
strict-event-emitter: 0.5.1
|
||||
type-fest: 4.33.0
|
||||
yargs: 17.7.2
|
||||
optionalDependencies:
|
||||
typescript: 4.9.5
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
|
||||
msw@2.7.1(@types/node@20.17.16)(typescript@5.7.3):
|
||||
dependencies:
|
||||
'@bundled-es-modules/cookie': 2.0.1
|
||||
@@ -15687,6 +15689,31 @@ snapshots:
|
||||
- '@types/node'
|
||||
optional: true
|
||||
|
||||
msw@2.7.1(@types/node@22.13.0)(typescript@4.9.5):
|
||||
dependencies:
|
||||
'@bundled-es-modules/cookie': 2.0.1
|
||||
'@bundled-es-modules/statuses': 1.0.1
|
||||
'@bundled-es-modules/tough-cookie': 0.1.6
|
||||
'@inquirer/confirm': 5.1.6(@types/node@22.13.0)
|
||||
'@mswjs/interceptors': 0.37.6
|
||||
'@open-draft/deferred-promise': 2.2.0
|
||||
'@open-draft/until': 2.1.0
|
||||
'@types/cookie': 0.6.0
|
||||
'@types/statuses': 2.0.5
|
||||
graphql: 16.10.0
|
||||
headers-polyfill: 4.0.3
|
||||
is-node-process: 1.2.0
|
||||
outvariant: 1.4.3
|
||||
path-to-regexp: 6.3.0
|
||||
picocolors: 1.1.1
|
||||
strict-event-emitter: 0.5.1
|
||||
type-fest: 4.33.0
|
||||
yargs: 17.7.2
|
||||
optionalDependencies:
|
||||
typescript: 4.9.5
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
|
||||
mute-stream@2.0.0: {}
|
||||
|
||||
mz@2.7.0:
|
||||
@@ -16090,13 +16117,13 @@ snapshots:
|
||||
camelcase-css: 2.0.1
|
||||
postcss: 8.5.1
|
||||
|
||||
postcss-load-config@3.1.4(postcss@8.5.1)(ts-node@10.9.2(@types/node@20.17.16)(typescript@4.9.5)):
|
||||
postcss-load-config@3.1.4(postcss@8.5.1)(ts-node@10.9.2(@types/node@22.13.0)(typescript@4.9.5)):
|
||||
dependencies:
|
||||
lilconfig: 2.1.0
|
||||
yaml: 1.10.2
|
||||
optionalDependencies:
|
||||
postcss: 8.5.1
|
||||
ts-node: 10.9.2(@types/node@20.17.16)(typescript@4.9.5)
|
||||
ts-node: 10.9.2(@types/node@22.13.0)(typescript@4.9.5)
|
||||
|
||||
postcss-load-config@3.1.4(postcss@8.5.1)(ts-node@10.9.2(@types/node@22.13.0)(typescript@5.7.3)):
|
||||
dependencies:
|
||||
@@ -16114,13 +16141,13 @@ snapshots:
|
||||
postcss: 8.5.1
|
||||
ts-node: 10.9.2(@types/node@17.0.45)(typescript@5.7.3)
|
||||
|
||||
postcss-load-config@4.0.2(postcss@8.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.7.3)):
|
||||
postcss-load-config@4.0.2(postcss@8.5.1)(ts-node@10.9.2(@types/node@20.17.16)(typescript@5.7.3)):
|
||||
dependencies:
|
||||
lilconfig: 3.1.3
|
||||
yaml: 2.7.0
|
||||
optionalDependencies:
|
||||
postcss: 8.5.1
|
||||
ts-node: 10.9.2(@types/node@20.17.16)(typescript@5.7.3)
|
||||
ts-node: 10.9.2(@types/node@20.5.1)(typescript@5.7.3)
|
||||
|
||||
postcss-nested@6.2.0(postcss@8.5.1):
|
||||
dependencies:
|
||||
@@ -17316,9 +17343,9 @@ snapshots:
|
||||
|
||||
tailwind-merge@3.0.1: {}
|
||||
|
||||
tailwindcss-animate@1.0.7(tailwindcss@3.4.6(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.7.3))):
|
||||
tailwindcss-animate@1.0.7(tailwindcss@3.4.6(ts-node@10.9.2(@types/node@20.17.16)(typescript@5.7.3))):
|
||||
dependencies:
|
||||
tailwindcss: 3.4.6(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.7.3))
|
||||
tailwindcss: 3.4.6(ts-node@10.9.2(@types/node@20.17.16)(typescript@5.7.3))
|
||||
|
||||
tailwindcss@3.4.6(ts-node@10.9.2(@types/node@17.0.45)(typescript@5.7.3)):
|
||||
dependencies:
|
||||
@@ -17347,7 +17374,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- ts-node
|
||||
|
||||
tailwindcss@3.4.6(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.7.3)):
|
||||
tailwindcss@3.4.6(ts-node@10.9.2(@types/node@20.17.16)(typescript@5.7.3)):
|
||||
dependencies:
|
||||
'@alloc/quick-lru': 5.2.0
|
||||
arg: 5.0.2
|
||||
@@ -17366,7 +17393,7 @@ snapshots:
|
||||
postcss: 8.5.1
|
||||
postcss-import: 15.1.0(postcss@8.5.1)
|
||||
postcss-js: 4.0.1(postcss@8.5.1)
|
||||
postcss-load-config: 4.0.2(postcss@8.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.7.3))
|
||||
postcss-load-config: 4.0.2(postcss@8.5.1)(ts-node@10.9.2(@types/node@20.17.16)(typescript@5.7.3))
|
||||
postcss-nested: 6.2.0(postcss@8.5.1)
|
||||
postcss-selector-parser: 6.1.2
|
||||
resolve: 1.22.10
|
||||
@@ -17534,14 +17561,32 @@ snapshots:
|
||||
yn: 3.1.1
|
||||
optional: true
|
||||
|
||||
ts-node@10.9.2(@types/node@20.17.16)(typescript@4.9.5):
|
||||
ts-node@10.9.2(@types/node@20.5.1)(typescript@5.7.3):
|
||||
dependencies:
|
||||
'@cspotcode/source-map-support': 0.8.1
|
||||
'@tsconfig/node10': 1.0.11
|
||||
'@tsconfig/node12': 1.0.11
|
||||
'@tsconfig/node14': 1.0.3
|
||||
'@tsconfig/node16': 1.0.4
|
||||
'@types/node': 20.17.16
|
||||
'@types/node': 20.5.1
|
||||
acorn: 8.14.0
|
||||
acorn-walk: 8.3.4
|
||||
arg: 4.1.3
|
||||
create-require: 1.1.1
|
||||
diff: 4.0.2
|
||||
make-error: 1.3.6
|
||||
typescript: 5.7.3
|
||||
v8-compile-cache-lib: 3.0.1
|
||||
yn: 3.1.1
|
||||
|
||||
ts-node@10.9.2(@types/node@22.13.0)(typescript@4.9.5):
|
||||
dependencies:
|
||||
'@cspotcode/source-map-support': 0.8.1
|
||||
'@tsconfig/node10': 1.0.11
|
||||
'@tsconfig/node12': 1.0.11
|
||||
'@tsconfig/node14': 1.0.3
|
||||
'@tsconfig/node16': 1.0.4
|
||||
'@types/node': 22.13.0
|
||||
acorn: 8.14.0
|
||||
acorn-walk: 8.3.4
|
||||
arg: 4.1.3
|
||||
@@ -17553,24 +17598,6 @@ snapshots:
|
||||
yn: 3.1.1
|
||||
optional: true
|
||||
|
||||
ts-node@10.9.2(@types/node@20.17.16)(typescript@5.7.3):
|
||||
dependencies:
|
||||
'@cspotcode/source-map-support': 0.8.1
|
||||
'@tsconfig/node10': 1.0.11
|
||||
'@tsconfig/node12': 1.0.11
|
||||
'@tsconfig/node14': 1.0.3
|
||||
'@tsconfig/node16': 1.0.4
|
||||
'@types/node': 20.17.16
|
||||
acorn: 8.14.0
|
||||
acorn-walk: 8.3.4
|
||||
arg: 4.1.3
|
||||
create-require: 1.1.1
|
||||
diff: 4.0.2
|
||||
make-error: 1.3.6
|
||||
typescript: 5.7.3
|
||||
v8-compile-cache-lib: 3.0.1
|
||||
yn: 3.1.1
|
||||
|
||||
ts-node@10.9.2(@types/node@22.13.0)(typescript@5.7.3):
|
||||
dependencies:
|
||||
'@cspotcode/source-map-support': 0.8.1
|
||||
@@ -17615,7 +17642,7 @@ snapshots:
|
||||
|
||||
tslib@2.8.1: {}
|
||||
|
||||
tsup@6.7.0(postcss@8.5.1)(ts-node@10.9.2(@types/node@20.17.16)(typescript@4.9.5))(typescript@4.9.5):
|
||||
tsup@6.7.0(postcss@8.5.1)(ts-node@10.9.2(@types/node@22.13.0)(typescript@4.9.5))(typescript@4.9.5):
|
||||
dependencies:
|
||||
bundle-require: 4.2.1(esbuild@0.17.19)
|
||||
cac: 6.7.14
|
||||
@@ -17625,7 +17652,7 @@ snapshots:
|
||||
execa: 5.1.1
|
||||
globby: 11.1.0
|
||||
joycon: 3.1.1
|
||||
postcss-load-config: 3.1.4(postcss@8.5.1)(ts-node@10.9.2(@types/node@20.17.16)(typescript@4.9.5))
|
||||
postcss-load-config: 3.1.4(postcss@8.5.1)(ts-node@10.9.2(@types/node@22.13.0)(typescript@4.9.5))
|
||||
resolve-from: 5.0.0
|
||||
rollup: 3.29.5
|
||||
source-map: 0.8.0-beta.0
|
||||
|
||||
Reference in New Issue
Block a user