@milkinteractive/react-native-age-range 1.0.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,4 @@
1
+ #import <React/RCTBridgeModule.h>
2
+
3
+ @interface StoreAgeSignalsNativeModules : NSObject <RCTBridgeModule>
4
+ @end
@@ -0,0 +1,73 @@
1
+ #import "StoreAgeSignalsNativeModules.h"
2
+ #import <React/RCTBridgeModule.h>
3
+ #if __has_include("react_native_store_age_signals_native_modules-Swift.h")
4
+ #import "react_native_store_age_signals_native_modules-Swift.h"
5
+ #else
6
+ #import "StoreAgeSignalsNativeModules-Swift.h"
7
+ #endif
8
+
9
+ @interface StoreAgeSignalsNativeModules ()
10
+ @property(nonatomic, strong) StoreAgeSignalsNativeModulesSwift *swiftImpl;
11
+ @end
12
+
13
+ @implementation StoreAgeSignalsNativeModules
14
+
15
+ RCT_EXPORT_MODULE()
16
+
17
+ - (instancetype)init {
18
+ if (self = [super init]) {
19
+ // Assuming StoreAgeSignalsNativeModulesSwift is a Swift class that will be
20
+ // bridged You might need to import the Swift bridging header if not already
21
+ // done. e.g., #import "YOUR_PRODUCT_MODULE_NAME-Swift.h"
22
+ _swiftImpl = [[StoreAgeSignalsNativeModulesSwift alloc] init];
23
+ }
24
+ return self;
25
+ }
26
+
27
+ + (BOOL)requiresMainQueueSetup {
28
+ return YES; // UI Required
29
+ }
30
+
31
+ RCT_EXPORT_METHOD(getAndroidPlayAgeRangeStatus : (RCTPromiseResolveBlock)
32
+ resolve reject : (RCTPromiseRejectBlock)reject) {
33
+ NSDictionary *result = @{
34
+ @"installId" : [NSNull null],
35
+ @"userStatus" : [NSNull null],
36
+ @"error" : @"This method is only available on Android. Use "
37
+ @"requestIOSDeclaredAgeRange on iOS."
38
+ };
39
+ resolve(result);
40
+ }
41
+
42
+ RCT_EXPORT_METHOD(requestIOSDeclaredAgeRange : (
43
+ double)firstThresholdAge secondThresholdAge : (double)
44
+ secondThresholdAge thirdThresholdAge : (double)
45
+ thirdThresholdAge resolve : (RCTPromiseResolveBlock)
46
+ resolve reject : (RCTPromiseRejectBlock)reject) {
47
+ // Assuming _swiftImpl has a method named
48
+ // requestIOSDeclaredAgeRangeWithFirstThresholdAge that matches the signature.
49
+ [_swiftImpl
50
+ requestIOSDeclaredAgeRangeWithFirstThresholdAge:@(firstThresholdAge)
51
+ secondThresholdAge:@(secondThresholdAge)
52
+ thirdThresholdAge:@(thirdThresholdAge)
53
+ resolve:resolve
54
+ reject:reject];
55
+ }
56
+
57
+ RCT_EXPORT_METHOD(isEligibleForAgeFeatures : (RCTPromiseResolveBlock)
58
+ resolve reject : (RCTPromiseRejectBlock)reject) {
59
+ [_swiftImpl isEligibleForAgeFeaturesWithResolve:resolve reject:reject];
60
+ }
61
+
62
+ // Don't compile this code when we build for the old architecture.
63
+ // Don't compile this code when we build for the old architecture.
64
+ #ifdef RCT_NEW_ARCH_ENABLED
65
+ // Legacy module: TurboModule spec not generated/configured.
66
+ // - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
67
+ // (const facebook::react::ObjCTurboModule::InitParams &)params {
68
+ // return std::make_shared<
69
+ // facebook::react::NativeStoreAgeSignalsNativeModulesSpecJSI>(params);
70
+ // }
71
+ #endif
72
+
73
+ @end
@@ -0,0 +1,180 @@
1
+ import Foundation
2
+ import React
3
+ import StoreKit
4
+
5
+ #if canImport(DeclaredAgeRange)
6
+ import DeclaredAgeRange
7
+ #endif
8
+ import UIKit
9
+
10
+ // Check if DeclaredAgeRange type exists (iOS 18+) or handled via availability checks
11
+ // Removing generic canImport because it's part of StoreKit usually
12
+
13
+ @objc(StoreAgeSignalsNativeModulesSwift)
14
+ public class StoreAgeSignalsNativeModulesSwift: NSObject {
15
+
16
+ @objc(multiply:withB:withResolver:withRejecter:)
17
+ public func multiply(a: Float, b: Float, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
18
+ resolve(a*b)
19
+ }
20
+
21
+ @objc
22
+ public func requestIOSDeclaredAgeRange(
23
+ firstThresholdAge: NSNumber,
24
+ secondThresholdAge: NSNumber,
25
+ thirdThresholdAge: NSNumber,
26
+ resolve: @escaping RCTPromiseResolveBlock,
27
+ reject: @escaping RCTPromiseRejectBlock
28
+ ) {
29
+ // NOTE: Using patterns from reference implementation
30
+ #if compiler(>=6.0) && canImport(DeclaredAgeRange)
31
+ // The SDK strictly requires iOS 26.0+ for AgeRangeService
32
+ if #available(iOS 26.0, *) {
33
+ Task { @MainActor in
34
+ do {
35
+ guard let viewController = self.topViewController() else {
36
+ reject("VIEW_CONTROLLER_ERROR", "Could not find top view controller", nil)
37
+ return
38
+ }
39
+
40
+ let t1 = Int(truncating: firstThresholdAge)
41
+ let t2 = Int(truncating: secondThresholdAge)
42
+ let t3 = Int(truncating: thirdThresholdAge)
43
+
44
+ // Use AgeRangeService as per reference
45
+ let response = try await AgeRangeService.shared.requestAgeRange(
46
+ ageGates: t1, t2, t3,
47
+ in: viewController
48
+ )
49
+
50
+ var statusString = "declined"
51
+ var lowerBound: NSNumber? = nil
52
+ var upperBound: NSNumber? = nil
53
+ var ageRangeDeclaration: String? = nil
54
+ var parentalControls: [String: Bool] = [:]
55
+
56
+ switch response {
57
+ case .sharing(let declaration):
58
+ statusString = "sharing"
59
+
60
+ // Extract age range declaration type
61
+ if let declType = declaration.ageRangeDeclaration {
62
+ switch declType {
63
+ case .selfDeclared:
64
+ ageRangeDeclaration = "selfDeclared"
65
+ case .guardianDeclared:
66
+ ageRangeDeclaration = "guardianDeclared"
67
+ case .checkedByOtherMethod:
68
+ ageRangeDeclaration = "checkedByOtherMethod"
69
+ case .guardianCheckedByOtherMethod:
70
+ ageRangeDeclaration = "guardianCheckedByOtherMethod"
71
+ case .governmentIDChecked:
72
+ ageRangeDeclaration = "governmentIDChecked"
73
+ case .guardianGovernmentIDChecked:
74
+ ageRangeDeclaration = "guardianGovernmentIDChecked"
75
+ case .paymentChecked:
76
+ ageRangeDeclaration = "paymentChecked"
77
+ case .guardianPaymentChecked:
78
+ ageRangeDeclaration = "guardianPaymentChecked"
79
+ @unknown default:
80
+ ageRangeDeclaration = "unknown"
81
+ }
82
+ }
83
+
84
+ if let lower = declaration.lowerBound {
85
+ lowerBound = NSNumber(value: lower)
86
+ }
87
+ if let upper = declaration.upperBound {
88
+ upperBound = NSNumber(value: upper)
89
+ }
90
+
91
+ // Parse parental controls as structured object
92
+ let controls = declaration.activeParentalControls
93
+ parentalControls["communicationLimits"] = controls.contains(.communicationLimits)
94
+ parentalControls["significantAppChangeApprovalRequired"] = controls.contains(.significantAppChangeApprovalRequired)
95
+
96
+ case .declinedSharing:
97
+ statusString = "declined"
98
+ @unknown default:
99
+ statusString = "unknown"
100
+ }
101
+
102
+ let resultMap: [String: Any?] = [
103
+ "status": statusString,
104
+ "lowerBound": lowerBound,
105
+ "upperBound": upperBound,
106
+ "ageRangeDeclaration": ageRangeDeclaration,
107
+ "parentalControls": parentalControls.isEmpty ? nil : parentalControls,
108
+ "error": nil
109
+ ]
110
+ resolve(resultMap)
111
+
112
+ } catch let error as AgeRangeService.Error {
113
+ var errorMsg = error.localizedDescription
114
+ switch error {
115
+ case .notAvailable:
116
+ errorMsg += ". (Hint: Missing Entitlement OR Feature is unavailable on Simulator. Verify on real device.)"
117
+ case .invalidRequest:
118
+ errorMsg += ". (Hint: Invalid request, check requested ages.)"
119
+ @unknown default:
120
+ break
121
+ }
122
+ reject("ERR_IOS_AGE_REQUEST", errorMsg, error)
123
+ } catch {
124
+ reject("ERR_IOS_AGE_REQUEST", error.localizedDescription, error)
125
+ }
126
+ }
127
+ } else {
128
+ resolve(["status": nil, "error": "Requires iOS 26.0+"])
129
+ }
130
+ #else
131
+ resolve(["status": nil, "error": "SDK not available"])
132
+ #endif
133
+ }
134
+
135
+ @objc
136
+ public func isEligibleForAgeFeatures(
137
+ resolve: @escaping RCTPromiseResolveBlock,
138
+ reject: @escaping RCTPromiseRejectBlock
139
+ ) {
140
+ #if compiler(>=6.0) && canImport(DeclaredAgeRange)
141
+ // isEligibleForAgeFeatures requires iOS 26.2+
142
+ if #available(iOS 26.2, *) {
143
+ Task {
144
+ do {
145
+ let isEligible = try await AgeRangeService.shared.isEligibleForAgeFeatures
146
+ let resultMap: [String: Any?] = [
147
+ "isEligible": isEligible,
148
+ "error": nil
149
+ ]
150
+ resolve(resultMap)
151
+ } catch {
152
+ reject("ERR_IOS_AGE_ELIGIBLE", error.localizedDescription, error)
153
+ }
154
+ }
155
+ } else {
156
+ resolve(["isEligible": false, "error": "Requires iOS 26.2+"])
157
+ }
158
+ #else
159
+ resolve(["isEligible": false, "error": "SDK not available"])
160
+ #endif
161
+ }
162
+
163
+ // Helper to get top view controller
164
+ private func topViewController() -> UIViewController? {
165
+ guard let windowScene = UIApplication.shared.connectedScenes
166
+ .compactMap({ $0 as? UIWindowScene })
167
+ .first(where: { $0.activationState == .foregroundActive }),
168
+ let window = windowScene.windows.first(where: { $0.isKeyWindow }),
169
+ let rootViewController = window.rootViewController else {
170
+ return nil
171
+ }
172
+
173
+ var topController = rootViewController
174
+ while let presentedViewController = topController.presentedViewController {
175
+ topController = presentedViewController
176
+ }
177
+
178
+ return topController
179
+ }
180
+ }
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getAndroidPlayAgeRangeStatus = getAndroidPlayAgeRangeStatus;
7
+ exports.isAndroidEligibleForAgeFeatures = isAndroidEligibleForAgeFeatures;
8
+ exports.isIOSEligibleForAgeFeatures = isIOSEligibleForAgeFeatures;
9
+ exports.requestIOSDeclaredAgeRange = requestIOSDeclaredAgeRange;
10
+ var _reactNative = require("react-native");
11
+ const LINKING_ERROR = `The package '@milkinteractive/react-native-age-range' doesn't seem to be linked. Make sure: \n\n` + _reactNative.Platform.select({
12
+ ios: "- You have run 'pod install'\n",
13
+ default: ''
14
+ }) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n';
15
+ const StoreAgeSignalsNativeModules = _reactNative.NativeModules.StoreAgeSignalsNativeModules ? _reactNative.NativeModules.StoreAgeSignalsNativeModules : new Proxy({}, {
16
+ get() {
17
+ throw new Error(LINKING_ERROR);
18
+ }
19
+ });
20
+
21
+ // Android Types
22
+
23
+ /**
24
+ * User verification status from Google Play Age Signals API.
25
+ * - OVER_AGE: User is verified as an adult (18+)
26
+ * - UNDER_AGE: User has a supervised account (child/teen)
27
+ * - UNDER_AGE_APPROVAL_PENDING: Supervised user, parent hasn't approved pending significant changes
28
+ * - UNDER_AGE_APPROVAL_DENIED: Supervised user, parent denied approval for significant changes
29
+ * - UNKNOWN: Status could not be determined
30
+ */
31
+
32
+ // iOS Types
33
+
34
+ /**
35
+ * How the age range was declared/verified.
36
+ * - selfDeclared: User declared their own age
37
+ * - guardianDeclared: Guardian set the age (for children in iCloud family)
38
+ * - checkedByOtherMethod: Verified by another method
39
+ * - guardianCheckedByOtherMethod: Guardian verified by another method
40
+ * - governmentIDChecked: Verified via government ID
41
+ * - guardianGovernmentIDChecked: Guardian verified via government ID
42
+ * - paymentChecked: Verified via payment method (credit card)
43
+ * - guardianPaymentChecked: Guardian verified via payment method
44
+ */
45
+
46
+ /**
47
+ * Parental control settings active for the user.
48
+ */
49
+
50
+ // Eligibility Result
51
+
52
+ /**
53
+ * Retrieves the age range declaration status from Google Play's Age Signals API.
54
+ * @platform android
55
+ */
56
+ function getAndroidPlayAgeRangeStatus(config) {
57
+ if (_reactNative.Platform.OS !== 'android') {
58
+ return Promise.resolve({
59
+ installId: null,
60
+ userStatus: null,
61
+ error: 'This method is only available on Android'
62
+ });
63
+ }
64
+ return StoreAgeSignalsNativeModules.getAndroidPlayAgeRangeStatus(config || {});
65
+ }
66
+
67
+ /**
68
+ * Requests age range declaration from iOS Declared Age Range API.
69
+ * @platform ios
70
+ * @param firstThresholdAge First age threshold (e.g., 13)
71
+ * @param secondThresholdAge Second age threshold (e.g., 17)
72
+ * @param thirdThresholdAge Third age threshold (e.g., 21)
73
+ */
74
+ function requestIOSDeclaredAgeRange(firstThresholdAge, secondThresholdAge, thirdThresholdAge) {
75
+ if (_reactNative.Platform.OS !== 'ios') {
76
+ return Promise.resolve({
77
+ status: null,
78
+ lowerBound: null,
79
+ upperBound: null,
80
+ ageRangeDeclaration: null,
81
+ parentalControls: null,
82
+ error: 'This method is only available on iOS'
83
+ });
84
+ }
85
+ return StoreAgeSignalsNativeModules.requestIOSDeclaredAgeRange(firstThresholdAge, secondThresholdAge, thirdThresholdAge);
86
+ }
87
+
88
+ /**
89
+ * Checks if the current user is eligible for age verification features on iOS.
90
+ * This determines if age checks need to be applied (e.g., user is in an applicable region like Texas).
91
+ * @platform ios
92
+ * @returns Promise<DeclaredAgeEligibilityResult> - Object containing isEligible boolean and error string
93
+ * @remarks Requires iOS 26.0+. Returns isEligible: false with error message if not available.
94
+ */
95
+ function isIOSEligibleForAgeFeatures() {
96
+ if (_reactNative.Platform.OS !== 'ios') {
97
+ return Promise.resolve({
98
+ isEligible: false,
99
+ error: 'This method is only available on iOS'
100
+ });
101
+ }
102
+ return StoreAgeSignalsNativeModules.isEligibleForAgeFeatures();
103
+ }
104
+
105
+ /**
106
+ * Checks if the current user is eligible for age verification features on Android.
107
+ * This determines if age checks need to be applied (e.g., user is in an applicable region like Texas, Utah, Louisiana).
108
+ * @platform android
109
+ * @returns Promise<DeclaredAgeEligibilityResult> - Object containing isEligible boolean and error string
110
+ * @remarks Makes a lightweight API call to determine eligibility. Returns isEligible: false with error message if not available.
111
+ */
112
+ function isAndroidEligibleForAgeFeatures() {
113
+ if (_reactNative.Platform.OS !== 'android') {
114
+ return Promise.resolve({
115
+ isEligible: false,
116
+ error: 'This method is only available on Android'
117
+ });
118
+ }
119
+ return StoreAgeSignalsNativeModules.isEligibleForAgeFeatures();
120
+ }
121
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_reactNative","require","LINKING_ERROR","Platform","select","ios","default","StoreAgeSignalsNativeModules","NativeModules","Proxy","get","Error","getAndroidPlayAgeRangeStatus","config","OS","Promise","resolve","installId","userStatus","error","requestIOSDeclaredAgeRange","firstThresholdAge","secondThresholdAge","thirdThresholdAge","status","lowerBound","upperBound","ageRangeDeclaration","parentalControls","isIOSEligibleForAgeFeatures","isEligible","isEligibleForAgeFeatures","isAndroidEligibleForAgeFeatures"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAEA,MAAMC,aAAa,GACjB,kGAAkG,GAClGC,qBAAQ,CAACC,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;AAEjC,MAAMC,4BAA4B,GAAGC,0BAAa,CAACD,4BAA4B,GAC3EC,0BAAa,CAACD,4BAA4B,GAC1C,IAAIE,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACT,aAAa,CAAC;EAChC;AACF,CACF,CAAC;;AAEL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAkCA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAYA;AACA;AACA;;AA2BA;;AAsCA;AACA;AACA;AACA;AACO,SAASU,4BAA4BA,CAC1CC,MAA8B,EACK;EACnC,IAAIV,qBAAQ,CAACW,EAAE,KAAK,SAAS,EAAE;IAC7B,OAAOC,OAAO,CAACC,OAAO,CAAC;MACrBC,SAAS,EAAE,IAAI;MACfC,UAAU,EAAE,IAAI;MAChBC,KAAK,EAAE;IACT,CAAC,CAAC;EACJ;EACA,OAAOZ,4BAA4B,CAACK,4BAA4B,CAC9DC,MAAM,IAAI,CAAC,CACb,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASO,0BAA0BA,CACxCC,iBAAyB,EACzBC,kBAA0B,EAC1BC,iBAAyB,EACQ;EACjC,IAAIpB,qBAAQ,CAACW,EAAE,KAAK,KAAK,EAAE;IACzB,OAAOC,OAAO,CAACC,OAAO,CAAC;MACrBQ,MAAM,EAAE,IAAI;MACZC,UAAU,EAAE,IAAI;MAChBC,UAAU,EAAE,IAAI;MAChBC,mBAAmB,EAAE,IAAI;MACzBC,gBAAgB,EAAE,IAAI;MACtBT,KAAK,EAAE;IACT,CAAC,CAAC;EACJ;EACA,OAAOZ,4BAA4B,CAACa,0BAA0B,CAC5DC,iBAAiB,EACjBC,kBAAkB,EAClBC,iBACF,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASM,2BAA2BA,CAAA,EAA0C;EACnF,IAAI1B,qBAAQ,CAACW,EAAE,KAAK,KAAK,EAAE;IACzB,OAAOC,OAAO,CAACC,OAAO,CAAC;MACrBc,UAAU,EAAE,KAAK;MACjBX,KAAK,EAAE;IACT,CAAC,CAAC;EACJ;EACA,OAAOZ,4BAA4B,CAACwB,wBAAwB,CAAC,CAAC;AAChE;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASC,+BAA+BA,CAAA,EAA0C;EACvF,IAAI7B,qBAAQ,CAACW,EAAE,KAAK,SAAS,EAAE;IAC7B,OAAOC,OAAO,CAACC,OAAO,CAAC;MACrBc,UAAU,EAAE,KAAK;MACjBX,KAAK,EAAE;IACT,CAAC,CAAC;EACJ;EACA,OAAOZ,4BAA4B,CAACwB,wBAAwB,CAAC,CAAC;AAChE","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+
3
+ import { NativeModules, Platform } from 'react-native';
4
+ const LINKING_ERROR = `The package '@milkinteractive/react-native-age-range' doesn't seem to be linked. Make sure: \n\n` + Platform.select({
5
+ ios: "- You have run 'pod install'\n",
6
+ default: ''
7
+ }) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n';
8
+ const StoreAgeSignalsNativeModules = NativeModules.StoreAgeSignalsNativeModules ? NativeModules.StoreAgeSignalsNativeModules : new Proxy({}, {
9
+ get() {
10
+ throw new Error(LINKING_ERROR);
11
+ }
12
+ });
13
+
14
+ // Android Types
15
+
16
+ /**
17
+ * User verification status from Google Play Age Signals API.
18
+ * - OVER_AGE: User is verified as an adult (18+)
19
+ * - UNDER_AGE: User has a supervised account (child/teen)
20
+ * - UNDER_AGE_APPROVAL_PENDING: Supervised user, parent hasn't approved pending significant changes
21
+ * - UNDER_AGE_APPROVAL_DENIED: Supervised user, parent denied approval for significant changes
22
+ * - UNKNOWN: Status could not be determined
23
+ */
24
+
25
+ // iOS Types
26
+
27
+ /**
28
+ * How the age range was declared/verified.
29
+ * - selfDeclared: User declared their own age
30
+ * - guardianDeclared: Guardian set the age (for children in iCloud family)
31
+ * - checkedByOtherMethod: Verified by another method
32
+ * - guardianCheckedByOtherMethod: Guardian verified by another method
33
+ * - governmentIDChecked: Verified via government ID
34
+ * - guardianGovernmentIDChecked: Guardian verified via government ID
35
+ * - paymentChecked: Verified via payment method (credit card)
36
+ * - guardianPaymentChecked: Guardian verified via payment method
37
+ */
38
+
39
+ /**
40
+ * Parental control settings active for the user.
41
+ */
42
+
43
+ // Eligibility Result
44
+
45
+ /**
46
+ * Retrieves the age range declaration status from Google Play's Age Signals API.
47
+ * @platform android
48
+ */
49
+ export function getAndroidPlayAgeRangeStatus(config) {
50
+ if (Platform.OS !== 'android') {
51
+ return Promise.resolve({
52
+ installId: null,
53
+ userStatus: null,
54
+ error: 'This method is only available on Android'
55
+ });
56
+ }
57
+ return StoreAgeSignalsNativeModules.getAndroidPlayAgeRangeStatus(config || {});
58
+ }
59
+
60
+ /**
61
+ * Requests age range declaration from iOS Declared Age Range API.
62
+ * @platform ios
63
+ * @param firstThresholdAge First age threshold (e.g., 13)
64
+ * @param secondThresholdAge Second age threshold (e.g., 17)
65
+ * @param thirdThresholdAge Third age threshold (e.g., 21)
66
+ */
67
+ export function requestIOSDeclaredAgeRange(firstThresholdAge, secondThresholdAge, thirdThresholdAge) {
68
+ if (Platform.OS !== 'ios') {
69
+ return Promise.resolve({
70
+ status: null,
71
+ lowerBound: null,
72
+ upperBound: null,
73
+ ageRangeDeclaration: null,
74
+ parentalControls: null,
75
+ error: 'This method is only available on iOS'
76
+ });
77
+ }
78
+ return StoreAgeSignalsNativeModules.requestIOSDeclaredAgeRange(firstThresholdAge, secondThresholdAge, thirdThresholdAge);
79
+ }
80
+
81
+ /**
82
+ * Checks if the current user is eligible for age verification features on iOS.
83
+ * This determines if age checks need to be applied (e.g., user is in an applicable region like Texas).
84
+ * @platform ios
85
+ * @returns Promise<DeclaredAgeEligibilityResult> - Object containing isEligible boolean and error string
86
+ * @remarks Requires iOS 26.0+. Returns isEligible: false with error message if not available.
87
+ */
88
+ export function isIOSEligibleForAgeFeatures() {
89
+ if (Platform.OS !== 'ios') {
90
+ return Promise.resolve({
91
+ isEligible: false,
92
+ error: 'This method is only available on iOS'
93
+ });
94
+ }
95
+ return StoreAgeSignalsNativeModules.isEligibleForAgeFeatures();
96
+ }
97
+
98
+ /**
99
+ * Checks if the current user is eligible for age verification features on Android.
100
+ * This determines if age checks need to be applied (e.g., user is in an applicable region like Texas, Utah, Louisiana).
101
+ * @platform android
102
+ * @returns Promise<DeclaredAgeEligibilityResult> - Object containing isEligible boolean and error string
103
+ * @remarks Makes a lightweight API call to determine eligibility. Returns isEligible: false with error message if not available.
104
+ */
105
+ export function isAndroidEligibleForAgeFeatures() {
106
+ if (Platform.OS !== 'android') {
107
+ return Promise.resolve({
108
+ isEligible: false,
109
+ error: 'This method is only available on Android'
110
+ });
111
+ }
112
+ return StoreAgeSignalsNativeModules.isEligibleForAgeFeatures();
113
+ }
114
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["NativeModules","Platform","LINKING_ERROR","select","ios","default","StoreAgeSignalsNativeModules","Proxy","get","Error","getAndroidPlayAgeRangeStatus","config","OS","Promise","resolve","installId","userStatus","error","requestIOSDeclaredAgeRange","firstThresholdAge","secondThresholdAge","thirdThresholdAge","status","lowerBound","upperBound","ageRangeDeclaration","parentalControls","isIOSEligibleForAgeFeatures","isEligible","isEligibleForAgeFeatures","isAndroidEligibleForAgeFeatures"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AAEtD,MAAMC,aAAa,GACjB,kGAAkG,GAClGD,QAAQ,CAACE,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;AAEjC,MAAMC,4BAA4B,GAAGN,aAAa,CAACM,4BAA4B,GAC3EN,aAAa,CAACM,4BAA4B,GAC1C,IAAIC,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACP,aAAa,CAAC;EAChC;AACF,CACF,CAAC;;AAEL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAkCA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAYA;AACA;AACA;;AA2BA;;AAsCA;AACA;AACA;AACA;AACA,OAAO,SAASQ,4BAA4BA,CAC1CC,MAA8B,EACK;EACnC,IAAIV,QAAQ,CAACW,EAAE,KAAK,SAAS,EAAE;IAC7B,OAAOC,OAAO,CAACC,OAAO,CAAC;MACrBC,SAAS,EAAE,IAAI;MACfC,UAAU,EAAE,IAAI;MAChBC,KAAK,EAAE;IACT,CAAC,CAAC;EACJ;EACA,OAAOX,4BAA4B,CAACI,4BAA4B,CAC9DC,MAAM,IAAI,CAAC,CACb,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASO,0BAA0BA,CACxCC,iBAAyB,EACzBC,kBAA0B,EAC1BC,iBAAyB,EACQ;EACjC,IAAIpB,QAAQ,CAACW,EAAE,KAAK,KAAK,EAAE;IACzB,OAAOC,OAAO,CAACC,OAAO,CAAC;MACrBQ,MAAM,EAAE,IAAI;MACZC,UAAU,EAAE,IAAI;MAChBC,UAAU,EAAE,IAAI;MAChBC,mBAAmB,EAAE,IAAI;MACzBC,gBAAgB,EAAE,IAAI;MACtBT,KAAK,EAAE;IACT,CAAC,CAAC;EACJ;EACA,OAAOX,4BAA4B,CAACY,0BAA0B,CAC5DC,iBAAiB,EACjBC,kBAAkB,EAClBC,iBACF,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASM,2BAA2BA,CAAA,EAA0C;EACnF,IAAI1B,QAAQ,CAACW,EAAE,KAAK,KAAK,EAAE;IACzB,OAAOC,OAAO,CAACC,OAAO,CAAC;MACrBc,UAAU,EAAE,KAAK;MACjBX,KAAK,EAAE;IACT,CAAC,CAAC;EACJ;EACA,OAAOX,4BAA4B,CAACuB,wBAAwB,CAAC,CAAC;AAChE;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,+BAA+BA,CAAA,EAA0C;EACvF,IAAI7B,QAAQ,CAACW,EAAE,KAAK,SAAS,EAAE;IAC7B,OAAOC,OAAO,CAACC,OAAO,CAAC;MACrBc,UAAU,EAAE,KAAK;MACjBX,KAAK,EAAE;IACT,CAAC,CAAC;EACJ;EACA,OAAOX,4BAA4B,CAACuB,wBAAwB,CAAC,CAAC;AAChE","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * User verification status from Google Play Age Signals API.
3
+ * - OVER_AGE: User is verified as an adult (18+)
4
+ * - UNDER_AGE: User has a supervised account (child/teen)
5
+ * - UNDER_AGE_APPROVAL_PENDING: Supervised user, parent hasn't approved pending significant changes
6
+ * - UNDER_AGE_APPROVAL_DENIED: Supervised user, parent denied approval for significant changes
7
+ * - UNKNOWN: Status could not be determined
8
+ */
9
+ export type AndroidUserStatus = 'OVER_AGE' | 'UNDER_AGE' | 'UNDER_AGE_APPROVAL_PENDING' | 'UNDER_AGE_APPROVAL_DENIED' | 'UNKNOWN';
10
+ export interface PlayAgeRangeStatusResult {
11
+ installId: string | null;
12
+ userStatus: AndroidUserStatus | null;
13
+ error: string | null;
14
+ /**
15
+ * The (inclusive) lower bound of a supervised user's age range.
16
+ * 0 to 18.
17
+ */
18
+ ageLower?: number | null;
19
+ /**
20
+ * The (inclusive) upper bound of a supervised user's age range.
21
+ * 2 to 18.
22
+ */
23
+ ageUpper?: number | null;
24
+ /**
25
+ * The effective from date of the most recent significant change that was approved.
26
+ * ISO string format.
27
+ */
28
+ mostRecentApprovalDate?: string | null;
29
+ /**
30
+ * The numerical error code if the request failed.
31
+ * e.g., -1 (API_NOT_AVAILABLE), -2 (PLAY_STORE_NOT_FOUND), etc.
32
+ */
33
+ errorCode?: number | null;
34
+ }
35
+ /**
36
+ * How the age range was declared/verified.
37
+ * - selfDeclared: User declared their own age
38
+ * - guardianDeclared: Guardian set the age (for children in iCloud family)
39
+ * - checkedByOtherMethod: Verified by another method
40
+ * - guardianCheckedByOtherMethod: Guardian verified by another method
41
+ * - governmentIDChecked: Verified via government ID
42
+ * - guardianGovernmentIDChecked: Guardian verified via government ID
43
+ * - paymentChecked: Verified via payment method (credit card)
44
+ * - guardianPaymentChecked: Guardian verified via payment method
45
+ */
46
+ export type AgeRangeDeclarationType = 'selfDeclared' | 'guardianDeclared' | 'checkedByOtherMethod' | 'guardianCheckedByOtherMethod' | 'governmentIDChecked' | 'guardianGovernmentIDChecked' | 'paymentChecked' | 'guardianPaymentChecked' | 'unknown';
47
+ /**
48
+ * Parental control settings active for the user.
49
+ */
50
+ export interface ParentalControlsInfo {
51
+ /** Whether communication limits are enabled (e.g., contact restrictions) */
52
+ communicationLimits?: boolean;
53
+ /** Whether significant app changes require parental approval */
54
+ significantAppChangeApprovalRequired?: boolean;
55
+ }
56
+ export interface DeclaredAgeRangeResult {
57
+ status: 'sharing' | 'declined' | null;
58
+ lowerBound: number | null;
59
+ upperBound: number | null;
60
+ /**
61
+ * How the age range was declared/verified (iOS 26+).
62
+ * For children: always 'guardianDeclared'
63
+ * For teens in iCloud family: 'guardianDeclared'
64
+ * For teens not in family: 'selfDeclared'
65
+ * For adults: 'selfDeclared'
66
+ */
67
+ ageRangeDeclaration?: AgeRangeDeclarationType | null;
68
+ /**
69
+ * Parental control settings active for the user (if under age of majority).
70
+ */
71
+ parentalControls?: ParentalControlsInfo | null;
72
+ error: string | null;
73
+ }
74
+ export interface DeclaredAgeEligibilityResult {
75
+ isEligible: boolean;
76
+ error: string | null;
77
+ }
78
+ export interface AndroidAgeRangeConfig {
79
+ /**
80
+ * Enable mock mode to simulate results without calling Google Play API.
81
+ * Useful for development and testing.
82
+ */
83
+ isMock?: boolean;
84
+ /**
85
+ * The status to return when isMock is true.
86
+ * Default: 'OVER_AGE'
87
+ */
88
+ mockStatus?: AndroidUserStatus;
89
+ /**
90
+ * (Mock Only) Lower bound of the age range (e.g. 13).
91
+ * Relevant when mockStatus is 'UNDER_AGE' (Supervised).
92
+ */
93
+ mockAgeLower?: number;
94
+ /**
95
+ * (Mock Only) Upper bound of the age range (e.g. 17).
96
+ * Relevant when mockStatus is 'UNDER_AGE' (Supervised).
97
+ */
98
+ mockAgeUpper?: number;
99
+ /**
100
+ * (Mock Only) The numerical error code to throw.
101
+ * e.g., -1 for API_NOT_AVAILABLE.
102
+ */
103
+ mockErrorCode?: number;
104
+ /**
105
+ * (Mock Only) ISO date string for most recent approval.
106
+ */
107
+ mockMostRecentApprovalDate?: string;
108
+ }
109
+ /**
110
+ * Retrieves the age range declaration status from Google Play's Age Signals API.
111
+ * @platform android
112
+ */
113
+ export declare function getAndroidPlayAgeRangeStatus(config?: AndroidAgeRangeConfig): Promise<PlayAgeRangeStatusResult>;
114
+ /**
115
+ * Requests age range declaration from iOS Declared Age Range API.
116
+ * @platform ios
117
+ * @param firstThresholdAge First age threshold (e.g., 13)
118
+ * @param secondThresholdAge Second age threshold (e.g., 17)
119
+ * @param thirdThresholdAge Third age threshold (e.g., 21)
120
+ */
121
+ export declare function requestIOSDeclaredAgeRange(firstThresholdAge: number, secondThresholdAge: number, thirdThresholdAge: number): Promise<DeclaredAgeRangeResult>;
122
+ /**
123
+ * Checks if the current user is eligible for age verification features on iOS.
124
+ * This determines if age checks need to be applied (e.g., user is in an applicable region like Texas).
125
+ * @platform ios
126
+ * @returns Promise<DeclaredAgeEligibilityResult> - Object containing isEligible boolean and error string
127
+ * @remarks Requires iOS 26.0+. Returns isEligible: false with error message if not available.
128
+ */
129
+ export declare function isIOSEligibleForAgeFeatures(): Promise<DeclaredAgeEligibilityResult>;
130
+ /**
131
+ * Checks if the current user is eligible for age verification features on Android.
132
+ * This determines if age checks need to be applied (e.g., user is in an applicable region like Texas, Utah, Louisiana).
133
+ * @platform android
134
+ * @returns Promise<DeclaredAgeEligibilityResult> - Object containing isEligible boolean and error string
135
+ * @remarks Makes a lightweight API call to determine eligibility. Returns isEligible: false with error message if not available.
136
+ */
137
+ export declare function isAndroidEligibleForAgeFeatures(): Promise<DeclaredAgeEligibilityResult>;
138
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAqBA;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GACzB,UAAU,GACV,WAAW,GACX,4BAA4B,GAC5B,2BAA2B,GAC3B,SAAS,CAAC;AAEd,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACrC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAID;;;;;;;;;;GAUG;AACH,MAAM,MAAM,uBAAuB,GAC/B,cAAc,GACd,kBAAkB,GAClB,sBAAsB,GACtB,8BAA8B,GAC9B,qBAAqB,GACrB,6BAA6B,GAC7B,gBAAgB,GAChB,wBAAwB,GACxB,SAAS,CAAC;AAEd;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,4EAA4E;IAC5E,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,gEAAgE;IAChE,oCAAoC,CAAC,EAAE,OAAO,CAAC;CAChD;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,IAAI,CAAC;IACtC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAC;IACrD;;OAEG;IACH,gBAAgB,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC/C,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAGD,MAAM,WAAW,4BAA4B;IAC3C,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,CAAC,EAAE,qBAAqB,GAC7B,OAAO,CAAC,wBAAwB,CAAC,CAWnC;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,iBAAiB,EAAE,MAAM,EACzB,kBAAkB,EAAE,MAAM,EAC1B,iBAAiB,EAAE,MAAM,GACxB,OAAO,CAAC,sBAAsB,CAAC,CAgBjC;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,IAAI,OAAO,CAAC,4BAA4B,CAAC,CAQnF;AAED;;;;;;GAMG;AACH,wBAAgB,+BAA+B,IAAI,OAAO,CAAC,4BAA4B,CAAC,CAQvF"}