@humanspeak/svelte-motion 0.4.3 → 0.4.4
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/README.md +23 -0
- package/dist/components/variantContext.context.d.ts +20 -0
- package/dist/components/variantContext.context.js +25 -0
- package/dist/html/_MotionContainer.svelte +59 -6
- package/dist/types.d.ts +31 -1
- package/dist/utils/variants.d.ts +35 -41
- package/dist/utils/variants.js +42 -45
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -214,6 +214,29 @@ Supported drag props:
|
|
|
214
214
|
|
|
215
215
|
- String variant keys are resolved from `variants`.
|
|
216
216
|
- Variant state inherits through context.
|
|
217
|
+
- A variant entry can be a `(custom) => keyframes` factory. The `custom` prop is forwarded — useful for staggered lists where each child needs its own offset or delay. Children without `custom` inherit the nearest motion ancestor's value.
|
|
218
|
+
|
|
219
|
+
```svelte
|
|
220
|
+
<script lang="ts">
|
|
221
|
+
import { motion, type Variants } from '@humanspeak/svelte-motion'
|
|
222
|
+
|
|
223
|
+
const variants: Variants = {
|
|
224
|
+
hidden: { opacity: 0, x: -100 },
|
|
225
|
+
visible: (i) => ({
|
|
226
|
+
opacity: 1,
|
|
227
|
+
x: 0,
|
|
228
|
+
transition: { delay: (i as number) * 0.1 }
|
|
229
|
+
})
|
|
230
|
+
}
|
|
231
|
+
const items = ['Alpha', 'Beta', 'Gamma', 'Delta']
|
|
232
|
+
</script>
|
|
233
|
+
|
|
234
|
+
{#each items as item, i}
|
|
235
|
+
<motion.li custom={i} {variants} initial="hidden" animate="visible">
|
|
236
|
+
{item}
|
|
237
|
+
</motion.li>
|
|
238
|
+
{/each}
|
|
239
|
+
```
|
|
217
240
|
|
|
218
241
|
## Layout animation
|
|
219
242
|
|
|
@@ -25,3 +25,23 @@ export declare const setInitialFalseContext: (value: boolean) => void;
|
|
|
25
25
|
* @returns `true` if a parent set `initial={false}`, otherwise `false`.
|
|
26
26
|
*/
|
|
27
27
|
export declare const getInitialFalseContext: () => boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Provide a writable store carrying the current motion component's
|
|
30
|
+
* `custom` value so descendant motion components without their own
|
|
31
|
+
* `custom` prop can inherit it — and re-resolve their variants when the
|
|
32
|
+
* parent's `custom` changes.
|
|
33
|
+
*
|
|
34
|
+
* Mirrors framer-motion's variant-tree custom propagation. A store
|
|
35
|
+
* (rather than a snapshot) lets descendants react to changes the parent
|
|
36
|
+
* makes after mount.
|
|
37
|
+
*
|
|
38
|
+
* @param store Writable store holding the current component's effective `custom`.
|
|
39
|
+
*/
|
|
40
|
+
export declare const setCustomContext: (store: Writable<unknown>) => void;
|
|
41
|
+
/**
|
|
42
|
+
* Read the nearest ancestor's `custom` store (if any).
|
|
43
|
+
*
|
|
44
|
+
* @returns The ancestor's writable store, or `undefined` when no motion
|
|
45
|
+
* ancestor has set one.
|
|
46
|
+
*/
|
|
47
|
+
export declare const getCustomContext: () => Writable<unknown> | undefined;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getContext, setContext } from 'svelte';
|
|
2
2
|
const VARIANT_CONTEXT_KEY = Symbol('variant-context');
|
|
3
3
|
const INITIAL_FALSE_CONTEXT_KEY = Symbol('initial-false-context');
|
|
4
|
+
const CUSTOM_CONTEXT_KEY = Symbol('custom-context');
|
|
4
5
|
/**
|
|
5
6
|
* Provide a writable store for the current variant key so children can
|
|
6
7
|
* react to changes over time (true inheritance like Framer Motion).
|
|
@@ -35,3 +36,27 @@ export const setInitialFalseContext = (value) => {
|
|
|
35
36
|
export const getInitialFalseContext = () => {
|
|
36
37
|
return getContext(INITIAL_FALSE_CONTEXT_KEY) ?? false;
|
|
37
38
|
};
|
|
39
|
+
/**
|
|
40
|
+
* Provide a writable store carrying the current motion component's
|
|
41
|
+
* `custom` value so descendant motion components without their own
|
|
42
|
+
* `custom` prop can inherit it — and re-resolve their variants when the
|
|
43
|
+
* parent's `custom` changes.
|
|
44
|
+
*
|
|
45
|
+
* Mirrors framer-motion's variant-tree custom propagation. A store
|
|
46
|
+
* (rather than a snapshot) lets descendants react to changes the parent
|
|
47
|
+
* makes after mount.
|
|
48
|
+
*
|
|
49
|
+
* @param store Writable store holding the current component's effective `custom`.
|
|
50
|
+
*/
|
|
51
|
+
export const setCustomContext = (store) => {
|
|
52
|
+
setContext(CUSTOM_CONTEXT_KEY, store);
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Read the nearest ancestor's `custom` store (if any).
|
|
56
|
+
*
|
|
57
|
+
* @returns The ancestor's writable store, or `undefined` when no motion
|
|
58
|
+
* ancestor has set one.
|
|
59
|
+
*/
|
|
60
|
+
export const getCustomContext = () => {
|
|
61
|
+
return getContext(CUSTOM_CONTEXT_KEY);
|
|
62
|
+
};
|
|
@@ -53,7 +53,9 @@
|
|
|
53
53
|
setVariantContext,
|
|
54
54
|
getVariantContext,
|
|
55
55
|
setInitialFalseContext,
|
|
56
|
-
getInitialFalseContext
|
|
56
|
+
getInitialFalseContext,
|
|
57
|
+
setCustomContext,
|
|
58
|
+
getCustomContext
|
|
57
59
|
} from '../components/variantContext.context'
|
|
58
60
|
import { get, writable } from 'svelte/store'
|
|
59
61
|
import {
|
|
@@ -75,6 +77,7 @@
|
|
|
75
77
|
tag = 'div',
|
|
76
78
|
key: keyProp,
|
|
77
79
|
variants: variantsProp,
|
|
80
|
+
custom: customProp,
|
|
78
81
|
initial: initialProp,
|
|
79
82
|
animate: animateProp,
|
|
80
83
|
exit: exitProp,
|
|
@@ -360,6 +363,32 @@
|
|
|
360
363
|
// Provide context immediately during initialization so children can inherit
|
|
361
364
|
setVariantContext(localVariantStore)
|
|
362
365
|
|
|
366
|
+
// Custom-value inheritance. Children with no `custom` prop adopt the
|
|
367
|
+
// nearest motion ancestor's value. Reactive via a writable store so a
|
|
368
|
+
// parent updating `custom` re-fires descendants' variant resolution.
|
|
369
|
+
const parentCustomStore = getCustomContext()
|
|
370
|
+
let inheritedCustom: unknown = undefined
|
|
371
|
+
if (parentCustomStore) {
|
|
372
|
+
parentCustomStore.subscribe((v) => (inheritedCustom = v))()
|
|
373
|
+
}
|
|
374
|
+
const initialCustomValue = customProp !== undefined ? customProp : inheritedCustom
|
|
375
|
+
const localCustomStore = writable<unknown>(initialCustomValue)
|
|
376
|
+
setCustomContext(localCustomStore)
|
|
377
|
+
|
|
378
|
+
let parentInheritedCustom = $state<unknown>(inheritedCustom)
|
|
379
|
+
$effect(() => {
|
|
380
|
+
if (!parentCustomStore) {
|
|
381
|
+
parentInheritedCustom = undefined
|
|
382
|
+
return
|
|
383
|
+
}
|
|
384
|
+
const unsubscribe = parentCustomStore.subscribe((v) => (parentInheritedCustom = v))
|
|
385
|
+
return () => unsubscribe()
|
|
386
|
+
})
|
|
387
|
+
const effectiveCustom = $derived(customProp !== undefined ? customProp : parentInheritedCustom)
|
|
388
|
+
$effect(() => {
|
|
389
|
+
localCustomStore.set(effectiveCustom)
|
|
390
|
+
})
|
|
391
|
+
|
|
363
392
|
$effect(() => {
|
|
364
393
|
if (!variantsProp) return localVariantStore.set(undefined)
|
|
365
394
|
if (typeof animateProp === 'string') return localVariantStore.set(animateProp)
|
|
@@ -367,9 +396,13 @@
|
|
|
367
396
|
localVariantStore.set(undefined)
|
|
368
397
|
})
|
|
369
398
|
|
|
370
|
-
const resolvedInitial = $derived(
|
|
371
|
-
|
|
372
|
-
|
|
399
|
+
const resolvedInitial = $derived(
|
|
400
|
+
resolveInitial(effectiveInitialProp, variantsProp, effectiveCustom)
|
|
401
|
+
)
|
|
402
|
+
const resolvedAnimate = $derived(
|
|
403
|
+
resolveAnimate(effectiveAnimate, variantsProp, effectiveCustom)
|
|
404
|
+
)
|
|
405
|
+
const resolvedExit = $derived(resolveExit(exitProp, variantsProp, effectiveCustom))
|
|
373
406
|
|
|
374
407
|
// Extract keyframes from resolved initial, handling initial={false}
|
|
375
408
|
const initialKeyframes = $derived(
|
|
@@ -639,6 +672,12 @@
|
|
|
639
672
|
|
|
640
673
|
// Track the last variant key we ran to avoid re-running on mount
|
|
641
674
|
let lastRanVariantKey = $state<string | undefined>(undefined)
|
|
675
|
+
// Companion to `lastRanVariantKey`: the JSON-serialized resolved
|
|
676
|
+
// keyframes for that variant. Lets us detect when a function-form
|
|
677
|
+
// variant produces new keyframes (because `custom` changed) while
|
|
678
|
+
// the variant key stayed the same — otherwise the animate effect
|
|
679
|
+
// would short-circuit and the element would never re-animate.
|
|
680
|
+
let lastRanResolvedJson = $state<string | undefined>(undefined)
|
|
642
681
|
let mountedWithInitialFalse = $state(false)
|
|
643
682
|
// Track if the initial->animate transition has already been triggered by main effect
|
|
644
683
|
let initialAnimationTriggered = $state(false)
|
|
@@ -916,8 +955,14 @@
|
|
|
916
955
|
return
|
|
917
956
|
}
|
|
918
957
|
if (typeof animateProp === 'string') {
|
|
919
|
-
|
|
958
|
+
// Compare BOTH the variant key and the resolved keyframes JSON.
|
|
959
|
+
// For static variants the JSON is constant per key; for
|
|
960
|
+
// function-form variants the JSON changes when `custom`
|
|
961
|
+
// changes, which we must treat as a new animation target.
|
|
962
|
+
const resolvedJson = resolvedAnimate ? JSON.stringify(resolvedAnimate) : undefined
|
|
963
|
+
if (lastRanVariantKey !== animateProp || lastRanResolvedJson !== resolvedJson) {
|
|
920
964
|
lastRanVariantKey = animateProp
|
|
965
|
+
lastRanResolvedJson = resolvedJson
|
|
921
966
|
runAnimation()
|
|
922
967
|
}
|
|
923
968
|
} else if (animateProp) {
|
|
@@ -956,8 +1001,10 @@
|
|
|
956
1001
|
mountedWithInitialFalse = false
|
|
957
1002
|
}
|
|
958
1003
|
if (typeof currentAnimateKey === 'string') {
|
|
959
|
-
|
|
1004
|
+
const resolvedJson = resolvedAnimate ? JSON.stringify(resolvedAnimate) : undefined
|
|
1005
|
+
if (lastRanVariantKey !== currentAnimateKey || lastRanResolvedJson !== resolvedJson) {
|
|
960
1006
|
lastRanVariantKey = currentAnimateKey
|
|
1007
|
+
lastRanResolvedJson = resolvedJson
|
|
961
1008
|
runAnimation()
|
|
962
1009
|
}
|
|
963
1010
|
} else {
|
|
@@ -989,6 +1036,9 @@
|
|
|
989
1036
|
mountedWithInitialFalse = true
|
|
990
1037
|
if (typeof currentAnimateKey === 'string') {
|
|
991
1038
|
lastRanVariantKey = currentAnimateKey
|
|
1039
|
+
lastRanResolvedJson = resolvedAnimate
|
|
1040
|
+
? JSON.stringify(resolvedAnimate)
|
|
1041
|
+
: undefined
|
|
992
1042
|
}
|
|
993
1043
|
dataPath = 5
|
|
994
1044
|
isLoaded = 'ready'
|
|
@@ -1081,6 +1131,9 @@
|
|
|
1081
1131
|
snapshot = transformSVGPathProperties(element!, snapshot)
|
|
1082
1132
|
animate(element!, snapshot as DOMKeyframesDefinition, { duration: 0 })
|
|
1083
1133
|
lastRanVariantKey = currentAnimateKey
|
|
1134
|
+
lastRanResolvedJson = resolvedAnimate
|
|
1135
|
+
? JSON.stringify(resolvedAnimate)
|
|
1136
|
+
: undefined
|
|
1084
1137
|
} else {
|
|
1085
1138
|
runAnimation()
|
|
1086
1139
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,32 @@
|
|
|
1
1
|
import type { AnimationOptions, DOMKeyframesDefinition } from 'motion';
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
+
/**
|
|
4
|
+
* A variant value: either a static keyframes object, or a factory function
|
|
5
|
+
* that receives the consumer-provided `custom` value and returns keyframes.
|
|
6
|
+
*
|
|
7
|
+
* Dynamic (function-form) variants let a single variants object emit
|
|
8
|
+
* per-instance keyframes — common for staggered lists where each child
|
|
9
|
+
* needs its own offset or delay.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```svelte
|
|
13
|
+
* <motion.div
|
|
14
|
+
* custom={index}
|
|
15
|
+
* variants={{
|
|
16
|
+
* visible: (i) => ({ opacity: 1, x: i * 50 }),
|
|
17
|
+
* hidden: { opacity: 0 }
|
|
18
|
+
* }}
|
|
19
|
+
* animate="visible"
|
|
20
|
+
* />
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export type Variant = DOMKeyframesDefinition | ((custom: unknown) => DOMKeyframesDefinition) | undefined;
|
|
3
24
|
/**
|
|
4
25
|
* Variants define named animation states that can be referenced by string keys.
|
|
5
26
|
*
|
|
27
|
+
* Each entry can be a static keyframes object or a `(custom) => keyframes`
|
|
28
|
+
* factory function (see {@link Variant}).
|
|
29
|
+
*
|
|
6
30
|
* @example
|
|
7
31
|
* ```svelte
|
|
8
32
|
* <script>
|
|
@@ -15,7 +39,7 @@ import type { Snippet } from 'svelte';
|
|
|
15
39
|
* <motion.div variants={variants} animate="open" />
|
|
16
40
|
* ```
|
|
17
41
|
*/
|
|
18
|
-
export type Variants = Record<string,
|
|
42
|
+
export type Variants = Record<string, Variant>;
|
|
19
43
|
/**
|
|
20
44
|
* Initial animation properties for a motion component.
|
|
21
45
|
*
|
|
@@ -245,6 +269,12 @@ export type MotionProps = {
|
|
|
245
269
|
key?: string;
|
|
246
270
|
/** Variants define named animation states */
|
|
247
271
|
variants?: Variants;
|
|
272
|
+
/**
|
|
273
|
+
* Value passed into function-form variants. Children without their own
|
|
274
|
+
* `custom` prop inherit this from the nearest motion ancestor — matching
|
|
275
|
+
* framer-motion's variant-tree custom propagation.
|
|
276
|
+
*/
|
|
277
|
+
custom?: unknown;
|
|
248
278
|
/** Initial state of the animation (object or variant key) */
|
|
249
279
|
initial?: MotionInitial;
|
|
250
280
|
/** Target state of the animation (object or variant key) */
|
package/dist/utils/variants.d.ts
CHANGED
|
@@ -3,80 +3,74 @@ import type { DOMKeyframesDefinition } from 'motion';
|
|
|
3
3
|
/**
|
|
4
4
|
* Resolves a variant key to its keyframes definition.
|
|
5
5
|
*
|
|
6
|
-
* Looks up
|
|
7
|
-
*
|
|
6
|
+
* Looks up `key` in `variants`. When the entry is a function (dynamic
|
|
7
|
+
* variant), it's invoked with `custom` to produce keyframes — matching
|
|
8
|
+
* framer-motion's per-instance variant pattern.
|
|
8
9
|
*
|
|
9
10
|
* @param variants - The variants object containing named animation states.
|
|
10
11
|
* @param key - The variant key to look up.
|
|
11
|
-
* @
|
|
12
|
+
* @param custom - Value forwarded to function-form variants. Pass-through
|
|
13
|
+
* `undefined` when no `custom` is in scope; the dynamic variant itself
|
|
14
|
+
* decides how to handle the absent input.
|
|
15
|
+
* @returns The keyframes definition for the variant, or `undefined` if the
|
|
16
|
+
* key is missing.
|
|
12
17
|
*
|
|
13
18
|
* @example
|
|
14
|
-
* ```
|
|
19
|
+
* ```ts
|
|
15
20
|
* const variants = {
|
|
16
|
-
* visible: {
|
|
17
|
-
* hidden:
|
|
21
|
+
* visible: (i: number) => ({ x: i * 50 }),
|
|
22
|
+
* hidden: { opacity: 0 }
|
|
18
23
|
* }
|
|
19
|
-
* resolveVariant(variants, 'visible') // {
|
|
20
|
-
* resolveVariant(variants, '
|
|
21
|
-
* resolveVariant(undefined, 'visible')
|
|
24
|
+
* resolveVariant(variants, 'visible', 3) // { x: 150 }
|
|
25
|
+
* resolveVariant(variants, 'hidden') // { opacity: 0 }
|
|
26
|
+
* resolveVariant(undefined, 'visible') // undefined
|
|
22
27
|
* ```
|
|
23
28
|
*/
|
|
24
|
-
export declare const resolveVariant: (variants: Variants | undefined, key: string | undefined) => DOMKeyframesDefinition | undefined;
|
|
29
|
+
export declare const resolveVariant: (variants: Variants | undefined, key: string | undefined, custom?: unknown) => DOMKeyframesDefinition | undefined;
|
|
25
30
|
/**
|
|
26
31
|
* Resolves the initial prop to keyframes, handling variant keys and `initial={false}`.
|
|
27
32
|
*
|
|
28
|
-
* When `initial` is a string, looks it up in the variants object
|
|
29
|
-
*
|
|
33
|
+
* When `initial` is a string, looks it up in the variants object (invoking
|
|
34
|
+
* dynamic variants with `custom`). When `initial={false}`, returns `false` to
|
|
35
|
+
* skip the initial animation. Otherwise returns the keyframes directly.
|
|
30
36
|
*
|
|
31
37
|
* @param initial - The initial prop value (keyframes, variant key, false, or undefined).
|
|
32
38
|
* @param variants - The variants object for resolving string keys.
|
|
39
|
+
* @param custom - Forwarded to function-form variants.
|
|
33
40
|
* @returns Keyframes definition, `false` to skip animation, or undefined.
|
|
34
41
|
*
|
|
35
42
|
* @example
|
|
36
|
-
* ```
|
|
37
|
-
* const variants = { hidden: {
|
|
38
|
-
* resolveInitial('hidden', variants)
|
|
39
|
-
* resolveInitial({ x: 0 }, variants)
|
|
40
|
-
* resolveInitial(false, variants)
|
|
41
|
-
* resolveInitial(undefined, variants)
|
|
43
|
+
* ```ts
|
|
44
|
+
* const variants = { hidden: (i: number) => ({ x: -i * 100 }) }
|
|
45
|
+
* resolveInitial('hidden', variants, 2) // { x: -200 }
|
|
46
|
+
* resolveInitial({ x: 0 }, variants) // { x: 0 }
|
|
47
|
+
* resolveInitial(false, variants) // false
|
|
48
|
+
* resolveInitial(undefined, variants) // undefined
|
|
42
49
|
* ```
|
|
43
50
|
*/
|
|
44
|
-
export declare const resolveInitial: (initial: MotionInitial, variants: Variants | undefined) => DOMKeyframesDefinition | false | undefined;
|
|
51
|
+
export declare const resolveInitial: (initial: MotionInitial, variants: Variants | undefined, custom?: unknown) => DOMKeyframesDefinition | false | undefined;
|
|
45
52
|
/**
|
|
46
53
|
* Resolves the animate prop to keyframes, handling variant keys.
|
|
47
54
|
*
|
|
48
|
-
* When `animate` is a string, looks it up in the variants object
|
|
49
|
-
* Otherwise returns the keyframes directly.
|
|
55
|
+
* When `animate` is a string, looks it up in the variants object (invoking
|
|
56
|
+
* dynamic variants with `custom`). Otherwise returns the keyframes directly.
|
|
50
57
|
*
|
|
51
58
|
* @param animate - The animate prop value (keyframes, variant key, or undefined).
|
|
52
59
|
* @param variants - The variants object for resolving string keys.
|
|
60
|
+
* @param custom - Forwarded to function-form variants.
|
|
53
61
|
* @returns Keyframes definition or undefined.
|
|
54
|
-
*
|
|
55
|
-
* @example
|
|
56
|
-
* ```typescript
|
|
57
|
-
* const variants = { visible: { opacity: 1 } }
|
|
58
|
-
* resolveAnimate('visible', variants) // { opacity: 1 }
|
|
59
|
-
* resolveAnimate({ scale: 1.2 }, variants) // { scale: 1.2 }
|
|
60
|
-
* resolveAnimate(undefined, variants) // undefined
|
|
61
|
-
* ```
|
|
62
62
|
*/
|
|
63
|
-
export declare const resolveAnimate: (animate: MotionAnimate, variants: Variants | undefined) => DOMKeyframesDefinition | undefined;
|
|
63
|
+
export declare const resolveAnimate: (animate: MotionAnimate, variants: Variants | undefined, custom?: unknown) => DOMKeyframesDefinition | undefined;
|
|
64
64
|
/**
|
|
65
65
|
* Resolves the exit prop to keyframes, handling variant keys.
|
|
66
66
|
*
|
|
67
|
-
* When `exit` is a string, looks it up in the variants object
|
|
68
|
-
* Otherwise returns the keyframes directly.
|
|
67
|
+
* When `exit` is a string, looks it up in the variants object (invoking
|
|
68
|
+
* dynamic variants with `custom`). Otherwise returns the keyframes directly.
|
|
69
|
+
* Used by AnimatePresence for exit animations.
|
|
69
70
|
*
|
|
70
71
|
* @param exit - The exit prop value (keyframes, variant key, or undefined).
|
|
71
72
|
* @param variants - The variants object for resolving string keys.
|
|
73
|
+
* @param custom - Forwarded to function-form variants.
|
|
72
74
|
* @returns Keyframes definition or undefined.
|
|
73
|
-
*
|
|
74
|
-
* @example
|
|
75
|
-
* ```typescript
|
|
76
|
-
* const variants = { hidden: { opacity: 0 } }
|
|
77
|
-
* resolveExit('hidden', variants) // { opacity: 0 }
|
|
78
|
-
* resolveExit({ y: -100 }, variants) // { y: -100 }
|
|
79
|
-
* resolveExit(undefined, variants) // undefined
|
|
80
|
-
* ```
|
|
81
75
|
*/
|
|
82
|
-
export declare const resolveExit: (exit: MotionExit, variants: Variants | undefined) => DOMKeyframesDefinition | undefined;
|
|
76
|
+
export declare const resolveExit: (exit: MotionExit, variants: Variants | undefined, custom?: unknown) => DOMKeyframesDefinition | undefined;
|
package/dist/utils/variants.js
CHANGED
|
@@ -1,104 +1,101 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Resolves a variant key to its keyframes definition.
|
|
3
3
|
*
|
|
4
|
-
* Looks up
|
|
5
|
-
*
|
|
4
|
+
* Looks up `key` in `variants`. When the entry is a function (dynamic
|
|
5
|
+
* variant), it's invoked with `custom` to produce keyframes — matching
|
|
6
|
+
* framer-motion's per-instance variant pattern.
|
|
6
7
|
*
|
|
7
8
|
* @param variants - The variants object containing named animation states.
|
|
8
9
|
* @param key - The variant key to look up.
|
|
9
|
-
* @
|
|
10
|
+
* @param custom - Value forwarded to function-form variants. Pass-through
|
|
11
|
+
* `undefined` when no `custom` is in scope; the dynamic variant itself
|
|
12
|
+
* decides how to handle the absent input.
|
|
13
|
+
* @returns The keyframes definition for the variant, or `undefined` if the
|
|
14
|
+
* key is missing.
|
|
10
15
|
*
|
|
11
16
|
* @example
|
|
12
|
-
* ```
|
|
17
|
+
* ```ts
|
|
13
18
|
* const variants = {
|
|
14
|
-
* visible: {
|
|
15
|
-
* hidden:
|
|
19
|
+
* visible: (i: number) => ({ x: i * 50 }),
|
|
20
|
+
* hidden: { opacity: 0 }
|
|
16
21
|
* }
|
|
17
|
-
* resolveVariant(variants, 'visible') // {
|
|
18
|
-
* resolveVariant(variants, '
|
|
19
|
-
* resolveVariant(undefined, 'visible')
|
|
22
|
+
* resolveVariant(variants, 'visible', 3) // { x: 150 }
|
|
23
|
+
* resolveVariant(variants, 'hidden') // { opacity: 0 }
|
|
24
|
+
* resolveVariant(undefined, 'visible') // undefined
|
|
20
25
|
* ```
|
|
21
26
|
*/
|
|
22
|
-
export const resolveVariant = (variants, key) => {
|
|
27
|
+
export const resolveVariant = (variants, key, custom) => {
|
|
23
28
|
if (!variants || !key)
|
|
24
29
|
return undefined;
|
|
25
|
-
|
|
30
|
+
const entry = variants[key];
|
|
31
|
+
if (typeof entry === 'function')
|
|
32
|
+
return entry(custom);
|
|
33
|
+
return entry;
|
|
26
34
|
};
|
|
27
35
|
/**
|
|
28
36
|
* Resolves the initial prop to keyframes, handling variant keys and `initial={false}`.
|
|
29
37
|
*
|
|
30
|
-
* When `initial` is a string, looks it up in the variants object
|
|
31
|
-
*
|
|
38
|
+
* When `initial` is a string, looks it up in the variants object (invoking
|
|
39
|
+
* dynamic variants with `custom`). When `initial={false}`, returns `false` to
|
|
40
|
+
* skip the initial animation. Otherwise returns the keyframes directly.
|
|
32
41
|
*
|
|
33
42
|
* @param initial - The initial prop value (keyframes, variant key, false, or undefined).
|
|
34
43
|
* @param variants - The variants object for resolving string keys.
|
|
44
|
+
* @param custom - Forwarded to function-form variants.
|
|
35
45
|
* @returns Keyframes definition, `false` to skip animation, or undefined.
|
|
36
46
|
*
|
|
37
47
|
* @example
|
|
38
|
-
* ```
|
|
39
|
-
* const variants = { hidden: {
|
|
40
|
-
* resolveInitial('hidden', variants)
|
|
41
|
-
* resolveInitial({ x: 0 }, variants)
|
|
42
|
-
* resolveInitial(false, variants)
|
|
43
|
-
* resolveInitial(undefined, variants)
|
|
48
|
+
* ```ts
|
|
49
|
+
* const variants = { hidden: (i: number) => ({ x: -i * 100 }) }
|
|
50
|
+
* resolveInitial('hidden', variants, 2) // { x: -200 }
|
|
51
|
+
* resolveInitial({ x: 0 }, variants) // { x: 0 }
|
|
52
|
+
* resolveInitial(false, variants) // false
|
|
53
|
+
* resolveInitial(undefined, variants) // undefined
|
|
44
54
|
* ```
|
|
45
55
|
*/
|
|
46
|
-
export const resolveInitial = (initial, variants) => {
|
|
56
|
+
export const resolveInitial = (initial, variants, custom) => {
|
|
47
57
|
if (initial === false)
|
|
48
58
|
return false;
|
|
49
59
|
if (initial === undefined)
|
|
50
60
|
return undefined;
|
|
51
61
|
if (typeof initial === 'string')
|
|
52
|
-
return resolveVariant(variants, initial);
|
|
62
|
+
return resolveVariant(variants, initial, custom);
|
|
53
63
|
return initial;
|
|
54
64
|
};
|
|
55
65
|
/**
|
|
56
66
|
* Resolves the animate prop to keyframes, handling variant keys.
|
|
57
67
|
*
|
|
58
|
-
* When `animate` is a string, looks it up in the variants object
|
|
59
|
-
* Otherwise returns the keyframes directly.
|
|
68
|
+
* When `animate` is a string, looks it up in the variants object (invoking
|
|
69
|
+
* dynamic variants with `custom`). Otherwise returns the keyframes directly.
|
|
60
70
|
*
|
|
61
71
|
* @param animate - The animate prop value (keyframes, variant key, or undefined).
|
|
62
72
|
* @param variants - The variants object for resolving string keys.
|
|
73
|
+
* @param custom - Forwarded to function-form variants.
|
|
63
74
|
* @returns Keyframes definition or undefined.
|
|
64
|
-
*
|
|
65
|
-
* @example
|
|
66
|
-
* ```typescript
|
|
67
|
-
* const variants = { visible: { opacity: 1 } }
|
|
68
|
-
* resolveAnimate('visible', variants) // { opacity: 1 }
|
|
69
|
-
* resolveAnimate({ scale: 1.2 }, variants) // { scale: 1.2 }
|
|
70
|
-
* resolveAnimate(undefined, variants) // undefined
|
|
71
|
-
* ```
|
|
72
75
|
*/
|
|
73
|
-
export const resolveAnimate = (animate, variants) => {
|
|
76
|
+
export const resolveAnimate = (animate, variants, custom) => {
|
|
74
77
|
if (animate === undefined)
|
|
75
78
|
return undefined;
|
|
76
79
|
if (typeof animate === 'string')
|
|
77
|
-
return resolveVariant(variants, animate);
|
|
80
|
+
return resolveVariant(variants, animate, custom);
|
|
78
81
|
return animate;
|
|
79
82
|
};
|
|
80
83
|
/**
|
|
81
84
|
* Resolves the exit prop to keyframes, handling variant keys.
|
|
82
85
|
*
|
|
83
|
-
* When `exit` is a string, looks it up in the variants object
|
|
84
|
-
* Otherwise returns the keyframes directly.
|
|
86
|
+
* When `exit` is a string, looks it up in the variants object (invoking
|
|
87
|
+
* dynamic variants with `custom`). Otherwise returns the keyframes directly.
|
|
88
|
+
* Used by AnimatePresence for exit animations.
|
|
85
89
|
*
|
|
86
90
|
* @param exit - The exit prop value (keyframes, variant key, or undefined).
|
|
87
91
|
* @param variants - The variants object for resolving string keys.
|
|
92
|
+
* @param custom - Forwarded to function-form variants.
|
|
88
93
|
* @returns Keyframes definition or undefined.
|
|
89
|
-
*
|
|
90
|
-
* @example
|
|
91
|
-
* ```typescript
|
|
92
|
-
* const variants = { hidden: { opacity: 0 } }
|
|
93
|
-
* resolveExit('hidden', variants) // { opacity: 0 }
|
|
94
|
-
* resolveExit({ y: -100 }, variants) // { y: -100 }
|
|
95
|
-
* resolveExit(undefined, variants) // undefined
|
|
96
|
-
* ```
|
|
97
94
|
*/
|
|
98
|
-
export const resolveExit = (exit, variants) => {
|
|
95
|
+
export const resolveExit = (exit, variants, custom) => {
|
|
99
96
|
if (exit === undefined)
|
|
100
97
|
return undefined;
|
|
101
98
|
if (typeof exit === 'string')
|
|
102
|
-
return resolveVariant(variants, exit);
|
|
99
|
+
return resolveVariant(variants, exit, custom);
|
|
103
100
|
return exit;
|
|
104
101
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@humanspeak/svelte-motion",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"description": "Framer Motion for Svelte 5. Declarative motion.<tag> components with AnimatePresence exit animations, gestures (hover, tap, drag, focus, in-view), variants, FLIP layout animations, shared-layout transitions, spring physics, and scroll-linked motion values. The drop-in Framer Motion alternative for Svelte and SvelteKit.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"svelte",
|