CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-tamagui--core

Universal style library for React and React Native with cross-platform support

Pending
Overview
Eval results
Files

utilities.mddocs/

Utility Functions

Helper functions for style processing, event handling, platform detection, and component utilities.

Capabilities

Event Handling

Utilities for composing and managing event handlers across platforms.

/**
 * Compose multiple event handlers into a single function
 * @param original - Original event handler
 * @param next - Next event handler to compose
 * @returns Composed event handler that calls both functions
 */
function composeEventHandlers<T extends Function>(
  original?: T,
  next?: T
): T;

Usage Examples:

import { composeEventHandlers, styled, View } from "@tamagui/core";

function ComposedEvents() {
  const handlePress1 = () => console.log('First handler');
  const handlePress2 = () => console.log('Second handler');
  
  const composedHandler = composeEventHandlers(handlePress1, handlePress2);
  
  return (
    <View onPress={composedHandler}>
      <Text>Press me - both handlers will fire</Text>
    </View>
  );
}

// Using in styled components
const InteractiveView = styled(View, {
  backgroundColor: '$background',
  padding: '$4',
  
  variants: {
    interactive: {
      true: {
        cursor: 'pointer',
      },
    },
  },
});

function InteractiveComponent({ onPress, onCustomEvent }) {
  const handlePress = composeEventHandlers(
    onPress,
    (event) => {
      // Custom press handling
      console.log('Custom press handling');
      onCustomEvent?.(event);
    }
  );
  
  return (
    <InteractiveView onPress={handlePress} interactive>
      <Text>Interactive element</Text>
    </InteractiveView>
  );
}

Style Processing

Advanced style processing and splitting utilities for optimized rendering.

/**
 * Split component props into style and non-style properties
 * @param props - Component props to split
 * @param staticConfig - Component static configuration
 * @param theme - Current theme context
 * @param state - Component state (hover, press, focus)
 * @param options - Processing options
 * @returns Split styles and properties
 */
function getSplitStyles<T>(
  props: T,
  staticConfig: StaticConfig,
  theme: Theme,
  state: ComponentState,
  options?: GetStylesOptions
): SplitStyles;

/**
 * Expand shorthand CSS properties to their full forms
 * @param styles - Style object with potential shorthands
 * @returns Style object with expanded properties
 */
function expandStyles(styles: StyleObject): StyleObject;

/**
 * Get expanded shorthand properties mapping
 * @param styles - Style object to process
 * @returns Mapping of shorthand to expanded properties
 */
function getExpandedShorthands(styles: StyleObject): Record<string, string[]>;

/**
 * Generate atomic CSS classes and rules
 * @param styles - Style object to convert
 * @returns Object with CSS class names and rule definitions
 */
function getCSSStylesAtomic(styles: StyleObject): {
  classNames: string;
  rules: string[];
};

interface SplitStyles {
  /** Non-media style properties */
  style: StyleObject;
  /** Generated CSS class names */
  classNames: string;
  /** Pseudo-state styles (hover, press, focus) */
  pseudos: Record<string, StyleObject>;
  /** Spacing-related styles */
  space: StyleObject;
  /** Whether media queries are present */
  hasMedia: boolean;
}

interface GetStylesOptions {
  /** Disable shorthand expansion */
  disableExpandShorthands?: boolean;
  /** How to resolve CSS variables */
  resolveVariablesAs?: 'value' | 'variable' | 'auto';
}

interface ComponentState {
  hover: boolean;
  press: boolean;
  focus: boolean;
}

Usage Examples:

import { getSplitStyles, expandStyles } from "@tamagui/core";

// Style expansion example
const shorthandStyles = {
  padding: 16,
  margin: '8px 16px',
  border: '1px solid red',
};

const expandedStyles = expandStyles(shorthandStyles);
// Result: {
//   paddingTop: 16, paddingRight: 16, paddingBottom: 16, paddingLeft: 16,
//   marginTop: '8px', marginRight: '16px', marginBottom: '8px', marginLeft: '16px',
//   borderWidth: '1px', borderStyle: 'solid', borderColor: 'red'
// }

// Advanced component using style splitting
function CustomComponent(props) {
  const theme = useTheme();
  const [state, setState] = useState({ hover: false, press: false, focus: false });
  
  const splitStyles = getSplitStyles(
    props,
    { componentName: 'Custom' },
    theme,
    state
  );
  
  return (
    <div 
      className={splitStyles.classNames}
      style={splitStyles.style}
      onMouseEnter={() => setState(s => ({ ...s, hover: true }))}
      onMouseLeave={() => setState(s => ({ ...s, hover: false }))}
    >
      {props.children}
    </div>
  );
}

