@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.
Files changed (374) hide show
  1. package/README.md +302 -0
  2. package/bin/setup.mjs +79 -0
  3. package/dist/{chunk-RXBK2EOE.js → chunk-4IES23GV.js} +3 -3
  4. package/dist/{chunk-RXBK2EOE.js.map → chunk-4IES23GV.js.map} +1 -1
  5. package/dist/{chunk-WNR4KNG4.cjs → chunk-5MEZU3OG.cjs} +4 -4
  6. package/dist/{chunk-WNR4KNG4.cjs.map → chunk-5MEZU3OG.cjs.map} +1 -1
  7. package/dist/chunk-7D4H36UF.js +13 -0
  8. package/dist/chunk-7D4H36UF.js.map +1 -0
  9. package/dist/chunk-7ZHRMWJU.cjs +306 -0
  10. package/dist/chunk-7ZHRMWJU.cjs.map +1 -0
  11. package/dist/chunk-CVT7I5BQ.js +71 -0
  12. package/dist/chunk-CVT7I5BQ.js.map +1 -0
  13. package/dist/chunk-HQGAX2LI.cjs +8 -0
  14. package/dist/chunk-HQGAX2LI.cjs.map +1 -0
  15. package/dist/chunk-K2BGTDSN.js +45 -0
  16. package/dist/chunk-K2BGTDSN.js.map +1 -0
  17. package/dist/chunk-KXLROAO5.js +291 -0
  18. package/dist/chunk-KXLROAO5.js.map +1 -0
  19. package/dist/chunk-L4EOQVRJ.js +6 -0
  20. package/dist/chunk-L4EOQVRJ.js.map +1 -0
  21. package/dist/chunk-NI4FVCLS.cjs +32 -0
  22. package/dist/chunk-NI4FVCLS.cjs.map +1 -0
  23. package/dist/chunk-NLGUPJZA.js +507 -0
  24. package/dist/chunk-NLGUPJZA.js.map +1 -0
  25. package/dist/chunk-QDXZ27R7.js +33 -0
  26. package/dist/chunk-QDXZ27R7.js.map +1 -0
  27. package/dist/chunk-QGSW43TM.cjs +538 -0
  28. package/dist/chunk-QGSW43TM.cjs.map +1 -0
  29. package/dist/{chunk-TVFXN6W6.js → chunk-QL6KVIFR.js} +8 -4
  30. package/dist/chunk-QL6KVIFR.js.map +1 -0
  31. package/dist/chunk-RWQ675N6.js +165 -0
  32. package/dist/chunk-RWQ675N6.js.map +1 -0
  33. package/dist/chunk-UXUU7FVT.cjs +171 -0
  34. package/dist/chunk-UXUU7FVT.cjs.map +1 -0
  35. package/dist/chunk-XJ434N7I.js +30 -0
  36. package/dist/chunk-XJ434N7I.js.map +1 -0
  37. package/dist/{chunk-EE75WRCM.cjs → chunk-XOWSXZYW.cjs} +8 -4
  38. package/dist/chunk-XOWSXZYW.cjs.map +1 -0
  39. package/dist/chunk-ZBPF7TLZ.cjs +16 -0
  40. package/dist/chunk-ZBPF7TLZ.cjs.map +1 -0
  41. package/dist/chunk-ZINKVJQU.js +67 -0
  42. package/dist/chunk-ZINKVJQU.js.map +1 -0
  43. package/dist/index.cjs +53 -30
  44. package/dist/index.cjs.map +1 -1
  45. package/dist/index.d.cts +17 -9
  46. package/dist/index.d.ts +17 -9
  47. package/dist/index.js +8 -9
  48. package/dist/index.js.map +1 -1
  49. package/dist/layout/index.cjs +3 -3
  50. package/dist/layout/index.d.cts +1 -1
  51. package/dist/layout/index.d.ts +1 -1
  52. package/dist/layout/index.js +2 -2
  53. package/dist/portfolio/client.cjs +376 -12
  54. package/dist/portfolio/client.cjs.map +1 -1
  55. package/dist/portfolio/client.d.cts +27 -85
  56. package/dist/portfolio/client.d.ts +27 -85
  57. package/dist/portfolio/client.js +182 -4
  58. package/dist/portfolio/client.js.map +1 -1
  59. package/dist/portfolio/components/PortfolioAnalytics.cjs +87 -0
  60. package/dist/portfolio/components/PortfolioAnalytics.cjs.map +1 -0
  61. package/dist/portfolio/components/PortfolioAnalytics.d.cts +5 -0
  62. package/dist/portfolio/components/PortfolioAnalytics.d.ts +5 -0
  63. package/dist/portfolio/components/PortfolioAnalytics.js +9 -0
  64. package/dist/portfolio/components/PortfolioAnalytics.js.map +1 -0
  65. package/dist/portfolio/components/PortfolioErrorFallback.cjs +65 -0
  66. package/dist/portfolio/components/PortfolioErrorFallback.cjs.map +1 -0
  67. package/dist/portfolio/components/PortfolioErrorFallback.d.cts +22 -0
  68. package/dist/portfolio/components/PortfolioErrorFallback.d.ts +22 -0
  69. package/dist/portfolio/components/PortfolioErrorFallback.js +9 -0
  70. package/dist/portfolio/components/PortfolioErrorFallback.js.map +1 -0
  71. package/dist/portfolio/components/PortfolioLeadCTA.cjs +91 -0
  72. package/dist/portfolio/components/PortfolioLeadCTA.cjs.map +1 -0
  73. package/dist/portfolio/components/PortfolioLeadCTA.d.cts +34 -0
  74. package/dist/portfolio/components/PortfolioLeadCTA.d.ts +34 -0
  75. package/dist/portfolio/components/PortfolioLeadCTA.js +9 -0
  76. package/dist/portfolio/components/PortfolioLeadCTA.js.map +1 -0
  77. package/dist/portfolio/index.cjs +43 -19
  78. package/dist/portfolio/index.d.cts +210 -7
  79. package/dist/portfolio/index.d.ts +210 -7
  80. package/dist/portfolio/index.js +7 -7
  81. package/dist/portfolio/primitives/AnimatedCounter.cjs +88 -0
  82. package/dist/portfolio/primitives/AnimatedCounter.cjs.map +1 -0
  83. package/dist/portfolio/primitives/AnimatedCounter.d.cts +22 -0
  84. package/dist/portfolio/primitives/AnimatedCounter.d.ts +22 -0
  85. package/dist/portfolio/primitives/AnimatedCounter.js +68 -0
  86. package/dist/portfolio/primitives/AnimatedCounter.js.map +1 -0
  87. package/dist/portfolio/primitives/AnnotatedImage.cjs +320 -0
  88. package/dist/portfolio/primitives/AnnotatedImage.cjs.map +1 -0
  89. package/dist/portfolio/primitives/AnnotatedImage.d.cts +18 -0
  90. package/dist/portfolio/primitives/AnnotatedImage.d.ts +18 -0
  91. package/dist/portfolio/primitives/AnnotatedImage.js +264 -0
  92. package/dist/portfolio/primitives/AnnotatedImage.js.map +1 -0
  93. package/dist/portfolio/primitives/BeforeAfterSlider.cjs +348 -0
  94. package/dist/portfolio/primitives/BeforeAfterSlider.cjs.map +1 -0
  95. package/dist/portfolio/primitives/BeforeAfterSlider.d.cts +13 -0
  96. package/dist/portfolio/primitives/BeforeAfterSlider.d.ts +13 -0
  97. package/dist/portfolio/primitives/BeforeAfterSlider.js +292 -0
  98. package/dist/portfolio/primitives/BeforeAfterSlider.js.map +1 -0
  99. package/dist/portfolio/primitives/DeviceTrifolio.cjs +298 -0
  100. package/dist/portfolio/primitives/DeviceTrifolio.cjs.map +1 -0
  101. package/dist/portfolio/primitives/DeviceTrifolio.d.cts +14 -0
  102. package/dist/portfolio/primitives/DeviceTrifolio.d.ts +14 -0
  103. package/dist/portfolio/primitives/DeviceTrifolio.js +242 -0
  104. package/dist/portfolio/primitives/DeviceTrifolio.js.map +1 -0
  105. package/dist/portfolio/primitives/FrequencyBarSkeleton.cjs +88 -0
  106. package/dist/portfolio/primitives/FrequencyBarSkeleton.cjs.map +1 -0
  107. package/dist/portfolio/primitives/FrequencyBarSkeleton.d.cts +10 -0
  108. package/dist/portfolio/primitives/FrequencyBarSkeleton.d.ts +10 -0
  109. package/dist/portfolio/primitives/FrequencyBarSkeleton.js +68 -0
  110. package/dist/portfolio/primitives/FrequencyBarSkeleton.js.map +1 -0
  111. package/dist/portfolio/primitives/GlassCard.cjs +45 -0
  112. package/dist/portfolio/primitives/GlassCard.cjs.map +1 -0
  113. package/dist/portfolio/primitives/GlassCard.d.cts +11 -0
  114. package/dist/portfolio/primitives/GlassCard.d.ts +11 -0
  115. package/dist/portfolio/primitives/GlassCard.js +43 -0
  116. package/dist/portfolio/primitives/GlassCard.js.map +1 -0
  117. package/dist/portfolio/primitives/MetricBadge.cjs +74 -0
  118. package/dist/portfolio/primitives/MetricBadge.cjs.map +1 -0
  119. package/dist/portfolio/primitives/MetricBadge.d.cts +9 -0
  120. package/dist/portfolio/primitives/MetricBadge.d.ts +9 -0
  121. package/dist/portfolio/primitives/MetricBadge.js +54 -0
  122. package/dist/portfolio/primitives/MetricBadge.js.map +1 -0
  123. package/dist/portfolio/primitives/SVGChart.cjs +316 -0
  124. package/dist/portfolio/primitives/SVGChart.cjs.map +1 -0
  125. package/dist/portfolio/primitives/SVGChart.d.cts +18 -0
  126. package/dist/portfolio/primitives/SVGChart.d.ts +18 -0
  127. package/dist/portfolio/primitives/SVGChart.js +296 -0
  128. package/dist/portfolio/primitives/SVGChart.js.map +1 -0
  129. package/dist/portfolio/primitives/ScrollReveal.cjs +97 -0
  130. package/dist/portfolio/primitives/ScrollReveal.cjs.map +1 -0
  131. package/dist/portfolio/primitives/ScrollReveal.d.cts +27 -0
  132. package/dist/portfolio/primitives/ScrollReveal.d.ts +27 -0
  133. package/dist/portfolio/primitives/ScrollReveal.js +77 -0
  134. package/dist/portfolio/primitives/ScrollReveal.js.map +1 -0
  135. package/dist/portfolio/primitives/SplitHeadline.cjs +107 -0
  136. package/dist/portfolio/primitives/SplitHeadline.cjs.map +1 -0
  137. package/dist/portfolio/primitives/SplitHeadline.d.cts +24 -0
  138. package/dist/portfolio/primitives/SplitHeadline.d.ts +24 -0
  139. package/dist/portfolio/primitives/SplitHeadline.js +87 -0
  140. package/dist/portfolio/primitives/SplitHeadline.js.map +1 -0
  141. package/dist/portfolio/sections/BeforeAfterSection.cjs +271 -0
  142. package/dist/portfolio/sections/BeforeAfterSection.cjs.map +1 -0
  143. package/dist/portfolio/sections/BeforeAfterSection.d.cts +9 -0
  144. package/dist/portfolio/sections/BeforeAfterSection.d.ts +9 -0
  145. package/dist/{BeforeAfterSection-6BHFLY4Y.js → portfolio/sections/BeforeAfterSection.js} +66 -27
  146. package/dist/portfolio/sections/BeforeAfterSection.js.map +1 -0
  147. package/dist/portfolio/sections/CTASection.cjs +123 -0
  148. package/dist/portfolio/sections/CTASection.cjs.map +1 -0
  149. package/dist/portfolio/sections/CTASection.d.cts +9 -0
  150. package/dist/portfolio/sections/CTASection.d.ts +9 -0
  151. package/dist/portfolio/sections/CTASection.js +93 -0
  152. package/dist/portfolio/sections/CTASection.js.map +1 -0
  153. package/dist/{ChallengesSection-IZ3DHECS.cjs → portfolio/sections/ChallengesSection.cjs} +13 -7
  154. package/dist/portfolio/sections/ChallengesSection.cjs.map +1 -0
  155. package/dist/portfolio/sections/ChallengesSection.d.cts +9 -0
  156. package/dist/portfolio/sections/ChallengesSection.d.ts +9 -0
  157. package/dist/{ChallengesSection-GEQGVSJN.js → portfolio/sections/ChallengesSection.js} +6 -5
  158. package/dist/portfolio/sections/ChallengesSection.js.map +1 -0
  159. package/dist/portfolio/sections/ConversionFunnelSection.cjs +263 -0
  160. package/dist/portfolio/sections/ConversionFunnelSection.cjs.map +1 -0
  161. package/dist/portfolio/sections/ConversionFunnelSection.d.cts +9 -0
  162. package/dist/portfolio/sections/ConversionFunnelSection.d.ts +9 -0
  163. package/dist/{ConversionFunnelSection-D3GE4NKE.js → portfolio/sections/ConversionFunnelSection.js} +60 -56
  164. package/dist/portfolio/sections/ConversionFunnelSection.js.map +1 -0
  165. package/dist/{DesignSystemSection-KXIQXITF.cjs → portfolio/sections/DesignSystemSection.cjs} +13 -7
  166. package/dist/portfolio/sections/DesignSystemSection.cjs.map +1 -0
  167. package/dist/portfolio/sections/DesignSystemSection.d.cts +32 -0
  168. package/dist/portfolio/sections/DesignSystemSection.d.ts +32 -0
  169. package/dist/{DesignSystemSection-2R5BRBGO.js → portfolio/sections/DesignSystemSection.js} +5 -4
  170. package/dist/portfolio/sections/DesignSystemSection.js.map +1 -0
  171. package/dist/{DetailsSection-TTUZAPZZ.cjs → portfolio/sections/DetailsSection.cjs} +12 -6
  172. package/dist/portfolio/sections/DetailsSection.cjs.map +1 -0
  173. package/dist/portfolio/sections/DetailsSection.d.cts +9 -0
  174. package/dist/portfolio/sections/DetailsSection.d.ts +9 -0
  175. package/dist/{DetailsSection-A6PZQUQL.js → portfolio/sections/DetailsSection.js} +5 -4
  176. package/dist/portfolio/sections/DetailsSection.js.map +1 -0
  177. package/dist/portfolio/sections/FeatureSpotlightSection.cjs +267 -0
  178. package/dist/portfolio/sections/FeatureSpotlightSection.cjs.map +1 -0
  179. package/dist/portfolio/sections/FeatureSpotlightSection.d.cts +9 -0
  180. package/dist/portfolio/sections/FeatureSpotlightSection.d.ts +9 -0
  181. package/dist/{FeatureSpotlightSection-B7P3JGNL.js → portfolio/sections/FeatureSpotlightSection.js} +39 -33
  182. package/dist/portfolio/sections/FeatureSpotlightSection.js.map +1 -0
  183. package/dist/portfolio/sections/GallerySection.cjs +321 -0
  184. package/dist/portfolio/sections/GallerySection.cjs.map +1 -0
  185. package/dist/portfolio/sections/GallerySection.d.cts +9 -0
  186. package/dist/portfolio/sections/GallerySection.d.ts +9 -0
  187. package/dist/{GallerySection-VMKORC47.js → portfolio/sections/GallerySection.js} +65 -18
  188. package/dist/portfolio/sections/GallerySection.js.map +1 -0
  189. package/dist/portfolio/sections/HeroSection.cjs +180 -0
  190. package/dist/portfolio/sections/HeroSection.cjs.map +1 -0
  191. package/dist/portfolio/sections/HeroSection.d.cts +15 -0
  192. package/dist/portfolio/sections/HeroSection.d.ts +15 -0
  193. package/dist/portfolio/sections/HeroSection.js +171 -0
  194. package/dist/portfolio/sections/HeroSection.js.map +1 -0
  195. package/dist/{MetricsTimelineSection-4L6DUHJ5.cjs → portfolio/sections/MetricsTimelineSection.cjs} +102 -61
  196. package/dist/portfolio/sections/MetricsTimelineSection.cjs.map +1 -0
  197. package/dist/portfolio/sections/MetricsTimelineSection.d.cts +9 -0
  198. package/dist/portfolio/sections/MetricsTimelineSection.d.ts +9 -0
  199. package/dist/{MetricsTimelineSection-6BT5GNFV.js → portfolio/sections/MetricsTimelineSection.js} +45 -29
  200. package/dist/portfolio/sections/MetricsTimelineSection.js.map +1 -0
  201. package/dist/portfolio/sections/PerformanceSection.cjs +336 -0
  202. package/dist/portfolio/sections/PerformanceSection.cjs.map +1 -0
  203. package/dist/portfolio/sections/PerformanceSection.d.cts +22 -0
  204. package/dist/portfolio/sections/PerformanceSection.d.ts +22 -0
  205. package/dist/{PerformanceSection-MGCEIXDX.js → portfolio/sections/PerformanceSection.js} +59 -104
  206. package/dist/portfolio/sections/PerformanceSection.js.map +1 -0
  207. package/dist/{ResultsSection-XLGMMQKY.cjs → portfolio/sections/ResultsSection.cjs} +23 -10
  208. package/dist/portfolio/sections/ResultsSection.cjs.map +1 -0
  209. package/dist/portfolio/sections/ResultsSection.d.cts +13 -0
  210. package/dist/portfolio/sections/ResultsSection.d.ts +13 -0
  211. package/dist/{ResultsSection-DFUJ5U6M.js → portfolio/sections/ResultsSection.js} +14 -7
  212. package/dist/portfolio/sections/ResultsSection.js.map +1 -0
  213. package/dist/portfolio/sections/ServicesSection.cjs +129 -0
  214. package/dist/portfolio/sections/ServicesSection.cjs.map +1 -0
  215. package/dist/portfolio/sections/ServicesSection.d.cts +9 -0
  216. package/dist/portfolio/sections/ServicesSection.d.ts +9 -0
  217. package/dist/portfolio/sections/ServicesSection.js +122 -0
  218. package/dist/portfolio/sections/ServicesSection.js.map +1 -0
  219. package/dist/{SiteArchitectureSection-J7BPBERH.cjs → portfolio/sections/SiteArchitectureSection.cjs} +117 -93
  220. package/dist/portfolio/sections/SiteArchitectureSection.cjs.map +1 -0
  221. package/dist/portfolio/sections/SiteArchitectureSection.d.cts +21 -0
  222. package/dist/portfolio/sections/SiteArchitectureSection.d.ts +21 -0
  223. package/dist/{SiteArchitectureSection-TE22OAWV.js → portfolio/sections/SiteArchitectureSection.js} +47 -48
  224. package/dist/portfolio/sections/SiteArchitectureSection.js.map +1 -0
  225. package/dist/{SpeedComparisonSection-EZKFQVGW.cjs → portfolio/sections/SpeedComparisonSection.cjs} +13 -7
  226. package/dist/portfolio/sections/SpeedComparisonSection.cjs.map +1 -0
  227. package/dist/portfolio/sections/SpeedComparisonSection.d.cts +20 -0
  228. package/dist/portfolio/sections/SpeedComparisonSection.d.ts +20 -0
  229. package/dist/{SpeedComparisonSection-Y3K7OFZQ.js → portfolio/sections/SpeedComparisonSection.js} +6 -5
  230. package/dist/portfolio/sections/SpeedComparisonSection.js.map +1 -0
  231. package/dist/portfolio/sections/StrategySection.cjs +233 -0
  232. package/dist/portfolio/sections/StrategySection.cjs.map +1 -0
  233. package/dist/portfolio/sections/StrategySection.d.cts +9 -0
  234. package/dist/portfolio/sections/StrategySection.d.ts +9 -0
  235. package/dist/{StrategySection-DI5RSCJU.js → portfolio/sections/StrategySection.js} +60 -26
  236. package/dist/portfolio/sections/StrategySection.js.map +1 -0
  237. package/dist/portfolio/sections/TeamSection.cjs +162 -0
  238. package/dist/portfolio/sections/TeamSection.cjs.map +1 -0
  239. package/dist/portfolio/sections/TeamSection.d.cts +9 -0
  240. package/dist/portfolio/sections/TeamSection.d.ts +9 -0
  241. package/dist/portfolio/sections/TeamSection.js +106 -0
  242. package/dist/portfolio/sections/TeamSection.js.map +1 -0
  243. package/dist/portfolio/sections/TechStackSection.cjs +106 -0
  244. package/dist/portfolio/sections/TechStackSection.cjs.map +1 -0
  245. package/dist/portfolio/sections/TechStackSection.d.cts +9 -0
  246. package/dist/portfolio/sections/TechStackSection.d.ts +9 -0
  247. package/dist/portfolio/sections/TechStackSection.js +99 -0
  248. package/dist/portfolio/sections/TechStackSection.js.map +1 -0
  249. package/dist/{TestimonialSection-XPTFUQIN.cjs → portfolio/sections/TestimonialSection.cjs} +47 -28
  250. package/dist/portfolio/sections/TestimonialSection.cjs.map +1 -0
  251. package/dist/portfolio/sections/TestimonialSection.d.cts +9 -0
  252. package/dist/portfolio/sections/TestimonialSection.d.ts +9 -0
  253. package/dist/{TestimonialSection-6RGSMXQB.js → portfolio/sections/TestimonialSection.js} +40 -27
  254. package/dist/portfolio/sections/TestimonialSection.js.map +1 -0
  255. package/dist/portfolio/sections/VideoSection.cjs +181 -0
  256. package/dist/portfolio/sections/VideoSection.cjs.map +1 -0
  257. package/dist/portfolio/sections/VideoSection.d.cts +9 -0
  258. package/dist/portfolio/sections/VideoSection.d.ts +9 -0
  259. package/dist/{VideoSection-4A2HC6K6.js → portfolio/sections/VideoSection.js} +21 -13
  260. package/dist/portfolio/sections/VideoSection.js.map +1 -0
  261. package/dist/portfolio/server.cjs +56 -144
  262. package/dist/portfolio/server.cjs.map +1 -1
  263. package/dist/portfolio/server.d.cts +157 -7
  264. package/dist/portfolio/server.d.ts +157 -7
  265. package/dist/portfolio/server.js +3 -142
  266. package/dist/portfolio/server.js.map +1 -1
  267. package/dist/preview.cjs +56 -0
  268. package/dist/preview.cjs.map +1 -0
  269. package/dist/preview.d.cts +31 -0
  270. package/dist/preview.d.ts +31 -0
  271. package/dist/preview.js +54 -0
  272. package/dist/preview.js.map +1 -0
  273. package/dist/{types-DL4t_Cfa.d.ts → types-0tVPy4pU.d.cts} +7 -1
  274. package/dist/{types-DL4t_Cfa.d.cts → types-0tVPy4pU.d.ts} +7 -1
  275. package/dist/types-D0nb6KAx.d.cts +299 -0
  276. package/dist/types-D0nb6KAx.d.ts +299 -0
  277. package/package.json +38 -14
  278. package/templates/api-portfolio-preview.ts +6 -0
  279. package/templates/api-revalidate.ts +5 -0
  280. package/templates/work-category-page.tsx +40 -0
  281. package/templates/work-error.tsx +3 -0
  282. package/templates/work-loading.tsx +1 -0
  283. package/templates/work-page.tsx +37 -0
  284. package/templates/work-slug-loading.tsx +1 -0
  285. package/templates/work-slug-page.tsx +41 -0
  286. package/dist/BeforeAfterSection-6BHFLY4Y.js.map +0 -1
  287. package/dist/BeforeAfterSection-JTORBR3A.cjs +0 -181
  288. package/dist/BeforeAfterSection-JTORBR3A.cjs.map +0 -1
  289. package/dist/CTASection-4JKLXEUF.cjs +0 -111
  290. package/dist/CTASection-4JKLXEUF.cjs.map +0 -1
  291. package/dist/CTASection-BJA72XIL.js +0 -106
  292. package/dist/CTASection-BJA72XIL.js.map +0 -1
  293. package/dist/ChallengesSection-GEQGVSJN.js.map +0 -1
  294. package/dist/ChallengesSection-IZ3DHECS.cjs.map +0 -1
  295. package/dist/ConversionFunnelSection-AUUSJ5HQ.cjs +0 -209
  296. package/dist/ConversionFunnelSection-AUUSJ5HQ.cjs.map +0 -1
  297. package/dist/ConversionFunnelSection-D3GE4NKE.js.map +0 -1
  298. package/dist/DesignSystemSection-2R5BRBGO.js.map +0 -1
  299. package/dist/DesignSystemSection-KXIQXITF.cjs.map +0 -1
  300. package/dist/DetailsSection-A6PZQUQL.js.map +0 -1
  301. package/dist/DetailsSection-TTUZAPZZ.cjs.map +0 -1
  302. package/dist/FeatureSpotlightSection-B7P3JGNL.js.map +0 -1
  303. package/dist/FeatureSpotlightSection-WRHXS7TU.cjs +0 -210
  304. package/dist/FeatureSpotlightSection-WRHXS7TU.cjs.map +0 -1
  305. package/dist/GallerySection-VMKORC47.js.map +0 -1
  306. package/dist/GallerySection-WJ4PQDBI.cjs +0 -219
  307. package/dist/GallerySection-WJ4PQDBI.cjs.map +0 -1
  308. package/dist/MetricsTimelineSection-4L6DUHJ5.cjs.map +0 -1
  309. package/dist/MetricsTimelineSection-6BT5GNFV.js.map +0 -1
  310. package/dist/PerformanceSection-24TVVFZA.cjs +0 -356
  311. package/dist/PerformanceSection-24TVVFZA.cjs.map +0 -1
  312. package/dist/PerformanceSection-MGCEIXDX.js.map +0 -1
  313. package/dist/ResultsSection-DFUJ5U6M.js.map +0 -1
  314. package/dist/ResultsSection-XLGMMQKY.cjs.map +0 -1
  315. package/dist/ServicesSection-D5V3Q4GR.js +0 -118
  316. package/dist/ServicesSection-D5V3Q4GR.js.map +0 -1
  317. package/dist/ServicesSection-WJMGK2MF.cjs +0 -120
  318. package/dist/ServicesSection-WJMGK2MF.cjs.map +0 -1
  319. package/dist/SiteArchitectureSection-J7BPBERH.cjs.map +0 -1
  320. package/dist/SiteArchitectureSection-TE22OAWV.js.map +0 -1
  321. package/dist/SpeedComparisonSection-EZKFQVGW.cjs.map +0 -1
  322. package/dist/SpeedComparisonSection-Y3K7OFZQ.js.map +0 -1
  323. package/dist/StrategySection-CJ7Y6OFQ.cjs +0 -174
  324. package/dist/StrategySection-CJ7Y6OFQ.cjs.map +0 -1
  325. package/dist/StrategySection-DI5RSCJU.js.map +0 -1
  326. package/dist/TeamSection-DZVSNZE6.cjs +0 -112
  327. package/dist/TeamSection-DZVSNZE6.cjs.map +0 -1
  328. package/dist/TeamSection-HGKFW6PQ.js +0 -107
  329. package/dist/TeamSection-HGKFW6PQ.js.map +0 -1
  330. package/dist/TechStackSection-2AQ7RGY3.js +0 -93
  331. package/dist/TechStackSection-2AQ7RGY3.js.map +0 -1
  332. package/dist/TechStackSection-VTNNZR5V.cjs +0 -95
  333. package/dist/TechStackSection-VTNNZR5V.cjs.map +0 -1
  334. package/dist/TestimonialSection-6RGSMXQB.js.map +0 -1
  335. package/dist/TestimonialSection-XPTFUQIN.cjs.map +0 -1
  336. package/dist/VideoSection-4A2HC6K6.js.map +0 -1
  337. package/dist/VideoSection-G3DFS7UH.cjs +0 -118
  338. package/dist/VideoSection-G3DFS7UH.cjs.map +0 -1
  339. package/dist/chunk-2Y4O3LWM.js +0 -53
  340. package/dist/chunk-2Y4O3LWM.js.map +0 -1
  341. package/dist/chunk-633UMQQH.cjs +0 -31
  342. package/dist/chunk-633UMQQH.cjs.map +0 -1
  343. package/dist/chunk-7CFFAKDM.js +0 -74
  344. package/dist/chunk-7CFFAKDM.js.map +0 -1
  345. package/dist/chunk-APG2QSMB.js +0 -131
  346. package/dist/chunk-APG2QSMB.js.map +0 -1
  347. package/dist/chunk-AVCH4LMG.cjs +0 -620
  348. package/dist/chunk-AVCH4LMG.cjs.map +0 -1
  349. package/dist/chunk-AYBUHRFS.js +0 -613
  350. package/dist/chunk-AYBUHRFS.js.map +0 -1
  351. package/dist/chunk-EE75WRCM.cjs.map +0 -1
  352. package/dist/chunk-IKBK7HYX.cjs +0 -79
  353. package/dist/chunk-IKBK7HYX.cjs.map +0 -1
  354. package/dist/chunk-KEOHORIH.cjs +0 -79
  355. package/dist/chunk-KEOHORIH.cjs.map +0 -1
  356. package/dist/chunk-OA5ZM4OA.cjs +0 -139
  357. package/dist/chunk-OA5ZM4OA.cjs.map +0 -1
  358. package/dist/chunk-TVFXN6W6.js.map +0 -1
  359. package/dist/chunk-VVTK4OL6.js +0 -28
  360. package/dist/chunk-VVTK4OL6.js.map +0 -1
  361. package/dist/chunk-XCKXHK44.js +0 -15
  362. package/dist/chunk-XCKXHK44.js.map +0 -1
  363. package/dist/chunk-XONXEFJY.cjs +0 -58
  364. package/dist/chunk-XONXEFJY.cjs.map +0 -1
  365. package/dist/chunk-XQNJED46.cjs +0 -19
  366. package/dist/chunk-XQNJED46.cjs.map +0 -1
  367. package/dist/chunk-YB4B3OMC.js +0 -74
  368. package/dist/chunk-YB4B3OMC.js.map +0 -1
  369. package/dist/portfolio/sections.cjs +0 -20
  370. package/dist/portfolio/sections.cjs.map +0 -1
  371. package/dist/portfolio/sections.d.cts +0 -42
  372. package/dist/portfolio/sections.d.ts +0 -42
  373. package/dist/portfolio/sections.js +0 -4
  374. package/dist/portfolio/sections.js.map +0 -1
