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.
Files changed (379) hide show
  1. package/README.md +7 -5
  2. package/lib/client.js +142 -16
  3. package/lib/index.js +7945 -7719
  4. package/lib/motion/asset-pack.js +394 -394
  5. package/lib/motion/assets.js +291 -291
  6. package/lib/motion/demo-assets-lock.js +10 -10
  7. package/lib/motion/mgstyles/briefs/23-ink-wash.md +147 -0
  8. package/lib/motion/mgstyles/catalog.d/23-ink-wash.json +28 -0
  9. package/lib/motion/mgstyles/catalog.json +127 -14
  10. package/lib/motion/mgstyles/upstream/demos/23-ink-wash/brush.js +149 -0
  11. package/lib/motion/mgstyles/upstream/demos/23-ink-wash/film.js +202 -0
  12. package/lib/motion/mgstyles/upstream/manifest.json +28 -3
  13. package/lib/motion/mgstyles/upstream/prompts/23-ink-wash.md +59 -0
  14. package/lib/motion/mgstyles/vendor/README.md +28 -28
  15. package/lib/motion/mgstyles/vendor/modules/d3/LICENSE +13 -13
  16. package/lib/motion/mgstyles/vendor/modules/d3/dist/d3.min.js +2 -2
  17. package/lib/motion/mgstyles/vendor/modules/opentype.js/LICENSE +20 -20
  18. package/lib/motion/mgstyles/vendor/modules/opentype.js/dist/opentype.mjs +14460 -14460
  19. package/lib/motion/mgstyles/vendor/modules/simplex-noise/LICENSE +21 -21
  20. package/lib/motion/mgstyles/vendor/modules/simplex-noise/dist/esm/simplex-noise.js +465 -465
  21. package/lib/motion/mgstyles/vendor/modules/topojson-client/LICENSE +13 -13
  22. package/lib/motion/mgstyles/vendor/modules/topojson-client/dist/topojson-client.min.js +2 -2
  23. package/lib/motion/project.js +5 -1
  24. package/lib/motion/qa.js +116 -6
  25. package/lib/motion/render.js +179 -179
  26. package/lib/motion/scene-kit.js +1 -1
  27. package/lib/motion/shotcraft/upstream/SKILL.md +286 -286
  28. package/lib/motion/shotcraft/upstream/assets/lib/Caption.tsx +54 -54
  29. package/lib/motion/shotcraft/upstream/assets/lib/ClipCard.tsx +200 -200
  30. package/lib/motion/shotcraft/upstream/assets/lib/DigitRoll.tsx +45 -45
  31. package/lib/motion/shotcraft/upstream/assets/lib/FlashCut.tsx +20 -20
  32. package/lib/motion/shotcraft/upstream/assets/lib/FlatPanel.tsx +65 -65
  33. package/lib/motion/shotcraft/upstream/assets/lib/PageCam.tsx +151 -151
  34. package/lib/motion/shotcraft/upstream/assets/lib/VerticalTicker.tsx +129 -129
  35. package/lib/motion/shotcraft/upstream/assets/lib/helpers/camera.tsx +75 -75
  36. package/lib/motion/shotcraft/upstream/assets/lib/helpers/motion.ts +40 -40
  37. package/lib/motion/shotcraft/upstream/assets/lib/helpers/rand.ts +11 -11
  38. package/lib/motion/shotcraft/upstream/assets/lib/helpers/shake.ts +10 -10
  39. package/lib/motion/shotcraft/upstream/assets/scripts/build-readme-cover.mjs +49 -49
  40. package/lib/motion/shotcraft/upstream/assets/scripts/capture-template.mjs +210 -210
  41. package/lib/motion/shotcraft/upstream/assets/scripts/sfx-source.py +423 -423
  42. package/lib/motion/shotcraft/upstream/assets/scripts/smoke-render-demos.py +170 -170
  43. package/lib/motion/shotcraft/upstream/assets/scripts/test_sfx_source.py +157 -157
  44. package/lib/motion/shotcraft/upstream/demos/README.md +120 -120
  45. package/lib/motion/shotcraft/upstream/demos/_fixtures/Brand.tsx +112 -112
  46. package/lib/motion/shotcraft/upstream/demos/_fixtures/Fixtures.tsx +647 -647
  47. package/lib/motion/shotcraft/upstream/demos/_fixtures/Look.tsx +316 -316
  48. package/lib/motion/shotcraft/upstream/demos/_fixtures/Motion.tsx +82 -82
  49. package/lib/motion/shotcraft/upstream/demos/_fixtures/PageCam2D.tsx +115 -115
  50. package/lib/motion/shotcraft/upstream/demos/_fixtures/Polish.tsx +243 -243
  51. package/lib/motion/shotcraft/upstream/demos/_textures/live-layout.json +388 -388
  52. package/lib/motion/shotcraft/upstream/demos/camera/basic-3d-scene/Basic3DScene.tsx +250 -250
  53. package/lib/motion/shotcraft/upstream/demos/camera/crash-zoom-punch/CrashImpactReal.tsx +305 -305
  54. package/lib/motion/shotcraft/upstream/demos/camera/crash-zoom-punch/CrashZoomReal.tsx +246 -246
  55. package/lib/motion/shotcraft/upstream/demos/camera/cursor-flyover/CursorFlyover.tsx +390 -390
  56. package/lib/motion/shotcraft/upstream/demos/camera/depth-layer-moves/MultiplaneReal.tsx +138 -138
  57. package/lib/motion/shotcraft/upstream/demos/camera/graze-face-tour/GrazeFaceTour.tsx +542 -542
  58. package/lib/motion/shotcraft/upstream/demos/camera/overhead-camera-moves/OverheadTabletopDrop.tsx +315 -315
  59. package/lib/motion/shotcraft/upstream/demos/camera/overhead-camera-moves/TiltReveal.tsx +299 -299
  60. package/lib/motion/shotcraft/upstream/demos/camera/space-camera-moves/DroneDiveLanding.tsx +173 -173
  61. package/lib/motion/shotcraft/upstream/demos/camera/space-camera-moves/ExplodedView.tsx +348 -348
  62. package/lib/motion/shotcraft/upstream/demos/camera/steep-tilt-glide/SteepTiltGlide.tsx +366 -366
  63. package/lib/motion/shotcraft/upstream/demos/camera/tension-camera-moves/BulletTimeFreezeOrbit.tsx +279 -279
  64. package/lib/motion/shotcraft/upstream/demos/camera/tension-camera-moves/PullBackIsolation.tsx +184 -184
  65. package/lib/motion/shotcraft/upstream/demos/camera/terminal-3d/Terminal3D.tsx +390 -390
  66. package/lib/motion/shotcraft/upstream/demos/data/before-after-slider-scrub/BeforeAfterSliderScrub.tsx +155 -155
  67. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/AxisRescaleShockV2.tsx +303 -303
  68. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/OscilloscopeStreamV2.tsx +290 -290
  69. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/UnitDotSwarmRegroupV2.tsx +278 -278
  70. package/lib/motion/shotcraft/upstream/demos/data/gauge-readout-moves/NeedleSweepSelftest.tsx +307 -307
  71. package/lib/motion/shotcraft/upstream/demos/data/gauge-readout-moves/TapeScrollFixedPointer.tsx +215 -215
  72. package/lib/motion/shotcraft/upstream/demos/data/scroll-brake-moves/BrakeReticleLock.tsx +299 -299
  73. package/lib/motion/shotcraft/upstream/demos/data/scroll-brake-moves/ChangelogScrollBrake.tsx +232 -232
  74. package/lib/motion/shotcraft/upstream/demos/data/timeline-travel/TimelineTravel.tsx +290 -290
  75. package/lib/motion/shotcraft/upstream/demos/effects/assemble-then-type-flyin/AssembleThenTypeFlyin.tsx +273 -273
  76. package/lib/motion/shotcraft/upstream/demos/effects/aurora-bloom-bg-flip/AuroraBloomBgFlip.tsx +167 -167
  77. package/lib/motion/shotcraft/upstream/demos/effects/brand-frame-snap/BrandFrameSnap.tsx +536 -536
  78. package/lib/motion/shotcraft/upstream/demos/effects/fui-hud-moves/ReticleLockOn.tsx +164 -164
  79. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/FlylineArc.tsx +175 -175
  80. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/GlowOrbAmbient.tsx +197 -197
  81. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/OrbFlylineRelay.tsx +241 -241
  82. package/lib/motion/shotcraft/upstream/demos/effects/icon-performance-moves/AttentionBounce.tsx +279 -279
  83. package/lib/motion/shotcraft/upstream/demos/effects/impact-feedback/AnimeImpact.tsx +230 -230
  84. package/lib/motion/shotcraft/upstream/demos/effects/impact-feedback/HitCounter.tsx +345 -345
  85. package/lib/motion/shotcraft/upstream/demos/effects/light-play-moves/SheenSweepRetry.tsx +275 -275
  86. package/lib/motion/shotcraft/upstream/demos/effects/light-play-moves/SpotlightSweepReveal.tsx +229 -229
  87. package/lib/motion/shotcraft/upstream/demos/effects/radial-ripple-phone-chips/RadialRipplePhoneChips.tsx +312 -312
  88. package/lib/motion/shotcraft/upstream/demos/effects/riso-print-hits/RisoMisregistrationHit.tsx +222 -222
  89. package/lib/motion/shotcraft/upstream/demos/effects/scan-bracket-sweep/ScanBracketSweep.tsx +295 -295
  90. package/lib/motion/shotcraft/upstream/demos/effects/scanline-annotate-focus/ScanlineAnnotateFocus.tsx +329 -329
  91. package/lib/motion/shotcraft/upstream/demos/effects/scanline-assemble-flyin/ScanlineAssembleFlyin.tsx +315 -315
  92. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/ImpactBurstKit.tsx +264 -264
  93. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/KanadaPerspectiveSnap.tsx +260 -260
  94. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/ScoreSlam.tsx +263 -263
  95. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/CornerSpotlightReveal.tsx +123 -123
  96. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/GlowWakeSleepPanel.tsx +187 -187
  97. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/SlideSpotlightPan.tsx +175 -175
  98. package/lib/motion/shotcraft/upstream/demos/interaction/autolayout-gap-dial/AutolayoutGapDial.tsx +305 -305
  99. package/lib/motion/shotcraft/upstream/demos/interaction/canvas-materialize-moves/DiagramCascadeBuild.tsx +350 -350
  100. package/lib/motion/shotcraft/upstream/demos/interaction/canvas-materialize-moves/PanelToCanvasMaterialize.tsx +352 -352
  101. package/lib/motion/shotcraft/upstream/demos/interaction/chip-grid-single-select-blackout/ChipGridSingleSelectBlackout.tsx +218 -218
  102. package/lib/motion/shotcraft/upstream/demos/interaction/collab-cursor-moves/CursorCastEnsemble.tsx +297 -297
  103. package/lib/motion/shotcraft/upstream/demos/interaction/glass-pill-dictation-typing/GlassPillDictationTyping.tsx +157 -157
  104. package/lib/motion/shotcraft/upstream/demos/interaction/hashtag-to-pill-materialize/HashtagToPillMaterialize.tsx +218 -218
  105. package/lib/motion/shotcraft/upstream/demos/interaction/picker-carousel-feature-cycle/PickerCarouselFeatureCycle.tsx +202 -202
  106. package/lib/motion/shotcraft/upstream/demos/interaction/segmented-thumb-hero/SegmentedThumbHero.tsx +265 -265
  107. package/lib/motion/shotcraft/upstream/demos/interaction/theme-switch-moves/PaletteThemeRipple.tsx +457 -457
  108. package/lib/motion/shotcraft/upstream/demos/interaction/theme-switch-moves/ThemeSweepToggle.tsx +446 -446
  109. package/lib/motion/shotcraft/upstream/demos/interaction/type-and-filter/TypeAndFilter.tsx +249 -249
  110. package/lib/motion/shotcraft/upstream/demos/interaction/voice-waveform-live/VoiceWaveformLive.tsx +278 -278
  111. package/lib/motion/shotcraft/upstream/demos/opening/crane-rise-reveal/CraneRiseReveal.tsx +332 -332
  112. package/lib/motion/shotcraft/upstream/demos/opening/dataviz-landscape-open/DatavizLandscapeOpen.tsx +358 -358
  113. package/lib/motion/shotcraft/upstream/demos/opening/fracture/Fracture.tsx +201 -201
  114. package/lib/motion/shotcraft/upstream/demos/opening/icon-field-colorize/IconFieldColorize.tsx +200 -200
  115. package/lib/motion/shotcraft/upstream/demos/opening/letterspace-materialize/LetterspaceMaterialize.tsx +208 -208
  116. package/lib/motion/shotcraft/upstream/demos/opening/magician-card-flourish/MagicianCardFlourish.tsx +341 -341
  117. package/lib/motion/shotcraft/upstream/demos/opening/orbit-ring-title-open/OrbitRingTitleOpen.tsx +389 -389
  118. package/lib/motion/shotcraft/upstream/demos/opening/spotlight-hero-card/SpotlightHeroCard.tsx +293 -293
  119. package/lib/motion/shotcraft/upstream/demos/opening/stroke-segment-build/StrokeSegmentBuild.tsx +183 -183
  120. package/lib/motion/shotcraft/upstream/demos/opening/text-as-mask/TextAsMask.tsx +245 -245
  121. package/lib/motion/shotcraft/upstream/demos/outro/grain-dissolve/GrainDissolve.tsx +222 -222
  122. package/lib/motion/shotcraft/upstream/demos/outro/logo-shrink-wordmark-lockup/LogoShrinkWordmarkLockup.tsx +223 -223
  123. package/lib/motion/shotcraft/upstream/demos/outro/neon-triple-marquee/NeonTripleMarquee.tsx +217 -217
  124. package/lib/motion/shotcraft/upstream/demos/outro/outro-group-photo-launch/OutroGroupPhotoLaunch.tsx +343 -343
  125. package/lib/motion/shotcraft/upstream/demos/outro/ui-strip-away-outro/UiStripAwayOutro.tsx +357 -357
  126. package/lib/motion/shotcraft/upstream/demos/outro/ui-to-brand-morph/IconFlipBloomLogo.tsx +187 -187
  127. package/lib/motion/shotcraft/upstream/demos/outro/ui-to-brand-morph/InputMorphsIntoLogo.tsx +333 -333
  128. package/lib/motion/shotcraft/upstream/demos/rhythm/beat-cut-moves/PaparazziFlash.tsx +274 -274
  129. package/lib/motion/shotcraft/upstream/demos/rhythm/beat-step-list-theme-cycle/BeatStepListThemeCycle.tsx +270 -270
  130. package/lib/motion/shotcraft/upstream/demos/rhythm/panel-grid-moves/ComicPanelSplit.tsx +430 -430
  131. package/lib/motion/shotcraft/upstream/demos/rhythm/quad-split-parallel-scenes/QuadSplitParallelScenes.tsx +252 -252
  132. package/lib/motion/shotcraft/upstream/demos/rhythm/rhythm-interrupt-moves/JumpCutPunchIn.tsx +106 -106
  133. package/lib/motion/shotcraft/upstream/demos/rhythm/sakuga-timing-shift/SakugaTimingShift.tsx +288 -288
  134. package/lib/motion/shotcraft/upstream/demos/rhythm/speed-ramp-freeze/FreezeAnnotateReal.tsx +362 -362
  135. package/lib/motion/shotcraft/upstream/demos/rhythm/trailer-grammar-moves/TrailerBumper.tsx +168 -168
  136. package/lib/motion/shotcraft/upstream/demos/transition/bottom-push-stack-wipe/BottomPushStackWipe.tsx +310 -310
  137. package/lib/motion/shotcraft/upstream/demos/transition/card-flip-reveal/CardFlipReveal.tsx +261 -261
  138. package/lib/motion/shotcraft/upstream/demos/transition/card-flock-tumble/CardFlockTumble.tsx +459 -459
  139. package/lib/motion/shotcraft/upstream/demos/transition/circle-match-iris/CircleMatchIris.tsx +294 -294
  140. package/lib/motion/shotcraft/upstream/demos/transition/gradient-transition/GradientTransition.tsx +161 -161
  141. package/lib/motion/shotcraft/upstream/demos/transition/line-carry-transition/LineCarryTransition.tsx +248 -248
  142. package/lib/motion/shotcraft/upstream/demos/transition/mosaic-reframe/MosaicReframe.tsx +359 -359
  143. package/lib/motion/shotcraft/upstream/demos/transition/page-turn-transitions/BarnDoorSplit.tsx +227 -227
  144. package/lib/motion/shotcraft/upstream/demos/transition/print-texture-transitions/InkBleedReveal.tsx +162 -162
  145. package/lib/motion/shotcraft/upstream/demos/transition/shot-transitions/PortalWipeV2.tsx +248 -248
  146. package/lib/motion/shotcraft/upstream/demos/transition/shot-transitions/WhipBrakeReal.tsx +186 -186
  147. package/lib/motion/shotcraft/upstream/demos/transition/tear-streak-transitions/GlitchDisplace.tsx +355 -355
  148. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/InvisibleCut.tsx +272 -272
  149. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/LightLeakBurn.tsx +262 -262
  150. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/VersusSlam.tsx +217 -217
  151. package/lib/motion/shotcraft/upstream/demos/transition/transition-travel/LetterformZoom.tsx +285 -285
  152. package/lib/motion/shotcraft/upstream/demos/transition/white-flash-logo-simplify-cut/WhiteFlashLogoSimplifyCut.tsx +205 -205
  153. package/lib/motion/shotcraft/upstream/demos/transition/wipe-transitions/BlindsSlice.tsx +178 -178
  154. package/lib/motion/shotcraft/upstream/demos/typography/blur-slide/BlurSlide.tsx +147 -147
  155. package/lib/motion/shotcraft/upstream/demos/typography/brace-expand/BraceExpand.tsx +143 -143
  156. package/lib/motion/shotcraft/upstream/demos/typography/brand-ink-open/BrandInkOpen.tsx +134 -134
  157. package/lib/motion/shotcraft/upstream/demos/typography/countdown-arc-scatter/CountdownArcScatter.tsx +217 -217
  158. package/lib/motion/shotcraft/upstream/demos/typography/flying-words/FlyingWords.tsx +198 -198
  159. package/lib/motion/shotcraft/upstream/demos/typography/glitch-cycle/GlitchCycle.tsx +221 -221
  160. package/lib/motion/shotcraft/upstream/demos/typography/gradient-word-sweep/GradientWordSweep.tsx +312 -312
  161. package/lib/motion/shotcraft/upstream/demos/typography/lead-word-zoom-assemble/LeadWordZoomAssemble.tsx +261 -261
  162. package/lib/motion/shotcraft/upstream/demos/typography/marker-underline-title/MarkerUnderlineTitle.tsx +121 -121
  163. package/lib/motion/shotcraft/upstream/demos/typography/outline-word-fill/OutlineWordFill.tsx +153 -153
  164. package/lib/motion/shotcraft/upstream/demos/typography/paper-title-card/PaperTitleCard.tsx +179 -179
  165. package/lib/motion/shotcraft/upstream/demos/typography/pill-chip-slot-cycle-handled/PillChipSlotCycleHandled.tsx +140 -140
  166. package/lib/motion/shotcraft/upstream/demos/typography/pill-slot-cycle/PillSlotCycle.tsx +309 -309
  167. package/lib/motion/shotcraft/upstream/demos/typography/text-column-converge/TextColumnConverge.tsx +191 -191
  168. package/lib/motion/shotcraft/upstream/demos/typography/title-demote-to-label/TitleDemoteToLabel.tsx +292 -292
  169. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/LetterformDriftAssembly.tsx +135 -135
  170. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/SplitTextStagger.tsx +124 -124
  171. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/TextOnPath.tsx +255 -255
  172. package/lib/motion/shotcraft/upstream/demos/typography/type-entrance-moves/LetterDropPhysics.tsx +173 -173
  173. package/lib/motion/shotcraft/upstream/demos/typography/type-rhythm-sync/FontWeightPump.tsx +225 -225
  174. package/lib/motion/shotcraft/upstream/demos/typography/type-rhythm-sync/KaraokeFillSync.tsx +141 -141
  175. package/lib/motion/shotcraft/upstream/demos/typography/typewriter-moves/TypewriterErrorRetype.tsx +137 -137
  176. package/lib/motion/shotcraft/upstream/demos/typography/vertical-word-roll-blur-cycle/VerticalWordRollBlurCycle.tsx +147 -147
  177. package/lib/motion/shotcraft/upstream/demos/typography/word-relay-filmstrip/WordRelayFilmstrip.tsx +409 -409
  178. package/lib/motion/shotcraft/upstream/demos/typography/word-relay-geometry/WordRelayGeometry.tsx +280 -280
  179. package/lib/motion/shotcraft/upstream/demos/ui-entrance/avatar-bracket-carousel/AvatarBracketCarousel.tsx +271 -271
  180. package/lib/motion/shotcraft/upstream/demos/ui-entrance/bezier-source-converge-merge/BezierSourceConvergeMerge.tsx +385 -385
  181. package/lib/motion/shotcraft/upstream/demos/ui-entrance/card-stack/CardStack.tsx +312 -312
  182. package/lib/motion/shotcraft/upstream/demos/ui-entrance/carousel-3d/Carousel3D.tsx +303 -303
  183. package/lib/motion/shotcraft/upstream/demos/ui-entrance/clipcard-looping/ClipCardLooping.tsx +77 -77
  184. package/lib/motion/shotcraft/upstream/demos/ui-entrance/cloner-depth-echo/ClonerDepthEcho.tsx +311 -311
  185. package/lib/motion/shotcraft/upstream/demos/ui-entrance/deck-deal-flyin/DeckDealFlyin.tsx +307 -307
  186. package/lib/motion/shotcraft/upstream/demos/ui-entrance/doc-park-left-pill-deal/DocParkLeftPillDeal.tsx +349 -349
  187. package/lib/motion/shotcraft/upstream/demos/ui-entrance/document-typewriter-reveal/DocumentTypewriterReveal.tsx +255 -255
  188. package/lib/motion/shotcraft/upstream/demos/ui-entrance/draw-svg-trace/DrawSvgTrace.tsx +244 -244
  189. package/lib/motion/shotcraft/upstream/demos/ui-entrance/element-body-moves/ContactShadowLift.tsx +217 -217
  190. package/lib/motion/shotcraft/upstream/demos/ui-entrance/integration-hub-map/IntegrationHubMap.tsx +652 -652
  191. package/lib/motion/shotcraft/upstream/demos/ui-entrance/list-reveal/ListReveal.tsx +153 -153
  192. package/lib/motion/shotcraft/upstream/demos/ui-entrance/list-stack-press/ListStackPress.tsx +238 -238
  193. package/lib/motion/shotcraft/upstream/demos/ui-entrance/neon-frame-forerun/NeonFrameForerun.tsx +324 -324
  194. package/lib/motion/shotcraft/upstream/demos/ui-entrance/neon-frame-orbit-drop/NeonFrameForerunOrbit.tsx +354 -354
  195. package/lib/motion/shotcraft/upstream/demos/ui-entrance/page-waterfall-wall/PageWaterfallWall.tsx +101 -101
  196. package/lib/motion/shotcraft/upstream/demos/ui-entrance/page-waterfall-wall/VerticalTicker.tsx +129 -129
  197. package/lib/motion/shotcraft/upstream/demos/ui-entrance/product-card-progressive-assemble/ProductCardProgressiveAssemble.tsx +297 -297
  198. package/lib/motion/shotcraft/upstream/demos/ui-entrance/radial-wave/RadialWave.tsx +57 -57
  199. package/lib/motion/shotcraft/upstream/demos/ui-entrance/research-card-stack-scroll/ResearchCardStackScroll.tsx +155 -155
  200. package/lib/motion/shotcraft/upstream/demos/ui-entrance/row-embed/RowEmbed.tsx +175 -175
  201. package/lib/motion/shotcraft/upstream/demos/ui-entrance/value-stagger-gradient/ValueStaggerGradient.tsx +153 -153
  202. package/lib/motion/shotcraft/upstream/demos/ui-entrance/wall-reveal-moves/BentoLightUp.tsx +146 -146
  203. package/lib/motion/shotcraft/upstream/demos/ui-entrance/wall-reveal-moves/WireframeDrawOn.tsx +226 -226
  204. package/lib/motion/shotcraft/upstream/gallery/api/library.json +1 -1
  205. package/lib/motion/shotcraft/upstream/references/aesthetic-rules.md +193 -193
  206. package/lib/motion/shotcraft/upstream/references/final-review.md +121 -121
  207. package/lib/motion/shotcraft/upstream/references/guided-free-creation.md +199 -199
  208. package/lib/motion/shotcraft/upstream/references/jianying-export.md +183 -183
  209. package/lib/motion/shotcraft/upstream/references/music-beat-sync.md +257 -257
  210. package/lib/motion/shotcraft/upstream/references/pipeline.md +382 -382
  211. package/lib/motion/shotcraft/upstream/references/publish-upload-post.md +111 -111
  212. package/lib/motion/shotcraft/upstream/references/sequences/promo-energy-arc.md +50 -50
  213. package/lib/motion/shotcraft/upstream/references/sfx-sourcing.md +95 -95
  214. package/lib/motion/shotcraft/upstream/references/shots/camera/basic-3d-scene.md +41 -41
  215. package/lib/motion/shotcraft/upstream/references/shots/camera/crash-zoom-punch.md +52 -52
  216. package/lib/motion/shotcraft/upstream/references/shots/camera/cursor-flyover.md +39 -39
  217. package/lib/motion/shotcraft/upstream/references/shots/camera/depth-layer-moves.md +39 -39
  218. package/lib/motion/shotcraft/upstream/references/shots/camera/graze-face-tour.md +57 -57
  219. package/lib/motion/shotcraft/upstream/references/shots/camera/overhead-camera-moves.md +51 -51
  220. package/lib/motion/shotcraft/upstream/references/shots/camera/space-camera-moves.md +46 -46
  221. package/lib/motion/shotcraft/upstream/references/shots/camera/steep-tilt-glide.md +52 -52
  222. package/lib/motion/shotcraft/upstream/references/shots/camera/tension-camera-moves.md +43 -43
  223. package/lib/motion/shotcraft/upstream/references/shots/camera/terminal-3d.md +42 -42
  224. package/lib/motion/shotcraft/upstream/references/shots/data/before-after-slider-scrub.md +48 -48
  225. package/lib/motion/shotcraft/upstream/references/shots/data/chart-live-moves.md +52 -52
  226. package/lib/motion/shotcraft/upstream/references/shots/data/gauge-readout-moves.md +45 -45
  227. package/lib/motion/shotcraft/upstream/references/shots/data/scroll-brake-moves.md +46 -46
  228. package/lib/motion/shotcraft/upstream/references/shots/data/timeline-travel.md +44 -44
  229. package/lib/motion/shotcraft/upstream/references/shots/effects/assemble-then-type-flyin.md +63 -63
  230. package/lib/motion/shotcraft/upstream/references/shots/effects/aurora-bloom-bg-flip.md +54 -54
  231. package/lib/motion/shotcraft/upstream/references/shots/effects/brand-frame-snap.md +58 -58
  232. package/lib/motion/shotcraft/upstream/references/shots/effects/fui-hud-moves.md +35 -35
  233. package/lib/motion/shotcraft/upstream/references/shots/effects/glow-flyline-moves.md +53 -53
  234. package/lib/motion/shotcraft/upstream/references/shots/effects/icon-performance-moves.md +42 -42
  235. package/lib/motion/shotcraft/upstream/references/shots/effects/impact-feedback.md +50 -50
  236. package/lib/motion/shotcraft/upstream/references/shots/effects/light-play-moves.md +46 -46
  237. package/lib/motion/shotcraft/upstream/references/shots/effects/radial-ripple-phone-chips.md +56 -56
  238. package/lib/motion/shotcraft/upstream/references/shots/effects/riso-print-hits.md +49 -49
  239. package/lib/motion/shotcraft/upstream/references/shots/effects/scan-bracket-sweep.md +50 -50
  240. package/lib/motion/shotcraft/upstream/references/shots/effects/scanline-annotate-focus.md +53 -53
  241. package/lib/motion/shotcraft/upstream/references/shots/effects/scanline-assemble-flyin.md +53 -53
  242. package/lib/motion/shotcraft/upstream/references/shots/effects/slam-entrance-moves.md +55 -55
  243. package/lib/motion/shotcraft/upstream/references/shots/effects/spotlight-sweep-moves.md +52 -52
  244. package/lib/motion/shotcraft/upstream/references/shots/interaction/autolayout-gap-dial.md +60 -60
  245. package/lib/motion/shotcraft/upstream/references/shots/interaction/canvas-materialize-moves.md +57 -57
  246. package/lib/motion/shotcraft/upstream/references/shots/interaction/chip-grid-single-select-blackout.md +51 -51
  247. package/lib/motion/shotcraft/upstream/references/shots/interaction/collab-cursor-moves.md +41 -41
  248. package/lib/motion/shotcraft/upstream/references/shots/interaction/glass-pill-dictation-typing.md +53 -53
  249. package/lib/motion/shotcraft/upstream/references/shots/interaction/hashtag-to-pill-materialize.md +60 -60
  250. package/lib/motion/shotcraft/upstream/references/shots/interaction/picker-carousel-feature-cycle.md +55 -55
  251. package/lib/motion/shotcraft/upstream/references/shots/interaction/segmented-thumb-hero.md +57 -57
  252. package/lib/motion/shotcraft/upstream/references/shots/interaction/theme-switch-moves.md +47 -47
  253. package/lib/motion/shotcraft/upstream/references/shots/interaction/type-and-filter.md +37 -37
  254. package/lib/motion/shotcraft/upstream/references/shots/interaction/voice-waveform-live.md +54 -54
  255. package/lib/motion/shotcraft/upstream/references/shots/opening/brand-ink-open.md +36 -36
  256. package/lib/motion/shotcraft/upstream/references/shots/opening/crane-rise-reveal.md +56 -56
  257. package/lib/motion/shotcraft/upstream/references/shots/opening/dataviz-landscape-open.md +56 -56
  258. package/lib/motion/shotcraft/upstream/references/shots/opening/fracture.md +40 -40
  259. package/lib/motion/shotcraft/upstream/references/shots/opening/icon-field-colorize.md +60 -60
  260. package/lib/motion/shotcraft/upstream/references/shots/opening/letterspace-materialize.md +57 -57
  261. package/lib/motion/shotcraft/upstream/references/shots/opening/magician-card-flourish.md +73 -73
  262. package/lib/motion/shotcraft/upstream/references/shots/opening/orbit-ring-title-open.md +87 -87
  263. package/lib/motion/shotcraft/upstream/references/shots/opening/spotlight-hero-card.md +55 -55
  264. package/lib/motion/shotcraft/upstream/references/shots/opening/stroke-segment-build.md +50 -50
  265. package/lib/motion/shotcraft/upstream/references/shots/opening/text-as-mask.md +59 -59
  266. package/lib/motion/shotcraft/upstream/references/shots/outro/grain-dissolve.md +38 -38
  267. package/lib/motion/shotcraft/upstream/references/shots/outro/logo-shrink-wordmark-lockup.md +38 -38
  268. package/lib/motion/shotcraft/upstream/references/shots/outro/neon-triple-marquee.md +59 -59
  269. package/lib/motion/shotcraft/upstream/references/shots/outro/outro-group-photo-launch.md +39 -39
  270. package/lib/motion/shotcraft/upstream/references/shots/outro/ui-strip-away-outro.md +61 -61
  271. package/lib/motion/shotcraft/upstream/references/shots/outro/ui-to-brand-morph.md +52 -52
  272. package/lib/motion/shotcraft/upstream/references/shots/rhythm/beat-cut-moves.md +50 -50
  273. package/lib/motion/shotcraft/upstream/references/shots/rhythm/beat-step-list-theme-cycle.md +66 -66
  274. package/lib/motion/shotcraft/upstream/references/shots/rhythm/panel-grid-moves.md +43 -43
  275. package/lib/motion/shotcraft/upstream/references/shots/rhythm/quad-split-parallel-scenes.md +38 -38
  276. package/lib/motion/shotcraft/upstream/references/shots/rhythm/rhythm-interrupt-moves.md +38 -38
  277. package/lib/motion/shotcraft/upstream/references/shots/rhythm/sakuga-timing-shift.md +56 -56
  278. package/lib/motion/shotcraft/upstream/references/shots/rhythm/speed-ramp-freeze.md +44 -44
  279. package/lib/motion/shotcraft/upstream/references/shots/rhythm/trailer-grammar-moves.md +38 -38
  280. package/lib/motion/shotcraft/upstream/references/shots/transition/bottom-push-stack-wipe.md +63 -63
  281. package/lib/motion/shotcraft/upstream/references/shots/transition/card-flip-reveal.md +57 -57
  282. package/lib/motion/shotcraft/upstream/references/shots/transition/card-flock-tumble.md +63 -63
  283. package/lib/motion/shotcraft/upstream/references/shots/transition/circle-match-iris.md +58 -58
  284. package/lib/motion/shotcraft/upstream/references/shots/transition/gradient-transition.md +45 -45
  285. package/lib/motion/shotcraft/upstream/references/shots/transition/line-carry-transition.md +55 -55
  286. package/lib/motion/shotcraft/upstream/references/shots/transition/mosaic-reframe.md +49 -49
  287. package/lib/motion/shotcraft/upstream/references/shots/transition/page-turn-transitions.md +42 -42
  288. package/lib/motion/shotcraft/upstream/references/shots/transition/print-texture-transitions.md +42 -42
  289. package/lib/motion/shotcraft/upstream/references/shots/transition/shot-transitions.md +45 -45
  290. package/lib/motion/shotcraft/upstream/references/shots/transition/tear-streak-transitions.md +48 -48
  291. package/lib/motion/shotcraft/upstream/references/shots/transition/transition-hidden-cut.md +55 -55
  292. package/lib/motion/shotcraft/upstream/references/shots/transition/transition-travel.md +43 -43
  293. package/lib/motion/shotcraft/upstream/references/shots/transition/white-flash-logo-simplify-cut.md +41 -41
  294. package/lib/motion/shotcraft/upstream/references/shots/transition/wipe-transitions.md +42 -42
  295. package/lib/motion/shotcraft/upstream/references/shots/typography/blur-slide.md +59 -59
  296. package/lib/motion/shotcraft/upstream/references/shots/typography/brace-expand.md +55 -55
  297. package/lib/motion/shotcraft/upstream/references/shots/typography/countdown-arc-scatter.md +65 -65
  298. package/lib/motion/shotcraft/upstream/references/shots/typography/document-typewriter-reveal.md +42 -42
  299. package/lib/motion/shotcraft/upstream/references/shots/typography/flying-words.md +64 -64
  300. package/lib/motion/shotcraft/upstream/references/shots/typography/glitch-cycle.md +64 -64
  301. package/lib/motion/shotcraft/upstream/references/shots/typography/gradient-word-sweep.md +54 -54
  302. package/lib/motion/shotcraft/upstream/references/shots/typography/lead-word-zoom-assemble.md +91 -91
  303. package/lib/motion/shotcraft/upstream/references/shots/typography/marker-underline-title.md +51 -51
  304. package/lib/motion/shotcraft/upstream/references/shots/typography/outline-word-fill.md +66 -66
  305. package/lib/motion/shotcraft/upstream/references/shots/typography/paper-title-card.md +38 -38
  306. package/lib/motion/shotcraft/upstream/references/shots/typography/pill-chip-slot-cycle-handled.md +66 -66
  307. package/lib/motion/shotcraft/upstream/references/shots/typography/pill-slot-cycle.md +58 -58
  308. package/lib/motion/shotcraft/upstream/references/shots/typography/text-column-converge.md +61 -61
  309. package/lib/motion/shotcraft/upstream/references/shots/typography/title-demote-to-label.md +64 -64
  310. package/lib/motion/shotcraft/upstream/references/shots/typography/type-assembly-moves.md +45 -45
  311. package/lib/motion/shotcraft/upstream/references/shots/typography/type-entrance-moves.md +41 -41
  312. package/lib/motion/shotcraft/upstream/references/shots/typography/type-rhythm-sync.md +51 -51
  313. package/lib/motion/shotcraft/upstream/references/shots/typography/typewriter-moves.md +42 -42
  314. package/lib/motion/shotcraft/upstream/references/shots/typography/vertical-word-roll-blur-cycle.md +63 -63
  315. package/lib/motion/shotcraft/upstream/references/shots/typography/word-relay-filmstrip.md +57 -57
  316. package/lib/motion/shotcraft/upstream/references/shots/typography/word-relay-geometry.md +75 -75
  317. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/avatar-bracket-carousel.md +59 -59
  318. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/bezier-source-converge-merge.md +67 -67
  319. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/card-stack.md +60 -60
  320. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/carousel-3d.md +66 -66
  321. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/cloner-depth-echo.md +40 -40
  322. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/deck-deal-flyin.md +45 -45
  323. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/doc-park-left-pill-deal.md +62 -62
  324. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/draw-svg-trace.md +55 -55
  325. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/element-body-moves.md +37 -37
  326. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/integration-hub-map.md +55 -55
  327. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/list-reveal.md +50 -50
  328. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/list-stack-press.md +43 -43
  329. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/neon-frame-forerun.md +55 -55
  330. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/neon-frame-orbit-drop.md +51 -51
  331. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/page-waterfall-wall.md +51 -51
  332. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/product-card-progressive-assemble.md +56 -56
  333. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/radial-wave.md +49 -49
  334. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/research-card-stack-scroll.md +57 -57
  335. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/row-embed.md +36 -36
  336. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/value-stagger-gradient.md +64 -64
  337. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/wall-reveal-moves.md +47 -47
  338. package/lib/motion/shotcraft/upstream/references/sound-design.md +170 -170
  339. package/lib/motion/shotcraft/upstream/references/workbench.md +157 -157
  340. package/lib/motion/shotcraft/upstream/template/TEMPLATE.md +103 -103
  341. package/lib/motion/shotcraft/upstream/template/THEMES.md +44 -44
  342. package/lib/motion/shotcraft/upstream/template/package.json +20 -20
  343. package/lib/motion/shotcraft/upstream/template/remotion.config.ts +6 -6
  344. package/lib/motion/shotcraft/upstream/template/src/Root.tsx +17 -17
  345. package/lib/motion/shotcraft/upstream/template/src/aifl/Caption.tsx +65 -65
  346. package/lib/motion/shotcraft/upstream/template/src/aifl/DigitRoll.tsx +48 -48
  347. package/lib/motion/shotcraft/upstream/template/src/aifl/FlashCut.tsx +24 -24
  348. package/lib/motion/shotcraft/upstream/template/src/aifl/Main.tsx +192 -192
  349. package/lib/motion/shotcraft/upstream/template/src/aifl/PaperTitleCard.tsx +111 -111
  350. package/lib/motion/shotcraft/upstream/template/src/aifl/live/PageCam.tsx +150 -150
  351. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneDetail.tsx +158 -158
  352. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneFlyIn.tsx +468 -468
  353. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneOpen.tsx +552 -552
  354. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneOutroLive.tsx +411 -411
  355. package/lib/motion/shotcraft/upstream/template/src/aifl/live/ScenePapers.tsx +200 -200
  356. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneWbr.tsx +324 -324
  357. package/lib/motion/shotcraft/upstream/template/src/aifl/live-layout.json +388 -388
  358. package/lib/motion/shotcraft/upstream/template/src/index.ts +4 -4
  359. package/lib/motion/shotcraft/upstream/template/src/themes/ThemedFilm.tsx +7 -7
  360. package/lib/motion/shotcraft/upstream/template/src/themes/manifest.tsx +68 -68
  361. package/lib/motion/shotcraft/upstream/template/src/themes/palette-assets.json +1 -1
  362. package/lib/motion/shotcraft/upstream/template/src/themes/palette-assets.ts +24 -24
  363. package/lib/motion/shotcraft/upstream/template/src/themes/palettes.json +74 -74
  364. package/lib/motion/shotcraft/upstream/template/src/themes/visual-theme.tsx +91 -91
  365. package/lib/motion/shotcraft/upstream/template/src/workbench.ts +213 -213
  366. package/lib/motion/shotcraft/upstream/template/tsconfig.json +15 -15
  367. package/lib/motion/style-frames.js +306 -306
  368. package/lib/motion/sync.js +214 -214
  369. package/lib/motion-library.js +1 -1
  370. package/lib/motion-project.js +105 -105
  371. package/lib/motion-render-worker.js +174 -174
  372. package/lib/routing/router.js +222 -222
  373. package/lib/routing/vendor/README.md +96 -96
  374. package/lib/routing/vendor/libavoid-routing.js +753 -753
  375. package/lib/routing/vendor/libavoid.min.js +59 -59
  376. package/lib/svg-export.js +1344 -0
  377. package/lib/video-trace-pool.js +128 -128
  378. package/package.json +3 -2
  379. package/LICENSE +0 -4175
