@tamagui/core 1.0.1-beta.215 → 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.
Files changed (42) hide show
  1. package/dist/cjs/createComponent.js +39 -81
  2. package/dist/cjs/createComponent.js.map +2 -2
  3. package/dist/cjs/createTamagui.js +2 -2
  4. package/dist/cjs/createTamagui.js.map +1 -1
  5. package/dist/cjs/helpers/createPropMapper.js.map +2 -2
  6. package/dist/cjs/helpers/getSplitStyles.js +44 -38
  7. package/dist/cjs/helpers/getSplitStyles.js.map +3 -3
  8. package/dist/cjs/helpers/mergeProps.js.map +2 -2
  9. package/dist/cjs/helpers/normalizeValueWithProperty.js +7 -2
  10. package/dist/cjs/helpers/normalizeValueWithProperty.js.map +2 -2
  11. package/dist/cjs/helpers/useShallowSetState.js.map +2 -2
  12. package/dist/cjs/hooks/useMedia.js +43 -38
  13. package/dist/cjs/hooks/useMedia.js.map +2 -2
  14. package/dist/cjs/views/ThemeInverse.js +1 -2
  15. package/dist/cjs/views/ThemeInverse.js.map +2 -2
  16. package/dist/esm/createComponent.js +41 -87
  17. package/dist/esm/createComponent.js.map +2 -2
  18. package/dist/esm/createTamagui.js +2 -2
  19. package/dist/esm/createTamagui.js.map +1 -1
  20. package/dist/esm/helpers/createPropMapper.js.map +2 -2
  21. package/dist/esm/helpers/getSplitStyles.js +44 -38
  22. package/dist/esm/helpers/getSplitStyles.js.map +3 -3
  23. package/dist/esm/helpers/mergeProps.js.map +2 -2
  24. package/dist/esm/helpers/normalizeValueWithProperty.js +7 -2
  25. package/dist/esm/helpers/normalizeValueWithProperty.js.map +2 -2
  26. package/dist/esm/helpers/useShallowSetState.js.map +2 -2
  27. package/dist/esm/hooks/useMedia.js +44 -39
  28. package/dist/esm/hooks/useMedia.js.map +2 -2
  29. package/dist/esm/views/ThemeInverse.js +1 -2
  30. package/dist/esm/views/ThemeInverse.js.map +2 -2
  31. package/package.json +16 -16
  32. package/src/createComponent.tsx +52 -103
  33. package/src/createTamagui.ts +2 -2
  34. package/src/helpers/createPropMapper.ts +1 -0
  35. package/src/helpers/getSplitStyles.tsx +44 -37
  36. package/src/helpers/mergeProps.ts +7 -7
  37. package/src/helpers/normalizeValueWithProperty.ts +9 -2
  38. package/src/helpers/useShallowSetState.tsx +3 -1
  39. package/src/hooks/useMedia.tsx +49 -41
  40. package/src/views/ThemeInverse.tsx +1 -2
  41. package/types/helpers/mergeProps.d.ts +2 -2
  42. package/types/helpers/useShallowSetState.d.ts +2 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/hooks/useMedia.tsx"],
