@sudobility/building_blocks 0.0.15 → 0.0.17

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.
@@ -3,3 +3,4 @@ export * from './breadcrumbs';
3
3
  export * from './footer';
4
4
  export * from './layout';
5
5
  export * from './settings';
6
+ export * from './subscription';
@@ -0,0 +1,96 @@
1
+ import React, { type ReactNode, type ComponentType } from 'react';
2
+ import { Theme, FontSize } from './appearance-settings';
3
+ /**
4
+ * Configuration for a settings section in the navigation.
5
+ */
6
+ export interface SettingsSectionConfig {
7
+ /** Unique identifier for the section */
8
+ id: string;
9
+ /** Icon component to display */
10
+ icon: ComponentType<{
11
+ className?: string;
12
+ }>;
13
+ /** Display label */
14
+ label: string;
15
+ /** Short description shown below label */
16
+ description: string;
17
+ /** The content to render when this section is selected */
18
+ content: ReactNode;
19
+ }
20
+ /**
21
+ * Translation keys used by GlobalSettingsPage.
22
+ */
23
+ export interface GlobalSettingsPageTranslations {
24
+ title: string;
25
+ backButton: string;
26
+ appearanceLabel: string;
27
+ appearanceDescription: string;
28
+ }
29
+ export interface GlobalSettingsPageProps {
30
+ /** Current theme value */
31
+ theme: Theme | string;
32
+ /** Current font size value */
33
+ fontSize: FontSize | string;
34
+ /** Callback when theme changes */
35
+ onThemeChange: (theme: Theme) => void;
36
+ /** Callback when font size changes */
37
+ onFontSizeChange: (fontSize: FontSize) => void;
38
+ /**
39
+ * Additional settings sections to display after Appearance.
40
+ * Each section needs an id, icon, label, description, and content.
41
+ */
42
+ additionalSections?: SettingsSectionConfig[];
43
+ /**
44
+ * Optional translation function.
45
+ * Falls back to default English strings if not provided.
46
+ */
47
+ t?: (key: string, fallback?: string) => string;
48
+ /**
49
+ * Translation function for AppearanceSettings.
50
+ * If provided, will be passed to AppearanceSettings component.
51
+ */
52
+ appearanceT?: (key: string, fallback?: string) => string;
53
+ /** Optional className for the container */
54
+ className?: string;
55
+ /** Whether to show the info box in appearance settings */
56
+ showAppearanceInfoBox?: boolean;
57
+ }
58
+ /**
59
+ * GlobalSettingsPage - A reusable settings page with master-detail layout.
60
+ *
61
+ * Features:
62
+ * - Appearance settings built-in as the first section
63
+ * - Extensible via additionalSections prop
64
+ * - Responsive master-detail layout
65
+ * - Mobile-friendly with back navigation
66
+ *
67
+ * @example
68
+ * ```tsx
69
+ * // Basic usage
70
+ * <GlobalSettingsPage
71
+ * theme={theme}
72
+ * fontSize={fontSize}
73
+ * onThemeChange={setTheme}
74
+ * onFontSizeChange={setFontSize}
75
+ * />
76
+ *
77
+ * // With additional sections
78
+ * <GlobalSettingsPage
79
+ * theme={theme}
80
+ * fontSize={fontSize}
81
+ * onThemeChange={setTheme}
82
+ * onFontSizeChange={setFontSize}
83
+ * additionalSections={[
84
+ * {
85
+ * id: 'notifications',
86
+ * icon: BellIcon,
87
+ * label: 'Notifications',
88
+ * description: 'Manage notification preferences',
89
+ * content: <NotificationSettings />,
90
+ * },
91
+ * ]}
92
+ * />
93
+ * ```
94
+ */
95
+ export declare const GlobalSettingsPage: React.FC<GlobalSettingsPageProps>;
96
+ export default GlobalSettingsPage;
@@ -1 +1,2 @@
1
1
  export { AppearanceSettings, Theme, FontSize, type AppearanceSettingsProps, type AppearanceSettingsTranslations, } from './appearance-settings';
