From 9145b52df0a21fdf7f4893d898191ec7e17b6624 Mon Sep 17 00:00:00 2001 From: shadcn Date: Mon, 16 Mar 2026 21:12:27 +0400 Subject: [PATCH 01/88] fix Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- packages/shadcn/src/utils/resolve-import.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shadcn/src/utils/resolve-import.ts b/packages/shadcn/src/utils/resolve-import.ts index 9aa3e20f5e..7a606fc787 100644 --- a/packages/shadcn/src/utils/resolve-import.ts +++ b/packages/shadcn/src/utils/resolve-import.ts @@ -130,7 +130,7 @@ function findMatchingTsPathPattern( key, target: targetList[0]?.includes("*") && wildcardValue !== null - ? targetList[0].replace("*", wildcardValue) + ? targetList[0].replace(/\*/g, wildcardValue) : targetList[0], } } From a9f997d00a66ef9190de931ae2549b06a005b933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aboubakary=20Ciss=C3=A9?= <58236609+Aboubakary833@users.noreply.github.com> Date: Tue, 17 Mar 2026 02:25:06 +0000 Subject: [PATCH 02/88] fix: Update import path for Button component in react-router-app template --- templates/react-router-app/app/routes/home.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/react-router-app/app/routes/home.tsx b/templates/react-router-app/app/routes/home.tsx index 938c95e082..a520f6ab13 100644 --- a/templates/react-router-app/app/routes/home.tsx +++ b/templates/react-router-app/app/routes/home.tsx @@ -1,4 +1,4 @@ -import { Button } from "@/components/ui/button" +import { Button } from "~/components/ui/button" export default function Home() { return ( From 78f6a8b0f0ed7d7cc74a5129f568e11160ce3046 Mon Sep 17 00:00:00 2001 From: Danila Yudin Date: Tue, 17 Mar 2026 07:07:46 +0300 Subject: [PATCH 03/88] Add @sabraman ui registry (#10054) * Add new UI component entry for @sabraman * fix: update registries.json --- apps/v4/public/r/registries.json | 6 ++++++ apps/v4/registry/directory.json | 10 +++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/apps/v4/public/r/registries.json b/apps/v4/public/r/registries.json index 652e11a585..da7430efc9 100644 --- a/apps/v4/public/r/registries.json +++ b/apps/v4/public/r/registries.json @@ -916,5 +916,11 @@ "homepage": "https://ui.flexnative.com", "url": "https://ui.flexnative.com/r/{name}.json", "description": "A collection of customizable UI blocks with interactive live previews" + }, + { + "name": "@sabraman", + "homepage": "https://sabraman.ru/components", + "url": "https://sabraman.ru/r/{name}.json", + "description": "Legacy skeuomorphic UI components and blocks for shadcn." } ] diff --git a/apps/v4/registry/directory.json b/apps/v4/registry/directory.json index 891ab13ab3..0c767052eb 100644 --- a/apps/v4/registry/directory.json +++ b/apps/v4/registry/directory.json @@ -1070,5 +1070,13 @@ "url": "https://ui.flexnative.com/r/{name}.json", "description": "A collection of customizable UI blocks with interactive live previews", "logo": "" - } + }, + { + "name": "@sabraman", + "homepage": "https://sabraman.ru/components", + "url": "https://sabraman.ru/r/{name}.json", + "description": "Legacy skeuomorphic UI components and blocks for shadcn.", + "logo": " " +} + ] From 632e2c012e7b83b6dd77b0eb15a9242eefb56c4a Mon Sep 17 00:00:00 2001 From: shadcn Date: Tue, 17 Mar 2026 08:26:13 +0400 Subject: [PATCH 04/88] fix: update skill and add allowed-tools (#10075) --- skills/shadcn/SKILL.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/skills/shadcn/SKILL.md b/skills/shadcn/SKILL.md index 8a76cc0dc2..39d1e48176 100644 --- a/skills/shadcn/SKILL.md +++ b/skills/shadcn/SKILL.md @@ -2,6 +2,7 @@ name: shadcn description: Manages shadcn components and projects — adding, searching, fixing, debugging, styling, and composing UI. Provides project context, component docs, and usage examples. Applies when working with shadcn/ui, component registries, presets, --preset codes, or any project with a components.json file. Also triggers for "shadcn init", "create an app with --preset", or "switch to --preset". user-invocable: false +allowed-tools: Bash(npx shadcn@latest *), Bash(pnpm dlx shadcn@latest *), Bash(bunx --bun shadcn@latest *) --- # shadcn/ui @@ -13,7 +14,7 @@ A framework for building ui, components and design systems. Components are added ## Current Project Context ```json -!`npx shadcn@latest info --json 2>/dev/null || echo '{"error": "No shadcn project found. Run shadcn init first."}'` +!`npx shadcn@latest info --json` ``` The JSON above contains the project config and installed components. Use `npx shadcn@latest docs ` to get documentation and example URLs for any component. From acaa0953dfec30f125a2af718714ce9f59abe3ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aboubakary=20Ciss=C3=A9?= <58236609+Aboubakary833@users.noreply.github.com> Date: Tue, 17 Mar 2026 04:43:46 +0000 Subject: [PATCH 05/88] fix: Update import path for Button component in react-router-app template (#10073) --- templates/react-router-app/app/routes/home.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/react-router-app/app/routes/home.tsx b/templates/react-router-app/app/routes/home.tsx index 938c95e082..a520f6ab13 100644 --- a/templates/react-router-app/app/routes/home.tsx +++ b/templates/react-router-app/app/routes/home.tsx @@ -1,4 +1,4 @@ -import { Button } from "@/components/ui/button" +import { Button } from "~/components/ui/button" export default function Home() { return ( From e78bb7b4f36e1c4677a252b7170e1af69f0b5d5f Mon Sep 17 00:00:00 2001 From: shadcn Date: Tue, 17 Mar 2026 09:55:37 +0400 Subject: [PATCH 06/88] feat: move base picker to project form (#10077) * feat: move base picker to project form * fix: format --- .../v4/app/(create)/components/customizer.tsx | 5 +- .../app/(create)/components/menu-picker.tsx | 2 +- .../app/(create)/components/project-form.tsx | 164 ++++++++++++------ 3 files changed, 112 insertions(+), 59 deletions(-) diff --git a/apps/v4/app/(create)/components/customizer.tsx b/apps/v4/app/(create)/components/customizer.tsx index 352cf94632..f1e57620b6 100644 --- a/apps/v4/app/(create)/components/customizer.tsx +++ b/apps/v4/app/(create)/components/customizer.tsx @@ -8,8 +8,6 @@ import { CardHeader, } from "@/examples/base/ui/card" import { FieldGroup } from "@/examples/base/ui/field" -import { Separator } from "@/examples/base/ui/separator" -import { CardTitle } from "@/examples/radix/ui/card" import { type RegistryItem } from "shadcn/schema" import { useIsMobile } from "@/hooks/use-mobile" @@ -23,7 +21,6 @@ import { FontPicker } from "@/app/(create)/components/font-picker" import { IconLibraryPicker } from "@/app/(create)/components/icon-library-picker" import { MainMenu } from "@/app/(create)/components/main-menu" import { MenuColorPicker } from "@/app/(create)/components/menu-picker" -import { ProjectForm } from "@/app/(create)/components/project-form" import { RadiusPicker } from "@/app/(create)/components/radius-picker" import { RandomButton } from "@/app/(create)/components/random-button" import { ResetDialog } from "@/app/(create)/components/reset-button" @@ -58,7 +55,7 @@ export function Customizer({ - + {isMobile && }
Menu
-
+
{currentMenu?.label}
diff --git a/apps/v4/app/(create)/components/project-form.tsx b/apps/v4/app/(create)/components/project-form.tsx index d64a7b7039..7cb6a6a30a 100644 --- a/apps/v4/app/(create)/components/project-form.tsx +++ b/apps/v4/app/(create)/components/project-form.tsx @@ -35,6 +35,7 @@ import { HugeiconsIcon } from "@hugeicons/react" import { cn } from "@/lib/utils" import { useConfig } from "@/hooks/use-config" import { copyToClipboardWithMeta } from "@/components/copy-button" +import { BASES, type BaseName } from "@/registry/config" import { usePresetCode } from "@/app/(create)/hooks/use-design-system" import { useDesignSystemSearchParams, @@ -129,68 +130,74 @@ export function ProjectForm({ }> Create Project - + Create Project - Pick a template and configure your project. Available for all major - React frameworks. + Pick a template and configure your project. - - - Template - - - -
- - Options - - - - - Create a monorepo - - { - const framework = getFramework(params.template ?? "next") - setParams({ - template: getTemplateValue( - framework, - checked === true - ) as typeof params.template, - }) - }} - /> +
+ + + Template + - - - - Enable RTL support - - - setParams({ rtl: checked === true }) - } - /> + + Base + -
-
+ +
+ + Options + + + + + Create a monorepo + + { + const framework = getFramework(params.template ?? "next") + setParams({ + template: getTemplateValue( + framework, + checked === true + ) as typeof params.template, + }) + }} + /> + + + + + + Enable RTL support + + + setParams({ rtl: checked === true }) + } + /> + +
+ +
) }) + +const BaseGrid = React.memo(function BaseGrid({ + base, + setParams, +}: { + base: DesignSystemSearchParams["base"] + setParams: ReturnType[1] +}) { + const handleBaseChange = React.useCallback( + (value: string) => { + setParams({ base: value as BaseName }) + }, + [setParams] + ) + + return ( + + {BASES.map((item) => ( + + + +
+ {item.title} + + + + + ))} + + ) +}) From a8bd00466a11b56c8f4d577dc3094c3d4a72c397 Mon Sep 17 00:00:00 2001 From: shadcn Date: Tue, 17 Mar 2026 09:56:02 +0400 Subject: [PATCH 07/88] chore(templates): bump minor dependencies (#10076) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: Update import path for Button component in react-router-app template * chore(templates): bump minor dependencies Co-Authored-By: Claude Opus 4.6 (1M context) --------- Co-authored-by: Aboubakary Cissé <58236609+Aboubakary833@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) --- templates/astro-app/package.json | 14 +++--- templates/astro-monorepo/package.json | 4 +- templates/next-app/package.json | 14 +++--- templates/next-monorepo/package.json | 4 +- templates/react-router-app/package.json | 20 ++++----- templates/react-router-monorepo/package.json | 4 +- templates/start-app/package.json | 46 ++++++++++---------- templates/start-monorepo/package.json | 4 +- templates/vite-app/package.json | 24 +++++----- templates/vite-monorepo/package.json | 4 +- 10 files changed, 69 insertions(+), 69 deletions(-) diff --git a/templates/astro-app/package.json b/templates/astro-app/package.json index 7bce68808a..2696bda9bf 100644 --- a/templates/astro-app/package.json +++ b/templates/astro-app/package.json @@ -14,24 +14,24 @@ }, "dependencies": { "@astrojs/react": "^4.4.2", - "@tailwindcss/vite": "^4.1.18", + "@tailwindcss/vite": "^4.2.1", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", - "astro": "^5.17.1", + "astro": "^5.18.1", "react": "^19.2.4", "react-dom": "^19.2.4", - "tailwindcss": "^4.1.18" + "tailwindcss": "^4.2.1" }, "devDependencies": { - "@eslint/js": "^9.39.1", - "eslint": "^9.39.1", + "@eslint/js": "^9.39.4", + "eslint": "^9.39.4", "eslint-plugin-react-hooks": "^7.0.1", - "eslint-plugin-react-refresh": "^0.4.24", + "eslint-plugin-react-refresh": "^0.5.2", "globals": "^16.5.0", "prettier": "^3.8.1", "prettier-plugin-astro": "^0.14.1", "prettier-plugin-tailwindcss": "^0.7.2", "typescript": "~5.9.3", - "typescript-eslint": "^8.46.4" + "typescript-eslint": "^8.57.1" } } diff --git a/templates/astro-monorepo/package.json b/templates/astro-monorepo/package.json index 4772b9b07f..a55c5bb1cd 100644 --- a/templates/astro-monorepo/package.json +++ b/templates/astro-monorepo/package.json @@ -13,10 +13,10 @@ "prettier": "^3.8.1", "prettier-plugin-astro": "^0.14.1", "prettier-plugin-tailwindcss": "^0.7.2", - "turbo": "^2.8.8", + "turbo": "^2.8.17", "typescript": "5.9.3" }, - "packageManager": "pnpm@9.0.6", + "packageManager": "pnpm@9.15.9", "engines": { "node": ">=20" } diff --git a/templates/next-app/package.json b/templates/next-app/package.json index 0f9127bfc0..513d6666ff 100644 --- a/templates/next-app/package.json +++ b/templates/next-app/package.json @@ -12,23 +12,23 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "next": "16.1.6", + "next": "16.1.7", "next-themes": "^0.4.6", "react": "^19.2.4", "react-dom": "^19.2.4" }, "devDependencies": { "@eslint/eslintrc": "^3", - "@tailwindcss/postcss": "^4.1.18", - "@types/node": "^25.1.0", - "@types/react": "^19.2.10", + "@tailwindcss/postcss": "^4.2.1", + "@types/node": "^25.5.0", + "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", - "eslint": "^9.39.2", - "eslint-config-next": "16.1.6", + "eslint": "^9.39.4", + "eslint-config-next": "16.1.7", "prettier": "^3.8.1", "prettier-plugin-tailwindcss": "^0.7.2", "postcss": "^8", - "tailwindcss": "^4.1.18", + "tailwindcss": "^4.2.1", "typescript": "^5.9.3" } } diff --git a/templates/next-monorepo/package.json b/templates/next-monorepo/package.json index 03929240da..3e042e9216 100644 --- a/templates/next-monorepo/package.json +++ b/templates/next-monorepo/package.json @@ -14,10 +14,10 @@ "@workspace/typescript-config": "workspace:*", "prettier": "^3.8.1", "prettier-plugin-tailwindcss": "^0.7.2", - "turbo": "^2.8.8", + "turbo": "^2.8.17", "typescript": "5.9.3" }, - "packageManager": "pnpm@9.0.6", + "packageManager": "pnpm@9.15.9", "engines": { "node": ">=20" } diff --git a/templates/react-router-app/package.json b/templates/react-router-app/package.json index a5ec9c779c..52e2f79e42 100644 --- a/templates/react-router-app/package.json +++ b/templates/react-router-app/package.json @@ -10,24 +10,24 @@ "format": "prettier --write \"**/*.{ts,tsx}\"" }, "dependencies": { - "@react-router/node": "7.12.0", - "@react-router/serve": "7.12.0", - "isbot": "^5.1.31", + "@react-router/node": "7.13.1", + "@react-router/serve": "7.13.1", + "isbot": "^5.1.36", "react": "^19.2.4", "react-dom": "^19.2.4", - "react-router": "7.12.0" + "react-router": "7.13.1" }, "devDependencies": { - "@react-router/dev": "7.12.0", - "@tailwindcss/vite": "^4.1.13", + "@react-router/dev": "7.13.1", + "@tailwindcss/vite": "^4.2.1", "@types/node": "^22", - "@types/react": "^19.2.7", + "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", "prettier": "^3.8.1", "prettier-plugin-tailwindcss": "^0.7.2", - "tailwindcss": "^4.1.13", - "typescript": "^5.9.2", - "vite": "^7.1.7", + "tailwindcss": "^4.2.1", + "typescript": "^5.9.3", + "vite": "^7.3.1", "vite-tsconfig-paths": "^5.1.4" } } diff --git a/templates/react-router-monorepo/package.json b/templates/react-router-monorepo/package.json index c080fb55c5..6540fbe797 100644 --- a/templates/react-router-monorepo/package.json +++ b/templates/react-router-monorepo/package.json @@ -11,10 +11,10 @@ "devDependencies": { "prettier": "^3.8.1", "prettier-plugin-tailwindcss": "^0.7.2", - "turbo": "^2.8.8", + "turbo": "^2.8.17", "typescript": "5.9.3" }, - "packageManager": "pnpm@9.0.6", + "packageManager": "pnpm@9.15.9", "engines": { "node": ">=20" } diff --git a/templates/start-app/package.json b/templates/start-app/package.json index 77b29faad2..1359fae334 100644 --- a/templates/start-app/package.json +++ b/templates/start-app/package.json @@ -12,34 +12,34 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@tailwindcss/vite": "^4.1.18", - "@tanstack/react-devtools": "^0.7.0", - "@tanstack/react-router": "^1.132.0", - "@tanstack/react-router-devtools": "^1.132.0", - "@tanstack/react-router-ssr-query": "^1.131.7", - "@tanstack/react-start": "^1.132.0", - "@tanstack/router-plugin": "^1.132.0", + "@tailwindcss/vite": "^4.2.1", + "@tanstack/react-devtools": "^0.10.0", + "@tanstack/react-router": "^1.167.4", + "@tanstack/react-router-devtools": "^1.166.9", + "@tanstack/react-router-ssr-query": "^1.166.9", + "@tanstack/react-start": "^1.166.15", + "@tanstack/router-plugin": "^1.166.13", "nitro": "latest", - "react": "^19.2.0", - "react-dom": "^19.2.0", - "tailwindcss": "^4.0.6", + "react": "^19.2.4", + "react-dom": "^19.2.4", + "tailwindcss": "^4.2.1", "vite-tsconfig-paths": "^5.1.4" }, "devDependencies": { - "@tanstack/devtools-vite": "^0.3.11", - "@tanstack/eslint-config": "^0.3.0", - "@testing-library/dom": "^10.4.0", - "@testing-library/react": "^16.2.0", - "@types/node": "^22.10.2", - "@types/react": "^19.2.0", - "@types/react-dom": "^19.2.0", - "@vitejs/plugin-react": "^5.0.4", - "jsdom": "^27.0.0", - "prettier": "^3.5.3", + "@tanstack/devtools-vite": "^0.6.0", + "@tanstack/eslint-config": "^0.4.0", + "@testing-library/dom": "^10.4.1", + "@testing-library/react": "^16.3.2", + "@types/node": "^22.19.15", + "@types/react": "^19.2.14", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.2.0", + "jsdom": "^27.4.0", + "prettier": "^3.8.1", "prettier-plugin-tailwindcss": "^0.7.2", - "typescript": "^5.7.2", - "vite": "^7.1.7", - "vitest": "^3.0.5", + "typescript": "^5.9.3", + "vite": "^7.3.1", + "vitest": "^3.2.4", "web-vitals": "^5.1.0" } } diff --git a/templates/start-monorepo/package.json b/templates/start-monorepo/package.json index 61cf76f04b..6b7b5515e5 100644 --- a/templates/start-monorepo/package.json +++ b/templates/start-monorepo/package.json @@ -12,10 +12,10 @@ "devDependencies": { "prettier": "^3.8.1", "prettier-plugin-tailwindcss": "^0.7.2", - "turbo": "^2.8.8", + "turbo": "^2.8.17", "typescript": "5.9.3" }, - "packageManager": "pnpm@9.0.6", + "packageManager": "pnpm@9.15.9", "engines": { "node": ">=20" } diff --git a/templates/vite-app/package.json b/templates/vite-app/package.json index 5a1dd70945..45901d1384 100644 --- a/templates/vite-app/package.json +++ b/templates/vite-app/package.json @@ -12,25 +12,25 @@ "preview": "vite preview" }, "dependencies": { - "@tailwindcss/vite": "^4.1.17", - "react": "^19.2.0", - "react-dom": "^19.2.0", - "tailwindcss": "^4.1.17" + "@tailwindcss/vite": "^4.2.1", + "react": "^19.2.4", + "react-dom": "^19.2.4", + "tailwindcss": "^4.2.1" }, "devDependencies": { - "@eslint/js": "^9.39.1", - "@types/node": "^24.10.1", - "@types/react": "^19.2.5", + "@eslint/js": "^9.39.4", + "@types/node": "^24.12.0", + "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^5.1.1", - "eslint": "^9.39.1", + "@vitejs/plugin-react": "^5.2.0", + "eslint": "^9.39.4", "eslint-plugin-react-hooks": "^7.0.1", - "eslint-plugin-react-refresh": "^0.4.24", + "eslint-plugin-react-refresh": "^0.5.2", "globals": "^16.5.0", "prettier": "^3.8.1", "prettier-plugin-tailwindcss": "^0.7.2", "typescript": "~5.9.3", - "typescript-eslint": "^8.46.4", - "vite": "^7.2.4" + "typescript-eslint": "^8.57.1", + "vite": "^7.3.1" } } diff --git a/templates/vite-monorepo/package.json b/templates/vite-monorepo/package.json index 73d474feeb..1c84a25aca 100644 --- a/templates/vite-monorepo/package.json +++ b/templates/vite-monorepo/package.json @@ -12,10 +12,10 @@ "devDependencies": { "prettier": "^3.8.1", "prettier-plugin-tailwindcss": "^0.7.2", - "turbo": "^2.8.8", + "turbo": "^2.8.17", "typescript": "5.9.3" }, - "packageManager": "pnpm@9.0.6", + "packageManager": "pnpm@9.15.9", "engines": { "node": ">=20" } From 8db2be8b0952581654acb5ae6d3fa0265b9e51fe Mon Sep 17 00:00:00 2001 From: Victor Williams Date: Wed, 18 Mar 2026 07:11:15 +0100 Subject: [PATCH 08/88] feat: add @nexus-ui registry to public directory (#10067) --- apps/v4/public/r/registries.json | 6 ++++++ apps/v4/registry/directory.json | 10 ++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/apps/v4/public/r/registries.json b/apps/v4/public/r/registries.json index da7430efc9..2a81c4c2aa 100644 --- a/apps/v4/public/r/registries.json +++ b/apps/v4/public/r/registries.json @@ -917,6 +917,12 @@ "url": "https://ui.flexnative.com/r/{name}.json", "description": "A collection of customizable UI blocks with interactive live previews" }, + { + "name": "@nexus-ui", + "homepage": "https://nexus-ui.dev", + "url": "https://nexus-ui.dev/r/{name}.json", + "description": "Open-source component library of composable, copy-paste primitives for building AI interfaces (chat, streaming, multimodal)" + }, { "name": "@sabraman", "homepage": "https://sabraman.ru/components", diff --git a/apps/v4/registry/directory.json b/apps/v4/registry/directory.json index 0c767052eb..e672f836a2 100644 --- a/apps/v4/registry/directory.json +++ b/apps/v4/registry/directory.json @@ -1071,12 +1071,18 @@ "description": "A collection of customizable UI blocks with interactive live previews", "logo": "" }, + { + "name": "@nexus-ui", + "homepage": "https://nexus-ui.dev", + "url": "https://nexus-ui.dev/r/{name}.json", + "description": "Open-source component library of composable, copy-paste primitives for building AI interfaces (chat, streaming, multimodal)", + "logo": "" + }, { "name": "@sabraman", "homepage": "https://sabraman.ru/components", "url": "https://sabraman.ru/r/{name}.json", "description": "Legacy skeuomorphic UI components and blocks for shadcn.", "logo": " " -} - + } ] From 687f09817b614a3450f0f56779edf367082e1e53 Mon Sep 17 00:00:00 2001 From: shadcn Date: Thu, 19 Mar 2026 23:35:01 +0400 Subject: [PATCH 09/88] feat: chartColor and fontHeading (#10115) * feat: chart color * fix * fix * fix: chart color * chore: changeset * chore: restore directory registry formatting * feat: add fontHeading * feat: rebuild registry * fix: v0 * refactor * fix * fix * fix * fix * fix * fix: refactor preset handling * fix * fix * fix --- .changeset/short-colts-go.md | 5 + .changeset/spicy-walls-visit.md | 5 + .cursor/rules/registry-bases-parity.mdc | 22 + apps/v4/app/(app)/docs/changelog/page.tsx | 2 +- .../components/chart-color-picker.tsx | 136 ++++++ .../v4/app/(create)/components/customizer.tsx | 27 +- .../components/design-system-provider.tsx | 61 ++- .../app/(create)/components/font-picker.tsx | 91 +++- .../app/(create)/components/preset-picker.tsx | 6 + .../app/(create)/components/project-form.tsx | 55 +-- .../app/(create)/hooks/use-design-system.ts | 35 +- apps/v4/app/(create)/hooks/use-locks.tsx | 2 + apps/v4/app/(create)/hooks/use-random.tsx | 37 +- apps/v4/app/(create)/hooks/use-reset.tsx | 2 + .../(create)/init/md/build-instructions.ts | 87 +++- .../v4/app/(create)/init/parse-config.test.ts | 21 + apps/v4/app/(create)/init/parse-config.ts | 5 + apps/v4/app/(create)/init/route.ts | 21 +- apps/v4/app/(create)/init/v0/route.ts | 10 +- apps/v4/app/(create)/lib/fonts.ts | 256 ++++++----- apps/v4/app/(create)/lib/preset-code.ts | 34 ++ apps/v4/app/(create)/lib/preset-query.test.ts | 34 ++ apps/v4/app/(create)/lib/preset-query.ts | 30 ++ apps/v4/app/(create)/lib/randomize-biases.ts | 50 ++- apps/v4/app/(create)/lib/search-params.ts | 111 +++-- apps/v4/app/(create)/lib/templates.ts | 2 +- apps/v4/app/(create)/lib/v0.test.ts | 115 +++++ apps/v4/app/(create)/lib/v0.ts | 125 ++++-- apps/v4/examples/base/ui-rtl/alert-dialog.tsx | 2 +- apps/v4/examples/base/ui-rtl/alert.tsx | 2 +- apps/v4/examples/base/ui-rtl/card.tsx | 2 +- apps/v4/examples/base/ui-rtl/dialog.tsx | 5 +- apps/v4/examples/base/ui-rtl/drawer.tsx | 5 +- apps/v4/examples/base/ui-rtl/empty.tsx | 5 +- apps/v4/examples/base/ui-rtl/item.tsx | 2 +- apps/v4/examples/base/ui-rtl/popover.tsx | 2 +- apps/v4/examples/base/ui-rtl/sheet.tsx | 5 +- apps/v4/examples/base/ui/alert-dialog.tsx | 2 +- apps/v4/examples/base/ui/alert.tsx | 2 +- apps/v4/examples/base/ui/card.tsx | 2 +- apps/v4/examples/base/ui/dialog.tsx | 5 +- apps/v4/examples/base/ui/drawer.tsx | 5 +- apps/v4/examples/base/ui/empty.tsx | 5 +- apps/v4/examples/base/ui/item.tsx | 2 +- apps/v4/examples/base/ui/popover.tsx | 2 +- apps/v4/examples/base/ui/sheet.tsx | 5 +- .../v4/examples/radix/ui-rtl/alert-dialog.tsx | 2 +- apps/v4/examples/radix/ui-rtl/alert.tsx | 2 +- apps/v4/examples/radix/ui-rtl/card.tsx | 2 +- apps/v4/examples/radix/ui-rtl/dialog.tsx | 5 +- apps/v4/examples/radix/ui-rtl/drawer.tsx | 5 +- apps/v4/examples/radix/ui-rtl/empty.tsx | 5 +- apps/v4/examples/radix/ui-rtl/item.tsx | 2 +- apps/v4/examples/radix/ui-rtl/popover.tsx | 2 +- apps/v4/examples/radix/ui-rtl/sheet.tsx | 5 +- apps/v4/examples/radix/ui/alert-dialog.tsx | 2 +- apps/v4/examples/radix/ui/alert.tsx | 2 +- apps/v4/examples/radix/ui/card.tsx | 2 +- apps/v4/examples/radix/ui/dialog.tsx | 5 +- apps/v4/examples/radix/ui/drawer.tsx | 5 +- apps/v4/examples/radix/ui/empty.tsx | 5 +- apps/v4/examples/radix/ui/item.tsx | 2 +- apps/v4/examples/radix/ui/popover.tsx | 2 +- apps/v4/examples/radix/ui/sheet.tsx | 5 +- apps/v4/lib/font-definitions.ts | 306 +++++++++++++ apps/v4/lib/format-code.ts | 15 +- apps/v4/mdx-components.tsx | 10 +- apps/v4/public/r/colors/mauve.json | 62 +-- apps/v4/public/r/colors/mist.json | 62 +-- apps/v4/public/r/colors/neutral.json | 62 +-- apps/v4/public/r/colors/olive.json | 62 +-- apps/v4/public/r/colors/stone.json | 62 +-- apps/v4/public/r/colors/taupe.json | 62 +-- apps/v4/public/r/colors/zinc.json | 62 +-- apps/v4/public/r/config.json | 20 + .../r/styles/base-lyra/alert-dialog.json | 2 +- apps/v4/public/r/styles/base-lyra/alert.json | 2 +- apps/v4/public/r/styles/base-lyra/card.json | 2 +- apps/v4/public/r/styles/base-lyra/demo.json | 2 +- apps/v4/public/r/styles/base-lyra/dialog.json | 2 +- apps/v4/public/r/styles/base-lyra/drawer.json | 2 +- apps/v4/public/r/styles/base-lyra/empty.json | 2 +- .../base-lyra/font-heading-dm-sans.json | 16 + .../base-lyra/font-heading-figtree.json | 16 + .../base-lyra/font-heading-geist-mono.json | 16 + .../styles/base-lyra/font-heading-geist.json | 16 + .../base-lyra/font-heading-ibm-plex-sans.json | 16 + .../font-heading-instrument-sans.json | 16 + .../styles/base-lyra/font-heading-inter.json | 16 + .../font-heading-jetbrains-mono.json | 16 + .../r/styles/base-lyra/font-heading-lora.json | 16 + .../base-lyra/font-heading-manrope.json | 16 + .../base-lyra/font-heading-merriweather.json | 16 + .../base-lyra/font-heading-montserrat.json | 16 + .../base-lyra/font-heading-noto-sans.json | 16 + .../base-lyra/font-heading-noto-serif.json | 16 + .../base-lyra/font-heading-nunito-sans.json | 16 + .../styles/base-lyra/font-heading-outfit.json | 16 + .../base-lyra/font-heading-oxanium.json | 16 + .../font-heading-playfair-display.json | 16 + .../base-lyra/font-heading-public-sans.json | 16 + .../base-lyra/font-heading-raleway.json | 16 + .../base-lyra/font-heading-roboto-slab.json | 16 + .../styles/base-lyra/font-heading-roboto.json | 16 + .../base-lyra/font-heading-source-sans-3.json | 16 + .../base-lyra/font-heading-space-grotesk.json | 16 + .../base-lyra/font-heading-tomorrow.json | 27 ++ .../styles/base-lyra/font-ibm-plex-sans.json | 16 + .../base-lyra/font-instrument-sans.json | 16 + .../r/styles/base-lyra/font-manrope.json | 16 + .../r/styles/base-lyra/font-montserrat.json | 16 + .../r/styles/base-lyra/font-noto-sans.json | 3 + .../r/styles/base-lyra/font-nunito-sans.json | 3 + .../r/styles/base-lyra/font-oxanium.json | 16 + .../styles/base-lyra/font-source-sans-3.json | 16 + .../styles/base-lyra/font-space-grotesk.json | 16 + .../r/styles/base-lyra/font-tomorrow.json | 27 ++ apps/v4/public/r/styles/base-lyra/item.json | 2 +- .../v4/public/r/styles/base-lyra/popover.json | 2 +- .../v4/public/r/styles/base-lyra/preview.json | 2 +- .../public/r/styles/base-lyra/registry.json | 405 ++++++++++++++++++ apps/v4/public/r/styles/base-lyra/sheet.json | 2 +- .../r/styles/base-maia/alert-dialog.json | 2 +- apps/v4/public/r/styles/base-maia/alert.json | 2 +- apps/v4/public/r/styles/base-maia/card.json | 2 +- apps/v4/public/r/styles/base-maia/demo.json | 2 +- apps/v4/public/r/styles/base-maia/dialog.json | 2 +- apps/v4/public/r/styles/base-maia/drawer.json | 2 +- apps/v4/public/r/styles/base-maia/empty.json | 2 +- .../base-maia/font-heading-dm-sans.json | 16 + .../base-maia/font-heading-figtree.json | 16 + .../base-maia/font-heading-geist-mono.json | 16 + .../styles/base-maia/font-heading-geist.json | 16 + .../base-maia/font-heading-ibm-plex-sans.json | 16 + .../font-heading-instrument-sans.json | 16 + .../styles/base-maia/font-heading-inter.json | 16 + .../font-heading-jetbrains-mono.json | 16 + .../r/styles/base-maia/font-heading-lora.json | 16 + .../base-maia/font-heading-manrope.json | 16 + .../base-maia/font-heading-merriweather.json | 16 + .../base-maia/font-heading-montserrat.json | 16 + .../base-maia/font-heading-noto-sans.json | 16 + .../base-maia/font-heading-noto-serif.json | 16 + .../base-maia/font-heading-nunito-sans.json | 16 + .../styles/base-maia/font-heading-outfit.json | 16 + .../base-maia/font-heading-oxanium.json | 16 + .../font-heading-playfair-display.json | 16 + .../base-maia/font-heading-public-sans.json | 16 + .../base-maia/font-heading-raleway.json | 16 + .../base-maia/font-heading-roboto-slab.json | 16 + .../styles/base-maia/font-heading-roboto.json | 16 + .../base-maia/font-heading-source-sans-3.json | 16 + .../base-maia/font-heading-space-grotesk.json | 16 + .../base-maia/font-heading-tomorrow.json | 27 ++ .../styles/base-maia/font-ibm-plex-sans.json | 16 + .../base-maia/font-instrument-sans.json | 16 + .../r/styles/base-maia/font-manrope.json | 16 + .../r/styles/base-maia/font-montserrat.json | 16 + .../r/styles/base-maia/font-noto-sans.json | 3 + .../r/styles/base-maia/font-nunito-sans.json | 3 + .../r/styles/base-maia/font-oxanium.json | 16 + .../styles/base-maia/font-source-sans-3.json | 16 + .../styles/base-maia/font-space-grotesk.json | 16 + .../r/styles/base-maia/font-tomorrow.json | 27 ++ apps/v4/public/r/styles/base-maia/item.json | 2 +- .../v4/public/r/styles/base-maia/popover.json | 2 +- .../v4/public/r/styles/base-maia/preview.json | 2 +- .../public/r/styles/base-maia/registry.json | 405 ++++++++++++++++++ apps/v4/public/r/styles/base-maia/sheet.json | 2 +- .../r/styles/base-mira/alert-dialog.json | 2 +- apps/v4/public/r/styles/base-mira/alert.json | 2 +- apps/v4/public/r/styles/base-mira/card.json | 2 +- apps/v4/public/r/styles/base-mira/demo.json | 2 +- apps/v4/public/r/styles/base-mira/dialog.json | 2 +- apps/v4/public/r/styles/base-mira/drawer.json | 2 +- apps/v4/public/r/styles/base-mira/empty.json | 2 +- .../base-mira/font-heading-dm-sans.json | 16 + .../base-mira/font-heading-figtree.json | 16 + .../base-mira/font-heading-geist-mono.json | 16 + .../styles/base-mira/font-heading-geist.json | 16 + .../base-mira/font-heading-ibm-plex-sans.json | 16 + .../font-heading-instrument-sans.json | 16 + .../styles/base-mira/font-heading-inter.json | 16 + .../font-heading-jetbrains-mono.json | 16 + .../r/styles/base-mira/font-heading-lora.json | 16 + .../base-mira/font-heading-manrope.json | 16 + .../base-mira/font-heading-merriweather.json | 16 + .../base-mira/font-heading-montserrat.json | 16 + .../base-mira/font-heading-noto-sans.json | 16 + .../base-mira/font-heading-noto-serif.json | 16 + .../base-mira/font-heading-nunito-sans.json | 16 + .../styles/base-mira/font-heading-outfit.json | 16 + .../base-mira/font-heading-oxanium.json | 16 + .../font-heading-playfair-display.json | 16 + .../base-mira/font-heading-public-sans.json | 16 + .../base-mira/font-heading-raleway.json | 16 + .../base-mira/font-heading-roboto-slab.json | 16 + .../styles/base-mira/font-heading-roboto.json | 16 + .../base-mira/font-heading-source-sans-3.json | 16 + .../base-mira/font-heading-space-grotesk.json | 16 + .../base-mira/font-heading-tomorrow.json | 27 ++ .../styles/base-mira/font-ibm-plex-sans.json | 16 + .../base-mira/font-instrument-sans.json | 16 + .../r/styles/base-mira/font-manrope.json | 16 + .../r/styles/base-mira/font-montserrat.json | 16 + .../r/styles/base-mira/font-noto-sans.json | 3 + .../r/styles/base-mira/font-nunito-sans.json | 3 + .../r/styles/base-mira/font-oxanium.json | 16 + .../styles/base-mira/font-source-sans-3.json | 16 + .../styles/base-mira/font-space-grotesk.json | 16 + .../r/styles/base-mira/font-tomorrow.json | 27 ++ apps/v4/public/r/styles/base-mira/item.json | 2 +- .../v4/public/r/styles/base-mira/popover.json | 2 +- .../v4/public/r/styles/base-mira/preview.json | 2 +- .../public/r/styles/base-mira/registry.json | 405 ++++++++++++++++++ apps/v4/public/r/styles/base-mira/sheet.json | 2 +- .../r/styles/base-nova/alert-dialog.json | 2 +- apps/v4/public/r/styles/base-nova/alert.json | 2 +- apps/v4/public/r/styles/base-nova/card.json | 2 +- apps/v4/public/r/styles/base-nova/demo.json | 2 +- apps/v4/public/r/styles/base-nova/dialog.json | 2 +- apps/v4/public/r/styles/base-nova/drawer.json | 2 +- apps/v4/public/r/styles/base-nova/empty.json | 2 +- .../base-nova/font-heading-dm-sans.json | 16 + .../base-nova/font-heading-figtree.json | 16 + .../base-nova/font-heading-geist-mono.json | 16 + .../styles/base-nova/font-heading-geist.json | 16 + .../base-nova/font-heading-ibm-plex-sans.json | 16 + .../font-heading-instrument-sans.json | 16 + .../styles/base-nova/font-heading-inter.json | 16 + .../font-heading-jetbrains-mono.json | 16 + .../r/styles/base-nova/font-heading-lora.json | 16 + .../base-nova/font-heading-manrope.json | 16 + .../base-nova/font-heading-merriweather.json | 16 + .../base-nova/font-heading-montserrat.json | 16 + .../base-nova/font-heading-noto-sans.json | 16 + .../base-nova/font-heading-noto-serif.json | 16 + .../base-nova/font-heading-nunito-sans.json | 16 + .../styles/base-nova/font-heading-outfit.json | 16 + .../base-nova/font-heading-oxanium.json | 16 + .../font-heading-playfair-display.json | 16 + .../base-nova/font-heading-public-sans.json | 16 + .../base-nova/font-heading-raleway.json | 16 + .../base-nova/font-heading-roboto-slab.json | 16 + .../styles/base-nova/font-heading-roboto.json | 16 + .../base-nova/font-heading-source-sans-3.json | 16 + .../base-nova/font-heading-space-grotesk.json | 16 + .../base-nova/font-heading-tomorrow.json | 27 ++ .../styles/base-nova/font-ibm-plex-sans.json | 16 + .../base-nova/font-instrument-sans.json | 16 + .../r/styles/base-nova/font-manrope.json | 16 + .../r/styles/base-nova/font-montserrat.json | 16 + .../r/styles/base-nova/font-noto-sans.json | 3 + .../r/styles/base-nova/font-nunito-sans.json | 3 + .../r/styles/base-nova/font-oxanium.json | 16 + .../styles/base-nova/font-source-sans-3.json | 16 + .../styles/base-nova/font-space-grotesk.json | 16 + .../r/styles/base-nova/font-tomorrow.json | 27 ++ apps/v4/public/r/styles/base-nova/item.json | 2 +- .../v4/public/r/styles/base-nova/popover.json | 2 +- .../v4/public/r/styles/base-nova/preview.json | 2 +- .../public/r/styles/base-nova/registry.json | 405 ++++++++++++++++++ apps/v4/public/r/styles/base-nova/sheet.json | 2 +- .../r/styles/base-vega/alert-dialog.json | 2 +- apps/v4/public/r/styles/base-vega/alert.json | 2 +- apps/v4/public/r/styles/base-vega/card.json | 2 +- apps/v4/public/r/styles/base-vega/demo.json | 2 +- apps/v4/public/r/styles/base-vega/dialog.json | 2 +- apps/v4/public/r/styles/base-vega/drawer.json | 2 +- apps/v4/public/r/styles/base-vega/empty.json | 2 +- .../base-vega/font-heading-dm-sans.json | 16 + .../base-vega/font-heading-figtree.json | 16 + .../base-vega/font-heading-geist-mono.json | 16 + .../styles/base-vega/font-heading-geist.json | 16 + .../base-vega/font-heading-ibm-plex-sans.json | 16 + .../font-heading-instrument-sans.json | 16 + .../styles/base-vega/font-heading-inter.json | 16 + .../font-heading-jetbrains-mono.json | 16 + .../r/styles/base-vega/font-heading-lora.json | 16 + .../base-vega/font-heading-manrope.json | 16 + .../base-vega/font-heading-merriweather.json | 16 + .../base-vega/font-heading-montserrat.json | 16 + .../base-vega/font-heading-noto-sans.json | 16 + .../base-vega/font-heading-noto-serif.json | 16 + .../base-vega/font-heading-nunito-sans.json | 16 + .../styles/base-vega/font-heading-outfit.json | 16 + .../base-vega/font-heading-oxanium.json | 16 + .../font-heading-playfair-display.json | 16 + .../base-vega/font-heading-public-sans.json | 16 + .../base-vega/font-heading-raleway.json | 16 + .../base-vega/font-heading-roboto-slab.json | 16 + .../styles/base-vega/font-heading-roboto.json | 16 + .../base-vega/font-heading-source-sans-3.json | 16 + .../base-vega/font-heading-space-grotesk.json | 16 + .../base-vega/font-heading-tomorrow.json | 27 ++ .../styles/base-vega/font-ibm-plex-sans.json | 16 + .../base-vega/font-instrument-sans.json | 16 + .../r/styles/base-vega/font-manrope.json | 16 + .../r/styles/base-vega/font-montserrat.json | 16 + .../r/styles/base-vega/font-noto-sans.json | 3 + .../r/styles/base-vega/font-nunito-sans.json | 3 + .../r/styles/base-vega/font-oxanium.json | 16 + .../styles/base-vega/font-source-sans-3.json | 16 + .../styles/base-vega/font-space-grotesk.json | 16 + .../r/styles/base-vega/font-tomorrow.json | 27 ++ apps/v4/public/r/styles/base-vega/item.json | 2 +- .../v4/public/r/styles/base-vega/popover.json | 2 +- .../v4/public/r/styles/base-vega/preview.json | 2 +- .../public/r/styles/base-vega/registry.json | 405 ++++++++++++++++++ apps/v4/public/r/styles/base-vega/sheet.json | 2 +- .../r/styles/radix-lyra/alert-dialog.json | 2 +- apps/v4/public/r/styles/radix-lyra/alert.json | 2 +- apps/v4/public/r/styles/radix-lyra/card.json | 2 +- apps/v4/public/r/styles/radix-lyra/demo.json | 2 +- .../v4/public/r/styles/radix-lyra/dialog.json | 2 +- .../v4/public/r/styles/radix-lyra/drawer.json | 2 +- apps/v4/public/r/styles/radix-lyra/empty.json | 2 +- .../radix-lyra/font-heading-dm-sans.json | 16 + .../radix-lyra/font-heading-figtree.json | 16 + .../radix-lyra/font-heading-geist-mono.json | 16 + .../styles/radix-lyra/font-heading-geist.json | 16 + .../font-heading-ibm-plex-sans.json | 16 + .../font-heading-instrument-sans.json | 16 + .../styles/radix-lyra/font-heading-inter.json | 16 + .../font-heading-jetbrains-mono.json | 16 + .../styles/radix-lyra/font-heading-lora.json | 16 + .../radix-lyra/font-heading-manrope.json | 16 + .../radix-lyra/font-heading-merriweather.json | 16 + .../radix-lyra/font-heading-montserrat.json | 16 + .../radix-lyra/font-heading-noto-sans.json | 16 + .../radix-lyra/font-heading-noto-serif.json | 16 + .../radix-lyra/font-heading-nunito-sans.json | 16 + .../radix-lyra/font-heading-outfit.json | 16 + .../radix-lyra/font-heading-oxanium.json | 16 + .../font-heading-playfair-display.json | 16 + .../radix-lyra/font-heading-public-sans.json | 16 + .../radix-lyra/font-heading-raleway.json | 16 + .../radix-lyra/font-heading-roboto-slab.json | 16 + .../radix-lyra/font-heading-roboto.json | 16 + .../font-heading-source-sans-3.json | 16 + .../font-heading-space-grotesk.json | 16 + .../radix-lyra/font-heading-tomorrow.json | 27 ++ .../styles/radix-lyra/font-ibm-plex-sans.json | 16 + .../radix-lyra/font-instrument-sans.json | 16 + .../r/styles/radix-lyra/font-manrope.json | 16 + .../r/styles/radix-lyra/font-montserrat.json | 16 + .../r/styles/radix-lyra/font-noto-sans.json | 3 + .../r/styles/radix-lyra/font-nunito-sans.json | 3 + .../r/styles/radix-lyra/font-oxanium.json | 16 + .../styles/radix-lyra/font-source-sans-3.json | 16 + .../styles/radix-lyra/font-space-grotesk.json | 16 + .../r/styles/radix-lyra/font-tomorrow.json | 27 ++ apps/v4/public/r/styles/radix-lyra/item.json | 2 +- .../public/r/styles/radix-lyra/popover.json | 2 +- .../public/r/styles/radix-lyra/preview.json | 2 +- .../public/r/styles/radix-lyra/registry.json | 405 ++++++++++++++++++ apps/v4/public/r/styles/radix-lyra/sheet.json | 2 +- .../r/styles/radix-maia/alert-dialog.json | 2 +- apps/v4/public/r/styles/radix-maia/alert.json | 2 +- apps/v4/public/r/styles/radix-maia/card.json | 2 +- apps/v4/public/r/styles/radix-maia/demo.json | 2 +- .../v4/public/r/styles/radix-maia/dialog.json | 2 +- .../v4/public/r/styles/radix-maia/drawer.json | 2 +- apps/v4/public/r/styles/radix-maia/empty.json | 2 +- .../radix-maia/font-heading-dm-sans.json | 16 + .../radix-maia/font-heading-figtree.json | 16 + .../radix-maia/font-heading-geist-mono.json | 16 + .../styles/radix-maia/font-heading-geist.json | 16 + .../font-heading-ibm-plex-sans.json | 16 + .../font-heading-instrument-sans.json | 16 + .../styles/radix-maia/font-heading-inter.json | 16 + .../font-heading-jetbrains-mono.json | 16 + .../styles/radix-maia/font-heading-lora.json | 16 + .../radix-maia/font-heading-manrope.json | 16 + .../radix-maia/font-heading-merriweather.json | 16 + .../radix-maia/font-heading-montserrat.json | 16 + .../radix-maia/font-heading-noto-sans.json | 16 + .../radix-maia/font-heading-noto-serif.json | 16 + .../radix-maia/font-heading-nunito-sans.json | 16 + .../radix-maia/font-heading-outfit.json | 16 + .../radix-maia/font-heading-oxanium.json | 16 + .../font-heading-playfair-display.json | 16 + .../radix-maia/font-heading-public-sans.json | 16 + .../radix-maia/font-heading-raleway.json | 16 + .../radix-maia/font-heading-roboto-slab.json | 16 + .../radix-maia/font-heading-roboto.json | 16 + .../font-heading-source-sans-3.json | 16 + .../font-heading-space-grotesk.json | 16 + .../radix-maia/font-heading-tomorrow.json | 27 ++ .../styles/radix-maia/font-ibm-plex-sans.json | 16 + .../radix-maia/font-instrument-sans.json | 16 + .../r/styles/radix-maia/font-manrope.json | 16 + .../r/styles/radix-maia/font-montserrat.json | 16 + .../r/styles/radix-maia/font-noto-sans.json | 3 + .../r/styles/radix-maia/font-nunito-sans.json | 3 + .../r/styles/radix-maia/font-oxanium.json | 16 + .../styles/radix-maia/font-source-sans-3.json | 16 + .../styles/radix-maia/font-space-grotesk.json | 16 + .../r/styles/radix-maia/font-tomorrow.json | 27 ++ apps/v4/public/r/styles/radix-maia/item.json | 2 +- .../public/r/styles/radix-maia/popover.json | 2 +- .../public/r/styles/radix-maia/preview.json | 2 +- .../public/r/styles/radix-maia/registry.json | 405 ++++++++++++++++++ apps/v4/public/r/styles/radix-maia/sheet.json | 2 +- .../r/styles/radix-mira/alert-dialog.json | 2 +- apps/v4/public/r/styles/radix-mira/alert.json | 2 +- apps/v4/public/r/styles/radix-mira/card.json | 2 +- apps/v4/public/r/styles/radix-mira/demo.json | 2 +- .../v4/public/r/styles/radix-mira/dialog.json | 2 +- .../v4/public/r/styles/radix-mira/drawer.json | 2 +- apps/v4/public/r/styles/radix-mira/empty.json | 2 +- .../radix-mira/font-heading-dm-sans.json | 16 + .../radix-mira/font-heading-figtree.json | 16 + .../radix-mira/font-heading-geist-mono.json | 16 + .../styles/radix-mira/font-heading-geist.json | 16 + .../font-heading-ibm-plex-sans.json | 16 + .../font-heading-instrument-sans.json | 16 + .../styles/radix-mira/font-heading-inter.json | 16 + .../font-heading-jetbrains-mono.json | 16 + .../styles/radix-mira/font-heading-lora.json | 16 + .../radix-mira/font-heading-manrope.json | 16 + .../radix-mira/font-heading-merriweather.json | 16 + .../radix-mira/font-heading-montserrat.json | 16 + .../radix-mira/font-heading-noto-sans.json | 16 + .../radix-mira/font-heading-noto-serif.json | 16 + .../radix-mira/font-heading-nunito-sans.json | 16 + .../radix-mira/font-heading-outfit.json | 16 + .../radix-mira/font-heading-oxanium.json | 16 + .../font-heading-playfair-display.json | 16 + .../radix-mira/font-heading-public-sans.json | 16 + .../radix-mira/font-heading-raleway.json | 16 + .../radix-mira/font-heading-roboto-slab.json | 16 + .../radix-mira/font-heading-roboto.json | 16 + .../font-heading-source-sans-3.json | 16 + .../font-heading-space-grotesk.json | 16 + .../radix-mira/font-heading-tomorrow.json | 27 ++ .../styles/radix-mira/font-ibm-plex-sans.json | 16 + .../radix-mira/font-instrument-sans.json | 16 + .../r/styles/radix-mira/font-manrope.json | 16 + .../r/styles/radix-mira/font-montserrat.json | 16 + .../r/styles/radix-mira/font-noto-sans.json | 3 + .../r/styles/radix-mira/font-nunito-sans.json | 3 + .../r/styles/radix-mira/font-oxanium.json | 16 + .../styles/radix-mira/font-source-sans-3.json | 16 + .../styles/radix-mira/font-space-grotesk.json | 16 + .../r/styles/radix-mira/font-tomorrow.json | 27 ++ apps/v4/public/r/styles/radix-mira/item.json | 2 +- .../public/r/styles/radix-mira/popover.json | 2 +- .../public/r/styles/radix-mira/preview.json | 2 +- .../public/r/styles/radix-mira/registry.json | 405 ++++++++++++++++++ apps/v4/public/r/styles/radix-mira/sheet.json | 2 +- .../r/styles/radix-nova/alert-dialog.json | 2 +- apps/v4/public/r/styles/radix-nova/alert.json | 2 +- apps/v4/public/r/styles/radix-nova/card.json | 2 +- apps/v4/public/r/styles/radix-nova/demo.json | 2 +- .../v4/public/r/styles/radix-nova/dialog.json | 2 +- .../v4/public/r/styles/radix-nova/drawer.json | 2 +- apps/v4/public/r/styles/radix-nova/empty.json | 2 +- .../radix-nova/font-heading-dm-sans.json | 16 + .../radix-nova/font-heading-figtree.json | 16 + .../radix-nova/font-heading-geist-mono.json | 16 + .../styles/radix-nova/font-heading-geist.json | 16 + .../font-heading-ibm-plex-sans.json | 16 + .../font-heading-instrument-sans.json | 16 + .../styles/radix-nova/font-heading-inter.json | 16 + .../font-heading-jetbrains-mono.json | 16 + .../styles/radix-nova/font-heading-lora.json | 16 + .../radix-nova/font-heading-manrope.json | 16 + .../radix-nova/font-heading-merriweather.json | 16 + .../radix-nova/font-heading-montserrat.json | 16 + .../radix-nova/font-heading-noto-sans.json | 16 + .../radix-nova/font-heading-noto-serif.json | 16 + .../radix-nova/font-heading-nunito-sans.json | 16 + .../radix-nova/font-heading-outfit.json | 16 + .../radix-nova/font-heading-oxanium.json | 16 + .../font-heading-playfair-display.json | 16 + .../radix-nova/font-heading-public-sans.json | 16 + .../radix-nova/font-heading-raleway.json | 16 + .../radix-nova/font-heading-roboto-slab.json | 16 + .../radix-nova/font-heading-roboto.json | 16 + .../font-heading-source-sans-3.json | 16 + .../font-heading-space-grotesk.json | 16 + .../radix-nova/font-heading-tomorrow.json | 27 ++ .../styles/radix-nova/font-ibm-plex-sans.json | 16 + .../radix-nova/font-instrument-sans.json | 16 + .../r/styles/radix-nova/font-manrope.json | 16 + .../r/styles/radix-nova/font-montserrat.json | 16 + .../r/styles/radix-nova/font-noto-sans.json | 3 + .../r/styles/radix-nova/font-nunito-sans.json | 3 + .../r/styles/radix-nova/font-oxanium.json | 16 + .../styles/radix-nova/font-source-sans-3.json | 16 + .../styles/radix-nova/font-space-grotesk.json | 16 + .../r/styles/radix-nova/font-tomorrow.json | 27 ++ apps/v4/public/r/styles/radix-nova/item.json | 2 +- .../public/r/styles/radix-nova/popover.json | 2 +- .../public/r/styles/radix-nova/preview.json | 2 +- .../public/r/styles/radix-nova/registry.json | 405 ++++++++++++++++++ apps/v4/public/r/styles/radix-nova/sheet.json | 2 +- .../r/styles/radix-vega/alert-dialog.json | 2 +- apps/v4/public/r/styles/radix-vega/alert.json | 2 +- apps/v4/public/r/styles/radix-vega/card.json | 2 +- apps/v4/public/r/styles/radix-vega/demo.json | 2 +- .../v4/public/r/styles/radix-vega/dialog.json | 2 +- .../v4/public/r/styles/radix-vega/drawer.json | 2 +- apps/v4/public/r/styles/radix-vega/empty.json | 2 +- .../radix-vega/font-heading-dm-sans.json | 16 + .../radix-vega/font-heading-figtree.json | 16 + .../radix-vega/font-heading-geist-mono.json | 16 + .../styles/radix-vega/font-heading-geist.json | 16 + .../font-heading-ibm-plex-sans.json | 16 + .../font-heading-instrument-sans.json | 16 + .../styles/radix-vega/font-heading-inter.json | 16 + .../font-heading-jetbrains-mono.json | 16 + .../styles/radix-vega/font-heading-lora.json | 16 + .../radix-vega/font-heading-manrope.json | 16 + .../radix-vega/font-heading-merriweather.json | 16 + .../radix-vega/font-heading-montserrat.json | 16 + .../radix-vega/font-heading-noto-sans.json | 16 + .../radix-vega/font-heading-noto-serif.json | 16 + .../radix-vega/font-heading-nunito-sans.json | 16 + .../radix-vega/font-heading-outfit.json | 16 + .../radix-vega/font-heading-oxanium.json | 16 + .../font-heading-playfair-display.json | 16 + .../radix-vega/font-heading-public-sans.json | 16 + .../radix-vega/font-heading-raleway.json | 16 + .../radix-vega/font-heading-roboto-slab.json | 16 + .../radix-vega/font-heading-roboto.json | 16 + .../font-heading-source-sans-3.json | 16 + .../font-heading-space-grotesk.json | 16 + .../radix-vega/font-heading-tomorrow.json | 27 ++ .../styles/radix-vega/font-ibm-plex-sans.json | 16 + .../radix-vega/font-instrument-sans.json | 16 + .../r/styles/radix-vega/font-manrope.json | 16 + .../r/styles/radix-vega/font-montserrat.json | 16 + .../r/styles/radix-vega/font-noto-sans.json | 3 + .../r/styles/radix-vega/font-nunito-sans.json | 3 + .../r/styles/radix-vega/font-oxanium.json | 16 + .../styles/radix-vega/font-source-sans-3.json | 16 + .../styles/radix-vega/font-space-grotesk.json | 16 + .../r/styles/radix-vega/font-tomorrow.json | 27 ++ apps/v4/public/r/styles/radix-vega/item.json | 2 +- .../public/r/styles/radix-vega/popover.json | 2 +- .../public/r/styles/radix-vega/preview.json | 2 +- .../public/r/styles/radix-vega/registry.json | 405 ++++++++++++++++++ apps/v4/public/r/styles/radix-vega/sheet.json | 2 +- apps/v4/registry/bases/README.md | 15 + .../blocks/preview/cards/bar-chart-card.tsx | 33 +- .../blocks/preview/cards/contributors.tsx | 2 +- .../base/blocks/preview/cards/invoice.tsx | 2 +- .../blocks/preview/cards/pie-chart-card.tsx | 5 - .../base/blocks/preview/cards/shortcuts.tsx | 83 ++-- .../blocks/preview/cards/style-overview.tsx | 21 +- .../preview/cards/typography-specimen.tsx | 53 +++ .../base/blocks/preview/cards/ui-elements.tsx | 2 +- .../preview/cards/weekly-fitness-summary.tsx | 5 + .../bases/base/blocks/preview/index.tsx | 110 ++--- apps/v4/registry/bases/base/examples/demo.tsx | 30 +- .../registry/bases/base/ui/alert-dialog.tsx | 2 +- apps/v4/registry/bases/base/ui/alert.tsx | 2 +- apps/v4/registry/bases/base/ui/card.tsx | 2 +- apps/v4/registry/bases/base/ui/dialog.tsx | 2 +- apps/v4/registry/bases/base/ui/drawer.tsx | 2 +- apps/v4/registry/bases/base/ui/empty.tsx | 2 +- apps/v4/registry/bases/base/ui/item.tsx | 2 +- apps/v4/registry/bases/base/ui/popover.tsx | 2 +- apps/v4/registry/bases/base/ui/sheet.tsx | 2 +- .../blocks/preview/cards/bar-chart-card.tsx | 33 +- .../blocks/preview/cards/contributors.tsx | 2 +- .../radix/blocks/preview/cards/invoice.tsx | 2 +- .../blocks/preview/cards/pie-chart-card.tsx | 5 - .../radix/blocks/preview/cards/shortcuts.tsx | 83 ++-- .../blocks/preview/cards/style-overview.tsx | 21 +- .../preview/cards/typography-specimen.tsx | 53 +++ .../blocks/preview/cards/ui-elements.tsx | 2 +- .../preview/cards/weekly-fitness-summary.tsx | 5 + .../bases/radix/blocks/preview/index.tsx | 110 ++--- .../v4/registry/bases/radix/examples/demo.tsx | 30 +- .../registry/bases/radix/ui/alert-dialog.tsx | 2 +- apps/v4/registry/bases/radix/ui/alert.tsx | 2 +- apps/v4/registry/bases/radix/ui/card.tsx | 2 +- apps/v4/registry/bases/radix/ui/dialog.tsx | 2 +- apps/v4/registry/bases/radix/ui/drawer.tsx | 2 +- apps/v4/registry/bases/radix/ui/empty.tsx | 2 +- apps/v4/registry/bases/radix/ui/item.tsx | 2 +- apps/v4/registry/bases/radix/ui/popover.tsx | 2 +- apps/v4/registry/bases/radix/ui/sheet.tsx | 2 +- apps/v4/registry/config.test.ts | 85 ++++ apps/v4/registry/config.ts | 90 +++- apps/v4/registry/directory.json | 12 +- apps/v4/registry/fonts.ts | 247 ++--------- apps/v4/registry/themes.ts | 140 +++--- apps/v4/scripts/build-registry.mts | 12 +- apps/v4/styles/globals.css | 4 + packages/shadcn/src/commands/diff.ts | 37 +- packages/shadcn/src/commands/init.ts | 2 +- packages/shadcn/src/preset/index.ts | 3 + packages/shadcn/src/preset/preset.test.ts | 67 ++- packages/shadcn/src/preset/preset.ts | 69 ++- packages/shadcn/src/preset/presets.test.ts | 40 ++ packages/shadcn/src/preset/presets.ts | 23 +- .../shadcn/src/styles/transform-style-map.ts | 1 + packages/shadcn/src/templates/monorepo.ts | 35 +- .../shadcn/src/utils/add-components.test.ts | 205 +++++++++ packages/shadcn/src/utils/add-components.ts | 6 + packages/shadcn/src/utils/dry-run.ts | 10 +- packages/shadcn/src/utils/font-markers.ts | 45 ++ packages/shadcn/src/utils/index.ts | 1 + .../shadcn/src/utils/transformers/index.ts | 1 + .../transformers/transform-cleanup.test.ts | 17 + .../utils/transformers/transform-cleanup.ts | 22 +- .../utils/transformers/transform-font.test.ts | 163 +++++++ .../src/utils/transformers/transform-font.ts | 174 ++++++++ .../shadcn/src/utils/updaters/update-files.ts | 4 + .../src/utils/updaters/update-fonts.test.ts | 147 ++++++- .../shadcn/src/utils/updaters/update-fonts.ts | 127 ++++-- 615 files changed, 13274 insertions(+), 1380 deletions(-) create mode 100644 .changeset/short-colts-go.md create mode 100644 .changeset/spicy-walls-visit.md create mode 100644 .cursor/rules/registry-bases-parity.mdc create mode 100644 apps/v4/app/(create)/components/chart-color-picker.tsx create mode 100644 apps/v4/app/(create)/init/parse-config.test.ts create mode 100644 apps/v4/app/(create)/lib/preset-code.ts create mode 100644 apps/v4/app/(create)/lib/preset-query.test.ts create mode 100644 apps/v4/app/(create)/lib/preset-query.ts create mode 100644 apps/v4/app/(create)/lib/v0.test.ts create mode 100644 apps/v4/lib/font-definitions.ts create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-dm-sans.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-figtree.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-geist-mono.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-geist.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-instrument-sans.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-inter.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-jetbrains-mono.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-lora.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-manrope.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-merriweather.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-montserrat.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-noto-sans.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-noto-serif.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-nunito-sans.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-outfit.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-oxanium.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-playfair-display.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-public-sans.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-raleway.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-roboto-slab.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-roboto.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-source-sans-3.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-space-grotesk.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-heading-tomorrow.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-instrument-sans.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-manrope.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-montserrat.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-oxanium.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-source-sans-3.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-space-grotesk.json create mode 100644 apps/v4/public/r/styles/base-lyra/font-tomorrow.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-dm-sans.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-figtree.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-geist-mono.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-geist.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-instrument-sans.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-inter.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-jetbrains-mono.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-lora.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-manrope.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-merriweather.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-montserrat.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-noto-sans.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-noto-serif.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-nunito-sans.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-outfit.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-oxanium.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-playfair-display.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-public-sans.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-raleway.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-roboto-slab.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-roboto.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-source-sans-3.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-space-grotesk.json create mode 100644 apps/v4/public/r/styles/base-maia/font-heading-tomorrow.json create mode 100644 apps/v4/public/r/styles/base-maia/font-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/base-maia/font-instrument-sans.json create mode 100644 apps/v4/public/r/styles/base-maia/font-manrope.json create mode 100644 apps/v4/public/r/styles/base-maia/font-montserrat.json create mode 100644 apps/v4/public/r/styles/base-maia/font-oxanium.json create mode 100644 apps/v4/public/r/styles/base-maia/font-source-sans-3.json create mode 100644 apps/v4/public/r/styles/base-maia/font-space-grotesk.json create mode 100644 apps/v4/public/r/styles/base-maia/font-tomorrow.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-dm-sans.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-figtree.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-geist-mono.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-geist.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-instrument-sans.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-inter.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-jetbrains-mono.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-lora.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-manrope.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-merriweather.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-montserrat.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-noto-sans.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-noto-serif.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-nunito-sans.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-outfit.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-oxanium.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-playfair-display.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-public-sans.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-raleway.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-roboto-slab.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-roboto.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-source-sans-3.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-space-grotesk.json create mode 100644 apps/v4/public/r/styles/base-mira/font-heading-tomorrow.json create mode 100644 apps/v4/public/r/styles/base-mira/font-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/base-mira/font-instrument-sans.json create mode 100644 apps/v4/public/r/styles/base-mira/font-manrope.json create mode 100644 apps/v4/public/r/styles/base-mira/font-montserrat.json create mode 100644 apps/v4/public/r/styles/base-mira/font-oxanium.json create mode 100644 apps/v4/public/r/styles/base-mira/font-source-sans-3.json create mode 100644 apps/v4/public/r/styles/base-mira/font-space-grotesk.json create mode 100644 apps/v4/public/r/styles/base-mira/font-tomorrow.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-dm-sans.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-figtree.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-geist-mono.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-geist.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-instrument-sans.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-inter.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-jetbrains-mono.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-lora.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-manrope.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-merriweather.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-montserrat.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-noto-sans.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-noto-serif.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-nunito-sans.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-outfit.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-oxanium.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-playfair-display.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-public-sans.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-raleway.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-roboto-slab.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-roboto.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-source-sans-3.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-space-grotesk.json create mode 100644 apps/v4/public/r/styles/base-nova/font-heading-tomorrow.json create mode 100644 apps/v4/public/r/styles/base-nova/font-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/base-nova/font-instrument-sans.json create mode 100644 apps/v4/public/r/styles/base-nova/font-manrope.json create mode 100644 apps/v4/public/r/styles/base-nova/font-montserrat.json create mode 100644 apps/v4/public/r/styles/base-nova/font-oxanium.json create mode 100644 apps/v4/public/r/styles/base-nova/font-source-sans-3.json create mode 100644 apps/v4/public/r/styles/base-nova/font-space-grotesk.json create mode 100644 apps/v4/public/r/styles/base-nova/font-tomorrow.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-dm-sans.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-figtree.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-geist-mono.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-geist.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-instrument-sans.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-inter.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-jetbrains-mono.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-lora.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-manrope.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-merriweather.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-montserrat.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-noto-sans.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-noto-serif.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-nunito-sans.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-outfit.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-oxanium.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-playfair-display.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-public-sans.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-raleway.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-roboto-slab.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-roboto.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-source-sans-3.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-space-grotesk.json create mode 100644 apps/v4/public/r/styles/base-vega/font-heading-tomorrow.json create mode 100644 apps/v4/public/r/styles/base-vega/font-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/base-vega/font-instrument-sans.json create mode 100644 apps/v4/public/r/styles/base-vega/font-manrope.json create mode 100644 apps/v4/public/r/styles/base-vega/font-montserrat.json create mode 100644 apps/v4/public/r/styles/base-vega/font-oxanium.json create mode 100644 apps/v4/public/r/styles/base-vega/font-source-sans-3.json create mode 100644 apps/v4/public/r/styles/base-vega/font-space-grotesk.json create mode 100644 apps/v4/public/r/styles/base-vega/font-tomorrow.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-dm-sans.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-figtree.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-geist-mono.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-geist.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-instrument-sans.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-inter.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-jetbrains-mono.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-lora.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-manrope.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-merriweather.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-montserrat.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-noto-sans.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-noto-serif.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-nunito-sans.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-outfit.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-oxanium.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-playfair-display.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-public-sans.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-raleway.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-roboto-slab.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-roboto.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-source-sans-3.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-space-grotesk.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-heading-tomorrow.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-instrument-sans.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-manrope.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-montserrat.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-oxanium.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-source-sans-3.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-space-grotesk.json create mode 100644 apps/v4/public/r/styles/radix-lyra/font-tomorrow.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-dm-sans.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-figtree.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-geist-mono.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-geist.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-instrument-sans.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-inter.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-jetbrains-mono.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-lora.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-manrope.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-merriweather.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-montserrat.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-noto-sans.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-noto-serif.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-nunito-sans.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-outfit.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-oxanium.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-playfair-display.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-public-sans.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-raleway.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-roboto-slab.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-roboto.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-source-sans-3.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-space-grotesk.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-heading-tomorrow.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-instrument-sans.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-manrope.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-montserrat.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-oxanium.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-source-sans-3.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-space-grotesk.json create mode 100644 apps/v4/public/r/styles/radix-maia/font-tomorrow.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-dm-sans.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-figtree.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-geist-mono.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-geist.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-instrument-sans.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-inter.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-jetbrains-mono.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-lora.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-manrope.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-merriweather.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-montserrat.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-noto-sans.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-noto-serif.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-nunito-sans.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-outfit.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-oxanium.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-playfair-display.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-public-sans.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-raleway.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-roboto-slab.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-roboto.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-source-sans-3.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-space-grotesk.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-heading-tomorrow.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-instrument-sans.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-manrope.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-montserrat.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-oxanium.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-source-sans-3.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-space-grotesk.json create mode 100644 apps/v4/public/r/styles/radix-mira/font-tomorrow.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-dm-sans.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-figtree.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-geist-mono.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-geist.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-instrument-sans.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-inter.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-jetbrains-mono.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-lora.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-manrope.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-merriweather.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-montserrat.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-noto-sans.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-noto-serif.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-nunito-sans.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-outfit.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-oxanium.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-playfair-display.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-public-sans.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-raleway.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-roboto-slab.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-roboto.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-source-sans-3.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-space-grotesk.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-heading-tomorrow.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-instrument-sans.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-manrope.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-montserrat.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-oxanium.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-source-sans-3.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-space-grotesk.json create mode 100644 apps/v4/public/r/styles/radix-nova/font-tomorrow.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-dm-sans.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-figtree.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-geist-mono.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-geist.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-instrument-sans.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-inter.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-jetbrains-mono.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-lora.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-manrope.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-merriweather.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-montserrat.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-noto-sans.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-noto-serif.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-nunito-sans.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-outfit.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-oxanium.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-playfair-display.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-public-sans.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-raleway.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-roboto-slab.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-roboto.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-source-sans-3.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-space-grotesk.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-heading-tomorrow.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-ibm-plex-sans.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-instrument-sans.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-manrope.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-montserrat.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-oxanium.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-source-sans-3.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-space-grotesk.json create mode 100644 apps/v4/public/r/styles/radix-vega/font-tomorrow.json create mode 100644 apps/v4/registry/bases/README.md create mode 100644 apps/v4/registry/bases/base/blocks/preview/cards/typography-specimen.tsx create mode 100644 apps/v4/registry/bases/radix/blocks/preview/cards/typography-specimen.tsx create mode 100644 apps/v4/registry/config.test.ts create mode 100644 packages/shadcn/src/utils/add-components.test.ts create mode 100644 packages/shadcn/src/utils/font-markers.ts create mode 100644 packages/shadcn/src/utils/transformers/transform-font.test.ts create mode 100644 packages/shadcn/src/utils/transformers/transform-font.ts diff --git a/.changeset/short-colts-go.md b/.changeset/short-colts-go.md new file mode 100644 index 0000000000..095e08dd73 --- /dev/null +++ b/.changeset/short-colts-go.md @@ -0,0 +1,5 @@ +--- +"shadcn": minor +--- + +add fontHeading to presets diff --git a/.changeset/spicy-walls-visit.md b/.changeset/spicy-walls-visit.md new file mode 100644 index 0000000000..69a81c5a53 --- /dev/null +++ b/.changeset/spicy-walls-visit.md @@ -0,0 +1,5 @@ +--- +"shadcn": minor +--- + +add chartColor diff --git a/.cursor/rules/registry-bases-parity.mdc b/.cursor/rules/registry-bases-parity.mdc new file mode 100644 index 0000000000..08ebd58b94 --- /dev/null +++ b/.cursor/rules/registry-bases-parity.mdc @@ -0,0 +1,22 @@ +--- +description: Keep registry base and radix trees in sync when editing shared UI +globs: apps/v4/registry/bases/**/* +alwaysApply: false +--- + +# Registry bases: Base UI ↔ Radix parity + +`apps/v4/registry/bases/base` and `apps/v4/registry/bases/radix` are **parallel registries**. Anything that exists in both trees for the same purpose (preview blocks, mirrored examples, shared card layouts, etc.) **must stay in sync**. + +## When editing + +- If you change a file under **`bases/base/...`**, apply the **same behavioral and visual change** to the matching path under **`bases/radix/...`** (and the reverse). +- Only diverge where APIs differ (e.g. import paths like `@/registry/bases/base/ui/*` vs `@/registry/bases/radix/ui/*`, or Base UI vs Radix component props). +- Do **not** update only one side unless the user explicitly asks for a single-base change. + +## Typical mirrored paths + +- `blocks/preview/**` — preview cards and blocks +- Parallel `ui/*` components when both exist for the same component + +After edits, briefly confirm both trees were updated (or state why one side is intentionally unchanged). diff --git a/apps/v4/app/(app)/docs/changelog/page.tsx b/apps/v4/app/(app)/docs/changelog/page.tsx index 7d08c2be93..b9193beeb0 100644 --- a/apps/v4/app/(app)/docs/changelog/page.tsx +++ b/apps/v4/app/(app)/docs/changelog/page.tsx @@ -79,7 +79,7 @@ export default function ChangelogPage() { })} {olderPages.length > 0 && (
-

+

More Updates

diff --git a/apps/v4/app/(create)/components/chart-color-picker.tsx b/apps/v4/app/(create)/components/chart-color-picker.tsx new file mode 100644 index 0000000000..33b3a12a5e --- /dev/null +++ b/apps/v4/app/(create)/components/chart-color-picker.tsx @@ -0,0 +1,136 @@ +"use client" + +import * as React from "react" + +import { useMounted } from "@/hooks/use-mounted" +import { + BASE_COLORS, + getThemesForBaseColor, + type ChartColorName, +} from "@/registry/config" +import { LockButton } from "@/app/(create)/components/lock-button" +import { + Picker, + PickerContent, + PickerGroup, + PickerRadioGroup, + PickerRadioItem, + PickerSeparator, + PickerTrigger, +} from "@/app/(create)/components/picker" +import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" + +export function ChartColorPicker({ + isMobile, + anchorRef, +}: { + isMobile: boolean + anchorRef: React.RefObject +}) { + const mounted = useMounted() + const [params, setParams] = useDesignSystemSearchParams() + + const availableChartColors = React.useMemo( + () => getThemesForBaseColor(params.baseColor), + [params.baseColor] + ) + + const currentChartColor = React.useMemo( + () => + availableChartColors.find((theme) => theme.name === params.chartColor), + [availableChartColors, params.chartColor] + ) + + const currentChartColorIsBaseColor = React.useMemo( + () => BASE_COLORS.find((baseColor) => baseColor.name === params.chartColor), + [params.chartColor] + ) + + React.useEffect(() => { + if (!currentChartColor && availableChartColors.length > 0) { + setParams({ chartColor: availableChartColors[0].name }) + } + }, [currentChartColor, availableChartColors, setParams]) + + return ( +
+ + +
+
Chart Color
+
+ {currentChartColor?.title} +
+
+ {mounted && ( +
+ )} + + + { + setParams({ chartColor: value as ChartColorName }) + }} + > + + {availableChartColors + .filter((theme) => + BASE_COLORS.find((baseColor) => baseColor.name === theme.name) + ) + .map((theme) => ( + + {theme.title} + + ))} + + + + {availableChartColors + .filter( + (theme) => + !BASE_COLORS.find( + (baseColor) => baseColor.name === theme.name + ) + ) + .map((theme) => ( + + {theme.title} + + ))} + + + + + +
+ ) +} diff --git a/apps/v4/app/(create)/components/customizer.tsx b/apps/v4/app/(create)/components/customizer.tsx index f1e57620b6..d42269307f 100644 --- a/apps/v4/app/(create)/components/customizer.tsx +++ b/apps/v4/app/(create)/components/customizer.tsx @@ -7,7 +7,7 @@ import { CardFooter, CardHeader, } from "@/examples/base/ui/card" -import { FieldGroup } from "@/examples/base/ui/field" +import { FieldGroup, FieldSeparator } from "@/examples/base/ui/field" import { type RegistryItem } from "shadcn/schema" import { useIsMobile } from "@/hooks/use-mobile" @@ -16,6 +16,7 @@ import { MenuAccentPicker } from "@/app/(create)/components/accent-picker" import { ActionMenu } from "@/app/(create)/components/action-menu" import { BaseColorPicker } from "@/app/(create)/components/base-color-picker" import { BasePicker } from "@/app/(create)/components/base-picker" +import { ChartColorPicker } from "@/app/(create)/components/chart-color-picker" import { CopyPreset } from "@/app/(create)/components/copy-preset" import { FontPicker } from "@/app/(create)/components/font-picker" import { IconLibraryPicker } from "@/app/(create)/components/icon-library-picker" @@ -27,7 +28,7 @@ import { ResetDialog } from "@/app/(create)/components/reset-button" import { StylePicker } from "@/app/(create)/components/style-picker" import { ThemePicker } from "@/app/(create)/components/theme-picker" import { V0Button } from "@/app/(create)/components/v0-button" -import { FONTS } from "@/app/(create)/lib/fonts" +import { FONT_HEADING_OPTIONS, FONTS } from "@/app/(create)/lib/fonts" import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" export function Customizer({ @@ -54,22 +55,40 @@ export function Customizer({ - + {isMobile && } + + + + + + - + diff --git a/apps/v4/app/(create)/components/design-system-provider.tsx b/apps/v4/app/(create)/components/design-system-provider.tsx index 31453c1051..c70d80872a 100644 --- a/apps/v4/app/(create)/components/design-system-provider.tsx +++ b/apps/v4/app/(create)/components/design-system-provider.tsx @@ -64,18 +64,37 @@ export function DesignSystemProvider({ history: "replace", // …or push updates into the iframe history. }) const [isReady, setIsReady] = React.useState(false) - const { style, theme, font, baseColor, menuAccent, menuColor, radius } = - searchParams + const { + style, + theme, + font, + fontHeading, + baseColor, + chartColor, + menuAccent, + menuColor, + radius, + } = searchParams const effectiveRadius = style === "lyra" ? "none" : radius const selectedFont = React.useMemo( () => FONTS.find((fontOption) => fontOption.value === font), [font] ) + const selectedHeadingFont = React.useMemo(() => { + if (fontHeading === "inherit" || fontHeading === font) { + return selectedFont + } + + return FONTS.find((fontOption) => fontOption.value === fontHeading) + }, [font, fontHeading, selectedFont]) const initialFontSansRef = React.useRef(null) + const initialFontHeadingRef = React.useRef(null) React.useEffect(() => { initialFontSansRef.current = document.documentElement.style.getPropertyValue("--font-sans") + initialFontHeadingRef.current = + document.documentElement.style.getPropertyValue("--font-heading") return () => { removeManagedBodyClasses(document.body) @@ -86,10 +105,18 @@ export function DesignSystemProvider({ "--font-sans", initialFontSansRef.current ) - return + } else { + document.documentElement.style.removeProperty("--font-sans") } - document.documentElement.style.removeProperty("--font-sans") + if (initialFontHeadingRef.current) { + document.documentElement.style.setProperty( + "--font-heading", + initialFontHeadingRef.current + ) + } else { + document.documentElement.style.removeProperty("--font-heading") + } } }, []) @@ -124,12 +151,29 @@ export function DesignSystemProvider({ // Always set --font-sans for the preview so the selected font is visible. // The font type (sans/serif/mono) is metadata for the CLI updater. if (selectedFont) { - const fontFamily = selectedFont.font.style.fontFamily - document.documentElement.style.setProperty("--font-sans", fontFamily) + document.documentElement.style.setProperty( + "--font-sans", + selectedFont.font.style.fontFamily + ) + } + + if (selectedHeadingFont) { + document.documentElement.style.setProperty( + "--font-heading", + selectedHeadingFont.font.style.fontFamily + ) } setIsReady(true) - }, [style, theme, font, baseColor, selectedFont]) + }, [ + style, + theme, + font, + fontHeading, + baseColor, + selectedFont, + selectedHeadingFont, + ]) const registryTheme = React.useMemo(() => { if (!baseColor || !theme || !menuAccent || !effectiveRadius) { @@ -140,12 +184,13 @@ export function DesignSystemProvider({ ...DEFAULT_CONFIG, baseColor, theme, + chartColor, menuAccent, radius: effectiveRadius, } return buildRegistryTheme(config) - }, [baseColor, theme, menuAccent, effectiveRadius]) + }, [baseColor, theme, chartColor, menuAccent, effectiveRadius]) // Use useLayoutEffect for synchronous CSS var updates. React.useLayoutEffect(() => { diff --git a/apps/v4/app/(create)/components/font-picker.tsx b/apps/v4/app/(create)/components/font-picker.tsx index 895b735429..db2f1c0bc1 100644 --- a/apps/v4/app/(create)/components/font-picker.tsx +++ b/apps/v4/app/(create)/components/font-picker.tsx @@ -2,13 +2,6 @@ import * as React from "react" -import { - Item, - ItemContent, - ItemDescription, - ItemTitle, -} from "@/registry/bases/radix/ui/item" -import { type FontValue } from "@/registry/config" import { LockButton } from "@/app/(create)/components/lock-button" import { Picker, @@ -20,28 +13,68 @@ import { PickerSeparator, PickerTrigger, } from "@/app/(create)/components/picker" -import { type Font } from "@/app/(create)/lib/fonts" -import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" +import { FONTS } from "@/app/(create)/lib/fonts" +import { + useDesignSystemSearchParams, + type DesignSystemSearchParams, +} from "@/app/(create)/lib/search-params" + +type FontPickerOption = { + name: string + value: string + type: string + font: { + style: { + fontFamily: string + } + } | null +} export function FontPicker({ + label, + param, fonts, isMobile, anchorRef, }: { - fonts: readonly Font[] + label: string + param: "font" | "fontHeading" + fonts: readonly FontPickerOption[] isMobile: boolean anchorRef: React.RefObject }) { const [params, setParams] = useDesignSystemSearchParams() + const currentValue = param === "font" ? params.font : params.fontHeading + const handleFontChange = React.useCallback( + (value: string) => { + setParams({ + [param]: value, + } as Partial) + }, + [param, setParams] + ) const currentFont = React.useMemo( - () => fonts.find((font) => font.value === params.font), - [fonts, params.font] + () => fonts.find((font) => font.value === currentValue), + [fonts, currentValue] ) + const currentBodyFont = React.useMemo( + () => FONTS.find((font) => font.value === params.font), + [params.font] + ) + const inheritsBodyFont = param === "fontHeading" && currentValue === "inherit" + const displayFontName = inheritsBodyFont + ? currentBodyFont?.name + : currentFont?.name + const inheritFontLabel = currentBodyFont ? currentBodyFont.name : "Body font" const groupedFonts = React.useMemo(() => { - const groups = new Map() + const pickerFonts = + param === "fontHeading" + ? fonts.filter((font) => font.value !== "inherit") + : fonts + const groups = new Map() - for (const font of fonts) { + for (const font of pickerFonts) { const existing = groups.get(font.type) if (existing) { existing.push(font) @@ -56,21 +89,25 @@ export function FontPicker({ label: `${type.charAt(0).toUpperCase()}${type.slice(1)}`, items, })) - }, [fonts]) + }, [fonts, param]) return (
-
Font
+
{label}
- {currentFont?.name} + {displayFontName}
Aa
@@ -82,11 +119,19 @@ export function FontPicker({ className="max-h-96" > { - setParams({ font: value as FontValue }) - }} + value={currentValue} + onValueChange={handleFontChange} > + {param === "fontHeading" ? ( + <> + + + {inheritFontLabel} + + + + + ) : null} {groupedFonts.map((group) => ( {group.label} @@ -105,7 +150,7 @@ export function FontPicker({
diff --git a/apps/v4/app/(create)/components/preset-picker.tsx b/apps/v4/app/(create)/components/preset-picker.tsx index d30129acaa..40ae28a98e 100644 --- a/apps/v4/app/(create)/components/preset-picker.tsx +++ b/apps/v4/app/(create)/components/preset-picker.tsx @@ -31,8 +31,10 @@ export function PresetPicker({ preset.style === params.style && preset.baseColor === params.baseColor && preset.theme === params.theme && + preset.chartColor === params.chartColor && preset.iconLibrary === params.iconLibrary && preset.font === params.font && + preset.fontHeading === params.fontHeading && preset.menuAccent === params.menuAccent && preset.menuColor === params.menuColor && preset.radius === params.radius @@ -43,8 +45,10 @@ export function PresetPicker({ params.style, params.baseColor, params.theme, + params.chartColor, params.iconLibrary, params.font, + params.fontHeading, params.menuAccent, params.menuColor, params.radius, @@ -67,8 +71,10 @@ export function PresetPicker({ style: preset.style, baseColor: preset.baseColor, theme: preset.theme, + chartColor: preset.chartColor, iconLibrary: preset.iconLibrary, font: preset.font, + fontHeading: preset.fontHeading, menuAccent: preset.menuAccent, menuColor: preset.menuColor, radius: preset.radius, diff --git a/apps/v4/app/(create)/components/project-form.tsx b/apps/v4/app/(create)/components/project-form.tsx index 7cb6a6a30a..eeda464ac6 100644 --- a/apps/v4/app/(create)/components/project-form.tsx +++ b/apps/v4/app/(create)/components/project-form.tsx @@ -87,7 +87,7 @@ export function ProjectForm({ const rtlFlag = params.rtl ? " --rtl" : "" const flags = `${presetFlag}${baseFlag}${templateFlag}${monorepoFlag}${rtlFlag}` - return IS_LOCAL_DEV && !process.env.NEXT_PUBLIC_RC + return IS_LOCAL_DEV ? { pnpm: `shadcn init${flags}`, npm: `shadcn init${flags}`, @@ -130,7 +130,7 @@ export function ProjectForm({ }> Create Project - + Create Project @@ -139,16 +139,17 @@ export function ProjectForm({
- + + Template - + Base - +
Options @@ -159,7 +160,7 @@ export function ProjectForm({ > - + @@ -198,7 +199,7 @@ export function ProjectForm({
- +
-
- +
+ {PACKAGE_MANAGERS.map((manager) => { return ( {manager} @@ -241,7 +242,7 @@ export function ProjectForm({ {Object.entries(commands).map(([key, cmd]) => { return ( -
+
{cmd} @@ -288,23 +289,26 @@ const TemplateGrid = React.memo(function TemplateGrid({ {TEMPLATES.map((item) => ( - - + +
- {item.title} + {item.title}
- - + +
- {item.title} + {item.title} { - // If preset is already in the URL, return it. - if (params.preset && isPresetCode(params.preset)) { - return params.preset - } - - // Otherwise encode current params (e.g. on initial load before first interaction). - return encodePreset({ - style: params.style ?? undefined, - baseColor: params.baseColor ?? undefined, - theme: params.theme ?? undefined, - iconLibrary: params.iconLibrary ?? undefined, - font: params.font ?? undefined, - radius: params.radius ?? undefined, - menuAccent: params.menuAccent ?? undefined, - menuColor: params.menuColor ?? undefined, - } as Parameters[0]) - }, [ - params.preset, - params.style, - params.baseColor, - params.theme, - params.iconLibrary, - params.font, - params.radius, - params.menuAccent, - params.menuColor, - ]) + return getPresetCode(params) } diff --git a/apps/v4/app/(create)/hooks/use-locks.tsx b/apps/v4/app/(create)/hooks/use-locks.tsx index 457b12d606..3949df7324 100644 --- a/apps/v4/app/(create)/hooks/use-locks.tsx +++ b/apps/v4/app/(create)/hooks/use-locks.tsx @@ -6,8 +6,10 @@ export type LockableParam = | "style" | "baseColor" | "theme" + | "chartColor" | "iconLibrary" | "font" + | "fontHeading" | "menuAccent" | "menuColor" | "radius" diff --git a/apps/v4/app/(create)/hooks/use-random.tsx b/apps/v4/app/(create)/hooks/use-random.tsx index 950b773440..e549d33e3d 100644 --- a/apps/v4/app/(create)/hooks/use-random.tsx +++ b/apps/v4/app/(create)/hooks/use-random.tsx @@ -10,6 +10,7 @@ import { MENU_COLORS, RADII, STYLES, + type FontHeadingValue, } from "@/registry/config" import { useLocks } from "@/app/(create)/hooks/use-locks" import { FONTS } from "@/app/(create)/lib/fonts" @@ -62,9 +63,41 @@ export function useRandom() { const selectedTheme = locks.has("theme") ? paramsRef.current.theme : randomItem(availableThemes).name + context.theme = selectedTheme + + const availableChartColors = applyBias( + getThemesForBaseColor(baseColor), + context, + RANDOMIZE_BIASES.chartColors + ) + const selectedChartColor = locks.has("chartColor") + ? paramsRef.current.chartColor + : randomItem(availableChartColors).name + context.chartColor = selectedChartColor const selectedFont = locks.has("font") ? paramsRef.current.font : randomItem(availableFonts).value + context.font = selectedFont + + // Pick heading font: ~70% inherit, ~30% distinct with cross-category contrast. + let selectedFontHeading: FontHeadingValue + if (locks.has("fontHeading")) { + selectedFontHeading = paramsRef.current.fontHeading + } else if (Math.random() < 0.7) { + selectedFontHeading = "inherit" + } else { + const bodyType = availableFonts.find( + (f) => f.value === selectedFont + )?.type + const contrastFonts = availableFonts.filter( + (f) => f.type !== bodyType && f.value !== selectedFont + ) + selectedFontHeading = ( + contrastFonts.length > 0 + ? randomItem(contrastFonts) + : randomItem(availableFonts) + ).value as FontHeadingValue + } const selectedRadius = locks.has("radius") ? paramsRef.current.radius : randomItem(availableRadii).name @@ -91,16 +124,16 @@ export function useRandom() { : paramsRef.current.menuAccent : randomItem(MENU_ACCENTS).value - context.theme = selectedTheme - context.font = selectedFont context.radius = selectedRadius const nextParams = { style: selectedStyle, baseColor, theme: selectedTheme, + chartColor: selectedChartColor, iconLibrary: selectedIconLibrary, font: selectedFont, + fontHeading: selectedFontHeading, menuAccent: selectedMenuAccent, menuColor: selectedMenuColor, radius: selectedRadius, diff --git a/apps/v4/app/(create)/hooks/use-reset.tsx b/apps/v4/app/(create)/hooks/use-reset.tsx index f185eb9d36..a2498edafc 100644 --- a/apps/v4/app/(create)/hooks/use-reset.tsx +++ b/apps/v4/app/(create)/hooks/use-reset.tsx @@ -24,8 +24,10 @@ export function useReset() { style: DEFAULT_CONFIG.style, baseColor: DEFAULT_CONFIG.baseColor, theme: DEFAULT_CONFIG.theme, + chartColor: DEFAULT_CONFIG.chartColor, iconLibrary: DEFAULT_CONFIG.iconLibrary, font: DEFAULT_CONFIG.font, + fontHeading: DEFAULT_CONFIG.fontHeading, menuAccent: DEFAULT_CONFIG.menuAccent, menuColor: DEFAULT_CONFIG.menuColor, radius: DEFAULT_CONFIG.radius, diff --git a/apps/v4/app/(create)/init/md/build-instructions.ts b/apps/v4/app/(create)/init/md/build-instructions.ts index 45d870fa98..3e8dee1b2e 100644 --- a/apps/v4/app/(create)/init/md/build-instructions.ts +++ b/apps/v4/app/(create)/init/md/build-instructions.ts @@ -3,13 +3,17 @@ import dedent from "dedent" import { UI_COMPONENTS } from "@/lib/components" import { buildRegistryBase, - fonts, + getBodyFont, + getHeadingFont, + getInheritedHeadingFontValue, type DesignSystemConfig, } from "@/registry/config" // Builds step-by-step markdown instructions for manually setting up a project. export function buildInstructions(config: DesignSystemConfig) { const registryBase = buildRegistryBase(config) + const normalizedFontHeading = + config.fontHeading === config.font ? "inherit" : config.fontHeading const dependencies = [ ...(registryBase.dependencies ?? []), @@ -25,13 +29,23 @@ export function buildInstructions(config: DesignSystemConfig) { .map(([key, value]) => ` --${key}: ${value};`) .join("\n") - const font = fonts.find((f) => f.name === `font-${config.font}`) + const font = getBodyFont(config.font) + const headingFont = + normalizedFontHeading === "inherit" + ? undefined + : getHeadingFont(normalizedFontHeading) const sections = [ buildDependenciesSection(dependencies), buildUtilsSection(), - buildCssSection(lightVars, darkVars), - buildFontSection(font), + buildCssSection( + lightVars, + darkVars, + normalizedFontHeading === "inherit" + ? getInheritedHeadingFontValue(config.font) + : "var(--font-heading)" + ), + buildFontSection(font, headingFont), buildComponentsJsonSection(config), buildAvailableComponentsSection(config), config.rtl ? buildRtlSection(config) : null, @@ -67,7 +81,11 @@ function buildUtilsSection() { ` } -function buildCssSection(lightVars: string, darkVars: string) { +function buildCssSection( + lightVars: string, + darkVars: string, + fontHeadingValue: string +) { return dedent` ## Step 3: Set up CSS @@ -80,6 +98,7 @@ function buildCssSection(lightVars: string, darkVars: string) { @theme inline { --font-sans: var(--font-sans); + --font-heading: ${fontHeadingValue}; --font-mono: var(--font-mono); --color-background: var(--background); --color-foreground: var(--foreground); @@ -142,40 +161,74 @@ function buildCssSection(lightVars: string, darkVars: string) { ` } -function buildFontSection(font: (typeof fonts)[number] | undefined) { +function buildFontSection( + font: ReturnType, + headingFont: ReturnType +) { if (!font) { return null } const googleFontsUrl = `https://fonts.google.com/specimen/${font.font.import.replace(/_/g, "+")}` + const headingGoogleFontsUrl = headingFont + ? `https://fonts.google.com/specimen/${headingFont.font.import.replace(/_/g, "+")}` + : null + const nextImports = headingFont + ? `${font.font.import}, ${headingFont.font.import}` + : font.font.import + const nextDeclarations = [ + `const fontSans = ${font.font.import}({`, + ` subsets: ["latin"],`, + ` variable: "${font.font.variable}",`, + `})`, + headingFont ? `const fontHeading = ${headingFont.font.import}({` : null, + headingFont ? ` subsets: ["latin"],` : null, + headingFont ? ` variable: "${headingFont.font.variable}",` : null, + headingFont ? `})` : null, + ] + .filter(Boolean) + .join("\n") + const nextHtmlClassName = headingFont + ? 'className={fontSans.variable + " " + fontHeading.variable}' + : `className={fontSans.variable}` + const otherFrameworkCss = [ + ":root {", + ` ${font.font.variable}: ${font.font.family};`, + ...(headingFont + ? [` ${headingFont.font.variable}: ${headingFont.font.family};`] + : []), + "}", + ].join("\n") + const headingSection = headingFont + ? dedent` + + This config also uses **${headingFont.title.replace(" (Heading)", "")}** for headings (\`${headingFont.font.variable}\`). + ` + : "" return dedent` ## Step 4: Set up the font This config uses **${font.title}** (\`${font.font.variable}\`). + ${headingSection} ### Next.js \`\`\`tsx - import { ${font.font.import} } from "next/font/google" + import { ${nextImports} } from "next/font/google" - const fontSans = ${font.font.import}({ - subsets: ["latin"], - variable: "${font.font.variable}", - }) + ${nextDeclarations} - // Add fontSans.variable to your className. - // + // Add the font variable classes to your className. + // \`\`\` ### Other frameworks - Add the font from [Google Fonts](${googleFontsUrl}) and set the \`${font.font.variable}\` CSS variable to the font family: + Add the font${headingFont ? "s" : ""} from [Google Fonts](${googleFontsUrl})${headingGoogleFontsUrl ? ` and [Google Fonts](${headingGoogleFontsUrl})` : ""} and set the CSS variable${headingFont ? "s" : ""} to the font famil${headingFont ? "ies" : "y"}: \`\`\`css - :root { - ${font.font.variable}: ${font.font.family}; - } + ${otherFrameworkCss} \`\`\` ` } diff --git a/apps/v4/app/(create)/init/parse-config.test.ts b/apps/v4/app/(create)/init/parse-config.test.ts new file mode 100644 index 0000000000..245a7b6151 --- /dev/null +++ b/apps/v4/app/(create)/init/parse-config.test.ts @@ -0,0 +1,21 @@ +import { describe, expect, it } from "vitest" + +import { parseDesignSystemConfig } from "./parse-config" + +describe("parseDesignSystemConfig", () => { + it("honors explicit fontHeading and chartColor overrides when a preset is present", () => { + const result = parseDesignSystemConfig( + new URLSearchParams( + "preset=a0&fontHeading=playfair-display&chartColor=emerald" + ) + ) + + expect(result.success).toBe(true) + if (!result.success) { + throw new Error(result.error) + } + + expect(result.data.fontHeading).toBe("playfair-display") + expect(result.data.chartColor).toBe("emerald") + }) +}) diff --git a/apps/v4/app/(create)/init/parse-config.ts b/apps/v4/app/(create)/init/parse-config.ts index 173c613d0d..168bccc11a 100644 --- a/apps/v4/app/(create)/init/parse-config.ts +++ b/apps/v4/app/(create)/init/parse-config.ts @@ -4,6 +4,7 @@ import { designSystemConfigSchema, type DesignSystemConfig, } from "@/registry/config" +import { resolvePresetOverrides } from "@/app/(create)/lib/preset-query" // Parses design system config from URL search params. export function parseDesignSystemConfig(searchParams: URLSearchParams) { @@ -15,8 +16,10 @@ export function parseDesignSystemConfig(searchParams: URLSearchParams) { if (!decoded) { return { success: false as const, error: "Invalid preset code" } } + const presetOverrides = resolvePresetOverrides(searchParams, decoded) configInput = { ...decoded, + ...presetOverrides, base: searchParams.get("base") ?? "radix", template: searchParams.get("template") ?? undefined, rtl: searchParams.get("rtl") === "true", @@ -28,7 +31,9 @@ export function parseDesignSystemConfig(searchParams: URLSearchParams) { iconLibrary: searchParams.get("iconLibrary"), baseColor: searchParams.get("baseColor"), theme: searchParams.get("theme"), + chartColor: searchParams.get("chartColor") ?? undefined, font: searchParams.get("font"), + fontHeading: searchParams.get("fontHeading") ?? undefined, menuAccent: searchParams.get("menuAccent"), menuColor: searchParams.get("menuColor"), radius: searchParams.get("radius"), diff --git a/apps/v4/app/(create)/init/route.ts b/apps/v4/app/(create)/init/route.ts index 22c02af2f5..e573548f7d 100644 --- a/apps/v4/app/(create)/init/route.ts +++ b/apps/v4/app/(create)/init/route.ts @@ -1,10 +1,11 @@ import { NextResponse, type NextRequest } from "next/server" import { track } from "@vercel/analytics/server" -import { encodePreset, isPresetCode } from "shadcn/preset" +import { isPresetCode } from "shadcn/preset" import { registryItemSchema } from "shadcn/schema" import { buildRegistryBase } from "@/registry/config" import { parseDesignSystemConfig } from "@/app/(create)/init/parse-config" +import { getPresetCode } from "@/app/(create)/lib/preset-code" export async function GET(request: NextRequest) { try { @@ -15,21 +16,11 @@ export async function GET(request: NextRequest) { return NextResponse.json({ error: result.error }, { status: 400 }) } - // Use the preset code from the URL if provided, otherwise encode one. - const presetParam = searchParams.get("preset") + const rawPreset = searchParams.get("preset") const presetCode = - presetParam && isPresetCode(presetParam) - ? presetParam - : encodePreset({ - style: result.data.style, - baseColor: result.data.baseColor, - theme: result.data.theme, - iconLibrary: result.data.iconLibrary, - font: result.data.font, - radius: result.data.radius, - menuAccent: result.data.menuAccent, - menuColor: result.data.menuColor, - } as Parameters[0]) + rawPreset && isPresetCode(rawPreset) + ? rawPreset + : getPresetCode(result.data) const registryBase = buildRegistryBase(result.data) const parseResult = registryItemSchema.safeParse(registryBase) diff --git a/apps/v4/app/(create)/init/v0/route.ts b/apps/v4/app/(create)/init/v0/route.ts index d973eb3391..901909933a 100644 --- a/apps/v4/app/(create)/init/v0/route.ts +++ b/apps/v4/app/(create)/init/v0/route.ts @@ -1,7 +1,9 @@ import { after, NextResponse, type NextRequest } from "next/server" import { track } from "@vercel/analytics/server" +import { isPresetCode } from "shadcn/preset" import { parseDesignSystemConfig } from "@/app/(create)/init/parse-config" +import { getPresetCode } from "@/app/(create)/lib/preset-code" import { buildV0Payload } from "@/app/(create)/lib/v0" export async function GET(request: NextRequest) { @@ -13,11 +15,17 @@ export async function GET(request: NextRequest) { return NextResponse.json({ error: result.error }, { status: 400 }) } + const rawPreset = searchParams.get("preset") + const presetCode = + rawPreset && isPresetCode(rawPreset) + ? rawPreset + : getPresetCode(result.data) + // Defer analytics to after response is sent. after(() => { track("create_open_in_v0", { ...result.data, - preset: searchParams.get("preset") ?? "", + preset: presetCode, }) }) diff --git a/apps/v4/app/(create)/lib/fonts.ts b/apps/v4/app/(create)/lib/fonts.ts index 92bb3f8f2b..7deda364ff 100644 --- a/apps/v4/app/(create)/lib/fonts.ts +++ b/apps/v4/app/(create)/lib/fonts.ts @@ -3,21 +3,37 @@ import { Figtree, Geist, Geist_Mono, + IBM_Plex_Sans, + Instrument_Sans, Inter, JetBrains_Mono, Lora, + Manrope, Merriweather, + Montserrat, Noto_Sans, Noto_Serif, Nunito_Sans, Outfit, + Oxanium, Playfair_Display, Public_Sans, Raleway, Roboto, Roboto_Slab, + Source_Sans_3, + Space_Grotesk, } from "next/font/google" +import { FONT_DEFINITIONS, type FontName } from "@/lib/font-definitions" + +type PreviewFont = ReturnType + +const geistSans = Geist({ + subsets: ["latin"], + variable: "--font-geist-sans", +}) + const inter = Inter({ subsets: ["latin"], variable: "--font-inter", @@ -38,21 +54,6 @@ const figtree = Figtree({ variable: "--font-figtree", }) -const jetbrainsMono = JetBrains_Mono({ - subsets: ["latin"], - variable: "--font-jetbrains-mono", -}) - -const geistSans = Geist({ - subsets: ["latin"], - variable: "--font-geist-sans", -}) - -const geistMono = Geist_Mono({ - subsets: ["latin"], - variable: "--font-geist-mono", -}) - const roboto = Roboto({ subsets: ["latin"], variable: "--font-roboto", @@ -78,6 +79,51 @@ const outfit = Outfit({ variable: "--font-outfit", }) +const oxanium = Oxanium({ + subsets: ["latin"], + variable: "--font-oxanium", +}) + +const manrope = Manrope({ + subsets: ["latin"], + variable: "--font-manrope", +}) + +const spaceGrotesk = Space_Grotesk({ + subsets: ["latin"], + variable: "--font-space-grotesk", +}) + +const montserrat = Montserrat({ + subsets: ["latin"], + variable: "--font-montserrat", +}) + +const ibmPlexSans = IBM_Plex_Sans({ + subsets: ["latin"], + variable: "--font-ibm-plex-sans", +}) + +const sourceSans3 = Source_Sans_3({ + subsets: ["latin"], + variable: "--font-source-sans-3", +}) + +const instrumentSans = Instrument_Sans({ + subsets: ["latin"], + variable: "--font-instrument-sans", +}) + +const jetbrainsMono = JetBrains_Mono({ + subsets: ["latin"], + variable: "--font-jetbrains-mono", +}) + +const geistMono = Geist_Mono({ + subsets: ["latin"], + variable: "--font-geist-mono", +}) + const notoSerif = Noto_Serif({ subsets: ["latin"], variable: "--font-noto-serif", @@ -103,109 +149,85 @@ const playfairDisplay = Playfair_Display({ variable: "--font-playfair-display", }) +const PREVIEW_FONTS = { + geist: geistSans, + inter, + "noto-sans": notoSans, + "nunito-sans": nunitoSans, + figtree, + roboto, + raleway, + "dm-sans": dmSans, + "public-sans": publicSans, + outfit, + oxanium, + manrope, + "space-grotesk": spaceGrotesk, + montserrat, + "ibm-plex-sans": ibmPlexSans, + "source-sans-3": sourceSans3, + "instrument-sans": instrumentSans, + "jetbrains-mono": jetbrainsMono, + "geist-mono": geistMono, + "noto-serif": notoSerif, + "roboto-slab": robotoSlab, + merriweather, + lora, + "playfair-display": playfairDisplay, +} satisfies Record + +function createFontOption(name: FontName) { + const definition = FONT_DEFINITIONS.find((font) => font.name === name) + + if (!definition) { + throw new Error(`Unknown font definition: ${name}`) + } + + return { + name: definition.title, + value: definition.name, + font: PREVIEW_FONTS[name], + type: definition.type, + } as const +} + export const FONTS = [ - { - name: "Geist", - value: "geist", - font: geistSans, - type: "sans", - }, - { - name: "Inter", - value: "inter", - font: inter, - type: "sans", - }, - { - name: "Noto Sans", - value: "noto-sans", - font: notoSans, - type: "sans", - }, - { - name: "Nunito Sans", - value: "nunito-sans", - font: nunitoSans, - type: "sans", - }, - { - name: "Figtree", - value: "figtree", - font: figtree, - type: "sans", - }, - { - name: "Roboto", - value: "roboto", - font: roboto, - type: "sans", - }, - { - name: "Raleway", - value: "raleway", - font: raleway, - type: "sans", - }, - { - name: "DM Sans", - value: "dm-sans", - font: dmSans, - type: "sans", - }, - { - name: "Public Sans", - value: "public-sans", - font: publicSans, - type: "sans", - }, - { - name: "Outfit", - value: "outfit", - font: outfit, - type: "sans", - }, - { - name: "Geist Mono", - value: "geist-mono", - font: geistMono, - type: "mono", - }, - { - name: "JetBrains Mono", - value: "jetbrains-mono", - font: jetbrainsMono, - type: "mono", - }, - { - name: "Noto Serif", - value: "noto-serif", - font: notoSerif, - type: "serif", - }, - { - name: "Roboto Slab", - value: "roboto-slab", - font: robotoSlab, - type: "serif", - }, - { - name: "Merriweather", - value: "merriweather", - font: merriweather, - type: "serif", - }, - { - name: "Lora", - value: "lora", - font: lora, - type: "serif", - }, - { - name: "Playfair Display", - value: "playfair-display", - font: playfairDisplay, - type: "serif", - }, + createFontOption("geist"), + createFontOption("inter"), + createFontOption("noto-sans"), + createFontOption("nunito-sans"), + createFontOption("figtree"), + createFontOption("roboto"), + createFontOption("raleway"), + createFontOption("dm-sans"), + createFontOption("public-sans"), + createFontOption("outfit"), + createFontOption("oxanium"), + createFontOption("manrope"), + createFontOption("space-grotesk"), + createFontOption("montserrat"), + createFontOption("ibm-plex-sans"), + createFontOption("source-sans-3"), + createFontOption("instrument-sans"), + createFontOption("geist-mono"), + createFontOption("jetbrains-mono"), + createFontOption("noto-serif"), + createFontOption("roboto-slab"), + createFontOption("merriweather"), + createFontOption("lora"), + createFontOption("playfair-display"), ] as const export type Font = (typeof FONTS)[number] + +export const FONT_HEADING_OPTIONS = [ + { + name: "Inherit", + value: "inherit", + font: null, + type: "default", + }, + ...FONTS, +] as const + +export type FontHeadingOption = (typeof FONT_HEADING_OPTIONS)[number] diff --git a/apps/v4/app/(create)/lib/preset-code.ts b/apps/v4/app/(create)/lib/preset-code.ts new file mode 100644 index 0000000000..50d1c00727 --- /dev/null +++ b/apps/v4/app/(create)/lib/preset-code.ts @@ -0,0 +1,34 @@ +import { encodePreset, type PresetConfig } from "shadcn/preset" + +import { type DesignSystemConfig } from "@/registry/config" + +type PresetCodeConfig = Pick< + DesignSystemConfig, + | "style" + | "baseColor" + | "theme" + | "chartColor" + | "iconLibrary" + | "font" + | "fontHeading" + | "radius" + | "menuAccent" + | "menuColor" +> + +export function getPresetCode(config: PresetCodeConfig) { + const presetConfig: Partial = { + style: config.style as PresetConfig["style"], + baseColor: config.baseColor as PresetConfig["baseColor"], + theme: config.theme as PresetConfig["theme"], + chartColor: config.chartColor as PresetConfig["chartColor"], + iconLibrary: config.iconLibrary as PresetConfig["iconLibrary"], + font: config.font as PresetConfig["font"], + fontHeading: config.fontHeading as PresetConfig["fontHeading"], + radius: config.radius as PresetConfig["radius"], + menuAccent: config.menuAccent as PresetConfig["menuAccent"], + menuColor: config.menuColor as PresetConfig["menuColor"], + } + + return encodePreset(presetConfig) +} diff --git a/apps/v4/app/(create)/lib/preset-query.test.ts b/apps/v4/app/(create)/lib/preset-query.test.ts new file mode 100644 index 0000000000..93c4ce3b6f --- /dev/null +++ b/apps/v4/app/(create)/lib/preset-query.test.ts @@ -0,0 +1,34 @@ +import { describe, expect, it } from "vitest" + +import { resolvePresetOverrides } from "./preset-query" + +describe("resolvePresetOverrides", () => { + it("prefers explicit fontHeading and chartColor query params", () => { + const overrides = resolvePresetOverrides( + new URLSearchParams("fontHeading=playfair-display&chartColor=emerald"), + { + theme: "neutral", + chartColor: "blue", + fontHeading: "inherit", + } + ) + + expect(overrides).toEqual({ + fontHeading: "playfair-display", + chartColor: "emerald", + }) + }) + + it("falls back to decoded preset values when no overrides are present", () => { + const overrides = resolvePresetOverrides(new URLSearchParams(), { + theme: "neutral", + chartColor: "blue", + fontHeading: "inherit", + }) + + expect(overrides).toEqual({ + fontHeading: "inherit", + chartColor: "blue", + }) + }) +}) diff --git a/apps/v4/app/(create)/lib/preset-query.ts b/apps/v4/app/(create)/lib/preset-query.ts new file mode 100644 index 0000000000..f69f1cf9fc --- /dev/null +++ b/apps/v4/app/(create)/lib/preset-query.ts @@ -0,0 +1,30 @@ +import { V1_CHART_COLOR_MAP, type PresetConfig } from "shadcn/preset" + +import { type ChartColorName, type FontHeadingValue } from "@/registry/config" + +type SearchParamsLike = Pick + +export function resolvePresetOverrides( + searchParams: SearchParamsLike, + decoded: Pick +) { + const hasFontHeadingOverride = searchParams.has("fontHeading") + const hasChartColorOverride = searchParams.has("chartColor") + + const fontHeading = hasFontHeadingOverride + ? ((searchParams.get("fontHeading") ?? + decoded.fontHeading) as FontHeadingValue) + : decoded.fontHeading + + const chartColor = hasChartColorOverride + ? ((searchParams.get("chartColor") ?? + decoded.chartColor ?? + V1_CHART_COLOR_MAP[decoded.theme] ?? + decoded.theme) as ChartColorName) + : (decoded.chartColor ?? V1_CHART_COLOR_MAP[decoded.theme] ?? decoded.theme) + + return { + fontHeading, + chartColor, + } +} diff --git a/apps/v4/app/(create)/lib/randomize-biases.ts b/apps/v4/app/(create)/lib/randomize-biases.ts index de04164bfc..c73965143f 100644 --- a/apps/v4/app/(create)/lib/randomize-biases.ts +++ b/apps/v4/app/(create)/lib/randomize-biases.ts @@ -3,6 +3,7 @@ import type { BaseColorName, Radius, StyleName, + Theme, ThemeName, } from "@/registry/config" @@ -12,6 +13,7 @@ export type RandomizeContext = { style?: StyleName baseColor?: BaseColorName theme?: ThemeName + chartColor?: string iconLibrary?: string font?: string menuAccent?: string @@ -26,12 +28,30 @@ export type BiasFilter = ( export type RandomizeBiases = { baseColors?: BiasFilter + chartColors?: BiasFilter fonts?: BiasFilter<(typeof FONTS)[number]> radius?: BiasFilter - // Add more bias filters as needed: - // styles?: BiasFilter" }, + { + "name": "@launchui", + "homepage": "https://www.launchuicomponents.com/", + "url": "https://www.launchuicomponents.com/r/{name}.json", + "description": "Carefully crafted landing page components and templates built with React, Shadcn/ui and Tailwind.", + "logo": "" + }, { "name": "@lens-blocks", "homepage": "https://lensblocks.com", From 6b190c6a18b69daa2789d33b381e48e9fb3553bb Mon Sep 17 00:00:00 2001 From: Kaiden / GL <457429+glsee@users.noreply.github.com> Date: Mon, 23 Mar 2026 15:11:14 +0800 Subject: [PATCH 25/88] chore: add GamifyKit to directory (#9286) (#9289) Co-authored-by: shadcn --- apps/v4/public/r/registries.json | 6 ++++++ apps/v4/registry/directory.json | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/apps/v4/public/r/registries.json b/apps/v4/public/r/registries.json index c53e9aa55d..1b40e63924 100644 --- a/apps/v4/public/r/registries.json +++ b/apps/v4/public/r/registries.json @@ -245,6 +245,12 @@ "url": "https://binnodon.github.io/gc-solid-ui/r/{name}.json", "description": "SolidJS port of shadcn-ui components built with Kobalte primitives. 57+ components with full TypeScript support and Vega theme." }, + { + "name": "@gamifykit", + "homepage": "https://gamifykit.com", + "url": "https://gamifykit.com/r/{name}.json", + "description": "A collection of fully composable components that extend shadcn/ui with a focus on common gamification UI patterns." + }, { "name": "@glass-ui", "homepage": "https://glass-ui.crenspire.com", diff --git a/apps/v4/registry/directory.json b/apps/v4/registry/directory.json index 827c63801f..4176211294 100644 --- a/apps/v4/registry/directory.json +++ b/apps/v4/registry/directory.json @@ -287,6 +287,13 @@ "homepage": "https://binnodon.github.io/gc-solid-ui", "logo": " " }, + { + "name": "@gamifykit", + "homepage": "https://gamifykit.com", + "url": "https://gamifykit.com/r/{name}.json", + "description": "A collection of fully composable components that extend shadcn/ui with a focus on common gamification UI patterns.", + "logo": "" + }, { "name": "@glass-ui", "homepage": "https://glass-ui.crenspire.com", From f900bd57d0d197d22b1a620bc43c964cb44a73ef Mon Sep 17 00:00:00 2001 From: shadcn Date: Mon, 23 Mar 2026 11:31:45 +0400 Subject: [PATCH 26/88] feat: implement reset shortcut (#10145) * feat: implement reset shortcut * fix * fix --- apps/v4/app/(create)/components/main-menu.tsx | 2 +- .../app/(create)/components/menu-picker.tsx | 2 +- apps/v4/app/(create)/components/preview.tsx | 10 +++++ .../app/(create)/components/random-button.tsx | 8 +++- apps/v4/app/(create)/create/page.tsx | 2 +- apps/v4/app/(create)/hooks/use-random.tsx | 2 +- apps/v4/app/(create)/hooks/use-reset.tsx | 45 ++++++++++++++++++- apps/v4/next.config.mjs | 4 ++ 8 files changed, 67 insertions(+), 8 deletions(-) diff --git a/apps/v4/app/(create)/components/main-menu.tsx b/apps/v4/app/(create)/components/main-menu.tsx index 9e8fd11d3c..6663ce680f 100644 --- a/apps/v4/app/(create)/components/main-menu.tsx +++ b/apps/v4/app/(create)/components/main-menu.tsx @@ -73,7 +73,7 @@ export function MainMenu({ className }: React.ComponentProps) { setShowResetDialog(true)}> - Reset + Reset ⇧R diff --git a/apps/v4/app/(create)/components/menu-picker.tsx b/apps/v4/app/(create)/components/menu-picker.tsx index 7e841a9b6b..ce86d7fc71 100644 --- a/apps/v4/app/(create)/components/menu-picker.tsx +++ b/apps/v4/app/(create)/components/menu-picker.tsx @@ -104,7 +104,7 @@ export function MenuColorPicker({
Menu
-
+
{currentMenu?.label}
diff --git a/apps/v4/app/(create)/components/preview.tsx b/apps/v4/app/(create)/components/preview.tsx index cf99e7feac..06bbffcdbc 100644 --- a/apps/v4/app/(create)/components/preview.tsx +++ b/apps/v4/app/(create)/components/preview.tsx @@ -10,6 +10,7 @@ import { import { DARK_MODE_FORWARD_TYPE } from "@/app/(create)/components/mode-switcher" import { RANDOMIZE_FORWARD_TYPE } from "@/app/(create)/components/random-button" import { sendToIframe } from "@/app/(create)/hooks/use-iframe-sync" +import { RESET_FORWARD_TYPE } from "@/app/(create)/hooks/use-reset" import { serializeDesignSystemSearchParams, useDesignSystemSearchParams, @@ -70,6 +71,15 @@ function handleMessage(event: MessageEvent) { cancelable: true, }) ) + } else if (type === RESET_FORWARD_TYPE) { + document.dispatchEvent( + new KeyboardEvent("keydown", { + key: "R", + shiftKey: true, + bubbles: true, + cancelable: true, + }) + ) } else if (type === DARK_MODE_FORWARD_TYPE) { document.dispatchEvent( new KeyboardEvent("keydown", { diff --git a/apps/v4/app/(create)/components/random-button.tsx b/apps/v4/app/(create)/components/random-button.tsx index cc23a4cfe8..d57d2609ab 100644 --- a/apps/v4/app/(create)/components/random-button.tsx +++ b/apps/v4/app/(create)/components/random-button.tsx @@ -7,6 +7,7 @@ import { HugeiconsIcon } from "@hugeicons/react" import { cn } from "@/lib/utils" import { useRandom } from "@/app/(create)/hooks/use-random" +import { RESET_FORWARD_TYPE } from "@/app/(create)/hooks/use-reset" export const RANDOMIZE_FORWARD_TYPE = "randomize-forward" @@ -40,7 +41,7 @@ export function RandomizeScript() { dangerouslySetInnerHTML={{ __html: ` (function() { - // Forward R key + // Forward r key (shuffle) and Shift+R (reset). document.addEventListener('keydown', function(e) { if ((e.key === 'r' || e.key === 'R') && !e.metaKey && !e.ctrlKey) { if ( @@ -53,8 +54,11 @@ export function RandomizeScript() { } e.preventDefault(); if (window.parent && window.parent !== window) { + var type = e.shiftKey + ? '${RESET_FORWARD_TYPE}' + : '${RANDOMIZE_FORWARD_TYPE}'; window.parent.postMessage({ - type: '${RANDOMIZE_FORWARD_TYPE}', + type: type, key: e.key }, '*'); } diff --git a/apps/v4/app/(create)/create/page.tsx b/apps/v4/app/(create)/create/page.tsx index 013b5bd3ad..1e21ef0098 100644 --- a/apps/v4/app/(create)/create/page.tsx +++ b/apps/v4/app/(create)/create/page.tsx @@ -44,7 +44,7 @@ export default async function CreatePage() { return (
{ const down = (e: KeyboardEvent) => { - if ((e.key === "r" || e.key === "R") && !e.metaKey && !e.ctrlKey) { + if (e.key === "r" && !e.shiftKey && !e.metaKey && !e.ctrlKey) { if ( (e.target instanceof HTMLElement && e.target.isContentEditable) || e.target instanceof HTMLInputElement || diff --git a/apps/v4/app/(create)/hooks/use-reset.tsx b/apps/v4/app/(create)/hooks/use-reset.tsx index a2498edafc..ad90419fc2 100644 --- a/apps/v4/app/(create)/hooks/use-reset.tsx +++ b/apps/v4/app/(create)/hooks/use-reset.tsx @@ -7,6 +7,7 @@ import { DEFAULT_CONFIG } from "@/registry/config" import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params" const RESET_DIALOG_KEY = "create:reset-dialog-open" +export const RESET_FORWARD_TYPE = "reset-forward" export function useReset() { const [params, setParams] = useDesignSystemSearchParams() @@ -32,9 +33,9 @@ export function useReset() { menuColor: DEFAULT_CONFIG.menuColor, radius: DEFAULT_CONFIG.radius, template: DEFAULT_CONFIG.template, - item: "preview", + item: params.item, }) - }, [setParams, params.base]) + }, [setParams, params.base, params.item]) const handleShowResetDialogChange = React.useCallback( (open: boolean) => { @@ -48,6 +49,46 @@ export function useReset() { void setShowResetDialogData(false, { revalidate: false }) }, [reset, setShowResetDialogData]) + const showResetDialogRef = React.useRef(showResetDialog) + React.useEffect(() => { + showResetDialogRef.current = showResetDialog + }, [showResetDialog]) + + const confirmResetRef = React.useRef(confirmReset) + React.useEffect(() => { + confirmResetRef.current = confirmReset + }, [confirmReset]) + + React.useEffect(() => { + const down = (e: KeyboardEvent) => { + if (e.key === "R" && e.shiftKey && !e.metaKey && !e.ctrlKey) { + if ( + (e.target instanceof HTMLElement && e.target.isContentEditable) || + e.target instanceof HTMLInputElement || + e.target instanceof HTMLTextAreaElement || + e.target instanceof HTMLSelectElement + ) { + return + } + + e.preventDefault() + + // If the dialog is already open, confirm the reset. + if (showResetDialogRef.current) { + confirmResetRef.current() + return + } + + handleShowResetDialogChange(true) + } + } + + document.addEventListener("keydown", down) + return () => { + document.removeEventListener("keydown", down) + } + }, [handleShowResetDialogChange]) + return { reset, showResetDialog, diff --git a/apps/v4/next.config.mjs b/apps/v4/next.config.mjs index b40450abd4..68b21d89f4 100644 --- a/apps/v4/next.config.mjs +++ b/apps/v4/next.config.mjs @@ -1,3 +1,4 @@ +import path from "path" import { createMDX } from "fumadocs-mdx/next" /** @type {import('next').NextConfig} */ @@ -25,6 +26,9 @@ const nextConfig = { }, ], }, + turbopack: { + root: path.resolve(import.meta.dirname, "../.."), + }, experimental: { turbopackFileSystemCacheForDev: true, }, From 228b0e3ecdf11f491b43806de4b00e66f49248e9 Mon Sep 17 00:00:00 2001 From: shadcn Date: Mon, 23 Mar 2026 12:16:35 +0400 Subject: [PATCH 27/88] feat(v4): support Recharts v3 --- .../components/chart-visitors.tsx | 2 +- .../sink/components/chart-bar-mixed.tsx | 2 +- .../v4/content/docs/components/base/chart.mdx | 4 +- .../content/docs/components/radix/chart.mdx | 4 +- apps/v4/examples/base/ui-rtl/chart.tsx | 66 ++++--- apps/v4/examples/base/ui/chart.tsx | 66 ++++--- apps/v4/examples/radix/ui-rtl/chart.tsx | 66 ++++--- apps/v4/examples/radix/ui/chart.tsx | 66 ++++--- apps/v4/package.json | 2 +- apps/v4/public/r/index.json | 2 +- apps/v4/public/r/styles/base-lyra/chart.json | 4 +- .../public/r/styles/base-lyra/registry.json | 2 +- apps/v4/public/r/styles/base-maia/chart.json | 4 +- .../public/r/styles/base-maia/registry.json | 2 +- apps/v4/public/r/styles/base-mira/chart.json | 4 +- .../public/r/styles/base-mira/registry.json | 2 +- apps/v4/public/r/styles/base-nova/chart.json | 4 +- .../public/r/styles/base-nova/registry.json | 2 +- apps/v4/public/r/styles/base-vega/chart.json | 4 +- .../public/r/styles/base-vega/registry.json | 2 +- .../styles/new-york-v4/chart-bar-active.json | 2 +- .../new-york-v4/chart-bar-label-custom.json | 2 +- .../r/styles/new-york-v4/chart-bar-mixed.json | 2 +- .../new-york-v4/chart-line-dots-custom.json | 2 +- .../new-york-v4/chart-line-label-custom.json | 2 +- .../new-york-v4/chart-pie-donut-active.json | 2 +- .../new-york-v4/chart-pie-interactive.json | 2 +- .../new-york-v4/chart-pie-label-list.json | 2 +- .../styles/new-york-v4/chart-radar-icons.json | 2 +- .../new-york-v4/chart-radar-label-custom.json | 2 +- .../new-york-v4/chart-radar-legend.json | 2 +- .../v4/public/r/styles/new-york-v4/chart.json | 4 +- .../public/r/styles/new-york-v4/registry.json | 2 +- apps/v4/public/r/styles/radix-lyra/chart.json | 4 +- .../public/r/styles/radix-lyra/registry.json | 2 +- apps/v4/public/r/styles/radix-maia/chart.json | 4 +- .../public/r/styles/radix-maia/registry.json | 2 +- apps/v4/public/r/styles/radix-mira/chart.json | 4 +- .../public/r/styles/radix-mira/registry.json | 2 +- apps/v4/public/r/styles/radix-nova/chart.json | 4 +- .../public/r/styles/radix-nova/registry.json | 2 +- apps/v4/public/r/styles/radix-vega/chart.json | 4 +- .../public/r/styles/radix-vega/registry.json | 2 +- .../blocks/preview/cards/sleep-report.tsx | 2 +- apps/v4/registry/bases/base/ui/_registry.ts | 2 +- apps/v4/registry/bases/base/ui/chart.tsx | 66 ++++--- .../blocks/preview/cards/sleep-report.tsx | 2 +- apps/v4/registry/bases/radix/ui/_registry.ts | 2 +- apps/v4/registry/bases/radix/ui/chart.tsx | 66 ++++--- .../new-york-v4/charts/chart-bar-active.tsx | 2 +- .../charts/chart-bar-label-custom.tsx | 7 +- .../new-york-v4/charts/chart-bar-mixed.tsx | 2 +- .../charts/chart-line-dots-custom.tsx | 5 + .../charts/chart-line-label-custom.tsx | 4 +- .../charts/chart-pie-donut-active.tsx | 2 +- .../charts/chart-pie-interactive.tsx | 2 +- .../charts/chart-pie-label-list.tsx | 4 +- .../new-york-v4/charts/chart-radar-icons.tsx | 2 + .../charts/chart-radar-label-custom.tsx | 5 +- .../new-york-v4/charts/chart-radar-legend.tsx | 2 + apps/v4/registry/new-york-v4/ui/_registry.ts | 2 +- apps/v4/registry/new-york-v4/ui/chart.tsx | 66 ++++--- pnpm-lock.yaml | 185 +++++++++++------- 63 files changed, 478 insertions(+), 320 deletions(-) diff --git a/apps/v4/app/(examples)/dashboard-03/components/chart-visitors.tsx b/apps/v4/app/(examples)/dashboard-03/components/chart-visitors.tsx index 4d89edb879..984ab8147d 100644 --- a/apps/v4/app/(examples)/dashboard-03/components/chart-visitors.tsx +++ b/apps/v4/app/(examples)/dashboard-03/components/chart-visitors.tsx @@ -129,6 +129,7 @@ export function ChartVisitors() { } + defaultIndex={activeIndex} /> } /> - + diff --git a/apps/v4/content/docs/components/base/chart.mdx b/apps/v4/content/docs/components/base/chart.mdx index 7db02232e5..7e7ac8aa1b 100644 --- a/apps/v4/content/docs/components/base/chart.mdx +++ b/apps/v4/content/docs/components/base/chart.mdx @@ -7,7 +7,7 @@ component: true -**Note:** We're working on upgrading to Recharts v3. In the meantime, if you'd like to start testing v3, see the code in the comment [here](https://github.com/shadcn-ui/ui/issues/7669#issuecomment-2998299159). We'll have an official release soon. +**Recharts v3:** The `chart` component now targets Recharts v3. If you're upgrading from v2, move default active states to `ChartTooltip.defaultIndex`, remove `layout` from `` when `BarChart` already sets it, and keep a height or `min-h-*` on `ChartContainer`. @@ -455,7 +455,7 @@ const chartData = [ #### Tailwind ```tsx title="components/example-chart.tsx" - + ``` ## Tooltip diff --git a/apps/v4/content/docs/components/radix/chart.mdx b/apps/v4/content/docs/components/radix/chart.mdx index c82cabd3bb..90bf521be9 100644 --- a/apps/v4/content/docs/components/radix/chart.mdx +++ b/apps/v4/content/docs/components/radix/chart.mdx @@ -7,7 +7,7 @@ component: true -**Note:** We're working on upgrading to Recharts v3. In the meantime, if you'd like to start testing v3, see the code in the comment [here](https://github.com/shadcn-ui/ui/issues/7669#issuecomment-2998299159). We'll have an official release soon. +**Recharts v3:** The `chart` component now targets Recharts v3. If you're upgrading from v2, move default active states to `ChartTooltip.defaultIndex`, remove `layout` from `` when `BarChart` already sets it, and keep a height or `min-h-*` on `ChartContainer`. @@ -455,7 +455,7 @@ const chartData = [ #### Tailwind ```tsx title="components/example-chart.tsx" - + ``` ## Tooltip diff --git a/apps/v4/examples/base/ui-rtl/chart.tsx b/apps/v4/examples/base/ui-rtl/chart.tsx index 10c047c3bd..71c63a4795 100644 --- a/apps/v4/examples/base/ui-rtl/chart.tsx +++ b/apps/v4/examples/base/ui-rtl/chart.tsx @@ -3,19 +3,26 @@ import * as React from "react" import { cn } from "@/examples/base/lib/utils" import * as RechartsPrimitive from "recharts" +import type { + NameType, + ValueType, +} from "recharts/types/component/DefaultTooltipContent" // Format: { THEME_NAME: CSS_SELECTOR } const THEMES = { light: "", dark: ".dark" } as const -export type ChartConfig = { - [k in string]: { +const INITIAL_DIMENSION = { width: 320, height: 200 } as const + +export type ChartConfig = Record< + string, + { label?: React.ReactNode icon?: React.ComponentType } & ( | { color?: string; theme?: never } | { color?: never; theme: Record } ) -} +> type ChartContextProps = { config: ChartConfig @@ -38,15 +45,20 @@ function ChartContainer({ className, children, config, + initialDimension = INITIAL_DIMENSION, ...props }: React.ComponentProps<"div"> & { config: ChartConfig children: React.ComponentProps< typeof RechartsPrimitive.ResponsiveContainer >["children"] + initialDimension?: { + width: number + height: number + } }) { const uniqueId = React.useId() - const chartId = `chart-${id || uniqueId.replace(/:/g, "")}` + const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}` return ( @@ -60,7 +72,9 @@ function ChartContainer({ {...props} > - + {children}
@@ -70,7 +84,7 @@ function ChartContainer({ const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { const colorConfig = Object.entries(config).filter( - ([, config]) => config.theme || config.color + ([, config]) => config.theme ?? config.color ) if (!colorConfig.length) { @@ -87,7 +101,7 @@ ${prefix} [data-chart=${id}] { ${colorConfig .map(([key, itemConfig]) => { const color = - itemConfig.theme?.[theme as keyof typeof itemConfig.theme] || + itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ?? itemConfig.color return color ? ` --color-${key}: ${color};` : null }) @@ -124,7 +138,10 @@ function ChartTooltipContent({ indicator?: "line" | "dot" | "dashed" nameKey?: string labelKey?: string - }) { + } & Omit< + RechartsPrimitive.DefaultTooltipContentProps, + "accessibilityLayer" + >) { const { config } = useChart() const tooltipLabel = React.useMemo(() => { @@ -133,11 +150,11 @@ function ChartTooltipContent({ } const [item] = payload - const key = `${labelKey || item?.dataKey || item?.name || "value"}` + const key = `${labelKey ?? item?.dataKey ?? item?.name ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) const value = !labelKey && typeof label === "string" - ? config[label as keyof typeof config]?.label || label + ? (config[label]?.label ?? label) : itemConfig?.label if (labelFormatter) { @@ -181,13 +198,13 @@ function ChartTooltipContent({ {payload .filter((item) => item.type !== "none") .map((item, index) => { - const key = `${nameKey || item.name || item.dataKey || "value"}` + const key = `${nameKey ?? item.name ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) - const indicatorColor = color || item.payload.fill || item.color + const indicatorColor = color ?? item.payload?.fill ?? item.color return (
svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground", indicator === "dot" && "items-center" @@ -230,12 +247,14 @@ function ChartTooltipContent({
{nestLabel ? tooltipLabel : null} - {itemConfig?.label || item.name} + {itemConfig?.label ?? item.name}
- {item.value && ( + {item.value != null && ( - {item.value.toLocaleString()} + {typeof item.value === "number" + ? item.value.toLocaleString() + : String(item.value)} )}
@@ -257,11 +276,10 @@ function ChartLegendContent({ payload, verticalAlign = "bottom", nameKey, -}: React.ComponentProps<"div"> & - Pick & { - hideIcon?: boolean - nameKey?: string - }) { +}: React.ComponentProps<"div"> & { + hideIcon?: boolean + nameKey?: string +} & RechartsPrimitive.DefaultLegendContentProps) { const { config } = useChart() if (!payload?.length) { @@ -279,7 +297,7 @@ function ChartLegendContent({ {payload .filter((item) => item.type !== "none") .map((item) => { - const key = `${nameKey || item.dataKey || "value"}` + const key = `${nameKey ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) return ( @@ -340,9 +358,7 @@ function getPayloadConfigFromPayload( ] as string } - return configLabelKey in config - ? config[configLabelKey] - : config[key as keyof typeof config] + return configLabelKey in config ? config[configLabelKey] : config[key] } export { diff --git a/apps/v4/examples/base/ui/chart.tsx b/apps/v4/examples/base/ui/chart.tsx index 10c047c3bd..71c63a4795 100644 --- a/apps/v4/examples/base/ui/chart.tsx +++ b/apps/v4/examples/base/ui/chart.tsx @@ -3,19 +3,26 @@ import * as React from "react" import { cn } from "@/examples/base/lib/utils" import * as RechartsPrimitive from "recharts" +import type { + NameType, + ValueType, +} from "recharts/types/component/DefaultTooltipContent" // Format: { THEME_NAME: CSS_SELECTOR } const THEMES = { light: "", dark: ".dark" } as const -export type ChartConfig = { - [k in string]: { +const INITIAL_DIMENSION = { width: 320, height: 200 } as const + +export type ChartConfig = Record< + string, + { label?: React.ReactNode icon?: React.ComponentType } & ( | { color?: string; theme?: never } | { color?: never; theme: Record } ) -} +> type ChartContextProps = { config: ChartConfig @@ -38,15 +45,20 @@ function ChartContainer({ className, children, config, + initialDimension = INITIAL_DIMENSION, ...props }: React.ComponentProps<"div"> & { config: ChartConfig children: React.ComponentProps< typeof RechartsPrimitive.ResponsiveContainer >["children"] + initialDimension?: { + width: number + height: number + } }) { const uniqueId = React.useId() - const chartId = `chart-${id || uniqueId.replace(/:/g, "")}` + const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}` return ( @@ -60,7 +72,9 @@ function ChartContainer({ {...props} > - + {children}
@@ -70,7 +84,7 @@ function ChartContainer({ const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { const colorConfig = Object.entries(config).filter( - ([, config]) => config.theme || config.color + ([, config]) => config.theme ?? config.color ) if (!colorConfig.length) { @@ -87,7 +101,7 @@ ${prefix} [data-chart=${id}] { ${colorConfig .map(([key, itemConfig]) => { const color = - itemConfig.theme?.[theme as keyof typeof itemConfig.theme] || + itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ?? itemConfig.color return color ? ` --color-${key}: ${color};` : null }) @@ -124,7 +138,10 @@ function ChartTooltipContent({ indicator?: "line" | "dot" | "dashed" nameKey?: string labelKey?: string - }) { + } & Omit< + RechartsPrimitive.DefaultTooltipContentProps, + "accessibilityLayer" + >) { const { config } = useChart() const tooltipLabel = React.useMemo(() => { @@ -133,11 +150,11 @@ function ChartTooltipContent({ } const [item] = payload - const key = `${labelKey || item?.dataKey || item?.name || "value"}` + const key = `${labelKey ?? item?.dataKey ?? item?.name ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) const value = !labelKey && typeof label === "string" - ? config[label as keyof typeof config]?.label || label + ? (config[label]?.label ?? label) : itemConfig?.label if (labelFormatter) { @@ -181,13 +198,13 @@ function ChartTooltipContent({ {payload .filter((item) => item.type !== "none") .map((item, index) => { - const key = `${nameKey || item.name || item.dataKey || "value"}` + const key = `${nameKey ?? item.name ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) - const indicatorColor = color || item.payload.fill || item.color + const indicatorColor = color ?? item.payload?.fill ?? item.color return (
svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground", indicator === "dot" && "items-center" @@ -230,12 +247,14 @@ function ChartTooltipContent({
{nestLabel ? tooltipLabel : null} - {itemConfig?.label || item.name} + {itemConfig?.label ?? item.name}
- {item.value && ( + {item.value != null && ( - {item.value.toLocaleString()} + {typeof item.value === "number" + ? item.value.toLocaleString() + : String(item.value)} )}
@@ -257,11 +276,10 @@ function ChartLegendContent({ payload, verticalAlign = "bottom", nameKey, -}: React.ComponentProps<"div"> & - Pick & { - hideIcon?: boolean - nameKey?: string - }) { +}: React.ComponentProps<"div"> & { + hideIcon?: boolean + nameKey?: string +} & RechartsPrimitive.DefaultLegendContentProps) { const { config } = useChart() if (!payload?.length) { @@ -279,7 +297,7 @@ function ChartLegendContent({ {payload .filter((item) => item.type !== "none") .map((item) => { - const key = `${nameKey || item.dataKey || "value"}` + const key = `${nameKey ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) return ( @@ -340,9 +358,7 @@ function getPayloadConfigFromPayload( ] as string } - return configLabelKey in config - ? config[configLabelKey] - : config[key as keyof typeof config] + return configLabelKey in config ? config[configLabelKey] : config[key] } export { diff --git a/apps/v4/examples/radix/ui-rtl/chart.tsx b/apps/v4/examples/radix/ui-rtl/chart.tsx index d287bdae6d..c1bf1e00a0 100644 --- a/apps/v4/examples/radix/ui-rtl/chart.tsx +++ b/apps/v4/examples/radix/ui-rtl/chart.tsx @@ -3,19 +3,26 @@ import * as React from "react" import { cn } from "@/examples/radix/lib/utils" import * as RechartsPrimitive from "recharts" +import type { + NameType, + ValueType, +} from "recharts/types/component/DefaultTooltipContent" // Format: { THEME_NAME: CSS_SELECTOR } const THEMES = { light: "", dark: ".dark" } as const -export type ChartConfig = { - [k in string]: { +const INITIAL_DIMENSION = { width: 320, height: 200 } as const + +export type ChartConfig = Record< + string, + { label?: React.ReactNode icon?: React.ComponentType } & ( | { color?: string; theme?: never } | { color?: never; theme: Record } ) -} +> type ChartContextProps = { config: ChartConfig @@ -38,15 +45,20 @@ function ChartContainer({ className, children, config, + initialDimension = INITIAL_DIMENSION, ...props }: React.ComponentProps<"div"> & { config: ChartConfig children: React.ComponentProps< typeof RechartsPrimitive.ResponsiveContainer >["children"] + initialDimension?: { + width: number + height: number + } }) { const uniqueId = React.useId() - const chartId = `chart-${id || uniqueId.replace(/:/g, "")}` + const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}` return ( @@ -60,7 +72,9 @@ function ChartContainer({ {...props} > - + {children}
@@ -70,7 +84,7 @@ function ChartContainer({ const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { const colorConfig = Object.entries(config).filter( - ([, config]) => config.theme || config.color + ([, config]) => config.theme ?? config.color ) if (!colorConfig.length) { @@ -87,7 +101,7 @@ ${prefix} [data-chart=${id}] { ${colorConfig .map(([key, itemConfig]) => { const color = - itemConfig.theme?.[theme as keyof typeof itemConfig.theme] || + itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ?? itemConfig.color return color ? ` --color-${key}: ${color};` : null }) @@ -124,7 +138,10 @@ function ChartTooltipContent({ indicator?: "line" | "dot" | "dashed" nameKey?: string labelKey?: string - }) { + } & Omit< + RechartsPrimitive.DefaultTooltipContentProps, + "accessibilityLayer" + >) { const { config } = useChart() const tooltipLabel = React.useMemo(() => { @@ -133,11 +150,11 @@ function ChartTooltipContent({ } const [item] = payload - const key = `${labelKey || item?.dataKey || item?.name || "value"}` + const key = `${labelKey ?? item?.dataKey ?? item?.name ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) const value = !labelKey && typeof label === "string" - ? config[label as keyof typeof config]?.label || label + ? (config[label]?.label ?? label) : itemConfig?.label if (labelFormatter) { @@ -181,13 +198,13 @@ function ChartTooltipContent({ {payload .filter((item) => item.type !== "none") .map((item, index) => { - const key = `${nameKey || item.name || item.dataKey || "value"}` + const key = `${nameKey ?? item.name ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) - const indicatorColor = color || item.payload.fill || item.color + const indicatorColor = color ?? item.payload?.fill ?? item.color return (
svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground", indicator === "dot" && "items-center" @@ -230,12 +247,14 @@ function ChartTooltipContent({
{nestLabel ? tooltipLabel : null} - {itemConfig?.label || item.name} + {itemConfig?.label ?? item.name}
- {item.value && ( + {item.value != null && ( - {item.value.toLocaleString()} + {typeof item.value === "number" + ? item.value.toLocaleString() + : String(item.value)} )}
@@ -257,11 +276,10 @@ function ChartLegendContent({ payload, verticalAlign = "bottom", nameKey, -}: React.ComponentProps<"div"> & - Pick & { - hideIcon?: boolean - nameKey?: string - }) { +}: React.ComponentProps<"div"> & { + hideIcon?: boolean + nameKey?: string +} & RechartsPrimitive.DefaultLegendContentProps) { const { config } = useChart() if (!payload?.length) { @@ -279,7 +297,7 @@ function ChartLegendContent({ {payload .filter((item) => item.type !== "none") .map((item) => { - const key = `${nameKey || item.dataKey || "value"}` + const key = `${nameKey ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) return ( @@ -340,9 +358,7 @@ function getPayloadConfigFromPayload( ] as string } - return configLabelKey in config - ? config[configLabelKey] - : config[key as keyof typeof config] + return configLabelKey in config ? config[configLabelKey] : config[key] } export { diff --git a/apps/v4/examples/radix/ui/chart.tsx b/apps/v4/examples/radix/ui/chart.tsx index d287bdae6d..c1bf1e00a0 100644 --- a/apps/v4/examples/radix/ui/chart.tsx +++ b/apps/v4/examples/radix/ui/chart.tsx @@ -3,19 +3,26 @@ import * as React from "react" import { cn } from "@/examples/radix/lib/utils" import * as RechartsPrimitive from "recharts" +import type { + NameType, + ValueType, +} from "recharts/types/component/DefaultTooltipContent" // Format: { THEME_NAME: CSS_SELECTOR } const THEMES = { light: "", dark: ".dark" } as const -export type ChartConfig = { - [k in string]: { +const INITIAL_DIMENSION = { width: 320, height: 200 } as const + +export type ChartConfig = Record< + string, + { label?: React.ReactNode icon?: React.ComponentType } & ( | { color?: string; theme?: never } | { color?: never; theme: Record } ) -} +> type ChartContextProps = { config: ChartConfig @@ -38,15 +45,20 @@ function ChartContainer({ className, children, config, + initialDimension = INITIAL_DIMENSION, ...props }: React.ComponentProps<"div"> & { config: ChartConfig children: React.ComponentProps< typeof RechartsPrimitive.ResponsiveContainer >["children"] + initialDimension?: { + width: number + height: number + } }) { const uniqueId = React.useId() - const chartId = `chart-${id || uniqueId.replace(/:/g, "")}` + const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}` return ( @@ -60,7 +72,9 @@ function ChartContainer({ {...props} > - + {children}
@@ -70,7 +84,7 @@ function ChartContainer({ const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { const colorConfig = Object.entries(config).filter( - ([, config]) => config.theme || config.color + ([, config]) => config.theme ?? config.color ) if (!colorConfig.length) { @@ -87,7 +101,7 @@ ${prefix} [data-chart=${id}] { ${colorConfig .map(([key, itemConfig]) => { const color = - itemConfig.theme?.[theme as keyof typeof itemConfig.theme] || + itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ?? itemConfig.color return color ? ` --color-${key}: ${color};` : null }) @@ -124,7 +138,10 @@ function ChartTooltipContent({ indicator?: "line" | "dot" | "dashed" nameKey?: string labelKey?: string - }) { + } & Omit< + RechartsPrimitive.DefaultTooltipContentProps, + "accessibilityLayer" + >) { const { config } = useChart() const tooltipLabel = React.useMemo(() => { @@ -133,11 +150,11 @@ function ChartTooltipContent({ } const [item] = payload - const key = `${labelKey || item?.dataKey || item?.name || "value"}` + const key = `${labelKey ?? item?.dataKey ?? item?.name ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) const value = !labelKey && typeof label === "string" - ? config[label as keyof typeof config]?.label || label + ? (config[label]?.label ?? label) : itemConfig?.label if (labelFormatter) { @@ -181,13 +198,13 @@ function ChartTooltipContent({ {payload .filter((item) => item.type !== "none") .map((item, index) => { - const key = `${nameKey || item.name || item.dataKey || "value"}` + const key = `${nameKey ?? item.name ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) - const indicatorColor = color || item.payload.fill || item.color + const indicatorColor = color ?? item.payload?.fill ?? item.color return (
svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground", indicator === "dot" && "items-center" @@ -230,12 +247,14 @@ function ChartTooltipContent({
{nestLabel ? tooltipLabel : null} - {itemConfig?.label || item.name} + {itemConfig?.label ?? item.name}
- {item.value && ( + {item.value != null && ( - {item.value.toLocaleString()} + {typeof item.value === "number" + ? item.value.toLocaleString() + : String(item.value)} )}
@@ -257,11 +276,10 @@ function ChartLegendContent({ payload, verticalAlign = "bottom", nameKey, -}: React.ComponentProps<"div"> & - Pick & { - hideIcon?: boolean - nameKey?: string - }) { +}: React.ComponentProps<"div"> & { + hideIcon?: boolean + nameKey?: string +} & RechartsPrimitive.DefaultLegendContentProps) { const { config } = useChart() if (!payload?.length) { @@ -279,7 +297,7 @@ function ChartLegendContent({ {payload .filter((item) => item.type !== "none") .map((item) => { - const key = `${nameKey || item.dataKey || "value"}` + const key = `${nameKey ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) return ( @@ -340,9 +358,7 @@ function getPayloadConfigFromPayload( ] as string } - return configLabelKey in config - ? config[configLabelKey] - : config[key as keyof typeof config] + return configLabelKey in config ? config[configLabelKey] : config[key] } export { diff --git a/apps/v4/package.json b/apps/v4/package.json index dee50fc2dc..3754b674b3 100644 --- a/apps/v4/package.json +++ b/apps/v4/package.json @@ -72,7 +72,7 @@ "react-hook-form": "^7.62.0", "react-resizable-panels": "^4", "react-textarea-autosize": "^8.5.9", - "recharts": "2.15.1", + "recharts": "3.8.0", "rehype-pretty-code": "^0.14.1", "rimraf": "^6.0.1", "server-only": "^0.0.1", diff --git a/apps/v4/public/r/index.json b/apps/v4/public/r/index.json index 25d6009c92..7d3fc8e7c0 100644 --- a/apps/v4/public/r/index.json +++ b/apps/v4/public/r/index.json @@ -289,7 +289,7 @@ "type": "registry:ui" } ], - "dependencies": ["recharts@2.15.4"], + "dependencies": ["recharts@3.8.0"], "meta": { "links": { "radix": { diff --git a/apps/v4/public/r/styles/base-lyra/chart.json b/apps/v4/public/r/styles/base-lyra/chart.json index 4944655e6d..a19c6b4aa7 100644 --- a/apps/v4/public/r/styles/base-lyra/chart.json +++ b/apps/v4/public/r/styles/base-lyra/chart.json @@ -2,7 +2,7 @@ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "chart", "dependencies": [ - "recharts@2.15.4" + "recharts@3.8.0" ], "registryDependencies": [ "card" @@ -10,7 +10,7 @@ "files": [ { "path": "registry/base-lyra/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\n\nimport { cn } from \"@/registry/base-lyra/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nexport type ChartConfig = {\n [k in string]: {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n}\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id || uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n
\n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme || config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n }) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey || item?.dataKey || item?.name || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? config[label as keyof typeof config]?.label || label\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey || item.name || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color || item.payload.fill || item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label || item.name}\n \n
\n {item.value && (\n \n {item.value.toLocaleString()}\n \n )}\n
\n \n )}\n
\n )\n })}\n
\n
\n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> &\n Pick & {\n hideIcon?: boolean\n nameKey?: string\n }) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n
\n )\n })}\n
\n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config\n ? config[configLabelKey]\n : config[key as keyof typeof config]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-lyra/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n
\n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n
\n )\n })}\n
\n
\n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/base-lyra/registry.json b/apps/v4/public/r/styles/base-lyra/registry.json index ab103b74c5..bcfc6d1f6a 100644 --- a/apps/v4/public/r/styles/base-lyra/registry.json +++ b/apps/v4/public/r/styles/base-lyra/registry.json @@ -257,7 +257,7 @@ }, { "name": "chart", - "dependencies": ["recharts@2.15.4"], + "dependencies": ["recharts@3.8.0"], "registryDependencies": ["card"], "files": [ { diff --git a/apps/v4/public/r/styles/base-maia/chart.json b/apps/v4/public/r/styles/base-maia/chart.json index 8e416620d9..895bd79b64 100644 --- a/apps/v4/public/r/styles/base-maia/chart.json +++ b/apps/v4/public/r/styles/base-maia/chart.json @@ -2,7 +2,7 @@ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "chart", "dependencies": [ - "recharts@2.15.4" + "recharts@3.8.0" ], "registryDependencies": [ "card" @@ -10,7 +10,7 @@ "files": [ { "path": "registry/base-maia/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\n\nimport { cn } from \"@/registry/base-maia/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nexport type ChartConfig = {\n [k in string]: {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n}\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id || uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme || config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n }) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey || item?.dataKey || item?.name || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? config[label as keyof typeof config]?.label || label\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey || item.name || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color || item.payload.fill || item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label || item.name}\n \n
\n {item.value && (\n \n {item.value.toLocaleString()}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> &\n Pick & {\n hideIcon?: boolean\n nameKey?: string\n }) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config\n ? config[configLabelKey]\n : config[key as keyof typeof config]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-maia/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/base-maia/registry.json b/apps/v4/public/r/styles/base-maia/registry.json index 839f16a558..aa4ac9c218 100644 --- a/apps/v4/public/r/styles/base-maia/registry.json +++ b/apps/v4/public/r/styles/base-maia/registry.json @@ -257,7 +257,7 @@ }, { "name": "chart", - "dependencies": ["recharts@2.15.4"], + "dependencies": ["recharts@3.8.0"], "registryDependencies": ["card"], "files": [ { diff --git a/apps/v4/public/r/styles/base-mira/chart.json b/apps/v4/public/r/styles/base-mira/chart.json index 8531569426..2a9c749d9e 100644 --- a/apps/v4/public/r/styles/base-mira/chart.json +++ b/apps/v4/public/r/styles/base-mira/chart.json @@ -2,7 +2,7 @@ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "chart", "dependencies": [ - "recharts@2.15.4" + "recharts@3.8.0" ], "registryDependencies": [ "card" @@ -10,7 +10,7 @@ "files": [ { "path": "registry/base-mira/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\n\nimport { cn } from \"@/registry/base-mira/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nexport type ChartConfig = {\n [k in string]: {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n}\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id || uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme || config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n }) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey || item?.dataKey || item?.name || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? config[label as keyof typeof config]?.label || label\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey || item.name || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color || item.payload.fill || item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label || item.name}\n \n
\n {item.value && (\n \n {item.value.toLocaleString()}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> &\n Pick & {\n hideIcon?: boolean\n nameKey?: string\n }) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config\n ? config[configLabelKey]\n : config[key as keyof typeof config]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-mira/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/base-mira/registry.json b/apps/v4/public/r/styles/base-mira/registry.json index b8c8cfbffa..3bf2dab33c 100644 --- a/apps/v4/public/r/styles/base-mira/registry.json +++ b/apps/v4/public/r/styles/base-mira/registry.json @@ -257,7 +257,7 @@ }, { "name": "chart", - "dependencies": ["recharts@2.15.4"], + "dependencies": ["recharts@3.8.0"], "registryDependencies": ["card"], "files": [ { diff --git a/apps/v4/public/r/styles/base-nova/chart.json b/apps/v4/public/r/styles/base-nova/chart.json index 9cb13b8456..991afd93f7 100644 --- a/apps/v4/public/r/styles/base-nova/chart.json +++ b/apps/v4/public/r/styles/base-nova/chart.json @@ -2,7 +2,7 @@ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "chart", "dependencies": [ - "recharts@2.15.4" + "recharts@3.8.0" ], "registryDependencies": [ "card" @@ -10,7 +10,7 @@ "files": [ { "path": "registry/base-nova/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\n\nimport { cn } from \"@/registry/base-nova/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nexport type ChartConfig = {\n [k in string]: {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n}\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id || uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme || config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n }) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey || item?.dataKey || item?.name || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? config[label as keyof typeof config]?.label || label\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey || item.name || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color || item.payload.fill || item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label || item.name}\n \n
\n {item.value && (\n \n {item.value.toLocaleString()}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> &\n Pick & {\n hideIcon?: boolean\n nameKey?: string\n }) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config\n ? config[configLabelKey]\n : config[key as keyof typeof config]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-nova/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/base-nova/registry.json b/apps/v4/public/r/styles/base-nova/registry.json index 5ad1badd83..2728d6058d 100644 --- a/apps/v4/public/r/styles/base-nova/registry.json +++ b/apps/v4/public/r/styles/base-nova/registry.json @@ -257,7 +257,7 @@ }, { "name": "chart", - "dependencies": ["recharts@2.15.4"], + "dependencies": ["recharts@3.8.0"], "registryDependencies": ["card"], "files": [ { diff --git a/apps/v4/public/r/styles/base-vega/chart.json b/apps/v4/public/r/styles/base-vega/chart.json index 96ec0d309a..12c9daa4a0 100644 --- a/apps/v4/public/r/styles/base-vega/chart.json +++ b/apps/v4/public/r/styles/base-vega/chart.json @@ -2,7 +2,7 @@ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "chart", "dependencies": [ - "recharts@2.15.4" + "recharts@3.8.0" ], "registryDependencies": [ "card" @@ -10,7 +10,7 @@ "files": [ { "path": "registry/base-vega/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\n\nimport { cn } from \"@/registry/base-vega/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nexport type ChartConfig = {\n [k in string]: {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n}\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id || uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme || config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n }) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey || item?.dataKey || item?.name || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? config[label as keyof typeof config]?.label || label\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey || item.name || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color || item.payload.fill || item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label || item.name}\n \n
\n {item.value && (\n \n {item.value.toLocaleString()}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> &\n Pick & {\n hideIcon?: boolean\n nameKey?: string\n }) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config\n ? config[configLabelKey]\n : config[key as keyof typeof config]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-vega/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/base-vega/registry.json b/apps/v4/public/r/styles/base-vega/registry.json index 84ea2be0c7..a4944370d4 100644 --- a/apps/v4/public/r/styles/base-vega/registry.json +++ b/apps/v4/public/r/styles/base-vega/registry.json @@ -257,7 +257,7 @@ }, { "name": "chart", - "dependencies": ["recharts@2.15.4"], + "dependencies": ["recharts@3.8.0"], "registryDependencies": ["card"], "files": [ { diff --git a/apps/v4/public/r/styles/new-york-v4/chart-bar-active.json b/apps/v4/public/r/styles/new-york-v4/chart-bar-active.json index a6da9eb0a4..b8c88b10f4 100644 --- a/apps/v4/public/r/styles/new-york-v4/chart-bar-active.json +++ b/apps/v4/public/r/styles/new-york-v4/chart-bar-active.json @@ -8,7 +8,7 @@ "files": [ { "path": "registry/new-york-v4/charts/chart-bar-active.tsx", - "content": "\"use client\"\n\nimport { TrendingUp } from \"lucide-react\"\nimport { Bar, BarChart, CartesianGrid, Rectangle, XAxis } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A bar chart with an active bar\"\n\nconst chartData = [\n { browser: \"chrome\", visitors: 187, fill: \"var(--color-chrome)\" },\n { browser: \"safari\", visitors: 200, fill: \"var(--color-safari)\" },\n { browser: \"firefox\", visitors: 275, fill: \"var(--color-firefox)\" },\n { browser: \"edge\", visitors: 173, fill: \"var(--color-edge)\" },\n { browser: \"other\", visitors: 90, fill: \"var(--color-other)\" },\n]\n\nconst chartConfig = {\n visitors: {\n label: \"Visitors\",\n },\n chrome: {\n label: \"Chrome\",\n color: \"var(--chart-1)\",\n },\n safari: {\n label: \"Safari\",\n color: \"var(--chart-2)\",\n },\n firefox: {\n label: \"Firefox\",\n color: \"var(--chart-3)\",\n },\n edge: {\n label: \"Edge\",\n color: \"var(--chart-4)\",\n },\n other: {\n label: \"Other\",\n color: \"var(--chart-5)\",\n },\n} satisfies ChartConfig\n\nexport function ChartBarActive() {\n return (\n \n \n Bar Chart - Active\n January - June 2024\n \n \n \n \n \n \n chartConfig[value as keyof typeof chartConfig]?.label\n }\n />\n }\n />\n {\n return (\n \n )\n }}\n />\n \n \n \n \n
\n Trending up by 5.2% this month \n
\n
\n Showing total visitors for the last 6 months\n
\n
\n
\n )\n}\n", + "content": "\"use client\"\n\nimport { TrendingUp } from \"lucide-react\"\nimport { Bar, BarChart, CartesianGrid, Rectangle, XAxis } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A bar chart with an active bar\"\n\nconst chartData = [\n { browser: \"chrome\", visitors: 187, fill: \"var(--color-chrome)\" },\n { browser: \"safari\", visitors: 200, fill: \"var(--color-safari)\" },\n { browser: \"firefox\", visitors: 275, fill: \"var(--color-firefox)\" },\n { browser: \"edge\", visitors: 173, fill: \"var(--color-edge)\" },\n { browser: \"other\", visitors: 90, fill: \"var(--color-other)\" },\n]\n\nconst chartConfig = {\n visitors: {\n label: \"Visitors\",\n },\n chrome: {\n label: \"Chrome\",\n color: \"var(--chart-1)\",\n },\n safari: {\n label: \"Safari\",\n color: \"var(--chart-2)\",\n },\n firefox: {\n label: \"Firefox\",\n color: \"var(--chart-3)\",\n },\n edge: {\n label: \"Edge\",\n color: \"var(--chart-4)\",\n },\n other: {\n label: \"Other\",\n color: \"var(--chart-5)\",\n },\n} satisfies ChartConfig\n\nexport function ChartBarActive() {\n return (\n \n \n Bar Chart - Active\n January - June 2024\n \n \n \n \n \n \n chartConfig[value as keyof typeof chartConfig]?.label\n }\n />\n }\n defaultIndex={2}\n />\n {\n return (\n \n )\n }}\n />\n \n \n \n \n
\n Trending up by 5.2% this month \n
\n
\n Showing total visitors for the last 6 months\n
\n
\n
\n )\n}\n", "type": "registry:block" } ], diff --git a/apps/v4/public/r/styles/new-york-v4/chart-bar-label-custom.json b/apps/v4/public/r/styles/new-york-v4/chart-bar-label-custom.json index 0d2b1c4d7f..1829f1a322 100644 --- a/apps/v4/public/r/styles/new-york-v4/chart-bar-label-custom.json +++ b/apps/v4/public/r/styles/new-york-v4/chart-bar-label-custom.json @@ -8,7 +8,7 @@ "files": [ { "path": "registry/new-york-v4/charts/chart-bar-label-custom.tsx", - "content": "\"use client\"\n\nimport { TrendingUp } from \"lucide-react\"\nimport { Bar, BarChart, CartesianGrid, LabelList, XAxis, YAxis } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A bar chart with a custom label\"\n\nconst chartData = [\n { month: \"January\", desktop: 186, mobile: 80 },\n { month: \"February\", desktop: 305, mobile: 200 },\n { month: \"March\", desktop: 237, mobile: 120 },\n { month: \"April\", desktop: 73, mobile: 190 },\n { month: \"May\", desktop: 209, mobile: 130 },\n { month: \"June\", desktop: 214, mobile: 140 },\n]\n\nconst chartConfig = {\n desktop: {\n label: \"Desktop\",\n color: \"var(--chart-2)\",\n },\n mobile: {\n label: \"Mobile\",\n color: \"var(--chart-2)\",\n },\n label: {\n color: \"var(--background)\",\n },\n} satisfies ChartConfig\n\nexport function ChartBarLabelCustom() {\n return (\n \n \n Bar Chart - Custom Label\n January - June 2024\n \n \n \n \n \n value.slice(0, 3)}\n hide\n />\n \n }\n />\n \n \n \n \n \n \n \n \n
\n Trending up by 5.2% this month \n
\n
\n Showing total visitors for the last 6 months\n
\n
\n
\n )\n}\n", + "content": "\"use client\"\n\nimport { TrendingUp } from \"lucide-react\"\nimport { Bar, BarChart, CartesianGrid, LabelList, XAxis, YAxis } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A bar chart with a custom label\"\n\nconst chartData = [\n { month: \"January\", desktop: 186, mobile: 80 },\n { month: \"February\", desktop: 305, mobile: 200 },\n { month: \"March\", desktop: 237, mobile: 120 },\n { month: \"April\", desktop: 73, mobile: 190 },\n { month: \"May\", desktop: 209, mobile: 130 },\n { month: \"June\", desktop: 214, mobile: 140 },\n]\n\nconst chartConfig = {\n desktop: {\n label: \"Desktop\",\n color: \"var(--chart-2)\",\n },\n mobile: {\n label: \"Mobile\",\n color: \"var(--chart-2)\",\n },\n label: {\n color: \"var(--background)\",\n },\n} satisfies ChartConfig\n\nexport function ChartBarLabelCustom() {\n return (\n \n \n Bar Chart - Custom Label\n January - June 2024\n \n \n \n \n \n value.slice(0, 3)}\n hide\n />\n \n }\n />\n \n \n \n \n \n \n \n \n
\n Trending up by 5.2% this month \n
\n
\n Showing total visitors for the last 6 months\n
\n
\n
\n )\n}\n", "type": "registry:block" } ], diff --git a/apps/v4/public/r/styles/new-york-v4/chart-bar-mixed.json b/apps/v4/public/r/styles/new-york-v4/chart-bar-mixed.json index edce7cbae6..06510b8b5f 100644 --- a/apps/v4/public/r/styles/new-york-v4/chart-bar-mixed.json +++ b/apps/v4/public/r/styles/new-york-v4/chart-bar-mixed.json @@ -8,7 +8,7 @@ "files": [ { "path": "registry/new-york-v4/charts/chart-bar-mixed.tsx", - "content": "\"use client\"\n\nimport { TrendingUp } from \"lucide-react\"\nimport { Bar, BarChart, XAxis, YAxis } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A mixed bar chart\"\n\nconst chartData = [\n { browser: \"chrome\", visitors: 275, fill: \"var(--color-chrome)\" },\n { browser: \"safari\", visitors: 200, fill: \"var(--color-safari)\" },\n { browser: \"firefox\", visitors: 187, fill: \"var(--color-firefox)\" },\n { browser: \"edge\", visitors: 173, fill: \"var(--color-edge)\" },\n { browser: \"other\", visitors: 90, fill: \"var(--color-other)\" },\n]\n\nconst chartConfig = {\n visitors: {\n label: \"Visitors\",\n },\n chrome: {\n label: \"Chrome\",\n color: \"var(--chart-1)\",\n },\n safari: {\n label: \"Safari\",\n color: \"var(--chart-2)\",\n },\n firefox: {\n label: \"Firefox\",\n color: \"var(--chart-3)\",\n },\n edge: {\n label: \"Edge\",\n color: \"var(--chart-4)\",\n },\n other: {\n label: \"Other\",\n color: \"var(--chart-5)\",\n },\n} satisfies ChartConfig\n\nexport function ChartBarMixed() {\n return (\n \n \n Bar Chart - Mixed\n January - June 2024\n \n \n \n \n \n chartConfig[value as keyof typeof chartConfig]?.label\n }\n />\n \n }\n />\n \n \n \n \n \n
\n Trending up by 5.2% this month \n
\n
\n Showing total visitors for the last 6 months\n
\n
\n
\n )\n}\n", + "content": "\"use client\"\n\nimport { TrendingUp } from \"lucide-react\"\nimport { Bar, BarChart, XAxis, YAxis } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A mixed bar chart\"\n\nconst chartData = [\n { browser: \"chrome\", visitors: 275, fill: \"var(--color-chrome)\" },\n { browser: \"safari\", visitors: 200, fill: \"var(--color-safari)\" },\n { browser: \"firefox\", visitors: 187, fill: \"var(--color-firefox)\" },\n { browser: \"edge\", visitors: 173, fill: \"var(--color-edge)\" },\n { browser: \"other\", visitors: 90, fill: \"var(--color-other)\" },\n]\n\nconst chartConfig = {\n visitors: {\n label: \"Visitors\",\n },\n chrome: {\n label: \"Chrome\",\n color: \"var(--chart-1)\",\n },\n safari: {\n label: \"Safari\",\n color: \"var(--chart-2)\",\n },\n firefox: {\n label: \"Firefox\",\n color: \"var(--chart-3)\",\n },\n edge: {\n label: \"Edge\",\n color: \"var(--chart-4)\",\n },\n other: {\n label: \"Other\",\n color: \"var(--chart-5)\",\n },\n} satisfies ChartConfig\n\nexport function ChartBarMixed() {\n return (\n \n \n Bar Chart - Mixed\n January - June 2024\n \n \n \n \n \n chartConfig[value as keyof typeof chartConfig]?.label\n }\n />\n \n }\n />\n \n \n \n \n \n
\n Trending up by 5.2% this month \n
\n
\n Showing total visitors for the last 6 months\n
\n
\n
\n )\n}\n", "type": "registry:block" } ], diff --git a/apps/v4/public/r/styles/new-york-v4/chart-line-dots-custom.json b/apps/v4/public/r/styles/new-york-v4/chart-line-dots-custom.json index 8a513c1147..78e6e964eb 100644 --- a/apps/v4/public/r/styles/new-york-v4/chart-line-dots-custom.json +++ b/apps/v4/public/r/styles/new-york-v4/chart-line-dots-custom.json @@ -8,7 +8,7 @@ "files": [ { "path": "registry/new-york-v4/charts/chart-line-dots-custom.tsx", - "content": "\"use client\"\n\nimport { GitCommitVertical, TrendingUp } from \"lucide-react\"\nimport { CartesianGrid, Line, LineChart, XAxis } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A line chart with custom dots\"\n\nconst chartData = [\n { month: \"January\", desktop: 186, mobile: 80 },\n { month: \"February\", desktop: 305, mobile: 200 },\n { month: \"March\", desktop: 237, mobile: 120 },\n { month: \"April\", desktop: 73, mobile: 190 },\n { month: \"May\", desktop: 209, mobile: 130 },\n { month: \"June\", desktop: 214, mobile: 140 },\n]\n\nconst chartConfig = {\n desktop: {\n label: \"Desktop\",\n color: \"var(--chart-1)\",\n },\n mobile: {\n label: \"Mobile\",\n color: \"var(--chart-2)\",\n },\n} satisfies ChartConfig\n\nexport function ChartLineDotsCustom() {\n return (\n \n \n Line Chart - Custom Dots\n January - June 2024\n \n \n \n \n \n value.slice(0, 3)}\n />\n }\n />\n {\n const r = 24\n return (\n \n )\n }}\n />\n \n \n \n \n
\n Trending up by 5.2% this month \n
\n
\n Showing total visitors for the last 6 months\n
\n
\n
\n )\n}\n", + "content": "\"use client\"\n\nimport { GitCommitVertical, TrendingUp } from \"lucide-react\"\nimport { CartesianGrid, Line, LineChart, XAxis } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A line chart with custom dots\"\n\nconst chartData = [\n { month: \"January\", desktop: 186, mobile: 80 },\n { month: \"February\", desktop: 305, mobile: 200 },\n { month: \"March\", desktop: 237, mobile: 120 },\n { month: \"April\", desktop: 73, mobile: 190 },\n { month: \"May\", desktop: 209, mobile: 130 },\n { month: \"June\", desktop: 214, mobile: 140 },\n]\n\nconst chartConfig = {\n desktop: {\n label: \"Desktop\",\n color: \"var(--chart-1)\",\n },\n mobile: {\n label: \"Mobile\",\n color: \"var(--chart-2)\",\n },\n} satisfies ChartConfig\n\nexport function ChartLineDotsCustom() {\n return (\n \n \n Line Chart - Custom Dots\n January - June 2024\n \n \n \n \n \n value.slice(0, 3)}\n />\n }\n />\n {\n if (cx == null || cy == null) {\n return null\n }\n\n const r = 24\n\n return (\n \n )\n }}\n />\n \n \n \n \n
\n Trending up by 5.2% this month \n
\n
\n Showing total visitors for the last 6 months\n
\n
\n
\n )\n}\n", "type": "registry:block" } ], diff --git a/apps/v4/public/r/styles/new-york-v4/chart-line-label-custom.json b/apps/v4/public/r/styles/new-york-v4/chart-line-label-custom.json index 95d87c621d..8910a45628 100644 --- a/apps/v4/public/r/styles/new-york-v4/chart-line-label-custom.json +++ b/apps/v4/public/r/styles/new-york-v4/chart-line-label-custom.json @@ -8,7 +8,7 @@ "files": [ { "path": "registry/new-york-v4/charts/chart-line-label-custom.tsx", - "content": "\"use client\"\n\nimport { TrendingUp } from \"lucide-react\"\nimport { CartesianGrid, LabelList, Line, LineChart } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A line chart with a custom label\"\n\nconst chartData = [\n { browser: \"chrome\", visitors: 275, fill: \"var(--color-chrome)\" },\n { browser: \"safari\", visitors: 200, fill: \"var(--color-safari)\" },\n { browser: \"firefox\", visitors: 187, fill: \"var(--color-firefox)\" },\n { browser: \"edge\", visitors: 173, fill: \"var(--color-edge)\" },\n { browser: \"other\", visitors: 90, fill: \"var(--color-other)\" },\n]\n\nconst chartConfig = {\n visitors: {\n label: \"Visitors\",\n color: \"var(--chart-2)\",\n },\n chrome: {\n label: \"Chrome\",\n color: \"var(--chart-1)\",\n },\n safari: {\n label: \"Safari\",\n color: \"var(--chart-2)\",\n },\n firefox: {\n label: \"Firefox\",\n color: \"var(--chart-3)\",\n },\n edge: {\n label: \"Edge\",\n color: \"var(--chart-4)\",\n },\n other: {\n label: \"Other\",\n color: \"var(--chart-5)\",\n },\n} satisfies ChartConfig\n\nexport function ChartLineLabelCustom() {\n return (\n \n \n Line Chart - Custom Label\n January - June 2024\n \n \n \n \n \n \n }\n />\n \n \n chartConfig[value]?.label\n }\n />\n \n \n \n \n \n
\n Trending up by 5.2% this month \n
\n
\n Showing total visitors for the last 6 months\n
\n
\n
\n )\n}\n", + "content": "\"use client\"\n\nimport { TrendingUp } from \"lucide-react\"\nimport { CartesianGrid, LabelList, Line, LineChart } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A line chart with a custom label\"\n\nconst chartData = [\n { browser: \"chrome\", visitors: 275, fill: \"var(--color-chrome)\" },\n { browser: \"safari\", visitors: 200, fill: \"var(--color-safari)\" },\n { browser: \"firefox\", visitors: 187, fill: \"var(--color-firefox)\" },\n { browser: \"edge\", visitors: 173, fill: \"var(--color-edge)\" },\n { browser: \"other\", visitors: 90, fill: \"var(--color-other)\" },\n]\n\nconst chartConfig = {\n visitors: {\n label: \"Visitors\",\n color: \"var(--chart-2)\",\n },\n chrome: {\n label: \"Chrome\",\n color: \"var(--chart-1)\",\n },\n safari: {\n label: \"Safari\",\n color: \"var(--chart-2)\",\n },\n firefox: {\n label: \"Firefox\",\n color: \"var(--chart-3)\",\n },\n edge: {\n label: \"Edge\",\n color: \"var(--chart-4)\",\n },\n other: {\n label: \"Other\",\n color: \"var(--chart-5)\",\n },\n} satisfies ChartConfig\n\nexport function ChartLineLabelCustom() {\n return (\n \n \n Line Chart - Custom Label\n January - June 2024\n \n \n \n \n \n \n }\n />\n \n \n chartConfig[value as keyof typeof chartConfig]?.label\n }\n />\n \n \n \n \n \n
\n Trending up by 5.2% this month \n
\n
\n Showing total visitors for the last 6 months\n
\n
\n
\n )\n}\n", "type": "registry:block" } ], diff --git a/apps/v4/public/r/styles/new-york-v4/chart-pie-donut-active.json b/apps/v4/public/r/styles/new-york-v4/chart-pie-donut-active.json index a852738a1b..3d58ae15cb 100644 --- a/apps/v4/public/r/styles/new-york-v4/chart-pie-donut-active.json +++ b/apps/v4/public/r/styles/new-york-v4/chart-pie-donut-active.json @@ -8,7 +8,7 @@ "files": [ { "path": "registry/new-york-v4/charts/chart-pie-donut-active.tsx", - "content": "\"use client\"\n\nimport { TrendingUp } from \"lucide-react\"\nimport { Label, Pie, PieChart, Sector } from \"recharts\"\nimport { type PieSectorDataItem } from \"recharts/types/polar/Pie\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A donut chart with an active sector\"\n\nconst chartData = [\n { browser: \"chrome\", visitors: 275, fill: \"var(--color-chrome)\" },\n { browser: \"safari\", visitors: 200, fill: \"var(--color-safari)\" },\n { browser: \"firefox\", visitors: 187, fill: \"var(--color-firefox)\" },\n { browser: \"edge\", visitors: 173, fill: \"var(--color-edge)\" },\n { browser: \"other\", visitors: 90, fill: \"var(--color-other)\" },\n]\n\nconst chartConfig = {\n visitors: {\n label: \"Visitors\",\n },\n chrome: {\n label: \"Chrome\",\n color: \"var(--chart-1)\",\n },\n safari: {\n label: \"Safari\",\n color: \"var(--chart-2)\",\n },\n firefox: {\n label: \"Firefox\",\n color: \"var(--chart-3)\",\n },\n edge: {\n label: \"Edge\",\n color: \"var(--chart-4)\",\n },\n other: {\n label: \"Other\",\n color: \"var(--chart-5)\",\n },\n} satisfies ChartConfig\n\nexport function ChartPieDonutActive() {\n return (\n \n \n Pie Chart - Donut Active\n January - June 2024\n \n \n \n \n }\n />\n (\n \n )}\n />\n \n
\n
\n \n
\n Trending up by 5.2% this month \n
\n
\n Showing total visitors for the last 6 months\n
\n
\n \n )\n}\n", + "content": "\"use client\"\n\nimport { TrendingUp } from \"lucide-react\"\nimport { Label, Pie, PieChart, Sector } from \"recharts\"\nimport { type PieSectorDataItem } from \"recharts/types/polar/Pie\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A donut chart with an active sector\"\n\nconst chartData = [\n { browser: \"chrome\", visitors: 275, fill: \"var(--color-chrome)\" },\n { browser: \"safari\", visitors: 200, fill: \"var(--color-safari)\" },\n { browser: \"firefox\", visitors: 187, fill: \"var(--color-firefox)\" },\n { browser: \"edge\", visitors: 173, fill: \"var(--color-edge)\" },\n { browser: \"other\", visitors: 90, fill: \"var(--color-other)\" },\n]\n\nconst chartConfig = {\n visitors: {\n label: \"Visitors\",\n },\n chrome: {\n label: \"Chrome\",\n color: \"var(--chart-1)\",\n },\n safari: {\n label: \"Safari\",\n color: \"var(--chart-2)\",\n },\n firefox: {\n label: \"Firefox\",\n color: \"var(--chart-3)\",\n },\n edge: {\n label: \"Edge\",\n color: \"var(--chart-4)\",\n },\n other: {\n label: \"Other\",\n color: \"var(--chart-5)\",\n },\n} satisfies ChartConfig\n\nexport function ChartPieDonutActive() {\n return (\n \n \n Pie Chart - Donut Active\n January - June 2024\n \n \n \n \n }\n defaultIndex={0}\n />\n (\n \n )}\n />\n \n \n \n \n
\n Trending up by 5.2% this month \n
\n
\n Showing total visitors for the last 6 months\n
\n
\n
\n )\n}\n", "type": "registry:block" } ], diff --git a/apps/v4/public/r/styles/new-york-v4/chart-pie-interactive.json b/apps/v4/public/r/styles/new-york-v4/chart-pie-interactive.json index c9e0afe543..c3f1072211 100644 --- a/apps/v4/public/r/styles/new-york-v4/chart-pie-interactive.json +++ b/apps/v4/public/r/styles/new-york-v4/chart-pie-interactive.json @@ -8,7 +8,7 @@ "files": [ { "path": "registry/new-york-v4/charts/chart-pie-interactive.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Label, Pie, PieChart, Sector } from \"recharts\"\nimport { type PieSectorDataItem } from \"recharts/types/polar/Pie\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartStyle,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/new-york-v4/ui/select\"\n\nexport const description = \"An interactive pie chart\"\n\nconst desktopData = [\n { month: \"january\", desktop: 186, fill: \"var(--color-january)\" },\n { month: \"february\", desktop: 305, fill: \"var(--color-february)\" },\n { month: \"march\", desktop: 237, fill: \"var(--color-march)\" },\n { month: \"april\", desktop: 173, fill: \"var(--color-april)\" },\n { month: \"may\", desktop: 209, fill: \"var(--color-may)\" },\n]\n\nconst chartConfig = {\n visitors: {\n label: \"Visitors\",\n },\n desktop: {\n label: \"Desktop\",\n },\n mobile: {\n label: \"Mobile\",\n },\n january: {\n label: \"January\",\n color: \"var(--chart-1)\",\n },\n february: {\n label: \"February\",\n color: \"var(--chart-2)\",\n },\n march: {\n label: \"March\",\n color: \"var(--chart-3)\",\n },\n april: {\n label: \"April\",\n color: \"var(--chart-4)\",\n },\n may: {\n label: \"May\",\n color: \"var(--chart-5)\",\n },\n} satisfies ChartConfig\n\nexport function ChartPieInteractive() {\n const id = \"pie-interactive\"\n const [activeMonth, setActiveMonth] = React.useState(desktopData[0].month)\n\n const activeIndex = React.useMemo(\n () => desktopData.findIndex((item) => item.month === activeMonth),\n [activeMonth]\n )\n const months = React.useMemo(() => desktopData.map((item) => item.month), [])\n\n return (\n \n \n \n
\n Pie Chart - Interactive\n January - June 2024\n
\n \n
\n \n \n \n }\n />\n (\n \n \n \n \n )}\n >\n {\n if (viewBox && \"cx\" in viewBox && \"cy\" in viewBox) {\n return (\n \n \n {desktopData[activeIndex].desktop.toLocaleString()}\n \n \n Visitors\n \n \n )\n }\n }}\n />\n \n \n \n \n
\n )\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Label, Pie, PieChart, Sector } from \"recharts\"\nimport { type PieSectorDataItem } from \"recharts/types/polar/Pie\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartStyle,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/new-york-v4/ui/select\"\n\nexport const description = \"An interactive pie chart\"\n\nconst desktopData = [\n { month: \"january\", desktop: 186, fill: \"var(--color-january)\" },\n { month: \"february\", desktop: 305, fill: \"var(--color-february)\" },\n { month: \"march\", desktop: 237, fill: \"var(--color-march)\" },\n { month: \"april\", desktop: 173, fill: \"var(--color-april)\" },\n { month: \"may\", desktop: 209, fill: \"var(--color-may)\" },\n]\n\nconst chartConfig = {\n visitors: {\n label: \"Visitors\",\n },\n desktop: {\n label: \"Desktop\",\n },\n mobile: {\n label: \"Mobile\",\n },\n january: {\n label: \"January\",\n color: \"var(--chart-1)\",\n },\n february: {\n label: \"February\",\n color: \"var(--chart-2)\",\n },\n march: {\n label: \"March\",\n color: \"var(--chart-3)\",\n },\n april: {\n label: \"April\",\n color: \"var(--chart-4)\",\n },\n may: {\n label: \"May\",\n color: \"var(--chart-5)\",\n },\n} satisfies ChartConfig\n\nexport function ChartPieInteractive() {\n const id = \"pie-interactive\"\n const [activeMonth, setActiveMonth] = React.useState(desktopData[0].month)\n\n const activeIndex = React.useMemo(\n () => desktopData.findIndex((item) => item.month === activeMonth),\n [activeMonth]\n )\n const months = React.useMemo(() => desktopData.map((item) => item.month), [])\n\n return (\n \n \n \n
\n Pie Chart - Interactive\n January - June 2024\n
\n \n
\n \n \n \n }\n defaultIndex={activeIndex}\n />\n (\n \n \n \n \n )}\n >\n {\n if (viewBox && \"cx\" in viewBox && \"cy\" in viewBox) {\n return (\n \n \n {desktopData[activeIndex].desktop.toLocaleString()}\n \n \n Visitors\n \n \n )\n }\n }}\n />\n \n \n \n \n
\n )\n}\n", "type": "registry:block" } ], diff --git a/apps/v4/public/r/styles/new-york-v4/chart-pie-label-list.json b/apps/v4/public/r/styles/new-york-v4/chart-pie-label-list.json index 7cddc2c94c..9a17db23ac 100644 --- a/apps/v4/public/r/styles/new-york-v4/chart-pie-label-list.json +++ b/apps/v4/public/r/styles/new-york-v4/chart-pie-label-list.json @@ -8,7 +8,7 @@ "files": [ { "path": "registry/new-york-v4/charts/chart-pie-label-list.tsx", - "content": "\"use client\"\n\nimport { TrendingUp } from \"lucide-react\"\nimport { LabelList, Pie, PieChart } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A pie chart with a label list\"\n\nconst chartData = [\n { browser: \"chrome\", visitors: 275, fill: \"var(--color-chrome)\" },\n { browser: \"safari\", visitors: 200, fill: \"var(--color-safari)\" },\n { browser: \"firefox\", visitors: 187, fill: \"var(--color-firefox)\" },\n { browser: \"edge\", visitors: 173, fill: \"var(--color-edge)\" },\n { browser: \"other\", visitors: 90, fill: \"var(--color-other)\" },\n]\n\nconst chartConfig = {\n visitors: {\n label: \"Visitors\",\n },\n chrome: {\n label: \"Chrome\",\n color: \"var(--chart-1)\",\n },\n safari: {\n label: \"Safari\",\n color: \"var(--chart-2)\",\n },\n firefox: {\n label: \"Firefox\",\n color: \"var(--chart-3)\",\n },\n edge: {\n label: \"Edge\",\n color: \"var(--chart-4)\",\n },\n other: {\n label: \"Other\",\n color: \"var(--chart-5)\",\n },\n} satisfies ChartConfig\n\nexport function ChartPieLabelList() {\n return (\n \n \n Pie Chart - Label List\n January - June 2024\n \n \n \n \n }\n />\n \n \n chartConfig[value]?.label\n }\n />\n \n \n \n \n \n
\n Trending up by 5.2% this month \n
\n
\n Showing total visitors for the last 6 months\n
\n
\n
\n )\n}\n", + "content": "\"use client\"\n\nimport { TrendingUp } from \"lucide-react\"\nimport { LabelList, Pie, PieChart } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A pie chart with a label list\"\n\nconst chartData = [\n { browser: \"chrome\", visitors: 275, fill: \"var(--color-chrome)\" },\n { browser: \"safari\", visitors: 200, fill: \"var(--color-safari)\" },\n { browser: \"firefox\", visitors: 187, fill: \"var(--color-firefox)\" },\n { browser: \"edge\", visitors: 173, fill: \"var(--color-edge)\" },\n { browser: \"other\", visitors: 90, fill: \"var(--color-other)\" },\n]\n\nconst chartConfig = {\n visitors: {\n label: \"Visitors\",\n },\n chrome: {\n label: \"Chrome\",\n color: \"var(--chart-1)\",\n },\n safari: {\n label: \"Safari\",\n color: \"var(--chart-2)\",\n },\n firefox: {\n label: \"Firefox\",\n color: \"var(--chart-3)\",\n },\n edge: {\n label: \"Edge\",\n color: \"var(--chart-4)\",\n },\n other: {\n label: \"Other\",\n color: \"var(--chart-5)\",\n },\n} satisfies ChartConfig\n\nexport function ChartPieLabelList() {\n return (\n \n \n Pie Chart - Label List\n January - June 2024\n \n \n \n \n }\n />\n \n \n chartConfig[value as keyof typeof chartConfig]?.label\n }\n />\n \n \n \n \n \n
\n Trending up by 5.2% this month \n
\n
\n Showing total visitors for the last 6 months\n
\n
\n
\n )\n}\n", "type": "registry:block" } ], diff --git a/apps/v4/public/r/styles/new-york-v4/chart-radar-icons.json b/apps/v4/public/r/styles/new-york-v4/chart-radar-icons.json index 5c2aeb9aae..f96fdc6328 100644 --- a/apps/v4/public/r/styles/new-york-v4/chart-radar-icons.json +++ b/apps/v4/public/r/styles/new-york-v4/chart-radar-icons.json @@ -8,7 +8,7 @@ "files": [ { "path": "registry/new-york-v4/charts/chart-radar-icons.tsx", - "content": "\"use client\"\n\nimport { ArrowDownFromLine, ArrowUpFromLine, TrendingUp } from \"lucide-react\"\nimport { PolarAngleAxis, PolarGrid, Radar, RadarChart } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartLegend,\n ChartLegendContent,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A radar chart with icons\"\n\nconst chartData = [\n { month: \"January\", desktop: 186, mobile: 80 },\n { month: \"February\", desktop: 305, mobile: 200 },\n { month: \"March\", desktop: 237, mobile: 120 },\n { month: \"April\", desktop: 73, mobile: 190 },\n { month: \"May\", desktop: 209, mobile: 130 },\n { month: \"June\", desktop: 214, mobile: 140 },\n]\n\nconst chartConfig = {\n desktop: {\n label: \"Desktop\",\n color: \"var(--chart-1)\",\n icon: ArrowDownFromLine,\n },\n mobile: {\n label: \"Mobile\",\n color: \"var(--chart-2)\",\n icon: ArrowUpFromLine,\n },\n} satisfies ChartConfig\n\nexport function ChartRadarIcons() {\n return (\n \n \n Radar Chart - Icons\n \n Showing total visitors for the last 6 months\n \n \n \n \n \n }\n />\n \n \n \n \n } />\n \n \n \n \n
\n Trending up by 5.2% this month \n
\n
\n January - June 2024\n
\n
\n
\n )\n}\n", + "content": "\"use client\"\n\nimport { ArrowDownFromLine, ArrowUpFromLine, TrendingUp } from \"lucide-react\"\nimport { PolarAngleAxis, PolarGrid, Radar, RadarChart } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartLegend,\n ChartLegendContent,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A radar chart with icons\"\n\nconst chartData = [\n { month: \"January\", desktop: 186, mobile: 80 },\n { month: \"February\", desktop: 305, mobile: 200 },\n { month: \"March\", desktop: 237, mobile: 120 },\n { month: \"April\", desktop: 73, mobile: 190 },\n { month: \"May\", desktop: 209, mobile: 130 },\n { month: \"June\", desktop: 214, mobile: 140 },\n]\n\nconst chartConfig = {\n desktop: {\n label: \"Desktop\",\n color: \"var(--chart-1)\",\n icon: ArrowDownFromLine,\n },\n mobile: {\n label: \"Mobile\",\n color: \"var(--chart-2)\",\n icon: ArrowUpFromLine,\n },\n} satisfies ChartConfig\n\nexport function ChartRadarIcons() {\n return (\n \n \n Radar Chart - Icons\n \n Showing total visitors for the last 6 months\n \n \n \n \n \n }\n />\n \n \n \n \n } />\n \n \n \n \n
\n Trending up by 5.2% this month \n
\n
\n January - June 2024\n
\n
\n
\n )\n}\n", "type": "registry:block" } ], diff --git a/apps/v4/public/r/styles/new-york-v4/chart-radar-label-custom.json b/apps/v4/public/r/styles/new-york-v4/chart-radar-label-custom.json index f3d93a0a80..64d203f575 100644 --- a/apps/v4/public/r/styles/new-york-v4/chart-radar-label-custom.json +++ b/apps/v4/public/r/styles/new-york-v4/chart-radar-label-custom.json @@ -8,7 +8,7 @@ "files": [ { "path": "registry/new-york-v4/charts/chart-radar-label-custom.tsx", - "content": "\"use client\"\n\nimport { TrendingUp } from \"lucide-react\"\nimport { PolarAngleAxis, PolarGrid, Radar, RadarChart } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A radar chart with a custom label\"\n\nconst chartData = [\n { month: \"January\", desktop: 186, mobile: 80 },\n { month: \"February\", desktop: 305, mobile: 200 },\n { month: \"March\", desktop: 237, mobile: 120 },\n { month: \"April\", desktop: 73, mobile: 190 },\n { month: \"May\", desktop: 209, mobile: 130 },\n { month: \"June\", desktop: 214, mobile: 140 },\n]\n\nconst chartConfig = {\n desktop: {\n label: \"Desktop\",\n color: \"var(--chart-1)\",\n },\n mobile: {\n label: \"Mobile\",\n color: \"var(--chart-2)\",\n },\n} satisfies ChartConfig\n\nexport function ChartRadarLabelCustom() {\n return (\n \n \n Radar Chart - Custom Label\n \n Showing total visitors for the last 6 months\n \n \n \n \n \n }\n />\n {\n const data = chartData[index]\n\n return (\n \n {data.desktop}\n /\n {data.mobile}\n \n {data.month}\n \n \n )\n }}\n />\n\n \n \n \n \n \n \n \n
\n Trending up by 5.2% this month \n
\n
\n January - June 2024\n
\n
\n
\n )\n}\n", + "content": "\"use client\"\n\nimport { TrendingUp } from \"lucide-react\"\nimport { PolarAngleAxis, PolarGrid, Radar, RadarChart } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A radar chart with a custom label\"\n\nconst chartData = [\n { month: \"January\", desktop: 186, mobile: 80 },\n { month: \"February\", desktop: 305, mobile: 200 },\n { month: \"March\", desktop: 237, mobile: 120 },\n { month: \"April\", desktop: 73, mobile: 190 },\n { month: \"May\", desktop: 209, mobile: 130 },\n { month: \"June\", desktop: 214, mobile: 140 },\n]\n\nconst chartConfig = {\n desktop: {\n label: \"Desktop\",\n color: \"var(--chart-1)\",\n },\n mobile: {\n label: \"Mobile\",\n color: \"var(--chart-2)\",\n },\n} satisfies ChartConfig\n\nexport function ChartRadarLabelCustom() {\n return (\n \n \n Radar Chart - Custom Label\n \n Showing total visitors for the last 6 months\n \n \n \n \n \n }\n />\n {\n const data = chartData[index]\n const yValue = typeof y === \"number\" ? y : 0\n\n return (\n \n {data.desktop}\n /\n {data.mobile}\n \n {data.month}\n \n \n )\n }}\n />\n\n \n \n \n \n \n \n \n
\n Trending up by 5.2% this month \n
\n
\n January - June 2024\n
\n
\n
\n )\n}\n", "type": "registry:block" } ], diff --git a/apps/v4/public/r/styles/new-york-v4/chart-radar-legend.json b/apps/v4/public/r/styles/new-york-v4/chart-radar-legend.json index 52af275540..1a62644e40 100644 --- a/apps/v4/public/r/styles/new-york-v4/chart-radar-legend.json +++ b/apps/v4/public/r/styles/new-york-v4/chart-radar-legend.json @@ -8,7 +8,7 @@ "files": [ { "path": "registry/new-york-v4/charts/chart-radar-legend.tsx", - "content": "\"use client\"\n\nimport { TrendingUp } from \"lucide-react\"\nimport { PolarAngleAxis, PolarGrid, Radar, RadarChart } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartLegend,\n ChartLegendContent,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A radar chart with a legend\"\n\nconst chartData = [\n { month: \"January\", desktop: 186, mobile: 80 },\n { month: \"February\", desktop: 305, mobile: 200 },\n { month: \"March\", desktop: 237, mobile: 120 },\n { month: \"April\", desktop: 73, mobile: 190 },\n { month: \"May\", desktop: 209, mobile: 130 },\n { month: \"June\", desktop: 214, mobile: 140 },\n]\n\nconst chartConfig = {\n desktop: {\n label: \"Desktop\",\n color: \"var(--chart-1)\",\n },\n mobile: {\n label: \"Mobile\",\n color: \"var(--chart-2)\",\n },\n} satisfies ChartConfig\n\nexport function ChartRadarLegend() {\n return (\n \n \n Radar Chart - Legend\n \n Showing total visitors for the last 6 months\n \n \n \n \n \n }\n />\n \n \n \n \n } />\n \n \n \n \n
\n Trending up by 5.2% this month \n
\n
\n January - June 2024\n
\n
\n
\n )\n}\n", + "content": "\"use client\"\n\nimport { TrendingUp } from \"lucide-react\"\nimport { PolarAngleAxis, PolarGrid, Radar, RadarChart } from \"recharts\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartLegend,\n ChartLegendContent,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\n\nexport const description = \"A radar chart with a legend\"\n\nconst chartData = [\n { month: \"January\", desktop: 186, mobile: 80 },\n { month: \"February\", desktop: 305, mobile: 200 },\n { month: \"March\", desktop: 237, mobile: 120 },\n { month: \"April\", desktop: 73, mobile: 190 },\n { month: \"May\", desktop: 209, mobile: 130 },\n { month: \"June\", desktop: 214, mobile: 140 },\n]\n\nconst chartConfig = {\n desktop: {\n label: \"Desktop\",\n color: \"var(--chart-1)\",\n },\n mobile: {\n label: \"Mobile\",\n color: \"var(--chart-2)\",\n },\n} satisfies ChartConfig\n\nexport function ChartRadarLegend() {\n return (\n \n \n Radar Chart - Legend\n \n Showing total visitors for the last 6 months\n \n \n \n \n \n }\n />\n \n \n \n \n } />\n \n \n \n \n
\n Trending up by 5.2% this month \n
\n
\n January - June 2024\n
\n
\n
\n )\n}\n", "type": "registry:block" } ], diff --git a/apps/v4/public/r/styles/new-york-v4/chart.json b/apps/v4/public/r/styles/new-york-v4/chart.json index 65c4f8ed82..c50cd3db75 100644 --- a/apps/v4/public/r/styles/new-york-v4/chart.json +++ b/apps/v4/public/r/styles/new-york-v4/chart.json @@ -2,7 +2,7 @@ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "chart", "dependencies": [ - "recharts@2.15.4", + "recharts@3.8.0", "lucide-react" ], "registryDependencies": [ @@ -11,7 +11,7 @@ "files": [ { "path": "registry/new-york-v4/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\n\nimport { cn } from \"@/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nexport type ChartConfig = {\n [k in string]: {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n}\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id || uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme || config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n }) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey || item?.dataKey || item?.name || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? config[label as keyof typeof config]?.label || label\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey || item.name || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color || item.payload.fill || item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label || item.name}\n \n
\n {item.value && (\n \n {item.value.toLocaleString()}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> &\n Pick & {\n hideIcon?: boolean\n nameKey?: string\n }) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\n// Helper to extract item config from a payload.\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config\n ? config[configLabelKey]\n : config[key as keyof typeof config]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\n// Helper to extract item config from a payload.\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/new-york-v4/registry.json b/apps/v4/public/r/styles/new-york-v4/registry.json index bcea5cd601..c7324843e7 100644 --- a/apps/v4/public/r/styles/new-york-v4/registry.json +++ b/apps/v4/public/r/styles/new-york-v4/registry.json @@ -179,7 +179,7 @@ }, { "name": "chart", - "dependencies": ["recharts@2.15.4", "lucide-react"], + "dependencies": ["recharts@3.8.0", "lucide-react"], "registryDependencies": ["card"], "files": [ { diff --git a/apps/v4/public/r/styles/radix-lyra/chart.json b/apps/v4/public/r/styles/radix-lyra/chart.json index 880b88b1bd..a07351fe12 100644 --- a/apps/v4/public/r/styles/radix-lyra/chart.json +++ b/apps/v4/public/r/styles/radix-lyra/chart.json @@ -2,12 +2,12 @@ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "chart", "dependencies": [ - "recharts@2.15.4" + "recharts@3.8.0" ], "files": [ { "path": "registry/radix-lyra/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\n\nimport { cn } from \"@/registry/radix-lyra/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nexport type ChartConfig = {\n [k in string]: {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n}\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id || uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme || config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n }) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey || item?.dataKey || item?.name || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? config[label as keyof typeof config]?.label || label\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey || item.name || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color || item.payload.fill || item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label || item.name}\n \n
\n {item.value && (\n \n {item.value.toLocaleString()}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> &\n Pick & {\n hideIcon?: boolean\n nameKey?: string\n }) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config\n ? config[configLabelKey]\n : config[key as keyof typeof config]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-lyra/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-lyra/registry.json b/apps/v4/public/r/styles/radix-lyra/registry.json index d47b6b2500..d636b20154 100644 --- a/apps/v4/public/r/styles/radix-lyra/registry.json +++ b/apps/v4/public/r/styles/radix-lyra/registry.json @@ -250,7 +250,7 @@ }, { "name": "chart", - "dependencies": ["recharts@2.15.4"], + "dependencies": ["recharts@3.8.0"], "files": [ { "path": "registry/radix-lyra/ui/chart.tsx", diff --git a/apps/v4/public/r/styles/radix-maia/chart.json b/apps/v4/public/r/styles/radix-maia/chart.json index efde1cf26e..c96d36dbe9 100644 --- a/apps/v4/public/r/styles/radix-maia/chart.json +++ b/apps/v4/public/r/styles/radix-maia/chart.json @@ -2,12 +2,12 @@ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "chart", "dependencies": [ - "recharts@2.15.4" + "recharts@3.8.0" ], "files": [ { "path": "registry/radix-maia/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\n\nimport { cn } from \"@/registry/radix-maia/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nexport type ChartConfig = {\n [k in string]: {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n}\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id || uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme || config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n }) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey || item?.dataKey || item?.name || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? config[label as keyof typeof config]?.label || label\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey || item.name || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color || item.payload.fill || item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label || item.name}\n \n
\n {item.value && (\n \n {item.value.toLocaleString()}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> &\n Pick & {\n hideIcon?: boolean\n nameKey?: string\n }) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config\n ? config[configLabelKey]\n : config[key as keyof typeof config]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-maia/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-maia/registry.json b/apps/v4/public/r/styles/radix-maia/registry.json index 1c54b1812d..cd05f6bf6f 100644 --- a/apps/v4/public/r/styles/radix-maia/registry.json +++ b/apps/v4/public/r/styles/radix-maia/registry.json @@ -250,7 +250,7 @@ }, { "name": "chart", - "dependencies": ["recharts@2.15.4"], + "dependencies": ["recharts@3.8.0"], "files": [ { "path": "registry/radix-maia/ui/chart.tsx", diff --git a/apps/v4/public/r/styles/radix-mira/chart.json b/apps/v4/public/r/styles/radix-mira/chart.json index 933164b334..df4bc3efef 100644 --- a/apps/v4/public/r/styles/radix-mira/chart.json +++ b/apps/v4/public/r/styles/radix-mira/chart.json @@ -2,12 +2,12 @@ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "chart", "dependencies": [ - "recharts@2.15.4" + "recharts@3.8.0" ], "files": [ { "path": "registry/radix-mira/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\n\nimport { cn } from \"@/registry/radix-mira/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nexport type ChartConfig = {\n [k in string]: {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n}\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id || uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme || config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n }) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey || item?.dataKey || item?.name || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? config[label as keyof typeof config]?.label || label\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey || item.name || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color || item.payload.fill || item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label || item.name}\n \n
\n {item.value && (\n \n {item.value.toLocaleString()}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> &\n Pick & {\n hideIcon?: boolean\n nameKey?: string\n }) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config\n ? config[configLabelKey]\n : config[key as keyof typeof config]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-mira/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-mira/registry.json b/apps/v4/public/r/styles/radix-mira/registry.json index d631a31b18..a71fdad378 100644 --- a/apps/v4/public/r/styles/radix-mira/registry.json +++ b/apps/v4/public/r/styles/radix-mira/registry.json @@ -250,7 +250,7 @@ }, { "name": "chart", - "dependencies": ["recharts@2.15.4"], + "dependencies": ["recharts@3.8.0"], "files": [ { "path": "registry/radix-mira/ui/chart.tsx", diff --git a/apps/v4/public/r/styles/radix-nova/chart.json b/apps/v4/public/r/styles/radix-nova/chart.json index be1b7ca155..b0ccde3b38 100644 --- a/apps/v4/public/r/styles/radix-nova/chart.json +++ b/apps/v4/public/r/styles/radix-nova/chart.json @@ -2,12 +2,12 @@ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "chart", "dependencies": [ - "recharts@2.15.4" + "recharts@3.8.0" ], "files": [ { "path": "registry/radix-nova/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\n\nimport { cn } from \"@/registry/radix-nova/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nexport type ChartConfig = {\n [k in string]: {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n}\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id || uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme || config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n }) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey || item?.dataKey || item?.name || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? config[label as keyof typeof config]?.label || label\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey || item.name || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color || item.payload.fill || item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label || item.name}\n \n
\n {item.value && (\n \n {item.value.toLocaleString()}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> &\n Pick & {\n hideIcon?: boolean\n nameKey?: string\n }) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config\n ? config[configLabelKey]\n : config[key as keyof typeof config]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-nova/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-nova/registry.json b/apps/v4/public/r/styles/radix-nova/registry.json index b883f6345e..1f952b0e7f 100644 --- a/apps/v4/public/r/styles/radix-nova/registry.json +++ b/apps/v4/public/r/styles/radix-nova/registry.json @@ -250,7 +250,7 @@ }, { "name": "chart", - "dependencies": ["recharts@2.15.4"], + "dependencies": ["recharts@3.8.0"], "files": [ { "path": "registry/radix-nova/ui/chart.tsx", diff --git a/apps/v4/public/r/styles/radix-vega/chart.json b/apps/v4/public/r/styles/radix-vega/chart.json index 6109c6fc3f..39f4908188 100644 --- a/apps/v4/public/r/styles/radix-vega/chart.json +++ b/apps/v4/public/r/styles/radix-vega/chart.json @@ -2,12 +2,12 @@ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "chart", "dependencies": [ - "recharts@2.15.4" + "recharts@3.8.0" ], "files": [ { "path": "registry/radix-vega/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\n\nimport { cn } from \"@/registry/radix-vega/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nexport type ChartConfig = {\n [k in string]: {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n}\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id || uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme || config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n }) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey || item?.dataKey || item?.name || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? config[label as keyof typeof config]?.label || label\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey || item.name || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color || item.payload.fill || item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label || item.name}\n \n
\n {item.value && (\n \n {item.value.toLocaleString()}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> &\n Pick & {\n hideIcon?: boolean\n nameKey?: string\n }) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config\n ? config[configLabelKey]\n : config[key as keyof typeof config]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-vega/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-vega/registry.json b/apps/v4/public/r/styles/radix-vega/registry.json index 8e8e8c3a81..e5abb8d15c 100644 --- a/apps/v4/public/r/styles/radix-vega/registry.json +++ b/apps/v4/public/r/styles/radix-vega/registry.json @@ -250,7 +250,7 @@ }, { "name": "chart", - "dependencies": ["recharts@2.15.4"], + "dependencies": ["recharts@3.8.0"], "files": [ { "path": "registry/radix-vega/ui/chart.tsx", diff --git a/apps/v4/registry/bases/base/blocks/preview/cards/sleep-report.tsx b/apps/v4/registry/bases/base/blocks/preview/cards/sleep-report.tsx index 19e5aee290..d52aa7f496 100644 --- a/apps/v4/registry/bases/base/blocks/preview/cards/sleep-report.tsx +++ b/apps/v4/registry/bases/base/blocks/preview/cards/sleep-report.tsx @@ -56,7 +56,7 @@ export function SleepReport() { } ) -} +> type ChartContextProps = { config: ChartConfig @@ -39,15 +46,20 @@ function ChartContainer({ className, children, config, + initialDimension = INITIAL_DIMENSION, ...props }: React.ComponentProps<"div"> & { config: ChartConfig children: React.ComponentProps< typeof RechartsPrimitive.ResponsiveContainer >["children"] + initialDimension?: { + width: number + height: number + } }) { const uniqueId = React.useId() - const chartId = `chart-${id || uniqueId.replace(/:/g, "")}` + const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}` return ( @@ -61,7 +73,9 @@ function ChartContainer({ {...props} > - + {children} @@ -71,7 +85,7 @@ function ChartContainer({ const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { const colorConfig = Object.entries(config).filter( - ([, config]) => config.theme || config.color + ([, config]) => config.theme ?? config.color ) if (!colorConfig.length) { @@ -88,7 +102,7 @@ ${prefix} [data-chart=${id}] { ${colorConfig .map(([key, itemConfig]) => { const color = - itemConfig.theme?.[theme as keyof typeof itemConfig.theme] || + itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ?? itemConfig.color return color ? ` --color-${key}: ${color};` : null }) @@ -125,7 +139,10 @@ function ChartTooltipContent({ indicator?: "line" | "dot" | "dashed" nameKey?: string labelKey?: string - }) { + } & Omit< + RechartsPrimitive.DefaultTooltipContentProps, + "accessibilityLayer" + >) { const { config } = useChart() const tooltipLabel = React.useMemo(() => { @@ -134,11 +151,11 @@ function ChartTooltipContent({ } const [item] = payload - const key = `${labelKey || item?.dataKey || item?.name || "value"}` + const key = `${labelKey ?? item?.dataKey ?? item?.name ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) const value = !labelKey && typeof label === "string" - ? config[label as keyof typeof config]?.label || label + ? (config[label]?.label ?? label) : itemConfig?.label if (labelFormatter) { @@ -179,13 +196,13 @@ function ChartTooltipContent({ {payload .filter((item) => item.type !== "none") .map((item, index) => { - const key = `${nameKey || item.name || item.dataKey || "value"}` + const key = `${nameKey ?? item.name ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) - const indicatorColor = color || item.payload.fill || item.color + const indicatorColor = color ?? item.payload?.fill ?? item.color return (
svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground", indicator === "dot" && "items-center" @@ -228,12 +245,14 @@ function ChartTooltipContent({
{nestLabel ? tooltipLabel : null} - {itemConfig?.label || item.name} + {itemConfig?.label ?? item.name}
- {item.value && ( + {item.value != null && ( - {item.value.toLocaleString()} + {typeof item.value === "number" + ? item.value.toLocaleString() + : String(item.value)} )}
@@ -255,11 +274,10 @@ function ChartLegendContent({ payload, verticalAlign = "bottom", nameKey, -}: React.ComponentProps<"div"> & - Pick & { - hideIcon?: boolean - nameKey?: string - }) { +}: React.ComponentProps<"div"> & { + hideIcon?: boolean + nameKey?: string +} & RechartsPrimitive.DefaultLegendContentProps) { const { config } = useChart() if (!payload?.length) { @@ -277,7 +295,7 @@ function ChartLegendContent({ {payload .filter((item) => item.type !== "none") .map((item) => { - const key = `${nameKey || item.dataKey || "value"}` + const key = `${nameKey ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) return ( @@ -338,9 +356,7 @@ function getPayloadConfigFromPayload( ] as string } - return configLabelKey in config - ? config[configLabelKey] - : config[key as keyof typeof config] + return configLabelKey in config ? config[configLabelKey] : config[key] } export { diff --git a/apps/v4/registry/bases/radix/blocks/preview/cards/sleep-report.tsx b/apps/v4/registry/bases/radix/blocks/preview/cards/sleep-report.tsx index 1959e699b5..157df2e90b 100644 --- a/apps/v4/registry/bases/radix/blocks/preview/cards/sleep-report.tsx +++ b/apps/v4/registry/bases/radix/blocks/preview/cards/sleep-report.tsx @@ -56,7 +56,7 @@ export function SleepReport() { } ) -} +> type ChartContextProps = { config: ChartConfig @@ -39,15 +46,20 @@ function ChartContainer({ className, children, config, + initialDimension = INITIAL_DIMENSION, ...props }: React.ComponentProps<"div"> & { config: ChartConfig children: React.ComponentProps< typeof RechartsPrimitive.ResponsiveContainer >["children"] + initialDimension?: { + width: number + height: number + } }) { const uniqueId = React.useId() - const chartId = `chart-${id || uniqueId.replace(/:/g, "")}` + const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}` return ( @@ -61,7 +73,9 @@ function ChartContainer({ {...props} > - + {children} @@ -71,7 +85,7 @@ function ChartContainer({ const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { const colorConfig = Object.entries(config).filter( - ([, config]) => config.theme || config.color + ([, config]) => config.theme ?? config.color ) if (!colorConfig.length) { @@ -88,7 +102,7 @@ ${prefix} [data-chart=${id}] { ${colorConfig .map(([key, itemConfig]) => { const color = - itemConfig.theme?.[theme as keyof typeof itemConfig.theme] || + itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ?? itemConfig.color return color ? ` --color-${key}: ${color};` : null }) @@ -125,7 +139,10 @@ function ChartTooltipContent({ indicator?: "line" | "dot" | "dashed" nameKey?: string labelKey?: string - }) { + } & Omit< + RechartsPrimitive.DefaultTooltipContentProps, + "accessibilityLayer" + >) { const { config } = useChart() const tooltipLabel = React.useMemo(() => { @@ -134,11 +151,11 @@ function ChartTooltipContent({ } const [item] = payload - const key = `${labelKey || item?.dataKey || item?.name || "value"}` + const key = `${labelKey ?? item?.dataKey ?? item?.name ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) const value = !labelKey && typeof label === "string" - ? config[label as keyof typeof config]?.label || label + ? (config[label]?.label ?? label) : itemConfig?.label if (labelFormatter) { @@ -179,13 +196,13 @@ function ChartTooltipContent({ {payload .filter((item) => item.type !== "none") .map((item, index) => { - const key = `${nameKey || item.name || item.dataKey || "value"}` + const key = `${nameKey ?? item.name ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) - const indicatorColor = color || item.payload.fill || item.color + const indicatorColor = color ?? item.payload?.fill ?? item.color return (
svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground", indicator === "dot" && "items-center" @@ -228,12 +245,14 @@ function ChartTooltipContent({
{nestLabel ? tooltipLabel : null} - {itemConfig?.label || item.name} + {itemConfig?.label ?? item.name}
- {item.value && ( + {item.value != null && ( - {item.value.toLocaleString()} + {typeof item.value === "number" + ? item.value.toLocaleString() + : String(item.value)} )}
@@ -255,11 +274,10 @@ function ChartLegendContent({ payload, verticalAlign = "bottom", nameKey, -}: React.ComponentProps<"div"> & - Pick & { - hideIcon?: boolean - nameKey?: string - }) { +}: React.ComponentProps<"div"> & { + hideIcon?: boolean + nameKey?: string +} & RechartsPrimitive.DefaultLegendContentProps) { const { config } = useChart() if (!payload?.length) { @@ -277,7 +295,7 @@ function ChartLegendContent({ {payload .filter((item) => item.type !== "none") .map((item) => { - const key = `${nameKey || item.dataKey || "value"}` + const key = `${nameKey ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) return ( @@ -338,9 +356,7 @@ function getPayloadConfigFromPayload( ] as string } - return configLabelKey in config - ? config[configLabelKey] - : config[key as keyof typeof config] + return configLabelKey in config ? config[configLabelKey] : config[key] } export { diff --git a/apps/v4/registry/new-york-v4/charts/chart-bar-active.tsx b/apps/v4/registry/new-york-v4/charts/chart-bar-active.tsx index a2762ef314..85b768774a 100644 --- a/apps/v4/registry/new-york-v4/charts/chart-bar-active.tsx +++ b/apps/v4/registry/new-york-v4/charts/chart-bar-active.tsx @@ -77,12 +77,12 @@ export function ChartBarActive() { } + defaultIndex={2} /> { return ( } /> - + } /> - +
diff --git a/apps/v4/registry/new-york-v4/charts/chart-line-dots-custom.tsx b/apps/v4/registry/new-york-v4/charts/chart-line-dots-custom.tsx index 07292f0d04..355f23a107 100644 --- a/apps/v4/registry/new-york-v4/charts/chart-line-dots-custom.tsx +++ b/apps/v4/registry/new-york-v4/charts/chart-line-dots-custom.tsx @@ -75,7 +75,12 @@ export function ChartLineDotsCustom() { stroke="var(--color-desktop)" strokeWidth={2} dot={({ cx, cy, payload }) => { + if (cx == null || cy == null) { + return null + } + const r = 24 + return ( - chartConfig[value]?.label + formatter={(value) => + chartConfig[value as keyof typeof chartConfig]?.label } /> diff --git a/apps/v4/registry/new-york-v4/charts/chart-pie-donut-active.tsx b/apps/v4/registry/new-york-v4/charts/chart-pie-donut-active.tsx index 48c13e6050..267e9d7cb5 100644 --- a/apps/v4/registry/new-york-v4/charts/chart-pie-donut-active.tsx +++ b/apps/v4/registry/new-york-v4/charts/chart-pie-donut-active.tsx @@ -71,6 +71,7 @@ export function ChartPieDonutActive() { } + defaultIndex={0} /> } + defaultIndex={activeIndex} /> - chartConfig[value]?.label + formatter={(value) => + chartConfig[value as keyof typeof chartConfig]?.label } /> diff --git a/apps/v4/registry/new-york-v4/charts/chart-radar-icons.tsx b/apps/v4/registry/new-york-v4/charts/chart-radar-icons.tsx index e279f7a293..3c4eec62fb 100644 --- a/apps/v4/registry/new-york-v4/charts/chart-radar-icons.tsx +++ b/apps/v4/registry/new-york-v4/charts/chart-radar-icons.tsx @@ -63,6 +63,8 @@ export function ChartRadarIcons() { margin={{ top: -40, bottom: -10, + left: 0, + right: 0, }} > { + tick={({ x, y, textAnchor, index, ...props }) => { const data = chartData[index] + const yValue = typeof y === "number" ? y : 0 return ( } ) -} +> type ChartContextProps = { config: ChartConfig @@ -39,15 +46,20 @@ function ChartContainer({ className, children, config, + initialDimension = INITIAL_DIMENSION, ...props }: React.ComponentProps<"div"> & { config: ChartConfig children: React.ComponentProps< typeof RechartsPrimitive.ResponsiveContainer >["children"] + initialDimension?: { + width: number + height: number + } }) { const uniqueId = React.useId() - const chartId = `chart-${id || uniqueId.replace(/:/g, "")}` + const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}` return ( @@ -61,7 +73,9 @@ function ChartContainer({ {...props} > - + {children} @@ -71,7 +85,7 @@ function ChartContainer({ const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { const colorConfig = Object.entries(config).filter( - ([, config]) => config.theme || config.color + ([, config]) => config.theme ?? config.color ) if (!colorConfig.length) { @@ -88,7 +102,7 @@ ${prefix} [data-chart=${id}] { ${colorConfig .map(([key, itemConfig]) => { const color = - itemConfig.theme?.[theme as keyof typeof itemConfig.theme] || + itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ?? itemConfig.color return color ? ` --color-${key}: ${color};` : null }) @@ -125,7 +139,10 @@ function ChartTooltipContent({ indicator?: "line" | "dot" | "dashed" nameKey?: string labelKey?: string - }) { + } & Omit< + RechartsPrimitive.DefaultTooltipContentProps, + "accessibilityLayer" + >) { const { config } = useChart() const tooltipLabel = React.useMemo(() => { @@ -134,11 +151,11 @@ function ChartTooltipContent({ } const [item] = payload - const key = `${labelKey || item?.dataKey || item?.name || "value"}` + const key = `${labelKey ?? item?.dataKey ?? item?.name ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) const value = !labelKey && typeof label === "string" - ? config[label as keyof typeof config]?.label || label + ? (config[label]?.label ?? label) : itemConfig?.label if (labelFormatter) { @@ -182,13 +199,13 @@ function ChartTooltipContent({ {payload .filter((item) => item.type !== "none") .map((item, index) => { - const key = `${nameKey || item.name || item.dataKey || "value"}` + const key = `${nameKey ?? item.name ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) - const indicatorColor = color || item.payload.fill || item.color + const indicatorColor = color ?? item.payload?.fill ?? item.color return (
svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground", indicator === "dot" && "items-center" @@ -231,12 +248,14 @@ function ChartTooltipContent({
{nestLabel ? tooltipLabel : null} - {itemConfig?.label || item.name} + {itemConfig?.label ?? item.name}
- {item.value && ( + {item.value != null && ( - {item.value.toLocaleString()} + {typeof item.value === "number" + ? item.value.toLocaleString() + : String(item.value)} )}
@@ -258,11 +277,10 @@ function ChartLegendContent({ payload, verticalAlign = "bottom", nameKey, -}: React.ComponentProps<"div"> & - Pick & { - hideIcon?: boolean - nameKey?: string - }) { +}: React.ComponentProps<"div"> & { + hideIcon?: boolean + nameKey?: string +} & RechartsPrimitive.DefaultLegendContentProps) { const { config } = useChart() if (!payload?.length) { @@ -280,7 +298,7 @@ function ChartLegendContent({ {payload .filter((item) => item.type !== "none") .map((item) => { - const key = `${nameKey || item.dataKey || "value"}` + const key = `${nameKey ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) return ( @@ -342,9 +360,7 @@ function getPayloadConfigFromPayload( ] as string } - return configLabelKey in config - ? config[configLabelKey] - : config[key as keyof typeof config] + return configLabelKey in config ? config[configLabelKey] : config[key] } export { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 47f8f14286..f86b54f6ac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -266,8 +266,8 @@ importers: specifier: ^8.5.9 version: 8.5.9(@types/react@19.2.2)(react@19.2.3) recharts: - specifier: 2.15.1 - version: 2.15.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + specifier: 3.8.0 + version: 3.8.0(@types/react@19.2.2)(react-dom@19.2.3(react@19.2.3))(react-is@18.3.1)(react@19.2.3)(redux@5.0.1) rehype-pretty-code: specifier: ^0.14.1 version: 0.14.1(shiki@1.29.2) @@ -2625,6 +2625,17 @@ packages: '@radix-ui/rect@1.1.1': resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} + '@reduxjs/toolkit@2.11.2': + resolution: {integrity: sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ==} + peerDependencies: + react: ^16.9.0 || ^17.0.0 || ^18 || ^19 + react-redux: ^7.2.1 || ^8.1.3 || ^9.0.0 + peerDependenciesMeta: + react: + optional: true + react-redux: + optional: true + '@remixicon/react@4.7.0': resolution: {integrity: sha512-ODBQjdbOjnFguCqctYkpDjERXOInNaBnRPDKfZOBvbzExBAwr2BaH/6AHFTg/UAFzBDkwtylfMT8iKPAkLwPLQ==} peerDependencies: @@ -2807,6 +2818,9 @@ packages: '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@standard-schema/utils@0.3.0': + resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==} + '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} @@ -3073,6 +3087,9 @@ packages: '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + '@types/use-sync-external-store@0.0.6': + resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==} + '@types/validate-npm-package-name@4.0.2': resolution: {integrity: sha512-lrpDziQipxCEeK5kWxvljWYhUvOiB2A9izZd9B2AFarYAkqZshb4lPbRs7zKEic6eGtH8V/2qJW+dPp9OtF6bw==} @@ -4209,9 +4226,6 @@ packages: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} - dom-helpers@5.2.1: - resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} - dot-prop@5.3.0: resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} engines: {node: '>=8'} @@ -4342,6 +4356,9 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} + es-toolkit@1.45.1: + resolution: {integrity: sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==} + esast-util-from-estree@2.0.0: resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==} @@ -4579,8 +4596,8 @@ packages: event-stream@3.3.4: resolution: {integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==} - eventemitter3@4.0.7: - resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} eventsource-parser@3.0.6: resolution: {integrity: sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==} @@ -4640,10 +4657,6 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-equals@5.2.2: - resolution: {integrity: sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==} - engines: {node: '>=6.0.0'} - fast-fifo@1.3.2: resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} @@ -5147,6 +5160,12 @@ packages: engines: {node: '>=16.x'} hasBin: true + immer@10.2.0: + resolution: {integrity: sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==} + + immer@11.1.4: + resolution: {integrity: sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw==} + import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} @@ -6688,6 +6707,18 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-redux@9.2.0: + resolution: {integrity: sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==} + peerDependencies: + '@types/react': 19.2.2 + react: ^18.0 || ^19 + redux: ^5.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + redux: + optional: true + react-remove-scroll-bar@2.3.8: resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} engines: {node: '>=10'} @@ -6714,12 +6745,6 @@ packages: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - react-smooth@4.0.4: - resolution: {integrity: sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-style-singleton@2.2.3: resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} engines: {node: '>=10'} @@ -6736,12 +6761,6 @@ packages: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-transition-group@4.4.5: - resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} - peerDependencies: - react: '>=16.6.0' - react-dom: '>=16.6.0' - react@19.2.3: resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==} engines: {node: '>=0.10.0'} @@ -6765,15 +6784,13 @@ packages: resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} engines: {node: '>= 4'} - recharts-scale@0.4.5: - resolution: {integrity: sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==} - - recharts@2.15.1: - resolution: {integrity: sha512-v8PUTUlyiDe56qUj82w/EDVuzEFXwEHp9/xOowGAZwfLjB9uAy3GllQVIYMWF6nU+qibx85WF75zD7AjqoT54Q==} - engines: {node: '>=14'} + recharts@3.8.0: + resolution: {integrity: sha512-Z/m38DX3L73ExO4Tpc9/iZWHmHnlzWG4njQbxsF5aSjwqmHNDDIm0rdEBArkwsBvR8U6EirlEHiQNYWCVh9sGQ==} + engines: {node: '>=18'} peerDependencies: - react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-is: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 recma-build-jsx@1.0.0: resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==} @@ -6789,6 +6806,14 @@ packages: recma-stringify@1.0.0: resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==} + redux-thunk@3.1.0: + resolution: {integrity: sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==} + peerDependencies: + redux: ^5.0.0 + + redux@5.0.1: + resolution: {integrity: sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==} + reflect.getprototypeof@1.0.10: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} @@ -7701,8 +7726,8 @@ packages: vfile@6.0.3: resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - victory-vendor@36.9.2: - resolution: {integrity: sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==} + victory-vendor@37.3.6: + resolution: {integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==} vite-node@2.1.9: resolution: {integrity: sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==} @@ -10128,6 +10153,18 @@ snapshots: '@radix-ui/rect@1.1.1': {} + '@reduxjs/toolkit@2.11.2(react-redux@9.2.0(@types/react@19.2.2)(react@19.2.3)(redux@5.0.1))(react@19.2.3)': + dependencies: + '@standard-schema/spec': 1.1.0 + '@standard-schema/utils': 0.3.0 + immer: 11.1.4 + redux: 5.0.1 + redux-thunk: 3.1.0(redux@5.0.1) + reselect: 5.1.1 + optionalDependencies: + react: 19.2.3 + react-redux: 9.2.0(@types/react@19.2.2)(react@19.2.3)(redux@5.0.1) + '@remixicon/react@4.7.0(react@19.2.3)': dependencies: react: 19.2.3 @@ -10294,6 +10331,8 @@ snapshots: '@standard-schema/spec@1.1.0': {} + '@standard-schema/utils@0.3.0': {} + '@swc/helpers@0.5.15': dependencies: tslib: 2.8.1 @@ -10549,6 +10588,8 @@ snapshots: '@types/unist@3.0.3': {} + '@types/use-sync-external-store@0.0.6': {} + '@types/validate-npm-package-name@4.0.2': {} '@types/yauzl@2.10.3': @@ -11675,11 +11716,6 @@ snapshots: dependencies: esutils: 2.0.3 - dom-helpers@5.2.1: - dependencies: - '@babel/runtime': 7.28.2 - csstype: 3.2.3 - dot-prop@5.3.0: dependencies: is-obj: 2.0.0 @@ -11864,6 +11900,8 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 + es-toolkit@1.45.1: {} + esast-util-from-estree@2.0.0: dependencies: '@types/estree-jsx': 1.0.5 @@ -12067,7 +12105,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.39.0(eslint@9.26.0(hono@4.11.7)(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.26.0(hono@4.11.7)(jiti@2.6.1)))(eslint@9.26.0(hono@4.11.7)(jiti@2.6.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.39.0(eslint@9.26.0(hono@4.11.7)(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.26.0(hono@4.11.7)(jiti@2.6.1)): dependencies: debug: 3.2.7 optionalDependencies: @@ -12078,7 +12116,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.54.0(eslint@9.26.0(hono@4.11.7)(jiti@1.21.7))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.26.0(hono@4.11.7)(jiti@1.21.7)))(eslint@9.26.0(hono@4.11.7)(jiti@1.21.7)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.54.0(eslint@9.26.0(hono@4.11.7)(jiti@1.21.7))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.26.0(hono@4.11.7)(jiti@1.21.7)): dependencies: debug: 3.2.7 optionalDependencies: @@ -12100,7 +12138,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.26.0(hono@4.11.7)(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.39.0(eslint@9.26.0(hono@4.11.7)(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.26.0(hono@4.11.7)(jiti@2.6.1)))(eslint@9.26.0(hono@4.11.7)(jiti@2.6.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.39.0(eslint@9.26.0(hono@4.11.7)(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.26.0(hono@4.11.7)(jiti@2.6.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -12129,7 +12167,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.26.0(hono@4.11.7)(jiti@1.21.7) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.54.0(eslint@9.26.0(hono@4.11.7)(jiti@1.21.7))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.26.0(hono@4.11.7)(jiti@1.21.7)))(eslint@9.26.0(hono@4.11.7)(jiti@1.21.7)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.54.0(eslint@9.26.0(hono@4.11.7)(jiti@1.21.7))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.26.0(hono@4.11.7)(jiti@1.21.7)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -12429,7 +12467,7 @@ snapshots: stream-combiner: 0.0.4 through: 2.3.8 - eventemitter3@4.0.7: {} + eventemitter3@5.0.4: {} eventsource-parser@3.0.6: {} @@ -12542,8 +12580,6 @@ snapshots: fast-deep-equal@3.1.3: {} - fast-equals@5.2.2: {} - fast-fifo@1.3.2: {} fast-glob@3.3.1: @@ -13149,6 +13185,10 @@ snapshots: image-size@2.0.2: {} + immer@10.2.0: {} + + immer@11.1.4: {} + import-fresh@3.3.1: dependencies: parent-module: 1.0.1 @@ -14848,6 +14888,15 @@ snapshots: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) + react-redux@9.2.0(@types/react@19.2.2)(react@19.2.3)(redux@5.0.1): + dependencies: + '@types/use-sync-external-store': 0.0.6 + react: 19.2.3 + use-sync-external-store: 1.6.0(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.2 + redux: 5.0.1 + react-remove-scroll-bar@2.3.8(@types/react@19.2.2)(react@19.2.3): dependencies: react: 19.2.3 @@ -14872,14 +14921,6 @@ snapshots: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) - react-smooth@4.0.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3): - dependencies: - fast-equals: 5.2.2 - prop-types: 15.8.1 - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - react-transition-group: 4.4.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - react-style-singleton@2.2.3(@types/react@19.2.2)(react@19.2.3): dependencies: get-nonce: 1.0.1 @@ -14897,15 +14938,6 @@ snapshots: transitivePeerDependencies: - '@types/react' - react-transition-group@4.4.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3): - dependencies: - '@babel/runtime': 7.28.2 - dom-helpers: 5.2.1 - loose-envify: 1.4.0 - prop-types: 15.8.1 - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - react@19.2.3: {} read-cache@1.0.0: @@ -14933,22 +14965,25 @@ snapshots: tiny-invariant: 1.3.3 tslib: 2.8.1 - recharts-scale@0.4.5: - dependencies: - decimal.js-light: 2.5.1 - - recharts@2.15.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + recharts@3.8.0(@types/react@19.2.2)(react-dom@19.2.3(react@19.2.3))(react-is@18.3.1)(react@19.2.3)(redux@5.0.1): dependencies: + '@reduxjs/toolkit': 2.11.2(react-redux@9.2.0(@types/react@19.2.2)(react@19.2.3)(redux@5.0.1))(react@19.2.3) clsx: 2.1.1 - eventemitter3: 4.0.7 - lodash: 4.17.23 + decimal.js-light: 2.5.1 + es-toolkit: 1.45.1 + eventemitter3: 5.0.4 + immer: 10.2.0 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) react-is: 18.3.1 - react-smooth: 4.0.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - recharts-scale: 0.4.5 + react-redux: 9.2.0(@types/react@19.2.2)(react@19.2.3)(redux@5.0.1) + reselect: 5.1.1 tiny-invariant: 1.3.3 - victory-vendor: 36.9.2 + use-sync-external-store: 1.6.0(react@19.2.3) + victory-vendor: 37.3.6 + transitivePeerDependencies: + - '@types/react' + - redux recma-build-jsx@1.0.0: dependencies: @@ -14979,6 +15014,12 @@ snapshots: unified: 11.0.5 vfile: 6.0.3 + redux-thunk@3.1.0(redux@5.0.1): + dependencies: + redux: 5.0.1 + + redux@5.0.1: {} + reflect.getprototypeof@1.0.10: dependencies: call-bind: 1.0.8 @@ -16117,7 +16158,7 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - victory-vendor@36.9.2: + victory-vendor@37.3.6: dependencies: '@types/d3-array': 3.2.1 '@types/d3-ease': 3.0.2 From 408b25c82ac762077418be9e6b9626a535384408 Mon Sep 17 00:00:00 2001 From: shadcn Date: Mon, 23 Mar 2026 12:29:31 +0400 Subject: [PATCH 28/88] fix(v4): stabilize chart legend keys --- apps/v4/examples/base/ui-rtl/chart.tsx | 4 ++-- apps/v4/examples/base/ui/chart.tsx | 4 ++-- apps/v4/examples/radix/ui-rtl/chart.tsx | 4 ++-- apps/v4/examples/radix/ui/chart.tsx | 4 ++-- apps/v4/public/r/styles/base-lyra/chart.json | 2 +- apps/v4/public/r/styles/base-maia/chart.json | 2 +- apps/v4/public/r/styles/base-mira/chart.json | 2 +- apps/v4/public/r/styles/base-nova/chart.json | 2 +- apps/v4/public/r/styles/base-vega/chart.json | 2 +- apps/v4/public/r/styles/new-york-v4/chart.json | 2 +- apps/v4/public/r/styles/radix-lyra/chart.json | 2 +- apps/v4/public/r/styles/radix-maia/chart.json | 2 +- apps/v4/public/r/styles/radix-mira/chart.json | 2 +- apps/v4/public/r/styles/radix-nova/chart.json | 2 +- apps/v4/public/r/styles/radix-vega/chart.json | 2 +- apps/v4/registry/bases/base/ui/chart.tsx | 4 ++-- apps/v4/registry/bases/radix/ui/chart.tsx | 4 ++-- apps/v4/registry/new-york-v4/ui/chart.tsx | 4 ++-- 18 files changed, 25 insertions(+), 25 deletions(-) diff --git a/apps/v4/examples/base/ui-rtl/chart.tsx b/apps/v4/examples/base/ui-rtl/chart.tsx index 71c63a4795..619bd25642 100644 --- a/apps/v4/examples/base/ui-rtl/chart.tsx +++ b/apps/v4/examples/base/ui-rtl/chart.tsx @@ -296,13 +296,13 @@ function ChartLegendContent({ > {payload .filter((item) => item.type !== "none") - .map((item) => { + .map((item, index) => { const key = `${nameKey ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) return (
svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground" )} diff --git a/apps/v4/examples/base/ui/chart.tsx b/apps/v4/examples/base/ui/chart.tsx index 71c63a4795..619bd25642 100644 --- a/apps/v4/examples/base/ui/chart.tsx +++ b/apps/v4/examples/base/ui/chart.tsx @@ -296,13 +296,13 @@ function ChartLegendContent({ > {payload .filter((item) => item.type !== "none") - .map((item) => { + .map((item, index) => { const key = `${nameKey ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) return (
svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground" )} diff --git a/apps/v4/examples/radix/ui-rtl/chart.tsx b/apps/v4/examples/radix/ui-rtl/chart.tsx index c1bf1e00a0..7dc49e6c0d 100644 --- a/apps/v4/examples/radix/ui-rtl/chart.tsx +++ b/apps/v4/examples/radix/ui-rtl/chart.tsx @@ -296,13 +296,13 @@ function ChartLegendContent({ > {payload .filter((item) => item.type !== "none") - .map((item) => { + .map((item, index) => { const key = `${nameKey ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) return (
svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground" )} diff --git a/apps/v4/examples/radix/ui/chart.tsx b/apps/v4/examples/radix/ui/chart.tsx index c1bf1e00a0..7dc49e6c0d 100644 --- a/apps/v4/examples/radix/ui/chart.tsx +++ b/apps/v4/examples/radix/ui/chart.tsx @@ -296,13 +296,13 @@ function ChartLegendContent({ > {payload .filter((item) => item.type !== "none") - .map((item) => { + .map((item, index) => { const key = `${nameKey ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) return (
svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground" )} diff --git a/apps/v4/public/r/styles/base-lyra/chart.json b/apps/v4/public/r/styles/base-lyra/chart.json index a19c6b4aa7..f09acfbf26 100644 --- a/apps/v4/public/r/styles/base-lyra/chart.json +++ b/apps/v4/public/r/styles/base-lyra/chart.json @@ -10,7 +10,7 @@ "files": [ { "path": "registry/base-lyra/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-lyra/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n
\n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n
\n )\n })}\n
\n
\n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-lyra/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n
\n \n
\n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/base-maia/chart.json b/apps/v4/public/r/styles/base-maia/chart.json index 895bd79b64..214672112c 100644 --- a/apps/v4/public/r/styles/base-maia/chart.json +++ b/apps/v4/public/r/styles/base-maia/chart.json @@ -10,7 +10,7 @@ "files": [ { "path": "registry/base-maia/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-maia/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-maia/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/base-mira/chart.json b/apps/v4/public/r/styles/base-mira/chart.json index 2a9c749d9e..7c29533a6b 100644 --- a/apps/v4/public/r/styles/base-mira/chart.json +++ b/apps/v4/public/r/styles/base-mira/chart.json @@ -10,7 +10,7 @@ "files": [ { "path": "registry/base-mira/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-mira/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-mira/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/base-nova/chart.json b/apps/v4/public/r/styles/base-nova/chart.json index 991afd93f7..009a933bf1 100644 --- a/apps/v4/public/r/styles/base-nova/chart.json +++ b/apps/v4/public/r/styles/base-nova/chart.json @@ -10,7 +10,7 @@ "files": [ { "path": "registry/base-nova/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-nova/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-nova/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/base-vega/chart.json b/apps/v4/public/r/styles/base-vega/chart.json index 12c9daa4a0..ade4fd2abd 100644 --- a/apps/v4/public/r/styles/base-vega/chart.json +++ b/apps/v4/public/r/styles/base-vega/chart.json @@ -10,7 +10,7 @@ "files": [ { "path": "registry/base-vega/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-vega/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-vega/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/new-york-v4/chart.json b/apps/v4/public/r/styles/new-york-v4/chart.json index c50cd3db75..2737da51cd 100644 --- a/apps/v4/public/r/styles/new-york-v4/chart.json +++ b/apps/v4/public/r/styles/new-york-v4/chart.json @@ -11,7 +11,7 @@ "files": [ { "path": "registry/new-york-v4/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\n// Helper to extract item config from a payload.\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\n// Helper to extract item config from a payload.\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-lyra/chart.json b/apps/v4/public/r/styles/radix-lyra/chart.json index a07351fe12..9006fc1057 100644 --- a/apps/v4/public/r/styles/radix-lyra/chart.json +++ b/apps/v4/public/r/styles/radix-lyra/chart.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/radix-lyra/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-lyra/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-lyra/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-maia/chart.json b/apps/v4/public/r/styles/radix-maia/chart.json index c96d36dbe9..9ded073db4 100644 --- a/apps/v4/public/r/styles/radix-maia/chart.json +++ b/apps/v4/public/r/styles/radix-maia/chart.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/radix-maia/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-maia/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-maia/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-mira/chart.json b/apps/v4/public/r/styles/radix-mira/chart.json index df4bc3efef..119e86ccb9 100644 --- a/apps/v4/public/r/styles/radix-mira/chart.json +++ b/apps/v4/public/r/styles/radix-mira/chart.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/radix-mira/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-mira/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-mira/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-nova/chart.json b/apps/v4/public/r/styles/radix-nova/chart.json index b0ccde3b38..0be1ab8988 100644 --- a/apps/v4/public/r/styles/radix-nova/chart.json +++ b/apps/v4/public/r/styles/radix-nova/chart.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/radix-nova/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-nova/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-nova/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-vega/chart.json b/apps/v4/public/r/styles/radix-vega/chart.json index 39f4908188..44d5906a57 100644 --- a/apps/v4/public/r/styles/radix-vega/chart.json +++ b/apps/v4/public/r/styles/radix-vega/chart.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/radix-vega/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-vega/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-vega/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/registry/bases/base/ui/chart.tsx b/apps/v4/registry/bases/base/ui/chart.tsx index 18cb5c9b60..6a5f115efa 100644 --- a/apps/v4/registry/bases/base/ui/chart.tsx +++ b/apps/v4/registry/bases/base/ui/chart.tsx @@ -294,13 +294,13 @@ function ChartLegendContent({ > {payload .filter((item) => item.type !== "none") - .map((item) => { + .map((item, index) => { const key = `${nameKey ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) return (
svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground" )} diff --git a/apps/v4/registry/bases/radix/ui/chart.tsx b/apps/v4/registry/bases/radix/ui/chart.tsx index 7c2febb63a..be02a47276 100644 --- a/apps/v4/registry/bases/radix/ui/chart.tsx +++ b/apps/v4/registry/bases/radix/ui/chart.tsx @@ -294,13 +294,13 @@ function ChartLegendContent({ > {payload .filter((item) => item.type !== "none") - .map((item) => { + .map((item, index) => { const key = `${nameKey ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) return (
svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground" )} diff --git a/apps/v4/registry/new-york-v4/ui/chart.tsx b/apps/v4/registry/new-york-v4/ui/chart.tsx index a671cf24f3..02f707c77e 100644 --- a/apps/v4/registry/new-york-v4/ui/chart.tsx +++ b/apps/v4/registry/new-york-v4/ui/chart.tsx @@ -297,13 +297,13 @@ function ChartLegendContent({ > {payload .filter((item) => item.type !== "none") - .map((item) => { + .map((item, index) => { const key = `${nameKey ?? item.dataKey ?? "value"}` const itemConfig = getPayloadConfigFromPayload(config, item, key) return (
svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground" )} From c5b40806491033e4abadb9c62cb2fe4d76b24109 Mon Sep 17 00:00:00 2001 From: shadcn Date: Mon, 23 Mar 2026 13:14:10 +0400 Subject: [PATCH 29/88] fix(v4): restore active chart demos --- .../components/chart-visitors.tsx | 45 +++++++++++-------- .../v4/content/docs/components/base/chart.mdx | 2 +- .../content/docs/components/radix/chart.mdx | 2 +- .../styles/new-york-v4/chart-bar-active.json | 2 +- .../new-york-v4/chart-pie-donut-active.json | 2 +- .../new-york-v4/chart-pie-interactive.json | 2 +- .../new-york-v4/charts/chart-bar-active.tsx | 12 +++-- .../charts/chart-pie-donut-active.tsx | 18 +++++--- .../charts/chart-pie-interactive.tsx | 40 ++++++++++------- 9 files changed, 76 insertions(+), 49 deletions(-) diff --git a/apps/v4/app/(examples)/dashboard-03/components/chart-visitors.tsx b/apps/v4/app/(examples)/dashboard-03/components/chart-visitors.tsx index 984ab8147d..ac3a36af64 100644 --- a/apps/v4/app/(examples)/dashboard-03/components/chart-visitors.tsx +++ b/apps/v4/app/(examples)/dashboard-03/components/chart-visitors.tsx @@ -2,7 +2,10 @@ import * as React from "react" import { Label, Pie, PieChart, Sector } from "recharts" -import { type PieSectorDataItem } from "recharts/types/polar/Pie" +import type { + PieSectorDataItem, + PieSectorShapeProps, +} from "recharts/types/polar/Pie" import { Card, @@ -77,6 +80,26 @@ export function ChartVisitors() { ) const months = React.useMemo(() => desktopData.map((item) => item.month), []) + const renderPieShape = React.useCallback( + ({ index, outerRadius = 0, ...props }: PieSectorShapeProps) => { + if (index === activeIndex) { + return ( + + + + + ) + } + + return + }, + [activeIndex] + ) + return ( @@ -126,30 +149,14 @@ export function ChartVisitors() { className="mx-auto aspect-square w-full max-w-[300px]" > - } - defaultIndex={activeIndex} - /> + } /> ( - - - - - )} + shape={renderPieShape} > \n \n \n \n \n )\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Label, Pie, PieChart, Sector } from \"recharts\"\nimport type {\n PieSectorDataItem,\n PieSectorShapeProps,\n} from \"recharts/types/polar/Pie\"\n\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york-v4/ui/card\"\nimport {\n ChartContainer,\n ChartStyle,\n ChartTooltip,\n ChartTooltipContent,\n type ChartConfig,\n} from \"@/registry/new-york-v4/ui/chart\"\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/new-york-v4/ui/select\"\n\nexport const description = \"An interactive pie chart\"\n\nconst desktopData = [\n { month: \"january\", desktop: 186, fill: \"var(--color-january)\" },\n { month: \"february\", desktop: 305, fill: \"var(--color-february)\" },\n { month: \"march\", desktop: 237, fill: \"var(--color-march)\" },\n { month: \"april\", desktop: 173, fill: \"var(--color-april)\" },\n { month: \"may\", desktop: 209, fill: \"var(--color-may)\" },\n]\n\nconst chartConfig = {\n visitors: {\n label: \"Visitors\",\n },\n desktop: {\n label: \"Desktop\",\n },\n mobile: {\n label: \"Mobile\",\n },\n january: {\n label: \"January\",\n color: \"var(--chart-1)\",\n },\n february: {\n label: \"February\",\n color: \"var(--chart-2)\",\n },\n march: {\n label: \"March\",\n color: \"var(--chart-3)\",\n },\n april: {\n label: \"April\",\n color: \"var(--chart-4)\",\n },\n may: {\n label: \"May\",\n color: \"var(--chart-5)\",\n },\n} satisfies ChartConfig\n\nexport function ChartPieInteractive() {\n const id = \"pie-interactive\"\n const [activeMonth, setActiveMonth] = React.useState(desktopData[0].month)\n\n const activeIndex = React.useMemo(\n () => desktopData.findIndex((item) => item.month === activeMonth),\n [activeMonth]\n )\n const months = React.useMemo(() => desktopData.map((item) => item.month), [])\n\n const renderPieShape = React.useCallback(\n ({ index, outerRadius = 0, ...props }: PieSectorShapeProps) => {\n if (index === activeIndex) {\n return (\n \n \n \n \n )\n }\n\n return \n },\n [activeIndex]\n )\n\n return (\n \n \n \n
\n Pie Chart - Interactive\n January - June 2024\n
\n \n
\n \n \n \n } />\n \n {\n if (viewBox && \"cx\" in viewBox && \"cy\" in viewBox) {\n return (\n \n \n {desktopData[activeIndex].desktop.toLocaleString()}\n \n \n Visitors\n \n \n )\n }\n }}\n />\n \n \n \n \n
\n )\n}\n", "type": "registry:block" } ], diff --git a/apps/v4/registry/new-york-v4/charts/chart-bar-active.tsx b/apps/v4/registry/new-york-v4/charts/chart-bar-active.tsx index 85b768774a..f76c5812e5 100644 --- a/apps/v4/registry/new-york-v4/charts/chart-bar-active.tsx +++ b/apps/v4/registry/new-york-v4/charts/chart-bar-active.tsx @@ -2,6 +2,7 @@ import { TrendingUp } from "lucide-react" import { Bar, BarChart, CartesianGrid, Rectangle, XAxis } from "recharts" +import type { BarShapeProps } from "recharts/types/cartesian/Bar" import { Card, @@ -54,6 +55,8 @@ const chartConfig = { }, } satisfies ChartConfig +const ACTIVE_INDEX = 2 + export function ChartBarActive() { return ( @@ -77,14 +80,13 @@ export function ChartBarActive() { } - defaultIndex={2} /> { - return ( + shape={({ index, ...props }: BarShapeProps) => + index === ACTIVE_INDEX ? ( + ) : ( + ) - }} + } /> diff --git a/apps/v4/registry/new-york-v4/charts/chart-pie-donut-active.tsx b/apps/v4/registry/new-york-v4/charts/chart-pie-donut-active.tsx index 267e9d7cb5..b2e41b5ebb 100644 --- a/apps/v4/registry/new-york-v4/charts/chart-pie-donut-active.tsx +++ b/apps/v4/registry/new-york-v4/charts/chart-pie-donut-active.tsx @@ -2,7 +2,7 @@ import { TrendingUp } from "lucide-react" import { Label, Pie, PieChart, Sector } from "recharts" -import { type PieSectorDataItem } from "recharts/types/polar/Pie" +import type { PieSectorShapeProps } from "recharts/types/polar/Pie" import { Card, @@ -55,6 +55,8 @@ const chartConfig = { }, } satisfies ChartConfig +const ACTIVE_INDEX = 0 + export function ChartPieDonutActive() { return ( @@ -71,7 +73,6 @@ export function ChartPieDonutActive() { } - defaultIndex={0} /> ( - - )} + }: PieSectorShapeProps) => + index === ACTIVE_INDEX ? ( + + ) : ( + + ) + } /> diff --git a/apps/v4/registry/new-york-v4/charts/chart-pie-interactive.tsx b/apps/v4/registry/new-york-v4/charts/chart-pie-interactive.tsx index d066d52adc..dfe17b688b 100644 --- a/apps/v4/registry/new-york-v4/charts/chart-pie-interactive.tsx +++ b/apps/v4/registry/new-york-v4/charts/chart-pie-interactive.tsx @@ -2,7 +2,10 @@ import * as React from "react" import { Label, Pie, PieChart, Sector } from "recharts" -import { type PieSectorDataItem } from "recharts/types/polar/Pie" +import type { + PieSectorDataItem, + PieSectorShapeProps, +} from "recharts/types/polar/Pie" import { Card, @@ -78,6 +81,26 @@ export function ChartPieInteractive() { ) const months = React.useMemo(() => desktopData.map((item) => item.month), []) + const renderPieShape = React.useCallback( + ({ index, outerRadius = 0, ...props }: PieSectorShapeProps) => { + if (index === activeIndex) { + return ( + + + + + ) + } + + return + }, + [activeIndex] + ) + return ( @@ -132,7 +155,6 @@ export function ChartPieInteractive() { } - defaultIndex={activeIndex} /> ( - - - - - )} + shape={renderPieShape} >
\n
\n )\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport default function Component() {\n return (\n
div]:relative [&>div]:flex [&>div]:h-[137px] [&>div]:w-[224px] [&>div]:items-center [&>div]:justify-center [&>div]:p-4\">\n
\n
\n Label\n
\n \n \n \n \n \n \n \n \n \n \n \n
\n
\n
\n Name\n
\n \n \n \n \n \n \n \n \n \n \n \n
\n
\n \n
\n
\n
\n Indicator\n
\n \n \n \n \n \n \n \n \n \n \n \n
\n
\n )\n}\n\nfunction TooltipDemo({\n indicator = \"dot\",\n label,\n payload,\n hideLabel,\n hideIndicator,\n className,\n}: {\n label: string\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n payload: {\n name: string\n value: number\n fill: string\n }[]\n nameKey?: string\n labelKey?: string\n} & React.ComponentProps<\"div\">) {\n const tooltipLabel = hideLabel ? null : (\n
{label}
\n )\n\n if (!payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload.map((item, index) => {\n const indicatorColor = item.fill\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n <>\n {!hideIndicator && (\n \n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n {item.name}\n
\n \n {item.value.toLocaleString()}\n \n
\n \n
\n )\n })}\n \n \n )\n}\n", "type": "registry:example" } ], diff --git a/apps/v4/registry/new-york-v4/charts/chart-pie-label-custom.tsx b/apps/v4/registry/new-york-v4/charts/chart-pie-label-custom.tsx index addae4e95b..465c78c2a8 100644 --- a/apps/v4/registry/new-york-v4/charts/chart-pie-label-custom.tsx +++ b/apps/v4/registry/new-york-v4/charts/chart-pie-label-custom.tsx @@ -83,7 +83,7 @@ export function ChartPieLabelCustom() { y={props.y} textAnchor={props.textAnchor} dominantBaseline={props.dominantBaseline} - fill="hsla(var(--foreground))" + fill="var(--foreground)" > {payload.visitors}
diff --git a/apps/v4/registry/new-york-v4/charts/chart-radar-radius.tsx b/apps/v4/registry/new-york-v4/charts/chart-radar-radius.tsx index e6b66e2c2e..61f29bb5b8 100644 --- a/apps/v4/registry/new-york-v4/charts/chart-radar-radius.tsx +++ b/apps/v4/registry/new-york-v4/charts/chart-radar-radius.tsx @@ -76,7 +76,7 @@ export function ChartRadarRadius() { diff --git a/apps/v4/registry/new-york-v4/examples/chart-tooltip-demo.tsx b/apps/v4/registry/new-york-v4/examples/chart-tooltip-demo.tsx index 5e3e0492c4..5b4a31ae66 100644 --- a/apps/v4/registry/new-york-v4/examples/chart-tooltip-demo.tsx +++ b/apps/v4/registry/new-york-v4/examples/chart-tooltip-demo.tsx @@ -34,8 +34,8 @@ export default function Component() { @@ -68,8 +68,8 @@ export default function Component() { label="Browser" hideLabel payload={[ - { name: "Chrome", value: 1286, fill: "hsl(var(--chart-3))" }, - { name: "Firefox", value: 1000, fill: "hsl(var(--chart-4))" }, + { name: "Chrome", value: 1286, fill: "var(--chart-3)" }, + { name: "Firefox", value: 1000, fill: "var(--chart-4)" }, ]} indicator="dashed" className="w-[8rem]" @@ -78,9 +78,7 @@ export default function Component() {
@@ -92,9 +90,7 @@ export default function Component() { @@ -177,7 +173,7 @@ function TooltipDemo({ {!hideIndicator && (
Date: Mon, 23 Mar 2026 15:58:15 +0400 Subject: [PATCH 32/88] fix: chart types (#10147) --- apps/v4/examples/base/ui-rtl/chart.tsx | 11 ++++++----- apps/v4/examples/base/ui/chart.tsx | 11 ++++++----- apps/v4/examples/radix/ui-rtl/chart.tsx | 11 ++++++----- apps/v4/examples/radix/ui/chart.tsx | 11 ++++++----- apps/v4/public/r/styles/base-lyra/chart.json | 2 +- apps/v4/public/r/styles/base-maia/chart.json | 2 +- apps/v4/public/r/styles/base-mira/chart.json | 2 +- apps/v4/public/r/styles/base-nova/chart.json | 2 +- apps/v4/public/r/styles/base-vega/chart.json | 2 +- .../r/styles/new-york-v4/chart-tooltip-demo.json | 2 +- apps/v4/public/r/styles/new-york-v4/chart.json | 2 +- apps/v4/public/r/styles/radix-lyra/chart.json | 2 +- apps/v4/public/r/styles/radix-maia/chart.json | 2 +- apps/v4/public/r/styles/radix-mira/chart.json | 2 +- apps/v4/public/r/styles/radix-nova/chart.json | 2 +- apps/v4/public/r/styles/radix-vega/chart.json | 2 +- apps/v4/registry/bases/base/ui/chart.tsx | 11 ++++++----- apps/v4/registry/bases/radix/ui/chart.tsx | 11 ++++++----- apps/v4/registry/new-york-v4/ui/chart.tsx | 11 ++++++----- 19 files changed, 54 insertions(+), 47 deletions(-) diff --git a/apps/v4/examples/base/ui-rtl/chart.tsx b/apps/v4/examples/base/ui-rtl/chart.tsx index 619bd25642..fe04cf5bdd 100644 --- a/apps/v4/examples/base/ui-rtl/chart.tsx +++ b/apps/v4/examples/base/ui-rtl/chart.tsx @@ -3,15 +3,13 @@ import * as React from "react" import { cn } from "@/examples/base/lib/utils" import * as RechartsPrimitive from "recharts" -import type { - NameType, - ValueType, -} from "recharts/types/component/DefaultTooltipContent" +import type { TooltipValueType } from "recharts" // Format: { THEME_NAME: CSS_SELECTOR } const THEMES = { light: "", dark: ".dark" } as const const INITIAL_DIMENSION = { width: 320, height: 200 } as const +type TooltipNameType = number | string export type ChartConfig = Record< string, @@ -139,7 +137,10 @@ function ChartTooltipContent({ nameKey?: string labelKey?: string } & Omit< - RechartsPrimitive.DefaultTooltipContentProps, + RechartsPrimitive.DefaultTooltipContentProps< + TooltipValueType, + TooltipNameType + >, "accessibilityLayer" >) { const { config } = useChart() diff --git a/apps/v4/examples/base/ui/chart.tsx b/apps/v4/examples/base/ui/chart.tsx index 619bd25642..fe04cf5bdd 100644 --- a/apps/v4/examples/base/ui/chart.tsx +++ b/apps/v4/examples/base/ui/chart.tsx @@ -3,15 +3,13 @@ import * as React from "react" import { cn } from "@/examples/base/lib/utils" import * as RechartsPrimitive from "recharts" -import type { - NameType, - ValueType, -} from "recharts/types/component/DefaultTooltipContent" +import type { TooltipValueType } from "recharts" // Format: { THEME_NAME: CSS_SELECTOR } const THEMES = { light: "", dark: ".dark" } as const const INITIAL_DIMENSION = { width: 320, height: 200 } as const +type TooltipNameType = number | string export type ChartConfig = Record< string, @@ -139,7 +137,10 @@ function ChartTooltipContent({ nameKey?: string labelKey?: string } & Omit< - RechartsPrimitive.DefaultTooltipContentProps, + RechartsPrimitive.DefaultTooltipContentProps< + TooltipValueType, + TooltipNameType + >, "accessibilityLayer" >) { const { config } = useChart() diff --git a/apps/v4/examples/radix/ui-rtl/chart.tsx b/apps/v4/examples/radix/ui-rtl/chart.tsx index 7dc49e6c0d..2ade038569 100644 --- a/apps/v4/examples/radix/ui-rtl/chart.tsx +++ b/apps/v4/examples/radix/ui-rtl/chart.tsx @@ -3,15 +3,13 @@ import * as React from "react" import { cn } from "@/examples/radix/lib/utils" import * as RechartsPrimitive from "recharts" -import type { - NameType, - ValueType, -} from "recharts/types/component/DefaultTooltipContent" +import type { TooltipValueType } from "recharts" // Format: { THEME_NAME: CSS_SELECTOR } const THEMES = { light: "", dark: ".dark" } as const const INITIAL_DIMENSION = { width: 320, height: 200 } as const +type TooltipNameType = number | string export type ChartConfig = Record< string, @@ -139,7 +137,10 @@ function ChartTooltipContent({ nameKey?: string labelKey?: string } & Omit< - RechartsPrimitive.DefaultTooltipContentProps, + RechartsPrimitive.DefaultTooltipContentProps< + TooltipValueType, + TooltipNameType + >, "accessibilityLayer" >) { const { config } = useChart() diff --git a/apps/v4/examples/radix/ui/chart.tsx b/apps/v4/examples/radix/ui/chart.tsx index 7dc49e6c0d..2ade038569 100644 --- a/apps/v4/examples/radix/ui/chart.tsx +++ b/apps/v4/examples/radix/ui/chart.tsx @@ -3,15 +3,13 @@ import * as React from "react" import { cn } from "@/examples/radix/lib/utils" import * as RechartsPrimitive from "recharts" -import type { - NameType, - ValueType, -} from "recharts/types/component/DefaultTooltipContent" +import type { TooltipValueType } from "recharts" // Format: { THEME_NAME: CSS_SELECTOR } const THEMES = { light: "", dark: ".dark" } as const const INITIAL_DIMENSION = { width: 320, height: 200 } as const +type TooltipNameType = number | string export type ChartConfig = Record< string, @@ -139,7 +137,10 @@ function ChartTooltipContent({ nameKey?: string labelKey?: string } & Omit< - RechartsPrimitive.DefaultTooltipContentProps, + RechartsPrimitive.DefaultTooltipContentProps< + TooltipValueType, + TooltipNameType + >, "accessibilityLayer" >) { const { config } = useChart() diff --git a/apps/v4/public/r/styles/base-lyra/chart.json b/apps/v4/public/r/styles/base-lyra/chart.json index f09acfbf26..aeddcf561b 100644 --- a/apps/v4/public/r/styles/base-lyra/chart.json +++ b/apps/v4/public/r/styles/base-lyra/chart.json @@ -10,7 +10,7 @@ "files": [ { "path": "registry/base-lyra/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-lyra/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n
\n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n
\n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type { TooltipValueType } from \"recharts\"\n\nimport { cn } from \"@/registry/base-lyra/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\ntype TooltipNameType = number | string\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps<\n TooltipValueType,\n TooltipNameType\n >,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/base-maia/chart.json b/apps/v4/public/r/styles/base-maia/chart.json index 214672112c..8bac800685 100644 --- a/apps/v4/public/r/styles/base-maia/chart.json +++ b/apps/v4/public/r/styles/base-maia/chart.json @@ -10,7 +10,7 @@ "files": [ { "path": "registry/base-maia/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-maia/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type { TooltipValueType } from \"recharts\"\n\nimport { cn } from \"@/registry/base-maia/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\ntype TooltipNameType = number | string\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps<\n TooltipValueType,\n TooltipNameType\n >,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/base-mira/chart.json b/apps/v4/public/r/styles/base-mira/chart.json index 7c29533a6b..25ba3376bd 100644 --- a/apps/v4/public/r/styles/base-mira/chart.json +++ b/apps/v4/public/r/styles/base-mira/chart.json @@ -10,7 +10,7 @@ "files": [ { "path": "registry/base-mira/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-mira/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type { TooltipValueType } from \"recharts\"\n\nimport { cn } from \"@/registry/base-mira/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\ntype TooltipNameType = number | string\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps<\n TooltipValueType,\n TooltipNameType\n >,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/base-nova/chart.json b/apps/v4/public/r/styles/base-nova/chart.json index 009a933bf1..6a00bc9310 100644 --- a/apps/v4/public/r/styles/base-nova/chart.json +++ b/apps/v4/public/r/styles/base-nova/chart.json @@ -10,7 +10,7 @@ "files": [ { "path": "registry/base-nova/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-nova/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type { TooltipValueType } from \"recharts\"\n\nimport { cn } from \"@/registry/base-nova/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\ntype TooltipNameType = number | string\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps<\n TooltipValueType,\n TooltipNameType\n >,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/base-vega/chart.json b/apps/v4/public/r/styles/base-vega/chart.json index ade4fd2abd..e33c17190f 100644 --- a/apps/v4/public/r/styles/base-vega/chart.json +++ b/apps/v4/public/r/styles/base-vega/chart.json @@ -10,7 +10,7 @@ "files": [ { "path": "registry/base-vega/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/base-vega/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type { TooltipValueType } from \"recharts\"\n\nimport { cn } from \"@/registry/base-vega/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\ntype TooltipNameType = number | string\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps<\n TooltipValueType,\n TooltipNameType\n >,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/new-york-v4/chart-tooltip-demo.json b/apps/v4/public/r/styles/new-york-v4/chart-tooltip-demo.json index aaf112b55b..56e44dbdf4 100644 --- a/apps/v4/public/r/styles/new-york-v4/chart-tooltip-demo.json +++ b/apps/v4/public/r/styles/new-york-v4/chart-tooltip-demo.json @@ -4,7 +4,7 @@ "files": [ { "path": "registry/new-york-v4/examples/chart-tooltip-demo.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport default function Component() {\n return (\n
div]:relative [&>div]:flex [&>div]:h-[137px] [&>div]:w-[224px] [&>div]:items-center [&>div]:justify-center [&>div]:p-4\">\n
\n
\n Label\n
\n \n \n \n \n \n \n \n \n \n \n \n
\n
\n
\n Name\n
\n \n \n \n \n \n \n \n \n \n \n \n
\n
\n \n
\n
\n
\n Indicator\n
\n \n \n \n \n \n \n \n \n \n \n \n
\n
\n )\n}\n\nfunction TooltipDemo({\n indicator = \"dot\",\n label,\n payload,\n hideLabel,\n hideIndicator,\n className,\n}: {\n label: string\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n payload: {\n name: string\n value: number\n fill: string\n }[]\n nameKey?: string\n labelKey?: string\n} & React.ComponentProps<\"div\">) {\n const tooltipLabel = hideLabel ? null : (\n
{label}
\n )\n\n if (!payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload.map((item, index) => {\n const indicatorColor = item.fill\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n <>\n {!hideIndicator && (\n \n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n {item.name}\n
\n \n {item.value.toLocaleString()}\n \n
\n \n \n )\n })}\n \n \n )\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport default function Component() {\n return (\n
div]:relative [&>div]:flex [&>div]:h-[137px] [&>div]:w-[224px] [&>div]:items-center [&>div]:justify-center [&>div]:p-4\">\n
\n
\n Label\n
\n \n \n \n \n \n \n \n \n \n \n \n
\n
\n
\n Name\n
\n \n \n \n \n \n \n \n \n \n \n \n
\n
\n \n
\n
\n
\n Indicator\n
\n \n \n \n \n \n \n \n \n \n \n \n
\n
\n )\n}\n\nfunction TooltipDemo({\n indicator = \"dot\",\n label,\n payload,\n hideLabel,\n hideIndicator,\n className,\n}: {\n label: string\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n payload: {\n name: string\n value: number\n fill: string\n }[]\n nameKey?: string\n labelKey?: string\n} & React.ComponentProps<\"div\">) {\n const tooltipLabel = hideLabel ? null : (\n
{label}
\n )\n\n if (!payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload.map((item, index) => {\n const indicatorColor = item.fill\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n <>\n {!hideIndicator && (\n \n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n {item.name}\n
\n \n {item.value.toLocaleString()}\n \n
\n \n \n )\n })}\n \n \n )\n}\n", "type": "registry:example" } ], diff --git a/apps/v4/public/r/styles/new-york-v4/chart.json b/apps/v4/public/r/styles/new-york-v4/chart.json index 2737da51cd..ad9612ff9c 100644 --- a/apps/v4/public/r/styles/new-york-v4/chart.json +++ b/apps/v4/public/r/styles/new-york-v4/chart.json @@ -11,7 +11,7 @@ "files": [ { "path": "registry/new-york-v4/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\n// Helper to extract item config from a payload.\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type { TooltipValueType } from \"recharts\"\n\nimport { cn } from \"@/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\ntype TooltipNameType = number | string\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps<\n TooltipValueType,\n TooltipNameType\n >,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\n// Helper to extract item config from a payload.\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-lyra/chart.json b/apps/v4/public/r/styles/radix-lyra/chart.json index 9006fc1057..77a70626e8 100644 --- a/apps/v4/public/r/styles/radix-lyra/chart.json +++ b/apps/v4/public/r/styles/radix-lyra/chart.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/radix-lyra/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-lyra/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type { TooltipValueType } from \"recharts\"\n\nimport { cn } from \"@/registry/radix-lyra/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\ntype TooltipNameType = number | string\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps<\n TooltipValueType,\n TooltipNameType\n >,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-maia/chart.json b/apps/v4/public/r/styles/radix-maia/chart.json index 9ded073db4..76d7b7a86e 100644 --- a/apps/v4/public/r/styles/radix-maia/chart.json +++ b/apps/v4/public/r/styles/radix-maia/chart.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/radix-maia/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-maia/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type { TooltipValueType } from \"recharts\"\n\nimport { cn } from \"@/registry/radix-maia/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\ntype TooltipNameType = number | string\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps<\n TooltipValueType,\n TooltipNameType\n >,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-mira/chart.json b/apps/v4/public/r/styles/radix-mira/chart.json index 119e86ccb9..d8db7d4397 100644 --- a/apps/v4/public/r/styles/radix-mira/chart.json +++ b/apps/v4/public/r/styles/radix-mira/chart.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/radix-mira/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-mira/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type { TooltipValueType } from \"recharts\"\n\nimport { cn } from \"@/registry/radix-mira/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\ntype TooltipNameType = number | string\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps<\n TooltipValueType,\n TooltipNameType\n >,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-nova/chart.json b/apps/v4/public/r/styles/radix-nova/chart.json index 0be1ab8988..11bb470eb5 100644 --- a/apps/v4/public/r/styles/radix-nova/chart.json +++ b/apps/v4/public/r/styles/radix-nova/chart.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/radix-nova/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-nova/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type { TooltipValueType } from \"recharts\"\n\nimport { cn } from \"@/registry/radix-nova/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\ntype TooltipNameType = number | string\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps<\n TooltipValueType,\n TooltipNameType\n >,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-vega/chart.json b/apps/v4/public/r/styles/radix-vega/chart.json index 44d5906a57..8f0811616d 100644 --- a/apps/v4/public/r/styles/radix-vega/chart.json +++ b/apps/v4/public/r/styles/radix-vega/chart.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/radix-vega/ui/chart.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n NameType,\n ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\n\nimport { cn } from \"@/registry/radix-vega/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type { TooltipValueType } from \"recharts\"\n\nimport { cn } from \"@/registry/radix-vega/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nconst INITIAL_DIMENSION = { width: 320, height: 200 } as const\ntype TooltipNameType = number | string\n\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n )\n>\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a \")\n }\n\n return context\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n initialDimension = INITIAL_DIMENSION,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n initialDimension?: {\n width: number\n height: number\n }\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id ?? uniqueId.replace(/:/g, \"\")}`\n\n return (\n \n \n \n \n {children}\n \n \n \n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme ?? config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps<\n TooltipValueType,\n TooltipNameType\n >,\n \"accessibilityLayer\"\n >) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey ?? item?.dataKey ?? item?.name ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? (config[label]?.label ?? label)\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.name ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color ?? item.payload?.fill ?? item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label ?? item.name}\n \n
\n {item.value != null && (\n \n {typeof item.value === \"number\"\n ? item.value.toLocaleString()\n : String(item.value)}\n \n )}\n
\n \n )}\n \n )\n })}\n \n \n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n hideIcon?: boolean\n nameKey?: string\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload\n .filter((item) => item.type !== \"none\")\n .map((item, index) => {\n const key = `${nameKey ?? item.dataKey ?? \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n}\n\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/registry/bases/base/ui/chart.tsx b/apps/v4/registry/bases/base/ui/chart.tsx index 6a5f115efa..86905c59c7 100644 --- a/apps/v4/registry/bases/base/ui/chart.tsx +++ b/apps/v4/registry/bases/base/ui/chart.tsx @@ -2,10 +2,7 @@ import * as React from "react" import * as RechartsPrimitive from "recharts" -import type { - NameType, - ValueType, -} from "recharts/types/component/DefaultTooltipContent" +import type { TooltipValueType } from "recharts" import { cn } from "@/registry/bases/base/lib/utils" @@ -13,6 +10,7 @@ import { cn } from "@/registry/bases/base/lib/utils" const THEMES = { light: "", dark: ".dark" } as const const INITIAL_DIMENSION = { width: 320, height: 200 } as const +type TooltipNameType = number | string export type ChartConfig = Record< string, @@ -140,7 +138,10 @@ function ChartTooltipContent({ nameKey?: string labelKey?: string } & Omit< - RechartsPrimitive.DefaultTooltipContentProps, + RechartsPrimitive.DefaultTooltipContentProps< + TooltipValueType, + TooltipNameType + >, "accessibilityLayer" >) { const { config } = useChart() diff --git a/apps/v4/registry/bases/radix/ui/chart.tsx b/apps/v4/registry/bases/radix/ui/chart.tsx index be02a47276..205bb3352b 100644 --- a/apps/v4/registry/bases/radix/ui/chart.tsx +++ b/apps/v4/registry/bases/radix/ui/chart.tsx @@ -2,10 +2,7 @@ import * as React from "react" import * as RechartsPrimitive from "recharts" -import type { - NameType, - ValueType, -} from "recharts/types/component/DefaultTooltipContent" +import type { TooltipValueType } from "recharts" import { cn } from "@/registry/bases/radix/lib/utils" @@ -13,6 +10,7 @@ import { cn } from "@/registry/bases/radix/lib/utils" const THEMES = { light: "", dark: ".dark" } as const const INITIAL_DIMENSION = { width: 320, height: 200 } as const +type TooltipNameType = number | string export type ChartConfig = Record< string, @@ -140,7 +138,10 @@ function ChartTooltipContent({ nameKey?: string labelKey?: string } & Omit< - RechartsPrimitive.DefaultTooltipContentProps, + RechartsPrimitive.DefaultTooltipContentProps< + TooltipValueType, + TooltipNameType + >, "accessibilityLayer" >) { const { config } = useChart() diff --git a/apps/v4/registry/new-york-v4/ui/chart.tsx b/apps/v4/registry/new-york-v4/ui/chart.tsx index 02f707c77e..011836a0fb 100644 --- a/apps/v4/registry/new-york-v4/ui/chart.tsx +++ b/apps/v4/registry/new-york-v4/ui/chart.tsx @@ -2,10 +2,7 @@ import * as React from "react" import * as RechartsPrimitive from "recharts" -import type { - NameType, - ValueType, -} from "recharts/types/component/DefaultTooltipContent" +import type { TooltipValueType } from "recharts" import { cn } from "@/lib/utils" @@ -13,6 +10,7 @@ import { cn } from "@/lib/utils" const THEMES = { light: "", dark: ".dark" } as const const INITIAL_DIMENSION = { width: 320, height: 200 } as const +type TooltipNameType = number | string export type ChartConfig = Record< string, @@ -140,7 +138,10 @@ function ChartTooltipContent({ nameKey?: string labelKey?: string } & Omit< - RechartsPrimitive.DefaultTooltipContentProps, + RechartsPrimitive.DefaultTooltipContentProps< + TooltipValueType, + TooltipNameType + >, "accessibilityLayer" >) { const { config } = useChart() From d3ab7fb00be5c8b4ab7671c639ea01a76466abb2 Mon Sep 17 00:00:00 2001 From: Ray <153027766+ramonclaudio@users.noreply.github.com> Date: Mon, 23 Mar 2026 12:08:25 -0400 Subject: [PATCH 33/88] feat(registry): add @ramonclaudio-coderabbit to directory (#9331) --- apps/v4/public/r/registries.json | 6 ++++++ apps/v4/registry/directory.json | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/apps/v4/public/r/registries.json b/apps/v4/public/r/registries.json index 1b40e63924..9b657c752d 100644 --- a/apps/v4/public/r/registries.json +++ b/apps/v4/public/r/registries.json @@ -155,6 +155,12 @@ "url": "https://clerk.com/r/{name}.json", "description": "The easiest way to add authentication and user management to your application. Purpose-built for React, Next.js, Remix, and The Modern Web." }, + { + "name": "@ramonclaudio-coderabbit", + "homepage": "https://ramonclaudio.com/registries/coderabbit", + "url": "https://coderabbit-shadcn-registry.vercel.app/r/{name}.json", + "description": "A framework-agnostic API client, pluggable storage adapters (LocalStorage, Convex, Supabase, PostgreSQL, MySQL), and React components for generating developer activity reports." + }, { "name": "@commercn", "homepage": "https://commercn.com", diff --git a/apps/v4/registry/directory.json b/apps/v4/registry/directory.json index 4176211294..d156169c30 100644 --- a/apps/v4/registry/directory.json +++ b/apps/v4/registry/directory.json @@ -181,6 +181,13 @@ "description": "The easiest way to add authentication and user management to your application. Purpose-built for React, Next.js, Remix, and The Modern Web.", "logo": "Clerk" }, + { + "name": "@ramonclaudio-coderabbit", + "homepage": "https://ramonclaudio.com/registries/coderabbit", + "url": "https://coderabbit-shadcn-registry.vercel.app/r/{name}.json", + "description": "A framework-agnostic API client, pluggable storage adapters (LocalStorage, Convex, Supabase, PostgreSQL, MySQL), and React components for generating developer activity reports.", + "logo": "" + }, { "name": "@commercn", "homepage": "https://commercn.com", From ef78384bfdb410c52b767f701471d25cbabbf2e9 Mon Sep 17 00:00:00 2001 From: shadcn Date: Tue, 24 Mar 2026 10:13:30 +0400 Subject: [PATCH 34/88] feat: replace "Add a block" button with "View Components" linking to /docs/components (#10154) https://claude.ai/code/session_01NnmghguJjhqSxuHE8PBLNi Co-authored-by: Claude --- apps/v4/app/(app)/blocks/layout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/v4/app/(app)/blocks/layout.tsx b/apps/v4/app/(app)/blocks/layout.tsx index 79bfcd280c..82edb4ab7c 100644 --- a/apps/v4/app/(app)/blocks/layout.tsx +++ b/apps/v4/app/(app)/blocks/layout.tsx @@ -56,7 +56,7 @@ export default function BlocksLayout({ Browse Blocks From d78ff8b85870665bdeb1cf76ca964fe131cecf49 Mon Sep 17 00:00:00 2001 From: shadcn Date: Tue, 24 Mar 2026 12:12:01 +0400 Subject: [PATCH 35/88] feat: update colors for popovers (#10155) * feat: update colors for popovers * fix: project form --- apps/v4/app/(create)/components/project-form.tsx | 6 +++--- apps/v4/examples/base/ui-rtl/alert-dialog.tsx | 2 +- apps/v4/examples/base/ui-rtl/dialog.tsx | 2 +- apps/v4/examples/base/ui-rtl/drawer.tsx | 2 +- apps/v4/examples/base/ui-rtl/sheet.tsx | 2 +- apps/v4/examples/base/ui/alert-dialog.tsx | 2 +- apps/v4/examples/base/ui/dialog.tsx | 2 +- apps/v4/examples/base/ui/drawer.tsx | 2 +- apps/v4/examples/base/ui/sheet.tsx | 2 +- apps/v4/examples/radix/ui-rtl/alert-dialog.tsx | 2 +- apps/v4/examples/radix/ui-rtl/dialog.tsx | 2 +- apps/v4/examples/radix/ui-rtl/drawer.tsx | 2 +- apps/v4/examples/radix/ui-rtl/sheet.tsx | 2 +- apps/v4/examples/radix/ui/alert-dialog.tsx | 2 +- apps/v4/examples/radix/ui/dialog.tsx | 2 +- apps/v4/examples/radix/ui/drawer.tsx | 2 +- apps/v4/examples/radix/ui/sheet.tsx | 2 +- apps/v4/public/r/styles/base-lyra/alert-dialog.json | 2 +- apps/v4/public/r/styles/base-lyra/dialog.json | 2 +- apps/v4/public/r/styles/base-lyra/drawer.json | 2 +- apps/v4/public/r/styles/base-lyra/sheet.json | 2 +- apps/v4/public/r/styles/base-maia/alert-dialog.json | 2 +- apps/v4/public/r/styles/base-maia/dialog.json | 2 +- apps/v4/public/r/styles/base-maia/drawer.json | 2 +- apps/v4/public/r/styles/base-maia/sheet.json | 2 +- apps/v4/public/r/styles/base-mira/alert-dialog.json | 2 +- apps/v4/public/r/styles/base-mira/dialog.json | 2 +- apps/v4/public/r/styles/base-mira/drawer.json | 2 +- apps/v4/public/r/styles/base-mira/sheet.json | 2 +- apps/v4/public/r/styles/base-nova/alert-dialog.json | 2 +- apps/v4/public/r/styles/base-nova/dialog.json | 2 +- apps/v4/public/r/styles/base-nova/drawer.json | 2 +- apps/v4/public/r/styles/base-nova/sheet.json | 2 +- apps/v4/public/r/styles/base-vega/alert-dialog.json | 2 +- apps/v4/public/r/styles/base-vega/dialog.json | 2 +- apps/v4/public/r/styles/base-vega/drawer.json | 2 +- apps/v4/public/r/styles/base-vega/sheet.json | 2 +- apps/v4/public/r/styles/radix-lyra/alert-dialog.json | 2 +- apps/v4/public/r/styles/radix-lyra/dialog.json | 2 +- apps/v4/public/r/styles/radix-lyra/drawer.json | 2 +- apps/v4/public/r/styles/radix-lyra/sheet.json | 2 +- apps/v4/public/r/styles/radix-maia/alert-dialog.json | 2 +- apps/v4/public/r/styles/radix-maia/dialog.json | 2 +- apps/v4/public/r/styles/radix-maia/drawer.json | 2 +- apps/v4/public/r/styles/radix-maia/sheet.json | 2 +- apps/v4/public/r/styles/radix-mira/alert-dialog.json | 2 +- apps/v4/public/r/styles/radix-mira/dialog.json | 2 +- apps/v4/public/r/styles/radix-mira/drawer.json | 2 +- apps/v4/public/r/styles/radix-mira/sheet.json | 2 +- apps/v4/public/r/styles/radix-nova/alert-dialog.json | 2 +- apps/v4/public/r/styles/radix-nova/dialog.json | 2 +- apps/v4/public/r/styles/radix-nova/drawer.json | 2 +- apps/v4/public/r/styles/radix-nova/sheet.json | 2 +- apps/v4/public/r/styles/radix-vega/alert-dialog.json | 2 +- apps/v4/public/r/styles/radix-vega/dialog.json | 2 +- apps/v4/public/r/styles/radix-vega/drawer.json | 2 +- apps/v4/public/r/styles/radix-vega/sheet.json | 2 +- apps/v4/registry/styles/style-lyra.css | 8 ++++---- apps/v4/registry/styles/style-maia.css | 8 ++++---- apps/v4/registry/styles/style-mira.css | 8 ++++---- apps/v4/registry/styles/style-nova.css | 8 ++++---- apps/v4/registry/styles/style-vega.css | 8 ++++---- 62 files changed, 79 insertions(+), 79 deletions(-) diff --git a/apps/v4/app/(create)/components/project-form.tsx b/apps/v4/app/(create)/components/project-form.tsx index eeda464ac6..5e879cb318 100644 --- a/apps/v4/app/(create)/components/project-form.tsx +++ b/apps/v4/app/(create)/components/project-form.tsx @@ -130,7 +130,7 @@ export function ProjectForm({ }> Create Project - + Create Project @@ -209,7 +209,7 @@ export function ProjectForm({ packageManager: value as PackageManager, })) }} - className="min-w-0 gap-0 overflow-hidden rounded-xl border-0 bg-neutral-950/20 ring-1 ring-neutral-950/80 dark:bg-neutral-900/50 dark:ring-neutral-700/50" + className="min-w-0 gap-0 overflow-hidden rounded-xl border-0 ring-1 ring-border" >
@@ -242,7 +242,7 @@ export function ProjectForm({ {Object.entries(commands).map(([key, cmd]) => { return ( -
+
{cmd} diff --git a/apps/v4/examples/base/ui-rtl/alert-dialog.tsx b/apps/v4/examples/base/ui-rtl/alert-dialog.tsx index e336e600fb..596d20ab87 100644 --- a/apps/v4/examples/base/ui-rtl/alert-dialog.tsx +++ b/apps/v4/examples/base/ui-rtl/alert-dialog.tsx @@ -51,7 +51,7 @@ function AlertDialogContent({ data-slot="alert-dialog-content" data-size={size} className={cn( - "group/alert-dialog-content fixed start-1/2 top-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-background p-4 ring-1 ring-foreground/10 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm rtl:translate-x-1/2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", + "group/alert-dialog-content fixed start-1/2 top-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm rtl:translate-x-1/2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className )} {...props} diff --git a/apps/v4/examples/base/ui-rtl/dialog.tsx b/apps/v4/examples/base/ui-rtl/dialog.tsx index 59e68b12cc..3a7040eac0 100644 --- a/apps/v4/examples/base/ui-rtl/dialog.tsx +++ b/apps/v4/examples/base/ui-rtl/dialog.tsx @@ -52,7 +52,7 @@ function DialogContent({ \n}\n\nfunction AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props) {\n return (\n \n )\n}\n\nfunction AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props) {\n return (\n \n )\n}\n\nfunction AlertDialogOverlay({\n className,\n ...props\n}: AlertDialogPrimitive.Backdrop.Props) {\n return (\n \n )\n}\n\nfunction AlertDialogContent({\n className,\n size = \"default\",\n ...props\n}: AlertDialogPrimitive.Popup.Props & {\n size?: \"default\" | \"sm\"\n}) {\n return (\n \n \n \n \n )\n}\n\nfunction AlertDialogHeader({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nfunction AlertDialogFooter({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nfunction AlertDialogMedia({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nfunction AlertDialogTitle({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction AlertDialogDescription({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction AlertDialogAction({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction AlertDialogCancel({\n className,\n variant = \"outline\",\n size = \"default\",\n ...props\n}: AlertDialogPrimitive.Close.Props &\n Pick, \"variant\" | \"size\">) {\n return (\n }\n {...props}\n />\n )\n}\n\nexport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogMedia,\n AlertDialogOverlay,\n AlertDialogPortal,\n AlertDialogTitle,\n AlertDialogTrigger,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { AlertDialog as AlertDialogPrimitive } from \"@base-ui/react/alert-dialog\"\n\nimport { cn } from \"@/registry/base-lyra/lib/utils\"\nimport { Button } from \"@/registry/base-lyra/ui/button\"\n\nfunction AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props) {\n return \n}\n\nfunction AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props) {\n return (\n \n )\n}\n\nfunction AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props) {\n return (\n \n )\n}\n\nfunction AlertDialogOverlay({\n className,\n ...props\n}: AlertDialogPrimitive.Backdrop.Props) {\n return (\n \n )\n}\n\nfunction AlertDialogContent({\n className,\n size = \"default\",\n ...props\n}: AlertDialogPrimitive.Popup.Props & {\n size?: \"default\" | \"sm\"\n}) {\n return (\n \n \n \n \n )\n}\n\nfunction AlertDialogHeader({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nfunction AlertDialogFooter({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nfunction AlertDialogMedia({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nfunction AlertDialogTitle({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction AlertDialogDescription({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction AlertDialogAction({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction AlertDialogCancel({\n className,\n variant = \"outline\",\n size = \"default\",\n ...props\n}: AlertDialogPrimitive.Close.Props &\n Pick, \"variant\" | \"size\">) {\n return (\n }\n {...props}\n />\n )\n}\n\nexport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogMedia,\n AlertDialogOverlay,\n AlertDialogPortal,\n AlertDialogTitle,\n AlertDialogTrigger,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/base-lyra/dialog.json b/apps/v4/public/r/styles/base-lyra/dialog.json index 434229995a..15b7c44726 100644 --- a/apps/v4/public/r/styles/base-lyra/dialog.json +++ b/apps/v4/public/r/styles/base-lyra/dialog.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/base-lyra/ui/dialog.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Dialog as DialogPrimitive } from \"@base-ui/react/dialog\"\n\nimport { cn } from \"@/registry/base-lyra/lib/utils\"\nimport { Button } from \"@/registry/base-lyra/ui/button\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Dialog({ ...props }: DialogPrimitive.Root.Props) {\n return \n}\n\nfunction DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props) {\n return \n}\n\nfunction DialogPortal({ ...props }: DialogPrimitive.Portal.Props) {\n return \n}\n\nfunction DialogClose({ ...props }: DialogPrimitive.Close.Props) {\n return \n}\n\nfunction DialogOverlay({\n className,\n ...props\n}: DialogPrimitive.Backdrop.Props) {\n return (\n \n )\n}\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n ...props\n}: DialogPrimitive.Popup.Props & {\n showCloseButton?: boolean\n}) {\n return (\n \n \n \n {children}\n {showCloseButton && (\n \n }\n >\n \n Close\n \n )}\n \n \n )\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nfunction DialogFooter({\n className,\n showCloseButton = false,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n showCloseButton?: boolean\n}) {\n return (\n \n {children}\n {showCloseButton && (\n }>\n Close\n \n )}\n
\n )\n}\n\nfunction DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {\n return (\n \n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: DialogPrimitive.Description.Props) {\n return (\n \n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Dialog as DialogPrimitive } from \"@base-ui/react/dialog\"\n\nimport { cn } from \"@/registry/base-lyra/lib/utils\"\nimport { Button } from \"@/registry/base-lyra/ui/button\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Dialog({ ...props }: DialogPrimitive.Root.Props) {\n return \n}\n\nfunction DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props) {\n return \n}\n\nfunction DialogPortal({ ...props }: DialogPrimitive.Portal.Props) {\n return \n}\n\nfunction DialogClose({ ...props }: DialogPrimitive.Close.Props) {\n return \n}\n\nfunction DialogOverlay({\n className,\n ...props\n}: DialogPrimitive.Backdrop.Props) {\n return (\n \n )\n}\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n ...props\n}: DialogPrimitive.Popup.Props & {\n showCloseButton?: boolean\n}) {\n return (\n \n \n \n {children}\n {showCloseButton && (\n \n }\n >\n \n Close\n \n )}\n \n \n )\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nfunction DialogFooter({\n className,\n showCloseButton = false,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n showCloseButton?: boolean\n}) {\n return (\n \n {children}\n {showCloseButton && (\n }>\n Close\n \n )}\n
\n )\n}\n\nfunction DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {\n return (\n \n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: DialogPrimitive.Description.Props) {\n return (\n \n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/base-lyra/drawer.json b/apps/v4/public/r/styles/base-lyra/drawer.json index a750229c53..a763c431dd 100644 --- a/apps/v4/public/r/styles/base-lyra/drawer.json +++ b/apps/v4/public/r/styles/base-lyra/drawer.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/base-lyra/ui/drawer.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Drawer as DrawerPrimitive } from \"vaul\"\n\nimport { cn } from \"@/registry/base-lyra/lib/utils\"\n\nfunction Drawer({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerTrigger({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerPortal({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerClose({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction DrawerContent({\n className,\n children,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n )\n}\n\nfunction DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {\n return (\n \n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: DialogPrimitive.Description.Props) {\n return (\n \n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/base-maia/drawer.json b/apps/v4/public/r/styles/base-maia/drawer.json index 169c9bcabd..104a4ab1e1 100644 --- a/apps/v4/public/r/styles/base-maia/drawer.json +++ b/apps/v4/public/r/styles/base-maia/drawer.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/base-maia/ui/drawer.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Drawer as DrawerPrimitive } from \"vaul\"\n\nimport { cn } from \"@/registry/base-maia/lib/utils\"\n\nfunction Drawer({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerTrigger({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerPortal({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerClose({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction DrawerContent({\n className,\n children,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n )\n}\n\nfunction DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {\n return (\n \n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: DialogPrimitive.Description.Props) {\n return (\n \n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/base-mira/drawer.json b/apps/v4/public/r/styles/base-mira/drawer.json index f943530598..30574dd89e 100644 --- a/apps/v4/public/r/styles/base-mira/drawer.json +++ b/apps/v4/public/r/styles/base-mira/drawer.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/base-mira/ui/drawer.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Drawer as DrawerPrimitive } from \"vaul\"\n\nimport { cn } from \"@/registry/base-mira/lib/utils\"\n\nfunction Drawer({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerTrigger({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerPortal({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerClose({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction DrawerContent({\n className,\n children,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n )\n}\n\nfunction DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {\n return (\n \n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: DialogPrimitive.Description.Props) {\n return (\n \n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/base-nova/drawer.json b/apps/v4/public/r/styles/base-nova/drawer.json index 6eb425859c..8f49c1c605 100644 --- a/apps/v4/public/r/styles/base-nova/drawer.json +++ b/apps/v4/public/r/styles/base-nova/drawer.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/base-nova/ui/drawer.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Drawer as DrawerPrimitive } from \"vaul\"\n\nimport { cn } from \"@/registry/base-nova/lib/utils\"\n\nfunction Drawer({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerTrigger({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerPortal({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerClose({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction DrawerContent({\n className,\n children,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n )\n}\n\nfunction DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {\n return (\n \n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: DialogPrimitive.Description.Props) {\n return (\n \n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/base-vega/drawer.json b/apps/v4/public/r/styles/base-vega/drawer.json index 981a6a3788..992b1f39a5 100644 --- a/apps/v4/public/r/styles/base-vega/drawer.json +++ b/apps/v4/public/r/styles/base-vega/drawer.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/base-vega/ui/drawer.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Drawer as DrawerPrimitive } from \"vaul\"\n\nimport { cn } from \"@/registry/base-vega/lib/utils\"\n\nfunction Drawer({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerTrigger({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerPortal({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerClose({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction DrawerContent({\n className,\n children,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n )\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-lyra/drawer.json b/apps/v4/public/r/styles/radix-lyra/drawer.json index 4b6069f39f..ea01dbc85f 100644 --- a/apps/v4/public/r/styles/radix-lyra/drawer.json +++ b/apps/v4/public/r/styles/radix-lyra/drawer.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/radix-lyra/ui/drawer.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Drawer as DrawerPrimitive } from \"vaul\"\n\nimport { cn } from \"@/registry/radix-lyra/lib/utils\"\n\nfunction Drawer({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerTrigger({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerPortal({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerClose({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction DrawerContent({\n className,\n children,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n )\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-maia/drawer.json b/apps/v4/public/r/styles/radix-maia/drawer.json index a4fc225301..37a6225a87 100644 --- a/apps/v4/public/r/styles/radix-maia/drawer.json +++ b/apps/v4/public/r/styles/radix-maia/drawer.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/radix-maia/ui/drawer.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Drawer as DrawerPrimitive } from \"vaul\"\n\nimport { cn } from \"@/registry/radix-maia/lib/utils\"\n\nfunction Drawer({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerTrigger({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerPortal({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerClose({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction DrawerContent({\n className,\n children,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n )\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-mira/drawer.json b/apps/v4/public/r/styles/radix-mira/drawer.json index 531b93c081..5606388b50 100644 --- a/apps/v4/public/r/styles/radix-mira/drawer.json +++ b/apps/v4/public/r/styles/radix-mira/drawer.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/radix-mira/ui/drawer.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Drawer as DrawerPrimitive } from \"vaul\"\n\nimport { cn } from \"@/registry/radix-mira/lib/utils\"\n\nfunction Drawer({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerTrigger({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerPortal({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerClose({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction DrawerContent({\n className,\n children,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n )\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-nova/drawer.json b/apps/v4/public/r/styles/radix-nova/drawer.json index 8630037fd0..ce479167a1 100644 --- a/apps/v4/public/r/styles/radix-nova/drawer.json +++ b/apps/v4/public/r/styles/radix-nova/drawer.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/radix-nova/ui/drawer.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Drawer as DrawerPrimitive } from \"vaul\"\n\nimport { cn } from \"@/registry/radix-nova/lib/utils\"\n\nfunction Drawer({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerTrigger({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerPortal({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerClose({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction DrawerContent({\n className,\n children,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n )\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n", "type": "registry:ui" } ], diff --git a/apps/v4/public/r/styles/radix-vega/drawer.json b/apps/v4/public/r/styles/radix-vega/drawer.json index 3626a4dd9a..564a422225 100644 --- a/apps/v4/public/r/styles/radix-vega/drawer.json +++ b/apps/v4/public/r/styles/radix-vega/drawer.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/radix-vega/ui/drawer.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Drawer as DrawerPrimitive } from \"vaul\"\n\nimport { cn } from \"@/registry/radix-vega/lib/utils\"\n\nfunction Drawer({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerTrigger({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerPortal({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerClose({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction DrawerContent({\n className,\n children,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n