@umituz/react-native-subscription 2.37.110 → 2.37.112

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.
Files changed (32) hide show
  1. package/package.json +1 -1
  2. package/src/domains/credits/infrastructure/CreditsRepository.ts +3 -2
  3. package/src/domains/credits/infrastructure/operations/CreditsWriter.ts +2 -13
  4. package/src/domains/revenuecat/core/types/RevenueCatData.ts +3 -9
  5. package/src/domains/revenuecat/infrastructure/services/userSwitchHandler.ts +5 -1
  6. package/src/domains/subscription/application/SubscriptionInitializerTypes.ts +2 -10
  7. package/src/domains/subscription/application/SubscriptionSyncProcessor.ts +6 -6
  8. package/src/domains/subscription/core/SubscriptionEvents.ts +3 -6
  9. package/src/domains/subscription/core/SubscriptionStatus.ts +4 -4
  10. package/src/domains/subscription/core/types/CreditInfo.ts +10 -0
  11. package/src/domains/subscription/core/types/PremiumStatus.ts +21 -0
  12. package/src/domains/subscription/core/types/SubscriptionMetadata.ts +18 -0
  13. package/src/domains/subscription/core/types/index.ts +3 -0
  14. package/src/domains/subscription/infrastructure/handlers/PurchaseStatusResolver.ts +2 -15
  15. package/src/domains/subscription/infrastructure/managers/SubscriptionManager.types.ts +1 -1
  16. package/src/domains/subscription/infrastructure/utils/PremiumStatusSyncer.ts +5 -1
  17. package/src/domains/subscription/presentation/components/details/PremiumDetailsCardTypes.ts +3 -7
  18. package/src/domains/subscription/presentation/components/details/PremiumStatusBadge.tsx +4 -13
  19. package/src/domains/subscription/presentation/components/details/PremiumStatusBadge.types.ts +11 -0
  20. package/src/domains/subscription/presentation/components/feedback/PaywallFeedbackModal.tsx +3 -21
  21. package/src/domains/subscription/presentation/components/feedback/PaywallFeedbackModal.types.ts +20 -0
  22. package/src/domains/subscription/presentation/components/overlay/PurchaseLoadingOverlay.tsx +2 -4
  23. package/src/domains/subscription/presentation/components/overlay/PurchaseLoadingOverlay.types.ts +4 -0
  24. package/src/domains/subscription/presentation/components/sections/SubscriptionSection.tsx +3 -34
  25. package/src/domains/subscription/presentation/components/sections/SubscriptionSection.types.ts +22 -0
  26. package/src/domains/subscription/presentation/screens/SubscriptionDetailScreen.types.ts +3 -7
  27. package/src/domains/subscription/presentation/useSubscriptionStatus.types.ts +3 -14
  28. package/src/domains/wallet/presentation/components/BalanceCard.tsx +2 -10
  29. package/src/domains/wallet/presentation/components/BalanceCard.types.ts +10 -0
  30. package/src/domains/wallet/presentation/components/TransactionList.tsx +2 -15
  31. package/src/domains/wallet/presentation/components/TransactionList.types.ts +16 -0
  32. package/src/index.ts +3 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-subscription",
3
- "version": "2.37.110",
3
+ "version": "2.37.112",
4
4
  "description": "Complete subscription management with RevenueCat, paywall UI, and credits system for React Native apps",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -8,7 +8,8 @@ import { refundCreditsOperation } from "../application/RefundCreditsCommand";
8
8
  import { PURCHASE_TYPE, type PurchaseType } from "../../subscription/core/SubscriptionConstants";
9
9
  import { requireFirestore, buildDocRef, type CollectionConfig } from "../../../shared/infrastructure/firestore";
10
10
  import { fetchCredits, checkHasCredits, documentExists } from "./operations/CreditsFetcher";
11
- import { syncExpiredStatus, syncPremiumMetadata, createRecoveryCreditsDocument, type PremiumMetadata } from "./operations/CreditsWriter";
11
+ import { syncExpiredStatus, syncPremiumMetadata, createRecoveryCreditsDocument } from "./operations/CreditsWriter";
12
+ import type { SubscriptionMetadata } from "../../subscription/core/types";
12
13
  import { initializeCreditsWithRetry } from "./operations/CreditsInitializer";
