gradient-forge 1.0.0 → 1.0.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.
Files changed (2) hide show
  1. package/cli/index.mjs +49 -27
  2. package/package.json +1 -2
package/cli/index.mjs CHANGED
@@ -567,16 +567,9 @@ const promptSelect = async (title, items, defaultIndex = 0) => {
567
567
  }
568
568
 
569
569
  let index = defaultIndex;
570
- let isFirstRender = true;
571
570
 
572
571
  const render = () => {
573
- if (isFirstRender) {
574
- process.stdout.write("\x1b[s");
575
- isFirstRender = false;
576
- } else {
577
- process.stdout.write("\x1b[u");
578
- process.stdout.write("\x1b[0J");
579
- }
572
+ process.stdout.write("\x1b[2J\x1b[H");
580
573
  log(title);
581
574
  log("");
582
575
  items.forEach((item, i) => {
@@ -603,11 +596,11 @@ const promptSelect = async (title, items, defaultIndex = 0) => {
603
596
  return;
604
597
  }
605
598
  if (key === "\u001b[A") {
606
- index = (index - 1 + items.length) % items.length;
599
+ index = index > 0 ? index - 1 : items.length - 1;
607
600
  render();
608
601
  }
609
602
  if (key === "\u001b[B") {
610
- index = (index + 1) % items.length;
603
+ index = index < items.length - 1 ? index + 1 : 0;
611
604
  render();
612
605
  }
613
606
  };
@@ -685,8 +678,13 @@ type ThemeContextValue = {
685
678
  colorMode: ColorMode;
686
679
  setThemeId: (themeId: ThemeId) => void;
687
680
  setColorMode: (mode: ColorMode) => void;
681
+ themes: { id: ThemeId; label: string }[];
688
682
  };
689
683
 
684
+ const allThemes: { id: ThemeId; label: string }[] = [
685
+ ${themes.map(t => ` { id: "${t.id}", label: "${t.label}" },`).join("\n")}
686
+ ];
687
+
690
688
  const ThemeContext = createContext<ThemeContextValue | null>(null);
691
689
 
692
690
  export const ThemeProvider = ({ children }: { children: ReactNode }) => {
@@ -696,7 +694,7 @@ export const ThemeProvider = ({ children }: { children: ReactNode }) => {
696
694
  useEffect(() => {
697
695
  const root = document.documentElement;
698
696
  root.classList.remove("dark", "light");
699
- root.classList.remove(${themes.map(t => `"${t.id}"`).join(", ")});
697
+ ${themes.map(t => ` root.classList.remove("${t.id}");`).join("\n")}
700
698
 
701
699
  root.classList.add(colorMode, themeId);
702
700
  root.setAttribute("data-theme", themeId);
@@ -707,7 +705,7 @@ export const ThemeProvider = ({ children }: { children: ReactNode }) => {
707
705
  }, [themeId, colorMode]);
708
706
 
709
707
  return (
710
- <ThemeContext.Provider value={{ themeId, colorMode, setThemeId, setColorMode }}>
708
+ <ThemeContext.Provider value={{ themeId, colorMode, setThemeId, setColorMode, themes: allThemes }}>
711
709
  {children}
712
710
  </ThemeContext.Provider>
713
711
  );
@@ -718,6 +716,31 @@ export const useTheme = () => {
718
716
  if (!ctx) throw new Error("useTheme must be used within ThemeProvider");
719
717
  return ctx;
720
718
  };
719
+
720
+ // Simple theme switcher component - drop into your app!
721
+ export function ThemeSwitcher() {
722
+ const { themeId, colorMode, setThemeId, setColorMode, themes } = useTheme();
723
+
724
+ return (
725
+ <div className="flex items-center gap-2 p-2 rounded-lg bg-card border">
726
+ <select
727
+ value={themeId}
728
+ onChange={(e) => setThemeId(e.target.value as ThemeId)}
729
+ className="bg-background text-foreground px-2 py-1 rounded border"
730
+ >
731
+ {themes.map(t => (
732
+ <option key={t.id} value={t.id}>{t.label}</option>
733
+ ))}
734
+ </select>
735
+ <button
736
+ onClick={() => setColorMode(colorMode === "dark" ? "light" : "dark")}
737
+ className="px-2 py-1 rounded bg-primary text-primary-foreground"
738
+ >
739
+ {colorMode === "dark" ? "🌙" : "☀️"}
740
+ </button>
741
+ </div>
742
+ );
743
+ }
721
744
  `;
722
745
  };
723
746
 
@@ -727,17 +750,17 @@ const generateSetupInstructions = (projectRoot, themeId, mode, themeLabel) => {
727
750
  Theme: ${themeLabel}
728
751
  Mode: ${mode}
729
752
 
730
- ## What was created:
731
- - components/theme/theme-engine.ts - Theme definitions
732
- - components/theme/theme-context.tsx - React context provider
733
- - app/gradient-forge.css - Theme CSS variables
753
+ ## Quick Setup (Done!)
734
754
 
735
- ## Next steps:
755
+ Already configured:
756
+ - app/gradient-forge.css - Theme CSS
757
+ - components/theme/theme-context.tsx - Theme provider + ThemeSwitcher component
758
+ - components/theme/theme-engine.ts - Theme definitions
759
+ - app/globals.css - Theme imported
736
760
 
737
- 1. Import the CSS in your layout:
738
- import "./app/gradient-forge.css";
761
+ ## Add to your app:
739
762
 
740
- 2. Wrap your app with ThemeProvider:
763
+ 1. Wrap your app with ThemeProvider in layout.tsx:
741
764
  import { ThemeProvider } from "./components/theme/theme-context";
742
765
 
743
766
  export default function RootLayout({ children }) {
@@ -750,15 +773,14 @@ Mode: ${mode}
750
773
  );
751
774
  }
752
775
 
753
- 3. Use the theme in your components:
754
- import { useTheme } from "./components/theme/theme-context";
776
+ 2. Add the theme switcher anywhere in your app:
777
+ import { ThemeSwitcher } from "./components/theme/theme-context";
755
778
 
756
- function MyComponent() {
757
- const { themeId, colorMode } = useTheme();
758
- // ...
759
- }
779
+ // Add <ThemeSwitcher /> anywhere to let users change themes!
780
+
781
+ ## Done! 🎉 Your app now has gradient themes!
760
782
 
761
- ## For more themes, visit: https://gradient-forge.vercel.app
783
+ For more themes, visit: https://gradient-forge.vercel.app
762
784
  `;
763
785
  };
764
786
 
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "gradient-forge",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "A production-ready gradient theming framework for shadcn/ui with CLI support",
5
- "main": "index.js",
6
5
  "type": "module",
7
6
  "bin": {
8
7
  "gradient-forge": "./cli/index.mjs"