Value Normalization

Functions for normalizing and processing style values across platforms.

/**
 * Normalize color values for cross-platform compatibility
 * @param color - Color value in any supported format
 * @returns Normalized color string
 */
function normalizeColor(color: any): string;

/**
 * Normalize style values with property-specific processing
 * @param value - Style value to normalize
 * @param property - CSS property name for context
 * @returns Normalized value appropriate for the property
 */
function normalizeValueWithProperty(value: any, property: string): any;

/**
 * Normalize entire style object
 * @param styles - Style object to normalize
 * @returns Normalized style object
 */
function normalizeStyle(styles: StyleObject): StyleObject;

Usage Examples:

import { normalizeColor, normalizeValueWithProperty } from "@tamagui/core";

// Color normalization
const color1 = normalizeColor('#ff0000');        // '#ff0000'
const color2 = normalizeColor('red');            // '#ff0000'
const color3 = normalizeColor('rgb(255,0,0)');   // '#ff0000'

// Value normalization by property
const width = normalizeValueWithProperty(100, 'width');        // '100px'
const fontSize = normalizeValueWithProperty(16, 'fontSize');   // 16
const margin = normalizeValueWithProperty('auto', 'margin');   // 'auto'

// Practical usage in components
function NormalizedButton({ color, size, ...props }) {
  const normalizedColor = normalizeColor(color || '#007AFF');
  const normalizedSize = normalizeValueWithProperty(size || 16, 'fontSize');
  
  return (
    <View 
      style={{
        backgroundColor: normalizedColor,
        fontSize: normalizedSize,
      }}
      {...props}
    />
  );
}

Component Property Utilities

Utilities for working with component properties and variants.

/**
 * Process component props through Tamagui's prop system
 * @param props - Raw component props
 * @param config - Component configuration
 * @returns Processed props with resolved tokens and variants
 */
function useProps<T>(props: T, config?: ComponentConfig): T;

/**
 * Merge multiple prop objects with proper precedence
 * @param props - Array of prop objects to merge
 * @returns Merged props object
 */
function mergeProps(...props: Record<string, any>[]): Record<string, any>;

/**
 * Get extra configuration for component variants
 * @param variants - Variant configuration
 * @param props - Component props
 * @returns Extra variant configuration
 */
function getVariantExtras(
  variants: VariantsConfig,
  props: Record<string, any>
): VariantExtras;

/**
 * Map props to different names or transform values
 * @param propMappings - Mapping configuration
 * @returns Prop mapping function
 */
function propMapper(propMappings: PropMappings): (props: any) => any;

interface ComponentConfig {
  variants?: VariantsConfig;
  defaultVariants?: Record<string, any>;
  accept?: Record<string, any>;
}

interface VariantExtras {
  resolvedProps: Record<string, any>;
  variantStyles: StyleObject;
  defaultVariants: Record<string, any>;
}

interface PropMappings {
  [propName: string]: string | ((value: any) => any);
}

Component Detection & Validation

Utilities for detecting and validating Tamagui components.

/**
 * Check if a value is a Tamagui component
 * @param component - Component to check
 * @returns True if component is a Tamagui component
 */
function isTamaguiComponent(component: any): component is TamaguiComponent;

/**
 * Check if a React element is a Tamagui element
 * @param element - Element to check
 * @returns True if element is created by a Tamagui component
 */
function isTamaguiElement(element: any): element is TamaguiElement;

/**
 * Make a component compatible with Tamagui theming
 * @param component - Component to make themeable
 * @param config - Theming configuration
 * @returns Themeable component
 */
function themeable<T extends React.ComponentType<any>>(
  component: T,
  config?: ThemeableConfig
): T;

interface ThemeableConfig {
  accept?: Record<string, any>;
  isText?: boolean;
}

Platform Detection Constants

Cross-platform detection constants for conditional behavior.

/** True when running on web platform */
declare const isWeb: boolean;

/** True when running on server (SSR) */
declare const isServer: boolean;

/** True when running on client */
declare const isClient: boolean;

/** True when running on Android platform */
declare const isAndroid: boolean;

/** True when running on iOS platform */
declare const isIos: boolean;

