@fakhrirafiki/theme-engine 0.2.2 → 0.2.5
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/dist/index.d.mts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +108 -62
- package/dist/index.mjs +108 -62
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -318,7 +318,7 @@ interface UnifiedThemeContextValue {
|
|
|
318
318
|
/** Current appearance mode setting */
|
|
319
319
|
mode: Mode;
|
|
320
320
|
/** Resolved appearance mode (never 'system') */
|
|
321
|
-
resolvedMode:
|
|
321
|
+
resolvedMode: "light" | "dark";
|
|
322
322
|
/** Change the appearance mode */
|
|
323
323
|
setMode: (mode: Mode) => void;
|
|
324
324
|
/** Toggle between light and dark modes with optional animation */
|
|
@@ -330,7 +330,7 @@ interface UnifiedThemeContextValue {
|
|
|
330
330
|
/** Human-readable preset name */
|
|
331
331
|
presetName: string;
|
|
332
332
|
/** Color values for light and dark modes */
|
|
333
|
-
colors: ThemePreset[
|
|
333
|
+
colors: ThemePreset["colors"];
|
|
334
334
|
/** Timestamp when preset was applied */
|
|
335
335
|
appliedAt: number;
|
|
336
336
|
} | null;
|
|
@@ -340,6 +340,8 @@ interface UnifiedThemeContextValue {
|
|
|
340
340
|
setThemePresetById: (presetId: string) => void;
|
|
341
341
|
/** Clear the current preset and revert to default colors */
|
|
342
342
|
clearPreset: () => void;
|
|
343
|
+
/** Whether the currently active preset matches the defaultPreset prop */
|
|
344
|
+
isUsingDefaultPreset: boolean;
|
|
343
345
|
/** Available presets (merged built-in + custom) */
|
|
344
346
|
availablePresets: Record<string, TweakCNThemePreset>;
|
|
345
347
|
/** Built-in presets only */
|
package/dist/index.d.ts
CHANGED
|
@@ -318,7 +318,7 @@ interface UnifiedThemeContextValue {
|
|
|
318
318
|
/** Current appearance mode setting */
|
|
319
319
|
mode: Mode;
|
|
320
320
|
/** Resolved appearance mode (never 'system') */
|
|
321
|
-
resolvedMode:
|
|
321
|
+
resolvedMode: "light" | "dark";
|
|
322
322
|
/** Change the appearance mode */
|
|
323
323
|
setMode: (mode: Mode) => void;
|
|
324
324
|
/** Toggle between light and dark modes with optional animation */
|
|
@@ -330,7 +330,7 @@ interface UnifiedThemeContextValue {
|
|
|
330
330
|
/** Human-readable preset name */
|
|
331
331
|
presetName: string;
|
|
332
332
|
/** Color values for light and dark modes */
|
|
333
|
-
colors: ThemePreset[
|
|
333
|
+
colors: ThemePreset["colors"];
|
|
334
334
|
/** Timestamp when preset was applied */
|
|
335
335
|
appliedAt: number;
|
|
336
336
|
} | null;
|
|
@@ -340,6 +340,8 @@ interface UnifiedThemeContextValue {
|
|
|
340
340
|
setThemePresetById: (presetId: string) => void;
|
|
341
341
|
/** Clear the current preset and revert to default colors */
|
|
342
342
|
clearPreset: () => void;
|
|
343
|
+
/** Whether the currently active preset matches the defaultPreset prop */
|
|
344
|
+
isUsingDefaultPreset: boolean;
|
|
343
345
|
/** Available presets (merged built-in + custom) */
|
|
344
346
|
availablePresets: Record<string, TweakCNThemePreset>;
|
|
345
347
|
/** Built-in presets only */
|
package/dist/index.js
CHANGED
|
@@ -3748,9 +3748,12 @@ function ThemeProvider({
|
|
|
3748
3748
|
}, [includeBuiltInPresets, customPresets]);
|
|
3749
3749
|
const builtInPresets = (0, import_react.useMemo)(() => includeBuiltInPresets ? tweakcnPresets : {}, [includeBuiltInPresets]);
|
|
3750
3750
|
const normalizedCustomPresets = (0, import_react.useMemo)(() => customPresets || {}, [customPresets]);
|
|
3751
|
-
const getAvailablePresetById = (0, import_react.useCallback)(
|
|
3752
|
-
|
|
3753
|
-
|
|
3751
|
+
const getAvailablePresetById = (0, import_react.useCallback)(
|
|
3752
|
+
(id) => {
|
|
3753
|
+
return availablePresets[id] || null;
|
|
3754
|
+
},
|
|
3755
|
+
[availablePresets]
|
|
3756
|
+
);
|
|
3754
3757
|
const [currentPreset, setCurrentPreset] = (0, import_react.useState)(null);
|
|
3755
3758
|
const [isReady, setIsReady] = (0, import_react.useState)(false);
|
|
3756
3759
|
(0, import_react.useEffect)(() => {
|
|
@@ -3760,10 +3763,9 @@ function ThemeProvider({
|
|
|
3760
3763
|
}
|
|
3761
3764
|
try {
|
|
3762
3765
|
const stored = localStorage.getItem(presetStorageKey);
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
} else if (defaultPreset) {
|
|
3766
|
+
const isDevelopment = typeof window !== "undefined" && window.location?.hostname === "localhost";
|
|
3767
|
+
const applyDefaultPreset = () => {
|
|
3768
|
+
if (!defaultPreset) return;
|
|
3767
3769
|
const preset = getAvailablePresetById(defaultPreset);
|
|
3768
3770
|
if (preset) {
|
|
3769
3771
|
const presetData = {
|
|
@@ -3779,13 +3781,42 @@ function ThemeProvider({
|
|
|
3779
3781
|
} else {
|
|
3780
3782
|
console.warn("\u{1F3A8} UnifiedTheme: Default preset not found:", defaultPreset);
|
|
3781
3783
|
}
|
|
3784
|
+
};
|
|
3785
|
+
if (stored) {
|
|
3786
|
+
try {
|
|
3787
|
+
const parsed = JSON.parse(stored);
|
|
3788
|
+
const isValidObject = parsed && typeof parsed === "object";
|
|
3789
|
+
const hasColors = isValidObject && "colors" in parsed && parsed.colors && typeof parsed.colors === "object" && parsed.colors.light && parsed.colors.dark;
|
|
3790
|
+
if (hasColors) {
|
|
3791
|
+
setCurrentPreset(parsed);
|
|
3792
|
+
if (isDevelopment) {
|
|
3793
|
+
}
|
|
3794
|
+
} else {
|
|
3795
|
+
if (isDevelopment) {
|
|
3796
|
+
console.warn("\u{1F3A8} UnifiedTheme: Invalid persisted preset shape. Clearing and falling back.");
|
|
3797
|
+
}
|
|
3798
|
+
localStorage.removeItem(presetStorageKey);
|
|
3799
|
+
applyDefaultPreset();
|
|
3800
|
+
}
|
|
3801
|
+
} catch (error) {
|
|
3802
|
+
if (isDevelopment) {
|
|
3803
|
+
console.warn("\u{1F3A8} UnifiedTheme: Failed to parse persisted preset. Clearing key.", error);
|
|
3804
|
+
}
|
|
3805
|
+
localStorage.removeItem(presetStorageKey);
|
|
3806
|
+
applyDefaultPreset();
|
|
3807
|
+
}
|
|
3808
|
+
} else {
|
|
3809
|
+
applyDefaultPreset();
|
|
3782
3810
|
}
|
|
3783
3811
|
} catch (error) {
|
|
3784
|
-
|
|
3812
|
+
const isDevelopment = typeof window !== "undefined" && window.location?.hostname === "localhost";
|
|
3813
|
+
if (isDevelopment) {
|
|
3814
|
+
console.warn("\u{1F3A8} UnifiedTheme: Failed to load preset from storage:", error);
|
|
3815
|
+
}
|
|
3785
3816
|
} finally {
|
|
3786
3817
|
setIsReady(true);
|
|
3787
3818
|
}
|
|
3788
|
-
}, [presetStorageKey, enablePresets, defaultPreset]);
|
|
3819
|
+
}, [presetStorageKey, enablePresets, defaultPreset, getAvailablePresetById]);
|
|
3789
3820
|
(0, import_react.useEffect)(() => {
|
|
3790
3821
|
if (mode === "system") {
|
|
3791
3822
|
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
@@ -3806,11 +3837,12 @@ function ThemeProvider({
|
|
|
3806
3837
|
root.style.colorScheme = resolvedMode;
|
|
3807
3838
|
}, [resolvedMode]);
|
|
3808
3839
|
const applyPresetColors = (0, import_react.useCallback)((preset, mode2) => {
|
|
3840
|
+
if (!preset) return;
|
|
3809
3841
|
const root = document.documentElement;
|
|
3810
3842
|
const colors = preset[mode2];
|
|
3811
3843
|
if (!colors) return;
|
|
3812
3844
|
const defaultValues = {
|
|
3813
|
-
|
|
3845
|
+
spacing: "0.25rem",
|
|
3814
3846
|
"letter-spacing": "normal"
|
|
3815
3847
|
};
|
|
3816
3848
|
const allCategories = [
|
|
@@ -3849,67 +3881,79 @@ function ThemeProvider({
|
|
|
3849
3881
|
}
|
|
3850
3882
|
});
|
|
3851
3883
|
}, []);
|
|
3852
|
-
const handleModeChange = (0, import_react.useCallback)(
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3884
|
+
const handleModeChange = (0, import_react.useCallback)(
|
|
3885
|
+
(newMode) => {
|
|
3886
|
+
setMode(newMode);
|
|
3887
|
+
setStoredMode(newMode, modeStorageKey);
|
|
3888
|
+
},
|
|
3889
|
+
[modeStorageKey]
|
|
3890
|
+
);
|
|
3891
|
+
const handleModeToggle = (0, import_react.useCallback)(
|
|
3892
|
+
(coordinates) => {
|
|
3893
|
+
const newMode = resolvedMode === "light" ? "dark" : "light";
|
|
3894
|
+
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
3895
|
+
if (enableTransitions && !prefersReducedMotion && typeof document !== "undefined" && "startViewTransition" in document) {
|
|
3896
|
+
const root = document.documentElement;
|
|
3897
|
+
if (coordinates) {
|
|
3898
|
+
root.style.setProperty("--x", `${coordinates.x}px`);
|
|
3899
|
+
root.style.setProperty("--y", `${coordinates.y}px`);
|
|
3900
|
+
}
|
|
3901
|
+
document.startViewTransition(() => {
|
|
3902
|
+
handleModeChange(newMode);
|
|
3903
|
+
});
|
|
3904
|
+
} else {
|
|
3866
3905
|
handleModeChange(newMode);
|
|
3867
|
-
}
|
|
3868
|
-
}
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
}, [resolvedMode, enableTransitions, handleModeChange]);
|
|
3906
|
+
}
|
|
3907
|
+
},
|
|
3908
|
+
[resolvedMode, enableTransitions, handleModeChange]
|
|
3909
|
+
);
|
|
3872
3910
|
(0, import_react.useEffect)(() => {
|
|
3873
3911
|
if (!currentPreset || typeof window === "undefined") return;
|
|
3874
3912
|
applyPresetColors(currentPreset.colors, resolvedMode);
|
|
3875
3913
|
}, [currentPreset, resolvedMode, applyPresetColors]);
|
|
3876
|
-
const applyPreset = (0, import_react.useCallback)(
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3914
|
+
const applyPreset = (0, import_react.useCallback)(
|
|
3915
|
+
(preset) => {
|
|
3916
|
+
const presetData = {
|
|
3917
|
+
presetId: preset.id,
|
|
3918
|
+
presetName: preset.name,
|
|
3919
|
+
colors: preset.colors,
|
|
3920
|
+
appliedAt: Date.now()
|
|
3921
|
+
};
|
|
3922
|
+
setCurrentPreset(presetData);
|
|
3923
|
+
if (enablePresets && typeof window !== "undefined") {
|
|
3924
|
+
try {
|
|
3925
|
+
localStorage.setItem(presetStorageKey, JSON.stringify(presetData));
|
|
3926
|
+
} catch (error) {
|
|
3927
|
+
console.error("\u{1F3A8} UnifiedTheme: Failed to save preset:", error);
|
|
3928
|
+
}
|
|
3889
3929
|
}
|
|
3890
|
-
}
|
|
3891
|
-
if (typeof window !== "undefined") {
|
|
3892
|
-
applyPresetColors(preset.colors, resolvedMode);
|
|
3893
|
-
}
|
|
3894
|
-
}, [presetStorageKey, enablePresets, applyPresetColors, resolvedMode]);
|
|
3895
|
-
const setThemePresetById = (0, import_react.useCallback)((presetId) => {
|
|
3896
|
-
const preset = getAvailablePresetById(presetId);
|
|
3897
|
-
if (!preset) {
|
|
3898
3930
|
if (typeof window !== "undefined") {
|
|
3899
|
-
|
|
3931
|
+
applyPresetColors(preset.colors, resolvedMode);
|
|
3900
3932
|
}
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3933
|
+
},
|
|
3934
|
+
[presetStorageKey, enablePresets, applyPresetColors, resolvedMode]
|
|
3935
|
+
);
|
|
3936
|
+
const setThemePresetById = (0, import_react.useCallback)(
|
|
3937
|
+
(presetId) => {
|
|
3938
|
+
const preset = getAvailablePresetById(presetId);
|
|
3939
|
+
if (!preset) {
|
|
3940
|
+
if (typeof window !== "undefined") {
|
|
3941
|
+
console.warn("\u{1F3A8} UnifiedTheme: Preset not found for id:", presetId);
|
|
3942
|
+
}
|
|
3943
|
+
return;
|
|
3909
3944
|
}
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3945
|
+
const presetData = {
|
|
3946
|
+
id: presetId,
|
|
3947
|
+
name: preset.label,
|
|
3948
|
+
colors: {
|
|
3949
|
+
light: preset.styles.light,
|
|
3950
|
+
dark: preset.styles.dark
|
|
3951
|
+
}
|
|
3952
|
+
};
|
|
3953
|
+
applyPreset(presetData);
|
|
3954
|
+
},
|
|
3955
|
+
[getAvailablePresetById, applyPreset]
|
|
3956
|
+
);
|
|
3913
3957
|
const clearPreset = (0, import_react.useCallback)(() => {
|
|
3914
3958
|
if (enablePresets && typeof window !== "undefined") {
|
|
3915
3959
|
try {
|
|
@@ -3957,6 +4001,7 @@ function ThemeProvider({
|
|
|
3957
4001
|
if (!isReady) {
|
|
3958
4002
|
return null;
|
|
3959
4003
|
}
|
|
4004
|
+
const isUsingDefaultPreset = !!defaultPreset && currentPreset?.presetId === defaultPreset;
|
|
3960
4005
|
const contextValue = {
|
|
3961
4006
|
mode,
|
|
3962
4007
|
resolvedMode,
|
|
@@ -3966,6 +4011,7 @@ function ThemeProvider({
|
|
|
3966
4011
|
applyPreset,
|
|
3967
4012
|
setThemePresetById,
|
|
3968
4013
|
clearPreset,
|
|
4014
|
+
isUsingDefaultPreset,
|
|
3969
4015
|
availablePresets,
|
|
3970
4016
|
builtInPresets,
|
|
3971
4017
|
customPresets: normalizedCustomPresets
|
package/dist/index.mjs
CHANGED
|
@@ -3707,9 +3707,12 @@ function ThemeProvider({
|
|
|
3707
3707
|
}, [includeBuiltInPresets, customPresets]);
|
|
3708
3708
|
const builtInPresets = useMemo(() => includeBuiltInPresets ? tweakcnPresets : {}, [includeBuiltInPresets]);
|
|
3709
3709
|
const normalizedCustomPresets = useMemo(() => customPresets || {}, [customPresets]);
|
|
3710
|
-
const getAvailablePresetById = useCallback(
|
|
3711
|
-
|
|
3712
|
-
|
|
3710
|
+
const getAvailablePresetById = useCallback(
|
|
3711
|
+
(id) => {
|
|
3712
|
+
return availablePresets[id] || null;
|
|
3713
|
+
},
|
|
3714
|
+
[availablePresets]
|
|
3715
|
+
);
|
|
3713
3716
|
const [currentPreset, setCurrentPreset] = useState(null);
|
|
3714
3717
|
const [isReady, setIsReady] = useState(false);
|
|
3715
3718
|
useEffect(() => {
|
|
@@ -3719,10 +3722,9 @@ function ThemeProvider({
|
|
|
3719
3722
|
}
|
|
3720
3723
|
try {
|
|
3721
3724
|
const stored = localStorage.getItem(presetStorageKey);
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
} else if (defaultPreset) {
|
|
3725
|
+
const isDevelopment = typeof window !== "undefined" && window.location?.hostname === "localhost";
|
|
3726
|
+
const applyDefaultPreset = () => {
|
|
3727
|
+
if (!defaultPreset) return;
|
|
3726
3728
|
const preset = getAvailablePresetById(defaultPreset);
|
|
3727
3729
|
if (preset) {
|
|
3728
3730
|
const presetData = {
|
|
@@ -3738,13 +3740,42 @@ function ThemeProvider({
|
|
|
3738
3740
|
} else {
|
|
3739
3741
|
console.warn("\u{1F3A8} UnifiedTheme: Default preset not found:", defaultPreset);
|
|
3740
3742
|
}
|
|
3743
|
+
};
|
|
3744
|
+
if (stored) {
|
|
3745
|
+
try {
|
|
3746
|
+
const parsed = JSON.parse(stored);
|
|
3747
|
+
const isValidObject = parsed && typeof parsed === "object";
|
|
3748
|
+
const hasColors = isValidObject && "colors" in parsed && parsed.colors && typeof parsed.colors === "object" && parsed.colors.light && parsed.colors.dark;
|
|
3749
|
+
if (hasColors) {
|
|
3750
|
+
setCurrentPreset(parsed);
|
|
3751
|
+
if (isDevelopment) {
|
|
3752
|
+
}
|
|
3753
|
+
} else {
|
|
3754
|
+
if (isDevelopment) {
|
|
3755
|
+
console.warn("\u{1F3A8} UnifiedTheme: Invalid persisted preset shape. Clearing and falling back.");
|
|
3756
|
+
}
|
|
3757
|
+
localStorage.removeItem(presetStorageKey);
|
|
3758
|
+
applyDefaultPreset();
|
|
3759
|
+
}
|
|
3760
|
+
} catch (error) {
|
|
3761
|
+
if (isDevelopment) {
|
|
3762
|
+
console.warn("\u{1F3A8} UnifiedTheme: Failed to parse persisted preset. Clearing key.", error);
|
|
3763
|
+
}
|
|
3764
|
+
localStorage.removeItem(presetStorageKey);
|
|
3765
|
+
applyDefaultPreset();
|
|
3766
|
+
}
|
|
3767
|
+
} else {
|
|
3768
|
+
applyDefaultPreset();
|
|
3741
3769
|
}
|
|
3742
3770
|
} catch (error) {
|
|
3743
|
-
|
|
3771
|
+
const isDevelopment = typeof window !== "undefined" && window.location?.hostname === "localhost";
|
|
3772
|
+
if (isDevelopment) {
|
|
3773
|
+
console.warn("\u{1F3A8} UnifiedTheme: Failed to load preset from storage:", error);
|
|
3774
|
+
}
|
|
3744
3775
|
} finally {
|
|
3745
3776
|
setIsReady(true);
|
|
3746
3777
|
}
|
|
3747
|
-
}, [presetStorageKey, enablePresets, defaultPreset]);
|
|
3778
|
+
}, [presetStorageKey, enablePresets, defaultPreset, getAvailablePresetById]);
|
|
3748
3779
|
useEffect(() => {
|
|
3749
3780
|
if (mode === "system") {
|
|
3750
3781
|
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
@@ -3765,11 +3796,12 @@ function ThemeProvider({
|
|
|
3765
3796
|
root.style.colorScheme = resolvedMode;
|
|
3766
3797
|
}, [resolvedMode]);
|
|
3767
3798
|
const applyPresetColors = useCallback((preset, mode2) => {
|
|
3799
|
+
if (!preset) return;
|
|
3768
3800
|
const root = document.documentElement;
|
|
3769
3801
|
const colors = preset[mode2];
|
|
3770
3802
|
if (!colors) return;
|
|
3771
3803
|
const defaultValues = {
|
|
3772
|
-
|
|
3804
|
+
spacing: "0.25rem",
|
|
3773
3805
|
"letter-spacing": "normal"
|
|
3774
3806
|
};
|
|
3775
3807
|
const allCategories = [
|
|
@@ -3808,67 +3840,79 @@ function ThemeProvider({
|
|
|
3808
3840
|
}
|
|
3809
3841
|
});
|
|
3810
3842
|
}, []);
|
|
3811
|
-
const handleModeChange = useCallback(
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3843
|
+
const handleModeChange = useCallback(
|
|
3844
|
+
(newMode) => {
|
|
3845
|
+
setMode(newMode);
|
|
3846
|
+
setStoredMode(newMode, modeStorageKey);
|
|
3847
|
+
},
|
|
3848
|
+
[modeStorageKey]
|
|
3849
|
+
);
|
|
3850
|
+
const handleModeToggle = useCallback(
|
|
3851
|
+
(coordinates) => {
|
|
3852
|
+
const newMode = resolvedMode === "light" ? "dark" : "light";
|
|
3853
|
+
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
3854
|
+
if (enableTransitions && !prefersReducedMotion && typeof document !== "undefined" && "startViewTransition" in document) {
|
|
3855
|
+
const root = document.documentElement;
|
|
3856
|
+
if (coordinates) {
|
|
3857
|
+
root.style.setProperty("--x", `${coordinates.x}px`);
|
|
3858
|
+
root.style.setProperty("--y", `${coordinates.y}px`);
|
|
3859
|
+
}
|
|
3860
|
+
document.startViewTransition(() => {
|
|
3861
|
+
handleModeChange(newMode);
|
|
3862
|
+
});
|
|
3863
|
+
} else {
|
|
3825
3864
|
handleModeChange(newMode);
|
|
3826
|
-
}
|
|
3827
|
-
}
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
}, [resolvedMode, enableTransitions, handleModeChange]);
|
|
3865
|
+
}
|
|
3866
|
+
},
|
|
3867
|
+
[resolvedMode, enableTransitions, handleModeChange]
|
|
3868
|
+
);
|
|
3831
3869
|
useEffect(() => {
|
|
3832
3870
|
if (!currentPreset || typeof window === "undefined") return;
|
|
3833
3871
|
applyPresetColors(currentPreset.colors, resolvedMode);
|
|
3834
3872
|
}, [currentPreset, resolvedMode, applyPresetColors]);
|
|
3835
|
-
const applyPreset = useCallback(
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3873
|
+
const applyPreset = useCallback(
|
|
3874
|
+
(preset) => {
|
|
3875
|
+
const presetData = {
|
|
3876
|
+
presetId: preset.id,
|
|
3877
|
+
presetName: preset.name,
|
|
3878
|
+
colors: preset.colors,
|
|
3879
|
+
appliedAt: Date.now()
|
|
3880
|
+
};
|
|
3881
|
+
setCurrentPreset(presetData);
|
|
3882
|
+
if (enablePresets && typeof window !== "undefined") {
|
|
3883
|
+
try {
|
|
3884
|
+
localStorage.setItem(presetStorageKey, JSON.stringify(presetData));
|
|
3885
|
+
} catch (error) {
|
|
3886
|
+
console.error("\u{1F3A8} UnifiedTheme: Failed to save preset:", error);
|
|
3887
|
+
}
|
|
3848
3888
|
}
|
|
3849
|
-
}
|
|
3850
|
-
if (typeof window !== "undefined") {
|
|
3851
|
-
applyPresetColors(preset.colors, resolvedMode);
|
|
3852
|
-
}
|
|
3853
|
-
}, [presetStorageKey, enablePresets, applyPresetColors, resolvedMode]);
|
|
3854
|
-
const setThemePresetById = useCallback((presetId) => {
|
|
3855
|
-
const preset = getAvailablePresetById(presetId);
|
|
3856
|
-
if (!preset) {
|
|
3857
3889
|
if (typeof window !== "undefined") {
|
|
3858
|
-
|
|
3890
|
+
applyPresetColors(preset.colors, resolvedMode);
|
|
3859
3891
|
}
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3892
|
+
},
|
|
3893
|
+
[presetStorageKey, enablePresets, applyPresetColors, resolvedMode]
|
|
3894
|
+
);
|
|
3895
|
+
const setThemePresetById = useCallback(
|
|
3896
|
+
(presetId) => {
|
|
3897
|
+
const preset = getAvailablePresetById(presetId);
|
|
3898
|
+
if (!preset) {
|
|
3899
|
+
if (typeof window !== "undefined") {
|
|
3900
|
+
console.warn("\u{1F3A8} UnifiedTheme: Preset not found for id:", presetId);
|
|
3901
|
+
}
|
|
3902
|
+
return;
|
|
3868
3903
|
}
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3904
|
+
const presetData = {
|
|
3905
|
+
id: presetId,
|
|
3906
|
+
name: preset.label,
|
|
3907
|
+
colors: {
|
|
3908
|
+
light: preset.styles.light,
|
|
3909
|
+
dark: preset.styles.dark
|
|
3910
|
+
}
|
|
3911
|
+
};
|
|
3912
|
+
applyPreset(presetData);
|
|
3913
|
+
},
|
|
3914
|
+
[getAvailablePresetById, applyPreset]
|
|
3915
|
+
);
|
|
3872
3916
|
const clearPreset = useCallback(() => {
|
|
3873
3917
|
if (enablePresets && typeof window !== "undefined") {
|
|
3874
3918
|
try {
|
|
@@ -3916,6 +3960,7 @@ function ThemeProvider({
|
|
|
3916
3960
|
if (!isReady) {
|
|
3917
3961
|
return null;
|
|
3918
3962
|
}
|
|
3963
|
+
const isUsingDefaultPreset = !!defaultPreset && currentPreset?.presetId === defaultPreset;
|
|
3919
3964
|
const contextValue = {
|
|
3920
3965
|
mode,
|
|
3921
3966
|
resolvedMode,
|
|
@@ -3925,6 +3970,7 @@ function ThemeProvider({
|
|
|
3925
3970
|
applyPreset,
|
|
3926
3971
|
setThemePresetById,
|
|
3927
3972
|
clearPreset,
|
|
3973
|
+
isUsingDefaultPreset,
|
|
3928
3974
|
availablePresets,
|
|
3929
3975
|
builtInPresets,
|
|
3930
3976
|
customPresets: normalizedCustomPresets
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fakhrirafiki/theme-engine",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Elegant theming system with smooth transitions, custom presets, semantic accent colors, and complete shadcn/ui support for modern React applications",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|