rn-system-bar 3.0.2 → 3.1.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/android/src/main/java/com/systembar/SystemBarModule.kt +334 -247
- package/android/src/main/java/com/systembar/SystemBarPackage.kt +2 -1
- package/index.ts +9 -0
- package/ios/SystemBarModule.m +32 -12
- package/ios/SystemBarModule.swift +241 -83
- package/lib/index.d.ts +4 -0
- package/lib/index.js +29 -0
- package/lib/specs/NativeSystemBar.d.ts +21 -0
- package/lib/specs/NativeSystemBar.js +8 -0
- package/lib/src/SystemBar.d.ts +73 -0
- package/lib/src/SystemBar.js +292 -0
- package/lib/src/types.d.ts +44 -0
- package/lib/src/types.js +5 -0
- package/lib/src/useSystemBar.d.ts +49 -0
- package/lib/src/useSystemBar.js +194 -0
- package/package.json +14 -4
- package/rn-system-bar.podspec +1 -1
- package/src/SystemBar.ts +215 -141
- package/src/types.ts +70 -43
- package/src/useSystemBar.ts +191 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ─────────────────────────────────────────────
|
|
3
|
+
// rn-system-bar · SystemBar.ts v5
|
|
4
|
+
// All features — Android + iOS
|
|
5
|
+
// ─────────────────────────────────────────────
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.onFontScaleChange = exports.getFontScaleInfo = exports.setSecureScreen = exports.onScreencastChange = exports.getScreencastInfo = exports.haptic = exports.onBatteryChange = exports.getBatteryInfo = exports.onNetworkChange = exports.getNetworkInfo = exports.setOrientation = exports.immersiveMode = exports.keepScreenOn = exports.setVolumeHUDVisible = exports.getVolume = exports.setVolume = exports.getBrightness = exports.setBrightness = exports.setStatusBarVisibility = exports.setStatusBarStyle = exports.setStatusBarColor = exports.setNavigationBarBehavior = exports.setNavigationBarStyle = exports.setNavigationBarButtonStyle = exports.setNavigationBarVisibility = exports.setNavigationBarColor = void 0;
|
|
8
|
+
const react_native_1 = require("react-native");
|
|
9
|
+
// expo-navigation-bar — peer dep, loaded at runtime
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
11
|
+
const NavBar = (() => {
|
|
12
|
+
try {
|
|
13
|
+
return require("expo-navigation-bar");
|
|
14
|
+
}
|
|
15
|
+
catch (_a) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
})();
|
|
19
|
+
const { SystemBar: Native } = react_native_1.NativeModules;
|
|
20
|
+
const isAndroid = react_native_1.Platform.OS === "android";
|
|
21
|
+
const isIOS = react_native_1.Platform.OS === "ios";
|
|
22
|
+
const androidOnly = (name) => {
|
|
23
|
+
if (!isAndroid) {
|
|
24
|
+
if (__DEV__)
|
|
25
|
+
console.warn(`[rn-system-bar] ${name}() is Android-only, no-op on iOS.`);
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
return true;
|
|
29
|
+
};
|
|
30
|
+
const checkNative = () => {
|
|
31
|
+
if (!Native)
|
|
32
|
+
throw new Error("[rn-system-bar] Native module not found. Rebuild your project.");
|
|
33
|
+
};
|
|
34
|
+
// ═══════════════════════════════════════════════
|
|
35
|
+
// NAVIGATION BAR (Android — expo-navigation-bar)
|
|
36
|
+
// ═══════════════════════════════════════════════
|
|
37
|
+
const setNavigationBarColor = (color) => {
|
|
38
|
+
var _a;
|
|
39
|
+
if (!androidOnly("setNavigationBarColor"))
|
|
40
|
+
return Promise.resolve();
|
|
41
|
+
return (_a = NavBar === null || NavBar === void 0 ? void 0 : NavBar.setBackgroundColorAsync(color)) !== null && _a !== void 0 ? _a : Promise.resolve();
|
|
42
|
+
};
|
|
43
|
+
exports.setNavigationBarColor = setNavigationBarColor;
|
|
44
|
+
const setNavigationBarVisibility = (mode) => {
|
|
45
|
+
var _a;
|
|
46
|
+
if (!androidOnly("setNavigationBarVisibility"))
|
|
47
|
+
return Promise.resolve();
|
|
48
|
+
return (_a = NavBar === null || NavBar === void 0 ? void 0 : NavBar.setVisibilityAsync(mode)) !== null && _a !== void 0 ? _a : Promise.resolve();
|
|
49
|
+
};
|
|
50
|
+
exports.setNavigationBarVisibility = setNavigationBarVisibility;
|
|
51
|
+
const setNavigationBarButtonStyle = (style) => {
|
|
52
|
+
var _a;
|
|
53
|
+
if (!androidOnly("setNavigationBarButtonStyle"))
|
|
54
|
+
return Promise.resolve();
|
|
55
|
+
return (_a = NavBar === null || NavBar === void 0 ? void 0 : NavBar.setButtonStyleAsync(style)) !== null && _a !== void 0 ? _a : Promise.resolve();
|
|
56
|
+
};
|
|
57
|
+
exports.setNavigationBarButtonStyle = setNavigationBarButtonStyle;
|
|
58
|
+
const setNavigationBarStyle = (style) => {
|
|
59
|
+
var _a;
|
|
60
|
+
if (!androidOnly("setNavigationBarStyle"))
|
|
61
|
+
return Promise.resolve();
|
|
62
|
+
const btn = style === "dark" || style === "auto" ? "dark" : "light";
|
|
63
|
+
return (_a = NavBar === null || NavBar === void 0 ? void 0 : NavBar.setButtonStyleAsync(btn)) !== null && _a !== void 0 ? _a : Promise.resolve();
|
|
64
|
+
};
|
|
65
|
+
exports.setNavigationBarStyle = setNavigationBarStyle;
|
|
66
|
+
const setNavigationBarBehavior = (behavior) => {
|
|
67
|
+
var _a;
|
|
68
|
+
if (!androidOnly("setNavigationBarBehavior"))
|
|
69
|
+
return Promise.resolve();
|
|
70
|
+
return (_a = NavBar === null || NavBar === void 0 ? void 0 : NavBar.setBehaviorAsync(behavior)) !== null && _a !== void 0 ? _a : Promise.resolve();
|
|
71
|
+
};
|
|
72
|
+
exports.setNavigationBarBehavior = setNavigationBarBehavior;
|
|
73
|
+
// ═══════════════════════════════════════════════
|
|
74
|
+
// STATUS BAR
|
|
75
|
+
// ═══════════════════════════════════════════════
|
|
76
|
+
const setStatusBarColor = (color, animated = false) => {
|
|
77
|
+
if (!androidOnly("setStatusBarColor"))
|
|
78
|
+
return;
|
|
79
|
+
react_native_1.StatusBar.setBackgroundColor(color, animated);
|
|
80
|
+
};
|
|
81
|
+
exports.setStatusBarColor = setStatusBarColor;
|
|
82
|
+
const setStatusBarStyle = (style, animated = false) => {
|
|
83
|
+
react_native_1.StatusBar.setBarStyle(style === "light" ? "light-content" : "dark-content", animated);
|
|
84
|
+
};
|
|
85
|
+
exports.setStatusBarStyle = setStatusBarStyle;
|
|
86
|
+
const setStatusBarVisibility = (visible, animated = false) => {
|
|
87
|
+
react_native_1.StatusBar.setHidden(!visible, animated ? "slide" : "none");
|
|
88
|
+
};
|
|
89
|
+
exports.setStatusBarVisibility = setStatusBarVisibility;
|
|
90
|
+
// ═══════════════════════════════════════════════
|
|
91
|
+
// BRIGHTNESS
|
|
92
|
+
// ═══════════════════════════════════════════════
|
|
93
|
+
const setBrightness = (level) => {
|
|
94
|
+
checkNative();
|
|
95
|
+
Native.setBrightness(Math.max(0, Math.min(1, level)));
|
|
96
|
+
};
|
|
97
|
+
exports.setBrightness = setBrightness;
|
|
98
|
+
const getBrightness = () => {
|
|
99
|
+
checkNative();
|
|
100
|
+
return Native.getBrightness();
|
|
101
|
+
};
|
|
102
|
+
exports.getBrightness = getBrightness;
|
|
103
|
+
// ═══════════════════════════════════════════════
|
|
104
|
+
// VOLUME
|
|
105
|
+
// ═══════════════════════════════════════════════
|
|
106
|
+
const setVolume = (level, stream = "music") => {
|
|
107
|
+
checkNative();
|
|
108
|
+
Native.setVolume(Math.max(0, Math.min(1, level)), stream);
|
|
109
|
+
};
|
|
110
|
+
exports.setVolume = setVolume;
|
|
111
|
+
const getVolume = (stream = "music") => {
|
|
112
|
+
checkNative();
|
|
113
|
+
return Native.getVolume(stream);
|
|
114
|
+
};
|
|
115
|
+
exports.getVolume = getVolume;
|
|
116
|
+
const setVolumeHUDVisible = (visible) => {
|
|
117
|
+
if (!androidOnly("setVolumeHUDVisible"))
|
|
118
|
+
return;
|
|
119
|
+
checkNative();
|
|
120
|
+
Native.setVolumeHUDVisible(visible);
|
|
121
|
+
};
|
|
122
|
+
exports.setVolumeHUDVisible = setVolumeHUDVisible;
|
|
123
|
+
// ═══════════════════════════════════════════════
|
|
124
|
+
// SCREEN
|
|
125
|
+
// ═══════════════════════════════════════════════
|
|
126
|
+
const keepScreenOn = (enable) => {
|
|
127
|
+
checkNative();
|
|
128
|
+
Native.keepScreenOn(enable);
|
|
129
|
+
};
|
|
130
|
+
exports.keepScreenOn = keepScreenOn;
|
|
131
|
+
const immersiveMode = (enable) => {
|
|
132
|
+
if (!androidOnly("immersiveMode"))
|
|
133
|
+
return;
|
|
134
|
+
checkNative();
|
|
135
|
+
Native.immersiveMode(enable);
|
|
136
|
+
};
|
|
137
|
+
exports.immersiveMode = immersiveMode;
|
|
138
|
+
// ═══════════════════════════════════════════════
|
|
139
|
+
// ORIENTATION
|
|
140
|
+
// ═══════════════════════════════════════════════
|
|
141
|
+
const setOrientation = (mode) => {
|
|
142
|
+
checkNative();
|
|
143
|
+
Native.setOrientation(mode);
|
|
144
|
+
};
|
|
145
|
+
exports.setOrientation = setOrientation;
|
|
146
|
+
// ═══════════════════════════════════════════════
|
|
147
|
+
// 🆕 NETWORK INFO
|
|
148
|
+
// ═══════════════════════════════════════════════
|
|
149
|
+
/**
|
|
150
|
+
* Get current network connection info.
|
|
151
|
+
* Includes: type, isConnected, isAirplaneMode, ssid, cellularGeneration
|
|
152
|
+
*/
|
|
153
|
+
const getNetworkInfo = () => {
|
|
154
|
+
checkNative();
|
|
155
|
+
return Native.getNetworkInfo();
|
|
156
|
+
};
|
|
157
|
+
exports.getNetworkInfo = getNetworkInfo;
|
|
158
|
+
/**
|
|
159
|
+
* Subscribe to network changes.
|
|
160
|
+
* @returns unsubscribe function — call it in useEffect cleanup
|
|
161
|
+
* @example
|
|
162
|
+
* const unsub = onNetworkChange((info) => console.log(info));
|
|
163
|
+
* return () => unsub();
|
|
164
|
+
*/
|
|
165
|
+
const onNetworkChange = (callback) => {
|
|
166
|
+
checkNative();
|
|
167
|
+
// Native side emits "SystemBar_NetworkChange" events
|
|
168
|
+
const { DeviceEventEmitter } = require("react-native");
|
|
169
|
+
Native.startNetworkListener();
|
|
170
|
+
const sub = DeviceEventEmitter.addListener("SystemBar_NetworkChange", callback);
|
|
171
|
+
return () => {
|
|
172
|
+
sub.remove();
|
|
173
|
+
Native.stopNetworkListener();
|
|
174
|
+
};
|
|
175
|
+
};
|
|
176
|
+
exports.onNetworkChange = onNetworkChange;
|
|
177
|
+
// ═══════════════════════════════════════════════
|
|
178
|
+
// 🆕 BATTERY
|
|
179
|
+
// ═══════════════════════════════════════════════
|
|
180
|
+
/**
|
|
181
|
+
* Get current battery info: level (0–100), state, isCharging, isLow.
|
|
182
|
+
*/
|
|
183
|
+
const getBatteryInfo = () => {
|
|
184
|
+
checkNative();
|
|
185
|
+
return Native.getBatteryInfo();
|
|
186
|
+
};
|
|
187
|
+
exports.getBatteryInfo = getBatteryInfo;
|
|
188
|
+
/**
|
|
189
|
+
* Subscribe to battery level / state changes.
|
|
190
|
+
* @returns unsubscribe function
|
|
191
|
+
*/
|
|
192
|
+
const onBatteryChange = (callback) => {
|
|
193
|
+
checkNative();
|
|
194
|
+
const { DeviceEventEmitter } = require("react-native");
|
|
195
|
+
Native.startBatteryListener();
|
|
196
|
+
const sub = DeviceEventEmitter.addListener("SystemBar_BatteryChange", callback);
|
|
197
|
+
return () => {
|
|
198
|
+
sub.remove();
|
|
199
|
+
Native.stopBatteryListener();
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
exports.onBatteryChange = onBatteryChange;
|
|
203
|
+
// ═══════════════════════════════════════════════
|
|
204
|
+
// 🆕 HAPTIC FEEDBACK
|
|
205
|
+
// ═══════════════════════════════════════════════
|
|
206
|
+
/**
|
|
207
|
+
* Trigger haptic feedback.
|
|
208
|
+
*
|
|
209
|
+
* iOS: Uses UIImpactFeedbackGenerator / UINotificationFeedbackGenerator.
|
|
210
|
+
* Android: Uses Vibrator / VibrationEffect (API 26+).
|
|
211
|
+
*
|
|
212
|
+
* @param pattern "light" | "medium" | "heavy" | "success" | "warning" | "error" | "selection"
|
|
213
|
+
*/
|
|
214
|
+
const haptic = (pattern) => {
|
|
215
|
+
if (isIOS) {
|
|
216
|
+
checkNative();
|
|
217
|
+
Native.haptic(pattern);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
// Android fallback using RN's built-in Vibration API
|
|
221
|
+
// when native module is unavailable
|
|
222
|
+
if (isAndroid) {
|
|
223
|
+
checkNative();
|
|
224
|
+
Native.haptic(pattern);
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
exports.haptic = haptic;
|
|
228
|
+
// ═══════════════════════════════════════════════
|
|
229
|
+
// 🆕 SCREENCAST DETECTION
|
|
230
|
+
// ═══════════════════════════════════════════════
|
|
231
|
+
/**
|
|
232
|
+
* Check if screen is currently being cast or mirrored.
|
|
233
|
+
*/
|
|
234
|
+
const getScreencastInfo = () => {
|
|
235
|
+
checkNative();
|
|
236
|
+
return Native.getScreencastInfo();
|
|
237
|
+
};
|
|
238
|
+
exports.getScreencastInfo = getScreencastInfo;
|
|
239
|
+
/**
|
|
240
|
+
* Subscribe to screencast state changes (started / stopped).
|
|
241
|
+
* @returns unsubscribe function
|
|
242
|
+
*/
|
|
243
|
+
const onScreencastChange = (callback) => {
|
|
244
|
+
checkNative();
|
|
245
|
+
const { DeviceEventEmitter } = require("react-native");
|
|
246
|
+
Native.startScreencastListener();
|
|
247
|
+
const sub = DeviceEventEmitter.addListener("SystemBar_ScreencastChange", callback);
|
|
248
|
+
return () => {
|
|
249
|
+
sub.remove();
|
|
250
|
+
Native.stopScreencastListener();
|
|
251
|
+
};
|
|
252
|
+
};
|
|
253
|
+
exports.onScreencastChange = onScreencastChange;
|
|
254
|
+
/**
|
|
255
|
+
* Prevent screen content from appearing in screenshots / recordings.
|
|
256
|
+
* Useful for sensitive screens (payments, passwords).
|
|
257
|
+
* @platform android
|
|
258
|
+
*/
|
|
259
|
+
const setSecureScreen = (enable) => {
|
|
260
|
+
if (!androidOnly("setSecureScreen"))
|
|
261
|
+
return;
|
|
262
|
+
checkNative();
|
|
263
|
+
Native.setSecureScreen(enable);
|
|
264
|
+
};
|
|
265
|
+
exports.setSecureScreen = setSecureScreen;
|
|
266
|
+
// ═══════════════════════════════════════════════
|
|
267
|
+
// 🆕 FONT SCALE / DISPLAY INFO
|
|
268
|
+
// ═══════════════════════════════════════════════
|
|
269
|
+
/**
|
|
270
|
+
* Get current system font scale and display density.
|
|
271
|
+
* Useful for adapting layout to accessibility settings.
|
|
272
|
+
*/
|
|
273
|
+
const getFontScaleInfo = () => {
|
|
274
|
+
checkNative();
|
|
275
|
+
return Native.getFontScaleInfo();
|
|
276
|
+
};
|
|
277
|
+
exports.getFontScaleInfo = getFontScaleInfo;
|
|
278
|
+
/**
|
|
279
|
+
* Subscribe to font scale changes (user changes system text size).
|
|
280
|
+
* @returns unsubscribe function
|
|
281
|
+
*/
|
|
282
|
+
const onFontScaleChange = (callback) => {
|
|
283
|
+
checkNative();
|
|
284
|
+
const { DeviceEventEmitter } = require("react-native");
|
|
285
|
+
Native.startFontScaleListener();
|
|
286
|
+
const sub = DeviceEventEmitter.addListener("SystemBar_FontScaleChange", callback);
|
|
287
|
+
return () => {
|
|
288
|
+
sub.remove();
|
|
289
|
+
Native.stopFontScaleListener();
|
|
290
|
+
};
|
|
291
|
+
};
|
|
292
|
+
exports.onFontScaleChange = onFontScaleChange;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export type NavigationBarBehavior = "overlay-swipe" | "inset-swipe" | "inset-touch";
|
|
2
|
+
export type NavigationBarButtonStyle = "light" | "dark";
|
|
3
|
+
export type NavigationBarStyle = "auto" | "inverted" | "light" | "dark";
|
|
4
|
+
export type NavigationBarVisibility = "visible" | "hidden";
|
|
5
|
+
export type StatusBarStyle = "light" | "dark";
|
|
6
|
+
export type Orientation = "portrait" | "landscape" | "landscape-left" | "landscape-right" | "auto";
|
|
7
|
+
export type VolumeStream = "music" | "ring" | "notification" | "alarm" | "system";
|
|
8
|
+
export type NetworkType = "wifi" | "cellular" | "ethernet" | "none" | "unknown";
|
|
9
|
+
export interface NetworkInfo {
|
|
10
|
+
/** Current connection type */
|
|
11
|
+
type: NetworkType;
|
|
12
|
+
/** true if any network is reachable */
|
|
13
|
+
isConnected: boolean;
|
|
14
|
+
/** true if in airplane mode */
|
|
15
|
+
isAirplaneMode: boolean;
|
|
16
|
+
/** WiFi SSID — Android only; null on iOS / when not connected */
|
|
17
|
+
ssid: string | null;
|
|
18
|
+
/** Cellular network generation: "2G" | "3G" | "4G" | "5G" | null */
|
|
19
|
+
cellularGeneration: "2G" | "3G" | "4G" | "5G" | null;
|
|
20
|
+
}
|
|
21
|
+
export type BatteryState = "charging" | "discharging" | "full" | "unknown";
|
|
22
|
+
export interface BatteryInfo {
|
|
23
|
+
/** 0–100 */
|
|
24
|
+
level: number;
|
|
25
|
+
/** Current charging state */
|
|
26
|
+
state: BatteryState;
|
|
27
|
+
/** Shorthand: is it plugged in? */
|
|
28
|
+
isCharging: boolean;
|
|
29
|
+
/** Low battery threshold (<= 20%) */
|
|
30
|
+
isLow: boolean;
|
|
31
|
+
}
|
|
32
|
+
export type HapticPattern = "light" | "medium" | "heavy" | "success" | "warning" | "error" | "selection";
|
|
33
|
+
export interface ScreencastInfo {
|
|
34
|
+
/** true if screen is currently being cast / mirrored */
|
|
35
|
+
isCasting: boolean;
|
|
36
|
+
/** Name of the display being cast to, or null */
|
|
37
|
+
displayName: string | null;
|
|
38
|
+
}
|
|
39
|
+
export interface FontScaleInfo {
|
|
40
|
+
/** System font scale multiplier, e.g. 1.0 = default, 1.3 = large */
|
|
41
|
+
fontScale: number;
|
|
42
|
+
/** Display density (Android: dp ratio, iOS: scale) */
|
|
43
|
+
density: number;
|
|
44
|
+
}
|
package/lib/src/types.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { BatteryInfo, FontScaleInfo, HapticPattern, NavigationBarBehavior, NavigationBarButtonStyle, NavigationBarStyle, NavigationBarVisibility, NetworkInfo, Orientation, ScreencastInfo, StatusBarStyle } from "./types";
|
|
2
|
+
export interface SystemBarConfig {
|
|
3
|
+
navigationBarColor?: string;
|
|
4
|
+
navigationBarVisibility?: NavigationBarVisibility;
|
|
5
|
+
navigationBarButtonStyle?: NavigationBarButtonStyle;
|
|
6
|
+
navigationBarStyle?: NavigationBarStyle;
|
|
7
|
+
navigationBarBehavior?: NavigationBarBehavior;
|
|
8
|
+
statusBarColor?: string;
|
|
9
|
+
statusBarStyle?: StatusBarStyle;
|
|
10
|
+
statusBarVisible?: boolean;
|
|
11
|
+
statusBarAnimated?: boolean;
|
|
12
|
+
keepScreenOn?: boolean;
|
|
13
|
+
immersiveMode?: boolean;
|
|
14
|
+
brightness?: number;
|
|
15
|
+
orientation?: Orientation;
|
|
16
|
+
secureScreen?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare const useSystemBar: (config: SystemBarConfig) => void;
|
|
19
|
+
/**
|
|
20
|
+
* Reactive battery info. Auto-updates on level/state changes.
|
|
21
|
+
* @example
|
|
22
|
+
* const { level, isCharging, isLow, state } = useBattery();
|
|
23
|
+
*/
|
|
24
|
+
export declare const useBattery: () => BatteryInfo;
|
|
25
|
+
/**
|
|
26
|
+
* Reactive network info. Auto-updates on connection changes.
|
|
27
|
+
* @example
|
|
28
|
+
* const { isConnected, type, isAirplaneMode } = useNetwork();
|
|
29
|
+
*/
|
|
30
|
+
export declare const useNetwork: () => NetworkInfo;
|
|
31
|
+
/**
|
|
32
|
+
* Reactive screencast detection.
|
|
33
|
+
* @example
|
|
34
|
+
* const { isCasting, displayName } = useScreencast();
|
|
35
|
+
*/
|
|
36
|
+
export declare const useScreencast: () => ScreencastInfo;
|
|
37
|
+
/**
|
|
38
|
+
* Reactive font scale info. Updates when user changes system text size.
|
|
39
|
+
* @example
|
|
40
|
+
* const { fontScale, density } = useFontScale();
|
|
41
|
+
*/
|
|
42
|
+
export declare const useFontScale: () => FontScaleInfo;
|
|
43
|
+
/**
|
|
44
|
+
* Returns a stable haptic trigger function.
|
|
45
|
+
* @example
|
|
46
|
+
* const triggerHaptic = useHaptic();
|
|
47
|
+
* <Button onPress={() => triggerHaptic("success")} />
|
|
48
|
+
*/
|
|
49
|
+
export declare const useHaptic: () => (pattern: HapticPattern) => void;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ─────────────────────────────────────────────
|
|
3
|
+
// rn-system-bar · useSystemBar.ts v5
|
|
4
|
+
// Hooks: useSystemBar, useBattery, useNetwork,
|
|
5
|
+
// useScreencast, useFontScale
|
|
6
|
+
// ─────────────────────────────────────────────
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.useHaptic = exports.useFontScale = exports.useScreencast = exports.useNetwork = exports.useBattery = exports.useSystemBar = void 0;
|
|
42
|
+
const react_1 = require("react");
|
|
43
|
+
const SystemBar = __importStar(require("./SystemBar"));
|
|
44
|
+
const useSystemBar = (config) => {
|
|
45
|
+
const configRef = (0, react_1.useRef)("");
|
|
46
|
+
const configStr = JSON.stringify(config);
|
|
47
|
+
(0, react_1.useEffect)(() => {
|
|
48
|
+
if (configRef.current === configStr)
|
|
49
|
+
return;
|
|
50
|
+
configRef.current = configStr;
|
|
51
|
+
const apply = async () => {
|
|
52
|
+
const p = [];
|
|
53
|
+
if (config.navigationBarColor !== undefined)
|
|
54
|
+
p.push(SystemBar.setNavigationBarColor(config.navigationBarColor));
|
|
55
|
+
if (config.navigationBarVisibility !== undefined)
|
|
56
|
+
p.push(SystemBar.setNavigationBarVisibility(config.navigationBarVisibility));
|
|
57
|
+
if (config.navigationBarButtonStyle !== undefined)
|
|
58
|
+
p.push(SystemBar.setNavigationBarButtonStyle(config.navigationBarButtonStyle));
|
|
59
|
+
if (config.navigationBarStyle !== undefined)
|
|
60
|
+
p.push(SystemBar.setNavigationBarStyle(config.navigationBarStyle));
|
|
61
|
+
if (config.navigationBarBehavior !== undefined)
|
|
62
|
+
p.push(SystemBar.setNavigationBarBehavior(config.navigationBarBehavior));
|
|
63
|
+
await Promise.allSettled(p);
|
|
64
|
+
if (config.statusBarColor !== undefined)
|
|
65
|
+
SystemBar.setStatusBarColor(config.statusBarColor, config.statusBarAnimated);
|
|
66
|
+
if (config.statusBarStyle !== undefined)
|
|
67
|
+
SystemBar.setStatusBarStyle(config.statusBarStyle, config.statusBarAnimated);
|
|
68
|
+
if (config.statusBarVisible !== undefined)
|
|
69
|
+
SystemBar.setStatusBarVisibility(config.statusBarVisible, config.statusBarAnimated);
|
|
70
|
+
if (config.keepScreenOn !== undefined)
|
|
71
|
+
SystemBar.keepScreenOn(config.keepScreenOn);
|
|
72
|
+
if (config.immersiveMode !== undefined)
|
|
73
|
+
SystemBar.immersiveMode(config.immersiveMode);
|
|
74
|
+
if (config.brightness !== undefined)
|
|
75
|
+
SystemBar.setBrightness(config.brightness);
|
|
76
|
+
if (config.orientation !== undefined)
|
|
77
|
+
SystemBar.setOrientation(config.orientation);
|
|
78
|
+
if (config.secureScreen !== undefined)
|
|
79
|
+
SystemBar.setSecureScreen(config.secureScreen);
|
|
80
|
+
};
|
|
81
|
+
apply().catch(() => {
|
|
82
|
+
if (__DEV__)
|
|
83
|
+
console.warn("[rn-system-bar] useSystemBar: one or more settings failed.");
|
|
84
|
+
});
|
|
85
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
86
|
+
}, [configStr]);
|
|
87
|
+
};
|
|
88
|
+
exports.useSystemBar = useSystemBar;
|
|
89
|
+
// ─────────────────────────────────────────────
|
|
90
|
+
// 🆕 useBattery
|
|
91
|
+
// ─────────────────────────────────────────────
|
|
92
|
+
/**
|
|
93
|
+
* Reactive battery info. Auto-updates on level/state changes.
|
|
94
|
+
* @example
|
|
95
|
+
* const { level, isCharging, isLow, state } = useBattery();
|
|
96
|
+
*/
|
|
97
|
+
const useBattery = () => {
|
|
98
|
+
const [info, setInfo] = (0, react_1.useState)({
|
|
99
|
+
level: -1,
|
|
100
|
+
state: "unknown",
|
|
101
|
+
isCharging: false,
|
|
102
|
+
isLow: false,
|
|
103
|
+
});
|
|
104
|
+
(0, react_1.useEffect)(() => {
|
|
105
|
+
let unsub;
|
|
106
|
+
SystemBar.getBatteryInfo().then(setInfo).catch(() => { });
|
|
107
|
+
unsub = SystemBar.onBatteryChange(setInfo);
|
|
108
|
+
return () => unsub === null || unsub === void 0 ? void 0 : unsub();
|
|
109
|
+
}, []);
|
|
110
|
+
return info;
|
|
111
|
+
};
|
|
112
|
+
exports.useBattery = useBattery;
|
|
113
|
+
// ─────────────────────────────────────────────
|
|
114
|
+
// 🆕 useNetwork
|
|
115
|
+
// ─────────────────────────────────────────────
|
|
116
|
+
/**
|
|
117
|
+
* Reactive network info. Auto-updates on connection changes.
|
|
118
|
+
* @example
|
|
119
|
+
* const { isConnected, type, isAirplaneMode } = useNetwork();
|
|
120
|
+
*/
|
|
121
|
+
const useNetwork = () => {
|
|
122
|
+
const [info, setInfo] = (0, react_1.useState)({
|
|
123
|
+
type: "unknown",
|
|
124
|
+
isConnected: false,
|
|
125
|
+
isAirplaneMode: false,
|
|
126
|
+
ssid: null,
|
|
127
|
+
cellularGeneration: null,
|
|
128
|
+
});
|
|
129
|
+
(0, react_1.useEffect)(() => {
|
|
130
|
+
let unsub;
|
|
131
|
+
SystemBar.getNetworkInfo().then(setInfo).catch(() => { });
|
|
132
|
+
unsub = SystemBar.onNetworkChange(setInfo);
|
|
133
|
+
return () => unsub === null || unsub === void 0 ? void 0 : unsub();
|
|
134
|
+
}, []);
|
|
135
|
+
return info;
|
|
136
|
+
};
|
|
137
|
+
exports.useNetwork = useNetwork;
|
|
138
|
+
// ─────────────────────────────────────────────
|
|
139
|
+
// 🆕 useScreencast
|
|
140
|
+
// ─────────────────────────────────────────────
|
|
141
|
+
/**
|
|
142
|
+
* Reactive screencast detection.
|
|
143
|
+
* @example
|
|
144
|
+
* const { isCasting, displayName } = useScreencast();
|
|
145
|
+
*/
|
|
146
|
+
const useScreencast = () => {
|
|
147
|
+
const [info, setInfo] = (0, react_1.useState)({
|
|
148
|
+
isCasting: false,
|
|
149
|
+
displayName: null,
|
|
150
|
+
});
|
|
151
|
+
(0, react_1.useEffect)(() => {
|
|
152
|
+
let unsub;
|
|
153
|
+
SystemBar.getScreencastInfo().then(setInfo).catch(() => { });
|
|
154
|
+
unsub = SystemBar.onScreencastChange(setInfo);
|
|
155
|
+
return () => unsub === null || unsub === void 0 ? void 0 : unsub();
|
|
156
|
+
}, []);
|
|
157
|
+
return info;
|
|
158
|
+
};
|
|
159
|
+
exports.useScreencast = useScreencast;
|
|
160
|
+
// ─────────────────────────────────────────────
|
|
161
|
+
// 🆕 useFontScale
|
|
162
|
+
// ─────────────────────────────────────────────
|
|
163
|
+
/**
|
|
164
|
+
* Reactive font scale info. Updates when user changes system text size.
|
|
165
|
+
* @example
|
|
166
|
+
* const { fontScale, density } = useFontScale();
|
|
167
|
+
*/
|
|
168
|
+
const useFontScale = () => {
|
|
169
|
+
const [info, setInfo] = (0, react_1.useState)({
|
|
170
|
+
fontScale: 1.0,
|
|
171
|
+
density: 1.0,
|
|
172
|
+
});
|
|
173
|
+
(0, react_1.useEffect)(() => {
|
|
174
|
+
let unsub;
|
|
175
|
+
SystemBar.getFontScaleInfo().then(setInfo).catch(() => { });
|
|
176
|
+
unsub = SystemBar.onFontScaleChange(setInfo);
|
|
177
|
+
return () => unsub === null || unsub === void 0 ? void 0 : unsub();
|
|
178
|
+
}, []);
|
|
179
|
+
return info;
|
|
180
|
+
};
|
|
181
|
+
exports.useFontScale = useFontScale;
|
|
182
|
+
// ─────────────────────────────────────────────
|
|
183
|
+
// 🆕 useHaptic
|
|
184
|
+
// ─────────────────────────────────────────────
|
|
185
|
+
/**
|
|
186
|
+
* Returns a stable haptic trigger function.
|
|
187
|
+
* @example
|
|
188
|
+
* const triggerHaptic = useHaptic();
|
|
189
|
+
* <Button onPress={() => triggerHaptic("success")} />
|
|
190
|
+
*/
|
|
191
|
+
const useHaptic = () => {
|
|
192
|
+
return (pattern) => SystemBar.haptic(pattern);
|
|
193
|
+
};
|
|
194
|
+
exports.useHaptic = useHaptic;
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rn-system-bar",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Control Android & iOS system bars, brightness, volume, orientation and screen flags from React Native.",
|
|
5
|
-
"main": "index.
|
|
6
|
-
"react-native": "index.
|
|
7
|
-
"types": "
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"react-native": "lib/index.js",
|
|
7
|
+
"types": "lib/index.d.ts",
|
|
8
8
|
"homepage": "https://github.com/your-org/rn-system-bar",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"author": "Your Name",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"files": [
|
|
24
24
|
"index.ts",
|
|
25
25
|
"src/",
|
|
26
|
+
"lib/",
|
|
26
27
|
"specs/",
|
|
27
28
|
"android/",
|
|
28
29
|
"ios/",
|
|
@@ -31,5 +32,14 @@
|
|
|
31
32
|
"peerDependencies": {
|
|
32
33
|
"react": ">=18.0.0",
|
|
33
34
|
"react-native": ">=0.73.0"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "rimraf lib && npx tsc",
|
|
38
|
+
"npm:prepublish": "npm publish --access public"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/react": "^19.2.14",
|
|
42
|
+
"@types/react-native": "^0.72.8",
|
|
43
|
+
"typescript": "^5.9.3"
|
|
34
44
|
}
|
|
35
45
|
}
|
package/rn-system-bar.podspec
CHANGED
|
@@ -14,7 +14,7 @@ Pod::Spec.new do |s|
|
|
|
14
14
|
s.authors = package["author"]
|
|
15
15
|
|
|
16
16
|
s.platforms = { :ios => "13.0" }
|
|
17
|
-
s.source = { :git => "https://github.com/your-org/rn-system-bar.git",
|
|
17
|
+
# s.source = { :git => "https://github.com/your-org/rn-system-bar.git",
|
|
18
18
|
:tag => "v#{s.version}" }
|
|
19
19
|
|
|
20
20
|
s.source_files = "ios/**/*.{h,m,mm,swift}"
|