create-lumen 2.0.0-alpha.1 → 2.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -12
- package/bin/cli.js +3 -1
- package/package.json +3 -3
- package/schema/fixtures/v2/invalid/shadcn-without-tailwind.json +1 -1
- package/schema/fixtures/v2/valid/react-vite-type-based.json +1 -1
- package/schema/lumen.config.v2.json +0 -1
- package/src/cli-args.js +169 -7
- package/src/configure.js +12 -4
- package/src/css.js +14 -30
- package/src/dependencies.js +36 -20
- package/src/engine/capabilities.js +195 -4
- package/src/engine/composition.js +736 -0
- package/src/engine/index.js +1 -0
- package/src/engine/providers/base-provider.js +4 -4
- package/src/injector.js +294 -446
- package/src/main.js +38 -16
- package/src/manifest/emit.js +1 -1
- package/src/manifest/schema.js +1 -1
- package/src/prompts.js +581 -238
- package/src/readme.js +23 -2
- package/src/scaffold.js +17 -0
- package/templates/architectures/hybrid/main.jsx +10 -0
- package/templates/architectures/hybrid/main.tsx +10 -0
- package/templates/architectures/hybrid/src/App.jsx +20 -0
- package/templates/architectures/hybrid/src/App.tsx +20 -0
- package/templates/architectures/hybrid/src/shared/components/ui/Button.jsx +31 -0
- package/templates/architectures/hybrid/src/shared/components/ui/Button.tsx +36 -0
- package/templates/architectures/hybrid/src/shared/components/ui/index.js +1 -0
- package/templates/architectures/hybrid/src/shared/components/ui/index.ts +1 -0
- package/templates/architectures/hybrid/src/shared/hooks/useLocalStorage.jsx +28 -0
- package/templates/architectures/hybrid/src/shared/hooks/useLocalStorage.ts +28 -0
- package/templates/architectures/hybrid/src/shared/layouts/.gitkeep +0 -0
- package/templates/architectures/hybrid/src/shared/stores/.gitkeep +0 -0
- package/templates/architectures/hybrid/src/shared/styles/.gitkeep +0 -0
- package/templates/architectures/hybrid/src/shared/types/index.js +20 -0
- package/templates/architectures/hybrid/src/shared/types/index.ts +16 -0
- package/templates/architectures/hybrid/src/shared/utils/cn.jsx +3 -0
- package/templates/architectures/hybrid/src/shared/utils/cn.ts +5 -0
- package/templates/architectures/none/main.jsx +10 -0
- package/templates/architectures/none/main.tsx +10 -0
- package/templates/architectures/none/src/App.jsx +15 -0
- package/templates/architectures/none/src/App.tsx +15 -0
- package/templates/architectures/none/src/styles/.gitkeep +1 -0
- package/templates/architectures/none/src/types/index.js +20 -0
- package/templates/architectures/none/src/types/index.ts +16 -0
- package/templates/bases/next/app-router/js/.provenance.json +19 -0
- package/templates/bases/next/app-router/js/README.md +36 -0
- package/templates/bases/next/app-router/js/jsconfig.json +7 -0
- package/templates/bases/next/app-router/js/next.config.mjs +6 -0
- package/templates/bases/next/app-router/js/package.json +15 -0
- package/templates/bases/next/app-router/js/public/file.svg +1 -0
- package/templates/bases/next/app-router/js/public/globe.svg +1 -0
- package/templates/bases/next/app-router/js/public/next.svg +1 -0
- package/templates/bases/next/app-router/js/public/vercel.svg +1 -0
- package/templates/bases/next/app-router/js/public/window.svg +1 -0
- package/templates/bases/next/app-router/js/src/app/api/hello/route.js +5 -0
- package/templates/bases/next/app-router/js/src/app/blog/[slug]/page.js +33 -0
- package/templates/bases/next/app-router/js/src/app/favicon.ico +0 -0
- package/templates/bases/next/app-router/js/src/app/globals.css +49 -0
- package/templates/bases/next/app-router/js/src/app/layout.js +25 -0
- package/templates/bases/next/app-router/js/src/app/loading.js +15 -0
- package/templates/bases/next/app-router/js/src/app/not-found.js +29 -0
- package/templates/bases/next/app-router/js/src/app/page.js +69 -0
- package/templates/bases/next/app-router/js/src/app/page.module.css +150 -0
- package/templates/bases/next/app-router/ts/.provenance.json +19 -0
- package/templates/bases/next/app-router/ts/README.md +36 -0
- package/templates/bases/next/app-router/ts/next.config.ts +7 -0
- package/templates/bases/next/app-router/ts/package.json +21 -0
- package/templates/bases/next/app-router/ts/public/file.svg +1 -0
- package/templates/bases/next/app-router/ts/public/globe.svg +1 -0
- package/templates/bases/next/app-router/ts/public/next.svg +1 -0
- package/templates/bases/next/app-router/ts/public/vercel.svg +1 -0
- package/templates/bases/next/app-router/ts/public/window.svg +1 -0
- package/templates/bases/next/app-router/ts/src/app/api/hello/route.ts +5 -0
- package/templates/bases/next/app-router/ts/src/app/blog/[slug]/page.tsx +38 -0
- package/templates/bases/next/app-router/ts/src/app/favicon.ico +0 -0
- package/templates/bases/next/app-router/ts/src/app/globals.css +49 -0
- package/templates/bases/next/app-router/ts/src/app/layout.tsx +30 -0
- package/templates/bases/next/app-router/ts/src/app/loading.tsx +15 -0
- package/templates/bases/next/app-router/ts/src/app/not-found.tsx +29 -0
- package/templates/bases/next/app-router/ts/src/app/page.module.css +150 -0
- package/templates/bases/next/app-router/ts/src/app/page.tsx +69 -0
- package/templates/bases/next/app-router/ts/tsconfig.json +34 -0
- package/templates/bases/next/pages-router/js/.provenance.json +19 -0
- package/templates/bases/next/pages-router/js/README.md +40 -0
- package/templates/bases/next/pages-router/js/jsconfig.json +7 -0
- package/templates/bases/next/pages-router/js/next.config.mjs +7 -0
- package/templates/bases/next/pages-router/js/package.json +15 -0
- package/templates/bases/next/pages-router/js/public/favicon.ico +0 -0
- package/templates/bases/next/pages-router/js/public/file.svg +1 -0
- package/templates/bases/next/pages-router/js/public/globe.svg +1 -0
- package/templates/bases/next/pages-router/js/public/next.svg +1 -0
- package/templates/bases/next/pages-router/js/public/vercel.svg +1 -0
- package/templates/bases/next/pages-router/js/public/window.svg +1 -0
- package/templates/bases/next/pages-router/js/src/pages/404.js +35 -0
- package/templates/bases/next/pages-router/js/src/pages/500.js +35 -0
- package/templates/bases/next/pages-router/js/src/pages/_app.js +20 -0
- package/templates/bases/next/pages-router/js/src/pages/_document.js +15 -0
- package/templates/bases/next/pages-router/js/src/pages/api/hello.js +5 -0
- package/templates/bases/next/pages-router/js/src/pages/blog/[slug].js +41 -0
- package/templates/bases/next/pages-router/js/src/pages/index.js +77 -0
- package/templates/bases/next/pages-router/js/src/styles/Home.module.css +149 -0
- package/templates/bases/next/pages-router/js/src/styles/globals.css +42 -0
- package/templates/bases/next/pages-router/ts/.provenance.json +19 -0
- package/templates/bases/next/pages-router/ts/README.md +40 -0
- package/templates/bases/next/pages-router/ts/next.config.ts +8 -0
- package/templates/bases/next/pages-router/ts/package.json +21 -0
- package/templates/bases/next/pages-router/ts/public/favicon.ico +0 -0
- package/templates/bases/next/pages-router/ts/public/file.svg +1 -0
- package/templates/bases/next/pages-router/ts/public/globe.svg +1 -0
- package/templates/bases/next/pages-router/ts/public/next.svg +1 -0
- package/templates/bases/next/pages-router/ts/public/vercel.svg +1 -0
- package/templates/bases/next/pages-router/ts/public/window.svg +1 -0
- package/templates/bases/next/pages-router/ts/src/pages/404.tsx +35 -0
- package/templates/bases/next/pages-router/ts/src/pages/500.tsx +35 -0
- package/templates/bases/next/pages-router/ts/src/pages/_app.tsx +21 -0
- package/templates/bases/next/pages-router/ts/src/pages/_document.tsx +15 -0
- package/templates/bases/next/pages-router/ts/src/pages/api/hello.ts +13 -0
- package/templates/bases/next/pages-router/ts/src/pages/blog/[slug].tsx +46 -0
- package/templates/bases/next/pages-router/ts/src/pages/index.tsx +77 -0
- package/templates/bases/next/pages-router/ts/src/styles/Home.module.css +149 -0
- package/templates/bases/next/pages-router/ts/src/styles/globals.css +42 -0
- package/templates/bases/next/pages-router/ts/tsconfig.json +29 -0
- package/templates/conditional/linting/biome/biome.json +31 -0
- package/templates/conditional/next/config/cloudflare/next.config.mjs +6 -0
- package/templates/conditional/next/config/cloudflare/next.config.ts +7 -0
- package/templates/conditional/next/config/node/next.config.mjs +6 -0
- package/templates/conditional/next/config/node/next.config.ts +7 -0
- package/templates/conditional/next/config/static/next.config.mjs +6 -0
- package/templates/conditional/next/config/static/next.config.ts +7 -0
- package/templates/conditional/next/config/turbopack/next.config.mjs +7 -0
- package/templates/conditional/next/config/turbopack/next.config.ts +8 -0
- package/templates/conditional/next/config/vercel/next.config.mjs +6 -0
- package/templates/conditional/next/config/vercel/next.config.ts +7 -0
- package/templates/conditional/next/config/webpack/next.config.mjs +9 -0
- package/templates/conditional/next/config/webpack/next.config.ts +10 -0
- package/templates/conditional/next/font/BUILD_SIZE_NOTE.md +17 -0
- package/templates/conditional/next/font/app-router/src/app/layout.js +25 -0
- package/templates/conditional/next/font/app-router/src/app/layout.tsx +30 -0
- package/templates/conditional/next/font/pages-router/src/pages/_app.js +20 -0
- package/templates/conditional/next/font/pages-router/src/pages/_app.tsx +21 -0
- package/templates/conditional/next/font/pages-router/src/pages/_document.js +18 -0
- package/templates/conditional/next/font/pages-router/src/pages/_document.tsx +18 -0
- package/templates/conditional/next/font/src/app/layout.js +25 -0
- package/templates/conditional/next/font/src/app/layout.tsx +30 -0
- package/templates/conditional/next/font/src/lib/fonts.js +11 -0
- package/templates/conditional/next/font/src/lib/fonts.ts +11 -0
- package/templates/conditional/next/font/src/pages/_app.js +20 -0
- package/templates/conditional/next/font/src/pages/_app.tsx +21 -0
- package/templates/conditional/next/font/src/pages/_document.js +18 -0
- package/templates/conditional/next/font/src/pages/_document.tsx +18 -0
- package/templates/conditional/next/image/BUILD_SIZE_NOTE.md +15 -0
- package/templates/conditional/next/image/app-router/src/components/ImageExample.jsx +34 -0
- package/templates/conditional/next/image/app-router/src/components/ImageExample.tsx +44 -0
- package/templates/conditional/next/image/pages-router/src/components/ImageExample.jsx +34 -0
- package/templates/conditional/next/image/pages-router/src/components/ImageExample.tsx +44 -0
- package/templates/conditional/next/image/src/components/ImageExample.jsx +44 -0
- package/templates/conditional/next/image/src/components/ImageExample.tsx +54 -0
- package/templates/conditional/next/image/src/components/image/index.js +1 -0
- package/templates/conditional/next/image/src/components/image/index.ts +2 -0
- package/templates/conditional/next/server-components/README.md +13 -0
- package/templates/conditional/next/server-components/eslint.config.mjs +47 -0
- package/templates/conditional/next/server-components/rules/no-server-imports-in-client.js +89 -0
- package/templates/conditional/next/server-components/rules/no-server-imports-in-client.mjs +88 -0
- package/templates/conditional/next/server-components/src/components/boundaries/ClientCounter.jsx +48 -0
- package/templates/conditional/next/server-components/src/components/boundaries/ClientCounter.tsx +53 -0
- package/templates/conditional/next/server-components/src/components/boundaries/ServerCard.jsx +41 -0
- package/templates/conditional/next/server-components/src/components/boundaries/ServerCard.tsx +46 -0
- package/templates/conditional/next/server-components/src/components/boundaries/index.js +2 -0
- package/templates/conditional/next/server-components/src/components/boundaries/index.ts +4 -0
- package/templates/conditional/testing/jest/hybrid/src/__tests__/App.test.jsx +11 -0
- package/templates/conditional/testing/jest/hybrid/src/__tests__/App.test.tsx +11 -0
- package/templates/conditional/testing/jest/none/src/__tests__/App.test.jsx +11 -0
- package/templates/conditional/testing/jest/none/src/__tests__/App.test.tsx +11 -0
- package/templates/conditional/testing/vitest/hybrid/src/__tests__/App.test.jsx +10 -0
- package/templates/conditional/testing/vitest/hybrid/src/__tests__/App.test.tsx +10 -0
- package/templates/conditional/testing/vitest/none/src/__tests__/App.test.jsx +10 -0
- package/templates/conditional/testing/vitest/none/src/__tests__/App.test.tsx +10 -0
- package/templates/css/tailwind/src/globals.css +10 -0
- package/templates/css/tailwind/src/themes.css +86 -4
- package/templates/ui/shadcn/lib/utils.js +6 -0
- package/templates/ui/shadcn/lib/utils.ts +6 -0
- package/templates/ui/shadcn/primitives/Button.jsx +48 -0
- package/templates/ui/shadcn/primitives/Button.tsx +59 -0
- package/templates/ui/shadcn/primitives/Card.jsx +55 -0
- package/templates/ui/shadcn/primitives/Card.tsx +73 -0
- package/templates/ui/shadcn/primitives/index.js +9 -0
- package/templates/ui/shadcn/primitives/index.ts +9 -0
- package/templates/css/bootstrap/src/themes.css +0 -14
- /package/templates/{css/bootstrap/src/globals.css → architectures/hybrid/src/features/.gitkeep} +0 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { ClientCounter } from "./ClientCounter";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Server Component example for RSC boundary.
|
|
6
|
+
* Renders on the server by default (zero client-side bundle impact).
|
|
7
|
+
* Demonstrates composing a Client Component across the RSC boundary.
|
|
8
|
+
* Compatible with both Next.js App Router and Pages Router.
|
|
9
|
+
*/
|
|
10
|
+
export function ServerCard({
|
|
11
|
+
title = "Server Component Shell",
|
|
12
|
+
serverMessage = "Rendered on the server with zero client bundle overhead for this card frame.",
|
|
13
|
+
}) {
|
|
14
|
+
return (
|
|
15
|
+
<div className="server-boundary p-6 rounded-xl border border-emerald-500/20 bg-emerald-500/5 my-4">
|
|
16
|
+
<div className="flex items-center justify-between mb-3">
|
|
17
|
+
<span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-semibold bg-emerald-100 text-emerald-800 dark:bg-emerald-900/60 dark:text-emerald-300">
|
|
18
|
+
Server Component (Default RSC)
|
|
19
|
+
</span>
|
|
20
|
+
</div>
|
|
21
|
+
<h3 className="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-2">
|
|
22
|
+
{title}
|
|
23
|
+
</h3>
|
|
24
|
+
<p className="text-sm text-gray-600 dark:text-gray-300 mb-4">
|
|
25
|
+
{serverMessage}
|
|
26
|
+
</p>
|
|
27
|
+
<div className="p-4 rounded-lg border border-dashed border-emerald-500/30 bg-white/40 dark:bg-black/20">
|
|
28
|
+
<p className="text-xs font-semibold text-emerald-700 dark:text-emerald-400 uppercase tracking-wider mb-2">
|
|
29
|
+
Server / Client Boundary
|
|
30
|
+
</p>
|
|
31
|
+
<ClientCounter initialCount={0}>
|
|
32
|
+
<p className="text-xs text-gray-500 dark:text-gray-400 italic">
|
|
33
|
+
Server-rendered child passed through client component boundary.
|
|
34
|
+
</p>
|
|
35
|
+
</ClientCounter>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default ServerCard;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { ClientCounter } from "./ClientCounter";
|
|
3
|
+
|
|
4
|
+
export interface ServerCardProps {
|
|
5
|
+
title?: string;
|
|
6
|
+
serverMessage?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Server Component example for RSC boundary.
|
|
11
|
+
* Renders on the server by default (zero client-side bundle impact).
|
|
12
|
+
* Demonstrates composing a Client Component across the RSC boundary.
|
|
13
|
+
* Compatible with both Next.js App Router and Pages Router.
|
|
14
|
+
*/
|
|
15
|
+
export function ServerCard({
|
|
16
|
+
title = "Server Component Shell",
|
|
17
|
+
serverMessage = "Rendered on the server with zero client bundle overhead for this card frame.",
|
|
18
|
+
}: ServerCardProps) {
|
|
19
|
+
return (
|
|
20
|
+
<div className="server-boundary p-6 rounded-xl border border-emerald-500/20 bg-emerald-500/5 my-4">
|
|
21
|
+
<div className="flex items-center justify-between mb-3">
|
|
22
|
+
<span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-semibold bg-emerald-100 text-emerald-800 dark:bg-emerald-900/60 dark:text-emerald-300">
|
|
23
|
+
Server Component (Default RSC)
|
|
24
|
+
</span>
|
|
25
|
+
</div>
|
|
26
|
+
<h3 className="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-2">
|
|
27
|
+
{title}
|
|
28
|
+
</h3>
|
|
29
|
+
<p className="text-sm text-gray-600 dark:text-gray-300 mb-4">
|
|
30
|
+
{serverMessage}
|
|
31
|
+
</p>
|
|
32
|
+
<div className="p-4 rounded-lg border border-dashed border-emerald-500/30 bg-white/40 dark:bg-black/20">
|
|
33
|
+
<p className="text-xs font-semibold text-emerald-700 dark:text-emerald-400 uppercase tracking-wider mb-2">
|
|
34
|
+
Server / Client Boundary
|
|
35
|
+
</p>
|
|
36
|
+
<ClientCounter initialCount={0}>
|
|
37
|
+
<p className="text-xs text-gray-500 dark:text-gray-400 italic">
|
|
38
|
+
Server-rendered child passed through client component boundary.
|
|
39
|
+
</p>
|
|
40
|
+
</ClientCounter>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default ServerCard;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { describe, it, expect } from "@jest/globals";
|
|
2
|
+
import { render, screen } from "@testing-library/react";
|
|
3
|
+
import "@testing-library/jest-dom/jest-globals";
|
|
4
|
+
import App from "@/App";
|
|
5
|
+
|
|
6
|
+
describe("App", () => {
|
|
7
|
+
it("renders without crashing", () => {
|
|
8
|
+
render(<App />);
|
|
9
|
+
expect(screen.getByText(/Welcome/i)).toBeInTheDocument();
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { describe, it, expect } from "@jest/globals";
|
|
2
|
+
import { render, screen } from "@testing-library/react";
|
|
3
|
+
import "@testing-library/jest-dom/jest-globals";
|
|
4
|
+
import App from "@/App";
|
|
5
|
+
|
|
6
|
+
describe("App", () => {
|
|
7
|
+
it("renders without crashing", () => {
|
|
8
|
+
render(<App />);
|
|
9
|
+
expect(screen.getByText(/Welcome/i)).toBeInTheDocument();
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { describe, it, expect } from "@jest/globals";
|
|
2
|
+
import { render, screen } from "@testing-library/react";
|
|
3
|
+
import "@testing-library/jest-dom/jest-globals";
|
|
4
|
+
import App from "@/App";
|
|
5
|
+
|
|
6
|
+
describe("App", () => {
|
|
7
|
+
it("renders without crashing", () => {
|
|
8
|
+
render(<App />);
|
|
9
|
+
expect(screen.getByText(/Welcome/i)).toBeInTheDocument();
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { describe, it, expect } from "@jest/globals";
|
|
2
|
+
import { render, screen } from "@testing-library/react";
|
|
3
|
+
import "@testing-library/jest-dom/jest-globals";
|
|
4
|
+
import App from "@/App";
|
|
5
|
+
|
|
6
|
+
describe("App", () => {
|
|
7
|
+
it("renders without crashing", () => {
|
|
8
|
+
render(<App />);
|
|
9
|
+
expect(screen.getByText(/Welcome/i)).toBeInTheDocument();
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { render, screen } from "@testing-library/react";
|
|
2
|
+
import { describe, it, expect } from "vitest";
|
|
3
|
+
import App from "@/App";
|
|
4
|
+
|
|
5
|
+
describe("App", () => {
|
|
6
|
+
it("renders without crashing", () => {
|
|
7
|
+
render(<App />);
|
|
8
|
+
expect(screen.getByText(/Welcome/i)).toBeInTheDocument();
|
|
9
|
+
});
|
|
10
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { render, screen } from "@testing-library/react";
|
|
2
|
+
import { describe, it, expect } from "vitest";
|
|
3
|
+
import App from "@/App";
|
|
4
|
+
|
|
5
|
+
describe("App", () => {
|
|
6
|
+
it("renders without crashing", () => {
|
|
7
|
+
render(<App />);
|
|
8
|
+
expect(screen.getByText(/Welcome/i)).toBeInTheDocument();
|
|
9
|
+
});
|
|
10
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { render, screen } from "@testing-library/react";
|
|
2
|
+
import { describe, it, expect } from "vitest";
|
|
3
|
+
import App from "@/App";
|
|
4
|
+
|
|
5
|
+
describe("App", () => {
|
|
6
|
+
it("renders without crashing", () => {
|
|
7
|
+
render(<App />);
|
|
8
|
+
expect(screen.getByText(/Welcome/i)).toBeInTheDocument();
|
|
9
|
+
});
|
|
10
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { render, screen } from "@testing-library/react";
|
|
2
|
+
import { describe, it, expect } from "vitest";
|
|
3
|
+
import App from "@/App";
|
|
4
|
+
|
|
5
|
+
describe("App", () => {
|
|
6
|
+
it("renders without crashing", () => {
|
|
7
|
+
render(<App />);
|
|
8
|
+
expect(screen.getByText(/Welcome/i)).toBeInTheDocument();
|
|
9
|
+
});
|
|
10
|
+
});
|
|
@@ -1,9 +1,91 @@
|
|
|
1
1
|
/* themes.css — Tailwind v4 theme tokens
|
|
2
2
|
* Synced with ThemeProvider / AppProvider via
|
|
3
|
-
* document.documentElement.dataset.theme.
|
|
3
|
+
* document.documentElement.dataset.theme and .dark class.
|
|
4
4
|
*/
|
|
5
|
-
@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));
|
|
5
|
+
@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *, .dark, .dark *));
|
|
6
6
|
|
|
7
|
-
@theme {
|
|
8
|
-
--color-
|
|
7
|
+
@theme inline {
|
|
8
|
+
--color-background: var(--background);
|
|
9
|
+
--color-foreground: var(--foreground);
|
|
10
|
+
--color-card: var(--card);
|
|
11
|
+
--color-card-foreground: var(--card-foreground);
|
|
12
|
+
--color-popover: var(--popover);
|
|
13
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
14
|
+
--color-primary: var(--primary);
|
|
15
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
16
|
+
--color-secondary: var(--secondary);
|
|
17
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
18
|
+
--color-muted: var(--muted);
|
|
19
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
20
|
+
--color-accent: var(--accent);
|
|
21
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
22
|
+
--color-destructive: var(--destructive);
|
|
23
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
24
|
+
--color-border: var(--border);
|
|
25
|
+
--color-input: var(--input);
|
|
26
|
+
--color-ring: var(--ring);
|
|
27
|
+
--color-chart-1: var(--chart-1);
|
|
28
|
+
--color-chart-2: var(--chart-2);
|
|
29
|
+
--color-chart-3: var(--chart-3);
|
|
30
|
+
--color-chart-4: var(--chart-4);
|
|
31
|
+
--color-chart-5: var(--chart-5);
|
|
32
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
33
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
34
|
+
--radius-lg: var(--radius);
|
|
35
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
:root {
|
|
39
|
+
--background: oklch(1 0 0);
|
|
40
|
+
--foreground: oklch(0.145 0 0);
|
|
41
|
+
--card: oklch(1 0 0);
|
|
42
|
+
--card-foreground: oklch(0.145 0 0);
|
|
43
|
+
--popover: oklch(1 0 0);
|
|
44
|
+
--popover-foreground: oklch(0.145 0 0);
|
|
45
|
+
--primary: oklch(0.205 0 0);
|
|
46
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
47
|
+
--secondary: oklch(0.97 0 0);
|
|
48
|
+
--secondary-foreground: oklch(0.205 0 0);
|
|
49
|
+
--muted: oklch(0.97 0 0);
|
|
50
|
+
--muted-foreground: oklch(0.556 0 0);
|
|
51
|
+
--accent: oklch(0.97 0 0);
|
|
52
|
+
--accent-foreground: oklch(0.205 0 0);
|
|
53
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
54
|
+
--destructive-foreground: oklch(0.577 0.245 27.325);
|
|
55
|
+
--border: oklch(0.922 0 0);
|
|
56
|
+
--input: oklch(0.922 0 0);
|
|
57
|
+
--ring: oklch(0.708 0 0);
|
|
58
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
59
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
|
60
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
61
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
62
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
63
|
+
--radius: 0.625rem;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
[data-theme="dark"], .dark {
|
|
67
|
+
--background: oklch(0.145 0 0);
|
|
68
|
+
--foreground: oklch(0.985 0 0);
|
|
69
|
+
--card: oklch(0.145 0 0);
|
|
70
|
+
--card-foreground: oklch(0.985 0 0);
|
|
71
|
+
--popover: oklch(0.145 0 0);
|
|
72
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
73
|
+
--primary: oklch(0.985 0 0);
|
|
74
|
+
--primary-foreground: oklch(0.205 0 0);
|
|
75
|
+
--secondary: oklch(0.269 0 0);
|
|
76
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
77
|
+
--muted: oklch(0.269 0 0);
|
|
78
|
+
--muted-foreground: oklch(0.708 0 0);
|
|
79
|
+
--accent: oklch(0.269 0 0);
|
|
80
|
+
--accent-foreground: oklch(0.985 0 0);
|
|
81
|
+
--destructive: oklch(0.396 0.141 25.723);
|
|
82
|
+
--destructive-foreground: oklch(0.637 0.237 25.331);
|
|
83
|
+
--border: oklch(0.269 0 0);
|
|
84
|
+
--input: oklch(0.269 0 0);
|
|
85
|
+
--ring: oklch(0.439 0 0);
|
|
86
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
87
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
88
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
89
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
90
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
9
91
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
|
|
4
|
+
const buttonVariants = ({
|
|
5
|
+
variant = "default",
|
|
6
|
+
size = "default",
|
|
7
|
+
className = "",
|
|
8
|
+
} = {}) => {
|
|
9
|
+
const base =
|
|
10
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0";
|
|
11
|
+
|
|
12
|
+
const variants = {
|
|
13
|
+
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
|
14
|
+
destructive:
|
|
15
|
+
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
|
16
|
+
outline:
|
|
17
|
+
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
18
|
+
secondary:
|
|
19
|
+
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
20
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
21
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const sizes = {
|
|
25
|
+
default: "h-9 px-4 py-2",
|
|
26
|
+
sm: "h-8 rounded-md px-3 text-xs",
|
|
27
|
+
lg: "h-10 rounded-md px-8",
|
|
28
|
+
icon: "h-9 w-9",
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
return cn(base, variants[variant] || variants.default, sizes[size] || sizes.default, className);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const Button = React.forwardRef(
|
|
35
|
+
({ className, variant = "default", size = "default", ...props }, ref) => {
|
|
36
|
+
return (
|
|
37
|
+
<button
|
|
38
|
+
className={buttonVariants({ variant, size, className })}
|
|
39
|
+
ref={ref}
|
|
40
|
+
{...props}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
Button.displayName = "Button";
|
|
46
|
+
|
|
47
|
+
// eslint-disable-next-line react-refresh/only-export-components
|
|
48
|
+
export { Button, buttonVariants };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
|
|
4
|
+
export interface ButtonProps
|
|
5
|
+
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
6
|
+
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link";
|
|
7
|
+
size?: "default" | "sm" | "lg" | "icon";
|
|
8
|
+
asChild?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const buttonVariants = ({
|
|
12
|
+
variant = "default",
|
|
13
|
+
size = "default",
|
|
14
|
+
className = "",
|
|
15
|
+
}: {
|
|
16
|
+
variant?: ButtonProps["variant"];
|
|
17
|
+
size?: ButtonProps["size"];
|
|
18
|
+
className?: string;
|
|
19
|
+
} = {}) => {
|
|
20
|
+
const base =
|
|
21
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0";
|
|
22
|
+
|
|
23
|
+
const variants = {
|
|
24
|
+
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
|
25
|
+
destructive:
|
|
26
|
+
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
|
27
|
+
outline:
|
|
28
|
+
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
29
|
+
secondary:
|
|
30
|
+
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
31
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
32
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const sizes = {
|
|
36
|
+
default: "h-9 px-4 py-2",
|
|
37
|
+
sm: "h-8 rounded-md px-3 text-xs",
|
|
38
|
+
lg: "h-10 rounded-md px-8",
|
|
39
|
+
icon: "h-9 w-9",
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
return cn(base, variants[variant] || variants.default, sizes[size] || sizes.default, className);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
46
|
+
({ className, variant = "default", size = "default", ...props }, ref) => {
|
|
47
|
+
return (
|
|
48
|
+
<button
|
|
49
|
+
className={buttonVariants({ variant, size, className })}
|
|
50
|
+
ref={ref}
|
|
51
|
+
{...props}
|
|
52
|
+
/>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
Button.displayName = "Button";
|
|
57
|
+
|
|
58
|
+
// eslint-disable-next-line react-refresh/only-export-components
|
|
59
|
+
export { Button, buttonVariants };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
|
|
4
|
+
export const Card = React.forwardRef(({ className, ...props }, ref) => (
|
|
5
|
+
<div
|
|
6
|
+
ref={ref}
|
|
7
|
+
className={cn(
|
|
8
|
+
"rounded-xl border bg-card text-card-foreground shadow",
|
|
9
|
+
className
|
|
10
|
+
)}
|
|
11
|
+
{...props}
|
|
12
|
+
/>
|
|
13
|
+
));
|
|
14
|
+
Card.displayName = "Card";
|
|
15
|
+
|
|
16
|
+
export const CardHeader = React.forwardRef(({ className, ...props }, ref) => (
|
|
17
|
+
<div
|
|
18
|
+
ref={ref}
|
|
19
|
+
className={cn("flex flex-col space-y-1.5 p-6", className)}
|
|
20
|
+
{...props}
|
|
21
|
+
/>
|
|
22
|
+
));
|
|
23
|
+
CardHeader.displayName = "CardHeader";
|
|
24
|
+
|
|
25
|
+
export const CardTitle = React.forwardRef(({ className, ...props }, ref) => (
|
|
26
|
+
<div
|
|
27
|
+
ref={ref}
|
|
28
|
+
className={cn("font-semibold leading-none tracking-tight", className)}
|
|
29
|
+
{...props}
|
|
30
|
+
/>
|
|
31
|
+
));
|
|
32
|
+
CardTitle.displayName = "CardTitle";
|
|
33
|
+
|
|
34
|
+
export const CardDescription = React.forwardRef(({ className, ...props }, ref) => (
|
|
35
|
+
<div
|
|
36
|
+
ref={ref}
|
|
37
|
+
className={cn("text-sm text-muted-foreground", className)}
|
|
38
|
+
{...props}
|
|
39
|
+
/>
|
|
40
|
+
));
|
|
41
|
+
CardDescription.displayName = "CardDescription";
|
|
42
|
+
|
|
43
|
+
export const CardContent = React.forwardRef(({ className, ...props }, ref) => (
|
|
44
|
+
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
|
45
|
+
));
|
|
46
|
+
CardContent.displayName = "CardContent";
|
|
47
|
+
|
|
48
|
+
export const CardFooter = React.forwardRef(({ className, ...props }, ref) => (
|
|
49
|
+
<div
|
|
50
|
+
ref={ref}
|
|
51
|
+
className={cn("flex items-center p-6 pt-0", className)}
|
|
52
|
+
{...props}
|
|
53
|
+
/>
|
|
54
|
+
));
|
|
55
|
+
CardFooter.displayName = "CardFooter";
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
|
|
4
|
+
export const Card = React.forwardRef<
|
|
5
|
+
HTMLDivElement,
|
|
6
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
7
|
+
>(({ className, ...props }, ref) => (
|
|
8
|
+
<div
|
|
9
|
+
ref={ref}
|
|
10
|
+
className={cn(
|
|
11
|
+
"rounded-xl border bg-card text-card-foreground shadow",
|
|
12
|
+
className
|
|
13
|
+
)}
|
|
14
|
+
{...props}
|
|
15
|
+
/>
|
|
16
|
+
));
|
|
17
|
+
Card.displayName = "Card";
|
|
18
|
+
|
|
19
|
+
export const CardHeader = React.forwardRef<
|
|
20
|
+
HTMLDivElement,
|
|
21
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
22
|
+
>(({ className, ...props }, ref) => (
|
|
23
|
+
<div
|
|
24
|
+
ref={ref}
|
|
25
|
+
className={cn("flex flex-col space-y-1.5 p-6", className)}
|
|
26
|
+
{...props}
|
|
27
|
+
/>
|
|
28
|
+
));
|
|
29
|
+
CardHeader.displayName = "CardHeader";
|
|
30
|
+
|
|
31
|
+
export const CardTitle = React.forwardRef<
|
|
32
|
+
HTMLDivElement,
|
|
33
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
34
|
+
>(({ className, ...props }, ref) => (
|
|
35
|
+
<div
|
|
36
|
+
ref={ref}
|
|
37
|
+
className={cn("font-semibold leading-none tracking-tight", className)}
|
|
38
|
+
{...props}
|
|
39
|
+
/>
|
|
40
|
+
));
|
|
41
|
+
CardTitle.displayName = "CardTitle";
|
|
42
|
+
|
|
43
|
+
export const CardDescription = React.forwardRef<
|
|
44
|
+
HTMLDivElement,
|
|
45
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
46
|
+
>(({ className, ...props }, ref) => (
|
|
47
|
+
<div
|
|
48
|
+
ref={ref}
|
|
49
|
+
className={cn("text-sm text-muted-foreground", className)}
|
|
50
|
+
{...props}
|
|
51
|
+
/>
|
|
52
|
+
));
|
|
53
|
+
CardDescription.displayName = "CardDescription";
|
|
54
|
+
|
|
55
|
+
export const CardContent = React.forwardRef<
|
|
56
|
+
HTMLDivElement,
|
|
57
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
58
|
+
>(({ className, ...props }, ref) => (
|
|
59
|
+
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
|
60
|
+
));
|
|
61
|
+
CardContent.displayName = "CardContent";
|
|
62
|
+
|
|
63
|
+
export const CardFooter = React.forwardRef<
|
|
64
|
+
HTMLDivElement,
|
|
65
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
66
|
+
>(({ className, ...props }, ref) => (
|
|
67
|
+
<div
|
|
68
|
+
ref={ref}
|
|
69
|
+
className={cn("flex items-center p-6 pt-0", className)}
|
|
70
|
+
{...props}
|
|
71
|
+
/>
|
|
72
|
+
));
|
|
73
|
+
CardFooter.displayName = "CardFooter";
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/* themes.css — Bootstrap 5.3+ theme overrides
|
|
2
|
-
* Bootstrap 5.3+ reads data-bs-theme on a parent element to switch between
|
|
3
|
-
* light/dark variants. The themes here customize the default tokens; the
|
|
4
|
-
* data-bs-theme attribute is applied externally.
|
|
5
|
-
*/
|
|
6
|
-
:root[data-bs-theme="light"] {
|
|
7
|
-
--bs-primary: #6366f1;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
:root[data-bs-theme="dark"] {
|
|
11
|
-
--bs-body-bg: #111827;
|
|
12
|
-
--bs-body-color: #f9fafb;
|
|
13
|
-
--bs-primary: #818cf8;
|
|
14
|
-
}
|
/package/templates/{css/bootstrap/src/globals.css → architectures/hybrid/src/features/.gitkeep}
RENAMED
|
File without changes
|