UNPKG

autumn-js

Version:

Autumn JS Library

707 lines (701 loc) 26 kB
"use client"; import { getAttachContent } from "./chunk-O6TAJHK3.mjs"; import { getPricingTableContent } from "./chunk-URQMBRFZ.mjs"; import { Input } from "./chunk-GUM4HIGI.mjs"; import { Popover, PopoverContent, PopoverTrigger } from "./chunk-UM3ZQPMU.mjs"; import { Switch } from "./chunk-6EZVNJHQ.mjs"; import { loadingStyles, spinnerStyles } from "./chunk-WVKYZYFT.mjs"; import { Button } from "./chunk-EV5RNY5U.mjs"; import { Dialog, DialogContent, DialogFooter, DialogTitle } from "./chunk-JPLUWGH4.mjs"; import { Accordion, AccordionContent, AccordionItem } from "./chunk-JGRLRPKG.mjs"; import { ArrowRight, ChevronDown, LoaderCircle } from "./chunk-QJPZFEVW.mjs"; import { usePricingTable } from "./chunk-OTYSAMRH.mjs"; import { cn } from "./chunk-4J6OC4ZQ.mjs"; import { useCustomer } from "./chunk-4CHWEUKX.mjs"; // src/libraries/react/components/pricing-table/pricing-table-synced.tsx import React2 from "react"; // src/libraries/react/components/attach-dialog/attach-dialog-synced.tsx import * as AccordionPrimitive from "@radix-ui/react-accordion"; import { useEffect, useState } from "react"; import { Fragment, jsx, jsxs } from "react/jsx-runtime"; var formatCurrency = ({ amount, currency }) => { return new Intl.NumberFormat("en-US", { style: "currency", currency }).format(amount); }; function AttachDialog(params) { const { attach } = useCustomer(); const [checkoutResult, setCheckoutResult] = useState(params?.checkoutResult); useEffect(() => { if (params.checkoutResult) { setCheckoutResult(params.checkoutResult); } }, [params.checkoutResult]); const [loading, setLoading] = useState(false); if (!checkoutResult) { return /* @__PURE__ */ jsx(Fragment, {}); } const { open, setOpen } = params; const { title, message } = getAttachContent(checkoutResult); const isFree = checkoutResult?.product.properties?.is_free; const isPaid = isFree === false; return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: "au-p-0 au-pt-4 au-gap-0 au-text-foreground au-overflow-hidden au-text-sm", children: [ /* @__PURE__ */ jsx(DialogTitle, { className: "au-px-6 au-mb-1", children: title }), /* @__PURE__ */ jsx("div", { className: "au-px-6 au-mt-1 au-mb-4 au-text-muted-foreground", children: message }), isPaid && checkoutResult && /* @__PURE__ */ jsx( PriceInformation, { checkoutResult, setCheckoutResult } ), /* @__PURE__ */ jsx(DialogFooter, { className: "au-flex au-flex-col sm:au-flex-row au-justify-between au-gap-x-4 au-py-2 au-pl-6 au-pr-3 au-bg-secondary au-border-t au-shadow-inner", children: /* @__PURE__ */ jsx( Button, { size: "sm", onClick: async () => { setLoading(true); const options = checkoutResult.options.map((option) => { return { featureId: option.feature_id, quantity: option.quantity }; }); await attach({ productId: checkoutResult.product.id, options }); setOpen(false); setLoading(false); }, disabled: loading, className: "au-min-w-16 au-flex au-items-center au-gap-2", children: loading ? /* @__PURE__ */ jsx(LoaderCircle, { className: "au-w-4 au-h-4 au-animate-spin" }) : /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx("span", { className: "au-whitespace-nowrap au-flex au-gap-1", children: "Confirm" }) }) } ) }) ] }) }); } function PriceInformation({ checkoutResult, setCheckoutResult }) { return /* @__PURE__ */ jsxs("div", { className: "au-px-6 au-mb-4 au-flex au-flex-col au-gap-4", children: [ /* @__PURE__ */ jsx( ProductItems, { checkoutResult, setCheckoutResult } ), /* @__PURE__ */ jsxs("div", { className: "au-flex au-flex-col au-gap-2", children: [ checkoutResult?.has_prorations && checkoutResult.lines.length > 0 && /* @__PURE__ */ jsx(CheckoutLines, { checkoutResult }), /* @__PURE__ */ jsx(DueAmounts, { checkoutResult }) ] }) ] }); } function DueAmounts({ checkoutResult }) { const { next_cycle, product } = checkoutResult; const nextCycleAtStr = next_cycle ? new Date(next_cycle.starts_at).toLocaleDateString() : void 0; const hasUsagePrice = product.items.some( (item) => item.usage_model === "pay_per_use" ); const showNextCycle = next_cycle && next_cycle.total !== checkoutResult.total; return /* @__PURE__ */ jsxs("div", { className: "au-flex au-flex-col au-gap-1", children: [ /* @__PURE__ */ jsxs("div", { className: "au-flex au-justify-between", children: [ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("p", { className: "au-font-medium au-text-md", children: "Total due today" }) }), /* @__PURE__ */ jsx("p", { className: "au-font-medium au-text-md", children: formatCurrency({ amount: checkoutResult?.total, currency: checkoutResult?.currency }) }) ] }), showNextCycle && /* @__PURE__ */ jsxs("div", { className: "au-flex au-justify-between au-text-muted-foreground", children: [ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs("p", { className: "au-text-md", children: [ "Due next cycle (", nextCycleAtStr, ")" ] }) }), /* @__PURE__ */ jsxs("p", { className: "au-text-md", children: [ formatCurrency({ amount: next_cycle.total, currency: checkoutResult?.currency }), hasUsagePrice && /* @__PURE__ */ jsx("span", { children: " + usage prices" }) ] }) ] }) ] }); } function ProductItems({ checkoutResult, setCheckoutResult }) { const isUpdateQuantity = checkoutResult?.product.scenario === "active" && checkoutResult.product.properties.updateable; return /* @__PURE__ */ jsxs("div", { className: "au-flex au-flex-col au-gap-2", children: [ /* @__PURE__ */ jsx("p", { className: "au-text-sm au-font-medium", children: "Price" }), checkoutResult?.product.items.filter((item) => item.type !== "feature").map((item, index) => { if (item.usage_model == "prepaid") { return /* @__PURE__ */ jsx( PrepaidItem, { item, checkoutResult, setCheckoutResult }, index ); } if (isUpdateQuantity) { return null; } return /* @__PURE__ */ jsxs("div", { className: "au-flex au-justify-between", children: [ /* @__PURE__ */ jsx("p", { className: "au-text-muted-foreground", children: item.feature ? item.feature.name : "Subscription" }), /* @__PURE__ */ jsxs("p", { children: [ item.display?.primary_text, " ", item.display?.secondary_text ] }) ] }, index); }) ] }); } function CheckoutLines({ checkoutResult }) { return /* @__PURE__ */ jsx(Accordion, { type: "single", collapsible: true, children: /* @__PURE__ */ jsxs(AccordionItem, { value: "total", className: "au-border-b-0", children: [ /* @__PURE__ */ jsx(CustomAccordionTrigger, { className: "au-justify-between au-w-full au-my-0 au-py-0 au-border-none", children: /* @__PURE__ */ jsxs("div", { className: "au-cursor-pointer au-flex au-items-center au-gap-1 au-w-full au-justify-end", children: [ /* @__PURE__ */ jsx("p", { className: "au-font-light au-text-muted-foreground", children: "View details" }), /* @__PURE__ */ jsx( ChevronDown, { className: "au-text-muted-foreground au-mt-0.5 au-rotate-90 au-transition-transform au-duration-200 au-ease-in-out", size: 14 } ) ] }) }), /* @__PURE__ */ jsx(AccordionContent, { className: "au-mt-2 au-mb-0 au-pb-2 au-flex au-flex-col au-gap-2", children: checkoutResult?.lines.filter((line) => line.amount != 0).map((line, index) => { return /* @__PURE__ */ jsxs("div", { className: "au-flex au-justify-between", children: [ /* @__PURE__ */ jsx("p", { className: "au-text-muted-foreground", children: line.description }), /* @__PURE__ */ jsx("p", { className: "au-text-muted-foreground", children: new Intl.NumberFormat("en-US", { style: "currency", currency: checkoutResult?.currency }).format(line.amount) }) ] }, index); }) }) ] }) }); } function CustomAccordionTrigger({ className, children, ...props }) { return /* @__PURE__ */ jsx(AccordionPrimitive.Header, { className: "au-flex", children: /* @__PURE__ */ jsx( AccordionPrimitive.Trigger, { "data-slot": "accordion-trigger", className: cn( "focus-visible:au-border-ring focus-visible:au-ring-ring/50 au-flex au-flex-1 au-items-start au-justify-between au-gap-4 au-rounded-md au-py-4 au-text-left au-text-sm au-font-medium au-transition-all au-outline-none focus-visible:au-ring-[3px] disabled:au-pointer-events-none disabled:au-opacity-50 [&[data-state=open]_svg]:au-rotate-0", className ), ...props, children } ) }); } var PrepaidItem = ({ item, checkoutResult, setCheckoutResult }) => { const { quantity = 0, billing_units: billingUnits = 1 } = item; const [quantityInput, setQuantityInput] = useState( (quantity / billingUnits).toString() ); const { checkout } = useCustomer(); const [loading, setLoading] = useState(false); const [open, setOpen] = useState(false); const scenario = checkoutResult.product.scenario; const handleSave = async () => { setLoading(true); try { const newOptions = checkoutResult.options.filter((option) => option.feature_id !== item.feature_id).map((option) => { return { featureId: option.feature_id, quantity: option.quantity }; }); newOptions.push({ featureId: item.feature_id, quantity: Number(quantityInput) * billingUnits }); const { data, error } = await checkout({ productId: checkoutResult.product.id, options: newOptions }); if (error) { console.error(error); return; } setCheckoutResult(data); } catch (error) { console.error(error); } finally { setLoading(false); setOpen(false); } }; const disableSelection = scenario === "renew"; return /* @__PURE__ */ jsxs("div", { className: "au-flex au-justify-between", children: [ /* @__PURE__ */ jsxs("div", { className: "au-flex au-gap-2", children: [ /* @__PURE__ */ jsx("p", { className: "au-text-muted-foreground", children: item.feature?.name }), /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [ /* @__PURE__ */ jsxs( PopoverTrigger, { className: cn( "au-text-muted-foreground au-text-xs au-px-1 au-py-0.5 au-rounded-md au-flex au-items-center au-gap-1 au-bg-accent/80", disableSelection !== true && "hover:au-bg-accent hover:au-text-foreground" ), disabled: disableSelection, children: [ "Qty: ", quantity, /* @__PURE__ */ jsx(ChevronDown, { size: 12 }) ] } ), /* @__PURE__ */ jsxs( PopoverContent, { align: "start", className: "au-w-80 au-text-sm au-p-4 au-pt-3 au-flex au-flex-col au-gap-4", children: [ /* @__PURE__ */ jsxs("div", { className: "au-flex au-flex-col au-gap-1", children: [ /* @__PURE__ */ jsx("p", { className: "au-text-sm au-font-medium", children: item.feature?.name }), /* @__PURE__ */ jsxs("p", { className: "au-text-muted-foreground", children: [ item.display?.primary_text, " ", item.display?.secondary_text ] }) ] }), /* @__PURE__ */ jsxs("div", { className: "au-flex au-justify-between au-items-end", children: [ /* @__PURE__ */ jsxs("div", { className: "au-flex au-gap-2 au-items-center", children: [ /* @__PURE__ */ jsx( Input, { className: "au-h-7 au-w-16 focus:!au-ring-2", value: quantityInput, onChange: (e) => setQuantityInput(e.target.value) } ), /* @__PURE__ */ jsxs("p", { className: "au-text-muted-foreground", children: [ billingUnits > 1 && `x ${billingUnits} `, item.feature?.name ] }) ] }), /* @__PURE__ */ jsx( Button, { onClick: handleSave, className: "au-w-14 !au-h-7 au-text-sm au-items-center au-bg-white au-text-foreground au-shadow-sm au-border au-border-zinc-200 hover:au-bg-zinc-100", disabled: loading, children: loading ? /* @__PURE__ */ jsx(LoaderCircle, { className: "au-text-muted-foreground au-animate-spin !au-w-4 !au-h-4" }) : "Save" } ) ] }) ] } ) ] }) ] }), /* @__PURE__ */ jsxs("p", { children: [ item.display?.primary_text, " ", item.display?.secondary_text ] }) ] }); }; var PriceItem = ({ children, className, ...props }) => { return /* @__PURE__ */ jsx( "div", { className: cn( "au-flex au-flex-col au-pb-4 sm:au-pb-0 au-gap-1 sm:au-flex-row au-justify-between sm:au-h-7 sm:au-gap-2 sm:au-items-center", className ), ...props, children } ); }; var PricingDialogButton = ({ children, size, onClick, disabled, className }) => { return /* @__PURE__ */ jsxs( Button, { onClick, disabled, size, className: cn(className, "au-shadow-sm au-shadow-stone-400"), children: [ children, /* @__PURE__ */ jsx(ArrowRight, { className: "!au-h-3" }) ] } ); }; // src/libraries/react/components/pricing-table/pricing-table-synced.tsx import { createContext, useContext, useState as useState2 } from "react"; import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime"; function PricingTable({ productDetails }) { const { checkout } = useCustomer(); const [isAnnual, setIsAnnual] = useState2(false); const { products, isLoading, error } = usePricingTable({ productDetails }); if (isLoading) { return /* @__PURE__ */ jsx2("div", { style: loadingStyles, children: /* @__PURE__ */ jsx2(LoaderCircle, { style: spinnerStyles }) }); } if (error) { return /* @__PURE__ */ jsx2("div", { children: " Something went wrong..." }); } const intervals = Array.from( new Set( products?.map((p) => p.properties?.interval_group).filter((i) => !!i) ) ); const multiInterval = intervals.length > 1; const intervalFilter = (product) => { if (!product.properties?.interval_group) { return true; } if (multiInterval) { if (isAnnual) { return product.properties?.interval_group === "year"; } else { return product.properties?.interval_group === "month"; } } return true; }; return /* @__PURE__ */ jsx2("div", { className: cn("au-root"), children: products && /* @__PURE__ */ jsx2( PricingTableContainer, { products, isAnnualToggle: isAnnual, setIsAnnualToggle: setIsAnnual, multiInterval, children: products.filter(intervalFilter).map((product, index) => /* @__PURE__ */ jsx2( PricingCard, { productId: product.id, buttonProps: { disabled: product.scenario === "active" && !product.properties.updateable || product.scenario === "scheduled", onClick: async () => { if (product.id) { await checkout({ productId: product.id, dialog: AttachDialog }); } else if (product.display?.button_url) { window.open(product.display?.button_url, "_blank"); } } } }, index )) } ) }); } var PricingTableContext = createContext({ isAnnualToggle: false, setIsAnnualToggle: () => { }, products: [], showFeatures: true }); var usePricingTableContext = (componentName) => { const context = useContext(PricingTableContext); if (context === void 0) { throw new Error(`${componentName} must be used within <PricingTable />`); } return context; }; var PricingTableContainer = ({ children, products, showFeatures = true, className, isAnnualToggle, setIsAnnualToggle, multiInterval }) => { if (!products) { throw new Error("products is required in <PricingTable />"); } if (products.length === 0) { return /* @__PURE__ */ jsx2(Fragment2, {}); } const hasRecommended = products?.some((p) => p.display?.recommend_text); return /* @__PURE__ */ jsx2( PricingTableContext.Provider, { value: { isAnnualToggle, setIsAnnualToggle, products, showFeatures }, children: /* @__PURE__ */ jsxs2( "div", { className: cn( "au-flex au-items-center au-flex-col", hasRecommended && "!au-py-10" ), children: [ multiInterval && /* @__PURE__ */ jsx2( "div", { className: cn( products.some((p) => p.display?.recommend_text) && "au-mb-8" ), children: /* @__PURE__ */ jsx2( AnnualSwitch, { isAnnualToggle, setIsAnnualToggle } ) } ), /* @__PURE__ */ jsx2( "div", { className: cn( "au-grid au-grid-cols-1 sm:au-grid-cols-2 lg:au-grid-cols-[repeat(auto-fit,minmax(200px,1fr))] au-w-full au-gap-2", className ), children } ) ] } ) } ); }; var PricingCard = ({ productId, className, buttonProps }) => { const { products, showFeatures } = usePricingTableContext("PricingCard"); const product = products.find((p) => p.id === productId); if (!product) { throw new Error(`Product with id ${productId} not found`); } const { name, display: productDisplay, items } = product; const { buttonText } = getPricingTableContent(product); const isRecommended = productDisplay?.recommend_text ? true : false; const mainPriceDisplay = product.properties?.is_free ? { primary_text: "Free" } : product.items[0].display; const featureItems = product.properties?.is_free ? product.items : product.items.slice(1); return /* @__PURE__ */ jsxs2( "div", { className: cn( " au-w-full au-h-full au-py-6 au-text-foreground au-border au-rounded-lg au-shadow-sm au-max-w-xl", isRecommended && "lg:au--translate-y-6 lg:au-shadow-lg dark:au-shadow-zinc-800/80 lg:au-h-[calc(100%+48px)] au-bg-secondary/40", className ), children: [ productDisplay?.recommend_text && /* @__PURE__ */ jsx2(RecommendedBadge, { recommended: productDisplay?.recommend_text }), /* @__PURE__ */ jsxs2( "div", { className: cn( "au-flex au-flex-col au-h-full au-flex-grow", isRecommended && "lg:au-translate-y-6" ), children: [ /* @__PURE__ */ jsxs2("div", { className: "au-h-full", children: [ /* @__PURE__ */ jsxs2("div", { className: "au-flex au-flex-col", children: [ /* @__PURE__ */ jsxs2("div", { className: "au-pb-4", children: [ /* @__PURE__ */ jsx2("h2", { className: "au-text-2xl au-font-semibold au-px-6 au-truncate", children: productDisplay?.name || name }), productDisplay?.description && /* @__PURE__ */ jsx2("div", { className: "au-text-sm au-text-muted-foreground au-px-6 au-h-8", children: /* @__PURE__ */ jsx2("p", { className: "au-line-clamp-2", children: productDisplay?.description }) }) ] }), /* @__PURE__ */ jsx2("div", { className: "au-mb-2", children: /* @__PURE__ */ jsx2("h3", { className: "au-font-semibold au-h-16 au-flex au-px-6 au-items-center au-border-y au-mb-4 au-bg-secondary/40", children: /* @__PURE__ */ jsxs2("div", { className: "au-line-clamp-2", children: [ mainPriceDisplay?.primary_text, " ", mainPriceDisplay?.secondary_text && /* @__PURE__ */ jsx2("span", { className: "au-font-normal au-text-muted-foreground au-mt-1", children: mainPriceDisplay?.secondary_text }) ] }) }) }) ] }), showFeatures && featureItems.length > 0 && /* @__PURE__ */ jsx2("div", { className: "au-flex-grow au-px-6 au-mb-6", children: /* @__PURE__ */ jsx2( PricingFeatureList, { items: featureItems, showIcon: true, everythingFrom: product.display?.everything_from } ) }) ] }), /* @__PURE__ */ jsx2( "div", { className: cn(" au-px-6 ", isRecommended && "lg:au--translate-y-12"), children: /* @__PURE__ */ jsx2( PricingCardButton, { recommended: productDisplay?.recommend_text ? true : false, ...buttonProps, children: productDisplay?.button_text || buttonText } ) } ) ] } ) ] } ); }; var PricingFeatureList = ({ items, showIcon = true, everythingFrom, className }) => { return /* @__PURE__ */ jsxs2("div", { className: cn("au-flex-grow", className), children: [ everythingFrom && /* @__PURE__ */ jsxs2("p", { className: "au-text-sm au-mb-4", children: [ "Everything from ", everythingFrom, ", plus:" ] }), /* @__PURE__ */ jsx2("div", { className: "au-space-y-3", children: items.map((item, index) => /* @__PURE__ */ jsx2( "div", { className: "au-flex au-items-start au-gap-2 au-text-sm", children: /* @__PURE__ */ jsxs2("div", { className: "au-flex au-flex-col", children: [ /* @__PURE__ */ jsx2("span", { children: item.display?.primary_text }), item.display?.secondary_text && /* @__PURE__ */ jsx2("span", { className: "au-text-sm au-text-muted-foreground", children: item.display?.secondary_text }) ] }) }, index )) }) ] }); }; var PricingCardButton = React2.forwardRef(({ recommended, children, className, onClick, ...props }, ref) => { const [loading, setLoading] = useState2(false); const handleClick = async (e) => { setLoading(true); try { await onClick?.(e); } catch (error) { console.error(error); } finally { setLoading(false); } }; return /* @__PURE__ */ jsx2( Button, { className: cn( "au-w-full au-py-3 au-px-4 au-group au-overflow-hidden au-relative au-transition-all au-duration-300 hover:au-brightness-90 au-border au-rounded-lg", className ), ...props, variant: recommended ? "default" : "secondary", ref, disabled: loading || props.disabled, onClick: handleClick, children: loading ? /* @__PURE__ */ jsx2(LoaderCircle, { className: "au-h-4 au-w-4 au-animate-spin" }) : /* @__PURE__ */ jsxs2(Fragment2, { children: [ /* @__PURE__ */ jsxs2("div", { className: "au-flex au-items-center au-justify-between au-w-full au-transition-transform au-duration-300 group-hover:au-translate-y-[-130%]", children: [ /* @__PURE__ */ jsx2("span", { children }), /* @__PURE__ */ jsx2("span", { className: "au-text-sm", children: "\u2192" }) ] }), /* @__PURE__ */ jsxs2("div", { className: "au-flex au-items-center au-justify-between au-w-full au-absolute au-px-4 au-translate-y-[130%] au-transition-transform au-duration-300 group-hover:au-translate-y-0 au-mt-2 group-hover:au-mt-0", children: [ /* @__PURE__ */ jsx2("span", { children }), /* @__PURE__ */ jsx2("span", { className: "au-text-sm", children: "\u2192" }) ] }) ] }) } ); }); PricingCardButton.displayName = "PricingCardButton"; var AnnualSwitch = ({ isAnnualToggle, setIsAnnualToggle }) => { return /* @__PURE__ */ jsxs2("div", { className: "au-flex au-items-center au-space-x-2 au-mb-4", children: [ /* @__PURE__ */ jsx2("span", { className: "au-text-sm au-text-muted-foreground", children: "Monthly" }), /* @__PURE__ */ jsx2( Switch, { id: "annual-billing", checked: isAnnualToggle, onCheckedChange: setIsAnnualToggle } ), /* @__PURE__ */ jsx2("span", { className: "au-text-sm au-text-muted-foreground", children: "Annual" }) ] }); }; var RecommendedBadge = ({ recommended }) => { return /* @__PURE__ */ jsx2("div", { className: "au-bg-secondary au-absolute au-border au-text-muted-foreground au-text-sm au-font-medium lg:au-rounded-full au-px-3 lg:au-py-0.5 lg:au-top-4 lg:au-right-4 au-top-[-1px] au-right-[-1px] au-rounded-bl-lg", children: recommended }); }; export { PricingTable, usePricingTableContext, PricingTableContainer, PricingCard, PricingFeatureList, PricingCardButton, AnnualSwitch, RecommendedBadge, AttachDialog, PriceItem, PricingDialogButton };