@tamagui/core 1.0.1-beta.192 → 1.0.1-beta.194
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Tamagui.js +4 -2
- package/dist/cjs/Tamagui.js.map +2 -2
- package/dist/cjs/config.js +1 -2
- package/dist/cjs/config.js.map +2 -2
- package/dist/cjs/constants/constants.js +13 -8
- package/dist/cjs/constants/constants.js.map +2 -2
- package/dist/cjs/contexts/TextAncestorContext.js +3 -16
- package/dist/cjs/contexts/TextAncestorContext.js.map +3 -3
- package/dist/cjs/createComponent.js +196 -284
- package/dist/cjs/createComponent.js.map +2 -2
- package/dist/cjs/createTamagui.js +15 -16
- package/dist/cjs/createTamagui.js.map +3 -3
- package/dist/cjs/createVariable.js +1 -2
- package/dist/cjs/createVariable.js.map +2 -2
- package/dist/cjs/helpers/ThemeManager.js +7 -14
- package/dist/cjs/helpers/ThemeManager.js.map +2 -2
- package/dist/cjs/helpers/{createShallowUpdate.js → cache.js} +20 -21
- package/dist/cjs/helpers/cache.js.map +7 -0
- package/dist/cjs/helpers/createMediaStyle.js +14 -8
- package/dist/cjs/helpers/createMediaStyle.js.map +2 -2
- package/dist/cjs/helpers/extendStaticConfig.js +0 -1
- package/dist/cjs/helpers/extendStaticConfig.js.map +2 -2
- package/dist/cjs/helpers/getSplitStyles.js +214 -94
- package/dist/cjs/helpers/getSplitStyles.js.map +3 -3
- package/dist/cjs/helpers/getStylesAtomic.js +16 -36
- package/dist/cjs/helpers/getStylesAtomic.js.map +3 -3
- package/dist/cjs/helpers/getVariantExtras.js +2 -1
- package/dist/cjs/helpers/getVariantExtras.js.map +2 -2
- package/dist/cjs/helpers/insertStyleRule.js +14 -6
- package/dist/cjs/helpers/insertStyleRule.js.map +2 -2
- package/dist/cjs/helpers/matchMedia.js.map +2 -2
- package/dist/cjs/helpers/mergeTransform.js.map +1 -1
- package/dist/cjs/helpers/normalizeValueWithProperty.js +32 -2
- package/dist/cjs/helpers/normalizeValueWithProperty.js.map +2 -2
- package/dist/cjs/helpers/proxyThemeVariables.js +2 -7
- package/dist/cjs/helpers/proxyThemeVariables.js.map +2 -2
- package/dist/cjs/helpers/useShallowSetState.js.map +2 -2
- package/dist/cjs/hooks/getThemeUnwrapped.js +1 -3
- package/dist/cjs/hooks/getThemeUnwrapped.js.map +2 -2
- package/dist/cjs/hooks/useElementLayout.js +92 -0
- package/dist/cjs/hooks/useElementLayout.js.map +7 -0
- package/dist/cjs/hooks/useIsTouchDevice.js +2 -10
- package/dist/cjs/hooks/useIsTouchDevice.js.map +2 -2
- package/dist/cjs/hooks/useMedia.js +79 -85
- package/dist/cjs/hooks/useMedia.js.map +2 -2
- package/dist/cjs/hooks/useMedia.test.js +2 -0
- package/dist/cjs/{helpers/validate.js.map → hooks/useMedia.test.js.map} +0 -0
- package/dist/cjs/hooks/usePressablePressResponder.js +370 -0
- package/dist/cjs/hooks/usePressablePressResponder.js.map +7 -0
- package/dist/cjs/hooks/useSafeRef.js +13 -15
- package/dist/cjs/hooks/useSafeRef.js.map +2 -2
- package/dist/cjs/hooks/useTheme.js +5 -5
- package/dist/cjs/hooks/useTheme.js.map +2 -2
- package/dist/cjs/index.js +1 -17
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/static.js +0 -20
- package/dist/cjs/static.js.map +2 -2
- package/dist/cjs/styled.js +4 -22
- package/dist/cjs/styled.js.map +2 -2
- package/dist/cjs/types.js.map +1 -1
- package/dist/cjs/{hooks/useIsSSR.js → views/AbsoluteFill.js} +18 -23
- package/dist/cjs/views/AbsoluteFill.js.map +7 -0
- package/dist/cjs/views/AbsoluteFill.native.js +45 -0
- package/dist/cjs/views/AbsoluteFill.native.js.map +7 -0
- package/dist/cjs/views/FontLanguage.native.js.map +2 -2
- package/dist/cjs/views/Stack.js.map +1 -1
- package/dist/cjs/views/TamaguiProvider.js +3 -2
- package/dist/cjs/views/TamaguiProvider.js.map +2 -2
- package/dist/cjs/views/Text.js.map +1 -1
- package/dist/cjs/views/ThemeReset.js +10 -10
- package/dist/cjs/views/ThemeReset.js.map +2 -2
- package/dist/esm/Tamagui.js +4 -2
- package/dist/esm/Tamagui.js.map +2 -2
- package/dist/esm/config.js +1 -2
- package/dist/esm/config.js.map +2 -2
- package/dist/esm/constants/constants.js +11 -7
- package/dist/esm/constants/constants.js.map +2 -2
- package/dist/esm/contexts/TextAncestorContext.js +2 -13
- package/dist/esm/contexts/TextAncestorContext.js.map +2 -2
- package/dist/esm/createComponent.js +195 -286
- package/dist/esm/createComponent.js.map +2 -2
- package/dist/esm/createTamagui.js +15 -16
- package/dist/esm/createTamagui.js.map +3 -3
- package/dist/esm/createVariable.js +1 -2
- package/dist/esm/createVariable.js.map +2 -2
- package/dist/esm/helpers/ThemeManager.js +7 -14
- package/dist/esm/helpers/ThemeManager.js.map +2 -2
- package/dist/esm/helpers/cache.js +18 -0
- package/dist/esm/helpers/cache.js.map +7 -0
- package/dist/esm/helpers/createMediaStyle.js +14 -8
- package/dist/esm/helpers/createMediaStyle.js.map +2 -2
- package/dist/esm/helpers/extendStaticConfig.js +0 -1
- package/dist/esm/helpers/extendStaticConfig.js.map +2 -2
- package/dist/esm/helpers/getSplitStyles.js +223 -95
- package/dist/esm/helpers/getSplitStyles.js.map +3 -3
- package/dist/esm/helpers/getStylesAtomic.js +13 -26
- package/dist/esm/helpers/getStylesAtomic.js.map +2 -2
- package/dist/esm/helpers/getVariantExtras.js +2 -1
- package/dist/esm/helpers/getVariantExtras.js.map +2 -2
- package/dist/esm/helpers/insertStyleRule.js +14 -6
- package/dist/esm/helpers/insertStyleRule.js.map +2 -2
- package/dist/esm/helpers/matchMedia.js.map +2 -2
- package/dist/esm/helpers/mergeTransform.js.map +1 -1
- package/dist/esm/helpers/normalizeValueWithProperty.js +30 -1
- package/dist/esm/helpers/normalizeValueWithProperty.js.map +2 -2
- package/dist/esm/helpers/proxyThemeVariables.js +2 -7
- package/dist/esm/helpers/proxyThemeVariables.js.map +2 -2
- package/dist/esm/helpers/useShallowSetState.js.map +2 -2
- package/dist/esm/hooks/getThemeUnwrapped.js +1 -3
- package/dist/esm/hooks/getThemeUnwrapped.js.map +2 -2
- package/dist/esm/hooks/useElementLayout.js +66 -0
- package/dist/esm/hooks/useElementLayout.js.map +7 -0
- package/dist/esm/hooks/useIsTouchDevice.js +3 -11
- package/dist/esm/hooks/useIsTouchDevice.js.map +2 -2
- package/dist/esm/hooks/useMedia.js +76 -84
- package/dist/esm/hooks/useMedia.js.map +2 -2
- package/dist/esm/hooks/useMedia.test.js +1 -0
- package/dist/esm/{helpers/validate.js.map → hooks/useMedia.test.js.map} +0 -0
- package/dist/esm/hooks/usePressablePressResponder.js +346 -0
- package/dist/esm/hooks/usePressablePressResponder.js.map +7 -0
- package/dist/esm/hooks/useSafeRef.js +13 -15
- package/dist/esm/hooks/useSafeRef.js.map +2 -2
- package/dist/esm/hooks/useTheme.js +5 -5
- package/dist/esm/hooks/useTheme.js.map +2 -2
- package/dist/esm/index.js +1 -14
- package/dist/esm/index.js.map +2 -2
- package/dist/esm/static.js +0 -14
- package/dist/esm/static.js.map +2 -2
- package/dist/esm/styled.js +4 -22
- package/dist/esm/styled.js.map +2 -2
- package/dist/esm/views/AbsoluteFill.js +17 -0
- package/dist/esm/views/AbsoluteFill.js.map +7 -0
- package/dist/esm/views/AbsoluteFill.native.js +21 -0
- package/dist/esm/views/AbsoluteFill.native.js.map +7 -0
- package/dist/esm/views/FontLanguage.native.js.map +2 -2
- package/dist/esm/views/Stack.js.map +1 -1
- package/dist/esm/views/TamaguiProvider.js +5 -4
- package/dist/esm/views/TamaguiProvider.js.map +2 -2
- package/dist/esm/views/Text.js.map +1 -1
- package/dist/esm/views/ThemeReset.js +10 -10
- package/dist/esm/views/ThemeReset.js.map +2 -2
- package/package.json +14 -14
- package/src/Tamagui.ts +7 -3
- package/src/config.ts +2 -3
- package/src/constants/constants.ts +10 -6
- package/src/contexts/TextAncestorContext.tsx +1 -8
- package/src/createComponent.tsx +250 -412
- package/src/createTamagui.ts +16 -19
- package/src/createVariable.ts +1 -3
- package/src/helpers/ThemeManager.tsx +7 -15
- package/src/helpers/cache.ts +18 -0
- package/src/helpers/createMediaStyle.ts +16 -9
- package/src/helpers/createProxy.ts +16 -0
- package/src/helpers/extendStaticConfig.ts +0 -1
- package/src/helpers/getSplitStyles.tsx +259 -152
- package/src/helpers/getStylesAtomic.ts +14 -34
- package/src/helpers/getVariantExtras.tsx +2 -1
- package/src/helpers/insertStyleRule.tsx +16 -8
- package/src/helpers/matchMedia.ts +1 -0
- package/src/helpers/mergeTransform.ts +1 -1
- package/src/helpers/normalizeValueWithProperty.ts +30 -0
- package/src/helpers/proxyThemeVariables.tsx +3 -8
- package/src/helpers/useShallowSetState.tsx +0 -1
- package/src/hooks/getThemeUnwrapped.tsx +1 -2
- package/src/hooks/useElementLayout.tsx +90 -0
- package/src/hooks/useIsTouchDevice.tsx +3 -17
- package/src/hooks/useMedia.tsx +82 -88
- package/src/hooks/useSafeRef.ts +17 -18
- package/src/hooks/useTheme.tsx +6 -5
- package/src/index.ts +1 -11
- package/src/static.ts +0 -10
- package/src/styled.tsx +15 -33
- package/src/types.tsx +58 -55
- package/src/views/FontLanguage.native.tsx +1 -0
- package/src/views/Stack.tsx +1 -1
- package/src/views/TamaguiProvider.tsx +5 -5
- package/src/views/Text.tsx +1 -1
- package/src/views/ThemeReset.tsx +11 -11
- package/types/Tamagui.d.ts +6 -4
- package/types/constants/constants.d.ts +14 -3
- package/types/contexts/TextAncestorContext.d.ts +1 -3
- package/types/createComponent.d.ts +0 -15
- package/types/helpers/ThemeManager.d.ts +2 -3
- package/types/helpers/cache.d.ts +12 -0
- package/types/helpers/calc.d.ts +0 -16
- package/types/helpers/createMediaStyle.d.ts +1 -1
- package/types/helpers/createProxy.d.ts +2 -0
- package/types/helpers/getSplitStyles.d.ts +6 -10
- package/types/helpers/getStylesAtomic.d.ts +1 -5
- package/types/helpers/insertStyleRule.d.ts +2 -2
- package/types/helpers/mergeTransform.d.ts +1 -1
- package/types/helpers/normalizeValueWithProperty.d.ts +1 -0
- package/types/hooks/useElementLayout.d.ts +27 -0
- package/types/hooks/useMedia.d.ts +3 -1
- package/types/hooks/useMedia.test.d.ts +1 -0
- package/types/hooks/usePressablePressResponder.d.ts +84 -0
- package/types/index.d.ts +1 -11
- package/types/static.d.ts +0 -1
- package/types/types.d.ts +42 -44
- package/types/views/AbsoluteFill.d.ts +5 -0
- package/types/views/AbsoluteFill.native.d.ts +3 -0
- package/types/views/Stack.d.ts +1 -1
- package/types/views/Text.d.ts +1 -1
- package/dist/cjs/constants/platform.js +0 -74
- package/dist/cjs/constants/platform.js.map +0 -7
- package/dist/cjs/constants/platform.native.js +0 -62
- package/dist/cjs/constants/platform.native.js.map +0 -7
- package/dist/cjs/helpers/createShallowUpdate.js.map +0 -7
- package/dist/cjs/helpers/validate.js +0 -2
- package/dist/cjs/hooks/useDidFinishSSR.js +0 -60
- package/dist/cjs/hooks/useDidFinishSSR.js.map +0 -7
- package/dist/cjs/hooks/useIsSSR.js.map +0 -7
- package/dist/esm/constants/platform.js +0 -39
- package/dist/esm/constants/platform.js.map +0 -7
- package/dist/esm/constants/platform.native.js +0 -28
- package/dist/esm/constants/platform.native.js.map +0 -7
- package/dist/esm/helpers/createShallowUpdate.js +0 -20
- package/dist/esm/helpers/createShallowUpdate.js.map +0 -7
- package/dist/esm/helpers/validate.js +0 -1
- package/dist/esm/hooks/useDidFinishSSR.js +0 -35
- package/dist/esm/hooks/useDidFinishSSR.js.map +0 -7
- package/dist/esm/hooks/useIsSSR.js +0 -22
- package/dist/esm/hooks/useIsSSR.js.map +0 -7
- package/src/helpers/assignNativePropsToWeb.tsx +0 -178
- package/src/helpers/calc.ts +0 -68
- package/src/helpers/getFont.tsx +0 -43
- package/src/helpers/getStackSize.ts +0 -22
- package/src/helpers/startTransition.ts +0 -4
- package/src/hooks/useConstant.tsx +0 -19
- package/src/hooks/useIsMounted.ts +0 -16
- package/src/hooks/usePressable.tsx +0 -9
- package/src/hooks/useUnmountEffect.ts +0 -5
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { StyleObject, simpleHash } from '@tamagui/helpers'
|
|
7
|
-
import
|
|
8
|
-
import type { TextStyle, ViewStyle } from 'react-native'
|
|
7
|
+
import type { TextStyle, ViewStyle } from '@tamagui/types-react-native'
|
|
9
8
|
|
|
10
9
|
import { getConfig } from '../config'
|
|
11
10
|
import { TamaguiInternalConfig } from '../types'
|
|
11
|
+
import { Style, cache } from './cache'
|
|
12
12
|
import { defaultOffset } from './expandStyles'
|
|
13
13
|
import { normalizeValueWithProperty } from './normalizeValueWithProperty.js'
|
|
14
14
|
import { PseudoDescriptor, pseudoDescriptors } from './pseudoDescriptors'
|
|
@@ -166,31 +166,23 @@ const mapTransform = (transform) => {
|
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
// cache
|
|
170
|
-
type Value = Object | Array<any> | string | number
|
|
171
|
-
export type Style = { [key: string]: Value }
|
|
172
|
-
class Cache {
|
|
173
|
-
values: Record<string, any> = {}
|
|
174
|
-
|
|
175
|
-
get(key: string, valStr: string) {
|
|
176
|
-
return this.values[key]?.[valStr]
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
set(key: string, valStr: string, object: any) {
|
|
180
|
-
this.values[key] ??= {}
|
|
181
|
-
this.values[key][valStr] = object
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
const cache = new Cache()
|
|
185
|
-
|
|
186
169
|
function createDeclarationBlock(style: Style, important = false) {
|
|
187
|
-
let
|
|
170
|
+
let next = ''
|
|
188
171
|
for (const key in style) {
|
|
189
172
|
const prop = hyphenateStyleName(key)
|
|
190
173
|
const value = style[key]
|
|
191
|
-
|
|
174
|
+
next += `${prop}:${value}${important ? ` !important` : ''};`
|
|
192
175
|
}
|
|
193
|
-
return `{${
|
|
176
|
+
return `{${next}}`
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const hcache = {}
|
|
180
|
+
const toHyphenLower = (match: string) => `-${match.toLowerCase()}`
|
|
181
|
+
const hyphenateStyleName = (key: string) => {
|
|
182
|
+
let val = hcache[key]
|
|
183
|
+
if (val) return val
|
|
184
|
+
hcache[key] = val = key.replace(/[A-Z]/g, toHyphenLower)
|
|
185
|
+
return val
|
|
194
186
|
}
|
|
195
187
|
|
|
196
188
|
const pseudoSelectorPrefixes = (() => {
|
|
@@ -239,7 +231,6 @@ function createAtomicRules(
|
|
|
239
231
|
}
|
|
240
232
|
|
|
241
233
|
// Polyfill for additional 'pointer-events' values
|
|
242
|
-
// See d13f78622b233a0afc0c7a200c0a0792c8ca9e58
|
|
243
234
|
case 'pointerEvents': {
|
|
244
235
|
let finalValue = value
|
|
245
236
|
if (value === 'auto' || value === 'box-only') {
|
|
@@ -258,17 +249,6 @@ function createAtomicRules(
|
|
|
258
249
|
break
|
|
259
250
|
}
|
|
260
251
|
|
|
261
|
-
// Polyfill for draft spec
|
|
262
|
-
// https://drafts.csswg.org/css-scrollbars-1/
|
|
263
|
-
case 'scrollbarWidth': {
|
|
264
|
-
if (value === 'none') {
|
|
265
|
-
rules.push(`${selector}::-webkit-scrollbar{display:none}`)
|
|
266
|
-
}
|
|
267
|
-
const block = createDeclarationBlock({ scrollbarWidth: value }, important)
|
|
268
|
-
rules.push(`${selector}${block}`)
|
|
269
|
-
break
|
|
270
|
-
}
|
|
271
|
-
|
|
272
252
|
default: {
|
|
273
253
|
const block = createDeclarationBlock({ [property]: value }, important)
|
|
274
254
|
rules.push(`${selector}${block}`)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getConfig } from '../config'
|
|
2
2
|
import { GenericFonts } from '../types'
|
|
3
3
|
import { LanguageContextType } from '../views/FontLanguage.types'
|
|
4
|
+
import { createProxy } from './createProxy'
|
|
4
5
|
|
|
5
6
|
const extrasCache = new WeakMap()
|
|
6
7
|
|
|
@@ -30,7 +31,7 @@ export function getVariantExtras(
|
|
|
30
31
|
// we avoid passing in default props for media queries because that would confuse things like SizableText.size:
|
|
31
32
|
props: avoidDefaultProps
|
|
32
33
|
? props
|
|
33
|
-
:
|
|
34
|
+
: createProxy(props, {
|
|
34
35
|
// handles shorthands
|
|
35
36
|
get(target, key) {
|
|
36
37
|
const shorthand = conf.inverseShorthands[key as any]
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
import type { StyleObject } from '@tamagui/helpers'
|
|
6
6
|
|
|
7
|
-
const allSelectors = {}
|
|
8
|
-
const allRules = {}
|
|
7
|
+
const allSelectors: Record<string, string> = {}
|
|
8
|
+
const allRules: Record<string, boolean | string[]> = {}
|
|
9
9
|
export const insertedTransforms = {}
|
|
10
10
|
|
|
11
11
|
export const getAllSelectors = () => allSelectors
|
|
@@ -84,7 +84,7 @@ export function updateInserted() {
|
|
|
84
84
|
const isTransform = identifier.startsWith('_transform')
|
|
85
85
|
const shouldInsert = isTransform ? addTransform(identifier, cssRule.cssText, cssRule) : true
|
|
86
86
|
if (shouldInsert) {
|
|
87
|
-
allSelectors[identifier] =
|
|
87
|
+
allSelectors[identifier] = cssRule.cssText
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
}
|
|
@@ -134,13 +134,21 @@ export type PartialStyleObject = Pick<StyleObject, 'identifier' | 'property' | '
|
|
|
134
134
|
export type RulesToInsert = PartialStyleObject[]
|
|
135
135
|
|
|
136
136
|
export function insertStyleRules(rulesToInsert: RulesToInsert) {
|
|
137
|
-
|
|
137
|
+
if (isClient && !sheet) {
|
|
138
|
+
if (process.env.NODE_ENV === 'development') {
|
|
139
|
+
// eslint-disable-next-line no-console
|
|
140
|
+
console.warn(`Missing sheet`)
|
|
141
|
+
}
|
|
142
|
+
return
|
|
143
|
+
}
|
|
138
144
|
for (const { identifier, rules } of rulesToInsert) {
|
|
139
|
-
if (allSelectors[identifier]
|
|
140
|
-
allSelectors[identifier] = process.env.NODE_ENV === 'development' ? rules :
|
|
145
|
+
if (allSelectors[identifier]) continue
|
|
146
|
+
allSelectors[identifier] = process.env.NODE_ENV === 'development' ? rules.join('\n') : ''
|
|
141
147
|
updateRules(identifier, rules)
|
|
142
|
-
|
|
143
|
-
|
|
148
|
+
if (sheet) {
|
|
149
|
+
for (const rule of rules) {
|
|
150
|
+
sheet.insertRule(rule, sheet.cssRules.length)
|
|
151
|
+
}
|
|
144
152
|
}
|
|
145
153
|
}
|
|
146
154
|
}
|
|
@@ -6,6 +6,7 @@ function matchMediaFallback(query: string): MediaQueryList {
|
|
|
6
6
|
!process.env.IS_STATIC &&
|
|
7
7
|
process.env.TAMAGUI_TARGET !== 'web'
|
|
8
8
|
) {
|
|
9
|
+
// eslint-disable-next-line no-console
|
|
9
10
|
console.log('warning: matchMedia not loading! Native not picking up .native.js files?')
|
|
10
11
|
}
|
|
11
12
|
return {
|
|
@@ -3,11 +3,15 @@
|
|
|
3
3
|
* Copyright (c) Nicolas Gallagher licensed under the MIT license.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { getAllSelectors } from './insertStyleRule'
|
|
6
7
|
import { normalizeColor } from './normalizeColor'
|
|
7
8
|
|
|
8
9
|
const cache = {}
|
|
9
10
|
|
|
10
11
|
export function normalizeValueWithProperty(value: any, property?: string): any {
|
|
12
|
+
if (property && unitlessNumbers[property]) {
|
|
13
|
+
return value
|
|
14
|
+
}
|
|
11
15
|
const cached = cache[value]
|
|
12
16
|
if (cached) {
|
|
13
17
|
return cached
|
|
@@ -78,3 +82,29 @@ const unitlessNumbers = {
|
|
|
78
82
|
scaleZ: true,
|
|
79
83
|
shadowOpacity: true,
|
|
80
84
|
}
|
|
85
|
+
|
|
86
|
+
// getting real values for colors for animations (reverse mapped from CSS)
|
|
87
|
+
// this isn't beautiful, but will do relatively fine performance for now
|
|
88
|
+
const rcache = {}
|
|
89
|
+
export function reverseMapClassNameToValue(key: string, className: string) {
|
|
90
|
+
const selectors = getAllSelectors()
|
|
91
|
+
const cssRule = selectors[className]
|
|
92
|
+
if (rcache[cssRule]) return rcache[cssRule]
|
|
93
|
+
if (!cssRule) {
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
const cssVal = cssRule.replace(/.*:/, '').replace(/;.*/, '')
|
|
97
|
+
let res: any
|
|
98
|
+
if (unitlessNumbers[key]) {
|
|
99
|
+
res = +cssVal
|
|
100
|
+
} else if (cssVal.endsWith('px')) {
|
|
101
|
+
res = +cssVal.replace('px', '')
|
|
102
|
+
} else {
|
|
103
|
+
res = cssVal
|
|
104
|
+
}
|
|
105
|
+
if (typeof res === 'string') {
|
|
106
|
+
res = res.trim()
|
|
107
|
+
}
|
|
108
|
+
rcache[cssRule] = res
|
|
109
|
+
return res
|
|
110
|
+
}
|
|
@@ -1,12 +1,7 @@
|
|
|
1
|
+
import { createProxy } from './createProxy'
|
|
2
|
+
|
|
1
3
|
export function proxyThemeVariables<A extends Object>(obj: A): A {
|
|
2
|
-
|
|
3
|
-
if (!obj || typeof obj !== 'object') {
|
|
4
|
-
// eslint-disable-next-line no-console
|
|
5
|
-
console.trace(`Empty value for proxyThemeVariables, broken config`, obj)
|
|
6
|
-
return obj
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
return new Proxy<A>(obj || {}, {
|
|
4
|
+
return createProxy<A>(obj || {}, {
|
|
10
5
|
has(target, key) {
|
|
11
6
|
return Reflect.has(target, removeStarting$(key))
|
|
12
7
|
},
|
|
@@ -3,7 +3,6 @@ import React, { useCallback } from 'react'
|
|
|
3
3
|
export function useShallowSetState<State extends Object>(
|
|
4
4
|
setter: React.Dispatch<React.SetStateAction<State>>
|
|
5
5
|
) {
|
|
6
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
7
6
|
return useCallback(
|
|
8
7
|
(next: Partial<State>) => {
|
|
9
8
|
setter((prev) => {
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export const getThemeUnwrapped = (theme: any) => {
|
|
2
2
|
if (!theme) return null
|
|
3
3
|
const first = theme[GetThemeUnwrapped]
|
|
4
|
-
|
|
5
|
-
return theme
|
|
4
|
+
return first?.[GetThemeUnwrapped] || first || theme
|
|
6
5
|
}
|
|
7
6
|
|
|
8
7
|
export const GetThemeUnwrapped = Symbol()
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { useIsomorphicLayoutEffect } from '@tamagui/constants'
|
|
2
|
+
import { getBoundingClientRect } from '@tamagui/react-native-use-responder-events'
|
|
3
|
+
import { useEvent } from '@tamagui/use-event'
|
|
4
|
+
import { RefObject } from 'react'
|
|
5
|
+
|
|
6
|
+
const LayoutHandlers = new WeakMap<Element, Function>()
|
|
7
|
+
|
|
8
|
+
export type LayoutValue = {
|
|
9
|
+
x: number
|
|
10
|
+
y: number
|
|
11
|
+
width: number
|
|
12
|
+
height: number
|
|
13
|
+
left: number
|
|
14
|
+
top: number
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type LayoutEvent = {
|
|
18
|
+
nativeEvent: {
|
|
19
|
+
layout: LayoutValue
|
|
20
|
+
target: any
|
|
21
|
+
}
|
|
22
|
+
timeStamp: number
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let resizeObserver: ResizeObserver | null = null
|
|
26
|
+
|
|
27
|
+
if (typeof window !== 'undefined' && 'ResizeObserver' in window) {
|
|
28
|
+
resizeObserver = new ResizeObserver((entries) => {
|
|
29
|
+
for (const { target } of entries) {
|
|
30
|
+
const onLayout = LayoutHandlers.get(target)
|
|
31
|
+
if (typeof onLayout !== 'function') return
|
|
32
|
+
measureLayout(target as HTMLElement, null, (x, y, width, height, left, top) => {
|
|
33
|
+
onLayout({
|
|
34
|
+
nativeEvent: {
|
|
35
|
+
layout: { x, y, width, height, left, top },
|
|
36
|
+
target,
|
|
37
|
+
},
|
|
38
|
+
timeStamp: Date.now(),
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const getRect = (node: HTMLElement) => {
|
|
46
|
+
const rect = getBoundingClientRect(node)
|
|
47
|
+
if (!rect) return
|
|
48
|
+
const { x, y, top, left } = rect
|
|
49
|
+
return { x, y, width: node.offsetWidth, height: node.offsetHeight, top, left }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const measureLayout = (
|
|
53
|
+
node: HTMLElement,
|
|
54
|
+
relativeTo: HTMLElement | null,
|
|
55
|
+
callback: Function
|
|
56
|
+
) => {
|
|
57
|
+
const relativeNode = relativeTo || node?.parentNode
|
|
58
|
+
if (relativeNode instanceof HTMLElement) {
|
|
59
|
+
setTimeout(() => {
|
|
60
|
+
const relativeRect = getBoundingClientRect(relativeNode)!
|
|
61
|
+
const { height, left, top, width } = getRect(node)!
|
|
62
|
+
const x = left - relativeRect.left
|
|
63
|
+
const y = top - relativeRect.top
|
|
64
|
+
callback(x, y, width, height, left, top)
|
|
65
|
+
}, 0)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const idFn = () => {}
|
|
70
|
+
|
|
71
|
+
export function useElementLayout(
|
|
72
|
+
ref: RefObject<Element>,
|
|
73
|
+
onLayout?: ((e: LayoutEvent) => void) | null
|
|
74
|
+
) {
|
|
75
|
+
const hasLayoutEvent = !!onLayout
|
|
76
|
+
const onLayoutEvent = useEvent(onLayout || idFn)
|
|
77
|
+
|
|
78
|
+
// Observing is done in a separate effect to avoid this effect running
|
|
79
|
+
// when 'onLayout' changes.
|
|
80
|
+
useIsomorphicLayoutEffect(() => {
|
|
81
|
+
if (!resizeObserver || !hasLayoutEvent) return
|
|
82
|
+
const node = ref.current
|
|
83
|
+
if (!node) return
|
|
84
|
+
LayoutHandlers.set(node, onLayoutEvent)
|
|
85
|
+
resizeObserver.observe(node)
|
|
86
|
+
return () => {
|
|
87
|
+
resizeObserver?.unobserve(node)
|
|
88
|
+
}
|
|
89
|
+
}, [ref, hasLayoutEvent])
|
|
90
|
+
}
|
|
@@ -1,20 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
// ssr friendly
|
|
1
|
+
import { isTouchable, isWeb } from '@tamagui/constants'
|
|
2
|
+
import { useDidFinishSSR } from '@tamagui/use-did-finish-ssr'
|
|
5
3
|
|
|
6
4
|
export const useIsTouchDevice = () => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
if (isWeb && !isServer) {
|
|
10
|
-
// only ever false on web SSR (env), so run effect conditionally
|
|
11
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
12
|
-
useIsomorphicLayoutEffect(() => {
|
|
13
|
-
if (isTouchable) {
|
|
14
|
-
setTouchOnly(true)
|
|
15
|
-
}
|
|
16
|
-
}, [])
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return touchOnly
|
|
5
|
+
return !isWeb ? true : useDidFinishSSR() ? isTouchable : false
|
|
20
6
|
}
|
package/src/hooks/useMedia.tsx
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { useIsomorphicLayoutEffect } from '@tamagui/constants'
|
|
2
|
-
import {
|
|
2
|
+
import { MutableRefObject, useEffect, useMemo, useState } from 'react'
|
|
3
3
|
|
|
4
4
|
import { getConfig } from '../config'
|
|
5
|
+
import { createProxy } from '../helpers/createProxy'
|
|
5
6
|
import { matchMedia } from '../helpers/matchMedia'
|
|
6
7
|
import {
|
|
7
8
|
MediaQueries,
|
|
@@ -15,7 +16,7 @@ import { useSafeRef } from './useSafeRef'
|
|
|
15
16
|
export const mediaState: MediaQueryState =
|
|
16
17
|
// development time safeguard
|
|
17
18
|
process.env.NODE_ENV === 'development'
|
|
18
|
-
?
|
|
19
|
+
? createProxy(
|
|
19
20
|
{},
|
|
20
21
|
{
|
|
21
22
|
get(target, key) {
|
|
@@ -30,20 +31,20 @@ export const mediaState: MediaQueryState =
|
|
|
30
31
|
|
|
31
32
|
type MediaListener = (next: boolean) => void
|
|
32
33
|
|
|
33
|
-
const
|
|
34
|
+
const listeners: { [key: string]: Set<MediaListener> } = {}
|
|
34
35
|
|
|
35
36
|
export function addMediaQueryListener(key: MediaQueryKey, cb: MediaListener) {
|
|
36
37
|
if (process.env.NODE_ENV === 'development' && key[0] === '$') {
|
|
37
38
|
// eslint-disable-next-line no-console
|
|
38
39
|
console.warn(`Warning, listening to media queries shouldn't use the "$" prefix`)
|
|
39
40
|
}
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
listeners[key] = listeners[key] || new Set()
|
|
42
|
+
listeners[key].add(cb)
|
|
42
43
|
return () => removeMediaQueryListener(key, cb)
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
export function removeMediaQueryListener(key: MediaQueryKey, cb: MediaListener) {
|
|
46
|
-
|
|
47
|
+
listeners[key]?.delete(cb)
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
export const mediaQueryConfig: MediaQueries = {}
|
|
@@ -53,16 +54,17 @@ export const getMedia = () => {
|
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
// for SSR capture it at time of startup
|
|
56
|
-
let
|
|
57
|
-
let
|
|
58
|
-
|
|
57
|
+
let curState: MediaQueryState
|
|
58
|
+
let initState: MediaQueryState
|
|
59
59
|
export const getInitialMediaState = () => {
|
|
60
|
-
|
|
61
|
-
return currentMediaState || {}
|
|
62
|
-
}
|
|
63
|
-
return initialMediaState || {}
|
|
60
|
+
return (getConfig().disableSSR ? curState : initState) || {}
|
|
64
61
|
}
|
|
65
62
|
|
|
63
|
+
let mediaKeysOrdered: string[]
|
|
64
|
+
export const getMediaKeyImportance = (key: string) =>
|
|
65
|
+
// + 2 because we set base usedKeys=1 in getSplitStyles and all media go above 1
|
|
66
|
+
mediaKeysOrdered.indexOf(key[0] === '$' ? key.slice(1) : key) + 2
|
|
67
|
+
|
|
66
68
|
const dispose = new Set<Function>()
|
|
67
69
|
|
|
68
70
|
export const configureMedia = (config: TamaguiInternalConfig) => {
|
|
@@ -72,8 +74,9 @@ export const configureMedia = (config: TamaguiInternalConfig) => {
|
|
|
72
74
|
mediaState[key] = mediaQueryDefaultActive?.[key] || false
|
|
73
75
|
}
|
|
74
76
|
Object.assign(mediaQueryConfig, media)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
+
curState = { ...mediaState }
|
|
78
|
+
initState = curState
|
|
79
|
+
mediaKeysOrdered = Object.keys(media)
|
|
77
80
|
if (config.disableSSR) {
|
|
78
81
|
setupMediaListeners()
|
|
79
82
|
}
|
|
@@ -101,40 +104,34 @@ function setupMediaListeners() {
|
|
|
101
104
|
// hmr, undo existing before re-binding
|
|
102
105
|
unlisten()
|
|
103
106
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
// react native needs these deprecated apis for now
|
|
115
|
-
match.addListener(update)
|
|
116
|
-
dispose.add(() => match.removeListener(update))
|
|
107
|
+
for (const key in mediaQueryConfig) {
|
|
108
|
+
const str = mediaObjectToString(mediaQueryConfig[key])
|
|
109
|
+
const getMatch = () => matchMedia(str)
|
|
110
|
+
const match = getMatch()
|
|
111
|
+
if (!match) {
|
|
112
|
+
throw new Error('⚠️ No match')
|
|
113
|
+
}
|
|
114
|
+
// react native needs these deprecated apis for now
|
|
115
|
+
match.addListener(update)
|
|
116
|
+
dispose.add(() => match.removeListener(update))
|
|
117
117
|
|
|
118
|
-
|
|
118
|
+
update()
|
|
119
119
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
120
|
+
function update() {
|
|
121
|
+
const next = !!getMatch().matches
|
|
122
|
+
if (next === mediaState[key]) return
|
|
123
|
+
mediaState[key] = next
|
|
124
|
+
curState = { ...mediaState }
|
|
125
|
+
const cur = listeners[key]
|
|
126
|
+
if (cur?.size) {
|
|
127
|
+
cur.forEach((cb) => cb(next))
|
|
129
128
|
}
|
|
130
129
|
}
|
|
131
|
-
}
|
|
130
|
+
}
|
|
132
131
|
}
|
|
133
132
|
|
|
134
|
-
export function
|
|
135
|
-
if (config.disableSSR)
|
|
136
|
-
return
|
|
137
|
-
}
|
|
133
|
+
export function useMediaListeners(config: TamaguiInternalConfig) {
|
|
134
|
+
if (config.disableSSR) return
|
|
138
135
|
useEffect(() => {
|
|
139
136
|
setupMediaListeners()
|
|
140
137
|
return unlisten
|
|
@@ -144,14 +141,14 @@ export function useMediaQueryListeners(config: TamaguiInternalConfig) {
|
|
|
144
141
|
export function useMedia(): {
|
|
145
142
|
[key in MediaQueryKey]: boolean
|
|
146
143
|
} {
|
|
147
|
-
const [state, setState] = useState<MediaQueryState>(initialMediaState || {})
|
|
148
144
|
const keys = useSafeRef({} as Record<string, boolean>)
|
|
145
|
+
const [state, setState] = useState<MediaQueryState>(() => getMediaState(initState || {}, keys))
|
|
149
146
|
|
|
150
147
|
function updateState() {
|
|
151
148
|
setState((prev) => {
|
|
152
149
|
for (const key in keys.current) {
|
|
153
150
|
if (prev[key] !== mediaState[key]) {
|
|
154
|
-
return { ...mediaState }
|
|
151
|
+
return getMediaState({ ...mediaState }, keys)
|
|
155
152
|
}
|
|
156
153
|
}
|
|
157
154
|
return prev
|
|
@@ -159,34 +156,27 @@ export function useMedia(): {
|
|
|
159
156
|
}
|
|
160
157
|
|
|
161
158
|
useIsomorphicLayoutEffect(() => {
|
|
162
|
-
|
|
159
|
+
updateState()
|
|
160
|
+
const disposers = Object.keys(keys.current).map((key) =>
|
|
163
161
|
addMediaQueryListener(key, updateState)
|
|
164
162
|
)
|
|
165
|
-
updateState()
|
|
166
163
|
return () => {
|
|
167
|
-
|
|
164
|
+
disposers.forEach((cb) => cb())
|
|
168
165
|
}
|
|
169
|
-
})
|
|
166
|
+
}, [keys.current])
|
|
170
167
|
|
|
171
|
-
return
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
keys.current[key] = true
|
|
184
|
-
}
|
|
185
|
-
return Reflect.get(state, key)
|
|
186
|
-
},
|
|
187
|
-
}),
|
|
188
|
-
[state, keys]
|
|
189
|
-
)
|
|
168
|
+
return state
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function getMediaState(state: MediaQueryState, keys: MutableRefObject<Record<string, boolean>>) {
|
|
172
|
+
return new Proxy(state, {
|
|
173
|
+
get(_, key: string) {
|
|
174
|
+
if (!keys.current[key]) {
|
|
175
|
+
keys.current[key] = true
|
|
176
|
+
}
|
|
177
|
+
return Reflect.get(state, key)
|
|
178
|
+
},
|
|
179
|
+
})
|
|
190
180
|
}
|
|
191
181
|
|
|
192
182
|
/**
|
|
@@ -205,44 +195,48 @@ export function useMediaPropsActive<A extends Object>(
|
|
|
205
195
|
const media = useMedia()
|
|
206
196
|
|
|
207
197
|
return useMemo(() => {
|
|
208
|
-
const
|
|
209
|
-
const
|
|
198
|
+
const next = {} as A
|
|
199
|
+
const importancesUsed = {}
|
|
210
200
|
const propNames = Object.keys(props)
|
|
211
|
-
const mediaKeysOrdered = Object.keys(getMedia())
|
|
212
|
-
|
|
213
|
-
function update(k: string, v: any, importance = 0) {
|
|
214
|
-
if (lastSetImportanceForKey[k] > importance) {
|
|
215
|
-
return
|
|
216
|
-
}
|
|
217
|
-
lastSetImportanceForKey[k] = importance
|
|
218
|
-
evaluated[k] = v
|
|
219
|
-
}
|
|
220
201
|
|
|
221
202
|
for (let i = propNames.length - 1; i >= 0; i--) {
|
|
222
203
|
const key = propNames[i]
|
|
223
204
|
const val = props[key]
|
|
224
205
|
if (key[0] === '$') {
|
|
225
|
-
|
|
226
|
-
if (!media[shortKey]) {
|
|
206
|
+
if (!media[key.slice(1)]) {
|
|
227
207
|
continue
|
|
228
208
|
}
|
|
229
209
|
if (val && typeof val === 'object') {
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
update(skey, val[skey], mediaImportance)
|
|
210
|
+
const subKeys = Object.keys(val)
|
|
211
|
+
for (let j = subKeys.length; j--; j >= 0) {
|
|
212
|
+
const subKey = subKeys[j]
|
|
213
|
+
mergeMediaByImportance(next, subKey, val[subKey], importancesUsed)
|
|
235
214
|
}
|
|
236
215
|
}
|
|
237
216
|
} else {
|
|
238
|
-
|
|
217
|
+
mergeMediaByImportance(next, key, val, importancesUsed)
|
|
239
218
|
}
|
|
240
219
|
}
|
|
241
220
|
|
|
242
|
-
return
|
|
221
|
+
return next
|
|
243
222
|
}, [media, props])
|
|
244
223
|
}
|
|
245
224
|
|
|
225
|
+
export function mergeMediaByImportance(
|
|
226
|
+
onto: Record<string, any>,
|
|
227
|
+
key: string,
|
|
228
|
+
value: any,
|
|
229
|
+
importancesUsed: Record<string, number>
|
|
230
|
+
) {
|
|
231
|
+
const importance = getMediaKeyImportance(key)
|
|
232
|
+
if (importancesUsed[key] > importance) {
|
|
233
|
+
return false
|
|
234
|
+
}
|
|
235
|
+
importancesUsed[key] = importance
|
|
236
|
+
onto[key] = value
|
|
237
|
+
return true
|
|
238
|
+
}
|
|
239
|
+
|
|
246
240
|
function camelToHyphen(str: string) {
|
|
247
241
|
return str.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`).toLowerCase()
|
|
248
242
|
}
|