@sonordev/agency-site-kit 0.3.1 → 0.4.0

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.
Files changed (369) hide show
  1. package/README.md +302 -0
  2. package/bin/setup.mjs +79 -0
  3. package/dist/{chunk-RXBK2EOE.js → chunk-4IES23GV.js} +3 -3
  4. package/dist/{chunk-RXBK2EOE.js.map → chunk-4IES23GV.js.map} +1 -1
  5. package/dist/chunk-4N7ENJ7L.cjs +108 -0
  6. package/dist/chunk-4N7ENJ7L.cjs.map +1 -0
  7. package/dist/{chunk-WNR4KNG4.cjs → chunk-5MEZU3OG.cjs} +4 -4
  8. package/dist/{chunk-WNR4KNG4.cjs.map → chunk-5MEZU3OG.cjs.map} +1 -1
  9. package/dist/chunk-7ZHRMWJU.cjs +306 -0
  10. package/dist/chunk-7ZHRMWJU.cjs.map +1 -0
  11. package/dist/chunk-CVT7I5BQ.js +71 -0
  12. package/dist/chunk-CVT7I5BQ.js.map +1 -0
  13. package/dist/chunk-HQGAX2LI.cjs +8 -0
  14. package/dist/chunk-HQGAX2LI.cjs.map +1 -0
  15. package/dist/chunk-KXLROAO5.js +291 -0
  16. package/dist/chunk-KXLROAO5.js.map +1 -0
  17. package/dist/chunk-L4EOQVRJ.js +6 -0
  18. package/dist/chunk-L4EOQVRJ.js.map +1 -0
  19. package/dist/chunk-L7E3UHQC.cjs +535 -0
  20. package/dist/chunk-L7E3UHQC.cjs.map +1 -0
  21. package/dist/chunk-NI4FVCLS.cjs +32 -0
  22. package/dist/chunk-NI4FVCLS.cjs.map +1 -0
  23. package/dist/chunk-NIZJLONK.js +106 -0
  24. package/dist/chunk-NIZJLONK.js.map +1 -0
  25. package/dist/chunk-QDXZ27R7.js +33 -0
  26. package/dist/chunk-QDXZ27R7.js.map +1 -0
  27. package/dist/{chunk-TVFXN6W6.js → chunk-QL6KVIFR.js} +8 -4
  28. package/dist/chunk-QL6KVIFR.js.map +1 -0
  29. package/dist/chunk-UNTOEWQL.js +504 -0
  30. package/dist/chunk-UNTOEWQL.js.map +1 -0
  31. package/dist/chunk-XJ434N7I.js +30 -0
  32. package/dist/chunk-XJ434N7I.js.map +1 -0
  33. package/dist/chunk-XLK77USA.js +45 -0
  34. package/dist/chunk-XLK77USA.js.map +1 -0
  35. package/dist/{chunk-EE75WRCM.cjs → chunk-XOWSXZYW.cjs} +8 -4
  36. package/dist/chunk-XOWSXZYW.cjs.map +1 -0
  37. package/dist/chunk-ZINKVJQU.js +67 -0
  38. package/dist/chunk-ZINKVJQU.js.map +1 -0
  39. package/dist/index.cjs +29 -31
  40. package/dist/index.cjs.map +1 -1
  41. package/dist/index.d.cts +17 -9
  42. package/dist/index.d.ts +17 -9
  43. package/dist/index.js +7 -9
  44. package/dist/index.js.map +1 -1
  45. package/dist/layout/index.cjs +3 -3
  46. package/dist/layout/index.d.cts +1 -1
  47. package/dist/layout/index.d.ts +1 -1
  48. package/dist/layout/index.js +2 -2
  49. package/dist/portfolio/client.cjs +342 -12
  50. package/dist/portfolio/client.cjs.map +1 -1
  51. package/dist/portfolio/client.d.cts +11 -88
  52. package/dist/portfolio/client.d.ts +11 -88
  53. package/dist/portfolio/client.js +150 -4
  54. package/dist/portfolio/client.js.map +1 -1
  55. package/dist/portfolio/components/PortfolioAnalytics.cjs +87 -0
  56. package/dist/portfolio/components/PortfolioAnalytics.cjs.map +1 -0
  57. package/dist/portfolio/components/PortfolioAnalytics.d.cts +5 -0
  58. package/dist/portfolio/components/PortfolioAnalytics.d.ts +5 -0
  59. package/dist/portfolio/components/PortfolioAnalytics.js +9 -0
  60. package/dist/portfolio/components/PortfolioAnalytics.js.map +1 -0
  61. package/dist/portfolio/components/PortfolioErrorFallback.cjs +65 -0
  62. package/dist/portfolio/components/PortfolioErrorFallback.cjs.map +1 -0
  63. package/dist/portfolio/components/PortfolioErrorFallback.d.cts +22 -0
  64. package/dist/portfolio/components/PortfolioErrorFallback.d.ts +22 -0
  65. package/dist/portfolio/components/PortfolioErrorFallback.js +9 -0
  66. package/dist/portfolio/components/PortfolioErrorFallback.js.map +1 -0
  67. package/dist/portfolio/components/PortfolioLeadCTA.cjs +91 -0
  68. package/dist/portfolio/components/PortfolioLeadCTA.cjs.map +1 -0
  69. package/dist/portfolio/components/PortfolioLeadCTA.d.cts +34 -0
  70. package/dist/portfolio/components/PortfolioLeadCTA.d.ts +34 -0
  71. package/dist/portfolio/components/PortfolioLeadCTA.js +9 -0
  72. package/dist/portfolio/components/PortfolioLeadCTA.js.map +1 -0
  73. package/dist/portfolio/index.cjs +19 -20
  74. package/dist/portfolio/index.d.cts +133 -7
  75. package/dist/portfolio/index.d.ts +133 -7
  76. package/dist/portfolio/index.js +6 -7
  77. package/dist/portfolio/primitives/AnimatedCounter.cjs +88 -0
  78. package/dist/portfolio/primitives/AnimatedCounter.cjs.map +1 -0
  79. package/dist/portfolio/primitives/AnimatedCounter.d.cts +22 -0
  80. package/dist/portfolio/primitives/AnimatedCounter.d.ts +22 -0
  81. package/dist/portfolio/primitives/AnimatedCounter.js +68 -0
  82. package/dist/portfolio/primitives/AnimatedCounter.js.map +1 -0
  83. package/dist/portfolio/primitives/AnnotatedImage.cjs +320 -0
  84. package/dist/portfolio/primitives/AnnotatedImage.cjs.map +1 -0
  85. package/dist/portfolio/primitives/AnnotatedImage.d.cts +18 -0
  86. package/dist/portfolio/primitives/AnnotatedImage.d.ts +18 -0
  87. package/dist/portfolio/primitives/AnnotatedImage.js +264 -0
  88. package/dist/portfolio/primitives/AnnotatedImage.js.map +1 -0
  89. package/dist/portfolio/primitives/BeforeAfterSlider.cjs +348 -0
  90. package/dist/portfolio/primitives/BeforeAfterSlider.cjs.map +1 -0
  91. package/dist/portfolio/primitives/BeforeAfterSlider.d.cts +13 -0
  92. package/dist/portfolio/primitives/BeforeAfterSlider.d.ts +13 -0
  93. package/dist/portfolio/primitives/BeforeAfterSlider.js +292 -0
  94. package/dist/portfolio/primitives/BeforeAfterSlider.js.map +1 -0
  95. package/dist/portfolio/primitives/DeviceTrifolio.cjs +298 -0
  96. package/dist/portfolio/primitives/DeviceTrifolio.cjs.map +1 -0
  97. package/dist/portfolio/primitives/DeviceTrifolio.d.cts +14 -0
  98. package/dist/portfolio/primitives/DeviceTrifolio.d.ts +14 -0
  99. package/dist/portfolio/primitives/DeviceTrifolio.js +242 -0
  100. package/dist/portfolio/primitives/DeviceTrifolio.js.map +1 -0
  101. package/dist/portfolio/primitives/FrequencyBarSkeleton.cjs +88 -0
  102. package/dist/portfolio/primitives/FrequencyBarSkeleton.cjs.map +1 -0
  103. package/dist/portfolio/primitives/FrequencyBarSkeleton.d.cts +10 -0
  104. package/dist/portfolio/primitives/FrequencyBarSkeleton.d.ts +10 -0
  105. package/dist/portfolio/primitives/FrequencyBarSkeleton.js +68 -0
  106. package/dist/portfolio/primitives/FrequencyBarSkeleton.js.map +1 -0
  107. package/dist/portfolio/primitives/GlassCard.cjs +45 -0
  108. package/dist/portfolio/primitives/GlassCard.cjs.map +1 -0
  109. package/dist/portfolio/primitives/GlassCard.d.cts +11 -0
  110. package/dist/portfolio/primitives/GlassCard.d.ts +11 -0
  111. package/dist/portfolio/primitives/GlassCard.js +43 -0
  112. package/dist/portfolio/primitives/GlassCard.js.map +1 -0
  113. package/dist/portfolio/primitives/MetricBadge.cjs +74 -0
  114. package/dist/portfolio/primitives/MetricBadge.cjs.map +1 -0
  115. package/dist/portfolio/primitives/MetricBadge.d.cts +9 -0
  116. package/dist/portfolio/primitives/MetricBadge.d.ts +9 -0
  117. package/dist/portfolio/primitives/MetricBadge.js +54 -0
  118. package/dist/portfolio/primitives/MetricBadge.js.map +1 -0
  119. package/dist/portfolio/primitives/SVGChart.cjs +316 -0
  120. package/dist/portfolio/primitives/SVGChart.cjs.map +1 -0
  121. package/dist/portfolio/primitives/SVGChart.d.cts +18 -0
  122. package/dist/portfolio/primitives/SVGChart.d.ts +18 -0
  123. package/dist/portfolio/primitives/SVGChart.js +296 -0
  124. package/dist/portfolio/primitives/SVGChart.js.map +1 -0
  125. package/dist/portfolio/primitives/ScrollReveal.cjs +97 -0
  126. package/dist/portfolio/primitives/ScrollReveal.cjs.map +1 -0
  127. package/dist/portfolio/primitives/ScrollReveal.d.cts +27 -0
  128. package/dist/portfolio/primitives/ScrollReveal.d.ts +27 -0
  129. package/dist/portfolio/primitives/ScrollReveal.js +77 -0
  130. package/dist/portfolio/primitives/ScrollReveal.js.map +1 -0
  131. package/dist/portfolio/primitives/SplitHeadline.cjs +107 -0
  132. package/dist/portfolio/primitives/SplitHeadline.cjs.map +1 -0
  133. package/dist/portfolio/primitives/SplitHeadline.d.cts +24 -0
  134. package/dist/portfolio/primitives/SplitHeadline.d.ts +24 -0
  135. package/dist/portfolio/primitives/SplitHeadline.js +87 -0
  136. package/dist/portfolio/primitives/SplitHeadline.js.map +1 -0
  137. package/dist/portfolio/sections/BeforeAfterSection.cjs +271 -0
  138. package/dist/portfolio/sections/BeforeAfterSection.cjs.map +1 -0
  139. package/dist/portfolio/sections/BeforeAfterSection.d.cts +9 -0
  140. package/dist/portfolio/sections/BeforeAfterSection.d.ts +9 -0
  141. package/dist/{BeforeAfterSection-6BHFLY4Y.js → portfolio/sections/BeforeAfterSection.js} +66 -27
  142. package/dist/portfolio/sections/BeforeAfterSection.js.map +1 -0
  143. package/dist/portfolio/sections/CTASection.cjs +123 -0
  144. package/dist/portfolio/sections/CTASection.cjs.map +1 -0
  145. package/dist/portfolio/sections/CTASection.d.cts +9 -0
  146. package/dist/portfolio/sections/CTASection.d.ts +9 -0
  147. package/dist/portfolio/sections/CTASection.js +93 -0
  148. package/dist/portfolio/sections/CTASection.js.map +1 -0
  149. package/dist/{ChallengesSection-IZ3DHECS.cjs → portfolio/sections/ChallengesSection.cjs} +12 -6
  150. package/dist/portfolio/sections/ChallengesSection.cjs.map +1 -0
  151. package/dist/portfolio/sections/ChallengesSection.d.cts +9 -0
  152. package/dist/portfolio/sections/ChallengesSection.d.ts +9 -0
  153. package/dist/{ChallengesSection-GEQGVSJN.js → portfolio/sections/ChallengesSection.js} +5 -4
  154. package/dist/portfolio/sections/ChallengesSection.js.map +1 -0
  155. package/dist/portfolio/sections/ConversionFunnelSection.cjs +263 -0
  156. package/dist/portfolio/sections/ConversionFunnelSection.cjs.map +1 -0
  157. package/dist/portfolio/sections/ConversionFunnelSection.d.cts +9 -0
  158. package/dist/portfolio/sections/ConversionFunnelSection.d.ts +9 -0
  159. package/dist/{ConversionFunnelSection-D3GE4NKE.js → portfolio/sections/ConversionFunnelSection.js} +60 -56
  160. package/dist/portfolio/sections/ConversionFunnelSection.js.map +1 -0
  161. package/dist/{DesignSystemSection-KXIQXITF.cjs → portfolio/sections/DesignSystemSection.cjs} +13 -7
  162. package/dist/portfolio/sections/DesignSystemSection.cjs.map +1 -0
  163. package/dist/portfolio/sections/DesignSystemSection.d.cts +32 -0
  164. package/dist/portfolio/sections/DesignSystemSection.d.ts +32 -0
  165. package/dist/{DesignSystemSection-2R5BRBGO.js → portfolio/sections/DesignSystemSection.js} +5 -4
  166. package/dist/portfolio/sections/DesignSystemSection.js.map +1 -0
  167. package/dist/{DetailsSection-TTUZAPZZ.cjs → portfolio/sections/DetailsSection.cjs} +12 -6
  168. package/dist/portfolio/sections/DetailsSection.cjs.map +1 -0
  169. package/dist/portfolio/sections/DetailsSection.d.cts +9 -0
  170. package/dist/portfolio/sections/DetailsSection.d.ts +9 -0
  171. package/dist/{DetailsSection-A6PZQUQL.js → portfolio/sections/DetailsSection.js} +5 -4
  172. package/dist/portfolio/sections/DetailsSection.js.map +1 -0
  173. package/dist/portfolio/sections/FeatureSpotlightSection.cjs +267 -0
  174. package/dist/portfolio/sections/FeatureSpotlightSection.cjs.map +1 -0
  175. package/dist/portfolio/sections/FeatureSpotlightSection.d.cts +9 -0
  176. package/dist/portfolio/sections/FeatureSpotlightSection.d.ts +9 -0
  177. package/dist/{FeatureSpotlightSection-B7P3JGNL.js → portfolio/sections/FeatureSpotlightSection.js} +39 -33
  178. package/dist/portfolio/sections/FeatureSpotlightSection.js.map +1 -0
  179. package/dist/portfolio/sections/GallerySection.cjs +321 -0
  180. package/dist/portfolio/sections/GallerySection.cjs.map +1 -0
  181. package/dist/portfolio/sections/GallerySection.d.cts +9 -0
  182. package/dist/portfolio/sections/GallerySection.d.ts +9 -0
  183. package/dist/{GallerySection-VMKORC47.js → portfolio/sections/GallerySection.js} +65 -18
  184. package/dist/portfolio/sections/GallerySection.js.map +1 -0
  185. package/dist/portfolio/sections/HeroSection.cjs +180 -0
  186. package/dist/portfolio/sections/HeroSection.cjs.map +1 -0
  187. package/dist/portfolio/sections/HeroSection.d.cts +15 -0
  188. package/dist/portfolio/sections/HeroSection.d.ts +15 -0
  189. package/dist/portfolio/sections/HeroSection.js +171 -0
  190. package/dist/portfolio/sections/HeroSection.js.map +1 -0
  191. package/dist/{MetricsTimelineSection-4L6DUHJ5.cjs → portfolio/sections/MetricsTimelineSection.cjs} +102 -61
  192. package/dist/portfolio/sections/MetricsTimelineSection.cjs.map +1 -0
  193. package/dist/portfolio/sections/MetricsTimelineSection.d.cts +9 -0
  194. package/dist/portfolio/sections/MetricsTimelineSection.d.ts +9 -0
  195. package/dist/{MetricsTimelineSection-6BT5GNFV.js → portfolio/sections/MetricsTimelineSection.js} +45 -29
  196. package/dist/portfolio/sections/MetricsTimelineSection.js.map +1 -0
  197. package/dist/{PerformanceSection-24TVVFZA.cjs → portfolio/sections/PerformanceSection.cjs} +136 -93
  198. package/dist/portfolio/sections/PerformanceSection.cjs.map +1 -0
  199. package/dist/portfolio/sections/PerformanceSection.d.cts +22 -0
  200. package/dist/portfolio/sections/PerformanceSection.d.ts +22 -0
  201. package/dist/{PerformanceSection-MGCEIXDX.js → portfolio/sections/PerformanceSection.js} +58 -40
  202. package/dist/portfolio/sections/PerformanceSection.js.map +1 -0
  203. package/dist/{ResultsSection-XLGMMQKY.cjs → portfolio/sections/ResultsSection.cjs} +22 -10
  204. package/dist/portfolio/sections/ResultsSection.cjs.map +1 -0
  205. package/dist/portfolio/sections/ResultsSection.d.cts +13 -0
  206. package/dist/portfolio/sections/ResultsSection.d.ts +13 -0
  207. package/dist/{ResultsSection-DFUJ5U6M.js → portfolio/sections/ResultsSection.js} +13 -7
  208. package/dist/portfolio/sections/ResultsSection.js.map +1 -0
  209. package/dist/portfolio/sections/ServicesSection.cjs +129 -0
  210. package/dist/portfolio/sections/ServicesSection.cjs.map +1 -0
  211. package/dist/portfolio/sections/ServicesSection.d.cts +9 -0
  212. package/dist/portfolio/sections/ServicesSection.d.ts +9 -0
  213. package/dist/portfolio/sections/ServicesSection.js +122 -0
  214. package/dist/portfolio/sections/ServicesSection.js.map +1 -0
  215. package/dist/{SiteArchitectureSection-J7BPBERH.cjs → portfolio/sections/SiteArchitectureSection.cjs} +116 -92
  216. package/dist/portfolio/sections/SiteArchitectureSection.cjs.map +1 -0
  217. package/dist/portfolio/sections/SiteArchitectureSection.d.cts +21 -0
  218. package/dist/portfolio/sections/SiteArchitectureSection.d.ts +21 -0
  219. package/dist/{SiteArchitectureSection-TE22OAWV.js → portfolio/sections/SiteArchitectureSection.js} +46 -47
  220. package/dist/portfolio/sections/SiteArchitectureSection.js.map +1 -0
  221. package/dist/{SpeedComparisonSection-EZKFQVGW.cjs → portfolio/sections/SpeedComparisonSection.cjs} +12 -6
  222. package/dist/portfolio/sections/SpeedComparisonSection.cjs.map +1 -0
  223. package/dist/portfolio/sections/SpeedComparisonSection.d.cts +20 -0
  224. package/dist/portfolio/sections/SpeedComparisonSection.d.ts +20 -0
  225. package/dist/{SpeedComparisonSection-Y3K7OFZQ.js → portfolio/sections/SpeedComparisonSection.js} +5 -4
  226. package/dist/portfolio/sections/SpeedComparisonSection.js.map +1 -0
  227. package/dist/portfolio/sections/StrategySection.cjs +233 -0
  228. package/dist/portfolio/sections/StrategySection.cjs.map +1 -0
  229. package/dist/portfolio/sections/StrategySection.d.cts +9 -0
  230. package/dist/portfolio/sections/StrategySection.d.ts +9 -0
  231. package/dist/{StrategySection-DI5RSCJU.js → portfolio/sections/StrategySection.js} +60 -26
  232. package/dist/portfolio/sections/StrategySection.js.map +1 -0
  233. package/dist/portfolio/sections/TeamSection.cjs +162 -0
  234. package/dist/portfolio/sections/TeamSection.cjs.map +1 -0
  235. package/dist/portfolio/sections/TeamSection.d.cts +9 -0
  236. package/dist/portfolio/sections/TeamSection.d.ts +9 -0
  237. package/dist/portfolio/sections/TeamSection.js +106 -0
  238. package/dist/portfolio/sections/TeamSection.js.map +1 -0
  239. package/dist/portfolio/sections/TechStackSection.cjs +106 -0
  240. package/dist/portfolio/sections/TechStackSection.cjs.map +1 -0
  241. package/dist/portfolio/sections/TechStackSection.d.cts +9 -0
  242. package/dist/portfolio/sections/TechStackSection.d.ts +9 -0
  243. package/dist/portfolio/sections/TechStackSection.js +99 -0
  244. package/dist/portfolio/sections/TechStackSection.js.map +1 -0
  245. package/dist/{TestimonialSection-XPTFUQIN.cjs → portfolio/sections/TestimonialSection.cjs} +47 -28
  246. package/dist/portfolio/sections/TestimonialSection.cjs.map +1 -0
  247. package/dist/portfolio/sections/TestimonialSection.d.cts +9 -0
  248. package/dist/portfolio/sections/TestimonialSection.d.ts +9 -0
  249. package/dist/{TestimonialSection-6RGSMXQB.js → portfolio/sections/TestimonialSection.js} +40 -27
  250. package/dist/portfolio/sections/TestimonialSection.js.map +1 -0
  251. package/dist/portfolio/sections/VideoSection.cjs +181 -0
  252. package/dist/portfolio/sections/VideoSection.cjs.map +1 -0
  253. package/dist/portfolio/sections/VideoSection.d.cts +9 -0
  254. package/dist/portfolio/sections/VideoSection.d.ts +9 -0
  255. package/dist/{VideoSection-4A2HC6K6.js → portfolio/sections/VideoSection.js} +21 -13
  256. package/dist/portfolio/sections/VideoSection.js.map +1 -0
  257. package/dist/portfolio/server.cjs +56 -144
  258. package/dist/portfolio/server.cjs.map +1 -1
  259. package/dist/portfolio/server.d.cts +157 -7
  260. package/dist/portfolio/server.d.ts +157 -7
  261. package/dist/portfolio/server.js +3 -142
  262. package/dist/portfolio/server.js.map +1 -1
  263. package/dist/preview.cjs +56 -0
  264. package/dist/preview.cjs.map +1 -0
  265. package/dist/preview.d.cts +31 -0
  266. package/dist/preview.d.ts +31 -0
  267. package/dist/preview.js +54 -0
  268. package/dist/preview.js.map +1 -0
  269. package/dist/{types-DL4t_Cfa.d.ts → types-0tVPy4pU.d.cts} +7 -1
  270. package/dist/{types-DL4t_Cfa.d.cts → types-0tVPy4pU.d.ts} +7 -1
  271. package/dist/types-D0nb6KAx.d.cts +299 -0
  272. package/dist/types-D0nb6KAx.d.ts +299 -0
  273. package/package.json +38 -14
  274. package/templates/api-portfolio-preview.ts +6 -0
  275. package/templates/api-revalidate.ts +5 -0
  276. package/templates/work-category-page.tsx +40 -0
  277. package/templates/work-error.tsx +3 -0
  278. package/templates/work-loading.tsx +1 -0
  279. package/templates/work-page.tsx +37 -0
  280. package/templates/work-slug-loading.tsx +1 -0
  281. package/templates/work-slug-page.tsx +41 -0
  282. package/dist/BeforeAfterSection-6BHFLY4Y.js.map +0 -1
  283. package/dist/BeforeAfterSection-JTORBR3A.cjs +0 -181
  284. package/dist/BeforeAfterSection-JTORBR3A.cjs.map +0 -1
  285. package/dist/CTASection-4JKLXEUF.cjs +0 -111
  286. package/dist/CTASection-4JKLXEUF.cjs.map +0 -1
  287. package/dist/CTASection-BJA72XIL.js +0 -106
  288. package/dist/CTASection-BJA72XIL.js.map +0 -1
  289. package/dist/ChallengesSection-GEQGVSJN.js.map +0 -1
  290. package/dist/ChallengesSection-IZ3DHECS.cjs.map +0 -1
  291. package/dist/ConversionFunnelSection-AUUSJ5HQ.cjs +0 -209
  292. package/dist/ConversionFunnelSection-AUUSJ5HQ.cjs.map +0 -1
  293. package/dist/ConversionFunnelSection-D3GE4NKE.js.map +0 -1
  294. package/dist/DesignSystemSection-2R5BRBGO.js.map +0 -1
  295. package/dist/DesignSystemSection-KXIQXITF.cjs.map +0 -1
  296. package/dist/DetailsSection-A6PZQUQL.js.map +0 -1
  297. package/dist/DetailsSection-TTUZAPZZ.cjs.map +0 -1
  298. package/dist/FeatureSpotlightSection-B7P3JGNL.js.map +0 -1
  299. package/dist/FeatureSpotlightSection-WRHXS7TU.cjs +0 -210
  300. package/dist/FeatureSpotlightSection-WRHXS7TU.cjs.map +0 -1
  301. package/dist/GallerySection-VMKORC47.js.map +0 -1
  302. package/dist/GallerySection-WJ4PQDBI.cjs +0 -219
  303. package/dist/GallerySection-WJ4PQDBI.cjs.map +0 -1
  304. package/dist/MetricsTimelineSection-4L6DUHJ5.cjs.map +0 -1
  305. package/dist/MetricsTimelineSection-6BT5GNFV.js.map +0 -1
  306. package/dist/PerformanceSection-24TVVFZA.cjs.map +0 -1
  307. package/dist/PerformanceSection-MGCEIXDX.js.map +0 -1
  308. package/dist/ResultsSection-DFUJ5U6M.js.map +0 -1
  309. package/dist/ResultsSection-XLGMMQKY.cjs.map +0 -1
  310. package/dist/ServicesSection-D5V3Q4GR.js +0 -118
  311. package/dist/ServicesSection-D5V3Q4GR.js.map +0 -1
  312. package/dist/ServicesSection-WJMGK2MF.cjs +0 -120
  313. package/dist/ServicesSection-WJMGK2MF.cjs.map +0 -1
  314. package/dist/SiteArchitectureSection-J7BPBERH.cjs.map +0 -1
  315. package/dist/SiteArchitectureSection-TE22OAWV.js.map +0 -1
  316. package/dist/SpeedComparisonSection-EZKFQVGW.cjs.map +0 -1
  317. package/dist/SpeedComparisonSection-Y3K7OFZQ.js.map +0 -1
  318. package/dist/StrategySection-CJ7Y6OFQ.cjs +0 -174
  319. package/dist/StrategySection-CJ7Y6OFQ.cjs.map +0 -1
  320. package/dist/StrategySection-DI5RSCJU.js.map +0 -1
  321. package/dist/TeamSection-DZVSNZE6.cjs +0 -112
  322. package/dist/TeamSection-DZVSNZE6.cjs.map +0 -1
  323. package/dist/TeamSection-HGKFW6PQ.js +0 -107
  324. package/dist/TeamSection-HGKFW6PQ.js.map +0 -1
  325. package/dist/TechStackSection-2AQ7RGY3.js +0 -93
  326. package/dist/TechStackSection-2AQ7RGY3.js.map +0 -1
  327. package/dist/TechStackSection-VTNNZR5V.cjs +0 -95
  328. package/dist/TechStackSection-VTNNZR5V.cjs.map +0 -1
  329. package/dist/TestimonialSection-6RGSMXQB.js.map +0 -1
  330. package/dist/TestimonialSection-XPTFUQIN.cjs.map +0 -1
  331. package/dist/VideoSection-4A2HC6K6.js.map +0 -1
  332. package/dist/VideoSection-G3DFS7UH.cjs +0 -118
  333. package/dist/VideoSection-G3DFS7UH.cjs.map +0 -1
  334. package/dist/chunk-2Y4O3LWM.js +0 -53
  335. package/dist/chunk-2Y4O3LWM.js.map +0 -1
  336. package/dist/chunk-633UMQQH.cjs +0 -31
  337. package/dist/chunk-633UMQQH.cjs.map +0 -1
  338. package/dist/chunk-7CFFAKDM.js +0 -74
  339. package/dist/chunk-7CFFAKDM.js.map +0 -1
  340. package/dist/chunk-APG2QSMB.js +0 -131
  341. package/dist/chunk-APG2QSMB.js.map +0 -1
  342. package/dist/chunk-AVCH4LMG.cjs +0 -620
  343. package/dist/chunk-AVCH4LMG.cjs.map +0 -1
  344. package/dist/chunk-AYBUHRFS.js +0 -613
  345. package/dist/chunk-AYBUHRFS.js.map +0 -1
  346. package/dist/chunk-EE75WRCM.cjs.map +0 -1
  347. package/dist/chunk-IKBK7HYX.cjs +0 -79
  348. package/dist/chunk-IKBK7HYX.cjs.map +0 -1
  349. package/dist/chunk-KEOHORIH.cjs +0 -79
  350. package/dist/chunk-KEOHORIH.cjs.map +0 -1
  351. package/dist/chunk-OA5ZM4OA.cjs +0 -139
  352. package/dist/chunk-OA5ZM4OA.cjs.map +0 -1
  353. package/dist/chunk-TVFXN6W6.js.map +0 -1
  354. package/dist/chunk-VVTK4OL6.js +0 -28
  355. package/dist/chunk-VVTK4OL6.js.map +0 -1
  356. package/dist/chunk-XCKXHK44.js +0 -15
  357. package/dist/chunk-XCKXHK44.js.map +0 -1
  358. package/dist/chunk-XONXEFJY.cjs +0 -58
  359. package/dist/chunk-XONXEFJY.cjs.map +0 -1
  360. package/dist/chunk-XQNJED46.cjs +0 -19
  361. package/dist/chunk-XQNJED46.cjs.map +0 -1
  362. package/dist/chunk-YB4B3OMC.js +0 -74
  363. package/dist/chunk-YB4B3OMC.js.map +0 -1
  364. package/dist/portfolio/sections.cjs +0 -20
  365. package/dist/portfolio/sections.cjs.map +0 -1
  366. package/dist/portfolio/sections.d.cts +0 -42
  367. package/dist/portfolio/sections.d.ts +0 -42
  368. package/dist/portfolio/sections.js +0 -4
  369. package/dist/portfolio/sections.js.map +0 -1
