@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.76",
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
- // Lazy-load expo-haptics to avoid crash when native module is not available
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
- await Haptics.impactAsync(
36
- style === 'Light' ? Haptics.ImpactFeedbackStyle.Light :
37
- style === 'Medium' ? Haptics.ImpactFeedbackStyle.Medium :
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
- await Haptics.notificationAsync(
50
- type === 'Success' ? Haptics.NotificationFeedbackType.Success :
51
- type === 'Warning' ? Haptics.NotificationFeedbackType.Warning :
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
  }