@tamagui/core 1.0.1-beta.214 → 1.0.1-beta.215

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 (46) hide show
  1. package/dist/cjs/constants/isDevTools.js +9 -1
  2. package/dist/cjs/constants/isDevTools.js.map +2 -2
  3. package/dist/cjs/createComponent.js +71 -152
  4. package/dist/cjs/createComponent.js.map +3 -3
  5. package/dist/cjs/helpers/getSplitStyles.js +74 -47
  6. package/dist/cjs/helpers/getSplitStyles.js.map +2 -2
  7. package/dist/cjs/helpers/getStylesAtomic.js +5 -1
  8. package/dist/cjs/helpers/getStylesAtomic.js.map +2 -2
  9. package/dist/cjs/helpers/normalizeValueWithProperty.js +9 -5
  10. package/dist/cjs/helpers/normalizeValueWithProperty.js.map +2 -2
  11. package/dist/cjs/helpers/pseudoDescriptors.js +10 -0
  12. package/dist/cjs/helpers/pseudoDescriptors.js.map +2 -2
  13. package/dist/cjs/helpers/useShallowSetState.js +1 -1
  14. package/dist/cjs/helpers/useShallowSetState.js.map +2 -2
  15. package/dist/cjs/types.js.map +1 -1
  16. package/dist/cjs/views/TamaguiProvider.js +2 -5
  17. package/dist/cjs/views/TamaguiProvider.js.map +3 -3
  18. package/dist/esm/constants/isDevTools.js +9 -1
  19. package/dist/esm/constants/isDevTools.js.map +2 -2
  20. package/dist/esm/createComponent.js +72 -152
  21. package/dist/esm/createComponent.js.map +3 -3
  22. package/dist/esm/helpers/getSplitStyles.js +75 -48
  23. package/dist/esm/helpers/getSplitStyles.js.map +2 -2
  24. package/dist/esm/helpers/getStylesAtomic.js +5 -1
  25. package/dist/esm/helpers/getStylesAtomic.js.map +2 -2
  26. package/dist/esm/helpers/normalizeValueWithProperty.js +9 -5
  27. package/dist/esm/helpers/normalizeValueWithProperty.js.map +2 -2
  28. package/dist/esm/helpers/pseudoDescriptors.js +10 -0
  29. package/dist/esm/helpers/pseudoDescriptors.js.map +2 -2
  30. package/dist/esm/helpers/useShallowSetState.js +1 -1
  31. package/dist/esm/helpers/useShallowSetState.js.map +2 -2
  32. package/dist/esm/views/TamaguiProvider.js +2 -5
  33. package/dist/esm/views/TamaguiProvider.js.map +3 -3
  34. package/package.json +12 -12
  35. package/src/constants/isDevTools.ts +10 -4
  36. package/src/createComponent.tsx +85 -200
  37. package/src/helpers/getSplitStyles.tsx +91 -57
  38. package/src/helpers/getStylesAtomic.ts +7 -2
  39. package/src/helpers/normalizeValueWithProperty.ts +11 -5
  40. package/src/helpers/pseudoDescriptors.ts +24 -3
  41. package/src/helpers/useShallowSetState.tsx +1 -1
  42. package/src/types.tsx +1 -1
  43. package/src/views/TamaguiProvider.tsx +5 -6
  44. package/types/helpers/getSplitStyles.d.ts +1 -1
  45. package/types/helpers/pseudoDescriptors.d.ts +8 -14
  46. package/types/types.d.ts +1 -1
@@ -1,6 +1,5 @@
1
- import { isClient, isRSC, isWeb, useIsomorphicLayoutEffect } from '@tamagui/constants'
1
+ import { isClient, isRSC, isServer, isWeb, useIsomorphicLayoutEffect } from '@tamagui/constants'
2
2
  import { stylePropsText, stylePropsTransform, validPseudoKeys, validStyles } from '@tamagui/helpers'
3
- import { timer } from '@tamagui/timer'
4
3
  import type { ViewStyle } from '@tamagui/types-react-native'
