@tamagui/core 1.0.1-beta.148 → 1.0.1-beta.151
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/constants/platform.js.map +2 -2
- package/dist/cjs/createComponent.js +161 -52
- package/dist/cjs/createComponent.js.map +2 -2
- package/dist/cjs/createFont.js +2 -1
- package/dist/cjs/createFont.js.map +2 -2
- package/dist/cjs/helpers/getSplitStyles.js +60 -50
- package/dist/cjs/helpers/getSplitStyles.js.map +2 -2
- package/dist/cjs/helpers/mergeTransform.js.map +2 -2
- package/dist/cjs/hooks/useFeatures.js +0 -120
- package/dist/cjs/hooks/useFeatures.js.map +2 -2
- package/dist/cjs/insertFont.js +1 -1
- package/dist/cjs/insertFont.js.map +2 -2
- package/dist/cjs/types.js.map +1 -1
- package/dist/esm/constants/platform.js.map +2 -2
- package/dist/esm/createComponent.js +169 -55
- package/dist/esm/createComponent.js.map +2 -2
- package/dist/esm/createFont.js +2 -1
- package/dist/esm/createFont.js.map +2 -2
- package/dist/esm/helpers/getSplitStyles.js +60 -50
- package/dist/esm/helpers/getSplitStyles.js.map +2 -2
- package/dist/esm/helpers/mergeTransform.js.map +2 -2
- package/dist/esm/hooks/useFeatures.js +0 -120
- package/dist/esm/hooks/useFeatures.js.map +2 -2
- package/dist/esm/insertFont.js +1 -1
- package/dist/esm/insertFont.js.map +2 -2
- package/package.json +10 -9
- package/src/constants/platform.ts +1 -0
- package/src/createComponent.tsx +246 -57
- package/src/createFont.ts +4 -1
- package/src/helpers/getSplitStyles.tsx +73 -65
- package/src/helpers/mergeTransform.ts +2 -0
- package/src/insertFont.ts +1 -1
- package/src/types.tsx +7 -5
- package/types/helpers/getSplitStyles.d.ts +1 -0
- package/types/hooks/useFeatures.d.ts +0 -1
- package/types/types.d.ts +11 -3
- package/src/hooks/useFeatures.tsx +0 -289
package/src/createComponent.tsx
CHANGED
|
@@ -20,6 +20,7 @@ import React, {
|
|
|
20
20
|
memo,
|
|
21
21
|
useCallback,
|
|
22
22
|
useContext,
|
|
23
|
+
useEffect,
|
|
23
24
|
} from 'react'
|
|
24
25
|
import { StyleSheet, Text, View, ViewStyle } from 'react-native'
|
|
25
26
|
|
|
@@ -32,12 +33,16 @@ import { assignNativePropsToWeb } from './helpers/assignNativePropsToWeb'
|
|
|
32
33
|
import { getReturnVariablesAs } from './helpers/createPropMapper'
|
|
33
34
|
import { createShallowUpdate } from './helpers/createShallowUpdate'
|
|
34
35
|
import { extendStaticConfig, parseStaticConfig } from './helpers/extendStaticConfig'
|
|
35
|
-
import {
|
|
36
|
+
import {
|
|
37
|
+
SplitStyleResult,
|
|
38
|
+
getSubStyle,
|
|
39
|
+
insertSplitStyles,
|
|
40
|
+
useSplitStyles,
|
|
41
|
+
} from './helpers/getSplitStyles'
|
|
36
42
|
import { getAllSelectors } from './helpers/insertStyleRule'
|
|
37
43
|
import { mergeProps } from './helpers/mergeProps'
|
|
38
44
|
import { proxyThemeVariables } from './helpers/proxyThemeVariables'
|
|
39
|
-
import {
|
|
40
|
-
import { mediaState } from './hooks/useMedia'
|
|
45
|
+
import { addMediaQueryListener, mediaState, removeMediaQueryListener } from './hooks/useMedia'
|
|
41
46
|
import { usePressable } from './hooks/usePressable'
|
|
42
47
|
import { useServerRef, useServerState } from './hooks/useServerHooks'
|
|
43
48
|
import { getThemeManager, useTheme } from './hooks/useTheme'
|
|
@@ -54,6 +59,7 @@ import {
|
|
|
54
59
|
TamaguiElement,
|
|
55
60
|
TamaguiInternalConfig,
|
|
56
61
|
UseAnimationHook,
|
|
62
|
+
UseAnimationProps,
|
|
57
63
|
} from './types'
|
|
58
64
|
import { usePressability } from './vendor/Pressability'
|
|
59
65
|
import { Slot, mergeEvent } from './views/Slot'
|
|
@@ -92,6 +98,7 @@ function mergeShorthands({ defaultProps }: StaticConfigParsed, { shorthands }: T
|
|
|
92
98
|
|
|
93
99
|
let initialTheme: any
|
|
94
100
|
let config: TamaguiInternalConfig
|
|
101
|
+
let mediaPropNames: string[] = []
|
|
95
102
|
|
|
96
103
|
export function createComponent<
|
|
97
104
|
ComponentPropTypes extends Object = {},
|
|
@@ -199,25 +206,114 @@ export function createComponent<
|
|
|
199
206
|
}
|
|
200
207
|
}
|
|
201
208
|
|
|
202
|
-
const { viewProps: viewPropsIn, pseudos, medias, style, classNames } = splitStyles
|
|
209
|
+
const { viewProps: viewPropsIn, pseudos, medias, style, classNames, mediaKeys } = splitStyles
|
|
210
|
+
|
|
211
|
+
// media queries
|
|
212
|
+
useIsomorphicLayoutEffect(() => {
|
|
213
|
+
for (const key of mediaKeys) {
|
|
214
|
+
addMediaQueryListener(key, forceUpdate)
|
|
215
|
+
}
|
|
216
|
+
return () => {
|
|
217
|
+
for (const key of mediaKeys) {
|
|
218
|
+
removeMediaQueryListener(key, forceUpdate)
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}, [mediaKeys.join(',')])
|
|
222
|
+
|
|
223
|
+
// animations
|
|
203
224
|
const useAnimations = tamaguiConfig?.animations?.useAnimations as UseAnimationHook | undefined
|
|
204
225
|
const isAnimated = !!(useAnimations && props.animation)
|
|
205
226
|
const hasEnterStyle = !!props.enterStyle
|
|
206
|
-
|
|
207
227
|
const animationFeatureStylesIn = props.animation ? { ...defaultNativeStyle, ...style } : null
|
|
228
|
+
const propsWithAnimation = props as UseAnimationProps
|
|
229
|
+
|
|
230
|
+
// lets make changing the key mandatory for adding/removing animations
|
|
231
|
+
// reason is animations are heavy no way around it, and must be run inline here (🙅 loading as a sub-component)
|
|
232
|
+
// because they need to sync update on first render. it's pretty rare too going to/from no animation => animation
|
|
233
|
+
// so requiring key change on animation change is least-bad option.
|
|
234
|
+
// plus, React use() may let us get away with conditional hooks soon :)
|
|
235
|
+
if (!isRSC && isAnimated) {
|
|
236
|
+
const animationState = useAnimations(propsWithAnimation, {
|
|
237
|
+
state,
|
|
238
|
+
pseudos,
|
|
239
|
+
onDidAnimate: props.onDidAnimate,
|
|
240
|
+
hostRef,
|
|
241
|
+
staticConfig,
|
|
242
|
+
getStyle({ isExiting, isEntering, exitVariant, enterVariant } = {}) {
|
|
243
|
+
// we have to merge such that transforms keys all exist
|
|
244
|
+
const style = animationFeatureStylesIn
|
|
245
|
+
|
|
246
|
+
const enterStyle = isEntering
|
|
247
|
+
? enterVariant && staticConfig.variants?.[enterVariant]['true']
|
|
248
|
+
? getSubStyle(
|
|
249
|
+
'',
|
|
250
|
+
staticConfig.variants?.[enterVariant]['true'],
|
|
251
|
+
staticConfig,
|
|
252
|
+
theme,
|
|
253
|
+
props,
|
|
254
|
+
state,
|
|
255
|
+
tamaguiConfig
|
|
256
|
+
) || pseudos.enterStyle
|
|
257
|
+
: null || pseudos.enterStyle
|
|
258
|
+
: null
|
|
259
|
+
|
|
260
|
+
const exitStyle = isExiting
|
|
261
|
+
? exitVariant && staticConfig.variants?.[exitVariant]['true']
|
|
262
|
+
? getSubStyle(
|
|
263
|
+
'',
|
|
264
|
+
staticConfig.variants?.[exitVariant]['true'],
|
|
265
|
+
staticConfig,
|
|
266
|
+
theme,
|
|
267
|
+
props,
|
|
268
|
+
state,
|
|
269
|
+
tamaguiConfig
|
|
270
|
+
) || pseudos.exitStyle
|
|
271
|
+
: null || pseudos.exitStyle
|
|
272
|
+
: null
|
|
273
|
+
|
|
274
|
+
// if you have hoverStyle={{ scale: 1.1 }} and don't have scale set on the base style
|
|
275
|
+
// no animation will run! this is really confusing. this will look at all variants,
|
|
276
|
+
// and fill in base styles if they don't exist. eg:
|
|
277
|
+
// input:
|
|
278
|
+
// base: {}
|
|
279
|
+
// hoverStyle: { scale: 2 }
|
|
280
|
+
// enterStyle: { x: 100 }
|
|
281
|
+
// output:
|
|
282
|
+
// base: { x: 0, scale: 1 }
|
|
283
|
+
ensureBaseHasDefaults(
|
|
284
|
+
style,
|
|
285
|
+
// enterStyle,
|
|
286
|
+
pseudos.hoverStyle,
|
|
287
|
+
pseudos.focusStyle,
|
|
288
|
+
pseudos.pressStyle,
|
|
289
|
+
pseudos.pressStyle
|
|
290
|
+
)
|
|
208
291
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
292
|
+
enterStyle && isEntering && merge(style, enterStyle)
|
|
293
|
+
state.hover && pseudos.hoverStyle && merge(style, pseudos.hoverStyle)
|
|
294
|
+
state.focus && pseudos.focusStyle && merge(style, pseudos.focusStyle)
|
|
295
|
+
state.press && pseudos.pressStyle && merge(style, pseudos.pressStyle)
|
|
296
|
+
exitStyle && isExiting && merge(style, exitStyle)
|
|
297
|
+
|
|
298
|
+
if (process.env.NODE_ENV === 'development') {
|
|
299
|
+
if (props['debug']) {
|
|
300
|
+
// eslint-disable-next-line no-console
|
|
301
|
+
console.log('animation style', style)
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return style
|
|
306
|
+
},
|
|
307
|
+
//, delay
|
|
308
|
+
})
|
|
309
|
+
|
|
310
|
+
// must be properly memoized
|
|
311
|
+
if (animationState !== state.animation) {
|
|
312
|
+
setStateShallow({
|
|
313
|
+
animation: animationState,
|
|
314
|
+
})
|
|
315
|
+
}
|
|
316
|
+
}
|
|
221
317
|
|
|
222
318
|
const {
|
|
223
319
|
tag,
|
|
@@ -434,7 +530,27 @@ export function createComponent<
|
|
|
434
530
|
|
|
435
531
|
// from react-native-web
|
|
436
532
|
const platformMethodsRef = usePlatformMethods(viewProps)
|
|
437
|
-
|
|
533
|
+
|
|
534
|
+
const shouldSetMounted = Boolean(
|
|
535
|
+
isClient && (hasEnterStyle || props.animation) && !state.mounted
|
|
536
|
+
)
|
|
537
|
+
|
|
538
|
+
const setRef = useMergeRefs(
|
|
539
|
+
hostRef,
|
|
540
|
+
platformMethodsRef,
|
|
541
|
+
forwardedRef as any,
|
|
542
|
+
shouldSetMounted
|
|
543
|
+
? () => {
|
|
544
|
+
// for some reason without some small delay it doesn't animate css
|
|
545
|
+
setTimeout(() => {
|
|
546
|
+
setStateShallow({
|
|
547
|
+
mounted: true,
|
|
548
|
+
})
|
|
549
|
+
}, 10)
|
|
550
|
+
}
|
|
551
|
+
: undefined
|
|
552
|
+
)
|
|
553
|
+
|
|
438
554
|
viewProps.ref = setRef
|
|
439
555
|
}
|
|
440
556
|
|
|
@@ -503,31 +619,14 @@ export function createComponent<
|
|
|
503
619
|
})
|
|
504
620
|
}
|
|
505
621
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
}
|
|
622
|
+
if (!isRSC) {
|
|
623
|
+
useEffect(() => {
|
|
624
|
+
return () => {
|
|
625
|
+
mouseUps.delete(unPress)
|
|
626
|
+
}
|
|
627
|
+
}, [])
|
|
512
628
|
}
|
|
513
629
|
|
|
514
|
-
useIsomorphicLayoutEffect(() => {
|
|
515
|
-
// we need to use state to properly have mounted go from false => true
|
|
516
|
-
if (isClient && (hasEnterStyle || props.animation) && !state.mounted) {
|
|
517
|
-
// for SSR we never set mounted, ensuring enterStyle={{}} is set by default
|
|
518
|
-
setStateShallow({
|
|
519
|
-
mounted: true,
|
|
520
|
-
})
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
internal.current!.isMounted = true
|
|
524
|
-
return () => {
|
|
525
|
-
mouseUps.delete(unPress)
|
|
526
|
-
internal.current!.isMounted = false
|
|
527
|
-
internal.current!.unmountEffects?.forEach((cb) => cb())
|
|
528
|
-
}
|
|
529
|
-
}, [hasEnterStyle, props.animation])
|
|
530
|
-
|
|
531
630
|
let styles: any[]
|
|
532
631
|
|
|
533
632
|
const animationStyles = state.animation ? state.animation.style : null
|
|
@@ -546,11 +645,13 @@ export function createComponent<
|
|
|
546
645
|
]
|
|
547
646
|
if (!animationStyles && initialSplitStyles) {
|
|
548
647
|
const initPseudos = initialSplitStyles.pseudos
|
|
549
|
-
const force = shouldForcePseudo
|
|
550
648
|
!state.mounted && addPseudoToStyles(styles, initPseudos, pseudos, 'enterStyle')
|
|
551
|
-
state.hover &&
|
|
552
|
-
|
|
553
|
-
state.
|
|
649
|
+
state.hover &&
|
|
650
|
+
addPseudoToStyles(styles, initPseudos, pseudos, 'hoverStyle', shouldForcePseudo)
|
|
651
|
+
state.focus &&
|
|
652
|
+
addPseudoToStyles(styles, initPseudos, pseudos, 'focusStyle', shouldForcePseudo)
|
|
653
|
+
state.press &&
|
|
654
|
+
addPseudoToStyles(styles, initPseudos, pseudos, 'pressStyle', shouldForcePseudo)
|
|
554
655
|
}
|
|
555
656
|
// ugly but for now...
|
|
556
657
|
if (shouldForcePseudo) {
|
|
@@ -606,7 +707,34 @@ export function createComponent<
|
|
|
606
707
|
}
|
|
607
708
|
|
|
608
709
|
viewProps.style = style
|
|
609
|
-
}
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
if (process.env.TAMAGUI_TARGET === 'native') {
|
|
713
|
+
// swap out the right family based on weight/style
|
|
714
|
+
if (splitStyles.fontFamily) {
|
|
715
|
+
const faceInfo = config.fontsParsed[splitStyles.fontFamily]?.face
|
|
716
|
+
if (faceInfo) {
|
|
717
|
+
const [weight, style] = (() => {
|
|
718
|
+
let weight: string | undefined
|
|
719
|
+
let style: string | undefined
|
|
720
|
+
for (let i = styles.length; i >= 0; i--) {
|
|
721
|
+
weight ??= styles[i]?.fontWeight
|
|
722
|
+
style ??= styles[i]?.fontStyle
|
|
723
|
+
}
|
|
724
|
+
return [weight || '400', style || 'normal'] as const
|
|
725
|
+
})()
|
|
726
|
+
const overrideFace = faceInfo[weight]?.[style]?.val
|
|
727
|
+
if (overrideFace) {
|
|
728
|
+
for (const style of styles) {
|
|
729
|
+
if (style?.fontFamily) {
|
|
730
|
+
style.fontFamily = overrideFace
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// assign styles
|
|
610
738
|
viewProps.style = styles
|
|
611
739
|
}
|
|
612
740
|
|
|
@@ -648,7 +776,6 @@ export function createComponent<
|
|
|
648
776
|
'onMouseLeave' in props)))
|
|
649
777
|
|
|
650
778
|
const unPress = useCallback(() => {
|
|
651
|
-
if (!internal.current!.isMounted) return
|
|
652
779
|
setStateShallow({
|
|
653
780
|
press: false,
|
|
654
781
|
pressIn: false,
|
|
@@ -739,8 +866,9 @@ export function createComponent<
|
|
|
739
866
|
: null
|
|
740
867
|
|
|
741
868
|
let space = spaceProp
|
|
869
|
+
|
|
742
870
|
// find space by media query
|
|
743
|
-
if (
|
|
871
|
+
if (mediaKeys.length) {
|
|
744
872
|
for (const key in mediaState) {
|
|
745
873
|
if (!mediaState[key]) continue
|
|
746
874
|
if (props[key] && props[key].space !== undefined) {
|
|
@@ -854,7 +982,9 @@ export function createComponent<
|
|
|
854
982
|
// only necessary when animating because some AnimatedView which wraps RNW View doesn't forward dataSet className
|
|
855
983
|
const isAnimatedRNWView = isAnimated && typeof elementType !== 'string' // assuming for now as reanimated is only driver
|
|
856
984
|
const shouldWrapWithComponentTheme =
|
|
857
|
-
|
|
985
|
+
!!theme.className &&
|
|
986
|
+
isAnimatedRNWView &&
|
|
987
|
+
getReturnVariablesAs(props, splitStyleState) === 'non-color-value'
|
|
858
988
|
const shouldWrapWithHover = Boolean(events || isRSC) && attachHover
|
|
859
989
|
|
|
860
990
|
if (shouldWrapWithHover || shouldWrapWithComponentTheme) {
|
|
@@ -901,14 +1031,7 @@ export function createComponent<
|
|
|
901
1031
|
}
|
|
902
1032
|
}
|
|
903
1033
|
|
|
904
|
-
return
|
|
905
|
-
<>
|
|
906
|
-
{features.elements}
|
|
907
|
-
{content}
|
|
908
|
-
</>
|
|
909
|
-
) : (
|
|
910
|
-
content
|
|
911
|
-
)
|
|
1034
|
+
return content
|
|
912
1035
|
})
|
|
913
1036
|
|
|
914
1037
|
if (staticConfig.componentName) {
|
|
@@ -1335,3 +1458,69 @@ function mergeConfigDefaultProps(
|
|
|
1335
1458
|
}
|
|
1336
1459
|
return props
|
|
1337
1460
|
}
|
|
1461
|
+
|
|
1462
|
+
const defaults = {
|
|
1463
|
+
left: 0,
|
|
1464
|
+
right: 0,
|
|
1465
|
+
top: 0,
|
|
1466
|
+
bottom: 0,
|
|
1467
|
+
opacity: 1,
|
|
1468
|
+
translateX: 0,
|
|
1469
|
+
translateY: 0,
|
|
1470
|
+
skew: 0,
|
|
1471
|
+
skewX: 0,
|
|
1472
|
+
skewY: 0,
|
|
1473
|
+
scale: 1,
|
|
1474
|
+
rotate: '0deg',
|
|
1475
|
+
rotateY: '0deg',
|
|
1476
|
+
rotateX: '0deg',
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
function ensureBaseHasDefaults(base: ViewStyle, ...pseudos: (ViewStyle | null | undefined)[]) {
|
|
1480
|
+
for (const pseudo of pseudos) {
|
|
1481
|
+
if (!pseudo) continue
|
|
1482
|
+
for (const key in pseudo) {
|
|
1483
|
+
const val = pseudo[key]
|
|
1484
|
+
// can we just use merge() here?
|
|
1485
|
+
if (key === 'transform') {
|
|
1486
|
+
if (typeof val === 'string') {
|
|
1487
|
+
continue
|
|
1488
|
+
}
|
|
1489
|
+
for (const t of val) {
|
|
1490
|
+
const tkey = Object.keys(t)[0]
|
|
1491
|
+
const defaultVal = defaults[tkey]
|
|
1492
|
+
const tDefaultVal = { [tkey]: defaultVal } as any
|
|
1493
|
+
if (!base.transform) {
|
|
1494
|
+
base.transform = [tDefaultVal]
|
|
1495
|
+
} else {
|
|
1496
|
+
if (!base.transform.find((x) => x[tkey])) {
|
|
1497
|
+
base.transform.push(tDefaultVal)
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
} else {
|
|
1502
|
+
if (!(key in base)) {
|
|
1503
|
+
base[key] = defaults[key]
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
function merge(base: ViewStyle, next: ViewStyle) {
|
|
1511
|
+
if (!next.transform || !base.transform) {
|
|
1512
|
+
Object.assign(base, next)
|
|
1513
|
+
return
|
|
1514
|
+
}
|
|
1515
|
+
const { transform, ...rest } = next
|
|
1516
|
+
Object.assign(base, rest)
|
|
1517
|
+
for (const t of transform) {
|
|
1518
|
+
const key = Object.keys(t)[0]
|
|
1519
|
+
const existing = base.transform.find((x) => key in x)
|
|
1520
|
+
if (existing) {
|
|
1521
|
+
existing[key] = t[key]
|
|
1522
|
+
} else {
|
|
1523
|
+
base.transform.push(t)
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
}
|
package/src/createFont.ts
CHANGED
|
@@ -4,8 +4,11 @@ export const createFont = <A extends GenericFont>(font: A): A => {
|
|
|
4
4
|
// fills in any missing values based on size keys being standard
|
|
5
5
|
const sizeKeys = Object.keys(font.size)
|
|
6
6
|
|
|
7
|
+
// fill in intermediate values
|
|
7
8
|
for (const key in font) {
|
|
8
|
-
if (key === 'size' || key === 'family')
|
|
9
|
+
if (key === 'size' || key === 'family' || key === 'face') {
|
|
10
|
+
continue
|
|
11
|
+
}
|
|
9
12
|
const section = font[key] as Object
|
|
10
13
|
const keys = Object.keys(section)
|
|
11
14
|
|
|
@@ -78,6 +78,7 @@ type StyleSplitter = (
|
|
|
78
78
|
rulesToInsert: RulesToInsert
|
|
79
79
|
viewProps: StackProps
|
|
80
80
|
fontFamily: string | undefined
|
|
81
|
+
mediaKeys: string[]
|
|
81
82
|
}
|
|
82
83
|
|
|
83
84
|
export const PROP_SPLIT = '-'
|
|
@@ -108,12 +109,14 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
108
109
|
) => {
|
|
109
110
|
conf = conf || getConfig()
|
|
110
111
|
const validStyleProps = staticConfig.isText ? stylePropsText : validStyles
|
|
112
|
+
const mediaKeys: string[] = []
|
|
111
113
|
const viewProps: StackProps = {}
|
|
112
114
|
const pseudos: PseudoStyles = {}
|
|
113
115
|
const medias: Record<MediaQueryKey, ViewStyle> = {}
|
|
114
116
|
const usedKeys = new Set<string>()
|
|
115
117
|
const propKeys = Object.keys(props)
|
|
116
|
-
const shouldDoClasses =
|
|
118
|
+
const shouldDoClasses =
|
|
119
|
+
(isWeb || process.env.IS_STATIC === 'is_static') && !state.noClassNames && !props.animation
|
|
117
120
|
const len = propKeys.length
|
|
118
121
|
const rulesToInsert: RulesToInsert = []
|
|
119
122
|
const style: ViewStyle = {}
|
|
@@ -125,54 +128,7 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
125
128
|
let classNames: ClassNamesObject = {}
|
|
126
129
|
// we need to gather these specific to each media query / pseudo
|
|
127
130
|
// value is [hash, val], so ["-jnjad-asdnjk", "scaleX(1) rotate(10deg)"]
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
function mergeClassName(key: string, val: string, isMediaOrPseudo = false) {
|
|
131
|
-
if (process.env.TAMAGUI_TARGET === 'web') {
|
|
132
|
-
// empty classnames passed by compiler sometimes
|
|
133
|
-
if (!val) return
|
|
134
|
-
if (val.startsWith('_transform-')) {
|
|
135
|
-
const namespace: TransformNamespaceKey = isMediaOrPseudo ? key : 'transform'
|
|
136
|
-
|
|
137
|
-
let transform = insertedTransforms[val]
|
|
138
|
-
if (isClient) {
|
|
139
|
-
if (!transform) {
|
|
140
|
-
// HMR or loaded a new chunk
|
|
141
|
-
updateInserted()
|
|
142
|
-
transform = insertedTransforms[val]
|
|
143
|
-
if (process.env.NODE_ENV === 'development') {
|
|
144
|
-
if (!transform) {
|
|
145
|
-
// eslint-disable-next-line no-console
|
|
146
|
-
console.warn('no transform found', { insertedTransforms, val })
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
if (!transform) {
|
|
151
|
-
if (isWeb && val[0] !== '_') {
|
|
152
|
-
// runtime insert
|
|
153
|
-
transform = val
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
|
|
157
|
-
// prettier-ignore
|
|
158
|
-
// eslint-disable-next-line no-console
|
|
159
|
-
console.log(' 🔹 getSplitStyles mergeClassName transform', { key, val, namespace, transform, insertedTransforms })
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
transforms = transforms || {}
|
|
163
|
-
transforms[namespace] = transforms[namespace] || ['', '']
|
|
164
|
-
const identifier = val.replace('_transform', '')
|
|
165
|
-
transforms[namespace][0] += identifier
|
|
166
|
-
// ssr doesn't need to do anything just make the right classname
|
|
167
|
-
if (transform) {
|
|
168
|
-
transforms[namespace][1] += transform
|
|
169
|
-
}
|
|
170
|
-
} else {
|
|
171
|
-
classNames[key] = val
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
131
|
+
const transforms: Record<TransformNamespaceKey, [string, string]> = {}
|
|
176
132
|
// fontFamily is our special baby, ensure we grab the latest set one always
|
|
177
133
|
let fontFamily: string | undefined
|
|
178
134
|
|
|
@@ -237,14 +193,14 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
237
193
|
fullKey += `${PROP_SPLIT}${pseudoShortKey}`
|
|
238
194
|
}
|
|
239
195
|
usedKeys.add(fullKey)
|
|
240
|
-
mergeClassName(fullKey, cn, isMediaOrPseudo)
|
|
196
|
+
mergeClassName(transforms, classNames, fullKey, cn, isMediaOrPseudo)
|
|
241
197
|
} else {
|
|
242
198
|
nonTamaguis += ' ' + cn
|
|
243
199
|
}
|
|
244
200
|
}
|
|
245
201
|
if (nonTamaguis) {
|
|
246
202
|
usedKeys.add(keyInit)
|
|
247
|
-
mergeClassName(keyInit, nonTamaguis)
|
|
203
|
+
mergeClassName(transforms, classNames, keyInit, nonTamaguis)
|
|
248
204
|
}
|
|
249
205
|
continue
|
|
250
206
|
}
|
|
@@ -259,7 +215,7 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
259
215
|
validStyles[keyInit.split(PROP_SPLIT)[0]]
|
|
260
216
|
if (isValidClassName || isMediaOrPseudo) {
|
|
261
217
|
usedKeys.add(keyInit)
|
|
262
|
-
mergeClassName(keyInit, valInit, isMediaOrPseudo)
|
|
218
|
+
mergeClassName(transforms, classNames, keyInit, valInit, isMediaOrPseudo)
|
|
263
219
|
continue
|
|
264
220
|
}
|
|
265
221
|
}
|
|
@@ -350,7 +306,7 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
350
306
|
continue
|
|
351
307
|
}
|
|
352
308
|
pseudos[key] = pseudos[key] || {}
|
|
353
|
-
|
|
309
|
+
const pseudoStyleObject = getSubStyle(
|
|
354
310
|
key,
|
|
355
311
|
val,
|
|
356
312
|
staticConfig,
|
|
@@ -361,15 +317,16 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
361
317
|
languageContext,
|
|
362
318
|
true
|
|
363
319
|
)
|
|
364
|
-
|
|
365
|
-
|
|
320
|
+
pseudos[key] = pseudoStyleObject
|
|
321
|
+
if (shouldDoClasses && key !== 'enterStyle' && key !== 'exitStyle') {
|
|
322
|
+
const pseudoStyles = getAtomicStyle(pseudoStyleObject, pseudoDescriptors[key])
|
|
366
323
|
for (const style of pseudoStyles) {
|
|
367
324
|
const postfix = pseudoDescriptors[key]?.name || key // exitStyle/enterStyle dont have pseudoDescriptors
|
|
368
325
|
const fullKey = `${style.property}${PROP_SPLIT}${postfix}`
|
|
369
326
|
if (!usedKeys.has(fullKey)) {
|
|
370
327
|
usedKeys.add(fullKey)
|
|
371
328
|
addStyleToInsertRules(rulesToInsert, style)
|
|
372
|
-
mergeClassName(fullKey, style.identifier, isMediaOrPseudo)
|
|
329
|
+
mergeClassName(transforms, classNames, fullKey, style.identifier, isMediaOrPseudo)
|
|
373
330
|
}
|
|
374
331
|
}
|
|
375
332
|
}
|
|
@@ -379,6 +336,7 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
379
336
|
// media
|
|
380
337
|
if (isMedia) {
|
|
381
338
|
const mediaKey = key
|
|
339
|
+
mediaKeys.push(key)
|
|
382
340
|
const mediaKeyShort = mediaKey.slice(1)
|
|
383
341
|
|
|
384
342
|
if (!mediaQueryConfig[mediaKeyShort]) {
|
|
@@ -419,7 +377,7 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
419
377
|
if (!usedKeys.has(fullKey)) {
|
|
420
378
|
usedKeys.add(fullKey)
|
|
421
379
|
addStyleToInsertRules(rulesToInsert, out)
|
|
422
|
-
mergeClassName(fullKey, out.identifier, true)
|
|
380
|
+
mergeClassName(transforms, classNames, fullKey, out.identifier, true)
|
|
423
381
|
}
|
|
424
382
|
}
|
|
425
383
|
} else {
|
|
@@ -428,7 +386,17 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
428
386
|
// eslint-disable-next-line no-console
|
|
429
387
|
console.log('apply media style', mediaKey, mediaState)
|
|
430
388
|
}
|
|
431
|
-
|
|
389
|
+
if (shouldDoClasses) {
|
|
390
|
+
Object.assign(medias, mediaStyle)
|
|
391
|
+
} else {
|
|
392
|
+
for (const key in mediaStyle) {
|
|
393
|
+
usedKeys.add(key)
|
|
394
|
+
style[key] = mediaStyle[key]
|
|
395
|
+
if (key === 'fontFamily') {
|
|
396
|
+
fontFamily = mediaStyle[key]
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
432
400
|
}
|
|
433
401
|
}
|
|
434
402
|
continue
|
|
@@ -447,13 +415,7 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
447
415
|
} else if (key in stylePropsTransform) {
|
|
448
416
|
mergeTransform(style, key, val, true)
|
|
449
417
|
} else {
|
|
450
|
-
// if (key === 'pointerEvents') {
|
|
451
|
-
// // pointer events can be box-none which requires css
|
|
452
|
-
// addStyleToInsertRules(out.identifier, out.styleRule)
|
|
453
|
-
// mergeClassName(fullKey, out.identifier, true)
|
|
454
|
-
// } else {
|
|
455
418
|
style[key] = normalizeValueWithProperty(val, key)
|
|
456
|
-
// }
|
|
457
419
|
}
|
|
458
420
|
continue
|
|
459
421
|
}
|
|
@@ -489,7 +451,7 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
489
451
|
// should probably have a few more exceptions here!
|
|
490
452
|
if (key === 'pointerEvents' || !state.dynamicStylesInline) {
|
|
491
453
|
addStyleToInsertRules(rulesToInsert, atomicStyle)
|
|
492
|
-
mergeClassName(key, atomicStyle.identifier)
|
|
454
|
+
mergeClassName(transforms, classNames, key, atomicStyle.identifier)
|
|
493
455
|
} else {
|
|
494
456
|
style[key] = atomicStyle.value
|
|
495
457
|
}
|
|
@@ -568,12 +530,58 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
568
530
|
viewProps,
|
|
569
531
|
style,
|
|
570
532
|
medias,
|
|
533
|
+
mediaKeys,
|
|
571
534
|
pseudos,
|
|
572
535
|
classNames,
|
|
573
536
|
rulesToInsert,
|
|
574
537
|
}
|
|
575
538
|
}
|
|
576
539
|
|
|
540
|
+
function mergeClassName(
|
|
541
|
+
transforms: Record<string, any[]>,
|
|
542
|
+
classNames: Record<string, string>,
|
|
543
|
+
key: string,
|
|
544
|
+
val: string,
|
|
545
|
+
isMediaOrPseudo = false
|
|
546
|
+
) {
|
|
547
|
+
if (process.env.TAMAGUI_TARGET === 'web') {
|
|
548
|
+
// empty classnames passed by compiler sometimes
|
|
549
|
+
if (!val) return
|
|
550
|
+
if (val.startsWith('_transform-')) {
|
|
551
|
+
const namespace: TransformNamespaceKey = isMediaOrPseudo ? key : 'transform'
|
|
552
|
+
let transform = insertedTransforms[val]
|
|
553
|
+
if (isClient) {
|
|
554
|
+
if (!transform) {
|
|
555
|
+
// HMR or loaded a new chunk
|
|
556
|
+
updateInserted()
|
|
557
|
+
transform = insertedTransforms[val]
|
|
558
|
+
if (process.env.NODE_ENV === 'development') {
|
|
559
|
+
if (!transform) {
|
|
560
|
+
// eslint-disable-next-line no-console
|
|
561
|
+
console.warn('no transform found', { insertedTransforms, val })
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
if (!transform) {
|
|
566
|
+
if (isWeb && val[0] !== '_') {
|
|
567
|
+
// runtime insert
|
|
568
|
+
transform = val
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
transforms[namespace] = transforms[namespace] || ['', '']
|
|
573
|
+
const identifier = val.replace('_transform', '')
|
|
574
|
+
transforms[namespace][0] += identifier
|
|
575
|
+
// ssr doesn't need to do anything just make the right classname
|
|
576
|
+
if (transform) {
|
|
577
|
+
transforms[namespace][1] += transform
|
|
578
|
+
}
|
|
579
|
+
} else {
|
|
580
|
+
classNames[key] = val
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
577
585
|
/**
|
|
578
586
|
* getSubStyle calls propMapper with props
|
|
579
587
|
* those should be specific to the substyle, but fallback to the base props
|
|
@@ -4,10 +4,12 @@ export const mergeTransform = (obj: ViewStyle, key: string, val: any, backwards
|
|
|
4
4
|
obj.transform ||= []
|
|
5
5
|
obj.transform[backwards ? 'unshift' : 'push']({ [mapTransformKeys[key] || key]: val } as any)
|
|
6
6
|
}
|
|
7
|
+
|
|
7
8
|
const mapTransformKeys = {
|
|
8
9
|
x: 'translateX',
|
|
9
10
|
y: 'translateY',
|
|
10
11
|
}
|
|
12
|
+
|
|
11
13
|
export const invertMapTransformKeys = {
|
|
12
14
|
translateX: 'x',
|
|
13
15
|
translateY: 'y',
|
package/src/insertFont.ts
CHANGED
|
@@ -27,7 +27,7 @@ export function parseFont<A extends GenericFont>(definition: A): DeepVariableObj
|
|
|
27
27
|
const parsed: any = {}
|
|
28
28
|
for (const attrKey in definition) {
|
|
29
29
|
const attr = definition[attrKey]
|
|
30
|
-
if (attrKey === 'family') {
|
|
30
|
+
if (attrKey === 'family' || attrKey === 'face') {
|
|
31
31
|
parsed[attrKey] = attr
|
|
32
32
|
continue
|
|
33
33
|
}
|