2
+ export { GlobalSettingsPage, type GlobalSettingsPageProps, type GlobalSettingsPageTranslations, type SettingsSectionConfig, } from './global-settings-page';
@@ -0,0 +1,86 @@
1
+ /**
2
+ * @fileoverview App Pricing Page
3
+ * @description Public pricing page for displaying subscription options
4
+ */
5
+ /** Product from subscription provider */
6
+ export interface PricingProduct {
7
+ identifier: string;
8
+ title: string;
9
+ price: string;
10
+ priceString: string;
11
+ period?: string;
12
+ }
13
+ /** FAQ item */
14
+ export interface FAQItem {
15
+ question: string;
16
+ answer: string;
17
+ }
18
+ /** All localized labels for the pricing page */
19
+ export interface PricingPageLabels {
20
+ title: string;
21
+ subtitle: string;
22
+ periodYear: string;
23
+ periodMonth: string;
24
+ periodWeek: string;
25
+ billingMonthly: string;
26
+ billingYearly: string;
27
+ freeTierTitle: string;
28
+ freeTierPrice: string;
29
+ freeTierFeatures: string[];
30
+ currentPlanBadge: string;
31
+ mostPopularBadge: string;
32
+ ctaLogIn: string;
33
+ ctaTryFree: string;
34
+ ctaUpgrade: string;
35
+ faqTitle: string;
36
+ }
37
+ /** Formatter functions for dynamic strings */
38
+ export interface PricingPageFormatters {
39
+ /** Format savings badge: "Save 20%" */
40
+ formatSavePercent: (percent: number) => string;
41
+ /** Get features for a product by its identifier */
42
+ getProductFeatures: (productId: string) => string[];
43
+ }
44
+ /** Package ID to entitlement mapping */
45
+ export interface EntitlementMap {
46
+ [packageId: string]: string;
47
+ }
48
+ /** Entitlement to level mapping for comparing plan tiers */
49
+ export interface EntitlementLevels {
50
+ [entitlement: string]: number;
51
+ }
52
+ export interface AppPricingPageProps {
53
+ /** Available subscription products */
54
+ products: PricingProduct[];
55
+ /** Whether user is authenticated */
56
+ isAuthenticated: boolean;
57
+ /** Whether user has an active subscription */
58
+ hasActiveSubscription: boolean;
59
+ /** Current subscription product identifier (if any) */
60
+ currentProductIdentifier?: string;
61
+ /** User ID used for subscription (the selected entity's ID when logged in) */
62
+ subscriptionUserId?: string;
63
+ /** All localized labels */
64
+ labels: PricingPageLabels;
65
+ /** Formatter functions */
66
+ formatters: PricingPageFormatters;
67
+ /** Package ID to entitlement mapping for calculating savings */
68
+ entitlementMap: EntitlementMap;
69
+ /** Entitlement to level mapping for comparing tiers (higher = better) */
70
+ entitlementLevels: EntitlementLevels;
71
+ /** Called when user clicks on a plan */
72
+ onPlanClick: (planIdentifier: string) => void;
73
+ /** Called when user clicks on free plan */
74
+ onFreePlanClick: () => void;
75
+ /** Optional FAQ items */
76
+ faqItems?: FAQItem[];
77
+ /** Optional className for the container */
78
+ className?: string;
79
+ }
80
+ /**
81
+ * Public pricing page for displaying subscription options.
82
+ * - Non-authenticated: Free tile shows "Try it for Free", paid tiles show "Log in to Continue"
83
+ * - Authenticated on free: Free tile shows "Current Plan" badge (no CTA), paid tiles show "Upgrade"
84
+ * - Authenticated with subscription: Current plan shows badge (no CTA), higher tiers show "Upgrade"
85
+ */
86
+ export declare function AppPricingPage({ products, isAuthenticated, hasActiveSubscription, currentProductIdentifier, labels, formatters, entitlementMap, entitlementLevels, onPlanClick, onFreePlanClick, faqItems, className, }: AppPricingPageProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,114 @@
1
+ /**
2
+ * @fileoverview App Subscriptions Page
3
+ * @description Page for managing app subscriptions and viewing rate limits
4
+ */
5
+ import type { RateLimitsConfigData } from '@sudobility/types';
6
+ /** Product from subscription provider */
7
+ export interface SubscriptionProduct {
8
+ identifier: string;
9
+ title: string;
10
+ price: string;
11
+ priceString: string;
12
+ period?: string;
13
+ freeTrialPeriod?: string;
14
+ introPrice?: string;
15
+ }
16
+ /** Current subscription state */
17
+ export interface CurrentSubscription {
18
+ isActive: boolean;
19
+ productIdentifier?: string;
20
+ expirationDate?: Date;
21
+ willRenew?: boolean;
22
+ }
23
+ /** Subscription context value passed from consumer */
24
+ export interface SubscriptionContextValue {
25
+ products: SubscriptionProduct[];
26
+ currentSubscription: CurrentSubscription | null;
27
+ isLoading: boolean;
28
+ error: string | null;
29
+ purchase: (productId: string) => Promise<boolean>;
30
+ restore: () => Promise<boolean>;
31
+ clearError: () => void;
32
+ }
33
+ /** All localized labels for the subscription page */
34
+ export interface SubscriptionPageLabels {
35
+ title: string;
36
+ errorTitle: string;
37
+ purchaseError: string;
38
+ restoreError: string;
39
+ restoreNoPurchases: string;
40
+ periodYear: string;
41
+ periodMonth: string;
42
+ periodWeek: string;
43
+ billingMonthly: string;
44
+ billingYearly: string;
45
+ unlimited: string;
46
+ unlimitedRequests: string;
47
+ currentStatusLabel: string;
48
+ statusActive: string;
49
+ statusInactive: string;
50
+ statusInactiveMessage: string;
51
+ labelPlan: string;
52
+ labelPremium: string;
53
+ labelExpires: string;
54
+ labelWillRenew: string;
55
+ labelMonthlyUsage: string;
56
+ labelDailyUsage: string;
57
+ yes: string;
58
+ no: string;
59
+ buttonSubscribe: string;
60
+ buttonPurchasing: string;
61
+ buttonRestore: string;
62
+ buttonRestoring: string;
63
+ noProducts: string;
64
+ noProductsForPeriod: string;
65
+ freeTierTitle: string;
66
+ freeTierPrice: string;
67
+ freeTierFeatures: string[];
68
+ currentPlanBadge: string;
69
+ }
70
+ /** Formatter functions for dynamic strings */
71
+ export interface SubscriptionPageFormatters {
72
+ /** Format rate limit: "1,000 requests/hour" */
73
+ formatHourlyLimit: (limit: string) => string;
74
+ /** Format rate limit: "10,000 requests/day" */
75
+ formatDailyLimit: (limit: string) => string;
76
+ /** Format rate limit: "100,000 requests/month" */
77
+ formatMonthlyLimit: (limit: string) => string;
78
+ /** Format trial period: "7 days free trial" */
79
+ formatTrialDays: (count: number) => string;
80
+ /** Format trial period: "2 weeks free trial" */
81
+ formatTrialWeeks: (count: number) => string;
82
+ /** Format trial period: "1 month free trial" */
83
+ formatTrialMonths: (count: number) => string;
84
+ /** Format savings badge: "Save 20%" */
85
+ formatSavePercent: (percent: number) => string;
86
+ /** Format intro price note */
87
+ formatIntroNote: (price: string) => string;
88
+ }
89
+ export interface AppSubscriptionsPageProps {
90
+ /** Subscription context value */
91
+ subscription: SubscriptionContextValue;
92
+ /** Rate limit configuration */
93
+ rateLimitsConfig?: RateLimitsConfigData | null;
94
+ /** User ID used for subscription (the selected entity's ID when logged in) */
95
+ subscriptionUserId?: string;
96
+ /** All localized labels */
97
+ labels: SubscriptionPageLabels;
98
+ /** Formatter functions for dynamic strings */
99
+ formatters: SubscriptionPageFormatters;
100
+ /** Package ID to entitlement mapping */
101
+ packageEntitlementMap?: Record<string, string>;
102
+ /** Called when purchase succeeds */
103
+ onPurchaseSuccess?: () => void;
104
+ /** Called when restore succeeds */
105
+ onRestoreSuccess?: () => void;
106
+ /** Called on error */
107
+ onError?: (title: string, message: string) => void;
108
+ /** Called on warning */
109
+ onWarning?: (title: string, message: string) => void;
110
+ }
111
+ /**
112
+ * Page for managing app subscriptions.
113
+ */
114
+ export declare function AppSubscriptionsPage({ subscription, rateLimitsConfig, labels, formatters, packageEntitlementMap, onPurchaseSuccess, onRestoreSuccess, onError, onWarning, }: AppSubscriptionsPageProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,4 @@
1
+ export { AppSubscriptionsPage } from './AppSubscriptionsPage';
2
+ export type { AppSubscriptionsPageProps, SubscriptionProduct, CurrentSubscription, SubscriptionContextValue, SubscriptionPageLabels, SubscriptionPageFormatters, } from './AppSubscriptionsPage';
3
+ export { AppPricingPage } from './AppPricingPage';
4
+ export type { AppPricingPageProps, PricingProduct, FAQItem, PricingPageLabels, PricingPageFormatters, EntitlementMap, EntitlementLevels, } from './AppPricingPage';