expo-widgetkit-bridge
v0.2.0
Published
Reload iOS home & lock screen widgets from React Native / Expo. A one-call bridge to WidgetKit's reloadAllTimelines and reloadTimelines(ofKind:).
Maintainers
Readme
expo-widgetkit-bridge
Features
reloadAllTimelines:- Reloads every widget your app provides.
- One-line call from JS after your data source changes.
reloadTimelines(ofKind:):- Reloads a single widget kind — the
kindstring you pass to yourWidget's configuration. - Useful when only part of your data changed and you want to spare battery.
- Reloads a single widget kind — the
getCurrentConfigurations:- Enumerate widgets the user has installed on their home / lock screen.
- Returns
{ kind, family }per widget — including iOS 16+ Lock Screen accessories.
Zero runtime cost:- No-ops on non-iOS platforms so you can call it unconditionally from cross-platform code.
Expo Modules API:- Ships as a modern Expo Module — no manual
.mbridge, no config plugin, no linking. Justnpx expo installand go.
- Ships as a modern Expo Module — no manual
Installation
npx expo install expo-widgetkit-bridgeThen rebuild your dev client (this package uses native code, so it is not available in Expo Go):
npx expo prebuild
npx expo run:iosSetup
No config plugin, no entitlements, no manual Xcode steps.
The package weak-links WidgetKit.framework automatically so it stays safe on iOS 13 devices (where it becomes a no-op).
If you do not yet have a widget target in your app, add one with expo-target or with expo-ios-widget-scaffold — this package only reloads existing widgets, it does not create them.
Usage
import {
reloadAllTimelines,
reloadTimelines,
getCurrentConfigurations,
isLockScreenSupported,
getLockScreenConfigurations,
hasWidget,
} from 'expo-widgetkit-bridge';
// After you save new data that the widget renders:
reloadAllTimelines();
// Or reload just one widget kind:
reloadTimelines('ScheduleWidget');
// Show which widgets the user has installed:
const installed = await getCurrentConfigurations();
// [{ kind: 'ScheduleWidget', family: 'systemMedium' }, ...]
// Lock Screen widgets are iOS 16+ only. Gate any onboarding UI:
if (isLockScreenSupported()) {
const lock = await getLockScreenConfigurations();
if (lock.length === 0) {
// Suggest the user to add a Lock Screen widget.
}
}
// Quick shorthand: is any widget of this kind installed?
if (await hasWidget('ScheduleWidget')) {
// …
}API reference
| Function | Signature | Description |
| -------- | --------- | ----------- |
| reloadAllTimelines | () => void | Calls WidgetCenter.shared.reloadAllTimelines(). |
| reloadTimelines | (kind: string) => void | Calls WidgetCenter.shared.reloadTimelines(ofKind:). |
| getCurrentConfigurations | () => Promise<WidgetInfo[]> | Wraps WidgetCenter.shared.getCurrentConfigurations. Resolves [] on iOS < 14 and non-iOS platforms. |
| isLockScreenSupported | () => boolean | true only on iOS ≥ 16 (where accessory families are available). |
| getLockScreenConfigurations | () => Promise<WidgetInfo[]> | Filtered getCurrentConfigurations() — only accessory families. |
| getHomeScreenConfigurations | () => Promise<WidgetInfo[]> | Filtered getCurrentConfigurations() — excludes accessory families. |
| hasWidget | (kind: string) => Promise<boolean> | true if any widget of that kind is installed. |
| getFamiliesForKind | (kind: string) => Promise<WidgetFamily[]> | Families the user picked for that kind. |
type WidgetFamily =
| 'systemSmall'
| 'systemMedium'
| 'systemLarge'
| 'systemExtraLarge'
| 'accessoryCircular'
| 'accessoryRectangular'
| 'accessoryInline'
| 'unknown';
interface WidgetInfo {
kind: string;
family: WidgetFamily;
}Requirements
- iOS 14.0+ for
reloadAllTimelines/reloadTimelines/getCurrentConfigurations. - iOS 15.0+ for
systemExtraLarge. - iOS 16.0+ for
accessoryCircular/accessoryRectangular/accessoryInline. - Expo SDK 54+ (uses Expo Modules API).
- Xcode 15+.
Non-iOS calls are silent no-ops (Promise<[]> for getCurrentConfigurations).
How it works
The module is a thin Swift wrapper around WidgetCenter.shared using the Expo Modules API — no legacy RCTBridgeModule or Objective-C shim. The WidgetKit.framework is weak-linked, so the module loads cleanly on iOS 13 devices even though the WidgetKit symbols aren't available there; at runtime we guard each call with #available(iOS 14.0, *).
For getCurrentConfigurations, we normalize WidgetKit's WidgetInfo.family enum into stable string identifiers so you can switch on them from TypeScript without pulling in Swift-side constants.
Contributing
The example/ directory contains a minimal Expo app that exercises every API.
git clone https://github.com/kostyabet/expo-widgetkit-bridge
cd expo-widgetkit-bridge
npm install
npm run build
cd example
npm install
npx expo run:iosPull requests welcome — please add a CHANGELOG.md entry.
Source code
GitHub repo
License
MIT
Support
Press star on our GitHub repo please!
