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.
- package/cli/index.mjs +49 -27
- 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
|
-
|
|
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 =
|
|
599
|
+
index = index > 0 ? index - 1 : items.length - 1;
|
|
607
600
|
render();
|
|
608
601
|
}
|
|
609
602
|
if (key === "\u001b[B") {
|
|
610
|
-
index =
|
|
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
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-
|
|
738
|
-
import "./app/gradient-forge.css";
|
|
761
|
+
## Add to your app:
|
|
739
762
|
|
|
740
|
-
|
|
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
|
-
|
|
754
|
-
import {
|
|
776
|
+
2. Add the theme switcher anywhere in your app:
|
|
777
|
+
import { ThemeSwitcher } from "./components/theme/theme-context";
|
|
755
778
|
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
}
|
|
779
|
+
// Add <ThemeSwitcher /> anywhere to let users change themes!
|
|
780
|
+
|
|
781
|
+
## Done! 🎉 Your app now has gradient themes!
|
|
760
782
|
|
|
761
|
-
|
|
783
|
+
For more themes, visit: https://gradient-forge.vercel.app
|
|
762
784
|
`;
|
|
763
785
|
};
|
|
764
786
|
|
package/package.json
CHANGED