@appinternalleads/ui 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/agent/AgentComponent.js +1 -1
- package/dist/cjs/agent/AgentComponent.js.map +1 -1
- package/dist/cjs/agent/manifests.js +81 -1
- package/dist/cjs/agent/manifests.js.map +1 -1
- package/dist/cjs/agent/result.js +6 -0
- package/dist/cjs/agent/result.js.map +1 -1
- package/dist/cjs/components/catalog.js +18 -0
- package/dist/cjs/components/catalog.js.map +1 -1
- package/dist/cjs/components/onboarding/animated-status/AnimatedStage.js +21 -0
- package/dist/cjs/components/onboarding/animated-status/AnimatedStage.js.map +1 -0
- package/dist/cjs/components/onboarding/animated-status/AnimatedStage.types.js +6 -0
- package/dist/cjs/components/onboarding/animated-status/AnimatedStage.types.js.map +1 -0
- package/dist/cjs/components/onboarding/animated-status/AnimatedStage.web.js +89 -0
- package/dist/cjs/components/onboarding/animated-status/AnimatedStage.web.js.map +1 -0
- package/dist/cjs/components/onboarding/animated-status/AnimatedStatusView.js +62 -0
- package/dist/cjs/components/onboarding/animated-status/AnimatedStatusView.js.map +1 -0
- package/dist/cjs/components/onboarding/animated-status/AnimatedStill.js +20 -0
- package/dist/cjs/components/onboarding/animated-status/AnimatedStill.js.map +1 -0
- package/dist/cjs/components/onboarding/animated-status/contract.js +87 -0
- package/dist/cjs/components/onboarding/animated-status/contract.js.map +1 -0
- package/dist/cjs/components/onboarding/animated-status/engine.js +40 -0
- package/dist/cjs/components/onboarding/animated-status/engine.js.map +1 -0
- package/dist/cjs/components/onboarding/animated-status/index.js +20 -0
- package/dist/cjs/components/onboarding/animated-status/index.js.map +1 -0
- package/dist/cjs/components/onboarding/animated-status/presets.json +126 -0
- package/dist/cjs/components/onboarding/animated-status/riv.js +7 -0
- package/dist/cjs/components/onboarding/animated-status/riv.js.map +1 -0
- package/dist/cjs/components/onboarding/index.js +4 -0
- package/dist/cjs/components/onboarding/index.js.map +1 -1
- package/dist/cjs/components/onboarding/presets.js +90 -84
- package/dist/cjs/components/onboarding/presets.js.map +1 -1
- package/dist/cjs/components/onboarding/receipt-printer/ReceiptStage.js +43 -6
- package/dist/cjs/components/onboarding/receipt-printer/ReceiptStage.js.map +1 -1
- package/dist/cjs/components/onboarding/send-completion/SendCompletionView.js +111 -0
- package/dist/cjs/components/onboarding/send-completion/SendCompletionView.js.map +1 -0
- package/dist/cjs/components/onboarding/send-completion/SendStage.js +37 -0
- package/dist/cjs/components/onboarding/send-completion/SendStage.js.map +1 -0
- package/dist/cjs/components/onboarding/send-completion/SendStage.types.js +6 -0
- package/dist/cjs/components/onboarding/send-completion/SendStage.types.js.map +1 -0
- package/dist/cjs/components/onboarding/send-completion/SendStage.web.js +107 -0
- package/dist/cjs/components/onboarding/send-completion/SendStage.web.js.map +1 -0
- package/dist/cjs/components/onboarding/send-completion/SendStill.js +17 -0
- package/dist/cjs/components/onboarding/send-completion/SendStill.js.map +1 -0
- package/dist/cjs/components/onboarding/send-completion/contract.js +83 -0
- package/dist/cjs/components/onboarding/send-completion/contract.js.map +1 -0
- package/dist/cjs/components/onboarding/send-completion/engine.js +32 -0
- package/dist/cjs/components/onboarding/send-completion/engine.js.map +1 -0
- package/dist/cjs/components/onboarding/send-completion/index.js +22 -0
- package/dist/cjs/components/onboarding/send-completion/index.js.map +1 -0
- package/dist/cjs/components/onboarding/send-completion/presets.json +132 -0
- package/dist/cjs/components/onboarding/send-completion/riv.js +7 -0
- package/dist/cjs/components/onboarding/send-completion/riv.js.map +1 -0
- package/dist/cjs/components/onboarding/shared/actions-data.js +2 -0
- package/dist/cjs/components/onboarding/shared/actions-data.js.map +1 -1
- package/dist/cjs/components/onboarding/shared/configColor.js +76 -0
- package/dist/cjs/components/onboarding/shared/configColor.js.map +1 -0
- package/dist/cjs/components/onboarding/shared/contract.js +4 -0
- package/dist/cjs/components/onboarding/shared/contract.js.map +1 -1
- package/dist/cjs/components/onboarding/shared/describe.js +1 -1
- package/dist/cjs/components/onboarding/shared/describe.js.map +1 -1
- package/dist/cjs/components/onboarding/shared/mock.js +2 -0
- package/dist/cjs/components/onboarding/shared/mock.js.map +1 -1
- package/dist/cjs/components/onboarding/views.js +8 -0
- package/dist/cjs/components/onboarding/views.js.map +1 -1
- package/dist/cjs/motion/MotionPlayer.js +42 -0
- package/dist/cjs/motion/MotionPlayer.js.map +1 -0
- package/dist/cjs/motion/agent.js +323 -0
- package/dist/cjs/motion/agent.js.map +1 -0
- package/dist/cjs/motion/cat/Cat.js +79 -0
- package/dist/cjs/motion/cat/Cat.js.map +1 -0
- package/dist/cjs/motion/cat/animation.js +204 -0
- package/dist/cjs/motion/cat/animation.js.map +1 -0
- package/dist/cjs/motion/cat/art.generated.js +37 -0
- package/dist/cjs/motion/cat/art.generated.js.map +1 -0
- package/dist/cjs/motion/cat/config.js +136 -0
- package/dist/cjs/motion/cat/config.js.map +1 -0
- package/dist/cjs/motion/cat/index.js +75 -0
- package/dist/cjs/motion/cat/index.js.map +1 -0
- package/dist/cjs/motion/cat/rig.js +99 -0
- package/dist/cjs/motion/cat/rig.js.map +1 -0
- package/dist/cjs/motion/cat/scene.js +148 -0
- package/dist/cjs/motion/cat/scene.js.map +1 -0
- package/dist/cjs/motion/configurable/config.js +477 -0
- package/dist/cjs/motion/configurable/config.js.map +1 -0
- package/dist/cjs/motion/configurable/controls.js +44 -0
- package/dist/cjs/motion/configurable/controls.js.map +1 -0
- package/dist/cjs/motion/easing.js +62 -0
- package/dist/cjs/motion/easing.js.map +1 -0
- package/dist/cjs/motion/fit.js +12 -0
- package/dist/cjs/motion/fit.js.map +1 -0
- package/dist/cjs/motion/index.js +101 -0
- package/dist/cjs/motion/index.js.map +1 -0
- package/dist/cjs/motion/neon/GlowRenderer.js +18 -0
- package/dist/cjs/motion/neon/GlowRenderer.js.map +1 -0
- package/dist/cjs/motion/neon/NeonCanvas.js +97 -0
- package/dist/cjs/motion/neon/NeonCanvas.js.map +1 -0
- package/dist/cjs/motion/neon/NeonText.js +108 -0
- package/dist/cjs/motion/neon/NeonText.js.map +1 -0
- package/dist/cjs/motion/neon/NeonTextFrame.js +36 -0
- package/dist/cjs/motion/neon/NeonTextFrame.js.map +1 -0
- package/dist/cjs/motion/neon/artwork.js +102 -0
- package/dist/cjs/motion/neon/artwork.js.map +1 -0
- package/dist/cjs/motion/neon/audio.js +165 -0
- package/dist/cjs/motion/neon/audio.js.map +1 -0
- package/dist/cjs/motion/neon/config.js +334 -0
- package/dist/cjs/motion/neon/config.js.map +1 -0
- package/dist/cjs/motion/neon/flicker.js +196 -0
- package/dist/cjs/motion/neon/flicker.js.map +1 -0
- package/dist/cjs/motion/neon/fonts.js +52 -0
- package/dist/cjs/motion/neon/fonts.js.map +1 -0
- package/dist/cjs/motion/neon/frame.js +24 -0
- package/dist/cjs/motion/neon/frame.js.map +1 -0
- package/dist/cjs/motion/neon/glitch.js +114 -0
- package/dist/cjs/motion/neon/glitch.js.map +1 -0
- package/dist/cjs/motion/neon/index.js +119 -0
- package/dist/cjs/motion/neon/index.js.map +1 -0
- package/dist/cjs/motion/neon/layers.js +68 -0
- package/dist/cjs/motion/neon/layers.js.map +1 -0
- package/dist/cjs/motion/neon/material.js +56 -0
- package/dist/cjs/motion/neon/material.js.map +1 -0
- package/dist/cjs/motion/neon/random.js +43 -0
- package/dist/cjs/motion/neon/random.js.map +1 -0
- package/dist/cjs/motion/neon/scene.js +549 -0
- package/dist/cjs/motion/neon/scene.js.map +1 -0
- package/dist/cjs/motion/neon/synth.js +213 -0
- package/dist/cjs/motion/neon/synth.js.map +1 -0
- package/dist/cjs/motion/neon/typography.js +81 -0
- package/dist/cjs/motion/neon/typography.js.map +1 -0
- package/dist/cjs/motion/neon/wall.js +113 -0
- package/dist/cjs/motion/neon/wall.js.map +1 -0
- package/dist/cjs/motion/paperfold/PaperFold.js +40 -0
- package/dist/cjs/motion/paperfold/PaperFold.js.map +1 -0
- package/dist/cjs/motion/paperfold/PaperFoldFrame.js +290 -0
- package/dist/cjs/motion/paperfold/PaperFoldFrame.js.map +1 -0
- package/dist/cjs/motion/paperfold/PaperFoldPlayer.js +59 -0
- package/dist/cjs/motion/paperfold/PaperFoldPlayer.js.map +1 -0
- package/dist/cjs/motion/paperfold/art.js +388 -0
- package/dist/cjs/motion/paperfold/art.js.map +1 -0
- package/dist/cjs/motion/paperfold/config.js +103 -0
- package/dist/cjs/motion/paperfold/config.js.map +1 -0
- package/dist/cjs/motion/paperfold/controls.js +493 -0
- package/dist/cjs/motion/paperfold/controls.js.map +1 -0
- package/dist/cjs/motion/paperfold/engine.js +722 -0
- package/dist/cjs/motion/paperfold/engine.js.map +1 -0
- package/dist/cjs/motion/paperfold/fonts.js +25 -0
- package/dist/cjs/motion/paperfold/fonts.js.map +1 -0
- package/dist/cjs/motion/paperfold/index.js +113 -0
- package/dist/cjs/motion/paperfold/index.js.map +1 -0
- package/dist/cjs/motion/paperfold/manipulate.js +170 -0
- package/dist/cjs/motion/paperfold/manipulate.js.map +1 -0
- package/dist/cjs/motion/paperfold/presets.js +119 -0
- package/dist/cjs/motion/paperfold/presets.js.map +1 -0
- package/dist/cjs/motion/paperfold/template.js +40 -0
- package/dist/cjs/motion/paperfold/template.js.map +1 -0
- package/dist/cjs/motion/player.js +203 -0
- package/dist/cjs/motion/player.js.map +1 -0
- package/dist/cjs/motion/promo/PromoFrame.js +293 -0
- package/dist/cjs/motion/promo/PromoFrame.js.map +1 -0
- package/dist/cjs/motion/promo/PromoShowcasePlayer.js +59 -0
- package/dist/cjs/motion/promo/PromoShowcasePlayer.js.map +1 -0
- package/dist/cjs/motion/promo/config.js +565 -0
- package/dist/cjs/motion/promo/config.js.map +1 -0
- package/dist/cjs/motion/promo/controls.js +571 -0
- package/dist/cjs/motion/promo/controls.js.map +1 -0
- package/dist/cjs/motion/promo/easing.js +35 -0
- package/dist/cjs/motion/promo/easing.js.map +1 -0
- package/dist/cjs/motion/promo/engine.js +567 -0
- package/dist/cjs/motion/promo/engine.js.map +1 -0
- package/dist/cjs/motion/promo/fonts.js +20 -0
- package/dist/cjs/motion/promo/fonts.js.map +1 -0
- package/dist/cjs/motion/promo/icons.js +29 -0
- package/dist/cjs/motion/promo/icons.js.map +1 -0
- package/dist/cjs/motion/promo/index.js +73 -0
- package/dist/cjs/motion/promo/index.js.map +1 -0
- package/dist/cjs/motion/promo/presets.js +44 -0
- package/dist/cjs/motion/promo/presets.js.map +1 -0
- package/dist/cjs/motion/promo/template.js +38 -0
- package/dist/cjs/motion/promo/template.js.map +1 -0
- package/dist/cjs/motion/replication2/Replication2Player.js +93 -0
- package/dist/cjs/motion/replication2/Replication2Player.js.map +1 -0
- package/dist/cjs/motion/replication2/config.js +352 -0
- package/dist/cjs/motion/replication2/config.js.map +1 -0
- package/dist/cjs/motion/replication2/controls.js +286 -0
- package/dist/cjs/motion/replication2/controls.js.map +1 -0
- package/dist/cjs/motion/replication2/driver.js +68 -0
- package/dist/cjs/motion/replication2/driver.js.map +1 -0
- package/dist/cjs/motion/replication2/easing.js +97 -0
- package/dist/cjs/motion/replication2/easing.js.map +1 -0
- package/dist/cjs/motion/replication2/engine.js +481 -0
- package/dist/cjs/motion/replication2/engine.js.map +1 -0
- package/dist/cjs/motion/replication2/html.js +88 -0
- package/dist/cjs/motion/replication2/html.js.map +1 -0
- package/dist/cjs/motion/replication2/index.js +61 -0
- package/dist/cjs/motion/replication2/index.js.map +1 -0
- package/dist/cjs/motion/replication2/measure.js +30 -0
- package/dist/cjs/motion/replication2/measure.js.map +1 -0
- package/dist/cjs/motion/replication2/metrics.js +10 -0
- package/dist/cjs/motion/replication2/metrics.js.map +1 -0
- package/dist/cjs/motion/replication2/presets.js +67 -0
- package/dist/cjs/motion/replication2/presets.js.map +1 -0
- package/dist/cjs/motion/replication2/riv.js +7 -0
- package/dist/cjs/motion/replication2/riv.js.map +1 -0
- package/dist/cjs/motion/replication2/rive-contract.js +158 -0
- package/dist/cjs/motion/replication2/rive-contract.js.map +1 -0
- package/dist/cjs/motion/replication2/template.js +35 -0
- package/dist/cjs/motion/replication2/template.js.map +1 -0
- package/dist/cjs/motion/sample.js +149 -0
- package/dist/cjs/motion/sample.js.map +1 -0
- package/dist/cjs/motion/templates/hey-template.js +1552 -0
- package/dist/cjs/motion/templates/hey-template.js.map +1 -0
- package/dist/cjs/motion/templates/index.js +22 -0
- package/dist/cjs/motion/templates/index.js.map +1 -0
- package/dist/cjs/motion/templates/word-motion.js +1165 -0
- package/dist/cjs/motion/templates/word-motion.js.map +1 -0
- package/dist/cjs/motion/types.js +3 -0
- package/dist/cjs/motion/types.js.map +1 -0
- package/dist/cjs/motion/typesurface/TypeSurfaceCanvas.js +62 -0
- package/dist/cjs/motion/typesurface/TypeSurfaceCanvas.js.map +1 -0
- package/dist/cjs/motion/typesurface/art.js +861 -0
- package/dist/cjs/motion/typesurface/art.js.map +1 -0
- package/dist/cjs/motion/typesurface/config.js +269 -0
- package/dist/cjs/motion/typesurface/config.js.map +1 -0
- package/dist/cjs/motion/typesurface/engine.js +607 -0
- package/dist/cjs/motion/typesurface/engine.js.map +1 -0
- package/dist/cjs/motion/typesurface/fonts.js +45 -0
- package/dist/cjs/motion/typesurface/fonts.js.map +1 -0
- package/dist/cjs/motion/typesurface/index.js +72 -0
- package/dist/cjs/motion/typesurface/index.js.map +1 -0
- package/dist/cjs/motion/typesurface/layout.js +130 -0
- package/dist/cjs/motion/typesurface/layout.js.map +1 -0
- package/dist/cjs/motion/typesurface/ops.js +175 -0
- package/dist/cjs/motion/typesurface/ops.js.map +1 -0
- package/dist/cjs/motion/typesurface/presets.js +192 -0
- package/dist/cjs/motion/typesurface/presets.js.map +1 -0
- package/dist/cjs/motion/typesurface/renderer.js +672 -0
- package/dist/cjs/motion/typesurface/renderer.js.map +1 -0
- package/dist/cjs/motion/typesurface/shaders.js +300 -0
- package/dist/cjs/motion/typesurface/shaders.js.map +1 -0
- package/dist/cjs/motion/typesurface/surfaces.js +156 -0
- package/dist/cjs/motion/typesurface/surfaces.js.map +1 -0
- package/dist/cjs/motion/typesurface/text.js +34 -0
- package/dist/cjs/motion/typesurface/text.js.map +1 -0
- package/dist/cjs/motion/typesurface/timeline.js +64 -0
- package/dist/cjs/motion/typesurface/timeline.js.map +1 -0
- package/dist/cjs/motion/validate.js +89 -0
- package/dist/cjs/motion/validate.js.map +1 -0
- package/dist/cjs/native/RiveReceiptStage.js +9 -150
- package/dist/cjs/native/RiveReceiptStage.js.map +1 -1
- package/dist/cjs/native/riveReceiptStageFactory.js +162 -0
- package/dist/cjs/native/riveReceiptStageFactory.js.map +1 -0
- package/dist/cjs/tokens/stage.js +10 -0
- package/dist/cjs/tokens/stage.js.map +1 -0
- package/dist/esm/agent/AgentComponent.js +1 -1
- package/dist/esm/agent/AgentComponent.js.map +1 -1
- package/dist/esm/agent/manifests.d.ts.map +1 -1
- package/dist/esm/agent/manifests.js +81 -1
- package/dist/esm/agent/manifests.js.map +1 -1
- package/dist/esm/agent/result.d.ts.map +1 -1
- package/dist/esm/agent/result.js +6 -0
- package/dist/esm/agent/result.js.map +1 -1
- package/dist/esm/agent/types.d.ts +1 -1
- package/dist/esm/agent/types.d.ts.map +1 -1
- package/dist/esm/components/catalog.d.ts +1 -1
- package/dist/esm/components/catalog.d.ts.map +1 -1
- package/dist/esm/components/catalog.js +18 -0
- package/dist/esm/components/catalog.js.map +1 -1
- package/dist/esm/components/onboarding/animated-status/AnimatedStage.d.ts +9 -0
- package/dist/esm/components/onboarding/animated-status/AnimatedStage.d.ts.map +1 -0
- package/dist/esm/components/onboarding/animated-status/AnimatedStage.js +18 -0
- package/dist/esm/components/onboarding/animated-status/AnimatedStage.js.map +1 -0
- package/dist/esm/components/onboarding/animated-status/AnimatedStage.types.d.ts +31 -0
- package/dist/esm/components/onboarding/animated-status/AnimatedStage.types.d.ts.map +1 -0
- package/dist/esm/components/onboarding/animated-status/AnimatedStage.types.js +3 -0
- package/dist/esm/components/onboarding/animated-status/AnimatedStage.types.js.map +1 -0
- package/dist/esm/components/onboarding/animated-status/AnimatedStage.web.d.ts +4 -0
- package/dist/esm/components/onboarding/animated-status/AnimatedStage.web.d.ts.map +1 -0
- package/dist/esm/components/onboarding/animated-status/AnimatedStage.web.js +86 -0
- package/dist/esm/components/onboarding/animated-status/AnimatedStage.web.js.map +1 -0
- package/dist/esm/components/onboarding/animated-status/AnimatedStatusView.d.ts +32 -0
- package/dist/esm/components/onboarding/animated-status/AnimatedStatusView.d.ts.map +1 -0
- package/dist/esm/components/onboarding/animated-status/AnimatedStatusView.js +59 -0
- package/dist/esm/components/onboarding/animated-status/AnimatedStatusView.js.map +1 -0
- package/dist/esm/components/onboarding/animated-status/AnimatedStill.d.ts +8 -0
- package/dist/esm/components/onboarding/animated-status/AnimatedStill.d.ts.map +1 -0
- package/dist/esm/components/onboarding/animated-status/AnimatedStill.js +17 -0
- package/dist/esm/components/onboarding/animated-status/AnimatedStill.js.map +1 -0
- package/dist/esm/components/onboarding/animated-status/contract.d.ts +61 -0
- package/dist/esm/components/onboarding/animated-status/contract.d.ts.map +1 -0
- package/dist/esm/components/onboarding/animated-status/contract.js +78 -0
- package/dist/esm/components/onboarding/animated-status/contract.js.map +1 -0
- package/dist/esm/components/onboarding/animated-status/engine.d.ts +24 -0
- package/dist/esm/components/onboarding/animated-status/engine.d.ts.map +1 -0
- package/dist/esm/components/onboarding/animated-status/engine.js +32 -0
- package/dist/esm/components/onboarding/animated-status/engine.js.map +1 -0
- package/dist/esm/components/onboarding/animated-status/index.d.ts +5 -0
- package/dist/esm/components/onboarding/animated-status/index.d.ts.map +1 -0
- package/dist/esm/components/onboarding/animated-status/index.js +4 -0
- package/dist/esm/components/onboarding/animated-status/index.js.map +1 -0
- package/dist/esm/components/onboarding/animated-status/presets.json +126 -0
- package/dist/esm/components/onboarding/animated-status/riv.d.ts +3 -0
- package/dist/esm/components/onboarding/animated-status/riv.d.ts.map +1 -0
- package/dist/esm/components/onboarding/animated-status/riv.js +4 -0
- package/dist/esm/components/onboarding/animated-status/riv.js.map +1 -0
- package/dist/esm/components/onboarding/index.d.ts +2 -0
- package/dist/esm/components/onboarding/index.d.ts.map +1 -1
- package/dist/esm/components/onboarding/index.js +4 -0
- package/dist/esm/components/onboarding/index.js.map +1 -1
- package/dist/esm/components/onboarding/presets.d.ts.map +1 -1
- package/dist/esm/components/onboarding/presets.js +6 -0
- package/dist/esm/components/onboarding/presets.js.map +1 -1
- package/dist/esm/components/onboarding/receipt-printer/ReceiptStage.d.ts +4 -6
- package/dist/esm/components/onboarding/receipt-printer/ReceiptStage.d.ts.map +1 -1
- package/dist/esm/components/onboarding/receipt-printer/ReceiptStage.js +42 -6
- package/dist/esm/components/onboarding/receipt-printer/ReceiptStage.js.map +1 -1
- package/dist/esm/components/onboarding/send-completion/SendCompletionView.d.ts +47 -0
- package/dist/esm/components/onboarding/send-completion/SendCompletionView.d.ts.map +1 -0
- package/dist/esm/components/onboarding/send-completion/SendCompletionView.js +108 -0
- package/dist/esm/components/onboarding/send-completion/SendCompletionView.js.map +1 -0
- package/dist/esm/components/onboarding/send-completion/SendStage.d.ts +9 -0
- package/dist/esm/components/onboarding/send-completion/SendStage.d.ts.map +1 -0
- package/dist/esm/components/onboarding/send-completion/SendStage.js +34 -0
- package/dist/esm/components/onboarding/send-completion/SendStage.js.map +1 -0
- package/dist/esm/components/onboarding/send-completion/SendStage.types.d.ts +33 -0
- package/dist/esm/components/onboarding/send-completion/SendStage.types.d.ts.map +1 -0
- package/dist/esm/components/onboarding/send-completion/SendStage.types.js +3 -0
- package/dist/esm/components/onboarding/send-completion/SendStage.types.js.map +1 -0
- package/dist/esm/components/onboarding/send-completion/SendStage.web.d.ts +4 -0
- package/dist/esm/components/onboarding/send-completion/SendStage.web.d.ts.map +1 -0
- package/dist/esm/components/onboarding/send-completion/SendStage.web.js +104 -0
- package/dist/esm/components/onboarding/send-completion/SendStage.web.js.map +1 -0
- package/dist/esm/components/onboarding/send-completion/SendStill.d.ts +11 -0
- package/dist/esm/components/onboarding/send-completion/SendStill.d.ts.map +1 -0
- package/dist/esm/components/onboarding/send-completion/SendStill.js +14 -0
- package/dist/esm/components/onboarding/send-completion/SendStill.js.map +1 -0
- package/dist/esm/components/onboarding/send-completion/contract.d.ts +99 -0
- package/dist/esm/components/onboarding/send-completion/contract.d.ts.map +1 -0
- package/dist/esm/components/onboarding/send-completion/contract.js +76 -0
- package/dist/esm/components/onboarding/send-completion/contract.js.map +1 -0
- package/dist/esm/components/onboarding/send-completion/engine.d.ts +20 -0
- package/dist/esm/components/onboarding/send-completion/engine.d.ts.map +1 -0
- package/dist/esm/components/onboarding/send-completion/engine.js +28 -0
- package/dist/esm/components/onboarding/send-completion/engine.js.map +1 -0
- package/dist/esm/components/onboarding/send-completion/index.d.ts +6 -0
- package/dist/esm/components/onboarding/send-completion/index.d.ts.map +1 -0
- package/dist/esm/components/onboarding/send-completion/index.js +6 -0
- package/dist/esm/components/onboarding/send-completion/index.js.map +1 -0
- package/dist/esm/components/onboarding/send-completion/presets.json +132 -0
- package/dist/esm/components/onboarding/send-completion/riv.d.ts +3 -0
- package/dist/esm/components/onboarding/send-completion/riv.d.ts.map +1 -0
- package/dist/esm/components/onboarding/send-completion/riv.js +4 -0
- package/dist/esm/components/onboarding/send-completion/riv.js.map +1 -0
- package/dist/esm/components/onboarding/shared/actions-data.d.ts.map +1 -1
- package/dist/esm/components/onboarding/shared/actions-data.js +2 -0
- package/dist/esm/components/onboarding/shared/actions-data.js.map +1 -1
- package/dist/esm/components/onboarding/shared/configColor.d.ts +29 -0
- package/dist/esm/components/onboarding/shared/configColor.d.ts.map +1 -0
- package/dist/esm/components/onboarding/shared/configColor.js +69 -0
- package/dist/esm/components/onboarding/shared/configColor.js.map +1 -0
- package/dist/esm/components/onboarding/shared/contract.d.ts +1 -1
- package/dist/esm/components/onboarding/shared/contract.d.ts.map +1 -1
- package/dist/esm/components/onboarding/shared/contract.js +4 -0
- package/dist/esm/components/onboarding/shared/contract.js.map +1 -1
- package/dist/esm/components/onboarding/shared/describe.d.ts.map +1 -1
- package/dist/esm/components/onboarding/shared/describe.js +1 -1
- package/dist/esm/components/onboarding/shared/describe.js.map +1 -1
- package/dist/esm/components/onboarding/shared/mock.d.ts +2 -0
- package/dist/esm/components/onboarding/shared/mock.d.ts.map +1 -1
- package/dist/esm/components/onboarding/shared/mock.js +2 -0
- package/dist/esm/components/onboarding/shared/mock.js.map +1 -1
- package/dist/esm/components/onboarding/views.d.ts.map +1 -1
- package/dist/esm/components/onboarding/views.js +8 -0
- package/dist/esm/components/onboarding/views.js.map +1 -1
- package/dist/esm/motion/MotionPlayer.d.ts +22 -0
- package/dist/esm/motion/MotionPlayer.d.ts.map +1 -0
- package/dist/esm/motion/MotionPlayer.js +39 -0
- package/dist/esm/motion/MotionPlayer.js.map +1 -0
- package/dist/esm/motion/agent.d.ts +146 -0
- package/dist/esm/motion/agent.d.ts.map +1 -0
- package/dist/esm/motion/agent.js +278 -0
- package/dist/esm/motion/agent.js.map +1 -0
- package/dist/esm/motion/cat/Cat.d.ts +43 -0
- package/dist/esm/motion/cat/Cat.d.ts.map +1 -0
- package/dist/esm/motion/cat/Cat.js +74 -0
- package/dist/esm/motion/cat/Cat.js.map +1 -0
- package/dist/esm/motion/cat/animation.d.ts +86 -0
- package/dist/esm/motion/cat/animation.d.ts.map +1 -0
- package/dist/esm/motion/cat/animation.js +193 -0
- package/dist/esm/motion/cat/animation.js.map +1 -0
- package/dist/esm/motion/cat/art.generated.d.ts +53 -0
- package/dist/esm/motion/cat/art.generated.d.ts.map +1 -0
- package/dist/esm/motion/cat/art.generated.js +34 -0
- package/dist/esm/motion/cat/art.generated.js.map +1 -0
- package/dist/esm/motion/cat/config.d.ts +103 -0
- package/dist/esm/motion/cat/config.d.ts.map +1 -0
- package/dist/esm/motion/cat/config.js +129 -0
- package/dist/esm/motion/cat/config.js.map +1 -0
- package/dist/esm/motion/cat/index.d.ts +13 -0
- package/dist/esm/motion/cat/index.d.ts.map +1 -0
- package/dist/esm/motion/cat/index.js +13 -0
- package/dist/esm/motion/cat/index.js.map +1 -0
- package/dist/esm/motion/cat/rig.d.ts +44 -0
- package/dist/esm/motion/cat/rig.d.ts.map +1 -0
- package/dist/esm/motion/cat/rig.js +86 -0
- package/dist/esm/motion/cat/rig.js.map +1 -0
- package/dist/esm/motion/cat/scene.d.ts +66 -0
- package/dist/esm/motion/cat/scene.d.ts.map +1 -0
- package/dist/esm/motion/cat/scene.js +137 -0
- package/dist/esm/motion/cat/scene.js.map +1 -0
- package/dist/esm/motion/configurable/config.d.ts +80 -0
- package/dist/esm/motion/configurable/config.d.ts.map +1 -0
- package/dist/esm/motion/configurable/config.js +468 -0
- package/dist/esm/motion/configurable/config.js.map +1 -0
- package/dist/esm/motion/configurable/controls.d.ts +74 -0
- package/dist/esm/motion/configurable/controls.d.ts.map +1 -0
- package/dist/esm/motion/configurable/controls.js +38 -0
- package/dist/esm/motion/configurable/controls.js.map +1 -0
- package/dist/esm/motion/easing.d.ts +4 -0
- package/dist/esm/motion/easing.d.ts.map +1 -0
- package/dist/esm/motion/easing.js +58 -0
- package/dist/esm/motion/easing.js.map +1 -0
- package/dist/esm/motion/fit.d.ts +8 -0
- package/dist/esm/motion/fit.d.ts.map +1 -0
- package/dist/esm/motion/fit.js +8 -0
- package/dist/esm/motion/fit.js.map +1 -0
- package/dist/esm/motion/index.d.ts +27 -0
- package/dist/esm/motion/index.d.ts.map +1 -0
- package/dist/esm/motion/index.js +21 -0
- package/dist/esm/motion/index.js.map +1 -0
- package/dist/esm/motion/neon/GlowRenderer.d.ts +31 -0
- package/dist/esm/motion/neon/GlowRenderer.d.ts.map +1 -0
- package/dist/esm/motion/neon/GlowRenderer.js +14 -0
- package/dist/esm/motion/neon/GlowRenderer.js.map +1 -0
- package/dist/esm/motion/neon/NeonCanvas.d.ts +42 -0
- package/dist/esm/motion/neon/NeonCanvas.d.ts.map +1 -0
- package/dist/esm/motion/neon/NeonCanvas.js +92 -0
- package/dist/esm/motion/neon/NeonCanvas.js.map +1 -0
- package/dist/esm/motion/neon/NeonText.d.ts +26 -0
- package/dist/esm/motion/neon/NeonText.d.ts.map +1 -0
- package/dist/esm/motion/neon/NeonText.js +103 -0
- package/dist/esm/motion/neon/NeonText.js.map +1 -0
- package/dist/esm/motion/neon/NeonTextFrame.d.ts +29 -0
- package/dist/esm/motion/neon/NeonTextFrame.d.ts.map +1 -0
- package/dist/esm/motion/neon/NeonTextFrame.js +33 -0
- package/dist/esm/motion/neon/NeonTextFrame.js.map +1 -0
- package/dist/esm/motion/neon/artwork.d.ts +29 -0
- package/dist/esm/motion/neon/artwork.d.ts.map +1 -0
- package/dist/esm/motion/neon/artwork.js +98 -0
- package/dist/esm/motion/neon/artwork.js.map +1 -0
- package/dist/esm/motion/neon/audio.d.ts +49 -0
- package/dist/esm/motion/neon/audio.d.ts.map +1 -0
- package/dist/esm/motion/neon/audio.js +161 -0
- package/dist/esm/motion/neon/audio.js.map +1 -0
- package/dist/esm/motion/neon/config.d.ts +319 -0
- package/dist/esm/motion/neon/config.d.ts.map +1 -0
- package/dist/esm/motion/neon/config.js +319 -0
- package/dist/esm/motion/neon/config.js.map +1 -0
- package/dist/esm/motion/neon/flicker.d.ts +82 -0
- package/dist/esm/motion/neon/flicker.d.ts.map +1 -0
- package/dist/esm/motion/neon/flicker.js +187 -0
- package/dist/esm/motion/neon/flicker.js.map +1 -0
- package/dist/esm/motion/neon/fonts.d.ts +29 -0
- package/dist/esm/motion/neon/fonts.d.ts.map +1 -0
- package/dist/esm/motion/neon/fonts.js +47 -0
- package/dist/esm/motion/neon/fonts.js.map +1 -0
- package/dist/esm/motion/neon/frame.d.ts +22 -0
- package/dist/esm/motion/neon/frame.d.ts.map +1 -0
- package/dist/esm/motion/neon/frame.js +20 -0
- package/dist/esm/motion/neon/frame.js.map +1 -0
- package/dist/esm/motion/neon/glitch.d.ts +64 -0
- package/dist/esm/motion/neon/glitch.d.ts.map +1 -0
- package/dist/esm/motion/neon/glitch.js +108 -0
- package/dist/esm/motion/neon/glitch.js.map +1 -0
- package/dist/esm/motion/neon/index.d.ts +29 -0
- package/dist/esm/motion/neon/index.d.ts.map +1 -0
- package/dist/esm/motion/neon/index.js +28 -0
- package/dist/esm/motion/neon/index.js.map +1 -0
- package/dist/esm/motion/neon/layers.d.ts +56 -0
- package/dist/esm/motion/neon/layers.d.ts.map +1 -0
- package/dist/esm/motion/neon/layers.js +64 -0
- package/dist/esm/motion/neon/layers.js.map +1 -0
- package/dist/esm/motion/neon/material.d.ts +68 -0
- package/dist/esm/motion/neon/material.d.ts.map +1 -0
- package/dist/esm/motion/neon/material.js +51 -0
- package/dist/esm/motion/neon/material.js.map +1 -0
- package/dist/esm/motion/neon/random.d.ts +15 -0
- package/dist/esm/motion/neon/random.d.ts.map +1 -0
- package/dist/esm/motion/neon/random.js +37 -0
- package/dist/esm/motion/neon/random.js.map +1 -0
- package/dist/esm/motion/neon/scene.d.ts +255 -0
- package/dist/esm/motion/neon/scene.d.ts.map +1 -0
- package/dist/esm/motion/neon/scene.js +532 -0
- package/dist/esm/motion/neon/scene.js.map +1 -0
- package/dist/esm/motion/neon/synth.d.ts +18 -0
- package/dist/esm/motion/neon/synth.d.ts.map +1 -0
- package/dist/esm/motion/neon/synth.js +208 -0
- package/dist/esm/motion/neon/synth.js.map +1 -0
- package/dist/esm/motion/neon/typography.d.ts +53 -0
- package/dist/esm/motion/neon/typography.d.ts.map +1 -0
- package/dist/esm/motion/neon/typography.js +74 -0
- package/dist/esm/motion/neon/typography.js.map +1 -0
- package/dist/esm/motion/neon/wall.d.ts +62 -0
- package/dist/esm/motion/neon/wall.d.ts.map +1 -0
- package/dist/esm/motion/neon/wall.js +106 -0
- package/dist/esm/motion/neon/wall.js.map +1 -0
- package/dist/esm/motion/paperfold/PaperFold.d.ts +36 -0
- package/dist/esm/motion/paperfold/PaperFold.d.ts.map +1 -0
- package/dist/esm/motion/paperfold/PaperFold.js +37 -0
- package/dist/esm/motion/paperfold/PaperFold.js.map +1 -0
- package/dist/esm/motion/paperfold/PaperFoldFrame.d.ts +39 -0
- package/dist/esm/motion/paperfold/PaperFoldFrame.d.ts.map +1 -0
- package/dist/esm/motion/paperfold/PaperFoldFrame.js +283 -0
- package/dist/esm/motion/paperfold/PaperFoldFrame.js.map +1 -0
- package/dist/esm/motion/paperfold/PaperFoldPlayer.d.ts +27 -0
- package/dist/esm/motion/paperfold/PaperFoldPlayer.d.ts.map +1 -0
- package/dist/esm/motion/paperfold/PaperFoldPlayer.js +56 -0
- package/dist/esm/motion/paperfold/PaperFoldPlayer.js.map +1 -0
- package/dist/esm/motion/paperfold/art.d.ts +148 -0
- package/dist/esm/motion/paperfold/art.d.ts.map +1 -0
- package/dist/esm/motion/paperfold/art.js +374 -0
- package/dist/esm/motion/paperfold/art.js.map +1 -0
- package/dist/esm/motion/paperfold/config.d.ts +47 -0
- package/dist/esm/motion/paperfold/config.d.ts.map +1 -0
- package/dist/esm/motion/paperfold/config.js +96 -0
- package/dist/esm/motion/paperfold/config.js.map +1 -0
- package/dist/esm/motion/paperfold/controls.d.ts +57 -0
- package/dist/esm/motion/paperfold/controls.d.ts.map +1 -0
- package/dist/esm/motion/paperfold/controls.js +506 -0
- package/dist/esm/motion/paperfold/controls.js.map +1 -0
- package/dist/esm/motion/paperfold/engine.d.ts +397 -0
- package/dist/esm/motion/paperfold/engine.d.ts.map +1 -0
- package/dist/esm/motion/paperfold/engine.js +699 -0
- package/dist/esm/motion/paperfold/engine.js.map +1 -0
- package/dist/esm/motion/paperfold/fonts.d.ts +3 -0
- package/dist/esm/motion/paperfold/fonts.d.ts.map +1 -0
- package/dist/esm/motion/paperfold/fonts.js +21 -0
- package/dist/esm/motion/paperfold/fonts.js.map +1 -0
- package/dist/esm/motion/paperfold/index.d.ts +17 -0
- package/dist/esm/motion/paperfold/index.d.ts.map +1 -0
- package/dist/esm/motion/paperfold/index.js +17 -0
- package/dist/esm/motion/paperfold/index.js.map +1 -0
- package/dist/esm/motion/paperfold/manipulate.d.ts +59 -0
- package/dist/esm/motion/paperfold/manipulate.d.ts.map +1 -0
- package/dist/esm/motion/paperfold/manipulate.js +161 -0
- package/dist/esm/motion/paperfold/manipulate.js.map +1 -0
- package/dist/esm/motion/paperfold/presets.d.ts +9 -0
- package/dist/esm/motion/paperfold/presets.d.ts.map +1 -0
- package/dist/esm/motion/paperfold/presets.js +115 -0
- package/dist/esm/motion/paperfold/presets.js.map +1 -0
- package/dist/esm/motion/paperfold/template.d.ts +3 -0
- package/dist/esm/motion/paperfold/template.d.ts.map +1 -0
- package/dist/esm/motion/paperfold/template.js +37 -0
- package/dist/esm/motion/paperfold/template.js.map +1 -0
- package/dist/esm/motion/player.d.ts +35 -0
- package/dist/esm/motion/player.d.ts.map +1 -0
- package/dist/esm/motion/player.js +197 -0
- package/dist/esm/motion/player.js.map +1 -0
- package/dist/esm/motion/promo/PromoFrame.d.ts +31 -0
- package/dist/esm/motion/promo/PromoFrame.d.ts.map +1 -0
- package/dist/esm/motion/promo/PromoFrame.js +288 -0
- package/dist/esm/motion/promo/PromoFrame.js.map +1 -0
- package/dist/esm/motion/promo/PromoShowcasePlayer.d.ts +25 -0
- package/dist/esm/motion/promo/PromoShowcasePlayer.d.ts.map +1 -0
- package/dist/esm/motion/promo/PromoShowcasePlayer.js +56 -0
- package/dist/esm/motion/promo/PromoShowcasePlayer.js.map +1 -0
- package/dist/esm/motion/promo/config.d.ts +91 -0
- package/dist/esm/motion/promo/config.d.ts.map +1 -0
- package/dist/esm/motion/promo/config.js +550 -0
- package/dist/esm/motion/promo/config.js.map +1 -0
- package/dist/esm/motion/promo/controls.d.ts +86 -0
- package/dist/esm/motion/promo/controls.d.ts.map +1 -0
- package/dist/esm/motion/promo/controls.js +567 -0
- package/dist/esm/motion/promo/controls.js.map +1 -0
- package/dist/esm/motion/promo/easing.d.ts +3 -0
- package/dist/esm/motion/promo/easing.d.ts.map +1 -0
- package/dist/esm/motion/promo/easing.js +32 -0
- package/dist/esm/motion/promo/easing.js.map +1 -0
- package/dist/esm/motion/promo/engine.d.ts +205 -0
- package/dist/esm/motion/promo/engine.d.ts.map +1 -0
- package/dist/esm/motion/promo/engine.js +551 -0
- package/dist/esm/motion/promo/engine.js.map +1 -0
- package/dist/esm/motion/promo/fonts.d.ts +7 -0
- package/dist/esm/motion/promo/fonts.d.ts.map +1 -0
- package/dist/esm/motion/promo/fonts.js +16 -0
- package/dist/esm/motion/promo/fonts.js.map +1 -0
- package/dist/esm/motion/promo/icons.d.ts +7 -0
- package/dist/esm/motion/promo/icons.d.ts.map +1 -0
- package/dist/esm/motion/promo/icons.js +26 -0
- package/dist/esm/motion/promo/icons.js.map +1 -0
- package/dist/esm/motion/promo/index.d.ts +15 -0
- package/dist/esm/motion/promo/index.d.ts.map +1 -0
- package/dist/esm/motion/promo/index.js +15 -0
- package/dist/esm/motion/promo/index.js.map +1 -0
- package/dist/esm/motion/promo/presets.d.ts +13 -0
- package/dist/esm/motion/promo/presets.d.ts.map +1 -0
- package/dist/esm/motion/promo/presets.js +40 -0
- package/dist/esm/motion/promo/presets.js.map +1 -0
- package/dist/esm/motion/promo/template.d.ts +8 -0
- package/dist/esm/motion/promo/template.d.ts.map +1 -0
- package/dist/esm/motion/promo/template.js +35 -0
- package/dist/esm/motion/promo/template.js.map +1 -0
- package/dist/esm/motion/replication2/Replication2Player.d.ts +26 -0
- package/dist/esm/motion/replication2/Replication2Player.d.ts.map +1 -0
- package/dist/esm/motion/replication2/Replication2Player.js +90 -0
- package/dist/esm/motion/replication2/Replication2Player.js.map +1 -0
- package/dist/esm/motion/replication2/config.d.ts +78 -0
- package/dist/esm/motion/replication2/config.d.ts.map +1 -0
- package/dist/esm/motion/replication2/config.js +341 -0
- package/dist/esm/motion/replication2/config.js.map +1 -0
- package/dist/esm/motion/replication2/controls.d.ts +70 -0
- package/dist/esm/motion/replication2/controls.d.ts.map +1 -0
- package/dist/esm/motion/replication2/controls.js +283 -0
- package/dist/esm/motion/replication2/controls.js.map +1 -0
- package/dist/esm/motion/replication2/driver.d.ts +23 -0
- package/dist/esm/motion/replication2/driver.d.ts.map +1 -0
- package/dist/esm/motion/replication2/driver.js +65 -0
- package/dist/esm/motion/replication2/driver.js.map +1 -0
- package/dist/esm/motion/replication2/easing.d.ts +19 -0
- package/dist/esm/motion/replication2/easing.d.ts.map +1 -0
- package/dist/esm/motion/replication2/easing.js +92 -0
- package/dist/esm/motion/replication2/easing.js.map +1 -0
- package/dist/esm/motion/replication2/engine.d.ts +236 -0
- package/dist/esm/motion/replication2/engine.d.ts.map +1 -0
- package/dist/esm/motion/replication2/engine.js +470 -0
- package/dist/esm/motion/replication2/engine.js.map +1 -0
- package/dist/esm/motion/replication2/html.d.ts +30 -0
- package/dist/esm/motion/replication2/html.d.ts.map +1 -0
- package/dist/esm/motion/replication2/html.js +83 -0
- package/dist/esm/motion/replication2/html.js.map +1 -0
- package/dist/esm/motion/replication2/index.d.ts +15 -0
- package/dist/esm/motion/replication2/index.d.ts.map +1 -0
- package/dist/esm/motion/replication2/index.js +15 -0
- package/dist/esm/motion/replication2/index.js.map +1 -0
- package/dist/esm/motion/replication2/measure.d.ts +3 -0
- package/dist/esm/motion/replication2/measure.d.ts.map +1 -0
- package/dist/esm/motion/replication2/measure.js +27 -0
- package/dist/esm/motion/replication2/measure.js.map +1 -0
- package/dist/esm/motion/replication2/metrics.d.ts +6 -0
- package/dist/esm/motion/replication2/metrics.d.ts.map +1 -0
- package/dist/esm/motion/replication2/metrics.js +7 -0
- package/dist/esm/motion/replication2/metrics.js.map +1 -0
- package/dist/esm/motion/replication2/presets.d.ts +13 -0
- package/dist/esm/motion/replication2/presets.d.ts.map +1 -0
- package/dist/esm/motion/replication2/presets.js +63 -0
- package/dist/esm/motion/replication2/presets.js.map +1 -0
- package/dist/esm/motion/replication2/riv.d.ts +3 -0
- package/dist/esm/motion/replication2/riv.d.ts.map +1 -0
- package/dist/esm/motion/replication2/riv.js +4 -0
- package/dist/esm/motion/replication2/riv.js.map +1 -0
- package/dist/esm/motion/replication2/rive-contract.d.ts +27 -0
- package/dist/esm/motion/replication2/rive-contract.d.ts.map +1 -0
- package/dist/esm/motion/replication2/rive-contract.js +153 -0
- package/dist/esm/motion/replication2/rive-contract.js.map +1 -0
- package/dist/esm/motion/replication2/template.d.ts +8 -0
- package/dist/esm/motion/replication2/template.d.ts.map +1 -0
- package/dist/esm/motion/replication2/template.js +32 -0
- package/dist/esm/motion/replication2/template.js.map +1 -0
- package/dist/esm/motion/sample.d.ts +61 -0
- package/dist/esm/motion/sample.d.ts.map +1 -0
- package/dist/esm/motion/sample.js +138 -0
- package/dist/esm/motion/sample.js.map +1 -0
- package/dist/esm/motion/templates/hey-template.d.ts +3 -0
- package/dist/esm/motion/templates/hey-template.d.ts.map +1 -0
- package/dist/esm/motion/templates/hey-template.js +1549 -0
- package/dist/esm/motion/templates/hey-template.js.map +1 -0
- package/dist/esm/motion/templates/index.d.ts +22 -0
- package/dist/esm/motion/templates/index.d.ts.map +1 -0
- package/dist/esm/motion/templates/index.js +15 -0
- package/dist/esm/motion/templates/index.js.map +1 -0
- package/dist/esm/motion/templates/word-motion.d.ts +3 -0
- package/dist/esm/motion/templates/word-motion.d.ts.map +1 -0
- package/dist/esm/motion/templates/word-motion.js +1162 -0
- package/dist/esm/motion/templates/word-motion.js.map +1 -0
- package/dist/esm/motion/types.d.ts +192 -0
- package/dist/esm/motion/types.d.ts.map +1 -0
- package/dist/esm/motion/types.js +2 -0
- package/dist/esm/motion/types.js.map +1 -0
- package/dist/esm/motion/typesurface/TypeSurfaceCanvas.d.ts +22 -0
- package/dist/esm/motion/typesurface/TypeSurfaceCanvas.d.ts.map +1 -0
- package/dist/esm/motion/typesurface/TypeSurfaceCanvas.js +58 -0
- package/dist/esm/motion/typesurface/TypeSurfaceCanvas.js.map +1 -0
- package/dist/esm/motion/typesurface/art.d.ts +21 -0
- package/dist/esm/motion/typesurface/art.d.ts.map +1 -0
- package/dist/esm/motion/typesurface/art.js +854 -0
- package/dist/esm/motion/typesurface/art.js.map +1 -0
- package/dist/esm/motion/typesurface/config.d.ts +273 -0
- package/dist/esm/motion/typesurface/config.d.ts.map +1 -0
- package/dist/esm/motion/typesurface/config.js +260 -0
- package/dist/esm/motion/typesurface/config.js.map +1 -0
- package/dist/esm/motion/typesurface/engine.d.ts +94 -0
- package/dist/esm/motion/typesurface/engine.d.ts.map +1 -0
- package/dist/esm/motion/typesurface/engine.js +603 -0
- package/dist/esm/motion/typesurface/engine.js.map +1 -0
- package/dist/esm/motion/typesurface/fonts.d.ts +25 -0
- package/dist/esm/motion/typesurface/fonts.d.ts.map +1 -0
- package/dist/esm/motion/typesurface/fonts.js +40 -0
- package/dist/esm/motion/typesurface/fonts.js.map +1 -0
- package/dist/esm/motion/typesurface/index.d.ts +17 -0
- package/dist/esm/motion/typesurface/index.d.ts.map +1 -0
- package/dist/esm/motion/typesurface/index.js +17 -0
- package/dist/esm/motion/typesurface/index.js.map +1 -0
- package/dist/esm/motion/typesurface/layout.d.ts +57 -0
- package/dist/esm/motion/typesurface/layout.d.ts.map +1 -0
- package/dist/esm/motion/typesurface/layout.js +122 -0
- package/dist/esm/motion/typesurface/layout.js.map +1 -0
- package/dist/esm/motion/typesurface/ops.d.ts +70 -0
- package/dist/esm/motion/typesurface/ops.d.ts.map +1 -0
- package/dist/esm/motion/typesurface/ops.js +164 -0
- package/dist/esm/motion/typesurface/ops.js.map +1 -0
- package/dist/esm/motion/typesurface/presets.d.ts +33 -0
- package/dist/esm/motion/typesurface/presets.d.ts.map +1 -0
- package/dist/esm/motion/typesurface/presets.js +185 -0
- package/dist/esm/motion/typesurface/presets.js.map +1 -0
- package/dist/esm/motion/typesurface/renderer.d.ts +78 -0
- package/dist/esm/motion/typesurface/renderer.d.ts.map +1 -0
- package/dist/esm/motion/typesurface/renderer.js +666 -0
- package/dist/esm/motion/typesurface/renderer.js.map +1 -0
- package/dist/esm/motion/typesurface/shaders.d.ts +17 -0
- package/dist/esm/motion/typesurface/shaders.d.ts.map +1 -0
- package/dist/esm/motion/typesurface/shaders.js +297 -0
- package/dist/esm/motion/typesurface/shaders.js.map +1 -0
- package/dist/esm/motion/typesurface/surfaces.d.ts +81 -0
- package/dist/esm/motion/typesurface/surfaces.d.ts.map +1 -0
- package/dist/esm/motion/typesurface/surfaces.js +149 -0
- package/dist/esm/motion/typesurface/surfaces.js.map +1 -0
- package/dist/esm/motion/typesurface/text.d.ts +17 -0
- package/dist/esm/motion/typesurface/text.d.ts.map +1 -0
- package/dist/esm/motion/typesurface/text.js +28 -0
- package/dist/esm/motion/typesurface/text.js.map +1 -0
- package/dist/esm/motion/typesurface/timeline.d.ts +15 -0
- package/dist/esm/motion/typesurface/timeline.d.ts.map +1 -0
- package/dist/esm/motion/typesurface/timeline.js +57 -0
- package/dist/esm/motion/typesurface/timeline.js.map +1 -0
- package/dist/esm/motion/validate.d.ts +22 -0
- package/dist/esm/motion/validate.d.ts.map +1 -0
- package/dist/esm/motion/validate.js +84 -0
- package/dist/esm/motion/validate.js.map +1 -0
- package/dist/esm/native/RiveReceiptStage.d.ts +25 -2
- package/dist/esm/native/RiveReceiptStage.d.ts.map +1 -1
- package/dist/esm/native/RiveReceiptStage.js +7 -148
- package/dist/esm/native/RiveReceiptStage.js.map +1 -1
- package/dist/esm/native/riveReceiptStageFactory.d.ts +26 -0
- package/dist/esm/native/riveReceiptStageFactory.d.ts.map +1 -0
- package/dist/esm/native/riveReceiptStageFactory.js +159 -0
- package/dist/esm/native/riveReceiptStageFactory.js.map +1 -0
- package/dist/esm/tokens/stage.d.ts +7 -0
- package/dist/esm/tokens/stage.d.ts.map +1 -0
- package/dist/esm/tokens/stage.js +7 -0
- package/dist/esm/tokens/stage.js.map +1 -0
- package/package.json +35 -1
- package/spec/examples/components/onboarding/animated-status/case1.json +42 -0
- package/spec/examples/components/onboarding/animated-status/case2.json +42 -0
- package/spec/examples/components/onboarding/animated-status/case3.json +42 -0
- package/spec/examples/components/onboarding/animated-status/case4.json +42 -0
- package/spec/examples/components/onboarding/animated-status/case5.json +42 -0
- package/spec/examples/components/onboarding/send-completion/case1.json +48 -0
- package/spec/examples/components/onboarding/send-completion/case2.json +48 -0
- package/spec/examples/components/onboarding/send-completion/case3.json +48 -0
- package/spec/examples/components/onboarding/send-completion/case4.json +48 -0
- package/spec/examples/components/onboarding/send-completion/case5.json +48 -0
- package/spec/families/onboarding.schema.json +610 -1
- package/src/agent/AgentComponent.tsx +1 -1
- package/src/agent/manifests.ts +83 -1
- package/src/agent/result.ts +6 -0
- package/src/agent/types.ts +1 -1
- package/src/components/catalog.ts +21 -1
- package/src/components/onboarding/animated-status/AnimatedStage.tsx +18 -0
- package/src/components/onboarding/animated-status/AnimatedStage.types.ts +30 -0
- package/src/components/onboarding/animated-status/AnimatedStage.web.tsx +99 -0
- package/src/components/onboarding/animated-status/AnimatedStatusView.tsx +109 -0
- package/src/components/onboarding/animated-status/AnimatedStill.tsx +23 -0
- package/src/components/onboarding/animated-status/contract.ts +105 -0
- package/src/components/onboarding/animated-status/engine.ts +49 -0
- package/src/components/onboarding/animated-status/index.ts +8 -0
- package/src/components/onboarding/animated-status/presets.json +126 -0
- package/src/components/onboarding/animated-status/riv.ts +4 -0
- package/src/components/onboarding/index.ts +4 -0
- package/src/components/onboarding/presets.ts +6 -0
- package/src/components/onboarding/receipt-printer/ReceiptStage.tsx +46 -7
- package/src/components/onboarding/send-completion/SendCompletionView.tsx +164 -0
- package/src/components/onboarding/send-completion/SendStage.tsx +27 -0
- package/src/components/onboarding/send-completion/SendStage.types.ts +32 -0
- package/src/components/onboarding/send-completion/SendStage.web.tsx +116 -0
- package/src/components/onboarding/send-completion/SendStill.tsx +19 -0
- package/src/components/onboarding/send-completion/contract.ts +127 -0
- package/src/components/onboarding/send-completion/engine.ts +37 -0
- package/src/components/onboarding/send-completion/index.ts +10 -0
- package/src/components/onboarding/send-completion/presets.json +132 -0
- package/src/components/onboarding/send-completion/riv.ts +4 -0
- package/src/components/onboarding/shared/actions-data.ts +2 -0
- package/src/components/onboarding/shared/configColor.ts +72 -0
- package/src/components/onboarding/shared/contract.ts +4 -0
- package/src/components/onboarding/shared/describe.ts +1 -1
- package/src/components/onboarding/shared/mock.ts +2 -0
- package/src/components/onboarding/views.ts +8 -0
- package/src/motion/MotionPlayer.tsx +62 -0
- package/src/motion/agent.ts +288 -0
- package/src/motion/cat/Cat.tsx +118 -0
- package/src/motion/cat/animation.ts +206 -0
- package/src/motion/cat/art.generated.ts +44 -0
- package/src/motion/cat/config.ts +186 -0
- package/src/motion/cat/index.ts +26 -0
- package/src/motion/cat/rig.ts +102 -0
- package/src/motion/cat/scene.ts +181 -0
- package/src/motion/configurable/config.ts +420 -0
- package/src/motion/configurable/controls.ts +93 -0
- package/src/motion/easing.ts +55 -0
- package/src/motion/fit.ts +8 -0
- package/src/motion/index.ts +29 -0
- package/src/motion/neon/GlowRenderer.tsx +83 -0
- package/src/motion/neon/NeonCanvas.tsx +175 -0
- package/src/motion/neon/NeonText.tsx +113 -0
- package/src/motion/neon/NeonTextFrame.tsx +67 -0
- package/src/motion/neon/artwork.ts +95 -0
- package/src/motion/neon/audio.ts +162 -0
- package/src/motion/neon/config.ts +484 -0
- package/src/motion/neon/flicker.ts +225 -0
- package/src/motion/neon/fonts.ts +76 -0
- package/src/motion/neon/frame.ts +34 -0
- package/src/motion/neon/glitch.ts +142 -0
- package/src/motion/neon/index.ts +41 -0
- package/src/motion/neon/layers.tsx +209 -0
- package/src/motion/neon/material.ts +88 -0
- package/src/motion/neon/random.ts +40 -0
- package/src/motion/neon/scene.ts +610 -0
- package/src/motion/neon/synth.ts +188 -0
- package/src/motion/neon/typography.ts +102 -0
- package/src/motion/neon/wall.ts +157 -0
- package/src/motion/paperfold/PaperFold.tsx +45 -0
- package/src/motion/paperfold/PaperFoldFrame.tsx +576 -0
- package/src/motion/paperfold/PaperFoldPlayer.tsx +80 -0
- package/src/motion/paperfold/art.ts +455 -0
- package/src/motion/paperfold/config.ts +98 -0
- package/src/motion/paperfold/controls.ts +557 -0
- package/src/motion/paperfold/engine.ts +852 -0
- package/src/motion/paperfold/fonts.ts +21 -0
- package/src/motion/paperfold/index.ts +30 -0
- package/src/motion/paperfold/manipulate.ts +188 -0
- package/src/motion/paperfold/presets.ts +117 -0
- package/src/motion/paperfold/template.ts +38 -0
- package/src/motion/player.ts +207 -0
- package/src/motion/promo/PromoFrame.tsx +501 -0
- package/src/motion/promo/PromoShowcasePlayer.tsx +78 -0
- package/src/motion/promo/config.ts +479 -0
- package/src/motion/promo/controls.ts +643 -0
- package/src/motion/promo/easing.ts +36 -0
- package/src/motion/promo/engine.ts +587 -0
- package/src/motion/promo/fonts.ts +16 -0
- package/src/motion/promo/icons.tsx +29 -0
- package/src/motion/promo/index.ts +24 -0
- package/src/motion/promo/presets.ts +40 -0
- package/src/motion/promo/template.ts +36 -0
- package/src/motion/replication2/Replication2Player.tsx +115 -0
- package/src/motion/replication2/config.ts +323 -0
- package/src/motion/replication2/controls.ts +336 -0
- package/src/motion/replication2/driver.ts +92 -0
- package/src/motion/replication2/easing.ts +88 -0
- package/src/motion/replication2/engine.ts +539 -0
- package/src/motion/replication2/html.ts +87 -0
- package/src/motion/replication2/index.ts +14 -0
- package/src/motion/replication2/measure.ts +28 -0
- package/src/motion/replication2/metrics.ts +7 -0
- package/src/motion/replication2/presets.ts +63 -0
- package/src/motion/replication2/riv.ts +4 -0
- package/src/motion/replication2/rive-contract.ts +165 -0
- package/src/motion/replication2/template.ts +33 -0
- package/src/motion/sample.ts +173 -0
- package/src/motion/templates/hey-template.ts +1553 -0
- package/src/motion/templates/index.ts +17 -0
- package/src/motion/templates/word-motion.ts +1166 -0
- package/src/motion/types.ts +162 -0
- package/src/motion/typesurface/TypeSurfaceCanvas.tsx +73 -0
- package/src/motion/typesurface/art.ts +639 -0
- package/src/motion/typesurface/config.ts +486 -0
- package/src/motion/typesurface/engine.ts +586 -0
- package/src/motion/typesurface/fonts.ts +63 -0
- package/src/motion/typesurface/index.ts +16 -0
- package/src/motion/typesurface/layout.ts +133 -0
- package/src/motion/typesurface/ops.ts +196 -0
- package/src/motion/typesurface/presets.ts +199 -0
- package/src/motion/typesurface/renderer.ts +579 -0
- package/src/motion/typesurface/shaders.ts +303 -0
- package/src/motion/typesurface/surfaces.ts +223 -0
- package/src/motion/typesurface/text.ts +35 -0
- package/src/motion/typesurface/timeline.ts +58 -0
- package/src/motion/validate.ts +101 -0
- package/src/native/RiveReceiptStage.tsx +8 -155
- package/src/native/riveReceiptStageFactory.tsx +175 -0
- package/src/tokens/stage.ts +6 -0
- package/tools/ask/dist/components.mjs +6887 -46
- package/tools/ask/mcp.mjs +80 -1
|
@@ -0,0 +1,852 @@
|
|
|
1
|
+
import { getPath, phaseSpans, type PaperFoldConfig } from './config';
|
|
2
|
+
import { LAYOUT_FOR, PANELS, PHASES, type AspectRatio, type HandId, type PanelId, type PhaseId } from './controls';
|
|
3
|
+
import { ease } from '../promo/easing';
|
|
4
|
+
import { mixHex, rgba, seeded } from '../promo/engine';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* **The paper-fold engine — a pure function from (config, frame, size) to everything on screen.** No
|
|
8
|
+
* clock, no unseeded randomness, no DOM: the same config, seed and frame always give the same state, so
|
|
9
|
+
* Remotion can render frames in any order and in parallel, and the live player and the video agree.
|
|
10
|
+
* The renderer (`PaperFoldFrame`) only draws what this returns.
|
|
11
|
+
*
|
|
12
|
+
* **The fold model.** The sheet is three rigid panels hinged at two creases — a kinematic chain. A
|
|
13
|
+
* fold is a rotation about its crease line (y = crease, z = 0 in the sheet's own frame) by the crease's
|
|
14
|
+
* dihedral angle; the panel on the moving side (`direction`) turns with it, the panel that stays put
|
|
15
|
+
* (the anchor) does not, and a panel beyond a moving panel is carried along. Each panel's full pose is
|
|
16
|
+
* a 4×4 matrix: sheet pose · hinge rotations · the camera's perspective. The renderer hands that
|
|
17
|
+
* matrix to CSS `matrix3d`, so the panel — its colour, texture and live text — is drawn in true
|
|
18
|
+
* perspective, turning about the exact crease line. Nothing is scaled to fake a fold.
|
|
19
|
+
*
|
|
20
|
+
* Depth is explicit: panels are painted back to front by the depth of their centres, and each hand's
|
|
21
|
+
* body and gripping finger are slotted in relative to the panel they hold. Lighting is Lambertian on
|
|
22
|
+
* each panel's normal; a closing crease darkens its valley and shades the panel it closes over.
|
|
23
|
+
*
|
|
24
|
+
* Frames here are authored 60 fps motion frames; `outputFrameToMotion` maps an output frame (at
|
|
25
|
+
* canvas.fps, after motion.speed) onto them.
|
|
26
|
+
*/
|
|
27
|
+
export const MOTION_FPS = 60;
|
|
28
|
+
export { mixHex, rgba, seeded };
|
|
29
|
+
|
|
30
|
+
const clamp = (v: number, lo = 0, hi = 1) => (v < lo ? lo : v > hi ? hi : v);
|
|
31
|
+
const lerp = (a: number, b: number, t: number) => a + (b - a) * t;
|
|
32
|
+
const RAD = Math.PI / 180;
|
|
33
|
+
const TAU = Math.PI * 2;
|
|
34
|
+
|
|
35
|
+
type Obj = Record<string, unknown>;
|
|
36
|
+
function reader(cfg: PaperFoldConfig) {
|
|
37
|
+
return {
|
|
38
|
+
n: (p: string) => getPath(cfg, p) as number,
|
|
39
|
+
s: (p: string) => getPath(cfg, p) as string,
|
|
40
|
+
b: (p: string) => getPath(cfg, p) as boolean,
|
|
41
|
+
list: <T = Obj>(p: string) => (getPath(cfg, p) as T[]) ?? [],
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* ─── 4×4 matrices (row-major, column vectors: p' = M · p) ────────────────────────────────────── */
|
|
46
|
+
export type Mat = number[];
|
|
47
|
+
export type Vec3 = [number, number, number];
|
|
48
|
+
const I = (): Mat => [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
|
|
49
|
+
export function mul(a: Mat, b: Mat): Mat {
|
|
50
|
+
const o = new Array<number>(16);
|
|
51
|
+
for (let r = 0; r < 4; r++) for (let c = 0; c < 4; c++) {
|
|
52
|
+
o[r * 4 + c] = a[r * 4]! * b[c]! + a[r * 4 + 1]! * b[4 + c]! + a[r * 4 + 2]! * b[8 + c]! + a[r * 4 + 3]! * b[12 + c]!;
|
|
53
|
+
}
|
|
54
|
+
return o;
|
|
55
|
+
}
|
|
56
|
+
const chain = (...ms: Mat[]) => ms.reduce((acc, m) => mul(acc, m), I());
|
|
57
|
+
const translate = (x: number, y: number, z = 0): Mat => [1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1];
|
|
58
|
+
const scale3 = (x: number, y: number): Mat => [x, 0, 0, 0, 0, y, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
|
|
59
|
+
/** About the x axis. With y down and z toward the viewer, a positive turn brings a point below the axis toward the viewer. */
|
|
60
|
+
const rotX = (a: number): Mat => { const c = Math.cos(a), s = Math.sin(a); return [1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1]; };
|
|
61
|
+
const rotY = (a: number): Mat => { const c = Math.cos(a), s = Math.sin(a); return [c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1]; };
|
|
62
|
+
/** In the picture plane; positive is clockwise on screen (as CSS rotate). */
|
|
63
|
+
const rotZ = (a: number): Mat => { const c = Math.cos(a), s = Math.sin(a); return [c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; };
|
|
64
|
+
const skew = (ax: number, ay: number): Mat => [1, Math.tan(ax), 0, 0, Math.tan(ay), 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
|
|
65
|
+
/** A viewer at distance d on the z axis, looking at (vx, vy): w = 1 − z/d (CSS perspective). */
|
|
66
|
+
const perspectiveAt = (vx: number, vy: number, d: number): Mat => chain(translate(vx, vy), [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, -1 / d, 1], translate(-vx, -vy));
|
|
67
|
+
/** A turn of `a` radians about the horizontal line y = yc (z = 0): the hinge of a crease. */
|
|
68
|
+
const hinge = (yc: number, a: number): Mat => chain(translate(0, yc), rotX(a), translate(0, -yc));
|
|
69
|
+
export function apply(m: Mat, p: Vec3): [number, number, number, number] {
|
|
70
|
+
const [x, y, z] = p;
|
|
71
|
+
return [
|
|
72
|
+
m[0]! * x + m[1]! * y + m[2]! * z + m[3]!, m[4]! * x + m[5]! * y + m[6]! * z + m[7]!,
|
|
73
|
+
m[8]! * x + m[9]! * y + m[10]! * z + m[11]!, m[12]! * x + m[13]! * y + m[14]! * z + m[15]!,
|
|
74
|
+
];
|
|
75
|
+
}
|
|
76
|
+
/** A point through a projective matrix, onto the picture. */
|
|
77
|
+
export function project(m: Mat, p: Vec3): [number, number] {
|
|
78
|
+
const [x, y, , w] = apply(m, p);
|
|
79
|
+
const ww = Math.max(w, 1e-3);
|
|
80
|
+
return [x / ww, y / ww];
|
|
81
|
+
}
|
|
82
|
+
const r4 = (v: number) => Math.round(v * 1e4) / 1e4;
|
|
83
|
+
/** CSS `matrix3d(...)` (column-major) of a row-major matrix. */
|
|
84
|
+
export function cssMatrix(m: Mat): string {
|
|
85
|
+
const o: number[] = [];
|
|
86
|
+
for (let c = 0; c < 4; c++) for (let r = 0; r < 4; r++) o.push(m[r * 4 + c]!);
|
|
87
|
+
// The perspective row (w) is tiny (≈ 1/distance): keep it at full precision, never in exponent form.
|
|
88
|
+
return `matrix3d(${o.map((v, i) => (i === 3 || i === 7 || i === 11 ? v.toFixed(12) : String(r4(v)))).join(', ')})`;
|
|
89
|
+
}
|
|
90
|
+
const cross = (a: Vec3, b: Vec3): Vec3 => [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
|
|
91
|
+
const norm3 = (v: Vec3): Vec3 => { const l = Math.hypot(v[0], v[1], v[2]) || 1; return [v[0] / l, v[1] / l, v[2] / l]; };
|
|
92
|
+
const dot3 = (a: Vec3, b: Vec3) => a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
93
|
+
const linear = (m: Mat, v: Vec3): Vec3 => [m[0]! * v[0] + m[1]! * v[1] + m[2]! * v[2], m[4]! * v[0] + m[5]! * v[1] + m[6]! * v[2], m[8]! * v[0] + m[9]! * v[1] + m[10]! * v[2]];
|
|
94
|
+
|
|
95
|
+
/* ─── time ────────────────────────────────────────────────────────────────────────────────────── */
|
|
96
|
+
export type PhaseSpan = { id: PhaseId; label: string; start: number; end: number };
|
|
97
|
+
export type Timeline = { phases: Record<PhaseId, PhaseSpan>; order: PhaseSpan[]; end: number; length: number; speed: number };
|
|
98
|
+
|
|
99
|
+
export function timeline(cfg: PaperFoldConfig): Timeline {
|
|
100
|
+
const { n, s } = reader(cfg);
|
|
101
|
+
const order = phaseSpans(cfg).map((p) => ({ id: p.id as PhaseId, label: p.label, start: p.start, end: p.end }));
|
|
102
|
+
const phases = Object.fromEntries(order.map((p) => [p.id, p])) as Record<PhaseId, PhaseSpan>;
|
|
103
|
+
const end = Math.max(...order.map((p) => p.end));
|
|
104
|
+
const speed = n('motion.speed');
|
|
105
|
+
// `length` is in authored frames: the part of the timeline the video shows.
|
|
106
|
+
const length = s('canvas.durationMode') === 'fixed' ? (n('canvas.durationFrames') * MOTION_FPS * speed) / n('canvas.fps') : end;
|
|
107
|
+
return { phases, order, end, length, speed };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Output frames for one play of the video at canvas.fps. */
|
|
111
|
+
export function outputDuration(cfg: PaperFoldConfig): number {
|
|
112
|
+
const { n, s } = reader(cfg);
|
|
113
|
+
if (s('canvas.durationMode') === 'fixed') return n('canvas.durationFrames');
|
|
114
|
+
return Math.max(1, Math.round(((timeline(cfg).end / n('motion.speed')) * n('canvas.fps')) / MOTION_FPS));
|
|
115
|
+
}
|
|
116
|
+
/** The authored motion frame an output frame shows. */
|
|
117
|
+
export function outputFrameToMotion(cfg: PaperFoldConfig, frame: number): number {
|
|
118
|
+
return (frame * MOTION_FPS * (getPath(cfg, 'motion.speed') as number)) / (getPath(cfg, 'canvas.fps') as number);
|
|
119
|
+
}
|
|
120
|
+
/** The output frame that shows an authored motion frame (the inverse of outputFrameToMotion, rounded). */
|
|
121
|
+
export function motionToOutputFrame(cfg: PaperFoldConfig, motion: number): number {
|
|
122
|
+
return Math.round((motion * (getPath(cfg, 'canvas.fps') as number)) / (MOTION_FPS * (getPath(cfg, 'motion.speed') as number)));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** The phase playing at motion frame `t` (the last phase that has started), and how far into it. */
|
|
126
|
+
export function phaseAt(tl: Timeline, t: number): { id: PhaseId; label: string; progress: number } {
|
|
127
|
+
let cur = tl.order[0]!;
|
|
128
|
+
for (const p of tl.order) if (t >= p.start && p.end > p.start) cur = p;
|
|
129
|
+
return { id: cur.id, label: cur.label, progress: cur.end > cur.start ? clamp((t - cur.start) / (cur.end - cur.start)) : 1 };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Representative motion frames of the seven stages (the render tests and the reference comparison use them). */
|
|
133
|
+
export function stageFrames(cfg: PaperFoldConfig) {
|
|
134
|
+
const { phases: p, end } = timeline(cfg);
|
|
135
|
+
const mid = (id: PhaseId) => (p[id].start + p[id].end) / 2;
|
|
136
|
+
const at = (id: PhaseId, f: number) => p[id].start + (p[id].end - p[id].start) * f;
|
|
137
|
+
return {
|
|
138
|
+
OPEN: p.topFold.start - 1 > 0 ? p.topFold.start - 1 : 0,
|
|
139
|
+
TOP_FOLD: mid('topFold'),
|
|
140
|
+
TOP_FOLD_BEGIN: p.topFold.start + (p.topFold.end - p.topFold.start) * 0.2,
|
|
141
|
+
TOP_FOLD_DEEPEST: p.topFold.end,
|
|
142
|
+
BOTTOM_FOLD: mid('bottomFold'),
|
|
143
|
+
BOTTOM_FOLD_BEGIN: p.bottomFold.start + (p.bottomFold.end - p.bottomFold.start) * 0.2,
|
|
144
|
+
FOLDED_HOLD: mid('foldedHold'),
|
|
145
|
+
BOTTOM_UNFOLD: mid('bottomUnfold'),
|
|
146
|
+
UNFOLD_BEGIN: p.bottomUnfold.start + (p.bottomUnfold.end - p.bottomUnfold.start) * 0.2,
|
|
147
|
+
TOP_UNFOLD: mid('topUnfold'),
|
|
148
|
+
FINAL_OPEN: Math.max(0, end - 1),
|
|
149
|
+
// The quality-check set: fractions of the top fold, the peaks, halfway through the whole unfold.
|
|
150
|
+
TOP_FOLD_25: at('topFold', 0.25),
|
|
151
|
+
TOP_FOLD_75: at('topFold', 0.75),
|
|
152
|
+
TOP_FOLD_PEAK: p.topFold.end,
|
|
153
|
+
BOTTOM_FOLD_PEAK: p.bottomFold.end,
|
|
154
|
+
FULLY_FOLDED: mid('foldedHold'),
|
|
155
|
+
UNFOLD_50: (p.bottomUnfold.start + p.topUnfold.end) / 2,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* ─── folds ───────────────────────────────────────────────────────────────────────────────────── */
|
|
160
|
+
type FoldCfg = {
|
|
161
|
+
id: 'top' | 'bottom'; enabled: boolean; direction: 'down' | 'up'; side: 'inward' | 'outward';
|
|
162
|
+
startAngle: number; peakAngle: number; endAngle: number; startScale: number; peakScale: number; endScale: number;
|
|
163
|
+
edgeLift: number; edgeLiftSize: number; curvature: number; perspective: number; translationX: number; translationY: number; rotationZ: number;
|
|
164
|
+
delayFrames: number; durationFrames: number; easing: string; unfoldDelayFrames: number; unfoldDurationFrames: number; unfoldEasing: string;
|
|
165
|
+
shadowIntensity: number; creaseIntensity: number;
|
|
166
|
+
};
|
|
167
|
+
export type FoldState = {
|
|
168
|
+
id: 'top' | 'bottom';
|
|
169
|
+
/** The crease's dihedral angle (deg). */
|
|
170
|
+
angle: number;
|
|
171
|
+
/** Signed: positive = the fronts close (a valley on the front). */
|
|
172
|
+
dihedral: number;
|
|
173
|
+
/** How far toward its peak the fold is (0 = open, 1 = at the peak). */
|
|
174
|
+
amount: number;
|
|
175
|
+
/** 0‥1‥0 while the fold or unfold is moving (a half sine), else 0. */
|
|
176
|
+
activity: number;
|
|
177
|
+
phase: 'before' | 'folding' | 'folded' | 'unfolding' | 'after' | 'off' | 'manual';
|
|
178
|
+
scale: number; perspective: number; tx: number; ty: number; rz: number;
|
|
179
|
+
/** How far the gripped free edge curls ahead of the fold (deg): it lifts first, then the panel folds over. */
|
|
180
|
+
lift: number;
|
|
181
|
+
};
|
|
182
|
+
/** The edge lift over a fold's progress `p` (0‥1, linear): it rises first and is flat again by 75%. */
|
|
183
|
+
const liftAt = (f: FoldCfg, p: number) => f.edgeLift * Math.max(0, Math.sin(Math.PI * clamp(p / 0.75)));
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* The folds posed by FOLD PROGRESS (motion.foldProgress, 0‥1) instead of the timeline: the first half
|
|
187
|
+
* folds the top crease from flat (0°) to its peak, the second half the bottom crease; a single enabled
|
|
188
|
+
* fold takes the whole range. 0 is the paper completely flat, 1 completely folded.
|
|
189
|
+
*/
|
|
190
|
+
export function manualFolds(folds: FoldCfg[], progress: number): FoldState[] {
|
|
191
|
+
const on = folds.map((f) => f.enabled);
|
|
192
|
+
const both = on[0] && on[1];
|
|
193
|
+
return folds.map((f, k) => {
|
|
194
|
+
const sigma = f.side === 'inward' ? 1 : -1;
|
|
195
|
+
const a = !f.enabled ? 0 : both ? clamp(progress * 2 - k) : clamp(progress);
|
|
196
|
+
const e = ease(f.easing, a, f.durationFrames);
|
|
197
|
+
const angle = lerp(0, f.peakAngle, e);
|
|
198
|
+
return {
|
|
199
|
+
id: f.id, angle, dihedral: sigma * angle, amount: e, activity: 0, phase: 'manual' as const,
|
|
200
|
+
scale: lerp(1, f.peakScale, e), perspective: lerp(1, f.perspective, e), tx: f.translationX * e, ty: f.translationY * e, rz: f.rotationZ * e,
|
|
201
|
+
lift: liftAt(f, a),
|
|
202
|
+
};
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function foldState(f: FoldCfg, foldSpan: PhaseSpan, unfoldSpan: PhaseSpan, t: number): FoldState {
|
|
207
|
+
const sigma = f.side === 'inward' ? 1 : -1;
|
|
208
|
+
if (!f.enabled) return { id: f.id, angle: f.startAngle, dihedral: sigma * f.startAngle, amount: 0, activity: 0, phase: 'off', scale: 1, perspective: 1, tx: 0, ty: 0, rz: 0, lift: 0 };
|
|
209
|
+
const pf = clamp((t - foldSpan.start) / Math.max(1e-6, foldSpan.end - foldSpan.start));
|
|
210
|
+
const pu = clamp((t - unfoldSpan.start) / Math.max(1e-6, unfoldSpan.end - unfoldSpan.start));
|
|
211
|
+
const ef = ease(f.easing, pf, f.durationFrames), eu = ease(f.unfoldEasing, pu, f.unfoldDurationFrames);
|
|
212
|
+
const unfolding = t >= unfoldSpan.start;
|
|
213
|
+
let angle: number, amount: number, sc: number;
|
|
214
|
+
if (!unfolding) {
|
|
215
|
+
angle = lerp(f.startAngle, f.peakAngle, ef);
|
|
216
|
+
amount = ef;
|
|
217
|
+
sc = lerp(f.startScale, f.peakScale, ef);
|
|
218
|
+
} else {
|
|
219
|
+
angle = lerp(f.peakAngle, f.endAngle, eu);
|
|
220
|
+
amount = f.peakAngle === f.startAngle ? 1 - eu : clamp((angle - f.startAngle) / (f.peakAngle - f.startAngle), -0.5, 1.5);
|
|
221
|
+
sc = lerp(f.peakScale, f.endScale, eu);
|
|
222
|
+
}
|
|
223
|
+
angle = clamp(angle, -110, 180);
|
|
224
|
+
const moving = (!unfolding && pf > 0 && pf < 1) ? Math.sin(Math.PI * pf) : (unfolding && pu > 0 && pu < 1) ? Math.sin(Math.PI * pu) : 0;
|
|
225
|
+
const phase = t < foldSpan.start ? 'before' : pf < 1 ? 'folding' : !unfolding ? 'folded' : pu < 1 ? 'unfolding' : 'after';
|
|
226
|
+
return {
|
|
227
|
+
id: f.id, angle, dihedral: sigma * angle, amount, activity: moving, phase,
|
|
228
|
+
scale: sc, perspective: lerp(1, f.perspective, clamp(amount, 0, 1.2)), tx: f.translationX * amount, ty: f.translationY * amount, rz: f.rotationZ * amount,
|
|
229
|
+
// The gripped edge lifts ahead of the fold (linear progress, so it leads the eased turn), and again as it unfolds.
|
|
230
|
+
lift: !unfolding ? (pf > 0 && pf < 1 ? liftAt(f, pf) : 0) : (pu > 0 && pu < 1 ? liftAt(f, 1 - pu) : 0),
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/* ─── layout ──────────────────────────────────────────────────────────────────────────────────── */
|
|
235
|
+
export type Layout = {
|
|
236
|
+
width: number; height: number; unit: number; pu: number;
|
|
237
|
+
shape: 'portrait' | 'landscape' | 'square';
|
|
238
|
+
paper: { width: number; height: number; pivotX: number; pivotY: number };
|
|
239
|
+
/** Crease y positions in the sheet (px), top then bottom. */
|
|
240
|
+
creases: [number, number];
|
|
241
|
+
panels: Record<PanelId, { y0: number; y1: number; height: number }>;
|
|
242
|
+
logo: { x: number; y: number; scale: number };
|
|
243
|
+
cta: { x: number; y: number; scale: number };
|
|
244
|
+
backgroundType: { scale: number; x: number; y: number };
|
|
245
|
+
handScale: number;
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
export function layout(cfg: PaperFoldConfig, width: number, height: number): Layout {
|
|
249
|
+
const { n, s } = reader(cfg);
|
|
250
|
+
const shape = LAYOUT_FOR[s('canvas.aspectRatio') as AspectRatio] ?? 'portrait';
|
|
251
|
+
const L = `layout.${shape}`;
|
|
252
|
+
const unit = Math.min(width, height) / 1080;
|
|
253
|
+
const PH = n(`${L}.paper.height`) * height;
|
|
254
|
+
const PW = PH * n('paper.aspect');
|
|
255
|
+
const c0 = n('creases.0.position') * PH, c1 = n('creases.1.position') * PH;
|
|
256
|
+
const safe = n('canvas.safeArea') * Math.min(width, height);
|
|
257
|
+
const inside = (v: number, size: number) => clamp(v, safe / size, 1 - safe / size);
|
|
258
|
+
return {
|
|
259
|
+
width, height, unit, pu: PW / 1000, shape,
|
|
260
|
+
paper: { width: PW, height: PH, pivotX: n(`${L}.paper.x`) * width, pivotY: n(`${L}.paper.y`) * height },
|
|
261
|
+
creases: [c0, c1],
|
|
262
|
+
panels: { top: { y0: 0, y1: c0, height: c0 }, middle: { y0: c0, y1: c1, height: c1 - c0 }, bottom: { y0: c1, y1: PH, height: PH - c1 } },
|
|
263
|
+
logo: { x: inside(n(`${L}.logo.x`), width) * width, y: inside(n(`${L}.logo.y`), height) * height, scale: n(`${L}.logo.scale`) },
|
|
264
|
+
cta: { x: inside(n(`${L}.cta.x`), width) * width, y: inside(n(`${L}.cta.y`), height) * height, scale: n(`${L}.cta.scale`) },
|
|
265
|
+
backgroundType: { scale: n(`${L}.backgroundType.scale`), x: n(`${L}.backgroundType.x`) * unit, y: n(`${L}.backgroundType.y`) * unit },
|
|
266
|
+
handScale: n(`${L}.handScale`),
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/* ─── the sheet: pose, chain, projection ──────────────────────────────────────────────────────── */
|
|
271
|
+
type SheetExtra = { tx: number; ty: number; rz: number; scale: number };
|
|
272
|
+
export type Anchor = PanelId;
|
|
273
|
+
|
|
274
|
+
/** The panel that stays put, from the two folds' directions (the validator refuses the one impossible pair). */
|
|
275
|
+
export function anchorOf(folds: { enabled: boolean; direction: 'down' | 'up' }[]): Anchor {
|
|
276
|
+
const [top, bottom] = folds;
|
|
277
|
+
if (top!.enabled && top!.direction === 'up') return 'top';
|
|
278
|
+
if (bottom!.enabled && bottom!.direction === 'down') return 'bottom';
|
|
279
|
+
return 'middle';
|
|
280
|
+
}
|
|
281
|
+
/** Which folds move a panel relative to the anchor (the hinges between them). */
|
|
282
|
+
export function moversOf(anchor: Anchor, panel: PanelId): number[] {
|
|
283
|
+
const idx = { top: 0, middle: 1, bottom: 2 };
|
|
284
|
+
const a = idx[anchor], p = idx[panel];
|
|
285
|
+
const out: number[] = [];
|
|
286
|
+
for (let k = Math.min(a, p); k < Math.max(a, p); k++) out.push(k);
|
|
287
|
+
return out;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/** How many hinges a curved crease is spread over (its bend is drawn as that many narrow strips). */
|
|
291
|
+
export const BEND_SEGMENTS = 6;
|
|
292
|
+
/** The widest bend band, as a fraction of the shorter panel beside the crease (at curvature 1). */
|
|
293
|
+
const MAX_BEND = 0.22;
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* One strip of the sheet: the flat part of a panel, or one narrow step of a crease's bend. Strips are
|
|
297
|
+
* cut from the ONE sheet at its hinge lines, so neighbouring strips share their edge exactly.
|
|
298
|
+
*/
|
|
299
|
+
export type Strip = { index: number; y0: number; y1: number; region: PanelId | 'crease0' | 'crease1'; T: Mat; /** Part of a free edge's lift curl. */ lift?: boolean };
|
|
300
|
+
export type Sheet = {
|
|
301
|
+
anchor: Anchor;
|
|
302
|
+
/** Sheet pose (sheet px → canvas px, in 3D). */
|
|
303
|
+
S: Mat;
|
|
304
|
+
/** The strips, top to bottom, each with its place in the sheet frame (the hinge chain). */
|
|
305
|
+
strips: Strip[];
|
|
306
|
+
/** Each panel's flat strip. */
|
|
307
|
+
T: Record<PanelId, Mat>;
|
|
308
|
+
/** The bend band of each crease (sheet px), [start, end]; equal when the crease is sharp. */
|
|
309
|
+
bands: [[number, number], [number, number]];
|
|
310
|
+
/** The camera's perspective. */
|
|
311
|
+
P: Mat;
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
/** Hinges near the sheet's free edges that curl the gripped edge (EDGE_LIFT_SEGMENTS per edge). */
|
|
315
|
+
export const EDGE_LIFT_SEGMENTS = 4;
|
|
316
|
+
type Lift = { top: number; bottom: number; topSize: number; bottomSize: number };
|
|
317
|
+
function buildSheet(cfg: PaperFoldConfig, lay: Layout, dihedrals: [number, number], curvatures: [number, number], perspectiveFactor: number, extra: SheetExtra, anchor: Anchor, lift: Lift = { top: 0, bottom: 0, topSize: 0, bottomSize: 0 }): Sheet {
|
|
318
|
+
const { n } = reader(cfg);
|
|
319
|
+
const { width: PW, height: PH, pivotX, pivotY } = lay.paper;
|
|
320
|
+
const u = lay.unit;
|
|
321
|
+
const sc = n('paper.scale') * extra.scale;
|
|
322
|
+
const S = chain(
|
|
323
|
+
translate(pivotX + (n('paper.translateX') + extra.tx) * u, pivotY + (n('paper.translateY') + extra.ty) * u),
|
|
324
|
+
rotZ((n('paper.rotationZ') + extra.rz) * RAD),
|
|
325
|
+
rotY(n('paper.rotationY') * RAD),
|
|
326
|
+
rotX(n('paper.rotationX') * RAD),
|
|
327
|
+
skew(n('paper.skewX') * RAD, n('paper.skewY') * RAD),
|
|
328
|
+
scale3(n('paper.scaleX') * sc, n('paper.scaleY') * sc),
|
|
329
|
+
translate(-n('paper.originX') * PW, -n('paper.originY') * PH),
|
|
330
|
+
);
|
|
331
|
+
// Hinges: a sharp crease is one hinge carrying the whole dihedral; a curved one spreads it evenly
|
|
332
|
+
// over BEND_SEGMENTS hinges across a band centred on the crease — a bend, not a card rotation.
|
|
333
|
+
const hinges: { y: number; a: number }[] = [];
|
|
334
|
+
const bands = ([0, 1] as const).map((k) => {
|
|
335
|
+
const yc = lay.creases[k];
|
|
336
|
+
const beside = Math.min(k === 0 ? lay.panels.top.height : lay.panels.middle.height, k === 0 ? lay.panels.middle.height : lay.panels.bottom.height);
|
|
337
|
+
const L = curvatures[k] * MAX_BEND * beside;
|
|
338
|
+
if (L < 0.5) { hinges.push({ y: yc, a: dihedrals[k] }); return [yc, yc] as [number, number]; }
|
|
339
|
+
for (let i = 0; i < BEND_SEGMENTS; i++) hinges.push({ y: yc - L / 2 + ((i + 0.5) * L) / BEND_SEGMENTS, a: dihedrals[k] / BEND_SEGMENTS });
|
|
340
|
+
return [yc - L / 2, yc + L / 2] as [number, number];
|
|
341
|
+
}) as Sheet['bands'];
|
|
342
|
+
// The lift curl: a few hinges across a band at a free edge, sharing its lift angle, so that edge rolls up.
|
|
343
|
+
const liftHinges: { y: number; a: number }[] = [];
|
|
344
|
+
if (lift.topSize > 0) for (let i = 0; i < EDGE_LIFT_SEGMENTS; i++) liftHinges.push({ y: ((i + 1) / (EDGE_LIFT_SEGMENTS + 1)) * lift.topSize * lay.panels.top.height, a: lift.top / EDGE_LIFT_SEGMENTS });
|
|
345
|
+
if (lift.bottomSize > 0) for (let i = 0; i < EDGE_LIFT_SEGMENTS; i++) liftHinges.push({ y: PH - ((EDGE_LIFT_SEGMENTS - i) / (EDGE_LIFT_SEGMENTS + 1)) * lift.bottomSize * lay.panels.bottom.height, a: lift.bottom / EDGE_LIFT_SEGMENTS });
|
|
346
|
+
hinges.push(...liftHinges);
|
|
347
|
+
hinges.sort((a, b) => a.y - b.y);
|
|
348
|
+
const liftTop = lift.topSize > 0 ? lift.topSize * lay.panels.top.height : -1, liftBottom = lift.bottomSize > 0 ? PH - lift.bottomSize * lay.panels.bottom.height : PH + 1;
|
|
349
|
+
const edges = [0, ...hinges.map((h) => h.y), PH];
|
|
350
|
+
const regionOf = (mid: number): Strip['region'] =>
|
|
351
|
+
mid < bands[0][0] ? 'top' : mid < bands[0][1] ? 'crease0' : mid < bands[1][0] ? 'middle' : mid < bands[1][1] ? 'crease1' : 'bottom';
|
|
352
|
+
const strips: Strip[] = edges.slice(0, -1).map((y0, i) => {
|
|
353
|
+
const y1 = edges[i + 1]!, mid = (y0 + y1) / 2;
|
|
354
|
+
return { index: i, y0, y1, region: regionOf(mid), T: I(), ...(mid < liftTop || mid > liftBottom ? { lift: true } : {}) };
|
|
355
|
+
});
|
|
356
|
+
// Walk the chain outward from the anchored panel's flat part: below a hinge the next strip turns by
|
|
357
|
+
// the hinge's angle about the hinge line; above it, by the inverse.
|
|
358
|
+
const flatOf = (id: PanelId) => strips.reduce((best, st, i) => (st.region === id && !st.lift && (best < 0 || st.y1 - st.y0 > strips[best]!.y1 - strips[best]!.y0) ? i : best), -1);
|
|
359
|
+
const a = flatOf(anchor);
|
|
360
|
+
for (let i = a + 1; i < strips.length; i++) strips[i]!.T = mul(strips[i - 1]!.T, hinge(hinges[i - 1]!.y, hinges[i - 1]!.a * RAD));
|
|
361
|
+
for (let i = a - 1; i >= 0; i--) strips[i]!.T = mul(strips[i + 1]!.T, hinge(hinges[i]!.y, -hinges[i]!.a * RAD));
|
|
362
|
+
const T = Object.fromEntries(PANELS.map((id) => [id, strips[flatOf(id)]!.T])) as Record<PanelId, Mat>;
|
|
363
|
+
const [vx, vy] = project(S, [n('camera.vanishX') * PW, n('camera.vanishY') * PH, 0]);
|
|
364
|
+
const P = perspectiveAt(vx, vy, (n('camera.perspective') * u) / perspectiveFactor);
|
|
365
|
+
return { anchor, S, strips, T, bands, P };
|
|
366
|
+
}
|
|
367
|
+
/** The strip that carries sheet height `y` (px). */
|
|
368
|
+
export function stripAt(sheet: Sheet, y: number): Strip {
|
|
369
|
+
return sheet.strips.find((st) => y >= st.y0 && y <= st.y1) ?? (y < 0 ? sheet.strips[0]! : sheet.strips.at(-1)!);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/* ─── lighting ────────────────────────────────────────────────────────────────────────────────── */
|
|
373
|
+
function lightVector(cfg: PaperFoldConfig): Vec3 {
|
|
374
|
+
const { n } = reader(cfg);
|
|
375
|
+
const az = n('foldLighting.lightAngle') * RAD, el = n('foldLighting.lightElevation') * RAD;
|
|
376
|
+
return norm3([Math.cos(el) * Math.cos(az), Math.cos(el) * Math.sin(az), Math.sin(el)]);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/* ─── state ───────────────────────────────────────────────────────────────────────────────────── */
|
|
380
|
+
export type EdgeFx = {
|
|
381
|
+
edge: 'top' | 'bottom';
|
|
382
|
+
crease: 0 | 1;
|
|
383
|
+
line: { opacity: number; width: number; blur: number; color: string };
|
|
384
|
+
highlight: { opacity: number; width: number; color: string };
|
|
385
|
+
valley: { opacity: number; length: number };
|
|
386
|
+
shadow: { opacity: number; length: number; blur: number };
|
|
387
|
+
};
|
|
388
|
+
/** One drawn strip of the sheet. */
|
|
389
|
+
export type StripState = {
|
|
390
|
+
index: number;
|
|
391
|
+
region: Strip['region'];
|
|
392
|
+
/** Sheet heights (px) the strip covers. */
|
|
393
|
+
y0: number; y1: number;
|
|
394
|
+
/** CSS matrix3d placing the strip's box (0‥paper width × 0‥height) on the canvas. */
|
|
395
|
+
matrix: string;
|
|
396
|
+
corners: [number, number][];
|
|
397
|
+
facing: 'front' | 'back';
|
|
398
|
+
depth: number;
|
|
399
|
+
rank: number;
|
|
400
|
+
z: number;
|
|
401
|
+
brightness: number;
|
|
402
|
+
sheen: number;
|
|
403
|
+
/** 0 = facing the viewer, 1 = edge-on: how much of the paper's cut edge (thickness) shows. */
|
|
404
|
+
edgeOn: number;
|
|
405
|
+
lift?: boolean;
|
|
406
|
+
};
|
|
407
|
+
export type TextFit = { slot: string; panel: PanelId; x: number; y: number; width: number; fontSize: number; scale: number; lines: number; area: { x: number; y: number; width: number; height: number } };
|
|
408
|
+
export type PanelState = {
|
|
409
|
+
id: PanelId;
|
|
410
|
+
y0: number; height: number; width: number;
|
|
411
|
+
/** CSS matrix3d placing the panel's box (0‥width × 0‥height) on the canvas. */
|
|
412
|
+
matrix: string;
|
|
413
|
+
/** Projected corners: top-left, top-right, bottom-right, bottom-left. */
|
|
414
|
+
corners: [number, number][];
|
|
415
|
+
facing: 'front' | 'back';
|
|
416
|
+
/** Depth of the panel's centre (px toward the viewer, before perspective). */
|
|
417
|
+
depth: number;
|
|
418
|
+
/** Paint order: 0 = furthest back. */
|
|
419
|
+
rank: number;
|
|
420
|
+
z: number;
|
|
421
|
+
brightness: number;
|
|
422
|
+
sheen: number;
|
|
423
|
+
edges: EdgeFx[];
|
|
424
|
+
};
|
|
425
|
+
export type HandState = {
|
|
426
|
+
id: HandId;
|
|
427
|
+
enabled: boolean;
|
|
428
|
+
panel: PanelId;
|
|
429
|
+
/** Where the hand's grip point is drawn (canvas px) and its pose. */
|
|
430
|
+
x: number; y: number; rotation: number; scale: number; skewX: number; skewY: number; opacity: number;
|
|
431
|
+
/** Local offset of the drawing from its grip point (hand units). */
|
|
432
|
+
offsetX: number; offsetY: number;
|
|
433
|
+
fingerAngle: number;
|
|
434
|
+
/** The grip point on the paper, exactly (canvas px): the debug anchor. */
|
|
435
|
+
gripX: number; gripY: number;
|
|
436
|
+
bodyZ: number; fingerZ: number;
|
|
437
|
+
/** Hand units → px: the drawing's reference paper width is 600 units. */
|
|
438
|
+
unitScale: number;
|
|
439
|
+
/** The pose the art is built with. */
|
|
440
|
+
pose: { wrist: number; fingerCurl: number; thumbBend: number; thumbRotation: number; thumbScale: number; thumbX: number; thumbY: number };
|
|
441
|
+
};
|
|
442
|
+
export type FrameState = {
|
|
443
|
+
cfg: PaperFoldConfig;
|
|
444
|
+
frame: number;
|
|
445
|
+
size: Layout;
|
|
446
|
+
timeline: Timeline;
|
|
447
|
+
phase: { id: PhaseId; label: string; progress: number };
|
|
448
|
+
folds: FoldState[];
|
|
449
|
+
anchor: Anchor;
|
|
450
|
+
panels: PanelState[];
|
|
451
|
+
/** The sheet as drawn: its strips (flat panel parts and crease bends), each placed by its own matrix. */
|
|
452
|
+
strips: StripState[];
|
|
453
|
+
/** Bend band of each crease in sheet px. */
|
|
454
|
+
bands: [[number, number], [number, number]];
|
|
455
|
+
/** Where each text element sits on its panel, fitted into the panel's content area. */
|
|
456
|
+
text: TextFit[];
|
|
457
|
+
/** The grip anchors: the point on the paper, and where the hand's grip point is drawn (canvas px). */
|
|
458
|
+
anchors: Record<HandId, { paper: [number, number]; hand: [number, number] }>;
|
|
459
|
+
hands: HandState[];
|
|
460
|
+
camera: { transform: string; backgroundTransform: string; zoom: number };
|
|
461
|
+
/** Projected outline of each panel, for the sheet's cast shadow (px). */
|
|
462
|
+
shadowQuads: [number, number][][];
|
|
463
|
+
sheetCentre: [number, number];
|
|
464
|
+
background: { typeRows: { y: number; x: number }[]; typeRepeat: number };
|
|
465
|
+
logo: { x: number; y: number; opacity: number; scale: number };
|
|
466
|
+
cta: { x: number; y: number; opacity: number; scale: number };
|
|
467
|
+
debug: { creases: { id: string; from: [number, number]; to: [number, number]; position: number; angle: number }[] };
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
/** Where the hand is pulled (x, y, rot, scale) and the grip it follows (bx, by), which it rides exactly. */
|
|
471
|
+
type HandTarget = { x: number; y: number; rot: number; scale: number; bx: number; by: number };
|
|
472
|
+
|
|
473
|
+
/** Everything the frame needs from the fold state at motion frame t (no hands). */
|
|
474
|
+
function sheetAt(cfg: PaperFoldConfig, lay: Layout, tl: Timeline, t: number) {
|
|
475
|
+
const { n, s, b, list } = reader(cfg);
|
|
476
|
+
const foldsCfg = list<FoldCfg>('folds');
|
|
477
|
+
const manual = s('motion.progressMode') === 'manual';
|
|
478
|
+
const folds = manual
|
|
479
|
+
? manualFolds(foldsCfg, n('motion.foldProgress'))
|
|
480
|
+
: foldsCfg.map((f, k) => foldState(f, tl.phases[k === 0 ? 'topFold' : 'bottomFold'], tl.phases[k === 0 ? 'topUnfold' : 'bottomUnfold'], t));
|
|
481
|
+
const anchor = anchorOf(foldsCfg);
|
|
482
|
+
// Idle sway and bob; the intro rise.
|
|
483
|
+
const rnd = seeded(n('canvas.seed'));
|
|
484
|
+
const ph1 = rnd() * TAU, ph2 = rnd() * TAU;
|
|
485
|
+
const sec = t / MOTION_FPS;
|
|
486
|
+
const idle = b('motion.idle.enabled');
|
|
487
|
+
const swayRz = idle ? n('motion.idle.swayAngle') * Math.sin(TAU * n('motion.idle.frequency') * sec + ph1) : 0;
|
|
488
|
+
const bob = idle ? n('motion.idle.bobAmplitude') * Math.sin(TAU * n('motion.idle.frequency') * 1.31 * sec + ph2) : 0;
|
|
489
|
+
const intro = tl.phases.intro;
|
|
490
|
+
const eIntro = ease(s('timeline.intro.easing'), (t - intro.start) / Math.max(1, intro.end - intro.start), intro.end - intro.start);
|
|
491
|
+
const rise = s('motion.intro.mode') === 'rise' ? 1 - eIntro : 0;
|
|
492
|
+
const hold = tl.phases.foldedHold;
|
|
493
|
+
const pHold = hold.end > hold.start ? clamp((t - hold.start) / (hold.end - hold.start)) : 0;
|
|
494
|
+
const squeeze = lerp(1, n('motion.holdSqueeze'), Math.sin(Math.PI * ease(s('timeline.foldedHold.easing'), pHold, hold.end - hold.start)));
|
|
495
|
+
const base: SheetExtra = { tx: 0, ty: bob + n('motion.intro.paperOffsetY') * rise, rz: swayRz + n('motion.intro.paperRotation') * rise, scale: 1 };
|
|
496
|
+
const withFolds: SheetExtra = {
|
|
497
|
+
tx: base.tx + folds.reduce((a, f) => a + f.tx, 0),
|
|
498
|
+
ty: base.ty + folds.reduce((a, f) => a + f.ty, 0),
|
|
499
|
+
rz: base.rz + folds.reduce((a, f) => a + f.rz, 0),
|
|
500
|
+
scale: folds.reduce((a, f) => a * f.scale, 1) * squeeze,
|
|
501
|
+
};
|
|
502
|
+
const persp = folds.reduce((a, f) => a * f.perspective, 1);
|
|
503
|
+
const curv = foldsCfg.map((f) => f.curvature) as [number, number];
|
|
504
|
+
// The free edge each fold swings (down: the sheet's top edge; up: its bottom edge) lifts ahead of it.
|
|
505
|
+
const lift: Lift = { top: 0, bottom: 0, topSize: 0, bottomSize: 0 };
|
|
506
|
+
foldsCfg.forEach((f, k) => {
|
|
507
|
+
if (!f.enabled || f.edgeLift <= 0) return;
|
|
508
|
+
const sign = f.side === 'inward' ? 1 : -1;
|
|
509
|
+
if (f.direction === 'down') { lift.top += sign * folds[k]!.lift; lift.topSize = Math.max(lift.topSize, f.edgeLiftSize); } else { lift.bottom += sign * folds[k]!.lift; lift.bottomSize = Math.max(lift.bottomSize, f.edgeLiftSize); }
|
|
510
|
+
});
|
|
511
|
+
const sheet = buildSheet(cfg, lay, [folds[0]!.dihedral, folds[1]!.dihedral], curv, persp, withFolds, anchor, lift);
|
|
512
|
+
// The same sheet with every crease at its start angle and no fold-driven motion: where the hands rest.
|
|
513
|
+
const restDihedrals = foldsCfg.map((f) => (f.side === 'inward' ? 1 : -1) * f.startAngle) as [number, number];
|
|
514
|
+
const rest = buildSheet(cfg, lay, restDihedrals, curv, 1, base, anchor, { ...lift, top: 0, bottom: 0 });
|
|
515
|
+
return { folds, anchor, sheet, rest, foldsCfg, manual };
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
function panelOf(cfg: PaperFoldConfig, gy: number): PanelId {
|
|
519
|
+
const c0 = getPath(cfg, 'creases.0.position') as number, c1 = getPath(cfg, 'creases.1.position') as number;
|
|
520
|
+
return gy < c0 ? 'top' : gy < c1 ? 'middle' : 'bottom';
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/** Where a paper point is on the picture, and the paper's local direction and scale there. */
|
|
524
|
+
function gripOn(sheet: Sheet, lay: Layout, _panel: PanelId, gx: number, gy: number) {
|
|
525
|
+
const q: Vec3 = [gx * lay.paper.width, gy * lay.paper.height, 0];
|
|
526
|
+
const M = chain(sheet.P, sheet.S, stripAt(sheet, q[1]).T);
|
|
527
|
+
const g = project(M, q);
|
|
528
|
+
const e = project(M, [q[0] + 10, q[1], 0]);
|
|
529
|
+
return { x: g[0], y: g[1], angle: Math.atan2(e[1] - g[1], e[0] - g[0]) / RAD, scale: Math.hypot(e[0] - g[0], e[1] - g[1]) / 10 };
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/** The pose a hand is pulled toward at motion frame t (before its settle spring). */
|
|
533
|
+
function handTarget(cfg: PaperFoldConfig, lay: Layout, tl: Timeline, id: HandId, t: number): HandTarget {
|
|
534
|
+
const { n, s } = reader(cfg);
|
|
535
|
+
const H = `hands.${id}`, HI = `handInteraction.${id}`;
|
|
536
|
+
const lead = n(`${HI}.leadFrames`);
|
|
537
|
+
const gx = n(`${H}.x`), gy = n(`${H}.y`);
|
|
538
|
+
const panel = panelOf(cfg, gy);
|
|
539
|
+
const at = sheetAt(cfg, lay, tl, t + lead);
|
|
540
|
+
const now = gripOn(at.sheet, lay, panel, gx, gy);
|
|
541
|
+
const rest = gripOn(at.rest, lay, panel, gx, gy);
|
|
542
|
+
const follow = n(`${HI}.followStrength`);
|
|
543
|
+
const movers = moversOf(at.anchor, panel);
|
|
544
|
+
const own = movers.map((k) => at.folds[k]!);
|
|
545
|
+
const amount = own.reduce((a, f) => Math.max(a, clamp(f.amount)), 0);
|
|
546
|
+
const tugActivity = own.reduce((a, f) => Math.max(a, f.activity), 0);
|
|
547
|
+
const anyActivity = at.folds.reduce((a, f) => Math.max(a, f.activity), 0);
|
|
548
|
+
const bx = rest.x + follow * (now.x - rest.x), by = rest.y + follow * (now.y - rest.y);
|
|
549
|
+
let x = bx, y = by;
|
|
550
|
+
// The tug: the hand pulls ahead along the way its grip point is travelling.
|
|
551
|
+
if (tugActivity > 0) {
|
|
552
|
+
const ahead = gripOn(sheetAt(cfg, lay, tl, t + lead + 2).sheet, lay, panel, gx, gy);
|
|
553
|
+
const dx = ahead.x - now.x, dy = ahead.y - now.y, len = Math.hypot(dx, dy);
|
|
554
|
+
if (len > 1e-3) { x += (dx / len) * n(`${HI}.gripOffset`) * lay.pu * tugActivity; y += (dy / len) * n(`${HI}.gripOffset`) * lay.pu * tugActivity; }
|
|
555
|
+
}
|
|
556
|
+
// Bracing: while any fold moves, the hand leans toward the sheet's centre.
|
|
557
|
+
if (anyActivity > 0) {
|
|
558
|
+
const c = project(chain(at.sheet.P, at.sheet.S), [lay.paper.width / 2, lay.paper.height / 2, 0]);
|
|
559
|
+
const dx = c[0] - rest.x, dy = c[1] - rest.y, len = Math.hypot(dx, dy) || 1;
|
|
560
|
+
x += (dx / len) * n(`${HI}.movementAmplitude`) * lay.pu * anyActivity;
|
|
561
|
+
y += (dy / len) * n(`${HI}.movementAmplitude`) * lay.pu * anyActivity;
|
|
562
|
+
}
|
|
563
|
+
// The approach from off the paper (none in manual mode: the hands already hold it).
|
|
564
|
+
if (s('motion.intro.mode') === 'hands' && s('motion.progressMode') !== 'manual') {
|
|
565
|
+
const intro = tl.phases.intro, delay = n(`${HI}.enterDelayFrames`);
|
|
566
|
+
const dur = Math.max(1, intro.end - intro.start - delay);
|
|
567
|
+
const e = ease(s('timeline.intro.easing'), (t - intro.start - delay) / dur, dur);
|
|
568
|
+
x += n(`${HI}.enterFromX`) * lay.width * (1 - e);
|
|
569
|
+
y += n(`${HI}.enterFromY`) * lay.height * (1 - e);
|
|
570
|
+
}
|
|
571
|
+
const rot = n(`${H}.rotation`) + follow * angleDelta(now.angle, rest.angle) + n(`${HI}.rotationAmplitude`) * amount;
|
|
572
|
+
const scale = n(`${H}.scale`) * (1 + follow * (now.scale / Math.max(1e-3, rest.scale) - 1));
|
|
573
|
+
return { x, y, rot, scale, bx, by };
|
|
574
|
+
}
|
|
575
|
+
const angleDelta = (a: number, b: number) => { let d = a - b; while (d > 180) d -= 360; while (d < -180) d += 360; return d; };
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* The hands' settle is a damped spring pulled toward the target, integrated from frame 0 in fixed
|
|
579
|
+
* one-frame steps — so any frame, sampled on its own and in any order, gets the same pose. The
|
|
580
|
+
* trajectory is cached per config object and size.
|
|
581
|
+
*/
|
|
582
|
+
const TRAJECTORIES = new WeakMap<object, Map<string, HandTarget[]>>();
|
|
583
|
+
function handPose(cfg: PaperFoldConfig, lay: Layout, tl: Timeline, id: HandId, t: number): HandTarget {
|
|
584
|
+
// FOLD PROGRESS poses the paper directly: the hands sit exactly on their grip, no settle to play out.
|
|
585
|
+
if (getPath(cfg, 'motion.progressMode') === 'manual') return handTarget(cfg, lay, tl, id, t);
|
|
586
|
+
const key = `${id}:${lay.width}x${lay.height}`;
|
|
587
|
+
let byKey = TRAJECTORIES.get(cfg);
|
|
588
|
+
if (!byKey) { byKey = new Map(); TRAJECTORIES.set(cfg, byKey); }
|
|
589
|
+
let traj = byKey.get(key);
|
|
590
|
+
if (!traj) { traj = []; byKey.set(key, traj); }
|
|
591
|
+
const HI = `handInteraction.${id}`;
|
|
592
|
+
const zeta = getPath(cfg, `${HI}.bounce`) as number;
|
|
593
|
+
// One-frame steps stay stable while ω ≤ 1 (a settle of at least ~4/ζ frames).
|
|
594
|
+
const omega = Math.min(1, 4 / (zeta * (getPath(cfg, `${HI}.settleDuration`) as number)));
|
|
595
|
+
const target = Math.max(0, Math.ceil(t));
|
|
596
|
+
// The spring carries only what the hand adds to its grip (the approach, the bracing, the wrist turn):
|
|
597
|
+
// the grip point itself is ridden exactly, so the fingers never trail the paper however fast it folds.
|
|
598
|
+
const offset = (g: HandTarget): HandTarget => ({ ...g, x: g.x - g.bx, y: g.y - g.by });
|
|
599
|
+
if (!traj.length) traj.push(offset(handTarget(cfg, lay, tl, id, 0)));
|
|
600
|
+
// Velocities are recomputed from the last two samples, so the cache holds only poses.
|
|
601
|
+
while (traj.length <= target) {
|
|
602
|
+
const k = traj.length;
|
|
603
|
+
const cur = traj[k - 1]!, prev = traj[k - 2] ?? cur;
|
|
604
|
+
const goal = offset(handTarget(cfg, lay, tl, id, k));
|
|
605
|
+
const step = (x: number, px: number, g: number) => {
|
|
606
|
+
let v = x - px;
|
|
607
|
+
v += -2 * zeta * omega * v - omega * omega * (x - g);
|
|
608
|
+
return x + v;
|
|
609
|
+
};
|
|
610
|
+
traj.push({ x: step(cur.x, prev.x, goal.x), y: step(cur.y, prev.y, goal.y), rot: step(cur.rot, prev.rot, goal.rot), scale: step(cur.scale, prev.scale, goal.scale), bx: 0, by: 0 });
|
|
611
|
+
}
|
|
612
|
+
const f = Math.max(0, Math.floor(t)), fr = t <= 0 ? 0 : t - f;
|
|
613
|
+
const a = traj[f]!, bb = traj[Math.min(f + 1, traj.length - 1)]!;
|
|
614
|
+
const now = handTarget(cfg, lay, tl, id, Math.max(0, t));
|
|
615
|
+
return { x: now.bx + lerp(a.x, bb.x, fr), y: now.by + lerp(a.y, bb.y, fr), rot: lerp(a.rot, bb.rot, fr), scale: lerp(a.scale, bb.scale, fr), bx: now.bx, by: now.by };
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
const TEXT_SLOTS: { slot: string; path: string; panel: PanelId }[] = [
|
|
619
|
+
{ slot: 'topLogo', path: 'content.top.logo', panel: 'top' }, { slot: 'topHeadline', path: 'content.top.headline', panel: 'top' },
|
|
620
|
+
{ slot: 'topSubtitle', path: 'content.top.subtitle', panel: 'top' }, { slot: 'middleHeadline', path: 'content.middle.headline', panel: 'middle' },
|
|
621
|
+
{ slot: 'middleBody', path: 'content.middle.body', panel: 'middle' }, { slot: 'bottomHeadline', path: 'content.bottom.headline', panel: 'bottom' },
|
|
622
|
+
{ slot: 'bottomBody', path: 'content.bottom.body', panel: 'bottom' }, { slot: 'bottomCta', path: 'content.bottom.cta', panel: 'bottom' },
|
|
623
|
+
];
|
|
624
|
+
/**
|
|
625
|
+
* How many lines `text` wraps to at `width` px: greedy word wrap on an estimated advance (an average
|
|
626
|
+
* glyph is ≈ 0.52 em at weight 400, a little wider when heavier, plus the tracking). Pure and
|
|
627
|
+
* deterministic; the renderer's own wrapping may differ by a word, and the content area clips anyway.
|
|
628
|
+
*/
|
|
629
|
+
export function estimateLines(text: string, fontSize: number, width: number, weight: number, tracking: number): number {
|
|
630
|
+
const em = fontSize * (0.5 + Math.max(0, weight - 300) * 0.00016 + tracking);
|
|
631
|
+
const maxChars = Math.max(1, Math.floor(width / Math.max(0.1, em)));
|
|
632
|
+
let lines = 0;
|
|
633
|
+
for (const para of text.split('\n')) {
|
|
634
|
+
let cur = 0;
|
|
635
|
+
lines++;
|
|
636
|
+
for (const word of para.split(/\s+/).filter(Boolean)) {
|
|
637
|
+
const need = (cur ? cur + 1 : 0) + word.length;
|
|
638
|
+
if (need > maxChars && cur) { lines++; cur = word.length; } else cur = need;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
return lines;
|
|
642
|
+
}
|
|
643
|
+
/** Every text element placed on its panel and fitted into the panel's content area. */
|
|
644
|
+
export function textFits(cfg: PaperFoldConfig, lay: Layout): TextFit[] {
|
|
645
|
+
const { n, s, b } = reader(cfg);
|
|
646
|
+
const PW = lay.paper.width;
|
|
647
|
+
const out: TextFit[] = [];
|
|
648
|
+
for (const { slot, path, panel } of TEXT_SLOTS) {
|
|
649
|
+
const text = s(path);
|
|
650
|
+
if (!text) continue;
|
|
651
|
+
const T = `typography.${slot}`, A = `panels.${panel}.contentArea`;
|
|
652
|
+
const h = lay.panels[panel].height, pad = n(`${A}.padding`) * lay.pu;
|
|
653
|
+
const area = { x: n(`${A}.x`) * PW + pad, y: n(`${A}.y`) * h + pad, width: Math.max(1, n(`${A}.width`) * PW - 2 * pad), height: Math.max(1, n(`${A}.height`) * h - 2 * pad) };
|
|
654
|
+
const x = n(`${T}.x`) * PW, y = n(`${T}.y`) * h, size = n(`${T}.fontSize`) * lay.pu;
|
|
655
|
+
const overflow = b(`panels.${panel}.overflow`);
|
|
656
|
+
const width = overflow ? n(`${T}.maxWidth`) * PW : Math.max(1, Math.min(n(`${T}.maxWidth`) * PW, area.x + area.width - Math.max(x, area.x)));
|
|
657
|
+
let scale = 1, lines = estimateLines(text, size, width, n(`${T}.fontWeight`), n(`${T}.letterSpacing`));
|
|
658
|
+
if (!overflow) {
|
|
659
|
+
const room = area.y + area.height - Math.max(y, area.y);
|
|
660
|
+
while (scale > 0.4 && lines * n(`${T}.lineHeight`) * size * scale > room) {
|
|
661
|
+
scale -= 0.04;
|
|
662
|
+
lines = estimateLines(text, size * scale, width, n(`${T}.fontWeight`), n(`${T}.letterSpacing`));
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
out.push({ slot, panel, x: overflow ? x : Math.max(x, area.x), y: overflow ? y : Math.max(y, area.y), width, fontSize: size * scale, scale: Math.round(scale * 100) / 100, lines, area });
|
|
666
|
+
}
|
|
667
|
+
return out;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/** Everything drawn at motion frame `frame` on a `width` × `height` canvas. */
|
|
671
|
+
export function frameState(cfg: PaperFoldConfig, frame: number, width: number, height: number): FrameState {
|
|
672
|
+
const { n, s, b, list } = reader(cfg);
|
|
673
|
+
const lay = layout(cfg, width, height);
|
|
674
|
+
const tl = timeline(cfg);
|
|
675
|
+
const t = clamp(frame, 0, Math.max(0, tl.length));
|
|
676
|
+
const { folds, anchor, sheet, foldsCfg } = sheetAt(cfg, lay, tl, t);
|
|
677
|
+
const L = lightVector(cfg);
|
|
678
|
+
const PW = lay.paper.width;
|
|
679
|
+
const creases = list<{ enabled: boolean; width: number; color: string; opacity: number; darkness: number; softness: number; highlight: number; highlightColor: string; position: number }>('creases');
|
|
680
|
+
|
|
681
|
+
/* strips: the one sheet, cut at its hinges */
|
|
682
|
+
const halfway = norm3([L[0], L[1], L[2] + 1]);
|
|
683
|
+
const rawStrips = sheet.strips.map((st) => {
|
|
684
|
+
const h = st.y1 - st.y0;
|
|
685
|
+
const world = mul(sheet.S, st.T);
|
|
686
|
+
const M = chain(sheet.P, world, translate(0, st.y0));
|
|
687
|
+
const corners = ([[0, 0], [PW, 0], [PW, h], [0, h]] as [number, number][]).map(([x, y]) => project(M, [x, y, 0]));
|
|
688
|
+
let area = 0;
|
|
689
|
+
for (let i = 0; i < 4; i++) { const [x1, y1] = corners[i]!, [x2, y2] = corners[(i + 1) % 4]!; area += x1 * y2 - x2 * y1; }
|
|
690
|
+
const facing: 'front' | 'back' = area >= 0 ? 'front' : 'back';
|
|
691
|
+
const centre = apply(world, [PW / 2, st.y0 + h / 2, 0]);
|
|
692
|
+
let normal = norm3(cross(linear(world, [1, 0, 0]), linear(world, [0, 1, 0])));
|
|
693
|
+
if (facing === 'back') normal = [-normal[0], -normal[1], -normal[2]];
|
|
694
|
+
const panel: PanelId = st.region === 'crease0' ? ((st.y0 + st.y1) / 2 < lay.creases[0] ? 'top' : 'middle') : st.region === 'crease1' ? ((st.y0 + st.y1) / 2 < lay.creases[1] ? 'middle' : 'bottom') : st.region;
|
|
695
|
+
const brightness = n('foldLighting.ambient') + n('foldLighting.diffuse') * Math.max(0, dot3(normal, L)) + n(`panels.${panel}.shade`) + (facing === 'back' ? n('foldLighting.backShade') : 0);
|
|
696
|
+
const sheen = n('foldLighting.highlightOpacity') * n(`panels.${panel}.highlightOpacity`) * Math.pow(Math.max(0, dot3(normal, halfway)), 24);
|
|
697
|
+
return { st, M, corners, facing, depth: centre[2], brightness, sheen, edgeOn: 1 - Math.abs(normal[2]) };
|
|
698
|
+
});
|
|
699
|
+
/* explicit depth order: back to front by the depth of each strip's centre (ties keep top → bottom) */
|
|
700
|
+
const order = [...rawStrips].sort((a, c) => a.depth - c.depth || a.st.index - c.st.index);
|
|
701
|
+
const STRIP_Z0 = 100, STRIP_STEP = 4;
|
|
702
|
+
const strips: StripState[] = rawStrips.map((r) => {
|
|
703
|
+
const rank = order.indexOf(r);
|
|
704
|
+
return {
|
|
705
|
+
index: r.st.index, region: r.st.region, y0: r.st.y0, y1: r.st.y1, matrix: cssMatrix(r.M), corners: r.corners, facing: r.facing,
|
|
706
|
+
depth: r.depth, rank, z: STRIP_Z0 + rank * STRIP_STEP, brightness: r.brightness, sheen: r.sheen, edgeOn: r.edgeOn, ...(r.st.lift ? { lift: true } : {}),
|
|
707
|
+
};
|
|
708
|
+
});
|
|
709
|
+
/** A sheet point on the picture, through the strip that carries it. */
|
|
710
|
+
const onPicture = (x: number, y: number) => project(chain(sheet.P, sheet.S, stripAt(sheet, y).T), [x, y, 0]);
|
|
711
|
+
|
|
712
|
+
/* crease effects on each panel's edges (drawn in sheet coordinates, on whichever strips carry them) */
|
|
713
|
+
const heightOf = (id: PanelId) => lay.panels[id].height;
|
|
714
|
+
const edgeFx = (id: PanelId, facing: 'front' | 'back'): EdgeFx[] => {
|
|
715
|
+
const out: EdgeFx[] = [];
|
|
716
|
+
const adj: [0 | 1, 'top' | 'bottom', PanelId][] = id === 'top' ? [[0, 'bottom', 'middle']] : id === 'middle' ? [[0, 'top', 'top'], [1, 'bottom', 'bottom']] : [[1, 'top', 'middle']];
|
|
717
|
+
for (const [k, edge, other] of adj) {
|
|
718
|
+
const c = creases[k]!, f = folds[k]!, fc = foldsCfg[k]!;
|
|
719
|
+
const closed = Math.abs(f.dihedral) / 180;
|
|
720
|
+
// Seen from the front, a positive dihedral (the fronts closing) is a valley; seen from the back, a ridge.
|
|
721
|
+
const concave = (facing === 'front') === (f.dihedral > 0) && Math.abs(f.dihedral) > 0.5;
|
|
722
|
+
const lineOpacity = c.enabled ? c.opacity * n('paperMaterial.creaseShadow') * clamp(n('paperMaterial.creaseTexture') + (1 - n('paperMaterial.creaseTexture')) * clamp(closed * fc.creaseIntensity)) : 0;
|
|
723
|
+
const moving = moversOf(anchor, id).includes(k);
|
|
724
|
+
const edgeLight = !concave && moving ? n('foldLighting.edgeHighlight') * Math.abs(Math.sin(f.dihedral * RAD)) : 0;
|
|
725
|
+
const shadowLen = Math.min(heightOf(id), heightOf(other) * (1 - Math.cos(f.dihedral * RAD)) / 2 + n('foldLighting.shadowOffset') * lay.pu);
|
|
726
|
+
out.push({
|
|
727
|
+
edge, crease: k,
|
|
728
|
+
line: { opacity: clamp(lineOpacity), width: c.width * lay.pu, blur: c.softness * lay.pu, color: c.color },
|
|
729
|
+
highlight: {
|
|
730
|
+
opacity: concave ? 0 : clamp(((c.enabled ? c.highlight * (0.35 + 0.65 * clamp(closed * fc.creaseIntensity)) : 0) + edgeLight) * n('paperMaterial.creaseHighlight')),
|
|
731
|
+
width: Math.max(c.width * lay.pu * 0.8, n('paper.thickness') * lay.pu * clamp(closed * 1.6)), color: c.highlightColor,
|
|
732
|
+
},
|
|
733
|
+
valley: { opacity: concave ? clamp(n('foldLighting.creaseDarkness') * c.darkness * 2 * clamp(closed * fc.creaseIntensity)) : 0, length: 70 * lay.pu * (0.4 + closed) },
|
|
734
|
+
shadow: {
|
|
735
|
+
opacity: concave ? n('foldLighting.shadowOpacity') * fc.shadowIntensity * n(`panels.${id}.shadowOpacity`) * clamp(closed * 1.4) ** 1.5 : 0,
|
|
736
|
+
length: Math.max(0, shadowLen), blur: n('foldLighting.shadowBlur') * lay.pu,
|
|
737
|
+
},
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
return out;
|
|
741
|
+
};
|
|
742
|
+
|
|
743
|
+
/* panels: the three regions of the sheet, summarized (their flat strip gives facing, light and depth) */
|
|
744
|
+
const panels: PanelState[] = PANELS.map((id) => {
|
|
745
|
+
const { y0, y1, height: h } = lay.panels[id];
|
|
746
|
+
const flat = strips.filter((st) => st.region === id && !st.lift).reduce((a, b) => (b.y1 - b.y0 > a.y1 - a.y0 ? b : a));
|
|
747
|
+
const corners: [number, number][] = [onPicture(0, y0), onPicture(PW, y0), onPicture(PW, y1), onPicture(0, y1)];
|
|
748
|
+
return {
|
|
749
|
+
id, y0, height: h, width: PW, matrix: flat.matrix, corners, facing: flat.facing, depth: flat.depth,
|
|
750
|
+
rank: flat.rank, z: flat.z, brightness: flat.brightness, sheen: flat.sheen, edges: edgeFx(id, flat.facing),
|
|
751
|
+
};
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
/* text: each element in its panel's content area, shrunk to fit unless the panel allows overflow */
|
|
755
|
+
const text = textFits(cfg, lay);
|
|
756
|
+
|
|
757
|
+
/* hands */
|
|
758
|
+
const hands: HandState[] = (['top', 'bottom'] as HandId[]).map((id, i) => {
|
|
759
|
+
const H = `hands.${id}`, HI = `handInteraction.${id}`;
|
|
760
|
+
const gx = n(`${H}.x`), gy = n(`${H}.y`);
|
|
761
|
+
const panelId = panelOf(cfg, gy);
|
|
762
|
+
const panel = panels.find((p) => p.id === panelId)!;
|
|
763
|
+
const pose = handPose(cfg, lay, tl, id, t);
|
|
764
|
+
const exact = gripOn(sheet, lay, panelId, gx, gy);
|
|
765
|
+
const intro = tl.phases.intro, delay = n(`${HI}.enterDelayFrames`);
|
|
766
|
+
const manualMode = s('motion.progressMode') === 'manual';
|
|
767
|
+
const approach = s('motion.intro.mode') === 'hands' && !manualMode ? clamp((t - intro.start - delay) / Math.max(1, intro.end - intro.start - delay)) : 1;
|
|
768
|
+
const closeOn = ease(s('easing.fingerGrip'), clamp((approach - 0.55) / 0.45), 30);
|
|
769
|
+
// Contact → grip → pull → fold → stabilize; while the paper holds folded the hand eases its grip,
|
|
770
|
+
// then takes it again before the paper unfolds.
|
|
771
|
+
const hold = tl.phases.foldedHold, rf = n(`${HI}.releaseFrames`);
|
|
772
|
+
const release = manualMode || hold.end <= hold.start ? 0 : Math.min(clamp((t - hold.start) / rf), clamp((hold.end - t) / rf));
|
|
773
|
+
const grip = closeOn * (1 - n(`${HI}.releaseAmount`) * ease('easeInOut', release, rf));
|
|
774
|
+
// Front-facing: the body is behind the whole sheet and the finger lies on the panel's front.
|
|
775
|
+
// Turned over: what was behind the panel is now in front of it, so the two swap.
|
|
776
|
+
const front = panel.facing === 'front';
|
|
777
|
+
return {
|
|
778
|
+
id, enabled: b(`${H}.enabled`), panel: panelId,
|
|
779
|
+
x: pose.x, y: pose.y, rotation: pose.rot, scale: pose.scale * lay.handScale, skewX: n(`${H}.skewX`), skewY: n(`${H}.skewY`), opacity: n(`${H}.opacity`),
|
|
780
|
+
offsetX: n(`${H}.offsetX`) * 0.6, offsetY: n(`${H}.offsetY`) * 0.6,
|
|
781
|
+
// Open by gripAngle before the grip closes; once holding, open by whatever pose.grip leaves open.
|
|
782
|
+
fingerAngle: n(`${HI}.gripAngle`) * (1 - grip * n(`${H}.pose.grip`)),
|
|
783
|
+
gripX: exact.x, gripY: exact.y,
|
|
784
|
+
bodyZ: front ? 20 + i : panel.z + 2,
|
|
785
|
+
fingerZ: front ? panel.z + 2 : panel.z - 2,
|
|
786
|
+
unitScale: PW / 600,
|
|
787
|
+
pose: {
|
|
788
|
+
wrist: n(`${H}.pose.wrist`),
|
|
789
|
+
fingerCurl: n(`${H}.pose.fingerCurl`), thumbBend: n(`${H}.pose.thumbBend`), thumbRotation: n(`${H}.thumb.rotation`),
|
|
790
|
+
thumbScale: n(`${H}.thumb.scale`), thumbX: n(`${H}.thumb.x`), thumbY: n(`${H}.thumb.y`),
|
|
791
|
+
},
|
|
792
|
+
};
|
|
793
|
+
});
|
|
794
|
+
const anchors = Object.fromEntries(hands.map((h) => [h.id, { paper: [h.gripX, h.gripY], hand: [h.x, h.y] }])) as FrameState['anchors'];
|
|
795
|
+
|
|
796
|
+
/* camera */
|
|
797
|
+
const enabledFolds = folds.filter((f, k) => foldsCfg[k]!.enabled);
|
|
798
|
+
const foldAmount = enabledFolds.length ? enabledFolds.reduce((a, f) => a + clamp(f.amount), 0) / enabledFolds.length : 0;
|
|
799
|
+
const fin = tl.phases.finalHold;
|
|
800
|
+
let zoom = lerp(n('camera.startZoom'), n('camera.foldZoom'), ease(s('easing.camera'), foldAmount, 60));
|
|
801
|
+
if (t >= fin.start && fin.end > fin.start) zoom = lerp(zoom, n('camera.endZoom'), ease(s('timeline.finalHold.easing'), (t - fin.start) / (fin.end - fin.start), fin.end - fin.start));
|
|
802
|
+
const u = lay.unit, W = width, Hh = height;
|
|
803
|
+
const camT = (z: number, k: number) => `translate(${W / 2}px, ${Hh / 2}px) rotate(${n('camera.rotation') * k}deg) scale(${z}) translate(${-W / 2 - n('camera.x') * u * k}px, ${-Hh / 2 - n('camera.y') * u * k}px)`;
|
|
804
|
+
const par = n('camera.parallax');
|
|
805
|
+
|
|
806
|
+
/* background type rows */
|
|
807
|
+
const bt = 'background.backgroundTypography';
|
|
808
|
+
const size = n(`${bt}.fontSize`) * u * lay.backgroundType.scale;
|
|
809
|
+
const pitch = size * n(`${bt}.rowGap`);
|
|
810
|
+
const drift = n(`${bt}.drift`) * u * (t / MOTION_FPS);
|
|
811
|
+
const typeRows = Array.from({ length: n(`${bt}.rows`) }, (_, i) => ({
|
|
812
|
+
y: n(`${bt}.y`) * u + lay.backgroundType.y + i * pitch,
|
|
813
|
+
x: n(`${bt}.x`) * u + lay.backgroundType.x + (b(`${bt}.alternate`) && i % 2 ? -drift : drift),
|
|
814
|
+
}));
|
|
815
|
+
|
|
816
|
+
// Fill: an estimate of the word's width (caps ≈ 0.66 em each, plus tracking) decides how many repeats span the canvas.
|
|
817
|
+
const wordWidth = Math.max(1, s(`${bt}.text`).length * (0.66 + n(`${bt}.tracking`)) * size + 0.3 * size);
|
|
818
|
+
const reach = width + Math.abs(n(`${bt}.x`) * u + lay.backgroundType.x) + Math.abs(drift) + size;
|
|
819
|
+
const typeRepeat = Math.max(n(`${bt}.repeat`), b(`${bt}.fill`) ? Math.min(12, Math.ceil(reach / wordWidth)) : 1);
|
|
820
|
+
|
|
821
|
+
/* logo and CTA */
|
|
822
|
+
const introSpan = tl.phases.intro;
|
|
823
|
+
const eLogo = ease(s('easing.logoEnter'), (t - introSpan.start) / Math.max(1, introSpan.end - introSpan.start), introSpan.end - introSpan.start);
|
|
824
|
+
const logoMode = s('logo.animation');
|
|
825
|
+
const logo = { x: lay.logo.x, y: lay.logo.y - (logoMode === 'drop' ? (1 - eLogo) * 60 * u : 0), opacity: logoMode === 'none' ? 1 : eLogo, scale: lay.logo.scale };
|
|
826
|
+
const ctaMode = s('cta.animation');
|
|
827
|
+
const pCta = clamp((t - n('cta.enterDelayFrames')) / n('cta.enterDurationFrames'));
|
|
828
|
+
const pop = ctaMode === 'pop' || ctaMode === 'pop-pulse';
|
|
829
|
+
const pulse = ctaMode === 'pulse' || ctaMode === 'pop-pulse';
|
|
830
|
+
const pulseT = Math.max(0, t - fin.start) / MOTION_FPS;
|
|
831
|
+
const pulseK = pulse && t >= fin.start ? n('cta.pulseAmount') * (0.5 - 0.5 * Math.cos(TAU * n('cta.pulseFrequency') * pulseT)) : 0;
|
|
832
|
+
const cta = { x: lay.cta.x, y: lay.cta.y, opacity: pop ? clamp(pCta * 3) : 1, scale: lay.cta.scale * (pop ? Math.max(0, ease(s('easing.ctaEnter'), pCta, n('cta.enterDurationFrames'))) : 1) * (1 + pulseK) };
|
|
833
|
+
|
|
834
|
+
/* debug: the creases on the picture */
|
|
835
|
+
const creaseLine = (k: 0 | 1) => {
|
|
836
|
+
const y = lay.creases[k];
|
|
837
|
+
return { id: k === 0 ? 'top' : 'bottom', from: onPicture(0, y), to: onPicture(PW, y), position: creases[k]!.position, angle: folds[k]!.angle };
|
|
838
|
+
};
|
|
839
|
+
|
|
840
|
+
return {
|
|
841
|
+
cfg, frame: t, size: lay, timeline: tl, phase: phaseAt(tl, t), folds, anchor, panels, strips, bands: sheet.bands, text, anchors, hands,
|
|
842
|
+
camera: { transform: camT(zoom, 1), backgroundTransform: camT(1 + (zoom - 1) * par, par), zoom },
|
|
843
|
+
shadowQuads: strips.map((p) => p.corners),
|
|
844
|
+
sheetCentre: project(chain(sheet.P, sheet.S), [PW / 2, lay.paper.height / 2, 0]),
|
|
845
|
+
background: { typeRows, typeRepeat },
|
|
846
|
+
logo, cta,
|
|
847
|
+
debug: { creases: [creaseLine(0), creaseLine(1)] },
|
|
848
|
+
};
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
/** The phase ids in order (re-exported for tests and tools). */
|
|
852
|
+
export { PHASES };
|