CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-unimodules--core

Deprecated compatibility wrapper that provides backward compatibility for applications migrating from legacy Unimodules infrastructure to Expo Modules API

Pending
Overview
Eval results
Files

native-views.mddocs/

Native View Integration

Component creation utilities for integrating native UI components into React Native applications with automatic prop handling and cross-platform compatibility.

Capabilities

requireNativeViewManager Function

Drop-in replacement for React Native's requireNativeComponent that provides enhanced prop handling and view manager integration.

/**
 * Create a React component for a native view manager
 * Drop-in replacement for React Native's requireNativeComponent
 * @param viewName - Name of the native view manager
 * @returns React component for the native view
 */
function requireNativeViewManager<P = any>(viewName: string): React.ComponentType<P>;

Usage Examples:

import { requireNativeViewManager } from "@unimodules/core";
import React from "react";

// Create native view component
interface CustomMapViewProps {
  region: {
    latitude: number;
    longitude: number;
    latitudeDelta: number;
    longitudeDelta: number;
  };
  onRegionChange?: (region: any) => void;
  showsUserLocation?: boolean;
  style?: any;
}

const CustomMapView = requireNativeViewManager<CustomMapViewProps>('CustomMapView');

// Use in React component
function MapScreen() {
  const [region, setRegion] = React.useState({
    latitude: 37.78825,
    longitude: -122.4324,
    latitudeDelta: 0.0922,
    longitudeDelta: 0.0421,
  });
  
  return (
    <CustomMapView
      style={{ flex: 1 }}
      region={region}
      showsUserLocation={true}
      onRegionChange={(newRegion) => {
        setRegion(newRegion);
      }}
    />
  );
}

Native View Props Handling

The function automatically handles prop separation between React Native standard props and custom view props.

Usage Examples:

import { requireNativeViewManager } from "@unimodules/core";

// Camera view with custom props
interface CameraViewProps {
  // Standard React Native props (handled automatically)
  style?: any;
  testID?: string;
  
  // Custom native view props (passed to native side)
  cameraType?: 'front' | 'back';
  flashMode?: 'on' | 'off' | 'auto';
  quality?: number;
  onCameraReady?: () => void;
  onPictureTaken?: (data: { uri: string }) => void;
}

const CameraView = requireNativeViewManager<CameraViewProps>('ExpoCameraView');

function CameraScreen() {
  return (
    <CameraView
      style={{ flex: 1 }}
      testID="camera-view"
      cameraType="back"
      flashMode="auto"
      quality={0.8}
      onCameraReady={() => {
        console.log('Camera is ready');
      }}
      onPictureTaken={(data) => {
        console.log('Picture taken:', data.uri);
      }}
    />
  );
}

Multiple Native Views

Create multiple native view components for different native managers.

Usage Examples:

import { requireNativeViewManager } from "@unimodules/core";

// Different native views
const VideoView = requireNativeViewManager<{
  source: { uri: string };
  shouldPlay?: boolean;
  isLooping?: boolean;
  volume?: number;
  onPlaybackStatusUpdate?: (status: any) => void;
}>('ExpoVideoView');

const WebView = requireNativeViewManager<{
  source: { uri: string };
  onLoadStart?: () => void;
  onLoadEnd?: () => void;
  onError?: (error: any) => void;
}>('ExpoWebView');

const BlurView = requireNativeViewManager<{
  intensity?: number;
  tint?: 'light' | 'dark' | 'default';
}>('ExpoBlurView');

// Use multiple views
function MediaScreen() {
  return (
    <View style={{ flex: 1 }}>
      <VideoView
        style={{ height: 200 }}
        source={{ uri: 'https://example.com/video.mp4' }}
        shouldPlay={true}
        volume={0.8}
      />
      
      <WebView
        style={{ flex: 1 }}
        source={{ uri: 'https://example.com' }}
        onLoadEnd={() => console.log('Web page loaded')}
      />
      
      <BlurView
        style={{ position: 'absolute', top: 0, left: 0, right: 0, height: 100 }}
        intensity={50}
        tint="light"
      />
    </View>
  );
}

Advanced Usage

Development Environment Checks

The function includes development-time validation to ensure view managers are properly registered.

Usage Examples:

import { requireNativeViewManager } from "@unimodules/core";

// This will warn in development if 'MyCustomView' is not registered
const MyCustomView = requireNativeViewManager('MyCustomView');

// Handle potential missing view managers gracefully
function createOptionalNativeView(viewName: string) {
  try {
    return requireNativeViewManager(viewName);
  } catch (error) {
    console.warn(`Native view ${viewName} not available:`, error.message);
    return null;
  }
}

// Conditional native view usage
const OptionalView = createOptionalNativeView('OptionalNativeView');