@@ -1,40 +1,57 @@
1
1
  'use strict';
2
2
 
3
- var chunkKEOHORIH_cjs = require('./chunk-KEOHORIH.cjs');
4
- var chunkIKBK7HYX_cjs = require('./chunk-IKBK7HYX.cjs');
3
+ var chunkNI4FVCLS_cjs = require('../../chunk-NI4FVCLS.cjs');
4
+ var Image = require('next/image');
5
+ var ScrollReveal = require('@sonordev/agency-site-kit/portfolio/primitives/ScrollReveal');
6
+ var GlassCard = require('@sonordev/agency-site-kit/portfolio/primitives/GlassCard');
5
7
  var jsxRuntime = require('react/jsx-runtime');
6
8
 
9
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
+
11
+ var Image__default = /*#__PURE__*/_interopDefault(Image);
12
+ var ScrollReveal__default = /*#__PURE__*/_interopDefault(ScrollReveal);
13
+ var GlassCard__default = /*#__PURE__*/_interopDefault(GlassCard);
14
+
7
15
  function StarRating({ rating }) {
8
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
9
- "svg",
16
+ return /* @__PURE__ */ jsxRuntime.jsx(
17
+ "div",
10
18
  {
11
- width: "20",
12
- height: "20",
13
- viewBox: "0 0 20 20",
14
- fill: i < rating ? "var(--sk-primary, #6366f1)" : "none",
15
- xmlns: "http://www.w3.org/2000/svg",
16
- children: /* @__PURE__ */ jsxRuntime.jsx(
17
- "path",
19
+ className: "flex items-center gap-1",
20
+ role: "img",
21
+ "aria-label": `Rated ${rating} out of 5 stars`,
22
+ children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
23
+ "svg",
18
24
  {
19
- d: "M10 1.667l2.575 5.216 5.758.84-4.166 4.06.983 5.734L10 14.808l-5.15 2.709.983-5.734-4.166-4.06 5.758-.84L10 1.667z",
20
- stroke: i < rating ? "var(--sk-primary, #6366f1)" : "var(--sk-text-tertiary, #71717a)",
21
- strokeWidth: "1.5",
22
- strokeLinecap: "round",
23
- strokeLinejoin: "round"
24
- }
25
- )
26
- },
27
- i
28
- )) });
25
+ "aria-hidden": "true",
26
+ width: "20",
27
+ height: "20",
28
+ viewBox: "0 0 20 20",
29
+ fill: i < rating ? "var(--sk-primary, #6366f1)" : "none",
30
+ xmlns: "http://www.w3.org/2000/svg",
31
+ children: /* @__PURE__ */ jsxRuntime.jsx(
32
+ "path",
33
+ {
34
+ d: "M10 1.667l2.575 5.216 5.758.84-4.166 4.06.983 5.734L10 14.808l-5.15 2.709.983-5.734-4.166-4.06 5.758-.84L10 1.667z",
35
+ stroke: i < rating ? "var(--sk-primary, #6366f1)" : "var(--sk-text-tertiary, #71717a)",
36
+ strokeWidth: "1.5",
37
+ strokeLinecap: "round",
38
+ strokeLinejoin: "round"
39
+ }
40
+ )
41
+ },
42
+ i
43
+ ))
44
+ }
45
+ );
29
46
  }