13
14
  import { calculateCreditLimit } from "../application/CreditLimitCalculator";
14
15
 
@@ -81,7 +82,7 @@ export class CreditsRepository extends BaseRepository {
81
82
  await syncExpiredStatus(this.getRef(db, userId));
82
83
  }
83
84
 
84
- async syncPremiumMetadata(userId: string, metadata: PremiumMetadata): Promise<void> {
85
+ async syncPremiumMetadata(userId: string, metadata: SubscriptionMetadata): Promise<void> {
85
86
  const db = requireFirestore();
86
87
  await syncPremiumMetadata(this.getRef(db, userId), metadata);
87
88
  }
@@ -3,6 +3,7 @@ import { runTransaction, serverTimestamp } from "@umituz/react-native-firebase";
3
3
  import { doc, getDoc, setDoc } from "firebase/firestore";
4
4
  import { SUBSCRIPTION_STATUS } from "../../../subscription/core/SubscriptionConstants";
5
5
  import { resolveSubscriptionStatus } from "../../../subscription/core/SubscriptionStatus";
6
+ import type { SubscriptionMetadata } from "../../../subscription/core/types";
6
7
  import { toTimestamp } from "../../../../shared/utils/dateConverter";
7
8
  import { isPast } from "../../../../utils/dateUtils";
8
9
  import { getAppVersion, validatePlatform } from "../../../../utils/appUtils";
@@ -25,22 +26,10 @@ export async function syncExpiredStatus(ref: DocumentReference): Promise<void> {
25
26
  });
26
27
  }
27
28
 
28
- export interface PremiumMetadata {
29
- isPremium: boolean;
30
- willRenew: boolean;
31
- expirationDate: string | null;
32
- productId: string;
33
- periodType: string | null;
34
- unsubscribeDetectedAt: string | null;
35
- billingIssueDetectedAt: string | null;
36
- store: string | null;
37
- ownershipType: string | null;
38
- }
39
-
40
29
  // Fix: was getDoc+setDoc (non-atomic) — now uses runTransaction.
