@12nil/theme-registry-package 0.1.0 → 0.1.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/README.md +91 -0
- package/bin/runtime-theme-registry.mjs +107 -0
- package/dist/app_theme-ED547XU4.js +7 -0
- package/dist/{chunk-GUPUN2GN.js → chunk-4HGH6QM7.js} +12 -1
- package/dist/chunk-4HGH6QM7.js.map +1 -0
- package/dist/index.cjs +240 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -3
- package/dist/index.d.ts +28 -3
- package/dist/index.js +228 -4
- package/dist/index.js.map +1 -1
- package/package.json +5 -1
- package/dist/app_theme-K3SQNO7I.js +0 -7
- package/dist/chunk-GUPUN2GN.js.map +0 -1
- /package/dist/{app_theme-K3SQNO7I.js.map → app_theme-ED547XU4.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -221,6 +221,16 @@ function tokenSetToCssVariables(tokens) {
|
|
|
221
221
|
variables[`--theme-${category}-${keyName}`] = value;
|
|
222
222
|
if (category === "colors") {
|
|
223
223
|
variables[`--color-theme-${keyName}`] = value;
|
|
224
|
+
variables[`--theme-${keyName}`] = value;
|
|
225
|
+
}
|
|
226
|
+
if (category === "surface") {
|
|
227
|
+
variables[`--surface-${keyName}`] = value;
|
|
228
|
+
}
|
|
229
|
+
if (category === "text") {
|
|
230
|
+
variables[`--text-${keyName}`] = value;
|
|
231
|
+
}
|
|
232
|
+
if (category === "border") {
|
|
233
|
+
variables[`--border-${keyName}`] = value;
|
|
224
234
|
}
|
|
225
235
|
});
|
|
226
236
|
};
|
|
@@ -233,6 +243,7 @@ function tokenSetToCssVariables(tokens) {
|
|
|
233
243
|
Object.entries(tokens).forEach(([key, value]) => {
|
|
234
244
|
if (key === "tertiary" && !value) return;
|
|
235
245
|
variables[`--color-theme-${key}`] = value;
|
|
246
|
+
variables[`--theme-${key}`] = value;
|
|
236
247
|
});
|
|
237
248
|
return variables;
|
|
238
249
|
}
|
|
@@ -767,7 +778,10 @@ var index_exports = {};
|
|
|
767
778
|
__export(index_exports, {
|
|
768
779
|
RUNTIME_THEME_REGISTRY_VERSION: () => RUNTIME_THEME_REGISTRY_VERSION,
|
|
769
780
|
ThemeProvider: () => ThemeProvider,
|
|
781
|
+
ThemeSwitcher: () => ThemeSwitcher,
|
|
782
|
+
ThemeSwitcherStyled: () => ThemeSwitcherStyled,
|
|
770
783
|
applyThemeToDocument: () => applyThemeToDocument,
|
|
784
|
+
createTailwindThemeColorMap: () => createTailwindThemeColorMap,
|
|
771
785
|
default: () => themeRegistry,
|
|
772
786
|
generateAllThemesCSS: () => generateAllThemesCSS,
|
|
773
787
|
generateThemeCSS: () => generateThemeCSS,
|
|
@@ -798,6 +812,16 @@ function semanticTokensToCSSVariables(tokens) {
|
|
|
798
812
|
variables[`--theme-${category}-${keyName}`] = value;
|
|
799
813
|
if (category === "colors") {
|
|
800
814
|
variables[`--color-theme-${keyName}`] = value;
|
|
815
|
+
variables[`--theme-${keyName}`] = value;
|
|
816
|
+
}
|
|
817
|
+
if (category === "surface") {
|
|
818
|
+
variables[`--surface-${keyName}`] = value;
|
|
819
|
+
}
|
|
820
|
+
if (category === "text") {
|
|
821
|
+
variables[`--text-${keyName}`] = value;
|
|
822
|
+
}
|
|
823
|
+
if (category === "border") {
|
|
824
|
+
variables[`--border-${keyName}`] = value;
|
|
801
825
|
}
|
|
802
826
|
});
|
|
803
827
|
};
|
|
@@ -812,7 +836,9 @@ function legacyTokensToCSSVariables(tokens) {
|
|
|
812
836
|
Object.entries(tokens).forEach(([key, value]) => {
|
|
813
837
|
if (key === "tertiary" && !value) return;
|
|
814
838
|
if (!value) return;
|
|
815
|
-
|
|
839
|
+
const keyName = String(key);
|
|
840
|
+
variables[`--color-theme-${keyName}`] = value;
|
|
841
|
+
variables[`--theme-${keyName}`] = value;
|
|
816
842
|
});
|
|
817
843
|
return variables;
|
|
818
844
|
}
|
|
@@ -853,15 +879,84 @@ function applyThemeToDocument(theme, mode) {
|
|
|
853
879
|
document.documentElement.style.setProperty(name, value);
|
|
854
880
|
});
|
|
855
881
|
}
|
|
882
|
+
function createTailwindThemeColorMap() {
|
|
883
|
+
return {
|
|
884
|
+
primary: "var(--theme-primary)",
|
|
885
|
+
secondary: "var(--theme-secondary)",
|
|
886
|
+
background: "var(--theme-background)",
|
|
887
|
+
text: "var(--theme-text)",
|
|
888
|
+
accent: "var(--theme-accent)",
|
|
889
|
+
muted: "var(--theme-muted)",
|
|
890
|
+
error: "var(--theme-error)",
|
|
891
|
+
warning: "var(--theme-warning)",
|
|
892
|
+
success: "var(--theme-success)",
|
|
893
|
+
info: "var(--theme-info)",
|
|
894
|
+
"surface-page": "var(--surface-page)",
|
|
895
|
+
"surface-card": "var(--surface-card)",
|
|
896
|
+
"surface-sidebar": "var(--surface-sidebar)",
|
|
897
|
+
"surface-modal": "var(--surface-modal)",
|
|
898
|
+
"surface-popover": "var(--surface-popover)",
|
|
899
|
+
"text-primary": "var(--text-primary)",
|
|
900
|
+
"text-secondary": "var(--text-secondary)",
|
|
901
|
+
"text-tertiary": "var(--text-tertiary)",
|
|
902
|
+
"text-disabled": "var(--text-disabled)",
|
|
903
|
+
"border-default": "var(--border-default)",
|
|
904
|
+
"border-subtle": "var(--border-subtle)",
|
|
905
|
+
"border-strong": "var(--border-strong)"
|
|
906
|
+
};
|
|
907
|
+
}
|
|
856
908
|
|
|
857
909
|
// theme-provider.tsx
|
|
858
910
|
init_app_theme();
|
|
859
911
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
912
|
+
var THEME_UTILITY_STYLE_ID = "runtime-theme-registry-utility-classes";
|
|
913
|
+
var THEME_UTILITY_CSS = `
|
|
914
|
+
.bg-primary{background-color:var(--theme-primary)!important}
|
|
915
|
+
.bg-secondary{background-color:var(--theme-secondary)!important}
|
|
916
|
+
.bg-background{background-color:var(--theme-background)!important}
|
|
917
|
+
.bg-accent{background-color:var(--theme-accent)!important}
|
|
918
|
+
.bg-muted{background-color:var(--theme-muted)!important}
|
|
919
|
+
.bg-error{background-color:var(--theme-error)!important}
|
|
920
|
+
.bg-warning{background-color:var(--theme-warning)!important}
|
|
921
|
+
.bg-success{background-color:var(--theme-success)!important}
|
|
922
|
+
.bg-info{background-color:var(--theme-info)!important}
|
|
923
|
+
.bg-surface-card{background-color:var(--surface-card)!important}
|
|
924
|
+
.bg-surface-page{background-color:var(--surface-page)!important}
|
|
925
|
+
|
|
926
|
+
.text-primary{color:var(--theme-primary)!important}
|
|
927
|
+
.text-secondary{color:var(--theme-secondary)!important}
|
|
928
|
+
.text-background{color:var(--theme-background)!important}
|
|
929
|
+
.text-text{color:var(--theme-text)!important}
|
|
930
|
+
.text-accent{color:var(--theme-accent)!important}
|
|
931
|
+
.text-muted{color:var(--theme-muted)!important}
|
|
932
|
+
.text-error{color:var(--theme-error)!important}
|
|
933
|
+
.text-warning{color:var(--theme-warning)!important}
|
|
934
|
+
.text-success{color:var(--theme-success)!important}
|
|
935
|
+
.text-info{color:var(--theme-info)!important}
|
|
936
|
+
.text-text-primary{color:var(--text-primary)!important}
|
|
937
|
+
.text-text-secondary{color:var(--text-secondary)!important}
|
|
938
|
+
.text-text-tertiary{color:var(--text-tertiary)!important}
|
|
939
|
+
.text-text-disabled{color:var(--text-disabled)!important}
|
|
940
|
+
|
|
941
|
+
.border-border-default{border-color:var(--border-default)!important}
|
|
942
|
+
.border-border-subtle{border-color:var(--border-subtle)!important}
|
|
943
|
+
.border-border-strong{border-color:var(--border-strong)!important}
|
|
944
|
+
`;
|
|
860
945
|
var ThemeContext = (0, import_react.createContext)(void 0);
|
|
861
|
-
function ThemeProvider({ children }) {
|
|
946
|
+
function ThemeProvider({ children, injectUtilityClasses = true }) {
|
|
862
947
|
const [currentTheme, setCurrentTheme] = (0, import_react.useState)(null);
|
|
863
948
|
const [currentMode, setCurrentMode] = (0, import_react.useState)(null);
|
|
864
949
|
const [themes, setThemes] = (0, import_react.useState)([]);
|
|
950
|
+
(0, import_react.useEffect)(() => {
|
|
951
|
+
if (!injectUtilityClasses) return;
|
|
952
|
+
if (typeof document === "undefined") return;
|
|
953
|
+
const existing = document.getElementById(THEME_UTILITY_STYLE_ID);
|
|
954
|
+
if (existing) return;
|
|
955
|
+
const style = document.createElement("style");
|
|
956
|
+
style.id = THEME_UTILITY_STYLE_ID;
|
|
957
|
+
style.textContent = THEME_UTILITY_CSS;
|
|
958
|
+
document.head.appendChild(style);
|
|
959
|
+
}, [injectUtilityClasses]);
|
|
865
960
|
(0, import_react.useEffect)(() => {
|
|
866
961
|
const registeredThemes = themeRegistry.getAll();
|
|
867
962
|
if (registeredThemes.length === 0) {
|
|
@@ -934,6 +1029,146 @@ function useTheme() {
|
|
|
934
1029
|
return context;
|
|
935
1030
|
}
|
|
936
1031
|
|
|
1032
|
+
// theme-switcher.tsx
|
|
1033
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1034
|
+
function getDefaultModeForTheme(themes, themeName, fallbackMode) {
|
|
1035
|
+
const nextTheme = themes.find((theme) => theme.name === themeName);
|
|
1036
|
+
if (!nextTheme) return null;
|
|
1037
|
+
if (fallbackMode && nextTheme.modes[fallbackMode]) {
|
|
1038
|
+
return fallbackMode;
|
|
1039
|
+
}
|
|
1040
|
+
const firstMode = Object.keys(nextTheme.modes)[0];
|
|
1041
|
+
return firstMode ?? null;
|
|
1042
|
+
}
|
|
1043
|
+
function ThemeSwitcher({
|
|
1044
|
+
className,
|
|
1045
|
+
themeLabel = "Theme",
|
|
1046
|
+
modeLabel = "Mode",
|
|
1047
|
+
showModeSelector = true,
|
|
1048
|
+
idPrefix = "runtime-theme-switcher",
|
|
1049
|
+
onThemeChanged,
|
|
1050
|
+
onModeChanged
|
|
1051
|
+
}) {
|
|
1052
|
+
const { themes, currentTheme, currentMode, availableModes, setTheme, setMode } = useTheme();
|
|
1053
|
+
if (themes.length === 0) {
|
|
1054
|
+
return null;
|
|
1055
|
+
}
|
|
1056
|
+
const handleThemeChange = (event) => {
|
|
1057
|
+
const nextThemeName = event.target.value;
|
|
1058
|
+
const nextMode = getDefaultModeForTheme(themes, nextThemeName, currentMode);
|
|
1059
|
+
if (!nextMode) return;
|
|
1060
|
+
setTheme(nextThemeName, nextMode);
|
|
1061
|
+
onThemeChanged?.(nextThemeName, nextMode);
|
|
1062
|
+
};
|
|
1063
|
+
const handleModeChange = (event) => {
|
|
1064
|
+
const nextMode = event.target.value;
|
|
1065
|
+
setMode(nextMode);
|
|
1066
|
+
onModeChanged?.(nextMode);
|
|
1067
|
+
};
|
|
1068
|
+
const themeSelectId = `${idPrefix}-theme`;
|
|
1069
|
+
const modeSelectId = `${idPrefix}-mode`;
|
|
1070
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className, children: [
|
|
1071
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { htmlFor: themeSelectId, children: themeLabel }),
|
|
1072
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("select", { id: themeSelectId, value: currentTheme ?? "", onChange: handleThemeChange, children: themes.map((theme) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: theme.name, children: theme.name }, theme.name)) }),
|
|
1073
|
+
showModeSelector ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
1074
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { htmlFor: modeSelectId, children: modeLabel }),
|
|
1075
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("select", { id: modeSelectId, value: currentMode ?? "", onChange: handleModeChange, children: availableModes.map((mode) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: mode, children: mode }, mode)) })
|
|
1076
|
+
] }) : null
|
|
1077
|
+
] });
|
|
1078
|
+
}
|
|
1079
|
+
function ThemeSwitcherStyled({
|
|
1080
|
+
className,
|
|
1081
|
+
title = "Theme",
|
|
1082
|
+
subtitle = "Switch appearance and mode",
|
|
1083
|
+
themeLabel = "Theme",
|
|
1084
|
+
modeLabel = "Mode",
|
|
1085
|
+
showModeSelector = true,
|
|
1086
|
+
idPrefix = "runtime-theme-switcher-styled",
|
|
1087
|
+
onThemeChanged,
|
|
1088
|
+
onModeChanged
|
|
1089
|
+
}) {
|
|
1090
|
+
const { themes, currentTheme, currentMode, availableModes, setTheme, setMode } = useTheme();
|
|
1091
|
+
if (themes.length === 0) {
|
|
1092
|
+
return null;
|
|
1093
|
+
}
|
|
1094
|
+
const handleThemeChange = (event) => {
|
|
1095
|
+
const nextThemeName = event.target.value;
|
|
1096
|
+
const nextMode = getDefaultModeForTheme(themes, nextThemeName, currentMode);
|
|
1097
|
+
if (!nextMode) return;
|
|
1098
|
+
setTheme(nextThemeName, nextMode);
|
|
1099
|
+
onThemeChanged?.(nextThemeName, nextMode);
|
|
1100
|
+
};
|
|
1101
|
+
const handleModeClick = (mode) => {
|
|
1102
|
+
setMode(mode);
|
|
1103
|
+
onModeChanged?.(mode);
|
|
1104
|
+
};
|
|
1105
|
+
const themeSelectId = `${idPrefix}-theme`;
|
|
1106
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1107
|
+
"section",
|
|
1108
|
+
{
|
|
1109
|
+
className,
|
|
1110
|
+
style: {
|
|
1111
|
+
border: "1px solid var(--theme-border-subtle, #d1d5db)",
|
|
1112
|
+
borderRadius: 12,
|
|
1113
|
+
padding: 12,
|
|
1114
|
+
background: "var(--theme-surface-card, var(--color-theme-background, #ffffff))",
|
|
1115
|
+
color: "var(--theme-text-primary, var(--color-theme-text, #111827))",
|
|
1116
|
+
display: "grid",
|
|
1117
|
+
gap: 10,
|
|
1118
|
+
maxWidth: 360
|
|
1119
|
+
},
|
|
1120
|
+
children: [
|
|
1121
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("header", { style: { display: "grid", gap: 2 }, children: [
|
|
1122
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: title }),
|
|
1123
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("small", { style: { opacity: 0.8 }, children: subtitle })
|
|
1124
|
+
] }),
|
|
1125
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "grid", gap: 6 }, children: [
|
|
1126
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { htmlFor: themeSelectId, children: themeLabel }),
|
|
1127
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1128
|
+
"select",
|
|
1129
|
+
{
|
|
1130
|
+
id: themeSelectId,
|
|
1131
|
+
value: currentTheme ?? "",
|
|
1132
|
+
onChange: handleThemeChange,
|
|
1133
|
+
style: {
|
|
1134
|
+
border: "1px solid var(--theme-border-default, #9ca3af)",
|
|
1135
|
+
borderRadius: 8,
|
|
1136
|
+
padding: "8px 10px",
|
|
1137
|
+
background: "var(--theme-surface-page, var(--color-theme-background, #ffffff))",
|
|
1138
|
+
color: "inherit"
|
|
1139
|
+
},
|
|
1140
|
+
children: themes.map((theme) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: theme.name, children: theme.name }, theme.name))
|
|
1141
|
+
}
|
|
1142
|
+
)
|
|
1143
|
+
] }),
|
|
1144
|
+
showModeSelector ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "grid", gap: 6 }, children: [
|
|
1145
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: modeLabel }),
|
|
1146
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: availableModes.map((mode) => {
|
|
1147
|
+
const isActive = mode === currentMode;
|
|
1148
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1149
|
+
"button",
|
|
1150
|
+
{
|
|
1151
|
+
type: "button",
|
|
1152
|
+
onClick: () => handleModeClick(mode),
|
|
1153
|
+
style: {
|
|
1154
|
+
border: "1px solid var(--theme-border-default, #9ca3af)",
|
|
1155
|
+
borderRadius: 999,
|
|
1156
|
+
padding: "6px 12px",
|
|
1157
|
+
cursor: "pointer",
|
|
1158
|
+
background: isActive ? "var(--theme-colors-primary, var(--color-theme-primary, #2563eb))" : "var(--theme-surface-page, var(--color-theme-background, #ffffff))",
|
|
1159
|
+
color: isActive ? "var(--theme-surface-page, var(--color-theme-background, #ffffff))" : "inherit"
|
|
1160
|
+
},
|
|
1161
|
+
children: mode
|
|
1162
|
+
},
|
|
1163
|
+
mode
|
|
1164
|
+
);
|
|
1165
|
+
}) })
|
|
1166
|
+
] }) : null
|
|
1167
|
+
]
|
|
1168
|
+
}
|
|
1169
|
+
);
|
|
1170
|
+
}
|
|
1171
|
+
|
|
937
1172
|
// index.ts
|
|
938
1173
|
init_theme_registry();
|
|
939
1174
|
init_theme_registry();
|
|
@@ -941,7 +1176,10 @@ init_theme_registry();
|
|
|
941
1176
|
0 && (module.exports = {
|
|
942
1177
|
RUNTIME_THEME_REGISTRY_VERSION,
|
|
943
1178
|
ThemeProvider,
|
|
1179
|
+
ThemeSwitcher,
|
|
1180
|
+
ThemeSwitcherStyled,
|
|
944
1181
|
applyThemeToDocument,
|
|
1182
|
+
createTailwindThemeColorMap,
|
|
945
1183
|
generateAllThemesCSS,
|
|
946
1184
|
generateThemeCSS,
|
|
947
1185
|
isThemeTokensV2,
|