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.
@@ -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
+ }
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ // ─────────────────────────────────────────────
3
+ // rn-system-bar · types.ts v5
4
+ // ─────────────────────────────────────────────
5
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -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.2",
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.ts",
6
- "react-native": "index.ts",
7
- "types": "src/types.ts",
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
  }
@@ -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}"