@@ -1,305 +1,305 @@
1
- // autolayout-gap-dial —— framer-ai 4.5–5.5s
2
- // 间距拨盘驱动布局:一个 gap 数值同帧驱动整排导航块的位置、测量线、徽章与读数。
3
- //
4
- // 第二轮重设计(石墨暗场 · 设计工具检查器海报):
5
- // - look = graphite(近单色暗场)。设计工具的"选择白 + 测量金"两色语义:框选描边/手柄用近白,
6
- // 间距测量线/徽章/拨盘指针用 accent2 香槟金——画面里只有"被拨动的那个数"是有颜色的。
7
- // - 主角是"数":顶部 196px 超大 tabular 读数(GAP 眉题 + 数值 + px 单位),下面一把 760px 拨盘刻度尺,
8
- // 刻度随 gap 横向滚过中心金针;拨动时读数由白转金、松手后回白——数值就是缰绳。
9
- // - 布局主体:一排 120px 高的导航块(video-shotcraft 站点的顶部导航),占画宽 ~64–86%;激活项白底黑字,
10
- // 其余是带色相深灰面板 + 发丝线 + 顶部内高光;块按自身速度做横向运动模糊(外侧块位移最大,拖影最长)。
11
- // - 节奏「预备—拉开—屏息—回弹」:开场先把 gap 往里收一点(anticip 预备,12→6),再 swift 不对称曲线
12
- // 拉到 104;hold 一拍屏息;松手后欠阻尼弹簧过冲到比起点更紧再回稳(过冲段 ×0.45 压缩,gap 永不为负)。
13
- //
14
- // 时间表(30fps,共 150f):
15
- // 0–20 入场:舞台光 + 点阵画布;导航块错峰上浮(父先到)、框选描边从外侧收拢、8 手柄 2f 错峰弹出
16
- // 6–22 读数入场:眉题字距收拢、数值从线下升起、刻度尺淡入
17
- // 22–32 预备:gap 12→6(anticip,观众先看到"往回收"再看到"冲出去")
18
- // 32–66 主动作:gap 6→104(34f swift),读数逐 2 跳、转金;测量线与徽章实时拉长
19
- // 66–86 屏息 hold 20f:相机极缓推近(总 +2.5%),金色读数停在 104
20
- // 86–118 回弹:spring(damping 9, stiffness 80) 104→~7→12,~118f 落定,读数回白
21
- // 118–150 落定 hold:完整海报(读数 12 + 收紧的导航条),相机继续极缓推进
22
- import React from 'react';
23
- import { AbsoluteFill, useCurrentFrame, spring } from 'remotion';
24
- import { EASE, FONT, ramp, softShadow } from '../../_fixtures/Polish';
25
- import { LOOKS, Stage, alpha, springAt, type } from '../../_fixtures/Look';
26
-
27
- export const AUTOLAYOUT_GAP_DIAL_DURATION = 150;
28
-
29
- const L = LOOKS.graphite;
30
- const FPS = 30;
31
- const SEL = 'rgba(244,244,242,0.92)'; // 选择白:框选描边 / 手柄
32
- const GOLD = L.accent2; // 测量金:间距线 / 徽章 / 指针 / 拨动中的读数
33
-
34
- const LABELS = ['Recipes', 'Gallery', 'Workbench', 'Showcase', 'Install']; // video-shotcraft 站点导航
35
- const BLOCK_WIDTHS = [252, 206, 278, 268, 220]; // 不等宽才像真导航
36
- const BLOCK_H = 120;
37
- const ROW_Y = 684; // 行中心
38
- const G_REST = 12;
39
- const G_PRE = 6; // 预备回收值
40
- const G_MAX = 104;
41
-
42
- const PRE_START = 22;
43
- const PRE_END = 32;
44
- const GROW_END = 66;
45
- const HOLD_END = 86;
46
- // damping 9 的原始过冲 ≈18%×106px 会把 gap 拉成负数;过冲段 ×0.45 → 最紧约 6px,仍"比起点更紧再回稳"
47
- const OVERSHOOT_K = 0.45;
48
-
49
- // 同一个 gap 参数派生全部几何(块位置、测量线、徽章、读数、刻度尺)
50
- const gapAt = (f: number) => {
51
- if (f < PRE_END) return G_REST + (G_PRE - G_REST) * ramp(f, PRE_START, PRE_END - PRE_START, EASE.swift);
52
- if (f < HOLD_END) return G_PRE + (G_MAX - G_PRE) * ramp(f, PRE_END, GROW_END - PRE_END, EASE.swift);
53
- const s = spring({ frame: f - HOLD_END, fps: FPS, config: { damping: 9, stiffness: 80, mass: 1.1 } });
54
- const s2 = s > 1 ? 1 + (s - 1) * OVERSHOOT_K : s;
55
- return G_MAX + (G_REST - G_MAX) * s2;
56
- };
57
-
58
- // 两个 hex 颜色按 t 混合
59
- const mixHex = (a: string, b: string, t: number) => {
60
- const pa = a.match(/[0-9a-f]{2}/gi)!.map((h) => parseInt(h, 16));
61
- const pb = b.match(/[0-9a-f]{2}/gi)!.map((h) => parseInt(h, 16));
62
- const k = Math.max(0, Math.min(1, t));
63
- return `rgb(${pa.slice(0, 3).map((x, i) => Math.round(x + (pb[i] - x) * k)).join(',')})`;
64
- };
65
-
66
- const rowLayout = (gap: number) => {
67
- const total = BLOCK_WIDTHS.reduce((a, b) => a + b, 0) + gap * (BLOCK_WIDTHS.length - 1);
68
- const startX = (1920 - total) / 2;
69
- const xs: number[] = [];
70
- let acc = startX;
71
- for (const w of BLOCK_WIDTHS) {
72
- xs.push(acc);
73
- acc += w + gap;
74
- }
75
- return { total, startX, xs };
76
- };
77
-
78
- const IconAutoLayout: React.FC<{ c: string; size?: number }> = ({ c, size = 22 }) => (
79
- <svg width={size} height={size} viewBox="0 0 14 14" fill="none">
80
- <rect x={1} y={3} width={3.4} height={8} rx={1} fill={c} />
81
- <rect x={5.3} y={3} width={3.4} height={8} rx={1} fill={c} opacity={0.7} />
82
- <rect x={9.6} y={3} width={3.4} height={8} rx={1} fill={c} opacity={0.45} />
83
- </svg>
84
- );
85
-
86
- // 拨盘刻度尺:每 1 单位 = UNIT px,中心金针读当前 gap
87
- const RULER_W = 760;
88
- const UNIT = 6.5;
89
- const Ruler: React.FC<{ gap: number; op: number; hot: number }> = ({ gap, op, hot }) => {
90
- const ticks: React.ReactNode[] = [];
91
- for (let u = -60; u <= 180; u += 2) {
92
- const x = RULER_W / 2 + (u - gap) * UNIT;
93
- if (x < -10 || x > RULER_W + 10) continue;
94
- const major = u % 10 === 0;
95
- const edge = Math.max(0, Math.min(1, Math.min(x, RULER_W - x) / 150)); // 两端淡出
96
- const near = Math.abs(x - RULER_W / 2);
97
- ticks.push(
98
- <div key={u} style={{
99
- position: 'absolute', left: x - 1, bottom: 0, width: 2, height: major ? 30 : 14, borderRadius: 1,
100
- background: u < 0 ? alpha(L.ink, 0.08) : major ? alpha(L.ink, 0.5) : alpha(L.ink, 0.22), opacity: edge,
101
- }} />,
102
- );
103
- if (major && u >= 0) {
104
- ticks.push(
105
- <div key={`l${u}`} style={{
106
- position: 'absolute', left: x, bottom: 40, transform: 'translateX(-50%)',
107
- ...type(22, 500, { mono: true }), color: L.ink3,
108
- opacity: edge * Math.min(1, Math.max(0, (near - 18) / 22)), // 靠近指针的数字让位
109
- }}>{u}</div>,
110
- );
111
- }
112
- }
113
- return (
114
- <div style={{ position: 'absolute', left: 960 - RULER_W / 2, top: 414, width: RULER_W, height: 76, opacity: op }}>
115
- <div style={{ position: 'absolute', inset: 0, overflow: 'hidden' }}>{ticks}</div>
116
- {/* 基线 */}
117
- <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, height: 1, background: `linear-gradient(90deg, transparent, ${alpha(L.ink, 0.18)} 20%, ${alpha(L.ink, 0.18)} 80%, transparent)` }} />
118
- {/* 金针:拨动时泛光 */}
119
- <div style={{
120
- position: 'absolute', left: RULER_W / 2 - 1.5, bottom: -6, width: 3, height: 50, borderRadius: 2, background: GOLD,
121
- boxShadow: `0 0 ${8 + hot * 14}px ${alpha(GOLD, 0.35 + hot * 0.4)}`,
122
- }} />
123
- <div style={{
124
- position: 'absolute', left: RULER_W / 2 - 8, bottom: 44, width: 0, height: 0,
125
- borderLeft: '8px solid transparent', borderRight: '8px solid transparent', borderTop: `10px solid ${GOLD}`,
126
- }} />
127
- </div>
128
- );
129
- };
130
-
131
- export const AutolayoutGapDial: React.FC = () => {
132
- const frame = useCurrentFrame();
133
-
134
- const gap = gapAt(frame);
135
- const gapShown = Math.max(0, Math.round(gap / 2) * 2); // 逐格跳数(步进 2 = 拨盘咔哒的颗粒)
136
- const v = gapAt(frame + 0.5) - gapAt(frame - 0.5); // gap 速度(px/帧)
137
- const moving = Math.min(1, Math.abs(v) / 1.2);
138
- // 拨动热度:读数白→金,带 ~6f 余温(松手回稳后慢慢褪回白)
139
- let hot = 0;
140
- for (let k = 0; k <= 6; k++) hot = Math.max(hot, Math.min(1, Math.abs(gapAt(frame - k + 0.5) - gapAt(frame - k - 0.5)) / 1.5) * (1 - k / 7));
141
- // 跳数脉冲:相位由数值本身驱动(每跨一个步进格脉冲一次)× 速度门限
142
- const tickPulse = 1 + 0.06 * Math.abs(Math.sin((Math.PI * gap) / 2)) * moving;
143
-
144
- const { total, startX, xs } = rowLayout(gap);
145
-
146
- // 相机:整段极缓推近(smooth,起止无速度突变)
147
- const cam = 1 + 0.025 * ramp(frame, 0, AUTOLAYOUT_GAP_DIAL_DURATION, EASE.smooth);
148
-
149
- // 框选描边:spring 从外侧 26px 收拢
150
- const selIn = springAt(frame, 4, { damping: 16, stiffness: 140 });
151
- const pad = 30;
152
- const grow = (1 - selIn) * 26;
153
- const selX = startX - pad - grow;
154
- const selW = total + pad * 2 + grow * 2;
155
- const selY = ROW_Y - BLOCK_H / 2 - pad - grow;
156
- const selH = BLOCK_H + pad * 2 + grow * 2;
157
-
158
- const measOp = ramp(frame, 14, 10, EASE.out);
159
- const eyebrow = ramp(frame, 4, 18, EASE.snappy);
160
- const numIn = ramp(frame, 8, 18, EASE.snappy);
161
- const rulerIn = ramp(frame, 12, 16, EASE.out);
162
-
163
- // 读数颜色:白 ↔ 金
164
- const numColor = mixHex(L.ink, GOLD, hot);
165
-
166
- return (
167
- <AbsoluteFill style={{ background: L.bg[1], overflow: 'hidden', fontFamily: FONT.sans }}>
168
- <Stage look={L} keyLight={{ x: 0.5, y: 0.0 }} fill={{ x: 0.5, y: 1.05 }} horizon={0.62} breathe={0.4}>
169
- {/* 画布点阵:围绕导航条清楚、四周隐去 */}
170
- <AbsoluteFill style={{
171
- backgroundImage: `radial-gradient(${alpha(L.ink, 0.13)} 1.4px, transparent 1.7px)`,
172
- backgroundSize: '36px 36px', backgroundPosition: '6px 16px',
173
- WebkitMaskImage: 'radial-gradient(ellipse 52% 40% at 50% 62%, #000 20%, transparent 100%)',
174
- maskImage: 'radial-gradient(ellipse 52% 40% at 50% 62%, #000 20%, transparent 100%)',
175
- }} />
176
- {/* 导航条落脚的光池:条子"站"在画布上 */}
177
- <div style={{
178
- position: 'absolute', left: 260, right: 260, top: ROW_Y + 40, height: 200,
179
- background: `radial-gradient(ellipse 50% 50% at 50% 30%, ${alpha(L.light, 0.1)} 0%, transparent 70%)`,
180
- }} />
181
- </Stage>
182
-
183
- <AbsoluteFill style={{ transform: `scale(${cam})`, transformOrigin: '50% 52%' }}>
184
- {/* ── 读数:眉题 + 超大数值 + 单位 ── */}
185
- <div style={{
186
- position: 'absolute', left: 0, right: 0, top: 150, display: 'flex', justifyContent: 'center', alignItems: 'center', gap: 16,
187
- opacity: eyebrow, letterSpacing: `${(0.28 + (1 - eyebrow) * 0.4).toFixed(3)}em`,
188
- ...type(22, 600, { caps: true }), color: L.ink2,
189
- }}>
190
- <IconAutoLayout c={L.ink2} />
191
- <span style={{ letterSpacing: 'inherit' }}>Auto layout · Gap</span>
192
- </div>
193
- <div style={{
194
- position: 'absolute', left: 0, right: 0, top: 186, height: 220, overflow: 'hidden',
195
- display: 'flex', justifyContent: 'center', alignItems: 'flex-end',
196
- }}>
197
- <div style={{
198
- display: 'flex', alignItems: 'baseline', gap: 18,
199
- transform: `translateY(${((1 - numIn) * 105).toFixed(2)}%)`,
200
- }}>
201
- <span style={{
202
- ...type(196, 300), letterSpacing: '-0.05em', color: numColor, display: 'inline-block',
203
- minWidth: '1.9em', textAlign: 'right', transform: `scale(${tickPulse})`, transformOrigin: '100% 80%',
204
- textShadow: hot > 0.05 ? `0 0 ${(40 * hot).toFixed(1)}px ${alpha(GOLD, 0.35 * hot)}` : undefined,
205
- }}>{gapShown}</span>
206
- <span style={{ ...type(60, 500), color: L.ink3, width: '1.9em' }}>px</span>
207
- </div>
208
- </div>
209
- <Ruler gap={gap} op={rulerIn} hot={hot} />
210
-
211
- {/* ── 导航块(video-shotcraft 站点顶部导航) ── */}
212
- {BLOCK_WIDTHS.map((w, i) => {
213
- const inP = ramp(frame, 1 + i * 2, 16, EASE.snappy);
214
- const active = i === 0;
215
- const vx = (i - 2) * v; // 块速度 = (i−2)·dgap/dt:外侧块位移最大
216
- const blur = Math.min(9, Math.abs(vx) * 0.5);
217
- const fid = `nb${i}`;
218
- const dy = (1 - inP) * 34;
219
- return (
220
- <div key={i} style={{
221
- position: 'absolute', left: xs[i], top: ROW_Y - BLOCK_H / 2, width: w, height: BLOCK_H,
222
- opacity: inP, transform: `translateY(${dy.toFixed(2)}px)`,
223
- }}>
224
- {blur > 0.5 && (
225
- <svg width={0} height={0} style={{ position: 'absolute' }} aria-hidden>
226
- <filter id={fid} x="-20%" y="-10%" width="140%" height="120%" colorInterpolationFilters="sRGB">
227
- <feGaussianBlur stdDeviation={`${blur.toFixed(2)} 0`} />
228
- </filter>
229
- </svg>
230
- )}
231
- <div style={{
232
- position: 'absolute', inset: 0, boxSizing: 'border-box', borderRadius: 24,
233
- background: active ? 'linear-gradient(180deg, #fbfbf8, #e6e6e1)' : 'linear-gradient(180deg, #212327, #17181b)',
234
- border: active ? '1px solid rgba(255,255,255,0.7)' : `1px solid ${alpha('#ffffff', 0.09)}`,
235
- boxShadow: active
236
- ? `inset 0 1px 0 rgba(255,255,255,1), inset 0 -2px 0 rgba(0,0,0,0.08), ${softShadow(18, { color: '#000000', strength: 2.4 })}`
237
- : `inset 0 1px 0 ${alpha('#ffffff', 0.08)}, ${softShadow(12, { color: '#000000', strength: 2.4 })}`,
238
- display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 14,
239
- filter: blur > 0.5 ? `url(#${fid})` : undefined,
240
- }}>
241
- {active && <div style={{ width: 12, height: 12, borderRadius: 99, background: '#111214' }} />}
242
- <span style={{ ...type(36, active ? 650 : 520), color: active ? '#0d0e10' : alpha(L.ink, 0.86) }}>{LABELS[i]}</span>
243
- </div>
244
- </div>
245
- );
246
- })}
247
-
248
- {/* ── 框选描边 + 8 手柄 + 图层名 ── */}
249
- <div style={{
250
- position: 'absolute', left: selX, top: selY, width: selW, height: selH, boxSizing: 'border-box',
251
- border: `2px solid ${SEL}`, borderRadius: 6, opacity: Math.min(1, selIn * 1.4),
252
- }}>
253
- <div style={{
254
- position: 'absolute', left: -2, top: -50, display: 'flex', alignItems: 'center', gap: 10,
255
- ...type(26, 560), color: SEL, whiteSpace: 'nowrap',
256
- }}>
257
- <IconAutoLayout c={SEL} size={20} />
258
- Nav links
259
- <span style={{ ...type(22, 500, { mono: true }), color: L.ink3, marginLeft: 8 }}>
260
- {Math.round(total)} × {BLOCK_H}
261
- </span>
262
- </div>
263
- {[[0, 0], [0.5, 0], [1, 0], [0, 0.5], [1, 0.5], [0, 1], [0.5, 1], [1, 1]].map(([hx, hy], i) => {
264
- const hp = springAt(frame, 7 + i * 1.2, { damping: 13, stiffness: 240 });
265
- return (
266
- <div key={i} style={{
267
- position: 'absolute', left: `${hx * 100}%`, top: `${hy * 100}%`, width: 16, height: 16, marginLeft: -8, marginTop: -8,
268
- background: L.bg[1], border: `2px solid ${SEL}`, borderRadius: 3, boxSizing: 'border-box', transform: `scale(${hp})`,
269
- }} />
270
- );
271
- })}
272
- </div>
273
-
274
- {/* ── 间距标注:延长线 ×2 + 测量线 + 徽章(全部由 gap 实时重算) ── */}
275
- {xs.slice(0, -1).map((x, i) => {
276
- const gx = x + BLOCK_WIDTHS[i];
277
- const cy = ROW_Y + BLOCK_H / 2 + 74;
278
- const extTop = ROW_Y + BLOCK_H / 2 + 34;
279
- const span = Math.max(0, gap);
280
- const bp = ramp(frame, 14 + i * 2, 12, EASE.snappy);
281
- return (
282
- <div key={i} style={{ position: 'absolute', left: 0, top: 0, opacity: measOp }}>
283
- {[gx, gx + gap].map((lx, k) => (
284
- <div key={k} style={{
285
- position: 'absolute', left: lx - 0.75, top: extTop, width: 1.5, height: 58,
286
- backgroundImage: `linear-gradient(${GOLD} 55%, transparent 55%)`, backgroundSize: '1.5px 7px', opacity: 0.7,
287
- }} />
288
- ))}
289
- <div style={{ position: 'absolute', left: gx, top: cy - 1, width: span, height: 2, background: GOLD, boxShadow: `0 0 10px ${alpha(GOLD, 0.4)}` }} />
290
- <div style={{ position: 'absolute', left: gx - 1, top: cy - 8, width: 2, height: 16, background: GOLD }} />
291
- <div style={{ position: 'absolute', left: gx + gap - 1, top: cy - 8, width: 2, height: 16, background: GOLD }} />
292
- <div style={{
293
- position: 'absolute', left: gx + gap / 2, top: cy + 20,
294
- transform: `translateX(-50%) translateY(${((1 - bp) * 10).toFixed(1)}px) scale(${(tickPulse * (0.7 + 0.3 * bp)).toFixed(3)})`,
295
- opacity: bp, minWidth: 64, textAlign: 'center', boxSizing: 'border-box', padding: '6px 14px', borderRadius: 10,
296
- background: GOLD, color: L.onAccent, ...type(28, 700), lineHeight: 1.1,
297
- boxShadow: `inset 0 1px 0 rgba(255,255,255,0.45), 0 6px 18px -6px ${alpha(GOLD, 0.6)}`,
298
- }}>{gapShown}</div>
299
- </div>
300
- );
301
- })}
302
- </AbsoluteFill>
303
- </AbsoluteFill>
304
- );
305
- };
1
+ // autolayout-gap-dial —— framer-ai 4.5–5.5s
2
+ // 间距拨盘驱动布局:一个 gap 数值同帧驱动整排导航块的位置、测量线、徽章与读数。
3
+ //
4
+ // 第二轮重设计(石墨暗场 · 设计工具检查器海报):
5
+ // - look = graphite(近单色暗场)。设计工具的"选择白 + 测量金"两色语义:框选描边/手柄用近白,
6
+ // 间距测量线/徽章/拨盘指针用 accent2 香槟金——画面里只有"被拨动的那个数"是有颜色的。
7
+ // - 主角是"数":顶部 196px 超大 tabular 读数(GAP 眉题 + 数值 + px 单位),下面一把 760px 拨盘刻度尺,
8
+ // 刻度随 gap 横向滚过中心金针;拨动时读数由白转金、松手后回白——数值就是缰绳。
9
+ // - 布局主体:一排 120px 高的导航块(video-shotcraft 站点的顶部导航),占画宽 ~64–86%;激活项白底黑字,
10
+ // 其余是带色相深灰面板 + 发丝线 + 顶部内高光;块按自身速度做横向运动模糊(外侧块位移最大,拖影最长)。
11
+ // - 节奏「预备—拉开—屏息—回弹」:开场先把 gap 往里收一点(anticip 预备,12→6),再 swift 不对称曲线
12
+ // 拉到 104;hold 一拍屏息;松手后欠阻尼弹簧过冲到比起点更紧再回稳(过冲段 ×0.45 压缩,gap 永不为负)。
13
+ //
14
+ // 时间表(30fps,共 150f):
15
+ // 0–20 入场:舞台光 + 点阵画布;导航块错峰上浮(父先到)、框选描边从外侧收拢、8 手柄 2f 错峰弹出
16
+ // 6–22 读数入场:眉题字距收拢、数值从线下升起、刻度尺淡入
17
+ // 22–32 预备:gap 12→6(anticip,观众先看到"往回收"再看到"冲出去")
18
+ // 32–66 主动作:gap 6→104(34f swift),读数逐 2 跳、转金;测量线与徽章实时拉长
19
+ // 66–86 屏息 hold 20f:相机极缓推近(总 +2.5%),金色读数停在 104
20
+ // 86–118 回弹:spring(damping 9, stiffness 80) 104→~7→12,~118f 落定,读数回白
21
+ // 118–150 落定 hold:完整海报(读数 12 + 收紧的导航条),相机继续极缓推进
22
+ import React from 'react';
23
+ import { AbsoluteFill, useCurrentFrame, spring } from 'remotion';
24
+ import { EASE, FONT, ramp, softShadow } from '../../_fixtures/Polish';
25
+ import { LOOKS, Stage, alpha, springAt, type } from '../../_fixtures/Look';
26
+
27
+ export const AUTOLAYOUT_GAP_DIAL_DURATION = 150;
28
+
29
+ const L = LOOKS.graphite;
30
+ const FPS = 30;
31
+ const SEL = 'rgba(244,244,242,0.92)'; // 选择白:框选描边 / 手柄
32
+ const GOLD = L.accent2; // 测量金:间距线 / 徽章 / 指针 / 拨动中的读数
33
+
34
+ const LABELS = ['Recipes', 'Gallery', 'Workbench', 'Showcase', 'Install']; // video-shotcraft 站点导航
35
+ const BLOCK_WIDTHS = [252, 206, 278, 268, 220]; // 不等宽才像真导航
36
+ const BLOCK_H = 120;
37
+ const ROW_Y = 684; // 行中心
38
+ const G_REST = 12;
39
+ const G_PRE = 6; // 预备回收值
40
+ const G_MAX = 104;
41
+
42
+ const PRE_START = 22;
43
+ const PRE_END = 32;
44
+ const GROW_END = 66;
45
+ const HOLD_END = 86;
46
+ // damping 9 的原始过冲 ≈18%×106px 会把 gap 拉成负数;过冲段 ×0.45 → 最紧约 6px,仍"比起点更紧再回稳"
47
+ const OVERSHOOT_K = 0.45;
48
+
49
+ // 同一个 gap 参数派生全部几何(块位置、测量线、徽章、读数、刻度尺)
50
+ const gapAt = (f: number) => {
51
+ if (f < PRE_END) return G_REST + (G_PRE - G_REST) * ramp(f, PRE_START, PRE_END - PRE_START, EASE.swift);
52
+ if (f < HOLD_END) return G_PRE + (G_MAX - G_PRE) * ramp(f, PRE_END, GROW_END - PRE_END, EASE.swift);
53
+ const s = spring({ frame: f - HOLD_END, fps: FPS, config: { damping: 9, stiffness: 80, mass: 1.1 } });
54
+ const s2 = s > 1 ? 1 + (s - 1) * OVERSHOOT_K : s;
55
+ return G_MAX + (G_REST - G_MAX) * s2;
56
+ };
57
+
58
+ // 两个 hex 颜色按 t 混合
59
+ const mixHex = (a: string, b: string, t: number) => {
60
+ const pa = a.match(/[0-9a-f]{2}/gi)!.map((h) => parseInt(h, 16));
61
+ const pb = b.match(/[0-9a-f]{2}/gi)!.map((h) => parseInt(h, 16));
62
+ const k = Math.max(0, Math.min(1, t));
63
+ return `rgb(${pa.slice(0, 3).map((x, i) => Math.round(x + (pb[i] - x) * k)).join(',')})`;
64
+ };
65
+
66
+ const rowLayout = (gap: number) => {
67
+ const total = BLOCK_WIDTHS.reduce((a, b) => a + b, 0) + gap * (BLOCK_WIDTHS.length - 1);
68
+ const startX = (1920 - total) / 2;
69
+ const xs: number[] = [];
70
+ let acc = startX;
71
+ for (const w of BLOCK_WIDTHS) {
72
+ xs.push(acc);
73
+ acc += w + gap;
74
+ }
75
+ return { total, startX, xs };
76
+ };
77
+
78
+ const IconAutoLayout: React.FC<{ c: string; size?: number }> = ({ c, size = 22 }) => (
79
+ <svg width={size} height={size} viewBox="0 0 14 14" fill="none">
80
+ <rect x={1} y={3} width={3.4} height={8} rx={1} fill={c} />
81
+ <rect x={5.3} y={3} width={3.4} height={8} rx={1} fill={c} opacity={0.7} />
82
+ <rect x={9.6} y={3} width={3.4} height={8} rx={1} fill={c} opacity={0.45} />
83
+ </svg>
84
+ );
85
+
86
+ // 拨盘刻度尺:每 1 单位 = UNIT px,中心金针读当前 gap
87
+ const RULER_W = 760;
88
+ const UNIT = 6.5;
89
+ const Ruler: React.FC<{ gap: number; op: number; hot: number }> = ({ gap, op, hot }) => {
90
+ const ticks: React.ReactNode[] = [];
91
+ for (let u = -60; u <= 180; u += 2) {
92
+ const x = RULER_W / 2 + (u - gap) * UNIT;
93
+ if (x < -10 || x > RULER_W + 10) continue;
94
+ const major = u % 10 === 0;
95
+ const edge = Math.max(0, Math.min(1, Math.min(x, RULER_W - x) / 150)); // 两端淡出
96
+ const near = Math.abs(x - RULER_W / 2);
97
+ ticks.push(
98
+ <div key={u} style={{
99
+ position: 'absolute', left: x - 1, bottom: 0, width: 2, height: major ? 30 : 14, borderRadius: 1,
100
+ background: u < 0 ? alpha(L.ink, 0.08) : major ? alpha(L.ink, 0.5) : alpha(L.ink, 0.22), opacity: edge,
101
+ }} />,
102
+ );
103
+ if (major && u >= 0) {
104
+ ticks.push(
105
+ <div key={`l${u}`} style={{
106
+ position: 'absolute', left: x, bottom: 40, transform: 'translateX(-50%)',
107
+ ...type(22, 500, { mono: true }), color: L.ink3,
108
+ opacity: edge * Math.min(1, Math.max(0, (near - 18) / 22)), // 靠近指针的数字让位
109
+ }}>{u}</div>,
110
+ );
111
+ }
112
+ }
113
+ return (
114
+ <div style={{ position: 'absolute', left: 960 - RULER_W / 2, top: 414, width: RULER_W, height: 76, opacity: op }}>
115
+ <div style={{ position: 'absolute', inset: 0, overflow: 'hidden' }}>{ticks}</div>
116
+ {/* 基线 */}
117
+ <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, height: 1, background: `linear-gradient(90deg, transparent, ${alpha(L.ink, 0.18)} 20%, ${alpha(L.ink, 0.18)} 80%, transparent)` }} />
118
+ {/* 金针:拨动时泛光 */}
119
+ <div style={{
120
+ position: 'absolute', left: RULER_W / 2 - 1.5, bottom: -6, width: 3, height: 50, borderRadius: 2, background: GOLD,
121
+ boxShadow: `0 0 ${8 + hot * 14}px ${alpha(GOLD, 0.35 + hot * 0.4)}`,
122
+ }} />
123
+ <div style={{
124
+ position: 'absolute', left: RULER_W / 2 - 8, bottom: 44, width: 0, height: 0,
125
+ borderLeft: '8px solid transparent', borderRight: '8px solid transparent', borderTop: `10px solid ${GOLD}`,
126
+ }} />
127
+ </div>
128
+ );
129
+ };
130
+
131
+ export const AutolayoutGapDial: React.FC = () => {
132
+ const frame = useCurrentFrame();
133
+
134
+ const gap = gapAt(frame);
135
+ const gapShown = Math.max(0, Math.round(gap / 2) * 2); // 逐格跳数(步进 2 = 拨盘咔哒的颗粒)
136
+ const v = gapAt(frame + 0.5) - gapAt(frame - 0.5); // gap 速度(px/帧)
137
+ const moving = Math.min(1, Math.abs(v) / 1.2);
138
+ // 拨动热度:读数白→金,带 ~6f 余温(松手回稳后慢慢褪回白)
139
+ let hot = 0;
140
+ for (let k = 0; k <= 6; k++) hot = Math.max(hot, Math.min(1, Math.abs(gapAt(frame - k + 0.5) - gapAt(frame - k - 0.5)) / 1.5) * (1 - k / 7));
141
+ // 跳数脉冲:相位由数值本身驱动(每跨一个步进格脉冲一次)× 速度门限
142
+ const tickPulse = 1 + 0.06 * Math.abs(Math.sin((Math.PI * gap) / 2)) * moving;
143
+
144
+ const { total, startX, xs } = rowLayout(gap);
145
+
146
+ // 相机:整段极缓推近(smooth,起止无速度突变)
147
+ const cam = 1 + 0.025 * ramp(frame, 0, AUTOLAYOUT_GAP_DIAL_DURATION, EASE.smooth);
148
+
149
+ // 框选描边:spring 从外侧 26px 收拢
150
+ const selIn = springAt(frame, 4, { damping: 16, stiffness: 140 });
151
+ const pad = 30;
152
+ const grow = (1 - selIn) * 26;
153
+ const selX = startX - pad - grow;
154
+ const selW = total + pad * 2 + grow * 2;
155
+ const selY = ROW_Y - BLOCK_H / 2 - pad - grow;
156
+ const selH = BLOCK_H + pad * 2 + grow * 2;
157
+
158
+ const measOp = ramp(frame, 14, 10, EASE.out);
159
+ const eyebrow = ramp(frame, 4, 18, EASE.snappy);
160
+ const numIn = ramp(frame, 8, 18, EASE.snappy);
161
+ const rulerIn = ramp(frame, 12, 16, EASE.out);
162
+
163
+ // 读数颜色:白 ↔ 金
164
+ const numColor = mixHex(L.ink, GOLD, hot);
165
+
166
+ return (
167
+ <AbsoluteFill style={{ background: L.bg[1], overflow: 'hidden', fontFamily: FONT.sans }}>
168
+ <Stage look={L} keyLight={{ x: 0.5, y: 0.0 }} fill={{ x: 0.5, y: 1.05 }} horizon={0.62} breathe={0.4}>
169
+ {/* 画布点阵:围绕导航条清楚、四周隐去 */}
170
+ <AbsoluteFill style={{
171
+ backgroundImage: `radial-gradient(${alpha(L.ink, 0.13)} 1.4px, transparent 1.7px)`,
172
+ backgroundSize: '36px 36px', backgroundPosition: '6px 16px',
173
+ WebkitMaskImage: 'radial-gradient(ellipse 52% 40% at 50% 62%, #000 20%, transparent 100%)',
174
+ maskImage: 'radial-gradient(ellipse 52% 40% at 50% 62%, #000 20%, transparent 100%)',
175
+ }} />
176
+ {/* 导航条落脚的光池:条子"站"在画布上 */}
177
+ <div style={{
178
+ position: 'absolute', left: 260, right: 260, top: ROW_Y + 40, height: 200,
179
+ background: `radial-gradient(ellipse 50% 50% at 50% 30%, ${alpha(L.light, 0.1)} 0%, transparent 70%)`,
180
+ }} />
181
+ </Stage>
182
+
183
+ <AbsoluteFill style={{ transform: `scale(${cam})`, transformOrigin: '50% 52%' }}>
184
+ {/* ── 读数:眉题 + 超大数值 + 单位 ── */}
185
+ <div style={{
186
+ position: 'absolute', left: 0, right: 0, top: 150, display: 'flex', justifyContent: 'center', alignItems: 'center', gap: 16,
187
+ opacity: eyebrow, letterSpacing: `${(0.28 + (1 - eyebrow) * 0.4).toFixed(3)}em`,
188
+ ...type(22, 600, { caps: true }), color: L.ink2,
189
+ }}>
190
+ <IconAutoLayout c={L.ink2} />
191
+ <span style={{ letterSpacing: 'inherit' }}>Auto layout · Gap</span>
192
+ </div>
193
+ <div style={{
194
+ position: 'absolute', left: 0, right: 0, top: 186, height: 220, overflow: 'hidden',
195
+ display: 'flex', justifyContent: 'center', alignItems: 'flex-end',
196
+ }}>
197
+ <div style={{
198
+ display: 'flex', alignItems: 'baseline', gap: 18,
199
+ transform: `translateY(${((1 - numIn) * 105).toFixed(2)}%)`,
200
+ }}>
201
+ <span style={{
202
+ ...type(196, 300), letterSpacing: '-0.05em', color: numColor, display: 'inline-block',
203
+ minWidth: '1.9em', textAlign: 'right', transform: `scale(${tickPulse})`, transformOrigin: '100% 80%',
204
+ textShadow: hot > 0.05 ? `0 0 ${(40 * hot).toFixed(1)}px ${alpha(GOLD, 0.35 * hot)}` : undefined,
205
+ }}>{gapShown}</span>
206
+ <span style={{ ...type(60, 500), color: L.ink3, width: '1.9em' }}>px</span>
207
+ </div>
208
+ </div>
209
+ <Ruler gap={gap} op={rulerIn} hot={hot} />
210
+
211
+ {/* ── 导航块(video-shotcraft 站点顶部导航) ── */}
212
+ {BLOCK_WIDTHS.map((w, i) => {
213
+ const inP = ramp(frame, 1 + i * 2, 16, EASE.snappy);
214
+ const active = i === 0;
215
+ const vx = (i - 2) * v; // 块速度 = (i−2)·dgap/dt:外侧块位移最大
216
+ const blur = Math.min(9, Math.abs(vx) * 0.5);
217
+ const fid = `nb${i}`;
218
+ const dy = (1 - inP) * 34;
219
+ return (
220
+ <div key={i} style={{
221
+ position: 'absolute', left: xs[i], top: ROW_Y - BLOCK_H / 2, width: w, height: BLOCK_H,
222
+ opacity: inP, transform: `translateY(${dy.toFixed(2)}px)`,
223
+ }}>
224
+ {blur > 0.5 && (
225
+ <svg width={0} height={0} style={{ position: 'absolute' }} aria-hidden>
226
+ <filter id={fid} x="-20%" y="-10%" width="140%" height="120%" colorInterpolationFilters="sRGB">
227
+ <feGaussianBlur stdDeviation={`${blur.toFixed(2)} 0`} />
228
+ </filter>
229
+ </svg>
230
+ )}
231
+ <div style={{
232
+ position: 'absolute', inset: 0, boxSizing: 'border-box', borderRadius: 24,
233
+ background: active ? 'linear-gradient(180deg, #fbfbf8, #e6e6e1)' : 'linear-gradient(180deg, #212327, #17181b)',
234
+ border: active ? '1px solid rgba(255,255,255,0.7)' : `1px solid ${alpha('#ffffff', 0.09)}`,
235
+ boxShadow: active
236
+ ? `inset 0 1px 0 rgba(255,255,255,1), inset 0 -2px 0 rgba(0,0,0,0.08), ${softShadow(18, { color: '#000000', strength: 2.4 })}`
237
+ : `inset 0 1px 0 ${alpha('#ffffff', 0.08)}, ${softShadow(12, { color: '#000000', strength: 2.4 })}`,
238
+ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 14,
239
+ filter: blur > 0.5 ? `url(#${fid})` : undefined,
240
+ }}>
241
+ {active && <div style={{ width: 12, height: 12, borderRadius: 99, background: '#111214' }} />}
242
+ <span style={{ ...type(36, active ? 650 : 520), color: active ? '#0d0e10' : alpha(L.ink, 0.86) }}>{LABELS[i]}</span>
243
+ </div>
244
+ </div>
245
+ );
246
+ })}
247
+
248
+ {/* ── 框选描边 + 8 手柄 + 图层名 ── */}
249
+ <div style={{
250
+ position: 'absolute', left: selX, top: selY, width: selW, height: selH, boxSizing: 'border-box',
251
+ border: `2px solid ${SEL}`, borderRadius: 6, opacity: Math.min(1, selIn * 1.4),
252
+ }}>
253
+ <div style={{
254
+ position: 'absolute', left: -2, top: -50, display: 'flex', alignItems: 'center', gap: 10,
255
+ ...type(26, 560), color: SEL, whiteSpace: 'nowrap',
256
+ }}>
257
+ <IconAutoLayout c={SEL} size={20} />
258
+ Nav links
259
+ <span style={{ ...type(22, 500, { mono: true }), color: L.ink3, marginLeft: 8 }}>
260
+ {Math.round(total)} × {BLOCK_H}
261
+ </span>
262
+ </div>
263
+ {[[0, 0], [0.5, 0], [1, 0], [0, 0.5], [1, 0.5], [0, 1], [0.5, 1], [1, 1]].map(([hx, hy], i) => {
264
+ const hp = springAt(frame, 7 + i * 1.2, { damping: 13, stiffness: 240 });
265
+ return (
266
+ <div key={i} style={{
267
+ position: 'absolute', left: `${hx * 100}%`, top: `${hy * 100}%`, width: 16, height: 16, marginLeft: -8, marginTop: -8,
268
+ background: L.bg[1], border: `2px solid ${SEL}`, borderRadius: 3, boxSizing: 'border-box', transform: `scale(${hp})`,
269
+ }} />
270
+ );
271
+ })}
272
+ </div>
273
+
274
+ {/* ── 间距标注:延长线 ×2 + 测量线 + 徽章(全部由 gap 实时重算) ── */}
275
+ {xs.slice(0, -1).map((x, i) => {
276
+ const gx = x + BLOCK_WIDTHS[i];
277
+ const cy = ROW_Y + BLOCK_H / 2 + 74;
278
+ const extTop = ROW_Y + BLOCK_H / 2 + 34;
279
+ const span = Math.max(0, gap);
280
+ const bp = ramp(frame, 14 + i * 2, 12, EASE.snappy);
281
+ return (
282
+ <div key={i} style={{ position: 'absolute', left: 0, top: 0, opacity: measOp }}>
283
+ {[gx, gx + gap].map((lx, k) => (
284
+ <div key={k} style={{
285
+ position: 'absolute', left: lx - 0.75, top: extTop, width: 1.5, height: 58,
286
+ backgroundImage: `linear-gradient(${GOLD} 55%, transparent 55%)`, backgroundSize: '1.5px 7px', opacity: 0.7,
287
+ }} />
288
+ ))}
289
+ <div style={{ position: 'absolute', left: gx, top: cy - 1, width: span, height: 2, background: GOLD, boxShadow: `0 0 10px ${alpha(GOLD, 0.4)}` }} />
290
+ <div style={{ position: 'absolute', left: gx - 1, top: cy - 8, width: 2, height: 16, background: GOLD }} />
291
+ <div style={{ position: 'absolute', left: gx + gap - 1, top: cy - 8, width: 2, height: 16, background: GOLD }} />
292
+ <div style={{
293
+ position: 'absolute', left: gx + gap / 2, top: cy + 20,
294
+ transform: `translateX(-50%) translateY(${((1 - bp) * 10).toFixed(1)}px) scale(${(tickPulse * (0.7 + 0.3 * bp)).toFixed(3)})`,
295
+ opacity: bp, minWidth: 64, textAlign: 'center', boxSizing: 'border-box', padding: '6px 14px', borderRadius: 10,
296
+ background: GOLD, color: L.onAccent, ...type(28, 700), lineHeight: 1.1,
297
+ boxShadow: `inset 0 1px 0 rgba(255,255,255,0.45), 0 6px 18px -6px ${alpha(GOLD, 0.6)}`,
298
+ }}>{gapShown}</div>
299
+ </div>
300
+ );
301
+ })}
302
+ </AbsoluteFill>
303
+ </AbsoluteFill>
304
+ );
305
+ };