@symbiote-native/haptics 3.0.1 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +38 -28
  2. package/package.json +15 -15
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # @symbiote-native/haptics
2
2
 
3
3
  Port of [`expo-haptics`](https://docs.expo.dev/versions/latest/sdk/haptics/) for
4
- [SymbioteNative](../../README.md) — impact/notification/selection vibration feedback via iOS's
4
+ [SymbioteNative](../../README.md) - impact/notification/selection vibration feedback via iOS's
5
5
  Taptic Engine and Android's Vibrator API, plus a direct Android haptics-engine path
6
6
  (`performAndroidHapticsAsync`). Built the same way as
7
7
  [`@symbiote-native/local-auth`](../local-auth): an `expo-modules-core`-based wrapper, free
8
- functions with no per-instance state and no event stream. Reachable from every adapter — React,
9
- Vue, Svelte, Solid, Angular — not just React.
8
+ functions with no per-instance state and no event stream. Reachable from every adapter - React,
9
+ Vue, Svelte, Solid, Angular - not just React.
10
10
 
11
11
  ## Install
12
12
 
@@ -22,40 +22,40 @@ npx @symbiote-native/cli new my-app --haptics
22
22
  npx @symbiote-native/cli add --haptics
23
23
  ```
24
24
 
25
- Either way: installs `@symbiote-native/haptics` and wires the native autolinking automatically —
25
+ Either way: installs `@symbiote-native/haptics` and wires the native autolinking automatically,
26
26
  see [`@symbiote-native/cli`](../cli).
27
27
 
28
28
  <details>
29
- <summary>Manual install (no CLI — installing and wiring native autolinking by hand)</summary>
29
+ <summary>Manual install (no CLI - installing and wiring native autolinking by hand)</summary>
30
30
 
31
31
  ```bash
32
32
  npm install @symbiote-native/haptics
33
33
  ```
34
34
 
35
- `expo-haptics` and `expo-modules-core` come along as regular, exact-pinned dependencies — never
35
+ `expo-haptics` and `expo-modules-core` come along as regular, exact-pinned dependencies - never
36
36
  install either yourself, and never add the `expo` meta-package (it bundles its own Metro/Babel
37
37
  pipeline that conflicts with this project's own).
38
38
 
39
39
  ### Required one-time step: native autolinking wiring
40
40
 
41
41
  Unlike a plain RN native module, `expo-haptics`' native code is discovered by
42
- `expo-modules-autolinking`, not RN's own `react-native.config.cjs`/podspec mechanism — this needs
42
+ `expo-modules-autolinking`, not RN's own `react-native.config.cjs`/podspec mechanism - this needs
43
43
  wiring into the native host app **once**, covering this package and every other
44
44
  `expo-modules-core` package with zero further changes:
45
45
 
46
46
  | Platform | Touches |
47
47
  | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
48
- | iOS | `ios/Podfile` — add `use_expo_modules!` |
49
- | iOS | `AppDelegate.swift` — Expo's runtime-bootstrap hook |
50
- | Android | `settings.gradle` / `app/build.gradle` — resolve and include the Expo Gradle projects |
51
- | Android | `MainApplication.kt` — Expo's bootstrap hook, plus a hand-written native-module name map (there's no `expo` meta-package here to auto-generate one) |
48
+ | iOS | `ios/Podfile` - add `use_expo_modules!` |
49
+ | iOS | `AppDelegate.swift` - Expo's runtime-bootstrap hook |
50
+ | Android | `settings.gradle` / `app/build.gradle` - resolve and include the Expo Gradle projects |
51
+ | Android | `MainApplication.kt` - Expo's bootstrap hook, plus a hand-written native-module name map (there's no `expo` meta-package here to auto-generate one) |
52
52
 
53
53
  Full mechanics live in the `symbiote-expo-native-module` project skill. Reference
54
54
  implementation: `examples/expo-react/ios/Podfile` and
55
55
  `examples/expo-react/android/app/src/main/java/com/canaryexpo/MainApplication.kt` (registers
56
56
  `HapticsModule` as `"ExpoHaptics"`).
57
57
 
58
- No permission or `Info.plist`/`AndroidManifest.xml` entry is needed on either platform — haptic
58
+ No permission or `Info.plist`/`AndroidManifest.xml` entry is needed on either platform - haptic
59
59
  feedback requires none.
60
60
 
61
61
  </details>
@@ -67,10 +67,10 @@ src/core/ notificationAsync / impactAsync / selectionAsync / performAndroidH
67
67
  plus NotificationFeedbackType / ImpactFeedbackStyle / AndroidHaptics.
68
68
  native-module.ts resolves the ExpoHaptics native module via
69
69
  expo-modules-core's requireNativeModule.
70
- src/angular/ @symbiote-native/haptics/angular — plain re-export of core.
70
+ src/angular/ @symbiote-native/haptics/angular - plain re-export of core.
71
71
  ```
72
72
 
73
- Upstream ships four async functions and three enums, not a subscribable sensor — there's
73
+ Upstream ships four async functions and three enums, not a subscribable sensor - there's
74
74
  nothing per-framework to add, so `./react`, `./vue`, `./svelte`, and `./solid` are
75
75
  `exports`-map aliases straight onto `src/core/` (no physical per-framework file). `./angular`
76
76
  stays a physical file/subpath since Angular ships through a separate `ngc`/AOT build
@@ -79,7 +79,7 @@ stays a physical file/subpath since Angular ships through a separate `ngc`/AOT b
79
79
  ## Use it
80
80
 
81
81
  ```tsx
82
- // React — examples/expo-react/screens/HapticsScreen.tsx
82
+ // React - examples/expo-react/screens/HapticsScreen.tsx
83
83
  import {
84
84
  impactAsync,
85
85
  ImpactFeedbackStyle,
@@ -106,7 +106,7 @@ function HapticsScreen() {
106
106
  ```
107
107
 
108
108
  ```vue
109
- <!-- Vue — examples/expo-vue-sfc/screens/HapticsScreen.vue -->
109
+ <!-- Vue - examples/expo-vue-sfc/screens/HapticsScreen.vue -->
110
110
  <script setup lang="ts">
111
111
  import {
112
112
  impactAsync,
@@ -129,7 +129,7 @@ function fireImpact(style: ImpactFeedbackStyle): void {
129
129
  ```
130
130
 
131
131
  ```svelte
132
- <!-- Svelte — examples/expo-svelte/screens/HapticsScreen.svelte -->
132
+ <!-- Svelte - examples/expo-svelte/screens/HapticsScreen.svelte -->
133
133
  <script lang="ts">
134
134
  import {
135
135
  impactAsync,
@@ -152,7 +152,7 @@ function fireImpact(style: ImpactFeedbackStyle): void {
152
152
  ```
153
153
 
154
154
  ```tsx
155
- // Solid — examples/expo-solid/screens/HapticsScreen.tsx
155
+ // Solid - examples/expo-solid/screens/HapticsScreen.tsx
156
156
  import {
157
157
  impactAsync,
158
158
  ImpactFeedbackStyle,
@@ -179,7 +179,7 @@ function HapticsScreen() {
179
179
  ```
180
180
 
181
181
  ```ts
182
- // Angular — examples/expo-angular/src/screens/HapticsScreen.ts
182
+ // Angular - examples/expo-angular/src/screens/HapticsScreen.ts
183
183
  import { Component } from '@angular/core';
184
184
  import {
185
185
  impactAsync,
@@ -202,7 +202,7 @@ export class HapticsScreen {
202
202
  }
203
203
  ```
204
204
 
205
- Every call is fire-and-forget (no result to await) — a real device is needed to feel the
205
+ Every call is fire-and-forget (no result to await) - a real device is needed to feel the
206
206
  feedback, a simulator produces none. Android also gets `performAndroidHapticsAsync`, which
207
207
  drives the device haptics engine directly instead of `impactAsync`'s Vibrator simulation; it
208
208
  no-ops on every other platform.
@@ -213,24 +213,24 @@ Free functions, no event stream, no per-instance state:
213
213
 
214
214
  ```ts
215
215
  notificationAsync(type?: NotificationFeedbackType): Promise<void>
216
- // Success/Warning/Error feedback — UINotificationFeedbackType on iOS, simulated via Vibrator on Android.
216
+ // Success/Warning/Error feedback - UINotificationFeedbackType on iOS, simulated via Vibrator on Android.
217
217
 
218
218
  impactAsync(style?: ImpactFeedbackStyle): Promise<void>
219
- // Collision-weight feedback (Light/Medium/Heavy/Soft/Rigid) — UIImpactFeedbackStyle on iOS, simulated via Vibrator on Android.
219
+ // Collision-weight feedback (Light/Medium/Heavy/Soft/Rigid) - UIImpactFeedbackStyle on iOS, simulated via Vibrator on Android.
220
220
 
221
221
  selectionAsync(): Promise<void>
222
222
  // Lets the user know a selection change was registered.
223
223
 
224
224
  performAndroidHapticsAsync(type: AndroidHaptics): Promise<void>
225
- // Android only — no-ops on other platforms. Uses the device haptics engine directly, unlike the Vibrator-based impactAsync.
225
+ // Android only - no-ops on other platforms. Uses the device haptics engine directly, unlike the Vibrator-based impactAsync.
226
226
  ```
227
227
 
228
- Plus `NotificationFeedbackType`, `ImpactFeedbackStyle`, `AndroidHaptics` — ported verbatim from
228
+ Plus `NotificationFeedbackType`, `ImpactFeedbackStyle`, `AndroidHaptics` - ported verbatim from
229
229
  upstream's `Haptics.types.ts`.
230
230
 
231
231
  ```ts
232
232
  import { impactAsync, ImpactFeedbackStyle } from '@symbiote-native/haptics';
233
- // or the framework-scoped entry points — identical surface, re-exported verbatim:
233
+ // or the framework-scoped entry points - identical surface, re-exported verbatim:
234
234
  import { impactAsync } from '@symbiote-native/haptics/react';
235
235
  import { impactAsync } from '@symbiote-native/haptics/vue';
236
236
  import { impactAsync } from '@symbiote-native/haptics/svelte';
@@ -238,17 +238,27 @@ import { impactAsync } from '@symbiote-native/haptics/solid';
238
238
  import { impactAsync } from '@symbiote-native/haptics/angular';
239
239
  ```
240
240
 
241
+ ## Common questions
242
+
243
+ - **Nothing on the iOS Simulator.** It never fires haptics; use a device.
244
+ - **Nothing on a real iPhone.** Low Power Mode, active camera or dictation, or system haptics off.
245
+ - **Silent in a standalone Android build.** Reported upstream; test a release build.
246
+
247
+ Sources: [Expo docs: Haptics](https://docs.expo.dev/versions/latest/sdk/haptics/),
248
+ [expo/expo#16218](https://github.com/expo/expo/issues/16218),
249
+ [expo/expo#6375](https://github.com/expo/expo/issues/6375).
250
+
241
251
  ## Test it
242
252
 
243
- No Fabric/Descriptor angle at all — haptics is a pure async-function surface, never a view.
253
+ No Fabric/Descriptor angle at all - haptics is a pure async-function surface, never a view.
244
254
  Tests exercise the JS layer via a fake native module in place of the real
245
- `requireNativeModule` resolution (`vitest`, `src/**/*.test.{ts,tsx}`) — no `installFabric()`, no
255
+ `requireNativeModule` resolution (`vitest`, `src/**/*.test.{ts,tsx}`) - no `installFabric()`, no
246
256
  ViewConfig. Native rendering itself is verified on-device (see the parent
247
257
  [README](../../README.md)).
248
258
 
249
259
  Native wiring for this package is done across all six `examples/expo-*` canary apps (Android
250
260
  3-layer registration in each app's `build.gradle`/`MainApplication.kt`/`AndroidManifest.xml`,
251
- plus iOS Podfile/pod install) — not yet ported into the plain, non-Expo public canaries
261
+ plus iOS Podfile/pod install) - not yet ported into the plain, non-Expo public canaries
252
262
  (`examples/react`, `examples/vue-sfc`, `examples/vue-tsx`, `examples/svelte`, `examples/solid`,
253
263
  `examples/angular`), and no on-device/simulator automated (Detox) smoke test exists yet, only
254
264
  manual verification.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbiote-native/haptics",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "description": "expo-haptics wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, Svelte, Solid, and Angular adapters. Impact/notification/selection vibration feedback via iOS's Taptic Engine and Android's Vibrator API.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -70,7 +70,7 @@
70
70
  },
71
71
  "dependencies": {
72
72
  "expo-haptics": "57.0.1",
73
- "expo-modules-core": "57.0.5"
73
+ "expo-modules-core": "57.0.20"
74
74
  },
75
75
  "peerDependencies": {
76
76
  "@angular/core": ">=20",
@@ -80,12 +80,12 @@
80
80
  "solid-js": ">=1.9.0",
81
81
  "svelte": ">=5.56.0",
82
82
  "vue": ">=3.5.0",
83
- "@symbiote-native/angular": "^3.1.1",
84
- "@symbiote-native/engine": "^1.3.0",
85
- "@symbiote-native/react": "^3.0.3",
86
- "@symbiote-native/solid": "^3.0.3",
87
- "@symbiote-native/svelte": "^3.0.3",
88
- "@symbiote-native/vue": "^3.0.3"
83
+ "@symbiote-native/angular": "^3.2.0",
84
+ "@symbiote-native/engine": "^1.5.0",
85
+ "@symbiote-native/react": "^3.2.0",
86
+ "@symbiote-native/solid": "^3.1.0",
87
+ "@symbiote-native/svelte": "^3.1.0",
88
+ "@symbiote-native/vue": "^3.2.0"
89
89
  },
90
90
  "peerDependenciesMeta": {
91
91
  "@symbiote-native/angular": {
@@ -133,13 +133,13 @@
133
133
  "solid-js": "^1.9.14",
134
134
  "svelte": "^5.56.0",
135
135
  "typescript": "~6.0.0",
136
- "@symbiote-native/angular": "3.1.1",
137
- "@symbiote-native/engine": "1.3.0",
138
- "@symbiote-native/react": "3.0.3",
139
- "@symbiote-native/solid": "3.0.3",
140
- "@symbiote-native/svelte": "3.0.3",
141
- "@symbiote-native/test-utils": "0.4.3",
142
- "@symbiote-native/vue": "3.0.3"
136
+ "@symbiote-native/angular": "3.2.0",
137
+ "@symbiote-native/engine": "1.5.0",
138
+ "@symbiote-native/react": "3.2.0",
139
+ "@symbiote-native/solid": "3.1.0",
140
+ "@symbiote-native/svelte": "3.1.0",
141
+ "@symbiote-native/test-utils": "0.4.6",
142
+ "@symbiote-native/vue": "3.2.0"
143
143
  },
144
144
  "scripts": {
145
145
  "typecheck": "tsc --build",