@tamagui/core 1.0.0-alpha.21 → 1.0.0-alpha.25

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 (54) hide show
  1. package/dist/cjs/helpers/getStylesAtomic.js.map +2 -2
  2. package/dist/esm/helpers/getStylesAtomic.js.map +2 -2
  3. package/package.json +8 -9
  4. package/types/helpers/createMediaStyle.d.ts +1 -0
  5. package/types/helpers/createMediaStyle.d.ts.map +1 -1
  6. package/types/helpers/getStylesAtomic.d.ts +1 -0
  7. package/types/helpers/getStylesAtomic.d.ts.map +1 -1
  8. package/src/constants/constants.ts +0 -12
  9. package/src/constants/platform.ts +0 -15
  10. package/src/constants/pseudos.ts +0 -14
  11. package/src/constants/rnw.tsx +0 -20
  12. package/src/createComponent.tsx +0 -614
  13. package/src/createFont.ts +0 -31
  14. package/src/createShorthands.ts +0 -5
  15. package/src/createTamagui.ts +0 -218
  16. package/src/createTheme.ts +0 -22
  17. package/src/createTokens.ts +0 -88
  18. package/src/createVariable.ts +0 -26
  19. package/src/helpers/addStylesUsingClassname.tsx +0 -60
  20. package/src/helpers/createMediaStyle.ts +0 -46
  21. package/src/helpers/createPropMapper.ts +0 -192
  22. package/src/helpers/createTamaguiProvider.tsx +0 -22
  23. package/src/helpers/extendStaticConfig.ts +0 -68
  24. package/src/helpers/fixNativeShadow.native.tsx +0 -27
  25. package/src/helpers/fixNativeShadow.tsx +0 -2
  26. package/src/helpers/getSplitStyles.tsx +0 -200
  27. package/src/helpers/getStylesAtomic.native.ts +0 -3
  28. package/src/helpers/getStylesAtomic.ts +0 -103
  29. package/src/helpers/insertStyleRule.tsx +0 -18
  30. package/src/helpers/isObj.ts +0 -1
  31. package/src/helpers/isTamaguiElement.tsx +0 -5
  32. package/src/helpers/matchMedia.native.ts +0 -6
  33. package/src/helpers/matchMedia.ts +0 -17
  34. package/src/helpers/themeable.tsx +0 -42
  35. package/src/helpers/validate.ts +0 -59
  36. package/src/hooks/useConstant.tsx +0 -10
  37. package/src/hooks/useFeatures.tsx +0 -79
  38. package/src/hooks/useMedia.tsx +0 -196
  39. package/src/hooks/usePressable.tsx +0 -9
  40. package/src/hooks/useTheme.tsx +0 -107
  41. package/src/index.ts +0 -32
  42. package/src/static/postProcessStyles.tsx +0 -20
  43. package/src/static.ts +0 -22
  44. package/src/styled.ts +0 -82
  45. package/src/types.tsx +0 -562
  46. package/src/views/Animated.tsx +0 -121
  47. package/src/views/Stack.tsx +0 -21
  48. package/src/views/Text.tsx +0 -67
  49. package/src/views/TextAncestorContext.tsx +0 -11
  50. package/src/views/Theme.tsx +0 -94
  51. package/src/views/ThemeContext.tsx +0 -5
  52. package/src/views/ThemeInverse.tsx +0 -22
  53. package/src/views/ThemeManagerContext.tsx +0 -62
  54. package/src/views/ThemeProvider.tsx +0 -52
