@sonordev/site-kit 5.6.0 → 5.8.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 +3 -3
- package/agent-manifest.json +24 -4
- package/dist/AnalyticsProvider-OCXRNIVE.js +33 -0
- package/dist/{AnalyticsProvider-6PXC7UDP.js.map → AnalyticsProvider-OCXRNIVE.js.map} +1 -1
- package/dist/AnalyticsProvider-ZAUONQCX.mjs +12 -0
- package/dist/{AnalyticsProvider-FVQIYSLY.mjs.map → AnalyticsProvider-ZAUONQCX.mjs.map} +1 -1
- package/dist/{BlogViewTracker-S4HSRCW7.js → BlogViewTracker-HK5C7PU6.js} +14 -11
- package/dist/BlogViewTracker-HK5C7PU6.js.map +1 -0
- package/dist/{BlogViewTracker-ZUGLBOVI.mjs → BlogViewTracker-KXRZHN3U.mjs} +13 -10
- package/dist/BlogViewTracker-KXRZHN3U.mjs.map +1 -0
- package/dist/ChatWidget-3OW5LY37.js +24 -0
- package/dist/{ChatWidget-2TQWCXWP.js.map → ChatWidget-3OW5LY37.js.map} +1 -1
- package/dist/ChatWidget-54GVS27I.mjs +15 -0
- package/dist/{ChatWidget-DG52ZIE6.mjs.map → ChatWidget-54GVS27I.mjs.map} +1 -1
- package/dist/EngageWidget-7EUP76WE.mjs +12 -0
- package/dist/{EngageWidget-2VUJADIU.mjs.map → EngageWidget-7EUP76WE.mjs.map} +1 -1
- package/dist/EngageWidget-DDP5UFA4.js +21 -0
- package/dist/{EngageWidget-Z7RC2INM.js.map → EngageWidget-DDP5UFA4.js.map} +1 -1
- package/dist/{FileField-FSQ7W3A5.mjs → FileField-IQLN6E3C.mjs} +5 -5
- package/dist/{FileField-FSQ7W3A5.mjs.map → FileField-IQLN6E3C.mjs.map} +1 -1
- package/dist/{FileField-UOQHL25J.js → FileField-SBPL4JHP.js} +6 -6
- package/dist/{FileField-UOQHL25J.js.map → FileField-SBPL4JHP.js.map} +1 -1
- package/dist/{FormSpotlight-RHL5FWM2.mjs → FormSpotlight-E2LKKHGV.mjs} +11 -7
- package/dist/FormSpotlight-E2LKKHGV.mjs.map +1 -0
- package/dist/{FormSpotlight-TED32NHP.js → FormSpotlight-YTACNE57.js} +25 -21
- package/dist/FormSpotlight-YTACNE57.js.map +1 -0
- package/dist/{FormStage-PFEBKHGY.js → FormStage-S277U2CP.js} +20 -15
- package/dist/FormStage-S277U2CP.js.map +1 -0
- package/dist/{FormStage-DINIRFOX.mjs → FormStage-YSBN5XKL.mjs} +9 -4
- package/dist/FormStage-YSBN5XKL.mjs.map +1 -0
- package/dist/ManagedForm-I3QVRQ53.mjs +16 -0
- package/dist/{ManagedForm-545YAUFC.mjs.map → ManagedForm-I3QVRQ53.mjs.map} +1 -1
- package/dist/ManagedForm-TSYKQFLJ.js +25 -0
- package/dist/{ManagedForm-43WLCUAK.js.map → ManagedForm-TSYKQFLJ.js.map} +1 -1
- package/dist/{ManagedNewsletterForm-ZPY5RRKX.mjs → ManagedNewsletterForm-T3YRAWKZ.mjs} +9 -7
- package/dist/ManagedNewsletterForm-T3YRAWKZ.mjs.map +1 -0
- package/dist/{ManagedNewsletterForm-I3QN57HB.js → ManagedNewsletterForm-YSOPPKS6.js} +10 -8
- package/dist/ManagedNewsletterForm-YSOPPKS6.js.map +1 -0
- package/dist/{SignalCore-EEH5IM4U.mjs → SignalCore-PPSIQ4BW.mjs} +8 -14
- package/dist/SignalCore-PPSIQ4BW.mjs.map +1 -0
- package/dist/{SignalCore-M4AXIMV4.js → SignalCore-SUZH3XWZ.js} +14 -20
- package/dist/SignalCore-SUZH3XWZ.js.map +1 -0
- package/dist/SitemapSync-HSHCOKCL.mjs +9 -0
- package/dist/{SitemapSync-46G7LVZS.mjs.map → SitemapSync-HSHCOKCL.mjs.map} +1 -1
- package/dist/SitemapSync-LH6UVP4P.js +18 -0
- package/dist/{SitemapSync-XK4JKCS7.js.map → SitemapSync-LH6UVP4P.js.map} +1 -1
- package/dist/analytics/AnalyticsProvider.d.ts.map +1 -1
- package/dist/analytics/index.js +10 -9
- package/dist/analytics/index.mjs +5 -4
- package/dist/blog/BlogLayout.d.ts +3 -1
- package/dist/blog/BlogLayout.d.ts.map +1 -1
- package/dist/blog/BlogList.d.ts +7 -1
- package/dist/blog/BlogList.d.ts.map +1 -1
- package/dist/blog/BlogPost.d.ts +20 -1
- package/dist/blog/BlogPost.d.ts.map +1 -1
- package/dist/blog/BlogSidebar.d.ts +3 -1
- package/dist/blog/BlogSidebar.d.ts.map +1 -1
- package/dist/blog/BlogViewTracker.d.ts +8 -2
- package/dist/blog/BlogViewTracker.d.ts.map +1 -1
- package/dist/blog/ClusterLandingPage.d.ts +3 -1
- package/dist/blog/ClusterLandingPage.d.ts.map +1 -1
- package/dist/blog/ClusterNavigation.d.ts +5 -2
- package/dist/blog/ClusterNavigation.d.ts.map +1 -1
- package/dist/blog/RelatedPosts.d.ts +3 -1
- package/dist/blog/RelatedPosts.d.ts.map +1 -1
- package/dist/blog/index.d.ts +1 -1
- package/dist/blog/index.d.ts.map +1 -1
- package/dist/blog/index.js +40 -31
- package/dist/blog/index.js.map +1 -1
- package/dist/blog/index.mjs +11 -6
- package/dist/blog/index.mjs.map +1 -1
- package/dist/blog/metadata-images.test.d.ts +2 -0
- package/dist/blog/metadata-images.test.d.ts.map +1 -0
- package/dist/blog/not-found.test.d.ts +2 -0
- package/dist/blog/not-found.test.d.ts.map +1 -0
- package/dist/blog/processBlogHtml.d.ts +19 -2
- package/dist/blog/processBlogHtml.d.ts.map +1 -1
- package/dist/blog/public-reads.d.ts +27 -0
- package/dist/blog/public-reads.d.ts.map +1 -0
- package/dist/blog/server-core.d.ts +107 -16
- package/dist/blog/server-core.d.ts.map +1 -1
- package/dist/blog/server-ui.js +29 -23
- package/dist/blog/server-ui.js.map +1 -1
- package/dist/blog/server-ui.mjs +12 -6
- package/dist/blog/server-ui.mjs.map +1 -1
- package/dist/blog/server.d.ts +107 -16
- package/dist/blog/server.d.ts.map +1 -1
- package/dist/blog/server.js +54 -47
- package/dist/blog/server.mjs +5 -2
- package/dist/blog/site-scope.test.d.ts +2 -0
- package/dist/blog/site-scope.test.d.ts.map +1 -0
- package/dist/blog/static-params.test.d.ts +2 -0
- package/dist/blog/static-params.test.d.ts.map +1 -0
- package/dist/brand/extract-brand-profile.d.ts +36 -2
- package/dist/brand/extract-brand-profile.d.ts.map +1 -1
- package/dist/brand/extract-brand-profile.test.d.ts +2 -0
- package/dist/brand/extract-brand-profile.test.d.ts.map +1 -0
- package/dist/{chunk-B64AZC6P.js → chunk-2FQG2AHJ.js} +60 -35
- package/dist/chunk-2FQG2AHJ.js.map +1 -0
- package/dist/{chunk-N2PGTPWN.js → chunk-2OQWLXDO.js} +13 -13
- package/dist/{chunk-N2PGTPWN.js.map → chunk-2OQWLXDO.js.map} +1 -1
- package/dist/{chunk-T5VTQUNF.js → chunk-2SCDUVFJ.js} +10 -10
- package/dist/{chunk-T5VTQUNF.js.map → chunk-2SCDUVFJ.js.map} +1 -1
- package/dist/{chunk-S4RC6VAQ.js → chunk-35ERUUH3.js} +6 -6
- package/dist/{chunk-S4RC6VAQ.js.map → chunk-35ERUUH3.js.map} +1 -1
- package/dist/{chunk-VHZ4LHQT.mjs → chunk-3AUFD7KR.mjs} +3 -3
- package/dist/{chunk-VHZ4LHQT.mjs.map → chunk-3AUFD7KR.mjs.map} +1 -1
- package/dist/{chunk-DHIWR7CG.js → chunk-3BVCF4ZF.js} +4 -4
- package/dist/{chunk-DHIWR7CG.js.map → chunk-3BVCF4ZF.js.map} +1 -1
- package/dist/{chunk-EEQYKMGH.mjs → chunk-3EY5E35M.mjs} +57 -86
- package/dist/chunk-3EY5E35M.mjs.map +1 -0
- package/dist/{chunk-JNABXCLY.mjs → chunk-3SLFT453.mjs} +5 -5
- package/dist/{chunk-JNABXCLY.mjs.map → chunk-3SLFT453.mjs.map} +1 -1
- package/dist/{chunk-AJQI3WTN.mjs → chunk-4L7OHRWB.mjs} +12 -9
- package/dist/chunk-4L7OHRWB.mjs.map +1 -0
- package/dist/chunk-4LYW6PMU.mjs +72 -0
- package/dist/chunk-4LYW6PMU.mjs.map +1 -0
- package/dist/{chunk-R3KTBKSW.js → chunk-4OS6M3V4.js} +6 -12
- package/dist/chunk-4OS6M3V4.js.map +1 -0
- package/dist/{chunk-AY7JBGYC.js → chunk-4RY7JETY.js} +14 -14
- package/dist/{chunk-AY7JBGYC.js.map → chunk-4RY7JETY.js.map} +1 -1
- package/dist/chunk-4TLFZ6NR.mjs +16 -0
- package/dist/chunk-4TLFZ6NR.mjs.map +1 -0
- package/dist/{chunk-4B4S56WJ.mjs → chunk-5B4J3IBX.mjs} +75 -21
- package/dist/chunk-5B4J3IBX.mjs.map +1 -0
- package/dist/chunk-5O7JSWT6.js +8 -0
- package/dist/{chunk-KSL3WA2I.js.map → chunk-5O7JSWT6.js.map} +1 -1
- package/dist/chunk-5SANRSX3.mjs +17 -0
- package/dist/chunk-5SANRSX3.mjs.map +1 -0
- package/dist/{chunk-LCSYJXIO.mjs → chunk-5WGMXSCB.mjs} +3 -3
- package/dist/{chunk-LCSYJXIO.mjs.map → chunk-5WGMXSCB.mjs.map} +1 -1
- package/dist/chunk-5XFFUP6D.js +100 -0
- package/dist/chunk-5XFFUP6D.js.map +1 -0
- package/dist/{chunk-AHZR4VGY.mjs → chunk-6HFFTGFP.mjs} +50 -26
- package/dist/chunk-6HFFTGFP.mjs.map +1 -0
- package/dist/{chunk-USKIL6V6.mjs → chunk-6SBTHS6C.mjs} +3 -3
- package/dist/{chunk-USKIL6V6.mjs.map → chunk-6SBTHS6C.mjs.map} +1 -1
- package/dist/{chunk-NZSFOZJV.js → chunk-7TC3GRXQ.js} +73 -38
- package/dist/chunk-7TC3GRXQ.js.map +1 -0
- package/dist/{chunk-HIHAXEPD.mjs → chunk-7THZOAUR.mjs} +4 -4
- package/dist/{chunk-HIHAXEPD.mjs.map → chunk-7THZOAUR.mjs.map} +1 -1
- package/dist/{chunk-YCI36ZUS.mjs → chunk-AOWJP25J.mjs} +4 -4
- package/dist/{chunk-YCI36ZUS.mjs.map → chunk-AOWJP25J.mjs.map} +1 -1
- package/dist/{chunk-H44XZUOV.mjs → chunk-B2VFMPVJ.mjs} +4 -4
- package/dist/{chunk-H44XZUOV.mjs.map → chunk-B2VFMPVJ.mjs.map} +1 -1
- package/dist/{chunk-OA7KKOAK.mjs → chunk-B35OJ7FR.mjs} +4 -4
- package/dist/{chunk-OA7KKOAK.mjs.map → chunk-B35OJ7FR.mjs.map} +1 -1
- package/dist/{chunk-XR32C47O.js → chunk-BER36QXU.js} +9 -9
- package/dist/{chunk-XR32C47O.js.map → chunk-BER36QXU.js.map} +1 -1
- package/dist/{chunk-7C7XO5HX.mjs → chunk-BFZNLTWK.mjs} +3 -3
- package/dist/{chunk-7C7XO5HX.mjs.map → chunk-BFZNLTWK.mjs.map} +1 -1
- package/dist/chunk-BQP6JIE2.mjs +28 -0
- package/dist/chunk-BQP6JIE2.mjs.map +1 -0
- package/dist/{chunk-5KIO6FXE.js → chunk-C3WU45JT.js} +7 -7
- package/dist/{chunk-5KIO6FXE.js.map → chunk-C3WU45JT.js.map} +1 -1
- package/dist/chunk-CUNZAD46.js +53 -0
- package/dist/chunk-CUNZAD46.js.map +1 -0
- package/dist/chunk-CXAXZFFW.js +157 -0
- package/dist/chunk-CXAXZFFW.js.map +1 -0
- package/dist/{chunk-H4OBGC43.mjs → chunk-DA7IANFG.mjs} +14 -3
- package/dist/chunk-DA7IANFG.mjs.map +1 -0
- package/dist/{chunk-BWSMUSDB.js → chunk-EIW6YEPY.js} +8 -8
- package/dist/{chunk-BWSMUSDB.js.map → chunk-EIW6YEPY.js.map} +1 -1
- package/dist/{chunk-UU47DGHE.js → chunk-F6SKG34N.js} +8 -13
- package/dist/chunk-F6SKG34N.js.map +1 -0
- package/dist/{chunk-LC7AM4J5.js → chunk-FHPW7XVH.js} +77 -20
- package/dist/chunk-FHPW7XVH.js.map +1 -0
- package/dist/{chunk-JNRHTZL4.js → chunk-FVW6FT6L.js} +73 -29
- package/dist/chunk-FVW6FT6L.js.map +1 -0
- package/dist/{chunk-KY6M76JW.js → chunk-GNDWTXLU.js} +56 -177
- package/dist/chunk-GNDWTXLU.js.map +1 -0
- package/dist/{chunk-OZ3FU4BT.js → chunk-H5NBFNND.js} +2 -2
- package/dist/chunk-H5NBFNND.js.map +1 -0
- package/dist/{chunk-SYGGZZMU.js → chunk-HAKD27AZ.js} +7 -7
- package/dist/{chunk-SYGGZZMU.js.map → chunk-HAKD27AZ.js.map} +1 -1
- package/dist/chunk-HCN3IKMW.mjs +106 -0
- package/dist/chunk-HCN3IKMW.mjs.map +1 -0
- package/dist/{chunk-QNPVVWR7.mjs → chunk-HCX343AS.mjs} +4 -4
- package/dist/{chunk-QNPVVWR7.mjs.map → chunk-HCX343AS.mjs.map} +1 -1
- package/dist/{chunk-C2MSD2UM.mjs → chunk-HEOQT5SM.mjs} +216 -103
- package/dist/chunk-HEOQT5SM.mjs.map +1 -0
- package/dist/{chunk-RU54J2PY.mjs → chunk-HOJ4J4X2.mjs} +30 -12
- package/dist/chunk-HOJ4J4X2.mjs.map +1 -0
- package/dist/{chunk-H3D3ZGOJ.js → chunk-HQOHB6QF.js} +15 -15
- package/dist/{chunk-H3D3ZGOJ.js.map → chunk-HQOHB6QF.js.map} +1 -1
- package/dist/chunk-HRMGITUZ.mjs +6 -0
- package/dist/{chunk-DQUBETXH.mjs.map → chunk-HRMGITUZ.mjs.map} +1 -1
- package/dist/{chunk-7AUDKXY5.mjs → chunk-HYVEIP2N.mjs} +3 -3
- package/dist/{chunk-7AUDKXY5.mjs.map → chunk-HYVEIP2N.mjs.map} +1 -1
- package/dist/{chunk-46BMNWE6.js → chunk-I3ND4XYW.js} +12 -9
- package/dist/chunk-I3ND4XYW.js.map +1 -0
- package/dist/{chunk-53KMRZT7.js → chunk-JDTU2RWC.js} +3 -3
- package/dist/{chunk-53KMRZT7.js.map → chunk-JDTU2RWC.js.map} +1 -1
- package/dist/{chunk-GZJE23Y5.mjs → chunk-JLVCWC6A.mjs} +2 -2
- package/dist/chunk-JLVCWC6A.mjs.map +1 -0
- package/dist/chunk-K4TCEAUX.js +52 -0
- package/dist/chunk-K4TCEAUX.js.map +1 -0
- package/dist/chunk-KV7XXLJV.mjs +30 -0
- package/dist/chunk-KV7XXLJV.mjs.map +1 -0
- package/dist/{chunk-5UFDHGFE.mjs → chunk-L24RDT6Q.mjs} +3 -3
- package/dist/{chunk-5UFDHGFE.mjs.map → chunk-L24RDT6Q.mjs.map} +1 -1
- package/dist/{chunk-JE5DWAE6.js → chunk-LBZGYF3B.js} +4 -4
- package/dist/{chunk-JE5DWAE6.js.map → chunk-LBZGYF3B.js.map} +1 -1
- package/dist/{chunk-746RKQHA.js → chunk-LMEUYRRR.js} +93 -121
- package/dist/chunk-LMEUYRRR.js.map +1 -0
- package/dist/chunk-LVGSOW2F.js +32 -0
- package/dist/chunk-LVGSOW2F.js.map +1 -0
- package/dist/{chunk-KPKQKFT4.js → chunk-M45AL7EA.js} +37 -19
- package/dist/chunk-M45AL7EA.js.map +1 -0
- package/dist/{chunk-XK5AIWQG.js → chunk-MHX6TOAS.js} +3 -3
- package/dist/{chunk-XK5AIWQG.js.map → chunk-MHX6TOAS.js.map} +1 -1
- package/dist/chunk-MLVHVKFT.mjs +148 -0
- package/dist/chunk-MLVHVKFT.mjs.map +1 -0
- package/dist/{chunk-RIYAMYLV.mjs → chunk-N2NZBPQ5.mjs} +4 -10
- package/dist/chunk-N2NZBPQ5.mjs.map +1 -0
- package/dist/chunk-NRBITVDK.js +114 -0
- package/dist/chunk-NRBITVDK.js.map +1 -0
- package/dist/{chunk-IYCLN3XS.mjs → chunk-O4YBWJHP.mjs} +6 -11
- package/dist/chunk-O4YBWJHP.mjs.map +1 -0
- package/dist/{chunk-5KIEZHVK.mjs → chunk-O5ZSGBQD.mjs} +4 -4
- package/dist/{chunk-5KIEZHVK.mjs.map → chunk-O5ZSGBQD.mjs.map} +1 -1
- package/dist/{chunk-TP7H6BSK.mjs → chunk-OE7CTIOU.mjs} +73 -30
- package/dist/chunk-OE7CTIOU.mjs.map +1 -0
- package/dist/{chunk-UJ6CHZAI.mjs → chunk-OEW2LFOV.js} +169 -25
- package/dist/chunk-OEW2LFOV.js.map +1 -0
- package/dist/chunk-P4Y75QSU.js +19 -0
- package/dist/chunk-P4Y75QSU.js.map +1 -0
- package/dist/{chunk-6OP5XSMM.mjs → chunk-PK2OTGW5.mjs} +6 -12
- package/dist/chunk-PK2OTGW5.mjs.map +1 -0
- package/dist/{chunk-OC7AO7XS.js → chunk-PRTXAIIC.js} +15 -15
- package/dist/{chunk-OC7AO7XS.js.map → chunk-PRTXAIIC.js.map} +1 -1
- package/dist/{chunk-K2V3ZW36.mjs → chunk-PUAXHYBL.mjs} +3 -3
- package/dist/{chunk-K2V3ZW36.mjs.map → chunk-PUAXHYBL.mjs.map} +1 -1
- package/dist/chunk-QRHVMTHF.mjs +94 -0
- package/dist/chunk-QRHVMTHF.mjs.map +1 -0
- package/dist/{chunk-BZLIOT7Q.js → chunk-QTJTDQYR.js} +76 -111
- package/dist/chunk-QTJTDQYR.js.map +1 -0
- package/dist/{chunk-GJ6NOLGC.mjs → chunk-QVHVL7EX.mjs} +3 -3
- package/dist/{chunk-GJ6NOLGC.mjs.map → chunk-QVHVL7EX.mjs.map} +1 -1
- package/dist/chunk-R7GHP3FY.js +81 -0
- package/dist/chunk-R7GHP3FY.js.map +1 -0
- package/dist/chunk-SEP5D4MI.js +116 -0
- package/dist/chunk-SEP5D4MI.js.map +1 -0
- package/dist/{chunk-GPLCPMVD.mjs → chunk-TXMVU4EY.mjs} +62 -97
- package/dist/chunk-TXMVU4EY.mjs.map +1 -0
- package/dist/chunk-U2V542EO.mjs +98 -0
- package/dist/chunk-U2V542EO.mjs.map +1 -0
- package/dist/{chunk-YYN4YZYZ.js → chunk-UWHCHYCX.js} +4 -4
- package/dist/{chunk-YYN4YZYZ.js.map → chunk-UWHCHYCX.js.map} +1 -1
- package/dist/{chunk-473WDGQZ.mjs → chunk-VJ74275U.mjs} +38 -156
- package/dist/chunk-VJ74275U.mjs.map +1 -0
- package/dist/{chunk-H7274TKR.mjs → chunk-VJV7WUR2.mjs} +12 -4
- package/dist/chunk-VJV7WUR2.mjs.map +1 -0
- package/dist/{chunk-CQS5ZYI6.mjs → chunk-VYL6IHJA.mjs} +9 -9
- package/dist/{chunk-CQS5ZYI6.mjs.map → chunk-VYL6IHJA.mjs.map} +1 -1
- package/dist/{chunk-5B4FABFK.js → chunk-WS7MH3GD.js} +14 -2
- package/dist/chunk-WS7MH3GD.js.map +1 -0
- package/dist/{chunk-IPV2TUAT.js → chunk-XA2GJFVM.js} +12 -4
- package/dist/chunk-XA2GJFVM.js.map +1 -0
- package/dist/chunk-XBX2K3GA.js +33 -0
- package/dist/chunk-XBX2K3GA.js.map +1 -0
- package/dist/{chunk-X5TCH7VZ.js → chunk-XCYKM2SA.js} +6 -13
- package/dist/chunk-XCYKM2SA.js.map +1 -0
- package/dist/{chunk-6CJP7BFM.js → chunk-XZO5I4RS.mjs} +147 -20
- package/dist/chunk-XZO5I4RS.mjs.map +1 -0
- package/dist/chunk-Y5QZPUL3.mjs +47 -0
- package/dist/chunk-Y5QZPUL3.mjs.map +1 -0
- package/dist/{chunk-B6O7D5U4.js → chunk-YECDJDDD.js} +10 -10
- package/dist/{chunk-B6O7D5U4.js.map → chunk-YECDJDDD.js.map} +1 -1
- package/dist/chunk-YN7QHLWF.js +19 -0
- package/dist/chunk-YN7QHLWF.js.map +1 -0
- package/dist/chunk-YU7QZ3PP.mjs +45 -0
- package/dist/chunk-YU7QZ3PP.mjs.map +1 -0
- package/dist/{chunk-CQRLKNHQ.js → chunk-ZEOC26LZ.js} +223 -110
- package/dist/chunk-ZEOC26LZ.js.map +1 -0
- package/dist/{chunk-AEARU24Q.mjs → chunk-ZVI7MBVF.mjs} +73 -38
- package/dist/chunk-ZVI7MBVF.mjs.map +1 -0
- package/dist/cli/agent/checks.d.ts +15 -1
- package/dist/cli/agent/checks.d.ts.map +1 -1
- package/dist/cli/agent/sitemap-trailing-slash.test.d.ts +2 -0
- package/dist/cli/agent/sitemap-trailing-slash.test.d.ts.map +1 -0
- package/dist/cli/commands/api-routes.d.ts.map +1 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/geo.d.ts +4 -0
- package/dist/cli/commands/geo.d.ts.map +1 -1
- package/dist/cli/commands/geo.test.d.ts +2 -0
- package/dist/cli/commands/geo.test.d.ts.map +1 -0
- package/dist/cli/commands/og.d.ts +31 -4
- package/dist/cli/commands/og.d.ts.map +1 -1
- package/dist/cli/commands/scaffold.d.ts +1 -2
- package/dist/cli/commands/scaffold.d.ts.map +1 -1
- package/dist/cli/commands/sync.d.ts.map +1 -1
- package/dist/cli/generators/index.d.ts +5 -0
- package/dist/cli/generators/index.d.ts.map +1 -1
- package/dist/cli/generators/index.test.d.ts +2 -0
- package/dist/cli/generators/index.test.d.ts.map +1 -0
- package/dist/cli/index.js +921 -466
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +862 -407
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/index.js +6 -6
- package/dist/client/index.mjs +5 -5
- package/dist/commerce/CheckoutForm.d.ts.map +1 -1
- package/dist/commerce/ProductDetail.d.ts.map +1 -1
- package/dist/commerce/api.d.ts +14 -0
- package/dist/commerce/api.d.ts.map +1 -1
- package/dist/commerce/discount-checkout.test.d.ts +2 -0
- package/dist/commerce/discount-checkout.test.d.ts.map +1 -0
- package/dist/commerce/index.d.ts +1 -1
- package/dist/commerce/index.d.ts.map +1 -1
- package/dist/commerce/index.js +61 -56
- package/dist/commerce/index.mjs +6 -5
- package/dist/config/index.js +3 -3
- package/dist/config/index.mjs +1 -1
- package/dist/discover-CYXYKHZ2.mjs +4 -0
- package/dist/{discover-BEJRYNFF.mjs.map → discover-CYXYKHZ2.mjs.map} +1 -1
- package/dist/discover-NGEPXZOD.js +21 -0
- package/dist/{discover-WVDYDUJX.js.map → discover-NGEPXZOD.js.map} +1 -1
- package/dist/engage/index.js +12 -10
- package/dist/engage/index.js.map +1 -1
- package/dist/engage/index.mjs +9 -7
- package/dist/engage/index.mjs.map +1 -1
- package/dist/fleet/index.js +8 -8
- package/dist/fleet/index.mjs +4 -4
- package/dist/forms/FormClient.d.ts.map +1 -1
- package/dist/forms/FormField.d.ts +7 -1
- package/dist/forms/FormField.d.ts.map +1 -1
- package/dist/forms/FormSpotlight.d.ts +1 -1
- package/dist/forms/FormSpotlight.d.ts.map +1 -1
- package/dist/forms/FormStage.d.ts +1 -1
- package/dist/forms/FormStage.d.ts.map +1 -1
- package/dist/forms/experience-plan.d.ts +0 -1
- package/dist/forms/experience-plan.d.ts.map +1 -1
- package/dist/forms/field-interactions.d.ts +63 -0
- package/dist/forms/field-interactions.d.ts.map +1 -0
- package/dist/forms/field-interactions.test.d.ts +8 -0
- package/dist/forms/field-interactions.test.d.ts.map +1 -0
- package/dist/forms/field-rules.d.ts +41 -0
- package/dist/forms/field-rules.d.ts.map +1 -0
- package/dist/forms/field-rules.test.d.ts +8 -0
- package/dist/forms/field-rules.test.d.ts.map +1 -0
- package/dist/forms/form-field-focus.test.d.ts +8 -0
- package/dist/forms/form-field-focus.test.d.ts.map +1 -0
- package/dist/forms/index.js +25 -23
- package/dist/forms/index.js.map +1 -1
- package/dist/forms/index.mjs +13 -11
- package/dist/forms/index.mjs.map +1 -1
- package/dist/forms/server.js +11 -11
- package/dist/forms/server.mjs +9 -9
- package/dist/forms/static.js +8 -8
- package/dist/forms/static.mjs +7 -7
- package/dist/forms/tracking-session.d.ts +48 -3
- package/dist/forms/tracking-session.d.ts.map +1 -1
- package/dist/forms/types.d.ts +11 -0
- package/dist/forms/types.d.ts.map +1 -1
- package/dist/forms/useForm.d.ts +8 -0
- package/dist/forms/useForm.d.ts.map +1 -1
- package/dist/forms/useFormTracking.d.ts +29 -4
- package/dist/forms/useFormTracking.d.ts.map +1 -1
- package/dist/images/index.js +11 -11
- package/dist/images/index.mjs +4 -4
- package/dist/index.js +72 -68
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +14 -10
- package/dist/index.mjs.map +1 -1
- package/dist/layout/client.js +10 -10
- package/dist/layout/client.mjs +9 -9
- package/dist/layout/index.js +13 -12
- package/dist/layout/index.js.map +1 -1
- package/dist/layout/index.mjs +11 -10
- package/dist/layout/index.mjs.map +1 -1
- package/dist/llms/aiRobots.d.ts +24 -5
- package/dist/llms/aiRobots.d.ts.map +1 -1
- package/dist/llms/api.d.ts +8 -3
- package/dist/llms/api.d.ts.map +1 -1
- package/dist/llms/discovery-headers.d.ts +24 -0
- package/dist/llms/discovery-headers.d.ts.map +1 -1
- package/dist/llms/generateLLMsTxt.d.ts.map +1 -1
- package/dist/llms/handlers.d.ts +20 -2
- package/dist/llms/handlers.d.ts.map +1 -1
- package/dist/llms/index.d.ts +2 -2
- package/dist/llms/index.d.ts.map +1 -1
- package/dist/llms/index.js +54 -98
- package/dist/llms/index.js.map +1 -1
- package/dist/llms/index.mjs +20 -83
- package/dist/llms/index.mjs.map +1 -1
- package/dist/llms/links.d.ts +26 -0
- package/dist/llms/links.d.ts.map +1 -0
- package/dist/llms/links.test.d.ts +2 -0
- package/dist/llms/links.test.d.ts.map +1 -0
- package/dist/llms/types.d.ts +15 -0
- package/dist/llms/types.d.ts.map +1 -1
- package/dist/llms/wiring.d.ts +103 -0
- package/dist/llms/wiring.d.ts.map +1 -0
- package/dist/llms/wiring.test.d.ts +2 -0
- package/dist/llms/wiring.test.d.ts.map +1 -0
- package/dist/llms/writeLLMsTxt.d.ts +9 -0
- package/dist/llms/writeLLMsTxt.d.ts.map +1 -1
- package/dist/maps/index.js +5 -5
- package/dist/maps/index.mjs +3 -3
- package/dist/motion/gsap.d.ts +54 -0
- package/dist/motion/gsap.d.ts.map +1 -1
- package/dist/motion/gsap.js +34 -4
- package/dist/motion/gsap.js.map +1 -1
- package/dist/motion/gsap.mjs +33 -5
- package/dist/motion/gsap.mjs.map +1 -1
- package/dist/motion/gsap.test.d.ts +2 -0
- package/dist/motion/gsap.test.d.ts.map +1 -0
- package/dist/og/config.d.ts +6 -0
- package/dist/og/config.d.ts.map +1 -1
- package/dist/og/contrast.d.ts +33 -0
- package/dist/og/contrast.d.ts.map +1 -0
- package/dist/og/index.d.ts +2 -0
- package/dist/og/index.d.ts.map +1 -1
- package/dist/og/index.js +26 -8
- package/dist/og/index.mjs +3 -1
- package/dist/og/pages.d.ts +101 -0
- package/dist/og/pages.d.ts.map +1 -1
- package/dist/og/route-copy.d.ts +34 -0
- package/dist/og/route-copy.d.ts.map +1 -0
- package/dist/og/route-fit.d.ts +77 -0
- package/dist/og/route-fit.d.ts.map +1 -0
- package/dist/og/route.d.ts +80 -20
- package/dist/og/route.d.ts.map +1 -1
- package/dist/og/route.js +195 -25
- package/dist/og/route.js.map +1 -1
- package/dist/og/route.mjs +193 -26
- package/dist/og/route.mjs.map +1 -1
- package/dist/og/route.test.d.ts +2 -0
- package/dist/og/route.test.d.ts.map +1 -0
- package/dist/og/template.d.ts.map +1 -1
- package/dist/og/wiring.d.ts +48 -4
- package/dist/og/wiring.d.ts.map +1 -1
- package/dist/proxy/index.d.ts +16 -11
- package/dist/proxy/index.d.ts.map +1 -1
- package/dist/proxy/index.js +15 -10
- package/dist/proxy/index.js.map +1 -1
- package/dist/proxy/index.mjs +12 -7
- package/dist/proxy/index.mjs.map +1 -1
- package/dist/proxy/llms-discovery.test.d.ts +2 -0
- package/dist/proxy/llms-discovery.test.d.ts.map +1 -0
- package/dist/redirects/index.d.ts +25 -1
- package/dist/redirects/index.d.ts.map +1 -1
- package/dist/redirects/index.js +11 -8
- package/dist/redirects/index.mjs +4 -1
- package/dist/redirects/index.test.d.ts +2 -0
- package/dist/redirects/index.test.d.ts.map +1 -0
- package/dist/redirects/not-found.d.ts +14 -29
- package/dist/redirects/not-found.d.ts.map +1 -1
- package/dist/redirects/not-found.js +15 -5
- package/dist/redirects/not-found.js.map +1 -1
- package/dist/redirects/not-found.mjs +11 -1
- package/dist/redirects/not-found.mjs.map +1 -1
- package/dist/robots/index.d.ts +7 -1
- package/dist/robots/index.d.ts.map +1 -1
- package/dist/robots/index.js +27 -1
- package/dist/robots/index.js.map +1 -1
- package/dist/robots/index.mjs +4 -1
- package/dist/robots/index.mjs.map +1 -1
- package/dist/robots/index.test.d.ts +2 -0
- package/dist/robots/index.test.d.ts.map +1 -0
- package/dist/robots/next-internals.d.ts +22 -0
- package/dist/robots/next-internals.d.ts.map +1 -0
- package/dist/search/index.js +4 -4
- package/dist/search/index.mjs +3 -3
- package/dist/seo/ManagedContent.d.ts +4 -2
- package/dist/seo/ManagedContent.d.ts.map +1 -1
- package/dist/seo/ManagedFAQ.d.ts.map +1 -1
- package/dist/seo/ManagedInternalLinks.d.ts.map +1 -1
- package/dist/seo/ManagedSchema.d.ts.map +1 -1
- package/dist/seo/client.js +6 -6
- package/dist/seo/client.mjs +5 -5
- package/dist/seo/getManagedMetadata.d.ts.map +1 -1
- package/dist/seo/getManagedMetadata.test.d.ts +2 -0
- package/dist/seo/getManagedMetadata.test.d.ts.map +1 -0
- package/dist/seo/index.js +59 -49
- package/dist/seo/index.js.map +1 -1
- package/dist/seo/index.mjs +29 -19
- package/dist/seo/index.mjs.map +1 -1
- package/dist/seo/managed-schema-filter.test.d.ts +2 -0
- package/dist/seo/managed-schema-filter.test.d.ts.map +1 -0
- package/dist/seo/register-sitemap-cli-impl.d.ts +32 -0
- package/dist/seo/register-sitemap-cli-impl.d.ts.map +1 -1
- package/dist/seo/register-sitemap-cli.d.ts +7 -0
- package/dist/seo/register-sitemap-cli.d.ts.map +1 -1
- package/dist/seo/register-sitemap-cli.js +273 -56
- package/dist/seo/register-sitemap-cli.js.map +1 -1
- package/dist/seo/register-sitemap-cli.mjs +269 -52
- package/dist/seo/register-sitemap-cli.mjs.map +1 -1
- package/dist/seo/register-sitemap-request.d.ts +36 -0
- package/dist/seo/register-sitemap-request.d.ts.map +1 -0
- package/dist/seo/register-sitemap-request.test.d.ts +2 -0
- package/dist/seo/register-sitemap-request.test.d.ts.map +1 -0
- package/dist/seo/routing.d.ts +2 -0
- package/dist/seo/routing.d.ts.map +1 -1
- package/dist/seo/schema-filter.d.ts +43 -0
- package/dist/seo/schema-filter.d.ts.map +1 -0
- package/dist/seo/schema-filter.test.d.ts +2 -0
- package/dist/seo/schema-filter.test.d.ts.map +1 -0
- package/dist/seo/server-api.d.ts +15 -2
- package/dist/seo/server-api.d.ts.map +1 -1
- package/dist/seo/server.js +23 -18
- package/dist/seo/server.mjs +7 -2
- package/dist/seo/site-scope.test.d.ts +2 -0
- package/dist/seo/site-scope.test.d.ts.map +1 -0
- package/dist/seo/types.d.ts +30 -0
- package/dist/seo/types.d.ts.map +1 -1
- package/dist/seo-meta/contract.d.ts +60 -0
- package/dist/seo-meta/contract.d.ts.map +1 -0
- package/dist/seo-meta/contract.js +41 -0
- package/dist/seo-meta/contract.js.map +1 -0
- package/dist/seo-meta/contract.mjs +4 -0
- package/dist/seo-meta/contract.mjs.map +1 -0
- package/dist/seo-meta/contract.test.d.ts +2 -0
- package/dist/seo-meta/contract.test.d.ts.map +1 -0
- package/dist/server/index.js +4 -3
- package/dist/server/index.mjs +3 -2
- package/dist/server/mint-site-token.d.ts +2 -32
- package/dist/server/mint-site-token.d.ts.map +1 -1
- package/dist/{server-api-RG3ZL3DV.mjs → server-api-A2EFCTZX.mjs} +7 -3
- package/dist/{server-api-RG3ZL3DV.mjs.map → server-api-A2EFCTZX.mjs.map} +1 -1
- package/dist/{server-api-RYJQAUGO.js → server-api-IWTZ7C3O.js} +25 -21
- package/dist/{server-api-RYJQAUGO.js.map → server-api-IWTZ7C3O.js.map} +1 -1
- package/dist/shared/build-entries.d.ts +2 -0
- package/dist/shared/build-entries.d.ts.map +1 -1
- package/dist/shared/fresh-fetch.d.ts +64 -0
- package/dist/shared/fresh-fetch.d.ts.map +1 -0
- package/dist/shared/fresh-fetch.test.d.ts +2 -0
- package/dist/shared/fresh-fetch.test.d.ts.map +1 -0
- package/dist/shared/next-files.d.ts +42 -0
- package/dist/shared/next-files.d.ts.map +1 -0
- package/dist/shared/next-files.test.d.ts +2 -0
- package/dist/shared/next-files.test.d.ts.map +1 -0
- package/dist/shared/page-leave.d.ts +27 -0
- package/dist/shared/page-leave.d.ts.map +1 -0
- package/dist/shared/page-leave.test.d.ts +2 -0
- package/dist/shared/page-leave.test.d.ts.map +1 -0
- package/dist/shared/source-graph.d.ts +63 -0
- package/dist/shared/source-graph.d.ts.map +1 -0
- package/dist/shared/source-graph.test.d.ts +2 -0
- package/dist/shared/source-graph.test.d.ts.map +1 -0
- package/dist/shared/version.d.ts +1 -1
- package/dist/signal/SignalCore.d.ts.map +1 -1
- package/dist/signal/index.js +11 -11
- package/dist/signal/index.mjs +2 -2
- package/dist/sitemap/discover.d.ts.map +1 -1
- package/dist/sitemap/index.d.ts +25 -5
- package/dist/sitemap/index.d.ts.map +1 -1
- package/dist/sitemap/index.js +54 -51
- package/dist/sitemap/index.js.map +1 -1
- package/dist/sitemap/index.mjs +39 -36
- package/dist/sitemap/index.mjs.map +1 -1
- package/dist/sitemap/shared.d.ts +65 -0
- package/dist/sitemap/shared.d.ts.map +1 -1
- package/dist/sitemap/trailing-slash.test.d.ts +2 -0
- package/dist/sitemap/trailing-slash.test.d.ts.map +1 -0
- package/dist/sites/resolve.d.ts.map +1 -1
- package/dist/sites/site-param.d.ts +16 -0
- package/dist/sites/site-param.d.ts.map +1 -0
- package/dist/sync/index.js +17 -17
- package/dist/sync/index.mjs +4 -4
- package/dist/writeLLMsTxt-CQ7A4AAL.js +20 -0
- package/dist/writeLLMsTxt-CQ7A4AAL.js.map +1 -0
- package/dist/writeLLMsTxt-NX5MSPYX.mjs +11 -0
- package/dist/writeLLMsTxt-NX5MSPYX.mjs.map +1 -0
- package/package.json +25 -22
- package/dist/AnalyticsProvider-6PXC7UDP.js +0 -32
- package/dist/AnalyticsProvider-FVQIYSLY.mjs +0 -11
- package/dist/BlogViewTracker-S4HSRCW7.js.map +0 -1
- package/dist/BlogViewTracker-ZUGLBOVI.mjs.map +0 -1
- package/dist/ChatWidget-2TQWCXWP.js +0 -22
- package/dist/ChatWidget-DG52ZIE6.mjs +0 -13
- package/dist/EngageWidget-2VUJADIU.mjs +0 -12
- package/dist/EngageWidget-Z7RC2INM.js +0 -21
- package/dist/FormSpotlight-RHL5FWM2.mjs.map +0 -1
- package/dist/FormSpotlight-TED32NHP.js.map +0 -1
- package/dist/FormStage-DINIRFOX.mjs.map +0 -1
- package/dist/FormStage-PFEBKHGY.js.map +0 -1
- package/dist/ManagedForm-43WLCUAK.js +0 -23
- package/dist/ManagedForm-545YAUFC.mjs +0 -14
- package/dist/ManagedNewsletterForm-I3QN57HB.js.map +0 -1
- package/dist/ManagedNewsletterForm-ZPY5RRKX.mjs.map +0 -1
- package/dist/SignalCore-EEH5IM4U.mjs.map +0 -1
- package/dist/SignalCore-M4AXIMV4.js.map +0 -1
- package/dist/SitemapSync-46G7LVZS.mjs +0 -9
- package/dist/SitemapSync-XK4JKCS7.js +0 -18
- package/dist/chunk-46BMNWE6.js.map +0 -1
- package/dist/chunk-473WDGQZ.mjs.map +0 -1
- package/dist/chunk-4B4S56WJ.mjs.map +0 -1
- package/dist/chunk-5B4FABFK.js.map +0 -1
- package/dist/chunk-6CJP7BFM.js.map +0 -1
- package/dist/chunk-6OP5XSMM.mjs.map +0 -1
- package/dist/chunk-746RKQHA.js.map +0 -1
- package/dist/chunk-AEARU24Q.mjs.map +0 -1
- package/dist/chunk-AHZR4VGY.mjs.map +0 -1
- package/dist/chunk-AJQI3WTN.mjs.map +0 -1
- package/dist/chunk-B64AZC6P.js.map +0 -1
- package/dist/chunk-BZLIOT7Q.js.map +0 -1
- package/dist/chunk-C2MSD2UM.mjs.map +0 -1
- package/dist/chunk-CQRLKNHQ.js.map +0 -1
- package/dist/chunk-DQUBETXH.mjs +0 -6
- package/dist/chunk-EEQYKMGH.mjs.map +0 -1
- package/dist/chunk-GPLCPMVD.mjs.map +0 -1
- package/dist/chunk-GZJE23Y5.mjs.map +0 -1
- package/dist/chunk-H4OBGC43.mjs.map +0 -1
- package/dist/chunk-H7274TKR.mjs.map +0 -1
- package/dist/chunk-IPV2TUAT.js.map +0 -1
- package/dist/chunk-IYCLN3XS.mjs.map +0 -1
- package/dist/chunk-JEOKDUPQ.js +0 -45
- package/dist/chunk-JEOKDUPQ.js.map +0 -1
- package/dist/chunk-JNRHTZL4.js.map +0 -1
- package/dist/chunk-KPKQKFT4.js.map +0 -1
- package/dist/chunk-KSL3WA2I.js +0 -8
- package/dist/chunk-KY6M76JW.js.map +0 -1
- package/dist/chunk-LC7AM4J5.js.map +0 -1
- package/dist/chunk-LOS5D6B3.js +0 -72
- package/dist/chunk-LOS5D6B3.js.map +0 -1
- package/dist/chunk-NZSFOZJV.js.map +0 -1
- package/dist/chunk-OZ3FU4BT.js.map +0 -1
- package/dist/chunk-QJU6HBSK.mjs +0 -39
- package/dist/chunk-QJU6HBSK.mjs.map +0 -1
- package/dist/chunk-R3KTBKSW.js.map +0 -1
- package/dist/chunk-RIYAMYLV.mjs.map +0 -1
- package/dist/chunk-RU54J2PY.mjs.map +0 -1
- package/dist/chunk-TP7H6BSK.mjs.map +0 -1
- package/dist/chunk-UJ6CHZAI.mjs.map +0 -1
- package/dist/chunk-UU47DGHE.js.map +0 -1
- package/dist/chunk-X5TCH7VZ.js.map +0 -1
- package/dist/chunk-XIJ4F6IE.mjs +0 -63
- package/dist/chunk-XIJ4F6IE.mjs.map +0 -1
- package/dist/discover-BEJRYNFF.mjs +0 -4
- package/dist/discover-WVDYDUJX.js +0 -21
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sonordev/site-kit — the single source of truth for "is this site's GEO /
|
|
3
|
+
* llms.txt wiring correct". `sonor-setup geo` renders it; nothing else should
|
|
4
|
+
* re-implement it.
|
|
5
|
+
*
|
|
6
|
+
* Split like og/wiring.ts: `readGeoWiring` gathers facts from disk,
|
|
7
|
+
* `judgeGeoWiring` turns them into rows, so the judgement is testable without
|
|
8
|
+
* a filesystem.
|
|
9
|
+
*
|
|
10
|
+
* THE FLEET STANCE, since 2026-09-15:
|
|
11
|
+
*
|
|
12
|
+
* 1. llms.txt is NOT a sitemap entry. An XML sitemap lists indexable HTML
|
|
13
|
+
* pages. llms.txt is a plain-text restatement of those pages, so listing it
|
|
14
|
+
* invites Google to index a thin duplicate of the site. AI crawlers find it
|
|
15
|
+
* by convention at /llms.txt. (heinrich-law-nextjs dropped it in de06cfc,
|
|
16
|
+
* and `geo` still failed the site for it until this rule changed.)
|
|
17
|
+
* 2. llms.txt sends `X-Robots-Tag: noindex`. Crawlers still fetch it; search
|
|
18
|
+
* indexes leave it out. `createLLMsTxtHandler` does this by default. A
|
|
19
|
+
* static `public/llms.txt` is served straight from the CDN and never runs
|
|
20
|
+
* the handler (or next.config `headers()`), so it needs the header in host
|
|
21
|
+
* config: see upforge-nextjs's netlify.toml.
|
|
22
|
+
* 3. Pages advertise it with `Link: <…/llms.txt>; rel="describedby"`. The
|
|
23
|
+
* proxy (`createProxy({ llmsDiscovery })`) is the usual place. The check
|
|
24
|
+
* used to look only at next.config and the root layout, so it failed sites
|
|
25
|
+
* that were sending the header live.
|
|
26
|
+
*
|
|
27
|
+
* A root layout that exports `headers()` is NOT a discovery source, though
|
|
28
|
+
* the llms README used to recommend exactly that ("Option B"). `headers()`
|
|
29
|
+
* is a next.config API; exported from a layout it's an unused function, so
|
|
30
|
+
* those sites sent nothing while this check passed them. It fails now, and
|
|
31
|
+
* says why.
|
|
32
|
+
*
|
|
33
|
+
* Route, sitemap and proxy files are read through `shared/source-graph`, so
|
|
34
|
+
* wiring that lives in a helper counts: the MDG property sites call their
|
|
35
|
+
* workspace package's createSitemap, which turns the build-time llms.txt off,
|
|
36
|
+
* and geo failed three of them until each restated `optimizedLLMsTxt: false`
|
|
37
|
+
* at the call site.
|
|
38
|
+
*
|
|
39
|
+
* Node-only (fs/path): never import from browser or client code.
|
|
40
|
+
*/
|
|
41
|
+
export type GeoLevel = 'ok' | 'info' | 'warn' | 'fail';
|
|
42
|
+
export interface GeoRow {
|
|
43
|
+
/** Stable id, safe to key on. */
|
|
44
|
+
id: string;
|
|
45
|
+
label: string;
|
|
46
|
+
level: GeoLevel;
|
|
47
|
+
/** Where it was found, or what's wrong. */
|
|
48
|
+
detail?: string;
|
|
49
|
+
fix?: string;
|
|
50
|
+
}
|
|
51
|
+
export type LlmsUrlPath = '/llms.txt' | '/llms-full.txt';
|
|
52
|
+
export interface LlmsFileFacts {
|
|
53
|
+
path: LlmsUrlPath;
|
|
54
|
+
/** Project-relative route handler file (`app/llms.txt/route.ts`), or null. */
|
|
55
|
+
route: string | null;
|
|
56
|
+
/** The route uses site-kit's handler factory for this file. */
|
|
57
|
+
routeUsesKitHandler: boolean;
|
|
58
|
+
/** The route passes `noindex: false`. */
|
|
59
|
+
routeOptsOutOfNoindex: boolean;
|
|
60
|
+
/** The route sets `X-Robots-Tag: noindex` itself (a hand-rolled handler). */
|
|
61
|
+
routeSetsNoindex: boolean;
|
|
62
|
+
/** `public/<file>` exists, or createSitemap will write it at build. */
|
|
63
|
+
servedStatic: boolean;
|
|
64
|
+
/** Why it counts as static, for the message. */
|
|
65
|
+
staticReason: string | null;
|
|
66
|
+
/** Host config file that sends `X-Robots-Tag: noindex` for this path, or null. */
|
|
67
|
+
hostNoindex: string | null;
|
|
68
|
+
}
|
|
69
|
+
export interface GeoWiringFacts {
|
|
70
|
+
/** Project-relative app dir, or null when the site has none. */
|
|
71
|
+
appDir: string | null;
|
|
72
|
+
llms: LlmsFileFacts[];
|
|
73
|
+
/** Project-relative sitemap route file, or null. */
|
|
74
|
+
sitemap: string | null;
|
|
75
|
+
/** The sitemap lists /llms.txt or /llms-full.txt. */
|
|
76
|
+
sitemapListsLlms: boolean;
|
|
77
|
+
/** Where the `Link: rel="describedby"` discovery header is wired, or null. */
|
|
78
|
+
discovery: string | null;
|
|
79
|
+
/**
|
|
80
|
+
* A root layout that tries to send the header by exporting `headers()`,
|
|
81
|
+
* which Next never calls. Only set when nothing else sends it.
|
|
82
|
+
*/
|
|
83
|
+
layoutHeadersAttempt?: string | null;
|
|
84
|
+
}
|
|
85
|
+
/** The host config file that sends `X-Robots-Tag: noindex` for `urlPath`, or null. */
|
|
86
|
+
export declare function findHostNoindex(cwd: string, urlPath: string): string | null;
|
|
87
|
+
/**
|
|
88
|
+
* Where the `Link: rel="describedby"` header for /llms.txt is wired, or null.
|
|
89
|
+
* First match wins, in the order sites actually wire it.
|
|
90
|
+
*/
|
|
91
|
+
export declare function findDiscoverySource(cwd: string): string | null;
|
|
92
|
+
/**
|
|
93
|
+
* The root layout, when it tries to send the header itself. A layout can't:
|
|
94
|
+
* `export async function headers()` there is an ordinary unused function.
|
|
95
|
+
*/
|
|
96
|
+
export declare function findLayoutHeadersAttempt(cwd: string): string | null;
|
|
97
|
+
/** Read the observable facts. No judgement here — that is `judgeGeoWiring`. */
|
|
98
|
+
export declare function readGeoWiring(cwd: string): GeoWiringFacts;
|
|
99
|
+
/** Turn the facts into rows, in display order. */
|
|
100
|
+
export declare function judgeGeoWiring(facts: GeoWiringFacts): GeoRow[];
|
|
101
|
+
/** Convenience: read + judge in one call. */
|
|
102
|
+
export declare function checkGeoWiring(cwd: string): GeoRow[];
|
|
103
|
+
//# sourceMappingURL=wiring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wiring.d.ts","sourceRoot":"","sources":["../../src/llms/wiring.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAcH,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;AAEtD,MAAM,WAAW,MAAM;IACrB,iCAAiC;IACjC,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,QAAQ,CAAA;IACf,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,gBAAgB,CAAA;AAExD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAA;IACjB,8EAA8E;IAC9E,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,+DAA+D;IAC/D,mBAAmB,EAAE,OAAO,CAAA;IAC5B,yCAAyC;IACzC,qBAAqB,EAAE,OAAO,CAAA;IAC9B,6EAA6E;IAC7E,gBAAgB,EAAE,OAAO,CAAA;IACzB,uEAAuE;IACvE,YAAY,EAAE,OAAO,CAAA;IACrB,gDAAgD;IAChD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,kFAAkF;IAClF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,gEAAgE;IAChE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,IAAI,EAAE,aAAa,EAAE,CAAA;IACrB,oDAAoD;IACpD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,qDAAqD;IACrD,gBAAgB,EAAE,OAAO,CAAA;IACzB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACrC;AAuFD,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ3E;AAUD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAuB9D;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOnE;AAED,+EAA+E;AAC/E,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CA4CzD;AAaD,kDAAkD;AAClD,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,EAAE,CAmF9D;AAED,6CAA6C;AAC7C,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAEpD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wiring.test.d.ts","sourceRoot":"","sources":["../../src/llms/wiring.test.ts"],"names":[],"mappings":""}
|
|
@@ -29,6 +29,15 @@ export interface WriteLLMsTxtOptions {
|
|
|
29
29
|
* from NEXT_PUBLIC_SITE_URL via the shared `resolveSiteHost`.
|
|
30
30
|
*/
|
|
31
31
|
site?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Match Next's `trailingSlash` in the written files' links to this site.
|
|
34
|
+
* Portal builds its links from unslashed paths, so on a `trailingSlash: true`
|
|
35
|
+
* site they're rewritten here before the write. createSitemap passes its
|
|
36
|
+
* resolved value. The default reads next.config through Next's bundle,
|
|
37
|
+
* which a plain-Node postbuild script doesn't have, so pass it explicitly
|
|
38
|
+
* there.
|
|
39
|
+
*/
|
|
40
|
+
trailingSlash?: boolean;
|
|
32
41
|
/** When Portal returns empty services/faq/pages, use this to supply local site data */
|
|
33
42
|
getLocalData?: () => Promise<LLMsDataResponse | null>;
|
|
34
43
|
/** Forward to GET /api/public/llms/txt and align local fallback with site-kit strict page notes */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writeLLMsTxt.d.ts","sourceRoot":"","sources":["../../src/llms/writeLLMsTxt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,gBAAgB,EAAkB,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"writeLLMsTxt.d.ts","sourceRoot":"","sources":["../../src/llms/writeLLMsTxt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,gBAAgB,EAAkB,MAAM,SAAS,CAAA;AAK/D,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,qBAAqB;IACrB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,qBAAqB;IACrB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,+CAA+C;IAC/C,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,uFAAuF;IACvF,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAA;IACrD,mGAAmG;IACnG,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B;;;;;;;;;OASG;IACH,cAAc,CAAC,EACX,iBAAiB,EAAE,GACnB,CAAC,MAAM,OAAO,CAAC,iBAAiB,EAAE,GAAG,IAAI,CAAC,GAAG,iBAAiB,EAAE,GAAG,IAAI,CAAC,CAAA;CAC7E;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC,CAoFjE"}
|
package/dist/maps/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
5
|
-
require('../chunk-
|
|
6
|
-
require('../chunk-
|
|
4
|
+
var chunkPRTXAIIC_js = require('../chunk-PRTXAIIC.js');
|
|
5
|
+
require('../chunk-UWHCHYCX.js');
|
|
6
|
+
require('../chunk-5O7JSWT6.js');
|
|
7
7
|
require('../chunk-SNAQBZPT.js');
|
|
8
8
|
var react = require('react');
|
|
9
9
|
var reactGoogleMaps = require('@vis.gl/react-google-maps');
|
|
@@ -141,7 +141,7 @@ async function fetchMapsConfig() {
|
|
|
141
141
|
const { apiUrl, apiKey } = getApiConfig();
|
|
142
142
|
if (apiKey) {
|
|
143
143
|
try {
|
|
144
|
-
const res = await
|
|
144
|
+
const res = await chunkPRTXAIIC_js.sonorFetch(
|
|
145
145
|
`${apiUrl}/api/public/maps/config`,
|
|
146
146
|
{ headers: { "Content-Type": "application/json" } },
|
|
147
147
|
{ apiKey }
|
|
@@ -181,7 +181,7 @@ async function fetchNearbyPlaces(params) {
|
|
|
181
181
|
});
|
|
182
182
|
if (params.radius) searchParams.set("radius", String(params.radius));
|
|
183
183
|
if (params.limit) searchParams.set("limit", String(params.limit));
|
|
184
|
-
const res = await
|
|
184
|
+
const res = await chunkPRTXAIIC_js.sonorFetch(
|
|
185
185
|
`${apiUrl}/api/public/maps/nearby-places?${searchParams}`,
|
|
186
186
|
{ headers: { "Content-Type": "application/json" } },
|
|
187
187
|
{ apiKey }
|
package/dist/maps/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { sonorFetch } from '../chunk-
|
|
3
|
-
import '../chunk-
|
|
4
|
-
import '../chunk-
|
|
2
|
+
import { sonorFetch } from '../chunk-7THZOAUR.mjs';
|
|
3
|
+
import '../chunk-PUAXHYBL.mjs';
|
|
4
|
+
import '../chunk-HRMGITUZ.mjs';
|
|
5
5
|
import '../chunk-BEXTDHO4.mjs';
|
|
6
6
|
import { useState, useCallback, useEffect } from 'react';
|
|
7
7
|
import { APIProvider, Map as Map$1, AdvancedMarker, Pin, InfoWindow } from '@vis.gl/react-google-maps';
|
package/dist/motion/gsap.d.ts
CHANGED
|
@@ -35,22 +35,68 @@ export interface GsapBundle {
|
|
|
35
35
|
* promise. Safe to call from anywhere; resolves the same bundle every time.
|
|
36
36
|
*/
|
|
37
37
|
export declare function loadGsap(): Promise<GsapBundle>;
|
|
38
|
+
/** Dynamic imports of GSAP plugins, by name: `{ SplitText: () => import('gsap/SplitText') }`. */
|
|
39
|
+
export type GsapPluginLoaders = Record<string, () => Promise<unknown>>;
|
|
40
|
+
type GsapContext = ReturnType<Gsap['context']>;
|
|
38
41
|
export interface GsapSetupContext extends GsapBundle {
|
|
39
42
|
/** The element the hook is attached to — use it as the ScrollTrigger trigger and the selector scope. */
|
|
40
43
|
el: HTMLElement;
|
|
44
|
+
/**
|
|
45
|
+
* The plugins asked for in `options.plugins`, loaded and registered before
|
|
46
|
+
* setup runs, by the same names: `plugins.SplitText`.
|
|
47
|
+
*/
|
|
48
|
+
plugins: Record<string, any>;
|
|
49
|
+
/**
|
|
50
|
+
* The gsap.context setup runs in. Anything setup starts asynchronously
|
|
51
|
+
* (after an await, in a timer, in a plugin callback that fires later)
|
|
52
|
+
* lands outside it, so wrap that work in `context.add(() => ...)` to have
|
|
53
|
+
* it scoped and reverted on unmount with the rest.
|
|
54
|
+
*/
|
|
55
|
+
context: GsapContext;
|
|
41
56
|
}
|
|
42
57
|
export interface UseGsapOptions {
|
|
43
58
|
/** Preload margin: load gsap when the element is this close. Default "200px 0px". */
|
|
44
59
|
near?: string;
|
|
45
60
|
/** "skip" (default) does nothing under prefers-reduced-motion; "run" lets setup decide. */
|
|
46
61
|
reducedMotion?: 'skip' | 'run';
|
|
62
|
+
/**
|
|
63
|
+
* GSAP plugins to load alongside gsap, as dynamic imports keyed by name:
|
|
64
|
+
*
|
|
65
|
+
* { plugins: { SplitText: () => import('gsap/SplitText') } }
|
|
66
|
+
*
|
|
67
|
+
* They're loaded when gsap is, registered, and handed to setup as
|
|
68
|
+
* `plugins`, so setup can stay synchronous. That matters: gsap.context
|
|
69
|
+
* only records what runs synchronously inside it, so a plugin imported
|
|
70
|
+
* from within setup did its work outside the context, unscoped and never
|
|
71
|
+
* reverted on unmount (vsf-consulting-nextjs's SplitHeading had to build a
|
|
72
|
+
* second context of its own to clean up).
|
|
73
|
+
*/
|
|
74
|
+
plugins?: GsapPluginLoaders;
|
|
47
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Load plugins by name, once per name for the page, and register them with
|
|
78
|
+
* gsap. Resolves to the plugins keyed by the same names.
|
|
79
|
+
*/
|
|
80
|
+
export declare function loadGsapPlugins(gsap: Gsap, loaders?: GsapPluginLoaders): Promise<Record<string, any>>;
|
|
81
|
+
/**
|
|
82
|
+
* Run a setup inside a gsap.context scoped to `el`, synchronously. Split out
|
|
83
|
+
* of useGsap so the contract (everything setup creates belongs to the
|
|
84
|
+
* returned context, plugins included) is testable without a DOM.
|
|
85
|
+
*/
|
|
86
|
+
export declare function runGsapSetup(bundle: GsapBundle, el: HTMLElement, plugins: Record<string, any>, setup: (ctx: GsapSetupContext) => void | (() => void)): {
|
|
87
|
+
context: GsapContext;
|
|
88
|
+
cleanup: (() => void) | void;
|
|
89
|
+
};
|
|
48
90
|
/**
|
|
49
91
|
* Run a GSAP setup against an element, lazily and safely:
|
|
50
92
|
*
|
|
51
93
|
* - gsap loads only when the element nears the viewport
|
|
52
94
|
* - setup runs inside `gsap.context(el)`, so selectors are scoped and
|
|
53
95
|
* everything it creates is reverted on unmount (including ScrollTriggers)
|
|
96
|
+
* - plugins beyond ScrollTrigger (SplitText, Flip, MorphSVG) come in through
|
|
97
|
+
* `options.plugins`, loaded before setup, so setup stays synchronous and
|
|
98
|
+
* inside the context. Anything setup must still start later goes through
|
|
99
|
+
* `context.add()`.
|
|
54
100
|
* - the element must be server-rendered and visible; hide things inside
|
|
55
101
|
* `setup` with `gsap.set`, never with a stylesheet
|
|
56
102
|
*
|
|
@@ -62,6 +108,14 @@ export interface UseGsapOptions {
|
|
|
62
108
|
* scrollTrigger: { trigger: el, start: 'top 80%' },
|
|
63
109
|
* })
|
|
64
110
|
* })
|
|
111
|
+
*
|
|
112
|
+
* @example With a plugin
|
|
113
|
+
* useGsap(ref, ({ gsap, el, plugins: { SplitText } }) => {
|
|
114
|
+
* SplitText.create(el, {
|
|
115
|
+
* type: 'lines', mask: 'lines', autoSplit: true,
|
|
116
|
+
* onSplit: self => gsap.from(self.lines, { yPercent: 115, stagger: 0.09, scrollTrigger: { trigger: el } }),
|
|
117
|
+
* })
|
|
118
|
+
* }, [], { plugins: { SplitText: () => import('gsap/SplitText') } })
|
|
65
119
|
*/
|
|
66
120
|
export declare function useGsap(ref: RefObject<HTMLElement | null>, setup: (ctx: GsapSetupContext) => void | (() => void), deps?: DependencyList, options?: UseGsapOptions): void;
|
|
67
121
|
export interface ExpandCollapseOptions {
|
|
@@ -1 +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;
|
|
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,iGAAiG;AACjG,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;AAEtE,KAAK,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAA;AAE9C,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAClD,wGAAwG;IACxG,EAAE,EAAE,WAAW,CAAA;IACf;;;OAGG;IAEH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC5B;;;;;OAKG;IACH,OAAO,EAAE,WAAW,CAAA;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,qFAAqF;IACrF,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,2FAA2F;IAC3F,aAAa,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;IAC9B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,EAAE,iBAAiB,CAAA;CAC5B;AAUD;;;GAGG;AAEH,wBAAsB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAgB/G;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,UAAU,EAClB,EAAE,EAAE,WAAW,EAEf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC5B,KAAK,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,GACpD;IAAE,OAAO,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAA;CAAE,CAMxD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;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,CAyCN;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"}
|
package/dist/motion/gsap.js
CHANGED
|
@@ -17,9 +17,39 @@ function loadGsap() {
|
|
|
17
17
|
}
|
|
18
18
|
return pending;
|
|
19
19
|
}
|
|
20
|
+
var pluginCache = /* @__PURE__ */ new Map();
|
|
21
|
+
function pickPlugin(mod, name) {
|
|
22
|
+
const m = mod;
|
|
23
|
+
return (m && (m[name] ?? m.default)) ?? mod;
|
|
24
|
+
}
|
|
25
|
+
async function loadGsapPlugins(gsap, loaders = {}) {
|
|
26
|
+
const entries = await Promise.all(
|
|
27
|
+
Object.entries(loaders).map(async ([name, load]) => {
|
|
28
|
+
let pending2 = pluginCache.get(name);
|
|
29
|
+
if (!pending2) {
|
|
30
|
+
pending2 = load().then((mod) => pickPlugin(mod, name));
|
|
31
|
+
pluginCache.set(name, pending2);
|
|
32
|
+
}
|
|
33
|
+
return [name, await pending2];
|
|
34
|
+
})
|
|
35
|
+
);
|
|
36
|
+
const plugins = Object.fromEntries(entries);
|
|
37
|
+
const list = Object.values(plugins);
|
|
38
|
+
if (list.length) gsap.registerPlugin(...list);
|
|
39
|
+
return plugins;
|
|
40
|
+
}
|
|
41
|
+
function runGsapSetup(bundle, el, plugins, setup) {
|
|
42
|
+
let cleanup = void 0;
|
|
43
|
+
const context = bundle.gsap.context((self) => {
|
|
44
|
+
cleanup = setup({ ...bundle, el, plugins, context: self });
|
|
45
|
+
}, el);
|
|
46
|
+
return { context, cleanup };
|
|
47
|
+
}
|
|
20
48
|
function useGsap(ref, setup, deps = [], options = {}) {
|
|
21
49
|
const setupRef = react.useRef(setup);
|
|
22
50
|
setupRef.current = setup;
|
|
51
|
+
const pluginsRef = react.useRef(options.plugins);
|
|
52
|
+
pluginsRef.current = options.plugins;
|
|
23
53
|
const { near = "200px 0px", reducedMotion = "skip" } = options;
|
|
24
54
|
react.useEffect(() => {
|
|
25
55
|
const el = ref.current;
|
|
@@ -32,11 +62,9 @@ function useGsap(ref, setup, deps = [], options = {}) {
|
|
|
32
62
|
([entry]) => {
|
|
33
63
|
if (!entry?.isIntersecting) return;
|
|
34
64
|
io.disconnect();
|
|
35
|
-
loadGsap().then(({ gsap,
|
|
65
|
+
loadGsap().then(async (bundle) => ({ bundle, plugins: await loadGsapPlugins(bundle.gsap, pluginsRef.current) })).then(({ bundle, plugins }) => {
|
|
36
66
|
if (cancelled || !el.isConnected) return;
|
|
37
|
-
ctx =
|
|
38
|
-
cleanup = setupRef.current({ gsap, ScrollTrigger, el });
|
|
39
|
-
}, el);
|
|
67
|
+
({ context: ctx, cleanup } = runGsapSetup(bundle, el, plugins, setupRef.current));
|
|
40
68
|
});
|
|
41
69
|
},
|
|
42
70
|
{ rootMargin: near }
|
|
@@ -97,6 +125,8 @@ function useExpandCollapse(isOpen, options = {}) {
|
|
|
97
125
|
}
|
|
98
126
|
|
|
99
127
|
exports.loadGsap = loadGsap;
|
|
128
|
+
exports.loadGsapPlugins = loadGsapPlugins;
|
|
129
|
+
exports.runGsapSetup = runGsapSetup;
|
|
100
130
|
exports.useExpandCollapse = useExpandCollapse;
|
|
101
131
|
exports.useGsap = useGsap;
|
|
102
132
|
//# sourceMappingURL=gsap.js.map
|
package/dist/motion/gsap.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/motion/gsap.ts"],"names":["useRef","useEffect","prefersReducedMotion"],"mappings":";;;;;;AAwCA,IAAI,OAAA,GAAsC,IAAA;AAMnC,SAAS,QAAA,GAAgC;AAC9C,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAA,GAAU,QAAQ,GAAA,CAAI,CAAC,OAAO,MAAM,GAAG,OAAO,oBAAoB,CAAC,CAAC,EAAE,IAAA,CAAK,CAAC,CAAC,CAAA,EAAG,EAAE,CAAA,KAAM;AACtF,MAAA,MAAM,IAAA,GAAO,CAAA,CAAE,IAAA,IAAQ,CAAA,CAAE,OAAA;AACzB,MAAA,MAAM,aAAA,GAAgB,EAAA,CAAG,aAAA,IAAiB,EAAA,CAAG,OAAA;AAC7C,MAAA,IAAA,CAAK,eAAe,aAAa,CAAA;AACjC,MAAA,OAAO,EAAE,MAAM,aAAA,EAAc;AAAA,IAC/B,CAAC,CAAA;AAAA,EACH;AACA,EAAA,OAAO,OAAA;AACT;AAgCO,SAAS,OAAA,CACd,KACA,KAAA,EACA,IAAA,GAAuB,EAAC,EACxB,OAAA,GAA0B,EAAC,EACrB;AACN,EAAA,MAAM,QAAA,GAAWA,aAAO,KAAK,CAAA;AAC7B,EAAA,QAAA,CAAS,OAAA,GAAU,KAAA;AACnB,EAAA,MAAM,EAAE,IAAA,GAAO,WAAA,EAAa,aAAA,GAAgB,QAAO,GAAI,OAAA;AAEvD,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,MAAM,KAAK,GAAA,CAAI,OAAA;AACf,IAAA,IAAI,CAAC,EAAA,EAAI;AACT,IAAA,IAAI,aAAA,KAAkB,MAAA,IAAUC,qCAAA,EAAqB,EAAG;AAExD,IAAA,IAAI,SAAA,GAAY,KAAA;AAChB,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI,GAAA;AAEJ,IAAA,MAAM,KAAK,IAAI,oBAAA;AAAA,MACb,CAAC,CAAC,KAAK,CAAA,KAAM;AACX,QAAA,IAAI,CAAC,OAAO,cAAA,EAAgB;AAC5B,QAAA,EAAA,CAAG,UAAA,EAAW;AACd,QAAA,QAAA,GAAW,IAAA,CAAK,CAAC,EAAE,IAAA,EAAM,eAAc,KAAM;AAC3C,UAAA,IAAI,SAAA,IAAa,CAAC,EAAA,CAAG,WAAA,EAAa;AAClC,UAAA,GAAA,GAAM,IAAA,CAAK,QAAQ,MAAM;AACvB,YAAA,OAAA,GAAU,SAAS,OAAA,CAAQ,EAAE,IAAA,EAAM,aAAA,EAAe,IAAI,CAAA;AAAA,UACxD,GAAG,EAAE,CAAA;AAAA,QACP,CAAC,CAAA;AAAA,MACH,CAAA;AAAA,MACA,EAAE,YAAY,IAAA;AAAK,KACrB;AACA,IAAA,EAAA,CAAG,QAAQ,EAAE,CAAA;AAEb,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,GAAY,IAAA;AACZ,MAAA,EAAA,CAAG,UAAA,EAAW;AACd,MAAA,IAAI,OAAO,OAAA,KAAY,UAAA,EAAY,OAAA,EAAQ;AAC3C,MAAA,GAAA,EAAK,MAAA,EAAO;AAAA,IACd,CAAA;AAAA,EAEF,GAAG,CAAC,GAAA,EAAK,MAAM,aAAA,EAAe,GAAG,IAAI,CAAC,CAAA;AACxC;AAgBO,SAAS,iBAAA,CACd,MAAA,EACA,OAAA,GAAiC,EAAC,EACgB;AAClD,EAAA,MAAM,EAAE,QAAA,GAAW,GAAA,EAAK,IAAA,GAAO,gBAAe,GAAI,OAAA;AAClD,EAAA,MAAM,UAAA,GAAaF,aAAuB,IAAI,CAAA;AAC9C,EAAA,MAAM,WAAA,GAAcA,aAAO,KAAK,CAAA;AAEhC,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,MAAM,KAAK,UAAA,CAAW,OAAA;AACtB,IAAA,IAAI,CAAC,EAAA,EAAI;AAGT,IAAA,IAAI,CAAC,YAAY,OAAA,EAAS;AACxB,MAAA,WAAA,CAAY,OAAA,GAAU,IAAA;AACtB,MAAA,EAAA,CAAG,MAAM,QAAA,GAAW,QAAA;AACpB,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,EAAA,CAAG,MAAM,MAAA,GAAS,KAAA;AAClB,QAAA,EAAA,CAAG,MAAM,OAAA,GAAU,GAAA;AAAA,MACrB;AACA,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,SAAA,GAAY,KAAA;AAChB,IAAA,QAAA,EAAS,CAAE,IAAA,CAAK,CAAC,EAAE,MAAK,KAAM;AAC5B,MAAA,IAAI,SAAA,IAAa,CAAC,EAAA,CAAG,WAAA,EAAa;AAClC,MAAA,IAAIC,uCAAqB,EAAG;AAC1B,QAAA,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,EAAE,MAAA,EAAQ,MAAA,GAAS,MAAA,GAAS,CAAA,EAAG,OAAA,EAAS,MAAA,GAAS,CAAA,GAAI,CAAA,EAAG,CAAA;AACrE,QAAA,EAAA,CAAG,KAAA,CAAM,QAAA,GAAW,MAAA,GAAS,SAAA,GAAY,QAAA;AACzC,QAAA;AAAA,MACF;AACA,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,IAAA,CAAK,GAAG,EAAA,EAAI;AAAA,UACV,MAAA,EAAQ,MAAA;AAAA,UACR,OAAA,EAAS,CAAA;AAAA,UACT,QAAA;AAAA,UACA,IAAA;AAAA,UACA,UAAA,GAAa;AACX,YAAA,EAAA,CAAG,MAAM,QAAA,GAAW,SAAA;AAAA,UACtB;AAAA,SACD,CAAA;AAAA,MACH,CAAA,MAAO;AACL,QAAA,EAAA,CAAG,MAAM,QAAA,GAAW,QAAA;AACpB,QAAA,IAAA,CAAK,EAAA,CAAG,EAAA,EAAI,EAAE,MAAA,EAAQ,CAAA,EAAG,OAAA,EAAS,CAAA,EAAG,QAAA,EAAU,QAAA,GAAW,IAAA,EAAM,IAAA,EAAM,CAAA;AAAA,MACxE;AAAA,IACF,CAAC,CAAA;AACD,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,GAAY,IAAA;AAAA,IACd,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,QAAA,EAAU,IAAI,CAAC,CAAA;AAE3B,EAAA,OAAO,EAAE,UAAA,EAAW;AACtB","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"]}
|
|
1
|
+
{"version":3,"sources":["../../src/motion/gsap.ts"],"names":["pending","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\n/** Dynamic imports of GSAP plugins, by name: `{ SplitText: () => import('gsap/SplitText') }`. */\nexport type GsapPluginLoaders = Record<string, () => Promise<unknown>>\n\ntype GsapContext = ReturnType<Gsap['context']>\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 * The plugins asked for in `options.plugins`, loaded and registered before\n * setup runs, by the same names: `plugins.SplitText`.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n plugins: Record<string, any>\n /**\n * The gsap.context setup runs in. Anything setup starts asynchronously\n * (after an await, in a timer, in a plugin callback that fires later)\n * lands outside it, so wrap that work in `context.add(() => ...)` to have\n * it scoped and reverted on unmount with the rest.\n */\n context: GsapContext\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 * GSAP plugins to load alongside gsap, as dynamic imports keyed by name:\n *\n * { plugins: { SplitText: () => import('gsap/SplitText') } }\n *\n * They're loaded when gsap is, registered, and handed to setup as\n * `plugins`, so setup can stay synchronous. That matters: gsap.context\n * only records what runs synchronously inside it, so a plugin imported\n * from within setup did its work outside the context, unscoped and never\n * reverted on unmount (vsf-consulting-nextjs's SplitHeading had to build a\n * second context of its own to clean up).\n */\n plugins?: GsapPluginLoaders\n}\n\nconst pluginCache = new Map<string, Promise<unknown>>()\n\n/** The plugin object out of its module: the named export, else the default. */\nfunction pickPlugin(mod: unknown, name: string): unknown {\n const m = mod as Record<string, unknown> | null\n return (m && (m[name] ?? m.default)) ?? mod\n}\n\n/**\n * Load plugins by name, once per name for the page, and register them with\n * gsap. Resolves to the plugins keyed by the same names.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function loadGsapPlugins(gsap: Gsap, loaders: GsapPluginLoaders = {}): Promise<Record<string, any>> {\n const entries = await Promise.all(\n Object.entries(loaders).map(async ([name, load]) => {\n let pending = pluginCache.get(name)\n if (!pending) {\n pending = load().then(mod => pickPlugin(mod, name))\n pluginCache.set(name, pending)\n }\n return [name, await pending] as const\n }),\n )\n const plugins = Object.fromEntries(entries)\n const list = Object.values(plugins)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (list.length) gsap.registerPlugin(...(list as any[]))\n return plugins\n}\n\n/**\n * Run a setup inside a gsap.context scoped to `el`, synchronously. Split out\n * of useGsap so the contract (everything setup creates belongs to the\n * returned context, plugins included) is testable without a DOM.\n */\nexport function runGsapSetup(\n bundle: GsapBundle,\n el: HTMLElement,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n plugins: Record<string, any>,\n setup: (ctx: GsapSetupContext) => void | (() => void),\n): { context: GsapContext; cleanup: (() => void) | void } {\n let cleanup: (() => void) | void = undefined\n const context = bundle.gsap.context((self: GsapContext) => {\n cleanup = setup({ ...bundle, el, plugins, context: self })\n }, el)\n return { context, cleanup }\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 * - plugins beyond ScrollTrigger (SplitText, Flip, MorphSVG) come in through\n * `options.plugins`, loaded before setup, so setup stays synchronous and\n * inside the context. Anything setup must still start later goes through\n * `context.add()`.\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 *\n * @example With a plugin\n * useGsap(ref, ({ gsap, el, plugins: { SplitText } }) => {\n * SplitText.create(el, {\n * type: 'lines', mask: 'lines', autoSplit: true,\n * onSplit: self => gsap.from(self.lines, { yPercent: 115, stagger: 0.09, scrollTrigger: { trigger: el } }),\n * })\n * }, [], { plugins: { SplitText: () => import('gsap/SplitText') } })\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 // A ref, like setup: an inline `plugins` object is new every render and\n // must not re-run the effect.\n const pluginsRef = useRef(options.plugins)\n pluginsRef.current = options.plugins\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: GsapContext | undefined\n\n const io = new IntersectionObserver(\n ([entry]) => {\n if (!entry?.isIntersecting) return\n io.disconnect()\n loadGsap()\n .then(async bundle => ({ bundle, plugins: await loadGsapPlugins(bundle.gsap, pluginsRef.current) }))\n .then(({ bundle, plugins }) => {\n if (cancelled || !el.isConnected) return\n ;({ context: ctx, cleanup } = runGsapSetup(bundle, el, plugins, setupRef.current))\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"]}
|
package/dist/motion/gsap.mjs
CHANGED
|
@@ -15,9 +15,39 @@ function loadGsap() {
|
|
|
15
15
|
}
|
|
16
16
|
return pending;
|
|
17
17
|
}
|
|
18
|
+
var pluginCache = /* @__PURE__ */ new Map();
|
|
19
|
+
function pickPlugin(mod, name) {
|
|
20
|
+
const m = mod;
|
|
21
|
+
return (m && (m[name] ?? m.default)) ?? mod;
|
|
22
|
+
}
|
|
23
|
+
async function loadGsapPlugins(gsap, loaders = {}) {
|
|
24
|
+
const entries = await Promise.all(
|
|
25
|
+
Object.entries(loaders).map(async ([name, load]) => {
|
|
26
|
+
let pending2 = pluginCache.get(name);
|
|
27
|
+
if (!pending2) {
|
|
28
|
+
pending2 = load().then((mod) => pickPlugin(mod, name));
|
|
29
|
+
pluginCache.set(name, pending2);
|
|
30
|
+
}
|
|
31
|
+
return [name, await pending2];
|
|
32
|
+
})
|
|
33
|
+
);
|
|
34
|
+
const plugins = Object.fromEntries(entries);
|
|
35
|
+
const list = Object.values(plugins);
|
|
36
|
+
if (list.length) gsap.registerPlugin(...list);
|
|
37
|
+
return plugins;
|
|
38
|
+
}
|
|
39
|
+
function runGsapSetup(bundle, el, plugins, setup) {
|
|
40
|
+
let cleanup = void 0;
|
|
41
|
+
const context = bundle.gsap.context((self) => {
|
|
42
|
+
cleanup = setup({ ...bundle, el, plugins, context: self });
|
|
43
|
+
}, el);
|
|
44
|
+
return { context, cleanup };
|
|
45
|
+
}
|
|
18
46
|
function useGsap(ref, setup, deps = [], options = {}) {
|
|
19
47
|
const setupRef = useRef(setup);
|
|
20
48
|
setupRef.current = setup;
|
|
49
|
+
const pluginsRef = useRef(options.plugins);
|
|
50
|
+
pluginsRef.current = options.plugins;
|
|
21
51
|
const { near = "200px 0px", reducedMotion = "skip" } = options;
|
|
22
52
|
useEffect(() => {
|
|
23
53
|
const el = ref.current;
|
|
@@ -30,11 +60,9 @@ function useGsap(ref, setup, deps = [], options = {}) {
|
|
|
30
60
|
([entry]) => {
|
|
31
61
|
if (!entry?.isIntersecting) return;
|
|
32
62
|
io.disconnect();
|
|
33
|
-
loadGsap().then(({ gsap,
|
|
63
|
+
loadGsap().then(async (bundle) => ({ bundle, plugins: await loadGsapPlugins(bundle.gsap, pluginsRef.current) })).then(({ bundle, plugins }) => {
|
|
34
64
|
if (cancelled || !el.isConnected) return;
|
|
35
|
-
ctx =
|
|
36
|
-
cleanup = setupRef.current({ gsap, ScrollTrigger, el });
|
|
37
|
-
}, el);
|
|
65
|
+
({ context: ctx, cleanup } = runGsapSetup(bundle, el, plugins, setupRef.current));
|
|
38
66
|
});
|
|
39
67
|
},
|
|
40
68
|
{ rootMargin: near }
|
|
@@ -94,6 +122,6 @@ function useExpandCollapse(isOpen, options = {}) {
|
|
|
94
122
|
return { contentRef };
|
|
95
123
|
}
|
|
96
124
|
|
|
97
|
-
export { loadGsap, useExpandCollapse, useGsap };
|
|
125
|
+
export { loadGsap, loadGsapPlugins, runGsapSetup, useExpandCollapse, useGsap };
|
|
98
126
|
//# sourceMappingURL=gsap.mjs.map
|
|
99
127
|
//# sourceMappingURL=gsap.mjs.map
|
package/dist/motion/gsap.mjs.map
CHANGED
|
@@ -1 +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"]}
|
|
1
|
+
{"version":3,"sources":["../../src/motion/gsap.ts"],"names":["pending"],"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\n/** Dynamic imports of GSAP plugins, by name: `{ SplitText: () => import('gsap/SplitText') }`. */\nexport type GsapPluginLoaders = Record<string, () => Promise<unknown>>\n\ntype GsapContext = ReturnType<Gsap['context']>\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 * The plugins asked for in `options.plugins`, loaded and registered before\n * setup runs, by the same names: `plugins.SplitText`.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n plugins: Record<string, any>\n /**\n * The gsap.context setup runs in. Anything setup starts asynchronously\n * (after an await, in a timer, in a plugin callback that fires later)\n * lands outside it, so wrap that work in `context.add(() => ...)` to have\n * it scoped and reverted on unmount with the rest.\n */\n context: GsapContext\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 * GSAP plugins to load alongside gsap, as dynamic imports keyed by name:\n *\n * { plugins: { SplitText: () => import('gsap/SplitText') } }\n *\n * They're loaded when gsap is, registered, and handed to setup as\n * `plugins`, so setup can stay synchronous. That matters: gsap.context\n * only records what runs synchronously inside it, so a plugin imported\n * from within setup did its work outside the context, unscoped and never\n * reverted on unmount (vsf-consulting-nextjs's SplitHeading had to build a\n * second context of its own to clean up).\n */\n plugins?: GsapPluginLoaders\n}\n\nconst pluginCache = new Map<string, Promise<unknown>>()\n\n/** The plugin object out of its module: the named export, else the default. */\nfunction pickPlugin(mod: unknown, name: string): unknown {\n const m = mod as Record<string, unknown> | null\n return (m && (m[name] ?? m.default)) ?? mod\n}\n\n/**\n * Load plugins by name, once per name for the page, and register them with\n * gsap. Resolves to the plugins keyed by the same names.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function loadGsapPlugins(gsap: Gsap, loaders: GsapPluginLoaders = {}): Promise<Record<string, any>> {\n const entries = await Promise.all(\n Object.entries(loaders).map(async ([name, load]) => {\n let pending = pluginCache.get(name)\n if (!pending) {\n pending = load().then(mod => pickPlugin(mod, name))\n pluginCache.set(name, pending)\n }\n return [name, await pending] as const\n }),\n )\n const plugins = Object.fromEntries(entries)\n const list = Object.values(plugins)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (list.length) gsap.registerPlugin(...(list as any[]))\n return plugins\n}\n\n/**\n * Run a setup inside a gsap.context scoped to `el`, synchronously. Split out\n * of useGsap so the contract (everything setup creates belongs to the\n * returned context, plugins included) is testable without a DOM.\n */\nexport function runGsapSetup(\n bundle: GsapBundle,\n el: HTMLElement,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n plugins: Record<string, any>,\n setup: (ctx: GsapSetupContext) => void | (() => void),\n): { context: GsapContext; cleanup: (() => void) | void } {\n let cleanup: (() => void) | void = undefined\n const context = bundle.gsap.context((self: GsapContext) => {\n cleanup = setup({ ...bundle, el, plugins, context: self })\n }, el)\n return { context, cleanup }\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 * - plugins beyond ScrollTrigger (SplitText, Flip, MorphSVG) come in through\n * `options.plugins`, loaded before setup, so setup stays synchronous and\n * inside the context. Anything setup must still start later goes through\n * `context.add()`.\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 *\n * @example With a plugin\n * useGsap(ref, ({ gsap, el, plugins: { SplitText } }) => {\n * SplitText.create(el, {\n * type: 'lines', mask: 'lines', autoSplit: true,\n * onSplit: self => gsap.from(self.lines, { yPercent: 115, stagger: 0.09, scrollTrigger: { trigger: el } }),\n * })\n * }, [], { plugins: { SplitText: () => import('gsap/SplitText') } })\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 // A ref, like setup: an inline `plugins` object is new every render and\n // must not re-run the effect.\n const pluginsRef = useRef(options.plugins)\n pluginsRef.current = options.plugins\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: GsapContext | undefined\n\n const io = new IntersectionObserver(\n ([entry]) => {\n if (!entry?.isIntersecting) return\n io.disconnect()\n loadGsap()\n .then(async bundle => ({ bundle, plugins: await loadGsapPlugins(bundle.gsap, pluginsRef.current) }))\n .then(({ bundle, plugins }) => {\n if (cancelled || !el.isConnected) return\n ;({ context: ctx, cleanup } = runGsapSetup(bundle, el, plugins, setupRef.current))\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 @@
|
|
|
1
|
+
{"version":3,"file":"gsap.test.d.ts","sourceRoot":"","sources":["../../src/motion/gsap.test.ts"],"names":[],"mappings":""}
|
package/dist/og/config.d.ts
CHANGED
|
@@ -24,6 +24,12 @@ export interface OgTheme {
|
|
|
24
24
|
surface: string;
|
|
25
25
|
/** Muted text (subtitle). Defaults derived from `text` when omitted. */
|
|
26
26
|
muted?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Bottom-bar text, set on `accent`. Defaults to the first of `surface`,
|
|
29
|
+
* `bg`, `text` that reaches WCAG AA for large text (3:1) against the
|
|
30
|
+
* accent (see og/contrast.ts).
|
|
31
|
+
*/
|
|
32
|
+
barText?: string;
|
|
27
33
|
}
|
|
28
34
|
export interface OgFont {
|
|
29
35
|
/** Google Fonts family name, e.g. 'Barlow Condensed'. */
|
package/dist/og/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/og/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,OAAO;IACtB,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAA;IACV,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAA;IACf,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/og/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,OAAO;IACtB,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAA;IACV,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAA;IACf,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,MAAM;IACrB,yDAAyD;IACzD,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAA;IACb,6BAA6B;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,OAAO;IACtB,iEAAiE;IACjE,GAAG,EAAE,MAAM,CAAA;IACX,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAA;IACb,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,mEAAmE;IACnE,GAAG,CAAC,EAAE,MAAM,EAAE,CAAA;CACf;AAED;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,GAAG,SAAS,CAAC,CAAC,GAAG;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAA;CAC7B,CAAA;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,OAAO,CAAA;IACd,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,gFAAgF;IAChF,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,YAAY,CAAA;IACzB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,YAAY,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,CAAA;IACvD,0GAA0G;IAC1G,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,SAAS,CAAA;IAClB;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IACtC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB,KAAK,MAAM,CAAA;IACvE,mEAAmE;IACnE,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,6BAA6B;IAC7B,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IAC1B,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAE/D;AAED,eAAO,MAAM,QAAQ,OAAO,CAAA;AAC5B,eAAO,MAAM,SAAS,MAAM,CAAA;AAE5B;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,MAAM,CAAA;AAC/B,eAAO,MAAM,YAAY,KAAK,CAAA;AAE9B;;;;GAIG;AACH,eAAO,MAAM,cAAc,mBAAmB,CAAA;AAE9C,kEAAkE;AAClE,MAAM,WAAW,cAAc;IAC7B,8EAA8E;IAC9E,IAAI,EAAE,OAAO,CAAA;IACb,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAA;IACf,yEAAyE;IACzE,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sonordev/site-kit/og — text color for the card's bottom bar.
|
|
3
|
+
*
|
|
4
|
+
* SINGLE SOURCE OF TRUTH for "what color is the bar text", shared by the
|
|
5
|
+
* build-time template (template.ts) and the runtime card (route.tsx). The two
|
|
6
|
+
* disagreed: the template set the bar in `theme.surface`, the runtime card in
|
|
7
|
+
* `theme.text`, and on a site whose text and accent are both strong colors the
|
|
8
|
+
* runtime bar came out unreadable (navy on crimson on watsonhac.com, ink on
|
|
9
|
+
* green on reinhart). Both sites dropped the bar rather than ship it.
|
|
10
|
+
*
|
|
11
|
+
* `theme.barText` always wins. Otherwise the first candidate that reaches
|
|
12
|
+
* WCAG AA for large text against the accent is used, in the order the
|
|
13
|
+
* template always preferred (surface, then bg, then text), so every card
|
|
14
|
+
* that already read well keeps its color. Failing that, the highest-contrast
|
|
15
|
+
* candidate.
|
|
16
|
+
*
|
|
17
|
+
* Pure: no DOM, no Node built-ins.
|
|
18
|
+
*/
|
|
19
|
+
/** `#abc`, `#aabbcc`, `#aabbccdd` → [r, g, b] in 0-255, or null for anything else. */
|
|
20
|
+
export declare function parseHexColor(color: string): [number, number, number] | null;
|
|
21
|
+
/** WCAG contrast ratio of two hex colors, or null when either isn't hex. */
|
|
22
|
+
export declare function contrastRatio(a: string, b: string): number | null;
|
|
23
|
+
export interface BarTheme {
|
|
24
|
+
bg: string;
|
|
25
|
+
text: string;
|
|
26
|
+
accent: string;
|
|
27
|
+
surface?: string;
|
|
28
|
+
/** Explicit bar text color. Always wins. */
|
|
29
|
+
barText?: string;
|
|
30
|
+
}
|
|
31
|
+
/** The color to set the bottom bar's text in, on `theme.accent`. */
|
|
32
|
+
export declare function barTextColor(theme: BarTheme): string;
|
|
33
|
+
//# sourceMappingURL=contrast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contrast.d.ts","sourceRoot":"","sources":["../../src/og/contrast.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AASH,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAK5E;AAUD,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMjE;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAUpD"}
|
package/dist/og/index.d.ts
CHANGED
|
@@ -5,4 +5,6 @@
|
|
|
5
5
|
export { defineOgCard, OG_WIDTH, OG_HEIGHT } from './config';
|
|
6
6
|
export type { OgCardConfig, OgTheme, OgFont, OgBackground, OgContent, OgPhoto, OgTemplateHelpers } from './config';
|
|
7
7
|
export { buildOgHtml } from './template';
|
|
8
|
+
export { paramCardImage, paramCardUrl, codeCardImage, PARAM_CARD_DIR } from './pages';
|
|
9
|
+
export type { OgImageDescriptor } from './pages';
|
|
8
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/og/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/og/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAC5D,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAClH,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/og/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAC5D,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAClH,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AACxC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AACrF,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA"}
|