@salesmind-ai/design-system 0.3.4 → 0.3.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/{StatsSection-wgd8Vge1.d.cts → StatsSection-Dihy3zml.d.cts} +2 -0
- package/dist/{StatsSection-B8iD9L-o.d.ts → StatsSection-MfKKyqL1.d.ts} +2 -0
- package/dist/admin/index.cjs +68 -2928
- package/dist/admin/index.cjs.map +1 -1
- package/dist/admin/index.js +5 -2915
- package/dist/admin/index.js.map +1 -1
- package/dist/blog/index.cjs +53 -1064
- package/dist/blog/index.cjs.map +1 -1
- package/dist/blog/index.js +8 -1054
- package/dist/blog/index.js.map +1 -1
- package/dist/charts/index.cjs +46 -2694
- package/dist/charts/index.cjs.map +1 -1
- package/dist/charts/index.js +3 -2680
- package/dist/charts/index.js.map +1 -1
- package/dist/chunk-2GARWEJK.js +17 -0
- package/dist/chunk-2GARWEJK.js.map +1 -0
- package/dist/chunk-2KQVZ5FB.js +485 -0
- package/dist/chunk-2KQVZ5FB.js.map +1 -0
- package/dist/chunk-3NKRFUAR.js +37 -0
- package/dist/chunk-3NKRFUAR.js.map +1 -0
- package/dist/chunk-3TGSIILM.cjs +201 -0
- package/dist/chunk-3TGSIILM.cjs.map +1 -0
- package/dist/chunk-4GM5BGBN.cjs +801 -0
- package/dist/chunk-4GM5BGBN.cjs.map +1 -0
- package/dist/chunk-5LGDEZWY.cjs +2434 -0
- package/dist/chunk-5LGDEZWY.cjs.map +1 -0
- package/dist/chunk-6H4DSTXR.js +786 -0
- package/dist/chunk-6H4DSTXR.js.map +1 -0
- package/dist/chunk-6HKQ5ILL.cjs +1624 -0
- package/dist/chunk-6HKQ5ILL.cjs.map +1 -0
- package/dist/chunk-6UNG76Y2.js +153 -0
- package/dist/chunk-6UNG76Y2.js.map +1 -0
- package/dist/chunk-7PX2AZ6Y.js +39 -0
- package/dist/chunk-7PX2AZ6Y.js.map +1 -0
- package/dist/chunk-ARC5KXBC.js +187 -0
- package/dist/chunk-ARC5KXBC.js.map +1 -0
- package/dist/chunk-B6AVAX4F.js +1415 -0
- package/dist/chunk-B6AVAX4F.js.map +1 -0
- package/dist/chunk-BILT5KD3.js +264 -0
- package/dist/chunk-BILT5KD3.js.map +1 -0
- package/dist/chunk-C2BCDNAV.js +24 -0
- package/dist/chunk-C2BCDNAV.js.map +1 -0
- package/dist/chunk-CH42VPWE.cjs +421 -0
- package/dist/chunk-CH42VPWE.cjs.map +1 -0
- package/dist/chunk-CJ2MKVAF.cjs +46 -0
- package/dist/chunk-CJ2MKVAF.cjs.map +1 -0
- package/dist/chunk-DP74LUXG.cjs +98 -0
- package/dist/chunk-DP74LUXG.cjs.map +1 -0
- package/dist/chunk-E7D6EKJ4.cjs +44 -0
- package/dist/chunk-E7D6EKJ4.cjs.map +1 -0
- package/dist/chunk-ECXBTUH6.cjs +584 -0
- package/dist/chunk-ECXBTUH6.cjs.map +1 -0
- package/dist/chunk-EFRAP5ES.js +157 -0
- package/dist/chunk-EFRAP5ES.js.map +1 -0
- package/dist/chunk-EM7JHRYW.cjs +69 -0
- package/dist/chunk-EM7JHRYW.cjs.map +1 -0
- package/dist/chunk-FAFAP4L5.js +183 -0
- package/dist/chunk-FAFAP4L5.js.map +1 -0
- package/dist/chunk-H2Y6BSTL.cjs +69 -0
- package/dist/chunk-H2Y6BSTL.cjs.map +1 -0
- package/dist/chunk-HN4PHABT.js +126 -0
- package/dist/chunk-HN4PHABT.js.map +1 -0
- package/dist/chunk-HRENHNDJ.js +211 -0
- package/dist/chunk-HRENHNDJ.js.map +1 -0
- package/dist/chunk-I75BFEYT.cjs +2561 -0
- package/dist/chunk-I75BFEYT.cjs.map +1 -0
- package/dist/chunk-IFRATNLU.js +562 -0
- package/dist/chunk-IFRATNLU.js.map +1 -0
- package/dist/chunk-JNASH4OQ.js +1022 -0
- package/dist/chunk-JNASH4OQ.js.map +1 -0
- package/dist/chunk-JPJN4YBC.js +409 -0
- package/dist/chunk-JPJN4YBC.js.map +1 -0
- package/dist/chunk-KCKUSU2M.cjs +166 -0
- package/dist/chunk-KCKUSU2M.cjs.map +1 -0
- package/dist/chunk-KDLH35OI.cjs +1042 -0
- package/dist/chunk-KDLH35OI.cjs.map +1 -0
- package/dist/chunk-KJ2OXQF4.js +287 -0
- package/dist/chunk-KJ2OXQF4.js.map +1 -0
- package/dist/chunk-KK5UO2P4.cjs +717 -0
- package/dist/chunk-KK5UO2P4.cjs.map +1 -0
- package/dist/chunk-KNQEIU7O.cjs +1202 -0
- package/dist/chunk-KNQEIU7O.cjs.map +1 -0
- package/dist/chunk-KVGSVGRK.cjs +569 -0
- package/dist/chunk-KVGSVGRK.cjs.map +1 -0
- package/dist/chunk-L352JRV6.cjs +105 -0
- package/dist/chunk-L352JRV6.cjs.map +1 -0
- package/dist/chunk-LGNMFBLF.cjs +502 -0
- package/dist/chunk-LGNMFBLF.cjs.map +1 -0
- package/dist/chunk-LJADZITX.cjs +298 -0
- package/dist/chunk-LJADZITX.cjs.map +1 -0
- package/dist/chunk-LSR7JYVH.cjs +196 -0
- package/dist/chunk-LSR7JYVH.cjs.map +1 -0
- package/dist/chunk-MDB2WCRQ.cjs +137 -0
- package/dist/chunk-MDB2WCRQ.cjs.map +1 -0
- package/dist/chunk-MQDEE7HC.cjs +283 -0
- package/dist/chunk-MQDEE7HC.cjs.map +1 -0
- package/dist/chunk-MQRB634A.cjs +34 -0
- package/dist/chunk-MQRB634A.cjs.map +1 -0
- package/dist/chunk-MU6GW5ZV.js +2317 -0
- package/dist/chunk-MU6GW5ZV.js.map +1 -0
- package/dist/chunk-NN3TUHIH.js +28 -0
- package/dist/chunk-NN3TUHIH.js.map +1 -0
- package/dist/chunk-NT4LBP7D.cjs +111 -0
- package/dist/chunk-NT4LBP7D.cjs.map +1 -0
- package/dist/chunk-OGKGIXFC.cjs +2162 -0
- package/dist/chunk-OGKGIXFC.cjs.map +1 -0
- package/dist/chunk-OXNXEQY7.js +2538 -0
- package/dist/chunk-OXNXEQY7.js.map +1 -0
- package/dist/chunk-P5BOFE5A.js +546 -0
- package/dist/chunk-P5BOFE5A.js.map +1 -0
- package/dist/chunk-Q2MFGYTE.cjs +1449 -0
- package/dist/chunk-Q2MFGYTE.cjs.map +1 -0
- package/dist/chunk-Q75DBVDY.cjs +68 -0
- package/dist/chunk-Q75DBVDY.cjs.map +1 -0
- package/dist/chunk-RQUFZAZ7.js +1608 -0
- package/dist/chunk-RQUFZAZ7.js.map +1 -0
- package/dist/chunk-SICKWUWB.js +62 -0
- package/dist/chunk-SICKWUWB.js.map +1 -0
- package/dist/chunk-T343CCH5.js +1190 -0
- package/dist/chunk-T343CCH5.js.map +1 -0
- package/dist/chunk-T5H5PNLN.js +701 -0
- package/dist/chunk-T5H5PNLN.js.map +1 -0
- package/dist/chunk-U3LK2GID.js +2122 -0
- package/dist/chunk-U3LK2GID.js.map +1 -0
- package/dist/chunk-UFAJY2DM.js +62 -0
- package/dist/chunk-UFAJY2DM.js.map +1 -0
- package/dist/chunk-VC5LMUVQ.cjs +20 -0
- package/dist/chunk-VC5LMUVQ.cjs.map +1 -0
- package/dist/chunk-VM7WFMKI.cjs +76 -0
- package/dist/chunk-VM7WFMKI.cjs.map +1 -0
- package/dist/chunk-W2WTP6HS.cjs +233 -0
- package/dist/chunk-W2WTP6HS.cjs.map +1 -0
- package/dist/chunk-WH7PYHZY.cjs +35 -0
- package/dist/chunk-WH7PYHZY.cjs.map +1 -0
- package/dist/chunk-XU3OMQ7V.js +98 -0
- package/dist/chunk-XU3OMQ7V.js.map +1 -0
- package/dist/chunk-XWPDRMZG.js +62 -0
- package/dist/chunk-XWPDRMZG.js.map +1 -0
- package/dist/chunk-Y3CPKNB7.js +67 -0
- package/dist/chunk-Y3CPKNB7.js.map +1 -0
- package/dist/chunk-YNVRDD2P.js +98 -0
- package/dist/chunk-YNVRDD2P.js.map +1 -0
- package/dist/chunk-YSYR54XR.js +92 -0
- package/dist/chunk-YSYR54XR.js.map +1 -0
- package/dist/chunk-YTYDQBVY.cjs +162 -0
- package/dist/chunk-YTYDQBVY.cjs.map +1 -0
- package/dist/core/index.cjs +807 -4333
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.js +14 -4130
- package/dist/core/index.js.map +1 -1
- package/dist/i18n/index.cjs +86 -558
- package/dist/i18n/index.cjs.map +1 -1
- package/dist/i18n/index.js +1 -544
- package/dist/i18n/index.js.map +1 -1
- package/dist/index.cjs +1432 -17140
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +31 -16785
- package/dist/index.js.map +1 -1
- package/dist/marketing/index.cjs +142 -3072
- package/dist/marketing/index.cjs.map +1 -1
- package/dist/marketing/index.js +11 -3042
- package/dist/marketing/index.js.map +1 -1
- package/dist/motion/index.cjs +26 -1222
- package/dist/motion/index.cjs.map +1 -1
- package/dist/motion/index.js +2 -1215
- package/dist/motion/index.js.map +1 -1
- package/dist/nav/index.cjs +101 -1518
- package/dist/nav/index.cjs.map +1 -1
- package/dist/nav/index.js +4 -1498
- package/dist/nav/index.js.map +1 -1
- package/dist/report/index.cjs +171 -2403
- package/dist/report/index.cjs.map +1 -1
- package/dist/report/index.js +3 -2363
- package/dist/report/index.js.map +1 -1
- package/dist/sections/index.cjs +22 -377
- package/dist/sections/index.cjs.map +1 -1
- package/dist/sections/index.d.cts +1 -1
- package/dist/sections/index.d.ts +1 -1
- package/dist/sections/index.js +6 -369
- package/dist/sections/index.js.map +1 -1
- package/dist/social-proof/index.cjs +53 -1250
- package/dist/social-proof/index.cjs.map +1 -1
- package/dist/social-proof/index.js +6 -1235
- package/dist/social-proof/index.js.map +1 -1
- package/dist/theme/index.cjs +38 -565
- package/dist/theme/index.cjs.map +1 -1
- package/dist/theme/index.js +2 -555
- package/dist/theme/index.js.map +1 -1
- package/dist/web/client/index.cjs +38 -491
- package/dist/web/client/index.cjs.map +1 -1
- package/dist/web/client/index.js +4 -483
- package/dist/web/client/index.js.map +1 -1
- package/dist/web/index.cjs +158 -1346
- package/dist/web/index.cjs.map +1 -1
- package/dist/web/index.js +9 -1305
- package/dist/web/index.js.map +1 -1
- package/dist/web/server/index.cjs +26 -563
- package/dist/web/server/index.cjs.map +1 -1
- package/dist/web/server/index.js +1 -560
- package/dist/web/server/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ArticleCard/ArticleCard.tsx","../src/components/ArticleLayout/ArticleLayout.tsx","../src/components/AuthorBio/AuthorBio.tsx","../src/components/TableOfContents/TableOfContents.tsx","../src/components/RelatedContent/RelatedContent.tsx","../src/components/LongFormLayout/LongFormLayout.tsx","../src/components/LongFormComponents/LongFormComponents.tsx","../src/components/ReadingProgress/ReadingProgress.tsx","../src/components/VersionedContent/VersionedContent.tsx"],"names":["React","forwardRef","clsx","jsx","jsxs","useEffect","useState"],"mappings":"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","sourcesContent":["import React, { forwardRef } from 'react';\nimport clsx from 'clsx';\nimport { useAnalytics } from '../../web/analytics/use-analytics';\nimport { ArrowRight, Clock, FileText } from 'lucide-react';\nimport { OutboundLink } from '../OutboundLink/OutboundLink';\nimport './ArticleCard.css';\n\nexport interface ArticleCardProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {\n /** Target URL */\n href: string;\n /** Article title */\n title: string;\n /** Short excerpt or description */\n excerpt: string;\n /** Image URL for the thumbnail */\n imageUrl?: string;\n /** Image alt text */\n imageAlt?: string;\n /** Category or tag label */\n category?: string;\n /** Publication date */\n date?: string;\n /** Reading time in minutes */\n readingTime?: number;\n /** Author name */\n author?: string;\n /** Variant for different grid layouts */\n variant?: 'vertical' | 'horizontal' | 'featured';\n}\n\n/**\n * Standardized card for blog posts, resources, and case studies.\n * Acts as a block-level link.\n */\nexport const ArticleCard = forwardRef<HTMLAnchorElement, ArticleCardProps>(\n (\n {\n href,\n title,\n excerpt,\n imageUrl,\n imageAlt = '',\n category,\n date,\n readingTime,\n author,\n variant = 'vertical',\n className,\n onClick,\n ...props\n },\n ref\n ) => {\n const { track } = useAnalytics();\n\n const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {\n track('article_click', { url: href, title, category });\n if (onClick) onClick(e);\n };\n\n return (\n <OutboundLink\n ref={ref}\n href={href}\n context=\"article-card\"\n className={clsx(\n 'ds-article-card',\n `ds-article-card--${variant}`,\n !imageUrl && 'ds-article-card--no-image',\n className\n )}\n onClick={handleClick}\n {...props}\n >\n {imageUrl ? (\n <div className=\"ds-article-card__image-wrapper\">\n <img \n src={imageUrl} \n alt={imageAlt} \n className=\"ds-article-card__image\" \n loading=\"lazy\" \n />\n {category && (\n <span className=\"ds-article-card__category-badge\">{category}</span>\n )}\n </div>\n ) : (\n <div className=\"ds-article-card__placeholder\">\n <FileText className=\"ds-article-card__placeholder-icon\" aria-hidden=\"true\" />\n {category && (\n <span className=\"ds-article-card__category-badge\">{category}</span>\n )}\n </div>\n )}\n \n <div className=\"ds-article-card__content\">\n \n <h3 className=\"ds-article-card__title\">{title}</h3>\n <p className=\"ds-article-card__excerpt\">{excerpt}</p>\n \n <div className=\"ds-article-card__meta\">\n {(date || author) && (\n <div className=\"ds-article-card__meta-primary\">\n {author && <span className=\"ds-article-card__author\">{author}</span>}\n {author && date && <span className=\"ds-article-card__dot\" aria-hidden=\"true\">•</span>}\n {date && <time dateTime={date} className=\"ds-article-card__date\">{date}</time>}\n </div>\n )}\n \n {readingTime && (\n <div className=\"ds-article-card__meta-secondary\">\n <Clock size={14} aria-hidden=\"true\" />\n <span>{readingTime} min read</span>\n </div>\n )}\n </div>\n \n <div className=\"ds-article-card__footer\">\n <span className=\"ds-article-card__read-more\">\n Read article\n <ArrowRight size={16} className=\"ds-article-card__arrow\" />\n </span>\n </div>\n </div>\n </OutboundLink>\n );\n }\n);\n\nArticleCard.displayName = 'ArticleCard';\n","import React, { forwardRef } from 'react';\nimport clsx from 'clsx';\nimport { useAnalytics } from '../../web/analytics/use-analytics';\nimport './ArticleLayout.css';\n\nexport interface ArticleLayoutProps extends React.HTMLAttributes<HTMLDivElement> {\n /** The main content of the article */\n children: React.ReactNode;\n /** Article title */\n title: string;\n /** Author name */\n author?: React.ReactNode;\n /** Publish date */\n date?: React.ReactNode;\n /** Main hero image */\n heroImage?: string;\n /** Sidebar content (like TOC or related articles) */\n sidebar?: React.ReactNode;\n}\n\n/**\n * Standardized layout for long-form content (blog posts, resources, case studies).\n * Handles responsive wrapping, prose width constraints, and sidebar positioning.\n */\nexport const ArticleLayout = forwardRef<HTMLDivElement, ArticleLayoutProps>(\n (\n {\n children,\n title,\n author,\n date,\n heroImage,\n sidebar,\n className,\n ...props\n },\n ref\n ) => {\n // Add scroll tracking\n const { track } = useAnalytics();\n \n React.useEffect(() => {\n let maxScroll = 0;\n \n const handleScroll = () => {\n const docHeight = document.documentElement.scrollHeight - window.innerHeight;\n if (docHeight > 0) {\n const scrollPercent = Math.round((window.scrollY / docHeight) * 100);\n \n if (scrollPercent > maxScroll) {\n maxScroll = scrollPercent;\n \n // Track milestones\n if (maxScroll === 25) track('article_scroll', { milestone: 25 });\n if (maxScroll === 50) track('article_scroll', { milestone: 50 });\n if (maxScroll === 75) track('article_scroll', { milestone: 75 });\n if (maxScroll === 100) track('article_scroll', { milestone: 100 });\n }\n }\n };\n\n window.addEventListener('scroll', handleScroll, { passive: true });\n return () => window.removeEventListener('scroll', handleScroll);\n }, [track]);\n\n return (\n <article\n ref={ref}\n className={clsx('ds-article-layout', className)}\n {...props}\n >\n <header className=\"ds-article-layout__header\">\n <h1 className=\"ds-article-layout__title\">{title}</h1>\n \n {(author || date) && (\n <div className=\"ds-article-layout__meta\">\n {author && <div className=\"ds-article-layout__author\">{author}</div>}\n {author && date && <span className=\"ds-article-layout__dot\" aria-hidden=\"true\">•</span>}\n {date && <time className=\"ds-article-layout__date\">{date}</time>}\n </div>\n )}\n </header>\n\n {heroImage && (\n <div className=\"ds-article-layout__hero\">\n <img src={heroImage} alt=\"\" aria-hidden=\"true\" />\n </div>\n )}\n\n <div className={clsx(\n 'ds-article-layout__body',\n sidebar && 'ds-article-layout__body--with-sidebar'\n )}>\n <div className=\"ds-article-layout__content ds-prose\">\n {children}\n </div>\n \n {sidebar && (\n <aside className=\"ds-article-layout__sidebar\">\n <div className=\"ds-article-layout__sidebar-inner\">\n {sidebar}\n </div>\n </aside>\n )}\n </div>\n </article>\n );\n }\n);\n\nArticleLayout.displayName = 'ArticleLayout';\n","import React, { forwardRef } from 'react';\nimport clsx from 'clsx';\nimport { Avatar, AvatarImage, AvatarFallback } from '../Avatar/Avatar';\nimport { OutboundLink } from '../OutboundLink/OutboundLink';\nimport './AuthorBio.css';\n\n/* ============================================================================\n AUTHOR BIO\n ============================================================================\n Author biography card for blog posts and articles.\n\n Strategic objective: Authority (expert credibility signal)\n ============================================================================ */\n\n/** Social/external link */\nexport interface AuthorLink {\n /** Link label (e.g., \"Twitter\", \"LinkedIn\") */\n label: string;\n /** Link URL */\n href: string;\n /** Optional icon */\n icon?: React.ReactNode;\n}\n\nexport interface AuthorBioProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Author name */\n name: string;\n /** Author role or title */\n role?: string;\n /** Avatar image URL */\n avatar?: string;\n /** Biography text */\n bio?: string;\n /** External links */\n links?: AuthorLink[];\n /** Layout variant */\n variant?: 'inline' | 'card' | 'compact' | 'longform';\n}\n\n/**\n * Author biography card.\n *\n * @example\n * ```tsx\n * <AuthorBio\n * name=\"Alex Chen\"\n * role=\"Head of Growth at SalesMind AI\"\n * avatar=\"/team/alex.jpg\"\n * bio=\"Alex has 10+ years of experience in B2B growth...\"\n * links={[{ label: 'LinkedIn', href: 'https://linkedin.com/in/alexchen' }]}\n * variant=\"card\"\n * />\n * ```\n */\nexport const AuthorBio = forwardRef<HTMLDivElement, AuthorBioProps>(\n (\n {\n name,\n role,\n avatar,\n bio,\n links,\n variant = 'card',\n className,\n ...props\n },\n ref,\n ) => {\n const initials = name\n .split(' ')\n .map((n) => n[0])\n .join('')\n .slice(0, 2);\n\n return (\n <div\n ref={ref}\n className={clsx('ds-author-bio', `ds-author-bio--${variant}`, className)}\n {...props}\n >\n <Avatar size={variant === 'compact' ? 'sm' : variant === 'longform' ? 'lg' : 'md'} className=\"ds-author-bio__avatar\">\n {avatar && <AvatarImage src={avatar} alt={name} />}\n <AvatarFallback>{initials}</AvatarFallback>\n </Avatar>\n\n <div className=\"ds-author-bio__info\">\n <span className=\"ds-author-bio__name\">{name}</span>\n {role && <span className=\"ds-author-bio__role\">{role}</span>}\n {bio && variant !== 'compact' && (\n <p className=\"ds-author-bio__bio\">{bio}</p>\n )}\n {links && links.length > 0 && variant !== 'compact' && (\n <div className=\"ds-author-bio__links\">\n {links.map((link, i) => (\n <OutboundLink\n key={i}\n href={link.href}\n context=\"author-bio-link\"\n className=\"ds-author-bio__link\"\n >\n {link.icon && <span className=\"ds-author-bio__link-icon\">{link.icon}</span>}\n {link.label}\n </OutboundLink>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n },\n);\n\nAuthorBio.displayName = 'AuthorBio';\n","import React, { forwardRef, useState, useEffect } from 'react';\nimport clsx from 'clsx';\nimport { useMessage } from '../../i18n';\nimport './TableOfContents.css';\n\n/* ============================================================================\n TABLE OF CONTENTS\n ============================================================================\n Sticky article TOC with active heading detection via IntersectionObserver.\n\n Strategic objective: Distribution (increases article dwell time)\n ============================================================================ */\n\n/** A TOC item mapping to a heading */\nexport interface TOCItem {\n /** Heading element ID */\n id: string;\n /** Heading text */\n title: string;\n /** Heading level (2 = h2, 3 = h3, etc.) */\n level: number;\n}\n\nexport interface TableOfContentsProps extends React.HTMLAttributes<HTMLElement> {\n /** TOC items (typically extracted from article headings) */\n items: TOCItem[];\n /** Currently active heading ID (controlled) */\n activeId?: string;\n /** Position variant */\n position?: 'sidebar' | 'inline' | 'floating';\n /** Label text */\n label?: string;\n /** Callback when an item is clicked */\n onItemClick?: (id: string) => void;\n}\n\n/**\n * Sticky table of contents with active heading tracking.\n *\n * @example\n * ```tsx\n * <TableOfContents\n * items={[\n * { id: 'intro', title: 'Introduction', level: 2 },\n * { id: 'setup', title: 'Getting Started', level: 2 },\n * { id: 'config', title: 'Configuration', level: 3 },\n * ]}\n * position=\"sidebar\"\n * />\n * ```\n */\nexport const TableOfContents = forwardRef<HTMLElement, TableOfContentsProps>(\n (\n {\n items,\n activeId: controlledActiveId,\n position = 'sidebar',\n label,\n onItemClick,\n className,\n ...props\n },\n ref,\n ) => {\n const t = useMessage();\n const defaultLabel = t({ id: 'ds.toc.label', defaultMessage: 'On this page' });\n const finalLabel = label || defaultLabel;\n\n const [observedActiveId, setObservedActiveId] = useState<string>('');\n const activeId = controlledActiveId ?? observedActiveId;\n\n // Auto-detect active heading via Scroll Listener (more robust than IO for long sections)\n useEffect(() => {\n if (controlledActiveId !== undefined) return;\n if (items.length === 0) return;\n\n const handleScroll = () => {\n const headingElements = items\n .map((item) => ({\n id: item.id,\n el: document.getElementById(item.id),\n }))\n .filter((h): h is { id: string; el: HTMLElement } => !!h.el);\n\n if (headingElements.length === 0) return;\n\n // Offset for sticky header\n const topOffset = 120; \n\n // Find the first heading that is clearly below the top offset\n const firstBelowIndex = headingElements.findIndex((h) => {\n const rect = h.el.getBoundingClientRect();\n return rect.top > topOffset;\n });\n\n let newActiveId = '';\n if (firstBelowIndex === -1) {\n // All headings are above the offset -> last one is active\n newActiveId = headingElements[headingElements.length - 1].id;\n } else if (firstBelowIndex === 0) {\n // First heading is below offset -> none active (or first if we want to be generous)\n newActiveId = ''; // Or headingElements[0].id\n } else {\n // The heading immediately before the one that is below is the active one\n newActiveId = headingElements[firstBelowIndex - 1].id;\n }\n\n setObservedActiveId(newActiveId);\n };\n\n window.addEventListener('scroll', handleScroll, { passive: true });\n // Initial check\n handleScroll();\n\n return () => window.removeEventListener('scroll', handleScroll);\n }, [items, controlledActiveId]);\n\n const handleClick = (id: string) => {\n const el = document.getElementById(id);\n if (el) {\n el.scrollIntoView({ behavior: 'smooth', block: 'start' });\n }\n if (onItemClick) onItemClick(id);\n };\n\n if (items.length === 0) return null;\n\n return (\n <nav\n ref={ref}\n className={clsx('ds-toc', `ds-toc--${position}`, className)}\n aria-label={finalLabel}\n {...props}\n >\n <span className=\"ds-toc__label\">{finalLabel}</span>\n <ul className=\"ds-toc__list\">\n {items.map((item) => (\n <li key={item.id} className=\"ds-toc__item\" style={{ paddingLeft: `${(item.level - 2) * 12}px` }}>\n <button\n type=\"button\"\n className={clsx(\n 'ds-toc__link',\n activeId === item.id && 'ds-toc__link--active',\n )}\n onClick={() => handleClick(item.id)}\n >\n {item.title}\n </button>\n </li>\n ))}\n </ul>\n </nav>\n );\n },\n);\n\nTableOfContents.displayName = 'TableOfContents';\n","import React, { forwardRef } from 'react';\nimport clsx from 'clsx';\nimport { SectionShell, type SectionShellProps } from '../SectionShell/SectionShell';\nimport { SectionHeader } from '../SectionShell/SectionShell';\nimport { ArticleCard, type ArticleCardProps } from '../ArticleCard/ArticleCard';\nimport './RelatedContent.css';\n\n/* ============================================================================\n RELATED CONTENT\n ============================================================================\n Related articles/resources section. Drives internal linking and increases\n session duration.\n\n Strategic objective: Distribution (internal linking + session depth)\n ============================================================================ */\n\nexport interface RelatedContentProps extends Omit<SectionShellProps, 'title'> {\n /** Section eyebrow */\n eyebrow?: React.ReactNode;\n /** Section title */\n title?: React.ReactNode;\n /** Related article items (uses ArticleCard props) */\n items: ArticleCardProps[];\n /** Max items to display */\n maxVisible?: number;\n}\n\n/**\n * Related articles section using ArticleCard grid.\n *\n * @example\n * ```tsx\n * <RelatedContent\n * title=\"Related Articles\"\n * items={[\n * { title: 'AI Outreach Guide', href: '/blog/ai-outreach', ... },\n * { title: 'Pipeline Automation', href: '/blog/pipeline', ... },\n * ]}\n * background=\"muted\"\n * />\n * ```\n */\nexport const RelatedContent = forwardRef<HTMLDivElement, RelatedContentProps>(\n (\n {\n eyebrow,\n title = 'Related Articles',\n items,\n maxVisible,\n className,\n ...props\n },\n ref,\n ) => {\n const visibleItems = maxVisible ? items.slice(0, maxVisible) : items;\n\n if (visibleItems.length === 0) return null;\n\n return (\n <SectionShell\n ref={ref}\n className={clsx('ds-related-content', className)}\n background=\"muted\"\n {...props}\n >\n <SectionHeader eyebrow={eyebrow} title={title} />\n\n <div className=\"ds-related-content__grid\">\n {visibleItems.map((item, i) => (\n <ArticleCard key={i} {...item} />\n ))}\n </div>\n </SectionShell>\n );\n },\n);\n\nRelatedContent.displayName = 'RelatedContent';\n","import React from 'react';\nimport clsx from 'clsx';\nimport './LongFormLayout.css';\n\nexport interface LongFormLayoutProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n /** Pass the TOC element here to render as a sticky sidebar on desktop */\n sidebar?: React.ReactNode;\n}\n\n/**\n * A layout primitive designed specifically for long-form content (e.g., blog posts, documentation).\n * Enforces maximum reading widths and manages the relationship between the main content and an optional sticky sidebar.\n */\nexport const LongFormLayout = React.forwardRef<HTMLDivElement, LongFormLayoutProps>(\n ({ children, sidebar, className, ...props }, ref) => {\n return (\n <div ref={ref} className={clsx('ds-longform-layout', className)} {...props}>\n <article className=\"ds-longform-layout__main\">{children}</article>\n {sidebar && <aside className=\"ds-longform-layout__sidebar\">{sidebar}</aside>}\n </div>\n );\n }\n);\n\nLongFormLayout.displayName = 'LongFormLayout';\n","import React from 'react';\nimport clsx from 'clsx';\nimport './LongFormComponents.css';\n\nexport interface InsightCalloutProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n icon?: React.ReactNode;\n title?: string;\n}\n\nexport const InsightCallout = React.forwardRef<HTMLDivElement, InsightCalloutProps>(\n ({ children, icon, title, className, ...props }, ref) => {\n return (\n <aside ref={ref} className={clsx('ds-insight-callout', className)} {...props}>\n {icon && <div className=\"ds-insight-callout__icon\">{icon}</div>}\n <div className=\"ds-insight-callout__content\">\n {title && <h5 className=\"ds-insight-callout__title\">{title}</h5>}\n {children}\n </div>\n </aside>\n );\n }\n);\nInsightCallout.displayName = 'InsightCallout';\n\nexport interface DataHighlightProps extends React.HTMLAttributes<HTMLDivElement> {\n stat: string;\n label: string;\n children?: React.ReactNode;\n}\n\nexport const DataHighlight = React.forwardRef<HTMLDivElement, DataHighlightProps>(\n ({ stat, label, children, className, ...props }, ref) => {\n return (\n <figure ref={ref} className={clsx('ds-data-highlight', className)} {...props}>\n <div className=\"ds-data-highlight__stat-group\">\n <span className=\"ds-data-highlight__stat\">{stat}</span>\n <span className=\"ds-data-highlight__label\">{label}</span>\n </div>\n {children && <figcaption className=\"ds-data-highlight__caption\">{children}</figcaption>}\n </figure>\n );\n }\n);\nDataHighlight.displayName = 'DataHighlight';\n","import React, { useEffect, useState, useRef } from 'react';\nimport clsx from 'clsx';\nimport './ReadingProgress.css';\n\nexport interface ReadingProgressProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Reference to the container element whose scroll progress we're tracking */\n targetRef?: React.RefObject<HTMLElement | null>;\n}\n\nexport const ReadingProgress = React.forwardRef<HTMLDivElement, ReadingProgressProps>(\n ({ targetRef, className, ...props }, ref) => {\n const [progress, setProgress] = useState(0);\n const frameRef = useRef<number | null>(null);\n\n useEffect(() => {\n const handleScroll = () => {\n if (frameRef.current) cancelAnimationFrame(frameRef.current);\n\n frameRef.current = requestAnimationFrame(() => {\n let percentage = 0;\n\n if (targetRef && targetRef.current) {\n // Calculate progress relative to the specific container\n const el = targetRef.current;\n const rect = el.getBoundingClientRect();\n const viewportHeight = window.innerHeight;\n \n // If top is below viewport, 0%. If bottom is above viewport, 100%.\n if (rect.top > viewportHeight) {\n percentage = 0;\n } else if (rect.bottom < 0) {\n percentage = 100;\n } else {\n const scrollableDistance = rect.height - viewportHeight;\n if (scrollableDistance <= 0) {\n percentage = 100; // Fits entirely on screen\n } else {\n const scrolled = viewportHeight - rect.top;\n percentage = Math.max(0, Math.min(100, (scrolled / scrollableDistance) * 100));\n }\n }\n } else {\n // Fallback to full page scroll\n const scrollPosition = window.scrollY;\n const scrollHeight = document.body.scrollHeight - window.innerHeight;\n percentage = scrollHeight > 0 ? (scrollPosition / scrollHeight) * 100 : 0;\n percentage = Math.max(0, Math.min(100, percentage));\n }\n\n setProgress(percentage);\n });\n };\n\n window.addEventListener('scroll', handleScroll, { passive: true });\n window.addEventListener('resize', handleScroll, { passive: true });\n \n // Initial calculation\n handleScroll();\n\n return () => {\n if (frameRef.current) cancelAnimationFrame(frameRef.current);\n window.removeEventListener('scroll', handleScroll);\n window.removeEventListener('resize', handleScroll);\n };\n }, [targetRef]);\n\n return (\n <div \n ref={ref} \n className={clsx('ds-reading-progress', className)} \n {...props}\n >\n <div \n className=\"ds-reading-progress__bar\" \n style={{ transform: `scaleX(${progress / 100})` }} \n />\n </div>\n );\n }\n);\nReadingProgress.displayName = 'ReadingProgress';\n","import React, { useState } from 'react';\nimport clsx from 'clsx';\nimport { OutboundLink } from '../OutboundLink/OutboundLink';\nimport './VersionedContent.css';\n\n// ============================================================================\n// VersionedUpgradeAlert\n// =============================================================================\n\nexport interface VersionedUpgradeAlertProps extends React.HTMLAttributes<HTMLDivElement> {\n seriesName: string;\n viewedYear: number;\n latestYear: number;\n latestUrl: string;\n deltaSummary?: string;\n}\n\nexport const VersionedUpgradeAlert = React.forwardRef<HTMLDivElement, VersionedUpgradeAlertProps>(\n ({ seriesName, viewedYear, latestYear, latestUrl, deltaSummary, className, ...props }, ref) => {\n const [dismissed, setDismissed] = useState(false);\n\n if (dismissed) return null;\n\n return (\n <div \n ref={ref} \n className={clsx('ds-versioned-alert', className)} \n role=\"alert\"\n {...props}\n >\n <div className=\"ds-versioned-alert__content\">\n <span className=\"ds-versioned-alert__icon\">⚠️</span>\n <div className=\"ds-versioned-alert__text\">\n <strong>Outdated Edition:</strong> You are viewing the {viewedYear} edition of {seriesName}. \n The <strong>{latestYear} edition</strong> is now available.\n {deltaSummary && <span className=\"ds-versioned-alert__delta\"> {deltaSummary}</span>}\n </div>\n </div>\n <div className=\"ds-versioned-alert__actions\">\n <OutboundLink href={latestUrl} context=\"versioned-alert-view-latest\" className=\"ds-versioned-alert__button ds-button ds-button--primary ds-button--sm\" openInNewTab={false}>\n View {latestYear} Edition\n </OutboundLink>\n <button \n className=\"ds-versioned-alert__close\" \n onClick={() => setDismissed(true)}\n aria-label=\"Dismiss alert\"\n >\n ×\n </button>\n </div>\n </div>\n );\n }\n);\nVersionedUpgradeAlert.displayName = 'VersionedUpgradeAlert';\n\n// ============================================================================\n// VersionedSeriesNavigator\n// =============================================================================\n\nexport interface SeriesEdition {\n year: number;\n url: string;\n isCurrent: boolean;\n}\n\nexport interface VersionedSeriesNavigatorProps extends React.HTMLAttributes<HTMLDivElement> {\n seriesName: string;\n hubUrl: string;\n editions: SeriesEdition[];\n}\n\nexport const VersionedSeriesNavigator = React.forwardRef<HTMLDivElement, VersionedSeriesNavigatorProps>(\n ({ seriesName, hubUrl, editions, className, ...props }, ref) => {\n const sortedEditions = [...editions].sort((a, b) => a.year - b.year);\n \n return (\n <div ref={ref} className={clsx('ds-versioned-navigator', className)} {...props}>\n <div className=\"ds-versioned-navigator__header\">\n <span className=\"ds-versioned-navigator__label\">Series</span>\n <OutboundLink href={hubUrl} context=\"versioned-navigator-hub\" className=\"ds-versioned-navigator__title\" openInNewTab={false}>{seriesName} Hub</OutboundLink>\n </div>\n \n <div className=\"ds-versioned-navigator__timeline\">\n {sortedEditions.map((edition, idx) => (\n <React.Fragment key={edition.year}>\n {idx > 0 && <div className=\"ds-versioned-navigator__connector\" />}\n <OutboundLink\n href={edition.url}\n context=\"versioned-navigator-edition\"\n className={clsx(\n 'ds-versioned-navigator__node',\n edition.isCurrent && 'ds-versioned-navigator__node--active'\n )}\n aria-current={edition.isCurrent ? 'page' : undefined}\n openInNewTab={false}\n >\n {edition.year}\n </OutboundLink>\n </React.Fragment>\n ))}\n </div>\n </div>\n );\n }\n);\nVersionedSeriesNavigator.displayName = 'VersionedSeriesNavigator';\n"]}
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
5
|
+
|
|
6
|
+
// src/web/utm/useUtmDefaults.ts
|
|
7
|
+
var UtmContext = react.createContext(null);
|
|
8
|
+
|
|
9
|
+
// src/web/utm/useUtmDefaults.ts
|
|
10
|
+
function useUtmDefaults() {
|
|
11
|
+
return react.useContext(UtmContext);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// src/web/utm/builders.ts
|
|
15
|
+
var PLACEHOLDER_ORIGIN = "https://__placeholder__.internal";
|
|
16
|
+
function buildUtmUrl(baseUrl, params) {
|
|
17
|
+
const isRelative = baseUrl.startsWith("/");
|
|
18
|
+
let url;
|
|
19
|
+
try {
|
|
20
|
+
url = isRelative ? new URL(baseUrl, PLACEHOLDER_ORIGIN) : new URL(baseUrl);
|
|
21
|
+
} catch {
|
|
22
|
+
return baseUrl;
|
|
23
|
+
}
|
|
24
|
+
const existingParams = [];
|
|
25
|
+
url.searchParams.forEach((value, key) => {
|
|
26
|
+
existingParams.push([key, value]);
|
|
27
|
+
});
|
|
28
|
+
for (const [key] of existingParams) {
|
|
29
|
+
url.searchParams.delete(key);
|
|
30
|
+
}
|
|
31
|
+
for (const [key, value] of existingParams) {
|
|
32
|
+
if (!key.startsWith("utm_")) {
|
|
33
|
+
url.searchParams.set(key, value);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
url.searchParams.set("utm_source", params.source);
|
|
37
|
+
url.searchParams.set("utm_medium", params.medium);
|
|
38
|
+
url.searchParams.set("utm_campaign", params.campaign);
|
|
39
|
+
if (params.term !== void 0) {
|
|
40
|
+
url.searchParams.set("utm_term", params.term);
|
|
41
|
+
}
|
|
42
|
+
if (params.content !== void 0) {
|
|
43
|
+
url.searchParams.set("utm_content", params.content);
|
|
44
|
+
}
|
|
45
|
+
if (isRelative) {
|
|
46
|
+
return url.href.replace(PLACEHOLDER_ORIGIN, "");
|
|
47
|
+
}
|
|
48
|
+
return url.href;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// src/web/utm/classifiers.ts
|
|
52
|
+
var INTERNAL_PATTERNS = [
|
|
53
|
+
/^\/(?!\/)/,
|
|
54
|
+
// Relative paths
|
|
55
|
+
/^https?:\/\/(www\.)?sales-mind\.ai/i,
|
|
56
|
+
// Marketing site
|
|
57
|
+
/^https?:\/\/app\.sales-mind\.ai/i,
|
|
58
|
+
// Web app
|
|
59
|
+
/^https?:\/\/apps\.sales-mind\.ai/i,
|
|
60
|
+
// Web app (legacy)
|
|
61
|
+
/^https?:\/\/meet\.sales-mind\.ai/i,
|
|
62
|
+
// Booking
|
|
63
|
+
/^https?:\/\/docs\.sales-mind\.ai/i
|
|
64
|
+
// Docs
|
|
65
|
+
];
|
|
66
|
+
var SYSTEM_PATTERNS = [
|
|
67
|
+
/^https?:\/\/.*\/api\//i,
|
|
68
|
+
// API endpoints
|
|
69
|
+
/^https?:\/\/.*\/webhook/i,
|
|
70
|
+
// Webhooks
|
|
71
|
+
/^https?:\/\/.*\/oauth/i,
|
|
72
|
+
// OAuth callbacks
|
|
73
|
+
/^https?:\/\/.*\/callback/i,
|
|
74
|
+
// Callbacks
|
|
75
|
+
/^https?:\/\/.*\.supabase\.(co|com)/i,
|
|
76
|
+
// Supabase
|
|
77
|
+
/^https?:\/\/.*\.firebaseapp\.com/i,
|
|
78
|
+
// Firebase
|
|
79
|
+
/^https?:\/\/.*\.cloudfunctions\.net/i
|
|
80
|
+
// Cloud Functions
|
|
81
|
+
];
|
|
82
|
+
var ASSET_PATTERNS = [
|
|
83
|
+
/\.(css|js|mjs|map|woff2?|ttf|eot|svg|png|jpe?g|gif|webp|avif|ico|pdf)(\?.*)?$/i
|
|
84
|
+
];
|
|
85
|
+
var CONVERSION_PATTERNS = [
|
|
86
|
+
/^https?:\/\/(www\.)?calendly\.com/i,
|
|
87
|
+
/^https?:\/\/(checkout\.)?stripe\.com/i,
|
|
88
|
+
/^https?:\/\/buy\.stripe\.com/i,
|
|
89
|
+
/^https?:\/\/chromewebstore\.google\.com/i,
|
|
90
|
+
/^https?:\/\/meet\.sales-mind\.ai/i
|
|
91
|
+
];
|
|
92
|
+
var PROTOCOL_EXEMPT = [
|
|
93
|
+
/^mailto:/i,
|
|
94
|
+
/^tel:/i,
|
|
95
|
+
/^#/,
|
|
96
|
+
/^javascript:/i
|
|
97
|
+
];
|
|
98
|
+
function classifyUrl(url) {
|
|
99
|
+
if (PROTOCOL_EXEMPT.some((p) => p.test(url))) return "protocol";
|
|
100
|
+
if (ASSET_PATTERNS.some((p) => p.test(url))) return "asset";
|
|
101
|
+
if (SYSTEM_PATTERNS.some((p) => p.test(url))) return "system";
|
|
102
|
+
if (CONVERSION_PATTERNS.some((p) => p.test(url))) return "conversion";
|
|
103
|
+
if (INTERNAL_PATTERNS.some((p) => p.test(url))) return "internal";
|
|
104
|
+
return "external";
|
|
105
|
+
}
|
|
106
|
+
function requiresUtm(url) {
|
|
107
|
+
const classification = classifyUrl(url);
|
|
108
|
+
return classification === "external" || classification === "conversion";
|
|
109
|
+
}
|
|
110
|
+
function isUtmExempt(url) {
|
|
111
|
+
const classification = classifyUrl(url);
|
|
112
|
+
return classification === "protocol" || classification === "asset" || classification === "system" || classification === "internal";
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// src/components/OutboundLink/outbound-link-utils.ts
|
|
116
|
+
var LEGACY_UTM_SOURCE = "salesmind";
|
|
117
|
+
var EXEMPT_PATTERNS = [
|
|
118
|
+
/^https?:\/\/(www\.)?(stripe\.com|checkout\.stripe\.com|paypal\.com)/i,
|
|
119
|
+
/^https?:\/\/(www\.)?github\.com\/login\/oauth/i
|
|
120
|
+
];
|
|
121
|
+
var isExemptUrl = (urlStr) => {
|
|
122
|
+
if (urlStr.startsWith("mailto:") || urlStr.startsWith("tel:")) return true;
|
|
123
|
+
const classification = classifyUrl(urlStr);
|
|
124
|
+
if (classification === "system" || classification === "protocol" || classification === "asset") {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
return EXEMPT_PATTERNS.some((pattern) => pattern.test(urlStr));
|
|
128
|
+
};
|
|
129
|
+
var appendGovernedUTMs = (href, params, preserveExisting = true) => {
|
|
130
|
+
try {
|
|
131
|
+
const url = new URL(href);
|
|
132
|
+
if (preserveExisting) {
|
|
133
|
+
const hasAll = url.searchParams.has("utm_source") && url.searchParams.has("utm_medium") && url.searchParams.has("utm_campaign");
|
|
134
|
+
if (hasAll) return href;
|
|
135
|
+
}
|
|
136
|
+
return buildUtmUrl(href, params);
|
|
137
|
+
} catch {
|
|
138
|
+
return href;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
var appendUTMs = (href, context, pageSlug, options) => {
|
|
142
|
+
try {
|
|
143
|
+
const url = new URL(href);
|
|
144
|
+
const { mediumOverride = "outbound_link", campaignOverride, preserveExisting = true } = options;
|
|
145
|
+
const utms = {
|
|
146
|
+
utm_source: LEGACY_UTM_SOURCE,
|
|
147
|
+
utm_medium: mediumOverride,
|
|
148
|
+
utm_campaign: campaignOverride || pageSlug,
|
|
149
|
+
utm_content: context
|
|
150
|
+
};
|
|
151
|
+
Object.entries(utms).forEach(([key, value]) => {
|
|
152
|
+
if (value) {
|
|
153
|
+
if (preserveExisting && url.searchParams.has(key)) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
url.searchParams.set(key, value);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
return url.toString();
|
|
160
|
+
} catch {
|
|
161
|
+
return href;
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
var OutboundLink = react.forwardRef(
|
|
165
|
+
({
|
|
166
|
+
href,
|
|
167
|
+
context,
|
|
168
|
+
campaignOverride,
|
|
169
|
+
mediumOverride = "outbound_link",
|
|
170
|
+
preserveExistingUTM = true,
|
|
171
|
+
openInNewTab = true,
|
|
172
|
+
disableTracking = false,
|
|
173
|
+
utmParams,
|
|
174
|
+
onClick,
|
|
175
|
+
children,
|
|
176
|
+
...props
|
|
177
|
+
}, ref) => {
|
|
178
|
+
const contextParams = useUtmDefaults();
|
|
179
|
+
const resolvedUtmParams = utmParams ?? contextParams;
|
|
180
|
+
let hostname = "";
|
|
181
|
+
try {
|
|
182
|
+
const url = new URL(href);
|
|
183
|
+
hostname = url.hostname;
|
|
184
|
+
} catch {
|
|
185
|
+
}
|
|
186
|
+
const [finalHref, setFinalHref] = react.useState(href);
|
|
187
|
+
react.useEffect(() => {
|
|
188
|
+
let isExternal = false;
|
|
189
|
+
let currentMedium = mediumOverride;
|
|
190
|
+
try {
|
|
191
|
+
const url = new URL(href);
|
|
192
|
+
const currentHost = window.location.hostname;
|
|
193
|
+
isExternal = url.hostname !== currentHost;
|
|
194
|
+
if (isExternal && currentHost.includes("sales-mind.ai") && url.hostname.includes("sales-mind.ai")) {
|
|
195
|
+
if (currentMedium === "outbound_link") {
|
|
196
|
+
currentMedium = "cross_subdomain";
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
} catch {
|
|
200
|
+
isExternal = false;
|
|
201
|
+
}
|
|
202
|
+
const isExempt = isExemptUrl(href) || disableTracking;
|
|
203
|
+
if (isExternal && !isExempt) {
|
|
204
|
+
if (resolvedUtmParams) {
|
|
205
|
+
setFinalHref(appendGovernedUTMs(href, resolvedUtmParams, preserveExistingUTM));
|
|
206
|
+
} else {
|
|
207
|
+
const pageSlug = window.location.pathname.replace(/^\/|\/$/g, "") || "home";
|
|
208
|
+
setFinalHref(appendUTMs(href, context, pageSlug, {
|
|
209
|
+
mediumOverride: currentMedium,
|
|
210
|
+
campaignOverride,
|
|
211
|
+
preserveExisting: preserveExistingUTM
|
|
212
|
+
}));
|
|
213
|
+
}
|
|
214
|
+
} else {
|
|
215
|
+
setFinalHref(href);
|
|
216
|
+
}
|
|
217
|
+
}, [href, context, mediumOverride, campaignOverride, preserveExistingUTM, disableTracking, resolvedUtmParams]);
|
|
218
|
+
const handleClick = (e) => {
|
|
219
|
+
if (typeof window === "undefined" || disableTracking) {
|
|
220
|
+
onClick?.(e);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
let clickExternal = false;
|
|
224
|
+
let clickCrossSubdomain = false;
|
|
225
|
+
let clickMedium = mediumOverride;
|
|
226
|
+
try {
|
|
227
|
+
const url = new URL(href);
|
|
228
|
+
const currentHost = window.location.hostname;
|
|
229
|
+
clickExternal = url.hostname !== currentHost;
|
|
230
|
+
if (clickExternal && currentHost.includes("sales-mind.ai") && url.hostname.includes("sales-mind.ai")) {
|
|
231
|
+
clickCrossSubdomain = true;
|
|
232
|
+
if (clickMedium === "outbound_link") {
|
|
233
|
+
clickMedium = "cross_subdomain";
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
} catch {
|
|
237
|
+
}
|
|
238
|
+
if (clickExternal) {
|
|
239
|
+
const detail = {
|
|
240
|
+
destination_domain: hostname,
|
|
241
|
+
destination_url: finalHref,
|
|
242
|
+
utm_medium_type: clickMedium,
|
|
243
|
+
page_slug: window.location.pathname,
|
|
244
|
+
component_location: context,
|
|
245
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
246
|
+
is_cross_subdomain: clickCrossSubdomain
|
|
247
|
+
};
|
|
248
|
+
const event = new CustomEvent("outbound_click", { detail });
|
|
249
|
+
window.dispatchEvent(event);
|
|
250
|
+
}
|
|
251
|
+
onClick?.(e);
|
|
252
|
+
};
|
|
253
|
+
const relParts = [];
|
|
254
|
+
let shouldOpenNewTab = openInNewTab;
|
|
255
|
+
try {
|
|
256
|
+
const url = new URL(href);
|
|
257
|
+
if (typeof window !== "undefined") {
|
|
258
|
+
const currentHost = window.location.hostname;
|
|
259
|
+
if (url.hostname !== currentHost && currentHost.includes("sales-mind.ai") && url.hostname.includes("sales-mind.ai")) {
|
|
260
|
+
shouldOpenNewTab = false;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
} catch {
|
|
264
|
+
}
|
|
265
|
+
if (shouldOpenNewTab) relParts.push("noopener", "noreferrer");
|
|
266
|
+
if (mediumOverride === "citation") relParts.push("nofollow");
|
|
267
|
+
const rel = relParts.length > 0 ? relParts.join(" ") : void 0;
|
|
268
|
+
return (
|
|
269
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
270
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
271
|
+
"a",
|
|
272
|
+
{
|
|
273
|
+
ref,
|
|
274
|
+
href: finalHref,
|
|
275
|
+
target: shouldOpenNewTab ? "_blank" : void 0,
|
|
276
|
+
rel,
|
|
277
|
+
onClick: handleClick,
|
|
278
|
+
...props,
|
|
279
|
+
children
|
|
280
|
+
}
|
|
281
|
+
)
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
);
|
|
285
|
+
OutboundLink.displayName = "OutboundLink";
|
|
286
|
+
|
|
287
|
+
exports.OutboundLink = OutboundLink;
|
|
288
|
+
exports.UtmContext = UtmContext;
|
|
289
|
+
exports.appendGovernedUTMs = appendGovernedUTMs;
|
|
290
|
+
exports.appendUTMs = appendUTMs;
|
|
291
|
+
exports.buildUtmUrl = buildUtmUrl;
|
|
292
|
+
exports.classifyUrl = classifyUrl;
|
|
293
|
+
exports.isExemptUrl = isExemptUrl;
|
|
294
|
+
exports.isUtmExempt = isUtmExempt;
|
|
295
|
+
exports.requiresUtm = requiresUtm;
|
|
296
|
+
exports.useUtmDefaults = useUtmDefaults;
|
|
297
|
+
//# sourceMappingURL=out.js.map
|
|
298
|
+
//# sourceMappingURL=chunk-LJADZITX.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/web/utm/useUtmDefaults.ts","../src/web/utm/utm-context.ts","../src/web/utm/builders.ts","../src/web/utm/classifiers.ts","../src/components/OutboundLink/outbound-link-utils.ts","../src/components/OutboundLink/OutboundLink.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useContext } from 'react';\nimport { UtmContext } from './utm-context';\nimport type { UtmParams } from './types';\n\n/**\n * Read the nearest UtmProvider's default params.\n * Returns `null` when no provider is present (callers should fall back gracefully).\n */\nexport function useUtmDefaults(): UtmParams | null {\n return useContext(UtmContext);\n}\n","import { createContext } from 'react';\nimport type { UtmParams } from './types';\n\n/** Internal React context instance. Import via UtmProvider / useUtmDefaults — do not use directly. */\nexport const UtmContext = createContext<UtmParams | null>(null);\n","/* ============================================================================\n UTM URL Builders\n ============================================================================ */\n\nimport type { UtmParams } from './types';\n\n/** Placeholder origin used internally to parse relative URLs. Never appears in output. */\nconst PLACEHOLDER_ORIGIN = 'https://__placeholder__.internal';\n\n/**\n * Build a URL with UTM parameters appended.\n *\n * - Supports both absolute and relative URLs.\n * - Preserves existing query parameters and hash fragments.\n * - Always emits params in canonical order: source → medium → campaign → term → content.\n * - Omits optional params (term, content) when undefined.\n *\n * @example\n * buildUtmUrl('https://app.sales-mind.ai/register', { source: 'linkedin', medium: 'dm', campaign: 'discoveryCall' })\n * // → 'https://app.sales-mind.ai/register?utm_source=linkedin&utm_medium=dm&utm_campaign=discoveryCall'\n *\n * buildUtmUrl('/pricing', { source: 'website', medium: 'webHome', campaign: 'trial' })\n * // → '/pricing?utm_source=website&utm_medium=webHome&utm_campaign=trial'\n */\nexport function buildUtmUrl(baseUrl: string, params: UtmParams): string {\n const isRelative = baseUrl.startsWith('/');\n\n let url: URL;\n try {\n url = isRelative ? new URL(baseUrl, PLACEHOLDER_ORIGIN) : new URL(baseUrl);\n } catch {\n // If URL parsing fails entirely, return the base URL unchanged.\n return baseUrl;\n }\n\n // Preserve existing params by collecting them first, then clearing and re-adding in order.\n const existingParams: [string, string][] = [];\n url.searchParams.forEach((value, key) => {\n existingParams.push([key, value]);\n });\n\n // Clear all params to rebuild in canonical order.\n for (const [key] of existingParams) {\n url.searchParams.delete(key);\n }\n\n // Re-add existing non-UTM params first.\n for (const [key, value] of existingParams) {\n if (!key.startsWith('utm_')) {\n url.searchParams.set(key, value);\n }\n }\n\n // Append UTM params in canonical order.\n url.searchParams.set('utm_source', params.source);\n url.searchParams.set('utm_medium', params.medium);\n url.searchParams.set('utm_campaign', params.campaign);\n if (params.term !== undefined) {\n url.searchParams.set('utm_term', params.term);\n }\n if (params.content !== undefined) {\n url.searchParams.set('utm_content', params.content);\n }\n\n if (isRelative) {\n // Strip placeholder origin to return a relative path.\n return url.href.replace(PLACEHOLDER_ORIGIN, '');\n }\n\n return url.href;\n}\n","/* ============================================================================\n URL Classification & UTM Enforcement Logic\n ============================================================================\n Determines whether a URL requires UTM parameters based on its type.\n No imports from validators — avoids circular dependency.\n ============================================================================ */\n\nimport type { UrlClassification } from './types';\n\n// ── Patterns ─────────────────────────────────────────────────────────────────\n\n/** Internal domains — UTMs not required for same-origin navigation. */\nconst INTERNAL_PATTERNS = [\n /^\\/(?!\\/)/, // Relative paths\n /^https?:\\/\\/(www\\.)?sales-mind\\.ai/i, // Marketing site\n /^https?:\\/\\/app\\.sales-mind\\.ai/i, // Web app\n /^https?:\\/\\/apps\\.sales-mind\\.ai/i, // Web app (legacy)\n /^https?:\\/\\/meet\\.sales-mind\\.ai/i, // Booking\n /^https?:\\/\\/docs\\.sales-mind\\.ai/i, // Docs\n];\n\n/** System endpoints — never receive UTMs. */\nconst SYSTEM_PATTERNS = [\n /^https?:\\/\\/.*\\/api\\//i, // API endpoints\n /^https?:\\/\\/.*\\/webhook/i, // Webhooks\n /^https?:\\/\\/.*\\/oauth/i, // OAuth callbacks\n /^https?:\\/\\/.*\\/callback/i, // Callbacks\n /^https?:\\/\\/.*\\.supabase\\.(co|com)/i, // Supabase\n /^https?:\\/\\/.*\\.firebaseapp\\.com/i, // Firebase\n /^https?:\\/\\/.*\\.cloudfunctions\\.net/i, // Cloud Functions\n];\n\n/** Static assets — never receive UTMs. */\nconst ASSET_PATTERNS = [\n /\\.(css|js|mjs|map|woff2?|ttf|eot|svg|png|jpe?g|gif|webp|avif|ico|pdf)(\\?.*)?$/i,\n];\n\n/** Conversion destinations — always require UTMs. */\nconst CONVERSION_PATTERNS = [\n /^https?:\\/\\/(www\\.)?calendly\\.com/i,\n /^https?:\\/\\/(checkout\\.)?stripe\\.com/i,\n /^https?:\\/\\/buy\\.stripe\\.com/i,\n /^https?:\\/\\/chromewebstore\\.google\\.com/i,\n /^https?:\\/\\/meet\\.sales-mind\\.ai/i,\n];\n\n/** Protocol-level links — never receive UTMs. */\nconst PROTOCOL_EXEMPT = [\n /^mailto:/i,\n /^tel:/i,\n /^#/,\n /^javascript:/i,\n];\n\n// ── Classification ───────────────────────────────────────────────────────────\n\n/**\n * Classify a URL to determine its type.\n *\n * Classification order (first match wins):\n * 1. Protocol links (mailto, tel, anchor)\n * 2. Static assets\n * 3. System endpoints (API, webhooks, OAuth)\n * 4. Conversion destinations (Calendly, Stripe, Chrome Store)\n * 5. Internal (*.sales-mind.ai)\n * 6. External (everything else)\n */\nexport function classifyUrl(url: string): UrlClassification {\n // Protocol links\n if (PROTOCOL_EXEMPT.some(p => p.test(url))) return 'protocol';\n\n // Static assets\n if (ASSET_PATTERNS.some(p => p.test(url))) return 'asset';\n\n // System endpoints\n if (SYSTEM_PATTERNS.some(p => p.test(url))) return 'system';\n\n // Conversion destinations\n if (CONVERSION_PATTERNS.some(p => p.test(url))) return 'conversion';\n\n // Internal\n if (INTERNAL_PATTERNS.some(p => p.test(url))) return 'internal';\n\n // Everything else is external\n return 'external';\n}\n\n/**\n * Determine whether a URL requires UTM parameters.\n *\n * UTMs are mandatory for:\n * - External third-party destinations\n * - Conversion destinations (Calendly, Stripe, Chrome Web Store)\n *\n * UTMs are NOT required for:\n * - Internal navigation\n * - System endpoints\n * - Static assets\n * - Protocol links\n */\nexport function requiresUtm(url: string): boolean {\n const classification = classifyUrl(url);\n return classification === 'external' || classification === 'conversion';\n}\n\n/**\n * Check if a URL is explicitly exempt from UTM requirements.\n */\nexport function isUtmExempt(url: string): boolean {\n const classification = classifyUrl(url);\n return classification === 'protocol'\n || classification === 'asset'\n || classification === 'system'\n || classification === 'internal';\n}\n","import type { UtmParams } from '../../web/utm/types';\nimport { buildUtmUrl } from '../../web/utm/builders';\nimport { classifyUrl } from '../../web/utm/classifiers';\n\n/**\n * @deprecated Use governed `utmParams` prop on OutboundLink instead.\n * Legacy default source — superseded by governed UTM_SOURCES enum.\n */\nconst LEGACY_UTM_SOURCE = 'salesmind';\n\nconst EXEMPT_PATTERNS = [\n /^https?:\\/\\/(www\\.)?(stripe\\.com|checkout\\.stripe\\.com|paypal\\.com)/i,\n /^https?:\\/\\/(www\\.)?github\\.com\\/login\\/oauth/i,\n];\n\n/**\n * Check if a URL is exempt from UTM tagging.\n * Uses both legacy patterns and governed URL classification.\n */\nexport const isExemptUrl = (urlStr: string): boolean => {\n if (urlStr.startsWith('mailto:') || urlStr.startsWith('tel:')) return true;\n\n // Governed classification: system/protocol/asset URLs are exempt\n const classification = classifyUrl(urlStr);\n if (classification === 'system' || classification === 'protocol' || classification === 'asset') {\n return true;\n }\n\n return EXEMPT_PATTERNS.some(pattern => pattern.test(urlStr));\n};\n\n/**\n * Append governed UTM parameters to a URL using `buildUtmUrl`.\n * Preferred over the legacy `appendUTMs` function.\n */\nexport const appendGovernedUTMs = (\n href: string,\n params: UtmParams,\n preserveExisting = true,\n): string => {\n try {\n const url = new URL(href);\n\n // If preserveExisting and all UTM params are already set, return unchanged\n if (preserveExisting) {\n const hasAll = url.searchParams.has('utm_source')\n && url.searchParams.has('utm_medium')\n && url.searchParams.has('utm_campaign');\n if (hasAll) return href;\n }\n\n return buildUtmUrl(href, params);\n } catch {\n return href;\n }\n};\n\n/**\n * @deprecated Prefer `appendGovernedUTMs` with governed `UtmParams`.\n *\n * Legacy UTM append function. Uses non-governed defaults:\n * - utm_source = 'salesmind' (not in governed enum)\n * - utm_medium = 'outbound_link' (snake_case, not in governed enum)\n *\n * Retained for backward compatibility. Consumers should migrate to\n * the `utmParams` prop on OutboundLink.\n */\nexport const appendUTMs = (\n href: string,\n context: string,\n pageSlug: string,\n options: {\n mediumOverride?: string;\n campaignOverride?: string;\n preserveExisting?: boolean;\n }\n): string => {\n try {\n const url = new URL(href);\n const { mediumOverride = 'outbound_link', campaignOverride, preserveExisting = true } = options;\n\n const utms = {\n utm_source: LEGACY_UTM_SOURCE,\n utm_medium: mediumOverride,\n utm_campaign: campaignOverride || pageSlug,\n utm_content: context,\n };\n\n Object.entries(utms).forEach(([key, value]) => {\n if (value) {\n if (preserveExisting && url.searchParams.has(key)) {\n // Do not override if preserve is true\n return;\n }\n url.searchParams.set(key, value);\n }\n });\n\n return url.toString();\n } catch {\n return href; // Return original if not valid URL (e.g. relative)\n }\n};\n","import React, { AnchorHTMLAttributes, forwardRef, MouseEvent, useState, useEffect } from 'react';\nimport type { UtmParams } from '../../web/utm/types';\nimport { useUtmDefaults } from '../../web/utm/useUtmDefaults';\nimport { isExemptUrl, appendUTMs, appendGovernedUTMs } from './outbound-link-utils';\n\nexport interface OutboundLinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {\n href: string;\n context: string;\n campaignOverride?: string;\n mediumOverride?: string;\n preserveExistingUTM?: boolean;\n openInNewTab?: boolean;\n disableTracking?: boolean;\n /**\n * Governed UTM parameters. When provided, the link uses the UTM governance\n * system (buildUtmUrl) instead of the legacy appendUTMs approach.\n *\n * Preferred for all new code. Existing usages without utmParams continue\n * to work via the legacy path.\n */\n utmParams?: UtmParams;\n children: React.ReactNode;\n}\n\nexport interface OutboundClickEventDetail {\n destination_domain: string;\n destination_url: string;\n utm_medium_type: string;\n page_slug: string;\n component_location: string;\n timestamp: string;\n is_cross_subdomain: boolean;\n}\n\nexport const OutboundLink = forwardRef<HTMLAnchorElement, OutboundLinkProps>(\n (\n {\n href,\n context,\n campaignOverride,\n mediumOverride = 'outbound_link',\n preserveExistingUTM = true,\n openInNewTab = true,\n disableTracking = false,\n utmParams,\n onClick,\n children,\n ...props\n },\n ref\n ) => {\n // ── Resolve UTM params: explicit prop > context > legacy fallback ──\n const contextParams = useUtmDefaults();\n const resolvedUtmParams = utmParams ?? contextParams;\n\n // Parse hostname for analytics events (safe on both server/client)\n let hostname = '';\n try {\n const url = new URL(href);\n hostname = url.hostname;\n } catch {\n // Relative URL or invalid — hostname stays empty\n }\n\n // SSR and initial client render use the plain href to avoid hydration\n // mismatches. UTM params are decorated after hydration via useEffect.\n const [finalHref, setFinalHref] = useState(href);\n\n useEffect(() => {\n let isExternal = false;\n let currentMedium = mediumOverride;\n\n try {\n const url = new URL(href);\n const currentHost = window.location.hostname;\n isExternal = url.hostname !== currentHost;\n\n if (isExternal && currentHost.includes('sales-mind.ai') && url.hostname.includes('sales-mind.ai')) {\n if (currentMedium === 'outbound_link') {\n currentMedium = 'cross_subdomain';\n }\n }\n } catch {\n isExternal = false;\n }\n\n const isExempt = isExemptUrl(href) || disableTracking;\n\n if (isExternal && !isExempt) {\n if (resolvedUtmParams) {\n // Governed path: use buildUtmUrl via appendGovernedUTMs\n setFinalHref(appendGovernedUTMs(href, resolvedUtmParams, preserveExistingUTM));\n } else {\n // Legacy path: use appendUTMs with non-governed defaults\n const pageSlug = window.location.pathname.replace(/^\\/|\\/$/g, '') || 'home';\n setFinalHref(appendUTMs(href, context, pageSlug, {\n mediumOverride: currentMedium,\n campaignOverride,\n preserveExisting: preserveExistingUTM,\n }));\n }\n } else {\n setFinalHref(href);\n }\n }, [href, context, mediumOverride, campaignOverride, preserveExistingUTM, disableTracking, resolvedUtmParams]);\n\n const handleClick = (e: MouseEvent<HTMLAnchorElement>) => {\n if (typeof window === 'undefined' || disableTracking) {\n onClick?.(e);\n return;\n }\n\n let clickExternal = false;\n let clickCrossSubdomain = false;\n let clickMedium = mediumOverride;\n\n try {\n const url = new URL(href);\n const currentHost = window.location.hostname;\n clickExternal = url.hostname !== currentHost;\n\n if (clickExternal && currentHost.includes('sales-mind.ai') && url.hostname.includes('sales-mind.ai')) {\n clickCrossSubdomain = true;\n if (clickMedium === 'outbound_link') {\n clickMedium = 'cross_subdomain';\n }\n }\n } catch { /* relative URL */ }\n\n if (clickExternal) {\n const detail: OutboundClickEventDetail = {\n destination_domain: hostname,\n destination_url: finalHref,\n utm_medium_type: clickMedium,\n page_slug: window.location.pathname,\n component_location: context,\n timestamp: new Date().toISOString(),\n is_cross_subdomain: clickCrossSubdomain,\n };\n\n const event = new CustomEvent('outbound_click', { detail });\n window.dispatchEvent(event);\n }\n\n onClick?.(e);\n };\n\n // Determine SEO attributes\n const relParts = [];\n \n // Check if it's cross-subdomain for target logic (usually open internal links in same tab, external in new)\n let shouldOpenNewTab = openInNewTab;\n try {\n const url = new URL(href);\n if (typeof window !== 'undefined') {\n const currentHost = window.location.hostname;\n if (url.hostname !== currentHost && currentHost.includes('sales-mind.ai') && url.hostname.includes('sales-mind.ai')) {\n shouldOpenNewTab = false; // By default, prefer same tab for cross-subdomain ecosystem links\n }\n }\n } catch { /* empty */ }\n\n if (shouldOpenNewTab) relParts.push('noopener', 'noreferrer');\n if (mediumOverride === 'citation') relParts.push('nofollow');\n const rel = relParts.length > 0 ? relParts.join(' ') : undefined;\n\n return (\n // eslint-disable-next-line no-restricted-syntax\n <a\n ref={ref}\n href={finalHref}\n target={shouldOpenNewTab ? '_blank' : undefined}\n rel={rel}\n onClick={handleClick}\n {...props}\n >\n {children}\n </a>\n );\n }\n);\n\nOutboundLink.displayName = 'OutboundLink';\n"]}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkMQRB634A_cjs = require('./chunk-MQRB634A.cjs');
|
|
4
|
+
var chunkEM7JHRYW_cjs = require('./chunk-EM7JHRYW.cjs');
|
|
5
|
+
var chunkMDB2WCRQ_cjs = require('./chunk-MDB2WCRQ.cjs');
|
|
6
|
+
var react = require('react');
|
|
7
|
+
var clsx = require('clsx');
|
|
8
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
9
|
+
|
|
10
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
+
|
|
12
|
+
var clsx__default = /*#__PURE__*/_interopDefault(clsx);
|
|
13
|
+
|
|
14
|
+
var HeroSection = react.forwardRef(
|
|
15
|
+
({
|
|
16
|
+
variant = "left",
|
|
17
|
+
title,
|
|
18
|
+
titleAs: TitleElement = "h1",
|
|
19
|
+
subtitle,
|
|
20
|
+
eyebrow,
|
|
21
|
+
eyebrowAs: EyebrowElement = "span",
|
|
22
|
+
primaryCta,
|
|
23
|
+
secondaryCta,
|
|
24
|
+
media,
|
|
25
|
+
mediaBrowserFrame = false,
|
|
26
|
+
floatingElement,
|
|
27
|
+
floatingPosition = "bottom-left",
|
|
28
|
+
withGrid = false,
|
|
29
|
+
withGlow = false,
|
|
30
|
+
align,
|
|
31
|
+
className,
|
|
32
|
+
children,
|
|
33
|
+
...props
|
|
34
|
+
}, ref) => {
|
|
35
|
+
const isSplit = variant === "split";
|
|
36
|
+
const isCenter = variant === "center";
|
|
37
|
+
const textAlignment = align || (isCenter ? "center" : "left");
|
|
38
|
+
const ContentBlock = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx__default.default("ds-hero__content", `ds-hero__content--${textAlignment}`), children: [
|
|
39
|
+
eyebrow && /* @__PURE__ */ jsxRuntime.jsx(EyebrowElement, { className: "ds-section-header__eyebrow", style: { marginBottom: "var(--space-2)" }, children: eyebrow }),
|
|
40
|
+
/* @__PURE__ */ jsxRuntime.jsx(TitleElement, { className: "ds-hero__title", children: title }),
|
|
41
|
+
subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ds-hero__subtitle", children: subtitle }),
|
|
42
|
+
(primaryCta || secondaryCta) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-hero__actions", children: [
|
|
43
|
+
primaryCta,
|
|
44
|
+
secondaryCta
|
|
45
|
+
] }),
|
|
46
|
+
children
|
|
47
|
+
] });
|
|
48
|
+
const MediaBlock = media && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-hero__media-wrapper", children: [
|
|
49
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx__default.default("ds-hero__media", mediaBrowserFrame && "ds-hero__media--browser"), children: media }),
|
|
50
|
+
floatingElement && /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx__default.default("ds-hero__float", `ds-hero__float--${floatingPosition}`), children: floatingElement })
|
|
51
|
+
] });
|
|
52
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
53
|
+
chunkEM7JHRYW_cjs.SectionShell,
|
|
54
|
+
{
|
|
55
|
+
ref,
|
|
56
|
+
className: clsx__default.default(
|
|
57
|
+
"ds-hero",
|
|
58
|
+
`ds-hero--${variant}`,
|
|
59
|
+
withGrid && "ds-hero--bg-grid",
|
|
60
|
+
withGlow && "ds-hero--bg-glow",
|
|
61
|
+
className
|
|
62
|
+
),
|
|
63
|
+
padding: "lg",
|
|
64
|
+
...props,
|
|
65
|
+
children: isSplit ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
66
|
+
"div",
|
|
67
|
+
{
|
|
68
|
+
style: {
|
|
69
|
+
display: "grid",
|
|
70
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 500px), 1fr))",
|
|
71
|
+
gap: "var(--space-16)",
|
|
72
|
+
alignItems: "center"
|
|
73
|
+
},
|
|
74
|
+
children: [
|
|
75
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunkMDB2WCRQ_cjs.Box, { children: ContentBlock }),
|
|
76
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunkMDB2WCRQ_cjs.Box, { children: MediaBlock })
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(chunkMQRB634A_cjs.Stack, { gap: 16, align: isCenter ? "center" : "start", children: [
|
|
80
|
+
ContentBlock,
|
|
81
|
+
MediaBlock && /* @__PURE__ */ jsxRuntime.jsx(
|
|
82
|
+
chunkMDB2WCRQ_cjs.Box,
|
|
83
|
+
{
|
|
84
|
+
style: {
|
|
85
|
+
width: "100%",
|
|
86
|
+
display: "flex",
|
|
87
|
+
justifyContent: isCenter ? "center" : "flex-start"
|
|
88
|
+
},
|
|
89
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "100%", maxWidth: isCenter ? "1200px" : "100%" }, children: MediaBlock })
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
] })
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
HeroSection.displayName = "HeroSection";
|
|
98
|
+
var FeatureCard = ({ item }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-feature-card", children: [
|
|
99
|
+
item.icon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-feature-card__icon", children: item.icon }),
|
|
100
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "ds-feature-card__title", children: item.title }),
|
|
101
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-feature-card__description", children: item.description }),
|
|
102
|
+
item.cta && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-feature-card__cta", children: item.cta })
|
|
103
|
+
] });
|
|
104
|
+
var FeatureRow = ({ item }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-feature-row", children: [
|
|
105
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-feature-row__content", children: [
|
|
106
|
+
item.step && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-feature-row__step", children: [
|
|
107
|
+
"STEP ",
|
|
108
|
+
item.step
|
|
109
|
+
] }),
|
|
110
|
+
item.icon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-feature-card__icon", children: item.icon }),
|
|
111
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "ds-section-header__title", style: { fontSize: "var(--font-size-2xl)" }, children: item.title }),
|
|
112
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-section-header__subtitle", style: { fontSize: "var(--font-size-lg)" }, children: item.description }),
|
|
113
|
+
item.cta && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-hero__actions", children: item.cta })
|
|
114
|
+
] }),
|
|
115
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-feature-row__media", children: item.media || /* @__PURE__ */ jsxRuntime.jsx("div", { style: { paddingBottom: "56.25%", background: "var(--glass-base-active)" } }) })
|
|
116
|
+
] });
|
|
117
|
+
var FeatureSection = react.forwardRef(
|
|
118
|
+
({
|
|
119
|
+
variant = "grid",
|
|
120
|
+
columns = 3,
|
|
121
|
+
features,
|
|
122
|
+
title,
|
|
123
|
+
subtitle,
|
|
124
|
+
eyebrow,
|
|
125
|
+
alignHeader = "center",
|
|
126
|
+
className,
|
|
127
|
+
...props
|
|
128
|
+
}, ref) => {
|
|
129
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(chunkEM7JHRYW_cjs.SectionShell, { ref, className: clsx__default.default("ds-feature-section", className), ...props, children: [
|
|
130
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunkEM7JHRYW_cjs.SectionHeader, { title, subtitle, eyebrow, align: alignHeader }),
|
|
131
|
+
variant === "grid" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx__default.default("ds-feature-grid", `ds-feature-grid--${columns}-col`), children: features.map((feature, index) => /* @__PURE__ */ jsxRuntime.jsx(FeatureCard, { item: feature }, index)) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-feature-zigzag", children: features.map((feature, index) => /* @__PURE__ */ jsxRuntime.jsx(FeatureRow, { item: feature }, index)) })
|
|
132
|
+
] });
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
FeatureSection.displayName = "FeatureSection";
|
|
136
|
+
var CTASection = react.forwardRef(
|
|
137
|
+
({
|
|
138
|
+
variant = "center",
|
|
139
|
+
title,
|
|
140
|
+
description,
|
|
141
|
+
primaryCta,
|
|
142
|
+
secondaryCta,
|
|
143
|
+
actions,
|
|
144
|
+
className,
|
|
145
|
+
children,
|
|
146
|
+
...props
|
|
147
|
+
}, ref) => {
|
|
148
|
+
const isBoxed = variant === "boxed";
|
|
149
|
+
const effectiveVariant = isBoxed ? "center" : variant;
|
|
150
|
+
const Content = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx__default.default("ds-cta-section", `ds-cta-section--${effectiveVariant}`), children: [
|
|
151
|
+
effectiveVariant === "split" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-cta-section--split", children: [
|
|
152
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-cta-content", children: [
|
|
153
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "ds-cta-title", children: title }),
|
|
154
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ds-cta-description", children: description })
|
|
155
|
+
] }),
|
|
156
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-cta-actions", children: actions || /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
157
|
+
primaryCta,
|
|
158
|
+
secondaryCta
|
|
159
|
+
] }) })
|
|
160
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-cta-content", children: [
|
|
161
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "ds-cta-title", children: title }),
|
|
162
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ds-cta-description", children: description }),
|
|
163
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-cta-actions", children: actions || /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
164
|
+
primaryCta,
|
|
165
|
+
secondaryCta
|
|
166
|
+
] }) })
|
|
167
|
+
] }),
|
|
168
|
+
children
|
|
169
|
+
] });
|
|
170
|
+
return /* @__PURE__ */ jsxRuntime.jsx(chunkEM7JHRYW_cjs.SectionShell, { ref, className: clsx__default.default(className), ...props, children: isBoxed ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-cta-card", children: Content }) : Content });
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
CTASection.displayName = "CTASection";
|
|
174
|
+
var StatsSection = react.forwardRef(
|
|
175
|
+
({ stats, title, subtitle, eyebrow, className, ...props }, ref) => {
|
|
176
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(chunkEM7JHRYW_cjs.SectionShell, { ref, className: clsx__default.default("ds-stats-section", className), ...props, children: [
|
|
177
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunkEM7JHRYW_cjs.SectionHeader, { title, subtitle, eyebrow }),
|
|
178
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-stats-grid", children: stats.map((stat, idx) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-stat-card", children: [
|
|
179
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-stat-value", children: [
|
|
180
|
+
stat.prefix,
|
|
181
|
+
stat.value,
|
|
182
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-stat-suffix", children: stat.suffix })
|
|
183
|
+
] }),
|
|
184
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-stat-label", children: stat.label })
|
|
185
|
+
] }, idx)) })
|
|
186
|
+
] });
|
|
187
|
+
}
|
|
188
|
+
);
|
|
189
|
+
StatsSection.displayName = "StatsSection";
|
|
190
|
+
|
|
191
|
+
exports.CTASection = CTASection;
|
|
192
|
+
exports.FeatureSection = FeatureSection;
|
|
193
|
+
exports.HeroSection = HeroSection;
|
|
194
|
+
exports.StatsSection = StatsSection;
|
|
195
|
+
//# sourceMappingURL=out.js.map
|
|
196
|
+
//# sourceMappingURL=chunk-LSR7JYVH.cjs.map
|