30
47
  function TestimonialSection({ data }) {
31
- const avatarUrl = data.avatar?.asset?._ref;
48
+ const avatar = chunkNI4FVCLS_cjs.resolvePortfolioImage(data.avatar);
32
49
  return /* @__PURE__ */ jsxRuntime.jsx(
33
50
  "section",
34
51
  {
35
52
  className: "w-full py-20 md:py-28",
36
53
  style: { background: "var(--sk-bg, #0a0a0a)" },
37
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-4xl mx-auto px-6", children: /* @__PURE__ */ jsxRuntime.jsx(chunkIKBK7HYX_cjs.ScrollReveal, { y: 30, duration: 1, children: /* @__PURE__ */ jsxRuntime.jsx(chunkKEOHORIH_cjs.GlassCard, { padding: "lg", hover: false, className: "text-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-6 py-8 px-4 md:px-12", children: [
54
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-4xl mx-auto px-6", children: /* @__PURE__ */ jsxRuntime.jsx(ScrollReveal__default.default, { y: 30, duration: 1, children: /* @__PURE__ */ jsxRuntime.jsx(GlassCard__default.default, { padding: "lg", hover: false, className: "text-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-6 py-8 px-4 md:px-12", children: [
38
55
  /* @__PURE__ */ jsxRuntime.jsx(
39
56
  "svg",
40
57
  {
@@ -70,11 +87,13 @@ function TestimonialSection({ data }) {
70
87
  ),
71
88
  data.rating !== void 0 && data.rating > 0 && /* @__PURE__ */ jsxRuntime.jsx(StarRating, { rating: data.rating }),
72
89
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 mt-2", children: [
73
- avatarUrl ? /* @__PURE__ */ jsxRuntime.jsx(
74
- "img",
90
+ avatar ? /* @__PURE__ */ jsxRuntime.jsx(
91
+ Image__default.default,
75
92
  {
76
- src: avatarUrl,
93
+ src: avatar.url,
77
94
  alt: data.author,
95
+ width: 48,
96
+ height: 48,
78
97
  className: "w-12 h-12 rounded-full object-cover",
79
98
  style: {
80
99
  border: "2px solid var(--sk-border, rgba(255,255,255,0.1))"
@@ -120,5 +139,5 @@ function TestimonialSection({ data }) {
120
139
  }
121
140
 
122
141
  module.exports = TestimonialSection;
123
- //# sourceMappingURL=TestimonialSection-XPTFUQIN.cjs.map
124
- //# sourceMappingURL=TestimonialSection-XPTFUQIN.cjs.map
142
+ //# sourceMappingURL=TestimonialSection.cjs.map
143
+ //# sourceMappingURL=TestimonialSection.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/portfolio/components/sections/TestimonialSection.tsx"],"names":["jsx","resolvePortfolioImage","ScrollReveal","GlassCard","jsxs","Image"],"mappings":"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","file":"TestimonialSection.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 Image from 'next/image';\nimport type { PortfolioTestimonialData } from '../../../types';\nimport { resolvePortfolioImage } from '../../../shared/images';\nimport ScrollReveal from '@sonordev/agency-site-kit/portfolio/primitives/ScrollReveal';\nimport GlassCard from '@sonordev/agency-site-kit/portfolio/primitives/GlassCard';\n\ninterface TestimonialSectionProps {\n data: PortfolioTestimonialData;\n}\n\nfunction StarRating({ rating }: { rating: number }) {\n return (\n <div\n className=\"flex items-center gap-1\"\n role=\"img\"\n aria-label={`Rated ${rating} out of 5 stars`}\n >\n {Array.from({ length: 5 }).map((_, i) => (\n <svg\n key={i}\n aria-hidden=\"true\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 20 20\"\n fill={i < rating ? 'var(--sk-primary, #6366f1)' : 'none'}\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M10 1.667l2.575 5.216 5.758.84-4.166 4.06.983 5.734L10 14.808l-5.15 2.709.983-5.734-4.166-4.06 5.758-.84L10 1.667z\"\n stroke={i < rating ? 'var(--sk-primary, #6366f1)' : 'var(--sk-text-tertiary, #71717a)'}\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n ))}\n </div>\n );\n}\n\nexport default function TestimonialSection({ data }: TestimonialSectionProps) {\n const avatar = resolvePortfolioImage(data.avatar);\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-4xl mx-auto px-6\">\n <ScrollReveal y={30} duration={1}>\n <GlassCard padding=\"lg\" hover={false} className=\"text-center\">\n <div className=\"flex flex-col items-center gap-6 py-8 px-4 md:px-12\">\n {/* Quote icon */}\n <svg\n width=\"48\"\n height=\"48\"\n viewBox=\"0 0 48 48\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n style={{ color: 'var(--sk-primary, #6366f1)', opacity: 0.4 }}\n >\n <path\n d=\"M14 28c-3.314 0-6-2.686-6-6 0-6.627 5.373-12 12-12v4c-4.418 0-8 3.582-8 8h2c3.314 0 6 2.686 6 6s-2.686 6-6 6zm20 0c-3.314 0-6-2.686-6-6 0-6.627 5.373-12 12-12v4c-4.418 0-8 3.582-8 8h2c3.314 0 6 2.686 6 6s-2.686 6-6 6z\"\n fill=\"currentColor\"\n />\n </svg>\n\n {/* Quote text */}\n <blockquote\n className=\"text-xl md:text-2xl lg:text-3xl font-medium leading-relaxed italic\"\n style={{\n color: 'var(--sk-text-primary, #ffffff)',\n fontFamily: 'var(--sk-font-heading, inherit)',\n }}\n >\n &ldquo;{data.quote}&rdquo;\n </blockquote>\n\n {/* Rating */}\n {data.rating !== undefined && data.rating > 0 && (\n <StarRating rating={data.rating} />\n )}\n\n {/* Author */}\n <div className=\"flex items-center gap-4 mt-2\">\n {avatar ? (\n <Image\n src={avatar.url}\n alt={data.author}\n width={48}\n height={48}\n className=\"w-12 h-12 rounded-full object-cover\"\n style={{\n border: '2px solid var(--sk-border, rgba(255,255,255,0.1))',\n }}\n />\n ) : (\n <div\n className=\"flex items-center justify-center w-12 h-12 rounded-full text-sm font-bold\"\n style={{\n background: 'color-mix(in srgb, var(--sk-primary, #6366f1) 20%, transparent)',\n color: 'var(--sk-primary, #6366f1)',\n }}\n >\n {data.author\n .split(' ')\n .map((w) => w[0])\n .join('')\n .slice(0, 2)\n .toUpperCase()}\n </div>\n )}\n <div className=\"text-left\">\n <div\n className=\"font-semibold\"\n style={{ color: 'var(--sk-text-primary, #ffffff)' }}\n >\n {data.author}\n </div>\n <div\n className=\"text-sm\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n {data.title}, {data.company}\n </div>\n </div>\n </div>\n </div>\n </GlassCard>\n </ScrollReveal>\n </div>\n </section>\n );\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { i as PortfolioTestimonialData } from '../../types-0tVPy4pU.cjs';
3
+
4
+ interface TestimonialSectionProps {
5
+ data: PortfolioTestimonialData;
6
+ }
7
+ declare function TestimonialSection({ data }: TestimonialSectionProps): React.JSX.Element;
8
+
9
+ export { TestimonialSection as default };
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { i as PortfolioTestimonialData } from '../../types-0tVPy4pU.js';
3
+
4
+ interface TestimonialSectionProps {
5
+ data: PortfolioTestimonialData;
6
+ }
7
+ declare function TestimonialSection({ data }: TestimonialSectionProps): React.JSX.Element;
8
+
9
+ export { TestimonialSection as default };
@@ -1,32 +1,43 @@
1
- import { GlassCard } from './chunk-YB4B3OMC.js';
2
- import { ScrollReveal } from './chunk-7CFFAKDM.js';
1
+ import { resolvePortfolioImage } from '../../chunk-XJ434N7I.js';
2
+ import Image from 'next/image';
3
+ import ScrollReveal from '@sonordev/agency-site-kit/portfolio/primitives/ScrollReveal';
4
+ import GlassCard from '@sonordev/agency-site-kit/portfolio/primitives/GlassCard';
3
5
  import { jsx, jsxs } from 'react/jsx-runtime';
4
6
 
5
7
  function StarRating({ rating }) {
6
- return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsx(
7
- "svg",
8
+ return /* @__PURE__ */ jsx(
9
+ "div",
8
10
  {
9
- width: "20",
10
- height: "20",
11
- viewBox: "0 0 20 20",
12
- fill: i < rating ? "var(--sk-primary, #6366f1)" : "none",
13
- xmlns: "http://www.w3.org/2000/svg",
14
- children: /* @__PURE__ */ jsx(
15
- "path",
11
+ className: "flex items-center gap-1",
12
+ role: "img",
13
+ "aria-label": `Rated ${rating} out of 5 stars`,
14
+ children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsx(
15
+ "svg",
16
16
  {
17
- d: "M10 1.667l2.575 5.216 5.758.84-4.166 4.06.983 5.734L10 14.808l-5.15 2.709.983-5.734-4.166-4.06 5.758-.84L10 1.667z",
18
- stroke: i < rating ? "var(--sk-primary, #6366f1)" : "var(--sk-text-tertiary, #71717a)",
19
- strokeWidth: "1.5",
20
- strokeLinecap: "round",
21
- strokeLinejoin: "round"
22
- }
23
- )
24
- },
25
- i
26
- )) });
17
+ "aria-hidden": "true",
18
+ width: "20",
19
+ height: "20",
20
+ viewBox: "0 0 20 20",
21
+ fill: i < rating ? "var(--sk-primary, #6366f1)" : "none",
22
+ xmlns: "http://www.w3.org/2000/svg",
23
+ children: /* @__PURE__ */ jsx(
24
+ "path",
25
+ {
26
+ d: "M10 1.667l2.575 5.216 5.758.84-4.166 4.06.983 5.734L10 14.808l-5.15 2.709.983-5.734-4.166-4.06 5.758-.84L10 1.667z",
27
+ stroke: i < rating ? "var(--sk-primary, #6366f1)" : "var(--sk-text-tertiary, #71717a)",
28
+ strokeWidth: "1.5",
29
+ strokeLinecap: "round",
30
+ strokeLinejoin: "round"
31
+ }
32
+ )
33
+ },
34
+ i
35
+ ))
36
+ }
37
+ );
27
38
  }
28
39
  function TestimonialSection({ data }) {
29
- const avatarUrl = data.avatar?.asset?._ref;
40
+ const avatar = resolvePortfolioImage(data.avatar);
30
41
  return /* @__PURE__ */ jsx(
31
42
  "section",
32
43
  {
@@ -68,11 +79,13 @@ function TestimonialSection({ data }) {
68
79
  ),
69
80
  data.rating !== void 0 && data.rating > 0 && /* @__PURE__ */ jsx(StarRating, { rating: data.rating }),
70
81
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 mt-2", children: [
71
- avatarUrl ? /* @__PURE__ */ jsx(
72
- "img",
82
+ avatar ? /* @__PURE__ */ jsx(
83
+ Image,
73
84
  {
74
- src: avatarUrl,
85
+ src: avatar.url,
75
86
  alt: data.author,
87
+ width: 48,
88
+ height: 48,
76
89
  className: "w-12 h-12 rounded-full object-cover",
77
90
  style: {
78
91
  border: "2px solid var(--sk-border, rgba(255,255,255,0.1))"
@@ -118,5 +131,5 @@ function TestimonialSection({ data }) {
118
131
  }
119
132
 
120
133
  export { TestimonialSection as default };
121
- //# sourceMappingURL=TestimonialSection-6RGSMXQB.js.map
122
- //# sourceMappingURL=TestimonialSection-6RGSMXQB.js.map
134
+ //# sourceMappingURL=TestimonialSection.js.map
135
+ //# sourceMappingURL=TestimonialSection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/portfolio/components/sections/TestimonialSection.tsx"],"names":[],"mappings":"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","file":"TestimonialSection.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 Image from 'next/image';\nimport type { PortfolioTestimonialData } from '../../../types';\nimport { resolvePortfolioImage } from '../../../shared/images';\nimport ScrollReveal from '@sonordev/agency-site-kit/portfolio/primitives/ScrollReveal';\nimport GlassCard from '@sonordev/agency-site-kit/portfolio/primitives/GlassCard';\n\ninterface TestimonialSectionProps {\n data: PortfolioTestimonialData;\n}\n\nfunction StarRating({ rating }: { rating: number }) {\n return (\n <div\n className=\"flex items-center gap-1\"\n role=\"img\"\n aria-label={`Rated ${rating} out of 5 stars`}\n >\n {Array.from({ length: 5 }).map((_, i) => (\n <svg\n key={i}\n aria-hidden=\"true\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 20 20\"\n fill={i < rating ? 'var(--sk-primary, #6366f1)' : 'none'}\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M10 1.667l2.575 5.216 5.758.84-4.166 4.06.983 5.734L10 14.808l-5.15 2.709.983-5.734-4.166-4.06 5.758-.84L10 1.667z\"\n stroke={i < rating ? 'var(--sk-primary, #6366f1)' : 'var(--sk-text-tertiary, #71717a)'}\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n ))}\n </div>\n );\n}\n\nexport default function TestimonialSection({ data }: TestimonialSectionProps) {\n const avatar = resolvePortfolioImage(data.avatar);\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-4xl mx-auto px-6\">\n <ScrollReveal y={30} duration={1}>\n <GlassCard padding=\"lg\" hover={false} className=\"text-center\">\n <div className=\"flex flex-col items-center gap-6 py-8 px-4 md:px-12\">\n {/* Quote icon */}\n <svg\n width=\"48\"\n height=\"48\"\n viewBox=\"0 0 48 48\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n style={{ color: 'var(--sk-primary, #6366f1)', opacity: 0.4 }}\n >\n <path\n d=\"M14 28c-3.314 0-6-2.686-6-6 0-6.627 5.373-12 12-12v4c-4.418 0-8 3.582-8 8h2c3.314 0 6 2.686 6 6s-2.686 6-6 6zm20 0c-3.314 0-6-2.686-6-6 0-6.627 5.373-12 12-12v4c-4.418 0-8 3.582-8 8h2c3.314 0 6 2.686 6 6s-2.686 6-6 6z\"\n fill=\"currentColor\"\n />\n </svg>\n\n {/* Quote text */}\n <blockquote\n className=\"text-xl md:text-2xl lg:text-3xl font-medium leading-relaxed italic\"\n style={{\n color: 'var(--sk-text-primary, #ffffff)',\n fontFamily: 'var(--sk-font-heading, inherit)',\n }}\n >\n &ldquo;{data.quote}&rdquo;\n </blockquote>\n\n {/* Rating */}\n {data.rating !== undefined && data.rating > 0 && (\n <StarRating rating={data.rating} />\n )}\n\n {/* Author */}\n <div className=\"flex items-center gap-4 mt-2\">\n {avatar ? (\n <Image\n src={avatar.url}\n alt={data.author}\n width={48}\n height={48}\n className=\"w-12 h-12 rounded-full object-cover\"\n style={{\n border: '2px solid var(--sk-border, rgba(255,255,255,0.1))',\n }}\n />\n ) : (\n <div\n className=\"flex items-center justify-center w-12 h-12 rounded-full text-sm font-bold\"\n style={{\n background: 'color-mix(in srgb, var(--sk-primary, #6366f1) 20%, transparent)',\n color: 'var(--sk-primary, #6366f1)',\n }}\n >\n {data.author\n .split(' ')\n .map((w) => w[0])\n .join('')\n .slice(0, 2)\n .toUpperCase()}\n </div>\n )}\n <div className=\"text-left\">\n <div\n className=\"font-semibold\"\n style={{ color: 'var(--sk-text-primary, #ffffff)' }}\n >\n {data.author}\n </div>\n <div\n className=\"text-sm\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n {data.title}, {data.company}\n </div>\n </div>\n </div>\n </div>\n </GlassCard>\n </ScrollReveal>\n </div>\n </section>\n );\n}\n"]}
@@ -0,0 +1,181 @@
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/VideoSection.tsx
33
+ var VideoSection_exports = {};
34
+ __export(VideoSection_exports, {
35
+ default: () => VideoSection
36
+ });
37
+ module.exports = __toCommonJS(VideoSection_exports);
38
+ var import_react = require("react");
39
+ var import_image = __toESM(require("next/image"), 1);
40
+
41
+ // src/shared/images.ts
42
+ var SANITY_ASSET_REF = /^image-[A-Za-z0-9]+-\d+x\d+-[a-z0-9]+$/;
43
+ var FILENAME_DIMS = /-(\d{2,5})x(\d{2,5})\.[a-z0-9]+(?:\?.*)?$/i;
44
+ var warnedAboutRefs = false;
45
+ function resolvePortfolioImage(input) {
46
+ const raw = typeof input === "string" ? input : input?.asset?._ref ?? "";
47
+ const value = (raw || "").trim();
48
+ if (!value) return null;
49
+ if (SANITY_ASSET_REF.test(value)) {
50
+ if (!warnedAboutRefs && typeof console !== "undefined") {
51
+ warnedAboutRefs = true;
52
+ console.warn(
53
+ "[@sonordev/agency-site-kit] Received a raw Sanity asset ref instead of an image URL \u2014 skipping render. The Sonor API should resolve image refs to cdn.sanity.io URLs before returning portfolio sections."
54
+ );
55
+ }
56
+ return null;
57
+ }
58
+ if (!/^https?:\/\//i.test(value) && !value.startsWith("/")) return null;
59
+ const dims = value.match(FILENAME_DIMS);
60
+ if (dims) {
61
+ const width = parseInt(dims[1], 10);
62
+ const height = parseInt(dims[2], 10);
63
+ if (width > 0 && height > 0) return { url: value, width, height };
64
+ }
65
+ return { url: value };
66
+ }
67
+
68
+ // src/portfolio/components/sections/VideoSection.tsx
69
+ var import_ScrollReveal = __toESM(require("@sonordev/agency-site-kit/portfolio/primitives/ScrollReveal"), 1);
70
+ var import_GlassCard = __toESM(require("@sonordev/agency-site-kit/portfolio/primitives/GlassCard"), 1);
71
+ var import_jsx_runtime = require("react/jsx-runtime");
72
+ function getEmbedUrl(data) {
73
+ if (data.embedUrl) return data.embedUrl;
74
+ if (!data.url) return "";
75
+ const ytMatch = data.url.match(
76
+ /(?:youtube\.com\/(?:watch\?v=|embed\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/
77
+ );
78
+ if (ytMatch) return `https://www.youtube.com/embed/${ytMatch[1]}?autoplay=1`;
79
+ const vimeoMatch = data.url.match(/vimeo\.com\/(\d+)/);
80
+ if (vimeoMatch) return `https://player.vimeo.com/video/${vimeoMatch[1]}?autoplay=1`;
81
+ return data.url;
82
+ }
83
+ function VideoSection({ data }) {
84
+ const [playing, setPlaying] = (0, import_react.useState)(false);
85
+ const thumbnail = resolvePortfolioImage(data.thumbnail);
86
+ const embedUrl = getEmbedUrl(data);
87
+ const handlePlay = (0, import_react.useCallback)(() => {
88
+ if (embedUrl) setPlaying(true);
89
+ }, [embedUrl]);
90
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
91
+ "section",
92
+ {
93
+ className: "w-full py-20 md:py-28",
94
+ style: { background: "var(--sk-bg, #0a0a0a)" },
95
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "max-w-5xl mx-auto px-6", children: [
96
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ScrollReveal.default, { y: 30, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
97
+ "h2",
98
+ {
99
+ className: "text-3xl md:text-4xl font-bold mb-4",
100
+ style: {
101
+ color: "var(--sk-text-primary, #ffffff)",
102
+ fontFamily: "var(--sk-font-heading, inherit)"
103
+ },
104
+ children: data.title
105
+ }
106
+ ) }),
107
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ScrollReveal.default, { y: 40, delay: 0.15, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_GlassCard.default, { padding: "sm", hover: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "relative w-full overflow-hidden rounded-xl", style: { aspectRatio: "16/9" }, children: playing ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
108
+ "iframe",
109
+ {
110
+ src: embedUrl,
111
+ className: "absolute inset-0 w-full h-full",
112
+ allow: "autoplay; fullscreen; picture-in-picture",
113
+ allowFullScreen: true,
114
+ title: data.title,
115
+ style: { border: "none" }
116
+ }
117
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
118
+ "button",
119
+ {
120
+ onClick: handlePlay,
121
+ className: "absolute inset-0 w-full h-full group cursor-pointer",
122
+ "aria-label": `Play ${data.title}`,
123
+ children: [
124
+ thumbnail && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
125
+ import_image.default,
126
+ {
127
+ src: thumbnail.url,
128
+ alt: data.title,
129
+ fill: true,
130
+ sizes: "(max-width: 1024px) 100vw, 976px",
131
+ className: "object-cover"
132
+ }
133
+ ),
134
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
135
+ "div",
136
+ {
137
+ className: "absolute inset-0 transition-opacity duration-300 group-hover:opacity-60",
138
+ style: { background: "rgba(0,0,0,0.4)", opacity: 0.5 }
139
+ }
140
+ ),
141
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
142
+ "div",
143
+ {
144
+ className: "flex items-center justify-center w-20 h-20 rounded-full transition-transform duration-300 group-hover:scale-110",
145
+ style: {
146
+ background: "var(--sk-primary, #6366f1)",
147
+ boxShadow: "0 8px 32px color-mix(in srgb, var(--sk-primary, #6366f1) 40%, transparent)"
148
+ },
149
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
150
+ "svg",
151
+ {
152
+ width: "32",
153
+ height: "32",
154
+ viewBox: "0 0 32 32",
155
+ fill: "none",
156
+ xmlns: "http://www.w3.org/2000/svg",
157
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 8l14 8-14 8V8z", fill: "#ffffff" })
158
+ }
159
+ )
160
+ }
161
+ ) }),
162
+ data.duration && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
163
+ "span",
164
+ {
165
+ className: "absolute bottom-4 right-4 px-3 py-1 rounded-lg text-xs font-medium",
166
+ style: {
167
+ background: "rgba(0,0,0,0.6)",
168
+ color: "#ffffff",
169
+ backdropFilter: "blur(4px)"
170
+ },
171
+ children: data.duration
172
+ }
173
+ )
174
+ ]
175
+ }
176
+ ) }) }) })
177
+ ] })
178
+ }
179
+ );
180
+ }
181
+ //# sourceMappingURL=VideoSection.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/portfolio/components/sections/VideoSection.tsx","../../../src/shared/images.ts"],"sourcesContent":["'use client';\n\nimport React, { useState, useCallback } from 'react';\nimport Image from 'next/image';\nimport type { PortfolioVideoData } from '../../../types';\nimport { resolvePortfolioImage } from '../../../shared/images';\nimport ScrollReveal from '@sonordev/agency-site-kit/portfolio/primitives/ScrollReveal';\nimport GlassCard from '@sonordev/agency-site-kit/portfolio/primitives/GlassCard';\n\ninterface VideoSectionProps {\n data: PortfolioVideoData;\n}\n\nfunction getEmbedUrl(data: PortfolioVideoData): string {\n if (data.embedUrl) return data.embedUrl;\n if (!data.url) return '';\n\n // Parse YouTube URLs\n const ytMatch = data.url.match(\n /(?:youtube\\.com\\/(?:watch\\?v=|embed\\/)|youtu\\.be\\/)([a-zA-Z0-9_-]{11})/,\n );\n if (ytMatch) return `https://www.youtube.com/embed/${ytMatch[1]}?autoplay=1`;\n\n // Parse Vimeo URLs\n const vimeoMatch = data.url.match(/vimeo\\.com\\/(\\d+)/);\n if (vimeoMatch) return `https://player.vimeo.com/video/${vimeoMatch[1]}?autoplay=1`;\n\n return data.url;\n}\n\nexport default function VideoSection({ data }: VideoSectionProps) {\n const [playing, setPlaying] = useState(false);\n\n const thumbnail = resolvePortfolioImage(data.thumbnail);\n const embedUrl = getEmbedUrl(data);\n\n const handlePlay = useCallback(() => {\n if (embedUrl) setPlaying(true);\n }, [embedUrl]);\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 {data.title}\n </h2>\n </ScrollReveal>\n\n <ScrollReveal y={40} delay={0.15}>\n <GlassCard padding=\"sm\" hover={false}>\n <div className=\"relative w-full overflow-hidden rounded-xl\" style={{ aspectRatio: '16/9' }}>\n {playing ? (\n <iframe\n src={embedUrl}\n className=\"absolute inset-0 w-full h-full\"\n allow=\"autoplay; fullscreen; picture-in-picture\"\n allowFullScreen\n title={data.title}\n style={{ border: 'none' }}\n />\n ) : (\n <button\n onClick={handlePlay}\n className=\"absolute inset-0 w-full h-full group cursor-pointer\"\n aria-label={`Play ${data.title}`}\n >\n {/* Thumbnail */}\n {thumbnail && (\n <Image\n src={thumbnail.url}\n alt={data.title}\n fill\n sizes=\"(max-width: 1024px) 100vw, 976px\"\n className=\"object-cover\"\n />\n )}\n\n {/* Dark overlay */}\n <div\n className=\"absolute inset-0 transition-opacity duration-300 group-hover:opacity-60\"\n style={{ background: 'rgba(0,0,0,0.4)', opacity: 0.5 }}\n />\n\n {/* Play button */}\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <div\n className=\"flex items-center justify-center w-20 h-20 rounded-full transition-transform duration-300 group-hover:scale-110\"\n style={{\n background: 'var(--sk-primary, #6366f1)',\n boxShadow: '0 8px 32px color-mix(in srgb, var(--sk-primary, #6366f1) 40%, transparent)',\n }}\n >\n <svg\n width=\"32\"\n height=\"32\"\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M12 8l14 8-14 8V8z\" fill=\"#ffffff\" />\n </svg>\n </div>\n </div>\n\n {/* Duration badge */}\n {data.duration && (\n <span\n className=\"absolute bottom-4 right-4 px-3 py-1 rounded-lg text-xs font-medium\"\n style={{\n background: 'rgba(0,0,0,0.6)',\n color: '#ffffff',\n backdropFilter: 'blur(4px)',\n }}\n >\n {data.duration}\n </span>\n )}\n </button>\n )}\n </div>\n </GlassCard>\n </ScrollReveal>\n </div>\n </section>\n );\n}\n","/**\n * Portfolio image resolution — single source of truth for turning the mixed\n * image shapes the API sends (plain URL strings, Supabase Storage URLs,\n * Sanity image objects) into something safe to render.\n *\n * IMPORTANT: a raw Sanity asset _ref (`image-{id}-{W}x{H}-{fmt}`) is an asset\n * ID, NOT a URL. Rendering it as `src` issues a garbage relative request\n * against the agency site's origin. Resolving refs to cdn.sanity.io URLs is\n * the API's job (it owns the Sanity project config); this helper refuses refs\n * so a broken image can never render, and warns once so the gap is visible.\n *\n * When a URL carries `-{W}x{H}.{ext}` dimensions (Sanity CDN URLs always do),\n * they're parsed out so callers can give next/image exact intrinsic sizes.\n */\n\nexport interface ResolvedPortfolioImage {\n url: string;\n width?: number;\n height?: number;\n}\n\n/** Raw Sanity asset reference — an ID, not a URL. */\nconst SANITY_ASSET_REF = /^image-[A-Za-z0-9]+-\\d+x\\d+-[a-z0-9]+$/;\n\n/** `…-1200x800.png` (optionally with a query string) → intrinsic dimensions. */\nconst FILENAME_DIMS = /-(\\d{2,5})x(\\d{2,5})\\.[a-z0-9]+(?:\\?.*)?$/i;\n\ninterface SanityImageLike {\n asset?: { _ref?: string };\n}\n\nlet warnedAboutRefs = false;\n\n/**\n * Resolve a portfolio image input into a renderable URL (+ intrinsic\n * dimensions when they can be derived). Returns null for empty values and\n * for unresolved Sanity refs — callers skip rendering in that case.\n */\nexport function resolvePortfolioImage(\n input: string | SanityImageLike | null | undefined,\n): ResolvedPortfolioImage | null {\n const raw =\n typeof input === 'string' ? input : input?.asset?._ref ?? '';\n const value = (raw || '').trim();\n if (!value) return null;\n\n if (SANITY_ASSET_REF.test(value)) {\n if (!warnedAboutRefs && typeof console !== 'undefined') {\n warnedAboutRefs = true;\n console.warn(\n '[@sonordev/agency-site-kit] Received a raw Sanity asset ref instead of an ' +\n 'image URL — skipping render. The Sonor API should resolve image refs to ' +\n 'cdn.sanity.io URLs before returning portfolio sections.',\n );\n }\n return null;\n }\n\n // Only absolute http(s) URLs or site-rooted paths are renderable.\n if (!/^https?:\\/\\//i.test(value) && !value.startsWith('/')) return null;\n\n const dims = value.match(FILENAME_DIMS);\n if (dims) {\n const width = parseInt(dims[1], 10);\n const height = parseInt(dims[2], 10);\n if (width > 0 && height > 0) return { url: value, width, height };\n }\n\n return { url: value };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,mBAA6C;AAC7C,mBAAkB;;;ACmBlB,IAAM,mBAAmB;AAGzB,IAAM,gBAAgB;AAMtB,IAAI,kBAAkB;AAOf,SAAS,sBACd,OAC+B;AAC/B,QAAM,MACJ,OAAO,UAAU,WAAW,QAAQ,OAAO,OAAO,QAAQ;AAC5D,QAAM,SAAS,OAAO,IAAI,KAAK;AAC/B,MAAI,CAAC,MAAO,QAAO;AAEnB,MAAI,iBAAiB,KAAK,KAAK,GAAG;AAChC,QAAI,CAAC,mBAAmB,OAAO,YAAY,aAAa;AACtD,wBAAkB;AAClB,cAAQ;AAAA,QACN;AAAA,MAGF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAGA,MAAI,CAAC,gBAAgB,KAAK,KAAK,KAAK,CAAC,MAAM,WAAW,GAAG,EAAG,QAAO;AAEnE,QAAM,OAAO,MAAM,MAAM,aAAa;AACtC,MAAI,MAAM;AACR,UAAM,QAAQ,SAAS,KAAK,CAAC,GAAG,EAAE;AAClC,UAAM,SAAS,SAAS,KAAK,CAAC,GAAG,EAAE;AACnC,QAAI,QAAQ,KAAK,SAAS,EAAG,QAAO,EAAE,KAAK,OAAO,OAAO,OAAO;AAAA,EAClE;AAEA,SAAO,EAAE,KAAK,MAAM;AACtB;;;AD/DA,0BAAyB;AACzB,uBAAsB;AAwCZ;AAlCV,SAAS,YAAY,MAAkC;AACrD,MAAI,KAAK,SAAU,QAAO,KAAK;AAC/B,MAAI,CAAC,KAAK,IAAK,QAAO;AAGtB,QAAM,UAAU,KAAK,IAAI;AAAA,IACvB;AAAA,EACF;AACA,MAAI,QAAS,QAAO,iCAAiC,QAAQ,CAAC,CAAC;AAG/D,QAAM,aAAa,KAAK,IAAI,MAAM,mBAAmB;AACrD,MAAI,WAAY,QAAO,kCAAkC,WAAW,CAAC,CAAC;AAEtE,SAAO,KAAK;AACd;AAEe,SAAR,aAA8B,EAAE,KAAK,GAAsB;AAChE,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAS,KAAK;AAE5C,QAAM,YAAY,sBAAsB,KAAK,SAAS;AACtD,QAAM,WAAW,YAAY,IAAI;AAEjC,QAAM,iBAAa,0BAAY,MAAM;AACnC,QAAI,SAAU,YAAW,IAAI;AAAA,EAC/B,GAAG,CAAC,QAAQ,CAAC;AAEb,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,OAAO,EAAE,YAAY,wBAAwB;AAAA,MAE7C,uDAAC,SAAI,WAAU,0BACb;AAAA,oDAAC,oBAAAA,SAAA,EAAa,GAAG,IACf;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO;AAAA,cACL,OAAO;AAAA,cACP,YAAY;AAAA,YACd;AAAA,YAEC,eAAK;AAAA;AAAA,QACR,GACF;AAAA,QAEA,4CAAC,oBAAAA,SAAA,EAAa,GAAG,IAAI,OAAO,MAC1B,sDAAC,iBAAAC,SAAA,EAAU,SAAQ,MAAK,OAAO,OAC7B,sDAAC,SAAI,WAAU,8CAA6C,OAAO,EAAE,aAAa,OAAO,GACtF,oBACC;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,WAAU;AAAA,YACV,OAAM;AAAA,YACN,iBAAe;AAAA,YACf,OAAO,KAAK;AAAA,YACZ,OAAO,EAAE,QAAQ,OAAO;AAAA;AAAA,QAC1B,IAEA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS;AAAA,YACT,WAAU;AAAA,YACV,cAAY,QAAQ,KAAK,KAAK;AAAA,YAG7B;AAAA,2BACC;AAAA,gBAAC,aAAAC;AAAA,gBAAA;AAAA,kBACC,KAAK,UAAU;AAAA,kBACf,KAAK,KAAK;AAAA,kBACV,MAAI;AAAA,kBACJ,OAAM;AAAA,kBACN,WAAU;AAAA;AAAA,cACZ;AAAA,cAIF;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAO,EAAE,YAAY,mBAAmB,SAAS,IAAI;AAAA;AAAA,cACvD;AAAA,cAGA,4CAAC,SAAI,WAAU,qDACb;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAO;AAAA,oBACL,YAAY;AAAA,oBACZ,WAAW;AAAA,kBACb;AAAA,kBAEA;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAM;AAAA,sBACN,QAAO;AAAA,sBACP,SAAQ;AAAA,sBACR,MAAK;AAAA,sBACL,OAAM;AAAA,sBAEN,sDAAC,UAAK,GAAE,sBAAqB,MAAK,WAAU;AAAA;AAAA,kBAC9C;AAAA;AAAA,cACF,GACF;AAAA,cAGC,KAAK,YACJ;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAO;AAAA,oBACL,YAAY;AAAA,oBACZ,OAAO;AAAA,oBACP,gBAAgB;AAAA,kBAClB;AAAA,kBAEC,eAAK;AAAA;AAAA,cACR;AAAA;AAAA;AAAA,QAEJ,GAEJ,GACF,GACF;AAAA,SACF;AAAA;AAAA,EACF;AAEJ;","names":["ScrollReveal","GlassCard","Image"]}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { h as PortfolioVideoData } from '../../types-D0nb6KAx.cjs';
3
+
4
+ interface VideoSectionProps {
5
+ data: PortfolioVideoData;
6
+ }
7
+ declare function VideoSection({ data }: VideoSectionProps): React.JSX.Element;
8
+
9
+ export { VideoSection as default };
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { h as PortfolioVideoData } from '../../types-D0nb6KAx.js';
3
+
4
+ interface VideoSectionProps {
5
+ data: PortfolioVideoData;
6
+ }
7
+ declare function VideoSection({ data }: VideoSectionProps): React.JSX.Element;
8
+
9
+ export { VideoSection as default };
@@ -1,9 +1,15 @@
1
1
  'use client';
