npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

react-native-dynamic-activities

v0.1.0

Published

react-native-dynamic-activities is a react native package built with Nitro Modules to allow you easily integrate Live Activities into your react-native app

Readme

Version Downloads License

Overview

React Native Dynamic Activities gives you a simple, type-safe way to start, update, and end iOS Live Activities from JavaScript. It uses Nitro Modules for zero-bridge, JSI-backed performance and auto-generated Swift/TypeScript types.

Demo video (coming soon)

[Placeholder for short demo video/GIF showcasing starting, updating, and ending a Live Activity.]

Production readiness

  • iOS: Implemented using ActivityKit. Tested via unit tests and example app. Requires iOS 16.2+.
  • Android: Not supported (APIs reject with a clear error).
  • Status: Pre-1.0. Ready for 0.1.0 iOS-only release. API is small and type-safe; surface may evolve.

Requirements

  • React Native ≥ 0.76 (Nitro Views require RN ≥ 0.78, but this package does not require Nitro Views)
  • Node ≥ 18
  • iOS ≥ 16.2 (ActivityKit), Xcode 15+

Installation

npm i react-native-dynamic-activities react-native-nitro-modules
# or
bun add react-native-dynamic-activities react-native-nitro-modules

Autolinking handles native integration. No manual linking required.

Screenshot placeholder

[Add a screenshot of the example widget running on device/lock screen here.]

iOS setup

🚀 Quick Setup (Recommended)

Use the built-in widget scaffolder to generate everything automatically:

# Generate widget with defaults
npx react-native-dynamic-activities create-widget

# Custom configuration
npx react-native-dynamic-activities create-widget \
  --name=TimerWidget \
  --activity=TimerActivity \
  --bundle-id=com.yourapp.timer.widget

This creates complete Swift files, ActivityKit integration, and UI templates. Then just add the Widget Extension target in Xcode and replace the generated files.

📱 Expo Projects

For Expo managed workflow, add the config plugin:

// app.config.js
export default {
	expo: {
		plugins: [
			[
				'react-native-dynamic-activities',
				{
					widgetName: 'MyAppWidget',
					activityName: 'MyActivity',
				},
			],
		],
	},
};

🛠 Manual Setup

Live Activities require a Widget Extension (WidgetKit + ActivityKit) and entitlements.

  1. Add entitlements to your iOS app target:
  • Enable "Live Activities" capability.
  1. Create a Widget Extension in Xcode:
  • File -> New -> Target… -> Widget Extension.
  • Check "Include Live Activity" if available, or add an Activity configuration manually.
  • Minimum iOS target: 16.2 or higher.
  1. Define your Activity attributes and widget UI. Example:
// In your Widget Extension target
import ActivityKit
import SwiftUI

struct TimerAttributes: ActivityAttributes {
  public struct ContentState: Codable, Hashable {
    var state: String // "active", "ended", etc.
    var relevanceScore: Double?
  }
  var title: String
  var body: String
}

@main
struct TimerWidgetBundle: WidgetBundle {
  var body: some Widget {
    TimerLiveActivity()
  }
}

struct TimerLiveActivity: Widget {
  var body: some WidgetConfiguration {
    ActivityConfiguration(for: TimerAttributes.self) { context in
      // Lock Screen / Banner UI
      HStack {
        Text(context.attributes.title)
        Text(context.state.state)
      }
    } dynamicIsland: { context in
      DynamicIsland {
        DynamicIslandExpandedRegion(.leading) { Text(context.attributes.title) }
        DynamicIslandExpandedRegion(.trailing) { Text("\(context.state.relevanceScore ?? 0, specifier: "%.2f")") }
      } compactLeading: {
        Text("T")
      } compactTrailing: {
        Text("⏱")
      } minimal: {
        Text("T")
      }
    }
  }
}

Note: The JS-facing types (LiveActivityAttributes, LiveActivityContent) should semantically match your Swift ActivityAttributes and ContentState fields you use in the widget.

Tip: Keep your Swift attributes and the TS interfaces aligned for predictable rendering in your Widget UI.

Usage

import {
	DynamicActivities,
	type LiveActivityAttributes,
	type LiveActivityContent,
} from 'react-native-dynamic-activities';

// Check support and OS version
const info = await DynamicActivities.areLiveActivitiesSupported();
// { supported: boolean, version: number, comment: string }

// Start an activity
const attributes: LiveActivityAttributes = {
	title: 'Timer',
	body: 'Counting down',
};
const content: LiveActivityContent = { state: 'active', relevanceScore: 1 };
const { activityId, pushToken } = await DynamicActivities.startLiveActivity(
	attributes,
	content
);

// Update activity
await DynamicActivities.updateLiveActivity(activityId, {
	state: 'active',
	relevanceScore: 0.8,
});

// End activity
await DynamicActivities.endLiveActivity(
	activityId,
	{ state: 'ended' },
	'default'
);

Error handling

Native errors are normalized with helpful messages and codes (matching ActivityAuthorizationError where applicable).

import {
	LiveActivityErrorFactory,
	isLiveActivityError,
	LiveActivityErrorCode,
} from 'react-native-dynamic-activities';

try {
	await DynamicActivities.startLiveActivity(attributes, content);
} catch (e) {
	const err = LiveActivityErrorFactory.createErrorFromNativeError(e);
	if (isLiveActivityError(err)) {
		if (err.code === LiveActivityErrorCode.DENIED) {
			// guide user to enable in Settings
		}
	}
}

Example app

The repo includes an example app demonstrating a simple timer Live Activity.

# From repo root
npm i

# iOS (requires Ruby + Bundler)
cd example
npm i
bundle install
bundle exec pod install --project-directory=ios
npm run ios

Note: You must add a Widget Extension and enable the Live Activities entitlement in the example app (Xcode) for the system UI to appear on the Lock Screen/Dynamic Island.

For complete setup documentation, see WIDGET_SETUP.md.

API

  • areLiveActivitiesSupported(): Promise<{ supported: boolean; version: number; comment: string }>
  • startLiveActivity(attributes, content, pushToken?, style?, alertConfiguration?, start?): Promise<{ activityId: string; pushToken?: string }>
  • updateLiveActivity(activityId, content, alertConfiguration?, timestamp?): Promise<void>
  • endLiveActivity(activityId, content, dismissalPolicy?): Promise<void>

Platform notes:

  • iOS only. Android methods reject with an error.
  • Some parameters are available only on newer iOS versions (e.g., style on 18.0+, timestamp support on 17.2+). See TS spec docs.

Troubleshooting

  • No widget shown: Ensure the app has a Widget Extension configured and Live Activities capability enabled.
  • denied errors: User disabled Live Activities; guide them to Settings.
  • Simulator support is limited. Test on a physical device for Dynamic Island/Lock Screen.
  • If build errors mention Nitro types, run npm run codegen and clean Xcode build.

Contributing

See CONTRIBUTING.md for development, testing, and PR guidelines.

Credits

Bootstrapped with create-nitro-module.

License

MIT © Pieczasz