framer-motion-theatre
Advanced tools
Comparing version 0.2.6 to 0.3.0
import * as react_jsx_runtime from 'react/jsx-runtime'; | ||
import React, { ReactNode } from 'react'; | ||
import * as _theatre_core from '@theatre/core'; | ||
import { IProject, UnknownShorthandCompoundProps, ISheetObject } from '@theatre/core'; | ||
import * as _theatre_studio from '@theatre/studio'; | ||
import { ReactNode } from 'react'; | ||
import { IProject } from '@theatre/core'; | ||
import { IStudio } from '@theatre/studio'; | ||
import { MotionValue } from 'framer-motion'; | ||
import { G as GizmoTheme } from './withTheatre-OGrWFIHQ.js'; | ||
export { u as useControls, a as useSheetObject, b as useTheatre, w as withTheatre } from './withTheatre-OGrWFIHQ.js'; | ||
import 'framer-motion'; | ||
type GizmoTheme = { | ||
normalColor: string; | ||
selectedColor: string; | ||
width: number; | ||
fillOpacity: number; | ||
}; | ||
type GizmoOptions = Partial<{ | ||
zIndex: number; | ||
ignoreComputedZIndex: boolean; | ||
translate: { | ||
x?: MotionValue<number>; | ||
y?: MotionValue<number>; | ||
strength?: number; | ||
}; | ||
}>; | ||
declare const TheatreProvider: ({ project, studio: userStudio, children, theme, }: { | ||
@@ -32,25 +16,2 @@ project: IProject; | ||
declare function useControls(): _theatre_core.ISequence; | ||
type MotionValueObject<Props extends UnknownShorthandCompoundProps> = { | ||
[K in keyof ISheetObject<Props>["value"]]: MotionValue<ISheetObject<Props>["value"][K]>; | ||
}; | ||
type MotionValueObjectWithStudio<Props extends UnknownShorthandCompoundProps> = MotionValueObject<Props> & { | ||
$studio: { | ||
isSelected: boolean; | ||
select: () => void; | ||
createGizmo: (options?: GizmoOptions) => (element: HTMLElement | null) => void; | ||
}; | ||
}; | ||
declare function useSheetObject<Props extends UnknownShorthandCompoundProps = UnknownShorthandCompoundProps>(objectId: string, initial: Props): MotionValueObjectWithStudio<Props>; | ||
declare function useTheatre(): { | ||
project: _theatre_core.IProject; | ||
studio: _theatre_studio.IStudio | undefined; | ||
}; | ||
declare function withTheatre<P>(componentId: string, Component: React.FC<P>): (props: P & { | ||
animationId: string; | ||
}) => react_jsx_runtime.JSX.Element; | ||
export { TheatreProvider, useControls, useSheetObject, useTheatre, withTheatre }; | ||
export { TheatreProvider }; |
@@ -1,2 +0,2 @@ | ||
import{useCallback as L,useContext as D,useEffect as C,useMemo as W,useRef as k,useState as O}from"react";import{cancelFrame as N,frame as _,useAnimationFrame as F,useMotionValue as j}from"framer-motion";import{createContext as A}from"react";var p=A(null);import{createRafDriver as H}from"@theatre/core";var v=H({name:"framer-motion-theatre"});import{motion as $}from"framer-motion";import{jsx as M,jsxs as J}from"react/jsx-runtime";function q(n){let r="";for(let s of Object.values(n.address))r+=s;return r}var B=({project:n,studio:r,children:s,theme:m})=>{let d={normalColor:"rgb(60, 140, 219)",selectedColor:"rgb(31, 121, 210)",fillOpacity:.2,width:3};C(()=>{let e=({timestamp:t})=>{v.tick(t)};return _.update(e,!0),()=>N(e)},[]);let i=W(()=>{if(r!=="auto"&&r)return r;process.env.NODE_ENV},[r]),[f,l]=O([]),[c,b]=O(!1),[u,h]=O(null),S=L(e=>(l(t=>[...t,e]),()=>{l(t=>t.filter(o=>o!==e))}),[]);return C(()=>{i?(h(i.selection.filter(e=>e.type==="Theatre_SheetObject_PublicAPI")[0]??null),i.onSelectionChange(e=>{let t=e.filter(o=>o.type==="Theatre_SheetObject_PublicAPI")[0];h(t??null)})):h(null)},[i]),C(()=>{if(!i)return;let e=o=>{o.altKey===!0&&b(!0)},t=o=>{o.altKey===!1&&b(!1)};return document.addEventListener("keydown",e),document.addEventListener("keyup",t),()=>{document.removeEventListener("keydown",e),document.removeEventListener("keyup",t)}},[i]),J(p.Provider,{value:{project:n,studio:i,gizmoTheme:m??d,registerGizmoTarget:S,selectedObject:u},children:[c&&M("div",{style:{position:"fixed",top:0,left:0,zIndex:999999999},children:f.map(e=>M(Z,{gizmoTarget:e},q(e.sheetObject)))}),s]})};function Z({gizmoTarget:n}){let{gizmoTheme:r,studio:s,selectedObject:m}=D(p),{target:d,options:i,axesMap:f,sheetObject:l}=n,[c,b]=O(!1),u=m===l,h=u?r.selectedColor:r.normalColor,S=j(i.zIndex??0),e=j(0),t=j(0),o=j(0),V=j(0);F(()=>{let g=d.getBoundingClientRect();i.ignoreComputedZIndex||S.set((i.zIndex??0)+Number(getComputedStyle(d).zIndex)),e.set(g.x),t.set(g.y),o.set(g.width),V.set(g.height)});let a=k(null),z=k(l.value),y=k({userSelect:document.body.style.userSelect,cursor:document.body.style.cursor});return C(()=>()=>{a.current&&a.current.discard(),document.body.style.userSelect=y.current.userSelect,document.body.style.webkitUserSelect=y.current.userSelect,document.body.style.cursor=y.current.cursor},[]),M($.div,{style:{position:"absolute",top:0,left:0,borderWidth:r.width,borderStyle:u?"solid":"dashed",borderColor:h,backgroundColor:`rgb(from ${h} r g b / ${c&&!u?r.fillOpacity:0})`,boxSizing:"border-box",contain:"strict",userSelect:"none",WebkitUserSelect:"none",touchAction:"none",x:e,y:t,width:o,height:V,zIndex:S},onHoverStart:()=>b(!0),onHoverEnd:()=>b(!1),onTap:()=>{s&&!a.current&&(s.setSelection([n.sheetObject]),s.ui.restore())},onPanStart:()=>{s&&(s.setSelection([n.sheetObject]),a.current&&a.current.discard(),a.current=s.scrub(),z.current=l.value,y.current={userSelect:document.body.style.userSelect,cursor:document.body.style.cursor},document.body.style.userSelect="none",document.body.style.webkitUserSelect="none",document.body.style.cursor="move")},onPan:(g,w)=>{if(!a.current)return;let T=f.translate.x,I=f.translate.y;a.current.capture(({set:E})=>{T&&E(l.props[T],z.current[T]+w.offset.x*(i.translate?.strength??1)),I&&E(l.props[I],z.current[I]+w.offset.y*(i.translate?.strength??1))})},onPanEnd:()=>{a.current&&(a.current.commit(),a.current=null),document.body.style.userSelect=y.current.userSelect,document.body.style.webkitUserSelect=y.current.userSelect,document.body.style.cursor=y.current.cursor}})}import{useContext as X}from"react";import{createContext as Q}from"react";var x=Q(null);function Y(){let{sheet:n}=X(x);return n.sequence}import{useContext as R,useEffect as P,useMemo as ee,useState as G}from"react";import{onChange as te}from"@theatre/core";import{motionValue as U}from"framer-motion";function oe(n,r){let{sheet:s}=R(x),{studio:m,selectedObject:d,registerGizmoTarget:i}=R(p),[f,l]=G(null),[c,b]=G(()=>s.object(n,r,{reconfigure:!0})),[u,h]=G(()=>{let e={};for(let t in c.value)e[t]=U(c.value[t]);return e}),S=ee(()=>({...u,$studio:{isSelected:d===c,select:()=>{m&&m.setSelection([c])},createGizmo:(e={})=>t=>{t&&l({element:t,options:e})}}}),[u,c,d,m]);return P(()=>{if(f){let e=f.options;return i({sheetObject:c,target:f.element,options:e,axesMap:{translate:{x:Object.entries(u).find(o=>o[1]===e.translate?.x)?.[0]??null,y:Object.entries(u).find(o=>o[1]===e.translate?.y)?.[0]??null}}})}},[u,c,i,f]),P(()=>{h(e=>{let t={};for(let o in c.value)e[o]?t[o]=e[o]:t[o]=U(c.value[o]);for(let o in e)t[o]||e[o].destroy();return t})},[c]),P(()=>te(c.props,t=>{for(let o in t)u[o]&&u[o].set(t[o])},v),[c,u]),P(()=>{b(s.object(n,r,{reconfigure:!0}))},[r,n,s]),S}import{useContext as re}from"react";function ne(){let{project:n,studio:r}=re(p);return{project:n,studio:r}}import{useContext as se,useState as ie}from"react";import{jsx as K}from"react/jsx-runtime";function ce(n,r){return s=>{let{project:m}=se(p),[d]=ie(()=>m.sheet(n,s.animationId));return K(x.Provider,{value:{sheet:d},children:K(r,{...s})})}}export{B as TheatreProvider,Y as useControls,oe as useSheetObject,ne as useTheatre,ce as withTheatre}; | ||
import{a as o,b as h,c as a,d as p,e as c}from"./chunk-KVTSBWXF.js";import{useMemo as f}from"react";import{jsx as n}from"react/jsx-runtime";var d=({project:r,studio:e,children:t,theme:m})=>{let i=f(()=>{if(e!=="auto"&&e)return e},[e]);return n(o,{project:r,studio:i,theme:m,children:t})};export{d as TheatreProvider,h as useControls,a as useSheetObject,p as useTheatre,c as withTheatre}; | ||
//# sourceMappingURL=main.js.map |
@@ -18,3 +18,3 @@ { | ||
"homepage": "https://github.com/AndrewPrifer/framer-motion-theatre", | ||
"version": "0.2.6", | ||
"version": "0.3.0", | ||
"type": "module", | ||
@@ -29,2 +29,7 @@ "files": [ | ||
".": { | ||
"development": { | ||
"types": "./dist/main.d.ts", | ||
"import": "./dist/dev.js", | ||
"require": "./dist/dev.cjs" | ||
}, | ||
"types": "./dist/main.d.ts", | ||
@@ -31,0 +36,0 @@ "import": "./dist/main.js", |
115
README.md
@@ -5,9 +5,9 @@ # Framer Motion 🤝 Theatre | ||
Animate Framer Motion's motion values using Theatre.js, with all the complex stuff like sheets, objects, animation instancing and wiring taken care of. | ||
Plus you automatically get visual selection tools when in dev mode. | ||
Automatically get visual editing tools with 1 line of code. | ||
https://github.com/AndrewPrifer/framer-motion-theatre/assets/2991360/92b71b1d-0877-4c43-89db-f8761b9f689e | ||
https://github.com/AndrewPrifer/framer-motion-theatre/assets/2991360/08f9c8e9-c86b-417b-b205-16d9292b63d2 | ||
## Why? | ||
While Theatre.js' concepts can be a bit hard to wrap your head around, its terminology maps surprisingly well to React and Framer Motion concepts. | ||
While Theatre.js' concepts can be a bit hard to wrap your head around, its terminology maps very well to React and Framer Motion concepts. | ||
@@ -18,3 +18,3 @@ - Sheets -> React components | ||
By enforcing this interpretation, we can wrap Theatre.js' complexity in a simple declarative API that is very easy to read and write. | ||
By enforcing this interpretation, we can wrap Theatre.js' complexity in a simple declarative API that is very easy to read and write, and which allows us to build powerful tools on top. | ||
@@ -27,3 +27,6 @@ ## Features | ||
- Hold down the `Alt` key to display selectable objects in dev mode. | ||
- Get visual editing tools with 1 line of code. | ||
https://github.com/AndrewPrifer/framer-motion-theatre/assets/2991360/44c77be8-c6de-4545-bcf7-75fe49164715 | ||
## Installation | ||
@@ -46,9 +49,7 @@ | ||
// Optionally, pass in studio, or 'auto' if you want it set up automatically in development | ||
// Caveat: 'auto' relies on your bundler being smart enough to tree-shake, | ||
// check the console when running the production bundle. | ||
<TheatreProvider project={project} studio="auto"> | ||
<div className="container"> | ||
{/* Pass your components a unique animation ID besides the regular props. */} | ||
<Box animationId="Box 1" color="#E493B3" /> | ||
<Box animationId="Box 2" color="#EEA5A6" /> | ||
<Box instanceId="Box 1" color="#E493B3" /> | ||
<Box instanceId="Box 2" color="#EEA5A6" /> | ||
</div> | ||
@@ -66,7 +67,2 @@ </TheatreProvider> | ||
scale: types.number(1, { nudgeMultiplier: 0.01 }), | ||
borderRadius: types.number(0, { | ||
nudgeMultiplier: 0.1, | ||
range: [0, Infinity], | ||
}), | ||
skewX: 0, | ||
}); | ||
@@ -84,3 +80,3 @@ | ||
<motion.div | ||
// Besides the motion values, useSheetObject also returns a function to enable selection tools for this element. | ||
// Besides the motion values, useSheetObject also returns a function to enable editing tools for this element. | ||
ref={div.$studio.createGizmo()} | ||
@@ -92,10 +88,3 @@ onClick={() => { | ||
style={{ | ||
// Being an object of motion values, you can even directly destructure it onto the style prop. | ||
...div, | ||
backgroundColor: color, | ||
color: "white", | ||
fontWeight: "bold", | ||
display: "flex", | ||
justifyContent: "center", | ||
alignItems: "center", | ||
}} | ||
@@ -119,3 +108,3 @@ > | ||
### **`TheatreProvider`** | ||
### **`<TheatreProvider>`** | ||
@@ -132,5 +121,5 @@ Wrap your app in `TheatreProvider`, passing it your Theatre.js project. | ||
### **`withTheatre`** | ||
### **`withTheatre()`** | ||
Wrap your components in `withTheatre` to gain access to Framer Motion Theatre hooks and automatically set up sheets and objects for that component. | ||
Wrap your components in `withTheatre` to gain access to Framer Motion Theatre hooks and automatically set up sheets and objects for that component. The returned component has an extra mandatory prop `instanceId` that must be unique for each instance of the component. | ||
@@ -141,7 +130,10 @@ ```tsx | ||
}); | ||
<MyComponent instanceId="MyComponent 1" />; | ||
<MyComponent instanceId="MyComponent 2" />; | ||
``` | ||
### **`useSheetObject`** | ||
### **`useSheetObject()`** | ||
Animate motion values using Theatre.js. Returns an object of motion values you can plug into `motion.*` elements. Accepts an object of Theatre.js' [prop types](https://www.theatrejs.com/docs/latest/api/core#prop-types). Additionally, it returns an object with a `$studio` property that allows you to enable selection tools for this element. | ||
Animate motion values using Theatre.js. Returns an object of motion values you can plug into `motion.*` elements. Accepts an object of Theatre.js' [prop types](https://www.theatrejs.com/docs/latest/api/core#prop-types). Additionally, it returns an object with a `$studio` property that allows you to enable editing tools for this element. | ||
@@ -167,4 +159,71 @@ ```tsx | ||
### **`useControls`** | ||
### **`$studio`** | ||
The `$studio` object returned by `useSheetObject` allows you to enable editing end editing tools for this element. And has the following properties: | ||
#### **`$studio.createGizmo()`** | ||
Creates a gizmo for this element. Hold down the `Alt` key to display selectable objects. | ||
`createGizmo()` accepts an object of options: | ||
- **`translate.x`**: Accepts a `MotionValue` returned by `useSheetObject`. It will set the corresponding value when the gizmo is moved on the x axis. | ||
- **`translate.y`**: Accepts a `MotionValue` returned by `useSheetObject`. It will set the corresponding value when the gizmo is moved on the y axis. | ||
- **`translate.strength`**: A factor to multiply the translation by. Defaults to `1`. | ||
- **`zIndex`**: The z-index of the gizmo. Defaults to `0`. Gizmos are displayed on top of the page independently of your elements. The `zIndex` option lets you define the stacking order of gizmos. Higher values will be on top of lower values. | ||
- **`ignoreComputedZIndex`**: By default, the z-index assigned to gizmos will take into account the computed z-index of their corresponding element, which is what you want most of the time. In that case, the final z-index of the gizmo will be the value of the `zIndex` option + the computed z-index of the element. If you want to ignore the computed z-index and only use the `zIndex` option, set this to `true`. | ||
```tsx | ||
const div = useSheetObject("div", { | ||
width: 100, | ||
height: 100, | ||
}); | ||
return ( | ||
<motion.div | ||
ref={div.$studio.createGizmo({ | ||
translate: { | ||
x: div.width, | ||
y: div.height, | ||
}, | ||
})} | ||
style={{ | ||
...div, | ||
}} | ||
> | ||
{/* ... */} | ||
</motion.div> | ||
); | ||
``` | ||
#### **`$studio.isSelected`** | ||
A boolean that indicates whether the object is currently selected. | ||
```tsx | ||
const div = useSheetObject("div", { | ||
width: 100, | ||
height: 100, | ||
}); | ||
if (div.$studio.isSelected) { | ||
// ... | ||
} | ||
``` | ||
#### **`$studio.select()`** | ||
Allows you to select the object programmatically. | ||
```tsx | ||
const div = useSheetObject("div", { | ||
width: 100, | ||
height: 100, | ||
}); | ||
div.$studio.select(); | ||
``` | ||
### **`useControls()`** | ||
Returns the controls associated with this animation instance. Learn more about Theatre.js' animation controls [here](https://www.theatrejs.com/docs/latest/api/core#sequence). | ||
@@ -178,3 +237,3 @@ | ||
### **`useTheatre`** | ||
### **`useTheatre()`** | ||
@@ -181,0 +240,0 @@ Returns the project and the studio instance associated with the component. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
109983
18
143
239
1
3