@tamagui/core 1.0.1-beta.216 → 1.0.1-beta.217
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 +37 -86
- package/dist/cjs/createComponent.js.map +2 -2
- package/dist/cjs/createTamagui.js +2 -2
- package/dist/cjs/createTamagui.js.map +1 -1
- package/dist/cjs/helpers/getSplitStyles.js +44 -38
- package/dist/cjs/helpers/getSplitStyles.js.map +3 -3
- package/dist/cjs/helpers/mergeProps.js.map +2 -2
- package/dist/cjs/helpers/normalizeValueWithProperty.js +7 -2
- package/dist/cjs/helpers/normalizeValueWithProperty.js.map +2 -2
- package/dist/cjs/helpers/useShallowSetState.js.map +2 -2
- package/dist/cjs/hooks/useMedia.js +43 -38
- package/dist/cjs/hooks/useMedia.js.map +2 -2
- package/dist/cjs/views/ThemeInverse.js +1 -2
- package/dist/cjs/views/ThemeInverse.js.map +2 -2
- package/dist/esm/createComponent.js +39 -92
- package/dist/esm/createComponent.js.map +2 -2
- package/dist/esm/createTamagui.js +2 -2
- package/dist/esm/createTamagui.js.map +1 -1
- package/dist/esm/helpers/getSplitStyles.js +44 -38
- package/dist/esm/helpers/getSplitStyles.js.map +3 -3
- package/dist/esm/helpers/mergeProps.js.map +2 -2
- package/dist/esm/helpers/normalizeValueWithProperty.js +7 -2
- package/dist/esm/helpers/normalizeValueWithProperty.js.map +2 -2
- package/dist/esm/helpers/useShallowSetState.js.map +2 -2
- package/dist/esm/hooks/useMedia.js +44 -39
- package/dist/esm/hooks/useMedia.js.map +2 -2
- package/dist/esm/views/ThemeInverse.js +1 -2
- package/dist/esm/views/ThemeInverse.js.map +2 -2
- package/package.json +16 -16
- package/src/createComponent.tsx +50 -109
- package/src/createTamagui.ts +2 -2
- package/src/helpers/getSplitStyles.tsx +44 -37
- package/src/helpers/mergeProps.ts +7 -7
- package/src/helpers/normalizeValueWithProperty.ts +9 -2
- package/src/helpers/useShallowSetState.tsx +3 -1
- package/src/hooks/useMedia.tsx +49 -41
- package/src/views/ThemeInverse.tsx +1 -2
- package/types/helpers/mergeProps.d.ts +2 -2
- package/types/helpers/useShallowSetState.d.ts +2 -1
package/src/createComponent.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useComposedRefs } from '@tamagui/compose-refs'
|
|
2
|
-
import { isClient, isRSC, isWeb, useIsomorphicLayoutEffect } from '@tamagui/constants'
|
|
2
|
+
import { isClient, isRSC, isServer, isWeb, useIsomorphicLayoutEffect } from '@tamagui/constants'
|
|
3
3
|
/* eslint-disable react-hooks/rules-of-hooks */
|
|
4
4
|
import {
|
|
5
5
|
composeEventHandlers,
|
|
@@ -29,23 +29,18 @@ import { stackDefaultStyles } from './constants/constants'
|
|
|
29
29
|
import { FontLanguageContext } from './contexts/FontLanguageContext'
|
|
30
30
|
import { TextAncestorContext } from './contexts/TextAncestorContext'
|
|
31
31
|
import { extendStaticConfig, parseStaticConfig } from './helpers/extendStaticConfig'
|
|
32
|
-
import {
|
|
33
|
-
SplitStyleResult,
|
|
34
|
-
getSubStyle,
|
|
35
|
-
insertSplitStyles,
|
|
36
|
-
useSplitStyles,
|
|
37
|
-
} from './helpers/getSplitStyles'
|
|
32
|
+
import { getSubStyle, useSplitStyles } from './helpers/getSplitStyles'
|
|
38
33
|
import { getAllSelectors } from './helpers/insertStyleRule'
|
|
39
34
|
import { mergeProps } from './helpers/mergeProps'
|
|
40
35
|
import { mergeTransform } from './helpers/mergeTransform'
|
|
41
36
|
import { proxyThemeVariables } from './helpers/proxyThemeVariables'
|
|
42
|
-
import { pseudoDescriptors } from './helpers/pseudoDescriptors'
|
|
43
37
|
import { useShallowSetState } from './helpers/useShallowSetState'
|
|
44
38
|
import { getRect, measureLayout, useElementLayout } from './hooks/useElementLayout'
|
|
45
39
|
import { addMediaQueryListener, getInitialMediaState } from './hooks/useMedia'
|
|
46
40
|
import { useServerRef, useServerState } from './hooks/useServerHooks'
|
|
47
41
|
import { getThemeManager, useTheme } from './hooks/useTheme'
|
|
48
42
|
import {
|
|
43
|
+
DebugProp,
|
|
49
44
|
SpaceDirection,
|
|
50
45
|
SpaceTokens,
|
|
51
46
|
SpacerProps,
|
|
@@ -140,7 +135,6 @@ export function createComponent<
|
|
|
140
135
|
let defaultNativeStyle: any
|
|
141
136
|
let tamaguiDefaultProps: any
|
|
142
137
|
let defaultTag: string | undefined
|
|
143
|
-
let initialSplitStyles: SplitStyleResult
|
|
144
138
|
|
|
145
139
|
// see onConfiguredOnce below which attaches a name then to this component
|
|
146
140
|
const component = forwardRef<Ref, ComponentPropTypes>((propsIn: any, forwardedRef) => {
|
|
@@ -157,7 +151,7 @@ export function createComponent<
|
|
|
157
151
|
|
|
158
152
|
// time`mergeProps`
|
|
159
153
|
|
|
160
|
-
const debugProp = props['debug']
|
|
154
|
+
const debugProp = props['debug'] as DebugProp
|
|
161
155
|
const { Component, isText, isZStack } = staticConfig
|
|
162
156
|
const componentName = props.componentName || staticConfig.componentName
|
|
163
157
|
const componentClassName = props.asChild
|
|
@@ -194,7 +188,7 @@ export function createComponent<
|
|
|
194
188
|
)
|
|
195
189
|
|
|
196
190
|
if (process.env.NODE_ENV === 'development') {
|
|
197
|
-
if (
|
|
191
|
+
if (debugProp) {
|
|
198
192
|
const name = `${
|
|
199
193
|
componentName || Component?.displayName || Component?.name || '[Unnamed Component]'
|
|
200
194
|
}`
|
|
@@ -203,8 +197,18 @@ export function createComponent<
|
|
|
203
197
|
const banner = `${name}${dataIs ? ` ${dataIs}` : ''} ${type}`
|
|
204
198
|
// eslint-disable-next-line no-console
|
|
205
199
|
console.group(`%c ${banner}`, 'background: yellow;')
|
|
206
|
-
|
|
207
|
-
|
|
200
|
+
if (!isServer) {
|
|
201
|
+
// eslint-disable-next-line no-console
|
|
202
|
+
console.log(`state`, state)
|
|
203
|
+
// eslint-disable-next-line no-console
|
|
204
|
+
console.groupCollapsed('props')
|
|
205
|
+
// eslint-disable-next-line no-console
|
|
206
|
+
console.log(props)
|
|
207
|
+
// eslint-disable-next-line no-console
|
|
208
|
+
console.log('order', Object.keys(props))
|
|
209
|
+
// eslint-disable-next-line no-console
|
|
210
|
+
console.groupEnd()
|
|
211
|
+
}
|
|
208
212
|
}
|
|
209
213
|
}
|
|
210
214
|
|
|
@@ -254,19 +258,18 @@ export function createComponent<
|
|
|
254
258
|
|
|
255
259
|
// time`setupStateConf`
|
|
256
260
|
|
|
257
|
-
const splitStyleState: SplitStyleState = {
|
|
258
|
-
...state,
|
|
259
|
-
noClassNames,
|
|
260
|
-
dynamicStylesInline: noClassNames,
|
|
261
|
-
hasTextAncestor,
|
|
262
|
-
resolveVariablesAs: 'value',
|
|
263
|
-
}
|
|
264
261
|
const splitStyles = useSplitStyles(
|
|
265
262
|
props,
|
|
266
263
|
staticConfig,
|
|
267
264
|
theme,
|
|
268
|
-
|
|
269
|
-
|
|
265
|
+
{
|
|
266
|
+
...state,
|
|
267
|
+
noClassNames,
|
|
268
|
+
dynamicStylesInline: noClassNames,
|
|
269
|
+
hasTextAncestor,
|
|
270
|
+
resolveVariablesAs: 'value',
|
|
271
|
+
},
|
|
272
|
+
null,
|
|
270
273
|
languageContext || undefined,
|
|
271
274
|
elementType,
|
|
272
275
|
debugProp
|
|
@@ -593,7 +596,7 @@ export function createComponent<
|
|
|
593
596
|
}, [unPress])
|
|
594
597
|
}
|
|
595
598
|
|
|
596
|
-
let styles: any[]
|
|
599
|
+
let styles: Record<string, any>[]
|
|
597
600
|
|
|
598
601
|
if (isStringElement && shouldAvoidClasses && !shouldForcePseudo) {
|
|
599
602
|
styles = {
|
|
@@ -607,11 +610,7 @@ export function createComponent<
|
|
|
607
610
|
// ugly but for now...
|
|
608
611
|
if (shouldForcePseudo) {
|
|
609
612
|
const next = {}
|
|
610
|
-
|
|
611
|
-
if (style) {
|
|
612
|
-
Object.assign(next, style)
|
|
613
|
-
}
|
|
614
|
-
}
|
|
613
|
+
styles.forEach((style) => Object.assign(next, style))
|
|
615
614
|
// @ts-ignore
|
|
616
615
|
Object.assign(splitStyles.style, next)
|
|
617
616
|
}
|
|
@@ -687,16 +686,11 @@ export function createComponent<
|
|
|
687
686
|
viewProps.style = styles
|
|
688
687
|
}
|
|
689
688
|
|
|
690
|
-
|
|
691
|
-
const initialPseudos = initialSplitStyles?.pseudos
|
|
692
|
-
const runtimePressStyle = noClassNames && (pseudos?.pressStyle || initialPseudos?.pressStyle)
|
|
689
|
+
const runtimePressStyle = !disabled && noClassNames && pseudos?.pressStyle
|
|
693
690
|
const attachPress = !!(runtimePressStyle || onPress || onPressOut || onPressIn || onClick)
|
|
694
|
-
|
|
695
|
-
const isHoverable =
|
|
696
|
-
|
|
697
|
-
const attachHover =
|
|
698
|
-
isHoverable &&
|
|
699
|
-
!!(runtimeHoverStyle || onHoverIn || onHoverOut || onMouseEnter || onMouseLeave)
|
|
691
|
+
const runtimeHoverStyle = !disabled && noClassNames && pseudos?.hoverStyle
|
|
692
|
+
const isHoverable =
|
|
693
|
+
isWeb && !!(runtimeHoverStyle || onHoverIn || onHoverOut || onMouseEnter || onMouseLeave)
|
|
700
694
|
|
|
701
695
|
const handlesPressEvents = !isWeb && !asChild
|
|
702
696
|
|
|
@@ -706,7 +700,7 @@ export function createComponent<
|
|
|
706
700
|
? false
|
|
707
701
|
: Boolean(
|
|
708
702
|
attachPress ||
|
|
709
|
-
|
|
703
|
+
isHoverable ||
|
|
710
704
|
'pressStyle' in props ||
|
|
711
705
|
'onPress' in props ||
|
|
712
706
|
'onPressIn' in props ||
|
|
@@ -729,28 +723,28 @@ export function createComponent<
|
|
|
729
723
|
onMouseUp?.(e)
|
|
730
724
|
}
|
|
731
725
|
: undefined,
|
|
732
|
-
...(
|
|
733
|
-
onMouseEnter:
|
|
726
|
+
...(isHoverable && {
|
|
727
|
+
onMouseEnter: isHoverable
|
|
734
728
|
? (e) => {
|
|
735
729
|
const next: Partial<typeof state> = {}
|
|
736
|
-
if (
|
|
730
|
+
if (isHoverable) {
|
|
737
731
|
next.hover = true
|
|
738
732
|
}
|
|
739
733
|
if (state.pressIn) {
|
|
740
734
|
next.press = true
|
|
741
735
|
}
|
|
742
|
-
if (
|
|
736
|
+
if (isHoverable || state.pressIn) {
|
|
743
737
|
setStateShallow(next)
|
|
744
738
|
}
|
|
745
739
|
onHoverIn?.(e)
|
|
746
740
|
onMouseEnter?.(e)
|
|
747
741
|
}
|
|
748
742
|
: undefined,
|
|
749
|
-
onMouseLeave:
|
|
743
|
+
onMouseLeave: isHoverable
|
|
750
744
|
? (e) => {
|
|
751
745
|
const next: Partial<typeof state> = {}
|
|
752
746
|
mouseUps.add(unPress)
|
|
753
|
-
if (
|
|
747
|
+
if (isHoverable) {
|
|
754
748
|
next.hover = false
|
|
755
749
|
}
|
|
756
750
|
if (state.pressIn) {
|
|
@@ -855,7 +849,7 @@ export function createComponent<
|
|
|
855
849
|
// EVENTS native
|
|
856
850
|
if (process.env.TAMAGUI_TARGET === 'native') {
|
|
857
851
|
// add focus events
|
|
858
|
-
const attachFocus = !!
|
|
852
|
+
const attachFocus = !!pseudos.focusStyle
|
|
859
853
|
if (attachFocus) {
|
|
860
854
|
viewProps.onFocus = mergeEvent(viewProps.onFocus, () => {
|
|
861
855
|
setStateShallow({ focus: true })
|
|
@@ -917,7 +911,7 @@ export function createComponent<
|
|
|
917
911
|
if (typeof window !== 'undefined') {
|
|
918
912
|
// prettier-ignore
|
|
919
913
|
// eslint-disable-next-line no-console
|
|
920
|
-
console.log({ state, shouldProvideThemeManager, isAnimated, isAnimatedReactNativeWeb, tamaguiDefaultProps, viewProps, splitStyles, animationStyles, handlesPressEvents, isStringElement, classNamesIn: props.className?.split(' '), classNamesOut: viewProps.className?.split(' '), events, shouldAttach, styles, pseudos, content, childEls, shouldAvoidClasses, avoidClasses: avoidClassesWhileAnimating, animation: props.animation, style: splitStylesStyle, defaultNativeStyle,
|
|
914
|
+
console.log({ state, shouldProvideThemeManager, isAnimated, isAnimatedReactNativeWeb, tamaguiDefaultProps, viewProps, splitStyles, animationStyles, handlesPressEvents, isStringElement, classNamesIn: props.className?.split(' '), classNamesOut: viewProps.className?.split(' '), events, shouldAttach, styles, pseudos, content, childEls, shouldAvoidClasses, avoidClasses: avoidClassesWhileAnimating, animation: props.animation, style: splitStylesStyle, defaultNativeStyle, ...(typeof window !== 'undefined' ? { theme, themeClassName: theme.className, staticConfig, tamaguiConfig, events, shouldAvoidClasses, shouldForcePseudo, classNames: Object.fromEntries(Object.entries(classNames).map(([k, v]) => [v, getAllSelectors()[v]])) } : null) })
|
|
921
915
|
}
|
|
922
916
|
// eslint-disable-next-line no-console
|
|
923
917
|
console.groupEnd()
|
|
@@ -994,50 +988,22 @@ export function createComponent<
|
|
|
994
988
|
const debug = defaultPropsIn['debug']
|
|
995
989
|
|
|
996
990
|
// remove all classNames
|
|
997
|
-
const [ourProps, ourClassNames] = mergeProps(defaultPropsIn, {}
|
|
991
|
+
const [ourProps, ourClassNames] = mergeProps(defaultPropsIn, {})
|
|
998
992
|
|
|
999
993
|
if (ourProps.tag) {
|
|
1000
994
|
defaultTag = ourProps.tag
|
|
1001
995
|
}
|
|
1002
996
|
|
|
1003
997
|
const noClassNames = !staticConfig.acceptsClassName
|
|
1004
|
-
|
|
1005
|
-
initialSplitStyles = insertSplitStyles(
|
|
1006
|
-
ourProps,
|
|
1007
|
-
staticConfig,
|
|
1008
|
-
initialTheme,
|
|
1009
|
-
{
|
|
1010
|
-
unmounted: false,
|
|
1011
|
-
hover: false,
|
|
1012
|
-
press: false,
|
|
1013
|
-
pressIn: false,
|
|
1014
|
-
focus: false,
|
|
1015
|
-
resolveVariablesAs: 'both',
|
|
1016
|
-
noClassNames,
|
|
1017
|
-
},
|
|
1018
|
-
undefined,
|
|
1019
|
-
undefined,
|
|
1020
|
-
debug
|
|
1021
|
-
)
|
|
998
|
+
const { name, variants, defaultVariants, ...restProps } = ourProps
|
|
1022
999
|
|
|
1023
1000
|
// must preserve prop order
|
|
1024
1001
|
// leave out className because we handle that already with initialSplitStyles.classNames
|
|
1025
1002
|
// otherwise it confuses variant functions getting className props
|
|
1026
|
-
const [defaults, defaultsClassnames] = mergeProps(
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
: initialSplitStyles.viewProps,
|
|
1031
|
-
true
|
|
1032
|
-
// conf.inverseShorthands
|
|
1033
|
-
)
|
|
1034
|
-
|
|
1035
|
-
// avoid passing className props to variants
|
|
1036
|
-
initialSplitStyles.classNames = {
|
|
1037
|
-
...defaultsClassnames,
|
|
1038
|
-
...initialSplitStyles.classNames,
|
|
1039
|
-
...ourClassNames,
|
|
1040
|
-
}
|
|
1003
|
+
const [defaults, defaultsClassnames] = mergeProps(component.defaultProps as any, {
|
|
1004
|
+
...defaultVariants,
|
|
1005
|
+
...restProps,
|
|
1006
|
+
})
|
|
1041
1007
|
|
|
1042
1008
|
defaultNativeStyle = {}
|
|
1043
1009
|
|
|
@@ -1056,40 +1022,15 @@ export function createComponent<
|
|
|
1056
1022
|
}
|
|
1057
1023
|
}
|
|
1058
1024
|
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
// temp bugfix, splitStyles isn't returning variables when resolveVariablesAs == 'both'
|
|
1063
|
-
if (!isWeb) {
|
|
1064
|
-
Object.keys(pseudoDescriptors).forEach((k) => {
|
|
1065
|
-
if (ourProps[k]) {
|
|
1066
|
-
// @ts-ignore
|
|
1067
|
-
initialSplitStyles.pseudos[k] = null
|
|
1068
|
-
tamaguiDefaultProps[k] = ourProps[k]
|
|
1069
|
-
}
|
|
1070
|
-
})
|
|
1071
|
-
}
|
|
1072
|
-
}
|
|
1025
|
+
// set to global
|
|
1026
|
+
tamaguiDefaultProps = defaults
|
|
1073
1027
|
|
|
1074
1028
|
// add debug logs
|
|
1075
1029
|
if (process.env.NODE_ENV === 'development' && debug) {
|
|
1076
1030
|
if (process.env.IS_STATIC !== 'is_static') {
|
|
1031
|
+
// prettier-ignore
|
|
1077
1032
|
// eslint-disable-next-line no-console
|
|
1078
|
-
console.log(`🐛 [${staticConfig.componentName || 'Component'}]`, {
|
|
1079
|
-
staticConfig,
|
|
1080
|
-
initialSplitStyles,
|
|
1081
|
-
tamaguiDefaultProps,
|
|
1082
|
-
defaultNativeStyle,
|
|
1083
|
-
defaults,
|
|
1084
|
-
defaultPropsIn,
|
|
1085
|
-
defaultPropsKeyOrder: Object.keys(staticConfig.defaultProps),
|
|
1086
|
-
defaultPropsInKeyOrder: Object.keys(defaultPropsIn).map((k) => [k, defaultPropsIn[k]]),
|
|
1087
|
-
ourProps,
|
|
1088
|
-
ourClassNames,
|
|
1089
|
-
defaultsClassnames,
|
|
1090
|
-
defaultTag,
|
|
1091
|
-
noClassNames,
|
|
1092
|
-
})
|
|
1033
|
+
console.log(`🐛 [${staticConfig.componentName || 'Component'}]`, { staticConfig, tamaguiDefaultProps, defaultNativeStyle, defaults, defaultPropsIn, defaultPropsKeyOrder: Object.keys(staticConfig.defaultProps), defaultPropsInKeyOrder: Object.keys(defaultPropsIn).map((k) => [k, defaultPropsIn[k]]), ourProps, ourClassNames, defaultsClassnames, defaultTag, noClassNames, })
|
|
1093
1034
|
}
|
|
1094
1035
|
}
|
|
1095
1036
|
})
|
package/src/createTamagui.ts
CHANGED
|
@@ -195,8 +195,8 @@ export function createTamagui<Conf extends CreateTamaguiProps>(
|
|
|
195
195
|
tokensParsed,
|
|
196
196
|
parsed: true,
|
|
197
197
|
getCSS: () => `
|
|
198
|
-
.is_Text .is_Text {
|
|
199
|
-
._dsp_contents {
|
|
198
|
+
.is_Text .is_Text {display:inline-flex;}
|
|
199
|
+
._dsp_contents {display:contents;}
|
|
200
200
|
${themeConfig.css}
|
|
201
201
|
${getAllRules().join('\n')}
|
|
202
202
|
`,
|
|
@@ -196,21 +196,9 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
196
196
|
const shouldDoClasses =
|
|
197
197
|
staticConfig.acceptsClassName && (isWeb || IS_STATIC) && !state.noClassNames
|
|
198
198
|
|
|
199
|
-
|
|
199
|
+
const style: ViewStyle = {}
|
|
200
200
|
let flatTransforms: Record<string, any> | undefined
|
|
201
201
|
|
|
202
|
-
function mergeStyle(key: string, val: any) {
|
|
203
|
-
usedKeys[key] = usedKeys[key] || 1
|
|
204
|
-
if (val && val[0] === '_') {
|
|
205
|
-
classNames[key] = val
|
|
206
|
-
} else if (key in stylePropsTransform) {
|
|
207
|
-
flatTransforms ||= {}
|
|
208
|
-
flatTransforms[key] = val
|
|
209
|
-
} else {
|
|
210
|
-
style[key] = normalizeValueWithProperty(val, key)
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
202
|
const len = propKeys.length
|
|
215
203
|
const rulesToInsert: RulesToInsert = []
|
|
216
204
|
const classNames: ClassNamesObject = {}
|
|
@@ -225,6 +213,18 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
225
213
|
let keyInit = propKeys[i]
|
|
226
214
|
const valInit = props[keyInit]
|
|
227
215
|
|
|
216
|
+
if (validStyleProps[keyInit] || keyInit.includes('-')) {
|
|
217
|
+
if (valInit && valInit[0] === '_') {
|
|
218
|
+
if (shouldDoClasses) {
|
|
219
|
+
classNames[keyInit] = valInit
|
|
220
|
+
} else {
|
|
221
|
+
style[keyInit] = reverseMapClassNameToValue(keyInit, valInit)
|
|
222
|
+
}
|
|
223
|
+
usedKeys[keyInit] = 1
|
|
224
|
+
continue
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
228
|
// normalize shorthands up front
|
|
229
229
|
const expandedKey = conf.shorthands[keyInit]
|
|
230
230
|
if (expandedKey) {
|
|
@@ -251,6 +251,18 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
251
251
|
continue
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
+
function mergeStyle(key: string, val: any) {
|
|
255
|
+
usedKeys[key] = usedKeys[key] || 1
|
|
256
|
+
if (val && val[0] === '_') {
|
|
257
|
+
classNames[key] = val
|
|
258
|
+
} else if (key in stylePropsTransform) {
|
|
259
|
+
flatTransforms ||= {}
|
|
260
|
+
flatTransforms[key] = val
|
|
261
|
+
} else {
|
|
262
|
+
style[key] = normalizeValueWithProperty(val, key)
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
254
266
|
if (process.env.TAMAGUI_TARGET === 'web') {
|
|
255
267
|
/**
|
|
256
268
|
* Copying in the accessibility/prop handling from react-native-web here
|
|
@@ -416,6 +428,7 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
416
428
|
!isValidClassName &&
|
|
417
429
|
keyInit.includes(PROP_SPLIT) &&
|
|
418
430
|
validStyles[keyInit.split(PROP_SPLIT)[0]]
|
|
431
|
+
|
|
419
432
|
if (isValidClassName || isMediaOrPseudo) {
|
|
420
433
|
usedKeys[keyInit] = 1
|
|
421
434
|
mergeClassName(transforms, classNames, keyInit, valInit, isMediaOrPseudo)
|
|
@@ -479,13 +492,9 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
479
492
|
}
|
|
480
493
|
|
|
481
494
|
if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
|
|
482
|
-
if (!isServer) {
|
|
483
|
-
// eslint-disable-next-line no-console
|
|
484
|
-
console.log('expanded', expanded)
|
|
485
|
-
// eslint-disable-next-line no-console
|
|
486
|
-
console.log('usedKeys', usedKeys)
|
|
495
|
+
if (!isServer && isWeb) {
|
|
487
496
|
// eslint-disable-next-line no-console
|
|
488
|
-
console.log('
|
|
497
|
+
console.log('expanded', expanded, '\nusedKeys', usedKeys, '\ncurrent', { ...style })
|
|
489
498
|
}
|
|
490
499
|
// eslint-disable-next-line no-console
|
|
491
500
|
console.groupEnd()
|
|
@@ -677,31 +686,32 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
677
686
|
|
|
678
687
|
// add in defaults if not set:
|
|
679
688
|
if (parentSplitStyles) {
|
|
680
|
-
if (process.env.NODE_ENV === 'development') {
|
|
681
|
-
if (debug === 'verbose') {
|
|
682
|
-
// eslint-disable-next-line no-console
|
|
683
|
-
console.log(` add in styled() parent styles`, { parentSplitStyles, shouldDoClasses })
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
689
|
if (process.env.TAMAGUI_TARGET === 'web') {
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
if (!shouldDoClasses) {
|
|
692
|
-
style[key] = reverseMapClassNameToValue(key, val)
|
|
693
|
-
} else {
|
|
690
|
+
if (shouldDoClasses) {
|
|
691
|
+
for (const key in parentSplitStyles.classNames) {
|
|
692
|
+
const val = parentSplitStyles.classNames[key]
|
|
693
|
+
if (key in style || key in classNames) continue
|
|
694
694
|
classNames[key] = val
|
|
695
695
|
}
|
|
696
696
|
}
|
|
697
697
|
}
|
|
698
698
|
if (!shouldDoClasses) {
|
|
699
699
|
for (const key in parentSplitStyles.style) {
|
|
700
|
-
if (key in classNames) continue
|
|
701
|
-
if (key in style) continue
|
|
700
|
+
if (key in classNames || key in style) continue
|
|
702
701
|
style[key] = parentSplitStyles.style[key]
|
|
703
702
|
}
|
|
704
703
|
}
|
|
704
|
+
if (process.env.NODE_ENV === 'development') {
|
|
705
|
+
if (debug === 'verbose') {
|
|
706
|
+
// eslint-disable-next-line no-console
|
|
707
|
+
console.log(` add in parent styled()`, {
|
|
708
|
+
parentSplitStyles,
|
|
709
|
+
shouldDoClasses,
|
|
710
|
+
style: { ...style },
|
|
711
|
+
classNames: { ...classNames },
|
|
712
|
+
})
|
|
713
|
+
}
|
|
714
|
+
}
|
|
705
715
|
}
|
|
706
716
|
|
|
707
717
|
if (process.env.TAMAGUI_TARGET === 'web') {
|
|
@@ -715,9 +725,6 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
715
725
|
addStyleToInsertRules(rulesToInsert, atomicStyle)
|
|
716
726
|
mergeClassName(transforms, classNames, key, atomicStyle.identifier)
|
|
717
727
|
}
|
|
718
|
-
if (!IS_STATIC) {
|
|
719
|
-
style = emptyObject
|
|
720
|
-
}
|
|
721
728
|
}
|
|
722
729
|
}
|
|
723
730
|
|
|
@@ -12,16 +12,16 @@
|
|
|
12
12
|
* - shorthands can be expanded before merging
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
type
|
|
15
|
+
type AnyRecord = Record<string, any>
|
|
16
16
|
|
|
17
17
|
export const mergeProps = (
|
|
18
18
|
a: Object,
|
|
19
19
|
b: Object,
|
|
20
20
|
leaveOutClassNames = false,
|
|
21
|
-
inverseShorthands?:
|
|
21
|
+
inverseShorthands?: AnyRecord
|
|
22
22
|
) => {
|
|
23
|
-
const out:
|
|
24
|
-
const outCns:
|
|
23
|
+
const out: AnyRecord = {}
|
|
24
|
+
const outCns: AnyRecord = leaveOutClassNames ? {} : (null as any)
|
|
25
25
|
for (const key in a) {
|
|
26
26
|
mergeProp(out, outCns, a, b, key, leaveOutClassNames, inverseShorthands)
|
|
27
27
|
}
|
|
@@ -32,13 +32,13 @@ export const mergeProps = (
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
function mergeProp(
|
|
35
|
-
out:
|
|
36
|
-
outCns:
|
|
35
|
+
out: AnyRecord,
|
|
36
|
+
outCns: AnyRecord,
|
|
37
37
|
a: Object,
|
|
38
38
|
b: Object | undefined,
|
|
39
39
|
key: string,
|
|
40
40
|
leaveOutClassNames: boolean,
|
|
41
|
-
inverseShorthands?:
|
|
41
|
+
inverseShorthands?: AnyRecord
|
|
42
42
|
) {
|
|
43
43
|
const val = a[key]
|
|
44
44
|
const shorthand = inverseShorthands ? inverseShorthands[key] : null
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* Copyright (c) Nicolas Gallagher licensed under the MIT license.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { isWeb } from '@tamagui/constants'
|
|
7
|
+
|
|
6
8
|
import { getAllSelectors } from './insertStyleRule'
|
|
7
9
|
import { normalizeColor } from './normalizeColor'
|
|
8
10
|
|
|
@@ -20,9 +22,11 @@ export function normalizeValueWithProperty(value: any, property?: string): any {
|
|
|
20
22
|
if (
|
|
21
23
|
process.env.TAMAGUI_TARGET === 'web' &&
|
|
22
24
|
typeof value === 'number' &&
|
|
23
|
-
(property === undefined || !unitlessNumbers[property])
|
|
25
|
+
(property === undefined || (!unitlessNumbers[property] && !stringNumbers[property]))
|
|
24
26
|
) {
|
|
25
27
|
res = `${value}px`
|
|
28
|
+
} else if (isWeb && property !== undefined && stringNumbers[property]) {
|
|
29
|
+
res = `${res}`
|
|
26
30
|
} else if (property && colorProps[property]) {
|
|
27
31
|
res = normalizeColor(value)
|
|
28
32
|
cache[value] = res
|
|
@@ -45,6 +49,10 @@ const colorProps = {
|
|
|
45
49
|
textShadowColor: true,
|
|
46
50
|
}
|
|
47
51
|
|
|
52
|
+
const stringNumbers = {
|
|
53
|
+
zIndex: true,
|
|
54
|
+
}
|
|
55
|
+
|
|
48
56
|
const unitlessNumbers = {
|
|
49
57
|
WebkitLineClamp: true,
|
|
50
58
|
animationIterationCount: true,
|
|
@@ -74,7 +82,6 @@ const unitlessNumbers = {
|
|
|
74
82
|
orphans: true,
|
|
75
83
|
tabSize: true,
|
|
76
84
|
widows: true,
|
|
77
|
-
zIndex: true,
|
|
78
85
|
zoom: true,
|
|
79
86
|
scale: true,
|
|
80
87
|
scaleX: true,
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import React, { useCallback } from 'react'
|
|
2
2
|
|
|
3
|
+
import { DebugProp } from '../types'
|
|
4
|
+
|
|
3
5
|
export function useShallowSetState<State extends Object>(
|
|
4
6
|
setter: React.Dispatch<React.SetStateAction<State>>,
|
|
5
|
-
debug?:
|
|
7
|
+
debug?: DebugProp,
|
|
6
8
|
debugName?: string
|
|
7
9
|
) {
|
|
8
10
|
return useCallback(
|
package/src/hooks/useMedia.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useIsomorphicLayoutEffect } from '@tamagui/constants'
|
|
2
|
-
import { MutableRefObject, useEffect, useMemo, useState } from 'react'
|
|
2
|
+
import { MutableRefObject, useEffect, useMemo, useState, useSyncExternalStore } from 'react'
|
|
3
3
|
|
|
4
4
|
import { getConfig } from '../config'
|
|
5
5
|
import { createProxy } from '../helpers/createProxy'
|
|
@@ -54,15 +54,12 @@ export function removeMediaQueryListener(key: MediaQueryKey, cb: MediaListener)
|
|
|
54
54
|
|
|
55
55
|
export const mediaQueryConfig: MediaQueries = {}
|
|
56
56
|
|
|
57
|
-
export const getMedia = () =>
|
|
58
|
-
return mediaState
|
|
59
|
-
}
|
|
57
|
+
export const getMedia = () => mediaState
|
|
60
58
|
|
|
61
59
|
// for SSR capture it at time of startup
|
|
62
|
-
let curState: MediaQueryState
|
|
63
60
|
let initState: MediaQueryState
|
|
64
61
|
export const getInitialMediaState = () => {
|
|
65
|
-
return (getConfig().disableSSR ?
|
|
62
|
+
return (getConfig().disableSSR ? mediaState : initState) || {}
|
|
66
63
|
}
|
|
67
64
|
|
|
68
65
|
let mediaKeysOrdered: string[]
|
|
@@ -79,8 +76,8 @@ export const configureMedia = (config: TamaguiInternalConfig) => {
|
|
|
79
76
|
mediaState[key] = mediaQueryDefaultActive?.[key] || false
|
|
80
77
|
}
|
|
81
78
|
Object.assign(mediaQueryConfig, media)
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
initState = { ...mediaState }
|
|
80
|
+
updateCurrentState()
|
|
84
81
|
mediaKeysOrdered = Object.keys(media)
|
|
85
82
|
if (config.disableSSR) {
|
|
86
83
|
setupMediaListeners()
|
|
@@ -126,7 +123,7 @@ function setupMediaListeners() {
|
|
|
126
123
|
const next = !!getMatch().matches
|
|
127
124
|
if (next === mediaState[key]) return
|
|
128
125
|
mediaState[key] = next
|
|
129
|
-
|
|
126
|
+
updateCurrentState()
|
|
130
127
|
const cur = listeners[key]
|
|
131
128
|
if (cur?.size) {
|
|
132
129
|
cur.forEach((cb) => cb(next))
|
|
@@ -143,45 +140,56 @@ export function useMediaListeners(config: TamaguiInternalConfig) {
|
|
|
143
140
|
}, [])
|
|
144
141
|
}
|
|
145
142
|
|
|
143
|
+
const nextTick = process.nextTick || setImmediate
|
|
144
|
+
const currentStateListeners = new Set<any>()
|
|
145
|
+
let isUpdating = false
|
|
146
|
+
function updateCurrentState() {
|
|
147
|
+
if (isUpdating) return
|
|
148
|
+
isUpdating = true
|
|
149
|
+
nextTick(() => {
|
|
150
|
+
currentStateListeners.forEach((cb) => cb(mediaState))
|
|
151
|
+
isUpdating = false
|
|
152
|
+
})
|
|
153
|
+
}
|
|
154
|
+
function subscribe(subscriber: any) {
|
|
155
|
+
currentStateListeners.add(subscriber)
|
|
156
|
+
return () => currentStateListeners.delete(subscriber)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
type MediaKeysState = {
|
|
160
|
+
[key: string]: any
|
|
161
|
+
}
|
|
162
|
+
|
|
146
163
|
export function useMedia(): {
|
|
147
164
|
[key in MediaQueryKey]: boolean
|
|
148
165
|
} {
|
|
149
|
-
const keys = useSafeRef({
|
|
150
|
-
const [state, setState] = useState<MediaQueryState>(() => getMediaState(initState || {}, keys))
|
|
166
|
+
const keys = useSafeRef<MediaKeysState>({ prev: initState })
|
|
151
167
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
168
|
+
const state = useSyncExternalStore<MediaQueryState>(
|
|
169
|
+
subscribe,
|
|
170
|
+
() => {
|
|
171
|
+
const { prev, ...curKeys } = keys.current
|
|
172
|
+
const shouldUpdate = !prev || Object.keys(curKeys).some((k) => mediaState[k] !== prev[k])
|
|
173
|
+
if (shouldUpdate) {
|
|
174
|
+
const next = { ...mediaState }
|
|
175
|
+
keys.current.prev = next
|
|
176
|
+
return next
|
|
158
177
|
}
|
|
159
178
|
return prev
|
|
160
|
-
})
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
useIsomorphicLayoutEffect(() => {
|
|
164
|
-
updateState()
|
|
165
|
-
const disposers = Object.keys(keys.current).map((key) =>
|
|
166
|
-
addMediaQueryListener(key, updateState)
|
|
167
|
-
)
|
|
168
|
-
return () => {
|
|
169
|
-
disposers.forEach((cb) => cb())
|
|
170
|
-
}
|
|
171
|
-
}, [keys.current])
|
|
172
|
-
|
|
173
|
-
return state
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function getMediaState(state: MediaQueryState, keys: MutableRefObject<Record<string, boolean>>) {
|
|
177
|
-
return new Proxy(state, {
|
|
178
|
-
get(_, key: string) {
|
|
179
|
-
if (!keys.current[key]) {
|
|
180
|
-
keys.current[key] = true
|
|
181
|
-
}
|
|
182
|
-
return Reflect.get(state, key)
|
|
183
179
|
},
|
|
184
|
-
|
|
180
|
+
() => initState
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
return useMemo(() => {
|
|
184
|
+
return new Proxy(state, {
|
|
185
|
+
get(_, key: string) {
|
|
186
|
+
if (!keys.current[key]) {
|
|
187
|
+
keys.current[key] = true
|
|
188
|
+
}
|
|
189
|
+
return Reflect.get(state, key)
|
|
190
|
+
},
|
|
191
|
+
})
|
|
192
|
+
}, [state])
|
|
185
193
|
}
|
|
186
194
|
|
|
187
195
|
/**
|