@burdenoff/website-sdk 2026.514.4 → 2026.514.6
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/components/pricing.js +23 -9
- package/dist/components/pricing.js.map +1 -1
- package/dist/components/pricing.mjs +23 -9
- package/dist/components/pricing.mjs.map +1 -1
- package/dist/index.js +23 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +23 -9
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -368,27 +368,41 @@ function getMetadataForPlan(planName, planMetadata) {
|
|
|
368
368
|
ctaType: "signup"
|
|
369
369
|
};
|
|
370
370
|
}
|
|
371
|
+
function humanizeQuotaName(name) {
|
|
372
|
+
const parts = name.split(".");
|
|
373
|
+
const resource = parts.length >= 3 ? parts[parts.length - 2] : parts[parts.length - 1];
|
|
374
|
+
return resource.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
375
|
+
}
|
|
371
376
|
function transformQuotaToFeature(quota) {
|
|
372
377
|
const { name, limits } = quota;
|
|
373
378
|
if (!limits || typeof limits !== "object") {
|
|
374
|
-
return name;
|
|
379
|
+
return humanizeQuotaName(name);
|
|
375
380
|
}
|
|
376
381
|
const limitsObj = limits;
|
|
377
382
|
const value = limitsObj.value;
|
|
378
383
|
const unit = limitsObj.unit;
|
|
379
384
|
const type = limitsObj.type;
|
|
380
385
|
const description = limitsObj.description;
|
|
381
|
-
if (
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
return
|
|
386
|
+
if (typeof description === "string" && description) {
|
|
387
|
+
if (type === "number" && typeof value === "number") {
|
|
388
|
+
return `${value.toLocaleString()} ${description}`;
|
|
389
|
+
}
|
|
390
|
+
return description;
|
|
391
|
+
}
|
|
392
|
+
if (typeof unit === "string" && unit) {
|
|
393
|
+
if (typeof value === "number") {
|
|
394
|
+
return `${value.toLocaleString()} ${unit}`;
|
|
395
|
+
}
|
|
396
|
+
return `${unit}`;
|
|
397
|
+
}
|
|
398
|
+
const label = humanizeQuotaName(name);
|
|
399
|
+
if (type === "boolean") {
|
|
400
|
+
return label;
|
|
386
401
|
}
|
|
387
402
|
if (typeof value === "number") {
|
|
388
|
-
|
|
389
|
-
return `${name}: ${formattedValue} ${unit || ""}`.trim();
|
|
403
|
+
return `${value.toLocaleString()} ${label}`;
|
|
390
404
|
}
|
|
391
|
-
return
|
|
405
|
+
return label;
|
|
392
406
|
}
|
|
393
407
|
function extractDisplayFeatures(features, planName, fallbackFeatures) {
|
|
394
408
|
const quotaFeatures = features.filter((f) => f.quota).map((f) => transformQuotaToFeature(f.quota));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/client/security.ts","../../src/client/graphql-client.ts","../../src/client/provider.tsx","../../src/seo/page-head.tsx","../../src/utils/cn.ts","../../src/ui/button.tsx","../../src/components/pricing.tsx"],"names":["createContext","useContext","Helmet","jsx","twMerge","clsx","cva","React","Slot","useState","useEffect","jsxs"],"mappings":"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","file":"pricing.js","sourcesContent":["const LOOPBACK_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"::1\"]);\nconst RESERVED_HEADERS = new Set([\n \"authorization\",\n \"cookie\",\n \"x-actor-id\",\n \"x-actor-type\",\n \"x-consent-granted-by\",\n \"x-consent-scope\",\n \"x-consent-granted-at\",\n \"x-consent-expires-at\",\n]);\n\nexport function validateGatewayUrl(value: string): string {\n let url: URL;\n\n try {\n url = new URL(value);\n } catch {\n throw new Error(\"Gateway URL must be a valid absolute URL\");\n }\n\n if (url.protocol === \"https:\") {\n return url.toString();\n }\n\n if (\n url.protocol === \"http:\" &&\n LOOPBACK_HOSTS.has(url.hostname.toLowerCase())\n ) {\n return url.toString();\n }\n\n throw new Error(\"Gateway URL must use HTTPS unless it targets localhost\");\n}\n\nexport function sanitizeHeaders(\n headers?: Record<string, string>,\n): Record<string, string> | undefined {\n if (!headers) return undefined;\n\n return Object.fromEntries(\n Object.entries(headers).filter(\n ([key]) => !RESERVED_HEADERS.has(key.toLowerCase()),\n ),\n );\n}\n","/**\n * Lightweight GraphQL client for the Burdenoff Web SDK.\n * Uses native fetch - zero external dependencies.\n * All calls are unauthenticated (public gateway operations only).\n */\n\nimport { sanitizeHeaders, validateGatewayUrl } from \"./security\";\n\nexport interface WebSDKClientConfig {\n /** Global public gateway URL (e.g. \"https://api.burdenoff.com/global/graphql\") */\n gatewayUrl: string;\n /** Platform product ID for scoping operations */\n productId: string;\n /** Product slug (used for public product queries) */\n productSlug?: string;\n /** reCAPTCHA site key (if not fetched from product config) */\n recaptchaSiteKey?: string;\n /** Rybbit analytics site ID */\n rybbitSiteId?: string;\n /** Custom headers to include in all requests */\n headers?: Record<string, string>;\n}\n\nexport interface GraphQLResponse<T = Record<string, unknown>> {\n data?: T;\n errors?: Array<{\n message: string;\n locations?: Array<{ line: number; column: number }>;\n path?: Array<string | number>;\n extensions?: Record<string, unknown>;\n }>;\n}\n\nexport class WebSDKClient {\n private config: WebSDKClientConfig;\n private queryCache = new Map<\n string,\n { data: GraphQLResponse<unknown>; ts: number }\n >();\n private inflight = new Map<string, Promise<GraphQLResponse<unknown>>>();\n private static CACHE_TTL = 5 * 60 * 1000; // 5 minutes\n private static MAX_CACHE_ENTRIES = 100;\n\n constructor(config: WebSDKClientConfig) {\n this.config = {\n ...config,\n gatewayUrl: validateGatewayUrl(config.gatewayUrl),\n headers: sanitizeHeaders(config.headers),\n };\n }\n\n getConfig(): WebSDKClientConfig {\n return this.config;\n }\n\n /**\n * Execute a GraphQL query (with deduplication and caching)\n */\n async query<T = Record<string, unknown>>(\n query: string,\n variables?: Record<string, unknown>,\n ): Promise<GraphQLResponse<T>> {\n const cacheKey = JSON.stringify({ query, variables });\n\n // Return cached response if still valid, evict if expired\n const cached = this.queryCache.get(cacheKey);\n if (cached) {\n if (Date.now() - cached.ts < WebSDKClient.CACHE_TTL) {\n return cached.data as GraphQLResponse<T>;\n }\n this.queryCache.delete(cacheKey);\n }\n\n // Deduplicate: if same query is already in-flight, reuse the promise\n const existing = this.inflight.get(cacheKey);\n if (existing) {\n return existing as Promise<GraphQLResponse<T>>;\n }\n\n const promise = this.request<T>(query, variables)\n .then((result) => {\n // Cache successful responses only\n if (result.data && !result.errors?.length) {\n if (this.queryCache.size >= WebSDKClient.MAX_CACHE_ENTRIES) {\n const oldestEntry = this.queryCache.keys().next().value;\n if (oldestEntry) {\n this.queryCache.delete(oldestEntry);\n }\n }\n this.queryCache.set(cacheKey, { data: result, ts: Date.now() });\n }\n return result;\n })\n .finally(() => {\n this.inflight.delete(cacheKey);\n });\n\n this.inflight.set(cacheKey, promise);\n return promise;\n }\n\n /**\n * Execute a GraphQL mutation\n */\n async mutate<T = Record<string, unknown>>(\n mutation: string,\n variables?: Record<string, unknown>,\n ): Promise<GraphQLResponse<T>> {\n return this.request<T>(mutation, variables);\n }\n\n private async request<T>(\n query: string,\n variables?: Record<string, unknown>,\n ): Promise<GraphQLResponse<T>> {\n try {\n const response = await fetch(this.config.gatewayUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-product-id\": this.config.productId,\n ...this.config.headers,\n },\n body: JSON.stringify({ query, variables }),\n });\n\n if (!response.ok) {\n console.error(\n \"[WebSDK] GraphQL request failed\",\n response.status,\n response.statusText,\n );\n return {\n errors: [\n {\n message: `HTTP ${response.status}: ${response.statusText}`,\n extensions: { code: `HTTP_${response.status}` },\n },\n ],\n };\n }\n\n return (await response.json()) as GraphQLResponse<T>;\n } catch (error) {\n console.error(\n \"[WebSDK] Network error\",\n error instanceof Error ? error.message : \"unknown error\",\n );\n return {\n errors: [\n {\n message: error instanceof Error ? error.message : \"Network error\",\n extensions: { code: \"NETWORK_ERROR\" },\n },\n ],\n };\n }\n }\n}\n","/**\n * React context provider for the Web SDK client.\n * Wraps the application with WebSDKClient configuration.\n */\n\"use client\";\n\nimport { createContext, useContext, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport { resolveGatewayUrl } from \"./gateway-resolver\";\nimport { WebSDKClient, type WebSDKClientConfig } from \"./graphql-client\";\n\nconst WebSDKContext = createContext<WebSDKClient | null>(null);\n\nexport interface WebSDKProviderProps {\n /** SDK client configuration */\n config: WebSDKClientConfig;\n /** Child components */\n children: ReactNode;\n}\n\n/**\n * Provider component that makes the WebSDKClient available to all child components.\n *\n * @example\n * ```tsx\n * <WebSDKProvider config={{\n * gatewayUrl: \"https://api.burdenoff.com/global/graphql\",\n * productId: \"your-product-id\",\n * productSlug: \"your-product\",\n * }}>\n * <App />\n * </WebSDKProvider>\n * ```\n */\nexport function WebSDKProvider({ config, children }: WebSDKProviderProps) {\n const client = useMemo(() => {\n const resolvedConfig = {\n ...config,\n gatewayUrl: resolveGatewayUrl(config.gatewayUrl),\n };\n return new WebSDKClient(resolvedConfig);\n }, [config]);\n\n return (\n <WebSDKContext.Provider value={client}>{children}</WebSDKContext.Provider>\n );\n}\n\n/**\n * Hook to access the WebSDKClient instance.\n * Must be used within a WebSDKProvider.\n */\nexport function useWebSDK(): WebSDKClient {\n const client = useContext(WebSDKContext);\n if (!client) {\n throw new Error(\"useWebSDK must be used within a WebSDKProvider\");\n }\n return client;\n}\n\n/**\n * Hook to access the SDK configuration.\n * Useful for components that need config values like productId, recaptchaSiteKey, etc.\n */\nexport function useWebSDKConfig(): WebSDKClientConfig {\n const client = useWebSDK();\n return client.getConfig();\n}\n","/**\n * PageHead Component\n * Manages dynamic meta tags for SEO optimization on a per-page basis.\n * Supports JSON-LD structured data, Open Graph, Twitter Cards, favicons, and robots directives.\n *\n * @example\n * ```tsx\n * <PageHead\n * title=\"About Us\"\n * description=\"Learn about our mission and team\"\n * productName=\"MyProduct\"\n * keywords=\"about, team, mission\"\n * image=\"/og-about.png\"\n * url=\"https://myproduct.com/about\"\n * favicon=\"/favicon.ico\"\n * robots=\"index, follow\"\n * locale=\"en_US\"\n * twitterHandle=\"@burdenoff\"\n * themeColor=\"#1a1a2e\"\n * structuredData={{\n * \"@context\": \"https://schema.org\",\n * \"@type\": \"WebPage\",\n * name: \"About Us\",\n * }}\n * />\n * ```\n */\n\nimport { Helmet } from \"react-helmet-async\";\n\nexport interface PageHeadProps {\n /** Page title */\n title: string;\n /** Meta description */\n description?: string;\n /** Product/brand name (appended to title) */\n productName?: string;\n /** SEO keywords */\n keywords?: string;\n /** Open Graph image URL */\n image?: string;\n /** Page canonical URL */\n url?: string;\n /** Favicon URL */\n favicon?: string;\n /** Robots directive (e.g., \"index, follow\") */\n robots?: string;\n /** Open Graph locale (e.g., \"en_US\") */\n locale?: string;\n /** Twitter handle (e.g., \"@burdenoff\") */\n twitterHandle?: string;\n /** Theme color for mobile browsers */\n themeColor?: string;\n /** JSON-LD structured data objects */\n structuredData?: Record<string, unknown> | Array<Record<string, unknown>>;\n /** Additional meta tags */\n additionalMeta?: Array<{\n name?: string;\n property?: string;\n content: string;\n }>;\n}\n\nexport function PageHead({\n title,\n description,\n productName,\n keywords,\n image,\n url,\n favicon,\n robots = \"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\",\n locale = \"en_US\",\n twitterHandle,\n themeColor = \"#000000\",\n structuredData,\n additionalMeta,\n}: PageHeadProps) {\n const fullTitle =\n productName && !title.includes(productName)\n ? `${title} | ${productName}`\n : title;\n\n const fullImageUrl =\n image && !image.startsWith(\"http\") && url\n ? `${url.replace(/\\/$/, \"\")}${image}`\n : image;\n\n // Normalize structured data to an array\n const structuredDataItems: Array<Record<string, unknown>> = structuredData\n ? Array.isArray(structuredData)\n ? structuredData\n : [structuredData]\n : [];\n\n return (\n <Helmet>\n {/* Primary Meta Tags */}\n <title>{fullTitle}</title>\n <meta name=\"title\" content={fullTitle} />\n {description && <meta name=\"description\" content={description} />}\n {keywords && <meta name=\"keywords\" content={keywords} />}\n <meta name=\"author\" content=\"Burdenoff Consultancy Services Pvt Ltd\" />\n <meta name=\"robots\" content={robots} />\n\n {/* Canonical URL */}\n {url && <link rel=\"canonical\" href={url} />}\n\n {/* Favicon */}\n {favicon && <link rel=\"icon\" href={favicon} />}\n\n {/* Open Graph / Facebook */}\n <meta property=\"og:type\" content=\"website\" />\n <meta property=\"og:title\" content={fullTitle} />\n {description && <meta property=\"og:description\" content={description} />}\n {fullImageUrl && <meta property=\"og:image\" content={fullImageUrl} />}\n {url && <meta property=\"og:url\" content={url} />}\n <meta property=\"og:locale\" content={locale} />\n {productName && <meta property=\"og:site_name\" content={productName} />}\n\n {/* Twitter Card */}\n <meta name=\"twitter:card\" content=\"summary_large_image\" />\n <meta name=\"twitter:title\" content={fullTitle} />\n {description && <meta name=\"twitter:description\" content={description} />}\n {fullImageUrl && <meta name=\"twitter:image\" content={fullImageUrl} />}\n {twitterHandle && <meta name=\"twitter:creator\" content={twitterHandle} />}\n\n {/* Theme Color */}\n <meta name=\"theme-color\" content={themeColor} />\n\n {/* JSON-LD Structured Data */}\n {structuredDataItems.map((data, index) => (\n <script key={`ld-${index}`} type=\"application/ld+json\">\n {JSON.stringify(data)}\n </script>\n ))}\n\n {/* Additional Meta Tags */}\n {additionalMeta?.map((meta, index) => (\n <meta\n key={`meta-${index}`}\n {...(meta.name ? { name: meta.name } : {})}\n {...(meta.property ? { property: meta.property } : {})}\n content={meta.content}\n />\n ))}\n </Helmet>\n );\n}\n","/**\n * Utility function to merge Tailwind CSS classes\n * Combines clsx and tailwind-merge for optimal class handling\n */\n\nimport { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge multiple class names intelligently\n * - Handles conditional classes via clsx\n * - Deduplicates and resolves Tailwind conflicts via tailwind-merge\n *\n * @example\n * ```ts\n * cn('px-4 py-2', 'bg-blue-500', { 'text-white': isActive })\n * // => 'px-4 py-2 bg-blue-500 text-white' (if isActive is true)\n * ```\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\n\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"../utils/cn\";\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground shadow hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90\",\n outline:\n \"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2\",\n sm: \"h-8 rounded-md px-3 text-xs\",\n lg: \"h-10 rounded-md px-8\",\n icon: \"h-9 w-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nexport interface ButtonProps\n extends\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\";\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, className }))}\n ref={ref}\n {...props}\n />\n );\n },\n);\nButton.displayName = \"Button\";\n\nexport { Button, buttonVariants };\n","/**\n * Pricing Component\n * GraphQL-powered pricing component with quota-based features and monthly/yearly toggle\n *\n * @example\n * ```tsx\n * import { PricingPage, PricingSection } from '@burdenoff/website-sdk/components/pricing'\n *\n * // Full page with hero\n * <PricingPage\n * productName=\"BigConsole\"\n * productId=\"bigconsole-123\"\n * appLoginUrl=\"https://app.bigconsole.com/login\"\n * contactUrl=\"/contact\"\n * fallbackFeatures={{\n * basic: ['Up to 5 dashboards', '10 data sources'],\n * professional: ['Unlimited dashboards', 'API access'],\n * enterprise: ['Everything in Professional', 'Dedicated support']\n * }}\n * />\n *\n * // Embeddable section\n * <PricingSection {...props} id=\"pricing\" className=\"bg-muted/30\" />\n * ```\n */\n\n\"use client\";\n\nimport { useEffect, useState } from \"react\";\n\nimport { useWebSDK, useWebSDKConfig } from \"../client/provider\";\nimport { PageHead } from \"../seo/page-head\";\nimport { Button } from \"../ui/button\";\n\n// ============================================================================\n// GRAPHQL QUERY\n// ============================================================================\n\nconst GET_PLANS_QUERY = `\n query GetPublicPlans($productId: String!) {\n publicPlans(productId: $productId) {\n id\n name\n price\n currency\n currencyPrices\n duration\n features {\n id\n quotaId\n quota {\n id\n name\n limits\n }\n }\n isActive\n productID\n createdAt\n }\n }\n`;\n\n// ============================================================================\n// TYPES & INTERFACES\n// ============================================================================\n\ninterface PlanFeature {\n id: string;\n quotaId?: string | null;\n quota?: {\n id: string;\n name: string;\n limits?: unknown;\n } | null;\n}\n\ninterface GatewayPlan {\n id: string;\n name: string;\n price: number;\n currency: string;\n currencyPrices?: Record<string, number> | null;\n duration: string;\n features: PlanFeature[];\n isActive: boolean;\n productID?: string | null;\n createdAt: string;\n}\n\ninterface GetPlansResponse {\n publicPlans: GatewayPlan[];\n}\n\nexport interface PlanCard {\n id: string;\n name: string;\n price: number;\n currency: string;\n currencyPrices?: Record<string, number> | null;\n duration: string;\n features: Array<{\n id: string;\n quotaId?: string | null;\n quota?: {\n id: string;\n name: string;\n limits?: unknown;\n } | null;\n }>;\n isActive: boolean;\n productID?: string | null;\n}\n\ninterface CurrencyConfig {\n code: string;\n symbol: string;\n position: \"prefix\" | \"suffix\";\n}\n\ninterface PlanMetadata {\n tier: \"basic\" | \"professional\" | \"enterprise\";\n displayName: string;\n defaultDescription: string;\n popular: boolean;\n ctaText: string;\n ctaType: \"signup\" | \"contact\";\n}\n\nexport interface PricingProps {\n /**\n * Product name (used in branding and SEO)\n */\n productName?: string;\n /**\n * Product ID for GraphQL query (falls back to WebSDKConfig.productId)\n */\n productId?: string;\n /**\n * App login URL for signup CTA\n */\n appLoginUrl: string;\n /**\n * Contact page URL for enterprise CTA\n * @default '/contact'\n */\n contactUrl?: string;\n /**\n * Supported currencies\n */\n currencies?: Record<string, CurrencyConfig>;\n /**\n * Billing interval display text\n */\n billingIntervals?: Record<string, string>;\n /**\n * Plan metadata (tier info, CTA text, etc.)\n */\n planMetadata?: Record<string, Partial<PlanMetadata>>;\n /**\n * Fallback features when API doesn't provide them or is unavailable\n */\n fallbackFeatures?: {\n basic?: string[];\n professional?: string[];\n enterprise?: string[];\n };\n /**\n * Hero section heading (for PricingPage)\n * @default 'Simple, Transparent Pricing'\n */\n heroHeading?: string;\n /**\n * Hero section subtitle (for PricingPage)\n * @default \"Choose the plan that's right for you. No hidden fees, no surprises.\"\n */\n heroSubtitle?: string;\n /**\n * Section heading (for PricingSection)\n * @default 'Pricing Plans'\n */\n sectionHeading?: string;\n /**\n * Section subtitle (for PricingSection)\n * @default 'Choose the perfect plan for your needs'\n */\n sectionSubtitle?: string;\n /**\n * Custom CSS class\n */\n className?: string;\n /**\n * Section ID for anchor links\n */\n id?: string;\n /**\n * SEO: Page title (optional, for PricingPage)\n */\n seoTitle?: string;\n /**\n * SEO: Page description (optional, for PricingPage)\n */\n seoDescription?: string;\n /**\n * SEO: Keywords (optional, for PricingPage)\n */\n seoKeywords?: string;\n /**\n * SEO: OG Image URL (optional, for PricingPage)\n */\n seoImage?: string;\n /**\n * SEO: Canonical URL (optional, for PricingPage)\n */\n seoUrl?: string;\n}\n\n// ============================================================================\n// SERVICE FUNCTIONS\n// ============================================================================\n\n/**\n * Format price for display with currency symbol\n */\nfunction formatPrice(\n price: number,\n currencyCode: string = \"USD\",\n currencies?: Record<string, CurrencyConfig>,\n): string {\n const defaultCurrencies: Record<string, CurrencyConfig> = {\n USD: { code: \"USD\", symbol: \"$\", position: \"prefix\" },\n EUR: { code: \"EUR\", symbol: \"\\u20AC\", position: \"prefix\" },\n GBP: { code: \"GBP\", symbol: \"\\u00A3\", position: \"prefix\" },\n INR: { code: \"INR\", symbol: \"\\u20B9\", position: \"prefix\" },\n };\n\n const currencyMap = currencies || defaultCurrencies;\n const currency: CurrencyConfig = currencyMap[currencyCode] || {\n code: currencyCode,\n symbol: currencyCode,\n position: \"prefix\",\n };\n\n const formattedNumber = price % 1 === 0 ? price.toString() : price.toFixed(2);\n\n return currency.position === \"prefix\"\n ? `${currency.symbol}${formattedNumber}`\n : `${formattedNumber}${currency.symbol}`;\n}\n\n/**\n * Format billing interval for display\n */\nfunction formatInterval(\n duration: string,\n billingIntervals?: Record<string, string>,\n): string {\n const defaultIntervals: Record<string, string> = {\n monthly: \"/month\",\n yearly: \"/year\",\n };\n\n const intervals = billingIntervals || defaultIntervals;\n return intervals[duration] || `/${duration}`;\n}\n\n/**\n * Detect plan tier from plan name\n */\nfunction detectPlanTier(\n planName: string,\n): \"basic\" | \"professional\" | \"enterprise\" | null {\n const name = planName.toLowerCase();\n\n if (name.includes(\"basic\") || name.includes(\"starter\")) {\n return \"basic\";\n } else if (\n name.includes(\"pro\") ||\n name.includes(\"professional\") ||\n name.includes(\"premium\")\n ) {\n return \"professional\";\n } else if (name.includes(\"enterprise\") || name.includes(\"business\")) {\n return \"enterprise\";\n }\n\n return null;\n}\n\n/**\n * Get features for a specific plan tier from fallback config\n */\nfunction getFallbackFeaturesForTier(\n tier: \"basic\" | \"professional\" | \"enterprise\",\n fallbackFeatures?: {\n basic?: string[];\n professional?: string[];\n enterprise?: string[];\n },\n): string[] {\n return [...(fallbackFeatures?.[tier] || [])];\n}\n\n/**\n * Get metadata for a plan by name\n */\nfunction getMetadataForPlan(\n planName: string,\n planMetadata?: Record<string, Partial<PlanMetadata>>,\n): PlanMetadata {\n const normalizedName = planName.toLowerCase();\n\n // Try exact match first\n if (planMetadata?.[normalizedName]) {\n const meta = planMetadata[normalizedName];\n return {\n tier: meta.tier || \"basic\",\n displayName: meta.displayName || planName,\n defaultDescription: meta.defaultDescription || \"Choose this plan\",\n popular: meta.popular ?? false,\n ctaText: meta.ctaText || \"Get Started\",\n ctaType: meta.ctaType || \"signup\",\n };\n }\n\n // Try tier detection\n const tier = detectPlanTier(planName);\n if (tier) {\n return {\n tier,\n displayName: planName,\n defaultDescription: \"Choose this plan\",\n popular: tier === \"professional\",\n ctaText: tier === \"enterprise\" ? \"Contact Sales\" : \"Get Started\",\n ctaType: tier === \"enterprise\" ? \"contact\" : \"signup\",\n };\n }\n\n // Fallback\n return {\n tier: \"basic\",\n displayName: planName,\n defaultDescription: \"Choose this plan\",\n popular: false,\n ctaText: \"Get Started\",\n ctaType: \"signup\",\n };\n}\n\n/**\n * Transform quota limits to a human-readable feature string\n */\nfunction transformQuotaToFeature(quota: {\n id: string;\n name: string;\n limits?: unknown;\n}): string {\n const { name, limits } = quota;\n\n if (!limits || typeof limits !== \"object\") {\n return name;\n }\n\n const limitsObj = limits as Record<string, unknown>;\n const value = limitsObj.value;\n const unit = limitsObj.unit;\n const type = limitsObj.type;\n const description = limitsObj.description;\n\n if (type === \"number\" && typeof value === \"number\") {\n const formattedValue = value.toLocaleString();\n return `${formattedValue} ${unit || \"\"}${description ? \" - \" + description : \"\"}`.trim();\n } else if (type === \"boolean\") {\n return (typeof description === \"string\" && description) || name;\n }\n\n if (typeof value === \"number\") {\n const formattedValue = value.toLocaleString();\n return `${name}: ${formattedValue} ${unit || \"\"}`.trim();\n }\n\n return name;\n}\n\n/**\n * Extract display features from a plan's feature list\n */\nfunction extractDisplayFeatures(\n features: PlanFeature[],\n planName: string,\n fallbackFeatures?: {\n basic?: string[];\n professional?: string[];\n enterprise?: string[];\n },\n): string[] {\n // If API provides features with quotas, transform them\n const quotaFeatures = features\n .filter((f) => f.quota)\n .map((f) => transformQuotaToFeature(f.quota!));\n\n if (quotaFeatures.length > 0) {\n return quotaFeatures;\n }\n\n // Fall back to tier-based features\n const tier = detectPlanTier(planName);\n if (tier) {\n return getFallbackFeaturesForTier(tier, fallbackFeatures);\n }\n\n return [];\n}\n\n// ============================================================================\n// UI CARD TYPE (internal)\n// ============================================================================\n\ninterface DisplayPlanCard {\n id: string;\n name: string;\n description: string;\n price: string;\n priceRaw: number;\n interval: string;\n duration: string;\n features: string[];\n popular: boolean;\n ctaText: string;\n ctaLink: string;\n tier: \"basic\" | \"professional\" | \"enterprise\" | null;\n}\n\n/**\n * Transform a GatewayPlan into a display card\n */\nfunction transformToDisplayCard(\n plan: GatewayPlan,\n props: PricingProps,\n): DisplayPlanCard {\n const metadata = getMetadataForPlan(plan.name, props.planMetadata);\n\n const formattedPrice = formatPrice(\n plan.price,\n plan.currency,\n props.currencies,\n );\n const interval = formatInterval(plan.duration, props.billingIntervals);\n\n const features = extractDisplayFeatures(\n plan.features,\n plan.name,\n props.fallbackFeatures,\n );\n\n const contactUrl = props.contactUrl || \"/contact\";\n const ctaLink =\n metadata.ctaType === \"contact\" ? contactUrl : props.appLoginUrl;\n\n return {\n id: plan.id,\n name: plan.name,\n description: metadata.defaultDescription,\n price: formattedPrice,\n priceRaw: plan.price,\n interval,\n duration: plan.duration,\n features,\n popular: metadata.popular,\n ctaText: metadata.ctaText,\n ctaLink,\n tier: metadata.tier,\n };\n}\n\n// ============================================================================\n// REACT COMPONENTS\n// ============================================================================\n\n/**\n * Pricing Section Component - Embeddable\n */\nexport function PricingSection(props: PricingProps) {\n const {\n sectionHeading = \"Pricing Plans\",\n sectionSubtitle = \"Choose the perfect plan for your needs\",\n id,\n className = \"\",\n } = props;\n\n const client = useWebSDK();\n const config = useWebSDKConfig();\n\n const resolvedProductId = props.productId || config.productId;\n\n const [allPlans, setAllPlans] = useState<DisplayPlanCard[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [billingCycle, setBillingCycle] = useState<\"monthly\" | \"yearly\">(\n \"monthly\",\n );\n\n useEffect(() => {\n let cancelled = false;\n\n async function loadPlans() {\n try {\n setLoading(true);\n\n const response = await client.query<GetPlansResponse>(\n GET_PLANS_QUERY,\n { productId: resolvedProductId },\n );\n\n if (cancelled) return;\n\n if (response.errors && response.errors.length > 0) {\n throw new Error(response.errors[0]!.message);\n }\n\n if (!response.data?.publicPlans) {\n throw new Error(\"No plans data received\");\n }\n\n // Server already filters by productId — just filter active, transform, sort\n const cards = response.data.publicPlans\n .filter((plan) => plan.isActive)\n .map((plan) => transformToDisplayCard(plan, props))\n .sort((a, b) => a.priceRaw - b.priceRaw);\n\n setAllPlans(cards);\n setError(null);\n } catch (err) {\n if (cancelled) return;\n console.error(\"Failed to load plans:\", err);\n setError(\"Unable to load pricing information. Please try again later.\");\n } finally {\n if (!cancelled) {\n setLoading(false);\n }\n }\n }\n\n loadPlans();\n\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- props is destructured, actual deps are client + productId\n }, [client, resolvedProductId]);\n\n // Filter plans based on selected billing cycle\n const plans = allPlans.filter((plan) =>\n billingCycle === \"monthly\"\n ? plan.duration === \"monthly\"\n : plan.duration === \"yearly\",\n );\n\n if (loading) {\n return (\n <section id={id} className={`py-12 sm:py-16 md:py-20 ${className}`}>\n <div className=\"container mx-auto px-4 sm:px-6\">\n <div className=\"text-center mb-8 sm:mb-12\">\n <h2 className=\"text-2xl sm:text-3xl md:text-4xl font-bold mb-3 sm:mb-4\">\n {sectionHeading}\n </h2>\n <p className=\"text-muted-foreground text-sm sm:text-base md:text-lg\">\n Loading pricing information...\n </p>\n </div>\n <div className=\"grid md:grid-cols-3 gap-6 sm:gap-8\">\n {[1, 2, 3].map((i) => (\n <div\n key={i}\n className=\"bg-card border rounded-lg p-6 animate-pulse\"\n >\n <div className=\"h-6 bg-muted rounded w-1/2 mb-4\"></div>\n <div className=\"h-4 bg-muted rounded w-3/4 mb-6\"></div>\n <div className=\"h-10 bg-muted rounded w-1/3 mb-6\"></div>\n <div className=\"space-y-3 mb-6\">\n {[1, 2, 3, 4].map((j) => (\n <div key={j} className=\"h-4 bg-muted rounded\"></div>\n ))}\n </div>\n <div className=\"h-10 bg-muted rounded\"></div>\n </div>\n ))}\n </div>\n </div>\n </section>\n );\n }\n\n if (error && plans.length === 0) {\n return (\n <section id={id} className={`py-12 sm:py-16 md:py-20 ${className}`}>\n <div className=\"container mx-auto px-4 sm:px-6\">\n <div className=\"text-center\">\n <h2 className=\"text-2xl sm:text-3xl md:text-4xl font-bold mb-4\">\n {sectionHeading}\n </h2>\n <p className=\"text-muted-foreground mb-8\">{error}</p>\n <Button onClick={() => window.location.reload()}>Retry</Button>\n </div>\n </div>\n </section>\n );\n }\n\n return (\n <section id={id} className={`py-12 sm:py-16 md:py-20 ${className}`}>\n <div className=\"container mx-auto px-4 sm:px-6\">\n <div className=\"text-center mb-8 sm:mb-12\">\n <h2 className=\"text-2xl sm:text-3xl md:text-4xl font-bold mb-3 sm:mb-4\">\n {sectionHeading}\n </h2>\n <p className=\"text-muted-foreground text-sm sm:text-base md:text-lg mb-6\">\n {sectionSubtitle}\n </p>\n\n {/* Billing Cycle Toggle */}\n <div className=\"inline-flex items-center gap-3 bg-muted p-1.5 rounded-lg\">\n <button\n onClick={() => setBillingCycle(\"monthly\")}\n className={`px-6 py-2 rounded-md text-sm font-medium transition-all ${\n billingCycle === \"monthly\"\n ? \"bg-background shadow-sm text-foreground\"\n : \"text-muted-foreground hover:text-foreground\"\n }`}\n >\n Monthly\n </button>\n <button\n onClick={() => setBillingCycle(\"yearly\")}\n className={`px-6 py-2 rounded-md text-sm font-medium transition-all ${\n billingCycle === \"yearly\"\n ? \"bg-background shadow-sm text-foreground\"\n : \"text-muted-foreground hover:text-foreground\"\n }`}\n >\n Yearly\n </button>\n </div>\n </div>\n\n <div className=\"grid md:grid-cols-3 gap-6 sm:gap-8 max-w-6xl mx-auto items-stretch\">\n {plans.map((plan) => (\n <div\n key={plan.id}\n className={`bg-card rounded-xl p-6 sm:p-8 transition-all duration-300 flex flex-col ${\n plan.popular\n ? \"border-2 border-primary shadow-xl ring-1 ring-primary/20\"\n : \"border hover:shadow-lg hover:border-primary/50\"\n }`}\n >\n <div className=\"text-center mb-6\">\n {plan.popular && (\n <span className=\"inline-block bg-primary text-primary-foreground px-4 py-1 rounded-full text-xs font-semibold mb-3\">\n Most Popular\n </span>\n )}\n <h3 className=\"text-xl sm:text-2xl font-bold mb-2\">\n {plan.name}\n </h3>\n <p className=\"text-muted-foreground text-sm\">\n {plan.description}\n </p>\n </div>\n\n <div className=\"text-center mb-8\">\n <div className=\"flex items-baseline justify-center gap-1\">\n <span className=\"text-4xl sm:text-5xl font-bold\">\n {plan.price}\n </span>\n <span className=\"text-muted-foreground text-lg\">\n {plan.interval}\n </span>\n </div>\n </div>\n\n <ul className=\"space-y-3 mb-8 flex-1\">\n {plan.features.map((feature, index) => (\n <li key={index} className=\"text-sm flex items-start gap-2\">\n <span className=\"text-primary mt-0.5 flex-shrink-0\">\n ✓\n </span>\n <span>{feature}</span>\n </li>\n ))}\n </ul>\n\n {plan.ctaLink.startsWith(\"/\") ? (\n <Button\n className=\"w-full h-11\"\n variant={plan.popular ? \"default\" : \"outline\"}\n size=\"lg\"\n asChild\n >\n <a\n href={plan.ctaLink}\n onClick={() =>\n window.scrollTo({ top: 0, behavior: \"smooth\" })\n }\n >\n {plan.ctaText}\n </a>\n </Button>\n ) : (\n <Button\n className=\"w-full h-11\"\n variant={plan.popular ? \"default\" : \"outline\"}\n size=\"lg\"\n asChild\n >\n <a\n href={plan.ctaLink}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {plan.ctaText}\n </a>\n </Button>\n )}\n </div>\n ))}\n </div>\n </div>\n </section>\n );\n}\n\n/**\n * Pricing Page Component - Full Page with Hero\n */\nexport function PricingPage(props: PricingProps) {\n const {\n productName,\n heroHeading = \"Simple, Transparent Pricing\",\n heroSubtitle = \"Choose the plan that's right for you. No hidden fees, no surprises.\",\n seoTitle,\n seoDescription,\n seoKeywords,\n seoImage,\n seoUrl,\n } = props;\n\n return (\n <div className=\"w-full\">\n {/* SEO Meta Tags */}\n {seoTitle && (\n <PageHead\n title={seoTitle}\n description={seoDescription || heroSubtitle}\n productName={productName}\n keywords={seoKeywords}\n image={seoImage}\n url={seoUrl}\n />\n )}\n\n {/* Hero Section */}\n <section className=\"bg-gradient-to-b from-background to-muted/20 py-12 sm:py-16 md:py-20 lg:py-24\">\n <div className=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8\">\n <div className=\"text-center max-w-3xl mx-auto\">\n <h1 className=\"text-3xl sm:text-4xl md:text-5xl font-bold mb-4 sm:mb-6\">\n {heroHeading}\n </h1>\n <p className=\"text-lg sm:text-xl text-muted-foreground leading-relaxed\">\n {heroSubtitle}\n </p>\n </div>\n </div>\n </section>\n\n {/* Pricing Section */}\n <PricingSection {...props} />\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/client/security.ts","../../src/client/graphql-client.ts","../../src/client/provider.tsx","../../src/seo/page-head.tsx","../../src/utils/cn.ts","../../src/ui/button.tsx","../../src/components/pricing.tsx"],"names":["createContext","useContext","Helmet","jsx","twMerge","clsx","cva","React","Slot","useState","useEffect","jsxs"],"mappings":"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","file":"pricing.js","sourcesContent":["const LOOPBACK_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"::1\"]);\nconst RESERVED_HEADERS = new Set([\n \"authorization\",\n \"cookie\",\n \"x-actor-id\",\n \"x-actor-type\",\n \"x-consent-granted-by\",\n \"x-consent-scope\",\n \"x-consent-granted-at\",\n \"x-consent-expires-at\",\n]);\n\nexport function validateGatewayUrl(value: string): string {\n let url: URL;\n\n try {\n url = new URL(value);\n } catch {\n throw new Error(\"Gateway URL must be a valid absolute URL\");\n }\n\n if (url.protocol === \"https:\") {\n return url.toString();\n }\n\n if (\n url.protocol === \"http:\" &&\n LOOPBACK_HOSTS.has(url.hostname.toLowerCase())\n ) {\n return url.toString();\n }\n\n throw new Error(\"Gateway URL must use HTTPS unless it targets localhost\");\n}\n\nexport function sanitizeHeaders(\n headers?: Record<string, string>,\n): Record<string, string> | undefined {\n if (!headers) return undefined;\n\n return Object.fromEntries(\n Object.entries(headers).filter(\n ([key]) => !RESERVED_HEADERS.has(key.toLowerCase()),\n ),\n );\n}\n","/**\n * Lightweight GraphQL client for the Burdenoff Web SDK.\n * Uses native fetch - zero external dependencies.\n * All calls are unauthenticated (public gateway operations only).\n */\n\nimport { sanitizeHeaders, validateGatewayUrl } from \"./security\";\n\nexport interface WebSDKClientConfig {\n /** Global public gateway URL (e.g. \"https://api.burdenoff.com/global/graphql\") */\n gatewayUrl: string;\n /** Platform product ID for scoping operations */\n productId: string;\n /** Product slug (used for public product queries) */\n productSlug?: string;\n /** reCAPTCHA site key (if not fetched from product config) */\n recaptchaSiteKey?: string;\n /** Rybbit analytics site ID */\n rybbitSiteId?: string;\n /** Custom headers to include in all requests */\n headers?: Record<string, string>;\n}\n\nexport interface GraphQLResponse<T = Record<string, unknown>> {\n data?: T;\n errors?: Array<{\n message: string;\n locations?: Array<{ line: number; column: number }>;\n path?: Array<string | number>;\n extensions?: Record<string, unknown>;\n }>;\n}\n\nexport class WebSDKClient {\n private config: WebSDKClientConfig;\n private queryCache = new Map<\n string,\n { data: GraphQLResponse<unknown>; ts: number }\n >();\n private inflight = new Map<string, Promise<GraphQLResponse<unknown>>>();\n private static CACHE_TTL = 5 * 60 * 1000; // 5 minutes\n private static MAX_CACHE_ENTRIES = 100;\n\n constructor(config: WebSDKClientConfig) {\n this.config = {\n ...config,\n gatewayUrl: validateGatewayUrl(config.gatewayUrl),\n headers: sanitizeHeaders(config.headers),\n };\n }\n\n getConfig(): WebSDKClientConfig {\n return this.config;\n }\n\n /**\n * Execute a GraphQL query (with deduplication and caching)\n */\n async query<T = Record<string, unknown>>(\n query: string,\n variables?: Record<string, unknown>,\n ): Promise<GraphQLResponse<T>> {\n const cacheKey = JSON.stringify({ query, variables });\n\n // Return cached response if still valid, evict if expired\n const cached = this.queryCache.get(cacheKey);\n if (cached) {\n if (Date.now() - cached.ts < WebSDKClient.CACHE_TTL) {\n return cached.data as GraphQLResponse<T>;\n }\n this.queryCache.delete(cacheKey);\n }\n\n // Deduplicate: if same query is already in-flight, reuse the promise\n const existing = this.inflight.get(cacheKey);\n if (existing) {\n return existing as Promise<GraphQLResponse<T>>;\n }\n\n const promise = this.request<T>(query, variables)\n .then((result) => {\n // Cache successful responses only\n if (result.data && !result.errors?.length) {\n if (this.queryCache.size >= WebSDKClient.MAX_CACHE_ENTRIES) {\n const oldestEntry = this.queryCache.keys().next().value;\n if (oldestEntry) {\n this.queryCache.delete(oldestEntry);\n }\n }\n this.queryCache.set(cacheKey, { data: result, ts: Date.now() });\n }\n return result;\n })\n .finally(() => {\n this.inflight.delete(cacheKey);\n });\n\n this.inflight.set(cacheKey, promise);\n return promise;\n }\n\n /**\n * Execute a GraphQL mutation\n */\n async mutate<T = Record<string, unknown>>(\n mutation: string,\n variables?: Record<string, unknown>,\n ): Promise<GraphQLResponse<T>> {\n return this.request<T>(mutation, variables);\n }\n\n private async request<T>(\n query: string,\n variables?: Record<string, unknown>,\n ): Promise<GraphQLResponse<T>> {\n try {\n const response = await fetch(this.config.gatewayUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-product-id\": this.config.productId,\n ...this.config.headers,\n },\n body: JSON.stringify({ query, variables }),\n });\n\n if (!response.ok) {\n console.error(\n \"[WebSDK] GraphQL request failed\",\n response.status,\n response.statusText,\n );\n return {\n errors: [\n {\n message: `HTTP ${response.status}: ${response.statusText}`,\n extensions: { code: `HTTP_${response.status}` },\n },\n ],\n };\n }\n\n return (await response.json()) as GraphQLResponse<T>;\n } catch (error) {\n console.error(\n \"[WebSDK] Network error\",\n error instanceof Error ? error.message : \"unknown error\",\n );\n return {\n errors: [\n {\n message: error instanceof Error ? error.message : \"Network error\",\n extensions: { code: \"NETWORK_ERROR\" },\n },\n ],\n };\n }\n }\n}\n","/**\n * React context provider for the Web SDK client.\n * Wraps the application with WebSDKClient configuration.\n */\n\"use client\";\n\nimport { createContext, useContext, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport { resolveGatewayUrl } from \"./gateway-resolver\";\nimport { WebSDKClient, type WebSDKClientConfig } from \"./graphql-client\";\n\nconst WebSDKContext = createContext<WebSDKClient | null>(null);\n\nexport interface WebSDKProviderProps {\n /** SDK client configuration */\n config: WebSDKClientConfig;\n /** Child components */\n children: ReactNode;\n}\n\n/**\n * Provider component that makes the WebSDKClient available to all child components.\n *\n * @example\n * ```tsx\n * <WebSDKProvider config={{\n * gatewayUrl: \"https://api.burdenoff.com/global/graphql\",\n * productId: \"your-product-id\",\n * productSlug: \"your-product\",\n * }}>\n * <App />\n * </WebSDKProvider>\n * ```\n */\nexport function WebSDKProvider({ config, children }: WebSDKProviderProps) {\n const client = useMemo(() => {\n const resolvedConfig = {\n ...config,\n gatewayUrl: resolveGatewayUrl(config.gatewayUrl),\n };\n return new WebSDKClient(resolvedConfig);\n }, [config]);\n\n return (\n <WebSDKContext.Provider value={client}>{children}</WebSDKContext.Provider>\n );\n}\n\n/**\n * Hook to access the WebSDKClient instance.\n * Must be used within a WebSDKProvider.\n */\nexport function useWebSDK(): WebSDKClient {\n const client = useContext(WebSDKContext);\n if (!client) {\n throw new Error(\"useWebSDK must be used within a WebSDKProvider\");\n }\n return client;\n}\n\n/**\n * Hook to access the SDK configuration.\n * Useful for components that need config values like productId, recaptchaSiteKey, etc.\n */\nexport function useWebSDKConfig(): WebSDKClientConfig {\n const client = useWebSDK();\n return client.getConfig();\n}\n","/**\n * PageHead Component\n * Manages dynamic meta tags for SEO optimization on a per-page basis.\n * Supports JSON-LD structured data, Open Graph, Twitter Cards, favicons, and robots directives.\n *\n * @example\n * ```tsx\n * <PageHead\n * title=\"About Us\"\n * description=\"Learn about our mission and team\"\n * productName=\"MyProduct\"\n * keywords=\"about, team, mission\"\n * image=\"/og-about.png\"\n * url=\"https://myproduct.com/about\"\n * favicon=\"/favicon.ico\"\n * robots=\"index, follow\"\n * locale=\"en_US\"\n * twitterHandle=\"@burdenoff\"\n * themeColor=\"#1a1a2e\"\n * structuredData={{\n * \"@context\": \"https://schema.org\",\n * \"@type\": \"WebPage\",\n * name: \"About Us\",\n * }}\n * />\n * ```\n */\n\nimport { Helmet } from \"react-helmet-async\";\n\nexport interface PageHeadProps {\n /** Page title */\n title: string;\n /** Meta description */\n description?: string;\n /** Product/brand name (appended to title) */\n productName?: string;\n /** SEO keywords */\n keywords?: string;\n /** Open Graph image URL */\n image?: string;\n /** Page canonical URL */\n url?: string;\n /** Favicon URL */\n favicon?: string;\n /** Robots directive (e.g., \"index, follow\") */\n robots?: string;\n /** Open Graph locale (e.g., \"en_US\") */\n locale?: string;\n /** Twitter handle (e.g., \"@burdenoff\") */\n twitterHandle?: string;\n /** Theme color for mobile browsers */\n themeColor?: string;\n /** JSON-LD structured data objects */\n structuredData?: Record<string, unknown> | Array<Record<string, unknown>>;\n /** Additional meta tags */\n additionalMeta?: Array<{\n name?: string;\n property?: string;\n content: string;\n }>;\n}\n\nexport function PageHead({\n title,\n description,\n productName,\n keywords,\n image,\n url,\n favicon,\n robots = \"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\",\n locale = \"en_US\",\n twitterHandle,\n themeColor = \"#000000\",\n structuredData,\n additionalMeta,\n}: PageHeadProps) {\n const fullTitle =\n productName && !title.includes(productName)\n ? `${title} | ${productName}`\n : title;\n\n const fullImageUrl =\n image && !image.startsWith(\"http\") && url\n ? `${url.replace(/\\/$/, \"\")}${image}`\n : image;\n\n // Normalize structured data to an array\n const structuredDataItems: Array<Record<string, unknown>> = structuredData\n ? Array.isArray(structuredData)\n ? structuredData\n : [structuredData]\n : [];\n\n return (\n <Helmet>\n {/* Primary Meta Tags */}\n <title>{fullTitle}</title>\n <meta name=\"title\" content={fullTitle} />\n {description && <meta name=\"description\" content={description} />}\n {keywords && <meta name=\"keywords\" content={keywords} />}\n <meta name=\"author\" content=\"Burdenoff Consultancy Services Pvt Ltd\" />\n <meta name=\"robots\" content={robots} />\n\n {/* Canonical URL */}\n {url && <link rel=\"canonical\" href={url} />}\n\n {/* Favicon */}\n {favicon && <link rel=\"icon\" href={favicon} />}\n\n {/* Open Graph / Facebook */}\n <meta property=\"og:type\" content=\"website\" />\n <meta property=\"og:title\" content={fullTitle} />\n {description && <meta property=\"og:description\" content={description} />}\n {fullImageUrl && <meta property=\"og:image\" content={fullImageUrl} />}\n {url && <meta property=\"og:url\" content={url} />}\n <meta property=\"og:locale\" content={locale} />\n {productName && <meta property=\"og:site_name\" content={productName} />}\n\n {/* Twitter Card */}\n <meta name=\"twitter:card\" content=\"summary_large_image\" />\n <meta name=\"twitter:title\" content={fullTitle} />\n {description && <meta name=\"twitter:description\" content={description} />}\n {fullImageUrl && <meta name=\"twitter:image\" content={fullImageUrl} />}\n {twitterHandle && <meta name=\"twitter:creator\" content={twitterHandle} />}\n\n {/* Theme Color */}\n <meta name=\"theme-color\" content={themeColor} />\n\n {/* JSON-LD Structured Data */}\n {structuredDataItems.map((data, index) => (\n <script key={`ld-${index}`} type=\"application/ld+json\">\n {JSON.stringify(data)}\n </script>\n ))}\n\n {/* Additional Meta Tags */}\n {additionalMeta?.map((meta, index) => (\n <meta\n key={`meta-${index}`}\n {...(meta.name ? { name: meta.name } : {})}\n {...(meta.property ? { property: meta.property } : {})}\n content={meta.content}\n />\n ))}\n </Helmet>\n );\n}\n","/**\n * Utility function to merge Tailwind CSS classes\n * Combines clsx and tailwind-merge for optimal class handling\n */\n\nimport { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge multiple class names intelligently\n * - Handles conditional classes via clsx\n * - Deduplicates and resolves Tailwind conflicts via tailwind-merge\n *\n * @example\n * ```ts\n * cn('px-4 py-2', 'bg-blue-500', { 'text-white': isActive })\n * // => 'px-4 py-2 bg-blue-500 text-white' (if isActive is true)\n * ```\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\n\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"../utils/cn\";\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground shadow hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90\",\n outline:\n \"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2\",\n sm: \"h-8 rounded-md px-3 text-xs\",\n lg: \"h-10 rounded-md px-8\",\n icon: \"h-9 w-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nexport interface ButtonProps\n extends\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\";\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, className }))}\n ref={ref}\n {...props}\n />\n );\n },\n);\nButton.displayName = \"Button\";\n\nexport { Button, buttonVariants };\n","/**\n * Pricing Component\n * GraphQL-powered pricing component with quota-based features and monthly/yearly toggle\n *\n * @example\n * ```tsx\n * import { PricingPage, PricingSection } from '@burdenoff/website-sdk/components/pricing'\n *\n * // Full page with hero\n * <PricingPage\n * productName=\"BigConsole\"\n * productId=\"bigconsole-123\"\n * appLoginUrl=\"https://app.bigconsole.com/login\"\n * contactUrl=\"/contact\"\n * fallbackFeatures={{\n * basic: ['Up to 5 dashboards', '10 data sources'],\n * professional: ['Unlimited dashboards', 'API access'],\n * enterprise: ['Everything in Professional', 'Dedicated support']\n * }}\n * />\n *\n * // Embeddable section\n * <PricingSection {...props} id=\"pricing\" className=\"bg-muted/30\" />\n * ```\n */\n\n\"use client\";\n\nimport { useEffect, useState } from \"react\";\n\nimport { useWebSDK, useWebSDKConfig } from \"../client/provider\";\nimport { PageHead } from \"../seo/page-head\";\nimport { Button } from \"../ui/button\";\n\n// ============================================================================\n// GRAPHQL QUERY\n// ============================================================================\n\nconst GET_PLANS_QUERY = `\n query GetPublicPlans($productId: String!) {\n publicPlans(productId: $productId) {\n id\n name\n price\n currency\n currencyPrices\n duration\n features {\n id\n quotaId\n quota {\n id\n name\n limits\n }\n }\n isActive\n productID\n createdAt\n }\n }\n`;\n\n// ============================================================================\n// TYPES & INTERFACES\n// ============================================================================\n\ninterface PlanFeature {\n id: string;\n quotaId?: string | null;\n quota?: {\n id: string;\n name: string;\n limits?: unknown;\n } | null;\n}\n\ninterface GatewayPlan {\n id: string;\n name: string;\n price: number;\n currency: string;\n currencyPrices?: Record<string, number> | null;\n duration: string;\n features: PlanFeature[];\n isActive: boolean;\n productID?: string | null;\n createdAt: string;\n}\n\ninterface GetPlansResponse {\n publicPlans: GatewayPlan[];\n}\n\nexport interface PlanCard {\n id: string;\n name: string;\n price: number;\n currency: string;\n currencyPrices?: Record<string, number> | null;\n duration: string;\n features: Array<{\n id: string;\n quotaId?: string | null;\n quota?: {\n id: string;\n name: string;\n limits?: unknown;\n } | null;\n }>;\n isActive: boolean;\n productID?: string | null;\n}\n\ninterface CurrencyConfig {\n code: string;\n symbol: string;\n position: \"prefix\" | \"suffix\";\n}\n\ninterface PlanMetadata {\n tier: \"basic\" | \"professional\" | \"enterprise\";\n displayName: string;\n defaultDescription: string;\n popular: boolean;\n ctaText: string;\n ctaType: \"signup\" | \"contact\";\n}\n\nexport interface PricingProps {\n /**\n * Product name (used in branding and SEO)\n */\n productName?: string;\n /**\n * Product ID for GraphQL query (falls back to WebSDKConfig.productId)\n */\n productId?: string;\n /**\n * App login URL for signup CTA\n */\n appLoginUrl: string;\n /**\n * Contact page URL for enterprise CTA\n * @default '/contact'\n */\n contactUrl?: string;\n /**\n * Supported currencies\n */\n currencies?: Record<string, CurrencyConfig>;\n /**\n * Billing interval display text\n */\n billingIntervals?: Record<string, string>;\n /**\n * Plan metadata (tier info, CTA text, etc.)\n */\n planMetadata?: Record<string, Partial<PlanMetadata>>;\n /**\n * Fallback features when API doesn't provide them or is unavailable\n */\n fallbackFeatures?: {\n basic?: string[];\n professional?: string[];\n enterprise?: string[];\n };\n /**\n * Hero section heading (for PricingPage)\n * @default 'Simple, Transparent Pricing'\n */\n heroHeading?: string;\n /**\n * Hero section subtitle (for PricingPage)\n * @default \"Choose the plan that's right for you. No hidden fees, no surprises.\"\n */\n heroSubtitle?: string;\n /**\n * Section heading (for PricingSection)\n * @default 'Pricing Plans'\n */\n sectionHeading?: string;\n /**\n * Section subtitle (for PricingSection)\n * @default 'Choose the perfect plan for your needs'\n */\n sectionSubtitle?: string;\n /**\n * Custom CSS class\n */\n className?: string;\n /**\n * Section ID for anchor links\n */\n id?: string;\n /**\n * SEO: Page title (optional, for PricingPage)\n */\n seoTitle?: string;\n /**\n * SEO: Page description (optional, for PricingPage)\n */\n seoDescription?: string;\n /**\n * SEO: Keywords (optional, for PricingPage)\n */\n seoKeywords?: string;\n /**\n * SEO: OG Image URL (optional, for PricingPage)\n */\n seoImage?: string;\n /**\n * SEO: Canonical URL (optional, for PricingPage)\n */\n seoUrl?: string;\n}\n\n// ============================================================================\n// SERVICE FUNCTIONS\n// ============================================================================\n\n/**\n * Format price for display with currency symbol\n */\nfunction formatPrice(\n price: number,\n currencyCode: string = \"USD\",\n currencies?: Record<string, CurrencyConfig>,\n): string {\n const defaultCurrencies: Record<string, CurrencyConfig> = {\n USD: { code: \"USD\", symbol: \"$\", position: \"prefix\" },\n EUR: { code: \"EUR\", symbol: \"\\u20AC\", position: \"prefix\" },\n GBP: { code: \"GBP\", symbol: \"\\u00A3\", position: \"prefix\" },\n INR: { code: \"INR\", symbol: \"\\u20B9\", position: \"prefix\" },\n };\n\n const currencyMap = currencies || defaultCurrencies;\n const currency: CurrencyConfig = currencyMap[currencyCode] || {\n code: currencyCode,\n symbol: currencyCode,\n position: \"prefix\",\n };\n\n const formattedNumber = price % 1 === 0 ? price.toString() : price.toFixed(2);\n\n return currency.position === \"prefix\"\n ? `${currency.symbol}${formattedNumber}`\n : `${formattedNumber}${currency.symbol}`;\n}\n\n/**\n * Format billing interval for display\n */\nfunction formatInterval(\n duration: string,\n billingIntervals?: Record<string, string>,\n): string {\n const defaultIntervals: Record<string, string> = {\n monthly: \"/month\",\n yearly: \"/year\",\n };\n\n const intervals = billingIntervals || defaultIntervals;\n return intervals[duration] || `/${duration}`;\n}\n\n/**\n * Detect plan tier from plan name\n */\nfunction detectPlanTier(\n planName: string,\n): \"basic\" | \"professional\" | \"enterprise\" | null {\n const name = planName.toLowerCase();\n\n if (name.includes(\"basic\") || name.includes(\"starter\")) {\n return \"basic\";\n } else if (\n name.includes(\"pro\") ||\n name.includes(\"professional\") ||\n name.includes(\"premium\")\n ) {\n return \"professional\";\n } else if (name.includes(\"enterprise\") || name.includes(\"business\")) {\n return \"enterprise\";\n }\n\n return null;\n}\n\n/**\n * Get features for a specific plan tier from fallback config\n */\nfunction getFallbackFeaturesForTier(\n tier: \"basic\" | \"professional\" | \"enterprise\",\n fallbackFeatures?: {\n basic?: string[];\n professional?: string[];\n enterprise?: string[];\n },\n): string[] {\n return [...(fallbackFeatures?.[tier] || [])];\n}\n\n/**\n * Get metadata for a plan by name\n */\nfunction getMetadataForPlan(\n planName: string,\n planMetadata?: Record<string, Partial<PlanMetadata>>,\n): PlanMetadata {\n const normalizedName = planName.toLowerCase();\n\n // Try exact match first\n if (planMetadata?.[normalizedName]) {\n const meta = planMetadata[normalizedName];\n return {\n tier: meta.tier || \"basic\",\n displayName: meta.displayName || planName,\n defaultDescription: meta.defaultDescription || \"Choose this plan\",\n popular: meta.popular ?? false,\n ctaText: meta.ctaText || \"Get Started\",\n ctaType: meta.ctaType || \"signup\",\n };\n }\n\n // Try tier detection\n const tier = detectPlanTier(planName);\n if (tier) {\n return {\n tier,\n displayName: planName,\n defaultDescription: \"Choose this plan\",\n popular: tier === \"professional\",\n ctaText: tier === \"enterprise\" ? \"Contact Sales\" : \"Get Started\",\n ctaType: tier === \"enterprise\" ? \"contact\" : \"signup\",\n };\n }\n\n // Fallback\n return {\n tier: \"basic\",\n displayName: planName,\n defaultDescription: \"Choose this plan\",\n popular: false,\n ctaText: \"Get Started\",\n ctaType: \"signup\",\n };\n}\n\n/**\n * Transform quota limits to a human-readable feature string\n */\n/**\n * Derive a human-readable label from a dotted quota name.\n * e.g. \"vibecontrols.workspaces.count\" → \"Workspaces\"\n * \"vibecontrols.storage.bytes\" → \"Storage\"\n */\nfunction humanizeQuotaName(name: string): string {\n const parts = name.split(\".\");\n // Use the second-to-last segment (the resource), or fall back to the last\n const resource = parts.length >= 3 ? parts[parts.length - 2]! : parts[parts.length - 1]!;\n // Capitalize and replace hyphens/underscores with spaces\n return resource\n .replace(/[-_]/g, \" \")\n .replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n\nfunction transformQuotaToFeature(quota: {\n id: string;\n name: string;\n limits?: unknown;\n}): string {\n const { name, limits } = quota;\n\n if (!limits || typeof limits !== \"object\") {\n return humanizeQuotaName(name);\n }\n\n const limitsObj = limits as Record<string, unknown>;\n const value = limitsObj.value;\n const unit = limitsObj.unit;\n const type = limitsObj.type;\n const description = limitsObj.description;\n\n // Use explicit description if provided\n if (typeof description === \"string\" && description) {\n if (type === \"number\" && typeof value === \"number\") {\n return `${value.toLocaleString()} ${description}`;\n }\n return description;\n }\n\n // Use unit if provided\n if (typeof unit === \"string\" && unit) {\n if (typeof value === \"number\") {\n return `${value.toLocaleString()} ${unit}`;\n }\n return `${unit}`;\n }\n\n // Derive label from quota name\n const label = humanizeQuotaName(name);\n\n if (type === \"boolean\") {\n return label;\n }\n\n if (typeof value === \"number\") {\n return `${value.toLocaleString()} ${label}`;\n }\n\n return label;\n}\n\n/**\n * Extract display features from a plan's feature list\n */\nfunction extractDisplayFeatures(\n features: PlanFeature[],\n planName: string,\n fallbackFeatures?: {\n basic?: string[];\n professional?: string[];\n enterprise?: string[];\n },\n): string[] {\n // If API provides features with quotas, transform them\n const quotaFeatures = features\n .filter((f) => f.quota)\n .map((f) => transformQuotaToFeature(f.quota!));\n\n if (quotaFeatures.length > 0) {\n return quotaFeatures;\n }\n\n // Fall back to tier-based features\n const tier = detectPlanTier(planName);\n if (tier) {\n return getFallbackFeaturesForTier(tier, fallbackFeatures);\n }\n\n return [];\n}\n\n// ============================================================================\n// UI CARD TYPE (internal)\n// ============================================================================\n\ninterface DisplayPlanCard {\n id: string;\n name: string;\n description: string;\n price: string;\n priceRaw: number;\n interval: string;\n duration: string;\n features: string[];\n popular: boolean;\n ctaText: string;\n ctaLink: string;\n tier: \"basic\" | \"professional\" | \"enterprise\" | null;\n}\n\n/**\n * Transform a GatewayPlan into a display card\n */\nfunction transformToDisplayCard(\n plan: GatewayPlan,\n props: PricingProps,\n): DisplayPlanCard {\n const metadata = getMetadataForPlan(plan.name, props.planMetadata);\n\n const formattedPrice = formatPrice(\n plan.price,\n plan.currency,\n props.currencies,\n );\n const interval = formatInterval(plan.duration, props.billingIntervals);\n\n const features = extractDisplayFeatures(\n plan.features,\n plan.name,\n props.fallbackFeatures,\n );\n\n const contactUrl = props.contactUrl || \"/contact\";\n const ctaLink =\n metadata.ctaType === \"contact\" ? contactUrl : props.appLoginUrl;\n\n return {\n id: plan.id,\n name: plan.name,\n description: metadata.defaultDescription,\n price: formattedPrice,\n priceRaw: plan.price,\n interval,\n duration: plan.duration,\n features,\n popular: metadata.popular,\n ctaText: metadata.ctaText,\n ctaLink,\n tier: metadata.tier,\n };\n}\n\n// ============================================================================\n// REACT COMPONENTS\n// ============================================================================\n\n/**\n * Pricing Section Component - Embeddable\n */\nexport function PricingSection(props: PricingProps) {\n const {\n sectionHeading = \"Pricing Plans\",\n sectionSubtitle = \"Choose the perfect plan for your needs\",\n id,\n className = \"\",\n } = props;\n\n const client = useWebSDK();\n const config = useWebSDKConfig();\n\n const resolvedProductId = props.productId || config.productId;\n\n const [allPlans, setAllPlans] = useState<DisplayPlanCard[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [billingCycle, setBillingCycle] = useState<\"monthly\" | \"yearly\">(\n \"monthly\",\n );\n\n useEffect(() => {\n let cancelled = false;\n\n async function loadPlans() {\n try {\n setLoading(true);\n\n const response = await client.query<GetPlansResponse>(\n GET_PLANS_QUERY,\n { productId: resolvedProductId },\n );\n\n if (cancelled) return;\n\n if (response.errors && response.errors.length > 0) {\n throw new Error(response.errors[0]!.message);\n }\n\n if (!response.data?.publicPlans) {\n throw new Error(\"No plans data received\");\n }\n\n // Server already filters by productId — just filter active, transform, sort\n const cards = response.data.publicPlans\n .filter((plan) => plan.isActive)\n .map((plan) => transformToDisplayCard(plan, props))\n .sort((a, b) => a.priceRaw - b.priceRaw);\n\n setAllPlans(cards);\n setError(null);\n } catch (err) {\n if (cancelled) return;\n console.error(\"Failed to load plans:\", err);\n setError(\"Unable to load pricing information. Please try again later.\");\n } finally {\n if (!cancelled) {\n setLoading(false);\n }\n }\n }\n\n loadPlans();\n\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- props is destructured, actual deps are client + productId\n }, [client, resolvedProductId]);\n\n // Filter plans based on selected billing cycle\n const plans = allPlans.filter((plan) =>\n billingCycle === \"monthly\"\n ? plan.duration === \"monthly\"\n : plan.duration === \"yearly\",\n );\n\n if (loading) {\n return (\n <section id={id} className={`py-12 sm:py-16 md:py-20 ${className}`}>\n <div className=\"container mx-auto px-4 sm:px-6\">\n <div className=\"text-center mb-8 sm:mb-12\">\n <h2 className=\"text-2xl sm:text-3xl md:text-4xl font-bold mb-3 sm:mb-4\">\n {sectionHeading}\n </h2>\n <p className=\"text-muted-foreground text-sm sm:text-base md:text-lg\">\n Loading pricing information...\n </p>\n </div>\n <div className=\"grid md:grid-cols-3 gap-6 sm:gap-8\">\n {[1, 2, 3].map((i) => (\n <div\n key={i}\n className=\"bg-card border rounded-lg p-6 animate-pulse\"\n >\n <div className=\"h-6 bg-muted rounded w-1/2 mb-4\"></div>\n <div className=\"h-4 bg-muted rounded w-3/4 mb-6\"></div>\n <div className=\"h-10 bg-muted rounded w-1/3 mb-6\"></div>\n <div className=\"space-y-3 mb-6\">\n {[1, 2, 3, 4].map((j) => (\n <div key={j} className=\"h-4 bg-muted rounded\"></div>\n ))}\n </div>\n <div className=\"h-10 bg-muted rounded\"></div>\n </div>\n ))}\n </div>\n </div>\n </section>\n );\n }\n\n if (error && plans.length === 0) {\n return (\n <section id={id} className={`py-12 sm:py-16 md:py-20 ${className}`}>\n <div className=\"container mx-auto px-4 sm:px-6\">\n <div className=\"text-center\">\n <h2 className=\"text-2xl sm:text-3xl md:text-4xl font-bold mb-4\">\n {sectionHeading}\n </h2>\n <p className=\"text-muted-foreground mb-8\">{error}</p>\n <Button onClick={() => window.location.reload()}>Retry</Button>\n </div>\n </div>\n </section>\n );\n }\n\n return (\n <section id={id} className={`py-12 sm:py-16 md:py-20 ${className}`}>\n <div className=\"container mx-auto px-4 sm:px-6\">\n <div className=\"text-center mb-8 sm:mb-12\">\n <h2 className=\"text-2xl sm:text-3xl md:text-4xl font-bold mb-3 sm:mb-4\">\n {sectionHeading}\n </h2>\n <p className=\"text-muted-foreground text-sm sm:text-base md:text-lg mb-6\">\n {sectionSubtitle}\n </p>\n\n {/* Billing Cycle Toggle */}\n <div className=\"inline-flex items-center gap-3 bg-muted p-1.5 rounded-lg\">\n <button\n onClick={() => setBillingCycle(\"monthly\")}\n className={`px-6 py-2 rounded-md text-sm font-medium transition-all ${\n billingCycle === \"monthly\"\n ? \"bg-background shadow-sm text-foreground\"\n : \"text-muted-foreground hover:text-foreground\"\n }`}\n >\n Monthly\n </button>\n <button\n onClick={() => setBillingCycle(\"yearly\")}\n className={`px-6 py-2 rounded-md text-sm font-medium transition-all ${\n billingCycle === \"yearly\"\n ? \"bg-background shadow-sm text-foreground\"\n : \"text-muted-foreground hover:text-foreground\"\n }`}\n >\n Yearly\n </button>\n </div>\n </div>\n\n <div className=\"grid md:grid-cols-3 gap-6 sm:gap-8 max-w-6xl mx-auto items-stretch\">\n {plans.map((plan) => (\n <div\n key={plan.id}\n className={`bg-card rounded-xl p-6 sm:p-8 transition-all duration-300 flex flex-col ${\n plan.popular\n ? \"border-2 border-primary shadow-xl ring-1 ring-primary/20\"\n : \"border hover:shadow-lg hover:border-primary/50\"\n }`}\n >\n <div className=\"text-center mb-6\">\n {plan.popular && (\n <span className=\"inline-block bg-primary text-primary-foreground px-4 py-1 rounded-full text-xs font-semibold mb-3\">\n Most Popular\n </span>\n )}\n <h3 className=\"text-xl sm:text-2xl font-bold mb-2\">\n {plan.name}\n </h3>\n <p className=\"text-muted-foreground text-sm\">\n {plan.description}\n </p>\n </div>\n\n <div className=\"text-center mb-8\">\n <div className=\"flex items-baseline justify-center gap-1\">\n <span className=\"text-4xl sm:text-5xl font-bold\">\n {plan.price}\n </span>\n <span className=\"text-muted-foreground text-lg\">\n {plan.interval}\n </span>\n </div>\n </div>\n\n <ul className=\"space-y-3 mb-8 flex-1\">\n {plan.features.map((feature, index) => (\n <li key={index} className=\"text-sm flex items-start gap-2\">\n <span className=\"text-primary mt-0.5 flex-shrink-0\">\n ✓\n </span>\n <span>{feature}</span>\n </li>\n ))}\n </ul>\n\n {plan.ctaLink.startsWith(\"/\") ? (\n <Button\n className=\"w-full h-11\"\n variant={plan.popular ? \"default\" : \"outline\"}\n size=\"lg\"\n asChild\n >\n <a\n href={plan.ctaLink}\n onClick={() =>\n window.scrollTo({ top: 0, behavior: \"smooth\" })\n }\n >\n {plan.ctaText}\n </a>\n </Button>\n ) : (\n <Button\n className=\"w-full h-11\"\n variant={plan.popular ? \"default\" : \"outline\"}\n size=\"lg\"\n asChild\n >\n <a\n href={plan.ctaLink}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {plan.ctaText}\n </a>\n </Button>\n )}\n </div>\n ))}\n </div>\n </div>\n </section>\n );\n}\n\n/**\n * Pricing Page Component - Full Page with Hero\n */\nexport function PricingPage(props: PricingProps) {\n const {\n productName,\n heroHeading = \"Simple, Transparent Pricing\",\n heroSubtitle = \"Choose the plan that's right for you. No hidden fees, no surprises.\",\n seoTitle,\n seoDescription,\n seoKeywords,\n seoImage,\n seoUrl,\n } = props;\n\n return (\n <div className=\"w-full\">\n {/* SEO Meta Tags */}\n {seoTitle && (\n <PageHead\n title={seoTitle}\n description={seoDescription || heroSubtitle}\n productName={productName}\n keywords={seoKeywords}\n image={seoImage}\n url={seoUrl}\n />\n )}\n\n {/* Hero Section */}\n <section className=\"bg-gradient-to-b from-background to-muted/20 py-12 sm:py-16 md:py-20 lg:py-24\">\n <div className=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8\">\n <div className=\"text-center max-w-3xl mx-auto\">\n <h1 className=\"text-3xl sm:text-4xl md:text-5xl font-bold mb-4 sm:mb-6\">\n {heroHeading}\n </h1>\n <p className=\"text-lg sm:text-xl text-muted-foreground leading-relaxed\">\n {heroSubtitle}\n </p>\n </div>\n </div>\n </section>\n\n {/* Pricing Section */}\n <PricingSection {...props} />\n </div>\n );\n}\n"]}
|
|
@@ -347,27 +347,41 @@ function getMetadataForPlan(planName, planMetadata) {
|
|
|
347
347
|
ctaType: "signup"
|
|
348
348
|
};
|
|
349
349
|
}
|
|
350
|
+
function humanizeQuotaName(name) {
|
|
351
|
+
const parts = name.split(".");
|
|
352
|
+
const resource = parts.length >= 3 ? parts[parts.length - 2] : parts[parts.length - 1];
|
|
353
|
+
return resource.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
354
|
+
}
|
|
350
355
|
function transformQuotaToFeature(quota) {
|
|
351
356
|
const { name, limits } = quota;
|
|
352
357
|
if (!limits || typeof limits !== "object") {
|
|
353
|
-
return name;
|
|
358
|
+
return humanizeQuotaName(name);
|
|
354
359
|
}
|
|
355
360
|
const limitsObj = limits;
|
|
356
361
|
const value = limitsObj.value;
|
|
357
362
|
const unit = limitsObj.unit;
|
|
358
363
|
const type = limitsObj.type;
|
|
359
364
|
const description = limitsObj.description;
|
|
360
|
-
if (
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
return
|
|
365
|
+
if (typeof description === "string" && description) {
|
|
366
|
+
if (type === "number" && typeof value === "number") {
|
|
367
|
+
return `${value.toLocaleString()} ${description}`;
|
|
368
|
+
}
|
|
369
|
+
return description;
|
|
370
|
+
}
|
|
371
|
+
if (typeof unit === "string" && unit) {
|
|
372
|
+
if (typeof value === "number") {
|
|
373
|
+
return `${value.toLocaleString()} ${unit}`;
|
|
374
|
+
}
|
|
375
|
+
return `${unit}`;
|
|
376
|
+
}
|
|
377
|
+
const label = humanizeQuotaName(name);
|
|
378
|
+
if (type === "boolean") {
|
|
379
|
+
return label;
|
|
365
380
|
}
|
|
366
381
|
if (typeof value === "number") {
|
|
367
|
-
|
|
368
|
-
return `${name}: ${formattedValue} ${unit || ""}`.trim();
|
|
382
|
+
return `${value.toLocaleString()} ${label}`;
|
|
369
383
|
}
|
|
370
|
-
return
|
|
384
|
+
return label;
|
|
371
385
|
}
|
|
372
386
|
function extractDisplayFeatures(features, planName, fallbackFeatures) {
|
|
373
387
|
const quotaFeatures = features.filter((f) => f.quota).map((f) => transformQuotaToFeature(f.quota));
|