@tamagui/core 1.0.1-beta.173 → 1.0.1-beta.174
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/createComponent.js +13 -0
- package/dist/cjs/createComponent.js.map +2 -2
- package/dist/cjs/helpers/ThemeManager.js +4 -2
- package/dist/cjs/helpers/ThemeManager.js.map +2 -2
- package/dist/cjs/helpers/createPropMapper.js +54 -8
- package/dist/cjs/helpers/createPropMapper.js.map +2 -2
- package/dist/cjs/helpers/getSplitStyles.js +7 -3
- package/dist/cjs/helpers/getSplitStyles.js.map +2 -2
- package/dist/cjs/hooks/useMedia.js +39 -0
- package/dist/cjs/hooks/useMedia.js.map +2 -2
- package/dist/cjs/hooks/useTheme.js +11 -2
- package/dist/cjs/hooks/useTheme.js.map +2 -2
- package/dist/cjs/index.js +4 -2
- package/dist/cjs/index.js.map +2 -2
- package/dist/esm/createComponent.js +13 -0
- package/dist/esm/createComponent.js.map +2 -2
- package/dist/esm/helpers/ThemeManager.js +4 -2
- package/dist/esm/helpers/ThemeManager.js.map +2 -2
- package/dist/esm/helpers/createPropMapper.js +53 -9
- package/dist/esm/helpers/createPropMapper.js.map +2 -2
- package/dist/esm/helpers/getSplitStyles.js +7 -3
- package/dist/esm/helpers/getSplitStyles.js.map +2 -2
- package/dist/esm/hooks/useMedia.js +38 -0
- package/dist/esm/hooks/useMedia.js.map +2 -2
- package/dist/esm/hooks/useTheme.js +11 -2
- package/dist/esm/hooks/useTheme.js.map +2 -2
- package/dist/esm/index.js +3 -1
- package/dist/esm/index.js.map +2 -2
- package/package.json +11 -10
- package/src/createComponent.tsx +15 -0
- package/src/helpers/ThemeManager.tsx +4 -2
- package/src/helpers/createPropMapper.ts +69 -8
- package/src/helpers/getSplitStyles.tsx +9 -4
- package/src/hooks/useMedia.tsx +54 -0
- package/src/hooks/useTheme.tsx +13 -2
- package/src/index.ts +1 -0
- package/types/helpers/ThemeManager.d.ts +1 -1
- package/types/helpers/createPropMapper.d.ts +3 -1
- package/types/hooks/useMedia.d.ts +10 -0
- package/types/index.d.ts +1 -1
package/src/createComponent.tsx
CHANGED
|
@@ -709,6 +709,21 @@ export function createComponent<
|
|
|
709
709
|
fontFamily = fontFamily.slice(1)
|
|
710
710
|
}
|
|
711
711
|
|
|
712
|
+
if (process.env.NODE_ENV === 'development') {
|
|
713
|
+
if (fontFamily?.startsWith(`var(`)) {
|
|
714
|
+
// eslint-disable-next-line no-console
|
|
715
|
+
console.warn(
|
|
716
|
+
`Received variable instead of resolved name of font, this is a bug. Please report on Github.`,
|
|
717
|
+
{
|
|
718
|
+
fontFamily,
|
|
719
|
+
props,
|
|
720
|
+
splitStyles,
|
|
721
|
+
staticConfig,
|
|
722
|
+
}
|
|
723
|
+
)
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
712
727
|
const classList = [
|
|
713
728
|
componentName ? componentClassName : '',
|
|
714
729
|
fontFamily ? `font_${fontFamily}` : '',
|
|
@@ -89,7 +89,7 @@ export class ThemeManager {
|
|
|
89
89
|
return Boolean(this.keys.get(uuid)?.size)
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
update({ name, theme, className }: SetActiveThemeProps = {}, force = false) {
|
|
92
|
+
update({ name, theme, className }: SetActiveThemeProps = {}, force = false, notify = true) {
|
|
93
93
|
if (!force) {
|
|
94
94
|
// className compare on web, avoids light/dark re-renders
|
|
95
95
|
const nameChanged = name !== this.name
|
|
@@ -100,7 +100,9 @@ export class ThemeManager {
|
|
|
100
100
|
this.className = className || ''
|
|
101
101
|
this.name = name || ''
|
|
102
102
|
this.theme = theme
|
|
103
|
-
|
|
103
|
+
if (notify) {
|
|
104
|
+
this.notifyListeners()
|
|
105
|
+
}
|
|
104
106
|
return true
|
|
105
107
|
}
|
|
106
108
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getConfig } from '../config'
|
|
2
2
|
import { isDevTools } from '../constants/isDevTools'
|
|
3
3
|
import { isWeb } from '../constants/platform'
|
|
4
|
-
import { Variable, isVariable } from '../createVariable'
|
|
4
|
+
import { Variable, getVariableValue, isVariable } from '../createVariable'
|
|
5
5
|
import {
|
|
6
6
|
DebugProp,
|
|
7
7
|
GenericVariantDefinitions,
|
|
@@ -57,6 +57,7 @@ export const createPropMapper = (staticConfig: StaticConfigParsed) => {
|
|
|
57
57
|
props[conf.inverseShorthands.fontFamily] ||
|
|
58
58
|
props.fontFamily ||
|
|
59
59
|
defaultProps.fontFamily ||
|
|
60
|
+
propsIn.fontFamily ||
|
|
60
61
|
'$body'
|
|
61
62
|
|
|
62
63
|
const variantValue = resolveVariants(
|
|
@@ -72,7 +73,8 @@ export const createPropMapper = (staticConfig: StaticConfigParsed) => {
|
|
|
72
73
|
staticConfig,
|
|
73
74
|
'',
|
|
74
75
|
languageContext,
|
|
75
|
-
avoidDefaultProps
|
|
76
|
+
avoidDefaultProps,
|
|
77
|
+
debug
|
|
76
78
|
)
|
|
77
79
|
|
|
78
80
|
if (variantValue) {
|
|
@@ -100,7 +102,7 @@ export const createPropMapper = (staticConfig: StaticConfigParsed) => {
|
|
|
100
102
|
debug
|
|
101
103
|
)
|
|
102
104
|
} else if (isVariable(value)) {
|
|
103
|
-
value =
|
|
105
|
+
value = resolveVariableValue(key, value, returnVariablesAs)
|
|
104
106
|
}
|
|
105
107
|
}
|
|
106
108
|
|
|
@@ -146,7 +148,10 @@ const resolveVariants: StyleResolver = (
|
|
|
146
148
|
debug
|
|
147
149
|
) => {
|
|
148
150
|
const variant = variants && variants[key]
|
|
149
|
-
if (!variant || value === undefined)
|
|
151
|
+
if (!variant || value === undefined) {
|
|
152
|
+
return
|
|
153
|
+
}
|
|
154
|
+
|
|
150
155
|
let variantValue = getVariantDefinition(variant, key, value, conf)
|
|
151
156
|
|
|
152
157
|
if (!variantValue) {
|
|
@@ -176,7 +181,16 @@ const resolveVariants: StyleResolver = (
|
|
|
176
181
|
)
|
|
177
182
|
}
|
|
178
183
|
|
|
184
|
+
let fontFamilyResult: any
|
|
185
|
+
|
|
179
186
|
if (isObj(variantValue)) {
|
|
187
|
+
const fontFamilyUpdate =
|
|
188
|
+
variantValue.fontFamily || variantValue[conf.inverseShorthands.fontFamily]
|
|
189
|
+
|
|
190
|
+
if (fontFamilyUpdate) {
|
|
191
|
+
fontFamilyResult = getFontFamilyFromNameOrVariable(fontFamilyUpdate, conf)
|
|
192
|
+
}
|
|
193
|
+
|
|
180
194
|
variantValue = resolveTokensAndVariants(
|
|
181
195
|
key,
|
|
182
196
|
variantValue,
|
|
@@ -184,7 +198,7 @@ const resolveVariants: StyleResolver = (
|
|
|
184
198
|
defaultProps,
|
|
185
199
|
theme,
|
|
186
200
|
variants,
|
|
187
|
-
fontFamily,
|
|
201
|
+
fontFamilyResult || fontFamily,
|
|
188
202
|
conf,
|
|
189
203
|
returnVariablesAs,
|
|
190
204
|
staticConfig,
|
|
@@ -196,10 +210,56 @@ const resolveVariants: StyleResolver = (
|
|
|
196
210
|
}
|
|
197
211
|
|
|
198
212
|
if (variantValue) {
|
|
199
|
-
|
|
213
|
+
const next = Object.entries(expandStyles(variantValue))
|
|
214
|
+
|
|
215
|
+
// store any changed font family (only support variables for now)
|
|
216
|
+
if (fontFamilyResult && fontFamilyResult[0] === '$') {
|
|
217
|
+
fontFamilyCache.set(next, getVariableValue(fontFamilyResult))
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return next
|
|
200
221
|
}
|
|
201
222
|
}
|
|
202
223
|
|
|
224
|
+
// handles finding and resolving the fontFamily to the token name
|
|
225
|
+
// this is used as `font_[name]` in className for nice css variable support
|
|
226
|
+
export function getFontFamilyFromNameOrVariable(input: any, conf: TamaguiInternalConfig) {
|
|
227
|
+
if (isVariable(input)) {
|
|
228
|
+
const val = variableToFontNameCache.get(input)
|
|
229
|
+
if (val) {
|
|
230
|
+
return val
|
|
231
|
+
} else {
|
|
232
|
+
for (const key in conf.fontsParsed) {
|
|
233
|
+
const familyVariable = conf.fontsParsed[key].family
|
|
234
|
+
if (isVariable(familyVariable)) {
|
|
235
|
+
variableToFontNameCache.set(familyVariable, key)
|
|
236
|
+
if (familyVariable === input) {
|
|
237
|
+
return key
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
} else if (typeof input === 'string') {
|
|
243
|
+
if (input?.[0] === '$') {
|
|
244
|
+
return input
|
|
245
|
+
} else {
|
|
246
|
+
// this could be mapped back to
|
|
247
|
+
if (process.env.NODE_ENV === 'development') {
|
|
248
|
+
// eslint-disable-next-line no-console
|
|
249
|
+
console.log('[tamagui] should map back', input)
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const variableToFontNameCache = new WeakMap<Variable, string>()
|
|
256
|
+
|
|
257
|
+
// special helper for special font family
|
|
258
|
+
const fontFamilyCache = new WeakMap()
|
|
259
|
+
export const getPropMappedFontFamily = (expanded?: any) => {
|
|
260
|
+
return expanded && fontFamilyCache.get(expanded)
|
|
261
|
+
}
|
|
262
|
+
|
|
203
263
|
const resolveTokensAndVariants: StyleResolver = (
|
|
204
264
|
key, // we dont use key assume value is object instead
|
|
205
265
|
value,
|
|
@@ -220,6 +280,7 @@ const resolveTokensAndVariants: StyleResolver = (
|
|
|
220
280
|
for (const rKey in value) {
|
|
221
281
|
const fKey = conf.shorthands[rKey] || rKey
|
|
222
282
|
const val = value[rKey]
|
|
283
|
+
|
|
223
284
|
if (isVariable(val)) {
|
|
224
285
|
res[fKey] = !isWeb || returnVariablesAs === 'value' ? val.val : val.variable
|
|
225
286
|
} else if (variants[fKey]) {
|
|
@@ -385,7 +446,7 @@ const getToken = (
|
|
|
385
446
|
// eslint-disable-next-line no-console
|
|
386
447
|
console.log(` ﹒ propMapper getToken`, key, valOrVar)
|
|
387
448
|
}
|
|
388
|
-
return
|
|
449
|
+
return resolveVariableValue(key, valOrVar, resolveAs)
|
|
389
450
|
}
|
|
390
451
|
if (process.env.NODE_ENV === 'development') {
|
|
391
452
|
if (value && value[0] === '$') {
|
|
@@ -407,7 +468,7 @@ Set the debug prop to true to see more detailed debug information.`
|
|
|
407
468
|
return value
|
|
408
469
|
}
|
|
409
470
|
|
|
410
|
-
function
|
|
471
|
+
function resolveVariableValue(
|
|
411
472
|
key: string,
|
|
412
473
|
valOrVar: Variable | any,
|
|
413
474
|
resolveAs: ResolveVariableTypes = 'auto'
|
|
@@ -19,6 +19,7 @@ import type {
|
|
|
19
19
|
} from '../types'
|
|
20
20
|
import { FontLanguageProps, LanguageContextType } from '../views/FontLanguage.types'
|
|
21
21
|
import { createMediaStyle } from './createMediaStyle'
|
|
22
|
+
import { getPropMappedFontFamily } from './createPropMapper'
|
|
22
23
|
import { fixStyles } from './expandStyles'
|
|
23
24
|
import { getAtomicStyle, getStylesAtomic, styleToCSS } from './getStylesAtomic'
|
|
24
25
|
import {
|
|
@@ -149,10 +150,6 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
149
150
|
keyInit = expandedKey
|
|
150
151
|
}
|
|
151
152
|
|
|
152
|
-
if (keyInit === 'fontFamily' && fontFamily === undefined) {
|
|
153
|
-
fontFamily = valInit
|
|
154
|
-
}
|
|
155
|
-
|
|
156
153
|
if (usedKeys.has(keyInit)) continue
|
|
157
154
|
if (skipProps[keyInit]) continue
|
|
158
155
|
if (!isWeb && keyInit.startsWith('data-')) continue
|
|
@@ -280,6 +277,10 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
280
277
|
debug
|
|
281
278
|
)
|
|
282
279
|
|
|
280
|
+
if (!fontFamily) {
|
|
281
|
+
fontFamily = getPropMappedFontFamily(expanded)
|
|
282
|
+
}
|
|
283
|
+
|
|
283
284
|
if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
|
|
284
285
|
// eslint-disable-next-line no-console
|
|
285
286
|
console.log('expanded', expanded)
|
|
@@ -431,6 +432,10 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
431
432
|
continue
|
|
432
433
|
}
|
|
433
434
|
|
|
435
|
+
if (key === 'fontFamily' && !fontFamily && valInit && val) {
|
|
436
|
+
fontFamily = valInit[0] === '$' ? valInit : val
|
|
437
|
+
}
|
|
438
|
+
|
|
434
439
|
if (validStyleProps[key]) {
|
|
435
440
|
usedKeys.add(key)
|
|
436
441
|
if (val && val[0] === '_') {
|
package/src/hooks/useMedia.tsx
CHANGED
|
@@ -177,6 +177,60 @@ export function useMedia(): {
|
|
|
177
177
|
)
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Useful for more complex components that need access to the currently active props,
|
|
182
|
+
* accounting for the currently active media queries.
|
|
183
|
+
*
|
|
184
|
+
* Use sparingly, is will loop props and trigger re-render on all media queries.
|
|
185
|
+
*
|
|
186
|
+
* */
|
|
187
|
+
export function useMediaPropsActive<A extends Object>(
|
|
188
|
+
props: A
|
|
189
|
+
): {
|
|
190
|
+
// remove all media
|
|
191
|
+
[Key in keyof A extends `$${string}` ? never : keyof A]: A[Key]
|
|
192
|
+
} {
|
|
193
|
+
const media = useMedia()
|
|
194
|
+
|
|
195
|
+
return useMemo(() => {
|
|
196
|
+
const evaluated = {} as A
|
|
197
|
+
const lastSetImportanceForKey = {}
|
|
198
|
+
const propNames = Object.keys(props)
|
|
199
|
+
const mediaKeysOrdered = Object.keys(getMedia())
|
|
200
|
+
|
|
201
|
+
function update(k: string, v: any, importance = 0) {
|
|
202
|
+
if (lastSetImportanceForKey[k] > importance) {
|
|
203
|
+
return
|
|
204
|
+
}
|
|
205
|
+
lastSetImportanceForKey[k] = importance
|
|
206
|
+
evaluated[k] = v
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
for (let i = propNames.length - 1; i >= 0; i--) {
|
|
210
|
+
const key = propNames[i]
|
|
211
|
+
const val = props[key]
|
|
212
|
+
if (key[0] === '$') {
|
|
213
|
+
const shortKey = key.slice(1)
|
|
214
|
+
if (!media[shortKey]) {
|
|
215
|
+
continue
|
|
216
|
+
}
|
|
217
|
+
if (val && typeof val === 'object') {
|
|
218
|
+
const subPropNames = Object.keys(val)
|
|
219
|
+
const mediaImportance = mediaKeysOrdered.indexOf(shortKey)
|
|
220
|
+
for (let j = subPropNames.length; j--; j >= 0) {
|
|
221
|
+
const skey = subPropNames[j]
|
|
222
|
+
update(skey, val[skey], mediaImportance)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
} else {
|
|
226
|
+
update(key, val)
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return evaluated
|
|
231
|
+
}, [media, props])
|
|
232
|
+
}
|
|
233
|
+
|
|
180
234
|
function camelToHyphen(str: string) {
|
|
181
235
|
return str.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`).toLowerCase()
|
|
182
236
|
}
|
package/src/hooks/useTheme.tsx
CHANGED
|
@@ -236,9 +236,20 @@ export const useChangeThemeEffect = (
|
|
|
236
236
|
return new ThemeManager(next.name, next.className, next.theme, parentManager, reset)
|
|
237
237
|
})
|
|
238
238
|
|
|
239
|
+
// not concurrent safe but fixes native (but breaks SSR and not needed on web (i think) so leave only on native)
|
|
240
|
+
let didChange = false
|
|
241
|
+
if (process.env.TAMAGUI_TARGET === 'native') {
|
|
242
|
+
didChange = Boolean(
|
|
243
|
+
next?.name !== themeManager.name || next?.className !== themeManager.className
|
|
244
|
+
)
|
|
245
|
+
if (didChange) {
|
|
246
|
+
themeManager.update(next, false, false)
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
239
250
|
if (!isServer) {
|
|
240
251
|
useLayoutEffect(() => {
|
|
241
|
-
themeManager.update(next)
|
|
252
|
+
themeManager.update(next, didChange)
|
|
242
253
|
activeThemeManagers.add(themeManager)
|
|
243
254
|
|
|
244
255
|
const disposeParentOnChange = parentManager.onChangeTheme(() => {
|
|
@@ -262,7 +273,7 @@ export const useChangeThemeEffect = (
|
|
|
262
273
|
disposeParentOnChange()
|
|
263
274
|
}
|
|
264
275
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
265
|
-
}, [themes, next?.name, next?.className, componentName, debug])
|
|
276
|
+
}, [didChange, themes, next?.name, next?.className, componentName, debug])
|
|
266
277
|
}
|
|
267
278
|
|
|
268
279
|
return {
|
package/src/index.ts
CHANGED
|
@@ -28,7 +28,7 @@ export declare class ThemeManager {
|
|
|
28
28
|
get fullName(): string;
|
|
29
29
|
getValue(key: string): import("..").Variable<import("..").VariableValue> | undefined;
|
|
30
30
|
isTracking(uuid: Object): boolean;
|
|
31
|
-
update({ name, theme, className }?: SetActiveThemeProps, force?: boolean): boolean;
|
|
31
|
+
update({ name, theme, className }?: SetActiveThemeProps, force?: boolean, notify?: boolean): boolean;
|
|
32
32
|
getNextTheme(props?: GetNextThemeProps, debug?: any): {
|
|
33
33
|
name: string;
|
|
34
34
|
theme: ThemeParsed | null;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { PropMapper, SplitStyleState, StaticConfigParsed } from '../types';
|
|
1
|
+
import { PropMapper, SplitStyleState, StaticConfigParsed, TamaguiInternalConfig } from '../types';
|
|
2
2
|
export declare type ResolveVariableTypes = 'auto' | 'value' | 'variable' | 'both' | 'non-color-value';
|
|
3
3
|
export declare const getReturnVariablesAs: (props: any, state: Partial<SplitStyleState>) => "auto" | "value" | "non-color-value";
|
|
4
4
|
export declare const createPropMapper: (staticConfig: StaticConfigParsed) => PropMapper;
|
|
5
|
+
export declare function getFontFamilyFromNameOrVariable(input: any, conf: TamaguiInternalConfig): string | undefined;
|
|
6
|
+
export declare const getPropMappedFontFamily: (expanded?: any) => any;
|
|
5
7
|
//# sourceMappingURL=createPropMapper.d.ts.map
|
|
@@ -11,6 +11,16 @@ export declare function useMediaQueryListeners(config: TamaguiInternalConfig): v
|
|
|
11
11
|
export declare function useMedia(): {
|
|
12
12
|
[key in MediaQueryKey]: boolean;
|
|
13
13
|
};
|
|
14
|
+
/**
|
|
15
|
+
* Useful for more complex components that need access to the currently active props,
|
|
16
|
+
* accounting for the currently active media queries.
|
|
17
|
+
*
|
|
18
|
+
* Use sparingly, is will loop props and trigger re-render on all media queries.
|
|
19
|
+
*
|
|
20
|
+
* */
|
|
21
|
+
export declare function useMediaPropsActive<A extends Object>(props: A): {
|
|
22
|
+
[Key in keyof A extends `$${string}` ? never : keyof A]: A[Key];
|
|
23
|
+
};
|
|
14
24
|
export declare function mediaObjectToString(query: string | MediaQueryObject): string;
|
|
15
25
|
export {};
|
|
16
26
|
//# sourceMappingURL=useMedia.d.ts.map
|
package/types/index.d.ts
CHANGED
|
@@ -42,7 +42,7 @@ export * from './hooks/useConstant';
|
|
|
42
42
|
export * from './hooks/useId';
|
|
43
43
|
export * from './hooks/useIsMounted';
|
|
44
44
|
export * from './hooks/useIsTouchDevice';
|
|
45
|
-
export { configureMedia, getMedia, mediaState, useMedia, mediaObjectToString, addMediaQueryListener, removeMediaQueryListener, mediaQueryConfig, } from './hooks/useMedia';
|
|
45
|
+
export { configureMedia, getMedia, mediaState, useMedia, useMediaPropsActive, mediaObjectToString, addMediaQueryListener, removeMediaQueryListener, mediaQueryConfig, } from './hooks/useMedia';
|
|
46
46
|
export * from './hooks/usePressable';
|
|
47
47
|
export * from './hooks/useTheme';
|
|
48
48
|
export * from './hooks/useIsSSR';
|