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 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-save-to-calendar

v0.0.4

Published

React Native module that opens the system add-event sheet on iOS and Android. Supports both the New and Legacy architectures. No calendar permission required — the OS handles its own permission prompt as part of the save flow.

Readme

react-native-save-to-calendar

Open the system Add Event sheet on iOS and Android from a React Native app.

The library never writes events itself — it just opens the OS-provided "create event" UI pre-filled with your data. The user reviews, picks a calendar, and saves. Because the system handles its own permission flow, the library does not request WRITE_CALENDAR (Android) or EKEntityType.event (iOS) write access on your behalf.

Features

  • One JS API, two platforms: presentEventDialog(event) → Promise<{ action: 'saved' | 'canceled' | 'deleted' }>.
  • Pre-fills title, start / end, location, notes, and all-day.
  • iOS uses EKEventEditViewController (EventKit + EventKitUI) and returns the user's real choice.
  • Android launches Intent.ACTION_INSERT against CalendarContract.Events — no permissions needed.
  • Works on the New Architecture (TurboModule via Codegen) and the Legacy bridge — the consumer doesn't need to opt in.
  • Ships with TypeScript types out of the box.

Requirements

| Platform | Minimum | | ------------ | ---------------------------------------------------------------------------------------- | | React Native | >= 0.71 (needs TurboModule + Codegen support). | | iOS | Deployment target inherited from the host app (min_ios_version_supported, 13.4+). | | Android | minSdkVersion 24, compileSdkVersion 35, Java 17, Kotlin 2.1.20 (overridable). |

The Kotlin version can be overridden by setting kotlinVersion in your root android/build.gradle. The Android module pulls compileSdkVersion / minSdkVersion / targetSdkVersion from your root ext if defined.

Expo

This library ships native code, so it does not run in Expo Go. It does work in:

  • Bare React Native projects.
  • Expo projects using prebuild or the Expo Dev Client (autolinking handles it on expo prebuild).

There is no Expo config plugin — the iOS Info.plist keys below must be added through your Expo app.json ios.infoPlist block or through prebuild.

Installation

npm install react-native-save-to-calendar
# or
yarn add react-native-save-to-calendar

iOS only — install the pod:

cd ios && pod install

Autolinking handles the rest on both platforms.

iOS setup

Add both keys to your app's Info.plist:

<key>NSCalendarsUsageDescription</key>
<string>Add this event to your calendar.</string>
<key>NSCalendarsWriteOnlyAccessUsageDescription</key>
<string>Add this event to your calendar.</string>
  • NSCalendarsWriteOnlyAccessUsageDescription is the iOS 17+ key. EKEventEditViewController requests write-only access on modern iOS and the system will silently fail without this string.
  • NSCalendarsUsageDescription is the legacy key for iOS 16 and earlier.

App Store review requires both even though EKEventEditViewController handles its own permission prompt internally — keep both regardless of your deployment target.

Android setup

Nothing. Intent.ACTION_INSERT doesn't require WRITE_CALENDAR or any other manifest permission.

Usage

import { presentEventDialog } from 'react-native-save-to-calendar';

const start = new Date('2026-06-01T15:00:00Z');
const end = new Date('2026-06-01T16:00:00Z');

try {
  const result = await presentEventDialog({
    title: 'Doctor appointment',
    startDate: start.toISOString(),
    endDate: end.toISOString(),
    location: 'Clinic, 221B Baker St',
    notes: 'Bring reports',
    allDay: false,
  });

  if (result.action === 'saved') {
    // iOS: the user committed the event.
    // Android: the OS reported RESULT_OK. Many calendar apps do NOT report this
    // even after a successful save — see Platform behaviour below.
  } else if (result.action === 'canceled') {
    // User dismissed the editor / chooser, OR (Android) the calendar app
    // finished without reporting success. Treat as "not confirmed", not failure.
  } else if (result.action === 'deleted') {
    // user tapped Delete on an existing event (iOS only)
  }
} catch (err) {
  // err.code will be one of E_INVALID_ARGS, E_NO_PRESENTER, E_NO_CALENDAR_APP,
  // E_NO_ACTIVITY, E_IN_PROGRESS, or E_CALENDAR — see the Reject reasons table below.
  console.warn('Calendar dialog failed:', err);
}

API

presentEventDialog(event)

| Field | Type | Required | Notes | | ------------ | --------- | -------- | --------------------------------------------------------------------- | | title | string | yes | Event title shown in the editor. | | startDate | string | yes | ISO 8601 datetime, e.g. the output of new Date(...).toISOString(). | | endDate | string | yes | ISO 8601 datetime. | | location | string | no | Free-form location text. | | notes | string | no | Event description / notes. | | allDay | boolean | no | Default false. |

Returns: Promise<{ action: 'saved' | 'canceled' | 'deleted' }>.

Platform behaviour

  • iOS — returns the real user choice via the EKEventEditViewDelegate callback. 'deleted' only fires if the user editing an existing event chooses Delete.

  • Android — the dialog is launched with startActivityForResult and the result is mapped from the returned activity result code: RESULT_OK → 'saved', anything else → 'canceled'. This means dismissing the "Complete action using" app chooser (or backing out before saving) reliably resolves 'canceled'.

    ⚠️ Android ACTION_INSERT limitation. ACTION_INSERT is fire-and-forget by design. Most calendar apps (Google Calendar, Samsung Calendar, Outlook, …) finish without calling setResult(RESULT_OK) even after the user saves — so a genuine save frequently also resolves as 'canceled'. Therefore on Android:

    • 'saved' is a strong signal (the app explicitly reported success) but is not emitted by every calendar app.
    • 'canceled' means "not confirmed" — the user may have cancelled, or saved in an app that doesn't report the result. It does not reliably mean the event was not created.

    Reliably detecting a real save would require READ_CALENDAR permission to query the provider after the editor closes, which this library deliberately avoids. Design your UX so that a non-'saved' result is treated as "outcome unknown" rather than a hard failure — the calendar app shows its own save confirmation regardless.

Reject reasons

| Code | Platform | Cause | | --------------------- | -------- | ------------------------------------------------------------ | | E_INVALID_ARGS | iOS | Missing or unparsable title, startDate, or endDate. | | E_NO_PRESENTER | iOS | No view controller available to present the editor. | | E_ALREADY_OPEN | iOS | A calendar dialog is already open. | | E_NO_CALENDAR_APP | Android | No installed activity handles ACTION_INSERT for events. | | E_NO_ACTIVITY | Android | No foreground activity available to launch the dialog. | | E_IN_PROGRESS | Android | A calendar dialog is already open. | | E_CALENDAR | Android | Generic failure (bad ISO date, intent launch exception). |

Architecture support

  • New Architecture (Fabric / TurboModules): the library declares a Codegen spec (src/NativeSaveToCalendar.ts) and ships a TurboModule on both platforms.
  • Legacy: the library registers a bridge module (RCT_EXTERN_MODULE on iOS, ReactContextBaseJavaModule on Android) selected via dual src/newarch / src/oldarch source sets on Android.

No consumer-side opt-in is needed for either mode.

License

MIT © Aditya Thummar