/** True when device supports touch */
declare const isTouchable: boolean;

/** True when web platform supports touch */
declare const isWebTouchable: boolean;

/**
 * SSR-safe version of useLayoutEffect
 * Uses useLayoutEffect on client, useEffect on server
 */
declare const useIsomorphicLayoutEffect: typeof React.useLayoutEffect;

Usage Examples:

import { 
  isWeb, 
  isAndroid, 
  isIos, 
  isTouchable,
  useIsomorphicLayoutEffect 
} from "@tamagui/core";

function PlatformAwareComponent() {
  useIsomorphicLayoutEffect(() => {
    // Safe to use on both client and server
    console.log('Layout effect');
  }, []);
  
  return (
    <View style={{
      // Platform-specific styles
      ...isWeb && { cursor: 'pointer' },
      ...isAndroid && { elevation: 4 },
      ...isIos && { shadowOpacity: 0.3 },
      ...isTouchable && { minHeight: 44 }, // Touch target size
    }}>
      <Text>
        Platform: {
          isWeb ? 'Web' : 
          isAndroid ? 'Android' : 
          isIos ? 'iOS' : 
          'Unknown'
        }
      </Text>
    </View>
  );
}

Context Utilities

Utilities for working with React contexts in styled components.

/**
 * Create a styled context for component communication
 * @param defaultValue - Default context value
 * @returns Context provider and consumer
 */
function createStyledContext<T>(defaultValue: T): {
  Provider: React.ComponentType<{ value: T; children: React.ReactNode }>;
  useStyledContext: () => T;
};

/**
 * Component-level context for sharing state
 */
declare const ComponentContext: React.Context<ComponentContextValue>;

/**
 * Group context for coordinating related components
 */
declare const GroupContext: React.Context<GroupContextValue>;

interface ComponentContextValue {
  disabled?: boolean;
  size?: string;
  variant?: string;
}

interface GroupContextValue {
  name?: string;
  disabled?: boolean;
  orientation?: 'horizontal' | 'vertical';
}

Debug Utilities

Development and debugging utilities.

/**
 * Setup development mode features
 * @param options - Development configuration
 */
function setupDev(options?: DevOptions): void;

interface DevOptions {
  /** Enable verbose logging */
  debug?: boolean;
  /** Enable style visualizer */
  visualizer?: boolean;
  /** Custom debug configuration */
  debugConfig?: DebugConfig;
}

interface DebugConfig {
  /** Log style calculations */
  logStyles?: boolean;
  /** Log theme changes */
  logThemes?: boolean;
  /** Log media query changes */
  logMedia?: boolean;
}

Advanced Utilities

Performance Optimization

// Custom hook combining multiple utilities
function useOptimizedComponent(props, config) {
  const theme = useTheme();
  const media = useMedia();
  const processedProps = useProps(props, config);
  
  const splitStyles = useMemo(() => 
    getSplitStyles(processedProps, config, theme, { hover: false, press: false, focus: false }),
    [processedProps, config, theme]
  );
  
  return {
    ...processedProps,
    style: splitStyles.style,
    className: splitStyles.classNames,
  };
}

Custom Style Processors

// Creating custom style processing logic
function createCustomStyleProcessor(options: ProcessorOptions) {
  return (styles: StyleObject) => {
    const expanded = expandStyles(styles);
    const normalized = normalizeStyle(expanded);
    
    if (options.addPrefix) {
      return Object.keys(normalized).reduce((acc, key) => {
        acc[`${options.prefix}-${key}`] = normalized[key];
        return acc;
      }, {});
    }
    
    return normalized;
  };
}

Types

interface StyleObject {
  [key: string]: any;
}

interface StaticConfig {
  componentName?: string;
  variants?: VariantsConfig;
  defaultVariants?: Record<string, any>;
  accept?: Record<string, any>;
  isText?: boolean;
  isZStack?: boolean;
  validStyles?: Record<string, boolean>;
}

interface VariantsConfig {
  [variantName: string]: {
    [variantValue: string]: StyleObject | (() => StyleObject);
  };
}

interface Theme {
  [key: string]: string | Variable;
}

interface Variable<T = any> {
  key: string;
  name: string;
  val: T;
  variable: string;
}

Install with Tessl CLI

npx tessl i tessl/npm-tamagui--core

docs

component-creation.md

configuration.md

index.md

react-native-features.md

styling-theming.md

utilities.md

tile.json