svelte-motion
Advanced tools
Comparing version 0.11.1 to 0.11.2
{ | ||
"name": "svelte-motion", | ||
"version": "0.11.1", | ||
"version": "0.11.2", | ||
"description": "Svelte animstion library baded on the React library framer-motion.", | ||
@@ -23,2 +23,3 @@ "main": "dist/index.js", | ||
"@emotion/is-prop-valid": "^1.1.0", | ||
"@rollup/plugin-commonjs": "^19.0.0", | ||
"@rollup/plugin-node-resolve": "^11.2.1", | ||
@@ -25,0 +26,0 @@ "@rollup/plugin-replace": "^2.4.2", |
@@ -8,2 +8,3 @@ | ||
const name = pkg.name | ||
@@ -19,3 +20,3 @@ .replace(/^(@\S+\/)?(svelte-)?(\S+)/, '$3') | ||
export default { | ||
export default [{ | ||
input: 'src/index.js', | ||
@@ -36,2 +37,3 @@ output: [ | ||
external | ||
} | ||
} | ||
] |
@@ -14,3 +14,3 @@ /** | ||
*/ | ||
function animationControls() { | ||
function animationControls(startStopNotifier) { | ||
/** | ||
@@ -29,6 +29,15 @@ * Track whether the host component has mounted. | ||
var subscribers = new Set(); | ||
var stopNotification; | ||
var controls = { | ||
subscribe: function (visualElement) { | ||
if (subscribers.size === 0){ | ||
stopNotification = startStopNotifier?.(); | ||
} | ||
subscribers.add(visualElement); | ||
return function () { return void subscribers.delete(visualElement); }; | ||
return function () { | ||
subscribers.delete(visualElement); | ||
if (subscribers.size===0){ | ||
stopNotification?.() | ||
} | ||
}; | ||
}, | ||
@@ -35,0 +44,0 @@ start: function (definition, transitionOverride) { |
@@ -6,3 +6,3 @@ /** | ||
import { onDestroy, tick } from "svelte"; | ||
import { tick } from "svelte"; | ||
import { animationControls } from "./animation-controls" | ||
@@ -60,7 +60,12 @@ | ||
export const useAnimation = () =>{ | ||
const controls = animationControls(); | ||
let cleanup = () => { }; | ||
tick().then(v => cleanup = controls.mount()); | ||
onDestroy(cleanup); | ||
const controls = animationControls(()=>{ | ||
const cleanup = {} | ||
tick().then(v => cleanup.clean = controls.mount()); | ||
return ()=>{ | ||
cleanup.clean?.(); | ||
} | ||
}); | ||
return controls; | ||
@@ -67,0 +72,0 @@ } |
@@ -17,10 +17,10 @@ /** | ||
export const useIsPresent = () => { | ||
let presenceContext = getContext(PresenceContext) || PresenceContext(); | ||
export const useIsPresent = (isCustom=false) => { | ||
let presenceContext = getContext(PresenceContext) || PresenceContext(isCustom); | ||
return derived(presenceContext, $v => $v === null ? true : $v.isPresent) | ||
} | ||
export const usePresence = () => { | ||
export const usePresence = (isCustom=false) => { | ||
const context = getContext(PresenceContext)||PresenceContext(); | ||
const context = getContext(PresenceContext)||PresenceContext(isCustom); | ||
const id = get(context) === null ? undefined : incrementId(); | ||
@@ -27,0 +27,0 @@ onMount(()=>{ |
import { writable } from "svelte/store"; | ||
import { getDomContext } from "./DOMcontext"; | ||
@@ -6,2 +7,2 @@ /** | ||
*/ | ||
export const LayoutGroupContext = ()=>writable(null); | ||
export const LayoutGroupContext = (c)=>getDomContext("LayoutGroup",c)||writable(null); |
import { writable } from "svelte/store"; | ||
import { getDomContext } from "./DOMcontext"; | ||
const LazyContext = () => writable({ strict: false }); | ||
const LazyContext = (c) => getDomContext("Lazy",c) || writable({ strict: false }); | ||
export { LazyContext }; |
import { writable } from "svelte/store"; | ||
import { getDomContext } from "./DOMcontext"; | ||
@@ -7,3 +8,3 @@ | ||
*/ | ||
var MotionConfigContext = ()=> writable({ | ||
var MotionConfigContext = (c)=> getDomContext("MotionConfig",c)||writable({ | ||
transformPagePoint: function (p) { return p; }, | ||
@@ -10,0 +11,0 @@ isStatic: false, |
import { writable } from "svelte/store"; | ||
import { getDomContext } from "./DOMcontext"; | ||
@@ -7,2 +8,2 @@ | ||
*/ | ||
export const PresenceContext = ()=> writable(null); | ||
export const PresenceContext = (c)=> getDomContext("Presence",c)||writable(null); |
@@ -8,4 +8,5 @@ /** | ||
import { createBatcher } from '../components/AnimateSharedLayout/utils/batcher.js'; | ||
import { getDomContext } from './DOMcontext.js'; | ||
var SharedLayoutContext = () => writable(createBatcher()); | ||
var SharedLayoutContext = (custom) => getDomContext("SharedLayout",custom)||writable(createBatcher()); | ||
/** | ||
@@ -12,0 +13,0 @@ * @internal |
@@ -0,1 +1,2 @@ | ||
/** | ||
@@ -5,3 +6,3 @@ based on framer-motion@4.0.3, | ||
*/ | ||
import {fixed} from '../utils/fix-process-env'; | ||
import { fixed } from '../utils/fix-process-env'; | ||
import sync, { getFrameData } from 'framesync'; | ||
@@ -28,3 +29,3 @@ import { velocityPerSecond } from 'popmotion'; | ||
*/ | ||
function MotionValue(init) { | ||
function MotionValue(init, startStopNotifier) { | ||
var _this = this; | ||
@@ -121,2 +122,21 @@ /** | ||
this.canTrackVelocity = isFloat(this.current); | ||
this.onSubscription = () => { } | ||
this.onUnsubscription = () => { } | ||
if (startStopNotifier) { | ||
this.onSubscription = () => { | ||
if (this.updateSubscribers.getSize() + this.velocityUpdateSubscribers.getSize() + this.renderSubscribers.getSize() === 0) { | ||
const unsub = startStopNotifier() | ||
this.onUnsubscription = () => { } | ||
if (unsub) { | ||
this.onUnsubscription = () => { | ||
if (this.updateSubscribers.getSize() + this.velocityUpdateSubscribers.getSize() + this.renderSubscribers.getSize() === 0) { | ||
unsub() | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
@@ -132,30 +152,2 @@ /** | ||
* | ||
* @library | ||
* | ||
* ```jsx | ||
* function MyComponent() { | ||
* const x = useMotionValue(0) | ||
* const y = useMotionValue(0) | ||
* const opacity = useMotionValue(1) | ||
* | ||
* useEffect(() => { | ||
* function updateOpacity() { | ||
* const maxXY = Math.max(x.get(), y.get()) | ||
* const newOpacity = transform(maxXY, [0, 100], [1, 0]) | ||
* opacity.set(newOpacity) | ||
* } | ||
* | ||
* const unsubscribeX = x.onChange(updateOpacity) | ||
* const unsubscribeY = y.onChange(updateOpacity) | ||
* | ||
* return () => { | ||
* unsubscribeX() | ||
* unsubscribeY() | ||
* } | ||
* }, []) | ||
* | ||
* return <Frame x={x} /> | ||
* } | ||
* ``` | ||
* | ||
* @motion | ||
@@ -203,3 +195,9 @@ * | ||
MotionValue.prototype.onChange = function (subscription) { | ||
return this.updateSubscribers.add(subscription); | ||
this.onSubscription(); | ||
const unsub = this.updateSubscribers.add(subscription); | ||
return () => { | ||
unsub() | ||
this.onUnsubscription() | ||
} | ||
}; | ||
@@ -213,2 +211,3 @@ /** Add subscribe method for Svelte store interface */ | ||
this.updateSubscribers.clear(); | ||
this.onUnsubscription() | ||
}; | ||
@@ -224,5 +223,10 @@ /** | ||
MotionValue.prototype.onRenderRequest = function (subscription) { | ||
this.onSubscription() | ||
// Render immediately | ||
subscription(this.get()); | ||
return this.renderSubscribers.add(subscription); | ||
const unsub = this.renderSubscribers.add(subscription); | ||
return () => { | ||
unsub() | ||
this.onUnsubscription() | ||
} | ||
}; | ||
@@ -262,3 +266,3 @@ /** | ||
/** Add update method for Svelte Store behavior */ | ||
MotionValue.prototype.update = function(v){ | ||
MotionValue.prototype.update = function (v) { | ||
this.set(v(this.get())); | ||
@@ -274,3 +278,6 @@ } | ||
MotionValue.prototype.get = function () { | ||
return this.current; | ||
this.onSubscription() | ||
const curr = this.current; | ||
this.onUnsubscription() | ||
return curr | ||
}; | ||
@@ -292,7 +299,10 @@ /** | ||
// This could be isFloat(this.prev) && isFloat(this.current), but that would be wasteful | ||
return this.canTrackVelocity | ||
this.onSubscription() | ||
const vel = this.canTrackVelocity | ||
? // These casts could be avoided if parseFloat would be typed better | ||
velocityPerSecond(parseFloat(this.current) - | ||
parseFloat(this.prev), this.timeDelta) | ||
velocityPerSecond(parseFloat(this.current) - | ||
parseFloat(this.prev), this.timeDelta) | ||
: 0; | ||
this.onUnsubscription() | ||
return vel; | ||
}; | ||
@@ -353,2 +363,3 @@ /** | ||
this.stop(); | ||
this.onUnsubscription() | ||
}; | ||
@@ -360,6 +371,7 @@ return MotionValue; | ||
*/ | ||
function motionValue(init) { | ||
return new MotionValue(init); | ||
function motionValue(init, startStopNotifier) { | ||
return new MotionValue(init, startStopNotifier); | ||
} | ||
export { MotionValue, motionValue }; | ||
@@ -10,4 +10,4 @@ /** | ||
import { addDomEvent } from "../../events/use-dom-event" | ||
import { onDestroy, tick } from "svelte" | ||
const getElementScrollOffsets = (element) => () => { | ||
@@ -23,10 +23,15 @@ return { | ||
export const useElementScroll = (ref) => { | ||
const values = createScrollMotionValues(); | ||
let cleanup; | ||
const setScroll = ()=>{ | ||
cleanup?.(); | ||
if ( (!ref || !ref.current) && !values.ref ){ | ||
return; | ||
const values = {} | ||
const setScroll = async () => { | ||
if (typeof window === "undefined") return ()=>{} | ||
let times = 10 | ||
while ( (!ref || !ref.current) && !values.ref ){ | ||
if(times-- < 1){ | ||
return ()=>{}; | ||
}; | ||
await new Promise(r=>setTimeout(()=>r(),200)); | ||
} | ||
@@ -52,3 +57,3 @@ const element = (ref && ref.current) ? ref : values.ref; | ||
) | ||
cleanup = ()=>{ | ||
return ()=>{ | ||
scrollListener && scrollListener() | ||
@@ -58,12 +63,4 @@ resizeListener && resizeListener() | ||
} | ||
Object.assign(values,createScrollMotionValues(setScroll)); | ||
if (ref && ref.current){ | ||
setScroll() | ||
}else{ | ||
tick().then(setScroll) | ||
} | ||
onDestroy(()=>cleanup?.()) | ||
return values; | ||
@@ -70,0 +67,0 @@ } |
@@ -50,18 +50,2 @@ /** | ||
* | ||
* @library | ||
* | ||
* ```jsx | ||
* import * as React from "react" | ||
* import { | ||
* Frame, | ||
* useViewportScroll, | ||
* useTransform | ||
* } from "framer" | ||
* | ||
* export function MyComponent() { | ||
* const { scrollYProgress } = useViewportScroll() | ||
* return <Frame scaleX={scrollYProgress} /> | ||
* } | ||
* ``` | ||
* | ||
* @motion | ||
@@ -68,0 +52,0 @@ * |
@@ -7,9 +7,30 @@ /** | ||
function createScrollMotionValues() { | ||
return { | ||
scrollX: motionValue(0), | ||
scrollY: motionValue(0), | ||
scrollXProgress: motionValue(0), | ||
scrollYProgress: motionValue(0), | ||
function createScrollMotionValues(startStopNotifier) { | ||
const hasListener = { x: false, y: false, xp: false, yp: false } | ||
let stop | ||
const jointNotifier = startStopNotifier ? (type) => ()=>{ | ||
if (!hasListener.x && !hasListener.y && !hasListener.xp && !hasListener.yp) { | ||
stop = startStopNotifier(); | ||
} | ||
hasListener[type] = true; | ||
return () => { | ||
hasListener[type] = false; | ||
if (!hasListener.x && !hasListener.y && !hasListener.xp && !hasListener.yp) { | ||
if (stop){ | ||
stop.then(v=>v()) | ||
} | ||
} | ||
} | ||
} : ()=>() => { } | ||
const smvs = { | ||
scrollX: motionValue(0,jointNotifier("x")), | ||
scrollY: motionValue(0,jointNotifier("y")), | ||
scrollXProgress: motionValue(0,jointNotifier("xp")), | ||
scrollYProgress: motionValue(0,jointNotifier("yp")), | ||
}; | ||
return smvs; | ||
} | ||
@@ -16,0 +37,0 @@ function setProgress(offset, maxOffset, value) { |
@@ -6,3 +6,2 @@ /** | ||
import sync from 'framesync'; | ||
import { onDestroy } from 'svelte'; | ||
import { motionValue } from '.'; | ||
@@ -12,4 +11,19 @@ | ||
const value = motionValue(combineValues()); | ||
let subscriptions = []; | ||
let vals = values; | ||
const unsubscribe = ()=>{ | ||
subscriptions.forEach((unsubscribe) => unsubscribe()) | ||
} | ||
const subscribe = () => { | ||
subscriptions = vals.map((val) => val.onChange(handler)) | ||
updateValue(); | ||
} | ||
const value = motionValue(combineValues(), () => { | ||
unsubscribe() | ||
subscribe() | ||
return unsubscribe; | ||
}); | ||
let updateValue = () => { | ||
@@ -19,24 +33,14 @@ value.set(combineValues()); | ||
const handler = () => { | ||
sync.update(updateValue, false, true); | ||
} | ||
let subscriptions = values.map((val) => val.onChange(handler)) | ||
onDestroy(() => { | ||
subscriptions.forEach((unsubscribe) => unsubscribe()) | ||
}) | ||
value.reset = (_values, _combineValues) => { | ||
vals=_values; | ||
//cleanup and reset | ||
subscriptions.forEach((unsubscribe) => unsubscribe()) | ||
updateValue = ()=>{ | ||
unsubscribe() | ||
updateValue = () => { | ||
value.set(_combineValues()) | ||
} | ||
subscriptions = _values.map((val) => val.onChange(handler)); | ||
updateValue(); | ||
subscribe() | ||
} | ||
@@ -43,0 +47,0 @@ |
@@ -33,5 +33,5 @@ /** | ||
*/ | ||
export const useSpring = (source, config = {}) => { | ||
export const useSpring = (source, config = {}, isCustom=false) => { | ||
const mcc = getContext(MotionConfigContext) || MotionConfigContext(); | ||
const mcc = getContext(MotionConfigContext) || MotionConfigContext(isCustom); | ||
@@ -38,0 +38,0 @@ let activeSpringAnimation = null; |
@@ -5,3 +5,2 @@ /** | ||
*/ | ||
import { onDestroy } from "svelte"; | ||
import { useMotionValue } from "./use-motion-value" | ||
@@ -20,18 +19,23 @@ /** | ||
export const useVelocity = (value) => { | ||
const velocity = useMotionValue(value.getVelocity()); | ||
let val = value; | ||
let cleanup; | ||
const reset = (val) => { | ||
const velocity = useMotionValue(value.getVelocity(),()=>{ | ||
cleanup?.(); | ||
cleanup = val.velocityUpdateSubscribers.add((newVelocity) => { | ||
velocity.set(newVelocity); | ||
}) | ||
} | ||
return ()=>{ | ||
cleanup?.() | ||
} | ||
}); | ||
reset(value); | ||
onDestroy(()=>{ | ||
cleanup?.() | ||
}) | ||
const reset = (valu) => { | ||
cleanup?.(); | ||
val = valu | ||
cleanup = val.velocityUpdateSubscribers.add((newVelocity) => { | ||
velocity.set(newVelocity); | ||
}) | ||
} | ||
@@ -38,0 +42,0 @@ velocity.reset = reset; |
@@ -9,2 +9,2 @@ /** | ||
*/ | ||
export declare function animationControls(): AnimationControls; | ||
export declare function animationControls(startStopNotifier?: ()=>()=>void): AnimationControls; |
@@ -8,3 +8,3 @@ /** | ||
*/ | ||
export { Motion/*, createDomMotionComponent*/ } from "./render/dom/motion"; | ||
export { Motion/*, createDomMotionComponent*/, M, Motion as MotionSVG } from "./render/dom/motion"; | ||
//export { m } from "./render/dom/motion-minimal"; | ||
@@ -11,0 +11,0 @@ export { AnimatePresence } from "./components/AnimatePresence"; |
@@ -54,1 +54,2 @@ /** | ||
export declare function createDomMotionComponent<T extends keyof DOMMotionComponents>(key: T): DOMMotionComponents[T]; | ||
export declare const M : {[key:string] : Motion} |
@@ -104,3 +104,4 @@ /** | ||
* @param init - The initiating value | ||
* @param config - Optional configuration options | ||
* @param startStopNotifier - a function that is called, once the first subscriber is added to this motion value. | ||
* The return function is called, when the last subscriber unsubscribes. | ||
* | ||
@@ -111,3 +112,3 @@ * - `transformer`: A function to transform incoming values with. | ||
*/ | ||
constructor(init: V); | ||
constructor(init: V, startStopNotifier: ()=>()=>void); | ||
/** | ||
@@ -114,0 +115,0 @@ * Adds a function that will be notified when the `MotionValue` is updated. |
Sorry, the diff of this file is too big to display
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
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
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
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
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
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
1620723
41117
9