gradient-forge 1.0.4 → 1.0.7

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.
Files changed (2) hide show
  1. package/cli/index.mjs +81 -23
  2. package/package.json +1 -1
package/cli/index.mjs CHANGED
@@ -164,23 +164,61 @@ const promptSelect = async (title, items, defaultIndex = 0) => {
164
164
  });
165
165
  };
166
166
 
167
- // Generate CSS
167
+ // Generate CSS - with !important to override tailwind defaults
168
168
  const generateCSS = (themeId, mode) => {
169
169
  const tokens = getThemeTokens(themeId);
170
- return `/* Gradient Forge Theme */
171
- .${themeId} {
170
+ const isDark = mode === "dark";
171
+
172
+ return `/* Gradient Forge Theme - ${mode} */
173
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
174
+
175
+ :root {
176
+ --font-sans: 'Inter', sans-serif;
177
+ }
178
+
179
+ /* Theme CSS Variables */
180
+ .${themeId},
181
+ .${themeId} body {
172
182
  ${Object.entries(tokens).map(([k, v]) => ` ${k}: ${v};`).join("\n")}
173
183
  }
174
184
 
175
- body {
176
- background: hsl(${tokens["--background"]});
177
- color: hsl(${tokens["--foreground"]});
185
+ /* Force theme override with !important */
186
+ .${themeId} {
187
+ --background: ${tokens["--background"]} !important;
188
+ --foreground: ${tokens["--foreground"]} !important;
189
+ --primary: ${tokens["--primary"]} !important;
190
+ --primary-foreground: ${tokens["--primary-foreground"]} !important;
191
+ --secondary: ${tokens["--secondary"]} !important;
192
+ --secondary-foreground: ${tokens["--secondary-foreground"]} !important;
193
+ --muted: ${tokens["--muted"]} !important;
194
+ --muted-foreground: ${tokens["--muted-foreground"]} !important;
195
+ --accent: ${tokens["--accent"]} !important;
196
+ --accent-foreground: ${tokens["--accent-foreground"]} !important;
197
+ --destructive: ${tokens["--destructive"]} !important;
198
+ --destructive-foreground: ${tokens["--destructive-foreground"]} !important;
199
+ --border: ${tokens["--border"]} !important;
200
+ --card: ${tokens["--card"]} !important;
201
+ --card-foreground: ${tokens["--card-foreground"]} !important;
202
+ --popover: ${tokens["--popover"]} !important;
203
+ --popover-foreground: ${tokens["--popover-foreground"]} !important;
204
+ --input: ${tokens["--input"]} !important;
205
+ --ring: ${tokens["--ring"]} !important;
206
+ }
207
+
208
+ /* Apply gradient background */
209
+ .${themeId} body {
210
+ background: linear-gradient(160deg, hsl(${tokens["--background"]}) 0%, hsl(${tokens["--background"]}) 50%, hsl(${tokens["--background"]}) 100%);
211
+ background-attachment: fixed;
178
212
  }
179
213
 
180
- .bg-card, .bg-popover, .bg-sidebar {
181
- background-color: hsl(${tokens["--card"]} / 0.34);
214
+ /* Surface layers with glassmorphism */
215
+ .${themeId} .bg-card,
216
+ .${themeId} .bg-popover,
217
+ .${themeId} .bg-sidebar {
218
+ background-color: hsl(${tokens["--card"]} / 0.4) !important;
182
219
  background-image: linear-gradient(${tokens["--app-surface-tint"]}, ${tokens["--app-surface-tint"]});
183
220
  backdrop-filter: blur(16px);
221
+ border: 1px solid hsl(${tokens["--border"]} / 0.3);
184
222
  }
185
223
  `;
186
224
  };
@@ -188,18 +226,26 @@ body {
188
226
  // Generate theme context
189
227
  const generateContext = (themeId, mode) => {
190
228
  return `"use client";
191
- import React, { createContext, useContext, useEffect, useState } from "react";
229
+ import { createContext, useContext, useEffect, useState, type ReactNode } from "react";
192
230
 
193
231
  export type ThemeId = string;
194
232
  export type ColorMode = string;
195
233
 
234
+ interface ThemeContextType {
235
+ themeId: string;
236
+ colorMode: string;
237
+ setThemeId: (id: string) => void;
238
+ setColorMode: (mode: string) => void;
239
+ themes: { id: string; label: string }[];
240
+ }
241
+
196
242
  const allThemes = [
197
243
  ${themes.map(t => ` { id: "${t.id}", label: "${t.label}" }`).join(",\n")}
198
244
  ];
199
245
 
200
- const ThemeContext: any = createContext(null);
246
+ const ThemeContext = createContext<ThemeContextType | null>(null);
201
247
 
202
- export const ThemeProvider = ({ children }: { children: any }) => {
248
+ export const ThemeProvider = ({ children }: { children: ReactNode }) => {
203
249
  const [themeId, setThemeId] = useState("${themeId}");
204
250
  const [colorMode, setColorMode] = useState("${mode}");
205
251
 
@@ -231,8 +277,8 @@ export function ThemeSwitcher() {
231
277
  const { themeId, colorMode, setThemeId, setColorMode, themes } = useTheme();
232
278
  return (
233
279
  <div style={{ display: "flex", gap: "8px", padding: "8px" }}>
234
- <select value={themeId} onChange={(e: any) => setThemeId(e.target.value)} style={{ padding: "4px" }}>
235
- {themes.map((t: any) => <option key={t.id} value={t.id}>{t.label}</option>)}
280
+ <select value={themeId} onChange={(e) => setThemeId(e.target.value)} style={{ padding: "4px" }}>
281
+ {themes.map((t) => <option key={t.id} value={t.id}>{t.label}</option>)}
236
282
  </select>
237
283
  <button onClick={() => setColorMode(colorMode === "dark" ? "light" : "dark")} style={{ padding: "4px 8px" }}>
238
284
  {colorMode === "dark" ? "🌙" : "☀️"}
@@ -260,12 +306,14 @@ const setupNextJs = (projectRoot, themeId, mode) => {
260
306
  fs.writeFileSync(contextPath, generateContext(themeId, mode));
261
307
  logSuccess(`Created: components/theme/theme-context.tsx`);
262
308
 
263
- // Inject into globals.css
309
+ // Inject into globals.css - add AFTER tailwind imports so theme overrides tailwind
264
310
  const globalsPath = path.join(appDir, "globals.css");
265
311
  if (fs.existsSync(globalsPath)) {
266
- const content = fs.readFileSync(globalsPath, "utf8");
312
+ let content = fs.readFileSync(globalsPath, "utf8");
267
313
  if (!content.includes("gradient-forge.css")) {
268
- fs.writeFileSync(globalsPath, `@import "./gradient-forge.css";\n${content}`);
314
+ // Add at the end after all tailwind imports
315
+ content = content + '\n@import "./gradient-forge.css";';
316
+ fs.writeFileSync(globalsPath, content);
269
317
  logSuccess(`Injected into: app/globals.css`);
270
318
  }
271
319
  }
@@ -276,18 +324,28 @@ const setupNextJs = (projectRoot, themeId, mode) => {
276
324
  let content = fs.readFileSync(layoutPath, "utf8");
277
325
 
278
326
  if (!content.includes("ThemeProvider")) {
279
- // Add import
280
- const importStmt = `import { ThemeProvider } from "./components/theme/theme-context";`;
327
+ // Use @/ import path for Next.js
328
+ const importStmt = `import { ThemeProvider } from "@/components/theme/theme-context";`;
281
329
  if (!content.includes(importStmt)) {
282
330
  content = importStmt + "\n" + content;
283
331
  }
284
332
 
285
- // Wrap body - ensure proper spacing
286
- content = content.replace(/(<body[^>]*>)/, "$1\n<ThemeProvider>");
287
- content = content.replace(/(<\/body>)/, "</ThemeProvider>\n$1");
333
+ // Wrap body - keep existing className and add ThemeProvider around children
334
+ content = content.replace(/(<body[^>]*>)([\s\S]*?)(<\/body>)/,
335
+ '$1<ThemeProvider>$2</ThemeProvider>$3');
288
336
 
289
- // Add classes to html - preserve existing attributes
290
- content = content.replace(/<html/, `<html class="${mode} ${themeId}" data-theme="${themeId}" data-color-mode="${mode}"`);
337
+ // Add theme classes to html - preserve existing className and add theme classes
338
+ if (content.includes('className=')) {
339
+ // For JSX className={expression}, add theme classes to the expression
340
+ content = content.replace(
341
+ /(className=\{)([^}]+)(\})/,
342
+ `$1$2 + " ${mode} ${themeId}"$3`
343
+ );
344
+ } else {
345
+ // For plain html or no className, add className attribute
346
+ content = content.replace(/<html/,
347
+ `<html className="${mode} ${themeId}" data-theme="${themeId}" data-color-mode="${mode}"`);
348
+ }
291
349
 
292
350
  fs.writeFileSync(layoutPath, content);
293
351
  logSuccess(`Updated: app/layout.tsx`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gradient-forge",
3
- "version": "1.0.4",
3
+ "version": "1.0.7",
4
4
  "description": "A production-ready gradient theming framework for shadcn/ui with CLI support",
5
5
  "type": "module",
6
6
  "bin": {