@tamagui/core 1.0.1-beta.136 → 1.0.1-beta.139
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/cjs/addTheme.js +74 -0
- package/dist/cjs/addTheme.js.map +7 -0
- package/dist/cjs/contexts/TextAncestorContext.js +44 -0
- package/dist/cjs/contexts/TextAncestorContext.js.map +7 -0
- package/dist/cjs/contexts/ThemeContext.js +30 -0
- package/dist/cjs/contexts/ThemeContext.js.map +7 -0
- package/dist/cjs/createComponent.js +10 -17
- package/dist/cjs/createComponent.js.map +2 -2
- package/dist/cjs/createTamagui.js +18 -118
- package/dist/cjs/createTamagui.js.map +2 -2
- package/dist/cjs/createTheme.js +2 -5
- package/dist/cjs/createTheme.js.map +2 -2
- package/dist/cjs/ensureThemeVariable.js +152 -0
- package/dist/cjs/ensureThemeVariable.js.map +7 -0
- package/dist/cjs/helpers/ThemeManager.js +209 -0
- package/dist/cjs/helpers/ThemeManager.js.map +7 -0
- package/dist/cjs/helpers/assignNativePropsToWeb.js +1 -0
- package/dist/cjs/helpers/assignNativePropsToWeb.js.map +2 -2
- package/dist/cjs/helpers/createPropMapper.js +2 -3
- package/dist/cjs/helpers/createPropMapper.js.map +2 -2
- package/dist/cjs/helpers/createTamaguiProvider.js +3 -1
- package/dist/cjs/helpers/createTamaguiProvider.js.map +2 -2
- package/dist/cjs/helpers/ensureThemeVariable.js +152 -0
- package/dist/cjs/helpers/ensureThemeVariable.js.map +7 -0
- package/dist/cjs/helpers/getSplitStyles.js +11 -2
- package/dist/cjs/helpers/getSplitStyles.js.map +2 -2
- package/dist/cjs/helpers/getThemeCSSRules.js +98 -0
- package/dist/cjs/helpers/getThemeCSSRules.js.map +7 -0
- package/dist/cjs/helpers/getThemeCSSRules.native.js +31 -0
- package/dist/cjs/helpers/getThemeCSSRules.native.js.map +7 -0
- package/dist/cjs/helpers/getVariantExtras.js +6 -6
- package/dist/cjs/helpers/getVariantExtras.js.map +2 -2
- package/dist/cjs/helpers/insertStyleRule.js +6 -1
- package/dist/cjs/helpers/insertStyleRule.js.map +2 -2
- package/dist/cjs/helpers/mergeProps.js +18 -14
- package/dist/cjs/helpers/mergeProps.js.map +2 -2
- package/dist/cjs/helpers/themes.js +79 -0
- package/dist/cjs/helpers/themes.js.map +7 -0
- package/dist/cjs/hooks/useId.js +2 -32
- package/dist/cjs/hooks/useId.js.map +2 -2
- package/dist/cjs/hooks/useMedia.js +75 -92
- package/dist/cjs/hooks/useMedia.js.map +2 -2
- package/dist/cjs/hooks/useSafeRef.js +60 -0
- package/dist/cjs/hooks/useSafeRef.js.map +7 -0
- package/dist/cjs/hooks/useTheme.js +20 -11
- package/dist/cjs/hooks/useTheme.js.map +2 -2
- package/dist/cjs/index.js +23 -4
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/loadTheme.js +64 -0
- package/dist/cjs/loadTheme.js.map +7 -0
- package/dist/cjs/types.js.map +1 -1
- package/dist/cjs/updateTheme.js +44 -0
- package/dist/cjs/updateTheme.js.map +7 -0
- package/dist/cjs/vendor/Pressability.js +32 -0
- package/dist/cjs/vendor/Pressability.js.map +7 -0
- package/dist/cjs/vendor/Pressability.native.js +32 -0
- package/dist/cjs/vendor/Pressability.native.js.map +7 -0
- package/dist/cjs/views/Slot.js +2 -2
- package/dist/cjs/views/Slot.js.map +2 -2
- package/dist/cjs/views/Theme.js +1 -1
- package/dist/cjs/views/Theme.js.map +2 -2
- package/dist/cjs/views/ThemeProvider.js +1 -1
- package/dist/cjs/views/ThemeProvider.js.map +1 -1
- package/dist/cjs/views/ThemeReset.js +1 -1
- package/dist/cjs/views/ThemeReset.js.map +1 -1
- package/dist/esm/addTheme.js +50 -0
- package/dist/esm/addTheme.js.map +7 -0
- package/dist/esm/contexts/TextAncestorContext.js +15 -0
- package/dist/esm/contexts/TextAncestorContext.js.map +7 -0
- package/dist/esm/contexts/ThemeContext.js +6 -0
- package/dist/esm/contexts/ThemeContext.js.map +7 -0
- package/dist/esm/createComponent.js +10 -17
- package/dist/esm/createComponent.js.map +2 -2
- package/dist/esm/createTamagui.js +17 -117
- package/dist/esm/createTamagui.js.map +2 -2
- package/dist/esm/createTheme.js +1 -3
- package/dist/esm/createTheme.js.map +2 -2
- package/dist/esm/ensureThemeVariable.js +125 -0
- package/dist/esm/ensureThemeVariable.js.map +7 -0
- package/dist/esm/helpers/ThemeManager.js +183 -0
- package/dist/esm/helpers/ThemeManager.js.map +7 -0
- package/dist/esm/helpers/assignNativePropsToWeb.js +1 -0
- package/dist/esm/helpers/assignNativePropsToWeb.js.map +2 -2
- package/dist/esm/helpers/createPropMapper.js +2 -3
- package/dist/esm/helpers/createPropMapper.js.map +2 -2
- package/dist/esm/helpers/createTamaguiProvider.js +3 -1
- package/dist/esm/helpers/createTamaguiProvider.js.map +2 -2
- package/dist/esm/helpers/ensureThemeVariable.js +125 -0
- package/dist/esm/helpers/ensureThemeVariable.js.map +7 -0
- package/dist/esm/helpers/getSplitStyles.js +11 -2
- package/dist/esm/helpers/getSplitStyles.js.map +2 -2
- package/dist/esm/helpers/getThemeCSSRules.js +74 -0
- package/dist/esm/helpers/getThemeCSSRules.js.map +7 -0
- package/dist/esm/helpers/getThemeCSSRules.native.js +7 -0
- package/dist/esm/helpers/getThemeCSSRules.native.js.map +7 -0
- package/dist/esm/helpers/getVariantExtras.js +6 -6
- package/dist/esm/helpers/getVariantExtras.js.map +2 -2
- package/dist/esm/helpers/insertStyleRule.js +6 -1
- package/dist/esm/helpers/insertStyleRule.js.map +2 -2
- package/dist/esm/helpers/mergeProps.js +18 -14
- package/dist/esm/helpers/mergeProps.js.map +2 -2
- package/dist/esm/helpers/themes.js +54 -0
- package/dist/esm/helpers/themes.js.map +7 -0
- package/dist/esm/hooks/useId.js +1 -28
- package/dist/esm/hooks/useId.js.map +2 -2
- package/dist/esm/hooks/useMedia.js +74 -92
- package/dist/esm/hooks/useMedia.js.map +2 -2
- package/dist/esm/hooks/useSafeRef.js +36 -0
- package/dist/esm/hooks/useSafeRef.js.map +7 -0
- package/dist/esm/hooks/useTheme.js +23 -11
- package/dist/esm/hooks/useTheme.js.map +2 -2
- package/dist/esm/index.js +23 -3
- package/dist/esm/index.js.map +2 -2
- package/dist/esm/loadTheme.js +40 -0
- package/dist/esm/loadTheme.js.map +7 -0
- package/dist/esm/updateTheme.js +20 -0
- package/dist/esm/updateTheme.js.map +7 -0
- package/dist/esm/vendor/Pressability.js +7 -0
- package/dist/esm/vendor/Pressability.js.map +7 -0
- package/dist/esm/vendor/Pressability.native.js +7 -0
- package/dist/esm/vendor/Pressability.native.js.map +7 -0
- package/dist/esm/views/Slot.js +2 -2
- package/dist/esm/views/Slot.js.map +2 -2
- package/dist/esm/views/Theme.js +1 -1
- package/dist/esm/views/Theme.js.map +1 -1
- package/dist/esm/views/ThemeProvider.js +1 -1
- package/dist/esm/views/ThemeProvider.js.map +1 -1
- package/dist/esm/views/ThemeReset.js +1 -1
- package/dist/esm/views/ThemeReset.js.map +1 -1
- package/package.json +8 -8
- package/types/addTheme.d.ts +11 -0
- package/types/{views → contexts}/TextAncestorContext.d.ts +0 -0
- package/types/{ThemeContext.d.ts → contexts/ThemeContext.d.ts} +1 -1
- package/types/createTheme.d.ts +0 -1
- package/types/{ThemeManager.d.ts → helpers/ThemeManager.d.ts} +5 -5
- package/types/helpers/getSplitStyles.d.ts +1 -0
- package/types/helpers/getThemeCSSRules.d.ts +8 -0
- package/types/helpers/getThemeCSSRules.native.d.ts +2 -0
- package/types/helpers/mergeProps.d.ts +3 -1
- package/types/helpers/themes.d.ts +4 -0
- package/types/hooks/useId.d.ts +1 -8
- package/types/hooks/useMedia.d.ts +2 -1
- package/types/hooks/useSafeRef.d.ts +4 -0
- package/types/hooks/useTheme.d.ts +2 -1
- package/types/index.d.ts +5 -2
- package/types/types.d.ts +2 -2
- package/types/updateTheme.d.ts +9 -0
- package/types/{Pressability.d.ts → vendor/Pressability.d.ts} +0 -0
- package/types/{Pressability.native.d.ts → vendor/Pressability.native.d.ts} +0 -0
- package/types/views/Theme.d.ts +1 -1
- package/types/defaultComponentState.d.ts +0 -1
- package/types/helpers/nativeGestureHandler.native.d.ts +0 -2
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import { configListeners, setConfig } from "./conf";
|
|
2
|
-
import { THEME_CLASSNAME_PREFIX } from "./constants/constants";
|
|
3
2
|
import { isWeb } from "./constants/platform";
|
|
4
|
-
import { themeToVariableToValueMap } from "./createTheme";
|
|
5
|
-
import { createVariable, isVariable } from "./createVariable";
|
|
6
3
|
import { createVariables } from "./createVariables";
|
|
7
4
|
import { createTamaguiProvider } from "./helpers/createTamaguiProvider";
|
|
5
|
+
import { getThemeCSSRules } from "./helpers/getThemeCSSRules";
|
|
8
6
|
import { getAllRules } from "./helpers/insertStyleRule";
|
|
9
7
|
import {
|
|
10
8
|
registerCSSVariable,
|
|
11
9
|
tokensValueToVariable,
|
|
12
10
|
variableToCSS
|
|
13
11
|
} from "./helpers/registerCSSVariable";
|
|
14
|
-
import {
|
|
12
|
+
import { ensureThemeVariable, proxyThemeToParents } from "./helpers/themes";
|
|
15
13
|
import { configureMedia } from "./hooks/useMedia";
|
|
16
14
|
import { parseFont, registerFontVariables } from "./insertFont";
|
|
17
15
|
import { Tamagui } from "./Tamagui";
|
|
@@ -45,7 +43,7 @@ function createTamagui(config) {
|
|
|
45
43
|
})();
|
|
46
44
|
const themeConfig = (() => {
|
|
47
45
|
const themes = { ...config.themes };
|
|
48
|
-
|
|
46
|
+
let cssRuleSets = [];
|
|
49
47
|
if (isWeb) {
|
|
50
48
|
let declarationsToRuleSet2 = function(decs, selector = "") {
|
|
51
49
|
return `:root${selector} {${sep}${[...decs].join(`;${sep}`)}${sep}}`;
|
|
@@ -70,17 +68,15 @@ function createTamagui(config) {
|
|
|
70
68
|
cssRuleSets.push(declarationsToRuleSet2(declarations));
|
|
71
69
|
if (fontDeclarations) {
|
|
72
70
|
for (const key in fontDeclarations) {
|
|
73
|
-
const { name, declarations: declarations2, language } = fontDeclarations[key];
|
|
74
|
-
const languageSelector = ` .t_lang-${name}-${language || "default"}`;
|
|
71
|
+
const { name, declarations: declarations2, language = "default" } = fontDeclarations[key];
|
|
75
72
|
const fontSelector = `.font_${name}`;
|
|
76
|
-
const
|
|
73
|
+
const langSelector = `:root .t_lang-${name}-${language} ${fontSelector}`;
|
|
74
|
+
const selectors = language === "default" ? ` ${fontSelector}, ${langSelector}` : langSelector;
|
|
77
75
|
const specificRuleSet = declarationsToRuleSet2(declarations2, selectors);
|
|
78
76
|
cssRuleSets.push(specificRuleSet);
|
|
79
77
|
}
|
|
80
78
|
}
|
|
81
79
|
}
|
|
82
|
-
const hasDarkLight = "light" in config.themes && "dark" in config.themes;
|
|
83
|
-
const CNP = `.${THEME_CLASSNAME_PREFIX}`;
|
|
84
80
|
const dedupedThemes = {};
|
|
85
81
|
const existing = /* @__PURE__ */ new WeakMap();
|
|
86
82
|
for (const themeName in themes) {
|
|
@@ -91,7 +87,7 @@ function createTamagui(config) {
|
|
|
91
87
|
e.names.push(themeName);
|
|
92
88
|
continue;
|
|
93
89
|
}
|
|
94
|
-
const theme = { ...
|
|
90
|
+
const theme = { ...rawTheme };
|
|
95
91
|
for (const key in theme) {
|
|
96
92
|
ensureThemeVariable(theme, key);
|
|
97
93
|
}
|
|
@@ -100,99 +96,22 @@ function createTamagui(config) {
|
|
|
100
96
|
names: [themeName],
|
|
101
97
|
theme
|
|
102
98
|
};
|
|
103
|
-
existing.set(
|
|
99
|
+
existing.set(rawTheme, dedupedThemes[themeName]);
|
|
104
100
|
}
|
|
105
101
|
if (isWeb) {
|
|
106
102
|
for (const themeName in dedupedThemes) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
varToValMap[variable.variable] = variable.val;
|
|
116
|
-
}
|
|
117
|
-
if (variable.isFloating || !tokensValueToVariable.has(variable.val)) {
|
|
118
|
-
value = variable.val;
|
|
119
|
-
} else {
|
|
120
|
-
value = tokensValueToVariable.get(variable.val).variable;
|
|
121
|
-
}
|
|
122
|
-
vars += `--${themeKey}:${value};`;
|
|
123
|
-
}
|
|
124
|
-
const isDarkOrLightBase = themeName === "dark" || themeName === "light";
|
|
125
|
-
const selectors = names.map((name) => {
|
|
126
|
-
return `${CNP}${name}`;
|
|
127
|
-
});
|
|
128
|
-
if (hasDarkLight) {
|
|
129
|
-
for (const subName of names) {
|
|
130
|
-
const isDark = isDarkOrLightBase || subName.startsWith("dark_");
|
|
131
|
-
const childSelector = `${CNP}${subName.replace(isDark ? "dark_" : "light_", "")}`;
|
|
132
|
-
const order = isDark ? ["dark", "light"] : ["light", "dark"];
|
|
133
|
-
if (isDarkOrLightBase) {
|
|
134
|
-
order.reverse();
|
|
135
|
-
}
|
|
136
|
-
const [stronger, weaker] = order;
|
|
137
|
-
const max = config.maxDarkLightNesting ?? 3;
|
|
138
|
-
new Array(Math.round(max * 1.5)).fill(void 0).forEach((_, pi) => {
|
|
139
|
-
const isOdd = pi % 2 === 1;
|
|
140
|
-
if (isOdd && pi < 3)
|
|
141
|
-
return;
|
|
142
|
-
const parents = new Array(pi + 1).fill(void 0).map((_2, psi) => {
|
|
143
|
-
return `${CNP}${psi % 2 === 0 ? stronger : weaker}`;
|
|
144
|
-
});
|
|
145
|
-
let parentSelectors = parents.length > 1 ? parents.slice(1) : parents;
|
|
146
|
-
if (isOdd) {
|
|
147
|
-
const [_first, second, ...rest] = parentSelectors;
|
|
148
|
-
parentSelectors = [second, ...rest, second];
|
|
149
|
-
}
|
|
150
|
-
const lastParentSelector = parentSelectors[parentSelectors.length - 1];
|
|
151
|
-
selectors.push(`${parentSelectors.join(" ")} ${childSelector === lastParentSelector ? "" : childSelector}`);
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
const rootSep = config.themeClassNameOnRoot ? "" : " ";
|
|
156
|
-
const css2 = `${selectors.map((x) => `:root${rootSep}${x}`).join(", ")} {${vars}}`;
|
|
157
|
-
cssRuleSets.push(css2);
|
|
158
|
-
if (config.shouldAddPrefersColorThemes && isDarkOrLightBase) {
|
|
159
|
-
const isDark = themeName.startsWith("dark");
|
|
160
|
-
cssRuleSets.push(`@media(prefers-color-scheme: ${isDark ? "dark" : "light"}) {
|
|
161
|
-
body { background:${theme.background}; color: ${theme.color} }
|
|
162
|
-
:root {${vars} }
|
|
163
|
-
}`);
|
|
164
|
-
}
|
|
103
|
+
cssRuleSets = [
|
|
104
|
+
...cssRuleSets,
|
|
105
|
+
...getThemeCSSRules({
|
|
106
|
+
config,
|
|
107
|
+
themeName,
|
|
108
|
+
...dedupedThemes[themeName]
|
|
109
|
+
})
|
|
110
|
+
];
|
|
165
111
|
}
|
|
166
112
|
}
|
|
167
113
|
for (const themeName in themes) {
|
|
168
|
-
|
|
169
|
-
const parents = themeName.split("_").slice(0, -1).map((part) => {
|
|
170
|
-
cur.push(part);
|
|
171
|
-
return cur.join("_");
|
|
172
|
-
});
|
|
173
|
-
if (!parents.length)
|
|
174
|
-
continue;
|
|
175
|
-
const og = themes[themeName];
|
|
176
|
-
themes[themeName] = new Proxy(og, {
|
|
177
|
-
get(target, key) {
|
|
178
|
-
if (key === GetThemeUnwrapped) {
|
|
179
|
-
return og;
|
|
180
|
-
}
|
|
181
|
-
if (Reflect.has(target, key)) {
|
|
182
|
-
return Reflect.get(target, key);
|
|
183
|
-
}
|
|
184
|
-
for (let i = parents.length - 1; i >= 0; i--) {
|
|
185
|
-
const parent = themes[parents[i]];
|
|
186
|
-
if (!parent) {
|
|
187
|
-
continue;
|
|
188
|
-
}
|
|
189
|
-
if (Reflect.has(parent, key)) {
|
|
190
|
-
return Reflect.get(parent, key);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
return Reflect.get(target, key);
|
|
194
|
-
}
|
|
195
|
-
});
|
|
114
|
+
themes[themeName] = proxyThemeToParents(themeName, themes[themeName], themes);
|
|
196
115
|
}
|
|
197
116
|
tokensValueToVariable.clear();
|
|
198
117
|
Object.freeze(cssRuleSets);
|
|
@@ -249,25 +168,6 @@ const parseTokens = (tokens) => {
|
|
|
249
168
|
}
|
|
250
169
|
return res;
|
|
251
170
|
};
|
|
252
|
-
function ensureThemeVariable(theme, key) {
|
|
253
|
-
const val = theme[key];
|
|
254
|
-
const themeKey = key;
|
|
255
|
-
if (!isVariable(val)) {
|
|
256
|
-
theme[key] = createVariable({
|
|
257
|
-
key: themeKey,
|
|
258
|
-
name: themeKey,
|
|
259
|
-
val
|
|
260
|
-
});
|
|
261
|
-
} else {
|
|
262
|
-
if (val.name !== themeKey) {
|
|
263
|
-
theme[key] = createVariable({
|
|
264
|
-
key: val.name,
|
|
265
|
-
name: themeKey,
|
|
266
|
-
val: val.val
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
171
|
export {
|
|
272
172
|
createTamagui
|
|
273
173
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/createTamagui.ts"],
|
|
4
|
-
"sourcesContent": ["import { simpleHash } from '@tamagui/helpers'\n\nimport { configListeners, setConfig } from './conf'\nimport { THEME_CLASSNAME_PREFIX } from './constants/constants'\nimport { isWeb } from './constants/platform'\nimport { themeToVariableToValueMap } from './createTheme'\nimport { Variable, createVariable, isVariable } from './createVariable'\nimport { createVariables } from './createVariables'\nimport { createTamaguiProvider } from './helpers/createTamaguiProvider'\nimport { getFontLanguage } from './helpers/getFontLanguage'\nimport { getAtomicStyle } from './helpers/getStylesAtomic'\nimport { getAllRules } from './helpers/insertStyleRule'\nimport {\n registerCSSVariable,\n tokensValueToVariable,\n variableToCSS,\n} from './helpers/registerCSSVariable'\nimport { GetThemeUnwrapped } from './hooks/getThemeUnwrapped'\nimport { configureMedia } from './hooks/useMedia'\nimport { parseFont, registerFontVariables } from './insertFont'\nimport { Tamagui } from './Tamagui'\nimport { CreateTamaguiProps, InferTamaguiConfig, TamaguiInternalConfig, ThemeObject } from './types'\n\n// config is re-run by the @tamagui/static, dont double validate\nconst createdConfigs = new WeakMap<any, boolean>()\n\nexport function createTamagui<Conf extends CreateTamaguiProps>(\n config: Conf\n): InferTamaguiConfig<Conf> {\n if (createdConfigs.has(config)) {\n return config as any\n }\n\n if (process.env.NODE_ENV === 'development') {\n if (!config.tokens) {\n throw new Error(`Must define tokens`)\n }\n if (!config.themes) {\n throw new Error(`Must define themes`)\n }\n if (!config.fonts) {\n throw new Error(`Must define fonts`)\n }\n }\n\n configureMedia({\n queries: config.media as any,\n defaultActive: config.mediaQueryDefaultActive,\n })\n\n const fontTokens = createVariables(config.fonts!, '', true)\n const fontsParsed = (() => {\n const res = {} as typeof fontTokens\n for (const familyName in fontTokens) {\n res[`$${familyName}`] = parseFont(fontTokens[familyName])\n }\n return res!\n })()\n\n const themeConfig = (() => {\n const themes = { ...config.themes }\n const cssRuleSets: string[] = []\n\n if (isWeb) {\n const declarations: string[] = []\n const fontDeclarations: Record<\n string,\n { name: string; declarations: string[]; language?: string }\n > = {}\n\n for (const key in config.tokens) {\n for (const skey in config.tokens[key]) {\n const val = config.tokens[key][skey]\n registerCSSVariable(val)\n declarations.push(variableToCSS(val))\n }\n }\n\n for (const key in fontsParsed) {\n const fontParsed = fontsParsed[key]\n const [name, language] = key.includes('_') ? key.split('_') : [key]\n const fontVars = registerFontVariables(fontParsed)\n fontDeclarations[key] = { name: name.slice(1), declarations: fontVars, language }\n }\n\n const sep = process.env.NODE_ENV === 'development' ? config.cssStyleSeparator || ' ' : ''\n\n function declarationsToRuleSet(decs: string[], selector = '') {\n return `:root${selector} {${sep}${[...decs].join(`;${sep}`)}${sep}}`\n }\n\n // non-font\n cssRuleSets.push(declarationsToRuleSet(declarations))\n\n // fonts\n if (fontDeclarations) {\n for (const key in fontDeclarations) {\n const { name, declarations, language } = fontDeclarations[key]\n const languageSelector = ` .t_lang-${name}-${language || 'default'}`\n const fontSelector = `.font_${name}`\n const selectors = ` ${fontSelector}, :root ${languageSelector} ${fontSelector}`\n const specificRuleSet = declarationsToRuleSet(declarations, selectors)\n cssRuleSets.push(specificRuleSet)\n }\n }\n }\n\n // special case for SSR\n const hasDarkLight = 'light' in config.themes && 'dark' in config.themes\n const CNP = `.${THEME_CLASSNAME_PREFIX}`\n\n // dedupe themes to avoid duplicate CSS generation\n type DedupedTheme = {\n names: string[]\n theme: ThemeObject\n }\n const dedupedThemes: {\n [key: string]: DedupedTheme\n } = {}\n const existing = new WeakMap<ThemeObject, DedupedTheme>()\n\n // first, de-dupe and parse them\n for (const themeName in themes) {\n const rawTheme = themes[themeName]\n\n // if existing, avoid\n if (existing.has(rawTheme)) {\n const e = existing.get(rawTheme)!\n themes[themeName] = e.theme\n e.names.push(themeName)\n continue\n }\n\n // parse into variables\n const theme = { ...config.themes[themeName] }\n for (const key in theme) {\n // make sure properly names theme variables\n ensureThemeVariable(theme, key)\n }\n themes[themeName] = theme\n\n // set deduped\n dedupedThemes[themeName] = {\n names: [themeName],\n theme,\n }\n existing.set(config.themes[themeName], dedupedThemes[themeName])\n }\n\n // then, generate from de-duped\n if (isWeb) {\n for (const themeName in dedupedThemes) {\n const { theme, names } = dedupedThemes[themeName]\n let vars = ''\n\n themeToVariableToValueMap.set(theme, {})\n const varToValMap = themeToVariableToValueMap.get(theme)\n for (const themeKey in theme) {\n const variable = theme[themeKey] as Variable\n let value: any = null\n if (varToValMap) {\n varToValMap[variable.variable] = variable.val\n }\n if (variable.isFloating || !tokensValueToVariable.has(variable.val)) {\n value = variable.val\n } else {\n value = tokensValueToVariable.get(variable.val)!.variable\n }\n vars += `--${themeKey}:${value};`\n }\n\n const isDarkOrLightBase = themeName === 'dark' || themeName === 'light'\n const selectors = names.map((name) => {\n return `${CNP}${name}`\n })\n\n // since we dont specify dark/light in classnames we have to do an awkward specificity war\n // use config.maxDarkLightNesting to determine how deep you can nest until it breaks\n if (hasDarkLight) {\n for (const subName of names) {\n const isDark = isDarkOrLightBase || subName.startsWith('dark_')\n const childSelector = `${CNP}${subName.replace(isDark ? 'dark_' : 'light_', '')}`\n const order = isDark ? ['dark', 'light'] : ['light', 'dark']\n if (isDarkOrLightBase) {\n order.reverse()\n }\n const [stronger, weaker] = order\n const max = config.maxDarkLightNesting ?? 3\n\n new Array(Math.round(max * 1.5)).fill(undefined).forEach((_, pi) => {\n const isOdd = pi % 2 === 1\n if (isOdd && pi < 3) return\n const parents = new Array(pi + 1).fill(undefined).map((_, psi) => {\n return `${CNP}${psi % 2 === 0 ? stronger : weaker}`\n })\n let parentSelectors = parents.length > 1 ? parents.slice(1) : parents\n if (isOdd) {\n const [_first, second, ...rest] = parentSelectors\n parentSelectors = [second, ...rest, second]\n }\n // avoid .t_light .t_light at the end (make sure child is unique from last parent)\n const lastParentSelector = parentSelectors[parentSelectors.length - 1]\n selectors.push(\n `${parentSelectors.join(' ')} ${\n childSelector === lastParentSelector ? '' : childSelector\n }`\n )\n })\n }\n }\n\n const rootSep = config.themeClassNameOnRoot ? '' : ' '\n const css = `${selectors.map((x) => `:root${rootSep}${x}`).join(', ')} {${vars}}`\n cssRuleSets.push(css)\n\n if (config.shouldAddPrefersColorThemes && isDarkOrLightBase) {\n // add media prefers for dark/light base\n const isDark = themeName.startsWith('dark')\n cssRuleSets.push(\n `@media(prefers-color-scheme: ${isDark ? 'dark' : 'light'}) {\n body { background:${theme.background}; color: ${theme.color} }\n :root {${vars} } \n }`\n )\n }\n }\n }\n\n // proxy upwards to get parent variables (themes are subset going down)\n for (const themeName in themes) {\n // we could test if this is better as just a straight object spread or fancier proxy\n const cur: string[] = []\n // if theme is dark_blue_alt1_Button\n // this will be the parent names in order: ['dark', 'dark_blue', 'dark_blue_alt1\"]\n const parents = themeName\n .split('_')\n .slice(0, -1)\n .map((part) => {\n cur.push(part)\n return cur.join('_')\n })\n\n if (!parents.length) continue\n\n // proxy fallback values to parent theme values\n const og = themes[themeName]\n themes[themeName] = new Proxy(og, {\n get(target, key) {\n if (key === GetThemeUnwrapped) {\n return og\n }\n if (Reflect.has(target, key)) {\n return Reflect.get(target, key)\n }\n // check parents\n for (let i = parents.length - 1; i >= 0; i--) {\n const parent = themes[parents[i]]\n if (!parent) {\n continue\n }\n if (Reflect.has(parent, key)) {\n return Reflect.get(parent, key)\n }\n }\n return Reflect.get(target, key)\n },\n })\n }\n\n tokensValueToVariable.clear()\n Object.freeze(cssRuleSets)\n const css = cssRuleSets.join('\\n')\n\n return {\n themes,\n cssRuleSets,\n css,\n }\n })()\n\n // faster lookups token keys become $keys to match input\n const tokensParsed: any = parseTokens(config.tokens)\n\n const getCSS = () => {\n return `${themeConfig.css}\\n${getAllRules().join('\\n')}`\n }\n\n const shorthands = config.shorthands || {}\n\n const next: TamaguiInternalConfig = {\n fontLanguages: [],\n defaultTheme: 'light',\n animations: {} as any,\n media: {},\n ...config,\n shorthands,\n inverseShorthands: shorthands\n ? Object.fromEntries(Object.entries(shorthands).map(([k, v]) => [v, k]))\n : {},\n themes: themeConfig.themes,\n fontsParsed,\n themeConfig,\n tokensParsed,\n parsed: true,\n getCSS,\n Provider: null as any,\n }\n\n next.Provider = createTamaguiProvider(next)\n\n setConfig(next)\n\n if (configListeners.size) {\n configListeners.forEach((cb) => cb(next))\n configListeners.clear()\n }\n\n createdConfigs.set(next, true)\n\n if (process.env.NODE_ENV === 'development') {\n if (!globalThis['Tamagui']) {\n globalThis['Tamagui'] = Tamagui\n }\n }\n\n // @ts-expect-error\n return next\n}\n\nconst parseTokens = (tokens: any) => {\n const res: any = {}\n for (const key in tokens) {\n res[key] = {}\n for (const skey in tokens[key]) {\n res[key][`$${skey}`] = tokens[key][skey]\n }\n }\n return res\n}\n\n// mutates, freeze after\n// shared by createTamagui so extracted here\nfunction ensureThemeVariable(theme: any, key: string) {\n const val = theme[key]\n const themeKey = key\n if (!isVariable(val)) {\n theme[key] = createVariable({\n key: themeKey,\n name: themeKey,\n val,\n })\n } else {\n if (val.name !== themeKey) {\n // rename to theme name\n theme[key] = createVariable({\n key: val.name,\n name: themeKey,\n val: val.val,\n })\n }\n }\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import { configListeners, setConfig } from './conf'\nimport { isWeb } from './constants/platform'\nimport { createVariables } from './createVariables'\nimport { createTamaguiProvider } from './helpers/createTamaguiProvider'\nimport { getThemeCSSRules } from './helpers/getThemeCSSRules'\nimport { getAllRules } from './helpers/insertStyleRule'\nimport {\n registerCSSVariable,\n tokensValueToVariable,\n variableToCSS,\n} from './helpers/registerCSSVariable'\nimport { ensureThemeVariable, proxyThemeToParents } from './helpers/themes'\nimport { configureMedia } from './hooks/useMedia'\nimport { parseFont, registerFontVariables } from './insertFont'\nimport { Tamagui } from './Tamagui'\nimport { CreateTamaguiProps, InferTamaguiConfig, TamaguiInternalConfig, ThemeObject } from './types'\n\n// config is re-run by the @tamagui/static, dont double validate\nconst createdConfigs = new WeakMap<any, boolean>()\n\nexport function createTamagui<Conf extends CreateTamaguiProps>(\n config: Conf\n): InferTamaguiConfig<Conf> {\n if (createdConfigs.has(config)) {\n return config as any\n }\n\n if (process.env.NODE_ENV === 'development') {\n if (!config.tokens) {\n throw new Error(`Must define tokens`)\n }\n if (!config.themes) {\n throw new Error(`Must define themes`)\n }\n if (!config.fonts) {\n throw new Error(`Must define fonts`)\n }\n }\n\n configureMedia({\n queries: config.media as any,\n defaultActive: config.mediaQueryDefaultActive,\n })\n\n const fontTokens = createVariables(config.fonts!, '', true)\n const fontsParsed = (() => {\n const res = {} as typeof fontTokens\n for (const familyName in fontTokens) {\n res[`$${familyName}`] = parseFont(fontTokens[familyName])\n }\n return res!\n })()\n\n const themeConfig = (() => {\n const themes = { ...config.themes }\n let cssRuleSets: string[] = []\n\n if (isWeb) {\n const declarations: string[] = []\n const fontDeclarations: Record<\n string,\n { name: string; declarations: string[]; language?: string }\n > = {}\n\n for (const key in config.tokens) {\n for (const skey in config.tokens[key]) {\n const val = config.tokens[key][skey]\n registerCSSVariable(val)\n declarations.push(variableToCSS(val))\n }\n }\n\n for (const key in fontsParsed) {\n const fontParsed = fontsParsed[key]\n const [name, language] = key.includes('_') ? key.split('_') : [key]\n const fontVars = registerFontVariables(fontParsed)\n fontDeclarations[key] = { name: name.slice(1), declarations: fontVars, language }\n }\n\n const sep = process.env.NODE_ENV === 'development' ? config.cssStyleSeparator || ' ' : ''\n\n function declarationsToRuleSet(decs: string[], selector = '') {\n return `:root${selector} {${sep}${[...decs].join(`;${sep}`)}${sep}}`\n }\n\n // non-font\n cssRuleSets.push(declarationsToRuleSet(declarations))\n\n // fonts\n if (fontDeclarations) {\n for (const key in fontDeclarations) {\n const { name, declarations, language = 'default' } = fontDeclarations[key]\n const fontSelector = `.font_${name}`\n const langSelector = `:root .t_lang-${name}-${language} ${fontSelector}`\n const selectors =\n language === 'default' ? ` ${fontSelector}, ${langSelector}` : langSelector\n const specificRuleSet = declarationsToRuleSet(declarations, selectors)\n cssRuleSets.push(specificRuleSet)\n }\n }\n }\n\n // dedupe themes to avoid duplicate CSS generation\n type DedupedTheme = {\n names: string[]\n theme: ThemeObject\n }\n const dedupedThemes: {\n [key: string]: DedupedTheme\n } = {}\n const existing = new WeakMap<ThemeObject, DedupedTheme>()\n\n // first, de-dupe and parse them\n for (const themeName in themes) {\n const rawTheme = themes[themeName]\n\n // if existing, avoid\n if (existing.has(rawTheme)) {\n const e = existing.get(rawTheme)!\n themes[themeName] = e.theme\n e.names.push(themeName)\n continue\n }\n\n // ensure each theme object unique for dedupe\n const theme = { ...rawTheme }\n // parse into variables\n for (const key in theme) {\n // make sure properly names theme variables\n ensureThemeVariable(theme, key)\n }\n themes[themeName] = theme\n\n // set deduped\n dedupedThemes[themeName] = {\n names: [themeName],\n theme,\n }\n existing.set(rawTheme, dedupedThemes[themeName])\n }\n\n // then, generate CSS from de-duped\n if (isWeb) {\n for (const themeName in dedupedThemes) {\n cssRuleSets = [\n ...cssRuleSets,\n ...getThemeCSSRules({\n config,\n themeName,\n ...dedupedThemes[themeName],\n }),\n ]\n }\n }\n\n // proxy upwards to get parent variables (themes are subset going down)\n for (const themeName in themes) {\n themes[themeName] = proxyThemeToParents(themeName, themes[themeName], themes)\n }\n\n tokensValueToVariable.clear()\n Object.freeze(cssRuleSets)\n const css = cssRuleSets.join('\\n')\n\n return {\n themes,\n cssRuleSets,\n css,\n }\n })()\n\n // faster lookups token keys become $keys to match input\n const tokensParsed: any = parseTokens(config.tokens)\n\n const getCSS = () => {\n return `${themeConfig.css}\\n${getAllRules().join('\\n')}`\n }\n\n const shorthands = config.shorthands || {}\n\n const next: TamaguiInternalConfig = {\n fontLanguages: [],\n defaultTheme: 'light',\n animations: {} as any,\n media: {},\n ...config,\n shorthands,\n inverseShorthands: shorthands\n ? Object.fromEntries(Object.entries(shorthands).map(([k, v]) => [v, k]))\n : {},\n themes: themeConfig.themes,\n fontsParsed,\n themeConfig,\n tokensParsed,\n parsed: true,\n getCSS,\n Provider: null as any,\n }\n\n next.Provider = createTamaguiProvider(next)\n\n setConfig(next)\n\n if (configListeners.size) {\n configListeners.forEach((cb) => cb(next))\n configListeners.clear()\n }\n\n createdConfigs.set(next, true)\n\n if (process.env.NODE_ENV === 'development') {\n if (!globalThis['Tamagui']) {\n globalThis['Tamagui'] = Tamagui\n }\n }\n\n // @ts-expect-error\n return next\n}\n\nconst parseTokens = (tokens: any) => {\n const res: any = {}\n for (const key in tokens) {\n res[key] = {}\n for (const skey in tokens[key]) {\n res[key][`$${skey}`] = tokens[key][skey]\n }\n }\n return res\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/esm/createTheme.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/createTheme.ts"],
|
|
4
|
-
"sourcesContent": ["import { Variable } from './createVariable'\n\ntype GenericTheme = { [key: string]: string | Variable }\n\
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import { Variable } from './createVariable'\n\ntype GenericTheme = { [key: string]: string | Variable }\n\n// export const themeToVariableToValueMap = new WeakMap<any, Record<string, string>>()\n\nexport const createTheme = <Theme extends GenericTheme>(\n theme: Theme\n): {\n [K in keyof Theme]: Theme[K] | string | Variable\n} => {\n return theme\n}\n"],
|
|
5
|
+
"mappings": "AAMO,MAAM,cAAc,CACzB,UAGG;AACH,SAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { THEME_CLASSNAME_PREFIX } from "./constants/constants";
|
|
2
|
+
import { createVariable, isVariable } from "./createVariable";
|
|
3
|
+
import { tokensValueToVariable } from "./helpers/registerCSSVariable";
|
|
4
|
+
import { GetThemeUnwrapped } from "./hooks/getThemeUnwrapped";
|
|
5
|
+
const themes = {};
|
|
6
|
+
function ensureThemeVariable(theme, key) {
|
|
7
|
+
const val = theme[key];
|
|
8
|
+
const themeKey = key;
|
|
9
|
+
if (!isVariable(val)) {
|
|
10
|
+
theme[key] = createVariable({
|
|
11
|
+
key: themeKey,
|
|
12
|
+
name: themeKey,
|
|
13
|
+
val
|
|
14
|
+
});
|
|
15
|
+
} else {
|
|
16
|
+
if (val.name !== themeKey) {
|
|
17
|
+
theme[key] = createVariable({
|
|
18
|
+
key: val.name,
|
|
19
|
+
name: themeKey,
|
|
20
|
+
val: val.val
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function proxyThemeToParents(themeName, themes2) {
|
|
26
|
+
const cur = [];
|
|
27
|
+
const parents = themeName.split("_").slice(0, -1).map((part) => {
|
|
28
|
+
cur.push(part);
|
|
29
|
+
return cur.join("_");
|
|
30
|
+
});
|
|
31
|
+
if (!parents.length) {
|
|
32
|
+
return themes2[themeName];
|
|
33
|
+
}
|
|
34
|
+
const og = themes2[themeName];
|
|
35
|
+
return new Proxy(og, {
|
|
36
|
+
get(target, key) {
|
|
37
|
+
if (key === GetThemeUnwrapped) {
|
|
38
|
+
return og;
|
|
39
|
+
}
|
|
40
|
+
if (Reflect.has(target, key)) {
|
|
41
|
+
return Reflect.get(target, key);
|
|
42
|
+
}
|
|
43
|
+
for (let i = parents.length - 1; i >= 0; i--) {
|
|
44
|
+
const parent = themes2[parents[i]];
|
|
45
|
+
if (!parent) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (Reflect.has(parent, key)) {
|
|
49
|
+
return Reflect.get(parent, key);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return Reflect.get(target, key);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function getThemeCSSRules({
|
|
57
|
+
config,
|
|
58
|
+
themeName,
|
|
59
|
+
theme,
|
|
60
|
+
names
|
|
61
|
+
}) {
|
|
62
|
+
const cssRuleSets = [];
|
|
63
|
+
const hasDarkLight = "light" in config.themes && "dark" in config.themes;
|
|
64
|
+
const CNP = `.${THEME_CLASSNAME_PREFIX}`;
|
|
65
|
+
let vars = "";
|
|
66
|
+
for (const themeKey in theme) {
|
|
67
|
+
const variable = theme[themeKey];
|
|
68
|
+
let value = null;
|
|
69
|
+
if (variable.isFloating || !tokensValueToVariable.has(variable.val)) {
|
|
70
|
+
value = variable.val;
|
|
71
|
+
} else {
|
|
72
|
+
value = tokensValueToVariable.get(variable.val).variable;
|
|
73
|
+
}
|
|
74
|
+
vars += `--${themeKey}:${value};`;
|
|
75
|
+
}
|
|
76
|
+
const isDarkOrLightBase = themeName === "dark" || themeName === "light";
|
|
77
|
+
const selectors = names.map((name) => {
|
|
78
|
+
return `${CNP}${name}`;
|
|
79
|
+
});
|
|
80
|
+
if (hasDarkLight) {
|
|
81
|
+
for (const subName of names) {
|
|
82
|
+
const isDark = isDarkOrLightBase || subName.startsWith("dark_");
|
|
83
|
+
const childSelector = `${CNP}${subName.replace(isDark ? "dark_" : "light_", "")}`;
|
|
84
|
+
const order = isDark ? ["dark", "light"] : ["light", "dark"];
|
|
85
|
+
if (isDarkOrLightBase) {
|
|
86
|
+
order.reverse();
|
|
87
|
+
}
|
|
88
|
+
const [stronger, weaker] = order;
|
|
89
|
+
const max = config.maxDarkLightNesting ?? 3;
|
|
90
|
+
new Array(Math.round(max * 1.5)).fill(void 0).forEach((_, pi) => {
|
|
91
|
+
const isOdd = pi % 2 === 1;
|
|
92
|
+
if (isOdd && pi < 3)
|
|
93
|
+
return;
|
|
94
|
+
const parents = new Array(pi + 1).fill(void 0).map((_2, psi) => {
|
|
95
|
+
return `${CNP}${psi % 2 === 0 ? stronger : weaker}`;
|
|
96
|
+
});
|
|
97
|
+
let parentSelectors = parents.length > 1 ? parents.slice(1) : parents;
|
|
98
|
+
if (isOdd) {
|
|
99
|
+
const [_first, second, ...rest] = parentSelectors;
|
|
100
|
+
parentSelectors = [second, ...rest, second];
|
|
101
|
+
}
|
|
102
|
+
const lastParentSelector = parentSelectors[parentSelectors.length - 1];
|
|
103
|
+
selectors.push(`${parentSelectors.join(" ")} ${childSelector === lastParentSelector ? "" : childSelector}`);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const rootSep = config.themeClassNameOnRoot ? "" : " ";
|
|
108
|
+
const css = `${selectors.map((x) => `:root${rootSep}${x}`).join(", ")} {${vars}}`;
|
|
109
|
+
cssRuleSets.push(css);
|
|
110
|
+
if (config.shouldAddPrefersColorThemes && isDarkOrLightBase) {
|
|
111
|
+
const isDark = themeName.startsWith("dark");
|
|
112
|
+
cssRuleSets.push(`@media(prefers-color-scheme: ${isDark ? "dark" : "light"}) {
|
|
113
|
+
body { background:${theme.background}; color: ${theme.color} }
|
|
114
|
+
:root {${vars} }
|
|
115
|
+
}`);
|
|
116
|
+
}
|
|
117
|
+
return cssRuleSets;
|
|
118
|
+
}
|
|
119
|
+
export {
|
|
120
|
+
ensureThemeVariable,
|
|
121
|
+
getThemeCSSRules,
|
|
122
|
+
proxyThemeToParents,
|
|
123
|
+
themes
|
|
124
|
+
};
|
|
125
|
+
//# sourceMappingURL=ensureThemeVariable.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/ensureThemeVariable.ts"],
|
|
4
|
+
"sourcesContent": ["import { THEME_CLASSNAME_PREFIX } from './constants/constants'\nimport { Variable, createVariable, isVariable } from './createVariable'\nimport { tokensValueToVariable } from './helpers/registerCSSVariable'\nimport { GetThemeUnwrapped } from './hooks/getThemeUnwrapped'\nimport { CreateTamaguiProps, ThemeObject } from './types'\n\nexport const themes = {}\n// mutates, freeze after\n// shared by createTamagui so extracted here\nexport function ensureThemeVariable(theme: any, key: string) {\n const val = theme[key]\n const themeKey = key\n if (!isVariable(val)) {\n theme[key] = createVariable({\n key: themeKey,\n name: themeKey,\n val,\n })\n } else {\n if (val.name !== themeKey) {\n // rename to theme name\n theme[key] = createVariable({\n key: val.name,\n name: themeKey,\n val: val.val,\n })\n }\n }\n}\nexport function proxyThemeToParents(themeName: string, themes: CreateTamaguiProps['themes']) {\n // we could test if this is better as just a straight object spread or fancier proxy\n const cur: string[] = []\n // if theme is dark_blue_alt1_Button\n // this will be the parent names in order: ['dark', 'dark_blue', 'dark_blue_alt1\"]\n const parents = themeName\n .split('_')\n .slice(0, -1)\n .map((part) => {\n cur.push(part)\n return cur.join('_')\n })\n\n if (!parents.length) {\n return themes[themeName]\n }\n\n // proxy fallback values to parent theme values\n const og = themes[themeName]\n return new Proxy(og, {\n get(target, key) {\n if (key === GetThemeUnwrapped) {\n return og\n }\n if (Reflect.has(target, key)) {\n return Reflect.get(target, key)\n }\n // check parents\n for (let i = parents.length - 1; i >= 0; i--) {\n const parent = themes[parents[i]]\n if (!parent) {\n continue\n }\n if (Reflect.has(parent, key)) {\n return Reflect.get(parent, key)\n }\n }\n return Reflect.get(target, key)\n },\n })\n}\nexport function getThemeCSSRules({\n config,\n themeName,\n theme,\n names,\n}: {\n config: CreateTamaguiProps\n themeName: string\n theme: ThemeObject\n names: string[]\n}) {\n const cssRuleSets: string[] = []\n\n // special case for SSR\n const hasDarkLight = 'light' in config.themes && 'dark' in config.themes\n const CNP = `.${THEME_CLASSNAME_PREFIX}`\n let vars = ''\n\n // themeToVariableToValueMap.set(theme, {})\n // const varToValMap = themeToVariableToValueMap.get(theme)\n for (const themeKey in theme) {\n const variable = theme[themeKey] as Variable\n let value: any = null\n // if (varToValMap) {\n // varToValMap[variable.variable] = variable.val\n // }\n if (variable.isFloating || !tokensValueToVariable.has(variable.val)) {\n value = variable.val\n } else {\n value = tokensValueToVariable.get(variable.val)!.variable\n }\n vars += `--${themeKey}:${value};`\n }\n\n const isDarkOrLightBase = themeName === 'dark' || themeName === 'light'\n const selectors = names.map((name) => {\n return `${CNP}${name}`\n })\n\n // since we dont specify dark/light in classnames we have to do an awkward specificity war\n // use config.maxDarkLightNesting to determine how deep you can nest until it breaks\n if (hasDarkLight) {\n for (const subName of names) {\n const isDark = isDarkOrLightBase || subName.startsWith('dark_')\n const childSelector = `${CNP}${subName.replace(isDark ? 'dark_' : 'light_', '')}`\n const order = isDark ? ['dark', 'light'] : ['light', 'dark']\n if (isDarkOrLightBase) {\n order.reverse()\n }\n const [stronger, weaker] = order\n const max = config.maxDarkLightNesting ?? 3\n\n new Array(Math.round(max * 1.5)).fill(undefined).forEach((_, pi) => {\n const isOdd = pi % 2 === 1\n if (isOdd && pi < 3) return\n const parents = new Array(pi + 1).fill(undefined).map((_, psi) => {\n return `${CNP}${psi % 2 === 0 ? stronger : weaker}`\n })\n let parentSelectors = parents.length > 1 ? parents.slice(1) : parents\n if (isOdd) {\n const [_first, second, ...rest] = parentSelectors\n parentSelectors = [second, ...rest, second]\n }\n // avoid .t_light .t_light at the end (make sure child is unique from last parent)\n const lastParentSelector = parentSelectors[parentSelectors.length - 1]\n selectors.push(\n `${parentSelectors.join(' ')} ${\n childSelector === lastParentSelector ? '' : childSelector\n }`\n )\n })\n }\n }\n\n const rootSep = config.themeClassNameOnRoot ? '' : ' '\n const css = `${selectors.map((x) => `:root${rootSep}${x}`).join(', ')} {${vars}}`\n cssRuleSets.push(css)\n\n if (config.shouldAddPrefersColorThemes && isDarkOrLightBase) {\n // add media prefers for dark/light base\n const isDark = themeName.startsWith('dark')\n cssRuleSets.push(\n `@media(prefers-color-scheme: ${isDark ? 'dark' : 'light'}) {\nbody { background:${theme.background}; color: ${theme.color} }\n:root {${vars} } \n}`\n )\n }\n\n return cssRuleSets\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { createContext } from "react";
|
|
2
|
+
import { getThemes } from "../conf";
|
|
3
|
+
import { THEME_CLASSNAME_PREFIX, THEME_NAME_SEPARATOR } from "../constants/constants";
|
|
4
|
+
import { getThemeUnwrapped } from "../hooks/getThemeUnwrapped";
|
|
5
|
+
class ThemeManager {
|
|
6
|
+
constructor(name = "", theme = null, parentManager = null, reset = false) {
|
|
7
|
+
this.name = name;
|
|
8
|
+
this.theme = theme;
|
|
9
|
+
this.parentManager = parentManager;
|
|
10
|
+
this.reset = reset;
|
|
11
|
+
this.keys = /* @__PURE__ */ new Map();
|
|
12
|
+
this.listeners = /* @__PURE__ */ new Map();
|
|
13
|
+
this.themeListeners = /* @__PURE__ */ new Set();
|
|
14
|
+
this.className = null;
|
|
15
|
+
let parent = parentManager;
|
|
16
|
+
let tries = 0;
|
|
17
|
+
while (true) {
|
|
18
|
+
tries++;
|
|
19
|
+
if (tries > 10) {
|
|
20
|
+
throw new Error(`Nested 10 of the same theme in a row, likely error`);
|
|
21
|
+
}
|
|
22
|
+
if (!parent)
|
|
23
|
+
break;
|
|
24
|
+
if (parent.name === name) {
|
|
25
|
+
parent = parent.parentManager;
|
|
26
|
+
} else {
|
|
27
|
+
this.parentManager = parent;
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
get didChangeTheme() {
|
|
33
|
+
return this.parentManager && this.name !== this.parentManager.fullName;
|
|
34
|
+
}
|
|
35
|
+
get parentName() {
|
|
36
|
+
var _a;
|
|
37
|
+
return ((_a = this.parentManager) == null ? void 0 : _a.name) || null;
|
|
38
|
+
}
|
|
39
|
+
get fullName() {
|
|
40
|
+
return this.getNextTheme().name || this.name || "";
|
|
41
|
+
}
|
|
42
|
+
getValue(key) {
|
|
43
|
+
let theme = this.theme;
|
|
44
|
+
let manager = this;
|
|
45
|
+
while (true) {
|
|
46
|
+
if (!theme)
|
|
47
|
+
return;
|
|
48
|
+
if (key in theme) {
|
|
49
|
+
return theme[key];
|
|
50
|
+
}
|
|
51
|
+
manager = this.parentManager;
|
|
52
|
+
if (!manager || manager.theme === theme) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
theme = manager.theme;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
update({ name, theme, className } = {}, force = false) {
|
|
59
|
+
if (!force) {
|
|
60
|
+
const nameChanged = name !== this.name;
|
|
61
|
+
if (!nameChanged) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
this.className = className || null;
|
|
66
|
+
this.name = name || "";
|
|
67
|
+
this.theme = theme;
|
|
68
|
+
this.notifyListeners();
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
getNextTheme(props = {}, debug) {
|
|
72
|
+
var _a;
|
|
73
|
+
const { themes = getThemes(), name, componentName } = props;
|
|
74
|
+
if (props.reset && name) {
|
|
75
|
+
return {
|
|
76
|
+
name,
|
|
77
|
+
theme: themes[name],
|
|
78
|
+
className: this.getClassName(name)
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const parentIsReset = (_a = this.parentManager) == null ? void 0 : _a.reset;
|
|
82
|
+
if (!name) {
|
|
83
|
+
if (componentName) {
|
|
84
|
+
const names = [
|
|
85
|
+
`${this.name}_${componentName}`,
|
|
86
|
+
`${withoutComponentName(this.name)}_${componentName}`
|
|
87
|
+
];
|
|
88
|
+
for (const name2 of names) {
|
|
89
|
+
if (name2 in themes) {
|
|
90
|
+
const className = this.getClassName(name2);
|
|
91
|
+
return { name: name2, theme: themes[name2], className };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
name: this.name,
|
|
97
|
+
theme: this.theme
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
let nextName = name || this.name || "";
|
|
101
|
+
let parentName = parentIsReset ? this.parentName || this.fullName : this.fullName;
|
|
102
|
+
while (true) {
|
|
103
|
+
if (nextName in themes) {
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
nextName = `${parentName}_${name}`;
|
|
107
|
+
if (nextName in themes) {
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
if (!parentName.includes(THEME_NAME_SEPARATOR)) {
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
parentName = parentName.slice(0, parentName.lastIndexOf(THEME_NAME_SEPARATOR));
|
|
114
|
+
}
|
|
115
|
+
if (componentName) {
|
|
116
|
+
const names = [
|
|
117
|
+
`${nextName}_${componentName}`,
|
|
118
|
+
`${withoutComponentName(nextName)}_${componentName}`
|
|
119
|
+
];
|
|
120
|
+
for (const name2 of names) {
|
|
121
|
+
if (name2 in themes) {
|
|
122
|
+
nextName = name2;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
let theme = themes[nextName];
|
|
127
|
+
if (!theme) {
|
|
128
|
+
theme = themes[`light_${nextName}`];
|
|
129
|
+
}
|
|
130
|
+
if (process.env.NODE_ENV === "development") {
|
|
131
|
+
if (debug) {
|
|
132
|
+
console.log("getNextTheme", this.getClassName(nextName), { props, nextName, parentName });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
name: nextName,
|
|
137
|
+
theme: getThemeUnwrapped(theme),
|
|
138
|
+
className: this.getClassName(nextName)
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
getClassName(name) {
|
|
142
|
+
return `${THEME_CLASSNAME_PREFIX}${name} t_Theme`.replace("light_", "").replace("dark_", "");
|
|
143
|
+
}
|
|
144
|
+
track(uuid, keys) {
|
|
145
|
+
if (!this.name)
|
|
146
|
+
return;
|
|
147
|
+
this.keys.set(uuid, keys);
|
|
148
|
+
}
|
|
149
|
+
notifyListeners() {
|
|
150
|
+
var _a;
|
|
151
|
+
if (!this.name) {
|
|
152
|
+
this.keys.clear();
|
|
153
|
+
}
|
|
154
|
+
for (const [uuid, keys] of this.keys.entries()) {
|
|
155
|
+
if (keys.size) {
|
|
156
|
+
(_a = this.listeners.get(uuid)) == null ? void 0 : _a();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
this.themeListeners.forEach((cb) => cb(this.name, this));
|
|
160
|
+
}
|
|
161
|
+
onChangeTheme(cb) {
|
|
162
|
+
this.themeListeners.add(cb);
|
|
163
|
+
return () => {
|
|
164
|
+
this.themeListeners.delete(cb);
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
onUpdate(uuid, cb) {
|
|
168
|
+
this.listeners.set(uuid, cb);
|
|
169
|
+
return () => {
|
|
170
|
+
this.listeners.delete(uuid);
|
|
171
|
+
this.keys.delete(uuid);
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const ThemeManagerContext = createContext(null);
|
|
176
|
+
const emptyManager = new ThemeManager();
|
|
177
|
+
const withoutComponentName = (name) => name.replace(/(\_[A-Z][a-zA-Z]+)+$/g, "");
|
|
178
|
+
export {
|
|
179
|
+
ThemeManager,
|
|
180
|
+
ThemeManagerContext,
|
|
181
|
+
emptyManager
|
|
182
|
+
};
|
|
183
|
+
//# sourceMappingURL=ThemeManager.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/helpers/ThemeManager.tsx"],
|
|
4
|
+
"sourcesContent": ["import { createContext } from 'react'\n\nimport { getThemes } from '../conf'\nimport { THEME_CLASSNAME_PREFIX, THEME_NAME_SEPARATOR } from '../constants/constants'\nimport { getThemeUnwrapped } from '../hooks/getThemeUnwrapped'\nimport { ThemeObject, Themes } from '../types'\n\ntype ThemeListener = (name: string | null, themeManager: ThemeManager) => void\n\nexport type SetActiveThemeProps = {\n className?: string\n parentManager?: ThemeManager | null\n name?: string | null\n theme?: any\n}\n\nexport type GetNextThemeProps = {\n themes?: Themes\n name?: string | null\n componentName?: string | null\n reset?: boolean\n}\n\nexport class ThemeManager {\n keys = new Map<any, Set<string>>()\n listeners = new Map<any, Function>()\n themeListeners = new Set<ThemeListener>()\n className: string | null = null\n\n constructor(\n public name: string = '',\n public theme: ThemeObject | null = null,\n public parentManager: ThemeManager | null = null,\n public reset: boolean = false\n ) {\n // find the nearest different parentManager\n let parent = parentManager\n let tries = 0\n while (true) {\n tries++\n if (tries > 10) {\n throw new Error(`Nested 10 of the same theme in a row, likely error`)\n }\n if (!parent) break\n if (parent.name === name) {\n // go up if same\n parent = parent.parentManager\n } else {\n this.parentManager = parent\n break\n }\n }\n }\n\n get didChangeTheme() {\n return this.parentManager && this.name !== this.parentManager.fullName\n }\n\n get parentName() {\n return this.parentManager?.name || null\n }\n\n get fullName(): string {\n return this.getNextTheme().name || this.name || ''\n // const parentName = this.parentManager?.fullName || ''\n // const name = this.name || ''\n // const parts = [...new Set([...`${parentName}_${name}`.split('_')])].filter(Boolean)\n // return parts.join('_')\n }\n\n // gets value going up to parents\n getValue(key: string) {\n let theme = this.theme\n let manager = this as ThemeManager | null\n while (true) {\n if (!theme) return\n if (key in theme) {\n return theme[key]\n }\n manager = this.parentManager\n if (!manager || manager.theme === theme) {\n return\n }\n theme = manager.theme\n }\n }\n\n update({ name, theme, className }: SetActiveThemeProps = {}, force = false) {\n if (!force) {\n // className compare on web, avoids light/dark re-renders\n const nameChanged = name !== this.name\n if (!nameChanged) {\n return false\n }\n }\n this.className = className || null\n this.name = name || ''\n this.theme = theme\n this.notifyListeners()\n return true\n }\n\n getNextTheme(props: GetNextThemeProps = {}, debug?: any) {\n const { themes = getThemes(), name, componentName } = props\n\n if (props.reset && name) {\n return {\n name: name,\n theme: themes[name],\n className: this.getClassName(name),\n }\n }\n\n const parentIsReset = this.parentManager?.reset\n\n if (!name) {\n if (componentName) {\n // allow for _Card_Button or just _Button\n const names = [\n `${this.name}_${componentName}`,\n `${withoutComponentName(this.name)}_${componentName}`,\n ]\n for (const name of names) {\n if (name in themes) {\n const className = this.getClassName(name)\n return { name, theme: themes[name], className }\n }\n }\n }\n return {\n name: this.name,\n theme: this.theme,\n }\n }\n\n let nextName = name || this.name || ''\n let parentName = parentIsReset ? this.parentName || this.fullName : this.fullName\n\n while (true) {\n if (nextName in themes) {\n break\n }\n nextName = `${parentName}_${name}`\n if (nextName in themes) {\n break\n }\n if (!parentName.includes(THEME_NAME_SEPARATOR)) {\n // this is fine - some themes can not have parents\n break\n }\n // go up one\n parentName = parentName.slice(0, parentName.lastIndexOf(THEME_NAME_SEPARATOR))\n }\n\n if (componentName) {\n // allow for _Card_Button or just _Button\n const names = [\n `${nextName}_${componentName}`,\n `${withoutComponentName(nextName)}_${componentName}`,\n ]\n for (const name of names) {\n if (name in themes) {\n nextName = name\n }\n }\n }\n\n let theme = themes[nextName]\n if (!theme) {\n theme = themes[`light_${nextName}`]\n }\n\n if (process.env.NODE_ENV === 'development') {\n if (debug) {\n console.log('getNextTheme', this.getClassName(nextName), { props, nextName, parentName })\n }\n }\n\n return {\n name: nextName,\n theme: getThemeUnwrapped(theme),\n className: this.getClassName(nextName),\n }\n }\n\n getClassName(name: string) {\n return `${THEME_CLASSNAME_PREFIX}${name} t_Theme`.replace('light_', '').replace('dark_', '')\n }\n\n track(uuid: any, keys: Set<string>) {\n if (!this.name) return\n this.keys.set(uuid, keys)\n }\n\n notifyListeners() {\n if (!this.name) {\n this.keys.clear()\n }\n for (const [uuid, keys] of this.keys.entries()) {\n if (keys.size) {\n this.listeners.get(uuid)?.()\n }\n }\n this.themeListeners.forEach((cb) => cb(this.name, this))\n }\n\n onChangeTheme(cb: ThemeListener) {\n this.themeListeners.add(cb)\n return () => {\n this.themeListeners.delete(cb)\n }\n }\n\n onUpdate(uuid: any, cb: Function) {\n this.listeners.set(uuid, cb)\n return () => {\n this.listeners.delete(uuid)\n this.keys.delete(uuid)\n }\n }\n}\n\nexport const ThemeManagerContext = createContext<ThemeManager | null>(null)\nexport const emptyManager = new ThemeManager()\n\nconst withoutComponentName = (name: string) => name.replace(/(\\_[A-Z][a-zA-Z]+)+$/g, '')\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -35,6 +35,7 @@ function assignNativePropsToWeb(elementType, viewProps, nativeProps) {
|
|
|
35
35
|
viewProps["aria-colspan"] = nativeProps.accessibilityColumnSpan;
|
|
36
36
|
}
|
|
37
37
|
if (nativeProps.accessibilityControls != null) {
|
|
38
|
+
console.log("wtf", nativeProps.accessibilityControls);
|
|
38
39
|
viewProps["aria-controls"] = processIDRefList(nativeProps.accessibilityControls);
|
|
39
40
|
}
|
|
40
41
|
if (nativeProps.accessibilityCurrent != null) {
|