|
| 1 | +/** |
| 2 | + * Optional react-native-pulsar adapter. |
| 3 | + * |
| 4 | + * Pulsar exposes its haptics through a Turbo Module ('RNPulsar'), so it only |
| 5 | + * works on the New Architecture and never in Expo Go. Like the expo-haptics |
| 6 | + * adapter, we never import the package: we look its native module up in the |
| 7 | + * Turbo Module registry, so Pulsar is used automatically when a consumer has |
| 8 | + * installed it and ignored everywhere else. That keeps it out of the |
| 9 | + * dependency tree and leaves bare old-architecture builds untouched. |
| 10 | + * |
| 11 | + * `Pulsar_play` is synchronous and Pulsar's own presets call it from worklets, |
| 12 | + * so we fire it directly on the UI thread without hopping to JS. |
| 13 | + */ |
| 14 | + |
| 15 | +import { type TurboModule, TurboModuleRegistry } from 'react-native'; |
| 16 | + |
| 17 | +import type { HapticsAdapter, HapticTrigger } from './types'; |
| 18 | + |
| 19 | +// Native preset names backing Pulsar's `Presets.System.impact*` helpers. |
| 20 | +const PRESET = { |
| 21 | + impactLight: 'SystemImpactLight', |
| 22 | + impactMedium: 'SystemImpactMedium' |
| 23 | +} as const; |
| 24 | + |
| 25 | +interface PulsarModule extends TurboModule { |
| 26 | + Pulsar_play(name: string): void; |
| 27 | +} |
| 28 | + |
| 29 | +const load = (): HapticTrigger | null => { |
| 30 | + const pulsar = TurboModuleRegistry.get<PulsarModule>('RNPulsar'); |
| 31 | + |
| 32 | + // Touching the method on the JS thread also primes the prototype cache so it |
| 33 | + // stays callable from the UI worklet (matches Pulsar's own workaround). |
| 34 | + if (!pulsar?.Pulsar_play) { |
| 35 | + return null; |
| 36 | + } |
| 37 | + |
| 38 | + const trigger: HapticTrigger = (type = 'impactLight') => { |
| 39 | + 'worklet'; |
| 40 | + // eslint-disable-next-line new-cap -- external Turbo Module method name |
| 41 | + pulsar.Pulsar_play( |
| 42 | + type === 'impactMedium' ? PRESET.impactMedium : PRESET.impactLight |
| 43 | + ); |
| 44 | + }; |
| 45 | + |
| 46 | + return trigger; |
| 47 | +}; |
| 48 | + |
| 49 | +const Pulsar: HapticsAdapter = { |
| 50 | + load, |
| 51 | + name: 'react-native-pulsar' |
| 52 | +}; |
| 53 | + |
| 54 | +export default Pulsar; |
0 commit comments