5
4
  import { useInsertionEffect } from 'react'
6
5
 
@@ -25,7 +24,6 @@ import type {
25
24
  import { FontLanguageProps, LanguageContextType } from '../views/FontLanguage.types'
26
25
  import { createMediaStyle } from './createMediaStyle'
27
26
  import { getPropMappedFontFamily } from './createPropMapper'
28
- import { createProxy } from './createProxy'
29
27
  import { fixStyles } from './expandStyles'
30
28
  import { getAtomicStyle, getStylesAtomic, styleToCSS } from './getStylesAtomic'
31
29
  import {
@@ -199,6 +197,19 @@ export const getSplitStyles: StyleSplitter = (
199
197
  staticConfig.acceptsClassName && (isWeb || IS_STATIC) && !state.noClassNames
200
198
 
201
199
  let style: ViewStyle = {}
200
+ let flatTransforms: Record<string, any> | undefined
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
+ }
202
213
 
203
214
  const len = propKeys.length
204
215
  const rulesToInsert: RulesToInsert = []
@@ -265,7 +276,11 @@ export const getSplitStyles: StyleSplitter = (
265
276
 
266
277
  if (keyInit === 'testID') {
267
278
  usedKeys[keyInit] = 1
268
- viewProps['data-testid'] = valInit
279
+ if (staticConfig.isReactNative) {
280
+ viewProps.testId = valInit
281
+ } else {
282
+ viewProps['data-testid'] = valInit
283
+ }
269
284
  continue
270
285
  }
271
286
 
@@ -409,15 +424,13 @@ export const getSplitStyles: StyleSplitter = (
409
424
  }
410
425
  }
411
426
 
412
- if (state.keepVariantsAsProps) {
413
- if (
414
- (staticConfig.defaultVariants && keyInit in staticConfig.defaultVariants) ||
415
- // may want to just: not compile styled() into classnames, always do this, and always pass in all values in extras.props
416
- // but we'd want to add styled({ extracted: true }) or something at compile time to save on parsing a bit...
417
- (staticConfig.variants && keyInit in staticConfig.variants)
418
- ) {
419
- viewProps[keyInit] = valInit
420
- }
427
+ if (
428
+ (staticConfig.defaultVariants && keyInit in staticConfig.defaultVariants) ||
429
+ // may want to just: not compile styled() into classnames, always do this, and always pass in all values in extras.props
430
+ // but we'd want to add styled({ extracted: true }) or something at compile time to save on parsing a bit...
431
+ (state.keepVariantsAsProps && staticConfig.variants && keyInit in staticConfig.variants)
432
+ ) {
433
+ viewProps[keyInit] = valInit
421
434
  }
422
435
 
423
436
  /**
@@ -466,11 +479,13 @@ export const getSplitStyles: StyleSplitter = (
466
479
  }
467
480
 
468
481
  if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
469
- if (isClient) {
482
+ if (!isServer) {
470
483
  // eslint-disable-next-line no-console
471
484
  console.log('expanded', expanded)
472
485
  // eslint-disable-next-line no-console
473
486
  console.log('usedKeys', usedKeys)
487
+ // eslint-disable-next-line no-console
488
+ console.log('current', { ...style })
474
489
  }
475
490
  // eslint-disable-next-line no-console
476
491
  console.groupEnd()
@@ -501,11 +516,8 @@ export const getSplitStyles: StyleSplitter = (
501
516
  // pseudo
502
517
  if (isPseudo) {
503
518
  if (!val) continue
504
- if (key === 'enterStyle' && state.mounted) {
505
- // once mounted we can ignore enterStyle
506
- continue
507
- }
508
- pseudos[key] ??= {}
519
+
520
+ // TODO can avoid processing this if !shouldDoClasses + state is off
509
521
  const pseudoStyleObject = getSubStyle(
510
522
  key,
511
523
  val,
@@ -515,57 +527,64 @@ export const getSplitStyles: StyleSplitter = (
515
527
  state,
516
528
  conf,
517
529
  languageContext,
530
+ true,
518
531
  true
519
532
  )
520
533
 
521
- pseudos[key] = {
522
- ...pseudoStyleObject,
523
- ...pseudos[key],
534
+ const descriptor = pseudoDescriptors[key as keyof typeof pseudoDescriptors]
535
+ if (!descriptor) {
536
+ continue
524
537
  }
525
538
 
526
- if (key === 'enterStyle' || key === 'exitStyle') {
527
- continue
539
+ if (key !== 'enterStyle') {
540
+ if (!shouldDoClasses || IS_STATIC) {
541
+ pseudos[key] ||= {}
542
+ Object.assign(pseudos[key], pseudoStyleObject)
543
+ }
528
544
  }
529
545
 
530
546
  if (shouldDoClasses) {
531
- const pseudoStyles = getAtomicStyle(pseudoStyleObject, pseudoDescriptors[key])
547
+ const pseudoStyles = getAtomicStyle(pseudoStyleObject, descriptor)
532
548
  for (const psuedoStyle of pseudoStyles) {
533
- const postfix = pseudoDescriptors[key]?.name || key // (exit/enterStyle have no pseudoDescriptors)
534
- const fullKey = `${psuedoStyle.property}${PROP_SPLIT}${postfix}`
549
+ const fullKey = `${psuedoStyle.property}${PROP_SPLIT}${descriptor.name}`
535
550
  if (!usedKeys[fullKey]) {
536
551
  usedKeys[fullKey] = 1
537
- if (shouldDoClasses) {
538
- addStyleToInsertRules(rulesToInsert, psuedoStyle)
539
- mergeClassName(
540
- transforms,
541
- classNames,
542
- fullKey,
543
- psuedoStyle.identifier,
544
- isMediaOrPseudo
545
- )
546
- }
552
+ addStyleToInsertRules(rulesToInsert, psuedoStyle)
553
+ mergeClassName(
554
+ transforms,
555
+ classNames,
556
+ fullKey,
557
+ psuedoStyle.identifier,
558
+ isMediaOrPseudo
559
+ )
547
560
  }
548
561
  }
549
562
  } else {
550
- psuedosUsed ??= {}
551
- const importance = pseudoDescriptors[key].priority
563
+ if (!state[descriptor.stateKey || descriptor.name]) {
564
+ continue
565
+ }
566
+
567
+ psuedosUsed ||= {}
568
+ usedKeys[key] ||= 1
569
+ const importance = descriptor.priority
552
570
  for (const pkey in pseudoStyleObject) {
553
- const curImportance = psuedosUsed[importance]
554
- // change after curImportance
555
- psuedosUsed[pkey] = importance
571
+ const curImportance = psuedosUsed[importance] || 0
556
572
  const val = pseudoStyleObject[pkey]
557
- if (curImportance <= importance) {
573
+ if (importance >= curImportance) {
558
574
  psuedosUsed[pkey] = importance
559
- style[pkey] = val
575
+ pseudos[key] ||= {}
576
+ pseudos[key][pkey] = val
577
+ mergeStyle(pkey, val)
560
578
  }
561
579
  }
562
580
  }
563
-
564
581
  continue
565
582
  }
566
583
 
567
584
  // media
568
585
  if (isMedia) {
586
+ if (!val) continue
587
+
569
588
  const mediaKey = key
570
589
  const mediaKeyShort = mediaKey.slice(1)
571
590
  mediaKeys.push(mediaKeyShort)
@@ -581,7 +600,10 @@ export const getSplitStyles: StyleSplitter = (
581
600
  props,
582
601
  state,
583
602
  conf,
584
- languageContext
603
+ languageContext,
604
+ // TODO try true like pseudo
605
+ false,
606
+ true
585
607
  )
586
608
 
587
609
  if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
@@ -604,8 +626,10 @@ export const getSplitStyles: StyleSplitter = (
604
626
  } else if (mediaState[mediaKey]) {
605
627
  for (const key in mediaStyle) {
606
628
  const didMerge = mergeMediaByImportance(style, key, mediaStyle[key], usedKeys)
607
- if (didMerge && key === 'fontFamily') {
608
- fontFamily = mediaStyle[key]
629
+ if (didMerge) {
630
+ if (key === 'fontFamily') {
631
+ fontFamily = mediaStyle[key]
632
+ }
609
633
  }
610
634
  }
611
635
  }
@@ -624,13 +648,7 @@ export const getSplitStyles: StyleSplitter = (
624
648
 
625
649
  if (validStyleProps[key]) {
626
650
  usedKeys[key] = 1
627
- if (val && val[0] === '_') {
628
- classNames[key] = val
629
- } else if (key in stylePropsTransform) {
630
- mergeTransform(style, key, val, true)
631
- } else {
632
- style[key] = normalizeValueWithProperty(val, key)
633
- }
651
+ mergeStyle(key, val)
634
652
  continue
635
653
  }
636
654
 
@@ -649,8 +667,22 @@ export const getSplitStyles: StyleSplitter = (
649
667
  styleToCSS(style)
650
668
  }
651
669
 
670
+ // always do this at the very end to preserve the order strictly (animations, origin)
671
+ // and allow proper merging of all pseudos before applying
672
+ if (flatTransforms) {
673
+ for (const key in flatTransforms) {
674
+ mergeTransform(style, key, flatTransforms[key], true)
675
+ }
676
+ }
677
+
652
678
  // add in defaults if not set:
653
679
  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
+ }
654
686
  if (process.env.TAMAGUI_TARGET === 'web') {
655
687
  for (const key in parentSplitStyles.classNames) {
656
688
  if (key in classNames) continue
@@ -825,9 +857,11 @@ export const getSubStyle = (
825
857
  state: SplitStyleState,
826
858
  conf: TamaguiInternalConfig,
827
859
  languageContext?: FontLanguageProps,
828
- avoidDefaultProps?: boolean
860
+ avoidDefaultProps?: boolean,
861
+ avoidMergeTransform?: boolean
829
862
  ): ViewStyle => {
830
863
  const styleOut: ViewStyle = {}
864
+
831
865
  for (let key in styleIn) {
832
866
  const val = styleIn[key]
833
867
  key = conf.shorthands[key] || key
@@ -842,7 +876,7 @@ export const getSubStyle = (
842
876
  )
843
877
  if (!expanded) continue
844
878
  for (const [skey, sval] of expanded) {
845
- if (skey in stylePropsTransform) {
879
+ if (!avoidMergeTransform && skey in stylePropsTransform) {
846
880
  mergeTransform(styleOut, skey, sval)
847
881
  } else {
848
882
  styleOut[skey] = normalizeValueWithProperty(sval, key)
@@ -23,7 +23,12 @@ export type ViewStyleWithPseudos = ViewOrTextStyle & {
23
23
  focusStyle?: ViewOrTextStyle
24
24
  }
25
25
 
26
- const pseudosOrdered = Object.values(pseudoDescriptors)
26
+ // matching order of the below *0
27
+ const pseudosOrdered = [
28
+ pseudoDescriptors.hoverStyle,
29
+ pseudoDescriptors.pressStyle,
30
+ pseudoDescriptors.focusStyle,
31
+ ]
27
32
 
28
33
  export function getStylesAtomic(stylesIn: ViewStyleWithPseudos) {
29
34
  // performance optimization
@@ -102,7 +107,7 @@ const generateAtomicStyles = (
102
107
  const rules = createAtomicRules(identifier, key, value, pseudo)
103
108
  const styleObject: StyleObject = {
104
109
  property: key,
105
- pseudo: pseudo?.name,
110
+ pseudo: pseudo?.name as any,
106
111
  value,
107
112
  identifier,
108
113
  rules,
@@ -93,18 +93,24 @@ export function reverseMapClassNameToValue(key: string, className: string) {
93
93
  if (!cssRule) {
94
94
  return
95
95
  }
96
- const cssVal = cssRule.replace(/.*:/, '').replace(/;.*/, '')
96
+ const cssVal = cssRule.replace(/.*:/, '').replace(/;.*/, '').trim()
97
97
  let res: any
98
- if (unitlessNumbers[key]) {
98
+ if (cssVal.startsWith('var(')) {
99
+ res = cssVal
100
+ } else if (unitlessNumbers[key]) {
99
101
  res = +cssVal
100
102
  } else if (cssVal.endsWith('px')) {
101
103
  res = +cssVal.replace('px', '')
102
104
  } else {
103
105
  res = cssVal
104
106
  }
105
- if (typeof res === 'string') {
106
- res = res.trim()
107
- }
108
107
  rcache[cssRule] = res
108
+ if (process.env.NODE_ENV === 'development') {
109
+ // ensure we are parsing properly
110
+ if (typeof res === 'number' && isNaN(res)) {
111
+ // eslint-disable-next-line no-console
112
+ console.log(`Tamagui invalid parsed value, NaN:`, { res, cssVal, cssRule, key, className })
113
+ }
114
+ }
109
115
  return res
110
116
  }
@@ -1,18 +1,39 @@
1
1
  // *0 order matches to *1
2
2
 
3
- export const pseudoDescriptors = {
3
+ export const pseudoDescriptors: Record<
4
+ 'hoverStyle' | 'pressStyle' | 'focusStyle' | 'enterStyle' | 'exitStyle',
5
+ PseudoDescriptor
6
+ > = {
4
7
  hoverStyle: {
5
8
  name: 'hover',
6
9
  priority: 1,
7
10
  },
8
11
  pressStyle: {
9
12
  name: 'active',
13
+ stateKey: 'press',
10
14
  priority: 2,
11
15
  },
12
16
  focusStyle: {
13
17
  name: 'focus',
14
18
  priority: 3,
15
19
  },
16
- } as const
20
+ enterStyle: {
21
+ name: 'enter',
22
+ stateKey: 'unmounted',
23
+ priority: 4,
24
+ },
25
+ exitStyle: {
26
+ name: 'exit',
27
+ priority: 5,
28
+ },
29
+ }
30
+
31
+ export type PseudoDescriptor = {
32
+ name: string
33
+ priority: number
34
+ stateKey?: string
35
+ }
17
36
 
18
- export type PseudoDescriptor = typeof pseudoDescriptors[keyof typeof pseudoDescriptors]
37
+ export type PseudoDescriptors = {
38
+ [Key in keyof typeof pseudoDescriptors]: PseudoDescriptor
39
+ }
@@ -13,7 +13,7 @@ export function useShallowSetState<State extends Object>(
13
13
  if (process.env.NODE_ENV === 'development') {
14
14
  if (debug === 'verbose') {
15
15
  // eslint-disable-next-line no-console
16
- console.warn(`update ${debugName}`, next)
16
+ console.log(` ▲ setState ${debugName}`, next)
17
17
  }
18
18
  }
19
19
  return { ...prev, ...next }
package/src/types.tsx CHANGED
@@ -1227,7 +1227,7 @@ export type TamaguiComponentState = {
1227
1227
  press: boolean
1228
1228
  pressIn: boolean
1229
1229
  focus: boolean
1230
- mounted: boolean
1230
+ unmounted: boolean
1231
1231
  mediaState?: null | Record<string, boolean>
1232
1232
  animation?: null | {
1233
1233
  style?: any
@@ -6,7 +6,6 @@ import { TextAncestorContext } from '../contexts/TextAncestorContext'
6
6
  import { useMediaListeners } from '../hooks/useMedia'
7
7
  import type { TamaguiProviderProps } from '../types'
8
8
  import { ThemeProvider } from './ThemeProvider'
9
- import { getConfig } from '..'
10
9
 
11
10
  export function TamaguiProvider({
12
11
  children,
@@ -15,9 +14,11 @@ export function TamaguiProvider({
15
14
  ...themePropsProvider
16
15
  }: TamaguiProviderProps) {
17
16
  if (isRSC) {
18
- const { themes } = getConfig()
19
17
  return (
20
- <span style={{ display: 'contents' }} className={`t_${Object.keys(themes)[0] || 'light'}`}>
18
+ <span
19
+ style={{ display: 'contents' }}
20
+ className={`t_${Object.keys(config.themes)[0] || 'light'}`}
21
+ >
21
22
  {children}
22
23
  </span>
23
24
  )
@@ -41,8 +42,6 @@ export function TamaguiProvider({
41
42
  }, [config, disableInjectCSS])
42
43
  }
43
44
 
44
- const { themes } = getConfig()
45
-
46
45
  return (
47
46
  <ButtonInsideButtonContext.Provider value={false}>
48
47
  <TextAncestorContext.Provider value={false}>
@@ -50,7 +49,7 @@ export function TamaguiProvider({
50
49
  themeClassNameOnRoot={config.themeClassNameOnRoot}
51
50
  disableRootThemeClass={config.disableRootThemeClass}
52
51
  {...themePropsProvider}
53
- defaultTheme={themePropsProvider.defaultTheme ?? Object.keys(themes)[0]}
52
+ defaultTheme={themePropsProvider.defaultTheme ?? Object.keys(config.themes)[0]}
54
53
  >
55
54
  {children}
56
55
  </ThemeProvider>
@@ -20,7 +20,7 @@ declare type StyleSplitter = (props: {
20
20
  }, staticConfig: StaticConfigParsed, theme: ThemeParsed, state: SplitStyleState, parentSplitStyles?: SplitStylesAndProps | null, languageContext?: LanguageContextType, elementType?: string, debug?: DebugProp) => SplitStylesAndProps;
21
21
  export declare const PROP_SPLIT = "-";
22
22
  export declare const getSplitStyles: StyleSplitter;
23
- export declare const getSubStyle: (subKey: string, styleIn: Object, staticConfig: StaticConfigParsed, theme: ThemeParsed, props: any, state: SplitStyleState, conf: TamaguiInternalConfig, languageContext?: FontLanguageProps, avoidDefaultProps?: boolean) => ViewStyle;
23
+ export declare const getSubStyle: (subKey: string, styleIn: Object, staticConfig: StaticConfigParsed, theme: ThemeParsed, props: any, state: SplitStyleState, conf: TamaguiInternalConfig, languageContext?: FontLanguageProps, avoidDefaultProps?: boolean, avoidMergeTransform?: boolean) => ViewStyle;
24
24
  export declare const insertSplitStyles: StyleSplitter;
25
25
  export declare const useSplitStyles: StyleSplitter;
26
26
  export {};
@@ -1,16 +1,10 @@
1
- export declare const pseudoDescriptors: {
2
- readonly hoverStyle: {
3
- readonly name: "hover";
4
- readonly priority: 1;
5
- };
6
- readonly pressStyle: {
7
- readonly name: "active";
8
- readonly priority: 2;
9
- };
10
- readonly focusStyle: {
11
- readonly name: "focus";
12
- readonly priority: 3;
13
- };
1
+ export declare const pseudoDescriptors: Record<'hoverStyle' | 'pressStyle' | 'focusStyle' | 'enterStyle' | 'exitStyle', PseudoDescriptor>;
2
+ export declare type PseudoDescriptor = {
3
+ name: string;
4
+ priority: number;
5
+ stateKey?: string;
6
+ };
7
+ export declare type PseudoDescriptors = {
8
+ [Key in keyof typeof pseudoDescriptors]: PseudoDescriptor;
14
9
  };
15
- export declare type PseudoDescriptor = typeof pseudoDescriptors[keyof typeof pseudoDescriptors];
16
10
  //# sourceMappingURL=pseudoDescriptors.d.ts.map
package/types/types.d.ts CHANGED
@@ -557,7 +557,7 @@ export declare type TamaguiComponentState = {
557
557
  press: boolean;
558
558
  pressIn: boolean;
559
559
  focus: boolean;
560
- mounted: boolean;
560
+ unmounted: boolean;
561
561
  mediaState?: null | Record<string, boolean>;
562
562
  animation?: null | {
563
563
  style?: any;