Skip to content

Instantly share code, notes, and snippets.

@vmarcosp
Created August 9, 2021 23:03
Show Gist options
  • Save vmarcosp/1969e6377f43ded8982a51d77b487a3e to your computer and use it in GitHub Desktop.
Save vmarcosp/1969e6377f43ded8982a51d77b487a3e to your computer and use it in GitHub Desktop.
Simple bindings for framer-motion
module Elements = {
type motionElement
type t = [#div | #section]
@module("React")
external createElement: (motionElement, 'props, React.element) => React.element = "createElement"
@module("framer-motion") @scope("motion")
external div: motionElement = "div"
@module("framer-motion") @scope("motion")
external section: motionElement = "section"
let make = (element: t, props, children) =>
createElement(
switch element {
| #div => div
| #section => section
},
props,
children,
)
}
module Animate = {
type identity
type initial = [#hidden | #visible]
type controlStatus = [#visible | #hidden]
type controls = {start: (. controlStatus) => unit}
type variants<'a> = {..} as 'a
type t = [#controlled(controls) | #visible | #hidden]
let identity = v =>
switch v {
| #controlled(value) => Obj.magic(value)
| value => Obj.magic(value)
}
let fromOption = Belt.Option.map(_, identity)
}
module Element = {
@deriving(abstract)
type motionProps<'a> = {
@optional initial: Animate.initial,
@optional variants: Animate.variants<'a>,
@optional animate: Animate.identity,
}
external toObject: 'a => {..} = "%identity"
@react.component
let make = (
/**
* Framer Motion Props
*/
~initial=?,
~variants=?,
~animate: option<Animate.t>=?,
~element: Elements.t=#div,
/**
* DOM props
*/
~onClick=?,
~children,
) => {
Elements.make(
element,
Js.Obj.assign(
motionProps(~initial?, ~animate=?animate->Animate.fromOption, ~variants?, ())->toObject,
ReactDOM.domProps(~onClick?, ())->toObject,
),
children,
)
}
}
module Hooks = {
@module("framer-motion")
external useAnimation: unit => Animate.controls = "useAnimation"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment