@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.
Files changed (184) hide show
  1. package/dist/cjs/contexts/ComponentContext.cjs +1 -6
  2. package/dist/cjs/contexts/ComponentContext.js +1 -6
  3. package/dist/cjs/contexts/ComponentContext.js.map +1 -1
  4. package/dist/cjs/contexts/ComponentContext.native.js +1 -6
  5. package/dist/cjs/contexts/ComponentContext.native.js.map +2 -2
  6. package/dist/cjs/contexts/GroupContext.cjs +27 -0
  7. package/dist/cjs/contexts/GroupContext.js +22 -0
  8. package/dist/cjs/contexts/GroupContext.js.map +6 -0
  9. package/dist/cjs/contexts/GroupContext.native.js +26 -0
  10. package/dist/cjs/contexts/GroupContext.native.js.map +6 -0
  11. package/dist/cjs/createComponent.cjs +131 -90
  12. package/dist/cjs/createComponent.js +139 -94
  13. package/dist/cjs/createComponent.js.map +2 -2
  14. package/dist/cjs/createComponent.native.js +156 -106
  15. package/dist/cjs/createComponent.native.js.map +2 -2
  16. package/dist/cjs/helpers/createStyledContext.js.map +1 -1
  17. package/dist/cjs/helpers/createStyledContext.native.js.map +1 -1
  18. package/dist/cjs/helpers/getSplitStyles.cjs +68 -49
  19. package/dist/cjs/helpers/getSplitStyles.js +64 -55
  20. package/dist/cjs/helpers/getSplitStyles.js.map +2 -2
  21. package/dist/cjs/helpers/getSplitStyles.native.js +82 -63
  22. package/dist/cjs/helpers/getSplitStyles.native.js.map +2 -2
  23. package/dist/cjs/helpers/pseudoDescriptors.cjs +12 -12
  24. package/dist/cjs/helpers/pseudoDescriptors.js +12 -12
  25. package/dist/cjs/helpers/pseudoDescriptors.js.map +1 -1
  26. package/dist/cjs/helpers/pseudoDescriptors.native.js +12 -12
  27. package/dist/cjs/helpers/pseudoDescriptors.native.js.map +1 -1
  28. package/dist/cjs/helpers/subscribeToContextGroup.cjs +48 -31
  29. package/dist/cjs/helpers/subscribeToContextGroup.js +36 -20
  30. package/dist/cjs/helpers/subscribeToContextGroup.js.map +1 -1
  31. package/dist/cjs/helpers/subscribeToContextGroup.native.js +48 -20
  32. package/dist/cjs/helpers/subscribeToContextGroup.native.js.map +2 -2
  33. package/dist/cjs/hooks/useComponentState.cjs +2 -40
  34. package/dist/cjs/hooks/useComponentState.js +2 -30
  35. package/dist/cjs/hooks/useComponentState.js.map +2 -2
  36. package/dist/cjs/hooks/useComponentState.native.js +3 -43
  37. package/dist/cjs/hooks/useComponentState.native.js.map +2 -2
  38. package/dist/cjs/hooks/useConfiguration.cjs +1 -17
  39. package/dist/cjs/hooks/useConfiguration.js +2 -9
  40. package/dist/cjs/hooks/useConfiguration.js.map +1 -1
  41. package/dist/cjs/hooks/useConfiguration.native.js +2 -7
  42. package/dist/cjs/hooks/useConfiguration.native.js.map +2 -2
  43. package/dist/cjs/hooks/useMedia.cjs +4 -3
  44. package/dist/cjs/hooks/useMedia.js +3 -3
  45. package/dist/cjs/hooks/useMedia.js.map +1 -1
  46. package/dist/cjs/hooks/useMedia.native.js +3 -3
  47. package/dist/cjs/hooks/useMedia.native.js.map +2 -2
  48. package/dist/cjs/hooks/useProps.cjs +7 -6
  49. package/dist/cjs/hooks/useProps.js +13 -11
  50. package/dist/cjs/hooks/useProps.js.map +1 -1
  51. package/dist/cjs/hooks/useProps.native.js +11 -10
  52. package/dist/cjs/hooks/useProps.native.js.map +2 -2
  53. package/dist/cjs/hooks/useThemeState.cjs +2 -2
  54. package/dist/cjs/hooks/useThemeState.js +2 -2
  55. package/dist/cjs/hooks/useThemeState.js.map +1 -1
  56. package/dist/cjs/hooks/useThemeState.native.js +2 -2
  57. package/dist/cjs/hooks/useThemeState.native.js.map +1 -1
  58. package/dist/cjs/index.cjs +1 -0
  59. package/dist/cjs/index.js +1 -0
  60. package/dist/cjs/index.js.map +1 -1
  61. package/dist/cjs/index.native.js +2 -0
  62. package/dist/cjs/index.native.js.map +1 -1
  63. package/dist/cjs/views/TamaguiProvider.js.map +1 -1
  64. package/dist/cjs/views/TamaguiProvider.native.js.map +1 -1
  65. package/dist/esm/contexts/ComponentContext.js +1 -6
  66. package/dist/esm/contexts/ComponentContext.js.map +1 -1
  67. package/dist/esm/contexts/ComponentContext.mjs +1 -6
  68. package/dist/esm/contexts/ComponentContext.mjs.map +1 -1
  69. package/dist/esm/contexts/ComponentContext.native.js +1 -6
  70. package/dist/esm/contexts/ComponentContext.native.js.map +1 -1
  71. package/dist/esm/contexts/GroupContext.js +6 -0
  72. package/dist/esm/contexts/GroupContext.js.map +6 -0
  73. package/dist/esm/contexts/GroupContext.mjs +4 -0
  74. package/dist/esm/contexts/GroupContext.mjs.map +1 -0
  75. package/dist/esm/contexts/GroupContext.native.js +4 -0
  76. package/dist/esm/contexts/GroupContext.native.js.map +1 -0
  77. package/dist/esm/createComponent.js +141 -94
  78. package/dist/esm/createComponent.js.map +2 -2
  79. package/dist/esm/createComponent.mjs +132 -91
  80. package/dist/esm/createComponent.mjs.map +1 -1
  81. package/dist/esm/createComponent.native.js +152 -102
  82. package/dist/esm/createComponent.native.js.map +1 -1
  83. package/dist/esm/helpers/createStyledContext.js.map +1 -1
  84. package/dist/esm/helpers/createStyledContext.mjs.map +1 -1
  85. package/dist/esm/helpers/createStyledContext.native.js.map +1 -1
  86. package/dist/esm/helpers/getSplitStyles.js +68 -56
  87. package/dist/esm/helpers/getSplitStyles.js.map +2 -2
  88. package/dist/esm/helpers/getSplitStyles.mjs +68 -49
  89. package/dist/esm/helpers/getSplitStyles.mjs.map +1 -1
  90. package/dist/esm/helpers/getSplitStyles.native.js +72 -53
  91. package/dist/esm/helpers/getSplitStyles.native.js.map +1 -1
  92. package/dist/esm/helpers/pseudoDescriptors.js +12 -12
  93. package/dist/esm/helpers/pseudoDescriptors.js.map +1 -1
  94. package/dist/esm/helpers/pseudoDescriptors.mjs +12 -12
  95. package/dist/esm/helpers/pseudoDescriptors.mjs.map +1 -1
  96. package/dist/esm/helpers/pseudoDescriptors.native.js +12 -12
  97. package/dist/esm/helpers/pseudoDescriptors.native.js.map +1 -1
  98. package/dist/esm/helpers/subscribeToContextGroup.js +36 -20
  99. package/dist/esm/helpers/subscribeToContextGroup.js.map +1 -1
  100. package/dist/esm/helpers/subscribeToContextGroup.mjs +47 -30
  101. package/dist/esm/helpers/subscribeToContextGroup.mjs.map +1 -1
  102. package/dist/esm/helpers/subscribeToContextGroup.native.js +64 -36
  103. package/dist/esm/helpers/subscribeToContextGroup.native.js.map +1 -1
  104. package/dist/esm/hooks/useComponentState.js +2 -30
  105. package/dist/esm/hooks/useComponentState.js.map +2 -2
  106. package/dist/esm/hooks/useComponentState.mjs +2 -40
  107. package/dist/esm/hooks/useComponentState.mjs.map +1 -1
  108. package/dist/esm/hooks/useComponentState.native.js +3 -46
  109. package/dist/esm/hooks/useComponentState.native.js.map +1 -1
  110. package/dist/esm/hooks/useConfiguration.js +1 -9
  111. package/dist/esm/hooks/useConfiguration.js.map +1 -1
  112. package/dist/esm/hooks/useConfiguration.mjs +1 -17
  113. package/dist/esm/hooks/useConfiguration.mjs.map +1 -1
  114. package/dist/esm/hooks/useConfiguration.native.js +1 -15
  115. package/dist/esm/hooks/useConfiguration.native.js.map +1 -1
  116. package/dist/esm/hooks/useMedia.js +3 -3
  117. package/dist/esm/hooks/useMedia.js.map +1 -1
  118. package/dist/esm/hooks/useMedia.mjs +4 -3
  119. package/dist/esm/hooks/useMedia.mjs.map +1 -1
  120. package/dist/esm/hooks/useMedia.native.js +4 -3
  121. package/dist/esm/hooks/useMedia.native.js.map +1 -1
  122. package/dist/esm/hooks/useProps.js +13 -10
  123. package/dist/esm/hooks/useProps.js.map +1 -1
  124. package/dist/esm/hooks/useProps.mjs +7 -6
  125. package/dist/esm/hooks/useProps.mjs.map +1 -1
  126. package/dist/esm/hooks/useProps.native.js +7 -6
  127. package/dist/esm/hooks/useProps.native.js.map +1 -1
  128. package/dist/esm/hooks/useThemeState.js +2 -2
  129. package/dist/esm/hooks/useThemeState.js.map +1 -1
  130. package/dist/esm/hooks/useThemeState.mjs +2 -2
  131. package/dist/esm/hooks/useThemeState.mjs.map +1 -1
  132. package/dist/esm/hooks/useThemeState.native.js +2 -2
  133. package/dist/esm/hooks/useThemeState.native.js.map +1 -1
  134. package/dist/esm/index.js +1 -0
  135. package/dist/esm/index.js.map +1 -1
  136. package/dist/esm/index.mjs +1 -0
  137. package/dist/esm/index.mjs.map +1 -1
  138. package/dist/esm/index.native.js +1 -0
  139. package/dist/esm/index.native.js.map +1 -1
  140. package/dist/esm/views/TamaguiProvider.js.map +1 -1
  141. package/dist/esm/views/TamaguiProvider.mjs.map +1 -1
  142. package/dist/esm/views/TamaguiProvider.native.js.map +1 -1
  143. package/package.json +12 -12
  144. package/src/contexts/ComponentContext.tsx +0 -5
  145. package/src/contexts/GroupContext.tsx +4 -0
  146. package/src/createComponent.tsx +251 -107
  147. package/src/helpers/createStyledContext.tsx +1 -1
  148. package/src/helpers/getSplitStyles.tsx +77 -56
  149. package/src/helpers/pseudoDescriptors.ts +15 -19
  150. package/src/helpers/subscribeToContextGroup.tsx +70 -34
  151. package/src/hooks/useComponentState.ts +2 -46
  152. package/src/hooks/useConfiguration.tsx +1 -9
  153. package/src/hooks/useMedia.tsx +4 -2
  154. package/src/hooks/useProps.tsx +15 -10
  155. package/src/hooks/useThemeState.ts +2 -2
  156. package/src/index.ts +1 -0
  157. package/src/interfaces/TamaguiComponentState.tsx +4 -3
  158. package/src/types.tsx +33 -36
  159. package/src/views/TamaguiProvider.tsx +1 -0
  160. package/types/contexts/ComponentContext.d.ts.map +1 -1
  161. package/types/contexts/GroupContext.d.ts +3 -0
  162. package/types/contexts/GroupContext.d.ts.map +1 -0
  163. package/types/createComponent.d.ts +1 -1
  164. package/types/createComponent.d.ts.map +1 -1
  165. package/types/helpers/getSplitStyles.d.ts +2 -2
  166. package/types/helpers/getSplitStyles.d.ts.map +1 -1
  167. package/types/helpers/pseudoDescriptors.d.ts +14 -13
  168. package/types/helpers/pseudoDescriptors.d.ts.map +1 -1
  169. package/types/helpers/subscribeToContextGroup.d.ts +7 -6
  170. package/types/helpers/subscribeToContextGroup.d.ts.map +1 -1
  171. package/types/hooks/useComponentState.d.ts +3 -3
  172. package/types/hooks/useComponentState.d.ts.map +1 -1
  173. package/types/hooks/useConfiguration.d.ts +1 -121
  174. package/types/hooks/useConfiguration.d.ts.map +1 -1
  175. package/types/hooks/useMedia.d.ts +2 -2
  176. package/types/hooks/useMedia.d.ts.map +1 -1
  177. package/types/hooks/useProps.d.ts.map +1 -1
  178. package/types/index.d.ts +1 -0
  179. package/types/index.d.ts.map +1 -1
  180. package/types/interfaces/TamaguiComponentState.d.ts +2 -2
  181. package/types/interfaces/TamaguiComponentState.d.ts.map +1 -1
  182. package/types/types.d.ts +22 -33
  183. package/types/types.d.ts.map +1 -1
  184. package/types/views/TamaguiProvider.d.ts.map +1 -1
