@ignix-social/editor 0.1.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/LICENSE +190 -0
- package/NOTICE +54 -0
- package/README.md +23 -0
- package/bin/ignix-editor.mjs +8 -0
- package/package.json +53 -0
- package/patches/index.mjs +53 -0
- package/scripts/build-ffmpeg-macos.sh +35 -0
- package/scripts/build-whisper-macos.sh +21 -0
- package/scripts/vendor.mjs +41 -0
- package/skills/ignix-editor/SKILL.md +132 -0
- package/src/audio.mjs +31 -0
- package/src/binaries.json +46 -0
- package/src/binaries.mjs +83 -0
- package/src/cli.mjs +254 -0
- package/src/prepare.mjs +74 -0
- package/src/runtime/ignix-frame.js +92 -0
- package/src/transcribe.mjs +71 -0
- package/src/validate.mjs +71 -0
- package/templates/blank/index.html +41 -0
- package/vendor/hyperframes/README.md +181 -0
- package/vendor/hyperframes/UPSTREAM.json +12 -0
- package/vendor/hyperframes/bin/hyperframes-localize-fonts.mjs +12 -0
- package/vendor/hyperframes/bin/hyperframes.mjs +11 -0
- package/vendor/hyperframes/dist/add-LR3ZR2A5.js +79 -0
- package/vendor/hyperframes/dist/agentPromptGenerator-VIIPZCJ3.js +143 -0
- package/vendor/hyperframes/dist/animatedGifPrep-P2T6YM7Z.js +34 -0
- package/vendor/hyperframes/dist/asset-BE2DOV72.js +26 -0
- package/vendor/hyperframes/dist/assetCataloger-VBLPHX24.js +340 -0
- package/vendor/hyperframes/dist/auth-RCQB2ZT7.js +60 -0
- package/vendor/hyperframes/dist/autoUpdate-RJAX3DAZ.js +268 -0
- package/vendor/hyperframes/dist/backgroundChecks-H2LCUIMJ.js +61 -0
- package/vendor/hyperframes/dist/backgroundChecksWorker.js +26 -0
- package/vendor/hyperframes/dist/batchRender-FT7AP7XH.js +355 -0
- package/vendor/hyperframes/dist/beat-analyzer.global.js +338 -0
- package/vendor/hyperframes/dist/beats-Y2EOP72P.js +309 -0
- package/vendor/hyperframes/dist/benchmark-MZ7GY3JW.js +231 -0
- package/vendor/hyperframes/dist/browser-HUTAMRQE.js +237 -0
- package/vendor/hyperframes/dist/bundleWithLocalizedFonts-5QOPOB5D.js +52 -0
- package/vendor/hyperframes/dist/capture-RLZA6EMR.js +4079 -0
- package/vendor/hyperframes/dist/capture-SZZ4IYJK.js +290 -0
- package/vendor/hyperframes/dist/captureFile-LYOJOUIE.js +15 -0
- package/vendor/hyperframes/dist/captureTimeout-PA4FYWT5.js +27 -0
- package/vendor/hyperframes/dist/catalog-KYU55EWR.js +1001 -0
- package/vendor/hyperframes/dist/check-TCG4PXLR.js +1697 -0
- package/vendor/hyperframes/dist/checkBrowser-RPMO4OW5.js +1032 -0
- package/vendor/hyperframes/dist/chunk-2EAXUCCE.js +88 -0
- package/vendor/hyperframes/dist/chunk-2EGFTPWD.js +1077 -0
- package/vendor/hyperframes/dist/chunk-2PSPARWP.js +6058 -0
- package/vendor/hyperframes/dist/chunk-2YN64IN5.js +5747 -0
- package/vendor/hyperframes/dist/chunk-3GXQPCJC.js +682 -0
- package/vendor/hyperframes/dist/chunk-3ZP5DXE7.js +15 -0
- package/vendor/hyperframes/dist/chunk-4NWOGZZS.js +1990 -0
- package/vendor/hyperframes/dist/chunk-4PFZPP2N.js +587 -0
- package/vendor/hyperframes/dist/chunk-4THIAPBL.js +128 -0
- package/vendor/hyperframes/dist/chunk-4YYJOFKS.js +28 -0
- package/vendor/hyperframes/dist/chunk-54HJ63Q2.js +29 -0
- package/vendor/hyperframes/dist/chunk-5ETJX6WM.js +89 -0
- package/vendor/hyperframes/dist/chunk-5IAKAQA7.js +389 -0
- package/vendor/hyperframes/dist/chunk-5Z63TBTX.js +37 -0
- package/vendor/hyperframes/dist/chunk-6BEFEWFB.js +25 -0
- package/vendor/hyperframes/dist/chunk-6CSYCFQV.js +68 -0
- package/vendor/hyperframes/dist/chunk-6CTIGJY7.js +154 -0
- package/vendor/hyperframes/dist/chunk-7HG4BFIN.js +93 -0
- package/vendor/hyperframes/dist/chunk-7JZ4FXP2.js +118 -0
- package/vendor/hyperframes/dist/chunk-A2Z4Z4VL.js +2961 -0
- package/vendor/hyperframes/dist/chunk-AMKC3AXA.js +25 -0
- package/vendor/hyperframes/dist/chunk-AVUUN2XD.js +4847 -0
- package/vendor/hyperframes/dist/chunk-AWDFDFI3.js +46 -0
- package/vendor/hyperframes/dist/chunk-AWNBM3MZ.js +94 -0
- package/vendor/hyperframes/dist/chunk-BXCMXMJQ.js +73 -0
- package/vendor/hyperframes/dist/chunk-BZ56MTDX.js +6 -0
- package/vendor/hyperframes/dist/chunk-CFKU7HTK.js +171 -0
- package/vendor/hyperframes/dist/chunk-CWPVM2QV.js +308 -0
- package/vendor/hyperframes/dist/chunk-DPVXBVLL.js +31292 -0
- package/vendor/hyperframes/dist/chunk-DQBY7FRR.js +397 -0
- package/vendor/hyperframes/dist/chunk-E6RPWJVC.js +213 -0
- package/vendor/hyperframes/dist/chunk-EISRN4E6.js +294 -0
- package/vendor/hyperframes/dist/chunk-EOVYQ3IG.js +143 -0
- package/vendor/hyperframes/dist/chunk-F3WZGU7C.js +479 -0
- package/vendor/hyperframes/dist/chunk-FCSIGXXP.js +366 -0
- package/vendor/hyperframes/dist/chunk-FI4I7CME.js +56 -0
- package/vendor/hyperframes/dist/chunk-FLWXXDNS.js +15 -0
- package/vendor/hyperframes/dist/chunk-GK4AIFIH.js +11171 -0
- package/vendor/hyperframes/dist/chunk-GMECXFAN.js +57 -0
- package/vendor/hyperframes/dist/chunk-GULOKZLI.js +155 -0
- package/vendor/hyperframes/dist/chunk-H4YZZ2VQ.js +68 -0
- package/vendor/hyperframes/dist/chunk-H6QMKUYA.js +477 -0
- package/vendor/hyperframes/dist/chunk-HBBJFK6I.js +273 -0
- package/vendor/hyperframes/dist/chunk-HRUGC23L.js +212 -0
- package/vendor/hyperframes/dist/chunk-HVW7ABXD.js +19 -0
- package/vendor/hyperframes/dist/chunk-HW6OYASV.js +344 -0
- package/vendor/hyperframes/dist/chunk-HWKCIWQT.js +3578 -0
- package/vendor/hyperframes/dist/chunk-I465DBM6.js +1214 -0
- package/vendor/hyperframes/dist/chunk-IGLEPPTN.js +24 -0
- package/vendor/hyperframes/dist/chunk-IGNAAHS3.js +433 -0
- package/vendor/hyperframes/dist/chunk-IHFUKJOR.js +85 -0
- package/vendor/hyperframes/dist/chunk-IQ3OUQ5Z.js +213 -0
- package/vendor/hyperframes/dist/chunk-ISN5GRYI.js +20 -0
- package/vendor/hyperframes/dist/chunk-IUZFXWSV.js +446 -0
- package/vendor/hyperframes/dist/chunk-JH556Q42.js +647 -0
- package/vendor/hyperframes/dist/chunk-JTHMTOMQ.js +601 -0
- package/vendor/hyperframes/dist/chunk-K2EQN4VU.js +405 -0
- package/vendor/hyperframes/dist/chunk-K2FTXJYH.js +16044 -0
- package/vendor/hyperframes/dist/chunk-K4WIOZFP.js +32 -0
- package/vendor/hyperframes/dist/chunk-K4WKGXRC.js +18 -0
- package/vendor/hyperframes/dist/chunk-KBJUXVOJ.js +172 -0
- package/vendor/hyperframes/dist/chunk-KC5XXX3X.js +590 -0
- package/vendor/hyperframes/dist/chunk-KNU5COPB.js +29 -0
- package/vendor/hyperframes/dist/chunk-KZI44OPA.js +185 -0
- package/vendor/hyperframes/dist/chunk-L3YOGIPG.js +48 -0
- package/vendor/hyperframes/dist/chunk-LAOCA3MQ.js +189 -0
- package/vendor/hyperframes/dist/chunk-LCSMOLGX.js +312 -0
- package/vendor/hyperframes/dist/chunk-LFGJWOVA.js +61 -0
- package/vendor/hyperframes/dist/chunk-LHSR3M4M.js +498 -0
- package/vendor/hyperframes/dist/chunk-LYNI3FOL.js +123 -0
- package/vendor/hyperframes/dist/chunk-M2WBOQ2Q.js +54 -0
- package/vendor/hyperframes/dist/chunk-MRF4AMKD.js +104 -0
- package/vendor/hyperframes/dist/chunk-MWB3ZIFM.js +852 -0
- package/vendor/hyperframes/dist/chunk-NGKM64BP.js +39 -0
- package/vendor/hyperframes/dist/chunk-NXMYHJAL.js +43 -0
- package/vendor/hyperframes/dist/chunk-OAF4XJOW.js +192 -0
- package/vendor/hyperframes/dist/chunk-OFQWTKPW.js +117 -0
- package/vendor/hyperframes/dist/chunk-P6LJ4Y32.js +4662 -0
- package/vendor/hyperframes/dist/chunk-PBN6GBJE.js +108 -0
- package/vendor/hyperframes/dist/chunk-PDAMK4Q5.js +28 -0
- package/vendor/hyperframes/dist/chunk-PFCFR3KZ.js +20 -0
- package/vendor/hyperframes/dist/chunk-PJ3HDUCY.js +108 -0
- package/vendor/hyperframes/dist/chunk-PMRBLBUP.js +152 -0
- package/vendor/hyperframes/dist/chunk-PPQUYWTW.js +240 -0
- package/vendor/hyperframes/dist/chunk-Q5X2B5WT.js +29 -0
- package/vendor/hyperframes/dist/chunk-Q7IU7MOR.js +351 -0
- package/vendor/hyperframes/dist/chunk-QC4FJVLM.js +371 -0
- package/vendor/hyperframes/dist/chunk-QNYYOUU3.js +1318 -0
- package/vendor/hyperframes/dist/chunk-RDNNAKEP.js +161 -0
- package/vendor/hyperframes/dist/chunk-RMHUQGRK.js +657 -0
- package/vendor/hyperframes/dist/chunk-RQVDTPGD.js +6 -0
- package/vendor/hyperframes/dist/chunk-RVCWIIZ7.js +68 -0
- package/vendor/hyperframes/dist/chunk-S3D6GE5W.js +72 -0
- package/vendor/hyperframes/dist/chunk-S3S4TGEH.js +424 -0
- package/vendor/hyperframes/dist/chunk-S7NPLFWV.js +11395 -0
- package/vendor/hyperframes/dist/chunk-SHB5VDMH.js +51 -0
- package/vendor/hyperframes/dist/chunk-TCLGPL65.js +860 -0
- package/vendor/hyperframes/dist/chunk-THXFSPLV.js +40 -0
- package/vendor/hyperframes/dist/chunk-TJSTGSAW.js +354 -0
- package/vendor/hyperframes/dist/chunk-TQFG7HTI.js +1024 -0
- package/vendor/hyperframes/dist/chunk-TVCRUG2S.js +265 -0
- package/vendor/hyperframes/dist/chunk-TWWSYAKJ.js +24 -0
- package/vendor/hyperframes/dist/chunk-U7CZBDMV.js +27 -0
- package/vendor/hyperframes/dist/chunk-UEZXMWG3.js +139 -0
- package/vendor/hyperframes/dist/chunk-UYEZTK4U.js +61 -0
- package/vendor/hyperframes/dist/chunk-VC76R6W2.js +27 -0
- package/vendor/hyperframes/dist/chunk-VFCKXTBB.js +159 -0
- package/vendor/hyperframes/dist/chunk-VWG7OQKU.js +22 -0
- package/vendor/hyperframes/dist/chunk-VXVRPIJA.js +105 -0
- package/vendor/hyperframes/dist/chunk-WBLXWOYK.js +15 -0
- package/vendor/hyperframes/dist/chunk-WERLJGIC.js +20 -0
- package/vendor/hyperframes/dist/chunk-WMQNIQDJ.js +2057 -0
- package/vendor/hyperframes/dist/chunk-WPHMNO44.js +4528 -0
- package/vendor/hyperframes/dist/chunk-X5HWXQPU.js +113 -0
- package/vendor/hyperframes/dist/chunk-X7MTZ4T2.js +6 -0
- package/vendor/hyperframes/dist/chunk-XH4DSOS5.js +59 -0
- package/vendor/hyperframes/dist/chunk-XS4EJSKU.js +23 -0
- package/vendor/hyperframes/dist/chunk-XT5P4QMO.js +181 -0
- package/vendor/hyperframes/dist/chunk-XT7X6QCP.js +6 -0
- package/vendor/hyperframes/dist/chunk-XUHOIDKG.js +6 -0
- package/vendor/hyperframes/dist/chunk-XUXGIA7H.js +485 -0
- package/vendor/hyperframes/dist/chunk-XZABUQTX.js +113 -0
- package/vendor/hyperframes/dist/chunk-Y6W4DVPS.js +356 -0
- package/vendor/hyperframes/dist/chunk-YEIFI443.js +44 -0
- package/vendor/hyperframes/dist/chunk-YQZNILVH.js +375 -0
- package/vendor/hyperframes/dist/chunk-Z27A7NUB.js +65 -0
- package/vendor/hyperframes/dist/chunk-Z6B37SNM.js +3081 -0
- package/vendor/hyperframes/dist/chunk-ZJUKFZ2P.js +10954 -0
- package/vendor/hyperframes/dist/chunk-ZKDMAOFU.js +32 -0
- package/vendor/hyperframes/dist/chunk-ZMXUQLI2.js +17219 -0
- package/vendor/hyperframes/dist/chunk-ZTZ7NCJT.js +58 -0
- package/vendor/hyperframes/dist/chunk-ZTZA4UWZ.js +108 -0
- package/vendor/hyperframes/dist/clean-W57E5YQ3.js +293 -0
- package/vendor/hyperframes/dist/cli.js +495 -0
- package/vendor/hyperframes/dist/cloud-FFTJGZ24.js +70 -0
- package/vendor/hyperframes/dist/cloudrun-AJUTHUEA.js +763 -0
- package/vendor/hyperframes/dist/colors-HKWSZCGK.js +15 -0
- package/vendor/hyperframes/dist/commands/contrast-audit.browser.js +459 -0
- package/vendor/hyperframes/dist/commands/layout-audit.browser.js +2102 -0
- package/vendor/hyperframes/dist/commands/motion-sample.browser.js +74 -0
- package/vendor/hyperframes/dist/commands/motion-signature.browser.js +374 -0
- package/vendor/hyperframes/dist/compare-AYCTT55F.js +421 -0
- package/vendor/hyperframes/dist/compiler-QO36EXLS.js +121 -0
- package/vendor/hyperframes/dist/component-VFFR2O7T.js +176 -0
- package/vendor/hyperframes/dist/compositions-QTVN3U2A.js +228 -0
- package/vendor/hyperframes/dist/contactSheet-27SRU7A4.js +22 -0
- package/vendor/hyperframes/dist/delete-ZAKYCB7I.js +114 -0
- package/vendor/hyperframes/dist/deploy-MX76RZ36.js +101 -0
- package/vendor/hyperframes/dist/destroy-H2TZBYHH.js +42 -0
- package/vendor/hyperframes/dist/deterministicFonts-HAEMV4TM.js +50 -0
- package/vendor/hyperframes/dist/dist-EWXJGN63.js +129 -0
- package/vendor/hyperframes/dist/dist-FNNGCKFS.js +29 -0
- package/vendor/hyperframes/dist/dist-S3PJNPXQ.js +392 -0
- package/vendor/hyperframes/dist/docker/Dockerfile.render +65 -0
- package/vendor/hyperframes/dist/docs/compositions.md +67 -0
- package/vendor/hyperframes/dist/docs/data-attributes.md +27 -0
- package/vendor/hyperframes/dist/docs/examples.md +19 -0
- package/vendor/hyperframes/dist/docs/gsap.md +26 -0
- package/vendor/hyperframes/dist/docs/rendering.md +35 -0
- package/vendor/hyperframes/dist/docs/troubleshooting.md +29 -0
- package/vendor/hyperframes/dist/docs-QAPJEGLS.js +131 -0
- package/vendor/hyperframes/dist/doctor-AI7C3FON.js +67 -0
- package/vendor/hyperframes/dist/dom-IROKGVJI.js +14 -0
- package/vendor/hyperframes/dist/dotEnv-AECLXQSO.js +14 -0
- package/vendor/hyperframes/dist/events-7LALYNKZ.js +92 -0
- package/vendor/hyperframes/dist/events-FQY3HGKZ.js +88 -0
- package/vendor/hyperframes/dist/feedback-WCMDMSTK.js +472 -0
- package/vendor/hyperframes/dist/ffmpeg-QIUFEFTY.js +35 -0
- package/vendor/hyperframes/dist/figma-64WY462P.js +63 -0
- package/vendor/hyperframes/dist/fontData.generated-NXAOI4GH.js +13 -0
- package/vendor/hyperframes/dist/fontLocalizeCli.js +132 -0
- package/vendor/hyperframes/dist/get-FPOMJMZB.js +103 -0
- package/vendor/hyperframes/dist/gpuPolicy-2ZUZE5D6.js +38 -0
- package/vendor/hyperframes/dist/grade-compare-E2CKPST4.js +647 -0
- package/vendor/hyperframes/dist/gsapParser-DIYYX6JT.js +2846 -0
- package/vendor/hyperframes/dist/gsapParserAcorn-E3GEIRZB.js +28 -0
- package/vendor/hyperframes/dist/help-YRQIDDML.js +197 -0
- package/vendor/hyperframes/dist/history-PP5NDRV3.js +571 -0
- package/vendor/hyperframes/dist/hyperframe-runtime.js +1081 -0
- package/vendor/hyperframes/dist/hyperframe.manifest.json +22 -0
- package/vendor/hyperframes/dist/hyperframe.runtime.iife.js +1081 -0
- package/vendor/hyperframes/dist/hyperframes-player.global.js +474 -0
- package/vendor/hyperframes/dist/hyperframes-slideshow.global.js +149 -0
- package/vendor/hyperframes/dist/info-SEX3B7JL.js +153 -0
- package/vendor/hyperframes/dist/init-U3AKHO5B.js +1147 -0
- package/vendor/hyperframes/dist/inspect-Q3K6EDEK.js +97 -0
- package/vendor/hyperframes/dist/installer-K6O5WF44.js +37 -0
- package/vendor/hyperframes/dist/keyframes-DC64JCI3.js +2602 -0
- package/vendor/hyperframes/dist/lambda-D7UMN4DJ.js +451 -0
- package/vendor/hyperframes/dist/layout-XSPPDHOO.js +86 -0
- package/vendor/hyperframes/dist/lib-TPG2ZMAX.js +128 -0
- package/vendor/hyperframes/dist/lint-7DQZE7L3.js +164 -0
- package/vendor/hyperframes/dist/lintProject-OHBBM3DJ.js +27 -0
- package/vendor/hyperframes/dist/list-4K5MVDQX.js +162 -0
- package/vendor/hyperframes/dist/login-NTX4OWXL.js +377 -0
- package/vendor/hyperframes/dist/logout-Q654A3SI.js +100 -0
- package/vendor/hyperframes/dist/manager-67P2XFXQ.js +34 -0
- package/vendor/hyperframes/dist/manager-CT3D67CG.js +38 -0
- package/vendor/hyperframes/dist/manager-GFN75DM4.js +30 -0
- package/vendor/hyperframes/dist/media-treatment-5FYAOPNL.js +972 -0
- package/vendor/hyperframes/dist/media-use-4XXGABIL.js +113 -0
- package/vendor/hyperframes/dist/models-C4E4IWJD.js +137 -0
- package/vendor/hyperframes/dist/motionShot-S4MIGMT5.js +614 -0
- package/vendor/hyperframes/dist/normalize-O76AC4HE.js +333 -0
- package/vendor/hyperframes/dist/normalize-audio-CSFTXLXD.js +276 -0
- package/vendor/hyperframes/dist/open-2ZD6BHZG.js +115 -0
- package/vendor/hyperframes/dist/pipeline-TNGWUZQC.js +54 -0
- package/vendor/hyperframes/dist/play-CTMUXX6E.js +349 -0
- package/vendor/hyperframes/dist/policies-FSDZVS2E.js +292 -0
- package/vendor/hyperframes/dist/preflight-SMNV6RW2.js +45 -0
- package/vendor/hyperframes/dist/present-WQVHV5CR.js +350 -0
- package/vendor/hyperframes/dist/preview-JOJXTH75.js +1820 -0
- package/vendor/hyperframes/dist/producer-ECLEN5RP.js +13 -0
- package/vendor/hyperframes/dist/progress-FBIEEB7Y.js +73 -0
- package/vendor/hyperframes/dist/projectConfig-HYJMJ5BY.js +56 -0
- package/vendor/hyperframes/dist/publication-HQ5Y3KBM.js +29 -0
- package/vendor/hyperframes/dist/publish-VHDYQASC.js +430 -0
- package/vendor/hyperframes/dist/refresh-K24ETHMA.js +53 -0
- package/vendor/hyperframes/dist/remove-background-W2YX2NVH.js +253 -0
- package/vendor/hyperframes/dist/render-AO5VX3YI.js +177 -0
- package/vendor/hyperframes/dist/render-LNO62LEL.js +2367 -0
- package/vendor/hyperframes/dist/render-TTQI7TGN.js +796 -0
- package/vendor/hyperframes/dist/render-batch-YH7CTWNY.js +284 -0
- package/vendor/hyperframes/dist/renderCancellation-JPIHE47X.js +35 -0
- package/vendor/hyperframes/dist/renderSetupWorker.js +79 -0
- package/vendor/hyperframes/dist/resolver-IZ647GBZ.js +38 -0
- package/vendor/hyperframes/dist/runtimeVersion.js +18 -0
- package/vendor/hyperframes/dist/screenshotCapture-ECBTLCU6.js +179 -0
- package/vendor/hyperframes/dist/shaderTransitionWorker.js +44 -0
- package/vendor/hyperframes/dist/sherpa-KKLNW6U2.js +314 -0
- package/vendor/hyperframes/dist/sherpaWorker.js +77 -0
- package/vendor/hyperframes/dist/sites-TNVKZS73.js +52 -0
- package/vendor/hyperframes/dist/skill-ZHVLH7KX.js +15 -0
- package/vendor/hyperframes/dist/skills/hyperframes/SKILL.md +152 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/brief-contract.md +108 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/brief-format.md +72 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/capability-menu.md +47 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/frame-worker-core.md +80 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/intent-interview.md +73 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/pitch-round.md +40 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/plugin-installation.md +43 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/production-loop.md +26 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/review-loop.md +37 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/route-briefs.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/embedded-captions.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/faceless-explainer.md +12 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/general-video.md +12 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/motion-graphics.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/music-to-video.md +12 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/pr-to-video.md +28 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/product-launch-video.md +13 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/remotion-to-hyperframes.md +9 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/slideshow.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/routes/talking-head-recut.md +11 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/script-format.md +52 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/skill-lifecycle.md +35 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/storyboard-format.md +99 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/subagent-dispatch.md +35 -0
- package/vendor/hyperframes/dist/skills/hyperframes/references/workflow-catalog.md +10 -0
- package/vendor/hyperframes/dist/skills/hyperframes/scripts/lib/frame-packets-core.mjs +194 -0
- package/vendor/hyperframes/dist/skills/hyperframes/scripts/plugin-cli.mjs +88 -0
- package/vendor/hyperframes/dist/skills/hyperframes/scripts/plugin-cli.test.mjs +117 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/SKILL.md +189 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/beats.md +19 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/cloud.md +163 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/cloudrun.md +62 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/compare-and-batch.md +105 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/doctor-browser.md +57 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/init-and-scaffold.md +74 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/lambda.md +185 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/lint-validate-inspect.md +132 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/preview-render.md +193 -0
- package/vendor/hyperframes/dist/skills/hyperframes-cli/references/upgrade-info-misc.md +134 -0
- package/vendor/hyperframes/dist/skills/media-use/SKILL.md +100 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/CREDITS.md +35 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/chime.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/click-soft.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/click.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/error.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/glitch-1.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/glitch-2.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/glitch-3.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/impact-bass-1.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/impact-bass-2.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/key-press.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/manifest.json +97 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/notification.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/ping.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/pop.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/riser.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/sparkle.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/typing.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/whoosh-cinematic.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/whoosh-short.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/assets/sfx/whoosh.mp3 +0 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/bgm.md +76 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/captions/authoring.md +163 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/captions/motion.md +87 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/captions/transcript-handling.md +97 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/remove-background.md +143 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/requirements.md +29 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/sfx.md +42 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/transcribe.md +52 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/tts-to-captions.md +35 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/references/tts.md +260 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/audio.mjs +311 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/audio.test.mjs +159 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/gemini-pipeline.test.mjs +131 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/heygen-tts.mjs +122 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/heygen-tts.test.mjs +38 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/heygen-voice.mjs +98 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/heygen-voice.test.mjs +233 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/audio-meta.mjs +39 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/audio-meta.test.mjs +136 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/bgm-volume.mjs +4 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/bgm.mjs +257 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/bgm.test.mjs +74 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/concurrency.mjs +14 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/concurrency.test.mjs +41 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-auth.mjs +43 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-auth.py +52 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-auth.test.mjs +86 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-auth_test.py +90 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-tts.mjs +122 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/gemini-tts.test.mjs +243 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/heygen.mjs +197 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/heygen.test.mjs +185 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/media-record.mjs +114 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/media-record.test.mjs +205 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/python.mjs +77 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/python.test.mjs +136 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/sfx.mjs +165 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/sfx.test.mjs +121 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/tts.mjs +389 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/tts.spawn.test.mjs +158 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lib/tts.test.mjs +230 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/lyria-recipe.py +136 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/wait-bgm.mjs +175 -0
- package/vendor/hyperframes/dist/skills/media-use/audio/scripts/wait-bgm.test.mjs +108 -0
- package/vendor/hyperframes/dist/skills/media-use/luts/README.md +28 -0
- package/vendor/hyperframes/dist/skills/media-use/luts/index.json +57 -0
- package/vendor/hyperframes/dist/skills/media-use/references/audio.md +20 -0
- package/vendor/hyperframes/dist/skills/media-use/references/grading.md +160 -0
- package/vendor/hyperframes/dist/skills/media-use/references/media-treatment-recipes.md +929 -0
- package/vendor/hyperframes/dist/skills/media-use/references/media-treatments.md +202 -0
- package/vendor/hyperframes/dist/skills/media-use/references/memory.md +37 -0
- package/vendor/hyperframes/dist/skills/media-use/references/meta.md +61 -0
- package/vendor/hyperframes/dist/skills/media-use/references/operations.md +327 -0
- package/vendor/hyperframes/dist/skills/media-use/references/resolve.md +150 -0
- package/vendor/hyperframes/dist/skills/media-use/references/setup-providers.md +80 -0
- package/vendor/hyperframes/dist/skills/media-use/references/telemetry-dashboard.md +49 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/audio-duck.mjs +113 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/compatibility.test.mjs +96 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/dither.mjs +328 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/dither.test.mjs +176 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/eval.mjs +369 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/adopt.mjs +128 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/adopt.test.mjs +95 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/bgm-provider.mjs +20 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/brand-provider.mjs +59 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/bundled-sfx-provider.mjs +119 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/bundled-sfx-provider.test.mjs +139 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cache.mjs +148 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/candidates.mjs +91 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/candidates.test.mjs +155 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/codex-provider.mjs +161 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/codex-provider.test.mjs +34 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/config-lock.d.mts +3 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/config-lock.mjs +45 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/config-lock.test.mjs +79 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/coverage.test.mjs +136 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cube-build.mjs +181 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cube-build.test.mjs +80 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cube-validate.mjs +198 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cube-validate.test.mjs +125 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cutlist.mjs +184 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/cutlist.test.mjs +162 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/duck.mjs +95 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/duck.test.mjs +153 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/error-diffusion.mjs +230 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/error-diffusion.test.mjs +102 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/ff-binaries.mjs +37 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/freeze.mjs +72 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/freeze.test.mjs +138 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/grade-analyzer.mjs +265 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/grade-analyzer.test.mjs +285 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-cli.mjs +191 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-cli.test.mjs +301 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-search.mjs +45 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-search.test.mjs +49 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-video-provider.mjs +138 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/heygen-video-provider.test.mjs +435 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/image-provider.mjs +44 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/index-gen.mjs +63 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-media-search.mjs +32 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-models.mjs +318 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-models.test.mjs +220 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-run.mjs +78 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/local-run.test.mjs +121 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/logo-provider.mjs +244 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/logo-provider.test.mjs +298 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/ltx-video-provider.mjs +94 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/ltx-video-provider.test.mjs +316 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/lut-preset-provider.mjs +271 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/lut-preset-provider.test.mjs +199 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/manifest.d.mts +19 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/manifest.mjs +279 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/manifest.test.mjs +397 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/match.mjs +47 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-fetch.mjs +85 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-fetch.test.mjs +197 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-home.mjs +20 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-home.test.mjs +61 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-search.d.mts +9 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/media-search.mjs +107 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/mflux-provider.mjs +128 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/mflux-provider.test.mjs +174 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/misses.mjs +49 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/misses.test.mjs +89 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/npx-sync.mjs +31 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/npx-sync.test.mjs +50 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/parakeet-words.mjs +27 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/parakeet-words.test.mjs +44 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/prefs-store.mjs +180 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/prefs-store.test.mjs +189 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/probe.mjs +41 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/probe.test.mjs +148 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/providers.mjs +5 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/recipe-store.mjs +367 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/recipe-store.test.mjs +367 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/registry.mjs +212 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/registry.test.mjs +262 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/search.mjs +24 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/search.test.mjs +32 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/sfx-provider.mjs +23 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/specs.mjs +132 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/specs.test.mjs +157 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/stats.mjs +117 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/stats.test.mjs +165 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/svg-sanitize.mjs +21 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/telemetry.mjs +210 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/telemetry.test.mjs +437 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/test-home.test.mjs +10 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/transcriptCutFade.mjs +21 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/transcriptCutFade.test.mjs +33 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/tts-local-provider.mjs +94 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/tts-local-provider.test.mjs +72 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/usage.mjs +57 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/usage.test.mjs +54 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/voice-provider.mjs +57 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/voice-provider.test.mjs +46 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/lib/words.mjs +18 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/prefs.mjs +70 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/recipe.mjs +103 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/resolve-plugin.test.mjs +62 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/resolve.mjs +1369 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/transcribe.mjs +194 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/transcribe.test.mjs +112 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/transcript-cut.mjs +270 -0
- package/vendor/hyperframes/dist/skills/media-use/scripts/transcript-cut.test.mjs +117 -0
- package/vendor/hyperframes/dist/skills-MJ2J4GEM.js +808 -0
- package/vendor/hyperframes/dist/skillsUpdateCheck-TKTYQN5R.js +26 -0
- package/vendor/hyperframes/dist/slideshow-EJ4IMY6P.js +24 -0
- package/vendor/hyperframes/dist/snapshot-KIVDUUMN.js +875 -0
- package/vendor/hyperframes/dist/src-6YQBJGWR.js +202 -0
- package/vendor/hyperframes/dist/src-PVYUYV3M.js +471 -0
- package/vendor/hyperframes/dist/state-KAXGHF77.js +26 -0
- package/vendor/hyperframes/dist/staticProjectServer-7EU666GS.js +49 -0
- package/vendor/hyperframes/dist/status-YM52BQ6S.js +311 -0
- package/vendor/hyperframes/dist/studio/assets/hyperframes-player-Cp8e_Zst.js +473 -0
- package/vendor/hyperframes/dist/studio/assets/index-BX3KHhGX.js +71 -0
- package/vendor/hyperframes/dist/studio/assets/index-CASEBNy2.js +1 -0
- package/vendor/hyperframes/dist/studio/assets/index-D11atkBt.css +1 -0
- package/vendor/hyperframes/dist/studio/assets/index-DMTt9nTf.js +531 -0
- package/vendor/hyperframes/dist/studio/assets/index-oE1pOdAy.js +399 -0
- package/vendor/hyperframes/dist/studio/chunk-5VSXRGIX.js +948 -0
- package/vendor/hyperframes/dist/studio/chunk-5VSXRGIX.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-7UQWVN52.js +938 -0
- package/vendor/hyperframes/dist/studio/chunk-7UQWVN52.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-EEXSYY5F.js +190 -0
- package/vendor/hyperframes/dist/studio/chunk-EEXSYY5F.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-FOEID72M.js +1441 -0
- package/vendor/hyperframes/dist/studio/chunk-FOEID72M.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-PZ5AY32C.js +10 -0
- package/vendor/hyperframes/dist/studio/chunk-PZ5AY32C.js.map +1 -0
- package/vendor/hyperframes/dist/studio/chunk-TDWGXBUT.js +1103 -0
- package/vendor/hyperframes/dist/studio/chunk-TDWGXBUT.js.map +1 -0
- package/vendor/hyperframes/dist/studio/domEditingLayers-IEVLO54Z.js +47 -0
- package/vendor/hyperframes/dist/studio/domEditingLayers-IEVLO54Z.js.map +1 -0
- package/vendor/hyperframes/dist/studio/favicon.svg +14 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/audio.svg +7 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/captions.svg +5 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/composition.svg +12 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/image.svg +18 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/music.svg +10 -0
- package/vendor/hyperframes/dist/studio/icons/timeline/text.svg +3 -0
- package/vendor/hyperframes/dist/studio/index.css +165 -0
- package/vendor/hyperframes/dist/studio/index.css.map +1 -0
- package/vendor/hyperframes/dist/studio/index.d.ts +4296 -0
- package/vendor/hyperframes/dist/studio/index.html +23 -0
- package/vendor/hyperframes/dist/studio/index.js +99693 -0
- package/vendor/hyperframes/dist/studio/index.js.map +1 -0
- package/vendor/hyperframes/dist/studio/player.d.ts +30 -0
- package/vendor/hyperframes/dist/studio/player.js +10 -0
- package/vendor/hyperframes/dist/studio/player.js.map +1 -0
- package/vendor/hyperframes/dist/studio/styles/tailwind-preset.d.ts +39 -0
- package/vendor/hyperframes/dist/studio/styles/tailwind-preset.js +50 -0
- package/vendor/hyperframes/dist/studio/styles/tailwind-preset.js.map +1 -0
- package/vendor/hyperframes/dist/studio/styles.css +1 -0
- package/vendor/hyperframes/dist/studio/ui.d.ts +296 -0
- package/vendor/hyperframes/dist/studio/ui.js +66 -0
- package/vendor/hyperframes/dist/studio/ui.js.map +1 -0
- package/vendor/hyperframes/dist/studio-api-PNQZRPX5.js +136 -0
- package/vendor/hyperframes/dist/studioSelectionClient-IUUPKUHZ.js +25 -0
- package/vendor/hyperframes/dist/studioServer-UWRBPIOJ.js +1457 -0
- package/vendor/hyperframes/dist/synthesize-K62TIZWI.js +182 -0
- package/vendor/hyperframes/dist/system-EZYZNUFD.js +44 -0
- package/vendor/hyperframes/dist/telemetry-2YC4SGQU.js +144 -0
- package/vendor/hyperframes/dist/telemetry-QMYM4WME.js +95 -0
- package/vendor/hyperframes/dist/templates/_shared/AGENTS.md +107 -0
- package/vendor/hyperframes/dist/templates/_shared/CLAUDE.md +107 -0
- package/vendor/hyperframes/dist/templates/blank/index.html +55 -0
- package/vendor/hyperframes/dist/templates/from-file/index.html +75 -0
- package/vendor/hyperframes/dist/templates/warm-grain/compositions/captions.html +154 -0
- package/vendor/hyperframes/dist/templates/warm-grain/compositions/graphics.html +162 -0
- package/vendor/hyperframes/dist/templates/warm-grain/compositions/intro.html +87 -0
- package/vendor/hyperframes/dist/templates/warm-grain/index.html +264 -0
- package/vendor/hyperframes/dist/templates/warm-grain/registry-item.json +34 -0
- package/vendor/hyperframes/dist/timeline-77Z3BBQM.js +1377 -0
- package/vendor/hyperframes/dist/tokens-OBGTYE4Z.js +92 -0
- package/vendor/hyperframes/dist/transcribe-7NVFHCGA.js +387 -0
- package/vendor/hyperframes/dist/transcribe-BNSJRR4M.js +62 -0
- package/vendor/hyperframes/dist/tts-P3LIPIL5.js +234 -0
- package/vendor/hyperframes/dist/updateCheck-UDWIJ4ZQ.js +39 -0
- package/vendor/hyperframes/dist/upgrade-CT3CPO3E.js +231 -0
- package/vendor/hyperframes/dist/urlDownloader-H6WRI2UE.js +39 -0
- package/vendor/hyperframes/dist/usage-EC3KFUIJ.js +2139 -0
- package/vendor/hyperframes/dist/validate-65QDZJWZ.js +70 -0
- package/vendor/hyperframes/dist/video-FGSGKRSV.js +261 -0
- package/vendor/hyperframes/dist/workspaceBuildCheck-TOLGAI4T.js +133 -0
- package/vendor/hyperframes/package.json +80 -0
|
@@ -0,0 +1,2846 @@
|
|
|
1
|
+
import { createRequire as __hf_createRequire } from "node:module";
|
|
2
|
+
import { fileURLToPath as __hf_fileURLToPath } from "node:url";
|
|
3
|
+
import { dirname as __hf_dirname } from "node:path";
|
|
4
|
+
var require = __hf_createRequire(import.meta.url);
|
|
5
|
+
var __filename = __hf_fileURLToPath(import.meta.url);
|
|
6
|
+
var __dirname = __hf_dirname(__filename);
|
|
7
|
+
import {
|
|
8
|
+
require_lib,
|
|
9
|
+
require_main
|
|
10
|
+
} from "./chunk-DPVXBVLL.js";
|
|
11
|
+
import {
|
|
12
|
+
__toESM
|
|
13
|
+
} from "./chunk-M2WBOQ2Q.js";
|
|
14
|
+
|
|
15
|
+
// ../parsers/dist/gsapParser.js
|
|
16
|
+
var recast = __toESM(require_main(), 1);
|
|
17
|
+
var import_parser = __toESM(require_lib(), 1);
|
|
18
|
+
var GSAP_DEFAULT_DURATION = 0.5;
|
|
19
|
+
var SUPPORTED_PROPS = [
|
|
20
|
+
// 2D Transforms
|
|
21
|
+
"x",
|
|
22
|
+
"y",
|
|
23
|
+
"scale",
|
|
24
|
+
"scaleX",
|
|
25
|
+
"scaleY",
|
|
26
|
+
"rotation",
|
|
27
|
+
"skewX",
|
|
28
|
+
"skewY",
|
|
29
|
+
// 3D Transforms
|
|
30
|
+
"z",
|
|
31
|
+
"rotationX",
|
|
32
|
+
"rotationY",
|
|
33
|
+
"rotationZ",
|
|
34
|
+
"perspective",
|
|
35
|
+
"transformPerspective",
|
|
36
|
+
"transformOrigin",
|
|
37
|
+
// Visibility
|
|
38
|
+
"opacity",
|
|
39
|
+
"visibility",
|
|
40
|
+
"autoAlpha",
|
|
41
|
+
// Dimensions
|
|
42
|
+
"width",
|
|
43
|
+
"height",
|
|
44
|
+
// Colors
|
|
45
|
+
"color",
|
|
46
|
+
"backgroundColor",
|
|
47
|
+
"borderColor",
|
|
48
|
+
// Box model
|
|
49
|
+
"borderRadius",
|
|
50
|
+
// Typography
|
|
51
|
+
"fontSize",
|
|
52
|
+
"letterSpacing",
|
|
53
|
+
// Filter & Clipping
|
|
54
|
+
"filter",
|
|
55
|
+
"clipPath",
|
|
56
|
+
// DOM content (number counters, text roll-ups)
|
|
57
|
+
"innerText"
|
|
58
|
+
];
|
|
59
|
+
var BUILTIN_VAR_KEYS = /* @__PURE__ */ new Set(["duration", "ease", "delay"]);
|
|
60
|
+
var DROPPED_VAR_KEYS = /* @__PURE__ */ new Set([
|
|
61
|
+
"onComplete",
|
|
62
|
+
"onStart",
|
|
63
|
+
"onUpdate",
|
|
64
|
+
"onRepeat"
|
|
65
|
+
]);
|
|
66
|
+
var EXTRAS_KEYS = /* @__PURE__ */ new Set([
|
|
67
|
+
"stagger",
|
|
68
|
+
"yoyo",
|
|
69
|
+
"repeat",
|
|
70
|
+
"repeatDelay",
|
|
71
|
+
"snap",
|
|
72
|
+
"overwrite",
|
|
73
|
+
"immediateRender"
|
|
74
|
+
]);
|
|
75
|
+
function isTweenConfigKey(key) {
|
|
76
|
+
return BUILTIN_VAR_KEYS.has(key) || DROPPED_VAR_KEYS.has(key) || EXTRAS_KEYS.has(key);
|
|
77
|
+
}
|
|
78
|
+
var PROPERTY_GROUPS = {
|
|
79
|
+
position: /* @__PURE__ */ new Set(["x", "y", "xPercent", "yPercent"]),
|
|
80
|
+
scale: /* @__PURE__ */ new Set(["scale", "scaleX", "scaleY"]),
|
|
81
|
+
size: /* @__PURE__ */ new Set(["width", "height"]),
|
|
82
|
+
rotation: /* @__PURE__ */ new Set(["rotation", "skewX", "skewY"]),
|
|
83
|
+
visual: /* @__PURE__ */ new Set(["opacity", "autoAlpha"]),
|
|
84
|
+
other: /* @__PURE__ */ new Set()
|
|
85
|
+
};
|
|
86
|
+
var PROP_TO_GROUP = /* @__PURE__ */ new Map();
|
|
87
|
+
for (const [group, props] of Object.entries(PROPERTY_GROUPS)) {
|
|
88
|
+
for (const p of props) PROP_TO_GROUP.set(p, group);
|
|
89
|
+
}
|
|
90
|
+
function writesProperty(animation, property) {
|
|
91
|
+
return property in animation.properties || !!animation.fromProperties && property in animation.fromProperties || !!animation.keyframes?.keyframes.some((k) => property in k.properties);
|
|
92
|
+
}
|
|
93
|
+
function isXYPositionWrite(a) {
|
|
94
|
+
return a.propertyGroup === "position" && (writesProperty(a, "x") || writesProperty(a, "y"));
|
|
95
|
+
}
|
|
96
|
+
function classifyPropertyGroup(prop) {
|
|
97
|
+
return PROP_TO_GROUP.get(prop) ?? "other";
|
|
98
|
+
}
|
|
99
|
+
function classifyTweenPropertyGroup(properties) {
|
|
100
|
+
const groups = /* @__PURE__ */ new Set();
|
|
101
|
+
for (const key of Object.keys(properties)) {
|
|
102
|
+
if (key === "transformOrigin" || key === "_auto" || key === "data") continue;
|
|
103
|
+
const g = classifyPropertyGroup(key);
|
|
104
|
+
groups.add(g);
|
|
105
|
+
}
|
|
106
|
+
if (groups.size === 1) return groups.values().next().value;
|
|
107
|
+
return void 0;
|
|
108
|
+
}
|
|
109
|
+
function knownStart(animation) {
|
|
110
|
+
if (animation.resolvedStart !== void 0) return animation.resolvedStart;
|
|
111
|
+
return typeof animation.position === "number" ? animation.position : void 0;
|
|
112
|
+
}
|
|
113
|
+
function positionHoldForAnimation(animation, animations) {
|
|
114
|
+
if (!animation.keyframes) return null;
|
|
115
|
+
const start = knownStart(animation) ?? 0;
|
|
116
|
+
if (!(start > 1e-3)) return null;
|
|
117
|
+
const atStart = animation.keyframes.keyframes.find((keyframe) => keyframe.percentage === 0);
|
|
118
|
+
if (!atStart) return null;
|
|
119
|
+
const earlier = animations.filter((other) => {
|
|
120
|
+
const otherStart = knownStart(other);
|
|
121
|
+
return other !== animation && !other.global && other.targetSelector === animation.targetSelector && otherStart !== void 0 && otherStart < start - 1e-3;
|
|
122
|
+
});
|
|
123
|
+
const position = {};
|
|
124
|
+
for (const [property, value] of Object.entries(atStart.properties)) {
|
|
125
|
+
if (classifyPropertyGroup(property) !== "position" || typeof value !== "number") continue;
|
|
126
|
+
if (earlier.some((other) => writesProperty(other, property))) continue;
|
|
127
|
+
position[property] = value;
|
|
128
|
+
}
|
|
129
|
+
return Object.keys(position).length > 0 ? position : null;
|
|
130
|
+
}
|
|
131
|
+
var SUPPORTED_EASES = [
|
|
132
|
+
"none",
|
|
133
|
+
"power1.in",
|
|
134
|
+
"power1.out",
|
|
135
|
+
"power1.inOut",
|
|
136
|
+
"power2.in",
|
|
137
|
+
"power2.out",
|
|
138
|
+
"power2.inOut",
|
|
139
|
+
"power3.in",
|
|
140
|
+
"power3.out",
|
|
141
|
+
"power3.inOut",
|
|
142
|
+
"power4.in",
|
|
143
|
+
"power4.out",
|
|
144
|
+
"power4.inOut",
|
|
145
|
+
"back.in",
|
|
146
|
+
"back.out",
|
|
147
|
+
"back.inOut",
|
|
148
|
+
"elastic.in",
|
|
149
|
+
"elastic.out",
|
|
150
|
+
"elastic.inOut",
|
|
151
|
+
"bounce.in",
|
|
152
|
+
"bounce.out",
|
|
153
|
+
"bounce.inOut",
|
|
154
|
+
"circ.inOut",
|
|
155
|
+
"expo.in",
|
|
156
|
+
"expo.out",
|
|
157
|
+
"expo.inOut",
|
|
158
|
+
"elastic.out(1,0.3)",
|
|
159
|
+
"elastic.inOut(1,0.3)",
|
|
160
|
+
"spring-gentle",
|
|
161
|
+
"spring-bouncy",
|
|
162
|
+
"spring-stiff",
|
|
163
|
+
"spring-wobbly",
|
|
164
|
+
"spring-heavy",
|
|
165
|
+
"hold",
|
|
166
|
+
"steps(1)"
|
|
167
|
+
];
|
|
168
|
+
function authorsKeyframes(anim) {
|
|
169
|
+
return anim.keyframes !== void 0 || anim.hasUnresolvedKeyframes === true;
|
|
170
|
+
}
|
|
171
|
+
function mergePercentageKeyframes(keyframes) {
|
|
172
|
+
const byPercentage = /* @__PURE__ */ new Map();
|
|
173
|
+
for (const keyframe of keyframes) {
|
|
174
|
+
const existing = byPercentage.get(keyframe.percentage);
|
|
175
|
+
if (!existing) {
|
|
176
|
+
byPercentage.set(keyframe.percentage, {
|
|
177
|
+
...keyframe,
|
|
178
|
+
properties: { ...keyframe.properties }
|
|
179
|
+
});
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
existing.properties = { ...existing.properties, ...keyframe.properties };
|
|
183
|
+
if (keyframe.ease !== void 0) existing.ease = keyframe.ease;
|
|
184
|
+
if (keyframe.auto !== void 0) existing.auto = keyframe.auto;
|
|
185
|
+
}
|
|
186
|
+
return [...byPercentage.values()].sort((a, b) => a.percentage - b.percentage);
|
|
187
|
+
}
|
|
188
|
+
function serializeGsapAnimations(animations, timelineVar = "tl", options) {
|
|
189
|
+
const sorted = [...animations].sort((a, b) => {
|
|
190
|
+
const aNum = a.resolvedStart ?? (typeof a.position === "number" ? a.position : Number.MAX_SAFE_INTEGER);
|
|
191
|
+
const bNum = b.resolvedStart ?? (typeof b.position === "number" ? b.position : Number.MAX_SAFE_INTEGER);
|
|
192
|
+
return aNum - bNum;
|
|
193
|
+
});
|
|
194
|
+
const lines = sorted.map((anim) => {
|
|
195
|
+
const selector = JSON.stringify(anim.targetSelector);
|
|
196
|
+
const props = { ...anim.properties };
|
|
197
|
+
if (anim.duration !== void 0) props.duration = anim.duration;
|
|
198
|
+
if (anim.ease) props.ease = anim.ease;
|
|
199
|
+
let propsStr = serializeObject(props);
|
|
200
|
+
if (anim.extras && Object.keys(anim.extras).length > 0) {
|
|
201
|
+
const extrasStr = serializeExtras(anim.extras);
|
|
202
|
+
if (Object.keys(props).length === 0) {
|
|
203
|
+
propsStr = `{ ${extrasStr} }`;
|
|
204
|
+
} else {
|
|
205
|
+
propsStr = propsStr.slice(0, -2) + `, ${extrasStr} }`;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
const posStr = JSON.stringify(anim.position);
|
|
209
|
+
switch (anim.method) {
|
|
210
|
+
case "set":
|
|
211
|
+
return anim.global ? ` gsap.set(${selector}, ${propsStr});` : ` ${timelineVar}.set(${selector}, ${propsStr}, ${posStr});`;
|
|
212
|
+
case "to":
|
|
213
|
+
return ` ${timelineVar}.to(${selector}, ${propsStr}, ${posStr});`;
|
|
214
|
+
case "from":
|
|
215
|
+
return ` ${timelineVar}.from(${selector}, ${propsStr}, ${posStr});`;
|
|
216
|
+
case "fromTo": {
|
|
217
|
+
const fromStr = serializeObject(anim.fromProperties || {});
|
|
218
|
+
return ` ${timelineVar}.fromTo(${selector}, ${fromStr}, ${propsStr}, ${posStr});`;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
let mediaSync = "";
|
|
223
|
+
if (options?.includeMediaSync) {
|
|
224
|
+
mediaSync = `
|
|
225
|
+
${timelineVar}.eventCallback("onUpdate", function() {
|
|
226
|
+
const time = ${timelineVar}.time();
|
|
227
|
+
document.querySelectorAll("video[data-start], audio[data-start]").forEach(function(media) {
|
|
228
|
+
const start = parseFloat(media.dataset.start);
|
|
229
|
+
const end = parseFloat(media.dataset.end) || Infinity;
|
|
230
|
+
const mediaTime = time - start;
|
|
231
|
+
if (time >= start && time < end) {
|
|
232
|
+
if (Math.abs(media.currentTime - mediaTime) > 0.1) {
|
|
233
|
+
media.currentTime = mediaTime;
|
|
234
|
+
}
|
|
235
|
+
if (media.paused && !${timelineVar}.paused()) {
|
|
236
|
+
media.play().catch(function() {});
|
|
237
|
+
}
|
|
238
|
+
} else if (!media.paused) {
|
|
239
|
+
media.pause();
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
});`;
|
|
243
|
+
}
|
|
244
|
+
const preamble = options?.preamble || `const ${timelineVar} = gsap.timeline({ paused: true });`;
|
|
245
|
+
const postamble = options?.postamble ? `
|
|
246
|
+
${options.postamble}` : "";
|
|
247
|
+
return `
|
|
248
|
+
${preamble}
|
|
249
|
+
${lines.join("\n")}${mediaSync}${postamble}
|
|
250
|
+
`;
|
|
251
|
+
}
|
|
252
|
+
function serializeValue(value) {
|
|
253
|
+
if (typeof value === "string" && value.startsWith("__raw:")) {
|
|
254
|
+
return value.slice(6);
|
|
255
|
+
}
|
|
256
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
257
|
+
return String(value);
|
|
258
|
+
}
|
|
259
|
+
function safeJsKey(key) {
|
|
260
|
+
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key) ? key : JSON.stringify(key);
|
|
261
|
+
}
|
|
262
|
+
function serializeObject(obj) {
|
|
263
|
+
const entries = Object.entries(obj).map(([key, value]) => {
|
|
264
|
+
return `${safeJsKey(key)}: ${serializeValue(value)}`;
|
|
265
|
+
});
|
|
266
|
+
return `{ ${entries.join(", ")} }`;
|
|
267
|
+
}
|
|
268
|
+
function serializeExtras(extras) {
|
|
269
|
+
return Object.entries(extras).map(([key, value]) => {
|
|
270
|
+
return `${safeJsKey(key)}: ${serializeValue(value)}`;
|
|
271
|
+
}).join(", ");
|
|
272
|
+
}
|
|
273
|
+
function getAnimationsForElementId(animations, elementId) {
|
|
274
|
+
const selector = `#${elementId}`;
|
|
275
|
+
return animations.filter((a) => a.targetSelector === selector);
|
|
276
|
+
}
|
|
277
|
+
var FORBIDDEN_GSAP_PATTERNS = [
|
|
278
|
+
{ pattern: /\.call\s*\(/, message: "call() method not allowed" },
|
|
279
|
+
{ pattern: /\.add\s*\(/, message: "add() method not allowed" },
|
|
280
|
+
{ pattern: /\.addPause\s*\(/, message: "addPause() method not allowed" },
|
|
281
|
+
{ pattern: /gsap\.registerEffect\s*\(/, message: "registerEffect() not allowed" },
|
|
282
|
+
{ pattern: /ScrollTrigger/, message: "ScrollTrigger not allowed" },
|
|
283
|
+
{ pattern: /onComplete\s*:/, message: "onComplete callback not allowed" },
|
|
284
|
+
{ pattern: /onUpdate\s*:/, message: "onUpdate callback not allowed" },
|
|
285
|
+
{ pattern: /onStart\s*:/, message: "onStart callback not allowed" },
|
|
286
|
+
{ pattern: /onRepeat\s*:/, message: "onRepeat callback not allowed" },
|
|
287
|
+
{ pattern: /onReverseComplete\s*:/, message: "onReverseComplete callback not allowed" },
|
|
288
|
+
{ pattern: /repeat\s*:\s*-1/, message: "Infinite repeat (repeat: -1) not allowed" },
|
|
289
|
+
{ pattern: /Math\.random\s*\(/, message: "Random values (Math.random) not allowed" },
|
|
290
|
+
{ pattern: /Date\.now\s*\(/, message: "Date-dependent values (Date.now) not allowed" },
|
|
291
|
+
{ pattern: /new\s+Date\s*\(/, message: "Date constructor not allowed" },
|
|
292
|
+
{ pattern: /setTimeout\s*\(/, message: "setTimeout not allowed" },
|
|
293
|
+
{ pattern: /setInterval\s*\(/, message: "setInterval not allowed" },
|
|
294
|
+
{ pattern: /requestAnimationFrame\s*\(/, message: "requestAnimationFrame not allowed" }
|
|
295
|
+
];
|
|
296
|
+
function validateCompositionGsap(script) {
|
|
297
|
+
const errors = [];
|
|
298
|
+
const warnings = [];
|
|
299
|
+
for (const { pattern, message } of FORBIDDEN_GSAP_PATTERNS) {
|
|
300
|
+
if (pattern.test(script)) errors.push(message);
|
|
301
|
+
}
|
|
302
|
+
if (/yoyo\s*:\s*true/.test(script)) {
|
|
303
|
+
warnings.push("yoyo animations may behave unexpectedly when scrubbing");
|
|
304
|
+
}
|
|
305
|
+
if (/stagger\s*:/.test(script)) {
|
|
306
|
+
warnings.push("stagger animations may not serialize correctly");
|
|
307
|
+
}
|
|
308
|
+
return { valid: errors.length === 0, errors, warnings };
|
|
309
|
+
}
|
|
310
|
+
function keyframesToGsapAnimations(elementId, keyframes, elementStartTime, base) {
|
|
311
|
+
const sorted = [...keyframes].sort((a, b) => a.time - b.time);
|
|
312
|
+
const animations = [];
|
|
313
|
+
const baseX = base?.x ?? 0;
|
|
314
|
+
const baseY = base?.y ?? 0;
|
|
315
|
+
const baseScale = base?.scale ?? 1;
|
|
316
|
+
sorted.forEach((kf, i) => {
|
|
317
|
+
const absoluteTime = elementStartTime + kf.time;
|
|
318
|
+
const isFirst = i === 0;
|
|
319
|
+
const prevKf = i > 0 ? sorted[i - 1] : null;
|
|
320
|
+
const duration = prevKf ? kf.time - prevKf.time : void 0;
|
|
321
|
+
const position = prevKf ? elementStartTime + prevKf.time : absoluteTime;
|
|
322
|
+
const properties = {};
|
|
323
|
+
for (const [key, value] of Object.entries(kf.properties)) {
|
|
324
|
+
if (typeof value !== "number") continue;
|
|
325
|
+
if (key === "x") properties.x = baseX + value;
|
|
326
|
+
else if (key === "y") properties.y = baseY + value;
|
|
327
|
+
else if (key === "scale") properties.scale = baseScale * value;
|
|
328
|
+
else properties[key] = value;
|
|
329
|
+
}
|
|
330
|
+
animations.push({
|
|
331
|
+
id: `${elementId}-kf-${kf.id}`,
|
|
332
|
+
targetSelector: `#${elementId}`,
|
|
333
|
+
method: isFirst ? "set" : "to",
|
|
334
|
+
position,
|
|
335
|
+
properties,
|
|
336
|
+
duration: isFirst ? void 0 : duration,
|
|
337
|
+
ease: kf.ease
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
return animations;
|
|
341
|
+
}
|
|
342
|
+
function gsapAnimationsToKeyframes(animations, elementStartTime, options) {
|
|
343
|
+
const validMethods = ["set", "to", "from", "fromTo"];
|
|
344
|
+
const baseX = options?.baseX ?? 0;
|
|
345
|
+
const baseY = options?.baseY ?? 0;
|
|
346
|
+
const baseScale = options?.baseScale ?? 1;
|
|
347
|
+
const clampTimeToZero = options?.clampTimeToZero ?? true;
|
|
348
|
+
const skipBaseSet = options?.skipBaseSet ?? false;
|
|
349
|
+
const baseTimeEpsilon = 1e-3;
|
|
350
|
+
const baseValueEpsilon = 1e-5;
|
|
351
|
+
return animations.filter(
|
|
352
|
+
(a) => validMethods.includes(a.method) && typeof a.position === "number"
|
|
353
|
+
).map((a) => {
|
|
354
|
+
const relativeTimeRaw = a.position - elementStartTime;
|
|
355
|
+
const time = clampTimeToZero ? Math.max(0, relativeTimeRaw) : relativeTimeRaw;
|
|
356
|
+
const properties = {};
|
|
357
|
+
for (const [key, value] of Object.entries(a.properties)) {
|
|
358
|
+
if (typeof value !== "number") continue;
|
|
359
|
+
if (key === "x") properties.x = value - baseX;
|
|
360
|
+
else if (key === "y") properties.y = value - baseY;
|
|
361
|
+
else if (key === "scale") {
|
|
362
|
+
properties.scale = baseScale !== 0 ? value / baseScale : value;
|
|
363
|
+
} else {
|
|
364
|
+
properties[key] = value;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
if (skipBaseSet && a.method === "set" && time < baseTimeEpsilon && Object.values(properties).every(
|
|
368
|
+
(v) => typeof v === "number" && Math.abs(v) < baseValueEpsilon
|
|
369
|
+
)) {
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
372
|
+
return {
|
|
373
|
+
id: a.id.replace(/^.*-kf-/, ""),
|
|
374
|
+
time,
|
|
375
|
+
properties,
|
|
376
|
+
ease: a.ease
|
|
377
|
+
};
|
|
378
|
+
}).filter((kf) => kf !== null);
|
|
379
|
+
}
|
|
380
|
+
var CSS_IDENTITY = {
|
|
381
|
+
opacity: 1,
|
|
382
|
+
autoAlpha: 1,
|
|
383
|
+
scale: 1,
|
|
384
|
+
scaleX: 1,
|
|
385
|
+
scaleY: 1
|
|
386
|
+
};
|
|
387
|
+
function cssIdentityValue(prop) {
|
|
388
|
+
return CSS_IDENTITY[prop] ?? 0;
|
|
389
|
+
}
|
|
390
|
+
function buildIdentityMap(props) {
|
|
391
|
+
const identity = {};
|
|
392
|
+
for (const [key, val] of Object.entries(props)) {
|
|
393
|
+
if (val != null) identity[key] = typeof val === "number" ? cssIdentityValue(key) : val;
|
|
394
|
+
}
|
|
395
|
+
return identity;
|
|
396
|
+
}
|
|
397
|
+
function resolveConversionProps(anim, resolvedFromValues) {
|
|
398
|
+
if (anim.method === "set") {
|
|
399
|
+
return { fromProps: { ...anim.properties }, toProps: { ...anim.properties } };
|
|
400
|
+
}
|
|
401
|
+
if (anim.method === "to") {
|
|
402
|
+
const identity = buildIdentityMap(anim.properties);
|
|
403
|
+
const fromProps = resolvedFromValues ? { ...identity, ...resolvedFromValues } : identity;
|
|
404
|
+
return { fromProps, toProps: { ...anim.properties } };
|
|
405
|
+
}
|
|
406
|
+
if (anim.method === "from") {
|
|
407
|
+
const identity = buildIdentityMap(anim.properties);
|
|
408
|
+
const toProps2 = resolvedFromValues ? { ...identity, ...resolvedFromValues } : identity;
|
|
409
|
+
return { fromProps: { ...anim.properties }, toProps: toProps2 };
|
|
410
|
+
}
|
|
411
|
+
const toProps = resolvedFromValues ? { ...anim.properties, ...resolvedFromValues } : { ...anim.properties };
|
|
412
|
+
return { fromProps: { ...anim.fromProperties ?? {} }, toProps };
|
|
413
|
+
}
|
|
414
|
+
function clipTweenMatcher(clipSelectors, root, queries = /* @__PURE__ */ new Map()) {
|
|
415
|
+
const own = typeof clipSelectors === "string" ? [clipSelectors] : clipSelectors;
|
|
416
|
+
if (!root)
|
|
417
|
+
return ({ targetSelector, hasPartialSelector }) => !hasPartialSelector && own.includes(targetSelector);
|
|
418
|
+
const queryAll = (selector) => {
|
|
419
|
+
if (ID_SELECTOR.test(selector)) {
|
|
420
|
+
if (!queries.has(ALL_IDS)) indexIds(root, queries);
|
|
421
|
+
return queries.get(selector) ?? [];
|
|
422
|
+
}
|
|
423
|
+
let found = queries.get(selector);
|
|
424
|
+
if (!found) queries.set(selector, found = queryRoot(root, selector));
|
|
425
|
+
return found;
|
|
426
|
+
};
|
|
427
|
+
const clips = own.flatMap((selector) => queryAll(selector));
|
|
428
|
+
return ({ targetSelector, hasPartialSelector }) => {
|
|
429
|
+
if (hasPartialSelector) return false;
|
|
430
|
+
if (own.includes(targetSelector)) return true;
|
|
431
|
+
if (clips.length === 0) return false;
|
|
432
|
+
const targets = queryAll(targetSelector);
|
|
433
|
+
return targets.length > 0 && targets.every((target) => {
|
|
434
|
+
const owner = target.closest("[data-start]");
|
|
435
|
+
return clips.includes(target) || owner !== null && clips.includes(owner);
|
|
436
|
+
});
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
function hasExplicitTime(animation) {
|
|
440
|
+
return typeof animation.position === "number" && !animation.implicitPosition;
|
|
441
|
+
}
|
|
442
|
+
var ID_SELECTOR = /^#-?[A-Za-z_][\w-]*$/;
|
|
443
|
+
var ALL_IDS = "[id]";
|
|
444
|
+
function indexIds(root, queries) {
|
|
445
|
+
const all = queryRoot(root, ALL_IDS);
|
|
446
|
+
queries.set(ALL_IDS, all);
|
|
447
|
+
for (const el of all) {
|
|
448
|
+
const key = `#${el.id}`;
|
|
449
|
+
if (!ID_SELECTOR.test(key)) continue;
|
|
450
|
+
const list = queries.get(key);
|
|
451
|
+
if (list) list.push(el);
|
|
452
|
+
else queries.set(key, [el]);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
function queryRoot(root, selector) {
|
|
456
|
+
try {
|
|
457
|
+
return Array.from(root.querySelectorAll(selector));
|
|
458
|
+
} catch {
|
|
459
|
+
return [];
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
var roundPercentage = (percentage) => Math.round(percentage * 10) / 10;
|
|
463
|
+
var OBJECT_ARRAY_PERCENTAGE_TOLERANCE = 2;
|
|
464
|
+
function getObjectArrayKeyframeTiming(durations) {
|
|
465
|
+
const steps = durations.map((duration) => duration ?? GSAP_DEFAULT_DURATION);
|
|
466
|
+
if (!steps.every(
|
|
467
|
+
(duration) => typeof duration === "number" && Number.isFinite(duration) && duration > 0
|
|
468
|
+
)) {
|
|
469
|
+
return null;
|
|
470
|
+
}
|
|
471
|
+
const totalDuration = steps.reduce((sum, duration) => sum + duration, 0);
|
|
472
|
+
let cumulative = 0;
|
|
473
|
+
return {
|
|
474
|
+
percentages: steps.map((duration) => {
|
|
475
|
+
cumulative += duration;
|
|
476
|
+
return roundPercentage(cumulative / totalDuration * 100);
|
|
477
|
+
}),
|
|
478
|
+
totalDuration
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
function getCompatibleObjectArrayKeyframeTiming(durations, outerDuration) {
|
|
482
|
+
const timing = getObjectArrayKeyframeTiming(durations);
|
|
483
|
+
if (!timing) return null;
|
|
484
|
+
const stepsAuthorDuration = durations.some((duration) => duration !== void 0);
|
|
485
|
+
if (!stepsAuthorDuration || outerDuration === void 0) return timing;
|
|
486
|
+
if (typeof outerDuration === "number" && Math.abs(outerDuration - timing.totalDuration) <= Number.EPSILON) {
|
|
487
|
+
return timing;
|
|
488
|
+
}
|
|
489
|
+
return null;
|
|
490
|
+
}
|
|
491
|
+
function findObjectArrayKeyframeIndex(durations, percentage, options) {
|
|
492
|
+
if (!Number.isFinite(percentage) || percentage < 0 || percentage > 100) return null;
|
|
493
|
+
const timing = getObjectArrayKeyframeTiming(durations);
|
|
494
|
+
if (!timing) return null;
|
|
495
|
+
const { percentages } = timing;
|
|
496
|
+
let match = null;
|
|
497
|
+
let bestDistance = Number.POSITIVE_INFINITY;
|
|
498
|
+
for (let index = 0; index < percentages.length; index++) {
|
|
499
|
+
const distance = Math.abs(percentages[index] - percentage);
|
|
500
|
+
if (distance < bestDistance) {
|
|
501
|
+
match = index;
|
|
502
|
+
bestDistance = distance;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
const tolerance = options?.tolerance ?? OBJECT_ARRAY_PERCENTAGE_TOLERANCE;
|
|
506
|
+
return bestDistance <= tolerance || options?.fallbackToNearest ? match : null;
|
|
507
|
+
}
|
|
508
|
+
var SPRING_PRESETS = [
|
|
509
|
+
{ name: "spring-gentle", label: "Gentle", mass: 1, stiffness: 100, damping: 15 },
|
|
510
|
+
{ name: "spring-bouncy", label: "Bouncy", mass: 1, stiffness: 180, damping: 12 },
|
|
511
|
+
{ name: "spring-stiff", label: "Stiff", mass: 1, stiffness: 300, damping: 20 },
|
|
512
|
+
{ name: "spring-wobbly", label: "Wobbly", mass: 1, stiffness: 120, damping: 8 },
|
|
513
|
+
{ name: "spring-heavy", label: "Heavy", mass: 3, stiffness: 200, damping: 20 }
|
|
514
|
+
];
|
|
515
|
+
function generateSpringEaseData(mass, stiffness, damping, steps = 120) {
|
|
516
|
+
const w0 = Math.sqrt(stiffness / mass);
|
|
517
|
+
const zeta = damping / (2 * Math.sqrt(stiffness * mass));
|
|
518
|
+
let settleDuration;
|
|
519
|
+
if (zeta < 1) {
|
|
520
|
+
settleDuration = Math.min(5 / (zeta * w0), 10);
|
|
521
|
+
} else {
|
|
522
|
+
const decayRate = zeta * w0 - w0 * Math.sqrt(zeta * zeta - 1);
|
|
523
|
+
settleDuration = Math.min(4 / Math.max(decayRate, 0.01), 10);
|
|
524
|
+
}
|
|
525
|
+
const simDuration = Math.max(settleDuration, 1);
|
|
526
|
+
const segments = ["M0,0"];
|
|
527
|
+
for (let i = 1; i <= steps; i++) {
|
|
528
|
+
const t = i / steps;
|
|
529
|
+
const simT = t * simDuration;
|
|
530
|
+
let value;
|
|
531
|
+
if (zeta < 1) {
|
|
532
|
+
const wd = w0 * Math.sqrt(1 - zeta * zeta);
|
|
533
|
+
value = 1 - Math.exp(-zeta * w0 * simT) * (Math.cos(wd * simT) + zeta * w0 / wd * Math.sin(wd * simT));
|
|
534
|
+
} else if (zeta === 1) {
|
|
535
|
+
value = 1 - (1 + w0 * simT) * Math.exp(-w0 * simT);
|
|
536
|
+
} else {
|
|
537
|
+
const s1 = -w0 * (zeta - Math.sqrt(zeta * zeta - 1));
|
|
538
|
+
const s2 = -w0 * (zeta + Math.sqrt(zeta * zeta - 1));
|
|
539
|
+
value = 1 + (s1 * Math.exp(s2 * simT) - s2 * Math.exp(s1 * simT)) / (s2 - s1);
|
|
540
|
+
}
|
|
541
|
+
segments.push(`${t.toFixed(4)},${value.toFixed(4)}`);
|
|
542
|
+
}
|
|
543
|
+
segments[segments.length - 1] = "1,1";
|
|
544
|
+
return `${segments[0]} L${segments.slice(1).join(" ")}`;
|
|
545
|
+
}
|
|
546
|
+
var GSAP_METHODS = /* @__PURE__ */ new Set(["set", "to", "from", "fromTo"]);
|
|
547
|
+
function parseScript(script) {
|
|
548
|
+
return recast.parse(script, {
|
|
549
|
+
parser: {
|
|
550
|
+
parse(source) {
|
|
551
|
+
return (0, import_parser.parse)(source, { sourceType: "script", plugins: [], tokens: true });
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
function collectScopeBindings(ast) {
|
|
557
|
+
const bindings = /* @__PURE__ */ new Map();
|
|
558
|
+
recast.types.visit(ast, {
|
|
559
|
+
visitVariableDeclarator(path) {
|
|
560
|
+
const name = path.node.id?.name;
|
|
561
|
+
const init = path.node.init;
|
|
562
|
+
if (name && init) {
|
|
563
|
+
const val = resolveNode(init, bindings);
|
|
564
|
+
if (val !== void 0) bindings.set(name, val);
|
|
565
|
+
}
|
|
566
|
+
this.traverse(path);
|
|
567
|
+
}
|
|
568
|
+
});
|
|
569
|
+
return bindings;
|
|
570
|
+
}
|
|
571
|
+
function resolveNode(node, scope) {
|
|
572
|
+
if (!node) return void 0;
|
|
573
|
+
if (node.type === "NumericLiteral" || node.type === "Literal" && typeof node.value === "number")
|
|
574
|
+
return node.value;
|
|
575
|
+
if (node.type === "StringLiteral" || node.type === "Literal" && typeof node.value === "string")
|
|
576
|
+
return node.value;
|
|
577
|
+
if (node.type === "BooleanLiteral" || node.type === "Literal" && typeof node.value === "boolean")
|
|
578
|
+
return node.value;
|
|
579
|
+
if (node.type === "UnaryExpression" && node.operator === "-" && node.argument) {
|
|
580
|
+
const val = resolveNode(node.argument, scope);
|
|
581
|
+
return typeof val === "number" ? -val : void 0;
|
|
582
|
+
}
|
|
583
|
+
if (node.type === "BinaryExpression") {
|
|
584
|
+
const left = resolveNode(node.left, scope);
|
|
585
|
+
const right = resolveNode(node.right, scope);
|
|
586
|
+
if (typeof left === "number" && typeof right === "number") {
|
|
587
|
+
switch (node.operator) {
|
|
588
|
+
case "+":
|
|
589
|
+
return left + right;
|
|
590
|
+
case "-":
|
|
591
|
+
return left - right;
|
|
592
|
+
case "*":
|
|
593
|
+
return left * right;
|
|
594
|
+
case "/":
|
|
595
|
+
return right !== 0 ? left / right : void 0;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
if (typeof left === "string" && node.operator === "+") return left + String(right ?? "");
|
|
599
|
+
if (typeof right === "string" && node.operator === "+") return String(left ?? "") + right;
|
|
600
|
+
}
|
|
601
|
+
if (node.type === "Identifier" && scope.has(node.name)) {
|
|
602
|
+
return scope.get(node.name);
|
|
603
|
+
}
|
|
604
|
+
if (node.type === "TemplateLiteral" && node.expressions?.length === 0) {
|
|
605
|
+
return node.quasis?.[0]?.value?.cooked ?? void 0;
|
|
606
|
+
}
|
|
607
|
+
return void 0;
|
|
608
|
+
}
|
|
609
|
+
function extractLiteralValue(node, scope) {
|
|
610
|
+
return resolveNode(node, scope);
|
|
611
|
+
}
|
|
612
|
+
var QUERY_METHODS = /* @__PURE__ */ new Set(["querySelector", "querySelectorAll"]);
|
|
613
|
+
var ITERATION_METHODS = /* @__PURE__ */ new Set(["forEach", "map"]);
|
|
614
|
+
var SCOPE_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
615
|
+
"Program",
|
|
616
|
+
"FunctionDeclaration",
|
|
617
|
+
"FunctionExpression",
|
|
618
|
+
"ArrowFunctionExpression"
|
|
619
|
+
]);
|
|
620
|
+
function selectorFromQueryCall(node, scope) {
|
|
621
|
+
if (node?.type !== "CallExpression") return null;
|
|
622
|
+
const callee = node.callee;
|
|
623
|
+
if (callee?.type !== "MemberExpression" || callee.property?.type !== "Identifier") return null;
|
|
624
|
+
const method = callee.property.name;
|
|
625
|
+
const argValue = resolveNode(node.arguments?.[0], scope);
|
|
626
|
+
if (typeof argValue !== "string" || argValue.length === 0) return null;
|
|
627
|
+
if (QUERY_METHODS.has(method) || method === "toArray") return argValue;
|
|
628
|
+
if (method === "getElementById") return `#${argValue}`;
|
|
629
|
+
return null;
|
|
630
|
+
}
|
|
631
|
+
function enclosingScopeNode(path) {
|
|
632
|
+
let p = path?.parentPath;
|
|
633
|
+
while (p) {
|
|
634
|
+
if (SCOPE_NODE_TYPES.has(p.node?.type)) return p.node;
|
|
635
|
+
p = p.parentPath;
|
|
636
|
+
}
|
|
637
|
+
return null;
|
|
638
|
+
}
|
|
639
|
+
function scopeChainOf(path) {
|
|
640
|
+
const chain = [];
|
|
641
|
+
let p = path;
|
|
642
|
+
while (p) {
|
|
643
|
+
if (SCOPE_NODE_TYPES.has(p.node?.type)) chain.push(p.node);
|
|
644
|
+
p = p.parentPath;
|
|
645
|
+
}
|
|
646
|
+
return chain;
|
|
647
|
+
}
|
|
648
|
+
function addBinding(bindings, scopeNode, name, selector) {
|
|
649
|
+
let scoped = bindings.get(scopeNode);
|
|
650
|
+
if (!scoped) {
|
|
651
|
+
scoped = /* @__PURE__ */ new Map();
|
|
652
|
+
bindings.set(scopeNode, scoped);
|
|
653
|
+
}
|
|
654
|
+
if (!scoped.has(name)) scoped.set(name, selector);
|
|
655
|
+
}
|
|
656
|
+
function directHelperReturn(node) {
|
|
657
|
+
if (node.type === "ArrowFunctionExpression" && node.body?.type !== "BlockStatement") {
|
|
658
|
+
return node.body;
|
|
659
|
+
}
|
|
660
|
+
if (!isFunctionNode(node) || node.body?.type !== "BlockStatement") return null;
|
|
661
|
+
const returns = (node.body.body ?? []).filter(
|
|
662
|
+
(statement) => statement.type === "ReturnStatement" && statement.argument
|
|
663
|
+
);
|
|
664
|
+
return returns.length === 1 ? returns[0].argument : null;
|
|
665
|
+
}
|
|
666
|
+
function collectTargetHelpers(ast) {
|
|
667
|
+
const helpers = /* @__PURE__ */ new Map();
|
|
668
|
+
const add = (scopeNode, name, fn) => {
|
|
669
|
+
const returnNode = directHelperReturn(fn);
|
|
670
|
+
const params = (fn.params ?? []).filter((param) => param.type === "Identifier").map((param) => param.name);
|
|
671
|
+
if (!returnNode || params.length !== (fn.params?.length ?? 0)) return;
|
|
672
|
+
let scoped = helpers.get(scopeNode);
|
|
673
|
+
if (!scoped) {
|
|
674
|
+
scoped = /* @__PURE__ */ new Map();
|
|
675
|
+
helpers.set(scopeNode, scoped);
|
|
676
|
+
}
|
|
677
|
+
if (!scoped.has(name)) scoped.set(name, { params, returnNode });
|
|
678
|
+
};
|
|
679
|
+
recast.types.visit(ast, {
|
|
680
|
+
visitFunctionDeclaration(path) {
|
|
681
|
+
const name = path.node.id?.name;
|
|
682
|
+
const scopeNode = enclosingScopeNode(path);
|
|
683
|
+
if (name && scopeNode) add(scopeNode, name, path.node);
|
|
684
|
+
this.traverse(path);
|
|
685
|
+
},
|
|
686
|
+
visitVariableDeclarator(path) {
|
|
687
|
+
const name = path.node.id?.name;
|
|
688
|
+
const fn = path.node.init;
|
|
689
|
+
const scopeNode = enclosingScopeNode(path);
|
|
690
|
+
if (name && fn && isFunctionNode(fn) && scopeNode) add(scopeNode, name, fn);
|
|
691
|
+
this.traverse(path);
|
|
692
|
+
}
|
|
693
|
+
});
|
|
694
|
+
return helpers;
|
|
695
|
+
}
|
|
696
|
+
function lookupTargetHelper(name, path, helpers) {
|
|
697
|
+
for (const scopeNode of scopeChainOf(path)) {
|
|
698
|
+
const helper = helpers.get(scopeNode)?.get(name);
|
|
699
|
+
if (helper) return helper;
|
|
700
|
+
}
|
|
701
|
+
return null;
|
|
702
|
+
}
|
|
703
|
+
function selectorFromTargetCall(node, path, scope, helpers) {
|
|
704
|
+
const direct = selectorFromQueryCall(node, scope);
|
|
705
|
+
if (direct) return direct;
|
|
706
|
+
if (node?.type !== "CallExpression" || node.callee?.type !== "Identifier") return null;
|
|
707
|
+
const helper = lookupTargetHelper(node.callee.name, path, helpers);
|
|
708
|
+
if (!helper || helper.params.length !== (node.arguments?.length ?? 0)) return null;
|
|
709
|
+
const helperScope = new Map(scope);
|
|
710
|
+
for (let i = 0; i < helper.params.length; i += 1) {
|
|
711
|
+
const param = helper.params[i];
|
|
712
|
+
if (!param) return null;
|
|
713
|
+
const value = resolveNode(node.arguments[i], scope);
|
|
714
|
+
if (value === void 0) return null;
|
|
715
|
+
helperScope.set(param, value);
|
|
716
|
+
}
|
|
717
|
+
return selectorFromQueryCall(helper.returnNode, helperScope);
|
|
718
|
+
}
|
|
719
|
+
function collectTargetBindings(ast, scope, helpers) {
|
|
720
|
+
const bindings = /* @__PURE__ */ new Map();
|
|
721
|
+
recast.types.visit(ast, {
|
|
722
|
+
visitVariableDeclarator(path) {
|
|
723
|
+
const name = path.node.id?.name;
|
|
724
|
+
const selector = selectorFromTargetCall(path.node.init, path, scope, helpers);
|
|
725
|
+
const scopeNode = enclosingScopeNode(path);
|
|
726
|
+
if (name && selector !== null && scopeNode) addBinding(bindings, scopeNode, name, selector);
|
|
727
|
+
this.traverse(path);
|
|
728
|
+
},
|
|
729
|
+
visitAssignmentExpression(path) {
|
|
730
|
+
const left = path.node.left;
|
|
731
|
+
const selector = selectorFromTargetCall(path.node.right, path, scope, helpers);
|
|
732
|
+
const scopeNode = enclosingScopeNode(path);
|
|
733
|
+
if (left?.type === "Identifier" && selector !== null && scopeNode) {
|
|
734
|
+
addBinding(bindings, scopeNode, left.name, selector);
|
|
735
|
+
}
|
|
736
|
+
this.traverse(path);
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
recast.types.visit(ast, {
|
|
740
|
+
visitCallExpression(path) {
|
|
741
|
+
const node = path.node;
|
|
742
|
+
const callee = node.callee;
|
|
743
|
+
if (callee?.type === "MemberExpression" && callee.property?.type === "Identifier" && ITERATION_METHODS.has(callee.property.name)) {
|
|
744
|
+
const collectionSelector = resolveCollectionSelector(callee.object, path, scope, bindings);
|
|
745
|
+
const fn = node.arguments?.[0];
|
|
746
|
+
const param = fn?.params?.[0];
|
|
747
|
+
if (collectionSelector && param?.type === "Identifier" && isFunctionNode(fn)) {
|
|
748
|
+
addBinding(bindings, fn, param.name, collectionSelector);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
this.traverse(path);
|
|
752
|
+
}
|
|
753
|
+
});
|
|
754
|
+
return bindings;
|
|
755
|
+
}
|
|
756
|
+
function isFunctionNode(node) {
|
|
757
|
+
return node?.type === "ArrowFunctionExpression" || node?.type === "FunctionExpression" || node?.type === "FunctionDeclaration";
|
|
758
|
+
}
|
|
759
|
+
function resolveCollectionSelector(node, callPath, scope, bindings) {
|
|
760
|
+
if (node?.type === "Identifier") return lookupBinding(node.name, callPath, bindings);
|
|
761
|
+
if (node?.type === "CallExpression") return selectorFromQueryCall(node, scope);
|
|
762
|
+
return null;
|
|
763
|
+
}
|
|
764
|
+
function lookupBinding(name, path, bindings) {
|
|
765
|
+
for (const scopeNode of scopeChainOf(path)) {
|
|
766
|
+
const selector = bindings.get(scopeNode)?.get(name);
|
|
767
|
+
if (selector !== void 0) return selector;
|
|
768
|
+
}
|
|
769
|
+
return null;
|
|
770
|
+
}
|
|
771
|
+
function hasUnresolvedArrayPart(node, path, scope, bindings, helpers) {
|
|
772
|
+
return node?.type === "ArrayExpression" && node.elements.some(
|
|
773
|
+
(el) => !resolveTargetSelector(el, path, scope, bindings, helpers) || hasUnresolvedArrayPart(el, path, scope, bindings, helpers)
|
|
774
|
+
);
|
|
775
|
+
}
|
|
776
|
+
function resolveTargetSelector(node, path, scope, bindings, helpers) {
|
|
777
|
+
if (!node) return null;
|
|
778
|
+
if (node.type === "StringLiteral" || node.type === "Literal") {
|
|
779
|
+
return typeof node.value === "string" ? node.value : null;
|
|
780
|
+
}
|
|
781
|
+
if (node.type === "Identifier") {
|
|
782
|
+
return lookupBinding(node.name, path, bindings);
|
|
783
|
+
}
|
|
784
|
+
if (node.type === "CallExpression") {
|
|
785
|
+
return selectorFromTargetCall(node, path, scope, helpers);
|
|
786
|
+
}
|
|
787
|
+
if (node.type === "ArrayExpression") {
|
|
788
|
+
const parts = node.elements.map((el) => resolveTargetSelector(el, path, scope, bindings, helpers)).filter((s) => typeof s === "string" && s.length > 0);
|
|
789
|
+
return parts.length > 0 ? parts.join(", ") : null;
|
|
790
|
+
}
|
|
791
|
+
if (node.type === "MemberExpression" && node.object?.type === "Identifier") {
|
|
792
|
+
return lookupBinding(node.object.name, path, bindings);
|
|
793
|
+
}
|
|
794
|
+
return null;
|
|
795
|
+
}
|
|
796
|
+
function objectExpressionToRecord(node, scope) {
|
|
797
|
+
const result = {};
|
|
798
|
+
if (node?.type !== "ObjectExpression") return result;
|
|
799
|
+
for (const prop of node.properties ?? []) {
|
|
800
|
+
if (prop.type !== "ObjectProperty" && prop.type !== "Property") continue;
|
|
801
|
+
const key = prop.key?.name ?? prop.key?.value;
|
|
802
|
+
if (!key) continue;
|
|
803
|
+
const resolved = resolveNode(prop.value, scope);
|
|
804
|
+
if (resolved !== void 0) {
|
|
805
|
+
result[key] = resolved;
|
|
806
|
+
} else {
|
|
807
|
+
result[key] = `__raw:${recast.print(prop.value).code}`;
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
return result;
|
|
811
|
+
}
|
|
812
|
+
function isGsapTimelineCall(node) {
|
|
813
|
+
return node?.type === "CallExpression" && node.callee?.type === "MemberExpression" && node.callee.object?.name === "gsap" && node.callee.property?.name === "timeline";
|
|
814
|
+
}
|
|
815
|
+
function staticMemberKey(node) {
|
|
816
|
+
if (!node || node.type !== "MemberExpression") return null;
|
|
817
|
+
if (node.computed) {
|
|
818
|
+
const p = node.property;
|
|
819
|
+
if (p?.type === "StringLiteral") return p.value;
|
|
820
|
+
if (p?.type === "Literal" && typeof p.value === "string") return p.value;
|
|
821
|
+
return null;
|
|
822
|
+
}
|
|
823
|
+
return node.property?.type === "Identifier" ? node.property.name : null;
|
|
824
|
+
}
|
|
825
|
+
function isStaticMemberRef(node) {
|
|
826
|
+
return node?.type === "MemberExpression" && staticMemberKey(node) !== null;
|
|
827
|
+
}
|
|
828
|
+
function sameMemberAccess(a, b) {
|
|
829
|
+
if (a?.type !== "MemberExpression" || b?.type !== "MemberExpression") return false;
|
|
830
|
+
if (staticMemberKey(a) !== staticMemberKey(b) || staticMemberKey(a) === null) return false;
|
|
831
|
+
const ao = a.object;
|
|
832
|
+
const bo = b.object;
|
|
833
|
+
if (ao?.type === "Identifier" && bo?.type === "Identifier") return ao.name === bo.name;
|
|
834
|
+
if (ao?.type === "MemberExpression" && bo?.type === "MemberExpression")
|
|
835
|
+
return sameMemberAccess(ao, bo);
|
|
836
|
+
return false;
|
|
837
|
+
}
|
|
838
|
+
function timelineRootSource(ref) {
|
|
839
|
+
return ref.kind === "identifier" ? ref.name : recast.print(ref.node).code;
|
|
840
|
+
}
|
|
841
|
+
function escapeRegExp(s) {
|
|
842
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
843
|
+
}
|
|
844
|
+
function extractTimelineDefaults(callNode, scope) {
|
|
845
|
+
const arg = callNode.arguments?.[0];
|
|
846
|
+
if (!arg || arg.type !== "ObjectExpression") return void 0;
|
|
847
|
+
const defaultsProp = arg.properties?.find(
|
|
848
|
+
(p) => isObjectProperty(p) && propKeyName(p) === "defaults"
|
|
849
|
+
);
|
|
850
|
+
if (!defaultsProp?.value || defaultsProp.value.type !== "ObjectExpression") return void 0;
|
|
851
|
+
const record = objectExpressionToRecord(defaultsProp.value, scope);
|
|
852
|
+
const result = {};
|
|
853
|
+
if (typeof record.ease === "string") result.ease = record.ease;
|
|
854
|
+
if (typeof record.duration === "number") result.duration = record.duration;
|
|
855
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
856
|
+
}
|
|
857
|
+
function findTimelineVar(ast, scope) {
|
|
858
|
+
let timelineVar = null;
|
|
859
|
+
let ref = null;
|
|
860
|
+
let timelineCount = 0;
|
|
861
|
+
let defaults;
|
|
862
|
+
const emptyScope = scope ?? /* @__PURE__ */ new Map();
|
|
863
|
+
recast.types.visit(ast, {
|
|
864
|
+
visitVariableDeclarator(path) {
|
|
865
|
+
if (isGsapTimelineCall(path.node.init)) {
|
|
866
|
+
timelineCount += 1;
|
|
867
|
+
if (!ref && path.node.id?.type === "Identifier") {
|
|
868
|
+
timelineVar = path.node.id.name;
|
|
869
|
+
ref = { kind: "identifier", name: path.node.id.name };
|
|
870
|
+
defaults = extractTimelineDefaults(path.node.init, emptyScope);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
this.traverse(path);
|
|
874
|
+
},
|
|
875
|
+
visitAssignmentExpression(path) {
|
|
876
|
+
if (isGsapTimelineCall(path.node.right)) {
|
|
877
|
+
timelineCount += 1;
|
|
878
|
+
if (!ref) {
|
|
879
|
+
const left = path.node.left;
|
|
880
|
+
if (left?.type === "Identifier") {
|
|
881
|
+
timelineVar = left.name;
|
|
882
|
+
ref = { kind: "identifier", name: left.name };
|
|
883
|
+
defaults = extractTimelineDefaults(path.node.right, emptyScope);
|
|
884
|
+
} else if (isStaticMemberRef(left)) {
|
|
885
|
+
ref = { kind: "member", node: left };
|
|
886
|
+
defaults = extractTimelineDefaults(path.node.right, emptyScope);
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
this.traverse(path);
|
|
891
|
+
}
|
|
892
|
+
});
|
|
893
|
+
return { timelineVar, ref, timelineCount, defaults };
|
|
894
|
+
}
|
|
895
|
+
function isTimelineRootedCall(callNode, ref) {
|
|
896
|
+
let obj = callNode.callee?.object;
|
|
897
|
+
while (obj?.type === "CallExpression") {
|
|
898
|
+
obj = obj.callee?.object;
|
|
899
|
+
}
|
|
900
|
+
if (ref.kind === "identifier") return obj?.type === "Identifier" && obj.name === ref.name;
|
|
901
|
+
return sameMemberAccess(obj, ref.node);
|
|
902
|
+
}
|
|
903
|
+
function findAllTweenCalls(ast, ref, scope, targetBindings, targetHelpers) {
|
|
904
|
+
const results = [];
|
|
905
|
+
recast.types.visit(ast, {
|
|
906
|
+
visitCallExpression(path) {
|
|
907
|
+
const node = path.node;
|
|
908
|
+
const callee = node.callee;
|
|
909
|
+
const gsapSetArg = node.arguments?.[0];
|
|
910
|
+
const isGlobalSet = callee?.type === "MemberExpression" && callee.object?.type === "Identifier" && callee.object.name === "gsap" && callee.property?.type === "Identifier" && callee.property.name === "set" && (gsapSetArg?.type === "StringLiteral" || gsapSetArg?.type === "Literal" && typeof gsapSetArg.value === "string");
|
|
911
|
+
if (callee?.type === "MemberExpression" && callee.property?.type === "Identifier" && (isTimelineRootedCall(node, ref) || isGlobalSet)) {
|
|
912
|
+
const method = callee.property.name;
|
|
913
|
+
if (!GSAP_METHODS.has(method)) {
|
|
914
|
+
this.traverse(path);
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
const args = node.arguments;
|
|
918
|
+
if (args.length < 2) {
|
|
919
|
+
this.traverse(path);
|
|
920
|
+
return;
|
|
921
|
+
}
|
|
922
|
+
const selectorValue = resolveTargetSelector(args[0], path, scope, targetBindings, targetHelpers) ?? "__unresolved__";
|
|
923
|
+
const partial = hasUnresolvedArrayPart(args[0], path, scope, targetBindings, targetHelpers) ? { selectorPartial: true } : {};
|
|
924
|
+
if (method === "fromTo") {
|
|
925
|
+
results.push({
|
|
926
|
+
path,
|
|
927
|
+
node,
|
|
928
|
+
method: "fromTo",
|
|
929
|
+
selector: selectorValue,
|
|
930
|
+
...partial,
|
|
931
|
+
fromArg: args[1],
|
|
932
|
+
varsArg: args[2],
|
|
933
|
+
positionArg: args[3]
|
|
934
|
+
});
|
|
935
|
+
} else {
|
|
936
|
+
results.push({
|
|
937
|
+
path,
|
|
938
|
+
node,
|
|
939
|
+
method,
|
|
940
|
+
selector: selectorValue,
|
|
941
|
+
...partial,
|
|
942
|
+
varsArg: args[1],
|
|
943
|
+
positionArg: args[2],
|
|
944
|
+
...isGlobalSet ? { global: true } : {}
|
|
945
|
+
});
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
this.traverse(path);
|
|
949
|
+
}
|
|
950
|
+
});
|
|
951
|
+
return results;
|
|
952
|
+
}
|
|
953
|
+
function extractRawPropertySource(varsArgNode, key) {
|
|
954
|
+
const node = findPropertyNode(varsArgNode, key);
|
|
955
|
+
return node ? recast.print(node).code : void 0;
|
|
956
|
+
}
|
|
957
|
+
function findPropertyNode(varsArgNode, key) {
|
|
958
|
+
if (varsArgNode?.type !== "ObjectExpression") return void 0;
|
|
959
|
+
for (const prop of varsArgNode.properties ?? []) {
|
|
960
|
+
if (!isObjectProperty(prop)) continue;
|
|
961
|
+
if (propKeyName(prop) === key) return prop.value;
|
|
962
|
+
}
|
|
963
|
+
return void 0;
|
|
964
|
+
}
|
|
965
|
+
var PERCENTAGE_KEY_RE = /^(\d+(?:\.\d+)?)%$/;
|
|
966
|
+
function tryResolveStringProp(propValue, scope) {
|
|
967
|
+
const val = resolveNode(propValue, scope);
|
|
968
|
+
return typeof val === "string" ? val : void 0;
|
|
969
|
+
}
|
|
970
|
+
function parseKeyframesNode(node, scope) {
|
|
971
|
+
if (!node) return void 0;
|
|
972
|
+
if (node.type === "ArrayExpression") {
|
|
973
|
+
return parseObjectArrayKeyframes(node, scope);
|
|
974
|
+
}
|
|
975
|
+
if (node.type !== "ObjectExpression") return void 0;
|
|
976
|
+
const props = node.properties ?? [];
|
|
977
|
+
let hasPercentageKey = false;
|
|
978
|
+
let hasArrayValue = false;
|
|
979
|
+
for (const prop of props) {
|
|
980
|
+
if (prop.type !== "ObjectProperty" && prop.type !== "Property") continue;
|
|
981
|
+
const key = prop.key?.value ?? prop.key?.name;
|
|
982
|
+
if (typeof key === "string" && PERCENTAGE_KEY_RE.test(key)) {
|
|
983
|
+
hasPercentageKey = true;
|
|
984
|
+
break;
|
|
985
|
+
}
|
|
986
|
+
if (prop.value?.type === "ArrayExpression") {
|
|
987
|
+
hasArrayValue = true;
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
if (hasPercentageKey) return parsePercentageKeyframes(node, scope);
|
|
991
|
+
if (hasArrayValue) return parseSimpleArrayKeyframes(node, scope);
|
|
992
|
+
return void 0;
|
|
993
|
+
}
|
|
994
|
+
function parsePercentageKeyframes(node, scope) {
|
|
995
|
+
const keyframes = [];
|
|
996
|
+
let ease;
|
|
997
|
+
let easeEach;
|
|
998
|
+
for (const prop of node.properties ?? []) {
|
|
999
|
+
if (prop.type !== "ObjectProperty" && prop.type !== "Property") continue;
|
|
1000
|
+
const key = prop.key?.value ?? prop.key?.name;
|
|
1001
|
+
if (typeof key !== "string") continue;
|
|
1002
|
+
const pctMatch = PERCENTAGE_KEY_RE.exec(key);
|
|
1003
|
+
if (pctMatch) {
|
|
1004
|
+
const percentage = Number.parseFloat(pctMatch[1]);
|
|
1005
|
+
const record = objectExpressionToRecord(prop.value, scope);
|
|
1006
|
+
const properties = {};
|
|
1007
|
+
let kfEase;
|
|
1008
|
+
for (const [k, v] of Object.entries(record)) {
|
|
1009
|
+
if (k === "ease" && typeof v === "string") {
|
|
1010
|
+
kfEase = v;
|
|
1011
|
+
} else if (k === "duration") {
|
|
1012
|
+
continue;
|
|
1013
|
+
} else if (typeof v === "number" || typeof v === "string") {
|
|
1014
|
+
properties[k] = v;
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
keyframes.push({ percentage, properties, ...kfEase ? { ease: kfEase } : {} });
|
|
1018
|
+
} else if (key === "ease") {
|
|
1019
|
+
ease = tryResolveStringProp(prop.value, scope) ?? ease;
|
|
1020
|
+
} else if (key === "easeEach") {
|
|
1021
|
+
easeEach = tryResolveStringProp(prop.value, scope) ?? easeEach;
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
keyframes.sort((a, b) => a.percentage - b.percentage);
|
|
1025
|
+
return {
|
|
1026
|
+
format: "percentage",
|
|
1027
|
+
keyframes,
|
|
1028
|
+
...ease ? { ease } : {},
|
|
1029
|
+
...easeEach ? { easeEach } : {}
|
|
1030
|
+
};
|
|
1031
|
+
}
|
|
1032
|
+
function computeKeyframesTotalDuration(varsNode, scope) {
|
|
1033
|
+
const kfNode = (varsNode.properties ?? []).find(
|
|
1034
|
+
(p) => (p.key?.name ?? p.key?.value) === "keyframes"
|
|
1035
|
+
)?.value;
|
|
1036
|
+
if (!kfNode || kfNode.type !== "ArrayExpression") return void 0;
|
|
1037
|
+
const durations = [];
|
|
1038
|
+
for (const el of kfNode.elements ?? []) {
|
|
1039
|
+
if (!el || el.type !== "ObjectExpression") continue;
|
|
1040
|
+
const r = objectExpressionToRecord(el, scope);
|
|
1041
|
+
durations.push(r.duration);
|
|
1042
|
+
}
|
|
1043
|
+
return getObjectArrayKeyframeTiming(durations)?.totalDuration;
|
|
1044
|
+
}
|
|
1045
|
+
function parseObjectArrayKeyframes(node, scope) {
|
|
1046
|
+
const elements = node.elements ?? [];
|
|
1047
|
+
const raw = [];
|
|
1048
|
+
for (const el of elements) {
|
|
1049
|
+
if (!el || el.type !== "ObjectExpression" && el.type !== "ObjectProperty") {
|
|
1050
|
+
if (el?.type !== "ObjectExpression") continue;
|
|
1051
|
+
}
|
|
1052
|
+
const record = objectExpressionToRecord(el, scope);
|
|
1053
|
+
const properties = {};
|
|
1054
|
+
let duration;
|
|
1055
|
+
let ease;
|
|
1056
|
+
for (const [k, v] of Object.entries(record)) {
|
|
1057
|
+
if (k === "duration") {
|
|
1058
|
+
duration = v;
|
|
1059
|
+
} else if (k === "ease" && typeof v === "string") {
|
|
1060
|
+
ease = v;
|
|
1061
|
+
} else if (typeof v === "number" || typeof v === "string") {
|
|
1062
|
+
properties[k] = v;
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
raw.push({ properties, duration, ease });
|
|
1066
|
+
}
|
|
1067
|
+
const timing = getObjectArrayKeyframeTiming(raw.map((entry) => entry.duration));
|
|
1068
|
+
if (!timing) return void 0;
|
|
1069
|
+
const { percentages } = timing;
|
|
1070
|
+
const keyframes = raw.map(
|
|
1071
|
+
(entry, index) => ({
|
|
1072
|
+
percentage: percentages[index],
|
|
1073
|
+
properties: entry.properties,
|
|
1074
|
+
...entry.ease ? { ease: entry.ease } : {}
|
|
1075
|
+
})
|
|
1076
|
+
);
|
|
1077
|
+
return { format: "object-array", keyframes };
|
|
1078
|
+
}
|
|
1079
|
+
function parseSimpleArrayKeyframes(node, scope) {
|
|
1080
|
+
const arrayProps = /* @__PURE__ */ new Map();
|
|
1081
|
+
let ease;
|
|
1082
|
+
let easeEach;
|
|
1083
|
+
for (const prop of node.properties ?? []) {
|
|
1084
|
+
if (prop.type !== "ObjectProperty" && prop.type !== "Property") continue;
|
|
1085
|
+
const key = prop.key?.name ?? prop.key?.value;
|
|
1086
|
+
if (typeof key !== "string") continue;
|
|
1087
|
+
if (prop.value?.type === "ArrayExpression") {
|
|
1088
|
+
const values = [];
|
|
1089
|
+
for (const el of prop.value.elements ?? []) {
|
|
1090
|
+
const val = resolveNode(el, scope);
|
|
1091
|
+
if (typeof val === "number" || typeof val === "string") {
|
|
1092
|
+
values.push(val);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
if (values.length > 0) arrayProps.set(key, values);
|
|
1096
|
+
} else if (key === "ease") {
|
|
1097
|
+
ease = tryResolveStringProp(prop.value, scope) ?? ease;
|
|
1098
|
+
} else if (key === "easeEach") {
|
|
1099
|
+
easeEach = tryResolveStringProp(prop.value, scope) ?? easeEach;
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
const maxLen = Math.max(...[...arrayProps.values()].map((a) => a.length), 0);
|
|
1103
|
+
const keyframes = [];
|
|
1104
|
+
for (let i = 0; i < maxLen; i++) {
|
|
1105
|
+
const percentage = maxLen > 1 ? Math.round(i / (maxLen - 1) * 100) : 0;
|
|
1106
|
+
const properties = {};
|
|
1107
|
+
for (const [key, values] of arrayProps) {
|
|
1108
|
+
if (i < values.length) properties[key] = values[i];
|
|
1109
|
+
}
|
|
1110
|
+
keyframes.push({ percentage, properties });
|
|
1111
|
+
}
|
|
1112
|
+
return {
|
|
1113
|
+
format: "simple-array",
|
|
1114
|
+
keyframes,
|
|
1115
|
+
...ease ? { ease } : {},
|
|
1116
|
+
...easeEach ? { easeEach } : {}
|
|
1117
|
+
};
|
|
1118
|
+
}
|
|
1119
|
+
function parseMotionPathNode(node, scope) {
|
|
1120
|
+
if (!node) return void 0;
|
|
1121
|
+
let pathNode;
|
|
1122
|
+
let autoRotate = false;
|
|
1123
|
+
let curviness = 1;
|
|
1124
|
+
let isCubic = false;
|
|
1125
|
+
if (node.type === "ObjectExpression") {
|
|
1126
|
+
for (const prop of node.properties ?? []) {
|
|
1127
|
+
if (!isObjectProperty(prop)) continue;
|
|
1128
|
+
const key = propKeyName(prop);
|
|
1129
|
+
if (key === "path") pathNode = prop.value;
|
|
1130
|
+
else if (key === "autoRotate") {
|
|
1131
|
+
const val = resolveNode(prop.value, scope);
|
|
1132
|
+
autoRotate = typeof val === "number" ? val : val === true;
|
|
1133
|
+
} else if (key === "curviness") {
|
|
1134
|
+
const val = resolveNode(prop.value, scope);
|
|
1135
|
+
if (typeof val === "number") curviness = val;
|
|
1136
|
+
} else if (key === "type") {
|
|
1137
|
+
const val = resolveNode(prop.value, scope);
|
|
1138
|
+
if (val === "cubic") isCubic = true;
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
} else if (node.type === "ArrayExpression") {
|
|
1142
|
+
pathNode = node;
|
|
1143
|
+
}
|
|
1144
|
+
if (!pathNode || pathNode.type !== "ArrayExpression") return void 0;
|
|
1145
|
+
const elements = pathNode.elements ?? [];
|
|
1146
|
+
const coords = [];
|
|
1147
|
+
for (const elem of elements) {
|
|
1148
|
+
if (!elem || elem.type !== "ObjectExpression") continue;
|
|
1149
|
+
const rec = objectExpressionToRecord(elem, scope);
|
|
1150
|
+
const x = typeof rec.x === "number" ? rec.x : void 0;
|
|
1151
|
+
const y = typeof rec.y === "number" ? rec.y : void 0;
|
|
1152
|
+
if (x !== void 0 && y !== void 0) coords.push({ x, y });
|
|
1153
|
+
}
|
|
1154
|
+
if (coords.length < 2) return void 0;
|
|
1155
|
+
let waypoints;
|
|
1156
|
+
const segments = [];
|
|
1157
|
+
if (isCubic && coords.length >= 4) {
|
|
1158
|
+
waypoints = [];
|
|
1159
|
+
waypoints.push(coords[0]);
|
|
1160
|
+
for (let i = 1; i + 2 < coords.length; i += 3) {
|
|
1161
|
+
const cp1 = coords[i];
|
|
1162
|
+
const cp2 = coords[i + 1];
|
|
1163
|
+
const anchor = coords[i + 2];
|
|
1164
|
+
waypoints.push(anchor);
|
|
1165
|
+
segments.push({ curviness, cp1, cp2 });
|
|
1166
|
+
}
|
|
1167
|
+
} else {
|
|
1168
|
+
waypoints = coords;
|
|
1169
|
+
for (let i = 0; i < waypoints.length - 1; i++) {
|
|
1170
|
+
segments.push({ curviness });
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
return {
|
|
1174
|
+
arcPath: { enabled: true, autoRotate, segments },
|
|
1175
|
+
waypoints
|
|
1176
|
+
};
|
|
1177
|
+
}
|
|
1178
|
+
function tweenCallToAnimation(call, scope) {
|
|
1179
|
+
const vars = objectExpressionToRecord(call.varsArg, scope);
|
|
1180
|
+
const properties = {};
|
|
1181
|
+
const extras = {};
|
|
1182
|
+
let keyframesData;
|
|
1183
|
+
let hasUnresolvedKeyframes = false;
|
|
1184
|
+
let motionPathResult;
|
|
1185
|
+
for (const [key, val] of Object.entries(vars)) {
|
|
1186
|
+
if (BUILTIN_VAR_KEYS.has(key)) continue;
|
|
1187
|
+
if (DROPPED_VAR_KEYS.has(key)) continue;
|
|
1188
|
+
if (key === "keyframes") {
|
|
1189
|
+
const kfNode = findPropertyNode(call.varsArg, "keyframes");
|
|
1190
|
+
keyframesData = parseKeyframesNode(kfNode, scope);
|
|
1191
|
+
if (!keyframesData && kfNode) hasUnresolvedKeyframes = true;
|
|
1192
|
+
continue;
|
|
1193
|
+
}
|
|
1194
|
+
if (key === "motionPath") {
|
|
1195
|
+
const mpNode = findPropertyNode(call.varsArg, "motionPath");
|
|
1196
|
+
motionPathResult = parseMotionPathNode(mpNode, scope);
|
|
1197
|
+
continue;
|
|
1198
|
+
}
|
|
1199
|
+
if (key === "easeEach") {
|
|
1200
|
+
continue;
|
|
1201
|
+
}
|
|
1202
|
+
if (EXTRAS_KEYS.has(key)) {
|
|
1203
|
+
const rawSource = extractRawPropertySource(call.varsArg, key);
|
|
1204
|
+
if (rawSource !== void 0) {
|
|
1205
|
+
extras[key] = `__raw:${rawSource}`;
|
|
1206
|
+
} else if (val !== void 0) {
|
|
1207
|
+
extras[key] = val;
|
|
1208
|
+
}
|
|
1209
|
+
continue;
|
|
1210
|
+
}
|
|
1211
|
+
if (typeof val === "number" || typeof val === "string") {
|
|
1212
|
+
properties[key] = val;
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
if (keyframesData && typeof vars.easeEach === "string") {
|
|
1216
|
+
keyframesData.easeEach = vars.easeEach;
|
|
1217
|
+
}
|
|
1218
|
+
if (motionPathResult) {
|
|
1219
|
+
const { waypoints } = motionPathResult;
|
|
1220
|
+
if (!keyframesData) {
|
|
1221
|
+
const kf = waypoints.map((wp, i) => ({
|
|
1222
|
+
percentage: waypoints.length > 1 ? Math.round(i / (waypoints.length - 1) * 100) : 0,
|
|
1223
|
+
properties: { x: wp.x, y: wp.y }
|
|
1224
|
+
}));
|
|
1225
|
+
keyframesData = { format: "percentage", keyframes: kf, fromMotionPath: true };
|
|
1226
|
+
} else {
|
|
1227
|
+
const kfs = keyframesData.keyframes;
|
|
1228
|
+
if (kfs.length === waypoints.length) {
|
|
1229
|
+
for (let i = 0; i < kfs.length; i++) {
|
|
1230
|
+
kfs[i].properties.x = waypoints[i].x;
|
|
1231
|
+
kfs[i].properties.y = waypoints[i].y;
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
let fromProperties;
|
|
1237
|
+
if (call.method === "fromTo" && call.fromArg) {
|
|
1238
|
+
fromProperties = {};
|
|
1239
|
+
const fromVars = objectExpressionToRecord(call.fromArg, scope);
|
|
1240
|
+
for (const [key, val] of Object.entries(fromVars)) {
|
|
1241
|
+
if (typeof val === "number" || typeof val === "string") {
|
|
1242
|
+
fromProperties[key] = val;
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
const hasPositionArg = !!call.positionArg;
|
|
1247
|
+
const posVal = call.positionArg ? extractLiteralValue(call.positionArg, scope) : 0;
|
|
1248
|
+
const position = typeof posVal === "number" ? posVal : typeof posVal === "string" ? posVal : 0;
|
|
1249
|
+
let duration = typeof vars.duration === "number" ? vars.duration : void 0;
|
|
1250
|
+
const ease = typeof vars.ease === "string" ? vars.ease : void 0;
|
|
1251
|
+
if (duration === void 0 && keyframesData) {
|
|
1252
|
+
duration = computeKeyframesTotalDuration(call.varsArg, scope);
|
|
1253
|
+
}
|
|
1254
|
+
const anim = {
|
|
1255
|
+
targetSelector: call.selector,
|
|
1256
|
+
method: call.method,
|
|
1257
|
+
position,
|
|
1258
|
+
properties,
|
|
1259
|
+
fromProperties,
|
|
1260
|
+
duration,
|
|
1261
|
+
ease
|
|
1262
|
+
};
|
|
1263
|
+
if (!hasPositionArg) anim.implicitPosition = true;
|
|
1264
|
+
let group = classifyTweenPropertyGroup(properties);
|
|
1265
|
+
if (!group && keyframesData) {
|
|
1266
|
+
const kfProps = {};
|
|
1267
|
+
for (const kf of keyframesData.keyframes) {
|
|
1268
|
+
for (const k of Object.keys(kf.properties)) kfProps[k] = true;
|
|
1269
|
+
}
|
|
1270
|
+
group = classifyTweenPropertyGroup(kfProps);
|
|
1271
|
+
}
|
|
1272
|
+
if (group) anim.propertyGroup = group;
|
|
1273
|
+
if (call.global) anim.global = true;
|
|
1274
|
+
if (Object.keys(extras).length > 0) anim.extras = extras;
|
|
1275
|
+
if (keyframesData) anim.keyframes = keyframesData;
|
|
1276
|
+
if (motionPathResult) anim.arcPath = motionPathResult.arcPath;
|
|
1277
|
+
if (hasUnresolvedKeyframes) anim.hasUnresolvedKeyframes = true;
|
|
1278
|
+
if (call.selector === "__unresolved__") anim.hasUnresolvedSelector = true;
|
|
1279
|
+
if (call.selectorPartial) anim.hasPartialSelector = true;
|
|
1280
|
+
return anim;
|
|
1281
|
+
}
|
|
1282
|
+
function resolvePositionString(pos, cursor, prevStart) {
|
|
1283
|
+
const trimmed = pos.trim();
|
|
1284
|
+
if (trimmed === "") return cursor;
|
|
1285
|
+
if (trimmed.startsWith("+=")) {
|
|
1286
|
+
const n2 = Number.parseFloat(trimmed.slice(2));
|
|
1287
|
+
return Number.isFinite(n2) ? cursor + n2 : null;
|
|
1288
|
+
}
|
|
1289
|
+
if (trimmed.startsWith("-=")) {
|
|
1290
|
+
const n2 = Number.parseFloat(trimmed.slice(2));
|
|
1291
|
+
return Number.isFinite(n2) ? cursor - n2 : null;
|
|
1292
|
+
}
|
|
1293
|
+
if (trimmed === "<") return prevStart;
|
|
1294
|
+
if (trimmed === ">") return cursor;
|
|
1295
|
+
if (trimmed.startsWith("<")) {
|
|
1296
|
+
const n2 = Number.parseFloat(trimmed.slice(1));
|
|
1297
|
+
return Number.isFinite(n2) ? prevStart + n2 : null;
|
|
1298
|
+
}
|
|
1299
|
+
if (trimmed.startsWith(">")) {
|
|
1300
|
+
const n2 = Number.parseFloat(trimmed.slice(1));
|
|
1301
|
+
return Number.isFinite(n2) ? cursor + n2 : null;
|
|
1302
|
+
}
|
|
1303
|
+
const n = Number.parseFloat(trimmed);
|
|
1304
|
+
return Number.isFinite(n) ? n : null;
|
|
1305
|
+
}
|
|
1306
|
+
function applyTimelineDefaults(anims, defaults) {
|
|
1307
|
+
if (!defaults) return;
|
|
1308
|
+
for (const anim of anims) {
|
|
1309
|
+
if (anim.method === "set") continue;
|
|
1310
|
+
if (anim.duration === void 0 && defaults.duration !== void 0) {
|
|
1311
|
+
anim.duration = defaults.duration;
|
|
1312
|
+
}
|
|
1313
|
+
if (anim.ease === void 0 && defaults.ease !== void 0 && (!anim.keyframes || anim.keyframes.fromMotionPath)) {
|
|
1314
|
+
anim.ease = defaults.ease;
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
function resolveTimelinePositions(anims) {
|
|
1319
|
+
let cursor = 0;
|
|
1320
|
+
let prevStart = 0;
|
|
1321
|
+
for (const anim of anims) {
|
|
1322
|
+
if (anim.method === "set" && anim.global) {
|
|
1323
|
+
anim.resolvedStart = 0;
|
|
1324
|
+
continue;
|
|
1325
|
+
}
|
|
1326
|
+
const duration = anim.method === "set" ? 0 : anim.duration ?? GSAP_DEFAULT_DURATION;
|
|
1327
|
+
let start;
|
|
1328
|
+
if (anim.implicitPosition) {
|
|
1329
|
+
start = cursor;
|
|
1330
|
+
} else if (typeof anim.position === "number") {
|
|
1331
|
+
start = anim.position;
|
|
1332
|
+
} else if (typeof anim.position === "string") {
|
|
1333
|
+
start = resolvePositionString(anim.position, cursor, prevStart);
|
|
1334
|
+
} else {
|
|
1335
|
+
start = cursor;
|
|
1336
|
+
}
|
|
1337
|
+
if (start != null) {
|
|
1338
|
+
anim.resolvedStart = Math.max(0, start);
|
|
1339
|
+
prevStart = anim.resolvedStart;
|
|
1340
|
+
cursor = Math.max(cursor, anim.resolvedStart + duration);
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
function sortBySourcePosition(calls) {
|
|
1345
|
+
calls.sort((a, b) => {
|
|
1346
|
+
const aLoc = a.node.callee?.property?.loc?.start;
|
|
1347
|
+
const bLoc = b.node.callee?.property?.loc?.start;
|
|
1348
|
+
if (!aLoc || !bLoc) return 0;
|
|
1349
|
+
return aLoc.line - bLoc.line || aLoc.column - bLoc.column;
|
|
1350
|
+
});
|
|
1351
|
+
}
|
|
1352
|
+
function assignStableIds(anims) {
|
|
1353
|
+
const counts = /* @__PURE__ */ new Map();
|
|
1354
|
+
return anims.map((anim) => {
|
|
1355
|
+
const posKey = typeof anim.position === "number" ? String(Math.round(anim.position * 1e3)) : String(anim.position);
|
|
1356
|
+
const groupSuffix = anim.propertyGroup ? `-${anim.propertyGroup}` : "";
|
|
1357
|
+
const base = `${anim.targetSelector}-${anim.method}-${posKey}${groupSuffix}`;
|
|
1358
|
+
const count = (counts.get(base) ?? 0) + 1;
|
|
1359
|
+
counts.set(base, count);
|
|
1360
|
+
const id = count === 1 ? base : `${base}-${count}`;
|
|
1361
|
+
return { ...anim, id };
|
|
1362
|
+
});
|
|
1363
|
+
}
|
|
1364
|
+
function parseGsapAst(script) {
|
|
1365
|
+
const ast = parseScript(script);
|
|
1366
|
+
const scope = collectScopeBindings(ast);
|
|
1367
|
+
const targetHelpers = collectTargetHelpers(ast);
|
|
1368
|
+
const targetBindings = collectTargetBindings(ast, scope, targetHelpers);
|
|
1369
|
+
const detection = findTimelineVar(ast, scope);
|
|
1370
|
+
const ref = detection.ref ?? { kind: "identifier", name: "tl" };
|
|
1371
|
+
const timelineVar = timelineRootSource(ref);
|
|
1372
|
+
const calls = findAllTweenCalls(ast, ref, scope, targetBindings, targetHelpers);
|
|
1373
|
+
sortBySourcePosition(calls);
|
|
1374
|
+
const rawAnims = calls.map((call) => tweenCallToAnimation(call, scope));
|
|
1375
|
+
applyTimelineDefaults(rawAnims, detection.defaults);
|
|
1376
|
+
resolveTimelinePositions(rawAnims);
|
|
1377
|
+
const animations = assignStableIds(rawAnims);
|
|
1378
|
+
const located = animations.map((animation, i) => ({
|
|
1379
|
+
id: animation.id,
|
|
1380
|
+
call: calls[i],
|
|
1381
|
+
animation
|
|
1382
|
+
}));
|
|
1383
|
+
return { ast, scope, timelineVar, detection, located };
|
|
1384
|
+
}
|
|
1385
|
+
function parseGsapScript(script) {
|
|
1386
|
+
try {
|
|
1387
|
+
const { detection, timelineVar, located } = parseGsapAst(script);
|
|
1388
|
+
const ref = detection.ref ?? { kind: "identifier", name: "tl" };
|
|
1389
|
+
const animations = located.map((l) => l.animation);
|
|
1390
|
+
const declPattern = ref.kind === "identifier" ? `(?:const|let|var)\\s+${timelineVar}\\s*=\\s*gsap\\.timeline\\s*\\([^)]*\\)\\s*;?` : `${escapeRegExp(timelineVar)}\\s*=\\s*gsap\\.timeline\\s*\\([^)]*\\)\\s*;?`;
|
|
1391
|
+
const timelineMatch = script.match(new RegExp(`^[\\s\\S]*?${declPattern}`));
|
|
1392
|
+
const fallbackPreamble = ref.kind === "identifier" ? `const ${timelineVar} = gsap.timeline({ paused: true });` : `${timelineVar} = gsap.timeline({ paused: true });`;
|
|
1393
|
+
const preamble = timelineMatch?.[0] ?? fallbackPreamble;
|
|
1394
|
+
const lastCallIdx = script.lastIndexOf(`${timelineVar}.`);
|
|
1395
|
+
let postamble = "";
|
|
1396
|
+
if (lastCallIdx !== -1) {
|
|
1397
|
+
const afterLast = script.slice(lastCallIdx);
|
|
1398
|
+
const endOfCall = afterLast.indexOf(";");
|
|
1399
|
+
if (endOfCall !== -1) {
|
|
1400
|
+
postamble = script.slice(lastCallIdx + endOfCall + 1).trim();
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
const result = { animations, timelineVar, preamble, postamble };
|
|
1404
|
+
if (detection.timelineCount > 1) result.multipleTimelines = true;
|
|
1405
|
+
if (detection.timelineCount > 0 && detection.ref === null)
|
|
1406
|
+
result.unsupportedTimelinePattern = true;
|
|
1407
|
+
return result;
|
|
1408
|
+
} catch {
|
|
1409
|
+
return { animations: [], timelineVar: "tl", preamble: "", postamble: "" };
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
function parseExpr(code) {
|
|
1413
|
+
return parseScript(`__hf__ = ${code};`).program.body[0].expression.right;
|
|
1414
|
+
}
|
|
1415
|
+
function propKeyName(prop) {
|
|
1416
|
+
return prop?.key?.name ?? prop?.key?.value;
|
|
1417
|
+
}
|
|
1418
|
+
function isObjectProperty(prop) {
|
|
1419
|
+
return prop?.type === "ObjectProperty" || prop?.type === "Property";
|
|
1420
|
+
}
|
|
1421
|
+
function isEditablePropertyKey(key) {
|
|
1422
|
+
return !isTweenConfigKey(key);
|
|
1423
|
+
}
|
|
1424
|
+
function makeObjectProperty(key, value) {
|
|
1425
|
+
const obj = parseExpr(`{ ${safeJsKey(key)}: ${serializeValue(value)} }`);
|
|
1426
|
+
return obj.properties[0];
|
|
1427
|
+
}
|
|
1428
|
+
function setVarsKey(varsArg, key, value) {
|
|
1429
|
+
if (varsArg?.type !== "ObjectExpression") return;
|
|
1430
|
+
const existing = varsArg.properties.find(
|
|
1431
|
+
(p) => isObjectProperty(p) && propKeyName(p) === key
|
|
1432
|
+
);
|
|
1433
|
+
if (existing) {
|
|
1434
|
+
existing.value = parseExpr(serializeValue(value));
|
|
1435
|
+
} else {
|
|
1436
|
+
varsArg.properties.push(makeObjectProperty(key, value));
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
function filterEditableKeys(varsArg, shouldKeep) {
|
|
1440
|
+
if (varsArg?.type !== "ObjectExpression") return;
|
|
1441
|
+
varsArg.properties = varsArg.properties.filter((p) => {
|
|
1442
|
+
if (!isObjectProperty(p)) return true;
|
|
1443
|
+
const key = propKeyName(p);
|
|
1444
|
+
if (typeof key !== "string") return true;
|
|
1445
|
+
if (!isEditablePropertyKey(key)) return true;
|
|
1446
|
+
return shouldKeep(key);
|
|
1447
|
+
});
|
|
1448
|
+
}
|
|
1449
|
+
function reconcileEditableProperties(varsArg, newProps) {
|
|
1450
|
+
filterEditableKeys(varsArg, (key) => key in newProps);
|
|
1451
|
+
for (const [key, value] of Object.entries(newProps)) {
|
|
1452
|
+
setVarsKey(varsArg, key, value);
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
function applyEaseUpdate(varsArg, ease) {
|
|
1456
|
+
const kfNode = findKeyframesObjectNode(varsArg);
|
|
1457
|
+
if (kfNode) {
|
|
1458
|
+
setVarsKey(kfNode, "easeEach", ease);
|
|
1459
|
+
removeVarsKey(varsArg, "ease");
|
|
1460
|
+
} else {
|
|
1461
|
+
setVarsKey(varsArg, "ease", ease);
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
function stripKeyframeEases(varsArg) {
|
|
1465
|
+
const kfNode = findKeyframesObjectNode(varsArg);
|
|
1466
|
+
const props = kfNode?.properties;
|
|
1467
|
+
if (!Array.isArray(props)) return;
|
|
1468
|
+
for (const entry of props) {
|
|
1469
|
+
if (isObjectProperty(entry)) removeVarsKey(entry.value, "ease");
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
function applyUpdatesToCall(call, updates) {
|
|
1473
|
+
if (updates.properties) reconcileEditableProperties(call.varsArg, updates.properties);
|
|
1474
|
+
if (updates.fromProperties && call.method === "fromTo" && call.fromArg) {
|
|
1475
|
+
reconcileEditableProperties(call.fromArg, updates.fromProperties);
|
|
1476
|
+
}
|
|
1477
|
+
if (updates.duration !== void 0) setVarsKey(call.varsArg, "duration", updates.duration);
|
|
1478
|
+
if (updates.easeEach !== void 0) applyEaseUpdate(call.varsArg, updates.easeEach);
|
|
1479
|
+
else if (updates.ease !== void 0) applyEaseUpdate(call.varsArg, updates.ease);
|
|
1480
|
+
if (updates.resetKeyframeEases) stripKeyframeEases(call.varsArg);
|
|
1481
|
+
if (updates.position !== void 0) {
|
|
1482
|
+
const posIdx = call.method === "fromTo" ? 3 : 2;
|
|
1483
|
+
call.node.arguments[posIdx] = parseExpr(serializeValue(updates.position));
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
function findStatementPath(path) {
|
|
1487
|
+
let p = path;
|
|
1488
|
+
while (p) {
|
|
1489
|
+
if (p.node?.type === "ExpressionStatement") return p;
|
|
1490
|
+
p = p.parentPath;
|
|
1491
|
+
}
|
|
1492
|
+
return null;
|
|
1493
|
+
}
|
|
1494
|
+
function insertAfterAnchor(parsed, newStatement) {
|
|
1495
|
+
const lastCall = parsed.located[parsed.located.length - 1]?.call;
|
|
1496
|
+
const lastPath = lastCall ? findStatementPath(lastCall.path) : null;
|
|
1497
|
+
const timeline = findTimelineDeclarationPath(parsed.ast, parsed.timelineVar);
|
|
1498
|
+
const beforeTimeline = !!timeline && !!lastPath && lastPath.node.start < timeline.node.start;
|
|
1499
|
+
const anchorPath = !lastCall || beforeTimeline ? timeline : lastPath;
|
|
1500
|
+
if (anchorPath) {
|
|
1501
|
+
anchorPath.insertAfter(newStatement);
|
|
1502
|
+
} else {
|
|
1503
|
+
parsed.ast.program.body.push(newStatement);
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
function buildTweenStatementCode(timelineVar, anim) {
|
|
1507
|
+
const selector = JSON.stringify(anim.targetSelector);
|
|
1508
|
+
const props = { ...anim.properties };
|
|
1509
|
+
if (anim.method !== "set" && anim.duration !== void 0) props.duration = anim.duration;
|
|
1510
|
+
if (anim.ease) props.ease = anim.ease;
|
|
1511
|
+
const entries = Object.entries(props).map(([k, v]) => `${safeJsKey(k)}: ${serializeValue(v)}`);
|
|
1512
|
+
const emitted = new Set(Object.keys(props));
|
|
1513
|
+
if (anim.method === "set" && !anim.global && !emitted.has("immediateRender") && !(anim.extras && "immediateRender" in anim.extras)) {
|
|
1514
|
+
entries.push("immediateRender: true");
|
|
1515
|
+
emitted.add("immediateRender");
|
|
1516
|
+
}
|
|
1517
|
+
if (anim.extras) {
|
|
1518
|
+
for (const [k, v] of Object.entries(anim.extras)) {
|
|
1519
|
+
if (emitted.has(k)) continue;
|
|
1520
|
+
emitted.add(k);
|
|
1521
|
+
entries.push(`${safeJsKey(k)}: ${serializeValue(v)}`);
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
const objCode = `{ ${entries.join(", ")} }`;
|
|
1525
|
+
const posCode = serializeValue(
|
|
1526
|
+
typeof anim.position === "number" ? anim.position : anim.position ?? 0
|
|
1527
|
+
);
|
|
1528
|
+
if (anim.method === "fromTo") {
|
|
1529
|
+
const fromEntries = Object.entries(anim.fromProperties ?? {}).map(
|
|
1530
|
+
([k, v]) => `${safeJsKey(k)}: ${serializeValue(v)}`
|
|
1531
|
+
);
|
|
1532
|
+
const fromCode = `{ ${fromEntries.join(", ")} }`;
|
|
1533
|
+
return `${timelineVar}.fromTo(${selector}, ${fromCode}, ${objCode}, ${posCode});`;
|
|
1534
|
+
}
|
|
1535
|
+
if (anim.method === "set" && anim.global) {
|
|
1536
|
+
return `gsap.set(${selector}, ${objCode});`;
|
|
1537
|
+
}
|
|
1538
|
+
return `${timelineVar}.${anim.method}(${selector}, ${objCode}, ${posCode});`;
|
|
1539
|
+
}
|
|
1540
|
+
function updateAnimationInScript(script, animationId, updates) {
|
|
1541
|
+
let parsed;
|
|
1542
|
+
try {
|
|
1543
|
+
parsed = parseGsapAst(script);
|
|
1544
|
+
} catch (e) {
|
|
1545
|
+
console.warn("[gsap-parser] updateAnimationInScript parse failed:", e);
|
|
1546
|
+
return script;
|
|
1547
|
+
}
|
|
1548
|
+
const target = parsed.located.find((l) => l.id === animationId);
|
|
1549
|
+
if (!target || updates.properties && target.animation.hasUnresolvedKeyframes) return script;
|
|
1550
|
+
applyUpdatesToCall(target.call, updates);
|
|
1551
|
+
return recast.print(parsed.ast).code;
|
|
1552
|
+
}
|
|
1553
|
+
function shiftPositionsInScript(script, targetSelector, delta, root) {
|
|
1554
|
+
const carries = clipTweenMatcher(targetSelector, root);
|
|
1555
|
+
let parsed;
|
|
1556
|
+
try {
|
|
1557
|
+
parsed = parseGsapAst(script);
|
|
1558
|
+
} catch (e) {
|
|
1559
|
+
console.warn("[gsap-parser] shiftPositionsInScript parse failed:", e);
|
|
1560
|
+
return script;
|
|
1561
|
+
}
|
|
1562
|
+
let changed = false;
|
|
1563
|
+
for (const entry of parsed.located) {
|
|
1564
|
+
if (!carries(entry.animation) || !hasExplicitTime(entry.animation)) continue;
|
|
1565
|
+
const newPos = Math.max(0, Math.round((entry.animation.position + delta) * 1e3) / 1e3);
|
|
1566
|
+
applyUpdatesToCall(entry.call, { position: newPos });
|
|
1567
|
+
changed = true;
|
|
1568
|
+
}
|
|
1569
|
+
return changed ? recast.print(parsed.ast).code : script;
|
|
1570
|
+
}
|
|
1571
|
+
function scalePositionsInScript(script, targetSelector, oldStart, oldDuration, newStart, newDuration, root) {
|
|
1572
|
+
if (oldDuration <= 0 || newDuration <= 0) return script;
|
|
1573
|
+
const ratio = newDuration / oldDuration;
|
|
1574
|
+
const carries = clipTweenMatcher(targetSelector, root);
|
|
1575
|
+
let parsed;
|
|
1576
|
+
try {
|
|
1577
|
+
parsed = parseGsapAst(script);
|
|
1578
|
+
} catch (e) {
|
|
1579
|
+
console.warn("[gsap-parser] scalePositionsInScript parse failed:", e);
|
|
1580
|
+
return script;
|
|
1581
|
+
}
|
|
1582
|
+
let changed = false;
|
|
1583
|
+
for (const entry of parsed.located) {
|
|
1584
|
+
if (!carries(entry.animation) || typeof entry.animation.position !== "number") continue;
|
|
1585
|
+
const updates = {};
|
|
1586
|
+
if (hasExplicitTime(entry.animation)) {
|
|
1587
|
+
updates.position = Math.max(
|
|
1588
|
+
0,
|
|
1589
|
+
Math.round((newStart + (entry.animation.position - oldStart) * ratio) * 1e3) / 1e3
|
|
1590
|
+
);
|
|
1591
|
+
}
|
|
1592
|
+
if (typeof entry.animation.duration === "number" && entry.animation.duration > 0) {
|
|
1593
|
+
updates.duration = Math.max(
|
|
1594
|
+
1e-3,
|
|
1595
|
+
Math.round(entry.animation.duration * ratio * 1e3) / 1e3
|
|
1596
|
+
);
|
|
1597
|
+
}
|
|
1598
|
+
applyUpdatesToCall(entry.call, updates);
|
|
1599
|
+
changed = true;
|
|
1600
|
+
}
|
|
1601
|
+
return changed ? recast.print(parsed.ast).code : script;
|
|
1602
|
+
}
|
|
1603
|
+
function updateAnimationSelector(script, animationId, newSelector) {
|
|
1604
|
+
let parsed;
|
|
1605
|
+
try {
|
|
1606
|
+
parsed = parseGsapAst(script);
|
|
1607
|
+
} catch {
|
|
1608
|
+
return script;
|
|
1609
|
+
}
|
|
1610
|
+
const target = parsed.located.find((l) => l.id === animationId);
|
|
1611
|
+
if (!target) return script;
|
|
1612
|
+
const selectorArg = target.call.path.node.arguments?.[0];
|
|
1613
|
+
if (selectorArg?.type === "StringLiteral") {
|
|
1614
|
+
selectorArg.value = newSelector;
|
|
1615
|
+
} else if (selectorArg?.type === "Identifier") {
|
|
1616
|
+
target.call.path.node.arguments[0] = { type: "StringLiteral", value: newSelector };
|
|
1617
|
+
}
|
|
1618
|
+
return recast.print(parsed.ast).code;
|
|
1619
|
+
}
|
|
1620
|
+
function addAnimationToScript(script, animation) {
|
|
1621
|
+
let parsed;
|
|
1622
|
+
try {
|
|
1623
|
+
parsed = parseGsapAst(script);
|
|
1624
|
+
} catch (e) {
|
|
1625
|
+
console.warn("[gsap-parser] addAnimationToScript parse failed:", e);
|
|
1626
|
+
return { script, id: "" };
|
|
1627
|
+
}
|
|
1628
|
+
if (parsed.located.length === 0 && parsed.detection.ref === null) {
|
|
1629
|
+
return { script, id: "" };
|
|
1630
|
+
}
|
|
1631
|
+
const id = `anim-${Date.now()}`;
|
|
1632
|
+
const statementCode = buildTweenStatementCode(parsed.timelineVar, animation);
|
|
1633
|
+
const newStatement = parseScript(statementCode).program.body[0];
|
|
1634
|
+
if (animation.method === "set" && animation.global) {
|
|
1635
|
+
const timeline = findTimelineDeclarationPath(parsed.ast, parsed.timelineVar);
|
|
1636
|
+
if (timeline) timeline.insertBefore(newStatement);
|
|
1637
|
+
else insertAfterAnchor(parsed, newStatement);
|
|
1638
|
+
} else {
|
|
1639
|
+
insertAfterAnchor(parsed, newStatement);
|
|
1640
|
+
}
|
|
1641
|
+
return { script: recast.print(parsed.ast).code, id };
|
|
1642
|
+
}
|
|
1643
|
+
function addAnimationWithKeyframesToScript(script, targetSelector, position, duration, keyframes, ease, easeEach) {
|
|
1644
|
+
let parsed;
|
|
1645
|
+
try {
|
|
1646
|
+
parsed = parseGsapAst(script);
|
|
1647
|
+
} catch (e) {
|
|
1648
|
+
console.warn("[gsap-parser] addAnimationWithKeyframesToScript parse failed:", e);
|
|
1649
|
+
return { script, id: "" };
|
|
1650
|
+
}
|
|
1651
|
+
if (parsed.located.length === 0 && parsed.detection.ref === null) {
|
|
1652
|
+
return { script, id: "" };
|
|
1653
|
+
}
|
|
1654
|
+
const selector = JSON.stringify(targetSelector);
|
|
1655
|
+
const kfCode = buildKeyframeObjectCode(keyframes, easeEach ? { easeEach } : void 0);
|
|
1656
|
+
const varEntries = [`keyframes: ${kfCode}`, `duration: ${serializeValue(duration)}`];
|
|
1657
|
+
if (ease) varEntries.push(`ease: ${JSON.stringify(ease)}`);
|
|
1658
|
+
const posCode = serializeValue(position);
|
|
1659
|
+
const stmtCode = `${parsed.timelineVar}.to(${selector}, { ${varEntries.join(", ")} }, ${posCode});`;
|
|
1660
|
+
const newStatement = parseScript(stmtCode).program.body[0];
|
|
1661
|
+
insertAfterAnchor(parsed, newStatement);
|
|
1662
|
+
const result = recast.print(parsed.ast).code;
|
|
1663
|
+
const reParsed = parseGsapAst(result);
|
|
1664
|
+
const newId = reParsed.located[reParsed.located.length - 1]?.id ?? "";
|
|
1665
|
+
return { script: result, id: newId };
|
|
1666
|
+
}
|
|
1667
|
+
function findTimelineDeclarationPath(ast, timelineVar) {
|
|
1668
|
+
let found = null;
|
|
1669
|
+
recast.types.visit(ast, {
|
|
1670
|
+
visitVariableDeclaration(path) {
|
|
1671
|
+
if (found) return false;
|
|
1672
|
+
for (const decl of path.node.declarations ?? []) {
|
|
1673
|
+
if (decl.id?.name === timelineVar && isGsapTimelineCall(decl.init)) {
|
|
1674
|
+
found = path;
|
|
1675
|
+
return false;
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
this.traverse(path);
|
|
1679
|
+
}
|
|
1680
|
+
});
|
|
1681
|
+
return found;
|
|
1682
|
+
}
|
|
1683
|
+
function findChainParentCall(stmtNode, targetNode) {
|
|
1684
|
+
let found = null;
|
|
1685
|
+
recast.types.visit(stmtNode, {
|
|
1686
|
+
visitCallExpression(p) {
|
|
1687
|
+
if (found) return false;
|
|
1688
|
+
if (p.node.callee?.type === "MemberExpression" && p.node.callee.object === targetNode) {
|
|
1689
|
+
found = p.node;
|
|
1690
|
+
return false;
|
|
1691
|
+
}
|
|
1692
|
+
this.traverse(p);
|
|
1693
|
+
}
|
|
1694
|
+
});
|
|
1695
|
+
return found;
|
|
1696
|
+
}
|
|
1697
|
+
function removeAnimationFromScript(script, animationId) {
|
|
1698
|
+
let parsed;
|
|
1699
|
+
try {
|
|
1700
|
+
parsed = parseGsapAst(script);
|
|
1701
|
+
} catch (e) {
|
|
1702
|
+
console.warn("[gsap-parser] removeAnimationFromScript parse failed:", e);
|
|
1703
|
+
return script;
|
|
1704
|
+
}
|
|
1705
|
+
let target = parsed.located.find((l) => l.id === animationId);
|
|
1706
|
+
if (!target) {
|
|
1707
|
+
const convertedId = animationId.replace(/-from-|-fromTo-/, "-to-");
|
|
1708
|
+
target = parsed.located.find((l) => l.id === convertedId);
|
|
1709
|
+
}
|
|
1710
|
+
if (!target) return script;
|
|
1711
|
+
removeCallFromAst(target.call);
|
|
1712
|
+
return recast.print(parsed.ast).code;
|
|
1713
|
+
}
|
|
1714
|
+
function removeCallFromAst(call) {
|
|
1715
|
+
const node = call.node;
|
|
1716
|
+
const stmtPath = findStatementPath(call.path);
|
|
1717
|
+
if (!stmtPath) return;
|
|
1718
|
+
const parentCall = findChainParentCall(stmtPath.node, node);
|
|
1719
|
+
if (parentCall) {
|
|
1720
|
+
parentCall.callee.object = node.callee.object;
|
|
1721
|
+
} else if (node.callee?.object?.type === "CallExpression") {
|
|
1722
|
+
stmtPath.node.expression = node.callee.object;
|
|
1723
|
+
} else {
|
|
1724
|
+
stmtPath.prune();
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
function dedupePositionWritesInScript(script, selector, keepId) {
|
|
1728
|
+
let parsed;
|
|
1729
|
+
try {
|
|
1730
|
+
parsed = parseGsapAst(script);
|
|
1731
|
+
} catch {
|
|
1732
|
+
return script;
|
|
1733
|
+
}
|
|
1734
|
+
const posWrites = parsed.located.filter(
|
|
1735
|
+
(l) => l.animation.targetSelector === selector && isXYPositionWrite(l.animation)
|
|
1736
|
+
);
|
|
1737
|
+
if (posWrites.length <= 1) return script;
|
|
1738
|
+
const keeper = posWrites.find((l) => l.id === keepId) ?? posWrites[posWrites.length - 1];
|
|
1739
|
+
for (const l of posWrites) {
|
|
1740
|
+
if (l === keeper) continue;
|
|
1741
|
+
removeCallFromAst(l.call);
|
|
1742
|
+
}
|
|
1743
|
+
return recast.print(parsed.ast).code;
|
|
1744
|
+
}
|
|
1745
|
+
function insertInheritedStateSet(script, selector, position, properties) {
|
|
1746
|
+
let parsed;
|
|
1747
|
+
try {
|
|
1748
|
+
parsed = parseGsapAst(script);
|
|
1749
|
+
} catch {
|
|
1750
|
+
return script;
|
|
1751
|
+
}
|
|
1752
|
+
const tlVar = parsed.timelineVar;
|
|
1753
|
+
const props = Object.entries(properties).map(([k, v]) => `${k}: ${typeof v === "string" ? JSON.stringify(v) : v}`).join(", ");
|
|
1754
|
+
const code = `${tlVar}.set(${JSON.stringify(selector)}, { ${props} }, ${position});`;
|
|
1755
|
+
const newStatement = parseScript(code).program.body[0];
|
|
1756
|
+
const anchor = findTimelineDeclarationPath(parsed.ast, tlVar);
|
|
1757
|
+
if (anchor) {
|
|
1758
|
+
anchor.insertAfter(newStatement);
|
|
1759
|
+
} else if (parsed.located.length > 0) {
|
|
1760
|
+
const firstTween = parsed.located[0].call;
|
|
1761
|
+
const stmtPath = findStatementPath(firstTween.path);
|
|
1762
|
+
if (stmtPath) stmtPath.insertBefore(newStatement);
|
|
1763
|
+
else parsed.ast.program.body.unshift(newStatement);
|
|
1764
|
+
} else {
|
|
1765
|
+
parsed.ast.program.body.push(newStatement);
|
|
1766
|
+
}
|
|
1767
|
+
return recast.print(parsed.ast).code;
|
|
1768
|
+
}
|
|
1769
|
+
var STUDIO_HOLD_MARKER = "hf-hold";
|
|
1770
|
+
function isStudioHoldSet(anim) {
|
|
1771
|
+
return anim.method === "set" && anim.properties?.data === STUDIO_HOLD_MARKER;
|
|
1772
|
+
}
|
|
1773
|
+
function syncPositionHoldsBeforeKeyframes(script) {
|
|
1774
|
+
let parsed;
|
|
1775
|
+
try {
|
|
1776
|
+
parsed = parseGsapScript(script);
|
|
1777
|
+
} catch {
|
|
1778
|
+
return script;
|
|
1779
|
+
}
|
|
1780
|
+
let result = script;
|
|
1781
|
+
const staleHoldIds = parsed.animations.filter(isStudioHoldSet).map((a) => a.id);
|
|
1782
|
+
for (const id of staleHoldIds) result = removeAnimationFromScript(result, id);
|
|
1783
|
+
let reparsed;
|
|
1784
|
+
try {
|
|
1785
|
+
reparsed = parseGsapScript(result);
|
|
1786
|
+
} catch {
|
|
1787
|
+
return result;
|
|
1788
|
+
}
|
|
1789
|
+
for (const anim of reparsed.animations) {
|
|
1790
|
+
const posProps = positionHoldForAnimation(anim, reparsed.animations);
|
|
1791
|
+
if (!posProps) continue;
|
|
1792
|
+
result = insertInheritedStateSet(result, anim.targetSelector, 0, {
|
|
1793
|
+
...posProps,
|
|
1794
|
+
data: STUDIO_HOLD_MARKER
|
|
1795
|
+
});
|
|
1796
|
+
}
|
|
1797
|
+
return result;
|
|
1798
|
+
}
|
|
1799
|
+
function splitAnimationsInScript(script, opts) {
|
|
1800
|
+
const parsed = parseGsapScript(script);
|
|
1801
|
+
const originalSelector = `#${opts.originalId}`;
|
|
1802
|
+
const newSelector = `#${opts.newId}`;
|
|
1803
|
+
const skippedSelectors = [];
|
|
1804
|
+
for (const a of parsed.animations) {
|
|
1805
|
+
if (a.targetSelector !== originalSelector && a.targetSelector.includes(opts.originalId)) {
|
|
1806
|
+
skippedSelectors.push(a.targetSelector);
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
const matching = parsed.animations.filter((a) => a.targetSelector === originalSelector);
|
|
1810
|
+
if (matching.length === 0) return { script, skippedSelectors };
|
|
1811
|
+
let result = script;
|
|
1812
|
+
const newElementStart = opts.splitTime;
|
|
1813
|
+
const inheritedProps = {};
|
|
1814
|
+
for (let i = matching.length - 1; i >= 0; i--) {
|
|
1815
|
+
const anim = matching[i];
|
|
1816
|
+
const pos = typeof anim.position === "number" ? anim.position : 0;
|
|
1817
|
+
const dur = anim.duration ?? 0;
|
|
1818
|
+
const animEnd = pos + dur;
|
|
1819
|
+
if (authorsKeyframes(anim)) {
|
|
1820
|
+
if (pos >= opts.splitTime) {
|
|
1821
|
+
result = updateAnimationSelector(result, anim.id, newSelector);
|
|
1822
|
+
} else if (animEnd > opts.splitTime) {
|
|
1823
|
+
skippedSelectors.push(`${originalSelector} (keyframes spanning split)`);
|
|
1824
|
+
const kfs = anim.keyframes?.keyframes ?? [];
|
|
1825
|
+
for (const kf of kfs) {
|
|
1826
|
+
const kfTime = pos + kf.percentage / 100 * dur;
|
|
1827
|
+
if (kfTime <= opts.splitTime) {
|
|
1828
|
+
for (const [k, v] of Object.entries(kf.properties)) {
|
|
1829
|
+
inheritedProps[k] = v;
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
} else {
|
|
1834
|
+
if (anim.hasUnresolvedKeyframes) {
|
|
1835
|
+
skippedSelectors.push(`${originalSelector} (unreadable keyframes before split)`);
|
|
1836
|
+
}
|
|
1837
|
+
const kfs = anim.keyframes?.keyframes ?? [];
|
|
1838
|
+
if (kfs.length > 0) {
|
|
1839
|
+
for (const [k, v] of Object.entries(kfs[kfs.length - 1].properties)) {
|
|
1840
|
+
inheritedProps[k] = v;
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
continue;
|
|
1845
|
+
}
|
|
1846
|
+
if (animEnd <= opts.splitTime) {
|
|
1847
|
+
if (anim.method === "from") {
|
|
1848
|
+
for (const k of Object.keys(anim.properties)) delete inheritedProps[k];
|
|
1849
|
+
} else {
|
|
1850
|
+
for (const [k, v] of Object.entries(anim.properties)) {
|
|
1851
|
+
inheritedProps[k] = v;
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
continue;
|
|
1855
|
+
}
|
|
1856
|
+
if (pos >= opts.splitTime) {
|
|
1857
|
+
result = updateAnimationSelector(result, anim.id, newSelector);
|
|
1858
|
+
continue;
|
|
1859
|
+
}
|
|
1860
|
+
const progress = dur > 0 ? (opts.splitTime - pos) / dur : 0;
|
|
1861
|
+
const fromSource = anim.fromProperties ?? inheritedProps;
|
|
1862
|
+
const midProps = {};
|
|
1863
|
+
for (const [k, v] of Object.entries(anim.properties)) {
|
|
1864
|
+
if (typeof v !== "number") {
|
|
1865
|
+
midProps[k] = v;
|
|
1866
|
+
continue;
|
|
1867
|
+
}
|
|
1868
|
+
const fromVal = typeof fromSource[k] === "number" ? fromSource[k] : 0;
|
|
1869
|
+
midProps[k] = fromVal + (v - fromVal) * progress;
|
|
1870
|
+
}
|
|
1871
|
+
const firstHalfDuration = opts.splitTime - pos;
|
|
1872
|
+
result = updateAnimationInScript(result, anim.id, {
|
|
1873
|
+
duration: firstHalfDuration,
|
|
1874
|
+
properties: midProps
|
|
1875
|
+
});
|
|
1876
|
+
const secondHalfDuration = animEnd - opts.splitTime;
|
|
1877
|
+
const addResult = addAnimationToScript(result, {
|
|
1878
|
+
targetSelector: newSelector,
|
|
1879
|
+
method: "fromTo",
|
|
1880
|
+
position: newElementStart,
|
|
1881
|
+
duration: secondHalfDuration,
|
|
1882
|
+
properties: { ...anim.properties },
|
|
1883
|
+
fromProperties: { ...midProps },
|
|
1884
|
+
ease: anim.ease,
|
|
1885
|
+
extras: anim.extras
|
|
1886
|
+
});
|
|
1887
|
+
result = addResult.script;
|
|
1888
|
+
for (const [k, v] of Object.entries(midProps)) {
|
|
1889
|
+
inheritedProps[k] = v;
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
if (Object.keys(inheritedProps).length > 0) {
|
|
1893
|
+
result = insertInheritedStateSet(result, newSelector, newElementStart, inheritedProps);
|
|
1894
|
+
}
|
|
1895
|
+
return { script: result, skippedSelectors };
|
|
1896
|
+
}
|
|
1897
|
+
function sortedKeyframes(kfs) {
|
|
1898
|
+
return kfs.slice().sort((a, b) => a.percentage - b.percentage);
|
|
1899
|
+
}
|
|
1900
|
+
function keyframePropsToCode(kf) {
|
|
1901
|
+
return Object.entries(kf.properties).map(([k, v]) => `${safeJsKey(k)}: ${serializeValue(v)}`);
|
|
1902
|
+
}
|
|
1903
|
+
function buildKeyframeObjectCode(keyframes, options) {
|
|
1904
|
+
const entries = mergePercentageKeyframes(keyframes).map((kf) => {
|
|
1905
|
+
const props = keyframePropsToCode(kf);
|
|
1906
|
+
if (kf.ease) props.push(`ease: ${JSON.stringify(kf.ease)}`);
|
|
1907
|
+
if (kf.auto) props.push(`_auto: 1`);
|
|
1908
|
+
return `${JSON.stringify(`${kf.percentage}%`)}: { ${props.join(", ")} }`;
|
|
1909
|
+
});
|
|
1910
|
+
if (options?.easeEach) entries.push(`easeEach: ${JSON.stringify(options.easeEach)}`);
|
|
1911
|
+
return `{ ${entries.join(", ")} }`;
|
|
1912
|
+
}
|
|
1913
|
+
function removeVarsKey(varsArg, key) {
|
|
1914
|
+
if (varsArg?.type !== "ObjectExpression") return;
|
|
1915
|
+
varsArg.properties = varsArg.properties.filter(
|
|
1916
|
+
(p) => !(isObjectProperty(p) && propKeyName(p) === key)
|
|
1917
|
+
);
|
|
1918
|
+
}
|
|
1919
|
+
function percentageFromKey(key) {
|
|
1920
|
+
const m = PERCENTAGE_KEY_RE.exec(key);
|
|
1921
|
+
return m ? Number.parseFloat(m[1]) : Number.NaN;
|
|
1922
|
+
}
|
|
1923
|
+
var PCT_TOLERANCE = 2;
|
|
1924
|
+
var MOVE_NOOP_EPSILON_PCT = 0.05;
|
|
1925
|
+
function findKeyframePropByPct(kfNode, percentage) {
|
|
1926
|
+
const props = kfNode.properties;
|
|
1927
|
+
for (let i = 0; i < props.length; i++) {
|
|
1928
|
+
if (!isObjectProperty(props[i])) continue;
|
|
1929
|
+
const key = propKeyName(props[i]);
|
|
1930
|
+
if (typeof key !== "string") continue;
|
|
1931
|
+
const parsed = percentageFromKey(key);
|
|
1932
|
+
if (Number.isNaN(parsed)) continue;
|
|
1933
|
+
if (Math.abs(parsed - percentage) <= PCT_TOLERANCE) return { idx: i, prop: props[i] };
|
|
1934
|
+
}
|
|
1935
|
+
return null;
|
|
1936
|
+
}
|
|
1937
|
+
function buildKeyframeValueNode(properties, ease) {
|
|
1938
|
+
const effectiveEase = ease ?? (typeof properties.ease === "string" ? properties.ease : void 0);
|
|
1939
|
+
const entries = Object.entries(properties).filter(([k]) => k !== "ease").map(([k, v]) => `${safeJsKey(k)}: ${serializeValue(v)}`);
|
|
1940
|
+
if (effectiveEase) entries.push(`ease: ${JSON.stringify(effectiveEase)}`);
|
|
1941
|
+
return parseExpr(`{ ${entries.join(", ")} }`);
|
|
1942
|
+
}
|
|
1943
|
+
function setObjectExpressionEase(node, ease) {
|
|
1944
|
+
if (node?.type !== "ObjectExpression") return false;
|
|
1945
|
+
const props = node.properties ?? [];
|
|
1946
|
+
const easeIdx = props.findIndex(
|
|
1947
|
+
(property) => isObjectProperty(property) && propKeyName(property) === "ease"
|
|
1948
|
+
);
|
|
1949
|
+
const easeNode = parseExpr(`({ ease: ${JSON.stringify(ease)} })`).properties[0];
|
|
1950
|
+
if (easeIdx >= 0) props[easeIdx] = easeNode;
|
|
1951
|
+
else props.push(easeNode);
|
|
1952
|
+
return true;
|
|
1953
|
+
}
|
|
1954
|
+
function locateAnimation(script, animationId) {
|
|
1955
|
+
let parsed;
|
|
1956
|
+
try {
|
|
1957
|
+
parsed = parseGsapAst(script);
|
|
1958
|
+
} catch {
|
|
1959
|
+
return null;
|
|
1960
|
+
}
|
|
1961
|
+
const target = parsed.located.find((l) => l.id === animationId);
|
|
1962
|
+
return target ? { parsed, target } : null;
|
|
1963
|
+
}
|
|
1964
|
+
var ANIM_ID_RE = /^(.*)-(fromTo|from|to|set)-(\d+)-([a-z]+)$/;
|
|
1965
|
+
function locateAnimationWithFallback(script, animationId) {
|
|
1966
|
+
const loc = locateAnimation(script, animationId);
|
|
1967
|
+
if (loc) return loc;
|
|
1968
|
+
const convertedId = animationId.replace(/-from-|-fromTo-/, "-to-");
|
|
1969
|
+
if (convertedId !== animationId) {
|
|
1970
|
+
const converted = locateAnimation(script, convertedId);
|
|
1971
|
+
if (converted) return converted;
|
|
1972
|
+
}
|
|
1973
|
+
const want = ANIM_ID_RE.exec(animationId);
|
|
1974
|
+
if (!want) return null;
|
|
1975
|
+
const [, sel, method, wantPosStr, group] = want;
|
|
1976
|
+
const wantPos = Number(wantPosStr);
|
|
1977
|
+
let parsed;
|
|
1978
|
+
try {
|
|
1979
|
+
parsed = parseGsapAst(script);
|
|
1980
|
+
} catch {
|
|
1981
|
+
return null;
|
|
1982
|
+
}
|
|
1983
|
+
let best = null;
|
|
1984
|
+
let bestDist = Number.POSITIVE_INFINITY;
|
|
1985
|
+
for (const l of parsed.located) {
|
|
1986
|
+
const m = ANIM_ID_RE.exec(l.id);
|
|
1987
|
+
if (!m || m[1] !== sel || m[2] !== method || m[4] !== group) continue;
|
|
1988
|
+
const dist = Math.abs(Number(m[3]) - wantPos);
|
|
1989
|
+
if (dist < bestDist) {
|
|
1990
|
+
best = l;
|
|
1991
|
+
bestDist = dist;
|
|
1992
|
+
}
|
|
1993
|
+
}
|
|
1994
|
+
return best ? { parsed, target: best } : null;
|
|
1995
|
+
}
|
|
1996
|
+
function findKeyframesObjectNode(varsArg) {
|
|
1997
|
+
const node = findPropertyNode(varsArg, "keyframes");
|
|
1998
|
+
return node?.type === "ObjectExpression" ? node : null;
|
|
1999
|
+
}
|
|
2000
|
+
function convertArrayKeyframesToObjectNode(varsArg, scope) {
|
|
2001
|
+
if (varsArg?.type !== "ObjectExpression") return null;
|
|
2002
|
+
const prop = (varsArg.properties ?? []).find(
|
|
2003
|
+
(p) => isObjectProperty(p) && propKeyName(p) === "keyframes"
|
|
2004
|
+
);
|
|
2005
|
+
if (!prop || prop.value?.type !== "ArrayExpression") return null;
|
|
2006
|
+
const els = (prop.value.elements ?? []).filter(
|
|
2007
|
+
(e) => !!e && e.type === "ObjectExpression"
|
|
2008
|
+
);
|
|
2009
|
+
if (els.length === 0) return null;
|
|
2010
|
+
const records = els.map((element) => objectExpressionToRecord(element, scope));
|
|
2011
|
+
const outerDuration = objectExpressionToRecord(varsArg, scope).duration;
|
|
2012
|
+
const timing = getCompatibleObjectArrayKeyframeTiming(
|
|
2013
|
+
records.map((record) => record.duration),
|
|
2014
|
+
outerDuration
|
|
2015
|
+
);
|
|
2016
|
+
if (!timing) return null;
|
|
2017
|
+
if (findPropertyNode(varsArg, "duration") === void 0) {
|
|
2018
|
+
setVarsKey(varsArg, "duration", timing.totalDuration);
|
|
2019
|
+
}
|
|
2020
|
+
const entries = els.map((el, i) => {
|
|
2021
|
+
el.properties = (el.properties ?? []).filter(
|
|
2022
|
+
(property) => !isObjectProperty(property) || propKeyName(property) !== "duration"
|
|
2023
|
+
);
|
|
2024
|
+
return `${JSON.stringify(`${timing.percentages[i]}%`)}: ${recast.print(el).code}`;
|
|
2025
|
+
});
|
|
2026
|
+
prop.value = parseExpr(`{ ${entries.join(", ")}, easeEach: "none" }`);
|
|
2027
|
+
return prop.value;
|
|
2028
|
+
}
|
|
2029
|
+
function filterPercentageProps(kfNode) {
|
|
2030
|
+
return kfNode.properties.filter((p) => {
|
|
2031
|
+
if (!isObjectProperty(p)) return false;
|
|
2032
|
+
const key = propKeyName(p);
|
|
2033
|
+
return typeof key === "string" && PERCENTAGE_KEY_RE.test(key);
|
|
2034
|
+
});
|
|
2035
|
+
}
|
|
2036
|
+
function collapseKeyframesToFlat(varsArg, record) {
|
|
2037
|
+
for (const [k, v] of Object.entries(record)) {
|
|
2038
|
+
if (k === "ease") continue;
|
|
2039
|
+
if (typeof v === "number" || typeof v === "string") setVarsKey(varsArg, k, v);
|
|
2040
|
+
}
|
|
2041
|
+
removeVarsKey(varsArg, "keyframes");
|
|
2042
|
+
removeVarsKey(varsArg, "easeEach");
|
|
2043
|
+
}
|
|
2044
|
+
function locateKeyframeCtx(script, animationId, percentage) {
|
|
2045
|
+
const loc = locateAnimationWithFallback(script, animationId);
|
|
2046
|
+
if (!loc) return null;
|
|
2047
|
+
const kfNode = findKeyframesObjectNode(loc.target.call.varsArg);
|
|
2048
|
+
if (!kfNode) return null;
|
|
2049
|
+
return { loc, kfNode, pctKey: `${percentage}%` };
|
|
2050
|
+
}
|
|
2051
|
+
function addKeyframeToScript(script, animationId, percentage, properties, ease, backfillDefaults) {
|
|
2052
|
+
let loc = locateAnimationWithFallback(script, animationId);
|
|
2053
|
+
if (!loc) return script;
|
|
2054
|
+
let kfNode = findKeyframesObjectNode(loc.target.call.varsArg);
|
|
2055
|
+
if (!kfNode) {
|
|
2056
|
+
kfNode = convertArrayKeyframesToObjectNode(loc.target.call.varsArg, loc.parsed.scope);
|
|
2057
|
+
}
|
|
2058
|
+
if (!kfNode) {
|
|
2059
|
+
script = convertToKeyframesInScript(script, animationId);
|
|
2060
|
+
loc = locateAnimationWithFallback(script, animationId);
|
|
2061
|
+
if (!loc) return script;
|
|
2062
|
+
kfNode = findKeyframesObjectNode(loc.target.call.varsArg);
|
|
2063
|
+
if (!kfNode) return script;
|
|
2064
|
+
}
|
|
2065
|
+
const pctKey = `${percentage}%`;
|
|
2066
|
+
const newValueNode = buildKeyframeValueNode(properties, ease);
|
|
2067
|
+
const existing = findKeyframePropByPct(kfNode, percentage);
|
|
2068
|
+
if (existing) {
|
|
2069
|
+
if (existing.prop.value?.type === "ObjectExpression") {
|
|
2070
|
+
const existingRecord = objectExpressionToRecord(existing.prop.value, loc.parsed.scope);
|
|
2071
|
+
const merged = { ...existingRecord };
|
|
2072
|
+
for (const [k, v] of Object.entries(properties)) merged[k] = v;
|
|
2073
|
+
existing.prop.value = buildKeyframeValueNode(
|
|
2074
|
+
merged,
|
|
2075
|
+
ease ?? (typeof existingRecord.ease === "string" ? existingRecord.ease : void 0)
|
|
2076
|
+
);
|
|
2077
|
+
} else {
|
|
2078
|
+
existing.prop.value = newValueNode;
|
|
2079
|
+
}
|
|
2080
|
+
} else {
|
|
2081
|
+
const newProp = parseExpr(`{ ${JSON.stringify(pctKey)}: {} }`).properties[0];
|
|
2082
|
+
newProp.value = newValueNode;
|
|
2083
|
+
let insertIdx = kfNode.properties.length;
|
|
2084
|
+
for (let i = 0; i < kfNode.properties.length; i++) {
|
|
2085
|
+
const key = isObjectProperty(kfNode.properties[i]) ? propKeyName(kfNode.properties[i]) : void 0;
|
|
2086
|
+
if (typeof key === "string" && percentageFromKey(key) > percentage) {
|
|
2087
|
+
insertIdx = i;
|
|
2088
|
+
break;
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
kfNode.properties.splice(insertIdx, 0, newProp);
|
|
2092
|
+
}
|
|
2093
|
+
if (percentage > 0 && percentage < 100) {
|
|
2094
|
+
const pctProps = filterPercentageProps(kfNode);
|
|
2095
|
+
const allPcts = pctProps.map((p) => percentageFromKey(propKeyName(p) ?? "")).filter((n) => !Number.isNaN(n) && n !== percentage).sort((a, b) => a - b);
|
|
2096
|
+
const leftNeighbor = allPcts.filter((p) => p < percentage).pop();
|
|
2097
|
+
const rightNeighbor = allPcts.find((p) => p > percentage);
|
|
2098
|
+
for (const endPct of [0, 100]) {
|
|
2099
|
+
const isNeighbor = endPct === 0 ? leftNeighbor === 0 : rightNeighbor === 100;
|
|
2100
|
+
if (!isNeighbor) continue;
|
|
2101
|
+
const endProp = pctProps.find(
|
|
2102
|
+
(p) => percentageFromKey(propKeyName(p) ?? "") === endPct
|
|
2103
|
+
);
|
|
2104
|
+
if (!endProp?.value || endProp.value.type !== "ObjectExpression") continue;
|
|
2105
|
+
const hasAuto = endProp.value.properties.some(
|
|
2106
|
+
(p) => isObjectProperty(p) && propKeyName(p) === "_auto"
|
|
2107
|
+
);
|
|
2108
|
+
if (!hasAuto) continue;
|
|
2109
|
+
const updatedProps = { ...properties, _auto: 1 };
|
|
2110
|
+
endProp.value = buildKeyframeValueNode(updatedProps, void 0);
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
if (backfillDefaults) {
|
|
2114
|
+
const newPropKeys = Object.keys(properties);
|
|
2115
|
+
const pctProps = filterPercentageProps(kfNode);
|
|
2116
|
+
for (const prop of pctProps) {
|
|
2117
|
+
const key = propKeyName(prop);
|
|
2118
|
+
if (key === pctKey) continue;
|
|
2119
|
+
const valObj = prop.value;
|
|
2120
|
+
if (!valObj || valObj.type !== "ObjectExpression") continue;
|
|
2121
|
+
const existingKeys = new Set(
|
|
2122
|
+
valObj.properties.filter((p) => isObjectProperty(p)).map((p) => propKeyName(p))
|
|
2123
|
+
);
|
|
2124
|
+
for (const pk of newPropKeys) {
|
|
2125
|
+
if (existingKeys.has(pk)) continue;
|
|
2126
|
+
const defaultVal = backfillDefaults[pk];
|
|
2127
|
+
if (defaultVal == null) continue;
|
|
2128
|
+
const fillProp = parseExpr(`{ ${safeJsKey(pk)}: ${serializeValue(defaultVal)} }`).properties[0];
|
|
2129
|
+
valObj.properties.push(fillProp);
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
return recast.print(loc.parsed.ast).code;
|
|
2134
|
+
}
|
|
2135
|
+
function removeKeyframeFromScript(script, animationId, percentage) {
|
|
2136
|
+
const arrLoc = locateAnimationWithFallback(script, animationId);
|
|
2137
|
+
const arrVal = arrLoc && findPropertyNode(arrLoc.target.call.varsArg, "keyframes");
|
|
2138
|
+
if (arrLoc && arrVal?.type === "ArrayExpression") {
|
|
2139
|
+
const elements = (arrVal.elements ?? []).filter(
|
|
2140
|
+
(e) => !!e && e.type === "ObjectExpression"
|
|
2141
|
+
);
|
|
2142
|
+
if (elements.length === 0) return script;
|
|
2143
|
+
const durations = elements.map(
|
|
2144
|
+
(element) => objectExpressionToRecord(element, arrLoc.parsed.scope).duration
|
|
2145
|
+
);
|
|
2146
|
+
const matchIdx = findObjectArrayKeyframeIndex(durations, percentage);
|
|
2147
|
+
if (matchIdx === null) return script;
|
|
2148
|
+
const remaining = elements.filter((_, i) => i !== matchIdx);
|
|
2149
|
+
if (remaining.length < 2) {
|
|
2150
|
+
const sole = remaining[0];
|
|
2151
|
+
const record = sole ? objectExpressionToRecord(sole, arrLoc.parsed.scope) : {};
|
|
2152
|
+
collapseKeyframesToFlat(arrLoc.target.call.varsArg, record);
|
|
2153
|
+
} else {
|
|
2154
|
+
const realIdx = arrVal.elements.indexOf(elements[matchIdx]);
|
|
2155
|
+
arrVal.elements.splice(realIdx, 1);
|
|
2156
|
+
}
|
|
2157
|
+
return recast.print(arrLoc.parsed.ast).code;
|
|
2158
|
+
}
|
|
2159
|
+
const ctx = locateKeyframeCtx(script, animationId, percentage);
|
|
2160
|
+
if (!ctx) return script;
|
|
2161
|
+
const { loc, kfNode } = ctx;
|
|
2162
|
+
const match = findKeyframePropByPct(kfNode, percentage);
|
|
2163
|
+
if (!match) return script;
|
|
2164
|
+
const removeIdx = match.idx;
|
|
2165
|
+
kfNode.properties.splice(removeIdx, 1);
|
|
2166
|
+
const remainingKfs = filterPercentageProps(kfNode);
|
|
2167
|
+
if (remainingKfs.length < 2) {
|
|
2168
|
+
const record = remainingKfs.length === 1 ? objectExpressionToRecord(remainingKfs[0].value, loc.parsed.scope) : {};
|
|
2169
|
+
collapseKeyframesToFlat(loc.target.call.varsArg, record);
|
|
2170
|
+
}
|
|
2171
|
+
return recast.print(loc.parsed.ast).code;
|
|
2172
|
+
}
|
|
2173
|
+
function moveKeyframeInScript(script, animationId, fromPercentage, toPercentage) {
|
|
2174
|
+
const loc = locateAnimationWithFallback(script, animationId);
|
|
2175
|
+
if (!loc) return script;
|
|
2176
|
+
const kfNode = findKeyframesObjectNode(loc.target.call.varsArg) ?? convertArrayKeyframesToObjectNode(loc.target.call.varsArg, loc.parsed.scope);
|
|
2177
|
+
if (!kfNode) return script;
|
|
2178
|
+
const match = findKeyframePropByPct(kfNode, fromPercentage);
|
|
2179
|
+
if (!match) return script;
|
|
2180
|
+
if (Math.abs(fromPercentage - toPercentage) < MOVE_NOOP_EPSILON_PCT) return script;
|
|
2181
|
+
const dest = findKeyframePropByPct(kfNode, toPercentage);
|
|
2182
|
+
if (dest && dest.prop !== match.prop) return script;
|
|
2183
|
+
const movedValue = match.prop.value;
|
|
2184
|
+
const entries = [];
|
|
2185
|
+
for (const prop of filterPercentageProps(kfNode)) {
|
|
2186
|
+
if (prop === match.prop) continue;
|
|
2187
|
+
const pct = percentageFromKey(propKeyName(prop) ?? "");
|
|
2188
|
+
if (Number.isNaN(pct)) continue;
|
|
2189
|
+
entries.push({ pct, value: prop.value });
|
|
2190
|
+
}
|
|
2191
|
+
entries.push({ pct: toPercentage, value: movedValue });
|
|
2192
|
+
entries.sort((a, b) => a.pct - b.pct);
|
|
2193
|
+
kfNode.properties = entries.map((e) => {
|
|
2194
|
+
const p = parseExpr(`{ ${JSON.stringify(`${e.pct}%`)}: {} }`).properties[0];
|
|
2195
|
+
p.value = e.value;
|
|
2196
|
+
return p;
|
|
2197
|
+
});
|
|
2198
|
+
return recast.print(loc.parsed.ast).code;
|
|
2199
|
+
}
|
|
2200
|
+
function resizeKeyframedTweenInScript(script, animationId, newPosition, newDuration, pctRemap) {
|
|
2201
|
+
const loc = locateAnimationWithFallback(script, animationId);
|
|
2202
|
+
if (!loc) return script;
|
|
2203
|
+
const kfNode = findKeyframesObjectNode(loc.target.call.varsArg) ?? convertArrayKeyframesToObjectNode(loc.target.call.varsArg, loc.parsed.scope);
|
|
2204
|
+
if (!kfNode) return script;
|
|
2205
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2206
|
+
for (const { from, to } of pctRemap) {
|
|
2207
|
+
const match = findKeyframePropByPct(kfNode, from);
|
|
2208
|
+
if (!match || seen.has(match.prop)) continue;
|
|
2209
|
+
seen.add(match.prop);
|
|
2210
|
+
match.prop.key = parseExpr(`{ ${JSON.stringify(`${to}%`)}: 0 }`).properties[0].key;
|
|
2211
|
+
}
|
|
2212
|
+
applyUpdatesToCall(loc.target.call, {
|
|
2213
|
+
position: newPosition,
|
|
2214
|
+
// Resizing is an explicit duration-authoring gesture. Promote GSAP's
|
|
2215
|
+
// implicit default so the dragged window is the window that plays.
|
|
2216
|
+
duration: newDuration
|
|
2217
|
+
});
|
|
2218
|
+
return recast.print(loc.parsed.ast).code;
|
|
2219
|
+
}
|
|
2220
|
+
function updateKeyframeInScript(script, animationId, percentage, properties, ease) {
|
|
2221
|
+
const arrLoc = locateAnimationWithFallback(script, animationId);
|
|
2222
|
+
const arrVal = arrLoc && findPropertyNode(arrLoc.target.call.varsArg, "keyframes");
|
|
2223
|
+
if (arrLoc && arrVal?.type === "ArrayExpression") {
|
|
2224
|
+
const elements = (arrVal.elements ?? []).filter(
|
|
2225
|
+
(e) => !!e && e.type === "ObjectExpression"
|
|
2226
|
+
);
|
|
2227
|
+
if (elements.length === 0) return script;
|
|
2228
|
+
const records = elements.map(
|
|
2229
|
+
(element) => objectExpressionToRecord(element, arrLoc.parsed.scope)
|
|
2230
|
+
);
|
|
2231
|
+
const matchIdx = findObjectArrayKeyframeIndex(
|
|
2232
|
+
records.map((record) => record.duration),
|
|
2233
|
+
percentage,
|
|
2234
|
+
{ fallbackToNearest: true }
|
|
2235
|
+
);
|
|
2236
|
+
if (matchIdx === null) return script;
|
|
2237
|
+
const matchEl = elements[matchIdx];
|
|
2238
|
+
if (!matchEl) return script;
|
|
2239
|
+
const realIdx = arrVal.elements.indexOf(matchEl);
|
|
2240
|
+
if (Object.keys(properties).length === 0 && ease && setObjectExpressionEase(matchEl, ease)) {
|
|
2241
|
+
return recast.print(arrLoc.parsed.ast).code;
|
|
2242
|
+
}
|
|
2243
|
+
const merged = {};
|
|
2244
|
+
for (const [key, value] of Object.entries(records[matchIdx] ?? {})) {
|
|
2245
|
+
if (typeof value === "number" || typeof value === "string") merged[key] = value;
|
|
2246
|
+
}
|
|
2247
|
+
Object.assign(merged, properties);
|
|
2248
|
+
arrVal.elements[realIdx] = buildKeyframeValueNode(merged, ease);
|
|
2249
|
+
return recast.print(arrLoc.parsed.ast).code;
|
|
2250
|
+
}
|
|
2251
|
+
if (arrLoc && !arrVal && arrLoc.target.animation.arcPath?.enabled) {
|
|
2252
|
+
const propertyKeys = Object.keys(properties);
|
|
2253
|
+
if (propertyKeys.some((key) => key !== "x" && key !== "y")) return script;
|
|
2254
|
+
let next = script;
|
|
2255
|
+
if (propertyKeys.length > 0) {
|
|
2256
|
+
const waypoints = extractArcWaypoints(arrLoc.target.animation);
|
|
2257
|
+
if (waypoints.length < 2) return script;
|
|
2258
|
+
const pointIndex = Math.max(
|
|
2259
|
+
0,
|
|
2260
|
+
Math.min(waypoints.length - 1, Math.round(percentage / 100 * (waypoints.length - 1)))
|
|
2261
|
+
);
|
|
2262
|
+
const current = waypoints[pointIndex];
|
|
2263
|
+
if (!current) return script;
|
|
2264
|
+
const x = properties.x ?? current.x;
|
|
2265
|
+
const y = properties.y ?? current.y;
|
|
2266
|
+
if (typeof x !== "number" || typeof y !== "number") return script;
|
|
2267
|
+
next = updateMotionPathPointInScript(next, animationId, pointIndex, { x, y });
|
|
2268
|
+
}
|
|
2269
|
+
if (ease !== void 0) {
|
|
2270
|
+
const updated = locateAnimationWithFallback(next, animationId);
|
|
2271
|
+
if (!updated) return script;
|
|
2272
|
+
applyUpdatesToCall(updated.target.call, { ease });
|
|
2273
|
+
next = recast.print(updated.parsed.ast).code;
|
|
2274
|
+
}
|
|
2275
|
+
return next;
|
|
2276
|
+
}
|
|
2277
|
+
const ctx = locateKeyframeCtx(script, animationId, percentage);
|
|
2278
|
+
if (!ctx) return script;
|
|
2279
|
+
const { loc, kfNode } = ctx;
|
|
2280
|
+
const match = findKeyframePropByPct(kfNode, percentage);
|
|
2281
|
+
if (!match) return script;
|
|
2282
|
+
if (Object.keys(properties).length === 0 && ease) {
|
|
2283
|
+
if (setObjectExpressionEase(match.prop.value, ease)) {
|
|
2284
|
+
return recast.print(loc.parsed.ast).code;
|
|
2285
|
+
}
|
|
2286
|
+
return script;
|
|
2287
|
+
}
|
|
2288
|
+
const existing = match.prop.value;
|
|
2289
|
+
if (existing?.type === "ObjectExpression") {
|
|
2290
|
+
const props = existing.properties ?? [];
|
|
2291
|
+
const upsert = (key, valueCode) => {
|
|
2292
|
+
const idx = props.findIndex((p) => isObjectProperty(p) && propKeyName(p) === key);
|
|
2293
|
+
const node = parseExpr(`({ ${safeJsKey(key)}: ${valueCode} })`).properties[0];
|
|
2294
|
+
if (idx >= 0) props[idx] = node;
|
|
2295
|
+
else props.push(node);
|
|
2296
|
+
};
|
|
2297
|
+
for (const [k, v] of Object.entries(properties)) upsert(k, serializeValue(v));
|
|
2298
|
+
if (ease !== void 0) upsert("ease", JSON.stringify(ease));
|
|
2299
|
+
return recast.print(loc.parsed.ast).code;
|
|
2300
|
+
}
|
|
2301
|
+
match.prop.value = buildKeyframeValueNode(properties, ease);
|
|
2302
|
+
return recast.print(loc.parsed.ast).code;
|
|
2303
|
+
}
|
|
2304
|
+
function stripEditableAndEase(varsArg) {
|
|
2305
|
+
if (varsArg?.type !== "ObjectExpression") return;
|
|
2306
|
+
varsArg.properties = varsArg.properties.filter((p) => {
|
|
2307
|
+
if (!isObjectProperty(p)) return true;
|
|
2308
|
+
const key = propKeyName(p);
|
|
2309
|
+
return key !== "ease" && key !== "keyframes";
|
|
2310
|
+
});
|
|
2311
|
+
filterEditableKeys(varsArg, () => false);
|
|
2312
|
+
}
|
|
2313
|
+
function insertKeyframesProp(varsArg, fromProps, toProps, easeEach) {
|
|
2314
|
+
const fromEntries = Object.entries(fromProps).map(([k, v]) => `${safeJsKey(k)}: ${serializeValue(v)}`);
|
|
2315
|
+
const toEntries = Object.entries(toProps).map(([k, v]) => `${safeJsKey(k)}: ${serializeValue(v)}`);
|
|
2316
|
+
const easeEntry = easeEach ? `, easeEach: ${JSON.stringify(easeEach)}` : "";
|
|
2317
|
+
const kfCode = `{ "0%": { ${fromEntries.join(", ")} }, "100%": { ${toEntries.join(", ")} }${easeEntry} }`;
|
|
2318
|
+
const kfProp = parseExpr(`{ keyframes: {} }`).properties[0];
|
|
2319
|
+
kfProp.value = parseExpr(kfCode);
|
|
2320
|
+
if (varsArg?.type === "ObjectExpression") varsArg.properties.unshift(kfProp);
|
|
2321
|
+
}
|
|
2322
|
+
function convertToKeyframesInScript(script, animationId, resolvedFromValues, setDuration = 1) {
|
|
2323
|
+
let loc = locateAnimationWithFallback(script, animationId);
|
|
2324
|
+
if (!loc) return script;
|
|
2325
|
+
const anim = loc.target.animation;
|
|
2326
|
+
if (authorsKeyframes(anim)) return script;
|
|
2327
|
+
const { fromProps, toProps } = resolveConversionProps(anim, resolvedFromValues);
|
|
2328
|
+
const varsArg = loc.target.call.varsArg;
|
|
2329
|
+
const originalEase = anim.ease;
|
|
2330
|
+
stripEditableAndEase(varsArg);
|
|
2331
|
+
insertKeyframesProp(varsArg, fromProps, toProps, originalEase || void 0);
|
|
2332
|
+
if (originalEase) {
|
|
2333
|
+
setVarsKey(varsArg, "ease", "none");
|
|
2334
|
+
}
|
|
2335
|
+
if (anim.method === "from" || anim.method === "fromTo") {
|
|
2336
|
+
loc.target.call.node.callee.property.name = "to";
|
|
2337
|
+
if (anim.method === "fromTo") loc.target.call.node.arguments.splice(1, 1);
|
|
2338
|
+
}
|
|
2339
|
+
if (anim.method === "set") {
|
|
2340
|
+
const calleeObj = loc.target.call.node.callee.object;
|
|
2341
|
+
if (anim.global && calleeObj?.type === "Identifier") {
|
|
2342
|
+
calleeObj.name = loc.parsed.timelineVar;
|
|
2343
|
+
if (loc.target.call.node.arguments.length < 3) {
|
|
2344
|
+
loc.target.call.node.arguments.push(parseExpr("0"));
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
loc.target.call.node.callee.property.name = "to";
|
|
2348
|
+
removeVarsKey(varsArg, "immediateRender");
|
|
2349
|
+
setVarsKey(varsArg, "duration", Math.max(1e-3, setDuration));
|
|
2350
|
+
}
|
|
2351
|
+
return recast.print(loc.parsed.ast).code;
|
|
2352
|
+
}
|
|
2353
|
+
function removeAllKeyframesFromScript(script, animationId) {
|
|
2354
|
+
let loc = locateAnimationWithFallback(script, animationId);
|
|
2355
|
+
if (!loc) return script;
|
|
2356
|
+
const kfNode = findKeyframesObjectNode(loc.target.call.varsArg) ?? convertArrayKeyframesToObjectNode(loc.target.call.varsArg, loc.parsed.scope);
|
|
2357
|
+
const method = loc.target.call.method;
|
|
2358
|
+
let record;
|
|
2359
|
+
if (kfNode) {
|
|
2360
|
+
const kfEntries = filterPercentageProps(kfNode).map((p) => ({ pct: percentageFromKey(propKeyName(p)), prop: p })).filter((e) => !Number.isNaN(e.pct)).sort((a, b) => a.pct - b.pct);
|
|
2361
|
+
if (kfEntries.length === 0) return script;
|
|
2362
|
+
const collapseEntry = method === "from" ? kfEntries[0] : kfEntries[kfEntries.length - 1];
|
|
2363
|
+
record = objectExpressionToRecord(collapseEntry.prop.value, loc.parsed.scope);
|
|
2364
|
+
} else {
|
|
2365
|
+
const synthetic = loc.target.animation.arcPath?.enabled ? loc.target.animation.keyframes?.keyframes : void 0;
|
|
2366
|
+
if (!synthetic?.length) return script;
|
|
2367
|
+
const sorted = [...synthetic].sort((a, b) => a.percentage - b.percentage);
|
|
2368
|
+
record = (method === "from" ? sorted[0] : sorted[sorted.length - 1]).properties;
|
|
2369
|
+
removeVarsKey(loc.target.call.varsArg, "motionPath");
|
|
2370
|
+
}
|
|
2371
|
+
collapseKeyframesToFlat(loc.target.call.varsArg, record);
|
|
2372
|
+
removeVarsKey(loc.target.call.varsArg, "ease");
|
|
2373
|
+
setVarsKey(loc.target.call.varsArg, "duration", 0);
|
|
2374
|
+
setVarsKey(loc.target.call.varsArg, "immediateRender", true);
|
|
2375
|
+
if (loc.target.animation.propertyGroup === "position") {
|
|
2376
|
+
for (const l of loc.parsed.located) {
|
|
2377
|
+
if (l === loc.target) continue;
|
|
2378
|
+
if (l.animation.targetSelector === loc.target.animation.targetSelector && l.animation.propertyGroup === "position") {
|
|
2379
|
+
removeCallFromAst(l.call);
|
|
2380
|
+
}
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
return recast.print(loc.parsed.ast).code;
|
|
2384
|
+
}
|
|
2385
|
+
function materializeKeyframesInScript(script, animationId, keyframes, easeEach, resolvedSelector) {
|
|
2386
|
+
let loc = locateAnimationWithFallback(script, animationId);
|
|
2387
|
+
if (!loc) return script;
|
|
2388
|
+
const varsArg = loc.target.call.varsArg;
|
|
2389
|
+
if (resolvedSelector && loc.target.call.node.arguments[0]) {
|
|
2390
|
+
loc.target.call.node.arguments[0] = parseExpr(JSON.stringify(resolvedSelector));
|
|
2391
|
+
}
|
|
2392
|
+
const kfObjCode = buildKeyframeObjectCode(sortedKeyframes(keyframes), { easeEach });
|
|
2393
|
+
const kfParent = varsArg.properties.find(
|
|
2394
|
+
(p) => isObjectProperty(p) && propKeyName(p) === "keyframes"
|
|
2395
|
+
);
|
|
2396
|
+
if (kfParent) {
|
|
2397
|
+
kfParent.value = parseExpr(kfObjCode);
|
|
2398
|
+
} else {
|
|
2399
|
+
const kfProp = parseExpr(`{ keyframes: ${kfObjCode} }`).properties[0];
|
|
2400
|
+
varsArg.properties.unshift(kfProp);
|
|
2401
|
+
}
|
|
2402
|
+
removeVarsKey(varsArg, "easeEach");
|
|
2403
|
+
return recast.print(loc.parsed.ast).code;
|
|
2404
|
+
}
|
|
2405
|
+
function numericXY(props) {
|
|
2406
|
+
const x = props.x;
|
|
2407
|
+
const y = props.y;
|
|
2408
|
+
return typeof x === "number" && typeof y === "number" ? { x, y } : null;
|
|
2409
|
+
}
|
|
2410
|
+
function extractArcWaypoints(anim) {
|
|
2411
|
+
const kfs = anim.keyframes?.keyframes ?? [];
|
|
2412
|
+
const waypoints = kfs.map((kf) => numericXY(kf.properties)).filter((p) => p !== null);
|
|
2413
|
+
if (waypoints.length >= 2) return waypoints;
|
|
2414
|
+
const px = anim.properties.x;
|
|
2415
|
+
const py = anim.properties.y;
|
|
2416
|
+
if (typeof px !== "number" && typeof py !== "number") return waypoints;
|
|
2417
|
+
return [
|
|
2418
|
+
{ x: 0, y: 0 },
|
|
2419
|
+
{ x: typeof px === "number" ? px : 0, y: typeof py === "number" ? py : 0 }
|
|
2420
|
+
];
|
|
2421
|
+
}
|
|
2422
|
+
function buildMotionPathObjectCode(config) {
|
|
2423
|
+
const { waypoints, segments, autoRotate } = config;
|
|
2424
|
+
const hasExplicitControlPoints = segments.some((s) => s.cp1 && s.cp2);
|
|
2425
|
+
const curvinessVaries = segments.some(
|
|
2426
|
+
(s) => (s.curviness ?? 1) !== (segments[0]?.curviness ?? 1)
|
|
2427
|
+
);
|
|
2428
|
+
let pathEntries;
|
|
2429
|
+
if ((hasExplicitControlPoints || curvinessVaries) && waypoints.length >= 2) {
|
|
2430
|
+
pathEntries = [`{x: ${waypoints[0].x}, y: ${waypoints[0].y}}`];
|
|
2431
|
+
for (let i = 0; i < segments.length; i++) {
|
|
2432
|
+
const seg = segments[i];
|
|
2433
|
+
const nextWp = waypoints[i + 1];
|
|
2434
|
+
if (seg.cp1 && seg.cp2) {
|
|
2435
|
+
pathEntries.push(`{x: ${seg.cp1.x}, y: ${seg.cp1.y}}`);
|
|
2436
|
+
pathEntries.push(`{x: ${seg.cp2.x}, y: ${seg.cp2.y}}`);
|
|
2437
|
+
} else {
|
|
2438
|
+
const wp = waypoints[i];
|
|
2439
|
+
const dx = nextWp.x - wp.x;
|
|
2440
|
+
const dy = nextWp.y - wp.y;
|
|
2441
|
+
const c = seg.curviness ?? 1;
|
|
2442
|
+
pathEntries.push(
|
|
2443
|
+
`{x: ${wp.x + dx * 0.33}, y: ${wp.y + dy * 0.33 - c * Math.abs(dx) * 0.25}}`
|
|
2444
|
+
);
|
|
2445
|
+
pathEntries.push(
|
|
2446
|
+
`{x: ${wp.x + dx * 0.66}, y: ${wp.y + dy * 0.66 - c * Math.abs(dx) * 0.25}}`
|
|
2447
|
+
);
|
|
2448
|
+
}
|
|
2449
|
+
pathEntries.push(`{x: ${nextWp.x}, y: ${nextWp.y}}`);
|
|
2450
|
+
}
|
|
2451
|
+
const pathStr = pathEntries.join(", ");
|
|
2452
|
+
const parts2 = [`path: [${pathStr}]`, `type: "cubic"`];
|
|
2453
|
+
if (autoRotate === true) parts2.push("autoRotate: true");
|
|
2454
|
+
else if (typeof autoRotate === "number") parts2.push(`autoRotate: ${autoRotate}`);
|
|
2455
|
+
return `{ ${parts2.join(", ")} }`;
|
|
2456
|
+
}
|
|
2457
|
+
pathEntries = waypoints.map((wp) => `{x: ${wp.x}, y: ${wp.y}}`);
|
|
2458
|
+
const curviness = segments[0]?.curviness ?? 1;
|
|
2459
|
+
const parts = [`path: [${pathEntries.join(", ")}]`];
|
|
2460
|
+
if (curviness !== 1) parts.push(`curviness: ${curviness}`);
|
|
2461
|
+
if (autoRotate === true) parts.push("autoRotate: true");
|
|
2462
|
+
else if (typeof autoRotate === "number") parts.push(`autoRotate: ${autoRotate}`);
|
|
2463
|
+
return `{ ${parts.join(", ")} }`;
|
|
2464
|
+
}
|
|
2465
|
+
function setArcPathInScript(script, animationId, config) {
|
|
2466
|
+
const loc = locateAnimation(script, animationId);
|
|
2467
|
+
if (!loc) return script;
|
|
2468
|
+
const varsArg = loc.target.call.varsArg;
|
|
2469
|
+
const anim = loc.target.animation;
|
|
2470
|
+
if (!config.enabled) {
|
|
2471
|
+
const motionPathProp = varsArg.properties.find(
|
|
2472
|
+
(p) => isObjectProperty(p) && propKeyName(p) === "motionPath"
|
|
2473
|
+
);
|
|
2474
|
+
if (motionPathProp) {
|
|
2475
|
+
const mpVal = motionPathProp.value;
|
|
2476
|
+
let pathArr;
|
|
2477
|
+
if (mpVal?.type === "ObjectExpression") {
|
|
2478
|
+
const pathProp = mpVal.properties.find(
|
|
2479
|
+
(p) => isObjectProperty(p) && propKeyName(p) === "path"
|
|
2480
|
+
);
|
|
2481
|
+
if (pathProp?.value?.type === "ArrayExpression") pathArr = pathProp.value.elements;
|
|
2482
|
+
}
|
|
2483
|
+
if (pathArr && pathArr.length > 0) {
|
|
2484
|
+
const last = pathArr[pathArr.length - 1];
|
|
2485
|
+
if (last?.type === "ObjectExpression") {
|
|
2486
|
+
for (const p of last.properties) {
|
|
2487
|
+
const k = propKeyName(p);
|
|
2488
|
+
if (k === "x" || k === "y") {
|
|
2489
|
+
const v = p.value?.value;
|
|
2490
|
+
if (typeof v === "number") setVarsKey(varsArg, k, v);
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2493
|
+
}
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
removeVarsKey(varsArg, "motionPath");
|
|
2497
|
+
return recast.print(loc.parsed.ast).code;
|
|
2498
|
+
}
|
|
2499
|
+
const waypoints = extractArcWaypoints(anim);
|
|
2500
|
+
if (waypoints.length < 2) return script;
|
|
2501
|
+
const segments = config.segments.length === waypoints.length - 1 ? config.segments : Array.from({ length: waypoints.length - 1 }, () => ({ curviness: 1 }));
|
|
2502
|
+
const motionPathCode = buildMotionPathObjectCode({
|
|
2503
|
+
waypoints,
|
|
2504
|
+
segments,
|
|
2505
|
+
autoRotate: config.autoRotate
|
|
2506
|
+
});
|
|
2507
|
+
const motionPathNode = parseExpr(motionPathCode);
|
|
2508
|
+
const existingProp = varsArg.properties.find(
|
|
2509
|
+
(p) => isObjectProperty(p) && propKeyName(p) === "motionPath"
|
|
2510
|
+
);
|
|
2511
|
+
if (existingProp) {
|
|
2512
|
+
existingProp.value = motionPathNode;
|
|
2513
|
+
} else {
|
|
2514
|
+
const prop = parseExpr(`{ motionPath: ${motionPathCode} }`).properties[0];
|
|
2515
|
+
varsArg.properties.push(prop);
|
|
2516
|
+
}
|
|
2517
|
+
const kfNode = findKeyframesObjectNode(varsArg);
|
|
2518
|
+
if (kfNode) {
|
|
2519
|
+
for (const pctProp of filterPercentageProps(kfNode)) {
|
|
2520
|
+
if (pctProp.value?.type === "ObjectExpression") {
|
|
2521
|
+
pctProp.value.properties = pctProp.value.properties.filter((p) => {
|
|
2522
|
+
const k = propKeyName(p);
|
|
2523
|
+
return k !== "x" && k !== "y";
|
|
2524
|
+
});
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
removeVarsKey(varsArg, "x");
|
|
2529
|
+
removeVarsKey(varsArg, "y");
|
|
2530
|
+
return recast.print(loc.parsed.ast).code;
|
|
2531
|
+
}
|
|
2532
|
+
function updateArcSegmentInScript(script, animationId, segmentIndex, update) {
|
|
2533
|
+
const loc = locateAnimation(script, animationId);
|
|
2534
|
+
if (!loc) return script;
|
|
2535
|
+
const anim = loc.target.animation;
|
|
2536
|
+
if (!anim.arcPath?.enabled) return script;
|
|
2537
|
+
const segments = [...anim.arcPath.segments];
|
|
2538
|
+
if (segmentIndex < 0 || segmentIndex >= segments.length) return script;
|
|
2539
|
+
segments[segmentIndex] = { ...segments[segmentIndex], ...update };
|
|
2540
|
+
const waypoints = extractArcWaypoints(anim);
|
|
2541
|
+
if (waypoints.length < 2) return script;
|
|
2542
|
+
const motionPathCode = buildMotionPathObjectCode({
|
|
2543
|
+
waypoints,
|
|
2544
|
+
segments,
|
|
2545
|
+
autoRotate: anim.arcPath.autoRotate
|
|
2546
|
+
});
|
|
2547
|
+
const varsArg = loc.target.call.varsArg;
|
|
2548
|
+
const existingProp = varsArg.properties.find(
|
|
2549
|
+
(p) => isObjectProperty(p) && propKeyName(p) === "motionPath"
|
|
2550
|
+
);
|
|
2551
|
+
if (existingProp) {
|
|
2552
|
+
existingProp.value = parseExpr(motionPathCode);
|
|
2553
|
+
}
|
|
2554
|
+
return recast.print(loc.parsed.ast).code;
|
|
2555
|
+
}
|
|
2556
|
+
function updateMotionPathPointInScript(script, animationId, pointIndex, point) {
|
|
2557
|
+
const loc = locateAnimation(script, animationId);
|
|
2558
|
+
if (!loc) return script;
|
|
2559
|
+
const anim = loc.target.animation;
|
|
2560
|
+
if (!anim.arcPath?.enabled) return script;
|
|
2561
|
+
const waypoints = extractArcWaypoints(anim);
|
|
2562
|
+
if (pointIndex < 0 || pointIndex >= waypoints.length || waypoints.length < 2) return script;
|
|
2563
|
+
const nextWaypoints = waypoints.map(
|
|
2564
|
+
(wp, i) => i === pointIndex ? { x: point.x, y: point.y } : wp
|
|
2565
|
+
);
|
|
2566
|
+
const motionPathCode = buildMotionPathObjectCode({
|
|
2567
|
+
waypoints: nextWaypoints,
|
|
2568
|
+
segments: anim.arcPath.segments,
|
|
2569
|
+
autoRotate: anim.arcPath.autoRotate
|
|
2570
|
+
});
|
|
2571
|
+
const varsArg = loc.target.call.varsArg;
|
|
2572
|
+
const existingProp = varsArg.properties.find(
|
|
2573
|
+
(p) => isObjectProperty(p) && propKeyName(p) === "motionPath"
|
|
2574
|
+
);
|
|
2575
|
+
if (existingProp) {
|
|
2576
|
+
existingProp.value = parseExpr(motionPathCode);
|
|
2577
|
+
}
|
|
2578
|
+
return recast.print(loc.parsed.ast).code;
|
|
2579
|
+
}
|
|
2580
|
+
function hasCubicSegments(segments) {
|
|
2581
|
+
return segments.some((s) => s.cp1 != null || s.cp2 != null);
|
|
2582
|
+
}
|
|
2583
|
+
function writeMotionPathValue(loc, waypoints, segments, autoRotate) {
|
|
2584
|
+
const motionPathCode = buildMotionPathObjectCode({ waypoints, segments, autoRotate });
|
|
2585
|
+
const varsArg = loc.target.call.varsArg;
|
|
2586
|
+
const existingProp = varsArg.properties.find(
|
|
2587
|
+
(p) => isObjectProperty(p) && propKeyName(p) === "motionPath"
|
|
2588
|
+
);
|
|
2589
|
+
if (existingProp) existingProp.value = parseExpr(motionPathCode);
|
|
2590
|
+
return recast.print(loc.parsed.ast).code;
|
|
2591
|
+
}
|
|
2592
|
+
function addMotionPathPointInScript(script, animationId, index, point) {
|
|
2593
|
+
const loc = locateAnimation(script, animationId);
|
|
2594
|
+
if (!loc) return script;
|
|
2595
|
+
const anim = loc.target.animation;
|
|
2596
|
+
if (!anim.arcPath?.enabled || hasCubicSegments(anim.arcPath.segments)) return script;
|
|
2597
|
+
const waypoints = extractArcWaypoints(anim);
|
|
2598
|
+
if (index < 1 || index > waypoints.length - 1) return script;
|
|
2599
|
+
const segments = [...anim.arcPath.segments];
|
|
2600
|
+
waypoints.splice(index, 0, { x: point.x, y: point.y });
|
|
2601
|
+
const splitCurviness = segments[index - 1]?.curviness ?? 1;
|
|
2602
|
+
segments.splice(index - 1, 0, { curviness: splitCurviness });
|
|
2603
|
+
return writeMotionPathValue(loc, waypoints, segments, anim.arcPath.autoRotate);
|
|
2604
|
+
}
|
|
2605
|
+
function removeMotionPathPointInScript(script, animationId, index) {
|
|
2606
|
+
const loc = locateAnimation(script, animationId);
|
|
2607
|
+
if (!loc) return script;
|
|
2608
|
+
const anim = loc.target.animation;
|
|
2609
|
+
if (!anim.arcPath?.enabled || hasCubicSegments(anim.arcPath.segments)) return script;
|
|
2610
|
+
const waypoints = extractArcWaypoints(anim);
|
|
2611
|
+
if (waypoints.length <= 2 || index < 0 || index >= waypoints.length) return script;
|
|
2612
|
+
const segments = [...anim.arcPath.segments];
|
|
2613
|
+
waypoints.splice(index, 1);
|
|
2614
|
+
segments.splice(Math.min(index, segments.length - 1), 1);
|
|
2615
|
+
return writeMotionPathValue(loc, waypoints, segments, anim.arcPath.autoRotate);
|
|
2616
|
+
}
|
|
2617
|
+
function addMotionPathToScript(script, targetSelector, position, duration, point, ease = "power1.inOut") {
|
|
2618
|
+
let parsed;
|
|
2619
|
+
try {
|
|
2620
|
+
parsed = parseGsapAst(script);
|
|
2621
|
+
} catch (e) {
|
|
2622
|
+
console.warn("[gsap-parser] addMotionPathToScript parse failed:", e);
|
|
2623
|
+
return { script, id: null };
|
|
2624
|
+
}
|
|
2625
|
+
if (parsed.located.length === 0 && parsed.detection.ref === null) {
|
|
2626
|
+
return { script, id: null };
|
|
2627
|
+
}
|
|
2628
|
+
const motionPathCode = buildMotionPathObjectCode({
|
|
2629
|
+
waypoints: [
|
|
2630
|
+
{ x: 0, y: 0 },
|
|
2631
|
+
{ x: point.x, y: point.y }
|
|
2632
|
+
],
|
|
2633
|
+
segments: [{ curviness: 1 }],
|
|
2634
|
+
autoRotate: false
|
|
2635
|
+
});
|
|
2636
|
+
const selector = JSON.stringify(targetSelector);
|
|
2637
|
+
const varEntries = [
|
|
2638
|
+
`motionPath: ${motionPathCode}`,
|
|
2639
|
+
`duration: ${serializeValue(duration)}`,
|
|
2640
|
+
`ease: ${JSON.stringify(ease)}`
|
|
2641
|
+
];
|
|
2642
|
+
const stmtCode = `${parsed.timelineVar}.to(${selector}, { ${varEntries.join(", ")} }, ${serializeValue(position)});`;
|
|
2643
|
+
const newStatement = parseScript(stmtCode).program.body[0];
|
|
2644
|
+
insertAfterAnchor(parsed, newStatement);
|
|
2645
|
+
const result = recast.print(parsed.ast).code;
|
|
2646
|
+
const reParsed = parseGsapAst(result);
|
|
2647
|
+
const newId = reParsed.located[reParsed.located.length - 1]?.id ?? null;
|
|
2648
|
+
return { script: result, id: newId };
|
|
2649
|
+
}
|
|
2650
|
+
function removeArcPathFromScript(script, animationId) {
|
|
2651
|
+
return setArcPathInScript(script, animationId, {
|
|
2652
|
+
enabled: false,
|
|
2653
|
+
autoRotate: false,
|
|
2654
|
+
segments: []
|
|
2655
|
+
});
|
|
2656
|
+
}
|
|
2657
|
+
function splitIntoPropertyGroups(script, animationId) {
|
|
2658
|
+
let loc = locateAnimationWithFallback(script, animationId);
|
|
2659
|
+
if (!loc) return { script, ids: [animationId] };
|
|
2660
|
+
const anim = loc.target.animation;
|
|
2661
|
+
if (anim.hasUnresolvedKeyframes) return { script, ids: [animationId] };
|
|
2662
|
+
const allPropKeys = /* @__PURE__ */ new Set();
|
|
2663
|
+
if (anim.keyframes) {
|
|
2664
|
+
for (const kf of anim.keyframes.keyframes) {
|
|
2665
|
+
for (const k of Object.keys(kf.properties)) allPropKeys.add(k);
|
|
2666
|
+
}
|
|
2667
|
+
} else {
|
|
2668
|
+
for (const k of Object.keys(anim.properties)) allPropKeys.add(k);
|
|
2669
|
+
}
|
|
2670
|
+
const groupProps = /* @__PURE__ */ new Map();
|
|
2671
|
+
for (const key of allPropKeys) {
|
|
2672
|
+
if (key === "transformOrigin") continue;
|
|
2673
|
+
const group = classifyPropertyGroup(key);
|
|
2674
|
+
let arr = groupProps.get(group);
|
|
2675
|
+
if (!arr) {
|
|
2676
|
+
arr = [];
|
|
2677
|
+
groupProps.set(group, arr);
|
|
2678
|
+
}
|
|
2679
|
+
arr.push(key);
|
|
2680
|
+
}
|
|
2681
|
+
if (groupProps.size <= 1) return { script, ids: [anim.id] };
|
|
2682
|
+
if (allPropKeys.has("transformOrigin")) {
|
|
2683
|
+
let largestGroup;
|
|
2684
|
+
let largestCount = 0;
|
|
2685
|
+
for (const [group, props] of groupProps) {
|
|
2686
|
+
if (props.length > largestCount) {
|
|
2687
|
+
largestCount = props.length;
|
|
2688
|
+
largestGroup = group;
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2691
|
+
if (largestGroup) {
|
|
2692
|
+
groupProps.get(largestGroup).push("transformOrigin");
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2695
|
+
let result = script;
|
|
2696
|
+
result = removeAnimationFromScript(result, anim.id);
|
|
2697
|
+
for (const [, props] of groupProps) {
|
|
2698
|
+
const propSet = new Set(props);
|
|
2699
|
+
if (anim.keyframes) {
|
|
2700
|
+
const groupKeyframes = [];
|
|
2701
|
+
for (const kf of anim.keyframes.keyframes) {
|
|
2702
|
+
const filtered = {};
|
|
2703
|
+
for (const [k, v] of Object.entries(kf.properties)) {
|
|
2704
|
+
if (propSet.has(k)) filtered[k] = v;
|
|
2705
|
+
}
|
|
2706
|
+
if (Object.keys(filtered).length === 0) continue;
|
|
2707
|
+
groupKeyframes.push({
|
|
2708
|
+
percentage: kf.percentage,
|
|
2709
|
+
properties: filtered,
|
|
2710
|
+
...kf.ease ? { ease: kf.ease } : {}
|
|
2711
|
+
});
|
|
2712
|
+
}
|
|
2713
|
+
if (groupKeyframes.length === 0) continue;
|
|
2714
|
+
const addResult = addAnimationWithKeyframesToScript(
|
|
2715
|
+
result,
|
|
2716
|
+
anim.targetSelector,
|
|
2717
|
+
typeof anim.position === "number" ? anim.position : 0,
|
|
2718
|
+
anim.duration ?? 0.5,
|
|
2719
|
+
groupKeyframes,
|
|
2720
|
+
anim.keyframes.easeEach ?? anim.ease
|
|
2721
|
+
);
|
|
2722
|
+
result = addResult.script;
|
|
2723
|
+
} else {
|
|
2724
|
+
const groupProperties = {};
|
|
2725
|
+
for (const [k, v] of Object.entries(anim.properties)) {
|
|
2726
|
+
if (propSet.has(k)) groupProperties[k] = v;
|
|
2727
|
+
}
|
|
2728
|
+
if (Object.keys(groupProperties).length === 0) continue;
|
|
2729
|
+
let fromProperties;
|
|
2730
|
+
if (anim.method === "fromTo" && anim.fromProperties) {
|
|
2731
|
+
fromProperties = {};
|
|
2732
|
+
for (const [k, v] of Object.entries(anim.fromProperties)) {
|
|
2733
|
+
if (propSet.has(k)) fromProperties[k] = v;
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2736
|
+
const addResult = addAnimationToScript(result, {
|
|
2737
|
+
targetSelector: anim.targetSelector,
|
|
2738
|
+
method: anim.method,
|
|
2739
|
+
position: anim.position,
|
|
2740
|
+
duration: anim.duration,
|
|
2741
|
+
ease: anim.ease,
|
|
2742
|
+
properties: groupProperties,
|
|
2743
|
+
fromProperties,
|
|
2744
|
+
extras: anim.extras
|
|
2745
|
+
});
|
|
2746
|
+
result = addResult.script;
|
|
2747
|
+
}
|
|
2748
|
+
}
|
|
2749
|
+
const reParsed = parseGsapAst(result);
|
|
2750
|
+
const newIds = reParsed.located.filter((l) => l.animation.targetSelector === anim.targetSelector).map((l) => l.id);
|
|
2751
|
+
return { script: result, ids: newIds };
|
|
2752
|
+
}
|
|
2753
|
+
function unrollDynamicAnimations(script, animationId, elements) {
|
|
2754
|
+
const loc = locateAnimation(script, animationId);
|
|
2755
|
+
if (!loc) return script;
|
|
2756
|
+
const varsArg = loc.target.call.varsArg;
|
|
2757
|
+
const durationVal = extractLiteralValue(findPropertyNode(varsArg, "duration"), loc.parsed.scope);
|
|
2758
|
+
const easeVal = extractLiteralValue(findPropertyNode(varsArg, "ease"), loc.parsed.scope);
|
|
2759
|
+
const duration = typeof durationVal === "number" ? durationVal : 8;
|
|
2760
|
+
const ease = typeof easeVal === "string" ? easeVal : "none";
|
|
2761
|
+
const posArg = loc.target.call.positionArg;
|
|
2762
|
+
const position = posArg ? extractLiteralValue(posArg, loc.parsed.scope) : 0;
|
|
2763
|
+
const posCode = typeof position === "number" ? String(position) : typeof position === "string" ? JSON.stringify(position) : "0";
|
|
2764
|
+
let loopNode = null;
|
|
2765
|
+
let current = loc.target.call.path;
|
|
2766
|
+
while (current) {
|
|
2767
|
+
const node = current.node ?? current.value;
|
|
2768
|
+
if (node?.type === "ForStatement" || node?.type === "ForInStatement" || node?.type === "ForOfStatement" || node?.type === "WhileStatement") {
|
|
2769
|
+
loopNode = node;
|
|
2770
|
+
break;
|
|
2771
|
+
}
|
|
2772
|
+
if (node?.type === "ExpressionStatement" && node.expression?.type === "CallExpression" && node.expression.callee?.property?.name === "forEach") {
|
|
2773
|
+
loopNode = node;
|
|
2774
|
+
break;
|
|
2775
|
+
}
|
|
2776
|
+
current = current.parent ?? current.parentPath;
|
|
2777
|
+
}
|
|
2778
|
+
const calls = [];
|
|
2779
|
+
for (const el of elements) {
|
|
2780
|
+
const kfCode = buildKeyframeObjectCode(sortedKeyframes(el.keyframes), {
|
|
2781
|
+
easeEach: el.easeEach
|
|
2782
|
+
});
|
|
2783
|
+
calls.push(
|
|
2784
|
+
`${loc.parsed.timelineVar}.to(${JSON.stringify(el.selector)}, { keyframes: ${kfCode}, duration: ${duration}, ease: ${JSON.stringify(ease)} }, ${posCode});`
|
|
2785
|
+
);
|
|
2786
|
+
}
|
|
2787
|
+
const replacement = calls.join("\n ");
|
|
2788
|
+
if (loopNode) {
|
|
2789
|
+
const start = loopNode.start ?? loopNode.range?.[0];
|
|
2790
|
+
const end = loopNode.end ?? loopNode.range?.[1];
|
|
2791
|
+
if (typeof start === "number" && typeof end === "number") {
|
|
2792
|
+
return script.slice(0, start) + replacement + script.slice(end);
|
|
2793
|
+
}
|
|
2794
|
+
}
|
|
2795
|
+
const stmtNode = loc.target.call.path?.parent?.node ?? loc.target.call.path?.parentPath?.node;
|
|
2796
|
+
if (stmtNode?.type === "ExpressionStatement") {
|
|
2797
|
+
const start = stmtNode.start ?? stmtNode.range?.[0];
|
|
2798
|
+
const end = stmtNode.end ?? stmtNode.range?.[1];
|
|
2799
|
+
if (typeof start === "number" && typeof end === "number") {
|
|
2800
|
+
return script.slice(0, start) + replacement + script.slice(end);
|
|
2801
|
+
}
|
|
2802
|
+
}
|
|
2803
|
+
return script;
|
|
2804
|
+
}
|
|
2805
|
+
export {
|
|
2806
|
+
PROPERTY_GROUPS,
|
|
2807
|
+
SPRING_PRESETS,
|
|
2808
|
+
SUPPORTED_EASES,
|
|
2809
|
+
SUPPORTED_PROPS,
|
|
2810
|
+
addAnimationToScript,
|
|
2811
|
+
addAnimationWithKeyframesToScript,
|
|
2812
|
+
addKeyframeToScript,
|
|
2813
|
+
addMotionPathPointInScript,
|
|
2814
|
+
addMotionPathToScript,
|
|
2815
|
+
classifyPropertyGroup,
|
|
2816
|
+
classifyTweenPropertyGroup,
|
|
2817
|
+
convertToKeyframesInScript,
|
|
2818
|
+
dedupePositionWritesInScript,
|
|
2819
|
+
generateSpringEaseData,
|
|
2820
|
+
getAnimationsForElementId,
|
|
2821
|
+
gsapAnimationsToKeyframes,
|
|
2822
|
+
isStudioHoldSet,
|
|
2823
|
+
keyframesToGsapAnimations,
|
|
2824
|
+
materializeKeyframesInScript,
|
|
2825
|
+
moveKeyframeInScript,
|
|
2826
|
+
parseGsapScript,
|
|
2827
|
+
removeAllKeyframesFromScript,
|
|
2828
|
+
removeAnimationFromScript,
|
|
2829
|
+
removeArcPathFromScript,
|
|
2830
|
+
removeKeyframeFromScript,
|
|
2831
|
+
removeMotionPathPointInScript,
|
|
2832
|
+
resizeKeyframedTweenInScript,
|
|
2833
|
+
scalePositionsInScript,
|
|
2834
|
+
serializeGsapAnimations,
|
|
2835
|
+
setArcPathInScript,
|
|
2836
|
+
shiftPositionsInScript,
|
|
2837
|
+
splitAnimationsInScript,
|
|
2838
|
+
splitIntoPropertyGroups,
|
|
2839
|
+
syncPositionHoldsBeforeKeyframes,
|
|
2840
|
+
unrollDynamicAnimations,
|
|
2841
|
+
updateAnimationInScript,
|
|
2842
|
+
updateArcSegmentInScript,
|
|
2843
|
+
updateKeyframeInScript,
|
|
2844
|
+
updateMotionPathPointInScript,
|
|
2845
|
+
validateCompositionGsap
|
|
2846
|
+
};
|