function ConditionalViewScreen() {
  if (OptionalView) {
    return <OptionalView style={{ flex: 1 }} />;
  } else {
    return <View style={{ flex: 1 }}><Text>Native view not available</Text></View>;
  }
}

Native View Ref Handling

Working with refs to access native view methods.

Usage Examples:

import { requireNativeViewManager } from "@unimodules/core";
import React, { useRef } from "react";

interface CameraViewRef {
  takePictureAsync: (options?: any) => Promise<{ uri: string }>;
  recordAsync: (options?: any) => Promise<{ uri: string }>;
  stopRecording: () => void;
}

const CameraView = requireNativeViewManager<{
  ref?: React.Ref<CameraViewRef>;
  cameraType?: 'front' | 'back';
}>('ExpoCameraView');

function CameraWithControls() {
  const cameraRef = useRef<CameraViewRef>(null);
  
  const takePicture = async () => {
    if (cameraRef.current) {
      try {
        const result = await cameraRef.current.takePictureAsync({
          quality: 0.8,
          base64: false
        });
        console.log('Picture saved to:', result.uri);
      } catch (error) {
        console.error('Failed to take picture:', error);
      }
    }
  };
  
  const startRecording = async () => {
    if (cameraRef.current) {
      try {
        const result = await cameraRef.current.recordAsync({
          maxDuration: 10, // 10 seconds
          quality: 'high'
        });
        console.log('Video saved to:', result.uri);
      } catch (error) {
        console.error('Failed to record video:', error);
      }
    }
  };
  
  return (
    <View style={{ flex: 1 }}>
      <CameraView
        ref={cameraRef}
        style={{ flex: 1 }}
        cameraType="back"
      />
      
      <View style={{ flexDirection: 'row', justifyContent: 'space-around', padding: 20 }}>
        <Button title="Take Picture" onPress={takePicture} />
        <Button title="Record Video" onPress={startRecording} />
      </View>
    </View>
  );
}

Custom Prop Validation

Add runtime prop validation for native views.

Usage Examples:

import { requireNativeViewManager } from "@unimodules/core";
import React from "react";

// Create wrapper with prop validation
function createValidatedNativeView<P>(viewName: string, validator?: (props: P) => void) {
  const NativeView = requireNativeViewManager<P>(viewName);
  
  return React.forwardRef<any, P>((props, ref) => {
    if (validator) {
      validator(props);
    }
    return <NativeView ref={ref} {...props} />;
  });
}

// Example with validation
interface MapViewProps {
  region: {
    latitude: number;
    longitude: number;
    latitudeDelta: number;
    longitudeDelta: number;
  };
  zoom?: number;
}

const MapView = createValidatedNativeView<MapViewProps>('MapView', (props) => {
  if (props.zoom && (props.zoom < 0 || props.zoom > 20)) {
    throw new Error('Zoom level must be between 0 and 20');
  }
  
  if (Math.abs(props.region.latitude) > 90) {
    throw new Error('Latitude must be between -90 and 90');
  }
  
  if (Math.abs(props.region.longitude) > 180) {
    throw new Error('Longitude must be between -180 and 180');
  }
});

Platform-Specific Native Views

Handle platform-specific view managers.

Usage Examples:

import { requireNativeViewManager, Platform } from "@unimodules/core";

// Platform-specific view creation
function createPlatformNativeView(viewNames: { ios?: string; android?: string; web?: string }) {
  const viewName = Platform.select(viewNames);
  
  if (!viewName) {
    console.warn('No native view available for current platform');
    return null;
  }
  
  return requireNativeViewManager(viewName);
}

// Platform-specific implementation
const PlatformSpecificView = createPlatformNativeView({
  ios: 'IOSSpecificView',
  android: 'AndroidSpecificView',
  web: 'WebSpecificView'
});

function PlatformViewScreen() {
  if (!PlatformSpecificView) {
    return <Text>Platform-specific view not available</Text>;
  }
  
  return (
    <PlatformSpecificView
      style={{ flex: 1 }}
      // Platform-specific props will be different
      {...Platform.select({
        ios: { iosSpecificProp: true },
        android: { androidSpecificProp: 'value' },
        web: { webSpecificProp: 42 }
      })}
    />
  );
}

Types

type NativeViewComponent<P = any> = React.ComponentType<P>;

interface NativeViewManagerAdapter {
  <P = any>(viewName: string): NativeViewComponent<P>;
}

interface ViewManagerConfig {
  viewManagersNames: string[];
}

interface NativeExpoComponentProps {
  proxiedProperties: object;
}

Install with Tessl CLI

npx tessl i tessl/npm-unimodules--core

docs

error-handling.md

event-management.md

index.md

native-modules.md

native-views.md

permissions.md

platform-utilities.md

utilities.md

tile.json