@@ -41,6 +41,7 @@ import type {
41
41
  DebugProp,
42
42
  GetStyleResult,
43
43
  GetStyleState,
44
+ AllGroupContexts,
44
45
  IsMediaType,
45
46
  MediaQueryKey,
46
47
  PseudoPropKeys,
@@ -65,7 +66,11 @@ import { isActiveTheme } from './isActiveTheme'
65
66
  import { log } from './log'
66
67
  import { normalizeValueWithProperty } from './normalizeValueWithProperty'
67
68
  import { propMapper } from './propMapper'
68
- import { pseudoDescriptors, pseudoPriorities } from './pseudoDescriptors'
69
+ import {
70
+ type PseudoDescriptorKey,
71
+ pseudoDescriptors,
72
+ pseudoPriorities,
73
+ } from './pseudoDescriptors'
69
74
  import { skipProps } from './skipProps'
70
75
  import { sortString } from './sortString'
71
76
  import { transformsToString } from './transformsToString'
@@ -87,6 +92,7 @@ type StyleSplitter = (
87
92
  styleProps: SplitStyleProps,
88
93
  parentSplitStyles?: GetStyleResult | null,
89
94
  context?: ComponentContextI,
95
+ groupContext?: AllGroupContexts | null,
90
96
  // web-only
91
97
  elementType?: string,
92
98
  startedUnhydrated?: boolean,
@@ -133,6 +139,7 @@ export const getSplitStyles: StyleSplitter = (
133
139
  styleProps,
134
140
  parentSplitStyles,
135
141
  componentContext,
142
+ groupContext,
136
143
  elementType,
137
144
  startedUnhydrated,
138
145
  debug
@@ -165,7 +172,6 @@ export const getSplitStyles: StyleSplitter = (
165
172
 
166
173
  const viewProps: GetStyleResult['viewProps'] = {}
167
174
  const mediaState = styleProps.mediaState || globalMediaState
168
- const usedKeys: Record<string, number> = {}
169
175
  const shouldDoClasses =
170
176
  acceptsClassName && isWeb && !styleProps.noClass && !styleProps.isAnimated
171
177
  const rulesToInsert: RulesToInsert =
@@ -202,7 +208,7 @@ export const getSplitStyles: StyleSplitter = (
202
208
  staticConfig,
203
209
  style: null,
204
210
  theme,
205
- usedKeys,
211
+ usedKeys: {},
206
212
  viewProps,
207
213
  context: componentContext,
208
214
  debug,
@@ -234,18 +240,19 @@ export const getSplitStyles: StyleSplitter = (
234
240
  debug !== 'profile' &&
235
241
  isClient
236
242
  ) {
237
- console.groupCollapsed('getSplitStyles (collapsed)')
238
- log({
239
- props,
240
- staticConfig,
241
- shouldDoClasses,
242
- styleProps,
243
- rulesToInsert,
244
- componentState,
245
- styleState,
246
- theme: { ...theme },
247
- })
248
- console.groupEnd()
243
+ if (isDevTools) {
244
+ console.groupCollapsed('🔹 getSplitStyles 👇')
245
+ log({
246
+ props,
247
+ staticConfig,
248
+ shouldDoClasses,
249
+ styleProps,
250
+ rulesToInsert,
251
+ componentState,
252
+ styleState,
253
+ theme: { ...theme },
254
+ })
255
+ }
249
256
  }
250
257
 
251
258
  const { asChild } = props
@@ -298,7 +305,6 @@ export const getSplitStyles: StyleSplitter = (
298
305
  }
299
306
 
300
307
  if (keyInit === 'className') continue // handled above first
301
- if (keyInit in usedKeys) continue
302
308
 
303
309
  if (process.env.TAMAGUI_TARGET === 'web') {
304
310
  // skip the webViewFlexCompatStyles when asChild on web
@@ -329,7 +335,6 @@ export const getSplitStyles: StyleSplitter = (
329
335
  continue
330
336
  }
331
337
 
332
- const valInitType = typeof valInit
333
338
  let isValidStyleKeyInit = isValidStyleKey(keyInit, validStyles, accept)
334
339
 
335
340
  // this is all for partially optimized (not flattened)... maybe worth removing?
@@ -499,13 +504,14 @@ export const getSplitStyles: StyleSplitter = (
499
504
 
500
505
  if (isMediaOrPseudo && keyInit.startsWith('$group-')) {
501
506
  const parts = keyInit.split('-')
507
+ const plen = parts.length
502
508
  if (
503
509
  // check if its actually a simple group selector to avoid breaking selectors
504
- parts.length === 2 ||
505
- (parts.length === 3 && pseudoPriorities[parts[parts.length - 1]])
510
+ plen === 2 ||
511
+ (plen === 3 && pseudoPriorities[parts[parts.length - 1]])
506
512
  ) {
507
513
  const name = parts[1]
508
- if (componentContext?.groups.subscribe && !componentContext?.groups.state[name]) {
514
+ if (groupContext && !groupContext?.[name]) {
509
515
  keyInit = keyInit.replace('$group-', `$group-true-`)
510
516
  }
511
517
  }
@@ -545,6 +551,7 @@ export const getSplitStyles: StyleSplitter = (
545
551
  variant: variants?.[keyInit],
546
552
  isVariant,
547
553
  isHOCShouldPassThrough,
554
+ usedKeys: { ...styleState.usedKeys },
548
555
  parentStaticConfig,
549
556
  })
550
557
  }
@@ -616,7 +623,6 @@ export const getSplitStyles: StyleSplitter = (
616
623
  }
617
624
 
618
625
  if (val == null) return
619
- if (key in usedKeys) return
620
626
 
621
627
  if (process.env.TAMAGUI_TARGET === 'native') {
622
628
  if (key === 'pointerEvents') {
@@ -629,7 +635,7 @@ export const getSplitStyles: StyleSplitter = (
629
635
  (!isHOC && isValidStyleKey(key, validStyles, accept)) ||
630
636
  (process.env.TAMAGUI_TARGET === 'native' && isAndroid && key === 'elevation')
631
637
  ) {
632
- mergeStyle(styleState, key, val)
638
+ mergeStyle(styleState, key, val, 1)
633
639
  return
634
640
  }
635
641
 
@@ -703,7 +709,6 @@ export const getSplitStyles: StyleSplitter = (
703
709
 
704
710
  for (const psuedoStyle of pseudoStyles) {
705
711
  const fullKey = `${psuedoStyle[StyleObjectProperty]}${PROP_SPLIT}${descriptor.name}`
706
- if (fullKey in usedKeys) continue
707
712
  addStyleToInsertRules(rulesToInsert, psuedoStyle)
708
713
  classNames[fullKey] = psuedoStyle[StyleObjectIdentifier]
709
714
  }
@@ -740,7 +745,7 @@ export const getSplitStyles: StyleSplitter = (
740
745
  if (isDisabled) {
741
746
  applyDefaultStyle(pkey, styleState)
742
747
  } else {
743
- const curImportance = usedKeys[pkey] || 0
748
+ const curImportance = styleState.usedKeys[pkey] || 0
744
749
  const shouldMerge = importance >= curImportance
745
750
 
746
751
  if (shouldMerge) {
@@ -749,7 +754,7 @@ export const getSplitStyles: StyleSplitter = (
749
754
  pseudos[key] ||= {}
750
755
  pseudos[key][pkey] = val
751
756
  }
752
- mergeStyle(styleState, pkey, val)
757
+ mergeStyle(styleState, pkey, val, importance)
753
758
  }
754
759
 
755
760
  if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
@@ -768,7 +773,7 @@ export const getSplitStyles: StyleSplitter = (
768
773
  // mark usedKeys based on pseudoStyleObject
769
774
  for (const key in val) {
770
775
  const k = shorthands[key] || key
771
- usedKeys[k] = Math.max(importance, usedKeys[k] || 0)
776
+ styleState.usedKeys[k] = Math.max(importance, styleState.usedKeys[k] || 0)
772
777
  }
773
778
  }
774
779
  }
@@ -813,6 +818,9 @@ export const getSplitStyles: StyleSplitter = (
813
818
  })
814
819
  }
815
820
 
821
+ const priority = mediaStylesSeen
822
+ mediaStylesSeen += 1
823
+
816
824
  if (shouldDoClasses) {
817
825
  const mediaStyle = getSubStyle(styleState, key, val, false)
818
826
 
@@ -823,12 +831,12 @@ export const getSplitStyles: StyleSplitter = (
823
831
  const importance = getMediaImportanceIfMoreImportant(
824
832
  mediaKeyShort,
825
833
  'space',
826
- usedKeys,
834
+ styleState,
827
835
  true
828
836
  )
829
837
  if (importance) {
830
838
  space = val['space']
831
- usedKeys['space'] = importance
839
+ styleState.usedKeys['space'] = importance
832
840
  if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
833
841
  log(
834
842
  `Found more important space for current media ${mediaKeyShort}: ${val} (importance: ${importance})`
@@ -839,8 +847,6 @@ export const getSplitStyles: StyleSplitter = (
839
847
  }
840
848
 
841
849
  const mediaStyles = getCSSStylesAtomic(mediaStyle)
842
- const priority = mediaStylesSeen
843
- mediaStylesSeen += 1
844
850
 
845
851
  for (const style of mediaStyles) {
846
852
  // handle nested media:
@@ -872,7 +878,6 @@ export const getSplitStyles: StyleSplitter = (
872
878
  style[StyleObjectProperty]
873
879
  }${subKey}${PROP_SPLIT}${mediaKeyShort}${style[StyleObjectPseudo] || ''}`
874
880
 
875
- if (fullKey in usedKeys) continue
876
881
  addStyleToInsertRules(rulesToInsert, out as any)
877
882
  classNames[fullKey] = out[StyleObjectIdentifier]
878
883
  }
@@ -922,7 +927,7 @@ export const getSplitStyles: StyleSplitter = (
922
927
  val,
923
928
  oppositeVal,
924
929
  })
925
- mergeStyle(styleState, subKey, mediaStyle[subKey])
930
+ mergeStyle(styleState, subKey, mediaStyle[subKey], priority)
926
931
  }
927
932
  } else if (
928
933
  !(themeName === mediaKeyShort || themeName.startsWith(mediaKeyShort))
@@ -934,9 +939,9 @@ export const getSplitStyles: StyleSplitter = (
934
939
  const groupName = groupInfo.name
935
940
 
936
941
  // $group-x
937
- const groupContext = componentContext?.groups.state[groupName]
942
+ const groupState = groupContext?.[groupName]?.state
938
943
 
939
- if (!groupContext) {
944
+ if (!groupState) {
940
945
  if (process.env.NODE_ENV === 'development' && debug) {
941
946
  log(`No parent with group prop, skipping styles: ${groupName}`)
942
947
  }
@@ -954,12 +959,15 @@ export const getSplitStyles: StyleSplitter = (
954
959
  let isActive = mediaState?.[groupMediaKey]
955
960
 
956
961
  // use parent styles if width and height hardcoded we can do an inline media match and avoid double render
957
- if (!mediaState && groupContext.layout) {
958
- isActive = mediaKeyMatch(groupMediaKey, groupContext.layout)
962
+ if (!mediaState && groupState.layout) {
963
+ isActive = mediaKeyMatch(groupMediaKey, groupState.layout)
959
964
  }
960
965
 
961
966
  if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
962
- log(` 🏘️ GROUP media ${groupMediaKey} active? ${isActive}`)
967
+ log(` 🏘️ GROUP media ${groupMediaKey} active? ${isActive}`, {
968
+ ...mediaState,
969
+ usedKeys: { ...styleState.usedKeys },
970
+ })
963
971
  }
964
972
  if (!isActive) {
965
973
  // ensure we set the defaults so animations work
@@ -978,15 +986,19 @@ export const getSplitStyles: StyleSplitter = (
978
986
  const componentGroupPseudoState = (
979
987
  componentGroupState ||
980
988
  // fallback to context initially
981
- componentContext.groups.state[groupName]
982
- ).pseudo
989
+ groupContext?.[groupName].state
990
+ )?.pseudo
983
991
 
984
992
  const isActive = componentGroupPseudoState?.[groupPseudoKey]
985
993
  const priority = pseudoPriorities[groupPseudoKey]
986
994
 
987
995
  if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
988
996
  log(
989
- ` 🏘️ GROUP pseudo ${groupMediaKey} active? ${isActive}, priority ${priority}`
997
+ ` 🏘️ GROUP pseudo ${groupMediaKey} active? ${isActive}, priority ${priority}`,
998
+ {
999
+ componentGroupPseudoState: { ...componentGroupPseudoState },
1000
+ usedKeys: { ...styleState.usedKeys },
1001
+ }
990
1002
  )
991
1003
  }
992
1004
  if (!isActive) {
@@ -1008,7 +1020,6 @@ export const getSplitStyles: StyleSplitter = (
1008
1020
  mediaKeyShort,
1009
1021
  key,
1010
1022
  val,
1011
- usedKeys,
1012
1023
  mediaState[mediaKeyShort],
1013
1024
  importanceBump,
1014
1025
  debug
@@ -1053,6 +1064,7 @@ export const getSplitStyles: StyleSplitter = (
1053
1064
  log(` ✔️ expand complete`, keyInit)
1054
1065
  log('style', { ...styleState.style })
1055
1066
  log('viewProps', { ...viewProps })
1067
+ log('transforms', { ...styleState.flatTransforms })
1056
1068
  } catch {
1057
1069
  // RN can run into PayloadTooLargeError: request entity too large
1058
1070
  }
@@ -1355,8 +1367,11 @@ export const getSplitStyles: StyleSplitter = (
1355
1367
  }
1356
1368
  }
1357
1369
 
1358
- if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
1359
- if (isDevTools) {
1370
+ if (process.env.NODE_ENV === 'development' && debug && debug !== 'profile') {
1371
+ if (isClient && isDevTools) {
1372
+ // end collapsed log above
1373
+ console.groupEnd()
1374
+
1360
1375
  console.groupCollapsed('🔹 getSplitStyles ===>')
1361
1376
  try {
1362
1377
  // prettier-ignore
@@ -1398,11 +1413,19 @@ function mergeStyle(
1398
1413
  styleState: GetStyleState,
1399
1414
  key: string,
1400
1415
  val: any,
1416
+ importance: number,
1401
1417
  disableNormalize = false
1402
1418
  ) {
1403
- const { viewProps, styleProps, staticConfig } = styleState
1419
+ const { viewProps, styleProps, staticConfig, usedKeys } = styleState
1420
+
1421
+ const existingImportance = usedKeys[key] || 0
1422
+ if (existingImportance > importance) {
1423
+ return
1424
+ }
1425
+
1404
1426
  if (key in stylePropsTransform) {
1405
1427
  styleState.flatTransforms ||= {}
1428
+ usedKeys[key] = importance
1406
1429
  styleState.flatTransforms[key] = val
1407
1430
  } else {
1408
1431
  const shouldNormalize = isWeb && !disableNormalize && !styleProps.noNormalize
@@ -1415,6 +1438,7 @@ function mergeStyle(
1415
1438
  viewProps[key] = out
1416
1439
  } else {
1417
1440
  styleState.style ||= {}
1441
+ usedKeys[key] = importance
1418
1442
  styleState.style[key] =
1419
1443
  // if you dont do this you'll be passing props.transform arrays directly here and then mutating them
1420
1444
  // if theres any flatTransforms later, causing issues (mutating props is bad, in strict mode styles get borked)
@@ -1481,11 +1505,10 @@ const useInsertEffectCompat = isWeb
1481
1505
  : () => {}
1482
1506
 
1483
1507
  // perf: ...args a bit expensive on native
1484
- export const useSplitStyles: StyleSplitter = (a, b, c, d, e, f, g, h, i, j, k) => {
1485
- const res = getSplitStyles(a, b, c, d, e, f, g, h, i, j, k)
1508
+ export const useSplitStyles: StyleSplitter = (a, b, c, d, e, f, g, h, i, j, k, l) => {
1509
+ const res = getSplitStyles(a, b, c, d, e, f, g, h, i, j, k, l)
1486
1510
 
1487
1511
  if (process.env.TAMAGUI_TARGET !== 'native') {
1488
- // j = startedUnhydrated
1489
1512
  useInsertEffectCompat(() => {
1490
1513
  insertStyleRules(res.rulesToInsert)
1491
1514
  }, [res.rulesToInsert])
@@ -1574,15 +1597,15 @@ function mergeMediaByImportance(
1574
1597
  mediaKey: string,
1575
1598
  key: string,
1576
1599
  value: any,
1577
- importancesUsed: Record<string, number>,
1578
1600
  isSizeMedia: boolean,
1579
1601
  importanceBump?: number,
1580
1602
  debugProp?: DebugProp
1581
1603
  ) {
1604
+ const usedKeys = styleState.usedKeys
1582
1605
  let importance = getMediaImportanceIfMoreImportant(
1583
1606
  mediaKey,
1584
1607
  key,
1585
- importancesUsed,
1608
+ styleState,
1586
1609
  isSizeMedia
1587
1610
  )
1588
1611
  if (importanceBump) {
@@ -1590,26 +1613,24 @@ function mergeMediaByImportance(
1590
1613
  }
1591
1614
  if (process.env.NODE_ENV === 'development' && debugProp === 'verbose') {
1592
1615
  log(
1593
- `mergeMediaByImportance ${key} importance existing ${importancesUsed[key]} next ${importance}`
1616
+ `mergeMediaByImportance ${key} importance usedKey ${usedKeys[key]} next ${importance}`
1594
1617
  )
1595
1618
  }
1596
1619
  if (importance === null) {
1597
1620
  return false
1598
1621
  }
1599
- importancesUsed[key] = importance
1600
-
1601
1622
  if (key in pseudoDescriptors) {
1602
- const descriptor = pseudoDescriptors[key]
1623
+ const descriptor = pseudoDescriptors[key as PseudoDescriptorKey]
1603
1624
  const descriptorKey = descriptor.stateKey || descriptor.name
1604
1625
  const isDisabled = styleState.componentState[descriptorKey] === false
1605
1626
  if (isDisabled) {
1606
1627
  return false
1607
1628
  }
1608
1629
  for (const subKey in value) {
1609
- mergeStyle(styleState, subKey, value[subKey])
1630
+ mergeStyle(styleState, subKey, value[subKey], importance)
1610
1631
  }
1611
1632
  } else {
1612
- mergeStyle(styleState, key, value)
1633
+ mergeStyle(styleState, key, value, importance)
1613
1634
  }
1614
1635
 
1615
1636
  return true
@@ -1639,6 +1660,6 @@ function applyDefaultStyle(pkey: string, styleState: GetStyleState) {
1639
1660
  !(pkey in styleState.usedKeys) &&
1640
1661
  (!styleState.style || !(pkey in styleState.style))
1641
1662
  ) {
1642
- mergeStyle(styleState, pkey, defaultValues)
1663
+ mergeStyle(styleState, pkey, defaultValues, 1)
1643
1664
  }
1644
1665
  }
@@ -4,51 +4,47 @@ export const pseudoDescriptorsBase = {
4
4
  // order of keys here important! in priority order
5
5
  hoverStyle: {
6
6
  name: 'hover',
7
- priority: 1,
7
+ priority: 2,
8
8
  },
9
9
  pressStyle: {
10
10
  name: 'active',
11
11
  stateKey: 'press',
12
- priority: 2,
12
+ priority: 3,
13
13
  },
14
14
  focusVisibleStyle: {
15
15
  name: 'focus-visible',
16
- priority: 3,
16
+ priority: 4,
17
17
  stateKey: 'focusVisible',
18
18
  },
19
19
  focusStyle: {
20
20
  name: 'focus',
21
- priority: 3,
21
+ priority: 4,
22
22
  },
23
23
  focusWithinStyle: {
24
24
  name: 'focus-within',
25
- priority: 3,
25
+ priority: 4,
26
26
  stateKey: 'focusWithin',
27
27
  },
28
28
  disabledStyle: {
29
29
  name: 'disabled',
30
- priority: 4,
30
+ priority: 5,
31
31
  stateKey: 'disabled',
32
32
  },
33
33
  } as const
34
34
 
35
35
  export const pseudoPriorities = {
36
- hover: 1,
37
- press: 2,
38
- focus: 3,
39
- focusVisible: 3,
40
- focusWithin: 3,
41
- disabled: 4,
36
+ hover: pseudoDescriptorsBase.hoverStyle.priority,
37
+ press: pseudoDescriptorsBase.pressStyle.priority,
38
+ focus: pseudoDescriptorsBase.focusStyle.priority,
39
+ focusVisible: pseudoDescriptorsBase.focusVisibleStyle.priority,
40
+ focusWithin: pseudoDescriptorsBase.focusWithinStyle.priority,
41
+ disabled: pseudoDescriptorsBase.disabledStyle.priority,
42
42
  }
43
43
 
44
+ export type PseudoDescriptorKey = keyof typeof pseudoDescriptorsBase
45
+
44
46
  export const pseudoDescriptors: Record<
45
- | 'hoverStyle'
46
- | 'pressStyle'
47
- | 'focusStyle'
48
- | 'focusVisibleStyle'
49
- | 'focusWithinStyle'
50
- | 'enterStyle'
51
- | 'exitStyle',
47
+ PseudoDescriptorKey | 'enterStyle' | 'exitStyle',
52
48
  PseudoDescriptor
53
49
  > = {
54
50
  ...pseudoDescriptorsBase,
@@ -1,55 +1,91 @@
1
- import { getMediaState } from '../hooks/useMedia'
2
- import type { ComponentContextI, GroupState, TamaguiComponentState } from '../types'
3
1
  import { mergeIfNotShallowEqual } from '@tamagui/is-equal-shallow'
2
+ import { getMediaState } from '../hooks/useMedia'
3
+ import type { ComponentSetStateShallow, DisposeFn, AllGroupContexts } from '../types'
4
4
 
5
- export const subscribeToContextGroup = ({
6
- setStateShallow,
7
- pseudoGroups,
8
- mediaGroups,
9
- componentContext,
10
- state,
11
- }: {
12
- setStateShallow: (next: Partial<TamaguiComponentState>) => void
5
+ type SubscribeToContextGroupProps = {
6
+ setStateShallow: ComponentSetStateShallow
13
7
  pseudoGroups?: Set<string>
14
8
  mediaGroups?: Set<string>
15
- componentContext: ComponentContextI
16
- state: TamaguiComponentState
17
- }) => {
18
- // parent group pseudo listening
9
+ groupContext: AllGroupContexts
10
+ }
11
+
12
+ export const subscribeToContextGroup = (props: SubscribeToContextGroupProps) => {
13
+ const { pseudoGroups, mediaGroups, groupContext } = props
19
14
  if (pseudoGroups || mediaGroups) {
20
- if (process.env.NODE_ENV === 'development' && !componentContext.groups) {
15
+ if (process.env.NODE_ENV === 'development' && !groupContext) {
21
16
  console.debug(`No context group found`)
22
17
  }
23
18
 
24
- return componentContext.groups?.subscribe?.((name, { layout, pseudo }) => {
25
- const current: GroupState = state.group?.[name] || {
19
+ const disposables = new Set<DisposeFn>()
20
+
21
+ if (pseudoGroups) {
22
+ for (const name of [...pseudoGroups]) {
23
+ disposables.add(createGroupListener(name, props))
24
+ }
25
+ }
26
+
27
+ if (mediaGroups) {
28
+ for (const name of [...mediaGroups]) {
29
+ disposables.add(createGroupListener(name, props))
30
+ }
31
+ }
32
+
33
+ return () => {
34
+ disposables.forEach((d) => d())
35
+ }
36
+ }
37
+ }
38
+
39
+ const createGroupListener = (
40
+ name: string,
41
+ {
42
+ setStateShallow,
43
+ pseudoGroups,
44
+ mediaGroups,
45
+ groupContext,
46
+ }: SubscribeToContextGroupProps
47
+ ): DisposeFn => {
48
+ const parent = groupContext?.[name]
49
+
50
+ if (!parent) {
51
+ return () => {}
52
+ }
53
+
54
+ return parent.subscribe(({ layout, pseudo }) => {
55
+ setStateShallow((prev) => {
56
+ let didChange = false
57
+ const group = prev.group?.[name] || {
26
58
  pseudo: {},
27
59
  media: {},
28
60
  }
29
61
 
30
- if (pseudo && pseudoGroups?.has(String(name))) {
31
- // we emit a partial so merge it + change reference so mergeIfNotShallowEqual runs
32
- Object.assign(current.pseudo!, pseudo)
33
- persist()
62
+ if (pseudo && pseudoGroups?.has(name)) {
63
+ group.pseudo ||= {}
64
+ const next = mergeIfNotShallowEqual(group.pseudo, pseudo)
65
+ if (next !== group.pseudo) {
66
+ Object.assign(group.pseudo, pseudo)
67
+ didChange = true
68
+ }
34
69
  } else if (layout && mediaGroups) {
70
+ group.media ||= {}
35
71
  const mediaState = getMediaState(mediaGroups, layout)
36
- const next = mergeIfNotShallowEqual(current.media || {}, mediaState)
37
- if (next !== current.media) {
38
- Object.assign(current.media!, next)
39
- persist()
72
+ const next = mergeIfNotShallowEqual(group.media, mediaState)
73
+ if (next !== group.media) {
74
+ Object.assign(group.media, next)
75
+ didChange = true
40
76
  }
41
77
  }
42
78
 
43
- function persist() {
44
- // force it to be referentially different so it always updates
45
- const group = {
46
- ...state.group,
47
- [name]: current,
79
+ if (didChange) {
80
+ return {
81
+ group: {
82
+ ...prev.group,
83
+ [name]: group,
84
+ },
48
85
  }
49
- setStateShallow({
50
- group,
51
- })
52
86
  }
87
+
88
+ return prev
53
89
  })
54
- }
90
+ })
55
91
  }
@@ -11,8 +11,6 @@ import { isObj } from '../helpers/isObj'
11
11
  import { log } from '../helpers/log'
12
12
  import type {
13
13
  ComponentContextI,
14
- ComponentStateListener,
15
- GroupStateListener,
16
14
  StackProps,
17
15
  StaticConfig,
18
16
  TamaguiComponentState,
@@ -24,7 +22,7 @@ import type {
24
22
 
25
23
  export const useComponentState = (
26
24
  props: StackProps | TextProps | Record<string, any>,
27
- { animationDriver }: ComponentContextI,
25
+ animationDriver: ComponentContextI['animationDriver'],
28
26
  staticConfig: StaticConfig,
29
27
  config: TamaguiInternalConfig
30
28
  ) => {
@@ -45,7 +43,6 @@ export const useComponentState = (
45
43
  'animation' in props || (props.style && hasAnimatedStyleValue(props.style))
46
44
  )
47
45
 
48
- // disable for now still ssr issues
49
46
  const supportsCSS = animationDriver?.supportsCSS
50
47
  const curStateRef = stateRef.current
51
48
 
@@ -125,7 +122,6 @@ export const useComponentState = (
125
122
  // unsafe yea yea
126
123
  if (stateRef.current.nextComponentState) {
127
124
  Object.assign(state, stateRef.current.nextComponentState)
128
- stateRef.current.nextComponentState = undefined
129
125
  }
130
126
 
131
127
  // only web server + initial client render run this when not hydrated:
@@ -145,7 +141,7 @@ export const useComponentState = (
145
141
  setState((_) => ({ ...state }))
146
142
  }
147
143
 
148
- const groupName = props.group as any as string
144
+ const groupName = props.group as any as string | undefined
149
145
 
150
146
  const setStateShallow = useCreateShallowSetState(setState, props.debug)
151
147
 
@@ -205,46 +201,6 @@ export const useComponentState = (
205
201
  }
206
202
  }
207
203
 
208
- if (groupName && !curStateRef.group) {
209
- const listeners = new Set<GroupStateListener>()
210
- curStateRef.group = {
211
- listeners,
212
- emit(name, state) {
213
- listeners.forEach((l) => l(name, state))
214
- },
215
- subscribe(cb) {
216
- listeners.add(cb)
217
- setStateShallow({ hasDynGroupChildren: true })
218
- return () => {
219
- listeners.delete(cb)
220
- if (listeners.size === 0) {
221
- setStateShallow({ hasDynGroupChildren: false })
222
- }
223
- }
224
- },
225
- }
226
- }
227
-
228
- if (!curStateRef.stateEmitter && hasAnimationProp) {
229
- const listeners = new Set<ComponentStateListener>()
230
- curStateRef.stateEmitter = {
231
- listeners,
232
- emit(state) {
233
- listeners.forEach((l) => l(state))
234
- },
235
- subscribe(cb) {
236
- listeners.add(cb)
237
- setStateShallow({ hasDynGroupChildren: true })
238
- return () => {
239
- listeners.delete(cb)
240
- if (listeners.size === 0) {
241
- setStateShallow({ hasDynGroupChildren: false })
242
- }
243
- }
244
- },
245
- }
246
- }
247
-
248
204
  return {
249
205
  startedUnhydrated,
250
206
  curStateRef,