solidjs-motion 0.1.2 → 0.1.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.
@@ -31,7 +31,7 @@ import { MotionOptions, MotionStyle } from './types';
31
31
  * AND `splitProps` at runtime break — the type check surfaces the
32
32
  * specific missing key by name.
33
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";
34
+ export type MotionOptKey = "initial" | "animate" | "exit" | "hover" | "press" | "focus" | "inView" | "inViewOptions" | "drag" | "dragConstraints" | "dragElastic" | "dragMomentum" | "dragTransition" | "dragSnapToOrigin" | "dragControls" | "dragListener" | "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
35
  /**
36
36
  * Frozen list of `MotionOptKey`s — fed to `splitProps` at every
37
37
  * tag-component render to separate motion options from element
@@ -146,6 +146,20 @@ export type DragOptions = {
146
146
  dragSnapToOrigin?: boolean;
147
147
  /** Imperatively-triggered drag (from createDragControls). */
148
148
  dragControls?: DragControls;
149
+ /**
150
+ * Whether drag listens for its OWN pointerdown events on the element.
151
+ * Defaults to `true`.
152
+ *
153
+ * Set to `false` when drag should only be started externally via a
154
+ * `dragControls.start(event)` call from a different element (typically
155
+ * a "drag handle"). The element itself remains non-draggable from
156
+ * direct pointer interaction — useful for drawers, sheets, and other
157
+ * surfaces where the body must stay scrollable and only a dedicated
158
+ * affordance should commit to a drag.
159
+ *
160
+ * Mirrors motion-react's `dragListener` prop.
161
+ */
162
+ dragListener?: boolean;
149
163
  };
150
164
  export type MotionCallbacks = {
151
165
  onAnimationStart?: () => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solidjs-motion",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "An animation library for SolidJS — port of motion/react patterns built on the framework-agnostic motion package",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -75,6 +75,7 @@ export type MotionOptKey =
75
75
  | "dragTransition"
76
76
  | "dragSnapToOrigin"
77
77
  | "dragControls"
78
+ | "dragListener"
78
79
  | "whileDrag"
79
80
  // Pan
80
81
  | "panThreshold"
@@ -132,6 +133,7 @@ export const MOTION_OPT_KEYS: readonly MotionOptKey[] = [
132
133
  "dragTransition",
133
134
  "dragSnapToOrigin",
134
135
  "dragControls",
136
+ "dragListener",
135
137
  "whileDrag",
136
138
  // Pan
137
139
  "panThreshold",
@@ -474,7 +474,16 @@ export function createDrag(
474
474
  restoreBodyAndElementStyles()
475
475
  releasePointerCaptureSafely()
476
476
 
477
- getOpts().onDragEnd?.(event, info)
477
+ // The user's `onDragEnd` callback fires at the END of this function
478
+ // (just before the early-out), not here. Rationale: a synchronous
479
+ // state flip from the callback (e.g. closing a Dialog whose contents
480
+ // are this draggable) used to race motion's own post-callback work
481
+ // — momentum dispatch, MV-ref cleanup — and could wedge surrounding
482
+ // libraries that observe the same DOM (scroll lock, pointer-event
483
+ // layers). Firing AFTER all motion DOM-touching work guarantees a
484
+ // clean handoff: by the time the callback runs, the drag session is
485
+ // fully torn down and any subsequent reactive cascade is unambiguous
486
+ // about ownership.
478
487
 
479
488
  // Capture refs locally — the closure clears xMV/yMV below before the
480
489
  // momentum promise can resolve, but the inertia animation needs stable
@@ -630,20 +639,34 @@ export function createDrag(
630
639
  xMV = null
631
640
  yMV = null
632
641
  sessionBounds = null
642
+
643
+ // Callback fires last — see the note at the top of handlePanEnd.
644
+ getOpts().onDragEnd?.(event, info)
633
645
  }
634
646
 
635
647
  // Function-form options so createPan reads `panThreshold` reactively.
636
648
  // Handler references are stable — only the threshold (and the wrapping
637
649
  // object) is recreated per call from createPan.
638
- createPan(
639
- () => el,
640
- () => ({
641
- threshold: getOpts().panThreshold,
642
- onPanStart: handlePanStart,
643
- onPan: handlePan,
644
- onPanEnd: handlePanEnd,
645
- }),
646
- )
650
+ //
651
+ // `dragListener: false` opts out of motion's own pointerdown listener
652
+ // on `el`. Drag becomes external-only — triggered through
653
+ // `dragControls.start(event)` from another element. Pointer
654
+ // interaction on `el` itself stays inert, letting the surface remain
655
+ // scrollable (the canonical case: a drawer body with a dedicated drag
656
+ // handle). One-time read at construction matches motion-react's
657
+ // semantic — toggling `dragListener` reactively is intentionally not
658
+ // supported.
659
+ if (getOpts().dragListener !== false) {
660
+ createPan(
661
+ () => el,
662
+ () => ({
663
+ threshold: getOpts().panThreshold,
664
+ onPanStart: handlePanStart,
665
+ onPan: handlePan,
666
+ onPanEnd: handlePanEnd,
667
+ }),
668
+ )
669
+ }
647
670
 
648
671
  // ---------- External drag (Q9 — createDragControls integration) ----------
649
672
  // When the user wires `dragControls: someControls` into MotionOptions, an
package/src/types.ts CHANGED
@@ -219,6 +219,20 @@ export type DragOptions = {
219
219
  dragSnapToOrigin?: boolean
220
220
  /** Imperatively-triggered drag (from createDragControls). */
221
221
  dragControls?: DragControls
222
+ /**
223
+ * Whether drag listens for its OWN pointerdown events on the element.
224
+ * Defaults to `true`.
225
+ *
226
+ * Set to `false` when drag should only be started externally via a
227
+ * `dragControls.start(event)` call from a different element (typically
228
+ * a "drag handle"). The element itself remains non-draggable from
229
+ * direct pointer interaction — useful for drawers, sheets, and other
230
+ * surfaces where the body must stay scrollable and only a dedicated
231
+ * affordance should commit to a drag.
232
+ *
233
+ * Mirrors motion-react's `dragListener` prop.
234
+ */
235
+ dragListener?: boolean
222
236
  }
223
237
 
224
238
  // ---------------------------------------------------------------------------