@umituz/react-native-design-system 4.25.76 → 4.25.77
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-design-system",
|
|
3
|
-
"version": "4.25.
|
|
3
|
+
"version": "4.25.77",
|
|
4
4
|
"description": "Universal design system for React Native apps - Consolidated package with atoms, molecules, organisms, theme, typography, responsive, safe area, exception, infinite scroll, UUID, image, timezone, offline, onboarding, and loading utilities",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
/**
|
|
12
12
|
* Impact feedback style (compatible with expo-haptics)
|
|
13
13
|
*/
|
|
14
|
-
export type ImpactStyle = 'Light' | 'Medium' | 'Heavy';
|
|
14
|
+
export type ImpactStyle = 'Light' | 'Medium' | 'Heavy' | 'Rigid' | 'Soft';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Notification feedback type (compatible with expo-haptics)
|
|
@@ -46,7 +46,7 @@ export const HAPTIC_CONSTANTS = {
|
|
|
46
46
|
*/
|
|
47
47
|
export function isImpactStyle(value: unknown): value is ImpactStyle {
|
|
48
48
|
return typeof value === 'string' &&
|
|
49
|
-
['Light', 'Medium', 'Heavy'].includes(value);
|
|
49
|
+
['Light', 'Medium', 'Heavy', 'Rigid', 'Soft'].includes(value);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/**
|
|
@@ -2,15 +2,30 @@
|
|
|
2
2
|
* Haptics Domain - Haptic Service
|
|
3
3
|
*
|
|
4
4
|
* Service for haptic feedback using expo-haptics (optional peer dep).
|
|
5
|
-
* Falls back to noop when expo-haptics is not installed.
|
|
5
|
+
* Falls back to noop when expo-haptics is not installed or haptics are disabled.
|
|
6
|
+
*
|
|
7
|
+
* LAZY LOADING:
|
|
8
|
+
* expo-haptics is only required at runtime when a haptic is triggered AND enabled.
|
|
9
|
+
* Apps that don't need haptics pay zero cost — no require() is ever called.
|
|
10
|
+
*
|
|
11
|
+
* USAGE:
|
|
12
|
+
* // Opt out entirely (e.g. tablet apps, web, or apps without expo-haptics):
|
|
13
|
+
* HapticService.configure({ enabled: false })
|
|
14
|
+
*
|
|
15
|
+
* // Opt in (default):
|
|
16
|
+
* HapticService.configure({ enabled: true })
|
|
6
17
|
*/
|
|
7
18
|
|
|
8
19
|
import type { ImpactStyle, NotificationType, HapticPattern } from '../../domain/entities/Haptic';
|
|
9
20
|
|
|
10
|
-
//
|
|
21
|
+
// ── App-level enable/disable flag ───────────────────────────────────────────
|
|
22
|
+
let _enabled = true;
|
|
23
|
+
|
|
24
|
+
// ── Module cache — required only on first haptic call (when enabled) ────────
|
|
11
25
|
let _hapticsModule: typeof import('expo-haptics') | null = null;
|
|
12
26
|
|
|
13
27
|
const getHapticsModule = (): typeof import('expo-haptics') | null => {
|
|
28
|
+
if (!_enabled) return null;
|
|
14
29
|
if (_hapticsModule !== null) return _hapticsModule;
|
|
15
30
|
try {
|
|
16
31
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
@@ -28,15 +43,32 @@ function logError(method: string, error: unknown): void {
|
|
|
28
43
|
}
|
|
29
44
|
|
|
30
45
|
export class HapticService {
|
|
46
|
+
/**
|
|
47
|
+
* Configure haptics at the app level.
|
|
48
|
+
* Call once at startup — before any haptic is triggered.
|
|
49
|
+
*
|
|
50
|
+
* @param enabled - false to silently disable all haptics (no expo-haptics required).
|
|
51
|
+
* Defaults to true.
|
|
52
|
+
*/
|
|
53
|
+
static configure({ enabled }: { enabled: boolean }): void {
|
|
54
|
+
_enabled = enabled;
|
|
55
|
+
if (!enabled) {
|
|
56
|
+
_hapticsModule = null; // release cached reference
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
31
60
|
static async impact(style: ImpactStyle = 'Light'): Promise<void> {
|
|
32
61
|
const Haptics = getHapticsModule();
|
|
33
62
|
if (!Haptics) return;
|
|
34
63
|
try {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
Haptics.ImpactFeedbackStyle.Heavy
|
|
39
|
-
|
|
64
|
+
const styleMap: Record<ImpactStyle, (typeof Haptics.ImpactFeedbackStyle)[keyof typeof Haptics.ImpactFeedbackStyle]> = {
|
|
65
|
+
Light: Haptics.ImpactFeedbackStyle.Light,
|
|
66
|
+
Medium: Haptics.ImpactFeedbackStyle.Medium,
|
|
67
|
+
Heavy: Haptics.ImpactFeedbackStyle.Heavy,
|
|
68
|
+
Rigid: Haptics.ImpactFeedbackStyle.Rigid,
|
|
69
|
+
Soft: Haptics.ImpactFeedbackStyle.Soft,
|
|
70
|
+
};
|
|
71
|
+
await Haptics.impactAsync(styleMap[style] ?? Haptics.ImpactFeedbackStyle.Light);
|
|
40
72
|
} catch (error) {
|
|
41
73
|
logError('impact', error);
|
|
42
74
|
}
|
|
@@ -46,11 +78,12 @@ export class HapticService {
|
|
|
46
78
|
const Haptics = getHapticsModule();
|
|
47
79
|
if (!Haptics) return;
|
|
48
80
|
try {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
Haptics.NotificationFeedbackType.Error
|
|
53
|
-
|
|
81
|
+
const typeMap: Record<NotificationType, (typeof Haptics.NotificationFeedbackType)[keyof typeof Haptics.NotificationFeedbackType]> = {
|
|
82
|
+
Success: Haptics.NotificationFeedbackType.Success,
|
|
83
|
+
Warning: Haptics.NotificationFeedbackType.Warning,
|
|
84
|
+
Error: Haptics.NotificationFeedbackType.Error,
|
|
85
|
+
};
|
|
86
|
+
await Haptics.notificationAsync(typeMap[type]);
|
|
54
87
|
} catch (error) {
|
|
55
88
|
logError('notification', error);
|
|
56
89
|
}
|
|
@@ -89,6 +122,7 @@ export class HapticService {
|
|
|
89
122
|
}
|
|
90
123
|
}
|
|
91
124
|
|
|
125
|
+
// ── Convenience methods ──────────────────────────────────────────────────
|
|
92
126
|
static async buttonPress(): Promise<void> { await HapticService.impact('Light'); }
|
|
93
127
|
static async success(): Promise<void> { await HapticService.pattern('success'); }
|
|
94
128
|
static async error(): Promise<void> { await HapticService.pattern('error'); }
|
|
@@ -97,4 +131,6 @@ export class HapticService {
|
|
|
97
131
|
static async refresh(): Promise<void> { await HapticService.impact('Light'); }
|
|
98
132
|
static async selectionChange(): Promise<void> { await HapticService.pattern('selection'); }
|
|
99
133
|
static async longPress(): Promise<void> { await HapticService.impact('Medium'); }
|
|
134
|
+
static async rigid(): Promise<void> { await HapticService.impact('Rigid'); }
|
|
135
|
+
static async soft(): Promise<void> { await HapticService.impact('Soft'); }
|
|
100
136
|
}
|