4
- "sourcesContent": ["import { useIsomorphicLayoutEffect } from '@tamagui/constants'\nimport { MutableRefObject, useEffect, useMemo, useState } from 'react'\n\nimport { getConfig } from '../config'\nimport { createProxy } from '../helpers/createProxy'\nimport { matchMedia } from '../helpers/matchMedia'\nimport {\n MediaQueries,\n MediaQueryKey,\n MediaQueryObject,\n MediaQueryState,\n TamaguiInternalConfig,\n} from '../types'\nimport { useSafeRef } from './useSafeRef'\n\nexport const mediaState: MediaQueryState =\n // development time safeguard\n process.env.NODE_ENV === 'development'\n ? createProxy(\n {},\n {\n get(target, key) {\n if (\n typeof key === 'string' &&\n key[0] === '$' &&\n // dont error on $$typeof\n key[1] !== '$'\n ) {\n throw new Error(`Access mediaState should not use \"$\": ${key}`)\n }\n return Reflect.get(target, key)\n },\n }\n )\n : ({} as any)\n\ntype MediaListener = (next: boolean) => void\n\nconst listeners: { [key: string]: Set<MediaListener> } = {}\n\nexport function addMediaQueryListener(key: MediaQueryKey, cb: MediaListener) {\n if (process.env.NODE_ENV === 'development' && key[0] === '$') {\n // eslint-disable-next-line no-console\n console.warn(`Warning, listening to media queries shouldn't use the \"$\" prefix`)\n }\n listeners[key] = listeners[key] || new Set()\n listeners[key].add(cb)\n return () => removeMediaQueryListener(key, cb)\n}\n\nexport function removeMediaQueryListener(key: MediaQueryKey, cb: MediaListener) {\n listeners[key]?.delete(cb)\n}\n\nexport const mediaQueryConfig: MediaQueries = {}\n\nexport const getMedia = () => {\n return mediaState\n}\n\n// for SSR capture it at time of startup\nlet curState: MediaQueryState\nlet initState: MediaQueryState\nexport const getInitialMediaState = () => {\n return (getConfig().disableSSR ? curState : initState) || {}\n}\n\nlet mediaKeysOrdered: string[]\nexport const getMediaKeyImportance = (key: string) =>\n // + 2 because we set base usedKeys=1 in getSplitStyles and all media go above 1\n mediaKeysOrdered.indexOf(key[0] === '$' ? key.slice(1) : key) + 2\n\nconst dispose = new Set<Function>()\n\nexport const configureMedia = (config: TamaguiInternalConfig) => {\n const { media, mediaQueryDefaultActive } = config\n if (!media) return\n for (const key in media) {\n mediaState[key] = mediaQueryDefaultActive?.[key] || false\n }\n Object.assign(mediaQueryConfig, media)\n curState = { ...mediaState }\n initState = curState\n mediaKeysOrdered = Object.keys(media)\n if (config.disableSSR) {\n setupMediaListeners()\n }\n}\n\nfunction unlisten() {\n dispose.forEach((cb) => cb())\n dispose.clear()\n}\n\n/**\n * Note: This should *not* set the state on the first render!\n * Because to avoid hydration issues SSR must match the server\n * *and then* re-render with the actual media query state.\n */\nlet configuredKey = ''\nfunction setupMediaListeners() {\n // avoid setting up more than once per config\n const nextKey = JSON.stringify(mediaQueryConfig)\n if (nextKey === configuredKey) {\n return\n }\n configuredKey = nextKey\n\n // hmr, undo existing before re-binding\n unlisten()\n\n for (const key in mediaQueryConfig) {\n const str = mediaObjectToString(mediaQueryConfig[key])\n const getMatch = () => matchMedia(str)\n const match = getMatch()\n if (!match) {\n throw new Error('\u26A0\uFE0F No match')\n }\n // react native needs these deprecated apis for now\n match.addListener(update)\n dispose.add(() => match.removeListener(update))\n\n update()\n\n function update() {\n const next = !!getMatch().matches\n if (next === mediaState[key]) return\n mediaState[key] = next\n curState = { ...mediaState }\n const cur = listeners[key]\n if (cur?.size) {\n cur.forEach((cb) => cb(next))\n }\n }\n }\n}\n\nexport function useMediaListeners(config: TamaguiInternalConfig) {\n if (config.disableSSR) return\n useEffect(() => {\n setupMediaListeners()\n return unlisten\n }, [])\n}\n\nexport function useMedia(): {\n [key in MediaQueryKey]: boolean\n} {\n const keys = useSafeRef({} as Record<string, boolean>)\n const [state, setState] = useState<MediaQueryState>(() => getMediaState(initState || {}, keys))\n\n function updateState() {\n setState((prev) => {\n for (const key in keys.current) {\n if (prev[key] !== mediaState[key]) {\n return getMediaState({ ...mediaState }, keys)\n }\n }\n return prev\n })\n }\n\n useIsomorphicLayoutEffect(() => {\n updateState()\n const disposers = Object.keys(keys.current).map((key) =>\n addMediaQueryListener(key, updateState)\n )\n return () => {\n disposers.forEach((cb) => cb())\n }\n }, [keys.current])\n\n return state\n}\n\nfunction getMediaState(state: MediaQueryState, keys: MutableRefObject<Record<string, boolean>>) {\n return new Proxy(state, {\n get(_, key: string) {\n if (!keys.current[key]) {\n keys.current[key] = true\n }\n return Reflect.get(state, key)\n },\n })\n}\n\n/**\n * Useful for more complex components that need access to the currently active props,\n * accounting for the currently active media queries.\n *\n * Use sparingly, is will loop props and trigger re-render on all media queries.\n *\n * */\nexport function useMediaPropsActive<A extends Object>(\n props: A\n): {\n // remove all media\n [Key in keyof A extends `$${string}` ? never : keyof A]?: A[Key]\n} {\n const media = useMedia()\n\n return useMemo(() => {\n const next = {} as A\n const importancesUsed = {}\n const propNames = Object.keys(props)\n\n for (let i = propNames.length - 1; i >= 0; i--) {\n const key = propNames[i]\n const val = props[key]\n if (key[0] === '$') {\n if (!media[key.slice(1)]) {\n continue\n }\n if (val && typeof val === 'object') {\n const subKeys = Object.keys(val)\n for (let j = subKeys.length; j--; j >= 0) {\n const subKey = subKeys[j]\n mergeMediaByImportance(next, subKey, val[subKey], importancesUsed)\n }\n }\n } else {\n mergeMediaByImportance(next, key, val, importancesUsed)\n }\n }\n\n return next\n }, [media, props])\n}\n\nexport function mergeMediaByImportance(\n onto: Record<string, any>,\n key: string,\n value: any,\n importancesUsed: Record<string, number>\n) {\n const importance = getMediaKeyImportance(key)\n if (importancesUsed[key] > importance) {\n return false\n }\n importancesUsed[key] = importance\n onto[key] = value\n return true\n}\n\nfunction camelToHyphen(str: string) {\n return str.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`).toLowerCase()\n}\n\nexport function mediaObjectToString(query: string | MediaQueryObject) {\n if (typeof query === 'string') {\n return query\n }\n return Object.entries(query)\n .map(([feature, value]) => {\n feature = camelToHyphen(feature)\n if (typeof value === 'string') {\n return `(${feature}: ${value})`\n }\n if (typeof value === 'number' && /[height|width]$/.test(feature)) {\n value = `${value}px`\n }\n return `(${feature}: ${value})`\n })\n .join(' and ')\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { useIsomorphicLayoutEffect } from '@tamagui/constants'\nimport { MutableRefObject, useEffect, useMemo, useState, useSyncExternalStore } from 'react'\n\nimport { getConfig } from '../config'\nimport { createProxy } from '../helpers/createProxy'\nimport { matchMedia } from '../helpers/matchMedia'\nimport {\n MediaQueries,\n MediaQueryKey,\n MediaQueryObject,\n MediaQueryState,\n TamaguiInternalConfig,\n} from '../types'\nimport { useSafeRef } from './useSafeRef'\n\nexport const mediaState: MediaQueryState =\n // development time safeguard\n process.env.NODE_ENV === 'development'\n ? createProxy(\n {},\n {\n get(target, key) {\n if (\n typeof key === 'string' &&\n key[0] === '$' &&\n // dont error on $$typeof\n key[1] !== '$'\n ) {\n throw new Error(`Access mediaState should not use \"$\": ${key}`)\n }\n return Reflect.get(target, key)\n },\n }\n )\n : ({} as any)\n\ntype MediaListener = (next: boolean) => void\n\nconst listeners: { [key: string]: Set<MediaListener> } = {}\n\nexport function addMediaQueryListener(key: MediaQueryKey, cb: MediaListener) {\n if (process.env.NODE_ENV === 'development' && key[0] === '$') {\n // eslint-disable-next-line no-console\n console.warn(`Warning, listening to media queries shouldn't use the \"$\" prefix`)\n }\n listeners[key] = listeners[key] || new Set()\n listeners[key].add(cb)\n return () => removeMediaQueryListener(key, cb)\n}\n\nexport function removeMediaQueryListener(key: MediaQueryKey, cb: MediaListener) {\n listeners[key]?.delete(cb)\n}\n\nexport const mediaQueryConfig: MediaQueries = {}\n\nexport const getMedia = () => mediaState\n\n// for SSR capture it at time of startup\nlet initState: MediaQueryState\nexport const getInitialMediaState = () => {\n return (getConfig().disableSSR ? mediaState : initState) || {}\n}\n\nlet mediaKeysOrdered: string[]\nexport const getMediaKeyImportance = (key: string) =>\n // + 2 because we set base usedKeys=1 in getSplitStyles and all media go above 1\n mediaKeysOrdered.indexOf(key[0] === '$' ? key.slice(1) : key) + 2\n\nconst dispose = new Set<Function>()\n\nexport const configureMedia = (config: TamaguiInternalConfig) => {\n const { media, mediaQueryDefaultActive } = config\n if (!media) return\n for (const key in media) {\n mediaState[key] = mediaQueryDefaultActive?.[key] || false\n }\n Object.assign(mediaQueryConfig, media)\n initState = { ...mediaState }\n updateCurrentState()\n mediaKeysOrdered = Object.keys(media)\n if (config.disableSSR) {\n setupMediaListeners()\n }\n}\n\nfunction unlisten() {\n dispose.forEach((cb) => cb())\n dispose.clear()\n}\n\n/**\n * Note: This should *not* set the state on the first render!\n * Because to avoid hydration issues SSR must match the server\n * *and then* re-render with the actual media query state.\n */\nlet configuredKey = ''\nfunction setupMediaListeners() {\n // avoid setting up more than once per config\n const nextKey = JSON.stringify(mediaQueryConfig)\n if (nextKey === configuredKey) {\n return\n }\n configuredKey = nextKey\n\n // hmr, undo existing before re-binding\n unlisten()\n\n for (const key in mediaQueryConfig) {\n const str = mediaObjectToString(mediaQueryConfig[key])\n const getMatch = () => matchMedia(str)\n const match = getMatch()\n if (!match) {\n throw new Error('\u26A0\uFE0F No match')\n }\n // react native needs these deprecated apis for now\n match.addListener(update)\n dispose.add(() => match.removeListener(update))\n\n update()\n\n function update() {\n const next = !!getMatch().matches\n if (next === mediaState[key]) return\n mediaState[key] = next\n updateCurrentState()\n const cur = listeners[key]\n if (cur?.size) {\n cur.forEach((cb) => cb(next))\n }\n }\n }\n}\n\nexport function useMediaListeners(config: TamaguiInternalConfig) {\n if (config.disableSSR) return\n useEffect(() => {\n setupMediaListeners()\n return unlisten\n }, [])\n}\n\nconst nextTick = process.nextTick || setImmediate\nconst currentStateListeners = new Set<any>()\nlet isUpdating = false\nfunction updateCurrentState() {\n if (isUpdating) return\n isUpdating = true\n nextTick(() => {\n currentStateListeners.forEach((cb) => cb(mediaState))\n isUpdating = false\n })\n}\nfunction subscribe(subscriber: any) {\n currentStateListeners.add(subscriber)\n return () => currentStateListeners.delete(subscriber)\n}\n\ntype MediaKeysState = {\n [key: string]: any\n}\n\nexport function useMedia(): {\n [key in MediaQueryKey]: boolean\n} {\n const keys = useSafeRef<MediaKeysState>({ prev: initState })\n\n const state = useSyncExternalStore<MediaQueryState>(\n subscribe,\n () => {\n const { prev, ...curKeys } = keys.current\n const shouldUpdate = !prev || Object.keys(curKeys).some((k) => mediaState[k] !== prev[k])\n if (shouldUpdate) {\n const next = { ...mediaState }\n keys.current.prev = next\n return next\n }\n return prev\n },\n () => initState\n )\n\n return useMemo(() => {\n return new Proxy(state, {\n get(_, key: string) {\n if (!keys.current[key]) {\n keys.current[key] = true\n }\n return Reflect.get(state, key)\n },\n })\n }, [state])\n}\n\n/**\n * Useful for more complex components that need access to the currently active props,\n * accounting for the currently active media queries.\n *\n * Use sparingly, is will loop props and trigger re-render on all media queries.\n *\n * */\nexport function useMediaPropsActive<A extends Object>(\n props: A\n): {\n // remove all media\n [Key in keyof A extends `$${string}` ? never : keyof A]?: A[Key]\n} {\n const media = useMedia()\n\n return useMemo(() => {\n const next = {} as A\n const importancesUsed = {}\n const propNames = Object.keys(props)\n\n for (let i = propNames.length - 1; i >= 0; i--) {\n const key = propNames[i]\n const val = props[key]\n if (key[0] === '$') {\n if (!media[key.slice(1)]) {\n continue\n }\n if (val && typeof val === 'object') {\n const subKeys = Object.keys(val)\n for (let j = subKeys.length; j--; j >= 0) {\n const subKey = subKeys[j]\n mergeMediaByImportance(next, subKey, val[subKey], importancesUsed)\n }\n }\n } else {\n mergeMediaByImportance(next, key, val, importancesUsed)\n }\n }\n\n return next\n }, [media, props])\n}\n\nexport function mergeMediaByImportance(\n onto: Record<string, any>,\n key: string,\n value: any,\n importancesUsed: Record<string, number>\n) {\n const importance = getMediaKeyImportance(key)\n if (importancesUsed[key] > importance) {\n return false\n }\n importancesUsed[key] = importance\n onto[key] = value\n return true\n}\n\nfunction camelToHyphen(str: string) {\n return str.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`).toLowerCase()\n}\n\nexport function mediaObjectToString(query: string | MediaQueryObject) {\n if (typeof query === 'string') {\n return query\n }\n return Object.entries(query)\n .map(([feature, value]) => {\n feature = camelToHyphen(feature)\n if (typeof value === 'string') {\n return `(${feature}: ${value})`\n }\n if (typeof value === 'number' && /[height|width]$/.test(feature)) {\n value = `${value}px`\n }\n return `(${feature}: ${value})`\n })\n .join(' and ')\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["update"]
7
7
  }
