@symbiote-native/haptics 0.0.1 → 0.2.0
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.
- package/README.md +130 -21
- package/build/angular/index.d.ts +1 -0
- package/build/angular/index.js +4 -0
- package/build/core/haptics.d.ts +24 -0
- package/build/core/haptics.js +50 -0
- package/build/core/index.d.ts +2 -0
- package/build/core/index.js +2 -0
- package/build/core/native-module.d.ts +8 -0
- package/build/core/native-module.js +3 -0
- package/build/core/types.d.ts +86 -0
- package/build/core/types.js +89 -0
- package/build/react/index.d.ts +1 -0
- package/build/react/index.js +5 -0
- package/build/svelte/index.d.ts +1 -0
- package/build/svelte/index.js +6 -0
- package/build/vue/index.d.ts +1 -0
- package/build/vue/index.js +4 -0
- package/build-ngc/angular/index.d.ts +1 -0
- package/build-ngc/angular/index.js +5 -0
- package/build-ngc/angular/index.js.map +1 -0
- package/build-ngc/core/haptics.d.ts +24 -0
- package/build-ngc/core/haptics.js +51 -0
- package/build-ngc/core/haptics.js.map +1 -0
- package/build-ngc/core/index.d.ts +2 -0
- package/build-ngc/core/index.js +3 -0
- package/build-ngc/core/index.js.map +1 -0
- package/build-ngc/core/native-module.d.ts +8 -0
- package/build-ngc/core/native-module.js +4 -0
- package/build-ngc/core/native-module.js.map +1 -0
- package/build-ngc/core/types.d.ts +86 -0
- package/build-ngc/core/types.js +90 -0
- package/build-ngc/core/types.js.map +1 -0
- package/native-link.json +12 -0
- package/package.json +106 -1
- package/src/angular/index.ts +4 -0
- package/src/core/haptics.ts +60 -0
- package/src/core/index.ts +7 -0
- package/src/core/native-module.ts +20 -0
- package/src/core/types.ts +88 -0
- package/src/react/index.ts +5 -0
- package/src/svelte/index.ts +6 -0
- package/src/vue/index.ts +4 -0
package/README.md
CHANGED
|
@@ -1,18 +1,116 @@
|
|
|
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
|
|
5
|
+
Taptic Engine and Android's Vibrator API, plus a direct Android haptics-engine path
|
|
6
|
+
(`performAndroidHapticsAsync`). Built the same way as
|
|
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, Angular — not just React.
|
|
4
10
|
|
|
5
|
-
|
|
6
|
-
[SymbioteNative](../../README.md) — vibration/haptic feedback via iOS's Taptic Engine and
|
|
7
|
-
Android's Vibrator API, reachable from every adapter (React, Vue, Angular), not just React.
|
|
8
|
-
Nothing is wired up yet: no `src/`, no dependencies, no build.
|
|
11
|
+
## Install
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
```bash
|
|
14
|
+
npm install @symbiote-native/haptics
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`expo-haptics` and `expo-modules-core` come along as regular, exact-pinned dependencies — never
|
|
18
|
+
install either yourself, and never add the `expo` meta-package (it bundles its own Metro/Babel
|
|
19
|
+
pipeline that conflicts with this project's own).
|
|
20
|
+
|
|
21
|
+
### Required one-time step: native autolinking wiring
|
|
22
|
+
|
|
23
|
+
Unlike a plain RN native module, `expo-haptics`' native code is discovered by
|
|
24
|
+
`expo-modules-autolinking`, not RN's own `react-native.config.cjs`/podspec mechanism — this needs
|
|
25
|
+
wiring into the native host app **once**, covering this package and every other
|
|
26
|
+
`expo-modules-core` package with zero further changes:
|
|
27
|
+
|
|
28
|
+
| Platform | Touches |
|
|
29
|
+
|---|---|
|
|
30
|
+
| iOS | `ios/Podfile` — add `use_expo_modules!` |
|
|
31
|
+
| iOS | `AppDelegate.swift` — Expo's runtime-bootstrap hook |
|
|
32
|
+
| Android | `settings.gradle` / `app/build.gradle` — resolve and include the Expo Gradle projects |
|
|
33
|
+
| 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) |
|
|
34
|
+
|
|
35
|
+
Full mechanics live in the `symbiote-expo-native-module` project skill. Reference
|
|
36
|
+
implementation: `examples/expo-react/ios/Podfile` and
|
|
37
|
+
`examples/expo-react/android/app/src/main/java/com/canaryexpo/MainApplication.kt` (registers
|
|
38
|
+
`HapticsModule` as `"ExpoHaptics"`).
|
|
39
|
+
|
|
40
|
+
No permission or `Info.plist`/`AndroidManifest.xml` entry is needed on either platform — haptic
|
|
41
|
+
feedback requires none.
|
|
42
|
+
|
|
43
|
+
## Shape
|
|
11
44
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
45
|
+
```
|
|
46
|
+
src/core/ notificationAsync / impactAsync / selectionAsync / performAndroidHapticsAsync,
|
|
47
|
+
plus NotificationFeedbackType / ImpactFeedbackStyle / AndroidHaptics.
|
|
48
|
+
native-module.ts resolves the ExpoHaptics native module via
|
|
49
|
+
expo-modules-core's requireNativeModule.
|
|
50
|
+
src/react/ @symbiote-native/haptics/react — plain re-export of core.
|
|
51
|
+
src/vue/ @symbiote-native/haptics/vue — plain re-export of core.
|
|
52
|
+
src/angular/ @symbiote-native/haptics/angular — plain re-export of core.
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Upstream ships four async functions and three enums, not a subscribable sensor — there's
|
|
56
|
+
nothing per-framework to add, so all three adapter entry points are identical re-exports of
|
|
57
|
+
`core`.
|
|
58
|
+
|
|
59
|
+
## Use it
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
// React — examples/expo-react/screens/HapticsScreen.tsx
|
|
63
|
+
import { impactAsync, ImpactFeedbackStyle, notificationAsync, NotificationFeedbackType, selectionAsync } from '@symbiote-native/haptics';
|
|
64
|
+
|
|
65
|
+
function HapticsScreen() {
|
|
66
|
+
return (
|
|
67
|
+
<>
|
|
68
|
+
<ActionButton title="Medium" onPress={() => impactAsync(ImpactFeedbackStyle.Medium)} />
|
|
69
|
+
<ActionButton title="Success" onPress={() => notificationAsync(NotificationFeedbackType.Success)} />
|
|
70
|
+
<ActionButton title="Selection" onPress={() => selectionAsync()} />
|
|
71
|
+
</>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```vue
|
|
77
|
+
<!-- Vue — examples/expo-vue-sfc/screens/HapticsScreen.vue -->
|
|
78
|
+
<script setup lang="ts">
|
|
79
|
+
import { impactAsync, ImpactFeedbackStyle, notificationAsync, NotificationFeedbackType, selectionAsync } from '@symbiote-native/haptics';
|
|
80
|
+
|
|
81
|
+
function fireImpact(style: ImpactFeedbackStyle): void {
|
|
82
|
+
void impactAsync(style);
|
|
83
|
+
}
|
|
84
|
+
</script>
|
|
85
|
+
<template>
|
|
86
|
+
<ActionButton title="Medium" :onPress="() => fireImpact(ImpactFeedbackStyle.Medium)" />
|
|
87
|
+
</template>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
// Angular — examples/expo-angular/src/screens/HapticsScreen.ts
|
|
92
|
+
import { Component } from '@angular/core';
|
|
93
|
+
import { impactAsync, ImpactFeedbackStyle, notificationAsync, NotificationFeedbackType } from '@symbiote-native/haptics';
|
|
94
|
+
|
|
95
|
+
@Component({
|
|
96
|
+
selector: 'HapticsScreen',
|
|
97
|
+
template: `<ActionButton title="Medium" (press)="handleImpact()"></ActionButton>`,
|
|
98
|
+
})
|
|
99
|
+
export class HapticsScreen {
|
|
100
|
+
handleImpact(): void {
|
|
101
|
+
impactAsync(ImpactFeedbackStyle.Medium);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Every call is fire-and-forget (no result to await) — a real device is needed to feel the
|
|
107
|
+
feedback, a simulator produces none. Android also gets `performAndroidHapticsAsync`, which
|
|
108
|
+
drives the device haptics engine directly instead of `impactAsync`'s Vibrator simulation; it
|
|
109
|
+
no-ops on every other platform.
|
|
110
|
+
|
|
111
|
+
## API
|
|
112
|
+
|
|
113
|
+
Free functions, no event stream, no per-instance state:
|
|
16
114
|
|
|
17
115
|
```ts
|
|
18
116
|
notificationAsync(type?: NotificationFeedbackType): Promise<void>
|
|
@@ -28,16 +126,27 @@ performAndroidHapticsAsync(type: AndroidHaptics): Promise<void>
|
|
|
28
126
|
// Android only — no-ops on other platforms. Uses the device haptics engine directly, unlike the Vibrator-based impactAsync.
|
|
29
127
|
```
|
|
30
128
|
|
|
31
|
-
Plus
|
|
32
|
-
|
|
129
|
+
Plus `NotificationFeedbackType`, `ImpactFeedbackStyle`, `AndroidHaptics` — ported verbatim from
|
|
130
|
+
upstream's `Haptics.types.ts`.
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
import { impactAsync, ImpactFeedbackStyle } from '@symbiote-native/haptics';
|
|
134
|
+
// or the framework-scoped entry points — identical surface, re-exported verbatim:
|
|
135
|
+
import { impactAsync } from '@symbiote-native/haptics/react';
|
|
136
|
+
import { impactAsync } from '@symbiote-native/haptics/vue';
|
|
137
|
+
import { impactAsync } from '@symbiote-native/haptics/angular';
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Test it
|
|
33
141
|
|
|
34
|
-
|
|
142
|
+
No Fabric/Descriptor angle at all — haptics is a pure async-function surface, never a view.
|
|
143
|
+
Tests exercise the JS layer via a fake native module in place of the real
|
|
144
|
+
`requireNativeModule` resolution (`vitest`, `src/**/*.test.{ts,tsx}`) — no `installFabric()`, no
|
|
145
|
+
ViewConfig. Native rendering itself is verified on-device (see the parent
|
|
146
|
+
[README](../../README.md)).
|
|
35
147
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
-
|
|
40
|
-
|
|
41
|
-
(depend on `expo-modules-core` only, never the `expo` meta-package; port the JS into `core/`
|
|
42
|
-
rather than importing upstream's; how autolinking picks up the native module) that will apply
|
|
43
|
-
when implementation starts.
|
|
148
|
+
Native wiring for this package is done across all four `examples/expo-*` canary apps (Android
|
|
149
|
+
3-layer registration in each app's `build.gradle`/`MainApplication.kt`/`AndroidManifest.xml`,
|
|
150
|
+
plus iOS Podfile/pod install) — not yet ported into the plain, non-Expo public canaries
|
|
151
|
+
(`examples/react`, `examples/vue-sfc`, `examples/vue-tsx`, `examples/angular`), and no
|
|
152
|
+
on-device/simulator automated (Detox) smoke test exists yet, only manual verification.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../core';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { AndroidHaptics, ImpactFeedbackStyle, NotificationFeedbackType } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* The kind of notification response used in the feedback. On Android it is simulated using
|
|
4
|
+
* `Vibrator`; on iOS it maps directly to `UINotificationFeedbackType`.
|
|
5
|
+
*/
|
|
6
|
+
export declare function notificationAsync(type?: NotificationFeedbackType): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* A collision indicator. On Android it is simulated using `Vibrator`; on iOS it maps directly to
|
|
9
|
+
* `UIImpactFeedbackStyle`.
|
|
10
|
+
* @see Android's `Vibrator` API is not recommended for haptics feedback — prefer
|
|
11
|
+
* `performAndroidHapticsAsync`, which drives the device haptics engine directly and does not
|
|
12
|
+
* require the `VIBRATE` permission.
|
|
13
|
+
*/
|
|
14
|
+
export declare function impactAsync(style?: ImpactFeedbackStyle): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Lets the user know a selection change has been registered.
|
|
17
|
+
*/
|
|
18
|
+
export declare function selectionAsync(): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Uses the device haptics engine directly to provide physical feedback to the user. A no-op on
|
|
21
|
+
* every platform except Android.
|
|
22
|
+
* @platform android
|
|
23
|
+
*/
|
|
24
|
+
export declare function performAndroidHapticsAsync(type: AndroidHaptics): Promise<void>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Platform, UnavailabilityError } from 'expo-modules-core';
|
|
2
|
+
import { expoHaptics } from './native-module.js';
|
|
3
|
+
import { AndroidHaptics, ImpactFeedbackStyle, NotificationFeedbackType } from './types.js';
|
|
4
|
+
const NATIVE_MODULE_NAME = 'expo-haptics';
|
|
5
|
+
/**
|
|
6
|
+
* The kind of notification response used in the feedback. On Android it is simulated using
|
|
7
|
+
* `Vibrator`; on iOS it maps directly to `UINotificationFeedbackType`.
|
|
8
|
+
*/
|
|
9
|
+
export async function notificationAsync(type = NotificationFeedbackType.Success) {
|
|
10
|
+
if (!expoHaptics.notificationAsync) {
|
|
11
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'notificationAsync');
|
|
12
|
+
}
|
|
13
|
+
await expoHaptics.notificationAsync(type);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A collision indicator. On Android it is simulated using `Vibrator`; on iOS it maps directly to
|
|
17
|
+
* `UIImpactFeedbackStyle`.
|
|
18
|
+
* @see Android's `Vibrator` API is not recommended for haptics feedback — prefer
|
|
19
|
+
* `performAndroidHapticsAsync`, which drives the device haptics engine directly and does not
|
|
20
|
+
* require the `VIBRATE` permission.
|
|
21
|
+
*/
|
|
22
|
+
export async function impactAsync(style = ImpactFeedbackStyle.Medium) {
|
|
23
|
+
if (!expoHaptics.impactAsync) {
|
|
24
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'impactAsync');
|
|
25
|
+
}
|
|
26
|
+
await expoHaptics.impactAsync(style);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Lets the user know a selection change has been registered.
|
|
30
|
+
*/
|
|
31
|
+
export async function selectionAsync() {
|
|
32
|
+
if (!expoHaptics.selectionAsync) {
|
|
33
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'selectionAsync');
|
|
34
|
+
}
|
|
35
|
+
await expoHaptics.selectionAsync();
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Uses the device haptics engine directly to provide physical feedback to the user. A no-op on
|
|
39
|
+
* every platform except Android.
|
|
40
|
+
* @platform android
|
|
41
|
+
*/
|
|
42
|
+
export async function performAndroidHapticsAsync(type) {
|
|
43
|
+
if (Platform.OS !== 'android') {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (!expoHaptics.performHapticsAsync) {
|
|
47
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'performHapticsAsync');
|
|
48
|
+
}
|
|
49
|
+
await expoHaptics.performHapticsAsync(type);
|
|
50
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AndroidHaptics, ImpactFeedbackStyle, NotificationFeedbackType } from './types';
|
|
2
|
+
export type INativeHapticsModule = {
|
|
3
|
+
notificationAsync?(type: NotificationFeedbackType): Promise<void>;
|
|
4
|
+
impactAsync?(style: ImpactFeedbackStyle): Promise<void>;
|
|
5
|
+
selectionAsync?(): Promise<void>;
|
|
6
|
+
performHapticsAsync?(type: AndroidHaptics): Promise<void>;
|
|
7
|
+
};
|
|
8
|
+
export declare const expoHaptics: INativeHapticsModule;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The type of notification feedback generated by a `UINotificationFeedbackGenerator` object.
|
|
3
|
+
* [`UINotificationFeedbackType`](https://developer.apple.com/documentation/uikit/uinotificationfeedbackgenerator/feedbacktype).
|
|
4
|
+
*/
|
|
5
|
+
export declare enum NotificationFeedbackType {
|
|
6
|
+
/** A notification feedback type indicating that a task has completed successfully. */
|
|
7
|
+
Success = "success",
|
|
8
|
+
/** A notification feedback type indicating that a task has produced a warning. */
|
|
9
|
+
Warning = "warning",
|
|
10
|
+
/** A notification feedback type indicating that a task has failed. */
|
|
11
|
+
Error = "error"
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The mass of the objects in the collision simulated by a `UIImpactFeedbackGenerator` object.
|
|
15
|
+
* [`UIImpactFeedbackStyle`](https://developer.apple.com/documentation/uikit/uiimpactfeedbackgenerator/feedbackstyle).
|
|
16
|
+
*/
|
|
17
|
+
export declare enum ImpactFeedbackStyle {
|
|
18
|
+
/** A collision between small, light user interface elements. */
|
|
19
|
+
Light = "light",
|
|
20
|
+
/** A collision between moderately sized user interface elements. */
|
|
21
|
+
Medium = "medium",
|
|
22
|
+
/** A collision between large, heavy user interface elements. */
|
|
23
|
+
Heavy = "heavy",
|
|
24
|
+
/**
|
|
25
|
+
* A collision between user interface elements that are soft, exhibiting a large amount of
|
|
26
|
+
* compression or elasticity.
|
|
27
|
+
*/
|
|
28
|
+
Soft = "soft",
|
|
29
|
+
/**
|
|
30
|
+
* A collision between user interface elements that are rigid, exhibiting a small amount of
|
|
31
|
+
* compression or elasticity.
|
|
32
|
+
*/
|
|
33
|
+
Rigid = "rigid"
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Feedback effects driven directly by Android's haptics engine, via `performAndroidHapticsAsync`.
|
|
37
|
+
* @platform android
|
|
38
|
+
*/
|
|
39
|
+
export declare enum AndroidHaptics {
|
|
40
|
+
/** A haptic effect to signal the confirmation or successful completion of a user interaction. */
|
|
41
|
+
Confirm = "confirm",
|
|
42
|
+
/** A haptic effect to signal the rejection or failure of a user interaction. */
|
|
43
|
+
Reject = "reject",
|
|
44
|
+
/** The user has started a gesture (for example, on the soft keyboard). */
|
|
45
|
+
Gesture_Start = "gesture-start",
|
|
46
|
+
/** The user has finished a gesture (for example, on the soft keyboard). */
|
|
47
|
+
Gesture_End = "gesture-end",
|
|
48
|
+
/** The user has toggled a switch or button into the on position. */
|
|
49
|
+
Toggle_On = "toggle-on",
|
|
50
|
+
/** The user has toggled a switch or button into the off position. */
|
|
51
|
+
Toggle_Off = "toggle-off",
|
|
52
|
+
/** The user has pressed either an hour or minute tick of a Clock. */
|
|
53
|
+
Clock_Tick = "clock-tick",
|
|
54
|
+
/** The user has performed a context click on an object. */
|
|
55
|
+
Context_Click = "context-click",
|
|
56
|
+
/** The user has started a drag-and-drop gesture. The drag target has just been "picked up". */
|
|
57
|
+
Drag_Start = "drag-start",
|
|
58
|
+
/** The user has pressed a soft keyboard key. */
|
|
59
|
+
Keyboard_Tap = "keyboard-tap",
|
|
60
|
+
/** The user has pressed a virtual or software keyboard key. */
|
|
61
|
+
Keyboard_Press = "keyboard-press",
|
|
62
|
+
/** The user has released a virtual keyboard key. */
|
|
63
|
+
Keyboard_Release = "keyboard-release",
|
|
64
|
+
/** The user has performed a long press on an object that results in an action being performed. */
|
|
65
|
+
Long_Press = "long-press",
|
|
66
|
+
/** The user has pressed on a virtual on-screen key. */
|
|
67
|
+
Virtual_Key = "virtual-key",
|
|
68
|
+
/** The user has released a virtual key. */
|
|
69
|
+
Virtual_Key_Release = "virtual-key-release",
|
|
70
|
+
/** No haptic feedback should be performed. */
|
|
71
|
+
No_Haptics = "no-haptics",
|
|
72
|
+
/**
|
|
73
|
+
* The user is switching between a series of potential choices. For example, items in a list
|
|
74
|
+
* or discrete points on a slider.
|
|
75
|
+
*/
|
|
76
|
+
Segment_Tick = "segment-tick",
|
|
77
|
+
/**
|
|
78
|
+
* The user is switching between a series of many potential choices. For example, minutes on a
|
|
79
|
+
* clock face or individual percentages. Expected to be very soft, so as not to be uncomfortable
|
|
80
|
+
* when performed a lot in quick succession — if the device can't make a suitably soft
|
|
81
|
+
* vibration, it may not make any vibration at all.
|
|
82
|
+
*/
|
|
83
|
+
Segment_Frequent_Tick = "segment-frequent-tick",
|
|
84
|
+
/** The user has performed a selection/insertion handle move on a text field. */
|
|
85
|
+
Text_Handle_Move = "text-handle-move"
|
|
86
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The type of notification feedback generated by a `UINotificationFeedbackGenerator` object.
|
|
3
|
+
* [`UINotificationFeedbackType`](https://developer.apple.com/documentation/uikit/uinotificationfeedbackgenerator/feedbacktype).
|
|
4
|
+
*/
|
|
5
|
+
export var NotificationFeedbackType;
|
|
6
|
+
(function (NotificationFeedbackType) {
|
|
7
|
+
/** A notification feedback type indicating that a task has completed successfully. */
|
|
8
|
+
NotificationFeedbackType["Success"] = "success";
|
|
9
|
+
/** A notification feedback type indicating that a task has produced a warning. */
|
|
10
|
+
NotificationFeedbackType["Warning"] = "warning";
|
|
11
|
+
/** A notification feedback type indicating that a task has failed. */
|
|
12
|
+
NotificationFeedbackType["Error"] = "error";
|
|
13
|
+
})(NotificationFeedbackType || (NotificationFeedbackType = {}));
|
|
14
|
+
/**
|
|
15
|
+
* The mass of the objects in the collision simulated by a `UIImpactFeedbackGenerator` object.
|
|
16
|
+
* [`UIImpactFeedbackStyle`](https://developer.apple.com/documentation/uikit/uiimpactfeedbackgenerator/feedbackstyle).
|
|
17
|
+
*/
|
|
18
|
+
export var ImpactFeedbackStyle;
|
|
19
|
+
(function (ImpactFeedbackStyle) {
|
|
20
|
+
/** A collision between small, light user interface elements. */
|
|
21
|
+
ImpactFeedbackStyle["Light"] = "light";
|
|
22
|
+
/** A collision between moderately sized user interface elements. */
|
|
23
|
+
ImpactFeedbackStyle["Medium"] = "medium";
|
|
24
|
+
/** A collision between large, heavy user interface elements. */
|
|
25
|
+
ImpactFeedbackStyle["Heavy"] = "heavy";
|
|
26
|
+
/**
|
|
27
|
+
* A collision between user interface elements that are soft, exhibiting a large amount of
|
|
28
|
+
* compression or elasticity.
|
|
29
|
+
*/
|
|
30
|
+
ImpactFeedbackStyle["Soft"] = "soft";
|
|
31
|
+
/**
|
|
32
|
+
* A collision between user interface elements that are rigid, exhibiting a small amount of
|
|
33
|
+
* compression or elasticity.
|
|
34
|
+
*/
|
|
35
|
+
ImpactFeedbackStyle["Rigid"] = "rigid";
|
|
36
|
+
})(ImpactFeedbackStyle || (ImpactFeedbackStyle = {}));
|
|
37
|
+
/**
|
|
38
|
+
* Feedback effects driven directly by Android's haptics engine, via `performAndroidHapticsAsync`.
|
|
39
|
+
* @platform android
|
|
40
|
+
*/
|
|
41
|
+
export var AndroidHaptics;
|
|
42
|
+
(function (AndroidHaptics) {
|
|
43
|
+
/** A haptic effect to signal the confirmation or successful completion of a user interaction. */
|
|
44
|
+
AndroidHaptics["Confirm"] = "confirm";
|
|
45
|
+
/** A haptic effect to signal the rejection or failure of a user interaction. */
|
|
46
|
+
AndroidHaptics["Reject"] = "reject";
|
|
47
|
+
/** The user has started a gesture (for example, on the soft keyboard). */
|
|
48
|
+
AndroidHaptics["Gesture_Start"] = "gesture-start";
|
|
49
|
+
/** The user has finished a gesture (for example, on the soft keyboard). */
|
|
50
|
+
AndroidHaptics["Gesture_End"] = "gesture-end";
|
|
51
|
+
/** The user has toggled a switch or button into the on position. */
|
|
52
|
+
AndroidHaptics["Toggle_On"] = "toggle-on";
|
|
53
|
+
/** The user has toggled a switch or button into the off position. */
|
|
54
|
+
AndroidHaptics["Toggle_Off"] = "toggle-off";
|
|
55
|
+
/** The user has pressed either an hour or minute tick of a Clock. */
|
|
56
|
+
AndroidHaptics["Clock_Tick"] = "clock-tick";
|
|
57
|
+
/** The user has performed a context click on an object. */
|
|
58
|
+
AndroidHaptics["Context_Click"] = "context-click";
|
|
59
|
+
/** The user has started a drag-and-drop gesture. The drag target has just been "picked up". */
|
|
60
|
+
AndroidHaptics["Drag_Start"] = "drag-start";
|
|
61
|
+
/** The user has pressed a soft keyboard key. */
|
|
62
|
+
AndroidHaptics["Keyboard_Tap"] = "keyboard-tap";
|
|
63
|
+
/** The user has pressed a virtual or software keyboard key. */
|
|
64
|
+
AndroidHaptics["Keyboard_Press"] = "keyboard-press";
|
|
65
|
+
/** The user has released a virtual keyboard key. */
|
|
66
|
+
AndroidHaptics["Keyboard_Release"] = "keyboard-release";
|
|
67
|
+
/** The user has performed a long press on an object that results in an action being performed. */
|
|
68
|
+
AndroidHaptics["Long_Press"] = "long-press";
|
|
69
|
+
/** The user has pressed on a virtual on-screen key. */
|
|
70
|
+
AndroidHaptics["Virtual_Key"] = "virtual-key";
|
|
71
|
+
/** The user has released a virtual key. */
|
|
72
|
+
AndroidHaptics["Virtual_Key_Release"] = "virtual-key-release";
|
|
73
|
+
/** No haptic feedback should be performed. */
|
|
74
|
+
AndroidHaptics["No_Haptics"] = "no-haptics";
|
|
75
|
+
/**
|
|
76
|
+
* The user is switching between a series of potential choices. For example, items in a list
|
|
77
|
+
* or discrete points on a slider.
|
|
78
|
+
*/
|
|
79
|
+
AndroidHaptics["Segment_Tick"] = "segment-tick";
|
|
80
|
+
/**
|
|
81
|
+
* The user is switching between a series of many potential choices. For example, minutes on a
|
|
82
|
+
* clock face or individual percentages. Expected to be very soft, so as not to be uncomfortable
|
|
83
|
+
* when performed a lot in quick succession — if the device can't make a suitably soft
|
|
84
|
+
* vibration, it may not make any vibration at all.
|
|
85
|
+
*/
|
|
86
|
+
AndroidHaptics["Segment_Frequent_Tick"] = "segment-frequent-tick";
|
|
87
|
+
/** The user has performed a selection/insertion handle move on a text field. */
|
|
88
|
+
AndroidHaptics["Text_Handle_Move"] = "text-handle-move";
|
|
89
|
+
})(AndroidHaptics || (AndroidHaptics = {}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../core';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// @symbiote-native/haptics/react: the React entry over the framework-agnostic core.
|
|
2
|
+
// Upstream ships free async functions and three enums, no per-instance state and no event
|
|
3
|
+
// stream (same shape as @symbiote-native/local-auth) — there is nothing for a hook to wrap, so
|
|
4
|
+
// this is a plain re-export.
|
|
5
|
+
export * from '../core/index.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../core';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// @symbiote-native/haptics/svelte: the Svelte entry over the framework-agnostic core.
|
|
2
|
+
// Upstream ships free async functions and three enums, no per-instance state and no event
|
|
3
|
+
// stream (same shape as @symbiote-native/local-auth) — there is nothing for a rune to wrap, so
|
|
4
|
+
// this is a plain re-export. Svelte's lifecycle bucket is `runes/` (adapters/svelte/src/runes —
|
|
5
|
+
// never React's `hooks` or Vue's `composables`), and this package has none to fill.
|
|
6
|
+
export * from '../core/index.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../core';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../core';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// @symbiote-native/haptics/angular: the Angular entry over the framework-agnostic core. Same
|
|
2
|
+
// reasoning as the React/Vue entries — no per-instance state or event stream to wrap in a
|
|
3
|
+
// service, so this is a plain re-export.
|
|
4
|
+
export * from '../core';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/angular/index.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,0FAA0F;AAC1F,yCAAyC;AACzC,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { AndroidHaptics, ImpactFeedbackStyle, NotificationFeedbackType } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* The kind of notification response used in the feedback. On Android it is simulated using
|
|
4
|
+
* `Vibrator`; on iOS it maps directly to `UINotificationFeedbackType`.
|
|
5
|
+
*/
|
|
6
|
+
export declare function notificationAsync(type?: NotificationFeedbackType): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* A collision indicator. On Android it is simulated using `Vibrator`; on iOS it maps directly to
|
|
9
|
+
* `UIImpactFeedbackStyle`.
|
|
10
|
+
* @see Android's `Vibrator` API is not recommended for haptics feedback — prefer
|
|
11
|
+
* `performAndroidHapticsAsync`, which drives the device haptics engine directly and does not
|
|
12
|
+
* require the `VIBRATE` permission.
|
|
13
|
+
*/
|
|
14
|
+
export declare function impactAsync(style?: ImpactFeedbackStyle): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Lets the user know a selection change has been registered.
|
|
17
|
+
*/
|
|
18
|
+
export declare function selectionAsync(): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Uses the device haptics engine directly to provide physical feedback to the user. A no-op on
|
|
21
|
+
* every platform except Android.
|
|
22
|
+
* @platform android
|
|
23
|
+
*/
|
|
24
|
+
export declare function performAndroidHapticsAsync(type: AndroidHaptics): Promise<void>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Platform, UnavailabilityError } from 'expo-modules-core';
|
|
2
|
+
import { expoHaptics } from './native-module';
|
|
3
|
+
import { AndroidHaptics, ImpactFeedbackStyle, NotificationFeedbackType } from './types';
|
|
4
|
+
const NATIVE_MODULE_NAME = 'expo-haptics';
|
|
5
|
+
/**
|
|
6
|
+
* The kind of notification response used in the feedback. On Android it is simulated using
|
|
7
|
+
* `Vibrator`; on iOS it maps directly to `UINotificationFeedbackType`.
|
|
8
|
+
*/
|
|
9
|
+
export async function notificationAsync(type = NotificationFeedbackType.Success) {
|
|
10
|
+
if (!expoHaptics.notificationAsync) {
|
|
11
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'notificationAsync');
|
|
12
|
+
}
|
|
13
|
+
await expoHaptics.notificationAsync(type);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A collision indicator. On Android it is simulated using `Vibrator`; on iOS it maps directly to
|
|
17
|
+
* `UIImpactFeedbackStyle`.
|
|
18
|
+
* @see Android's `Vibrator` API is not recommended for haptics feedback — prefer
|
|
19
|
+
* `performAndroidHapticsAsync`, which drives the device haptics engine directly and does not
|
|
20
|
+
* require the `VIBRATE` permission.
|
|
21
|
+
*/
|
|
22
|
+
export async function impactAsync(style = ImpactFeedbackStyle.Medium) {
|
|
23
|
+
if (!expoHaptics.impactAsync) {
|
|
24
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'impactAsync');
|
|
25
|
+
}
|
|
26
|
+
await expoHaptics.impactAsync(style);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Lets the user know a selection change has been registered.
|
|
30
|
+
*/
|
|
31
|
+
export async function selectionAsync() {
|
|
32
|
+
if (!expoHaptics.selectionAsync) {
|
|
33
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'selectionAsync');
|
|
34
|
+
}
|
|
35
|
+
await expoHaptics.selectionAsync();
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Uses the device haptics engine directly to provide physical feedback to the user. A no-op on
|
|
39
|
+
* every platform except Android.
|
|
40
|
+
* @platform android
|
|
41
|
+
*/
|
|
42
|
+
export async function performAndroidHapticsAsync(type) {
|
|
43
|
+
if (Platform.OS !== 'android') {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (!expoHaptics.performHapticsAsync) {
|
|
47
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'performHapticsAsync');
|
|
48
|
+
}
|
|
49
|
+
await expoHaptics.performHapticsAsync(type);
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=haptics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"haptics.js","sourceRoot":"","sources":["../../src/core/haptics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAElE,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAExF,MAAM,kBAAkB,GAAG,cAAc,CAAC;AAE1C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAiC,wBAAwB,CAAC,OAAO;IAEjE,IAAI,CAAC,WAAW,CAAC,iBAAiB,EAAE,CAAC;QACnC,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,WAAW,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,QAA6B,mBAAmB,CAAC,MAAM;IAEvD,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC;QAC7B,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAC;IACnE,CAAC;IACD,MAAM,WAAW,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE,CAAC;QAChC,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC;IACtE,CAAC;IACD,MAAM,WAAW,CAAC,cAAc,EAAE,CAAC;AACrC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,IAAoB;IACnE,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO;IACT,CAAC;IACD,IAAI,CAAC,WAAW,CAAC,mBAAmB,EAAE,CAAC;QACrC,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,WAAW,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,cAAc,EACd,0BAA0B,GAC3B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AndroidHaptics, ImpactFeedbackStyle, NotificationFeedbackType } from './types';
|
|
2
|
+
export type INativeHapticsModule = {
|
|
3
|
+
notificationAsync?(type: NotificationFeedbackType): Promise<void>;
|
|
4
|
+
impactAsync?(style: ImpactFeedbackStyle): Promise<void>;
|
|
5
|
+
selectionAsync?(): Promise<void>;
|
|
6
|
+
performHapticsAsync?(type: AndroidHaptics): Promise<void>;
|
|
7
|
+
};
|
|
8
|
+
export declare const expoHaptics: INativeHapticsModule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-module.js","sourceRoot":"","sources":["../../src/core/native-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAGxD,MAAM,wBAAwB,GAAG,aAAa,CAAC;AAgB/C,MAAM,CAAC,MAAM,WAAW,GAAG,mBAAmB,CAAuB,wBAAwB,CAAC,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The type of notification feedback generated by a `UINotificationFeedbackGenerator` object.
|
|
3
|
+
* [`UINotificationFeedbackType`](https://developer.apple.com/documentation/uikit/uinotificationfeedbackgenerator/feedbacktype).
|
|
4
|
+
*/
|
|
5
|
+
export declare enum NotificationFeedbackType {
|
|
6
|
+
/** A notification feedback type indicating that a task has completed successfully. */
|
|
7
|
+
Success = "success",
|
|
8
|
+
/** A notification feedback type indicating that a task has produced a warning. */
|
|
9
|
+
Warning = "warning",
|
|
10
|
+
/** A notification feedback type indicating that a task has failed. */
|
|
11
|
+
Error = "error"
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The mass of the objects in the collision simulated by a `UIImpactFeedbackGenerator` object.
|
|
15
|
+
* [`UIImpactFeedbackStyle`](https://developer.apple.com/documentation/uikit/uiimpactfeedbackgenerator/feedbackstyle).
|
|
16
|
+
*/
|
|
17
|
+
export declare enum ImpactFeedbackStyle {
|
|
18
|
+
/** A collision between small, light user interface elements. */
|
|
19
|
+
Light = "light",
|
|
20
|
+
/** A collision between moderately sized user interface elements. */
|
|
21
|
+
Medium = "medium",
|
|
22
|
+
/** A collision between large, heavy user interface elements. */
|
|
23
|
+
Heavy = "heavy",
|
|
24
|
+
/**
|
|
25
|
+
* A collision between user interface elements that are soft, exhibiting a large amount of
|
|
26
|
+
* compression or elasticity.
|
|
27
|
+
*/
|
|
28
|
+
Soft = "soft",
|
|
29
|
+
/**
|
|
30
|
+
* A collision between user interface elements that are rigid, exhibiting a small amount of
|
|
31
|
+
* compression or elasticity.
|
|
32
|
+
*/
|
|
33
|
+
Rigid = "rigid"
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Feedback effects driven directly by Android's haptics engine, via `performAndroidHapticsAsync`.
|
|
37
|
+
* @platform android
|
|
38
|
+
*/
|
|
39
|
+
export declare enum AndroidHaptics {
|
|
40
|
+
/** A haptic effect to signal the confirmation or successful completion of a user interaction. */
|
|
41
|
+
Confirm = "confirm",
|
|
42
|
+
/** A haptic effect to signal the rejection or failure of a user interaction. */
|
|
43
|
+
Reject = "reject",
|
|
44
|
+
/** The user has started a gesture (for example, on the soft keyboard). */
|
|
45
|
+
Gesture_Start = "gesture-start",
|
|
46
|
+
/** The user has finished a gesture (for example, on the soft keyboard). */
|
|
47
|
+
Gesture_End = "gesture-end",
|
|
48
|
+
/** The user has toggled a switch or button into the on position. */
|
|
49
|
+
Toggle_On = "toggle-on",
|
|
50
|
+
/** The user has toggled a switch or button into the off position. */
|
|
51
|
+
Toggle_Off = "toggle-off",
|
|
52
|
+
/** The user has pressed either an hour or minute tick of a Clock. */
|
|
53
|
+
Clock_Tick = "clock-tick",
|
|
54
|
+
/** The user has performed a context click on an object. */
|
|
55
|
+
Context_Click = "context-click",
|
|
56
|
+
/** The user has started a drag-and-drop gesture. The drag target has just been "picked up". */
|
|
57
|
+
Drag_Start = "drag-start",
|
|
58
|
+
/** The user has pressed a soft keyboard key. */
|
|
59
|
+
Keyboard_Tap = "keyboard-tap",
|
|
60
|
+
/** The user has pressed a virtual or software keyboard key. */
|
|
61
|
+
Keyboard_Press = "keyboard-press",
|
|
62
|
+
/** The user has released a virtual keyboard key. */
|
|
63
|
+
Keyboard_Release = "keyboard-release",
|
|
64
|
+
/** The user has performed a long press on an object that results in an action being performed. */
|
|
65
|
+
Long_Press = "long-press",
|
|
66
|
+
/** The user has pressed on a virtual on-screen key. */
|
|
67
|
+
Virtual_Key = "virtual-key",
|
|
68
|
+
/** The user has released a virtual key. */
|
|
69
|
+
Virtual_Key_Release = "virtual-key-release",
|
|
70
|
+
/** No haptic feedback should be performed. */
|
|
71
|
+
No_Haptics = "no-haptics",
|
|
72
|
+
/**
|
|
73
|
+
* The user is switching between a series of potential choices. For example, items in a list
|
|
74
|
+
* or discrete points on a slider.
|
|
75
|
+
*/
|
|
76
|
+
Segment_Tick = "segment-tick",
|
|
77
|
+
/**
|
|
78
|
+
* The user is switching between a series of many potential choices. For example, minutes on a
|
|
79
|
+
* clock face or individual percentages. Expected to be very soft, so as not to be uncomfortable
|
|
80
|
+
* when performed a lot in quick succession — if the device can't make a suitably soft
|
|
81
|
+
* vibration, it may not make any vibration at all.
|
|
82
|
+
*/
|
|
83
|
+
Segment_Frequent_Tick = "segment-frequent-tick",
|
|
84
|
+
/** The user has performed a selection/insertion handle move on a text field. */
|
|
85
|
+
Text_Handle_Move = "text-handle-move"
|
|
86
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The type of notification feedback generated by a `UINotificationFeedbackGenerator` object.
|
|
3
|
+
* [`UINotificationFeedbackType`](https://developer.apple.com/documentation/uikit/uinotificationfeedbackgenerator/feedbacktype).
|
|
4
|
+
*/
|
|
5
|
+
export var NotificationFeedbackType;
|
|
6
|
+
(function (NotificationFeedbackType) {
|
|
7
|
+
/** A notification feedback type indicating that a task has completed successfully. */
|
|
8
|
+
NotificationFeedbackType["Success"] = "success";
|
|
9
|
+
/** A notification feedback type indicating that a task has produced a warning. */
|
|
10
|
+
NotificationFeedbackType["Warning"] = "warning";
|
|
11
|
+
/** A notification feedback type indicating that a task has failed. */
|
|
12
|
+
NotificationFeedbackType["Error"] = "error";
|
|
13
|
+
})(NotificationFeedbackType || (NotificationFeedbackType = {}));
|
|
14
|
+
/**
|
|
15
|
+
* The mass of the objects in the collision simulated by a `UIImpactFeedbackGenerator` object.
|
|
16
|
+
* [`UIImpactFeedbackStyle`](https://developer.apple.com/documentation/uikit/uiimpactfeedbackgenerator/feedbackstyle).
|
|
17
|
+
*/
|
|
18
|
+
export var ImpactFeedbackStyle;
|
|
19
|
+
(function (ImpactFeedbackStyle) {
|
|
20
|
+
/** A collision between small, light user interface elements. */
|
|
21
|
+
ImpactFeedbackStyle["Light"] = "light";
|
|
22
|
+
/** A collision between moderately sized user interface elements. */
|
|
23
|
+
ImpactFeedbackStyle["Medium"] = "medium";
|
|
24
|
+
/** A collision between large, heavy user interface elements. */
|
|
25
|
+
ImpactFeedbackStyle["Heavy"] = "heavy";
|
|
26
|
+
/**
|
|
27
|
+
* A collision between user interface elements that are soft, exhibiting a large amount of
|
|
28
|
+
* compression or elasticity.
|
|
29
|
+
*/
|
|
30
|
+
ImpactFeedbackStyle["Soft"] = "soft";
|
|
31
|
+
/**
|
|
32
|
+
* A collision between user interface elements that are rigid, exhibiting a small amount of
|
|
33
|
+
* compression or elasticity.
|
|
34
|
+
*/
|
|
35
|
+
ImpactFeedbackStyle["Rigid"] = "rigid";
|
|
36
|
+
})(ImpactFeedbackStyle || (ImpactFeedbackStyle = {}));
|
|
37
|
+
/**
|
|
38
|
+
* Feedback effects driven directly by Android's haptics engine, via `performAndroidHapticsAsync`.
|
|
39
|
+
* @platform android
|
|
40
|
+
*/
|
|
41
|
+
export var AndroidHaptics;
|
|
42
|
+
(function (AndroidHaptics) {
|
|
43
|
+
/** A haptic effect to signal the confirmation or successful completion of a user interaction. */
|
|
44
|
+
AndroidHaptics["Confirm"] = "confirm";
|
|
45
|
+
/** A haptic effect to signal the rejection or failure of a user interaction. */
|
|
46
|
+
AndroidHaptics["Reject"] = "reject";
|
|
47
|
+
/** The user has started a gesture (for example, on the soft keyboard). */
|
|
48
|
+
AndroidHaptics["Gesture_Start"] = "gesture-start";
|
|
49
|
+
/** The user has finished a gesture (for example, on the soft keyboard). */
|
|
50
|
+
AndroidHaptics["Gesture_End"] = "gesture-end";
|
|
51
|
+
/** The user has toggled a switch or button into the on position. */
|
|
52
|
+
AndroidHaptics["Toggle_On"] = "toggle-on";
|
|
53
|
+
/** The user has toggled a switch or button into the off position. */
|
|
54
|
+
AndroidHaptics["Toggle_Off"] = "toggle-off";
|
|
55
|
+
/** The user has pressed either an hour or minute tick of a Clock. */
|
|
56
|
+
AndroidHaptics["Clock_Tick"] = "clock-tick";
|
|
57
|
+
/** The user has performed a context click on an object. */
|
|
58
|
+
AndroidHaptics["Context_Click"] = "context-click";
|
|
59
|
+
/** The user has started a drag-and-drop gesture. The drag target has just been "picked up". */
|
|
60
|
+
AndroidHaptics["Drag_Start"] = "drag-start";
|
|
61
|
+
/** The user has pressed a soft keyboard key. */
|
|
62
|
+
AndroidHaptics["Keyboard_Tap"] = "keyboard-tap";
|
|
63
|
+
/** The user has pressed a virtual or software keyboard key. */
|
|
64
|
+
AndroidHaptics["Keyboard_Press"] = "keyboard-press";
|
|
65
|
+
/** The user has released a virtual keyboard key. */
|
|
66
|
+
AndroidHaptics["Keyboard_Release"] = "keyboard-release";
|
|
67
|
+
/** The user has performed a long press on an object that results in an action being performed. */
|
|
68
|
+
AndroidHaptics["Long_Press"] = "long-press";
|
|
69
|
+
/** The user has pressed on a virtual on-screen key. */
|
|
70
|
+
AndroidHaptics["Virtual_Key"] = "virtual-key";
|
|
71
|
+
/** The user has released a virtual key. */
|
|
72
|
+
AndroidHaptics["Virtual_Key_Release"] = "virtual-key-release";
|
|
73
|
+
/** No haptic feedback should be performed. */
|
|
74
|
+
AndroidHaptics["No_Haptics"] = "no-haptics";
|
|
75
|
+
/**
|
|
76
|
+
* The user is switching between a series of potential choices. For example, items in a list
|
|
77
|
+
* or discrete points on a slider.
|
|
78
|
+
*/
|
|
79
|
+
AndroidHaptics["Segment_Tick"] = "segment-tick";
|
|
80
|
+
/**
|
|
81
|
+
* The user is switching between a series of many potential choices. For example, minutes on a
|
|
82
|
+
* clock face or individual percentages. Expected to be very soft, so as not to be uncomfortable
|
|
83
|
+
* when performed a lot in quick succession — if the device can't make a suitably soft
|
|
84
|
+
* vibration, it may not make any vibration at all.
|
|
85
|
+
*/
|
|
86
|
+
AndroidHaptics["Segment_Frequent_Tick"] = "segment-frequent-tick";
|
|
87
|
+
/** The user has performed a selection/insertion handle move on a text field. */
|
|
88
|
+
AndroidHaptics["Text_Handle_Move"] = "text-handle-move";
|
|
89
|
+
})(AndroidHaptics || (AndroidHaptics = {}));
|
|
90
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAN,IAAY,wBAOX;AAPD,WAAY,wBAAwB;IAClC,sFAAsF;IACtF,+CAAmB,CAAA;IACnB,kFAAkF;IAClF,+CAAmB,CAAA;IACnB,sEAAsE;IACtE,2CAAe,CAAA;AACjB,CAAC,EAPW,wBAAwB,KAAxB,wBAAwB,QAOnC;AAED;;;GAGG;AACH,MAAM,CAAN,IAAY,mBAiBX;AAjBD,WAAY,mBAAmB;IAC7B,gEAAgE;IAChE,sCAAe,CAAA;IACf,oEAAoE;IACpE,wCAAiB,CAAA;IACjB,gEAAgE;IAChE,sCAAe,CAAA;IACf;;;OAGG;IACH,oCAAa,CAAA;IACb;;;OAGG;IACH,sCAAe,CAAA;AACjB,CAAC,EAjBW,mBAAmB,KAAnB,mBAAmB,QAiB9B;AAED;;;GAGG;AACH,MAAM,CAAN,IAAY,cA+CX;AA/CD,WAAY,cAAc;IACxB,iGAAiG;IACjG,qCAAmB,CAAA;IACnB,gFAAgF;IAChF,mCAAiB,CAAA;IACjB,0EAA0E;IAC1E,iDAA+B,CAAA;IAC/B,2EAA2E;IAC3E,6CAA2B,CAAA;IAC3B,oEAAoE;IACpE,yCAAuB,CAAA;IACvB,qEAAqE;IACrE,2CAAyB,CAAA;IACzB,qEAAqE;IACrE,2CAAyB,CAAA;IACzB,2DAA2D;IAC3D,iDAA+B,CAAA;IAC/B,+FAA+F;IAC/F,2CAAyB,CAAA;IACzB,gDAAgD;IAChD,+CAA6B,CAAA;IAC7B,+DAA+D;IAC/D,mDAAiC,CAAA;IACjC,oDAAoD;IACpD,uDAAqC,CAAA;IACrC,kGAAkG;IAClG,2CAAyB,CAAA;IACzB,uDAAuD;IACvD,6CAA2B,CAAA;IAC3B,2CAA2C;IAC3C,6DAA2C,CAAA;IAC3C,8CAA8C;IAC9C,2CAAyB,CAAA;IACzB;;;OAGG;IACH,+CAA6B,CAAA;IAC7B;;;;;OAKG;IACH,iEAA+C,CAAA;IAC/C,gFAAgF;IAChF,uDAAqC,CAAA;AACvC,CAAC,EA/CW,cAAc,KAAd,cAAc,QA+CzB"}
|
package/native-link.json
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbiote-native/haptics",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "expo-haptics wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, 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": {
|
|
@@ -13,7 +13,112 @@
|
|
|
13
13
|
"url": "https://github.com/OneEyed1366/symbiote-native/issues"
|
|
14
14
|
},
|
|
15
15
|
"author": "Andrey Prokopenko <psevdoproger@gmail.com>",
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "./build/core/index.js",
|
|
18
|
+
"module": "./build/core/index.js",
|
|
19
|
+
"types": "./build/core/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./build/core/index.d.ts",
|
|
23
|
+
"default": "./build/core/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./vue": {
|
|
26
|
+
"types": "./build/vue/index.d.ts",
|
|
27
|
+
"default": "./build/vue/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./react": {
|
|
30
|
+
"types": "./build/react/index.d.ts",
|
|
31
|
+
"default": "./build/react/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./svelte": {
|
|
34
|
+
"types": "./build/svelte/index.d.ts",
|
|
35
|
+
"default": "./build/svelte/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./angular": {
|
|
38
|
+
"types": "./build-ngc/angular/index.d.ts",
|
|
39
|
+
"react-native": "./build-ngc/angular/index.js",
|
|
40
|
+
"default": "./src/angular/index.ts"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"src",
|
|
45
|
+
"build",
|
|
46
|
+
"build-ngc",
|
|
47
|
+
"native-link.json",
|
|
48
|
+
"!src/**/*.test.*",
|
|
49
|
+
"!src/**/*.spec.*",
|
|
50
|
+
"!src/**/*.detox.*"
|
|
51
|
+
],
|
|
16
52
|
"publishConfig": {
|
|
17
53
|
"access": "public"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"expo-haptics": "57.0.1",
|
|
57
|
+
"expo-modules-core": "57.0.5"
|
|
58
|
+
},
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"@symbiote-native/angular": ">=0.6.2",
|
|
61
|
+
"@symbiote-native/engine": ">=0.1.7",
|
|
62
|
+
"@symbiote-native/react": ">=0.2.8",
|
|
63
|
+
"@symbiote-native/svelte": ">=0.1.0",
|
|
64
|
+
"@symbiote-native/vue": ">=0.3.8",
|
|
65
|
+
"@angular/core": ">=20",
|
|
66
|
+
"@vue/runtime-core": "^3.5.13",
|
|
67
|
+
"react": ">=19.0.0",
|
|
68
|
+
"react-native": ">=0.86",
|
|
69
|
+
"svelte": ">=5.56.0",
|
|
70
|
+
"vue": ">=3.5.0"
|
|
71
|
+
},
|
|
72
|
+
"peerDependenciesMeta": {
|
|
73
|
+
"@symbiote-native/angular": {
|
|
74
|
+
"optional": true
|
|
75
|
+
},
|
|
76
|
+
"@symbiote-native/react": {
|
|
77
|
+
"optional": true
|
|
78
|
+
},
|
|
79
|
+
"@symbiote-native/svelte": {
|
|
80
|
+
"optional": true
|
|
81
|
+
},
|
|
82
|
+
"@symbiote-native/vue": {
|
|
83
|
+
"optional": true
|
|
84
|
+
},
|
|
85
|
+
"@angular/core": {
|
|
86
|
+
"optional": true
|
|
87
|
+
},
|
|
88
|
+
"@vue/runtime-core": {
|
|
89
|
+
"optional": true
|
|
90
|
+
},
|
|
91
|
+
"react": {
|
|
92
|
+
"optional": true
|
|
93
|
+
},
|
|
94
|
+
"svelte": {
|
|
95
|
+
"optional": true
|
|
96
|
+
},
|
|
97
|
+
"vue": {
|
|
98
|
+
"optional": true
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"devDependencies": {
|
|
102
|
+
"@angular/compiler": "~22.0.8",
|
|
103
|
+
"@angular/compiler-cli": "~22.0.8",
|
|
104
|
+
"@angular/core": "~22.0.8",
|
|
105
|
+
"@types/node": "^26.0.0",
|
|
106
|
+
"@types/react": "^19.2.0",
|
|
107
|
+
"@vue/runtime-core": "^3.5.13",
|
|
108
|
+
"react": "19.2.3",
|
|
109
|
+
"svelte": "^5.56.0",
|
|
110
|
+
"typescript": "~6.0.0",
|
|
111
|
+
"@symbiote-native/angular": "0.7.0",
|
|
112
|
+
"@symbiote-native/engine": "0.2.0",
|
|
113
|
+
"@symbiote-native/react": "0.3.0",
|
|
114
|
+
"@symbiote-native/svelte": "0.2.0",
|
|
115
|
+
"@symbiote-native/test-utils": "0.1.6",
|
|
116
|
+
"@symbiote-native/vue": "0.4.0"
|
|
117
|
+
},
|
|
118
|
+
"scripts": {
|
|
119
|
+
"typecheck": "tsc --build",
|
|
120
|
+
"clean": "rm -rf build-ngc",
|
|
121
|
+
"ng:build": "pnpm run clean && ngc -p tsconfig.angular.json",
|
|
122
|
+
"format": "prettier --write \"src/**/*.{ts,tsx}\""
|
|
18
123
|
}
|
|
19
124
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Platform, UnavailabilityError } from 'expo-modules-core';
|
|
2
|
+
|
|
3
|
+
import { expoHaptics } from './native-module';
|
|
4
|
+
import { AndroidHaptics, ImpactFeedbackStyle, NotificationFeedbackType } from './types';
|
|
5
|
+
|
|
6
|
+
const NATIVE_MODULE_NAME = 'expo-haptics';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The kind of notification response used in the feedback. On Android it is simulated using
|
|
10
|
+
* `Vibrator`; on iOS it maps directly to `UINotificationFeedbackType`.
|
|
11
|
+
*/
|
|
12
|
+
export async function notificationAsync(
|
|
13
|
+
type: NotificationFeedbackType = NotificationFeedbackType.Success,
|
|
14
|
+
): Promise<void> {
|
|
15
|
+
if (!expoHaptics.notificationAsync) {
|
|
16
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'notificationAsync');
|
|
17
|
+
}
|
|
18
|
+
await expoHaptics.notificationAsync(type);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A collision indicator. On Android it is simulated using `Vibrator`; on iOS it maps directly to
|
|
23
|
+
* `UIImpactFeedbackStyle`.
|
|
24
|
+
* @see Android's `Vibrator` API is not recommended for haptics feedback — prefer
|
|
25
|
+
* `performAndroidHapticsAsync`, which drives the device haptics engine directly and does not
|
|
26
|
+
* require the `VIBRATE` permission.
|
|
27
|
+
*/
|
|
28
|
+
export async function impactAsync(
|
|
29
|
+
style: ImpactFeedbackStyle = ImpactFeedbackStyle.Medium,
|
|
30
|
+
): Promise<void> {
|
|
31
|
+
if (!expoHaptics.impactAsync) {
|
|
32
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'impactAsync');
|
|
33
|
+
}
|
|
34
|
+
await expoHaptics.impactAsync(style);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Lets the user know a selection change has been registered.
|
|
39
|
+
*/
|
|
40
|
+
export async function selectionAsync(): Promise<void> {
|
|
41
|
+
if (!expoHaptics.selectionAsync) {
|
|
42
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'selectionAsync');
|
|
43
|
+
}
|
|
44
|
+
await expoHaptics.selectionAsync();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Uses the device haptics engine directly to provide physical feedback to the user. A no-op on
|
|
49
|
+
* every platform except Android.
|
|
50
|
+
* @platform android
|
|
51
|
+
*/
|
|
52
|
+
export async function performAndroidHapticsAsync(type: AndroidHaptics): Promise<void> {
|
|
53
|
+
if (Platform.OS !== 'android') {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (!expoHaptics.performHapticsAsync) {
|
|
57
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'performHapticsAsync');
|
|
58
|
+
}
|
|
59
|
+
await expoHaptics.performHapticsAsync(type);
|
|
60
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { requireNativeModule } from 'expo-modules-core';
|
|
2
|
+
import type { AndroidHaptics, ImpactFeedbackStyle, NotificationFeedbackType } from './types';
|
|
3
|
+
|
|
4
|
+
const EXPO_HAPTICS_MODULE_NAME = 'ExpoHaptics';
|
|
5
|
+
|
|
6
|
+
// Every method is optional — each call site checks for its presence before calling through and
|
|
7
|
+
// throws an UnavailabilityError itself, matching upstream's own per-platform capability checks
|
|
8
|
+
// rather than assuming the native module implements the whole surface (same convention as
|
|
9
|
+
// packages/local-auth/src/core/native-module.ts). `performHapticsAsync` in particular only
|
|
10
|
+
// exists on the Android native module (HapticsModule.kt) — iOS's HapticsModule.swift has no
|
|
11
|
+
// equivalent, since `performAndroidHapticsAsync` short-circuits on non-Android platforms before
|
|
12
|
+
// ever reaching this call.
|
|
13
|
+
export type INativeHapticsModule = {
|
|
14
|
+
notificationAsync?(type: NotificationFeedbackType): Promise<void>;
|
|
15
|
+
impactAsync?(style: ImpactFeedbackStyle): Promise<void>;
|
|
16
|
+
selectionAsync?(): Promise<void>;
|
|
17
|
+
performHapticsAsync?(type: AndroidHaptics): Promise<void>;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const expoHaptics = requireNativeModule<INativeHapticsModule>(EXPO_HAPTICS_MODULE_NAME);
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The type of notification feedback generated by a `UINotificationFeedbackGenerator` object.
|
|
3
|
+
* [`UINotificationFeedbackType`](https://developer.apple.com/documentation/uikit/uinotificationfeedbackgenerator/feedbacktype).
|
|
4
|
+
*/
|
|
5
|
+
export enum NotificationFeedbackType {
|
|
6
|
+
/** A notification feedback type indicating that a task has completed successfully. */
|
|
7
|
+
Success = 'success',
|
|
8
|
+
/** A notification feedback type indicating that a task has produced a warning. */
|
|
9
|
+
Warning = 'warning',
|
|
10
|
+
/** A notification feedback type indicating that a task has failed. */
|
|
11
|
+
Error = 'error',
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The mass of the objects in the collision simulated by a `UIImpactFeedbackGenerator` object.
|
|
16
|
+
* [`UIImpactFeedbackStyle`](https://developer.apple.com/documentation/uikit/uiimpactfeedbackgenerator/feedbackstyle).
|
|
17
|
+
*/
|
|
18
|
+
export enum ImpactFeedbackStyle {
|
|
19
|
+
/** A collision between small, light user interface elements. */
|
|
20
|
+
Light = 'light',
|
|
21
|
+
/** A collision between moderately sized user interface elements. */
|
|
22
|
+
Medium = 'medium',
|
|
23
|
+
/** A collision between large, heavy user interface elements. */
|
|
24
|
+
Heavy = 'heavy',
|
|
25
|
+
/**
|
|
26
|
+
* A collision between user interface elements that are soft, exhibiting a large amount of
|
|
27
|
+
* compression or elasticity.
|
|
28
|
+
*/
|
|
29
|
+
Soft = 'soft',
|
|
30
|
+
/**
|
|
31
|
+
* A collision between user interface elements that are rigid, exhibiting a small amount of
|
|
32
|
+
* compression or elasticity.
|
|
33
|
+
*/
|
|
34
|
+
Rigid = 'rigid',
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Feedback effects driven directly by Android's haptics engine, via `performAndroidHapticsAsync`.
|
|
39
|
+
* @platform android
|
|
40
|
+
*/
|
|
41
|
+
export enum AndroidHaptics {
|
|
42
|
+
/** A haptic effect to signal the confirmation or successful completion of a user interaction. */
|
|
43
|
+
Confirm = 'confirm',
|
|
44
|
+
/** A haptic effect to signal the rejection or failure of a user interaction. */
|
|
45
|
+
Reject = 'reject',
|
|
46
|
+
/** The user has started a gesture (for example, on the soft keyboard). */
|
|
47
|
+
Gesture_Start = 'gesture-start',
|
|
48
|
+
/** The user has finished a gesture (for example, on the soft keyboard). */
|
|
49
|
+
Gesture_End = 'gesture-end',
|
|
50
|
+
/** The user has toggled a switch or button into the on position. */
|
|
51
|
+
Toggle_On = 'toggle-on',
|
|
52
|
+
/** The user has toggled a switch or button into the off position. */
|
|
53
|
+
Toggle_Off = 'toggle-off',
|
|
54
|
+
/** The user has pressed either an hour or minute tick of a Clock. */
|
|
55
|
+
Clock_Tick = 'clock-tick',
|
|
56
|
+
/** The user has performed a context click on an object. */
|
|
57
|
+
Context_Click = 'context-click',
|
|
58
|
+
/** The user has started a drag-and-drop gesture. The drag target has just been "picked up". */
|
|
59
|
+
Drag_Start = 'drag-start',
|
|
60
|
+
/** The user has pressed a soft keyboard key. */
|
|
61
|
+
Keyboard_Tap = 'keyboard-tap',
|
|
62
|
+
/** The user has pressed a virtual or software keyboard key. */
|
|
63
|
+
Keyboard_Press = 'keyboard-press',
|
|
64
|
+
/** The user has released a virtual keyboard key. */
|
|
65
|
+
Keyboard_Release = 'keyboard-release',
|
|
66
|
+
/** The user has performed a long press on an object that results in an action being performed. */
|
|
67
|
+
Long_Press = 'long-press',
|
|
68
|
+
/** The user has pressed on a virtual on-screen key. */
|
|
69
|
+
Virtual_Key = 'virtual-key',
|
|
70
|
+
/** The user has released a virtual key. */
|
|
71
|
+
Virtual_Key_Release = 'virtual-key-release',
|
|
72
|
+
/** No haptic feedback should be performed. */
|
|
73
|
+
No_Haptics = 'no-haptics',
|
|
74
|
+
/**
|
|
75
|
+
* The user is switching between a series of potential choices. For example, items in a list
|
|
76
|
+
* or discrete points on a slider.
|
|
77
|
+
*/
|
|
78
|
+
Segment_Tick = 'segment-tick',
|
|
79
|
+
/**
|
|
80
|
+
* The user is switching between a series of many potential choices. For example, minutes on a
|
|
81
|
+
* clock face or individual percentages. Expected to be very soft, so as not to be uncomfortable
|
|
82
|
+
* when performed a lot in quick succession — if the device can't make a suitably soft
|
|
83
|
+
* vibration, it may not make any vibration at all.
|
|
84
|
+
*/
|
|
85
|
+
Segment_Frequent_Tick = 'segment-frequent-tick',
|
|
86
|
+
/** The user has performed a selection/insertion handle move on a text field. */
|
|
87
|
+
Text_Handle_Move = 'text-handle-move',
|
|
88
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// @symbiote-native/haptics/react: the React entry over the framework-agnostic core.
|
|
2
|
+
// Upstream ships free async functions and three enums, no per-instance state and no event
|
|
3
|
+
// stream (same shape as @symbiote-native/local-auth) — there is nothing for a hook to wrap, so
|
|
4
|
+
// this is a plain re-export.
|
|
5
|
+
export * from '../core';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// @symbiote-native/haptics/svelte: the Svelte entry over the framework-agnostic core.
|
|
2
|
+
// Upstream ships free async functions and three enums, no per-instance state and no event
|
|
3
|
+
// stream (same shape as @symbiote-native/local-auth) — there is nothing for a rune to wrap, so
|
|
4
|
+
// this is a plain re-export. Svelte's lifecycle bucket is `runes/` (adapters/svelte/src/runes —
|
|
5
|
+
// never React's `hooks` or Vue's `composables`), and this package has none to fill.
|
|
6
|
+
export * from '../core';
|
package/src/vue/index.ts
ADDED