Skip to content

Commit

Permalink
feat: 🎸 more rewrite work on hooks
Browse files Browse the repository at this point in the history
hooks rewriting

BREAKING CHANGE: 🧨 all

✅ Closes: none
  • Loading branch information
JonathonRP committed Nov 13, 2024
1 parent 49276d7 commit b8514ae
Show file tree
Hide file tree
Showing 26 changed files with 796 additions and 577 deletions.
93 changes: 50 additions & 43 deletions src/lib/motion-start/animation/hooks/UseAnimatedState.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<!-- based on [email protected],
Copyright (c) 2018 Framer B.V. -->

<script module lang="ts">
<script context="module" module lang="ts">
interface AnimatedStateOptions {
initialState: ResolvedValues
initialState: ResolvedValues;
}
const createObject = () => ({});
// const stateVisualElement = visualElement({
Expand All @@ -26,33 +26,37 @@ Copyright (c) 2018 Framer B.V. -->
// );
// },
// });
class StateVisualElement extends VisualElement<ResolvedValues, {}, AnimatedStateOptions> {
type: "state"
build() {}
measureInstanceViewportBox = createBox
resetTransform() {}
restoreTransform() {}
removeValueFromRenderState() {}
renderInstance() {}
scrapeMotionValuesFromProps() {
return createObject()
}
getBaseTargetFromProps() {
return undefined
}
class StateVisualElement extends VisualElement<
ResolvedValues,
{},
AnimatedStateOptions
> {
type: "state";
build() {}
measureInstanceViewportBox = createBox;
resetTransform() {}
restoreTransform() {}
removeValueFromRenderState() {}
renderInstance() {}
scrapeMotionValuesFromProps() {
return createObject();
}
getBaseTargetFromProps() {
return undefined;
}
readValueFromInstance(
readValueFromInstance(
_state: ResolvedValues,
key: string,
options: AnimatedStateOptions
) {
return options.initialState[key] || 0
}
options: AnimatedStateOptions,
) {
return options.initialState[key] || 0;
}
sortInstanceNodePosition() {
return 0
sortInstanceNodePosition() {
return 0;
}
}
}
</script>

<script lang="ts">
Expand All @@ -61,54 +65,57 @@ class StateVisualElement extends VisualElement<ResolvedValues, {}, AnimatedState
import { afterUpdate, getContext, onMount } from "svelte";
import { ScaleCorrectionParentContext } from "../../context/ScaleCorrectionProvider.svelte";
import { UseVisualState } from "../../motion/utils/use-visual-state.js";
import { visualElement } from "../../render/index.js";
// import { type AnimationDefinition } from "../../render/utils/animation";
// import { checkTargetForNewValues, getOrigin } from "../../render/utils/setters.js";
import type { ResolvedValues, VisualElementOptions } from "../../render/types";
import type {
ResolvedValues,
VisualElementOptions,
} from "../../render/types";
import { createBox } from "../../projection/geometry/models";
import { VisualElement } from "../../render/VisualElement";
import { animateVisualElement } from "../interfaces/visual-element";
export let initialState: VisualElementOptions<any, any>;
let animationState = initialState;
// @ts-expect-error
$:( element = new StateVisualElement({
props: {
onUpdate: (v) => {
$: element = new StateVisualElement(
{
props: {
onUpdate: (v) => {
// @ts-expect-error
animationState = { ...v };
},
},
// @ts-expect-error
visualState: state,
presenceContext: null,
},
visualState,
presenceContext: null,
}, { initialState }));
onMount(() => {
// @ts-expect-error
{ initialState },
);
onMount(() => {
element.mount({});
// @ts-expect-error
return () => element.unmount();
});
const _afterUpdate = () => {
// @ts-expect-error
element.setProps({
onUpdate: (v: VisualElementOptions<any, any>) => (animationState = { ...v }),
onUpdate: (v: VisualElementOptions<any, any>) =>
(animationState = { ...v }),
});
};
afterUpdate(_afterUpdate);
const scaleCorrectionParentContext = getContext<Writable<Array<unknown>>>(
ScaleCorrectionParentContext
ScaleCorrectionParentContext,
);
scaleCorrectionParentContext.update((v) =>
v.concat([
{
afterU: _afterUpdate,
},
])
]),
);
let startAnimation = (animationDefinition: TargetAndTransition) => {
// @ts-expect-error
return animateVisualElement(element, animationDefinition);
};
</script>
Expand All @@ -120,7 +127,7 @@ class StateVisualElement extends VisualElement<ResolvedValues, {}, AnimatedState
}}
props={{}}
isStatic={false}
let:state={visualState}
let:state
>
<slot {...[animationState, startAnimation]} />
</UseVisualState>
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!-- based on [email protected],
Copyright (c) 2018 Framer B.V. -->

<script context="module" lang="ts">
<script context="module" module lang="ts">
let presenceId = 0;
function getPresenceId() {
const id = presenceId;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<script module lang="ts" context="module">
<script lang="ts" context="module" module>
import { getContext, setContext } from "svelte";
import { writable } from "svelte/store";
import { getDomContext, setDomContext } from "./DOMcontext.js";
Expand Down
15 changes: 10 additions & 5 deletions src/lib/motion-start/gestures/UseHoverGesture.svelte
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
<!-- based on [email protected],
Copyright (c) 2018 Framer B.V. -->

<script lang="ts" context="module">
<script lang="ts" context="module" module>
import { isDragActive } from "./drag/utils/lock.js";
function createHoverEvent(visualElement:VisualElement, isActive:boolean, callback:any) {
return (event?: any | MouseEvent | TouchEvent | PointerEvent, info?: any) => {
function createHoverEvent(
visualElement: VisualElement,
isActive: boolean,
callback: any,
) {
return (
event?: any | MouseEvent | TouchEvent | PointerEvent,
info?: any,
) => {
if (!isMouseEvent(event) || isDragActive()) return;
callback?.(event, info);
visualElement.animationState?.setActive(AnimationType.Hover, isActive);
};
}
</script>

<script lang="ts">
Expand All @@ -23,7 +29,6 @@ Copyright (c) 2018 Framer B.V. -->
export let props, visualElement;
let { onHoverStart, onHoverEnd, whileHover } = props;
$: ({ onHoverStart, onHoverEnd, whileHover } = props);
</script>

<UsePointerEvent
Expand Down
2 changes: 1 addition & 1 deletion src/lib/motion-start/gestures/drag/UseDragControls.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!-- based on [email protected],
Copyright (c) 2018 Framer B.V. -->

<script module lang="ts">
<script context="module" module lang="ts">
import { DragControls } from "./use-drag-controls";
const createDragControls = () => new DragControls();
</script>
Expand Down
2 changes: 1 addition & 1 deletion src/lib/motion-start/motion/features/layout/Animate.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!-- based on [email protected],
Copyright (c) 2018 Framer B.V. -->

<script lang="ts" context="module">
<script lang="ts" context="module" module>
const progressTarget = 1000;
function hasMoved(a: AxisBox2D, b: AxisBox2D) {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/motion-start/motion/utils/UseVisualElement.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!-- based on [email protected],
Copyright (c) 2018 Framer B.V. -->

<script lang="ts" context="module">
<script lang="ts" context="module" module>
export const ssr = false;
function createProjectionNode(
Expand Down
8 changes: 7 additions & 1 deletion src/lib/motion-start/render/VisualElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import { complex } from '../value/types/complex';
import { getAnimatableNone } from './dom/value-types/animatable-none';
import { createBox } from '../projection/geometry/models';
import { time } from '../frameloop/sync-time';
import type { Booleanish } from 'svelte/elements';
import type { Snippet } from 'svelte';

const propEventHandlers = [
'AnimationStart',
Expand Down Expand Up @@ -82,7 +84,11 @@ export abstract class VisualElement<Instance = unknown, RenderState = unknown, O
* Often this have been specified via the initial prop but it might be
* that the value needs to be read from the Instance.
*/
abstract readValueFromInstance(instance: Instance, key: string, options: Options): string | number | null | undefined;
abstract readValueFromInstance(
instance: Instance,
key: string,
options: Options
): string | number | Booleanish | null | undefined | Snippet<any>;

/**
* When a value has been removed from the VisualElement we use this to remove
Expand Down
2 changes: 1 addition & 1 deletion src/lib/motion-start/render/html/UseStyle.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!-- based on [email protected],
Copyright (c) 2018 Framer B.V. -->

<script lang="ts" context="module">
<script lang="ts" context="module" module>
import type { MotionProps } from "../../motion/types.js";
import type { ResolvedValues } from "../types.js";
import { copyRawValuesOnly } from "./use-props.js";
Expand Down
10 changes: 8 additions & 2 deletions src/lib/motion-start/utils/UseMotionValueEvent.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,21 @@ Copyright (c) 2018 Framer B.V. -->
event: EventName,
callback: MotionValueEventCallbacks<V>[EventName];
const memo = (
_value?: typeof value | undefined,
_event?: typeof event | undefined,
_callback?: typeof callback | undefined,
) => value.on(event, callback);
/**
* useInsertionEffect will create subscriptions before any other
* effects will run. Effects run upwards through the tree so it
* can be that binding a useLayoutEffect higher up the tree can
* miss changes from lower down the tree.
*/
beforeUpdate(() => value.on(event, callback));
beforeUpdate(() => memo());
$: value.on(event, callback);
$: memo(value, event, callback);
</script>

<slot />
24 changes: 15 additions & 9 deletions src/lib/motion-start/utils/use-animation-frame.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
// TODO: update
/**
based on [email protected],
Copyright (c) 2018 Framer B.V.
*/

import { frame, cancelFrame } from '../frameloop';
import { useContext, useEffect, useRef } from 'react';
import { MotionConfigContext } from '../context/MotionConfigContext';
import type { FrameData } from '../frameloop/types';
import { getContext, tick } from 'svelte';
import { get, type Writable } from 'svelte/store';

export type FrameCallback = (timestamp: number, delta: number) => void;

export function useAnimationFrame(callback: FrameCallback) {
const initialTimestamp = useRef(0);
const { isStatic } = useContext(MotionConfigContext);
export function useAnimationFrame(callback: FrameCallback, isCustom = false) {
let initialTimestamp = 0;
const { isStatic } = get(
getContext<Writable<MotionConfigContext>>(MotionConfigContext) || MotionConfigContext(isCustom)
);

useEffect(() => {
tick().then(() => {
if (isStatic) return;

const provideTimeSinceStart = ({ timestamp, delta }: FrameData) => {
if (!initialTimestamp.current) initialTimestamp.current = timestamp;
if (!initialTimestamp) initialTimestamp = timestamp;

callback(timestamp - initialTimestamp.current, delta);
callback(timestamp - initialTimestamp, delta);
};

frame.update(provideTimeSinceStart, true);
return () => cancelFrame(provideTimeSinceStart);
}, [callback]);
});
}
Loading

0 comments on commit b8514ae

Please sign in to comment.