Showing preview only (1,270K chars total). Download the full file or copy to clipboard to get everything.
Repository: Popmotion/popmotion
Branch: master
Commit: adf681efd856
Files: 536
Total size: 1.1 MB
Directory structure:
gitextract_kjzyuham/
├── .babelrc
├── .circleci/
│ └── config.yml
├── .eslintrc
├── .github/
│ └── ISSUE_TEMPLATE/
│ ├── Feature_request.md
│ └── bug-report.md
├── .gitignore
├── .prettierignore
├── .storybook/
│ └── config.js
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── README.md
├── lerna.json
├── package.json
├── packages/
│ ├── blend-tweens/
│ │ ├── blend-tweens.js
│ │ └── cross-fade.js
│ ├── framesync/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── rollup.config.js
│ │ ├── src/
│ │ │ ├── _tests/
│ │ │ │ └── test.ts
│ │ │ ├── create-render-step.ts
│ │ │ ├── index.ts
│ │ │ ├── on-next-frame.ts
│ │ │ └── types.ts
│ │ └── tsconfig.json
│ ├── popcorn/
│ │ └── docs/
│ │ └── api/
│ │ └── utilities/
│ │ ├── angle.md
│ │ ├── apply-offset.md
│ │ ├── clamp.md
│ │ ├── conditional.md
│ │ ├── degreesToRadians.md
│ │ ├── distance.md
│ │ ├── interpolate.md
│ │ ├── is-point-3d.md
│ │ ├── is-point.md
│ │ ├── mix-array.md
│ │ ├── mix-color.md
│ │ ├── mix-complex.md
│ │ ├── mix.md
│ │ ├── pipe.md
│ │ ├── point-from-vector.md
│ │ ├── progress.md
│ │ ├── radians-to-degrees.md
│ │ ├── smooth-frame.md
│ │ ├── smooth.md
│ │ ├── snap.md
│ │ ├── to-decimal.md
│ │ ├── velocity-per-frame.md
│ │ ├── velocity-per-second.md
│ │ └── wrap.md
│ ├── popmotion/
│ │ ├── .gitignore
│ │ ├── .npmignore
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE.md
│ │ ├── README.md
│ │ ├── docs/
│ │ │ ├── api/
│ │ │ │ ├── action.md
│ │ │ │ ├── animation/
│ │ │ │ │ ├── decay.md
│ │ │ │ │ ├── every-frame.md
│ │ │ │ │ ├── inertia.md
│ │ │ │ │ ├── keyframes.md
│ │ │ │ │ ├── physics.md
│ │ │ │ │ ├── spring.md
│ │ │ │ │ ├── timeline.md
│ │ │ │ │ └── tween.md
│ │ │ │ ├── calc.md
│ │ │ │ ├── compositors/
│ │ │ │ │ ├── chain.md
│ │ │ │ │ ├── composite.md
│ │ │ │ │ ├── crossfade.md
│ │ │ │ │ ├── delay.md
│ │ │ │ │ ├── merge.md
│ │ │ │ │ ├── parallel.md
│ │ │ │ │ ├── schedule.md
│ │ │ │ │ └── stagger.md
│ │ │ │ ├── easing.md
│ │ │ │ ├── faqs.md
│ │ │ │ ├── framesync.md
│ │ │ │ ├── input/
│ │ │ │ │ ├── listen.md
│ │ │ │ │ ├── multitouch.md
│ │ │ │ │ └── pointer.md
│ │ │ │ ├── reactions/
│ │ │ │ │ ├── multicast.md
│ │ │ │ │ └── value.md
│ │ │ │ └── transformers.md
│ │ │ ├── blog/
│ │ │ │ ├── 20170703-choosing-a-default-easing-for-popmotion.md
│ │ │ │ ├── 20170704-manually-set-scroll-while-ios-momentum-scroll-bounces.md
│ │ │ │ ├── 20170710-mobile-web-is-awful-and-were-all-to-blame.md
│ │ │ │ ├── 20170803-coding-style-dont-be-a-dick.md
│ │ │ │ ├── 20171210-popmotion-8-upgrade-guide.md
│ │ │ │ ├── 20171211-introducing-popmotion-8.md
│ │ │ │ ├── 20180104-when-ios-throttles-requestanimationframe.md
│ │ │ │ ├── 20180521-pose-2-migration-guide.md
│ │ │ │ ├── 20180820-introducing-pose-3.md
│ │ │ │ ├── 20180829-pose-3-1-animate-between-anything.md
│ │ │ │ ├── 20180904-introducing-pose-for-vue.md
│ │ │ │ ├── 20181101-react-pose-4-forwardref.md
│ │ │ │ ├── 20190123-introducing-inertia-animation-for-popmotion-pure.md
│ │ │ │ ├── 20190704-upgrade-to-pure-9.md
│ │ │ │ ├── 20200115-pose-is-deprecated.md
│ │ │ │ ├── draft-60fps-hi-res-image-scaling-with-translatez-and-maths.md
│ │ │ │ ├── draft-css-vs-js-animation.md
│ │ │ │ └── draft-the-emerging-reality.md
│ │ │ └── learn/
│ │ │ ├── advanced/
│ │ │ │ └── value-pipelines.md
│ │ │ ├── basics/
│ │ │ │ ├── action-reaction.md
│ │ │ │ ├── get-started.md
│ │ │ │ ├── input-tracking.md
│ │ │ │ ├── install.md
│ │ │ │ └── velocity-and-physics.md
│ │ │ ├── how-to/
│ │ │ │ ├── circular-motion.md
│ │ │ │ ├── constrain-motion.md
│ │ │ │ ├── input-smoothing.md
│ │ │ │ ├── morph-svg.md
│ │ │ │ └── rounded-values.md
│ │ │ └── projects/
│ │ │ └── spring-loaded-characters-remaining.md
│ │ ├── package.json
│ │ ├── rollup.config.js
│ │ ├── src/
│ │ │ ├── animations/
│ │ │ │ ├── __tests__/
│ │ │ │ │ ├── animate.test.ts
│ │ │ │ │ ├── inertia.test.ts
│ │ │ │ │ └── utils.ts
│ │ │ │ ├── generators/
│ │ │ │ │ ├── __tests__/
│ │ │ │ │ │ ├── decay.test.ts
│ │ │ │ │ │ ├── keyframes.test.ts
│ │ │ │ │ │ ├── spring.test.ts
│ │ │ │ │ │ └── utils.ts
│ │ │ │ │ ├── decay.ts
│ │ │ │ │ ├── keyframes.ts
│ │ │ │ │ └── spring.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── inertia.ts
│ │ │ │ ├── types.ts
│ │ │ │ └── utils/
│ │ │ │ ├── __tests__/
│ │ │ │ │ ├── detect-animation-from-config.test.ts
│ │ │ │ │ ├── elapsed.test.ts
│ │ │ │ │ └── find-spring.test.ts
│ │ │ │ ├── detect-animation-from-options.ts
│ │ │ │ ├── elapsed.ts
│ │ │ │ └── find-spring.ts
│ │ │ ├── easing/
│ │ │ │ ├── __tests__/
│ │ │ │ │ ├── cubic-bezier.test.ts
│ │ │ │ │ ├── index.test.ts
│ │ │ │ │ ├── steps.test.ts
│ │ │ │ │ └── utils.test.ts
│ │ │ │ ├── cubic-bezier.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── steps.ts
│ │ │ │ ├── types.ts
│ │ │ │ └── utils.ts
│ │ │ ├── index.ts
│ │ │ ├── types.ts
│ │ │ ├── utils/
│ │ │ │ ├── __tests__/
│ │ │ │ │ ├── angle.test.ts
│ │ │ │ │ ├── apply-offset.test.ts
│ │ │ │ │ ├── attract.test.ts
│ │ │ │ │ ├── clamp.test.ts
│ │ │ │ │ ├── degrees-to-radians.test.ts
│ │ │ │ │ ├── distance.test.ts
│ │ │ │ │ ├── hsla-to-rgba.test.ts
│ │ │ │ │ ├── interpolate.test.ts
│ │ │ │ │ ├── is-point-3d.test.ts
│ │ │ │ │ ├── is-point.test.ts
│ │ │ │ │ ├── mix-array.test.ts
│ │ │ │ │ ├── mix-color.test.ts
│ │ │ │ │ ├── mix-complex.test.ts
│ │ │ │ │ ├── mix-object.test.ts
│ │ │ │ │ ├── mix.test.ts
│ │ │ │ │ ├── point-from-vector.test.ts
│ │ │ │ │ ├── progress.test.ts
│ │ │ │ │ ├── radians-to-degrees.test.ts
│ │ │ │ │ ├── smooth-frame.test.ts
│ │ │ │ │ ├── smooth.test.ts
│ │ │ │ │ ├── snap.test.ts
│ │ │ │ │ ├── to-decimal.test.ts
│ │ │ │ │ ├── velocity-per-frame.test.ts
│ │ │ │ │ ├── velocity-per-second.test.ts
│ │ │ │ │ └── wrap.test.ts
│ │ │ │ ├── angle.ts
│ │ │ │ ├── apply-offset.ts
│ │ │ │ ├── attract.ts
│ │ │ │ ├── clamp.ts
│ │ │ │ ├── degrees-to-radians.ts
│ │ │ │ ├── distance.ts
│ │ │ │ ├── hsla-to-rgba.ts
│ │ │ │ ├── inc.ts
│ │ │ │ ├── interpolate.ts
│ │ │ │ ├── is-point-3d.ts
│ │ │ │ ├── is-point.ts
│ │ │ │ ├── mix-color.ts
│ │ │ │ ├── mix-complex.ts
│ │ │ │ ├── mix.ts
│ │ │ │ ├── pipe.ts
│ │ │ │ ├── point-from-vector.ts
│ │ │ │ ├── progress.ts
│ │ │ │ ├── radians-to-degrees.ts
│ │ │ │ ├── smooth-frame.ts
│ │ │ │ ├── smooth.ts
│ │ │ │ ├── snap.ts
│ │ │ │ ├── to-decimal.ts
│ │ │ │ ├── velocity-per-frame.ts
│ │ │ │ ├── velocity-per-second.ts
│ │ │ │ └── wrap.ts
│ │ │ └── worklet/
│ │ │ ├── animate.ts.wip
│ │ │ ├── custom-properties.ts
│ │ │ ├── index.ts.wip
│ │ │ └── load-worklet.ts
│ │ ├── tsconfig.json
│ │ └── tslint.json
│ ├── popmotion-pose/
│ │ └── docs/
│ │ ├── api/
│ │ │ ├── dom/
│ │ │ │ ├── config.md
│ │ │ │ └── dom-pose.md
│ │ │ ├── faqs.md
│ │ │ ├── react/
│ │ │ │ ├── posed.md
│ │ │ │ ├── posegroup.md
│ │ │ │ ├── react-config.md
│ │ │ │ ├── react-pose-text.md
│ │ │ │ └── supported-values.md
│ │ │ ├── react-native/
│ │ │ │ ├── native-config.md
│ │ │ │ ├── native-posed.md
│ │ │ │ ├── native-supported-values.md
│ │ │ │ └── native-transition.md
│ │ │ └── vue/
│ │ │ ├── vue-config.md
│ │ │ ├── vue-posed.md
│ │ │ ├── vue-posetransition.md
│ │ │ └── vue-supported-values.md
│ │ ├── examples/
│ │ │ ├── react/
│ │ │ │ ├── accordion.md
│ │ │ │ ├── css-variables.md
│ │ │ │ ├── enter-exit.md
│ │ │ │ ├── event-drag-boundaries.md
│ │ │ │ ├── event-drag.md
│ │ │ │ ├── event-focus.md
│ │ │ │ ├── event-hover.md
│ │ │ │ ├── event-press.md
│ │ │ │ ├── filter.md
│ │ │ │ ├── outline.md
│ │ │ │ ├── posegroup-reordering.md
│ │ │ │ ├── react-medium-style-image-zoom.md
│ │ │ │ ├── route-transitions-reach-router.md
│ │ │ │ ├── route-transitions-react-router.md
│ │ │ │ ├── splittext-as-children.md
│ │ │ │ ├── splittext-custom-animations.md
│ │ │ │ ├── splittext-ui-events.md
│ │ │ │ ├── splittext.md
│ │ │ │ └── svg-morphing.md
│ │ │ └── vue/
│ │ │ ├── vue-animating-children.md
│ │ │ ├── vue-enter-exit.md
│ │ │ ├── vue-flip.md
│ │ │ ├── vue-magic-animations.md
│ │ │ ├── vue-medium-style-image-zoom.md
│ │ │ ├── vue-passive-values.md
│ │ │ ├── vue-ui-events-dragging.md
│ │ │ ├── vue-ui-events-focus.md
│ │ │ ├── vue-ui-events-hover.md
│ │ │ └── vue-ui-events-press.md
│ │ └── learn/
│ │ ├── get-started.md
│ │ ├── how-to/
│ │ │ ├── css-variables.md
│ │ │ └── framer-x.md
│ │ ├── react/
│ │ │ ├── animating-children.md
│ │ │ ├── custom-transitions.md
│ │ │ ├── dynamic-props.md
│ │ │ ├── flip.md
│ │ │ ├── install.md
│ │ │ ├── passive.md
│ │ │ ├── popmotion-get-started.md
│ │ │ ├── react-exit-enter-transitions.md
│ │ │ ├── react-tutorial-medium-style-image-zoom.md
│ │ │ ├── route-transitions-reach-router.md
│ │ │ ├── route-transitions-react-router.md
│ │ │ └── ui-events.md
│ │ ├── react-native/
│ │ │ ├── native-animating-children.md
│ │ │ ├── native-custom-transitions.md
│ │ │ ├── native-dragging.md
│ │ │ ├── native-get-started.md
│ │ │ └── native-passive.md
│ │ └── vue/
│ │ ├── vue-animating-children.md
│ │ ├── vue-custom-transitions.md
│ │ ├── vue-dynamic-props.md
│ │ ├── vue-enter-exit-transitions.md
│ │ ├── vue-flip.md
│ │ ├── vue-get-started.md
│ │ ├── vue-install.md
│ │ ├── vue-passive.md
│ │ ├── vue-tutorial-medium-style-image-zoom.md
│ │ └── vue-ui-events.md
│ ├── projection/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE.md
│ │ ├── README.md
│ │ ├── cypress/
│ │ │ ├── fixtures/
│ │ │ │ └── example.json
│ │ │ ├── integration/
│ │ │ │ └── index.spec.js
│ │ │ ├── plugins/
│ │ │ │ └── index.js
│ │ │ ├── support/
│ │ │ │ ├── commands.js
│ │ │ │ └── index.js
│ │ │ └── tests/
│ │ │ └── index.html
│ │ ├── cypress.json
│ │ ├── package.json
│ │ ├── rollup.config.js
│ │ ├── src/
│ │ │ ├── __tests__/
│ │ │ │ └── index.test.ts
│ │ │ ├── dom/
│ │ │ │ ├── correct-border-radius.ts
│ │ │ │ ├── correct-box-shadow.ts
│ │ │ │ └── style.ts
│ │ │ ├── geometry/
│ │ │ │ ├── __tests__/
│ │ │ │ │ ├── apply.test.ts
│ │ │ │ │ └── calc.test.ts
│ │ │ │ ├── apply.ts
│ │ │ │ ├── calc.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── types.ts
│ │ │ ├── index.ts
│ │ │ ├── node.ts
│ │ │ └── types.ts
│ │ └── tsconfig.json
│ ├── site/
│ │ ├── .babelrc
│ │ ├── .gitignore
│ │ ├── components/
│ │ │ ├── examples/
│ │ │ │ ├── Ball.js
│ │ │ │ ├── CodePen.js
│ │ │ │ ├── CodeSandbox.js
│ │ │ │ ├── Counter.js
│ │ │ │ ├── Example.js
│ │ │ │ ├── Swatch.js
│ │ │ │ └── templates.js
│ │ │ ├── icons/
│ │ │ │ ├── BrandGradientDef.js
│ │ │ │ ├── DropDownArrow.js
│ │ │ │ ├── FramesyncLogo.js
│ │ │ │ ├── GitHub.js
│ │ │ │ ├── Logo.js
│ │ │ │ ├── PopcornLogo.js
│ │ │ │ ├── PopmotionIcon.js
│ │ │ │ ├── PopmotionPure.js
│ │ │ │ ├── PoseLogo.js
│ │ │ │ ├── StylefireLogo.js
│ │ │ │ └── Twitter.js
│ │ │ ├── layout/
│ │ │ │ ├── Content.js
│ │ │ │ ├── SiteLink.js
│ │ │ │ └── grid.js
│ │ │ └── template.js
│ │ ├── data/
│ │ │ ├── authors.json
│ │ │ ├── category-names.json
│ │ │ ├── route-paths.json
│ │ │ ├── section-names.json
│ │ │ ├── settings.json
│ │ │ └── site-names.json
│ │ ├── docs/
│ │ │ ├── popcorn/
│ │ │ │ └── index.md
│ │ │ └── stylefire/
│ │ │ └── index.md
│ │ ├── package.json
│ │ ├── pages/
│ │ │ ├── _document.js
│ │ │ ├── _error.js
│ │ │ ├── api.js
│ │ │ ├── blog.js
│ │ │ ├── index.js
│ │ │ ├── popcorn/
│ │ │ │ └── index.js
│ │ │ ├── pose/
│ │ │ │ ├── api.js
│ │ │ │ ├── examples.js
│ │ │ │ └── index.js
│ │ │ ├── pure/
│ │ │ │ ├── api/
│ │ │ │ │ ├── action.js
│ │ │ │ │ ├── calc.js
│ │ │ │ │ ├── chain.js
│ │ │ │ │ ├── composite.js
│ │ │ │ │ ├── crossfade.js
│ │ │ │ │ ├── css.js
│ │ │ │ │ ├── decay.js
│ │ │ │ │ ├── delay.js
│ │ │ │ │ ├── easing.js
│ │ │ │ │ ├── every-frame.js
│ │ │ │ │ ├── framesync.js
│ │ │ │ │ ├── keyframes.js
│ │ │ │ │ ├── listen.js
│ │ │ │ │ ├── merge.js
│ │ │ │ │ ├── multicast.js
│ │ │ │ │ ├── multitouch.js
│ │ │ │ │ ├── parallel.js
│ │ │ │ │ ├── physics.js
│ │ │ │ │ ├── pointer.js
│ │ │ │ │ ├── schedule.js
│ │ │ │ │ ├── scroll.js
│ │ │ │ │ ├── spring.js
│ │ │ │ │ ├── stagger.js
│ │ │ │ │ ├── stylefire.js
│ │ │ │ │ ├── svg.js
│ │ │ │ │ ├── timeline.js
│ │ │ │ │ ├── transformers.js
│ │ │ │ │ ├── tween.js
│ │ │ │ │ ├── value-types.js
│ │ │ │ │ └── value.js
│ │ │ │ ├── blog/
│ │ │ │ │ ├── 20170703-choosing-a-default-easing-for-popmotion.js
│ │ │ │ │ ├── 20170704-manually-set-scroll-while-ios-momentum-scroll-bounces.js
│ │ │ │ │ ├── 20170710-mobile-web-is-awful-and-were-all-to-blame.js
│ │ │ │ │ ├── 20170803-coding-style-dont-be-a-dick.js
│ │ │ │ │ ├── 20171210-popmotion-8-upgrade-guide.js
│ │ │ │ │ ├── 20171211-introducing-popmotion-8.js
│ │ │ │ │ ├── 20180104-when-ios-throttles-requestanimationframe.js
│ │ │ │ │ └── 20180521-pose-2-migration-guide.js
│ │ │ │ ├── index.js
│ │ │ │ └── learn/
│ │ │ │ ├── action-reaction.js
│ │ │ │ ├── circular-motion.js
│ │ │ │ ├── constrain-motion.js
│ │ │ │ ├── get-started.js
│ │ │ │ ├── input-smoothing.js
│ │ │ │ ├── input-tracking.js
│ │ │ │ ├── install.js
│ │ │ │ ├── morph-svg.js
│ │ │ │ ├── rounded-values.js
│ │ │ │ ├── spring-loaded-characters-remaining.js
│ │ │ │ ├── value-pipelines.js
│ │ │ │ └── velocity-and-physics.js
│ │ │ ├── stylefire/
│ │ │ │ ├── api/
│ │ │ │ │ ├── create-styler-factory.js
│ │ │ │ │ ├── html.js
│ │ │ │ │ ├── styler.js
│ │ │ │ │ ├── svg.js
│ │ │ │ │ └── viewport.js
│ │ │ │ ├── api.js
│ │ │ │ └── index.js
│ │ │ └── support.js
│ │ ├── public/
│ │ │ └── manifest.json
│ │ ├── scripts/
│ │ │ ├── build-next-config.js
│ │ │ ├── convert-date-format.js
│ │ │ ├── filename-operations.js
│ │ │ ├── generate-content-page.js
│ │ │ ├── generate-content.js
│ │ │ └── generate-menus.js
│ │ ├── styles/
│ │ │ ├── fonts.js
│ │ │ ├── nprogress.js
│ │ │ ├── reset.js
│ │ │ ├── syntax-highlighting.js
│ │ │ ├── themes.js
│ │ │ └── vars.js
│ │ ├── templates/
│ │ │ ├── Popcorn/
│ │ │ │ └── index.js
│ │ │ ├── Popmotion/
│ │ │ │ ├── FinalCTA/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── styled.js
│ │ │ │ ├── Header/
│ │ │ │ │ └── index.js
│ │ │ │ ├── Masthead/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── styled.js
│ │ │ │ ├── USPs/
│ │ │ │ │ ├── Example.js
│ │ │ │ │ ├── ExampleSection.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── styled.js
│ │ │ │ └── index.js
│ │ │ ├── Pose/
│ │ │ │ ├── Header/
│ │ │ │ │ └── index.js
│ │ │ │ ├── USPs/
│ │ │ │ │ ├── AnimateAnything.js
│ │ │ │ │ ├── ChildrenExample.js
│ │ │ │ │ ├── CustomExample.js
│ │ │ │ │ ├── DeclarativeExample.js
│ │ │ │ │ ├── DraggableExample.js
│ │ │ │ │ ├── FlipExample.js
│ │ │ │ │ ├── PassiveExample.js
│ │ │ │ │ ├── PluginsExample.js
│ │ │ │ │ ├── ReactExample.js
│ │ │ │ │ ├── ZeroConfigExample.js
│ │ │ │ │ └── index.js
│ │ │ │ └── index.js
│ │ │ ├── Stylefire/
│ │ │ │ └── index.js
│ │ │ ├── blog/
│ │ │ │ ├── components/
│ │ │ │ │ └── BlogItem/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── styled.js
│ │ │ │ └── index.js
│ │ │ ├── content/
│ │ │ │ ├── ContentCTA/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── styled.js
│ │ │ │ ├── ContentNav.js
│ │ │ │ ├── MenuPage/
│ │ │ │ │ └── index.js
│ │ │ │ ├── PostDetails/
│ │ │ │ │ └── index.js
│ │ │ │ ├── TableOfContents/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── styled.js
│ │ │ │ ├── Template.js
│ │ │ │ └── styled.js
│ │ │ ├── global/
│ │ │ │ ├── Analytics.js
│ │ │ │ ├── Footer.js
│ │ │ │ ├── Header.js
│ │ │ │ ├── SectionNav.js
│ │ │ │ ├── SocialLinks.js
│ │ │ │ ├── Template.js
│ │ │ │ ├── grid.js
│ │ │ │ └── styled.js
│ │ │ ├── global-new/
│ │ │ │ ├── ContentPage/
│ │ │ │ │ └── index.js
│ │ │ │ ├── Footer/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── styled.js
│ │ │ │ ├── Header/
│ │ │ │ │ └── index.js
│ │ │ │ ├── Nav/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── styled.js
│ │ │ │ └── styled.js
│ │ │ └── homepage/
│ │ │ └── index.js
│ │ └── utils/
│ │ └── string.js
│ └── style-value-types/
│ ├── CHANGELOG.md
│ ├── LICENSE.md
│ ├── README.md
│ ├── package.json
│ ├── rollup.config.js
│ ├── src/
│ │ ├── _tests/
│ │ │ └── index.test.ts
│ │ ├── color/
│ │ │ ├── hex.ts
│ │ │ ├── hsla.ts
│ │ │ ├── index.ts
│ │ │ ├── rgba.ts
│ │ │ └── utils.ts
│ │ ├── complex/
│ │ │ ├── filter.ts
│ │ │ └── index.ts
│ │ ├── index.ts
│ │ ├── numbers/
│ │ │ ├── index.ts
│ │ │ └── units.ts
│ │ ├── types.ts
│ │ └── utils.ts
│ ├── tsconfig.json
│ └── tslint.json
├── playground/
│ ├── animate.js
│ ├── index.js
│ └── worklet.js
├── rollup-generate-config.js
├── tsconfig.json
├── tslint.json
└── types/
├── animations/
│ ├── decay.d.ts
│ ├── index.d.ts
│ ├── inertia.d.ts
│ ├── keyframes.d.ts
│ ├── spring.d.ts
│ ├── types.d.ts
│ └── utils/
│ └── detect-animation-from-options.d.ts
├── easing/
│ ├── cubic-bezier.d.ts
│ ├── index.d.ts
│ ├── steps.d.ts
│ ├── types.d.ts
│ └── utils.d.ts
├── global.d.ts
├── index.d.ts
├── types.d.ts
├── utils/
│ ├── angle.d.ts
│ ├── apply-offset.d.ts
│ ├── attract.d.ts
│ ├── clamp.d.ts
│ ├── degrees-to-radians.d.ts
│ ├── distance.d.ts
│ ├── inc.d.ts
│ ├── interpolate.d.ts
│ ├── is-point-3d.d.ts
│ ├── is-point.d.ts
│ ├── mix-color.d.ts
│ ├── mix-complex.d.ts
│ ├── mix.d.ts
│ ├── pipe.d.ts
│ ├── point-from-vector.d.ts
│ ├── progress.d.ts
│ ├── radians-to-degrees.d.ts
│ ├── smooth-frame.d.ts
│ ├── smooth.d.ts
│ ├── snap.d.ts
│ ├── to-decimal.d.ts
│ ├── velocity-per-frame.d.ts
│ ├── velocity-per-second.d.ts
│ └── wrap.d.ts
└── worklet/
├── custom-properties.d.ts
└── load-worklet.d.ts
================================================
FILE CONTENTS
================================================
================================================
FILE: .babelrc
================================================
{
"presets": [["env", { "loose": true} ], "stage-2"],
"plugins": ["transform-export-extensions", "transform-react-jsx"],
"env": {
"development": {
"sourceMaps": "inline"
}
}
}
================================================
FILE: .circleci/config.yml
================================================
# Javascript Node CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-javascript/ for more details
#
version: 2
jobs:
build:
docker:
# specify the version you desire here
- image: circleci/node:10
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
# - image: circleci/mongo:3.4.4
working_directory: ~/repo
steps:
- checkout
# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
- run: yarn
- run: yarn bootstrap
- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}
# Build and run tests
- run: yarn test
- run: yarn build
================================================
FILE: .eslintrc
================================================
{
"rules": {
"strict": 0,
"indent": [2, 2],
"quotes": [2, "single"],
"linebreak-style": [2, "unix"],
"semi": [2, "always"],
"no-unused-vars": [2, { "ignoreRestSiblings": true }],
"react/jsx-uses-react": 1,
"react/jsx-uses-vars": 1
},
"ecmaFeatures": {
"restParams": true,
"destructuring": true,
"modules": true,
"jsx": true
},
"env": {
"es6": true,
"browser": true,
"node": true,
"jest": true
},
"parser": "babel-eslint",
"extends": "eslint:recommended",
"plugins": ["jsx-a11y", "react", "import", "jasmine", "flowtype"]
}
================================================
FILE: .github/ISSUE_TEMPLATE/Feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.md
================================================
---
name: Bug report
about: Create a report to help us improve
---
## Ensure you're using the latest version
CodeSandbox examples might not always be using the latest version of Pose.
## Add the package name to bug title
For instance, if this is a bug in Popmotion, write "Popmotion: Name of bug"
## Describe the bug
A clear and concise description of what the bug is.
## How to reproduce
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
## Expected behaviour
A clear and concise description of what you expected to happen.
## Link to CodePen example (or similar)
## Device information
In which environment are you reproducing the bug?
- Device: [e.g. iPhone6]
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
## Additional context
Add any other context about the problem here.
================================================
FILE: .gitignore
================================================
node_modules
.DS_Store
lib
packages/site/.next
packages/site/pages/api
packages/site/pages/learn
packages/site/pages/blog
packages/site/pages/pose/api
packages/site/pages/pose/examples
packages/site/pages/pose/learn
packages/site/pages/popcorn/api
packages/site/data/content.json
packages/site/data/menus.json
packages/site/next.config.js
packages/projection/cypress/screenshots/*
playground/public
storybook-static
coverage
.vscode
tmp
dist
*.log
videos
================================================
FILE: .prettierignore
================================================
*.md
================================================
FILE: .storybook/config.js
================================================
import { configure } from '@storybook/react';
function loadStories() {
require('../playground');
}
configure(loadStories, module);
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Code of conduct

================================================
FILE: CONTRIBUTING.md
================================================
# How to Contribute
This guide will run through the types of contributions you can make and how to set the Popmotion repo up, ready for local development.
- [Types of Contribution](#types-of-contribution)
- [Bugs](#bugs)
- [Features](#features)
- [Development](#development)
- [Codebase Overview](#codebase-overview)
- [Package Hierarchy](#package-hierarchy)
- [Get in Touch](#get-in-touch)
## Types of Contribution
### Bugs
Open issues can be found on our [GitHub issues](https://github.com/Popmotion/popmotion/issues) page.
If you begin working on a bug, post your intent on the issue itself. This will prevent more than one person tackling a bug at once.
If the bug you wish to work on doesn't currently have an issue, make one and label it "Bug".
### Features
Before adding any features, open a Feature Proposal as a [new issue](https://github.com/Popmotion/popmotion/issues).
This will let us talk through your proposed API and/or implementation before you spend time on it.
## Development
Follow these steps to get your code PR-ready:
1. [Fork the Popmotion repo](https://github.com/Popmotion/popmotion).
2. Clone your fork locally.
3. Run `yarn`, `yarn bootstrap`, and `yarn build` in the repo root ([install Yarn](https://yarnpkg.com/lang/en/docs/install/#mac-stable) if necessary).
4. Add your code and supporting tests.
5. If this is a feature that requires doc changes, make as necessary.
6. Update `CHANGELOG.md`.
7. Ensure your changes build by running `yarn build` in the appropriate package directory(s).
## Codebase Overview
Other than [Stylefire](https://github.com/popmotion/stylefire) and [Framesync](https://github.com/popmotion/framesync), Popmotion is a monorepo. All Popmotion and Pose packages are contained in the [`packages` directory](https://github.com/Popmotion/popmotion/tree/master/packages).
All code and tests must be written in Typescript.
### Package Hierarchy
This flowchart illustrates the Popmotion package dependency tree.
**Note:** Currently, this illustration depicts `popmotion` as **not** dependent on `stylefire`, which isn't currently true. In `popmotion@9.0.0`, I'm considering removing Stylefire as a Popmotion dependency.

## Get in Touch
If you need help, you can reach out to the [official Popmotion Twitter](https://twitter.com/popmotionjs) account.
================================================
FILE: README.md
================================================
# <a href="https://popmotion.io"><img src="https://user-images.githubusercontent.com/7850794/90245722-80926e80-de33-11ea-9c39-ea6c5b344217.png" height="52" width="243" alt="Popmotion" /></a>
### The animator's toolbox
[](https://www.npmjs.com/package/popmotion)
[](https://www.npmjs.com/package/popmotion)
[](http://twitter.com/popmotionjs)
Popmotion is:
- **Powerful**: It supports keyframe and spring animations for numbers, colors and complex strings.
- **Low level**: It's designed to be composable and portable into any JavaScript environment, with an eye on worklets in the future.
- **Stable**: It's written in TypeScript and enjoys over 95% test coverage.
- **Tiny**: `animate` is just ~4.5kb, and every function is individually importable.
<!-- Documentation -->
## Quick start
```bash
npm install popmotion
```
```javascript
import { animate } from "popmotion"
animate({
from: 0,
to: 100,
onUpdate: latest => console.log(latest)
})
```
## Animation
### animate
`animate` performs a keyframes or spring animation.
```javascript
import { animate } from "popmotion"
animate({
from: 0,
to: 100,
onUpdate: latest => console.log(latest)
})
```
It can animate numbers:
```javascript
animate({ from: 0, to: 100 })
```
Or strings of the same type:
```javascript
animate({ from: "0px", to: "100px" })
animate({ from: "#fff", to: "#000" })
```
The strings can be pretty complex, for instance box shadows or SVG path definitions. The only limitation is that the numbers and colors contained within must be in the same order:
```javascript
animate({
from: "0px 0px 0px rgba(0, 0, 0, 0)",
to: "10px 10px 0px rgba(0, 0, 0, 0.2)"
})
```
<!--
Arrays of the above:
```javascript
animate({
from: [0, "#fff"],
to: [100, "#000"]
})
```
And objects of the above:
```javascript
animate({
from: { x: 0, backgroundColor: "#fff" },
to: { x: 100, backgroundColor: "#000" }
})
```
-->
The type of animation performed will be automatically detected from the provided options, or can be chosen manually by defining `type` as `"keyframes"`, `"spring"` or `"decay"`.
#### Options
These options can be set for **all animations**:
##### from
An initial value to start the animation from.
Defaults to `0`
```javascript
animate({
from: "linear-gradient(#e66465, #9198e5)",
to: "linear-gradient(#9198e5, #e66465)"
})
```
##### elapsed
Sets an initial elapsed time, in milliseconds. Set to a negative value for a delay.
```javascript
animate({
to: 100,
elapsed: -300
})
```
##### repeat
The number of times to repeat the animation. Set to `Infinity` to repeat forever.
```javascript
animate({
to: 100,
repeat: 2
})
```
##### repeatDelay
The duration, in milliseconds, to wait before repeating the animation.
```javascript
animate({
to: 100,
repeat: 2,
repeatDelay: 200
})
```
##### repeatType
Either `"loop"`, `"mirror"` or `"reverse"`. Defaults to `"loop"`.
- `"loop"`: Repeats the animation from `0`.
- `"mirror":` Swaps the `from`/`to` values alternately.
- `"reverse":` Reverses the animation alternately.
```javascript
animate({
to: 100,
repeat: 2,
repeatType: "reverse"
})
```
##### driver
By default, the animation will be driven by a `requestAnimationFrame` loop. `driver` can specify a different source.
A `Driver` is a function that accepts the animations `update` function. This is a function that can be called with a time delta from the previous frame. The `Driver` must return a function that will be called when the animation is stopped.
```javascript
const xrDriver = session => update => {
let latestRequestId = 0
let prevTimestamp = performance.now()
const step = timestamp => {
const delta = timestamp - prevTimestamp
prevTimestamp = timestamp
update(delta)
latestRequestId = session.requestAnimationFrame(step)
}
let latestRequestId = session.requestAnimationFrame(step)
return () => session.cancelRequestAnimationFrame(latestRequestId)
}
animate({
to: 100,
driver: xrDriver(xrSession)
})
```
##### type
`animate` will automatically detect the type of animation to use based on the options provided. But a specific type can be chosen manually by defining `type` as `"keyframes"`, `"spring"` or `"decay"`.
```jsx
animate({
to: 100,
type: "spring"
})
```
#### Lifecycle events
The following lifecycle events are available for **all animations**:
##### onUpdate
This is called every frame the animation fires with the latest computed value.
```javascript
animate({
to: 100,
onUpdate: latest => console.log(latest)
})
```
##### onPlay
This is called when the animation starts. Currently this automatically when `animate` is called.
```javascript
animate({
to: 100,
onPlay: () => {}
})
```
##### onComplete
This is called when the animation successfully completes.
```javascript
animate({
to: 100,
onComplete:() => {}
})
```
##### onRepeat
This is called when an animation repeats.
```javascript
animate({
to: 100,
repeat: 2,
onRepeat: () => {}
})
```
##### onStop
This is called when the animation is stopped by the `stop` control.
```javascript
const animation = animate({
to: 100,
onStop: () => {}
})
animation.stop()
```
#### Keyframes options
A keyframes animation is the default animation type and it can be defined either with a `from` and `to` option:
```javascript
animate({ from: 0, to: 100 })
```
Or as a series of keyframes provided to the `to` option:
```javascript
animate({ to: [0, 100, 200] })
```
##### to
A single value to animate to, or an array of values to animate through.
```javascript
animate({
to: ["#0ff", "#f00", "#0f0"]
})
```
If `to` is an array, any defined `from` will be ignored.
##### duration
This defines the duration of the animation, in milliseconds.
```javascript
animate({
to: 100,
duration: 300
})
```
##### ease
This is an easing function, or array of functions, to use when easing between each keyframe.
```javascript
import { animate, linear, easeInOut } from "popmotion"
animate({
to: 100,
ease: linear
})
animate({
to: ["#fff", "#000", "#f00"],
ease: [linear, easeInOut]
})
```
If set as any array, the length of this array must be one shorter than the number of values being animated between.
##### offset
This is an array of values between `0` and `1` that defines at which point throughout the animation each keyframe should be reached.
This array should be the same length as the number of defined keyframes.
```javascript
animate({
to: ["#fff", "#000", "#f00"],
offset: [0, 0.2, 1]
})
```
#### Spring options
Springs are great for creating natural-feeling interfaces and dynamic interruptable animations.
A spring animation will be used if any of the `stiffness`, `damping` or `mass` options are detected.
**Note:** A spring simulation is inherently numerical so if it's given a color, array or object, it runs the animation from `0` to `100` and interpolates that to the given values. This strategy is likely to be tweaked before the official release so animations made this way may change in feel.
##### to
A single value to animate to.
```javascript
animate({
to: 100,
type: "spring"
})
```
If `to` is an array, any defined `from` will be ignored.
##### stiffness
This defines the stiffness of the spring. A higher stiffness will result in a snappier animation.
Defaults to `100`
```javascript
animate({
to: 100,
stiffness: 1000
})
```
##### damping
This is the opposing force to `stiffness`. As you reduce this value, relative to `stiffness`, the spring will become bouncier and the animation will last longer. Likewise, higher relative values will have less bounciness and result in shorter animations.
Defaults to `10`
```javascript
animate({
to: 100,
damping: 50
})
```
##### mass
This is the mass of the animating object. Heavier objects will take longer to speed up and slow down.
Defaults to `1`.
```javascript
animate({
to: 100,
mass: 2
})
```
##### velocity
The initial velocity, in units per second, of the animation.
```javascript
animate({
to: 100,
velocity: 1000
})
```
##### duration
The duration of the spring, in milliseconds.
Will be overridden by `stiffness`, `mass` or `damping`.
```javascript
animate({
to: 100,
duration: 1000
})
```
##### bounce
The bounciness of the spring, as a value between `0` and `1`, where `0` is no bounce.
Will be overridden by `stiffness`, `mass` or `damping`.
```javascript
animate({
to: 100,
bounce: 0.2
})
```
##### restDelta
The distance from the animation target at which the animation can be considered complete. When both `restDelta` and `restSpeed` are met, the animation completes.
```javascript
animate({
to: 100,
restDelta: 0.5
})
```
##### restSpeed
The absolute velocity, in units per second, below which the animation can be considered complete. When both `restDelta` and `restSpeed` are met, the animation completes. Defaults to `10`.
```javascript
animate({
to: 100,
restSpeed: 5
})
```
#### Playback controls
`animate` returns `PlaybackControls`, which can be used to control the playback of the animation.
Currently this only includes a `stop` method, but may expand with more.
##### stop
Stops the animation.
```javascript
const playback = animate({ from: 0, to: 100 })
playback.stop()
```
### inertia
The `inertia` animation is used to gradually decelerate a number. Think smartphone scroll momentum.
#### Options
In addition to `animate`'s `from`, `onUpdate` and `onComplete` options, `inertia` also supports the following:
##### velocity
The initial velocity, in units per second, of the animation.
```javascript
inertia({
from: 0,
velocity: 100
})
```
##### power
A constant with which to calculate a target value. Higher power = further target.
Defaults to `0.8`.
```javascript
inertia({
from: 0,
power: 0.3
})
```
##### timeConstant
Adjusting the time constant will change the duration of the deceleration, thereby affecting its feel.
Defaults to `350`.
```javascript
inertia({
from: 0,
velocity: 100,
timeConstant: 400
})
```
##### modifyTarget
A function that receives the calculated target and returns a new one. Useful for snapping the target to a grid.
```javascript
const roundToNearest = target => v => Math.ceil(v / target) * target
inertia({
from: 0,
velocity: 100,
modifyTarget: roundToNearest(100)
})
```
##### min
The minimum value at which the animation will switch from gradual deceleration and use a spring animation to snap to this point.
```javascript
inertia({
from: 50,
velocity: -100,
min: 0
})
```
##### max
The maximum value at which the animation will switch from gradual deceleration and use a spring animation to snap to this point.
```javascript
inertia({
from: 50,
velocity: 100,
max: 100
})
```
##### bounceStiffness
This defines the stiffness of the spring when the animation hits either `min` or `max`. A higher stiffness will result in a snappier animation.
Defaults to `500`
```javascript
inertia({
from: 0,
velocity: 100,
max: 50,
bounceStiffness: 1000
})
```
##### bounceDamping
This is the opposing force to `bounceStiffness`. As you reduce this value, relative to `bounceStiffness`, the spring will become bouncier and the animation will last longer. Likewise, higher relative values will have less bounciness and result in shorter animations.
Defaults to `10`
```javascript
inertia({
from: 0,
velocity: 100,
max: 50,
bounceDamping: 300
})
```
##### restDelta
The distance from the animation target at which the animation can be considered complete.
```javascript
inertia({
from: 0,
velocity: 100,
restDelta: 0.5
})
```
### Iterators
Powering `animate` and `inertia` are the `keyframes`, `spring`, and `decay` [iterators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterator_protocol).
```javascript
import { keyframes, spring, decay } from "popmotion";
```
Iterators give you the ability to run an animation with a high degree of control. For example, [Framer](https://framer.com) uses the `spring` iterator to draw its animation editor visualiser by running it synchronously.
Each can be initialised with the matching options above (`decay` with a subset of `inertia`'s options, excluding the `bounce-` options):
```javascript
const animation = spring({
from: 0,
to: 100,
stiffness: 200
})
```
With the returned iterator, you can resolve the animation at a specific timestamp with its `next` method.
```javascript
// Resolve the animation at 200ms
const { value, done } = animation.next(200)
```
## Easing
Popmotion includes a number of in-built easing functions, as well as factory functions to make entirely new ones.
### Functions
Each easing function can be imported like so:
```javascript
import { linear } from "popmotion"
```
Each function accepts a progress value between `0` and `1`, and returns a new one:
```javascript
const progress = 0.5
const easedProgress = easeInOut(progress)
```
- `linear`
- `easeIn`
- `easeInOut`
- `easeOut`
- `circIn`
- `circInOut`
- `circOut`
- `backIn`
- `backInOut`
- `backOut`
- `anticipate`
- `bounceIn`
- `bounceInOut`
- `bounceOut`
### Factories
#### cubicBezier
```javascript
import { cubicBezier } from "popmotion"
const easing = cubicBezier(0, .42, 0, 1)
```
New cubic bezier definitions can be created in the [Framer](https://framer.com) animation editor and copy/pasted directly into this function.
#### steps
`steps` returns an easing function that will convert the animation into a discrete series of steps.
```javascript
import { steps } from "popmotion"
const easing = steps(5)
```
It optionally accepts a second parameter, either `"start"` or `"end"` (default)that decides whether the steps are aligned with the start or end of the animation.
```javascript
steps(5, "start")
```
#### mirrorEasing
Mirrors an existing easing function.
#### reverseEasing
Reverses an existing easing function. For instance, providing it `easeIn` would return an `easeOut`.
```javascript
import { reverseEasing, linear } from "popmotion"
const reversed = reverseEasing(linear)
reversed(1) // 0
reversed(0.5) // 0.5
reversed(0) // 1
```
#### createExpoIn
Creates an easing function based on the exponent of the provided `power`. The higher the `power`, the stronger the easing.
```javascript
import { createExpoIn } from "popmotion"
const expoIn = createExpoIn(4)
```
The returned easing function is an ease in, which means it starts slow and finished fast. `mirrorEasing` and `reverseEasing` can be used to create ease in out, and ease out variations:
```javascript
const expoIn = createExpoIn(4)
const expoOut = mirrorEasing(easeIn)
const expoInOut = reverseEasing(easeIn)
```
#### createBackIn
Creates an easing function with an overshoot. It accepts a `power` value, the higher the `power` the stronger the overshoot.
```javascript
import { createBackIn } from "popmotion"
const backIn = createBackIn(4)
```
The returned easing function is an ease in, which means the overshoot happens at the start of the animation. `mirrorEasing` and `reverseEasing` can be used to create ease in out, and ease out variations:
```javascript
const backIn = createBackIn(4)
const backOut = mirrorEasing(easeIn)
const backInOut = reverseEasing(easeIn)
```
#### createAnticipate
Creates an easing that pulls back a little before animating out with an overshoot. The stronger the `power` the bigger the overshoot.
```javascript
import { createAnticipate } from "popmotion"
const anticipate = createAnticipate(4)
```
## Utils
#### angle
Returns an angle between two points, in degrees.
```javascript
import { angle } from "popmotion"
angle(
{ x: 0, y: 0 },
{ x: 45, y: 100 }
)
```
#### attract
```javascript
import { attract } from "popmotion"
attract(5, 10, 12)
```
#### attractExpo
```javascript
import { attractExpo } from "popmotion"
attractExpo(5, 10, 12)
```
#### clamp
Clamp a value to within the given range.
```javascript
import { clamp } from "popmotion"
const min = 50
const max = 100
clamp(min, max, 150) // 100
```
#### degreesToRadians
Converts degrees to radians.
```javascript
import { degreesToRadians } from "popmotion"
degreesToRadians(45) // 0.785...
```
#### distance
Returns the distance between two numbers, two 2D points, or two 3D points.
```javascript
import { distance } from "popmotion"
distance(10, 50)
distance({ x: 0, y: 0 }, { x: 45, y: 100 })
distance({ x: 0, y: 0, z: 100 }, { x: 45, y: 100, z: 0 })
```
#### interpolate
Creates a function that will interpolate from an linear series of numbers, to a non-linear series of numbers, strings of the same numerical format, colours, or arrays/objects of those.
```javascript
import { interpolate } from "popmotion"
const mapXToOpacity = interpolate(
[-100, 0, 100],
[0, 1, 0]
)
mapXToOpacity(-50) // 0.5
const mapProgressToValues = interpolate(
[0, 1],
[
{ x: 0, color: "#fff" },
{ x: 100, color: "#000" }
]
)
mapProgressToValues(0.5) // { x: 50, color: "#888" }
const rescale = interpolate(
[0, 1],
[100, 200],
{ clamp: false }
)
rescale(2) // 300
```
#### Options
`interpolate` accepts an optional third argument, an object of options.
- `clamp`: Clamps values to within given range. Defaults to `true`.
- `ease`: An `Easing` function, or array of easing functions, to ease the interpolation of each segment.
- `mixer`: A function that, when provided a `from` and `to` value, will return a new function that accepts a progress value between `0` and `1` to mix between those two values. For integration with libraries like Flubber.
#### isPoint
Returns `true` if the provided argument is a 2D point.
```javascript
import { isPoint } from "popmotion"
isPoint({ x: 0 }) // false
isPoint({ x: 0, y: 0 }) // true
```
#### isPoint3D
Returns `true` if the provided argument is a 3D point.
```javascript
import { isPoint3D } from "popmotion"
isPoint3D({ x: 0 }) // false
isPoint3D({ x: 0, y: 0 }) // false
isPoint3D({ x: 0, y: 0, z: 0 }) // true
```
#### mix
Will mix between two values, given `progress` as a third argument.
```javascript
import { mix } from "popmotion"
mix(0, 100, 0.5) // 50
mix(0, 100, 2) // 200
```
#### mixColor
Returns a function that, when provided a `progress` value, will mix between two colors. Accepts hex, rgba and hsla colors.
```javascript
import { mixColor } from "popmotion"
mixColor("#000", "#fff")(0.5) // "rgba(125, 125, 125, 1)"
```
#### mixComplex
Returns a function that, when provided a `progress` value, will mix between two strings with the same order of numbers and colors.
```javascript
import { mixComplex } from "popmotion"
mixComplex("100px #fff", "0px #000")(0.5) // "50px rgba(125, 125, 125, 1)"
```
#### pointFromVector
Given a point, angle in degrees, and distance, will return a new point.
```javascript
import { pointFromVector } from "popmotion"
const point = { x: 0, y: 0 }
const angle = 45
const distance = 100
pointFromVector(point, angle, distance)
```
#### progress
Given a min and a max range, and a value, will return the `progress` of the value within the range as normalised to a `0`-`1` range.
```javascript
import { progress } from "popmotion"
const min = 100
const max = 200
progress(min, max, 150) // 0.5
```
#### radiansToDegrees
Converts radians to degrees.
```javascript
import { radiansToDegrees } from "popmotion"
radiansToDegrees(0.785) // 45
```
#### snap
Creates a function that will snap numbers to the nearest in a provided array or to a regular interval.
```javascript
import { snap } from "popmotion"
// Snap to regular intervals
const snapTo = snap(45);
snapTo(1); // 0
snapTo(40); // 45
snapTo(50); // 45
snapTo(80); // 90
// Snap to values in an array
const snapTo = snap([-100, -50, 100, 200]);
snapTo(-200); // -100
snapTo(-76); // -100
snapTo(-74); // -50
```
#### toDecimal
Rounds a number to a specific decimal place.
```javascript
import { toDecimal } from "popmotion"
toDecimal(3.3333); // 3.33
toDecimal(6.6666, 1); // 6.67
```
#### velocityPerFrame
```javascript
import { velocityPerFrame } from "popmotion"
velocityPerFrame(50, 16.7); // 0.835
```
#### velocityPerSecond
```javascript
import { velocityPerSecond } from "popmotion"
velocityPerSecond(1, 16.7); // 59.880...
```
#### wrap
```javascript
import { wrap } from "popmotion"
wrap(0, 1, 0.5); // 0.5
wrap(0, 1, 1.5); // 0.5
```
================================================
FILE: lerna.json
================================================
{
"lerna": "3.0.6",
"version": "independent",
"packages": ["packages/*"],
"npmClient": "yarn",
"useWorkspaces": true
}
================================================
FILE: package.json
================================================
{
"private": true,
"name": "popmotion-packages",
"author": "Matt Perry",
"homepage": "https://popmotion.io",
"scripts": {
"bootstrap": "lerna bootstrap",
"build": "cd packages/style-value-types && yarn build && cd ../framesync && yarn build && cd ../popmotion",
"playground": "start-storybook -s ./storybook-static -p 6006",
"build-playground": "build-storybook",
"clean": "lerna clean --yes && rm -rf node_modules",
"clear": "yarn clean && rm yarn.lock",
"test": "lerna run test"
},
"devDependencies": {
"@rollup/plugin-node-resolve": "^7.0.0",
"@rollup/plugin-replace": "^2.3.0",
"@storybook/react": "^3.2.13",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
"babel-eslint": "^5.0.4",
"babel-loader": "^6.0.1",
"babel-plugin-annotate-pure-calls": "^0.2.2",
"babel-plugin-root-import": "^5.1.0",
"babel-plugin-transform-export-extensions": "^6.4.0",
"babel-plugin-transform-react-constant-elements": "^6.9.1",
"babel-plugin-transform-react-jsx": "^6.24.1",
"babel-plugin-transform-react-remove-prop-types": "^0.2.6",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.6.1",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-0": "^6.24.1",
"babel-preset-stage-2": "^6.17.0",
"babel-register": "^6.3.13",
"eslint": "^3.19.0",
"eslint-plugin-flowtype": "^2.30.0",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-jasmine": "2.2.0",
"eslint-plugin-jsx-a11y": "^4.0.0",
"eslint-plugin-react": "^6.10.0",
"estraverse-fb": "^1.3.1",
"husky": "^1.1.2",
"jest": "^24.0.0",
"jest-cli": "^24.0.0",
"jest-diff": "^24.0.0",
"lerna": "^3.0.6",
"lint-staged": "^7.3.0",
"prettier": "^2.1.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"rollup": "^2.40.0",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-typescript2": "^0.30.0",
"string-replace-loader": "^1.3.0",
"styled-components": "^4.1.1",
"ts-jest": "^22.4.6",
"tslint": "^5.11.0",
"tslint-config-prettier": "^1.15.0",
"tslint-react": "^4.1.0",
"typescript": "^4.7",
"webpack": "^3.0.0"
},
"workspaces": {
"packages": [
"packages/*"
],
"nohoist": [
"gatsby"
]
},
"resolutions": {
"jest": "24.2.0-alpha.0",
"babel-jest": "^22.4.3",
"tslib": "2.4.0"
},
"prettier": {
"parser": "typescript",
"singleQuote": true
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{ts,tsx}": [
"prettier --write",
"git add"
]
},
"version": "10.1.0"
}
================================================
FILE: packages/blend-tweens/blend-tweens.js
================================================
import tween from './tween';
import { linear } from '../inc/easing';
import { getProgressFromValue, getValueFromProgress } from '../inc/calc';
import { flow, clamp, bezier } from '../inc/transformers';
const clampProgress = clamp(0, 1);
function calcValueAtTime(from, to, duration, elapsed, ease) {
const progressAtTime = ease(clampProgress(getProgressFromValue(0, duration, elapsed)));
return getValueFromProgress(from, to, progressAtTime);
}
export default ({ from, to, onUpdate, accuracy = 60, ...props }) => {
// Get tween properties
const a = from;
const b = to;
const aCurrent = a.get();
const aDuration = a.getProp('duration');
const bDuration = b.getProp('duration');
const aEase = a.getProp('ease');
const bEase = b.getProp('ease');
const aFrom = a.getProp('from');
const bFrom = b.getProp('from');
const aTo = a.getProp('to');
const bTo = b.getProp('to');
// Analyse tweens
const overlapDuration = Math.min(aDuration - a.getElapsed(), bDuration);
const bValueAtTweenOverlapComplete = calcValueAtTime(bFrom, bTo, bDuration, overlapDuration, bEase);
const bStartsHigherThanA = (bFrom > aCurrent);
const bEndsHigherThanA = (bValueAtTweenOverlapComplete > aTo);
// Blend points are defined as [t = time, v = valueAtTime]
// P1
// The start of the tween blend
const P1 = aCurrent;
const blendPoints = [P1];
// Find P2
// The possible intersection point between the two tweens
const tweensIntersect = (bStartsHigherThanA !== bEndsHigherThanA);
if (tweensIntersect) {
let timestep = overlapDuration / accuracy;
for (let i = 0; i < accuracy; i++) {
const runningTime = i * timestep;
const aValueAtTime = calcValueAtTime(aFrom, aTo, aDuration, a.elapsed + runningTime, aEase);
const bValueAtTime = calcValueAtTime(bFrom, bTo, bDuration, b.elapsed + runningTime, bEase);
const hasIntersected = (
(bStartsHigherThanA && aValueAtTime > bValueAtTime) ||
(!bStartsHigherThanA && aValueAtTime < bValueAtTime)
);
if (hasIntersected) {
const P2 = bValueAtTime;
blendPoints.push(P2);
break;
}
}
}
// P3
// The points the two tweens stop overlapping
const P3 = bValueAtTweenOverlapComplete;
blendPoints.push(P3);
// Push the end state of b tween as final control point
const P4 = bTo;
blendPoints.push(P4);
return tween({
...props,
duration: bDuration,
ease: linear,
onUpdate: flow(
bezier(blendPoints),
onUpdate
)
});
};
================================================
FILE: packages/blend-tweens/cross-fade.js
================================================
import Action from './';
import tween from './tween';
import { linear } from '../inc/easing';
import { getValueFromProgress } from '../inc/calc';
class CrossFade extends Action {
static defaultProps = {
ease: linear
}
onStart() {
const { duration, ease, fader } = this.props;
this.fader = fader || tween({
to: 1,
duration,
ease
}).start();
}
update() {
const { from, to } = this.props;
const balance = this.fader.get();
const latestFromValue = from.get();
const latestToValue = to.get();
return getValueFromProgress(latestFromValue, latestToValue, balance);
}
}
export default (props) => new CrossFade(props);
================================================
FILE: packages/framesync/CHANGELOG.md
================================================
# Changelog
Framesync adheres to [Semantic Versioning](http://semver.org/).
## [6.1.2] 2022-08-15
### Update
- `tslib` and `typescript`.
## [6.1.1] 2022-08-10
### Update
- Adding `types` to `exports` field.
## [6.1.0] 2021-11-24
### Update
- Updating `tslib`.
## [6.0.1] 2021-10-22
### Fixed
- Fixing bug where `flushSync` being called from an existing process would boot keep-alive processes off the thread.
## [6.0.0] 2021-09-23
### Fixed
- Fixing `exports` and `module` in `package.json`. This will break (unsupported) direct file imports.
## [5.3.0] 2021-03-30
### Added
- Adding `flushSync` API for manual flushing of job queues.
## [5.2.3] 2021-03-19
### Fixed
- Fixing `main` entry point.
## [5.2.2] 2021-03-19
### Fixed
- Fixing `main` entry point.
## [5.2.1] 2021-03-19
### Added
- Adding `exports` to `package.json`.
### Updated
- `tslib` to latest.
## [5.2.0] 2021-03-01
### Fixed
- Unbundling ES code to facilitate code-splitting in Webpack.
## [5.1.0] 2021-02-22
### Fixed
- Adding polyfill for `performance.now` for better compatibility with Node environments.
## [5.0.0] 2021-01-01
### Changed
- Using `performance.now` to measure polyfilled elapsed time.
## [4.1.0] 2020-8-24
### Added
- `preRender` step.
## [4.0.2] 2019-02-05
### Fixed
- Fixing rescheduling keepAlive method.
## [4.0.1] 2018-09-24
### Changed
- Updated README.
## [4.0.0] 2018-09-24
### Changed
- New API.
- `onFrameUpdate(callback, immediate)` -> `sync.update(callback, keepAlive, immediate)`
- `cancelOnFrameUpdate(callback)` -> `cancelSync.update(callback)`
### Added
- `keepAlive` parameter.
## [3.1.9] 2018-05-16
### Fixed
- Fixing Rollup config.
## [3.1.8] 2018-05-13
### Added
- Rollup support for outputting ES modules and UMD bundles.
## [3.1.7] 2018-01-04
### Fixed
- Fixing illegal invocation errors.
## [3.1.6] 2018-01-04
### Changed
- Using previous frame duration as default duration (for instance between active cycles).
## [3.1.5] 2018-01-04
### Changed
- Cleaning polyfill.
## [3.1.4] 2018-01-04
### Changed
- Max permitted time elapsed is now 40ms to permit 30fps max.
- When `startRenderLoop` is fired, and the loop is not active, we set a new `currentTime`.
## [3.1.3] 2017-11-08
### Fixed
- Actually pointing to new declaration file.
## [3.1.2] 2017-11-08
### Fixed
- Pointing to new declaration file.
## [3.1.1] 2017-11-08
### Fixed
- Automatically exporting declaration file.
## [3.1.0] 2017-11-08
### Added
- Added optional `true` flag to `schedule`. This will schedule a job to run at the end of the current frame step.
## [3.0.0] 2017-08-28
- `currentFrameTimestamp` becomes `currentFrameTime` for symmetry with `currentTime`.
## [2.0.1] 2017-08-26
### Added
- Changelog and Readme.
## [2.0.0] 2017-08-26
### Added
- First publish.
================================================
FILE: packages/framesync/LICENSE.md
================================================
MIT License
Copyright © 2019 Framer BV
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: packages/framesync/README.md
================================================
# Framesync
A tiny frame scheduler for performantly batching reads, updates and renders.
Segregating actions that read and write to the DOM will avoid [layout thrashing](https://developers.google.com/web/fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing).
It's also a way of ensuring order of execution across a frame. For instance, [Framer Motion](https://github.com/framer/motion) batches animations on the `update` step, and renders on the `render` step, allowing independent animation of `transform` properties.
## Install
```bash
npm install framesync
```
## Usage
Framesync splits a frame into discrete `read`, `update`, `preRender`, `render` and `postRender` steps.
### Scheduling functions
Functions can be scheduled to different parts of the render loop with `sync`.
```javascript
import sync from 'framesync';
```
It provides four functions, one for scheduling a function to run on each part of the frame:
```javascript
sync.update(() => {});
```
### Frame data
Each function is provided data about the current frame:
```javascript
sync.update(({ delta, timestamp }) => {});
```
- `delta`: Time since last frame (in milliseconds)
- `timestamp`: Timestamp of the current frame.
This object is recycled across frames, so values should be destructured if intended to be used asynchronously.
### Keep alive
We can run a function as an ongoing process by passing `true` as the second parameter:
```javascript
let count = 0;
sync.update(() => count++, true);
```
This will keep the process running until it's actively cancelled.
### Run immediately
The third parameter, `immediate`, can be used to sync a function on the **current frame step**.
By default, Framesync will schedule functions to run the next time that frame step is fired:
```javascript
sync.update(({ timestamp }) => {
// The following function will run on the subsequent frame:
sync.update((frame) => frame.timestamp !== timestamp);
});
```
By setting `immediate` to `true`, we can add this at the end of the current step:
```javascript
sync.update(({ timestamp }) => {
// The following function will run on the **current** frame:
sync.update(
(frame) => frame.timestamp === timestamp,
false,
true
);
});
```
### Cancelling
Synced processes can be cancelled with the `cancelSync` function:
```javascript
import sync, { cancelSync } from 'framesync';
let count = 0;
const process = sync.render(() => {
count++;
if (count >= 10) cancelSync.render(process);
}, true);
```
================================================
FILE: packages/framesync/package.json
================================================
{
"name": "framesync",
"license": "MIT",
"version": "6.1.2",
"description": "A frame-synced render loop for JavaScript",
"author": "Matt Perry",
"homepage": "https://popmotion.io",
"main": "dist/framesync.cjs.js",
"types": "lib/index.d.ts",
"module": "dist/es/index.mjs",
"jsnext:main": "dist/es/index.mjs",
"unpkg": "./dist/framesync.min.js",
"exports": {
".": {
"types": "./lib/index.d.ts",
"import": "./dist/es/index.mjs",
"require": "./dist/framesync.cjs.js",
"default": "./dist/framesync.cjs.js"
},
"./package.json": "./package.json"
},
"scripts": {
"build": "tsc -p . && rollup -c && yarn measure",
"watch": "rollup -c -w",
"lint": "tslint -c tslint.json 'src/**/*.{ts}'",
"test": "jest",
"measure": "gzip -c dist/framesync.min.js | wc -c",
"prepublishOnly": "npm run test && npm run build"
},
"files": [
"lib",
"dist"
],
"repository": {
"type": "git",
"url": "git+https://github.com/Popmotion/popmotion.git"
},
"keywords": [
"animation",
"raf"
],
"bugs": {
"url": "https://github.com/Popmotion/popmotion/issues"
},
"jest": {
"moduleFileExtensions": [
"ts",
"js"
],
"transform": {
"\\.(ts)$": "../../../node_modules/ts-jest/preprocessor.js"
},
"testRegex": "/_tests/.*\\.(ts|js)$",
"rootDir": "src"
},
"prettier": {
"printWidth": 80,
"tabWidth": 4,
"semi": false,
"trailingComma": "es5"
},
"dependencies": {
"tslib": "2.4.0"
}
}
================================================
FILE: packages/framesync/rollup.config.js
================================================
import generateConfig from '../../rollup-generate-config';
import pkg from './package.json';
export default generateConfig(pkg);
================================================
FILE: packages/framesync/src/_tests/test.ts
================================================
import sync, { cancelSync, flushSync } from "../"
import { onNextFrame } from "../on-next-frame"
describe("onNextFrame", () => {
it("fires callback on following frame", () => {
return new Promise((resolve) => onNextFrame(resolve))
})
})
describe("sync", () => {
it("fires callbacks in the correct order", () => {
return new Promise<void>((resolve, reject) => {
const order: number[] = []
sync.read(() => order.push(0))
sync.update(() => order.push(1))
sync.preRender(() => order.push(2))
sync.render(() => order.push(3))
sync.postRender(() => {
order.push(4)
if (
order[0] === 0 &&
order[1] === 1 &&
order[2] === 2 &&
order[3] === 3 &&
order[4] === 4
) {
resolve()
} else {
reject(order)
}
})
})
})
it("cancels callbacks", () => {
return new Promise<void>((resolve, reject) => {
let hasFired = false
const process = sync.render(() => (hasFired = true))
sync.update(() => cancelSync.render(process))
sync.postRender(() => (hasFired ? reject(hasFired) : resolve()))
})
})
it("fires callback on current frame if scheduled with `true` within the same step", () => {
return new Promise<number | string | void>((resolve, reject) => {
let v = 0
sync.update(({ timestamp: prevTimestamp }) => {
v++
sync.update(
({ timestamp }) => {
v++
if (timestamp !== prevTimestamp) {
reject(`${timestamp} ${prevTimestamp}`)
}
},
false,
true
)
})
sync.render(() => (v === 2 ? resolve() : reject(v)))
})
})
it("fires callback on next frame if scheduled with `true` outside the same step", () => {
return new Promise((resolve: Function, reject: Function) => {
let v = 0
sync.update(() => v++)
sync.update(() => v++, false, true)
sync.render(() => (v === 2 ? resolve() : reject()))
})
})
it("uses default elapsed time if first fire", () => {
return new Promise((resolve: Function, reject: Function) => {
sync.update(({ delta: defaultElapsed }) => {
setTimeout(
() =>
sync.update(({ delta }) =>
delta === defaultElapsed
? resolve()
: reject(defaultElapsed, delta)
),
50
)
})
})
})
it("correctly cancels", () => {
return new Promise<void>((resolve, reject) => {
const callback = () => reject()
sync.read(() => cancelSync.update(callback))
sync.update(callback)
sync.render(() => resolve())
})
})
it("correctly keeps alive", () => {
return new Promise<void>((resolve) => {
let v = 0
sync.update(() => v++, true)
sync.render(() => v === 2 && resolve(), true)
})
})
it("correctly cancels a keepAlive process", () => {
return new Promise<number[] | void>((resolve, reject) => {
let updateCount = 0
let renderCount = 0
const update = sync.update(() => {
updateCount++
if (updateCount === 4) cancelSync.update(update)
}, true)
sync.render(() => {
renderCount++
if (renderCount === 6) {
if (renderCount !== updateCount) {
resolve()
} else {
reject([renderCount, updateCount])
}
}
}, true)
})
})
it("correctly keeps alive after a flush", async () => {
const promise = new Promise<boolean>((resolve) => {
let v = 0
sync.update(() => {
if (v === 2) flushSync.update()
}, true)
sync.update(() => {
v++
if (v > 6) resolve(true)
}, true)
})
flushSync.update()
return expect(promise).resolves.toBe(true)
})
})
================================================
FILE: packages/framesync/src/create-render-step.ts
================================================
import { Step, Process } from "./types"
export function createRenderStep(runNextFrame: () => void): Step {
/**
* We create and reuse two arrays, one to queue jobs for the current frame
* and one for the next. We reuse to avoid triggering GC after x frames.
*/
let toRun: Process[] = []
let toRunNextFrame: Process[] = []
/**
*
*/
let numToRun = 0
/**
* Track whether we're currently processing jobs in this step. This way
* we can decide whether to schedule new jobs for this frame or next.
*/
let isProcessing = false
let flushNextFrame = false
/**
* A set of processes which were marked keepAlive when scheduled.
*/
const toKeepAlive = new WeakSet<Process>()
const step: Step = {
/**
* Schedule a process to run on the next frame.
*/
schedule: (callback, keepAlive = false, immediate = false) => {
const addToCurrentFrame = immediate && isProcessing
const buffer = addToCurrentFrame ? toRun : toRunNextFrame
if (keepAlive) toKeepAlive.add(callback)
// If the buffer doesn't already contain this callback, add it
if (buffer.indexOf(callback) === -1) {
buffer.push(callback)
// If we're adding it to the currently running buffer, update its measured size
if (addToCurrentFrame && isProcessing) numToRun = toRun.length
}
return callback
},
/**
* Cancel the provided callback from running on the next frame.
*/
cancel: (callback) => {
const index = toRunNextFrame.indexOf(callback)
if (index !== -1) toRunNextFrame.splice(index, 1)
toKeepAlive.delete(callback)
},
/**
* Execute all schedule callbacks.
*/
process: (frameData) => {
/**
* If we're already processing we've probably been triggered by a flushSync
* inside an existing process. Instead of executing, mark flushNextFrame
* as true and ensure we flush the following frame at the end of this one.
*/
if (isProcessing) {
flushNextFrame = true
return
}
isProcessing = true
// Swap this frame and the next to avoid GC
;[toRun, toRunNextFrame] = [toRunNextFrame, toRun]
// Clear the next frame list
toRunNextFrame.length = 0
// Execute this frame
numToRun = toRun.length
if (numToRun) {
for (let i = 0; i < numToRun; i++) {
const callback = toRun[i]
callback(frameData)
if (toKeepAlive.has(callback)) {
step.schedule(callback)
runNextFrame()
}
}
}
isProcessing = false
if (flushNextFrame) {
flushNextFrame = false
step.process(frameData)
}
},
}
return step
}
================================================
FILE: packages/framesync/src/index.ts
================================================
import { onNextFrame, defaultTimestep } from "./on-next-frame"
import { createRenderStep } from "./create-render-step"
import {
Process,
StepId,
FrameData,
CancelSync,
FlushSync,
Sync,
Steps,
} from "./types"
const maxElapsed = 40
let useDefaultElapsed = true
let runNextFrame = false
let isProcessing = false
const frame = {
delta: 0,
timestamp: 0,
}
const stepsOrder: StepId[] = [
"read",
"update",
"preRender",
"render",
"postRender",
]
const steps = stepsOrder.reduce((acc, key) => {
acc[key] = createRenderStep(() => (runNextFrame = true))
return acc
}, {} as Steps)
const sync = stepsOrder.reduce((acc, key) => {
const step = steps[key]
acc[key] = (process: Process, keepAlive = false, immediate = false) => {
if (!runNextFrame) startLoop()
return step.schedule(process, keepAlive, immediate)
}
return acc
}, {} as Sync)
const cancelSync = stepsOrder.reduce((acc, key) => {
acc[key] = steps[key].cancel
return acc
}, {} as CancelSync)
const flushSync = stepsOrder.reduce((acc, key) => {
acc[key] = () => steps[key].process(frame)
return acc
}, {} as FlushSync)
const processStep = (stepId: StepId) => steps[stepId].process(frame)
const processFrame = (timestamp: number) => {
runNextFrame = false
frame.delta = useDefaultElapsed
? defaultTimestep
: Math.max(Math.min(timestamp - frame.timestamp, maxElapsed), 1)
frame.timestamp = timestamp
isProcessing = true
stepsOrder.forEach(processStep)
isProcessing = false
if (runNextFrame) {
useDefaultElapsed = false
onNextFrame(processFrame)
}
}
const startLoop = () => {
runNextFrame = true
useDefaultElapsed = true
if (!isProcessing) onNextFrame(processFrame)
}
const getFrameData = () => frame
export default sync
export { cancelSync, flushSync, getFrameData, FrameData, Process }
================================================
FILE: packages/framesync/src/on-next-frame.ts
================================================
/*
Detect and load appropriate clock setting for the execution environment
*/
export const defaultTimestep = (1 / 60) * 1000
const getCurrentTime =
typeof performance !== "undefined"
? () => performance.now()
: () => Date.now()
export const onNextFrame =
typeof window !== "undefined"
? (callback: FrameRequestCallback) =>
window.requestAnimationFrame(callback)
: (callback: FrameRequestCallback) =>
setTimeout(() => callback(getCurrentTime()), defaultTimestep)
================================================
FILE: packages/framesync/src/types.ts
================================================
export type FrameData = {
delta: number
timestamp: number
}
export type Process = (data: FrameData) => void
export type Schedule = (
process: Process,
keepAlive?: boolean,
immediate?: boolean
) => Process
export interface Step {
schedule: Schedule
cancel: (process: Process) => void
process: (frame: FrameData) => void
}
export type StepId =
| "read"
| "update"
| "postUpdate"
| "preRender"
| "render"
| "postRender"
export type Sync = {
[key in StepId]: Schedule
}
export type Steps = {
[key in StepId]: Step
}
export type CancelSync = {
[key in StepId]: (process: Process) => void
}
export type FlushSync = {
[key in StepId]: () => void
}
================================================
FILE: packages/framesync/tsconfig.json
================================================
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"declarationDir": "lib",
"rootDir": "src",
"outDir": "lib"
},
"include": ["src/**/*"]
}
================================================
FILE: packages/popcorn/docs/api/utilities/angle.md
================================================
---
title: angle
description: Returns the angle between two 2D points.
category: functions
---
# `angle`
`angle` returns the angle between two 2D points, in degrees.
<TOC />
## Import
```javascript
import { angle } from '@popmotion/popcorn';
```
## Usage
```javascript
angle(
{ x: 0, y: 0 },
{ x: 0, y: 20 }
) // 90
```
## Types
```typescript
type Point2D = {
x: number;
y: number;
}
angle(a: Point2D, b: Point2D): number
```
================================================
FILE: packages/popcorn/docs/api/utilities/apply-offset.md
================================================
---
title: applyOffset
description: Creates a function that measures the offset of incoming values and applies it to an initial value.
category: functions
---
# `applyOffset`
`applyOffset` creates a function that measures the offset of any given value from the initial `from`, and applies it to `to`.
<TOC />
## Import
```javascript
import { applyOffset } from '@popmotion/popcorn';
```
## Usage
`applyOffset` can be used both when you know the initial value you want to measure the offset from, and when you don't.
### With an initial value
```javascript
applyOffset(100, 0)(101) // 1
```
### Without an initial value
If we don't provide an initial `from` value, the first value we call the returned function will be considered `from` and apply `to` with a delta of `0`.
```javascript
const applyPointerMovementToX = applyOffset(x);
applyPointerMovement(100); // x
applyPointerMovement(120); // x + 20
```
## Types
```typescript
applyOffset(from: number, to: number): (v: number) => number;
applyOffset(to: number): (v: number) => number;
```
================================================
FILE: packages/popcorn/docs/api/utilities/clamp.md
================================================
---
title: clamp
description: Restricts a number to within the defined range.
category: functions
---
# `clamp`
`clamp` restricts a number to within the given range.
<TOC />
## Import
```javascript
import { clamp } from '@popmotion/popcorn';
```
## Usage
Clamp accepts a `min` and `max` value.
If a third value is provided, it returns a number that is clamped within that given range:
```javascript
clamp(100, 200, 99); // 100
clamp(100, 200, 201); // 200
```
If only a range is provided, it returns a function. When that function is provided a number, it returns a new number that is clamped within the defined range:
```javascript
const restrictOpacity = clamp(0, 1);
restrictOpacity(-1); // 0
```
## Types
```typescript
clamp(min: number, max: number, v: number) => number;
clamp(min: number, max: number) => (v: number) => number;
```
================================================
FILE: packages/popcorn/docs/api/utilities/conditional.md
================================================
---
title: conditional
description: Creates a function that conditionally transforms provided values.
category: functions
---
# `conditional`
`conditional` is used to create a function that will conditionally transform incoming values.
<TOC />
## Import
```javascript
import { conditional } from '@popmotion/popcorn';
```
## Usage
`conditional` is provided a `check` and `transform` function, and returns a new function.
This function, when provided a value, will provide it to `check`.
If `check` returns `true`, it will return the value as transformed by `transform`. If `false`, it will return the value.
```javascript
const conditionallyDouble = conditional(
v => v > 5,
v => v * 2
);
conditionallyDouble(4); // 4
conditionallyDouble(6); // 12
```
## Types
```typescript
type Check = (v: any) => boolean;
type Apply = (v: any) => any;
conditional(check: Check, transform: Apply) => (v: any) => any;
```
================================================
FILE: packages/popcorn/docs/api/utilities/degreesToRadians.md
================================================
---
title: degreesToRadians
description: Converts degrees to radians.
category: functions
---
# `degreesToRadians`
`degreesToRadians` converts degrees to radians.
<TOC />
## Import
```javascript
import { degreesToRadians } from '@popmotion/popcorn';
```
## Usage
```javascript
degreesToRadians(45) // 0.785...
```
## Types
```typescript
degreesToRadians(degrees: number): number;
```
================================================
FILE: packages/popcorn/docs/api/utilities/distance.md
================================================
---
title: distance
description: Calculate the distance between two n-dimensional points.
category: functions
---
# `distance`
`distance` calculates the distance between two n-dimensional points.
<TOC />
## Import
```javascript
import { distance } from '@popmotion/popcorn';
```
## Usage
### 1D points
Provide two numbers to measure the distance between them.
```javascript
distance(-100, 100); // 200
```
### 2D and 3D points
Provide two `Point` values, with `x`, `y` and optionally `z` numbers, to measure the distance between them.
```javascript
distance(
{ x: 0, y: 0, z: 0 },
{ x: 0, y: 0, z: 10 }
); // 10
```
## Types
```typescript
type Point = {
x: number;
y: number;
z?: number;
}
distance(a: number | Point, b: number | Point): number
```
================================================
FILE: packages/popcorn/docs/api/utilities/interpolate.md
================================================
---
title: interpolate
description: Map from a series of numbers to a range of numbers, colors or strings.
category: functions
---
# `interpolate`
Using an `input` range of sequential numbers, and an `output` range of numbers or colors, `interpolate` will create a function that maps a number from the `input` range to the `output`.
<TOC />
## Import
```javascript
import { interpolate } from '@popmotion/popcorn';
```
## Usage
`interpolate` can map from an `input` array of sequential numbers like this:
```javascript
[0, 1, 2]
```
To an array of **either** numbers, colors, or strings containing one or more numbers or colors.
The two arrays must be the **same length**.
### Numbers
```javascript
const mapper = interpolate(
[-100, -50, 50, 100],
[0, 1, 1, 0]
);
mapper(-200); // 0
mapper(-75); // 0.5
mapper(50); // 1
```
### Colors
`interpolate` can map to hex, RGB(A) or HSL(A) colors.
**Note:** Hex numbers will be output as RGBA.
```javascript
const mapper = interpolate(
[0, 50, 100],
['#fff', '#f00', '#000']
);
mapper(25); // rgba(255, 128, 128, 1)
mapper(50); // rgba(255, 0, 0, 1)
mapper(75); // rgba(128, 0, 0, 1)
```
### Strings
`interpolate` can maps to complex value types that include multiple numbers or colors.
Every string in the `output` range must be of the exact same format.
```javascript
const mapper = interpolate(
[0, 1, 2],
[
'20px, rgba(0, 0, 0, 0)',
'10px, rgba(255, 255, 255, 1)',
'40px, rgba(100, 100, 100, 0.5)'
]
);
mapper(0.5); // '15px, rgba(128, 128, 128, 0.5)'
```
## Options
`interpolate` takes an optional third argument, options. This is an object that may contain the following configurations:
### Clamp
Clamp values to within the provided ranges.
Default: `true`.
```javascript
interpolate([0, 1], [0, 100])(2) // 100
interpolate([0, 1], [0, 100], { clamp: false })(2) // 200
```
### Ease
Default: `linear`
An easing function, or list of easing functions, to apply to every transition.
If defined as an array, it must be the `input.length - 1`, as it applies to the transitions **between** the defined values.
```javascript
interpolate(
[0, 100, 200],
['#fff', '#500', '#000'],
{ ease: [linear, easeOut] }
)
```
## Types
```typescript
interpolate(
input: number[],
output: string[] | number[],
options: InterpolateOptions
): string | number;
type InterpolateOptions = {
clamp?: boolean = true,
ease?: Easing | Easing[]
};
type Easing = v => v;
```
================================================
FILE: packages/popcorn/docs/api/utilities/is-point-3d.md
================================================
---
title: isPoint3D
description: Test a value for x, y and z properties.
category: functions
---
# `isPoint3D`
Returns `true` if the provided value has an `x`, `y` and `z` properties.
<TOC />
## Import
```javascript
import { isPoint3D } from '@popmotion/popcorn';
```
## Usage
```javascript
isPoint3D(0); // false
isPoint3D({ x: 0, y: 0 }); // false
isPoint3D({ x: 0, y: 0, z: 0 }); // true
```
## Types
```typescript
isPoint3D(v: any): boolean;
```
================================================
FILE: packages/popcorn/docs/api/utilities/is-point.md
================================================
---
title: isPoint
description: Test a value for an `x` and `y` property.
category: functions
---
# `isPoint`
Returns `true` if the provided value has an `x` and `y` property.
<TOC />
## Import
```javascript
import { isPoint } from '@popmotion/popcorn';
```
## Usage
```javascript
isPoint(0); // false
isPoint({ x: 0, y: 0 }); // true
```
## Types
```typescript
isPoint(v: any): boolean;
```
================================================
FILE: packages/popcorn/docs/api/utilities/mix-array.md
================================================
---
title: mixArray
description: Creates a function that can interpolate between two arrays of matching value types.
category: functions
---
# `mixArray`
`mixArray` creates a function that can interpolate between two arrays of matching value types.
Values can be any number, color, or a string containing multiple numbers or colors.
<TOC />
## Import
```javascript
import { mixArray } from '@popmotion/popcorn';
```
## Usage
`mixArray` accepts two arrays, a `from` and `to` array.
The values in each can be:
- Number
- Hex color
- RGB(A) color
- HSL(A) color
- String containing one or more of the above types
It returns a function that can be used to interpolate between the two arrays using a value between `0-1`.
```javascript
const mixer = mixArray(
[0, '60px', '#fff'],
[100, '-60px', '#000']
)
mixer(0.5) // [50, '0px', 'rgba(128, 128, 128, 1)']
```
**Note:** Colors, if defined as hex values, will be returned as rgba.
## Types
```typescript
type Mixable = Array<Number | String>;
mixArray(from: Mixable, to: Mixable): Mixable
```
================================================
FILE: packages/popcorn/docs/api/utilities/mix-color.md
================================================
---
title: mixColor
description: Creates a function that can interpolate between two hex, rgba or hsla colors.
category: functions
---
# `mixColor`
`mixColor` creates a function that can interpolate between two hex, rgba or hsla colors.
Hex and RGBA colors are mixed using linear color space blending which avoids brightness dips. [Learn more](https://www.youtube.com/watch?v=LKnqECcg6Gw).
<TOC />
## Import
```javascript
import { mixColor } from '@popmotion/popcorn';
```
## Usage
`mixColor` accepts two colors, either hex/RGB(A), or HSL(A).
It returns a function that can be used to interpolate between the two colors using a value between `0-1`.
```javascript
const mixer = mixColor('#f00', '#0f0');
mixer(0.5) // 'rgba(128, 128, 0, 1)'
```
**Note:** Colors, if defined as hex values, will be returned as rgba.
## Types
```typescript
mixColor(from: string, to: string) => (v: number) => string
```
================================================
FILE: packages/popcorn/docs/api/utilities/mix-complex.md
================================================
---
title: mixComplex
description: Creates a function that can mix between two strings that contain one or more numbers and/or colors.
category: functions
---
# `mixComplex`
Creates a function that can mix between two strings that contain one or more numbers and/or colors.
Hex and RGBA colors are mixed using linear color space blending which avoids brightness dips. [Learn more](https://www.youtube.com/watch?v=LKnqECcg6Gw).
<TOC />
## Import
```javascript
import { mixComplex } from '@popmotion/popcorn';
```
## Usage
`mixComplex` can be used to animate any string in which numbers or colors are detected.
As simple as single unit types:
```javascript
const mixer = mixComplex('10px', '20px');
mixer(0.5); // '15px'
```
Or strings containing multiple numbers and colors:
```javascript
const mixer = mixComplex(
'0px 0px auto rgba(0, 0, 0, 0)',
'5px 5px auto rgba(0, 0, 0, 0.5)'
);
mixer(0.5); // '2.5px 2.5px auto rgba(0, 0, 0, 0.25)'
```
**Note:** The non-numerical portions of the string must be the same in both `from` and `to` values.
## Types
```typescript
mixColor(from: string, to: string) => (v: number) => string
```
================================================
FILE: packages/popcorn/docs/api/utilities/mix.md
================================================
---
title: mix
description: Mixes between two numbers
category: functions
---
# `mix`
`mix` can interpolate between two numbers.
<TOC />
## Import
```javascript
import { mix } from '@popmotion/popcorn';
```
## Usage
```javascript
mix(0, 100, 0.5); // 50
mix(0, 100, 1); // 100
mix(0, 100, 2); // 200
```
## Types
```typescript
mix(from: number, to: number, progress: number): number
```
================================================
FILE: packages/popcorn/docs/api/utilities/pipe.md
================================================
---
title: pipe
description: Left-to-right function composition.
category: functions
---
# `pipe`
`pipe` composes a new function out of a series of provided functions.
When this new function is provided a value, it will run this value through the provided functions in left-to-right order.
This provides a way of composing logic from simpler, reusable functions.
<TOC />
## Import
```javascript
import { pipe } from '@popmotion/popcorn';
```
## Usage
```javascript
const double = v => v * 2;
const add = toAdd => v => v + toAdd;
const negative = v => -v;
const func = pipe(double, add(1), negative);
func(2); // -5
```
## Types
```typescript
pipe(...funcs: Function): Function
```
================================================
FILE: packages/popcorn/docs/api/utilities/point-from-vector.md
================================================
---
title: pointFromVector
description: Calculates a point, given a point and vector (angle and distance)
category: functions
---
# `pointFromVector`
`pointFromVector` takes a point, an angle (in degrees), and a distance, and returns a new point.
<TOC />
## Import
```javascript
import { pointFromVector } from '@popmotion/popcorn';
```
## Usage
```javascript
pointFromVector({ x: 0, y: 0 }, 45, 100);
// { x: 70.710..., y: 70.710... }
```
## Types
```typescript
type Point = {
x :number;
y: number;
};
pointFromVector(origin: Point, angle: number, distance: number): Point
```
================================================
FILE: packages/popcorn/docs/api/utilities/progress.md
================================================
---
title: progress
description: Calculates the progress of a value between in a given range.
category: functions
---
# `progress`
`progress` returns the progress of a value in a given range.
Progress is represented as a number between `0` and `1`, but is unclamped.
<TOC />
## Import
```javascript
import { progress } from '@popmotion/popcorn';
```
## Usage
```javascript
progress(100, -100, 50); // 0.25
progress(100, -100, -300); // 2
```
## Types
```typescript
progress(from: number, to: number, value: number): number
```
================================================
FILE: packages/popcorn/docs/api/utilities/radians-to-degrees.md
================================================
---
title: radiansToDegrees
description: Converts radians to degrees.
category: functions
---
# `radiansToDegrees`
`radiansToDegrees` converts radian units to degrees.
<TOC />
## Import
```javascript
import { radiansToDegrees } from '@popmotion/popcorn';
```
## Usage
```javascript
radiansToDegrees(0.7); // 40.107...
```
## Types
```typescript
radiansToDegrees(radians: number): number
```
================================================
FILE: packages/popcorn/docs/api/utilities/smooth-frame.md
================================================
---
title: smoothFrame
description: Smooth the motion from one value to a new value over a single frame.
category: functions
---
# `smoothFrame`
`smoothFrame` can be used to smooth motion across a single frame, independent of framerate.
This can be used, for example, to implement input smoothing.
**Note:** To smooth motion using a [Framesync](/api/framesync)-based process or library like [Popmotion Pure](/pure), the [smooth](/popcorn/api/smooth) utility offers a simpler API.
<TOC />
## Import
```javascript
import { smoothFrame } from '@popmotion/popcorn';
```
## Usage
`smoothFrame` accepts `prevValue`, `nextValue`, `frameDuration` and `strength` arguments.
It will return a value that smooths the difference between `prevValue` and `nextValue` according to the `frameDuration` and `strength` properties.
```javascript
smoothFrame(0, 100, 16.7, 50); // 33.4
```
Higher `strength` values impose stronger smoothing, with values the same as or less than the `frameDuration` imposing no smoothing.
## Types
```typescript
smoothFrame(
prev: number,
next: number,
frameDuration: number,
strength: number
): number
```
================================================
FILE: packages/popcorn/docs/api/utilities/smooth.md
================================================
---
title: smooth
description: Creates a function that will smooth values across frames when used with Framesync or Popmotion Pure.
category: functions
---
# `smooth`
`smooth` creates a function that can smooth a value across frames when paired with a [Framesync](/api/framesync) process or [Popmotion Pure](/pure) animation.
<TOC />
## Import
```javascript
import { smooth } from '@popmotion/popcorn';
```
## Usage
### With Framesync
```javascript
import { smooth } from '@popmotion/popcorn';
import sync from 'framesync';
let counter = 0;
const smoother = smooth(100);
sync.update(() => {
counter = counter + 10;
counter = smoother(counter);
}, true);
```
### With Popmotion Pure
As Popmotion Pure runs on Framesync, we can use it to smooth animations.
For instance, here's an example of input smoothing:
```javascript
import { smooth } from '@popmotion/popcorn';
import { pointer } from 'popmotion';
pointer({ x: 100 })
.pipe(
({ x }) => x,
smooth(50)
)
.start(v => console.log(v))
```
## Types
```typescript
smoothFrame(strength: number) => (v: number) => number
```
================================================
FILE: packages/popcorn/docs/api/utilities/snap.md
================================================
---
title: snap
description: Creates a function that will snap provided values to regular intervals, or to numbers provided as an array.
category: functions
---
# `snap`
`snap` creates a function that will snap numbers to the nearest in a provided array or to a regular interval.
<TOC />
## Import
```javascript
import { snap } from '@popmotion/popcorn';
```
## Usage
### Snap to regular interval
```javascript
const snapTo = snap(45);
snapTo(1); // 0
snapTo(40); // 45
snapTo(50); // 45
snapTo(80); // 90
```
### Snap to values in an array
```javascript
const snapTo = snap([-100, -50, 100, 200]);
snapTo(-200); // -100
snapTo(-76); // -100
snapTo(-74); // -50
```
## Types
```typescript
snap(interval: number) => (v: number) => number;
snap(intervals: number[]) => (v: number) => number;
```
================================================
FILE: packages/popcorn/docs/api/utilities/to-decimal.md
================================================
---
title: toDecimal
description: Rounds a number to a specified decimal place.
category: functions
---
# `toDecimal`
`toDecimal` will round a number to the specified decimal place.
<TOC />
## Import
```javascript
import { toDecimal } from '@popmotion/popcorn';
```
## Usage
```javascript
toDecimal(3.3333); // 3.33
toDecimal(6.6666, 1); // 6.67
```
## Types
```typescript
toDecimal(value: number, precision: number = 2): number
```
================================================
FILE: packages/popcorn/docs/api/utilities/velocity-per-frame.md
================================================
---
title: velocityPerFrame
description: Converts velocity per second into velocity per frame.
category: functions
---
# `velocityPerFrame`
`velocityPerFrame` converts velocity per second into velocity per frame. It is framerate-independent.
<TOC />
## Import
```javascript
import { velocityPerFrame } from '@popmotion/popcorn';
```
## Usage
If a number is changing at a velocity of `50` per second, we can find its velocity per frame by passing `50` along with the duration of the previous frame (in milliseconds):
```javascript
velocityPerFrame(50, 16.7); // 0.835
```
## Types
```typescript
snap(velocityPerSecond: number, frameDuration: number): number;
```
================================================
FILE: packages/popcorn/docs/api/utilities/velocity-per-second.md
================================================
---
title: velocityPerSecond
description: Converts velocity per frame into velocity per second.
category: functions
---
# `velocityPerSecond`
`velocityPerSecond` converts velocity per frame into velocity per second. It is framerate-independent.
<TOC />
## Import
```javascript
import { velocityPerSecond } from '@popmotion/popcorn';
```
## Usage
If a number changed, for instanced, by an increase of `1` in the previous frame, we can calculate its velocity per second by passing `velocityPerSecond` `1` along with the duration of the previous frame (in milliseconds):
```javascript
velocityPerSecond(1, 16.7); // 59.880...
```
## Types
```typescript
velocityPerSecond(velocityPerFrame: number, frameDuration: number): number;
```
================================================
FILE: packages/popcorn/docs/api/utilities/wrap.md
================================================
---
title: wrap
description: Wraps a number when it breaches the defined range.
category: functions
---
# `wrap`
Wraps a number when it breaches the defined range.
<TOC />
## Import
```javascript
import { wrap } from '@popmotion/popcorn';
```
## Usage
`wrap` accepts a range, defined as a `min` and `max`.
When a third number is provided:
- If it lies within the range, it is returned.
- If it lies outside the range, it is wrapped back around:
```javascript
wrap(0, 1, 0.5); // 0.5
wrap(0, 1, 1.5); // 0.5
```
## Types
```typescript
wrap(min: number, max: number, v: number): number;
wrap(min: number, max: number) => (v: number) => number;
```
================================================
FILE: packages/popmotion/.gitignore
================================================
/*.js
/*.js.map
*.d.ts
/coverage
================================================
FILE: packages/popmotion/.npmignore
================================================
*.md
*.map
docs
webpack.config.js
tmp
coverage
src
================================================
FILE: packages/popmotion/CHANGELOG.md
================================================
# Changelog
Popmotion adheres to [Semantic Versioning](http://semver.org/).
## [11.0.5] 2022-08-15
### Update
- `tslib` and `typescript`.
## [11.0.4] 2022-08-10
### Update
- Adding `types` to `exports` field.
## [11.0.3] 2021-12-03
### Update
- Dynamic `restDelta` for smoother springs at low values.
## [11.0.2] 2021-12-02
### Update
- Locking dependencies.
## [11.0.1] 2021-12-02
### Update
- Locking dependencies.
## [11.0.0] 2021-11-03
### Changed
- `mixColor` always outputs RGB, even when mixing HSLA.
### Added
- Animate HSLA with linear color mix.
- Animate between HSLA, RGBA and Hex with `mixColor`.
## [10.0.2] 2021-10-22
### Fixed
- Updating `framesync`.
## [10.0.0] 2021-09-23
### Fixed
- Fixing `exports` and `module` in `package.json`. This will break (unsupported) direct file imports.
### [9.4.1] 2021-09-21
### Changed
- Change `mixComplex` "too complex" error to warning, and allowing instant interpolation when `p > 0`.
### [9.4.0] 2021-06-18
### Added
- `onStop` to `inertia`.
### [9.3.6] 2021-05-11
### Fix
- Correctly end spring animation if provided `bounce` without `duration`.
### [9.3.5] 2021-03-30
### Update
- Updating `framesync`.
### [9.3.4] 2021-03-19
### Fixed
- Updating `style-value-types`.
### [9.3.3] 2021-03-19
### Fixed
- Fixing `main` entry point.
### [9.3.2] 2021-03-19
### Added
- Adding `exports` to `package.json`.
### Updated
- `tslib` to latest.
### [9.3.1] 2021-03-02
### Fixed
- Scheduling of first animation frame was previously set to `immediate`, leading to double animations for animations stopped/started within the same frame.
### [9.3.0] 2021-03-01
### Fixed
- Unbundling ES code to facilitate code-splitting in Webpack.
## [9.2.1] 2020-02-22
### Update
- Upgrading to `style-value-types@4.0.3`.
## [9.2.0] 2020-02-22
### Update
- Upgrading to `framesync@5.1.0` for better Node compatibility.
## [9.1.0] 2020-01-08
### Update
- Support for hex alpha in `mixColor`.
## [9.0.2] 2020-12-18
### Update
- Dependency updates.
## [9.0.1] 2020-12-01
### Fixed
- If `offsets` is a different length to `values`, rather than throw an error we now just generate default offsets.
## [9.0.0] 2020-10-24
- Full API revamp, see documentation.
## [8.7.5] 2020-09-03
### Fixed
- Refreshing published bundle.
## [8.7.2] 2020-04-28
### Fixed
- Decay and inertia correctly start motion at from prop when using modifyTarget
- Decay and inertia no longer round target calculation
- Inertia calls modifyTarget even with zero-velocity
### Changed
- Inertia implementation refinements
## [8.7.1] 2019-11-14
### Upgrade
- Upgraded to Typescript 3.7.
## [8.7.0] 2019-06-25
### Added
- `repeatDelay` prop to `tween`.
## [8.6.10] 2019-05-09
### Fixed
- Fixing undefined action creator. (https://github.com/Popmotion/popmotion/issues/794)[#794]
## [8.6.9] 2019-05-01
### Update
- Dependencies.
## [8.6.8] 2019-04-01
### Update
- `@popmotion/popcorn@0.3.6`
## [8.6.7] 2019-04-01
### Fixed
- Making `inertia.complete` call conditional on there not being a subsequent animation. (https://github.com/Popmotion/popmotion/pull/763)[#763]
## [8.6.6] 2019-04-01
### Update
- `@popmotion/popcorn@0.3.5`
## [8.6.5] 2019-04-01
### Update
- Changing the behaviour of `inertia` to always spring back if the initial value is out of bounds. On multi-axis `inertia` animations it used to be possible that both values are out of bounds and only one was travelling towards its bound - this led to a situation where one animation used a spring and the other used decay.
## [8.6.4] 2019-03-12
### Upgrade
- Upgrading `style-value-types@3.1.0`.
## [8.6.3] 2019-02-21
### Fixed
- Correctly integrating remainder of `elapsed` in yoyo tweens to ensure multiple concurrent tweens stay in sync.
## [8.6.2] 2019-01-28
### Updated
- Tightened type definitions for TransitionMapFactory [#714](https://github.com/Popmotion/popmotion/pull/714)
## [8.6.1] 2019-01-23
### Added
- Adding `bounceStiffness`, `bounceDamping`, `restDelta`, `timeConstant` and `power` options to `inertia`.
## [8.6.0] 2019-01-16
### Added
- `inertia` animation.
## [8.5.5] 2018-12-28
### Update
- `stylefire@8.3.4`
## [8.5.4] 2018-12-10
### Fixed
- When a subscriber is added, only that subscriber is fired with the latest value.
## [8.5.3] 2018-11-20
### Fixed
- Ensuring `.stop()` is part of `ColdSubscription` definition.
## [8.5.2] 2018-11-16
### Upgrade
- Moving to `popcorn@0.2.0`
## [8.5.0] 2018-11-01
### Fixed
- Enforcing minor upgrade to Popcorn.
## [8.4.2] 2018-11-01
### Fixed
- Migrating functions to Popcorn.
## [8.4.1] 2018-09-29
### Fixed
- Calling `transform.steps()` should round properly to each step. [#528](https://github.com/Popmotion/popmotion/issues/528)
## [8.4.0] 2018-09-21
### Updated
- Moved to `framesync@4.0.0`
## [8.3.8] 2018-08-30
### Fixed
- Calling `tween.resume()` would speed the tween up by firing multiple timers. [#395](https://github.com/Popmotion/popmotion/issues/395)
## [8.3.7] 2018-08-30
### Fixed
- Updating latest style-value-types and stylefire
## [8.3.6] 2018-08-21
### Fixed
- Fixed `postinstall` script by removing Chalk.
## [8.3.4] 2018-08-20
### Fixed
- Forcing `multitouch` to use `passive: true`.
## [8.3.2] 2018-06-27
### Fixed
- Forced fix from `style-value-types@3.0.3`
## [8.3.2] 2018-06-27
### Fixed
- Updated color regex in `style-value-types`
## [8.3.1] 2018-06-27
### Fixed
- Fixing some TypeScript definition incompatibilities with newer versions of TS.
## [8.3.0] 2018-06-20
### Added
- Support for animating value types:
- `px`
- `deg`
- `%`
- `vw`
- `vh`
- Complex types including:
- SVG paths
- CSS gradients
- CSS shadows
## [8.2.5] 2018-06-13
### Fixed
- Removing `import`s from output declaration files.
## [8.2.4] 2018-06-08
### Added
- Exporting popular types from index.ts.
## [8.2.3] 2018-05-28
### Fixed
- Renaming `popmotion.min.js` back to `popmotion.global.min.js`
## [8.2.1] 2018-05-17
### Fixed
- Removing `process.env.NODE_ENV` from bundled hey-listen
## [8.2.0] 2018-05-17
### Changed
- Added Rollup to build process. Now just 11.1kb.
### Deprecated
- `css` and `svg` functions from `stylefire`. Use `styler` instead.
## [8.1.23] 2018-05-10
### Fixed
- If an action stops more than once, `parallel` doesn't increase the stop counter.
## [8.1.22] 2018-03-23
### Fixed
- Making `easing` type optional in `interpolate`.
## [8.1.21] 2018-03-13
### Updated
- Updating `stylefire`.
## [8.1.20] 2018-03-13
### Updated
- Updating `stylefire`.
## [8.1.19] 2018-03-13
### Updated
- Updating `stylefire`.
## [8.1.18] 2018-03-13
### Updated
- Changed `Update` type definition to `Function`.
## [8.1.17] 2018-03-09
### Updated
- Stylefire updated to `1.2.6`
## [8.1.16] 2018-03-06
### Fixed
- `value` now fires a velocity check at the end of the following frame to set velocity to `0` if it hasn't been updated.
## [8.1.15] 2018-03-06
### Updated
- Stylefire updated to `1.2.5`
## [8.1.14] 2018-03-04
### Updated
- Stylefire updated to `1.2.4`
## [8.1.13] 2018-03-04
### Updated
- Stylefire updated to `1.2.3`
## [8.1.12] 2018-03-04
### Update
- Running `parseFloat` on string values when returning velocity.
- Stylefire and Style Value Types upgrade
## [8.1.11] 2018-02-19
### Update
- `interpolate` roughly 200x faster when interpolating between just two numbers.
## [8.1.10] 2018-02-04
### Fixed
- Stylefire update.
## [8.1.9] 2018-01-22
### Fixed
- Fix removeEventListener in Chrome 46 [#248](https://github.com/Popmotion/popmotion/pull/248)
## [8.1.8] 2018-01-15
### Fixed
- Fixing TS errors for `stop`
## [8.1.7] 2018-01-04
### Changed
- Updating Framesync to improve performance at 30fps.
## [8.1.6] 2018-01-03
### Fixed
- Fix build.
## [8.1.5] 2018-01-03
### Fixed
- Upgrading Stylefire.
- Corrected types on `tween`.
## [8.1.4] 2017-12-22
### Added
- `generateStaticSpring` transformer.
## [8.1.3] 2017-12-18
### Added
- `conditional` transformer.
## [8.1.2] 2017-12-12
### Changed
- Removed `esnext` and `module` settings from package.json, added `src` to exclude.
## [8.1.1] 2017-12-12
### Changed
- Adding README.md to package.
## [8.1.0] 2017-12-12
### Release!
## [8.0.37@beta] 2017-12-11
### Changed
- `everyFrame` now outputs the `timeSinceStart` rather than the current framestamp (which can be taken from `framesync`).
### Fixed
- Actions that use internal `everyFrame` actions now stop the timer when complete.
## [8.0.35@beta] 2017-12-09
### Added
- The API matching of `parallel` and `composite` can now accept arguments with the same shape. For instance:
```javascript
composite({
x: physics(),
y: physics(),
}).setSpringStrength({ x: 100, y: 50 })
```
## [8.0.34@beta] 2017-12-05
### Changed
- `keyframes` prop `ease` is now `easings`. `ease` applies easing to the overall tween.
## [8.0.33@beta] 2017-12-04
### Added
- `timeline` animation.
### Changed
- `stagger` now outputs array.
## [8.0.32@beta] 2017-11-28
### Added
- New `schedule` compositor.
### Changed
- `transformChildValues` is now `transformMap`, and finally docced.
## [8.0.31@beta] 2017-11-27
### Fixed
- Stopped new instances of actions mutating shared vars.
## [8.0.30@beta] 2017-11-24
### Fixed
- Published with wrong version of Stylefire.
## [8.0.29@beta] 2017-11-24
### Fixed
- Ensuring `everyFrame` stops when it's bloody well told to.
## [8.0.28@beta] 2017-11-22
### Changed
- Upgrading Stylefire
## [8.0.27@beta] 2017-11-16
### Fixed
- `delay` waits appropriate number of time before `complete`.
## [8.0.26@beta] 2017-11-16
### Fixed
- Fixing `scale` delta equation and firing `preventDefault` on multitouch events.
## [8.0.25@beta] 2017-11-16
### Fixed
- Providing `multitouch` `scale` and `rotate` props outputs the delta as applied to those values.
## [8.0.24@beta] 2017-11-16
### Added
- `keyframes` `ease` property can now be a single function.
- `multitouch` accepts initial `scale` and `rotate` properties.
- `filter` chainable to actions and reactions.
### Changed
- `touch` becomes `multitouch`.
- `reaction` becomes `multicast`.
- `onFrame` becomes `everyFrame`.
## [8.0.22@beta] 2017-11-16
### Fixed
- Fixed `tween` flip.
## [8.0.21@beta] 2017-11-16
### Added
- `scale` and `rotate` properties to `touch`.
- `listen` action.
## [8.0.20@beta] 2017-11-14
### Fixed
- Fixed `isActive` bug with observable. Should look at removing this in favor of Reaction.
## [8.0.19@beta] 2017-11-14
## [8.0.18@beta] 2017-11-14
### Changed
- Changed `spring` equation.
## [8.0.17@beta] 2017-11-14
### Changed
- Changed `spring` equation.
## [8.0.16@beta] 2017-11-14
### Fixed
- Reactivating a reaction when provided a new parent.
## [8.0.15@beta] 2017-11-14
### Fixed
- Re-reversing `spring` initial velocity.
## [8.0.14@beta] 2017-11-14
### Fixed
- Not reversing `spring` initial velocity.
## [8.0.13@beta] 2017-11-14
### Fixed
- `keyframes` composite undefined value fixed.
## [8.0.12@beta] 2017-11-11
### Added
- `value` handles objects and arrays.
- `reaction` and `value` automatically stop previous action if used to start a new one.
### Fixed
- `composite` APIs now map return values to the provided object, rather than as a flat array.
## [8.0.11@beta] 2017-11-10
### Added
- Object, array and colour support to `keyframes`.
### Changed
- `pointerDelta` has been removed, `pointer` now accepts an initial point.
## [8.0.10@beta] 2017-11-09
### Fixed
- Fixing broken entry point in `package.json`.
## [8.0.9@beta] 2017-11-08
### Added
- Color support to all vector actions.
## [8.0.8@beta] 2017-11-08
### Added
- `crossfade`, `delay`, `merge` and `stagger` compositors.
## [8.0.7@beta] 2017-11-07
### Added
- `chain` compositor.
## [8.0.4@beta] 2017-10-30
### Added
- New reactive API.
- `keyframes` animation.
- `decay` animation.
- `delta` transformer.
### Removed
- `flow` alias for `pipe`
- Transformers: `add`/`subtract`/`divide`/`multiply`/`conditional`/`alpha`/`percent`/`degrees`/`px`/`rgbUnit`/`rgba`/`hex`/`color`/`hsla`
- Renderers: Moved to [Stylefire](https://github.com/Popmotion/stylefire)
- Render Loop: Moved to [Framesync](https://github.com/Popmotion/framesync)
- Color Tween: Moved to [Popmotion Color Tween](https://github.com/Popmotion/popmotion-color-tween)
- Value Types: Moved to [Style Value Types](https://github.com/Popmotion/style-value-types)
### Changed
- `physics` prop `to` is now `to`
- `physics` prop `spring` is now `springStrength`
- `physics` prop `autoStopSpeed` is now `restSpeed`.
- `spring` prop `restDisplacement` is now `restDelta`.
## [7.8.2] 2017-10-02
### Changed
- Now publishing `dist` folder on npm for use on CodePen via unpkg.com
### Changed
- `spring` transformer becomes `linearSpring` to avoid clashing with the `spring` action.
## [7.8.1] 2017-08-29
### Fixed
- Fixing mistake where Framesync's renamed `currentFrameTime` was exported instead of the previously-named `currentFrameTimestamp`.
## [7.8.0] 2017-08-29
- Spinning off `framesync` to it's own module and deprecating render loop functions for removal in `8.0.0`.
## [7.7.1] 2017-08-27
### Fixed
- Bug in `touches` (via [Mars](https://twitter.com/marsi))
## [7.7.0] 2017-08-24
### Added
- `touches` action for multitouch support. (via [Mars](https://twitter.com/marsi))
- `parallel.getChildren` method now returns array of children actions.
- `parallel` can now accept an `onUpdate` function that is provided an array of latest child values.
## [7.6.2] 2017-08-17
### Fixed
- Composite Actions were firing `onUpdate` as soon as registered.
## [7.6.1] 2017-08-17
### Fixed
- Actions were firing `onUpdate` as soon as registered.
## [7.6.0] 2017-08-07
### Added
- New `spring` action based on an interpretation of Apple's `CASpringAnimation` by [@skevy](https://github.com/skevy)
## [7.5.6] 2017-08-04
### Fixed
- Prevent `Value.toUpdate` from being undefined.
## [7.5.5] 2017-08-02
### Fixed
- Only firing `onStop` on an action bound to a value if the action is active.
## [7.5.4] 2017-07-31
### Fixed
- A key is only added to Renderer's `changedValues` array if it doesn't already exist for that frame.
## [7.5.3] 2017-07-18
### Fixed
- Consistency issue with scheduling update on `value.set` - area to look at in the future.
## [7.5.2] 2017-07-18
### Fixed
- Bug with `css` translate map.
## [7.5.1] 2017-07-17
### Fixed
- Fixed a bug with `smooth`, preventing it from working if the initial given numbers were `0`, or if it was called twice in the same frame.
## [7.5.0] 2017-07-17
### Added
- Enforced order for css `transform` properties.
## [7.4.0] 2017-07-16
### Added
- Added `seek` to `tween`.
## [7.3.1] 2017-07-13
### Added
- Updated `snap` transform to take numbers for regular interval snapping.
## [7.3.0] 2017-07-13
### Added
- New `snap` transformer.
## [7.2.9] 2017-07-12
### Changed
- `trackOffset` now calls `get` instead of `getBeforeTransform`.
## [7.2.8] 2017-07-12
### Fixed
- `angle` calculation fixed.
## [7.2.7] 2017-07-11
### Fixed
- `steps` now returning actual value rather than stepped progress.
## [7.2.6] 2017-07-05
### Fixed
- `speedPerSecond` divide by `0` bug.
## [7.2.5] 2017-07-05
### Fixed
- `lastUpdated` set to `0` on action start to prevent `NaN` velocities.
## [7.2.4] 2017-07-05
### Fixed
- `prev = current` on action start, to prevent `NaN` velocities.
## [7.2.3] 2017-07-04
### Fixed
- `pointer` events are now `passive: true` if `preventDefault` is also set to `true` to fix bug introduced by Chrome 56.
## [7.2.2] 2017-07-03
### Changed
- `composite` action is now `passive: true` to enable composition of other passive actions.
## [7.2.0] 2017-06-26
### Added
- `value` can now be provided to an action's `onUpdate` for automatic action management.
## [7.1.1] 2017-06-23
- Minor bugfix.
## [7.1.0] 2017-06-23
### Added
- `complex` `valueType`.
## [7.0.3] 2017-06-23
### Fixed
- Changed `pointer` to read mouse event `client` positioning instead of `page`, to make consistent with touch events.
## [7.0.2] 2017-06-23
- Minor bugfix.
## [7.0.1] 2017-06-23
- Minor bugfix.
## [7.0.0] 2017-06-22
### Features
- `trackOffset` action returns to simplify the process of tracking the offset of other actions.
- `esnext` package.json property supported.
### Deprecated
- `flow` is now `pipe`, to avoid terminology clashes with [Flow](https://flow.org/). `flow` will continue to work until `7.1.0`.
### Removed
- `blendTweens` is now an optional include.
## [6.7.2] 2017-06-01
### Fixed
- Removing dependencies from `package.json`
## [6.7.1] 2017-06-01
### Fixed
- `colorTween` now uses `transform` property to convert from progress to color, which fixes composition compatibility.
## [6.7.0] 2017-06-01
### Added
- `transform` property for actions. If set, any values passed to `onUpdate` or returned from `get` will be run through this function.
- `getBeforeTransform` method added for actions. Will return the current value, before transform is applied.
## [6.3.5] 2017-03-03
### Added
- `applyOffset` transformer.
## [6.3.4] 2017-03-01
### Fixed
- Undocumented range easing property in `interpolate` transformer was looking at the wrong index.
## [6.3.3] 2017-18-01
### Added
- `top`, `left`, `bottom` and `right` CSS renderer value types.
## [6.3.2] 2017-11-01
### Added
- `smooth` transformer
## [6.3.1] 2017-11-01
### Fixed
- `transformChildValues` transformer now keeps a local mutable state rather than mutating the provided state.
## [6.3.0] 2017-11-01
### Added
- Actions now have an `output` shorthand for setting the `onUpdate` property.
## [6.2.1] 2017-09-01
### Added
- Updated bezier tween blend algorithm.
- Exposed bezier resolver as a transformer.
## [6.2.0] 2017-09-01
### Added
- Bezier tween blending
## [6.1.0] 2017-06-01
- Public release of new API
## [6.0.0@alpha] 2017-01-01
- New API
## [5.0.20] 2016-11-15
### Fixed
- Accidentally transpiled a version of 6.0.
## [5.0.19] 2016-11-15
### Added
- `track` Can take `preventDefault` as optional second param. Defaults to `true`.
## [5.0.18] 2016-08-08
### Fixed
- Firing `onActivateLoop` even if task is already active to prevent `once` from running more than once.
## [5.0.17] 2016-05-08
### Fixed
- Actually fixing spring clamping this time.
## [5.0.16] 2016-05-08
### Fixed
- Spring physics action now automatically ending when target is reached.
## [5.0.15] 2016-18-07
### Fixed
- Missing compilation of `5.0.14`
## [5.0.14] 2016-18-07
### Fixed
- Preventing `current` being overwritten by value type default properties.
- `Tween`s now finish automatically when scrubbed, fixing timeline/stagger bug where tweens wouldn't end.
## [5.0.13] 2016-06-07
### Fixed
- `track.start` and `track.stop` now returning `this`, allowing chaining.
- `from` restored as `track` default value.
## [5.0.12] 2016-06-01
### Fixed
- @[jamieowen](https://github.com/jamieowen): `transform` now being prefixed correctly.
- [#156](https://github.com/Popmotion/popmotion/issues/156): Explicit tween `from` values now honoured by `flow.start`.
### Changed
- Converted project from 4 space indent to 2.
## [5.0.11] 2016-05-21
### Changed
- Tween `blend` property set to `false` by default.
### Fixed
- Mouse tracking in Firefox - `Object.watch` is truthy in Firefox.
## [5.0.10] 2016-05-21
### Fixed
- @[FreakTheMighty](https://github.com/FreakTheMighty): Setting bound pointer listener to ensure correct removal on `Pointer.stop`.
## [5.0.9] 2016-05-21
### Fixed
- @[jamieowen](https://github.com/jamieowen): Prefixed properties now being set correctly.
## [5.0.8] 2016-05-15
### Added
- Unit tests for `transformers.createMapper`.
### Fixed
- Fixed mapped values calculated from `transformers.createMapper` mappers that are outside of the input range returning `undefined`.
## [5.0.7] 2016-04-20
### Changed
- Subsequent actions started on a flow are only given the flow's velocity if their velocity is 0.
## [5.0.6] 2016-04-17
### Changed
- Inherited actions now receive a `parentId` property with the `id` of their parent action.
## [5.0.5] 2016-04-13
### Fixed
- On `set`, `current` was returning undefined if `values` prop set as value, forcing an `adapter` read.
## [5.0.4] 2016-04-13
### Fixed
- If `adapter` returns a string that should be a pure number, we parse that as a float.
## [5.0.3] 2016-04-06
### Fixed
- Regression from testing `5.0.2`.
## [5.0.2] 2016-04-06
### Fixed
- Fixing entry point in `package.json`.
## [5.0.1] 2016-03-30
Minor bugfixes.
## [5.0.0] 2016-03-29
### Popmotion 5.0: timelines, streamlined API, tween blending, still 12kb.
**Warning:** This is a major API revision. Previous Popmotion code **will** be incompatible with this upgrade.
### Added
- **Timelines**: Super-simple yet fully-featured nestable timelines to easily sequence `tweens`.
- **Tween blending**: Smooth transitions between overlapping tweens.
- **Standalone actions**: `tween`, `physics` and `track` can all run without the need for an `actor`.
- **Adapters**: Minimal `get`/`set` API wrappers for smoothing differences between DOM, SVG and frameworks.
- **Transformers**: Composable functions to transform values between update and render.
- **Unified physics engine**: Handles `velocity`, `friction` and `spring` in one unified `physics` action.
- **Small**: All this for less than 12kb minified & gzipped.
- **Smaller**: Rewritten entirely using ES6 exports to allow tree-shaking, ignoring the parts of Popmotion you don't include.
- **Global time dilation**: `setGlobalDilation` method can change the global time.
- **Flow layer**: Replaces Actors and can work entirely in the background to manage multiple actions on the same object.
- Support `points` property for `polygon` and `polyline` tags.
- **MIT**: Changed licence to MIT.
### Removed
- `new` - dropped in favour of factory functions (ie `new Tween()` becomes `tween()`). This will allow further non-API-breaking optimisations.
- `Actor` dropped in favour of `flow`. The Actor model was monolithic, flows are automatically generated for `element`s in the background and can be accessed optionally via `detectFlow`.
- `process`: Now `task`. Prevents conflict with global common in browsers.
- Removed Action `watch` property in favour of more flexible `transform`: Simply provide a function that returns a different value.
- Native Meteor support, as we kept forgetting to update it.
- jQuery support - provide elements as returned from `$('.yourElement').get()` instead.
- `Sequence`: Dropped in favour of the `timeline` function.
- `Iterator`: Dropped in favour of using native array methods and the new `stagger` function.
- `Simulate`: Dropped in favour of unified `physics` action.
### Changed
- `friction` now a value between `0` and `1` - `0` provides no friction, `1` will strip all velocity within a single frame.
## [4.3.4] 2015-12-30
### Fixed
- `Simulate.hasChanged` incorrectly calculated.
## [4.3.3] 2015-12-29
### Fixed
- Added `acceleration` to list of properties that can be set as functions, resolved when an Action starts.
## [4.3.2] 2015-12-26
### Fixed
- Recursion bug with `Actor.sync` under specific circumstances.
## [4.3.1] 2015-12-24
### Removed
- `deceleration` from `Simulate`.
### Fixed
- Fixed bug where `Tween` would start as ended if initialised during `update` ie via a `Sequence`.
## [4.3.0] 2015-12-17
### Added
- `scale` value type hooked up to CSS and SVG roles.
- `utils.camelToDash` utility function for converting camelCase props to dash-case.
### Changed
- Default `Simulate` `stopSpeed` changed from `5` to `0.0001` to account for tiny numbers like 0-1.
## [4.2.7] 2015-12-09
### Fixed
- SVG properties set ie `fillOpacity` are now getting set as `fill-opacity`.
## [4.2.6] 2015-12-08
### Fixed
- Fixed recursive loop when splitting Actor values.
## [4.2.5] 2015-12-07
### Added
- `opacity`, `fillOpacity` and `strokeOpacity` to `ui.svg` Role type map.
## [4.2.4] 2015-12-07
### Added
- `Simulate.autoEnd` property, set to `false` to prevent simulations from automatically ending.
### Fixed
- TweenControls `reverse` now work on completed Tweens.
## [4.2.3] 2015-12-06
### Added
- Actors automatically `sync` on init.
## [4.2.2] 2015-12-03
### Update
- Moving from Babel's official es2015 preset to a custom build.
## [4.2.1] 2015-12-03
### Update
- Updating Babel to fix transpilation errors in IE10.
## [4.2.0] 2015-12-02
### Changed
- Moving to dual commercial and GPLv3 licence.
## [4.1.0] 2015-11-28
### Added
- Actor value `watch` property can now be a function returning any numerical value.
- Added `smooth` for all actions.
- Added `calc.toDecimal` calculator function.
## [4.0.0] 2015-11-20
### Added
- New core processing loop. Separates processes into four stages: `update`, `preRender`, `render`, `postRender`.
- `Process.once` to fire a Process for a single frame.
- Run background processes by passing `true` to `Process.setBackground` or as the last argument to the `Process` constructor. Background processes won't spin up the process loop when activated, only running when non-background processes are active.
### Changed
- `new ui.Process()` takes `callback, scope` instead of `scope, callback`.
- `Process` callbacks now receive `scope` as the first argument, then `framestamp, frameDuration`.
### Removed
- `Process.every`, `Process.reset` and `Process.fire`. Processes should only be started/stopped with `Process.start` and `Process.stop` respectively, to ensure they're run as part of the main loop. `every` is redundant with a combination of `setInterval` and `Process.once`.
- `Process.start` no longer takes a time period as an argument - use `setTimeout` to `Process.stop`.
## [3.8.1] 2015-11-19
### Fixed
- Pow easings incorrectly named var.
## [3.8.0] 2015-11-19
### Added
- Elliot Geno's awesome `'anticipate'` easing. Follow him at [@ElliotGeno](https://twitter.com/ElliotGeno/).
- In-built easings now available in the `ui.ease` namespace. So instead of providing `'backOut'` you can reference it literally - `ui.ease.anticipate`.
- Create modified easing function strengths, for instance `ease: ui.modifyEase(ui.ease.backOut, 2)`. `'ease'` and `'back'` in/out/inOut variants and `'anticipate'` are available. You must provide the literal reference rather than string reference.
## [3.7.1] 2015-11-11
### Changed
- Refactored core clock to increase performance in lower-end devices.
## [3.7.0] 2015-11-07
### Changed
- Software licence changed. Popmotion is now free for non-commercial uses, and requires a per-project licence for commercial projects.
- More files converted to ES6 syntax.
- Moved back to small for production compilation.
- Upgraded Babel from 5 to 6.
### Added
- Beginning suite of Mocha unit tests.
## [3.6.3] 2015-11-03
### Added
- Extra tests to ensure Popmotion is loading correctly in Meteor.
### Fixed
- Explicit test for rAF for when `window` is available and `requestAnimationFrame` isn't.
## [3.6.2] 2015-11-02
### Added
- Meteor support. Published on [Atmosphere](https://atmospherejs.com/popmotion/popmotion) as `popmotion:popmotion`.
### Fixed
- `performance` and `window` checks in Node.
## [3.6.1] 2015-10-29
### Fixed
- Smoothing lower than frameduration produced odd values.
- Smooth by `0` `Infinity` error
## [3.6.0] 2015-10-29
### Added
- New `transform(value, key, actor)` property for `Actor` values. Allows you to return a new value after its been processed by an action, but before it's been limited/rounded etc.
- Exposed our `Track` `smooth` calculator as `ui.calc.smooth`.
### Changed
- Refactored some files to cut down on filesize.
### Fixed
- Fixed a regression from `3.3.3` that fixed `performance` in IE9.
## [3.5.0] 2015-10-21
### Added
- Roles are now getter/setters, if `get` and `set` methods are present. For example: CSS role has getter/setters, so you can call:
ui.css(element, {
position: 'absolute',
top: 0
});
## [3.4.4] 2015-10-22
### Fixed
- `Actor.stop().start()` was failing to run.
## [3.4.3] 2015-10-21
### Fixed
- `Actor.sync` now returns `Actor` rather than the bound sync `Action`.
## [3.4.2] 2015-10-21
### Fixed
- `svg` tags are now assigned `ui.css` role.
## [3.4.1] 2015-10-17
### Fixed
- Delaying test element creation in CSS Role prevents error in server-side rendering.
## [3.4.0] 2015-10-16
### Added
- `Sequence` class, for creating a sequence of non-sequential actions.
- `onComplete` property to `Iterator.stagger`.
- Pass an action as the `Iterator.each` and `Iterator.stagger` `method` argument to automatically run `start` on each `Actor`.
### Changed
- Using rAF-provided timestamp instead of `performance.now` for smoother motion.
## [3.3.3] 2015-10-13
### Fixed
- @stoikerty: Fixed `performance.now` check for IE9.
## [3.3.2] 2015-10-10
### Fixed
- `Pointer` events now properly unbound on `Actor` stop.
## [3.3.1] 2015-10-09
### Added
- `Actor.smooth` now settable on a per-value basis.
- `direct` value property added to take direct input values instead of inputOffset.
## [3.3.0] 2015-10-08
### Added
- `smooth` property added to `Track` - smoothes out values coming from `Input` sources.
## [3.2.1] 2015-10-07
### Fixed
- `watch` no longer overwritten on `set`.
## [3.2.0] 2015-10-06
### Added
- `ui.select` now caches and finds cached Actors bound to DOM elements. If one Actor is found, it returns an Actor. If multiple Actors are found, an Iterator.
- `reverse` method to `Iterator`.
## [3.1.7] 2015-10-05
## Fixed
- Adjusting `hasChanged` logic to always fire on first frame.
- Changing `Iterator.stagger` logic for more even staggers.
## [3.1.6] 2015-10-05
## Fixed
- Manually moved the library class filenames to uppercase.
## [3.1.5] 2015-10-05
## Fixed
- Renamed some class files to uppercase to fix include fails in some Browserify compilations.
## [3.1.4] 2015-10-05
## Added
- Simulation functions are now sent `value <object>, frameDuration <int>, timeStarted <timestamp>` as arguments.
## [3.1.3] 2015-10-04
## Fixed
- Actions fired within an `onComplete` wouldn't start because the number of active Actions was being counted incorrectly.
## [3.1.2] 2015-10-03
### Fixed
- Major Firefox bug 1) `values` false-positive test for `watch` property, now explicitly checking for `string`.
- Major Firefox bug 2) `element.style.hasOwnProperty()` always returning false, switching to `in element.style`.
## [3.1.1] 2015-10-02
### Fixed
- Clearing Actor then/next queue on `start`.
- Saving all arguments to queue via `then` so we can pass Inputs.
## [3.1.0] 2015-10-01
### Added
- Action-specific `onStart`, `onUpdate`, `onFrame` and `onComplete` callbacks. These callbacks will be active only for the duration of the action, while callbacks attached to the host Actor will persist through all actions.
### Changed
- `onStart` callbacks are now fired immediately before the Actor is activated, giving actions extra time to initiate and make use of the [< 100ms response window](https://aerotwist.com/blog/flip-your-animations/).
### Fixed
- Bugfix for deep-copying Actions on Action start. That was a whoops and a half.
## [3.0.4] 2015-09-30
### Fixed
- Bugfix for subvalues not being flipped correctly.
## [3.0.3] 2015-09-30
### Fixed
- SVG Role divide by 0 error when `scale` === 0.
## [3.0.2] 2015-09-29
### Fixed
- Bugfix where Popmotion would attempt to split numerical values.
- Bugfix for `complex` valueType regex where negative numbers were made positive.
## [3.0.0] 2015-09-29
### Added
- Full SVG support.
- Multiple simultaneous Actions on a single Actor - mix Simulations, Tracking and Tweens on the same elements!
- Animate complex strings, like `path` `d` attributes.
- Iterator - to allow single classes to be extended the ActorCollector has been dropped in favour of a generic Iterator class, which can iterate over any set of classes. This also makes it clearer when you're interacting with multiple items vs a single Actor, and these items are not longer limited to Actors.
- Roles - `ui.css`, `ui.attr`, `ui.svg`, `ui.draw`. These are auto-assigned to Actors when initialised with an `element` property, but can also be manually assigned with the `as` property on Actor initialisation.
- Actors can have multiple roles by providing an array to `as`.
- New roles can be created with `new ui.Role()`.
- Value names can be translated before a Role accesses it, via a Role's `map` property. For example `ui.cssRole` maps `x` to `translateX`.
- Action classes/definitions - `Tween`, `Simulate`, `Track`
### Removed
- `ui.addRoute` - see Roles
- `ui.addPreset`, `ui.addAction` - see Tween, Simulate and Track classes
- `ActorCollection` - see Iterator
- `play`, `run`, `track` Actor methods - use `start`
### Changed
- `addToQueue` Actor method is now `then` and takes Tween, Simulate and Track instances instead of raw properties.
- `mapLink` Actor value property is now `mapFrom`.
- Default tween `duration` set to `300`.
- Default tween `ease` set to `"easeOut"`.
- `reverse`, `reset` -> `restart`, `seek` methods moved to `TweenControls` (returned when a `Tween` is passed to `start`)
### Deprecated
- `flipValues`, `reverse`, `reset`, `resetProgress`, `resetOrigins` and `seek` Actor methods - these are all going to be moved to the `Tween` class in `3.2.0`
## [2.0.4] 2015-08-10
### Fixed
- Fixing `bounce` and `capture` simulation calls.
## [2.0.3] 2015-08-10
### Removed
- Removed undocumented `ui.addSimulation` - new simulations now passed as function instead of simulation name.
## [2.0.2] 2015-08-10
### Changed
- `Actor.seek` no longer an Action, much higher performance.
## [2.0.1] 2015-08-07
### Changed
- Only numerical properties can be set as functions to be resolved on action start.
## [2.0.0] 2015-08-07
### Removed
- `ui.addEasing()`
### Added
- New easing functions are now generated with `new ui.Easing()` and provided as the `ease` property. When provided an easeIn function, `in`, `out` and `inOut` methods are returned.
## [1.0.0] 2015-08-06
**Note:** Forked from Redshift v2.1.1.
### Changed
- `redshift` object name now `ui`.
- Terminology changes to fix API semantics:
- **Action:** Actor
- **ActionCollection:** ActionCollection
- **Rubix:** Action (as in, an Action an Actor can perform)
### Added
- Add new easing functions with `ui.addEasing()`. Provide the easeIn function and Popmotion will generate easeOut and easeInOut variants.
- Add new simulation functions to `run` with `ui.addSimulation()`.
- Any value can be a special **value type**, ie a color. `'#FFF'` splits into four numerical properties, `Red`, `Blue`, `Green` and `Alpha`.
- Add new value types with `ui.addValueType()`.
- HSLA value type support.
## [2.1.1] 2015-06-11
### Fixed
- Change Action `rubix` from `"seek"` to `"play"` onEnd.
## [2.1.0] 2015-06-11
### Added
- Added `.seek()` method to Actions.
## [2.0.5] 2015-06-02
### Added
- ActionGroup returns array of values when a getter is called.
## [2.0.4] 2015-06-01
### Fixed
- `onStart` regression from 2.0.0 - only firing for 'values' route.
## [2.0.3] 2015-06-01
### Fixed
- Fixing hasChanged regression, prevented .run() from stopping automatically.
## [2.0.2] 2015-06-01
### Fixed
- Adding Alpha property to all split color values (default: 1), in case a value has mixed RGB and RGBA properties.
## [2.0.1] 2015-06-01
### Added
- CSS values travelling through a splitter (ie backgroundColor is split into RGB values) can be set as functions like normal values.
## [2.0.0] 2015-06-01
### Changed
- Upgraded stepped easing algorithm.
- `Action.hasChanged` set to `true` when `Action.isActive(true)`
### Removed
- `.props()` method removed - properties now saved directly to Action object.
- `.data()` functionality removed, just set properties of Action instead.
- `.flip()` is now `.flipValues()`.
## [1.4.1] 2015-05-31
### Fixed
- ActionGroup.stagger() wasn't returning `this`
## [1.4.0] 2015-05-31
### Added
- Action Groups for controlling multiple Actions at once.
- Stagger method for Action Groups.
- DOM selection support for creating Actions prepopulated with DOM elements.
### Fixed
- Calling .play(preset) while Action was in progress failed to add that call to the play queue.
- Added check for Process timers before clearing as clearTimeout is costing ~.4ms.
================================================
FILE: packages/popmotion/LICENSE.md
================================================
The MIT License (MIT)
Copyright © 2019 Framer BV
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: packages/popmotion/README.md
================================================
# <a href="https://popmotion.io"><img src="https://cloud.githubusercontent.com/assets/7850794/21642571/1910a15e-d27b-11e6-84c7-19e88e207c14.png" height="52" width="243" alt="Popmotion" /></a>
================================================
FILE: packages/popmotion/docs/api/action.md
================================================
---
title: Action
description: Create a reactive stream of values.
next: animations
---
# Action
Action is a simplified Rx-inspired reactive stream focused on animation.
**Every Popmotion animation and input is an action.**
When an action is started, it returns a simple interface that includes **at least** a `stop` method.
<TOC />
## Import
```javascript
import { action } from 'popmotion';
```
## Usage
### Definition
The `action` factory takes one argument, an `init` function.
This is a function that is provided an object of `update`, `complete`, and `error` functions.
Usage of these functions is optional. Your action may call all or just some of them:
```javascript
action(({ update, complete, error }) => {
update(1);
});
```
### Initialisation
`action` returns a `start` method. This also accepts an object of `update`, `complete`, and `error` functions.
When called, the `init` function is provided these functions, and a **new instance** of the action is created.
Calling `start` multiple times will create multiple, separate instances of the action.
For example:
```javascript
const foo = action(({ update }) => {
let i = 0;
setInterval(() => update(i++), 50);
});
foo.start({
update: (v) => console.log(v)
}); // 0, 1, 2...
```
If `start` is passed **only a function**, that is assigned to the `update` function:
```javascript
foo.start((v) => console.log(v)); // 0, 1, 2...
```
We can also listen for the `complete` event like this:
```javascript
const foo = action(({ update, complete }) => {
let i = 0;
setInterval(() => {
update(i++);
if (i === 10) complete();
}, 50);
});
foo.start({
update: (v) => console.log(v), // ...8, 9, 10
complete: () => console.log('complete!')
});
```
### Interface
The `init` function can **optionally** return an API.
For instance, we might use this to stop a timer:
```javascript
const foo = action(({ update }) => {
const interval = setInterval(() => update('ping!'), 100);
return {
stop: () => clearInterval(interval)
};
});
const bar = foo.start(console.log);
setTimeout(() => bar.stop(), 1000);
```
Any method returned by the action `init` function will be exposed when an action instance is created.
### Modification
`action` is **chainable**, which means it offers methods that can alter the behaviour of the base action. Currently, these are `while` and `pipe` (see [Methods](#methods)).
When an action is chained, a **new action** is returned. For instance:
```javascript
const foo = action(({ update }) => {
let i = 0;
setInterval(() => update(i++), 50);
});
const lessThanTen = (v) => v < 10;
const log = (v) => console.log(v);
foo.start(log); // ...8, 9, 10, 11...
foo.while(lessThanTen).start(log); // ...8, 9
```
## Methods
### pipe
```typescript
pipe(...funcs: (v: any) => any)
```
Returns a **new** action that passes the output of the original action's `update` through the provided functions, from left to right.
#### Example
```javascript
const init = ({ update }) => update(10);
const double = (v) => v * 2;
const px = (v) => v + 'px';
action(init)
.pipe(double, px)
.start((v) => console.log(v)); // '20px'
```
### start
```typescript
start(update: (v: any) => void)
start({
complete? () => void,
error?: (err: any) => void,
update?: (v: any) => void
})
start(reaction)
```
Starts the action by running its initiation function, and returning its API.
Every interface returned by a `start` call, **regardless of the API returned from the observable**, will return at least a `stop` function.
It can be provided either an `update` function, or an object with `update`, `complete` and `error` functions.
#### Example
```javascript
// Doesn't return an API
const foo = action(({ update }) => update(1)).start();
foo.stop();
// Returns a custom API
const bar = action(({ update }) => {
let i = 0;
setInterval(() => update(i), 100);
return {
setOutput: (v) => i = v
};
}).start();
bar.setOutput(2);
setTimeout(() => bar.stop(), 1000);
```
### while
```typescript
while(predicate: (v: any) => boolean)
```
Returns a new action, that will continue to run **while** the updated values match the provided predicate.
When the predicate function returns `false`, the action will `complete`.
### Example
```javascript
let latest = 0;
const init = ({ update }) => {
let i = latest;
setInterval(() => update(i++), 50);
};
action(init)
.while((v) => v < 10)
.start({
update: (v) => latest = v,
complete: () => console.log(v) // 9
});
```
================================================
FILE: packages/popmotion/docs/api/animation/decay.md
================================================
---
title: Decay
description: Exponential deceleration, primarily for use in momentum scrolling.
category: animation
---
# Decay
An animation that decelerates to an automatically generated target value, based on its initial velocity.
This target can be modified.
**Note:** This animation is deprecated in favour of [`inertia`](/api/inertia).
<TOC />
## Import
```javascript
import { decay } from 'popmotion';
```
## Usage
Provide a `velocity` and `from` value, and `decay` will calculate a `to` target value and decelerate towards it.
It will output values to a function provided to `start`:
```javascript
decay({ velocity: 200, from: 50 })
.start(v => console.log(v))
```
We can adjust the calculated target value with the `modifyTarget` prop.
This is a function that accepts the calculated target and returns a new one. For instance, we can snap the target to the nearest `100` like so:
```javascript
decay({
velocity: 200,
from: 50,
modifyTarget: v => Math.round(v / 100) * 100
})
```
## Props
The following properties may be passed to `decay`:
### velocity
Initial velocity to decelerate from.
**Default:** `0`
### from
Start value of the animation.
**Default:** `0`
### power
A constant with which to calculate a target value. Higher power = further target.
**Default:** `0.8`
### timeConstant
Adjusting the time constant will change the duration of the deceleration, thereby affecting its feel.
**Default:** `350`
### restDelta
Automatically completes the action when the calculated value is this far away from the target. The final output value will be snapped to the target.
**Default:** `0.5`
### modifyTarget
A function that receives the calculated target and returns a new one. Useful for snapping the target to a grid, for example.
**Default:** `v => v`
## Methods
### Action methods
`decay()` returns:
#### start
Starts the animation and returns playback controls.
Can be provided **either** a function:
```javascript
decay(props).start(v => {})
```
Or a named map of functions for `update` and `complete`:
```javascript
decay(props).start({
update: v => {},
complete: () => {}
})
```
#### filter
Returns a new version of the animation, that filters out any value when the provided predicate function returns `false`:
```javascript
const filtered = decay(props).filter(v => v > 0.5)
// This animation will only output values higher than 0.5:
filtered.start(v => {})
```
#### pipe
Returns a new animation that will pass any output value through this series of functions:
```javascript
// This animation will round output values and then double them:
decay({ from: 0, velocity: 1000 })
.pipe(Math.round, v => v * 2)
.start(v => {})
```
#### while
Returns a new animation that will `complete` when the provided predicate function returns `false`:
```javascript
// This animation will end when an output value is higher than 0.5:
decay().while(v => v < 0.5)
```
### Playback methods
`decay().start()` starts a new animation and returns the following playback methods:
#### stop
Stops the animation.
## Example
<CodePen id="Kyewbv" />
================================================
FILE: packages/popmotion/docs/api/animation/every-frame.md
================================================
---
title: Every Frame
description: Fires with timestamp, once every frame.
category: animation
---
# Every Frame
`everyFrame` fires once per frame, and provides `update` with the duration of time since it started.
<TOC />
## Import
```javascript
import { everyFrame } from 'popmotion';
```
## Usage
```javascript
everyFrame()
.start((timeSinceStart) => console.log(timeSinceStart));
```
## Methods
### Action methods
`everyFrame()` returns:
- `filter((v: any) => boolean)`: Returns a new action that filters out values when the provided function returns `false`.
- `pipe(...funcs: Array<(v) => v)`: Returns a new action that will run `update` values through this sequence of functions.
- `start(update | { update, complete })`: Starts the action and returns a subscription.
- `while((v: any) => boolean)`: Returns a new action that will `complete` when the provided function returns `false`.
### Subscription methods
`everyFrame().start()` returns:
- `stop(): void`
## Example
<CodePen id="XzYJvP" />
================================================
FILE: packages/popmotion/docs/api/animation/inertia.md
================================================
---
title: Inertia
description: Inertial scrolling with spring-loaded boundaries.
category: animation
---
# Inertia
An animation decelerates a value based on its initial velocity, usually used to implement inertial scrolling.
Optionally, `min` and `max` boundaries can be defined, and `inertia` will snap to these with a [`spring`](/api/spring) animation.
This animation will automatically precalculate a target value, which can be modified with the `modifyTarget` property. This allows you to add snap-to-grid or similar functionality.
<TOC />
## Import
```javascript
import { inertia } from 'popmotion';
```
## Usage
Provide a `velocity` and `from` value, and `inertia` will automatically calculate a target and decelerate towards it.
```javascript
inertia({ velocity: 200, from: 50 })
.start(v => console.log(v))
```
We can adjust the calculated target value with the `modifyTarget` prop.
This is a function that accepts the calculated target and returns a new one. For instance, we can snap the target to the nearest `100` like so:
```javascript
inertia({
velocity: 200,
from: 50,
modifyTarget: v => Math.round(v / 100) * 100
})
```
We can also set `min` and/or `max` boundaries:
```javascript
inertia({
velocity: 500,
from: 50,
max: 1000
})
```
When the animated value breaches `max`, it'll snap to `max` using a [spring](/api/spring) animation.
## Props
The following properties may be passed to `inertia`:
### velocity
Initial velocity to decelerate from.
**Default:** `0`
### from
Start value of the animation.
**Default:** `0`
### modifyTarget
A function that receives the calculated target and returns a new one. Useful for snapping the target to a grid, for example.
**Default:** `v => v`
### bounceStiffness
Stiffness of the bounce animations. Higher values will create more sudden movement.
**Default:** `500`
### bounceDamping
Strength of opposing force for the bounce animations. If set to `0`, spring will oscillate indefinitely.
**Default:** `10`
### power
Higher power = further target.
**Default:** `0.8`
### timeConstant
Adjusting the time constant will change the duration of the deceleration, thereby affecting its feel.
**Default:** `700`
## Methods
### Action methods
`inertia()` returns:
#### start
Starts the animation and returns playback controls.
Can be provided **either** a function:
```javascript
inertia(props).start(v => {})
```
Or a named map of functions for `update` and `complete`:
```javascript
inertia(props).start({
update: v => {},
complete: () => {}
})
```
#### filter
Returns a new version of the animation, that filters out any value when the provided predicate function returns `false`:
```javascript
const filtered = inertia(props).filter(v => v > 0.5)
// This animation will only output values higher than 0.5:
filtered.start(v => {})
```
#### pipe
Returns a new animation that will pass any output value through this series of functions:
```javascript
// This animation will round output values and then double them:
inertia({ from: 0, velocity: 1000 })
.pipe(Math.round, v => v * 2)
.start(v => {})
```
#### while
Returns a new animation that will `complete` when the provided predicate function returns `false`:
```javascript
// This animation will end when an output value is higher than 0.5:
inertia().while(v => v < 0.5)
```
### Playback methods
`inertia().start()` starts a new animation and returns the following playback methods:
#### stop
Stops the animation.
## Example
<CodePen id="BMNvqj" />
================================================
FILE: packages/popmotion/docs/api/animation/keyframes.md
================================================
---
title: Keyframes
description: Animate through a linear sequence of values.
category: animation
---
# Keyframes
Keyframes accepts an array of values and will animate between each in sequence.
Timing is defined with a combination of `duration`, `easings` and `times` properties (see [Props](#props))
<TOC />
## Import
```javascript
import { keyframes } from 'popmotion';
```
## Usage
You can set the values to animate between with the `values` property. You can set as many values as you wish.
```javascript
keyframes({ values: [0, 1, 3] })
.start(v => console.log(v))
```
The overall length of the animation can be changed via `duration`.
Each individual value can be given a progress value between `0` and `1` via the `times` array. That determines at which point during the animation it should be at the corresponding value.
Finally, and `easings` property maps to the animations between each value transition (so the length of this array is one fewer than our total number of values).
```javascript
keyframes({
values: [0, 100, 200],
times: [0, 0.2, 1],
duration: 1000,
easings: [ease.linear, ease.cubicBezier(.17,.67,.83,.67)]
})
```
### Value types
`keyframes` supports the animation of the following value types:
#### Number
```javascript
keyframes({
values: [10, 40, 100, -100]
})
```
#### Units
**Supported**: `px`, `%`, `deg`, `vh`, and `vw`
```javascript
keyframes({
values: ['10%', '40%', '100%', '-100%']
})
```
#### Colors
**Supported**: RGB(A), HSL(A) and Hex
```javascript
keyframes({
values: ['#fff', '#000', '#f00']
})
keyframes({
values: [
'rgba(0, 200, 100, 1)',
'rgba(60, 100, 80, 0.5)',
'rgba(60, 100, 80, 1)'
]
})
keyframes({
values: [
'hsl(0, 50%, 50%)',
'hsl(180, 80%, 50%)',
'hsl(45, 60%, 60%)'
]
})
```
#### Complex
Complex sequences of values, like SVG path definitions, CSS shadows and background gradients.
The non-numerical portions of these values must stay in the same format in the `from` and `to` props.
```javascript
keyframes({
values: [
'0px 0px 0px inset rgba(0, 0, 0, 0.2)',
'3px 3px 10px inset rgba(0, 0, 0, 0.5)',
'10px 10px 20px inset rgba(0, 0, 0, 0.8)'
]
})
```
```javascript
keyframes({
values: [
'linear-gradient(to right, #f00, #0f0)',
'linear-gradient(to right, #00f, #f00)',
'linear-gradient(to right, #f00, #0f0)'
]
})
```
#### Objects
Named objects composed of any of the above types may also be animated.
```javascript
keyframes({
values: [
{ x: 0, background: 'hsla(125, 100, 50, 1)' },
{ x: 0, background: 'hsla(20, 100, 60, 1)' },
{ x: 100, background: 'hsla(20, 100, 60, 1)' }
]
})
```
#### Arrays
Arrays composed of any of the above types may also be animated.
```javascript
keyframes({
values: [
[0, '10vh', 'hsla(125, 100, 50, 1)'],
[1, '20vh', 'hsla(20, 100, 60, 1)'],
[0, '40vh', 'hsla(125, 100, 50, 1)']
]
})
```
## Props
The following properties may be passed to `keyframes`:
### values
An array of values to animate between.
**Required**
### duration
Total duration of animation, in milliseconds.
**Default:** `300`
### easings
An array of easing functions for each generated tween, or a single easing function applied to all tweens. This array should be `values.length - 1`.
**Default** `[...easeOut]`
### times
An array of numbers between `0` and `1`, representing `0` to `duration`, that represent at which point each number should be hit. Defaults to an array of evenly-spread durations.
### elapsed
Duration of animation already elapsed, in milliseconds.
**Default:** `0`
### ease
A function, given a progress between `0` and `1`, that returns a new progress value. Used to affect the rate of playback across the duration of the **overall** animation.
**Default:** `linear`
### loop
Number of times to loop animation on `complete`. Set as `Infinity` to loop forever.
**Default:** 0
### flip
Number of times to flip animation on `complete`. Set as `Infinity` to flip forever.
**Default:** 0
### yoyo
Number of times to reverse animation on `complete`. Set as `Infinity` to reverse forever.
**Default:** 0
## Methods
### Action methods
`keyframes()` returns:
`tween()` returns:
#### start
Starts the animation and returns playback controls.
Can be provided **either** a function:
```javascript
keyframes().start(v => {})
```
Or a named map of functions for `update` and `complete`:
```javascript
keyframes().start({
update: v => {},
complete: () => {}
})
```
#### filter
Returns a new version of the animation, that filters out any value when the provided predicate function returns `false`:
```javascript
const filtered = keyframes().filter(v => v > 0.5)
// This animation will only output values higher than 0.5:
filtered.start(v => {})
```
#### pipe
Returns a new animation that will pass any output value through this series of functions:
```javascript
// This animation will round output values and then double them:
keyframes()
.pipe(Math.round, v => v * 2)
.start(v => {})
```
#### while
Returns a new animation that will `complete` when the provided predicate function returns `false`:
```javascript
// This animation will end when an output value is higher than 0.5:
keyframes().while(v => v < 0.5)
```
### Playback methods
`keyframes().start()` starts a new animation and returns the following playback methods:
#### getElapsed
Returns time elapsed in milliseconds.
#### getProgress
Returns animation progress as a value of `0`-`1`.
#### seek
Seeks animation to this position as a value of `0`-`1`.
```javascript
const playback = keyframes().start(v => {})
playback.seek(0.5)
```
#### pause
Pauses playback.
#### resume
Resumes playback.
#### reverse
Reverses the direction of playback.
#### stop
Stops the animation.
## Example
<CodePen id="JOZGdp" />
================================================
FILE: packages/popmotion/docs/api/animation/physics.md
================================================
---
title: Physics
description: Integrated simulation of velocity, acceleration, friction and springs.
category: animation
---
# Physics
Simulate velocity, acceleration, friction and springs.
This is an integrated simulation, meaning the latest state is incorporated at discrete time intervals. It exposes `set` methods that change the simulation while it's running.
This is unlike the differential equations in [decay](/api/decay) and [spring](/api/spring), which can't be changed while in motion (although both offer higher-accuracy simulations which lead to smoother animations).
<TOC />
## Import
```javascript
import { physics } from 'popmotion';
```
## Usage
We can simulate a consistent velocity by providing the `velocity` property. Values are output to the function provided to `start`:
```javascript
physics({ from: 0, velocity: 1000 })
.start(v => console.log(v))
```
To slow the velocity down over time, we can provide a `friction` value between `0` (no friction) and `1` (dead stop):
```javascript
physics({
from: 0,
velocity: 1000,
friction: 0.8
})
```
To put speed back in the system we can use `acceleration`, measured in units per second:
```javascript
physics({
from: 0,
velocity: 1000,
acceleration: 200
})
```
To simulate a spring, we add `to` and `springStrength` values:
```javascript
physics({
from: 0,
velocity: 1000,
friction: 0.8,
to: 400,
springStrength: 500
})
```
### Value types
`physics` supports the animation of a number of different value types.
#### Number
```javascript
physics({ from: 0, velocity: 100 })
```
#### Units
**Supported**: `px`, `%`, `deg`, `vh`, and `vw`
```javascript
physics({ from: '0px', velocity: 100 })
```
#### Objects
Named objects composed of any of the above types may also be animated.
`friction`, `acceleration`, `velocity` and `springStrength` can also be set as objects, to apply property-specific settings:
```javascript
physics({
from: { x: '0px', y: '0px' },
velocity: { x: 200, y: 1000 }
})
```
#### Arrays
Arrays composed of any of the above types may also be animated.
`friction`, `acceleration`, `velocity` and `springStrength` can also be set as arrays, to apply property-specific settings:
```javascript
physics({
from: ['10vh', 0],
velocity: [100, 100]
})
```
## Props
The following properties may be passed to `physics`:
### velocity
Velocity in units per second.
**Default:** `0`
### from
Start simulation from this number.
**Default:** `0`
### acceleration
Increase `velocity` by this amount every second.
**Default:** `0`
### restSpeed
When absolute speed drops below this value, `complete` is fired.
**Default:** `0.001`
### friction
Amount of friction to apply per frame, from `0` to `1`.
**Default:** `0`
### springStrength
If set with `to`, will spring towards target with this strength.
**Default:** `0`
### to
If set with `springStrength`, will gradually "spring" towards this value.
**Default:** `0`
## Methods
### Action methods
`physics()` returns:
#### start
Starts the animation and returns playback controls.
Can be provided **either** a function:
```javascript
physics().start(v => {})
```
Or a named map of functions for `update` and `complete`:
```javascript
physics().start({
update: v => {},
complete: () => {}
})
```
#### filter
Returns a new version of the animation, that filters out any value when the provided predicate function returns `false`:
```javascript
const filtered = physics().filter(v => v > 0.5)
// This animation will only output values higher than 0.5:
filtered.start(v => {})
```
#### pipe
Returns a new animation that will pass any output value through this series of functions:
```javascript
// This animation will round output values and then double them:
physics({ from: 0, velocity: 100 })
.pipe(Math.round, v => v * 2)
.start(v => {})
```
#### while
Returns a new animation that will `complete` when the provided predicate function returns `false`:
```javascript
// This animation will end when an output value is higher than 0.5:
physics().while(v => v < 0.5)
```
### Playback methods
`physics().start()` starts a new animation and returns the following playback methods:
#### set
Change the current value.
#### setAcceleration
Set `acceleration`.
#### setFriction
Set `friction`.
#### setSpringStrength
Set `springStrength`.
#### setSpringTarget
Set `to`.
#### setVelocity
Set `velocity`.
#### stop
Stops the animation.
## Example
<CodePen id="ooybYP" />
================================================
FILE: packages/popmotion/docs/api/animation/spring.md
================================================
---
title: Spring
description: Accurate, versatile spring animation.
category: animation
---
# Spring
A spring animation based on `stiffness`, `damping` and `mass`.
This simulation offers smoother motion and a greater variety of spring-feels than the basic spring simulation found in [physics](/api/physics).
It's based on the same equations underlying Apple's `CASpringAnimation`.
<TOC />
## Import
```javascript
import { spring } from 'popmotion';
```
## Usage
`spring` accepts a `from` and `to` value, and will output values to the function provided to `start`:
```javascript
spring({ from: 0, to: 100 })
.start(v => console.log(v))
```
Pass props like `damping`, `stiffness` and `mass` to affect the character of the spring:
```javascript
spring({
from: 0,
to: 100,
stiffness: 200,
damping: 20
})
```
### Value types
`spring` supports the animation of a number of different value types.
It's generally best output as values that govern physical movement, like `x`, `y` and `rotate`, but it can be used to power colors and shadows.
#### Number
```javascript
spring({ from: 0, to: 100 })
```
#### Units
**Supported**: `px`, `%`, `deg`, `vh`, and `vw`
```javascript
spring({ from: '0px', to: '100px' })
```
#### Colors
**Supported**: RGB(A), HSL(A) and Hex
```javascript
spring({ from: '#fff', to: '#000' })
spring({ from: 'rgba(0, 200, 100, 1)', to: 'rgba(60, 100, 80, 0.5)' })
spring({ from: 'hsl(0, 50%, 50%)', to: 'hsl(180, 80%, 50%)' })
```
#### Complex
Complex sequences of values, like SVG path definitions, CSS shadows and background gradients.
The non-numerical portions of these values must stay in the same format in the `from` and `to` props.
```javascript
spring({
from: '0px 0px 0px inset rgba(0, 0, 0, 0.2)',
to: '3px 3px 10px inset rgba(0, 0, 0, 0.5)'
})
```
```javascript
spring({
from: 'linear-gradient(to right, #fff, #000)',
to: 'linear-gradient(to right, #333, #666)'
})
```
#### Objects
Named objects composed of any of the above types may also be animated.
`velocity`, `mass`, `damping` and `stiffness` can also be set as objects, to apply property-specific settings:
```javascript
spring({
from: { x: '0px', y: '0px' },
to: { x: '100px', y: '200px' },
stiffness: { x: 200, y: 1000 },
damping: { x: 10, y: 50 }
})
```
#### Arrays
Arrays composed of any of the above types may also be animated.
`velocity`, `mass`, `damping` and `stiffness` can also be set as arrays, to apply property-specific settings:
```javascript
spring({
from: ['10vh', 0],
to: ['50vh', 100],
stiffness: [400, 1000]
})
```
## Props
The following properties may be passed to `spring`:
### from
Start value of the animation.
**Default:** `0`
### to
End value of the animation.
**Default:** `1`
### stiffness
Stiffness of the spring. Higher values will create more sudden movement.
**Default:** `100`
### damping
Strength of opposing force. If set to `0`, spring will oscillate indefinitely.
**Default:** `10`
### mass
Mass of the moving object. Higher values will result in more lethargic movement.
**Default:** `1`
### velocity
Initial velocity of the object, measured in units per second.
**Default:** `0`
### restDelta
End animation if distance to `to` is below this value **and** speed is below `restSpeed`. When animation ends, spring gets "snapped" to `to`.
**Default:** `0.01`
### restSpeed
End animation if absolute speed (in units per second) drops below this value **and** delta is smaller than `restDelta`.
**Default:** `0.01`
## Methods
### Action methods
`spring()` returns:
#### start
Starts the animation and returns playback controls.
Can be provided **either** a function:
```javascript
spring().start(v => {})
```
Or a named map of functions for `update` and `complete`:
```javascript
spring().start({
update: v => {},
complete: () => {}
})
```
#### filter
Returns a new version of the animation, that filters out any value when the provided predicate function returns `false`:
```javascript
const filtered = spring().filter(v => v > 0.5)
// This animation will only output values higher than 0.5:
filtered.start(v => {})
```
#### pipe
Returns a new animation that will pass any output value through this series of functions:
```javascript
// This animation will round output values and then double them:
spring({ from: 0, to: 100 })
.pipe(Math.round, v => v * 2)
.start(v => {})
```
#### while
Returns a new animation that will `complete` when the provided predicate function returns `false`:
```javascript
// This animation will end when an output value is higher than 0.5:
spring().while(v => v < 0.5)
```
### Playback methods
`spring().start()` starts a new animation and returns the following playback methods:
#### stop
Stops the animation.
## Example
<CodePen id="mqKyjd" />
================================================
FILE: packages/popmotion/docs/api/animation/timeline.md
================================================
---
title: Timeline
description: Sequence a multitrack animation with full playback controls.
category: animation
---
# Timeline
Timeline is used to script complex sequences of animation, split across independent tracks.
If offers all the same playback options as a [`tween`](/api/tween).
<TOC />
## Import
```javascript
import { timeline } from 'popmotion';
```
## Usage
### Create a sequence of animations
`timeline` accepts an array of playhead instructions.
A playhead instruction can be an animation, array of animations for parallel or staggered execution, or a timestamp.
#### Animation
Each animation is defined as an object. This looks a lot like a simplified `tween`, with `from`, `to`, `duration` and `ease` properties:
```javascript
timeline([
{ track: 'x', from: 0, to: 300, duration: 1000 }
])
```
There's a **required** property called `track`. No two animations should overlap that share the same `track` label, and `timeline` will output every track to the function given to `start` together as an object:
```javascript
timeline([
{ track: 'x', from: 0, to: 300, duration: 1000 }
]).start(v => console.log(v.x))
```
#### Sequencing
If we provide a second animation, it will (by default) play **after** the first:
```javascript
timeline([
{ track: 'x', from: 0, to: 300, duration: 1000 },
{ track: 'y', from: 0, to: 300 }
])
```
In this example animation, the second animation will start after `1000` milliseconds, as that's when the first ends (as defined by `duration`).
#### Timestamps
We can, however, move the playhead from that default position. If we provide a number as the next instruction, the playhead will move to that position.
In this example, the second animation will start after `500` milliseconds:
```javascript
timeline([
{ track: 'x', from: 0, to: 300, duration: 1000 },
500,
{ track: 'y', from: 0, to: 300 }
])
```
If we instead provide a string, we can move the playhead **relative** to the current timestamp with either `'-'` or `'+'` instructions. For instance, this time the second animation will start after `800` milliseconds:
```javascript
timeline([
{ track: 'x', from: 0, to: 300, duration: 1000 },
'-200',
{ track: 'y', from: 0, to: 300 }
])
```
#### Parallel and stagger
Animations can be played in parallel, from the same point in time, by providing them in an array.
In this example, both animations provided after the first animation will play after `1000`ms:
```javascript
timeline([
{ track: 'x', from: 0, to: 300, duration: 1000 },
[
{ track: 'x', to: 0 },
{ track: 'y', from: 0, to: 300 }
]
])
```
If we provide a number as the last item in the array, `timeline` will stagger over all the other items in the array with this delay:
```javascript
timeline([
{ track: 'x', from: 0, to: 300, duration: 1000 },
[
{ track: 'x', to: 0 },
{ track: 'y', from: 0, to: 300 },
50
]
])
```
### Value types
`timeline` supports the animation of the following value types:
#### Number
```javascript
timeline([
{ track: 'x', from: 0, to: 100 }
])
```
#### Units
**Supported**: `px`, `%`, `deg`, `vh`, and `vw`
```javascript
timeline([
{ track: 'x', from: '0%', to: '100%' }
])
```
#### Colors
**Supported**: RGB(A), HSL(A) and Hex
```javascript
timeline([
{ track: 'backgroundColor', from: '#fff', to: '#f00' }
])
```
#### Complex
Complex sequences of values, like SVG path definitions, CSS shadows and background gradients.
The non-numerical portions of these values must stay in the same format in the `from` and `to` props.
```javascript
timeline([
{
track: 'boxShadow',
from: '0px 0px 0px inset rgba(0, 0, 0, 0.2)',
to: '3px 3px 10px inset rgba(0, 0, 0, 0.5)'
}
])
```
#### Objects
Named objects composed of any of the above types may also be animated.
```javascript
timeline([
{
track: 'ball',
from: {
backgroundColor: '#f00',
x: 0
},
to: {
backgroundColor: '#fff',
x: 100
}
}
])
```
#### Arrays
Arrays composed of any of the above types may also be animated.
```javascript
timeline([
{
track: 'ball',
from: [0, '10vh'],
to: [0, '0vh']
}
])
```
## Props
The following props can be passed as the second argument to timeline:
```javascript
timeline(playlist, props)
```
### duration
Total duration of animation, in milliseconds.
**Default:** `300`
### elapsed
Duration of animation already elapsed, in milliseconds.
**Default:** `0`
### ease
A function that, given a progress between `0` and `1`, will return a new progress value. Used to affect the speed of playback across the duration of the animation.
If `from` and `to` are set as objects or arrays, `ease` may be set with a corresponding structure to apply a unique easing for each animating value.
**Default:** `easeOut`
### loop
Number of times to loop animation on `complete`. Set as `Infinity` to loop forever.
**Default:** 0
### flip
Number of times to flip animation on `complete`. Set as `Infinity` to flip forever.
**Default:** 0
### yoyo
Number of times to reverse animation on `complete`. Set as `Infinity` to reverse forever.
**Default:** 0
## Methods
### Action methods
`timeline()` returns:
#### start
Starts the animation and returns playback controls.
Can be provided **either** a function:
```javascript
timeline().start(v => {})
```
Or a named map of functions for `update` and `complete`:
```javascript
timeline().start({
update: v => {},
complete: () => {}
})
```
#### filter
Returns a new version of the animation, that filters out any value when the provided predicate function returns `false`:
```javascript
const filtered = timeline().filter(v => v.x > 0.5)
// This animation will only output values higher than 0.5:
filtered.start(v => {})
```
#### pipe
Returns a new animation that will pass any output value through this series of functions:
```javascript
timeline()
.pipe(v => v)
.start(v => {})
```
#### while
Returns a new animation that will `complete` when the provided predicate function returns `false`:
```javascript
// This animation will end when an output value is higher than 0.5:
timeline().while(v => v.x < 0.5)
```
### Playback methods
`timeline().start()` starts a new animation and returns the following playback methods:
#### getElapsed
Returns time elapsed in milliseconds.
#### getProgress
Returns animation progress as a value of `0`-`1`.
#### seek
Seeks animation to this position as a value of `0`-`1`.
```javascript
const playback = tween().start(v => {})
playback.seek(0.5)
```
#### pause
Pauses playback.
#### resume
Resumes playback.
#### reverse
Reverses the direction of playback.
#### stop
Stops the animation.
================================================
FILE: packages/popmotion/docs/api/animation/tween.md
================================================
---
title: Tween
description: Animate between two values over a set duration of time.
category: animation
---
# Tween
Animate between two values over a set duration of time.
The behaviour and feel of the animation can be affected by providing a different [easing](/api/easing) function.
<TOC />
## Import
```javascript
import { tween } from 'popmotion';
```
## Usage
By default, `tween` will tween from `0` to `1` over `300` milliseconds, with `easeOut` easing, and will output values to the function provided to `start`:
```javascript
tween()
.start(v => console.log(v))
```
Pass props to adjust the character of the tween:
```javascript
tween({ to: 200, duration: 500 })
```
### Value types
`tween` supports the animation of the following value types:
#### Number
```javascript
tween({ from: 0, to: 1 })
```
#### Units
**Supported**: `px`, `%`, `deg`, `vh`, and `vw`
```javascript
tween({ from: '0px', to: '100px' })
```
#### Colors
**Supported**: RGB(A), HSL(A) and Hex
```javascript
tween({ from: '#fff', to: '#000' })
tween({ from: 'rgba(0, 200, 100, 1)', to: 'rgba(60, 100, 80, 0.5)' })
tween({ from: 'hsl(0, 50%, 50%)', to: 'hsl(180, 80%, 50%)' })
```
#### Complex
Complex sequences of values, like SVG path definitions, CSS shadows and background gradients.
The non-numerical portions of these values must stay in the same format in the `from` and `to` props.
```javascript
tween({
from: '0px 0px 0px inset rgba(0, 0, 0, 0.2)',
to: '3px 3px 10px inset rgba(0, 0, 0, 0.5)'
})
```
```javascript
tween({
from: 'linear-gradient(to right, #fff, #000)',
to: 'linear-gradient(to right, #333, #666)'
})
```
#### Objects
Named objects composed of any of the above types may also be animated.
`ease` can also be set as an object, to apply property-specific [easing](/api/easing):
```javascript
tween({
from: {
x: 0,
background: 'hsla(125, 100, 50, 1)'
},
to: {
x: 100,
background: 'hsla(20, 100, 60, 1)'
},
ease: {
x: easeOut,
background: linear
}
})
```
#### Arrays
Arrays composed of any of the above types may also be animated.
`ease` can also be set as an array, to apply property-specific [easing](/api/easing):
```javascript
tween({
from: [0, '10vh', 'hsla(125, 100, 50, 1)'],
to: [1, '20vh', 'hsla(20, 100, 60, 1)'],
ease: [easeOut, backOut, linear]
})
```
## Props
The following properties may be passed to `tween`:
### from
Start value of the animation.
**Default:** `0`
### to
End value of the animation.
**Default:** `1`
### duration
Total duration of animation, in milliseconds.
**Default:** `300`
### elapsed
Duration of animation already elapsed, in milliseconds.
**Default:** `0`
### ease
A function that, given a progress between `0` and `1`, will return a new progress value. Used to affect the speed of playback across the duration of the animation.
If `from` and `to` are set as objects or arrays, `ease` may be set with a corresponding structure to apply a unique easing for each animating value.
**Default:** `easeOut`
### loop
Number of times to loop animation on `complete`. Set as `Infinity` to loop forever.
**Default:** 0
### flip
Number of times to flip animation on `complete`. Set as `Infinity` to flip forever.
**Default:** 0
### yoyo
Number of times to reverse animation on `complete`. Set as `Infinity` to reverse forever.
**Default:** 0
## Methods
### Action methods
`tween()` returns:
#### start
Starts the animation and returns playback controls.
Can be provided **either** a function:
```javascript
tween().start(v => {})
```
Or a named map of functions for `update` and `complete`:
```javascript
tween().start({
update: v => {},
complete: () => {}
})
```
#### filter
Returns a new version of the animation, that filters out any value when the provided predicate function returns `false`:
```javascript
const filtered = tween().filter(v => v > 0.5)
// This animation will only output values higher than 0.5:
filtered.start(v => {})
```
#### pipe
Returns a new animation that will pass any output value through this series of functions:
```javascript
// This animation will round output values and then double them:
tween({ from: 0, to: 100 })
.pipe(Math.round, v => v * 2)
.start(v => {})
```
#### while
Returns a new animation that will `complete` when the provided predicate function returns `false`:
```javascript
// This animation will end when an output value is higher than 0.5:
tween().while(v => v < 0.5)
```
### Playback methods
`tween().start()` starts a new animation and returns the following playback methods:
#### getElapsed
Returns time elapsed in milliseconds.
#### getProgress
Returns animation progress as a value of `0`-`1`.
#### seek
Seeks animation to this position as a value of `0`-`1`.
```javascript
const playback = tween().start(v => {})
playback.seek(0.5)
```
#### pause
Pauses playback.
#### resume
Resumes playback.
#### reverse
Reverses the direction of playback.
#### stop
Stops the animation.
## Example
<CodePen id="WXOPWX" />
================================================
FILE: packages/popmotion/docs/api/calc.md
================================================
---
title: Calculators
description: Simple functions useful in UI calculations.
---
Moved to [Popcorn](/popcorn)
================================================
FILE: packages/popmotion/docs/api/compositors/chain.md
================================================
---
title: Chain
description: Chain a sequence of actions, move to the next when the current one completes.
category: compositors
---
# Chain
Chain a sequence of actions, move to the next when the current one completes.
<TOC />
## Import
```javascript
import { chain } from 'popmotion';
```
## Usage
```javascript
chain(
tween({ to: 300 }),
spring({ from: 300, to: 0 })
).start({
update: (v) => console.log(v),
complete: () => console.log('All actions complete')
})
```
## Methods
### Action methods
`chain()` returns:
- `filter((v: any) => boolean)`: Returns a new action that filters out values when the provided function returns `false`.
- `pipe(...funcs: Array<(v) => v)`: Returns a new action that will run `update` values through this sequence of functions.
- `start(update | { update, complete })`: Starts the action and returns a subscription.
- `while((v: any) => boolean)`: Returns a new action that will `complete` when the provided function returns `false`.
### Subscription methods
`chain().start()` returns:
- `stop(): void`
================================================
FILE: packages/popmotion/docs/api/compositors/composite.md
================================================
---
title: Composite
description: Control a map of actions and output to that same structure.
category: compositors
---
# Composite
Control a named map of actions, and output to the same structure.
<TOC />
## Import
```javascript
import { composite } from 'popmotion';
```
## Usage
```javascript
composite({
x: tween({ from: 60, to: 400 }),
y: physics({ from: 60, velocity: 300 })
}).start(({ x, y }) => {});
```
`composite` outputs at most once per frame.
## Methods
### Action methods
`composite()` returns:
- `filter((v: any) => boolean)`: Returns a new action that filters out values when the provided function returns `false`.
- `pipe(...funcs: Array<(v) => v)`: Returns a new action that will run `update` values through this sequence of functions.
- `start(update | { update, complete })`: Starts the action and returns a subscription.
- `while((v: any) => boolean)`: Returns a new action that will `complete` when the provided function returns `false`.
### Subscription methods
`composite().start()` returns:
- `stop(): void`
**Note:** If all actions return the same API, for instance all composed actions are `tween`s, the `composite` subscription will also return a version of that API that controls all child actions.
================================================
FILE: packages/popmotion/docs/api/compositors/crossfade.md
================================================
---
title: Crossfade
description: Fade between two numerical actions.
category: compositors
---
# Crossfade
Fade between two numerical actions.
<TOC />
## Import
```javascript
import { crossfade } from 'popmotion';
```
## Usage
Example: blend from one tween to another:
```javascript
const blendTweens = crossfade(
tween({ from: 0, to: 500, elapsed: 200 }),
tween({ from: 500, to: 0 })
).start((v) => console.log(v));
tween({ duration: 100 }).start(blendTweens.setBalance);
```
## Methods
### Action methods
`crossfade()` returns:
- `filter((v: any) => boolean)`: Returns a new action that filters out values when the provided function returns `false`.
- `pipe(...funcs: Array<(v) => v)`: Returns a new action that will run `update` values through this sequence of functions.
- `start(update | { update, complete })`: Starts the action and returns a subscription.
- `while((v: any) => boolean)`: Returns a new action that will `complete` when the provided function returns `false`.
### Subscription methods
`crossfade().start()` returns:
- `setBalance(): this`: Sets the balance of blended output from the first action (`0`) to the second (`1`).
- `stop(): void`
## Example
<CodePen id="ooPjxj" />
================================================
FILE: packages/popmotion/docs/api/compositors/delay.md
================================================
---
title: Delay
description: Fires complete after the defined interval.
category: compositors
---
# Delay
Fires `complete` after the defined interval.
<TOC />
## Import
```javascript
import { delay } from 'popmotion';
```
## Usage
```javascript
delay(100).start({
complete: () => console.log('complete!')
});
```
Useful for delaying actions in a `chain`.
```javascript
chain(
delay(100),
tween({ to: 400, duration: 500 })
);
```
### Action methods
`delay()` returns:
- `start(update | { update, complete })`: Starts the action and returns a subscription.
### Subscription methods
`delay().start()` returns:
- `stop(): void`
================================================
FILE: packages/popmotion/docs/api/compositors/merge.md
================================================
---
title: Merge
description: Combine multiple actions into one output.
category: compositors
---
# Merge
Combine multiple actions into one output.
<TOC />
## Import
```javascript
import { merge } from 'popmotion';
```
## Usage
```javascript
merge(
tween(),
action(({ update }) => update(1)),
physics({ velocity: 1000 })
).start((v) => console.log(v));
```
## Methods
### Action methods
`merge()` returns:
- `filter((v: any) => boolean)`: Returns a new action that filters out values when the provided function returns `false`.
- `pipe(...funcs: Array<(v) => v)`: Returns a new action that will run `update` values through this sequence of functions.
- `start(update | { update, complete })`: Starts the action and returns a subscription.
- `while((v: any) => boolean)`: Returns a new action that will `complete` when the provided function returns `false`.
### Subscription methods
`merge().start()` returns:
- `stop(): void`
================================================
FILE: packages/popmotion/docs/api/compositors/parallel.md
================================================
---
title: Parallel
description: Control multiple actions in parallel and output as an array.
category: compositors
---
# Parallel
Control an n-dimensional array of actions in parallel, and output as an array.
<TOC />
## Import
```javascript
import { parallel } from 'popmotion';
```
## Usage
```javascript
parallel(
tween({ from: 40, to: 50 }),
spring({ to: 500 })
).start(([ tweenOutput, springOutput ]) => {});
```
`parallel` outputs max once per frame.
## Methods
### Action methods
`parallel()` returns:
- `filter((v: any) => boolean)`: Returns a new action that filters out values when the provided function returns `false`.
- `pipe(...funcs: Array<(v) => v)`: Returns a new action that will run `update` values through this sequence of functions.
- `start(update | { update, complete })`: Starts the action and returns a subscription.
- `while((v: any) => boolean)`: Returns a new action that will `complete` when the provided function returns `false`.
### Subscription methods
`parallel().start()` returns:
- `stop(): void`
**Note:** If all actions return the same API, for instance all composed actions are `tween`s, the `parallel` subscription will also return a version of that API that controls all child actions.
================================================
FILE: packages/popmotion/docs/api/compositors/schedule.md
================================================
---
title: Schedule
description: Use an action to control the output of another.
category: compositors
---
# Schedule
`schedule` can use one action to control the output of another.
For instance, by default `pointer` outputs only when the pointer updates.
With `schedule`, you could compose it with `everyFrame` to output the latest `pointer` value every frame.
<TOC />
## Import
```javascript
import { schedule } from 'popmotion';
```
## Usage
```typescript
schedule(scheduler: Action, subject: Action): Action
```
```javascript
// `pointer` will output at most once every frame
schedule(
everyFrame(),
pointer()
).start(({ x, y }) => {});
```
## Methods
### Action methods
`schedule()` returns:
- `filter((v: any) => boolean)`: Returns a new action that filters out values when the provided function returns `false`.
- `pipe(...funcs: Array<(v) => v)`: Returns a new action that will run `update` values through this sequence of functions.
- `start(update | { update, complete })`: Starts the action and returns a subscription.
- `while((v: any) => boolean)`: Returns a new action that will `complete` when the provided function returns `false`.
### Subscription methods
`schedule().start()` returns:
- `stop(): void`
================================================
FILE: packages/popmotion/docs/api/compositors/stagger.md
================================================
---
title: Stagger
description: Stagger the execution of a series of actions.
category: compositors
---
# Stagger
Stagger the execution of a series of actions.
<TOC />
## Import
```javascript
import { stagger } from 'popmotion';
```
## Usage
```typescript
stagger(actions: Action[], interval: number | (i: number) => number): Action
```
`stagger` accepts two arguments, an array of actions and an `interval`:
```javascript
stagger([
tween(),
spring()
], 100)
```
When started, it outputs the values as an array. Actions that haven't yet started will output `undefined`, and you can define a default.
```javascript
stagger([
tween(),
spring()
], 100).start((values) => values.forEach((v = 0, i) => {
console.log(v);
}))
```
## Methods
### Action methods
`stagger()` returns:
- `filter((v: any) => boolean)`: Returns a new action that filters out values when the provided function returns `false`.
- `pipe(...funcs: Array<(v) => v)`: Returns a new action that will run `update` values through this sequence of functions.
- `start(update | { update, complete })`: Starts the tween and returns a subscription.
- `while((v: any) => boolean)`: Returns a new action that will `complete` when the provided function returns `false`.
### Subscription methods
`stagger().start()` returns:
- `stop(): void`
================================================
FILE: packages/popmotion/docs/api/easing.md
================================================
---
title: Easing
description: Functions that speed or slow a tween over time.
---
# Easing
Easing functions make tweened motion look more natural by emulating the changes in velocity experienced by objects in the real world.
They work by accepting a progress value from `0` to `1`, and returning a new one.
There's a seperate Popmotion package for easing:
<TOC />
## Import
```
npm install @popmotion/easing
```
```javascript
import { linear } from '@popmotion/easing';
```
## Example
```javascript
import { tween, easing } from 'popmotion';
import { easeOut } from '@popmotion/easing';
tween({
ease: easeOut
}).start();
```
## Presets
Popmotion comes with the following preset easing functions:
- `cubicBezier`
- `linear`
- `easeIn`, `easeOut`, `easeInOut`
- `circIn`, `circOut`, `circInOut`
- `backIn`, `backOut`, `backInOut`
- `anticipate`
Try them out by editing this live example:
```marksy
<Example template="Ball" id="b">{`
const ball = document.querySelector('#b .ball');
const ballStyler = styler(ball);
tween({
to: 300,
duration: 300,
ease: linear
}).start(ballStyler.set('x'));
`}</Example>
```
## Easing creation
Popmotion provides the following functions to create your own easing functions:
### cubicBezier
Creates cubic bezier curve easing function.
```javascript
const { cubicBezier } = easing;
const longTail = cubicBezier(0, .42, 0, 1);
```
### reversed
Accepts an easing function and returns a new one that reverses the provided one.
For instance, an `easeIn` would become an `easeOut`.
```javascript
const { anticipate, reversed } = easing;
const anticipateOut = reversed(anticipate);
```
### mirrored
Accepts an easing function and returns a new one that mirrors the provided one.
For instance, an `easeIn` would become an `easeInOut`.
```javascript
const { anticipate, mirrored } = easing;
const anticipateInOut = mirrored(anticipate);
```
### createExpoIn
Creates an easing function based on the exponent function `progress ** exponent`. `easeIn` is `createExpoIn(2)`.
```javascript
const { createExpoIn } = easing;
const strongerEaseIn = createExpoIn(3);
```
### createBackIn
Creates an easing function with an overshoot. `backIn` is `createBackIn(1.525)`.
```javascript
const { createBackIn, reversed } = easing;
const strongerBackOut = reversed(createBackIn(3));
```
### createAnticipateEasing
Creates an easing function with a small anticipate and ease out. `anticipate` is `createAnticipateEasing(1.525)`.
```javascript
const { createAnticipateEasing } = easing;
const strongerAnticipate = createAnticipateEasing(3);
```
================================================
FILE: packages/popmotion/docs/api/faqs.md
================================================
---
title: FAQs
description: Popmotion frequently asked questions
---
# FAQs
<TOC />
## Browser support?
Popmotion supports all major browsers.
For legacy IE11 support, the following polyfills are required:
- [String.endsWith](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith#Polyfill)
- [WeakSet](https://github.com/dy/weakset)
## Filesize?
As of version 8.3.4, Popmotion is **12kb**.
================================================
FILE: packages/popmotion/docs/api/framesync.md
================================================
---
title: Framesync
description: Schedule functions to run at specific steps on the render loop.
---
# Framesync
A tiny frame scheduler for performantly batching reads, updates and renders.
Segregating actions that read and write to the DOM will avoid [layout thrashing](https://developers.google.com/web/fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing).
It's also a way of ensuring order of execution across a frame. For instance, Popmotion batches updates on the `update` step, and Stylefire batches renders on the `render` step, allowing independent animation of `transform` properties.
<TOC />
## Install
```bash
npm install framesync
```
## Usage
Framesync splits a frame into discrete `read`, `update`, `render` and `postRender` steps.
### Scheduling functions
Functions can be scheduled to different parts of the render loop with `sync`.
```javascript
import sync from 'framesync';
```
It provides four functions, one for scheduling a function to run on each part of the frame:
```javascript
sync.update(() => {});
```
### Frame data
Each function is provided data about the current frame:
```javascript
sync.update({ delta, timestamp }) => {});
```
- `delta`: Time since last frame (in milliseconds)
- `timestamp`: Timestamp of the current frame.
This object is recycled across frames, so values should be destructured if intended to be used asynchronously.
### Keep alive
We can run a function as an ongoing process by passing `true` as the second parameter:
```javascript
let count = 0;
sync.update(() => count++, true);
```
This will keep the process running until it's actively cancelled.
### Run immediately
The third parameter, `immediate`, can be used to sync a function on the **current frame step**.
By default, Framesync will schedule functions to run the next time that frame step is fired:
```javascript
sync.update(({ timestamp }) => {
// The following function will run on the subsequent frame:
sync.update((frame) => frame.timestamp !== timestamp);
});
```
By setting `immediate` to `true`, we can add this at the end of the current step:
```javascript
sync.update(({ timestamp }) => {
// The following function will run on the **current** frame:
sync.update(
(frame) => frame.timestamp === timestamp,
false,
true
);
});
```
### Cancelling
Synced processes can be cancelled with the `cancelSync` function:
```javascript
import sync, { cancelSync } from 'framesync';
let count = 0;
const process = sync.render(() => {
count++;
if (count >= 10) cancelSync.render(process);
}, true);
```
================================================
FILE: packages/popmotion/docs/api/input/listen.md
================================================
---
title: Listen
description: Creates a DOM event listener as an action stream.
category: input
---
# Listen
`listen` creates DOM event listeners as an action stream.
<TOC />
## Import
```javascript
import { listen } from 'popmotion';
```
## Usage
To listen to an event, provide a DOM element and an event name to `listen`:
```javascript
listen(document, 'mousemove')
.start((e) => console.log(e));
```
### Multiple events
Multiple events can be subscribed to by providing a space-delimited string:
```javascript
listen(document, 'touchstart touchend')
```
### Chainable actions
The primary benefit of using `listen` is passing each event through the chainable actions like `filter`. For instance, here's an event listener that only fires when two or more touches are detected:
```javascript
const onMultitouch = listen(document, 'touchstart')
.filter(({ touches }) => touches.length > 1);
onMultitouch.start((e) => ...);
```
### Options
`listen` optionally accepts a third argument of options:
```typescript
type EventOpts = boolean | {
capture?: boolean;
passive?: boolean;
once?: boolean;
};
listen(element: Element, eventNames: string, opts?: EventOpts): Action
```
## Methods
### Action methods
`listen()` returns:
- `filter((v: any) => boolean)`: Returns a new action that filters out values when the provided function returns `false`.
- `pipe(...funcs: Array<(v) => v)`: Returns a new action that will run `update` values through this sequence of functions.
- `start(update | { update, complete })`: Starts the action and returns a subscription.
- `while((v: any) => boolean)`: Returns a new action that will `complete` when the provided function returns `false`.
### Subscription methods
`listen().start()` returns:
- `stop(): void`
================================================
FILE: packages/popmotion/docs/api/input/multitouch.md
================================================
---
title: Multitouch
description: Tracks multitouch input.
category: input
---
# Multitouch
Tracks multitouch input and outputs a list of active touches, plus scale and rotation delta between the first two touch points.
For single-point input, generally [pointer](/api/pointer) is more appropriate as it provides a simple, cross-platform interface.
<TOC />
## Import
```javascript
import { multitouch } from 'popmotion';
```
## Usage
```typescript
multitouch({
preventDefault?: boolean = true,
scale?: number,
rotate?: number
})
```
```javascript
multitouch().start(({ touches, scale, rotate }) => {
touches.forEach(({ x, y }) => console.log(x, y))
});
```
`multitouch` provides:
- `touches: { x: number, y: number }[]`: An array of `x`/`y` coordinates representing each active finger.
- `scale: number`: The distance between the first two fingers since `start`, represented as a multiplier of the original distance. `scale` starts from `1.0`, or the initially provided `scale`.
- `rotate: number`: The angle rotation of the first two fingers as a delta of the original rotation. `rotate` starts from `0.0`, or the initially provided `rotate`.
### Commonly-used properties
If you often use, for instance, `rotate`, you can easily create a new action that returns only that value:
```javascript
const touchRotation = (initialRotate = 0) => multitouch({ rotate: initialRotate })
.pipe(({ rotate }) => rotate);
touchRotation(45).start((rotate) => console.log(rotate));
```
## Props
- `preventDefault?: boolean = true`
- `scale?: number = 1.0`
- `rotate?: number = 0.0`
## Methods
### Action methods
`multitouch()` returns:
- `filter((v: any) => boolean)`: Returns a new action that filters out values when the provided function returns `false`.
- `pipe(...funcs: Array<(v) => v)`: Returns a new action that will run `update` values through this sequence of functions.
- `start(update | { update, complete })`: Starts the action and returns a subscription.
- `while((v: any) => boolean)`: Returns a new action that will `complete` when the provided function returns `false`.
### Subscription methods
`multitouch().start()` returns:
- `stop(): void`
## Example
<CodePen id="LOBjxQ" />
================================================
FILE: packages/popmotion/docs/api/input/pointer.md
================================================
---
title: Pointer
description: Outputs the screen position of a single mouse or touch point.
category: input
---
# Pointer
Outputs the screen position of a single mouse or touch point.
<TOC />
## Import
```javascript
import { pointer } from 'popmotion';
```
## Usage
### Absolute position
```javascript
pointer()
.start(({ x, y }) => console.log(x, y));
```
### Relative position
Provide initial `x` and `y` properties to output pointer movement **applied to this initial point**.
This is useful for dragging motion.
```javascript
pointer({ x: 200, y: 175 })
.start(({ x, y }) => console.log(x, y));
```
Reactions are provided the following pointer data:
- `x`, `y`: Alias of `clientX` / `clientY`, or
- `clientX`, `clientY`: Position relative to the viewport.
- `pageX`, `pageY`: Position relative to the document.
## Props
- `preventDefault: boolean = true`
- `x?: number`: If defined, apply pointer `y` movement to this number.
- `y?: number`: If defined, apply pointer `y` movement to this number.
## Methods
### Action methods
`pointer()` returns:
- `filter((v: any) => boolean)`: Returns a new action that filters out values when the provided function returns `false`.
- `pipe(...funcs: Array<(v) => v)`: Returns a new action that will run `update` values through this sequence of functions.
- `start(update | { update, complete })`: Starts the action and returns a subscription.
- `while((v: any) => boolean)`: Returns a new action that will `complete` when the provided function returns `false`.
### Subscription methods
`pointer().start()` returns:
- `stop(): void`
## Example
<CodePen id="RjBZoe" />
================================================
FILE: packages/popmotion/docs/api/reactions/multicast.md
================================================
---
title: Multicast
description: A reaction that multiple reactions can subscribe to.
category: reactions
---
# Multicast
The multicast reaction provides a reaction that many other reactions can `subscribe` to.
It also helps manage actions: if a `multicast` reaction is passed to another `action`, the first `action` will automatically `stop`.
<TOC />
## Import
```javascript
import { multicast } from 'popmotion';
```
## Usage
### Subscription
Provide a reactions to `mulitcast.subscribe()`:
```javascript
const foo = multicast();
foo.subscribe((v) => console.log('first subscriber', v));
foo.subscribe((v) => console.log('second subscriber', v));
```
When the multicast reaction is `update`d, all listeners will fire:
```javascript
foo.update(5);
// first subscriber, 5
// second subscriber, 5
```
### Automatically stop previous action
Passing the multicast reaction to a new action will stop the previous one:
```javascript
tween().start(foo);
spring().start(foo); // This will stop `tween`
```
### Chain methods
`multicast` can be chained in the same way as [actions](/api/action).
```javascript
const double = (v) => v * 2;
const px = (v) => v + 'px';
const foo = multicast().pipe(double, px);
foo.update(5); // 10px
```
### Unsubscribe
`subscribe` returns an `unsubscribe` method:
```javascript
const foo = multicast();
const sub = foo.subcribe(console.log);
sub.unsubscribe();
```
## Methods
### Multicast methods
`multicast()` returns:
- `filter((v: any) => boolean)`: Returns a new action that filters out values when the provided function returns `false`.
- `pipe(...funcs: Array<(v) => v)`: Returns a new reaction that will run `update` values through this sequence of functions.
- `subscribe(update | { update, complete, error })`: Returns a subscription.
- `stop()`: Stops current parent action.
- `while((v: any) => boolean)`: Returns a new reaction that will `complete` when the provided function returns `false`.
### Subscription methods
`multicast().subscribe()` returns:
- `unsubscribe()`
================================================
FILE: packages/popmotion/docs/api/reactions/value.md
================================================
---
title: Value
description: Track value state and query velocity
category: reactions
---
# Value
A [multicast reaction](/api/multicast) that tracks the state of a number and allows velocity queries.
<TOC />
## Import
```javascript
import { value } from 'popmotion';
```
## Usage
```typescript
value(initialValue, onUpdate);
```
```javascript
import { tween, value } from 'popmotion';
import styler from 'stylefire';
const div = styler(document.querySelector('div'));
const divX = value(0, div.set('x'));
tween({ to: 500 }).start(divX);
setTimeout(() => console.log(() => {
physics({
velocity: divX.getVelocity()
}).start(divX); // This will automatically `stop` the tween
}), 150);
```
`value` can also handle objects and arrays:
```javascript
const foo = value({ x: 0, y: 0 });
const bar = value([0, 0]);
foo.getVelocity(); // { x: 0, y: 0 }
bar.getVelocity(); // [0, 0]
```
As a multicast reaction, you can optionally `subscribe` with multiple other reactions rather than providing an initial subscription:
```javascript
const foo = value(0);
foo.subscribe(() => console.log('first reaction'));
foo.subscribe(() => console.log('second reaction'));
```
## Methods
### Reaction methods
`value()` returns:
- `get(): number`: Returns the current value state.
- `getVelocity: number`: Returns the current value velocity.
- `filter((v: any) => boolean)`: Returns a new action that filters out values when the provided function returns `false`.
- `pipe(...funcs: Array<(v) => v)`: Returns a new reaction that will run `update` values through this sequence of functions.
- `stop()`: Stops parent action.
- `subscribe(update | { update, complete })`: Returns a subscription.
- `while((v: any) => boolean)`: Returns a new reaction that will `complete` when the provided function returns `false`.
### Subscription methods
`value().subscribe()` returns:
- `unsubscribe(): void`
================================================
FILE: packages/popmotion/docs/api/transformers.md
================================================
---
title: Transformers
description: Simple composable functions that take a value and return a new one.
---
Moved to [Popcorn](/popcorn)
================================================
FILE: packages/popmotion/docs/blog/20170703-choosing-a-default-easing-for-popmotion.md
================================================
---
title: Choosing the correct default easing for Popmotion
description: "Why I settled on easeOut for Popmotion's default easing, and why easeInOut sucks for interfaces"
published: 20170703
---
# Choosing the correct default easing for Popmotion
Choosing default values for a library is difficult. Should you be the benefactor/victim of a wider audience:
- These defaults will be used, often unwittingly, by your consumers.
- You can change them only at the risk of breaking other people's stuff.
In a motion engine, these choices manifest themselves in a visual and visceral way. A duration here, a spring tightness there.
This means there's responsibility to choose values intelligently, so that the little patches of the web that use your library benefit from more responsive motion.
As the userbase of Popmotion is relatively small, I've always felt comfortable shirking the shackles of API stability until I finally felt like it had arrived at a the Good Place. Apologies to anyone who's lived that.
Luckily, over the years of wildly oscillating GitHub activity graphs,
there has been one (one) decision that I felt like I got right at the start: Making the `tween` default easing property `easeOut`.

## A brief history of timing
Like many greying front end devs, my first exposure to UI animation was [Greensock's](https://greensock.com) then-ActionScript library, TweenMax. For a platform so disposed to garish show-off loading screen animations, Flash animations were disgusting to hand code unless you were using TweenMax.
And that's largely what we used it for: showy animations. The Flash days were as over-the-top and as divorced from the user's interests as the Amiga demoscene. All you wanted to do was play your cracked version of Worms but first you had to sit through the seizure-inducing cock-prancing of some git in Norwich. At least Flash intros occasionally had a skip button.

Greensock, in its sunrise years, had the right intentions. It did, and still to this day, has an `easeOut` as default. That's because the author understands, despite our hedonism and heathenism, that animation in UI design **should** be as a result of a user's action. `easeOut` is snappy, and as we'll see later, "snappy" is how we should respond to user actions.
Flash died, and the community collectively denied any involvement.

Then it was all about jQuery. jQuery was incredible for literally **everything**, which in the new world of composable asynchronous micropackages is probably why we again collectively deny any involvement, and why I'm talking about it in the past tense even while it's standing **right there**, watching us.
For me, and maybe for you, the coolest thing about jQuery was `animate`. It was amazing to easily get something resembling movement in humble HTML. Even if it defaulted to `swing` easing, a tepid, muddy `easeInOut` of homeopathic strength.
That easing was coupled with a default duration of `400`ms. Then that was folded into our neanderthal, performance-ignorant tweening of the CPU-choking, layout-breaking `width` and `height` properties. Lethargic animation ruled the internet.

## The problem with `easeInOut`
To arrive at an actual point, the problem with `easeInOut` is that it **feels** incredibly slow. When we [watch videos about the principles of animation](https://vimeo.com/93206523), one of the things we're taught is that objects in motion don't start in motion and they don't stop dead.
They start slow, and end slow.
So that sounds about right, we think, and then we stop thinking, and use `easeInOut` by choice, or a framework like jQuery makes it default, and then everyone uses it, by default, and everything feels sluggish, by default. Why?
## Why
Our eyes and brain are hardwired to detect motion. We've evolved to find that motion distracting. Motion indicates that the present situation has changed, and we need to react if we'd prefer to survive. We **need** motion to be distracting.
When you're scrolling through a website, and a space opens for an advert in the middle of your article, and everything jumps around, and then after a couple of seconds your crap, overpriced "4G" connection finally loads the banner ad, which animates on loop, until you scroll past it, when it then needlessly closes, god I hate Motherboard, your text jumps back up, you think of the poor bastard forced to make it, their hopes, their dreams, their broken dreams - all of those things are distracting.
That motion, the things causing it: They're not imparting useful information, they're not even trying to kill you. So it's annoying.
It's all shit, the user isn't involved in any of this, he's happy about the broken dreams. And yet, `easeInOut` is entirely appropriate, it is the least damaging easing to use for uninstigated animation, it is the right choice.
What does it say about an easing that **this** is a good use case for it?
## It's sometimes okay, I guess
A **very** tiny amount of uninstigated motion is fine in a UI, as long as it correctly indicates that **the situation has changed, and the user needs to react**. A small "new message" dot, probably. Or a notification panel, possibly.
For this kind of animation, an `easeInOut` or `anticipate` is very appropriate because it gives the user a little bit of time to acclimatise to the movement, and it stops quite gently, naturally. It adheres to the principles of animation, these dots and panels now feel a little more real, your UI a little more alive.
It's certainly better than things just flicking around the page without the user understanding what's changed.
## But usually it very much isn't
The **vast majority** of animation in UI is, or should be, user instigated.
For these animations, these interactions, the user already knows that an action has taken place. **They** started the motion, and the situation has changed, and the UI needs to react. The "in" of an `easeIn` or `easeInOut` feels sluggish in this instance because for god's sake hurry up, get on with it.
The energy and momentum of `easeInOut` starts in the virtual reality and stays there. The energy and momentum `easeOut`, conversely, starts in the user's reality and ends in the interface's.
It takes the user's energy, directly from their finger, through the wire or screen, straight into the button, the tooltip, the whatever, and bursts with the maximum energy at that initial moment of contact.
`easeInOut` is barely bothered to get out of bed, like a stupid stroppy teenager who probably doesn't even have a finger. Probably.
A user will feel that difference, even if it's subconscious, even if I have to pretend to myself that deep down they **know**, just to justify the hours of my life I've spent writing (and now writing about) animations.
This is why Greensock comes with `easeOut` by default. It's why [Anime.js](http://animejs.com/) uses a zinger `elasticOut`. And it's why Popmotion uses `easeOut` too.
Whereas, CSS transitions default to the `swing`-alike `ease`, which is exactly as bland as it sounds. Worse, the native Web Animations API uses `linear` easing, which is, frankly, a fucking crime.

## Feel it for yourself
Here's `easeInOut`.
```marksy
<Example template="Ball" id="a">{`
const ball = document.querySelector('#a .ball');
const ballRenderer = styler(ball);
tween({
to: 300,
duration: 500,
ease: easing.easeInOut
}).start((x) => ballRenderer.set('x', x));
`}</Example>
```
Buuuuuuurrrrr. END ME.
Conversely, here's an `easeOut` with the Popmotion default of `300`ms.
```marksy
<Example template="Ball" id="b">{`
const ball = document.querySelector('#b .ball');
const ballRenderer = styler(ball);
tween({
to: 300,
ease: easing.easeOut
}).start((x) => ballRenderer.set('x', x));
`}</Example>
```
I. Am. Blushing.
Notice that when you press start on these examples, you're pressing the button yet it's the ball that's moving. Even with this physical disconnect, the first example feels like you're **telling** the ball to move, and then it moves of its own accord. Whereas the second example, you're **making** the ball move, it's using **your** energy.
It makes a difference! Users can tell.
It does. It makes a difference.It does.Userscantellitmakesadifferencepleasemakeadifferenceuserscantell
---
[Get started with Popmotion](/learn/get-started)
================================================
FILE: packages/popmotion/docs/blog/20170704-manually-set-scroll-while-ios-momentum-scroll-bounces.md
================================================
---
title: How to manually set scrollTop during an iOS momentum bounce
description: Why does existence hurt so much
published: 20170804
---
# How to manually set scrollTop during an iOS momentum bounce
Here's one to file under [the mobile is web is awful](/blog/20170710-mobile-web-is-awful-and-were-all-to-blame).
I've been writing a Slack-esque chat that lazy-loads new messages as you scroll up. The adventure of reliably anchoring scroll position as these new messages are added to the DOM is probably a blog post in itself, but there's a specific issue on iOS that I'd like to share solution to.
## The problem
Here's the code to restore a previous scroll position, (which has to be recalculated to accommodate the newly-loaded messages):
```javascript
node.scrollTop = node.scrollHeight - prevScrollTop;
```
Works great in every browser, except of course the modern-day IE:

As you can see, the scroll position stays at the top, almost as if we never manually reset the scroll position at all.
The problem, as I began to understand, was that if you try and manually set a node's (and probably the viewport's) scroll position **while iOS is doing it's out-of-bounds bouncy thing**, that scroll position will be immediately overridden by the rest of the bounce animation.
## The fix
To fix, we simply disable momentum scrolling on that element, restore scroll position, and then re-enable momentum scrolling:
```javascript
node.style['-webkit-overflow-scrolling'] = 'auto';
node.scrollTop = node.scrollHeight - prevScrollTop;
node.style['-webkit-overflow-scrolling'] = 'touch';
```
Here's how that looks:

Not as graceful as I'd prefer, but looking at the timestamps the user is still left on the correct message. It also avoids funny residual momentum effects, so I presume this technique can also be used to kill scroll momentum when a pointer moves from one overflowing node to another.
---
Popmotion is a 9kb JavaScript motion engine, and it'll give you way less bother than mobile Safari. Create awesome interactions with tweens, physics and input tracking.
[Excite your users with Popmotion](/learn/get-started) and/or [excite us with 140 characters](https://twitter.com/popmotionjs)
================================================
FILE: packages/popmotion/docs/blog/20170710-mobile-web-is-awful-and-were-all-to-blame.md
================================================
---
title: The mobile web is awful, and everyone's to blame
description: From browser vendors to front end developers, everyone is implicated in the state of the mobile web.
published: 20170710
---
# The mobile web is awful, and everyone's to blame
At work today, we were discussing the future direction of the website and app. A concern was raised that, without a clear mandate, the website would "continue to be a great desktop version, and a much poorer version of the app."
As the front end lead, that stung. I felt like the "much" was undeserved.
I took the point. It's worth imagining that the use-case of the app and website may well be different.
However, the comment came as a response to a mini-moan that it'd taken me a couple hours to get an input field to stick to the bottom of the page and still be tappable in mobile Safari. A simple task made difficult.
It was an indictment that I haven't yet changed perceptions about the capabilities of the mobile web. Maybe those perceptions don't deserve to be changed.
I've long held that the web experience **can** be just as performant and polished as native. It's only for a lack of time and ambition that it isn't. That belief is the reason I wrote Popmotion in the first place.
So I began to think, it's usually easy and quite enjoyable to make a great desktop experience. Yet developing for mobile is a constant headache.
With some mobile Geekbench scores approaching laptops, the technical argument is diminishing. So why?
I realised that everyone is to blame. Browser vendors, Business People, every member of the Google AMP team, you reading this, me writing this: Everyone.
## Browsers Know Best
Implementing simple design features like overlays or bottom navigation on mobile browsers invariably involves trawling through blogs and forums to find that special hack that worked for that one guy that one day in June.
As every developer knows, no good hack goes unpunished. Testing cross-browser serves a specific cocktail; a nostalgic blend of heart palpitations, dream-like confusion and a palpable sense of impending disappointment. It takes you right back to '99.
It usually c
gitextract_kjzyuham/
├── .babelrc
├── .circleci/
│ └── config.yml
├── .eslintrc
├── .github/
│ └── ISSUE_TEMPLATE/
│ ├── Feature_request.md
│ └── bug-report.md
├── .gitignore
├── .prettierignore
├── .storybook/
│ └── config.js
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── README.md
├── lerna.json
├── package.json
├── packages/
│ ├── blend-tweens/
│ │ ├── blend-tweens.js
│ │ └── cross-fade.js
│ ├── framesync/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── rollup.config.js
│ │ ├── src/
│ │ │ ├── _tests/
│ │ │ │ └── test.ts
│ │ │ ├── create-render-step.ts
│ │ │ ├── index.ts
│ │ │ ├── on-next-frame.ts
│ │ │ └── types.ts
│ │ └── tsconfig.json
│ ├── popcorn/
│ │ └── docs/
│ │ └── api/
│ │ └── utilities/
│ │ ├── angle.md
│ │ ├── apply-offset.md
│ │ ├── clamp.md
│ │ ├── conditional.md
│ │ ├── degreesToRadians.md
│ │ ├── distance.md
│ │ ├── interpolate.md
│ │ ├── is-point-3d.md
│ │ ├── is-point.md
│ │ ├── mix-array.md
│ │ ├── mix-color.md
│ │ ├── mix-complex.md
│ │ ├── mix.md
│ │ ├── pipe.md
│ │ ├── point-from-vector.md
│ │ ├── progress.md
│ │ ├── radians-to-degrees.md
│ │ ├── smooth-frame.md
│ │ ├── smooth.md
│ │ ├── snap.md
│ │ ├── to-decimal.md
│ │ ├── velocity-per-frame.md
│ │ ├── velocity-per-second.md
│ │ └── wrap.md
│ ├── popmotion/
│ │ ├── .gitignore
│ │ ├── .npmignore
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE.md
│ │ ├── README.md
│ │ ├── docs/
│ │ │ ├── api/
│ │ │ │ ├── action.md
│ │ │ │ ├── animation/
│ │ │ │ │ ├── decay.md
│ │ │ │ │ ├── every-frame.md
│ │ │ │ │ ├── inertia.md
│ │ │ │ │ ├── keyframes.md
│ │ │ │ │ ├── physics.md
│ │ │ │ │ ├── spring.md
│ │ │ │ │ ├── timeline.md
│ │ │ │ │ └── tween.md
│ │ │ │ ├── calc.md
│ │ │ │ ├── compositors/
│ │ │ │ │ ├── chain.md
│ │ │ │ │ ├── composite.md
│ │ │ │ │ ├── crossfade.md
│ │ │ │ │ ├── delay.md
│ │ │ │ │ ├── merge.md
│ │ │ │ │ ├── parallel.md
│ │ │ │ │ ├── schedule.md
│ │ │ │ │ └── stagger.md
│ │ │ │ ├── easing.md
│ │ │ │ ├── faqs.md
│ │ │ │ ├── framesync.md
│ │ │ │ ├── input/
│ │ │ │ │ ├── listen.md
│ │ │ │ │ ├── multitouch.md
│ │ │ │ │ └── pointer.md
│ │ │ │ ├── reactions/
│ │ │ │ │ ├── multicast.md
│ │ │ │ │ └── value.md
│ │ │ │ └── transformers.md
│ │ │ ├── blog/
│ │ │ │ ├── 20170703-choosing-a-default-easing-for-popmotion.md
│ │ │ │ ├── 20170704-manually-set-scroll-while-ios-momentum-scroll-bounces.md
│ │ │ │ ├── 20170710-mobile-web-is-awful-and-were-all-to-blame.md
│ │ │ │ ├── 20170803-coding-style-dont-be-a-dick.md
│ │ │ │ ├── 20171210-popmotion-8-upgrade-guide.md
│ │ │ │ ├── 20171211-introducing-popmotion-8.md
│ │ │ │ ├── 20180104-when-ios-throttles-requestanimationframe.md
│ │ │ │ ├── 20180521-pose-2-migration-guide.md
│ │ │ │ ├── 20180820-introducing-pose-3.md
│ │ │ │ ├── 20180829-pose-3-1-animate-between-anything.md
│ │ │ │ ├── 20180904-introducing-pose-for-vue.md
│ │ │ │ ├── 20181101-react-pose-4-forwardref.md
│ │ │ │ ├── 20190123-introducing-inertia-animation-for-popmotion-pure.md
│ │ │ │ ├── 20190704-upgrade-to-pure-9.md
│ │ │ │ ├── 20200115-pose-is-deprecated.md
│ │ │ │ ├── draft-60fps-hi-res-image-scaling-with-translatez-and-maths.md
│ │ │ │ ├── draft-css-vs-js-animation.md
│ │ │ │ └── draft-the-emerging-reality.md
│ │ │ └── learn/
│ │ │ ├── advanced/
│ │ │ │ └── value-pipelines.md
│ │ │ ├── basics/
│ │ │ │ ├── action-reaction.md
│ │ │ │ ├── get-started.md
│ │ │ │ ├── input-tracking.md
│ │ │ │ ├── install.md
│ │ │ │ └── velocity-and-physics.md
│ │ │ ├── how-to/
│ │ │ │ ├── circular-motion.md
│ │ │ │ ├── constrain-motion.md
│ │ │ │ ├── input-smoothing.md
│ │ │ │ ├── morph-svg.md
│ │ │ │ └── rounded-values.md
│ │ │ └── projects/
│ │ │ └── spring-loaded-characters-remaining.md
│ │ ├── package.json
│ │ ├── rollup.config.js
│ │ ├── src/
│ │ │ ├── animations/
│ │ │ │ ├── __tests__/
│ │ │ │ │ ├── animate.test.ts
│ │ │ │ │ ├── inertia.test.ts
│ │ │ │ │ └── utils.ts
│ │ │ │ ├── generators/
│ │ │ │ │ ├── __tests__/
│ │ │ │ │ │ ├── decay.test.ts
│ │ │ │ │ │ ├── keyframes.test.ts
│ │ │ │ │ │ ├── spring.test.ts
│ │ │ │ │ │ └── utils.ts
│ │ │ │ │ ├── decay.ts
│ │ │ │ │ ├── keyframes.ts
│ │ │ │ │ └── spring.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── inertia.ts
│ │ │ │ ├── types.ts
│ │ │ │ └── utils/
│ │ │ │ ├── __tests__/
│ │ │ │ │ ├── detect-animation-from-config.test.ts
│ │ │ │ │ ├── elapsed.test.ts
│ │ │ │ │ └── find-spring.test.ts
│ │ │ │ ├── detect-animation-from-options.ts
│ │ │ │ ├── elapsed.ts
│ │ │ │ └── find-spring.ts
│ │ │ ├── easing/
│ │ │ │ ├── __tests__/
│ │ │ │ │ ├── cubic-bezier.test.ts
│ │ │ │ │ ├── index.test.ts
│ │ │ │ │ ├── steps.test.ts
│ │ │ │ │ └── utils.test.ts
│ │ │ │ ├── cubic-bezier.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── steps.ts
│ │ │ │ ├── types.ts
│ │ │ │ └── utils.ts
│ │ │ ├── index.ts
│ │ │ ├── types.ts
│ │ │ ├── utils/
│ │ │ │ ├── __tests__/
│ │ │ │ │ ├── angle.test.ts
│ │ │ │ │ ├── apply-offset.test.ts
│ │ │ │ │ ├── attract.test.ts
│ │ │ │ │ ├── clamp.test.ts
│ │ │ │ │ ├── degrees-to-radians.test.ts
│ │ │ │ │ ├── distance.test.ts
│ │ │ │ │ ├── hsla-to-rgba.test.ts
│ │ │ │ │ ├── interpolate.test.ts
│ │ │ │ │ ├── is-point-3d.test.ts
│ │ │ │ │ ├── is-point.test.ts
│ │ │ │ │ ├── mix-array.test.ts
│ │ │ │ │ ├── mix-color.test.ts
│ │ │ │ │ ├── mix-complex.test.ts
│ │ │ │ │ ├── mix-object.test.ts
│ │ │ │ │ ├── mix.test.ts
│ │ │ │ │ ├── point-from-vector.test.ts
│ │ │ │ │ ├── progress.test.ts
│ │ │ │ │ ├── radians-to-degrees.test.ts
│ │ │ │ │ ├── smooth-frame.test.ts
│ │ │ │ │ ├── smooth.test.ts
│ │ │ │ │ ├── snap.test.ts
│ │ │ │ │ ├── to-decimal.test.ts
│ │ │ │ │ ├── velocity-per-frame.test.ts
│ │ │ │ │ ├── velocity-per-second.test.ts
│ │ │ │ │ └── wrap.test.ts
│ │ │ │ ├── angle.ts
│ │ │ │ ├── apply-offset.ts
│ │ │ │ ├── attract.ts
│ │ │ │ ├── clamp.ts
│ │ │ │ ├── degrees-to-radians.ts
│ │ │ │ ├── distance.ts
│ │ │ │ ├── hsla-to-rgba.ts
│ │ │ │ ├── inc.ts
│ │ │ │ ├── interpolate.ts
│ │ │ │ ├── is-point-3d.ts
│ │ │ │ ├── is-point.ts
│ │ │ │ ├── mix-color.ts
│ │ │ │ ├── mix-complex.ts
│ │ │ │ ├── mix.ts
│ │ │ │ ├── pipe.ts
│ │ │ │ ├── point-from-vector.ts
│ │ │ │ ├── progress.ts
│ │ │ │ ├── radians-to-degrees.ts
│ │ │ │ ├── smooth-frame.ts
│ │ │ │ ├── smooth.ts
│ │ │ │ ├── snap.ts
│ │ │ │ ├── to-decimal.ts
│ │ │ │ ├── velocity-per-frame.ts
│ │ │ │ ├── velocity-per-second.ts
│ │ │ │ └── wrap.ts
│ │ │ └── worklet/
│ │ │ ├── animate.ts.wip
│ │ │ ├── custom-properties.ts
│ │ │ ├── index.ts.wip
│ │ │ └── load-worklet.ts
│ │ ├── tsconfig.json
│ │ └── tslint.json
│ ├── popmotion-pose/
│ │ └── docs/
│ │ ├── api/
│ │ │ ├── dom/
│ │ │ │ ├── config.md
│ │ │ │ └── dom-pose.md
│ │ │ ├── faqs.md
│ │ │ ├── react/
│ │ │ │ ├── posed.md
│ │ │ │ ├── posegroup.md
│ │ │ │ ├── react-config.md
│ │ │ │ ├── react-pose-text.md
│ │ │ │ └── supported-values.md
│ │ │ ├── react-native/
│ │ │ │ ├── native-config.md
│ │ │ │ ├── native-posed.md
│ │ │ │ ├── native-supported-values.md
│ │ │ │ └── native-transition.md
│ │ │ └── vue/
│ │ │ ├── vue-config.md
│ │ │ ├── vue-posed.md
│ │ │ ├── vue-posetransition.md
│ │ │ └── vue-supported-values.md
│ │ ├── examples/
│ │ │ ├── react/
│ │ │ │ ├── accordion.md
│ │ │ │ ├── css-variables.md
│ │ │ │ ├── enter-exit.md
│ │ │ │ ├── event-drag-boundaries.md
│ │ │ │ ├── event-drag.md
│ │ │ │ ├── event-focus.md
│ │ │ │ ├── event-hover.md
│ │ │ │ ├── event-press.md
│ │ │ │ ├── filter.md
│ │ │ │ ├── outline.md
│ │ │ │ ├── posegroup-reordering.md
│ │ │ │ ├── react-medium-style-image-zoom.md
│ │ │ │ ├── route-transitions-reach-router.md
│ │ │ │ ├── route-transitions-react-router.md
│ │ │ │ ├── splittext-as-children.md
│ │ │ │ ├── splittext-custom-animations.md
│ │ │ │ ├── splittext-ui-events.md
│ │ │ │ ├── splittext.md
│ │ │ │ └── svg-morphing.md
│ │ │ └── vue/
│ │ │ ├── vue-animating-children.md
│ │ │ ├── vue-enter-exit.md
│ │ │ ├── vue-flip.md
│ │ │ ├── vue-magic-animations.md
│ │ │ ├── vue-medium-style-image-zoom.md
│ │ │ ├── vue-passive-values.md
│ │ │ ├── vue-ui-events-dragging.md
│ │ │ ├── vue-ui-events-focus.md
│ │ │ ├── vue-ui-events-hover.md
│ │ │ └── vue-ui-events-press.md
│ │ └── learn/
│ │ ├── get-started.md
│ │ ├── how-to/
│ │ │ ├── css-variables.md
│ │ │ └── framer-x.md
│ │ ├── react/
│ │ │ ├── animating-children.md
│ │ │ ├── custom-transitions.md
│ │ │ ├── dynamic-props.md
│ │ │ ├── flip.md
│ │ │ ├── install.md
│ │ │ ├── passive.md
│ │ │ ├── popmotion-get-started.md
│ │ │ ├── react-exit-enter-transitions.md
│ │ │ ├── react-tutorial-medium-style-image-zoom.md
│ │ │ ├── route-transitions-reach-router.md
│ │ │ ├── route-transitions-react-router.md
│ │ │ └── ui-events.md
│ │ ├── react-native/
│ │ │ ├── native-animating-children.md
│ │ │ ├── native-custom-transitions.md
│ │ │ ├── native-dragging.md
│ │ │ ├── native-get-started.md
│ │ │ └── native-passive.md
│ │ └── vue/
│ │ ├── vue-animating-children.md
│ │ ├── vue-custom-transitions.md
│ │ ├── vue-dynamic-props.md
│ │ ├── vue-enter-exit-transitions.md
│ │ ├── vue-flip.md
│ │ ├── vue-get-started.md
│ │ ├── vue-install.md
│ │ ├── vue-passive.md
│ │ ├── vue-tutorial-medium-style-image-zoom.md
│ │ └── vue-ui-events.md
│ ├── projection/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE.md
│ │ ├── README.md
│ │ ├── cypress/
│ │ │ ├── fixtures/
│ │ │ │ └── example.json
│ │ │ ├── integration/
│ │ │ │ └── index.spec.js
│ │ │ ├── plugins/
│ │ │ │ └── index.js
│ │ │ ├── support/
│ │ │ │ ├── commands.js
│ │ │ │ └── index.js
│ │ │ └── tests/
│ │ │ └── index.html
│ │ ├── cypress.json
│ │ ├── package.json
│ │ ├── rollup.config.js
│ │ ├── src/
│ │ │ ├── __tests__/
│ │ │ │ └── index.test.ts
│ │ │ ├── dom/
│ │ │ │ ├── correct-border-radius.ts
│ │ │ │ ├── correct-box-shadow.ts
│ │ │ │ └── style.ts
│ │ │ ├── geometry/
│ │ │ │ ├── __tests__/
│ │ │ │ │ ├── apply.test.ts
│ │ │ │ │ └── calc.test.ts
│ │ │ │ ├── apply.ts
│ │ │ │ ├── calc.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── types.ts
│ │ │ ├── index.ts
│ │ │ ├── node.ts
│ │ │ └── types.ts
│ │ └── tsconfig.json
│ ├── site/
│ │ ├── .babelrc
│ │ ├── .gitignore
│ │ ├── components/
│ │ │ ├── examples/
│ │ │ │ ├── Ball.js
│ │ │ │ ├── CodePen.js
│ │ │ │ ├── CodeSandbox.js
│ │ │ │ ├── Counter.js
│ │ │ │ ├── Example.js
│ │ │ │ ├── Swatch.js
│ │ │ │ └── templates.js
│ │ │ ├── icons/
│ │ │ │ ├── BrandGradientDef.js
│ │ │ │ ├── DropDownArrow.js
│ │ │ │ ├── FramesyncLogo.js
│ │ │ │ ├── GitHub.js
│ │ │ │ ├── Logo.js
│ │ │ │ ├── PopcornLogo.js
│ │ │ │ ├── PopmotionIcon.js
│ │ │ │ ├── PopmotionPure.js
│ │ │ │ ├── PoseLogo.js
│ │ │ │ ├── StylefireLogo.js
│ │ │ │ └── Twitter.js
│ │ │ ├── layout/
│ │ │ │ ├── Content.js
│ │ │ │ ├── SiteLink.js
│ │ │ │ └── grid.js
│ │ │ └── template.js
│ │ ├── data/
│ │ │ ├── authors.json
│ │ │ ├── category-names.json
│ │ │ ├── route-paths.json
│ │ │ ├── section-names.json
│ │ │ ├── settings.json
│ │ │ └── site-names.json
│ │ ├── docs/
│ │ │ ├── popcorn/
│ │ │ │ └── index.md
│ │ │ └── stylefire/
│ │ │ └── index.md
│ │ ├── package.json
│ │ ├── pages/
│ │ │ ├── _document.js
│ │ │ ├── _error.js
│ │ │ ├── api.js
│ │ │ ├── blog.js
│ │ │ ├── index.js
│ │ │ ├── popcorn/
│ │ │ │ └── index.js
│ │ │ ├── pose/
│ │ │ │ ├── api.js
│ │ │ │ ├── examples.js
│ │ │ │ └── index.js
│ │ │ ├── pure/
│ │ │ │ ├── api/
│ │ │ │ │ ├── action.js
│ │ │ │ │ ├── calc.js
│ │ │ │ │ ├── chain.js
│ │ │ │ │ ├── composite.js
│ │ │ │ │ ├── crossfade.js
│ │ │ │ │ ├── css.js
│ │ │ │ │ ├── decay.js
│ │ │ │ │ ├── delay.js
│ │ │ │ │ ├── easing.js
│ │ │ │ │ ├── every-frame.js
│ │ │ │ │ ├── framesync.js
│ │ │ │ │ ├── keyframes.js
│ │ │ │ │ ├── listen.js
│ │ │ │ │ ├── merge.js
│ │ │ │ │ ├── multicast.js
│ │ │ │ │ ├── multitouch.js
│ │ │ │ │ ├── parallel.js
│ │ │ │ │ ├── physics.js
│ │ │ │ │ ├── pointer.js
│ │ │ │ │ ├── schedule.js
│ │ │ │ │ ├── scroll.js
│ │ │ │ │ ├── spring.js
│ │ │ │ │ ├── stagger.js
│ │ │ │ │ ├── stylefire.js
│ │ │ │ │ ├── svg.js
│ │ │ │ │ ├── timeline.js
│ │ │ │ │ ├── transformers.js
│ │ │ │ │ ├── tween.js
│ │ │ │ │ ├── value-types.js
│ │ │ │ │ └── value.js
│ │ │ │ ├── blog/
│ │ │ │ │ ├── 20170703-choosing-a-default-easing-for-popmotion.js
│ │ │ │ │ ├── 20170704-manually-set-scroll-while-ios-momentum-scroll-bounces.js
│ │ │ │ │ ├── 20170710-mobile-web-is-awful-and-were-all-to-blame.js
│ │ │ │ │ ├── 20170803-coding-style-dont-be-a-dick.js
│ │ │ │ │ ├── 20171210-popmotion-8-upgrade-guide.js
│ │ │ │ │ ├── 20171211-introducing-popmotion-8.js
│ │ │ │ │ ├── 20180104-when-ios-throttles-requestanimationframe.js
│ │ │ │ │ └── 20180521-pose-2-migration-guide.js
│ │ │ │ ├── index.js
│ │ │ │ └── learn/
│ │ │ │ ├── action-reaction.js
│ │ │ │ ├── circular-motion.js
│ │ │ │ ├── constrain-motion.js
│ │ │ │ ├── get-started.js
│ │ │ │ ├── input-smoothing.js
│ │ │ │ ├── input-tracking.js
│ │ │ │ ├── install.js
│ │ │ │ ├── morph-svg.js
│ │ │ │ ├── rounded-values.js
│ │ │ │ ├── spring-loaded-characters-remaining.js
│ │ │ │ ├── value-pipelines.js
│ │ │ │ └── velocity-and-physics.js
│ │ │ ├── stylefire/
│ │ │ │ ├── api/
│ │ │ │ │ ├── create-styler-factory.js
│ │ │ │ │ ├── html.js
│ │ │ │ │ ├── styler.js
│ │ │ │ │ ├── svg.js
│ │ │ │ │ └── viewport.js
│ │ │ │ ├── api.js
│ │ │ │ └── index.js
│ │ │ └── support.js
│ │ ├── public/
│ │ │ └── manifest.json
│ │ ├── scripts/
│ │ │ ├── build-next-config.js
│ │ │ ├── convert-date-format.js
│ │ │ ├── filename-operations.js
│ │ │ ├── generate-content-page.js
│ │ │ ├── generate-content.js
│ │ │ └── generate-menus.js
│ │ ├── styles/
│ │ │ ├── fonts.js
│ │ │ ├── nprogress.js
│ │ │ ├── reset.js
│ │ │ ├── syntax-highlighting.js
│ │ │ ├── themes.js
│ │ │ └── vars.js
│ │ ├── templates/
│ │ │ ├── Popcorn/
│ │ │ │ └── index.js
│ │ │ ├── Popmotion/
│ │ │ │ ├── FinalCTA/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── styled.js
│ │ │ │ ├── Header/
│ │ │ │ │ └── index.js
│ │ │ │ ├── Masthead/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── styled.js
│ │ │ │ ├── USPs/
│ │ │ │ │ ├── Example.js
│ │ │ │ │ ├── ExampleSection.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── styled.js
│ │ │ │ └── index.js
│ │ │ ├── Pose/
│ │ │ │ ├── Header/
│ │ │ │ │ └── index.js
│ │ │ │ ├── USPs/
│ │ │ │ │ ├── AnimateAnything.js
│ │ │ │ │ ├── ChildrenExample.js
│ │ │ │ │ ├── CustomExample.js
│ │ │ │ │ ├── DeclarativeExample.js
│ │ │ │ │ ├── DraggableExample.js
│ │ │ │ │ ├── FlipExample.js
│ │ │ │ │ ├── PassiveExample.js
│ │ │ │ │ ├── PluginsExample.js
│ │ │ │ │ ├── ReactExample.js
│ │ │ │ │ ├── ZeroConfigExample.js
│ │ │ │ │ └── index.js
│ │ │ │ └── index.js
│ │ │ ├── Stylefire/
│ │ │ │ └── index.js
│ │ │ ├── blog/
│ │ │ │ ├── components/
│ │ │ │ │ └── BlogItem/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── styled.js
│ │ │ │ └── index.js
│ │ │ ├── content/
│ │ │ │ ├── ContentCTA/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── styled.js
│ │ │ │ ├── ContentNav.js
│ │ │ │ ├── MenuPage/
│ │ │ │ │ └── index.js
│ │ │ │ ├── PostDetails/
│ │ │ │ │ └── index.js
│ │ │ │ ├── TableOfContents/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── styled.js
│ │ │ │ ├── Template.js
│ │ │ │ └── styled.js
│ │ │ ├── global/
│ │ │ │ ├── Analytics.js
│ │ │ │ ├── Footer.js
│ │ │ │ ├── Header.js
│ │ │ │ ├── SectionNav.js
│ │ │ │ ├── SocialLinks.js
│ │ │ │ ├── Template.js
│ │ │ │ ├── grid.js
│ │ │ │ └── styled.js
│ │ │ ├── global-new/
│ │ │ │ ├── ContentPage/
│ │ │ │ │ └── index.js
│ │ │ │ ├── Footer/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── styled.js
│ │ │ │ ├── Header/
│ │ │ │ │ └── index.js
│ │ │ │ ├── Nav/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── styled.js
│ │ │ │ └── styled.js
│ │ │ └── homepage/
│ │ │ └── index.js
│ │ └── utils/
│ │ └── string.js
│ └── style-value-types/
│ ├── CHANGELOG.md
│ ├── LICENSE.md
│ ├── README.md
│ ├── package.json
│ ├── rollup.config.js
│ ├── src/
│ │ ├── _tests/
│ │ │ └── index.test.ts
│ │ ├── color/
│ │ │ ├── hex.ts
│ │ │ ├── hsla.ts
│ │ │ ├── index.ts
│ │ │ ├── rgba.ts
│ │ │ └── utils.ts
│ │ ├── complex/
│ │ │ ├── filter.ts
│ │ │ └── index.ts
│ │ ├── index.ts
│ │ ├── numbers/
│ │ │ ├── index.ts
│ │ │ └── units.ts
│ │ ├── types.ts
│ │ └── utils.ts
│ ├── tsconfig.json
│ └── tslint.json
├── playground/
│ ├── animate.js
│ ├── index.js
│ └── worklet.js
├── rollup-generate-config.js
├── tsconfig.json
├── tslint.json
└── types/
├── animations/
│ ├── decay.d.ts
│ ├── index.d.ts
│ ├── inertia.d.ts
│ ├── keyframes.d.ts
│ ├── spring.d.ts
│ ├── types.d.ts
│ └── utils/
│ └── detect-animation-from-options.d.ts
├── easing/
│ ├── cubic-bezier.d.ts
│ ├── index.d.ts
│ ├── steps.d.ts
│ ├── types.d.ts
│ └── utils.d.ts
├── global.d.ts
├── index.d.ts
├── types.d.ts
├── utils/
│ ├── angle.d.ts
│ ├── apply-offset.d.ts
│ ├── attract.d.ts
│ ├── clamp.d.ts
│ ├── degrees-to-radians.d.ts
│ ├── distance.d.ts
│ ├── inc.d.ts
│ ├── interpolate.d.ts
│ ├── is-point-3d.d.ts
│ ├── is-point.d.ts
│ ├── mix-color.d.ts
│ ├── mix-complex.d.ts
│ ├── mix.d.ts
│ ├── pipe.d.ts
│ ├── point-from-vector.d.ts
│ ├── progress.d.ts
│ ├── radians-to-degrees.d.ts
│ ├── smooth-frame.d.ts
│ ├── smooth.d.ts
│ ├── snap.d.ts
│ ├── to-decimal.d.ts
│ ├── velocity-per-frame.d.ts
│ ├── velocity-per-second.d.ts
│ └── wrap.d.ts
└── worklet/
├── custom-properties.d.ts
└── load-worklet.d.ts
SYMBOL INDEX (242 symbols across 80 files)
FILE: .storybook/config.js
function loadStories (line 3) | function loadStories() {
FILE: packages/blend-tweens/blend-tweens.js
function calcValueAtTime (line 8) | function calcValueAtTime(from, to, duration, elapsed, ease) {
FILE: packages/blend-tweens/cross-fade.js
class CrossFade (line 6) | class CrossFade extends Action {
method onStart (line 11) | onStart() {
method update (line 21) | update() {
FILE: packages/framesync/src/create-render-step.ts
function createRenderStep (line 3) | function createRenderStep(runNextFrame: () => void): Step {
FILE: packages/framesync/src/types.ts
type FrameData (line 1) | type FrameData = {
type Process (line 6) | type Process = (data: FrameData) => void
type Schedule (line 8) | type Schedule = (
type Step (line 14) | interface Step {
type StepId (line 20) | type StepId =
type Sync (line 28) | type Sync = {
type Steps (line 32) | type Steps = {
type CancelSync (line 36) | type CancelSync = {
type FlushSync (line 40) | type FlushSync = {
FILE: packages/popmotion/src/animations/__tests__/animate.test.ts
function testAnimate (line 6) | function testAnimate<V>(
FILE: packages/popmotion/src/animations/__tests__/inertia.test.ts
function testInertia (line 5) | async function testInertia(
FILE: packages/popmotion/src/animations/generators/__tests__/utils.ts
function animateSync (line 3) | function animateSync(
FILE: packages/popmotion/src/animations/generators/decay.ts
function decay (line 3) | function decay({
FILE: packages/popmotion/src/animations/generators/keyframes.ts
function defaultEasing (line 6) | function defaultEasing(values: any[], easing?: Easing): Easing[] {
function defaultOffset (line 10) | function defaultOffset(values: any[]): number[] {
function convertOffsetToTimes (line 17) | function convertOffsetToTimes(offset: number[], duration: number) {
function keyframes (line 21) | function keyframes<V>({
FILE: packages/popmotion/src/animations/generators/spring.ts
function isSpringType (line 12) | function isSpringType(options: SpringOptions, keys: string[]) {
function getSpringOptions (line 16) | function getSpringOptions(
function spring (line 53) | function spring({
FILE: packages/popmotion/src/animations/index.ts
function animate (line 25) | function animate<V = number>({
FILE: packages/popmotion/src/animations/inertia.ts
function inertia (line 11) | function inertia({
FILE: packages/popmotion/src/animations/types.ts
type Animation (line 3) | interface Animation<V> {
type AnimationState (line 14) | interface AnimationState<V> {
type PlaybackControls (line 19) | interface PlaybackControls {
type Update (line 26) | type Update = (timestamp: number) => void
type DriverControls (line 32) | interface DriverControls {
type Driver (line 36) | type Driver = (update: Update) => DriverControls
type PlaybackOptions (line 41) | interface PlaybackOptions<V> {
type KeyframeOptions (line 63) | interface KeyframeOptions<V = number> {
type DecayOptions (line 71) | interface DecayOptions {
type PhysicsSpringOptions (line 81) | interface PhysicsSpringOptions {
type SpringOptions (line 88) | interface SpringOptions extends PhysicsSpringOptions {
type InertiaOptions (line 97) | interface InertiaOptions extends DecayOptions {
type AnimationOptions (line 110) | type AnimationOptions<V> = PlaybackOptions<V> &
FILE: packages/popmotion/src/animations/utils/detect-animation-from-options.ts
type Options (line 11) | interface Options {
function detectAnimationFromOptions (line 16) | function detectAnimationFromOptions<T extends Options>(config: T) {
FILE: packages/popmotion/src/animations/utils/elapsed.ts
function loopElapsed (line 1) | function loopElapsed(elapsed: number, duration: number, delay = 0) {
function reverseElapsed (line 5) | function reverseElapsed(
function hasRepeatDelayElapsed (line 16) | function hasRepeatDelayElapsed(
FILE: packages/popmotion/src/animations/utils/find-spring.ts
type Resolver (line 9) | type Resolver = (num: number) => number
function findSpring (line 17) | function findSpring({
function approximateRoot (line 101) | function approximateRoot(
function calcAngularFreq (line 113) | function calcAngularFreq(undampedFreq: number, dampingRatio: number) {
FILE: packages/popmotion/src/easing/cubic-bezier.ts
function binarySubdivide (line 32) | function binarySubdivide(
function newtonRaphsonIterate (line 61) | function newtonRaphsonIterate(
function cubicBezier (line 81) | function cubicBezier(
FILE: packages/popmotion/src/easing/index.ts
constant DEFAULT_OVERSHOOT_STRENGTH (line 10) | const DEFAULT_OVERSHOOT_STRENGTH = 1.525
constant BOUNCE_FIRST_THRESHOLD (line 11) | const BOUNCE_FIRST_THRESHOLD = 4.0 / 11.0
constant BOUNCE_SECOND_THRESHOLD (line 12) | const BOUNCE_SECOND_THRESHOLD = 8.0 / 11.0
constant BOUNCE_THIRD_THRESHOLD (line 13) | const BOUNCE_THIRD_THRESHOLD = 9.0 / 10.0
FILE: packages/popmotion/src/easing/steps.ts
type Direction (line 10) | type Direction = 'start' | 'end';
FILE: packages/popmotion/src/easing/types.ts
type Easing (line 1) | type Easing = (v: number) => number;
type EasingModifier (line 2) | type EasingModifier = (easing: Easing) => Easing;
FILE: packages/popmotion/src/types.ts
type Point2D (line 1) | type Point2D = {
type Point3D (line 6) | type Point3D = Point2D & {
type Point (line 10) | type Point = Point2D | Point3D;
FILE: packages/popmotion/src/utils/distance.ts
function distance (line 18) | function distance<P extends Point | number>(a: P, b: P): number {
FILE: packages/popmotion/src/utils/hsla-to-rgba.ts
function hueToRgb (line 4) | function hueToRgb(p: number, q: number, t: number) {
function hslaToRgba (line 13) | function hslaToRgba({ hue, saturation, lightness, alpha }: HSLA): RGBA {
FILE: packages/popmotion/src/utils/interpolate.ts
type MixEasing (line 11) | type MixEasing = Easing | Easing[];
type InterpolateOptions (line 13) | type InterpolateOptions<T> = {
type Mix (line 19) | type Mix<T> = (v: number) => T;
type MixerFactory (line 20) | type MixerFactory<T> = (from: T, to: T) => Mix<T>;
function detectMixerFactory (line 24) | function detectMixerFactory<T>(v: T): MixerFactory<any> {
function createMixers (line 40) | function createMixers<T>(
function fastInterpolate (line 64) | function fastInterpolate<T>([from, to]: number[], [mixer]: Array<Mix<T>>) {
function slowInterpolate (line 68) | function slowInterpolate<T>(input: number[], mixers: Array<Mix<T>>) {
function interpolate (line 118) | function interpolate<T>(
FILE: packages/popmotion/src/utils/mix-complex.ts
type MixComplex (line 8) | type MixComplex = (p: number) => string
type BlendableArray (line 10) | type BlendableArray = Array<number | RGBA | HSLA | string>
type BlendableObject (line 11) | type BlendableObject = {
function getMixer (line 15) | function getMixer(origin: any, target: any) {
function analyse (line 57) | function analyse(value: string | number) {
FILE: packages/popmotion/src/utils/velocity-per-frame.ts
function velocityPerFrame (line 7) | function velocityPerFrame(xps: number, frameDuration: number) {
FILE: packages/popmotion/src/utils/velocity-per-second.ts
function velocityPerSecond (line 7) | function velocityPerSecond(velocity: number, frameDuration: number) {
FILE: packages/popmotion/src/worklet/custom-properties.ts
type CustomProperty (line 1) | interface CustomProperty {
function namespace (line 40) | function namespace(name: string) {
function registerCustomProperties (line 44) | function registerCustomProperties() {
FILE: packages/popmotion/src/worklet/load-worklet.ts
type Resolve (line 1) | type Resolve = () => void
function whenWorkletReady (line 7) | async function whenWorkletReady() {
function flushAwaiting (line 15) | function flushAwaiting() {
function workletReady (line 19) | function workletReady() {
FILE: packages/projection/src/dom/correct-border-radius.ts
function pixelsToPercent (line 4) | function pixelsToPercent(pixels: number, axis: Axis): number {
function correctBorderRadius (line 17) | function correctBorderRadius(latest: string | number, node: LayoutNode) {
FILE: packages/projection/src/dom/correct-box-shadow.ts
function correctBoxShadow (line 15) | function correctBoxShadow(latest: string, node: LayoutNode) {
FILE: packages/projection/src/dom/style.ts
function updateProjectionStyle (line 3) | function updateProjectionStyle(
FILE: packages/projection/src/geometry/apply.ts
function resetAxis (line 4) | function resetAxis(axis: Axis, originAxis: Axis) {
function resetBox (line 9) | function resetBox(box: Box, originBox: Box) {
function scalePoint (line 17) | function scalePoint(point: number, scale: number, originPoint: number) {
function applyPointProjection (line 26) | function applyPointProjection(
function applyAxisProjection (line 43) | function applyAxisProjection(
function applyBoxProjection (line 70) | function applyBoxProjection(box: Box, { x, y }: Projection): void {
function applyTreeProjection (line 79) | function applyTreeProjection(
FILE: packages/projection/src/geometry/calc.ts
function isNear (line 7) | function isNear(value: number, target = 0, maxDistance = 0.01): boolean {
function calcLength (line 11) | function calcLength(axis: Axis) {
function calcOrigin (line 19) | function calcOrigin(source: Axis, target: Axis): number {
function updateAxisProjection (line 39) | function updateAxisProjection(
function updateBoxProjection (line 63) | function updateBoxProjection(
function calcRelativeAxis (line 73) | function calcRelativeAxis(
function calcRelativeBox (line 83) | function calcRelativeBox(
FILE: packages/projection/src/geometry/types.ts
type Axis (line 1) | interface Axis {
type Box (line 7) | interface Box {
type RelativeBox (line 12) | interface RelativeBox {
type BoundingBox (line 17) | interface BoundingBox {
type Point (line 24) | interface Point {
type AxisProjection (line 29) | interface AxisProjection {
type Projection (line 36) | interface Projection {
FILE: packages/projection/src/node.ts
function layoutNode (line 8) | function layoutNode(
function fireUpdateProjection (line 203) | function fireUpdateProjection(node: LayoutNode) {
FILE: packages/projection/src/types.ts
type LayoutNode (line 3) | interface LayoutNode {
type NodeOptions (line 33) | interface NodeOptions {
FILE: packages/site/components/examples/CodeSandbox.js
class CodeSandbox (line 12) | class CodeSandbox extends React.Component {
method render (line 21) | render() {
FILE: packages/site/components/template.js
function TaglineCharacter (line 15) | function TaglineCharacter({ character, index }) {
function USP (line 148) | function USP({ title, children }) {
function Tick (line 158) | function Tick() {
FILE: packages/site/pages/_document.js
class PageTemplate (line 6) | class PageTemplate extends Document {
method render (line 7) | render() {
FILE: packages/site/scripts/filename-operations.js
constant DS_STORE (line 1) | const DS_STORE = '.DS_Store';
FILE: packages/site/scripts/generate-content.js
function generateContent (line 20) | function generateContent({
FILE: packages/site/styles/vars.js
constant WHITE (line 7) | const WHITE = '#fff';
constant BLACK (line 8) | const BLACK = '#3d454e';
constant SUPER_LIGHT_GREY (line 9) | const SUPER_LIGHT_GREY = '#FAFAFA';
constant LIGHT_GREY (line 10) | const LIGHT_GREY = '#f2f2f2';
constant PINK (line 12) | const PINK = '#FF1C68';
constant PINK_BURN (line 13) | const PINK_BURN = '#DB0068';
constant BLUE (line 15) | const BLUE = '#09f';
constant BLUE_BURN (line 16) | const BLUE_BURN = '#064FB5';
constant GREEN (line 18) | const GREEN = '#14D790';
constant PURPLE (line 19) | const PURPLE = '#9B65DE';
constant BRAND (line 21) | const BRAND = PINK;
constant BRAND_BURN (line 22) | const BRAND_BURN = PINK_BURN;
constant BRAND_GRADIENT (line 23) | const BRAND_GRADIENT = verticalGradient(PINK, PINK_BURN);
constant ACTION (line 25) | const ACTION = BLUE;
constant ACTION_BURN (line 26) | const ACTION_BURN = BLUE_BURN;
constant ACTION_GRADIENT (line 27) | const ACTION_GRADIENT = verticalGradient(BLUE, BLUE_BURN);
constant ENTITY (line 29) | const ENTITY = PURPLE;
constant SKEW (line 60) | const SKEW = '-5.7deg';
constant UNSKEW (line 61) | const UNSKEW = '5.7deg';
constant COL_WIDTH (line 63) | const COL_WIDTH = 15;
FILE: packages/site/templates/Popmotion/Masthead/styled.js
constant CTA (line 97) | const CTA = styled.div`
FILE: packages/site/templates/Popmotion/USPs/styled.js
constant MAX_WIDTH (line 6) | const MAX_WIDTH = cols(60);
FILE: packages/site/templates/Pose/USPs/AnimateAnything.js
class Example (line 42) | class Example extends React.Component {
method componentDidMount (line 45) | componentDidMount() {
method componentWillUnmount (line 49) | componentWillUnmount() {
method render (line 55) | render() {
FILE: packages/site/templates/Pose/USPs/ChildrenExample.js
class Example (line 83) | class Example extends React.Component {
method componentDidMount (line 86) | componentDidMount() {
method componentWillUnmount (line 90) | componentWillUnmount() {
method render (line 96) | render() {
FILE: packages/site/templates/Pose/USPs/CustomExample.js
class Example (line 55) | class Example extends React.Component {
method componentDidMount (line 58) | componentDidMount() {
method componentWillUnmount (line 62) | componentWillUnmount() {
method render (line 68) | render() {
FILE: packages/site/templates/Pose/USPs/DeclarativeExample.js
class Example (line 34) | class Example extends React.Component {
method componentDidMount (line 37) | componentDidMount() {
method componentWillUnmount (line 41) | componentWillUnmount() {
method render (line 47) | render() {
FILE: packages/site/templates/Pose/USPs/DraggableExample.js
class Example (line 51) | class Example extends React.Component {
method render (line 52) | render() {
FILE: packages/site/templates/Pose/USPs/FlipExample.js
class Example (line 69) | class Example extends React.Component {
method componentDidMount (line 95) | componentDidMount() {
method componentWillUnmount (line 113) | componentWillUnmount() {
method componentDidUpdate (line 117) | componentDidUpdate() {
method render (line 123) | render() {
FILE: packages/site/templates/Pose/USPs/PassiveExample.js
class Example (line 49) | class Example extends React.Component {
method componentDidMount (line 52) | componentDidMount() {
method componentWillUnmount (line 56) | componentWillUnmount() {
method render (line 62) | render() {
FILE: packages/site/templates/Pose/USPs/PluginsExample.js
class Example (line 36) | class Example extends React.Component {
method render (line 37) | render() {
FILE: packages/site/templates/Pose/USPs/ReactExample.js
function shuffle (line 79) | function shuffle(array) {
class Example (line 99) | class Example extends React.Component {
method componentDidMount (line 102) | componentDidMount() {
method componentWillUnmount (line 106) | componentWillUnmount() {
method render (line 112) | render() {
FILE: packages/site/templates/Pose/USPs/ZeroConfigExample.js
class Example (line 43) | class Example extends React.Component {
method componentDidMount (line 46) | componentDidMount() {
method componentWillUnmount (line 50) | componentWillUnmount() {
method render (line 56) | render() {
FILE: packages/site/templates/Pose/USPs/index.js
class Examples (line 21) | class Examples extends React.Component {
method render (line 31) | render() {
FILE: packages/site/templates/content/ContentNav.js
class ContentNav (line 132) | class ContentNav extends React.PureComponent {
method render (line 133) | render() {
FILE: packages/site/templates/content/Template.js
class Template (line 17) | class Template extends React.PureComponent {
method render (line 27) | render() {
FILE: packages/site/templates/global/Footer.js
constant YEAR (line 9) | const YEAR = new Date().getFullYear();
FILE: packages/site/utils/string.js
function htmlUnencode (line 1) | function htmlUnencode(str) {
FILE: packages/style-value-types/src/_tests/index.test.ts
constant PATH (line 17) | const PATH = 'M150 0 L75 200 L225 200 Z';
constant GREYSCALE (line 18) | const GREYSCALE = 'greyscale(100%)';
constant PATH_VALUES (line 19) | const PATH_VALUES = [150, 0, 75, 200, 225, 200];
constant MIXED (line 20) | const MIXED = '0px 0px 0px rgba(161, 0, 246, 0)';
FILE: packages/style-value-types/src/color/hex.ts
function parseHex (line 5) | function parseHex(v: string): RGBA {
FILE: packages/style-value-types/src/complex/filter.ts
function applyDefaultFilter (line 9) | function applyDefaultFilter(v: string) {
FILE: packages/style-value-types/src/complex/index.ts
function test (line 9) | function test(v: any) {
function analyse (line 17) | function analyse(v: string | number) {
function parse (line 41) | function parse(v: string | number) {
function createTransformer (line 45) | function createTransformer(v: string | number) {
function getAnimatableNone (line 66) | function getAnimatableNone(v: string | number) {
FILE: packages/style-value-types/src/types.ts
type Transformer (line 1) | type Transformer = (v: any) => any;
type ValueType (line 3) | type ValueType = {
type NumberMap (line 12) | type NumberMap = {
type RGBA (line 16) | type RGBA = {
type HSLA (line 23) | type HSLA = {
type Color (line 30) | type Color = HSLA | RGBA;
FILE: packages/style-value-types/src/utils.ts
function isString (line 12) | function isString(v: any): v is string {
FILE: playground/animate.js
function Keyframes (line 13) | function Keyframes() {
FILE: playground/worklet.js
function Tween (line 15) | function Tween() {
FILE: types/animations/decay.d.ts
class DecayAnimator (line 2) | class DecayAnimator implements Animator<DecayOptions, number> {
FILE: types/animations/keyframes.d.ts
class KeyframesAnimator (line 9) | class KeyframesAnimator
FILE: types/animations/spring.d.ts
class SpringAnimator (line 2) | class SpringAnimator implements Animator<SpringOptions, number> {
FILE: types/animations/types.d.ts
type Animatable (line 5) | type Animatable = string | number;
type Animator (line 9) | interface Animator<O, V> {
type PlaybackControls (line 15) | interface PlaybackControls {
type Update (line 26) | type Update = (timestamp: number) => void;
type Driver (line 31) | type Driver = (update: Update) => () => void;
type PlaybackOptions (line 35) | interface PlaybackOptions<V extends Animatable> {
type KeyframeOptions (line 53) | interface KeyframeOptions<V extends Animatable = number> {
type DecayOptions (line 60) | interface DecayOptions<T extends Animatable = number> {
type SpringOptions (line 69) | interface SpringOptions<T extends Animatable = number> {
type AnimationOptions (line 79) | type AnimationOptions<V extends Animatable> = PlaybackOptions<
FILE: types/animations/utils/detect-animation-from-options.d.ts
type Options (line 4) | interface Options {}
FILE: types/easing/steps.d.ts
type Direction (line 2) | type Direction = 'start' | 'end';
FILE: types/easing/types.d.ts
type Easing (line 1) | type Easing = (v: number) => number;
type EasingModifier (line 2) | type EasingModifier = (easing: Easing) => Easing;
FILE: types/types.d.ts
type Point2D (line 1) | type Point2D = {
type Point3D (line 5) | type Point3D = Point2D & {
type Point (line 8) | type Point = Point2D | Point3D;
FILE: types/utils/distance.d.ts
type _Point (line 2) | type _Point = Point | number;
FILE: types/utils/interpolate.d.ts
type MixEasing (line 2) | type MixEasing = Easing | Easing[];
type InterpolateOptions (line 3) | type InterpolateOptions<T> = {
type Mix (line 8) | type Mix<T> = (v: number) => T;
type MixerFactory (line 9) | type MixerFactory<T> = (from: T, to: T) => Mix<T>;
FILE: types/utils/mix-complex.d.ts
type MixComplex (line 2) | type MixComplex = (p: number) => string;
type BlendableObject (line 3) | type BlendableObject = {
Condensed preview — 536 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,260K chars).
[
{
"path": ".babelrc",
"chars": 198,
"preview": "{\n \"presets\": [[\"env\", { \"loose\": true} ], \"stage-2\"],\n \"plugins\": [\"transform-export-extensions\", \"transform-react-js"
},
{
"path": ".circleci/config.yml",
"chars": 1022,
"preview": "# Javascript Node CircleCI 2.0 configuration file\n#\n# Check https://circleci.com/docs/2.0/language-javascript/ for more "
},
{
"path": ".eslintrc",
"chars": 605,
"preview": "{\n \"rules\": {\n \"strict\": 0,\n \"indent\": [2, 2],\n \"quotes\": [2, \"single\"],\n \"linebreak-style\": [2, \"unix\"],\n "
},
{
"path": ".github/ISSUE_TEMPLATE/Feature_request.md",
"chars": 560,
"preview": "---\nname: Feature request\nabout: Suggest an idea for this project\n\n---\n\n**Is your feature request related to a problem? "
},
{
"path": ".github/ISSUE_TEMPLATE/bug-report.md",
"chars": 867,
"preview": "---\nname: Bug report\nabout: Create a report to help us improve\n\n---\n\n## Ensure you're using the latest version\nCodeSandb"
},
{
"path": ".gitignore",
"chars": 454,
"preview": "node_modules\n.DS_Store\nlib\npackages/site/.next\npackages/site/pages/api\npackages/site/pages/learn\npackages/site/pages/blo"
},
{
"path": ".prettierignore",
"chars": 4,
"preview": "*.md"
},
{
"path": ".storybook/config.js",
"chars": 135,
"preview": "import { configure } from '@storybook/react';\n\nfunction loadStories() {\n require('../playground');\n}\n\nconfigure(loadSto"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 150,
"preview": "# Code of conduct\n\n.\n\n## [6.1.2] 2022-08-15\n\n### Update\n\n- `ts"
},
{
"path": "packages/framesync/LICENSE.md",
"chars": 1064,
"preview": "MIT License\n\nCopyright © 2019 Framer BV\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof"
},
{
"path": "packages/framesync/README.md",
"chars": 2533,
"preview": "# Framesync\n\nA tiny frame scheduler for performantly batching reads, updates and renders.\n\nSegregating actions that read"
},
{
"path": "packages/framesync/package.json",
"chars": 1751,
"preview": "{\n \"name\": \"framesync\",\n \"license\": \"MIT\",\n \"version\": \"6.1.2\",\n \"description\": \"A frame-synced render loop "
},
{
"path": "packages/framesync/rollup.config.js",
"chars": 130,
"preview": "import generateConfig from '../../rollup-generate-config';\nimport pkg from './package.json';\n\nexport default generateCon"
},
{
"path": "packages/framesync/src/_tests/test.ts",
"chars": 4705,
"preview": "import sync, { cancelSync, flushSync } from \"../\"\nimport { onNextFrame } from \"../on-next-frame\"\n\ndescribe(\"onNextFrame\""
},
{
"path": "packages/framesync/src/create-render-step.ts",
"chars": 3187,
"preview": "import { Step, Process } from \"./types\"\n\nexport function createRenderStep(runNextFrame: () => void): Step {\n /**\n "
},
{
"path": "packages/framesync/src/index.ts",
"chars": 1938,
"preview": "import { onNextFrame, defaultTimestep } from \"./on-next-frame\"\nimport { createRenderStep } from \"./create-render-step\"\ni"
},
{
"path": "packages/framesync/src/on-next-frame.ts",
"chars": 535,
"preview": "/*\n Detect and load appropriate clock setting for the execution environment\n */\nexport const defaultTimestep = (1 / 60)"
},
{
"path": "packages/framesync/src/types.ts",
"chars": 721,
"preview": "export type FrameData = {\n delta: number\n timestamp: number\n}\n\nexport type Process = (data: FrameData) => void\n\nex"
},
{
"path": "packages/framesync/tsconfig.json",
"chars": 164,
"preview": "{\n \"extends\": \"../../tsconfig.json\",\n \"compilerOptions\": {\n \"declarationDir\": \"lib\",\n \"rootDir\": \"src\",\n \"out"
},
{
"path": "packages/popcorn/docs/api/utilities/angle.md",
"chars": 444,
"preview": "---\ntitle: angle\ndescription: Returns the angle between two 2D points.\ncategory: functions\n---\n\n# `angle`\n\n`angle` retur"
},
{
"path": "packages/popcorn/docs/api/utilities/apply-offset.md",
"chars": 1059,
"preview": "---\ntitle: applyOffset\ndescription: Creates a function that measures the offset of incoming values and applies it to an "
},
{
"path": "packages/popcorn/docs/api/utilities/clamp.md",
"chars": 852,
"preview": "---\ntitle: clamp\ndescription: Restricts a number to within the defined range.\ncategory: functions\n---\n\n# `clamp`\n\n`clamp"
},
{
"path": "packages/popcorn/docs/api/utilities/conditional.md",
"chars": 925,
"preview": "---\ntitle: conditional\ndescription: Creates a function that conditionally transforms provided values.\ncategory: function"
},
{
"path": "packages/popcorn/docs/api/utilities/degreesToRadians.md",
"chars": 393,
"preview": "---\ntitle: degreesToRadians\ndescription: Converts degrees to radians.\ncategory: functions\n---\n\n# `degreesToRadians`\n\n`de"
},
{
"path": "packages/popcorn/docs/api/utilities/distance.md",
"chars": 774,
"preview": "---\ntitle: distance\ndescription: Calculate the distance between two n-dimensional points.\ncategory: functions\n---\n\n# `di"
},
{
"path": "packages/popcorn/docs/api/utilities/interpolate.md",
"chars": 2471,
"preview": "---\ntitle: interpolate\ndescription: Map from a series of numbers to a range of numbers, colors or strings.\ncategory: fun"
},
{
"path": "packages/popcorn/docs/api/utilities/is-point-3d.md",
"chars": 460,
"preview": "---\ntitle: isPoint3D\ndescription: Test a value for x, y and z properties.\ncategory: functions\n---\n\n# `isPoint3D`\n\nReturn"
},
{
"path": "packages/popcorn/docs/api/utilities/is-point.md",
"chars": 401,
"preview": "---\ntitle: isPoint\ndescription: Test a value for an `x` and `y` property.\ncategory: functions\n---\n\n# `isPoint`\n\nReturns "
},
{
"path": "packages/popcorn/docs/api/utilities/mix-array.md",
"chars": 1059,
"preview": "---\ntitle: mixArray\ndescription: Creates a function that can interpolate between two arrays of matching value types.\ncat"
},
{
"path": "packages/popcorn/docs/api/utilities/mix-color.md",
"chars": 915,
"preview": "---\ntitle: mixColor\ndescription: Creates a function that can interpolate between two hex, rgba or hsla colors.\ncategory:"
},
{
"path": "packages/popcorn/docs/api/utilities/mix-complex.md",
"chars": 1150,
"preview": "---\ntitle: mixComplex\ndescription: Creates a function that can mix between two strings that contain one or more numbers "
},
{
"path": "packages/popcorn/docs/api/utilities/mix.md",
"chars": 396,
"preview": "---\ntitle: mix\ndescription: Mixes between two numbers\ncategory: functions\n---\n\n# `mix`\n\n`mix` can interpolate between tw"
},
{
"path": "packages/popcorn/docs/api/utilities/pipe.md",
"chars": 694,
"preview": "---\ntitle: pipe\ndescription: Left-to-right function composition.\ncategory: functions\n---\n\n# `pipe`\n\n`pipe` composes a ne"
},
{
"path": "packages/popcorn/docs/api/utilities/point-from-vector.md",
"chars": 592,
"preview": "---\ntitle: pointFromVector\ndescription: Calculates a point, given a point and vector (angle and distance)\ncategory: func"
},
{
"path": "packages/popcorn/docs/api/utilities/progress.md",
"chars": 537,
"preview": "---\ntitle: progress\ndescription: Calculates the progress of a value between in a given range.\ncategory: functions\n---\n\n#"
},
{
"path": "packages/popcorn/docs/api/utilities/radians-to-degrees.md",
"chars": 400,
"preview": "---\ntitle: radiansToDegrees\ndescription: Converts radians to degrees.\ncategory: functions\n---\n\n# `radiansToDegrees`\n\n`ra"
},
{
"path": "packages/popcorn/docs/api/utilities/smooth-frame.md",
"chars": 1141,
"preview": "---\ntitle: smoothFrame\ndescription: Smooth the motion from one value to a new value over a single frame.\ncategory: funct"
},
{
"path": "packages/popcorn/docs/api/utilities/smooth.md",
"chars": 1106,
"preview": "---\ntitle: smooth\ndescription: Creates a function that will smooth values across frames when used with Framesync or Popm"
},
{
"path": "packages/popcorn/docs/api/utilities/snap.md",
"chars": 809,
"preview": "---\ntitle: snap\ndescription: Creates a function that will snap provided values to regular intervals, or to numbers provi"
},
{
"path": "packages/popcorn/docs/api/utilities/to-decimal.md",
"chars": 442,
"preview": "---\ntitle: toDecimal\ndescription: Rounds a number to a specified decimal place.\ncategory: functions\n---\n\n# `toDecimal`\n\n"
},
{
"path": "packages/popcorn/docs/api/utilities/velocity-per-frame.md",
"chars": 672,
"preview": "---\ntitle: velocityPerFrame\ndescription: Converts velocity per second into velocity per frame.\ncategory: functions\n---\n\n"
},
{
"path": "packages/popcorn/docs/api/utilities/velocity-per-second.md",
"chars": 740,
"preview": "---\ntitle: velocityPerSecond\ndescription: Converts velocity per frame into velocity per second.\ncategory: functions\n---\n"
},
{
"path": "packages/popcorn/docs/api/utilities/wrap.md",
"chars": 658,
"preview": "---\ntitle: wrap\ndescription: Wraps a number when it breaches the defined range.\ncategory: functions\n---\n\n# `wrap`\n\nWraps"
},
{
"path": "packages/popmotion/.gitignore",
"chars": 33,
"preview": "/*.js\n/*.js.map\n*.d.ts\n/coverage\n"
},
{
"path": "packages/popmotion/.npmignore",
"chars": 50,
"preview": "*.md\n*.map\ndocs\nwebpack.config.js\ntmp\ncoverage\nsrc"
},
{
"path": "packages/popmotion/CHANGELOG.md",
"chars": 37395,
"preview": "# Changelog\n\nPopmotion adheres to [Semantic Versioning](http://semver.org/).\n\n## [11.0.5] 2022-08-15\n\n### Update\n\n- `t"
},
{
"path": "packages/popmotion/LICENSE.md",
"chars": 1073,
"preview": "The MIT License (MIT)\n\nCopyright © 2019 Framer BV\n\nPermission is hereby granted, free of charge, to any person obtaining"
},
{
"path": "packages/popmotion/README.md",
"chars": 191,
"preview": "# <a href=\"https://popmotion.io\"><img src=\"https://cloud.githubusercontent.com/assets/7850794/21642571/1910a15e-d27b-11e"
},
{
"path": "packages/popmotion/docs/api/action.md",
"chars": 4534,
"preview": "---\ntitle: Action\ndescription: Create a reactive stream of values.\nnext: animations\n---\n\n# Action\n\nAction is a simplifie"
},
{
"path": "packages/popmotion/docs/api/animation/decay.md",
"chars": 3118,
"preview": "---\ntitle: Decay\ndescription: Exponential deceleration, primarily for use in momentum scrolling.\ncategory: animation\n---"
},
{
"path": "packages/popmotion/docs/api/animation/every-frame.md",
"chars": 1021,
"preview": "---\ntitle: Every Frame\ndescription: Fires with timestamp, once every frame.\ncategory: animation\n---\n\n# Every Frame\n\n`eve"
},
{
"path": "packages/popmotion/docs/api/animation/inertia.md",
"chars": 3539,
"preview": "---\ntitle: Inertia\ndescription: Inertial scrolling with spring-loaded boundaries.\ncategory: animation\n---\n\n# Inertia\n\nAn"
},
{
"path": "packages/popmotion/docs/api/animation/keyframes.md",
"chars": 5855,
"preview": "---\ntitle: Keyframes\ndescription: Animate through a linear sequence of values.\ncategory: animation\n---\n\n# Keyframes\n\nKey"
},
{
"path": "packages/popmotion/docs/api/animation/physics.md",
"chars": 4510,
"preview": "---\ntitle: Physics\ndescription: Integrated simulation of velocity, acceleration, friction and springs.\ncategory: animati"
},
{
"path": "packages/popmotion/docs/api/animation/spring.md",
"chars": 4821,
"preview": "---\ntitle: Spring\ndescription: Accurate, versatile spring animation.\ncategory: animation\n---\n\n# Spring\n\nA spring animati"
},
{
"path": "packages/popmotion/docs/api/animation/timeline.md",
"chars": 6719,
"preview": "---\ntitle: Timeline\ndescription: Sequence a multitrack animation with full playback controls.\ncategory: animation\n---\n\n#"
},
{
"path": "packages/popmotion/docs/api/animation/tween.md",
"chars": 5053,
"preview": "---\ntitle: Tween\ndescription: Animate between two values over a set duration of time.\ncategory: animation\n---\n\n# Tween\n\n"
},
{
"path": "packages/popmotion/docs/api/calc.md",
"chars": 113,
"preview": "---\ntitle: Calculators\ndescription: Simple functions useful in UI calculations.\n---\n\nMoved to [Popcorn](/popcorn)"
},
{
"path": "packages/popmotion/docs/api/compositors/chain.md",
"chars": 1062,
"preview": "---\ntitle: Chain\ndescription: Chain a sequence of actions, move to the next when the current one completes.\ncategory: co"
},
{
"path": "packages/popmotion/docs/api/compositors/composite.md",
"chars": 1249,
"preview": "---\ntitle: Composite\ndescription: Control a map of actions and output to that same structure.\ncategory: compositors\n---\n"
},
{
"path": "packages/popmotion/docs/api/compositors/crossfade.md",
"chars": 1221,
"preview": "---\ntitle: Crossfade\ndescription: Fade between two numerical actions.\ncategory: compositors\n---\n\n# Crossfade\n\nFade betwe"
},
{
"path": "packages/popmotion/docs/api/compositors/delay.md",
"chars": 646,
"preview": "---\ntitle: Delay\ndescription: Fires complete after the defined interval.\ncategory: compositors\n---\n\n# Delay\n\nFires `comp"
},
{
"path": "packages/popmotion/docs/api/compositors/merge.md",
"chars": 948,
"preview": "---\ntitle: Merge\ndescription: Combine multiple actions into one output.\ncategory: compositors\n---\n\n# Merge\n\nCombine mult"
},
{
"path": "packages/popmotion/docs/api/compositors/parallel.md",
"chars": 1246,
"preview": "---\ntitle: Parallel\ndescription: Control multiple actions in parallel and output as an array.\ncategory: compositors\n---\n"
},
{
"path": "packages/popmotion/docs/api/compositors/schedule.md",
"chars": 1242,
"preview": "---\ntitle: Schedule\ndescription: Use an action to control the output of another.\ncategory: compositors\n---\n\n# Schedule\n\n"
},
{
"path": "packages/popmotion/docs/api/compositors/stagger.md",
"chars": 1325,
"preview": "---\ntitle: Stagger\ndescription: Stagger the execution of a series of actions.\ncategory: compositors\n---\n\n# Stagger\n\nStag"
},
{
"path": "packages/popmotion/docs/api/easing.md",
"chars": 2598,
"preview": "---\ntitle: Easing\ndescription: Functions that speed or slow a tween over time.\n---\n\n# Easing\n\nEasing functions make twee"
},
{
"path": "packages/popmotion/docs/api/faqs.md",
"chars": 443,
"preview": "---\ntitle: FAQs\ndescription: Popmotion frequently asked questions\n---\n\n# FAQs\n\n<TOC />\n\n## Browser support?\n\nPopmotion s"
},
{
"path": "packages/popmotion/docs/api/framesync.md",
"chars": 2606,
"preview": "---\ntitle: Framesync\ndescription: Schedule functions to run at specific steps on the render loop.\n---\n\n# Framesync\n\nA ti"
},
{
"path": "packages/popmotion/docs/api/input/listen.md",
"chars": 1778,
"preview": "---\ntitle: Listen\ndescription: Creates a DOM event listener as an action stream.\ncategory: input\n---\n\n# Listen\n\n`listen`"
},
{
"path": "packages/popmotion/docs/api/input/multitouch.md",
"chars": 2217,
"preview": "---\ntitle: Multitouch\ndescription: Tracks multitouch input.\ncategory: input\n---\n\n# Multitouch\n\nTracks multitouch input a"
},
{
"path": "packages/popmotion/docs/api/input/pointer.md",
"chars": 1641,
"preview": "---\ntitle: Pointer\ndescription: Outputs the screen position of a single mouse or touch point.\ncategory: input\n---\n\n# Poi"
},
{
"path": "packages/popmotion/docs/api/reactions/multicast.md",
"chars": 2040,
"preview": "---\ntitle: Multicast\ndescription: A reaction that multiple reactions can subscribe to.\ncategory: reactions\n---\n\n# Multic"
},
{
"path": "packages/popmotion/docs/api/reactions/value.md",
"chars": 1901,
"preview": "---\ntitle: Value\ndescription: Track value state and query velocity\ncategory: reactions\n---\n\n# Value\n\nA [multicast reacti"
},
{
"path": "packages/popmotion/docs/api/transformers.md",
"chars": 138,
"preview": "---\ntitle: Transformers\ndescription: Simple composable functions that take a value and return a new one.\n---\n\nMoved to ["
},
{
"path": "packages/popmotion/docs/blog/20170703-choosing-a-default-easing-for-popmotion.md",
"chars": 8741,
"preview": "---\ntitle: Choosing the correct default easing for Popmotion\ndescription: \"Why I settled on easeOut for Popmotion's defa"
},
{
"path": "packages/popmotion/docs/blog/20170704-manually-set-scroll-while-ios-momentum-scroll-bounces.md",
"chars": 2316,
"preview": "---\ntitle: How to manually set scrollTop during an iOS momentum bounce\ndescription: Why does existence hurt so much\npubl"
},
{
"path": "packages/popmotion/docs/blog/20170710-mobile-web-is-awful-and-were-all-to-blame.md",
"chars": 13212,
"preview": "---\ntitle: The mobile web is awful, and everyone's to blame\ndescription: From browser vendors to front end developers, e"
},
{
"path": "packages/popmotion/docs/blog/20170803-coding-style-dont-be-a-dick.md",
"chars": 4814,
"preview": "---\ntitle: \"Adhering to a project's coding style: Don't be a dick\"\ndescription: \npublished: 20170803\nauthor: Matt Perry\n"
},
{
"path": "packages/popmotion/docs/blog/20171210-popmotion-8-upgrade-guide.md",
"chars": 6243,
"preview": "---\ntitle: Popmotion 8 upgrade guide\ndescription: How to upgrade Popmotion 7 to 8\npublished: 20171210\nauthor: Matt Perry"
},
{
"path": "packages/popmotion/docs/blog/20171211-introducing-popmotion-8.md",
"chars": 8805,
"preview": "---\ntitle: Introducing Popmotion 8\ndescription: Popmotion 8 is a functional, reactive approach to animation.\npublished: "
},
{
"path": "packages/popmotion/docs/blog/20180104-when-ios-throttles-requestanimationframe.md",
"chars": 5204,
"preview": "---\ntitle: When iOS throttles requestAnimationFrame to 30fps\ndescription: In specific situations, iOS throttles rAF to 3"
},
{
"path": "packages/popmotion/docs/blog/20180521-pose-2-migration-guide.md",
"chars": 5280,
"preview": "---\ntitle: \"What's new in Pose 2.0\"\ndescription: A quick overview of what's new in Pose and React Pose 2.0, and how to m"
},
{
"path": "packages/popmotion/docs/blog/20180820-introducing-pose-3.md",
"chars": 3631,
"preview": "---\ntitle: Introducing Pose 3.0\ndescription: A look at the latest Pose features, changes, and a hint of what's next\npubl"
},
{
"path": "packages/popmotion/docs/blog/20180829-pose-3-1-animate-between-anything.md",
"chars": 1768,
"preview": "---\ntitle: \"Pose 3.1: Animate between any unit type\"\ndescription: A look at the latest Pose features, changes, and a hin"
},
{
"path": "packages/popmotion/docs/blog/20180904-introducing-pose-for-vue.md",
"chars": 4509,
"preview": "---\ntitle: Introducing Pose for Vue\ndescription: An introduction to the declarative animation library for Vue\npublished:"
},
{
"path": "packages/popmotion/docs/blog/20181101-react-pose-4-forwardref.md",
"chars": 3067,
"preview": "---\ntitle: \"Pose for React 4.0: Custom components made simple(r)\"\ndescription: Pose previously used special properties t"
},
{
"path": "packages/popmotion/docs/blog/20190123-introducing-inertia-animation-for-popmotion-pure.md",
"chars": 519,
"preview": "---\ntitle: Introducing Inertia for Popmotion Pure\ndescription: The new inertia animation allows the creation of physics-"
},
{
"path": "packages/popmotion/docs/blog/20190704-upgrade-to-pure-9.md",
"chars": 605,
"preview": "---\ntitle: \"Popmotion Pure 9: How to upgrade\"\ndescription: Popmotion Pure 9 introduces some breaking changes - here's ho"
},
{
"path": "packages/popmotion/docs/blog/20200115-pose-is-deprecated.md",
"chars": 3971,
"preview": "---\ntitle: Pose is deprecated\ndescription: All versions of Pose are now deprecated.\npublished: 20200115\nauthor: Matt Per"
},
{
"path": "packages/popmotion/docs/blog/draft-60fps-hi-res-image-scaling-with-translatez-and-maths.md",
"chars": 2868,
"preview": "---\ntitle: Achieve 4K 60fps image scaling animations with translateZ and maths\ndescription: At high resolutions, image s"
},
{
"path": "packages/popmotion/docs/blog/draft-css-vs-js-animation.md",
"chars": 19,
"preview": "---\ndraft: true\n---"
},
{
"path": "packages/popmotion/docs/blog/draft-the-emerging-reality.md",
"chars": 67,
"preview": "---\ntitle: UX in the Emerging Reality\ndescription: \ndraft: true\n---"
},
{
"path": "packages/popmotion/docs/learn/advanced/value-pipelines.md",
"chars": 4215,
"preview": "---\ntitle: Composable value pipelines\ndescription: Use `pipe` to compose reusable value pipelines\ncategory: advanced\n---"
},
{
"path": "packages/popmotion/docs/learn/basics/action-reaction.md",
"chars": 5826,
"preview": "---\ntitle: Actions and reactions\ndescription: A quick look at Popmotion's simplified reactive model.\ncategory: basics\nne"
},
{
"path": "packages/popmotion/docs/learn/basics/get-started.md",
"chars": 4601,
"preview": "---\ntitle: Get started\ndescription: Introduction to Popmotion's tween animation.\ncategory: basics\nnext: action-reaction\n"
},
{
"path": "packages/popmotion/docs/learn/basics/input-tracking.md",
"chars": 5890,
"preview": "---\ntitle: Pointer tracking\ndescription: Learn to track pointer movement and use that to drag DOM elements.\ncategory: ba"
},
{
"path": "packages/popmotion/docs/learn/basics/install.md",
"chars": 1319,
"preview": "---\ntitle: Install Popmotion\ndescription: Overview of Popmotion's different installation options.\ncategory: basics\nnext:"
},
{
"path": "packages/popmotion/docs/learn/basics/velocity-and-physics.md",
"chars": 8278,
"preview": "---\ntitle: Physics and velocity\ndescription: Create responsive interactions with velocity, decay, physics and spring.\nca"
},
{
"path": "packages/popmotion/docs/learn/how-to/circular-motion.md",
"chars": 3984,
"preview": "---\ntitle: Circular motion\ndescription: How to animate angle and radius to output x and y coordinates.\ncategory: how-to\n"
},
{
"path": "packages/popmotion/docs/learn/how-to/constrain-motion.md",
"chars": 6214,
"preview": "---\ntitle: Constrain motion\ndescription: How to constrain motion to within ranges using clamping and springs.\ncategory: "
},
{
"path": "packages/popmotion/docs/learn/how-to/input-smoothing.md",
"chars": 3038,
"preview": "---\ntitle: Input smoothing\ndescription: How to apply input smoothing to mouse and touch input\ncategory: how-to\n---\n\n# In"
},
{
"path": "packages/popmotion/docs/learn/how-to/morph-svg.md",
"chars": 4597,
"preview": "---\ntitle: Morph SVG\ndescription: How to animate between two SVG shapes with Popmotion.\ncategory: how-to\n---\n\n# Morph SV"
},
{
"path": "packages/popmotion/docs/learn/how-to/rounded-values.md",
"chars": 1696,
"preview": "---\ntitle: Rounded values\ndescription: How to output rounded values from any action\ncategory: how-to\n---\n\n# Rounded valu"
},
{
"path": "packages/popmotion/docs/learn/projects/spring-loaded-characters-remaining.md",
"chars": 8046,
"preview": "---\ntitle: \"Spring-loaded 'characters remaining' counter\"\ndescription: Inject some fun into your text fields with a spri"
},
{
"path": "packages/popmotion/package.json",
"chars": 2851,
"preview": "{\n \"name\": \"popmotion\",\n \"version\": \"11.0.5\",\n \"description\": \"The animator's toolbox\",\n \"author\": \"Matt Per"
},
{
"path": "packages/popmotion/rollup.config.js",
"chars": 811,
"preview": "import typescript from 'rollup-plugin-typescript2';\nimport generateConfig from '../../rollup-generate-config';\nimport re"
},
{
"path": "packages/popmotion/src/animations/__tests__/animate.test.ts",
"chars": 26621,
"preview": "import { animate } from \"..\"\nimport { linear, easeOut } from \"../..\"\nimport { AnimationOptions } from \"../types\"\nimport "
},
{
"path": "packages/popmotion/src/animations/__tests__/inertia.test.ts",
"chars": 5750,
"preview": "import { syncDriver } from \"./utils\"\nimport { inertia } from \"../inertia\"\nimport { InertiaOptions } from \"../types\"\n\nasy"
},
{
"path": "packages/popmotion/src/animations/__tests__/utils.ts",
"chars": 327,
"preview": "export const syncDriver = (interval = 10) => (update: (v: number) => void) => {\n let isRunning = true\n return {\n "
},
{
"path": "packages/popmotion/src/animations/generators/__tests__/decay.test.ts",
"chars": 1478,
"preview": "import { decay } from \"../decay\"\nimport { animateSync } from \"./utils\"\n\ndescribe(\"decay\", () => {\n test(\"Runs animati"
},
{
"path": "packages/popmotion/src/animations/generators/__tests__/keyframes.test.ts",
"chars": 2422,
"preview": "import {\n keyframes,\n defaultEasing,\n defaultOffset,\n convertOffsetToTimes,\n} from \"../keyframes\"\nimport { l"
},
{
"path": "packages/popmotion/src/animations/generators/__tests__/spring.test.ts",
"chars": 4127,
"preview": "import { spring } from \"../spring\"\nimport { animateSync } from \"./utils\"\n\ndescribe(\"spring\", () => {\n test(\"Runs anim"
},
{
"path": "packages/popmotion/src/animations/generators/__tests__/utils.ts",
"chars": 419,
"preview": "import { Animation } from \"../../types\"\n\nexport function animateSync(\n animation: Animation<number>,\n timeStep = 2"
},
{
"path": "packages/popmotion/src/animations/generators/decay.ts",
"chars": 1142,
"preview": "import { Animation, AnimationState, DecayOptions } from \"../types\"\n\nexport function decay({\n velocity = 0,\n from ="
},
{
"path": "packages/popmotion/src/animations/generators/keyframes.ts",
"chars": 2114,
"preview": "import { Animation, AnimationState, KeyframeOptions } from \"../types\"\nimport { interpolate } from \"../../utils/interpola"
},
{
"path": "packages/popmotion/src/animations/generators/spring.ts",
"chars": 6707,
"preview": "import {\n SpringOptions,\n PhysicsSpringOptions,\n Animation,\n AnimationState,\n} from \"../types\"\nimport { calc"
},
{
"path": "packages/popmotion/src/animations/index.ts",
"chars": 3339,
"preview": "import {\n AnimationOptions,\n Driver,\n DriverControls,\n KeyframeOptions,\n} from \"./types\"\nimport { detectAnim"
},
{
"path": "packages/popmotion/src/animations/inertia.ts",
"chars": 3026,
"preview": "import {\n InertiaOptions,\n PlaybackControls,\n AnimationOptions,\n SpringOptions,\n} from \"./types\"\nimport { an"
},
{
"path": "packages/popmotion/src/animations/types.ts",
"chars": 2680,
"preview": "import { Easing } from \"../easing/types\"\n\nexport interface Animation<V> {\n next: (\n t: number\n ) => {\n "
},
{
"path": "packages/popmotion/src/animations/utils/__tests__/detect-animation-from-config.test.ts",
"chars": 1218,
"preview": "import { detectAnimationFromOptions } from \"../detect-animation-from-options\"\nimport { decay } from \"../../generators/de"
},
{
"path": "packages/popmotion/src/animations/utils/__tests__/elapsed.test.ts",
"chars": 1438,
"preview": "import { loopElapsed, reverseElapsed, hasRepeatDelayElapsed } from \"../elapsed\"\n\ndescribe(\"loopElapsed\", () => {\n tes"
},
{
"path": "packages/popmotion/src/animations/utils/__tests__/find-spring.test.ts",
"chars": 1291,
"preview": "import { findSpring, minDamping, minDuration } from \"../find-spring\"\n\ntest(\"findSpring\", () => {\n // let time = perfo"
},
{
"path": "packages/popmotion/src/animations/utils/detect-animation-from-options.ts",
"chars": 1434,
"preview": "import { spring } from \"../generators/spring\"\nimport { keyframes } from \"../generators/keyframes\"\nimport { decay } from "
},
{
"path": "packages/popmotion/src/animations/utils/elapsed.ts",
"chars": 599,
"preview": "export function loopElapsed(elapsed: number, duration: number, delay = 0) {\n return elapsed - duration - delay\n}\n\nexp"
},
{
"path": "packages/popmotion/src/animations/utils/find-spring.ts",
"chars": 3402,
"preview": "import { warning } from \"hey-listen\"\nimport { clamp } from \"../../utils/clamp\"\nimport { SpringOptions } from \"../types\"\n"
},
{
"path": "packages/popmotion/src/easing/__tests__/cubic-bezier.test.ts",
"chars": 645,
"preview": "import { cubicBezier } from \"../cubic-bezier\"\n\ndescribe(\"cubicBezier\", () => {\n test(\"correctly generates easing func"
},
{
"path": "packages/popmotion/src/easing/__tests__/index.test.ts",
"chars": 831,
"preview": "import { circIn, bounceOut, bounceInOut } from \"../\"\n\ndescribe(\"circIn\", () => {\n test(\"correctly eases\", () => {\n "
},
{
"path": "packages/popmotion/src/easing/__tests__/steps.test.ts",
"chars": 778,
"preview": "import { steps } from \"../steps\"\n\ntest(\"steps\", () => {\n const stepEnd = steps(4)\n\n expect(stepEnd(0)).toBe(0)\n "
},
{
"path": "packages/popmotion/src/easing/__tests__/utils.test.ts",
"chars": 1446,
"preview": "import {\n reverseEasing,\n mirrorEasing,\n createExpoIn,\n createBackIn,\n createAnticipate,\n} from \"../utils"
},
{
"path": "packages/popmotion/src/easing/cubic-bezier.ts",
"chars": 3715,
"preview": "/*\n Bezier function generator\n\n Gaëtan Renaudeau's BezierEasing\n https://github.com/gre/bezier-easing/blob/master/src"
},
{
"path": "packages/popmotion/src/easing/index.ts",
"chars": 1528,
"preview": "import {\n createExpoIn,\n reverseEasing,\n mirrorEasing,\n createBackIn,\n createAnticipate,\n} from \"./utils\""
},
{
"path": "packages/popmotion/src/easing/steps.ts",
"chars": 631,
"preview": "import { clamp } from '../utils/clamp';\nimport { Easing } from './types';\n/*\n Create stepped version of 0-1 progress\n\n "
},
{
"path": "packages/popmotion/src/easing/types.ts",
"chars": 101,
"preview": "export type Easing = (v: number) => number;\nexport type EasingModifier = (easing: Easing) => Easing;\n"
},
{
"path": "packages/popmotion/src/easing/utils.ts",
"chars": 1267,
"preview": "import { Easing, EasingModifier } from \"./types\"\n\n// Accepts an easing function and returns a new one that outputs rever"
},
{
"path": "packages/popmotion/src/index.ts",
"chars": 2046,
"preview": "export { animate } from \"./animations\"\nexport { inertia } from \"./animations/inertia\"\n\n// Animators\nexport { decay } fro"
},
{
"path": "packages/popmotion/src/types.ts",
"chars": 144,
"preview": "export type Point2D = {\n x: number;\n y: number;\n};\n\nexport type Point3D = Point2D & {\n z: number;\n};\n\nexport type Poi"
},
{
"path": "packages/popmotion/src/utils/__tests__/angle.test.ts",
"chars": 358,
"preview": "import { angle } from \"../angle\"\n\nconst a = { x: 0, y: 0 }\nconst b = { x: 1, y: 0 }\nconst c = { x: 1, y: 1 }\nconst d = {"
},
{
"path": "packages/popmotion/src/utils/__tests__/apply-offset.test.ts",
"chars": 313,
"preview": "import { applyOffset } from \"../apply-offset\"\n\ntest(\"applyOffset\", () => {\n const withInitialOffset = applyOffset(10,"
},
{
"path": "packages/popmotion/src/utils/__tests__/attract.test.ts",
"chars": 881,
"preview": "import { createAttractor, attract, attractExpo } from \"../attract\"\n\ndescribe(\"createAttractor\", () => {\n test(\"Will c"
},
{
"path": "packages/popmotion/src/utils/__tests__/clamp.test.ts",
"chars": 187,
"preview": "import { clamp } from \"../clamp\"\n\ntest(\"clamp\", () => {\n expect(clamp(100, 200, 99)).toBe(100)\n expect(clamp(100, "
},
{
"path": "packages/popmotion/src/utils/__tests__/degrees-to-radians.test.ts",
"chars": 152,
"preview": "import { degreesToRadians } from \"../degrees-to-radians\"\n\ntest(\"degreesToRadians\", () => {\n expect(degreesToRadians(4"
},
{
"path": "packages/popmotion/src/utils/__tests__/distance.test.ts",
"chars": 597,
"preview": "import { distance } from \"../distance\"\n\ntest(\"distance\", () => {\n expect(distance(-100, 100)).toBe(200)\n expect(di"
},
{
"path": "packages/popmotion/src/utils/__tests__/hsla-to-rgba.test.ts",
"chars": 376,
"preview": "import { hslaToRgba } from \"../hsla-to-rgba\"\n\ndescribe(\"hslaToRgba\", () => {\n test(\"Correctly converts hsla to rgba\","
},
{
"path": "packages/popmotion/src/utils/__tests__/interpolate.test.ts",
"chars": 2943,
"preview": "import { interpolate } from \"../interpolate\"\n\nconst invert = (v: number) => -v\n\ntest(\"interpolate numbers\", () => {\n "
},
{
"path": "packages/popmotion/src/utils/__tests__/is-point-3d.test.ts",
"chars": 273,
"preview": "import { isPoint3D } from \"../is-point-3d\"\n\ntest(\"isPoint3D\", () => {\n expect(isPoint3D(9 as any)).toBe(false)\n ex"
},
{
"path": "packages/popmotion/src/utils/__tests__/is-point.test.ts",
"chars": 243,
"preview": "import { isPoint } from \"../is-point\"\n\ntest(\"isPoint\", () => {\n expect(isPoint(9)).toBe(false)\n expect(isPoint({ x"
},
{
"path": "packages/popmotion/src/utils/__tests__/mix-array.test.ts",
"chars": 415,
"preview": "import { mixArray } from \"../mix-complex\"\n\ntest(\"mixArray\", () => {\n const a = [0, \"100px 0px\", \"#fff\"]\n const b ="
},
{
"path": "packages/popmotion/src/utils/__tests__/mix-color.test.ts",
"chars": 3210,
"preview": "import { mixColor, mixLinearColor } from \"../mix-color\"\n\ntest(\"mixColor hex\", () => {\n expect(mixColor(\"#fff\", \"#000\""
},
{
"path": "packages/popmotion/src/utils/__tests__/mix-complex.test.ts",
"chars": 1184,
"preview": "import { mixComplex } from \"../mix-complex\"\n\ntest(\"mixComplex\", () => {\n expect(mixComplex(\"20px\", \"10px\")(0.5)).toBe"
},
{
"path": "packages/popmotion/src/utils/__tests__/mix-object.test.ts",
"chars": 573,
"preview": "import { mixObject } from \"../mix-complex\"\n\ntest(\"mixObject\", () => {\n expect(\n mixObject(\n {\n "
},
{
"path": "packages/popmotion/src/utils/__tests__/mix.test.ts",
"chars": 325,
"preview": "import { mix } from \"../mix\"\n\ntest(\"mix\", () => {\n expect(mix(0, 1, 0.5)).toBe(0.5)\n expect(mix(-100, 100, 2)).toB"
},
{
"path": "packages/popmotion/src/utils/__tests__/point-from-vector.test.ts",
"chars": 221,
"preview": "import { pointFromVector } from \"../point-from-vector\"\n\ntest(\"pointFromVector\", () => {\n expect(pointFromVector({ x: "
},
{
"path": "packages/popmotion/src/utils/__tests__/progress.test.ts",
"chars": 204,
"preview": "import { progress } from \"../progress\"\n\ntest(\"progress\", () => {\n expect(progress(0, 100, 50)).toBe(0.5)\n expect(p"
},
{
"path": "packages/popmotion/src/utils/__tests__/radians-to-degrees.test.ts",
"chars": 152,
"preview": "import { radiansToDegrees } from \"../radians-to-degrees\"\n\ntest(\"radiansToDegrees\", () => {\n expect(radiansToDegrees(0"
},
{
"path": "packages/popmotion/src/utils/__tests__/smooth-frame.test.ts",
"chars": 182,
"preview": "import { smoothFrame } from \"../smooth-frame\"\n\ntest(\"smoothFrame\", () => {\n expect(smoothFrame(0, 100, 16.7, 0)).toBe"
},
{
"path": "packages/popmotion/src/utils/__tests__/smooth.test.ts",
"chars": 381,
"preview": "import { smooth } from \"../smooth\"\nimport sync from \"framesync\"\n\ntest(\"smooth\", () => {\n const smoother = smooth()\n\n "
},
{
"path": "packages/popmotion/src/utils/__tests__/snap.test.ts",
"chars": 745,
"preview": "import { snap } from \"../snap\"\n\nit(\"should snap a number to the nearest in the provided array\", () => {\n const snapTo"
},
{
"path": "packages/popmotion/src/utils/__tests__/to-decimal.test.ts",
"chars": 197,
"preview": "import { toDecimal } from \"../to-decimal\"\n\ntest(\"toDecimal\", () => {\n expect(toDecimal(3.33333)).toBe(3.33)\n expec"
},
{
"path": "packages/popmotion/src/utils/__tests__/velocity-per-frame.test.ts",
"chars": 145,
"preview": "import { velocityPerFrame } from \"../velocity-per-frame\"\n\ntest(\"velocityPerFrame\", () => {\n expect(velocityPerFrame(5"
},
{
"path": "packages/popmotion/src/utils/__tests__/velocity-per-second.test.ts",
"chars": 197,
"preview": "import { velocityPerSecond } from \"../velocity-per-second\"\n\ntest(\"velocityPerSecond\", () => {\n expect(velocityPerSeco"
},
{
"path": "packages/popmotion/src/utils/__tests__/wrap.test.ts",
"chars": 225,
"preview": "import { wrap } from \"../wrap\"\n\ntest(\"wrap\", () => {\n expect(wrap(-100, 100, -100)).toBe(-100)\n expect(wrap(-100, "
},
{
"path": "packages/popmotion/src/utils/angle.ts",
"chars": 432,
"preview": "import { Point } from '../types';\nimport { radiansToDegrees } from './radians-to-degrees';\nimport { zeroPoint } from './"
},
{
"path": "packages/popmotion/src/utils/apply-offset.ts",
"chars": 521,
"preview": "/**\n * Apply offset\n * A function that, given a value, will get the offset from `from`\n * and apply it to `to`\n * @param"
},
{
"path": "packages/popmotion/src/utils/attract.ts",
"chars": 680,
"preview": "const identity = (v: any): any => v\n\n/**\n * Creates an attractor that, given a strength constant, origin and value,\n * w"
},
{
"path": "packages/popmotion/src/utils/clamp.ts",
"chars": 97,
"preview": "export const clamp = (min: number, max: number, v: number) =>\n Math.min(Math.max(v, min), max);\n"
},
{
"path": "packages/popmotion/src/utils/degrees-to-radians.ts",
"chars": 189,
"preview": "/*\n Convert degrees to radians\n\n @param [number]: Value in degrees\n @return [number]: Value in radians\n*/\nexport cons"
},
{
"path": "packages/popmotion/src/utils/distance.ts",
"chars": 936,
"preview": "import { Point } from \"../types\"\nimport { isPoint } from \"./is-point\"\nimport { isPoint3D } from \"./is-point-3d\"\nimport {"
},
{
"path": "packages/popmotion/src/utils/hsla-to-rgba.ts",
"chars": 1088,
"preview": "import { HSLA, RGBA } from \"style-value-types\"\n\n// Adapted from https://gist.github.com/mjackson/5311256\nfunction hueToR"
},
{
"path": "packages/popmotion/src/utils/inc.ts",
"chars": 165,
"preview": "import { Point } from '../types';\n\nexport const zeroPoint: Point = {\n x: 0,\n y: 0,\n z: 0\n};\n\nexport const isNum = (v:"
},
{
"path": "packages/popmotion/src/utils/interpolate.ts",
"chars": 3885,
"preview": "import { Easing } from '../easing/types';\nimport { progress } from './progress';\nimport { mix } from './mix';\nimport { m"
},
{
"path": "packages/popmotion/src/utils/is-point-3d.ts",
"chars": 190,
"preview": "import { isPoint } from './is-point';\nimport { Point, Point3D } from '../types';\n\nexport const isPoint3D = (point: Point"
},
{
"path": "packages/popmotion/src/utils/is-point.ts",
"chars": 151,
"preview": "import { Point } from '../types';\n\nexport const isPoint = (point: Object): point is Point =>\n point.hasOwnProperty('x')"
},
{
"path": "packages/popmotion/src/utils/mix-color.ts",
"chars": 1699,
"preview": "import { mix } from \"./mix\"\nimport { hsla, rgba, hex, Color } from \"style-value-types\"\nimport { invariant } from \"hey-li"
},
{
"path": "packages/popmotion/src/utils/mix-complex.ts",
"chars": 3277,
"preview": "import { color, complex, RGBA, HSLA } from \"style-value-types\"\nimport { mix } from \"./mix\"\nimport { mixColor } from \"./m"
},
{
"path": "packages/popmotion/src/utils/mix.ts",
"chars": 663,
"preview": "/*\n Value in range from progress\n\n Given a lower limit and an upper limit, we return the value within\n that range as "
},
{
"path": "packages/popmotion/src/utils/pipe.ts",
"chars": 320,
"preview": "/**\n * Pipe\n * Compose other transformers to run linearily\n * pipe(min(20), max(40))\n * @param {...functions} transform"
},
{
"path": "packages/popmotion/src/utils/point-from-vector.ts",
"chars": 529,
"preview": "import { Point2D } from '../types';\nimport { degreesToRadians } from './degrees-to-radians';\n\n/*\n Point from angle and "
},
{
"path": "packages/popmotion/src/utils/progress.ts",
"chars": 583,
"preview": "/*\n Progress within given range\n\n Given a lower limit and an upper limit, we return the progress\n (expressed as a num"
},
{
"path": "packages/popmotion/src/utils/radians-to-degrees.ts",
"chars": 189,
"preview": "/*\n Convert radians to degrees\n\n @param [number]: Value in radians\n @return [number]: Value in degrees\n*/\nexport cons"
},
{
"path": "packages/popmotion/src/utils/smooth-frame.ts",
"chars": 457,
"preview": "import { toDecimal } from './to-decimal';\n\n/*\n Framerate-independent smoothing\n\n @param [number]: New value\n @param ["
},
{
"path": "packages/popmotion/src/utils/smooth.ts",
"chars": 581,
"preview": "import { smoothFrame } from './smooth-frame';\nimport { getFrameData } from 'framesync';\n\nexport const smooth = (strength"
},
{
"path": "packages/popmotion/src/utils/snap.ts",
"chars": 617,
"preview": "export const snap = (points: number | number[]) => {\n if (typeof points === 'number') {\n return (v: number) => Math."
},
{
"path": "packages/popmotion/src/utils/to-decimal.ts",
"chars": 151,
"preview": "export const toDecimal = (num: number, precision: number = 2) => {\n precision = 10 ** precision;\n return Math.round(nu"
},
{
"path": "packages/popmotion/src/utils/velocity-per-frame.ts",
"chars": 253,
"preview": "/*\n Convert x per second to per frame velocity based on fps\n\n @param [number]: Unit per second\n @param [number]: Fram"
},
{
"path": "packages/popmotion/src/utils/velocity-per-second.ts",
"chars": 269,
"preview": "/*\n Convert velocity into velocity per second\n\n @param [number]: Unit per frame\n @param [number]: Frame duration in m"
},
{
"path": "packages/popmotion/src/utils/wrap.ts",
"chars": 165,
"preview": "export const wrap = (min: number, max: number, v: number) => {\n const rangeSize = max - min;\n return ((((v - min) % ra"
},
{
"path": "packages/popmotion/src/worklet/animate.ts.wip",
"chars": 1767,
"preview": "import { registerCustomProperties, namespace } from './custom-properties';\nimport { whenWorkletReady } from './load-work"
},
{
"path": "packages/popmotion/src/worklet/custom-properties.ts",
"chars": 1094,
"preview": "interface CustomProperty {\n name: string;\n syntax: string;\n initial: string | number;\n}\n\nconst transforms: CustomProp"
},
{
"path": "packages/popmotion/src/worklet/index.ts.wip",
"chars": 1806,
"preview": "//import { tween } from '../animations/tween';\nimport { ForT } from '../types';\nimport { spring } from '../animations/sp"
},
{
"path": "packages/popmotion/src/worklet/load-worklet.ts",
"chars": 410,
"preview": "type Resolve = () => void\n\nlet isReady = false\n\nconst awaitingReady: Resolve[] = []\n\nexport async function whenWorkletRe"
},
{
"path": "packages/popmotion/tsconfig.json",
"chars": 135,
"preview": "{\n \"extends\": \"../../tsconfig.json\",\n \"compilerOptions\": {\n \"rootDir\": \"src\",\n \"outDir\": \"lib\"\n },\n \"include\":"
},
{
"path": "packages/popmotion/tslint.json",
"chars": 57,
"preview": "{\n \"extends\": [\n \"tslint-circular-dependencies\"\n ]\n}"
}
]
// ... and 336 more files (download for full content)
About this extraction
This page contains the full source code of the Popmotion/popmotion GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 536 files (1.1 MB), approximately 330.2k tokens, and a symbol index with 242 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.