@work-rjkashyap/unified-ui 0.1.2 → 0.2.0
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/CHANGELOG.md +93 -0
- package/bin/cli.mjs +721 -0
- package/dist/{chunk-EO4WROWH.mjs → chunk-3OZJ4JLW.mjs} +116 -2
- package/dist/chunk-B3CW2WZS.cjs +20748 -0
- package/dist/chunk-CTWNFFLB.mjs +20438 -0
- package/dist/{chunk-7ITQSRGX.cjs → chunk-FUWXGHWQ.cjs} +0 -1
- package/dist/{chunk-ZPIPKY2J.cjs → chunk-HITTFB2U.cjs} +127 -1
- package/dist/{chunk-F5S6NLOT.mjs → chunk-OHEH57BV.mjs} +0 -1
- package/dist/{chunk-PQR7C4OH.cjs → chunk-TESKVASH.cjs} +332 -99
- package/dist/{chunk-ZDB557B2.mjs → chunk-YFH5JPAA.mjs} +331 -101
- package/dist/components.cjs +780 -126
- package/dist/components.d.cts +5183 -1464
- package/dist/components.d.ts +5183 -1464
- package/dist/components.mjs +3 -1
- package/dist/index.cjs +926 -214
- package/dist/index.d.cts +9 -6
- package/dist/index.d.ts +9 -6
- package/dist/index.mjs +5 -5
- package/dist/motion.cjs +94 -46
- package/dist/motion.d.cts +53 -2
- package/dist/motion.d.ts +53 -2
- package/dist/motion.mjs +1 -1
- package/dist/primitives.cjs +13 -13
- package/dist/primitives.mjs +1 -1
- package/dist/theme.cjs +40 -28
- package/dist/theme.d.cts +100 -62
- package/dist/theme.d.ts +100 -62
- package/dist/theme.mjs +1 -1
- package/dist/utils.d.cts +1 -1
- package/dist/utils.d.ts +1 -1
- package/package.json +190 -183
- package/styles.css +636 -473
- package/dist/chunk-4NYLE2LT.cjs +0 -10042
- package/dist/chunk-A4YYJAAJ.mjs +0 -9897
|
@@ -2,7 +2,7 @@ import { blue, red, amber, green, zinc, slate, gray, teal, brand, zIndex, shadow
|
|
|
2
2
|
import { fontFamily } from './chunk-ITBG42M5.mjs';
|
|
3
3
|
import { easingCSS, durationCSS } from './chunk-EZ2L3XPS.mjs';
|
|
4
4
|
import { cn } from './chunk-ZT3PCXDF.mjs';
|
|
5
|
-
import { createContext, useContext, useState,
|
|
5
|
+
import { createContext, useContext, useState, useRef, useEffect, useCallback, useMemo } from 'react';
|
|
6
6
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
7
|
|
|
8
8
|
// src/theme/contract.ts
|
|
@@ -210,96 +210,6 @@ var cssVar = {
|
|
|
210
210
|
/** Returns the raw `var(--<key>)` — same as color() since values are complete oklch */
|
|
211
211
|
colorChannels: (key) => `var(${colorVarNames[key]})`
|
|
212
212
|
};
|
|
213
|
-
var DSThemeContext = createContext(null);
|
|
214
|
-
function useDSTheme() {
|
|
215
|
-
const ctx = useContext(DSThemeContext);
|
|
216
|
-
if (!ctx) {
|
|
217
|
-
throw new Error(
|
|
218
|
-
"useDSTheme must be used within a <DSThemeProvider>. Wrap your application (or layout) with <DSThemeProvider>."
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
return ctx;
|
|
222
|
-
}
|
|
223
|
-
function getSystemPreference() {
|
|
224
|
-
if (typeof window === "undefined") return "light";
|
|
225
|
-
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
226
|
-
}
|
|
227
|
-
function resolveTheme(theme) {
|
|
228
|
-
if (theme === "system") return getSystemPreference();
|
|
229
|
-
return theme;
|
|
230
|
-
}
|
|
231
|
-
var STORAGE_KEY = "ds-theme-preference";
|
|
232
|
-
function getStoredTheme() {
|
|
233
|
-
if (typeof window === "undefined") return "system";
|
|
234
|
-
try {
|
|
235
|
-
const stored = localStorage.getItem(STORAGE_KEY);
|
|
236
|
-
if (stored === "light" || stored === "dark" || stored === "system") {
|
|
237
|
-
return stored;
|
|
238
|
-
}
|
|
239
|
-
} catch {
|
|
240
|
-
}
|
|
241
|
-
return "system";
|
|
242
|
-
}
|
|
243
|
-
function storeTheme(theme) {
|
|
244
|
-
try {
|
|
245
|
-
localStorage.setItem(STORAGE_KEY, theme);
|
|
246
|
-
} catch {
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
function DSThemeProvider({
|
|
250
|
-
children,
|
|
251
|
-
defaultTheme,
|
|
252
|
-
manageHtmlClass = false
|
|
253
|
-
}) {
|
|
254
|
-
const [theme, setThemeState] = useState(
|
|
255
|
-
() => defaultTheme ?? getStoredTheme()
|
|
256
|
-
);
|
|
257
|
-
const [systemPreference, setSystemPreference] = useState("light");
|
|
258
|
-
useEffect(() => {
|
|
259
|
-
setSystemPreference(getSystemPreference());
|
|
260
|
-
const mql = window.matchMedia("(prefers-color-scheme: dark)");
|
|
261
|
-
const handler = (e) => {
|
|
262
|
-
setSystemPreference(e.matches ? "dark" : "light");
|
|
263
|
-
};
|
|
264
|
-
mql.addEventListener("change", handler);
|
|
265
|
-
return () => mql.removeEventListener("change", handler);
|
|
266
|
-
}, []);
|
|
267
|
-
const resolvedTheme = useMemo(
|
|
268
|
-
() => theme === "system" ? systemPreference : theme,
|
|
269
|
-
[theme, systemPreference]
|
|
270
|
-
);
|
|
271
|
-
useEffect(() => {
|
|
272
|
-
if (!manageHtmlClass) return;
|
|
273
|
-
const root = document.documentElement;
|
|
274
|
-
if (resolvedTheme === "dark") {
|
|
275
|
-
root.classList.add("dark");
|
|
276
|
-
} else {
|
|
277
|
-
root.classList.remove("dark");
|
|
278
|
-
}
|
|
279
|
-
}, [resolvedTheme, manageHtmlClass]);
|
|
280
|
-
const setTheme = useCallback((newTheme) => {
|
|
281
|
-
setThemeState(newTheme);
|
|
282
|
-
storeTheme(newTheme);
|
|
283
|
-
}, []);
|
|
284
|
-
const toggleTheme = useCallback(() => {
|
|
285
|
-
setThemeState((current) => {
|
|
286
|
-
const resolved = resolveTheme(current);
|
|
287
|
-
const next = resolved === "dark" ? "light" : "dark";
|
|
288
|
-
storeTheme(next);
|
|
289
|
-
return next;
|
|
290
|
-
});
|
|
291
|
-
}, []);
|
|
292
|
-
const value = useMemo(
|
|
293
|
-
() => ({
|
|
294
|
-
theme,
|
|
295
|
-
resolvedTheme,
|
|
296
|
-
setTheme,
|
|
297
|
-
toggleTheme
|
|
298
|
-
}),
|
|
299
|
-
[theme, resolvedTheme, setTheme, toggleTheme]
|
|
300
|
-
);
|
|
301
|
-
return /* @__PURE__ */ jsx(DSThemeContext.Provider, { value, children });
|
|
302
|
-
}
|
|
303
213
|
|
|
304
214
|
// src/theme/presets.ts
|
|
305
215
|
var STATUS_LIGHT = {
|
|
@@ -839,7 +749,119 @@ var SURFACE_STYLE_PRESETS = [
|
|
|
839
749
|
}
|
|
840
750
|
];
|
|
841
751
|
var DEFAULT_SURFACE_STYLE_KEY = "bordered";
|
|
752
|
+
var STYLE_PRESETS = [
|
|
753
|
+
{
|
|
754
|
+
name: "Vega",
|
|
755
|
+
key: "vega",
|
|
756
|
+
description: "The classic shadcn/ui look. Clean, neutral, and familiar.",
|
|
757
|
+
iconPath: "M3 3h18v18H3V3zm2 2v14h14V5H7z",
|
|
758
|
+
defaults: {
|
|
759
|
+
radius: "0.625",
|
|
760
|
+
font: "outfit",
|
|
761
|
+
shadow: "default",
|
|
762
|
+
surfaceStyle: "bordered"
|
|
763
|
+
},
|
|
764
|
+
vars: {
|
|
765
|
+
spacingUnit: "1",
|
|
766
|
+
paddingCard: "1.5rem",
|
|
767
|
+
paddingButtonX: "1rem",
|
|
768
|
+
paddingButtonY: "0.5rem",
|
|
769
|
+
gapDefault: "0.75rem",
|
|
770
|
+
borderWidth: "1px",
|
|
771
|
+
controlHeight: "2.25rem"
|
|
772
|
+
}
|
|
773
|
+
},
|
|
774
|
+
{
|
|
775
|
+
name: "Nova",
|
|
776
|
+
key: "nova",
|
|
777
|
+
description: "Reduced padding and margins for compact layouts.",
|
|
778
|
+
iconPath: "M4 4h16v16H4V4zm1.5 1.5v13h13v-13h-13z",
|
|
779
|
+
defaults: {
|
|
780
|
+
radius: "0.5",
|
|
781
|
+
font: "inter",
|
|
782
|
+
shadow: "subtle",
|
|
783
|
+
surfaceStyle: "bordered"
|
|
784
|
+
},
|
|
785
|
+
vars: {
|
|
786
|
+
spacingUnit: "0.875",
|
|
787
|
+
paddingCard: "1rem",
|
|
788
|
+
paddingButtonX: "0.75rem",
|
|
789
|
+
paddingButtonY: "0.375rem",
|
|
790
|
+
gapDefault: "0.5rem",
|
|
791
|
+
borderWidth: "1px",
|
|
792
|
+
controlHeight: "2rem"
|
|
793
|
+
}
|
|
794
|
+
},
|
|
795
|
+
{
|
|
796
|
+
name: "Maia",
|
|
797
|
+
key: "maia",
|
|
798
|
+
description: "Soft and rounded, with generous spacing.",
|
|
799
|
+
iconPath: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z",
|
|
800
|
+
defaults: {
|
|
801
|
+
radius: "0.75",
|
|
802
|
+
font: "outfit",
|
|
803
|
+
shadow: "default",
|
|
804
|
+
surfaceStyle: "mixed"
|
|
805
|
+
},
|
|
806
|
+
vars: {
|
|
807
|
+
spacingUnit: "1.125",
|
|
808
|
+
paddingCard: "1.75rem",
|
|
809
|
+
paddingButtonX: "1.25rem",
|
|
810
|
+
paddingButtonY: "0.625rem",
|
|
811
|
+
gapDefault: "1rem",
|
|
812
|
+
borderWidth: "1px",
|
|
813
|
+
controlHeight: "2.5rem"
|
|
814
|
+
}
|
|
815
|
+
},
|
|
816
|
+
{
|
|
817
|
+
name: "Lyra",
|
|
818
|
+
key: "lyra",
|
|
819
|
+
description: "Boxy and sharp. Pairs well with mono fonts.",
|
|
820
|
+
iconPath: "M3 3h18v18H3V3zm1 1v16h16V4H4z",
|
|
821
|
+
defaults: {
|
|
822
|
+
radius: "0",
|
|
823
|
+
font: "system",
|
|
824
|
+
shadow: "none",
|
|
825
|
+
surfaceStyle: "bordered"
|
|
826
|
+
},
|
|
827
|
+
vars: {
|
|
828
|
+
spacingUnit: "1",
|
|
829
|
+
paddingCard: "1.25rem",
|
|
830
|
+
paddingButtonX: "1rem",
|
|
831
|
+
paddingButtonY: "0.5rem",
|
|
832
|
+
gapDefault: "0.75rem",
|
|
833
|
+
borderWidth: "1px",
|
|
834
|
+
controlHeight: "2.25rem"
|
|
835
|
+
}
|
|
836
|
+
},
|
|
837
|
+
{
|
|
838
|
+
name: "Mira",
|
|
839
|
+
key: "mira",
|
|
840
|
+
description: "Compact. Made for dense interfaces.",
|
|
841
|
+
iconPath: "M5 3h14a2 2 0 012 2v14a2 2 0 01-2 2H5a2 2 0 01-2-2V5a2 2 0 012-2zm0 2v14h14V5H5zm2 2h10v2H7V7zm0 4h10v2H7v-2zm0 4h7v2H7v-2z",
|
|
842
|
+
defaults: {
|
|
843
|
+
radius: "0.375",
|
|
844
|
+
font: "inter",
|
|
845
|
+
shadow: "none",
|
|
846
|
+
surfaceStyle: "bordered"
|
|
847
|
+
},
|
|
848
|
+
vars: {
|
|
849
|
+
spacingUnit: "0.75",
|
|
850
|
+
paddingCard: "0.75rem",
|
|
851
|
+
paddingButtonX: "0.625rem",
|
|
852
|
+
paddingButtonY: "0.25rem",
|
|
853
|
+
gapDefault: "0.375rem",
|
|
854
|
+
borderWidth: "1px",
|
|
855
|
+
controlHeight: "1.75rem"
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
];
|
|
859
|
+
var DEFAULT_STYLE_KEY = "vega";
|
|
860
|
+
function getStylePreset(key) {
|
|
861
|
+
return STYLE_PRESETS.find((s) => s.key === key) ?? STYLE_PRESETS[0];
|
|
862
|
+
}
|
|
842
863
|
var DEFAULT_THEME_CONFIG = {
|
|
864
|
+
style: DEFAULT_STYLE_KEY,
|
|
843
865
|
colorPreset: "zinc",
|
|
844
866
|
radius: DEFAULT_RADIUS_KEY,
|
|
845
867
|
font: DEFAULT_FONT_KEY,
|
|
@@ -925,7 +947,15 @@ function buildThemeOverrides(config, mode) {
|
|
|
925
947
|
}
|
|
926
948
|
}
|
|
927
949
|
const radiusPreset = getRadiusPreset(config.radius);
|
|
950
|
+
const baseRem = Number.parseFloat(radiusPreset.value);
|
|
951
|
+
const isZero = radiusPreset.key === "0";
|
|
928
952
|
vars["--radius"] = radiusPreset.value;
|
|
953
|
+
vars["--radius-none"] = "0px";
|
|
954
|
+
vars["--radius-sm"] = isZero ? "0px" : `${Math.max(baseRem * 0.4, 0.125)}rem`;
|
|
955
|
+
vars["--radius-md"] = isZero ? "0px" : `${Math.max(baseRem * 0.6, 0.25)}rem`;
|
|
956
|
+
vars["--radius-lg"] = isZero ? "0px" : `${Math.max(baseRem * 0.8, 0.375)}rem`;
|
|
957
|
+
vars["--radius-xl"] = isZero ? "0px" : `${Math.max(baseRem * 1.2, 0.5)}rem`;
|
|
958
|
+
vars["--radius-full"] = "9999px";
|
|
929
959
|
const fontPreset = getFontPreset(config.font);
|
|
930
960
|
vars["--font-sans"] = fontPreset.value;
|
|
931
961
|
const shadowPreset = getShadowPreset(config.shadow);
|
|
@@ -937,6 +967,23 @@ function buildThemeOverrides(config, mode) {
|
|
|
937
967
|
vars["--shadow-lg"] = shadows.lg;
|
|
938
968
|
vars["--shadow-xl"] = shadows.xl;
|
|
939
969
|
vars["--shadow-2xl"] = shadows["2xl"];
|
|
970
|
+
const stylePreset = getStylePreset(config.style);
|
|
971
|
+
const sv = stylePreset.vars;
|
|
972
|
+
vars["--ds-spacing-unit"] = sv.spacingUnit;
|
|
973
|
+
vars["--ds-padding-card"] = sv.paddingCard;
|
|
974
|
+
vars["--ds-padding-button-x"] = sv.paddingButtonX;
|
|
975
|
+
vars["--ds-padding-button-y"] = sv.paddingButtonY;
|
|
976
|
+
vars["--ds-gap-default"] = sv.gapDefault;
|
|
977
|
+
vars["--ds-border-width"] = sv.borderWidth;
|
|
978
|
+
vars["--ds-control-height"] = sv.controlHeight;
|
|
979
|
+
if (config.surfaceStyle === "elevated") {
|
|
980
|
+
vars["--card"] = mode === "dark" ? "oklch(0.205 0 0)" : "oklch(1 0 0)";
|
|
981
|
+
vars["--border"] = mode === "dark" ? "oklch(0.205 0 0 / 0)" : "oklch(0.922 0 0 / 0)";
|
|
982
|
+
vars["--border-muted"] = mode === "dark" ? "oklch(0.205 0 0 / 0)" : "oklch(0.922 0 0 / 0)";
|
|
983
|
+
} else if (config.surfaceStyle === "mixed") {
|
|
984
|
+
vars["--border"] = mode === "dark" ? "oklch(0.4 0 0 / 0.15)" : "oklch(0.8 0 0 / 0.3)";
|
|
985
|
+
vars["--border-muted"] = mode === "dark" ? "oklch(0.4 0 0 / 0.1)" : "oklch(0.85 0 0 / 0.25)";
|
|
986
|
+
}
|
|
940
987
|
return vars;
|
|
941
988
|
}
|
|
942
989
|
function generateThemeCSS(config) {
|
|
@@ -947,6 +994,7 @@ function generateThemeCSS(config) {
|
|
|
947
994
|
"/* ============================================",
|
|
948
995
|
" * Unified UI \u2014 Custom Theme",
|
|
949
996
|
` * Preset: ${getColorPreset(config.colorPreset).name}`,
|
|
997
|
+
` * Style: ${getStylePreset(config.style).name}`,
|
|
950
998
|
` * Radius: ${getRadiusPreset(config.radius).label}`,
|
|
951
999
|
` * Font: ${getFontPreset(config.font).name}`,
|
|
952
1000
|
` * Shadows: ${getShadowPreset(config.shadow).name}`,
|
|
@@ -961,7 +1009,7 @@ function generateThemeCSS(config) {
|
|
|
961
1009
|
"}"
|
|
962
1010
|
].join("\n");
|
|
963
1011
|
}
|
|
964
|
-
var
|
|
1012
|
+
var STORAGE_KEY = "ds-theme-customizer";
|
|
965
1013
|
var STYLE_ELEMENT_ID = "ds-theme-customizer";
|
|
966
1014
|
var ThemeCustomizerContext = createContext(null);
|
|
967
1015
|
function useThemeCustomizer() {
|
|
@@ -976,10 +1024,11 @@ function useThemeCustomizer() {
|
|
|
976
1024
|
function loadConfig() {
|
|
977
1025
|
if (typeof window === "undefined") return DEFAULT_THEME_CONFIG;
|
|
978
1026
|
try {
|
|
979
|
-
const raw = localStorage.getItem(
|
|
1027
|
+
const raw = localStorage.getItem(STORAGE_KEY);
|
|
980
1028
|
if (!raw) return DEFAULT_THEME_CONFIG;
|
|
981
1029
|
const parsed = JSON.parse(raw);
|
|
982
1030
|
return {
|
|
1031
|
+
style: STYLE_PRESETS.some((s) => s.key === parsed.style) ? parsed.style : DEFAULT_THEME_CONFIG.style,
|
|
983
1032
|
colorPreset: COLOR_PRESET_KEYS.includes(parsed.colorPreset ?? "") ? parsed.colorPreset : DEFAULT_THEME_CONFIG.colorPreset,
|
|
984
1033
|
radius: RADIUS_PRESETS.some((r) => r.key === parsed.radius) ? parsed.radius : DEFAULT_THEME_CONFIG.radius,
|
|
985
1034
|
font: FONT_PRESETS.some((f) => f.key === parsed.font) ? parsed.font : DEFAULT_THEME_CONFIG.font,
|
|
@@ -995,7 +1044,7 @@ function loadConfig() {
|
|
|
995
1044
|
function saveConfig(config) {
|
|
996
1045
|
if (typeof window === "undefined") return;
|
|
997
1046
|
try {
|
|
998
|
-
localStorage.setItem(
|
|
1047
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify(config));
|
|
999
1048
|
} catch {
|
|
1000
1049
|
}
|
|
1001
1050
|
}
|
|
@@ -1005,7 +1054,9 @@ function getResolvedMode() {
|
|
|
1005
1054
|
}
|
|
1006
1055
|
function injectStyles(config) {
|
|
1007
1056
|
if (typeof document === "undefined") return;
|
|
1008
|
-
let styleEl = document.getElementById(
|
|
1057
|
+
let styleEl = document.getElementById(
|
|
1058
|
+
STYLE_ELEMENT_ID
|
|
1059
|
+
);
|
|
1009
1060
|
if (!styleEl) {
|
|
1010
1061
|
styleEl = document.createElement("style");
|
|
1011
1062
|
styleEl.id = STYLE_ELEMENT_ID;
|
|
@@ -1028,7 +1079,7 @@ function removeStyles() {
|
|
|
1028
1079
|
}
|
|
1029
1080
|
}
|
|
1030
1081
|
function configsEqual(a, b) {
|
|
1031
|
-
return a.colorPreset === b.colorPreset && a.radius === b.radius && a.font === b.font && a.shadow === b.shadow && a.surfaceStyle === b.surfaceStyle;
|
|
1082
|
+
return a.style === b.style && a.colorPreset === b.colorPreset && a.radius === b.radius && a.font === b.font && a.shadow === b.shadow && a.surfaceStyle === b.surfaceStyle;
|
|
1032
1083
|
}
|
|
1033
1084
|
function ThemeCustomizerProvider({
|
|
1034
1085
|
children,
|
|
@@ -1038,7 +1089,7 @@ function ThemeCustomizerProvider({
|
|
|
1038
1089
|
const [config, setConfigState] = useState(
|
|
1039
1090
|
() => defaultConfig ?? loadConfig()
|
|
1040
1091
|
);
|
|
1041
|
-
const [
|
|
1092
|
+
const [_resolvedMode, setResolvedMode] = useState("light");
|
|
1042
1093
|
const configRef = useRef(config);
|
|
1043
1094
|
configRef.current = config;
|
|
1044
1095
|
useEffect(() => {
|
|
@@ -1060,7 +1111,7 @@ function ThemeCustomizerProvider({
|
|
|
1060
1111
|
if (applyStyles) {
|
|
1061
1112
|
injectStyles(config);
|
|
1062
1113
|
}
|
|
1063
|
-
}, [config,
|
|
1114
|
+
}, [config, applyStyles]);
|
|
1064
1115
|
useEffect(() => {
|
|
1065
1116
|
saveConfig(config);
|
|
1066
1117
|
}, [config]);
|
|
@@ -1073,7 +1124,7 @@ function ThemeCustomizerProvider({
|
|
|
1073
1124
|
}, [applyStyles]);
|
|
1074
1125
|
useEffect(() => {
|
|
1075
1126
|
const handleStorage = (e) => {
|
|
1076
|
-
if (e.key ===
|
|
1127
|
+
if (e.key === STORAGE_KEY && e.newValue) {
|
|
1077
1128
|
try {
|
|
1078
1129
|
const parsed = JSON.parse(e.newValue);
|
|
1079
1130
|
setConfigState((prev) => {
|
|
@@ -1090,6 +1141,20 @@ function ThemeCustomizerProvider({
|
|
|
1090
1141
|
const setConfig = useCallback((newConfig) => {
|
|
1091
1142
|
setConfigState(newConfig);
|
|
1092
1143
|
}, []);
|
|
1144
|
+
const setStyle = useCallback((key) => {
|
|
1145
|
+
const preset = getStylePreset(key);
|
|
1146
|
+
setConfigState((prev) => {
|
|
1147
|
+
if (prev.style === key) return prev;
|
|
1148
|
+
return {
|
|
1149
|
+
...prev,
|
|
1150
|
+
style: key,
|
|
1151
|
+
radius: preset.defaults.radius,
|
|
1152
|
+
font: preset.defaults.font,
|
|
1153
|
+
shadow: preset.defaults.shadow,
|
|
1154
|
+
surfaceStyle: preset.defaults.surfaceStyle
|
|
1155
|
+
};
|
|
1156
|
+
});
|
|
1157
|
+
}, []);
|
|
1093
1158
|
const setColorPreset = useCallback((key) => {
|
|
1094
1159
|
setConfigState((prev) => {
|
|
1095
1160
|
if (prev.colorPreset === key) return prev;
|
|
@@ -1131,6 +1196,7 @@ function ThemeCustomizerProvider({
|
|
|
1131
1196
|
() => ({
|
|
1132
1197
|
config,
|
|
1133
1198
|
setConfig,
|
|
1199
|
+
setStyle,
|
|
1134
1200
|
setColorPreset,
|
|
1135
1201
|
setRadius,
|
|
1136
1202
|
setFont,
|
|
@@ -1143,6 +1209,7 @@ function ThemeCustomizerProvider({
|
|
|
1143
1209
|
[
|
|
1144
1210
|
config,
|
|
1145
1211
|
setConfig,
|
|
1212
|
+
setStyle,
|
|
1146
1213
|
setColorPreset,
|
|
1147
1214
|
setRadius,
|
|
1148
1215
|
setFont,
|
|
@@ -1242,7 +1309,7 @@ function RadiusOption({
|
|
|
1242
1309
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
1243
1310
|
isActive ? "border-primary bg-muted/60 shadow-sm" : "border-border bg-transparent"
|
|
1244
1311
|
),
|
|
1245
|
-
title: preset.name
|
|
1312
|
+
title: `${preset.name} (${preset.label})`,
|
|
1246
1313
|
children: [
|
|
1247
1314
|
/* @__PURE__ */ jsx(
|
|
1248
1315
|
"span",
|
|
@@ -1332,6 +1399,69 @@ function PillToggle({
|
|
|
1332
1399
|
}
|
|
1333
1400
|
);
|
|
1334
1401
|
}
|
|
1402
|
+
function StyleOption({
|
|
1403
|
+
preset,
|
|
1404
|
+
isActive,
|
|
1405
|
+
onClick
|
|
1406
|
+
}) {
|
|
1407
|
+
return /* @__PURE__ */ jsxs(
|
|
1408
|
+
"button",
|
|
1409
|
+
{
|
|
1410
|
+
type: "button",
|
|
1411
|
+
onClick,
|
|
1412
|
+
className: cn(
|
|
1413
|
+
"flex items-start gap-3 rounded-md border px-3 py-3 text-left transition-all duration-fast ease-standard",
|
|
1414
|
+
"hover:border-border-strong hover:bg-muted/50",
|
|
1415
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
1416
|
+
isActive ? "border-primary bg-muted/60 shadow-sm" : "border-border bg-transparent"
|
|
1417
|
+
),
|
|
1418
|
+
title: preset.description,
|
|
1419
|
+
children: [
|
|
1420
|
+
/* @__PURE__ */ jsx(
|
|
1421
|
+
"svg",
|
|
1422
|
+
{
|
|
1423
|
+
className: cn(
|
|
1424
|
+
"size-5 shrink-0 mt-0.5",
|
|
1425
|
+
isActive ? "text-primary" : "text-muted-foreground"
|
|
1426
|
+
),
|
|
1427
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1428
|
+
viewBox: "0 0 24 24",
|
|
1429
|
+
fill: "none",
|
|
1430
|
+
stroke: "currentColor",
|
|
1431
|
+
strokeWidth: "1.5",
|
|
1432
|
+
strokeLinecap: "round",
|
|
1433
|
+
strokeLinejoin: "round",
|
|
1434
|
+
"aria-hidden": "true",
|
|
1435
|
+
children: /* @__PURE__ */ jsx("path", { d: preset.iconPath })
|
|
1436
|
+
}
|
|
1437
|
+
),
|
|
1438
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1439
|
+
/* @__PURE__ */ jsx(
|
|
1440
|
+
"div",
|
|
1441
|
+
{
|
|
1442
|
+
className: cn(
|
|
1443
|
+
"text-sm font-semibold leading-tight",
|
|
1444
|
+
isActive ? "text-foreground" : "text-foreground"
|
|
1445
|
+
),
|
|
1446
|
+
children: preset.name
|
|
1447
|
+
}
|
|
1448
|
+
),
|
|
1449
|
+
/* @__PURE__ */ jsx(
|
|
1450
|
+
"div",
|
|
1451
|
+
{
|
|
1452
|
+
className: cn(
|
|
1453
|
+
"mt-0.5 text-xs leading-snug",
|
|
1454
|
+
isActive ? "text-muted-foreground" : "text-muted-foreground/70"
|
|
1455
|
+
),
|
|
1456
|
+
children: preset.description
|
|
1457
|
+
}
|
|
1458
|
+
)
|
|
1459
|
+
] }),
|
|
1460
|
+
isActive && /* @__PURE__ */ jsx(CheckIcon, { className: "shrink-0 mt-0.5 text-primary" })
|
|
1461
|
+
]
|
|
1462
|
+
}
|
|
1463
|
+
);
|
|
1464
|
+
}
|
|
1335
1465
|
function CopyButton({
|
|
1336
1466
|
getText,
|
|
1337
1467
|
className,
|
|
@@ -1397,6 +1527,7 @@ function ThemeCustomizer({
|
|
|
1397
1527
|
}) {
|
|
1398
1528
|
const {
|
|
1399
1529
|
config,
|
|
1530
|
+
setStyle,
|
|
1400
1531
|
setColorPreset,
|
|
1401
1532
|
setRadius,
|
|
1402
1533
|
setFont,
|
|
@@ -1413,6 +1544,15 @@ function ThemeCustomizer({
|
|
|
1413
1544
|
"data-ds": "",
|
|
1414
1545
|
"data-ds-component": "theme-customizer",
|
|
1415
1546
|
children: [
|
|
1547
|
+
/* @__PURE__ */ jsx(Section, { title: "Style", children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-2", children: STYLE_PRESETS.map((preset) => /* @__PURE__ */ jsx(
|
|
1548
|
+
StyleOption,
|
|
1549
|
+
{
|
|
1550
|
+
preset,
|
|
1551
|
+
isActive: config.style === preset.key,
|
|
1552
|
+
onClick: () => setStyle(preset.key)
|
|
1553
|
+
},
|
|
1554
|
+
preset.key
|
|
1555
|
+
)) }) }),
|
|
1416
1556
|
/* @__PURE__ */ jsx(Section, { title: "Color", children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-2", children: COLOR_PRESETS.map((preset) => /* @__PURE__ */ jsx(
|
|
1417
1557
|
ColorSwatch,
|
|
1418
1558
|
{
|
|
@@ -1501,5 +1641,95 @@ function ThemeCustomizer({
|
|
|
1501
1641
|
);
|
|
1502
1642
|
}
|
|
1503
1643
|
ThemeCustomizer.displayName = "ThemeCustomizer";
|
|
1644
|
+
var DSThemeContext = createContext(null);
|
|
1645
|
+
function useDSTheme() {
|
|
1646
|
+
const ctx = useContext(DSThemeContext);
|
|
1647
|
+
if (!ctx) {
|
|
1648
|
+
throw new Error(
|
|
1649
|
+
"useDSTheme must be used within a <DSThemeProvider>. Wrap your application (or layout) with <DSThemeProvider>."
|
|
1650
|
+
);
|
|
1651
|
+
}
|
|
1652
|
+
return ctx;
|
|
1653
|
+
}
|
|
1654
|
+
function getSystemPreference() {
|
|
1655
|
+
if (typeof window === "undefined") return "light";
|
|
1656
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
1657
|
+
}
|
|
1658
|
+
function resolveTheme(theme) {
|
|
1659
|
+
if (theme === "system") return getSystemPreference();
|
|
1660
|
+
return theme;
|
|
1661
|
+
}
|
|
1662
|
+
var STORAGE_KEY2 = "ds-theme-preference";
|
|
1663
|
+
function getStoredTheme() {
|
|
1664
|
+
if (typeof window === "undefined") return "system";
|
|
1665
|
+
try {
|
|
1666
|
+
const stored = localStorage.getItem(STORAGE_KEY2);
|
|
1667
|
+
if (stored === "light" || stored === "dark" || stored === "system") {
|
|
1668
|
+
return stored;
|
|
1669
|
+
}
|
|
1670
|
+
} catch {
|
|
1671
|
+
}
|
|
1672
|
+
return "system";
|
|
1673
|
+
}
|
|
1674
|
+
function storeTheme(theme) {
|
|
1675
|
+
try {
|
|
1676
|
+
localStorage.setItem(STORAGE_KEY2, theme);
|
|
1677
|
+
} catch {
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
function DSThemeProvider({
|
|
1681
|
+
children,
|
|
1682
|
+
defaultTheme,
|
|
1683
|
+
manageHtmlClass = false
|
|
1684
|
+
}) {
|
|
1685
|
+
const [theme, setThemeState] = useState(
|
|
1686
|
+
() => defaultTheme ?? getStoredTheme()
|
|
1687
|
+
);
|
|
1688
|
+
const [systemPreference, setSystemPreference] = useState("light");
|
|
1689
|
+
useEffect(() => {
|
|
1690
|
+
setSystemPreference(getSystemPreference());
|
|
1691
|
+
const mql = window.matchMedia("(prefers-color-scheme: dark)");
|
|
1692
|
+
const handler = (e) => {
|
|
1693
|
+
setSystemPreference(e.matches ? "dark" : "light");
|
|
1694
|
+
};
|
|
1695
|
+
mql.addEventListener("change", handler);
|
|
1696
|
+
return () => mql.removeEventListener("change", handler);
|
|
1697
|
+
}, []);
|
|
1698
|
+
const resolvedTheme = useMemo(
|
|
1699
|
+
() => theme === "system" ? systemPreference : theme,
|
|
1700
|
+
[theme, systemPreference]
|
|
1701
|
+
);
|
|
1702
|
+
useEffect(() => {
|
|
1703
|
+
if (!manageHtmlClass) return;
|
|
1704
|
+
const root = document.documentElement;
|
|
1705
|
+
if (resolvedTheme === "dark") {
|
|
1706
|
+
root.classList.add("dark");
|
|
1707
|
+
} else {
|
|
1708
|
+
root.classList.remove("dark");
|
|
1709
|
+
}
|
|
1710
|
+
}, [resolvedTheme, manageHtmlClass]);
|
|
1711
|
+
const setTheme = useCallback((newTheme) => {
|
|
1712
|
+
setThemeState(newTheme);
|
|
1713
|
+
storeTheme(newTheme);
|
|
1714
|
+
}, []);
|
|
1715
|
+
const toggleTheme = useCallback(() => {
|
|
1716
|
+
setThemeState((current) => {
|
|
1717
|
+
const resolved = resolveTheme(current);
|
|
1718
|
+
const next = resolved === "dark" ? "light" : "dark";
|
|
1719
|
+
storeTheme(next);
|
|
1720
|
+
return next;
|
|
1721
|
+
});
|
|
1722
|
+
}, []);
|
|
1723
|
+
const value = useMemo(
|
|
1724
|
+
() => ({
|
|
1725
|
+
theme,
|
|
1726
|
+
resolvedTheme,
|
|
1727
|
+
setTheme,
|
|
1728
|
+
toggleTheme
|
|
1729
|
+
}),
|
|
1730
|
+
[theme, resolvedTheme, setTheme, toggleTheme]
|
|
1731
|
+
);
|
|
1732
|
+
return /* @__PURE__ */ jsx(DSThemeContext.Provider, { value, children });
|
|
1733
|
+
}
|
|
1504
1734
|
|
|
1505
|
-
export { COLOR_PRESETS, COLOR_PRESET_KEYS, DEFAULT_FONT_KEY, DEFAULT_RADIUS_KEY, DEFAULT_SHADOW_KEY, DEFAULT_SURFACE_STYLE_KEY, DEFAULT_THEME_CONFIG, DSThemeProvider, FONT_PRESETS, RADIUS_PRESETS, SHADOW_PRESETS, SURFACE_STYLE_PRESETS, ThemeCustomizer, ThemeCustomizerProvider, buildDarkThemeVars, buildLightThemeVars, buildThemeCSS, buildThemeOverrides, contract, cssVar, generateThemeCSS, getColorPreset, getFontPreset, getRadiusPreset, getShadowPreset, useDSTheme, useThemeCustomizer };
|
|
1735
|
+
export { COLOR_PRESETS, COLOR_PRESET_KEYS, DEFAULT_FONT_KEY, DEFAULT_RADIUS_KEY, DEFAULT_SHADOW_KEY, DEFAULT_STYLE_KEY, DEFAULT_SURFACE_STYLE_KEY, DEFAULT_THEME_CONFIG, DSThemeProvider, FONT_PRESETS, RADIUS_PRESETS, SHADOW_PRESETS, STYLE_PRESETS, SURFACE_STYLE_PRESETS, ThemeCustomizer, ThemeCustomizerProvider, buildDarkThemeVars, buildLightThemeVars, buildThemeCSS, buildThemeOverrides, contract, cssVar, generateThemeCSS, getColorPreset, getFontPreset, getRadiusPreset, getShadowPreset, getStylePreset, useDSTheme, useThemeCustomizer };
|