diff --git a/package-lock.json b/package-lock.json index 9b1f989..d5f618c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2864,6 +2864,39 @@ "node": ">=14" } }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@remix-run/dev": { "version": "2.15.3", "resolved": "https://registry.npmjs.org/@remix-run/dev/-/dev-2.15.3.tgz", @@ -6106,6 +6139,18 @@ "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", "license": "MIT" }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, "node_modules/clean-css": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", @@ -6249,6 +6294,15 @@ "node": ">=0.8" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -10890,6 +10944,15 @@ "yallist": "^3.0.2" } }, + "node_modules/lucide-react": { + "version": "0.517.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.517.0.tgz", + "integrity": "sha512-TQCwwbwIuVG6SSutUC2Ol6PRXcuZndqoVAnDa7S7xb/RWPaiKTvLwX7byUKeh0pUgvtFh0NZZwFIDuMSeB7Iwg==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/magic-string": { "version": "0.30.17", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", @@ -15026,6 +15089,16 @@ "dev": true, "license": "MIT" }, + "node_modules/tailwind-merge": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.1.tgz", + "integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, "node_modules/tar": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", @@ -16273,6 +16346,15 @@ "win32" ] }, + "node_modules/tw-animate-css": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.3.4.tgz", + "integrity": "sha512-dd1Ht6/YQHcNbq0znIT6dG8uhO7Ce+VIIhZUhjsryXsMPJQz3bZg7Q2eNzLwipb25bRZslGb2myio5mScd1TFg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Wombosvideo" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -17905,6 +17987,14 @@ "name": "@repo/ui", "version": "0.0.0", "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "^1.2.3", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "lucide-react": "^0.517.0", + "tailwind-merge": "^3.3.1", + "tw-animate-css": "^1.3.4" + }, "devDependencies": { "@jest/globals": "^29.7.0", "@repo/eslint-config": "*", diff --git a/packages/ui/components.json b/packages/ui/components.json new file mode 100644 index 0000000..13fce71 --- /dev/null +++ b/packages/ui/components.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "", + "css": "src/styles/globals.css", + "baseColor": "neutral", + "cssVariables": true + }, + "iconLibrary": "lucide", + "aliases": { + "components": "@repo/ui/components", + "utils": "@repo/ui/lib/utils", + "hooks": "@repo/ui/hooks", + "lib": "@repo/ui/lib", + "ui": "@repo/ui/components" + } +} diff --git a/packages/ui/package.json b/packages/ui/package.json index 6a94d21..7dcf529 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,60 +1,73 @@ { - "name": "@repo/ui", - "version": "0.0.0", - "private": true, - "license": "MIT", - "sideEffects": false, - "files": [ - "dist/**", - "dist" - ], - "exports": { - "./counter-button": { - "import": { - "types": "./dist/es/counter-button.d.mts", - "default": "./dist/es/counter-button.mjs" - }, - "require": { - "types": "./dist/cjs/counter-button.d.ts", - "default": "./dist/cjs/counter-button.js" - } - }, - "./link": { - "import": { - "types": "./dist/es/link.d.mts", - "default": "./dist/es/link.mjs" - }, - "require": { - "types": "./dist/cjs/link.d.ts", - "default": "./dist/cjs/link.js" - } - } - }, - "scripts": { - "build": "bunchee", - "dev": "bunchee --watch", - "check-types": "tsc --noEmit", - "lint": "eslint src/", - "test": "jest" - }, - "jest": { - "preset": "@repo/jest-presets/browser" - }, - "devDependencies": { - "@jest/globals": "^29.7.0", - "@repo/eslint-config": "*", - "@repo/jest-presets": "*", - "@repo/typescript-config": "*", - "@types/node": "^22.15.3", - "bunchee": "^6.4.0", - "eslint": "^9.29.0", - "jest": "^29.7.0", - "typescript": "5.8.2" - }, - "peerDependencies": { - "@types/react": ">=18", - "@types/react-dom": ">=18", - "react": ">=18", - "react-dom": ">=18" - } + "name": "@repo/ui", + "version": "0.0.0", + "private": true, + "license": "MIT", + "sideEffects": false, + "files": [ + "dist/**", + "dist" + ], + "scripts": { + "build": "bunchee", + "dev": "bunchee --watch", + "check-types": "tsc --noEmit", + "lint": "eslint src/", + "test": "jest" + }, + "jest": { + "preset": "@repo/jest-presets/browser" + }, + "devDependencies": { + "@jest/globals": "^29.7.0", + "@repo/eslint-config": "*", + "@repo/jest-presets": "*", + "@repo/typescript-config": "*", + "@types/node": "^22.15.3", + "bunchee": "^6.4.0", + "eslint": "^9.29.0", + "jest": "^29.7.0", + "typescript": "5.8.2" + }, + "peerDependencies": { + "@types/react": ">=18", + "@types/react-dom": ">=18", + "react": ">=18", + "react-dom": ">=18" + }, + "exports": { + "./counter-button": { + "import": { + "types": "./dist/es/counter-button.d.mts", + "default": "./dist/es/counter-button.mjs" + }, + "require": { + "types": "./dist/cjs/counter-button.d.ts", + "default": "./dist/cjs/counter-button.js" + } + }, + "./link": { + "import": { + "types": "./dist/es/link.d.mts", + "default": "./dist/es/link.mjs" + }, + "require": { + "types": "./dist/cjs/link.d.ts", + "default": "./dist/cjs/link.js" + } + }, + "./globals.css": "./src/styles/globals.css", + "./postcss.config": "./postcss.config.mjs", + "./lib/*": "./src/lib/*.ts", + "./components/*": "./src/components/*.tsx", + "./hooks/*": "./src/hooks/*.ts" + }, + "dependencies": { + "@radix-ui/react-slot": "^1.2.3", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "lucide-react": "^0.517.0", + "tailwind-merge": "^3.3.1", + "tw-animate-css": "^1.3.4" + } } diff --git a/packages/ui/postcss.config.mjs b/packages/ui/postcss.config.mjs new file mode 100644 index 0000000..4ae682d --- /dev/null +++ b/packages/ui/postcss.config.mjs @@ -0,0 +1,6 @@ +/** @type {import('postcss-load-config').Config} */ +const config = { + plugins: { "@tailwindcss/postcss": {} }, +}; + +export default config; diff --git a/packages/ui/src/components/button.tsx b/packages/ui/src/components/button.tsx new file mode 100644 index 0000000..b134ce7 --- /dev/null +++ b/packages/ui/src/components/button.tsx @@ -0,0 +1,58 @@ +import * as React from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { cva, type VariantProps } from "class-variance-authority"; + +import { cn } from "@repo/ui/lib/utils"; + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[color,box-shadow] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", + { + variants: { + variant: { + default: + "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90", + destructive: + "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40", + outline: + "border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2 has-[>svg]:px-3", + sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", + lg: "h-10 rounded-md px-6 has-[>svg]:px-4", + icon: "size-9", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +); + +function Button({ + className, + variant, + size, + asChild = false, + ...props +}: React.ComponentProps<"button"> & + VariantProps & { + asChild?: boolean; + }) { + const Comp = asChild ? Slot : "button"; + + return ( + + ); +} + +export { Button, buttonVariants }; diff --git a/packages/ui/src/components/card.tsx b/packages/ui/src/components/card.tsx new file mode 100644 index 0000000..4768e35 --- /dev/null +++ b/packages/ui/src/components/card.tsx @@ -0,0 +1,92 @@ +import * as React from "react" + +import { cn } from "@repo/ui/lib/utils" + +function Card({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function CardHeader({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function CardTitle({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function CardDescription({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function CardAction({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function CardContent({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function CardFooter({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +export { + Card, + CardHeader, + CardFooter, + CardTitle, + CardAction, + CardDescription, + CardContent, +} diff --git a/packages/ui/src/hooks/.gitkeep b/packages/ui/src/hooks/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/packages/ui/src/lib/utils.ts b/packages/ui/src/lib/utils.ts new file mode 100644 index 0000000..bd0c391 --- /dev/null +++ b/packages/ui/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/packages/ui/src/styles/globals.css b/packages/ui/src/styles/globals.css new file mode 100644 index 0000000..a5c6ce3 --- /dev/null +++ b/packages/ui/src/styles/globals.css @@ -0,0 +1,127 @@ +@import "tailwindcss"; +@source "../../../apps/**/*.{ts,tsx}"; +@source "../../../components/**/*.{ts,tsx}"; +@source "../**/*.{ts,tsx}"; + +@import "tw-animate-css"; + +@custom-variant dark (&:is(.dark *)); + +:root { + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.205 0 0); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.97 0 0); + --secondary-foreground: oklch(0.205 0 0); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); + --destructive-foreground: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --radius: 0.625rem; + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.205 0 0); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); +} + +.dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.145 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.145 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.985 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.396 0.141 25.723); + --destructive-foreground: oklch(0.637 0.237 25.331); + --border: oklch(0.269 0 0); + --input: oklch(0.269 0 0); + --ring: oklch(0.556 0 0); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(0.269 0 0); + --sidebar-ring: oklch(0.439 0 0); +} + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-destructive-foreground: var(--destructive-foreground); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); +} + +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } +} diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json index d049e2d..7d23cec 100644 --- a/packages/ui/tsconfig.json +++ b/packages/ui/tsconfig.json @@ -1,10 +1,14 @@ { - "extends": "@repo/typescript-config/react-library.json", - "compilerOptions": { - "lib": ["dom", "ES2015"], - "sourceMap": true, - "types": ["jest", "node"] - }, - "include": ["."], - "exclude": ["dist", "build", "node_modules"] + "extends": "@repo/typescript-config/react-library.json", + "compilerOptions": { + "lib": ["dom", "ES2015"], + "sourceMap": true, + "types": ["jest", "node"], + "baseUrl": ".", + "paths": { + "@repo/ui/*": ["./src/*"] + } + }, + "include": ["."], + "exclude": ["dist", "build", "node_modules"] }