41
30
  export async function syncPremiumMetadata(
42
31
  ref: DocumentReference,
43
- metadata: PremiumMetadata
32
+ metadata: SubscriptionMetadata
44
33
  ): Promise<void> {
45
34
  await runTransaction(async (tx: Transaction) => {
46
35
  const doc = await tx.get(ref);
@@ -1,15 +1,9 @@
1
- import type { Store, OwnershipType, PackageType } from "./RevenueCatTypes";
1
+ import type { SubscriptionMetadata } from "../../../subscription/core/types";
2
+ import type { PackageType } from "./RevenueCatTypes";
2
3
 
3
- export interface RevenueCatData {
4
- expirationDate: string | null;
4
+ export interface RevenueCatData extends Omit<SubscriptionMetadata, 'willRenew' | 'productId'> {
5
5
  willRenew: boolean | null;
6
6
  storeTransactionId: string | null;
7
- isPremium: boolean;
8
- periodType: string | null;
9
7
  packageType: PackageType | null;
10
- unsubscribeDetectedAt: string | null;
11
- billingIssueDetectedAt: string | null;
12
- store: Store | null;
13
- ownershipType: OwnershipType | null;
14
8
  revenueCatUserId?: string | null;
15
9
  }
@@ -193,10 +193,14 @@ export async function handleInitialConfiguration(
193
193
  userId: normalizedUserId,
194
194
  isPremium: true,
195
195
  productId: premiumEntitlement.productIdentifier,
196
- expiresAt: premiumEntitlement.expirationDate ?? undefined,
196
+ expirationDate: premiumEntitlement.expirationDate ?? null,
197
197
  willRenew: premiumEntitlement.willRenew,
198
198
  periodType: premiumEntitlement.periodType as PeriodType | undefined,
199
199
  storeTransactionId: subscription?.storeTransactionId ?? undefined,
200
+ unsubscribeDetectedAt: premiumEntitlement.unsubscribeDetectedAt ?? null,
201
+ billingIssueDetectedAt: premiumEntitlement.billingIssueDetectedAt ?? null,
202
+ store: premiumEntitlement.store ?? null,
203
+ ownershipType: premiumEntitlement.ownershipType ?? null,
200
204
  });
201
205
  } else {
202
206
  await deps.config.onPremiumStatusChanged({
@@ -1,7 +1,7 @@
1
1
  import type { CreditsConfig } from "../../credits/core/Credits";
2
2
  import type { UserCreditsDocumentRead } from "../../credits/core/UserCreditsDocument";
3
3
  import type { PurchaseSource, PurchaseType } from "../core/SubscriptionConstants";
4
- import type { Store, OwnershipType } from "../../revenuecat/core/types";
4
+ import type { SubscriptionMetadata } from "../core/types";
5
5
 
6
6
  export interface FirebaseAuthLike {
7
7
  currentUser: { uid: string; isAnonymous: boolean } | null;
@@ -28,19 +28,11 @@ export interface SubscriptionInitConfig {
28
28
  authStateTimeoutMs?: number;
29
29
  }
30
30
 
31
- export interface InitializeCreditsMetadata {
32
- productId: string;
31
+ export interface InitializeCreditsMetadata extends Omit<SubscriptionMetadata, 'willRenew'> {
33
32
  source: PurchaseSource;
34
33
  type: PurchaseType;
35
- expirationDate: string | null;
36
34
  willRenew: boolean | null;
37
35
  storeTransactionId: string | null;
38
- isPremium: boolean;
39
- periodType: string | null;
40
- unsubscribeDetectedAt: string | null;
41
- billingIssueDetectedAt: string | null;
42
- store: Store | null;
43
- ownershipType: OwnershipType | null;
44
36
  revenueCatUserId?: string | null;
45
37
  }
46
38
 
@@ -220,7 +220,7 @@ export class SubscriptionSyncProcessor {
220
220
  userId,
221
221
  event.productId!,
222
222
  event.willRenew ?? false,
223
- event.expiresAt ?? null,
223
+ event.expirationDate ?? null,
224
224
  event.periodType ?? null,
225
225
  event.storeTransactionId,
226
226
  );
@@ -235,13 +235,13 @@ export class SubscriptionSyncProcessor {
235
235
  await repo.syncPremiumMetadata(userId, {
236
236
  isPremium: event.isPremium,
237
237
  willRenew: event.willRenew ?? false,
238
- expirationDate: event.expiresAt ?? null,
238
+ expirationDate: event.expirationDate ?? null,
239
239
  productId: event.productId!,
240
240
  periodType: event.periodType ?? null,
241
- unsubscribeDetectedAt: null,
242
- billingIssueDetectedAt: null,
243
- store: null,
244
- ownershipType: null,
241
+ unsubscribeDetectedAt: event.unsubscribeDetectedAt ?? null,
242
+ billingIssueDetectedAt: event.billingIssueDetectedAt ?? null,
243
+ store: event.store ?? null,
244
+ ownershipType: event.ownershipType ?? null,
245
245
  });
246
246
  this.emitCreditsUpdated(userId);
247
247
  }
@@ -1,5 +1,6 @@
1
1
  import type { CustomerInfo } from "react-native-purchases";
2
- import type { PeriodType, PurchaseSource } from "./SubscriptionConstants";
2
+ import type { PurchaseSource } from "./SubscriptionConstants";
3
+ import type { SubscriptionMetadata } from "./types";
3
4
  import type { PackageType } from "../../revenuecat/core/types/RevenueCatTypes";
4
5
 
5
6
  export interface PurchaseCompletedEvent {
@@ -17,13 +18,9 @@ export interface RenewalDetectedEvent {
17
18
  customerInfo: CustomerInfo;
18
19
  }
19
20
 
20
- export interface PremiumStatusChangedEvent {
21
+ export interface PremiumStatusChangedEvent extends Partial<SubscriptionMetadata> {
21
22
  userId: string;
22
23
  isPremium: boolean;
23
- productId?: string;
24
- expiresAt?: string;
25
- willRenew?: boolean;
26
- periodType?: PeriodType;
27
24
  storeTransactionId?: string;
28
25
  }
29
26
 
@@ -12,7 +12,7 @@ export type { SubscriptionStatusType };
12
12
 
13
13
  export interface SubscriptionStatus {
14
14
  isPremium: boolean;
15
- expiresAt: string | null;
15
+ expirationDate: string | null;
16
16
  productId: string | null;
17
17
  purchasedAt?: string | null;
18
18
  customerId?: string | null;
@@ -23,7 +23,7 @@ export interface SubscriptionStatus {
23
23
 
24
24
  export const createDefaultSubscriptionStatus = (): SubscriptionStatus => ({
25
25
  isPremium: false,
26
- expiresAt: null,
26
+ expirationDate: null,
27
27
  productId: null,
28
28
  purchasedAt: null,
29
29
  customerId: null,
@@ -33,8 +33,8 @@ export const createDefaultSubscriptionStatus = (): SubscriptionStatus => ({
33
33
 
34
34
  export const isSubscriptionValid = (status: SubscriptionStatus | null): boolean => {
35
35
  if (!status || !status.isPremium) return false;
36
- if (!status.expiresAt) return true;
37
- return timezoneService.isFuture(new Date(status.expiresAt));
36
+ if (!status.expirationDate) return true;
37
+ return timezoneService.isFuture(new Date(status.expirationDate));
38
38
  };
39
39
 
40
40
  export interface StatusResolverInput {
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Credit usage information for display in subscription UI components.
3
+ * Single source of truth — used by SubscriptionDetailScreen and PremiumDetailsCard.
4
+ */
5
+ export interface CreditInfo {
6
+ id: string;
7
+ label: string;
8
+ current: number;
9
+ total: number;
10
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Resolved premium status from RevenueCat CustomerInfo.
3
+ * Uses Date objects (presentation-ready).
4
+ *
5
+ * Extended by SubscriptionStatusResult which adds hook state (isLoading, error, refetch).
6
+ */
7
+ export interface PremiumStatus {
8
+ isPremium: boolean;
9
+ expirationDate: Date | null;
10
+ willRenew: boolean;
11
+ productIdentifier: string | null;
12
+ originalPurchaseDate: Date | null;
13
+ latestPurchaseDate: Date | null;
14
+ billingIssuesDetected: boolean;
15
+ isSandbox: boolean;
16
+ periodType: string | null;
17
+ packageType: string | null;
18
+ store: string | null;
19
+ gracePeriodExpiresDate: Date | null;
20
+ unsubscribeDetectedAt: Date | null;
21
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Base subscription metadata — the single source of truth for subscription state fields.
3
+ *
4
+ * All subscription-related types (RevenueCatData, PremiumStatusChangedEvent,
5
+ * InitializeCreditsMetadata) extend or compose from this base to eliminate
6
+ * field duplication and ensure consistent naming.
7
+ */
8
+ export interface SubscriptionMetadata {
9
+ isPremium: boolean;
10
+ willRenew: boolean;
11
+ expirationDate: string | null;
12
+ productId: string;
13
+ periodType: string | null;
14
+ unsubscribeDetectedAt: string | null;
15
+ billingIssueDetectedAt: string | null;
16
+ store: string | null;
17
+ ownershipType: string | null;
18
+ }
@@ -0,0 +1,3 @@
1
+ export type { SubscriptionMetadata } from "./SubscriptionMetadata";
2
+ export type { PremiumStatus } from "./PremiumStatus";
3
+ export type { CreditInfo } from "./CreditInfo";
@@ -2,22 +2,9 @@ import type { CustomerInfo } from "react-native-purchases";
2
2
  import { getPremiumEntitlement } from "../../../revenuecat/core/types";
3
3
  import { toDate } from "../../../../shared/utils/dateConverter";
4
4
  import { detectPackageType } from "../../../../utils/packageTypeDetector";
5
+ import type { PremiumStatus } from "../../core/types";
5
6
 
6
- export interface PremiumStatus {
7
- isPremium: boolean;
8
- expirationDate: Date | null;
9
- willRenew: boolean;
10
- productIdentifier: string | null;
11
- originalPurchaseDate: Date | null;
12
- latestPurchaseDate: Date | null;
13
- billingIssuesDetected: boolean;
14
- isSandbox: boolean;
15
- periodType: string | null;
16
- packageType: string | null;
17
- store: string | null;
18
- gracePeriodExpiresDate: Date | null;
19
- unsubscribeDetectedAt: Date | null;
20
- }
7
+ export type { PremiumStatus };
21
8
 
22
9
  export class PurchaseStatusResolver {
23
10
  static resolve(customerInfo: CustomerInfo, entitlementId: string): PremiumStatus {
@@ -1,5 +1,5 @@
1
1
  import type { RevenueCatConfig } from "../../../revenuecat/core/types";
2
- import type { PremiumStatus } from "../handlers/PurchaseStatusResolver";
2
+ import type { PremiumStatus } from "../../core/types";
3
3
  import type { RestoreResultInfo } from "../handlers/package-operations/types";
4
4
 
5
5
  export interface SubscriptionManagerConfig {
@@ -36,10 +36,14 @@ export async function syncPremiumStatus(
36
36
  userId,
37
37
  isPremium: true,
38
38
  productId: premiumEntitlement.productIdentifier,
39
- expiresAt: premiumEntitlement.expirationDate ?? undefined,
39
+ expirationDate: premiumEntitlement.expirationDate ?? null,
40
40
  willRenew: premiumEntitlement.willRenew,
41
41
  periodType: premiumEntitlement.periodType as PeriodType | undefined,
42
42
  storeTransactionId: subscription?.storeTransactionId ?? undefined,
43
+ unsubscribeDetectedAt: premiumEntitlement.unsubscribeDetectedAt ?? null,
44
+ billingIssueDetectedAt: premiumEntitlement.billingIssueDetectedAt ?? null,
45
+ store: premiumEntitlement.store ?? null,
46
+ ownershipType: premiumEntitlement.ownershipType ?? null,
43
47
  });
44
48
  } else {
45
49
  await config.onPremiumStatusChanged({ userId, isPremium: false });
@@ -1,11 +1,7 @@
1
- import type { SubscriptionStatusType } from "./PremiumStatusBadge";
1
+ import type { SubscriptionStatusType } from "./PremiumStatusBadge.types";
2
+ import type { CreditInfo } from "../../../core/types";
2
3
 
3
- export interface CreditInfo {
4
- id: string;
5
- label: string;
6
- current: number;
7
- total: number;
8
- }
4
+ export type { CreditInfo };
9
5
 
10
6
  export interface PremiumDetailsTranslations {
11
7
  title: string;
@@ -7,20 +7,11 @@ import React, { useMemo } from "react";
7
7
  import { View, StyleSheet } from "react-native";
8
8
  import { AtomicText } from "@umituz/react-native-design-system/atoms";
9
9
  import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
10
- import {
11
- SUBSCRIPTION_STATUS,
12
- type SubscriptionStatusType
13
- } from "../../../core/SubscriptionConstants";
10
+ import { SUBSCRIPTION_STATUS } from "../../../core/SubscriptionConstants";
11
+ import type { PremiumStatusBadgeProps } from "./PremiumStatusBadge.types";
12
+ import type { SubscriptionStatusType } from "../../../core/SubscriptionConstants";
14
13
 
15
- export type { SubscriptionStatusType };
16
-
17
- export interface PremiumStatusBadgeProps {
18
- status: SubscriptionStatusType;
19
- activeLabel: string;
20
- expiredLabel: string;
21
- noneLabel: string;
22
- canceledLabel: string;
23
- }
14
+ export type { PremiumStatusBadgeProps };
24
15
 
25
16
  export const PremiumStatusBadge: React.FC<PremiumStatusBadgeProps> = ({
26
17
  status,
@@ -0,0 +1,11 @@
1
+ import type { SubscriptionStatusType } from "../../../../core/SubscriptionConstants";
2
+
3
+ export type { SubscriptionStatusType };
4
+
5
+ export interface PremiumStatusBadgeProps {
6
+ status: SubscriptionStatusType;
7
+ activeLabel: string;
8
+ expiredLabel: string;
9
+ noneLabel: string;
10
+ canceledLabel: string;
11
+ }
@@ -6,6 +6,9 @@ import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
6
6
  import { usePaywallFeedback } from "../../../../../presentation/hooks/feedback/usePaywallFeedback";
7
7
  import { createPaywallFeedbackStyles } from "./paywallFeedbackStyles";
8
8
  import { FeedbackOption } from "./FeedbackOption";
9
+ import type { PaywallFeedbackTranslations, PaywallFeedbackModalProps } from "./PaywallFeedbackModal.types";
10
+
11
+ export type { PaywallFeedbackTranslations, PaywallFeedbackModalProps };
9
12
 
10
13
  const FEEDBACK_OPTION_IDS = [
11
14
  "too_expensive",
@@ -15,27 +18,6 @@ const FEEDBACK_OPTION_IDS = [
15
18
  "other",
16
19
  ] as const;
17
20
 
18
- export interface PaywallFeedbackTranslations {
19
- title: string;
20
- subtitle: string;
21
- submit: string;
22
- otherPlaceholder: string;
23
- reasons: {
24
- too_expensive: string;
25
- no_need: string;
26
- trying_out: string;
27
- technical_issues: string;
28
- other: string;
29
- };
30
- }
31
-
32
- export interface PaywallFeedbackModalProps {
33
- translations: PaywallFeedbackTranslations;
34
- visible: boolean;
35
- onClose: () => void;
36
- onSubmit: (reason: string) => void;
37
- }
38
-
39
21
  export const PaywallFeedbackModal: React.FC<PaywallFeedbackModalProps> = React.memo(({
40
22
  translations,
41
23
  visible,
@@ -0,0 +1,20 @@
1
+ export interface PaywallFeedbackTranslations {
2
+ title: string;
3
+ subtitle: string;
4
+ submit: string;
5
+ otherPlaceholder: string;
6
+ reasons: {
7
+ too_expensive: string;
8
+ no_need: string;
9
+ trying_out: string;
10
+ technical_issues: string;
11
+ other: string;
12
+ };
13
+ }
14
+
15
+ export interface PaywallFeedbackModalProps {
16
+ translations: PaywallFeedbackTranslations;
17
+ visible: boolean;
18
+ onClose: () => void;
19
+ onSubmit: (reason: string) => void;
20
+ }
@@ -9,11 +9,9 @@ import { View, Modal, StyleSheet } from "react-native";
9
9
  import { AtomicSpinner, AtomicText } from "@umituz/react-native-design-system/atoms";
10
10
  import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
11
11
  import { usePurchaseLoadingStore, selectIsPurchasing } from "../../stores/purchaseLoadingStore";
12
+ import type { PurchaseLoadingOverlayProps } from "./PurchaseLoadingOverlay.types";
12
13
 
13
- export interface PurchaseLoadingOverlayProps {
14
- /** Loading message to display */
15
- loadingText?: string;
16
- }
14
+ export type { PurchaseLoadingOverlayProps };
17
15
 
18
16
  export const PurchaseLoadingOverlay: React.FC<PurchaseLoadingOverlayProps> = React.memo(
19
17
  ({ loadingText }) => {
@@ -0,0 +1,4 @@
1
+ export interface PurchaseLoadingOverlayProps {
2
+ /** Loading message to display */
3
+ loadingText?: string;
4
+ }
@@ -6,41 +6,10 @@
6
6
 
7
7
  import React from "react";
8
8
  import { View, TouchableOpacity } from "react-native";
9
- import type { StyleProp, ViewStyle } from "react-native";
10
- import {
11
- PremiumDetailsCard,
12
- type CreditInfo,
13
- type PremiumDetailsTranslations,
14
- } from "../details/PremiumDetailsCard";
15
- import type { SubscriptionStatusType } from "../details/PremiumStatusBadge";
9
+ import { PremiumDetailsCard } from "../details/PremiumDetailsCard";
10
+ import type { SubscriptionSectionConfig, SubscriptionSectionProps } from "./SubscriptionSection.types";
16
11
 
17
- export interface SubscriptionSectionConfig {
18
- /** Subscription status type */
19
- statusType: SubscriptionStatusType;
20
- /** Whether user has premium */
21
- isPremium: boolean;
22
- /** Formatted expiration date string */
23
- expirationDate?: string | null;
24
- /** Formatted purchase date string */
25
- purchaseDate?: string | null;
26
- /** Days remaining until expiration */
27
- daysRemaining?: number | null;
28
- /** Credit info array (app-specific, passed from app) */
29
- credits?: CreditInfo[];
30
- /** All translations (app must provide these) */
31
- translations: PremiumDetailsTranslations;
32
- /** Handler for manage subscription button */
33
- onManageSubscription?: () => void;
34
- /** Handler for upgrade button */
35
- onUpgrade?: () => void;
36
- /** Handler for when section is tapped (navigate to detail screen) */
37
- onPress?: () => void;
38
- }
39
-
40
- export interface SubscriptionSectionProps {
41
- config: SubscriptionSectionConfig;
42
- containerStyle?: StyleProp<ViewStyle>;
43
- }
12
+ export type { SubscriptionSectionConfig, SubscriptionSectionProps };
44
13
 
45
14
  export const SubscriptionSection: React.FC<SubscriptionSectionProps> = ({
46
15
  config,
@@ -0,0 +1,22 @@
1
+ import type { StyleProp, ViewStyle } from "react-native";
2
+ import type { SubscriptionStatusType } from "../../../../core/SubscriptionConstants";
3
+ import type { CreditInfo } from "../../../../core/types";
4
+ import type { PremiumDetailsTranslations } from "../details/PremiumDetailsCardTypes";
5
+
6
+ export interface SubscriptionSectionConfig {
7
+ statusType: SubscriptionStatusType;
8
+ isPremium: boolean;
9
+ expirationDate?: string | null;
10
+ purchaseDate?: string | null;
11
+ daysRemaining?: number | null;
12
+ credits?: CreditInfo[];
13
+ translations: PremiumDetailsTranslations;
14
+ onManageSubscription?: () => void;
15
+ onUpgrade?: () => void;
16
+ onPress?: () => void;
17
+ }
18
+
19
+ export interface SubscriptionSectionProps {
20
+ config: SubscriptionSectionConfig;
21
+ containerStyle?: StyleProp<ViewStyle>;
22
+ }
@@ -1,4 +1,7 @@
1
1
  import type { SubscriptionStatusType } from "../../core/SubscriptionConstants";
2
+ import type { CreditInfo } from "../../core/types";
3
+
4
+ export type { CreditInfo };
2
5
 
3
6
  export interface SubscriptionDisplayFlags {
4
7
  showHeader: boolean;
@@ -40,13 +43,6 @@ export interface UpgradePromptConfig {
40
43
  onUpgrade?: () => void;
41
44
  }
42
45
 
43
- export interface CreditInfo {
44
- id: string;
45
- label: string;
46
- current: number;
47
- total: number;
48
- }
49
-
50
46
  export interface SubscriptionDetailConfig {
51
47
  display: SubscriptionDisplayFlags;
52
48
  statusType: SubscriptionStatusType;
@@ -1,17 +1,6 @@
1
- export interface SubscriptionStatusResult {
2
- isPremium: boolean;
3
- expirationDate: Date | null;
4
- willRenew: boolean;
5
- productIdentifier: string | null;
6
- originalPurchaseDate: Date | null;
7
- latestPurchaseDate: Date | null;
8
- billingIssuesDetected: boolean;
9
- isSandbox: boolean;
10
- periodType: string | null;
11
- packageType: string | null;
12
- store: string | null;
13
- gracePeriodExpiresDate: Date | null;
14
- unsubscribeDetectedAt: Date | null;
1
+ import type { PremiumStatus } from "../core/types";
2
+
3
+ export interface SubscriptionStatusResult extends PremiumStatus {
15
4
  isLoading: boolean;
16
5
  error: Error | null;
17
6
  refetch: () => void;
@@ -10,17 +10,9 @@ import { View, StyleSheet } from "react-native";
10
10
 
11
11
  import { AtomicText, AtomicIcon } from "@umituz/react-native-design-system/atoms";
12
12
  import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
13
+ import type { BalanceCardTranslations, BalanceCardProps } from "./BalanceCard.types";
13
14
 
14
- export interface BalanceCardTranslations {
15
- balanceLabel: string;
16
- availableCredits: string;
17
- }
18
-
19
- interface BalanceCardProps {
20
- balance: number;
21
- translations: BalanceCardTranslations;
22
- iconName?: string;
23
- }
15
+ export type { BalanceCardTranslations };
24
16
 
25
17
  export const BalanceCard: React.FC<BalanceCardProps> = ({
26
18
  balance,
@@ -0,0 +1,10 @@
1
+ export interface BalanceCardTranslations {
2
+ balanceLabel: string;
3
+ availableCredits: string;
4
+ }
5
+
6
+ export interface BalanceCardProps {
7
+ balance: number;
8
+ translations: BalanceCardTranslations;
9
+ iconName?: string;
10
+ }
@@ -2,26 +2,13 @@ import React from "react";
2
2
  import { View, ScrollView } from "react-native";
3
3
  import { AtomicText, AtomicIcon } from "@umituz/react-native-design-system/atoms";
4
4
  import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
5
- import type { CreditLog } from "../../domain/types/transaction.types";
6
5
  import { TransactionItem } from "./TransactionItem";
7
- import type { TransactionItemTranslations } from "./TransactionItem.types";
8
6
  import { transactionListStyles } from "./TransactionList.styles";
9
7
  import { LoadingState, EmptyState } from "./TransactionListStates";
10
8
  import { DEFAULT_TRANSACTION_LIST_MAX_HEIGHT } from "./TransactionList.constants";
9
+ import type { TransactionListTranslations, TransactionListProps } from "./TransactionList.types";
11
10
 
12
- export interface TransactionListTranslations extends TransactionItemTranslations {
13
- title: string;
14
- empty: string;
15
- loading: string;
16
- }
17
-
18
- interface TransactionListProps {
19
- transactions: CreditLog[];
20
- loading: boolean;
21
- translations: TransactionListTranslations;
22
- maxHeight?: number;
23
- dateFormatter?: (timestamp: number) => string;
24
- }
11
+ export type { TransactionListTranslations };
25
12
 
26
13
  export const TransactionList: React.FC<TransactionListProps> = ({
27
14
  transactions,
@@ -0,0 +1,16 @@
1
+ import type { CreditLog } from "../../domain/types/transaction.types";
2
+ import type { TransactionItemTranslations } from "./TransactionItem.types";
3
+
4
+ export interface TransactionListTranslations extends TransactionItemTranslations {
5
+ title: string;
6
+ empty: string;
7
+ loading: string;
8
+ }
9
+
10
+ export interface TransactionListProps {
11
+ transactions: CreditLog[];
12
+ loading: boolean;
13
+ translations: TransactionListTranslations;
14
+ maxHeight?: number;
15
+ dateFormatter?: (timestamp: number) => string;
16
+ }
package/src/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  // Domain Layer - Constants & Types
2
2
  export * from "./domains/subscription/core/SubscriptionConstants";
3
+ export type { SubscriptionMetadata, PremiumStatus, CreditInfo } from "./domains/subscription/core/types";
3
4
  export {
4
5
  createDefaultSubscriptionStatus,
5
6
  isSubscriptionValid,
@@ -48,7 +49,8 @@ export * from "./presentation/hooks/feedback/useFeedbackSubmit";
48
49
 
49
50
  // Presentation Layer - Components
50
51
  export * from "./domains/subscription/presentation/components/details/PremiumDetailsCard";
51
- export * from "./domains/subscription/presentation/components/details/PremiumStatusBadge";
52
+ export { PremiumStatusBadge } from "./domains/subscription/presentation/components/details/PremiumStatusBadge";
53
+ export type { PremiumStatusBadgeProps } from "./domains/subscription/presentation/components/details/PremiumStatusBadge.types";
52
54
  export * from "./domains/subscription/presentation/components/sections/SubscriptionSection";
53
55
  export * from "./domains/subscription/presentation/components/feedback/PaywallFeedbackModal";
54
56
  export * from "./domains/subscription/presentation/screens/SubscriptionDetailScreen";
@@ -57,7 +59,6 @@ export type {
57
59
  SubscriptionDetailTranslations,
58
60
  SubscriptionDisplayFlags,
59
61
  UpgradePromptConfig,
60
- CreditInfo,
61
62
  } from "./domains/subscription/presentation/screens/SubscriptionDetailScreen.types";
62
63
  export * from "./domains/paywall/components/PaywallContainer";
63
64