motiondesk-studio 0.0.0-stage → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +8 -0
- package/README.md +53 -2
- package/THIRD_PARTY_NOTICES.md +13 -0
- package/app/assets/ai-assistant-DOEK1wrr.js +138 -0
- package/app/assets/annual-report-C59pnbh2.js +147 -0
- package/app/assets/app-tour-B8525Qt1.js +164 -0
- package/app/assets/apps-DwnIwigQ.js +1 -0
- package/app/assets/arrows-_CCvumhN.js +1 -0
- package/app/assets/auto-CJsCPj1R.js +1 -0
- package/app/assets/badges-BPgMBVy0.js +1 -0
- package/app/assets/balloon-party-BDWzrF-Z.js +160 -0
- package/app/assets/beauty-DgeCsQdf.js +1 -0
- package/app/assets/boarding-pass-i17EemsZ.js +192 -0
- package/app/assets/business-BQslCr0i.js +1 -0
- package/app/assets/business-DfyVziqj.js +1 -0
- package/app/assets/catalog-Cdx5nbp0.js +1 -0
- package/app/assets/celebration-COCZTKjl.js +1 -0
- package/app/assets/celebrations-CkfTGLEK.js +1 -0
- package/app/assets/chalk-menu-CQSqwxNP.js +158 -0
- package/app/assets/claim-steps-BNFeoYYZ.js +180 -0
- package/app/assets/clinic-booking-CvQEpBWn.js +178 -0
- package/app/assets/community-BV13F-Wp.js +1 -0
- package/app/assets/concert-poster-iUOM-elw.js +189 -0
- package/app/assets/course-syllabus-CnM_03XP.js +164 -0
- package/app/assets/culture-DpL14_5r.js +1 -0
- package/app/assets/cyber-shield-B_6oatye.js +192 -0
- package/app/assets/data-DgES5FIF.js +1 -0
- package/app/assets/dev-hiring-code-Bg00S1Iz.js +138 -0
- package/app/assets/devices-D1500q8F.js +1 -0
- package/app/assets/donation-meter-C3wuRmFA.js +164 -0
- package/app/assets/editorial-mag-DsTVzQMx.js +180 -0
- package/app/assets/education-CGTOg3_0.js +1 -0
- package/app/assets/ev-charge-KaMIQd_s.js +218 -0
- package/app/assets/event-announce-cLmuvt45.js +147 -0
- package/app/assets/events-kZ6HshfK.js +1 -0
- package/app/assets/family-De56hVSo.js +1 -0
- package/app/assets/fashion-DbGAD96W.js +1 -0
- package/app/assets/finance-BUdlKAud.js +1 -0
- package/app/assets/finance-growth-CYgFE0RC.js +140 -0
- package/app/assets/fitness-rings-streak-Cp7n4zq_.js +141 -0
- package/app/assets/flash-sale-Tc0Jw34H.js +143 -0
- package/app/assets/flipclock-countdown-BkrU9ZhF.js +153 -0
- package/app/assets/floorplan-linedraw-B4ZwEDv3.js +192 -0
- package/app/assets/food-CiEyQAd1.js +1 -0
- package/app/assets/food-PijmcKM-.js +1 -0
- package/app/assets/gaming-DnzPj6Uv.js +1 -0
- package/app/assets/glass-product-CsUqplIf.js +139 -0
- package/app/assets/glossy-cosmetics-DBb-YonD.js +203 -0
- package/app/assets/gold-couture-e6c5nsVY.js +190 -0
- package/app/assets/gradient-blobs-Daiu9eFf.js +139 -0
- package/app/assets/graduation-day-vdz-kGI1.js +134 -0
- package/app/assets/headline-news-ticker-GgZ_nRXK.js +181 -0
- package/app/assets/health-CbyTqvSM.js +1 -0
- package/app/assets/health-DMeKWmDa.js +1 -0
- package/app/assets/hiring-team-Bia3GQaH.js +137 -0
- package/app/assets/holiday-greeting-B7TFl0_5.js +144 -0
- package/app/assets/holidays-BmXfhKdf.js +1 -0
- package/app/assets/hr-2i-f-S-M.js +1 -0
- package/app/assets/hyperframes-BM7eWgx2.js +1 -0
- package/app/assets/index-BlSoi5FK.css +1 -0
- package/app/assets/index-D3rEDfqX.js +290 -0
- package/app/assets/index-b2-CMdBrCiU.js +1 -0
- package/app/assets/index-b3-egAjkT9z.js +1 -0
- package/app/assets/index-b4-Cnj_xde0.js +1 -0
- package/app/assets/index-b5-CoZgwX8-.js +1 -0
- package/app/assets/iso-product-3d-DQT1lHDq.js +229 -0
- package/app/assets/itinerary-map-pins-BTX0ZebL.js +201 -0
- package/app/assets/key-handover-DuIj4oKe.js +171 -0
- package/app/assets/kids-BNwXKe4O.js +1 -0
- package/app/assets/kinetic-launch-D2rSnewM.js +161 -0
- package/app/assets/launch-DqkMfeFI.js +1 -0
- package/app/assets/legal-Caoeh9dp.js +1 -0
- package/app/assets/legal-trust-T01BmIDB.js +186 -0
- package/app/assets/level-up-CBXf6nj2.js +205 -0
- package/app/assets/logo-sting-Uf0nckUQ.js +106 -0
- package/app/assets/manifesto-quote-DCIONyzh.js +120 -0
- package/app/assets/match-day-p25bzqbq.js +146 -0
- package/app/assets/match-score-CSZ4Tx4B.js +210 -0
- package/app/assets/music-hbnVS8dK.js +1 -0
- package/app/assets/nature-Bj99iNsv.js +1 -0
- package/app/assets/neighborhood-map-BpbZiy-v.js +158 -0
- package/app/assets/neon-grid-Bo0xfsL6.js +159 -0
- package/app/assets/nonprofit-DK7XI33A.js +1 -0
- package/app/assets/objects-DD8bqyWR.js +1 -0
- package/app/assets/org-chart-hiring-tGX1UpiJ.js +161 -0
- package/app/assets/paper-collage-CK-XODvZ.js +181 -0
- package/app/assets/paw-adopt-D5hKgsaL.js +173 -0
- package/app/assets/people-l3GsDfAr.js +1 -0
- package/app/assets/pets-Dp8EeTjS.js +1 -0
- package/app/assets/playful-blocks-BGXW4vra.js +162 -0
- package/app/assets/podcast-waveform-promo-D-h_ydpJ.js +182 -0
- package/app/assets/premium-Cy680sWT.js +1 -0
- package/app/assets/price-grid-DbYGPlJt.js +176 -0
- package/app/assets/quote-carousel-bold-D5fpKgSS.js +143 -0
- package/app/assets/realestate-BXW-rsfP.js +1 -0
- package/app/assets/recipe-ingredients-B_bSw3x_.js +162 -0
- package/app/assets/retail-D-XWCWed.js +1 -0
- package/app/assets/retro-80s-CCZc9S6x.js +141 -0
- package/app/assets/roadmap-timeline-BpbNdfCr.js +164 -0
- package/app/assets/saas-dashboard-s-2gR3AN.js +195 -0
- package/app/assets/sale-wheel-24h-CsiOja2Z.js +153 -0
- package/app/assets/save-the-date-C6O8fH8f.js +141 -0
- package/app/assets/seasons-BFYc_klb.js +1 -0
- package/app/assets/services-DRPQcCXX.js +1 -0
- package/app/assets/shapes-AVMwC-FR.js +1 -0
- package/app/assets/social-CNpE0GKG.js +1 -0
- package/app/assets/split-wipe-before-after-Lg-NbF0V.js +198 -0
- package/app/assets/sports-DyBfpPm5.js +1 -0
- package/app/assets/stats-dashboard-CxxFtNfj.js +149 -0
- package/app/assets/stickers-J4NDCW2L.js +1 -0
- package/app/assets/stock-portfolio-DFpeHEjJ.js +174 -0
- package/app/assets/swiss-grid-jfcgySaJ.js +153 -0
- package/app/assets/tech-BaRjeFZ0.js +1 -0
- package/app/assets/tech-D-xc9pRv.js +1 -0
- package/app/assets/transport-Bolufhfq.js +1 -0
- package/app/assets/travel-DoqS5vPB.js +1 -0
- package/app/assets/travel-route-DUPXi7Qa.js +169 -0
- package/app/assets/tutorial-steps-Ep2JeqXu.js +160 -0
- package/app/assets/wallet-card-transactions-DtI9Usn9.js +188 -0
- package/app/assets/wedding-invite-BhgqMwO7.js +142 -0
- package/app/catalog/bank-previews/01-car-choice.webp +0 -0
- package/app/catalog/bank-previews/02-holiday-budget.webp +0 -0
- package/app/catalog/bank-previews/03-one-click.webp +0 -0
- package/app/catalog/bank-previews/04-career-course.webp +0 -0
- package/app/catalog/bank-previews/05-home-refresh.webp +0 -0
- package/app/catalog/bank-previews/06-summer-plans.webp +0 -0
- package/app/catalog/bank-previews/07-car-upgrade.webp +0 -0
- package/app/catalog/bank-previews/08-wedding-plan.webp +0 -0
- package/app/catalog/bank-previews/09-share-intro.webp +0 -0
- package/app/catalog/bank-previews/10-suspicious-message.webp +0 -0
- package/app/catalog/bank-previews/11-student-routine.webp +0 -0
- package/app/catalog/bank-previews/12-investing-first-step.webp +0 -0
- package/app/catalog/bank-previews/13-fomo.webp +0 -0
- package/app/catalog/bank-previews/14-market-timing.webp +0 -0
- package/app/catalog/bank-previews/15-investing-for-all.webp +0 -0
- package/app/catalog/bank-previews/16-two-paths.webp +0 -0
- package/app/catalog/bank-previews/17-small-business.webp +0 -0
- package/app/catalog/bank-previews/18-travel-forex.webp +0 -0
- package/app/catalog/bank-previews/19-mortgage-questions.webp +0 -0
- package/app/catalog/bank-previews/20-market-app.webp +0 -0
- package/app/catalog/enhanced-v2/01-revenue-quarter/config.motiondesk-config.json +54 -0
- package/app/catalog/enhanced-v2/01-revenue-quarter/poster.jpg +0 -0
- package/app/catalog/enhanced-v2/01-revenue-quarter/preview.mp4 +0 -0
- package/app/catalog/enhanced-v2/01-revenue-quarter/project.motiondesk.json +5127 -0
- package/app/catalog/enhanced-v2/02-daily-workout/config.motiondesk-config.json +54 -0
- package/app/catalog/enhanced-v2/02-daily-workout/poster.jpg +0 -0
- package/app/catalog/enhanced-v2/02-daily-workout/preview.mp4 +0 -0
- package/app/catalog/enhanced-v2/02-daily-workout/project.motiondesk.json +5747 -0
- package/app/catalog/enhanced-v2/03-italy-trip/config.motiondesk-config.json +44 -0
- package/app/catalog/enhanced-v2/03-italy-trip/poster.jpg +0 -0
- package/app/catalog/enhanced-v2/03-italy-trip/preview.mp4 +0 -0
- package/app/catalog/enhanced-v2/03-italy-trip/project.motiondesk.json +5139 -0
- package/app/catalog/enhanced-v2/04-smart-savings/config.motiondesk-config.json +41 -0
- package/app/catalog/enhanced-v2/04-smart-savings/poster.jpg +0 -0
- package/app/catalog/enhanced-v2/04-smart-savings/preview.mp4 +0 -0
- package/app/catalog/enhanced-v2/04-smart-savings/project.motiondesk.json +5322 -0
- package/app/catalog/enhanced-v2/05-weekly-challenge/config.motiondesk-config.json +45 -0
- package/app/catalog/enhanced-v2/05-weekly-challenge/poster.jpg +0 -0
- package/app/catalog/enhanced-v2/05-weekly-challenge/preview.mp4 +0 -0
- package/app/catalog/enhanced-v2/05-weekly-challenge/project.motiondesk.json +5442 -0
- package/app/catalog/enhanced-v2/06-flash-sale/config.motiondesk-config.json +42 -0
- package/app/catalog/enhanced-v2/06-flash-sale/poster.jpg +0 -0
- package/app/catalog/enhanced-v2/06-flash-sale/preview.mp4 +0 -0
- package/app/catalog/enhanced-v2/06-flash-sale/project.motiondesk.json +5616 -0
- package/app/catalog/enhanced-v2/07-flight-savings/config.motiondesk-config.json +43 -0
- package/app/catalog/enhanced-v2/07-flight-savings/poster.jpg +0 -0
- package/app/catalog/enhanced-v2/07-flight-savings/preview.mp4 +0 -0
- package/app/catalog/enhanced-v2/07-flight-savings/project.motiondesk.json +6319 -0
- package/app/catalog/enhanced-v2/08-team-dashboard/config.motiondesk-config.json +52 -0
- package/app/catalog/enhanced-v2/08-team-dashboard/poster.jpg +0 -0
- package/app/catalog/enhanced-v2/08-team-dashboard/preview.mp4 +0 -0
- package/app/catalog/enhanced-v2/08-team-dashboard/project.motiondesk.json +5327 -0
- package/app/catalog/showcase-v3/11-flow-finance/poster.jpg +0 -0
- package/app/catalog/showcase-v3/11-flow-finance/preview.mp4 +0 -0
- package/app/catalog/showcase-v3/11-flow-finance/project.motiondesk.json +5690 -0
- package/app/catalog/showcase-v3/12-pulse-training/poster.jpg +0 -0
- package/app/catalog/showcase-v3/12-pulse-training/preview.mp4 +0 -0
- package/app/catalog/showcase-v3/12-pulse-training/project.motiondesk.json +3643 -0
- package/app/catalog/showcase-v3/13-orbit-travel/poster.jpg +0 -0
- package/app/catalog/showcase-v3/13-orbit-travel/preview.mp4 +0 -0
- package/app/catalog/showcase-v3/13-orbit-travel/project.motiondesk.json +3939 -0
- package/app/catalog/showcase-v3/14-nova-product/config.motiondesk-config.json +163 -0
- package/app/catalog/showcase-v3/14-nova-product/poster.jpg +0 -0
- package/app/catalog/showcase-v3/14-nova-product/preview.mp4 +0 -0
- package/app/catalog/showcase-v3/14-nova-product/project.motiondesk.json +11196 -0
- package/app/catalog/showcase-v3/15-tempo-motion/config.motiondesk-config.json +122 -0
- package/app/catalog/showcase-v3/15-tempo-motion/poster.jpg +0 -0
- package/app/catalog/showcase-v3/15-tempo-motion/preview.mp4 +0 -0
- package/app/catalog/showcase-v3/15-tempo-motion/project.motiondesk.json +7424 -0
- package/app/catalog/showcase-v3/16-atlas-journey/config.motiondesk-config.json +132 -0
- package/app/catalog/showcase-v3/16-atlas-journey/poster.jpg +0 -0
- package/app/catalog/showcase-v3/16-atlas-journey/preview.mp4 +0 -0
- package/app/catalog/showcase-v3/16-atlas-journey/project.motiondesk.json +9257 -0
- package/app/catalog/showcase-v3/17-revenue-quarter/config.motiondesk-config.json +151 -0
- package/app/catalog/showcase-v3/17-revenue-quarter/poster.jpg +0 -0
- package/app/catalog/showcase-v3/17-revenue-quarter/preview.mp4 +0 -0
- package/app/catalog/showcase-v3/17-revenue-quarter/project.motiondesk.json +10473 -0
- package/app/catalog/showcase-v3/18-daily-workout/config.motiondesk-config.json +139 -0
- package/app/catalog/showcase-v3/18-daily-workout/poster.jpg +0 -0
- package/app/catalog/showcase-v3/18-daily-workout/preview.mp4 +0 -0
- package/app/catalog/showcase-v3/18-daily-workout/project.motiondesk.json +8656 -0
- package/app/catalog/showcase-v3/19-italy-trip/config.motiondesk-config.json +132 -0
- package/app/catalog/showcase-v3/19-italy-trip/poster.jpg +0 -0
- package/app/catalog/showcase-v3/19-italy-trip/preview.mp4 +0 -0
- package/app/catalog/showcase-v3/19-italy-trip/project.motiondesk.json +9690 -0
- package/app/catalog/showcase-v3/20-smart-savings/config.motiondesk-config.json +152 -0
- package/app/catalog/showcase-v3/20-smart-savings/poster.jpg +0 -0
- package/app/catalog/showcase-v3/20-smart-savings/preview.mp4 +0 -0
- package/app/catalog/showcase-v3/20-smart-savings/project.motiondesk.json +9770 -0
- package/app/catalog/showcase-v3/21-weekly-challenge/config.motiondesk-config.json +125 -0
- package/app/catalog/showcase-v3/21-weekly-challenge/poster.jpg +0 -0
- package/app/catalog/showcase-v3/21-weekly-challenge/preview.mp4 +0 -0
- package/app/catalog/showcase-v3/21-weekly-challenge/project.motiondesk.json +8404 -0
- package/app/catalog/showcase-v3/22-flash-sale/config.motiondesk-config.json +116 -0
- package/app/catalog/showcase-v3/22-flash-sale/poster.jpg +0 -0
- package/app/catalog/showcase-v3/22-flash-sale/preview.mp4 +0 -0
- package/app/catalog/showcase-v3/22-flash-sale/project.motiondesk.json +7482 -0
- package/app/catalog/showcase-v3/23-flight-savings/config.motiondesk-config.json +139 -0
- package/app/catalog/showcase-v3/23-flight-savings/poster.jpg +0 -0
- package/app/catalog/showcase-v3/23-flight-savings/preview.mp4 +0 -0
- package/app/catalog/showcase-v3/23-flight-savings/project.motiondesk.json +9205 -0
- package/app/catalog/showcase-v3/24-team-dashboard/config.motiondesk-config.json +155 -0
- package/app/catalog/showcase-v3/24-team-dashboard/poster.jpg +0 -0
- package/app/catalog/showcase-v3/24-team-dashboard/preview.mp4 +0 -0
- package/app/catalog/showcase-v3/24-team-dashboard/project.motiondesk.json +10735 -0
- package/app/catalog/v4/bank-01-car-choice/config.motiondesk-config.json +86 -0
- package/app/catalog/v4/bank-01-car-choice/poster.webp +0 -0
- package/app/catalog/v4/bank-01-car-choice/project.motiondesk.json +6962 -0
- package/app/catalog/v4/bank-02-holiday-budget/config.motiondesk-config.json +98 -0
- package/app/catalog/v4/bank-02-holiday-budget/poster.webp +0 -0
- package/app/catalog/v4/bank-02-holiday-budget/project.motiondesk.json +7242 -0
- package/app/catalog/v4/bank-03-one-click/config.motiondesk-config.json +97 -0
- package/app/catalog/v4/bank-03-one-click/poster.webp +0 -0
- package/app/catalog/v4/bank-03-one-click/project.motiondesk.json +6789 -0
- package/app/catalog/v4/bank-04-career-course/config.motiondesk-config.json +88 -0
- package/app/catalog/v4/bank-04-career-course/poster.webp +0 -0
- package/app/catalog/v4/bank-04-career-course/project.motiondesk.json +6514 -0
- package/app/catalog/v4/bank-05-five-years-new-word/config.motiondesk-config.json +86 -0
- package/app/catalog/v4/bank-05-five-years-new-word/poster.webp +0 -0
- package/app/catalog/v4/bank-05-five-years-new-word/project.motiondesk.json +5865 -0
- package/app/catalog/v4/bank-06-home-upgrade/config.motiondesk-config.json +88 -0
- package/app/catalog/v4/bank-06-home-upgrade/poster.webp +0 -0
- package/app/catalog/v4/bank-06-home-upgrade/project.motiondesk.json +7187 -0
- package/app/catalog/v4/bank-07-car-upgrade/config.motiondesk-config.json +87 -0
- package/app/catalog/v4/bank-07-car-upgrade/poster.webp +0 -0
- package/app/catalog/v4/bank-07-car-upgrade/project.motiondesk.json +6018 -0
- package/app/catalog/v4/bank-08-summer-dollar/config.motiondesk-config.json +85 -0
- package/app/catalog/v4/bank-08-summer-dollar/poster.webp +0 -0
- package/app/catalog/v4/bank-08-summer-dollar/project.motiondesk.json +6291 -0
- package/app/catalog/v4/bank-09-wedding/config.motiondesk-config.json +88 -0
- package/app/catalog/v4/bank-09-wedding/poster.webp +0 -0
- package/app/catalog/v4/bank-09-wedding/project.motiondesk.json +6517 -0
- package/app/catalog/v4/bank-10-family-dinner-pay/config.motiondesk-config.json +100 -0
- package/app/catalog/v4/bank-10-family-dinner-pay/poster.webp +0 -0
- package/app/catalog/v4/bank-10-family-dinner-pay/project.motiondesk.json +7053 -0
- package/app/catalog/v4/bank-11-youth-pitch-creator/config.motiondesk-config.json +100 -0
- package/app/catalog/v4/bank-11-youth-pitch-creator/poster.webp +0 -0
- package/app/catalog/v4/bank-11-youth-pitch-creator/project.motiondesk.json +6820 -0
- package/app/catalog/v4/bank-12-gift-shares/config.motiondesk-config.json +90 -0
- package/app/catalog/v4/bank-12-gift-shares/poster.webp +0 -0
- package/app/catalog/v4/bank-12-gift-shares/project.motiondesk.json +6025 -0
- package/app/catalog/v4/bank-13-suspicious-call/config.motiondesk-config.json +96 -0
- package/app/catalog/v4/bank-13-suspicious-call/poster.webp +0 -0
- package/app/catalog/v4/bank-13-suspicious-call/project.motiondesk.json +6734 -0
- package/app/catalog/v4/bank-14-urgent-message/config.motiondesk-config.json +89 -0
- package/app/catalog/v4/bank-14-urgent-message/poster.webp +0 -0
- package/app/catalog/v4/bank-14-urgent-message/project.motiondesk.json +6724 -0
- package/app/catalog/v4/bank-15-olympic-excellence/config.motiondesk-config.json +88 -0
- package/app/catalog/v4/bank-15-olympic-excellence/poster.webp +0 -0
- package/app/catalog/v4/bank-15-olympic-excellence/project.motiondesk.json +6431 -0
- package/app/catalog/v4/bank-16-savings-pocket/config.motiondesk-config.json +97 -0
- package/app/catalog/v4/bank-16-savings-pocket/poster.webp +0 -0
- package/app/catalog/v4/bank-16-savings-pocket/project.motiondesk.json +6628 -0
- package/app/catalog/v4/bank-17-students/config.motiondesk-config.json +91 -0
- package/app/catalog/v4/bank-17-students/poster.webp +0 -0
- package/app/catalog/v4/bank-17-students/project.motiondesk.json +6629 -0
- package/app/catalog/v4/bank-18-phone-phobia/config.motiondesk-config.json +86 -0
- package/app/catalog/v4/bank-18-phone-phobia/poster.webp +0 -0
- package/app/catalog/v4/bank-18-phone-phobia/project.motiondesk.json +6140 -0
- package/app/catalog/v4/bank-19-financial-fomo/config.motiondesk-config.json +91 -0
- package/app/catalog/v4/bank-19-financial-fomo/poster.webp +0 -0
- package/app/catalog/v4/bank-19-financial-fomo/project.motiondesk.json +7189 -0
- package/app/catalog/v4/bank-20-start-investing/config.motiondesk-config.json +95 -0
- package/app/catalog/v4/bank-20-start-investing/poster.webp +0 -0
- package/app/catalog/v4/bank-20-start-investing/project.motiondesk.json +7149 -0
- package/app/catalog/v4/bank-21-market-timing/config.motiondesk-config.json +95 -0
- package/app/catalog/v4/bank-21-market-timing/poster.webp +0 -0
- package/app/catalog/v4/bank-21-market-timing/project.motiondesk.json +6166 -0
- package/app/catalog/v4/bank-22-market-vs-realestate/config.motiondesk-config.json +88 -0
- package/app/catalog/v4/bank-22-market-vs-realestate/poster.webp +0 -0
- package/app/catalog/v4/bank-22-market-vs-realestate/project.motiondesk.json +7698 -0
- package/app/catalog/v4/bank-23-investing-for-all/config.motiondesk-config.json +92 -0
- package/app/catalog/v4/bank-23-investing-for-all/poster.webp +0 -0
- package/app/catalog/v4/bank-23-investing-for-all/project.motiondesk.json +6150 -0
- package/app/catalog/v4/bank-24-business-loan/config.motiondesk-config.json +85 -0
- package/app/catalog/v4/bank-24-business-loan/poster.webp +0 -0
- package/app/catalog/v4/bank-24-business-loan/project.motiondesk.json +6804 -0
- package/app/catalog/v4/bank-25-open-door/config.motiondesk-config.json +84 -0
- package/app/catalog/v4/bank-25-open-door/poster.webp +0 -0
- package/app/catalog/v4/bank-25-open-door/project.motiondesk.json +5976 -0
- package/app/catalog/v4/bank-26-first-card-challenge/config.motiondesk-config.json +84 -0
- package/app/catalog/v4/bank-26-first-card-challenge/poster.webp +0 -0
- package/app/catalog/v4/bank-26-first-card-challenge/project.motiondesk.json +6167 -0
- package/app/catalog/v4/bank-27-holiday-trip/config.motiondesk-config.json +85 -0
- package/app/catalog/v4/bank-27-holiday-trip/poster.webp +0 -0
- package/app/catalog/v4/bank-27-holiday-trip/project.motiondesk.json +6291 -0
- package/app/catalog/v4/bank-28-renew-home/config.motiondesk-config.json +87 -0
- package/app/catalog/v4/bank-28-renew-home/poster.webp +0 -0
- package/app/catalog/v4/bank-28-renew-home/project.motiondesk.json +6489 -0
- package/app/catalog/v4/bank-29-fastest-way-to-pay/config.motiondesk-config.json +98 -0
- package/app/catalog/v4/bank-29-fastest-way-to-pay/poster.webp +0 -0
- package/app/catalog/v4/bank-29-fastest-way-to-pay/project.motiondesk.json +6915 -0
- package/app/catalog/v4/bank-30-forex-terminal/config.motiondesk-config.json +103 -0
- package/app/catalog/v4/bank-30-forex-terminal/poster.webp +0 -0
- package/app/catalog/v4/bank-30-forex-terminal/project.motiondesk.json +6997 -0
- package/app/catalog/v4/bank-31-youth-campaign-brief/config.motiondesk-config.json +103 -0
- package/app/catalog/v4/bank-31-youth-campaign-brief/poster.webp +0 -0
- package/app/catalog/v4/bank-31-youth-campaign-brief/project.motiondesk.json +7136 -0
- package/app/catalog/v4/bank-32-dream-vacation/config.motiondesk-config.json +87 -0
- package/app/catalog/v4/bank-32-dream-vacation/poster.webp +0 -0
- package/app/catalog/v4/bank-32-dream-vacation/project.motiondesk.json +6531 -0
- package/app/catalog/v4/bank-33-mortgage-advice/config.motiondesk-config.json +87 -0
- package/app/catalog/v4/bank-33-mortgage-advice/poster.webp +0 -0
- package/app/catalog/v4/bank-33-mortgage-advice/project.motiondesk.json +6767 -0
- package/app/catalog/v4/bank-34-who-are-you-saver/config.motiondesk-config.json +97 -0
- package/app/catalog/v4/bank-34-who-are-you-saver/poster.webp +0 -0
- package/app/catalog/v4/bank-34-who-are-you-saver/project.motiondesk.json +6309 -0
- package/app/catalog/v4/bank-35-strange-calls/config.motiondesk-config.json +85 -0
- package/app/catalog/v4/bank-35-strange-calls/poster.webp +0 -0
- package/app/catalog/v4/bank-35-strange-calls/project.motiondesk.json +7034 -0
- package/app/catalog/v4/bank-36-one-shekel-flight/config.motiondesk-config.json +91 -0
- package/app/catalog/v4/bank-36-one-shekel-flight/poster.webp +0 -0
- package/app/catalog/v4/bank-36-one-shekel-flight/project.motiondesk.json +6364 -0
- package/app/catalog/v4/bank-37-street-quiz-pay/config.motiondesk-config.json +81 -0
- package/app/catalog/v4/bank-37-street-quiz-pay/poster.webp +0 -0
- package/app/catalog/v4/bank-37-street-quiz-pay/project.motiondesk.json +6466 -0
- package/app/catalog/v4/bank-38-pension-compare/config.motiondesk-config.json +92 -0
- package/app/catalog/v4/bank-38-pension-compare/poster.webp +0 -0
- package/app/catalog/v4/bank-38-pension-compare/project.motiondesk.json +6752 -0
- package/app/catalog/v4/bank-39-new-look-app/config.motiondesk-config.json +103 -0
- package/app/catalog/v4/bank-39-new-look-app/poster.webp +0 -0
- package/app/catalog/v4/bank-39-new-look-app/project.motiondesk.json +6954 -0
- package/app/catalog/v4/bank-40-interest-pocket/config.motiondesk-config.json +83 -0
- package/app/catalog/v4/bank-40-interest-pocket/poster.webp +0 -0
- package/app/catalog/v4/bank-40-interest-pocket/project.motiondesk.json +5783 -0
- package/app/catalog/v4/bank-41-young-telenovela/config.motiondesk-config.json +95 -0
- package/app/catalog/v4/bank-41-young-telenovela/poster.webp +0 -0
- package/app/catalog/v4/bank-41-young-telenovela/project.motiondesk.json +5967 -0
- package/app/catalog/v4/bank-42-market-app/config.motiondesk-config.json +103 -0
- package/app/catalog/v4/bank-42-market-app/poster.webp +0 -0
- package/app/catalog/v4/bank-42-market-app/project.motiondesk.json +6766 -0
- package/app/catalog/v4/bank-43-passover-sites/config.motiondesk-config.json +92 -0
- package/app/catalog/v4/bank-43-passover-sites/poster.webp +0 -0
- package/app/catalog/v4/bank-43-passover-sites/project.motiondesk.json +7173 -0
- package/app/catalog/v4/bank-44-end-of-excuses/config.motiondesk-config.json +93 -0
- package/app/catalog/v4/bank-44-end-of-excuses/poster.webp +0 -0
- package/app/catalog/v4/bank-44-end-of-excuses/project.motiondesk.json +6010 -0
- package/app/catalog/v4/bank-45-good-reasons/config.motiondesk-config.json +90 -0
- package/app/catalog/v4/bank-45-good-reasons/poster.webp +0 -0
- package/app/catalog/v4/bank-45-good-reasons/project.motiondesk.json +7122 -0
- package/app/catalog/v4/bank-46-mortgage-hotline/config.motiondesk-config.json +99 -0
- package/app/catalog/v4/bank-46-mortgage-hotline/poster.webp +0 -0
- package/app/catalog/v4/bank-46-mortgage-hotline/project.motiondesk.json +6923 -0
- package/app/catalog/v4/bank-47-financial-growth-center/config.motiondesk-config.json +84 -0
- package/app/catalog/v4/bank-47-financial-growth-center/poster.webp +0 -0
- package/app/catalog/v4/bank-47-financial-growth-center/project.motiondesk.json +6424 -0
- package/app/catalog/v4/bank-48-judo-grand-prix/config.motiondesk-config.json +88 -0
- package/app/catalog/v4/bank-48-judo-grand-prix/poster.webp +0 -0
- package/app/catalog/v4/bank-48-judo-grand-prix/project.motiondesk.json +6335 -0
- package/app/catalog/v4/bank-49-currency-convert/config.motiondesk-config.json +98 -0
- package/app/catalog/v4/bank-49-currency-convert/poster.webp +0 -0
- package/app/catalog/v4/bank-49-currency-convert/project.motiondesk.json +7036 -0
- package/app/catalog/v4/bank-50-salary-young/config.motiondesk-config.json +95 -0
- package/app/catalog/v4/bank-50-salary-young/poster.webp +0 -0
- package/app/catalog/v4/bank-50-salary-young/project.motiondesk.json +6414 -0
- package/app/catalog/v4/v4-onboarding-beats-16x9/config.motiondesk-config.json +162 -0
- package/app/catalog/v4/v4-onboarding-beats-16x9/poster.webp +0 -0
- package/app/catalog/v4/v4-onboarding-beats-16x9/project.motiondesk.json +9796 -0
- package/app/catalog/v4/v4-savings-goal-9x16/config.motiondesk-config.json +151 -0
- package/app/catalog/v4/v4-savings-goal-9x16/poster.webp +0 -0
- package/app/catalog/v4/v4-savings-goal-9x16/project.motiondesk.json +11847 -0
- package/app/catalog/v4/v4-trip-planner-1x1/config.motiondesk-config.json +137 -0
- package/app/catalog/v4/v4-trip-planner-1x1/poster.webp +0 -0
- package/app/catalog/v4/v4-trip-planner-1x1/project.motiondesk.json +10797 -0
- package/app/catalog/v4/v4-wallet-launch-16x9/config.motiondesk-config.json +172 -0
- package/app/catalog/v4/v4-wallet-launch-16x9/poster.webp +0 -0
- package/app/catalog/v4/v4-wallet-launch-16x9/project.motiondesk.json +14270 -0
- package/app/fonts/heebo-hebrew-400-normal.woff2 +0 -0
- package/app/fonts/heebo-hebrew-700-normal.woff2 +0 -0
- package/app/fonts/heebo-latin-400-normal.woff2 +0 -0
- package/app/fonts/heebo-latin-700-normal.woff2 +0 -0
- package/app/fonts/motiondesk-symbols.ttf +0 -0
- package/app/fonts/noto-sans-math-OFL.txt +93 -0
- package/app/index.html +15 -0
- package/app/studio-hf/fonts/heebo-hebrew-400-normal.woff2 +0 -0
- package/app/studio-hf/fonts/heebo-hebrew-700-normal.woff2 +0 -0
- package/app/studio-hf/fonts/heebo-latin-400-normal.woff2 +0 -0
- package/app/studio-hf/fonts/heebo-latin-700-normal.woff2 +0 -0
- package/app/studio-hf/frame.html +21 -0
- package/app/studio-hf/vendor/gsap.min.js +11 -0
- package/bin/motiondesk-studio.mjs +244 -0
- package/lib/catalog/hyperframes/ai-assistant.html +137 -0
- package/lib/catalog/hyperframes/annual-report.html +146 -0
- package/lib/catalog/hyperframes/app-tour.html +163 -0
- package/lib/catalog/hyperframes/balloon-party.html +159 -0
- package/lib/catalog/hyperframes/boarding-pass.html +191 -0
- package/lib/catalog/hyperframes/chalk-menu.html +157 -0
- package/lib/catalog/hyperframes/claim-steps.html +179 -0
- package/lib/catalog/hyperframes/clinic-booking.html +177 -0
- package/lib/catalog/hyperframes/concert-poster.html +188 -0
- package/lib/catalog/hyperframes/course-syllabus.html +163 -0
- package/lib/catalog/hyperframes/cyber-shield.html +191 -0
- package/lib/catalog/hyperframes/dev-hiring-code.html +137 -0
- package/lib/catalog/hyperframes/donation-meter.html +163 -0
- package/lib/catalog/hyperframes/editorial-mag.html +179 -0
- package/lib/catalog/hyperframes/ev-charge.html +217 -0
- package/lib/catalog/hyperframes/event-announce.html +146 -0
- package/lib/catalog/hyperframes/finance-growth.html +139 -0
- package/lib/catalog/hyperframes/fitness-rings-streak.html +140 -0
- package/lib/catalog/hyperframes/flash-sale.html +142 -0
- package/lib/catalog/hyperframes/flipclock-countdown.html +152 -0
- package/lib/catalog/hyperframes/floorplan-linedraw.html +191 -0
- package/lib/catalog/hyperframes/glass-product.html +138 -0
- package/lib/catalog/hyperframes/glossy-cosmetics.html +202 -0
- package/lib/catalog/hyperframes/gold-couture.html +189 -0
- package/lib/catalog/hyperframes/gradient-blobs.html +138 -0
- package/lib/catalog/hyperframes/graduation-day.html +133 -0
- package/lib/catalog/hyperframes/headline-news-ticker.html +180 -0
- package/lib/catalog/hyperframes/hiring-team.html +136 -0
- package/lib/catalog/hyperframes/holiday-greeting.html +143 -0
- package/lib/catalog/hyperframes/index-b2.json +194 -0
- package/lib/catalog/hyperframes/index-b3.json +194 -0
- package/lib/catalog/hyperframes/index-b4.json +162 -0
- package/lib/catalog/hyperframes/index-b5.json +130 -0
- package/lib/catalog/hyperframes/index.json +322 -0
- package/lib/catalog/hyperframes/iso-product-3d.html +228 -0
- package/lib/catalog/hyperframes/itinerary-map-pins.html +200 -0
- package/lib/catalog/hyperframes/key-handover.html +170 -0
- package/lib/catalog/hyperframes/kinetic-launch.html +160 -0
- package/lib/catalog/hyperframes/legal-trust.html +185 -0
- package/lib/catalog/hyperframes/level-up.html +204 -0
- package/lib/catalog/hyperframes/logo-sting.html +105 -0
- package/lib/catalog/hyperframes/manifesto-quote.html +119 -0
- package/lib/catalog/hyperframes/match-day.html +145 -0
- package/lib/catalog/hyperframes/match-score.html +209 -0
- package/lib/catalog/hyperframes/neighborhood-map.html +157 -0
- package/lib/catalog/hyperframes/neon-grid.html +158 -0
- package/lib/catalog/hyperframes/org-chart-hiring.html +160 -0
- package/lib/catalog/hyperframes/paper-collage.html +180 -0
- package/lib/catalog/hyperframes/paw-adopt.html +172 -0
- package/lib/catalog/hyperframes/playful-blocks.html +161 -0
- package/lib/catalog/hyperframes/podcast-waveform-promo.html +181 -0
- package/lib/catalog/hyperframes/price-grid.html +175 -0
- package/lib/catalog/hyperframes/quote-carousel-bold.html +142 -0
- package/lib/catalog/hyperframes/recipe-ingredients.html +161 -0
- package/lib/catalog/hyperframes/retro-80s.html +140 -0
- package/lib/catalog/hyperframes/roadmap-timeline.html +163 -0
- package/lib/catalog/hyperframes/saas-dashboard.html +194 -0
- package/lib/catalog/hyperframes/sale-wheel-24h.html +152 -0
- package/lib/catalog/hyperframes/save-the-date.html +140 -0
- package/lib/catalog/hyperframes/split-wipe-before-after.html +197 -0
- package/lib/catalog/hyperframes/stats-dashboard.html +148 -0
- package/lib/catalog/hyperframes/stock-portfolio.html +173 -0
- package/lib/catalog/hyperframes/swiss-grid.html +152 -0
- package/lib/catalog/hyperframes/travel-route.html +168 -0
- package/lib/catalog/hyperframes/tutorial-steps.html +159 -0
- package/lib/catalog/hyperframes/wallet-card-transactions.html +187 -0
- package/lib/catalog/hyperframes/wedding-invite.html +141 -0
- package/lib/catalog/studio/apps.json +2134 -0
- package/lib/catalog/studio/auto.json +2019 -0
- package/lib/catalog/studio/beauty.json +1630 -0
- package/lib/catalog/studio/business.json +2064 -0
- package/lib/catalog/studio/celebrations.json +2142 -0
- package/lib/catalog/studio/community.json +1926 -0
- package/lib/catalog/studio/culture.json +2156 -0
- package/lib/catalog/studio/data.json +1934 -0
- package/lib/catalog/studio/education.json +1914 -0
- package/lib/catalog/studio/events.json +1921 -0
- package/lib/catalog/studio/family.json +2159 -0
- package/lib/catalog/studio/fashion.json +1958 -0
- package/lib/catalog/studio/finance.json +1922 -0
- package/lib/catalog/studio/food.json +2128 -0
- package/lib/catalog/studio/gaming.json +1756 -0
- package/lib/catalog/studio/health.json +1934 -0
- package/lib/catalog/studio/hr.json +1860 -0
- package/lib/catalog/studio/kids.json +1697 -0
- package/lib/catalog/studio/launch.json +2161 -0
- package/lib/catalog/studio/legal.json +1732 -0
- package/lib/catalog/studio/music.json +1721 -0
- package/lib/catalog/studio/nonprofit.json +1665 -0
- package/lib/catalog/studio/pets.json +2196 -0
- package/lib/catalog/studio/premium.json +5577 -0
- package/lib/catalog/studio/realestate.json +2018 -0
- package/lib/catalog/studio/retail.json +1959 -0
- package/lib/catalog/studio/services.json +2154 -0
- package/lib/catalog/studio/social.json +2004 -0
- package/lib/catalog/studio/sports.json +1999 -0
- package/lib/catalog/studio/tech.json +2124 -0
- package/lib/catalog/studio/travel.json +1966 -0
- package/lib/core-v4.cjs +4897 -0
- package/lib/core.cjs +4223 -0
- package/lib/motion-blur.cjs +36 -0
- package/lib/studio.cjs +4419 -0
- package/lib/vercel-render.mjs +494 -0
- package/lib/vercel-source.cjs +88 -0
- package/package.json +16 -4
package/lib/core.cjs
ADDED
|
@@ -0,0 +1,4223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/core/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
SOURCE_ADAPTER_DEFINITIONS: () => SOURCE_ADAPTER_DEFINITIONS,
|
|
24
|
+
analyzeSource: () => analyzeSource,
|
|
25
|
+
analyzeSourceAdapter: () => analyzeSourceAdapter,
|
|
26
|
+
animateMotif: () => animateMotif,
|
|
27
|
+
annotateSourcePreview: () => annotateSourcePreview,
|
|
28
|
+
applySourceEdits: () => applySourceEdits,
|
|
29
|
+
assertProject: () => assertProject,
|
|
30
|
+
cameraStyle: () => cameraStyle,
|
|
31
|
+
commitProject: () => commitProject,
|
|
32
|
+
compileProjectHtml: () => compileProjectHtml,
|
|
33
|
+
componentTypes: () => componentTypes,
|
|
34
|
+
componentTypesV3: () => componentTypesV3,
|
|
35
|
+
configToProject: () => configToProject,
|
|
36
|
+
configV2ToProject: () => configV2ToProject,
|
|
37
|
+
configV3Backgrounds: () => configV3Backgrounds,
|
|
38
|
+
configV3Cameras: () => configV3Cameras,
|
|
39
|
+
configV3Energies: () => configV3Energies,
|
|
40
|
+
configV3ThemePalettes: () => configV3ThemePalettes,
|
|
41
|
+
configV3Themes: () => configV3Themes,
|
|
42
|
+
configV3ToProject: () => configV3ToProject,
|
|
43
|
+
configV3Transitions: () => configV3Transitions,
|
|
44
|
+
configV3Variants: () => configV3Variants,
|
|
45
|
+
contrastRatio: () => contrastRatio,
|
|
46
|
+
contrastText: () => contrastText,
|
|
47
|
+
createLayer: () => createLayer,
|
|
48
|
+
createMediaRenderPlan: () => createMediaRenderPlan,
|
|
49
|
+
createProject: () => createProject,
|
|
50
|
+
createScene: () => createScene,
|
|
51
|
+
duplicateScene: () => duplicateScene,
|
|
52
|
+
escapeHtml: () => escapeHtml,
|
|
53
|
+
evaluateLayer: () => evaluateLayer,
|
|
54
|
+
flight: () => flight,
|
|
55
|
+
importHtmlSource: () => importHtmlSource,
|
|
56
|
+
importStructuredHtml: () => importStructuredHtml,
|
|
57
|
+
isLocalAsset: () => isLocalAsset,
|
|
58
|
+
layerStyle: () => layerStyle,
|
|
59
|
+
migrateProject: () => migrateProject,
|
|
60
|
+
moveScene: () => moveScene,
|
|
61
|
+
newId: () => newId,
|
|
62
|
+
parseMotionConfig: () => parseMotionConfig,
|
|
63
|
+
parseMotionConfigV2: () => parseMotionConfigV2,
|
|
64
|
+
parseMotionConfigV3: () => parseMotionConfigV3,
|
|
65
|
+
parseProject: () => parseProject,
|
|
66
|
+
point: () => point,
|
|
67
|
+
projectDuration: () => projectDuration,
|
|
68
|
+
projectWarnings: () => projectWarnings,
|
|
69
|
+
pulse: () => pulse,
|
|
70
|
+
rebuildConfigV3Scene: () => rebuildConfigV3Scene,
|
|
71
|
+
removeScene: () => removeScene,
|
|
72
|
+
repeaterLayers: () => repeaterLayers,
|
|
73
|
+
sceneAtTime: () => sceneAtTime,
|
|
74
|
+
sceneStyle: () => sceneStyle,
|
|
75
|
+
serializeProject: () => serializeProject,
|
|
76
|
+
sourceFingerprint: () => sourceFingerprint,
|
|
77
|
+
sourcePreviewHtml: () => sourcePreviewHtml,
|
|
78
|
+
textLineStyle: () => textLineStyle,
|
|
79
|
+
textUnitStyle: () => textUnitStyle,
|
|
80
|
+
updateSourceText: () => updateSourceText,
|
|
81
|
+
upgradeConfigV2ToV3: () => upgradeConfigV2ToV3,
|
|
82
|
+
validateProject: () => validateProject,
|
|
83
|
+
visualThemes: () => visualThemes
|
|
84
|
+
});
|
|
85
|
+
module.exports = __toCommonJS(index_exports);
|
|
86
|
+
|
|
87
|
+
// src/core/motion.ts
|
|
88
|
+
function evaluateLayer(layer2, localTime, context = {}) {
|
|
89
|
+
const clamp = (value) => Math.max(0, Math.min(1, value));
|
|
90
|
+
const ease = (p, name = "smooth", seconds = 1) => {
|
|
91
|
+
const t = Math.max(0, Math.min(1, p));
|
|
92
|
+
if (Array.isArray(name)) {
|
|
93
|
+
const [x1, y1, x2, y2] = name;
|
|
94
|
+
const curve = (u, a, b) => 3 * (1 - u) * (1 - u) * u * a + 3 * (1 - u) * u * u * b + u * u * u;
|
|
95
|
+
let lo = 0, hi = 1;
|
|
96
|
+
for (let i = 0; i < 24; i++) {
|
|
97
|
+
const mid = (lo + hi) / 2;
|
|
98
|
+
if (curve(mid, x1, x2) < t) lo = mid;
|
|
99
|
+
else hi = mid;
|
|
100
|
+
}
|
|
101
|
+
return t === 0 || t === 1 ? t : curve((lo + hi) / 2, y1, y2);
|
|
102
|
+
}
|
|
103
|
+
if (typeof name === "object") {
|
|
104
|
+
const { stiffness: k, damping: c, mass: m } = name, w = Math.sqrt(k / m), z = c / (2 * Math.sqrt(k * m));
|
|
105
|
+
const response = (s) => {
|
|
106
|
+
if (z < 1 - 1e-6) {
|
|
107
|
+
const wd = w * Math.sqrt(1 - z * z);
|
|
108
|
+
return 1 - Math.exp(-z * w * s) * (Math.cos(wd * s) + z * w / wd * Math.sin(wd * s));
|
|
109
|
+
}
|
|
110
|
+
if (z <= 1 + 1e-6) return 1 - Math.exp(-w * s) * (1 + w * s);
|
|
111
|
+
const root = Math.sqrt(z * z - 1), r1 = -w / (z + root), r2 = -w * (z + root);
|
|
112
|
+
return 1 - (r2 * Math.exp(r1 * s) - r1 * Math.exp(r2 * s)) / (r2 - r1);
|
|
113
|
+
};
|
|
114
|
+
const end = response(Math.max(1e-3, seconds));
|
|
115
|
+
return t === 0 || t === 1 ? t : response(t * Math.max(1e-3, seconds)) + (1 - end) * t * t * (3 - 2 * t);
|
|
116
|
+
}
|
|
117
|
+
switch (name) {
|
|
118
|
+
case "hold":
|
|
119
|
+
return t === 1 ? 1 : 0;
|
|
120
|
+
case "linear":
|
|
121
|
+
return t;
|
|
122
|
+
case "ease-in":
|
|
123
|
+
return t * t * t;
|
|
124
|
+
case "ease-out":
|
|
125
|
+
return 1 - (1 - t) ** 3;
|
|
126
|
+
case "ease-in-out":
|
|
127
|
+
return t < 0.5 ? 4 * t ** 3 : 1 - (-2 * t + 2) ** 3 / 2;
|
|
128
|
+
case "back":
|
|
129
|
+
return 1 + 2.70158 * (t - 1) ** 3 + 1.70158 * (t - 1) ** 2;
|
|
130
|
+
case "elastic":
|
|
131
|
+
return t === 0 || t === 1 ? t : 2 ** (-10 * t) * Math.sin((t * 10 - 0.75) * 2 * Math.PI / 3) + 1;
|
|
132
|
+
default:
|
|
133
|
+
return t * t * (3 - 2 * t);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
const elapsed = localTime - layer2.start;
|
|
137
|
+
const hash = (seed, n) => {
|
|
138
|
+
let x = seed ^ n * 374761393 | 0;
|
|
139
|
+
x = Math.imul(x ^ x >>> 13, 1274126177);
|
|
140
|
+
return ((x ^ x >>> 16) >>> 0) / 4294967296;
|
|
141
|
+
};
|
|
142
|
+
const nearestBeat = (t) => context.beats?.length ? context.beats.reduce((a, b) => Math.abs(b - t) < Math.abs(a - t) ? b : a) : t;
|
|
143
|
+
const origin = (context.sceneStart ?? 0) + layer2.start;
|
|
144
|
+
const clipMix = (a, b, u) => {
|
|
145
|
+
if (!a && !b) return void 0;
|
|
146
|
+
const clear = (m) => m.type === "circle" ? { type: "circle", radius: 150, x: m.x, y: m.y } : { type: "inset", top: 0, right: 0, bottom: 0, left: 0 };
|
|
147
|
+
a = a ?? clear(b);
|
|
148
|
+
b = b ?? clear(a);
|
|
149
|
+
if (a.type !== b.type) return u < 1 ? a : b;
|
|
150
|
+
const mix2 = (x, y) => x + (y - x) * clamp(u);
|
|
151
|
+
if (a.type === "circle" && b.type === "circle") return { type: "circle", radius: mix2(a.radius, b.radius), x: mix2(a.x, b.x), y: mix2(a.y, b.y) };
|
|
152
|
+
if (a.type === "inset" && b.type === "inset") return { type: "inset", top: mix2(a.top, b.top), right: mix2(a.right, b.right), bottom: mix2(a.bottom, b.bottom), left: mix2(a.left, b.left) };
|
|
153
|
+
return b;
|
|
154
|
+
};
|
|
155
|
+
const colorMix = (a, b, u) => {
|
|
156
|
+
if (a === void 0 && b === void 0) return void 0;
|
|
157
|
+
a = a ?? b;
|
|
158
|
+
b = b ?? a;
|
|
159
|
+
const expand = (c) => c.length === 4 ? "#" + c.slice(1).split("").map((x) => x + x).join("") : c;
|
|
160
|
+
const aa = expand(a), bb = expand(b);
|
|
161
|
+
return "#" + [1, 3, 5].map((i) => Math.round(parseInt(aa.slice(i, i + 2), 16) + (parseInt(bb.slice(i, i + 2), 16) - parseInt(aa.slice(i, i + 2), 16)) * clamp(u)).toString(16).padStart(2, "0")).join("");
|
|
162
|
+
};
|
|
163
|
+
const formatValue = (value) => (layer2.countPrefix ?? "") + value.toLocaleString("he-IL", { minimumFractionDigits: layer2.countDecimals ?? 0, maximumFractionDigits: layer2.countDecimals ?? 0, useGrouping: layer2.countThousands ?? true }) + (layer2.countSuffix ?? "");
|
|
164
|
+
const duration = Math.max(0.01, layer2.duration);
|
|
165
|
+
const sample = (points, time, timeOrigin = origin) => {
|
|
166
|
+
const t = Math.max(0, time);
|
|
167
|
+
if (context.beats?.length && points.some((p) => p.snapToBeat)) points = points.map((p) => ({ ...p, at: p.snapToBeat ? Math.max(0, nearestBeat(timeOrigin + p.at) - timeOrigin) : p.at })).sort((a, b) => a.at - b.at);
|
|
168
|
+
let left = points[0], right = points[points.length - 1];
|
|
169
|
+
if (t <= left.at) right = left;
|
|
170
|
+
else if (t >= right.at) left = right;
|
|
171
|
+
else for (let i = 0; i < points.length - 1; i++) {
|
|
172
|
+
if (t >= points[i].at && t <= points[i + 1].at) {
|
|
173
|
+
left = points[i];
|
|
174
|
+
right = points[i + 1];
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const u = left === right ? 0 : ease((t - left.at) / (right.at - left.at), right.easing ?? layer2.easing ?? "smooth", right.at - left.at);
|
|
179
|
+
const mix2 = (a, b) => a + (b - a) * u;
|
|
180
|
+
const extras = {};
|
|
181
|
+
for (const channel of ["blur", "skewX", "skewY", "rotateX", "rotateY", "borderRadius", "letterSpacing", "glow"]) {
|
|
182
|
+
if (left[channel] !== void 0 || right[channel] !== void 0) {
|
|
183
|
+
const fallback = layer2[channel] ?? 0;
|
|
184
|
+
extras[channel] = mix2(left[channel] ?? fallback, right[channel] ?? fallback);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (left.color !== void 0 || right.color !== void 0) extras.color = colorMix(left.color ?? layer2.color, right.color ?? layer2.color, u);
|
|
188
|
+
if (left.clip || right.clip) extras.clip = clipMix(left.clip ?? layer2.clip, right.clip ?? layer2.clip, u);
|
|
189
|
+
return {
|
|
190
|
+
...extras,
|
|
191
|
+
translateX: mix2(left.x, right.x),
|
|
192
|
+
translateY: mix2(left.y, right.y),
|
|
193
|
+
scaleX: mix2(left.scaleX, right.scaleX) * mix2(left.scale ?? 1, right.scale ?? 1),
|
|
194
|
+
scaleY: mix2(left.scaleY, right.scaleY) * mix2(left.scale ?? 1, right.scale ?? 1),
|
|
195
|
+
rotation: mix2(left.rotation, right.rotation),
|
|
196
|
+
opacity: clamp(mix2(left.opacity, right.opacity)),
|
|
197
|
+
reveal: clamp(mix2(left.reveal ?? 1, right.reveal ?? 1)),
|
|
198
|
+
value: left.value === void 0 && right.value === void 0 ? void 0 : mix2(left.value ?? right.value, right.value ?? left.value)
|
|
199
|
+
};
|
|
200
|
+
};
|
|
201
|
+
const frame = { visible: !layer2.hidden && elapsed >= 0 && elapsed < duration, opacity: layer2.opacity, translateX: 0, translateY: 0, scale: 1, scaleX: 1, scaleY: 1, rotation: layer2.rotation, reveal: 1, text: layer2.text ?? "" };
|
|
202
|
+
const entryDuration = Math.min(duration, layer2.motionDuration ?? Math.min(0.7, duration / 2));
|
|
203
|
+
const entryP = ease((elapsed - (layer2.motionDelay ?? 0)) / entryDuration, layer2.easing ?? "smooth", entryDuration);
|
|
204
|
+
if (layer2.type === "repeater") return frame;
|
|
205
|
+
const relative = context.schemaVersion === 3;
|
|
206
|
+
const slideX = relative ? (context.canvas?.width ?? 1920) * 0.12 : 100, slideY = relative ? (context.canvas?.height ?? 1080) * 0.12 : 70;
|
|
207
|
+
const applyPreset = (preset, progress, outgoing = false) => {
|
|
208
|
+
const rest = outgoing ? progress : 1 - progress;
|
|
209
|
+
if (preset === "fade") frame.opacity *= outgoing ? 1 - progress : progress;
|
|
210
|
+
if (preset === "slide-up") {
|
|
211
|
+
frame.translateY += (outgoing ? -slideY : slideY) * rest;
|
|
212
|
+
frame.opacity *= outgoing ? 1 - progress : progress;
|
|
213
|
+
}
|
|
214
|
+
if (preset === "slide-down") {
|
|
215
|
+
frame.translateY += (outgoing ? slideY : -slideY) * rest;
|
|
216
|
+
frame.opacity *= outgoing ? 1 - progress : progress;
|
|
217
|
+
}
|
|
218
|
+
if (preset === "slide-left") {
|
|
219
|
+
frame.translateX += (outgoing ? -slideX : slideX) * rest;
|
|
220
|
+
frame.opacity *= outgoing ? 1 - progress : progress;
|
|
221
|
+
}
|
|
222
|
+
if (preset === "slide-right") {
|
|
223
|
+
frame.translateX += (outgoing ? slideX : -slideX) * rest;
|
|
224
|
+
frame.opacity *= outgoing ? 1 - progress : progress;
|
|
225
|
+
}
|
|
226
|
+
if (preset === "zoom") {
|
|
227
|
+
frame.scale *= outgoing ? 1 + 0.25 * progress : 0.75 + 0.25 * progress;
|
|
228
|
+
frame.opacity *= outgoing ? 1 - progress : progress;
|
|
229
|
+
}
|
|
230
|
+
if (preset === "pop") {
|
|
231
|
+
frame.scale *= outgoing ? 1 - 0.25 * progress : progress === 1 ? 1 : 1 + 2.70158 * (progress - 1) ** 3 + 1.70158 * (progress - 1) ** 2;
|
|
232
|
+
frame.opacity *= outgoing ? 1 - progress : Math.min(1, progress * 4);
|
|
233
|
+
}
|
|
234
|
+
const reveal = outgoing ? 1 - progress : progress;
|
|
235
|
+
if (preset === "mask-up") {
|
|
236
|
+
frame.translateY += (outgoing ? -1 : 1) * layer2.height * 0.35 * rest;
|
|
237
|
+
frame.clip = { type: "inset", top: 0, right: 0, bottom: clamp(1 - reveal) * 100, left: 0 };
|
|
238
|
+
frame.opacity *= clamp(reveal * 4);
|
|
239
|
+
}
|
|
240
|
+
if (preset === "blur-in") {
|
|
241
|
+
frame.blur = (layer2.blur ?? 0) + Math.max(0, rest) * 24;
|
|
242
|
+
frame.opacity *= clamp(reveal);
|
|
243
|
+
frame.scale *= 1 + 0.08 * rest;
|
|
244
|
+
}
|
|
245
|
+
if (preset === "flip-in") {
|
|
246
|
+
frame.rotateY = rest * (outgoing ? -85 : 85);
|
|
247
|
+
frame.opacity *= clamp(reveal * 2);
|
|
248
|
+
}
|
|
249
|
+
if (preset === "scale-pop") {
|
|
250
|
+
const t = clamp(reveal);
|
|
251
|
+
frame.scale *= 1 + 2.70158 * (t - 1) ** 3 + 1.70158 * (t - 1) ** 2;
|
|
252
|
+
frame.opacity *= clamp(t * 4);
|
|
253
|
+
}
|
|
254
|
+
if (preset === "drop") {
|
|
255
|
+
const t = clamp(reveal), landing = Math.sin(Math.PI * clamp((t - 0.6) / 0.4)) * 0.22;
|
|
256
|
+
frame.translateY -= slideY * 2 * (1 - t);
|
|
257
|
+
frame.scaleX *= 1 + landing;
|
|
258
|
+
frame.scaleY *= 1 - landing;
|
|
259
|
+
frame.opacity *= clamp(t * 5);
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
applyPreset(layer2.motion, entryP);
|
|
263
|
+
const outDuration = Math.min(duration, layer2.motionOutDuration ?? 0.45);
|
|
264
|
+
if (layer2.motionOut && layer2.motionOut !== "none" && elapsed >= duration - outDuration) {
|
|
265
|
+
const outP = ease((elapsed - duration + outDuration) / outDuration, layer2.easing ?? "smooth", outDuration);
|
|
266
|
+
applyPreset(layer2.motionOut, outP, true);
|
|
267
|
+
}
|
|
268
|
+
if (layer2.motion === "typewriter") {
|
|
269
|
+
const segmenter = typeof Intl.Segmenter === "function" ? new Intl.Segmenter(void 0, { granularity: "grapheme" }) : null;
|
|
270
|
+
const chars = segmenter ? Array.from(segmenter.segment(frame.text), (s) => s.segment) : Array.from(frame.text);
|
|
271
|
+
frame.text = chars.slice(0, Math.ceil(chars.length * clamp(entryP))).join("");
|
|
272
|
+
}
|
|
273
|
+
if (layer2.type === "text" && layer2.countTo !== void 0) {
|
|
274
|
+
const start = layer2.countFrom ?? 0;
|
|
275
|
+
frame.value = start + (layer2.countTo - start) * entryP;
|
|
276
|
+
frame.text = layer2.countPrefix !== void 0 || layer2.countDecimals !== void 0 || layer2.countThousands !== void 0 ? formatValue(frame.value) : Math.round(frame.value).toLocaleString("he-IL") + (layer2.countSuffix ?? "");
|
|
277
|
+
}
|
|
278
|
+
if (layer2.keyframes?.length) {
|
|
279
|
+
const pose = sample(layer2.keyframes, elapsed);
|
|
280
|
+
frame.translateX += pose.translateX;
|
|
281
|
+
frame.translateY += pose.translateY;
|
|
282
|
+
frame.scaleX *= pose.scaleX;
|
|
283
|
+
frame.scaleY *= pose.scaleY;
|
|
284
|
+
frame.rotation += pose.rotation;
|
|
285
|
+
frame.opacity *= pose.opacity;
|
|
286
|
+
frame.reveal = pose.reveal;
|
|
287
|
+
for (const channel of ["color", "blur", "skewX", "skewY", "rotateX", "rotateY", "clip", "borderRadius", "letterSpacing", "glow"]) if (pose[channel] !== void 0) Object.assign(frame, { [channel]: pose[channel] });
|
|
288
|
+
if (pose.value !== void 0) frame.value = pose.value;
|
|
289
|
+
if (layer2.type === "text" && pose.value !== void 0) frame.text = layer2.countPrefix !== void 0 || layer2.countDecimals !== void 0 || layer2.countThousands !== void 0 ? formatValue(pose.value) : Math.round(pose.value).toLocaleString("he-IL") + (layer2.countSuffix ?? "");
|
|
290
|
+
}
|
|
291
|
+
if (layer2.type === "text" && layer2.splitText && layer2.splitText !== "none") {
|
|
292
|
+
const segmenter = layer2.splitText === "letter" && typeof Intl.Segmenter === "function" ? new Intl.Segmenter(void 0, { granularity: "grapheme" }) : null;
|
|
293
|
+
const units = layer2.splitText === "word" ? frame.text.match(/\S+|\s+/gu) ?? [] : segmenter ? Array.from(segmenter.segment(frame.text), (item) => item.segment) : Array.from(frame.text);
|
|
294
|
+
const count = units.filter((text3) => text3.trim()).length;
|
|
295
|
+
const order = Array.from({ length: count }, (_, i) => i);
|
|
296
|
+
if (layer2.staggerOrder === "end") order.reverse();
|
|
297
|
+
if (layer2.staggerOrder === "center") order.sort((a, b) => Math.abs(a - (count - 1) / 2) - Math.abs(b - (count - 1) / 2) || a - b);
|
|
298
|
+
if (layer2.staggerOrder === "seeded-random") order.sort((a, b) => hash(layer2.staggerSeed ?? 0, a) - hash(layer2.staggerSeed ?? 0, b) || a - b);
|
|
299
|
+
const ranks = Array.from({ length: count }, (_, i) => order.indexOf(i));
|
|
300
|
+
let index = 0;
|
|
301
|
+
frame.textUnits = units.map((text3) => {
|
|
302
|
+
if (!text3.trim()) return { text: text3, opacity: 1, translateX: 0, translateY: 0, scaleX: 1, scaleY: 1, rotation: 0 };
|
|
303
|
+
const unitIndex = index++, rank = ranks[unitIndex];
|
|
304
|
+
let delay = (layer2.motionDelay ?? 0) + rank * (layer2.stagger ?? 0.08);
|
|
305
|
+
if (layer2.staggerToBeats && context.beats?.length) {
|
|
306
|
+
const beats = context.beats.filter((b) => b >= origin + (layer2.motionDelay ?? 0));
|
|
307
|
+
const beatIndex = rank + (layer2.staggerBeatOffset ?? 0);
|
|
308
|
+
delay = (beats[beatIndex] ?? (beats.length ? beats[beats.length - 1] + (beatIndex - beats.length + 1) * (layer2.stagger ?? 0.08) : origin + delay)) - origin;
|
|
309
|
+
}
|
|
310
|
+
const unitTime = elapsed - delay, color = layer2.textUnitColors?.[unitIndex % layer2.textUnitColors.length];
|
|
311
|
+
if (layer2.textUnitKeyframes?.length) return { text: text3, color, ...sample(layer2.textUnitKeyframes, unitTime, origin + delay) };
|
|
312
|
+
const p = ease(unitTime / Math.max(0.08, entryDuration * 0.6), layer2.easing ?? "smooth", Math.max(0.08, entryDuration * 0.6));
|
|
313
|
+
return { text: text3, color, opacity: clamp(p), translateX: 0, translateY: (relative ? (context.canvas?.height ?? 1080) * 0.045 : 28) * (1 - p), scaleX: 1, scaleY: 1, rotation: 0 };
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
for (const modifier of layer2.modifiers ?? []) {
|
|
317
|
+
const t = Math.max(0, elapsed), phase = hash(modifier.seed, 0) * Math.PI * 2, w = 2 * Math.PI * modifier.frequency, a = modifier.amplitude;
|
|
318
|
+
if (modifier.type === "float") frame.translateY += a * Math.sin(w * t + phase);
|
|
319
|
+
if (modifier.type === "orbit") {
|
|
320
|
+
frame.translateX += a * Math.cos(w * t + phase);
|
|
321
|
+
frame.translateY += a * Math.sin(w * t + phase);
|
|
322
|
+
}
|
|
323
|
+
if (modifier.type === "spin") frame.rotation += a * modifier.frequency * t;
|
|
324
|
+
if (modifier.type === "wiggle") {
|
|
325
|
+
const noise = (offset) => {
|
|
326
|
+
const at = t * modifier.frequency, i = Math.floor(at), f = at - i, u = f * f * (3 - 2 * f);
|
|
327
|
+
return (hash(modifier.seed, i * 2 + offset) * (1 - u) + hash(modifier.seed, (i + 1) * 2 + offset) * u) * 2 - 1;
|
|
328
|
+
};
|
|
329
|
+
frame.translateX += a * noise(1);
|
|
330
|
+
frame.translateY += a * noise(2);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
if (layer2.revealBinding && context.layers) {
|
|
334
|
+
const source = context.layers.find((l) => l.id === layer2.revealBinding.layerId);
|
|
335
|
+
if (source && source.id !== layer2.id && !source.revealBinding) {
|
|
336
|
+
const value = evaluateLayer(source, localTime, context).value;
|
|
337
|
+
if (value !== void 0) frame.reveal = clamp((value - layer2.revealBinding.from) / (layer2.revealBinding.to - layer2.revealBinding.from));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
frame.opacity = clamp(frame.opacity);
|
|
341
|
+
return frame;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// src/core/layer-style.ts
|
|
345
|
+
function textUnitStyle(unit) {
|
|
346
|
+
const result = {
|
|
347
|
+
display: "inline-block",
|
|
348
|
+
flexShrink: 0,
|
|
349
|
+
whiteSpace: "pre",
|
|
350
|
+
opacity: unit.opacity,
|
|
351
|
+
transform: `${unit.rotateX || unit.rotateY ? `perspective(1000px) rotateX(${unit.rotateX ?? 0}deg) rotateY(${unit.rotateY ?? 0}deg) ` : ""}translate(${unit.translateX}px,${unit.translateY}px) rotate(${unit.rotation}deg)${unit.skewX || unit.skewY ? ` skew(${unit.skewX ?? 0}deg,${unit.skewY ?? 0}deg)` : ""} scale(${unit.scaleX},${unit.scaleY})`,
|
|
352
|
+
transformOrigin: "center",
|
|
353
|
+
color: "inherit",
|
|
354
|
+
filter: "none",
|
|
355
|
+
clipPath: "none",
|
|
356
|
+
borderRadius: 0,
|
|
357
|
+
letterSpacing: "inherit"
|
|
358
|
+
};
|
|
359
|
+
if (unit.color) result.color = unit.color;
|
|
360
|
+
if (unit.blur !== void 0 || unit.glow !== void 0) result.filter = `blur(${Math.max(0, unit.blur ?? 0)}px)${unit.glow ? ` drop-shadow(0 0 ${Math.max(0, unit.glow)}px ${unit.color ?? "currentColor"})` : ""}`;
|
|
361
|
+
if (unit.borderRadius !== void 0) result.borderRadius = `${Math.max(0, unit.borderRadius)}px`;
|
|
362
|
+
if (unit.letterSpacing !== void 0) result.letterSpacing = `${unit.letterSpacing}px`;
|
|
363
|
+
if (unit.clip) result.clipPath = unit.clip.type === "inset" ? `inset(${unit.clip.top}% ${unit.clip.right}% ${unit.clip.bottom}% ${unit.clip.left}%)` : `circle(${unit.clip.radius}% at ${unit.clip.x}% ${unit.clip.y}%)`;
|
|
364
|
+
return result;
|
|
365
|
+
}
|
|
366
|
+
function textLineStyle(layer2) {
|
|
367
|
+
const direction = !/[\u0590-\u05ff]/.test(layer2.text ?? "") && /[A-Za-z]/.test(layer2.text ?? "") ? "ltr" : "rtl";
|
|
368
|
+
return {
|
|
369
|
+
display: "flex",
|
|
370
|
+
flexWrap: "wrap",
|
|
371
|
+
width: "100%",
|
|
372
|
+
direction,
|
|
373
|
+
alignItems: "center",
|
|
374
|
+
justifyContent: layer2.textAlign === "center" ? "center" : layer2.textAlign === "right" === (direction === "rtl") ? "flex-start" : "flex-end"
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
function layerStyle(layer2, frame) {
|
|
378
|
+
const color = frame.color ?? layer2.color, blur = Math.max(0, frame.blur ?? layer2.blur ?? 0), glow = Math.max(0, frame.glow ?? layer2.glow ?? 0), clip = frame.clip ?? layer2.clip;
|
|
379
|
+
let fontSize = layer2.fontSize;
|
|
380
|
+
if (layer2.textFit === "shrink" && layer2.type === "text") {
|
|
381
|
+
const measure = (size) => {
|
|
382
|
+
const limit = layer2.width / Math.max(1, size * 0.6 + (frame.letterSpacing ?? layer2.letterSpacing ?? 0));
|
|
383
|
+
let lines = 1, count = 0;
|
|
384
|
+
for (const word of (frame.text || "").split(/(\s+)/u)) {
|
|
385
|
+
if (word.includes("\n")) {
|
|
386
|
+
lines += word.split("\n").length - 1;
|
|
387
|
+
count = 0;
|
|
388
|
+
} else {
|
|
389
|
+
const n = Array.from(word).length;
|
|
390
|
+
if (count + n > limit) {
|
|
391
|
+
lines += Math.max(1, Math.floor(n / limit));
|
|
392
|
+
count = n % limit;
|
|
393
|
+
} else count += n;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return lines * size * (layer2.lineHeight ?? 1.2) <= layer2.height;
|
|
397
|
+
};
|
|
398
|
+
for (let i = 0; i < 80 && !measure(fontSize) && fontSize > 4; i++) fontSize *= 0.95;
|
|
399
|
+
}
|
|
400
|
+
const extra = { clipPath: "none" };
|
|
401
|
+
if (clip) extra.clipPath = clip.type === "inset" ? `inset(${clip.top}% ${clip.right}% ${clip.bottom}% ${clip.left}%)` : `circle(${clip.radius}% at ${clip.x}% ${clip.y}%)`;
|
|
402
|
+
if (layer2.type === "shape" && layer2.revealBinding && !clip) extra.clipPath = `inset(0 ${(1 - frame.reveal) * 100}% 0 0)`;
|
|
403
|
+
if (layer2.type === "repeater" || layer2.textFit) extra.overflow = "visible";
|
|
404
|
+
if (layer2.type === "repeater") {
|
|
405
|
+
extra.filter = "none";
|
|
406
|
+
extra.boxShadow = "none";
|
|
407
|
+
extra.border = "none";
|
|
408
|
+
extra.clipPath = "none";
|
|
409
|
+
if (!frame.visible) extra.display = "none";
|
|
410
|
+
}
|
|
411
|
+
const sx = frame.skewX ?? layer2.skewX ?? 0, sy = frame.skewY ?? layer2.skewY ?? 0, rx = frame.rotateX ?? layer2.rotateX ?? 0, ry = frame.rotateY ?? layer2.rotateY ?? 0;
|
|
412
|
+
const spatial = rx || ry ? `perspective(${layer2.perspective ?? 1e3}px) rotateX(${rx}deg) rotateY(${ry}deg) ` : "";
|
|
413
|
+
return {
|
|
414
|
+
position: "absolute",
|
|
415
|
+
left: `${layer2.x}px`,
|
|
416
|
+
top: `${layer2.y}px`,
|
|
417
|
+
width: `${layer2.width}px`,
|
|
418
|
+
height: `${layer2.height}px`,
|
|
419
|
+
display: "flex",
|
|
420
|
+
alignItems: "center",
|
|
421
|
+
justifyContent: layer2.textAlign === "right" ? "flex-start" : layer2.textAlign === "left" ? "flex-end" : "center",
|
|
422
|
+
direction: "rtl",
|
|
423
|
+
textAlign: layer2.textAlign,
|
|
424
|
+
whiteSpace: "pre-wrap",
|
|
425
|
+
overflowWrap: "anywhere",
|
|
426
|
+
overflow: "hidden",
|
|
427
|
+
color,
|
|
428
|
+
background: layer2.type === "shape" ? color : "transparent",
|
|
429
|
+
fontSize: `${fontSize}px`,
|
|
430
|
+
fontWeight: layer2.fontWeight,
|
|
431
|
+
fontFamily: `"MotionDesk Symbols", ${layer2.fontFamily || "Heebo"}, Heebo, sans-serif`,
|
|
432
|
+
letterSpacing: `${frame.letterSpacing ?? layer2.letterSpacing ?? 0}px`,
|
|
433
|
+
lineHeight: layer2.lineHeight ?? 1.2,
|
|
434
|
+
borderRadius: `${Math.max(0, frame.borderRadius ?? layer2.borderRadius)}px`,
|
|
435
|
+
border: `${layer2.borderWidth ?? 0}px solid ${layer2.borderColor ?? "transparent"}`,
|
|
436
|
+
boxShadow: layer2.shadow ?? "none",
|
|
437
|
+
filter: `blur(${blur}px)${glow ? ` drop-shadow(0 0 ${glow}px ${layer2.glowColor ?? color})` : ""}`,
|
|
438
|
+
mixBlendMode: layer2.blendMode ?? "normal",
|
|
439
|
+
opacity: frame.opacity,
|
|
440
|
+
visibility: frame.visible ? "visible" : "hidden",
|
|
441
|
+
transform: `${spatial}translate(${frame.translateX}px,${frame.translateY}px) rotate(${frame.rotation}deg)${sx || sy ? ` skew(${sx}deg,${sy}deg)` : ""} scale(${frame.scale * frame.scaleX},${frame.scale * frame.scaleY})`,
|
|
442
|
+
transformOrigin: layer2.transformOrigin ?? "center",
|
|
443
|
+
...extra
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// src/core/config-v3-schema.ts
|
|
448
|
+
var componentTypesV3 = ["hook", "kinetic", "counter", "cards", "checklist", "compare", "timeline", "bars", "phone", "chat", "map-route", "coins", "confetti", "freeze", "endcard", "quote", "progress", "logo", "line-chart", "donut", "notification-stack", "ui-cursor", "marquee", "big-number"];
|
|
449
|
+
var configV3Variants = ["split", "centered", "stacked"];
|
|
450
|
+
var configV3Energies = ["calm", "normal", "punchy"];
|
|
451
|
+
var configV3Backgrounds = ["solid", "gradient", "grid", "dots", "motif"];
|
|
452
|
+
var configV3Cameras = ["push-in", "drift", "orbit", "none"];
|
|
453
|
+
var configV3Themes = ["summer_ice", "bank_red", "midnight", "warm", "mono", "flow", "pulse", "orbit"];
|
|
454
|
+
var configV3Transitions = ["cut", "fade", "slide", "wipe", "zoom", "push", "iris", "diagonal-wipe", "whip", "zoom-through", "stack"];
|
|
455
|
+
var rootKeys = ["format", "title", "theme", "aspectRatio", "fps", "palette", "seed", "beats", "motionBlur", "scenes"];
|
|
456
|
+
var sceneKeys = ["type", "duration", "title", "subtitle", "label", "product", "cta", "words", "items", "rows", "to", "beat", "ring", "transition", "variant", "energy", "background", "camera", "emphasis", "accent", "value", "from", "prefix", "suffix", "decimals", "thousands", "max", "values"];
|
|
457
|
+
var fail = (path, reason) => {
|
|
458
|
+
throw new Error(`${path}: ${reason}`);
|
|
459
|
+
};
|
|
460
|
+
function record(v, keys, path) {
|
|
461
|
+
if (!v || typeof v !== "object" || Array.isArray(v) || ![Object.prototype, null].includes(Object.getPrototypeOf(v))) return fail(path, "\u05E0\u05D3\u05E8\u05E9 \u05D0\u05D5\u05D1\u05D9\u05D9\u05E7\u05D8");
|
|
462
|
+
const r = v;
|
|
463
|
+
for (const key of Object.keys(r)) if (!keys.includes(key)) fail(`${path}.${key}`, "\u05E9\u05D3\u05D4 \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8");
|
|
464
|
+
return r;
|
|
465
|
+
}
|
|
466
|
+
function number(v, min, max, path, integer = false) {
|
|
467
|
+
if (typeof v !== "number" || !Number.isFinite(v) || v < min || v > max || integer && !Number.isInteger(v)) return fail(path, "\u05DE\u05E1\u05E4\u05E8 \u05DE\u05D7\u05D5\u05E5 \u05DC\u05D8\u05D5\u05D5\u05D7");
|
|
468
|
+
return v;
|
|
469
|
+
}
|
|
470
|
+
function text(v, max, path) {
|
|
471
|
+
if (typeof v !== "string" || !v.trim() || v.length > max || /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/.test(v) || /<\/?[a-z][^>]*>/i.test(v)) return fail(path, `\u05E0\u05D3\u05E8\u05E9 \u05D8\u05E7\u05E1\u05D8 \u05E8\u05D2\u05D9\u05DC \u05D1\u05D0\u05D5\u05E8\u05DA 1\u2013${max}`);
|
|
472
|
+
return v;
|
|
473
|
+
}
|
|
474
|
+
function choice(v, choices, path) {
|
|
475
|
+
if (!choices.includes(v)) return fail(path, "\u05E2\u05E8\u05DA \u05DC\u05D0 \u05E0\u05EA\u05DE\u05DA");
|
|
476
|
+
return v;
|
|
477
|
+
}
|
|
478
|
+
function hex(v, path) {
|
|
479
|
+
if (typeof v !== "string" || !/^#[a-fA-F0-9]{6}$/.test(v)) return fail(path, "\u05E0\u05D3\u05E8\u05E9 \u05E6\u05D1\u05E2 #RRGGBB");
|
|
480
|
+
return v;
|
|
481
|
+
}
|
|
482
|
+
function list(v, min, max, path, read) {
|
|
483
|
+
if (!Array.isArray(v) || v.length < min || v.length > max) return fail(path, `\u05E0\u05D3\u05E8\u05E9\u05D9\u05DD ${min}\u2013${max} \u05E4\u05E8\u05D9\u05D8\u05D9\u05DD`);
|
|
484
|
+
return Array.from(v, (entry, i) => read(entry, `${path}.${i}`));
|
|
485
|
+
}
|
|
486
|
+
function parseMotionConfigV3(input) {
|
|
487
|
+
let encoded;
|
|
488
|
+
try {
|
|
489
|
+
encoded = JSON.stringify(input);
|
|
490
|
+
} catch {
|
|
491
|
+
return fail("config", "\u05E7\u05D5\u05E0\u05E4\u05D9\u05D2\u05D5\u05E8\u05E6\u05D9\u05D4 \u05D0\u05D9\u05E0\u05D4 JSON \u05EA\u05E7\u05D9\u05DF");
|
|
492
|
+
}
|
|
493
|
+
if (!encoded || new TextEncoder().encode(encoded).length > 256 * 1024) return fail("config", "\u05E7\u05D5\u05D1\u05E5 \u05D4\u05D4\u05D2\u05D3\u05E8\u05D5\u05EA \u05D2\u05D3\u05D5\u05DC \u05DE\u05D3\u05D9");
|
|
494
|
+
const r = record(input, rootKeys, "config");
|
|
495
|
+
choice(r.format, ["motiondesk-config/v3"], "format");
|
|
496
|
+
const config = { format: "motiondesk-config/v3", title: r.title === void 0 ? "\u05E1\u05E8\u05D8\u05D5\u05DF Motion \u05D7\u05D3\u05E9" : text(r.title, 120, "title"), theme: choice(r.theme === void 0 ? "bank_red" : r.theme, configV3Themes, "theme"), aspectRatio: choice(r.aspectRatio === void 0 ? "16:9" : r.aspectRatio, ["16:9", "9:16", "1:1"], "aspectRatio"), fps: choice(r.fps === void 0 ? 30 : r.fps, [24, 25, 30, 60], "fps"), seed: number(r.seed === void 0 ? 319 : r.seed, -2147483648, 2147483647, "seed", true), scenes: [] };
|
|
497
|
+
if (r.palette !== void 0) {
|
|
498
|
+
const p = record(r.palette, ["background", "foreground", "accent", "secondary"], "palette");
|
|
499
|
+
config.palette = { background: hex(p.background, "palette.background"), foreground: hex(p.foreground, "palette.foreground"), accent: hex(p.accent, "palette.accent") };
|
|
500
|
+
if (p.secondary !== void 0) config.palette.secondary = hex(p.secondary, "palette.secondary");
|
|
501
|
+
}
|
|
502
|
+
config.scenes = list(r.scenes, 1, 30, "scenes", (raw, path) => {
|
|
503
|
+
const s = record(raw, sceneKeys, path);
|
|
504
|
+
const scene = { type: choice(s.type, componentTypesV3, `${path}.type`), duration: number(s.duration === void 0 ? 4 : s.duration, 0.5, 30, `${path}.duration`), beat: number(s.beat === void 0 ? 0.5 : s.beat, 0.05, 3, `${path}.beat`), variant: choice(s.variant === void 0 ? "split" : s.variant, configV3Variants, `${path}.variant`), energy: choice(s.energy === void 0 ? "normal" : s.energy, configV3Energies, `${path}.energy`), background: choice(s.background === void 0 ? "motif" : s.background, configV3Backgrounds, `${path}.background`), camera: choice(s.camera === void 0 ? "push-in" : s.camera, configV3Cameras, `${path}.camera`) };
|
|
505
|
+
for (const key of ["title", "subtitle", "label", "product", "cta", "emphasis", "prefix", "suffix"]) if (s[key] !== void 0) scene[key] = text(s[key], key === "emphasis" ? 80 : ["prefix", "suffix"].includes(key) ? 24 : 220, `${path}.${key}`);
|
|
506
|
+
for (const key of ["words", "items"]) if (s[key] !== void 0) scene[key] = list(s[key], 1, 20, `${path}.${key}`, (v, p) => text(v, 220, p));
|
|
507
|
+
if (s.rows !== void 0) scene.rows = list(s.rows, 1, 12, `${path}.rows`, (v, p) => list(v, 1, 3, p, (cell, p2) => text(cell, 220, p2)));
|
|
508
|
+
if (scene.type === "bars" && scene.rows && s.values === void 0 && scene.rows.some((row) => row.length < 2 || !Number.isFinite(Number(row[1])))) fail(`${path}.rows`, "\u05E2\u05DE\u05D5\u05D3\u05D5\u05EA \u05D3\u05D5\u05E8\u05E9\u05D5\u05EA \u05EA\u05D5\u05D5\u05D9\u05EA \u05D5\u05E2\u05E8\u05DA \u05DE\u05E1\u05E4\u05E8\u05D9");
|
|
509
|
+
if (s.values !== void 0) scene.values = list(s.values, 2, 20, `${path}.values`, (v, p) => number(v, -1e9, 1e9, p));
|
|
510
|
+
for (const key of ["value", "to", "from"]) if (s[key] !== void 0) scene[key] = number(s[key], -1e9, 1e9, `${path}.${key}`);
|
|
511
|
+
if (s.value !== void 0 && s.to !== void 0 && s.value !== s.to) fail(`${path}.value`, "value \u05D5-to \u05E1\u05D5\u05EA\u05E8\u05D9\u05DD");
|
|
512
|
+
if (scene.value === void 0 && scene.to !== void 0) scene.value = scene.to;
|
|
513
|
+
delete scene.to;
|
|
514
|
+
if (s.max !== void 0) scene.max = number(s.max, Number.MIN_VALUE, 1e9, `${path}.max`);
|
|
515
|
+
if (s.decimals !== void 0) scene.decimals = number(s.decimals, 0, 6, `${path}.decimals`, true);
|
|
516
|
+
for (const key of ["thousands", "ring"]) if (s[key] !== void 0) {
|
|
517
|
+
if (typeof s[key] !== "boolean") fail(`${path}.${key}`, "\u05E0\u05D3\u05E8\u05E9 \u05E2\u05E8\u05DA \u05D1\u05D5\u05DC\u05D9\u05D0\u05E0\u05D9");
|
|
518
|
+
scene[key] = s[key];
|
|
519
|
+
}
|
|
520
|
+
if (s.accent !== void 0) scene.accent = hex(s.accent, `${path}.accent`);
|
|
521
|
+
if (s.transition !== void 0) scene.transition = choice(s.transition, configV3Transitions, `${path}.transition`);
|
|
522
|
+
return scene;
|
|
523
|
+
});
|
|
524
|
+
const duration = config.scenes.reduce((sum, s) => sum + s.duration, 0);
|
|
525
|
+
if (r.beats !== void 0) {
|
|
526
|
+
config.beats = list(r.beats, 0, 1e3, "beats", (v, p) => number(v, 0, duration, p));
|
|
527
|
+
if (config.beats.some((beat, i) => i > 0 && beat <= config.beats[i - 1])) fail("beats", "\u05E0\u05E7\u05D5\u05D3\u05D5\u05EA \u05D4\u05D6\u05DE\u05DF \u05D7\u05D9\u05D9\u05D1\u05D5\u05EA \u05DC\u05E2\u05DC\u05D5\u05EA");
|
|
528
|
+
}
|
|
529
|
+
if (r.motionBlur !== void 0) {
|
|
530
|
+
const b = record(r.motionBlur, ["samples", "shutterAngle"], "motionBlur");
|
|
531
|
+
config.motionBlur = { samples: number(b.samples, 1, 8, "motionBlur.samples", true), shutterAngle: number(b.shutterAngle, 0, 360, "motionBlur.shutterAngle") };
|
|
532
|
+
}
|
|
533
|
+
return config;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// src/core/project.ts
|
|
537
|
+
function newId(prefix = "id") {
|
|
538
|
+
return `${prefix}_${globalThis.crypto?.randomUUID?.() ?? `${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`}`;
|
|
539
|
+
}
|
|
540
|
+
function createLayer(type = "text", patch = {}) {
|
|
541
|
+
return {
|
|
542
|
+
id: newId("layer"),
|
|
543
|
+
type,
|
|
544
|
+
name: type === "text" ? "\u05D8\u05E7\u05E1\u05D8 \u05D7\u05D3\u05E9" : "\u05E9\u05DB\u05D1\u05D4 \u05D7\u05D3\u05E9\u05D4",
|
|
545
|
+
...type === "text" ? { text: "\u05D4\u05E1\u05D9\u05E4\u05D5\u05E8 \u05E9\u05DC\u05DA \u05DE\u05EA\u05D7\u05D9\u05DC \u05DB\u05D0\u05DF" } : {},
|
|
546
|
+
x: 120,
|
|
547
|
+
y: 240,
|
|
548
|
+
width: 840,
|
|
549
|
+
height: 220,
|
|
550
|
+
rotation: 0,
|
|
551
|
+
opacity: 1,
|
|
552
|
+
color: "#ffffff",
|
|
553
|
+
fontSize: 72,
|
|
554
|
+
fontWeight: 700,
|
|
555
|
+
fontFamily: "Heebo",
|
|
556
|
+
textAlign: "center",
|
|
557
|
+
borderRadius: 0,
|
|
558
|
+
motion: "fade",
|
|
559
|
+
motionOut: "none",
|
|
560
|
+
motionDuration: 0.7,
|
|
561
|
+
motionDelay: 0,
|
|
562
|
+
motionOutDuration: 0.45,
|
|
563
|
+
easing: "ease-out",
|
|
564
|
+
splitText: "none",
|
|
565
|
+
stagger: 0.08,
|
|
566
|
+
shadow: "none",
|
|
567
|
+
borderColor: "#000000",
|
|
568
|
+
borderWidth: 0,
|
|
569
|
+
letterSpacing: 0,
|
|
570
|
+
lineHeight: 1.2,
|
|
571
|
+
blur: 0,
|
|
572
|
+
blendMode: "normal",
|
|
573
|
+
start: 0,
|
|
574
|
+
duration: 5,
|
|
575
|
+
locked: false,
|
|
576
|
+
hidden: false,
|
|
577
|
+
...patch
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
function createScene(name = "\u05E1\u05E6\u05E0\u05D4 \u05D7\u05D3\u05E9\u05D4", duration = 5) {
|
|
581
|
+
return { id: newId("scene"), name, duration, background: "#111827", layers: [], transition: "cut" };
|
|
582
|
+
}
|
|
583
|
+
function createProject(title = "\u05D4\u05E1\u05E8\u05D8\u05D5\u05DF \u05E9\u05DC\u05D9", options = {}) {
|
|
584
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
585
|
+
return {
|
|
586
|
+
schemaVersion: 2,
|
|
587
|
+
id: newId("project"),
|
|
588
|
+
title,
|
|
589
|
+
mode: "authored",
|
|
590
|
+
revision: 0,
|
|
591
|
+
createdAt: now,
|
|
592
|
+
updatedAt: now,
|
|
593
|
+
canvas: { width: 1080, height: 1920, fps: 30 },
|
|
594
|
+
scenes: [createScene("\u05E4\u05EA\u05D9\u05D7\u05D4")],
|
|
595
|
+
assets: [],
|
|
596
|
+
mediaTracks: [],
|
|
597
|
+
...options
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
function projectDuration(project) {
|
|
601
|
+
return Math.max(
|
|
602
|
+
project.scenes.reduce((sum, scene) => sum + scene.duration, 0),
|
|
603
|
+
...project.mediaTracks.flatMap((track) => track.clips.map((clip) => clip.start + clip.out - clip.in)),
|
|
604
|
+
0
|
|
605
|
+
);
|
|
606
|
+
}
|
|
607
|
+
function sceneAtTime(project, time) {
|
|
608
|
+
if (!Number.isFinite(time) || time < 0) return null;
|
|
609
|
+
let start = 0;
|
|
610
|
+
for (let index = 0; index < project.scenes.length; index++) {
|
|
611
|
+
const scene = project.scenes[index];
|
|
612
|
+
if (time < start + scene.duration) return { scene, index, localTime: time - start, start };
|
|
613
|
+
start += scene.duration;
|
|
614
|
+
}
|
|
615
|
+
return null;
|
|
616
|
+
}
|
|
617
|
+
function commitProject(project) {
|
|
618
|
+
return { ...project, revision: project.revision + 1, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
619
|
+
}
|
|
620
|
+
function duplicateScene(project, sceneId) {
|
|
621
|
+
const index = project.scenes.findIndex((scene) => scene.id === sceneId);
|
|
622
|
+
if (index < 0) throw new Error("\u05D4\u05E1\u05E6\u05E0\u05D4 \u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D4");
|
|
623
|
+
const copy = structuredClone(project.scenes[index]);
|
|
624
|
+
copy.id = newId("scene");
|
|
625
|
+
copy.name += " \u2014 \u05E2\u05D5\u05EA\u05E7";
|
|
626
|
+
const replacements = /* @__PURE__ */ new Map();
|
|
627
|
+
const collect = (layer2) => {
|
|
628
|
+
replacements.set(layer2.id, newId("layer"));
|
|
629
|
+
layer2.children?.forEach(collect);
|
|
630
|
+
};
|
|
631
|
+
copy.layers.forEach(collect);
|
|
632
|
+
const reidentify = (layer2) => ({
|
|
633
|
+
...layer2,
|
|
634
|
+
id: replacements.get(layer2.id),
|
|
635
|
+
...layer2.revealBinding ? { revealBinding: { ...layer2.revealBinding, layerId: replacements.get(layer2.revealBinding.layerId) ?? layer2.revealBinding.layerId } } : {},
|
|
636
|
+
...layer2.children ? { children: layer2.children.map(reidentify) } : {}
|
|
637
|
+
});
|
|
638
|
+
copy.layers = copy.layers.map(reidentify);
|
|
639
|
+
const scenes = [...project.scenes];
|
|
640
|
+
scenes.splice(index + 1, 0, copy);
|
|
641
|
+
return commitProject({ ...project, scenes });
|
|
642
|
+
}
|
|
643
|
+
function moveScene(project, sceneId, index) {
|
|
644
|
+
const previous = project.scenes.findIndex((scene2) => scene2.id === sceneId);
|
|
645
|
+
if (previous < 0 || !Number.isInteger(index) || index < 0 || index >= project.scenes.length) throw new Error("\u05DE\u05D9\u05E7\u05D5\u05DD \u05E1\u05E6\u05E0\u05D4 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF");
|
|
646
|
+
const scenes = [...project.scenes];
|
|
647
|
+
const [scene] = scenes.splice(previous, 1);
|
|
648
|
+
scenes.splice(index, 0, scene);
|
|
649
|
+
return commitProject({ ...project, scenes });
|
|
650
|
+
}
|
|
651
|
+
function removeScene(project, sceneId) {
|
|
652
|
+
if (!project.scenes.some((scene) => scene.id === sceneId)) throw new Error("\u05D4\u05E1\u05E6\u05E0\u05D4 \u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D4");
|
|
653
|
+
if (project.scenes.length < 2) throw new Error("\u05E6\u05E8\u05D9\u05DA \u05DC\u05D4\u05E9\u05D0\u05D9\u05E8 \u05DC\u05E4\u05D7\u05D5\u05EA \u05E1\u05E6\u05E0\u05D4 \u05D0\u05D7\u05EA");
|
|
654
|
+
return commitProject({ ...project, scenes: project.scenes.filter((scene) => scene.id !== sceneId) });
|
|
655
|
+
}
|
|
656
|
+
function isLocalAsset(src) {
|
|
657
|
+
if (/^motiondesk-media:\/\/[a-zA-Z0-9_-]+(?:\/[a-zA-Z0-9_.-]+)?$/.test(src)) return true;
|
|
658
|
+
if (/^data:(?:image\/(?:png|jpeg|webp|gif)|audio\/[a-z0-9.+-]+|video\/[a-z0-9.+-]+|font\/[a-z0-9.+-]+);base64,[A-Za-z0-9+/=]+$/.test(src)) return true;
|
|
659
|
+
return !!src && !/[\x00-\x1f<>"'`?#]/.test(src) && !src.startsWith("/") && !src.startsWith("\\") && !src.includes("\\") && !src.includes(":") && !src.split("/").some((p) => p === ".." || p === "." || !p) && !/%(?:2e|2f|5c)/i.test(src);
|
|
660
|
+
}
|
|
661
|
+
function migrateProject(value) {
|
|
662
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("\u05E0\u05D3\u05E8\u05E9 \u05D0\u05D5\u05D1\u05D9\u05D9\u05E7\u05D8 \u05E4\u05E8\u05D5\u05D9\u05E7\u05D8");
|
|
663
|
+
const input = value;
|
|
664
|
+
if (input.schemaVersion === 2 || input.schemaVersion === 3) {
|
|
665
|
+
assertProject(value);
|
|
666
|
+
return value;
|
|
667
|
+
}
|
|
668
|
+
if (input.schemaVersion !== 1) throw new Error("\u05D2\u05E8\u05E1\u05EA \u05E4\u05E8\u05D5\u05D9\u05E7\u05D8 \u05D0\u05D9\u05E0\u05D4 \u05E0\u05EA\u05DE\u05DB\u05EA");
|
|
669
|
+
const migrated = structuredClone(input);
|
|
670
|
+
migrated.schemaVersion = 2;
|
|
671
|
+
const upgrade = (layer2) => ({
|
|
672
|
+
...layer2,
|
|
673
|
+
motionOut: "none",
|
|
674
|
+
motionDuration: Math.min(0.7, layer2.duration / 2),
|
|
675
|
+
motionDelay: 0,
|
|
676
|
+
motionOutDuration: Math.min(0.45, layer2.duration / 2),
|
|
677
|
+
easing: "smooth",
|
|
678
|
+
splitText: "none",
|
|
679
|
+
stagger: 0.08,
|
|
680
|
+
shadow: "none",
|
|
681
|
+
borderColor: "#000000",
|
|
682
|
+
borderWidth: 0,
|
|
683
|
+
letterSpacing: 0,
|
|
684
|
+
lineHeight: 1.2,
|
|
685
|
+
blur: 0,
|
|
686
|
+
blendMode: "normal",
|
|
687
|
+
...layer2.children ? { children: layer2.children.map(upgrade) } : {}
|
|
688
|
+
});
|
|
689
|
+
migrated.scenes = migrated.scenes.map((scene) => ({ ...scene, transitionDuration: 0.35, layers: scene.layers.map(upgrade) }));
|
|
690
|
+
assertProject(migrated);
|
|
691
|
+
return migrated;
|
|
692
|
+
}
|
|
693
|
+
function validateProject(value) {
|
|
694
|
+
if (value && typeof value === "object" && value.schemaVersion === 1) {
|
|
695
|
+
try {
|
|
696
|
+
migrateProject(value);
|
|
697
|
+
return [];
|
|
698
|
+
} catch (error) {
|
|
699
|
+
return [{ path: "project", message: String(error instanceof Error ? error.message : error) }];
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
const issues = [];
|
|
703
|
+
const fail3 = (path, message) => issues.push({ path, message });
|
|
704
|
+
const record2 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
705
|
+
if (!record2(value)) return [{ path: "", message: "\u05E0\u05D3\u05E8\u05E9 \u05D0\u05D5\u05D1\u05D9\u05D9\u05E7\u05D8 \u05E4\u05E8\u05D5\u05D9\u05E7\u05D8" }];
|
|
706
|
+
const p = value;
|
|
707
|
+
if (p.schemaVersion !== 2 && p.schemaVersion !== 3) fail3("schemaVersion", "\u05D2\u05E8\u05E1\u05EA \u05E4\u05E8\u05D5\u05D9\u05E7\u05D8 \u05D0\u05D9\u05E0\u05D4 \u05E0\u05EA\u05DE\u05DB\u05EA");
|
|
708
|
+
if (!["authored", "imported-source", "flat-video"].includes(p.mode)) fail3("mode", "\u05DE\u05E6\u05D1 \u05E4\u05E8\u05D5\u05D9\u05E7\u05D8 \u05D0\u05D9\u05E0\u05D5 \u05DE\u05D5\u05DB\u05E8");
|
|
709
|
+
const ids = /* @__PURE__ */ new Set();
|
|
710
|
+
const id = (v, path) => {
|
|
711
|
+
if (typeof v !== "string" || !/^[a-zA-Z0-9_-]{1,100}$/.test(v) || ids.has(v)) fail3(path, "\u05DE\u05D6\u05D4\u05D4 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF \u05D0\u05D5 \u05DB\u05E4\u05D5\u05DC");
|
|
712
|
+
else ids.add(v);
|
|
713
|
+
};
|
|
714
|
+
const text3 = (v, path, max = 1e5) => {
|
|
715
|
+
if (typeof v !== "string" || v.length > max) fail3(path, "\u05D8\u05E7\u05E1\u05D8 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF");
|
|
716
|
+
};
|
|
717
|
+
const num = (v, path, min, max) => {
|
|
718
|
+
if (typeof v !== "number" || !Number.isFinite(v) || v < min || v > max) fail3(path, "\u05E2\u05E8\u05DA \u05DE\u05E1\u05E4\u05E8\u05D9 \u05DE\u05D7\u05D5\u05E5 \u05DC\u05D8\u05D5\u05D5\u05D7");
|
|
719
|
+
};
|
|
720
|
+
const integer = (v, path, min, max) => {
|
|
721
|
+
num(v, path, min, max);
|
|
722
|
+
if (typeof v === "number" && Number.isFinite(v) && v >= min && v <= max && !Number.isInteger(v)) fail3(path, "\u05E0\u05D3\u05E8\u05E9 \u05DE\u05E1\u05E4\u05E8 \u05E9\u05DC\u05DD");
|
|
723
|
+
};
|
|
724
|
+
const seed = (v, path) => integer(v, path, -2147483648, 2147483647);
|
|
725
|
+
const hex2 = (v, path) => {
|
|
726
|
+
if (typeof v !== "string" || !/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(v)) fail3(path, "\u05E0\u05D3\u05E8\u05E9 \u05E6\u05D1\u05E2 hex");
|
|
727
|
+
};
|
|
728
|
+
const bool = (v, path) => {
|
|
729
|
+
if (typeof v !== "boolean") fail3(path, "\u05E0\u05D3\u05E8\u05E9 \u05E2\u05E8\u05DA \u05D1\u05D5\u05DC\u05D9\u05D0\u05E0\u05D9");
|
|
730
|
+
};
|
|
731
|
+
const known = (v, path, keys) => {
|
|
732
|
+
for (const key of Object.keys(v)) if (!keys.includes(key)) fail3(`${path}.${key}`, "\u05E9\u05D3\u05D4 \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8");
|
|
733
|
+
};
|
|
734
|
+
const easing = (v, path) => {
|
|
735
|
+
if (typeof v === "string") {
|
|
736
|
+
if (!["linear", "smooth", "ease-in", "ease-out", "ease-in-out", "back", "elastic", "hold"].includes(v)) fail3(path, "easing \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8");
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
if (Array.isArray(v)) {
|
|
740
|
+
if (v.length !== 4 || Object.keys(v).some((key) => !/^[0-3]$/.test(key))) {
|
|
741
|
+
fail3(path, "\u05E0\u05D3\u05E8\u05E9\u05D5\u05EA \u05D0\u05E8\u05D1\u05E2 \u05E0\u05E7\u05D5\u05D3\u05D5\u05EA bezier");
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
num(v[0], `${path}.0`, 0, 1);
|
|
745
|
+
num(v[1], `${path}.1`, -4, 4);
|
|
746
|
+
num(v[2], `${path}.2`, 0, 1);
|
|
747
|
+
num(v[3], `${path}.3`, -4, 4);
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
if (record2(v)) {
|
|
751
|
+
known(v, path, ["stiffness", "damping", "mass"]);
|
|
752
|
+
num(v.stiffness, `${path}.stiffness`, 1e-3, 1e4);
|
|
753
|
+
num(v.damping, `${path}.damping`, 1e-3, 1e4);
|
|
754
|
+
num(v.mass, `${path}.mass`, 1e-3, 1e3);
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
fail3(path, "easing \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8");
|
|
758
|
+
};
|
|
759
|
+
const clip = (v, path) => {
|
|
760
|
+
if (!record2(v)) {
|
|
761
|
+
fail3(path, "\u05DE\u05E1\u05DB\u05D4 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D4");
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
if (v.type === "inset") {
|
|
765
|
+
known(v, path, ["type", "top", "right", "bottom", "left"]);
|
|
766
|
+
for (const key of ["top", "right", "bottom", "left"]) num(v[key], `${path}.${key}`, 0, 100);
|
|
767
|
+
} else if (v.type === "circle") {
|
|
768
|
+
known(v, path, ["type", "radius", "x", "y"]);
|
|
769
|
+
for (const key of ["radius", "x", "y"]) num(v[key], `${path}.${key}`, 0, 100);
|
|
770
|
+
} else fail3(`${path}.type`, "\u05E1\u05D5\u05D2 \u05DE\u05E1\u05DB\u05D4 \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8");
|
|
771
|
+
};
|
|
772
|
+
id(p.id, "id");
|
|
773
|
+
text3(p.title, "title", 500);
|
|
774
|
+
num(p.revision, "revision", 0, Number.MAX_SAFE_INTEGER);
|
|
775
|
+
for (const field of ["createdAt", "updatedAt"]) if (typeof p[field] !== "string" || !Number.isFinite(Date.parse(p[field]))) fail3(field, "\u05EA\u05D0\u05E8\u05D9\u05DA \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF");
|
|
776
|
+
if (!record2(p.canvas)) fail3("canvas", "\u05DE\u05D9\u05D3\u05D5\u05EA \u05D7\u05E1\u05E8\u05D5\u05EA");
|
|
777
|
+
else {
|
|
778
|
+
num(p.canvas.width, "canvas.width", 16, 8192);
|
|
779
|
+
num(p.canvas.height, "canvas.height", 16, 8192);
|
|
780
|
+
num(p.canvas.fps, "canvas.fps", 1, 120);
|
|
781
|
+
}
|
|
782
|
+
const assetIds = /* @__PURE__ */ new Set();
|
|
783
|
+
let expandedLayers = 0;
|
|
784
|
+
if (p.renderSettings !== void 0) {
|
|
785
|
+
if (!record2(p.renderSettings)) fail3("renderSettings", "\u05D4\u05D2\u05D3\u05E8\u05D5\u05EA \u05E8\u05D9\u05E0\u05D3\u05D5\u05E8 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D5\u05EA");
|
|
786
|
+
else {
|
|
787
|
+
known(p.renderSettings, "renderSettings", ["motionBlur"]);
|
|
788
|
+
if (p.renderSettings.motionBlur !== void 0) {
|
|
789
|
+
const blur = p.renderSettings.motionBlur;
|
|
790
|
+
if (!record2(blur)) fail3("renderSettings.motionBlur", "\u05D8\u05E9\u05D8\u05D5\u05E9 \u05EA\u05E0\u05D5\u05E2\u05D4 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF");
|
|
791
|
+
else {
|
|
792
|
+
known(blur, "renderSettings.motionBlur", ["samples", "shutterAngle"]);
|
|
793
|
+
integer(blur.samples, "renderSettings.motionBlur.samples", 1, 8);
|
|
794
|
+
num(blur.shutterAngle, "renderSettings.motionBlur.shutterAngle", 0, 360);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
if (!Array.isArray(p.assets) || p.assets.length > 1e3) fail3("assets", "\u05E8\u05E9\u05D9\u05DE\u05EA \u05E0\u05DB\u05E1\u05D9\u05DD \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D4");
|
|
800
|
+
else p.assets.forEach((a, i) => {
|
|
801
|
+
const at = `assets.${i}`;
|
|
802
|
+
if (!record2(a)) {
|
|
803
|
+
fail3(at, "\u05E0\u05DB\u05E1 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF");
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
id(a.id, at + ".id");
|
|
807
|
+
assetIds.add(a.id);
|
|
808
|
+
text3(a.name, at + ".name", 1e3);
|
|
809
|
+
text3(a.mime, at + ".mime", 100);
|
|
810
|
+
if (!["image", "video", "audio", "font"].includes(a.kind)) fail3(at + ".kind", "\u05E1\u05D5\u05D2 \u05E0\u05DB\u05E1 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF");
|
|
811
|
+
if (typeof a.src !== "string" || !isLocalAsset(a.src)) fail3(at + ".src", "\u05E0\u05D3\u05E8\u05E9 \u05E0\u05DB\u05E1 \u05DE\u05E7\u05D5\u05DE\u05D9 \u05DC\u05DC\u05D0 \u05E0\u05EA\u05D9\u05D1 \u05D7\u05D9\u05E6\u05D5\u05E0\u05D9");
|
|
812
|
+
if (a.duration !== void 0) num(a.duration, at + ".duration", 0, 86400);
|
|
813
|
+
});
|
|
814
|
+
const motions = ["none", "fade", "slide-up", "slide-left", "slide-right", "slide-down", "zoom", "pop", "typewriter", "mask-up", "blur-in", "drop", "flip-in", "scale-pop"];
|
|
815
|
+
const validateLayer = (l, lt, sceneDuration, siblings, depth = 0) => {
|
|
816
|
+
if (!record2(l)) {
|
|
817
|
+
fail3(lt, "\u05E9\u05DB\u05D1\u05D4 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D4");
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
if (depth > 4) {
|
|
821
|
+
fail3(lt, "\u05E7\u05D1\u05D5\u05E6\u05D5\u05EA \u05DE\u05E7\u05D5\u05E0\u05E0\u05D5\u05EA \u05E2\u05D3 \u05D0\u05E8\u05D1\u05E2 \u05E8\u05DE\u05D5\u05EA");
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
id(l.id, lt + ".id");
|
|
825
|
+
text3(l.name, lt + ".name", 500);
|
|
826
|
+
if (!["text", "shape", "image", "video", "path", "svg", "group", "repeater"].includes(l.type)) fail3(lt + ".type", "\u05E1\u05D5\u05D2 \u05E9\u05DB\u05D1\u05D4 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF");
|
|
827
|
+
expandedLayers += l.type === "repeater" && record2(l.repeater) && Number.isInteger(l.repeater.count) && l.repeater.count >= 1 && l.repeater.count <= 200 ? l.repeater.count : 1;
|
|
828
|
+
if (l.type === "text") text3(l.text, lt + ".text");
|
|
829
|
+
if (l.countFrom !== void 0) num(l.countFrom, lt + ".countFrom", -1e9, 1e9);
|
|
830
|
+
if (l.countTo !== void 0) num(l.countTo, lt + ".countTo", -1e9, 1e9);
|
|
831
|
+
if (l.countSuffix !== void 0) text3(l.countSuffix, lt + ".countSuffix", 40);
|
|
832
|
+
if (l.countPrefix !== void 0) text3(l.countPrefix, lt + ".countPrefix", 40);
|
|
833
|
+
if (l.countDecimals !== void 0) integer(l.countDecimals, lt + ".countDecimals", 0, 8);
|
|
834
|
+
if (l.countThousands !== void 0) bool(l.countThousands, lt + ".countThousands");
|
|
835
|
+
for (const prop of ["perspective", "skewX", "skewY", "rotateX", "rotateY", "glow", "depth"]) if (l[prop] !== void 0) {
|
|
836
|
+
const ranges = { perspective: [100, 4e3], skewX: [-85, 85], skewY: [-85, 85], rotateX: [-36e3, 36e3], rotateY: [-36e3, 36e3], glow: [0, 100], depth: [-1, 1] };
|
|
837
|
+
num(l[prop], `${lt}.${prop}`, ranges[prop][0], ranges[prop][1]);
|
|
838
|
+
}
|
|
839
|
+
if (l.glowColor !== void 0) hex2(l.glowColor, lt + ".glowColor");
|
|
840
|
+
if (l.clip !== void 0) clip(l.clip, lt + ".clip");
|
|
841
|
+
if (l.modifiers !== void 0) {
|
|
842
|
+
if (!Array.isArray(l.modifiers) || l.modifiers.length > 16) fail3(lt + ".modifiers", "\u05DE\u05D5\u05D3\u05D9\u05E4\u05D9\u05D9\u05E8\u05D9\u05DD \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D9\u05DD");
|
|
843
|
+
else l.modifiers.forEach((modifier, i) => {
|
|
844
|
+
const mt = `${lt}.modifiers.${i}`;
|
|
845
|
+
if (!record2(modifier)) {
|
|
846
|
+
fail3(mt, "\u05DE\u05D5\u05D3\u05D9\u05E4\u05D9\u05D9\u05E8 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF");
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
known(modifier, mt, ["type", "amplitude", "frequency", "seed"]);
|
|
850
|
+
if (!["float", "wiggle", "orbit", "spin"].includes(modifier.type)) fail3(mt + ".type", "\u05E1\u05D5\u05D2 \u05DE\u05D5\u05D3\u05D9\u05E4\u05D9\u05D9\u05E8 \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8");
|
|
851
|
+
num(modifier.amplitude, mt + ".amplitude", 0, 1e4);
|
|
852
|
+
num(modifier.frequency, mt + ".frequency", 0, 100);
|
|
853
|
+
seed(modifier.seed, mt + ".seed");
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
if (l.type === "repeater" && l.repeater === void 0) fail3(lt + ".repeater", "\u05E0\u05D3\u05E8\u05E9\u05D5\u05EA \u05D4\u05D2\u05D3\u05E8\u05D5\u05EA repeater");
|
|
857
|
+
if (l.repeater !== void 0) {
|
|
858
|
+
if (l.type !== "repeater") fail3(lt + ".repeater", "\u05D4\u05D2\u05D3\u05E8\u05D5\u05EA repeater \u05D6\u05DE\u05D9\u05E0\u05D5\u05EA \u05DC\u05E9\u05DB\u05D1\u05EA repeater \u05D1\u05DC\u05D1\u05D3");
|
|
859
|
+
if (!record2(l.repeater)) fail3(lt + ".repeater", "\u05D4\u05D2\u05D3\u05E8\u05D5\u05EA repeater \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D5\u05EA");
|
|
860
|
+
else {
|
|
861
|
+
const rt = lt + ".repeater";
|
|
862
|
+
const r = l.repeater;
|
|
863
|
+
known(r, rt, ["count", "seed", "shape", "offsetX", "offsetY", "rotation", "delay", "jitterX", "jitterY", "jitterRotation", "jitterDelay", "colors"]);
|
|
864
|
+
integer(r.count, rt + ".count", 1, 200);
|
|
865
|
+
seed(r.seed, rt + ".seed");
|
|
866
|
+
if (!["rect", "ellipse", "diamond"].includes(r.shape)) fail3(rt + ".shape", "\u05E6\u05D5\u05E8\u05EA repeater \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8\u05EA");
|
|
867
|
+
for (const prop of ["offsetX", "offsetY", "jitterX", "jitterY"]) if (r[prop] !== void 0) num(r[prop], `${rt}.${prop}`, -32768, 32768);
|
|
868
|
+
for (const prop of ["rotation", "jitterRotation"]) if (r[prop] !== void 0) num(r[prop], `${rt}.${prop}`, -36e3, 36e3);
|
|
869
|
+
for (const prop of ["delay", "jitterDelay"]) if (r[prop] !== void 0) num(r[prop], `${rt}.${prop}`, 0, 3600);
|
|
870
|
+
if (r.offsetX === void 0) num(r.offsetX, rt + ".offsetX", -32768, 32768);
|
|
871
|
+
if (r.offsetY === void 0) num(r.offsetY, rt + ".offsetY", -32768, 32768);
|
|
872
|
+
if (r.rotation === void 0) num(r.rotation, rt + ".rotation", -36e3, 36e3);
|
|
873
|
+
if (r.delay === void 0) num(r.delay, rt + ".delay", 0, 3600);
|
|
874
|
+
if (Number.isFinite(r.count) && Number.isFinite(r.delay) && Number.isFinite(l.duration) && (r.count - 1) * r.delay + (r.jitterDelay ?? 0) >= l.duration) fail3(rt + ".delay", "\u05DB\u05DC \u05D4\u05E2\u05D5\u05EA\u05E7\u05D9\u05DD \u05E6\u05E8\u05D9\u05DB\u05D9\u05DD \u05DC\u05D4\u05EA\u05D7\u05D9\u05DC \u05D1\u05EA\u05D5\u05DA \u05DE\u05E9\u05DA \u05D4\u05E9\u05DB\u05D1\u05D4");
|
|
875
|
+
if (r.colors !== void 0) {
|
|
876
|
+
if (!Array.isArray(r.colors) || r.colors.length > 200) fail3(rt + ".colors", "\u05E6\u05D1\u05E2\u05D9 repeater \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D9\u05DD");
|
|
877
|
+
else r.colors.forEach((color, i) => hex2(color, `${rt}.colors.${i}`));
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
if (l.revealBinding !== void 0) {
|
|
882
|
+
const bt = lt + ".revealBinding";
|
|
883
|
+
const binding = l.revealBinding;
|
|
884
|
+
if (!record2(binding)) fail3(bt, "\u05E7\u05D9\u05E9\u05D5\u05E8 reveal \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF");
|
|
885
|
+
else {
|
|
886
|
+
known(binding, bt, ["layerId", "from", "to"]);
|
|
887
|
+
const source = siblings.find((sibling) => record2(sibling) && sibling.id === binding.layerId);
|
|
888
|
+
if (!["path", "svg", "shape"].includes(l.type)) fail3(bt, "\u05E7\u05D9\u05E9\u05D5\u05E8 reveal \u05D6\u05DE\u05D9\u05DF \u05DC\u05E9\u05DB\u05D1\u05EA \u05E6\u05D5\u05E8\u05D4 \u05D0\u05D5 \u05E0\u05EA\u05D9\u05D1 \u05D1\u05DC\u05D1\u05D3");
|
|
889
|
+
if (typeof binding.layerId !== "string" || !source || source === l || !record2(source) || source.revealBinding !== void 0 || !(source.type === "text" && typeof source.countTo === "number" && Number.isFinite(source.countTo)) && !(Array.isArray(source.keyframes) && source.keyframes.some((point2) => record2(point2) && typeof point2.value === "number" && Number.isFinite(point2.value))))
|
|
890
|
+
fail3(bt + ".layerId", "\u05E0\u05D3\u05E8\u05E9 \u05DE\u05E7\u05D5\u05E8 \u05DE\u05E1\u05E4\u05E8\u05D9 \u05D0\u05D7\u05D0\u05D9 \u05DC\u05DC\u05D0 \u05E7\u05D9\u05E9\u05D5\u05E8 \u05E0\u05D5\u05E1\u05E3");
|
|
891
|
+
num(binding.from, bt + ".from", -1e9, 1e9);
|
|
892
|
+
num(binding.to, bt + ".to", -1e9, 1e9);
|
|
893
|
+
if (binding.from === binding.to) fail3(bt + ".to", "\u05E0\u05E7\u05D5\u05D3\u05D5\u05EA \u05EA\u05D7\u05D5\u05DD \u05D7\u05D9\u05D9\u05D1\u05D5\u05EA \u05DC\u05D4\u05D9\u05D5\u05EA \u05E9\u05D5\u05E0\u05D5\u05EA");
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
if (l.staggerOrder !== void 0 && !["start", "end", "center", "seeded-random"].includes(l.staggerOrder)) fail3(lt + ".staggerOrder", "\u05E1\u05D3\u05E8 stagger \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8");
|
|
897
|
+
if (l.staggerSeed !== void 0) seed(l.staggerSeed, lt + ".staggerSeed");
|
|
898
|
+
if (l.staggerToBeats !== void 0) bool(l.staggerToBeats, lt + ".staggerToBeats");
|
|
899
|
+
if (l.staggerBeatOffset !== void 0) integer(l.staggerBeatOffset, lt + ".staggerBeatOffset", 0, 1e4);
|
|
900
|
+
if (l.textUnitColors !== void 0) {
|
|
901
|
+
if (l.type !== "text" || !Array.isArray(l.textUnitColors) || l.textUnitColors.length > 1e4) fail3(lt + ".textUnitColors", "\u05E6\u05D1\u05E2\u05D9 \u05D9\u05D7\u05D9\u05D3\u05D5\u05EA \u05D8\u05E7\u05E1\u05D8 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D9\u05DD");
|
|
902
|
+
else l.textUnitColors.forEach((color, i) => hex2(color, `${lt}.textUnitColors.${i}`));
|
|
903
|
+
}
|
|
904
|
+
if (l.textFit !== void 0 && !["shrink", "warn"].includes(l.textFit)) fail3(lt + ".textFit", "\u05D4\u05EA\u05D0\u05DE\u05EA \u05D8\u05E7\u05E1\u05D8 \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8\u05EA");
|
|
905
|
+
if (l.type === "path" || l.type === "svg") {
|
|
906
|
+
if (typeof l.pathData !== "string" || l.pathData.length > 2e4 || !/^[MmLlHhVvCcSsQqTtAaZz0-9eE+\-.,\s]+$/.test(l.pathData)) fail3(lt + ".pathData", "\u05E0\u05D3\u05E8\u05E9 \u05E0\u05EA\u05D9\u05D1 SVG \u05EA\u05E7\u05D9\u05DF \u05DC\u05DC\u05D0 \u05E7\u05D5\u05D3");
|
|
907
|
+
if (l.stroke !== void 0) text3(l.stroke, lt + ".stroke", 100);
|
|
908
|
+
if (l.strokeWidth !== void 0) num(l.strokeWidth, lt + ".strokeWidth", 0, 1e3);
|
|
909
|
+
}
|
|
910
|
+
if (l.type === "group" && (!Array.isArray(l.children) || l.children.length > 200)) fail3(lt + ".children", "\u05E7\u05D1\u05D5\u05E6\u05D4 \u05E6\u05E8\u05D9\u05DB\u05D4 \u05E8\u05E9\u05D9\u05DE\u05EA \u05E9\u05DB\u05D1\u05D5\u05EA");
|
|
911
|
+
if (l.children !== void 0 && l.type !== "group") fail3(lt + ".children", "\u05E8\u05E7 \u05DC\u05E7\u05D1\u05D5\u05E6\u05D4 \u05D9\u05E9 \u05E9\u05DB\u05D1\u05D5\u05EA \u05E4\u05E0\u05D9\u05DE\u05D9\u05D5\u05EA");
|
|
912
|
+
for (const prop of ["x", "y"]) num(l[prop], `${lt}.${prop}`, -32768, 32768);
|
|
913
|
+
for (const prop of ["width", "height"]) num(l[prop], `${lt}.${prop}`, 1, 32768);
|
|
914
|
+
num(l.rotation, lt + ".rotation", -36e3, 36e3);
|
|
915
|
+
num(l.opacity, lt + ".opacity", 0, 1);
|
|
916
|
+
num(l.fontSize, lt + ".fontSize", 1, 2e3);
|
|
917
|
+
num(l.fontWeight, lt + ".fontWeight", 100, 1e3);
|
|
918
|
+
num(l.borderRadius, lt + ".borderRadius", 0, 16e3);
|
|
919
|
+
text3(l.color, lt + ".color", 500);
|
|
920
|
+
text3(l.fontFamily, lt + ".fontFamily", 200);
|
|
921
|
+
if (!["left", "center", "right"].includes(l.textAlign)) fail3(lt + ".textAlign", "\u05D9\u05D9\u05E9\u05D5\u05E8 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF");
|
|
922
|
+
if (!motions.includes(l.motion)) fail3(lt + ".motion", "\u05EA\u05E0\u05D5\u05E2\u05D4 \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8\u05EA");
|
|
923
|
+
if (l.motionOut !== void 0 && !motions.includes(l.motionOut)) fail3(lt + ".motionOut", "\u05EA\u05E0\u05D5\u05E2\u05EA \u05D9\u05E6\u05D9\u05D0\u05D4 \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8\u05EA");
|
|
924
|
+
if (l.easing !== void 0) easing(l.easing, lt + ".easing");
|
|
925
|
+
if (l.splitText !== void 0 && !["none", "word", "letter"].includes(l.splitText)) fail3(lt + ".splitText", "\u05E4\u05D9\u05E6\u05D5\u05DC \u05D8\u05E7\u05E1\u05D8 \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8");
|
|
926
|
+
if (l.transformOrigin !== void 0 && !["center", "left center", "right center", "center top", "center bottom"].includes(l.transformOrigin)) fail3(lt + ".transformOrigin", "\u05E0\u05E7\u05D5\u05D3\u05EA \u05E2\u05D9\u05D2\u05D5\u05DF \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8\u05EA");
|
|
927
|
+
if (l.blendMode !== void 0 && !["normal", "multiply", "screen", "overlay", "darken", "lighten"].includes(l.blendMode)) fail3(lt + ".blendMode", "\u05DE\u05E6\u05D1 \u05E9\u05D9\u05DC\u05D5\u05D1 \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8");
|
|
928
|
+
for (const [prop, min, max] of [["motionDuration", 0.01, 3600], ["motionDelay", 0, 3600], ["motionOutDuration", 0.01, 3600], ["stagger", 0, 5], ["borderWidth", 0, 1e3], ["letterSpacing", -100, 100], ["lineHeight", 0.5, 5], ["blur", 0, 100]]) if (l[prop] !== void 0) num(l[prop], `${lt}.${prop}`, min, max);
|
|
929
|
+
for (const prop of ["shadow", "borderColor"]) if (l[prop] !== void 0) text3(l[prop], `${lt}.${prop}`, 500);
|
|
930
|
+
num(l.start, lt + ".start", 0, sceneDuration);
|
|
931
|
+
num(l.duration, lt + ".duration", 0.01, 3600);
|
|
932
|
+
for (const field of ["keyframes", "textUnitKeyframes"]) if (l[field] !== void 0) {
|
|
933
|
+
if (field === "textUnitKeyframes" && l.type !== "text") fail3(lt + "." + field, "\u05EA\u05E0\u05D5\u05E2\u05EA \u05DE\u05D9\u05DC\u05D9\u05DD \u05D6\u05DE\u05D9\u05E0\u05D4 \u05DC\u05E9\u05DB\u05D1\u05EA \u05D8\u05E7\u05E1\u05D8 \u05D1\u05DC\u05D1\u05D3");
|
|
934
|
+
if (!Array.isArray(l[field]) || l[field].length < 2 || l[field].length > 100) fail3(lt + "." + field, "\u05E0\u05D3\u05E8\u05E9\u05D5\u05EA 2\u2013100 \u05E0\u05E7\u05D5\u05D3\u05D5\u05EA \u05EA\u05E0\u05D5\u05E2\u05D4");
|
|
935
|
+
else {
|
|
936
|
+
let previous = -1;
|
|
937
|
+
l[field].forEach((keyframe, k) => {
|
|
938
|
+
const kt = `${lt}.${field}.${k}`;
|
|
939
|
+
if (!record2(keyframe)) {
|
|
940
|
+
fail3(kt, "\u05E0\u05E7\u05D5\u05D3\u05EA \u05EA\u05E0\u05D5\u05E2\u05D4 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D4");
|
|
941
|
+
return;
|
|
942
|
+
}
|
|
943
|
+
num(keyframe.at, kt + ".at", 0, l.duration);
|
|
944
|
+
if (typeof keyframe.at === "number" && keyframe.at <= previous) fail3(kt + ".at", "\u05E0\u05E7\u05D5\u05D3\u05D5\u05EA \u05D4\u05D6\u05DE\u05DF \u05D7\u05D9\u05D9\u05D1\u05D5\u05EA \u05DC\u05E2\u05DC\u05D5\u05EA");
|
|
945
|
+
previous = keyframe.at;
|
|
946
|
+
for (const property of ["x", "y"]) num(keyframe[property], kt + "." + property, -32768, 32768);
|
|
947
|
+
for (const property of ["scaleX", "scaleY"]) num(keyframe[property], kt + "." + property, 0, 100);
|
|
948
|
+
if (keyframe.scale !== void 0) num(keyframe.scale, kt + ".scale", 0, 100);
|
|
949
|
+
if (keyframe.easing !== void 0) easing(keyframe.easing, kt + ".easing");
|
|
950
|
+
num(keyframe.rotation, kt + ".rotation", -36e3, 36e3);
|
|
951
|
+
num(keyframe.opacity, kt + ".opacity", 0, 1);
|
|
952
|
+
if (keyframe.value !== void 0) num(keyframe.value, kt + ".value", -1e9, 1e9);
|
|
953
|
+
if (keyframe.reveal !== void 0) num(keyframe.reveal, kt + ".reveal", 0, 1);
|
|
954
|
+
if (keyframe.color !== void 0) hex2(keyframe.color, kt + ".color");
|
|
955
|
+
for (const prop of ["blur", "glow"]) if (keyframe[prop] !== void 0) num(keyframe[prop], `${kt}.${prop}`, 0, 100);
|
|
956
|
+
for (const prop of ["skewX", "skewY"]) if (keyframe[prop] !== void 0) num(keyframe[prop], `${kt}.${prop}`, -85, 85);
|
|
957
|
+
for (const prop of ["rotateX", "rotateY"]) if (keyframe[prop] !== void 0) num(keyframe[prop], `${kt}.${prop}`, -36e3, 36e3);
|
|
958
|
+
if (keyframe.clip !== void 0) clip(keyframe.clip, kt + ".clip");
|
|
959
|
+
if (keyframe.borderRadius !== void 0) num(keyframe.borderRadius, kt + ".borderRadius", 0, 16e3);
|
|
960
|
+
if (keyframe.letterSpacing !== void 0) num(keyframe.letterSpacing, kt + ".letterSpacing", -100, 100);
|
|
961
|
+
if (keyframe.snapToBeat !== void 0) bool(keyframe.snapToBeat, kt + ".snapToBeat");
|
|
962
|
+
});
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
if (["keyframes", "textUnitKeyframes"].some((field) => Array.isArray(l[field]) && l[field].some((point2) => record2(point2) && point2.color !== void 0)))
|
|
966
|
+
hex2(l.color, lt + ".color");
|
|
967
|
+
for (const prop of ["hidden", "locked"]) if (typeof l[prop] !== "boolean") fail3(`${lt}.${prop}`, "\u05E0\u05D3\u05E8\u05E9 \u05E2\u05E8\u05DA \u05D1\u05D5\u05DC\u05D9\u05D0\u05E0\u05D9");
|
|
968
|
+
if (l.assetId !== void 0 && !assetIds.has(l.assetId)) fail3(lt + ".assetId", "\u05D4\u05E0\u05DB\u05E1 \u05D7\u05E1\u05E8 \u05D1\u05E4\u05E8\u05D5\u05D9\u05E7\u05D8");
|
|
969
|
+
if (Array.isArray(l.children)) l.children.forEach((child, index) => validateLayer(child, `${lt}.children.${index}`, l.duration, l.children, depth + 1));
|
|
970
|
+
};
|
|
971
|
+
if (!Array.isArray(p.scenes) || p.scenes.length > 1e3 || p.mode === "authored" && !p.scenes.length) fail3("scenes", "\u05E8\u05E9\u05D9\u05DE\u05EA \u05E1\u05E6\u05E0\u05D5\u05EA \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D4");
|
|
972
|
+
else p.scenes.forEach((s, i) => {
|
|
973
|
+
const at = `scenes.${i}`;
|
|
974
|
+
if (!record2(s)) {
|
|
975
|
+
fail3(at, "\u05E1\u05E6\u05E0\u05D4 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D4");
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
id(s.id, at + ".id");
|
|
979
|
+
text3(s.name, at + ".name", 500);
|
|
980
|
+
text3(s.background, at + ".background", 500);
|
|
981
|
+
num(s.duration, at + ".duration", 0.01, 3600);
|
|
982
|
+
if (!["cut", "fade", "slide", "wipe", "zoom", "push", "iris", "diagonal-wipe", "whip", "zoom-through", "stack"].includes(s.transition)) fail3(at + ".transition", "\u05DE\u05E2\u05D1\u05E8 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF");
|
|
983
|
+
if (s.transitionDuration !== void 0) num(s.transitionDuration, at + ".transitionDuration", 0.01, s.duration);
|
|
984
|
+
if (s.transitionEasing !== void 0) easing(s.transitionEasing, at + ".transitionEasing");
|
|
985
|
+
if (s.configV3 !== void 0) {
|
|
986
|
+
const rt = at + ".configV3";
|
|
987
|
+
if (p.schemaVersion !== 3) fail3(rt, "\u05DE\u05EA\u05DB\u05D5\u05DF v3 \u05D3\u05D5\u05E8\u05E9 \u05E4\u05E8\u05D5\u05D9\u05E7\u05D8 \u05D1\u05D2\u05E8\u05E1\u05D4 3");
|
|
988
|
+
if (!record2(s.configV3) || ![Object.prototype, null].includes(Object.getPrototypeOf(s.configV3))) fail3(rt, "\u05DE\u05EA\u05DB\u05D5\u05DF v3 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF");
|
|
989
|
+
else {
|
|
990
|
+
known(s.configV3, rt, ["config", "sceneIndex"]);
|
|
991
|
+
try {
|
|
992
|
+
const config = parseMotionConfigV3(s.configV3.config);
|
|
993
|
+
integer(s.configV3.sceneIndex, rt + ".sceneIndex", 0, config.scenes.length - 1);
|
|
994
|
+
} catch (error) {
|
|
995
|
+
fail3(rt + ".config", error instanceof Error ? error.message : "\u05DE\u05EA\u05DB\u05D5\u05DF v3 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF");
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
if (s.camera !== void 0) {
|
|
1000
|
+
const ct = at + ".camera";
|
|
1001
|
+
if (!record2(s.camera)) fail3(ct, "\u05DE\u05E6\u05DC\u05DE\u05D4 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D4");
|
|
1002
|
+
else {
|
|
1003
|
+
known(s.camera, ct, ["keyframes"]);
|
|
1004
|
+
if (!Array.isArray(s.camera.keyframes) || s.camera.keyframes.length < 1 || s.camera.keyframes.length > 100) fail3(ct + ".keyframes", "\u05E0\u05E7\u05D5\u05D3\u05D5\u05EA \u05DE\u05E6\u05DC\u05DE\u05D4 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D5\u05EA");
|
|
1005
|
+
else {
|
|
1006
|
+
let previous = -1;
|
|
1007
|
+
s.camera.keyframes.forEach((frame, k) => {
|
|
1008
|
+
const ft = `${ct}.keyframes.${k}`;
|
|
1009
|
+
if (!record2(frame)) {
|
|
1010
|
+
fail3(ft, "\u05E0\u05E7\u05D5\u05D3\u05EA \u05DE\u05E6\u05DC\u05DE\u05D4 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D4");
|
|
1011
|
+
return;
|
|
1012
|
+
}
|
|
1013
|
+
known(frame, ft, ["at", "x", "y", "zoom", "rotation", "easing"]);
|
|
1014
|
+
num(frame.at, ft + ".at", 0, s.duration);
|
|
1015
|
+
if (typeof frame.at === "number" && frame.at <= previous) fail3(ft + ".at", "\u05E0\u05E7\u05D5\u05D3\u05D5\u05EA \u05D4\u05D6\u05DE\u05DF \u05D7\u05D9\u05D9\u05D1\u05D5\u05EA \u05DC\u05E2\u05DC\u05D5\u05EA");
|
|
1016
|
+
previous = frame.at;
|
|
1017
|
+
num(frame.x, ft + ".x", -32768, 32768);
|
|
1018
|
+
num(frame.y, ft + ".y", -32768, 32768);
|
|
1019
|
+
num(frame.zoom, ft + ".zoom", 0.01, 100);
|
|
1020
|
+
num(frame.rotation, ft + ".rotation", -36e3, 36e3);
|
|
1021
|
+
if (frame.easing !== void 0) easing(frame.easing, ft + ".easing");
|
|
1022
|
+
});
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
if (!Array.isArray(s.layers) || s.layers.length > 1e3) {
|
|
1027
|
+
fail3(at + ".layers", "\u05E9\u05DB\u05D1\u05D5\u05EA \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D5\u05EA");
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
s.layers.forEach((l, j) => validateLayer(l, `${at}.layers.${j}`, s.duration, s.layers));
|
|
1031
|
+
});
|
|
1032
|
+
if (expandedLayers > 1e4) fail3("scenes", "\u05D9\u05D5\u05EA\u05E8 \u05DE\u05D3\u05D9 \u05E9\u05DB\u05D1\u05D5\u05EA \u05DC\u05D0\u05D7\u05E8 \u05E9\u05DB\u05E4\u05D5\u05DC");
|
|
1033
|
+
if (!Array.isArray(p.mediaTracks) || p.mediaTracks.length > 100) fail3("mediaTracks", "\u05E8\u05E6\u05D5\u05E2\u05D5\u05EA \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D5\u05EA");
|
|
1034
|
+
else p.mediaTracks.forEach((t, i) => {
|
|
1035
|
+
const at = `mediaTracks.${i}`;
|
|
1036
|
+
if (!record2(t)) {
|
|
1037
|
+
fail3(at, "\u05E8\u05E6\u05D5\u05E2\u05D4 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D4");
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1040
|
+
id(t.id, at + ".id");
|
|
1041
|
+
text3(t.name, at + ".name", 500);
|
|
1042
|
+
if (!["video", "audio"].includes(t.type)) fail3(at + ".type", "\u05E1\u05D5\u05D2 \u05E8\u05E6\u05D5\u05E2\u05D4 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF");
|
|
1043
|
+
if (typeof t.muted !== "boolean") fail3(at + ".muted", "\u05E0\u05D3\u05E8\u05E9 \u05E2\u05E8\u05DA \u05D1\u05D5\u05DC\u05D9\u05D0\u05E0\u05D9");
|
|
1044
|
+
if (!Array.isArray(t.clips) || t.clips.length > 1e4) {
|
|
1045
|
+
fail3(at + ".clips", "\u05E7\u05DC\u05D9\u05E4\u05D9\u05DD \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D9\u05DD");
|
|
1046
|
+
return;
|
|
1047
|
+
}
|
|
1048
|
+
t.clips.forEach((c, j) => {
|
|
1049
|
+
const ct = `${at}.clips.${j}`;
|
|
1050
|
+
if (!record2(c)) {
|
|
1051
|
+
fail3(ct, "\u05E7\u05DC\u05D9\u05E4 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF");
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
id(c.id, ct + ".id");
|
|
1055
|
+
if (!assetIds.has(c.assetId)) fail3(ct + ".assetId", "\u05E0\u05DB\u05E1 \u05D4\u05E7\u05DC\u05D9\u05E4 \u05D7\u05E1\u05E8");
|
|
1056
|
+
num(c.start, ct + ".start", 0, 86400);
|
|
1057
|
+
num(c.in, ct + ".in", 0, 86400);
|
|
1058
|
+
num(c.out, ct + ".out", 0.01, 86400);
|
|
1059
|
+
num(c.volume, ct + ".volume", 0, 4);
|
|
1060
|
+
if (c.out <= c.in) fail3(ct + ".out", "\u05E1\u05D9\u05D5\u05DD \u05D7\u05D9\u05D9\u05D1 \u05DC\u05D4\u05D9\u05D5\u05EA \u05D0\u05D7\u05E8\u05D9 \u05D4\u05D4\u05EA\u05D7\u05DC\u05D4");
|
|
1061
|
+
const asset = Array.isArray(p.assets) ? p.assets.find((a) => a?.id === c.assetId) : void 0;
|
|
1062
|
+
if (asset?.duration !== void 0 && c.out > asset.duration + 1e-3) fail3(ct + ".out", "\u05E1\u05D9\u05D5\u05DD \u05DE\u05E2\u05D1\u05E8 \u05DC\u05D0\u05D5\u05E8\u05DA \u05D4\u05DE\u05E7\u05D5\u05E8");
|
|
1063
|
+
if (typeof c.muted !== "boolean") fail3(ct + ".muted", "\u05E0\u05D3\u05E8\u05E9 \u05E2\u05E8\u05DA \u05D1\u05D5\u05DC\u05D9\u05D0\u05E0\u05D9");
|
|
1064
|
+
});
|
|
1065
|
+
});
|
|
1066
|
+
if (p.beats !== void 0) {
|
|
1067
|
+
if (!Array.isArray(p.beats) || p.beats.length > 1e5) fail3("beats", "\u05E1\u05D9\u05DE\u05D5\u05E0\u05D9 \u05E7\u05E6\u05D1 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D9\u05DD");
|
|
1068
|
+
else {
|
|
1069
|
+
const sceneDuration = Array.isArray(p.scenes) ? p.scenes.reduce((sum, scene) => sum + (record2(scene) && typeof scene.duration === "number" && Number.isFinite(scene.duration) ? scene.duration : 0), 0) : 0;
|
|
1070
|
+
const mediaDuration = Array.isArray(p.mediaTracks) ? p.mediaTracks.reduce((longest, track) => Math.max(longest, record2(track) && Array.isArray(track.clips) ? track.clips.reduce((clipMax, item) => Math.max(clipMax, record2(item) && [item.start, item.in, item.out].every((v) => typeof v === "number" && Number.isFinite(v)) ? item.start + item.out - item.in : 0), 0) : 0), 0) : 0;
|
|
1071
|
+
const duration = Math.max(sceneDuration, mediaDuration, 0);
|
|
1072
|
+
let previous = -1;
|
|
1073
|
+
p.beats.forEach((beat, i) => {
|
|
1074
|
+
num(beat, `beats.${i}`, 0, duration);
|
|
1075
|
+
if (typeof beat === "number" && beat <= previous) fail3(`beats.${i}`, "\u05E1\u05D9\u05DE\u05D5\u05E0\u05D9 \u05E7\u05E6\u05D1 \u05D7\u05D9\u05D9\u05D1\u05D9\u05DD \u05DC\u05E2\u05DC\u05D5\u05EA \u05DC\u05DC\u05D0 \u05DB\u05E4\u05D9\u05DC\u05D5\u05D9\u05D5\u05EA");
|
|
1076
|
+
previous = typeof beat === "number" ? beat : previous;
|
|
1077
|
+
});
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
if (p.source !== void 0) {
|
|
1081
|
+
if (!record2(p.source)) fail3("source", "\u05DE\u05E7\u05D5\u05E8 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF");
|
|
1082
|
+
else {
|
|
1083
|
+
if (p.source.sourceUrl !== void 0 && (typeof p.source.sourceUrl !== "string" || p.source.sourceUrl.startsWith("data:") || !isLocalAsset(p.source.sourceUrl))) fail3("source.sourceUrl", "\u05E0\u05D3\u05E8\u05E9 \u05DE\u05D6\u05D4\u05D4 \u05DE\u05E7\u05D5\u05E8 \u05DE\u05E7\u05D5\u05DE\u05D9");
|
|
1084
|
+
text3(p.source.filename, "source.filename", 500);
|
|
1085
|
+
text3(p.source.original, "source.original", 1e7);
|
|
1086
|
+
text3(p.source.current, "source.current", 1e7);
|
|
1087
|
+
if (p.source.execution !== "disabled") fail3("source.execution", "\u05D4\u05E8\u05E6\u05EA \u05DE\u05E7\u05D5\u05E8 \u05D7\u05D9\u05E6\u05D5\u05E0\u05D9 \u05D0\u05D9\u05E0\u05D4 \u05DE\u05D5\u05EA\u05E8\u05EA");
|
|
1088
|
+
if (!["html", "hyperframes"].includes(p.source.detectedEngine)) fail3("source.detectedEngine", "\u05DE\u05E0\u05D5\u05E2 \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8");
|
|
1089
|
+
if (!Array.isArray(p.source.warnings) || !p.source.warnings.every((w) => typeof w === "string")) fail3("source.warnings", "\u05D0\u05D6\u05D4\u05E8\u05D5\u05EA \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D5\u05EA");
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
if (p.mode === "imported-source" && !p.source) fail3("source", "\u05DE\u05E7\u05D5\u05E8 \u05D7\u05E1\u05E8");
|
|
1093
|
+
return issues;
|
|
1094
|
+
}
|
|
1095
|
+
function projectWarnings(project) {
|
|
1096
|
+
if (project.schemaVersion !== 3 || !Array.isArray(project.scenes)) return [];
|
|
1097
|
+
const issues = [];
|
|
1098
|
+
const visit = (layers, path, parentHidden = false) => {
|
|
1099
|
+
layers.forEach((layer2, index) => {
|
|
1100
|
+
const at = `${path}.${index}`;
|
|
1101
|
+
const hidden = parentHidden || layer2.hidden;
|
|
1102
|
+
if (!hidden && layer2.type === "text" && layer2.textFit === "shrink" && typeof layer2.text === "string") {
|
|
1103
|
+
const rest = evaluateLayer(layer2, layer2.start + Math.max(0, layer2.duration * 0.8), { schemaVersion: project.schemaVersion, canvas: project.canvas, layers });
|
|
1104
|
+
const fontSize = Number.parseFloat(String(layerStyle(layer2, rest).fontSize));
|
|
1105
|
+
if (rest.visible && Number.isFinite(fontSize) && fontSize < 16)
|
|
1106
|
+
issues.push({ path: `${at}.text`, message: `\u05D4\u05D8\u05E7\u05E1\u05D8 \u201E${layer2.name}\u201D \u05E7\u05D8\u05DF \u05DE\u05BE16 \u05E4\u05D9\u05E7\u05E1\u05DC\u05D9\u05DD \u05DC\u05D0\u05D7\u05E8 \u05D4\u05EA\u05D0\u05DE\u05D4 \u05DC\u05DE\u05E1\u05D2\u05E8\u05EA. \u05E4\u05E6\u05DC \u05D0\u05EA \u05D4\u05EA\u05D5\u05DB\u05DF \u05DC\u05DB\u05DE\u05D4 \u05E1\u05E6\u05E0\u05D5\u05EA \u05D0\u05D5 \u05E7\u05E6\u05E8 \u05D0\u05EA \u05D4\u05E8\u05E9\u05D9\u05DE\u05D4.` });
|
|
1107
|
+
}
|
|
1108
|
+
if (layer2.type === "text" && layer2.textFit !== "shrink" && typeof layer2.text === "string" && Number.isFinite(layer2.width) && layer2.width > 0 && Number.isFinite(layer2.height) && layer2.height > 0 && Number.isFinite(layer2.fontSize) && layer2.fontSize > 0) {
|
|
1109
|
+
const charactersPerLine = Math.max(1, Math.floor(layer2.width / (layer2.fontSize * 0.55)));
|
|
1110
|
+
const requiredLines = layer2.text.split("\n").reduce((lines, part) => lines + Math.max(1, Math.ceil(Array.from(part).length / charactersPerLine)), 0);
|
|
1111
|
+
const lineHeight = typeof layer2.lineHeight === "number" && Number.isFinite(layer2.lineHeight) ? layer2.lineHeight : 1.2;
|
|
1112
|
+
if (requiredLines * layer2.fontSize * lineHeight > layer2.height * 1.05)
|
|
1113
|
+
issues.push({ path: `${at}.text`, message: "\u05D4\u05D8\u05E7\u05E1\u05D8 \u05E2\u05DC\u05D5\u05DC \u05DC\u05D7\u05E8\u05D5\u05D2 \u05DE\u05D2\u05D1\u05D5\u05DC\u05D5\u05EA \u05D4\u05EA\u05D9\u05D1\u05D4" });
|
|
1114
|
+
}
|
|
1115
|
+
if (Array.isArray(layer2.children)) visit(layer2.children, `${at}.children`, hidden);
|
|
1116
|
+
});
|
|
1117
|
+
};
|
|
1118
|
+
project.scenes.forEach((scene, index) => {
|
|
1119
|
+
if (Array.isArray(scene.layers)) visit(scene.layers, `scenes.${index}.layers`);
|
|
1120
|
+
});
|
|
1121
|
+
return issues;
|
|
1122
|
+
}
|
|
1123
|
+
function assertProject(value) {
|
|
1124
|
+
const issues = validateProject(value);
|
|
1125
|
+
if (issues.length) throw new Error(issues.slice(0, 5).map((issue) => `${issue.path}: ${issue.message}`).join("\n"));
|
|
1126
|
+
}
|
|
1127
|
+
function serializeProject(project) {
|
|
1128
|
+
return JSON.stringify(migrateProject(project), null, 2);
|
|
1129
|
+
}
|
|
1130
|
+
function parseProject(json) {
|
|
1131
|
+
if (json.length > 1e8) throw new Error("\u05E7\u05D5\u05D1\u05E5 \u05D4\u05E4\u05E8\u05D5\u05D9\u05E7\u05D8 \u05D2\u05D3\u05D5\u05DC \u05DE\u05D3\u05D9");
|
|
1132
|
+
const value = JSON.parse(json);
|
|
1133
|
+
return migrateProject(value);
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
// src/core/scene-style.ts
|
|
1137
|
+
function sceneStyle(scene, progress, outgoing = false, schemaVersion = 2) {
|
|
1138
|
+
const p = Math.max(0, Math.min(1, progress));
|
|
1139
|
+
const ease = (p2, name = "smooth", seconds = 1) => {
|
|
1140
|
+
const t = Math.max(0, Math.min(1, p2));
|
|
1141
|
+
if (Array.isArray(name)) {
|
|
1142
|
+
const [x1, y1, x2, y2] = name;
|
|
1143
|
+
const curve = (u, a, b) => 3 * (1 - u) * (1 - u) * u * a + 3 * (1 - u) * u * u * b + u * u * u;
|
|
1144
|
+
let lo = 0, hi = 1;
|
|
1145
|
+
for (let i = 0; i < 24; i++) {
|
|
1146
|
+
const mid = (lo + hi) / 2;
|
|
1147
|
+
if (curve(mid, x1, x2) < t) lo = mid;
|
|
1148
|
+
else hi = mid;
|
|
1149
|
+
}
|
|
1150
|
+
return t === 0 || t === 1 ? t : curve((lo + hi) / 2, y1, y2);
|
|
1151
|
+
}
|
|
1152
|
+
if (typeof name === "object") {
|
|
1153
|
+
const { stiffness: k, damping: c, mass: m } = name, w = Math.sqrt(k / m), z = c / (2 * Math.sqrt(k * m));
|
|
1154
|
+
const response = (s) => {
|
|
1155
|
+
if (z < 1 - 1e-6) {
|
|
1156
|
+
const wd = w * Math.sqrt(1 - z * z);
|
|
1157
|
+
return 1 - Math.exp(-z * w * s) * (Math.cos(wd * s) + z * w / wd * Math.sin(wd * s));
|
|
1158
|
+
}
|
|
1159
|
+
if (z <= 1 + 1e-6) return 1 - Math.exp(-w * s) * (1 + w * s);
|
|
1160
|
+
const root = Math.sqrt(z * z - 1), r1 = -w / (z + root), r2 = -w * (z + root);
|
|
1161
|
+
return 1 - (r2 * Math.exp(r1 * s) - r1 * Math.exp(r2 * s)) / (r2 - r1);
|
|
1162
|
+
};
|
|
1163
|
+
const end = response(Math.max(1e-3, seconds));
|
|
1164
|
+
return t === 0 || t === 1 ? t : response(t * Math.max(1e-3, seconds)) + (1 - end) * t * t * (3 - 2 * t);
|
|
1165
|
+
}
|
|
1166
|
+
switch (name) {
|
|
1167
|
+
case "hold":
|
|
1168
|
+
return t === 1 ? 1 : 0;
|
|
1169
|
+
case "linear":
|
|
1170
|
+
return t;
|
|
1171
|
+
case "ease-in":
|
|
1172
|
+
return t * t * t;
|
|
1173
|
+
case "ease-out":
|
|
1174
|
+
return 1 - (1 - t) ** 3;
|
|
1175
|
+
case "ease-in-out":
|
|
1176
|
+
return t < 0.5 ? 4 * t ** 3 : 1 - (-2 * t + 2) ** 3 / 2;
|
|
1177
|
+
case "back":
|
|
1178
|
+
return 1 + 2.70158 * (t - 1) ** 3 + 1.70158 * (t - 1) ** 2;
|
|
1179
|
+
case "elastic":
|
|
1180
|
+
return t === 0 || t === 1 ? t : 2 ** (-10 * t) * Math.sin((t * 10 - 0.75) * 2 * Math.PI / 3) + 1;
|
|
1181
|
+
default:
|
|
1182
|
+
return t * t * (3 - 2 * t);
|
|
1183
|
+
}
|
|
1184
|
+
};
|
|
1185
|
+
const e = scene.transitionEasing ? ease(p, scene.transitionEasing, scene.transitionDuration ?? 0.5) : p * p * (3 - 2 * p);
|
|
1186
|
+
const rich = schemaVersion === 3 || ["iris", "diagonal-wipe", "whip", "zoom-through", "stack"].includes(scene.transition);
|
|
1187
|
+
const result = { opacity: 1, transform: "none", clipPath: "none", filter: "none" };
|
|
1188
|
+
if (outgoing) {
|
|
1189
|
+
if (scene.transition === "push") result.transform = `translateX(${-e * 100}%)`;
|
|
1190
|
+
if (scene.transition === "zoom") {
|
|
1191
|
+
result.transform = `scale(${1 + e * 0.2})`;
|
|
1192
|
+
result.opacity = 1 - e;
|
|
1193
|
+
}
|
|
1194
|
+
if (rich) {
|
|
1195
|
+
if (scene.transition === "fade") result.opacity = 1 - e;
|
|
1196
|
+
if (scene.transition === "slide") result.transform = `translateX(${-e * 30}%)`;
|
|
1197
|
+
if (scene.transition === "wipe") result.clipPath = `inset(0 0 0 ${e * 100}%)`;
|
|
1198
|
+
if (scene.transition === "iris") {
|
|
1199
|
+
result.transform = `scale(${1 - e * 0.08})`;
|
|
1200
|
+
result.opacity = 1 - e;
|
|
1201
|
+
}
|
|
1202
|
+
if (scene.transition === "diagonal-wipe") result.transform = `translate(${-e * 12}%,${e * 8}%)`;
|
|
1203
|
+
if (scene.transition === "whip") {
|
|
1204
|
+
result.transform = `translateX(${-e * 110}%) skewX(${-Math.sin(p * Math.PI) * 12}deg)`;
|
|
1205
|
+
result.filter = `blur(${Math.sin(p * Math.PI) * 18}px)`;
|
|
1206
|
+
}
|
|
1207
|
+
if (scene.transition === "zoom-through") {
|
|
1208
|
+
result.transform = `scale(${1 + e * 2.5})`;
|
|
1209
|
+
result.opacity = 1 - e;
|
|
1210
|
+
}
|
|
1211
|
+
if (scene.transition === "stack") {
|
|
1212
|
+
result.transform = `translateY(${-e * 8}%) scale(${1 - e * 0.12}) rotate(${-e * 5}deg)`;
|
|
1213
|
+
result.opacity = 1 - e * 0.6;
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
return result;
|
|
1217
|
+
}
|
|
1218
|
+
if (scene.transition === "fade") result.opacity = e;
|
|
1219
|
+
if (scene.transition === "slide" || scene.transition === "push") result.transform = `translateX(${(1 - e) * 100}%)`;
|
|
1220
|
+
if (scene.transition === "wipe") result.clipPath = `inset(0 ${(1 - e) * 100}% 0 0)`;
|
|
1221
|
+
if (scene.transition === "zoom") {
|
|
1222
|
+
result.opacity = e;
|
|
1223
|
+
result.transform = `scale(${0.8 + e * 0.2})`;
|
|
1224
|
+
}
|
|
1225
|
+
if (scene.transition === "iris") result.clipPath = `circle(${Math.max(0, e) * 75}% at 50% 50%)`;
|
|
1226
|
+
if (scene.transition === "diagonal-wipe") {
|
|
1227
|
+
const x = e * 200;
|
|
1228
|
+
result.clipPath = `polygon(0 0, ${x}% 0, ${x - 100}% 100%, 0 100%)`;
|
|
1229
|
+
}
|
|
1230
|
+
if (scene.transition === "whip") {
|
|
1231
|
+
result.transform = `translateX(${(1 - e) * 110}%) skewX(${Math.sin(p * Math.PI) * 12}deg)`;
|
|
1232
|
+
result.filter = `blur(${Math.sin(p * Math.PI) * 18}px)`;
|
|
1233
|
+
}
|
|
1234
|
+
if (scene.transition === "zoom-through") {
|
|
1235
|
+
result.transform = `scale(${0.3 + e * 0.7})`;
|
|
1236
|
+
result.opacity = Math.max(0, Math.min(1, e));
|
|
1237
|
+
}
|
|
1238
|
+
if (scene.transition === "stack") {
|
|
1239
|
+
result.transform = `translateY(${(1 - e) * 100}%) rotate(${(1 - e) * 8}deg)`;
|
|
1240
|
+
result.opacity = Math.max(0, Math.min(1, e * 2));
|
|
1241
|
+
}
|
|
1242
|
+
if (rich && result.filter === void 0) result.filter = "none";
|
|
1243
|
+
return result;
|
|
1244
|
+
}
|
|
1245
|
+
function cameraStyle(scene, time, canvas, depth = 0) {
|
|
1246
|
+
const points = scene.camera?.keyframes;
|
|
1247
|
+
if (!points?.length) return {};
|
|
1248
|
+
const ease = (p, name = "smooth", seconds = 1) => {
|
|
1249
|
+
const t = Math.max(0, Math.min(1, p));
|
|
1250
|
+
if (Array.isArray(name)) {
|
|
1251
|
+
const [x1, y1, x2, y2] = name;
|
|
1252
|
+
const curve = (u2, a2, b2) => 3 * (1 - u2) * (1 - u2) * u2 * a2 + 3 * (1 - u2) * u2 * u2 * b2 + u2 * u2 * u2;
|
|
1253
|
+
let lo = 0, hi = 1;
|
|
1254
|
+
for (let i = 0; i < 24; i++) {
|
|
1255
|
+
const mid = (lo + hi) / 2;
|
|
1256
|
+
if (curve(mid, x1, x2) < t) lo = mid;
|
|
1257
|
+
else hi = mid;
|
|
1258
|
+
}
|
|
1259
|
+
return t === 0 || t === 1 ? t : curve((lo + hi) / 2, y1, y2);
|
|
1260
|
+
}
|
|
1261
|
+
if (typeof name === "object") {
|
|
1262
|
+
const { stiffness: k, damping: c, mass: m } = name, w = Math.sqrt(k / m), z = c / (2 * Math.sqrt(k * m));
|
|
1263
|
+
const response = (s) => {
|
|
1264
|
+
if (z < 1 - 1e-6) {
|
|
1265
|
+
const wd = w * Math.sqrt(1 - z * z);
|
|
1266
|
+
return 1 - Math.exp(-z * w * s) * (Math.cos(wd * s) + z * w / wd * Math.sin(wd * s));
|
|
1267
|
+
}
|
|
1268
|
+
if (z <= 1 + 1e-6) return 1 - Math.exp(-w * s) * (1 + w * s);
|
|
1269
|
+
const root = Math.sqrt(z * z - 1), r1 = -w / (z + root), r2 = -w * (z + root);
|
|
1270
|
+
return 1 - (r2 * Math.exp(r1 * s) - r1 * Math.exp(r2 * s)) / (r2 - r1);
|
|
1271
|
+
};
|
|
1272
|
+
const end = response(Math.max(1e-3, seconds));
|
|
1273
|
+
return t === 0 || t === 1 ? t : response(t * Math.max(1e-3, seconds)) + (1 - end) * t * t * (3 - 2 * t);
|
|
1274
|
+
}
|
|
1275
|
+
switch (name) {
|
|
1276
|
+
case "hold":
|
|
1277
|
+
return t === 1 ? 1 : 0;
|
|
1278
|
+
case "linear":
|
|
1279
|
+
return t;
|
|
1280
|
+
case "ease-in":
|
|
1281
|
+
return t * t * t;
|
|
1282
|
+
case "ease-out":
|
|
1283
|
+
return 1 - (1 - t) ** 3;
|
|
1284
|
+
case "ease-in-out":
|
|
1285
|
+
return t < 0.5 ? 4 * t ** 3 : 1 - (-2 * t + 2) ** 3 / 2;
|
|
1286
|
+
case "back":
|
|
1287
|
+
return 1 + 2.70158 * (t - 1) ** 3 + 1.70158 * (t - 1) ** 2;
|
|
1288
|
+
case "elastic":
|
|
1289
|
+
return t === 0 || t === 1 ? t : 2 ** (-10 * t) * Math.sin((t * 10 - 0.75) * 2 * Math.PI / 3) + 1;
|
|
1290
|
+
default:
|
|
1291
|
+
return t * t * (3 - 2 * t);
|
|
1292
|
+
}
|
|
1293
|
+
};
|
|
1294
|
+
let a = points[0], b = points[points.length - 1];
|
|
1295
|
+
if (time <= a.at) b = a;
|
|
1296
|
+
else if (time >= b.at) a = b;
|
|
1297
|
+
else for (let i = 0; i < points.length - 1; i++) if (time >= points[i].at && time <= points[i + 1].at) {
|
|
1298
|
+
a = points[i];
|
|
1299
|
+
b = points[i + 1];
|
|
1300
|
+
break;
|
|
1301
|
+
}
|
|
1302
|
+
const u = a === b ? 0 : ease((time - a.at) / (b.at - a.at), b.easing ?? "smooth", b.at - a.at), mix2 = (x2, y2) => x2 + (y2 - x2) * u;
|
|
1303
|
+
const factor = 1 - depth * 0.5;
|
|
1304
|
+
const x = mix2(a.x, b.x) * factor, y = mix2(a.y, b.y) * factor, zoom = Math.max(0.01, mix2(a.zoom, b.zoom)) ** factor, rotation = mix2(a.rotation, b.rotation) * factor;
|
|
1305
|
+
return { position: "absolute", inset: 0, transformOrigin: `${canvas.width / 2}px ${canvas.height / 2}px`, transform: `translate(${x}px,${y}px) rotate(${rotation}deg) scale(${zoom})` };
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
// src/core/source.ts
|
|
1309
|
+
var escapeHtml = (value) => value.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
|
|
1310
|
+
function analyzeSource(filename, html) {
|
|
1311
|
+
if (html.length > 1e7) throw new Error("\u05DE\u05E7\u05D5\u05E8 HTML \u05DE\u05D5\u05D2\u05D1\u05DC \u05DC\u05BE10 \u05DE\u05D2\u05D4");
|
|
1312
|
+
if (!/\.html?$/i.test(filename) || !/<(?:!doctype|html|head|body|div|section|main)\b/i.test(html)) throw new Error("\u05E0\u05D3\u05E8\u05E9 \u05E7\u05D5\u05D1\u05E5 HTML \u05EA\u05E7\u05D9\u05DF");
|
|
1313
|
+
const engine = /data-composition-id\s*=|\bhyperframes\b/i.test(html) ? "hyperframes" : "html";
|
|
1314
|
+
const externalReferences = [...new Set(html.match(/(?:https?:)?\/\/[^\s"'<>`)]+/gi) ?? [])];
|
|
1315
|
+
const warnings = ["\u05DE\u05E7\u05D5\u05E8 \u05D7\u05D9\u05E6\u05D5\u05E0\u05D9 \u05E0\u05E9\u05DE\u05E8 \u05DC\u05E2\u05E8\u05D9\u05DB\u05EA \u05E7\u05D5\u05D3; \u05D4\u05E8\u05E6\u05EA JavaScript \u05D5\u05EA\u05E6\u05D5\u05D2\u05EA \u05EA\u05E0\u05D5\u05E2\u05D4 \u05D7\u05E1\u05D5\u05DE\u05D5\u05EA.", "\u05E9\u05D3\u05D5\u05EA \u05D8\u05E7\u05E1\u05D8 \u05DE\u05D6\u05D5\u05D4\u05D9\u05DD \u05E8\u05E7 \u05DC\u05E4\u05D9 \u05DE\u05D6\u05D4\u05D9\u05DD \u05DE\u05E4\u05D5\u05E8\u05E9\u05D9\u05DD. \u05E9\u05D9\u05E0\u05D5\u05D9 \u05D8\u05E7\u05E1\u05D8 \u05D0\u05D9\u05E0\u05D5 \u05DE\u05DE\u05E4\u05D4 \u05D0\u05D5\u05D8\u05D5\u05DE\u05D8\u05D9\u05EA \u05E1\u05E6\u05E0\u05D5\u05EA \u05D5\u05EA\u05E0\u05D5\u05E2\u05D4."];
|
|
1316
|
+
if (externalReferences.length) warnings.push(`\u05E0\u05DE\u05E6\u05D0\u05D5 ${externalReferences.length} \u05D4\u05E4\u05E0\u05D9\u05D5\u05EA \u05D7\u05D9\u05E6\u05D5\u05E0\u05D9\u05D5\u05EA. \u05D9\u05E9 \u05DC\u05D4\u05D7\u05DC\u05D9\u05E4\u05DF \u05D1\u05E0\u05DB\u05E1\u05D9\u05DD \u05DE\u05E7\u05D5\u05DE\u05D9\u05D9\u05DD \u05DC\u05E4\u05E0\u05D9 \u05D4\u05E4\u05E7\u05D4 \u05D1\u05DE\u05E6\u05D1 \u05DE\u05E0\u05D5\u05EA\u05E7.`);
|
|
1317
|
+
if (/<(?:script|iframe|object|embed)\b|\son[a-z]+\s*=/i.test(html)) warnings.push("\u05D4\u05DE\u05E7\u05D5\u05E8 \u05DE\u05DB\u05D9\u05DC \u05EA\u05D5\u05DB\u05DF \u05E4\u05E2\u05D9\u05DC \u05E9\u05DC\u05D0 \u05D9\u05D1\u05D5\u05E6\u05E2 \u05D1\u05D9\u05D9\u05E9\u05D5\u05DD.");
|
|
1318
|
+
const masked = html.replace(/<!--[\s\S]*?-->|<(script|style|textarea|title)\b[^>]*>[\s\S]*?<\/\1\s*>/gi, (match) => " ".repeat(match.length));
|
|
1319
|
+
const textFields = [];
|
|
1320
|
+
const leaf = /<(h[1-6]|p|span|div|button|label|strong|em|a)\b([^<>]*)>([^<>]*)<\/\1\s*>/gi;
|
|
1321
|
+
for (const match of masked.matchAll(leaf)) {
|
|
1322
|
+
const id = /(?:^|\s)id\s*=\s*(["'])([a-zA-Z0-9_-]+)\1/i.exec(match[2]);
|
|
1323
|
+
if (id && match[3].trim()) textFields.push({ id: id[2], tag: match[1], text: decodeText(match[3]) });
|
|
1324
|
+
}
|
|
1325
|
+
const allIds = Array.from(masked.matchAll(/<[a-z][^<>]*?\s+id\s*=\s*(["'])([a-zA-Z0-9_-]+)\1/gi), (match) => match[2]);
|
|
1326
|
+
const unique = textFields.filter((field) => allIds.filter((id) => id === field.id).length === 1);
|
|
1327
|
+
return { mode: "imported-source", structuredEditing: false, sourceEditing: true, videoEditing: false, executablePreview: false, warnings, engine, externalReferences, textFields: unique };
|
|
1328
|
+
}
|
|
1329
|
+
function decodeText(text3) {
|
|
1330
|
+
return text3.replace(/&(#x[\da-f]+|#\d+|amp|lt|gt|quot|apos|nbsp);/gi, (full, entity) => {
|
|
1331
|
+
const named = { amp: "&", lt: "<", gt: ">", quot: '"', apos: "'", nbsp: " " };
|
|
1332
|
+
if (named[entity.toLowerCase()]) return named[entity.toLowerCase()];
|
|
1333
|
+
const point2 = entity.startsWith("#x") ? parseInt(entity.slice(2), 16) : parseInt(entity.slice(1), 10);
|
|
1334
|
+
return point2 > 0 && point2 <= 1114111 ? String.fromCodePoint(point2) : full;
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1337
|
+
function importHtmlSource(filename, html) {
|
|
1338
|
+
const report = analyzeSource(filename, html);
|
|
1339
|
+
return {
|
|
1340
|
+
...createProject(filename.replace(/\.html?$/i, ""), { mode: "imported-source", scenes: [] }),
|
|
1341
|
+
source: { filename, original: html, current: html, detectedEngine: report.engine, execution: "disabled", warnings: report.warnings }
|
|
1342
|
+
};
|
|
1343
|
+
}
|
|
1344
|
+
function updateSourceText(project, id, text3) {
|
|
1345
|
+
if (!project.source) throw new Error("\u05D0\u05D9\u05DF \u05DE\u05E7\u05D5\u05E8 HTML");
|
|
1346
|
+
const report = analyzeSource(project.source.filename, project.source.current);
|
|
1347
|
+
if (!report.textFields.some((field) => field.id === id)) throw new Error("\u05D4\u05E9\u05D3\u05D4 \u05D0\u05D9\u05E0\u05D5 \u05DE\u05D6\u05D5\u05D4\u05D4 \u05D1\u05D0\u05D5\u05E4\u05DF \u05D7\u05D3\u05BE\u05DE\u05E9\u05DE\u05E2\u05D9");
|
|
1348
|
+
const leaf = /<(h[1-6]|p|span|div|button|label|strong|em|a)\b([^<>]*)>([^<>]*)<\/\1\s*>/gi;
|
|
1349
|
+
const masked = project.source.current.replace(/<!--[\s\S]*?-->|<(script|style|textarea|title)\b[^>]*>[\s\S]*?<\/\1\s*>/gi, (match) => " ".repeat(match.length));
|
|
1350
|
+
let current = project.source.current;
|
|
1351
|
+
for (const match of masked.matchAll(leaf)) {
|
|
1352
|
+
const matchId = /(?:^|\s)id\s*=\s*(["'])([a-zA-Z0-9_-]+)\1/i.exec(match[2]);
|
|
1353
|
+
if (matchId?.[2] === id) {
|
|
1354
|
+
const start = match.index + match[0].indexOf(">") + 1;
|
|
1355
|
+
current = current.slice(0, start) + escapeHtml(text3) + current.slice(start + match[3].length);
|
|
1356
|
+
break;
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
return commitProject({ ...project, source: { ...project.source, current } });
|
|
1360
|
+
}
|
|
1361
|
+
function sourcePreviewHtml(html) {
|
|
1362
|
+
return `<!doctype html><html dir="rtl"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'"><style>body{background:#101624;color:#ced8e9;font:14px monospace;padding:24px}pre{white-space:pre-wrap;direction:ltr;text-align:left}h2{font:18px Arial}</style></head><body><h2>\u05EA\u05E6\u05D5\u05D2\u05EA \u05DE\u05E7\u05D5\u05E8 \u05D1\u05D8\u05D5\u05D7\u05D4 \u2014 \u05D4\u05E8\u05E6\u05EA \u05E7\u05D5\u05D3 \u05DB\u05D1\u05D5\u05D9\u05D4</h2><pre>${escapeHtml(html)}</pre></body></html>`;
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
// src/core/font-data.ts
|
|
1366
|
+
var heeboFontCss = "@font-face{font-family:Heebo;src:url(data:font/woff2;base64,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) format('woff2');font-weight:400;font-style:normal;unicode-range:U+0000-058F,U+0600-FB1C,U+FB50-10FFFF;}@font-face{font-family:Heebo;src:url(data:font/woff2;base64,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) format('woff2');font-weight:400;font-style:normal;unicode-range:U+0590-05FF,U+FB1D-FB4F;}@font-face{font-family:Heebo;src:url(data:font/woff2;base64,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) format('woff2');font-weight:700;font-style:normal;unicode-range:U+0000-058F,U+0600-FB1C,U+FB50-10FFFF;}@font-face{font-family:Heebo;src:url(data:font/woff2;base64,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) format('woff2');font-weight:700;font-style:normal;unicode-range:U+0590-05FF,U+FB1D-FB4F;}";
|
|
1367
|
+
|
|
1368
|
+
// src/core/symbol-font-data.ts
|
|
1369
|
+
var symbolFontCss = '@font-face{font-family:"MotionDesk Symbols";src:url(data:font/ttf;base64,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) format("truetype");font-weight:400;font-style:normal;unicode-range:U+2190-21FF,U+25A0-25FF,U+2700-27BF;}';
|
|
1370
|
+
|
|
1371
|
+
// src/core/repeater.ts
|
|
1372
|
+
function repeaterLayers(layer2) {
|
|
1373
|
+
const r = layer2.repeater;
|
|
1374
|
+
if (layer2.type !== "repeater" || !r) return [];
|
|
1375
|
+
const random = (i, salt) => {
|
|
1376
|
+
let x = r.seed ^ Math.imul(i + 1, 374761393) ^ Math.imul(salt, 668265263) | 0;
|
|
1377
|
+
x = Math.imul(x ^ x >>> 13, 1274126177);
|
|
1378
|
+
return ((x ^ x >>> 16) >>> 0) / 4294967296;
|
|
1379
|
+
};
|
|
1380
|
+
return Array.from({ length: r.count }, (_, i) => {
|
|
1381
|
+
const delay = i * r.delay + random(i, 4) * (r.jitterDelay ?? 0);
|
|
1382
|
+
const copy = {
|
|
1383
|
+
...layer2,
|
|
1384
|
+
id: `${layer2.id}_repeat_${i}`,
|
|
1385
|
+
type: "shape",
|
|
1386
|
+
x: i * r.offsetX + (random(i, 1) * 2 - 1) * (r.jitterX ?? 0),
|
|
1387
|
+
y: i * r.offsetY + (random(i, 2) * 2 - 1) * (r.jitterY ?? 0),
|
|
1388
|
+
start: delay,
|
|
1389
|
+
duration: Math.max(0.01, layer2.duration - delay),
|
|
1390
|
+
rotation: i * r.rotation + (random(i, 3) * 2 - 1) * (r.jitterRotation ?? 0) + (r.shape === "diamond" ? 45 : 0),
|
|
1391
|
+
opacity: 1,
|
|
1392
|
+
color: r.colors?.[i % r.colors.length] ?? layer2.color,
|
|
1393
|
+
borderRadius: r.shape === "ellipse" ? Math.max(layer2.width, layer2.height) : layer2.borderRadius
|
|
1394
|
+
};
|
|
1395
|
+
delete copy.repeater;
|
|
1396
|
+
delete copy.depth;
|
|
1397
|
+
delete copy.revealBinding;
|
|
1398
|
+
return copy;
|
|
1399
|
+
});
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
// src/core/compiler.ts
|
|
1403
|
+
function compileProjectHtml(project) {
|
|
1404
|
+
assertProject(project);
|
|
1405
|
+
if (project.mode === "imported-source") throw new Error("\u05DE\u05E7\u05D5\u05E8 \u05D7\u05D9\u05E6\u05D5\u05E0\u05D9 \u05E0\u05D9\u05EA\u05DF \u05DC\u05D9\u05D9\u05E6\u05D0 \u05DB\u05E7\u05D5\u05D3 \u05D1\u05DC\u05D1\u05D3; \u05D4\u05E4\u05E7\u05EA \u05E0\u05D2\u05DF \u05D3\u05D5\u05E8\u05E9\u05EA \u05E4\u05E8\u05D5\u05D9\u05E7\u05D8 \u05DE\u05D5\u05D1\u05E0\u05D4");
|
|
1406
|
+
const json = JSON.stringify(project).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
1407
|
+
return `<!doctype html>
|
|
1408
|
+
<html lang="he" dir="rtl"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
1409
|
+
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; img-src data: blob: motiondesk-media: 'self'; media-src data: blob: motiondesk-media: 'self'; font-src data: 'self'; connect-src 'none'; base-uri 'none'; form-action 'none'">
|
|
1410
|
+
<title>${escapeHtml(project.title)}</title><style>${heeboFontCss}${symbolFontCss}
|
|
1411
|
+
*{box-sizing:border-box}html,body{margin:0;width:100%;height:100%;overflow:hidden;background:#000}#stage{position:absolute;overflow:hidden;transform-origin:top left;direction:rtl}.scene,.media{position:absolute;inset:0}.layer{position:absolute;display:flex;align-items:center;justify-content:center;white-space:pre-wrap;overflow-wrap:anywhere;overflow:hidden;transform-origin:center}.layer img,.layer video{width:100%;height:100%;object-fit:cover}.media video{width:100%;height:100%;object-fit:contain}.scene{pointer-events:none}
|
|
1412
|
+
</style></head><body><main id="stage" aria-label="${escapeHtml(project.title)}"></main>
|
|
1413
|
+
<script type="application/json" id="motiondesk-project">${json}</script>
|
|
1414
|
+
<script>(()=>{'use strict';
|
|
1415
|
+
const project=JSON.parse(document.getElementById('motiondesk-project').textContent),duration=${projectDuration(project)};
|
|
1416
|
+
const evaluateLayer=${evaluateLayer.toString()};
|
|
1417
|
+
const layerStyle=${layerStyle.toString()};
|
|
1418
|
+
const textUnitStyle=${textUnitStyle.toString()};
|
|
1419
|
+
const textLineStyle=${textLineStyle.toString()};
|
|
1420
|
+
const sceneStyle=${sceneStyle.toString()};
|
|
1421
|
+
const cameraStyle=${cameraStyle.toString()};
|
|
1422
|
+
const repeaterLayers=${repeaterLayers.toString()};
|
|
1423
|
+
const stage=document.getElementById('stage');stage.style.width=project.canvas.width+'px';stage.style.height=project.canvas.height+'px';
|
|
1424
|
+
const assets=new Map(project.assets.map(a=>[a.id,a]));const sceneNodes=[];const mediaNodes=[];
|
|
1425
|
+
function resize(){const scale=Math.min(innerWidth/project.canvas.width,innerHeight/project.canvas.height);stage.style.transform='scale('+scale+')';stage.style.left=(innerWidth-project.canvas.width*scale)/2+'px';stage.style.top=(innerHeight-project.canvas.height*scale)/2+'px'}addEventListener('resize',resize);resize();
|
|
1426
|
+
for(const track of project.mediaTracks){for(const clip of track.clips){const asset=assets.get(clip.assetId);if(!asset)continue;const el=document.createElement(track.type==='video'?'video':'audio');el.src=asset.src;el.preload='auto';el.muted=track.muted||clip.muted;el.volume=Math.min(1,clip.volume);if(track.type==='video'){const wrap=document.createElement('div');wrap.className='media';wrap.append(el);stage.append(wrap)}else{el.hidden=true;stage.append(el)}mediaNodes.push({el,clip,track})}}
|
|
1427
|
+
function addLayer(parent,layer,layers){
|
|
1428
|
+
const node=document.createElement('div');node.className='layer';node.dataset.layerId=layer.id;
|
|
1429
|
+
if(layer.type==='text')node.textContent=layer.text||'';
|
|
1430
|
+
if(layer.type==='path'||layer.type==='svg'){
|
|
1431
|
+
const svg=document.createElementNS('http://www.w3.org/2000/svg','svg');svg.setAttribute('viewBox','0 0 '+layer.width+' '+layer.height);svg.setAttribute('width','100%');svg.setAttribute('height','100%');
|
|
1432
|
+
const path=document.createElementNS('http://www.w3.org/2000/svg','path');path.setAttribute('d',layer.pathData||'');path.setAttribute('fill',layer.type==='svg'?layer.color:'none');path.setAttribute('stroke',layer.stroke||layer.color);path.setAttribute('stroke-width',String(layer.strokeWidth||3));svg.append(path);node.append(svg);
|
|
1433
|
+
}
|
|
1434
|
+
if(layer.type==='image'||layer.type==='video'){const asset=assets.get(layer.assetId);if(asset){const media=document.createElement(layer.type==='image'?'img':'video');media.src=asset.src;if(layer.type==='video'){media.muted=true;media.preload='auto'}node.append(media)}}
|
|
1435
|
+
const entry={layer,node,children:[]};layers.push(entry);parent.append(node);
|
|
1436
|
+
if(layer.type==='group'||layer.type==='repeater')for(const child of layer.type==='repeater'?repeaterLayers(layer):layer.children||[])addLayer(node,child,entry.children);
|
|
1437
|
+
}
|
|
1438
|
+
let sceneStart=0;for(const scene of project.scenes){const el=document.createElement('section');el.className='scene';const layers=[];for(const layer of scene.layers){let parent=el;if(scene.camera){parent=document.createElement('div');parent.dataset.cameraDepth=String(layer.depth||0);el.append(parent);}addLayer(parent,layer,layers);if(scene.camera)layers[layers.length-1].plane=parent;}stage.append(el);sceneNodes.push({scene,el,layers,start:sceneStart});sceneStart+=scene.duration}
|
|
1439
|
+
let time=0,playing=false,last=0,messageRevision=0;
|
|
1440
|
+
function positionMedia(el,target,active){el.style.visibility=active?'visible':'hidden';if(!active){el.pause();return}if(Number.isFinite(el.duration)&&Math.abs(el.currentTime-target)>0.06)el.currentTime=Math.min(target,Math.max(0,el.duration-0.001));if(playing)el.play().catch(()=>{});else el.pause()}
|
|
1441
|
+
function paintLayer(entry,local,context){
|
|
1442
|
+
const {layer,node}=entry;const frame=evaluateLayer(layer,local,context);Object.assign(node.style,layerStyle(layer,frame));
|
|
1443
|
+
if(layer.type==='text'){
|
|
1444
|
+
if(frame.textUnits){
|
|
1445
|
+
if(!entry.textLine){entry.textLine=document.createElement('span');Object.assign(entry.textLine.style,textLineStyle(layer));node.replaceChildren(entry.textLine);}
|
|
1446
|
+
const line=entry.textLine;
|
|
1447
|
+
while(line.children.length>frame.textUnits.length)line.lastChild.remove();
|
|
1448
|
+
frame.textUnits.forEach((unit,index)=>{let span=line.children[index];if(!span){span=document.createElement('span');line.append(span);}if(span.textContent!==unit.text)span.textContent=unit.text;Object.assign(span.style,textUnitStyle(unit));});
|
|
1449
|
+
}
|
|
1450
|
+
else if(node.textContent!==frame.text)node.textContent=frame.text;
|
|
1451
|
+
}
|
|
1452
|
+
const path=node.querySelector(':scope > svg > path');if(path){path.setAttribute('pathLength','1');path.setAttribute('stroke-dasharray','1');path.setAttribute('stroke-dashoffset',String(1-frame.reveal));path.setAttribute('stroke',frame.color||layer.stroke||layer.color);if(layer.type==='svg')path.setAttribute('fill',frame.color||layer.color);}
|
|
1453
|
+
const video=node.querySelector(':scope > video');if(video)positionMedia(video,Math.max(0,local-layer.start),frame.visible);
|
|
1454
|
+
for(const child of entry.children)paintLayer(child,local-layer.start,{...context,sceneStart:context.sceneStart+layer.start,layers:layer.type==='repeater'?entry.children.map(c=>c.layer):layer.children});
|
|
1455
|
+
}
|
|
1456
|
+
function paint(t){
|
|
1457
|
+
time=Math.max(0,Math.min(duration,t));
|
|
1458
|
+
if(project.schemaVersion===3){const index=sceneNodes.findIndex(entry=>time>=entry.start&&time<entry.start+entry.scene.duration);const active=sceneNodes[index];const transitioning=active&&index>0&&active.scene.transition!=='cut'&&time<active.start+Math.min(active.scene.transitionDuration||.5,active.scene.duration/2);stage.style.background=(transitioning?sceneNodes[index-1].scene.background:active?.scene.background)||'#000';}
|
|
1459
|
+
for(let i=0;i<sceneNodes.length;i++){
|
|
1460
|
+
const entry=sceneNodes[i],next=sceneNodes[i+1];
|
|
1461
|
+
const incoming=time>=entry.start&&time<entry.start+entry.scene.duration;
|
|
1462
|
+
const nextDuration=next?Math.min(next.scene.transitionDuration||.5,next.scene.duration/2):0;
|
|
1463
|
+
const outgoing=next&&next.scene.transition!=='cut'&&time>=next.start&&time<next.start+nextDuration;
|
|
1464
|
+
entry.el.style.display=incoming||outgoing?'block':'none';
|
|
1465
|
+
if(!incoming&&!outgoing){for(const video of entry.el.querySelectorAll('video'))video.pause();continue}
|
|
1466
|
+
const local=outgoing?(project.schemaVersion===3?entry.scene.duration-.001:entry.scene.duration-nextDuration+(time-next.start)):time-entry.start;
|
|
1467
|
+
const spec=outgoing?next.scene:entry.scene;
|
|
1468
|
+
const d=outgoing?nextDuration:Math.min(spec.transitionDuration||.5,spec.duration/2);
|
|
1469
|
+
const progress=outgoing?(time-next.start)/d:local/d;
|
|
1470
|
+
Object.assign(entry.el.style,sceneStyle(spec,progress,!!outgoing,project.schemaVersion));
|
|
1471
|
+
entry.el.style.background=entry.scene.background;
|
|
1472
|
+
const context={canvas:project.canvas,schemaVersion:project.schemaVersion,beats:project.beats,sceneStart:entry.start,layers:entry.scene.layers};
|
|
1473
|
+
for(const layer of entry.layers){if(layer.plane)Object.assign(layer.plane.style,cameraStyle(entry.scene,local,project.canvas,layer.layer.depth||0));paintLayer(layer,local,context);}
|
|
1474
|
+
}
|
|
1475
|
+
for(const {el,clip} of mediaNodes)positionMedia(el,clip.in+time-clip.start,time>=clip.start&&time<clip.start+clip.out-clip.in)
|
|
1476
|
+
}
|
|
1477
|
+
async function seek(t){playing=false;paint(t);await Promise.all(Array.from(document.querySelectorAll('video')).filter(v=>v.seeking).map(v=>new Promise(resolve=>{v.addEventListener('seeked',resolve,{once:true});setTimeout(resolve,1500)})));return time}
|
|
1478
|
+
function tick(now){if(playing){paint(time+(now-last)/1000);if(time>=duration){playing=false;for(const el of document.querySelectorAll('video,audio'))el.pause()}}last=now;requestAnimationFrame(tick)}
|
|
1479
|
+
window.__motiondesk={seek,play(){playing=true;last=performance.now()},pause(){playing=false;for(const el of document.querySelectorAll('video,audio'))el.pause()},get time(){return time},duration,project};
|
|
1480
|
+
addEventListener('message',event=>{if(event.source!==parent||event.data?.type!=='motiondesk:seek'||typeof event.data.time!=='number'||!Number.isFinite(event.data.time))return;const revision=++messageRevision;seek(event.data.time).then(()=>{if(revision===messageRevision&&event.data.playing)window.__motiondesk.play()})});
|
|
1481
|
+
window.__motiondeskReady=Promise.all([...Array.from(document.images).map(img=>img.decode().catch(()=>{})),...Array.from(document.querySelectorAll('video,audio')).map(el=>el.readyState>=1?Promise.resolve():new Promise(resolve=>{el.addEventListener('loadedmetadata',resolve,{once:true});el.addEventListener('error',resolve,{once:true});setTimeout(resolve,3000)}))]).then(()=>document.fonts.ready).then(()=>{paint(0);return true});paint(0);requestAnimationFrame(tick);document.addEventListener('keydown',e=>{if(e.code==='Space'){e.preventDefault();playing=!playing}});
|
|
1482
|
+
})();</script></body></html>`;
|
|
1483
|
+
}
|
|
1484
|
+
function importStructuredHtml(html) {
|
|
1485
|
+
const match = /<script\b(?=[^>]*\bid=["']motiondesk-project["'])(?=[^>]*\btype=["']application\/json["'])[^>]*>([\s\S]*?)<\/script\s*>/i.exec(html);
|
|
1486
|
+
if (!match) return null;
|
|
1487
|
+
const parsed = parseProject(match[1]);
|
|
1488
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1489
|
+
return { ...parsed, id: newId("project"), revision: 0, createdAt: now, updatedAt: now };
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
// src/core/media.ts
|
|
1493
|
+
function createMediaRenderPlan(project, options) {
|
|
1494
|
+
assertProject(project);
|
|
1495
|
+
const duration = projectDuration(project);
|
|
1496
|
+
if (duration <= 0) throw new Error("\u05D0\u05D9\u05DF \u05EA\u05D5\u05DB\u05DF \u05DC\u05D4\u05E4\u05E7\u05D4");
|
|
1497
|
+
if (project.mode === "imported-source") throw new Error("\u05DC\u05D0 \u05E0\u05D9\u05EA\u05DF \u05DC\u05D4\u05E4\u05D9\u05E7 \u05DE\u05E7\u05D5\u05E8 \u05D7\u05D9\u05E6\u05D5\u05E0\u05D9 \u05E9\u05D8\u05E8\u05DD \u05DE\u05D5\u05E4\u05D4");
|
|
1498
|
+
if (project.canvas.width % 2 || project.canvas.height % 2) throw new Error("\u05D9\u05E6\u05D5\u05D0 MP4 \u05D3\u05D5\u05E8\u05E9 \u05DE\u05D9\u05D3\u05D5\u05EA \u05D6\u05D5\u05D2\u05D9\u05D5\u05EA");
|
|
1499
|
+
const clips = project.mediaTracks.flatMap((track) => track.clips.map((clip) => ({ track, clip })));
|
|
1500
|
+
const missingAssets = [...new Set(clips.filter(({ clip }) => !options.inputs[clip.assetId]).map(({ clip }) => clip.assetId))];
|
|
1501
|
+
if (missingAssets.length) return { args: [], duration, missingAssets };
|
|
1502
|
+
const num = (value) => Number(value.toFixed(6)).toString();
|
|
1503
|
+
const { width, height, fps } = project.canvas;
|
|
1504
|
+
const args = ["-hide_banner", "-y", "-f", "lavfi", "-i", `color=c=black:s=${width}x${height}:r=${fps}:d=${num(duration)}`];
|
|
1505
|
+
const filters = ["[0:v]format=yuv420p[base0]"];
|
|
1506
|
+
let inputIndex = 1, videoIndex = 0;
|
|
1507
|
+
const audioLabels = [];
|
|
1508
|
+
for (const { track, clip } of clips) {
|
|
1509
|
+
const input = options.inputs[clip.assetId];
|
|
1510
|
+
const idx = inputIndex++;
|
|
1511
|
+
args.push("-i", input.path);
|
|
1512
|
+
const length = clip.out - clip.in;
|
|
1513
|
+
if (track.type === "video") {
|
|
1514
|
+
filters.push(`[${idx}:v]trim=start=${num(clip.in)}:end=${num(clip.out)},setpts=PTS-STARTPTS+${num(clip.start)}/TB,scale=${width}:${height}:force_original_aspect_ratio=decrease,pad=${width}:${height}:(ow-iw)/2:(oh-ih)/2:black,setsar=1,fps=${fps}[v${idx}]`);
|
|
1515
|
+
filters.push(`[base${videoIndex}][v${idx}]overlay=eof_action=pass:enable='gte(t,${num(clip.start)})*lt(t,${num(clip.start + length)})'[base${videoIndex + 1}]`);
|
|
1516
|
+
videoIndex++;
|
|
1517
|
+
}
|
|
1518
|
+
if (!track.muted && !clip.muted && clip.volume > 0 && (track.type === "audio" || input.hasAudio)) {
|
|
1519
|
+
const label = `a${idx}`;
|
|
1520
|
+
const delay = Math.round(clip.start * 1e3);
|
|
1521
|
+
filters.push(`[${idx}:a]atrim=start=${num(clip.in)}:end=${num(clip.out)},asetpts=PTS-STARTPTS,volume=${num(clip.volume)},aresample=48000,adelay=${delay}:all=1[${label}]`);
|
|
1522
|
+
audioLabels.push(`[${label}]`);
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
for (const overlay of options.overlays ?? []) {
|
|
1526
|
+
if (![overlay.start, overlay.end, overlay.x, overlay.y, overlay.width, overlay.height].every(Number.isFinite) || overlay.start < 0 || overlay.end <= overlay.start || overlay.width < 1 || overlay.height < 1) throw new Error("\u05E9\u05DB\u05D1\u05EA \u05EA\u05DE\u05D5\u05E0\u05D4 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D4");
|
|
1527
|
+
const idx = inputIndex++;
|
|
1528
|
+
args.push("-loop", "1", "-i", overlay.path);
|
|
1529
|
+
filters.push(`[${idx}:v]scale=${num(overlay.width)}:${num(overlay.height)},format=rgba[ov${idx}]`);
|
|
1530
|
+
filters.push(`[base${videoIndex}][ov${idx}]overlay=x=${num(overlay.x)}:y=${num(overlay.y)}:eof_action=pass:enable='gte(t,${num(overlay.start)})*lt(t,${num(overlay.end)})'[base${videoIndex + 1}]`);
|
|
1531
|
+
videoIndex++;
|
|
1532
|
+
}
|
|
1533
|
+
if (audioLabels.length) filters.push(`${audioLabels.join("")}amix=inputs=${audioLabels.length}:normalize=0:duration=longest,apad,atrim=duration=${num(duration)}[audio]`);
|
|
1534
|
+
args.push("-filter_complex", filters.join(";"), "-map", `[base${videoIndex}]`);
|
|
1535
|
+
if (audioLabels.length) args.push("-map", "[audio]", "-c:a", "aac", "-b:a", "192k");
|
|
1536
|
+
args.push("-c:v", "libx264", "-preset", "medium", "-crf", "20", "-pix_fmt", "yuv420p", "-r", String(fps), "-t", num(duration), "-movflags", "+faststart", options.output);
|
|
1537
|
+
return { args, duration, missingAssets };
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
// src/core/source-adapter.ts
|
|
1541
|
+
var SOURCE_ADAPTER_DEFINITIONS = [{
|
|
1542
|
+
id: "bank-growth-gsap-v1",
|
|
1543
|
+
compositionId: "bank-growth",
|
|
1544
|
+
sceneIds: ["s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8"],
|
|
1545
|
+
timingProfile: "gsap-bo-bn-v1",
|
|
1546
|
+
literalCalls: [{ name: "caption", argument: 1, encoding: "js-text" }, { name: "chip", argument: 1, encoding: "js-html" }, { name: "el", argument: 3, encoding: "js-html" }, { name: "photo", argument: 1, encoding: "js-asset" }]
|
|
1547
|
+
}];
|
|
1548
|
+
var decode = (s) => s.replace(/&(#x[\da-f]+|#\d+|amp|lt|gt|quot|apos|nbsp);/gi, (full, c) => {
|
|
1549
|
+
const names = { amp: "&", lt: "<", gt: ">", quot: '"', apos: "'", nbsp: " " };
|
|
1550
|
+
if (names[c.toLowerCase()]) return names[c.toLowerCase()];
|
|
1551
|
+
const point2 = c.toLowerCase().startsWith("#x") ? parseInt(c.slice(2), 16) : parseInt(c.slice(1), 10);
|
|
1552
|
+
return point2 > 0 && point2 <= 1114111 ? String.fromCodePoint(point2) : full;
|
|
1553
|
+
});
|
|
1554
|
+
function sourceFingerprint(html) {
|
|
1555
|
+
let hash = 2166136261;
|
|
1556
|
+
for (let i = 0; i < html.length; i++) {
|
|
1557
|
+
hash ^= html.charCodeAt(i);
|
|
1558
|
+
hash = Math.imul(hash, 16777619);
|
|
1559
|
+
}
|
|
1560
|
+
return `${html.length.toString(36)}-${(hash >>> 0).toString(16)}`;
|
|
1561
|
+
}
|
|
1562
|
+
function elements(html) {
|
|
1563
|
+
const result = [], stack = [];
|
|
1564
|
+
const re = /<!--[\s\S]*?-->|<\/?[a-zA-Z][^>"']*(?:(?:"[^"]*"|'[^']*')[^>"']*)*>/g;
|
|
1565
|
+
let m;
|
|
1566
|
+
while (m = re.exec(html)) {
|
|
1567
|
+
if (m[0].startsWith("<!--")) continue;
|
|
1568
|
+
const tag = /^<\/?([a-zA-Z][\w:-]*)/.exec(m[0])[1].toLowerCase();
|
|
1569
|
+
if (m[0].startsWith("</")) {
|
|
1570
|
+
const idx = stack.map((n) => n.tag).lastIndexOf(tag);
|
|
1571
|
+
if (idx >= 0) {
|
|
1572
|
+
for (const node2 of stack.splice(idx)) {
|
|
1573
|
+
node2.contentEnd = m.index;
|
|
1574
|
+
node2.end = re.lastIndex;
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
continue;
|
|
1578
|
+
}
|
|
1579
|
+
const node = { tag, start: m.index, end: re.lastIndex, contentStart: re.lastIndex, contentEnd: re.lastIndex, attrs: {}, parent: stack.at(-1) };
|
|
1580
|
+
const attrs = /\s+([\w:-]+)\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/g;
|
|
1581
|
+
for (const attr of m[0].matchAll(attrs)) {
|
|
1582
|
+
const value = attr[2] ?? attr[3] ?? attr[4], offset = attr[0].indexOf("=") + 1;
|
|
1583
|
+
const local = attr[0].slice(offset).search(/\S/);
|
|
1584
|
+
const quote = attr[0][offset + local];
|
|
1585
|
+
const start = m.index + attr.index + offset + local + (quote === '"' || quote === "'" ? 1 : 0);
|
|
1586
|
+
node.attrs[attr[1].toLowerCase()] = { value, start, end: start + value.length };
|
|
1587
|
+
}
|
|
1588
|
+
result.push(node);
|
|
1589
|
+
if (["script", "style", "textarea", "title"].includes(tag)) {
|
|
1590
|
+
const close = new RegExp(`</${tag}\\s*>`, "ig");
|
|
1591
|
+
close.lastIndex = re.lastIndex;
|
|
1592
|
+
const end = close.exec(html);
|
|
1593
|
+
node.contentEnd = end?.index ?? html.length;
|
|
1594
|
+
node.end = end ? close.lastIndex : html.length;
|
|
1595
|
+
re.lastIndex = node.end;
|
|
1596
|
+
} else if (!/\/>$/.test(m[0]) && !["img", "input", "meta", "link", "br", "hr", "source", "area", "base", "embed", "param", "track", "wbr"].includes(tag)) stack.push(node);
|
|
1597
|
+
}
|
|
1598
|
+
return result;
|
|
1599
|
+
}
|
|
1600
|
+
function tokens(code, offset) {
|
|
1601
|
+
const out = [];
|
|
1602
|
+
for (let i = 0; i < code.length; ) {
|
|
1603
|
+
if (/\s/.test(code[i])) {
|
|
1604
|
+
i++;
|
|
1605
|
+
continue;
|
|
1606
|
+
}
|
|
1607
|
+
if (code.startsWith("//", i)) {
|
|
1608
|
+
i = code.indexOf("\n", i + 2);
|
|
1609
|
+
if (i < 0) break;
|
|
1610
|
+
continue;
|
|
1611
|
+
}
|
|
1612
|
+
if (code.startsWith("/*", i)) {
|
|
1613
|
+
const end = code.indexOf("*/", i + 2);
|
|
1614
|
+
i = end < 0 ? code.length : end + 2;
|
|
1615
|
+
continue;
|
|
1616
|
+
}
|
|
1617
|
+
const start = i, quote = code[i];
|
|
1618
|
+
if (quote === '"' || quote === "'" || quote === "`") {
|
|
1619
|
+
i++;
|
|
1620
|
+
let value = "", valid = quote !== "`";
|
|
1621
|
+
while (i < code.length && code[i] !== quote) {
|
|
1622
|
+
if (code[i] === "\\") {
|
|
1623
|
+
i++;
|
|
1624
|
+
const escaped = code[i++];
|
|
1625
|
+
if (escaped === "n") value += "\n";
|
|
1626
|
+
else if (escaped === "r") value += "\r";
|
|
1627
|
+
else if (escaped === "t") value += " ";
|
|
1628
|
+
else if (escaped === "u" && /^[0-9a-fA-F]{4}/.test(code.slice(i))) {
|
|
1629
|
+
value += String.fromCharCode(parseInt(code.slice(i, i + 4), 16));
|
|
1630
|
+
i += 4;
|
|
1631
|
+
} else if (escaped === "x" && /^[0-9a-fA-F]{2}/.test(code.slice(i))) {
|
|
1632
|
+
value += String.fromCharCode(parseInt(code.slice(i, i + 2), 16));
|
|
1633
|
+
i += 2;
|
|
1634
|
+
} else if (["\\", '"', "'"].includes(escaped)) value += escaped;
|
|
1635
|
+
else {
|
|
1636
|
+
valid = false;
|
|
1637
|
+
value += escaped;
|
|
1638
|
+
}
|
|
1639
|
+
} else value += code[i++];
|
|
1640
|
+
}
|
|
1641
|
+
i++;
|
|
1642
|
+
out.push({ kind: valid ? "string" : "other", value, start: offset + start, end: offset + i });
|
|
1643
|
+
continue;
|
|
1644
|
+
}
|
|
1645
|
+
if (/[a-zA-Z_$]/.test(code[i])) {
|
|
1646
|
+
i++;
|
|
1647
|
+
while (i < code.length && /[\w$]/.test(code[i])) i++;
|
|
1648
|
+
out.push({ kind: "word", value: code.slice(start, i), start: offset + start, end: offset + i });
|
|
1649
|
+
continue;
|
|
1650
|
+
}
|
|
1651
|
+
out.push({ kind: "other", value: code[i++], start: offset + start, end: offset + i });
|
|
1652
|
+
}
|
|
1653
|
+
return out;
|
|
1654
|
+
}
|
|
1655
|
+
function literalCallArguments(ts, at) {
|
|
1656
|
+
if (ts[at + 1]?.value !== "(") return null;
|
|
1657
|
+
const args = [[]];
|
|
1658
|
+
let depth = 0;
|
|
1659
|
+
for (let i = at + 2; i < ts.length; i++) {
|
|
1660
|
+
const token = ts[i];
|
|
1661
|
+
if (token.kind !== "string") {
|
|
1662
|
+
if (token.value === ")" && depth === 0) return args;
|
|
1663
|
+
if (["(", "[", "{"].includes(token.value)) depth++;
|
|
1664
|
+
if ([")", "]", "}"].includes(token.value)) depth--;
|
|
1665
|
+
if (token.value === "," && depth === 0) {
|
|
1666
|
+
args.push([]);
|
|
1667
|
+
continue;
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
args.at(-1).push(token);
|
|
1671
|
+
}
|
|
1672
|
+
return null;
|
|
1673
|
+
}
|
|
1674
|
+
function discover(html, definitions = SOURCE_ADAPTER_DEFINITIONS) {
|
|
1675
|
+
if (html.length > 1e7) throw new Error("\u05DE\u05E7\u05D5\u05E8 \u05D2\u05D3\u05D5\u05DC \u05DE\u05BE10 \u05DE\u05D2\u05D4 \u05D0\u05D9\u05E0\u05D5 \u05E0\u05EA\u05DE\u05DA");
|
|
1676
|
+
const nodes = elements(html), targets = [];
|
|
1677
|
+
const root = nodes.find((n) => n.attrs["data-composition-id"]);
|
|
1678
|
+
const compositionId = root?.attrs["data-composition-id"].value;
|
|
1679
|
+
const scenes = nodes.filter((n) => /(?:^|\s)scene(?:\s|$)/.test(n.attrs.class?.value ?? "") && n.attrs["data-start"] && n.attrs["data-duration"]).map((n) => ({
|
|
1680
|
+
id: n.attrs.id?.value ?? `scene-${n.start}`,
|
|
1681
|
+
name: n.attrs["data-name"]?.value ?? n.attrs.id?.value ?? "\u05E1\u05E6\u05E0\u05D4",
|
|
1682
|
+
start: Number(n.attrs["data-start"].value),
|
|
1683
|
+
duration: Number(n.attrs["data-duration"].value),
|
|
1684
|
+
timingEditable: false
|
|
1685
|
+
})).filter((s) => Number.isFinite(s.start) && Number.isFinite(s.duration) && s.start >= 0 && s.duration > 0);
|
|
1686
|
+
const warnings = ["\u05D6\u05D9\u05D4\u05D5\u05D9 \u05E1\u05D8\u05D8\u05D9 \u05D0\u05D9\u05E0\u05D5 \u05D0\u05D9\u05E9\u05D5\u05E8 \u05DC\u05D4\u05E8\u05E6\u05EA \u05DE\u05E7\u05D5\u05E8. \u05EA\u05E6\u05D5\u05D2\u05D4 \u05E4\u05E2\u05D9\u05DC\u05D4 \u05D3\u05D5\u05E8\u05E9\u05EA \u05E1\u05D1\u05D9\u05D1\u05EA \u05D1\u05D9\u05D3\u05D5\u05D3 \u05E9\u05DC \u05D4\u05DE\u05D0\u05E8\u05D7."];
|
|
1687
|
+
const scriptText = nodes.filter((n) => n.tag === "script" && !n.attrs.src).map((n) => html.slice(n.contentStart, n.contentEnd)).join("\n");
|
|
1688
|
+
const externalScripts = nodes.filter((n) => n.tag === "script" && n.attrs.src).map((n) => n.attrs.src.value);
|
|
1689
|
+
const engine = externalScripts.some((s) => /(?:hf3d|three-bundle)\.js(?:$|\?)/.test(s)) ? "three-gsap" : /getContext\s*\(|targets\.js/.test(scriptText + " " + externalScripts.join(" ")) ? "canvas-gsap" : /gsap/.test(scriptText + " " + externalScripts.join(" ")) ? "dom-gsap" : "html";
|
|
1690
|
+
const dynamicIds = /* @__PURE__ */ new Set();
|
|
1691
|
+
for (const match of scriptText.matchAll(/(?:const|let|var)\s+([a-zA-Z_$][\w$]*)\s*=\s*(?:document\.)?(?:getElementById|querySelector|q)\s*\(\s*(["'])(#?[a-zA-Z0-9_-]+)\2\s*\)/g)) {
|
|
1692
|
+
const variable = match[1].replace(/[$]/g, "\\$");
|
|
1693
|
+
if (new RegExp("\\b" + variable + "\\.(?:textContent|innerHTML)\\s*=").test(scriptText)) dynamicIds.add(match[3].replace(/^#/, ""));
|
|
1694
|
+
}
|
|
1695
|
+
if (externalScripts.some((s) => /(?:^|\/)city\.js$/.test(s))) dynamicIds.add("cnt");
|
|
1696
|
+
if (engine === "three-gsap") warnings.push("\u05D8\u05E7\u05E1\u05D8 \u05EA\u05DC\u05EA\u05BE\u05DE\u05DE\u05D3 \u05D0\u05D5 \u05D8\u05E7\u05E1\u05D8\u05D5\u05E8\u05D4 \u05E0\u05D9\u05EA\u05E0\u05D9\u05DD \u05DC\u05E2\u05E8\u05D9\u05DB\u05D4 \u05E8\u05E7 \u05DB\u05D0\u05E9\u05E8 \u05D6\u05D5\u05D4\u05EA\u05D4 \u05E7\u05E8\u05D9\u05D0\u05EA \u05E6\u05D9\u05D5\u05E8 \u05DC\u05D9\u05D8\u05E8\u05DC\u05D9\u05EA \u05D1\u05EA\u05D5\u05DA HTML. \u05E7\u05D5\u05D3 \u05D7\u05D9\u05E6\u05D5\u05E0\u05D9 \u05DB\u05D2\u05D5\u05DF city.js \u05D0\u05D9\u05E0\u05D5 \u05DE\u05DE\u05D5\u05E4\u05D4 \u05DC\u05D8\u05D5\u05E4\u05E1.");
|
|
1697
|
+
if (engine === "canvas-gsap") warnings.push("\u05D8\u05E7\u05E1\u05D8\u05D9\u05DD \u05D4\u05DE\u05E6\u05D5\u05D9\u05E8\u05D9\u05DD \u05D1\u05DE\u05E2\u05E8\u05DB\u05D9 \u05E4\u05D9\u05E7\u05E1\u05DC\u05D9\u05DD \u05D0\u05D5 \u05D1\u05E0\u05EA\u05D5\u05E0\u05D9 targets \u05D0\u05D9\u05E0\u05DD \u05DE\u05E9\u05EA\u05E0\u05D9\u05DD \u05D3\u05E8\u05DA \u05E9\u05D3\u05D5\u05EA HTML. \u05E0\u05D3\u05E8\u05E9 \u05DE\u05EA\u05D0\u05DD \u05E6\u05D9\u05D5\u05E8 \u05D9\u05D9\u05E2\u05D5\u05D3\u05D9 \u05E2\u05D1\u05D5\u05E8\u05DD.");
|
|
1698
|
+
const add = (target) => {
|
|
1699
|
+
const existing = targets.find((t) => t.field.id === target.field.id);
|
|
1700
|
+
if (existing) {
|
|
1701
|
+
existing.field.editable = false;
|
|
1702
|
+
existing.field.evidence = "\u05D9\u05D5\u05EA\u05E8 \u05DE\u05D4\u05E6\u05D4\u05E8\u05D4 \u05D0\u05D7\u05EA \u05DE\u05EA\u05D0\u05D9\u05DE\u05D4; \u05E0\u05D3\u05E8\u05E9\u05EA \u05E2\u05E8\u05D9\u05DB\u05EA \u05DE\u05E7\u05D5\u05E8 \u05DE\u05E4\u05D5\u05E8\u05E9\u05EA";
|
|
1703
|
+
} else targets.push(target);
|
|
1704
|
+
};
|
|
1705
|
+
const findScene = (node) => {
|
|
1706
|
+
let current = node;
|
|
1707
|
+
while (current) {
|
|
1708
|
+
if (scenes.some((s) => s.id === current.attrs.id?.value)) return current.attrs.id.value;
|
|
1709
|
+
current = current.parent;
|
|
1710
|
+
}
|
|
1711
|
+
return void 0;
|
|
1712
|
+
};
|
|
1713
|
+
for (const style of nodes.filter((n) => n.tag === "style")) {
|
|
1714
|
+
const css = html.slice(style.contentStart, style.contentEnd);
|
|
1715
|
+
for (const rootStyle of css.matchAll(/:root\s*\{([^{}]*)\}/g)) {
|
|
1716
|
+
const base = style.contentStart + rootStyle.index + rootStyle[0].indexOf("{") + 1;
|
|
1717
|
+
for (const match of rootStyle[1].matchAll(/(--[a-zA-Z][\w-]*)\s*:\s*(#[a-fA-F0-9]{3,8})(?=\s*(?:[;}]|$))/g)) {
|
|
1718
|
+
const start = base + match.index + match[0].lastIndexOf(match[2]);
|
|
1719
|
+
add({ start, end: start + match[2].length, encoding: "css", field: { id: `css:${match[1]}`, label: `\u05E6\u05D1\u05E2 ${match[1]}`, kind: "color", value: match[2], editable: true, evidence: "\u05D4\u05E6\u05D4\u05E8\u05EA CSS \u05DE\u05E4\u05D5\u05E8\u05E9\u05EA \u05D1\u05BE:root; \u05DE\u05E9\u05E4\u05D9\u05E2\u05D4 \u05E2\u05DC \u05E6\u05E8\u05DB\u05E0\u05D9 var \u05E9\u05DC \u05D4\u05DE\u05E9\u05EA\u05E0\u05D4 \u05D1\u05DC\u05D1\u05D3" } });
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
const textTags = ["h1", "h2", "h3", "h4", "h5", "h6", "p", "span", "div", "b", "strong", "em", "label", "button", "bdi", "small", "text", "tspan"];
|
|
1724
|
+
const parentTextLeaves = /* @__PURE__ */ new Map();
|
|
1725
|
+
for (const node of nodes) {
|
|
1726
|
+
if (!node.parent || !textTags.includes(node.tag)) continue;
|
|
1727
|
+
const raw = html.slice(node.contentStart, node.contentEnd);
|
|
1728
|
+
if (raw.trim() && !raw.includes("<")) parentTextLeaves.set(node.parent, (parentTextLeaves.get(node.parent) || 0) + 1);
|
|
1729
|
+
}
|
|
1730
|
+
let domOrdinal = 0;
|
|
1731
|
+
for (const node of nodes) {
|
|
1732
|
+
if (!textTags.includes(node.tag)) continue;
|
|
1733
|
+
const ordinal = ++domOrdinal;
|
|
1734
|
+
const raw = html.slice(node.contentStart, node.contentEnd);
|
|
1735
|
+
if (!raw.trim() || raw.includes("<")) continue;
|
|
1736
|
+
const leading = raw.length - raw.trimStart().length, trailing = raw.length - raw.trimEnd().length;
|
|
1737
|
+
const parentId = node.parent?.attrs.id?.value;
|
|
1738
|
+
const id = node.attrs.id?.value ?? (parentId && parentTextLeaves.get(node.parent) === 1 ? parentId : `leaf-${ordinal}`);
|
|
1739
|
+
let ancestor = node, dynamic = false;
|
|
1740
|
+
while (ancestor) {
|
|
1741
|
+
if (dynamicIds.has(ancestor.attrs.id?.value)) dynamic = true;
|
|
1742
|
+
ancestor = ancestor.parent;
|
|
1743
|
+
}
|
|
1744
|
+
add({ start: node.contentStart + leading, end: node.contentEnd - trailing, encoding: "html", node, field: { id: `dom:${id}:${node.tag}`, label: id === "wordmark" ? "\u05E9\u05DD \u05D4\u05DE\u05D5\u05EA\u05D2" : `\u05D8\u05E7\u05E1\u05D8 ${id}`, kind: "text", value: decode(raw.trim()), editable: !dynamic, sceneId: findScene(node), evidence: dynamic ? "\u05E7\u05D5\u05D3 \u05D4\u05D0\u05E0\u05D9\u05DE\u05E6\u05D9\u05D4 \u05DB\u05D5\u05EA\u05D1 \u05DC\u05D8\u05E7\u05E1\u05D8 \u05D4\u05D6\u05D4 \u05D1\u05D6\u05DE\u05DF \u05E0\u05D9\u05D2\u05D5\u05DF; \u05E2\u05E8\u05D9\u05DB\u05EA \u05D8\u05E7\u05E1\u05D8 HTML \u05E8\u05D0\u05E9\u05D5\u05E0\u05D9 \u05D0\u05D9\u05E0\u05D4 \u05E0\u05EA\u05DE\u05DB\u05EA" : "\u05EA\u05D5\u05DB\u05DF \u05D8\u05E7\u05E1\u05D8 \u05E1\u05D8\u05D8\u05D9 \u05D1\u05D0\u05DC\u05DE\u05E0\u05D8 HTML \u05E7\u05D9\u05D9\u05DD; \u05DE\u05D1\u05E0\u05D4 \u05D4\u05D0\u05DC\u05DE\u05E0\u05D8 \u05E0\u05E9\u05DE\u05E8" } });
|
|
1745
|
+
}
|
|
1746
|
+
let remap;
|
|
1747
|
+
const scriptNodes = nodes.filter((n) => n.tag === "script" && !n.attrs.src);
|
|
1748
|
+
const adapter = definitions.find((d) => d.compositionId === compositionId && scenes.length === d.sceneIds.length && scenes.every((s, i) => s.id === d.sceneIds[i]));
|
|
1749
|
+
if (adapter) {
|
|
1750
|
+
let ordinal = 0;
|
|
1751
|
+
for (const script of scriptNodes) {
|
|
1752
|
+
const code = html.slice(script.contentStart, script.contentEnd), ts = tokens(code, script.contentStart);
|
|
1753
|
+
for (let i = 0; i < ts.length; i++) {
|
|
1754
|
+
const name = ts[i].value;
|
|
1755
|
+
const call = adapter.literalCalls.find((c) => c.name === name);
|
|
1756
|
+
if (ts[i].kind !== "word" || !call || ts[i - 1]?.value === "function") continue;
|
|
1757
|
+
const args = literalCallArguments(ts, i), index = call.argument;
|
|
1758
|
+
if (!args || args[index]?.length !== 1 || args[index][0].kind !== "string") continue;
|
|
1759
|
+
const literal = args[index][0];
|
|
1760
|
+
if (call.encoding === "js-asset" && !literal.value.trim() || call.encoding === "js-html" && /[<>]/.test(literal.value)) continue;
|
|
1761
|
+
const preceding = code.slice(0, ts[i].start - script.contentStart);
|
|
1762
|
+
const sceneCalls = [...preceding.matchAll(/const\s+c\s*=\s*S\s*\(\s*(\d+)\s*\)/g)];
|
|
1763
|
+
const sceneId = sceneCalls.length ? `s${sceneCalls.at(-1)[1]}` : void 0;
|
|
1764
|
+
const kind = call.encoding === "js-asset" ? "asset" : "text";
|
|
1765
|
+
add({ start: literal.start, end: literal.end, encoding: call.encoding, field: { id: `bank:${name}:${++ordinal}`, label: name === "caption" ? `\u05DB\u05EA\u05D5\u05D1\u05D9\u05EA ${sceneId ?? ""}` : name === "photo" ? `\u05EA\u05DE\u05D5\u05E0\u05D4 ${sceneId ?? ""}` : `\u05D8\u05E7\u05E1\u05D8 ${sceneId ?? ""}`, kind, value: call.encoding === "js-html" ? decode(literal.value) : literal.value, editable: true, sceneId, evidence: `\u05D0\u05E8\u05D2\u05D5\u05DE\u05E0\u05D8 \u05DE\u05D7\u05E8\u05D5\u05D6\u05EA \u05DC\u05D9\u05D8\u05E8\u05DC\u05D9 \u05D1\u05E7\u05E8\u05D9\u05D0\u05EA ${name}; \u05D6\u05DE\u05DF \u05D4\u05E7\u05E8\u05D9\u05D0\u05D4 \u05D5\u05DB\u05DC \u05D1\u05D9\u05D8\u05D5\u05D9\u05D9 GSAP \u05E0\u05E9\u05DE\u05E8\u05D9\u05DD` } });
|
|
1766
|
+
}
|
|
1767
|
+
const arrays = /const\s+Bo\s*=\s*(\[[\d\s.,]+\])\s*,\s*Bn\s*=\s*(\[[\d\s.,]+\])/.exec(code);
|
|
1768
|
+
const compact = code.replace(/\s+/g, "");
|
|
1769
|
+
const mapping = /master\.fromTo\(tl,\{time:Bo\[k\]\},\{time:Bo\[k\+1\],duration:Bn\[k\+1\]-Bn\[k\],ease:["']none["'],immediateRender:false\},Bn\[k\]\)/.test(compact);
|
|
1770
|
+
if (adapter.timingProfile === "gsap-bo-bn-v1" && arrays && mapping && compact.includes("window.__remap={Bo,Bn}")) {
|
|
1771
|
+
try {
|
|
1772
|
+
const old = JSON.parse(arrays[1]), boundaries = JSON.parse(arrays[2]);
|
|
1773
|
+
const monotonic = (a) => a.length === adapter.sceneIds.length + 1 && a[0] === 0 && a.every((n, i) => Number.isFinite(n) && (!i || n > a[i - 1]));
|
|
1774
|
+
if (monotonic(old) && monotonic(boundaries) && scenes.every((s, i) => Math.abs(s.start - boundaries[i]) < 1e-3)) {
|
|
1775
|
+
const start = script.contentStart + arrays.index + arrays[0].lastIndexOf(arrays[2]);
|
|
1776
|
+
remap = { range: { start, end: start + arrays[2].length }, boundaries };
|
|
1777
|
+
scenes.forEach((scene, i) => {
|
|
1778
|
+
scene.timingEditable = true;
|
|
1779
|
+
add({ start, end: start + arrays[2].length, encoding: "duration", field: { id: `scene:${scene.id}:duration`, label: `\u05DE\u05E9\u05DA \u05DE\u05E7\u05D8\u05E2 ${scene.id}`, kind: "number", value: Number((boundaries[i + 1] - boundaries[i]).toFixed(6)), sceneId: scene.id, editable: true, evidence: "\u05DE\u05E9\u05DA \u05DE\u05E7\u05D8\u05E2 \u05D1\u05DE\u05E4\u05EA Bn \u05E9\u05DE\u05E0\u05D9\u05E2\u05D4 \u05D1\u05E4\u05D5\u05E2\u05DC \u05D0\u05EA master.fromTo; \u05D7\u05DC\u05D5\u05E0\u05D5\u05EA \u05D7\u05E4\u05D9\u05E4\u05D4 \u05E9\u05DC \u05E1\u05E6\u05E0\u05D5\u05EA \u05E0\u05E9\u05DE\u05E8\u05D9\u05DD" } });
|
|
1780
|
+
});
|
|
1781
|
+
}
|
|
1782
|
+
} catch {
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
if (!adapter && (engine === "three-gsap" || engine === "canvas-gsap")) {
|
|
1788
|
+
let drawingOrdinal = 0;
|
|
1789
|
+
for (const script of scriptNodes) {
|
|
1790
|
+
const code = html.slice(script.contentStart, script.contentEnd), ts = tokens(code, script.contentStart);
|
|
1791
|
+
const wordHelper = /function\s+word\s*\([^)]*\)\s*\{[^{}]*H\.text\s*\(/.test(code);
|
|
1792
|
+
for (let i = 0; i < ts.length; i++) {
|
|
1793
|
+
const name = ts[i].value;
|
|
1794
|
+
const isGeometry = name === "text" && ts[i - 1]?.value === "." && ts[i - 2]?.value === "H";
|
|
1795
|
+
const isCanvas = name === "fillText" && ts[i - 1]?.value === ".";
|
|
1796
|
+
if (ts[i].kind !== "word" || !(isGeometry || isCanvas || name === "word" && wordHelper) || ts[i - 1]?.value === "function") continue;
|
|
1797
|
+
const args = literalCallArguments(ts, i);
|
|
1798
|
+
if (!args || args[0]?.length !== 1 || args[0][0].kind !== "string") continue;
|
|
1799
|
+
const literal = args[0][0];
|
|
1800
|
+
add({ start: literal.start, end: literal.end, encoding: "js-text", field: { id: `drawing:${name}:${++drawingOrdinal}`, label: isCanvas ? "\u05D8\u05E7\u05E1\u05D8 \u05D1\u05DE\u05E9\u05D8\u05D7 \u05E6\u05D9\u05D5\u05E8" : "\u05D8\u05E7\u05E1\u05D8 \u05EA\u05DC\u05EA\u05BE\u05DE\u05DE\u05D3", kind: "text", value: literal.value, editable: true, evidence: "\u05D0\u05E8\u05D2\u05D5\u05DE\u05E0\u05D8 \u05DE\u05D7\u05E8\u05D5\u05D6\u05EA \u05DE\u05E4\u05D5\u05E8\u05E9 \u05D1\u05E7\u05E8\u05D9\u05D0\u05EA \u05E6\u05D9\u05D5\u05E8; \u05E9\u05D9\u05E0\u05D5\u05D9 \u05D4\u05DE\u05E7\u05D5\u05E8 \u05D1\u05D5\u05E0\u05D4 \u05DE\u05D7\u05D3\u05E9 \u05D0\u05EA \u05D4\u05D2\u05D0\u05D5\u05DE\u05D8\u05E8\u05D9\u05D4 \u05D0\u05D5 \u05D4\u05D8\u05E7\u05E1\u05D8\u05D5\u05E8\u05D4 \u05D1\u05D8\u05E2\u05D9\u05E0\u05D4 \u05D4\u05D1\u05D0\u05D4" } });
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
if (!remap && scenes.length) warnings.push("\u05EA\u05D6\u05DE\u05D5\u05DF \u05D4\u05E1\u05E6\u05E0\u05D5\u05EA \u05D6\u05D5\u05D4\u05D4 \u05DE\u05D4\u05E6\u05D4\u05E8\u05D5\u05EA \u05D1\u05DC\u05D1\u05D3. \u05D0\u05D9\u05DF \u05E9\u05D9\u05E0\u05D5\u05D9 \u05DE\u05E9\u05DA \u05D1\u05D8\u05D5\u05E4\u05E1 \u05DC\u05DC\u05D0 \u05DE\u05D9\u05E4\u05D5\u05D9 \u05DE\u05D0\u05D5\u05DE\u05EA \u05DC\u05DE\u05E0\u05D5\u05E2 \u05D4\u05D0\u05E0\u05D9\u05DE\u05E6\u05D9\u05D4.");
|
|
1805
|
+
if (remap) warnings.push("\u05E9\u05D9\u05E0\u05D5\u05D9 \u05DE\u05E9\u05DA \u05DE\u05E9\u05E0\u05D4 \u05D0\u05EA \u05DE\u05E4\u05EA \u05D4\u05D6\u05DE\u05DF \u05E9\u05DC \u05D4\u05D0\u05E0\u05D9\u05DE\u05E6\u05D9\u05D4. \u05E7\u05D5\u05D1\u05E5 \u05E9\u05DE\u05E2 \u05E7\u05D9\u05D9\u05DD \u05D0\u05D9\u05E0\u05D5 \u05E0\u05DE\u05EA\u05D7 \u05D0\u05D5\u05D8\u05D5\u05DE\u05D8\u05D9\u05EA \u05D5\u05E2\u05DC\u05D5\u05DC \u05DC\u05D3\u05E8\u05D5\u05E9 \u05E2\u05E8\u05D9\u05DB\u05D4 \u05E0\u05E4\u05E8\u05D3\u05EA.");
|
|
1806
|
+
return { nodes, targets, remap, report: { adapterId: adapter?.id ?? (root ? "hyperframes-declared-v1" : "html-static-v1"), fingerprint: sourceFingerprint(html), compositionId, width: Number(root?.attrs["data-width"]?.value) || 1920, height: Number(root?.attrs["data-height"]?.value) || 1080, duration: remap?.boundaries.at(-1) ?? (Number(root?.attrs["data-duration"]?.value) || Math.max(0, ...scenes.map((s) => s.start + s.duration))), scenes, fields: targets.map((t) => t.field), warnings, capabilities: { engine, staticText: targets.some((t) => t.encoding === "html" && t.field.editable), cssColors: targets.some((t) => t.encoding === "css" && t.field.editable), inlineDrawingText: targets.some((t) => t.field.id.startsWith("drawing:")), sceneTiming: !!remap, sourceCode: true, externalCodeMapped: false } } };
|
|
1807
|
+
}
|
|
1808
|
+
function analyzeSourceAdapter(html, definitions = SOURCE_ADAPTER_DEFINITIONS) {
|
|
1809
|
+
return discover(html, definitions).report;
|
|
1810
|
+
}
|
|
1811
|
+
function annotateSourcePreview(html) {
|
|
1812
|
+
const { targets } = discover(html);
|
|
1813
|
+
const markers = targets.filter((target) => target.encoding === "html" && target.field.editable && target.node).map((target) => ({ at: target.node.contentStart - 1, id: target.field.id })).sort((a, b) => b.at - a.at);
|
|
1814
|
+
let preview = html;
|
|
1815
|
+
for (const marker of markers) preview = preview.slice(0, marker.at) + ` data-motiondesk-field="${escapeHtml(marker.id)}"` + preview.slice(marker.at);
|
|
1816
|
+
return preview;
|
|
1817
|
+
}
|
|
1818
|
+
function applySourceEdits(project, edits, expectedFingerprint, definitions = SOURCE_ADAPTER_DEFINITIONS) {
|
|
1819
|
+
if (!project.source) throw new Error("\u05D0\u05D9\u05DF \u05DE\u05E7\u05D5\u05E8 \u05DC\u05E2\u05E8\u05D9\u05DB\u05D4");
|
|
1820
|
+
const html = project.source.current, discovery = discover(html, definitions);
|
|
1821
|
+
if (expectedFingerprint && expectedFingerprint !== discovery.report.fingerprint) throw new Error("\u05D4\u05DE\u05E7\u05D5\u05E8 \u05D4\u05E9\u05EA\u05E0\u05D4 \u05DE\u05D0\u05D6 \u05E4\u05EA\u05D9\u05D7\u05EA \u05D4\u05D8\u05D5\u05E4\u05E1; \u05D9\u05E9 \u05DC\u05E8\u05E2\u05E0\u05DF \u05D0\u05EA \u05D4\u05E9\u05D3\u05D5\u05EA");
|
|
1822
|
+
if (new Set(edits.map((e) => e.fieldId)).size !== edits.length) throw new Error("\u05E9\u05D3\u05D4 \u05E0\u05E9\u05DC\u05D7 \u05D9\u05D5\u05EA\u05E8 \u05DE\u05E4\u05E2\u05DD \u05D0\u05D7\u05EA");
|
|
1823
|
+
const changes = [], durations = /* @__PURE__ */ new Map();
|
|
1824
|
+
for (const edit of edits) {
|
|
1825
|
+
const target = discovery.targets.find((t) => t.field.id === edit.fieldId && t.field.editable);
|
|
1826
|
+
if (!target) throw new Error("\u05E9\u05D3\u05D4 \u05D4\u05DE\u05E7\u05D5\u05E8 \u05D0\u05D9\u05E0\u05D5 \u05E0\u05EA\u05DE\u05DA \u05DC\u05E2\u05E8\u05D9\u05DB\u05D4");
|
|
1827
|
+
if (target.encoding === "duration") {
|
|
1828
|
+
if (typeof edit.value !== "number" || !Number.isFinite(edit.value) || edit.value < 0.1 || edit.value > 3600) throw new Error("\u05DE\u05E9\u05DA \u05D7\u05D9\u05D9\u05D1 \u05DC\u05D4\u05D9\u05D5\u05EA \u05D1\u05D9\u05DF 0.1 \u05DC\u05BE3600 \u05E9\u05E0\u05D9\u05D5\u05EA");
|
|
1829
|
+
durations.set(target.field.sceneId, edit.value);
|
|
1830
|
+
continue;
|
|
1831
|
+
}
|
|
1832
|
+
if (typeof edit.value !== "string" || edit.value.length > 1e4 || edit.value.includes("\0")) throw new Error("\u05E2\u05E8\u05DA \u05D8\u05E7\u05E1\u05D8 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF");
|
|
1833
|
+
let value = edit.value;
|
|
1834
|
+
if (target.encoding === "css" && !/^#(?:[\da-fA-F]{3}|[\da-fA-F]{4}|[\da-fA-F]{6}|[\da-fA-F]{8})$/.test(value)) throw new Error("\u05E0\u05D3\u05E8\u05E9 \u05E6\u05D1\u05E2 HEX \u05EA\u05E7\u05D9\u05DF");
|
|
1835
|
+
if (target.encoding === "js-asset" && (!isLocalAsset(value) || value.includes(":"))) throw new Error("\u05E0\u05D3\u05E8\u05E9 \u05E0\u05EA\u05D9\u05D1 \u05E0\u05DB\u05E1 \u05D9\u05D7\u05E1\u05D9 \u05D1\u05EA\u05D9\u05E7\u05D9\u05D9\u05EA assets");
|
|
1836
|
+
if (target.encoding === "html") {
|
|
1837
|
+
value = escapeHtml(value).replace(/^[ \t\r\n]+|[ \t\r\n]+$/g, (whitespace) => [...whitespace].map((char) => `&#${char.charCodeAt(0)};`).join(""));
|
|
1838
|
+
} else if (target.encoding === "js-html") value = escapeHtml(value);
|
|
1839
|
+
if (target.encoding.startsWith("js-")) value = JSON.stringify(value).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
1840
|
+
changes.push({ start: target.start, end: target.end, value });
|
|
1841
|
+
}
|
|
1842
|
+
if (durations.size) {
|
|
1843
|
+
if (!discovery.remap) throw new Error("\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0 \u05DE\u05EA\u05D0\u05DD \u05EA\u05D6\u05DE\u05D5\u05DF \u05E4\u05E2\u05D9\u05DC");
|
|
1844
|
+
const old = discovery.remap.boundaries, next = [0];
|
|
1845
|
+
discovery.report.scenes.forEach((scene, i) => next.push(Number((next[i] + (durations.get(scene.id) ?? old[i + 1] - old[i])).toFixed(6))));
|
|
1846
|
+
changes.push({ ...discovery.remap.range, value: JSON.stringify(next) });
|
|
1847
|
+
for (const node of discovery.nodes) {
|
|
1848
|
+
const sceneIndex = discovery.report.scenes.findIndex((scene) => scene.id === node.attrs.id?.value);
|
|
1849
|
+
if (sceneIndex >= 0) {
|
|
1850
|
+
const start = node.attrs["data-start"], duration = node.attrs["data-duration"];
|
|
1851
|
+
if (start) changes.push({ ...start, value: String(next[sceneIndex]) });
|
|
1852
|
+
if (duration) changes.push({ ...duration, value: String(Number((Number(duration.value) + next[sceneIndex + 1] - next[sceneIndex] - (old[sceneIndex + 1] - old[sceneIndex])).toFixed(6))) });
|
|
1853
|
+
} else if (node.attrs["data-duration"] && Math.abs(Number(node.attrs["data-duration"].value) - old.at(-1)) < 1e-3) {
|
|
1854
|
+
changes.push({ ...node.attrs["data-duration"], value: String(next.at(-1)) });
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
changes.sort((a, b) => b.start - a.start);
|
|
1859
|
+
let current = html, previous = html.length;
|
|
1860
|
+
for (const change of changes) {
|
|
1861
|
+
if (change.end > previous) throw new Error("\u05E9\u05D3\u05D5\u05EA \u05D7\u05D5\u05E4\u05E4\u05D9\u05DD; \u05D4\u05E9\u05D9\u05E0\u05D5\u05D9 \u05D1\u05D5\u05D8\u05DC");
|
|
1862
|
+
current = current.slice(0, change.start) + change.value + current.slice(change.end);
|
|
1863
|
+
previous = change.start;
|
|
1864
|
+
}
|
|
1865
|
+
return commitProject({ ...project, source: { ...project.source, current, warnings: discover(current, definitions).report.warnings } });
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
// src/core/motion-library.ts
|
|
1869
|
+
function point(at, x = 0, y = 0, scaleX = 1, scaleY = 1, rotation = 0, opacity = 1) {
|
|
1870
|
+
return { at, x, y, scaleX, scaleY, rotation, opacity };
|
|
1871
|
+
}
|
|
1872
|
+
function flight(duration, delay, fromX = -160, fromY = 0, travelX = 20, travelY = 0, turn = 0) {
|
|
1873
|
+
const enter = Math.max(delay + 0.1, Math.min(duration * 0.42, delay + 0.54));
|
|
1874
|
+
const hold = Math.max(enter + 0.12, duration - 0.48);
|
|
1875
|
+
return [
|
|
1876
|
+
point(0, fromX, fromY, 0.85, 0.85, -turn, 0),
|
|
1877
|
+
...delay > 0 ? [point(delay, fromX, fromY, 0.85, 0.85, -turn, 0)] : [],
|
|
1878
|
+
point(enter, 0, 0, 1, 1, 0, 1),
|
|
1879
|
+
point(hold, travelX, travelY, 1.02, 1.02, turn, 1),
|
|
1880
|
+
point(duration - 0.02, travelX + 24, travelY - 14, 1.02, 1.02, turn, 0)
|
|
1881
|
+
];
|
|
1882
|
+
}
|
|
1883
|
+
function pulse(duration, delay = 0) {
|
|
1884
|
+
const enter = Math.max(delay + 0.12, Math.min(duration * 0.4, delay + 0.48));
|
|
1885
|
+
return [
|
|
1886
|
+
point(0, 0, 0, 0.35, 0.35, -15, 0),
|
|
1887
|
+
...delay > 0 ? [point(delay, 0, 0, 0.35, 0.35, -15, 0)] : [],
|
|
1888
|
+
point(enter, 0, 0, 1, 1, 0, 1),
|
|
1889
|
+
point(Math.max(enter + 0.12, duration * 0.64), 0, -10, 1.07, 1.07, 8, 1),
|
|
1890
|
+
point(duration - 0.02, 0, 0, 0.98, 0.98, -3, 0.94)
|
|
1891
|
+
];
|
|
1892
|
+
}
|
|
1893
|
+
function animateMotif(ctx, layers) {
|
|
1894
|
+
const d = ctx.scene.duration;
|
|
1895
|
+
const end = d - 0.02;
|
|
1896
|
+
const direction = ctx.index % 2 === 0 ? 1 : -1;
|
|
1897
|
+
const set = (layer2, keys) => {
|
|
1898
|
+
layer2.keyframes = keys;
|
|
1899
|
+
};
|
|
1900
|
+
for (const item of layers) {
|
|
1901
|
+
const name = item.name;
|
|
1902
|
+
if (ctx.theme === "car-road" && /חישור/.test(name)) {
|
|
1903
|
+
set(item, [
|
|
1904
|
+
point(0, -420 * direction, 0, 1, 1, 0, 0),
|
|
1905
|
+
point(0.58, -145 * direction, 0, 1, 1, 160, 1),
|
|
1906
|
+
point(d * 0.55, 0, 0, 1, 1, 460, 1),
|
|
1907
|
+
point(end, 125 * direction, 0, 1, 1, 760, 1)
|
|
1908
|
+
]);
|
|
1909
|
+
} else if (ctx.theme === "car-road" && /שובל מהירות/.test(name)) {
|
|
1910
|
+
const n = Number(name.match(/\d+/)?.[0] ?? 1);
|
|
1911
|
+
set(item, [
|
|
1912
|
+
point(0, -80, 0, 0.2, 1, 0, 0),
|
|
1913
|
+
point(0.35 + n * 0.12, -80, 0, 0.2, 1, 0, 0),
|
|
1914
|
+
point(0.7 + n * 0.12, 0, 0, 1, 1, 0, 0.85),
|
|
1915
|
+
point(end, -130, 0, 1.35, 1, 0, 0)
|
|
1916
|
+
]);
|
|
1917
|
+
} else if ((ctx.theme === "car-road" || ctx.theme === "car-garage") && /רכב|גלגל|חלון|גג|פנס/.test(name)) {
|
|
1918
|
+
set(item, [
|
|
1919
|
+
point(0, -420 * direction, 0, 1, 1, 0, 0),
|
|
1920
|
+
point(0.58, -145 * direction, 0),
|
|
1921
|
+
point(d * 0.55, 0, 0),
|
|
1922
|
+
point(end, 125 * direction, 0)
|
|
1923
|
+
]);
|
|
1924
|
+
} else if (ctx.theme === "car-road" && /סימון כביש/.test(name)) {
|
|
1925
|
+
set(item, [point(0, 190, 0), point(end, -230, 0)]);
|
|
1926
|
+
} else if (ctx.theme === "holiday-table" && /צלחת|מרכז שולחן/.test(name)) {
|
|
1927
|
+
set(item, [
|
|
1928
|
+
point(0, 0, 0, 0.15, 0.15, -45, 0),
|
|
1929
|
+
point(0.7, 0, 0, 0.92, 0.92, 0),
|
|
1930
|
+
point(d * 0.67, 0, 0, 1.06, 1.06, 8),
|
|
1931
|
+
point(end, 0, 0, 1, 1)
|
|
1932
|
+
]);
|
|
1933
|
+
} else if (ctx.theme === "one-click" && /גל הדף/.test(name)) {
|
|
1934
|
+
set(item, [
|
|
1935
|
+
point(0, 0, 0, 0.08, 0.08, 0, 0),
|
|
1936
|
+
point(0.7, 0, 0, 0.8, 0.8, 0, 1),
|
|
1937
|
+
point(d * 0.65, 0, 0, 1.18, 1.18, 0, 0.65),
|
|
1938
|
+
point(end, 0, 0, 1.4, 1.4, 0, 0)
|
|
1939
|
+
]);
|
|
1940
|
+
} else if (ctx.theme === "book-steps" && /ספר מדרגה|כריכת ספר/.test(name)) {
|
|
1941
|
+
const n = Number(name.match(/\d+/)?.[0] ?? 1);
|
|
1942
|
+
set(item, [
|
|
1943
|
+
point(0, 0, 270, 1, 1, 0, 0),
|
|
1944
|
+
point(0.28 * n, 0, 270, 1, 1, 0, 0),
|
|
1945
|
+
point(0.28 * n + 0.48, 0, 0),
|
|
1946
|
+
point(end, 0, -38)
|
|
1947
|
+
]);
|
|
1948
|
+
} else if (ctx.theme === "room-build" && /קיר|חלון|ספה|רגל/.test(name)) {
|
|
1949
|
+
const delay = /קיר/.test(name) ? 0.15 : /חלון/.test(name) ? 0.75 : 1.25;
|
|
1950
|
+
set(item, [
|
|
1951
|
+
point(0, 0, 260, 1, 0.2, 0, 0),
|
|
1952
|
+
point(delay, 0, 260, 1, 0.2, 0, 0),
|
|
1953
|
+
point(delay + 0.55, 0, 0),
|
|
1954
|
+
point(end, 0, -22)
|
|
1955
|
+
]);
|
|
1956
|
+
} else if ((ctx.theme === "summer-case" || ctx.theme === "travel-conveyor") && /מזווד|גלגל מזוודה/.test(name)) {
|
|
1957
|
+
set(item, [
|
|
1958
|
+
point(0, -320, 0, 0.8, 0.8, -8, 0),
|
|
1959
|
+
point(0.75, -120, 0),
|
|
1960
|
+
point(d * 0.6, 25, 0),
|
|
1961
|
+
point(end, 190, 0, 1, 1, 7)
|
|
1962
|
+
]);
|
|
1963
|
+
} else if (ctx.theme === "wedding-rings" && /טבעת/.test(name)) {
|
|
1964
|
+
const left = /ראשונה/.test(name);
|
|
1965
|
+
set(item, [
|
|
1966
|
+
point(0, left ? -260 : 260, 0, 0.72, 0.72, left ? -25 : 25, 0),
|
|
1967
|
+
point(0.85, left ? -60 : 60, 0),
|
|
1968
|
+
point(d * 0.7, left ? 35 : -35, -12),
|
|
1969
|
+
point(end, left ? 25 : -25, 0)
|
|
1970
|
+
]);
|
|
1971
|
+
} else if (ctx.theme === "share-mosaic" && /אריח בעלות/.test(name)) {
|
|
1972
|
+
const n = Number(name.match(/\d+/)?.[0] ?? 1);
|
|
1973
|
+
const delay = 0.08 + n % 5 * 0.12 + Math.floor(n / 5) * 0.08;
|
|
1974
|
+
set(item, [
|
|
1975
|
+
point(0, 0, 0, 0.2, 0.2, 35, 0),
|
|
1976
|
+
point(delay, 0, 0, 0.2, 0.2, 35, 0),
|
|
1977
|
+
point(delay + 0.5, 0, 0),
|
|
1978
|
+
point(end, 0, -16 * (n % 3))
|
|
1979
|
+
]);
|
|
1980
|
+
} else if (ctx.theme === "fraud-alert" && /הודעה חשודה/.test(name)) {
|
|
1981
|
+
const n = Number(name.match(/\d+/)?.[0] ?? 1);
|
|
1982
|
+
const delay = 0.23 * n;
|
|
1983
|
+
set(item, [
|
|
1984
|
+
point(0, 340, 0, 1, 1, 0, 0),
|
|
1985
|
+
point(delay, 340, 0, 1, 1, 0, 0),
|
|
1986
|
+
point(delay + 0.48, 0, 0),
|
|
1987
|
+
point(d * 0.73, 0, -18),
|
|
1988
|
+
point(end, -80, -18, 1, 1, -3)
|
|
1989
|
+
]);
|
|
1990
|
+
} else if (ctx.theme === "learning-domino" && /אבן למידה/.test(name)) {
|
|
1991
|
+
const n = Number(name.match(/\d+/)?.[0] ?? 1);
|
|
1992
|
+
const delay = 0.19 * n;
|
|
1993
|
+
set(item, [
|
|
1994
|
+
point(0, 0, -200, 1, 1, -12, 0),
|
|
1995
|
+
point(delay, 0, -200, 1, 1, -12, 0),
|
|
1996
|
+
point(delay + 0.43, 0, 0, 1, 1, 0),
|
|
1997
|
+
point(end, n % 2 ? 30 : -30, 10, 1, 1, 18)
|
|
1998
|
+
]);
|
|
1999
|
+
} else if (ctx.theme === "fomo-storm" && /התראת לחץ/.test(name)) {
|
|
2000
|
+
const n = Number(name.match(/\d+/)?.[0] ?? 1);
|
|
2001
|
+
const delay = 0.1 * n;
|
|
2002
|
+
set(item, [
|
|
2003
|
+
point(0, n % 2 ? -350 : 350, 0, 0.85, 0.85, 0, 0),
|
|
2004
|
+
point(delay, n % 2 ? -350 : 350, 0, 0.85, 0.85, 0, 0),
|
|
2005
|
+
point(delay + 0.45, 0, 0),
|
|
2006
|
+
point(end, n % 2 ? 90 : -90, -55, 1, 1, 0, 0.45)
|
|
2007
|
+
]);
|
|
2008
|
+
} else if (ctx.theme === "market-clock" && /מחוג/.test(name)) {
|
|
2009
|
+
const long = /ארוך/.test(name);
|
|
2010
|
+
set(item, [
|
|
2011
|
+
point(0, 0, 0, 1, 1, long ? -95 : -40, 0),
|
|
2012
|
+
point(0.48, 0, 0, 1, 1, 0),
|
|
2013
|
+
point(d * 0.6, 0, 0, 1, 1, long ? 78 : 33),
|
|
2014
|
+
point(end, 0, 0, 1, 1, long ? 140 : 65)
|
|
2015
|
+
]);
|
|
2016
|
+
} else if (ctx.theme === "small-bricks" && /לבנה/.test(name)) {
|
|
2017
|
+
const n = Number(name.match(/\d+/)?.[0] ?? 1);
|
|
2018
|
+
const delay = n * 0.058;
|
|
2019
|
+
set(item, [
|
|
2020
|
+
point(0, 0, -220, 1, 1, 0, 0),
|
|
2021
|
+
point(delay, 0, -220, 1, 1, 0, 0),
|
|
2022
|
+
point(delay + 0.42, 0, 0),
|
|
2023
|
+
point(end, 0, -5)
|
|
2024
|
+
]);
|
|
2025
|
+
} else if (ctx.theme === "two-paths" && /מסלול/.test(name)) {
|
|
2026
|
+
const left = /1/.test(name);
|
|
2027
|
+
set(item, [
|
|
2028
|
+
point(0, left ? -310 : 310, 0, 0.8, 0.8, 0, 0),
|
|
2029
|
+
point(left ? 0.5 : 0.85, 0, 0),
|
|
2030
|
+
point(d * 0.6, 0, 0, left ? 1.04 : 0.94, left ? 1.04 : 0.94),
|
|
2031
|
+
point(end, 0, 0)
|
|
2032
|
+
]);
|
|
2033
|
+
} else if (ctx.theme === "small-store" && /פס סוכך/.test(name)) {
|
|
2034
|
+
const n = Number(name.match(/\d+/)?.[0] ?? 1);
|
|
2035
|
+
set(item, [
|
|
2036
|
+
point(0, 0, -240, 1, 0.2, 0, 0),
|
|
2037
|
+
point(0.16 * n, 0, -240, 1, 0.2, 0, 0),
|
|
2038
|
+
point(0.16 * n + 0.43, 0, 0),
|
|
2039
|
+
point(end, 0, 0)
|
|
2040
|
+
]);
|
|
2041
|
+
} else if (ctx.theme === "travel-conveyor" && /מסוע/.test(name)) {
|
|
2042
|
+
set(item, [point(0, -180, 0), point(d * 0.6, 0, 0), point(end, 80, 0)]);
|
|
2043
|
+
} else if (ctx.theme === "mortgage-blueprint" && /קו|קיר|גג|דלת/.test(name)) {
|
|
2044
|
+
const n = layers.indexOf(item);
|
|
2045
|
+
const delay = 0.16 * (n % 7);
|
|
2046
|
+
set(item, [
|
|
2047
|
+
point(0, 0, 0, 0, 1, 0, 0),
|
|
2048
|
+
point(delay, 0, 0, 0, 1, 0, 0),
|
|
2049
|
+
point(delay + 0.6, 0, 0),
|
|
2050
|
+
point(end, 0, 0)
|
|
2051
|
+
]);
|
|
2052
|
+
} else if (ctx.theme === "market-phone" && /עמודת נתון/.test(name)) {
|
|
2053
|
+
const n = Number(name.match(/\d+/)?.[0] ?? 1);
|
|
2054
|
+
const delay = 0.17 * n;
|
|
2055
|
+
set(item, [
|
|
2056
|
+
point(0, 0, 110, 1, 0.05, 0, 0),
|
|
2057
|
+
point(delay, 0, 110, 1, 0.05, 0, 0),
|
|
2058
|
+
point(delay + 0.55, 0, 0),
|
|
2059
|
+
point(end, 0, -30 + 9 * n, 1, 1.1)
|
|
2060
|
+
]);
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
var luminance = (c) => {
|
|
2065
|
+
const rgb = c.slice(1).match(/../g).map((v) => parseInt(v, 16) / 255).map((v) => v <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4);
|
|
2066
|
+
return rgb[0] * 0.2126 + rgb[1] * 0.7152 + rgb[2] * 0.0722;
|
|
2067
|
+
};
|
|
2068
|
+
var contrastRatio = (a, b) => {
|
|
2069
|
+
const x = luminance(a), y = luminance(b);
|
|
2070
|
+
return (Math.max(x, y) + 0.05) / (Math.min(x, y) + 0.05);
|
|
2071
|
+
};
|
|
2072
|
+
function contrastText(surface, preferred, alternative = "#101216") {
|
|
2073
|
+
if (contrastRatio(surface, preferred) >= 4.5) return preferred;
|
|
2074
|
+
if (contrastRatio(surface, alternative) >= 4.5) return alternative;
|
|
2075
|
+
return contrastRatio(surface, "#ffffff") >= contrastRatio(surface, "#101216") ? "#ffffff" : "#101216";
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2078
|
+
// src/core/config-v2.ts
|
|
2079
|
+
var componentTypes = ["hook", "kinetic", "counter", "cards", "checklist", "compare", "timeline", "bars", "phone", "chat", "map-route", "coins", "confetti", "freeze", "endcard", "quote", "progress", "logo"];
|
|
2080
|
+
var themes = {
|
|
2081
|
+
summer_ice: { bg: "#e7f8ff", fg: "#081b37", accent: "#0989d8", secondary: "#ffce42" },
|
|
2082
|
+
bank_red: { bg: "#ffffff", fg: "#172239", accent: "#e30613", secondary: "#ffe8e9" },
|
|
2083
|
+
midnight: { bg: "#07152f", fg: "#ffffff", accent: "#44e0d0", secondary: "#1a3158" },
|
|
2084
|
+
warm: { bg: "#fff6eb", fg: "#29213d", accent: "#f15a43", secondary: "#ffdb8a" },
|
|
2085
|
+
mono: { bg: "#101216", fg: "#ffffff", accent: "#eeeeee", secondary: "#41444c" }
|
|
2086
|
+
};
|
|
2087
|
+
var allowed = /* @__PURE__ */ new Set(["type", "duration", "title", "subtitle", "label", "product", "cta", "words", "items", "rows", "to", "beat", "ring", "transition"]);
|
|
2088
|
+
function safeText(value, label) {
|
|
2089
|
+
if (value === void 0) return void 0;
|
|
2090
|
+
if (typeof value !== "string" || value.length > 220 || /[\x00-\x08\x0b\x0c\x0e-\x1f]/.test(value)) throw new Error(`${label}: \u05D8\u05E7\u05E1\u05D8 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF`);
|
|
2091
|
+
return value;
|
|
2092
|
+
}
|
|
2093
|
+
function parseMotionConfigV2(value) {
|
|
2094
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("\u05E7\u05D5\u05E0\u05E4\u05D9\u05D2\u05D5\u05E8\u05E6\u05D9\u05D4 v2 \u05D0\u05D9\u05E0\u05D4 \u05D0\u05D5\u05D1\u05D9\u05D9\u05E7\u05D8");
|
|
2095
|
+
const v = value;
|
|
2096
|
+
if (v.format !== "motiondesk-config/v2") throw new Error("\u05E4\u05D5\u05E8\u05DE\u05D8 v2 \u05D0\u05D9\u05E0\u05D5 \u05EA\u05E7\u05D9\u05DF");
|
|
2097
|
+
for (const key of Object.keys(v)) if (!["format", "title", "theme", "aspectRatio", "fps", "scenes"].includes(key)) throw new Error(`\u05E9\u05D3\u05D4 \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8: ${key}`);
|
|
2098
|
+
const theme = v.theme === void 0 ? "bank_red" : safeText(v.theme, "theme");
|
|
2099
|
+
if (!themes[theme]) throw new Error("\u05E2\u05E8\u05DB\u05EA \u05E0\u05D5\u05E9\u05D0 \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8\u05EA");
|
|
2100
|
+
const aspectRatio = v.aspectRatio ?? "16:9";
|
|
2101
|
+
if (!["16:9", "9:16", "1:1"].includes(String(aspectRatio))) throw new Error("\u05D9\u05D7\u05E1 \u05DE\u05E1\u05DA \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8");
|
|
2102
|
+
const fps = v.fps ?? 30;
|
|
2103
|
+
if (![24, 25, 30, 60].includes(Number(fps))) throw new Error("fps \u05DC\u05D0 \u05E0\u05EA\u05DE\u05DA");
|
|
2104
|
+
if (!Array.isArray(v.scenes) || v.scenes.length < 1 || v.scenes.length > 30) throw new Error("\u05E0\u05D3\u05E8\u05E9\u05D5\u05EA 1\u201330 \u05E1\u05E6\u05E0\u05D5\u05EA");
|
|
2105
|
+
const scenes = v.scenes.map((raw, index) => {
|
|
2106
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) throw new Error(`\u05E1\u05E6\u05E0\u05D4 ${index + 1} \u05D0\u05D9\u05E0\u05D4 \u05D0\u05D5\u05D1\u05D9\u05D9\u05E7\u05D8`);
|
|
2107
|
+
const scene = raw;
|
|
2108
|
+
for (const key of Object.keys(scene)) if (!allowed.has(key)) throw new Error(`\u05E1\u05E6\u05E0\u05D4 ${index + 1}: \u05E9\u05D3\u05D4 \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8 ${key}`);
|
|
2109
|
+
if (!componentTypes.includes(scene.type)) throw new Error(`\u05E1\u05E6\u05E0\u05D4 ${index + 1}: \u05E8\u05DB\u05D9\u05D1 \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8`);
|
|
2110
|
+
const duration = scene.duration ?? 4;
|
|
2111
|
+
if (typeof duration !== "number" || !Number.isFinite(duration) || duration < 0.5 || duration > 30) throw new Error(`\u05E1\u05E6\u05E0\u05D4 ${index + 1}: \u05DE\u05E9\u05DA \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF`);
|
|
2112
|
+
const beat = scene.beat ?? 0.5;
|
|
2113
|
+
if (typeof beat !== "number" || !Number.isFinite(beat) || beat < 0.05 || beat > 3) throw new Error(`\u05E1\u05E6\u05E0\u05D4 ${index + 1}: beat \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF`);
|
|
2114
|
+
if (scene.to !== void 0 && (typeof scene.to !== "number" || !Number.isFinite(scene.to) || Math.abs(scene.to) > 1e9)) throw new Error(`\u05E1\u05E6\u05E0\u05D4 ${index + 1}: \u05DE\u05E1\u05E4\u05E8 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF`);
|
|
2115
|
+
if (scene.ring !== void 0 && typeof scene.ring !== "boolean") throw new Error(`\u05E1\u05E6\u05E0\u05D4 ${index + 1}: ring \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF`);
|
|
2116
|
+
if (scene.transition !== void 0 && !["cut", "fade", "slide", "wipe", "zoom", "push"].includes(String(scene.transition))) throw new Error(`\u05E1\u05E6\u05E0\u05D4 ${index + 1}: \u05DE\u05E2\u05D1\u05E8 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF`);
|
|
2117
|
+
const entry = { type: scene.type, duration, beat };
|
|
2118
|
+
for (const key of ["title", "subtitle", "label", "product", "cta"]) if (scene[key] !== void 0) entry[key] = safeText(scene[key], key);
|
|
2119
|
+
for (const key of ["words", "items"]) if (scene[key] !== void 0) {
|
|
2120
|
+
if (!Array.isArray(scene[key]) || scene[key].length > 20) throw new Error(`${key}: \u05E8\u05E9\u05D9\u05DE\u05D4 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D4`);
|
|
2121
|
+
entry[key] = scene[key].map((item, i) => safeText(item, `${key}.${i}`));
|
|
2122
|
+
}
|
|
2123
|
+
if (scene.rows !== void 0) {
|
|
2124
|
+
if (!Array.isArray(scene.rows) || scene.rows.length > 12) throw new Error("rows: \u05E8\u05E9\u05D9\u05DE\u05D4 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D4");
|
|
2125
|
+
entry.rows = scene.rows.map((row, i) => {
|
|
2126
|
+
if (!Array.isArray(row) || row.length > 3) return (() => {
|
|
2127
|
+
throw new Error(`rows.${i}: \u05E9\u05D5\u05E8\u05D4 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D4`);
|
|
2128
|
+
})();
|
|
2129
|
+
return row.map((cell, j) => safeText(cell, `rows.${i}.${j}`));
|
|
2130
|
+
});
|
|
2131
|
+
}
|
|
2132
|
+
if (scene.to !== void 0) entry.to = scene.to;
|
|
2133
|
+
if (scene.ring !== void 0) entry.ring = scene.ring;
|
|
2134
|
+
if (scene.transition !== void 0) entry.transition = scene.transition;
|
|
2135
|
+
return entry;
|
|
2136
|
+
});
|
|
2137
|
+
return { format: "motiondesk-config/v2", title: safeText(v.title, "title") || "\u05E1\u05E8\u05D8\u05D5\u05DF Motion \u05D7\u05D3\u05E9", theme, aspectRatio, fps, scenes };
|
|
2138
|
+
}
|
|
2139
|
+
function configV2ToProject(input) {
|
|
2140
|
+
const config = parseMotionConfigV2(input), ratio = config.aspectRatio, [w, h] = ratio === "9:16" ? [1080, 1920] : ratio === "1:1" ? [1080, 1080] : [1920, 1080];
|
|
2141
|
+
const theme = themes[config.theme], base = Math.min(w, h), portrait = h > w;
|
|
2142
|
+
const scenes = config.scenes.map((spec, index) => {
|
|
2143
|
+
const duration = spec.duration, scene = createScene(`${index + 1}. ${spec.type}`, duration);
|
|
2144
|
+
scene.background = theme.bg;
|
|
2145
|
+
scene.transition = spec.transition ?? (index ? "push" : "cut");
|
|
2146
|
+
scene.transitionDuration = Math.min(0.5, duration / 3);
|
|
2147
|
+
const add = (type, name, x, y, ww, hh, patch = {}) => {
|
|
2148
|
+
const layer2 = createLayer(type, { name, x: Math.round(x * w), y: Math.round(y * h), width: Math.round(ww * w), height: Math.round(hh * h), start: 0, duration, color: theme.fg, fontSize: Math.round(base * 0.065), fontWeight: 700, textAlign: "center", motion: "fade", motionDuration: 0.45, motionOut: "fade", motionOutDuration: 0.3, ...patch });
|
|
2149
|
+
scene.layers.push(layer2);
|
|
2150
|
+
return layer2;
|
|
2151
|
+
};
|
|
2152
|
+
const txt = (name, text3, x, y, ww, hh, size = 0.06, color = theme.fg, delay = 0, surface = theme.bg) => text3 !== void 0 ? add("text", name, x, y, ww, hh, { text: text3, fontSize: Math.round(base * size), color: contrastText(surface, color, theme.bg), motion: "slide-up", motionDelay: delay, splitText: "word", stagger: 0.08, shadow: "0 3px 10px #0002" }) : void 0;
|
|
2153
|
+
const box2 = (name, x, y, ww, hh, color = theme.accent, radius = 0.02) => add("shape", name, x, y, ww, hh, { color, borderRadius: Math.round(base * radius), motion: "pop" });
|
|
2154
|
+
const row = (items, y = 0.45) => items.slice(0, 5).forEach((item, i) => {
|
|
2155
|
+
const x = 0.08 + i * 0.84 / items.length, ww = 0.8 / items.length;
|
|
2156
|
+
box2(`\u05DB\u05E8\u05D8\u05D9\u05E1 ${i + 1}`, x, y, ww, 0.16, i % 2 ? theme.secondary : theme.accent);
|
|
2157
|
+
txt(`\u05D8\u05E7\u05E1\u05D8 \u05DB\u05E8\u05D8\u05D9\u05E1 ${i + 1}`, item, x + 0.015, y + 0.04, ww - 0.03, 0.08, 0.03, theme.fg, i * 0.12, i % 2 ? theme.secondary : theme.accent);
|
|
2158
|
+
});
|
|
2159
|
+
const headline = spec.title || spec.product || spec.label || spec.words?.[0] || "";
|
|
2160
|
+
switch (spec.type) {
|
|
2161
|
+
case "hook":
|
|
2162
|
+
box2("\u05E4\u05E1 \u05E4\u05EA\u05D9\u05D7\u05D4", 0.05, 0.08, 0.08, 0.82);
|
|
2163
|
+
txt("\u05DB\u05D5\u05EA\u05E8\u05EA", headline, 0.16, 0.29, 0.77, 0.32, 0.105);
|
|
2164
|
+
txt("\u05DB\u05D5\u05EA\u05E8\u05EA \u05DE\u05E9\u05E0\u05D4", spec.subtitle, 0.18, 0.65, 0.7, 0.13, 0.04, theme.accent, 0.3);
|
|
2165
|
+
break;
|
|
2166
|
+
case "kinetic":
|
|
2167
|
+
(spec.words?.length ? spec.words : [headline]).slice(0, 5).forEach((word, i) => txt(`\u05DE\u05D9\u05DC\u05D4 ${i + 1}`, word, 0.1, 0.15 + i * 0.15, 0.8, 0.14, 0.08, i % 2 ? theme.accent : theme.fg, i * (spec.beat || 0.5)));
|
|
2168
|
+
break;
|
|
2169
|
+
case "counter":
|
|
2170
|
+
txt("\u05DE\u05D5\u05E0\u05D4", String(spec.to ?? 100), 0.1, 0.27, 0.8, 0.28, 0.16, theme.accent);
|
|
2171
|
+
{
|
|
2172
|
+
const l = scene.layers.at(-1);
|
|
2173
|
+
l.countFrom = 0;
|
|
2174
|
+
l.countTo = spec.to ?? 100;
|
|
2175
|
+
l.motion = "none";
|
|
2176
|
+
l.motionDuration = Math.min(duration * 0.75, 2);
|
|
2177
|
+
}
|
|
2178
|
+
txt("\u05EA\u05D5\u05D5\u05D9\u05EA", spec.label || headline, 0.2, 0.64, 0.6, 0.13, 0.05);
|
|
2179
|
+
if (spec.ring) add("path", "\u05D8\u05D1\u05E2\u05EA", 0.28, 0.16, 0.44, 0.56, { pathData: `M ${0.22 * w} 0 A ${0.22 * w} ${0.28 * h} 0 1 1 ${0.22 * w - 1} 0`, stroke: theme.accent, strokeWidth: base * 0.012, color: theme.accent, motion: "zoom" });
|
|
2180
|
+
break;
|
|
2181
|
+
case "cards":
|
|
2182
|
+
txt("\u05DB\u05D5\u05EA\u05E8\u05EA", headline, 0.1, 0.1, 0.8, 0.15, 0.065);
|
|
2183
|
+
row(spec.items || spec.words || ["\u05E8\u05E2\u05D9\u05D5\u05DF", "\u05EA\u05E0\u05D5\u05E2\u05D4", "\u05EA\u05D5\u05E6\u05D0\u05D4"]);
|
|
2184
|
+
break;
|
|
2185
|
+
case "checklist":
|
|
2186
|
+
txt("\u05DB\u05D5\u05EA\u05E8\u05EA", headline, 0.1, 0.07, 0.8, 0.14, 0.064);
|
|
2187
|
+
(spec.items || ["\u05E9\u05DC\u05D1 \u05E8\u05D0\u05E9\u05D5\u05DF", "\u05E9\u05DC\u05D1 \u05E9\u05E0\u05D9", "\u05DE\u05D5\u05DB\u05E0\u05D9\u05DD"]).slice(0, 5).forEach((item, i) => {
|
|
2188
|
+
box2(`\u05E1\u05D9\u05DE\u05D5\u05DF ${i + 1}`, 0.15, 0.29 + i * 0.12, 0.055, 0.075);
|
|
2189
|
+
txt(`\u05E1\u05E2\u05D9\u05E3 ${i + 1}`, item, 0.24, 0.28 + i * 0.12, 0.6, 0.08, 0.038, theme.fg, i * 0.15);
|
|
2190
|
+
});
|
|
2191
|
+
break;
|
|
2192
|
+
case "compare":
|
|
2193
|
+
txt("\u05DB\u05D5\u05EA\u05E8\u05EA", headline, 0.1, 0.08, 0.8, 0.15);
|
|
2194
|
+
box2("\u05E6\u05D3 \u05D0", 0.07, 0.32, 0.4, 0.42, theme.secondary);
|
|
2195
|
+
box2("\u05E6\u05D3 \u05D1", 0.53, 0.32, 0.4, 0.42, theme.accent);
|
|
2196
|
+
txt("\u05D0\u05E4\u05E9\u05E8\u05D5\u05EA \u05D0", spec.items?.[0] || "\u05DC\u05E4\u05E0\u05D9", 0.09, 0.45, 0.36, 0.13, 0.053, theme.fg, 0, theme.secondary);
|
|
2197
|
+
txt("\u05D0\u05E4\u05E9\u05E8\u05D5\u05EA \u05D1", spec.items?.[1] || "\u05D0\u05D7\u05E8\u05D9", 0.55, 0.45, 0.36, 0.13, 0.053, theme.fg, 0, theme.accent);
|
|
2198
|
+
break;
|
|
2199
|
+
case "timeline":
|
|
2200
|
+
txt("\u05DB\u05D5\u05EA\u05E8\u05EA", headline, 0.1, 0.1, 0.8, 0.14);
|
|
2201
|
+
box2("\u05E6\u05D9\u05E8", 0.12, 0.52, 0.76, 0.018);
|
|
2202
|
+
(spec.items || ["\u05D4\u05EA\u05D7\u05DC\u05D4", "\u05D1\u05D3\u05E8\u05DA", "\u05D9\u05E2\u05D3"]).slice(0, 5).forEach((item, i, arr) => {
|
|
2203
|
+
const x = 0.12 + i * 0.72 / Math.max(1, arr.length - 1);
|
|
2204
|
+
box2(`\u05EA\u05D7\u05E0\u05D4 ${i + 1}`, x, 0.49, 0.045, 0.065);
|
|
2205
|
+
txt(`\u05E9\u05DD \u05EA\u05D7\u05E0\u05D4 ${i + 1}`, item, x - 0.06, 0.6, 0.17, 0.1, 0.028);
|
|
2206
|
+
});
|
|
2207
|
+
break;
|
|
2208
|
+
case "bars":
|
|
2209
|
+
txt("\u05DB\u05D5\u05EA\u05E8\u05EA", headline, 0.1, 0.08, 0.8, 0.14);
|
|
2210
|
+
(spec.rows || [["\u05D0", "40"], ["\u05D1", "70"], ["\u05D2", "95"]]).slice(0, 5).forEach((r, i) => {
|
|
2211
|
+
txt(`\u05E9\u05DD \u05E2\u05DE\u05D5\u05D3\u05D4 ${i + 1}`, r[0], 0.12, 0.3 + i * 0.12, 0.18, 0.07, 0.032);
|
|
2212
|
+
const l = box2(`\u05E2\u05DE\u05D5\u05D3\u05D4 ${i + 1}`, 0.32, 0.31 + i * 0.12, Math.min(0.55, Math.max(0.05, Number(r[1]) * 55e-4 || 0.3)), 0.055);
|
|
2213
|
+
l.keyframes = [{ at: 0, x: 0, y: 0, scaleX: 0.01, scaleY: 1, rotation: 0, opacity: 1 }, { at: Math.min(1, duration * 0.5), x: 0, y: 0, scaleX: 1, scaleY: 1, rotation: 0, opacity: 1, easing: "ease-out" }];
|
|
2214
|
+
});
|
|
2215
|
+
break;
|
|
2216
|
+
case "phone": {
|
|
2217
|
+
const frame = box2("\u05D8\u05DC\u05E4\u05D5\u05DF", portrait ? 0.2 : 0.36, 0.12, portrait ? 0.6 : 0.28, 0.75, theme.fg, 0.04);
|
|
2218
|
+
frame.type = "group";
|
|
2219
|
+
frame.color = theme.fg;
|
|
2220
|
+
const fw = frame.width, fh = frame.height;
|
|
2221
|
+
frame.children = [createLayer("shape", { name: "\u05DE\u05E1\u05D2\u05E8\u05EA \u05D8\u05DC\u05E4\u05D5\u05DF", x: 0, y: 0, width: fw, height: fh, color: theme.fg, borderRadius: base * 0.04, start: 0, duration }), createLayer("shape", { name: "\u05DE\u05E1\u05DA", x: fw * 0.05, y: fh * 0.04, width: fw * 0.9, height: fh * 0.91, color: theme.bg, borderRadius: base * 0.02, start: 0, duration }), createLayer("text", { name: "\u05DB\u05D5\u05EA\u05E8\u05EA \u05DE\u05E1\u05DA", text: headline, x: fw * 0.1, y: fh * 0.12, width: fw * 0.8, height: fh * 0.14, color: theme.fg, fontSize: Math.round(base * 0.035), textAlign: "center", start: 0, duration }), ...(spec.rows || [["\u05E4\u05E8\u05D9\u05D8", "72%"]]).slice(0, 4).map((r, i) => createLayer("text", { name: `\u05E9\u05D5\u05E8\u05EA \u05DE\u05E1\u05DA ${i + 1}`, text: r.join(" "), x: fw * 0.1, y: fh * (0.34 + i * 0.12), width: fw * 0.8, height: fh * 0.09, color: theme.fg, fontSize: Math.round(base * 0.025), textAlign: "right", start: 0, duration })), createLayer("text", { name: "\u05E4\u05E2\u05D5\u05DC\u05D4", text: spec.cta || "\u05DC\u05D4\u05DE\u05E9\u05DA", x: fw * 0.13, y: fh * 0.78, width: fw * 0.74, height: fh * 0.08, color: theme.accent, fontSize: Math.round(base * 0.03), textAlign: "center", start: 0, duration })];
|
|
2222
|
+
frame.motion = "slide-up";
|
|
2223
|
+
break;
|
|
2224
|
+
}
|
|
2225
|
+
case "chat":
|
|
2226
|
+
txt("\u05DB\u05D5\u05EA\u05E8\u05EA", headline, 0.1, 0.08, 0.8, 0.14);
|
|
2227
|
+
(spec.items || spec.words || ["\u05D4\u05D9\u05D9!", "\u05D0\u05D9\u05D6\u05D4 \u05D9\u05D5\u05E4\u05D9", "\u05D1\u05D5\u05D0\u05D5 \u05E0\u05EA\u05D7\u05D9\u05DC"]).slice(0, 5).forEach((item, i) => {
|
|
2228
|
+
const x = i % 2 ? 0.17 : 0.43;
|
|
2229
|
+
box2(`\u05D1\u05D5\u05E2\u05D4 ${i + 1}`, x, 0.27 + i * 0.12, 0.4, 0.095, i % 2 ? theme.secondary : theme.accent);
|
|
2230
|
+
txt(`\u05D4\u05D5\u05D3\u05E2\u05D4 ${i + 1}`, item, x + 0.02, 0.28 + i * 0.12, 0.36, 0.07, 0.03, theme.fg, i * 0.25, i % 2 ? theme.secondary : theme.accent);
|
|
2231
|
+
});
|
|
2232
|
+
break;
|
|
2233
|
+
case "map-route":
|
|
2234
|
+
txt("\u05DB\u05D5\u05EA\u05E8\u05EA", headline, 0.1, 0.07, 0.8, 0.14);
|
|
2235
|
+
add("path", "\u05DE\u05E1\u05DC\u05D5\u05DC", 0.12, 0.25, 0.76, 0.5, { pathData: `M 0 ${0.3 * h} C ${0.2 * w} 0 ${0.37 * w} ${0.5 * h} ${0.7 * w} ${0.1 * h}`, stroke: theme.accent, strokeWidth: base * 0.015, color: theme.accent, motion: "fade" });
|
|
2236
|
+
row(spec.items || ["\u05D9\u05D5\u05E6\u05D0\u05D9\u05DD", "\u05DE\u05D2\u05D9\u05E2\u05D9\u05DD"], 0.8);
|
|
2237
|
+
break;
|
|
2238
|
+
case "coins":
|
|
2239
|
+
txt("\u05DB\u05D5\u05EA\u05E8\u05EA", headline, 0.1, 0.08, 0.8, 0.14);
|
|
2240
|
+
for (let i = 0; i < 7; i++) {
|
|
2241
|
+
const coin = box2(`\u05DE\u05D8\u05D1\u05E2 ${i + 1}`, 0.18 + i * 0.09, 0.42 - i % 3 * 0.055, 0.075, 0.12, theme.secondary, 0.05);
|
|
2242
|
+
coin.rotation = i * 8;
|
|
2243
|
+
coin.motion = "slide-up";
|
|
2244
|
+
coin.motionDelay = i * 0.1;
|
|
2245
|
+
}
|
|
2246
|
+
txt("\u05E1\u05DB\u05D5\u05DD", spec.label || String(spec.to || ""), 0.1, 0.7, 0.8, 0.16, 0.07, theme.accent);
|
|
2247
|
+
break;
|
|
2248
|
+
case "confetti":
|
|
2249
|
+
txt("\u05DB\u05D5\u05EA\u05E8\u05EA", headline, 0.1, 0.28, 0.8, 0.25, 0.095);
|
|
2250
|
+
for (let i = 0; i < 18; i++) {
|
|
2251
|
+
const x = i * 37 % 91 / 100, y = i * 29 % 83 / 100;
|
|
2252
|
+
const bit = box2(`\u05E7\u05D5\u05E0\u05E4\u05D8\u05D9 ${i + 1}`, x, y, 0.015, 0.045, i % 2 ? theme.accent : theme.secondary, 0);
|
|
2253
|
+
bit.rotation = i * 25;
|
|
2254
|
+
bit.motion = "slide-down";
|
|
2255
|
+
bit.motionDelay = i % 6 * 0.08;
|
|
2256
|
+
}
|
|
2257
|
+
break;
|
|
2258
|
+
case "freeze":
|
|
2259
|
+
txt("\u05DB\u05D5\u05EA\u05E8\u05EA", headline, 0.1, 0.2, 0.8, 0.2, 0.085);
|
|
2260
|
+
box2("\u05E7\u05D5 \u05D4\u05E7\u05E4\u05D0\u05D4", 0.1, 0.52, 0.8, 0.018, theme.accent);
|
|
2261
|
+
txt("\u05DB\u05D9\u05EA\u05D5\u05D1", spec.subtitle || spec.label, 0.18, 0.59, 0.64, 0.12, 0.04);
|
|
2262
|
+
break;
|
|
2263
|
+
case "endcard":
|
|
2264
|
+
box2("\u05E4\u05E1 \u05DE\u05D5\u05E6\u05E8", 0.08, 0.17, 0.84, 0.05);
|
|
2265
|
+
txt("\u05DE\u05D5\u05E6\u05E8", spec.product || headline, 0.1, 0.3, 0.8, 0.19, 0.09);
|
|
2266
|
+
txt("\u05E4\u05E2\u05D5\u05DC\u05D4", spec.cta || "\u05DC\u05E4\u05E8\u05D8\u05D9\u05DD \u05E0\u05D5\u05E1\u05E4\u05D9\u05DD", 0.22, 0.65, 0.56, 0.13, 0.045, theme.accent, 0.3);
|
|
2267
|
+
break;
|
|
2268
|
+
case "quote":
|
|
2269
|
+
box2("\u05E1\u05D9\u05DE\u05DF \u05E6\u05D9\u05D8\u05D5\u05D8", 0.1, 0.16, 0.1, 0.12, theme.accent);
|
|
2270
|
+
txt("\u05E6\u05D9\u05D8\u05D5\u05D8", headline, 0.18, 0.33, 0.65, 0.3, 0.07);
|
|
2271
|
+
txt("\u05D9\u05D9\u05D7\u05D5\u05E1", spec.label, 0.2, 0.73, 0.6, 0.09, 0.035, theme.accent);
|
|
2272
|
+
break;
|
|
2273
|
+
case "progress":
|
|
2274
|
+
txt("\u05DB\u05D5\u05EA\u05E8\u05EA", headline, 0.1, 0.15, 0.8, 0.15);
|
|
2275
|
+
box2("\u05DE\u05E1\u05D9\u05DC\u05D4", 0.12, 0.5, 0.76, 0.07, theme.secondary);
|
|
2276
|
+
{
|
|
2277
|
+
const l = box2("\u05D4\u05EA\u05E7\u05D3\u05DE\u05D5\u05EA", 0.12, 0.5, 0.76, 0.07, theme.accent);
|
|
2278
|
+
l.keyframes = [{ at: 0, x: 0, y: 0, scaleX: 0, scaleY: 1, rotation: 0, opacity: 1 }, { at: Math.min(2, duration * 0.7), x: 0, y: 0, scaleX: 1, scaleY: 1, rotation: 0, opacity: 1, easing: "ease-out" }];
|
|
2279
|
+
}
|
|
2280
|
+
txt("\u05D9\u05E2\u05D3", spec.label || `${spec.to || 100}%`, 0.2, 0.65, 0.6, 0.11, 0.05);
|
|
2281
|
+
break;
|
|
2282
|
+
case "logo":
|
|
2283
|
+
box2("\u05E1\u05DE\u05DC", 0.38, 0.22, 0.24, 0.3, theme.accent, 0.06);
|
|
2284
|
+
txt("\u05DE\u05D5\u05EA\u05D2", headline, 0.13, 0.6, 0.74, 0.15, 0.075);
|
|
2285
|
+
break;
|
|
2286
|
+
}
|
|
2287
|
+
return scene;
|
|
2288
|
+
});
|
|
2289
|
+
const project = createProject(config.title, { canvas: { width: w, height: h, fps: config.fps }, scenes });
|
|
2290
|
+
assertProject(project);
|
|
2291
|
+
return project;
|
|
2292
|
+
}
|
|
2293
|
+
|
|
2294
|
+
// src/core/config-v3-components.ts
|
|
2295
|
+
var mix = (a, b, t) => "#" + [0, 2, 4].map((i) => Math.round(parseInt(a.slice(i + 1, i + 3), 16) * (1 - t) + parseInt(b.slice(i + 1, i + 3), 16) * t).toString(16).padStart(2, "0")).join("");
|
|
2296
|
+
function compileConfigV3Scene(spec, palette, w, h, seed, index) {
|
|
2297
|
+
const d = spec.duration, base = Math.min(w, h), portrait = h > w, variant = spec.variant, energy = spec.energy, a = spec.accent ?? palette.accent;
|
|
2298
|
+
const bg = palette.background, fg = contrastText(bg, palette.foreground), secondary = palette.secondary, accentText = contrastText(bg, a, fg);
|
|
2299
|
+
const factor = energy === "calm" ? 0.48 : energy === "punchy" ? 1.45 : 1, stagger = energy === "calm" ? 0.065 : energy === "punchy" ? 0.035 : 0.05;
|
|
2300
|
+
const spring = { stiffness: energy === "punchy" ? 190 : 100, damping: energy === "punchy" ? 14 : 23, mass: 1 };
|
|
2301
|
+
const headline = spec.title ?? spec.product ?? (spec.type === "kinetic" ? void 0 : spec.words?.[0]);
|
|
2302
|
+
const scene = createScene(`${index + 1}. ${spec.title ?? spec.product ?? "\u05E1\u05E6\u05E0\u05EA \u05EA\u05E0\u05D5\u05E2\u05D4"}`, d);
|
|
2303
|
+
scene.background = bg;
|
|
2304
|
+
scene.transition = spec.transition ?? (index ? energy === "punchy" ? "whip" : variant === "stacked" ? "stack" : "diagonal-wipe" : "cut");
|
|
2305
|
+
scene.transitionDuration = Math.min(d * 0.18, 0.62);
|
|
2306
|
+
scene.transitionEasing = [0.16, 0.85, 0.22, 1];
|
|
2307
|
+
const visual = variant === "split" ? portrait ? { x: 0.08 * w, y: 0.39 * h, w: 0.84 * w, h: 0.43 * h } : { x: 0.065 * w, y: 0.23 * h, w: 0.44 * w, h: 0.6 * h } : variant === "centered" ? { x: 0.14 * w, y: 0.39 * h, w: 0.72 * w, h: 0.43 * h } : { x: 0.09 * w, y: 0.17 * h, w: 0.82 * w, h: 0.43 * h };
|
|
2308
|
+
const titleRect = variant === "split" ? portrait ? { x: 0.09 * w, y: 0.14 * h, w: 0.82 * w, h: 0.22 * h } : { x: 0.55 * w, y: 0.25 * h, w: 0.38 * w, h: 0.48 * h } : variant === "centered" ? { x: 0.09 * w, y: 0.15 * h, w: 0.82 * w, h: 0.2 * h } : { x: 0.09 * w, y: 0.65 * h, w: 0.82 * w, h: 0.22 * h };
|
|
2309
|
+
const k = (time, patch = {}) => ({ ...point(d * time), ...patch });
|
|
2310
|
+
let serial = 0;
|
|
2311
|
+
const layer2 = (type, name, x, y, ww, hh, patch = {}) => {
|
|
2312
|
+
const l = createLayer(type, { name, x, y, width: Math.max(1, ww), height: Math.max(1, hh), start: 0, duration: d, color: fg, fontSize: base * 0.04, fontWeight: 700, motion: "none", motionOut: "none", textAlign: "center", textFit: "shrink", lineHeight: 1.12, depth: 0, ...patch });
|
|
2313
|
+
l.keyframes ??= [k(0, { x: (serial % 2 ? 1 : -1) * base * 0.1 * factor, y: base * 0.035 * factor, scaleX: 0.87, scaleY: 0.87, opacity: 0, blur: energy === "calm" ? 0 : 7, rotateY: energy === "punchy" ? -16 : 0 }), k(0.22, { easing: spring }), k(0.94, { y: -base * 9e-3 * factor, easing: "linear" })];
|
|
2314
|
+
serial++;
|
|
2315
|
+
scene.layers.push(l);
|
|
2316
|
+
return l;
|
|
2317
|
+
};
|
|
2318
|
+
const shape = (name, x, y, ww, hh, color = a, patch = {}) => layer2("shape", name, x, y, ww, hh, { color, borderRadius: base * 0.018, ...patch });
|
|
2319
|
+
const text3 = (name, value, x, y, ww, hh, size = base * 0.06, color = fg, delay = 0, surface = bg) => {
|
|
2320
|
+
if (!value) return void 0;
|
|
2321
|
+
let fontSize = Math.min(size, hh * 0.8);
|
|
2322
|
+
const lines = (font) => value.split("\n").reduce((sum, line) => sum + Math.max(1, Math.ceil(line.length * font * 0.68 / Math.max(1, ww))), 0);
|
|
2323
|
+
while (fontSize > 12 && lines(fontSize) * fontSize * 1.2 > hh) fontSize--;
|
|
2324
|
+
const result = layer2("text", name, x, y, ww, hh, { text: value, fontSize: Math.max(12, fontSize), color, splitText: "word", stagger: Math.min(d * stagger, d * 0.18 / Math.max(1, value.split(/\s+/).length)), staggerOrder: variant === "centered" ? "center" : "start", textUnitKeyframes: [point(0, 0, base * 0.065 * factor, 0.9, 0.9, energy === "punchy" ? 7 : 0, 0), { ...point(d * 0.18), easing: spring }], keyframes: [k(0, { opacity: delay > 0 ? 0 : 1 }), ...delay > 0 ? [k(delay, { opacity: 1, easing: "hold" })] : [], k(0.95)] });
|
|
2325
|
+
if (spec.emphasis) {
|
|
2326
|
+
const matches = [];
|
|
2327
|
+
let from = 0;
|
|
2328
|
+
while (from < value.length) {
|
|
2329
|
+
const start = value.indexOf(spec.emphasis, from);
|
|
2330
|
+
if (start < 0) break;
|
|
2331
|
+
matches.push([start, start + spec.emphasis.length]);
|
|
2332
|
+
from = start + Math.max(1, spec.emphasis.length);
|
|
2333
|
+
}
|
|
2334
|
+
result.textUnitColors = Array.from(value.matchAll(/\S+/gu), (unit) => matches.some(([start, end]) => unit.index < end && unit.index + unit[0].length > start) ? contrastText(surface, a, color) : color);
|
|
2335
|
+
}
|
|
2336
|
+
return result;
|
|
2337
|
+
};
|
|
2338
|
+
const localShape = (name, x, y, ww, hh, c = a, patch = {}) => shape(name, visual.x + x * visual.w, visual.y + y * visual.h, ww * visual.w, hh * visual.h, c, patch);
|
|
2339
|
+
const localText = (name, value, x, y, ww, hh, size = 0.07, c = fg, delay = 0, surface = bg) => text3(name, value, visual.x + x * visual.w, visual.y + y * visual.h, ww * visual.w, hh * visual.h, Math.min(base * size, visual.w * 0.22), c, delay, surface);
|
|
2340
|
+
const path = (name, x, y, ww, hh, pathData, c = a, sw = base * 6e-3, patch = {}) => layer2("path", name, x, y, ww, hh, { pathData, color: c, stroke: c, strokeWidth: sw, keyframes: [k(0, { reveal: 0 }), k(0.65, { reveal: 1, easing: [0.16, 0.85, 0.22, 1] }), k(0.96, { reveal: 1 })], ...patch });
|
|
2341
|
+
const number2 = (name, x, y, ww, hh, size, target = spec.value ?? 100) => layer2("text", name, x, y, ww, hh, { text: "0", fontSize: Math.min(size, hh * 0.8), textFit: "shrink", color: accentText, countFrom: spec.from ?? 0, countTo: target, countPrefix: spec.prefix, countSuffix: spec.suffix, countDecimals: spec.decimals ?? 0, countThousands: spec.thousands ?? true, keyframes: [k(0, { value: spec.from ?? 0, opacity: 0 }), k(0.07, { value: spec.from ?? 0 }), k(0.66, { value: target, easing: "ease-out" }), k(0.96, { value: target })] });
|
|
2342
|
+
const badge = (name, content, x, y, ww, hh, c = a) => {
|
|
2343
|
+
localShape(name, x, y, ww, hh, c);
|
|
2344
|
+
localText(`${name} \u05D8\u05E7\u05E1\u05D8`, content, x + 0.025, y + 0.15 * hh, ww - 0.05, hh * 0.7, 0.033, contrastText(c, palette.foreground, bg), 0, c);
|
|
2345
|
+
};
|
|
2346
|
+
const list2 = spec.items ?? spec.words ?? ["\u05E8\u05E2\u05D9\u05D5\u05DF", "\u05EA\u05E0\u05D5\u05E2\u05D4", "\u05EA\u05D5\u05E6\u05D0\u05D4"];
|
|
2347
|
+
const card = (item, i, n) => {
|
|
2348
|
+
const cols = variant === "centered" ? Math.min(3, n) : variant === "stacked" ? Math.min(4, n) : portrait ? 1 : Math.min(2, n), rows = Math.ceil(n / cols), gap = 0.035, cw = (1 - gap * (cols - 1)) / cols, ch = (0.88 - gap * (rows - 1)) / rows, x = i % cols * (cw + gap), y = Math.floor(i / cols) * (ch + gap);
|
|
2349
|
+
const c = i % 2 ? secondary : a;
|
|
2350
|
+
localShape(`\u05DB\u05E8\u05D8\u05D9\u05E1 ${i + 1}`, x, y, cw, ch, c, { rotation: variant === "stacked" ? i % 2 ? 2 : -2 : 0, depth: -0.1 - i * 0.03 });
|
|
2351
|
+
localText(`\u05DE\u05E1\u05E4\u05E8 \u05DB\u05E8\u05D8\u05D9\u05E1 ${i + 1}`, String(i + 1).padStart(2, "0"), x + 0.04, y + 0.04, cw - 0.08, ch * 0.27, 0.035, contrastText(c, palette.foreground, bg), Math.min(0.22, i * stagger), c);
|
|
2352
|
+
localText(`\u05D8\u05E7\u05E1\u05D8 \u05DB\u05E8\u05D8\u05D9\u05E1 ${i + 1}`, item, x + 0.04, y + ch * 0.35, cw - 0.08, ch * 0.54, 0.045, contrastText(c, palette.foreground, bg), Math.min(0.25, i * stagger), c);
|
|
2353
|
+
};
|
|
2354
|
+
if (spec.background === "gradient") shape("\u05DE\u05E2\u05D1\u05E8 \u05D2\u05D5\u05D5\u05DF", 0, 0, w, h, `linear-gradient(90deg, ${bg}, ${mix(bg, secondary, 0.32)})`, { keyframes: [k(0), k(1)], depth: 1, borderRadius: 0 });
|
|
2355
|
+
if (spec.background === "grid" || spec.background === "dots") {
|
|
2356
|
+
const dots = spec.background === "dots";
|
|
2357
|
+
for (let row = 0; row < (dots ? 8 : 1); row++) layer2("repeater", dots ? `\u05E8\u05E9\u05EA \u05E0\u05E7\u05D5\u05D3\u05D5\u05EA ${row + 1}` : "\u05E8\u05E9\u05EA \u05D0\u05E0\u05DB\u05D9\u05EA", w * 0.04, dots ? h * (0.15 + row * 0.1) : h * 0.12, dots ? base * 5e-3 : 1, dots ? base * 5e-3 : h * 0.75, { color: fg, opacity: 0.09, borderRadius: dots ? 10 : 0, depth: 1, keyframes: [k(0), k(1)], repeater: { count: dots ? 14 : 16, seed: seed + row | 0, shape: dots ? "ellipse" : "rect", offsetX: w * 0.068, offsetY: 0, rotation: 0, delay: 0 } });
|
|
2358
|
+
if (!dots) layer2("repeater", "\u05E8\u05E9\u05EA \u05D0\u05D5\u05E4\u05E7\u05D9\u05EA", w * 0.04, h * 0.15, w * 0.92, 1, { color: fg, opacity: 0.09, depth: 1, keyframes: [k(0), k(1)], repeater: { count: 8, seed, shape: "rect", offsetX: 0, offsetY: h * 0.1, rotation: 0, delay: 0 } });
|
|
2359
|
+
}
|
|
2360
|
+
if (spec.background === "motif") {
|
|
2361
|
+
const diameter = base * 0.58;
|
|
2362
|
+
const rings = [shape("\u05D8\u05D1\u05E2\u05EA \u05E8\u05D0\u05E9\u05D5\u05E0\u05D4", w * 0.03, h * 0.18, diameter, diameter, a, { color: bg, borderColor: a, borderWidth: base * 2e-3, borderRadius: diameter, opacity: 0.18, depth: 1 }), shape("\u05D8\u05D1\u05E2\u05EA \u05E9\u05E0\u05D9\u05D9\u05D4", w * 0.6, h * 0.35, diameter * 0.64, diameter * 0.64, secondary, { color: bg, borderColor: secondary, borderWidth: base * 0.018, borderRadius: diameter, opacity: 0.26, depth: 0.8 })];
|
|
2363
|
+
animateMotif({ scene: { ...scene, duration: 4 }, index, theme: "wedding-rings" }, rings);
|
|
2364
|
+
for (const ring of rings) ring.keyframes = ring.keyframes.map((frame) => ({ ...frame, at: frame.at / 4 * d }));
|
|
2365
|
+
}
|
|
2366
|
+
shape("\u05E7\u05D5 \u05DE\u05E2\u05E8\u05DB\u05EA", w * 0.06, h * 0.095, w * 0.88, 1, fg, { opacity: 0.2, depth: 1, keyframes: [k(0), k(1)] });
|
|
2367
|
+
text3("\u05DE\u05E1\u05E4\u05E8 \u05E1\u05E6\u05E0\u05D4", String(index + 1).padStart(2, "0"), w * 0.065, h * 0.05, w * 0.08, h * 0.03, base * 0.021, fg);
|
|
2368
|
+
shape("\u05E6\u05D9\u05E8 \u05E1\u05E6\u05E0\u05D4", w * 0.06, h * 0.925, w * 0.88, base * 4e-3, fg, { opacity: 0.15, keyframes: [k(0), k(1)] });
|
|
2369
|
+
shape("\u05E7\u05E6\u05D1 \u05E1\u05E6\u05E0\u05D4", w * 0.06, h * 0.925, w * 0.88, base * 4e-3, a, { transformOrigin: "left center", keyframes: [k(0, { scaleX: 0 }), k(1, { scaleX: 1, easing: "linear" })] });
|
|
2370
|
+
const header = text3("\u05DB\u05D5\u05EA\u05E8\u05EA", headline, titleRect.x, titleRect.y, titleRect.w, titleRect.h * 0.65, base * (headline && headline.length < 24 ? 0.09 : 0.065), fg);
|
|
2371
|
+
if (header) {
|
|
2372
|
+
header.textAlign = variant === "split" && !portrait ? "right" : "center";
|
|
2373
|
+
header.fontWeight = 850;
|
|
2374
|
+
}
|
|
2375
|
+
text3("\u05DB\u05D5\u05EA\u05E8\u05EA \u05DE\u05E9\u05E0\u05D4", spec.subtitle, titleRect.x, titleRect.y + titleRect.h * 0.7, titleRect.w, titleRect.h * 0.28, base * 0.033, fg, 0.08);
|
|
2376
|
+
switch (spec.type) {
|
|
2377
|
+
case "counter":
|
|
2378
|
+
case "donut": {
|
|
2379
|
+
const diameter = Math.min(visual.w * 0.85, visual.h * 0.72), x = visual.x + (visual.w - diameter) / 2, y = visual.y;
|
|
2380
|
+
const n = number2("\u05DE\u05D5\u05E0\u05D4", x + diameter * 0.07, y + diameter * 0.32, diameter * 0.86, diameter * 0.32, diameter * 0.23);
|
|
2381
|
+
if (spec.ring !== false || spec.type === "donut") {
|
|
2382
|
+
const pad = diameter * 0.045, r = diameter / 2 - pad, arc = `M ${diameter / 2} ${pad} A ${r} ${r} 0 1 1 ${diameter / 2 - 0.01} ${pad}`;
|
|
2383
|
+
path("\u05DE\u05E1\u05D9\u05DC\u05EA \u05D8\u05D1\u05E2\u05EA", x, y, diameter, diameter, arc, mix(bg, fg, 0.16), diameter * 0.035, { keyframes: [k(0, { reveal: 1 }), k(1, { reveal: 1 })] });
|
|
2384
|
+
path("\u05D8\u05D1\u05E2\u05EA \u05E2\u05E8\u05DA", x, y, diameter, diameter, arc, a, diameter * 0.035, { ...(spec.from ?? 0) === (spec.max ?? spec.value ?? 100) ? { keyframes: [k(0, { reveal: 1 }), k(1, { reveal: 1 })] } : { revealBinding: { layerId: n.id, from: spec.from ?? 0, to: spec.max ?? spec.value ?? 100 }, keyframes: [k(0), k(1)] } });
|
|
2385
|
+
}
|
|
2386
|
+
text3("\u05EA\u05D5\u05D5\u05D9\u05EA", spec.label, x - diameter * 0.1, y + diameter + base * 0.025, diameter * 1.2, Math.min(visual.h - diameter - base * 0.025, base * 0.09), base * 0.034, fg);
|
|
2387
|
+
break;
|
|
2388
|
+
}
|
|
2389
|
+
case "big-number": {
|
|
2390
|
+
localShape("\u05DC\u05D5\u05D7 \u05DE\u05E1\u05E4\u05E8", 0.02, 0.08, 0.96, 0.61, secondary, { rotation: variant === "stacked" ? -3 : 0 });
|
|
2391
|
+
const n = number2("\u05DE\u05E1\u05E4\u05E8 \u05D2\u05D3\u05D5\u05DC", visual.x + visual.w * 0.04, visual.y + visual.h * 0.1, visual.w * 0.92, visual.h * 0.51, base * 0.22);
|
|
2392
|
+
n.color = contrastText(secondary, a, palette.foreground);
|
|
2393
|
+
n.keyframes = n.keyframes.map((frame, i) => ({ ...frame, clip: { type: "inset", top: i ? 0 : 100, right: 0, bottom: 0, left: 0 }, blur: i ? 0 : 8 }));
|
|
2394
|
+
localText("\u05EA\u05D5\u05D5\u05D9\u05EA", spec.label, 0.05, 0.76, 0.9, 0.13, 0.04);
|
|
2395
|
+
break;
|
|
2396
|
+
}
|
|
2397
|
+
case "progress": {
|
|
2398
|
+
const n = number2("\u05DE\u05D5\u05E0\u05D4 \u05D4\u05EA\u05E7\u05D3\u05DE\u05D5\u05EA", visual.x, visual.y + visual.h * 0.05, visual.w, visual.h * 0.29, base * 0.13);
|
|
2399
|
+
const y = 0.49;
|
|
2400
|
+
localShape("\u05DE\u05E1\u05D9\u05DC\u05EA \u05D4\u05EA\u05E7\u05D3\u05DE\u05D5\u05EA", 0.03, y, 0.94, 0.065, secondary, { keyframes: [k(0), k(1)] });
|
|
2401
|
+
localShape("\u05DE\u05D9\u05DC\u05D5\u05D9 \u05D4\u05EA\u05E7\u05D3\u05DE\u05D5\u05EA", 0.03, y, 0.94, 0.065, a, { transformOrigin: "left center", ...(spec.from ?? 0) === (spec.max ?? spec.value ?? 100) ? { keyframes: [k(0, { reveal: 1 }), k(1, { reveal: 1 })] } : { revealBinding: { layerId: n.id, from: spec.from ?? 0, to: spec.max ?? spec.value ?? 100 }, keyframes: [k(0), k(1)] } });
|
|
2402
|
+
localText("\u05EA\u05D5\u05D5\u05D9\u05EA", spec.label, 0.02, 0.69, 0.96, 0.16, 0.045);
|
|
2403
|
+
break;
|
|
2404
|
+
}
|
|
2405
|
+
case "cards":
|
|
2406
|
+
list2.forEach((item, i) => card(item, i, list2.length));
|
|
2407
|
+
break;
|
|
2408
|
+
case "compare": {
|
|
2409
|
+
const n = 2;
|
|
2410
|
+
for (let i = 0; i < n; i++) {
|
|
2411
|
+
const vertical = variant === "stacked" || portrait, x = vertical ? 0 : i * 0.52, y = vertical ? i * 0.47 : 0, c = i ? a : secondary, cw = vertical ? 1 : 0.48, ch = vertical ? 0.42 : 0.86;
|
|
2412
|
+
localShape(`\u05D0\u05E4\u05E9\u05E8\u05D5\u05EA ${i + 1}`, x, y, cw, ch, c, { rotation: variant === "centered" ? i ? 2 : -2 : 0 });
|
|
2413
|
+
localText(`\u05E1\u05D9\u05DE\u05D5\u05DF \u05D0\u05E4\u05E9\u05E8\u05D5\u05EA ${i + 1}`, i ? "02" : "01", x + 0.04, y + 0.06, cw - 0.08, ch * 0.25, 0.045, contrastText(c, palette.foreground, bg));
|
|
2414
|
+
localText(`\u05EA\u05D5\u05DB\u05DF \u05D0\u05E4\u05E9\u05E8\u05D5\u05EA ${i + 1}`, list2[i] ?? (i ? "\u05D0\u05D7\u05E8\u05D9" : "\u05DC\u05E4\u05E0\u05D9"), x + 0.04, y + ch * 0.43, cw - 0.08, ch * 0.42, 0.058, contrastText(c, palette.foreground, bg), 0, c);
|
|
2415
|
+
}
|
|
2416
|
+
break;
|
|
2417
|
+
}
|
|
2418
|
+
case "checklist":
|
|
2419
|
+
case "chat":
|
|
2420
|
+
case "notification-stack": {
|
|
2421
|
+
const hasCta = spec.type === "notification-stack" && !!spec.cta, n = list2.length, gap = 0.025, ch = ((hasCta ? 0.7 : 0.92) - gap * (n - 1)) / n;
|
|
2422
|
+
list2.forEach((item, i) => {
|
|
2423
|
+
const chat = spec.type === "chat", x = chat ? i % 2 ? 0.03 : 0.16 : variant === "stacked" ? i * 0.012 : 0, c = i % 2 ? secondary : a, cw = chat ? 0.8 : 0.94;
|
|
2424
|
+
localShape(`${chat ? "\u05D1\u05D5\u05E2\u05D4" : "\u05D4\u05EA\u05E8\u05D0\u05D4"} ${i + 1}`, x, i * (ch + gap), cw, ch, c, { rotation: spec.type === "notification-stack" && variant === "centered" ? i % 2 ? 2 : -2 : 0, depth: -i * 0.03 });
|
|
2425
|
+
if (!chat) localText(`\u05E1\u05D9\u05DE\u05D5\u05DF ${i + 1}`, spec.type === "checklist" ? "\u2713" : "\u2022", x + 0.02, i * (ch + gap) + ch * 0.2, 0.1, ch * 0.55, 0.04, contrastText(c, palette.foreground, bg));
|
|
2426
|
+
localText(`\u05D4\u05D5\u05D3\u05E2\u05D4 ${i + 1}`, item, x + (chat ? 0.03 : 0.14), i * (ch + gap) + ch * 0.16, cw - (chat ? 0.06 : 0.18), ch * 0.68, 0.045, contrastText(c, palette.foreground, bg), Math.min(0.3, i * stagger), c);
|
|
2427
|
+
});
|
|
2428
|
+
if (hasCta) badge("\u05DB\u05E8\u05D8\u05D9\u05E1 \u05E4\u05E2\u05D5\u05DC\u05D4", spec.cta, 0.06, 0.78, 0.88, 0.16, a);
|
|
2429
|
+
break;
|
|
2430
|
+
}
|
|
2431
|
+
case "bars": {
|
|
2432
|
+
const values = spec.values ?? spec.rows?.map((r) => Number(r[1])) ?? [34, 49, 45, 63, 74, 91], max = spec.max ?? Math.max(1, ...values.map(Math.abs));
|
|
2433
|
+
const vertical = variant !== "split", n = values.length;
|
|
2434
|
+
values.forEach((v, i) => {
|
|
2435
|
+
const band = 0.9 / n, c = i === n - 1 ? a : secondary, name = spec.rows?.[i]?.[0] ?? spec.items?.[i] ?? String(i + 1), ratio = Math.min(1, Math.abs(v) / max);
|
|
2436
|
+
const delay = 0.06 + i * 0.24 / Math.max(1, n - 1), enter = delay + (energy === "calm" ? 0.42 : energy === "punchy" ? 0.27 : 0.35), height = visual.h * 0.65 * ratio;
|
|
2437
|
+
const poses = (value) => [k(0, { ...value ? { value: 0, y: vertical ? height : 0 } : { scaleY: vertical ? 0 : 1, scaleX: vertical ? 1 : 0 }, opacity: 0 }), k(delay, { ...value ? { value: 0, y: vertical ? height : 0 } : { scaleY: vertical ? 0 : 1, scaleX: vertical ? 1 : 0 } }), k(enter, { ...value ? { value: v } : {}, easing: spring }), k(0.96, { ...value ? { value: v } : {} })];
|
|
2438
|
+
if (vertical) {
|
|
2439
|
+
const x = 0.04 + i * band, bh = 0.65 * ratio;
|
|
2440
|
+
localShape(`\u05E2\u05DE\u05D5\u05D3\u05D4 ${i + 1}`, x, 0.72 - bh, band * 0.66, bh, c, { transformOrigin: "center bottom", keyframes: poses(false) });
|
|
2441
|
+
const numeric = number2(`\u05E2\u05E8\u05DA ${i + 1}`, visual.x + (x - 0.01) * visual.w, visual.y + (0.72 - bh - 0.105) * visual.h, band * 0.75 * visual.w, 0.085 * visual.h, base * 0.03, v);
|
|
2442
|
+
numeric.color = fg;
|
|
2443
|
+
numeric.countFrom = 0;
|
|
2444
|
+
numeric.keyframes = poses(true);
|
|
2445
|
+
localText(`\u05E9\u05DD ${i + 1}`, name, x - 0.02, 0.8, band * 0.8, 0.13, 0.026);
|
|
2446
|
+
} else {
|
|
2447
|
+
localText(`\u05E9\u05DD ${i + 1}`, name, 0, 0.02 + i * band, 0.22, band * 0.72, 0.032);
|
|
2448
|
+
localShape(`\u05E2\u05DE\u05D5\u05D3\u05D4 ${i + 1}`, 0.26, 0.04 + i * band, 0.56 * ratio, band * 0.48, c, { transformOrigin: "left center", keyframes: poses(false) });
|
|
2449
|
+
const numeric = number2(`\u05E2\u05E8\u05DA ${i + 1}`, visual.x + visual.w * 0.84, visual.y + (0.015 + i * band) * visual.h, visual.w * 0.15, visual.h * band * 0.76, base * 0.032, v);
|
|
2450
|
+
numeric.color = fg;
|
|
2451
|
+
numeric.countFrom = 0;
|
|
2452
|
+
numeric.keyframes = poses(true);
|
|
2453
|
+
}
|
|
2454
|
+
});
|
|
2455
|
+
break;
|
|
2456
|
+
}
|
|
2457
|
+
case "line-chart":
|
|
2458
|
+
case "map-route": {
|
|
2459
|
+
const values = spec.values ?? [25, 55, 42, 81, 67, 96], lo = Math.min(...values), hi = Math.max(...values), n = values.length;
|
|
2460
|
+
const points = spec.type === "line-chart" ? values.map((v, i) => [visual.w * (0.08 + i * 0.84 / (n - 1)), visual.h * (0.77 - (v - lo) / Math.max(1, hi - lo) * 0.62)]) : [[visual.w * 0.08, visual.h * 0.75], [visual.w * 0.44, visual.h * 0.18], [visual.w * 0.88, visual.h * 0.55]];
|
|
2461
|
+
for (let i = 0; i < 4; i++) localShape(`\u05E7\u05D5 \u05D2\u05E8\u05E3 ${i + 1}`, 0.05, 0.15 + i * 0.2, 0.9, 2e-3, fg, { opacity: 0.14, keyframes: [k(0), k(1)] });
|
|
2462
|
+
const lengths = points.map((p, i) => i ? Math.hypot(p[0] - points[i - 1][0], p[1] - points[i - 1][1]) : 0);
|
|
2463
|
+
const total = lengths.reduce((sum, v) => sum + v, 0);
|
|
2464
|
+
let covered = 0;
|
|
2465
|
+
const timing = points.map((_, i) => {
|
|
2466
|
+
covered += lengths[i];
|
|
2467
|
+
return total ? covered / total : i / (points.length - 1);
|
|
2468
|
+
});
|
|
2469
|
+
const geometry = points.map((p, i) => `${i ? "L" : "M"} ${p[0]} ${p[1]}`).join(" ");
|
|
2470
|
+
path(spec.type === "line-chart" ? "\u05E7\u05D5 \u05DE\u05D2\u05DE\u05D4" : "\u05DE\u05E1\u05DC\u05D5\u05DC", visual.x, visual.y, visual.w, visual.h, geometry, a, base * 8e-3, { keyframes: [k(0, { reveal: 0 }), k(0.12, { reveal: 0 }), ...points.slice(1).map((_, i) => k(0.12 + timing[i + 1] * 0.58, { reveal: timing[i + 1], easing: "linear" })), k(0.96, { reveal: 1 })] });
|
|
2471
|
+
const p0 = points[0], dot = base * 0.025;
|
|
2472
|
+
shape("\u05E0\u05E7\u05D5\u05D3\u05D4 \u05E0\u05E2\u05D4", visual.x + p0[0] - dot / 2, visual.y + p0[1] - dot / 2, dot, dot, a, { borderRadius: dot, glow: 8, glowColor: a, keyframes: [k(0, { opacity: 0 }), k(0.12), ...points.slice(1).map((p, i) => k(0.12 + timing[i + 1] * 0.58, { x: p[0] - p0[0], y: p[1] - p0[1], easing: "linear" })), k(0.96, { x: points.at(-1)[0] - p0[0], y: points.at(-1)[1] - p0[1] })] });
|
|
2473
|
+
if (spec.type === "map-route") (spec.items ?? ["\u05D9\u05D5\u05E6\u05D0\u05D9\u05DD", "\u05D1\u05D3\u05E8\u05DA", "\u05DE\u05D2\u05D9\u05E2\u05D9\u05DD"]).forEach((item, i, arr) => localText(`\u05EA\u05D7\u05E0\u05EA \u05DE\u05E1\u05DC\u05D5\u05DC ${i + 1}`, item, i * 0.9 / Math.max(1, arr.length), 0.86, 0.9 / arr.length, 0.1, 0.03));
|
|
2474
|
+
break;
|
|
2475
|
+
}
|
|
2476
|
+
case "timeline": {
|
|
2477
|
+
const n = list2.length, vertical = variant === "stacked" || portrait;
|
|
2478
|
+
localShape("\u05E7\u05D5 \u05D6\u05DE\u05DF", vertical ? 0.16 : 0.05, vertical ? 0.04 : 0.39, vertical ? 8e-3 : 0.88, vertical ? 0.83 : 9e-3, secondary, { keyframes: [k(0, { scaleX: vertical ? 1 : 0, scaleY: vertical ? 0 : 1 }), k(0.7)] });
|
|
2479
|
+
list2.forEach((item, i) => {
|
|
2480
|
+
const step = 0.84 / Math.max(1, n - 1), x = vertical ? 0.12 : 0.05 + i * step, y = vertical ? 0.04 + i * step : 0.35, size = Math.min(base * 0.055, visual.w / (n + 2));
|
|
2481
|
+
shape(`\u05EA\u05D7\u05E0\u05D4 ${i + 1}`, visual.x + x * visual.w, visual.y + y * visual.h, size, size, a, { borderRadius: size, keyframes: pulse(4, i * 0.03).map((k2) => ({ ...k2, at: k2.at / 4 * d })) });
|
|
2482
|
+
localText(`\u05E9\u05DD \u05EA\u05D7\u05E0\u05D4 ${i + 1}`, item, vertical ? 0.26 : Math.max(0, x - 0.06), vertical ? y - 0.01 : 0.57, vertical ? 0.7 : Math.min(0.18, 0.92 / n), vertical ? 0.8 / n : 0.18, 0.035);
|
|
2483
|
+
});
|
|
2484
|
+
break;
|
|
2485
|
+
}
|
|
2486
|
+
case "phone": {
|
|
2487
|
+
const pw = Math.min(visual.w * 0.67, visual.h * 0.63), ph = Math.min(visual.h * 0.94, pw * 1.62), px = visual.x + (visual.w - pw) / 2, py = visual.y;
|
|
2488
|
+
const first = scene.layers.length;
|
|
2489
|
+
shape("\u05DE\u05E1\u05D2\u05E8\u05EA \u05D8\u05DC\u05E4\u05D5\u05DF", px, py, pw, ph, fg, { borderRadius: pw * 0.1 });
|
|
2490
|
+
shape("\u05DE\u05E1\u05DA \u05D8\u05DC\u05E4\u05D5\u05DF", px + pw * 0.035, py + ph * 0.025, pw * 0.93, ph * 0.95, bg, { borderRadius: pw * 0.08 });
|
|
2491
|
+
shape("\u05E2\u05D3\u05E9\u05D4", px + pw * 0.35, py + ph * 0.045, pw * 0.3, ph * 0.025, fg, { borderRadius: base * 0.02 });
|
|
2492
|
+
text3("\u05DB\u05D5\u05EA\u05E8\u05EA \u05DE\u05E1\u05DA", spec.product ?? spec.label, px + pw * 0.09, py + ph * 0.15, pw * 0.82, ph * 0.13, pw * 0.11, fg);
|
|
2493
|
+
const rows = spec.rows ?? (spec.items ?? ["\u05D4\u05DB\u05D5\u05DC \u05D1\u05DE\u05E7\u05D5\u05DD \u05D0\u05D7\u05D3", "\u05E4\u05E9\u05D5\u05D8 \u05DC\u05D4\u05EA\u05E7\u05D3\u05DD", "\u05DE\u05D5\u05DB\u05E0\u05D9\u05DD \u05DC\u05D3\u05E8\u05DA"]).map((item) => [item]);
|
|
2494
|
+
rows.forEach((row, i) => {
|
|
2495
|
+
const yy = py + ph * (0.34 + i * 0.42 / rows.length), hh = ph * 0.32 / rows.length;
|
|
2496
|
+
shape(`\u05DB\u05E8\u05D8\u05D9\u05E1 \u05DE\u05E1\u05DA ${i + 1}`, px + pw * 0.08, yy, pw * 0.84, hh, i % 2 ? secondary : a, { borderRadius: pw * 0.025 });
|
|
2497
|
+
text3(`\u05E9\u05D5\u05E8\u05EA \u05DE\u05E1\u05DA ${i + 1}`, row.join(" "), px + pw * 0.12, yy + hh * 0.14, pw * 0.76, hh * 0.7, pw * 0.065, contrastText(i % 2 ? secondary : a, palette.foreground, bg));
|
|
2498
|
+
});
|
|
2499
|
+
text3("\u05E4\u05E2\u05D5\u05DC\u05D4 \u05D1\u05DE\u05E1\u05DA", spec.cta ?? "\u05DC\u05D4\u05DE\u05E9\u05DA", px + pw * 0.1, py + ph * 0.84, pw * 0.8, ph * 0.08, pw * 0.075, accentText);
|
|
2500
|
+
const children = scene.layers.splice(first).map((l) => ({ ...l, x: l.x - px, y: l.y - py, keyframes: [k(0), k(0.96)] }));
|
|
2501
|
+
layer2("group", "\u05D8\u05DC\u05E4\u05D5\u05DF", px, py, pw, ph, { children, perspective: base * 1.5, depth: -0.5, rotation: variant === "stacked" ? -5 : 0, keyframes: [k(0, { y: base * 0.14, rotateY: -25, opacity: 0 }), k(0.27, { easing: spring }), k(0.94, { rotateY: variant === "centered" ? 5 : -3, y: -base * 0.01 })] });
|
|
2502
|
+
break;
|
|
2503
|
+
}
|
|
2504
|
+
case "ui-cursor": {
|
|
2505
|
+
localShape("\u05D7\u05DC\u05D5\u05DF \u05DE\u05DE\u05E9\u05E7", 0.04, 0.05, 0.92, 0.79, secondary, { borderColor: fg, borderWidth: 1 });
|
|
2506
|
+
localShape("\u05E1\u05E8\u05D2\u05DC \u05D7\u05DC\u05D5\u05DF", 0.04, 0.05, 0.92, 0.1, fg);
|
|
2507
|
+
localText("\u05EA\u05D5\u05DB\u05DF \u05DE\u05DE\u05E9\u05E7", spec.label ?? spec.product, 0.12, 0.22, 0.76, 0.18, 0.055, contrastText(secondary, palette.foreground, bg));
|
|
2508
|
+
const button = localShape("\u05DB\u05E4\u05EA\u05D5\u05E8", 0.21, 0.54, 0.58, 0.17, a, { keyframes: [k(0), k(0.52), k(0.58, { scaleX: 0.94, scaleY: 0.94, easing: "ease-out" }), k(0.67, { easing: spring }), k(0.96)] });
|
|
2509
|
+
localText("\u05D8\u05E7\u05E1\u05D8 \u05DB\u05E4\u05EA\u05D5\u05E8", spec.cta ?? "\u05DE\u05EA\u05D7\u05D9\u05DC\u05D9\u05DD", 0.24, 0.57, 0.52, 0.11, 0.04, contrastText(a, palette.foreground, bg));
|
|
2510
|
+
const size = base * 0.06, cx = button.x + button.width * 0.64, cy = button.y + button.height * 0.5;
|
|
2511
|
+
layer2("svg", "\u05E1\u05DE\u05DF", cx, cy, size, size * 1.2, { pathData: `M 2 2 L ${size * 0.73} ${size * 0.58} L ${size * 0.46} ${size * 0.62} L ${size * 0.66} ${size} L ${size * 0.48} ${size * 1.1} L ${size * 0.28} ${size * 0.7} L 2 ${size * 0.92} Z`, color: fg, stroke: bg, strokeWidth: 2, keyframes: [k(0, { x: visual.w * 0.3, y: visual.h * 0.24, opacity: 0 }), k(0.18, { x: visual.w * 0.3, y: visual.h * 0.24 }), k(0.5, { easing: [0.16, 0.85, 0.22, 1] }), k(0.58, { scaleX: 0.86, scaleY: 0.86 }), k(0.67, { easing: spring }), k(0.96)] });
|
|
2512
|
+
shape("\u05D2\u05DC \u05DC\u05D7\u05D9\u05E6\u05D4", cx - size * 0.3, cy - size * 0.3, size, size, a, { borderRadius: size, color: a, opacity: 0.35, keyframes: [k(0, { scaleX: 0, scaleY: 0, opacity: 0 }), k(0.53, { scaleX: 0, scaleY: 0, opacity: 0 }), k(0.58, { scaleX: 0.4, scaleY: 0.4, opacity: 1 }), k(0.78, { scaleX: 2, scaleY: 2, opacity: 0 }), k(0.96, { opacity: 0 })] });
|
|
2513
|
+
break;
|
|
2514
|
+
}
|
|
2515
|
+
case "coins": {
|
|
2516
|
+
const size = Math.min(visual.w * 0.15, visual.h * 0.22);
|
|
2517
|
+
layer2("repeater", "\u05DE\u05D8\u05D1\u05E2\u05D5\u05EA", visual.x + visual.w * 0.12, visual.y + visual.h * 0.12, size, size, { color: secondary, borderColor: a, borderWidth: size * 0.06, borderRadius: size, depth: -0.2, repeater: { count: 7, seed, shape: "ellipse", offsetX: visual.w * 0.09, offsetY: visual.h * 0.035, rotation: 12, delay: d * 0.02, jitterY: visual.h * 0.09, jitterRotation: 22, colors: [a, secondary] }, keyframes: flight(4, 0, 0, -160, 0, -12, 8).map((frame) => ({ ...frame, at: frame.at / 4 * d, x: frame.x * base / 1080, y: frame.y * base / 1080 })) });
|
|
2518
|
+
number2("\u05E1\u05DB\u05D5\u05DD", visual.x, visual.y + visual.h * 0.53, visual.w, visual.h * 0.23, base * 0.12);
|
|
2519
|
+
localText("\u05EA\u05D5\u05D5\u05D9\u05EA", spec.label, 0.05, 0.83, 0.9, 0.12, 0.035);
|
|
2520
|
+
break;
|
|
2521
|
+
}
|
|
2522
|
+
case "confetti": {
|
|
2523
|
+
layer2("repeater", "\u05E7\u05D5\u05E0\u05E4\u05D8\u05D9", visual.x, visual.y + visual.h * 0.1, base * 0.018, base * 0.043, { color: a, repeater: { count: 28, seed, shape: "rect", offsetX: visual.w / 28, offsetY: 0, rotation: 13, delay: d * 8e-3, jitterY: visual.h * 0.5, jitterRotation: 120, colors: [a, secondary, fg] }, depth: 0.5, keyframes: [k(0, { y: visual.h * 0.8, opacity: 0, rotation: -25 }), k(0.3, { easing: spring }), k(0.96, { y: -visual.h * 0.2, rotation: 45, easing: "linear" })] });
|
|
2524
|
+
localShape("\u05D7\u05D5\u05EA\u05DD \u05D7\u05D2\u05D9\u05D2\u05D4", 0.25, 0.13, 0.5, 0.6, a, { borderRadius: base * 0.25, rotation: -6 });
|
|
2525
|
+
localText("\u05D7\u05D5\u05EA\u05DD", spec.emphasis ?? "\u2713", 0.3, 0.25, 0.4, 0.32, 0.16, contrastText(a, palette.foreground, bg), 0, a);
|
|
2526
|
+
break;
|
|
2527
|
+
}
|
|
2528
|
+
case "kinetic": {
|
|
2529
|
+
const words = spec.words ?? [spec.emphasis ?? headline ?? "\u05D1\u05EA\u05E0\u05D5\u05E2\u05D4"];
|
|
2530
|
+
words.forEach((word, i) => {
|
|
2531
|
+
const yy = i * 0.92 / words.length;
|
|
2532
|
+
const l = localText(`\u05DE\u05D9\u05DC\u05D4 ${i + 1}`, word, 0, yy, 1, 0.84 / words.length, 0.12, i % 2 ? accentText : fg, Math.min(0.32, i * (spec.beat ?? 0.5) / d));
|
|
2533
|
+
if (l) {
|
|
2534
|
+
l.splitText = "letter";
|
|
2535
|
+
l.staggerOrder = variant === "centered" ? "center" : variant === "stacked" ? "end" : "start";
|
|
2536
|
+
l.stagger = Math.min(d * 0.016, d * 0.12 / word.length);
|
|
2537
|
+
l.fontWeight = 900;
|
|
2538
|
+
l.textUnitKeyframes = [point(0, base * 0.03, base * 0.06, 0.65, 0.65, -7, 0), { ...point(d * 0.18), easing: spring }];
|
|
2539
|
+
}
|
|
2540
|
+
});
|
|
2541
|
+
break;
|
|
2542
|
+
}
|
|
2543
|
+
case "marquee": {
|
|
2544
|
+
const words = spec.words ?? spec.items ?? [spec.emphasis ?? headline ?? "\u05E7\u05D3\u05D9\u05DE\u05D4"];
|
|
2545
|
+
const value = words.join(" \xB7 "), stripes = variant === "centered" ? 3 : 2, band = spec.cta ? 0.72 : 1;
|
|
2546
|
+
for (let i = 0; i < stripes; i++) {
|
|
2547
|
+
const y = visual.y + visual.h * (0.08 + i * 0.29) * band, c = i % 2 ? secondary : a;
|
|
2548
|
+
shape(`\u05E1\u05E8\u05D8 ${i + 1}`, visual.x - visual.w * 0.06, y, visual.w * 1.12, visual.h * 0.22 * band, c, { rotation: i % 2 ? -4 : 4 });
|
|
2549
|
+
for (let copy = 0; copy < 2; copy++) {
|
|
2550
|
+
const l = text3(`\u05D8\u05E7\u05E1\u05D8 \u05E0\u05E2 ${i + 1}.${copy}`, value, visual.x + copy * visual.w * 0.95, y + visual.h * 0.035 * band, visual.w * 0.95, visual.h * 0.15 * band, base * 0.065, contrastText(c, palette.foreground, bg));
|
|
2551
|
+
if (l) {
|
|
2552
|
+
l.splitText = "none";
|
|
2553
|
+
l.textUnitKeyframes = void 0;
|
|
2554
|
+
l.keyframes = [k(0, { x: i % 2 ? -visual.w * 0.95 : 0 }), k(1, { x: i % 2 ? 0 : -visual.w * 0.95, easing: "linear" })];
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2558
|
+
if (spec.cta) badge("\u05DB\u05E8\u05D8\u05D9\u05E1 \u05E4\u05E2\u05D5\u05DC\u05D4", spec.cta, 0.06, 0.78, 0.88, 0.16, a);
|
|
2559
|
+
break;
|
|
2560
|
+
}
|
|
2561
|
+
case "hook":
|
|
2562
|
+
case "endcard":
|
|
2563
|
+
case "freeze":
|
|
2564
|
+
case "quote":
|
|
2565
|
+
case "logo": {
|
|
2566
|
+
if (spec.type === "quote") {
|
|
2567
|
+
localText("\u05E1\u05D9\u05DE\u05DF \u05E6\u05D9\u05D8\u05D5\u05D8", "\u05F4", 0.01, 0.01, 0.3, 0.4, 0.28, accentText);
|
|
2568
|
+
localShape("\u05E4\u05E1 \u05E6\u05D9\u05D8\u05D5\u05D8", 0.1, 0.61, 0.8, 0.012, a);
|
|
2569
|
+
localText("\u05D9\u05D9\u05D7\u05D5\u05E1", spec.label, 0.03, 0.76, 0.94, 0.14, 0.04);
|
|
2570
|
+
} else if (spec.type === "logo") {
|
|
2571
|
+
localShape("\u05E1\u05DE\u05DC \u05DE\u05D5\u05EA\u05D2", 0.22, 0.02, 0.56, 0.64, a, { borderRadius: base * 0.08, rotation: variant === "stacked" ? -8 : 0 });
|
|
2572
|
+
localShape("\u05DE\u05E8\u05DB\u05D6 \u05E1\u05DE\u05DC", 0.38, 0.17, 0.24, 0.29, bg, { borderRadius: base * 0.035, rotation: 45 });
|
|
2573
|
+
localText("\u05D7\u05EA\u05D9\u05DE\u05D4", spec.label, 0.05, 0.8, 0.9, 0.13, 0.04);
|
|
2574
|
+
} else if (spec.type === "freeze") {
|
|
2575
|
+
localShape("\u05E7\u05D5 \u05D4\u05E7\u05E4\u05D0\u05D4", 0.03, 0.48, 0.94, 0.017, a, { keyframes: [k(0, { scaleX: 0 }), k(0.28, { easing: spring }), k(0.9)] });
|
|
2576
|
+
localText("\u05DE\u05E1\u05E8 \u05D4\u05E7\u05E4\u05D0\u05D4", spec.label ?? spec.emphasis, 0.03, 0.14, 0.94, 0.23, 0.08, accentText);
|
|
2577
|
+
localText("\u05EA\u05D5\u05D5\u05D9\u05EA", spec.cta, 0.05, 0.7, 0.9, 0.15, 0.035);
|
|
2578
|
+
} else {
|
|
2579
|
+
const size = Math.min(visual.w * 0.65, visual.h * 0.7), x = visual.x + (visual.w - size) / 2;
|
|
2580
|
+
shape("\u05D3\u05D9\u05E1\u05E7 \u05EA\u05E0\u05D5\u05E2\u05D4", x, visual.y, size, size, a, { borderRadius: size, perspective: base * 1.8, depth: -0.4, modifiers: [{ type: "float", amplitude: base * 8e-3 * factor, frequency: 0.15, seed }], keyframes: [k(0, { rotateY: -50, rotation: -30, scaleX: 0.3, scaleY: 0.3, opacity: 0 }), k(0.32, { easing: spring }), k(0.95, { rotateY: 15, rotation: 12 })] });
|
|
2581
|
+
shape("\u05DC\u05D9\u05D1\u05EA \u05D3\u05D9\u05E1\u05E7", x + size * 0.27, visual.y + size * 0.27, size * 0.46, size * 0.46, bg, { borderRadius: size });
|
|
2582
|
+
if (spec.type === "endcard") {
|
|
2583
|
+
badge("\u05DB\u05E8\u05D8\u05D9\u05E1 \u05E4\u05E2\u05D5\u05DC\u05D4", spec.cta ?? "\u05DE\u05EA\u05D7\u05D9\u05DC\u05D9\u05DD \u05DB\u05D0\u05DF", 0.06, 0.75, 0.88, 0.19, a);
|
|
2584
|
+
} else localText("\u05D4\u05D3\u05D2\u05E9\u05D4", spec.emphasis ?? spec.label, 0.02, 0.78, 0.96, 0.15, 0.05, accentText);
|
|
2585
|
+
}
|
|
2586
|
+
break;
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
if (spec.camera !== "none") {
|
|
2590
|
+
const key = (at, x = 0, y = 0, zoom = 1, rotation = 0) => ({ at, x, y, zoom, rotation, easing: "linear" });
|
|
2591
|
+
scene.camera = { keyframes: spec.camera === "orbit" ? [key(0, -base * 8e-3, base * 8e-3, 1.025, -0.6 * factor), key(d * 0.5, base * 8e-3, -base * 8e-3, 1.04, 0.4 * factor), key(d, 0, 0, 1.025, -0.2 * factor)] : spec.camera === "drift" ? [key(0, -base * 0.01, 0, 1.035), key(d, base * 0.01, -base * 0.012, 1.035, 0.25 * factor)] : [key(0), key(d, 0, -base * 7e-3, 1 + 0.035 * factor)] };
|
|
2592
|
+
}
|
|
2593
|
+
return scene;
|
|
2594
|
+
}
|
|
2595
|
+
|
|
2596
|
+
// src/core/config-v3.ts
|
|
2597
|
+
var configV3ThemePalettes = {
|
|
2598
|
+
summer_ice: { background: "#e7f8ff", foreground: "#081b37", accent: "#0989d8", secondary: "#ffce42" },
|
|
2599
|
+
bank_red: { background: "#ffffff", foreground: "#172239", accent: "#e30613", secondary: "#ffe8e9" },
|
|
2600
|
+
midnight: { background: "#07152f", foreground: "#ffffff", accent: "#44e0d0", secondary: "#1a3158" },
|
|
2601
|
+
warm: { background: "#fff6eb", foreground: "#29213d", accent: "#f15a43", secondary: "#ffdb8a" },
|
|
2602
|
+
mono: { background: "#101216", foreground: "#ffffff", accent: "#eeeeee", secondary: "#41444c" },
|
|
2603
|
+
flow: { background: "#101e2b", foreground: "#f1f3eb", accent: "#c8f36a", secondary: "#749cff" },
|
|
2604
|
+
pulse: { background: "#111313", foreground: "#f5f4ef", accent: "#d1ff48", secondary: "#b9a4ff" },
|
|
2605
|
+
orbit: { background: "#f8f2e7", foreground: "#173d8f", accent: "#ff806c", secondary: "#f4d86b" }
|
|
2606
|
+
};
|
|
2607
|
+
function configV3ToProject(input) {
|
|
2608
|
+
const config = parseMotionConfigV3(input), [width, height] = config.aspectRatio === "9:16" ? [1080, 1920] : config.aspectRatio === "1:1" ? [1080, 1080] : [1920, 1080];
|
|
2609
|
+
const palette = { ...configV3ThemePalettes[config.theme], ...config.palette };
|
|
2610
|
+
const scenes = config.scenes.map((spec, index) => ({ ...compileConfigV3Scene(spec, palette, width, height, config.seed, index), configV3: { config: structuredClone(config), sceneIndex: index } }));
|
|
2611
|
+
const project = createProject(config.title, { canvas: { width, height, fps: config.fps }, scenes });
|
|
2612
|
+
project.schemaVersion = 3;
|
|
2613
|
+
if (config.beats) project.beats = [...config.beats];
|
|
2614
|
+
if (config.motionBlur) project.renderSettings = { motionBlur: { ...config.motionBlur } };
|
|
2615
|
+
assertProject(project);
|
|
2616
|
+
return project;
|
|
2617
|
+
}
|
|
2618
|
+
function upgradeConfigV2ToV3(input) {
|
|
2619
|
+
const legacy = parseMotionConfigV2(input);
|
|
2620
|
+
const clean = (raw) => {
|
|
2621
|
+
if (typeof raw === "string" && !raw.trim()) return void 0;
|
|
2622
|
+
if (Array.isArray(raw)) {
|
|
2623
|
+
const entries = raw.map(clean).filter((value) => value !== void 0);
|
|
2624
|
+
return entries.length ? entries : void 0;
|
|
2625
|
+
}
|
|
2626
|
+
if (raw && typeof raw === "object") return Object.fromEntries(Object.entries(raw).map(([key, value]) => [key, clean(value)]).filter(([, value]) => value !== void 0));
|
|
2627
|
+
return raw;
|
|
2628
|
+
};
|
|
2629
|
+
return parseMotionConfigV3({ ...clean(legacy), format: "motiondesk-config/v3" });
|
|
2630
|
+
}
|
|
2631
|
+
function rebuildConfigV3Scene(project, sceneId, patch) {
|
|
2632
|
+
assertProject(project);
|
|
2633
|
+
if (!patch || typeof patch !== "object" || Array.isArray(patch) || Object.keys(patch).some((key) => !["variant", "energy"].includes(key))) throw new Error("\u05E2\u05D3\u05DB\u05D5\u05DF \u05E4\u05E8\u05D9\u05E1\u05D4 \u05DC\u05D0 \u05EA\u05E7\u05D9\u05DF");
|
|
2634
|
+
const position = project.scenes.findIndex((s) => s.id === sceneId);
|
|
2635
|
+
if (position < 0) throw new Error("\u05D4\u05E1\u05E6\u05E0\u05D4 \u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D4");
|
|
2636
|
+
const scene = project.scenes[position], recipe = scene.configV3;
|
|
2637
|
+
if (!recipe) throw new Error("\u05DC\u05E1\u05E6\u05E0\u05D4 \u05D0\u05D9\u05DF \u05DE\u05EA\u05DB\u05D5\u05DF v3");
|
|
2638
|
+
const config = structuredClone(recipe.config), spec = config.scenes[recipe.sceneIndex];
|
|
2639
|
+
Object.assign(spec, patch);
|
|
2640
|
+
const normalized = parseMotionConfigV3(config), palette = { ...configV3ThemePalettes[normalized.theme], ...normalized.palette };
|
|
2641
|
+
if (/^#[a-fA-F0-9]{6}$/.test(scene.background)) palette.background = scene.background;
|
|
2642
|
+
const generated = compileConfigV3Scene({ ...normalized.scenes[recipe.sceneIndex], duration: scene.duration }, palette, project.canvas.width, project.canvas.height, normalized.seed, recipe.sceneIndex);
|
|
2643
|
+
const rebuilt = { ...generated, id: scene.id, name: scene.name, duration: scene.duration, background: scene.background, transition: scene.transition, transitionDuration: scene.transitionDuration, transitionEasing: scene.transitionEasing, configV3: { config: normalized, sceneIndex: recipe.sceneIndex } };
|
|
2644
|
+
const scenes = [...project.scenes];
|
|
2645
|
+
scenes[position] = rebuilt;
|
|
2646
|
+
const result = { ...project, schemaVersion: 3, scenes };
|
|
2647
|
+
assertProject(result);
|
|
2648
|
+
return result;
|
|
2649
|
+
}
|
|
2650
|
+
|
|
2651
|
+
// src/core/visualMotion.ts
|
|
2652
|
+
var RED = "#E3063B";
|
|
2653
|
+
var DEEP_RED = "#A90037";
|
|
2654
|
+
var NAVY = "#10192A";
|
|
2655
|
+
var WHITE = "#FFFFFF";
|
|
2656
|
+
var PALE = "#FFF1F4";
|
|
2657
|
+
function layer(ctx, type, name, x, y, width, height, color, opts = {}) {
|
|
2658
|
+
const result = createLayer(type, {
|
|
2659
|
+
name,
|
|
2660
|
+
x,
|
|
2661
|
+
y,
|
|
2662
|
+
width,
|
|
2663
|
+
height,
|
|
2664
|
+
color,
|
|
2665
|
+
text: opts.text,
|
|
2666
|
+
fontSize: opts.size ?? 48,
|
|
2667
|
+
fontWeight: opts.weight ?? 700,
|
|
2668
|
+
fontFamily: "Arial",
|
|
2669
|
+
textAlign: opts.align ?? "center",
|
|
2670
|
+
borderRadius: opts.radius ?? 0,
|
|
2671
|
+
rotation: opts.rotation ?? 0,
|
|
2672
|
+
opacity: opts.opacity ?? 1,
|
|
2673
|
+
motion: "none",
|
|
2674
|
+
start: 0,
|
|
2675
|
+
duration: ctx.scene.duration,
|
|
2676
|
+
keyframes: opts.keys ?? flight(ctx.scene.duration, 0)
|
|
2677
|
+
});
|
|
2678
|
+
ctx.scene.layers.push(result);
|
|
2679
|
+
return result;
|
|
2680
|
+
}
|
|
2681
|
+
function box(ctx, name, x, y, width, height, color = ctx.accent, radius = 0, delay = 0, fromX = -140, travelX = 14, opacity = 1, rotation = 0) {
|
|
2682
|
+
return layer(ctx, "shape", name, ctx.ox + x, ctx.oy + y, width, height, color, {
|
|
2683
|
+
radius,
|
|
2684
|
+
opacity,
|
|
2685
|
+
rotation,
|
|
2686
|
+
keys: flight(ctx.scene.duration, delay, fromX, 0, travelX, -6, rotation * 0.08)
|
|
2687
|
+
});
|
|
2688
|
+
}
|
|
2689
|
+
function caption(ctx, name, text3, x, y, width, height, size = 38, color = ctx.ink, delay = 0.25) {
|
|
2690
|
+
return layer(ctx, "text", name, ctx.ox + x, ctx.oy + y, width, height, color, {
|
|
2691
|
+
text: text3,
|
|
2692
|
+
size,
|
|
2693
|
+
weight: 800,
|
|
2694
|
+
align: "center",
|
|
2695
|
+
keys: flight(ctx.scene.duration, delay, 0, 80, 0, -12)
|
|
2696
|
+
});
|
|
2697
|
+
}
|
|
2698
|
+
function motif(ctx) {
|
|
2699
|
+
const a = ctx.accent, ink = ctx.ink, surface = ctx.surface;
|
|
2700
|
+
const sq = (name, x, y, d, color = a, delay = 0) => box(ctx, name, x, y, d, d, color, d * 0.18, delay);
|
|
2701
|
+
const circle = (name, x, y, d, color = a, delay = 0) => box(ctx, name, x, y, d, d, color, d / 2, delay);
|
|
2702
|
+
const bar = (name, x, y, w, h = 18, color = a, delay = 0) => box(ctx, name, x, y, w, h, color, h / 2, delay);
|
|
2703
|
+
switch (ctx.theme) {
|
|
2704
|
+
case "car-road":
|
|
2705
|
+
box(ctx, "\u05DB\u05D1\u05D9\u05E9", 30, 590, 690, 32, ink, 16, 0, -460, 70);
|
|
2706
|
+
for (let i = 0; i < 4; i++) bar(`\u05E1\u05D9\u05DE\u05D5\u05DF \u05DB\u05D1\u05D9\u05E9 ${i + 1}`, 80 + i * 170, 600, 78, 8, surface, 0.2 + i * 0.13);
|
|
2707
|
+
box(ctx, "\u05E6\u05DC \u05E8\u05DB\u05D1", 136, 550, 502, 28, NAVY, 14, 0.2, -430, 50, 0.3);
|
|
2708
|
+
for (let i = 0; i < 3; i++) bar(`\u05E9\u05D5\u05D1\u05DC \u05DE\u05D4\u05D9\u05E8\u05D5\u05EA ${i + 1}`, 40 - i * 18, 432 + i * 44, 110 + i * 35, 7, surface, 0.35 + i * 0.12);
|
|
2709
|
+
box(ctx, "\u05DE\u05E8\u05DB\u05D1 \u05E8\u05DB\u05D1", 110, 390, 520, 170, a, 74, 0.2, -430, 50);
|
|
2710
|
+
box(ctx, "\u05D2\u05D2 \u05E8\u05DB\u05D1", 245, 315, 250, 125, a, 78, 0.3, -430, 50);
|
|
2711
|
+
box(ctx, "\u05D7\u05DC\u05D5\u05DF \u05E7\u05D3\u05DE\u05D9", 370, 327, 95, 68, surface, 16, 0.52, -430, 50);
|
|
2712
|
+
box(ctx, "\u05D7\u05DC\u05D5\u05DF \u05D0\u05D7\u05D5\u05E8\u05D9", 270, 327, 90, 68, surface, 16, 0.47, -430, 50);
|
|
2713
|
+
box(ctx, "\u05E4\u05E0\u05E1 \u05E7\u05D3\u05DE\u05D9", 602, 427, 28, 49, "#FFE1A8", 13, 0.48, -430, 50);
|
|
2714
|
+
box(ctx, "\u05E4\u05E0\u05E1 \u05D0\u05D7\u05D5\u05E8\u05D9", 106, 429, 23, 46, "#FF7A98", 11, 0.48, -430, 50);
|
|
2715
|
+
for (const [i, x] of [185, 505].entries()) {
|
|
2716
|
+
circle(`\u05D2\u05DC\u05D2\u05DC ${i + 1}`, x, 500, 98, NAVY, 0.43 + i * 0.08);
|
|
2717
|
+
circle(`\u05DE\u05E8\u05DB\u05D6 \u05D2\u05DC\u05D2\u05DC ${i + 1}`, x + 27, 527, 44, WHITE, 0.55 + i * 0.08);
|
|
2718
|
+
box(ctx, `\u05D7\u05D9\u05E9\u05D5\u05E8 \u05D0\u05E0\u05DB\u05D9 ${i + 1}`, x + 43, 530, 12, 38, NAVY, 6, 0.58 + i * 0.08, -430, 50);
|
|
2719
|
+
box(ctx, `\u05D7\u05D9\u05E9\u05D5\u05E8 \u05D0\u05D5\u05E4\u05E7\u05D9 ${i + 1}`, x + 30, 543, 38, 12, NAVY, 6, 0.58 + i * 0.08, -430, 50);
|
|
2720
|
+
}
|
|
2721
|
+
break;
|
|
2722
|
+
case "holiday-table":
|
|
2723
|
+
circle("\u05E6\u05DC\u05D7\u05EA \u05D7\u05D9\u05E6\u05D5\u05E0\u05D9\u05EA", 140, 170, 490, surface, 0.1);
|
|
2724
|
+
circle("\u05E6\u05DC\u05D7\u05EA \u05E4\u05E0\u05D9\u05DE\u05D9\u05EA", 205, 235, 360, a, 0.25);
|
|
2725
|
+
circle("\u05DE\u05E8\u05DB\u05D6 \u05E9\u05D5\u05DC\u05D7\u05DF", 270, 300, 230, surface, 0.42);
|
|
2726
|
+
for (let i = 0; i < 4; i++) {
|
|
2727
|
+
const x = 60 + i % 2 * 550, y = 100 + Math.floor(i / 2) * 390;
|
|
2728
|
+
box(ctx, `\u05DE\u05E2\u05D8\u05E4\u05EA \u05EA\u05E7\u05E6\u05D9\u05D1 ${i + 1}`, x, y, 110, 128, i % 2 ? ink : a, 18, 0.35 + i * 0.18, i % 2 ? 160 : -160);
|
|
2729
|
+
}
|
|
2730
|
+
caption(ctx, "\u05E1\u05DB\u05D5\u05DD \u05DC\u05EA\u05DB\u05E0\u05D5\u05DF", "\u20AA", 336, 338, 100, 100, 96, ink, 0.68);
|
|
2731
|
+
break;
|
|
2732
|
+
case "one-click":
|
|
2733
|
+
circle("\u05D2\u05DC \u05D4\u05D3\u05E3 \u05D7\u05D9\u05E6\u05D5\u05E0\u05D9", 70, 70, 630, a, 0.1);
|
|
2734
|
+
circle("\u05D2\u05DC \u05D4\u05D3\u05E3 \u05E4\u05E0\u05D9\u05DE\u05D9", 130, 130, 510, surface, 0.28);
|
|
2735
|
+
circle("\u05DB\u05E4\u05EA\u05D5\u05E8 \u05E8\u05D0\u05E9\u05D9", 245, 245, 280, a, 0.42);
|
|
2736
|
+
box(ctx, "\u05D5\u05D9 \u05E7\u05E6\u05E8 \u05D1\u05DB\u05E4\u05EA\u05D5\u05E8 \u05D4\u05E8\u05D0\u05E9\u05D9", 317, 368, 57, 17, WHITE, 8, 0.64, -140, 14, 1, 43);
|
|
2737
|
+
box(ctx, "\u05D5\u05D9 \u05D0\u05E8\u05D5\u05DA \u05D1\u05DB\u05E4\u05EA\u05D5\u05E8 \u05D4\u05E8\u05D0\u05E9\u05D9", 357, 340, 111, 17, WHITE, 8, 0.7, -140, 14, 1, -43);
|
|
2738
|
+
for (let i = 0; i < 3; i++) box(ctx, `\u05E9\u05DC\u05D1 ${i + 1}`, 60 + i * 238, 645, 170, 16, i === 2 ? ink : a, 8, 0.55 + i * 0.2);
|
|
2739
|
+
break;
|
|
2740
|
+
case "book-steps":
|
|
2741
|
+
for (let i = 0; i < 4; i++) {
|
|
2742
|
+
box(ctx, `\u05E1\u05E4\u05E8 \u05DE\u05D3\u05E8\u05D2\u05D4 ${i + 1}`, 60 + i * 152, 525 - i * 105, 175, 115, i % 2 ? ink : a, 12, 0.18 + i * 0.18, -220, 8);
|
|
2743
|
+
bar(`\u05DB\u05E8\u05D9\u05DB\u05EA \u05E1\u05E4\u05E8 ${i + 1}`, 68 + i * 152, 548 - i * 105, 150, 9, surface, 0.34 + i * 0.18);
|
|
2744
|
+
}
|
|
2745
|
+
box(ctx, "\u05EA\u05E2\u05D5\u05D3\u05D4", 580, 80, 150, 190, surface, 10, 0.95);
|
|
2746
|
+
circle("\u05D7\u05D5\u05EA\u05DD \u05EA\u05E2\u05D5\u05D3\u05D4", 625, 150, 60, a, 1.12);
|
|
2747
|
+
box(ctx, "\u05E4\u05E1 \u05EA\u05E2\u05D5\u05D3\u05D4 \u05E2\u05DC\u05D9\u05D5\u05DF", 598, 110, 115, 9, a, 4, 1.06);
|
|
2748
|
+
box(ctx, "\u05E4\u05E1 \u05EA\u05E2\u05D5\u05D3\u05D4 \u05EA\u05D7\u05EA\u05D5\u05DF", 598, 235, 115, 9, a, 4, 1.23);
|
|
2749
|
+
break;
|
|
2750
|
+
case "room-build":
|
|
2751
|
+
bar("\u05E8\u05E6\u05E4\u05EA \u05D7\u05D3\u05E8", 40, 650, 690, 24, ink, 0.08);
|
|
2752
|
+
bar("\u05E7\u05D9\u05E8 \u05E9\u05DE\u05D0\u05DC", 70, 115, 24, 555, a, 0.18);
|
|
2753
|
+
bar("\u05E7\u05D9\u05E8 \u05D9\u05DE\u05D9\u05DF", 690, 115, 24, 555, a, 0.22);
|
|
2754
|
+
box(ctx, "\u05D7\u05DC\u05D5\u05DF", 435, 205, 200, 230, surface, 12, 0.38);
|
|
2755
|
+
bar("\u05D7\u05DC\u05D5\u05E7\u05EA \u05D7\u05DC\u05D5\u05DF", 525, 205, 12, 230, a, 0.52);
|
|
2756
|
+
box(ctx, "\u05E1\u05E4\u05D4", 175, 490, 350, 145, a, 45, 0.58);
|
|
2757
|
+
for (const [i, x] of [220, 435].entries()) box(ctx, `\u05E8\u05D2\u05DC \u05E1\u05E4\u05D4 ${i + 1}`, x, 610, 35, 55, ink, 6, 0.7);
|
|
2758
|
+
break;
|
|
2759
|
+
case "summer-case":
|
|
2760
|
+
circle("\u05E9\u05DE\u05E9", 510, 90, 190, a, 0.12);
|
|
2761
|
+
for (let i = 0; i < 6; i++) {
|
|
2762
|
+
const angle = i * Math.PI / 3;
|
|
2763
|
+
bar(`\u05E7\u05E8\u05DF \u05E9\u05DE\u05E9 ${i + 1}`, 605 + Math.cos(angle) * 132, 185 + Math.sin(angle) * 132, 64, 12, a, 0.2 + i * 0.06);
|
|
2764
|
+
}
|
|
2765
|
+
box(ctx, "\u05DE\u05D6\u05D5\u05D5\u05D3\u05D4", 145, 325, 450, 320, ink, 35, 0.4);
|
|
2766
|
+
box(ctx, "\u05D9\u05D3\u05D9\u05EA \u05DE\u05D6\u05D5\u05D5\u05D3\u05D4", 300, 260, 145, 90, a, 42, 0.3);
|
|
2767
|
+
bar("\u05E4\u05E1 \u05DE\u05D6\u05D5\u05D5\u05D3\u05D4", 340, 335, 50, 300, surface, 0.6);
|
|
2768
|
+
for (const [i, x] of [220, 510].entries()) circle(`\u05D2\u05DC\u05D2\u05DC \u05DE\u05D6\u05D5\u05D5\u05D3\u05D4 ${i + 1}`, x, 620, 52, a, 0.7);
|
|
2769
|
+
break;
|
|
2770
|
+
case "car-garage":
|
|
2771
|
+
box(ctx, "\u05DE\u05E1\u05D2\u05E8\u05EA \u05DE\u05D5\u05E1\u05DA", 70, 105, 650, 560, ink, 18, 0.1);
|
|
2772
|
+
box(ctx, "\u05E4\u05EA\u05D7 \u05DE\u05D5\u05E1\u05DA", 115, 155, 560, 460, surface, 12, 0.25);
|
|
2773
|
+
for (let i = 0; i < 4; i++) bar(`\u05D7\u05E8\u05D9\u05E5 \u05EA\u05E8\u05D9\u05E1 ${i + 1}`, 130, 175 + i * 52, 530, 12, a, 0.28 + i * 0.08);
|
|
2774
|
+
box(ctx, "\u05E8\u05DB\u05D1 \u05D7\u05D3\u05E9", 180, 440, 440, 125, a, 62, 0.76, -450, 60);
|
|
2775
|
+
for (const [i, x] of [248, 510].entries()) circle(`\u05D2\u05DC\u05D2\u05DC \u05D7\u05D3\u05E9 ${i + 1}`, x, 535, 78, NAVY, 0.86);
|
|
2776
|
+
break;
|
|
2777
|
+
case "wedding-rings":
|
|
2778
|
+
circle("\u05D8\u05D1\u05E2\u05EA \u05E8\u05D0\u05E9\u05D5\u05E0\u05D4", 112, 220, 370, a, 0.12);
|
|
2779
|
+
circle("\u05D7\u05DC\u05DC \u05D8\u05D1\u05E2\u05EA \u05E8\u05D0\u05E9\u05D5\u05E0\u05D4", 176, 284, 242, surface, 0.18);
|
|
2780
|
+
circle("\u05D8\u05D1\u05E2\u05EA \u05E9\u05E0\u05D9\u05D9\u05D4", 330, 220, 370, ink, 0.42);
|
|
2781
|
+
circle("\u05D7\u05DC\u05DC \u05D8\u05D1\u05E2\u05EA \u05E9\u05E0\u05D9\u05D9\u05D4", 394, 284, 242, surface, 0.48);
|
|
2782
|
+
circle("\u05D7\u05D5\u05EA\u05DD \u05D4\u05D6\u05DE\u05E0\u05D4", 363, 553, 85, a, 0.82);
|
|
2783
|
+
circle("\u05DE\u05E8\u05DB\u05D6 \u05D7\u05D5\u05EA\u05DD \u05D4\u05D6\u05DE\u05E0\u05D4", 383, 573, 45, surface, 0.91);
|
|
2784
|
+
for (let i = 0; i < 5; i++) circle(`\u05E0\u05E7\u05D5\u05D3\u05EA \u05D0\u05D5\u05E8 ${i + 1}`, 125 + i * 130, 115 + i % 2 * 490, 25, a, 0.2 + i * 0.14);
|
|
2785
|
+
break;
|
|
2786
|
+
case "share-mosaic":
|
|
2787
|
+
for (let row = 0; row < 4; row++) for (let col = 0; col < 5; col++) {
|
|
2788
|
+
box(
|
|
2789
|
+
ctx,
|
|
2790
|
+
`\u05D0\u05E8\u05D9\u05D7 \u05D1\u05E2\u05DC\u05D5\u05EA ${row * 5 + col + 1}`,
|
|
2791
|
+
70 + col * 128,
|
|
2792
|
+
130 + row * 128,
|
|
2793
|
+
102,
|
|
2794
|
+
102,
|
|
2795
|
+
row === 1 && col === 3 ? a : row % 2 ? ink : surface,
|
|
2796
|
+
10,
|
|
2797
|
+
0.12 + (row + col) * 0.085,
|
|
2798
|
+
col % 2 ? 120 : -120,
|
|
2799
|
+
3
|
|
2800
|
+
);
|
|
2801
|
+
}
|
|
2802
|
+
break;
|
|
2803
|
+
case "fraud-alert":
|
|
2804
|
+
box(ctx, "\u05D8\u05DC\u05E4\u05D5\u05DF \u05D0\u05D6\u05D4\u05E8\u05D4", 205, 55, 370, 650, NAVY, 42, 0.08);
|
|
2805
|
+
box(ctx, "\u05DE\u05E1\u05DA \u05D8\u05DC\u05E4\u05D5\u05DF", 229, 83, 322, 590, surface, 28, 0.18);
|
|
2806
|
+
for (let i = 0; i < 3; i++) box(ctx, `\u05D4\u05D5\u05D3\u05E2\u05D4 \u05D7\u05E9\u05D5\u05D3\u05D4 ${i + 1}`, 258, 175 + i * 130, 264, 95, i === 1 ? a : PALE, 18, 0.3 + i * 0.28, i % 2 ? 140 : -140);
|
|
2807
|
+
caption(ctx, "\u05E1\u05D9\u05DE\u05DF \u05D0\u05D6\u05D4\u05E8\u05D4", "!", 340, 516, 100, 100, 104, a, 1.1);
|
|
2808
|
+
break;
|
|
2809
|
+
case "student-desk":
|
|
2810
|
+
box(ctx, "\u05E9\u05D5\u05DC\u05D7\u05DF \u05DC\u05D9\u05DE\u05D5\u05D3", 55, 585, 660, 45, ink, 12, 0.1);
|
|
2811
|
+
box(ctx, "\u05DE\u05D7\u05D1\u05E8\u05EA \u05E9\u05DE\u05D0\u05DC", 145, 215, 255, 360, surface, 16, 0.24, -230, 6);
|
|
2812
|
+
box(ctx, "\u05DE\u05D7\u05D1\u05E8\u05EA \u05D9\u05DE\u05D9\u05DF", 396, 215, 255, 360, a, 16, 0.3, 230, -6);
|
|
2813
|
+
for (let i = 0; i < 4; i++) bar(`\u05E9\u05D5\u05E8\u05EA \u05DE\u05E9\u05D9\u05DE\u05D4 ${i + 1}`, 195, 287 + i * 57, 178, 10, ink, 0.5 + i * 0.12);
|
|
2814
|
+
circle("\u05E9\u05E2\u05D5\u05DF \u05DC\u05D9\u05DE\u05D5\u05D3", 550, 68, 146, ink, 0.5);
|
|
2815
|
+
caption(ctx, "\u05DE\u05D7\u05D5\u05D2 \u05E9\u05E2\u05D5\u05DF", "\u2197", 583, 91, 80, 80, 70, surface, 0.72);
|
|
2816
|
+
break;
|
|
2817
|
+
case "learning-domino":
|
|
2818
|
+
for (let i = 0; i < 5; i++) box(ctx, `\u05D0\u05D1\u05DF \u05DC\u05DE\u05D9\u05D3\u05D4 ${i + 1}`, 90 + i * 127, 305 + i * 30, 96, 260, i === 4 ? a : ink, 12, 0.1 + i * 0.18, -180, 14, 1, i * 8);
|
|
2819
|
+
bar("\u05DE\u05E1\u05DC\u05D5\u05DC \u05DC\u05DE\u05D9\u05D3\u05D4", 48, 618, 680, 26, a, 0.42);
|
|
2820
|
+
caption(ctx, "\u05E6\u05E2\u05D3 \u05E8\u05D0\u05E9\u05D5\u05DF", "01", 580, 80, 130, 110, 84, a, 0.96);
|
|
2821
|
+
break;
|
|
2822
|
+
case "fomo-storm":
|
|
2823
|
+
for (let i = 0; i < 7; i++) {
|
|
2824
|
+
const left = 62 + i % 3 * 220, top = 70 + i * 82;
|
|
2825
|
+
box(ctx, `\u05D4\u05EA\u05E8\u05D0\u05EA \u05DC\u05D7\u05E5 ${i + 1}`, left, top, 220, 74, i % 2 ? ink : a, 14, i * 0.11, i % 2 ? 450 : -450, i % 2 ? -50 : 50);
|
|
2826
|
+
}
|
|
2827
|
+
box(ctx, "\u05DE\u05E1\u05D2\u05E8\u05EA \u05E2\u05E6\u05D9\u05E8\u05D4", 175, 220, 410, 260, surface, 28, 0.72);
|
|
2828
|
+
caption(ctx, "\u05DE\u05D9\u05DC\u05EA \u05E2\u05E6\u05D9\u05E8\u05D4", "\u05E2\u05D5\u05E6\u05E8\u05D9\u05DD", 208, 290, 345, 110, 86, a, 0.96);
|
|
2829
|
+
break;
|
|
2830
|
+
case "market-clock":
|
|
2831
|
+
circle("\u05DC\u05D5\u05D7 \u05E9\u05E2\u05D5\u05DF", 100, 105, 560, surface, 0.1);
|
|
2832
|
+
circle("\u05E4\u05E0\u05D9\u05DD \u05E9\u05E2\u05D5\u05DF", 145, 150, 470, ink, 0.22);
|
|
2833
|
+
for (let i = 0; i < 12; i++) {
|
|
2834
|
+
const angle = i * Math.PI / 6;
|
|
2835
|
+
circle(`\u05E1\u05D9\u05DE\u05D5\u05DF \u05E9\u05E2\u05D4 ${i + 1}`, 370 + Math.sin(angle) * 195, 375 - Math.cos(angle) * 195, 17, surface, 0.28 + i * 0.025);
|
|
2836
|
+
}
|
|
2837
|
+
bar("\u05DE\u05D7\u05D5\u05D2 \u05D0\u05E8\u05D5\u05DA", 365, 210, 16, 225, a, 0.48);
|
|
2838
|
+
bar("\u05DE\u05D7\u05D5\u05D2 \u05E7\u05E6\u05E8", 372, 370, 145, 16, a, 0.55);
|
|
2839
|
+
circle("\u05E6\u05D9\u05E8 \u05E9\u05E2\u05D5\u05DF", 355, 360, 38, a, 0.62);
|
|
2840
|
+
break;
|
|
2841
|
+
case "small-bricks":
|
|
2842
|
+
for (let row = 0; row < 5; row++) for (let col = 0; col < 4; col++) {
|
|
2843
|
+
box(
|
|
2844
|
+
ctx,
|
|
2845
|
+
`\u05DC\u05D1\u05E0\u05D4 ${row * 4 + col + 1}`,
|
|
2846
|
+
95 + col * 140 + row % 2 * 58,
|
|
2847
|
+
555 - row * 95,
|
|
2848
|
+
130,
|
|
2849
|
+
72,
|
|
2850
|
+
(row + col) % 3 === 0 ? a : ink,
|
|
2851
|
+
10,
|
|
2852
|
+
0.1 + (row * 4 + col) * 0.065,
|
|
2853
|
+
0,
|
|
2854
|
+
4
|
|
2855
|
+
);
|
|
2856
|
+
}
|
|
2857
|
+
break;
|
|
2858
|
+
case "two-paths":
|
|
2859
|
+
bar("\u05E6\u05D5\u05DE\u05EA", 344, 35, 30, 600, ink, 0.12);
|
|
2860
|
+
for (const [i, side] of [-1, 1].entries()) {
|
|
2861
|
+
box(ctx, `\u05DE\u05E1\u05DC\u05D5\u05DC ${i + 1}`, side < 0 ? 72 : 390, 220, 270, 335, i ? a : ink, 25, 0.3 + i * 0.14, side * 320);
|
|
2862
|
+
caption(ctx, `\u05E1\u05DE\u05DC \u05DE\u05E1\u05DC\u05D5\u05DC ${i + 1}`, i ? "\u2302" : "\u2197", side < 0 ? 145 : 464, 310, 125, 125, 106, surface, 0.6 + i * 0.12);
|
|
2863
|
+
}
|
|
2864
|
+
circle("\u05E0\u05E7\u05D5\u05D3\u05EA \u05D4\u05D7\u05DC\u05D8\u05D4", 315, 575, 88, a, 0.9);
|
|
2865
|
+
break;
|
|
2866
|
+
case "small-store":
|
|
2867
|
+
box(ctx, "\u05D7\u05D6\u05D9\u05EA \u05D7\u05E0\u05D5\u05EA", 115, 235, 535, 400, surface, 14, 0.15);
|
|
2868
|
+
for (let i = 0; i < 5; i++) box(ctx, `\u05E4\u05E1 \u05E1\u05D5\u05DB\u05DA ${i + 1}`, 115 + i * 107, 182, 105, 105, i % 2 ? a : ink, 4, 0.23 + i * 0.1);
|
|
2869
|
+
box(ctx, "\u05D3\u05DC\u05EA \u05D7\u05E0\u05D5\u05EA", 185, 365, 170, 270, ink, 8, 0.55);
|
|
2870
|
+
box(ctx, "\u05D7\u05DC\u05D5\u05DF \u05E8\u05D0\u05D5\u05D5\u05D4", 390, 345, 205, 165, a, 8, 0.65);
|
|
2871
|
+
for (let i = 0; i < 3; i++) sq(`\u05DE\u05D5\u05E6\u05E8 ${i + 1}`, 418 + i * 53, 440, 37, surface, 0.78 + i * 0.08);
|
|
2872
|
+
break;
|
|
2873
|
+
case "travel-conveyor":
|
|
2874
|
+
box(ctx, "\u05DE\u05E1\u05D5\u05E2 \u05E9\u05D3\u05D4 \u05EA\u05E2\u05D5\u05E4\u05D4", 24, 570, 710, 58, ink, 29, 0.1, -500, 95);
|
|
2875
|
+
for (let i = 0; i < 6; i++) circle(`\u05D2\u05DC\u05D2\u05DC \u05DE\u05E1\u05D5\u05E2 ${i + 1}`, 54 + i * 115, 620, 45, a, 0.24 + i * 0.06);
|
|
2876
|
+
box(ctx, "\u05DE\u05D6\u05D5\u05D5\u05D3\u05EA \u05E0\u05E1\u05D9\u05E2\u05D4", 185, 260, 345, 315, a, 30, 0.42, -390, 90);
|
|
2877
|
+
box(ctx, "\u05D9\u05D3\u05D9\u05EA \u05DE\u05D6\u05D5\u05D5\u05D3\u05D4", 300, 205, 110, 75, ink, 32, 0.35);
|
|
2878
|
+
caption(ctx, "\u05E1\u05DE\u05DC \u05D8\u05D9\u05E1\u05D4", "\u2708", 520, 105, 170, 140, 120, ink, 0.74);
|
|
2879
|
+
break;
|
|
2880
|
+
case "mortgage-blueprint":
|
|
2881
|
+
box(ctx, "\u05D3\u05E3 \u05EA\u05DB\u05E0\u05D9\u05EA", 72, 85, 650, 570, surface, 12, 0.08);
|
|
2882
|
+
bar("\u05E7\u05D5 \u05E8\u05E6\u05E4\u05D4", 166, 520, 460, 12, a, 0.3);
|
|
2883
|
+
bar("\u05E7\u05D9\u05E8 \u05E9\u05DE\u05D0\u05DC", 176, 300, 13, 235, a, 0.42);
|
|
2884
|
+
bar("\u05E7\u05D9\u05E8 \u05D9\u05DE\u05D9\u05DF", 612, 300, 13, 235, a, 0.48);
|
|
2885
|
+
box(ctx, "\u05D2\u05D2 \u05E9\u05DE\u05D0\u05DC", 176, 240, 258, 15, a, 6, 0.54, -200, 4, 1, -27);
|
|
2886
|
+
box(ctx, "\u05D2\u05D2 \u05D9\u05DE\u05D9\u05DF", 397, 240, 258, 15, a, 6, 0.6, 200, -4, 1, 27);
|
|
2887
|
+
box(ctx, "\u05D3\u05DC\u05EA \u05D1\u05EA\u05DB\u05E0\u05D9\u05EA", 328, 393, 112, 132, ink, 6, 0.72);
|
|
2888
|
+
for (let i = 0; i < 3; i++) bar(`\u05DE\u05D9\u05D3\u05D4 ${i + 1}`, 155, 585 + i * 18, 350 - i * 55, 5, ink, 0.82 + i * 0.08);
|
|
2889
|
+
break;
|
|
2890
|
+
case "market-phone":
|
|
2891
|
+
box(ctx, "\u05DE\u05E1\u05D2\u05E8\u05EA \u05D0\u05E4\u05DC\u05D9\u05E7\u05E6\u05D9\u05D4", 175, 50, 425, 665, NAVY, 45, 0.1);
|
|
2892
|
+
box(ctx, "\u05DE\u05E1\u05DA \u05E9\u05D5\u05E7", 203, 82, 369, 595, surface, 27, 0.2);
|
|
2893
|
+
for (let i = 0; i < 5; i++) box(ctx, `\u05E2\u05DE\u05D5\u05D3\u05EA \u05E0\u05EA\u05D5\u05DF ${i + 1}`, 247 + i * 58, 515 - i * 42, 36, 93 + i * 42, i % 2 ? ink : a, 7, 0.4 + i * 0.14, 0, 6);
|
|
2894
|
+
bar("\u05E7\u05D5 \u05DB\u05D5\u05EA\u05E8\u05EA \u05D1\u05D0\u05E4\u05DC\u05D9\u05E7\u05E6\u05D9\u05D4", 244, 171, 275, 18, ink, 0.48);
|
|
2895
|
+
bar("\u05E7\u05D5 \u05E0\u05EA\u05D5\u05DF \u05D1\u05D0\u05E4\u05DC\u05D9\u05E7\u05E6\u05D9\u05D4", 244, 216, 196, 12, a, 0.59);
|
|
2896
|
+
break;
|
|
2897
|
+
}
|
|
2898
|
+
}
|
|
2899
|
+
var storyFrames = {
|
|
2900
|
+
"car-road": [{ kind: "choices", labels: ["\u05E8\u05DB\u05D1 \u05D7\u05D3\u05E9", "\u05D9\u05D3 \u05E9\u05E0\u05D9\u05D9\u05D4"] }, { kind: "bars", labels: ["\u05DE\u05D7\u05D9\u05E8", "\u05EA\u05D7\u05D6\u05D5\u05E7\u05D4", "\u05DE\u05D9\u05DE\u05D5\u05DF"] }],
|
|
2901
|
+
"holiday-table": [{ kind: "meter", labels: ["\u05DE\u05E1\u05D2\u05E8\u05EA \u05DC\u05D7\u05D2"] }, { kind: "stack", labels: ["\u05E7\u05E0\u05D9\u05D5\u05EA", "\u05D0\u05D9\u05E8\u05D5\u05D7", "\u05E0\u05E1\u05D9\u05E2\u05D5\u05EA"] }],
|
|
2902
|
+
"one-click": [{ kind: "phone", labels: ["\u05E4\u05D5\u05EA\u05D7\u05D9\u05DD", "\u05D1\u05D5\u05D7\u05E8\u05D9\u05DD", "\u05DE\u05D0\u05E9\u05E8\u05D9\u05DD"] }, { kind: "steps", labels: ["\u05E4\u05E2\u05D5\u05DC\u05D4", "\u05E4\u05E8\u05D8\u05D9\u05DD", "\u05D0\u05D9\u05E9\u05D5\u05E8"] }, { kind: "check", labels: ["\u05D1\u05D3\u05D9\u05E7\u05D4", "\u05E9\u05DC\u05D9\u05D8\u05D4", "\u05D4\u05EA\u05E7\u05D3\u05DE\u05D5\u05EA"] }],
|
|
2903
|
+
"book-steps": [{ kind: "steps", labels: ["\u05D9\u05E2\u05D3", "\u05DC\u05D9\u05DE\u05D5\u05D3", "\u05D4\u05DB\u05E9\u05E8\u05D4"] }, { kind: "bars", labels: ["\u05D6\u05DE\u05DF", "\u05E2\u05DC\u05D5\u05EA", "\u05E9\u05D2\u05E8\u05D4"] }],
|
|
2904
|
+
"room-build": [{ kind: "choices", labels: ["\u05DE\u05D8\u05D1\u05D7", "\u05D7\u05D3\u05E8 \u05E2\u05D1\u05D5\u05D3\u05D4"] }, { kind: "bars", labels: ["\u05E1\u05DB\u05D5\u05DD", "\u05D6\u05DE\u05DF", "\u05EA\u05D5\u05E6\u05D0\u05D4"] }],
|
|
2905
|
+
"summer-case": [{ kind: "choices", labels: ["\u05E0\u05D5\u05E1\u05E2\u05D9\u05DD", "\u05E0\u05E9\u05D0\u05E8\u05D9\u05DD"] }, { kind: "meter", labels: ["\u05EA\u05E7\u05E6\u05D9\u05D1 \u05DC\u05E7\u05D9\u05E5"] }, { kind: "steps", labels: ["\u05D9\u05E2\u05D3", "\u05EA\u05DB\u05E0\u05D5\u05DF", "\u05E1\u05E4\u05D5\u05E0\u05D8\u05E0\u05D9\u05D5\u05EA"] }],
|
|
2906
|
+
"car-garage": [{ kind: "choices", labels: ["\u05E0\u05D5\u05D7\u05D5\u05EA", "\u05D7\u05D9\u05E1\u05DB\u05D5\u05DF"] }, { kind: "bars", labels: ["\u05E7\u05E0\u05D9\u05D9\u05D4", "\u05EA\u05D7\u05D6\u05D5\u05E7\u05D4", "\u05DE\u05D9\u05DE\u05D5\u05DF"] }],
|
|
2907
|
+
"wedding-rings": [{ kind: "choices", labels: ["\u05DE\u05E7\u05D5\u05DD", "\u05D0\u05E0\u05E9\u05D9\u05DD"] }, { kind: "bars", labels: ["\u05D7\u05D5\u05D5\u05D9\u05D4", "\u05EA\u05E7\u05E6\u05D9\u05D1", "\u05DE\u05E8\u05D5\u05D5\u05D7"] }, { kind: "meter", labels: ["\u05D4\u05D9\u05D5\u05DD \u05E9\u05DC\u05DB\u05DD"] }],
|
|
2908
|
+
"share-mosaic": [{ kind: "steps", labels: ["\u05D7\u05D1\u05E8\u05D4", "\u05D7\u05DC\u05E7", "\u05E1\u05D9\u05DB\u05D5\u05DF"] }, { kind: "check", labels: ["\u05DC\u05D5\u05DE\u05D3\u05D9\u05DD", "\u05D1\u05D5\u05D3\u05E7\u05D9\u05DD", "\u05D1\u05D5\u05D7\u05E8\u05D9\u05DD"] }],
|
|
2909
|
+
"fraud-alert": [{ kind: "warning", labels: ["\u05E7\u05D9\u05E9\u05D5\u05E8", "\u05E1\u05D9\u05E1\u05DE\u05D4", "\u05E7\u05D5\u05D3"] }, { kind: "phone", labels: ["\u05D0\u05E4\u05DC\u05D9\u05E7\u05E6\u05D9\u05D4", "\u05D0\u05EA\u05E8 \u05E8\u05E9\u05DE\u05D9", "\u05D1\u05D3\u05D9\u05E7\u05D4"] }, { kind: "check", labels: ["\u05E2\u05D5\u05E6\u05E8\u05D9\u05DD", "\u05D1\u05D5\u05D3\u05E7\u05D9\u05DD", "\u05DE\u05D2\u05E0\u05D9\u05DD"] }],
|
|
2910
|
+
"student-desk": [{ kind: "stack", labels: ["\u05DC\u05D9\u05DE\u05D5\u05D3\u05D9\u05DD", "\u05E0\u05E1\u05D9\u05E2\u05D5\u05EA", "\u05D9\u05D5\u05DE\u05D9\u05D5\u05DD"] }, { kind: "bars", labels: ["\u05D4\u05DB\u05E0\u05E1\u05D4", "\u05D4\u05D5\u05E6\u05D0\u05D5\u05EA", "\u05D6\u05DE\u05DF"] }],
|
|
2911
|
+
"learning-domino": [{ kind: "steps", labels: ["\u05DE\u05D8\u05E8\u05D4", "\u05D8\u05D5\u05D5\u05D7", "\u05E1\u05D9\u05DB\u05D5\u05DF"] }, { kind: "check", labels: ["\u05D9\u05D3\u05E2", "\u05D0\u05E4\u05E9\u05E8\u05D5\u05D9\u05D5\u05EA", "\u05D4\u05D7\u05DC\u05D8\u05D4"] }],
|
|
2912
|
+
"fomo-storm": [{ kind: "warning", labels: ["\u05DB\u05D5\u05DC\u05DD", "\u05E2\u05DB\u05E9\u05D9\u05D5", "\u05DE\u05D4\u05E8"] }, { kind: "steps", labels: ["\u05E2\u05D5\u05E6\u05E8\u05D9\u05DD", "\u05E9\u05D5\u05D0\u05DC\u05D9\u05DD", "\u05D1\u05D5\u05D3\u05E7\u05D9\u05DD"] }],
|
|
2913
|
+
"market-clock": [{ kind: "meter", labels: ["\u05D0\u05D9\u05DF \u05E8\u05D2\u05E2 \u05DE\u05D5\u05E9\u05DC\u05DD"] }, { kind: "steps", labels: ["\u05DE\u05D8\u05E8\u05D4", "\u05E1\u05D9\u05DB\u05D5\u05DF", "\u05D0\u05D5\u05E4\u05E7"] }],
|
|
2914
|
+
"small-bricks": [{ kind: "steps", labels: ["\u05DC\u05D5\u05DE\u05D3\u05D9\u05DD", "\u05DE\u05D1\u05D9\u05E0\u05D9\u05DD", "\u05D1\u05D5\u05D7\u05E8\u05D9\u05DD"] }, { kind: "bars", labels: ["\u05E1\u05DB\u05D5\u05DD", "\u05D6\u05DE\u05DF", "\u05E1\u05D9\u05DB\u05D5\u05DF"] }],
|
|
2915
|
+
"two-paths": [{ kind: "choices", labels: ["\u05E9\u05D5\u05E7 \u05D4\u05D4\u05D5\u05DF", "\u05E0\u05D3\u05DC\u05F4\u05DF"] }, { kind: "stack", labels: ["\u05E0\u05D6\u05D9\u05DC\u05D5\u05EA", "\u05D4\u05D5\u05DF", "\u05E4\u05D9\u05D6\u05D5\u05E8"] }],
|
|
2916
|
+
"small-store": [{ kind: "choices", labels: ["\u05DE\u05DC\u05D0\u05D9", "\u05E6\u05D9\u05D5\u05D3"] }, { kind: "bars", labels: ["\u05E0\u05EA\u05D5\u05E0\u05D9\u05DD", "\u05EA\u05D6\u05E8\u05D9\u05DD", "\u05DE\u05D9\u05DE\u05D5\u05DF"] }, { kind: "phone", labels: ["\u05E6\u05D5\u05E8\u05DA", "\u05E4\u05EA\u05E8\u05D5\u05DF", "\u05D4\u05DE\u05E9\u05DA"] }],
|
|
2917
|
+
"travel-conveyor": [{ kind: "check", labels: ["\u05DE\u05D8\u05F4\u05D7", "\u05EA\u05E7\u05E6\u05D9\u05D1", "\u05D2\u05D9\u05D1\u05D5\u05D9"] }, { kind: "bars", labels: ["\u05D0\u05D5\u05DB\u05DC", "\u05E0\u05E1\u05D9\u05E2\u05D5\u05EA", "\u05E9\u05D5\u05E0\u05D5\u05EA"] }],
|
|
2918
|
+
"mortgage-blueprint": [{ kind: "meter", labels: ["\u05D9\u05DB\u05D5\u05DC\u05EA \u05D4\u05D7\u05D6\u05E8"] }, { kind: "stack", labels: ["\u05DE\u05E1\u05DC\u05D5\u05DC\u05D9\u05DD", "\u05E2\u05DC\u05D5\u05D9\u05D5\u05EA", "\u05D8\u05D5\u05D5\u05D7"] }, { kind: "check", labels: ["\u05E9\u05D0\u05DC\u05D5\u05EA", "\u05D4\u05E9\u05D5\u05D5\u05D0\u05D4", "\u05D9\u05D9\u05E2\u05D5\u05E5"] }],
|
|
2919
|
+
"market-phone": [{ kind: "phone", labels: ["\u05DE\u05D9\u05D3\u05E2", "\u05D4\u05E9\u05D5\u05D5\u05D0\u05D4", "\u05DE\u05E2\u05E7\u05D1"] }, { kind: "bars", labels: ["\u05E0\u05EA\u05D5\u05E0\u05D9\u05DD", "\u05DE\u05D2\u05DE\u05D4", "\u05D4\u05D7\u05DC\u05D8\u05D4"] }]
|
|
2920
|
+
};
|
|
2921
|
+
function holidayStoryboard(ctx) {
|
|
2922
|
+
if (ctx.theme !== "holiday-table" || ctx.index > 2) return false;
|
|
2923
|
+
const d = ctx.scene.duration;
|
|
2924
|
+
const end = d - 0.02;
|
|
2925
|
+
const keys = (item, frames) => {
|
|
2926
|
+
item.keyframes = frames;
|
|
2927
|
+
return item;
|
|
2928
|
+
};
|
|
2929
|
+
const disc = (name, x, y, diameter, color, delay = 0) => box(ctx, name, x, y, diameter, diameter, color, diameter / 2, delay);
|
|
2930
|
+
if (ctx.index === 0) {
|
|
2931
|
+
keys(box(ctx, "\u05DE\u05E4\u05EA \u05E9\u05D5\u05DC\u05D7\u05DF", 66, 67, 640, 630, "#920C33", 42), [
|
|
2932
|
+
point(0, 0, 0, 0.72, 0.72, -8, 0),
|
|
2933
|
+
point(0.46, 0, 0, 1, 1, 0),
|
|
2934
|
+
point(d * 0.72, 0, 0, 1.025, 1.025, 1),
|
|
2935
|
+
point(end, 0, 0, 1, 1)
|
|
2936
|
+
]);
|
|
2937
|
+
keys(disc("\u05E6\u05DC \u05E6\u05DC\u05D7\u05EA", 151, 139, 480, "#630B2A"), [point(0, 0, 130, 0.7, 0.7, -25, 0), point(0.55, 0, 0, 1, 1, 0), point(end, 0, 0)]);
|
|
2938
|
+
keys(disc("\u05E6\u05DC\u05D7\u05EA \u05DC\u05D1\u05E0\u05D4", 142, 120, 480, WHITE), [point(0, 0, 130, 0.7, 0.7, -25, 0), point(0.62, 0, 0, 1, 1, 0), point(d * 0.68, 0, -9, 1.03, 1.03, 4), point(end, 0, 0)]);
|
|
2939
|
+
keys(disc("\u05E9\u05E4\u05EA \u05E6\u05DC\u05D7\u05EA", 190, 168, 384, PALE), [point(0, 0, 130, 0.7, 0.7, -25, 0), point(0.7, 0, 0, 1, 1, 0), point(end, 0, 0)]);
|
|
2940
|
+
keys(disc("\u05DE\u05E8\u05DB\u05D6 \u05E6\u05DC\u05D7\u05EA", 219, 197, 326, RED), [point(0, 0, 130, 0.7, 0.7, -25, 0), point(0.77, 0, 0, 1, 1, 0), point(end, 0, 0)]);
|
|
2941
|
+
const symbol = caption(ctx, "\u05E1\u05DE\u05DC \u05D7\u05D2", "\u20AA", 319, 269, 126, 160, 132, WHITE, 0.8);
|
|
2942
|
+
keys(symbol, [point(0, 0, 90, 0.2, 0.2, -20, 0), point(0.81, 0, 90, 0.2, 0.2, -20, 0), point(1.22, 0, 0), point(d * 0.74, 0, -9, 1.1, 1.1, 4), point(end, 0, 0)]);
|
|
2943
|
+
for (const [i, x] of [97, 628].entries()) {
|
|
2944
|
+
const side = i ? 1 : -1;
|
|
2945
|
+
const utensil = box(ctx, `\u05E1\u05DB\u05D5\u05F4\u05DD ${i + 1}`, x, 220, 15, 280, WHITE, 7);
|
|
2946
|
+
keys(utensil, [point(0, side * 170, 0, 1, 1, side * 22, 0), point(0.65, side * 170, 0, 1, 1, side * 22, 0), point(1.08, 0, 0), point(end, 0, -12, 1, 1, side * 3)]);
|
|
2947
|
+
}
|
|
2948
|
+
for (let i = 0; i < 8; i++) {
|
|
2949
|
+
const theta = i * Math.PI / 4;
|
|
2950
|
+
const x = 372 + Math.cos(theta) * 286;
|
|
2951
|
+
const y = 360 + Math.sin(theta) * 286;
|
|
2952
|
+
const spark = disc(`\u05E0\u05E7\u05D5\u05D3\u05EA \u05D7\u05D2 ${i + 1}`, x, y, i % 2 ? 12 : 18, i % 3 ? "#FFDDA3" : WHITE);
|
|
2953
|
+
const beat = 0.35 + i * 0.095;
|
|
2954
|
+
keys(spark, [point(0, 0, 0, 0.2, 0.2, 0, 0), point(beat, 0, 0, 0.2, 0.2, 0, 0), point(beat + 0.36, 0, 0), point(end, 0, -15 - i * 2, 0.7, 0.7, 0, 0.55)]);
|
|
2955
|
+
}
|
|
2956
|
+
return true;
|
|
2957
|
+
}
|
|
2958
|
+
if (ctx.index === 1) {
|
|
2959
|
+
keys(box(ctx, "\u05E6\u05DC \u05DB\u05E8\u05D8\u05D9\u05E1 \u05EA\u05E7\u05E6\u05D9\u05D1", 67, 99, 654, 574, "#E6BBC5", 30), [point(0, 0, 160, 0.92, 0.92, 0, 0), point(0.53, 0, 0), point(end, 0, -8)]);
|
|
2960
|
+
keys(box(ctx, "\u05DB\u05E8\u05D8\u05D9\u05E1 \u05EA\u05E7\u05E6\u05D9\u05D1", 53, 81, 654, 574, WHITE, 30), [point(0, 0, 160, 0.92, 0.92, 0, 0), point(0.58, 0, 0), point(d * 0.72, 0, -8), point(end, 0, 0)]);
|
|
2961
|
+
caption(ctx, "\u05DB\u05D5\u05EA\u05E8\u05EA \u05DC\u05D5\u05D7 \u05EA\u05DB\u05E0\u05D5\u05DF", "\u05DE\u05E1\u05D2\u05E8\u05EA \u05DC\u05D7\u05D2", 115, 113, 520, 78, 52, NAVY, 0.42);
|
|
2962
|
+
box(ctx, "\u05E7\u05D5 \u05DB\u05D5\u05EA\u05E8\u05EA", 116, 199, 519, 6, RED, 3, 0.55);
|
|
2963
|
+
const labels = ["\u05E7\u05E0\u05D9\u05D5\u05EA", "\u05D0\u05D9\u05E8\u05D5\u05D7", "\u05E0\u05E1\u05D9\u05E2\u05D5\u05EA"];
|
|
2964
|
+
labels.forEach((label, i) => {
|
|
2965
|
+
const y = 238 + i * 123;
|
|
2966
|
+
const delay = 0.63 + i * 0.37;
|
|
2967
|
+
const icon = disc(`\u05E1\u05DE\u05DC \u05E1\u05E2\u05D9\u05E3 ${i + 1}`, 113, y, 70, i === 1 ? NAVY : RED);
|
|
2968
|
+
keys(icon, [point(0, -95, 0, 0.6, 0.6, -20, 0), point(delay, -95, 0, 0.6, 0.6, -20, 0), point(delay + 0.32, 0, 0), point(end, 0, -5)]);
|
|
2969
|
+
caption(ctx, `\u05E9\u05DD \u05E1\u05E2\u05D9\u05E3 ${i + 1}`, label, 206, y + 4, 180, 64, 38, NAVY, delay + 0.09);
|
|
2970
|
+
const guide = box(ctx, `\u05DE\u05E1\u05DC\u05D5\u05DC \u05E1\u05E2\u05D9\u05E3 ${i + 1}`, 397, y + 20, 238, 28, "#F8DEE5", 14, delay);
|
|
2971
|
+
keys(guide, [point(0, 0, 0, 0.2, 1, 0, 0), point(delay, 0, 0, 0.2, 1, 0, 0), point(delay + 0.38, 0, 0), point(end, 0, 0)]);
|
|
2972
|
+
const fill = box(ctx, `\u05D4\u05D3\u05D2\u05E9\u05EA \u05E1\u05E2\u05D9\u05E3 ${i + 1}`, 397, y + 20, 168, 28, i === 1 ? NAVY : RED, 14, delay + 0.24);
|
|
2973
|
+
keys(fill, [point(0, -80, 0, 0.05, 1, 0, 0), point(delay + 0.22, -80, 0, 0.05, 1, 0, 0), point(delay + 0.73, 0, 0), point(end, 12, 0)]);
|
|
2974
|
+
});
|
|
2975
|
+
caption(ctx, "\u05D4\u05E2\u05E8\u05EA \u05EA\u05DB\u05E0\u05D5\u05DF", "\u05DE\u05EA\u05DB\u05E0\u05E0\u05D9\u05DD \u05DE\u05E8\u05D0\u05E9 \u2022 \u05D1\u05D5\u05D7\u05E8\u05D9\u05DD \u05D1\u05E0\u05D7\u05EA", 119, 594, 523, 56, 29, NAVY, 1.5);
|
|
2976
|
+
return true;
|
|
2977
|
+
}
|
|
2978
|
+
box(ctx, "\u05E7\u05D5 \u05D7\u05DC\u05D5\u05E7\u05D4", 360, 85, 12, 601, WHITE, 6, 0.12, 0, 0, 0.42);
|
|
2979
|
+
["\u05E7\u05E0\u05D9\u05D5\u05EA", "\u05D0\u05D9\u05E8\u05D5\u05D7", "\u05E0\u05E1\u05D9\u05E2\u05D5\u05EA"].forEach((label, i) => {
|
|
2980
|
+
const y = 115 + i * 174;
|
|
2981
|
+
const delay = 0.24 + i * 0.58;
|
|
2982
|
+
const direction = i % 2 ? 1 : -1;
|
|
2983
|
+
const card = box(ctx, `\u05DB\u05E8\u05D8\u05D9\u05E1 ${label}`, 42, y, 674, 142, WHITE, 25, delay, direction * 570);
|
|
2984
|
+
keys(card, [
|
|
2985
|
+
point(0, direction * 570, 0, 0.88, 0.88, direction * 7, 0),
|
|
2986
|
+
point(delay, direction * 570, 0, 0.88, 0.88, direction * 7, 0),
|
|
2987
|
+
point(delay + 0.42, 0, 0),
|
|
2988
|
+
point(delay + 0.67, 0, -8, 1.025, 1.025, 0),
|
|
2989
|
+
point(end, 0, 0)
|
|
2990
|
+
]);
|
|
2991
|
+
const badge = disc(`\u05DE\u05E1\u05E4\u05E8 \u05E1\u05E2\u05D9\u05E3 ${i + 1}`, 70, y + 27, 88, RED, delay + 0.16);
|
|
2992
|
+
keys(badge, [point(0, -90, 0, 0.2, 0.2, -35, 0), point(delay + 0.12, -90, 0, 0.2, 0.2, -35, 0), point(delay + 0.5, 0, 0), point(end, 0, -3)]);
|
|
2993
|
+
caption(ctx, `\u05E1\u05E4\u05E8\u05EA \u05E1\u05E2\u05D9\u05E3 ${i + 1}`, `0${i + 1}`, 88, y + 47, 52, 53, 38, WHITE, delay + 0.31);
|
|
2994
|
+
caption(ctx, `\u05EA\u05D5\u05D5\u05D9\u05EA \u05E1\u05E2\u05D9\u05E3 ${i + 1}`, label, 188, y + 25, 355, 93, 55, NAVY, delay + 0.21);
|
|
2995
|
+
const dash = box(ctx, `\u05E7\u05D5 \u05E1\u05E2\u05D9\u05E3 ${i + 1}`, 574, y + 66, 99, 10, RED, 5, delay + 0.45);
|
|
2996
|
+
keys(dash, [point(0, -80, 0, 0.1, 1, 0, 0), point(delay + 0.42, -80, 0, 0.1, 1, 0, 0), point(delay + 0.8, 0, 0), point(end, 20, 0)]);
|
|
2997
|
+
});
|
|
2998
|
+
return true;
|
|
2999
|
+
}
|
|
3000
|
+
function oneClickStoryboard(ctx) {
|
|
3001
|
+
if (ctx.theme !== "one-click" || ctx.index > 3) return false;
|
|
3002
|
+
const end = ctx.scene.duration - 0.02;
|
|
3003
|
+
const set = (item, keys) => {
|
|
3004
|
+
item.keyframes = keys;
|
|
3005
|
+
return item;
|
|
3006
|
+
};
|
|
3007
|
+
const appear = (delay, fromX = 0, fromY = 70) => [
|
|
3008
|
+
point(0, fromX, fromY, 0.82, 0.82, 0, 0),
|
|
3009
|
+
point(delay, fromX, fromY, 0.82, 0.82, 0, 0),
|
|
3010
|
+
point(delay + 0.38, 0, 0),
|
|
3011
|
+
point(end, 0, -8)
|
|
3012
|
+
];
|
|
3013
|
+
const text3 = (name, value, x, y, w, h, size, color, delay) => set(caption(ctx, name, value, x, y, w, h, size, color, delay), appear(delay, 0, 0));
|
|
3014
|
+
const circle = (name, x, y, d, color, delay) => box(ctx, name, x, y, d, d, color, d / 2, delay);
|
|
3015
|
+
const bar = (name, x, y, w, h, color, delay, rotation = 0) => set(box(ctx, name, x, y, w, h, color, h / 2, delay, 0, 0, 1, rotation), appear(delay, 0, 0));
|
|
3016
|
+
const body = box(ctx, "\u05DE\u05E1\u05D2\u05E8\u05EA \u05D8\u05DC\u05E4\u05D5\u05DF \u05D3\u05D9\u05D2\u05D9\u05D8\u05DC\u05D9\u05EA", 182, 47, 394, 642, NAVY, 45, 0.08);
|
|
3017
|
+
const screen = box(ctx, "\u05DE\u05E1\u05DA \u05D8\u05DC\u05E4\u05D5\u05DF \u05D3\u05D9\u05D2\u05D9\u05D8\u05DC\u05D9", 204, 69, 350, 598, WHITE, 29, 0.2);
|
|
3018
|
+
for (const item of [body, screen]) set(item, [
|
|
3019
|
+
point(0, 0, 195, 0.76, 0.76, -8, 0),
|
|
3020
|
+
point(0.48, 0, 0, 1, 1, 0),
|
|
3021
|
+
point(1.78, 0, -8, 1.025, 1.025, 1),
|
|
3022
|
+
point(end, 0, 0)
|
|
3023
|
+
]);
|
|
3024
|
+
box(ctx, "\u05E8\u05DE\u05E7\u05D5\u05DC \u05D8\u05DC\u05E4\u05D5\u05DF", 343, 89, 70, 8, NAVY, 4, 0.42);
|
|
3025
|
+
box(ctx, "\u05E9\u05D5\u05E8\u05EA \u05E0\u05D9\u05D5\u05D5\u05D8", 226, 124, 306, 8, PALE, 4, 0.53);
|
|
3026
|
+
for (let i = 0; i < 3; i++) {
|
|
3027
|
+
const dot = circle(
|
|
3028
|
+
`\u05E9\u05DC\u05D1 \u05D0\u05E4\u05DC\u05D9\u05E7\u05E6\u05D9\u05D4 ${i + 1}`,
|
|
3029
|
+
273 + i * 106,
|
|
3030
|
+
607,
|
|
3031
|
+
20,
|
|
3032
|
+
i === Math.min(ctx.index, 2) ? RED : "#D4D9E2",
|
|
3033
|
+
0.55 + i * 0.11
|
|
3034
|
+
);
|
|
3035
|
+
set(dot, appear(0.58 + i * 0.12, 0, 26));
|
|
3036
|
+
}
|
|
3037
|
+
if (ctx.index === 0) {
|
|
3038
|
+
const halo = circle("\u05D4\u05D9\u05DC\u05D4 \u05E1\u05D1\u05D9\u05D1 \u05E4\u05E2\u05D5\u05DC\u05D4", 236, 169, 286, "#FDE5EC", 0.16);
|
|
3039
|
+
set(halo, [
|
|
3040
|
+
point(0, 0, 0, 0.3, 0.3, 0, 0),
|
|
3041
|
+
point(0.9, 0, 0, 1, 1, 0, 0.95),
|
|
3042
|
+
point(2, 0, 0, 1.12, 1.12, 0, 0.6),
|
|
3043
|
+
point(end, 0, 0, 1.27, 1.27, 0, 0.25)
|
|
3044
|
+
]);
|
|
3045
|
+
const tile = box(ctx, "\u05D0\u05E8\u05D9\u05D7 \u05E4\u05E2\u05D5\u05DC\u05D4 \u05E8\u05D0\u05E9\u05D9", 283, 225, 194, 184, RED, 37, 0.55);
|
|
3046
|
+
set(tile, [
|
|
3047
|
+
point(0, 0, 140, 0.28, 0.28, -18, 0),
|
|
3048
|
+
point(0.6, 0, 140, 0.28, 0.28, -18, 0),
|
|
3049
|
+
point(1.1, 0, 0),
|
|
3050
|
+
point(2.1, 0, -9, 1.07, 1.07, 4),
|
|
3051
|
+
point(end, 0, 0)
|
|
3052
|
+
]);
|
|
3053
|
+
bar("\u05D7\u05E5 \u05E4\u05E2\u05D5\u05DC\u05D4 \u05D0\u05D5\u05E4\u05E7\u05D9", 338, 313, 91, 8, WHITE, 0.84);
|
|
3054
|
+
bar("\u05D7\u05E5 \u05E4\u05E2\u05D5\u05DC\u05D4 \u05E2\u05DC\u05D9\u05D5\u05DF", 333, 303, 29, 8, WHITE, 0.9, -43);
|
|
3055
|
+
bar("\u05D7\u05E5 \u05E4\u05E2\u05D5\u05DC\u05D4 \u05EA\u05D7\u05EA\u05D5\u05DF", 333, 322, 29, 8, WHITE, 0.9, 43);
|
|
3056
|
+
const button = box(ctx, "\u05DB\u05E4\u05EA\u05D5\u05E8 \u05D4\u05EA\u05D7\u05DC\u05D4", 253, 481, 252, 76, NAVY, 38, 1.1);
|
|
3057
|
+
set(button, appear(1.13, 0, 90));
|
|
3058
|
+
text3("\u05DC\u05D7\u05E6\u05DF \u05D4\u05EA\u05D7\u05DC\u05D4", "\u05DE\u05EA\u05D7\u05D9\u05DC\u05D9\u05DD", 272, 491, 214, 53, 38, WHITE, 1.52);
|
|
3059
|
+
const tap = circle("\u05DC\u05D7\u05D9\u05E6\u05D4 \u05E8\u05D0\u05E9\u05D5\u05E0\u05D4", 409, 500, 88, "#FD9CB7", 1.7);
|
|
3060
|
+
set(tap, [
|
|
3061
|
+
point(0, 0, 0, 0.1, 0.1, 0, 0),
|
|
3062
|
+
point(1.67, 0, 0, 0.1, 0.1, 0, 0),
|
|
3063
|
+
point(2.03, 0, 0, 1, 1, 0, 0.8),
|
|
3064
|
+
point(end, 0, 0, 1.8, 1.8, 0, 0)
|
|
3065
|
+
]);
|
|
3066
|
+
return true;
|
|
3067
|
+
}
|
|
3068
|
+
if (ctx.index === 1) {
|
|
3069
|
+
text3("\u05DB\u05D5\u05EA\u05E8\u05EA \u05E4\u05EA\u05D9\u05D7\u05EA \u05D0\u05E4\u05DC\u05D9\u05E7\u05E6\u05D9\u05D4", "\u05D4\u05DE\u05E1\u05DA \u05E0\u05E4\u05EA\u05D7", 245, 167, 270, 70, 51, NAVY, 0.63);
|
|
3070
|
+
const panel = box(ctx, "\u05DC\u05D5\u05D7 \u05D0\u05E4\u05DC\u05D9\u05E7\u05E6\u05D9\u05D4", 240, 252, 280, 280, PALE, 24, 0.7);
|
|
3071
|
+
set(panel, appear(0.7, 0, 100));
|
|
3072
|
+
const emblem = circle("\u05E1\u05DE\u05DC \u05D0\u05E4\u05DC\u05D9\u05E7\u05E6\u05D9\u05D4", 329, 280, 100, RED, 0.88);
|
|
3073
|
+
set(emblem, [
|
|
3074
|
+
point(0, 0, 80, 0.2, 0.2, -30, 0),
|
|
3075
|
+
point(0.88, 0, 80, 0.2, 0.2, -30, 0),
|
|
3076
|
+
point(1.26, 0, 0),
|
|
3077
|
+
point(2.25, 0, -9, 1.12, 1.12, 8),
|
|
3078
|
+
point(end, 0, 0)
|
|
3079
|
+
]);
|
|
3080
|
+
bar("\u05D2\u05D2 \u05D1\u05D9\u05EA \u05E9\u05DE\u05D0\u05DC", 351, 316, 34, 5, WHITE, 1.02, -43);
|
|
3081
|
+
bar("\u05D2\u05D2 \u05D1\u05D9\u05EA \u05D9\u05DE\u05D9\u05DF", 377, 316, 34, 5, WHITE, 1.02, 43);
|
|
3082
|
+
bar("\u05E7\u05D9\u05E8 \u05D1\u05D9\u05EA \u05E9\u05DE\u05D0\u05DC", 356, 333, 5, 30, WHITE, 1.08);
|
|
3083
|
+
bar("\u05E7\u05D9\u05E8 \u05D1\u05D9\u05EA \u05D9\u05DE\u05D9\u05DF", 397, 333, 5, 30, WHITE, 1.08);
|
|
3084
|
+
bar("\u05D1\u05E1\u05D9\u05E1 \u05D1\u05D9\u05EA", 356, 359, 46, 5, WHITE, 1.08);
|
|
3085
|
+
for (let i = 0; i < 3; i++) {
|
|
3086
|
+
const row = box(ctx, `\u05E9\u05D5\u05E8\u05EA \u05D8\u05E2\u05D9\u05E0\u05D4 ${i + 1}`, 270, 409 + i * 43, 218 - i * 34, 17, i === 0 ? RED : "#DAA6B2", 8, 1.05 + i * 0.24);
|
|
3087
|
+
set(row, [
|
|
3088
|
+
point(0, -180, 0, 0.08, 1, 0, 0),
|
|
3089
|
+
point(1.03 + i * 0.22, -180, 0, 0.08, 1, 0, 0),
|
|
3090
|
+
point(1.48 + i * 0.22, 0, 0),
|
|
3091
|
+
point(end, 8, 0)
|
|
3092
|
+
]);
|
|
3093
|
+
}
|
|
3094
|
+
return true;
|
|
3095
|
+
}
|
|
3096
|
+
if (ctx.index === 2) {
|
|
3097
|
+
text3("\u05DB\u05D5\u05EA\u05E8\u05EA \u05D1\u05D7\u05D9\u05E8\u05EA \u05E4\u05E2\u05D5\u05DC\u05D4", "\u05DE\u05D4 \u05E2\u05D5\u05E9\u05D9\u05DD \u05E2\u05DB\u05E9\u05D9\u05D5?", 242, 166, 273, 78, 44, NAVY, 0.6);
|
|
3098
|
+
["\u05D4\u05DC\u05D5\u05D5\u05D0\u05D4", "\u05DE\u05D9\u05D3\u05E2 \u05E0\u05D5\u05E1\u05E3"].forEach((label, i) => {
|
|
3099
|
+
const y = 276 + i * 130;
|
|
3100
|
+
const row = box(ctx, `\u05D0\u05E4\u05E9\u05E8\u05D5\u05EA \u05D1\u05D0\u05E4\u05DC\u05D9\u05E7\u05E6\u05D9\u05D4 ${i + 1}`, 238, y, 286, 103, i ? PALE : "#FDE1E9", 20, 0.82 + i * 0.31);
|
|
3101
|
+
set(row, appear(0.82 + i * 0.31, i ? 180 : -180, 0));
|
|
3102
|
+
const marker = circle(`\u05E1\u05D9\u05DE\u05D5\u05DF \u05D0\u05E4\u05E9\u05E8\u05D5\u05EA ${i + 1}`, 263, y + 29, 44, i ? "#D6DCE4" : RED, 1.01 + i * 0.31);
|
|
3103
|
+
set(marker, appear(1.01 + i * 0.31, i ? 100 : -100, 0));
|
|
3104
|
+
text3(`\u05EA\u05D5\u05D5\u05D9\u05EA \u05D0\u05E4\u05E9\u05E8\u05D5\u05EA \u05D1\u05D0\u05E4\u05DC\u05D9\u05E7\u05E6\u05D9\u05D4 ${i + 1}`, label, 315, y + 22, 180, 61, 37, NAVY, 1.21 + i * 0.31);
|
|
3105
|
+
});
|
|
3106
|
+
const focus = circle("\u05DC\u05D7\u05D9\u05E6\u05D4 \u05E2\u05DC \u05D1\u05D7\u05D9\u05E8\u05D4", 272, 302, 75, "#FF7D9D", 1.67);
|
|
3107
|
+
set(focus, [
|
|
3108
|
+
point(0, 0, 0, 0.1, 0.1, 0, 0),
|
|
3109
|
+
point(1.65, 0, 0, 0.1, 0.1, 0, 0),
|
|
3110
|
+
point(1.94, 0, 0, 1, 1, 0, 0.72),
|
|
3111
|
+
point(end, 0, 0, 2, 2, 0, 0)
|
|
3112
|
+
]);
|
|
3113
|
+
return true;
|
|
3114
|
+
}
|
|
3115
|
+
text3("\u05DB\u05D5\u05EA\u05E8\u05EA \u05D1\u05D3\u05D9\u05E7\u05EA \u05E4\u05E8\u05D8\u05D9\u05DD", "\u05DC\u05E4\u05E0\u05D9 \u05E9\u05DE\u05D0\u05E9\u05E8\u05D9\u05DD", 229, 155, 300, 88, 35, NAVY, 0.63);
|
|
3116
|
+
["\u05E4\u05E8\u05D8\u05D9\u05DD", "\u05EA\u05E0\u05D0\u05D9\u05DD", "\u05D1\u05D7\u05D9\u05E8\u05D4"].forEach((label, i) => {
|
|
3117
|
+
const y = 250 + i * 89;
|
|
3118
|
+
const row = box(ctx, `\u05E9\u05D5\u05E8\u05EA \u05D1\u05D3\u05D9\u05E7\u05D4 ${i + 1}`, 243, y, 277, 72, PALE, 15, 0.78 + i * 0.33);
|
|
3119
|
+
set(row, appear(0.78 + i * 0.33, i % 2 ? 130 : -130, 0));
|
|
3120
|
+
text3(`\u05EA\u05D5\u05DB\u05DF \u05D1\u05D3\u05D9\u05E7\u05D4 ${i + 1}`, label, 297, y + 9, 173, 50, 31, NAVY, 1.17 + i * 0.33);
|
|
3121
|
+
const check = circle(`\u05E1\u05D9\u05DE\u05D5\u05DF \u05D1\u05D3\u05D9\u05E7\u05D4 ${i + 1}`, 466, y + 17, 39, RED, 1.23 + i * 0.33);
|
|
3122
|
+
set(check, appear(1.23 + i * 0.33, 0, 0));
|
|
3123
|
+
bar(`\u05D5\u05D9 \u05E7\u05E6\u05E8 \u05D1\u05D3\u05D9\u05E7\u05D4 ${i + 1}`, 474, y + 37, 13, 4, WHITE, 1.31 + i * 0.33, 43);
|
|
3124
|
+
bar(`\u05D5\u05D9 \u05D0\u05E8\u05D5\u05DA \u05D1\u05D3\u05D9\u05E7\u05D4 ${i + 1}`, 483, y + 34, 21, 4, WHITE, 1.35 + i * 0.33, -43);
|
|
3125
|
+
});
|
|
3126
|
+
const confirm = box(ctx, "\u05DB\u05E4\u05EA\u05D5\u05E8 \u05D4\u05DE\u05E9\u05DA", 247, 550, 268, 56, RED, 28, 1.85);
|
|
3127
|
+
set(confirm, [
|
|
3128
|
+
point(0, 0, 85, 0.8, 0.8, 0, 0),
|
|
3129
|
+
point(1.85, 0, 85, 0.8, 0.8, 0, 0),
|
|
3130
|
+
point(2.27, 0, 0),
|
|
3131
|
+
point(end, 0, 0, 1.07, 1.07)
|
|
3132
|
+
]);
|
|
3133
|
+
text3("\u05EA\u05D5\u05D5\u05D9\u05EA \u05D4\u05DE\u05E9\u05DA", "\u05DE\u05DE\u05E9\u05D9\u05DB\u05D9\u05DD", 282, 553, 198, 50, 31, WHITE, 2.27);
|
|
3134
|
+
return true;
|
|
3135
|
+
}
|
|
3136
|
+
function careerStoryboard(ctx) {
|
|
3137
|
+
if (ctx.theme !== "book-steps" || ctx.index > 2) return false;
|
|
3138
|
+
const end = ctx.scene.duration - 0.02;
|
|
3139
|
+
const set = (item, frames) => {
|
|
3140
|
+
item.keyframes = frames;
|
|
3141
|
+
return item;
|
|
3142
|
+
};
|
|
3143
|
+
const reveal = (delay, fromX = 0, fromY = 0) => [
|
|
3144
|
+
point(0, fromX, fromY, 0.88, 0.88, 0, 0),
|
|
3145
|
+
point(delay, fromX, fromY, 0.88, 0.88, 0, 0),
|
|
3146
|
+
point(delay + 0.43, 0, 0),
|
|
3147
|
+
point(Math.max(delay + 0.53, end - 0.44), 0, -8, 1.025, 1.025),
|
|
3148
|
+
point(end, 0, 0)
|
|
3149
|
+
];
|
|
3150
|
+
const shape = (name, x, y, w, h, color, radius, delay, fromX = 0, fromY = 0) => set(box(ctx, name, x, y, w, h, color, radius, delay), reveal(delay, fromX, fromY));
|
|
3151
|
+
const text3 = (name, value, x, y, w, h, size, color, delay) => set(caption(ctx, name, value, x, y, w, h, size, color, delay), reveal(delay));
|
|
3152
|
+
if (ctx.index === 0) {
|
|
3153
|
+
shape("\u05D4\u05D9\u05DC\u05D4 \u05DE\u05D0\u05D7\u05D5\u05E8\u05D9 \u05E1\u05E4\u05E8\u05D9\u05DD", 73, 79, 610, 610, "#C9003C", 305, 0.04);
|
|
3154
|
+
["\u05DE\u05D8\u05E8\u05D4", "\u05DC\u05D9\u05DE\u05D5\u05D3", "\u05D4\u05DB\u05E9\u05E8\u05D4"].forEach((label, i) => {
|
|
3155
|
+
const x = 62 + i * 127;
|
|
3156
|
+
const y = 495 - i * 137;
|
|
3157
|
+
const delay = 0.2 + i * 0.48;
|
|
3158
|
+
shape(`\u05E6\u05DC \u05E1\u05E4\u05E8 ${i + 1}`, x + 12, y + 15, 322, 101, "#9E0634", 15, delay, 0, 155);
|
|
3159
|
+
shape(`\u05E1\u05E4\u05E8 \u05DE\u05E1\u05DC\u05D5\u05DC ${i + 1}`, x, y, 322, 101, i === 1 ? PALE : WHITE, 15, delay + 0.08, 0, 155);
|
|
3160
|
+
shape(`\u05E9\u05D3\u05E8\u05EA \u05E1\u05E4\u05E8 ${i + 1}`, x + 10, y + 16, 12, 69, RED, 6, delay + 0.19);
|
|
3161
|
+
shape(`\u05D3\u05E4\u05D9 \u05E1\u05E4\u05E8 ${i + 1}`, x + 40, y + 88, 260, 4, "#EFCBD5", 2, delay + 0.21);
|
|
3162
|
+
text3(`\u05DE\u05E1\u05E4\u05E8 \u05E1\u05E4\u05E8 ${i + 1}`, `0${i + 1}`, x + 38, y + 14, 77, 67, 45, RED, delay + 0.28);
|
|
3163
|
+
text3(`\u05E0\u05D5\u05E9\u05D0 \u05E1\u05E4\u05E8 ${i + 1}`, label, x + 117, y + 16, 176, 65, 38, NAVY, delay + 0.33);
|
|
3164
|
+
});
|
|
3165
|
+
shape("\u05E7\u05D5 \u05E2\u05DC\u05D9\u05D4", 474, 121, 179, 10, WHITE, 5, 1.51, -120, 0);
|
|
3166
|
+
shape("\u05D7\u05D5\u05EA\u05DD \u05D9\u05E2\u05D3", 629, 99, 56, 56, WHITE, 28, 1.69, 0, 90);
|
|
3167
|
+
return true;
|
|
3168
|
+
}
|
|
3169
|
+
if (ctx.index === 1) {
|
|
3170
|
+
shape("\u05E6\u05DC \u05DC\u05D5\u05D7 \u05DE\u05E1\u05DC\u05D5\u05DC\u05D9\u05DD", 75, 103, 633, 568, "#EFDDE2", 29, 0.08, 0, 145);
|
|
3171
|
+
shape("\u05DC\u05D5\u05D7 \u05DE\u05E1\u05DC\u05D5\u05DC\u05D9\u05DD", 62, 86, 633, 568, WHITE, 29, 0.15, 0, 145);
|
|
3172
|
+
text3("\u05DB\u05D5\u05EA\u05E8\u05EA \u05D1\u05D7\u05D9\u05E8\u05EA \u05DE\u05E1\u05DC\u05D5\u05DC", "\u05D1\u05D5\u05D7\u05E8\u05D9\u05DD \u05EA\u05D7\u05D5\u05DD", 109, 119, 538, 77, 50, NAVY, 0.58);
|
|
3173
|
+
["\u05E2\u05D9\u05E6\u05D5\u05D1", "\u05E0\u05EA\u05D5\u05E0\u05D9\u05DD", "\u05E4\u05D9\u05EA\u05D5\u05D7"].forEach((label, i) => {
|
|
3174
|
+
const y = 216 + i * 117;
|
|
3175
|
+
const delay = 0.79 + i * 0.49;
|
|
3176
|
+
shape(`\u05DB\u05E8\u05D8\u05D9\u05E1 \u05EA\u05D7\u05D5\u05DD ${i + 1}`, 102, y, 555, 87, i === 1 ? "#FDE0E8" : PALE, 20, delay, i % 2 ? 170 : -170);
|
|
3177
|
+
shape(`\u05E1\u05D9\u05DE\u05D5\u05DF \u05EA\u05D7\u05D5\u05DD ${i + 1}`, 125, y + 22, 43, 43, i === 1 ? RED : "#E4B5C2", 22, delay + 0.13, i % 2 ? 90 : -90);
|
|
3178
|
+
text3(`\u05E9\u05DD \u05EA\u05D7\u05D5\u05DD ${i + 1}`, label, 200, y + 9, 293, 66, 41, NAVY, delay + 0.3);
|
|
3179
|
+
shape(`\u05E7\u05D5 \u05EA\u05D7\u05D5\u05DD ${i + 1}`, 563, y + 38, 62, 9, i === 1 ? RED : "#D1AAB6", 5, delay + 0.36);
|
|
3180
|
+
});
|
|
3181
|
+
text3("\u05D4\u05E2\u05E8\u05EA \u05D1\u05D7\u05D9\u05E8\u05EA \u05DE\u05E1\u05DC\u05D5\u05DC", "\u05DC\u05D5\u05DE\u05D3\u05D9\u05DD \u05D0\u05EA \u05DE\u05D4 \u05E9\u05DE\u05EA\u05D0\u05D9\u05DD \u05DC\u05DB\u05DD", 124, 581, 510, 49, 26, NAVY, 2.55);
|
|
3182
|
+
return true;
|
|
3183
|
+
}
|
|
3184
|
+
shape("\u05E6\u05DC \u05DC\u05D5\u05D7 \u05EA\u05DB\u05E0\u05D5\u05DF", 75, 103, 633, 568, "#B9003C", 29, 0.06, 0, 145);
|
|
3185
|
+
shape("\u05DC\u05D5\u05D7 \u05EA\u05DB\u05E0\u05D5\u05DF \u05DC\u05D9\u05DE\u05D5\u05D3\u05D9\u05DD", 62, 86, 633, 568, WHITE, 29, 0.14, 0, 145);
|
|
3186
|
+
text3("\u05DB\u05D5\u05EA\u05E8\u05EA \u05DC\u05D5\u05D7 \u05EA\u05DB\u05E0\u05D5\u05DF \u05DC\u05D9\u05DE\u05D5\u05D3\u05D9\u05DD", "\u05DE\u05EA\u05DB\u05E0\u05E0\u05D9\u05DD \u05D0\u05EA \u05D4\u05D3\u05E8\u05DA", 103, 121, 554, 75, 45, NAVY, 0.52);
|
|
3187
|
+
["\u05D6\u05DE\u05DF", "\u05E2\u05DC\u05D5\u05EA", "\u05E9\u05D2\u05E8\u05D4"].forEach((label, i) => {
|
|
3188
|
+
const y = 226 + i * 116;
|
|
3189
|
+
const delay = 0.72 + i * 0.53;
|
|
3190
|
+
shape(`\u05E8\u05E7\u05E2 \u05DE\u05D3\u05D3 ${i + 1}`, 101, y, 554, 87, i === 1 ? "#FDE0E8" : PALE, 18, delay, 0, 100);
|
|
3191
|
+
text3(`\u05E9\u05DD \u05DE\u05D3\u05D3 ${i + 1}`, label, 119, y + 9, 146, 64, 35, NAVY, delay + 0.25);
|
|
3192
|
+
shape(`\u05DE\u05E1\u05DC\u05D5\u05DC \u05DE\u05D3\u05D3 ${i + 1}`, 292, y + 32, 312, 22, "#DFBCC7", 11, delay + 0.19);
|
|
3193
|
+
const widths = [230, 173, 263];
|
|
3194
|
+
const fill = box(ctx, `\u05D4\u05EA\u05E7\u05D3\u05DE\u05D5\u05EA \u05DE\u05D3\u05D3 ${i + 1}`, 292, y + 32, widths[i], 22, RED, 11, delay + 0.33);
|
|
3195
|
+
set(fill, [
|
|
3196
|
+
point(0, -widths[i] / 2, 0, 0.02, 1, 0, 0),
|
|
3197
|
+
point(delay + 0.31, -widths[i] / 2, 0, 0.02, 1, 0, 0),
|
|
3198
|
+
point(delay + 0.85, 0, 0),
|
|
3199
|
+
point(end, 5, 0)
|
|
3200
|
+
]);
|
|
3201
|
+
});
|
|
3202
|
+
text3("\u05D4\u05E2\u05E8\u05EA \u05EA\u05DB\u05E0\u05D5\u05DF \u05DC\u05D9\u05DE\u05D5\u05D3\u05D9\u05DD", "\u05D1\u05D5\u05E0\u05D9\u05DD \u05DE\u05E1\u05D2\u05E8\u05EA \u05D9\u05E9\u05D9\u05DE\u05D4", 120, 588, 519, 48, 27, NAVY, 2.65);
|
|
3203
|
+
return true;
|
|
3204
|
+
}
|
|
3205
|
+
function homeRefreshStoryboard(ctx) {
|
|
3206
|
+
if (ctx.theme !== "room-build" || ctx.index > 2) return false;
|
|
3207
|
+
const end = ctx.scene.duration - 0.02;
|
|
3208
|
+
const set = (item, frames) => {
|
|
3209
|
+
item.keyframes = frames;
|
|
3210
|
+
return item;
|
|
3211
|
+
};
|
|
3212
|
+
const arrive = (delay, dx = 0, dy = 0) => [
|
|
3213
|
+
point(0, dx, dy, 0.9, 0.9, 0, 0),
|
|
3214
|
+
point(delay, dx, dy, 0.9, 0.9, 0, 0),
|
|
3215
|
+
point(delay + 0.38, 0, 0),
|
|
3216
|
+
point(Math.max(delay + 0.5, end - 0.42), 0, -5, 1.02, 1.02),
|
|
3217
|
+
point(end, 0, 0)
|
|
3218
|
+
];
|
|
3219
|
+
const shape = (name, x, y, w, h, color, radius, delay, dx = 0, dy = 0) => set(box(ctx, name, x, y, w, h, color, radius, delay), arrive(delay, dx, dy));
|
|
3220
|
+
const label = (name, value, x, y, w, h, size, color, delay) => set(caption(ctx, name, value, x, y, w, h, size, color, delay), arrive(delay, 0, 24));
|
|
3221
|
+
if (ctx.index === 0) {
|
|
3222
|
+
shape("\u05D4\u05D9\u05DC\u05D4 \u05E9\u05DC \u05D4\u05D1\u05D9\u05EA", 62, 55, 640, 630, "#BB0038", 310, 0.03);
|
|
3223
|
+
shape("\u05E9\u05D8\u05D9\u05D7 \u05D7\u05D3\u05E8", 117, 568, 534, 71, "#E9C0CA", 35, 0.37, 0, 75);
|
|
3224
|
+
shape("\u05E7\u05D9\u05E8 \u05D4\u05D7\u05D3\u05E8", 92, 160, 586, 425, WHITE, 20, 0.12, 0, 130);
|
|
3225
|
+
shape("\u05E8\u05E6\u05E4\u05EA \u05D4\u05D1\u05D9\u05EA", 91, 581, 587, 26, NAVY, 13, 0.42, -160);
|
|
3226
|
+
shape("\u05DE\u05E1\u05D2\u05E8\u05EA \u05D7\u05DC\u05D5\u05DF \u05D4\u05D1\u05D9\u05EA", 418, 196, 192, 228, NAVY, 14, 0.62, 0, -100);
|
|
3227
|
+
shape("\u05D0\u05D5\u05E8 \u05D7\u05DC\u05D5\u05DF \u05D4\u05D1\u05D9\u05EA", 430, 209, 168, 204, "#F7B8C9", 7, 0.75, 0, -85);
|
|
3228
|
+
shape("\u05DE\u05D5\u05D8 \u05D7\u05DC\u05D5\u05DF \u05D4\u05D1\u05D9\u05EA", 505, 209, 12, 204, WHITE, 6, 0.86);
|
|
3229
|
+
shape("\u05E7\u05D5 \u05D7\u05DC\u05D5\u05DF \u05D4\u05D1\u05D9\u05EA", 430, 308, 168, 10, WHITE, 5, 0.94);
|
|
3230
|
+
shape("\u05D1\u05E1\u05D9\u05E1 \u05E1\u05E4\u05D4", 160, 471, 350, 93, RED, 28, 1.02, -160);
|
|
3231
|
+
shape("\u05D2\u05D1 \u05E1\u05E4\u05D4", 174, 399, 319, 92, "#C9003C", 28, 1.14, -160);
|
|
3232
|
+
[181, 453].forEach((x, i) => shape(`\u05E8\u05D2\u05DC \u05E1\u05E4\u05D4 \u05D1\u05D9\u05EA ${i + 1}`, x, 557, 26, 36, NAVY, 7, 1.31));
|
|
3233
|
+
shape("\u05DE\u05D5\u05D8 \u05DE\u05E0\u05D5\u05E8\u05D4", 328, 202, 10, 196, NAVY, 5, 1.42, 0, -100);
|
|
3234
|
+
shape("\u05D0\u05D4\u05D9\u05DC \u05DE\u05E0\u05D5\u05E8\u05D4", 284, 367, 97, 64, "#EAC6D0", 18, 1.57, 0, -95);
|
|
3235
|
+
shape("\u05D0\u05D5\u05E8 \u05DE\u05E0\u05D5\u05E8\u05D4", 307, 409, 52, 9, "#FFC7D4", 5, 1.81);
|
|
3236
|
+
return true;
|
|
3237
|
+
}
|
|
3238
|
+
if (ctx.index === 1) {
|
|
3239
|
+
shape("\u05E6\u05DC \u05E7\u05D8\u05DC\u05D5\u05D2 \u05D7\u05D3\u05E8\u05D9\u05DD", 74, 87, 642, 584, "#E9C8D1", 30, 0.08, 0, 135);
|
|
3240
|
+
shape("\u05E7\u05D8\u05DC\u05D5\u05D2 \u05D7\u05D3\u05E8\u05D9\u05DD", 61, 74, 642, 584, WHITE, 30, 0.16, 0, 135);
|
|
3241
|
+
label("\u05DB\u05D5\u05EA\u05E8\u05EA \u05E4\u05D9\u05E0\u05D5\u05EA \u05D4\u05D1\u05D9\u05EA", "\u05D1\u05D5\u05D7\u05E8\u05D9\u05DD \u05E4\u05D9\u05E0\u05D4", 98, 101, 564, 75, 48, NAVY, 0.47);
|
|
3242
|
+
const rooms = [
|
|
3243
|
+
{ name: "\u05DE\u05D8\u05D1\u05D7", color: "#FFE1E9" },
|
|
3244
|
+
{ name: "\u05D7\u05D3\u05E8 \u05E2\u05D1\u05D5\u05D3\u05D4", color: "#F8D0DB" },
|
|
3245
|
+
{ name: "\u05E4\u05D9\u05E0\u05EA \u05D9\u05E9\u05D9\u05D1\u05D4", color: "#FFE1E9" }
|
|
3246
|
+
];
|
|
3247
|
+
rooms.forEach((room, i) => {
|
|
3248
|
+
const y = 194 + i * 138;
|
|
3249
|
+
const delay = 0.68 + i * 0.53;
|
|
3250
|
+
shape(`\u05DB\u05E8\u05D8\u05D9\u05E1 ${room.name}`, 96, y, 573, 112, room.color, 22, delay, i % 2 ? 160 : -160);
|
|
3251
|
+
shape(`\u05D0\u05E8\u05D9\u05D7 ${room.name}`, 113, y + 14, 81, 83, i === 1 ? RED : "#E5ACBB", 17, delay + 0.12, 0, 54);
|
|
3252
|
+
if (i === 0) {
|
|
3253
|
+
for (let cell = 0; cell < 4; cell++) shape(
|
|
3254
|
+
`\u05D0\u05E8\u05D9\u05D7 \u05DE\u05D8\u05D1\u05D7 ${cell + 1}`,
|
|
3255
|
+
134 + cell % 2 * 25,
|
|
3256
|
+
y + 37 + Math.floor(cell / 2) * 25,
|
|
3257
|
+
17,
|
|
3258
|
+
17,
|
|
3259
|
+
WHITE,
|
|
3260
|
+
3,
|
|
3261
|
+
delay + 0.22 + cell * 0.045
|
|
3262
|
+
);
|
|
3263
|
+
} else if (i === 1) {
|
|
3264
|
+
shape("\u05DE\u05E1\u05DA \u05D7\u05D3\u05E8 \u05D4\u05E2\u05D1\u05D5\u05D3\u05D4", 132, y + 34, 47, 31, WHITE, 5, delay + 0.23);
|
|
3265
|
+
shape("\u05E8\u05D2\u05DC \u05DE\u05E1\u05DA \u05D7\u05D3\u05E8 \u05D4\u05E2\u05D1\u05D5\u05D3\u05D4", 152, y + 65, 7, 11, WHITE, 2, delay + 0.29);
|
|
3266
|
+
shape("\u05D1\u05E1\u05D9\u05E1 \u05DE\u05E1\u05DA \u05D7\u05D3\u05E8 \u05D4\u05E2\u05D1\u05D5\u05D3\u05D4", 140, y + 76, 31, 5, WHITE, 2, delay + 0.35);
|
|
3267
|
+
} else {
|
|
3268
|
+
shape("\u05DB\u05E8\u05D9\u05EA \u05E4\u05D9\u05E0\u05EA \u05D9\u05E9\u05D9\u05D1\u05D4", 135, y + 36, 45, 40, WHITE, 17, delay + 0.23);
|
|
3269
|
+
shape("\u05D1\u05E1\u05D9\u05E1 \u05E4\u05D9\u05E0\u05EA \u05D9\u05E9\u05D9\u05D1\u05D4", 128, y + 73, 58, 8, WHITE, 4, delay + 0.34);
|
|
3270
|
+
}
|
|
3271
|
+
label(`\u05E9\u05DD ${room.name}`, room.name, 224, y + 20, 347, 68, 39, NAVY, delay + 0.27);
|
|
3272
|
+
shape(`\u05E7\u05D5 \u05D1\u05D7\u05D9\u05E8\u05D4 ${room.name}`, 599, y + 50, 42, 11, i === 1 ? RED : "#D2A4B1", 6, delay + 0.35);
|
|
3273
|
+
});
|
|
3274
|
+
label("\u05E9\u05D5\u05E8\u05EA \u05D1\u05D7\u05D9\u05E8\u05EA \u05D4\u05D1\u05D9\u05EA", "\u05DE\u05EA\u05D7\u05D9\u05DC\u05D9\u05DD \u05D1\u05DE\u05D4 \u05E9\u05D4\u05DB\u05D9 \u05D7\u05E9\u05D5\u05D1", 110, 608, 540, 43, 25, NAVY, 2.66);
|
|
3275
|
+
return true;
|
|
3276
|
+
}
|
|
3277
|
+
shape("\u05E6\u05DC \u05EA\u05DB\u05E0\u05D9\u05EA \u05D4\u05D1\u05D9\u05EA", 74, 87, 642, 584, "#B6003C", 30, 0.08, 0, 135);
|
|
3278
|
+
shape("\u05EA\u05DB\u05E0\u05D9\u05EA \u05D4\u05D1\u05D9\u05EA", 61, 74, 642, 584, WHITE, 30, 0.15, 0, 135);
|
|
3279
|
+
label("\u05DB\u05D5\u05EA\u05E8\u05EA \u05EA\u05DB\u05E0\u05D9\u05EA \u05D4\u05D1\u05D9\u05EA", "\u05DE\u05EA\u05DB\u05E0\u05E0\u05D9\u05DD \u05E9\u05D9\u05E0\u05D5\u05D9", 105, 104, 550, 72, 48, NAVY, 0.48);
|
|
3280
|
+
shape("\u05D2\u05D2 \u05D4\u05EA\u05DB\u05E0\u05D9\u05EA \u05E9\u05DE\u05D0\u05DC", 149, 232, 252, 12, RED, 6, 0.79, -90);
|
|
3281
|
+
shape("\u05D2\u05D2 \u05D4\u05EA\u05DB\u05E0\u05D9\u05EA \u05D9\u05DE\u05D9\u05DF", 397, 232, 252, 12, RED, 6, 0.9, 90);
|
|
3282
|
+
shape("\u05E7\u05D9\u05E8 \u05EA\u05DB\u05E0\u05D9\u05EA \u05E9\u05DE\u05D0\u05DC", 177, 244, 11, 230, NAVY, 5, 1.01, 0, -70);
|
|
3283
|
+
shape("\u05E7\u05D9\u05E8 \u05EA\u05DB\u05E0\u05D9\u05EA \u05D9\u05DE\u05D9\u05DF", 603, 244, 11, 230, NAVY, 5, 1.13, 0, -70);
|
|
3284
|
+
shape("\u05E8\u05E6\u05E4\u05EA \u05D4\u05EA\u05DB\u05E0\u05D9\u05EA", 177, 465, 437, 12, NAVY, 6, 1.24, -110);
|
|
3285
|
+
["\u05E1\u05DB\u05D5\u05DD", "\u05D6\u05DE\u05DF", "\u05E1\u05D3\u05E8"].forEach((name, i) => {
|
|
3286
|
+
const y = 279 + i * 56;
|
|
3287
|
+
const delay = 1.27 + i * 0.38;
|
|
3288
|
+
label(`\u05E9\u05D3\u05D4 \u05EA\u05DB\u05E0\u05D5\u05DF ${name}`, name, 207, y, 128, 48, 30, NAVY, delay);
|
|
3289
|
+
shape(`\u05DE\u05E1\u05DC\u05D5\u05DC ${name}`, 360, y + 17, 205, 15, "#E9C5CE", 8, delay + 0.09);
|
|
3290
|
+
const width = [153, 114, 173][i];
|
|
3291
|
+
const fill = box(ctx, `\u05DE\u05D7\u05D5\u05D5\u05DF ${name}`, 360, y + 17, width, 15, RED, 8, delay + 0.2);
|
|
3292
|
+
set(fill, [
|
|
3293
|
+
point(0, -width / 2, 0, 0.02, 1, 0, 0),
|
|
3294
|
+
point(delay + 0.2, -width / 2, 0, 0.02, 1, 0, 0),
|
|
3295
|
+
point(delay + 0.73, 0, 0),
|
|
3296
|
+
point(end, 4, 0)
|
|
3297
|
+
]);
|
|
3298
|
+
});
|
|
3299
|
+
label("\u05D7\u05EA\u05D9\u05DE\u05EA \u05EA\u05DB\u05E0\u05D5\u05DF \u05D4\u05D1\u05D9\u05EA", "\u05E6\u05E2\u05D3 \u05D0\u05D7\u05E8 \u05E6\u05E2\u05D3", 160, 535, 465, 59, 35, RED, 2.9);
|
|
3300
|
+
return true;
|
|
3301
|
+
}
|
|
3302
|
+
function summerStoryboard(ctx) {
|
|
3303
|
+
if (ctx.theme !== "summer-case" || ctx.index > 3) return false;
|
|
3304
|
+
const end = ctx.scene.duration - 0.02;
|
|
3305
|
+
const set = (item, frames) => {
|
|
3306
|
+
item.keyframes = frames;
|
|
3307
|
+
return item;
|
|
3308
|
+
};
|
|
3309
|
+
const inView = (delay, dx = 0, dy = 0) => [
|
|
3310
|
+
point(0, dx, dy, 0.84, 0.84, 0, 0),
|
|
3311
|
+
point(delay, dx, dy, 0.84, 0.84, 0, 0),
|
|
3312
|
+
point(delay + 0.33, 0, 0),
|
|
3313
|
+
point(Math.max(delay + 0.39, end - 0.35), 0, -6, 1.025, 1.025),
|
|
3314
|
+
point(end, 0, 0)
|
|
3315
|
+
];
|
|
3316
|
+
const shape = (name, x, y, w, h, color, radius, delay, dx = 0, dy = 0) => set(box(ctx, name, x, y, w, h, color, radius, delay), inView(delay, dx, dy));
|
|
3317
|
+
const word = (name, value, x, y, w, h, size, color, delay) => set(caption(ctx, name, value, x, y, w, h, size, color, delay), inView(delay, 0, 34));
|
|
3318
|
+
if (ctx.index === 0) {
|
|
3319
|
+
const sun = shape("\u05E9\u05DE\u05E9 \u05D4\u05E7\u05D9\u05E5", 488, 67, 195, 195, "#FFC5D4", 98, 0.12, 0, -90);
|
|
3320
|
+
set(sun, [
|
|
3321
|
+
point(0, 0, -90, 0.3, 0.3, -35, 0),
|
|
3322
|
+
point(0.12, 0, -90, 0.3, 0.3, -35, 0),
|
|
3323
|
+
point(0.6, 0, 0),
|
|
3324
|
+
point(end, -15, 13, 1.14, 1.14, 25)
|
|
3325
|
+
]);
|
|
3326
|
+
for (let i = 0; i < 7; i++) {
|
|
3327
|
+
const angle = i * Math.PI * 2 / 7;
|
|
3328
|
+
shape(
|
|
3329
|
+
`\u05E7\u05E8\u05DF \u05E7\u05D9\u05E5 ${i + 1}`,
|
|
3330
|
+
575 + Math.cos(angle) * 135,
|
|
3331
|
+
154 + Math.sin(angle) * 135,
|
|
3332
|
+
37,
|
|
3333
|
+
8,
|
|
3334
|
+
WHITE,
|
|
3335
|
+
4,
|
|
3336
|
+
0.28 + i * 0.07,
|
|
3337
|
+
0,
|
|
3338
|
+
-30
|
|
3339
|
+
);
|
|
3340
|
+
}
|
|
3341
|
+
shape("\u05E6\u05DC \u05DE\u05D6\u05D5\u05D5\u05D3\u05D4 \u05E7\u05D9\u05E5", 94, 606, 570, 37, "#9F0033", 19, 0.36, -250);
|
|
3342
|
+
shape("\u05D9\u05D3\u05D9\u05EA \u05DE\u05D6\u05D5\u05D5\u05D3\u05D4 \u05E7\u05D9\u05E5", 313, 253, 141, 110, WHITE, 37, 0.49, 0, 160);
|
|
3343
|
+
shape("\u05E4\u05EA\u05D7 \u05D9\u05D3\u05D9\u05EA \u05E7\u05D9\u05E5", 337, 278, 93, 71, RED, 25, 0.57, 0, 160);
|
|
3344
|
+
shape("\u05D2\u05D5\u05E3 \u05DE\u05D6\u05D5\u05D5\u05D3\u05D4 \u05E7\u05D9\u05E5", 130, 330, 500, 296, WHITE, 38, 0.64, -430);
|
|
3345
|
+
shape("\u05EA\u05E4\u05E8 \u05DE\u05D6\u05D5\u05D5\u05D3\u05D4 \u05E7\u05D9\u05E5", 151, 348, 457, 260, "#FFD6E1", 27, 0.73, -430);
|
|
3346
|
+
["\u05D7\u05D5\u05E4\u05E9", "\u05D7\u05D5\u05D5\u05D9\u05D4", "\u05E8\u05D2\u05E2"].forEach((label, i) => {
|
|
3347
|
+
const x = 189 + i * 137;
|
|
3348
|
+
const delay = 0.89 + i * 0.32;
|
|
3349
|
+
shape(`\u05DB\u05E8\u05D8\u05D9\u05E1 ${label}`, x, 395 + i % 2 * 35, 118, 117, i === 1 ? RED : "#EFA1B6", 17, delay, 0, -185);
|
|
3350
|
+
word(`\u05DE\u05D9\u05DC\u05EA \u05DE\u05D6\u05D5\u05D5\u05D3\u05D4 ${label}`, label, x + 4, 421 + i % 2 * 35, 111, 56, 26, WHITE, delay + 0.12);
|
|
3351
|
+
});
|
|
3352
|
+
shape("\u05E1\u05E8\u05D8 \u05DE\u05D6\u05D5\u05D5\u05D3\u05D4 \u05E7\u05D9\u05E5", 350, 348, 29, 259, NAVY, 8, 1.83, 0, -95);
|
|
3353
|
+
return true;
|
|
3354
|
+
}
|
|
3355
|
+
if (ctx.index === 1) {
|
|
3356
|
+
shape("\u05DB\u05E8\u05D8\u05D9\u05E1 \u05E8\u05D7\u05D5\u05E7", 32, 101, 329, 565, WHITE, 29, 0.15, -350);
|
|
3357
|
+
shape("\u05DB\u05E8\u05D8\u05D9\u05E1 \u05E7\u05E8\u05D5\u05D1", 396, 101, 329, 565, "#FFE3EA", 29, 0.36, 350);
|
|
3358
|
+
shape("\u05E9\u05DE\u05D9\u05D9\u05DD \u05E8\u05D7\u05D5\u05E7", 57, 135, 279, 261, "#FFD9E3", 20, 0.33, 0, -105);
|
|
3359
|
+
shape("\u05E9\u05DE\u05E9 \u05E8\u05D7\u05D5\u05E7", 224, 172, 83, 83, RED, 42, 0.59, 0, -95);
|
|
3360
|
+
shape("\u05D9\u05DD \u05E8\u05D7\u05D5\u05E7", 57, 326, 279, 72, "#E8A5B8", 13, 0.77, -95);
|
|
3361
|
+
shape("\u05E7\u05D5 \u05D7\u05D5\u05E3 \u05E8\u05D7\u05D5\u05E7", 77, 310, 240, 12, WHITE, 6, 0.84, -95);
|
|
3362
|
+
shape("\u05DE\u05D6\u05D5\u05D5\u05D3\u05D4 \u05E7\u05D8\u05E0\u05D4 \u05E8\u05D7\u05D5\u05E7", 119, 262, 88, 109, NAVY, 17, 0.98, -120);
|
|
3363
|
+
shape("\u05D9\u05D3\u05D9\u05EA \u05DE\u05D6\u05D5\u05D5\u05D3\u05D4 \u05E8\u05D7\u05D5\u05E7", 144, 243, 39, 31, NAVY, 13, 0.91, -120);
|
|
3364
|
+
word("\u05E9\u05DD \u05D0\u05E4\u05E9\u05E8\u05D5\u05EA \u05E8\u05D7\u05D5\u05E7\u05D4", "\u05E0\u05D5\u05E1\u05E2\u05D9\u05DD", 68, 465, 258, 84, 47, NAVY, 1.19);
|
|
3365
|
+
shape("\u05E9\u05DE\u05D9\u05D9\u05DD \u05E7\u05E8\u05D5\u05D1", 419, 135, 282, 261, WHITE, 20, 0.55, 0, -105);
|
|
3366
|
+
shape("\u05D2\u05D2 \u05D1\u05D9\u05EA \u05E7\u05E8\u05D5\u05D1", 467, 216, 192, 22, RED, 11, 0.9, 0, -92);
|
|
3367
|
+
shape("\u05D1\u05D9\u05EA \u05E7\u05E8\u05D5\u05D1", 479, 236, 170, 146, "#EF9FB5", 12, 1.01, 0, -92);
|
|
3368
|
+
shape("\u05D7\u05DC\u05D5\u05DF \u05D1\u05D9\u05EA \u05E7\u05E8\u05D5\u05D1", 529, 260, 58, 59, WHITE, 8, 1.17, 0, -92);
|
|
3369
|
+
shape("\u05D3\u05DC\u05EA \u05D1\u05D9\u05EA \u05E7\u05E8\u05D5\u05D1", 597, 298, 30, 84, NAVY, 5, 1.32, 0, -92);
|
|
3370
|
+
word("\u05E9\u05DD \u05D0\u05E4\u05E9\u05E8\u05D5\u05EA \u05E7\u05E8\u05D5\u05D1\u05D4", "\u05E0\u05E9\u05D0\u05E8\u05D9\u05DD \u05E7\u05E8\u05D5\u05D1", 422, 461, 278, 92, 38, NAVY, 1.45);
|
|
3371
|
+
shape("\u05E1\u05DE\u05DF \u05D1\u05D7\u05D9\u05E8\u05D4 \u05E8\u05D7\u05D5\u05E7", 166, 580, 62, 8, RED, 4, 1.72);
|
|
3372
|
+
shape("\u05E1\u05DE\u05DF \u05D1\u05D7\u05D9\u05E8\u05D4 \u05E7\u05E8\u05D5\u05D1", 529, 580, 62, 8, RED, 4, 1.86);
|
|
3373
|
+
return true;
|
|
3374
|
+
}
|
|
3375
|
+
if (ctx.index === 2) {
|
|
3376
|
+
shape("\u05E6\u05DC \u05DC\u05D5\u05D7 \u05E7\u05D9\u05E5", 75, 95, 620, 555, "#AA0034", 29, 0.06, 0, 130);
|
|
3377
|
+
shape("\u05DC\u05D5\u05D7 \u05E7\u05D9\u05E5", 63, 80, 620, 555, WHITE, 29, 0.14, 0, 130);
|
|
3378
|
+
word("\u05DB\u05D5\u05EA\u05E8\u05EA \u05DC\u05D5\u05D7 \u05E7\u05D9\u05E5", "\u05DE\u05EA\u05DB\u05E0\u05E0\u05D9\u05DD \u05D0\u05EA \u05D4\u05E7\u05D9\u05E5", 93, 113, 560, 72, 45, NAVY, 0.42);
|
|
3379
|
+
["\u05D3\u05E8\u05DA", "\u05D1\u05D9\u05DC\u05D5\u05D9", "\u05DE\u05E8\u05D5\u05D5\u05D7"].forEach((label, i) => {
|
|
3380
|
+
const y = 227 + i * 112;
|
|
3381
|
+
const delay = 0.63 + i * 0.44;
|
|
3382
|
+
shape(`\u05E9\u05D5\u05E8\u05EA \u05E7\u05D9\u05E5 ${i + 1}`, 100, y, 543, 88, i === 1 ? "#FAD4DF" : PALE, 19, delay, i % 2 ? 160 : -160);
|
|
3383
|
+
word(`\u05E9\u05DD \u05DE\u05D3\u05D3 \u05E7\u05D9\u05E5 ${i + 1}`, label, 123, y + 11, 132, 64, 34, NAVY, delay + 0.18);
|
|
3384
|
+
shape(`\u05DE\u05E1\u05DC\u05D5\u05DC \u05E7\u05D9\u05E5 ${i + 1}`, 280, y + 34, 319, 19, "#DEB8C4", 10, delay + 0.17);
|
|
3385
|
+
const width = [225, 165, 259][i];
|
|
3386
|
+
const fill = box(ctx, `\u05D4\u05EA\u05E7\u05D3\u05DE\u05D5\u05EA \u05E7\u05D9\u05E5 ${i + 1}`, 280, y + 34, width, 19, RED, 10, delay + 0.26);
|
|
3387
|
+
set(fill, [
|
|
3388
|
+
point(0, -width / 2, 0, 0.02, 1, 0, 0),
|
|
3389
|
+
point(delay + 0.26, -width / 2, 0, 0.02, 1, 0, 0),
|
|
3390
|
+
point(delay + 0.7, 0, 0),
|
|
3391
|
+
point(end, 5, 0)
|
|
3392
|
+
]);
|
|
3393
|
+
});
|
|
3394
|
+
word("\u05D4\u05E2\u05E8\u05EA \u05DE\u05E1\u05D2\u05E8\u05EA \u05E7\u05D9\u05E5", "\u05DE\u05E9\u05D0\u05D9\u05E8\u05D9\u05DD \u05DE\u05E7\u05D5\u05DD \u05DC\u05D1\u05D7\u05D9\u05E8\u05D4", 107, 583, 546, 49, 27, RED, 2.07);
|
|
3395
|
+
return true;
|
|
3396
|
+
}
|
|
3397
|
+
shape("\u05E8\u05E7\u05E2 \u05DE\u05E1\u05DC\u05D5\u05DC \u05E7\u05D9\u05E5", 54, 104, 653, 540, "#FFE5EC", 30, 0.11, 0, 130);
|
|
3398
|
+
shape("\u05E7\u05D5 \u05DE\u05E1\u05DC\u05D5\u05DC \u05E7\u05D9\u05E5", 112, 370, 538, 18, NAVY, 9, 0.26, -320);
|
|
3399
|
+
[131, 337, 546].forEach((x, i) => {
|
|
3400
|
+
const delay = 0.51 + i * 0.49;
|
|
3401
|
+
shape(`\u05EA\u05D7\u05E0\u05EA \u05E7\u05D9\u05E5 ${i + 1}`, x, 315, 128, 128, i === 2 ? RED : WHITE, 64, delay, 0, 140);
|
|
3402
|
+
shape(`\u05DC\u05D9\u05D1\u05EA \u05EA\u05D7\u05E0\u05EA \u05E7\u05D9\u05E5 ${i + 1}`, x + 32, 347, 64, 64, i === 2 ? WHITE : RED, 32, delay + 0.14, 0, 100);
|
|
3403
|
+
});
|
|
3404
|
+
word("\u05E8\u05D2\u05E2 \u05EA\u05DB\u05E0\u05D5\u05DF \u05E7\u05D9\u05E5", "\u05D1\u05D5\u05D7\u05E8\u05D9\u05DD", 105, 468, 180, 67, 34, NAVY, 0.8);
|
|
3405
|
+
word("\u05E8\u05D2\u05E2 \u05D9\u05E6\u05D9\u05D0\u05D4 \u05E7\u05D9\u05E5", "\u05D9\u05D5\u05E6\u05D0\u05D9\u05DD", 307, 468, 180, 67, 34, NAVY, 1.3);
|
|
3406
|
+
word("\u05E8\u05D2\u05E2 \u05E1\u05E4\u05D5\u05E0\u05D8\u05E0\u05D9 \u05E7\u05D9\u05E5", "\u05DE\u05D2\u05DC\u05D9\u05DD", 512, 468, 180, 67, 34, NAVY, 1.85);
|
|
3407
|
+
shape("\u05E2\u05E0\u05E3 \u05E1\u05E4\u05D5\u05E0\u05D8\u05E0\u05D9 \u05E7\u05D9\u05E5", 595, 213, 11, 108, RED, 6, 2.04, 0, 80);
|
|
3408
|
+
shape("\u05E0\u05E7\u05D5\u05D3\u05EA \u05D2\u05D9\u05DC\u05D5\u05D9 \u05E7\u05D9\u05E5", 569, 179, 63, 63, RED, 32, 2.18, 0, 70);
|
|
3409
|
+
return true;
|
|
3410
|
+
}
|
|
3411
|
+
function carUpgradeStoryboard(ctx) {
|
|
3412
|
+
if (ctx.theme !== "car-garage" || ctx.index > 2) return false;
|
|
3413
|
+
const end = ctx.scene.duration - 0.02;
|
|
3414
|
+
const set = (item, frames) => {
|
|
3415
|
+
item.keyframes = frames;
|
|
3416
|
+
return item;
|
|
3417
|
+
};
|
|
3418
|
+
const arrive = (delay, dx = 0, dy = 0) => [
|
|
3419
|
+
point(0, dx, dy, 0.9, 0.9, 0, 0),
|
|
3420
|
+
point(delay, dx, dy, 0.9, 0.9, 0, 0),
|
|
3421
|
+
point(delay + 0.38, 0, 0),
|
|
3422
|
+
point(Math.max(delay + 0.45, end - 0.4), 0, -5, 1.02, 1.02),
|
|
3423
|
+
point(end, 0, 0)
|
|
3424
|
+
];
|
|
3425
|
+
const shape = (name, x, y, w, h, color, radius, delay, dx = 0, dy = 0) => set(box(ctx, name, x, y, w, h, color, radius, delay), arrive(delay, dx, dy));
|
|
3426
|
+
const word = (name, value, x, y, w, h, size, color, delay) => set(caption(ctx, name, value, x, y, w, h, size, color, delay), arrive(delay, 0, 35));
|
|
3427
|
+
if (ctx.index === 0) {
|
|
3428
|
+
shape("\u05D4\u05D9\u05DC\u05D4 \u05DE\u05D5\u05E1\u05DA", 62, 74, 640, 610, "#AF0037", 305, 0.04);
|
|
3429
|
+
shape("\u05E7\u05D9\u05E8 \u05DE\u05D5\u05E1\u05DA", 81, 140, 598, 463, WHITE, 21, 0.11, 0, 120);
|
|
3430
|
+
shape("\u05E4\u05EA\u05D7 \u05DE\u05D5\u05E1\u05DA \u05DB\u05D4\u05D4", 118, 180, 521, 369, NAVY, 12, 0.24, 0, 120);
|
|
3431
|
+
for (let i = 0; i < 5; i++) {
|
|
3432
|
+
const shutter = box(ctx, `\u05EA\u05E8\u05D9\u05E1 \u05DE\u05D5\u05E1\u05DA ${i + 1}`, 127, 188 + i * 57, 502, 52, "#E6AFBF", 3, 0.27);
|
|
3433
|
+
set(shutter, [point(0, 0, 0), point(0.48, 0, 0), point(1.05 + i * 0.11, 0, -205 - i * 12, 1, 0.2, 0, 0), point(end, 0, -230, 1, 0.2, 0, 0)]);
|
|
3434
|
+
}
|
|
3435
|
+
shape("\u05E8\u05E6\u05E4\u05EA \u05DE\u05D5\u05E1\u05DA", 94, 550, 580, 23, "#DCA9B8", 11, 0.3, -170);
|
|
3436
|
+
const body = shape("\u05D2\u05D5\u05E3 \u05E8\u05DB\u05D1 \u05DE\u05E9\u05D5\u05D3\u05E8\u05D2", 154, 419, 470, 106, RED, 50, 1.08, -470);
|
|
3437
|
+
set(body, [point(0, -470, 0, 1, 1, 0, 0), point(1.08, -470, 0, 1, 1, 0, 0), point(1.77, 0, 0), point(end, 40, 0)]);
|
|
3438
|
+
shape("\u05D2\u05D2 \u05E8\u05DB\u05D1 \u05DE\u05E9\u05D5\u05D3\u05E8\u05D2", 244, 360, 276, 79, "#F0678B", 48, 1.15, -470);
|
|
3439
|
+
shape("\u05D7\u05DC\u05D5\u05DF \u05E7\u05D3\u05DE\u05D9 \u05E8\u05DB\u05D1", 407, 370, 94, 61, PALE, 20, 1.39, -470);
|
|
3440
|
+
shape("\u05D7\u05DC\u05D5\u05DF \u05D0\u05D7\u05D5\u05E8\u05D9 \u05E8\u05DB\u05D1", 264, 370, 119, 61, PALE, 20, 1.47, -470);
|
|
3441
|
+
[231, 505].forEach((x, i) => {
|
|
3442
|
+
const wheel = shape(`\u05D2\u05DC\u05D2\u05DC \u05DE\u05E9\u05D5\u05D3\u05E8\u05D2 ${i + 1}`, x, 491, 80, 80, NAVY, 40, 1.35 + i * 0.07, -470);
|
|
3443
|
+
set(wheel, [
|
|
3444
|
+
point(0, -470, 0, 1, 1, 0, 0),
|
|
3445
|
+
point(1.35 + i * 0.07, -470, 0, 1, 1, 0, 0),
|
|
3446
|
+
point(1.89, 0, 0, 1, 1, 390),
|
|
3447
|
+
point(end, 40, 0, 1, 1, 720)
|
|
3448
|
+
]);
|
|
3449
|
+
shape(`\u05D8\u05D1\u05D5\u05E8 \u05D2\u05DC\u05D2\u05DC ${i + 1}`, x + 28, 519, 24, 24, WHITE, 12, 1.62 + i * 0.07, -470);
|
|
3450
|
+
});
|
|
3451
|
+
shape("\u05E4\u05E0\u05E1 \u05E8\u05DB\u05D1 \u05DE\u05E9\u05D5\u05D3\u05E8\u05D2", 585, 450, 44, 17, WHITE, 8, 1.62, -470);
|
|
3452
|
+
return true;
|
|
3453
|
+
}
|
|
3454
|
+
if (ctx.index === 1) {
|
|
3455
|
+
shape("\u05E6\u05DC \u05DC\u05D5\u05D7 \u05E6\u05E8\u05DB\u05D9\u05DD", 72, 88, 650, 571, "#E9C5D0", 30, 0.07, 0, 140);
|
|
3456
|
+
shape("\u05DC\u05D5\u05D7 \u05E6\u05E8\u05DB\u05D9\u05DD", 59, 75, 650, 571, WHITE, 30, 0.15, 0, 140);
|
|
3457
|
+
word("\u05DB\u05D5\u05EA\u05E8\u05EA \u05E6\u05E8\u05DB\u05D9 \u05E8\u05DB\u05D1", "\u05DE\u05EA\u05D0\u05D9\u05DE\u05D9\u05DD \u05DC\u05D7\u05D9\u05D9\u05DD", 103, 113, 557, 74, 44, NAVY, 0.46);
|
|
3458
|
+
const needs = [
|
|
3459
|
+
{ name: "\u05DE\u05E8\u05D5\u05D5\u05D7", x: 104, y: 230, width: 248, color: "#FFE1E9" },
|
|
3460
|
+
{ name: "\u05E0\u05D5\u05D7\u05D5\u05EA", x: 405, y: 230, width: 248, color: "#F7CED9" },
|
|
3461
|
+
{ name: "\u05D7\u05D9\u05E1\u05DB\u05D5\u05DF", x: 104, y: 406, width: 248, color: "#F7CED9" },
|
|
3462
|
+
{ name: "\u05D9\u05D5\u05DE\u05D9\u05D5\u05DD", x: 405, y: 406, width: 248, color: "#FFE1E9" }
|
|
3463
|
+
];
|
|
3464
|
+
needs.forEach((need, i) => {
|
|
3465
|
+
const delay = 0.67 + i * 0.38;
|
|
3466
|
+
shape(`\u05DB\u05E8\u05D8\u05D9\u05E1 ${need.name}`, need.x, need.y, need.width, 140, need.color, 22, delay, i % 2 ? 180 : -180);
|
|
3467
|
+
shape(`\u05E1\u05DE\u05DF ${need.name}`, need.x + 20, need.y + 30, 35, 35, i === 1 ? RED : "#D798AB", 18, delay + 0.1);
|
|
3468
|
+
word(`\u05E9\u05DD \u05E6\u05D5\u05E8\u05DA ${need.name}`, need.name, need.x + 65, need.y + 26, need.width - 88, 74, 36, NAVY, delay + 0.19);
|
|
3469
|
+
shape(`\u05E7\u05D5 ${need.name}`, need.x + 30, need.y + 108, need.width - 60, 8, i === 1 ? RED : "#D4A5B2", 4, delay + 0.26);
|
|
3470
|
+
});
|
|
3471
|
+
return true;
|
|
3472
|
+
}
|
|
3473
|
+
shape("\u05E6\u05DC \u05D4\u05E9\u05D5\u05D5\u05D0\u05EA \u05E8\u05DB\u05D1", 73, 91, 649, 561, "#AF0037", 30, 0.07, 0, 135);
|
|
3474
|
+
shape("\u05DC\u05D5\u05D7 \u05D4\u05E9\u05D5\u05D5\u05D0\u05EA \u05E8\u05DB\u05D1", 60, 78, 649, 561, WHITE, 30, 0.15, 0, 135);
|
|
3475
|
+
word("\u05DB\u05D5\u05EA\u05E8\u05EA \u05D4\u05E9\u05D5\u05D5\u05D0\u05EA \u05E8\u05DB\u05D1", "\u05DE\u05E1\u05EA\u05DB\u05DC\u05D9\u05DD \u05E2\u05DC \u05D4\u05DB\u05D5\u05DC", 104, 111, 556, 75, 44, NAVY, 0.49);
|
|
3476
|
+
["\u05E8\u05DB\u05D9\u05E9\u05D4", "\u05EA\u05D7\u05D6\u05D5\u05E7\u05D4", "\u05DE\u05D9\u05DE\u05D5\u05DF"].forEach((name, i) => {
|
|
3477
|
+
const y = 231 + i * 121;
|
|
3478
|
+
const delay = 0.72 + i * 0.55;
|
|
3479
|
+
shape(`\u05E8\u05E7\u05E2 \u05E9\u05D9\u05E7\u05D5\u05DC ${name}`, 101, y, 563, 92, i === 1 ? "#F9D2DD" : PALE, 18, delay, 0, 97);
|
|
3480
|
+
word(`\u05E9\u05DD \u05E9\u05D9\u05E7\u05D5\u05DC ${name}`, name, 128, y + 10, 162, 67, 35, NAVY, delay + 0.17);
|
|
3481
|
+
shape(`\u05DE\u05E1\u05DC\u05D5\u05DC \u05E9\u05D9\u05E7\u05D5\u05DC ${name}`, 318, y + 36, 299, 20, "#DDB5C0", 10, delay + 0.15);
|
|
3482
|
+
const width = [184, 236, 151][i];
|
|
3483
|
+
const fill = box(ctx, `\u05DE\u05D7\u05D5\u05D5\u05DF \u05E9\u05D9\u05E7\u05D5\u05DC ${name}`, 318, y + 36, width, 20, RED, 10, delay + 0.23);
|
|
3484
|
+
set(fill, [
|
|
3485
|
+
point(0, -width / 2, 0, 0.02, 1, 0, 0),
|
|
3486
|
+
point(delay + 0.23, -width / 2, 0, 0.02, 1, 0, 0),
|
|
3487
|
+
point(delay + 0.73, 0, 0),
|
|
3488
|
+
point(end, 5, 0)
|
|
3489
|
+
]);
|
|
3490
|
+
});
|
|
3491
|
+
word("\u05D4\u05E2\u05E8\u05EA \u05D4\u05E9\u05D5\u05D5\u05D0\u05EA \u05E8\u05DB\u05D1", "\u05D1\u05D5\u05D7\u05E8\u05D9\u05DD \u05DC\u05E4\u05D9 \u05D4\u05E6\u05E8\u05DB\u05D9\u05DD", 111, 591, 535, 42, 26, RED, 2.74);
|
|
3492
|
+
return true;
|
|
3493
|
+
}
|
|
3494
|
+
function weddingStoryboard(ctx) {
|
|
3495
|
+
if (ctx.theme !== "wedding-rings" || ctx.index > 3) return false;
|
|
3496
|
+
const end = ctx.scene.duration - 0.02;
|
|
3497
|
+
const set = (item, frames) => {
|
|
3498
|
+
item.keyframes = frames;
|
|
3499
|
+
return item;
|
|
3500
|
+
};
|
|
3501
|
+
const arrive = (delay, dx = 0, dy = 0) => [
|
|
3502
|
+
point(0, dx, dy, 0.9, 0.9, 0, 0),
|
|
3503
|
+
point(delay, dx, dy, 0.9, 0.9, 0, 0),
|
|
3504
|
+
point(delay + 0.39, 0, 0),
|
|
3505
|
+
point(Math.max(delay + 0.45, end - 0.42), 0, -6, 1.025, 1.025),
|
|
3506
|
+
point(end, 0, 0)
|
|
3507
|
+
];
|
|
3508
|
+
const shape = (name, x, y, w, h, color, radius, delay, dx = 0, dy = 0) => set(box(ctx, name, x, y, w, h, color, radius, delay), arrive(delay, dx, dy));
|
|
3509
|
+
const word = (name, value, x, y, w, h, size, color, delay) => set(caption(ctx, name, value, x, y, w, h, size, color, delay), arrive(delay, 0, 36));
|
|
3510
|
+
if (ctx.index === 0) {
|
|
3511
|
+
shape("\u05D4\u05D9\u05DC\u05D4 \u05D4\u05D6\u05DE\u05E0\u05D4", 58, 52, 640, 640, "#B8003C", 320, 0.04);
|
|
3512
|
+
shape("\u05E6\u05DC \u05E0\u05D9\u05D9\u05E8 \u05D4\u05D6\u05DE\u05E0\u05D4", 133, 105, 506, 548, "#A30034", 30, 0.13, 0, 135);
|
|
3513
|
+
shape("\u05E0\u05D9\u05D9\u05E8 \u05D4\u05D6\u05DE\u05E0\u05D4", 117, 88, 506, 548, WHITE, 30, 0.22, 0, 135);
|
|
3514
|
+
shape("\u05D8\u05D1\u05E2\u05EA \u05D4\u05D6\u05DE\u05E0\u05D4 \u05E8\u05D0\u05E9\u05D5\u05E0\u05D4", 234, 133, 145, 145, RED, 73, 0.42, -120);
|
|
3515
|
+
shape("\u05D7\u05DC\u05DC \u05D8\u05D1\u05E2\u05EA \u05D4\u05D6\u05DE\u05E0\u05D4 \u05E8\u05D0\u05E9\u05D5\u05E0\u05D4", 260, 159, 93, 93, WHITE, 47, 0.5, -120);
|
|
3516
|
+
shape("\u05D8\u05D1\u05E2\u05EA \u05D4\u05D6\u05DE\u05E0\u05D4 \u05E9\u05E0\u05D9\u05D9\u05D4", 337, 133, 145, 145, "#F37899", 73, 0.59, 120);
|
|
3517
|
+
shape("\u05D7\u05DC\u05DC \u05D8\u05D1\u05E2\u05EA \u05D4\u05D6\u05DE\u05E0\u05D4 \u05E9\u05E0\u05D9\u05D9\u05D4", 363, 159, 93, 93, WHITE, 47, 0.67, 120);
|
|
3518
|
+
word("\u05DB\u05D5\u05EA\u05E8\u05EA \u05E8\u05E9\u05D9\u05DE\u05EA \u05D7\u05EA\u05D5\u05E0\u05D4", "\u05DE\u05EA\u05D7\u05D9\u05DC\u05D9\u05DD \u05DC\u05EA\u05DB\u05E0\u05DF", 165, 305, 417, 79, 43, NAVY, 0.86);
|
|
3519
|
+
["\u05EA\u05D0\u05E8\u05D9\u05DA", "\u05DE\u05E7\u05D5\u05DD", "\u05D0\u05E0\u05E9\u05D9\u05DD"].forEach((label, i) => {
|
|
3520
|
+
const y = 416 + i * 62;
|
|
3521
|
+
const delay = 1.11 + i * 0.4;
|
|
3522
|
+
shape(`\u05E1\u05D9\u05DE\u05D5\u05DF \u05E8\u05E9\u05D9\u05DE\u05D4 ${i + 1}`, 192, y + 12, 24, 24, i === 2 ? RED : "#DDA6B6", 12, delay, -80);
|
|
3523
|
+
word(`\u05E4\u05E8\u05D9\u05D8 \u05E8\u05E9\u05D9\u05DE\u05D4 ${i + 1}`, label, 237, y, 265, 49, 30, NAVY, delay + 0.12);
|
|
3524
|
+
shape(`\u05E7\u05D5 \u05E8\u05E9\u05D9\u05DE\u05D4 ${i + 1}`, 510, y + 27, 69, 7, "#DEBAC5", 4, delay + 0.22);
|
|
3525
|
+
});
|
|
3526
|
+
return true;
|
|
3527
|
+
}
|
|
3528
|
+
if (ctx.index === 1) {
|
|
3529
|
+
shape("\u05E6\u05DC \u05E1\u05D3\u05E8 \u05E2\u05D3\u05D9\u05E4\u05D5\u05D9\u05D5\u05EA", 77, 91, 630, 553, "#E3BCC8", 29, 0.08, 0, 133);
|
|
3530
|
+
shape("\u05DC\u05D5\u05D7 \u05E1\u05D3\u05E8 \u05E2\u05D3\u05D9\u05E4\u05D5\u05D9\u05D5\u05EA", 61, 76, 630, 553, WHITE, 29, 0.16, 0, 133);
|
|
3531
|
+
word("\u05DB\u05D5\u05EA\u05E8\u05EA \u05E1\u05D3\u05E8 \u05E2\u05D3\u05D9\u05E4\u05D5\u05D9\u05D5\u05EA", "\u05DE\u05D4 \u05D4\u05DB\u05D9 \u05D7\u05E9\u05D5\u05D1?", 107, 106, 539, 74, 45, NAVY, 0.51);
|
|
3532
|
+
["\u05DE\u05E7\u05D5\u05DD", "\u05D0\u05E0\u05E9\u05D9\u05DD", "\u05D7\u05D5\u05D5\u05D9\u05D4"].forEach((label, i) => {
|
|
3533
|
+
const y = 206 + i * 128;
|
|
3534
|
+
const delay = 0.74 + i * 0.61;
|
|
3535
|
+
shape(`\u05DB\u05E8\u05D8\u05D9\u05E1 \u05D7\u05EA\u05D5\u05E0\u05D4 ${label}`, 102, y, 547, 99, i === 1 ? "#F8D2DD" : PALE, 20, delay, i % 2 ? 180 : -180);
|
|
3536
|
+
shape(`\u05E2\u05D9\u05D2\u05D5\u05DC ${label}`, 123, y + 20, 60, 60, i === 1 ? RED : "#DFA6B7", 30, delay + 0.11, 0, 65);
|
|
3537
|
+
word(`\u05E9\u05DD \u05E2\u05D3\u05D9\u05E4\u05D5\u05EA ${label}`, label, 209, y + 12, 336, 74, 39, NAVY, delay + 0.25);
|
|
3538
|
+
shape(`\u05E4\u05E1 \u05E2\u05D3\u05D9\u05E4\u05D5\u05EA ${label}`, 573, y + 43, 47, 11, i === 1 ? RED : "#D2A6B2", 6, delay + 0.33);
|
|
3539
|
+
});
|
|
3540
|
+
word("\u05D4\u05E2\u05E8\u05EA \u05E1\u05D3\u05E8 \u05E2\u05D3\u05D9\u05E4\u05D5\u05D9\u05D5\u05EA", "\u05D4\u05D1\u05D7\u05D9\u05E8\u05D4 \u05E9\u05DC\u05DB\u05DD", 117, 583, 516, 46, 26, RED, 2.65);
|
|
3541
|
+
return true;
|
|
3542
|
+
}
|
|
3543
|
+
if (ctx.index === 2) {
|
|
3544
|
+
shape("\u05E6\u05DC \u05DE\u05E1\u05D2\u05E8\u05EA \u05D7\u05EA\u05D5\u05E0\u05D4", 76, 93, 629, 558, "#A80036", 29, 0.07, 0, 137);
|
|
3545
|
+
shape("\u05DC\u05D5\u05D7 \u05DE\u05E1\u05D2\u05E8\u05EA \u05D7\u05EA\u05D5\u05E0\u05D4", 62, 77, 629, 558, WHITE, 29, 0.15, 0, 137);
|
|
3546
|
+
word("\u05DB\u05D5\u05EA\u05E8\u05EA \u05DE\u05E1\u05D2\u05E8\u05EA \u05D7\u05EA\u05D5\u05E0\u05D4", "\u05DE\u05EA\u05DB\u05E0\u05E0\u05D9\u05DD \u05DE\u05E1\u05D2\u05E8\u05EA", 105, 109, 546, 78, 44, NAVY, 0.47);
|
|
3547
|
+
["\u05DE\u05E7\u05D5\u05DD", "\u05D0\u05D9\u05E8\u05D5\u05D7", "\u05DE\u05E8\u05D5\u05D5\u05D7"].forEach((label, i) => {
|
|
3548
|
+
const y = 230 + i * 121;
|
|
3549
|
+
const delay = 0.7 + i * 0.58;
|
|
3550
|
+
shape(`\u05E9\u05D5\u05E8\u05EA \u05EA\u05E7\u05E6\u05D9\u05D1 ${label}`, 103, y, 545, 88, i === 1 ? "#F9D4DE" : PALE, 18, delay, 0, 95);
|
|
3551
|
+
word(`\u05E9\u05DD \u05EA\u05E7\u05E6\u05D9\u05D1 ${label}`, label, 119, y + 11, 150, 66, 33, NAVY, delay + 0.15);
|
|
3552
|
+
shape(`\u05DE\u05E1\u05DC\u05D5\u05DC \u05EA\u05E7\u05E6\u05D9\u05D1 ${label}`, 297, y + 34, 305, 20, "#DAB2BE", 10, delay + 0.17);
|
|
3553
|
+
const width = [218, 174, 247][i];
|
|
3554
|
+
const fill = box(ctx, `\u05DE\u05D7\u05D5\u05D5\u05DF \u05EA\u05E7\u05E6\u05D9\u05D1 ${label}`, 297, y + 34, width, 20, RED, 10, delay + 0.24);
|
|
3555
|
+
set(fill, [
|
|
3556
|
+
point(0, -width / 2, 0, 0.02, 1, 0, 0),
|
|
3557
|
+
point(delay + 0.24, -width / 2, 0, 0.02, 1, 0, 0),
|
|
3558
|
+
point(delay + 0.75, 0, 0),
|
|
3559
|
+
point(end, 5, 0)
|
|
3560
|
+
]);
|
|
3561
|
+
});
|
|
3562
|
+
word("\u05D4\u05E2\u05E8\u05EA \u05DE\u05E1\u05D2\u05E8\u05EA \u05D7\u05EA\u05D5\u05E0\u05D4", "\u05DC\u05DC\u05D0 \u05E1\u05DB\u05D5\u05DE\u05D9\u05DD \u05DE\u05D5\u05DB\u05EA\u05D1\u05D9\u05DD", 120, 591, 520, 44, 25, RED, 2.88);
|
|
3563
|
+
return true;
|
|
3564
|
+
}
|
|
3565
|
+
shape("\u05E8\u05E7\u05E2 \u05D9\u05D5\u05DD \u05D7\u05EA\u05D5\u05E0\u05D4", 64, 85, 630, 568, "#FFE4EC", 29, 0.1, 0, 130);
|
|
3566
|
+
word("\u05DB\u05D5\u05EA\u05E8\u05EA \u05D9\u05D5\u05DD \u05D2\u05DE\u05D9\u05E9", "\u05D9\u05E9 \u05DE\u05E7\u05D5\u05DD \u05D2\u05DD \u05DC\u05E9\u05D9\u05E0\u05D5\u05D9", 112, 112, 538, 73, 43, NAVY, 0.53);
|
|
3567
|
+
shape("\u05E7\u05D5 \u05D6\u05DE\u05DF \u05D7\u05EA\u05D5\u05E0\u05D4", 143, 365, 473, 15, NAVY, 8, 0.74, -300);
|
|
3568
|
+
["\u05DE\u05EA\u05DB\u05E0\u05E0\u05D9\u05DD", "\u05E0\u05D4\u05E0\u05D9\u05DD", "\u05DE\u05E4\u05EA\u05D9\u05E2\u05D9\u05DD"].forEach((label, i) => {
|
|
3569
|
+
const x = 107 + i * 210;
|
|
3570
|
+
const delay = 0.96 + i * 0.59;
|
|
3571
|
+
shape(`\u05EA\u05D7\u05E0\u05D4 ${label}`, x, 316, 111, 111, i === 2 ? RED : WHITE, 56, delay, 0, 135);
|
|
3572
|
+
shape(`\u05DE\u05E8\u05DB\u05D6 \u05EA\u05D7\u05E0\u05D4 ${label}`, x + 29, 345, 53, 53, i === 2 ? WHITE : RED, 27, delay + 0.14, 0, 105);
|
|
3573
|
+
word(`\u05E9\u05DD \u05EA\u05D7\u05E0\u05D4 ${label}`, label, x - 12, 463, 139, 67, 30, NAVY, delay + 0.24);
|
|
3574
|
+
});
|
|
3575
|
+
for (let i = 0; i < 7; i++) {
|
|
3576
|
+
const x = 120 + i * 86;
|
|
3577
|
+
shape(
|
|
3578
|
+
`\u05E0\u05D9\u05E6\u05D5\u05E5 \u05D7\u05EA\u05D5\u05E0\u05D4 ${i + 1}`,
|
|
3579
|
+
x,
|
|
3580
|
+
220 + i % 3 * 17,
|
|
3581
|
+
14,
|
|
3582
|
+
14,
|
|
3583
|
+
i % 2 ? RED : "#E387A2",
|
|
3584
|
+
7,
|
|
3585
|
+
1.71 + i * 0.12,
|
|
3586
|
+
0,
|
|
3587
|
+
-85
|
|
3588
|
+
);
|
|
3589
|
+
}
|
|
3590
|
+
return true;
|
|
3591
|
+
}
|
|
3592
|
+
function shareStoryboard(ctx) {
|
|
3593
|
+
if (ctx.theme !== "share-mosaic" || ctx.index > 2) return false;
|
|
3594
|
+
const end = ctx.scene.duration - 0.02;
|
|
3595
|
+
const set = (item, frames) => {
|
|
3596
|
+
item.keyframes = frames;
|
|
3597
|
+
return item;
|
|
3598
|
+
};
|
|
3599
|
+
const arrive = (delay, dx = 0, dy = 0) => [
|
|
3600
|
+
point(0, dx, dy, 0.88, 0.88, 0, 0),
|
|
3601
|
+
point(delay, dx, dy, 0.88, 0.88, 0, 0),
|
|
3602
|
+
point(delay + 0.36, 0, 0),
|
|
3603
|
+
point(Math.max(delay + 0.4, end - 0.4), 0, -8, 1.025, 1.025),
|
|
3604
|
+
point(end, 0, 0)
|
|
3605
|
+
];
|
|
3606
|
+
const shape = (name, x, y, w, h, color, radius, delay, dx = 0, dy = 0) => set(box(ctx, name, x, y, w, h, color, radius, delay), arrive(delay, dx, dy));
|
|
3607
|
+
const word = (name, value, x, y, w, h, size, color, delay) => set(caption(ctx, name, value, x, y, w, h, size, color, delay), arrive(delay, 0, 42));
|
|
3608
|
+
if (ctx.index === 0) {
|
|
3609
|
+
shape("\u05E6\u05DC \u05D1\u05E0\u05D9\u05D9\u05DF \u05D7\u05D1\u05E8\u05D4", 113, 165, 536, 470, "#A80036", 28, 0.05, 0, 120);
|
|
3610
|
+
shape("\u05D1\u05E0\u05D9\u05D9\u05DF \u05D7\u05D1\u05E8\u05D4", 94, 144, 536, 470, WHITE, 28, 0.14, 0, 120);
|
|
3611
|
+
shape("\u05D2\u05D2 \u05D7\u05D1\u05E8\u05D4", 94, 144, 536, 69, RED, 27, 0.25, 0, -80);
|
|
3612
|
+
for (let row = 0; row < 3; row++) for (let col = 0; col < 4; col++) {
|
|
3613
|
+
const i = row * 4 + col;
|
|
3614
|
+
shape(
|
|
3615
|
+
`\u05D7\u05DC\u05E7 \u05D7\u05D1\u05E8\u05D4 ${i + 1}`,
|
|
3616
|
+
122 + col * 127,
|
|
3617
|
+
243 + row * 111,
|
|
3618
|
+
101,
|
|
3619
|
+
86,
|
|
3620
|
+
i === 6 ? RED : "#F7D4DE",
|
|
3621
|
+
16,
|
|
3622
|
+
0.43 + i * 0.135,
|
|
3623
|
+
col % 2 ? 110 : -110,
|
|
3624
|
+
64
|
|
3625
|
+
);
|
|
3626
|
+
}
|
|
3627
|
+
word("\u05D7\u05DC\u05E7 \u05D1\u05D1\u05E2\u05DC\u05D5\u05EA", "\u05D7\u05DC\u05E7", 382, 379, 102, 56, 31, WHITE, 1.44);
|
|
3628
|
+
shape("\u05E7\u05D5 \u05D7\u05DC\u05E7 \u05D1\u05D1\u05E2\u05DC\u05D5\u05EA", 453, 540, 123, 11, RED, 6, 2.1, -110);
|
|
3629
|
+
return true;
|
|
3630
|
+
}
|
|
3631
|
+
if (ctx.index === 1) {
|
|
3632
|
+
shape("\u05DC\u05D5\u05D7 \u05D7\u05D1\u05E8\u05D4 \u05DE\u05E9\u05D5\u05EA\u05E4\u05EA", 83, 93, 612, 542, WHITE, 30, 0.08, 0, 130);
|
|
3633
|
+
word("\u05DB\u05D5\u05EA\u05E8\u05EA \u05DC\u05D5\u05D7 \u05D1\u05E2\u05DC\u05D5\u05EA", "\u05D7\u05D1\u05E8\u05D4", 188, 119, 404, 68, 45, NAVY, 0.4);
|
|
3634
|
+
const colors = [RED, "#F7A7BA", "#D52C57", "#E8BDC9"];
|
|
3635
|
+
for (let i = 0; i < 4; i++) {
|
|
3636
|
+
const x = 130 + i * 137;
|
|
3637
|
+
const delay = 0.74 + i * 0.35;
|
|
3638
|
+
shape(`\u05D8\u05D5\u05E8 \u05D7\u05DC\u05E7\u05D9\u05DD ${i + 1}`, x, 244, 108, 234, colors[i], 18, delay, 0, 190);
|
|
3639
|
+
shape(
|
|
3640
|
+
`\u05E1\u05D9\u05DE\u05D5\u05DF \u05D1\u05E2\u05DC\u05D5\u05EA ${i + 1}`,
|
|
3641
|
+
x + 35,
|
|
3642
|
+
505,
|
|
3643
|
+
38,
|
|
3644
|
+
38,
|
|
3645
|
+
i === 0 ? RED : "#DFA6B7",
|
|
3646
|
+
19,
|
|
3647
|
+
delay + 0.18,
|
|
3648
|
+
0,
|
|
3649
|
+
70
|
|
3650
|
+
);
|
|
3651
|
+
}
|
|
3652
|
+
shape("\u05E7\u05D5 \u05D4\u05D3\u05D2\u05E9\u05EA \u05D7\u05DC\u05E7", 127, 590, 520, 9, "#EBC6D0", 5, 2, -320);
|
|
3653
|
+
shape("\u05DE\u05E7\u05D8\u05E2 \u05D4\u05D3\u05D2\u05E9\u05EA \u05D7\u05DC\u05E7", 127, 590, 108, 9, RED, 5, 2.25, -108);
|
|
3654
|
+
return true;
|
|
3655
|
+
}
|
|
3656
|
+
if (ctx.index === 2) {
|
|
3657
|
+
shape("\u05DB\u05E8\u05D8\u05D9\u05E1 \u05D1\u05D3\u05D9\u05E7\u05EA \u05D4\u05D7\u05DC\u05D8\u05D4", 70, 83, 637, 560, WHITE, 30, 0.08, 0, 130);
|
|
3658
|
+
word("\u05DB\u05D5\u05EA\u05E8\u05EA \u05D1\u05D3\u05D9\u05E7\u05EA \u05D4\u05D7\u05DC\u05D8\u05D4", "\u05DC\u05E4\u05E0\u05D9 \u05E9\u05DE\u05D7\u05DC\u05D9\u05D8\u05D9\u05DD", 128, 110, 520, 79, 43, NAVY, 0.43);
|
|
3659
|
+
const labels = ["\u05DE\u05D8\u05E8\u05D4", "\u05DE\u05D9\u05D3\u05E2", "\u05E1\u05D9\u05DB\u05D5\u05DF"];
|
|
3660
|
+
labels.forEach((label, i) => {
|
|
3661
|
+
const y = 216 + i * 128, delay = 0.67 + i * 0.6;
|
|
3662
|
+
shape(
|
|
3663
|
+
`\u05E8\u05E6\u05D5\u05E2\u05EA \u05D1\u05D3\u05D9\u05E7\u05D4 ${label}`,
|
|
3664
|
+
113,
|
|
3665
|
+
y,
|
|
3666
|
+
555,
|
|
3667
|
+
95,
|
|
3668
|
+
i === 2 ? "#F9D5DF" : PALE,
|
|
3669
|
+
20,
|
|
3670
|
+
delay,
|
|
3671
|
+
i % 2 ? 180 : -180
|
|
3672
|
+
);
|
|
3673
|
+
shape(
|
|
3674
|
+
`\u05E0\u05E7\u05D5\u05D3\u05EA \u05D1\u05D3\u05D9\u05E7\u05D4 ${label}`,
|
|
3675
|
+
135,
|
|
3676
|
+
y + 21,
|
|
3677
|
+
54,
|
|
3678
|
+
54,
|
|
3679
|
+
i === 2 ? RED : "#DFA0B2",
|
|
3680
|
+
27,
|
|
3681
|
+
delay + 0.13,
|
|
3682
|
+
0,
|
|
3683
|
+
85
|
|
3684
|
+
);
|
|
3685
|
+
word(`\u05E9\u05DD \u05D1\u05D3\u05D9\u05E7\u05D4 ${label}`, label, 214, y + 12, 330, 71, 37, NAVY, delay + 0.26);
|
|
3686
|
+
shape(
|
|
3687
|
+
`\u05E4\u05E1 \u05D1\u05D3\u05D9\u05E7\u05D4 ${label}`,
|
|
3688
|
+
578,
|
|
3689
|
+
y + 43,
|
|
3690
|
+
61,
|
|
3691
|
+
10,
|
|
3692
|
+
i === 2 ? RED : "#D8A3B1",
|
|
3693
|
+
5,
|
|
3694
|
+
delay + 0.34,
|
|
3695
|
+
-80
|
|
3696
|
+
);
|
|
3697
|
+
});
|
|
3698
|
+
return true;
|
|
3699
|
+
}
|
|
3700
|
+
return false;
|
|
3701
|
+
}
|
|
3702
|
+
function fraudStoryboard(ctx) {
|
|
3703
|
+
if (ctx.theme !== "fraud-alert" || ctx.index > 3) return false;
|
|
3704
|
+
const end = ctx.scene.duration - 0.02;
|
|
3705
|
+
const set = (item, frames) => {
|
|
3706
|
+
item.keyframes = frames;
|
|
3707
|
+
return item;
|
|
3708
|
+
};
|
|
3709
|
+
const arrive = (delay, dx = 0, dy = 0) => [
|
|
3710
|
+
point(0, dx, dy, 0.88, 0.88, 0, 0),
|
|
3711
|
+
point(delay, dx, dy, 0.88, 0.88, 0, 0),
|
|
3712
|
+
point(delay + 0.36, 0, 0),
|
|
3713
|
+
point(Math.max(delay + 0.4, end - 0.43), 0, -7, 1.025, 1.025),
|
|
3714
|
+
point(end, 0, 0)
|
|
3715
|
+
];
|
|
3716
|
+
const shape = (name, x, y, w, h, color, radius, delay, dx = 0, dy = 0) => set(box(ctx, name, x, y, w, h, color, radius, delay), arrive(delay, dx, dy));
|
|
3717
|
+
const word = (name, value, x, y, w, h, size, color, delay) => set(caption(ctx, name, value, x, y, w, h, size, color, delay), arrive(delay, 0, 42));
|
|
3718
|
+
if (ctx.index === 0) {
|
|
3719
|
+
shape("\u05E6\u05DC \u05D8\u05DC\u05E4\u05D5\u05DF \u05D0\u05D6\u05D4\u05E8\u05D4", 174, 85, 434, 615, "#A50034", 45, 0.05, 0, 140);
|
|
3720
|
+
shape("\u05D2\u05D5\u05E3 \u05D8\u05DC\u05E4\u05D5\u05DF \u05D0\u05D6\u05D4\u05E8\u05D4", 158, 68, 434, 615, NAVY, 45, 0.13, 0, 140);
|
|
3721
|
+
shape("\u05DE\u05E1\u05DA \u05D8\u05DC\u05E4\u05D5\u05DF \u05D0\u05D6\u05D4\u05E8\u05D4", 180, 96, 390, 558, WHITE, 29, 0.23, 0, 140);
|
|
3722
|
+
shape("\u05E4\u05E1 \u05DE\u05E6\u05D1 \u05D1\u05D8\u05DC\u05E4\u05D5\u05DF", 304, 107, 144, 13, NAVY, 7, 0.31, 0, 100);
|
|
3723
|
+
word("\u05DB\u05D5\u05EA\u05E8\u05EA \u05D4\u05D5\u05D3\u05E2\u05D5\u05EA", "\u05D4\u05D5\u05D3\u05E2\u05D5\u05EA", 229, 155, 300, 59, 39, NAVY, 0.42);
|
|
3724
|
+
["\u05D4\u05D5\u05D3\u05E2\u05D4 \u05D7\u05D3\u05E9\u05D4", "\u05DC\u05E4\u05E2\u05D5\u05DC \u05DE\u05D9\u05D3"].forEach((label, i) => {
|
|
3725
|
+
const y = 257 + i * 134, delay = 0.72 + i * 0.6;
|
|
3726
|
+
shape(
|
|
3727
|
+
`\u05D4\u05D5\u05D3\u05E2\u05D4 \u05D7\u05E9\u05D5\u05D3\u05D4 ${i + 1}`,
|
|
3728
|
+
207,
|
|
3729
|
+
y,
|
|
3730
|
+
335,
|
|
3731
|
+
108,
|
|
3732
|
+
i ? "#FFD9E4" : PALE,
|
|
3733
|
+
20,
|
|
3734
|
+
delay,
|
|
3735
|
+
i ? 240 : -240
|
|
3736
|
+
);
|
|
3737
|
+
shape(
|
|
3738
|
+
`\u05E0\u05E7\u05D5\u05D3\u05EA \u05D4\u05D5\u05D3\u05E2\u05D4 ${i + 1}`,
|
|
3739
|
+
224,
|
|
3740
|
+
y + 29,
|
|
3741
|
+
49,
|
|
3742
|
+
49,
|
|
3743
|
+
i ? RED : "#DF9EB1",
|
|
3744
|
+
25,
|
|
3745
|
+
delay + 0.12,
|
|
3746
|
+
0,
|
|
3747
|
+
65
|
|
3748
|
+
);
|
|
3749
|
+
word(`\u05EA\u05D5\u05DB\u05DF \u05D4\u05D5\u05D3\u05E2\u05D4 ${i + 1}`, label, 285, y + 20, 226, 67, 30, NAVY, delay + 0.22);
|
|
3750
|
+
});
|
|
3751
|
+
shape("\u05E7\u05D5 \u05D7\u05E9\u05D3", 277, 563, 216, 10, RED, 5, 2.15, -180);
|
|
3752
|
+
return true;
|
|
3753
|
+
}
|
|
3754
|
+
if (ctx.index === 1) {
|
|
3755
|
+
shape("\u05D4\u05D9\u05DC\u05EA \u05E2\u05E6\u05D9\u05E8\u05D4 \u05D7\u05D9\u05E6\u05D5\u05E0\u05D9\u05EA", 84, 72, 598, 598, "#FCE0E9", 299, 0.08, 0, 130);
|
|
3756
|
+
shape("\u05D4\u05D9\u05DC\u05EA \u05E2\u05E6\u05D9\u05E8\u05D4 \u05E4\u05E0\u05D9\u05DE\u05D9\u05EA", 168, 156, 430, 430, WHITE, 215, 0.23, 0, 120);
|
|
3757
|
+
shape("\u05EA\u05DE\u05E8\u05D5\u05E8 \u05E2\u05E6\u05D9\u05E8\u05D4", 249, 238, 270, 270, RED, 56, 0.44, 0, 110);
|
|
3758
|
+
word("\u05D8\u05E7\u05E1\u05D8 \u05E2\u05E6\u05D9\u05E8\u05D4", "\u05E2\u05E6\u05D5\u05E8", 274, 302, 222, 115, 77, WHITE, 0.69);
|
|
3759
|
+
shape("\u05E7\u05D9\u05E9\u05D5\u05E8 \u05E9\u05DC\u05D0 \u05E0\u05E4\u05EA\u05D7", 167, 580, 438, 48, "#F8C5D4", 24, 1.15, 0, 95);
|
|
3760
|
+
shape("\u05E7\u05D5 \u05DE\u05D7\u05D9\u05E7\u05EA \u05E7\u05D9\u05E9\u05D5\u05E8", 154, 595, 465, 16, RED, 8, 1.54, -390);
|
|
3761
|
+
return true;
|
|
3762
|
+
}
|
|
3763
|
+
if (ctx.index === 2) {
|
|
3764
|
+
shape("\u05DB\u05E8\u05D8\u05D9\u05E1 \u05E2\u05E8\u05D5\u05E5 \u05E8\u05E9\u05DE\u05D9", 80, 83, 618, 555, WHITE, 29, 0.08, 0, 130);
|
|
3765
|
+
word("\u05DB\u05D5\u05EA\u05E8\u05EA \u05D1\u05D3\u05D9\u05E7\u05D4 \u05E2\u05E6\u05DE\u05D0\u05D9\u05EA", "\u05E4\u05D5\u05EA\u05D7\u05D9\u05DD \u05D1\u05E2\u05E6\u05DE\u05E0\u05D5", 127, 111, 526, 77, 44, NAVY, 0.43);
|
|
3766
|
+
["\u05D0\u05E4\u05DC\u05D9\u05E7\u05E6\u05D9\u05D4", "\u05D0\u05EA\u05E8 \u05E8\u05E9\u05DE\u05D9", "\u05D9\u05E6\u05D9\u05E8\u05EA \u05E7\u05E9\u05E8"].forEach((label, i) => {
|
|
3767
|
+
const y = 218 + i * 125, delay = 0.7 + i * 0.59;
|
|
3768
|
+
shape(
|
|
3769
|
+
`\u05E2\u05E8\u05D5\u05E5 \u05D1\u05D3\u05D9\u05E7\u05D4 ${label}`,
|
|
3770
|
+
110,
|
|
3771
|
+
y,
|
|
3772
|
+
555,
|
|
3773
|
+
93,
|
|
3774
|
+
i === 0 ? "#F8D0DC" : PALE,
|
|
3775
|
+
19,
|
|
3776
|
+
delay,
|
|
3777
|
+
i % 2 ? 190 : -190
|
|
3778
|
+
);
|
|
3779
|
+
shape(
|
|
3780
|
+
`\u05E1\u05DE\u05DC \u05E2\u05E8\u05D5\u05E5 ${label}`,
|
|
3781
|
+
132,
|
|
3782
|
+
y + 19,
|
|
3783
|
+
56,
|
|
3784
|
+
56,
|
|
3785
|
+
i === 0 ? RED : "#DB9CAF",
|
|
3786
|
+
17,
|
|
3787
|
+
delay + 0.14,
|
|
3788
|
+
0,
|
|
3789
|
+
85
|
|
3790
|
+
);
|
|
3791
|
+
word(`\u05E9\u05DD \u05E2\u05E8\u05D5\u05E5 ${label}`, label, 206, y + 10, 350, 71, 35, NAVY, delay + 0.26);
|
|
3792
|
+
shape(
|
|
3793
|
+
`\u05E4\u05E1 \u05E2\u05E8\u05D5\u05E5 ${label}`,
|
|
3794
|
+
578,
|
|
3795
|
+
y + 42,
|
|
3796
|
+
57,
|
|
3797
|
+
10,
|
|
3798
|
+
i === 0 ? RED : "#D6A2B0",
|
|
3799
|
+
5,
|
|
3800
|
+
delay + 0.35,
|
|
3801
|
+
-70
|
|
3802
|
+
);
|
|
3803
|
+
});
|
|
3804
|
+
return true;
|
|
3805
|
+
}
|
|
3806
|
+
shape("\u05DE\u05D2\u05DF \u05DE\u05D9\u05D3\u05E2 \u05D0\u05D9\u05E9\u05D9", 130, 112, 515, 530, WHITE, 36, 0.12, 0, 135);
|
|
3807
|
+
shape("\u05DC\u05D5\u05D7 \u05E0\u05E2\u05D9\u05DC\u05D4", 220, 267, 340, 283, "#FFD7E2", 34, 0.46, 0, 120);
|
|
3808
|
+
shape("\u05E7\u05E9\u05EA \u05DE\u05E0\u05E2\u05D5\u05DC \u05D7\u05D9\u05E6\u05D5\u05E0\u05D9\u05EA", 305, 178, 168, 155, RED, 77, 0.65, 0, 100);
|
|
3809
|
+
shape("\u05E7\u05E9\u05EA \u05DE\u05E0\u05E2\u05D5\u05DC \u05E4\u05E0\u05D9\u05DE\u05D9\u05EA", 332, 205, 114, 113, WHITE, 58, 0.73, 0, 100);
|
|
3810
|
+
shape("\u05D2\u05D5\u05E3 \u05DE\u05E0\u05E2\u05D5\u05DC", 247, 304, 287, 230, RED, 24, 0.84, 0, 110);
|
|
3811
|
+
shape("\u05D7\u05D5\u05E8 \u05DE\u05E0\u05E2\u05D5\u05DC", 371, 385, 40, 72, WHITE, 20, 1.16, 0, 70);
|
|
3812
|
+
word("\u05E1\u05D9\u05E1\u05DE\u05D4 \u05D5\u05E7\u05D5\u05D3", "\u05E1\u05D9\u05E1\u05DE\u05D4 \u2022 \u05E7\u05D5\u05D3", 231, 566, 345, 60, 30, NAVY, 1.47);
|
|
3813
|
+
return true;
|
|
3814
|
+
}
|
|
3815
|
+
function storyboard(ctx) {
|
|
3816
|
+
if (holidayStoryboard(ctx)) return true;
|
|
3817
|
+
if (oneClickStoryboard(ctx)) return true;
|
|
3818
|
+
if (careerStoryboard(ctx)) return true;
|
|
3819
|
+
if (homeRefreshStoryboard(ctx)) return true;
|
|
3820
|
+
if (summerStoryboard(ctx)) return true;
|
|
3821
|
+
if (carUpgradeStoryboard(ctx)) return true;
|
|
3822
|
+
if (weddingStoryboard(ctx)) return true;
|
|
3823
|
+
if (shareStoryboard(ctx)) return true;
|
|
3824
|
+
if (fraudStoryboard(ctx)) return true;
|
|
3825
|
+
const spec = storyFrames[ctx.theme][ctx.index - 1];
|
|
3826
|
+
if (!spec) return false;
|
|
3827
|
+
const { kind, labels } = spec;
|
|
3828
|
+
const a = ctx.accent, ink = ctx.ink, surface = ctx.surface;
|
|
3829
|
+
const d = ctx.scene.duration, end = d - 0.02;
|
|
3830
|
+
if (kind === "choices") {
|
|
3831
|
+
labels.slice(0, 2).forEach((label, i) => {
|
|
3832
|
+
const x = 38 + i * 370;
|
|
3833
|
+
box(ctx, `\u05D0\u05E4\u05E9\u05E8\u05D5\u05EA ${i + 1}`, x, 195, 320, 360, i ? ink : a, 32, 0.2 + i * 0.42, i ? 420 : -420, 0);
|
|
3834
|
+
box(ctx, `\u05E1\u05DE\u05DC \u05D0\u05E4\u05E9\u05E8\u05D5\u05EA ${i + 1}`, x + 106, 260, 108, 108, i ? a : surface, 54, 0.55 + i * 0.42, i ? 240 : -240);
|
|
3835
|
+
caption(ctx, `\u05EA\u05D5\u05D5\u05D9\u05EA \u05D0\u05E4\u05E9\u05E8\u05D5\u05EA ${i + 1}`, label, x + 20, 407, 280, 100, 50, i ? surface : ctx.ink === WHITE ? RED : WHITE, 0.72 + i * 0.42);
|
|
3836
|
+
});
|
|
3837
|
+
box(ctx, "\u05E6\u05D9\u05E8 \u05D4\u05E9\u05D5\u05D5\u05D0\u05D4", 371, 215, 8, 320, surface, 4, 0.88, 0, 0, 0.65);
|
|
3838
|
+
} else if (kind === "bars") {
|
|
3839
|
+
box(ctx, "\u05D1\u05E1\u05D9\u05E1 \u05D4\u05E9\u05D5\u05D5\u05D0\u05D4", 50, 605, 660, 18, ink, 9, 0.1);
|
|
3840
|
+
labels.slice(0, 3).forEach((label, i) => {
|
|
3841
|
+
const height = 310;
|
|
3842
|
+
const item = box(ctx, `\u05E2\u05DE\u05D5\u05D3\u05EA ${label}`, 80 + i * 215, 605 - height, 145, height, i === 1 ? ink : a, 18, 0.3 + i * 0.24, 0, 0);
|
|
3843
|
+
item.keyframes = [
|
|
3844
|
+
point(0, 0, height, 1, 0.04, 0, 0),
|
|
3845
|
+
point(0.25 + i * 0.22, 0, height, 1, 0.04, 0, 0),
|
|
3846
|
+
point(0.88 + i * 0.22, 0, 0),
|
|
3847
|
+
point(end, 0, -18)
|
|
3848
|
+
];
|
|
3849
|
+
caption(ctx, `\u05E9\u05DD \u05DE\u05D3\u05D3 ${i + 1}`, label, 66 + i * 215, 642, 175, 70, 39, ink, 0.82 + i * 0.2);
|
|
3850
|
+
});
|
|
3851
|
+
} else if (kind === "steps") {
|
|
3852
|
+
box(ctx, "\u05E7\u05D5 \u05DE\u05E1\u05DC\u05D5\u05DC", 72, 371, 630, 16, ink, 8, 0.1, -420, 0);
|
|
3853
|
+
labels.slice(0, 3).forEach((label, i) => {
|
|
3854
|
+
const x = 65 + i * 235;
|
|
3855
|
+
box(ctx, `\u05EA\u05D7\u05E0\u05D4 ${i + 1}`, x, 305, 150, 150, i === 2 ? ink : a, 75, 0.22 + i * 0.37, -320, 0);
|
|
3856
|
+
caption(ctx, `\u05DE\u05E1\u05E4\u05E8 \u05EA\u05D7\u05E0\u05D4 ${i + 1}`, `0${i + 1}`, x + 25, 335, 100, 85, 63, i === 2 ? surface : ctx.ink === WHITE ? RED : WHITE, 0.44 + i * 0.37);
|
|
3857
|
+
caption(ctx, `\u05E9\u05DD \u05EA\u05D7\u05E0\u05D4 ${i + 1}`, label, x - 18, 485, 190, 85, 40, ink, 0.66 + i * 0.37);
|
|
3858
|
+
});
|
|
3859
|
+
} else if (kind === "phone") {
|
|
3860
|
+
box(ctx, "\u05D8\u05DC\u05E4\u05D5\u05DF \u05EA\u05D4\u05DC\u05D9\u05DA", 192, 75, 390, 630, NAVY, 46, 0.1);
|
|
3861
|
+
box(ctx, "\u05DE\u05E1\u05DA \u05EA\u05D4\u05DC\u05D9\u05DA", 214, 102, 346, 575, surface, 30, 0.2);
|
|
3862
|
+
labels.slice(0, 3).forEach((label, i) => {
|
|
3863
|
+
box(ctx, `\u05E9\u05D5\u05E8\u05EA \u05D0\u05E4\u05DC\u05D9\u05E7\u05E6\u05D9\u05D4 ${i + 1}`, 244, 200 + i * 135, 286, 98, i === 2 ? a : ctx.ink === WHITE ? "#FF7A98" : "#F7BAC7", 22, 0.36 + i * 0.3, i % 2 ? 250 : -250);
|
|
3864
|
+
caption(ctx, `\u05E4\u05E2\u05D5\u05DC\u05EA \u05D0\u05E4\u05DC\u05D9\u05E7\u05E6\u05D9\u05D4 ${i + 1}`, label, 258, 217 + i * 135, 257, 70, 38, NAVY, 0.56 + i * 0.3);
|
|
3865
|
+
});
|
|
3866
|
+
} else if (kind === "check" || kind === "stack" || kind === "warning") {
|
|
3867
|
+
labels.slice(0, 3).forEach((label, i) => {
|
|
3868
|
+
const y = 128 + i * 185;
|
|
3869
|
+
box(ctx, `\u05DB\u05E8\u05D8\u05D9\u05E1 ${i + 1}`, 62, y, 640, 145, i === 1 ? ink : surface, 22, 0.16 + i * 0.31, i % 2 ? 390 : -390);
|
|
3870
|
+
if (kind !== "stack") {
|
|
3871
|
+
box(ctx, `\u05E1\u05D9\u05DE\u05D5\u05DF ${i + 1}`, 90, y + 36, 72, 72, kind === "warning" ? RED : a, 36, 0.36 + i * 0.31, -180);
|
|
3872
|
+
caption(ctx, `\u05E1\u05DE\u05DC ${i + 1}`, kind === "warning" ? "!" : "\u2713", 102, y + 43, 48, 57, 43, kind === "warning" ? WHITE : ctx.ink === WHITE ? RED : WHITE, 0.55 + i * 0.31);
|
|
3873
|
+
}
|
|
3874
|
+
caption(
|
|
3875
|
+
ctx,
|
|
3876
|
+
`\u05E9\u05D5\u05E8\u05EA \u05EA\u05D5\u05DB\u05DF ${i + 1}`,
|
|
3877
|
+
label,
|
|
3878
|
+
kind === "stack" ? 115 : 195,
|
|
3879
|
+
y + 27,
|
|
3880
|
+
kind === "stack" ? 530 : 465,
|
|
3881
|
+
92,
|
|
3882
|
+
48,
|
|
3883
|
+
i === 1 ? surface : ink,
|
|
3884
|
+
0.52 + i * 0.31
|
|
3885
|
+
);
|
|
3886
|
+
});
|
|
3887
|
+
} else if (kind === "meter") {
|
|
3888
|
+
box(ctx, "\u05DE\u05D3 \u05D8\u05D1\u05E2\u05EA \u05D7\u05D9\u05E6\u05D5\u05E0\u05D9", 95, 87, 570, 570, a, 285, 0.14);
|
|
3889
|
+
box(ctx, "\u05DE\u05D3 \u05D8\u05D1\u05E2\u05EA \u05E4\u05E0\u05D9\u05DE\u05D9", 165, 157, 430, 430, surface, 215, 0.35);
|
|
3890
|
+
box(ctx, "\u05DC\u05D9\u05D1\u05EA \u05D4\u05DE\u05D3", 243, 235, 274, 274, a, 137, 0.58);
|
|
3891
|
+
caption(
|
|
3892
|
+
ctx,
|
|
3893
|
+
"\u05DE\u05E1\u05E8 \u05D1\u05DE\u05E8\u05DB\u05D6 \u05D4\u05DE\u05D3",
|
|
3894
|
+
labels[0],
|
|
3895
|
+
269,
|
|
3896
|
+
303,
|
|
3897
|
+
222,
|
|
3898
|
+
140,
|
|
3899
|
+
50,
|
|
3900
|
+
ctx.ink === WHITE ? RED : WHITE,
|
|
3901
|
+
0.72
|
|
3902
|
+
);
|
|
3903
|
+
for (let i = 0; i < 4; i++) box(ctx, `\u05E4\u05E2\u05D9\u05DE\u05EA \u05DE\u05D3 ${i + 1}`, 126 + i * 143, 672, 110, 13, ink, 7, 0.78 + i * 0.19);
|
|
3904
|
+
}
|
|
3905
|
+
return true;
|
|
3906
|
+
}
|
|
3907
|
+
function visualConfigToProject(config) {
|
|
3908
|
+
if (!config.visualTheme) throw new Error("\u05D7\u05E1\u05E8 \u05E2\u05D5\u05DC\u05DD \u05D7\u05D6\u05D5\u05EA\u05D9");
|
|
3909
|
+
const scenes = config.scenes.map((spec, index) => {
|
|
3910
|
+
const scene = createScene(`${index + 1}. ${spec.headline.slice(0, 54)}`, spec.duration);
|
|
3911
|
+
const last = index === config.scenes.length - 1;
|
|
3912
|
+
const light = index % 3 === 1;
|
|
3913
|
+
scene.background = last ? `linear-gradient(135deg,${DEEP_RED},${RED})` : light ? `linear-gradient(135deg,${WHITE},${PALE})` : `linear-gradient(130deg,${RED},${DEEP_RED})`;
|
|
3914
|
+
scene.transition = index ? "fade" : "cut";
|
|
3915
|
+
const visualOnLeft = index % 2 === 0;
|
|
3916
|
+
const ctx = {
|
|
3917
|
+
scene,
|
|
3918
|
+
theme: config.visualTheme,
|
|
3919
|
+
index,
|
|
3920
|
+
count: config.scenes.length,
|
|
3921
|
+
ox: visualOnLeft ? 105 : 1020,
|
|
3922
|
+
oy: 160,
|
|
3923
|
+
ink: light ? NAVY : WHITE,
|
|
3924
|
+
accent: light ? RED : WHITE,
|
|
3925
|
+
surface: light ? PALE : "#F02450"
|
|
3926
|
+
};
|
|
3927
|
+
for (let i = 0; i < 4; i++) layer(
|
|
3928
|
+
ctx,
|
|
3929
|
+
"shape",
|
|
3930
|
+
`\u05E4\u05E1 \u05E8\u05E7\u05E2 ${i + 1}`,
|
|
3931
|
+
0,
|
|
3932
|
+
100 + i * 250,
|
|
3933
|
+
1920,
|
|
3934
|
+
2,
|
|
3935
|
+
light ? "#E9CDD4" : "#FFFFFF",
|
|
3936
|
+
{ opacity: 0.12, keys: [point(0, -120, 0, 1, 1, 0, 0), point(0.6, 0, 0, 1, 1, 0, 1), point(spec.duration - 0.02, 90, 0, 1, 1, 0, 1)] }
|
|
3937
|
+
);
|
|
3938
|
+
if (!last) {
|
|
3939
|
+
const firstMotifLayer = scene.layers.length;
|
|
3940
|
+
if (!storyboard(ctx)) {
|
|
3941
|
+
motif(ctx);
|
|
3942
|
+
animateMotif(ctx, scene.layers.slice(firstMotifLayer));
|
|
3943
|
+
}
|
|
3944
|
+
} else {
|
|
3945
|
+
ctx.ox = 0;
|
|
3946
|
+
ctx.oy = 0;
|
|
3947
|
+
const motifStart = scene.layers.length;
|
|
3948
|
+
motif(ctx);
|
|
3949
|
+
const closingMotif = scene.layers.slice(motifStart);
|
|
3950
|
+
animateMotif(ctx, closingMotif);
|
|
3951
|
+
for (const item of closingMotif) {
|
|
3952
|
+
item.x = 850 + item.x * 0.25;
|
|
3953
|
+
item.y = 28 + item.y * 0.25;
|
|
3954
|
+
item.width = Math.max(1, item.width * 0.25);
|
|
3955
|
+
item.height = Math.max(1, item.height * 0.25);
|
|
3956
|
+
item.fontSize = Math.max(12, item.fontSize * 0.25);
|
|
3957
|
+
item.borderRadius *= 0.25;
|
|
3958
|
+
if (item.keyframes) for (const key of item.keyframes) {
|
|
3959
|
+
key.x *= 0.25;
|
|
3960
|
+
key.y *= 0.25;
|
|
3961
|
+
}
|
|
3962
|
+
}
|
|
3963
|
+
box(ctx, "\u05E4\u05E1 \u05D7\u05EA\u05D9\u05DE\u05D4", 610, 942, 700, 12, WHITE, 6, 0.7, 0, 0, 0.8);
|
|
3964
|
+
}
|
|
3965
|
+
const textX = last ? 230 : visualOnLeft ? 1010 : 135;
|
|
3966
|
+
const textY = last ? 305 : 320;
|
|
3967
|
+
const textW = last ? 1460 : 770;
|
|
3968
|
+
const headlineSize = spec.headline.length > 30 ? 72 : spec.headline.length > 22 ? 80 : 94;
|
|
3969
|
+
layer(ctx, "text", "\u05DB\u05D5\u05EA\u05E8\u05EA", textX, textY, textW, last ? 280 : 310, last ? WHITE : ctx.ink, {
|
|
3970
|
+
text: spec.headline,
|
|
3971
|
+
size: headlineSize,
|
|
3972
|
+
weight: 800,
|
|
3973
|
+
align: last ? "center" : "right",
|
|
3974
|
+
keys: flight(spec.duration, last ? 0.28 : 0.42, 0, 130, 0, -18)
|
|
3975
|
+
});
|
|
3976
|
+
if (spec.eyebrow) layer(ctx, "text", "\u05DB\u05D5\u05EA\u05E8\u05EA \u05DE\u05E9\u05E0\u05D4", textX, last ? 208 : 233, textW, 78, last ? WHITE : ctx.ink, {
|
|
3977
|
+
text: spec.eyebrow,
|
|
3978
|
+
size: 34,
|
|
3979
|
+
weight: 700,
|
|
3980
|
+
align: last ? "center" : "right",
|
|
3981
|
+
keys: flight(spec.duration, 0.18, 0, 60, 0, -8)
|
|
3982
|
+
});
|
|
3983
|
+
if (spec.supporting) layer(ctx, "text", "\u05D8\u05E7\u05E1\u05D8 \u05EA\u05D5\u05DE\u05DA", textX, last ? 603 : 690, textW, 170, last ? WHITE : ctx.ink, {
|
|
3984
|
+
text: spec.supporting,
|
|
3985
|
+
size: 38,
|
|
3986
|
+
weight: 500,
|
|
3987
|
+
align: last ? "center" : "right",
|
|
3988
|
+
keys: flight(spec.duration, 0.92, 0, 75, 0, -10)
|
|
3989
|
+
});
|
|
3990
|
+
if (spec.emphasis) layer(ctx, "text", "\u05D4\u05D3\u05D2\u05E9\u05D4", textX, last ? 810 : 865, textW, 98, last ? WHITE : light ? RED : WHITE, {
|
|
3991
|
+
text: spec.emphasis,
|
|
3992
|
+
size: 55,
|
|
3993
|
+
weight: 900,
|
|
3994
|
+
align: last ? "center" : "right",
|
|
3995
|
+
keys: pulse(spec.duration, 1.1)
|
|
3996
|
+
});
|
|
3997
|
+
layer(ctx, "text", "\u05DE\u05E1\u05E4\u05E8 \u05E1\u05E6\u05E0\u05D4", 118, 45, 130, 50, last ? WHITE : ctx.ink, {
|
|
3998
|
+
text: `${String(index + 1).padStart(2, "0")} \u05DE\u05EA\u05D5\u05DA ${String(config.scenes.length).padStart(2, "0")}`,
|
|
3999
|
+
size: 23,
|
|
4000
|
+
weight: 700,
|
|
4001
|
+
align: "left",
|
|
4002
|
+
opacity: 0.75,
|
|
4003
|
+
keys: flight(spec.duration, 0, 0, -24, 0, 0)
|
|
4004
|
+
});
|
|
4005
|
+
layer(ctx, "shape", "\u05E6\u05D9\u05E8 \u05D4\u05EA\u05E7\u05D3\u05DE\u05D5\u05EA", 120, 1012, 1680, 7, last ? WHITE : ctx.ink, {
|
|
4006
|
+
radius: 4,
|
|
4007
|
+
opacity: 0.25,
|
|
4008
|
+
keys: [point(0), point(spec.duration - 0.02)]
|
|
4009
|
+
});
|
|
4010
|
+
layer(ctx, "shape", "\u05D4\u05EA\u05E7\u05D3\u05DE\u05D5\u05EA \u05D4\u05E1\u05E6\u05E0\u05D4", 120, 1012, 1680, 7, last ? WHITE : light ? RED : WHITE, {
|
|
4011
|
+
radius: 4,
|
|
4012
|
+
opacity: 0.8,
|
|
4013
|
+
keys: [point(0, 0, 0, 0, 1, 0, 1), point(spec.duration - 0.02, 0, 0, 1, 1, 0, 1)]
|
|
4014
|
+
});
|
|
4015
|
+
return scene;
|
|
4016
|
+
});
|
|
4017
|
+
const project = createProject(config.title, { canvas: { width: 1920, height: 1080, fps: config.fps ?? 30 }, scenes });
|
|
4018
|
+
assertProject(project);
|
|
4019
|
+
return project;
|
|
4020
|
+
}
|
|
4021
|
+
|
|
4022
|
+
// src/core/config.ts
|
|
4023
|
+
var visualThemes = ["car-road", "holiday-table", "one-click", "book-steps", "room-build", "summer-case", "car-garage", "wedding-rings", "share-mosaic", "fraud-alert", "student-desk", "learning-domino", "fomo-storm", "market-clock", "small-bricks", "two-paths", "small-store", "travel-conveyor", "mortgage-blueprint", "market-phone"];
|
|
4024
|
+
var MAX_BYTES = 256 * 1024;
|
|
4025
|
+
function fail2(path, reason) {
|
|
4026
|
+
throw new Error(`${path}: ${reason}`);
|
|
4027
|
+
}
|
|
4028
|
+
function object(value, keys, path) {
|
|
4029
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) fail2(path, "\u05E0\u05D3\u05E8\u05E9 \u05D0\u05D5\u05D1\u05D9\u05D9\u05E7\u05D8");
|
|
4030
|
+
const record2 = value;
|
|
4031
|
+
for (const key of Object.keys(record2)) if (!keys.includes(key)) fail2(`${path}.${key}`, "\u05E9\u05D3\u05D4 \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8");
|
|
4032
|
+
return record2;
|
|
4033
|
+
}
|
|
4034
|
+
function text2(value, max, path) {
|
|
4035
|
+
if (typeof value !== "string" || !value.trim() || value.length > max || /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/.test(value)) fail2(path, `\u05E0\u05D3\u05E8\u05E9 \u05D8\u05E7\u05E1\u05D8 \u05D1\u05D0\u05D5\u05E8\u05DA 1\u2013${max} \u05EA\u05D5\u05D5\u05D9\u05DD`);
|
|
4036
|
+
return value;
|
|
4037
|
+
}
|
|
4038
|
+
function choice2(value, values, path) {
|
|
4039
|
+
if (!values.includes(value)) fail2(path, "\u05E2\u05E8\u05DA \u05DC\u05D0 \u05E0\u05EA\u05DE\u05DA");
|
|
4040
|
+
return value;
|
|
4041
|
+
}
|
|
4042
|
+
function validateConfig(value) {
|
|
4043
|
+
const p = object(value, ["format", "title", "aspectRatio", "fps", "palette", "visualTheme", "scenes"], "config");
|
|
4044
|
+
const config = {
|
|
4045
|
+
format: choice2(p.format, ["motiondesk-config/v1"], "format"),
|
|
4046
|
+
title: text2(p.title, 120, "title"),
|
|
4047
|
+
aspectRatio: choice2(p.aspectRatio, ["16:9", "9:16", "1:1"], "aspectRatio"),
|
|
4048
|
+
scenes: []
|
|
4049
|
+
};
|
|
4050
|
+
if (p.fps !== void 0) config.fps = choice2(p.fps, [24, 25, 30, 60], "fps");
|
|
4051
|
+
if (p.visualTheme !== void 0) config.visualTheme = choice2(p.visualTheme, visualThemes, "visualTheme");
|
|
4052
|
+
if (p.palette !== void 0) {
|
|
4053
|
+
const palette = object(p.palette, ["background", "foreground", "accent"], "palette");
|
|
4054
|
+
const color = (key) => {
|
|
4055
|
+
const value2 = palette[key];
|
|
4056
|
+
if (typeof value2 !== "string" || !/^#[a-fA-F0-9]{6}$/.test(value2)) fail2(`palette.${key}`, "\u05E0\u05D3\u05E8\u05E9 \u05E6\u05D1\u05E2 \u05D4\u05E7\u05E1\u05D3\u05E6\u05D9\u05DE\u05DC\u05D9 \u05D1\u05DF \u05E9\u05E9 \u05E1\u05E4\u05E8\u05D5\u05EA");
|
|
4057
|
+
return value2;
|
|
4058
|
+
};
|
|
4059
|
+
config.palette = { background: color("background"), foreground: color("foreground"), accent: color("accent") };
|
|
4060
|
+
}
|
|
4061
|
+
if (!Array.isArray(p.scenes) || p.scenes.length < 1 || p.scenes.length > 12) fail2("scenes", "\u05E0\u05D3\u05E8\u05E9\u05D5\u05EA 1\u201312 \u05E1\u05E6\u05E0\u05D5\u05EA");
|
|
4062
|
+
config.scenes = p.scenes.map((value2, index) => {
|
|
4063
|
+
const path = `scenes.${index}`;
|
|
4064
|
+
const s = object(value2, ["duration", "layout", "headline", "eyebrow", "supporting", "emphasis", "motion"], path);
|
|
4065
|
+
if (typeof s.duration !== "number" || !Number.isFinite(s.duration) || s.duration < 0.5 || s.duration > 20) fail2(`${path}.duration`, "\u05DE\u05E9\u05DA \u05D7\u05D9\u05D9\u05D1 \u05DC\u05D4\u05D9\u05D5\u05EA \u05D1\u05D9\u05DF 0.5 \u05DC\u05BE20 \u05E9\u05E0\u05D9\u05D5\u05EA");
|
|
4066
|
+
const scene = { duration: s.duration, layout: choice2(s.layout, ["statement", "split", "number", "end-card"], `${path}.layout`), headline: text2(s.headline, 160, `${path}.headline`) };
|
|
4067
|
+
for (const [key, max] of [["eyebrow", 60], ["supporting", 280], ["emphasis", 40]]) {
|
|
4068
|
+
if (s[key] !== void 0) scene[key] = text2(s[key], max, `${path}.${key}`);
|
|
4069
|
+
}
|
|
4070
|
+
if (s.motion !== void 0) scene.motion = choice2(s.motion, ["fade", "slide-up", "pop"], `${path}.motion`);
|
|
4071
|
+
if (scene.layout === "number" && !scene.emphasis) fail2(`${path}.emphasis`, "\u05E4\u05E8\u05D9\u05E1\u05EA \u05DE\u05E1\u05E4\u05E8 \u05D3\u05D5\u05E8\u05E9\u05EA \u05D4\u05D3\u05D2\u05E9\u05D4");
|
|
4072
|
+
return scene;
|
|
4073
|
+
});
|
|
4074
|
+
if (config.visualTheme) {
|
|
4075
|
+
if (config.aspectRatio !== "16:9") fail2("aspectRatio", "\u05D4\u05E2\u05D5\u05DC\u05DE\u05D5\u05EA \u05D4\u05D7\u05D6\u05D5\u05EA\u05D9\u05D9\u05DD \u05D6\u05DE\u05D9\u05E0\u05D9\u05DD \u05DB\u05E8\u05D2\u05E2 \u05D1\u05E4\u05D5\u05E8\u05DE\u05D8 16:9");
|
|
4076
|
+
config.scenes.forEach((scene, index) => {
|
|
4077
|
+
if (scene.duration < 2.5) fail2(`scenes.${index}.duration`, "\u05E1\u05E6\u05E0\u05D4 \u05E2\u05DD \u05E2\u05D5\u05DC\u05DD \u05D7\u05D6\u05D5\u05EA\u05D9 \u05E6\u05E8\u05D9\u05DB\u05D4 \u05DC\u05D4\u05D9\u05DE\u05E9\u05DA \u05DC\u05E4\u05D7\u05D5\u05EA 2.5 \u05E9\u05E0\u05D9\u05D5\u05EA");
|
|
4078
|
+
});
|
|
4079
|
+
}
|
|
4080
|
+
return config;
|
|
4081
|
+
}
|
|
4082
|
+
function parseMotionConfig(json) {
|
|
4083
|
+
if (typeof json !== "string" || json.length > MAX_BYTES || new TextEncoder().encode(json).length > MAX_BYTES) fail2("config", "\u05E7\u05D5\u05D1\u05E5 \u05D4\u05D4\u05D2\u05D3\u05E8\u05D5\u05EA \u05D2\u05D3\u05D5\u05DC \u05DE\u05D3\u05D9");
|
|
4084
|
+
let value;
|
|
4085
|
+
try {
|
|
4086
|
+
value = JSON.parse(json);
|
|
4087
|
+
} catch {
|
|
4088
|
+
return fail2("config", "\u05E0\u05D3\u05E8\u05E9 JSON \u05EA\u05E7\u05D9\u05DF \u05DC\u05DC\u05D0 \u05E2\u05D8\u05D9\u05E4\u05EA Markdown");
|
|
4089
|
+
}
|
|
4090
|
+
if (value?.format === "motiondesk-config/v3") return parseMotionConfigV3(value);
|
|
4091
|
+
if (value?.format === "motiondesk-config/v2") return parseMotionConfigV2(value);
|
|
4092
|
+
return validateConfig(value);
|
|
4093
|
+
}
|
|
4094
|
+
function configToProject(input) {
|
|
4095
|
+
if (input.format === "motiondesk-config/v3") return configV3ToProject(input);
|
|
4096
|
+
if (input.format === "motiondesk-config/v2") return configV2ToProject(input);
|
|
4097
|
+
const config = validateConfig(input);
|
|
4098
|
+
if (config.visualTheme) return visualConfigToProject(config);
|
|
4099
|
+
const [width, height] = config.aspectRatio === "16:9" ? [1920, 1080] : config.aspectRatio === "9:16" ? [1080, 1920] : [1080, 1080];
|
|
4100
|
+
const palette = config.palette ?? { background: "#FFFFFF", foreground: "#252833", accent: "#E30613" };
|
|
4101
|
+
const base = Math.min(width, height);
|
|
4102
|
+
const scenes = config.scenes.map((spec, index) => {
|
|
4103
|
+
const scene = createScene(`${index + 1}. ${spec.headline.slice(0, 80)}`, spec.duration);
|
|
4104
|
+
scene.background = palette.background;
|
|
4105
|
+
const motion = spec.motion ?? "slide-up";
|
|
4106
|
+
const shape = (name, x, y, w, h, opacity = 1) => {
|
|
4107
|
+
scene.layers.push(createLayer("shape", { name, x: x * width, y: y * height, width: w * width, height: h * height, color: palette.accent, opacity, borderRadius: base * 0.018, motion: "fade", start: 0, duration: spec.duration }));
|
|
4108
|
+
};
|
|
4109
|
+
const label = (name, value, x, y, w, h, size, accent = false, align = "right") => {
|
|
4110
|
+
if (!value) return;
|
|
4111
|
+
const boxWidth = w * width, boxHeight = h * height;
|
|
4112
|
+
let fontSize = Math.round(base * size);
|
|
4113
|
+
const lines = (font) => value.split("\n").reduce((sum, line) => sum + Math.max(1, Math.ceil(line.length * font * 0.72 / boxWidth)), 0);
|
|
4114
|
+
while (fontSize > 10 && lines(fontSize) * fontSize * 1.35 > boxHeight) fontSize = Math.max(10, fontSize - 1);
|
|
4115
|
+
if (lines(fontSize) * fontSize * 1.35 > boxHeight) {
|
|
4116
|
+
const field = { "\u05DB\u05D5\u05EA\u05E8\u05EA \u05DE\u05E9\u05E0\u05D4": "eyebrow", "\u05DB\u05D5\u05EA\u05E8\u05EA": "headline", "\u05D8\u05E7\u05E1\u05D8 \u05EA\u05D5\u05DE\u05DA": "supporting", "\u05D4\u05D3\u05D2\u05E9\u05D4": "emphasis" }[name] ?? name;
|
|
4117
|
+
fail2(`scenes.${index}.${field}`, "\u05D4\u05D8\u05E7\u05E1\u05D8 \u05D0\u05D9\u05E0\u05D5 \u05E0\u05DB\u05E0\u05E1 \u05DC\u05EA\u05D9\u05D1\u05EA \u05D4\u05EA\u05E6\u05D5\u05D2\u05D4; \u05D9\u05E9 \u05DC\u05E7\u05E6\u05E8 \u05D0\u05D5\u05EA\u05D5 \u05D0\u05D5 \u05DC\u05D4\u05E4\u05D7\u05D9\u05EA \u05DE\u05E2\u05D1\u05E8\u05D9 \u05E9\u05D5\u05E8\u05D4");
|
|
4118
|
+
}
|
|
4119
|
+
const start = Math.min(0.08 * scene.layers.filter((l) => l.type === "text").length, spec.duration * 0.2);
|
|
4120
|
+
scene.layers.push(createLayer("text", { name, text: value, x: x * width, y: y * height, width: boxWidth, height: boxHeight, fontSize, fontWeight: name === "\u05D8\u05E7\u05E1\u05D8 \u05EA\u05D5\u05DE\u05DA" ? 400 : 700, color: accent ? palette.accent : palette.foreground, textAlign: align, motion, start, duration: spec.duration - start }));
|
|
4121
|
+
};
|
|
4122
|
+
switch (spec.layout) {
|
|
4123
|
+
case "statement":
|
|
4124
|
+
shape("\u05E7\u05D5 \u05D4\u05D3\u05D2\u05E9\u05D4", 0.84, 0.13, 0.08, 9e-3);
|
|
4125
|
+
label("\u05DB\u05D5\u05EA\u05E8\u05EA \u05DE\u05E9\u05E0\u05D4", spec.eyebrow, 0.08, 0.17, 0.84, 0.07, 0.027, true);
|
|
4126
|
+
label("\u05DB\u05D5\u05EA\u05E8\u05EA", spec.headline, 0.08, 0.28, 0.84, 0.3, 0.085);
|
|
4127
|
+
label("\u05D4\u05D3\u05D2\u05E9\u05D4", spec.emphasis, 0.08, 0.6, 0.84, 0.09, 0.044, true);
|
|
4128
|
+
label("\u05D8\u05E7\u05E1\u05D8 \u05EA\u05D5\u05DE\u05DA", spec.supporting, 0.08, 0.73, 0.84, 0.18, 0.033);
|
|
4129
|
+
break;
|
|
4130
|
+
case "split": {
|
|
4131
|
+
const portrait = height > width;
|
|
4132
|
+
shape("\u05DC\u05D5\u05D7 \u05D4\u05D3\u05D2\u05E9\u05D4", 0.06, portrait ? 0.64 : 0.12, portrait ? 0.88 : 0.4, portrait ? 0.29 : 0.76, 0.12);
|
|
4133
|
+
label("\u05DB\u05D5\u05EA\u05E8\u05EA \u05DE\u05E9\u05E0\u05D4", spec.eyebrow, portrait ? 0.08 : 0.53, 0.12, portrait ? 0.84 : 0.39, 0.08, 0.025, true);
|
|
4134
|
+
label("\u05DB\u05D5\u05EA\u05E8\u05EA", spec.headline, portrait ? 0.08 : 0.53, 0.23, portrait ? 0.84 : 0.39, portrait ? 0.2 : 0.34, 0.068);
|
|
4135
|
+
label("\u05D8\u05E7\u05E1\u05D8 \u05EA\u05D5\u05DE\u05DA", spec.supporting, portrait ? 0.08 : 0.53, portrait ? 0.45 : 0.62, portrait ? 0.84 : 0.39, portrait ? 0.15 : 0.24, 0.03);
|
|
4136
|
+
label("\u05D4\u05D3\u05D2\u05E9\u05D4", spec.emphasis, 0.1, portrait ? 0.69 : 0.25, portrait ? 0.8 : 0.32, portrait ? 0.19 : 0.5, 0.1, true, "center");
|
|
4137
|
+
break;
|
|
4138
|
+
}
|
|
4139
|
+
case "number":
|
|
4140
|
+
shape("\u05E4\u05E1 \u05E0\u05EA\u05D5\u05DF", 0.46, 0.59, 0.08, 9e-3);
|
|
4141
|
+
label("\u05DB\u05D5\u05EA\u05E8\u05EA \u05DE\u05E9\u05E0\u05D4", spec.eyebrow, 0.08, 0.08, 0.84, 0.08, 0.027, true, "center");
|
|
4142
|
+
label("\u05D4\u05D3\u05D2\u05E9\u05D4", spec.emphasis, 0.08, 0.2, 0.84, 0.34, 0.19, true, "center");
|
|
4143
|
+
label("\u05DB\u05D5\u05EA\u05E8\u05EA", spec.headline, 0.08, 0.63, 0.84, 0.15, 0.055, false, "center");
|
|
4144
|
+
label("\u05D8\u05E7\u05E1\u05D8 \u05EA\u05D5\u05DE\u05DA", spec.supporting, 0.08, 0.8, 0.84, 0.14, 0.03, false, "center");
|
|
4145
|
+
break;
|
|
4146
|
+
case "end-card":
|
|
4147
|
+
shape("\u05DE\u05E1\u05D2\u05E8\u05EA \u05E1\u05D9\u05D5\u05DD", 0.06, 0.08, 0.88, 0.84, 0.09);
|
|
4148
|
+
label("\u05DB\u05D5\u05EA\u05E8\u05EA \u05DE\u05E9\u05E0\u05D4", spec.eyebrow, 0.12, 0.14, 0.76, 0.08, 0.025, true, "center");
|
|
4149
|
+
label("\u05DB\u05D5\u05EA\u05E8\u05EA", spec.headline, 0.12, 0.26, 0.76, 0.27, 0.075, false, "center");
|
|
4150
|
+
label("\u05D8\u05E7\u05E1\u05D8 \u05EA\u05D5\u05DE\u05DA", spec.supporting, 0.12, 0.55, 0.76, 0.18, 0.032, false, "center");
|
|
4151
|
+
label("\u05D4\u05D3\u05D2\u05E9\u05D4", spec.emphasis, 0.12, 0.77, 0.76, 0.09, 0.043, true, "center");
|
|
4152
|
+
break;
|
|
4153
|
+
}
|
|
4154
|
+
return scene;
|
|
4155
|
+
});
|
|
4156
|
+
const project = createProject(config.title, { canvas: { width, height, fps: config.fps ?? 30 }, scenes });
|
|
4157
|
+
assertProject(project);
|
|
4158
|
+
return project;
|
|
4159
|
+
}
|
|
4160
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
4161
|
+
0 && (module.exports = {
|
|
4162
|
+
SOURCE_ADAPTER_DEFINITIONS,
|
|
4163
|
+
analyzeSource,
|
|
4164
|
+
analyzeSourceAdapter,
|
|
4165
|
+
animateMotif,
|
|
4166
|
+
annotateSourcePreview,
|
|
4167
|
+
applySourceEdits,
|
|
4168
|
+
assertProject,
|
|
4169
|
+
cameraStyle,
|
|
4170
|
+
commitProject,
|
|
4171
|
+
compileProjectHtml,
|
|
4172
|
+
componentTypes,
|
|
4173
|
+
componentTypesV3,
|
|
4174
|
+
configToProject,
|
|
4175
|
+
configV2ToProject,
|
|
4176
|
+
configV3Backgrounds,
|
|
4177
|
+
configV3Cameras,
|
|
4178
|
+
configV3Energies,
|
|
4179
|
+
configV3ThemePalettes,
|
|
4180
|
+
configV3Themes,
|
|
4181
|
+
configV3ToProject,
|
|
4182
|
+
configV3Transitions,
|
|
4183
|
+
configV3Variants,
|
|
4184
|
+
contrastRatio,
|
|
4185
|
+
contrastText,
|
|
4186
|
+
createLayer,
|
|
4187
|
+
createMediaRenderPlan,
|
|
4188
|
+
createProject,
|
|
4189
|
+
createScene,
|
|
4190
|
+
duplicateScene,
|
|
4191
|
+
escapeHtml,
|
|
4192
|
+
evaluateLayer,
|
|
4193
|
+
flight,
|
|
4194
|
+
importHtmlSource,
|
|
4195
|
+
importStructuredHtml,
|
|
4196
|
+
isLocalAsset,
|
|
4197
|
+
layerStyle,
|
|
4198
|
+
migrateProject,
|
|
4199
|
+
moveScene,
|
|
4200
|
+
newId,
|
|
4201
|
+
parseMotionConfig,
|
|
4202
|
+
parseMotionConfigV2,
|
|
4203
|
+
parseMotionConfigV3,
|
|
4204
|
+
parseProject,
|
|
4205
|
+
point,
|
|
4206
|
+
projectDuration,
|
|
4207
|
+
projectWarnings,
|
|
4208
|
+
pulse,
|
|
4209
|
+
rebuildConfigV3Scene,
|
|
4210
|
+
removeScene,
|
|
4211
|
+
repeaterLayers,
|
|
4212
|
+
sceneAtTime,
|
|
4213
|
+
sceneStyle,
|
|
4214
|
+
serializeProject,
|
|
4215
|
+
sourceFingerprint,
|
|
4216
|
+
sourcePreviewHtml,
|
|
4217
|
+
textLineStyle,
|
|
4218
|
+
textUnitStyle,
|
|
4219
|
+
updateSourceText,
|
|
4220
|
+
upgradeConfigV2ToV3,
|
|
4221
|
+
validateProject,
|
|
4222
|
+
visualThemes
|
|
4223
|
+
});
|