react-native-permission-handler 0.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/dist/index.js ADDED
@@ -0,0 +1,598 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ DefaultBlockedPrompt: () => DefaultBlockedPrompt,
24
+ DefaultPrePrompt: () => DefaultPrePrompt,
25
+ PermissionGate: () => PermissionGate,
26
+ transition: () => transition,
27
+ useMultiplePermissions: () => useMultiplePermissions,
28
+ usePermissionHandler: () => usePermissionHandler
29
+ });
30
+ module.exports = __toCommonJS(index_exports);
31
+
32
+ // src/core/state-machine.ts
33
+ function transition(state, event) {
34
+ switch (state) {
35
+ case "idle":
36
+ if (event.type === "CHECK") return "checking";
37
+ return state;
38
+ case "checking":
39
+ if (event.type === "CHECK_RESULT") {
40
+ switch (event.status) {
41
+ case "granted":
42
+ case "limited":
43
+ return "granted";
44
+ case "denied":
45
+ return "prePrompt";
46
+ case "blocked":
47
+ return "blockedPrompt";
48
+ case "unavailable":
49
+ return "unavailable";
50
+ default:
51
+ return state;
52
+ }
53
+ }
54
+ return state;
55
+ case "prePrompt":
56
+ if (event.type === "PRE_PROMPT_CONFIRM") return "requesting";
57
+ if (event.type === "PRE_PROMPT_DISMISS") return "denied";
58
+ return state;
59
+ case "requesting":
60
+ if (event.type === "REQUEST_RESULT") {
61
+ switch (event.status) {
62
+ case "granted":
63
+ case "limited":
64
+ return "granted";
65
+ case "denied":
66
+ return "denied";
67
+ case "blocked":
68
+ return "blockedPrompt";
69
+ default:
70
+ return state;
71
+ }
72
+ }
73
+ return state;
74
+ case "blockedPrompt":
75
+ if (event.type === "OPEN_SETTINGS") return "openingSettings";
76
+ return state;
77
+ case "openingSettings":
78
+ if (event.type === "SETTINGS_RETURN") return "recheckingAfterSettings";
79
+ return state;
80
+ case "recheckingAfterSettings":
81
+ if (event.type === "RECHECK_RESULT") {
82
+ switch (event.status) {
83
+ case "granted":
84
+ case "limited":
85
+ return "granted";
86
+ case "blocked":
87
+ return "blockedPrompt";
88
+ case "denied":
89
+ return "blockedPrompt";
90
+ default:
91
+ return state;
92
+ }
93
+ }
94
+ return state;
95
+ case "granted":
96
+ case "denied":
97
+ case "unavailable":
98
+ if (event.type === "CHECK") return "checking";
99
+ return state;
100
+ case "blocked":
101
+ return state;
102
+ default:
103
+ return state;
104
+ }
105
+ }
106
+
107
+ // src/hooks/use-permission-handler.ts
108
+ var import_react = require("react");
109
+ var import_react_native = require("react-native");
110
+ var import_react_native_permissions = require("react-native-permissions");
111
+ function isNotifications(permission) {
112
+ return permission === "notifications";
113
+ }
114
+ function usePermissionHandler(config) {
115
+ const [flowState, setFlowState] = (0, import_react.useState)("idle");
116
+ const [nativeStatus, setNativeStatus] = (0, import_react.useState)(null);
117
+ const isRequesting = (0, import_react.useRef)(false);
118
+ const waitingForSettings = (0, import_react.useRef)(false);
119
+ const appStateRef = (0, import_react.useRef)(import_react_native.AppState.currentState);
120
+ const { permission, autoCheck = true, onGrant, onDeny, onBlock, onSettingsReturn } = config;
121
+ const checkPermission = (0, import_react.useCallback)(async () => {
122
+ setFlowState((s) => transition(s, { type: "CHECK" }));
123
+ try {
124
+ let status;
125
+ if (isNotifications(permission)) {
126
+ const result = await (0, import_react_native_permissions.checkNotifications)();
127
+ status = result.status;
128
+ } else {
129
+ status = await (0, import_react_native_permissions.check)(permission);
130
+ }
131
+ setNativeStatus(status);
132
+ setFlowState((s) => {
133
+ const next = transition(s, { type: "CHECK_RESULT", status });
134
+ if (next === "granted" && s !== "granted") onGrant?.();
135
+ return next;
136
+ });
137
+ } catch {
138
+ setFlowState("idle");
139
+ }
140
+ }, [permission, onGrant]);
141
+ const requestPermission = (0, import_react.useCallback)(async () => {
142
+ if (isRequesting.current) return;
143
+ isRequesting.current = true;
144
+ setFlowState((s) => transition(s, { type: "PRE_PROMPT_CONFIRM" }));
145
+ try {
146
+ let status;
147
+ if (isNotifications(permission)) {
148
+ const result = await (0, import_react_native_permissions.requestNotifications)(["alert", "badge", "sound"]);
149
+ status = result.status;
150
+ } else {
151
+ status = await (0, import_react_native_permissions.request)(permission);
152
+ }
153
+ setNativeStatus(status);
154
+ setFlowState((s) => {
155
+ const next = transition(s, { type: "REQUEST_RESULT", status });
156
+ if (next === "granted") onGrant?.();
157
+ if (next === "denied") onDeny?.();
158
+ if (next === "blockedPrompt") onBlock?.();
159
+ return next;
160
+ });
161
+ } catch {
162
+ setFlowState("denied");
163
+ } finally {
164
+ isRequesting.current = false;
165
+ }
166
+ }, [permission, onGrant, onDeny, onBlock]);
167
+ const dismiss = (0, import_react.useCallback)(() => {
168
+ setFlowState((s) => transition(s, { type: "PRE_PROMPT_DISMISS" }));
169
+ onDeny?.();
170
+ }, [onDeny]);
171
+ const goToSettings = (0, import_react.useCallback)(async () => {
172
+ setFlowState((s) => transition(s, { type: "OPEN_SETTINGS" }));
173
+ waitingForSettings.current = true;
174
+ try {
175
+ await (0, import_react_native_permissions.openSettings)();
176
+ } catch {
177
+ waitingForSettings.current = false;
178
+ setFlowState("blockedPrompt");
179
+ }
180
+ }, []);
181
+ const recheckAfterSettings = (0, import_react.useCallback)(async () => {
182
+ setFlowState((s) => transition(s, { type: "SETTINGS_RETURN" }));
183
+ try {
184
+ let status;
185
+ if (isNotifications(permission)) {
186
+ const result = await (0, import_react_native_permissions.checkNotifications)();
187
+ status = result.status;
188
+ } else {
189
+ status = await (0, import_react_native_permissions.check)(permission);
190
+ }
191
+ setNativeStatus(status);
192
+ setFlowState((s) => {
193
+ const next = transition(s, { type: "RECHECK_RESULT", status });
194
+ if (next === "granted") onGrant?.();
195
+ onSettingsReturn?.(next === "granted");
196
+ return next;
197
+ });
198
+ } catch {
199
+ setFlowState("blockedPrompt");
200
+ }
201
+ }, [permission, onGrant, onSettingsReturn]);
202
+ (0, import_react.useEffect)(() => {
203
+ if (autoCheck) {
204
+ checkPermission();
205
+ }
206
+ }, []);
207
+ (0, import_react.useEffect)(() => {
208
+ const subscription = import_react_native.AppState.addEventListener("change", (nextAppState) => {
209
+ if (appStateRef.current.match(/inactive|background/) && nextAppState === "active" && waitingForSettings.current) {
210
+ waitingForSettings.current = false;
211
+ recheckAfterSettings();
212
+ }
213
+ appStateRef.current = nextAppState;
214
+ });
215
+ return () => subscription.remove();
216
+ }, [recheckAfterSettings]);
217
+ return {
218
+ state: flowState,
219
+ nativeStatus,
220
+ isGranted: flowState === "granted",
221
+ isDenied: flowState === "denied",
222
+ isBlocked: flowState === "blocked" || flowState === "blockedPrompt" || flowState === "openingSettings",
223
+ isChecking: flowState === "checking" || flowState === "recheckingAfterSettings",
224
+ isUnavailable: flowState === "unavailable",
225
+ request: requestPermission,
226
+ check: checkPermission,
227
+ dismiss,
228
+ openSettings: goToSettings
229
+ };
230
+ }
231
+
232
+ // src/hooks/use-multiple-permissions.ts
233
+ var import_react2 = require("react");
234
+ var import_react_native_permissions2 = require("react-native-permissions");
235
+ function isNotifications2(permission) {
236
+ return permission === "notifications";
237
+ }
238
+ async function checkOne(entry) {
239
+ if (isNotifications2(entry.permission)) {
240
+ const result = await (0, import_react_native_permissions2.checkNotifications)();
241
+ return result.status;
242
+ }
243
+ return (0, import_react_native_permissions2.check)(entry.permission);
244
+ }
245
+ async function requestOne(entry) {
246
+ if (isNotifications2(entry.permission)) {
247
+ const result = await (0, import_react_native_permissions2.requestNotifications)(["alert", "badge", "sound"]);
248
+ return result.status;
249
+ }
250
+ return (0, import_react_native_permissions2.request)(entry.permission);
251
+ }
252
+ function permissionKey(entry) {
253
+ return String(entry.permission);
254
+ }
255
+ function isGrantedStatus(status) {
256
+ return status === "granted" || status === "limited";
257
+ }
258
+ function useMultiplePermissions(config) {
259
+ const { permissions, strategy, onAllGranted } = config;
260
+ const [statuses, setStatuses] = (0, import_react2.useState)(() => {
261
+ const initial = {};
262
+ for (const entry of permissions) {
263
+ initial[permissionKey(entry)] = "idle";
264
+ }
265
+ return initial;
266
+ });
267
+ const isRunning = (0, import_react2.useRef)(false);
268
+ const allGranted = permissions.every((entry) => statuses[permissionKey(entry)] === "granted");
269
+ const requestAll = (0, import_react2.useCallback)(async () => {
270
+ if (isRunning.current) return;
271
+ isRunning.current = true;
272
+ const update = (key, state) => {
273
+ setStatuses((prev) => ({ ...prev, [key]: state }));
274
+ };
275
+ try {
276
+ if (strategy === "sequential") {
277
+ await runSequential(permissions, update);
278
+ } else {
279
+ await runParallel(permissions, update);
280
+ }
281
+ let allDone = true;
282
+ for (const entry of permissions) {
283
+ const finalStatus = await checkOne(entry);
284
+ if (!isGrantedStatus(finalStatus)) {
285
+ allDone = false;
286
+ break;
287
+ }
288
+ }
289
+ if (allDone) {
290
+ onAllGranted?.();
291
+ }
292
+ } finally {
293
+ isRunning.current = false;
294
+ }
295
+ }, [permissions, strategy, onAllGranted]);
296
+ return {
297
+ statuses,
298
+ allGranted,
299
+ request: requestAll
300
+ };
301
+ }
302
+ async function runSequential(permissions, updateStatus) {
303
+ for (const entry of permissions) {
304
+ const key = permissionKey(entry);
305
+ updateStatus(key, "checking");
306
+ const checkStatus = await checkOne(entry);
307
+ if (isGrantedStatus(checkStatus)) {
308
+ updateStatus(key, "granted");
309
+ entry.onGrant?.();
310
+ continue;
311
+ }
312
+ if (checkStatus === "unavailable") {
313
+ updateStatus(key, "unavailable");
314
+ continue;
315
+ }
316
+ if (checkStatus === "blocked") {
317
+ updateStatus(key, "blockedPrompt");
318
+ entry.onBlock?.();
319
+ break;
320
+ }
321
+ updateStatus(key, "requesting");
322
+ const requestStatus = await requestOne(entry);
323
+ if (isGrantedStatus(requestStatus)) {
324
+ updateStatus(key, "granted");
325
+ entry.onGrant?.();
326
+ } else if (requestStatus === "blocked") {
327
+ updateStatus(key, "blockedPrompt");
328
+ entry.onBlock?.();
329
+ break;
330
+ } else {
331
+ updateStatus(key, "denied");
332
+ entry.onDeny?.();
333
+ break;
334
+ }
335
+ }
336
+ }
337
+ async function runParallel(permissions, updateStatus) {
338
+ const checkResults = await Promise.all(
339
+ permissions.map(async (entry) => {
340
+ const key = permissionKey(entry);
341
+ updateStatus(key, "checking");
342
+ const status = await checkOne(entry);
343
+ return { entry, key, status };
344
+ })
345
+ );
346
+ for (const { entry, key, status } of checkResults) {
347
+ if (isGrantedStatus(status)) {
348
+ updateStatus(key, "granted");
349
+ entry.onGrant?.();
350
+ } else if (status === "unavailable") {
351
+ updateStatus(key, "unavailable");
352
+ }
353
+ }
354
+ const needsAction = checkResults.filter(
355
+ ({ status }) => status === "denied" || status === "blocked"
356
+ );
357
+ for (const { entry, key, status } of needsAction) {
358
+ if (status === "blocked") {
359
+ updateStatus(key, "blockedPrompt");
360
+ entry.onBlock?.();
361
+ continue;
362
+ }
363
+ updateStatus(key, "requesting");
364
+ const requestStatus = await requestOne(entry);
365
+ if (isGrantedStatus(requestStatus)) {
366
+ updateStatus(key, "granted");
367
+ entry.onGrant?.();
368
+ } else if (requestStatus === "blocked") {
369
+ updateStatus(key, "blockedPrompt");
370
+ entry.onBlock?.();
371
+ } else {
372
+ updateStatus(key, "denied");
373
+ entry.onDeny?.();
374
+ }
375
+ }
376
+ }
377
+
378
+ // src/components/default-blocked-prompt.tsx
379
+ var import_react_native2 = require("react-native");
380
+ var import_jsx_runtime = require("react/jsx-runtime");
381
+ function DefaultBlockedPrompt({
382
+ visible,
383
+ title,
384
+ message,
385
+ settingsLabel = "Open Settings",
386
+ onOpenSettings
387
+ }) {
388
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Modal, { visible, transparent: true, animationType: "fade", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: styles.overlay, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: styles.modal, children: [
389
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.title, children: title }),
390
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.message, children: message }),
391
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
392
+ import_react_native2.TouchableOpacity,
393
+ {
394
+ style: styles.settingsButton,
395
+ onPress: onOpenSettings,
396
+ accessibilityRole: "button",
397
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: styles.settingsText, children: settingsLabel })
398
+ }
399
+ )
400
+ ] }) }) });
401
+ }
402
+ var styles = import_react_native2.StyleSheet.create({
403
+ overlay: {
404
+ flex: 1,
405
+ backgroundColor: "rgba(0,0,0,0.5)",
406
+ justifyContent: "center",
407
+ alignItems: "center"
408
+ },
409
+ modal: {
410
+ backgroundColor: "white",
411
+ borderRadius: 16,
412
+ padding: 24,
413
+ width: "85%",
414
+ alignItems: "center"
415
+ },
416
+ title: {
417
+ fontSize: 20,
418
+ fontWeight: "600",
419
+ marginBottom: 12,
420
+ textAlign: "center"
421
+ },
422
+ message: {
423
+ fontSize: 15,
424
+ color: "#666",
425
+ textAlign: "center",
426
+ marginBottom: 24,
427
+ lineHeight: 22
428
+ },
429
+ settingsButton: {
430
+ backgroundColor: "#007AFF",
431
+ borderRadius: 12,
432
+ paddingVertical: 14,
433
+ paddingHorizontal: 32,
434
+ width: "100%",
435
+ alignItems: "center"
436
+ },
437
+ settingsText: {
438
+ color: "white",
439
+ fontSize: 16,
440
+ fontWeight: "600"
441
+ }
442
+ });
443
+
444
+ // src/components/default-pre-prompt.tsx
445
+ var import_react_native3 = require("react-native");
446
+ var import_jsx_runtime2 = require("react/jsx-runtime");
447
+ function DefaultPrePrompt({
448
+ visible,
449
+ title,
450
+ message,
451
+ confirmLabel = "Continue",
452
+ cancelLabel = "Not Now",
453
+ onConfirm,
454
+ onCancel
455
+ }) {
456
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.Modal, { visible, transparent: true, animationType: "fade", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.View, { style: styles2.overlay, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native3.View, { style: styles2.modal, children: [
457
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.Text, { style: styles2.title, children: title }),
458
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.Text, { style: styles2.message, children: message }),
459
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
460
+ import_react_native3.TouchableOpacity,
461
+ {
462
+ style: styles2.confirmButton,
463
+ onPress: onConfirm,
464
+ accessibilityRole: "button",
465
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.Text, { style: styles2.confirmText, children: confirmLabel })
466
+ }
467
+ ),
468
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.TouchableOpacity, { onPress: onCancel, accessibilityRole: "button", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.Text, { style: styles2.cancelText, children: cancelLabel }) })
469
+ ] }) }) });
470
+ }
471
+ var styles2 = import_react_native3.StyleSheet.create({
472
+ overlay: {
473
+ flex: 1,
474
+ backgroundColor: "rgba(0,0,0,0.5)",
475
+ justifyContent: "center",
476
+ alignItems: "center"
477
+ },
478
+ modal: {
479
+ backgroundColor: "white",
480
+ borderRadius: 16,
481
+ padding: 24,
482
+ width: "85%",
483
+ alignItems: "center"
484
+ },
485
+ title: {
486
+ fontSize: 20,
487
+ fontWeight: "600",
488
+ marginBottom: 12,
489
+ textAlign: "center"
490
+ },
491
+ message: {
492
+ fontSize: 15,
493
+ color: "#666",
494
+ textAlign: "center",
495
+ marginBottom: 24,
496
+ lineHeight: 22
497
+ },
498
+ confirmButton: {
499
+ backgroundColor: "#007AFF",
500
+ borderRadius: 12,
501
+ paddingVertical: 14,
502
+ paddingHorizontal: 32,
503
+ width: "100%",
504
+ alignItems: "center",
505
+ marginBottom: 12
506
+ },
507
+ confirmText: {
508
+ color: "white",
509
+ fontSize: 16,
510
+ fontWeight: "600"
511
+ },
512
+ cancelText: {
513
+ color: "#007AFF",
514
+ fontSize: 15
515
+ }
516
+ });
517
+
518
+ // src/components/permission-gate.tsx
519
+ var import_jsx_runtime3 = require("react/jsx-runtime");
520
+ function PermissionGate({
521
+ permission,
522
+ prePrompt,
523
+ blockedPrompt,
524
+ children,
525
+ fallback = null,
526
+ renderPrePrompt,
527
+ renderBlockedPrompt,
528
+ onGrant,
529
+ onDeny,
530
+ onBlock,
531
+ onSettingsReturn
532
+ }) {
533
+ const handler = usePermissionHandler({
534
+ permission,
535
+ prePrompt,
536
+ blockedPrompt,
537
+ onGrant,
538
+ onDeny,
539
+ onBlock,
540
+ onSettingsReturn
541
+ });
542
+ if (handler.isGranted) {
543
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children });
544
+ }
545
+ if (handler.isChecking || handler.isUnavailable) {
546
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: fallback });
547
+ }
548
+ if (handler.state === "prePrompt") {
549
+ if (renderPrePrompt) {
550
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: renderPrePrompt({
551
+ config: prePrompt,
552
+ onConfirm: handler.request,
553
+ onCancel: handler.dismiss
554
+ }) });
555
+ }
556
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
557
+ DefaultPrePrompt,
558
+ {
559
+ visible: true,
560
+ title: prePrompt.title,
561
+ message: prePrompt.message,
562
+ confirmLabel: prePrompt.confirmLabel,
563
+ cancelLabel: prePrompt.cancelLabel,
564
+ onConfirm: handler.request,
565
+ onCancel: handler.dismiss
566
+ }
567
+ );
568
+ }
569
+ if (handler.state === "blockedPrompt") {
570
+ if (renderBlockedPrompt) {
571
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: renderBlockedPrompt({
572
+ config: blockedPrompt,
573
+ onOpenSettings: handler.openSettings
574
+ }) });
575
+ }
576
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
577
+ DefaultBlockedPrompt,
578
+ {
579
+ visible: true,
580
+ title: blockedPrompt.title,
581
+ message: blockedPrompt.message,
582
+ settingsLabel: blockedPrompt.settingsLabel,
583
+ onOpenSettings: handler.openSettings
584
+ }
585
+ );
586
+ }
587
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: fallback });
588
+ }
589
+ // Annotate the CommonJS export names for ESM import in node:
590
+ 0 && (module.exports = {
591
+ DefaultBlockedPrompt,
592
+ DefaultPrePrompt,
593
+ PermissionGate,
594
+ transition,
595
+ useMultiplePermissions,
596
+ usePermissionHandler
597
+ });
598
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/core/state-machine.ts","../src/hooks/use-permission-handler.ts","../src/hooks/use-multiple-permissions.ts","../src/components/default-blocked-prompt.tsx","../src/components/default-pre-prompt.tsx","../src/components/permission-gate.tsx"],"sourcesContent":["export type {\n BlockedPromptConfig,\n MultiPermissionEntry,\n MultiplePermissionsConfig,\n MultiplePermissionsResult,\n PermissionCallbacks,\n PermissionFlowEvent,\n PermissionFlowState,\n PermissionHandlerConfig,\n PermissionHandlerResult,\n PrePromptConfig,\n} from \"./types\";\n\nexport { transition } from \"./core/state-machine\";\nexport { usePermissionHandler } from \"./hooks/use-permission-handler\";\nexport { useMultiplePermissions } from \"./hooks/use-multiple-permissions\";\nexport { PermissionGate } from \"./components/permission-gate\";\nexport type { PermissionGateProps } from \"./components/permission-gate\";\nexport { DefaultPrePrompt } from \"./components/default-pre-prompt\";\nexport type { DefaultPrePromptProps } from \"./components/default-pre-prompt\";\nexport { DefaultBlockedPrompt } from \"./components/default-blocked-prompt\";\nexport type { DefaultBlockedPromptProps } from \"./components/default-blocked-prompt\";\n","import type { PermissionFlowEvent, PermissionFlowState } from \"../types\";\n\nexport function transition(\n state: PermissionFlowState,\n event: PermissionFlowEvent,\n): PermissionFlowState {\n switch (state) {\n case \"idle\":\n if (event.type === \"CHECK\") return \"checking\";\n return state;\n\n case \"checking\":\n if (event.type === \"CHECK_RESULT\") {\n switch (event.status) {\n case \"granted\":\n case \"limited\":\n return \"granted\";\n case \"denied\":\n return \"prePrompt\";\n case \"blocked\":\n return \"blockedPrompt\";\n case \"unavailable\":\n return \"unavailable\";\n default:\n return state;\n }\n }\n return state;\n\n case \"prePrompt\":\n if (event.type === \"PRE_PROMPT_CONFIRM\") return \"requesting\";\n if (event.type === \"PRE_PROMPT_DISMISS\") return \"denied\";\n return state;\n\n case \"requesting\":\n if (event.type === \"REQUEST_RESULT\") {\n switch (event.status) {\n case \"granted\":\n case \"limited\":\n return \"granted\";\n case \"denied\":\n return \"denied\";\n case \"blocked\":\n return \"blockedPrompt\";\n default:\n return state;\n }\n }\n return state;\n\n case \"blockedPrompt\":\n if (event.type === \"OPEN_SETTINGS\") return \"openingSettings\";\n return state;\n\n case \"openingSettings\":\n if (event.type === \"SETTINGS_RETURN\") return \"recheckingAfterSettings\";\n return state;\n\n case \"recheckingAfterSettings\":\n if (event.type === \"RECHECK_RESULT\") {\n switch (event.status) {\n case \"granted\":\n case \"limited\":\n return \"granted\";\n case \"blocked\":\n return \"blockedPrompt\";\n case \"denied\":\n return \"blockedPrompt\";\n default:\n return state;\n }\n }\n return state;\n\n case \"granted\":\n case \"denied\":\n case \"unavailable\":\n if (event.type === \"CHECK\") return \"checking\";\n return state;\n\n case \"blocked\":\n return state;\n\n default:\n return state;\n }\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { AppState } from \"react-native\";\nimport {\n type PermissionStatus,\n check,\n checkNotifications,\n openSettings,\n request,\n requestNotifications,\n} from \"react-native-permissions\";\nimport { transition } from \"../core/state-machine\";\nimport type {\n PermissionFlowState,\n PermissionHandlerConfig,\n PermissionHandlerResult,\n} from \"../types\";\n\nfunction isNotifications(\n permission: PermissionHandlerConfig[\"permission\"],\n): permission is \"notifications\" {\n return permission === \"notifications\";\n}\n\nexport function usePermissionHandler(config: PermissionHandlerConfig): PermissionHandlerResult {\n const [flowState, setFlowState] = useState<PermissionFlowState>(\"idle\");\n const [nativeStatus, setNativeStatus] = useState<PermissionStatus | null>(null);\n const isRequesting = useRef(false);\n const waitingForSettings = useRef(false);\n const appStateRef = useRef(AppState.currentState);\n\n const { permission, autoCheck = true, onGrant, onDeny, onBlock, onSettingsReturn } = config;\n\n const checkPermission = useCallback(async () => {\n setFlowState((s) => transition(s, { type: \"CHECK\" }));\n try {\n let status: PermissionStatus;\n if (isNotifications(permission)) {\n const result = await checkNotifications();\n status = result.status;\n } else {\n status = await check(permission);\n }\n setNativeStatus(status);\n setFlowState((s) => {\n const next = transition(s, { type: \"CHECK_RESULT\", status });\n if (next === \"granted\" && s !== \"granted\") onGrant?.();\n return next;\n });\n } catch {\n setFlowState(\"idle\");\n }\n }, [permission, onGrant]);\n\n const requestPermission = useCallback(async () => {\n if (isRequesting.current) return;\n isRequesting.current = true;\n\n setFlowState((s) => transition(s, { type: \"PRE_PROMPT_CONFIRM\" }));\n try {\n let status: PermissionStatus;\n if (isNotifications(permission)) {\n const result = await requestNotifications([\"alert\", \"badge\", \"sound\"]);\n status = result.status;\n } else {\n status = await request(permission);\n }\n setNativeStatus(status);\n setFlowState((s) => {\n const next = transition(s, { type: \"REQUEST_RESULT\", status });\n if (next === \"granted\") onGrant?.();\n if (next === \"denied\") onDeny?.();\n if (next === \"blockedPrompt\") onBlock?.();\n return next;\n });\n } catch {\n setFlowState(\"denied\");\n } finally {\n isRequesting.current = false;\n }\n }, [permission, onGrant, onDeny, onBlock]);\n\n const dismiss = useCallback(() => {\n setFlowState((s) => transition(s, { type: \"PRE_PROMPT_DISMISS\" }));\n onDeny?.();\n }, [onDeny]);\n\n const goToSettings = useCallback(async () => {\n setFlowState((s) => transition(s, { type: \"OPEN_SETTINGS\" }));\n waitingForSettings.current = true;\n try {\n await openSettings();\n } catch {\n waitingForSettings.current = false;\n setFlowState(\"blockedPrompt\");\n }\n }, []);\n\n const recheckAfterSettings = useCallback(async () => {\n setFlowState((s) => transition(s, { type: \"SETTINGS_RETURN\" }));\n try {\n let status: PermissionStatus;\n if (isNotifications(permission)) {\n const result = await checkNotifications();\n status = result.status;\n } else {\n status = await check(permission);\n }\n setNativeStatus(status);\n setFlowState((s) => {\n const next = transition(s, { type: \"RECHECK_RESULT\", status });\n if (next === \"granted\") onGrant?.();\n onSettingsReturn?.(next === \"granted\");\n return next;\n });\n } catch {\n setFlowState(\"blockedPrompt\");\n }\n }, [permission, onGrant, onSettingsReturn]);\n\n // Auto-check on mount\n // biome-ignore lint/correctness/useExhaustiveDependencies: intentional mount-only effect\n useEffect(() => {\n if (autoCheck) {\n checkPermission();\n }\n }, []);\n\n // AppState listener for settings return\n useEffect(() => {\n const subscription = AppState.addEventListener(\"change\", (nextAppState) => {\n if (\n appStateRef.current.match(/inactive|background/) &&\n nextAppState === \"active\" &&\n waitingForSettings.current\n ) {\n waitingForSettings.current = false;\n recheckAfterSettings();\n }\n appStateRef.current = nextAppState;\n });\n return () => subscription.remove();\n }, [recheckAfterSettings]);\n\n return {\n state: flowState,\n nativeStatus,\n isGranted: flowState === \"granted\",\n isDenied: flowState === \"denied\",\n isBlocked:\n flowState === \"blocked\" || flowState === \"blockedPrompt\" || flowState === \"openingSettings\",\n isChecking: flowState === \"checking\" || flowState === \"recheckingAfterSettings\",\n isUnavailable: flowState === \"unavailable\",\n request: requestPermission,\n check: checkPermission,\n dismiss,\n openSettings: goToSettings,\n };\n}\n","import { useCallback, useRef, useState } from \"react\";\nimport {\n type PermissionStatus,\n check,\n checkNotifications,\n request,\n requestNotifications,\n} from \"react-native-permissions\";\nimport type {\n MultiPermissionEntry,\n MultiplePermissionsConfig,\n MultiplePermissionsResult,\n PermissionFlowState,\n} from \"../types\";\n\nfunction isNotifications(\n permission: MultiPermissionEntry[\"permission\"],\n): permission is \"notifications\" {\n return permission === \"notifications\";\n}\n\nasync function checkOne(entry: MultiPermissionEntry): Promise<PermissionStatus> {\n if (isNotifications(entry.permission)) {\n const result = await checkNotifications();\n return result.status;\n }\n return check(entry.permission);\n}\n\nasync function requestOne(entry: MultiPermissionEntry): Promise<PermissionStatus> {\n if (isNotifications(entry.permission)) {\n const result = await requestNotifications([\"alert\", \"badge\", \"sound\"]);\n return result.status;\n }\n return request(entry.permission);\n}\n\nfunction permissionKey(entry: MultiPermissionEntry): string {\n return String(entry.permission);\n}\n\nfunction isGrantedStatus(status: PermissionStatus): boolean {\n return status === \"granted\" || status === \"limited\";\n}\n\nexport function useMultiplePermissions(\n config: MultiplePermissionsConfig,\n): MultiplePermissionsResult {\n const { permissions, strategy, onAllGranted } = config;\n const [statuses, setStatuses] = useState<Record<string, PermissionFlowState>>(() => {\n const initial: Record<string, PermissionFlowState> = {};\n for (const entry of permissions) {\n initial[permissionKey(entry)] = \"idle\";\n }\n return initial;\n });\n const isRunning = useRef(false);\n\n const allGranted = permissions.every((entry) => statuses[permissionKey(entry)] === \"granted\");\n\n const requestAll = useCallback(async () => {\n if (isRunning.current) return;\n isRunning.current = true;\n\n const update = (key: string, state: PermissionFlowState) => {\n setStatuses((prev) => ({ ...prev, [key]: state }));\n };\n\n try {\n if (strategy === \"sequential\") {\n await runSequential(permissions, update);\n } else {\n await runParallel(permissions, update);\n }\n\n // Final check: are all granted?\n let allDone = true;\n for (const entry of permissions) {\n const finalStatus = await checkOne(entry);\n if (!isGrantedStatus(finalStatus)) {\n allDone = false;\n break;\n }\n }\n if (allDone) {\n onAllGranted?.();\n }\n } finally {\n isRunning.current = false;\n }\n }, [permissions, strategy, onAllGranted]);\n\n return {\n statuses,\n allGranted,\n request: requestAll,\n };\n}\n\nasync function runSequential(\n permissions: MultiPermissionEntry[],\n updateStatus: (key: string, state: PermissionFlowState) => void,\n): Promise<void> {\n for (const entry of permissions) {\n const key = permissionKey(entry);\n\n updateStatus(key, \"checking\");\n const checkStatus = await checkOne(entry);\n\n if (isGrantedStatus(checkStatus)) {\n updateStatus(key, \"granted\");\n entry.onGrant?.();\n continue;\n }\n\n if (checkStatus === \"unavailable\") {\n updateStatus(key, \"unavailable\");\n continue;\n }\n\n if (checkStatus === \"blocked\") {\n updateStatus(key, \"blockedPrompt\");\n entry.onBlock?.();\n break;\n }\n\n // Denied — request it\n updateStatus(key, \"requesting\");\n const requestStatus = await requestOne(entry);\n\n if (isGrantedStatus(requestStatus)) {\n updateStatus(key, \"granted\");\n entry.onGrant?.();\n } else if (requestStatus === \"blocked\") {\n updateStatus(key, \"blockedPrompt\");\n entry.onBlock?.();\n break;\n } else {\n updateStatus(key, \"denied\");\n entry.onDeny?.();\n break;\n }\n }\n}\n\nasync function runParallel(\n permissions: MultiPermissionEntry[],\n updateStatus: (key: string, state: PermissionFlowState) => void,\n): Promise<void> {\n // Check all in parallel\n const checkResults = await Promise.all(\n permissions.map(async (entry) => {\n const key = permissionKey(entry);\n updateStatus(key, \"checking\");\n const status = await checkOne(entry);\n return { entry, key, status };\n }),\n );\n\n // Update granted/unavailable immediately\n for (const { entry, key, status } of checkResults) {\n if (isGrantedStatus(status)) {\n updateStatus(key, \"granted\");\n entry.onGrant?.();\n } else if (status === \"unavailable\") {\n updateStatus(key, \"unavailable\");\n }\n }\n\n // Request denied/blocked ones sequentially (system dialogs are sequential)\n const needsAction = checkResults.filter(\n ({ status }) => status === \"denied\" || status === \"blocked\",\n );\n\n for (const { entry, key, status } of needsAction) {\n if (status === \"blocked\") {\n updateStatus(key, \"blockedPrompt\");\n entry.onBlock?.();\n continue;\n }\n\n updateStatus(key, \"requesting\");\n const requestStatus = await requestOne(entry);\n\n if (isGrantedStatus(requestStatus)) {\n updateStatus(key, \"granted\");\n entry.onGrant?.();\n } else if (requestStatus === \"blocked\") {\n updateStatus(key, \"blockedPrompt\");\n entry.onBlock?.();\n } else {\n updateStatus(key, \"denied\");\n entry.onDeny?.();\n }\n }\n}\n","import React from \"react\";\nimport { Modal, StyleSheet, Text, TouchableOpacity, View } from \"react-native\";\nimport type { BlockedPromptConfig } from \"../types\";\n\nexport interface DefaultBlockedPromptProps extends BlockedPromptConfig {\n visible: boolean;\n onOpenSettings: () => void;\n}\n\nexport function DefaultBlockedPrompt({\n visible,\n title,\n message,\n settingsLabel = \"Open Settings\",\n onOpenSettings,\n}: DefaultBlockedPromptProps) {\n return (\n <Modal visible={visible} transparent animationType=\"fade\">\n <View style={styles.overlay}>\n <View style={styles.modal}>\n <Text style={styles.title}>{title}</Text>\n <Text style={styles.message}>{message}</Text>\n <TouchableOpacity\n style={styles.settingsButton}\n onPress={onOpenSettings}\n accessibilityRole=\"button\"\n >\n <Text style={styles.settingsText}>{settingsLabel}</Text>\n </TouchableOpacity>\n </View>\n </View>\n </Modal>\n );\n}\n\nconst styles = StyleSheet.create({\n overlay: {\n flex: 1,\n backgroundColor: \"rgba(0,0,0,0.5)\",\n justifyContent: \"center\",\n alignItems: \"center\",\n },\n modal: {\n backgroundColor: \"white\",\n borderRadius: 16,\n padding: 24,\n width: \"85%\",\n alignItems: \"center\",\n },\n title: {\n fontSize: 20,\n fontWeight: \"600\",\n marginBottom: 12,\n textAlign: \"center\",\n },\n message: {\n fontSize: 15,\n color: \"#666\",\n textAlign: \"center\",\n marginBottom: 24,\n lineHeight: 22,\n },\n settingsButton: {\n backgroundColor: \"#007AFF\",\n borderRadius: 12,\n paddingVertical: 14,\n paddingHorizontal: 32,\n width: \"100%\",\n alignItems: \"center\",\n },\n settingsText: {\n color: \"white\",\n fontSize: 16,\n fontWeight: \"600\",\n },\n});\n","import React from \"react\";\nimport { Modal, StyleSheet, Text, TouchableOpacity, View } from \"react-native\";\nimport type { PrePromptConfig } from \"../types\";\n\nexport interface DefaultPrePromptProps extends PrePromptConfig {\n visible: boolean;\n onConfirm: () => void;\n onCancel: () => void;\n}\n\nexport function DefaultPrePrompt({\n visible,\n title,\n message,\n confirmLabel = \"Continue\",\n cancelLabel = \"Not Now\",\n onConfirm,\n onCancel,\n}: DefaultPrePromptProps) {\n return (\n <Modal visible={visible} transparent animationType=\"fade\">\n <View style={styles.overlay}>\n <View style={styles.modal}>\n <Text style={styles.title}>{title}</Text>\n <Text style={styles.message}>{message}</Text>\n <TouchableOpacity\n style={styles.confirmButton}\n onPress={onConfirm}\n accessibilityRole=\"button\"\n >\n <Text style={styles.confirmText}>{confirmLabel}</Text>\n </TouchableOpacity>\n <TouchableOpacity onPress={onCancel} accessibilityRole=\"button\">\n <Text style={styles.cancelText}>{cancelLabel}</Text>\n </TouchableOpacity>\n </View>\n </View>\n </Modal>\n );\n}\n\nconst styles = StyleSheet.create({\n overlay: {\n flex: 1,\n backgroundColor: \"rgba(0,0,0,0.5)\",\n justifyContent: \"center\",\n alignItems: \"center\",\n },\n modal: {\n backgroundColor: \"white\",\n borderRadius: 16,\n padding: 24,\n width: \"85%\",\n alignItems: \"center\",\n },\n title: {\n fontSize: 20,\n fontWeight: \"600\",\n marginBottom: 12,\n textAlign: \"center\",\n },\n message: {\n fontSize: 15,\n color: \"#666\",\n textAlign: \"center\",\n marginBottom: 24,\n lineHeight: 22,\n },\n confirmButton: {\n backgroundColor: \"#007AFF\",\n borderRadius: 12,\n paddingVertical: 14,\n paddingHorizontal: 32,\n width: \"100%\",\n alignItems: \"center\",\n marginBottom: 12,\n },\n confirmText: {\n color: \"white\",\n fontSize: 16,\n fontWeight: \"600\",\n },\n cancelText: {\n color: \"#007AFF\",\n fontSize: 15,\n },\n});\n","import React from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { Permission } from \"react-native-permissions\";\nimport { usePermissionHandler } from \"../hooks/use-permission-handler\";\nimport type { BlockedPromptConfig, PermissionCallbacks, PrePromptConfig } from \"../types\";\nimport { DefaultBlockedPrompt } from \"./default-blocked-prompt\";\nimport { DefaultPrePrompt } from \"./default-pre-prompt\";\n\nexport interface PermissionGateProps extends PermissionCallbacks {\n permission: Permission | \"notifications\";\n prePrompt: PrePromptConfig;\n blockedPrompt: BlockedPromptConfig;\n children: ReactNode;\n fallback?: ReactNode;\n renderPrePrompt?: (props: {\n config: PrePromptConfig;\n onConfirm: () => void;\n onCancel: () => void;\n }) => ReactNode;\n renderBlockedPrompt?: (props: {\n config: BlockedPromptConfig;\n onOpenSettings: () => void;\n }) => ReactNode;\n}\n\nexport function PermissionGate({\n permission,\n prePrompt,\n blockedPrompt,\n children,\n fallback = null,\n renderPrePrompt,\n renderBlockedPrompt,\n onGrant,\n onDeny,\n onBlock,\n onSettingsReturn,\n}: PermissionGateProps) {\n const handler = usePermissionHandler({\n permission,\n prePrompt,\n blockedPrompt,\n onGrant,\n onDeny,\n onBlock,\n onSettingsReturn,\n });\n\n if (handler.isGranted) {\n return <>{children}</>;\n }\n\n if (handler.isChecking || handler.isUnavailable) {\n return <>{fallback}</>;\n }\n\n if (handler.state === \"prePrompt\") {\n if (renderPrePrompt) {\n return (\n <>\n {renderPrePrompt({\n config: prePrompt,\n onConfirm: handler.request,\n onCancel: handler.dismiss,\n })}\n </>\n );\n }\n return (\n <DefaultPrePrompt\n visible\n title={prePrompt.title}\n message={prePrompt.message}\n confirmLabel={prePrompt.confirmLabel}\n cancelLabel={prePrompt.cancelLabel}\n onConfirm={handler.request}\n onCancel={handler.dismiss}\n />\n );\n }\n\n if (handler.state === \"blockedPrompt\") {\n if (renderBlockedPrompt) {\n return (\n <>\n {renderBlockedPrompt({\n config: blockedPrompt,\n onOpenSettings: handler.openSettings,\n })}\n </>\n );\n }\n return (\n <DefaultBlockedPrompt\n visible\n title={blockedPrompt.title}\n message={blockedPrompt.message}\n settingsLabel={blockedPrompt.settingsLabel}\n onOpenSettings={handler.openSettings}\n />\n );\n }\n\n return <>{fallback}</>;\n}\n"],"mappings":"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","names":["import_react","import_react_native_permissions","isNotifications","import_react_native","import_react_native","import_jsx_runtime","styles","import_jsx_runtime"]}