import { Accordion, AccordionItem, AccordionContent, AccordionTrigger, } from "@/components/ui/accordion"; import { Badge as Chip } from "@/components/ui/badge"; import { Button, buttonVariants } from "@/components/ui/button"; import { Card as BaseCard } from "@/components/ui/card"; import { Tabs, TabsTrigger as Tab, TabsList } from "@/components/ui/tabs"; // import { PiCheckCircleDuotone } from 'react-icons/pi'; import { cn } from "@/lib/utils"; import { ChevronRight as MdChevronRight } from "lucide-react"; import { CheckCircle as PiCheckCircleDuotone } from "lucide-react"; import Link from "next/link"; import type { HTMLAttributeAnchorTarget, HTMLAttributes, ReactNode, } from "react"; // import { MdChevronRight } from 'react-icons/md'; import React from "react"; import { twMerge } from "tailwind-merge"; type ButtonProps = React.ComponentProps; type LinkProps = React.ComponentProps; type CardProps = React.ComponentProps; type TabsProps = React.ComponentProps; type AccordionProps = React.ComponentProps; type ChipProps = React.ComponentProps; function Section({ className, children, ...props }: HTMLAttributes) { // extract the primary action and secondary action from the children const primaryAction = getChildComponent(children, PrimaryAction); const secondaryAction = getChildComponent(children, SecondaryAction); return (
{removeFromChildren(children, [PrimaryAction, SecondaryAction])}
{primaryAction} {secondaryAction}
); } function Title({ children, className, ...props }: HTMLAttributes) { return (

{children}

); } function Subtitle({ children, className, ...props }: HTMLAttributes) { return (

{children}

); } function Announcement({ className, children, href, target = "_blank", ...props }: ChipProps & { href?: string; //string | UrlObject; target?: HTMLAttributeAnchorTarget | undefined; }) { return ( // } style={{ // @ts-ignore textWrap: "balance", }} {...props} > {children} {" "} ); } type ActionProps = ButtonProps & { be: "button"; hideArrow?: boolean; }; type ActionLinkProps = LinkProps & { be?: "a"; hideArrow?: boolean; variant?: ButtonProps["variant"]; }; function PrimaryAction({ className, variant, children, hideArrow, ...props }: ActionLinkProps | ActionProps) { if (props.be === "button") { return ( ); } return ( {children} {!hideArrow && ( )} ); } function SecondaryAction({ className, variant, children, hideArrow, ...props }: ActionLinkProps | ActionProps) { if (props.be === "button") { return ( ); } return ( {children} {!hideArrow && ( )} ); } function PricingCard({ className, children, ...props }: Omit & { children: | ReactNode | ReactNode[] | ((pricingType: PricingType) => ReactNode | ReactNode[]); }) { // const { pricingType } = usePricingContext(); if (typeof children === "function") children = (children("month") as React.ReactElement).props.children as | ReactNode | ReactNode[]; // extract the title and subtitle from the children // const cardTitleStyles = const title = getChildComponent(children, Title, { className: "text-2xl md:text-2xl text-start font-bold", }); const subTitle = getChildComponent(children, Subtitle, { className: "text-md text-start text-foreground-500 mt-4", }); const priceTags = getChildComponents(children, PriceTag, { className: "text-4xl font-bold", }); const primaryAction = getChildComponent(children, PrimaryAction, { className: "w-full", }); return (
{title} {priceTags} {subTitle}
{removeFromChildren(children, [ Title, Subtitle, ImageArea, PriceTag, PrimaryAction, ]).map((item, i) => { return (
{item}
); })}
{primaryAction}
); } // create a Pricing Context that store the monthly and pricing state // const PricingContext = createContext<{ // pricingType: PricingType; // setPricingType: (pricingType: PricingType) => void; // }>({ // pricingType: 'month', // setPricingType: (pricingType: PricingType) => {}, // }); const PricingTypeValue = ["month", "year"] as const; export type PricingType = (typeof PricingTypeValue)[number]; // // an helper function to useContext // export function usePricingContext() { // return React.useContext(PricingContext); // } function Pricing({ children, ...props }: HTMLAttributes) { // const [pricingType, setPricingType] = useState('month'); // const context = useMemo(() => { // return { // pricingType, // setPricingType, // }; // }, [pricingType]); return ( //
{children}
//
); } function PricingOption({ className, ...props }: TabsProps) { // const { setPricingType } = usePricingContext(); return ( { // setPricingType(key as PricingType); }} // onSelectionChange={(key: any) => { // setPricingType(key as PricingType); // }} > {PricingTypeValue.map((pricingType) => { return ( {pricingType} ); })} ); } function PriceTag({ children, pricingType, ...props }: HTMLAttributes & { pricingType?: "month" | "year" | string; }) { // const { pricingType: currentPricingType } = usePricingContext(); const currentPricingType = "month"; if (pricingType != undefined && currentPricingType !== pricingType) return <>; return

{children}

; } function Card({ className, children, ...props }: CardProps) { // extract the title and subtitle from the children // const cardTitleStyles = const title = getChildComponent(children, Title, { className: "text-2xl md:text-2xl font-normal text-center", }); const subTitle = getChildComponent(children, Subtitle, { className: "text-md text-center", }); const image = getChildComponent(children, ImageArea); return ( {image} {title} {subTitle} {removeFromChildren(children, [Title, Subtitle, ImageArea])} ); } function ImageArea({ className, children, ...props }: HTMLAttributes) { return (
{children}
); } // create a helper to get and remove the title and subtitle from the children function getChildComponent React.JSX.Element>( children: React.ReactNode | React.ReactNode[], type: T, propsOverride?: Partial[0]> ) { const childrenArr = React.Children.toArray(children); let child = childrenArr.find( (child) => React.isValidElement(child) && child.type === type ) as React.ReactElement< Parameters[0], string | React.JSXElementConstructor >; if (child && propsOverride) { const { className, ...rest } = child.props; child = React.cloneElement(child, { className: twMerge(className, propsOverride.className), ...rest, }); } return child; } function getChildComponents React.JSX.Element>( children: React.ReactNode | React.ReactNode[], type: T, propsOverride?: Partial[0]> ) { const childrenArr = React.Children.toArray(children); const child = ( childrenArr.filter( (child) => React.isValidElement(child) && child.type === type ) as React.ReactElement< Parameters[0], string | React.JSXElementConstructor >[] ).map((child) => { if (child && propsOverride) { const { className, ...rest } = child.props; child = React.cloneElement(child, { className: twMerge(className, propsOverride.className), ...rest, }); } return child; }); return child; } function removeFromChildren( children: React.ReactNode | React.ReactNode[], types: any[] ): React.ReactNode[] { return React.Children.toArray(children).filter( (child) => React.isValidElement(child) && !types.includes(child.type) ); } function FAQ({ children, ...props }: AccordionProps) { return {children}; } function FAQItem({ children, ...props }: { children: React.ReactNode | React.ReactNode[]; "aria-label": string; title: string; }): JSX.Element { return ( {props.title} {children} ); } // const FAQItem = AccordionItem; const pkg = Object.assign(Section, { Pricing, PricingOption, Title, Subtitle, Announcement, PrimaryAction, SecondaryAction, ImageArea, Card, FAQItem, FAQ, PricingCard, PriceTag, }); export { pkg as Section };