@sonordev/site-kit 5.1.0 → 5.3.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 (267) hide show
  1. package/README.md +15 -0
  2. package/agent-manifest.json +23 -2
  3. package/dist/AnalyticsProvider-NA7EMJCA.mjs +10 -0
  4. package/dist/{AnalyticsProvider-2LCSA6G3.mjs.map → AnalyticsProvider-NA7EMJCA.mjs.map} +1 -1
  5. package/dist/AnalyticsProvider-XE3ADUUH.js +31 -0
  6. package/dist/{AnalyticsProvider-V2U3TQMH.js.map → AnalyticsProvider-XE3ADUUH.js.map} +1 -1
  7. package/dist/{BlogViewTracker-COTPD7WL.js → BlogViewTracker-DVJHZ7CM.js} +6 -6
  8. package/dist/{BlogViewTracker-COTPD7WL.js.map → BlogViewTracker-DVJHZ7CM.js.map} +1 -1
  9. package/dist/{BlogViewTracker-HG25ONRP.mjs → BlogViewTracker-MKJYTTJQ.mjs} +5 -5
  10. package/dist/{BlogViewTracker-HG25ONRP.mjs.map → BlogViewTracker-MKJYTTJQ.mjs.map} +1 -1
  11. package/dist/ChatWidget-BD4F4XLD.mjs +11 -0
  12. package/dist/{ChatWidget-RWO7R7EJ.mjs.map → ChatWidget-BD4F4XLD.mjs.map} +1 -1
  13. package/dist/ChatWidget-BZ3KOSXG.js +20 -0
  14. package/dist/{ChatWidget-4QUJYFXU.js.map → ChatWidget-BZ3KOSXG.js.map} +1 -1
  15. package/dist/EngageWidget-JPP6EDCJ.js +18 -0
  16. package/dist/{EngageWidget-RSOXB3YM.js.map → EngageWidget-JPP6EDCJ.js.map} +1 -1
  17. package/dist/EngageWidget-L7B6PCM3.mjs +9 -0
  18. package/dist/{EngageWidget-LF4AC4QN.mjs.map → EngageWidget-L7B6PCM3.mjs.map} +1 -1
  19. package/dist/{FileField-YJ7DZXC3.mjs → FileField-7WPRONDS.mjs} +5 -5
  20. package/dist/{FileField-YJ7DZXC3.mjs.map → FileField-7WPRONDS.mjs.map} +1 -1
  21. package/dist/{FileField-S2GUM3QB.js → FileField-GHT7444Y.js} +6 -6
  22. package/dist/{FileField-S2GUM3QB.js.map → FileField-GHT7444Y.js.map} +1 -1
  23. package/dist/{FormSpotlight-7WAXLXZA.js → FormSpotlight-BB2IB7IX.js} +18 -18
  24. package/dist/{FormSpotlight-7WAXLXZA.js.map → FormSpotlight-BB2IB7IX.js.map} +1 -1
  25. package/dist/{FormSpotlight-HLH5LQKI.mjs → FormSpotlight-WZVS6HHR.mjs} +4 -4
  26. package/dist/{FormSpotlight-HLH5LQKI.mjs.map → FormSpotlight-WZVS6HHR.mjs.map} +1 -1
  27. package/dist/{FormStage-LEZYERJB.js → FormStage-FLBLXENZ.js} +15 -15
  28. package/dist/{FormStage-LEZYERJB.js.map → FormStage-FLBLXENZ.js.map} +1 -1
  29. package/dist/{FormStage-Q5JW75AF.mjs → FormStage-Y3NHHMV2.mjs} +4 -4
  30. package/dist/{FormStage-Q5JW75AF.mjs.map → FormStage-Y3NHHMV2.mjs.map} +1 -1
  31. package/dist/ManagedForm-2OPCHDNJ.js +23 -0
  32. package/dist/{ManagedForm-H4SEFSAF.js.map → ManagedForm-2OPCHDNJ.js.map} +1 -1
  33. package/dist/ManagedForm-AJM6D4SK.mjs +14 -0
  34. package/dist/{ManagedForm-U3NFIVEC.mjs.map → ManagedForm-AJM6D4SK.mjs.map} +1 -1
  35. package/dist/{ManagedNewsletterForm-KT2NGUNW.js → ManagedNewsletterForm-L2ZHJ7F4.js} +8 -8
  36. package/dist/{ManagedNewsletterForm-KT2NGUNW.js.map → ManagedNewsletterForm-L2ZHJ7F4.js.map} +1 -1
  37. package/dist/{ManagedNewsletterForm-YKYW7B6P.mjs → ManagedNewsletterForm-MJI2JXIB.mjs} +7 -7
  38. package/dist/{ManagedNewsletterForm-YKYW7B6P.mjs.map → ManagedNewsletterForm-MJI2JXIB.mjs.map} +1 -1
  39. package/dist/{SignalCore-2BH5PUGS.mjs → SignalCore-23YDDSWO.mjs} +5 -5
  40. package/dist/{SignalCore-2BH5PUGS.mjs.map → SignalCore-23YDDSWO.mjs.map} +1 -1
  41. package/dist/{SignalCore-JM4ODFL2.js → SignalCore-G2VM7NUP.js} +11 -11
  42. package/dist/{SignalCore-JM4ODFL2.js.map → SignalCore-G2VM7NUP.js.map} +1 -1
  43. package/dist/SitemapSync-T2N3TCWF.js +17 -0
  44. package/dist/{SitemapSync-J4UMJRTO.js.map → SitemapSync-T2N3TCWF.js.map} +1 -1
  45. package/dist/SitemapSync-YLWMU6J3.mjs +8 -0
  46. package/dist/{SitemapSync-5CXS2JGB.mjs.map → SitemapSync-YLWMU6J3.mjs.map} +1 -1
  47. package/dist/analytics/index.js +9 -9
  48. package/dist/analytics/index.mjs +4 -4
  49. package/dist/blog/index.js +20 -20
  50. package/dist/blog/index.mjs +3 -3
  51. package/dist/blog/server-ui.js +14 -14
  52. package/dist/blog/server-ui.mjs +2 -2
  53. package/dist/{chunk-44ZTBQH4.js → chunk-2MPOO6QJ.js} +3 -3
  54. package/dist/{chunk-44ZTBQH4.js.map → chunk-2MPOO6QJ.js.map} +1 -1
  55. package/dist/{chunk-E3GHVAMK.js → chunk-2VQ5YXOD.js} +23 -23
  56. package/dist/{chunk-E3GHVAMK.js.map → chunk-2VQ5YXOD.js.map} +1 -1
  57. package/dist/{chunk-CGQO7MFO.js → chunk-47566YF4.js} +14 -14
  58. package/dist/{chunk-CGQO7MFO.js.map → chunk-47566YF4.js.map} +1 -1
  59. package/dist/{chunk-ADOGOLYO.mjs → chunk-4HL6CAZ7.mjs} +4 -4
  60. package/dist/{chunk-ADOGOLYO.mjs.map → chunk-4HL6CAZ7.mjs.map} +1 -1
  61. package/dist/{chunk-DTNNZJYM.mjs → chunk-4IMZ45YA.mjs} +5 -5
  62. package/dist/{chunk-DTNNZJYM.mjs.map → chunk-4IMZ45YA.mjs.map} +1 -1
  63. package/dist/{chunk-ACLBRIYD.js → chunk-4S7BHFGT.js} +3 -3
  64. package/dist/{chunk-ACLBRIYD.js.map → chunk-4S7BHFGT.js.map} +1 -1
  65. package/dist/{chunk-FMOOQKZU.js → chunk-5HMN3FXL.js} +10 -10
  66. package/dist/{chunk-FMOOQKZU.js.map → chunk-5HMN3FXL.js.map} +1 -1
  67. package/dist/{chunk-TAM2D54C.js → chunk-5TGSM5EQ.js} +14 -14
  68. package/dist/{chunk-TAM2D54C.js.map → chunk-5TGSM5EQ.js.map} +1 -1
  69. package/dist/{chunk-BVLGJ2CZ.mjs → chunk-77HT6TYK.mjs} +3 -3
  70. package/dist/{chunk-BVLGJ2CZ.mjs.map → chunk-77HT6TYK.mjs.map} +1 -1
  71. package/dist/{chunk-2XHEUWHV.mjs → chunk-7UPPYERC.mjs} +4 -4
  72. package/dist/{chunk-2XHEUWHV.mjs.map → chunk-7UPPYERC.mjs.map} +1 -1
  73. package/dist/chunk-AEW7EFYU.js +147 -0
  74. package/dist/chunk-AEW7EFYU.js.map +1 -0
  75. package/dist/{chunk-OAJVITNO.mjs → chunk-AJBJH3BA.mjs} +3 -3
  76. package/dist/{chunk-OAJVITNO.mjs.map → chunk-AJBJH3BA.mjs.map} +1 -1
  77. package/dist/{chunk-SXNKLHOX.mjs → chunk-AKQA5ZYZ.mjs} +3 -3
  78. package/dist/{chunk-SXNKLHOX.mjs.map → chunk-AKQA5ZYZ.mjs.map} +1 -1
  79. package/dist/{chunk-WZMM57R2.js → chunk-APL44ZVK.js} +5 -5
  80. package/dist/{chunk-WZMM57R2.js.map → chunk-APL44ZVK.js.map} +1 -1
  81. package/dist/{chunk-JEI3CSY4.js → chunk-AVPMSJCQ.js} +4 -4
  82. package/dist/{chunk-JEI3CSY4.js.map → chunk-AVPMSJCQ.js.map} +1 -1
  83. package/dist/{chunk-TECD4AP7.mjs → chunk-COAVBUMS.mjs} +3 -3
  84. package/dist/{chunk-TECD4AP7.mjs.map → chunk-COAVBUMS.mjs.map} +1 -1
  85. package/dist/{chunk-BUDV7QHH.mjs → chunk-DBJRJ2Q2.mjs} +4 -4
  86. package/dist/{chunk-BUDV7QHH.mjs.map → chunk-DBJRJ2Q2.mjs.map} +1 -1
  87. package/dist/{chunk-OTHKWMDB.mjs → chunk-DN6A6KXH.mjs} +3 -3
  88. package/dist/{chunk-OTHKWMDB.mjs.map → chunk-DN6A6KXH.mjs.map} +1 -1
  89. package/dist/{chunk-GYAH4KFC.js → chunk-DTX4R45S.js} +40 -4
  90. package/dist/chunk-DTX4R45S.js.map +1 -0
  91. package/dist/{chunk-UMWVTIIZ.mjs → chunk-FH4LLJFL.mjs} +8 -8
  92. package/dist/{chunk-UMWVTIIZ.mjs.map → chunk-FH4LLJFL.mjs.map} +1 -1
  93. package/dist/{chunk-ZFZMN4LT.mjs → chunk-GM5E6R5W.mjs} +39 -3
  94. package/dist/chunk-GM5E6R5W.mjs.map +1 -0
  95. package/dist/{chunk-GZVSGQKT.js → chunk-GPH3VVLP.js} +3 -3
  96. package/dist/{chunk-GZVSGQKT.js.map → chunk-GPH3VVLP.js.map} +1 -1
  97. package/dist/{chunk-CBMHJPR7.js → chunk-GQTSQR63.js} +5 -5
  98. package/dist/{chunk-CBMHJPR7.js.map → chunk-GQTSQR63.js.map} +1 -1
  99. package/dist/{chunk-BGBJSMXT.js → chunk-GTK3CGWF.js} +6 -6
  100. package/dist/{chunk-BGBJSMXT.js.map → chunk-GTK3CGWF.js.map} +1 -1
  101. package/dist/{chunk-LB7LHVWI.mjs → chunk-H7274TKR.mjs} +9 -3
  102. package/dist/chunk-H7274TKR.mjs.map +1 -0
  103. package/dist/{chunk-MCXHQHIX.js → chunk-HIV5YK5G.js} +4 -4
  104. package/dist/{chunk-MCXHQHIX.js.map → chunk-HIV5YK5G.js.map} +1 -1
  105. package/dist/chunk-HRQ4367C.mjs +6 -0
  106. package/dist/{chunk-4SQ6PROR.mjs.map → chunk-HRQ4367C.mjs.map} +1 -1
  107. package/dist/{chunk-A3VGZAZQ.mjs → chunk-I72AUITZ.mjs} +3 -3
  108. package/dist/{chunk-A3VGZAZQ.mjs.map → chunk-I72AUITZ.mjs.map} +1 -1
  109. package/dist/{chunk-2ACKOMAL.js → chunk-IPV2TUAT.js} +9 -3
  110. package/dist/chunk-IPV2TUAT.js.map +1 -0
  111. package/dist/{chunk-CYQB5GLU.mjs → chunk-ISKJLXB4.mjs} +4 -4
  112. package/dist/{chunk-CYQB5GLU.mjs.map → chunk-ISKJLXB4.mjs.map} +1 -1
  113. package/dist/{chunk-HPIY7AR3.js → chunk-KP56C66Z.js} +14 -14
  114. package/dist/{chunk-HPIY7AR3.js.map → chunk-KP56C66Z.js.map} +1 -1
  115. package/dist/{chunk-PXAALKTP.js → chunk-KP5BFPGT.js} +5 -3
  116. package/dist/chunk-KP5BFPGT.js.map +1 -0
  117. package/dist/{chunk-VCNPTLK2.js → chunk-LFJRMY4V.js} +12 -12
  118. package/dist/{chunk-VCNPTLK2.js.map → chunk-LFJRMY4V.js.map} +1 -1
  119. package/dist/{chunk-2EJX56YJ.js → chunk-LHD45PGP.js} +8 -8
  120. package/dist/{chunk-2EJX56YJ.js.map → chunk-LHD45PGP.js.map} +1 -1
  121. package/dist/chunk-MLXUMVBK.mjs +142 -0
  122. package/dist/chunk-MLXUMVBK.mjs.map +1 -0
  123. package/dist/{chunk-ROJ25QM3.mjs → chunk-NW5CBNRU.mjs} +3 -3
  124. package/dist/{chunk-ROJ25QM3.mjs.map → chunk-NW5CBNRU.mjs.map} +1 -1
  125. package/dist/{chunk-5G2ZRQMO.mjs → chunk-PA5ZVCW2.mjs} +3 -3
  126. package/dist/{chunk-5G2ZRQMO.mjs.map → chunk-PA5ZVCW2.mjs.map} +1 -1
  127. package/dist/{chunk-IQLYFQKZ.js → chunk-QG7WHAGD.js} +15 -15
  128. package/dist/{chunk-IQLYFQKZ.js.map → chunk-QG7WHAGD.js.map} +1 -1
  129. package/dist/{chunk-FZISCIJV.mjs → chunk-R4PFWVGZ.mjs} +4 -4
  130. package/dist/{chunk-FZISCIJV.mjs.map → chunk-R4PFWVGZ.mjs.map} +1 -1
  131. package/dist/{chunk-5YKMHPJL.mjs → chunk-R5F2JQVX.mjs} +5 -3
  132. package/dist/chunk-R5F2JQVX.mjs.map +1 -0
  133. package/dist/{chunk-CKPFETIO.js → chunk-SHZXSIRH.js} +4 -4
  134. package/dist/{chunk-CKPFETIO.js.map → chunk-SHZXSIRH.js.map} +1 -1
  135. package/dist/{chunk-NSTY7ZZA.mjs → chunk-SI7R3IJX.mjs} +8 -8
  136. package/dist/{chunk-NSTY7ZZA.mjs.map → chunk-SI7R3IJX.mjs.map} +1 -1
  137. package/dist/{chunk-ACWGG4VW.js → chunk-TAIGHH5J.js} +9 -9
  138. package/dist/{chunk-ACWGG4VW.js.map → chunk-TAIGHH5J.js.map} +1 -1
  139. package/dist/chunk-TMQKZ4DO.js +8 -0
  140. package/dist/{chunk-YPEX4RDE.js.map → chunk-TMQKZ4DO.js.map} +1 -1
  141. package/dist/{chunk-VIIGOCX4.js → chunk-UJOEN4X6.js} +15 -15
  142. package/dist/{chunk-VIIGOCX4.js.map → chunk-UJOEN4X6.js.map} +1 -1
  143. package/dist/{chunk-EZLK2OQL.js → chunk-UYR22S67.js} +7 -7
  144. package/dist/{chunk-EZLK2OQL.js.map → chunk-UYR22S67.js.map} +1 -1
  145. package/dist/{chunk-5W56B52Z.mjs → chunk-VGX6G3TA.mjs} +3 -3
  146. package/dist/{chunk-5W56B52Z.mjs.map → chunk-VGX6G3TA.mjs.map} +1 -1
  147. package/dist/{chunk-WMNRTCYY.js → chunk-VLR2UYO4.js} +11 -11
  148. package/dist/{chunk-WMNRTCYY.js.map → chunk-VLR2UYO4.js.map} +1 -1
  149. package/dist/{chunk-VWVUYL5J.mjs → chunk-W47J6ZZG.mjs} +4 -4
  150. package/dist/{chunk-VWVUYL5J.mjs.map → chunk-W47J6ZZG.mjs.map} +1 -1
  151. package/dist/{chunk-NIJVVW4G.mjs → chunk-WD57YWY5.mjs} +3 -3
  152. package/dist/{chunk-NIJVVW4G.mjs.map → chunk-WD57YWY5.mjs.map} +1 -1
  153. package/dist/{chunk-ADBLBGCQ.mjs → chunk-WZZYTFDV.mjs} +3 -3
  154. package/dist/{chunk-ADBLBGCQ.mjs.map → chunk-WZZYTFDV.mjs.map} +1 -1
  155. package/dist/{chunk-EKTMXHBI.mjs → chunk-X4PL7R63.mjs} +3 -3
  156. package/dist/{chunk-EKTMXHBI.mjs.map → chunk-X4PL7R63.mjs.map} +1 -1
  157. package/dist/{chunk-6YKNDQYJ.mjs → chunk-XR47TOGW.mjs} +3 -3
  158. package/dist/{chunk-6YKNDQYJ.mjs.map → chunk-XR47TOGW.mjs.map} +1 -1
  159. package/dist/{chunk-DKRXPXOR.js → chunk-ZMFJXFUY.js} +3 -3
  160. package/dist/{chunk-DKRXPXOR.js.map → chunk-ZMFJXFUY.js.map} +1 -1
  161. package/dist/cli/index.js +3 -3
  162. package/dist/cli/index.mjs +1 -1
  163. package/dist/client/index.js +4 -4
  164. package/dist/client/index.mjs +3 -3
  165. package/dist/commerce/index.js +56 -56
  166. package/dist/commerce/index.mjs +5 -5
  167. package/dist/config/index.js +2 -2
  168. package/dist/config/index.mjs +1 -1
  169. package/dist/engage/index.js +13 -13
  170. package/dist/engage/index.mjs +7 -7
  171. package/dist/fleet/index.js +8 -8
  172. package/dist/fleet/index.mjs +4 -4
  173. package/dist/forms/FormField.d.ts +2 -1
  174. package/dist/forms/FormField.d.ts.map +1 -1
  175. package/dist/forms/ga4-identity.d.ts +31 -0
  176. package/dist/forms/ga4-identity.d.ts.map +1 -0
  177. package/dist/forms/ga4-identity.test.d.ts +2 -0
  178. package/dist/forms/ga4-identity.test.d.ts.map +1 -0
  179. package/dist/forms/index.js +24 -24
  180. package/dist/forms/index.mjs +10 -10
  181. package/dist/forms/server.js +11 -11
  182. package/dist/forms/server.mjs +9 -9
  183. package/dist/forms/static.js +8 -8
  184. package/dist/forms/static.mjs +7 -7
  185. package/dist/forms/styles.css +21 -0
  186. package/dist/forms/submitForm.d.ts.map +1 -1
  187. package/dist/forms/types.d.ts +13 -0
  188. package/dist/forms/types.d.ts.map +1 -1
  189. package/dist/images/index.js +11 -11
  190. package/dist/images/index.mjs +4 -4
  191. package/dist/index.js +63 -63
  192. package/dist/index.mjs +9 -9
  193. package/dist/layout/client.js +8 -8
  194. package/dist/layout/client.mjs +7 -7
  195. package/dist/layout/index.js +10 -10
  196. package/dist/layout/index.mjs +8 -8
  197. package/dist/maps/index.js +5 -5
  198. package/dist/maps/index.mjs +3 -3
  199. package/dist/motion/Parallax.d.ts +42 -0
  200. package/dist/motion/Parallax.d.ts.map +1 -0
  201. package/dist/motion/Reveal.d.ts +59 -0
  202. package/dist/motion/Reveal.d.ts.map +1 -0
  203. package/dist/motion/ScrollScene.d.ts +42 -0
  204. package/dist/motion/ScrollScene.d.ts.map +1 -0
  205. package/dist/motion/engine.d.ts +74 -0
  206. package/dist/motion/engine.d.ts.map +1 -0
  207. package/dist/motion/failsafe.d.ts +20 -0
  208. package/dist/motion/failsafe.d.ts.map +1 -0
  209. package/dist/motion/gsap.d.ts +84 -0
  210. package/dist/motion/gsap.d.ts.map +1 -0
  211. package/dist/motion/gsap.js +103 -0
  212. package/dist/motion/gsap.js.map +1 -0
  213. package/dist/motion/gsap.mjs +99 -0
  214. package/dist/motion/gsap.mjs.map +1 -0
  215. package/dist/motion/index.d.ts +31 -0
  216. package/dist/motion/index.d.ts.map +1 -0
  217. package/dist/motion/index.js +252 -0
  218. package/dist/motion/index.js.map +1 -0
  219. package/dist/motion/index.mjs +230 -0
  220. package/dist/motion/index.mjs.map +1 -0
  221. package/dist/motion/motion.test.d.ts +16 -0
  222. package/dist/motion/motion.test.d.ts.map +1 -0
  223. package/dist/motion/three.d.ts +105 -0
  224. package/dist/motion/three.d.ts.map +1 -0
  225. package/dist/motion/three.js +150 -0
  226. package/dist/motion/three.js.map +1 -0
  227. package/dist/motion/three.mjs +145 -0
  228. package/dist/motion/three.mjs.map +1 -0
  229. package/dist/proxy/index.js +3 -3
  230. package/dist/proxy/index.mjs +2 -2
  231. package/dist/proxy/securityHeaders.d.ts +21 -6
  232. package/dist/proxy/securityHeaders.d.ts.map +1 -1
  233. package/dist/search/index.js +4 -4
  234. package/dist/search/index.mjs +3 -3
  235. package/dist/seo/client.js +5 -5
  236. package/dist/seo/client.mjs +4 -4
  237. package/dist/seo/index.js +5 -5
  238. package/dist/seo/index.mjs +4 -4
  239. package/dist/server/index.js +3 -3
  240. package/dist/server/index.mjs +2 -2
  241. package/dist/shared/build-entries.d.ts +7 -1
  242. package/dist/shared/build-entries.d.ts.map +1 -1
  243. package/dist/shared/version.d.ts +1 -1
  244. package/dist/signal/index.js +11 -11
  245. package/dist/signal/index.mjs +2 -2
  246. package/dist/sync/index.js +16 -16
  247. package/dist/sync/index.mjs +4 -4
  248. package/package.json +28 -2
  249. package/skills/site-kit/SKILL.md +6 -0
  250. package/dist/AnalyticsProvider-2LCSA6G3.mjs +0 -10
  251. package/dist/AnalyticsProvider-V2U3TQMH.js +0 -31
  252. package/dist/ChatWidget-4QUJYFXU.js +0 -20
  253. package/dist/ChatWidget-RWO7R7EJ.mjs +0 -11
  254. package/dist/EngageWidget-LF4AC4QN.mjs +0 -9
  255. package/dist/EngageWidget-RSOXB3YM.js +0 -18
  256. package/dist/ManagedForm-H4SEFSAF.js +0 -23
  257. package/dist/ManagedForm-U3NFIVEC.mjs +0 -14
  258. package/dist/SitemapSync-5CXS2JGB.mjs +0 -8
  259. package/dist/SitemapSync-J4UMJRTO.js +0 -17
  260. package/dist/chunk-2ACKOMAL.js.map +0 -1
  261. package/dist/chunk-4SQ6PROR.mjs +0 -6
  262. package/dist/chunk-5YKMHPJL.mjs.map +0 -1
  263. package/dist/chunk-GYAH4KFC.js.map +0 -1
  264. package/dist/chunk-LB7LHVWI.mjs.map +0 -1
  265. package/dist/chunk-PXAALKTP.js.map +0 -1
  266. package/dist/chunk-YPEX4RDE.js +0 -8
  267. package/dist/chunk-ZFZMN4LT.mjs.map +0 -1
