dsh-drawai 0.4.2 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -5
- package/lib/client.js +142 -16
- package/lib/index.js +7945 -7719
- package/lib/motion/asset-pack.js +394 -394
- package/lib/motion/assets.js +291 -291
- package/lib/motion/demo-assets-lock.js +10 -10
- package/lib/motion/mgstyles/briefs/23-ink-wash.md +147 -0
- package/lib/motion/mgstyles/catalog.d/23-ink-wash.json +28 -0
- package/lib/motion/mgstyles/catalog.json +127 -14
- package/lib/motion/mgstyles/upstream/demos/23-ink-wash/brush.js +149 -0
- package/lib/motion/mgstyles/upstream/demos/23-ink-wash/film.js +202 -0
- package/lib/motion/mgstyles/upstream/manifest.json +28 -3
- package/lib/motion/mgstyles/upstream/prompts/23-ink-wash.md +59 -0
- package/lib/motion/mgstyles/vendor/README.md +28 -28
- package/lib/motion/mgstyles/vendor/modules/d3/LICENSE +13 -13
- package/lib/motion/mgstyles/vendor/modules/d3/dist/d3.min.js +2 -2
- package/lib/motion/mgstyles/vendor/modules/opentype.js/LICENSE +20 -20
- package/lib/motion/mgstyles/vendor/modules/opentype.js/dist/opentype.mjs +14460 -14460
- package/lib/motion/mgstyles/vendor/modules/simplex-noise/LICENSE +21 -21
- package/lib/motion/mgstyles/vendor/modules/simplex-noise/dist/esm/simplex-noise.js +465 -465
- package/lib/motion/mgstyles/vendor/modules/topojson-client/LICENSE +13 -13
- package/lib/motion/mgstyles/vendor/modules/topojson-client/dist/topojson-client.min.js +2 -2
- package/lib/motion/project.js +5 -1
- package/lib/motion/qa.js +116 -6
- package/lib/motion/render.js +179 -179
- package/lib/motion/scene-kit.js +1 -1
- package/lib/motion/shotcraft/upstream/SKILL.md +286 -286
- package/lib/motion/shotcraft/upstream/assets/lib/Caption.tsx +54 -54
- package/lib/motion/shotcraft/upstream/assets/lib/ClipCard.tsx +200 -200
- package/lib/motion/shotcraft/upstream/assets/lib/DigitRoll.tsx +45 -45
- package/lib/motion/shotcraft/upstream/assets/lib/FlashCut.tsx +20 -20
- package/lib/motion/shotcraft/upstream/assets/lib/FlatPanel.tsx +65 -65
- package/lib/motion/shotcraft/upstream/assets/lib/PageCam.tsx +151 -151
- package/lib/motion/shotcraft/upstream/assets/lib/VerticalTicker.tsx +129 -129
- package/lib/motion/shotcraft/upstream/assets/lib/helpers/camera.tsx +75 -75
- package/lib/motion/shotcraft/upstream/assets/lib/helpers/motion.ts +40 -40
- package/lib/motion/shotcraft/upstream/assets/lib/helpers/rand.ts +11 -11
- package/lib/motion/shotcraft/upstream/assets/lib/helpers/shake.ts +10 -10
- package/lib/motion/shotcraft/upstream/assets/scripts/build-readme-cover.mjs +49 -49
- package/lib/motion/shotcraft/upstream/assets/scripts/capture-template.mjs +210 -210
- package/lib/motion/shotcraft/upstream/assets/scripts/sfx-source.py +423 -423
- package/lib/motion/shotcraft/upstream/assets/scripts/smoke-render-demos.py +170 -170
- package/lib/motion/shotcraft/upstream/assets/scripts/test_sfx_source.py +157 -157
- package/lib/motion/shotcraft/upstream/demos/README.md +120 -120
- package/lib/motion/shotcraft/upstream/demos/_fixtures/Brand.tsx +112 -112
- package/lib/motion/shotcraft/upstream/demos/_fixtures/Fixtures.tsx +647 -647
- package/lib/motion/shotcraft/upstream/demos/_fixtures/Look.tsx +316 -316
- package/lib/motion/shotcraft/upstream/demos/_fixtures/Motion.tsx +82 -82
- package/lib/motion/shotcraft/upstream/demos/_fixtures/PageCam2D.tsx +115 -115
- package/lib/motion/shotcraft/upstream/demos/_fixtures/Polish.tsx +243 -243
- package/lib/motion/shotcraft/upstream/demos/_textures/live-layout.json +388 -388
- package/lib/motion/shotcraft/upstream/demos/camera/basic-3d-scene/Basic3DScene.tsx +250 -250
- package/lib/motion/shotcraft/upstream/demos/camera/crash-zoom-punch/CrashImpactReal.tsx +305 -305
- package/lib/motion/shotcraft/upstream/demos/camera/crash-zoom-punch/CrashZoomReal.tsx +246 -246
- package/lib/motion/shotcraft/upstream/demos/camera/cursor-flyover/CursorFlyover.tsx +390 -390
- package/lib/motion/shotcraft/upstream/demos/camera/depth-layer-moves/MultiplaneReal.tsx +138 -138
- package/lib/motion/shotcraft/upstream/demos/camera/graze-face-tour/GrazeFaceTour.tsx +542 -542
- package/lib/motion/shotcraft/upstream/demos/camera/overhead-camera-moves/OverheadTabletopDrop.tsx +315 -315
- package/lib/motion/shotcraft/upstream/demos/camera/overhead-camera-moves/TiltReveal.tsx +299 -299
- package/lib/motion/shotcraft/upstream/demos/camera/space-camera-moves/DroneDiveLanding.tsx +173 -173
- package/lib/motion/shotcraft/upstream/demos/camera/space-camera-moves/ExplodedView.tsx +348 -348
- package/lib/motion/shotcraft/upstream/demos/camera/steep-tilt-glide/SteepTiltGlide.tsx +366 -366
- package/lib/motion/shotcraft/upstream/demos/camera/tension-camera-moves/BulletTimeFreezeOrbit.tsx +279 -279
- package/lib/motion/shotcraft/upstream/demos/camera/tension-camera-moves/PullBackIsolation.tsx +184 -184
- package/lib/motion/shotcraft/upstream/demos/camera/terminal-3d/Terminal3D.tsx +390 -390
- package/lib/motion/shotcraft/upstream/demos/data/before-after-slider-scrub/BeforeAfterSliderScrub.tsx +155 -155
- package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/AxisRescaleShockV2.tsx +303 -303
- package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/OscilloscopeStreamV2.tsx +290 -290
- package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/UnitDotSwarmRegroupV2.tsx +278 -278
- package/lib/motion/shotcraft/upstream/demos/data/gauge-readout-moves/NeedleSweepSelftest.tsx +307 -307
- package/lib/motion/shotcraft/upstream/demos/data/gauge-readout-moves/TapeScrollFixedPointer.tsx +215 -215
- package/lib/motion/shotcraft/upstream/demos/data/scroll-brake-moves/BrakeReticleLock.tsx +299 -299
- package/lib/motion/shotcraft/upstream/demos/data/scroll-brake-moves/ChangelogScrollBrake.tsx +232 -232
- package/lib/motion/shotcraft/upstream/demos/data/timeline-travel/TimelineTravel.tsx +290 -290
- package/lib/motion/shotcraft/upstream/demos/effects/assemble-then-type-flyin/AssembleThenTypeFlyin.tsx +273 -273
- package/lib/motion/shotcraft/upstream/demos/effects/aurora-bloom-bg-flip/AuroraBloomBgFlip.tsx +167 -167
- package/lib/motion/shotcraft/upstream/demos/effects/brand-frame-snap/BrandFrameSnap.tsx +536 -536
- package/lib/motion/shotcraft/upstream/demos/effects/fui-hud-moves/ReticleLockOn.tsx +164 -164
- package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/FlylineArc.tsx +175 -175
- package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/GlowOrbAmbient.tsx +197 -197
- package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/OrbFlylineRelay.tsx +241 -241
- package/lib/motion/shotcraft/upstream/demos/effects/icon-performance-moves/AttentionBounce.tsx +279 -279
- package/lib/motion/shotcraft/upstream/demos/effects/impact-feedback/AnimeImpact.tsx +230 -230
- package/lib/motion/shotcraft/upstream/demos/effects/impact-feedback/HitCounter.tsx +345 -345
- package/lib/motion/shotcraft/upstream/demos/effects/light-play-moves/SheenSweepRetry.tsx +275 -275
- package/lib/motion/shotcraft/upstream/demos/effects/light-play-moves/SpotlightSweepReveal.tsx +229 -229
- package/lib/motion/shotcraft/upstream/demos/effects/radial-ripple-phone-chips/RadialRipplePhoneChips.tsx +312 -312
- package/lib/motion/shotcraft/upstream/demos/effects/riso-print-hits/RisoMisregistrationHit.tsx +222 -222
- package/lib/motion/shotcraft/upstream/demos/effects/scan-bracket-sweep/ScanBracketSweep.tsx +295 -295
- package/lib/motion/shotcraft/upstream/demos/effects/scanline-annotate-focus/ScanlineAnnotateFocus.tsx +329 -329
- package/lib/motion/shotcraft/upstream/demos/effects/scanline-assemble-flyin/ScanlineAssembleFlyin.tsx +315 -315
- package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/ImpactBurstKit.tsx +264 -264
- package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/KanadaPerspectiveSnap.tsx +260 -260
- package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/ScoreSlam.tsx +263 -263
- package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/CornerSpotlightReveal.tsx +123 -123
- package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/GlowWakeSleepPanel.tsx +187 -187
- package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/SlideSpotlightPan.tsx +175 -175
- package/lib/motion/shotcraft/upstream/demos/interaction/autolayout-gap-dial/AutolayoutGapDial.tsx +305 -305
- package/lib/motion/shotcraft/upstream/demos/interaction/canvas-materialize-moves/DiagramCascadeBuild.tsx +350 -350
- package/lib/motion/shotcraft/upstream/demos/interaction/canvas-materialize-moves/PanelToCanvasMaterialize.tsx +352 -352
- package/lib/motion/shotcraft/upstream/demos/interaction/chip-grid-single-select-blackout/ChipGridSingleSelectBlackout.tsx +218 -218
- package/lib/motion/shotcraft/upstream/demos/interaction/collab-cursor-moves/CursorCastEnsemble.tsx +297 -297
- package/lib/motion/shotcraft/upstream/demos/interaction/glass-pill-dictation-typing/GlassPillDictationTyping.tsx +157 -157
- package/lib/motion/shotcraft/upstream/demos/interaction/hashtag-to-pill-materialize/HashtagToPillMaterialize.tsx +218 -218
- package/lib/motion/shotcraft/upstream/demos/interaction/picker-carousel-feature-cycle/PickerCarouselFeatureCycle.tsx +202 -202
- package/lib/motion/shotcraft/upstream/demos/interaction/segmented-thumb-hero/SegmentedThumbHero.tsx +265 -265
- package/lib/motion/shotcraft/upstream/demos/interaction/theme-switch-moves/PaletteThemeRipple.tsx +457 -457
- package/lib/motion/shotcraft/upstream/demos/interaction/theme-switch-moves/ThemeSweepToggle.tsx +446 -446
- package/lib/motion/shotcraft/upstream/demos/interaction/type-and-filter/TypeAndFilter.tsx +249 -249
- package/lib/motion/shotcraft/upstream/demos/interaction/voice-waveform-live/VoiceWaveformLive.tsx +278 -278
- package/lib/motion/shotcraft/upstream/demos/opening/crane-rise-reveal/CraneRiseReveal.tsx +332 -332
- package/lib/motion/shotcraft/upstream/demos/opening/dataviz-landscape-open/DatavizLandscapeOpen.tsx +358 -358
- package/lib/motion/shotcraft/upstream/demos/opening/fracture/Fracture.tsx +201 -201
- package/lib/motion/shotcraft/upstream/demos/opening/icon-field-colorize/IconFieldColorize.tsx +200 -200
- package/lib/motion/shotcraft/upstream/demos/opening/letterspace-materialize/LetterspaceMaterialize.tsx +208 -208
- package/lib/motion/shotcraft/upstream/demos/opening/magician-card-flourish/MagicianCardFlourish.tsx +341 -341
- package/lib/motion/shotcraft/upstream/demos/opening/orbit-ring-title-open/OrbitRingTitleOpen.tsx +389 -389
- package/lib/motion/shotcraft/upstream/demos/opening/spotlight-hero-card/SpotlightHeroCard.tsx +293 -293
- package/lib/motion/shotcraft/upstream/demos/opening/stroke-segment-build/StrokeSegmentBuild.tsx +183 -183
- package/lib/motion/shotcraft/upstream/demos/opening/text-as-mask/TextAsMask.tsx +245 -245
- package/lib/motion/shotcraft/upstream/demos/outro/grain-dissolve/GrainDissolve.tsx +222 -222
- package/lib/motion/shotcraft/upstream/demos/outro/logo-shrink-wordmark-lockup/LogoShrinkWordmarkLockup.tsx +223 -223
- package/lib/motion/shotcraft/upstream/demos/outro/neon-triple-marquee/NeonTripleMarquee.tsx +217 -217
- package/lib/motion/shotcraft/upstream/demos/outro/outro-group-photo-launch/OutroGroupPhotoLaunch.tsx +343 -343
- package/lib/motion/shotcraft/upstream/demos/outro/ui-strip-away-outro/UiStripAwayOutro.tsx +357 -357
- package/lib/motion/shotcraft/upstream/demos/outro/ui-to-brand-morph/IconFlipBloomLogo.tsx +187 -187
- package/lib/motion/shotcraft/upstream/demos/outro/ui-to-brand-morph/InputMorphsIntoLogo.tsx +333 -333
- package/lib/motion/shotcraft/upstream/demos/rhythm/beat-cut-moves/PaparazziFlash.tsx +274 -274
- package/lib/motion/shotcraft/upstream/demos/rhythm/beat-step-list-theme-cycle/BeatStepListThemeCycle.tsx +270 -270
- package/lib/motion/shotcraft/upstream/demos/rhythm/panel-grid-moves/ComicPanelSplit.tsx +430 -430
- package/lib/motion/shotcraft/upstream/demos/rhythm/quad-split-parallel-scenes/QuadSplitParallelScenes.tsx +252 -252
- package/lib/motion/shotcraft/upstream/demos/rhythm/rhythm-interrupt-moves/JumpCutPunchIn.tsx +106 -106
- package/lib/motion/shotcraft/upstream/demos/rhythm/sakuga-timing-shift/SakugaTimingShift.tsx +288 -288
- package/lib/motion/shotcraft/upstream/demos/rhythm/speed-ramp-freeze/FreezeAnnotateReal.tsx +362 -362
- package/lib/motion/shotcraft/upstream/demos/rhythm/trailer-grammar-moves/TrailerBumper.tsx +168 -168
- package/lib/motion/shotcraft/upstream/demos/transition/bottom-push-stack-wipe/BottomPushStackWipe.tsx +310 -310
- package/lib/motion/shotcraft/upstream/demos/transition/card-flip-reveal/CardFlipReveal.tsx +261 -261
- package/lib/motion/shotcraft/upstream/demos/transition/card-flock-tumble/CardFlockTumble.tsx +459 -459
- package/lib/motion/shotcraft/upstream/demos/transition/circle-match-iris/CircleMatchIris.tsx +294 -294
- package/lib/motion/shotcraft/upstream/demos/transition/gradient-transition/GradientTransition.tsx +161 -161
- package/lib/motion/shotcraft/upstream/demos/transition/line-carry-transition/LineCarryTransition.tsx +248 -248
- package/lib/motion/shotcraft/upstream/demos/transition/mosaic-reframe/MosaicReframe.tsx +359 -359
- package/lib/motion/shotcraft/upstream/demos/transition/page-turn-transitions/BarnDoorSplit.tsx +227 -227
- package/lib/motion/shotcraft/upstream/demos/transition/print-texture-transitions/InkBleedReveal.tsx +162 -162
- package/lib/motion/shotcraft/upstream/demos/transition/shot-transitions/PortalWipeV2.tsx +248 -248
- package/lib/motion/shotcraft/upstream/demos/transition/shot-transitions/WhipBrakeReal.tsx +186 -186
- package/lib/motion/shotcraft/upstream/demos/transition/tear-streak-transitions/GlitchDisplace.tsx +355 -355
- package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/InvisibleCut.tsx +272 -272
- package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/LightLeakBurn.tsx +262 -262
- package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/VersusSlam.tsx +217 -217
- package/lib/motion/shotcraft/upstream/demos/transition/transition-travel/LetterformZoom.tsx +285 -285
- package/lib/motion/shotcraft/upstream/demos/transition/white-flash-logo-simplify-cut/WhiteFlashLogoSimplifyCut.tsx +205 -205
- package/lib/motion/shotcraft/upstream/demos/transition/wipe-transitions/BlindsSlice.tsx +178 -178
- package/lib/motion/shotcraft/upstream/demos/typography/blur-slide/BlurSlide.tsx +147 -147
- package/lib/motion/shotcraft/upstream/demos/typography/brace-expand/BraceExpand.tsx +143 -143
- package/lib/motion/shotcraft/upstream/demos/typography/brand-ink-open/BrandInkOpen.tsx +134 -134
- package/lib/motion/shotcraft/upstream/demos/typography/countdown-arc-scatter/CountdownArcScatter.tsx +217 -217
- package/lib/motion/shotcraft/upstream/demos/typography/flying-words/FlyingWords.tsx +198 -198
- package/lib/motion/shotcraft/upstream/demos/typography/glitch-cycle/GlitchCycle.tsx +221 -221
- package/lib/motion/shotcraft/upstream/demos/typography/gradient-word-sweep/GradientWordSweep.tsx +312 -312
- package/lib/motion/shotcraft/upstream/demos/typography/lead-word-zoom-assemble/LeadWordZoomAssemble.tsx +261 -261
- package/lib/motion/shotcraft/upstream/demos/typography/marker-underline-title/MarkerUnderlineTitle.tsx +121 -121
- package/lib/motion/shotcraft/upstream/demos/typography/outline-word-fill/OutlineWordFill.tsx +153 -153
- package/lib/motion/shotcraft/upstream/demos/typography/paper-title-card/PaperTitleCard.tsx +179 -179
- package/lib/motion/shotcraft/upstream/demos/typography/pill-chip-slot-cycle-handled/PillChipSlotCycleHandled.tsx +140 -140
- package/lib/motion/shotcraft/upstream/demos/typography/pill-slot-cycle/PillSlotCycle.tsx +309 -309
- package/lib/motion/shotcraft/upstream/demos/typography/text-column-converge/TextColumnConverge.tsx +191 -191
- package/lib/motion/shotcraft/upstream/demos/typography/title-demote-to-label/TitleDemoteToLabel.tsx +292 -292
- package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/LetterformDriftAssembly.tsx +135 -135
- package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/SplitTextStagger.tsx +124 -124
- package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/TextOnPath.tsx +255 -255
- package/lib/motion/shotcraft/upstream/demos/typography/type-entrance-moves/LetterDropPhysics.tsx +173 -173
- package/lib/motion/shotcraft/upstream/demos/typography/type-rhythm-sync/FontWeightPump.tsx +225 -225
- package/lib/motion/shotcraft/upstream/demos/typography/type-rhythm-sync/KaraokeFillSync.tsx +141 -141
- package/lib/motion/shotcraft/upstream/demos/typography/typewriter-moves/TypewriterErrorRetype.tsx +137 -137
- package/lib/motion/shotcraft/upstream/demos/typography/vertical-word-roll-blur-cycle/VerticalWordRollBlurCycle.tsx +147 -147
- package/lib/motion/shotcraft/upstream/demos/typography/word-relay-filmstrip/WordRelayFilmstrip.tsx +409 -409
- package/lib/motion/shotcraft/upstream/demos/typography/word-relay-geometry/WordRelayGeometry.tsx +280 -280
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/avatar-bracket-carousel/AvatarBracketCarousel.tsx +271 -271
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/bezier-source-converge-merge/BezierSourceConvergeMerge.tsx +385 -385
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/card-stack/CardStack.tsx +312 -312
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/carousel-3d/Carousel3D.tsx +303 -303
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/clipcard-looping/ClipCardLooping.tsx +77 -77
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/cloner-depth-echo/ClonerDepthEcho.tsx +311 -311
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/deck-deal-flyin/DeckDealFlyin.tsx +307 -307
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/doc-park-left-pill-deal/DocParkLeftPillDeal.tsx +349 -349
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/document-typewriter-reveal/DocumentTypewriterReveal.tsx +255 -255
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/draw-svg-trace/DrawSvgTrace.tsx +244 -244
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/element-body-moves/ContactShadowLift.tsx +217 -217
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/integration-hub-map/IntegrationHubMap.tsx +652 -652
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/list-reveal/ListReveal.tsx +153 -153
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/list-stack-press/ListStackPress.tsx +238 -238
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/neon-frame-forerun/NeonFrameForerun.tsx +324 -324
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/neon-frame-orbit-drop/NeonFrameForerunOrbit.tsx +354 -354
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/page-waterfall-wall/PageWaterfallWall.tsx +101 -101
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/page-waterfall-wall/VerticalTicker.tsx +129 -129
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/product-card-progressive-assemble/ProductCardProgressiveAssemble.tsx +297 -297
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/radial-wave/RadialWave.tsx +57 -57
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/research-card-stack-scroll/ResearchCardStackScroll.tsx +155 -155
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/row-embed/RowEmbed.tsx +175 -175
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/value-stagger-gradient/ValueStaggerGradient.tsx +153 -153
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/wall-reveal-moves/BentoLightUp.tsx +146 -146
- package/lib/motion/shotcraft/upstream/demos/ui-entrance/wall-reveal-moves/WireframeDrawOn.tsx +226 -226
- package/lib/motion/shotcraft/upstream/gallery/api/library.json +1 -1
- package/lib/motion/shotcraft/upstream/references/aesthetic-rules.md +193 -193
- package/lib/motion/shotcraft/upstream/references/final-review.md +121 -121
- package/lib/motion/shotcraft/upstream/references/guided-free-creation.md +199 -199
- package/lib/motion/shotcraft/upstream/references/jianying-export.md +183 -183
- package/lib/motion/shotcraft/upstream/references/music-beat-sync.md +257 -257
- package/lib/motion/shotcraft/upstream/references/pipeline.md +382 -382
- package/lib/motion/shotcraft/upstream/references/publish-upload-post.md +111 -111
- package/lib/motion/shotcraft/upstream/references/sequences/promo-energy-arc.md +50 -50
- package/lib/motion/shotcraft/upstream/references/sfx-sourcing.md +95 -95
- package/lib/motion/shotcraft/upstream/references/shots/camera/basic-3d-scene.md +41 -41
- package/lib/motion/shotcraft/upstream/references/shots/camera/crash-zoom-punch.md +52 -52
- package/lib/motion/shotcraft/upstream/references/shots/camera/cursor-flyover.md +39 -39
- package/lib/motion/shotcraft/upstream/references/shots/camera/depth-layer-moves.md +39 -39
- package/lib/motion/shotcraft/upstream/references/shots/camera/graze-face-tour.md +57 -57
- package/lib/motion/shotcraft/upstream/references/shots/camera/overhead-camera-moves.md +51 -51
- package/lib/motion/shotcraft/upstream/references/shots/camera/space-camera-moves.md +46 -46
- package/lib/motion/shotcraft/upstream/references/shots/camera/steep-tilt-glide.md +52 -52
- package/lib/motion/shotcraft/upstream/references/shots/camera/tension-camera-moves.md +43 -43
- package/lib/motion/shotcraft/upstream/references/shots/camera/terminal-3d.md +42 -42
- package/lib/motion/shotcraft/upstream/references/shots/data/before-after-slider-scrub.md +48 -48
- package/lib/motion/shotcraft/upstream/references/shots/data/chart-live-moves.md +52 -52
- package/lib/motion/shotcraft/upstream/references/shots/data/gauge-readout-moves.md +45 -45
- package/lib/motion/shotcraft/upstream/references/shots/data/scroll-brake-moves.md +46 -46
- package/lib/motion/shotcraft/upstream/references/shots/data/timeline-travel.md +44 -44
- package/lib/motion/shotcraft/upstream/references/shots/effects/assemble-then-type-flyin.md +63 -63
- package/lib/motion/shotcraft/upstream/references/shots/effects/aurora-bloom-bg-flip.md +54 -54
- package/lib/motion/shotcraft/upstream/references/shots/effects/brand-frame-snap.md +58 -58
- package/lib/motion/shotcraft/upstream/references/shots/effects/fui-hud-moves.md +35 -35
- package/lib/motion/shotcraft/upstream/references/shots/effects/glow-flyline-moves.md +53 -53
- package/lib/motion/shotcraft/upstream/references/shots/effects/icon-performance-moves.md +42 -42
- package/lib/motion/shotcraft/upstream/references/shots/effects/impact-feedback.md +50 -50
- package/lib/motion/shotcraft/upstream/references/shots/effects/light-play-moves.md +46 -46
- package/lib/motion/shotcraft/upstream/references/shots/effects/radial-ripple-phone-chips.md +56 -56
- package/lib/motion/shotcraft/upstream/references/shots/effects/riso-print-hits.md +49 -49
- package/lib/motion/shotcraft/upstream/references/shots/effects/scan-bracket-sweep.md +50 -50
- package/lib/motion/shotcraft/upstream/references/shots/effects/scanline-annotate-focus.md +53 -53
- package/lib/motion/shotcraft/upstream/references/shots/effects/scanline-assemble-flyin.md +53 -53
- package/lib/motion/shotcraft/upstream/references/shots/effects/slam-entrance-moves.md +55 -55
- package/lib/motion/shotcraft/upstream/references/shots/effects/spotlight-sweep-moves.md +52 -52
- package/lib/motion/shotcraft/upstream/references/shots/interaction/autolayout-gap-dial.md +60 -60
- package/lib/motion/shotcraft/upstream/references/shots/interaction/canvas-materialize-moves.md +57 -57
- package/lib/motion/shotcraft/upstream/references/shots/interaction/chip-grid-single-select-blackout.md +51 -51
- package/lib/motion/shotcraft/upstream/references/shots/interaction/collab-cursor-moves.md +41 -41
- package/lib/motion/shotcraft/upstream/references/shots/interaction/glass-pill-dictation-typing.md +53 -53
- package/lib/motion/shotcraft/upstream/references/shots/interaction/hashtag-to-pill-materialize.md +60 -60
- package/lib/motion/shotcraft/upstream/references/shots/interaction/picker-carousel-feature-cycle.md +55 -55
- package/lib/motion/shotcraft/upstream/references/shots/interaction/segmented-thumb-hero.md +57 -57
- package/lib/motion/shotcraft/upstream/references/shots/interaction/theme-switch-moves.md +47 -47
- package/lib/motion/shotcraft/upstream/references/shots/interaction/type-and-filter.md +37 -37
- package/lib/motion/shotcraft/upstream/references/shots/interaction/voice-waveform-live.md +54 -54
- package/lib/motion/shotcraft/upstream/references/shots/opening/brand-ink-open.md +36 -36
- package/lib/motion/shotcraft/upstream/references/shots/opening/crane-rise-reveal.md +56 -56
- package/lib/motion/shotcraft/upstream/references/shots/opening/dataviz-landscape-open.md +56 -56
- package/lib/motion/shotcraft/upstream/references/shots/opening/fracture.md +40 -40
- package/lib/motion/shotcraft/upstream/references/shots/opening/icon-field-colorize.md +60 -60
- package/lib/motion/shotcraft/upstream/references/shots/opening/letterspace-materialize.md +57 -57
- package/lib/motion/shotcraft/upstream/references/shots/opening/magician-card-flourish.md +73 -73
- package/lib/motion/shotcraft/upstream/references/shots/opening/orbit-ring-title-open.md +87 -87
- package/lib/motion/shotcraft/upstream/references/shots/opening/spotlight-hero-card.md +55 -55
- package/lib/motion/shotcraft/upstream/references/shots/opening/stroke-segment-build.md +50 -50
- package/lib/motion/shotcraft/upstream/references/shots/opening/text-as-mask.md +59 -59
- package/lib/motion/shotcraft/upstream/references/shots/outro/grain-dissolve.md +38 -38
- package/lib/motion/shotcraft/upstream/references/shots/outro/logo-shrink-wordmark-lockup.md +38 -38
- package/lib/motion/shotcraft/upstream/references/shots/outro/neon-triple-marquee.md +59 -59
- package/lib/motion/shotcraft/upstream/references/shots/outro/outro-group-photo-launch.md +39 -39
- package/lib/motion/shotcraft/upstream/references/shots/outro/ui-strip-away-outro.md +61 -61
- package/lib/motion/shotcraft/upstream/references/shots/outro/ui-to-brand-morph.md +52 -52
- package/lib/motion/shotcraft/upstream/references/shots/rhythm/beat-cut-moves.md +50 -50
- package/lib/motion/shotcraft/upstream/references/shots/rhythm/beat-step-list-theme-cycle.md +66 -66
- package/lib/motion/shotcraft/upstream/references/shots/rhythm/panel-grid-moves.md +43 -43
- package/lib/motion/shotcraft/upstream/references/shots/rhythm/quad-split-parallel-scenes.md +38 -38
- package/lib/motion/shotcraft/upstream/references/shots/rhythm/rhythm-interrupt-moves.md +38 -38
- package/lib/motion/shotcraft/upstream/references/shots/rhythm/sakuga-timing-shift.md +56 -56
- package/lib/motion/shotcraft/upstream/references/shots/rhythm/speed-ramp-freeze.md +44 -44
- package/lib/motion/shotcraft/upstream/references/shots/rhythm/trailer-grammar-moves.md +38 -38
- package/lib/motion/shotcraft/upstream/references/shots/transition/bottom-push-stack-wipe.md +63 -63
- package/lib/motion/shotcraft/upstream/references/shots/transition/card-flip-reveal.md +57 -57
- package/lib/motion/shotcraft/upstream/references/shots/transition/card-flock-tumble.md +63 -63
- package/lib/motion/shotcraft/upstream/references/shots/transition/circle-match-iris.md +58 -58
- package/lib/motion/shotcraft/upstream/references/shots/transition/gradient-transition.md +45 -45
- package/lib/motion/shotcraft/upstream/references/shots/transition/line-carry-transition.md +55 -55
- package/lib/motion/shotcraft/upstream/references/shots/transition/mosaic-reframe.md +49 -49
- package/lib/motion/shotcraft/upstream/references/shots/transition/page-turn-transitions.md +42 -42
- package/lib/motion/shotcraft/upstream/references/shots/transition/print-texture-transitions.md +42 -42
- package/lib/motion/shotcraft/upstream/references/shots/transition/shot-transitions.md +45 -45
- package/lib/motion/shotcraft/upstream/references/shots/transition/tear-streak-transitions.md +48 -48
- package/lib/motion/shotcraft/upstream/references/shots/transition/transition-hidden-cut.md +55 -55
- package/lib/motion/shotcraft/upstream/references/shots/transition/transition-travel.md +43 -43
- package/lib/motion/shotcraft/upstream/references/shots/transition/white-flash-logo-simplify-cut.md +41 -41
- package/lib/motion/shotcraft/upstream/references/shots/transition/wipe-transitions.md +42 -42
- package/lib/motion/shotcraft/upstream/references/shots/typography/blur-slide.md +59 -59
- package/lib/motion/shotcraft/upstream/references/shots/typography/brace-expand.md +55 -55
- package/lib/motion/shotcraft/upstream/references/shots/typography/countdown-arc-scatter.md +65 -65
- package/lib/motion/shotcraft/upstream/references/shots/typography/document-typewriter-reveal.md +42 -42
- package/lib/motion/shotcraft/upstream/references/shots/typography/flying-words.md +64 -64
- package/lib/motion/shotcraft/upstream/references/shots/typography/glitch-cycle.md +64 -64
- package/lib/motion/shotcraft/upstream/references/shots/typography/gradient-word-sweep.md +54 -54
- package/lib/motion/shotcraft/upstream/references/shots/typography/lead-word-zoom-assemble.md +91 -91
- package/lib/motion/shotcraft/upstream/references/shots/typography/marker-underline-title.md +51 -51
- package/lib/motion/shotcraft/upstream/references/shots/typography/outline-word-fill.md +66 -66
- package/lib/motion/shotcraft/upstream/references/shots/typography/paper-title-card.md +38 -38
- package/lib/motion/shotcraft/upstream/references/shots/typography/pill-chip-slot-cycle-handled.md +66 -66
- package/lib/motion/shotcraft/upstream/references/shots/typography/pill-slot-cycle.md +58 -58
- package/lib/motion/shotcraft/upstream/references/shots/typography/text-column-converge.md +61 -61
- package/lib/motion/shotcraft/upstream/references/shots/typography/title-demote-to-label.md +64 -64
- package/lib/motion/shotcraft/upstream/references/shots/typography/type-assembly-moves.md +45 -45
- package/lib/motion/shotcraft/upstream/references/shots/typography/type-entrance-moves.md +41 -41
- package/lib/motion/shotcraft/upstream/references/shots/typography/type-rhythm-sync.md +51 -51
- package/lib/motion/shotcraft/upstream/references/shots/typography/typewriter-moves.md +42 -42
- package/lib/motion/shotcraft/upstream/references/shots/typography/vertical-word-roll-blur-cycle.md +63 -63
- package/lib/motion/shotcraft/upstream/references/shots/typography/word-relay-filmstrip.md +57 -57
- package/lib/motion/shotcraft/upstream/references/shots/typography/word-relay-geometry.md +75 -75
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/avatar-bracket-carousel.md +59 -59
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/bezier-source-converge-merge.md +67 -67
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/card-stack.md +60 -60
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/carousel-3d.md +66 -66
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/cloner-depth-echo.md +40 -40
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/deck-deal-flyin.md +45 -45
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/doc-park-left-pill-deal.md +62 -62
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/draw-svg-trace.md +55 -55
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/element-body-moves.md +37 -37
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/integration-hub-map.md +55 -55
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/list-reveal.md +50 -50
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/list-stack-press.md +43 -43
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/neon-frame-forerun.md +55 -55
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/neon-frame-orbit-drop.md +51 -51
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/page-waterfall-wall.md +51 -51
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/product-card-progressive-assemble.md +56 -56
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/radial-wave.md +49 -49
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/research-card-stack-scroll.md +57 -57
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/row-embed.md +36 -36
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/value-stagger-gradient.md +64 -64
- package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/wall-reveal-moves.md +47 -47
- package/lib/motion/shotcraft/upstream/references/sound-design.md +170 -170
- package/lib/motion/shotcraft/upstream/references/workbench.md +157 -157
- package/lib/motion/shotcraft/upstream/template/TEMPLATE.md +103 -103
- package/lib/motion/shotcraft/upstream/template/THEMES.md +44 -44
- package/lib/motion/shotcraft/upstream/template/package.json +20 -20
- package/lib/motion/shotcraft/upstream/template/remotion.config.ts +6 -6
- package/lib/motion/shotcraft/upstream/template/src/Root.tsx +17 -17
- package/lib/motion/shotcraft/upstream/template/src/aifl/Caption.tsx +65 -65
- package/lib/motion/shotcraft/upstream/template/src/aifl/DigitRoll.tsx +48 -48
- package/lib/motion/shotcraft/upstream/template/src/aifl/FlashCut.tsx +24 -24
- package/lib/motion/shotcraft/upstream/template/src/aifl/Main.tsx +192 -192
- package/lib/motion/shotcraft/upstream/template/src/aifl/PaperTitleCard.tsx +111 -111
- package/lib/motion/shotcraft/upstream/template/src/aifl/live/PageCam.tsx +150 -150
- package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneDetail.tsx +158 -158
- package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneFlyIn.tsx +468 -468
- package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneOpen.tsx +552 -552
- package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneOutroLive.tsx +411 -411
- package/lib/motion/shotcraft/upstream/template/src/aifl/live/ScenePapers.tsx +200 -200
- package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneWbr.tsx +324 -324
- package/lib/motion/shotcraft/upstream/template/src/aifl/live-layout.json +388 -388
- package/lib/motion/shotcraft/upstream/template/src/index.ts +4 -4
- package/lib/motion/shotcraft/upstream/template/src/themes/ThemedFilm.tsx +7 -7
- package/lib/motion/shotcraft/upstream/template/src/themes/manifest.tsx +68 -68
- package/lib/motion/shotcraft/upstream/template/src/themes/palette-assets.json +1 -1
- package/lib/motion/shotcraft/upstream/template/src/themes/palette-assets.ts +24 -24
- package/lib/motion/shotcraft/upstream/template/src/themes/palettes.json +74 -74
- package/lib/motion/shotcraft/upstream/template/src/themes/visual-theme.tsx +91 -91
- package/lib/motion/shotcraft/upstream/template/src/workbench.ts +213 -213
- package/lib/motion/shotcraft/upstream/template/tsconfig.json +15 -15
- package/lib/motion/style-frames.js +306 -306
- package/lib/motion/sync.js +214 -214
- package/lib/motion-library.js +1 -1
- package/lib/motion-project.js +105 -105
- package/lib/motion-render-worker.js +174 -174
- package/lib/routing/router.js +222 -222
- package/lib/routing/vendor/README.md +96 -96
- package/lib/routing/vendor/libavoid-routing.js +753 -753
- package/lib/routing/vendor/libavoid.min.js +59 -59
- package/lib/svg-export.js +1344 -0
- package/lib/video-trace-pool.js +128 -128
- package/package.json +3 -2
- package/LICENSE +0 -4175
|
@@ -1,150 +1,150 @@
|
|
|
1
|
-
import { useVisualTheme, themePaint, themeAsset } from '../../themes/visual-theme';
|
|
2
|
-
import { AbsoluteFill, Img, interpolate, staticFile, useCurrentFrame, Easing } from 'remotion';
|
|
3
|
-
|
|
4
|
-
export type CamKey = {
|
|
5
|
-
frame: number;
|
|
6
|
-
cx: number;
|
|
7
|
-
cy: number;
|
|
8
|
-
zoom: number;
|
|
9
|
-
rotX?: number; // deg, tilt about the horizontal axis (positive = top leans away, like looking at a table)
|
|
10
|
-
rotY?: number; // deg, tilt about the vertical axis (positive = right edge recedes, i.e. seen from the LEFT)
|
|
11
|
-
rotZ?: number; // deg, in-plane roll
|
|
12
|
-
persp?: number; // px, perspective strength (default 1400; smaller = stronger)
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
const lerp = (a: number, b: number, t: number) => a + (b - a) * t;
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* 2.5D camera over a full-page screenshot. (cx, cy) is the page-space CSS
|
|
19
|
-
* point centered in the 1920x1080 viewport; zoom is scale (1 = 1 CSS px
|
|
20
|
-
* -> 1 output px). Page textures are 2x, rendered at CSS size via width.
|
|
21
|
-
*
|
|
22
|
-
* Optional 3D: keys may carry rotX/rotZ/persp to tilt the page like a plane
|
|
23
|
-
* seen from an oblique camera. When NO key declares any 3D field, the markup
|
|
24
|
-
* degrades to the original flat pan/zoom and renders pixel-identical.
|
|
25
|
-
*
|
|
26
|
-
* Optional DOF: a screen-space gradient-blur band approximating a focal plane
|
|
27
|
-
* near `focusY` (blurring the far/top part of a tilted page).
|
|
28
|
-
*/
|
|
29
|
-
export const PageCam: React.FC<{
|
|
30
|
-
src: string; // staticFile path under textures/live/
|
|
31
|
-
pageH: number; // CSS page height
|
|
32
|
-
keys: CamKey[];
|
|
33
|
-
children?: React.ReactNode; // page-space overlays (positioned in CSS px)
|
|
34
|
-
blur?: number;
|
|
35
|
-
saturate?: number;
|
|
36
|
-
ease?: (t: number) => number;
|
|
37
|
-
dof?: { focusY: number; strength: number };
|
|
38
|
-
}> = ({ src, pageH, keys, children, blur = 0, saturate = 1, ease = Easing.bezier(0.33, 0, 0.15, 1), dof }) => {
|
|
39
|
-
const theme = useVisualTheme();
|
|
40
|
-
const paint = (css: string) => themePaint(theme, css);
|
|
41
|
-
const asset = (src: string) => themeAsset(theme, src);
|
|
42
|
-
|
|
43
|
-
const frame = useCurrentFrame();
|
|
44
|
-
// find segment
|
|
45
|
-
let a = keys[0], b = keys[keys.length - 1];
|
|
46
|
-
for (let i = 0; i < keys.length - 1; i++) {
|
|
47
|
-
if (frame >= keys[i].frame && frame <= keys[i + 1].frame) { a = keys[i]; b = keys[i + 1]; break; }
|
|
48
|
-
}
|
|
49
|
-
const t = a.frame === b.frame ? 1 : interpolate(frame, [a.frame, b.frame], [0, 1], {
|
|
50
|
-
extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: ease,
|
|
51
|
-
});
|
|
52
|
-
const cx = lerp(a.cx, b.cx, t);
|
|
53
|
-
const cy = lerp(a.cy, b.cy, t);
|
|
54
|
-
const zoom = lerp(a.zoom, b.zoom, t);
|
|
55
|
-
|
|
56
|
-
const filters: string[] = [];
|
|
57
|
-
if (blur > 0) filters.push(`blur(${blur}px)`);
|
|
58
|
-
if (saturate !== 1) filters.push(`saturate(${saturate})`);
|
|
59
|
-
|
|
60
|
-
// Does any key request 3D? If not, keep the original flat markup exactly.
|
|
61
|
-
const has3D = keys.some((k) => k.rotX !== undefined || k.rotY !== undefined || k.rotZ !== undefined || k.persp !== undefined);
|
|
62
|
-
|
|
63
|
-
if (!has3D) {
|
|
64
|
-
return (
|
|
65
|
-
<AbsoluteFill style={{ overflow: 'hidden', backgroundColor: paint('#faf7f2') }}>
|
|
66
|
-
<div
|
|
67
|
-
style={{
|
|
68
|
-
position: 'absolute', width: 1920, height: pageH,
|
|
69
|
-
transform: `translate(${960 - cx * zoom}px, ${540 - cy * zoom}px) scale(${zoom})`,
|
|
70
|
-
transformOrigin: '0 0',
|
|
71
|
-
filter: filters.length ? filters.join(' ') : undefined,
|
|
72
|
-
}}
|
|
73
|
-
>
|
|
74
|
-
<Img src={asset(src)} style={{ position: 'absolute', width: 1920, height: pageH }} />
|
|
75
|
-
{children}
|
|
76
|
-
</div>
|
|
77
|
-
</AbsoluteFill>
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// 3D mode: pivot rotation/scale about the focal page-point (cx, cy) so it
|
|
82
|
-
// stays centered in the viewport. With rotX=rotZ=0 this reduces to the flat
|
|
83
|
-
// transform (proven identical: (960,540) + zoom*(p - (cx,cy))).
|
|
84
|
-
const rotX = lerp(a.rotX ?? 0, b.rotX ?? 0, t);
|
|
85
|
-
const rotY = lerp(a.rotY ?? 0, b.rotY ?? 0, t);
|
|
86
|
-
const rotZ = lerp(a.rotZ ?? 0, b.rotZ ?? 0, t);
|
|
87
|
-
const persp = lerp(a.persp ?? 1400, b.persp ?? 1400, t);
|
|
88
|
-
|
|
89
|
-
return (
|
|
90
|
-
<AbsoluteFill style={{ overflow: 'hidden', backgroundColor: paint('#faf7f2') }}>
|
|
91
|
-
<div
|
|
92
|
-
style={{
|
|
93
|
-
position: 'absolute', inset: 0,
|
|
94
|
-
perspective: `${persp * zoom}px`,
|
|
95
|
-
perspectiveOrigin: '960px 540px',
|
|
96
|
-
}}
|
|
97
|
-
>
|
|
98
|
-
{/* LAYOUT-SCALE zoom: instead of scale(zoom) in the transform chain (which
|
|
99
|
-
makes Chromium rasterize the 3D-composited layer at 1920-wide LAYOUT
|
|
100
|
-
size and then GPU-upscale by zoom — everything inside gets downsampled
|
|
101
|
-
before magnification, hence blurry text), we apply the magnification as
|
|
102
|
-
the CSS `zoom` property. `zoom` enlarges the layout box itself, so the
|
|
103
|
-
page + card textures rasterize at the ENLARGED device size and sample
|
|
104
|
-
down from their hi-res sources → sharp glyph edges under perspective.
|
|
105
|
-
|
|
106
|
-
Coordinate math: `zoom` scales this element's local coordinate space by
|
|
107
|
-
`zoom`, so a page point (cx,cy) renders at (cx*zoom, cy*zoom) device px
|
|
108
|
-
from the box origin, and a `translate(Tx px)` renders as Tx*zoom device
|
|
109
|
-
px. To land the focal point (cx,cy) at viewport centre (960,540):
|
|
110
|
-
cx*zoom + Tx*zoom = 960 ⟹ Tx = 960/zoom - cx (likewise Ty).
|
|
111
|
-
Rotations pivot about transform-origin (cx,cy) = the focal point, so
|
|
112
|
-
they leave its screen position unchanged. With rot=0 this reduces to
|
|
113
|
-
translate(960/zoom - cx, 540/zoom - cy) under zoom — identical framing
|
|
114
|
-
to the old scale-based transform, just rasterized at layout scale. */}
|
|
115
|
-
<div
|
|
116
|
-
style={{
|
|
117
|
-
position: 'absolute', width: 1920, height: pageH,
|
|
118
|
-
zoom,
|
|
119
|
-
transform: `translate(${960 / zoom - cx}px, ${540 / zoom - cy}px) rotateY(${rotY}deg) rotateX(${rotX}deg) rotateZ(${rotZ}deg)`,
|
|
120
|
-
transformOrigin: `${cx}px ${cy}px`,
|
|
121
|
-
transformStyle: 'preserve-3d',
|
|
122
|
-
filter: filters.length ? filters.join(' ') : undefined,
|
|
123
|
-
}}
|
|
124
|
-
>
|
|
125
|
-
<Img src={asset(src)} style={{ position: 'absolute', width: 1920, height: pageH }} />
|
|
126
|
-
{children}
|
|
127
|
-
</div>
|
|
128
|
-
</div>
|
|
129
|
-
|
|
130
|
-
{/* Depth-of-field approximation: a top-band gradient blur (far part of a
|
|
131
|
-
tilted page reads soft). Screen-space, over the page. */}
|
|
132
|
-
{dof ? (
|
|
133
|
-
<div
|
|
134
|
-
style={{
|
|
135
|
-
position: 'absolute',
|
|
136
|
-
left: 0,
|
|
137
|
-
right: 0,
|
|
138
|
-
top: 0,
|
|
139
|
-
height: Math.max(0, dof.focusY),
|
|
140
|
-
backdropFilter: `blur(${dof.strength}px)`,
|
|
141
|
-
WebkitBackdropFilter: `blur(${dof.strength}px)`,
|
|
142
|
-
maskImage: paint('linear-gradient(to bottom, rgba(0,0,0,1) 0%, rgba(0,0,0,1) 45%, rgba(0,0,0,0) 100%)'),
|
|
143
|
-
WebkitMaskImage: paint('linear-gradient(to bottom, rgba(0,0,0,1) 0%, rgba(0,0,0,1) 45%, rgba(0,0,0,0) 100%)'),
|
|
144
|
-
pointerEvents: 'none',
|
|
145
|
-
}}
|
|
146
|
-
/>
|
|
147
|
-
) : null}
|
|
148
|
-
</AbsoluteFill>
|
|
149
|
-
);
|
|
150
|
-
};
|
|
1
|
+
import { useVisualTheme, themePaint, themeAsset } from '../../themes/visual-theme';
|
|
2
|
+
import { AbsoluteFill, Img, interpolate, staticFile, useCurrentFrame, Easing } from 'remotion';
|
|
3
|
+
|
|
4
|
+
export type CamKey = {
|
|
5
|
+
frame: number;
|
|
6
|
+
cx: number;
|
|
7
|
+
cy: number;
|
|
8
|
+
zoom: number;
|
|
9
|
+
rotX?: number; // deg, tilt about the horizontal axis (positive = top leans away, like looking at a table)
|
|
10
|
+
rotY?: number; // deg, tilt about the vertical axis (positive = right edge recedes, i.e. seen from the LEFT)
|
|
11
|
+
rotZ?: number; // deg, in-plane roll
|
|
12
|
+
persp?: number; // px, perspective strength (default 1400; smaller = stronger)
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const lerp = (a: number, b: number, t: number) => a + (b - a) * t;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 2.5D camera over a full-page screenshot. (cx, cy) is the page-space CSS
|
|
19
|
+
* point centered in the 1920x1080 viewport; zoom is scale (1 = 1 CSS px
|
|
20
|
+
* -> 1 output px). Page textures are 2x, rendered at CSS size via width.
|
|
21
|
+
*
|
|
22
|
+
* Optional 3D: keys may carry rotX/rotZ/persp to tilt the page like a plane
|
|
23
|
+
* seen from an oblique camera. When NO key declares any 3D field, the markup
|
|
24
|
+
* degrades to the original flat pan/zoom and renders pixel-identical.
|
|
25
|
+
*
|
|
26
|
+
* Optional DOF: a screen-space gradient-blur band approximating a focal plane
|
|
27
|
+
* near `focusY` (blurring the far/top part of a tilted page).
|
|
28
|
+
*/
|
|
29
|
+
export const PageCam: React.FC<{
|
|
30
|
+
src: string; // staticFile path under textures/live/
|
|
31
|
+
pageH: number; // CSS page height
|
|
32
|
+
keys: CamKey[];
|
|
33
|
+
children?: React.ReactNode; // page-space overlays (positioned in CSS px)
|
|
34
|
+
blur?: number;
|
|
35
|
+
saturate?: number;
|
|
36
|
+
ease?: (t: number) => number;
|
|
37
|
+
dof?: { focusY: number; strength: number };
|
|
38
|
+
}> = ({ src, pageH, keys, children, blur = 0, saturate = 1, ease = Easing.bezier(0.33, 0, 0.15, 1), dof }) => {
|
|
39
|
+
const theme = useVisualTheme();
|
|
40
|
+
const paint = (css: string) => themePaint(theme, css);
|
|
41
|
+
const asset = (src: string) => themeAsset(theme, src);
|
|
42
|
+
|
|
43
|
+
const frame = useCurrentFrame();
|
|
44
|
+
// find segment
|
|
45
|
+
let a = keys[0], b = keys[keys.length - 1];
|
|
46
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
47
|
+
if (frame >= keys[i].frame && frame <= keys[i + 1].frame) { a = keys[i]; b = keys[i + 1]; break; }
|
|
48
|
+
}
|
|
49
|
+
const t = a.frame === b.frame ? 1 : interpolate(frame, [a.frame, b.frame], [0, 1], {
|
|
50
|
+
extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: ease,
|
|
51
|
+
});
|
|
52
|
+
const cx = lerp(a.cx, b.cx, t);
|
|
53
|
+
const cy = lerp(a.cy, b.cy, t);
|
|
54
|
+
const zoom = lerp(a.zoom, b.zoom, t);
|
|
55
|
+
|
|
56
|
+
const filters: string[] = [];
|
|
57
|
+
if (blur > 0) filters.push(`blur(${blur}px)`);
|
|
58
|
+
if (saturate !== 1) filters.push(`saturate(${saturate})`);
|
|
59
|
+
|
|
60
|
+
// Does any key request 3D? If not, keep the original flat markup exactly.
|
|
61
|
+
const has3D = keys.some((k) => k.rotX !== undefined || k.rotY !== undefined || k.rotZ !== undefined || k.persp !== undefined);
|
|
62
|
+
|
|
63
|
+
if (!has3D) {
|
|
64
|
+
return (
|
|
65
|
+
<AbsoluteFill style={{ overflow: 'hidden', backgroundColor: paint('#faf7f2') }}>
|
|
66
|
+
<div
|
|
67
|
+
style={{
|
|
68
|
+
position: 'absolute', width: 1920, height: pageH,
|
|
69
|
+
transform: `translate(${960 - cx * zoom}px, ${540 - cy * zoom}px) scale(${zoom})`,
|
|
70
|
+
transformOrigin: '0 0',
|
|
71
|
+
filter: filters.length ? filters.join(' ') : undefined,
|
|
72
|
+
}}
|
|
73
|
+
>
|
|
74
|
+
<Img src={asset(src)} style={{ position: 'absolute', width: 1920, height: pageH }} />
|
|
75
|
+
{children}
|
|
76
|
+
</div>
|
|
77
|
+
</AbsoluteFill>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// 3D mode: pivot rotation/scale about the focal page-point (cx, cy) so it
|
|
82
|
+
// stays centered in the viewport. With rotX=rotZ=0 this reduces to the flat
|
|
83
|
+
// transform (proven identical: (960,540) + zoom*(p - (cx,cy))).
|
|
84
|
+
const rotX = lerp(a.rotX ?? 0, b.rotX ?? 0, t);
|
|
85
|
+
const rotY = lerp(a.rotY ?? 0, b.rotY ?? 0, t);
|
|
86
|
+
const rotZ = lerp(a.rotZ ?? 0, b.rotZ ?? 0, t);
|
|
87
|
+
const persp = lerp(a.persp ?? 1400, b.persp ?? 1400, t);
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<AbsoluteFill style={{ overflow: 'hidden', backgroundColor: paint('#faf7f2') }}>
|
|
91
|
+
<div
|
|
92
|
+
style={{
|
|
93
|
+
position: 'absolute', inset: 0,
|
|
94
|
+
perspective: `${persp * zoom}px`,
|
|
95
|
+
perspectiveOrigin: '960px 540px',
|
|
96
|
+
}}
|
|
97
|
+
>
|
|
98
|
+
{/* LAYOUT-SCALE zoom: instead of scale(zoom) in the transform chain (which
|
|
99
|
+
makes Chromium rasterize the 3D-composited layer at 1920-wide LAYOUT
|
|
100
|
+
size and then GPU-upscale by zoom — everything inside gets downsampled
|
|
101
|
+
before magnification, hence blurry text), we apply the magnification as
|
|
102
|
+
the CSS `zoom` property. `zoom` enlarges the layout box itself, so the
|
|
103
|
+
page + card textures rasterize at the ENLARGED device size and sample
|
|
104
|
+
down from their hi-res sources → sharp glyph edges under perspective.
|
|
105
|
+
|
|
106
|
+
Coordinate math: `zoom` scales this element's local coordinate space by
|
|
107
|
+
`zoom`, so a page point (cx,cy) renders at (cx*zoom, cy*zoom) device px
|
|
108
|
+
from the box origin, and a `translate(Tx px)` renders as Tx*zoom device
|
|
109
|
+
px. To land the focal point (cx,cy) at viewport centre (960,540):
|
|
110
|
+
cx*zoom + Tx*zoom = 960 ⟹ Tx = 960/zoom - cx (likewise Ty).
|
|
111
|
+
Rotations pivot about transform-origin (cx,cy) = the focal point, so
|
|
112
|
+
they leave its screen position unchanged. With rot=0 this reduces to
|
|
113
|
+
translate(960/zoom - cx, 540/zoom - cy) under zoom — identical framing
|
|
114
|
+
to the old scale-based transform, just rasterized at layout scale. */}
|
|
115
|
+
<div
|
|
116
|
+
style={{
|
|
117
|
+
position: 'absolute', width: 1920, height: pageH,
|
|
118
|
+
zoom,
|
|
119
|
+
transform: `translate(${960 / zoom - cx}px, ${540 / zoom - cy}px) rotateY(${rotY}deg) rotateX(${rotX}deg) rotateZ(${rotZ}deg)`,
|
|
120
|
+
transformOrigin: `${cx}px ${cy}px`,
|
|
121
|
+
transformStyle: 'preserve-3d',
|
|
122
|
+
filter: filters.length ? filters.join(' ') : undefined,
|
|
123
|
+
}}
|
|
124
|
+
>
|
|
125
|
+
<Img src={asset(src)} style={{ position: 'absolute', width: 1920, height: pageH }} />
|
|
126
|
+
{children}
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
|
|
130
|
+
{/* Depth-of-field approximation: a top-band gradient blur (far part of a
|
|
131
|
+
tilted page reads soft). Screen-space, over the page. */}
|
|
132
|
+
{dof ? (
|
|
133
|
+
<div
|
|
134
|
+
style={{
|
|
135
|
+
position: 'absolute',
|
|
136
|
+
left: 0,
|
|
137
|
+
right: 0,
|
|
138
|
+
top: 0,
|
|
139
|
+
height: Math.max(0, dof.focusY),
|
|
140
|
+
backdropFilter: `blur(${dof.strength}px)`,
|
|
141
|
+
WebkitBackdropFilter: `blur(${dof.strength}px)`,
|
|
142
|
+
maskImage: paint('linear-gradient(to bottom, rgba(0,0,0,1) 0%, rgba(0,0,0,1) 45%, rgba(0,0,0,0) 100%)'),
|
|
143
|
+
WebkitMaskImage: paint('linear-gradient(to bottom, rgba(0,0,0,1) 0%, rgba(0,0,0,1) 45%, rgba(0,0,0,0) 100%)'),
|
|
144
|
+
pointerEvents: 'none',
|
|
145
|
+
}}
|
|
146
|
+
/>
|
|
147
|
+
) : null}
|
|
148
|
+
</AbsoluteFill>
|
|
149
|
+
);
|
|
150
|
+
};
|
|
@@ -1,158 +1,158 @@
|
|
|
1
|
-
import { useVisualTheme, themePaint, themeAsset, sceneDefaults } from '../../themes/visual-theme';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
import { interpolate, useCurrentFrame, Easing } from 'remotion';
|
|
4
|
-
import { PageCam, CamKey } from './PageCam';
|
|
5
|
-
import layout from '../live-layout.json';
|
|
6
|
-
|
|
7
|
-
const DETAIL_H = layout.detail.pageH;
|
|
8
|
-
const rows = layout.detail.rows;
|
|
9
|
-
|
|
10
|
-
// the fly-in shot ends on the click into the nano-lab card; this shot opens
|
|
11
|
-
// directly on its detail page (the FlashCut transition covers the cut).
|
|
12
|
-
const DETAIL_CAM: CamKey[] = [
|
|
13
|
-
{ frame: 0, cx: 960, cy: 300, zoom: 1.1 },
|
|
14
|
-
{ frame: 75, cx: 960, cy: 760, zoom: 1.0 }, // 75 ≤ duration 100
|
|
15
|
-
];
|
|
16
|
-
|
|
17
|
-
const FLY_EASE = Easing.bezier(0.3, 0, 0.25, 1);
|
|
18
|
-
|
|
19
|
-
/** Context-level defaults, editable per clip in the workbench. */
|
|
20
|
-
export const SCENE_DETAIL_DEFAULTS = {
|
|
21
|
-
accent: '#ae6700', // oklch(58% 0.13 65) — embed seam colour
|
|
22
|
-
};
|
|
23
|
-
type SceneDetailProps = Partial<typeof SCENE_DETAIL_DEFAULTS>;
|
|
24
|
-
|
|
25
|
-
/** Open on the nano-lab detail page, then pan down while the
|
|
26
|
-
* research-question rows fly in from the air and embed into their slots. */
|
|
27
|
-
export const SceneDetail: React.FC<SceneDetailProps> = (props) => {
|
|
28
|
-
const theme = useVisualTheme();
|
|
29
|
-
const paperStyle = theme.id === 'ink-press';
|
|
30
|
-
const paint = (css: string) => themePaint(theme, css);
|
|
31
|
-
const asset = (src: string) => themeAsset(theme, src);
|
|
32
|
-
const detailSrc = asset('textures/live/detail-full.png');
|
|
33
|
-
const { accent } = { ...sceneDefaults(theme, 'macro', SCENE_DETAIL_DEFAULTS), ...props };
|
|
34
|
-
const frame = useCurrentFrame();
|
|
35
|
-
const df = frame;
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<PageCam src="textures/live/detail-full.png" pageH={DETAIL_H} keys={DETAIL_CAM} ease={Easing.bezier(0.33, 0, 0.15, 1)}>
|
|
39
|
-
{/* research-question rows fly in from the air and embed into their slots.
|
|
40
|
-
Cue table 12+i*9: last row lands 12+36+12=60, amber seam done 68 ≤ 70. */}
|
|
41
|
-
{rows.map((r, i) => {
|
|
42
|
-
const cue = 12 + i * 9;
|
|
43
|
-
const land = cue + 12;
|
|
44
|
-
|
|
45
|
-
// empty-slot paper patch (under the flying row), gone 2f after landing
|
|
46
|
-
const patchOpacity = interpolate(df, [land, land + 2], [1, 0], {
|
|
47
|
-
extrapolateLeft: 'clamp',
|
|
48
|
-
extrapolateRight: 'clamp',
|
|
49
|
-
});
|
|
50
|
-
const patch =
|
|
51
|
-
patchOpacity > 0 ? (
|
|
52
|
-
<div
|
|
53
|
-
key={`patch-${i}`}
|
|
54
|
-
style={{
|
|
55
|
-
position: 'absolute',
|
|
56
|
-
left: r.x - 8,
|
|
57
|
-
top: r.y - 4,
|
|
58
|
-
width: r.w + 24,
|
|
59
|
-
height: r.h + 8,
|
|
60
|
-
background: paperStyle ? '#fdfcfa' : theme.surface,
|
|
61
|
-
opacity: patchOpacity,
|
|
62
|
-
zIndex: 1,
|
|
63
|
-
pointerEvents: 'none',
|
|
64
|
-
}}
|
|
65
|
-
/>
|
|
66
|
-
) : null;
|
|
67
|
-
|
|
68
|
-
// flying row: texture-crop of the row, dropping in from the air.
|
|
69
|
-
// Removed once fully embedded (press bounce done) — texture shows through.
|
|
70
|
-
let flyer: React.ReactNode = null;
|
|
71
|
-
if (df >= cue && df < cue + 16) {
|
|
72
|
-
const p = interpolate(df, [cue, cue + 12], [0, 1], {
|
|
73
|
-
extrapolateLeft: 'clamp',
|
|
74
|
-
extrapolateRight: 'clamp',
|
|
75
|
-
easing: FLY_EASE,
|
|
76
|
-
});
|
|
77
|
-
const appear = interpolate(df, [cue, cue + 3], [0, 1], {
|
|
78
|
-
extrapolateLeft: 'clamp',
|
|
79
|
-
extrapolateRight: 'clamp',
|
|
80
|
-
});
|
|
81
|
-
// 1.06 -> 0.995 during flight, then press-bounce back to 1
|
|
82
|
-
const scale =
|
|
83
|
-
df < land
|
|
84
|
-
? 1.06 - 0.065 * p
|
|
85
|
-
: interpolate(df, [land, land + 4], [0.995, 1], {
|
|
86
|
-
extrapolateLeft: 'clamp',
|
|
87
|
-
extrapolateRight: 'clamp',
|
|
88
|
-
easing: Easing.out(Easing.quad),
|
|
89
|
-
});
|
|
90
|
-
const air = 1 - p; // shadow / tilt fade with flight progress
|
|
91
|
-
flyer = (
|
|
92
|
-
<div
|
|
93
|
-
key={`row-${i}`}
|
|
94
|
-
style={{
|
|
95
|
-
position: 'absolute',
|
|
96
|
-
left: r.x,
|
|
97
|
-
top: r.y,
|
|
98
|
-
width: r.w,
|
|
99
|
-
height: r.h,
|
|
100
|
-
borderRadius: 8,
|
|
101
|
-
backgroundColor: paint('#fff'),
|
|
102
|
-
backgroundImage: `url(${detailSrc})`,
|
|
103
|
-
backgroundSize: `1920px ${DETAIL_H}px`,
|
|
104
|
-
backgroundPosition: `-${r.x}px -${r.y}px`,
|
|
105
|
-
opacity: appear,
|
|
106
|
-
transform: `perspective(900px) translateY(${-120 * air}px) rotateX(${16 * air}deg) scale(${scale})`,
|
|
107
|
-
boxShadow: paint(`0 ${30 * air}px ${60 * air}px rgba(30,25,18,${0.22 * air}), 0 ${8 * air}px ${16 * air}px rgba(30,25,18,${0.12 * air})`),
|
|
108
|
-
zIndex: 3,
|
|
109
|
-
pointerEvents: 'none',
|
|
110
|
-
}}
|
|
111
|
-
/>
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// embed flash: 2px amber seam at the row's bottom edge, expanding from
|
|
116
|
-
// the center on touchdown, then fading out
|
|
117
|
-
let seam: React.ReactNode = null;
|
|
118
|
-
if (df >= land && df < land + 8) {
|
|
119
|
-
const spread = interpolate(df, [land, land + 5], [0, 1], {
|
|
120
|
-
extrapolateLeft: 'clamp',
|
|
121
|
-
extrapolateRight: 'clamp',
|
|
122
|
-
easing: Easing.out(Easing.cubic),
|
|
123
|
-
});
|
|
124
|
-
const seamOpacity = interpolate(df, [land, land + 2, land + 8], [1, 1, 0], {
|
|
125
|
-
extrapolateLeft: 'clamp',
|
|
126
|
-
extrapolateRight: 'clamp',
|
|
127
|
-
});
|
|
128
|
-
const seamW = r.w * spread;
|
|
129
|
-
seam = (
|
|
130
|
-
<div
|
|
131
|
-
key={`seam-${i}`}
|
|
132
|
-
style={{
|
|
133
|
-
position: 'absolute',
|
|
134
|
-
left: r.x + (r.w - seamW) / 2,
|
|
135
|
-
top: r.y + r.h - 2,
|
|
136
|
-
width: seamW,
|
|
137
|
-
height: 2,
|
|
138
|
-
background: accent,
|
|
139
|
-
boxShadow: paint('0 0 6px rgba(180,120,50,0.35)'),
|
|
140
|
-
opacity: seamOpacity,
|
|
141
|
-
zIndex: 4,
|
|
142
|
-
pointerEvents: 'none',
|
|
143
|
-
}}
|
|
144
|
-
/>
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return (
|
|
149
|
-
<React.Fragment key={i}>
|
|
150
|
-
{patch}
|
|
151
|
-
{flyer}
|
|
152
|
-
{seam}
|
|
153
|
-
</React.Fragment>
|
|
154
|
-
);
|
|
155
|
-
})}
|
|
156
|
-
</PageCam>
|
|
157
|
-
);
|
|
158
|
-
};
|
|
1
|
+
import { useVisualTheme, themePaint, themeAsset, sceneDefaults } from '../../themes/visual-theme';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { interpolate, useCurrentFrame, Easing } from 'remotion';
|
|
4
|
+
import { PageCam, CamKey } from './PageCam';
|
|
5
|
+
import layout from '../live-layout.json';
|
|
6
|
+
|
|
7
|
+
const DETAIL_H = layout.detail.pageH;
|
|
8
|
+
const rows = layout.detail.rows;
|
|
9
|
+
|
|
10
|
+
// the fly-in shot ends on the click into the nano-lab card; this shot opens
|
|
11
|
+
// directly on its detail page (the FlashCut transition covers the cut).
|
|
12
|
+
const DETAIL_CAM: CamKey[] = [
|
|
13
|
+
{ frame: 0, cx: 960, cy: 300, zoom: 1.1 },
|
|
14
|
+
{ frame: 75, cx: 960, cy: 760, zoom: 1.0 }, // 75 ≤ duration 100
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
const FLY_EASE = Easing.bezier(0.3, 0, 0.25, 1);
|
|
18
|
+
|
|
19
|
+
/** Context-level defaults, editable per clip in the workbench. */
|
|
20
|
+
export const SCENE_DETAIL_DEFAULTS = {
|
|
21
|
+
accent: '#ae6700', // oklch(58% 0.13 65) — embed seam colour
|
|
22
|
+
};
|
|
23
|
+
type SceneDetailProps = Partial<typeof SCENE_DETAIL_DEFAULTS>;
|
|
24
|
+
|
|
25
|
+
/** Open on the nano-lab detail page, then pan down while the
|
|
26
|
+
* research-question rows fly in from the air and embed into their slots. */
|
|
27
|
+
export const SceneDetail: React.FC<SceneDetailProps> = (props) => {
|
|
28
|
+
const theme = useVisualTheme();
|
|
29
|
+
const paperStyle = theme.id === 'ink-press';
|
|
30
|
+
const paint = (css: string) => themePaint(theme, css);
|
|
31
|
+
const asset = (src: string) => themeAsset(theme, src);
|
|
32
|
+
const detailSrc = asset('textures/live/detail-full.png');
|
|
33
|
+
const { accent } = { ...sceneDefaults(theme, 'macro', SCENE_DETAIL_DEFAULTS), ...props };
|
|
34
|
+
const frame = useCurrentFrame();
|
|
35
|
+
const df = frame;
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<PageCam src="textures/live/detail-full.png" pageH={DETAIL_H} keys={DETAIL_CAM} ease={Easing.bezier(0.33, 0, 0.15, 1)}>
|
|
39
|
+
{/* research-question rows fly in from the air and embed into their slots.
|
|
40
|
+
Cue table 12+i*9: last row lands 12+36+12=60, amber seam done 68 ≤ 70. */}
|
|
41
|
+
{rows.map((r, i) => {
|
|
42
|
+
const cue = 12 + i * 9;
|
|
43
|
+
const land = cue + 12;
|
|
44
|
+
|
|
45
|
+
// empty-slot paper patch (under the flying row), gone 2f after landing
|
|
46
|
+
const patchOpacity = interpolate(df, [land, land + 2], [1, 0], {
|
|
47
|
+
extrapolateLeft: 'clamp',
|
|
48
|
+
extrapolateRight: 'clamp',
|
|
49
|
+
});
|
|
50
|
+
const patch =
|
|
51
|
+
patchOpacity > 0 ? (
|
|
52
|
+
<div
|
|
53
|
+
key={`patch-${i}`}
|
|
54
|
+
style={{
|
|
55
|
+
position: 'absolute',
|
|
56
|
+
left: r.x - 8,
|
|
57
|
+
top: r.y - 4,
|
|
58
|
+
width: r.w + 24,
|
|
59
|
+
height: r.h + 8,
|
|
60
|
+
background: paperStyle ? '#fdfcfa' : theme.surface,
|
|
61
|
+
opacity: patchOpacity,
|
|
62
|
+
zIndex: 1,
|
|
63
|
+
pointerEvents: 'none',
|
|
64
|
+
}}
|
|
65
|
+
/>
|
|
66
|
+
) : null;
|
|
67
|
+
|
|
68
|
+
// flying row: texture-crop of the row, dropping in from the air.
|
|
69
|
+
// Removed once fully embedded (press bounce done) — texture shows through.
|
|
70
|
+
let flyer: React.ReactNode = null;
|
|
71
|
+
if (df >= cue && df < cue + 16) {
|
|
72
|
+
const p = interpolate(df, [cue, cue + 12], [0, 1], {
|
|
73
|
+
extrapolateLeft: 'clamp',
|
|
74
|
+
extrapolateRight: 'clamp',
|
|
75
|
+
easing: FLY_EASE,
|
|
76
|
+
});
|
|
77
|
+
const appear = interpolate(df, [cue, cue + 3], [0, 1], {
|
|
78
|
+
extrapolateLeft: 'clamp',
|
|
79
|
+
extrapolateRight: 'clamp',
|
|
80
|
+
});
|
|
81
|
+
// 1.06 -> 0.995 during flight, then press-bounce back to 1
|
|
82
|
+
const scale =
|
|
83
|
+
df < land
|
|
84
|
+
? 1.06 - 0.065 * p
|
|
85
|
+
: interpolate(df, [land, land + 4], [0.995, 1], {
|
|
86
|
+
extrapolateLeft: 'clamp',
|
|
87
|
+
extrapolateRight: 'clamp',
|
|
88
|
+
easing: Easing.out(Easing.quad),
|
|
89
|
+
});
|
|
90
|
+
const air = 1 - p; // shadow / tilt fade with flight progress
|
|
91
|
+
flyer = (
|
|
92
|
+
<div
|
|
93
|
+
key={`row-${i}`}
|
|
94
|
+
style={{
|
|
95
|
+
position: 'absolute',
|
|
96
|
+
left: r.x,
|
|
97
|
+
top: r.y,
|
|
98
|
+
width: r.w,
|
|
99
|
+
height: r.h,
|
|
100
|
+
borderRadius: 8,
|
|
101
|
+
backgroundColor: paint('#fff'),
|
|
102
|
+
backgroundImage: `url(${detailSrc})`,
|
|
103
|
+
backgroundSize: `1920px ${DETAIL_H}px`,
|
|
104
|
+
backgroundPosition: `-${r.x}px -${r.y}px`,
|
|
105
|
+
opacity: appear,
|
|
106
|
+
transform: `perspective(900px) translateY(${-120 * air}px) rotateX(${16 * air}deg) scale(${scale})`,
|
|
107
|
+
boxShadow: paint(`0 ${30 * air}px ${60 * air}px rgba(30,25,18,${0.22 * air}), 0 ${8 * air}px ${16 * air}px rgba(30,25,18,${0.12 * air})`),
|
|
108
|
+
zIndex: 3,
|
|
109
|
+
pointerEvents: 'none',
|
|
110
|
+
}}
|
|
111
|
+
/>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// embed flash: 2px amber seam at the row's bottom edge, expanding from
|
|
116
|
+
// the center on touchdown, then fading out
|
|
117
|
+
let seam: React.ReactNode = null;
|
|
118
|
+
if (df >= land && df < land + 8) {
|
|
119
|
+
const spread = interpolate(df, [land, land + 5], [0, 1], {
|
|
120
|
+
extrapolateLeft: 'clamp',
|
|
121
|
+
extrapolateRight: 'clamp',
|
|
122
|
+
easing: Easing.out(Easing.cubic),
|
|
123
|
+
});
|
|
124
|
+
const seamOpacity = interpolate(df, [land, land + 2, land + 8], [1, 1, 0], {
|
|
125
|
+
extrapolateLeft: 'clamp',
|
|
126
|
+
extrapolateRight: 'clamp',
|
|
127
|
+
});
|
|
128
|
+
const seamW = r.w * spread;
|
|
129
|
+
seam = (
|
|
130
|
+
<div
|
|
131
|
+
key={`seam-${i}`}
|
|
132
|
+
style={{
|
|
133
|
+
position: 'absolute',
|
|
134
|
+
left: r.x + (r.w - seamW) / 2,
|
|
135
|
+
top: r.y + r.h - 2,
|
|
136
|
+
width: seamW,
|
|
137
|
+
height: 2,
|
|
138
|
+
background: accent,
|
|
139
|
+
boxShadow: paint('0 0 6px rgba(180,120,50,0.35)'),
|
|
140
|
+
opacity: seamOpacity,
|
|
141
|
+
zIndex: 4,
|
|
142
|
+
pointerEvents: 'none',
|
|
143
|
+
}}
|
|
144
|
+
/>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
<React.Fragment key={i}>
|
|
150
|
+
{patch}
|
|
151
|
+
{flyer}
|
|
152
|
+
{seam}
|
|
153
|
+
</React.Fragment>
|
|
154
|
+
);
|
|
155
|
+
})}
|
|
156
|
+
</PageCam>
|
|
157
|
+
);
|
|
158
|
+
};
|