@sonordev/agency-site-kit 0.3.0 → 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.
- package/README.md +302 -0
- package/bin/setup.mjs +79 -0
- package/dist/{chunk-RXBK2EOE.js → chunk-4IES23GV.js} +3 -3
- package/dist/{chunk-RXBK2EOE.js.map → chunk-4IES23GV.js.map} +1 -1
- package/dist/chunk-4N7ENJ7L.cjs +108 -0
- package/dist/chunk-4N7ENJ7L.cjs.map +1 -0
- package/dist/{chunk-WNR4KNG4.cjs → chunk-5MEZU3OG.cjs} +4 -4
- package/dist/{chunk-WNR4KNG4.cjs.map → chunk-5MEZU3OG.cjs.map} +1 -1
- package/dist/chunk-7ZHRMWJU.cjs +306 -0
- package/dist/chunk-7ZHRMWJU.cjs.map +1 -0
- package/dist/chunk-CVT7I5BQ.js +71 -0
- package/dist/chunk-CVT7I5BQ.js.map +1 -0
- package/dist/chunk-HQGAX2LI.cjs +8 -0
- package/dist/chunk-HQGAX2LI.cjs.map +1 -0
- package/dist/chunk-KXLROAO5.js +291 -0
- package/dist/chunk-KXLROAO5.js.map +1 -0
- package/dist/chunk-L4EOQVRJ.js +6 -0
- package/dist/chunk-L4EOQVRJ.js.map +1 -0
- package/dist/chunk-L7E3UHQC.cjs +535 -0
- package/dist/chunk-L7E3UHQC.cjs.map +1 -0
- package/dist/chunk-NI4FVCLS.cjs +32 -0
- package/dist/chunk-NI4FVCLS.cjs.map +1 -0
- package/dist/chunk-NIZJLONK.js +106 -0
- package/dist/chunk-NIZJLONK.js.map +1 -0
- package/dist/chunk-QDXZ27R7.js +33 -0
- package/dist/chunk-QDXZ27R7.js.map +1 -0
- package/dist/{chunk-TVFXN6W6.js → chunk-QL6KVIFR.js} +8 -4
- package/dist/chunk-QL6KVIFR.js.map +1 -0
- package/dist/chunk-UNTOEWQL.js +504 -0
- package/dist/chunk-UNTOEWQL.js.map +1 -0
- package/dist/chunk-XJ434N7I.js +30 -0
- package/dist/chunk-XJ434N7I.js.map +1 -0
- package/dist/chunk-XLK77USA.js +45 -0
- package/dist/chunk-XLK77USA.js.map +1 -0
- package/dist/{chunk-EE75WRCM.cjs → chunk-XOWSXZYW.cjs} +8 -4
- package/dist/chunk-XOWSXZYW.cjs.map +1 -0
- package/dist/chunk-ZINKVJQU.js +67 -0
- package/dist/chunk-ZINKVJQU.js.map +1 -0
- package/dist/index.cjs +29 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -9
- package/dist/index.d.ts +17 -9
- package/dist/index.js +7 -8
- package/dist/index.js.map +1 -1
- package/dist/layout/index.cjs +3 -3
- package/dist/layout/index.d.cts +1 -1
- package/dist/layout/index.d.ts +1 -1
- package/dist/layout/index.js +2 -2
- package/dist/portfolio/client.cjs +342 -12
- package/dist/portfolio/client.cjs.map +1 -1
- package/dist/portfolio/client.d.cts +11 -88
- package/dist/portfolio/client.d.ts +11 -88
- package/dist/portfolio/client.js +150 -4
- package/dist/portfolio/client.js.map +1 -1
- package/dist/portfolio/components/PortfolioAnalytics.cjs +87 -0
- package/dist/portfolio/components/PortfolioAnalytics.cjs.map +1 -0
- package/dist/portfolio/components/PortfolioAnalytics.d.cts +5 -0
- package/dist/portfolio/components/PortfolioAnalytics.d.ts +5 -0
- package/dist/portfolio/components/PortfolioAnalytics.js +9 -0
- package/dist/portfolio/components/PortfolioAnalytics.js.map +1 -0
- package/dist/portfolio/components/PortfolioErrorFallback.cjs +65 -0
- package/dist/portfolio/components/PortfolioErrorFallback.cjs.map +1 -0
- package/dist/portfolio/components/PortfolioErrorFallback.d.cts +22 -0
- package/dist/portfolio/components/PortfolioErrorFallback.d.ts +22 -0
- package/dist/portfolio/components/PortfolioErrorFallback.js +9 -0
- package/dist/portfolio/components/PortfolioErrorFallback.js.map +1 -0
- package/dist/portfolio/components/PortfolioLeadCTA.cjs +91 -0
- package/dist/portfolio/components/PortfolioLeadCTA.cjs.map +1 -0
- package/dist/portfolio/components/PortfolioLeadCTA.d.cts +34 -0
- package/dist/portfolio/components/PortfolioLeadCTA.d.ts +34 -0
- package/dist/portfolio/components/PortfolioLeadCTA.js +9 -0
- package/dist/portfolio/components/PortfolioLeadCTA.js.map +1 -0
- package/dist/portfolio/index.cjs +19 -19
- package/dist/portfolio/index.d.cts +133 -7
- package/dist/portfolio/index.d.ts +133 -7
- package/dist/portfolio/index.js +6 -6
- package/dist/portfolio/primitives/AnimatedCounter.cjs +88 -0
- package/dist/portfolio/primitives/AnimatedCounter.cjs.map +1 -0
- package/dist/portfolio/primitives/AnimatedCounter.d.cts +22 -0
- package/dist/portfolio/primitives/AnimatedCounter.d.ts +22 -0
- package/dist/portfolio/primitives/AnimatedCounter.js +68 -0
- package/dist/portfolio/primitives/AnimatedCounter.js.map +1 -0
- package/dist/portfolio/primitives/AnnotatedImage.cjs +320 -0
- package/dist/portfolio/primitives/AnnotatedImage.cjs.map +1 -0
- package/dist/portfolio/primitives/AnnotatedImage.d.cts +18 -0
- package/dist/portfolio/primitives/AnnotatedImage.d.ts +18 -0
- package/dist/portfolio/primitives/AnnotatedImage.js +264 -0
- package/dist/portfolio/primitives/AnnotatedImage.js.map +1 -0
- package/dist/portfolio/primitives/BeforeAfterSlider.cjs +348 -0
- package/dist/portfolio/primitives/BeforeAfterSlider.cjs.map +1 -0
- package/dist/portfolio/primitives/BeforeAfterSlider.d.cts +13 -0
- package/dist/portfolio/primitives/BeforeAfterSlider.d.ts +13 -0
- package/dist/portfolio/primitives/BeforeAfterSlider.js +292 -0
- package/dist/portfolio/primitives/BeforeAfterSlider.js.map +1 -0
- package/dist/portfolio/primitives/DeviceTrifolio.cjs +298 -0
- package/dist/portfolio/primitives/DeviceTrifolio.cjs.map +1 -0
- package/dist/portfolio/primitives/DeviceTrifolio.d.cts +14 -0
- package/dist/portfolio/primitives/DeviceTrifolio.d.ts +14 -0
- package/dist/portfolio/primitives/DeviceTrifolio.js +242 -0
- package/dist/portfolio/primitives/DeviceTrifolio.js.map +1 -0
- package/dist/portfolio/primitives/FrequencyBarSkeleton.cjs +88 -0
- package/dist/portfolio/primitives/FrequencyBarSkeleton.cjs.map +1 -0
- package/dist/portfolio/primitives/FrequencyBarSkeleton.d.cts +10 -0
- package/dist/portfolio/primitives/FrequencyBarSkeleton.d.ts +10 -0
- package/dist/portfolio/primitives/FrequencyBarSkeleton.js +68 -0
- package/dist/portfolio/primitives/FrequencyBarSkeleton.js.map +1 -0
- package/dist/portfolio/primitives/GlassCard.cjs +45 -0
- package/dist/portfolio/primitives/GlassCard.cjs.map +1 -0
- package/dist/portfolio/primitives/GlassCard.d.cts +11 -0
- package/dist/portfolio/primitives/GlassCard.d.ts +11 -0
- package/dist/portfolio/primitives/GlassCard.js +43 -0
- package/dist/portfolio/primitives/GlassCard.js.map +1 -0
- package/dist/portfolio/primitives/MetricBadge.cjs +74 -0
- package/dist/portfolio/primitives/MetricBadge.cjs.map +1 -0
- package/dist/portfolio/primitives/MetricBadge.d.cts +9 -0
- package/dist/portfolio/primitives/MetricBadge.d.ts +9 -0
- package/dist/portfolio/primitives/MetricBadge.js +54 -0
- package/dist/portfolio/primitives/MetricBadge.js.map +1 -0
- package/dist/portfolio/primitives/SVGChart.cjs +316 -0
- package/dist/portfolio/primitives/SVGChart.cjs.map +1 -0
- package/dist/portfolio/primitives/SVGChart.d.cts +18 -0
- package/dist/portfolio/primitives/SVGChart.d.ts +18 -0
- package/dist/portfolio/primitives/SVGChart.js +296 -0
- package/dist/portfolio/primitives/SVGChart.js.map +1 -0
- package/dist/portfolio/primitives/ScrollReveal.cjs +97 -0
- package/dist/portfolio/primitives/ScrollReveal.cjs.map +1 -0
- package/dist/portfolio/primitives/ScrollReveal.d.cts +27 -0
- package/dist/portfolio/primitives/ScrollReveal.d.ts +27 -0
- package/dist/portfolio/primitives/ScrollReveal.js +77 -0
- package/dist/portfolio/primitives/ScrollReveal.js.map +1 -0
- package/dist/portfolio/primitives/SplitHeadline.cjs +107 -0
- package/dist/portfolio/primitives/SplitHeadline.cjs.map +1 -0
- package/dist/portfolio/primitives/SplitHeadline.d.cts +24 -0
- package/dist/portfolio/primitives/SplitHeadline.d.ts +24 -0
- package/dist/portfolio/primitives/SplitHeadline.js +87 -0
- package/dist/portfolio/primitives/SplitHeadline.js.map +1 -0
- package/dist/portfolio/sections/BeforeAfterSection.cjs +271 -0
- package/dist/portfolio/sections/BeforeAfterSection.cjs.map +1 -0
- package/dist/portfolio/sections/BeforeAfterSection.d.cts +9 -0
- package/dist/portfolio/sections/BeforeAfterSection.d.ts +9 -0
- package/dist/{BeforeAfterSection-6BHFLY4Y.js → portfolio/sections/BeforeAfterSection.js} +66 -27
- package/dist/portfolio/sections/BeforeAfterSection.js.map +1 -0
- package/dist/portfolio/sections/CTASection.cjs +123 -0
- package/dist/portfolio/sections/CTASection.cjs.map +1 -0
- package/dist/portfolio/sections/CTASection.d.cts +9 -0
- package/dist/portfolio/sections/CTASection.d.ts +9 -0
- package/dist/portfolio/sections/CTASection.js +93 -0
- package/dist/portfolio/sections/CTASection.js.map +1 -0
- package/dist/{ChallengesSection-IZ3DHECS.cjs → portfolio/sections/ChallengesSection.cjs} +12 -6
- package/dist/portfolio/sections/ChallengesSection.cjs.map +1 -0
- package/dist/portfolio/sections/ChallengesSection.d.cts +9 -0
- package/dist/portfolio/sections/ChallengesSection.d.ts +9 -0
- package/dist/{ChallengesSection-GEQGVSJN.js → portfolio/sections/ChallengesSection.js} +5 -4
- package/dist/portfolio/sections/ChallengesSection.js.map +1 -0
- package/dist/portfolio/sections/ConversionFunnelSection.cjs +263 -0
- package/dist/portfolio/sections/ConversionFunnelSection.cjs.map +1 -0
- package/dist/portfolio/sections/ConversionFunnelSection.d.cts +9 -0
- package/dist/portfolio/sections/ConversionFunnelSection.d.ts +9 -0
- package/dist/{ConversionFunnelSection-D3GE4NKE.js → portfolio/sections/ConversionFunnelSection.js} +60 -56
- package/dist/portfolio/sections/ConversionFunnelSection.js.map +1 -0
- package/dist/{DesignSystemSection-KXIQXITF.cjs → portfolio/sections/DesignSystemSection.cjs} +13 -7
- package/dist/portfolio/sections/DesignSystemSection.cjs.map +1 -0
- package/dist/portfolio/sections/DesignSystemSection.d.cts +32 -0
- package/dist/portfolio/sections/DesignSystemSection.d.ts +32 -0
- package/dist/{DesignSystemSection-2R5BRBGO.js → portfolio/sections/DesignSystemSection.js} +5 -4
- package/dist/portfolio/sections/DesignSystemSection.js.map +1 -0
- package/dist/{DetailsSection-TTUZAPZZ.cjs → portfolio/sections/DetailsSection.cjs} +12 -6
- package/dist/portfolio/sections/DetailsSection.cjs.map +1 -0
- package/dist/portfolio/sections/DetailsSection.d.cts +9 -0
- package/dist/portfolio/sections/DetailsSection.d.ts +9 -0
- package/dist/{DetailsSection-A6PZQUQL.js → portfolio/sections/DetailsSection.js} +5 -4
- package/dist/portfolio/sections/DetailsSection.js.map +1 -0
- package/dist/portfolio/sections/FeatureSpotlightSection.cjs +267 -0
- package/dist/portfolio/sections/FeatureSpotlightSection.cjs.map +1 -0
- package/dist/portfolio/sections/FeatureSpotlightSection.d.cts +9 -0
- package/dist/portfolio/sections/FeatureSpotlightSection.d.ts +9 -0
- package/dist/{FeatureSpotlightSection-B7P3JGNL.js → portfolio/sections/FeatureSpotlightSection.js} +39 -33
- package/dist/portfolio/sections/FeatureSpotlightSection.js.map +1 -0
- package/dist/portfolio/sections/GallerySection.cjs +321 -0
- package/dist/portfolio/sections/GallerySection.cjs.map +1 -0
- package/dist/portfolio/sections/GallerySection.d.cts +9 -0
- package/dist/portfolio/sections/GallerySection.d.ts +9 -0
- package/dist/{GallerySection-VMKORC47.js → portfolio/sections/GallerySection.js} +65 -18
- package/dist/portfolio/sections/GallerySection.js.map +1 -0
- package/dist/portfolio/sections/HeroSection.cjs +180 -0
- package/dist/portfolio/sections/HeroSection.cjs.map +1 -0
- package/dist/portfolio/sections/HeroSection.d.cts +15 -0
- package/dist/portfolio/sections/HeroSection.d.ts +15 -0
- package/dist/portfolio/sections/HeroSection.js +171 -0
- package/dist/portfolio/sections/HeroSection.js.map +1 -0
- package/dist/{MetricsTimelineSection-4L6DUHJ5.cjs → portfolio/sections/MetricsTimelineSection.cjs} +102 -61
- package/dist/portfolio/sections/MetricsTimelineSection.cjs.map +1 -0
- package/dist/portfolio/sections/MetricsTimelineSection.d.cts +9 -0
- package/dist/portfolio/sections/MetricsTimelineSection.d.ts +9 -0
- package/dist/{MetricsTimelineSection-6BT5GNFV.js → portfolio/sections/MetricsTimelineSection.js} +45 -29
- package/dist/portfolio/sections/MetricsTimelineSection.js.map +1 -0
- package/dist/{PerformanceSection-24TVVFZA.cjs → portfolio/sections/PerformanceSection.cjs} +136 -93
- package/dist/portfolio/sections/PerformanceSection.cjs.map +1 -0
- package/dist/portfolio/sections/PerformanceSection.d.cts +22 -0
- package/dist/portfolio/sections/PerformanceSection.d.ts +22 -0
- package/dist/{PerformanceSection-MGCEIXDX.js → portfolio/sections/PerformanceSection.js} +58 -40
- package/dist/portfolio/sections/PerformanceSection.js.map +1 -0
- package/dist/{ResultsSection-XLGMMQKY.cjs → portfolio/sections/ResultsSection.cjs} +22 -10
- package/dist/portfolio/sections/ResultsSection.cjs.map +1 -0
- package/dist/portfolio/sections/ResultsSection.d.cts +13 -0
- package/dist/portfolio/sections/ResultsSection.d.ts +13 -0
- package/dist/{ResultsSection-DFUJ5U6M.js → portfolio/sections/ResultsSection.js} +13 -7
- package/dist/portfolio/sections/ResultsSection.js.map +1 -0
- package/dist/portfolio/sections/ServicesSection.cjs +129 -0
- package/dist/portfolio/sections/ServicesSection.cjs.map +1 -0
- package/dist/portfolio/sections/ServicesSection.d.cts +9 -0
- package/dist/portfolio/sections/ServicesSection.d.ts +9 -0
- package/dist/portfolio/sections/ServicesSection.js +122 -0
- package/dist/portfolio/sections/ServicesSection.js.map +1 -0
- package/dist/{SiteArchitectureSection-J7BPBERH.cjs → portfolio/sections/SiteArchitectureSection.cjs} +116 -92
- package/dist/portfolio/sections/SiteArchitectureSection.cjs.map +1 -0
- package/dist/portfolio/sections/SiteArchitectureSection.d.cts +21 -0
- package/dist/portfolio/sections/SiteArchitectureSection.d.ts +21 -0
- package/dist/{SiteArchitectureSection-TE22OAWV.js → portfolio/sections/SiteArchitectureSection.js} +46 -47
- package/dist/portfolio/sections/SiteArchitectureSection.js.map +1 -0
- package/dist/{SpeedComparisonSection-EZKFQVGW.cjs → portfolio/sections/SpeedComparisonSection.cjs} +12 -6
- package/dist/portfolio/sections/SpeedComparisonSection.cjs.map +1 -0
- package/dist/portfolio/sections/SpeedComparisonSection.d.cts +20 -0
- package/dist/portfolio/sections/SpeedComparisonSection.d.ts +20 -0
- package/dist/{SpeedComparisonSection-Y3K7OFZQ.js → portfolio/sections/SpeedComparisonSection.js} +5 -4
- package/dist/portfolio/sections/SpeedComparisonSection.js.map +1 -0
- package/dist/portfolio/sections/StrategySection.cjs +233 -0
- package/dist/portfolio/sections/StrategySection.cjs.map +1 -0
- package/dist/portfolio/sections/StrategySection.d.cts +9 -0
- package/dist/portfolio/sections/StrategySection.d.ts +9 -0
- package/dist/{StrategySection-DI5RSCJU.js → portfolio/sections/StrategySection.js} +60 -26
- package/dist/portfolio/sections/StrategySection.js.map +1 -0
- package/dist/portfolio/sections/TeamSection.cjs +162 -0
- package/dist/portfolio/sections/TeamSection.cjs.map +1 -0
- package/dist/portfolio/sections/TeamSection.d.cts +9 -0
- package/dist/portfolio/sections/TeamSection.d.ts +9 -0
- package/dist/portfolio/sections/TeamSection.js +106 -0
- package/dist/portfolio/sections/TeamSection.js.map +1 -0
- package/dist/portfolio/sections/TechStackSection.cjs +106 -0
- package/dist/portfolio/sections/TechStackSection.cjs.map +1 -0
- package/dist/portfolio/sections/TechStackSection.d.cts +9 -0
- package/dist/portfolio/sections/TechStackSection.d.ts +9 -0
- package/dist/portfolio/sections/TechStackSection.js +99 -0
- package/dist/portfolio/sections/TechStackSection.js.map +1 -0
- package/dist/{TestimonialSection-XPTFUQIN.cjs → portfolio/sections/TestimonialSection.cjs} +47 -28
- package/dist/portfolio/sections/TestimonialSection.cjs.map +1 -0
- package/dist/portfolio/sections/TestimonialSection.d.cts +9 -0
- package/dist/portfolio/sections/TestimonialSection.d.ts +9 -0
- package/dist/{TestimonialSection-6RGSMXQB.js → portfolio/sections/TestimonialSection.js} +40 -27
- package/dist/portfolio/sections/TestimonialSection.js.map +1 -0
- package/dist/portfolio/sections/VideoSection.cjs +181 -0
- package/dist/portfolio/sections/VideoSection.cjs.map +1 -0
- package/dist/portfolio/sections/VideoSection.d.cts +9 -0
- package/dist/portfolio/sections/VideoSection.d.ts +9 -0
- package/dist/{VideoSection-4A2HC6K6.js → portfolio/sections/VideoSection.js} +21 -13
- package/dist/portfolio/sections/VideoSection.js.map +1 -0
- package/dist/portfolio/server.cjs +56 -139
- package/dist/portfolio/server.cjs.map +1 -1
- package/dist/portfolio/server.d.cts +157 -7
- package/dist/portfolio/server.d.ts +157 -7
- package/dist/portfolio/server.js +3 -137
- package/dist/portfolio/server.js.map +1 -1
- package/dist/preview.cjs +56 -0
- package/dist/preview.cjs.map +1 -0
- package/dist/preview.d.cts +31 -0
- package/dist/preview.d.ts +31 -0
- package/dist/preview.js +54 -0
- package/dist/preview.js.map +1 -0
- package/dist/{types-DL4t_Cfa.d.ts → types-0tVPy4pU.d.cts} +7 -1
- package/dist/{types-DL4t_Cfa.d.cts → types-0tVPy4pU.d.ts} +7 -1
- package/dist/types-D0nb6KAx.d.cts +299 -0
- package/dist/types-D0nb6KAx.d.ts +299 -0
- package/package.json +38 -14
- package/templates/api-portfolio-preview.ts +6 -0
- package/templates/api-revalidate.ts +5 -0
- package/templates/work-category-page.tsx +40 -0
- package/templates/work-error.tsx +3 -0
- package/templates/work-loading.tsx +1 -0
- package/templates/work-page.tsx +37 -0
- package/templates/work-slug-loading.tsx +1 -0
- package/templates/work-slug-page.tsx +41 -0
- package/dist/BeforeAfterSection-6BHFLY4Y.js.map +0 -1
- package/dist/BeforeAfterSection-JTORBR3A.cjs +0 -181
- package/dist/BeforeAfterSection-JTORBR3A.cjs.map +0 -1
- package/dist/CTASection-4JKLXEUF.cjs +0 -111
- package/dist/CTASection-4JKLXEUF.cjs.map +0 -1
- package/dist/CTASection-BJA72XIL.js +0 -106
- package/dist/CTASection-BJA72XIL.js.map +0 -1
- package/dist/ChallengesSection-GEQGVSJN.js.map +0 -1
- package/dist/ChallengesSection-IZ3DHECS.cjs.map +0 -1
- package/dist/ConversionFunnelSection-AUUSJ5HQ.cjs +0 -209
- package/dist/ConversionFunnelSection-AUUSJ5HQ.cjs.map +0 -1
- package/dist/ConversionFunnelSection-D3GE4NKE.js.map +0 -1
- package/dist/DesignSystemSection-2R5BRBGO.js.map +0 -1
- package/dist/DesignSystemSection-KXIQXITF.cjs.map +0 -1
- package/dist/DetailsSection-A6PZQUQL.js.map +0 -1
- package/dist/DetailsSection-TTUZAPZZ.cjs.map +0 -1
- package/dist/FeatureSpotlightSection-B7P3JGNL.js.map +0 -1
- package/dist/FeatureSpotlightSection-WRHXS7TU.cjs +0 -210
- package/dist/FeatureSpotlightSection-WRHXS7TU.cjs.map +0 -1
- package/dist/GallerySection-VMKORC47.js.map +0 -1
- package/dist/GallerySection-WJ4PQDBI.cjs +0 -219
- package/dist/GallerySection-WJ4PQDBI.cjs.map +0 -1
- package/dist/MetricsTimelineSection-4L6DUHJ5.cjs.map +0 -1
- package/dist/MetricsTimelineSection-6BT5GNFV.js.map +0 -1
- package/dist/PerformanceSection-24TVVFZA.cjs.map +0 -1
- package/dist/PerformanceSection-MGCEIXDX.js.map +0 -1
- package/dist/ResultsSection-DFUJ5U6M.js.map +0 -1
- package/dist/ResultsSection-XLGMMQKY.cjs.map +0 -1
- package/dist/ServicesSection-D5V3Q4GR.js +0 -118
- package/dist/ServicesSection-D5V3Q4GR.js.map +0 -1
- package/dist/ServicesSection-WJMGK2MF.cjs +0 -120
- package/dist/ServicesSection-WJMGK2MF.cjs.map +0 -1
- package/dist/SiteArchitectureSection-J7BPBERH.cjs.map +0 -1
- package/dist/SiteArchitectureSection-TE22OAWV.js.map +0 -1
- package/dist/SpeedComparisonSection-EZKFQVGW.cjs.map +0 -1
- package/dist/SpeedComparisonSection-Y3K7OFZQ.js.map +0 -1
- package/dist/StrategySection-CJ7Y6OFQ.cjs +0 -174
- package/dist/StrategySection-CJ7Y6OFQ.cjs.map +0 -1
- package/dist/StrategySection-DI5RSCJU.js.map +0 -1
- package/dist/TeamSection-DZVSNZE6.cjs +0 -112
- package/dist/TeamSection-DZVSNZE6.cjs.map +0 -1
- package/dist/TeamSection-HGKFW6PQ.js +0 -107
- package/dist/TeamSection-HGKFW6PQ.js.map +0 -1
- package/dist/TechStackSection-2AQ7RGY3.js +0 -93
- package/dist/TechStackSection-2AQ7RGY3.js.map +0 -1
- package/dist/TechStackSection-VTNNZR5V.cjs +0 -95
- package/dist/TechStackSection-VTNNZR5V.cjs.map +0 -1
- package/dist/TestimonialSection-6RGSMXQB.js.map +0 -1
- package/dist/TestimonialSection-XPTFUQIN.cjs.map +0 -1
- package/dist/VideoSection-4A2HC6K6.js.map +0 -1
- package/dist/VideoSection-G3DFS7UH.cjs +0 -118
- package/dist/VideoSection-G3DFS7UH.cjs.map +0 -1
- package/dist/chunk-2UNKXWQM.js +0 -630
- package/dist/chunk-2UNKXWQM.js.map +0 -1
- package/dist/chunk-2Y4O3LWM.js +0 -53
- package/dist/chunk-2Y4O3LWM.js.map +0 -1
- package/dist/chunk-7CFFAKDM.js +0 -74
- package/dist/chunk-7CFFAKDM.js.map +0 -1
- package/dist/chunk-APG2QSMB.js +0 -131
- package/dist/chunk-APG2QSMB.js.map +0 -1
- package/dist/chunk-EE75WRCM.cjs.map +0 -1
- package/dist/chunk-FDFVLYAM.cjs +0 -637
- package/dist/chunk-FDFVLYAM.cjs.map +0 -1
- package/dist/chunk-IKBK7HYX.cjs +0 -79
- package/dist/chunk-IKBK7HYX.cjs.map +0 -1
- package/dist/chunk-KEOHORIH.cjs +0 -79
- package/dist/chunk-KEOHORIH.cjs.map +0 -1
- package/dist/chunk-OA5ZM4OA.cjs +0 -139
- package/dist/chunk-OA5ZM4OA.cjs.map +0 -1
- package/dist/chunk-TVFXN6W6.js.map +0 -1
- package/dist/chunk-XCKXHK44.js +0 -15
- package/dist/chunk-XCKXHK44.js.map +0 -1
- package/dist/chunk-XONXEFJY.cjs +0 -58
- package/dist/chunk-XONXEFJY.cjs.map +0 -1
- package/dist/chunk-XQNJED46.cjs +0 -19
- package/dist/chunk-XQNJED46.cjs.map +0 -1
- package/dist/chunk-YB4B3OMC.js +0 -74
- package/dist/chunk-YB4B3OMC.js.map +0 -1
- package/dist/portfolio/sections.cjs +0 -20
- package/dist/portfolio/sections.cjs.map +0 -1
- package/dist/portfolio/sections.d.cts +0 -42
- package/dist/portfolio/sections.d.ts +0 -42
- package/dist/portfolio/sections.js +0 -4
- package/dist/portfolio/sections.js.map +0 -1
package/dist/{MetricsTimelineSection-4L6DUHJ5.cjs → portfolio/sections/MetricsTimelineSection.cjs}
RENAMED
|
@@ -1,16 +1,44 @@
|
|
|
1
|
-
'use
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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 =
|
|
28
|
-
const pathRef =
|
|
29
|
-
const
|
|
30
|
-
const [
|
|
31
|
-
const
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
116
|
-
(data.title || data.description) && /* @__PURE__ */
|
|
117
|
-
data.title && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
175
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
201
|
-
/* @__PURE__ */
|
|
202
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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 };
|
package/dist/{MetricsTimelineSection-6BT5GNFV.js → portfolio/sections/MetricsTimelineSection.js}
RENAMED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
|
|
252
|
-
|
|
253
|
-
//# sourceMappingURL=MetricsTimelineSection
|
|
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":[]}
|