0
# Utility Functions
1
2
Helper functions for style processing, event handling, platform detection, and component utilities.
3
4
## Capabilities
5
6
### Event Handling
7
8
Utilities for composing and managing event handlers across platforms.
9
10
```typescript { .api }
11
/**
12
* Compose multiple event handlers into a single function
13
* @param original - Original event handler
14
* @param next - Next event handler to compose
15
* @returns Composed event handler that calls both functions
16
*/
17
function composeEventHandlers<T extends Function>(
18
original?: T,
19
next?: T
20
): T;
21
```
22
23
**Usage Examples:**
24
25
```typescript
26
import { composeEventHandlers, styled, View } from "@tamagui/core";
27
28
function ComposedEvents() {
29
const handlePress1 = () => console.log('First handler');
30
const handlePress2 = () => console.log('Second handler');
31
32
const composedHandler = composeEventHandlers(handlePress1, handlePress2);
33
34
return (
35
<View onPress={composedHandler}>
36
<Text>Press me - both handlers will fire</Text>
37
</View>
38
);
39
}
40
41
// Using in styled components
42
const InteractiveView = styled(View, {
43
backgroundColor: '$background',
44
padding: '$4',
45
46
variants: {
47
interactive: {
48
true: {
49
cursor: 'pointer',
50
},
51
},
52
},
53
});
54
55
function InteractiveComponent({ onPress, onCustomEvent }) {
56
const handlePress = composeEventHandlers(
57
onPress,
58
(event) => {
59
// Custom press handling
60
console.log('Custom press handling');
61
onCustomEvent?.(event);
62
}
63
);
64
65
return (
66
<InteractiveView onPress={handlePress} interactive>
67
<Text>Interactive element</Text>
68
</InteractiveView>
69
);
70
}
71
```
72
73
### Style Processing
74
75
Advanced style processing and splitting utilities for optimized rendering.
76
77
```typescript { .api }
78
/**
79
* Split component props into style and non-style properties
80
* @param props - Component props to split
81
* @param staticConfig - Component static configuration
82
* @param theme - Current theme context
83
* @param state - Component state (hover, press, focus)
84
* @param options - Processing options
85
* @returns Split styles and properties
86
*/
87
function getSplitStyles<T>(
88
props: T,
89
staticConfig: StaticConfig,
90
theme: Theme,
91
state: ComponentState,
92
options?: GetStylesOptions
93
): SplitStyles;
94
95
/**
96
* Expand shorthand CSS properties to their full forms
97
* @param styles - Style object with potential shorthands
98
* @returns Style object with expanded properties
99
*/
100
function expandStyles(styles: StyleObject): StyleObject;
101
102
/**
103
* Get expanded shorthand properties mapping
104
* @param styles - Style object to process
105
* @returns Mapping of shorthand to expanded properties
106
*/
107
function getExpandedShorthands(styles: StyleObject): Record<string, string[]>;
108
109
/**
110
* Generate atomic CSS classes and rules
111
* @param styles - Style object to convert
112
* @returns Object with CSS class names and rule definitions
113
*/
114
function getCSSStylesAtomic(styles: StyleObject): {
115
classNames: string;
116
rules: string[];
117
};
118
119
interface SplitStyles {
120
/** Non-media style properties */
121
style: StyleObject;
122
/** Generated CSS class names */
123
classNames: string;
124
/** Pseudo-state styles (hover, press, focus) */
125
pseudos: Record<string, StyleObject>;
126
/** Spacing-related styles */
127
space: StyleObject;
128
/** Whether media queries are present */
129
hasMedia: boolean;
130
}
131
132
interface GetStylesOptions {
133
/** Disable shorthand expansion */
134
disableExpandShorthands?: boolean;
135
/** How to resolve CSS variables */
136
resolveVariablesAs?: 'value' | 'variable' | 'auto';
137
}
138
139
interface ComponentState {
140
hover: boolean;
141
press: boolean;
142
focus: boolean;
143
}
144
```
145
146
**Usage Examples:**
147
148
```typescript
149
import { getSplitStyles, expandStyles } from "@tamagui/core";
150
151
// Style expansion example
152
const shorthandStyles = {
153
padding: 16,
154
margin: '8px 16px',
155
border: '1px solid red',
156
};
157
158
const expandedStyles = expandStyles(shorthandStyles);
159
// Result: {
160
// paddingTop: 16, paddingRight: 16, paddingBottom: 16, paddingLeft: 16,
161
// marginTop: '8px', marginRight: '16px', marginBottom: '8px', marginLeft: '16px',
162
// borderWidth: '1px', borderStyle: 'solid', borderColor: 'red'
163
// }
164
165
// Advanced component using style splitting
166
function CustomComponent(props) {
167
const theme = useTheme();
168
const [state, setState] = useState({ hover: false, press: false, focus: false });
169
170
const splitStyles = getSplitStyles(
171
props,
172
{ componentName: 'Custom' },
173
theme,
174
state
175
);
176
177
return (
178
<div
179
className={splitStyles.classNames}
180
style={splitStyles.style}
181
onMouseEnter={() => setState(s => ({ ...s, hover: true }))}
182
onMouseLeave={() => setState(s => ({ ...s, hover: false }))}
183
>
184
{props.children}
185
</div>
186
);
187
}
188
```
189
190
### Value Normalization
191
192
Functions for normalizing and processing style values across platforms.
193
194
```typescript { .api }
195
/**
196
* Normalize color values for cross-platform compatibility
197
* @param color - Color value in any supported format
198
* @returns Normalized color string
199
*/
200
function normalizeColor(color: any): string;
201
202
/**
203
* Normalize style values with property-specific processing
204
* @param value - Style value to normalize
205
* @param property - CSS property name for context
206
* @returns Normalized value appropriate for the property
207
*/
208
function normalizeValueWithProperty(value: any, property: string): any;
209
210
/**
211
* Normalize entire style object
212
* @param styles - Style object to normalize
213
* @returns Normalized style object
214
*/
215
function normalizeStyle(styles: StyleObject): StyleObject;
216
```
217
218
**Usage Examples:**
219
220
```typescript
221
import { normalizeColor, normalizeValueWithProperty } from "@tamagui/core";
222
223
// Color normalization
224
const color1 = normalizeColor('#ff0000'); // '#ff0000'
225
const color2 = normalizeColor('red'); // '#ff0000'
226
const color3 = normalizeColor('rgb(255,0,0)'); // '#ff0000'
227
228
// Value normalization by property
229
const width = normalizeValueWithProperty(100, 'width'); // '100px'
230
const fontSize = normalizeValueWithProperty(16, 'fontSize'); // 16
231
const margin = normalizeValueWithProperty('auto', 'margin'); // 'auto'
232
233
// Practical usage in components
234
function NormalizedButton({ color, size, ...props }) {
235
const normalizedColor = normalizeColor(color || '#007AFF');
236
const normalizedSize = normalizeValueWithProperty(size || 16, 'fontSize');
237
238
return (
239
<View
240
style={{
241
backgroundColor: normalizedColor,
242
fontSize: normalizedSize,
243
}}
244
{...props}
245
/>
246
);
247
}
248
```
249
250
### Component Property Utilities
251
252
Utilities for working with component properties and variants.
253
254
```typescript { .api }
255
/**
256
* Process component props through Tamagui's prop system
257
* @param props - Raw component props
258
* @param config - Component configuration
259
* @returns Processed props with resolved tokens and variants
260
*/
261
function useProps<T>(props: T, config?: ComponentConfig): T;
262
263
/**
264
* Merge multiple prop objects with proper precedence
265
* @param props - Array of prop objects to merge
266
* @returns Merged props object
267
*/
268
function mergeProps(...props: Record<string, any>[]): Record<string, any>;
269
270
/**
271
* Get extra configuration for component variants
272
* @param variants - Variant configuration
273
* @param props - Component props
274
* @returns Extra variant configuration
275
*/
276
function getVariantExtras(
277
variants: VariantsConfig,
278
props: Record<string, any>
279
): VariantExtras;
280
281
/**
282
* Map props to different names or transform values
283
* @param propMappings - Mapping configuration
284
* @returns Prop mapping function
285
*/
286
function propMapper(propMappings: PropMappings): (props: any) => any;
287
288
interface ComponentConfig {
289
variants?: VariantsConfig;
290
defaultVariants?: Record<string, any>;
291
accept?: Record<string, any>;
292
}
293
294
interface VariantExtras {
295
resolvedProps: Record<string, any>;
296
variantStyles: StyleObject;
297
defaultVariants: Record<string, any>;
298
}
299
300
interface PropMappings {
301
[propName: string]: string | ((value: any) => any);
302
}
303
```
304
305
### Component Detection & Validation
306
307
Utilities for detecting and validating Tamagui components.
308
309
```typescript { .api }
310
/**
311
* Check if a value is a Tamagui component
312
* @param component - Component to check
313
* @returns True if component is a Tamagui component
314
*/
315
function isTamaguiComponent(component: any): component is TamaguiComponent;
316
317
/**
318
* Check if a React element is a Tamagui element
319
* @param element - Element to check
320
* @returns True if element is created by a Tamagui component
321
*/
322
function isTamaguiElement(element: any): element is TamaguiElement;
323
324
/**
325
* Make a component compatible with Tamagui theming
326
* @param component - Component to make themeable
327
* @param config - Theming configuration
328
* @returns Themeable component
329
*/
330
function themeable<T extends React.ComponentType<any>>(
331
component: T,
332
config?: ThemeableConfig
333
): T;
334
335
interface ThemeableConfig {
336
accept?: Record<string, any>;
337
isText?: boolean;
338
}
339
```
340
341
### Platform Detection Constants
342
343
Cross-platform detection constants for conditional behavior.
344
345
```typescript { .api }
346
/** True when running on web platform */
347
declare const isWeb: boolean;
348
349
/** True when running on server (SSR) */
350
declare const isServer: boolean;
351
352
/** True when running on client */
353
declare const isClient: boolean;
354
355
/** True when running on Android platform */
356
declare const isAndroid: boolean;
357
358
/** True when running on iOS platform */
359
declare const isIos: boolean;
360
361
/** True when device supports touch */
362
declare const isTouchable: boolean;
363
364
/** True when web platform supports touch */
365
declare const isWebTouchable: boolean;
366
367
/**
368
* SSR-safe version of useLayoutEffect
369
* Uses useLayoutEffect on client, useEffect on server
370
*/
371
declare const useIsomorphicLayoutEffect: typeof React.useLayoutEffect;
372
```
373
374
**Usage Examples:**
375
376
```typescript
377
import {
378
isWeb,
379
isAndroid,
380
isIos,
381
isTouchable,
382
useIsomorphicLayoutEffect
383
} from "@tamagui/core";
384
385
function PlatformAwareComponent() {
386
useIsomorphicLayoutEffect(() => {
387
// Safe to use on both client and server
388
console.log('Layout effect');
389
}, []);
390
391
return (
392
<View style={{
393
// Platform-specific styles
394
...isWeb && { cursor: 'pointer' },
395
...isAndroid && { elevation: 4 },
396
...isIos && { shadowOpacity: 0.3 },
397
...isTouchable && { minHeight: 44 }, // Touch target size
398
}}>
399
<Text>
400
Platform: {
401
isWeb ? 'Web' :
402
isAndroid ? 'Android' :
403
isIos ? 'iOS' :
404
'Unknown'
405
}
406
</Text>
407
</View>
408
);
409
}
410
```
411
412
### Context Utilities
413
414
Utilities for working with React contexts in styled components.
415
416
```typescript { .api }
417
/**
418
* Create a styled context for component communication
419
* @param defaultValue - Default context value
420
* @returns Context provider and consumer
421
*/
422
function createStyledContext<T>(defaultValue: T): {
423
Provider: React.ComponentType<{ value: T; children: React.ReactNode }>;
424
useStyledContext: () => T;
425
};
426
427
/**
428
* Component-level context for sharing state
429
*/
430
declare const ComponentContext: React.Context<ComponentContextValue>;
431
432
/**
433
* Group context for coordinating related components
434
*/
435
declare const GroupContext: React.Context<GroupContextValue>;
436
437
interface ComponentContextValue {
438
disabled?: boolean;
439
size?: string;
440
variant?: string;
441
}
442
443
interface GroupContextValue {
444
name?: string;
445
disabled?: boolean;
446
orientation?: 'horizontal' | 'vertical';
447
}
448
```
449
450
### Debug Utilities
451
452
Development and debugging utilities.
453
454
```typescript { .api }
455
/**
456
* Setup development mode features
457
* @param options - Development configuration
458
*/
459
function setupDev(options?: DevOptions): void;
460
461
interface DevOptions {
462
/** Enable verbose logging */
463
debug?: boolean;
464
/** Enable style visualizer */
465
visualizer?: boolean;
466
/** Custom debug configuration */
467
debugConfig?: DebugConfig;
468
}
469
470
interface DebugConfig {
471
/** Log style calculations */
472
logStyles?: boolean;
473
/** Log theme changes */
474
logThemes?: boolean;
475
/** Log media query changes */
476
logMedia?: boolean;
477
}
478
```
479
480
## Advanced Utilities
481
482
### Performance Optimization
483
484
```typescript
485
// Custom hook combining multiple utilities
486
function useOptimizedComponent(props, config) {
487
const theme = useTheme();
488
const media = useMedia();
489
const processedProps = useProps(props, config);
490
491
const splitStyles = useMemo(() =>
492
getSplitStyles(processedProps, config, theme, { hover: false, press: false, focus: false }),
493
[processedProps, config, theme]
494
);
495
496
return {
497
...processedProps,
498
style: splitStyles.style,
499
className: splitStyles.classNames,
500
};
501
}
502
```
503
504
### Custom Style Processors
505
506
```typescript
507
// Creating custom style processing logic
508
function createCustomStyleProcessor(options: ProcessorOptions) {
509
return (styles: StyleObject) => {
510
const expanded = expandStyles(styles);
511
const normalized = normalizeStyle(expanded);
512
513
if (options.addPrefix) {
514
return Object.keys(normalized).reduce((acc, key) => {
515
acc[`${options.prefix}-${key}`] = normalized[key];
516
return acc;
517
}, {});
518
}
519
520
return normalized;
521
};
522
}
523
```
524
525
## Types
526
527
```typescript { .api }
528
interface StyleObject {
529
[key: string]: any;
530
}
531
532
interface StaticConfig {
533
componentName?: string;
534
variants?: VariantsConfig;
535
defaultVariants?: Record<string, any>;
536
accept?: Record<string, any>;
537
isText?: boolean;
538
isZStack?: boolean;
539
validStyles?: Record<string, boolean>;
540
}
541
542
interface VariantsConfig {
543
[variantName: string]: {
544
[variantValue: string]: StyleObject | (() => StyleObject);
545
};
546
}
547
548
interface Theme {
549
[key: string]: string | Variable;
550
}
551
552
interface Variable<T = any> {
553
key: string;
554
name: string;
555
val: T;
556
variable: string;
557
}
558
```