@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,614 +0,0 @@
1
- import { concatClassName, stylePropsView } from '@tamagui/helpers'
2
- import { useForceUpdate } from '@tamagui/use-force-update'
3
- import React, {
4
- Children,
5
- Fragment,
6
- createElement,
7
- forwardRef,
8
- useCallback,
9
- useContext,
10
- useEffect,
11
- useRef,
12
- useState,
13
- } from 'react'
14
- import { StyleSheet, Text, View, ViewStyle } from 'react-native'
15
-
16
- import { stackDefaultStyles } from './constants/constants'
17
- import { isTouchDevice, isWeb } from './constants/platform'
18
- import { rnw } from './constants/rnw'
19
- import { onConfiguredOnce } from './createTamagui'
20
- import { addStylesUsingClassname, useStylesAsClassname } from './helpers/addStylesUsingClassname'
21
- import { extendStaticConfig, parseStaticConfig } from './helpers/extendStaticConfig'
22
- import { getSplitStyles } from './helpers/getSplitStyles'
23
- import { useFeatures } from './hooks/useFeatures'
24
- import { usePressable } from './hooks/usePressable'
25
- import {
26
- SpaceTokens,
27
- StaticComponent,
28
- StaticConfig,
29
- StaticConfigParsed,
30
- TamaguiInternalConfig,
31
- } from './types'
32
- import { TextAncestorContext } from './views/TextAncestorContext'
33
- import { ThemeManagerContext } from './views/ThemeManagerContext'
34
-
35
- export const mouseUps = new Set<Function>()
36
-
37
- if (typeof document !== 'undefined') {
38
- document.addEventListener('mouseup', () => {
39
- mouseUps.forEach((x) => x())
40
- mouseUps.clear()
41
- })
42
- }
43
-
44
- type DefaultProps = {}
45
-
46
- export function createComponent<A extends Object = DefaultProps>(
47
- configIn: Partial<StaticConfig> | StaticConfigParsed
48
- ) {
49
- let staticConfig: StaticConfigParsed
50
- if ('parsed' in configIn) {
51
- staticConfig = configIn
52
- } else {
53
- staticConfig = parseStaticConfig(configIn)
54
- }
55
-
56
- const { Component, validStyles, isText, isZStack } = staticConfig
57
- const validStyleProps = validStyles ?? stylePropsView
58
-
59
- // split out default styles vs props so we can assign it to component.defaultProps
60
- let defaultProps = null as any
61
- let tamaguiConfig: TamaguiInternalConfig
62
-
63
- // web uses className, native uses style
64
- let defaultsStyle: any
65
- let defaultsClassName = ''
66
- let initialTheme: any
67
-
68
- // see onConfiguredOnce below which attaches a name then to this component
69
-
70
- const component = forwardRef<View, A>((props: any, forwardedRef) => {
71
- const forceUpdate = useForceUpdate()
72
- const features = useFeatures(props, { forceUpdate })
73
- const manager = useContext(ThemeManagerContext)
74
- const [state, set_] = useState(() => ({
75
- hover: false,
76
- press: false,
77
- pressIn: false,
78
- theme: manager.name,
79
- }))
80
- const set = (next: Partial<typeof state>) =>
81
- set_((prev) => {
82
- for (const key in next) {
83
- if (prev[key] !== next[key]) {
84
- return { ...prev, ...next }
85
- }
86
- }
87
- return prev
88
- })
89
-
90
- // from react-native-web
91
- if (process.env.NODE_ENV === 'development' && !isText && isWeb) {
92
- Children.toArray(props.children).forEach((item) => {
93
- if (typeof item === 'string') {
94
- console.error(`Unexpected text node: ${item}. A text node cannot be a child of a <View>.`)
95
- }
96
- })
97
- }
98
-
99
- const hasTextAncestor = isWeb ? useContext(TextAncestorContext) : false
100
- const hostRef = useRef(null)
101
-
102
- const theme = (manager.theme as any) || initialTheme
103
-
104
- const {
105
- viewProps: viewPropsIn,
106
- pseudos,
107
- style,
108
- classNames,
109
- } = getSplitStyles(props, staticConfig, theme)
110
-
111
- const {
112
- tag,
113
- hitSlop,
114
- children,
115
- pointerEvents,
116
- onPress,
117
- onPressIn,
118
- onPressOut,
119
- onHoverIn,
120
- onHoverOut,
121
- space,
122
- disabled,
123
- onMouseEnter,
124
- onMouseLeave,
125
- hrefAttrs,
126
- onMoveShouldSetResponder,
127
- onMoveShouldSetResponderCapture,
128
- onResponderEnd,
129
- onResponderGrant,
130
- onResponderMove,
131
- onResponderReject,
132
- onResponderRelease,
133
- onResponderStart,
134
- onResponderTerminate,
135
- onResponderTerminationRequest,
136
- onScrollShouldSetResponder,
137
- onScrollShouldSetResponderCapture,
138
- onSelectionChangeShouldSetResponder,
139
- onSelectionChangeShouldSetResponderCapture,
140
- onStartShouldSetResponder,
141
- onStartShouldSetResponderCapture,
142
- onMouseDown,
143
- onClick,
144
-
145
- accessible,
146
- accessibilityRole,
147
-
148
- // TODO feature load layout hook
149
- onLayout,
150
- ...viewProps
151
- } = viewPropsIn
152
-
153
- if (!isWeb) {
154
- if (accessible) viewProps.accessible = accessible
155
- if (accessibilityRole) viewProps.accessibilityRole = accessibilityRole
156
- }
157
-
158
- if (isWeb) {
159
- // from react-native-web
160
- rnw.useResponderEvents(hostRef, {
161
- onMoveShouldSetResponder,
162
- onMoveShouldSetResponderCapture,
163
- onResponderEnd,
164
- onResponderGrant,
165
- onResponderMove,
166
- onResponderReject,
167
- onResponderRelease,
168
- onResponderStart,
169
- onResponderTerminate,
170
- onResponderTerminationRequest,
171
- onScrollShouldSetResponder,
172
- onScrollShouldSetResponderCapture,
173
- onSelectionChangeShouldSetResponder,
174
- onSelectionChangeShouldSetResponderCapture,
175
- onStartShouldSetResponder,
176
- onStartShouldSetResponderCapture,
177
- })
178
- }
179
-
180
- const isTracking = useRef(false)
181
-
182
- // hasEverHadEvents prevents repareting if you remove onPress or similar...
183
- const internal = useRef<{ isMounted: boolean; hasEverHadEvents?: boolean }>()
184
- if (!internal.current) {
185
- internal.current = {
186
- isMounted: true,
187
- }
188
- }
189
-
190
- useEffect(() => {
191
- internal.current!.isMounted = true
192
- const dispose = manager?.onChangeTheme((name) => {
193
- if (isTracking.current) {
194
- set({ theme: name })
195
- }
196
- })
197
- return () => {
198
- dispose()
199
- mouseUps.delete(unPress)
200
- isTracking.current = false
201
- internal.current!.isMounted = false
202
- }
203
- }, [manager])
204
-
205
- // element
206
- const element = isWeb
207
- ? !Component || typeof Component === 'string'
208
- ? // default to tag, fallback to component (when both strings)
209
- tag || Component
210
- : Component
211
- : Component
212
- const ReactView = !isWeb ? View : element || (hasTextAncestor ? 'span' : 'div')
213
- const ReactText = !isWeb ? Text : element || 'span'
214
- const ViewComponent = isText ? ReactText : ReactView
215
-
216
- // styles
217
- const isHovering = !isTouchDevice && !disabled && pseudos && state.hover
218
- const isPressing = !disabled && pseudos && state.press
219
-
220
- const styles = [
221
- // parity w react-native-web, only for text in text
222
- // TODO this should be able to be done w css to replicate after extraction:
223
- // (.text .text { display: inline-flex; }) (but if they set display we'd need stronger precendence)
224
- // isText && hasTextAncestor && isWeb ? { display: 'inline-flex' } : null,
225
- style,
226
- isHovering ? pseudos.hoverStyle || null : null,
227
- isPressing ? pseudos.pressStyle || null : null,
228
- ]
229
-
230
- if (isWeb) {
231
- const stylesClassNames = useStylesAsClassname(styles)
232
- const classList = isText
233
- ? [
234
- defaultsClassName,
235
- // hasTextAncestor === true && cssText.textHasAncestor,
236
- // TODO MOVE TO VARIANTS [number] [any]
237
- // numberOfLines != null && numberOfLines > 1 && cssText.textMultiLine,
238
- classNames,
239
- stylesClassNames,
240
- props.className,
241
- ]
242
- : [defaultsClassName, props.className, classNames, stylesClassNames]
243
-
244
- // @ts-ignore we are optimizing using arguments
245
- const className = concatClassName(...classList)
246
- if (process.env.NODE_ENV === 'development') {
247
- if (props['debug']) {
248
- // prettier-ignore
249
- console.log('🥚 className', { style, styles, classList, stylesClassNames, className })
250
- }
251
- }
252
- viewProps.className = className
253
- } else {
254
- viewProps.style = styles
255
- }
256
-
257
- if (pointerEvents) {
258
- viewProps.pointerEvents = pointerEvents
259
- }
260
-
261
- if (isWeb) {
262
- // from react-native-web
263
- const platformMethodsRef = rnw.usePlatformMethods(viewProps)
264
- const setRef = rnw.useMergeRefs(hostRef, platformMethodsRef, forwardedRef)
265
- viewProps.ref = setRef
266
- if (props.href != null && hrefAttrs != null) {
267
- const { download, rel, target } = hrefAttrs
268
- if (download != null) {
269
- viewProps.download = download
270
- }
271
- if (rel != null) {
272
- viewProps.rel = rel
273
- }
274
- if (typeof target === 'string') {
275
- viewProps.target = target.charAt(0) !== '_' ? '_' + target : target
276
- }
277
- }
278
- } else {
279
- if (forwardedRef) {
280
- viewProps.ref = forwardedRef
281
- }
282
- }
283
-
284
- const attachPress = !!(
285
- (pseudos && pseudos.pressStyle) ||
286
- onPress ||
287
- onPressOut ||
288
- onPressIn ||
289
- onClick
290
- )
291
- const attachHover =
292
- isWeb &&
293
- !isTouchDevice &&
294
- !!((pseudos && pseudos.hoverStyle) || onHoverIn || onHoverOut || onMouseEnter || onMouseLeave)
295
-
296
- // check presence to prevent reparenting bugs, allows for onPress={x ? function : undefined} usage
297
- // while avoiding reparenting...
298
- // once proper reparenting is supported, we can remove this and use that...
299
- const shouldAttach =
300
- internal.current.hasEverHadEvents ||
301
- attachPress ||
302
- attachHover ||
303
- 'pressStyle' in props ||
304
- 'onPress' in props ||
305
- 'onPressIn' in props ||
306
- 'onPressOut' in props ||
307
- (isWeb &&
308
- ('hoverStyle' in props ||
309
- 'onClick' in props ||
310
- 'onHoverIn' in props ||
311
- 'onHoverOut' in props ||
312
- 'onMouseEnter' in props ||
313
- 'onMouseLeave' in props))
314
-
315
- // never remove events as we wrap in a div (for now, may be able to remove..)
316
- if (shouldAttach) {
317
- internal.current.hasEverHadEvents = true
318
- }
319
-
320
- const unPress = useCallback(() => {
321
- if (!internal.current!.isMounted) return
322
- set({
323
- press: false,
324
- pressIn: false,
325
- })
326
- }, [])
327
-
328
- const events = shouldAttach
329
- ? {
330
- ...(!isWeb && {
331
- // non web
332
- onPressOut: (e) => {
333
- unPress()
334
- onPressOut?.(e)
335
- },
336
- }),
337
- ...(isWeb &&
338
- !isTouchDevice && {
339
- onMouseEnter:
340
- attachHover || attachPress
341
- ? (e) => {
342
- let next: Partial<typeof state> = {}
343
- if (attachHover) {
344
- next.hover = true
345
- }
346
- if (state.pressIn) {
347
- next.press = true
348
- }
349
- if (Object.keys(next).length) {
350
- set(next)
351
- }
352
- onHoverIn?.(e)
353
- onMouseEnter?.(e)
354
- }
355
- : undefined,
356
- onMouseLeave:
357
- attachHover || attachPress
358
- ? (e) => {
359
- let next: Partial<typeof state> = {}
360
- mouseUps.add(unPress)
361
- if (attachHover) {
362
- next.hover = false
363
- }
364
- if (state.pressIn) {
365
- next.press = false
366
- next.pressIn = false
367
- }
368
- if (Object.keys(next).length) {
369
- set(next)
370
- }
371
- onHoverOut?.(e)
372
- onMouseLeave?.(e)
373
- }
374
- : undefined,
375
- }),
376
- onMouseDown: attachPress
377
- ? (e) => {
378
- set({
379
- press: true,
380
- pressIn: true,
381
- })
382
- onPressIn?.(e)
383
- onMouseDown?.(e)
384
- }
385
- : (onPressIn as any),
386
- onClick: attachPress
387
- ? (e) => {
388
- // this caused issue with next.js passing href
389
- // e.preventDefault()
390
- onPress?.(e)
391
- onClick?.(e)
392
- unPress()
393
- onPressOut?.(e)
394
- }
395
- : (onPressOut as any),
396
- }
397
- : null
398
-
399
- if (events) {
400
- if (typeof ViewComponent !== 'string') {
401
- // TODO once we do the above we can then rely entirely on pressStyle returned here isntead of above pressStyle logic
402
- const [pressProps] = usePressable({
403
- disabled,
404
- hitSlop,
405
- onPressIn: events.onMouseDown,
406
- onPressOut: events.onPressOut,
407
- onPress: events.onClick,
408
- })
409
- Object.assign(viewProps, pressProps)
410
- } else {
411
- Object.assign(viewProps, events)
412
- }
413
- }
414
-
415
- const childEls = spacedChildren({
416
- children,
417
- space,
418
- flexDirection: props.flexDirection || defaultProps?.flexDirection,
419
- isZStack: isZStack,
420
- })
421
-
422
- let content: any
423
-
424
- // replicate react-native-web's `createElement`
425
- if (isWeb && rnw) {
426
- const domProps = rnw.createDOMProps(viewProps)
427
- const className =
428
- domProps.className && domProps.className !== viewProps.className
429
- ? `${domProps.className} ${viewProps.className}`
430
- : viewProps.className
431
- Object.assign(viewProps, domProps)
432
- viewProps.className = className
433
- content = createElement(ViewComponent, viewProps, childEls)
434
- } else {
435
- content = createElement(ViewComponent, viewProps, childEls)
436
- }
437
-
438
- const shouldWrapTextAncestor = isWeb && isText && !hasTextAncestor
439
- if (shouldWrapTextAncestor) {
440
- // from react-native-web
441
- // @ts-ignore
442
- content = createElement(TextAncestorContext.Provider, { value: true }, content)
443
- }
444
-
445
- if (process.env.NODE_ENV === 'development') {
446
- if (props['debug']) {
447
- viewProps['debug'] = true
448
- console.log('🥚 props in:', props)
449
- console.log('🥚 props out:', viewProps)
450
- console.log(props.onClick?.toString())
451
- // prettier-ignore
452
- console.log('🥚 etc:', { shouldAttach, ViewComponent, viewProps, styles, pseudos, content, childEls })
453
- // only on browser because node expands it huge
454
- if (isWeb) {
455
- console.log('🥚 component info', { staticConfig, tamaguiConfig })
456
- }
457
- }
458
- }
459
-
460
- return (
461
- <>
462
- {features}
463
- {content}
464
- </>
465
- )
466
- })
467
-
468
- // Once configuration is run and all components are registered
469
- // get default props + className and analyze styles
470
- onConfiguredOnce((conf) => {
471
- tamaguiConfig = conf
472
- initialTheme = conf.themes[conf.defaultTheme || Object.keys(conf.themes)[0]]
473
- const next = getSplitStyles(staticConfig.defaultProps, staticConfig, initialTheme, true)
474
- if (isWeb) {
475
- if (next.classNames) {
476
- defaultsClassName += next.classNames + ' '
477
- }
478
- defaultsClassName += addStylesUsingClassname([next.style, next.pseudos])
479
- } else {
480
- if (!hasWarnedOnce) {
481
- hasWarnedOnce = true
482
- console.log('⚠️ TODO account for default styles for media queries')
483
- }
484
- }
485
- // @ts-ignore
486
- component.defaultProps = {
487
- ...next.viewProps,
488
- ...component.defaultProps,
489
- }
490
- if (process.env.NODE_ENV === 'development') {
491
- if (staticConfig.defaultProps?.debug) {
492
- console.log('tamagui debug component:', next, defaultsClassName, component.defaultProps)
493
- }
494
- }
495
- })
496
-
497
- component['staticConfig'] = {
498
- validStyles: validStyleProps,
499
- ...staticConfig,
500
- }
501
-
502
- const res = component as any as StaticComponent<A, void>
503
-
504
- // add extractable HoC
505
- res['extractable'] = (Component: any, conf?: StaticConfig) => {
506
- Component['staticConfig'] = extendStaticConfig(res, {
507
- ...conf,
508
- neverFlatten: true,
509
- defaultProps: {
510
- ...Component.defaultProps,
511
- ...conf?.defaultProps,
512
- },
513
- })
514
- return Component
515
- }
516
-
517
- return res
518
- }
519
-
520
- let hasWarnedOnce = false
521
-
522
- // dont used styled() here to avoid circular deps
523
- // keep inline to avoid circular deps
524
-
525
- export const Spacer = createComponent<{ size?: number | SpaceTokens; flex?: boolean | number }>({
526
- defaultProps: {
527
- ...stackDefaultStyles,
528
- size: true,
529
- },
530
- variants: {
531
- size: {
532
- '...size': (size, { tokens }) => {
533
- size = size == true ? '$true' : size
534
- return {
535
- width: tokens.size[size] ?? size,
536
- height: tokens.size[size] ?? size,
537
- }
538
- },
539
- },
540
-
541
- direction: {
542
- horizontal: {
543
- height: 0,
544
- },
545
- vertical: {
546
- width: 0,
547
- },
548
- },
549
- },
550
- })
551
-
552
- export function spacedChildren({
553
- isZStack,
554
- children,
555
- space,
556
- flexDirection,
557
- }: {
558
- isZStack?: boolean
559
- children: any
560
- space?: any
561
- flexDirection?: ViewStyle['flexDirection']
562
- }) {
563
- if (!space && !isZStack) {
564
- return children
565
- }
566
- const childrenList = Children.toArray(children)
567
- const len = childrenList.length
568
- if (len === 1) {
569
- return children
570
- }
571
- const next: any[] = []
572
- for (const [index, child] of childrenList.entries()) {
573
- if (child === null || child === undefined) {
574
- continue
575
- }
576
-
577
- const key = `${child?.['key'] ?? index}`
578
-
579
- next.push(<Fragment key={key}>{isZStack ? <Absolute>{child}</Absolute> : child}</Fragment>)
580
-
581
- // allows for custom visually hidden components that dont insert spacing
582
- if (child?.['type']?.['isVisuallyHidden']) {
583
- continue
584
- }
585
-
586
- if (index !== len - 1) {
587
- if (space) {
588
- next.push(
589
- <Spacer
590
- key={`${key}_spacer`}
591
- // @ts-ignore TODO
592
- direction={
593
- flexDirection === 'row' || flexDirection === 'row-reverse' ? 'horizontal' : 'vertical'
594
- }
595
- size={space}
596
- />
597
- )
598
- }
599
- }
600
- }
601
- return next
602
- }
603
-
604
- // for now not so "tamagui-y"
605
- const Absolute = ({ children }) => <View style={sheet.fullscreen}>{children}</View>
606
- const sheet = StyleSheet.create({
607
- fullscreen: {
608
- position: 'absolute',
609
- top: 0,
610
- left: 0,
611
- right: 0,
612
- bottom: 0,
613
- },
614
- })
package/src/createFont.ts DELETED
@@ -1,31 +0,0 @@
1
- import { validateFont } from './helpers/validate'
2
- import { GenericFont } from './types'
3
-
4
- export const createFont = <A extends GenericFont>(font: A): A => {
5
- if (process.env.NODE_ENV === 'development') {
6
- validateFont(font)
7
- }
8
-
9
- // fills in any missing values based on size keys being standard
10
- const sizeKeys = Object.keys(font.size)
11
-
12
- for (const key in font) {
13
- if (key === 'size' || key === 'family') continue
14
- const section = font[key]
15
- const keys = Object.keys(section)
16
-
17
- // fill with first filled in value to start
18
- let fillVal = section[keys[0]]
19
-
20
- for (const sKey of sizeKeys) {
21
- if (!(sKey in section)) {
22
- section[sKey] = fillVal
23
- } else {
24
- // if exists, set as the fillVal
25
- fillVal = section[sKey]
26
- }
27
- }
28
- }
29
-
30
- return Object.freeze(font)
31
- }
@@ -1,5 +0,0 @@
1
- // type helper
2
-
3
- export function createShorthands<A extends Record<string, string>>(shorthands: A): A {
4
- return Object.freeze(shorthands) as any
5
- }