2
- import { GlassCard } from './chunk-YB4B3OMC.js';
3
- import { ScrollReveal } from './chunk-7CFFAKDM.js';
4
- import { useState, useCallback } from 'react';
5
- import { jsx, jsxs } from 'react/jsx-runtime';
2
+ "use client";
3
+ import {
4
+ resolvePortfolioImage
5
+ } from "../../chunk-QDXZ27R7.js";
6
6
 
7
+ // src/portfolio/components/sections/VideoSection.tsx
8
+ import { useState, useCallback } from "react";
9
+ import Image from "next/image";
10
+ import ScrollReveal from "@sonordev/agency-site-kit/portfolio/primitives/ScrollReveal";
11
+ import GlassCard from "@sonordev/agency-site-kit/portfolio/primitives/GlassCard";
12
+ import { jsx, jsxs } from "react/jsx-runtime";
7
13
  function getEmbedUrl(data) {
8
14
  if (data.embedUrl) return data.embedUrl;
9
15
  if (!data.url) return "";
@@ -17,7 +23,7 @@ function getEmbedUrl(data) {
17
23
  }
18
24
  function VideoSection({ data }) {
19
25
  const [playing, setPlaying] = useState(false);
20
- const thumbnailUrl = data.thumbnail?.asset?._ref || "";
26
+ const thumbnail = resolvePortfolioImage(data.thumbnail);
21
27
  const embedUrl = getEmbedUrl(data);
22
28
  const handlePlay = useCallback(() => {
23
29
  if (embedUrl) setPlaying(true);
@@ -56,12 +62,14 @@ function VideoSection({ data }) {
56
62
  className: "absolute inset-0 w-full h-full group cursor-pointer",
57
63
  "aria-label": `Play ${data.title}`,
58
64
  children: [
59
- thumbnailUrl && /* @__PURE__ */ jsx(
60
- "img",
65
+ thumbnail && /* @__PURE__ */ jsx(
66
+ Image,
61
67
  {
62
- src: thumbnailUrl,
68
+ src: thumbnail.url,
63
69
  alt: data.title,
64
- className: "w-full h-full object-cover"
70
+ fill: true,
71
+ sizes: "(max-width: 1024px) 100vw, 976px",
72
+ className: "object-cover"
65
73
  }
66
74
  ),
67
75
  /* @__PURE__ */ jsx(
@@ -111,7 +119,7 @@ function VideoSection({ data }) {
111
119
  }
112
120
  );
113
121
  }
114
-
115
- export { VideoSection as default };
116
- //# sourceMappingURL=VideoSection-4A2HC6K6.js.map
117
- //# sourceMappingURL=VideoSection-4A2HC6K6.js.map
122
+ export {
123
+ VideoSection as default
124
+ };
125
+ //# sourceMappingURL=VideoSection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/portfolio/components/sections/VideoSection.tsx"],"sourcesContent":["'use client';\n\nimport React, { useState, useCallback } from 'react';\nimport Image from 'next/image';\nimport type { PortfolioVideoData } from '../../../types';\nimport { resolvePortfolioImage } from '../../../shared/images';\nimport ScrollReveal from '@sonordev/agency-site-kit/portfolio/primitives/ScrollReveal';\nimport GlassCard from '@sonordev/agency-site-kit/portfolio/primitives/GlassCard';\n\ninterface VideoSectionProps {\n data: PortfolioVideoData;\n}\n\nfunction getEmbedUrl(data: PortfolioVideoData): string {\n if (data.embedUrl) return data.embedUrl;\n if (!data.url) return '';\n\n // Parse YouTube URLs\n const ytMatch = data.url.match(\n /(?:youtube\\.com\\/(?:watch\\?v=|embed\\/)|youtu\\.be\\/)([a-zA-Z0-9_-]{11})/,\n );\n if (ytMatch) return `https://www.youtube.com/embed/${ytMatch[1]}?autoplay=1`;\n\n // Parse Vimeo URLs\n const vimeoMatch = data.url.match(/vimeo\\.com\\/(\\d+)/);\n if (vimeoMatch) return `https://player.vimeo.com/video/${vimeoMatch[1]}?autoplay=1`;\n\n return data.url;\n}\n\nexport default function VideoSection({ data }: VideoSectionProps) {\n const [playing, setPlaying] = useState(false);\n\n const thumbnail = resolvePortfolioImage(data.thumbnail);\n const embedUrl = getEmbedUrl(data);\n\n const handlePlay = useCallback(() => {\n if (embedUrl) setPlaying(true);\n }, [embedUrl]);\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 {data.title}\n </h2>\n </ScrollReveal>\n\n <ScrollReveal y={40} delay={0.15}>\n <GlassCard padding=\"sm\" hover={false}>\n <div className=\"relative w-full overflow-hidden rounded-xl\" style={{ aspectRatio: '16/9' }}>\n {playing ? (\n <iframe\n src={embedUrl}\n className=\"absolute inset-0 w-full h-full\"\n allow=\"autoplay; fullscreen; picture-in-picture\"\n allowFullScreen\n title={data.title}\n style={{ border: 'none' }}\n />\n ) : (\n <button\n onClick={handlePlay}\n className=\"absolute inset-0 w-full h-full group cursor-pointer\"\n aria-label={`Play ${data.title}`}\n >\n {/* Thumbnail */}\n {thumbnail && (\n <Image\n src={thumbnail.url}\n alt={data.title}\n fill\n sizes=\"(max-width: 1024px) 100vw, 976px\"\n className=\"object-cover\"\n />\n )}\n\n {/* Dark overlay */}\n <div\n className=\"absolute inset-0 transition-opacity duration-300 group-hover:opacity-60\"\n style={{ background: 'rgba(0,0,0,0.4)', opacity: 0.5 }}\n />\n\n {/* Play button */}\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <div\n className=\"flex items-center justify-center w-20 h-20 rounded-full transition-transform duration-300 group-hover:scale-110\"\n style={{\n background: 'var(--sk-primary, #6366f1)',\n boxShadow: '0 8px 32px color-mix(in srgb, var(--sk-primary, #6366f1) 40%, transparent)',\n }}\n >\n <svg\n width=\"32\"\n height=\"32\"\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M12 8l14 8-14 8V8z\" fill=\"#ffffff\" />\n </svg>\n </div>\n </div>\n\n {/* Duration badge */}\n {data.duration && (\n <span\n className=\"absolute bottom-4 right-4 px-3 py-1 rounded-lg text-xs font-medium\"\n style={{\n background: 'rgba(0,0,0,0.6)',\n color: '#ffffff',\n backdropFilter: 'blur(4px)',\n }}\n >\n {data.duration}\n </span>\n )}\n </button>\n )}\n </div>\n </GlassCard>\n </ScrollReveal>\n </div>\n </section>\n );\n}\n"],"mappings":";;;;;;;AAEA,SAAgB,UAAU,mBAAmB;AAC7C,OAAO,WAAW;AAGlB,OAAO,kBAAkB;AACzB,OAAO,eAAe;AAwCZ,cAwBM,YAxBN;AAlCV,SAAS,YAAY,MAAkC;AACrD,MAAI,KAAK,SAAU,QAAO,KAAK;AAC/B,MAAI,CAAC,KAAK,IAAK,QAAO;AAGtB,QAAM,UAAU,KAAK,IAAI;AAAA,IACvB;AAAA,EACF;AACA,MAAI,QAAS,QAAO,iCAAiC,QAAQ,CAAC,CAAC;AAG/D,QAAM,aAAa,KAAK,IAAI,MAAM,mBAAmB;AACrD,MAAI,WAAY,QAAO,kCAAkC,WAAW,CAAC,CAAC;AAEtE,SAAO,KAAK;AACd;AAEe,SAAR,aAA8B,EAAE,KAAK,GAAsB;AAChE,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAE5C,QAAM,YAAY,sBAAsB,KAAK,SAAS;AACtD,QAAM,WAAW,YAAY,IAAI;AAEjC,QAAM,aAAa,YAAY,MAAM;AACnC,QAAI,SAAU,YAAW,IAAI;AAAA,EAC/B,GAAG,CAAC,QAAQ,CAAC;AAEb,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,OAAO,EAAE,YAAY,wBAAwB;AAAA,MAE7C,+BAAC,SAAI,WAAU,0BACb;AAAA,4BAAC,gBAAa,GAAG,IACf;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO;AAAA,cACL,OAAO;AAAA,cACP,YAAY;AAAA,YACd;AAAA,YAEC,eAAK;AAAA;AAAA,QACR,GACF;AAAA,QAEA,oBAAC,gBAAa,GAAG,IAAI,OAAO,MAC1B,8BAAC,aAAU,SAAQ,MAAK,OAAO,OAC7B,8BAAC,SAAI,WAAU,8CAA6C,OAAO,EAAE,aAAa,OAAO,GACtF,oBACC;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,WAAU;AAAA,YACV,OAAM;AAAA,YACN,iBAAe;AAAA,YACf,OAAO,KAAK;AAAA,YACZ,OAAO,EAAE,QAAQ,OAAO;AAAA;AAAA,QAC1B,IAEA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS;AAAA,YACT,WAAU;AAAA,YACV,cAAY,QAAQ,KAAK,KAAK;AAAA,YAG7B;AAAA,2BACC;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAK,UAAU;AAAA,kBACf,KAAK,KAAK;AAAA,kBACV,MAAI;AAAA,kBACJ,OAAM;AAAA,kBACN,WAAU;AAAA;AAAA,cACZ;AAAA,cAIF;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAO,EAAE,YAAY,mBAAmB,SAAS,IAAI;AAAA;AAAA,cACvD;AAAA,cAGA,oBAAC,SAAI,WAAU,qDACb;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAO;AAAA,oBACL,YAAY;AAAA,oBACZ,WAAW;AAAA,kBACb;AAAA,kBAEA;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAM;AAAA,sBACN,QAAO;AAAA,sBACP,SAAQ;AAAA,sBACR,MAAK;AAAA,sBACL,OAAM;AAAA,sBAEN,8BAAC,UAAK,GAAE,sBAAqB,MAAK,WAAU;AAAA;AAAA,kBAC9C;AAAA;AAAA,cACF,GACF;AAAA,cAGC,KAAK,YACJ;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAO;AAAA,oBACL,YAAY;AAAA,oBACZ,OAAO;AAAA,oBACP,gBAAgB;AAAA,kBAClB;AAAA,kBAEC,eAAK;AAAA;AAAA,cACR;AAAA;AAAA;AAAA,QAEJ,GAEJ,GACF,GACF;AAAA,SACF;AAAA;AAAA,EACF;AAEJ;","names":[]}