@tamagui/web 1.129.12 → 1.129.13
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/contexts/ComponentContext.cjs +1 -6
- package/dist/cjs/contexts/ComponentContext.js +1 -6
- package/dist/cjs/contexts/ComponentContext.js.map +1 -1
- package/dist/cjs/contexts/ComponentContext.native.js +1 -6
- package/dist/cjs/contexts/ComponentContext.native.js.map +2 -2
- package/dist/cjs/contexts/GroupContext.cjs +27 -0
- package/dist/cjs/contexts/GroupContext.js +22 -0
- package/dist/cjs/contexts/GroupContext.js.map +6 -0
- package/dist/cjs/contexts/GroupContext.native.js +26 -0
- package/dist/cjs/contexts/GroupContext.native.js.map +6 -0
- package/dist/cjs/createComponent.cjs +131 -90
- package/dist/cjs/createComponent.js +139 -94
- package/dist/cjs/createComponent.js.map +2 -2
- package/dist/cjs/createComponent.native.js +156 -106
- package/dist/cjs/createComponent.native.js.map +2 -2
- package/dist/cjs/helpers/createStyledContext.js.map +1 -1
- package/dist/cjs/helpers/createStyledContext.native.js.map +1 -1
- package/dist/cjs/helpers/getSplitStyles.cjs +68 -49
- package/dist/cjs/helpers/getSplitStyles.js +64 -55
- package/dist/cjs/helpers/getSplitStyles.js.map +2 -2
- package/dist/cjs/helpers/getSplitStyles.native.js +82 -63
- package/dist/cjs/helpers/getSplitStyles.native.js.map +2 -2
- package/dist/cjs/helpers/pseudoDescriptors.cjs +12 -12
- package/dist/cjs/helpers/pseudoDescriptors.js +12 -12
- package/dist/cjs/helpers/pseudoDescriptors.js.map +1 -1
- package/dist/cjs/helpers/pseudoDescriptors.native.js +12 -12
- package/dist/cjs/helpers/pseudoDescriptors.native.js.map +1 -1
- package/dist/cjs/helpers/subscribeToContextGroup.cjs +48 -31
- package/dist/cjs/helpers/subscribeToContextGroup.js +36 -20
- package/dist/cjs/helpers/subscribeToContextGroup.js.map +1 -1
- package/dist/cjs/helpers/subscribeToContextGroup.native.js +48 -20
- package/dist/cjs/helpers/subscribeToContextGroup.native.js.map +2 -2
- package/dist/cjs/hooks/useComponentState.cjs +2 -40
- package/dist/cjs/hooks/useComponentState.js +2 -30
- package/dist/cjs/hooks/useComponentState.js.map +2 -2
- package/dist/cjs/hooks/useComponentState.native.js +3 -43
- package/dist/cjs/hooks/useComponentState.native.js.map +2 -2
- package/dist/cjs/hooks/useConfiguration.cjs +1 -17
- package/dist/cjs/hooks/useConfiguration.js +2 -9
- package/dist/cjs/hooks/useConfiguration.js.map +1 -1
- package/dist/cjs/hooks/useConfiguration.native.js +2 -7
- package/dist/cjs/hooks/useConfiguration.native.js.map +2 -2
- package/dist/cjs/hooks/useMedia.cjs +4 -3
- package/dist/cjs/hooks/useMedia.js +3 -3
- package/dist/cjs/hooks/useMedia.js.map +1 -1
- package/dist/cjs/hooks/useMedia.native.js +3 -3
- package/dist/cjs/hooks/useMedia.native.js.map +2 -2
- package/dist/cjs/hooks/useProps.cjs +7 -6
- package/dist/cjs/hooks/useProps.js +13 -11
- package/dist/cjs/hooks/useProps.js.map +1 -1
- package/dist/cjs/hooks/useProps.native.js +11 -10
- package/dist/cjs/hooks/useProps.native.js.map +2 -2
- package/dist/cjs/hooks/useThemeState.cjs +2 -2
- package/dist/cjs/hooks/useThemeState.js +2 -2
- package/dist/cjs/hooks/useThemeState.js.map +1 -1
- package/dist/cjs/hooks/useThemeState.native.js +2 -2
- package/dist/cjs/hooks/useThemeState.native.js.map +1 -1
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.native.js +2 -0
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/views/TamaguiProvider.js.map +1 -1
- package/dist/cjs/views/TamaguiProvider.native.js.map +1 -1
- package/dist/esm/contexts/ComponentContext.js +1 -6
- package/dist/esm/contexts/ComponentContext.js.map +1 -1
- package/dist/esm/contexts/ComponentContext.mjs +1 -6
- package/dist/esm/contexts/ComponentContext.mjs.map +1 -1
- package/dist/esm/contexts/ComponentContext.native.js +1 -6
- package/dist/esm/contexts/ComponentContext.native.js.map +1 -1
- package/dist/esm/contexts/GroupContext.js +6 -0
- package/dist/esm/contexts/GroupContext.js.map +6 -0
- package/dist/esm/contexts/GroupContext.mjs +4 -0
- package/dist/esm/contexts/GroupContext.mjs.map +1 -0
- package/dist/esm/contexts/GroupContext.native.js +4 -0
- package/dist/esm/contexts/GroupContext.native.js.map +1 -0
- package/dist/esm/createComponent.js +141 -94
- package/dist/esm/createComponent.js.map +2 -2
- package/dist/esm/createComponent.mjs +132 -91
- package/dist/esm/createComponent.mjs.map +1 -1
- package/dist/esm/createComponent.native.js +152 -102
- package/dist/esm/createComponent.native.js.map +1 -1
- package/dist/esm/helpers/createStyledContext.js.map +1 -1
- package/dist/esm/helpers/createStyledContext.mjs.map +1 -1
- package/dist/esm/helpers/createStyledContext.native.js.map +1 -1
- package/dist/esm/helpers/getSplitStyles.js +68 -56
- package/dist/esm/helpers/getSplitStyles.js.map +2 -2
- package/dist/esm/helpers/getSplitStyles.mjs +68 -49
- package/dist/esm/helpers/getSplitStyles.mjs.map +1 -1
- package/dist/esm/helpers/getSplitStyles.native.js +72 -53
- package/dist/esm/helpers/getSplitStyles.native.js.map +1 -1
- package/dist/esm/helpers/pseudoDescriptors.js +12 -12
- package/dist/esm/helpers/pseudoDescriptors.js.map +1 -1
- package/dist/esm/helpers/pseudoDescriptors.mjs +12 -12
- package/dist/esm/helpers/pseudoDescriptors.mjs.map +1 -1
- package/dist/esm/helpers/pseudoDescriptors.native.js +12 -12
- package/dist/esm/helpers/pseudoDescriptors.native.js.map +1 -1
- package/dist/esm/helpers/subscribeToContextGroup.js +36 -20
- package/dist/esm/helpers/subscribeToContextGroup.js.map +1 -1
- package/dist/esm/helpers/subscribeToContextGroup.mjs +47 -30
- package/dist/esm/helpers/subscribeToContextGroup.mjs.map +1 -1
- package/dist/esm/helpers/subscribeToContextGroup.native.js +64 -36
- package/dist/esm/helpers/subscribeToContextGroup.native.js.map +1 -1
- package/dist/esm/hooks/useComponentState.js +2 -30
- package/dist/esm/hooks/useComponentState.js.map +2 -2
- package/dist/esm/hooks/useComponentState.mjs +2 -40
- package/dist/esm/hooks/useComponentState.mjs.map +1 -1
- package/dist/esm/hooks/useComponentState.native.js +3 -46
- package/dist/esm/hooks/useComponentState.native.js.map +1 -1
- package/dist/esm/hooks/useConfiguration.js +1 -9
- package/dist/esm/hooks/useConfiguration.js.map +1 -1
- package/dist/esm/hooks/useConfiguration.mjs +1 -17
- package/dist/esm/hooks/useConfiguration.mjs.map +1 -1
- package/dist/esm/hooks/useConfiguration.native.js +1 -15
- package/dist/esm/hooks/useConfiguration.native.js.map +1 -1
- package/dist/esm/hooks/useMedia.js +3 -3
- package/dist/esm/hooks/useMedia.js.map +1 -1
- package/dist/esm/hooks/useMedia.mjs +4 -3
- package/dist/esm/hooks/useMedia.mjs.map +1 -1
- package/dist/esm/hooks/useMedia.native.js +4 -3
- package/dist/esm/hooks/useMedia.native.js.map +1 -1
- package/dist/esm/hooks/useProps.js +13 -10
- package/dist/esm/hooks/useProps.js.map +1 -1
- package/dist/esm/hooks/useProps.mjs +7 -6
- package/dist/esm/hooks/useProps.mjs.map +1 -1
- package/dist/esm/hooks/useProps.native.js +7 -6
- package/dist/esm/hooks/useProps.native.js.map +1 -1
- package/dist/esm/hooks/useThemeState.js +2 -2
- package/dist/esm/hooks/useThemeState.js.map +1 -1
- package/dist/esm/hooks/useThemeState.mjs +2 -2
- package/dist/esm/hooks/useThemeState.mjs.map +1 -1
- package/dist/esm/hooks/useThemeState.native.js +2 -2
- package/dist/esm/hooks/useThemeState.native.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.mjs +1 -0
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +1 -0
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/views/TamaguiProvider.js.map +1 -1
- package/dist/esm/views/TamaguiProvider.mjs.map +1 -1
- package/dist/esm/views/TamaguiProvider.native.js.map +1 -1
- package/package.json +12 -12
- package/src/contexts/ComponentContext.tsx +0 -5
- package/src/contexts/GroupContext.tsx +4 -0
- package/src/createComponent.tsx +251 -107
- package/src/helpers/createStyledContext.tsx +1 -1
- package/src/helpers/getSplitStyles.tsx +77 -56
- package/src/helpers/pseudoDescriptors.ts +15 -19
- package/src/helpers/subscribeToContextGroup.tsx +70 -34
- package/src/hooks/useComponentState.ts +2 -46
- package/src/hooks/useConfiguration.tsx +1 -9
- package/src/hooks/useMedia.tsx +4 -2
- package/src/hooks/useProps.tsx +15 -10
- package/src/hooks/useThemeState.ts +2 -2
- package/src/index.ts +1 -0
- package/src/interfaces/TamaguiComponentState.tsx +4 -3
- package/src/types.tsx +33 -36
- package/src/views/TamaguiProvider.tsx +1 -0
- package/types/contexts/ComponentContext.d.ts.map +1 -1
- package/types/contexts/GroupContext.d.ts +3 -0
- package/types/contexts/GroupContext.d.ts.map +1 -0
- package/types/createComponent.d.ts +1 -1
- package/types/createComponent.d.ts.map +1 -1
- package/types/helpers/getSplitStyles.d.ts +2 -2
- package/types/helpers/getSplitStyles.d.ts.map +1 -1
- package/types/helpers/pseudoDescriptors.d.ts +14 -13
- package/types/helpers/pseudoDescriptors.d.ts.map +1 -1
- package/types/helpers/subscribeToContextGroup.d.ts +7 -6
- package/types/helpers/subscribeToContextGroup.d.ts.map +1 -1
- package/types/hooks/useComponentState.d.ts +3 -3
- package/types/hooks/useComponentState.d.ts.map +1 -1
- package/types/hooks/useConfiguration.d.ts +1 -121
- package/types/hooks/useConfiguration.d.ts.map +1 -1
- package/types/hooks/useMedia.d.ts +2 -2
- package/types/hooks/useMedia.d.ts.map +1 -1
- package/types/hooks/useProps.d.ts.map +1 -1
- package/types/index.d.ts +1 -0
- package/types/index.d.ts.map +1 -1
- package/types/interfaces/TamaguiComponentState.d.ts +2 -2
- package/types/interfaces/TamaguiComponentState.d.ts.map +1 -1
- package/types/types.d.ts +22 -33
- package/types/types.d.ts.map +1 -1
- package/types/views/TamaguiProvider.d.ts.map +1 -1
package/src/createComponent.tsx
CHANGED
|
@@ -8,11 +8,13 @@ import {
|
|
|
8
8
|
useIsomorphicLayoutEffect,
|
|
9
9
|
} from '@tamagui/constants'
|
|
10
10
|
import { composeEventHandlers, validStyles } from '@tamagui/helpers'
|
|
11
|
-
import
|
|
11
|
+
import { isEqualShallow } from '@tamagui/is-equal-shallow'
|
|
12
|
+
import React, { type RefObject, useEffect, useId, useMemo } from 'react'
|
|
12
13
|
import { devConfig, onConfiguredOnce } from './config'
|
|
13
14
|
import { stackDefaultStyles } from './constants/constants'
|
|
14
15
|
import { isDevTools } from './constants/isDevTools'
|
|
15
16
|
import { ComponentContext } from './contexts/ComponentContext'
|
|
17
|
+
import { GroupContext } from './contexts/GroupContext'
|
|
16
18
|
import { didGetVariableValue, setDidGetVariableValue } from './createVariable'
|
|
17
19
|
import { defaultComponentStateMounted } from './defaultComponentState'
|
|
18
20
|
import { getShorthandValue } from './helpers/getShorthandValue'
|
|
@@ -31,19 +33,24 @@ import type { TamaguiComponentState } from './interfaces/TamaguiComponentState'
|
|
|
31
33
|
import type { WebOnlyPressEvents } from './interfaces/WebOnlyPressEvents'
|
|
32
34
|
import { hooks } from './setupHooks'
|
|
33
35
|
import type {
|
|
34
|
-
|
|
36
|
+
ComponentGroupEmitter,
|
|
37
|
+
ComponentGroupState,
|
|
35
38
|
DebugProp,
|
|
39
|
+
AllGroupContexts,
|
|
40
|
+
GroupStateListener,
|
|
36
41
|
LayoutEvent,
|
|
42
|
+
PseudoGroupState,
|
|
37
43
|
SizeTokens,
|
|
38
44
|
SpaceDirection,
|
|
39
|
-
SpaceValue,
|
|
40
45
|
SpacerProps,
|
|
41
46
|
SpacerStyleProps,
|
|
47
|
+
SpaceValue,
|
|
42
48
|
StackNonStyleProps,
|
|
43
49
|
StackProps,
|
|
44
50
|
StaticConfig,
|
|
45
51
|
StyleableOptions,
|
|
46
52
|
TamaguiComponent,
|
|
53
|
+
TamaguiComponentStateRef,
|
|
47
54
|
TamaguiElement,
|
|
48
55
|
TamaguiInternalConfig,
|
|
49
56
|
TextProps,
|
|
@@ -51,6 +58,7 @@ import type {
|
|
|
51
58
|
UseAnimationProps,
|
|
52
59
|
UseStyleEmitter,
|
|
53
60
|
UseThemeWithStateProps,
|
|
61
|
+
SingleGroupContext,
|
|
54
62
|
} from './types'
|
|
55
63
|
import { Slot } from './views/Slot'
|
|
56
64
|
import { getThemedChildren } from './views/Theme'
|
|
@@ -66,6 +74,16 @@ let startVisualizer: Function | undefined
|
|
|
66
74
|
type ComponentSetState = React.Dispatch<React.SetStateAction<TamaguiComponentState>>
|
|
67
75
|
|
|
68
76
|
export const componentSetStates = new Set<ComponentSetState>()
|
|
77
|
+
const avoidReRenderKeys = new Set([
|
|
78
|
+
'hover',
|
|
79
|
+
'press',
|
|
80
|
+
'pressIn',
|
|
81
|
+
'group',
|
|
82
|
+
'focus',
|
|
83
|
+
'focusWithin',
|
|
84
|
+
'media',
|
|
85
|
+
'group',
|
|
86
|
+
])
|
|
69
87
|
|
|
70
88
|
if (process.env.TAMAGUI_TARGET !== 'native' && typeof window !== 'undefined') {
|
|
71
89
|
const cancelTouches = () => {
|
|
@@ -92,7 +110,10 @@ if (process.env.TAMAGUI_TARGET !== 'native' && typeof window !== 'undefined') {
|
|
|
92
110
|
if (process.env.NODE_ENV === 'development') {
|
|
93
111
|
startVisualizer = () => {
|
|
94
112
|
const devVisualizerConfig = devConfig?.visualizer
|
|
95
|
-
|
|
113
|
+
|
|
114
|
+
if (devVisualizerConfig && !globalThis.__tamaguiDevVisualizer) {
|
|
115
|
+
globalThis.__tamaguiDevVisualizer = true
|
|
116
|
+
|
|
96
117
|
debugKeyListeners = new Set()
|
|
97
118
|
let tm
|
|
98
119
|
let isShowing = false
|
|
@@ -144,15 +165,21 @@ let BaseView: any
|
|
|
144
165
|
let hasSetupBaseViews = false
|
|
145
166
|
|
|
146
167
|
const lastInteractionWasKeyboard = { value: false }
|
|
147
|
-
if (isWeb &&
|
|
168
|
+
if (isWeb && typeof document !== 'undefined') {
|
|
148
169
|
document.addEventListener('keydown', () => {
|
|
149
|
-
lastInteractionWasKeyboard.value
|
|
170
|
+
if (!lastInteractionWasKeyboard.value) {
|
|
171
|
+
lastInteractionWasKeyboard.value = true
|
|
172
|
+
}
|
|
150
173
|
})
|
|
151
174
|
document.addEventListener('mousedown', () => {
|
|
152
|
-
lastInteractionWasKeyboard.value
|
|
175
|
+
if (lastInteractionWasKeyboard.value) {
|
|
176
|
+
lastInteractionWasKeyboard.value = false
|
|
177
|
+
}
|
|
153
178
|
})
|
|
154
179
|
document.addEventListener('mousemove', () => {
|
|
155
|
-
lastInteractionWasKeyboard.value
|
|
180
|
+
if (lastInteractionWasKeyboard.value) {
|
|
181
|
+
lastInteractionWasKeyboard.value = false
|
|
182
|
+
}
|
|
156
183
|
})
|
|
157
184
|
}
|
|
158
185
|
|
|
@@ -222,8 +249,6 @@ export function createComponent<
|
|
|
222
249
|
}
|
|
223
250
|
}
|
|
224
251
|
|
|
225
|
-
const componentContext = React.useContext(ComponentContext)
|
|
226
|
-
|
|
227
252
|
// set variants through context
|
|
228
253
|
// order is after default props but before props
|
|
229
254
|
let styledContextProps: Object | undefined
|
|
@@ -294,7 +319,7 @@ export function createComponent<
|
|
|
294
319
|
let overlay: HTMLSpanElement | null = null
|
|
295
320
|
|
|
296
321
|
const debugVisualizerHandler = (show = false) => {
|
|
297
|
-
const node =
|
|
322
|
+
const node = stateRef.current.host as HTMLElement
|
|
298
323
|
if (!node) return
|
|
299
324
|
|
|
300
325
|
if (show) {
|
|
@@ -338,21 +363,19 @@ export function createComponent<
|
|
|
338
363
|
}, [componentName])
|
|
339
364
|
}
|
|
340
365
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
*/
|
|
366
|
+
const componentContext = React.useContext(ComponentContext)
|
|
367
|
+
const groupContextParent = React.useContext(GroupContext)
|
|
344
368
|
const animationDriver = componentContext.animationDriver
|
|
345
369
|
const useAnimations = animationDriver?.useAnimations as UseAnimationHook | undefined
|
|
346
370
|
|
|
347
371
|
const componentState = useComponentState(
|
|
348
372
|
props,
|
|
349
|
-
|
|
373
|
+
animationDriver,
|
|
350
374
|
staticConfig,
|
|
351
375
|
config!
|
|
352
376
|
)
|
|
353
377
|
|
|
354
378
|
const {
|
|
355
|
-
curStateRef,
|
|
356
379
|
disabled,
|
|
357
380
|
groupName,
|
|
358
381
|
hasAnimationProp,
|
|
@@ -372,11 +395,64 @@ export function createComponent<
|
|
|
372
395
|
startedUnhydrated,
|
|
373
396
|
} = componentState
|
|
374
397
|
|
|
398
|
+
// create new context with groups, or else sublings will grab the same one
|
|
399
|
+
const allGroupContexts = useMemo((): AllGroupContexts | null => {
|
|
400
|
+
if (!groupName) {
|
|
401
|
+
return groupContextParent
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// TODO this shouldn't be in useMemo
|
|
405
|
+
stateRef.current.group?.listeners.clear()
|
|
406
|
+
const listeners = new Set<GroupStateListener>()
|
|
407
|
+
stateRef.current.group = {
|
|
408
|
+
listeners,
|
|
409
|
+
emit(state) {
|
|
410
|
+
listeners.forEach((l) => l(state))
|
|
411
|
+
},
|
|
412
|
+
subscribe(cb) {
|
|
413
|
+
listeners.add(cb)
|
|
414
|
+
if (listeners.size === 1) {
|
|
415
|
+
setStateShallow({ hasDynGroupChildren: true })
|
|
416
|
+
}
|
|
417
|
+
return () => {
|
|
418
|
+
listeners.delete(cb)
|
|
419
|
+
if (listeners.size === 0) {
|
|
420
|
+
setStateShallow({ hasDynGroupChildren: false })
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
},
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
return {
|
|
427
|
+
...groupContextParent,
|
|
428
|
+
[groupName]: {
|
|
429
|
+
state: {
|
|
430
|
+
pseudo: defaultComponentStateMounted,
|
|
431
|
+
},
|
|
432
|
+
subscribe: (listener) => {
|
|
433
|
+
const dispose = stateRef.current.group?.subscribe(listener)
|
|
434
|
+
return () => {
|
|
435
|
+
dispose?.()
|
|
436
|
+
}
|
|
437
|
+
},
|
|
438
|
+
},
|
|
439
|
+
}
|
|
440
|
+
}, [stateRef, groupName, groupContextParent])
|
|
441
|
+
|
|
375
442
|
// if our animation driver supports noReRender, we'll replace this below with
|
|
376
443
|
// a version that essentially uses an internall emitter rather than setting state
|
|
377
444
|
// but still stores the current state and applies if it it needs to during render
|
|
378
445
|
let setStateShallow = componentState.setStateShallow
|
|
379
446
|
|
|
447
|
+
const pendingState = stateRef.current.nextComponentState
|
|
448
|
+
if (pendingState) {
|
|
449
|
+
stateRef.current.nextComponentState = undefined
|
|
450
|
+
componentState.setState((prev) => ({
|
|
451
|
+
...prev,
|
|
452
|
+
...pendingState,
|
|
453
|
+
}))
|
|
454
|
+
}
|
|
455
|
+
|
|
380
456
|
if (process.env.NODE_ENV === 'development' && time) time`use-state`
|
|
381
457
|
|
|
382
458
|
const hasTextAncestor = !!(isWeb && isText ? componentContext.inText : false)
|
|
@@ -412,13 +488,13 @@ export function createComponent<
|
|
|
412
488
|
if (process.env.NODE_ENV === 'development' && time) time`theme-props`
|
|
413
489
|
|
|
414
490
|
if (props.themeShallow) {
|
|
415
|
-
|
|
491
|
+
stateRef.current.themeShallow = true
|
|
416
492
|
}
|
|
417
493
|
|
|
418
494
|
const themeStateProps: UseThemeWithStateProps = {
|
|
419
495
|
componentName,
|
|
420
496
|
disable: disableTheme,
|
|
421
|
-
shallow:
|
|
497
|
+
shallow: stateRef.current.themeShallow,
|
|
422
498
|
debug: debugProp,
|
|
423
499
|
}
|
|
424
500
|
|
|
@@ -430,7 +506,7 @@ export function createComponent<
|
|
|
430
506
|
if ('theme' in props) {
|
|
431
507
|
themeStateProps.name = props.theme
|
|
432
508
|
}
|
|
433
|
-
if (typeof
|
|
509
|
+
if (typeof stateRef.current.isListeningToTheme === 'boolean') {
|
|
434
510
|
themeStateProps.needsUpdate = () => !!stateRef.current.isListeningToTheme
|
|
435
511
|
}
|
|
436
512
|
// on native we optimize theme changes if fastSchemeChange is enabled, otherwise deopt
|
|
@@ -482,7 +558,11 @@ export function createComponent<
|
|
|
482
558
|
log('props in:', propsIn)
|
|
483
559
|
log('final props:', props)
|
|
484
560
|
log({ state, staticConfig, elementType, themeStateProps })
|
|
485
|
-
log({
|
|
561
|
+
log({
|
|
562
|
+
contextProps: styledContextProps,
|
|
563
|
+
overriddenContextProps,
|
|
564
|
+
componentContext,
|
|
565
|
+
})
|
|
486
566
|
log({ presence, isAnimated, isHOC, hasAnimationProp, useAnimations })
|
|
487
567
|
console.groupEnd()
|
|
488
568
|
}
|
|
@@ -535,26 +615,87 @@ export function createComponent<
|
|
|
535
615
|
styleProps,
|
|
536
616
|
null,
|
|
537
617
|
componentContext,
|
|
618
|
+
allGroupContexts,
|
|
538
619
|
elementType,
|
|
539
620
|
startedUnhydrated,
|
|
540
621
|
debugProp
|
|
541
622
|
)
|
|
542
623
|
|
|
624
|
+
const groupContext = groupName ? allGroupContexts?.[groupName] || null : null
|
|
625
|
+
|
|
626
|
+
// one tiny mutation 🙏 get width/height optimistically from raw values if possible
|
|
627
|
+
// if set hardcoded it avoids extra renders
|
|
628
|
+
if (groupContext) {
|
|
629
|
+
const groupState = groupContext?.state
|
|
630
|
+
if (groupState && groupState.layout === undefined) {
|
|
631
|
+
if (splitStyles.style?.width || splitStyles.style?.height) {
|
|
632
|
+
groupState.layout = {
|
|
633
|
+
width: fromPx(splitStyles.style.width),
|
|
634
|
+
height: fromPx(splitStyles.style.height),
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
543
640
|
// avoids re-rendering if animation driver supports it
|
|
544
641
|
// TODO believe we need to set some sort of "pendingState" in case it re-renders
|
|
545
|
-
if (hasAnimationProp && animationDriver?.avoidReRenders) {
|
|
642
|
+
if ((hasAnimationProp || groupName) && animationDriver?.avoidReRenders) {
|
|
546
643
|
const styleListener = stateRef.current.useStyleListener
|
|
547
644
|
const ogSetStateShallow = setStateShallow
|
|
548
|
-
|
|
645
|
+
|
|
646
|
+
stateRef.current.setStateShallow = (nextOrGetNext) => {
|
|
647
|
+
const prev = stateRef.current.nextComponentState || state
|
|
648
|
+
const next =
|
|
649
|
+
typeof nextOrGetNext === 'function' ? nextOrGetNext(prev) : nextOrGetNext
|
|
650
|
+
|
|
651
|
+
if (next === prev || isEqualShallow(prev, next)) {
|
|
652
|
+
return
|
|
653
|
+
}
|
|
654
|
+
|
|
549
655
|
// one thing we have to handle here and where it gets a bit more complex is group styles
|
|
550
|
-
// but i think we can just emit to the group too?
|
|
551
|
-
const avoidReRenderKeys = new Set(['hover', 'press', 'pressIn'])
|
|
552
656
|
const canAvoidReRender = Object.keys(next).every((key) =>
|
|
553
657
|
avoidReRenderKeys.has(key)
|
|
554
658
|
)
|
|
555
|
-
|
|
556
|
-
|
|
659
|
+
|
|
660
|
+
if (canAvoidReRender) {
|
|
661
|
+
const updatedState = {
|
|
662
|
+
...prev,
|
|
663
|
+
...next,
|
|
664
|
+
}
|
|
557
665
|
stateRef.current.nextComponentState = updatedState
|
|
666
|
+
|
|
667
|
+
if (
|
|
668
|
+
process.env.NODE_ENV === 'development' &&
|
|
669
|
+
debugProp &&
|
|
670
|
+
debugProp !== 'profile'
|
|
671
|
+
) {
|
|
672
|
+
console.groupCollapsed(`[⚡️] avoid setState`, next, { updatedState, props })
|
|
673
|
+
console.info(stateRef.current.host)
|
|
674
|
+
console.groupEnd()
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
const {
|
|
678
|
+
group,
|
|
679
|
+
hasDynGroupChildren,
|
|
680
|
+
unmounted,
|
|
681
|
+
animation,
|
|
682
|
+
...childrenGroupState
|
|
683
|
+
} = updatedState
|
|
684
|
+
|
|
685
|
+
// update before getting styles
|
|
686
|
+
if (groupContext) {
|
|
687
|
+
notifyGroupSubscribers(
|
|
688
|
+
groupContext,
|
|
689
|
+
stateRef.current.group || null,
|
|
690
|
+
childrenGroupState
|
|
691
|
+
)
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// we just emit and return for group without animation ^
|
|
695
|
+
if (!hasAnimationProp || !styleListener) {
|
|
696
|
+
return
|
|
697
|
+
}
|
|
698
|
+
|
|
558
699
|
const nextStyles = getSplitStyles(
|
|
559
700
|
props,
|
|
560
701
|
staticConfig,
|
|
@@ -564,26 +705,42 @@ export function createComponent<
|
|
|
564
705
|
styleProps,
|
|
565
706
|
null,
|
|
566
707
|
componentContext,
|
|
708
|
+
allGroupContexts,
|
|
567
709
|
elementType,
|
|
568
710
|
startedUnhydrated,
|
|
569
711
|
debugProp
|
|
570
712
|
)
|
|
713
|
+
|
|
571
714
|
styleListener(nextStyles.style as any)
|
|
572
715
|
} else {
|
|
716
|
+
if (
|
|
717
|
+
process.env.NODE_ENV === 'development' &&
|
|
718
|
+
debugProp &&
|
|
719
|
+
debugProp !== 'profile'
|
|
720
|
+
) {
|
|
721
|
+
console.info(`[🐌] re-render`, { canAvoidReRender, next })
|
|
722
|
+
}
|
|
573
723
|
ogSetStateShallow(next)
|
|
574
724
|
}
|
|
575
725
|
}
|
|
726
|
+
|
|
727
|
+
// needs to capture latest props (it's called from memoized `events`)
|
|
728
|
+
setStateShallow = (state) => {
|
|
729
|
+
stateRef.current.setStateShallow?.(state)
|
|
730
|
+
}
|
|
576
731
|
}
|
|
577
732
|
|
|
578
733
|
if (process.env.NODE_ENV === 'development' && time) time`split-styles`
|
|
579
734
|
|
|
580
735
|
// hide strategy will set this opacity = 0 until measured
|
|
581
|
-
if (props.group && props.untilMeasured === 'hide' && !
|
|
736
|
+
if (props.group && props.untilMeasured === 'hide' && !stateRef.current.hasMeasured) {
|
|
582
737
|
splitStyles.style ||= {}
|
|
583
738
|
splitStyles.style.opacity = 0
|
|
584
739
|
}
|
|
585
740
|
|
|
586
|
-
|
|
741
|
+
if (splitStyles.dynamicThemeAccess != null) {
|
|
742
|
+
stateRef.current.isListeningToTheme = splitStyles.dynamicThemeAccess
|
|
743
|
+
}
|
|
587
744
|
|
|
588
745
|
// only listen for changes if we are using raw theme values or media space, or dynamic media (native)
|
|
589
746
|
// array = space media breakpoints
|
|
@@ -710,16 +867,16 @@ export function createComponent<
|
|
|
710
867
|
|
|
711
868
|
if (process.env.NODE_ENV === 'development' && time) time`destructure`
|
|
712
869
|
|
|
713
|
-
if (
|
|
870
|
+
if (groupContext) {
|
|
714
871
|
nonTamaguiProps.onLayout = composeEventHandlers(
|
|
715
872
|
nonTamaguiProps.onLayout,
|
|
716
873
|
(e: LayoutEvent) => {
|
|
874
|
+
// one off update here
|
|
717
875
|
const layout = e.nativeEvent.layout
|
|
718
|
-
|
|
719
|
-
stateRef.current.group
|
|
876
|
+
groupContext.state.layout = layout
|
|
877
|
+
stateRef.current.group?.emit({
|
|
720
878
|
layout,
|
|
721
879
|
})
|
|
722
|
-
|
|
723
880
|
// force re-render if measure strategy is hide
|
|
724
881
|
if (!stateRef.current.hasMeasured && props.untilMeasured === 'hide') {
|
|
725
882
|
setState((prev) => ({ ...prev }))
|
|
@@ -735,11 +892,11 @@ export function createComponent<
|
|
|
735
892
|
elementType,
|
|
736
893
|
nonTamaguiProps,
|
|
737
894
|
stateRef,
|
|
738
|
-
|
|
895
|
+
stateRef.current.willHydrate
|
|
739
896
|
) || nonTamaguiProps
|
|
740
897
|
|
|
741
|
-
if (!
|
|
742
|
-
|
|
898
|
+
if (!stateRef.current.composedRef) {
|
|
899
|
+
stateRef.current.composedRef = composeRefs<TamaguiElement>(
|
|
743
900
|
(x) => (stateRef.current.host = x as TamaguiElement),
|
|
744
901
|
forwardedRef,
|
|
745
902
|
setElementProps,
|
|
@@ -747,7 +904,7 @@ export function createComponent<
|
|
|
747
904
|
)
|
|
748
905
|
}
|
|
749
906
|
|
|
750
|
-
viewProps.ref =
|
|
907
|
+
viewProps.ref = stateRef.current.composedRef
|
|
751
908
|
|
|
752
909
|
if (process.env.NODE_ENV === 'development') {
|
|
753
910
|
if (!isReactNative && !isText && isWeb && !isHOC) {
|
|
@@ -822,44 +979,41 @@ export function createComponent<
|
|
|
822
979
|
}
|
|
823
980
|
|
|
824
981
|
// Only subscribe to context group if not disabled
|
|
825
|
-
const dispose =
|
|
826
|
-
!disabled && (pseudoGroups || mediaGroups)
|
|
827
|
-
? subscribeToContextGroup({
|
|
828
|
-
componentContext,
|
|
829
|
-
setStateShallow,
|
|
830
|
-
state,
|
|
831
|
-
mediaGroups,
|
|
832
|
-
pseudoGroups,
|
|
833
|
-
})
|
|
834
|
-
: null
|
|
835
982
|
|
|
836
983
|
return () => {
|
|
837
|
-
dispose?.()
|
|
838
984
|
componentSetStates.delete(setState)
|
|
839
985
|
}
|
|
986
|
+
}, [state.unmounted, disabled])
|
|
987
|
+
|
|
988
|
+
useIsomorphicLayoutEffect(() => {
|
|
989
|
+
if (disabled) return
|
|
990
|
+
if (!pseudoGroups && !mediaGroups) return
|
|
991
|
+
if (!allGroupContexts) return
|
|
992
|
+
return subscribeToContextGroup({
|
|
993
|
+
groupContext: allGroupContexts,
|
|
994
|
+
setStateShallow,
|
|
995
|
+
mediaGroups,
|
|
996
|
+
pseudoGroups,
|
|
997
|
+
})
|
|
840
998
|
}, [
|
|
841
|
-
|
|
999
|
+
allGroupContexts,
|
|
842
1000
|
disabled,
|
|
843
1001
|
pseudoGroups ? Object.keys([...pseudoGroups]).join('') : 0,
|
|
844
1002
|
mediaGroups ? Object.keys([...mediaGroups]).join('') : 0,
|
|
845
1003
|
])
|
|
846
1004
|
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
layout: curStateRef.group?.layout,
|
|
1005
|
+
if (hasAnimationProp && animationDriver?.avoidReRenders) {
|
|
1006
|
+
useEffect(() => {
|
|
1007
|
+
// always clear after render
|
|
1008
|
+
stateRef.current.nextComponentState = undefined
|
|
852
1009
|
})
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
groupContextState[groupName] = next
|
|
861
|
-
}
|
|
862
|
-
}, [groupName, state])
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
const groupEmitter = stateRef.current.group
|
|
1013
|
+
useIsomorphicLayoutEffect(() => {
|
|
1014
|
+
if (!groupContext || !groupEmitter) return
|
|
1015
|
+
notifyGroupSubscribers(groupContext, groupEmitter, state)
|
|
1016
|
+
}, [groupContext, groupEmitter, state])
|
|
863
1017
|
|
|
864
1018
|
// if its a group its gotta listen for pseudos to emit them to children
|
|
865
1019
|
|
|
@@ -889,6 +1043,7 @@ export function createComponent<
|
|
|
889
1043
|
onClick ||
|
|
890
1044
|
pseudos?.focusVisibleStyle
|
|
891
1045
|
)
|
|
1046
|
+
|
|
892
1047
|
const runtimeHoverStyle = !disabled && noClass && pseudos?.hoverStyle
|
|
893
1048
|
const needsHoverState = Boolean(hasDynamicGroupChildren || runtimeHoverStyle)
|
|
894
1049
|
const attachHover =
|
|
@@ -958,10 +1113,8 @@ export function createComponent<
|
|
|
958
1113
|
next.hover = false
|
|
959
1114
|
}
|
|
960
1115
|
if (needsPressState) {
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
next.pressIn = false
|
|
964
|
-
}
|
|
1116
|
+
next.press = false
|
|
1117
|
+
next.pressIn = false
|
|
965
1118
|
}
|
|
966
1119
|
setStateShallow(next)
|
|
967
1120
|
onHoverOut?.(e)
|
|
@@ -1004,22 +1157,20 @@ export function createComponent<
|
|
|
1004
1157
|
}),
|
|
1005
1158
|
...(attachFocus && {
|
|
1006
1159
|
onFocus: (e) => {
|
|
1160
|
+
const next: Partial<typeof state> = {}
|
|
1007
1161
|
if (componentContext.setParentFocusState) {
|
|
1008
|
-
|
|
1162
|
+
next.focusWithin = true
|
|
1009
1163
|
}
|
|
1010
1164
|
if (pseudos?.focusVisibleStyle) {
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
}, 0)
|
|
1165
|
+
if (lastInteractionWasKeyboard.value) {
|
|
1166
|
+
next.focusVisible = true
|
|
1167
|
+
} else {
|
|
1168
|
+
next.focus = true
|
|
1169
|
+
}
|
|
1017
1170
|
} else {
|
|
1018
|
-
|
|
1019
|
-
focus: true,
|
|
1020
|
-
focusVisible: false,
|
|
1021
|
-
})
|
|
1171
|
+
next.focus = true
|
|
1022
1172
|
}
|
|
1173
|
+
setStateShallow(next)
|
|
1023
1174
|
onFocus?.(e)
|
|
1024
1175
|
},
|
|
1025
1176
|
onBlur: (e) => {
|
|
@@ -1029,6 +1180,7 @@ export function createComponent<
|
|
|
1029
1180
|
setStateShallow({
|
|
1030
1181
|
focus: false,
|
|
1031
1182
|
focusVisible: false,
|
|
1183
|
+
focusWithin: false,
|
|
1032
1184
|
})
|
|
1033
1185
|
onBlur?.(e)
|
|
1034
1186
|
},
|
|
@@ -1132,38 +1284,10 @@ export function createComponent<
|
|
|
1132
1284
|
|
|
1133
1285
|
if (process.env.NODE_ENV === 'development' && time) time`create-element`
|
|
1134
1286
|
|
|
1135
|
-
|
|
1136
|
-
const groupState = curStateRef.group
|
|
1137
|
-
const subGroupContext = React.useMemo(() => {
|
|
1138
|
-
if (!groupState || !groupName) return
|
|
1139
|
-
groupState.listeners.clear()
|
|
1140
|
-
// change reference so context value updates
|
|
1141
|
-
|
|
1142
|
-
return {
|
|
1143
|
-
...componentContext.groups,
|
|
1144
|
-
// change reference so as we mutate it doesn't affect siblings etc
|
|
1145
|
-
state: {
|
|
1146
|
-
...componentContext.groups.state,
|
|
1147
|
-
[groupName]: {
|
|
1148
|
-
pseudo: defaultComponentStateMounted,
|
|
1149
|
-
// capture just initial width and height if they exist
|
|
1150
|
-
// will have top, left, width, height (not x, y)
|
|
1151
|
-
layout: {
|
|
1152
|
-
width: fromPx(splitStyles.style?.width),
|
|
1153
|
-
height: fromPx(splitStyles.style?.height),
|
|
1154
|
-
},
|
|
1155
|
-
},
|
|
1156
|
-
},
|
|
1157
|
-
emit: groupState.emit,
|
|
1158
|
-
subscribe: groupState.subscribe,
|
|
1159
|
-
} satisfies ComponentContextI['groups']
|
|
1160
|
-
}, [groupName])
|
|
1161
|
-
|
|
1162
|
-
if ('group' in props || propsIn.focusWithinStyle) {
|
|
1287
|
+
if ('focusWithinStyle' in propsIn) {
|
|
1163
1288
|
content = (
|
|
1164
1289
|
<ComponentContext.Provider
|
|
1165
1290
|
{...componentContext}
|
|
1166
|
-
groups={subGroupContext}
|
|
1167
1291
|
setParentFocusState={setStateShallow}
|
|
1168
1292
|
>
|
|
1169
1293
|
{content}
|
|
@@ -1171,6 +1295,12 @@ export function createComponent<
|
|
|
1171
1295
|
)
|
|
1172
1296
|
}
|
|
1173
1297
|
|
|
1298
|
+
if ('group' in props) {
|
|
1299
|
+
content = (
|
|
1300
|
+
<GroupContext.Provider value={allGroupContexts}>{content}</GroupContext.Provider>
|
|
1301
|
+
)
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1174
1304
|
if (process.env.NODE_ENV === 'development' && time) time`group-context`
|
|
1175
1305
|
|
|
1176
1306
|
content = disableTheme
|
|
@@ -1254,6 +1384,7 @@ export function createComponent<
|
|
|
1254
1384
|
log({
|
|
1255
1385
|
propsIn,
|
|
1256
1386
|
props,
|
|
1387
|
+
attachPress,
|
|
1257
1388
|
animationStyles,
|
|
1258
1389
|
classNames,
|
|
1259
1390
|
content,
|
|
@@ -1307,6 +1438,19 @@ export function createComponent<
|
|
|
1307
1438
|
return content
|
|
1308
1439
|
})
|
|
1309
1440
|
|
|
1441
|
+
function notifyGroupSubscribers(
|
|
1442
|
+
groupContext: SingleGroupContext | null,
|
|
1443
|
+
groupEmitter: ComponentGroupEmitter | null,
|
|
1444
|
+
pseudo: PseudoGroupState
|
|
1445
|
+
) {
|
|
1446
|
+
if (!groupContext || !groupEmitter) {
|
|
1447
|
+
return
|
|
1448
|
+
}
|
|
1449
|
+
const nextState = { ...groupContext.state, pseudo }
|
|
1450
|
+
groupEmitter.emit(nextState)
|
|
1451
|
+
groupContext.state = nextState
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1310
1454
|
// let hasLogged = false
|
|
1311
1455
|
|
|
1312
1456
|
if (staticConfig.componentName) {
|