motion-start 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +39 -0
- package/package.json +64 -0
- package/src/animation/UseAnimatedState.svelte +86 -0
- package/src/animation/UseAnimation.svelte +61 -0
- package/src/animation/animate.ts +78 -0
- package/src/animation/animation-controls.ts +101 -0
- package/src/animation/types.ts +83 -0
- package/src/animation/use-animated-state.ts +1 -0
- package/src/animation/use-animation.ts +74 -0
- package/src/animation/utils/default-transitions.ts +70 -0
- package/src/animation/utils/easing.ts +55 -0
- package/src/animation/utils/is-animatable.ts +42 -0
- package/src/animation/utils/is-animation-controls.ts +17 -0
- package/src/animation/utils/is-keyframes-target.ts +17 -0
- package/src/animation/utils/transitions.ts +218 -0
- package/src/animation/utils/variant-resolvers.ts +15 -0
- package/src/components/AnimatePresence/AnimatePresence.svelte +180 -0
- package/src/components/AnimatePresence/PresenceChild/PresenceChild.svelte +78 -0
- package/src/components/AnimatePresence/PresenceChild/index.ts +7 -0
- package/src/components/AnimatePresence/PresenceChild/types.ts +10 -0
- package/src/components/AnimatePresence/index.ts +46 -0
- package/src/components/AnimatePresence/types.ts +79 -0
- package/src/components/AnimatePresence/use-presence.ts +90 -0
- package/src/components/AnimateSharedLayout/AnimateSharedLayout.svelte +239 -0
- package/src/components/AnimateSharedLayout/index.ts +11 -0
- package/src/components/AnimateSharedLayout/types.ts +111 -0
- package/src/components/AnimateSharedLayout/utils/batcher.ts +96 -0
- package/src/components/AnimateSharedLayout/utils/crossfader.ts +260 -0
- package/src/components/AnimateSharedLayout/utils/rotate.ts +48 -0
- package/src/components/AnimateSharedLayout/utils/stack.ts +160 -0
- package/src/components/LazyMotion/LazyMotion.svelte +82 -0
- package/src/components/LazyMotion/index.ts +42 -0
- package/src/components/LazyMotion/types.ts +58 -0
- package/src/components/MotionConfig/MotionConfig.svelte +56 -0
- package/src/components/MotionConfig/MotionConfigScaleCorrection.ts +47 -0
- package/src/components/MotionConfig/index.ts +20 -0
- package/src/components/MotionDiv.svelte +8 -0
- package/src/context/DOMcontext.ts +21 -0
- package/src/context/LayoutGroupContext.ts +13 -0
- package/src/context/LazyContext.ts +18 -0
- package/src/context/MotionConfigContext.ts +48 -0
- package/src/context/MotionContext/MotionContext.svelte +27 -0
- package/src/context/MotionContext/MotionContextProvider.svelte +22 -0
- package/src/context/MotionContext/UseCreateMotionContext.svelte +34 -0
- package/src/context/MotionContext/create.ts +1 -0
- package/src/context/MotionContext/index.ts +14 -0
- package/src/context/MotionContext/utils.ts +29 -0
- package/src/context/PresenceContext.ts +26 -0
- package/src/context/ScaleCorrectionProvider.svelte +27 -0
- package/src/context/SharedLayoutContext.ts +29 -0
- package/src/events/UseDomEvent.svelte +67 -0
- package/src/events/UsePointerEvent.svelte +76 -0
- package/src/events/event-info.ts +69 -0
- package/src/events/types.ts +15 -0
- package/src/events/use-dom-event.ts +48 -0
- package/src/events/use-pointer-event.ts +29 -0
- package/src/events/utils.ts +25 -0
- package/src/gestures/PanSession.ts +298 -0
- package/src/gestures/UseFocusGesture.svelte +31 -0
- package/src/gestures/UseGestures.svelte +17 -0
- package/src/gestures/UseHoverGesture.svelte +40 -0
- package/src/gestures/UsePanGesture.svelte +58 -0
- package/src/gestures/UseTapGesture.svelte +77 -0
- package/src/gestures/drag/UseDrag.svelte +55 -0
- package/src/gestures/drag/UseDragControls.svelte +145 -0
- package/src/gestures/drag/VisualElementDragControls.ts +632 -0
- package/src/gestures/drag/types.ts +307 -0
- package/src/gestures/drag/use-drag-controls.ts +148 -0
- package/src/gestures/drag/use-drag.ts +15 -0
- package/src/gestures/drag/utils/constraints.ts +157 -0
- package/src/gestures/drag/utils/lock.ts +69 -0
- package/src/gestures/types.ts +257 -0
- package/src/gestures/use-focus-gesture.ts +16 -0
- package/src/gestures/use-gestures.ts +2 -0
- package/src/gestures/use-hover-gesture.ts +10 -0
- package/src/gestures/use-pan-gesture.ts +22 -0
- package/src/gestures/use-tap-gesture.ts +14 -0
- package/src/gestures/utils/event-type.ts +24 -0
- package/src/gestures/utils/is-node-or-child.ts +31 -0
- package/src/index.ts +104 -0
- package/src/motion/Motion.svelte +246 -0
- package/src/motion/MotionSSR.svelte +244 -0
- package/src/motion/features/AnimationState.svelte +29 -0
- package/src/motion/features/Exit.svelte +32 -0
- package/src/motion/features/UseFeatures.svelte +39 -0
- package/src/motion/features/animations.ts +22 -0
- package/src/motion/features/definitions.ts +49 -0
- package/src/motion/features/drag.ts +24 -0
- package/src/motion/features/gestures.ts +24 -0
- package/src/motion/features/layout/Animate.svelte +314 -0
- package/src/motion/features/layout/Animate.ts +9 -0
- package/src/motion/features/layout/AnimateLayoutContextProvider.svelte +14 -0
- package/src/motion/features/layout/Measure.svelte +98 -0
- package/src/motion/features/layout/Measure.ts +9 -0
- package/src/motion/features/layout/MeasureContextProvider.svelte +32 -0
- package/src/motion/features/layout/index.ts +20 -0
- package/src/motion/features/layout/types.ts +71 -0
- package/src/motion/features/layout/utils.ts +40 -0
- package/src/motion/features/types.ts +53 -0
- package/src/motion/features/use-features.ts +16 -0
- package/src/motion/index.ts +64 -0
- package/src/motion/types.ts +278 -0
- package/src/motion/utils/UseLayoutId.svelte +18 -0
- package/src/motion/utils/UseVisualElement.svelte +104 -0
- package/src/motion/utils/UseVisualState.svelte +137 -0
- package/src/motion/utils/is-forced-motion-value.ts +23 -0
- package/src/motion/utils/make-renderless-component.ts +17 -0
- package/src/motion/utils/should-inhert-variant.ts +6 -0
- package/src/motion/utils/use-motion-ref.ts +41 -0
- package/src/motion/utils/use-visual-element.ts +13 -0
- package/src/motion/utils/use-visual-state.ts +24 -0
- package/src/motion/utils/valid-prop.ts +80 -0
- package/src/render/dom/M.svelte +16 -0
- package/src/render/dom/UseRender.svelte +37 -0
- package/src/render/dom/create-motion-class.ts +12 -0
- package/src/render/dom/create-visual-element.ts +22 -0
- package/src/render/dom/featureBundle.ts +22 -0
- package/src/render/dom/motion-minimal.ts +22 -0
- package/src/render/dom/motion-proxy.ts +107 -0
- package/src/render/dom/motion.ts +62 -0
- package/src/render/dom/projection/convert-to-relative.ts +40 -0
- package/src/render/dom/projection/default-scale-correctors.ts +138 -0
- package/src/render/dom/projection/measure.ts +28 -0
- package/src/render/dom/projection/relative-set.ts +27 -0
- package/src/render/dom/projection/scale-correction.ts +22 -0
- package/src/render/dom/projection/types.ts +13 -0
- package/src/render/dom/projection/utils.ts +69 -0
- package/src/render/dom/svg-visual-element.ts +114 -0
- package/src/render/dom/types.ts +32 -0
- package/src/render/dom/use-render.ts +11 -0
- package/src/render/dom/utils/UseInitialMotionProps.svelte +26 -0
- package/src/render/dom/utils/batch-layout.ts +77 -0
- package/src/render/dom/utils/camel-to-dash.ts +20 -0
- package/src/render/dom/utils/create-config.ts +33 -0
- package/src/render/dom/utils/css-variables-conversion.ts +121 -0
- package/src/render/dom/utils/filter-props.ts +55 -0
- package/src/render/dom/utils/is-css-variable.ts +18 -0
- package/src/render/dom/utils/is-svg-component.ts +41 -0
- package/src/render/dom/utils/parse-dom-variant.ts +26 -0
- package/src/render/dom/utils/unit-conversion.ts +258 -0
- package/src/render/dom/utils/use-html-props.ts +2 -0
- package/src/render/dom/utils/use-svg-props.ts +1 -0
- package/src/render/dom/value-types/animatable-none.ts +24 -0
- package/src/render/dom/value-types/defaults.ts +30 -0
- package/src/render/dom/value-types/dimensions.ts +27 -0
- package/src/render/dom/value-types/find.ts +31 -0
- package/src/render/dom/value-types/get-as-type.ts +21 -0
- package/src/render/dom/value-types/number.ts +83 -0
- package/src/render/dom/value-types/test.ts +17 -0
- package/src/render/dom/value-types/type-auto.ts +21 -0
- package/src/render/dom/value-types/type-int.ts +23 -0
- package/src/render/dom/value-types/types.ts +8 -0
- package/src/render/html/UseHTMLProps.svelte +33 -0
- package/src/render/html/UseInitialMotionValues.svelte +27 -0
- package/src/render/html/UseStyle.svelte +47 -0
- package/src/render/html/config-motion.ts +23 -0
- package/src/render/html/supported-elements.ts +10 -0
- package/src/render/html/types.ts +64 -0
- package/src/render/html/use-props.ts +14 -0
- package/src/render/html/utils/build-projection-transform.ts +53 -0
- package/src/render/html/utils/build-styles.ts +121 -0
- package/src/render/html/utils/build-transform.ts +79 -0
- package/src/render/html/utils/create-render-state.ts +18 -0
- package/src/render/html/utils/render.ts +22 -0
- package/src/render/html/utils/scrape-motion-values.ts +26 -0
- package/src/render/html/utils/transform.ts +51 -0
- package/src/render/html/visual-element.ts +129 -0
- package/src/render/index.ts +703 -0
- package/src/render/svg/UseSVGProps.svelte +34 -0
- package/src/render/svg/config-motion.ts +51 -0
- package/src/render/svg/lowercase-elements.ts +35 -0
- package/src/render/svg/supported-elements.ts +10 -0
- package/src/render/svg/types.ts +51 -0
- package/src/render/svg/use-props.ts +14 -0
- package/src/render/svg/utils/build-attrs.ts +58 -0
- package/src/render/svg/utils/camel-case-attrs.ts +27 -0
- package/src/render/svg/utils/create-render-state.ts +17 -0
- package/src/render/svg/utils/path.ts +49 -0
- package/src/render/svg/utils/render.ts +22 -0
- package/src/render/svg/utils/scrape-motion-values.ts +26 -0
- package/src/render/svg/utils/transform-origin.ts +30 -0
- package/src/render/svg/visual-element.ts +44 -0
- package/src/render/types.ts +148 -0
- package/src/render/utils/animation-state.ts +375 -0
- package/src/render/utils/animation.ts +167 -0
- package/src/render/utils/compare-by-depth.ts +18 -0
- package/src/render/utils/flat-tree.ts +35 -0
- package/src/render/utils/is-draggable.ts +17 -0
- package/src/render/utils/lifecycles.ts +172 -0
- package/src/render/utils/motion-values.ts +59 -0
- package/src/render/utils/projection.ts +38 -0
- package/src/render/utils/setters.ts +910 -0
- package/src/render/utils/state.ts +113 -0
- package/src/render/utils/types.ts +12 -0
- package/src/render/utils/variants.ts +76 -0
- package/src/types/geometry.ts +91 -0
- package/src/types.ts +1088 -0
- package/src/utils/UseUnmountEffect.svelte +11 -0
- package/src/utils/array.ts +18 -0
- package/src/utils/each-axis.ts +15 -0
- package/src/utils/errors.ts +22 -0
- package/src/utils/fix-process-env.ts +22 -0
- package/src/utils/geometry/delta-apply.ts +162 -0
- package/src/utils/geometry/delta-calc.ts +89 -0
- package/src/utils/geometry/index.ts +83 -0
- package/src/utils/is-browser.ts +12 -0
- package/src/utils/is-numerical-string.ts +15 -0
- package/src/utils/is-ref-object.ts +16 -0
- package/src/utils/noop.ts +15 -0
- package/src/utils/resolve-value.ts +23 -0
- package/src/utils/shallow-compare.ts +23 -0
- package/src/utils/subscription-manager.ts +49 -0
- package/src/utils/time-conversion.ts +18 -0
- package/src/utils/transform.ts +120 -0
- package/src/utils/use-constant.ts +23 -0
- package/src/utils/use-cycle.ts +78 -0
- package/src/utils/use-force-update.ts +7 -0
- package/src/utils/use-isomorphic-effect.ts +8 -0
- package/src/utils/use-reduced-motion.ts +70 -0
- package/src/utils/use-unmount-effect.ts +8 -0
- package/src/value/index.ts +409 -0
- package/src/value/scroll/use-element-scroll.ts +73 -0
- package/src/value/scroll/use-viewport-scroll.ts +81 -0
- package/src/value/scroll/utils.ts +76 -0
- package/src/value/use-combine-values.ts +53 -0
- package/src/value/use-motion-template.ts +57 -0
- package/src/value/use-motion-value.ts +27 -0
- package/src/value/use-spring.ts +84 -0
- package/src/value/use-transform.ts +216 -0
- package/src/value/use-velocity.ts +44 -0
- package/src/value/utils/is-motion-value.ts +15 -0
- package/src/value/utils/resolve-motion-value.ts +29 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
based on framer-motion@4.1.17,
|
|
3
|
+
Copyright (c) 2018 Framer B.V.
|
|
4
|
+
*/
|
|
5
|
+
export type { AnimatePresenceProps } from "./types.js";
|
|
6
|
+
/**
|
|
7
|
+
* `AnimatePresence` enables the animation of components that have been removed from the tree.
|
|
8
|
+
*
|
|
9
|
+
* You can provide an array T[] to the `list` prop, where each item has to have a unique `key` attribute. Via slot prop `item`
|
|
10
|
+
* single items of the array are passed down to children, so that for each array item one component is rendered.
|
|
11
|
+
*
|
|
12
|
+
* Alternatively you can leave `list` undefined and supply a boolean to the `show` prop. If `true`, the child is rendered.
|
|
13
|
+
*
|
|
14
|
+
* @motion
|
|
15
|
+
*
|
|
16
|
+
* Any `motion` components that have an `exit` property defined will animate out when removed from
|
|
17
|
+
* the tree.
|
|
18
|
+
*
|
|
19
|
+
* ```jsx
|
|
20
|
+
* import { motion, AnimatePresence } from 'svelte-motion'
|
|
21
|
+
* const items = [
|
|
22
|
+
* {key:1},
|
|
23
|
+
* {key:2},
|
|
24
|
+
* {key:3}
|
|
25
|
+
* ]
|
|
26
|
+
* <AnimatePresence list={items}>
|
|
27
|
+
* <MotionDiv
|
|
28
|
+
* initial={{ opacity: 0 }}
|
|
29
|
+
* animate={{ opacity: 1 }}
|
|
30
|
+
* exit={{ opacity: 0 }}
|
|
31
|
+
* />
|
|
32
|
+
* </AnimatePresence>
|
|
33
|
+
* )
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* You can sequence exit animations throughout a tree using variants.
|
|
37
|
+
*
|
|
38
|
+
* If a child contains multiple `Motion` components with `exit` props, it will only unmount the child
|
|
39
|
+
* once all `motion` components have finished animating out. Likewise, any components using
|
|
40
|
+
* `usePresence` all need to call `safeToRemove`.
|
|
41
|
+
*
|
|
42
|
+
* @public
|
|
43
|
+
*/
|
|
44
|
+
export type ConditionalGeneric<T> = T extends {key:any} ? T : { key: 1}; // Better handling of defaults and the optional list prop
|
|
45
|
+
export { default as AnimatePresence } from './AnimatePresence.svelte';
|
|
46
|
+
export { PresenceChild } from './PresenceChild/index.js';
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
based on framer-motion@4.1.17,
|
|
3
|
+
Copyright (c) 2018 Framer B.V.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export interface AnimatePresenceProps<T extends {key:any}> {
|
|
9
|
+
/**
|
|
10
|
+
* By passing `initial={false}`, `AnimatePresence` will disable any initial animations on children
|
|
11
|
+
* that are present when the component is first rendered.
|
|
12
|
+
*
|
|
13
|
+
* @motion
|
|
14
|
+
*
|
|
15
|
+
* ```jsx
|
|
16
|
+
* <AnimatePresence initial={false} show={isVisible}>
|
|
17
|
+
* <MotionDiv
|
|
18
|
+
* key="modal"
|
|
19
|
+
* initial={{ opacity: 0 }}
|
|
20
|
+
* animate={{ opacity: 1 }}
|
|
21
|
+
* exit={{ opacity: 0 }}
|
|
22
|
+
* />
|
|
23
|
+
* </AnimatePresence>
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
initial?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* When a component is removed, there's no longer a chance to update its props. So if a component's `exit`
|
|
31
|
+
* prop is defined as a dynamic variant and you want to pass a new `custom` prop, you can do so via `AnimatePresence`.
|
|
32
|
+
* This will ensure all leaving components animate using the latest data.
|
|
33
|
+
*
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
custom?: any;
|
|
37
|
+
/**
|
|
38
|
+
* Fires when all exiting nodes have completed animating out.
|
|
39
|
+
*
|
|
40
|
+
* @public
|
|
41
|
+
*/
|
|
42
|
+
onExitComplete?: () => void;
|
|
43
|
+
/**
|
|
44
|
+
* If set to `true`, `AnimatePresence` will only render one component at a time. The exiting component
|
|
45
|
+
* will finished its exit animation before the entering component is rendered.
|
|
46
|
+
*
|
|
47
|
+
* @motion
|
|
48
|
+
*
|
|
49
|
+
* ```jsx
|
|
50
|
+
* const MyComponent = ({ currentItem }) => (
|
|
51
|
+
* <AnimatePresence exitBeforeEnter>
|
|
52
|
+
* <MotionDiv key={currentItem} exit={{ opacity: 0 }} />
|
|
53
|
+
* </AnimatePresence>
|
|
54
|
+
* )
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* @beta
|
|
58
|
+
*/
|
|
59
|
+
exitBeforeEnter?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Used in Framer to flag that sibling children *shouldn't* re-render as a result of a
|
|
62
|
+
* child being removed.
|
|
63
|
+
*
|
|
64
|
+
* @internal
|
|
65
|
+
*/
|
|
66
|
+
presenceAffectsLayout?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* The data array for the items you want to render. Every Item needs a unique `key`.
|
|
69
|
+
*
|
|
70
|
+
* Alternatively, you can leave this undefined and supply `show` prop.
|
|
71
|
+
*/
|
|
72
|
+
list?:T[]
|
|
73
|
+
/**
|
|
74
|
+
* Render the child when this is set to `true`, exit it when changed to `false`.
|
|
75
|
+
*
|
|
76
|
+
* Only used when list is undefined.
|
|
77
|
+
*/
|
|
78
|
+
show?: boolean
|
|
79
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
based on framer-motion@4.1.17,
|
|
3
|
+
Copyright (c) 2018 Framer B.V.
|
|
4
|
+
*/
|
|
5
|
+
import type { Readable } from 'svelte/store';
|
|
6
|
+
import type { PresenceContextProps } from "../../context/PresenceContext";
|
|
7
|
+
|
|
8
|
+
import { derived, get, readable } from 'svelte/store';
|
|
9
|
+
import { PresenceContext } from '../../context/PresenceContext.js';
|
|
10
|
+
|
|
11
|
+
import { getContext, onMount } from "svelte";
|
|
12
|
+
|
|
13
|
+
export type SafeToRemove = () => void;
|
|
14
|
+
type AlwaysPresent = [true, null];
|
|
15
|
+
type Present = [true];
|
|
16
|
+
type NotPresent = [false, SafeToRemove];
|
|
17
|
+
|
|
18
|
+
let counter = 0;
|
|
19
|
+
const incrementId = () => counter++;
|
|
20
|
+
|
|
21
|
+
export function isPresent(context: PresenceContextProps) {
|
|
22
|
+
return context === null ? true : context.isPresent
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Similar to `usePresence`, except `useIsPresent` simply returns whether or not the component is present.
|
|
27
|
+
* There is no `safeToRemove` function.
|
|
28
|
+
*
|
|
29
|
+
* ```jsx
|
|
30
|
+
* import { useIsPresent } from "framer-motion"
|
|
31
|
+
*
|
|
32
|
+
* export const Component = () => {
|
|
33
|
+
* const isPresent = useIsPresent()
|
|
34
|
+
*
|
|
35
|
+
* useEffect(() => {
|
|
36
|
+
* !isPresent && console.log("I've been removed!")
|
|
37
|
+
* }, [isPresent])
|
|
38
|
+
*
|
|
39
|
+
* return <div />
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
export const useIsPresent = (isCustom=false): Readable<boolean> => {
|
|
46
|
+
let presenceContext = getContext(PresenceContext) || PresenceContext(isCustom);
|
|
47
|
+
return derived(presenceContext, $v => $v === null ? true : $v.isPresent)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* When a component is the child of `AnimatePresence`, it can use `usePresence`
|
|
52
|
+
* to access information about whether it's still present in the React tree.
|
|
53
|
+
*
|
|
54
|
+
* ```jsx
|
|
55
|
+
* import { usePresence } from "framer-motion"
|
|
56
|
+
*
|
|
57
|
+
* const [isPresent, safeToRemove] = usePresence()
|
|
58
|
+
*
|
|
59
|
+
*
|
|
60
|
+
* $: !isPresent && setTimeout(safeToRemove, 1000)
|
|
61
|
+
*
|
|
62
|
+
*
|
|
63
|
+
* return <div />
|
|
64
|
+
* }
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* If `isPresent` is `false`, it means that a component has been removed the tree, but
|
|
68
|
+
* `AnimatePresence` won't really remove it until `safeToRemove` has been called.
|
|
69
|
+
*
|
|
70
|
+
* @public
|
|
71
|
+
*/
|
|
72
|
+
export const usePresence = (isCustom=false): Readable<AlwaysPresent | Present | NotPresent> => {
|
|
73
|
+
|
|
74
|
+
const context = getContext(PresenceContext)||PresenceContext(isCustom);
|
|
75
|
+
const id = get(context) === null ? undefined : incrementId();
|
|
76
|
+
onMount(()=>{
|
|
77
|
+
if (get(context)!==null){
|
|
78
|
+
get(context).register(id);
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
if (get(context) === null){
|
|
83
|
+
return readable([true,null]);
|
|
84
|
+
}
|
|
85
|
+
return derived(context,$v=>
|
|
86
|
+
(!$v.isPresent && $v.onExitComplete) ?
|
|
87
|
+
[false, ()=>$v.onExitComplete?.(id)] :
|
|
88
|
+
[true]
|
|
89
|
+
)
|
|
90
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
<!-- based on framer-motion@4.0.3,
|
|
2
|
+
Copyright (c) 2018 Framer B.V. -->
|
|
3
|
+
|
|
4
|
+
<script lang="ts">
|
|
5
|
+
import { SharedLayoutContext } from "../../context/SharedLayoutContext.js";
|
|
6
|
+
import type { Presence, SharedLayoutProps } from "./index.js";
|
|
7
|
+
import { createBatcher } from "./utils/batcher.js";
|
|
8
|
+
|
|
9
|
+
import { getContext, onMount, setContext, tick } from "svelte";
|
|
10
|
+
import { get, writable } from "svelte/store";
|
|
11
|
+
import { setDomContext } from "../../context/DOMcontext.js";
|
|
12
|
+
import { MotionContext } from "../../context/MotionContext/index.js";
|
|
13
|
+
import { snapshotViewportBox } from "../../render/dom/projection/utils.js";
|
|
14
|
+
import { resetRotate } from "./utils/rotate.js";
|
|
15
|
+
import { layoutStack } from "./utils/stack.js";
|
|
16
|
+
|
|
17
|
+
type $$Props = SharedLayoutProps;
|
|
18
|
+
|
|
19
|
+
export let type: $$Props["type"] = undefined,
|
|
20
|
+
isCustom = false;
|
|
21
|
+
|
|
22
|
+
const context = getContext(MotionContext) || MotionContext(isCustom);
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Track whether the component has mounted. If it hasn't, the presence of added children
|
|
26
|
+
* are set to Present, whereas if it has they're considered Entering
|
|
27
|
+
*/
|
|
28
|
+
let hasMounted = false;
|
|
29
|
+
/**
|
|
30
|
+
* A list of all the children in the shared layout
|
|
31
|
+
*/
|
|
32
|
+
let children = new Set();
|
|
33
|
+
/**
|
|
34
|
+
* As animate components with a defined `layoutId` are added/removed to the tree,
|
|
35
|
+
* we store them in order. When one is added, it will animate out from the
|
|
36
|
+
* previous one, and when it's removed, it'll animate to the previous one.
|
|
37
|
+
*/
|
|
38
|
+
let stacks = new Map();
|
|
39
|
+
/**
|
|
40
|
+
* Track whether we already have an update scheduled. If we don't, we'll run snapshots
|
|
41
|
+
* and schedule one.
|
|
42
|
+
*/
|
|
43
|
+
let updateScheduled = false;
|
|
44
|
+
/**
|
|
45
|
+
* Tracks whether we already have a render scheduled. If we don't, we'll force one with this.forceRender
|
|
46
|
+
*/
|
|
47
|
+
let renderScheduled = false;
|
|
48
|
+
|
|
49
|
+
let forced = false; /*
|
|
50
|
+
const resetForced = ()=>{
|
|
51
|
+
if (forced){
|
|
52
|
+
forced=false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
$: resetForced(forced);
|
|
56
|
+
*/
|
|
57
|
+
/**
|
|
58
|
+
* The methods provided to all children in the shared layout tree.
|
|
59
|
+
*/
|
|
60
|
+
let syncContext = {
|
|
61
|
+
...createBatcher(),
|
|
62
|
+
syncUpdate: (force) => scheduleUpdate(force),
|
|
63
|
+
forceUpdate: () => {
|
|
64
|
+
// By copying syncContext to itself, when this component re-renders it'll also re-render
|
|
65
|
+
// all children subscribed to the SharedLayout context.
|
|
66
|
+
//syncContext = { ...syncContext }
|
|
67
|
+
//scheduleUpdate(true)
|
|
68
|
+
//syncContext = { ...syncContext }
|
|
69
|
+
//setSyncContext()
|
|
70
|
+
scheduleUpdate();
|
|
71
|
+
|
|
72
|
+
forced = true;
|
|
73
|
+
},
|
|
74
|
+
register: (child) => addChild(child),
|
|
75
|
+
remove: (child) => {
|
|
76
|
+
removeChild(child);
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const startLayoutAnimation = () => {
|
|
81
|
+
/**
|
|
82
|
+
* Reset update and render scheduled status
|
|
83
|
+
*/
|
|
84
|
+
renderScheduled = updateScheduled = false;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Update presence metadata based on the latest AnimatePresence status.
|
|
88
|
+
* This is a kind of goofy way of dealing with this, perhaps there's a better model to find.
|
|
89
|
+
*/
|
|
90
|
+
children.forEach((child) => {
|
|
91
|
+
if (!child.isPresent) {
|
|
92
|
+
child.presence = Presence.Exiting;
|
|
93
|
+
} else if (child.presence !== Presence.Entering) {
|
|
94
|
+
child.presence =
|
|
95
|
+
child.presence === Presence.Exiting
|
|
96
|
+
? Presence.Entering
|
|
97
|
+
: Presence.Present;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
updateStacks();
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Create a handler which we can use to flush the children animations
|
|
105
|
+
*/
|
|
106
|
+
const handler = {
|
|
107
|
+
measureLayout: (child) => child.updateLayoutMeasurement(),
|
|
108
|
+
layoutReady: (child) => {
|
|
109
|
+
if (child.getLayoutId() !== undefined) {
|
|
110
|
+
const stack = getStack(child);
|
|
111
|
+
stack.animate(child, type === "crossfade");
|
|
112
|
+
} else {
|
|
113
|
+
child.notifyLayoutReady();
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
parent: get(context).visualElement,
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Shared layout animations can be used without the AnimateSharedLayout wrapping component.
|
|
120
|
+
* This requires some co-ordination across components to stop layout thrashing
|
|
121
|
+
* and ensure measurements are taken at the correct time.
|
|
122
|
+
*
|
|
123
|
+
* Here we use that same mechanism of schedule/flush.
|
|
124
|
+
*/
|
|
125
|
+
children.forEach((child) => syncContext.add(child));
|
|
126
|
+
syncContext.flush(handler);
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Clear snapshots so subsequent rerenders don't retain memory of outgoing components
|
|
130
|
+
*/
|
|
131
|
+
stacks.forEach((stack) => stack.clearSnapshot());
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const updateStacks = () => {
|
|
135
|
+
stacks.forEach((stack) => stack.updateLeadAndFollow());
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const scheduleUpdate = (force = false) => {
|
|
139
|
+
if (!(force || !updateScheduled)) return;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Flag we've scheduled an update
|
|
143
|
+
*/
|
|
144
|
+
updateScheduled = true;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Write: Reset rotation transforms so bounding boxes can be accurately measured.
|
|
148
|
+
*/
|
|
149
|
+
children.forEach((child) => resetRotate(child));
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Read: Snapshot children
|
|
153
|
+
*/
|
|
154
|
+
children.forEach((child) => snapshotViewportBox(child));
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Every child keeps a local snapshot, but we also want to record
|
|
158
|
+
* snapshots of the visible children as, if they're are being removed
|
|
159
|
+
* in this render, we can still access them.
|
|
160
|
+
*
|
|
161
|
+
* TODO: What would be better here is doing a single loop where we
|
|
162
|
+
* only snapshotViewportBoxes of undefined layoutIds and then one for each stack
|
|
163
|
+
*/
|
|
164
|
+
stacks.forEach((stack) => stack.updateSnapshot());
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Force a rerender by setting state if we aren't already going to render.
|
|
168
|
+
*/
|
|
169
|
+
if (force || !renderScheduled) {
|
|
170
|
+
renderScheduled = true;
|
|
171
|
+
forced = true;
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const addChild = (child) => {
|
|
176
|
+
children.add(child);
|
|
177
|
+
addToStack(child);
|
|
178
|
+
|
|
179
|
+
child.presence = hasMounted ? Presence.Entering : Presence.Present;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const removeChild = (child) => {
|
|
183
|
+
scheduleUpdate();
|
|
184
|
+
children.delete(child);
|
|
185
|
+
removeFromStack(child);
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const addToStack = (child) => {
|
|
189
|
+
const stack = getStack(child);
|
|
190
|
+
stack?.add(child);
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const removeFromStack = (child) => {
|
|
194
|
+
const stack = getStack(child);
|
|
195
|
+
stack?.remove(child);
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Return a stack of animate children based on the provided layoutId.
|
|
200
|
+
* Will create a stack if none currently exists with that layoutId.
|
|
201
|
+
*/
|
|
202
|
+
const getStack = (child) => {
|
|
203
|
+
const id = child.getLayoutId();
|
|
204
|
+
if (id === undefined) return;
|
|
205
|
+
|
|
206
|
+
// Create stack if it doesn't already exist
|
|
207
|
+
!stacks.has(id) && stacks.set(id, layoutStack());
|
|
208
|
+
|
|
209
|
+
return stacks.get(id);
|
|
210
|
+
};
|
|
211
|
+
let sc = writable(syncContext);
|
|
212
|
+
|
|
213
|
+
const setSyncContext = () => {
|
|
214
|
+
syncContext = { ...syncContext };
|
|
215
|
+
sc.set(syncContext);
|
|
216
|
+
//forced = !forced
|
|
217
|
+
};
|
|
218
|
+
//$: sc.set(syncContext)
|
|
219
|
+
setContext(SharedLayoutContext, sc);
|
|
220
|
+
setDomContext("SharedLayout", isCustom, sc);
|
|
221
|
+
|
|
222
|
+
onMount(() => {
|
|
223
|
+
hasMounted = true;
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
//afterUpdate(()=>!forced && startLayoutAnimation())
|
|
227
|
+
//const falseForced = ()=>{forced=false;return true;}
|
|
228
|
+
//$: forced && renderScheduled && falseForced() && startLayoutAnimation()
|
|
229
|
+
|
|
230
|
+
$: if (renderScheduled) {
|
|
231
|
+
tick().then(() => {
|
|
232
|
+
startLayoutAnimation();
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
//afterUpdate(startLayoutAnimation)
|
|
237
|
+
</script>
|
|
238
|
+
|
|
239
|
+
<slot />
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
based on framer-motion@4.1.17,
|
|
3
|
+
Copyright (c) 2018 Framer B.V.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type { SharedLayoutProps, Presence } from "./types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Wrap several [#Motion] components with the \`layout\` or \`layoutId\` prop with this component, so that all react smoothly to the change of a single component.
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
export {default as AnimateSharedLayout} from './AnimateSharedLayout.svelte'
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
based on framer-motion@4.1.17,
|
|
3
|
+
Copyright (c) 2018 Framer B.V.
|
|
4
|
+
*/
|
|
5
|
+
import type { VisualElement } from "../../render/types";
|
|
6
|
+
import type { Transition } from "../../types";
|
|
7
|
+
import type { AxisBox2D } from "../../types/geometry";
|
|
8
|
+
import { MotionValue } from "../../value";
|
|
9
|
+
/**
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export enum Presence {
|
|
13
|
+
Entering = 0,
|
|
14
|
+
Present = 1,
|
|
15
|
+
Exiting = 2
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
export enum VisibilityAction {
|
|
21
|
+
Hide = 0,
|
|
22
|
+
Show = 1
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
27
|
+
export interface SharedLayoutProps {
|
|
28
|
+
/**
|
|
29
|
+
* @public
|
|
30
|
+
*/
|
|
31
|
+
//children: React.ReactNode;
|
|
32
|
+
/**
|
|
33
|
+
* When combined with `AnimatePresence`, `SharedLayoutProps` can customise how to visually switch
|
|
34
|
+
* between `layoutId` components as new ones enter and leave the tree.
|
|
35
|
+
*
|
|
36
|
+
* - "switch" (default): The old `layoutId` component will be hidden instantly when a new one enters, and
|
|
37
|
+
* the new one will perform the full transition. When the newest one is removed, it will perform
|
|
38
|
+
* the full exit transition and then the old component will be shown instantly.
|
|
39
|
+
* - "crossfade": The root shared components will crossfade as `layoutId` children of both perform
|
|
40
|
+
* the same transition.
|
|
41
|
+
*
|
|
42
|
+
* @public
|
|
43
|
+
*/
|
|
44
|
+
type?: "switch" | "crossfade";
|
|
45
|
+
}
|
|
46
|
+
export interface SharedLayoutAnimationConfig {
|
|
47
|
+
visibilityAction?: VisibilityAction;
|
|
48
|
+
originBox?: AxisBox2D;
|
|
49
|
+
targetBox?: AxisBox2D;
|
|
50
|
+
transition?: Transition;
|
|
51
|
+
crossfadeOpacity?: MotionValue<number>;
|
|
52
|
+
shouldStackAnimate?: boolean;
|
|
53
|
+
onComplete?: () => void;
|
|
54
|
+
isRelative?: boolean;
|
|
55
|
+
prevParent?: VisualElement;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Handlers for batching sync layout lifecycles. We batches these processes to cut
|
|
59
|
+
* down on layout thrashing
|
|
60
|
+
*
|
|
61
|
+
* @public
|
|
62
|
+
*/
|
|
63
|
+
export interface SyncLayoutLifecycles {
|
|
64
|
+
layoutReady: (child: VisualElement) => void;
|
|
65
|
+
parent?: VisualElement;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The exposed API for children to add themselves to the batcher and to flush it.
|
|
69
|
+
*
|
|
70
|
+
* @public
|
|
71
|
+
*/
|
|
72
|
+
export interface SyncLayoutBatcher {
|
|
73
|
+
add: (child: VisualElement) => void;
|
|
74
|
+
flush: (handler?: SyncLayoutLifecycles) => void;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Extra API methods available to children if they're a descendant of AnimateSharedLayout
|
|
78
|
+
*/
|
|
79
|
+
export interface SharedLayoutSyncMethods extends SyncLayoutBatcher {
|
|
80
|
+
syncUpdate: (force?: boolean) => void;
|
|
81
|
+
forceUpdate: () => void;
|
|
82
|
+
register: (child: VisualElement) => void;
|
|
83
|
+
remove: (child: VisualElement) => void;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
based on framer-motion@4.0.3,
|
|
89
|
+
Copyright (c) 2018 Framer B.V.
|
|
90
|
+
*/
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @public
|
|
94
|
+
*/
|
|
95
|
+
// var Presence;
|
|
96
|
+
// (function (Presence) {
|
|
97
|
+
// Presence[Presence["Entering"] = 0] = "Entering";
|
|
98
|
+
// Presence[Presence["Present"] = 1] = "Present";
|
|
99
|
+
// Presence[Presence["Exiting"] = 2] = "Exiting";
|
|
100
|
+
// })(Presence || (Presence = {}));
|
|
101
|
+
// /**
|
|
102
|
+
// * @public
|
|
103
|
+
// */
|
|
104
|
+
// var VisibilityAction;
|
|
105
|
+
// (function (VisibilityAction) {
|
|
106
|
+
// VisibilityAction[VisibilityAction["Hide"] = 0] = "Hide";
|
|
107
|
+
// VisibilityAction[VisibilityAction["Show"] = 1] = "Show";
|
|
108
|
+
// })(VisibilityAction || (VisibilityAction = {}));
|
|
109
|
+
|
|
110
|
+
// export { Presence, VisibilityAction };
|
|
111
|
+
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
based on framer-motion@4.1.17,
|
|
3
|
+
Copyright (c) 2018 Framer B.V.
|
|
4
|
+
*/
|
|
5
|
+
import type { SyncLayoutBatcher } from "../types";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
based on framer-motion@4.1.15,
|
|
9
|
+
Copyright (c) 2018 Framer B.V.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { __spreadArray, __read } from 'tslib';
|
|
13
|
+
import sync, { flushSync } from 'framesync';
|
|
14
|
+
import { collectProjectingAncestors, updateLayoutMeasurement } from '../../../render/dom/projection/utils.js';
|
|
15
|
+
import { batchLayout, flushLayout } from '../../../render/dom/utils/batch-layout.js';
|
|
16
|
+
import { compareByDepth } from '../../../render/utils/compare-by-depth.js';
|
|
17
|
+
import { Presence } from '../types.js';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Default handlers for batching VisualElements
|
|
21
|
+
*/
|
|
22
|
+
var defaultHandler = {
|
|
23
|
+
layoutReady: function (child) { return child.notifyLayoutReady(); },
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Create a batcher to process VisualElements
|
|
27
|
+
*/
|
|
28
|
+
function createBatcher(): SyncLayoutBatcher {
|
|
29
|
+
var queue = new Set();
|
|
30
|
+
return {
|
|
31
|
+
add: function (child) { return queue.add(child); },
|
|
32
|
+
flush: function (_a) {
|
|
33
|
+
var _b = _a === void 0 ? defaultHandler : _a, layoutReady = _b.layoutReady, parent = _b.parent;
|
|
34
|
+
batchLayout(function (read, write) {
|
|
35
|
+
var order = Array.from(queue).sort(compareByDepth);
|
|
36
|
+
var ancestors = parent
|
|
37
|
+
? collectProjectingAncestors(parent)
|
|
38
|
+
: [];
|
|
39
|
+
write(function () {
|
|
40
|
+
var allElements = __spreadArray(__spreadArray([], __read(ancestors)), __read(order));
|
|
41
|
+
allElements.forEach(function (element) { return element.resetTransform(); });
|
|
42
|
+
});
|
|
43
|
+
read(function () {
|
|
44
|
+
order.forEach(updateLayoutMeasurement);
|
|
45
|
+
});
|
|
46
|
+
write(function () {
|
|
47
|
+
ancestors.forEach(function (element) { return element.restoreTransform(); });
|
|
48
|
+
order.forEach(layoutReady);
|
|
49
|
+
});
|
|
50
|
+
read(function () {
|
|
51
|
+
/**
|
|
52
|
+
* After all children have started animating, ensure any Entering components are set to Present.
|
|
53
|
+
* If we add deferred animations (set up all animations and then start them in two loops) this
|
|
54
|
+
* could be moved to the start loop. But it needs to happen after all the animations configs
|
|
55
|
+
* are generated in AnimateSharedLayout as this relies on presence data
|
|
56
|
+
*/
|
|
57
|
+
order.forEach(function (child) {
|
|
58
|
+
if (child.isPresent)
|
|
59
|
+
child.presence = Presence.Present;
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
write(function () {
|
|
63
|
+
/**
|
|
64
|
+
* Starting these animations will have queued jobs on the frame loop. In some situations,
|
|
65
|
+
* like when removing an element, these will be processed too late after the DOM is manipulated,
|
|
66
|
+
* leaving a flash of incorrectly-projected content. By manually flushing these jobs
|
|
67
|
+
* we ensure there's no flash.
|
|
68
|
+
*/
|
|
69
|
+
flushSync.preRender();
|
|
70
|
+
flushSync.render();
|
|
71
|
+
});
|
|
72
|
+
read(function () {
|
|
73
|
+
/**
|
|
74
|
+
* Schedule a callback at the end of the following frame to assign the latest projection
|
|
75
|
+
* box to the prevViewportBox snapshot. Once global batching is in place this could be run
|
|
76
|
+
* synchronously. But for now it ensures that if any nested `AnimateSharedLayout` top-level
|
|
77
|
+
* child attempts to calculate its previous relative position against a prevViewportBox
|
|
78
|
+
* it will be against its latest projection box instead, as the snapshot is useless beyond this
|
|
79
|
+
* render.
|
|
80
|
+
*/
|
|
81
|
+
sync.postRender(function () {
|
|
82
|
+
return order.forEach(assignProjectionToSnapshot);
|
|
83
|
+
});
|
|
84
|
+
queue.clear();
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
// TODO: Need to find a layout-synchronous way of flushing this
|
|
88
|
+
flushLayout();
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function assignProjectionToSnapshot(child) {
|
|
93
|
+
child.prevViewportBox = child.projection.target;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export { createBatcher };
|