@tamagui/web 1.88.13 → 1.89.0-1706308641099
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/LICENSE +21 -0
- package/dist/cjs/createComponent.js +1 -1
- package/dist/cjs/createComponent.js.map +1 -1
- package/dist/cjs/helpers/getSplitStyles.js +1 -1
- package/dist/cjs/helpers/getSplitStyles.js.map +1 -1
- package/dist/cjs/helpers/getSplitStyles.native.js +1 -1
- package/dist/cjs/helpers/getSplitStyles.native.js.map +1 -1
- package/dist/esm/Tamagui.mjs +43 -0
- package/dist/esm/config.mjs +51 -0
- package/dist/esm/constants/accessibilityDirectMap.mjs +50 -0
- package/dist/esm/constants/constants.mjs +16 -0
- package/dist/esm/constants/isDevTools.mjs +7 -0
- package/dist/esm/contexts/ComponentContext.mjs +13 -0
- package/dist/esm/createComponent.js +1 -1
- package/dist/esm/createComponent.js.map +1 -1
- package/dist/esm/createComponent.mjs +771 -0
- package/dist/esm/createFont.mjs +18 -0
- package/dist/esm/createShorthands.mjs +4 -0
- package/dist/esm/createTamagui.mjs +206 -0
- package/dist/esm/createTheme.mjs +2 -0
- package/dist/esm/createTokens.mjs +5 -0
- package/dist/esm/createVariable.mjs +48 -0
- package/dist/esm/createVariables.mjs +35 -0
- package/dist/esm/defaultComponentState.mjs +16 -0
- package/dist/esm/helpers/ThemeManager.mjs +156 -0
- package/dist/esm/helpers/ThemeManagerContext.mjs +3 -0
- package/dist/esm/helpers/createMediaStyle.mjs +71 -0
- package/dist/esm/helpers/createShallowSetState.mjs +17 -0
- package/dist/esm/helpers/createStyledContext.mjs +35 -0
- package/dist/esm/helpers/defaultOffset.mjs +5 -0
- package/dist/esm/helpers/expandStyle.mjs +38 -0
- package/dist/esm/helpers/expandStyles.mjs +15 -0
- package/dist/esm/helpers/getExpandedShorthands.mjs +9 -0
- package/dist/esm/helpers/getFontLanguage.mjs +2 -0
- package/dist/esm/helpers/getGroupPropParts.mjs +13 -0
- package/dist/esm/helpers/getSplitStyles.js +1 -1
- package/dist/esm/helpers/getSplitStyles.js.map +1 -1
- package/dist/esm/helpers/getSplitStyles.mjs +643 -0
- package/dist/esm/helpers/getSplitStyles.native.js +1 -1
- package/dist/esm/helpers/getSplitStyles.native.js.map +1 -1
- package/dist/esm/helpers/getStylesAtomic.mjs +150 -0
- package/dist/esm/helpers/getThemeCSSRules.mjs +87 -0
- package/dist/esm/helpers/getVariantExtras.mjs +43 -0
- package/dist/esm/helpers/insertStyleRule.mjs +177 -0
- package/dist/esm/helpers/isObj.mjs +2 -0
- package/dist/esm/helpers/isTamaguiComponent.mjs +5 -0
- package/dist/esm/helpers/isTamaguiElement.mjs +4 -0
- package/dist/esm/helpers/log.mjs +4 -0
- package/dist/esm/helpers/matchMedia.mjs +11 -0
- package/dist/esm/helpers/mergeProps.mjs +21 -0
- package/dist/esm/helpers/mergeVariants.mjs +16 -0
- package/dist/esm/helpers/normalizeColor.mjs +17 -0
- package/dist/esm/helpers/normalizeShadow.mjs +23 -0
- package/dist/esm/helpers/normalizeStyle.mjs +23 -0
- package/dist/esm/helpers/normalizeStylePropKeys.mjs +2 -0
- package/dist/esm/helpers/normalizeValueWithProperty.mjs +32 -0
- package/dist/esm/helpers/objectIdentityKey.mjs +15 -0
- package/dist/esm/helpers/propMapper.mjs +239 -0
- package/dist/esm/helpers/proxyThemeToParents.mjs +36 -0
- package/dist/esm/helpers/proxyThemeVariables.mjs +12 -0
- package/dist/esm/helpers/pseudoDescriptors.mjs +34 -0
- package/dist/esm/helpers/registerCSSVariable.mjs +7 -0
- package/dist/esm/helpers/themeable.mjs +33 -0
- package/dist/esm/helpers/themes.mjs +14 -0
- package/dist/esm/helpers/timer.mjs +8 -0
- package/dist/esm/hooks/useConfiguration.mjs +20 -0
- package/dist/esm/hooks/useDisableSSR.mjs +5 -0
- package/dist/esm/hooks/useIsTouchDevice.mjs +4 -0
- package/dist/esm/hooks/useMedia.mjs +146 -0
- package/dist/esm/hooks/useProps.mjs +40 -0
- package/dist/esm/hooks/useTheme.mjs +222 -0
- package/dist/esm/hooks/useThemeName.mjs +15 -0
- package/dist/esm/index.mjs +61 -0
- package/dist/esm/inject-styles.mjs +13 -0
- package/dist/esm/insertFont.mjs +44 -0
- package/dist/esm/interfaces/CSSColorNames.mjs +0 -0
- package/dist/esm/interfaces/GetRef.mjs +0 -0
- package/dist/esm/interfaces/KeyTypes.mjs +0 -0
- package/dist/esm/interfaces/RNExclusiveTypes.mjs +0 -0
- package/dist/esm/interfaces/Role.mjs +0 -0
- package/dist/esm/interfaces/TamaguiComponentEvents.mjs +0 -0
- package/dist/esm/interfaces/TamaguiComponentPropsBaseBase.mjs +0 -0
- package/dist/esm/interfaces/TamaguiComponentState.mjs +0 -0
- package/dist/esm/interfaces/WebOnlyPressEvents.mjs +0 -0
- package/dist/esm/internalWithTheme.mjs +14 -0
- package/dist/esm/setupHooks.mjs +5 -0
- package/dist/esm/setupReactNative.mjs +24 -0
- package/dist/esm/styled.mjs +56 -0
- package/dist/esm/type-utils.mjs +0 -0
- package/dist/esm/types.mjs +2 -0
- package/dist/esm/views/Configuration.mjs +12 -0
- package/dist/esm/views/FontLanguage.mjs +13 -0
- package/dist/esm/views/FontLanguage.types.mjs +0 -0
- package/dist/esm/views/Slot.mjs +53 -0
- package/dist/esm/views/Stack.mjs +10 -0
- package/dist/esm/views/TamaguiProvider.mjs +32 -0
- package/dist/esm/views/Text.mjs +64 -0
- package/dist/esm/views/Theme.mjs +104 -0
- package/dist/esm/views/ThemeDebug.mjs +57 -0
- package/dist/esm/views/ThemeProvider.mjs +20 -0
- package/dist/esm/views/View.mjs +9 -0
- package/package.json +10 -10
- package/src/createComponent.tsx +1 -1
- package/src/helpers/getSplitStyles.tsx +5 -0
- package/types/helpers/getSplitStyles.d.ts.map +1 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const fontWeights = ["100", "200", "300", "400", "500", "600", "700", "800", "900"],
|
|
2
|
+
processSection = (section, keys, defaultValue) => {
|
|
3
|
+
if (typeof section == "string") return section;
|
|
4
|
+
const sectionKeys = Object.keys(section);
|
|
5
|
+
let fillValue = section[sectionKeys[0]];
|
|
6
|
+
return Object.fromEntries([... /* @__PURE__ */new Set([...keys, ...sectionKeys])].map(key => {
|
|
7
|
+
const value = section[key] ?? defaultValue ?? fillValue;
|
|
8
|
+
return fillValue = value, defaultValue = value, [key, value];
|
|
9
|
+
}));
|
|
10
|
+
},
|
|
11
|
+
createFont = font => {
|
|
12
|
+
const sizeKeys = Object.keys(font.size),
|
|
13
|
+
processedFont = Object.fromEntries(Object.entries(font).map(([key, section]) => [key, processSection(section, key === "face" ? fontWeights : sizeKeys, key === "face" ? {
|
|
14
|
+
normal: font.family
|
|
15
|
+
} : void 0)]));
|
|
16
|
+
return Object.freeze(processedFont);
|
|
17
|
+
};
|
|
18
|
+
export { createFont };
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { isWeb } from "@tamagui/constants";
|
|
2
|
+
import { configListeners, setConfig, setTokens } from "./config.mjs";
|
|
3
|
+
import { createVariables } from "./createVariables.mjs";
|
|
4
|
+
import { getThemeCSSRules } from "./helpers/getThemeCSSRules.mjs";
|
|
5
|
+
import { getAllRules, listenForSheetChanges, scanAllSheets } from "./helpers/insertStyleRule.mjs";
|
|
6
|
+
import { proxyThemesToParents } from "./helpers/proxyThemeToParents.mjs";
|
|
7
|
+
import { registerCSSVariable, variableToCSS } from "./helpers/registerCSSVariable.mjs";
|
|
8
|
+
import { ensureThemeVariable } from "./helpers/themes.mjs";
|
|
9
|
+
import { configureMedia } from "./hooks/useMedia.mjs";
|
|
10
|
+
import { parseFont, registerFontVariables } from "./insertFont.mjs";
|
|
11
|
+
import { Tamagui } from "./Tamagui.mjs";
|
|
12
|
+
const createdConfigs = /* @__PURE__ */new WeakMap();
|
|
13
|
+
function createTamagui(configIn) {
|
|
14
|
+
if (createdConfigs.has(configIn)) return configIn;
|
|
15
|
+
const tokensParsed = {},
|
|
16
|
+
tokens = createVariables(configIn.tokens || {});
|
|
17
|
+
if (configIn.tokens) {
|
|
18
|
+
const tokensMerged = {};
|
|
19
|
+
for (const cat in tokens) {
|
|
20
|
+
tokensParsed[cat] = {}, tokensMerged[cat] = {};
|
|
21
|
+
const tokenCat = tokens[cat];
|
|
22
|
+
for (const key in tokenCat) {
|
|
23
|
+
const val = tokenCat[key],
|
|
24
|
+
prefixedKey = `$${key}`;
|
|
25
|
+
tokensParsed[cat][prefixedKey] = val, tokensMerged[cat][prefixedKey] = val, tokensMerged[cat][key] = val;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
setTokens(tokensMerged);
|
|
29
|
+
}
|
|
30
|
+
let foundThemes;
|
|
31
|
+
if (configIn.themes) {
|
|
32
|
+
const noThemes = Object.keys(configIn.themes).length === 0;
|
|
33
|
+
foundThemes = scanAllSheets(noThemes, tokensParsed);
|
|
34
|
+
}
|
|
35
|
+
listenForSheetChanges();
|
|
36
|
+
let fontSizeTokens = null,
|
|
37
|
+
fontsParsed;
|
|
38
|
+
if (configIn.fonts) {
|
|
39
|
+
const fontTokens = Object.fromEntries(Object.entries(configIn.fonts).map(([k, v]) => [k, createVariables(v, "f", !0)]));
|
|
40
|
+
fontsParsed = (() => {
|
|
41
|
+
const res = {};
|
|
42
|
+
for (const familyName in fontTokens) {
|
|
43
|
+
const font = fontTokens[familyName],
|
|
44
|
+
fontParsed = parseFont(font);
|
|
45
|
+
res[`$${familyName}`] = fontParsed, !fontSizeTokens && fontParsed.size && (fontSizeTokens = new Set(Object.keys(fontParsed.size)));
|
|
46
|
+
}
|
|
47
|
+
return res;
|
|
48
|
+
})();
|
|
49
|
+
}
|
|
50
|
+
const specificTokens = {},
|
|
51
|
+
themeConfig = (() => {
|
|
52
|
+
const cssRuleSets = [];
|
|
53
|
+
if (process.env.TAMAGUI_DOES_SSR_CSS !== "true" &&
|
|
54
|
+
// we can leave this out if mutating, only need the js for getThemeCSSRules
|
|
55
|
+
process.env.TAMAGUI_DOES_SSR_CSS !== "mutates-themes") {
|
|
56
|
+
const declarations = [],
|
|
57
|
+
fontDeclarations = {};
|
|
58
|
+
for (const key in tokens) for (const skey in tokens[key]) {
|
|
59
|
+
const variable = tokens[key][skey];
|
|
60
|
+
if (specificTokens[`$${key}.${skey}`] = variable, process.env.NODE_ENV === "development" && typeof variable > "u") throw new Error(`No value for tokens.${key}.${skey}:
|
|
61
|
+
${JSON.stringify(variable, null, 2)}`);
|
|
62
|
+
isWeb && (registerCSSVariable(variable), declarations.push(variableToCSS(variable, key === "zIndex")));
|
|
63
|
+
}
|
|
64
|
+
if (isWeb) {
|
|
65
|
+
let declarationsToRuleSet = function (decs, selector = "") {
|
|
66
|
+
return `:root${selector} {${sep}${[...decs].join(`;${sep}`)}${sep}}`;
|
|
67
|
+
};
|
|
68
|
+
for (const key in fontsParsed) {
|
|
69
|
+
const fontParsed = fontsParsed[key],
|
|
70
|
+
[name, language] = key.includes("_") ? key.split("_") : [key],
|
|
71
|
+
fontVars = registerFontVariables(fontParsed);
|
|
72
|
+
fontDeclarations[key] = {
|
|
73
|
+
name: name.slice(1),
|
|
74
|
+
declarations: fontVars,
|
|
75
|
+
language
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const sep = process.env.NODE_ENV === "development" ? configIn.cssStyleSeparator || " " : "";
|
|
79
|
+
if (cssRuleSets.push(declarationsToRuleSet(declarations)), fontDeclarations) for (const key in fontDeclarations) {
|
|
80
|
+
const {
|
|
81
|
+
name,
|
|
82
|
+
declarations: declarations2,
|
|
83
|
+
language = "default"
|
|
84
|
+
} = fontDeclarations[key],
|
|
85
|
+
fontSelector = `.font_${name}`,
|
|
86
|
+
langSelector = `:root .t_lang-${name}-${language} ${fontSelector}`,
|
|
87
|
+
selectors = language === "default" ? ` ${fontSelector}, ${langSelector}` : langSelector,
|
|
88
|
+
specificRuleSet = declarationsToRuleSet(declarations2, selectors);
|
|
89
|
+
cssRuleSets.push(specificRuleSet);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const themesIn = {
|
|
94
|
+
...configIn.themes
|
|
95
|
+
},
|
|
96
|
+
dedupedThemes = foundThemes ?? getThemesDeduped(themesIn);
|
|
97
|
+
return {
|
|
98
|
+
themes: proxyThemesToParents(dedupedThemes),
|
|
99
|
+
cssRuleSets,
|
|
100
|
+
getThemeRulesSets() {
|
|
101
|
+
let themeRuleSets = [];
|
|
102
|
+
if (isWeb) for (const {
|
|
103
|
+
names,
|
|
104
|
+
theme
|
|
105
|
+
} of dedupedThemes) {
|
|
106
|
+
const nextRules = getThemeCSSRules({
|
|
107
|
+
config: configIn,
|
|
108
|
+
themeName: names[0],
|
|
109
|
+
names,
|
|
110
|
+
theme
|
|
111
|
+
});
|
|
112
|
+
themeRuleSets = [...themeRuleSets, ...nextRules];
|
|
113
|
+
}
|
|
114
|
+
return themeRuleSets;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
})(),
|
|
118
|
+
shorthands = configIn.shorthands || {};
|
|
119
|
+
let lastCSSInsertedRulesIndex = -1;
|
|
120
|
+
const getCSS = ({
|
|
121
|
+
separator = `
|
|
122
|
+
`,
|
|
123
|
+
sinceLastCall,
|
|
124
|
+
exclude
|
|
125
|
+
} = {}) => {
|
|
126
|
+
if (sinceLastCall && lastCSSInsertedRulesIndex >= 0) {
|
|
127
|
+
const rules = getAllRules();
|
|
128
|
+
return lastCSSInsertedRulesIndex = rules.length, rules.slice(lastCSSInsertedRulesIndex).join(separator);
|
|
129
|
+
}
|
|
130
|
+
lastCSSInsertedRulesIndex = 0;
|
|
131
|
+
const runtimeStyles = getAllRules().join(separator);
|
|
132
|
+
return exclude === "design-system" ? runtimeStyles : `${`._ovs-contain {overscroll-behavior:contain;}
|
|
133
|
+
.is_Text .is_Text {display:inline-flex;}
|
|
134
|
+
._dsp_contents {display:contents;}
|
|
135
|
+
${themeConfig.cssRuleSets.join(separator)}`}
|
|
136
|
+
${exclude ? "" : themeConfig.getThemeRulesSets().join(separator)}
|
|
137
|
+
${runtimeStyles}`;
|
|
138
|
+
},
|
|
139
|
+
getNewCSS = opts => getCSS({
|
|
140
|
+
...opts,
|
|
141
|
+
sinceLastCall: !0
|
|
142
|
+
});
|
|
143
|
+
let defaultFontName = configIn.defaultFont ||
|
|
144
|
+
// uses font named "body" if present for compat
|
|
145
|
+
configIn.fonts && ("body" in configIn.fonts ? "body" : "");
|
|
146
|
+
!defaultFontName && configIn.fonts && (defaultFontName = Object.keys(configIn.fonts)[0]), defaultFontName?.[0] === "$" && (defaultFontName = defaultFontName.slice(1));
|
|
147
|
+
const defaultFont = `$${defaultFontName}`,
|
|
148
|
+
config = {
|
|
149
|
+
fonts: {},
|
|
150
|
+
onlyAllowShorthands: !1,
|
|
151
|
+
fontLanguages: [],
|
|
152
|
+
animations: {},
|
|
153
|
+
media: {},
|
|
154
|
+
...configIn,
|
|
155
|
+
unset: {
|
|
156
|
+
fontFamily: configIn.defaultFont ? defaultFont : void 0,
|
|
157
|
+
...configIn.unset
|
|
158
|
+
},
|
|
159
|
+
settings: {
|
|
160
|
+
webContainerType: "inline-size",
|
|
161
|
+
...configIn.settings
|
|
162
|
+
},
|
|
163
|
+
tokens,
|
|
164
|
+
// vite made this into a function if it wasn't set
|
|
165
|
+
shorthands,
|
|
166
|
+
inverseShorthands: shorthands ? Object.fromEntries(Object.entries(shorthands).map(([k, v]) => [v, k])) : {},
|
|
167
|
+
themes: themeConfig.themes,
|
|
168
|
+
fontsParsed: fontsParsed || {},
|
|
169
|
+
themeConfig,
|
|
170
|
+
tokensParsed,
|
|
171
|
+
parsed: !0,
|
|
172
|
+
getNewCSS,
|
|
173
|
+
getCSS,
|
|
174
|
+
defaultFont,
|
|
175
|
+
fontSizeTokens: fontSizeTokens || /* @__PURE__ */new Set(),
|
|
176
|
+
specificTokens
|
|
177
|
+
// const tokens = [...getToken(tokens.size[0])]
|
|
178
|
+
// .spacer-sm + ._dsp_contents._dsp-sm-hidden { margin-left: -var(--${}) }
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
return configureMedia(config), setConfig(config), createdConfigs.set(config, !0), configListeners.size && (configListeners.forEach(cb => cb(config)), configListeners.clear()), process.env.NODE_ENV === "development" && (process.env.DEBUG?.startsWith("tamagui") && console.info("Tamagui config:", config), globalThis.Tamagui || (globalThis.Tamagui = Tamagui)), config;
|
|
182
|
+
}
|
|
183
|
+
function getThemesDeduped(themes) {
|
|
184
|
+
const dedupedThemes = [],
|
|
185
|
+
existing = /* @__PURE__ */new Map();
|
|
186
|
+
for (const themeName in themes) {
|
|
187
|
+
const darkOrLightSpecificPrefix = themeName.startsWith("dark") ? "dark" : themeName.startsWith("light") ? "light" : "",
|
|
188
|
+
rawTheme = themes[themeName],
|
|
189
|
+
key = darkOrLightSpecificPrefix + JSON.stringify(Object.entries(rawTheme).sort((a, b) => a[0] > b[0] ? -1 : 1));
|
|
190
|
+
if (existing.has(key)) {
|
|
191
|
+
existing.get(key).names.push(themeName);
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
const theme = {
|
|
195
|
+
...rawTheme
|
|
196
|
+
};
|
|
197
|
+
for (const key2 in theme) ensureThemeVariable(theme, key2);
|
|
198
|
+
const deduped = {
|
|
199
|
+
names: [themeName],
|
|
200
|
+
theme
|
|
201
|
+
};
|
|
202
|
+
dedupedThemes.push(deduped), existing.set(key, deduped);
|
|
203
|
+
}
|
|
204
|
+
return dedupedThemes;
|
|
205
|
+
}
|
|
206
|
+
export { createTamagui };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { isWeb } from "@tamagui/constants";
|
|
2
|
+
import { simpleHash } from "@tamagui/helpers";
|
|
3
|
+
import { getConfig } from "./config.mjs";
|
|
4
|
+
const IS_VAR = "isVar",
|
|
5
|
+
createVariable = (props, skipHash = !1) => {
|
|
6
|
+
if (!skipHash && isVariable(props)) return props;
|
|
7
|
+
const {
|
|
8
|
+
key,
|
|
9
|
+
name,
|
|
10
|
+
val
|
|
11
|
+
} = props;
|
|
12
|
+
return {
|
|
13
|
+
[IS_VAR]: !0,
|
|
14
|
+
key,
|
|
15
|
+
name: skipHash ? "" : simpleHash(name, 40),
|
|
16
|
+
val,
|
|
17
|
+
variable: isWeb ? skipHash ? `var(--${name})` : createCSSVariable(name) : ""
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
function variableToString(vrble, getValue = !1) {
|
|
21
|
+
return isVariable(vrble) ? !getValue && isWeb && vrble.variable ? vrble.variable : `${vrble.val}` : `${vrble || ""}`;
|
|
22
|
+
}
|
|
23
|
+
function isVariable(v) {
|
|
24
|
+
return v && typeof v == "object" && IS_VAR in v;
|
|
25
|
+
}
|
|
26
|
+
function getVariable(nameOrVariable) {
|
|
27
|
+
if (setDidGetVariableValue(!0), isVariable(nameOrVariable)) return variableToString(nameOrVariable);
|
|
28
|
+
const tokens = getConfig().tokensParsed;
|
|
29
|
+
return variableToString(tokens[nameOrVariable] ?? nameOrVariable);
|
|
30
|
+
}
|
|
31
|
+
let accessed = !1;
|
|
32
|
+
const setDidGetVariableValue = val => accessed = val,
|
|
33
|
+
didGetVariableValue = () => accessed;
|
|
34
|
+
function getVariableValue(v) {
|
|
35
|
+
return isVariable(v) ? (setDidGetVariableValue(!0), v.val) : v;
|
|
36
|
+
}
|
|
37
|
+
function getVariableName(v) {
|
|
38
|
+
return isVariable(v) ? v.name : v;
|
|
39
|
+
}
|
|
40
|
+
function getVariableVariable(v) {
|
|
41
|
+
return isVariable(v) ? v.variable : v;
|
|
42
|
+
}
|
|
43
|
+
const createCSSVariable = (nameProp, includeVar = !0) => {
|
|
44
|
+
if (process.env.NODE_ENV === "development" && (!nameProp || typeof nameProp != "string")) throw new Error(`createCSSVariable expected string, got: ${nameProp}`);
|
|
45
|
+
const name = simpleHash(nameProp, 60);
|
|
46
|
+
return includeVar ? `var(--${name})` : name;
|
|
47
|
+
};
|
|
48
|
+
export { createCSSVariable, createVariable, didGetVariableValue, getVariable, getVariableName, getVariableValue, getVariableVariable, isVariable, setDidGetVariableValue, variableToString };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { simpleHash } from "@tamagui/helpers";
|
|
2
|
+
import { createVariable, isVariable } from "./createVariable.mjs";
|
|
3
|
+
const cache = /* @__PURE__ */new WeakMap(),
|
|
4
|
+
createVariables = (tokens, parentPath = "", isFont = !1) => {
|
|
5
|
+
if (cache.has(tokens)) return tokens;
|
|
6
|
+
const res = {};
|
|
7
|
+
let i = 0;
|
|
8
|
+
for (let keyIn in tokens) {
|
|
9
|
+
i++;
|
|
10
|
+
const val = tokens[keyIn],
|
|
11
|
+
isPrefixed = keyIn[0] === "$",
|
|
12
|
+
keyWithPrefix = isPrefixed ? keyIn : `$${keyIn}`,
|
|
13
|
+
key = isPrefixed ? keyWithPrefix.slice(1) : keyIn;
|
|
14
|
+
if (isVariable(val)) {
|
|
15
|
+
res[key] = val;
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
const niceKey = simpleHash(key);
|
|
19
|
+
let name = isFont ? niceKey.slice(0, 2) : i;
|
|
20
|
+
if (name = parentPath ? `${parentPath}-${name}` : niceKey, val && typeof val == "object") {
|
|
21
|
+
res[key] = createVariables(tokens[key], name, !1
|
|
22
|
+
/* note: don't pass isFont down, we want to avoid it past the first level */);
|
|
23
|
+
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const finalValue = isVariable(val) ? val : createVariable({
|
|
27
|
+
val,
|
|
28
|
+
name,
|
|
29
|
+
key: keyWithPrefix
|
|
30
|
+
});
|
|
31
|
+
res[key] = finalValue;
|
|
32
|
+
}
|
|
33
|
+
return cache.set(res, !0), res;
|
|
34
|
+
};
|
|
35
|
+
export { createVariables };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const defaultComponentState = {
|
|
2
|
+
hover: !1,
|
|
3
|
+
press: !1,
|
|
4
|
+
pressIn: !1,
|
|
5
|
+
focus: !1,
|
|
6
|
+
unmounted: !0
|
|
7
|
+
},
|
|
8
|
+
defaultComponentStateMounted = {
|
|
9
|
+
...defaultComponentState,
|
|
10
|
+
unmounted: !1
|
|
11
|
+
},
|
|
12
|
+
defaultComponentStateShouldEnter = {
|
|
13
|
+
...defaultComponentState,
|
|
14
|
+
unmounted: "should-enter"
|
|
15
|
+
};
|
|
16
|
+
export { defaultComponentState, defaultComponentStateMounted, defaultComponentStateShouldEnter };
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { isWeb } from "@tamagui/constants";
|
|
2
|
+
import { getThemes } from "../config.mjs";
|
|
3
|
+
import { THEME_CLASSNAME_PREFIX, THEME_NAME_SEPARATOR } from "../constants/constants.mjs";
|
|
4
|
+
const emptyState = {
|
|
5
|
+
name: ""
|
|
6
|
+
};
|
|
7
|
+
function getHasThemeUpdatingProps(props) {
|
|
8
|
+
return !!(props.name || props.componentName || props.inverse || props.reset);
|
|
9
|
+
}
|
|
10
|
+
let uid = 0;
|
|
11
|
+
class ThemeManager {
|
|
12
|
+
constructor(props = {}, parentManager) {
|
|
13
|
+
this.props = props;
|
|
14
|
+
if (uid = (uid + 1) % Number.MAX_VALUE, this.id = uid, parentManager === "root") {
|
|
15
|
+
this.updateStateFromProps(props, !1);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (!parentManager) throw process.env.NODE_ENV !== "production" ? new Error("No parent manager given, this is likely due to duplicated Tamagui dependencies. Check your lockfile for mis-matched versions. It could also be from an error somewhere else in your stack causing Tamagui to recieve undefined context, you can try putting some ErrorBoundary components around other areas of your app, or a Suspense boundary.") : "\u274C 000";
|
|
19
|
+
if (this.parentManager = parentManager, !this.updateStateFromProps(props, !1)) return parentManager;
|
|
20
|
+
}
|
|
21
|
+
id = 0;
|
|
22
|
+
themeListeners = /* @__PURE__ */new Set();
|
|
23
|
+
parentManager = null;
|
|
24
|
+
state = emptyState;
|
|
25
|
+
updateStateFromProps(props = this.props || {}, shouldNotify = !0) {
|
|
26
|
+
if (this.props = props, props.forceTheme) return this.state.theme = props.forceTheme, this.state.name = props.name || "", this.updateState(this.state, !0), this.state;
|
|
27
|
+
const nextState = this.getStateIfChanged(props);
|
|
28
|
+
if (nextState) return this.updateState(nextState, shouldNotify), nextState;
|
|
29
|
+
}
|
|
30
|
+
updateState(nextState, shouldNotify = !0) {
|
|
31
|
+
this.state = nextState, this._allKeys = null, shouldNotify && queueMicrotask(() => {
|
|
32
|
+
this.notify();
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
getStateIfChanged(props = this.props, state = this.state, parentManager = this.parentManager) {
|
|
36
|
+
const _ = this.getState(props, parentManager);
|
|
37
|
+
if (state && state !== emptyState && !_) return parentManager?.state;
|
|
38
|
+
if (this.getStateShouldChange(_, state)) return _;
|
|
39
|
+
}
|
|
40
|
+
getStateShouldChange(nextState, state = this.state) {
|
|
41
|
+
return !(!nextState?.theme || nextState.theme === state?.theme);
|
|
42
|
+
}
|
|
43
|
+
getState(props = this.props, parentManager = this.parentManager) {
|
|
44
|
+
return getState(props, parentManager) || null;
|
|
45
|
+
}
|
|
46
|
+
_allKeys = null;
|
|
47
|
+
get allKeys() {
|
|
48
|
+
return this._allKeys ||= /* @__PURE__ */new Set([...(this.parentManager?.allKeys || []), ...Object.keys(this.state.theme || {})]), this._allKeys;
|
|
49
|
+
}
|
|
50
|
+
notify(forced = !1) {
|
|
51
|
+
this.themeListeners.forEach(cb => cb(this.state.name, this, forced)), process.env.NODE_ENV !== "production" && (this._numChangeEventsSent ??= 0, this._numChangeEventsSent++);
|
|
52
|
+
}
|
|
53
|
+
onChangeTheme(cb, debugId) {
|
|
54
|
+
return process.env.NODE_ENV !== "production" && debugId && (this._listeningIds ??= /* @__PURE__ */new Set(), this._listeningIds.add(debugId)), this.themeListeners.add(cb), () => {
|
|
55
|
+
this.themeListeners.delete(cb);
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function getState(props, manager) {
|
|
60
|
+
if (props.name && props.reset) throw new Error(process.env.NODE_ENV === "production" ? "\u274C004" : "Cannot reset and set a new name at the same time.");
|
|
61
|
+
if (!getHasThemeUpdatingProps(props)) return null;
|
|
62
|
+
const themes = getThemes(),
|
|
63
|
+
[allManagers, componentManagers] = getManagers(manager),
|
|
64
|
+
isDirectParentAComponentTheme = !!manager?.state.isComponent,
|
|
65
|
+
startIndex = props.reset && !isDirectParentAComponentTheme ? 1 : 0;
|
|
66
|
+
let baseManager = allManagers[startIndex],
|
|
67
|
+
parentManager = allManagers[startIndex + 1];
|
|
68
|
+
if (!baseManager && props.reset) return process.env.NODE_ENV !== "production" && console.warn("Cannot reset, no parent theme exists"), null;
|
|
69
|
+
const {
|
|
70
|
+
componentName
|
|
71
|
+
} = props;
|
|
72
|
+
let result = null,
|
|
73
|
+
baseName = baseManager?.state.name || "";
|
|
74
|
+
baseManager?.state.isComponent && (baseName = baseName.replace(/_[A-Z][A-Za-z]+/, ""));
|
|
75
|
+
const nextName = props.reset ? baseName : props.name || "",
|
|
76
|
+
allComponentThemes = componentManagers.map(x => x?.state.name || "");
|
|
77
|
+
isDirectParentAComponentTheme && allComponentThemes.shift();
|
|
78
|
+
const base = baseName.split(THEME_NAME_SEPARATOR),
|
|
79
|
+
max = base.length,
|
|
80
|
+
min = props.componentName && !nextName ? max : 0;
|
|
81
|
+
for (let i = max; i >= min; i--) {
|
|
82
|
+
let prefix = base.slice(0, i).join(THEME_NAME_SEPARATOR);
|
|
83
|
+
props.inverse && (prefix = inverseThemeName(prefix));
|
|
84
|
+
let potentials = [];
|
|
85
|
+
if (prefix && prefix !== baseName && potentials.push(prefix), nextName && potentials.unshift(prefix ? `${prefix}_${nextName}` : nextName), i === 1) {
|
|
86
|
+
const lastSegment = potentials.findIndex(x => !x.includes("_"));
|
|
87
|
+
lastSegment > 0 && potentials.splice(lastSegment, 0, nextName);
|
|
88
|
+
}
|
|
89
|
+
if (componentName && !props.reset) {
|
|
90
|
+
const baseLen = base.length;
|
|
91
|
+
let componentPotentials = [];
|
|
92
|
+
if (nextName && baseLen > 1) {
|
|
93
|
+
const beforeSeparator = base[0];
|
|
94
|
+
componentPotentials.push(`${beforeSeparator}_${nextName}_${componentName}`);
|
|
95
|
+
}
|
|
96
|
+
if (componentPotentials.push(`${prefix}_${componentName}`), nextName) {
|
|
97
|
+
if (i > baseLen) {
|
|
98
|
+
const prefixLessOne = base.slice(0, i - 1).join(THEME_NAME_SEPARATOR);
|
|
99
|
+
if (prefixLessOne) {
|
|
100
|
+
const lessSpecific = `${prefixLessOne}_${nextName}_${componentName}`;
|
|
101
|
+
componentPotentials.unshift(lessSpecific);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const moreSpecific = `${prefix}_${nextName}_${componentName}`;
|
|
105
|
+
componentPotentials.unshift(moreSpecific);
|
|
106
|
+
}
|
|
107
|
+
potentials = [...componentPotentials, ...potentials, ...allComponentThemes];
|
|
108
|
+
}
|
|
109
|
+
const found = potentials.find(t => t in themes);
|
|
110
|
+
if (process.env.NODE_ENV !== "production" && typeof props.debug == "string" && console.info(" getState ", {
|
|
111
|
+
props,
|
|
112
|
+
found,
|
|
113
|
+
potentials,
|
|
114
|
+
baseManager,
|
|
115
|
+
nextName,
|
|
116
|
+
baseName,
|
|
117
|
+
prefix
|
|
118
|
+
}), found) {
|
|
119
|
+
const names = found.split("_"),
|
|
120
|
+
[firstName, ...restNames] = names,
|
|
121
|
+
lastName = names[names.length - 1],
|
|
122
|
+
isComponent = lastName[0] === lastName[0].toUpperCase(),
|
|
123
|
+
scheme = firstName === "light" ? "light" : firstName === "dark" ? "dark" : void 0,
|
|
124
|
+
pre = THEME_CLASSNAME_PREFIX,
|
|
125
|
+
className = isWeb ? `${pre}sub_theme ${pre}${!scheme || !restNames.length ? firstName : restNames.join("_")}` : "",
|
|
126
|
+
parentName = (baseManager || parentManager)?.state?.name;
|
|
127
|
+
result = {
|
|
128
|
+
name: found,
|
|
129
|
+
parentName,
|
|
130
|
+
theme: themes[found],
|
|
131
|
+
className,
|
|
132
|
+
isComponent,
|
|
133
|
+
scheme
|
|
134
|
+
};
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return process.env.NODE_ENV !== "production" && props.debug === "verbose" && typeof window < "u" && (console.groupCollapsed("ThemeManager.getState()"), console.info({
|
|
139
|
+
props,
|
|
140
|
+
baseName,
|
|
141
|
+
base,
|
|
142
|
+
min,
|
|
143
|
+
max
|
|
144
|
+
}), console.warn("result", {
|
|
145
|
+
result
|
|
146
|
+
}), console.trace(), console.groupEnd()), result;
|
|
147
|
+
}
|
|
148
|
+
const inverseThemeName = themeName => themeName.startsWith("light") ? themeName.replace(/^light/, "dark") : themeName.replace(/^dark/, "light");
|
|
149
|
+
function getManagers(themeManager) {
|
|
150
|
+
const comp = [],
|
|
151
|
+
all = [];
|
|
152
|
+
let cur = themeManager;
|
|
153
|
+
for (; cur;) all.push(cur), cur.state.isComponent && comp.push(cur), cur = cur.parentManager;
|
|
154
|
+
return [all, comp];
|
|
155
|
+
}
|
|
156
|
+
export { ThemeManager, getHasThemeUpdatingProps, getManagers };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { getConfig } from "../config.mjs";
|
|
2
|
+
import { mediaObjectToString } from "../hooks/useMedia.mjs";
|
|
3
|
+
import { getGroupPropParts } from "./getGroupPropParts.mjs";
|
|
4
|
+
const MEDIA_SEP = "_";
|
|
5
|
+
let prefixes = null,
|
|
6
|
+
selectors = null;
|
|
7
|
+
const groupPseudoToPseudoCSSMap = {
|
|
8
|
+
press: "active"
|
|
9
|
+
},
|
|
10
|
+
createMediaStyle = (styleObject, mediaKeyIn, mediaQueries, type, negate, priority) => {
|
|
11
|
+
const {
|
|
12
|
+
property,
|
|
13
|
+
identifier,
|
|
14
|
+
rules
|
|
15
|
+
} = styleObject,
|
|
16
|
+
conf = getConfig(),
|
|
17
|
+
enableMediaPropOrder = conf.settings.mediaPropOrder,
|
|
18
|
+
isTheme = type === "theme",
|
|
19
|
+
isPlatform = type === "platform",
|
|
20
|
+
isGroup = type === "group",
|
|
21
|
+
isNonWindowMedia = isTheme || isPlatform || isGroup,
|
|
22
|
+
negKey = negate ? "0" : "",
|
|
23
|
+
ogPrefix = identifier.slice(0, identifier.indexOf("-") + 1),
|
|
24
|
+
id = `${ogPrefix}${MEDIA_SEP}${mediaKeyIn.replace("-", "")}${negKey}${MEDIA_SEP}`;
|
|
25
|
+
let styleRule = "",
|
|
26
|
+
groupMediaKey,
|
|
27
|
+
containerName,
|
|
28
|
+
nextIdentifier = identifier.replace(ogPrefix, id),
|
|
29
|
+
styleInner = rules.map(rule => rule.replace(identifier, nextIdentifier)).join(";");
|
|
30
|
+
if (isNonWindowMedia) {
|
|
31
|
+
const precedenceImportancePrefix = new Array((priority || 0) + (isGroup ? 1 : 0)).fill(":root").join("");
|
|
32
|
+
if (isTheme || isGroup) {
|
|
33
|
+
const groupInfo = getGroupPropParts(mediaKeyIn),
|
|
34
|
+
mediaName = groupInfo?.name;
|
|
35
|
+
groupMediaKey = groupInfo?.media, isGroup && (containerName = mediaName);
|
|
36
|
+
const name = (isGroup ? "group_" : "") + mediaName,
|
|
37
|
+
selectorStart = styleInner.indexOf(":root"),
|
|
38
|
+
selectorEnd = styleInner.lastIndexOf("{"),
|
|
39
|
+
selector = styleInner.slice(selectorStart, selectorEnd),
|
|
40
|
+
precedenceSpace = conf.themeClassNameOnRoot && isTheme ? "" : " ",
|
|
41
|
+
pseudoSelectorName = groupInfo.pseudo ? groupPseudoToPseudoCSSMap[groupInfo.pseudo] || groupInfo.pseudo : void 0,
|
|
42
|
+
pseudoSelector = pseudoSelectorName ? `:${pseudoSelectorName}` : "",
|
|
43
|
+
presedencePrefix = `:root${precedenceImportancePrefix}${precedenceSpace}`,
|
|
44
|
+
mediaSelector = `.t_${name}${pseudoSelector}`,
|
|
45
|
+
nextSelector = `${presedencePrefix}${mediaSelector} ${selector.replace(":root", "")}`;
|
|
46
|
+
styleRule = styleInner.replace(selector, nextSelector);
|
|
47
|
+
} else styleRule = `${precedenceImportancePrefix}${styleInner}`;
|
|
48
|
+
}
|
|
49
|
+
if (!isNonWindowMedia || groupMediaKey) {
|
|
50
|
+
if (!selectors) {
|
|
51
|
+
const mediaKeys = Object.keys(mediaQueries);
|
|
52
|
+
selectors = Object.fromEntries(mediaKeys.map(key => [key, mediaObjectToString(mediaQueries[key])])), enableMediaPropOrder || (prefixes = Object.fromEntries(mediaKeys.map((k, index) => [k, new Array(index + 1).fill(":root").join("")])));
|
|
53
|
+
}
|
|
54
|
+
const mediaKey = groupMediaKey || mediaKeyIn,
|
|
55
|
+
mediaSelector = selectors[mediaKey],
|
|
56
|
+
mediaQuery = `${negate ? "not all and " : ""}${mediaSelector}`,
|
|
57
|
+
precedenceImportancePrefix = groupMediaKey ? "" : enableMediaPropOrder ?
|
|
58
|
+
// this new array should be cached
|
|
59
|
+
new Array(priority).fill(":root").join("") :
|
|
60
|
+
// @ts-ignore
|
|
61
|
+
prefixes[mediaKey],
|
|
62
|
+
prefix = groupMediaKey ? `@container ${containerName}` : "@media";
|
|
63
|
+
groupMediaKey && (styleInner = styleRule), styleInner.includes(prefix) ? styleRule = styleInner.replace("{", ` and ${mediaQuery} {`).replace("and screen and", "and") : styleRule = `${prefix} ${mediaQuery}{${precedenceImportancePrefix}${styleInner}}`, groupMediaKey && (styleRule = `@supports (contain: ${conf.settings.webContainerType || "inline-size"}) {${styleRule}}`);
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
property,
|
|
67
|
+
rules: [styleRule],
|
|
68
|
+
identifier: nextIdentifier
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
export { MEDIA_SEP, createMediaStyle };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
function createShallowSetState(setter, debug) {
|
|
2
|
+
return next => setter(prev => mergeIfNotShallowEqual(prev, next, debug));
|
|
3
|
+
}
|
|
4
|
+
function mergeIfNotShallowEqual(prev, next, debug) {
|
|
5
|
+
return isEqualShallow(prev, next) ? prev : (process.env.NODE_ENV === "development" && debug && console.warn("setStateShallow CHANGE", {
|
|
6
|
+
prev,
|
|
7
|
+
next
|
|
8
|
+
}), {
|
|
9
|
+
...prev,
|
|
10
|
+
...next
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
function isEqualShallow(prev, next) {
|
|
14
|
+
for (const key in next) if (prev[key] !== next[key]) return !1;
|
|
15
|
+
return !0;
|
|
16
|
+
}
|
|
17
|
+
export { createShallowSetState, isEqualShallow, mergeIfNotShallowEqual };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createContext, useContext, useMemo } from "react";
|
|
2
|
+
import { objectIdentityKey } from "./objectIdentityKey.mjs";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
function createStyledContext(defaultValues) {
|
|
5
|
+
const OGContext = createContext(defaultValues),
|
|
6
|
+
OGProvider = OGContext.Provider,
|
|
7
|
+
Context = OGContext,
|
|
8
|
+
scopedContexts = /* @__PURE__ */new Map(),
|
|
9
|
+
Provider = ({
|
|
10
|
+
children,
|
|
11
|
+
scope,
|
|
12
|
+
...values
|
|
13
|
+
}) => {
|
|
14
|
+
const next = useMemo(() => ({
|
|
15
|
+
// this ! is a workaround for ts error
|
|
16
|
+
...defaultValues,
|
|
17
|
+
...values
|
|
18
|
+
}), [objectIdentityKey(values)]);
|
|
19
|
+
let Provider2 = OGProvider;
|
|
20
|
+
if (scope) {
|
|
21
|
+
let ScopedContext = scopedContexts.get(scope);
|
|
22
|
+
ScopedContext || (ScopedContext = createContext(defaultValues), scopedContexts.set(scope, ScopedContext)), Provider2 = ScopedContext.Provider;
|
|
23
|
+
}
|
|
24
|
+
return /* @__PURE__ */jsx(Provider2, {
|
|
25
|
+
value: next,
|
|
26
|
+
children
|
|
27
|
+
});
|
|
28
|
+
},
|
|
29
|
+
useStyledContext = scope => {
|
|
30
|
+
const context = scope ? scopedContexts.get(scope) : OGContext;
|
|
31
|
+
return useContext(context);
|
|
32
|
+
};
|
|
33
|
+
return Context.Provider = Provider, Context.props = defaultValues, Context.context = OGContext, Context.useStyledContext = useStyledContext, Context;
|
|
34
|
+
}
|
|
35
|
+
export { createStyledContext };
|