@sonordev/agency-site-kit 0.3.1 → 0.4.1
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-WNR4KNG4.cjs → chunk-5MEZU3OG.cjs} +4 -4
- package/dist/{chunk-WNR4KNG4.cjs.map → chunk-5MEZU3OG.cjs.map} +1 -1
- package/dist/chunk-7D4H36UF.js +13 -0
- package/dist/chunk-7D4H36UF.js.map +1 -0
- 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-K2BGTDSN.js +45 -0
- package/dist/chunk-K2BGTDSN.js.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-NI4FVCLS.cjs +32 -0
- package/dist/chunk-NI4FVCLS.cjs.map +1 -0
- package/dist/chunk-NLGUPJZA.js +507 -0
- package/dist/chunk-NLGUPJZA.js.map +1 -0
- package/dist/chunk-QDXZ27R7.js +33 -0
- package/dist/chunk-QDXZ27R7.js.map +1 -0
- package/dist/chunk-QGSW43TM.cjs +538 -0
- package/dist/chunk-QGSW43TM.cjs.map +1 -0
- package/dist/{chunk-TVFXN6W6.js → chunk-QL6KVIFR.js} +8 -4
- package/dist/chunk-QL6KVIFR.js.map +1 -0
- package/dist/chunk-RWQ675N6.js +165 -0
- package/dist/chunk-RWQ675N6.js.map +1 -0
- package/dist/chunk-UXUU7FVT.cjs +171 -0
- package/dist/chunk-UXUU7FVT.cjs.map +1 -0
- package/dist/chunk-XJ434N7I.js +30 -0
- package/dist/chunk-XJ434N7I.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-ZBPF7TLZ.cjs +16 -0
- package/dist/chunk-ZBPF7TLZ.cjs.map +1 -0
- package/dist/chunk-ZINKVJQU.js +67 -0
- package/dist/chunk-ZINKVJQU.js.map +1 -0
- package/dist/index.cjs +53 -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 +8 -9
- 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 +376 -12
- package/dist/portfolio/client.cjs.map +1 -1
- package/dist/portfolio/client.d.cts +27 -85
- package/dist/portfolio/client.d.ts +27 -85
- package/dist/portfolio/client.js +182 -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 +43 -19
- package/dist/portfolio/index.d.cts +210 -7
- package/dist/portfolio/index.d.ts +210 -7
- package/dist/portfolio/index.js +7 -7
- 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} +13 -7
- 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} +6 -5
- 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/portfolio/sections/PerformanceSection.cjs +336 -0
- 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} +59 -104
- package/dist/portfolio/sections/PerformanceSection.js.map +1 -0
- package/dist/{ResultsSection-XLGMMQKY.cjs → portfolio/sections/ResultsSection.cjs} +23 -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} +14 -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} +117 -93
- 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} +47 -48
- package/dist/portfolio/sections/SiteArchitectureSection.js.map +1 -0
- package/dist/{SpeedComparisonSection-EZKFQVGW.cjs → portfolio/sections/SpeedComparisonSection.cjs} +13 -7
- 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} +6 -5
- 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 -144
- 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 -142
- 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 +0 -356
- 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-2Y4O3LWM.js +0 -53
- package/dist/chunk-2Y4O3LWM.js.map +0 -1
- package/dist/chunk-633UMQQH.cjs +0 -31
- package/dist/chunk-633UMQQH.cjs.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-AVCH4LMG.cjs +0 -620
- package/dist/chunk-AVCH4LMG.cjs.map +0 -1
- package/dist/chunk-AYBUHRFS.js +0 -613
- package/dist/chunk-AYBUHRFS.js.map +0 -1
- package/dist/chunk-EE75WRCM.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-VVTK4OL6.js +0 -28
- package/dist/chunk-VVTK4OL6.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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/portfolio/components/sections/SiteArchitectureSection.tsx"],"sourcesContent":["'use client';\n\nimport React, { useRef, useEffect, useState } from 'react';\nimport ScrollReveal from '@sonordev/agency-site-kit/portfolio/primitives/ScrollReveal';\nimport GlassCard from '@sonordev/agency-site-kit/portfolio/primitives/GlassCard';\n\ninterface PageGroup {\n label: string;\n count: number;\n // path is optional: PortfolioPage strips raw client-site paths before they\n // reach this client component so they never enter the RSC flight payload\n // (Googlebot crawls path-like strings against the host site → 404 floods).\n pages: Array<{ path?: string; title: string }>;\n}\n\nexport interface SiteArchitectureData {\n totalPages: number;\n totalWords: number;\n groups: PageGroup[];\n}\n\ninterface SiteArchitectureSectionProps {\n data: SiteArchitectureData;\n}\n\n/** Generates a pleasing color from the brand palette for each branch */\nfunction getBranchColor(index: number): string {\n const hues = [\n 'var(--sk-primary, #6366f1)',\n '#10b981',\n '#f59e0b',\n '#8b5cf6',\n '#ec4899',\n '#06b6d4',\n '#f97316',\n '#14b8a6',\n ];\n return hues[index % hues.length];\n}\n\nconst EASE = 'cubic-bezier(0.25, 0.46, 0.45, 0.94)'; // ≈ power2.out\nconst EASE_BACK = 'cubic-bezier(0.34, 1.4, 0.64, 1)'; // ≈ back.out(1.4)\n\nexport default function SiteArchitectureSection({ data }: SiteArchitectureSectionProps) {\n const { totalPages, totalWords, groups } = data;\n const treeRef = useRef<HTMLDivElement>(null);\n const [expandedGroup, setExpandedGroup] = useState<number | null>(null);\n\n // Animate each branch node in on scroll\n useEffect(() => {\n const tree = treeRef.current;\n if (!tree) return;\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;\n\n // Never re-hide a tree already in the viewport at hydration.\n const rect = tree.getBoundingClientRect();\n if (rect.top < window.innerHeight && rect.bottom > 0) return;\n\n const nodes = Array.from(tree.querySelectorAll<HTMLElement>('.arch-node'));\n if (nodes.length === 0) return;\n\n // Hidden state — nodes pop in with a slight back-out overshoot on reveal.\n for (const node of nodes) {\n node.style.opacity = '0';\n node.style.transform = 'translateY(20px) scale(0.8)';\n node.style.willChange = 'opacity, transform';\n }\n\n const io = new IntersectionObserver(\n ([entry]) => {\n if (!entry.isIntersecting) return;\n io.disconnect();\n nodes.forEach((node, i) => {\n const d = i * 0.08;\n node.style.transition = `opacity 0.5s ${EASE} ${d}s, transform 0.5s ${EASE_BACK} ${d}s`;\n node.style.opacity = '1';\n node.style.transform = 'translateY(0px) scale(1)';\n });\n },\n { rootMargin: '0px 0px -30% 0px' }, // ≈ the old 'top 70%' trigger\n );\n io.observe(tree);\n\n return () => {\n io.disconnect();\n for (const node of nodes) {\n node.style.opacity = '';\n node.style.transform = '';\n node.style.transition = '';\n node.style.willChange = '';\n }\n };\n }, [groups.length]);\n\n const hasWords = totalWords > 0;\n const subtitle = hasWords\n ? `${totalPages} pages structured across ${groups.length} content ${groups.length === 1 ? 'category' : 'categories'} with ${totalWords.toLocaleString()} words of content.`\n : `${totalPages} pages structured across ${groups.length} content ${groups.length === 1 ? 'category' : 'categories'}.`;\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 <ScrollReveal y={30}>\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 Site Architecture\n </h2>\n <p\n className=\"text-lg mb-16 max-w-3xl\"\n style={{ color: 'var(--sk-text-secondary, #a1a1aa)' }}\n >\n {subtitle}\n </p>\n </ScrollReveal>\n\n {/* Visual Tree */}\n <div ref={treeRef} className=\"relative\">\n {/* Root node — the domain */}\n <div className=\"flex justify-center mb-8\">\n <div\n className=\"arch-node relative px-6 py-3 rounded-xl text-center\"\n style={{\n background: 'color-mix(in srgb, var(--sk-primary, #6366f1) 15%, var(--sk-bg, #0a0a0a))',\n border: '2px solid var(--sk-primary, #6366f1)',\n boxShadow: '0 0 30px color-mix(in srgb, var(--sk-primary, #6366f1) 20%, transparent)',\n }}\n >\n <span\n className=\"text-sm font-bold tracking-wide\"\n style={{ color: 'var(--sk-primary, #6366f1)' }}\n >\n /\n </span>\n <span\n className=\"block text-xs mt-0.5\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n {totalPages} pages\n </span>\n </div>\n </div>\n\n {/* Branch nodes — each page group */}\n <div className=\"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4\">\n {groups.map((group, gi) => {\n const color = getBranchColor(gi);\n const isExpanded = expandedGroup === gi;\n const hasChildren = group.pages.length > 0;\n\n return (\n <div\n key={gi}\n className=\"arch-node flex flex-col\"\n >\n {/* Branch connector line (vertical from root) */}\n <div\n className=\"w-px h-6 mx-auto mb-2\"\n style={{\n background: `linear-gradient(to bottom, color-mix(in srgb, ${color} 40%, transparent), ${color})`,\n }}\n />\n\n {/* Branch node */}\n <button\n onClick={() => hasChildren && setExpandedGroup(isExpanded ? null : gi)}\n className=\"relative rounded-xl p-4 text-left transition-all duration-300 cursor-pointer group\"\n style={{\n background: `color-mix(in srgb, ${color} 8%, var(--sk-bg, #0a0a0a))`,\n border: `1.5px solid color-mix(in srgb, ${color} ${isExpanded ? '40' : '20'}%, transparent)`,\n boxShadow: isExpanded\n ? `0 0 20px color-mix(in srgb, ${color} 15%, transparent)`\n : 'none',\n }}\n >\n {/* Count badge */}\n <div\n className=\"absolute -top-2.5 -right-2 px-2 py-0.5 rounded-full text-xs font-bold\"\n style={{\n background: color,\n color: '#000',\n boxShadow: `0 0 10px color-mix(in srgb, ${color} 40%, transparent)`,\n }}\n >\n {group.count}\n </div>\n\n <div className=\"flex items-center gap-2\">\n {/* Branch icon — folder-like indicator */}\n <div\n className=\"w-2 h-2 rounded-full shrink-0\"\n style={{ background: color }}\n />\n <span\n className=\"text-sm font-semibold truncate\"\n style={{ color: 'var(--sk-text-primary, #ffffff)' }}\n >\n {group.label}\n </span>\n </div>\n\n {/* Expand indicator */}\n {hasChildren && (\n <span\n className=\"text-[10px] mt-1 block transition-colors\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n {isExpanded ? 'click to collapse' : `${group.count} ${group.count === 1 ? 'page' : 'pages'} · click to expand`}\n </span>\n )}\n </button>\n\n {/* Expanded page list */}\n {isExpanded && hasChildren && (\n <div\n className=\"mt-2 rounded-lg overflow-hidden\"\n style={{\n background: `color-mix(in srgb, ${color} 5%, var(--sk-bg, #0a0a0a))`,\n border: `1px solid color-mix(in srgb, ${color} 15%, transparent)`,\n }}\n >\n {group.pages.map((page, pi) => (\n <div\n key={pi}\n className=\"flex items-center gap-2 px-3 py-1.5\"\n style={{\n borderBottom:\n pi < group.pages.length - 1\n ? `1px solid color-mix(in srgb, ${color} 8%, transparent)`\n : 'none',\n }}\n >\n <div\n className=\"w-1 h-1 rounded-full shrink-0\"\n style={{ background: color, opacity: 0.5 }}\n />\n <span\n className=\"text-xs truncate\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n title={page.title || page.path}\n >\n {page.title || page.path}\n </span>\n </div>\n ))}\n {group.count > group.pages.length && (\n <div\n className=\"px-3 py-1.5 text-xs italic\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)', opacity: 0.6 }}\n >\n +{group.count - group.pages.length} more pages\n </div>\n )}\n </div>\n )}\n </div>\n );\n })}\n </div>\n </div>\n\n {/* Bottom stats bar */}\n <ScrollReveal y={20} delay={0.4}>\n <div\n className=\"mt-12 flex items-center justify-center gap-8 md:gap-12 py-4 px-6 rounded-xl mx-auto max-w-2xl\"\n style={{\n background: 'color-mix(in srgb, var(--sk-primary, #6366f1) 5%, var(--sk-bg, #0a0a0a))',\n border: '1px solid color-mix(in srgb, var(--sk-primary, #6366f1) 15%, transparent)',\n }}\n >\n <div className=\"text-center\">\n <span\n className=\"text-2xl font-bold block\"\n style={{ color: 'var(--sk-primary, #6366f1)' }}\n >\n {totalPages}\n </span>\n <span\n className=\"text-[10px] uppercase tracking-wider block mt-0.5\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n Pages\n </span>\n </div>\n <div\n className=\"w-px h-8\"\n style={{ background: 'color-mix(in srgb, var(--sk-text-tertiary, #71717a) 20%, transparent)' }}\n />\n <div className=\"text-center\">\n <span\n className=\"text-2xl font-bold block\"\n style={{ color: 'var(--sk-primary, #6366f1)' }}\n >\n {groups.length}\n </span>\n <span\n className=\"text-[10px] uppercase tracking-wider block mt-0.5\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n Categories\n </span>\n </div>\n {hasWords && (\n <>\n <div\n className=\"w-px h-8\"\n style={{ background: 'color-mix(in srgb, var(--sk-text-tertiary, #71717a) 20%, transparent)' }}\n />\n <div className=\"text-center\">\n <span\n className=\"text-2xl font-bold block\"\n style={{ color: 'var(--sk-primary, #6366f1)' }}\n >\n {totalWords > 1000 ? `${(totalWords / 1000).toFixed(0)}k` : totalWords}\n </span>\n <span\n className=\"text-[10px] uppercase tracking-wider block mt-0.5\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n Words\n </span>\n </div>\n </>\n )}\n </div>\n </ScrollReveal>\n </div>\n </section>\n );\n}\n"],"mappings":"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","names":[]}
|
package/dist/{SpeedComparisonSection-EZKFQVGW.cjs → portfolio/sections/SpeedComparisonSection.cjs}
RENAMED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
3
|
+
var ScrollReveal = require('@sonordev/agency-site-kit/portfolio/primitives/ScrollReveal');
|
|
4
|
+
var GlassCard = require('@sonordev/agency-site-kit/portfolio/primitives/GlassCard');
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
|
|
7
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
+
|
|
9
|
+
var ScrollReveal__default = /*#__PURE__*/_interopDefault(ScrollReveal);
|
|
10
|
+
var GlassCard__default = /*#__PURE__*/_interopDefault(GlassCard);
|
|
11
|
+
|
|
12
|
+
// src/portfolio/components/sections/SpeedComparisonSection.tsx
|
|
7
13
|
var CATEGORIES = [
|
|
8
|
-
{ key: "performance", label: "Performance", why: "Faster sites convert better
|
|
14
|
+
{ key: "performance", label: "Performance", why: "Faster sites convert better: every 100ms of improvement increases conversions by up to 8%." },
|
|
9
15
|
{ key: "seo", label: "SEO", why: "Higher SEO scores mean better search rankings, more organic traffic, and lower customer acquisition costs." },
|
|
10
16
|
{ key: "accessibility", label: "Accessibility", why: "Accessible sites reach 15-20% more users and reduce legal liability." },
|
|
11
17
|
{ key: "bestPractices", label: "Best Practices", why: "Modern security headers, HTTPS, and optimized assets build trust and protect users." }
|
|
@@ -67,7 +73,7 @@ function SpeedComparisonSection({ data }) {
|
|
|
67
73
|
className: "w-full py-20 md:py-28",
|
|
68
74
|
style: { background: "var(--sk-bg, #0a0a0a)" },
|
|
69
75
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-5xl mx-auto px-6", children: [
|
|
70
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
76
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ScrollReveal__default.default, { y: 30, children: [
|
|
71
77
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
72
78
|
"h2",
|
|
73
79
|
{
|
|
@@ -104,7 +110,7 @@ function SpeedComparisonSection({ data }) {
|
|
|
104
110
|
const ours = actual[cat.key];
|
|
105
111
|
const theirs = benchmarks[cat.key];
|
|
106
112
|
const diff = ours - theirs;
|
|
107
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
113
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ScrollReveal__default.default, { y: 20, delay: ci * 0.1, children: /* @__PURE__ */ jsxRuntime.jsx(GlassCard__default.default, { padding: "lg", hover: false, className: "h-full", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-5", children: [
|
|
108
114
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-3 shrink-0", children: [
|
|
109
115
|
/* @__PURE__ */ jsxRuntime.jsx(ScoreRing, { score: ours }),
|
|
110
116
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -170,5 +176,5 @@ function SpeedComparisonSection({ data }) {
|
|
|
170
176
|
}
|
|
171
177
|
|
|
172
178
|
module.exports = SpeedComparisonSection;
|
|
173
|
-
//# sourceMappingURL=SpeedComparisonSection
|
|
174
|
-
//# sourceMappingURL=SpeedComparisonSection
|
|
179
|
+
//# sourceMappingURL=SpeedComparisonSection.cjs.map
|
|
180
|
+
//# sourceMappingURL=SpeedComparisonSection.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/portfolio/components/sections/SpeedComparisonSection.tsx"],"names":["jsxs","jsx","ScrollReveal","GlassCard"],"mappings":"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","file":"SpeedComparisonSection.cjs","sourcesContent":["// Server component — renders on the server; the client primitives below cross the\n// RSC boundary via package subpaths (never import them relatively here).\nimport React from 'react';\nimport ScrollReveal from '@sonordev/agency-site-kit/portfolio/primitives/ScrollReveal';\nimport GlassCard from '@sonordev/agency-site-kit/portfolio/primitives/GlassCard';\n\ninterface Scores {\n performance: number;\n seo: number;\n accessibility: number;\n bestPractices: number;\n}\n\nexport interface SpeedComparisonData {\n platform: string;\n platformLabel: string;\n benchmarks: Scores;\n actual: Scores;\n}\n\ninterface SpeedComparisonSectionProps {\n data: SpeedComparisonData;\n}\n\nconst CATEGORIES: Array<{ key: keyof Scores; label: string; why: string }> = [\n { key: 'performance', label: 'Performance', why: 'Faster sites convert better: every 100ms of improvement increases conversions by up to 8%.' },\n { key: 'seo', label: 'SEO', why: 'Higher SEO scores mean better search rankings, more organic traffic, and lower customer acquisition costs.' },\n { key: 'accessibility', label: 'Accessibility', why: 'Accessible sites reach 15-20% more users and reduce legal liability.' },\n { key: 'bestPractices', label: 'Best Practices', why: 'Modern security headers, HTTPS, and optimized assets build trust and protect users.' },\n];\n\nfunction getScoreColor(score: number): string {\n if (score >= 90) return '#10b981';\n if (score >= 50) return '#f59e0b';\n return '#ef4444';\n}\n\n/** Circular score gauge */\nfunction ScoreRing({ score, size = 72 }: { score: number; size?: number }) {\n const strokeWidth = 5;\n const radius = (size - strokeWidth) / 2;\n const circumference = 2 * Math.PI * radius;\n const progress = (score / 100) * circumference;\n const color = getScoreColor(score);\n\n return (\n <div className=\"relative\" style={{ width: size, height: size }}>\n <svg width={size} height={size} className=\"transform -rotate-90\">\n <circle\n cx={size / 2}\n cy={size / 2}\n r={radius}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={strokeWidth}\n style={{ color: 'color-mix(in srgb, var(--sk-text-tertiary, #71717a) 20%, transparent)' }}\n />\n <circle\n cx={size / 2}\n cy={size / 2}\n r={radius}\n fill=\"none\"\n stroke={color}\n strokeWidth={strokeWidth}\n strokeDasharray={`${progress} ${circumference - progress}`}\n strokeLinecap=\"round\"\n />\n </svg>\n <span\n className=\"absolute inset-0 flex items-center justify-center text-lg font-bold\"\n style={{ color }}\n >\n {score}\n </span>\n </div>\n );\n}\n\nexport default function SpeedComparisonSection({ data }: SpeedComparisonSectionProps) {\n const { platformLabel, benchmarks, actual } = data;\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-5xl mx-auto px-6\">\n <ScrollReveal y={30}>\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 Why This Matters\n </h2>\n <p\n className=\"text-lg mb-4 max-w-3xl\"\n style={{ color: 'var(--sk-text-secondary, #a1a1aa)' }}\n >\n Lighthouse measures real-world site quality across performance, SEO, accessibility, and best practices.\n These scores directly impact search rankings, conversion rates, and user experience.\n </p>\n <p\n className=\"text-base mb-12 max-w-3xl\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n Here's how this Next.js build compares to the average {platformLabel} site.\n </p>\n </ScrollReveal>\n\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n {CATEGORIES.map((cat, ci) => {\n const ours = actual[cat.key];\n const theirs = benchmarks[cat.key];\n const diff = ours - theirs;\n\n return (\n <ScrollReveal key={cat.key} y={20} delay={ci * 0.1}>\n <GlassCard padding=\"lg\" hover={false} className=\"h-full\">\n <div className=\"flex items-start gap-5\">\n {/* Score rings side by side */}\n <div className=\"flex flex-col items-center gap-3 shrink-0\">\n <ScoreRing score={ours} />\n <span\n className=\"text-[10px] font-medium uppercase tracking-wider\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n Next.js\n </span>\n </div>\n <div className=\"flex flex-col items-center gap-3 shrink-0\">\n <ScoreRing score={theirs} />\n <span\n className=\"text-[10px] font-medium uppercase tracking-wider\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n {platformLabel}\n </span>\n </div>\n\n {/* Details */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 mb-2\">\n <h3\n className=\"text-base font-semibold\"\n style={{ color: 'var(--sk-text-primary, #ffffff)' }}\n >\n {cat.label}\n </h3>\n {diff > 0 && (\n <span\n className=\"text-xs font-bold px-2 py-0.5 rounded-full\"\n style={{\n background: 'color-mix(in srgb, #10b981 15%, transparent)',\n color: '#10b981',\n }}\n >\n +{diff} pts\n </span>\n )}\n </div>\n <p\n className=\"text-sm leading-relaxed\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n {cat.why}\n </p>\n </div>\n </div>\n </GlassCard>\n </ScrollReveal>\n );\n })}\n </div>\n </div>\n </section>\n );\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface Scores {
|
|
4
|
+
performance: number;
|
|
5
|
+
seo: number;
|
|
6
|
+
accessibility: number;
|
|
7
|
+
bestPractices: number;
|
|
8
|
+
}
|
|
9
|
+
interface SpeedComparisonData {
|
|
10
|
+
platform: string;
|
|
11
|
+
platformLabel: string;
|
|
12
|
+
benchmarks: Scores;
|
|
13
|
+
actual: Scores;
|
|
14
|
+
}
|
|
15
|
+
interface SpeedComparisonSectionProps {
|
|
16
|
+
data: SpeedComparisonData;
|
|
17
|
+
}
|
|
18
|
+
declare function SpeedComparisonSection({ data }: SpeedComparisonSectionProps): React.JSX.Element;
|
|
19
|
+
|
|
20
|
+
export { type SpeedComparisonData, SpeedComparisonSection as default };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface Scores {
|
|
4
|
+
performance: number;
|
|
5
|
+
seo: number;
|
|
6
|
+
accessibility: number;
|
|
7
|
+
bestPractices: number;
|
|
8
|
+
}
|
|
9
|
+
interface SpeedComparisonData {
|
|
10
|
+
platform: string;
|
|
11
|
+
platformLabel: string;
|
|
12
|
+
benchmarks: Scores;
|
|
13
|
+
actual: Scores;
|
|
14
|
+
}
|
|
15
|
+
interface SpeedComparisonSectionProps {
|
|
16
|
+
data: SpeedComparisonData;
|
|
17
|
+
}
|
|
18
|
+
declare function SpeedComparisonSection({ data }: SpeedComparisonSectionProps): React.JSX.Element;
|
|
19
|
+
|
|
20
|
+
export { type SpeedComparisonData, SpeedComparisonSection as default };
|
package/dist/{SpeedComparisonSection-Y3K7OFZQ.js → portfolio/sections/SpeedComparisonSection.js}
RENAMED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import ScrollReveal from '@sonordev/agency-site-kit/portfolio/primitives/ScrollReveal';
|
|
2
|
+
import GlassCard from '@sonordev/agency-site-kit/portfolio/primitives/GlassCard';
|
|
3
3
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
4
|
|
|
5
|
+
// src/portfolio/components/sections/SpeedComparisonSection.tsx
|
|
5
6
|
var CATEGORIES = [
|
|
6
|
-
{ key: "performance", label: "Performance", why: "Faster sites convert better
|
|
7
|
+
{ key: "performance", label: "Performance", why: "Faster sites convert better: every 100ms of improvement increases conversions by up to 8%." },
|
|
7
8
|
{ key: "seo", label: "SEO", why: "Higher SEO scores mean better search rankings, more organic traffic, and lower customer acquisition costs." },
|
|
8
9
|
{ key: "accessibility", label: "Accessibility", why: "Accessible sites reach 15-20% more users and reduce legal liability." },
|
|
9
10
|
{ key: "bestPractices", label: "Best Practices", why: "Modern security headers, HTTPS, and optimized assets build trust and protect users." }
|
|
@@ -168,5 +169,5 @@ function SpeedComparisonSection({ data }) {
|
|
|
168
169
|
}
|
|
169
170
|
|
|
170
171
|
export { SpeedComparisonSection as default };
|
|
171
|
-
//# sourceMappingURL=SpeedComparisonSection
|
|
172
|
-
//# sourceMappingURL=SpeedComparisonSection
|
|
172
|
+
//# sourceMappingURL=SpeedComparisonSection.js.map
|
|
173
|
+
//# sourceMappingURL=SpeedComparisonSection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/portfolio/components/sections/SpeedComparisonSection.tsx"],"names":[],"mappings":"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","file":"SpeedComparisonSection.js","sourcesContent":["// Server component — renders on the server; the client primitives below cross the\n// RSC boundary via package subpaths (never import them relatively here).\nimport React from 'react';\nimport ScrollReveal from '@sonordev/agency-site-kit/portfolio/primitives/ScrollReveal';\nimport GlassCard from '@sonordev/agency-site-kit/portfolio/primitives/GlassCard';\n\ninterface Scores {\n performance: number;\n seo: number;\n accessibility: number;\n bestPractices: number;\n}\n\nexport interface SpeedComparisonData {\n platform: string;\n platformLabel: string;\n benchmarks: Scores;\n actual: Scores;\n}\n\ninterface SpeedComparisonSectionProps {\n data: SpeedComparisonData;\n}\n\nconst CATEGORIES: Array<{ key: keyof Scores; label: string; why: string }> = [\n { key: 'performance', label: 'Performance', why: 'Faster sites convert better: every 100ms of improvement increases conversions by up to 8%.' },\n { key: 'seo', label: 'SEO', why: 'Higher SEO scores mean better search rankings, more organic traffic, and lower customer acquisition costs.' },\n { key: 'accessibility', label: 'Accessibility', why: 'Accessible sites reach 15-20% more users and reduce legal liability.' },\n { key: 'bestPractices', label: 'Best Practices', why: 'Modern security headers, HTTPS, and optimized assets build trust and protect users.' },\n];\n\nfunction getScoreColor(score: number): string {\n if (score >= 90) return '#10b981';\n if (score >= 50) return '#f59e0b';\n return '#ef4444';\n}\n\n/** Circular score gauge */\nfunction ScoreRing({ score, size = 72 }: { score: number; size?: number }) {\n const strokeWidth = 5;\n const radius = (size - strokeWidth) / 2;\n const circumference = 2 * Math.PI * radius;\n const progress = (score / 100) * circumference;\n const color = getScoreColor(score);\n\n return (\n <div className=\"relative\" style={{ width: size, height: size }}>\n <svg width={size} height={size} className=\"transform -rotate-90\">\n <circle\n cx={size / 2}\n cy={size / 2}\n r={radius}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={strokeWidth}\n style={{ color: 'color-mix(in srgb, var(--sk-text-tertiary, #71717a) 20%, transparent)' }}\n />\n <circle\n cx={size / 2}\n cy={size / 2}\n r={radius}\n fill=\"none\"\n stroke={color}\n strokeWidth={strokeWidth}\n strokeDasharray={`${progress} ${circumference - progress}`}\n strokeLinecap=\"round\"\n />\n </svg>\n <span\n className=\"absolute inset-0 flex items-center justify-center text-lg font-bold\"\n style={{ color }}\n >\n {score}\n </span>\n </div>\n );\n}\n\nexport default function SpeedComparisonSection({ data }: SpeedComparisonSectionProps) {\n const { platformLabel, benchmarks, actual } = data;\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-5xl mx-auto px-6\">\n <ScrollReveal y={30}>\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 Why This Matters\n </h2>\n <p\n className=\"text-lg mb-4 max-w-3xl\"\n style={{ color: 'var(--sk-text-secondary, #a1a1aa)' }}\n >\n Lighthouse measures real-world site quality across performance, SEO, accessibility, and best practices.\n These scores directly impact search rankings, conversion rates, and user experience.\n </p>\n <p\n className=\"text-base mb-12 max-w-3xl\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n Here's how this Next.js build compares to the average {platformLabel} site.\n </p>\n </ScrollReveal>\n\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n {CATEGORIES.map((cat, ci) => {\n const ours = actual[cat.key];\n const theirs = benchmarks[cat.key];\n const diff = ours - theirs;\n\n return (\n <ScrollReveal key={cat.key} y={20} delay={ci * 0.1}>\n <GlassCard padding=\"lg\" hover={false} className=\"h-full\">\n <div className=\"flex items-start gap-5\">\n {/* Score rings side by side */}\n <div className=\"flex flex-col items-center gap-3 shrink-0\">\n <ScoreRing score={ours} />\n <span\n className=\"text-[10px] font-medium uppercase tracking-wider\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n Next.js\n </span>\n </div>\n <div className=\"flex flex-col items-center gap-3 shrink-0\">\n <ScoreRing score={theirs} />\n <span\n className=\"text-[10px] font-medium uppercase tracking-wider\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n {platformLabel}\n </span>\n </div>\n\n {/* Details */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 mb-2\">\n <h3\n className=\"text-base font-semibold\"\n style={{ color: 'var(--sk-text-primary, #ffffff)' }}\n >\n {cat.label}\n </h3>\n {diff > 0 && (\n <span\n className=\"text-xs font-bold px-2 py-0.5 rounded-full\"\n style={{\n background: 'color-mix(in srgb, #10b981 15%, transparent)',\n color: '#10b981',\n }}\n >\n +{diff} pts\n </span>\n )}\n </div>\n <p\n className=\"text-sm leading-relaxed\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n {cat.why}\n </p>\n </div>\n </div>\n </GlassCard>\n </ScrollReveal>\n );\n })}\n </div>\n </div>\n </section>\n );\n}\n"]}
|
|
@@ -0,0 +1,233 @@
|
|
|
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);
|
|
31
|
+
|
|
32
|
+
// src/portfolio/components/sections/StrategySection.tsx
|
|
33
|
+
var StrategySection_exports = {};
|
|
34
|
+
__export(StrategySection_exports, {
|
|
35
|
+
default: () => StrategySection
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(StrategySection_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");
|
|
42
|
+
function StrategySection({ data }) {
|
|
43
|
+
const timelineRef = (0, import_react.useRef)(null);
|
|
44
|
+
const sectionRef = (0, import_react.useRef)(null);
|
|
45
|
+
(0, import_react.useEffect)(() => {
|
|
46
|
+
const line = timelineRef.current;
|
|
47
|
+
const section = sectionRef.current;
|
|
48
|
+
if (!line || !section) return;
|
|
49
|
+
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
50
|
+
if (prefersReducedMotion) return;
|
|
51
|
+
const progressAt = () => {
|
|
52
|
+
const rect = section.getBoundingClientRect();
|
|
53
|
+
const vh = window.innerHeight;
|
|
54
|
+
const scrolled = vh * 0.6 - rect.top;
|
|
55
|
+
const range = Math.max(rect.height - vh * 0.2, 1);
|
|
56
|
+
return Math.min(1, Math.max(0, scrolled / range));
|
|
57
|
+
};
|
|
58
|
+
line.style.transformOrigin = "top center";
|
|
59
|
+
line.style.willChange = "transform";
|
|
60
|
+
let current = progressAt();
|
|
61
|
+
line.style.transform = `scaleY(${current})`;
|
|
62
|
+
let raf = 0;
|
|
63
|
+
let last = 0;
|
|
64
|
+
const step = (now) => {
|
|
65
|
+
raf = 0;
|
|
66
|
+
const dt = last ? Math.min((now - last) / 1e3, 0.1) : 1 / 60;
|
|
67
|
+
last = now;
|
|
68
|
+
const target = progressAt();
|
|
69
|
+
current += (target - current) * Math.min(1, dt * 3);
|
|
70
|
+
if (Math.abs(target - current) < 1e-3) current = target;
|
|
71
|
+
line.style.transform = `scaleY(${current})`;
|
|
72
|
+
if (current !== target) raf = requestAnimationFrame(step);
|
|
73
|
+
};
|
|
74
|
+
const onScroll = () => {
|
|
75
|
+
if (!raf) {
|
|
76
|
+
last = 0;
|
|
77
|
+
raf = requestAnimationFrame(step);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const io = new IntersectionObserver(([entry]) => {
|
|
81
|
+
if (entry.isIntersecting) {
|
|
82
|
+
window.addEventListener("scroll", onScroll, { passive: true });
|
|
83
|
+
window.addEventListener("resize", onScroll);
|
|
84
|
+
onScroll();
|
|
85
|
+
} else {
|
|
86
|
+
window.removeEventListener("scroll", onScroll);
|
|
87
|
+
window.removeEventListener("resize", onScroll);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
io.observe(section);
|
|
91
|
+
return () => {
|
|
92
|
+
io.disconnect();
|
|
93
|
+
window.removeEventListener("scroll", onScroll);
|
|
94
|
+
window.removeEventListener("resize", onScroll);
|
|
95
|
+
cancelAnimationFrame(raf);
|
|
96
|
+
line.style.transformOrigin = "";
|
|
97
|
+
line.style.willChange = "";
|
|
98
|
+
line.style.transform = "";
|
|
99
|
+
};
|
|
100
|
+
}, [data.phases.length]);
|
|
101
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
102
|
+
"section",
|
|
103
|
+
{
|
|
104
|
+
className: "w-full py-20 md:py-28",
|
|
105
|
+
style: { background: "var(--sk-bg, #0a0a0a)" },
|
|
106
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "max-w-5xl mx-auto px-6", children: [
|
|
107
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ScrollReveal.default, { y: 30, children: [
|
|
108
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
109
|
+
"h2",
|
|
110
|
+
{
|
|
111
|
+
className: "text-3xl md:text-4xl font-bold mb-4",
|
|
112
|
+
style: {
|
|
113
|
+
color: "var(--sk-text-primary, #ffffff)",
|
|
114
|
+
fontFamily: "var(--sk-font-heading, inherit)"
|
|
115
|
+
},
|
|
116
|
+
children: "Our Strategy"
|
|
117
|
+
}
|
|
118
|
+
),
|
|
119
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
120
|
+
"p",
|
|
121
|
+
{
|
|
122
|
+
className: "text-lg mb-16 max-w-2xl",
|
|
123
|
+
style: { color: "var(--sk-text-secondary, #a1a1aa)" },
|
|
124
|
+
children: "A phased approach to delivering measurable results."
|
|
125
|
+
}
|
|
126
|
+
)
|
|
127
|
+
] }),
|
|
128
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ref: sectionRef, className: "relative", children: [
|
|
129
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
130
|
+
"div",
|
|
131
|
+
{
|
|
132
|
+
ref: timelineRef,
|
|
133
|
+
className: "absolute top-0 bottom-0 hidden md:block pointer-events-none w-12 md:w-16",
|
|
134
|
+
style: { left: 0 },
|
|
135
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
136
|
+
"div",
|
|
137
|
+
{
|
|
138
|
+
className: "absolute top-0 bottom-0",
|
|
139
|
+
style: {
|
|
140
|
+
left: "50%",
|
|
141
|
+
transform: "translateX(-50%)",
|
|
142
|
+
width: "2px",
|
|
143
|
+
background: "var(--sk-primary, #6366f1)",
|
|
144
|
+
opacity: 0.3
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
),
|
|
150
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-col gap-12", children: data.phases.map((phase, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ScrollReveal.default, { y: 40, delay: index * 0.15, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex gap-6 md:gap-8", children: [
|
|
151
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-col items-center shrink-0 w-12 md:w-16", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
152
|
+
"div",
|
|
153
|
+
{
|
|
154
|
+
className: "flex items-center justify-center w-12 h-12 md:w-16 md:h-16 rounded-full text-lg md:text-xl font-bold z-10",
|
|
155
|
+
style: {
|
|
156
|
+
background: "var(--sk-bg, #0a0a0a)",
|
|
157
|
+
border: "3px solid var(--sk-primary, #6366f1)",
|
|
158
|
+
color: "var(--sk-primary, #6366f1)",
|
|
159
|
+
boxShadow: "0 0 20px color-mix(in srgb, var(--sk-primary, #6366f1) 30%, transparent)"
|
|
160
|
+
},
|
|
161
|
+
children: phase.number
|
|
162
|
+
}
|
|
163
|
+
) }),
|
|
164
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_GlassCard.default, { padding: "lg", hover: false, className: "flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-3", children: [
|
|
165
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-3 flex-wrap", children: [
|
|
166
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
167
|
+
"h3",
|
|
168
|
+
{
|
|
169
|
+
className: "text-xl font-semibold",
|
|
170
|
+
style: { color: "var(--sk-text-primary, #ffffff)" },
|
|
171
|
+
children: phase.title
|
|
172
|
+
}
|
|
173
|
+
),
|
|
174
|
+
phase.timeline && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
175
|
+
"span",
|
|
176
|
+
{
|
|
177
|
+
className: "px-3 py-0.5 rounded-full text-xs font-medium",
|
|
178
|
+
style: {
|
|
179
|
+
background: "color-mix(in srgb, var(--sk-primary, #6366f1) 12%, transparent)",
|
|
180
|
+
color: "var(--sk-primary, #6366f1)",
|
|
181
|
+
border: "1px solid color-mix(in srgb, var(--sk-primary, #6366f1) 20%, transparent)"
|
|
182
|
+
},
|
|
183
|
+
children: phase.timeline
|
|
184
|
+
}
|
|
185
|
+
)
|
|
186
|
+
] }),
|
|
187
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
188
|
+
"p",
|
|
189
|
+
{
|
|
190
|
+
className: "text-base leading-relaxed",
|
|
191
|
+
style: { color: "var(--sk-text-tertiary, #71717a)" },
|
|
192
|
+
children: phase.description
|
|
193
|
+
}
|
|
194
|
+
),
|
|
195
|
+
phase.deliverables && phase.deliverables.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "flex flex-col gap-2 mt-2", children: phase.deliverables.map((deliverable, di) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: "flex items-start gap-2", children: [
|
|
196
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
197
|
+
"svg",
|
|
198
|
+
{
|
|
199
|
+
width: "18",
|
|
200
|
+
height: "18",
|
|
201
|
+
viewBox: "0 0 18 18",
|
|
202
|
+
fill: "none",
|
|
203
|
+
className: "shrink-0 mt-0.5",
|
|
204
|
+
style: { color: "#10b981" },
|
|
205
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
206
|
+
"path",
|
|
207
|
+
{
|
|
208
|
+
d: "M15 4.5L6.75 12.75 3 9",
|
|
209
|
+
stroke: "currentColor",
|
|
210
|
+
strokeWidth: "2",
|
|
211
|
+
strokeLinecap: "round",
|
|
212
|
+
strokeLinejoin: "round"
|
|
213
|
+
}
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
),
|
|
217
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
218
|
+
"span",
|
|
219
|
+
{
|
|
220
|
+
className: "text-sm",
|
|
221
|
+
style: { color: "var(--sk-text-secondary, #a1a1aa)" },
|
|
222
|
+
children: deliverable
|
|
223
|
+
}
|
|
224
|
+
)
|
|
225
|
+
] }, di)) })
|
|
226
|
+
] }) })
|
|
227
|
+
] }) }, index)) })
|
|
228
|
+
] })
|
|
229
|
+
] })
|
|
230
|
+
}
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=StrategySection.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/portfolio/components/sections/StrategySection.tsx"],"sourcesContent":["'use client';\n\nimport React, { useRef, useEffect } from 'react';\nimport type { PortfolioStrategyData } from '../../../types';\nimport ScrollReveal from '@sonordev/agency-site-kit/portfolio/primitives/ScrollReveal';\nimport GlassCard from '@sonordev/agency-site-kit/portfolio/primitives/GlassCard';\n\ninterface StrategySectionProps {\n data: PortfolioStrategyData;\n}\n\nexport default function StrategySection({ data }: StrategySectionProps) {\n const timelineRef = useRef<HTMLDivElement>(null);\n const sectionRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const line = timelineRef.current;\n const section = sectionRef.current;\n if (!line || !section) return;\n\n const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n if (prefersReducedMotion) return;\n\n // Scroll-scrubbed timeline line draw via scaleY: progress maps the range\n // \"section top at 60% of the viewport\" → \"section bottom at 40%\", with a\n // time-based catch-up (~1s to converge) matching the old scrubbed feel.\n const progressAt = () => {\n const rect = section.getBoundingClientRect();\n const vh = window.innerHeight;\n const scrolled = vh * 0.6 - rect.top;\n const range = Math.max(rect.height - vh * 0.2, 1);\n return Math.min(1, Math.max(0, scrolled / range));\n };\n\n line.style.transformOrigin = 'top center';\n line.style.willChange = 'transform';\n\n // Snap to the progress for the current scroll position, so content\n // already in the viewport at hydration is never re-hidden.\n let current = progressAt();\n line.style.transform = `scaleY(${current})`;\n\n let raf = 0;\n let last = 0;\n\n const step = (now: number) => {\n raf = 0;\n const dt = last ? Math.min((now - last) / 1000, 0.1) : 1 / 60;\n last = now;\n const target = progressAt();\n current += (target - current) * Math.min(1, dt * 3);\n if (Math.abs(target - current) < 0.001) current = target;\n line.style.transform = `scaleY(${current})`;\n if (current !== target) raf = requestAnimationFrame(step);\n };\n\n const onScroll = () => {\n if (!raf) {\n last = 0;\n raf = requestAnimationFrame(step);\n }\n };\n\n // Only do per-scroll work while the section is near the viewport.\n const io = new IntersectionObserver(([entry]) => {\n if (entry.isIntersecting) {\n window.addEventListener('scroll', onScroll, { passive: true });\n window.addEventListener('resize', onScroll);\n onScroll();\n } else {\n window.removeEventListener('scroll', onScroll);\n window.removeEventListener('resize', onScroll);\n }\n });\n io.observe(section);\n\n return () => {\n io.disconnect();\n window.removeEventListener('scroll', onScroll);\n window.removeEventListener('resize', onScroll);\n cancelAnimationFrame(raf);\n line.style.transformOrigin = '';\n line.style.willChange = '';\n line.style.transform = '';\n };\n }, [data.phases.length]);\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-5xl mx-auto px-6\">\n <ScrollReveal y={30}>\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 Our Strategy\n </h2>\n <p\n className=\"text-lg mb-16 max-w-2xl\"\n style={{ color: 'var(--sk-text-secondary, #a1a1aa)' }}\n >\n A phased approach to delivering measurable results.\n </p>\n </ScrollReveal>\n\n <div ref={sectionRef} className=\"relative\">\n {/* Vertical timeline line — uses the circle column width to find center */}\n <div\n ref={timelineRef}\n className=\"absolute top-0 bottom-0 hidden md:block pointer-events-none w-12 md:w-16\"\n style={{ left: 0 }}\n >\n <div\n className=\"absolute top-0 bottom-0\"\n style={{\n left: '50%',\n transform: 'translateX(-50%)',\n width: '2px',\n background: 'var(--sk-primary, #6366f1)',\n opacity: 0.3,\n }}\n />\n </div>\n\n <div className=\"flex flex-col gap-12\">\n {data.phases.map((phase, index) => (\n <ScrollReveal key={index} y={40} delay={index * 0.15}>\n <div className=\"flex gap-6 md:gap-8\">\n {/* Number circle — fixed-width column so line can center on it */}\n <div className=\"flex flex-col items-center shrink-0 w-12 md:w-16\">\n <div\n className=\"flex items-center justify-center w-12 h-12 md:w-16 md:h-16 rounded-full text-lg md:text-xl font-bold z-10\"\n style={{\n background: 'var(--sk-bg, #0a0a0a)',\n border: '3px solid var(--sk-primary, #6366f1)',\n color: 'var(--sk-primary, #6366f1)',\n boxShadow: '0 0 20px color-mix(in srgb, var(--sk-primary, #6366f1) 30%, transparent)',\n }}\n >\n {phase.number}\n </div>\n </div>\n\n {/* Phase content */}\n <GlassCard padding=\"lg\" hover={false} className=\"flex-1\">\n <div className=\"flex flex-col gap-3\">\n <div className=\"flex items-center gap-3 flex-wrap\">\n <h3\n className=\"text-xl font-semibold\"\n style={{ color: 'var(--sk-text-primary, #ffffff)' }}\n >\n {phase.title}\n </h3>\n {phase.timeline && (\n <span\n className=\"px-3 py-0.5 rounded-full text-xs font-medium\"\n style={{\n background: 'color-mix(in srgb, var(--sk-primary, #6366f1) 12%, transparent)',\n color: 'var(--sk-primary, #6366f1)',\n border: '1px solid color-mix(in srgb, var(--sk-primary, #6366f1) 20%, transparent)',\n }}\n >\n {phase.timeline}\n </span>\n )}\n </div>\n\n <p\n className=\"text-base leading-relaxed\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n {phase.description}\n </p>\n\n {/* Deliverables */}\n {phase.deliverables && phase.deliverables.length > 0 && (\n <ul className=\"flex flex-col gap-2 mt-2\">\n {phase.deliverables.map((deliverable, di) => (\n <li key={di} className=\"flex items-start gap-2\">\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 18 18\"\n fill=\"none\"\n className=\"shrink-0 mt-0.5\"\n style={{ color: '#10b981' }}\n >\n <path\n d=\"M15 4.5L6.75 12.75 3 9\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n <span\n className=\"text-sm\"\n style={{ color: 'var(--sk-text-secondary, #a1a1aa)' }}\n >\n {deliverable}\n </span>\n </li>\n ))}\n </ul>\n )}\n </div>\n </GlassCard>\n </div>\n </ScrollReveal>\n ))}\n </div>\n </div>\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 { f as PortfolioStrategyData } from '../../types-D0nb6KAx.cjs';
|
|
3
|
+
|
|
4
|
+
interface StrategySectionProps {
|
|
5
|
+
data: PortfolioStrategyData;
|
|
6
|
+
}
|
|
7
|
+
declare function StrategySection({ data }: StrategySectionProps): React.JSX.Element;
|
|
8
|
+
|
|
9
|
+
export { StrategySection as default };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { f as PortfolioStrategyData } from '../../types-D0nb6KAx.js';
|
|
3
|
+
|
|
4
|
+
interface StrategySectionProps {
|
|
5
|
+
data: PortfolioStrategyData;
|
|
6
|
+
}
|
|
7
|
+
declare function StrategySection({ data }: StrategySectionProps): React.JSX.Element;
|
|
8
|
+
|
|
9
|
+
export { StrategySection as default };
|
|
@@ -1,35 +1,69 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
|
|
3
|
-
import { ScrollReveal } from './chunk-7CFFAKDM.js';
|
|
4
|
-
import { useRef, useEffect } from 'react';
|
|
5
|
-
import gsap from 'gsap';
|
|
6
|
-
import { ScrollTrigger } from 'gsap/ScrollTrigger';
|
|
7
|
-
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
"use client";
|
|
8
3
|
|
|
4
|
+
// src/portfolio/components/sections/StrategySection.tsx
|
|
5
|
+
import { useRef, useEffect } 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 { jsx, jsxs } from "react/jsx-runtime";
|
|
9
9
|
function StrategySection({ data }) {
|
|
10
10
|
const timelineRef = useRef(null);
|
|
11
11
|
const sectionRef = useRef(null);
|
|
12
12
|
useEffect(() => {
|
|
13
|
-
|
|
13
|
+
const line = timelineRef.current;
|
|
14
|
+
const section = sectionRef.current;
|
|
15
|
+
if (!line || !section) return;
|
|
14
16
|
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
15
17
|
if (prefersReducedMotion) return;
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
18
|
+
const progressAt = () => {
|
|
19
|
+
const rect = section.getBoundingClientRect();
|
|
20
|
+
const vh = window.innerHeight;
|
|
21
|
+
const scrolled = vh * 0.6 - rect.top;
|
|
22
|
+
const range = Math.max(rect.height - vh * 0.2, 1);
|
|
23
|
+
return Math.min(1, Math.max(0, scrolled / range));
|
|
24
|
+
};
|
|
25
|
+
line.style.transformOrigin = "top center";
|
|
26
|
+
line.style.willChange = "transform";
|
|
27
|
+
let current = progressAt();
|
|
28
|
+
line.style.transform = `scaleY(${current})`;
|
|
29
|
+
let raf = 0;
|
|
30
|
+
let last = 0;
|
|
31
|
+
const step = (now) => {
|
|
32
|
+
raf = 0;
|
|
33
|
+
const dt = last ? Math.min((now - last) / 1e3, 0.1) : 1 / 60;
|
|
34
|
+
last = now;
|
|
35
|
+
const target = progressAt();
|
|
36
|
+
current += (target - current) * Math.min(1, dt * 3);
|
|
37
|
+
if (Math.abs(target - current) < 1e-3) current = target;
|
|
38
|
+
line.style.transform = `scaleY(${current})`;
|
|
39
|
+
if (current !== target) raf = requestAnimationFrame(step);
|
|
40
|
+
};
|
|
41
|
+
const onScroll = () => {
|
|
42
|
+
if (!raf) {
|
|
43
|
+
last = 0;
|
|
44
|
+
raf = requestAnimationFrame(step);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const io = new IntersectionObserver(([entry]) => {
|
|
48
|
+
if (entry.isIntersecting) {
|
|
49
|
+
window.addEventListener("scroll", onScroll, { passive: true });
|
|
50
|
+
window.addEventListener("resize", onScroll);
|
|
51
|
+
onScroll();
|
|
52
|
+
} else {
|
|
53
|
+
window.removeEventListener("scroll", onScroll);
|
|
54
|
+
window.removeEventListener("resize", onScroll);
|
|
30
55
|
}
|
|
31
56
|
});
|
|
32
|
-
|
|
57
|
+
io.observe(section);
|
|
58
|
+
return () => {
|
|
59
|
+
io.disconnect();
|
|
60
|
+
window.removeEventListener("scroll", onScroll);
|
|
61
|
+
window.removeEventListener("resize", onScroll);
|
|
62
|
+
cancelAnimationFrame(raf);
|
|
63
|
+
line.style.transformOrigin = "";
|
|
64
|
+
line.style.willChange = "";
|
|
65
|
+
line.style.transform = "";
|
|
66
|
+
};
|
|
33
67
|
}, [data.phases.length]);
|
|
34
68
|
return /* @__PURE__ */ jsx(
|
|
35
69
|
"section",
|
|
@@ -163,7 +197,7 @@ function StrategySection({ data }) {
|
|
|
163
197
|
}
|
|
164
198
|
);
|
|
165
199
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
//# sourceMappingURL=StrategySection
|
|
200
|
+
export {
|
|
201
|
+
StrategySection as default
|
|
202
|
+
};
|
|
203
|
+
//# sourceMappingURL=StrategySection.js.map
|