solidjs-motion 0.1.0
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/CHANGELOG.md +117 -0
- package/LICENSE +21 -0
- package/README.md +140 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2627 -0
- package/dist/index.js.map +1 -0
- package/dist/src/default-values.d.ts +6 -0
- package/dist/src/index.d.ts +16 -0
- package/dist/src/motion-config.d.ts +14 -0
- package/dist/src/motion-proxy.d.ts +103 -0
- package/dist/src/presence-context.d.ts +4 -0
- package/dist/src/presence.d.ts +95 -0
- package/dist/src/primitives/createDrag.d.ts +16 -0
- package/dist/src/primitives/createDragControls.d.ts +30 -0
- package/dist/src/primitives/createGestures.d.ts +8 -0
- package/dist/src/primitives/createInView.d.ts +51 -0
- package/dist/src/primitives/createMotion.d.ts +82 -0
- package/dist/src/primitives/createPan.d.ts +83 -0
- package/dist/src/primitives/createScroll.d.ts +40 -0
- package/dist/src/primitives/gesture-state.d.ts +108 -0
- package/dist/src/primitives/motion-value.d.ts +111 -0
- package/dist/src/primitives/value-registry.d.ts +34 -0
- package/dist/src/reduced-motion.d.ts +29 -0
- package/dist/src/style.d.ts +79 -0
- package/dist/src/types.d.ts +374 -0
- package/dist/src/use-motion.d.ts +35 -0
- package/dist/src/variants.d.ts +64 -0
- package/package.json +78 -0
- package/src/default-values.ts +52 -0
- package/src/index.ts +60 -0
- package/src/motion-config.tsx +37 -0
- package/src/motion-proxy.tsx +377 -0
- package/src/presence-context.ts +32 -0
- package/src/presence.tsx +466 -0
- package/src/primitives/createDrag.ts +670 -0
- package/src/primitives/createDragControls.ts +101 -0
- package/src/primitives/createGestures.ts +145 -0
- package/src/primitives/createInView.ts +124 -0
- package/src/primitives/createMotion.ts +638 -0
- package/src/primitives/createPan.ts +338 -0
- package/src/primitives/createScroll.ts +101 -0
- package/src/primitives/gesture-state.ts +772 -0
- package/src/primitives/motion-value.ts +328 -0
- package/src/primitives/value-registry.ts +114 -0
- package/src/reduced-motion.ts +51 -0
- package/src/style.ts +266 -0
- package/src/types.ts +538 -0
- package/src/use-motion.tsx +412 -0
- package/src/variants.ts +134 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Look up the canonical fallback value for a property key. Returns the table
|
|
3
|
+
* value if known, else `null` — which motion's `animate()` interprets as
|
|
4
|
+
* "read from computed style at animation start."
|
|
5
|
+
*/
|
|
6
|
+
export declare function getMotionDefault(key: string): number | null;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { animate, inView, isMotionValue, motionValue, scroll, spring } from 'motion';
|
|
2
|
+
export { MotionConfig, MotionConfigContext, useMotionConfig } from './motion-config';
|
|
3
|
+
export { MOTION_OPT_KEYS, type Motion, motion } from './motion-proxy';
|
|
4
|
+
export { Presence, type PresenceProps, type UseAnimatePresenceOptions, type UseAnimatePresenceResult, useAnimatePresence, } from './presence';
|
|
5
|
+
export { PresenceContext, usePresenceContext } from './presence-context';
|
|
6
|
+
export { createDragControls } from './primitives/createDragControls';
|
|
7
|
+
export { type CreateInViewOptions, type CreateInViewResult, createInView, } from './primitives/createInView';
|
|
8
|
+
export { createMotion } from './primitives/createMotion';
|
|
9
|
+
export { type CreatePanOptions, type CreatePanResult, createPan, type PanAxisPair, } from './primitives/createPan';
|
|
10
|
+
export { type CreateScrollOptions, type CreateScrollResult, createScroll, } from './primitives/createScroll';
|
|
11
|
+
export { createMotionValue, createMotionValueEvent, createSpring, createTemplate, createTime, createTransform, createVelocity, toSignal, } from './primitives/motion-value';
|
|
12
|
+
export { createReducedMotion, shouldReduceMotion } from './reduced-motion';
|
|
13
|
+
export { targetToStyle } from './style';
|
|
14
|
+
export type * from './types';
|
|
15
|
+
export { useMotion } from './use-motion';
|
|
16
|
+
export { effectiveLabels, resolveVariant, useVariantContext, VariantContext } from './variants';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Context, JSX } from 'solid-js';
|
|
2
|
+
import { MotionConfigContextValue, MotionConfigProps } from './types';
|
|
3
|
+
export declare const MotionConfigContext: Context<MotionConfigContextValue>;
|
|
4
|
+
export declare function useMotionConfig(): MotionConfigContextValue;
|
|
5
|
+
/**
|
|
6
|
+
* Provider that flows reduced-motion mode, default transition, and CSP nonce
|
|
7
|
+
* to every descendant motion element.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* <MotionConfig reducedMotion="user" transition={{ duration: 0.4 }}>
|
|
11
|
+
* <App />
|
|
12
|
+
* </MotionConfig>
|
|
13
|
+
*/
|
|
14
|
+
export declare function MotionConfig(props: MotionConfigProps): JSX.Element;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Component, JSX } from 'solid-js';
|
|
2
|
+
import { MotionOptions, MotionStyle } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* The exhaustive list of keys that `motion.X` (and `motion.create`,
|
|
5
|
+
* landing next) route to `useMotion` rather than the underlying element.
|
|
6
|
+
* Anything not in this array falls through to `rest` and is spread onto
|
|
7
|
+
* the DOM element via Solid's reactive spread — keeping things like
|
|
8
|
+
* `class`, `onClick`, dynamic style, etc. reactive end-to-end.
|
|
9
|
+
*
|
|
10
|
+
* The `satisfies` clause ensures every entry IS a valid `MotionOptions`
|
|
11
|
+
* key (typos fail to compile). The `_ensureExhaustive` constant below
|
|
12
|
+
* asserts the converse — every `MotionOptions` key appears in this
|
|
13
|
+
* array — so adding a new option to types.ts without registering here
|
|
14
|
+
* fails to compile with the missing key surfaced in the error.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Union of every `MotionOptions` key the proxy splits off from element
|
|
18
|
+
* attributes. Hardcoded as a literal union — NOT derived from
|
|
19
|
+
* `typeof MOTION_OPT_KEYS[number]` — so JSR's "slow types" rule can
|
|
20
|
+
* resolve the public type without inferring it from a const.
|
|
21
|
+
*
|
|
22
|
+
* Two compile-time exhaustiveness directions guarantee consistency
|
|
23
|
+
* between this type and the runtime `MOTION_OPT_KEYS` array:
|
|
24
|
+
*
|
|
25
|
+
* 1. `_MissingMotionOptKeys` (below) verifies the union covers every
|
|
26
|
+
* key in `keyof MotionOptions`.
|
|
27
|
+
* 2. The `satisfies` clause on `MOTION_OPT_KEYS` verifies every array
|
|
28
|
+
* entry IS a `MotionOptKey` (typo-proof at the runtime layer).
|
|
29
|
+
*
|
|
30
|
+
* If `MotionOptions` grows a new key, both `_MissingMotionOptKeys`
|
|
31
|
+
* AND `splitProps` at runtime break — the type check surfaces the
|
|
32
|
+
* specific missing key by name.
|
|
33
|
+
*/
|
|
34
|
+
export type MotionOptKey = "initial" | "animate" | "exit" | "hover" | "press" | "focus" | "inView" | "inViewOptions" | "drag" | "dragConstraints" | "dragElastic" | "dragMomentum" | "dragTransition" | "dragSnapToOrigin" | "dragControls" | "whileDrag" | "panThreshold" | "variants" | "custom" | "transition" | "onAnimationStart" | "onAnimationComplete" | "onAnimationCancel" | "onUpdate" | "onHoverStart" | "onHoverEnd" | "onPressStart" | "onPress" | "onPressCancel" | "onFocus" | "onBlur" | "onPanStart" | "onPan" | "onPanEnd" | "onViewportEnter" | "onViewportLeave" | "onDragStart" | "onDrag" | "onDragEnd" | "onDragTransitionEnd";
|
|
35
|
+
/**
|
|
36
|
+
* Frozen list of `MotionOptKey`s — fed to `splitProps` at every
|
|
37
|
+
* tag-component render to separate motion options from element
|
|
38
|
+
* attributes. The `satisfies` clause checks every entry against
|
|
39
|
+
* `MotionOptKey` at compile time so typos / drift between the union
|
|
40
|
+
* and the array surface as errors.
|
|
41
|
+
*/
|
|
42
|
+
export declare const MOTION_OPT_KEYS: readonly MotionOptKey[];
|
|
43
|
+
/**
|
|
44
|
+
* The shape of the `motion` proxy: every HTML/SVG intrinsic element name
|
|
45
|
+
* maps to a typed `Component` whose props are that element's native
|
|
46
|
+
* attribute set intersected with {@link MotionOptions}.
|
|
47
|
+
*
|
|
48
|
+
* The intersected `{ create: ... }` member adds the HOC entry point. The
|
|
49
|
+
* intersection's explicit `create` field wins over the mapped type's
|
|
50
|
+
* lookup (and there's no HTML/SVG tag named `create`), so `motion.create`
|
|
51
|
+
* is unambiguously typed as the HOC.
|
|
52
|
+
*/
|
|
53
|
+
export type Motion = {
|
|
54
|
+
[Tag in keyof JSX.IntrinsicElements]: Component<Omit<JSX.IntrinsicElements[Tag], "style"> & {
|
|
55
|
+
style?: MotionStyle;
|
|
56
|
+
} & MotionOptions>;
|
|
57
|
+
} & {
|
|
58
|
+
/**
|
|
59
|
+
* Wrap a custom Component with motion's behavior. The wrapped Component
|
|
60
|
+
* must forward props (specifically `ref` and `style`) to a single DOM
|
|
61
|
+
* element root — either by spreading `{...props}` on its root or by
|
|
62
|
+
* explicitly setting `ref={props.ref}` and `style={props.style}`. Solid
|
|
63
|
+
* doesn't have `forwardRef`; the contract is enforced by convention and
|
|
64
|
+
* a dev-mode runtime warning if motion's ref never reaches the DOM.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```tsx
|
|
68
|
+
* function MyCard(props) {
|
|
69
|
+
* return <div {...props}>{props.children}</div>
|
|
70
|
+
* }
|
|
71
|
+
* const Animated = motion.create(MyCard)
|
|
72
|
+
* <Animated animate={{ x: 100 }} hover={{ scale: 1.05 }} class="card" />
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
create: <P extends Record<string, any>>(Component: Component<P>) => Component<P & MotionOptions>;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* `motion` — the indexable proxy. Every property access returns a cached
|
|
79
|
+
* motion-aware component for the given HTML/SVG tag. The reserved
|
|
80
|
+
* `motion.create` key returns the HOC entry point.
|
|
81
|
+
*
|
|
82
|
+
* @example HTML element
|
|
83
|
+
* ```tsx
|
|
84
|
+
* <motion.div animate={{ x: 100 }} hover={{ scale: 1.05 }}>
|
|
85
|
+
* draggable card
|
|
86
|
+
* </motion.div>
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* @example SVG element (handled transparently via <Dynamic>)
|
|
90
|
+
* ```tsx
|
|
91
|
+
* <motion.path d="M0 0 L100 100" animate={{ pathLength: 1 }} />
|
|
92
|
+
* ```
|
|
93
|
+
*
|
|
94
|
+
* @example Wrapping a custom Component via the HOC
|
|
95
|
+
* ```tsx
|
|
96
|
+
* const Animated = motion.create(MyCard)
|
|
97
|
+
* <Animated animate={{ scale: 1.05 }} class="my-card" />
|
|
98
|
+
* ```
|
|
99
|
+
*
|
|
100
|
+
* Non-string keys (Symbols, well-known properties) return `undefined` so
|
|
101
|
+
* debugging tools and `typeof` checks see a sane shape.
|
|
102
|
+
*/
|
|
103
|
+
export declare const motion: Motion;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Component, JSX } from 'solid-js';
|
|
2
|
+
export type PresenceProps = {
|
|
3
|
+
/**
|
|
4
|
+
* Exit/enter coordination.
|
|
5
|
+
* - `"sync"` (default) — exit and enter overlap (transition-group's
|
|
6
|
+
* `parallel`). Best for list animations and independent items.
|
|
7
|
+
* - `"wait"` — old child fully exits before the new one enters
|
|
8
|
+
* (transition-group's `out-in`). Single-child only; ignored (with a
|
|
9
|
+
* dev-mode warning) when wrapping a list.
|
|
10
|
+
*/
|
|
11
|
+
mode?: "sync" | "wait";
|
|
12
|
+
/**
|
|
13
|
+
* Animate children on first mount. Defaults to `true` (matches motion-
|
|
14
|
+
* react). Set `false` to suppress the entry animation for the very first
|
|
15
|
+
* child(ren); subsequent mounts mid-life still animate.
|
|
16
|
+
*/
|
|
17
|
+
initial?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* List-path only — controls what transition-group does with an exiting
|
|
20
|
+
* element while its `exit` animation is playing. Forwarded directly to
|
|
21
|
+
* `@solid-primitives/transition-group`'s `createListTransition`.
|
|
22
|
+
*
|
|
23
|
+
* - `"move-to-end"` (default) — the exiting element is appended to the
|
|
24
|
+
* end of the rendered array so its DOM position changes during exit.
|
|
25
|
+
* Fine for grids/cascades; surprising for vertically-stacked toasts
|
|
26
|
+
* because surviving siblings JUMP up while the dismissed item is
|
|
27
|
+
* still fading out below them.
|
|
28
|
+
* - `"keep-index"` — the exiting element stays at its original index
|
|
29
|
+
* until exit completes. Surviving siblings don't reflow until the
|
|
30
|
+
* slot is released. Best default for notification stacks.
|
|
31
|
+
* - `"remove"` — no exit transition; the element is gone from the
|
|
32
|
+
* rendered array immediately. Useful when the exit is purely visual
|
|
33
|
+
* on the child (e.g., it self-animates via opacity transitions
|
|
34
|
+
* instead of `exit`).
|
|
35
|
+
*/
|
|
36
|
+
exitMethod?: "move-to-end" | "keep-index" | "remove";
|
|
37
|
+
children: JSX.Element;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Wraps a conditional or iterated JSX subtree and runs the descendants'
|
|
41
|
+
* `exit` targets before they unmount. Matches motion-react's
|
|
42
|
+
* `<AnimatePresence>` shape but with Solid's `<Show>` / `<For>` /
|
|
43
|
+
* `<Index>` patterns instead of conditional children.
|
|
44
|
+
*
|
|
45
|
+
* Nested motion children are first-class: when an ancestor unmounts,
|
|
46
|
+
* Presence walks the subtree from each resolved child and fires every
|
|
47
|
+
* registered `runExit` it finds in parallel — including motion children
|
|
48
|
+
* nested inside plain wrappers, or descendants whose `exit` label was
|
|
49
|
+
* cascaded down via `m.Provider`. Each motion descendant animates with
|
|
50
|
+
* its own variant/target; transition-group only releases the DOM once
|
|
51
|
+
* the combined `Promise.all` settles. Mirrors motion-react's behavior
|
|
52
|
+
* where a `<motion.div exit={...}>` inside an `<AnimatePresence>` boundary
|
|
53
|
+
* animates correctly regardless of depth.
|
|
54
|
+
*
|
|
55
|
+
* @example Single (conditional unmount)
|
|
56
|
+
* <Presence>
|
|
57
|
+
* <Show when={open()}>
|
|
58
|
+
* <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}>
|
|
59
|
+
* saved
|
|
60
|
+
* </motion.div>
|
|
61
|
+
* </Show>
|
|
62
|
+
* </Presence>
|
|
63
|
+
*
|
|
64
|
+
* @example List (items entering and exiting independently)
|
|
65
|
+
* <Presence>
|
|
66
|
+
* <For each={items()}>
|
|
67
|
+
* {(item) => (
|
|
68
|
+
* <motion.li exit={{ opacity: 0, x: 20 }}>{item.text}</motion.li>
|
|
69
|
+
* )}
|
|
70
|
+
* </For>
|
|
71
|
+
* </Presence>
|
|
72
|
+
*/
|
|
73
|
+
export declare const Presence: Component<PresenceProps>;
|
|
74
|
+
export type UseAnimatePresenceOptions = {
|
|
75
|
+
/** Same semantics as `<Presence initial>`. Defaults to `true`. */
|
|
76
|
+
initial?: boolean;
|
|
77
|
+
};
|
|
78
|
+
export type UseAnimatePresenceResult = {
|
|
79
|
+
/**
|
|
80
|
+
* Provider component to wrap your conditional rendering. Every motion
|
|
81
|
+
* descendant inside this Provider registers with the hook's internal
|
|
82
|
+
* registry and is reachable via `exit()`.
|
|
83
|
+
*/
|
|
84
|
+
Provider: Component<{
|
|
85
|
+
children: JSX.Element;
|
|
86
|
+
}>;
|
|
87
|
+
/**
|
|
88
|
+
* Trigger exit on every motion child currently registered with this
|
|
89
|
+
* hook. Resolves when all exit animations have settled. Calling `exit()`
|
|
90
|
+
* does NOT unmount anything — the caller is responsible for flipping
|
|
91
|
+
* their mount signal once the promise resolves.
|
|
92
|
+
*/
|
|
93
|
+
exit: () => Promise<void>;
|
|
94
|
+
};
|
|
95
|
+
export declare function useAnimatePresence(options?: UseAnimatePresenceOptions): UseAnimatePresenceResult;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { MotionOptions } from '../types';
|
|
2
|
+
import { SetActive } from './gesture-state';
|
|
3
|
+
/**
|
|
4
|
+
* Bind pointer-driven drag to an element. Layers on top of createPan for the
|
|
5
|
+
* pointer session; adds transform writes, body styles, pointer capture, and
|
|
6
|
+
* state-machine activation.
|
|
7
|
+
*
|
|
8
|
+
* Drag is enabled when `opts.drag` is truthy (`true`, `"x"`, or `"y"`).
|
|
9
|
+
* createDrag always wires the pointer session — the enable check is per-
|
|
10
|
+
* gesture-start, so toggling `opts.drag` on/off doesn't churn listeners.
|
|
11
|
+
*
|
|
12
|
+
* Phase 2 Commit 6 — Stage 2 scope: VE bootstrap, translation, axis lock,
|
|
13
|
+
* body/pointer styles, callbacks, cleanup. Constraints + elastic resistance
|
|
14
|
+
* land in Stage 3; momentum + dragSnapToOrigin in Stage 4.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createDrag(el: HTMLElement, getOpts: () => MotionOptions, setActive: SetActive): void;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { DragControls } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Symbol used to attach the registration method on the controls object.
|
|
4
|
+
* `createDrag` imports this symbol to find/register its handler. Userland
|
|
5
|
+
* code never touches it — exported only for library-internal use.
|
|
6
|
+
*/
|
|
7
|
+
export declare const DRAG_CONTROLS_REGISTER: unique symbol;
|
|
8
|
+
/**
|
|
9
|
+
* Create a controls instance for imperatively starting a drag on a motion
|
|
10
|
+
* element from a different element (e.g., a drag-handle button).
|
|
11
|
+
*
|
|
12
|
+
* Pattern (Q9):
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* function Card() {
|
|
16
|
+
* const controls = createDragControls()
|
|
17
|
+
* const m = useMotion({ drag: "y", dragControls: controls })
|
|
18
|
+
* return (
|
|
19
|
+
* <div {...m()}>
|
|
20
|
+
* <button onPointerDown={(e) => controls.start(e)}>handle</button>
|
|
21
|
+
* Card body
|
|
22
|
+
* </div>
|
|
23
|
+
* )
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* The handle's pointerdown fires `controls.start(event)`. createDrag is
|
|
27
|
+
* registered with the controls and translates the call into a pan-session
|
|
28
|
+
* synthesized from the handle's event, bypassing the threshold gate.
|
|
29
|
+
*/
|
|
30
|
+
export declare function createDragControls(): DragControls;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { MotionElement, MotionOptions } from '../types';
|
|
2
|
+
import { SetActive } from './gesture-state';
|
|
3
|
+
/**
|
|
4
|
+
* Bind pointer-event-driven gestures (hover, press) to the motion element.
|
|
5
|
+
* Toggles the state machine's `whileHover` / `whilePress` flags and forwards
|
|
6
|
+
* events to the user's `MotionCallbacks`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createGestures(el: MotionElement, getOpts: () => MotionOptions, setActive: SetActive): void;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Accessor } from 'solid-js';
|
|
2
|
+
import { ViewportOptions } from '../types';
|
|
3
|
+
export type CreateInViewOptions = ViewportOptions & {
|
|
4
|
+
/**
|
|
5
|
+
* Fires with the raw {@link IntersectionObserverEntry} on every
|
|
6
|
+
* visibility transition (enter AND leave). Convenience hook for callers
|
|
7
|
+
* who prefer event-driven access to the entry — the entry is also
|
|
8
|
+
* available reactively via the returned `view.entry()` accessor.
|
|
9
|
+
*/
|
|
10
|
+
onChange?: (entry: IntersectionObserverEntry) => void;
|
|
11
|
+
};
|
|
12
|
+
/** Returned by {@link createInView}. Two Solid Accessors — call them to track. */
|
|
13
|
+
export type CreateInViewResult = {
|
|
14
|
+
/** Solid Accessor; `true` while the element intersects the viewport per the configured threshold. */
|
|
15
|
+
isInView: Accessor<boolean>;
|
|
16
|
+
/** Solid Accessor; the most recent {@link IntersectionObserverEntry}, or `null` before any. */
|
|
17
|
+
entry: Accessor<IntersectionObserverEntry | null>;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Observe an element via {@link IntersectionObserver} and expose its
|
|
21
|
+
* in-view state as a pair of Solid Accessors.
|
|
22
|
+
*
|
|
23
|
+
* Pass a ref-style accessor that returns the element. The observer
|
|
24
|
+
* attaches once the accessor returns a non-null element and re-attaches
|
|
25
|
+
* if it changes. The observer is disconnected on owner disposal.
|
|
26
|
+
*
|
|
27
|
+
* Options can be a static object or a function form (matching `useMotion`
|
|
28
|
+
* and `createPan`'s convention). The function form is tracked inside the
|
|
29
|
+
* effect — option changes (e.g., switching `root`) re-attach the observer.
|
|
30
|
+
*
|
|
31
|
+
* @example Static options
|
|
32
|
+
* const [el, setEl] = createSignal<HTMLElement>()
|
|
33
|
+
* const view = createInView(el, { once: true })
|
|
34
|
+
* createEffect(() => {
|
|
35
|
+
* if (view.isInView()) console.log("now in view")
|
|
36
|
+
* })
|
|
37
|
+
*
|
|
38
|
+
* @example Function-form options (reactive)
|
|
39
|
+
* const [root, setRoot] = createSignal<HTMLElement>()
|
|
40
|
+
* const view = createInView(el, () => ({ root, margin: "100px" }))
|
|
41
|
+
*
|
|
42
|
+
* @example Reading the raw entry reactively
|
|
43
|
+
* const view = createInView(el)
|
|
44
|
+
* createEffect(() => {
|
|
45
|
+
* const e = view.entry()
|
|
46
|
+
* if (e) console.log("ratio:", e.intersectionRatio)
|
|
47
|
+
* })
|
|
48
|
+
*
|
|
49
|
+
* <div ref={setEl}>watch me</div>
|
|
50
|
+
*/
|
|
51
|
+
export declare function createInView(ref: () => Element | null | undefined, options?: CreateInViewOptions | (() => CreateInViewOptions)): CreateInViewResult;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { MotionValue } from 'motion';
|
|
2
|
+
import { AnimateValue, MotionElement, MotionOptions, Target, Transition, VariantContextValue, VariantLabels, Variants } from '../types';
|
|
3
|
+
import { ActiveStoreTuple } from './gesture-state';
|
|
4
|
+
/**
|
|
5
|
+
* Detect whether an animate-value is a variant name (string or string[]) vs.
|
|
6
|
+
* an explicit target object. Returns the labels or undefined.
|
|
7
|
+
*/
|
|
8
|
+
export declare function asVariantLabels(value: AnimateValue | undefined): VariantLabels | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Resolve a per-state animate value into a {@link Target}. Implements the
|
|
11
|
+
* Q4 sub-2 priority table:
|
|
12
|
+
*
|
|
13
|
+
* - explicit Target object → use as-is (parent context ignored)
|
|
14
|
+
* - variant name → look up in own variants only (no cascade)
|
|
15
|
+
* - undefined → fall back to parent context's variant name, then look up in
|
|
16
|
+
* own variants
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveTarget(ownValue: AnimateValue | undefined, ownVariants: Variants | undefined, parentLabel: VariantLabels | undefined, custom: unknown): Target | null;
|
|
19
|
+
/**
|
|
20
|
+
* Merge transition specs in priority order: MotionConfig default <
|
|
21
|
+
* user's `transition` < per-target `transition`. When reduced motion is
|
|
22
|
+
* active, returns `{ duration: 0 }` and drops everything else (Q11 sub-4).
|
|
23
|
+
*/
|
|
24
|
+
export declare function mergeTransition(configDefault: Transition | undefined, ownTransition: Transition | undefined, perTargetTransition: Transition | undefined, reduced: boolean): Transition;
|
|
25
|
+
/**
|
|
26
|
+
* Apply a static target to an element's inline style before paint. Used on
|
|
27
|
+
* mount when no SSR style was emitted. The ref callback fires before the
|
|
28
|
+
* browser yields, so this avoids a frame of flicker.
|
|
29
|
+
*/
|
|
30
|
+
declare function applyStaticStyle(el: MotionElement, target: Target): void;
|
|
31
|
+
export type CreateMotionConfig = {
|
|
32
|
+
/**
|
|
33
|
+
* When true, `createMotion` skips applying the initial style — the server
|
|
34
|
+
* already emitted it inline, and re-applying on hydration would shift the
|
|
35
|
+
* paint. Detected via the `data-motion-hydrated` marker in useMotion.
|
|
36
|
+
*/
|
|
37
|
+
initialAppliedBySSR?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Q4 — useMotion lifts the gesture-state active store one level up so its
|
|
40
|
+
* `myVariantCtx` can read the same flags it propagates to descendants.
|
|
41
|
+
* When omitted (standalone createMotion use), the state machine creates
|
|
42
|
+
* its own internal store.
|
|
43
|
+
*/
|
|
44
|
+
activeStore?: ActiveStoreTuple;
|
|
45
|
+
/**
|
|
46
|
+
* Q4 follow-up — useMotion passes a shadowed parent context here so the
|
|
47
|
+
* controlling-variants check is applied uniformly. When omitted, createMotion
|
|
48
|
+
* falls back to `useVariantContext()` directly (the standalone path).
|
|
49
|
+
*/
|
|
50
|
+
parentContext?: VariantContextValue;
|
|
51
|
+
/**
|
|
52
|
+
* MV-in-style Stage 2 — useMotion scrapes `MotionValue`-valued keys out of
|
|
53
|
+
* the user's `style` prop and passes them here. createMotion registers
|
|
54
|
+
* each as an external (user-owned) entry in the value registry and
|
|
55
|
+
* subscribes a writer that re-composes `el.style` from the registry
|
|
56
|
+
* snapshot on every change.
|
|
57
|
+
*/
|
|
58
|
+
styleMotionValues?: Map<string, MotionValue<unknown>>;
|
|
59
|
+
/**
|
|
60
|
+
* MV-in-style Stage 4 — static transform-shortcut entries in the user's
|
|
61
|
+
* `style` (e.g., `style={{ x: 10, scale: mv }}`'s `x: 10`). useMotion scrapes
|
|
62
|
+
* these alongside MVs so createMotion can seed transient registry entries
|
|
63
|
+
* for them. Without this, the writer would drop the static keys on every
|
|
64
|
+
* recompose since they wouldn't appear in the registry.
|
|
65
|
+
*
|
|
66
|
+
* Map values are the resolved leaf (number or string) — no MVs, no
|
|
67
|
+
* keyframe arrays, no accessor functions. useMotion runs the
|
|
68
|
+
* `snapshotValue` reduction before passing them in.
|
|
69
|
+
*/
|
|
70
|
+
styleStaticTransforms?: Map<string, number | string>;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* The imperative primitive: bind an element to a reactive motion-options
|
|
74
|
+
* source. Caller is responsible for keeping the element alive (refs in a
|
|
75
|
+
* component, drag controls, etc.).
|
|
76
|
+
*
|
|
77
|
+
* Phase 1 scope: animate + initial + transition + lifecycle hooks +
|
|
78
|
+
* reduced-motion override + presence registration. Phase 2 layers gesture
|
|
79
|
+
* states (hover/press/focus/inView) and drag on top.
|
|
80
|
+
*/
|
|
81
|
+
export declare function createMotion(el: MotionElement, getOpts: () => MotionOptions, config?: CreateMotionConfig): void;
|
|
82
|
+
export { applyStaticStyle };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Accessor } from 'solid-js';
|
|
2
|
+
import { MotionValueAccessor, PanInfo } from '../types';
|
|
3
|
+
export type CreatePanOptions = {
|
|
4
|
+
/** Fires once after pointer movement crosses the threshold. */
|
|
5
|
+
onPanStart?: (event: PointerEvent, info: PanInfo) => void;
|
|
6
|
+
/** Fires on every pointermove after onPanStart, until pointerup/cancel. */
|
|
7
|
+
onPan?: (event: PointerEvent, info: PanInfo) => void;
|
|
8
|
+
/**
|
|
9
|
+
* Fires on pointerup OR pointercancel after onPanStart has fired.
|
|
10
|
+
* If the pointer was released before the threshold was crossed, onPanEnd
|
|
11
|
+
* is NOT fired (no pan ever happened).
|
|
12
|
+
*/
|
|
13
|
+
onPanEnd?: (event: PointerEvent, info: PanInfo) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Minimum cumulative offset (in px) before onPanStart fires. Distinguishes
|
|
16
|
+
* pan from click. Default: 3px (motion's default).
|
|
17
|
+
*/
|
|
18
|
+
threshold?: number;
|
|
19
|
+
};
|
|
20
|
+
/** Per-axis pair of {@link MotionValueAccessor}s — `pan.point`, `pan.delta`, etc. */
|
|
21
|
+
export type PanAxisPair = {
|
|
22
|
+
x: MotionValueAccessor<number>;
|
|
23
|
+
y: MotionValueAccessor<number>;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Returned by {@link createPan}. `isPanning` is a plain Accessor (booleans
|
|
27
|
+
* aren't animate-able). The four numeric pairs are MotionValueAccessors,
|
|
28
|
+
* each composable with `animate()`, `createTransform`, and `useMotion`.
|
|
29
|
+
*/
|
|
30
|
+
export type CreatePanResult = {
|
|
31
|
+
isPanning: Accessor<boolean>;
|
|
32
|
+
point: PanAxisPair;
|
|
33
|
+
delta: PanAxisPair;
|
|
34
|
+
offset: PanAxisPair;
|
|
35
|
+
velocity: PanAxisPair;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Observe pointer-driven pan gestures on an element.
|
|
39
|
+
*
|
|
40
|
+
* Returns `{ isPanning, point, delta, offset, velocity }`:
|
|
41
|
+
*
|
|
42
|
+
* - `pan.isPanning()` — Solid Accessor; `true` between onPanStart and onPanEnd.
|
|
43
|
+
* - `pan.point.x`, `pan.point.y` — current pointer position in client coords.
|
|
44
|
+
* Each is a {@link MotionValueAccessor}: call `pan.point.x()` for a tracked
|
|
45
|
+
* read, `pan.point.x.get()` for an untracked snapshot, and pass it directly
|
|
46
|
+
* to `animate()`, `createTransform`, or `useMotion` targets.
|
|
47
|
+
* - `pan.delta.x/y` — delta since last pointermove.
|
|
48
|
+
* - `pan.offset.x/y` — cumulative offset since the current pointerdown.
|
|
49
|
+
* - `pan.velocity.x/y` — sliding-window velocity in px/sec.
|
|
50
|
+
*
|
|
51
|
+
* Fields update from `pointerdown` forward (including pre-threshold moves)
|
|
52
|
+
* — gate reads on `pan.isPanning()` if you only care about real pans.
|
|
53
|
+
*
|
|
54
|
+
* The `options` argument accepts either a static object or a function form
|
|
55
|
+
* (matching `useMotion`'s convention). The function form is read INSIDE
|
|
56
|
+
* each pointer-event handler, so reactive option changes apply on the next
|
|
57
|
+
* relevant event without re-attaching listeners.
|
|
58
|
+
*
|
|
59
|
+
* @example Static options
|
|
60
|
+
* const pan = createPan(el, {
|
|
61
|
+
* onPanStart: (e, info) => console.log("start", info.point),
|
|
62
|
+
* threshold: 3,
|
|
63
|
+
* })
|
|
64
|
+
*
|
|
65
|
+
* @example Reactive options (function form — signals tracked)
|
|
66
|
+
* const [threshold, setThreshold] = createSignal(3)
|
|
67
|
+
* const pan = createPan(el, () => ({
|
|
68
|
+
* threshold: threshold(),
|
|
69
|
+
* onPanStart: (e, info) => console.log(info),
|
|
70
|
+
* }))
|
|
71
|
+
*
|
|
72
|
+
* @example Composing pan.point.x with createTransform
|
|
73
|
+
* const pan = createPan(el)
|
|
74
|
+
* const rotation = createTransform(pan.point.x, [0, 300], [0, 90])
|
|
75
|
+
* <div ref={setEl} style={{ transform: `rotate(${rotation()}deg)` }} />
|
|
76
|
+
*
|
|
77
|
+
* @example Reading reactively in JSX
|
|
78
|
+
* const pan = createPan(el)
|
|
79
|
+
* <Show when={pan.isPanning()}>
|
|
80
|
+
* Position: {pan.point.x()}, {pan.point.y()}
|
|
81
|
+
* </Show>
|
|
82
|
+
*/
|
|
83
|
+
export declare function createPan(ref: () => HTMLElement | null | undefined, options?: CreatePanOptions | (() => CreatePanOptions)): CreatePanResult;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { MotionValueAccessor } from '../types';
|
|
2
|
+
type ScrollOffset = any[];
|
|
3
|
+
export type CreateScrollOptions = {
|
|
4
|
+
/** Accessor returning the scroll container element. Defaults to window. */
|
|
5
|
+
container?: () => Element | null;
|
|
6
|
+
/** Accessor returning the scroll target. Defaults to the container itself. */
|
|
7
|
+
target?: () => Element | null;
|
|
8
|
+
/** Primary scroll axis (both axes are still populated regardless). */
|
|
9
|
+
axis?: "x" | "y";
|
|
10
|
+
/** Intersection offsets controlling when progress reaches 0/1. */
|
|
11
|
+
offset?: ScrollOffset;
|
|
12
|
+
};
|
|
13
|
+
export type CreateScrollResult = {
|
|
14
|
+
/** Current scroll-x position in px. Callable: `scrollX()` for reactive read. */
|
|
15
|
+
scrollX: MotionValueAccessor<number>;
|
|
16
|
+
/** Current scroll-y position in px. Callable: `scrollY()` for reactive read. */
|
|
17
|
+
scrollY: MotionValueAccessor<number>;
|
|
18
|
+
/** Normalized scroll-x progress in `[0, 1]` (or `[0, n]` for multi-offset). */
|
|
19
|
+
scrollXProgress: MotionValueAccessor<number>;
|
|
20
|
+
/** Normalized scroll-y progress in `[0, 1]`. */
|
|
21
|
+
scrollYProgress: MotionValueAccessor<number>;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Bind four {@link MotionValueAccessor}s to a scroll source. Mirrors
|
|
25
|
+
* motion/react's `useScroll`; defaults to the window when no container is
|
|
26
|
+
* supplied. Each returned value is callable as a Solid Accessor AND has the
|
|
27
|
+
* full MotionValue surface, so it composes with `useMotion`'s target,
|
|
28
|
+
* `animate()`, `createTransform`, and direct JSX reactivity.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* const { scrollY, scrollYProgress } = createScroll()
|
|
32
|
+
* const opacity = createTransform(scrollYProgress, [0, 1], [1, 0])
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* const [el, setEl] = createSignal<HTMLElement>()
|
|
36
|
+
* const { scrollY } = createScroll({ container: el })
|
|
37
|
+
* <div ref={setEl} style={{ overflow: "auto" }}>...</div>
|
|
38
|
+
*/
|
|
39
|
+
export declare function createScroll(options?: CreateScrollOptions): CreateScrollResult;
|
|
40
|
+
export {};
|