Compare commits

...

12 Commits

Author SHA1 Message Date
github-actions[bot]
729b9ec8ca chore(release): version packages (#5812)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-12-10 12:17:32 +04:00
Jens Astrup
a1bed464f3 chore(apps): Update lodash (#4397)
* chore(apps): Refactor usage of lodash.template to lodash to address security vulnerability

* chore(cli): Refactor usage of lodash.template to lodash to address security vulnerability

* deps: update lock

* chore: changesets

* style: fix format

* fix: import

* chore: build registry

---------

Co-authored-by: shadcn <m@shadcn.com>
2024-12-09 12:33:28 +04:00
shadcn
805ed4120a feat(www): refactor examples page (#5818) 2024-11-13 16:01:14 +04:00
shadcn
600a593c87 docs(www): update manual installation (#5817) 2024-11-13 15:42:52 +04:00
Braden Corbold
500dbe2664 fix(shadcn) arrays and nested deeply nested spread (#5711)
* fix: tailwind config updater parser

* fix: remove quote around spread element

* fix: specify deepmerge option for array

* fix(shadcn): Nested and spread array elements

* add test case for boolean primitive

---------

Co-authored-by: matsuyoshi30 <sfbgwm30@gmail.com>
Co-authored-by: shadcn <m@shadcn.com>
2024-11-13 15:19:21 +04:00
JEM
c577ee0666 docs(contributing): add CLI usage instructions (#5807)
Introduce a detailed workflow for running the CLI locally, ensuring contributors can easily test and develop enhancements in their local environment. This addition helps maintain consistency between CLI and component updates.
2024-11-13 15:17:11 +04:00
shadcn
d5bf0018fd fix(shadcn): handling of tsconfig aliases (#5813)
* fix(shadcn): handling of tsconfig aliases

* chore: add changeset
2024-11-13 15:15:22 +04:00
Tobbe Lundberg
fb36ca4159 fix(transform): Support aliases that are longer than one character (#5678)
* fix(transform): Support aliases that are longer than one character

* feat(shadcn): update handling of aliases

* chore: add changeset

---------

Co-authored-by: shadcn <m@shadcn.com>
2024-11-12 22:13:38 +04:00
JEM
824a35ada1 test(snapshots): update test snapshots for consistency (#5801)
Updated snapshot components to use `React.ComponentProps` instead of custom interfaces for `input` and `Dialog` components. This simplifies the code by leveraging built-in React types, ensuring consistency and reducing potential errors arising from custom definitions.
2024-11-12 12:54:31 +04:00
shadcn
8d520c8d49 fix(www): figma link (#5798) 2024-11-11 20:08:24 +04:00
Temkin Mengsitu
0873835339 fix: ensure block component name is copied in shadcn (#5790) 2024-11-11 12:10:04 +04:00
JEM
4a0d4cfdb9 refactor(components): remove redundant empty interfaces from Input, Command, and Textarea components (#5657)
* refactor(components): remove redundant empty interfaces from Input, Command, and Textarea components

Simplified props handling by removing redundant empty interfaces (`InputProps`, `CommandDialogProps`, `TextareaProps`). Directly extended native HTML attributes/lib for each component, enhancing code clarity and maintainability. This refactor ensures compliance with ESLint rules and streamlines future modifications without altering component functionality.

* updated the registry

* rerun build:registry with updated command

* Refactor input and textarea components to use `React.ComponentProps`

* update registry
2024-11-08 20:26:01 +04:00
51 changed files with 1069 additions and 239 deletions

View File

@@ -91,6 +91,42 @@ pnpm --filter=www dev
pnpm --filter=shadcn-ui dev
```
## Running the CLI Locally
To run the CLI locally, you can follow the workflow:
1. Start by running the registry (main site) to make sure the components are up to date:
```bash
pnpm www:dev
```
2. Run the development script for the CLI:
```bash
pnpm shadcn:dev
```
3. In another terminal tab, test the CLI by running:
```bash
pnpm shadcn
```
To test the CLI in a specific app, use a command like:
```bash
pnpm shadcn <init | add | ...> -c ~/Desktop/my-app
```
4. To run the tests for the CLI:
```bash
pnpm --filter=shadcn test
```
This workflow ensures that you are running the most recent version of the registry and testing the CLI properly in your local environment.
## Documentation
The documentation for this project is located in the `www` workspace. You can run the documentation locally by running the following command:

View File

@@ -141,15 +141,16 @@ export default function Component() {
const filteredData = chartData.filter((item) => {
const date = new Date(item.date)
const now = new Date()
const referenceDate = new Date("2024-06-30")
let daysToSubtract = 90
if (timeRange === "30d") {
daysToSubtract = 30
} else if (timeRange === "7d") {
daysToSubtract = 7
}
now.setDate(now.getDate() - daysToSubtract)
return date >= now
const startDate = new Date(referenceDate)
startDate.setDate(startDate.getDate() - daysToSubtract)
return date >= startDate
})
return (

View File

@@ -1,6 +1,7 @@
import { Metadata } from "next"
import Link from "next/link"
import { siteConfig } from "@/config/site"
import { Announcement } from "@/components/announcement"
import { ExamplesNav } from "@/components/examples-nav"
import {
@@ -25,20 +26,23 @@ export default function ExamplesLayout({ children }: ExamplesLayoutProps) {
<div className="relative">
<PageHeader>
<Announcement />
<PageHeaderHeading className="hidden md:block">
Check out some examples
</PageHeaderHeading>
<PageHeaderHeading className="md:hidden">Examples</PageHeaderHeading>
<PageHeaderHeading>Build your component library</PageHeaderHeading>
<PageHeaderDescription>
Dashboard, cards, authentication. Some examples built using the
components. Use this as a guide to build your own.
Beautifully designed components that you can copy and paste into your
apps. Made with Tailwind CSS. Open source.
</PageHeaderDescription>
<PageActions>
<Button asChild size="sm">
<Link href="/docs">Get Started</Link>
</Button>
<Button asChild size="sm" variant="ghost">
<Link href="/components">Components</Link>
<Link
target="_blank"
rel="noreferrer"
href={siteConfig.links.github}
>
GitHub
</Link>
</Button>
</PageActions>
</PageHeader>

View File

@@ -166,7 +166,7 @@ function BlockViewerToolbar() {
className="hidden h-7 w-7 rounded-md border bg-transparent shadow-none md:flex lg:w-auto"
size="sm"
onClick={() => {
copyToClipboard(`npx shadcn@latest add ${name}`)
copyToClipboard(`npx shadcn@latest add ${item.name}`)
}}
>
{isCopied ? <Check /> : <Terminal />}

View File

@@ -59,7 +59,7 @@ export function ExamplesNav({ className, ...props }: ExamplesNavProps) {
<div className="relative">
<ScrollArea className="max-w-[600px] lg:max-w-none">
<div className={cn("mb-4 flex items-center", className)} {...props}>
{examples.map((example, index) => (
{examples.map((example) => (
<Link
href={example.href}
key={example.href}

View File

@@ -12,7 +12,7 @@ export function MainNav() {
return (
<div className="mr-4 hidden md:flex">
<Link href="/" className="mr-4 flex items-center space-x-2 lg:mr-6">
<Link href="/" className="mr-4 flex items-center gap-2 lg:mr-6">
<Icons.logo className="h-6 w-6" />
<span className="hidden font-bold lg:inline-block">
{siteConfig.name}
@@ -23,7 +23,7 @@ export function MainNav() {
href="/docs"
className={cn(
"transition-colors hover:text-foreground/80",
pathname === "/docs" ? "text-foreground" : "text-foreground/60"
pathname === "/docs" ? "text-foreground" : "text-foreground/80"
)}
>
Docs
@@ -35,7 +35,7 @@ export function MainNav() {
pathname?.startsWith("/docs/components") &&
!pathname?.startsWith("/docs/component/chart")
? "text-foreground"
: "text-foreground/60"
: "text-foreground/80"
)}
>
Components
@@ -46,7 +46,7 @@ export function MainNav() {
"transition-colors hover:text-foreground/80",
pathname?.startsWith("/blocks")
? "text-foreground"
: "text-foreground/60"
: "text-foreground/80"
)}
>
Blocks
@@ -58,7 +58,7 @@ export function MainNav() {
pathname?.startsWith("/docs/component/chart") ||
pathname?.startsWith("/charts")
? "text-foreground"
: "text-foreground/60"
: "text-foreground/80"
)}
>
Charts
@@ -69,29 +69,18 @@ export function MainNav() {
"transition-colors hover:text-foreground/80",
pathname?.startsWith("/themes")
? "text-foreground"
: "text-foreground/60"
: "text-foreground/80"
)}
>
Themes
</Link>
<Link
href="/examples"
className={cn(
"hidden transition-colors hover:text-foreground/80 lg:inline-block",
pathname?.startsWith("/examples")
? "text-foreground"
: "text-foreground/60"
)}
>
Examples
</Link>
<Link
href="/colors"
className={cn(
"transition-colors hover:text-foreground/80",
pathname?.startsWith("/colors")
? "text-foreground"
: "text-foreground/60"
: "text-foreground/80"
)}
>
Colors

View File

@@ -1,7 +1,7 @@
"use client"
import * as React from "react"
import template from "lodash.template"
import template from "lodash/template"
import { Check, Copy, Moon, Repeat, Sun } from "lucide-react"
import { useTheme } from "next-themes"

View File

@@ -32,10 +32,6 @@ export const docsConfig: DocsConfig = {
title: "Themes",
href: "/themes",
},
{
title: "Examples",
href: "/examples",
},
{
title: "Colors",
href: "/colors",

View File

@@ -5,7 +5,7 @@ description: Every component recreated in Figma. With customizable props, typogr
## Paid
- [shadcn/ui kit](http://shadcndesign.com) by [ Matt Wierzbicki](https://x.com/matsugfx) - A premium, always up-to-date UI kit for Figma - shadcn/ui compatible and optimized for smooth design-to-dev handoff.
- [shadcn/ui kit](https://shadcndesign.com) by [ Matt Wierzbicki](https://x.com/matsugfx) - A premium, always up-to-date UI kit for Figma - shadcn/ui compatible and optimized for smooth design-to-dev handoff.
## Free

View File

@@ -16,22 +16,14 @@ Components are styled using Tailwind CSS. You need to install Tailwind CSS in yo
Add the following dependencies to your project:
```bash
npm install tailwindcss-animate class-variance-authority clsx tailwind-merge
```
### Add icon library
If you're using the `default` style, install `lucide-react`:
```bash
npm install lucide-react
npm install tailwindcss-animate class-variance-authority clsx tailwind-merge lucide-react
```
### Configure path aliases
I use the `@` alias. This is how I configure it in tsconfig.json:
Configure the path aliases in your `tsconfig.json` file.
```json {3-6} title="tsconfig.json"
```json {3-6} title="tsconfig.json" showLineNumbers
{
"compilerOptions": {
"baseUrl": ".",
@@ -44,27 +36,16 @@ I use the `@` alias. This is how I configure it in tsconfig.json:
The `@` alias is a preference. You can use other aliases if you want.
**If you use a different alias such as ~, you'll need to update import statements when adding components.**
### Configure tailwind.config.js
Here's what my `tailwind.config.js` file looks like:
```js title="tailwind.config.js"
const { fontFamily } = require("tailwindcss/defaultTheme")
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: ["class"],
content: ["app/**/*.{ts,tsx}", "components/**/*.{ts,tsx}"],
theme: {
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px",
},
},
extend: {
colors: {
border: "hsl(var(--border))",
@@ -106,23 +87,6 @@ module.exports = {
md: `calc(var(--radius) - 2px)`,
sm: "calc(var(--radius) - 4px)",
},
fontFamily: {
sans: ["var(--font-sans)", ...fontFamily.sans],
},
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",
},
},
},
plugins: [require("tailwindcss-animate")],
@@ -142,67 +106,46 @@ Add the following to your styles/globals.css file. You can learn more about usin
:root {
--background: 0 0% 100%;
--foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 47.4% 11.2%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--card: 0 0% 100%;
--card-foreground: 222.2 47.4% 11.2%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 100% 50%;
--destructive-foreground: 210 40% 98%;
--ring: 215 20.2% 65.1%;
--radius: 0.5rem;
}
.dark {
--background: 224 71% 4%;
--foreground: 213 31% 91%;
--muted: 223 47% 11%;
--muted-foreground: 215.4 16.3% 56.9%;
--accent: 216 34% 17%;
--accent-foreground: 210 40% 98%;
--popover: 224 71% 4%;
--popover-foreground: 215 20.2% 65.1%;
--border: 216 34% 17%;
--input: 216 34% 17%;
--card: 224 71% 4%;
--card-foreground: 213 31% 91%;
--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 1.2%;
--secondary: 222.2 47.4% 11.2%;
--secondary-foreground: 210 40% 98%;
--destructive: 0 63% 31%;
--destructive-foreground: 210 40% 98%;
--ring: 216 34% 17%;
--radius: 0.5rem;
}
}
@@ -211,17 +154,14 @@ Add the following to your styles/globals.css file. You can learn more about usin
@apply border-border;
}
body {
@apply bg-background text-foreground;
font-feature-settings: "rlig" 1, "calt" 1;
@apply font-sans antialiased bg-background text-foreground;
}
}
```
### Add a cn helper
I use a `cn` helper to make it easier to conditionally add Tailwind CSS classes. Here's how I define it in `lib/utils.ts`:
```ts title="lib/utils.ts"
```ts title="lib/utils.ts" showLineNumbers
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
@@ -230,6 +170,34 @@ export function cn(...inputs: ClassValue[]) {
}
```
### Create a `components.json` file
Create a `components.json` file in the root of your project.
```json title="components.json" showLineNumbers
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "src/index.css",
"baseColor": "zinc",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"iconLibrary": "lucide"
}
```
### That's it
You can now start adding components to your project.

View File

@@ -67,7 +67,7 @@
"geist": "^1.2.2",
"input-otp": "^1.2.2",
"jotai": "^2.1.0",
"lodash.template": "^4.5.0",
"lodash": "^4.17.21",
"lucide-react": "0.359.0",
"markdown-wasm": "^1.2.0",
"next": "14.3.0-canary.43",
@@ -90,7 +90,7 @@
},
"devDependencies": {
"@shikijs/compat": "^1.1.7",
"@types/lodash.template": "^4.5.1",
"@types/lodash": "^4.17.7",
"@types/node": "^17.0.45",
"@types/react": "^18.2.65",
"@types/react-color": "^3.0.6",

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,7 @@
"files": [
{
"path": "ui/input.tsx",
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport interface InputProps\n extends React.InputHTMLAttributes<HTMLInputElement> {}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n className={cn(\n \"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n className\n )}\n ref={ref}\n {...props}\n />\n )\n }\n)\nInput.displayName = \"Input\"\n\nexport { Input }\n",
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Input = React.forwardRef<HTMLInputElement, React.ComponentProps<\"input\">>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n className={cn(\n \"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n className\n )}\n ref={ref}\n {...props}\n />\n )\n }\n)\nInput.displayName = \"Input\"\n\nexport { Input }\n",
"type": "registry:ui",
"target": ""
}

View File

@@ -4,7 +4,7 @@
"files": [
{
"path": "ui/textarea.tsx",
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport interface TextareaProps\n extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, ...props }, ref) => {\n return (\n <textarea\n className={cn(\n \"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n className\n )}\n ref={ref}\n {...props}\n />\n )\n }\n)\nTextarea.displayName = \"Textarea\"\n\nexport { Textarea }\n",
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Textarea = React.forwardRef<\n HTMLTextAreaElement,\n React.ComponentProps<\"textarea\">\n>(({ className, ...props }, ref) => {\n return (\n <textarea\n className={cn(\n \"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n className\n )}\n ref={ref}\n {...props}\n />\n )\n})\nTextarea.displayName = \"Textarea\"\n\nexport { Textarea }\n",
"type": "registry:ui",
"target": ""
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,7 @@
"files": [
{
"path": "ui/input.tsx",
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport interface InputProps\n extends React.InputHTMLAttributes<HTMLInputElement> {}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n className={cn(\n \"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n className\n )}\n ref={ref}\n {...props}\n />\n )\n }\n)\nInput.displayName = \"Input\"\n\nexport { Input }\n",
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Input = React.forwardRef<HTMLInputElement, React.ComponentProps<\"input\">>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n className={cn(\n \"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n className\n )}\n ref={ref}\n {...props}\n />\n )\n }\n)\nInput.displayName = \"Input\"\n\nexport { Input }\n",
"type": "registry:ui",
"target": ""
}

View File

@@ -4,7 +4,7 @@
"files": [
{
"path": "ui/textarea.tsx",
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport interface TextareaProps\n extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, ...props }, ref) => {\n return (\n <textarea\n className={cn(\n \"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n className\n )}\n ref={ref}\n {...props}\n />\n )\n }\n)\nTextarea.displayName = \"Textarea\"\n\nexport { Textarea }\n",
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Textarea = React.forwardRef<\n HTMLTextAreaElement,\n React.ComponentProps<\"textarea\">\n>(({ className, ...props }, ref) => {\n return (\n <textarea\n className={cn(\n \"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n className\n )}\n ref={ref}\n {...props}\n />\n )\n})\nTextarea.displayName = \"Textarea\"\n\nexport { Textarea }\n",
"type": "registry:ui",
"target": ""
}

View File

@@ -23,9 +23,7 @@ const Command = React.forwardRef<
))
Command.displayName = CommandPrimitive.displayName
interface CommandDialogProps extends DialogProps {}
const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
const CommandDialog = ({ children, ...props }: DialogProps) => {
return (
<Dialog {...props}>
<DialogContent className="overflow-hidden p-0 shadow-lg">

View File

@@ -2,10 +2,7 @@ import * as React from "react"
import { cn } from "@/lib/utils"
export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {}
const Input = React.forwardRef<HTMLInputElement, InputProps>(
const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
({ className, type, ...props }, ref) => {
return (
<input

View File

@@ -2,23 +2,21 @@ import * as React from "react"
import { cn } from "@/lib/utils"
export interface TextareaProps
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
({ className, ...props }, ref) => {
return (
<textarea
className={cn(
"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
className
)}
ref={ref}
{...props}
/>
)
}
)
const Textarea = React.forwardRef<
HTMLTextAreaElement,
React.ComponentProps<"textarea">
>(({ className, ...props }, ref) => {
return (
<textarea
className={cn(
"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
className
)}
ref={ref}
{...props}
/>
)
})
Textarea.displayName = "Textarea"
export { Textarea }

View File

@@ -23,9 +23,7 @@ const Command = React.forwardRef<
))
Command.displayName = CommandPrimitive.displayName
interface CommandDialogProps extends DialogProps {}
const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
const CommandDialog = ({ children, ...props }: DialogProps) => {
return (
<Dialog {...props}>
<DialogContent className="overflow-hidden p-0">

View File

@@ -2,10 +2,7 @@ import * as React from "react"
import { cn } from "@/lib/utils"
export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {}
const Input = React.forwardRef<HTMLInputElement, InputProps>(
const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
({ className, type, ...props }, ref) => {
return (
<input

View File

@@ -2,23 +2,21 @@ import * as React from "react"
import { cn } from "@/lib/utils"
export interface TextareaProps
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
({ className, ...props }, ref) => {
return (
<textarea
className={cn(
"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
className
)}
ref={ref}
{...props}
/>
)
}
)
const Textarea = React.forwardRef<
HTMLTextAreaElement,
React.ComponentProps<"textarea">
>(({ className, ...props }, ref) => {
return (
<textarea
className={cn(
"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
className
)}
ref={ref}
{...props}
/>
)
})
Textarea.displayName = "Textarea"
export { Textarea }

View File

@@ -3,7 +3,7 @@ import { existsSync, promises as fs, readFileSync } from "fs"
import { tmpdir } from "os"
import path from "path"
import { cwd } from "process"
import template from "lodash.template"
import template from "lodash/template"
import { rimraf } from "rimraf"
import { Project, ScriptKind, SyntaxKind } from "ts-morph"
import { z } from "zod"

View File

@@ -1,5 +1,11 @@
# @shadcn/ui
## 0.9.4
### Patch Changes
- [#4397](https://github.com/shadcn-ui/ui/pull/4397) [`a1bed46`](https://github.com/shadcn-ui/ui/commit/a1bed464f329e9025a7fa1ae7dee094d4c9c6f44) Thanks [@JensAstrup](https://github.com/JensAstrup)! - replace lodash.template
## 0.9.3
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "shadcn-ui",
"version": "0.9.3",
"version": "0.9.4",
"description": "Add components to your apps.",
"publishConfig": {
"access": "public"
@@ -57,7 +57,7 @@
"fast-glob": "^3.3.2",
"fs-extra": "^11.1.0",
"https-proxy-agent": "^6.2.0",
"lodash.template": "^4.5.0",
"lodash": "^4.17.21",
"node-fetch": "^3.3.0",
"ora": "^6.1.2",
"prompts": "^2.4.2",
@@ -70,7 +70,7 @@
"@types/babel__core": "^7.20.1",
"@types/diff": "^5.0.3",
"@types/fs-extra": "^11.0.1",
"@types/lodash.template": "^4.5.1",
"@types/lodash": "^4.17.7",
"@types/prompts": "^2.4.2",
"rimraf": "^4.1.3",
"tsup": "^6.6.3",

View File

@@ -24,7 +24,7 @@ import * as templates from "@/src/utils/templates"
import chalk from "chalk"
import { Command } from "commander"
import { execa } from "execa"
import template from "lodash.template"
import template from "lodash/template"
import ora from "ora"
import prompts from "prompts"
import { z } from "zod"

View File

@@ -1,5 +1,15 @@
# @shadcn/ui
## 2.1.7
### Patch Changes
- [#5711](https://github.com/shadcn-ui/ui/pull/5711) [`500dbe2`](https://github.com/shadcn-ui/ui/commit/500dbe2664c04936cc3edb739fc97f6cecff57c5) Thanks [@bcorbold](https://github.com/bcorbold)! - Update spread/unspread helpers to handle ArrayLiteralExpression and nested values within arrays
- [#5678](https://github.com/shadcn-ui/ui/pull/5678) [`fb36ca4`](https://github.com/shadcn-ui/ui/commit/fb36ca41591ae952f3a015e2a4470f26458cf1b5) Thanks [@Tobbe](https://github.com/Tobbe)! - support aliases longer than one char
- [#5813](https://github.com/shadcn-ui/ui/pull/5813) [`d5bf001`](https://github.com/shadcn-ui/ui/commit/d5bf0018fda42faeb314dc3edc87b8cd7c0354c6) Thanks [@shadcn](https://github.com/shadcn)! - fix handling of aliases
## 2.1.6
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "shadcn",
"version": "2.1.6",
"version": "2.1.7",
"description": "Add components to your apps.",
"publishConfig": {
"access": "public"

View File

@@ -10,6 +10,7 @@ import { getPackageInfo } from "@/src/utils/get-package-info"
import fg from "fast-glob"
import fs from "fs-extra"
import { loadConfig } from "tsconfig-paths"
import { z } from "zod"
type ProjectInfo = {
framework: Framework
@@ -29,6 +30,12 @@ const PROJECT_SHARED_IGNORE = [
"build",
]
const TS_CONFIG_SCHEMA = z.object({
compilerOptions: z.object({
paths: z.record(z.string().or(z.array(z.string()))),
}),
})
export async function getProjectInfo(cwd: string): Promise<ProjectInfo | null> {
const [
configFiles,
@@ -153,7 +160,10 @@ export async function getTailwindConfigFile(cwd: string) {
export async function getTsConfigAliasPrefix(cwd: string) {
const tsConfig = await loadConfig(cwd)
if (tsConfig?.resultType === "failed" || !tsConfig?.paths) {
if (
tsConfig?.resultType === "failed" ||
!Object.entries(tsConfig?.paths).length
) {
return null
}
@@ -165,11 +175,12 @@ export async function getTsConfigAliasPrefix(cwd: string) {
paths.includes("./app/*") ||
paths.includes("./resources/js/*") // Laravel.
) {
return alias.at(0) ?? null
return alias.replace(/\/\*$/, "") ?? null
}
}
return null
// Use the first alias as the prefix.
return Object.keys(tsConfig?.paths)?.[0].replace(/\/\*$/, "") ?? null
}
export async function isTypeScriptProject(cwd: string) {
@@ -182,19 +193,30 @@ export async function isTypeScriptProject(cwd: string) {
return files.length > 0
}
export async function getTsConfig() {
try {
const tsconfigPath = path.join("tsconfig.json")
const tsconfig = await fs.readJSON(tsconfigPath)
if (!tsconfig) {
throw new Error("tsconfig.json is missing")
export async function getTsConfig(cwd: string) {
for (const fallback of [
"tsconfig.json",
"tsconfig.web.json",
"tsconfig.app.json",
]) {
const filePath = path.resolve(cwd, fallback)
if (!(await fs.pathExists(filePath))) {
continue
}
return tsconfig
} catch (error) {
return null
// We can't use fs.readJSON because it doesn't support comments.
const contents = await fs.readFile(filePath, "utf8")
const cleanedContents = contents.replace(/\/\*\s*\*\//g, "")
const result = TS_CONFIG_SCHEMA.safeParse(JSON.parse(cleanedContents))
if (result.error) {
continue
}
return result.data
}
return null
}
export async function getProjectConfig(

View File

@@ -35,8 +35,8 @@ function updateImportAliases(moduleSpecifier: string, config: Config) {
// Not a registry import.
if (!moduleSpecifier.startsWith("@/registry/")) {
// We fix the alias an return.
const alias = config.aliases.components.charAt(0)
// We fix the alias and return.
const alias = config.aliases.components.split("/")[0]
return moduleSpecifier.replace(/^@\//, `${alias}/`)
}

View File

@@ -9,6 +9,7 @@ import deepmerge from "deepmerge"
import objectToString from "stringify-object"
import { type Config as TailwindConfig } from "tailwindcss"
import {
ArrayLiteralExpression,
ObjectLiteralExpression,
Project,
PropertyAssignment,
@@ -194,8 +195,11 @@ async function addTailwindConfigTheme(
if (themeInitializer?.isKind(SyntaxKind.ObjectLiteralExpression)) {
const themeObjectString = themeInitializer.getText()
const themeObject = await parseObjectLiteral(themeObjectString)
const result = deepmerge(themeObject, theme)
const result = deepmerge(themeObject, theme, {
arrayMerge: (dst, src) => src,
})
const resultString = objectToString(result)
.replace(/\'\.\.\.(.*)\'/g, "...$1") // Remove quote around spread element
.replace(/\'\"/g, "'") // Replace `\" with "
.replace(/\"\'/g, "'") // Replace `\" with "
.replace(/\'\[/g, "[") // Replace `[ with [
@@ -287,7 +291,8 @@ export function nestSpreadProperties(obj: ObjectLiteralExpression) {
// Replace spread with a property assignment
obj.insertPropertyAssignment(i, {
name: `___${spreadText.replace(/^\.\.\./, "")}`,
// Need to escape the name with " so that deepmerge doesn't mishandle the key
name: `"___${spreadText.replace(/^\.\.\./, "")}"`,
initializer: `"...${spreadText.replace(/^\.\.\./, "")}"`,
})
@@ -305,11 +310,41 @@ export function nestSpreadProperties(obj: ObjectLiteralExpression) {
nestSpreadProperties(
initializer.asKindOrThrow(SyntaxKind.ObjectLiteralExpression)
)
} else if (
initializer &&
initializer.isKind(SyntaxKind.ArrayLiteralExpression)
) {
nestSpreadElements(
initializer.asKindOrThrow(SyntaxKind.ArrayLiteralExpression)
)
}
}
}
}
export function nestSpreadElements(arr: ArrayLiteralExpression) {
const elements = arr.getElements()
for (let j = 0; j < elements.length; j++) {
const element = elements[j]
if (element.isKind(SyntaxKind.ObjectLiteralExpression)) {
// Recursive check on objects within arrays
nestSpreadProperties(
element.asKindOrThrow(SyntaxKind.ObjectLiteralExpression)
)
} else if (element.isKind(SyntaxKind.ArrayLiteralExpression)) {
// Recursive check on nested arrays
nestSpreadElements(
element.asKindOrThrow(SyntaxKind.ArrayLiteralExpression)
)
} else if (element.isKind(SyntaxKind.SpreadElement)) {
const spreadText = element.getText()
// Spread element within an array
arr.removeElement(j)
arr.insertElement(j, `"${spreadText}"`)
}
}
}
export function unnestSpreadProperties(obj: ObjectLiteralExpression) {
const properties = obj.getProperties()
@@ -319,14 +354,49 @@ export function unnestSpreadProperties(obj: ObjectLiteralExpression) {
const propAssignment = prop as PropertyAssignment
const initializer = propAssignment.getInitializer()
if (initializer?.isKind(SyntaxKind.StringLiteral)) {
const value = initializer.getLiteralValue()
if (initializer && initializer.isKind(SyntaxKind.StringLiteral)) {
const value = initializer
.asKindOrThrow(SyntaxKind.StringLiteral)
.getLiteralValue()
if (value.startsWith("...")) {
obj.insertSpreadAssignment(i, { expression: value.slice(3) })
propAssignment.remove()
}
} else if (initializer?.isKind(SyntaxKind.ObjectLiteralExpression)) {
unnestSpreadProperties(initializer as ObjectLiteralExpression)
} else if (
initializer &&
initializer.isKind(SyntaxKind.ArrayLiteralExpression)
) {
unnsetSpreadElements(
initializer.asKindOrThrow(SyntaxKind.ArrayLiteralExpression)
)
}
}
}
}
export function unnsetSpreadElements(arr: ArrayLiteralExpression) {
const elements = arr.getElements()
for (let j = 0; j < elements.length; j++) {
const element = elements[j]
if (element.isKind(SyntaxKind.ObjectLiteralExpression)) {
// Recursive check on objects within arrays
unnestSpreadProperties(
element.asKindOrThrow(SyntaxKind.ObjectLiteralExpression)
)
} else if (element.isKind(SyntaxKind.ArrayLiteralExpression)) {
// Recursive check on nested arrays
unnsetSpreadElements(
element.asKindOrThrow(SyntaxKind.ArrayLiteralExpression)
)
} else if (element.isKind(SyntaxKind.StringLiteral)) {
const spreadText = element.getText()
// check if spread element
const spreadTest = /(?:^['"])(\.\.\..*)(?:['"]$)/g
if (spreadTest.test(spreadText)) {
arr.removeElement(j)
arr.insertElement(j, spreadText.replace(spreadTest, "$1"))
}
}
}
@@ -363,6 +433,12 @@ function parseObjectLiteralExpression(node: ObjectLiteralExpression): any {
result[name] = parseObjectLiteralExpression(
property.getInitializer() as ObjectLiteralExpression
)
} else if (
property.getInitializer()?.isKind(SyntaxKind.ArrayLiteralExpression)
) {
result[name] = parseArrayLiteralExpression(
property.getInitializer() as ArrayLiteralExpression
)
} else {
result[name] = parseValue(property.getInitializer())
}
@@ -371,12 +447,34 @@ function parseObjectLiteralExpression(node: ObjectLiteralExpression): any {
return result
}
function parseArrayLiteralExpression(node: ArrayLiteralExpression): any[] {
const result: any[] = []
for (const element of node.getElements()) {
if (element.isKind(SyntaxKind.ObjectLiteralExpression)) {
result.push(
parseObjectLiteralExpression(
element.asKindOrThrow(SyntaxKind.ObjectLiteralExpression)
)
)
} else if (element.isKind(SyntaxKind.ArrayLiteralExpression)) {
result.push(
parseArrayLiteralExpression(
element.asKindOrThrow(SyntaxKind.ArrayLiteralExpression)
)
)
} else {
result.push(parseValue(element))
}
}
return result
}
function parseValue(node: any): any {
switch (node.kind) {
switch (node.getKind()) {
case SyntaxKind.StringLiteral:
return node.text
return node.getText()
case SyntaxKind.NumericLiteral:
return Number(node.text)
return Number(node.getText())
case SyntaxKind.TrueKeyword:
return true
case SyntaxKind.FalseKeyword:
@@ -384,7 +482,9 @@ function parseValue(node: any): any {
case SyntaxKind.NullKeyword:
return null
case SyntaxKind.ArrayLiteralExpression:
return node.elements.map(parseValue)
return node.getElements().map(parseValue)
case SyntaxKind.ObjectLiteralExpression:
return parseObjectLiteralExpression(node)
default:
return node.getText()
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -0,0 +1,27 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
--background-end-rgb: 255, 255, 255;
}
@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
--background-start-rgb: 0, 0, 0;
--background-end-rgb: 0, 0, 0;
}
}
body {
color: rgb(var(--foreground-rgb));
background: linear-gradient(
to bottom,
transparent,
rgb(var(--background-end-rgb))
)
rgb(var(--background-start-rgb));
}

View File

@@ -0,0 +1,22 @@
import './globals.css'
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
)
}

View File

@@ -0,0 +1,3 @@
body {
background-color: red;
}

View File

@@ -0,0 +1,113 @@
import Image from 'next/image'
export default function Home() {
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<div className="z-10 max-w-5xl w-full items-center justify-between font-mono text-sm lg:flex">
<p className="fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl dark:border-neutral-800 dark:bg-zinc-800/30 dark:from-inherit lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4 lg:dark:bg-zinc-800/30">
Get started by editing&nbsp;
<code className="font-mono font-bold">app/page.tsx</code>
</p>
<div className="fixed bottom-0 left-0 flex h-48 w-full items-end justify-center bg-gradient-to-t from-white via-white dark:from-black dark:via-black lg:static lg:h-auto lg:w-auto lg:bg-none">
<a
className="pointer-events-none flex place-items-center gap-2 p-8 lg:pointer-events-auto lg:p-0"
href="https://vercel.com?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
By{' '}
<Image
src="/vercel.svg"
alt="Vercel Logo"
className="dark:invert"
width={100}
height={24}
priority
/>
</a>
</div>
</div>
<div className="relative flex place-items-center before:absolute before:h-[300px] before:w-[480px] before:-translate-x-1/2 before:rounded-full before:bg-gradient-radial before:from-white before:to-transparent before:blur-2xl before:content-[''] after:absolute after:-z-20 after:h-[180px] after:w-[240px] after:translate-x-1/3 after:bg-gradient-conic after:from-sky-200 after:via-blue-200 after:blur-2xl after:content-[''] before:dark:bg-gradient-to-br before:dark:from-transparent before:dark:to-blue-700 before:dark:opacity-10 after:dark:from-sky-900 after:dark:via-[#0141ff] after:dark:opacity-40 before:lg:h-[360px] z-[-1]">
<Image
className="relative dark:drop-shadow-[0_0_0.3rem_#ffffff70] dark:invert"
src="/next.svg"
alt="Next.js Logo"
width={180}
height={37}
priority
/>
</div>
<div className="mb-32 grid text-center lg:max-w-5xl lg:w-full lg:mb-0 lg:grid-cols-4 lg:text-left">
<a
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
target="_blank"
rel="noopener noreferrer"
>
<h2 className={`mb-3 text-2xl font-semibold`}>
Docs{' '}
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
-&gt;
</span>
</h2>
<p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
Find in-depth information about Next.js features and API.
</p>
</a>
<a
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
target="_blank"
rel="noopener noreferrer"
>
<h2 className={`mb-3 text-2xl font-semibold`}>
Learn{' '}
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
-&gt;
</span>
</h2>
<p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
Learn about Next.js in an interactive course with&nbsp;quizzes!
</p>
</a>
<a
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
target="_blank"
rel="noopener noreferrer"
>
<h2 className={`mb-3 text-2xl font-semibold`}>
Templates{' '}
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
-&gt;
</span>
</h2>
<p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
Explore the Next.js 13 playground.
</p>
</a>
<a
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
target="_blank"
rel="noopener noreferrer"
>
<h2 className={`mb-3 text-2xl font-semibold`}>
Deploy{' '}
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
-&gt;
</span>
</h2>
<p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
Instantly deploy your Next.js site to a shareable URL with Vercel.
</p>
</a>
</div>
</main>
)
}

View File

@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

View File

@@ -0,0 +1,4 @@
/** @type {import('next').NextConfig} */
const nextConfig = {}
module.exports = nextConfig

View File

@@ -0,0 +1,11 @@
{
"name": "test-cli-next-app",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
}
}

View File

@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

View File

@@ -0,0 +1,21 @@
// @ts-nocheck
import type { Config } from 'tailwindcss'
const config: Config = {
content: [
'./pages/**/*.{js,ts,jsx,tsx,mdx}',
'./components/**/*.{js,ts,jsx,tsx,mdx}',
'./app/**/*.{js,ts,jsx,tsx,mdx}'
],
theme: {
extend: {
backgroundImage: {
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
'gradient-conic':
'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))'
}
}
},
plugins: []
}
export default config

View File

@@ -0,0 +1,27 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@custom-alias/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}

View File

@@ -58,3 +58,14 @@ import { Foo } from "bar"
import { bar } from "~/lib/utils/bar"
"
`;
exports[`transform import 6`] = `
"import * as React from "react"
import { Foo } from "bar"
import { Button } from "@custom-alias/components/ui/button"
import { Label} from "ui/label"
import { Box } from "@custom-alias/components/box"
import { cn } from "@custom-alias/lib/utils"
"
`;

View File

@@ -25,6 +25,10 @@ describe("get ts config alias prefix", async () => {
name: "t3-app",
prefix: "~",
},
{
name: "next-app-custom-alias",
prefix: "@custom-alias",
},
])(`getTsConfigAliasPrefix($name) -> $prefix`, async ({ name, prefix }) => {
expect(
await getTsConfigAliasPrefix(

View File

@@ -28,6 +28,7 @@ export function cn(...inputs: ClassValue[]) {
}
",
"path": "lib/utils.ts",
"target": "",
"type": "registry:lib",
},
{
@@ -238,10 +239,7 @@ export { Button, buttonVariants }
import { cn } from "@/lib/utils"
export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {}
const Input = React.forwardRef<HTMLInputElement, InputProps>(
const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
({ className, type, ...props }, ref) => {
return (
<input
@@ -290,9 +288,7 @@ const Command = React.forwardRef<
))
Command.displayName = CommandPrimitive.displayName
interface CommandDialogProps extends DialogProps {}
const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
const CommandDialog = ({ children, ...props }: DialogProps) => {
return (
<Dialog {...props}>
<DialogContent className="overflow-hidden p-0 shadow-lg">

View File

@@ -117,4 +117,29 @@ import { Foo } from "bar"
},
})
).toMatchSnapshot()
expect(
await transform({
filename: "test.ts",
raw: `import * as React from "react"
import { Foo } from "bar"
import { Button } from "@/components/ui/button"
import { Label} from "ui/label"
import { Box } from "@/registry/new-york/box"
import { cn } from "@/lib/utils"
`,
config: {
tsx: true,
tailwind: {
baseColor: "neutral",
cssVariables: true,
},
aliases: {
components: "@custom-alias/components",
utils: "@custom-alias/lib/utils",
},
},
})
).toMatchSnapshot()
})

View File

@@ -324,8 +324,14 @@ const config: Config = {
theme: {
extend: {
fontFamily: {
sans: ["var(--font-geist-sans)", ...fontFamily.sans],
mono: ["var(--font-mono)", ...fontFamily.mono],
sans: [
'var(--font-geist-sans)',
...fontFamily.sans
],
mono: [
'var(--font-mono)',
...fontFamily.mono
],
heading: [
'var(--font-geist-sans)'
]
@@ -369,6 +375,75 @@ export default config
"
`;
exports[`transformTailwindConfig -> theme > should handle objects nested in arrays 1`] = `
"import type { Config } from 'tailwindcss'
const config: Config = {
darkMode: ["class"],
content: [
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
fontSize: {
xs: [
'0.75rem',
{
lineHeight: '1rem'
}
],
sm: [
'0.875rem',
{
lineHeight: '1.25rem'
}
],
xl: [
'clamp(1.5rem, 1.04vi + 1.17rem, 2rem)',
{
lineHeight: '1.2',
letterSpacing: '-0.02em',
fontWeight: '600'
}
]
}
}
},
}
export default config
"
`;
exports[`transformTailwindConfig -> theme > should keep arrays when formatted on multilines 1`] = `
"import type { Config } from 'tailwindcss'
const config: Config = {
darkMode: ["class"],
content: [
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
fontFamily: {
sans: [
'Figtree',
...defaultTheme.fontFamily.sans
],
mono: [
'Foo'
]
}
}
},
}
export default config
"
`;
exports[`transformTailwindConfig -> theme > should keep quotes in strings 1`] = `
"import type { Config } from 'tailwindcss'
@@ -382,7 +457,10 @@ const config: Config = {
theme: {
extend: {
fontFamily: {
sans: ['Figtree', ...defaultTheme.fontFamily.sans]
sans: [
'Figtree',
...defaultTheme.fontFamily.sans
]
},
colors: {
...defaultColors,
@@ -448,6 +526,12 @@ const config: Config = {
],
theme: {
extend: {
fontFamily: {
sans: [
'ui-sans-serif',
'sans-serif'
]
},
colors: {
background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))',
@@ -466,3 +550,23 @@ const config: Config = {
export default config
"
`;
exports[`transformTailwindConfig -> theme > should preserve boolean values 1`] = `
"import type { Config } from 'tailwindcss'
const config: Config = {
darkMode: ["class"],
content: [
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
container: {
center: true
}
},
}
export default config
"
`;

View File

@@ -2,10 +2,10 @@ import { Project, SyntaxKind } from "ts-morph"
import { beforeEach, describe, expect, test } from "vitest"
import {
buildTailwindThemeColorsFromCssVars,
buildTailwindThemeColorsFromCssVars, nestSpreadElements,
nestSpreadProperties,
transformTailwindConfig,
unnestSpreadProperties,
unnestSpreadProperties, unnsetSpreadElements,
} from "../../../src/utils/updaters/update-tailwind-config"
const SHARED_CONFIG = {
@@ -522,6 +522,12 @@ const config: Config = {
],
theme: {
extend: {
fontFamily: {
sans: [
"ui-sans-serif",
"sans-serif",
],
},
colors: {
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
@@ -809,6 +815,123 @@ export default config
)
).toMatchSnapshot()
})
test("should keep arrays when formatted on multilines", async () => {
expect(
await transformTailwindConfig(
`import type { Config } from 'tailwindcss'
const config: Config = {
content: [
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
fontFamily: {
sans: [
'Figtree',
...defaultTheme.fontFamily.sans
],
},
},
},
}
export default config
`,
{
theme: {
extend: {
fontFamily: {
mono: ['Foo']
}
},
},
},
{
config: SHARED_CONFIG,
}
)
).toMatchSnapshot()
})
test("should handle objects nested in arrays", async () => {
expect(
await transformTailwindConfig(
`import type { Config } from 'tailwindcss'
const config: Config = {
content: [
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
fontSize: {
xs: ['0.75rem', { lineHeight: '1rem' }],
sm: [
'0.875rem',
{
lineHeight: '1.25rem',
},
],
},
},
},
}
export default config
`,
{
theme: {
extend: {
fontSize: {
xl: [
'clamp(1.5rem, 1.04vi + 1.17rem, 2rem)',
{
lineHeight: '1.2',
letterSpacing: '-0.02em',
fontWeight: '600',
},
],
}
},
},
},
{
config: SHARED_CONFIG,
}
)
).toMatchSnapshot()
})
test("should preserve boolean values", async () => {
expect(
await transformTailwindConfig(
`import type { Config } from 'tailwindcss'
const config: Config = {
content: [
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
container: {
center: true
}
},
}
export default config
`,
{},
{
config: SHARED_CONFIG,
}
)
).toMatchSnapshot()
})
})
describe("nestSpreadProperties", () => {
@@ -837,36 +960,137 @@ describe("nestSpreadProperties", () => {
test("should nest spread properties", () => {
testTransformation(
`{ theme: { ...foo, bar: { ...baz, one: "two" }, other: { a: "b", ...c } } }`,
`{ theme: { ___foo: "...foo", bar: { ___baz: "...baz", one: "two" }, other: { a: "b", ___c: "...c" } } }`
`{ theme: { "___foo": "...foo", bar: { "___baz": "...baz", one: "two" }, other: { a: "b", "___c": "...c" } } }`
)
})
test("should handle mixed property assignments", () => {
testTransformation(
`{ ...foo, a: 1, b() {}, ...bar, c: { ...baz } }`,
`{ ___foo: "...foo", a: 1, b() {}, ___bar: "...bar", c: { ___baz: "...baz" } }`
`{ "___foo": "...foo", a: 1, b() {}, "___bar": "...bar", c: { "___baz": "...baz" } }`
)
})
test("should handle objects with only spread properties", () => {
testTransformation(
`{ ...foo, ...bar, ...baz }`,
`{ ___foo: "...foo", ___bar: "...bar", ___baz: "...baz" }`
`{ "___foo": "...foo", "___bar": "...bar", "___baz": "...baz" }`
)
})
test("should handle property name conflicts", () => {
testTransformation(`{ foo: 1, ...foo }`, `{ foo: 1, ___foo: "...foo" }`)
testTransformation(`{ foo: 1, ...foo }`, `{ foo: 1, "___foo": "...foo" }`)
})
test("should handle shorthand property names", () => {
testTransformation(`{ a, ...foo, b }`, `{ a, ___foo: "...foo", b }`)
testTransformation(`{ a, ...foo, b }`, `{ a, "___foo": "...foo", b }`)
})
test("should handle computed property names", () => {
testTransformation(
`{ ["computed"]: 1, ...foo }`,
`{ ["computed"]: 1, ___foo: "...foo" }`
`{ ["computed"]: 1, "___foo": "...foo" }`
)
})
test("should handle spreads in arrays", () => {
testTransformation(
`{ foo: [{ ...bar }] }`,
`{ foo: [{ "___bar": "...bar" }] }`
)
})
test("should handle deep nesting in arrays", () => {
testTransformation(
`{ foo: [{ baz: { ...other.baz }, ...bar }] }`,
`{ foo: [{ baz: { "___other.baz": "...other.baz" }, "___bar": "...bar" }] }`
)
})
})
describe("nestSpreadElements", () => {
let project: Project
beforeEach(() => {
project = new Project({ useInMemoryFileSystem: true })
})
function testTransformation(input: string, expected: string) {
const sourceFile = project.createSourceFile(
"test.ts",
`const config = ${input};`
)
const configObject = sourceFile.getFirstDescendantByKind(
SyntaxKind.ArrayLiteralExpression
)
if (!configObject) throw new Error("Config object not found")
nestSpreadElements(configObject)
const result = configObject.getText()
expect(result.replace(/\s+/g, "")).toBe(expected.replace(/\s+/g, ""))
}
test("should spread elements", () => {
testTransformation(
`[...bar]`,
`["...bar"]`
)
})
test("should handle mixed element types", () => {
testTransformation(
`['foo', 2, true, ...bar, "baz"]`,
`['foo', 2, true, "...bar", "baz"]`
)
})
test("should handle arrays with only spread elements", () => {
testTransformation(
`[...foo, ...foo.bar, ...baz]`,
`["...foo", "...foo.bar", "...baz"]`
)
})
test("should handle nested arrays with spreads", () => {
testTransformation(
`[...foo, [...bar]]`,
`["...foo", ["...bar"]]`
)
})
test("should handle nested arrays within objects", () => {
testTransformation(
`[{ foo: [...foo] }]`,
`[{ foo: ["...foo"] }]`
)
})
test("should handle deeply nested arrays within spread objects", () => {
testTransformation(
`[{ foo: [...foo, { bar: ['bar', ...bar ]}] }]`,
`[{ foo: ["...foo", { bar: ['bar', "...bar" ]}] }]`
)
})
test("should handle optional paths in spread", () => {
testTransformation(
`[{ foo: [...foo?.bar] }]`,
`[{ foo: ["...foo?.bar"] }]`
)
})
test('should handle computed property paths within spread', () => {
testTransformation(
`[{ foo: [...foo["bar"]] }]`,
`[{ foo: ["...foo["bar"]"] }]`
)
})
test('should handle indexed paths in spread', () => {
testTransformation(
`[{ foo: [...foo[0]] }]`,
`[{ foo: ["...foo[0]"] }]`
)
})
})
@@ -925,10 +1149,119 @@ describe("unnestSpreadProperties", () => {
test("should handle computed property names", () => {
testTransformation(
`{ ["computed"]: 1, ___foo: "...foo" }`,
`{ ["computed"]: 1, "___foo": "...foo" }`,
`{ ["computed"]: 1, ...foo }`
)
})
test("should handle spread objects within arrays", () => {
testTransformation(
`{ ["computed"]: 1, foo: [{ "___foo": "...foo" }] }`,
`{ ["computed"]: 1, foo: [{...foo}] }`
)
})
test("should handle deeply nested spread objects within an array", () => {
testTransformation(
`{ ["computed"]: 1, foo: [{ "___foo": "...foo", bar: { baz: 'baz', "___foo.bar": "...foo.bar" } }] }`,
`{ ["computed"]: 1, foo: [{...foo, bar: { baz: 'baz', ...foo.bar } }] }`
)
})
})
describe("unnestSpreadElements", () => {
let project: Project
beforeEach(() => {
project = new Project({ useInMemoryFileSystem: true })
})
function testTransformation(input: string, expected: string) {
const sourceFile = project.createSourceFile(
"test.ts",
`const config = ${input};`
)
const configObject = sourceFile.getFirstDescendantByKind(
SyntaxKind.ArrayLiteralExpression
)
if (!configObject) throw new Error("Config object not found")
unnsetSpreadElements(configObject)
const result = configObject.getText()
expect(result.replace(/\s+/g, "")).toBe(expected.replace(/\s+/g, ""))
}
test("should spread elements", () => {
testTransformation(
`["...bar"]`,
`[...bar]`,
)
})
test("should handle mixed element types", () => {
testTransformation(
`['foo', 2, true, "...bar", "baz"]`,
`['foo', 2, true, ...bar, "baz"]`,
)
})
test("should handle arrays with only spread elements", () => {
testTransformation(
`["...foo", "...foo.bar", "...baz"]`,
`[...foo, ...foo.bar, ...baz]`,
)
})
test("should handle nested arrays with spreads", () => {
testTransformation(
`["...foo", ["...bar"]]`,
`[...foo, [...bar]]`,
)
})
test("should handle nested arrays within objects", () => {
testTransformation(
`[{ foo: ["...foo"] }]`,
`[{ foo: [...foo] }]`,
)
})
test("should handle deeply nested arrays within spread objects", () => {
testTransformation(
`[{ foo: ["...foo", { bar: ['bar', "...bar" ]}] }]`,
`[{ foo: [...foo, { bar: ['bar', ...bar ]}] }]`,
)
})
test("should handle optional paths in spread", () => {
testTransformation(
`[{ foo: ["...foo?.bar"] }]`,
`[{ foo: [...foo?.bar] }]`,
)
})
test("should handle computed property paths (') within spread", () => {
testTransformation(
`[{ foo: ["...foo['bar']"] }]`,
`[{ foo: [...foo['bar']] }]`,
)
})
test('should handle computed property paths (") within spread', () => {
testTransformation(
`[{ foo: ['...foo["bar"]'] }]`,
`[{ foo: [...foo["bar"]] }]`,
)
})
test('should handle indexed paths in spread', () => {
testTransformation(
`[{ foo: ["...foo[0]"] }]`,
`[{ foo: [...foo[0]] }]`,
)
})
})
describe("buildTailwindThemeColorsFromCssVars", () => {

66
pnpm-lock.yaml generated
View File

@@ -252,9 +252,9 @@ importers:
jotai:
specifier: ^2.1.0
version: 2.1.0(react@18.2.0)
lodash.template:
specifier: ^4.5.0
version: 4.5.0
lodash:
specifier: ^4.17.21
version: 4.17.21
lucide-react:
specifier: 0.359.0
version: 0.359.0(react@18.2.0)
@@ -316,9 +316,9 @@ importers:
'@shikijs/compat':
specifier: ^1.1.7
version: 1.1.7
'@types/lodash.template':
specifier: ^4.5.1
version: 4.5.1
'@types/lodash':
specifier: ^4.17.7
version: 4.17.7
'@types/node':
specifier: ^17.0.45
version: 17.0.45
@@ -421,9 +421,9 @@ importers:
https-proxy-agent:
specifier: ^6.2.0
version: 6.2.0
lodash.template:
specifier: ^4.5.0
version: 4.5.0
lodash:
specifier: ^4.17.21
version: 4.17.21
node-fetch:
specifier: ^3.3.0
version: 3.3.0
@@ -455,9 +455,9 @@ importers:
'@types/fs-extra':
specifier: ^11.0.1
version: 11.0.1
'@types/lodash.template':
specifier: ^4.5.1
version: 4.5.1
'@types/lodash':
specifier: ^4.17.7
version: 4.17.7
'@types/prompts':
specifier: ^2.4.2
version: 2.4.2
@@ -466,7 +466,7 @@ importers:
version: 4.1.3
tsup:
specifier: ^6.6.3
version: 6.6.3(postcss@8.4.41)(ts-node@10.9.2(@types/node@20.11.27)(typescript@4.9.5))(typescript@4.9.5)
version: 6.6.3(postcss@8.4.41)(ts-node@10.9.2(@types/node@20.14.0)(typescript@4.9.5))(typescript@4.9.5)
type-fest:
specifier: ^3.8.0
version: 3.8.0
@@ -557,7 +557,7 @@ importers:
version: 11.0.1
'@types/lodash.template':
specifier: ^4.5.1
version: 4.5.1
version: 4.5.3
'@types/prompts':
specifier: ^2.4.2
version: 2.4.2
@@ -569,7 +569,7 @@ importers:
version: 6.0.1
tsup:
specifier: ^6.6.3
version: 6.6.3(postcss@8.4.41)(ts-node@10.9.2(@types/node@20.11.27)(typescript@4.9.5))(typescript@4.9.5)
version: 6.6.3(postcss@8.4.41)(ts-node@10.9.2(@types/node@20.14.0)(typescript@4.9.5))(typescript@4.9.5)
type-fest:
specifier: ^3.8.0
version: 3.8.0
@@ -2885,11 +2885,11 @@ packages:
'@types/keyv@3.1.4':
resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==}
'@types/lodash.template@4.5.1':
resolution: {integrity: sha512-0y71S2dGgmwdkSsyW95JBp8HSZchgKCsjr6F0lsT3eSMtaT3Nn9rcMHU1U4UKu6XjQT3YC6/PNwgFI7k9f+ltw==}
'@types/lodash.template@4.5.3':
resolution: {integrity: sha512-Mo0UYKLu1oXgkV9TVoXZLlXXjyIXlW7ZQRxi/4gQJmzJr63dmicE8gG0OkPjYTKBrBic852q0JzqrtNUWLBIyA==}
'@types/lodash@4.17.4':
resolution: {integrity: sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ==}
'@types/lodash@4.17.7':
resolution: {integrity: sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==}
'@types/mdast@3.0.15':
resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==}
@@ -7779,7 +7779,7 @@ snapshots:
'@types/node': 20.5.1
chalk: 4.1.2
cosmiconfig: 8.3.6(typescript@5.5.3)
cosmiconfig-typescript-loader: 4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.5.3))(ts-node@10.9.2(@types/node@20.11.27)(typescript@5.5.3))(typescript@5.5.3)
cosmiconfig-typescript-loader: 4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.5.3))(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.5.3))(typescript@5.5.3)
lodash.isplainobject: 4.0.6
lodash.merge: 4.6.2
lodash.uniq: 4.5.0
@@ -9802,11 +9802,11 @@ snapshots:
dependencies:
'@types/node': 20.14.0
'@types/lodash.template@4.5.1':
'@types/lodash.template@4.5.3':
dependencies:
'@types/lodash': 4.17.4
'@types/lodash': 4.17.7
'@types/lodash@4.17.4': {}
'@types/lodash@4.17.7': {}
'@types/mdast@3.0.15':
dependencies:
@@ -10514,7 +10514,7 @@ snapshots:
core-util-is@1.0.3: {}
cosmiconfig-typescript-loader@4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.5.3))(ts-node@10.9.2(@types/node@20.11.27)(typescript@5.5.3))(typescript@5.5.3):
cosmiconfig-typescript-loader@4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.5.3))(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.5.3))(typescript@5.5.3):
dependencies:
'@types/node': 20.5.1
cosmiconfig: 8.3.6(typescript@5.5.3)
@@ -11058,7 +11058,7 @@ snapshots:
debug: 4.3.5
enhanced-resolve: 5.16.1
eslint: 8.44.0
eslint-module-utils: 2.8.1(@typescript-eslint/parser@5.61.0(eslint@8.44.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.61.0(eslint@8.44.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.44.0))(eslint@8.44.0)
eslint-module-utils: 2.8.1(@typescript-eslint/parser@5.61.0(eslint@8.44.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.44.0)
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.61.0(eslint@8.44.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.44.0)
fast-glob: 3.3.2
get-tsconfig: 4.7.5
@@ -11070,7 +11070,7 @@ snapshots:
- eslint-import-resolver-webpack
- supports-color
eslint-module-utils@2.8.1(@typescript-eslint/parser@5.61.0(eslint@8.44.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.61.0(eslint@8.44.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.44.0))(eslint@8.44.0):
eslint-module-utils@2.8.1(@typescript-eslint/parser@5.61.0(eslint@8.44.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.44.0):
dependencies:
debug: 3.2.7
optionalDependencies:
@@ -11091,7 +11091,7 @@ snapshots:
doctrine: 2.1.0
eslint: 8.44.0
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.8.1(@typescript-eslint/parser@5.61.0(eslint@8.44.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.61.0(eslint@8.44.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.44.0))(eslint@8.44.0)
eslint-module-utils: 2.8.1(@typescript-eslint/parser@5.61.0(eslint@8.44.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.44.0)
hasown: 2.0.2
is-core-module: 2.13.1
is-glob: 4.0.3
@@ -13469,13 +13469,13 @@ snapshots:
camelcase-css: 2.0.1
postcss: 8.4.41
postcss-load-config@3.1.4(postcss@8.4.41)(ts-node@10.9.2(@types/node@20.11.27)(typescript@4.9.5)):
postcss-load-config@3.1.4(postcss@8.4.41)(ts-node@10.9.2(@types/node@20.14.0)(typescript@4.9.5)):
dependencies:
lilconfig: 2.1.0
yaml: 1.10.2
optionalDependencies:
postcss: 8.4.41
ts-node: 10.9.2(@types/node@20.11.27)(typescript@4.9.5)
ts-node: 10.9.2(@types/node@20.14.0)(typescript@4.9.5)
postcss-load-config@4.0.2(postcss@8.4.41)(ts-node@10.9.2(@types/node@17.0.45)(typescript@5.5.3)):
dependencies:
@@ -14661,14 +14661,14 @@ snapshots:
yn: 3.1.1
optional: true
ts-node@10.9.2(@types/node@20.11.27)(typescript@4.9.5):
ts-node@10.9.2(@types/node@20.14.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': 20.11.27
'@types/node': 20.14.0
acorn: 8.11.3
acorn-walk: 8.3.2
arg: 4.1.3
@@ -14721,7 +14721,7 @@ snapshots:
tslib@2.6.2: {}
tsup@6.6.3(postcss@8.4.41)(ts-node@10.9.2(@types/node@20.11.27)(typescript@4.9.5))(typescript@4.9.5):
tsup@6.6.3(postcss@8.4.41)(ts-node@10.9.2(@types/node@20.14.0)(typescript@4.9.5))(typescript@4.9.5):
dependencies:
bundle-require: 4.2.1(esbuild@0.17.19)
cac: 6.7.14
@@ -14731,7 +14731,7 @@ snapshots:
execa: 5.1.1
globby: 11.1.0
joycon: 3.1.1
postcss-load-config: 3.1.4(postcss@8.4.41)(ts-node@10.9.2(@types/node@20.11.27)(typescript@4.9.5))
postcss-load-config: 3.1.4(postcss@8.4.41)(ts-node@10.9.2(@types/node@20.14.0)(typescript@4.9.5))
resolve-from: 5.0.0
rollup: 3.29.4
source-map: 0.8.0-beta.0