@@ -1,68 +0,0 @@
1
- import React from 'react'
2
-
3
- import { StaticComponent, StaticConfig, StaticConfigParsed } from '../types'
4
- import { createPropMapper } from './createPropMapper'
5
-
6
- export function extendStaticConfig(
7
- // can be undefined when loading with @tamagui/fake-react-native
8
- // could be fixed a bit cleaner
9
- Component?: StaticComponent | React.Component<any>,
10
- config: StaticConfig = {}
11
- ): StaticConfigParsed | null {
12
- const parent = (Component || {}) as any
13
- if (!parent.staticConfig) {
14
- // if no static config, we are extending an external component
15
- parent.staticConfig = {
16
- Component,
17
- }
18
- }
19
-
20
- const variants = {
21
- ...parent.staticConfig.variants,
22
- }
23
-
24
- // merge variants without clobbering previous... can we tho (typed??
25
- if (config.variants) {
26
- for (const key in config.variants) {
27
- if (variants[key]) {
28
- variants[key] = {
29
- ...variants[key],
30
- ...config.variants[key],
31
- }
32
- } else {
33
- variants[key] = config.variants[key]
34
- }
35
- }
36
- }
37
-
38
- return parseStaticConfig({
39
- ...parent.staticConfig,
40
- isZStack: config.isZStack || parent.staticConfig.isZStack,
41
- variants,
42
- isText: config.isText || parent.staticConfig.isText || false,
43
- neverFlatten: config.neverFlatten ?? parent.staticConfig.neverFlatten,
44
- ensureOverriddenProp: config.ensureOverriddenProp ?? parent.staticConfig.ensureOverriddenProp,
45
- validStyles: config.validStyles
46
- ? {
47
- ...parent.staticConfig.validStyles,
48
- ...config.validStyles,
49
- }
50
- : parent.staticConfig.validStyles,
51
- validPropsExtra: {
52
- ...parent.staticConfig.validPropsExtra,
53
- ...config.validPropsExtra,
54
- },
55
- defaultProps: {
56
- ...parent.staticConfig.defaultProps,
57
- ...config.defaultProps,
58
- },
59
- })
60
- }
61
-
62
- export const parseStaticConfig = (config: StaticConfig): StaticConfigParsed => {
63
- return {
64
- ...config,
65
- parsed: true,
66
- propMapper: createPropMapper(config),
67
- }
68
- }
@@ -1,27 +0,0 @@
1
- const matchRgba =
2
- /rgba\(\s*([\d\.]{1,})\s*,\s*([\d\.]{1,})\s*,\s*([\d\.]{1,})\s*,\s*([\d\.]{1,})\s*\)$/
3
-
4
- export function fixNativeShadow(props: any) {
5
- if (props.shadowColor) {
6
- if (!!!('shadowOffset' in props)) {
7
- // fixes some broken shadows
8
- props.shadowOffset = {
9
- width: 0,
10
- height: 0,
11
- }
12
- }
13
- if (!!!('shadowOpacity' in props)) {
14
- const c = `${props.shadowColor}`
15
- // react native has issues sometimes with rgba()
16
- if (c[0] === 'r' && c[3] === 'a') {
17
- const [_, r, g, b, a] = c.match(matchRgba) || []
18
- if (typeof a !== 'string') {
19
- console.warn('non valid rgba', c)
20
- return props
21
- }
22
- props.shadowColor = `rgb(${r},${g},${b})`
23
- props.shadowOpacity = +a
24
- }
25
- }
26
- }
27
- }
@@ -1,2 +0,0 @@
1
- // only native of course
2
- export const fixNativeShadow = (a: any) => {}
@@ -1,200 +0,0 @@
1
- import {
2
- AllRules,
3
- stylePropsText,
4
- stylePropsTransform,
5
- validStyles,
6
- validStylesPseudo,
7
- } from '@tamagui/helpers'
8
- import { ViewStyle } from 'react-native'
9
-
10
- import { isWeb } from '../constants/platform'
11
- import { mediaQueryConfig, mediaState } from '../hooks/useMedia'
12
- import { StaticConfigParsed, ThemeObject } from '../types'
13
- import { createMediaStyle } from './createMediaStyle'
14
- import { fixNativeShadow } from './fixNativeShadow'
15
- import { getStylesAtomic } from './getStylesAtomic'
16
- import { insertStyleRule } from './insertStyleRule'
17
-
18
- export type SplitStyles = ReturnType<typeof getSplitStyles>
19
-
20
- // TODO run over this, should be able to cut it down quite a bit
21
-
22
- export const getSplitStyles = (
23
- props: { [key: string]: any },
24
- staticConfig: StaticConfigParsed,
25
- theme: ThemeObject,
26
- isSplittingDefaultProps?: boolean
27
- ) => {
28
- const validStyleProps = staticConfig.isText ? stylePropsText : validStyles
29
- const viewProps: Record<string, any> = {}
30
- const style: any[] = []
31
-
32
- let pseudos: { hoverStyle?: ViewStyle; pressStyle?: ViewStyle } | null = null
33
- let cur: ViewStyle | null = null
34
- let classNames: string[] | null = null
35
-
36
- for (const keyInit in props) {
37
- // be sure to sync next few lines below to getSubStyle (*1)
38
- const valInit = props[keyInit]
39
-
40
- // media
41
- if (keyInit[0] === '$') {
42
- const mediaKey = keyInit.slice(1)
43
-
44
- if (!mediaQueryConfig[mediaKey]) {
45
- // this isn't a media key, pass through
46
- viewProps[keyInit] = valInit
47
- continue
48
- }
49
-
50
- // dont check if media is active, we just apply *all* media styles
51
- // we combine the media props on top regular props, could proxy this
52
- // TODO test proxy here instead of merge
53
- const mediaProps = { ...props, ...valInit }
54
- // TODO media + hover
55
- const mediaStyle = getSubStyle(valInit, staticConfig, theme, props)
56
-
57
- if (isWeb) {
58
- const mediaStyles = getStylesAtomic(mediaStyle)
59
- if (process.env.NODE_ENV === 'development') {
60
- if (props['debug']) {
61
- console.log('mediaStyles', keyInit, { mediaProps, mediaStyle, mediaStyles })
62
- }
63
- }
64
- for (const style of mediaStyles) {
65
- const out = createMediaStyle(style, mediaKey, mediaQueryConfig)
66
- classNames = classNames || []
67
- classNames.push(out.identifier)
68
- AllRules.add(out.styleRule)
69
- insertStyleRule(out.styleRule)
70
- if (process.env.NODE_ENV === 'development' && props['debug']) {
71
- console.log('mediaProp', style.identifier, out, mediaProps, mediaStyle, mediaStyles)
72
- }
73
- }
74
- } else {
75
- if (mediaState[mediaKey]) {
76
- style.push(mediaStyle)
77
- }
78
- }
79
- continue
80
- }
81
-
82
- // pseudo
83
- if (validStylesPseudo[keyInit]) {
84
- if (!valInit) continue
85
- pseudos = pseudos || {}
86
- pseudos[keyInit] = getSubStyle(valInit, staticConfig, theme, props)
87
- continue
88
- }
89
-
90
- const out = staticConfig.propMapper(keyInit, valInit, theme, props)
91
-
92
- const expanded = out === true || !out ? [[keyInit, valInit]] : Object.entries(out)
93
-
94
- for (const [key, val] of expanded) {
95
- // const val = valueMap(valInit) ?? valInit
96
- const keyFirstChar = key[0]
97
- if (key === 'style' || (keyFirstChar === '_' && key.startsWith('_style'))) {
98
- if (cur) {
99
- // process last
100
- fixNativeShadow(cur)
101
- style.push(cur)
102
- cur = null
103
- }
104
- fixNativeShadow(val)
105
- style.push(val)
106
- continue
107
- }
108
- // expand flex so it merged with flexShrink etc properly
109
- // TODO this shouldn't be here...
110
- if (key === 'flex') {
111
- cur = cur || {}
112
- // see spec for flex shorthand https://developer.mozilla.org/en-US/docs/Web/CSS/flex
113
- // TODO this fixed a behavior but need to find / document / test
114
- Object.assign(cur, {
115
- flexGrow: val,
116
- flexShrink: 1,
117
- })
118
- continue
119
- }
120
- if (!isWeb && key === 'pointerEvents') {
121
- viewProps[key] = val
122
- continue
123
- }
124
- if (validStyleProps[key]) {
125
- // transforms
126
- if (key in stylePropsTransform) {
127
- cur = cur || {}
128
- mergeTransform(cur, key, val)
129
- continue
130
- }
131
- cur = cur || {}
132
- cur[key] = val
133
- continue
134
- }
135
-
136
- // pass to view props
137
- if (!staticConfig.variants || !(key in staticConfig.variants)) {
138
- viewProps[key] = val
139
- }
140
- }
141
- }
142
- // push last style
143
- if (cur) {
144
- fixNativeShadow(cur)
145
- style.push(cur)
146
- }
147
-
148
- if (process.env.NODE_ENV === 'development') {
149
- if (props['debug']) {
150
- console.log(' 🥚 splitProps:', { props, viewProps, style })
151
- }
152
- }
153
-
154
- return {
155
- viewProps,
156
- style,
157
- pseudos,
158
- classNames,
159
- }
160
- }
161
-
162
- const getSubStyle = (
163
- styleIn: Object,
164
- staticConfig: StaticConfigParsed,
165
- theme: ThemeObject,
166
- props: any
167
- ): ViewStyle => {
168
- const styleOut: ViewStyle = {}
169
- for (const key in styleIn) {
170
- // be sure to sync next few lines below to loop above (*1)
171
- const val = styleIn[key]
172
- const out = staticConfig.propMapper(key, val, theme, props)
173
- const expanded = out === true || !out ? [[key, val]] : Object.entries(out)
174
- for (const [skey, sval] of expanded) {
175
- // const sval = valueMap(valInit)
176
- if (skey in stylePropsTransform) {
177
- mergeTransform(styleOut, skey, sval)
178
- } else {
179
- styleOut[skey] = sval
180
- }
181
- }
182
- }
183
- fixNativeShadow(styleOut)
184
- return styleOut
185
- }
186
-
187
- const mapTransformKeys = {
188
- x: 'translateX',
189
- y: 'translateY',
190
- }
191
-
192
- const mergeTransform = (obj: ViewStyle, key: string, val: any) => {
193
- const transform: any[] = obj.transform
194
- ? Array.isArray(obj.transform)
195
- ? obj.transform
196
- : [obj.transform]
197
- : []
198
- transform.push({ [mapTransformKeys[key] || key]: val })
199
- obj.transform = transform
200
- }
@@ -1,3 +0,0 @@
1
- export function getStylesAtomic() {
2
- console.warn('no-op native')
3
- }
@@ -1,103 +0,0 @@
1
- import { AllRules, StyleObject } from '@tamagui/helpers'
2
- import { ViewStyle } from 'react-native'
3
-
4
- import { pseudos } from '../constants/pseudos'
5
- import { rnw } from '../constants/rnw'
6
-
7
- const generateStyle = (style: any) => {
8
- const { atomic, createCompileableStyle, createReactDOMStyle, i18Style } = rnw
9
- return {
10
- ...atomic(createCompileableStyle(createReactDOMStyle(i18Style(style)))),
11
- }
12
- }
13
-
14
- const borderDefaults = {
15
- borderWidth: 'borderStyle',
16
- borderBottomWidth: 'borderBottomStyle',
17
- borderTopWidth: 'borderTopStyle',
18
- borderLeftWidth: 'borderLeftStyle',
19
- borderRightWidth: 'borderRightStyle',
20
- }
21
-
22
- export function getStylesAtomic(style: any, avoidCollection = false) {
23
- const styles: { [key: string]: ViewStyle } = {
24
- base: {},
25
- }
26
- // split pseudos
27
- for (const key in style) {
28
- if (!!pseudos[key]) {
29
- styles[key] = style[key]
30
- } else {
31
- styles.base[key] = style[key]
32
- }
33
- }
34
- return Object.keys(styles)
35
- .map((key) => {
36
- return getAtomicStyle(styles[key], pseudos[key], avoidCollection)
37
- })
38
- .flat()
39
- }
40
-
41
- const importantRegex = /\!important*/g
42
-
43
- function getAtomicStyle(
44
- style: ViewStyle,
45
- pseudo?: { name: string; priority: number },
46
- avoidCollection?: boolean
47
- ): StyleObject[] {
48
- if (style == null || typeof style !== 'object') {
49
- throw new Error(`Wrong style type: "${typeof style}": ${style}`)
50
- }
51
-
52
- // why is this diff from react-native-web!? need to figure out
53
- for (const key in borderDefaults) {
54
- if (key in style) {
55
- style[borderDefaults[key]] = style[borderDefaults[key]] ?? 'solid'
56
- }
57
- }
58
-
59
- const all = generateStyle(style)
60
- return Object.keys(all).map((key) => {
61
- const val = all[key]
62
- const hash = val.identifier.slice(`${val.identifier}`.lastIndexOf('-') + 1)
63
- // pseudos have a `--` to be easier to find with concatClassNames
64
- const psuedoPrefix = pseudo ? `-${pseudo.name}-` : ''
65
- const identifier = `_${val.property}-${psuedoPrefix}${hash}`
66
- const className = `.${identifier}`
67
- const rules = val.rules.map((rule) => {
68
- if (pseudo) {
69
- const psuedoPrefixSelect = [...Array(pseudo.priority)].map(() => ':root').join('') + ' '
70
- let res = rule
71
- .replace(`.${val.identifier}`, `${psuedoPrefixSelect} ${className}`)
72
- .replace('{', `:${pseudo.name}{`)
73
-
74
- if (pseudo.name === 'hover') {
75
- // hover styles need to be conditional
76
- // perhaps this can be generalized but for now lets just shortcut
77
- // and hardcode for hover styles, if we need to later we can
78
- // WEIRD SYNTAX, SEE:
79
- // https://stackoverflow.com/questions/40532204/media-query-for-devices-supporting-hover
80
- res = `@media not all and (hover: none) { ${res} }`
81
- }
82
- return res
83
- }
84
- return rule.replace(`.${val.identifier}`, className).replace(importantRegex, '')
85
- })
86
-
87
- if (!avoidCollection) {
88
- if (rules.length > 1) {
89
- console.warn('have never seen more than one, verifying')
90
- }
91
- AllRules.add(rules[0])
92
- }
93
-
94
- const result: StyleObject = {
95
- property: val.property,
96
- value: val.value,
97
- identifier,
98
- className,
99
- rules,
100
- }
101
- return result
102
- })
103
- }
@@ -1,18 +0,0 @@
1
- import { isWeb } from '../constants/platform'
2
-
3
- export function insertStyleRule(rule: string) {
4
- if (typeof window === 'undefined') {
5
- return
6
- }
7
- if (process.env.NODE_ENV === 'development') {
8
- if (!isWeb) {
9
- console.warn('non web platform, dont use this')
10
- return
11
- }
12
- }
13
- const sheet = window.document.styleSheets[0]
14
- if (!sheet) {
15
- return
16
- }
17
- sheet.insertRule(rule, sheet.cssRules.length)
18
- }
@@ -1 +0,0 @@
1
- export const isObj = (x: any) => x && !Array.isArray(x) && typeof x === 'object'
@@ -1,5 +0,0 @@
1
- import React, { isValidElement } from 'react'
2
-
3
- export const isTamaguiElement = (child: any): child is React.ReactElement => {
4
- return isValidElement(child) && !!child.type['staticConfig']?.parsed
5
- }
@@ -1,6 +0,0 @@
1
- import MediaQueryList from '@expo/match-media/build/MediaQueryList.js'
2
-
3
- export const matchMedia = (media: string) => new MediaQueryList(media)
4
-
5
- // @ts-ignore
6
- globalThis['matchMedia'] = matchMedia
@@ -1,17 +0,0 @@
1
- export const matchMedia =
2
- (typeof window !== 'undefined' && window.matchMedia) ||
3
- (function matchMediaFallback(query: string) {
4
- return {
5
- addListener() {
6
- if (
7
- process.env.NODE_ENV === 'development' &&
8
- !process.env.IS_STATIC &&
9
- process.env.TAMAGUI_TARGET !== 'web'
10
- ) {
11
- console.log('warning: matchMedia not loading! Is native picking up .native.js files?')
12
- }
13
- },
14
- removeListener() {},
15
- matches: false,
16
- }
17
- } as any)
@@ -1,42 +0,0 @@
1
- import React, { ReactElement, forwardRef } from 'react'
2
-
3
- import { Theme } from '../views/Theme'
4
- import { ThemeInverse } from '../views/ThemeInverse'
5
-
6
- export type ThemeableProps = {
7
- theme?: string | null
8
- themeInverse?: boolean
9
- }
10
-
11
- export const themeable: ThemeableHOC = function graphql<
12
- R extends ReactElement<any, any> | null,
13
- P extends ThemeableProps = {}
14
- >(component: (props: P) => R) {
15
- const withThemeComponent = forwardRef(function WithTheme({ themeInverse, ...rest }: P, ref) {
16
- const el = React.createElement(component, { ...rest, ref } as any) as R
17
- if (themeInverse) {
18
- return (<ThemeInverse>{el}</ThemeInverse>) as R
19
- }
20
- if (rest.theme) {
21
- return (<Theme name={rest.theme || null}>{el}</Theme>) as R
22
- }
23
- return el
24
- })
25
-
26
- const withTheme: {
27
- (props: P): R
28
- displayName: string
29
- } = withThemeComponent as any
30
-
31
- withTheme.displayName = `Themed(${
32
- (component as any)?.displayName || (component as any)?.name || 'Anonymous'
33
- })`
34
-
35
- return withTheme
36
- }
37
-
38
- export interface ThemeableHOC {
39
- <R extends ReactElement<any, any> | null, P extends ThemeableProps = {}>(
40
- component: (props: P) => R
41
- ): (props: P) => R
42
- }
@@ -1,59 +0,0 @@
1
- // published a patched version that works on native
2
- import ow from '@tamagui/ow'
3
-
4
- export const validateConfig = (conf: any) => {
5
- if (!conf) {
6
- console.warn('no conf?')
7
- return
8
- }
9
- try {
10
- ow(conf, validConfig)
11
- } catch (err: any) {
12
- console.log('Given config:\n', JSON.stringify(conf, null, 2))
13
- throw err
14
- }
15
- }
16
-
17
- const validConfig = ow.object.exactShape({
18
- defaultTheme: ow.optional.string,
19
- disableRootThemeClass: ow.optional.boolean,
20
- shorthands: ow.optional.object.valuesOfType(ow.string),
21
- themes: ow.object.valuesOfType(ow.object),
22
- tokens: ow.object.valuesOfType(ow.object),
23
- media: ow.object.valuesOfType(ow.object),
24
- })
25
-
26
- const validFont = ow.object.exactShape({
27
- family: ow.string,
28
- size: ow.object.nonEmpty.valuesOfType(ow.number),
29
- lineHeight: ow.object.nonEmpty.valuesOfType(ow.number),
30
- weight: ow.object.nonEmpty.valuesOfType(ow.string),
31
- letterSpacing: ow.object.nonEmpty.valuesOfType(ow.number),
32
- })
33
-
34
- const validTokens = ow.object.exactShape({
35
- font: ow.object.valuesOfType(validFont),
36
- size: ow.object.nonEmpty.valuesOfType(ow.number),
37
- space: ow.object.nonEmpty.valuesOfType(ow.number),
38
- zIndex: ow.object.nonEmpty.valuesOfType(ow.number),
39
- radius: ow.object.nonEmpty.valuesOfType(ow.number),
40
- color: ow.object.nonEmpty.valuesOfType(ow.string),
41
- })
42
-
43
- export const validateTokens = (tokens: any) => {
44
- try {
45
- ow(tokens, validTokens)
46
- } catch (err: any) {
47
- console.log('Given tokens:\n', JSON.stringify(tokens, null, 2))
48
- throw err
49
- }
50
- }
51
-
52
- export const validateFont = (font: any) => {
53
- try {
54
- ow(font, validFont)
55
- } catch (err: any) {
56
- console.log('Given font:\n', JSON.stringify(font, null, 2))
57
- throw err
58
- }
59
- }
@@ -1,10 +0,0 @@
1
- import { useRef } from 'react'
2
-
3
- type ResultBox<T> = { v: T }
4
- export function useConstant<T>(fn: () => T): T {
5
- const ref = useRef<ResultBox<T>>()
6
- if (!ref.current) {
7
- ref.current = { v: fn() }
8
- }
9
- return ref.current.v
10
- }
@@ -1,79 +0,0 @@
1
- import React from 'react'
2
-
3
- import { isWeb, useIsomorphicLayoutEffect } from '../constants/platform'
4
- import { addMediaQueryListener, mediaState, removeMediaQueryListener } from './useMedia'
5
-
6
- type FeatureDefinition = {
7
- isEnabled: (props: any) => boolean
8
- Component: any
9
- }
10
-
11
- const createDefinition = ({
12
- Component,
13
- propNames,
14
- }: {
15
- Component: any
16
- propNames: string[]
17
- }): FeatureDefinition => ({
18
- isEnabled: (props: any) => propNames.some((name) => !!props[name]),
19
- Component,
20
- })
21
-
22
- let featureDefinitions: Record<string, FeatureDefinition> | null = null
23
-
24
- export const useFeatures = (props: any, utils?: { forceUpdate?: Function }) => {
25
- if (!featureDefinitions) {
26
- featureDefinitions = loadFeatures()
27
- }
28
- const features: JSX.Element[] = []
29
- for (const name in featureDefinitions) {
30
- const { isEnabled, Component } = featureDefinitions[name]
31
- if (isEnabled(props) && Component) {
32
- features.push(<Component key={name} {...props} _utils={utils} />)
33
- }
34
- }
35
- return features
36
- }
37
-
38
- function loadFeatures(): Record<string, FeatureDefinition> {
39
- return {
40
- // TODO
41
- // measureLayout: createDefinition({
42
- // Component: (props) => {
43
- // console.log('measure', props)
44
- // return null
45
- // },
46
- // propNames: ['onLayout'],
47
- // }),
48
-
49
- // will update the parent whenever media query changes
50
- // no need on web, media queries are inserted and run in css
51
- ...(!isWeb && {
52
- mediaQuery: loadMediaQueryFeature(),
53
- }),
54
- }
55
- }
56
-
57
- function loadMediaQueryFeature() {
58
- const mediaPropNames = Object.keys(mediaState)
59
-
60
- return createDefinition({
61
- Component: (props: any) => {
62
- const keys = mediaPropNames.flatMap((x) => (x in props ? x.slice(1) : []))
63
-
64
- useIsomorphicLayoutEffect(() => {
65
- for (const key of keys) {
66
- addMediaQueryListener(key, props._utils.forceUpdate)
67
- }
68
- return () => {
69
- for (const key of keys) {
70
- removeMediaQueryListener(key, props._utils.forceUpdate)
71
- }
72
- }
73
- }, [keys.join(',')])
74
-
75
- return null
76
- },
77
- propNames: mediaPropNames,
78
- })
79
- }