@@ -1,16 +1,44 @@
1
- 'use strict';
2
-
3
- var chunkKEOHORIH_cjs = require('./chunk-KEOHORIH.cjs');
4
- var chunkIKBK7HYX_cjs = require('./chunk-IKBK7HYX.cjs');
5
- var react = require('react');
6
- var gsap = require('gsap');
7
- var ScrollTrigger = require('gsap/ScrollTrigger');
8
- var jsxRuntime = require('react/jsx-runtime');
9
-
10
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
-
12
- var gsap__default = /*#__PURE__*/_interopDefault(gsap);
1
+ 'use client';
2
+ "use strict";
3
+ "use client";
4
+ var __create = Object.create;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __export = (target, all) => {
11
+ for (var name in all)
12
+ __defProp(target, name, { get: all[name], enumerable: true });
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from))
17
+ if (!__hasOwnProp.call(to, key) && key !== except)
18
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
23
+ // If the importer is in node compatibility mode or this is not an ESM
24
+ // file that has been converted to a CommonJS file using a Babel-
25
+ // compatible transform (i.e. "__esModule" has not been set), then set
26
+ // "default" to the CommonJS "module.exports" for node compatibility.
27
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
28
+ mod
29
+ ));
30
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
13
31
 
32
+ // src/portfolio/components/sections/MetricsTimelineSection.tsx
33
+ var MetricsTimelineSection_exports = {};
34
+ __export(MetricsTimelineSection_exports, {
35
+ default: () => MetricsTimelineSection
36
+ });
37
+ module.exports = __toCommonJS(MetricsTimelineSection_exports);
38
+ var import_react = require("react");
39
+ var import_ScrollReveal = __toESM(require("@sonordev/agency-site-kit/portfolio/primitives/ScrollReveal"), 1);
40
+ var import_GlassCard = __toESM(require("@sonordev/agency-site-kit/portfolio/primitives/GlassCard"), 1);
41
+ var import_jsx_runtime = require("react/jsx-runtime");
14
42
  var metricColors = {
15
43
  traffic: "#6366f1",
16
44
  conversions: "#10b981",
@@ -23,18 +51,20 @@ var metricLabels = {
23
51
  revenue: "Revenue",
24
52
  rankings: "Rankings"
25
53
  };
54
+ var EASE = "cubic-bezier(0.25, 0.46, 0.45, 0.94)";
26
55
  function MetricsTimelineSection({ data }) {
27
- const svgRef = react.useRef(null);
28
- const pathRef = react.useRef(null);
29
- const [activeMetric, setActiveMetric] = react.useState("traffic");
30
- const [hasTriggered, setHasTriggered] = react.useState(false);
31
- const availableMetrics = react.useMemo(() => {
56
+ const svgRef = (0, import_react.useRef)(null);
57
+ const pathRef = (0, import_react.useRef)(null);
58
+ const hydratedRef = (0, import_react.useRef)(false);
59
+ const [activeMetric, setActiveMetric] = (0, import_react.useState)("traffic");
60
+ const [hasTriggered, setHasTriggered] = (0, import_react.useState)(false);
61
+ const availableMetrics = (0, import_react.useMemo)(() => {
32
62
  const keys = ["traffic", "conversions", "revenue", "rankings"];
33
63
  return keys.filter(
34
64
  (key) => data.dataPoints.some((dp) => dp.metrics[key] !== void 0 && dp.metrics[key] !== null)
35
65
  );
36
66
  }, [data.dataPoints]);
37
- const chartData = react.useMemo(() => {
67
+ const chartData = (0, import_react.useMemo)(() => {
38
68
  const values = data.dataPoints.map((dp) => dp.metrics[activeMetric] ?? 0);
39
69
  const maxVal = Math.max(...values, 1);
40
70
  const minVal = Math.min(...values, 0);
@@ -74,47 +104,61 @@ function MetricsTimelineSection({ data }) {
74
104
  labels: data.dataPoints.map((dp) => dp.label)
75
105
  };
76
106
  }, [data.dataPoints, data.baselineDate, activeMetric]);
77
- react.useEffect(() => {
78
- gsap__default.default.registerPlugin(ScrollTrigger.ScrollTrigger);
107
+ (0, import_react.useEffect)(() => {
79
108
  const path = pathRef.current;
80
109
  const svg = svgRef.current;
81
110
  if (!path || !svg) return;
111
+ const isHydration = !hydratedRef.current;
112
+ hydratedRef.current = true;
82
113
  const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
83
- const ctx = gsap__default.default.context(() => {
84
- const length = path.getTotalLength();
85
- gsap__default.default.set(path, { strokeDasharray: length, strokeDashoffset: length });
86
- if (prefersReducedMotion) {
87
- gsap__default.default.set(path, { strokeDashoffset: 0 });
114
+ if (prefersReducedMotion) {
115
+ setHasTriggered(true);
116
+ return;
117
+ }
118
+ if (isHydration) {
119
+ const rect = svg.getBoundingClientRect();
120
+ if (rect.top < window.innerHeight && rect.bottom > 0) {
88
121
  setHasTriggered(true);
89
122
  return;
90
123
  }
91
- gsap__default.default.to(path, {
92
- strokeDashoffset: 0,
93
- duration: 2,
94
- ease: "power2.out",
95
- scrollTrigger: {
96
- trigger: svg,
97
- start: "top 75%",
98
- toggleActions: "play none none none"
99
- },
100
- onComplete: () => setHasTriggered(true)
101
- });
102
- });
103
- return () => ctx.revert();
124
+ }
125
+ const length = path.getTotalLength();
126
+ path.style.strokeDasharray = String(length);
127
+ path.style.strokeDashoffset = String(length);
128
+ let timeout = 0;
129
+ const io = new IntersectionObserver(
130
+ ([entry]) => {
131
+ if (!entry.isIntersecting) return;
132
+ io.disconnect();
133
+ path.style.transition = `stroke-dashoffset 2s ${EASE}`;
134
+ path.style.strokeDashoffset = "0";
135
+ timeout = window.setTimeout(() => setHasTriggered(true), 2e3);
136
+ },
137
+ { rootMargin: "0px 0px -25% 0px" }
138
+ // ≈ the old 'top 75%' trigger
139
+ );
140
+ io.observe(svg);
141
+ return () => {
142
+ io.disconnect();
143
+ window.clearTimeout(timeout);
144
+ path.style.transition = "";
145
+ path.style.strokeDasharray = "";
146
+ path.style.strokeDashoffset = "";
147
+ };
104
148
  }, [activeMetric]);
105
- const handleMetricChange = react.useCallback((metric) => {
149
+ const handleMetricChange = (0, import_react.useCallback)((metric) => {
106
150
  setActiveMetric(metric);
107
151
  setHasTriggered(false);
108
152
  }, []);
109
153
  const color = metricColors[activeMetric];
110
- return /* @__PURE__ */ jsxRuntime.jsx(
154
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
111
155
  "section",
112
156
  {
113
157
  className: "w-full py-20 md:py-28",
114
158
  style: { background: "var(--sk-bg, #0a0a0a)" },
115
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-6xl mx-auto px-6", children: [
116
- (data.title || data.description) && /* @__PURE__ */ jsxRuntime.jsxs(chunkIKBK7HYX_cjs.ScrollReveal, { y: 30, children: [
117
- data.title && /* @__PURE__ */ jsxRuntime.jsx(
159
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "max-w-6xl mx-auto px-6", children: [
160
+ (data.title || data.description) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ScrollReveal.default, { y: 30, children: [
161
+ data.title && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
118
162
  "h2",
119
163
  {
120
164
  className: "text-3xl md:text-4xl font-bold mb-4",
@@ -125,7 +169,7 @@ function MetricsTimelineSection({ data }) {
125
169
  children: data.title
126
170
  }
127
171
  ),
128
- data.description && /* @__PURE__ */ jsxRuntime.jsx(
172
+ data.description && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
129
173
  "p",
130
174
  {
131
175
  className: "text-lg mb-8 max-w-2xl",
@@ -134,7 +178,7 @@ function MetricsTimelineSection({ data }) {
134
178
  }
135
179
  )
136
180
  ] }),
137
- /* @__PURE__ */ jsxRuntime.jsx(chunkIKBK7HYX_cjs.ScrollReveal, { y: 20, delay: 0.1, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2 mb-8", children: availableMetrics.map((metric) => /* @__PURE__ */ jsxRuntime.jsx(
181
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ScrollReveal.default, { y: 20, delay: 0.1, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-wrap gap-2 mb-8", children: availableMetrics.map((metric) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
138
182
  "button",
139
183
  {
140
184
  onClick: () => handleMetricChange(metric),
@@ -148,7 +192,7 @@ function MetricsTimelineSection({ data }) {
148
192
  },
149
193
  metric
150
194
  )) }) }),
151
- /* @__PURE__ */ jsxRuntime.jsx(chunkIKBK7HYX_cjs.ScrollReveal, { y: 40, delay: 0.2, children: /* @__PURE__ */ jsxRuntime.jsx(chunkKEOHORIH_cjs.GlassCard, { padding: "lg", hover: false, children: /* @__PURE__ */ jsxRuntime.jsxs(
195
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ScrollReveal.default, { y: 40, delay: 0.2, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_GlassCard.default, { padding: "lg", hover: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
152
196
  "svg",
153
197
  {
154
198
  ref: svgRef,
@@ -158,7 +202,7 @@ function MetricsTimelineSection({ data }) {
158
202
  children: [
159
203
  [0, 1, 2, 3, 4].map((i) => {
160
204
  const y = chartData.padding + i / 4 * (chartData.chartHeight - chartData.padding * 2);
161
- return /* @__PURE__ */ jsxRuntime.jsx(
205
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
162
206
  "line",
163
207
  {
164
208
  x1: chartData.padding,
@@ -171,8 +215,8 @@ function MetricsTimelineSection({ data }) {
171
215
  i
172
216
  );
173
217
  }),
174
- chartData.baselineX !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
175
- /* @__PURE__ */ jsxRuntime.jsx(
218
+ chartData.baselineX !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
219
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
176
220
  "line",
177
221
  {
178
222
  x1: chartData.baselineX,
@@ -184,7 +228,7 @@ function MetricsTimelineSection({ data }) {
184
228
  strokeDasharray: "6 4"
185
229
  }
186
230
  ),
187
- /* @__PURE__ */ jsxRuntime.jsx(
231
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
188
232
  "text",
189
233
  {
190
234
  x: chartData.baselineX,
@@ -197,18 +241,18 @@ function MetricsTimelineSection({ data }) {
197
241
  }
198
242
  )
199
243
  ] }),
200
- /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: `area-gradient-${activeMetric}`, x1: "0", y1: "0", x2: "0", y2: "1", children: [
201
- /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: color, stopOpacity: "0.3" }),
202
- /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: color, stopOpacity: "0" })
244
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("linearGradient", { id: `area-gradient-${activeMetric}`, x1: "0", y1: "0", x2: "0", y2: "1", children: [
245
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: "0%", stopColor: color, stopOpacity: "0.3" }),
246
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: "100%", stopColor: color, stopOpacity: "0" })
203
247
  ] }) }),
204
- hasTriggered && chartData.areaD && /* @__PURE__ */ jsxRuntime.jsx(
248
+ hasTriggered && chartData.areaD && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
205
249
  "path",
206
250
  {
207
251
  d: chartData.areaD,
208
252
  fill: `url(#area-gradient-${activeMetric})`
209
253
  }
210
254
  ),
211
- chartData.d && /* @__PURE__ */ jsxRuntime.jsx(
255
+ chartData.d && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
212
256
  "path",
213
257
  {
214
258
  ref: pathRef,
@@ -220,7 +264,7 @@ function MetricsTimelineSection({ data }) {
220
264
  strokeLinejoin: "round"
221
265
  }
222
266
  ),
223
- hasTriggered && chartData.points.map((pt, i) => /* @__PURE__ */ jsxRuntime.jsx(
267
+ hasTriggered && chartData.points.map((pt, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
224
268
  "circle",
225
269
  {
226
270
  cx: pt.x,
@@ -232,7 +276,7 @@ function MetricsTimelineSection({ data }) {
232
276
  },
233
277
  i
234
278
  )),
235
- chartData.labels.map((label, i) => /* @__PURE__ */ jsxRuntime.jsx(
279
+ chartData.labels.map((label, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
236
280
  "text",
237
281
  {
238
282
  x: chartData.points[i]?.x ?? 0,
@@ -252,7 +296,4 @@ function MetricsTimelineSection({ data }) {
252
296
  }
253
297
  );
254
298
  }
255
-
256
- module.exports = MetricsTimelineSection;
257
- //# sourceMappingURL=MetricsTimelineSection-4L6DUHJ5.cjs.map
258
- //# sourceMappingURL=MetricsTimelineSection-4L6DUHJ5.cjs.map
299
+ //# sourceMappingURL=MetricsTimelineSection.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/portfolio/components/sections/MetricsTimelineSection.tsx"],"sourcesContent":["'use client';\n\nimport React, { useRef, useEffect, useState, useCallback, useMemo } from 'react';\nimport type { PortfolioMetricsTimelineData } from '../../../types';\nimport ScrollReveal from '@sonordev/agency-site-kit/portfolio/primitives/ScrollReveal';\nimport GlassCard from '@sonordev/agency-site-kit/portfolio/primitives/GlassCard';\n\ninterface MetricsTimelineSectionProps {\n data: PortfolioMetricsTimelineData;\n}\n\ntype MetricKey = 'traffic' | 'conversions' | 'revenue' | 'rankings';\n\nconst metricColors: Record<MetricKey, string> = {\n traffic: '#6366f1',\n conversions: '#10b981',\n revenue: '#f59e0b',\n rankings: '#ec4899',\n};\n\nconst metricLabels: Record<MetricKey, string> = {\n traffic: 'Traffic',\n conversions: 'Conversions',\n revenue: 'Revenue',\n rankings: 'Rankings',\n};\n\nconst EASE = 'cubic-bezier(0.25, 0.46, 0.45, 0.94)'; // ≈ power2.out\n\nexport default function MetricsTimelineSection({ data }: MetricsTimelineSectionProps) {\n const svgRef = useRef<SVGSVGElement>(null);\n const pathRef = useRef<SVGPathElement>(null);\n const hydratedRef = useRef(false);\n const [activeMetric, setActiveMetric] = useState<MetricKey>('traffic');\n const [hasTriggered, setHasTriggered] = useState(false);\n\n // Determine available metrics\n const availableMetrics = useMemo(() => {\n const keys: MetricKey[] = ['traffic', 'conversions', 'revenue', 'rankings'];\n return keys.filter((key) =>\n data.dataPoints.some((dp) => dp.metrics[key] !== undefined && dp.metrics[key] !== null),\n );\n }, [data.dataPoints]);\n\n // Compute chart path for the active metric\n const chartData = useMemo(() => {\n const values = data.dataPoints.map((dp) => dp.metrics[activeMetric] ?? 0);\n const maxVal = Math.max(...values, 1);\n const minVal = Math.min(...values, 0);\n const range = maxVal - minVal || 1;\n\n const chartWidth = 800;\n const chartHeight = 300;\n const padding = 40;\n\n const points = values.map((val, i) => ({\n x: padding + (i / Math.max(values.length - 1, 1)) * (chartWidth - padding * 2),\n y: chartHeight - padding - ((val - minVal) / range) * (chartHeight - padding * 2),\n }));\n\n // Build SVG path\n let d = '';\n if (points.length > 0) {\n d = `M ${points[0].x} ${points[0].y}`;\n for (let i = 1; i < points.length; i++) {\n const cpx1 = (points[i - 1].x + points[i].x) / 2;\n const cpy1 = points[i - 1].y;\n const cpx2 = (points[i - 1].x + points[i].x) / 2;\n const cpy2 = points[i].y;\n d += ` C ${cpx1} ${cpy1}, ${cpx2} ${cpy2}, ${points[i].x} ${points[i].y}`;\n }\n }\n\n // Area fill path\n let areaD = d;\n if (points.length > 0) {\n areaD += ` L ${points[points.length - 1].x} ${chartHeight - padding} L ${points[0].x} ${chartHeight - padding} Z`;\n }\n\n // Find baseline index\n const baselineIdx = data.dataPoints.findIndex((dp) => dp.month === data.baselineDate);\n const baselineX = baselineIdx >= 0 ? points[baselineIdx]?.x : undefined;\n\n return {\n d,\n areaD,\n points,\n chartWidth,\n chartHeight,\n padding,\n baselineX,\n labels: data.dataPoints.map((dp) => dp.label),\n };\n }, [data.dataPoints, data.baselineDate, activeMetric]);\n\n // Animate path draw on scroll (re-runs when the metric changes)\n useEffect(() => {\n const path = pathRef.current;\n const svg = svgRef.current;\n if (!path || !svg) return;\n\n const isHydration = !hydratedRef.current;\n hydratedRef.current = true;\n\n const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n if (prefersReducedMotion) {\n setHasTriggered(true);\n return;\n }\n\n // Never re-hide a chart already in the viewport at hydration. Metric\n // switches still redraw in place — that re-run is user-initiated.\n if (isHydration) {\n const rect = svg.getBoundingClientRect();\n if (rect.top < window.innerHeight && rect.bottom > 0) {\n setHasTriggered(true);\n return;\n }\n }\n\n // Hidden state: line fully undrawn.\n const length = path.getTotalLength();\n path.style.strokeDasharray = String(length);\n path.style.strokeDashoffset = String(length);\n\n let timeout = 0;\n const io = new IntersectionObserver(\n ([entry]) => {\n if (!entry.isIntersecting) return;\n io.disconnect();\n path.style.transition = `stroke-dashoffset 2s ${EASE}`;\n path.style.strokeDashoffset = '0';\n // Area fill + data points pop in once the draw completes.\n timeout = window.setTimeout(() => setHasTriggered(true), 2000);\n },\n { rootMargin: '0px 0px -25% 0px' }, // ≈ the old 'top 75%' trigger\n );\n io.observe(svg);\n\n return () => {\n io.disconnect();\n window.clearTimeout(timeout);\n path.style.transition = '';\n path.style.strokeDasharray = '';\n path.style.strokeDashoffset = '';\n };\n }, [activeMetric]);\n\n const handleMetricChange = useCallback((metric: MetricKey) => {\n setActiveMetric(metric);\n setHasTriggered(false);\n }, []);\n\n const color = metricColors[activeMetric];\n\n return (\n <section\n className=\"w-full py-20 md:py-28\"\n style={{ background: 'var(--sk-bg, #0a0a0a)' }}\n >\n <div className=\"max-w-6xl mx-auto px-6\">\n {(data.title || data.description) && (\n <ScrollReveal y={30}>\n {data.title && (\n <h2\n className=\"text-3xl md:text-4xl font-bold mb-4\"\n style={{\n color: 'var(--sk-text-primary, #ffffff)',\n fontFamily: 'var(--sk-font-heading, inherit)',\n }}\n >\n {data.title}\n </h2>\n )}\n {data.description && (\n <p\n className=\"text-lg mb-8 max-w-2xl\"\n style={{ color: 'var(--sk-text-secondary, #a1a1aa)' }}\n >\n {data.description}\n </p>\n )}\n </ScrollReveal>\n )}\n\n {/* Metric toggle pills */}\n <ScrollReveal y={20} delay={0.1}>\n <div className=\"flex flex-wrap gap-2 mb-8\">\n {availableMetrics.map((metric) => (\n <button\n key={metric}\n onClick={() => handleMetricChange(metric)}\n className=\"px-4 py-2 rounded-full text-sm font-medium transition-all duration-200 cursor-pointer\"\n style={{\n background:\n activeMetric === metric\n ? metricColors[metric]\n : 'var(--sk-surface, rgba(255,255,255,0.05))',\n color:\n activeMetric === metric\n ? '#ffffff'\n : 'var(--sk-text-secondary, #a1a1aa)',\n border: `1px solid ${\n activeMetric === metric\n ? metricColors[metric]\n : 'var(--sk-border, rgba(255,255,255,0.1))'\n }`,\n }}\n >\n {metricLabels[metric]}\n </button>\n ))}\n </div>\n </ScrollReveal>\n\n <ScrollReveal y={40} delay={0.2}>\n <GlassCard padding=\"lg\" hover={false}>\n <svg\n ref={svgRef}\n viewBox={`0 0 ${chartData.chartWidth} ${chartData.chartHeight}`}\n className=\"w-full h-auto\"\n preserveAspectRatio=\"xMidYMid meet\"\n >\n {/* Grid lines */}\n {[0, 1, 2, 3, 4].map((i) => {\n const y =\n chartData.padding +\n (i / 4) * (chartData.chartHeight - chartData.padding * 2);\n return (\n <line\n key={i}\n x1={chartData.padding}\n y1={y}\n x2={chartData.chartWidth - chartData.padding}\n y2={y}\n stroke=\"var(--sk-border, rgba(255,255,255,0.1))\"\n strokeWidth=\"1\"\n />\n );\n })}\n\n {/* Baseline marker */}\n {chartData.baselineX !== undefined && (\n <>\n <line\n x1={chartData.baselineX}\n y1={chartData.padding}\n x2={chartData.baselineX}\n y2={chartData.chartHeight - chartData.padding}\n stroke=\"var(--sk-text-tertiary, #71717a)\"\n strokeWidth=\"1.5\"\n strokeDasharray=\"6 4\"\n />\n <text\n x={chartData.baselineX}\n y={chartData.padding - 10}\n textAnchor=\"middle\"\n fill=\"var(--sk-text-tertiary, #71717a)\"\n fontSize=\"11\"\n fontFamily=\"var(--sk-font, sans-serif)\"\n >\n Launch\n </text>\n </>\n )}\n\n {/* Area fill (gradient) */}\n <defs>\n <linearGradient id={`area-gradient-${activeMetric}`} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={color} stopOpacity=\"0.3\" />\n <stop offset=\"100%\" stopColor={color} stopOpacity=\"0\" />\n </linearGradient>\n </defs>\n {hasTriggered && chartData.areaD && (\n <path\n d={chartData.areaD}\n fill={`url(#area-gradient-${activeMetric})`}\n />\n )}\n\n {/* Chart line (animated draw) */}\n {chartData.d && (\n <path\n ref={pathRef}\n d={chartData.d}\n fill=\"none\"\n stroke={color}\n strokeWidth=\"3\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n )}\n\n {/* Data points */}\n {hasTriggered &&\n chartData.points.map((pt, i) => (\n <circle\n key={i}\n cx={pt.x}\n cy={pt.y}\n r=\"4\"\n fill={color}\n stroke=\"var(--sk-bg, #0a0a0a)\"\n strokeWidth=\"2\"\n />\n ))}\n\n {/* X-axis labels */}\n {chartData.labels.map((label, i) => (\n <text\n key={i}\n x={chartData.points[i]?.x ?? 0}\n y={chartData.chartHeight - 10}\n textAnchor=\"middle\"\n fill=\"var(--sk-text-tertiary, #71717a)\"\n fontSize=\"10\"\n fontFamily=\"var(--sk-font, sans-serif)\"\n >\n {label}\n </text>\n ))}\n </svg>\n </GlassCard>\n </ScrollReveal>\n </div>\n </section>\n );\n}\n"],"mappings":"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","names":["ScrollReveal","GlassCard"]}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { e as PortfolioMetricsTimelineData } from '../../types-D0nb6KAx.cjs';
3
+
4
+ interface MetricsTimelineSectionProps {
5
+ data: PortfolioMetricsTimelineData;
6
+ }
7
+ declare function MetricsTimelineSection({ data }: MetricsTimelineSectionProps): React.JSX.Element;
8
+
9
+ export { MetricsTimelineSection as default };
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { e as PortfolioMetricsTimelineData } from '../../types-D0nb6KAx.js';
3
+
4
+ interface MetricsTimelineSectionProps {
5
+ data: PortfolioMetricsTimelineData;
6
+ }
7
+ declare function MetricsTimelineSection({ data }: MetricsTimelineSectionProps): React.JSX.Element;
8
+
9
+ export { MetricsTimelineSection as default };
@@ -1,11 +1,11 @@
1
1
  'use client';
2
- import { GlassCard } from './chunk-YB4B3OMC.js';
3
- import { ScrollReveal } from './chunk-7CFFAKDM.js';
4
- import { useRef, useState, useMemo, useEffect, useCallback } from 'react';
5
- import gsap from 'gsap';
6
- import { ScrollTrigger } from 'gsap/ScrollTrigger';
7
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ "use client";
8
3
 
4
+ // src/portfolio/components/sections/MetricsTimelineSection.tsx
5
+ import { useRef, useEffect, useState, useCallback, useMemo } from "react";
6
+ import ScrollReveal from "@sonordev/agency-site-kit/portfolio/primitives/ScrollReveal";
7
+ import GlassCard from "@sonordev/agency-site-kit/portfolio/primitives/GlassCard";
8
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
9
  var metricColors = {
10
10
  traffic: "#6366f1",
11
11
  conversions: "#10b981",
@@ -18,9 +18,11 @@ var metricLabels = {
18
18
  revenue: "Revenue",
19
19
  rankings: "Rankings"
20
20
  };
21
+ var EASE = "cubic-bezier(0.25, 0.46, 0.45, 0.94)";
21
22
  function MetricsTimelineSection({ data }) {
22
23
  const svgRef = useRef(null);
23
24
  const pathRef = useRef(null);
25
+ const hydratedRef = useRef(false);
24
26
  const [activeMetric, setActiveMetric] = useState("traffic");
25
27
  const [hasTriggered, setHasTriggered] = useState(false);
26
28
  const availableMetrics = useMemo(() => {
@@ -70,32 +72,46 @@ function MetricsTimelineSection({ data }) {
70
72
  };
71
73
  }, [data.dataPoints, data.baselineDate, activeMetric]);
72
74
  useEffect(() => {
73
- gsap.registerPlugin(ScrollTrigger);
74
75
  const path = pathRef.current;
75
76
  const svg = svgRef.current;
76
77
  if (!path || !svg) return;
78
+ const isHydration = !hydratedRef.current;
79
+ hydratedRef.current = true;
77
80
  const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
78
- const ctx = gsap.context(() => {
79
- const length = path.getTotalLength();
80
- gsap.set(path, { strokeDasharray: length, strokeDashoffset: length });
81
- if (prefersReducedMotion) {
82
- gsap.set(path, { strokeDashoffset: 0 });
81
+ if (prefersReducedMotion) {
82
+ setHasTriggered(true);
83
+ return;
84
+ }
85
+ if (isHydration) {
86
+ const rect = svg.getBoundingClientRect();
87
+ if (rect.top < window.innerHeight && rect.bottom > 0) {
83
88
  setHasTriggered(true);
84
89
  return;
85
90
  }
86
- gsap.to(path, {
87
- strokeDashoffset: 0,
88
- duration: 2,
89
- ease: "power2.out",
90
- scrollTrigger: {
91
- trigger: svg,
92
- start: "top 75%",
93
- toggleActions: "play none none none"
94
- },
95
- onComplete: () => setHasTriggered(true)
96
- });
97
- });
98
- return () => ctx.revert();
91
+ }
92
+ const length = path.getTotalLength();
93
+ path.style.strokeDasharray = String(length);
94
+ path.style.strokeDashoffset = String(length);
95
+ let timeout = 0;
96
+ const io = new IntersectionObserver(
97
+ ([entry]) => {
98
+ if (!entry.isIntersecting) return;
99
+ io.disconnect();
100
+ path.style.transition = `stroke-dashoffset 2s ${EASE}`;
101
+ path.style.strokeDashoffset = "0";
102
+ timeout = window.setTimeout(() => setHasTriggered(true), 2e3);
103
+ },
104
+ { rootMargin: "0px 0px -25% 0px" }
105
+ // ≈ the old 'top 75%' trigger
106
+ );
107
+ io.observe(svg);
108
+ return () => {
109
+ io.disconnect();
110
+ window.clearTimeout(timeout);
111
+ path.style.transition = "";
112
+ path.style.strokeDasharray = "";
113
+ path.style.strokeDashoffset = "";
114
+ };
99
115
  }, [activeMetric]);
100
116
  const handleMetricChange = useCallback((metric) => {
101
117
  setActiveMetric(metric);
@@ -247,7 +263,7 @@ function MetricsTimelineSection({ data }) {
247
263
  }
248
264
  );
249
265
  }
250
-
251
- export { MetricsTimelineSection as default };
252
- //# sourceMappingURL=MetricsTimelineSection-6BT5GNFV.js.map
253
- //# sourceMappingURL=MetricsTimelineSection-6BT5GNFV.js.map
266
+ export {
267
+ MetricsTimelineSection as default
268
+ };
269
+ //# sourceMappingURL=MetricsTimelineSection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/portfolio/components/sections/MetricsTimelineSection.tsx"],"sourcesContent":["'use client';\n\nimport React, { useRef, useEffect, useState, useCallback, useMemo } from 'react';\nimport type { PortfolioMetricsTimelineData } from '../../../types';\nimport ScrollReveal from '@sonordev/agency-site-kit/portfolio/primitives/ScrollReveal';\nimport GlassCard from '@sonordev/agency-site-kit/portfolio/primitives/GlassCard';\n\ninterface MetricsTimelineSectionProps {\n data: PortfolioMetricsTimelineData;\n}\n\ntype MetricKey = 'traffic' | 'conversions' | 'revenue' | 'rankings';\n\nconst metricColors: Record<MetricKey, string> = {\n traffic: '#6366f1',\n conversions: '#10b981',\n revenue: '#f59e0b',\n rankings: '#ec4899',\n};\n\nconst metricLabels: Record<MetricKey, string> = {\n traffic: 'Traffic',\n conversions: 'Conversions',\n revenue: 'Revenue',\n rankings: 'Rankings',\n};\n\nconst EASE = 'cubic-bezier(0.25, 0.46, 0.45, 0.94)'; // ≈ power2.out\n\nexport default function MetricsTimelineSection({ data }: MetricsTimelineSectionProps) {\n const svgRef = useRef<SVGSVGElement>(null);\n const pathRef = useRef<SVGPathElement>(null);\n const hydratedRef = useRef(false);\n const [activeMetric, setActiveMetric] = useState<MetricKey>('traffic');\n const [hasTriggered, setHasTriggered] = useState(false);\n\n // Determine available metrics\n const availableMetrics = useMemo(() => {\n const keys: MetricKey[] = ['traffic', 'conversions', 'revenue', 'rankings'];\n return keys.filter((key) =>\n data.dataPoints.some((dp) => dp.metrics[key] !== undefined && dp.metrics[key] !== null),\n );\n }, [data.dataPoints]);\n\n // Compute chart path for the active metric\n const chartData = useMemo(() => {\n const values = data.dataPoints.map((dp) => dp.metrics[activeMetric] ?? 0);\n const maxVal = Math.max(...values, 1);\n const minVal = Math.min(...values, 0);\n const range = maxVal - minVal || 1;\n\n const chartWidth = 800;\n const chartHeight = 300;\n const padding = 40;\n\n const points = values.map((val, i) => ({\n x: padding + (i / Math.max(values.length - 1, 1)) * (chartWidth - padding * 2),\n y: chartHeight - padding - ((val - minVal) / range) * (chartHeight - padding * 2),\n }));\n\n // Build SVG path\n let d = '';\n if (points.length > 0) {\n d = `M ${points[0].x} ${points[0].y}`;\n for (let i = 1; i < points.length; i++) {\n const cpx1 = (points[i - 1].x + points[i].x) / 2;\n const cpy1 = points[i - 1].y;\n const cpx2 = (points[i - 1].x + points[i].x) / 2;\n const cpy2 = points[i].y;\n d += ` C ${cpx1} ${cpy1}, ${cpx2} ${cpy2}, ${points[i].x} ${points[i].y}`;\n }\n }\n\n // Area fill path\n let areaD = d;\n if (points.length > 0) {\n areaD += ` L ${points[points.length - 1].x} ${chartHeight - padding} L ${points[0].x} ${chartHeight - padding} Z`;\n }\n\n // Find baseline index\n const baselineIdx = data.dataPoints.findIndex((dp) => dp.month === data.baselineDate);\n const baselineX = baselineIdx >= 0 ? points[baselineIdx]?.x : undefined;\n\n return {\n d,\n areaD,\n points,\n chartWidth,\n chartHeight,\n padding,\n baselineX,\n labels: data.dataPoints.map((dp) => dp.label),\n };\n }, [data.dataPoints, data.baselineDate, activeMetric]);\n\n // Animate path draw on scroll (re-runs when the metric changes)\n useEffect(() => {\n const path = pathRef.current;\n const svg = svgRef.current;\n if (!path || !svg) return;\n\n const isHydration = !hydratedRef.current;\n hydratedRef.current = true;\n\n const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n if (prefersReducedMotion) {\n setHasTriggered(true);\n return;\n }\n\n // Never re-hide a chart already in the viewport at hydration. Metric\n // switches still redraw in place — that re-run is user-initiated.\n if (isHydration) {\n const rect = svg.getBoundingClientRect();\n if (rect.top < window.innerHeight && rect.bottom > 0) {\n setHasTriggered(true);\n return;\n }\n }\n\n // Hidden state: line fully undrawn.\n const length = path.getTotalLength();\n path.style.strokeDasharray = String(length);\n path.style.strokeDashoffset = String(length);\n\n let timeout = 0;\n const io = new IntersectionObserver(\n ([entry]) => {\n if (!entry.isIntersecting) return;\n io.disconnect();\n path.style.transition = `stroke-dashoffset 2s ${EASE}`;\n path.style.strokeDashoffset = '0';\n // Area fill + data points pop in once the draw completes.\n timeout = window.setTimeout(() => setHasTriggered(true), 2000);\n },\n { rootMargin: '0px 0px -25% 0px' }, // ≈ the old 'top 75%' trigger\n );\n io.observe(svg);\n\n return () => {\n io.disconnect();\n window.clearTimeout(timeout);\n path.style.transition = '';\n path.style.strokeDasharray = '';\n path.style.strokeDashoffset = '';\n };\n }, [activeMetric]);\n\n const handleMetricChange = useCallback((metric: MetricKey) => {\n setActiveMetric(metric);\n setHasTriggered(false);\n }, []);\n\n const color = metricColors[activeMetric];\n\n return (\n <section\n className=\"w-full py-20 md:py-28\"\n style={{ background: 'var(--sk-bg, #0a0a0a)' }}\n >\n <div className=\"max-w-6xl mx-auto px-6\">\n {(data.title || data.description) && (\n <ScrollReveal y={30}>\n {data.title && (\n <h2\n className=\"text-3xl md:text-4xl font-bold mb-4\"\n style={{\n color: 'var(--sk-text-primary, #ffffff)',\n fontFamily: 'var(--sk-font-heading, inherit)',\n }}\n >\n {data.title}\n </h2>\n )}\n {data.description && (\n <p\n className=\"text-lg mb-8 max-w-2xl\"\n style={{ color: 'var(--sk-text-secondary, #a1a1aa)' }}\n >\n {data.description}\n </p>\n )}\n </ScrollReveal>\n )}\n\n {/* Metric toggle pills */}\n <ScrollReveal y={20} delay={0.1}>\n <div className=\"flex flex-wrap gap-2 mb-8\">\n {availableMetrics.map((metric) => (\n <button\n key={metric}\n onClick={() => handleMetricChange(metric)}\n className=\"px-4 py-2 rounded-full text-sm font-medium transition-all duration-200 cursor-pointer\"\n style={{\n background:\n activeMetric === metric\n ? metricColors[metric]\n : 'var(--sk-surface, rgba(255,255,255,0.05))',\n color:\n activeMetric === metric\n ? '#ffffff'\n : 'var(--sk-text-secondary, #a1a1aa)',\n border: `1px solid ${\n activeMetric === metric\n ? metricColors[metric]\n : 'var(--sk-border, rgba(255,255,255,0.1))'\n }`,\n }}\n >\n {metricLabels[metric]}\n </button>\n ))}\n </div>\n </ScrollReveal>\n\n <ScrollReveal y={40} delay={0.2}>\n <GlassCard padding=\"lg\" hover={false}>\n <svg\n ref={svgRef}\n viewBox={`0 0 ${chartData.chartWidth} ${chartData.chartHeight}`}\n className=\"w-full h-auto\"\n preserveAspectRatio=\"xMidYMid meet\"\n >\n {/* Grid lines */}\n {[0, 1, 2, 3, 4].map((i) => {\n const y =\n chartData.padding +\n (i / 4) * (chartData.chartHeight - chartData.padding * 2);\n return (\n <line\n key={i}\n x1={chartData.padding}\n y1={y}\n x2={chartData.chartWidth - chartData.padding}\n y2={y}\n stroke=\"var(--sk-border, rgba(255,255,255,0.1))\"\n strokeWidth=\"1\"\n />\n );\n })}\n\n {/* Baseline marker */}\n {chartData.baselineX !== undefined && (\n <>\n <line\n x1={chartData.baselineX}\n y1={chartData.padding}\n x2={chartData.baselineX}\n y2={chartData.chartHeight - chartData.padding}\n stroke=\"var(--sk-text-tertiary, #71717a)\"\n strokeWidth=\"1.5\"\n strokeDasharray=\"6 4\"\n />\n <text\n x={chartData.baselineX}\n y={chartData.padding - 10}\n textAnchor=\"middle\"\n fill=\"var(--sk-text-tertiary, #71717a)\"\n fontSize=\"11\"\n fontFamily=\"var(--sk-font, sans-serif)\"\n >\n Launch\n </text>\n </>\n )}\n\n {/* Area fill (gradient) */}\n <defs>\n <linearGradient id={`area-gradient-${activeMetric}`} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={color} stopOpacity=\"0.3\" />\n <stop offset=\"100%\" stopColor={color} stopOpacity=\"0\" />\n </linearGradient>\n </defs>\n {hasTriggered && chartData.areaD && (\n <path\n d={chartData.areaD}\n fill={`url(#area-gradient-${activeMetric})`}\n />\n )}\n\n {/* Chart line (animated draw) */}\n {chartData.d && (\n <path\n ref={pathRef}\n d={chartData.d}\n fill=\"none\"\n stroke={color}\n strokeWidth=\"3\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n )}\n\n {/* Data points */}\n {hasTriggered &&\n chartData.points.map((pt, i) => (\n <circle\n key={i}\n cx={pt.x}\n cy={pt.y}\n r=\"4\"\n fill={color}\n stroke=\"var(--sk-bg, #0a0a0a)\"\n strokeWidth=\"2\"\n />\n ))}\n\n {/* X-axis labels */}\n {chartData.labels.map((label, i) => (\n <text\n key={i}\n x={chartData.points[i]?.x ?? 0}\n y={chartData.chartHeight - 10}\n textAnchor=\"middle\"\n fill=\"var(--sk-text-tertiary, #71717a)\"\n fontSize=\"10\"\n fontFamily=\"var(--sk-font, sans-serif)\"\n >\n {label}\n </text>\n ))}\n </svg>\n </GlassCard>\n </ScrollReveal>\n </div>\n </section>\n );\n}\n"],"mappings":"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","names":[]}