@sonordev/site-kit 5.0.0 → 5.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/agent-manifest.json +30 -6
- package/dist/AnalyticsProvider-2YV4ZVZD.js +31 -0
- package/dist/{AnalyticsProvider-TXM3DRLI.js.map → AnalyticsProvider-2YV4ZVZD.js.map} +1 -1
- package/dist/AnalyticsProvider-XSPROVHM.mjs +10 -0
- package/dist/{AnalyticsProvider-KCLRFOX6.mjs.map → AnalyticsProvider-XSPROVHM.mjs.map} +1 -1
- package/dist/{BlogViewTracker-J6LRGUHU.js → BlogViewTracker-BQBJTL5L.js} +6 -6
- package/dist/{BlogViewTracker-J6LRGUHU.js.map → BlogViewTracker-BQBJTL5L.js.map} +1 -1
- package/dist/{BlogViewTracker-PZWAWB3O.mjs → BlogViewTracker-FEAXIUEW.mjs} +5 -5
- package/dist/{BlogViewTracker-PZWAWB3O.mjs.map → BlogViewTracker-FEAXIUEW.mjs.map} +1 -1
- package/dist/ChatWidget-B2DI2OWH.mjs +11 -0
- package/dist/{ChatWidget-PMDPSZXG.mjs.map → ChatWidget-B2DI2OWH.mjs.map} +1 -1
- package/dist/ChatWidget-GPBFJ4A3.js +20 -0
- package/dist/{ChatWidget-LD54Z2PQ.js.map → ChatWidget-GPBFJ4A3.js.map} +1 -1
- package/dist/EngageWidget-JXJSFONK.js +18 -0
- package/dist/{EngageWidget-BF5NMQ5A.js.map → EngageWidget-JXJSFONK.js.map} +1 -1
- package/dist/EngageWidget-KF4HU4YA.mjs +9 -0
- package/dist/{EngageWidget-4CBFRN4Y.mjs.map → EngageWidget-KF4HU4YA.mjs.map} +1 -1
- package/dist/{FileField-VXADIOMN.js → FileField-22BB34L3.js} +6 -6
- package/dist/{FileField-VXADIOMN.js.map → FileField-22BB34L3.js.map} +1 -1
- package/dist/{FileField-FFRHS3XP.mjs → FileField-WI6SADBA.mjs} +5 -5
- package/dist/{FileField-FFRHS3XP.mjs.map → FileField-WI6SADBA.mjs.map} +1 -1
- package/dist/{FormSpotlight-KE46EDP5.mjs → FormSpotlight-6FZV6JOA.mjs} +3 -3
- package/dist/{FormSpotlight-KE46EDP5.mjs.map → FormSpotlight-6FZV6JOA.mjs.map} +1 -1
- package/dist/{FormSpotlight-JG4ZHS56.js → FormSpotlight-QCIN67NB.js} +15 -15
- package/dist/{FormSpotlight-JG4ZHS56.js.map → FormSpotlight-QCIN67NB.js.map} +1 -1
- package/dist/{FormStage-PZKWEXZE.mjs → FormStage-P3IIHVCC.mjs} +3 -3
- package/dist/{FormStage-PZKWEXZE.mjs.map → FormStage-P3IIHVCC.mjs.map} +1 -1
- package/dist/{FormStage-5Z53Z2WY.js → FormStage-SBQQZDW6.js} +13 -13
- package/dist/{FormStage-5Z53Z2WY.js.map → FormStage-SBQQZDW6.js.map} +1 -1
- package/dist/ManagedForm-6LII4DED.js +23 -0
- package/dist/{ManagedForm-E4WHMARH.js.map → ManagedForm-6LII4DED.js.map} +1 -1
- package/dist/ManagedForm-O3JRRWZ6.mjs +14 -0
- package/dist/{ManagedForm-VU2TKV6J.mjs.map → ManagedForm-O3JRRWZ6.mjs.map} +1 -1
- package/dist/{ManagedNewsletterForm-6DET3VGZ.mjs → ManagedNewsletterForm-FFFF5UEX.mjs} +7 -7
- package/dist/{ManagedNewsletterForm-6DET3VGZ.mjs.map → ManagedNewsletterForm-FFFF5UEX.mjs.map} +1 -1
- package/dist/{ManagedNewsletterForm-PG4EX3W6.js → ManagedNewsletterForm-Z7NYZPAN.js} +8 -8
- package/dist/{ManagedNewsletterForm-PG4EX3W6.js.map → ManagedNewsletterForm-Z7NYZPAN.js.map} +1 -1
- package/dist/{SignalCore-RZVTLUC2.mjs → SignalCore-IUOSVYUE.mjs} +5 -5
- package/dist/{SignalCore-RZVTLUC2.mjs.map → SignalCore-IUOSVYUE.mjs.map} +1 -1
- package/dist/{SignalCore-TCUVXVMN.js → SignalCore-WL5WKQEI.js} +11 -11
- package/dist/{SignalCore-TCUVXVMN.js.map → SignalCore-WL5WKQEI.js.map} +1 -1
- package/dist/SitemapSync-2O5UM4GM.mjs +8 -0
- package/dist/{SitemapSync-T75NAFB3.mjs.map → SitemapSync-2O5UM4GM.mjs.map} +1 -1
- package/dist/SitemapSync-LA67GKKS.js +17 -0
- package/dist/{SitemapSync-AJU4DM3G.js.map → SitemapSync-LA67GKKS.js.map} +1 -1
- package/dist/analytics/index.js +9 -9
- package/dist/analytics/index.mjs +4 -4
- package/dist/blog/index.d.ts +9 -5
- package/dist/blog/index.d.ts.map +1 -1
- package/dist/blog/index.js +20 -20
- package/dist/blog/index.mjs +3 -3
- package/dist/blog/server-ui.js +14 -14
- package/dist/blog/server-ui.mjs +2 -2
- package/dist/{chunk-LZY374FB.js → chunk-2OZ2SMZH.js} +4 -4
- package/dist/{chunk-LZY374FB.js.map → chunk-2OZ2SMZH.js.map} +1 -1
- package/dist/{chunk-BQY3FJ3R.js → chunk-3DQXXYCS.js} +8 -8
- package/dist/{chunk-BQY3FJ3R.js.map → chunk-3DQXXYCS.js.map} +1 -1
- package/dist/chunk-3PTKHSF7.mjs +6 -0
- package/dist/{chunk-JPTJGLKS.mjs.map → chunk-3PTKHSF7.mjs.map} +1 -1
- package/dist/{chunk-PPCTL4B5.mjs → chunk-4TU246Q4.mjs} +10 -3
- package/dist/chunk-4TU246Q4.mjs.map +1 -0
- package/dist/{chunk-3FZ76VI5.js → chunk-4YJFC6FC.js} +14 -14
- package/dist/{chunk-3FZ76VI5.js.map → chunk-4YJFC6FC.js.map} +1 -1
- package/dist/{chunk-7T4VMXKD.js → chunk-5I7UEXJL.js} +3 -3
- package/dist/{chunk-7T4VMXKD.js.map → chunk-5I7UEXJL.js.map} +1 -1
- package/dist/{chunk-MGPHBVOK.js → chunk-6ABEAO2K.js} +9 -9
- package/dist/{chunk-MGPHBVOK.js.map → chunk-6ABEAO2K.js.map} +1 -1
- package/dist/{chunk-SW6KWUNI.mjs → chunk-6RYCAW5B.mjs} +3 -3
- package/dist/{chunk-SW6KWUNI.mjs.map → chunk-6RYCAW5B.mjs.map} +1 -1
- package/dist/{chunk-MVJQ4ZA2.mjs → chunk-7MQR4KDL.mjs} +4 -4
- package/dist/{chunk-MVJQ4ZA2.mjs.map → chunk-7MQR4KDL.mjs.map} +1 -1
- package/dist/{chunk-FQ3JQV3M.js → chunk-7NMI7M56.js} +4 -4
- package/dist/{chunk-FQ3JQV3M.js.map → chunk-7NMI7M56.js.map} +1 -1
- package/dist/{chunk-XPAHKYX7.mjs → chunk-7OCQ4646.mjs} +3 -3
- package/dist/{chunk-XPAHKYX7.mjs.map → chunk-7OCQ4646.mjs.map} +1 -1
- package/dist/chunk-AEW7EFYU.js +147 -0
- package/dist/chunk-AEW7EFYU.js.map +1 -0
- package/dist/{chunk-OGPS3DKE.js → chunk-B7FHRTBA.js} +5 -5
- package/dist/{chunk-OGPS3DKE.js.map → chunk-B7FHRTBA.js.map} +1 -1
- package/dist/{chunk-SXPINIJG.mjs → chunk-BAFGZQWP.mjs} +4 -4
- package/dist/{chunk-SXPINIJG.mjs.map → chunk-BAFGZQWP.mjs.map} +1 -1
- package/dist/chunk-BIZT7AYK.js +8 -0
- package/dist/{chunk-S65JSRWW.js.map → chunk-BIZT7AYK.js.map} +1 -1
- package/dist/{chunk-EISVUD75.mjs → chunk-D2D3YKWT.mjs} +3 -3
- package/dist/{chunk-EISVUD75.mjs.map → chunk-D2D3YKWT.mjs.map} +1 -1
- package/dist/{chunk-FTBABL3T.mjs → chunk-DXFZA34N.mjs} +3 -3
- package/dist/{chunk-FTBABL3T.mjs.map → chunk-DXFZA34N.mjs.map} +1 -1
- package/dist/{chunk-4UHO6DPJ.mjs → chunk-F4DZH4E5.mjs} +4 -4
- package/dist/{chunk-4UHO6DPJ.mjs.map → chunk-F4DZH4E5.mjs.map} +1 -1
- package/dist/{chunk-QH3WVTEK.mjs → chunk-FDLFXHUU.mjs} +4 -4
- package/dist/{chunk-QH3WVTEK.mjs.map → chunk-FDLFXHUU.mjs.map} +1 -1
- package/dist/{chunk-MWXBRCM2.mjs → chunk-GCY6VPBG.mjs} +3 -3
- package/dist/{chunk-MWXBRCM2.mjs.map → chunk-GCY6VPBG.mjs.map} +1 -1
- package/dist/{chunk-LLKXPJSE.js → chunk-GF7CQMBL.js} +7 -7
- package/dist/{chunk-LLKXPJSE.js.map → chunk-GF7CQMBL.js.map} +1 -1
- package/dist/{chunk-FDWDXMJL.mjs → chunk-HHX72A2B.mjs} +3 -3
- package/dist/{chunk-FDWDXMJL.mjs.map → chunk-HHX72A2B.mjs.map} +1 -1
- package/dist/{chunk-UFURXSAI.mjs → chunk-ITV76G3L.mjs} +39 -3
- package/dist/chunk-ITV76G3L.mjs.map +1 -0
- package/dist/{chunk-N3RWPAR5.js → chunk-JJ6AI6LW.js} +5 -5
- package/dist/{chunk-N3RWPAR5.js.map → chunk-JJ6AI6LW.js.map} +1 -1
- package/dist/{chunk-AXYKBQVI.mjs → chunk-K447AIIB.mjs} +8 -8
- package/dist/{chunk-AXYKBQVI.mjs.map → chunk-K447AIIB.mjs.map} +1 -1
- package/dist/{chunk-6QQFEJIP.js → chunk-K6YQ73IX.js} +8 -8
- package/dist/{chunk-6QQFEJIP.js.map → chunk-K6YQ73IX.js.map} +1 -1
- package/dist/{chunk-FCKL5CF3.mjs → chunk-KC2FCI5V.mjs} +3 -3
- package/dist/{chunk-FCKL5CF3.mjs.map → chunk-KC2FCI5V.mjs.map} +1 -1
- package/dist/{chunk-YVE65W47.mjs → chunk-KHHMU4UH.mjs} +4 -4
- package/dist/{chunk-YVE65W47.mjs.map → chunk-KHHMU4UH.mjs.map} +1 -1
- package/dist/{chunk-HEUCDF3O.mjs → chunk-KIGIAA6Q.mjs} +3 -3
- package/dist/{chunk-HEUCDF3O.mjs.map → chunk-KIGIAA6Q.mjs.map} +1 -1
- package/dist/{chunk-5OHHYGD6.js → chunk-KMNIW4K4.js} +15 -15
- package/dist/{chunk-5OHHYGD6.js.map → chunk-KMNIW4K4.js.map} +1 -1
- package/dist/{chunk-PZE5L2FK.mjs → chunk-LCRWCOPI.mjs} +4 -4
- package/dist/{chunk-PZE5L2FK.mjs.map → chunk-LCRWCOPI.mjs.map} +1 -1
- package/dist/{chunk-62ODUWUX.js → chunk-LFBMFACZ.js} +40 -4
- package/dist/chunk-LFBMFACZ.js.map +1 -0
- package/dist/chunk-MLXUMVBK.mjs +142 -0
- package/dist/chunk-MLXUMVBK.mjs.map +1 -0
- package/dist/{chunk-3SMG4EXR.mjs → chunk-MOVMDHGE.mjs} +3 -3
- package/dist/{chunk-3SMG4EXR.mjs.map → chunk-MOVMDHGE.mjs.map} +1 -1
- package/dist/{chunk-KWH6RAVY.js → chunk-NQLE3V3T.js} +11 -11
- package/dist/{chunk-KWH6RAVY.js.map → chunk-NQLE3V3T.js.map} +1 -1
- package/dist/{chunk-5JNLZRLX.mjs → chunk-O2KN2SC7.mjs} +3 -3
- package/dist/{chunk-5JNLZRLX.mjs.map → chunk-O2KN2SC7.mjs.map} +1 -1
- package/dist/{chunk-IX5RAZWX.js → chunk-OQBDJRVP.js} +6 -6
- package/dist/{chunk-IX5RAZWX.js.map → chunk-OQBDJRVP.js.map} +1 -1
- package/dist/{chunk-MPO6TRLS.js → chunk-PEIWCJXS.js} +14 -14
- package/dist/{chunk-MPO6TRLS.js.map → chunk-PEIWCJXS.js.map} +1 -1
- package/dist/{chunk-VACFVPNF.js → chunk-RE54UKET.js} +14 -14
- package/dist/{chunk-VACFVPNF.js.map → chunk-RE54UKET.js.map} +1 -1
- package/dist/{chunk-4D2G5ZNP.js → chunk-RMLRZOVE.js} +15 -15
- package/dist/{chunk-4D2G5ZNP.js.map → chunk-RMLRZOVE.js.map} +1 -1
- package/dist/{chunk-GCZMDY2T.js → chunk-ULGTZ2VU.js} +3 -3
- package/dist/{chunk-GCZMDY2T.js.map → chunk-ULGTZ2VU.js.map} +1 -1
- package/dist/{chunk-JY3KZDEM.js → chunk-VTEIXKBA.js} +3 -3
- package/dist/{chunk-JY3KZDEM.js.map → chunk-VTEIXKBA.js.map} +1 -1
- package/dist/{chunk-YGRHEEPX.mjs → chunk-W7QMCG2A.mjs} +7 -7
- package/dist/{chunk-YGRHEEPX.mjs.map → chunk-W7QMCG2A.mjs.map} +1 -1
- package/dist/{chunk-HCN2US4M.js → chunk-WZ6QNL2D.js} +18 -18
- package/dist/{chunk-HCN2US4M.js.map → chunk-WZ6QNL2D.js.map} +1 -1
- package/dist/{chunk-YSZB2DRX.mjs → chunk-X4H2RAIQ.mjs} +3 -3
- package/dist/{chunk-YSZB2DRX.mjs.map → chunk-X4H2RAIQ.mjs.map} +1 -1
- package/dist/{chunk-JIUVBSQZ.js → chunk-X6SAM7CR.js} +3 -3
- package/dist/{chunk-JIUVBSQZ.js.map → chunk-X6SAM7CR.js.map} +1 -1
- package/dist/{chunk-J4JXAFSW.mjs → chunk-XRONA2QL.mjs} +3 -3
- package/dist/{chunk-J4JXAFSW.mjs.map → chunk-XRONA2QL.mjs.map} +1 -1
- package/dist/{chunk-5JQLLF2T.js → chunk-XYZZJZGS.js} +12 -12
- package/dist/{chunk-5JQLLF2T.js.map → chunk-XYZZJZGS.js.map} +1 -1
- package/dist/{chunk-DX6D7HDI.js → chunk-XZI6KUB3.js} +4 -4
- package/dist/{chunk-DX6D7HDI.js.map → chunk-XZI6KUB3.js.map} +1 -1
- package/dist/{chunk-UV6KQUSL.mjs → chunk-YDIINUWD.mjs} +3 -3
- package/dist/{chunk-UV6KQUSL.mjs.map → chunk-YDIINUWD.mjs.map} +1 -1
- package/dist/{chunk-QI2H5KK6.mjs → chunk-YUOVAWCL.mjs} +4 -4
- package/dist/{chunk-QI2H5KK6.mjs.map → chunk-YUOVAWCL.mjs.map} +1 -1
- package/dist/{chunk-UABMMR7U.js → chunk-Z33JXJTJ.js} +10 -3
- package/dist/chunk-Z33JXJTJ.js.map +1 -0
- package/dist/cli/index.js +3 -3
- package/dist/cli/index.mjs +1 -1
- package/dist/client/index.js +4 -4
- package/dist/client/index.mjs +3 -3
- package/dist/commerce/index.js +56 -56
- package/dist/commerce/index.mjs +5 -5
- package/dist/commerce/server-result.test.d.ts +2 -0
- package/dist/commerce/server-result.test.d.ts.map +1 -0
- package/dist/commerce/server.d.ts +51 -0
- package/dist/commerce/server.d.ts.map +1 -1
- package/dist/commerce/server.js +57 -24
- package/dist/commerce/server.js.map +1 -1
- package/dist/commerce/server.mjs +54 -25
- package/dist/commerce/server.mjs.map +1 -1
- package/dist/engage/index.js +13 -13
- package/dist/engage/index.mjs +7 -7
- package/dist/fleet/index.js +8 -8
- package/dist/fleet/index.mjs +4 -4
- package/dist/forms/ga4-identity.d.ts +31 -0
- package/dist/forms/ga4-identity.d.ts.map +1 -0
- package/dist/forms/ga4-identity.test.d.ts +2 -0
- package/dist/forms/ga4-identity.test.d.ts.map +1 -0
- package/dist/forms/index.js +22 -22
- package/dist/forms/index.mjs +9 -9
- package/dist/forms/server.js +10 -10
- package/dist/forms/server.mjs +8 -8
- package/dist/forms/static.js +7 -7
- package/dist/forms/static.mjs +6 -6
- package/dist/forms/submitForm.d.ts.map +1 -1
- package/dist/forms/types.d.ts +13 -0
- package/dist/forms/types.d.ts.map +1 -1
- package/dist/images/index.js +11 -11
- package/dist/images/index.mjs +4 -4
- package/dist/index.js +63 -63
- package/dist/index.mjs +9 -9
- package/dist/layout/client.js +8 -8
- package/dist/layout/client.mjs +7 -7
- package/dist/layout/index.js +10 -10
- package/dist/layout/index.mjs +8 -8
- package/dist/llms/generateLLMsTxt.d.ts.map +1 -1
- package/dist/llms/humanize-industry.d.ts +9 -0
- package/dist/llms/humanize-industry.d.ts.map +1 -0
- package/dist/llms/humanize-industry.test.d.ts +2 -0
- package/dist/llms/humanize-industry.test.d.ts.map +1 -0
- package/dist/llms/index.js +12 -12
- package/dist/llms/index.mjs +2 -2
- package/dist/maps/index.js +5 -5
- package/dist/maps/index.mjs +3 -3
- package/dist/motion/Parallax.d.ts +42 -0
- package/dist/motion/Parallax.d.ts.map +1 -0
- package/dist/motion/Reveal.d.ts +59 -0
- package/dist/motion/Reveal.d.ts.map +1 -0
- package/dist/motion/ScrollScene.d.ts +42 -0
- package/dist/motion/ScrollScene.d.ts.map +1 -0
- package/dist/motion/engine.d.ts +74 -0
- package/dist/motion/engine.d.ts.map +1 -0
- package/dist/motion/failsafe.d.ts +20 -0
- package/dist/motion/failsafe.d.ts.map +1 -0
- package/dist/motion/gsap.d.ts +84 -0
- package/dist/motion/gsap.d.ts.map +1 -0
- package/dist/motion/gsap.js +103 -0
- package/dist/motion/gsap.js.map +1 -0
- package/dist/motion/gsap.mjs +99 -0
- package/dist/motion/gsap.mjs.map +1 -0
- package/dist/motion/index.d.ts +31 -0
- package/dist/motion/index.d.ts.map +1 -0
- package/dist/motion/index.js +252 -0
- package/dist/motion/index.js.map +1 -0
- package/dist/motion/index.mjs +230 -0
- package/dist/motion/index.mjs.map +1 -0
- package/dist/motion/motion.test.d.ts +16 -0
- package/dist/motion/motion.test.d.ts.map +1 -0
- package/dist/motion/three.d.ts +105 -0
- package/dist/motion/three.d.ts.map +1 -0
- package/dist/motion/three.js +150 -0
- package/dist/motion/three.js.map +1 -0
- package/dist/motion/three.mjs +145 -0
- package/dist/motion/three.mjs.map +1 -0
- package/dist/search/index.js +4 -4
- package/dist/search/index.mjs +3 -3
- package/dist/seo/client.js +5 -5
- package/dist/seo/client.mjs +4 -4
- package/dist/seo/index.js +5 -5
- package/dist/seo/index.mjs +4 -4
- package/dist/server/index.js +3 -3
- package/dist/server/index.mjs +2 -2
- package/dist/shared/build-entries.d.ts +7 -1
- package/dist/shared/build-entries.d.ts.map +1 -1
- package/dist/shared/version.d.ts +1 -1
- package/dist/signal/index.js +11 -11
- package/dist/signal/index.mjs +2 -2
- package/dist/sitemap/index.js +2 -2
- package/dist/sitemap/index.mjs +1 -1
- package/dist/sync/index.js +16 -16
- package/dist/sync/index.mjs +4 -4
- package/package.json +28 -2
- package/skills/site-kit/SKILL.md +6 -0
- package/dist/AnalyticsProvider-KCLRFOX6.mjs +0 -10
- package/dist/AnalyticsProvider-TXM3DRLI.js +0 -31
- package/dist/ChatWidget-LD54Z2PQ.js +0 -20
- package/dist/ChatWidget-PMDPSZXG.mjs +0 -11
- package/dist/EngageWidget-4CBFRN4Y.mjs +0 -9
- package/dist/EngageWidget-BF5NMQ5A.js +0 -18
- package/dist/ManagedForm-E4WHMARH.js +0 -23
- package/dist/ManagedForm-VU2TKV6J.mjs +0 -14
- package/dist/SitemapSync-AJU4DM3G.js +0 -17
- package/dist/SitemapSync-T75NAFB3.mjs +0 -8
- package/dist/chunk-62ODUWUX.js.map +0 -1
- package/dist/chunk-JPTJGLKS.mjs +0 -6
- package/dist/chunk-PPCTL4B5.mjs.map +0 -1
- package/dist/chunk-S65JSRWW.js +0 -8
- package/dist/chunk-UABMMR7U.js.map +0 -1
- package/dist/chunk-UFURXSAI.mjs.map +0 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type CSSProperties, type ElementType, type ReactNode, type RefObject } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Scroll-linked parallax with no animation library.
|
|
4
|
+
*
|
|
5
|
+
* The element's progress through the viewport (0 as its top enters at the
|
|
6
|
+
* bottom, 1 as its bottom leaves at the top) is mapped onto transform and
|
|
7
|
+
* opacity — compositor-only properties, so a page full of these never
|
|
8
|
+
* triggers layout or paint. Driven by the shared engine, so thirty of them
|
|
9
|
+
* cost one requestAnimationFrame.
|
|
10
|
+
*
|
|
11
|
+
* Server-rendered exactly as authored: no offset, no hidden state. Under
|
|
12
|
+
* prefers-reduced-motion nothing registers and the element stays put.
|
|
13
|
+
*
|
|
14
|
+
* Replaces the per-site ParallaxImage / ParallaxY components: wrap the
|
|
15
|
+
* image in an overflow-hidden frame and give <Parallax> a scale so the
|
|
16
|
+
* travel never shows the frame's edges.
|
|
17
|
+
*/
|
|
18
|
+
export interface ParallaxOptions {
|
|
19
|
+
/** Vertical travel in px as [at p=0, at p=1]. Default [40, -40]. */
|
|
20
|
+
y?: [number, number];
|
|
21
|
+
/** Horizontal travel in px. */
|
|
22
|
+
x?: [number, number];
|
|
23
|
+
/** Scale as [from, to]. */
|
|
24
|
+
scale?: [number, number];
|
|
25
|
+
/** Opacity as [from, to]. */
|
|
26
|
+
opacity?: [number, number];
|
|
27
|
+
/** Rotation in degrees as [from, to]. */
|
|
28
|
+
rotate?: [number, number];
|
|
29
|
+
/** Remap progress before it's applied (e.g. an ease-in-out). */
|
|
30
|
+
ease?: (p: number) => number;
|
|
31
|
+
}
|
|
32
|
+
export declare function useParallax(ref: RefObject<HTMLElement | null>, options?: ParallaxOptions): void;
|
|
33
|
+
export interface ParallaxProps extends ParallaxOptions {
|
|
34
|
+
children?: ReactNode;
|
|
35
|
+
/** Element to render. Default "div". */
|
|
36
|
+
as?: ElementType;
|
|
37
|
+
className?: string;
|
|
38
|
+
style?: CSSProperties;
|
|
39
|
+
id?: string;
|
|
40
|
+
}
|
|
41
|
+
export declare function Parallax({ children, as, className, style, id, ...options }: ParallaxProps): import("react").JSX.Element;
|
|
42
|
+
//# sourceMappingURL=Parallax.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Parallax.d.ts","sourceRoot":"","sources":["../../src/motion/Parallax.tsx"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AAGd;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,eAAe;IAC9B,oEAAoE;IACpE,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpB,+BAA+B;IAC/B,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACxB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1B,yCAAyC;IACzC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACzB,gEAAgE;IAChE,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;CAC7B;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EAAE,OAAO,GAAE,eAAoB,GAAG,IAAI,CA+BnG;AAED,MAAM,WAAW,aAAc,SAAQ,eAAe;IACpD,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,wCAAwC;IACxC,EAAE,CAAC,EAAE,WAAW,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,EAAE,CAAC,EAAE,MAAM,CAAA;CACZ;AAED,wBAAgB,QAAQ,CAAC,EAAE,QAAQ,EAAE,EAAU,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,OAAO,EAAE,EAAE,aAAa,+BASjG"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { type CSSProperties, type ElementType, type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* <Reveal> — scroll-entrance reveal with no animation library.
|
|
4
|
+
*
|
|
5
|
+
* The SEO contract, in order of importance:
|
|
6
|
+
*
|
|
7
|
+
* 1. The server HTML is fully visible. Nothing is hidden by a stylesheet or
|
|
8
|
+
* an inline style at render time, so crawlers, no-JS visitors, and the
|
|
9
|
+
* LCP measurement all see the finished page.
|
|
10
|
+
* 2. Above-the-fold content is never touched. On mount, one
|
|
11
|
+
* IntersectionObserver pass asks whether the element is already on
|
|
12
|
+
* screen; if it is, this component does nothing at all.
|
|
13
|
+
* 3. Only below-the-fold content is hidden (offscreen, so nobody sees the
|
|
14
|
+
* swap) and revealed with a compositor-only CSS transition on opacity
|
|
15
|
+
* and transform as it scrolls in.
|
|
16
|
+
* 4. A headless renderer that never scrolls gets the content back after
|
|
17
|
+
* 2.5s (see ./failsafe), so the indexed snapshot is never transparent.
|
|
18
|
+
* 5. prefers-reduced-motion disables all of it.
|
|
19
|
+
*
|
|
20
|
+
* Replaces the per-site Reveal / ScrollReveal / RevealOnScroll components.
|
|
21
|
+
*/
|
|
22
|
+
export type RevealDirection = 'up' | 'down' | 'left' | 'right' | 'none';
|
|
23
|
+
export interface RevealProps {
|
|
24
|
+
children?: ReactNode;
|
|
25
|
+
/** Element to render. Default "div". */
|
|
26
|
+
as?: ElementType;
|
|
27
|
+
className?: string;
|
|
28
|
+
style?: CSSProperties;
|
|
29
|
+
id?: string;
|
|
30
|
+
/** Where the element travels in from. Default "up" (starts lower). */
|
|
31
|
+
from?: RevealDirection;
|
|
32
|
+
/** Travel distance in px. Default 24. */
|
|
33
|
+
distance?: number;
|
|
34
|
+
/** Seconds before the transition starts. Default 0. */
|
|
35
|
+
delay?: number;
|
|
36
|
+
/** Transition length in seconds. Default 0.7. */
|
|
37
|
+
duration?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Reveal the element's direct children one after another instead of the
|
|
40
|
+
* element itself. `true` = 0.08s apart; a number = that many seconds.
|
|
41
|
+
*/
|
|
42
|
+
stagger?: boolean | number;
|
|
43
|
+
/** Play once (default) or re-hide when the element scrolls back out. */
|
|
44
|
+
once?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* How far up the viewport the element's top must travel before it
|
|
47
|
+
* reveals, as a fraction of viewport height. 0.15 (default) = reveal when
|
|
48
|
+
* the top crosses 85% down the screen.
|
|
49
|
+
*/
|
|
50
|
+
threshold?: number;
|
|
51
|
+
/** Starting scale, e.g. 0.96. Off by default. */
|
|
52
|
+
scale?: number;
|
|
53
|
+
/** Starting opacity. Default 0. */
|
|
54
|
+
opacity?: number;
|
|
55
|
+
/** CSS easing. Default an ease-out-quint curve. */
|
|
56
|
+
easing?: string;
|
|
57
|
+
}
|
|
58
|
+
export declare function Reveal({ children, as, className, style, id, from, distance, delay, duration, stagger, once, threshold, scale, opacity, easing, }: RevealProps): import("react").JSX.Element;
|
|
59
|
+
//# sourceMappingURL=Reveal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Reveal.d.ts","sourceRoot":"","sources":["../../src/motion/Reveal.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAqB,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAI/F;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAA;AAEvE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,wCAAwC;IACxC,EAAE,CAAC,EAAE,WAAW,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,sEAAsE;IACtE,IAAI,CAAC,EAAE,eAAe,CAAA;IACtB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;IAC1B,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,CAAA;IACd;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAeD,wBAAgB,MAAM,CAAC,EACrB,QAAQ,EACR,EAAU,EACV,SAAS,EACT,KAAK,EACL,EAAE,EACF,IAAW,EACX,QAAa,EACb,KAAS,EACT,QAAc,EACd,OAAe,EACf,IAAW,EACX,SAAgB,EAChB,KAAK,EACL,OAAW,EACX,MAAuB,GACxB,EAAE,WAAW,+BA2Gb"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type CSSProperties, type ElementType, type ReactNode, type RefObject } from 'react';
|
|
2
|
+
import { type SceneInfo, type SceneOptions } from './engine';
|
|
3
|
+
/**
|
|
4
|
+
* A pinned scene: a tall wrapper with a sticky, viewport-sized stage inside
|
|
5
|
+
* it. As the visitor scrolls the wrapper's height, the stage stays put and
|
|
6
|
+
* the scene's progress runs 0 → 1. This is the unit of scroll cinema.
|
|
7
|
+
*
|
|
8
|
+
* What it does for you on every frame:
|
|
9
|
+
* - writes progress to a CSS custom property on the wrapper (`--sk-p` by
|
|
10
|
+
* default), so choreography can be pure CSS: `opacity: var(--sk-p)`,
|
|
11
|
+
* `transform: translateX(calc(var(--sk-p) * -40vw))` — no per-frame JS.
|
|
12
|
+
* - calls `onProgress(p, info)` for anything that needs code (canvas
|
|
13
|
+
* frame-scrub, three.js, DOM measured moves).
|
|
14
|
+
*
|
|
15
|
+
* The children are server-rendered. A "use client" component still renders
|
|
16
|
+
* its children on the server when they arrive as props, so the copy inside
|
|
17
|
+
* a scene is in the HTML for crawlers and for first paint. What you must
|
|
18
|
+
* NOT do is load this (or a component containing it) through
|
|
19
|
+
* `dynamic(..., { ssr: false })` — that de-opts the whole subtree to client
|
|
20
|
+
* rendering and the copy disappears from the HTML.
|
|
21
|
+
*/
|
|
22
|
+
export interface UseScrollSceneOptions extends SceneOptions {
|
|
23
|
+
/** CSS custom property to write progress to. Default "--sk-p"; false to skip. */
|
|
24
|
+
cssVar?: string | false;
|
|
25
|
+
}
|
|
26
|
+
export declare function useScrollScene(ref: RefObject<HTMLElement | null>, onProgress?: (p: number, info: SceneInfo) => void, options?: UseScrollSceneOptions): void;
|
|
27
|
+
export interface ScrollSceneProps extends Omit<UseScrollSceneOptions, 'mode'> {
|
|
28
|
+
children?: ReactNode;
|
|
29
|
+
/** Scroll length of the scene — the wrapper's height. Default "300vh". */
|
|
30
|
+
length?: string;
|
|
31
|
+
/** Wrapper element. Default "section". */
|
|
32
|
+
as?: ElementType;
|
|
33
|
+
className?: string;
|
|
34
|
+
style?: CSSProperties;
|
|
35
|
+
id?: string;
|
|
36
|
+
/** Class/style for the sticky stage that holds the children. */
|
|
37
|
+
stageClassName?: string;
|
|
38
|
+
stageStyle?: CSSProperties;
|
|
39
|
+
onProgress?: (p: number, info: SceneInfo) => void;
|
|
40
|
+
}
|
|
41
|
+
export declare function ScrollScene({ children, length, as, className, style, id, stageClassName, stageStyle, onProgress, continuous, reducedP, lerp, cssVar, }: ScrollSceneProps): import("react").JSX.Element;
|
|
42
|
+
//# sourceMappingURL=ScrollScene.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScrollScene.d.ts","sourceRoot":"","sources":["../../src/motion/ScrollScene.tsx"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AACd,OAAO,EAAiB,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,UAAU,CAAA;AAE3E;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,qBAAsB,SAAQ,YAAY;IACzD,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;CACxB;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EAClC,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,KAAK,IAAI,EACjD,OAAO,GAAE,qBAA0B,GAClC,IAAI,CAkBN;AAED,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC;IAC3E,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0CAA0C;IAC1C,EAAE,CAAC,EAAE,WAAW,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,gEAAgE;IAChE,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,aAAa,CAAA;IAC1B,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;CAClD;AAED,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,MAAgB,EAChB,EAAc,EACd,SAAS,EACT,KAAK,EACL,EAAE,EACF,cAAc,EACd,UAAU,EACV,UAAU,EACV,UAAU,EACV,QAAQ,EACR,IAAI,EACJ,MAAM,GACP,EAAE,gBAAgB,+BAqBlB"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sonordev/site-kit/motion — the scroll engine.
|
|
3
|
+
*
|
|
4
|
+
* One idea, applied everywhere: pin a scene, turn scroll into p in [0,1],
|
|
5
|
+
* render(p). Every motion primitive in this module (Reveal, Parallax,
|
|
6
|
+
* ScrollScene, the GSAP and three.js tiers) sits on this loop.
|
|
7
|
+
*
|
|
8
|
+
* Rules the engine enforces so every site inherits them:
|
|
9
|
+
*
|
|
10
|
+
* - Native scroll only. The wheel is never hijacked and the body is never
|
|
11
|
+
* transformed; the liquid feel comes from each scene lerping its rendered
|
|
12
|
+
* p toward the real scroll position.
|
|
13
|
+
* - One shared requestAnimationFrame loop drives every visible scene and
|
|
14
|
+
* sleeps when everything has settled. A page with thirty parallax layers
|
|
15
|
+
* costs one rAF, not thirty.
|
|
16
|
+
* - Offscreen scenes (beyond a 35% viewport margin) are not rendered at all.
|
|
17
|
+
* - prefers-reduced-motion holds each scene at a fixed representative frame
|
|
18
|
+
* instead of scrubbing, and the loop stays asleep.
|
|
19
|
+
* - Nothing here touches the DOM at import time, so it is safe in any module
|
|
20
|
+
* graph a server component reaches; scenes register from effects.
|
|
21
|
+
*
|
|
22
|
+
* Zero dependencies, ~2KB. Extracted from the upforgelabs.com engine
|
|
23
|
+
* (components/cinema/engine.ts) — that repo's docs/SCROLL-CINEMA.md is the
|
|
24
|
+
* full playbook for building scenes on top of it.
|
|
25
|
+
*/
|
|
26
|
+
export type SceneMode = 'pin' | 'view';
|
|
27
|
+
export interface SceneInfo {
|
|
28
|
+
/** The un-smoothed progress the scene is easing toward. */
|
|
29
|
+
target: number;
|
|
30
|
+
/** False on the single frame rendered as the scene leaves the margin. */
|
|
31
|
+
visible: boolean;
|
|
32
|
+
}
|
|
33
|
+
export type SceneRender = (p: number, info: SceneInfo) => void;
|
|
34
|
+
export interface SceneOptions {
|
|
35
|
+
/** Keep rendering every frame while visible (shader time, particles). */
|
|
36
|
+
continuous?: boolean;
|
|
37
|
+
/** Frame to hold under prefers-reduced-motion. Default 0.55. */
|
|
38
|
+
reducedP?: number;
|
|
39
|
+
/**
|
|
40
|
+
* "pin": progress across a tall sticky wrapper — 0 when its top reaches
|
|
41
|
+
* the top of the viewport, 1 when its bottom does (default).
|
|
42
|
+
* "view": progress of a normal block traveling through the viewport —
|
|
43
|
+
* 0 as its top enters at the bottom, 1 as its bottom leaves at the top.
|
|
44
|
+
*/
|
|
45
|
+
mode?: SceneMode;
|
|
46
|
+
/**
|
|
47
|
+
* Per-frame interpolation toward the real scroll position, in (0, 1].
|
|
48
|
+
* Lower is more liquid, 1 is locked to the scrollbar. Default 0.16.
|
|
49
|
+
*/
|
|
50
|
+
lerp?: number;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Pure progress math, exported so it can be unit-tested and reused by
|
|
54
|
+
* anything that wants the same mapping without registering a scene.
|
|
55
|
+
*/
|
|
56
|
+
export declare function sceneProgress(mode: SceneMode, top: number, height: number, scrollY: number, viewportHeight: number): number;
|
|
57
|
+
/** True when the visitor asked for reduced motion. Always false on the server. */
|
|
58
|
+
export declare function prefersReducedMotion(): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Re-measure every scene and redraw. Call after a layout change the engine
|
|
61
|
+
* cannot see — an accordion opening above a scene, images without
|
|
62
|
+
* dimensions settling, a font swap outside document.fonts.
|
|
63
|
+
*/
|
|
64
|
+
export declare function refreshScenes(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Register a scene. Returns an unregister function for effect cleanup.
|
|
67
|
+
*
|
|
68
|
+
* `pin` is the element whose position drives progress: the tall wrapper of
|
|
69
|
+
* a sticky stage in "pin" mode, or the block itself in "view" mode. The
|
|
70
|
+
* callback runs only while the pin is within 35% of the viewport, plus one
|
|
71
|
+
* final frame as it leaves.
|
|
72
|
+
*/
|
|
73
|
+
export declare function registerScene(pin: HTMLElement, cb: SceneRender, opts?: SceneOptions): () => void;
|
|
74
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/motion/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,MAAM,CAAA;AAEtC,MAAM,WAAW,SAAS;IACxB,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAA;IACd,yEAAyE;IACzE,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;AAE9D,MAAM,WAAW,YAAY;IAC3B,yEAAyE;IACzE,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AA0BD;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,SAAS,EACf,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,GACrB,MAAM,CAKR;AAiGD,kFAAkF;AAClF,wBAAgB,oBAAoB,IAAI,OAAO,CAI9C;AAED;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAIpC;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,WAAW,EAChB,EAAE,EAAE,WAAW,EACf,IAAI,GAAE,YAAiB,GACtB,MAAM,IAAI,CA+BZ"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renderer failsafe for scroll-entrance reveals.
|
|
3
|
+
*
|
|
4
|
+
* Headless renderers — Google's Web Rendering Service included — execute
|
|
5
|
+
* JavaScript but never scroll, so a scroll-triggered reveal would leave
|
|
6
|
+
* below-the-fold content transparent in the rendered snapshot that gets
|
|
7
|
+
* indexed. (Measured at ~85 transparent elements on one page before this
|
|
8
|
+
* guard existed.) If the visitor hasn't scrolled shortly after a reveal
|
|
9
|
+
* arms, we assume nobody is going to and show the content. Real visitors
|
|
10
|
+
* scroll well inside the window, so animations are unaffected.
|
|
11
|
+
*
|
|
12
|
+
* Single source of truth for every reveal system in the kit. Ported from
|
|
13
|
+
* upforge.io's lib/reveal-failsafe.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Run `fn` after `ms` milliseconds unless the visitor scrolls first.
|
|
17
|
+
* Returns a cancel function for effect cleanups.
|
|
18
|
+
*/
|
|
19
|
+
export declare function onNoScroll(fn: () => void, ms?: number): () => void;
|
|
20
|
+
//# sourceMappingURL=failsafe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"failsafe.d.ts","sourceRoot":"","sources":["../../src/motion/failsafe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAiBH;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,SAAO,GAAG,MAAM,IAAI,CAOhE"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sonordev/site-kit/motion/gsap — the Upforge motion standard, tier 1.
|
|
3
|
+
*
|
|
4
|
+
* GSAP for the moments that earn it: sequenced timelines, SplitText,
|
|
5
|
+
* Flip, MorphSVG. Requires the optional peer `gsap` (all plugins are free
|
|
6
|
+
* since 3.13):
|
|
7
|
+
*
|
|
8
|
+
* npm i gsap
|
|
9
|
+
*
|
|
10
|
+
* A site that never imports this subpath never installs gsap. NOTHING
|
|
11
|
+
* outside this file may import from 'gsap' — that is what keeps the tier
|
|
12
|
+
* boundary real (src/motion/motion.test.tsx enforces it).
|
|
13
|
+
*
|
|
14
|
+
* Cost and where it goes: gsap core + ScrollTrigger is ~46KB gzipped.
|
|
15
|
+
* `useGsap` loads it only when its element comes within 200px of the
|
|
16
|
+
* viewport, so it never sits on the LCP critical path, and it must only be
|
|
17
|
+
* used BELOW the fold. First-paint content renders static.
|
|
18
|
+
*
|
|
19
|
+
* Not included on purpose: ScrollSmoother. It drives scrolling by
|
|
20
|
+
* transforming the page body, which fights native scroll, costs INP on
|
|
21
|
+
* mobile, and breaks every scroll-geometry read on the page. The engine's
|
|
22
|
+
* per-scene lerp gives the liquid feel without hijacking anything.
|
|
23
|
+
*/
|
|
24
|
+
import { type DependencyList, type RefObject } from 'react';
|
|
25
|
+
type GsapModule = typeof import('gsap');
|
|
26
|
+
type ScrollTriggerModule = typeof import('gsap/ScrollTrigger');
|
|
27
|
+
export type Gsap = GsapModule['gsap'];
|
|
28
|
+
export type ScrollTriggerStatic = ScrollTriggerModule['ScrollTrigger'];
|
|
29
|
+
export interface GsapBundle {
|
|
30
|
+
gsap: Gsap;
|
|
31
|
+
ScrollTrigger: ScrollTriggerStatic;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Load gsap + ScrollTrigger once, register the plugin, and share the
|
|
35
|
+
* promise. Safe to call from anywhere; resolves the same bundle every time.
|
|
36
|
+
*/
|
|
37
|
+
export declare function loadGsap(): Promise<GsapBundle>;
|
|
38
|
+
export interface GsapSetupContext extends GsapBundle {
|
|
39
|
+
/** The element the hook is attached to — use it as the ScrollTrigger trigger and the selector scope. */
|
|
40
|
+
el: HTMLElement;
|
|
41
|
+
}
|
|
42
|
+
export interface UseGsapOptions {
|
|
43
|
+
/** Preload margin: load gsap when the element is this close. Default "200px 0px". */
|
|
44
|
+
near?: string;
|
|
45
|
+
/** "skip" (default) does nothing under prefers-reduced-motion; "run" lets setup decide. */
|
|
46
|
+
reducedMotion?: 'skip' | 'run';
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Run a GSAP setup against an element, lazily and safely:
|
|
50
|
+
*
|
|
51
|
+
* - gsap loads only when the element nears the viewport
|
|
52
|
+
* - setup runs inside `gsap.context(el)`, so selectors are scoped and
|
|
53
|
+
* everything it creates is reverted on unmount (including ScrollTriggers)
|
|
54
|
+
* - the element must be server-rendered and visible; hide things inside
|
|
55
|
+
* `setup` with `gsap.set`, never with a stylesheet
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* const ref = useRef<HTMLDivElement>(null)
|
|
59
|
+
* useGsap(ref, ({ gsap, el }) => {
|
|
60
|
+
* gsap.from(el.querySelectorAll('[data-line]'), {
|
|
61
|
+
* yPercent: 100, opacity: 0, stagger: 0.06, duration: 0.8, ease: 'power3.out',
|
|
62
|
+
* scrollTrigger: { trigger: el, start: 'top 80%' },
|
|
63
|
+
* })
|
|
64
|
+
* })
|
|
65
|
+
*/
|
|
66
|
+
export declare function useGsap(ref: RefObject<HTMLElement | null>, setup: (ctx: GsapSetupContext) => void | (() => void), deps?: DependencyList, options?: UseGsapOptions): void;
|
|
67
|
+
export interface ExpandCollapseOptions {
|
|
68
|
+
duration?: number;
|
|
69
|
+
ease?: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Animate expand/collapse without mount/unmount. Content stays in the DOM
|
|
73
|
+
* (so it stays indexable) with overflow hidden; gsap animates height and
|
|
74
|
+
* opacity, and loads on the first toggle, not at mount.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* const { contentRef } = useExpandCollapse(isOpen)
|
|
78
|
+
* <div ref={contentRef}>{children}</div>
|
|
79
|
+
*/
|
|
80
|
+
export declare function useExpandCollapse(isOpen: boolean, options?: ExpandCollapseOptions): {
|
|
81
|
+
contentRef: RefObject<HTMLDivElement | null>;
|
|
82
|
+
};
|
|
83
|
+
export {};
|
|
84
|
+
//# sourceMappingURL=gsap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gsap.d.ts","sourceRoot":"","sources":["../../src/motion/gsap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,EAAqB,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAG9E,KAAK,UAAU,GAAG,cAAc,MAAM,CAAC,CAAA;AACvC,KAAK,mBAAmB,GAAG,cAAc,oBAAoB,CAAC,CAAA;AAE9D,MAAM,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAA;AACrC,MAAM,MAAM,mBAAmB,GAAG,mBAAmB,CAAC,eAAe,CAAC,CAAA;AAEtE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,IAAI,CAAA;IACV,aAAa,EAAE,mBAAmB,CAAA;CACnC;AAID;;;GAGG;AACH,wBAAgB,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC,CAU9C;AAED,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAClD,wGAAwG;IACxG,EAAE,EAAE,WAAW,CAAA;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,qFAAqF;IACrF,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,2FAA2F;IAC3F,aAAa,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;CAC/B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,OAAO,CACrB,GAAG,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EAClC,KAAK,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,EACrD,IAAI,GAAE,cAAmB,EACzB,OAAO,GAAE,cAAmB,GAC3B,IAAI,CAqCN;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,OAAO,EACf,OAAO,GAAE,qBAA0B,GAClC;IAAE,UAAU,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;CAAE,CAiDlD"}
|
|
@@ -0,0 +1,103 @@
|
|
|
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
|
+
|
|
8
|
+
var pending = null;
|
|
9
|
+
function loadGsap() {
|
|
10
|
+
if (!pending) {
|
|
11
|
+
pending = Promise.all([import('gsap'), import('gsap/ScrollTrigger')]).then(([g, st]) => {
|
|
12
|
+
const gsap = g.gsap ?? g.default;
|
|
13
|
+
const ScrollTrigger = st.ScrollTrigger ?? st.default;
|
|
14
|
+
gsap.registerPlugin(ScrollTrigger);
|
|
15
|
+
return { gsap, ScrollTrigger };
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
return pending;
|
|
19
|
+
}
|
|
20
|
+
function useGsap(ref, setup, deps = [], options = {}) {
|
|
21
|
+
const setupRef = react.useRef(setup);
|
|
22
|
+
setupRef.current = setup;
|
|
23
|
+
const { near = "200px 0px", reducedMotion = "skip" } = options;
|
|
24
|
+
react.useEffect(() => {
|
|
25
|
+
const el = ref.current;
|
|
26
|
+
if (!el) return;
|
|
27
|
+
if (reducedMotion === "skip" && chunkAEW7EFYU_js.prefersReducedMotion()) return;
|
|
28
|
+
let cancelled = false;
|
|
29
|
+
let cleanup;
|
|
30
|
+
let ctx;
|
|
31
|
+
const io = new IntersectionObserver(
|
|
32
|
+
([entry]) => {
|
|
33
|
+
if (!entry?.isIntersecting) return;
|
|
34
|
+
io.disconnect();
|
|
35
|
+
loadGsap().then(({ gsap, ScrollTrigger }) => {
|
|
36
|
+
if (cancelled || !el.isConnected) return;
|
|
37
|
+
ctx = gsap.context(() => {
|
|
38
|
+
cleanup = setupRef.current({ gsap, ScrollTrigger, el });
|
|
39
|
+
}, el);
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
{ rootMargin: near }
|
|
43
|
+
);
|
|
44
|
+
io.observe(el);
|
|
45
|
+
return () => {
|
|
46
|
+
cancelled = true;
|
|
47
|
+
io.disconnect();
|
|
48
|
+
if (typeof cleanup === "function") cleanup();
|
|
49
|
+
ctx?.revert();
|
|
50
|
+
};
|
|
51
|
+
}, [ref, near, reducedMotion, ...deps]);
|
|
52
|
+
}
|
|
53
|
+
function useExpandCollapse(isOpen, options = {}) {
|
|
54
|
+
const { duration = 0.3, ease = "power2.inOut" } = options;
|
|
55
|
+
const contentRef = react.useRef(null);
|
|
56
|
+
const initialized = react.useRef(false);
|
|
57
|
+
react.useEffect(() => {
|
|
58
|
+
const el = contentRef.current;
|
|
59
|
+
if (!el) return;
|
|
60
|
+
if (!initialized.current) {
|
|
61
|
+
initialized.current = true;
|
|
62
|
+
el.style.overflow = "hidden";
|
|
63
|
+
if (!isOpen) {
|
|
64
|
+
el.style.height = "0px";
|
|
65
|
+
el.style.opacity = "0";
|
|
66
|
+
}
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
let cancelled = false;
|
|
70
|
+
loadGsap().then(({ gsap }) => {
|
|
71
|
+
if (cancelled || !el.isConnected) return;
|
|
72
|
+
if (chunkAEW7EFYU_js.prefersReducedMotion()) {
|
|
73
|
+
gsap.set(el, { height: isOpen ? "auto" : 0, opacity: isOpen ? 1 : 0 });
|
|
74
|
+
el.style.overflow = isOpen ? "visible" : "hidden";
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (isOpen) {
|
|
78
|
+
gsap.to(el, {
|
|
79
|
+
height: "auto",
|
|
80
|
+
opacity: 1,
|
|
81
|
+
duration,
|
|
82
|
+
ease,
|
|
83
|
+
onComplete() {
|
|
84
|
+
el.style.overflow = "visible";
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
} else {
|
|
88
|
+
el.style.overflow = "hidden";
|
|
89
|
+
gsap.to(el, { height: 0, opacity: 0, duration: duration * 0.85, ease });
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
return () => {
|
|
93
|
+
cancelled = true;
|
|
94
|
+
};
|
|
95
|
+
}, [isOpen, duration, ease]);
|
|
96
|
+
return { contentRef };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
exports.loadGsap = loadGsap;
|
|
100
|
+
exports.useExpandCollapse = useExpandCollapse;
|
|
101
|
+
exports.useGsap = useGsap;
|
|
102
|
+
//# sourceMappingURL=gsap.js.map
|
|
103
|
+
//# sourceMappingURL=gsap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/motion/gsap.ts"],"names":["useRef","useEffect","prefersReducedMotion"],"mappings":"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","file":"gsap.js","sourcesContent":["/**\n * @sonordev/site-kit/motion/gsap — the Upforge motion standard, tier 1.\n *\n * GSAP for the moments that earn it: sequenced timelines, SplitText,\n * Flip, MorphSVG. Requires the optional peer `gsap` (all plugins are free\n * since 3.13):\n *\n * npm i gsap\n *\n * A site that never imports this subpath never installs gsap. NOTHING\n * outside this file may import from 'gsap' — that is what keeps the tier\n * boundary real (src/motion/motion.test.tsx enforces it).\n *\n * Cost and where it goes: gsap core + ScrollTrigger is ~46KB gzipped.\n * `useGsap` loads it only when its element comes within 200px of the\n * viewport, so it never sits on the LCP critical path, and it must only be\n * used BELOW the fold. First-paint content renders static.\n *\n * Not included on purpose: ScrollSmoother. It drives scrolling by\n * transforming the page body, which fights native scroll, costs INP on\n * mobile, and breaks every scroll-geometry read on the page. The engine's\n * per-scene lerp gives the liquid feel without hijacking anything.\n */\n\n'use client'\n\nimport { useEffect, useRef, type DependencyList, type RefObject } from 'react'\nimport { prefersReducedMotion } from './engine'\n\ntype GsapModule = typeof import('gsap')\ntype ScrollTriggerModule = typeof import('gsap/ScrollTrigger')\n\nexport type Gsap = GsapModule['gsap']\nexport type ScrollTriggerStatic = ScrollTriggerModule['ScrollTrigger']\n\nexport interface GsapBundle {\n gsap: Gsap\n ScrollTrigger: ScrollTriggerStatic\n}\n\nlet pending: Promise<GsapBundle> | null = null\n\n/**\n * Load gsap + ScrollTrigger once, register the plugin, and share the\n * promise. Safe to call from anywhere; resolves the same bundle every time.\n */\nexport function loadGsap(): Promise<GsapBundle> {\n if (!pending) {\n pending = Promise.all([import('gsap'), import('gsap/ScrollTrigger')]).then(([g, st]) => {\n const gsap = g.gsap ?? g.default\n const ScrollTrigger = st.ScrollTrigger ?? st.default\n gsap.registerPlugin(ScrollTrigger)\n return { gsap, ScrollTrigger }\n })\n }\n return pending\n}\n\nexport interface GsapSetupContext extends GsapBundle {\n /** The element the hook is attached to — use it as the ScrollTrigger trigger and the selector scope. */\n el: HTMLElement\n}\n\nexport interface UseGsapOptions {\n /** Preload margin: load gsap when the element is this close. Default \"200px 0px\". */\n near?: string\n /** \"skip\" (default) does nothing under prefers-reduced-motion; \"run\" lets setup decide. */\n reducedMotion?: 'skip' | 'run'\n}\n\n/**\n * Run a GSAP setup against an element, lazily and safely:\n *\n * - gsap loads only when the element nears the viewport\n * - setup runs inside `gsap.context(el)`, so selectors are scoped and\n * everything it creates is reverted on unmount (including ScrollTriggers)\n * - the element must be server-rendered and visible; hide things inside\n * `setup` with `gsap.set`, never with a stylesheet\n *\n * @example\n * const ref = useRef<HTMLDivElement>(null)\n * useGsap(ref, ({ gsap, el }) => {\n * gsap.from(el.querySelectorAll('[data-line]'), {\n * yPercent: 100, opacity: 0, stagger: 0.06, duration: 0.8, ease: 'power3.out',\n * scrollTrigger: { trigger: el, start: 'top 80%' },\n * })\n * })\n */\nexport function useGsap(\n ref: RefObject<HTMLElement | null>,\n setup: (ctx: GsapSetupContext) => void | (() => void),\n deps: DependencyList = [],\n options: UseGsapOptions = {},\n): void {\n const setupRef = useRef(setup)\n setupRef.current = setup\n const { near = '200px 0px', reducedMotion = 'skip' } = options\n\n useEffect(() => {\n const el = ref.current\n if (!el) return\n if (reducedMotion === 'skip' && prefersReducedMotion()) return\n\n let cancelled = false\n let cleanup: (() => void) | void\n let ctx: ReturnType<Gsap['context']> | undefined\n\n const io = new IntersectionObserver(\n ([entry]) => {\n if (!entry?.isIntersecting) return\n io.disconnect()\n loadGsap().then(({ gsap, ScrollTrigger }) => {\n if (cancelled || !el.isConnected) return\n ctx = gsap.context(() => {\n cleanup = setupRef.current({ gsap, ScrollTrigger, el })\n }, el)\n })\n },\n { rootMargin: near },\n )\n io.observe(el)\n\n return () => {\n cancelled = true\n io.disconnect()\n if (typeof cleanup === 'function') cleanup()\n ctx?.revert()\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [ref, near, reducedMotion, ...deps])\n}\n\nexport interface ExpandCollapseOptions {\n duration?: number\n ease?: string\n}\n\n/**\n * Animate expand/collapse without mount/unmount. Content stays in the DOM\n * (so it stays indexable) with overflow hidden; gsap animates height and\n * opacity, and loads on the first toggle, not at mount.\n *\n * @example\n * const { contentRef } = useExpandCollapse(isOpen)\n * <div ref={contentRef}>{children}</div>\n */\nexport function useExpandCollapse(\n isOpen: boolean,\n options: ExpandCollapseOptions = {},\n): { contentRef: RefObject<HTMLDivElement | null> } {\n const { duration = 0.3, ease = 'power2.inOut' } = options\n const contentRef = useRef<HTMLDivElement>(null)\n const initialized = useRef(false)\n\n useEffect(() => {\n const el = contentRef.current\n if (!el) return\n\n // First render: set the resting state with inline styles, no gsap.\n if (!initialized.current) {\n initialized.current = true\n el.style.overflow = 'hidden'\n if (!isOpen) {\n el.style.height = '0px'\n el.style.opacity = '0'\n }\n return\n }\n\n let cancelled = false\n loadGsap().then(({ gsap }) => {\n if (cancelled || !el.isConnected) return\n if (prefersReducedMotion()) {\n gsap.set(el, { height: isOpen ? 'auto' : 0, opacity: isOpen ? 1 : 0 })\n el.style.overflow = isOpen ? 'visible' : 'hidden'\n return\n }\n if (isOpen) {\n gsap.to(el, {\n height: 'auto',\n opacity: 1,\n duration,\n ease,\n onComplete() {\n el.style.overflow = 'visible'\n },\n })\n } else {\n el.style.overflow = 'hidden'\n gsap.to(el, { height: 0, opacity: 0, duration: duration * 0.85, ease })\n }\n })\n return () => {\n cancelled = true\n }\n }, [isOpen, duration, ease])\n\n return { contentRef }\n}\n"]}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { prefersReducedMotion } from '../chunk-MLXUMVBK.mjs';
|
|
3
|
+
import '../chunk-BEXTDHO4.mjs';
|
|
4
|
+
import { useRef, useEffect } from 'react';
|
|
5
|
+
|
|
6
|
+
var pending = null;
|
|
7
|
+
function loadGsap() {
|
|
8
|
+
if (!pending) {
|
|
9
|
+
pending = Promise.all([import('gsap'), import('gsap/ScrollTrigger')]).then(([g, st]) => {
|
|
10
|
+
const gsap = g.gsap ?? g.default;
|
|
11
|
+
const ScrollTrigger = st.ScrollTrigger ?? st.default;
|
|
12
|
+
gsap.registerPlugin(ScrollTrigger);
|
|
13
|
+
return { gsap, ScrollTrigger };
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return pending;
|
|
17
|
+
}
|
|
18
|
+
function useGsap(ref, setup, deps = [], options = {}) {
|
|
19
|
+
const setupRef = useRef(setup);
|
|
20
|
+
setupRef.current = setup;
|
|
21
|
+
const { near = "200px 0px", reducedMotion = "skip" } = options;
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
const el = ref.current;
|
|
24
|
+
if (!el) return;
|
|
25
|
+
if (reducedMotion === "skip" && prefersReducedMotion()) return;
|
|
26
|
+
let cancelled = false;
|
|
27
|
+
let cleanup;
|
|
28
|
+
let ctx;
|
|
29
|
+
const io = new IntersectionObserver(
|
|
30
|
+
([entry]) => {
|
|
31
|
+
if (!entry?.isIntersecting) return;
|
|
32
|
+
io.disconnect();
|
|
33
|
+
loadGsap().then(({ gsap, ScrollTrigger }) => {
|
|
34
|
+
if (cancelled || !el.isConnected) return;
|
|
35
|
+
ctx = gsap.context(() => {
|
|
36
|
+
cleanup = setupRef.current({ gsap, ScrollTrigger, el });
|
|
37
|
+
}, el);
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
{ rootMargin: near }
|
|
41
|
+
);
|
|
42
|
+
io.observe(el);
|
|
43
|
+
return () => {
|
|
44
|
+
cancelled = true;
|
|
45
|
+
io.disconnect();
|
|
46
|
+
if (typeof cleanup === "function") cleanup();
|
|
47
|
+
ctx?.revert();
|
|
48
|
+
};
|
|
49
|
+
}, [ref, near, reducedMotion, ...deps]);
|
|
50
|
+
}
|
|
51
|
+
function useExpandCollapse(isOpen, options = {}) {
|
|
52
|
+
const { duration = 0.3, ease = "power2.inOut" } = options;
|
|
53
|
+
const contentRef = useRef(null);
|
|
54
|
+
const initialized = useRef(false);
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
const el = contentRef.current;
|
|
57
|
+
if (!el) return;
|
|
58
|
+
if (!initialized.current) {
|
|
59
|
+
initialized.current = true;
|
|
60
|
+
el.style.overflow = "hidden";
|
|
61
|
+
if (!isOpen) {
|
|
62
|
+
el.style.height = "0px";
|
|
63
|
+
el.style.opacity = "0";
|
|
64
|
+
}
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
let cancelled = false;
|
|
68
|
+
loadGsap().then(({ gsap }) => {
|
|
69
|
+
if (cancelled || !el.isConnected) return;
|
|
70
|
+
if (prefersReducedMotion()) {
|
|
71
|
+
gsap.set(el, { height: isOpen ? "auto" : 0, opacity: isOpen ? 1 : 0 });
|
|
72
|
+
el.style.overflow = isOpen ? "visible" : "hidden";
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (isOpen) {
|
|
76
|
+
gsap.to(el, {
|
|
77
|
+
height: "auto",
|
|
78
|
+
opacity: 1,
|
|
79
|
+
duration,
|
|
80
|
+
ease,
|
|
81
|
+
onComplete() {
|
|
82
|
+
el.style.overflow = "visible";
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
} else {
|
|
86
|
+
el.style.overflow = "hidden";
|
|
87
|
+
gsap.to(el, { height: 0, opacity: 0, duration: duration * 0.85, ease });
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
return () => {
|
|
91
|
+
cancelled = true;
|
|
92
|
+
};
|
|
93
|
+
}, [isOpen, duration, ease]);
|
|
94
|
+
return { contentRef };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export { loadGsap, useExpandCollapse, useGsap };
|
|
98
|
+
//# sourceMappingURL=gsap.mjs.map
|
|
99
|
+
//# sourceMappingURL=gsap.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/motion/gsap.ts"],"names":[],"mappings":"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","file":"gsap.mjs","sourcesContent":["/**\n * @sonordev/site-kit/motion/gsap — the Upforge motion standard, tier 1.\n *\n * GSAP for the moments that earn it: sequenced timelines, SplitText,\n * Flip, MorphSVG. Requires the optional peer `gsap` (all plugins are free\n * since 3.13):\n *\n * npm i gsap\n *\n * A site that never imports this subpath never installs gsap. NOTHING\n * outside this file may import from 'gsap' — that is what keeps the tier\n * boundary real (src/motion/motion.test.tsx enforces it).\n *\n * Cost and where it goes: gsap core + ScrollTrigger is ~46KB gzipped.\n * `useGsap` loads it only when its element comes within 200px of the\n * viewport, so it never sits on the LCP critical path, and it must only be\n * used BELOW the fold. First-paint content renders static.\n *\n * Not included on purpose: ScrollSmoother. It drives scrolling by\n * transforming the page body, which fights native scroll, costs INP on\n * mobile, and breaks every scroll-geometry read on the page. The engine's\n * per-scene lerp gives the liquid feel without hijacking anything.\n */\n\n'use client'\n\nimport { useEffect, useRef, type DependencyList, type RefObject } from 'react'\nimport { prefersReducedMotion } from './engine'\n\ntype GsapModule = typeof import('gsap')\ntype ScrollTriggerModule = typeof import('gsap/ScrollTrigger')\n\nexport type Gsap = GsapModule['gsap']\nexport type ScrollTriggerStatic = ScrollTriggerModule['ScrollTrigger']\n\nexport interface GsapBundle {\n gsap: Gsap\n ScrollTrigger: ScrollTriggerStatic\n}\n\nlet pending: Promise<GsapBundle> | null = null\n\n/**\n * Load gsap + ScrollTrigger once, register the plugin, and share the\n * promise. Safe to call from anywhere; resolves the same bundle every time.\n */\nexport function loadGsap(): Promise<GsapBundle> {\n if (!pending) {\n pending = Promise.all([import('gsap'), import('gsap/ScrollTrigger')]).then(([g, st]) => {\n const gsap = g.gsap ?? g.default\n const ScrollTrigger = st.ScrollTrigger ?? st.default\n gsap.registerPlugin(ScrollTrigger)\n return { gsap, ScrollTrigger }\n })\n }\n return pending\n}\n\nexport interface GsapSetupContext extends GsapBundle {\n /** The element the hook is attached to — use it as the ScrollTrigger trigger and the selector scope. */\n el: HTMLElement\n}\n\nexport interface UseGsapOptions {\n /** Preload margin: load gsap when the element is this close. Default \"200px 0px\". */\n near?: string\n /** \"skip\" (default) does nothing under prefers-reduced-motion; \"run\" lets setup decide. */\n reducedMotion?: 'skip' | 'run'\n}\n\n/**\n * Run a GSAP setup against an element, lazily and safely:\n *\n * - gsap loads only when the element nears the viewport\n * - setup runs inside `gsap.context(el)`, so selectors are scoped and\n * everything it creates is reverted on unmount (including ScrollTriggers)\n * - the element must be server-rendered and visible; hide things inside\n * `setup` with `gsap.set`, never with a stylesheet\n *\n * @example\n * const ref = useRef<HTMLDivElement>(null)\n * useGsap(ref, ({ gsap, el }) => {\n * gsap.from(el.querySelectorAll('[data-line]'), {\n * yPercent: 100, opacity: 0, stagger: 0.06, duration: 0.8, ease: 'power3.out',\n * scrollTrigger: { trigger: el, start: 'top 80%' },\n * })\n * })\n */\nexport function useGsap(\n ref: RefObject<HTMLElement | null>,\n setup: (ctx: GsapSetupContext) => void | (() => void),\n deps: DependencyList = [],\n options: UseGsapOptions = {},\n): void {\n const setupRef = useRef(setup)\n setupRef.current = setup\n const { near = '200px 0px', reducedMotion = 'skip' } = options\n\n useEffect(() => {\n const el = ref.current\n if (!el) return\n if (reducedMotion === 'skip' && prefersReducedMotion()) return\n\n let cancelled = false\n let cleanup: (() => void) | void\n let ctx: ReturnType<Gsap['context']> | undefined\n\n const io = new IntersectionObserver(\n ([entry]) => {\n if (!entry?.isIntersecting) return\n io.disconnect()\n loadGsap().then(({ gsap, ScrollTrigger }) => {\n if (cancelled || !el.isConnected) return\n ctx = gsap.context(() => {\n cleanup = setupRef.current({ gsap, ScrollTrigger, el })\n }, el)\n })\n },\n { rootMargin: near },\n )\n io.observe(el)\n\n return () => {\n cancelled = true\n io.disconnect()\n if (typeof cleanup === 'function') cleanup()\n ctx?.revert()\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [ref, near, reducedMotion, ...deps])\n}\n\nexport interface ExpandCollapseOptions {\n duration?: number\n ease?: string\n}\n\n/**\n * Animate expand/collapse without mount/unmount. Content stays in the DOM\n * (so it stays indexable) with overflow hidden; gsap animates height and\n * opacity, and loads on the first toggle, not at mount.\n *\n * @example\n * const { contentRef } = useExpandCollapse(isOpen)\n * <div ref={contentRef}>{children}</div>\n */\nexport function useExpandCollapse(\n isOpen: boolean,\n options: ExpandCollapseOptions = {},\n): { contentRef: RefObject<HTMLDivElement | null> } {\n const { duration = 0.3, ease = 'power2.inOut' } = options\n const contentRef = useRef<HTMLDivElement>(null)\n const initialized = useRef(false)\n\n useEffect(() => {\n const el = contentRef.current\n if (!el) return\n\n // First render: set the resting state with inline styles, no gsap.\n if (!initialized.current) {\n initialized.current = true\n el.style.overflow = 'hidden'\n if (!isOpen) {\n el.style.height = '0px'\n el.style.opacity = '0'\n }\n return\n }\n\n let cancelled = false\n loadGsap().then(({ gsap }) => {\n if (cancelled || !el.isConnected) return\n if (prefersReducedMotion()) {\n gsap.set(el, { height: isOpen ? 'auto' : 0, opacity: isOpen ? 1 : 0 })\n el.style.overflow = isOpen ? 'visible' : 'hidden'\n return\n }\n if (isOpen) {\n gsap.to(el, {\n height: 'auto',\n opacity: 1,\n duration,\n ease,\n onComplete() {\n el.style.overflow = 'visible'\n },\n })\n } else {\n el.style.overflow = 'hidden'\n gsap.to(el, { height: 0, opacity: 0, duration: duration * 0.85, ease })\n }\n })\n return () => {\n cancelled = true\n }\n }, [isOpen, duration, ease])\n\n return { contentRef }\n}\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sonordev/site-kit/motion — the Upforge motion standard, tier 0.
|
|
3
|
+
*
|
|
4
|
+
* Highly interactive, lean, and designed from day one for SEO/AEO. This
|
|
5
|
+
* subpath has ZERO dependencies (~2KB) and is what every site gets:
|
|
6
|
+
*
|
|
7
|
+
* <Reveal> scroll-entrance reveal; server HTML always visible,
|
|
8
|
+
* above-the-fold untouched, headless-renderer failsafe
|
|
9
|
+
* <Parallax> scroll-linked transform/opacity, compositor-only
|
|
10
|
+
* <ScrollScene> a pinned scene: sticky stage, progress 0→1 as a CSS var
|
|
11
|
+
* registerScene the engine itself, for anything custom
|
|
12
|
+
*
|
|
13
|
+
* The heavier tiers are separate subpaths so a site that never imports
|
|
14
|
+
* them never installs or ships them:
|
|
15
|
+
*
|
|
16
|
+
* @sonordev/site-kit/motion/gsap GSAP timelines, lazy-loaded (peer: gsap)
|
|
17
|
+
* @sonordev/site-kit/motion/three WebGL stages on the engine (peer: three)
|
|
18
|
+
*
|
|
19
|
+
* Nothing in this module is mounted by SiteKitLayout. Motion is opt-in per
|
|
20
|
+
* element, never a wrapper around the page.
|
|
21
|
+
*/
|
|
22
|
+
export { registerScene, refreshScenes, prefersReducedMotion, sceneProgress, } from './engine';
|
|
23
|
+
export type { SceneRender, SceneOptions, SceneInfo, SceneMode } from './engine';
|
|
24
|
+
export { onNoScroll } from './failsafe';
|
|
25
|
+
export { Reveal } from './Reveal';
|
|
26
|
+
export type { RevealProps, RevealDirection } from './Reveal';
|
|
27
|
+
export { Parallax, useParallax } from './Parallax';
|
|
28
|
+
export type { ParallaxProps, ParallaxOptions } from './Parallax';
|
|
29
|
+
export { ScrollScene, useScrollScene } from './ScrollScene';
|
|
30
|
+
export type { ScrollSceneProps, UseScrollSceneOptions } from './ScrollScene';
|
|
31
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/motion/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,EACL,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,aAAa,GACd,MAAM,UAAU,CAAA;AACjB,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAE/E,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAE5D,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAClD,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEhE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC3D,YAAY,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA"}
|