@@ -0,0 +1,252 @@
1
+ 'use client';
2
+ 'use strict';
3
+
4
+ var chunkAEW7EFYU_js = require('../chunk-AEW7EFYU.js');
5
+ require('../chunk-SNAQBZPT.js');
6
+ var react = require('react');
7
+ var jsxRuntime = require('react/jsx-runtime');
8
+
9
+ // src/motion/failsafe.ts
10
+ var scrolled = false;
11
+ var armed = false;
12
+ function arm() {
13
+ if (armed || typeof window === "undefined") return;
14
+ armed = true;
15
+ window.addEventListener(
16
+ "scroll",
17
+ () => {
18
+ scrolled = true;
19
+ },
20
+ { passive: true, once: true }
21
+ );
22
+ }
23
+ function onNoScroll(fn, ms = 2500) {
24
+ if (typeof window === "undefined") return () => {
25
+ };
26
+ arm();
27
+ const t = setTimeout(() => {
28
+ if (!scrolled) fn();
29
+ }, ms);
30
+ return () => clearTimeout(t);
31
+ }
32
+ var DEFAULT_EASING = "cubic-bezier(0.22, 1, 0.36, 1)";
33
+ var DEFAULT_STAGGER = 0.08;
34
+ function hiddenTransform(from, distance, scale) {
35
+ let t = "";
36
+ if (from === "up") t = `translate3d(0, ${distance}px, 0)`;
37
+ else if (from === "down") t = `translate3d(0, ${-distance}px, 0)`;
38
+ else if (from === "left") t = `translate3d(${-distance}px, 0, 0)`;
39
+ else if (from === "right") t = `translate3d(${distance}px, 0, 0)`;
40
+ if (scale !== void 0) t = `${t} scale(${scale})`.trim();
41
+ return t;
42
+ }
43
+ function Reveal({
44
+ children,
45
+ as = "div",
46
+ className,
47
+ style,
48
+ id,
49
+ from = "up",
50
+ distance = 24,
51
+ delay = 0,
52
+ duration = 0.7,
53
+ stagger = false,
54
+ once = true,
55
+ threshold = 0.15,
56
+ scale,
57
+ opacity = 0,
58
+ easing = DEFAULT_EASING
59
+ }) {
60
+ const ref = react.useRef(null);
61
+ const Tag = as;
62
+ react.useEffect(() => {
63
+ const el = ref.current;
64
+ if (!el) return;
65
+ if (chunkAEW7EFYU_js.prefersReducedMotion()) return;
66
+ const step = stagger === true ? DEFAULT_STAGGER : stagger || 0;
67
+ const targets = () => step > 0 && el.children.length > 0 ? Array.from(el.children) : [el];
68
+ const hiddenOpacity = String(opacity);
69
+ const transform = hiddenTransform(from, distance, scale);
70
+ let clearTimer;
71
+ let animObserver = null;
72
+ let cancelFailsafe;
73
+ let shown = false;
74
+ const hide = (animated) => {
75
+ clearTimeout(clearTimer);
76
+ for (const t of targets()) {
77
+ t.style.transition = animated ? `opacity ${duration * 0.5}s ${easing}, transform ${duration * 0.5}s ${easing}` : "none";
78
+ t.style.opacity = hiddenOpacity;
79
+ t.style.transform = transform;
80
+ }
81
+ };
82
+ const show = () => {
83
+ const list = targets();
84
+ let total = 0;
85
+ list.forEach((t, i) => {
86
+ const d = delay + step * i;
87
+ total = Math.max(total, d + duration);
88
+ t.style.transition = `opacity ${duration}s ${easing} ${d}s, transform ${duration}s ${easing} ${d}s`;
89
+ t.style.opacity = "";
90
+ t.style.transform = "";
91
+ });
92
+ clearTimeout(clearTimer);
93
+ clearTimer = setTimeout(() => {
94
+ for (const t of list) t.style.transition = "";
95
+ }, total * 1e3 + 100);
96
+ };
97
+ const restore = () => {
98
+ clearTimeout(clearTimer);
99
+ for (const t of targets()) {
100
+ t.style.transition = "";
101
+ t.style.opacity = "";
102
+ t.style.transform = "";
103
+ }
104
+ };
105
+ const foldObserver = new IntersectionObserver(([entry]) => {
106
+ foldObserver.disconnect();
107
+ if (!el.isConnected || entry?.isIntersecting) return;
108
+ hide(false);
109
+ cancelFailsafe = onNoScroll(() => {
110
+ animObserver?.disconnect();
111
+ restore();
112
+ });
113
+ animObserver = new IntersectionObserver(
114
+ ([e]) => {
115
+ if (!e) return;
116
+ if (e.isIntersecting) {
117
+ shown = true;
118
+ if (once) animObserver?.disconnect();
119
+ show();
120
+ } else if (shown && !once) {
121
+ hide(true);
122
+ }
123
+ },
124
+ // Fire when the element's top crosses `threshold` up from the
125
+ // bottom edge — the same trigger line as GSAP's "top 85%", and it
126
+ // works for elements taller than the viewport.
127
+ { rootMargin: `0px 0px -${Math.round(threshold * 100)}% 0px`, threshold: 0 }
128
+ );
129
+ animObserver.observe(el);
130
+ });
131
+ foldObserver.observe(el);
132
+ return () => {
133
+ foldObserver.disconnect();
134
+ animObserver?.disconnect();
135
+ cancelFailsafe?.();
136
+ clearTimeout(clearTimer);
137
+ };
138
+ }, [from, distance, delay, duration, stagger, once, threshold, scale, opacity, easing]);
139
+ return /* @__PURE__ */ jsxRuntime.jsx(Tag, { ref, id, className, style, "data-sk-reveal": "", children });
140
+ }
141
+ function useParallax(ref, options = {}) {
142
+ const { y = [40, -40], x, scale, opacity, rotate } = options;
143
+ const easeRef = react.useRef(options.ease);
144
+ easeRef.current = options.ease;
145
+ const key = JSON.stringify([y, x, scale, opacity, rotate]);
146
+ react.useEffect(() => {
147
+ const el = ref.current;
148
+ if (!el) return;
149
+ if (chunkAEW7EFYU_js.prefersReducedMotion()) return;
150
+ const between = (r, q) => r[0] + (r[1] - r[0]) * q;
151
+ return chunkAEW7EFYU_js.registerScene(
152
+ el,
153
+ (p, info) => {
154
+ const q = easeRef.current ? easeRef.current(p) : p;
155
+ let t = `translate3d(${x ? between(x, q) : 0}px, ${between(y, q)}px, 0)`;
156
+ if (scale) t += ` scale(${between(scale, q)})`;
157
+ if (rotate) t += ` rotate(${between(rotate, q)}deg)`;
158
+ el.style.transform = t;
159
+ if (opacity) el.style.opacity = String(between(opacity, q));
160
+ el.style.willChange = info.visible ? "transform" : "";
161
+ },
162
+ { mode: "view", lerp: 1 }
163
+ );
164
+ }, [ref, key]);
165
+ }
166
+ function Parallax({ children, as = "div", className, style, id, ...options }) {
167
+ const ref = react.useRef(null);
168
+ const Tag = as;
169
+ useParallax(ref, options);
170
+ return /* @__PURE__ */ jsxRuntime.jsx(Tag, { ref, id, className, style, "data-sk-parallax": "", children });
171
+ }
172
+ function useScrollScene(ref, onProgress, options = {}) {
173
+ const cbRef = react.useRef(onProgress);
174
+ cbRef.current = onProgress;
175
+ const { continuous, reducedP, mode, lerp, cssVar } = options;
176
+ react.useEffect(() => {
177
+ const el = ref.current;
178
+ if (!el) return;
179
+ const prop = cssVar === false ? null : cssVar ?? "--sk-p";
180
+ return chunkAEW7EFYU_js.registerScene(
181
+ el,
182
+ (p, info) => {
183
+ if (prop) el.style.setProperty(prop, p.toFixed(4));
184
+ cbRef.current?.(p, info);
185
+ },
186
+ { continuous, reducedP, mode, lerp }
187
+ );
188
+ }, [ref, continuous, reducedP, mode, lerp, cssVar]);
189
+ }
190
+ function ScrollScene({
191
+ children,
192
+ length = "300vh",
193
+ as = "section",
194
+ className,
195
+ style,
196
+ id,
197
+ stageClassName,
198
+ stageStyle,
199
+ onProgress,
200
+ continuous,
201
+ reducedP,
202
+ lerp,
203
+ cssVar
204
+ }) {
205
+ const ref = react.useRef(null);
206
+ const Tag = as;
207
+ useScrollScene(ref, onProgress, { continuous, reducedP, lerp, cssVar, mode: "pin" });
208
+ return /* @__PURE__ */ jsxRuntime.jsx(
209
+ Tag,
210
+ {
211
+ ref,
212
+ id,
213
+ className,
214
+ style: { position: "relative", height: length, ...style },
215
+ "data-sk-scene": "",
216
+ children: /* @__PURE__ */ jsxRuntime.jsx(
217
+ "div",
218
+ {
219
+ className: stageClassName,
220
+ style: { position: "sticky", top: 0, height: "100svh", overflow: "hidden", ...stageStyle },
221
+ "data-sk-stage": "",
222
+ children
223
+ }
224
+ )
225
+ }
226
+ );
227
+ }
228
+
229
+ Object.defineProperty(exports, "prefersReducedMotion", {
230
+ enumerable: true,
231
+ get: function () { return chunkAEW7EFYU_js.prefersReducedMotion; }
232
+ });
233
+ Object.defineProperty(exports, "refreshScenes", {
234
+ enumerable: true,
235
+ get: function () { return chunkAEW7EFYU_js.refreshScenes; }
236
+ });
237
+ Object.defineProperty(exports, "registerScene", {
238
+ enumerable: true,
239
+ get: function () { return chunkAEW7EFYU_js.registerScene; }
240
+ });
241
+ Object.defineProperty(exports, "sceneProgress", {
242
+ enumerable: true,
243
+ get: function () { return chunkAEW7EFYU_js.sceneProgress; }
244
+ });
245
+ exports.Parallax = Parallax;
246
+ exports.Reveal = Reveal;
247
+ exports.ScrollScene = ScrollScene;
248
+ exports.onNoScroll = onNoScroll;
249
+ exports.useParallax = useParallax;
250
+ exports.useScrollScene = useScrollScene;
251
+ //# sourceMappingURL=index.js.map
252
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/motion/failsafe.ts","../../src/motion/Reveal.tsx","../../src/motion/Parallax.tsx","../../src/motion/ScrollScene.tsx"],"names":["useRef","useEffect","prefersReducedMotion","jsx","registerScene"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Renderer failsafe for scroll-entrance reveals.\n *\n * Headless renderers — Google's Web Rendering Service included — execute\n * JavaScript but never scroll, so a scroll-triggered reveal would leave\n * below-the-fold content transparent in the rendered snapshot that gets\n * indexed. (Measured at ~85 transparent elements on one page before this\n * guard existed.) If the visitor hasn't scrolled shortly after a reveal\n * arms, we assume nobody is going to and show the content. Real visitors\n * scroll well inside the window, so animations are unaffected.\n *\n * Single source of truth for every reveal system in the kit. Ported from\n * upforge.io's lib/reveal-failsafe.\n */\n\nlet scrolled = false\nlet armed = false\n\nfunction arm() {\n if (armed || typeof window === 'undefined') return\n armed = true\n window.addEventListener(\n 'scroll',\n () => {\n scrolled = true\n },\n { passive: true, once: true },\n )\n}\n\n/**\n * Run `fn` after `ms` milliseconds unless the visitor scrolls first.\n * Returns a cancel function for effect cleanups.\n */\nexport function onNoScroll(fn: () => void, ms = 2500): () => void {\n if (typeof window === 'undefined') return () => {}\n arm()\n const t = setTimeout(() => {\n if (!scrolled) fn()\n }, ms)\n return () => clearTimeout(t)\n}\n","'use client'\n\nimport { useEffect, useRef, type CSSProperties, type ElementType, type ReactNode } from 'react'\nimport { prefersReducedMotion } from './engine'\nimport { onNoScroll } from './failsafe'\n\n/**\n * <Reveal> — scroll-entrance reveal with no animation library.\n *\n * The SEO contract, in order of importance:\n *\n * 1. The server HTML is fully visible. Nothing is hidden by a stylesheet or\n * an inline style at render time, so crawlers, no-JS visitors, and the\n * LCP measurement all see the finished page.\n * 2. Above-the-fold content is never touched. On mount, one\n * IntersectionObserver pass asks whether the element is already on\n * screen; if it is, this component does nothing at all.\n * 3. Only below-the-fold content is hidden (offscreen, so nobody sees the\n * swap) and revealed with a compositor-only CSS transition on opacity\n * and transform as it scrolls in.\n * 4. A headless renderer that never scrolls gets the content back after\n * 2.5s (see ./failsafe), so the indexed snapshot is never transparent.\n * 5. prefers-reduced-motion disables all of it.\n *\n * Replaces the per-site Reveal / ScrollReveal / RevealOnScroll components.\n */\n\nexport type RevealDirection = 'up' | 'down' | 'left' | 'right' | 'none'\n\nexport interface RevealProps {\n children?: ReactNode\n /** Element to render. Default \"div\". */\n as?: ElementType\n className?: string\n style?: CSSProperties\n id?: string\n /** Where the element travels in from. Default \"up\" (starts lower). */\n from?: RevealDirection\n /** Travel distance in px. Default 24. */\n distance?: number\n /** Seconds before the transition starts. Default 0. */\n delay?: number\n /** Transition length in seconds. Default 0.7. */\n duration?: number\n /**\n * Reveal the element's direct children one after another instead of the\n * element itself. `true` = 0.08s apart; a number = that many seconds.\n */\n stagger?: boolean | number\n /** Play once (default) or re-hide when the element scrolls back out. */\n once?: boolean\n /**\n * How far up the viewport the element's top must travel before it\n * reveals, as a fraction of viewport height. 0.15 (default) = reveal when\n * the top crosses 85% down the screen.\n */\n threshold?: number\n /** Starting scale, e.g. 0.96. Off by default. */\n scale?: number\n /** Starting opacity. Default 0. */\n opacity?: number\n /** CSS easing. Default an ease-out-quint curve. */\n easing?: string\n}\n\nconst DEFAULT_EASING = 'cubic-bezier(0.22, 1, 0.36, 1)'\nconst DEFAULT_STAGGER = 0.08\n\nfunction hiddenTransform(from: RevealDirection, distance: number, scale?: number): string {\n let t = ''\n if (from === 'up') t = `translate3d(0, ${distance}px, 0)`\n else if (from === 'down') t = `translate3d(0, ${-distance}px, 0)`\n else if (from === 'left') t = `translate3d(${-distance}px, 0, 0)`\n else if (from === 'right') t = `translate3d(${distance}px, 0, 0)`\n if (scale !== undefined) t = `${t} scale(${scale})`.trim()\n return t\n}\n\nexport function Reveal({\n children,\n as = 'div',\n className,\n style,\n id,\n from = 'up',\n distance = 24,\n delay = 0,\n duration = 0.7,\n stagger = false,\n once = true,\n threshold = 0.15,\n scale,\n opacity = 0,\n easing = DEFAULT_EASING,\n}: RevealProps) {\n const ref = useRef<HTMLElement>(null)\n const Tag = as as ElementType\n\n useEffect(() => {\n const el = ref.current\n if (!el) return\n if (prefersReducedMotion()) return\n\n const step = stagger === true ? DEFAULT_STAGGER : stagger || 0\n const targets = (): HTMLElement[] =>\n step > 0 && el.children.length > 0\n ? (Array.from(el.children) as HTMLElement[])\n : [el]\n const hiddenOpacity = String(opacity)\n const transform = hiddenTransform(from, distance, scale)\n\n let clearTimer: ReturnType<typeof setTimeout> | undefined\n let animObserver: IntersectionObserver | null = null\n let cancelFailsafe: (() => void) | undefined\n let shown = false\n\n const hide = (animated: boolean) => {\n clearTimeout(clearTimer)\n for (const t of targets()) {\n t.style.transition = animated\n ? `opacity ${duration * 0.5}s ${easing}, transform ${duration * 0.5}s ${easing}`\n : 'none'\n t.style.opacity = hiddenOpacity\n t.style.transform = transform\n }\n }\n\n const show = () => {\n const list = targets()\n let total = 0\n list.forEach((t, i) => {\n const d = delay + step * i\n total = Math.max(total, d + duration)\n t.style.transition = `opacity ${duration}s ${easing} ${d}s, transform ${duration}s ${easing} ${d}s`\n t.style.opacity = ''\n t.style.transform = ''\n })\n // Once the transition has run, drop the inline transition too, so the\n // element is back to exactly what the stylesheet says.\n clearTimeout(clearTimer)\n clearTimer = setTimeout(() => {\n for (const t of list) t.style.transition = ''\n }, total * 1000 + 100)\n }\n\n const restore = () => {\n clearTimeout(clearTimer)\n for (const t of targets()) {\n t.style.transition = ''\n t.style.opacity = ''\n t.style.transform = ''\n }\n }\n\n // Pass 1: one observation with no margin tells us above-vs-below fold\n // without a forced layout read. Above the fold: leave the static render\n // alone. Below: hide (offscreen, unseen) and arm the reveal.\n const foldObserver = new IntersectionObserver(([entry]) => {\n foldObserver.disconnect()\n if (!el.isConnected || entry?.isIntersecting) return\n\n hide(false)\n\n cancelFailsafe = onNoScroll(() => {\n animObserver?.disconnect()\n restore()\n })\n\n animObserver = new IntersectionObserver(\n ([e]) => {\n if (!e) return\n if (e.isIntersecting) {\n shown = true\n if (once) animObserver?.disconnect()\n show()\n } else if (shown && !once) {\n hide(true)\n }\n },\n // Fire when the element's top crosses `threshold` up from the\n // bottom edge — the same trigger line as GSAP's \"top 85%\", and it\n // works for elements taller than the viewport.\n { rootMargin: `0px 0px -${Math.round(threshold * 100)}% 0px`, threshold: 0 },\n )\n animObserver.observe(el)\n })\n foldObserver.observe(el)\n\n return () => {\n foldObserver.disconnect()\n animObserver?.disconnect()\n cancelFailsafe?.()\n clearTimeout(clearTimer)\n }\n }, [from, distance, delay, duration, stagger, once, threshold, scale, opacity, easing])\n\n return (\n <Tag ref={ref} id={id} className={className} style={style} data-sk-reveal=\"\">\n {children}\n </Tag>\n )\n}\n","'use client'\n\nimport {\n useEffect,\n useRef,\n type CSSProperties,\n type ElementType,\n type ReactNode,\n type RefObject,\n} from 'react'\nimport { prefersReducedMotion, registerScene } from './engine'\n\n/**\n * Scroll-linked parallax with no animation library.\n *\n * The element's progress through the viewport (0 as its top enters at the\n * bottom, 1 as its bottom leaves at the top) is mapped onto transform and\n * opacity — compositor-only properties, so a page full of these never\n * triggers layout or paint. Driven by the shared engine, so thirty of them\n * cost one requestAnimationFrame.\n *\n * Server-rendered exactly as authored: no offset, no hidden state. Under\n * prefers-reduced-motion nothing registers and the element stays put.\n *\n * Replaces the per-site ParallaxImage / ParallaxY components: wrap the\n * image in an overflow-hidden frame and give <Parallax> a scale so the\n * travel never shows the frame's edges.\n */\n\nexport interface ParallaxOptions {\n /** Vertical travel in px as [at p=0, at p=1]. Default [40, -40]. */\n y?: [number, number]\n /** Horizontal travel in px. */\n x?: [number, number]\n /** Scale as [from, to]. */\n scale?: [number, number]\n /** Opacity as [from, to]. */\n opacity?: [number, number]\n /** Rotation in degrees as [from, to]. */\n rotate?: [number, number]\n /** Remap progress before it's applied (e.g. an ease-in-out). */\n ease?: (p: number) => number\n}\n\nexport function useParallax(ref: RefObject<HTMLElement | null>, options: ParallaxOptions = {}): void {\n const { y = [40, -40], x, scale, opacity, rotate } = options\n const easeRef = useRef(options.ease)\n easeRef.current = options.ease\n // Ranges are small tuples; a string key keeps the effect stable across\n // renders that pass a fresh array literal with the same values.\n const key = JSON.stringify([y, x, scale, opacity, rotate])\n\n useEffect(() => {\n const el = ref.current\n if (!el) return\n if (prefersReducedMotion()) return\n\n const between = (r: [number, number], q: number) => r[0] + (r[1] - r[0]) * q\n\n return registerScene(\n el,\n (p, info) => {\n const q = easeRef.current ? easeRef.current(p) : p\n let t = `translate3d(${x ? between(x, q) : 0}px, ${between(y, q)}px, 0)`\n if (scale) t += ` scale(${between(scale, q)})`\n if (rotate) t += ` rotate(${between(rotate, q)}deg)`\n el.style.transform = t\n if (opacity) el.style.opacity = String(between(opacity, q))\n // Promote to its own layer only while it's actually moving on screen.\n el.style.willChange = info.visible ? 'transform' : ''\n },\n { mode: 'view', lerp: 1 },\n )\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [ref, key])\n}\n\nexport interface ParallaxProps extends ParallaxOptions {\n children?: ReactNode\n /** Element to render. Default \"div\". */\n as?: ElementType\n className?: string\n style?: CSSProperties\n id?: string\n}\n\nexport function Parallax({ children, as = 'div', className, style, id, ...options }: ParallaxProps) {\n const ref = useRef<HTMLElement>(null)\n const Tag = as as ElementType\n useParallax(ref, options)\n return (\n <Tag ref={ref} id={id} className={className} style={style} data-sk-parallax=\"\">\n {children}\n </Tag>\n )\n}\n","'use client'\n\nimport {\n useEffect,\n useRef,\n type CSSProperties,\n type ElementType,\n type ReactNode,\n type RefObject,\n} from 'react'\nimport { registerScene, type SceneInfo, type SceneOptions } from './engine'\n\n/**\n * A pinned scene: a tall wrapper with a sticky, viewport-sized stage inside\n * it. As the visitor scrolls the wrapper's height, the stage stays put and\n * the scene's progress runs 0 → 1. This is the unit of scroll cinema.\n *\n * What it does for you on every frame:\n * - writes progress to a CSS custom property on the wrapper (`--sk-p` by\n * default), so choreography can be pure CSS: `opacity: var(--sk-p)`,\n * `transform: translateX(calc(var(--sk-p) * -40vw))` — no per-frame JS.\n * - calls `onProgress(p, info)` for anything that needs code (canvas\n * frame-scrub, three.js, DOM measured moves).\n *\n * The children are server-rendered. A \"use client\" component still renders\n * its children on the server when they arrive as props, so the copy inside\n * a scene is in the HTML for crawlers and for first paint. What you must\n * NOT do is load this (or a component containing it) through\n * `dynamic(..., { ssr: false })` — that de-opts the whole subtree to client\n * rendering and the copy disappears from the HTML.\n */\n\nexport interface UseScrollSceneOptions extends SceneOptions {\n /** CSS custom property to write progress to. Default \"--sk-p\"; false to skip. */\n cssVar?: string | false\n}\n\nexport function useScrollScene(\n ref: RefObject<HTMLElement | null>,\n onProgress?: (p: number, info: SceneInfo) => void,\n options: UseScrollSceneOptions = {},\n): void {\n const cbRef = useRef(onProgress)\n cbRef.current = onProgress\n const { continuous, reducedP, mode, lerp, cssVar } = options\n\n useEffect(() => {\n const el = ref.current\n if (!el) return\n const prop = cssVar === false ? null : (cssVar ?? '--sk-p')\n return registerScene(\n el,\n (p, info) => {\n if (prop) el.style.setProperty(prop, p.toFixed(4))\n cbRef.current?.(p, info)\n },\n { continuous, reducedP, mode, lerp },\n )\n }, [ref, continuous, reducedP, mode, lerp, cssVar])\n}\n\nexport interface ScrollSceneProps extends Omit<UseScrollSceneOptions, 'mode'> {\n children?: ReactNode\n /** Scroll length of the scene — the wrapper's height. Default \"300vh\". */\n length?: string\n /** Wrapper element. Default \"section\". */\n as?: ElementType\n className?: string\n style?: CSSProperties\n id?: string\n /** Class/style for the sticky stage that holds the children. */\n stageClassName?: string\n stageStyle?: CSSProperties\n onProgress?: (p: number, info: SceneInfo) => void\n}\n\nexport function ScrollScene({\n children,\n length = '300vh',\n as = 'section',\n className,\n style,\n id,\n stageClassName,\n stageStyle,\n onProgress,\n continuous,\n reducedP,\n lerp,\n cssVar,\n}: ScrollSceneProps) {\n const ref = useRef<HTMLElement>(null)\n const Tag = as as ElementType\n useScrollScene(ref, onProgress, { continuous, reducedP, lerp, cssVar, mode: 'pin' })\n return (\n <Tag\n ref={ref}\n id={id}\n className={className}\n style={{ position: 'relative', height: length, ...style }}\n data-sk-scene=\"\"\n >\n <div\n className={stageClassName}\n style={{ position: 'sticky', top: 0, height: '100svh', overflow: 'hidden', ...stageStyle }}\n data-sk-stage=\"\"\n >\n {children}\n </div>\n </Tag>\n )\n}\n"]}
@@ -0,0 +1,230 @@
1
+ 'use client';
2
+ import { prefersReducedMotion, registerScene } from '../chunk-MLXUMVBK.mjs';
3
+ export { prefersReducedMotion, refreshScenes, registerScene, sceneProgress } from '../chunk-MLXUMVBK.mjs';
4
+ import '../chunk-BEXTDHO4.mjs';
5
+ import { useRef, useEffect } from 'react';
6
+ import { jsx } from 'react/jsx-runtime';
7
+
8
+ // src/motion/failsafe.ts
9
+ var scrolled = false;
10
+ var armed = false;
11
+ function arm() {
12
+ if (armed || typeof window === "undefined") return;
13
+ armed = true;
14
+ window.addEventListener(
15
+ "scroll",
16
+ () => {
17
+ scrolled = true;
18
+ },
19
+ { passive: true, once: true }
20
+ );
21
+ }
22
+ function onNoScroll(fn, ms = 2500) {
23
+ if (typeof window === "undefined") return () => {
24
+ };
25
+ arm();
26
+ const t = setTimeout(() => {
27
+ if (!scrolled) fn();
28
+ }, ms);
29
+ return () => clearTimeout(t);
30
+ }
31
+ var DEFAULT_EASING = "cubic-bezier(0.22, 1, 0.36, 1)";
32
+ var DEFAULT_STAGGER = 0.08;
33
+ function hiddenTransform(from, distance, scale) {
34
+ let t = "";
35
+ if (from === "up") t = `translate3d(0, ${distance}px, 0)`;
36
+ else if (from === "down") t = `translate3d(0, ${-distance}px, 0)`;
37
+ else if (from === "left") t = `translate3d(${-distance}px, 0, 0)`;
38
+ else if (from === "right") t = `translate3d(${distance}px, 0, 0)`;
39
+ if (scale !== void 0) t = `${t} scale(${scale})`.trim();
40
+ return t;
41
+ }
42
+ function Reveal({
43
+ children,
44
+ as = "div",
45
+ className,
46
+ style,
47
+ id,
48
+ from = "up",
49
+ distance = 24,
50
+ delay = 0,
51
+ duration = 0.7,
52
+ stagger = false,
53
+ once = true,
54
+ threshold = 0.15,
55
+ scale,
56
+ opacity = 0,
57
+ easing = DEFAULT_EASING
58
+ }) {
59
+ const ref = useRef(null);
60
+ const Tag = as;
61
+ useEffect(() => {
62
+ const el = ref.current;
63
+ if (!el) return;
64
+ if (prefersReducedMotion()) return;
65
+ const step = stagger === true ? DEFAULT_STAGGER : stagger || 0;
66
+ const targets = () => step > 0 && el.children.length > 0 ? Array.from(el.children) : [el];
67
+ const hiddenOpacity = String(opacity);
68
+ const transform = hiddenTransform(from, distance, scale);
69
+ let clearTimer;
70
+ let animObserver = null;
71
+ let cancelFailsafe;
72
+ let shown = false;
73
+ const hide = (animated) => {
74
+ clearTimeout(clearTimer);
75
+ for (const t of targets()) {
76
+ t.style.transition = animated ? `opacity ${duration * 0.5}s ${easing}, transform ${duration * 0.5}s ${easing}` : "none";
77
+ t.style.opacity = hiddenOpacity;
78
+ t.style.transform = transform;
79
+ }
80
+ };
81
+ const show = () => {
82
+ const list = targets();
83
+ let total = 0;
84
+ list.forEach((t, i) => {
85
+ const d = delay + step * i;
86
+ total = Math.max(total, d + duration);
87
+ t.style.transition = `opacity ${duration}s ${easing} ${d}s, transform ${duration}s ${easing} ${d}s`;
88
+ t.style.opacity = "";
89
+ t.style.transform = "";
90
+ });
91
+ clearTimeout(clearTimer);
92
+ clearTimer = setTimeout(() => {
93
+ for (const t of list) t.style.transition = "";
94
+ }, total * 1e3 + 100);
95
+ };
96
+ const restore = () => {
97
+ clearTimeout(clearTimer);
98
+ for (const t of targets()) {
99
+ t.style.transition = "";
100
+ t.style.opacity = "";
101
+ t.style.transform = "";
102
+ }
103
+ };
104
+ const foldObserver = new IntersectionObserver(([entry]) => {
105
+ foldObserver.disconnect();
106
+ if (!el.isConnected || entry?.isIntersecting) return;
107
+ hide(false);
108
+ cancelFailsafe = onNoScroll(() => {
109
+ animObserver?.disconnect();
110
+ restore();
111
+ });
112
+ animObserver = new IntersectionObserver(
113
+ ([e]) => {
114
+ if (!e) return;
115
+ if (e.isIntersecting) {
116
+ shown = true;
117
+ if (once) animObserver?.disconnect();
118
+ show();
119
+ } else if (shown && !once) {
120
+ hide(true);
121
+ }
122
+ },
123
+ // Fire when the element's top crosses `threshold` up from the
124
+ // bottom edge — the same trigger line as GSAP's "top 85%", and it
125
+ // works for elements taller than the viewport.
126
+ { rootMargin: `0px 0px -${Math.round(threshold * 100)}% 0px`, threshold: 0 }
127
+ );
128
+ animObserver.observe(el);
129
+ });
130
+ foldObserver.observe(el);
131
+ return () => {
132
+ foldObserver.disconnect();
133
+ animObserver?.disconnect();
134
+ cancelFailsafe?.();
135
+ clearTimeout(clearTimer);
136
+ };
137
+ }, [from, distance, delay, duration, stagger, once, threshold, scale, opacity, easing]);
138
+ return /* @__PURE__ */ jsx(Tag, { ref, id, className, style, "data-sk-reveal": "", children });
139
+ }
140
+ function useParallax(ref, options = {}) {
141
+ const { y = [40, -40], x, scale, opacity, rotate } = options;
142
+ const easeRef = useRef(options.ease);
143
+ easeRef.current = options.ease;
144
+ const key = JSON.stringify([y, x, scale, opacity, rotate]);
145
+ useEffect(() => {
146
+ const el = ref.current;
147
+ if (!el) return;
148
+ if (prefersReducedMotion()) return;
149
+ const between = (r, q) => r[0] + (r[1] - r[0]) * q;
150
+ return registerScene(
151
+ el,
152
+ (p, info) => {
153
+ const q = easeRef.current ? easeRef.current(p) : p;
154
+ let t = `translate3d(${x ? between(x, q) : 0}px, ${between(y, q)}px, 0)`;
155
+ if (scale) t += ` scale(${between(scale, q)})`;
156
+ if (rotate) t += ` rotate(${between(rotate, q)}deg)`;
157
+ el.style.transform = t;
158
+ if (opacity) el.style.opacity = String(between(opacity, q));
159
+ el.style.willChange = info.visible ? "transform" : "";
160
+ },
161
+ { mode: "view", lerp: 1 }
162
+ );
163
+ }, [ref, key]);
164
+ }
165
+ function Parallax({ children, as = "div", className, style, id, ...options }) {
166
+ const ref = useRef(null);
167
+ const Tag = as;
168
+ useParallax(ref, options);
169
+ return /* @__PURE__ */ jsx(Tag, { ref, id, className, style, "data-sk-parallax": "", children });
170
+ }
171
+ function useScrollScene(ref, onProgress, options = {}) {
172
+ const cbRef = useRef(onProgress);
173
+ cbRef.current = onProgress;
174
+ const { continuous, reducedP, mode, lerp, cssVar } = options;
175
+ useEffect(() => {
176
+ const el = ref.current;
177
+ if (!el) return;
178
+ const prop = cssVar === false ? null : cssVar ?? "--sk-p";
179
+ return registerScene(
180
+ el,
181
+ (p, info) => {
182
+ if (prop) el.style.setProperty(prop, p.toFixed(4));
183
+ cbRef.current?.(p, info);
184
+ },
185
+ { continuous, reducedP, mode, lerp }
186
+ );
187
+ }, [ref, continuous, reducedP, mode, lerp, cssVar]);
188
+ }
189
+ function ScrollScene({
190
+ children,
191
+ length = "300vh",
192
+ as = "section",
193
+ className,
194
+ style,
195
+ id,
196
+ stageClassName,
197
+ stageStyle,
198
+ onProgress,
199
+ continuous,
200
+ reducedP,
201
+ lerp,
202
+ cssVar
203
+ }) {
204
+ const ref = useRef(null);
205
+ const Tag = as;
206
+ useScrollScene(ref, onProgress, { continuous, reducedP, lerp, cssVar, mode: "pin" });
207
+ return /* @__PURE__ */ jsx(
208
+ Tag,
209
+ {
210
+ ref,
211
+ id,
212
+ className,
213
+ style: { position: "relative", height: length, ...style },
214
+ "data-sk-scene": "",
215
+ children: /* @__PURE__ */ jsx(
216
+ "div",
217
+ {
218
+ className: stageClassName,
219
+ style: { position: "sticky", top: 0, height: "100svh", overflow: "hidden", ...stageStyle },
220
+ "data-sk-stage": "",
221
+ children
222
+ }
223
+ )
224
+ }
225
+ );
226
+ }
227
+
228
+ export { Parallax, Reveal, ScrollScene, onNoScroll, useParallax, useScrollScene };
229
+ //# sourceMappingURL=index.mjs.map
230
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/motion/failsafe.ts","../../src/motion/Reveal.tsx","../../src/motion/Parallax.tsx","../../src/motion/ScrollScene.tsx"],"names":["useRef","useEffect","jsx"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Renderer failsafe for scroll-entrance reveals.\n *\n * Headless renderers — Google's Web Rendering Service included — execute\n * JavaScript but never scroll, so a scroll-triggered reveal would leave\n * below-the-fold content transparent in the rendered snapshot that gets\n * indexed. (Measured at ~85 transparent elements on one page before this\n * guard existed.) If the visitor hasn't scrolled shortly after a reveal\n * arms, we assume nobody is going to and show the content. Real visitors\n * scroll well inside the window, so animations are unaffected.\n *\n * Single source of truth for every reveal system in the kit. Ported from\n * upforge.io's lib/reveal-failsafe.\n */\n\nlet scrolled = false\nlet armed = false\n\nfunction arm() {\n if (armed || typeof window === 'undefined') return\n armed = true\n window.addEventListener(\n 'scroll',\n () => {\n scrolled = true\n },\n { passive: true, once: true },\n )\n}\n\n/**\n * Run `fn` after `ms` milliseconds unless the visitor scrolls first.\n * Returns a cancel function for effect cleanups.\n */\nexport function onNoScroll(fn: () => void, ms = 2500): () => void {\n if (typeof window === 'undefined') return () => {}\n arm()\n const t = setTimeout(() => {\n if (!scrolled) fn()\n }, ms)\n return () => clearTimeout(t)\n}\n","'use client'\n\nimport { useEffect, useRef, type CSSProperties, type ElementType, type ReactNode } from 'react'\nimport { prefersReducedMotion } from './engine'\nimport { onNoScroll } from './failsafe'\n\n/**\n * <Reveal> — scroll-entrance reveal with no animation library.\n *\n * The SEO contract, in order of importance:\n *\n * 1. The server HTML is fully visible. Nothing is hidden by a stylesheet or\n * an inline style at render time, so crawlers, no-JS visitors, and the\n * LCP measurement all see the finished page.\n * 2. Above-the-fold content is never touched. On mount, one\n * IntersectionObserver pass asks whether the element is already on\n * screen; if it is, this component does nothing at all.\n * 3. Only below-the-fold content is hidden (offscreen, so nobody sees the\n * swap) and revealed with a compositor-only CSS transition on opacity\n * and transform as it scrolls in.\n * 4. A headless renderer that never scrolls gets the content back after\n * 2.5s (see ./failsafe), so the indexed snapshot is never transparent.\n * 5. prefers-reduced-motion disables all of it.\n *\n * Replaces the per-site Reveal / ScrollReveal / RevealOnScroll components.\n */\n\nexport type RevealDirection = 'up' | 'down' | 'left' | 'right' | 'none'\n\nexport interface RevealProps {\n children?: ReactNode\n /** Element to render. Default \"div\". */\n as?: ElementType\n className?: string\n style?: CSSProperties\n id?: string\n /** Where the element travels in from. Default \"up\" (starts lower). */\n from?: RevealDirection\n /** Travel distance in px. Default 24. */\n distance?: number\n /** Seconds before the transition starts. Default 0. */\n delay?: number\n /** Transition length in seconds. Default 0.7. */\n duration?: number\n /**\n * Reveal the element's direct children one after another instead of the\n * element itself. `true` = 0.08s apart; a number = that many seconds.\n */\n stagger?: boolean | number\n /** Play once (default) or re-hide when the element scrolls back out. */\n once?: boolean\n /**\n * How far up the viewport the element's top must travel before it\n * reveals, as a fraction of viewport height. 0.15 (default) = reveal when\n * the top crosses 85% down the screen.\n */\n threshold?: number\n /** Starting scale, e.g. 0.96. Off by default. */\n scale?: number\n /** Starting opacity. Default 0. */\n opacity?: number\n /** CSS easing. Default an ease-out-quint curve. */\n easing?: string\n}\n\nconst DEFAULT_EASING = 'cubic-bezier(0.22, 1, 0.36, 1)'\nconst DEFAULT_STAGGER = 0.08\n\nfunction hiddenTransform(from: RevealDirection, distance: number, scale?: number): string {\n let t = ''\n if (from === 'up') t = `translate3d(0, ${distance}px, 0)`\n else if (from === 'down') t = `translate3d(0, ${-distance}px, 0)`\n else if (from === 'left') t = `translate3d(${-distance}px, 0, 0)`\n else if (from === 'right') t = `translate3d(${distance}px, 0, 0)`\n if (scale !== undefined) t = `${t} scale(${scale})`.trim()\n return t\n}\n\nexport function Reveal({\n children,\n as = 'div',\n className,\n style,\n id,\n from = 'up',\n distance = 24,\n delay = 0,\n duration = 0.7,\n stagger = false,\n once = true,\n threshold = 0.15,\n scale,\n opacity = 0,\n easing = DEFAULT_EASING,\n}: RevealProps) {\n const ref = useRef<HTMLElement>(null)\n const Tag = as as ElementType\n\n useEffect(() => {\n const el = ref.current\n if (!el) return\n if (prefersReducedMotion()) return\n\n const step = stagger === true ? DEFAULT_STAGGER : stagger || 0\n const targets = (): HTMLElement[] =>\n step > 0 && el.children.length > 0\n ? (Array.from(el.children) as HTMLElement[])\n : [el]\n const hiddenOpacity = String(opacity)\n const transform = hiddenTransform(from, distance, scale)\n\n let clearTimer: ReturnType<typeof setTimeout> | undefined\n let animObserver: IntersectionObserver | null = null\n let cancelFailsafe: (() => void) | undefined\n let shown = false\n\n const hide = (animated: boolean) => {\n clearTimeout(clearTimer)\n for (const t of targets()) {\n t.style.transition = animated\n ? `opacity ${duration * 0.5}s ${easing}, transform ${duration * 0.5}s ${easing}`\n : 'none'\n t.style.opacity = hiddenOpacity\n t.style.transform = transform\n }\n }\n\n const show = () => {\n const list = targets()\n let total = 0\n list.forEach((t, i) => {\n const d = delay + step * i\n total = Math.max(total, d + duration)\n t.style.transition = `opacity ${duration}s ${easing} ${d}s, transform ${duration}s ${easing} ${d}s`\n t.style.opacity = ''\n t.style.transform = ''\n })\n // Once the transition has run, drop the inline transition too, so the\n // element is back to exactly what the stylesheet says.\n clearTimeout(clearTimer)\n clearTimer = setTimeout(() => {\n for (const t of list) t.style.transition = ''\n }, total * 1000 + 100)\n }\n\n const restore = () => {\n clearTimeout(clearTimer)\n for (const t of targets()) {\n t.style.transition = ''\n t.style.opacity = ''\n t.style.transform = ''\n }\n }\n\n // Pass 1: one observation with no margin tells us above-vs-below fold\n // without a forced layout read. Above the fold: leave the static render\n // alone. Below: hide (offscreen, unseen) and arm the reveal.\n const foldObserver = new IntersectionObserver(([entry]) => {\n foldObserver.disconnect()\n if (!el.isConnected || entry?.isIntersecting) return\n\n hide(false)\n\n cancelFailsafe = onNoScroll(() => {\n animObserver?.disconnect()\n restore()\n })\n\n animObserver = new IntersectionObserver(\n ([e]) => {\n if (!e) return\n if (e.isIntersecting) {\n shown = true\n if (once) animObserver?.disconnect()\n show()\n } else if (shown && !once) {\n hide(true)\n }\n },\n // Fire when the element's top crosses `threshold` up from the\n // bottom edge — the same trigger line as GSAP's \"top 85%\", and it\n // works for elements taller than the viewport.\n { rootMargin: `0px 0px -${Math.round(threshold * 100)}% 0px`, threshold: 0 },\n )\n animObserver.observe(el)\n })\n foldObserver.observe(el)\n\n return () => {\n foldObserver.disconnect()\n animObserver?.disconnect()\n cancelFailsafe?.()\n clearTimeout(clearTimer)\n }\n }, [from, distance, delay, duration, stagger, once, threshold, scale, opacity, easing])\n\n return (\n <Tag ref={ref} id={id} className={className} style={style} data-sk-reveal=\"\">\n {children}\n </Tag>\n )\n}\n","'use client'\n\nimport {\n useEffect,\n useRef,\n type CSSProperties,\n type ElementType,\n type ReactNode,\n type RefObject,\n} from 'react'\nimport { prefersReducedMotion, registerScene } from './engine'\n\n/**\n * Scroll-linked parallax with no animation library.\n *\n * The element's progress through the viewport (0 as its top enters at the\n * bottom, 1 as its bottom leaves at the top) is mapped onto transform and\n * opacity — compositor-only properties, so a page full of these never\n * triggers layout or paint. Driven by the shared engine, so thirty of them\n * cost one requestAnimationFrame.\n *\n * Server-rendered exactly as authored: no offset, no hidden state. Under\n * prefers-reduced-motion nothing registers and the element stays put.\n *\n * Replaces the per-site ParallaxImage / ParallaxY components: wrap the\n * image in an overflow-hidden frame and give <Parallax> a scale so the\n * travel never shows the frame's edges.\n */\n\nexport interface ParallaxOptions {\n /** Vertical travel in px as [at p=0, at p=1]. Default [40, -40]. */\n y?: [number, number]\n /** Horizontal travel in px. */\n x?: [number, number]\n /** Scale as [from, to]. */\n scale?: [number, number]\n /** Opacity as [from, to]. */\n opacity?: [number, number]\n /** Rotation in degrees as [from, to]. */\n rotate?: [number, number]\n /** Remap progress before it's applied (e.g. an ease-in-out). */\n ease?: (p: number) => number\n}\n\nexport function useParallax(ref: RefObject<HTMLElement | null>, options: ParallaxOptions = {}): void {\n const { y = [40, -40], x, scale, opacity, rotate } = options\n const easeRef = useRef(options.ease)\n easeRef.current = options.ease\n // Ranges are small tuples; a string key keeps the effect stable across\n // renders that pass a fresh array literal with the same values.\n const key = JSON.stringify([y, x, scale, opacity, rotate])\n\n useEffect(() => {\n const el = ref.current\n if (!el) return\n if (prefersReducedMotion()) return\n\n const between = (r: [number, number], q: number) => r[0] + (r[1] - r[0]) * q\n\n return registerScene(\n el,\n (p, info) => {\n const q = easeRef.current ? easeRef.current(p) : p\n let t = `translate3d(${x ? between(x, q) : 0}px, ${between(y, q)}px, 0)`\n if (scale) t += ` scale(${between(scale, q)})`\n if (rotate) t += ` rotate(${between(rotate, q)}deg)`\n el.style.transform = t\n if (opacity) el.style.opacity = String(between(opacity, q))\n // Promote to its own layer only while it's actually moving on screen.\n el.style.willChange = info.visible ? 'transform' : ''\n },\n { mode: 'view', lerp: 1 },\n )\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [ref, key])\n}\n\nexport interface ParallaxProps extends ParallaxOptions {\n children?: ReactNode\n /** Element to render. Default \"div\". */\n as?: ElementType\n className?: string\n style?: CSSProperties\n id?: string\n}\n\nexport function Parallax({ children, as = 'div', className, style, id, ...options }: ParallaxProps) {\n const ref = useRef<HTMLElement>(null)\n const Tag = as as ElementType\n useParallax(ref, options)\n return (\n <Tag ref={ref} id={id} className={className} style={style} data-sk-parallax=\"\">\n {children}\n </Tag>\n )\n}\n","'use client'\n\nimport {\n useEffect,\n useRef,\n type CSSProperties,\n type ElementType,\n type ReactNode,\n type RefObject,\n} from 'react'\nimport { registerScene, type SceneInfo, type SceneOptions } from './engine'\n\n/**\n * A pinned scene: a tall wrapper with a sticky, viewport-sized stage inside\n * it. As the visitor scrolls the wrapper's height, the stage stays put and\n * the scene's progress runs 0 → 1. This is the unit of scroll cinema.\n *\n * What it does for you on every frame:\n * - writes progress to a CSS custom property on the wrapper (`--sk-p` by\n * default), so choreography can be pure CSS: `opacity: var(--sk-p)`,\n * `transform: translateX(calc(var(--sk-p) * -40vw))` — no per-frame JS.\n * - calls `onProgress(p, info)` for anything that needs code (canvas\n * frame-scrub, three.js, DOM measured moves).\n *\n * The children are server-rendered. A \"use client\" component still renders\n * its children on the server when they arrive as props, so the copy inside\n * a scene is in the HTML for crawlers and for first paint. What you must\n * NOT do is load this (or a component containing it) through\n * `dynamic(..., { ssr: false })` — that de-opts the whole subtree to client\n * rendering and the copy disappears from the HTML.\n */\n\nexport interface UseScrollSceneOptions extends SceneOptions {\n /** CSS custom property to write progress to. Default \"--sk-p\"; false to skip. */\n cssVar?: string | false\n}\n\nexport function useScrollScene(\n ref: RefObject<HTMLElement | null>,\n onProgress?: (p: number, info: SceneInfo) => void,\n options: UseScrollSceneOptions = {},\n): void {\n const cbRef = useRef(onProgress)\n cbRef.current = onProgress\n const { continuous, reducedP, mode, lerp, cssVar } = options\n\n useEffect(() => {\n const el = ref.current\n if (!el) return\n const prop = cssVar === false ? null : (cssVar ?? '--sk-p')\n return registerScene(\n el,\n (p, info) => {\n if (prop) el.style.setProperty(prop, p.toFixed(4))\n cbRef.current?.(p, info)\n },\n { continuous, reducedP, mode, lerp },\n )\n }, [ref, continuous, reducedP, mode, lerp, cssVar])\n}\n\nexport interface ScrollSceneProps extends Omit<UseScrollSceneOptions, 'mode'> {\n children?: ReactNode\n /** Scroll length of the scene — the wrapper's height. Default \"300vh\". */\n length?: string\n /** Wrapper element. Default \"section\". */\n as?: ElementType\n className?: string\n style?: CSSProperties\n id?: string\n /** Class/style for the sticky stage that holds the children. */\n stageClassName?: string\n stageStyle?: CSSProperties\n onProgress?: (p: number, info: SceneInfo) => void\n}\n\nexport function ScrollScene({\n children,\n length = '300vh',\n as = 'section',\n className,\n style,\n id,\n stageClassName,\n stageStyle,\n onProgress,\n continuous,\n reducedP,\n lerp,\n cssVar,\n}: ScrollSceneProps) {\n const ref = useRef<HTMLElement>(null)\n const Tag = as as ElementType\n useScrollScene(ref, onProgress, { continuous, reducedP, lerp, cssVar, mode: 'pin' })\n return (\n <Tag\n ref={ref}\n id={id}\n className={className}\n style={{ position: 'relative', height: length, ...style }}\n data-sk-scene=\"\"\n >\n <div\n className={stageClassName}\n style={{ position: 'sticky', top: 0, height: '100svh', overflow: 'hidden', ...stageStyle }}\n data-sk-stage=\"\"\n >\n {children}\n </div>\n </Tag>\n )\n}\n"]}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The motion module's contracts:
3
+ *
4
+ * 1. Server HTML never hides content. Every primitive renders its children
5
+ * fully visible with no opacity/transform in the markup — that is the
6
+ * whole reason this module exists instead of the per-site reveals it
7
+ * replaces (crawlers, no-JS visitors, and LCP all read the server HTML).
8
+ * 2. The progress math is exact.
9
+ * 3. The tiers are real: nothing outside src/motion/gsap.ts imports gsap,
10
+ * nothing outside src/motion/three.ts imports three. A stray import in
11
+ * the zero-dep tier would force every consumer of ./motion to install a
12
+ * library it never asked for — bundlers resolve even dynamic import()
13
+ * at build time.
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=motion.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motion.test.d.ts","sourceRoot":"","sources":["../../src/motion/motion.test.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}