@@ -13,8 +13,7 @@ const ThemeInverse = ({
13
13
  useIsomorphicLayoutEffect(() => {
14
14
  if (themeName.startsWith("dark")) {
15
15
  setName("light");
16
- }
17
- if (themeName.startsWith("light")) {
16
+ } else if (themeName.startsWith("light")) {
18
17
  setName("dark");
19
18
  }
20
19
  }, [defaultTheme, themeName]);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/views/ThemeInverse.tsx"],
4
- "sourcesContent": ["import { useIsomorphicLayoutEffect } from '@tamagui/constants'\nimport React, { useState } from 'react'\n\nimport { useDefaultThemeName, useThemeName } from '../hooks/useTheme'\nimport { Theme } from './Theme'\n\nexport const ThemeInverse = ({\n children,\n disable,\n}: {\n children: React.ReactNode\n disable?: boolean\n}) => {\n const themeName = useThemeName()\n const defaultTheme = useDefaultThemeName()\n const [name, setName] = useState<null | string>(null)\n\n // ssr\n useIsomorphicLayoutEffect(() => {\n if (themeName.startsWith('dark')) {\n setName('light')\n }\n if (themeName.startsWith('light')) {\n setName('dark')\n }\n }, [defaultTheme, themeName])\n\n if (disable) {\n return children as JSX.Element\n }\n\n return <Theme name={name}>{children}</Theme>\n}\n"],
5
- "mappings": "AA+BS;AA/BT,SAAS,iCAAiC;AAC1C,SAAgB,gBAAgB;AAEhC,SAAS,qBAAqB,oBAAoB;AAClD,SAAS,aAAa;AAEf,MAAM,eAAe,CAAC;AAAA,EAC3B;AAAA,EACA;AACF,MAGM;AACJ,QAAM,YAAY,aAAa;AAC/B,QAAM,eAAe,oBAAoB;AACzC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAwB,IAAI;AAGpD,4BAA0B,MAAM;AAC9B,QAAI,UAAU,WAAW,MAAM,GAAG;AAChC,cAAQ,OAAO;AAAA,IACjB;AACA,QAAI,UAAU,WAAW,OAAO,GAAG;AACjC,cAAQ,MAAM;AAAA,IAChB;AAAA,EACF,GAAG,CAAC,cAAc,SAAS,CAAC;AAE5B,MAAI,SAAS;AACX,WAAO;AAAA,EACT;AAEA,SAAO,oBAAC;AAAA,IAAM;AAAA,IAAa;AAAA,GAAS;AACtC;",
4
+ "sourcesContent": ["import { useIsomorphicLayoutEffect } from '@tamagui/constants'\nimport React, { useState } from 'react'\n\nimport { useDefaultThemeName, useThemeName } from '../hooks/useTheme'\nimport { Theme } from './Theme'\n\nexport const ThemeInverse = ({\n children,\n disable,\n}: {\n children: React.ReactNode\n disable?: boolean\n}) => {\n const themeName = useThemeName()\n const defaultTheme = useDefaultThemeName()\n const [name, setName] = useState<null | string>(null)\n\n // ssr\n useIsomorphicLayoutEffect(() => {\n if (themeName.startsWith('dark')) {\n setName('light')\n } else if (themeName.startsWith('light')) {\n setName('dark')\n }\n }, [defaultTheme, themeName])\n\n if (disable) {\n return children as JSX.Element\n }\n\n return <Theme name={name}>{children}</Theme>\n}\n"],
5
+ "mappings": "AA8BS;AA9BT,SAAS,iCAAiC;AAC1C,SAAgB,gBAAgB;AAEhC,SAAS,qBAAqB,oBAAoB;AAClD,SAAS,aAAa;AAEf,MAAM,eAAe,CAAC;AAAA,EAC3B;AAAA,EACA;AACF,MAGM;AACJ,QAAM,YAAY,aAAa;AAC/B,QAAM,eAAe,oBAAoB;AACzC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAwB,IAAI;AAGpD,4BAA0B,MAAM;AAC9B,QAAI,UAAU,WAAW,MAAM,GAAG;AAChC,cAAQ,OAAO;AAAA,IACjB,WAAW,UAAU,WAAW,OAAO,GAAG;AACxC,cAAQ,MAAM;AAAA,IAChB;AAAA,EACF,GAAG,CAAC,cAAc,SAAS,CAAC;AAE5B,MAAI,SAAS;AACX,WAAO;AAAA,EACT;AAEA,SAAO,oBAAC;AAAA,IAAM;AAAA,IAAa;AAAA,GAAS;AACtC;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tamagui/core",
3
- "version": "1.0.1-beta.215",
3
+ "version": "1.0.1-beta.217",
4
4
  "source": "src/index.ts",
5
5
  "main": "dist/cjs",
6
6
  "module": "dist/esm",
@@ -28,30 +28,30 @@
28
28
  ],
29
29
  "dependencies": {
30
30
  "@expo/match-media": "^0.3.0",
31
- "@tamagui/compose-refs": "^1.0.1-beta.215",
32
- "@tamagui/constants": "^1.0.1-beta.215",
33
- "@tamagui/helpers": "^1.0.1-beta.215",
34
- "@tamagui/normalize-css-color-lite": "^1.0.1-beta.215",
35
- "@tamagui/react-native-use-pressable": "^1.0.1-beta.215",
36
- "@tamagui/react-native-use-responder-events": "^1.0.1-beta.215",
37
- "@tamagui/types-react-native": "^1.0.1-beta.215",
38
- "@tamagui/use-did-finish-ssr": "^1.0.1-beta.215",
39
- "@tamagui/use-event": "^1.0.1-beta.215",
40
- "@tamagui/use-force-update": "^1.0.1-beta.215"
31
+ "@tamagui/compose-refs": "^1.0.1-beta.217",
32
+ "@tamagui/constants": "^1.0.1-beta.217",
33
+ "@tamagui/helpers": "^1.0.1-beta.217",
34
+ "@tamagui/normalize-css-color-lite": "^1.0.1-beta.217",
35
+ "@tamagui/react-native-use-pressable": "^1.0.1-beta.217",
36
+ "@tamagui/react-native-use-responder-events": "^1.0.1-beta.217",
37
+ "@tamagui/types-react-native": "^1.0.1-beta.217",
38
+ "@tamagui/use-did-finish-ssr": "^1.0.1-beta.217",
39
+ "@tamagui/use-event": "^1.0.1-beta.217",
40
+ "@tamagui/use-force-update": "^1.0.1-beta.217"
41
41
  },
42
42
  "peerDependencies": {
43
- "react": "*",
44
- "react-dom": "*"
43
+ "react": ">=18",
44
+ "react-dom": ">=18"
45
45
  },
46
46
  "devDependencies": {
47
- "@tamagui/build": "^1.0.1-beta.215",
47
+ "@tamagui/build": "^1.0.1-beta.217",
48
48
  "@types/node": "^16.11.9",
49
49
  "@types/react": "^18.0.15",
50
50
  "@types/react-native": "^0.69.2",
51
51
  "csstype": "^3.0.10",
52
52
  "esbuild": "^0.15.11",
53
- "react": "*",
54
- "react-dom": "*",
53
+ "react": ">=18",
54
+ "react-dom": ">=18",
55
55
  "typescript": "^4.7.4",
56
56
  "vitest": "^0.24.3"
57
57
  },
@@ -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,12 +29,7 @@ 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'
@@ -45,6 +40,7 @@ import { addMediaQueryListener, getInitialMediaState } from './hooks/useMedia'
45
40
  import { useServerRef, useServerState } from './hooks/useServerHooks'
46
41
  import { getThemeManager, useTheme } from './hooks/useTheme'
47
42
  import {
43
+ DebugProp,
48
44
  SpaceDirection,
49
45
  SpaceTokens,
50
46
  SpacerProps,
@@ -139,7 +135,6 @@ export function createComponent<
139
135
  let defaultNativeStyle: any
140
136
  let tamaguiDefaultProps: any
141
137
  let defaultTag: string | undefined
142
- let initialSplitStyles: SplitStyleResult
143
138
 
144
139
  // see onConfiguredOnce below which attaches a name then to this component
145
140
  const component = forwardRef<Ref, ComponentPropTypes>((propsIn: any, forwardedRef) => {
@@ -156,7 +151,7 @@ export function createComponent<
156
151
 
157
152
  // time`mergeProps`
158
153
 
159
- const debugProp = props['debug']
154
+ const debugProp = props['debug'] as DebugProp
160
155
  const { Component, isText, isZStack } = staticConfig
161
156
  const componentName = props.componentName || staticConfig.componentName
162
157
  const componentClassName = props.asChild
@@ -193,7 +188,7 @@ export function createComponent<
193
188
  )
194
189
 
195
190
  if (process.env.NODE_ENV === 'development') {
196
- if (props['debug']) {
191
+ if (debugProp) {
197
192
  const name = `${
198
193
  componentName || Component?.displayName || Component?.name || '[Unnamed Component]'
199
194
  }`
@@ -202,8 +197,18 @@ export function createComponent<
202
197
  const banner = `${name}${dataIs ? ` ${dataIs}` : ''} ${type}`
203
198
  // eslint-disable-next-line no-console
204
199
  console.group(`%c ${banner}`, 'background: yellow;')
205
- // eslint-disable-next-line no-console
206
- console.log(`state`, state)
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
+ }
207
212
  }
208
213
  }
209
214
 
@@ -253,19 +258,18 @@ export function createComponent<
253
258
 
254
259
  // time`setupStateConf`
255
260
 
256
- const splitStyleState: SplitStyleState = {
257
- ...state,
258
- noClassNames,
259
- dynamicStylesInline: noClassNames,
260
- hasTextAncestor,
261
- resolveVariablesAs: 'value',
262
- }
263
261
  const splitStyles = useSplitStyles(
264
262
  props,
265
263
  staticConfig,
266
264
  theme,
267
- splitStyleState,
268
- props.asChild ? null : initialSplitStyles,
265
+ {
266
+ ...state,
267
+ noClassNames,
268
+ dynamicStylesInline: noClassNames,
269
+ hasTextAncestor,
270
+ resolveVariablesAs: 'value',
271
+ },
272
+ null,
269
273
  languageContext || undefined,
270
274
  elementType,
271
275
  debugProp
@@ -592,7 +596,7 @@ export function createComponent<
592
596
  }, [unPress])
593
597
  }
594
598
 
595
- let styles: any[]
599
+ let styles: Record<string, any>[]
596
600
 
597
601
  if (isStringElement && shouldAvoidClasses && !shouldForcePseudo) {
598
602
  styles = {
@@ -606,11 +610,7 @@ export function createComponent<
606
610
  // ugly but for now...
607
611
  if (shouldForcePseudo) {
608
612
  const next = {}
609
- for (const style of styles) {
610
- if (style) {
611
- Object.assign(next, style)
612
- }
613
- }
613
+ styles.forEach((style) => Object.assign(next, style))
614
614
  // @ts-ignore
615
615
  Object.assign(splitStyles.style, next)
616
616
  }
@@ -686,16 +686,11 @@ export function createComponent<
686
686
  viewProps.style = styles
687
687
  }
688
688
 
689
- // TODO need to loop active variants and see if they have matchin pseudos and apply as well
690
- const initialPseudos = initialSplitStyles?.pseudos
691
- const runtimePressStyle = noClassNames && (pseudos?.pressStyle || initialPseudos?.pressStyle)
689
+ const runtimePressStyle = !disabled && noClassNames && pseudos?.pressStyle
692
690
  const attachPress = !!(runtimePressStyle || onPress || onPressOut || onPressIn || onClick)
693
-
694
- const isHoverable = isWeb
695
- const runtimeHoverStyle = noClassNames && (pseudos?.hoverStyle || initialPseudos.hoverStyle)
696
- const attachHover =
697
- isHoverable &&
698
- !!(runtimeHoverStyle || onHoverIn || onHoverOut || onMouseEnter || onMouseLeave)
691
+ const runtimeHoverStyle = !disabled && noClassNames && pseudos?.hoverStyle
692
+ const isHoverable =
693
+ isWeb && !!(runtimeHoverStyle || onHoverIn || onHoverOut || onMouseEnter || onMouseLeave)
699
694
 
700
695
  const handlesPressEvents = !isWeb && !asChild
701
696
 
@@ -705,7 +700,7 @@ export function createComponent<
705
700
  ? false
706
701
  : Boolean(
707
702
  attachPress ||
708
- attachHover ||
703
+ isHoverable ||
709
704
  'pressStyle' in props ||
710
705
  'onPress' in props ||
711
706
  'onPressIn' in props ||
@@ -728,28 +723,28 @@ export function createComponent<
728
723
  onMouseUp?.(e)
729
724
  }
730
725
  : undefined,
731
- ...(attachHover && {
732
- onMouseEnter: attachHover
726
+ ...(isHoverable && {
727
+ onMouseEnter: isHoverable
733
728
  ? (e) => {
734
729
  const next: Partial<typeof state> = {}
735
- if (attachHover) {
730
+ if (isHoverable) {
736
731
  next.hover = true
737
732
  }
738
733
  if (state.pressIn) {
739
734
  next.press = true
740
735
  }
741
- if (attachHover || state.pressIn) {
736
+ if (isHoverable || state.pressIn) {
742
737
  setStateShallow(next)
743
738
  }
744
739
  onHoverIn?.(e)
745
740
  onMouseEnter?.(e)
746
741
  }
747
742
  : undefined,
748
- onMouseLeave: attachHover
743
+ onMouseLeave: isHoverable
749
744
  ? (e) => {
750
745
  const next: Partial<typeof state> = {}
751
746
  mouseUps.add(unPress)
752
- if (attachHover) {
747
+ if (isHoverable) {
753
748
  next.hover = false
754
749
  }
755
750
  if (state.pressIn) {
@@ -854,7 +849,7 @@ export function createComponent<
854
849
  // EVENTS native
855
850
  if (process.env.TAMAGUI_TARGET === 'native') {
856
851
  // add focus events
857
- const attachFocus = !!(pseudos.focusStyle || (initialPseudos && initialPseudos.focusStyle))
852
+ const attachFocus = !!pseudos.focusStyle
858
853
  if (attachFocus) {
859
854
  viewProps.onFocus = mergeEvent(viewProps.onFocus, () => {
860
855
  setStateShallow({ focus: true })
@@ -916,7 +911,7 @@ export function createComponent<
916
911
  if (typeof window !== 'undefined') {
917
912
  // prettier-ignore
918
913
  // eslint-disable-next-line no-console
919
- 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, initialSplitStyles, ...(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) })
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) })
920
915
  }
921
916
  // eslint-disable-next-line no-console
922
917
  console.groupEnd()
@@ -993,48 +988,22 @@ export function createComponent<
993
988
  const debug = defaultPropsIn['debug']
994
989
 
995
990
  // remove all classNames
996
- const [ourProps, ourClassNames] = mergeProps(defaultPropsIn, {}, true)
991
+ const [ourProps, ourClassNames] = mergeProps(defaultPropsIn, {})
997
992
 
998
993
  if (ourProps.tag) {
999
994
  defaultTag = ourProps.tag
1000
995
  }
1001
996
 
1002
997
  const noClassNames = !staticConfig.acceptsClassName
1003
-
1004
- initialSplitStyles = insertSplitStyles(
1005
- ourProps,
1006
- staticConfig,
1007
- initialTheme,
1008
- {
1009
- unmounted: false,
1010
- hover: false,
1011
- press: false,
1012
- pressIn: false,
1013
- focus: false,
1014
- resolveVariablesAs: 'both',
1015
- noClassNames,
1016
- },
1017
- undefined,
1018
- undefined,
1019
- debug
1020
- )
998
+ const { name, variants, defaultVariants, ...restProps } = ourProps
1021
999
 
1022
1000
  // must preserve prop order
1023
1001
  // leave out className because we handle that already with initialSplitStyles.classNames
1024
1002
  // otherwise it confuses variant functions getting className props
1025
- const [defaults, defaultsClassnames] = mergeProps(
1026
- component.defaultProps as any,
1027
- { ...initialSplitStyles.pseudos, ...initialSplitStyles.viewProps },
1028
- true
1029
- // conf.inverseShorthands
1030
- )
1031
-
1032
- // avoid passing className props to variants
1033
- initialSplitStyles.classNames = {
1034
- ...defaultsClassnames,
1035
- ...initialSplitStyles.classNames,
1036
- ...ourClassNames,
1037
- }
1003
+ const [defaults, defaultsClassnames] = mergeProps(component.defaultProps as any, {
1004
+ ...defaultVariants,
1005
+ ...restProps,
1006
+ })
1038
1007
 
1039
1008
  defaultNativeStyle = {}
1040
1009
 
@@ -1053,29 +1022,15 @@ export function createComponent<
1053
1022
  }
1054
1023
  }
1055
1024
 
1056
- if (Object.keys(defaults).length) {
1057
- tamaguiDefaultProps = defaults
1058
- }
1025
+ // set to global
1026
+ tamaguiDefaultProps = defaults
1059
1027
 
1060
1028
  // add debug logs
1061
1029
  if (process.env.NODE_ENV === 'development' && debug) {
1062
1030
  if (process.env.IS_STATIC !== 'is_static') {
1031
+ // prettier-ignore
1063
1032
  // eslint-disable-next-line no-console
1064
- console.log(`🐛 [${staticConfig.componentName || 'Component'}]`, {
1065
- staticConfig,
1066
- initialSplitStyles,
1067
- tamaguiDefaultProps,
1068
- defaultNativeStyle,
1069
- defaults,
1070
- defaultPropsIn,
1071
- defaultPropsKeyOrder: Object.keys(staticConfig.defaultProps),
1072
- defaultPropsInKeyOrder: Object.keys(defaultPropsIn).map((k) => [k, defaultPropsIn[k]]),
1073
- ourProps,
1074
- ourClassNames,
1075
- defaultsClassnames,
1076
- defaultTag,
1077
- noClassNames,
1078
- })
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, })
1079
1034
  }
1080
1035
  }
1081
1036
  })
@@ -1197,7 +1152,6 @@ export function spacedChildren({
1197
1152
  for (const [index, child] of childrenList.entries()) {
1198
1153
  const isEmpty =
1199
1154
  child === null || child === undefined || (Array.isArray(child) && child.length === 0)
1200
-
1201
1155
  // push them all, but wrap some in Fragment
1202
1156
  if (isEmpty || !child || (child['key'] && !isZStack)) {
1203
1157
  final.push(child)
@@ -1208,14 +1162,9 @@ export function spacedChildren({
1208
1162
  }
1209
1163
 
1210
1164
  // first child unspaced avoid insert space
1211
- if (isUnspaced(child) && index === 0) {
1212
- continue
1213
- }
1214
-
1165
+ if (isUnspaced(child) && index === 0) continue
1215
1166
  // no spacing on ZStack
1216
- if (isZStack) {
1217
- continue
1218
- }
1167
+ if (isZStack) continue
1219
1168
 
1220
1169
  const next = childrenList[index + 1]
1221
1170
 
@@ -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 { display: inline-flex; }
199
- ._dsp_contents { display: 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
  `,
@@ -351,6 +351,7 @@ const resolveTokensAndVariants: StyleResolver = (
351
351
  }
352
352
  }
353
353
  }
354
+
354
355
  return res
355
356
  }
356
357
 
@@ -196,21 +196,9 @@ export const getSplitStyles: StyleSplitter = (
196
196
  const shouldDoClasses =
197
197
  staticConfig.acceptsClassName && (isWeb || IS_STATIC) && !state.noClassNames
198
198
 
199
- let style: ViewStyle = {}
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('current', { ...style })
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
- for (const key in parentSplitStyles.classNames) {
688
- if (key in classNames) continue
689
- if (key in style) continue
690
- const val = parentSplitStyles.classNames[key]
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