# `DragOptions.constrain`

> Contract 2.0.0 · package sha256 `a857eca95b35921109faf997094bb4192f12527d9d0fcd4be7e97f06425bad6e` · generated from `configurator-runtime.d.ts` by `services/onsite-scripter/scripts/build-contract-docs.mjs`; edit the source, not this file.

Function property of [`DragOptions`](DragOptions.md) · labs, `@experimental` · since 2.0.0 · optional: reach it through `has()`

```ts
constrain?: (move: DragMove, frame: Frame) => PoseInput | null;
```

Synchronous. Runs before every frame drawn while a drag is active, at least once after each
pointer move, and once at release. While the pointer and the camera rest and it returns the
pose it returned before, the runtime draws no more frames for the drag until the next move,
camera motion or animation, so a held press costs no redraws. Writes made inside it, and
through `frame`, show in the same frame as the pose
it returns. Return a world PoseInput with one rotation (never a [`Pose`](Pose.md) read: copy
`{ position, quaternion, scale }` from it), or null to keep `move.pose`. It can't await, so it can't
call [`input.raycast`](Input.raycast.md): aim with `move.ray` and `/math`. Budget 1 ms, averaged over its last 60
calls ('frame-budget'). Check [`session.supports('input.drag.constrain')`](Session.supports.md) before passing it.

**Default:** undefined (the unit follows `move.pose`)

## Generic-API test (spec 3.1)

| Rule | Result |
| --- | --- |
| 1. Neutral name | pass: `constrain` names no product |
| 2. A precedent | pass: [Babylon.js PointerDragBehavior (startDrag, onDragObservable, validateDrag)](https://github.com/BabylonJS/Babylon.js/blob/master/packages/dev/core/src/Behaviors/Meshes/pointerDragBehavior.ts) (row `G1`); [jQuery UI draggable (drag, revert)](https://api.jqueryui.com/draggable/) (row `G1`) |
| 3. Two apps, or labs | labs (`@experimental` at a stable path, reached through `has()` or `supports()`): it graduates when a second app uses it; apps today: app-04c2774145, app-37356bf09f, app-4762caacdc, app-fc07850558, app-fc306ec3dc |
| 4. The cheaper fix first | decided per need in Appendix B: rows `G1`, `K47` at tier labs, stable (a member only where no rule, data, asset or app code serves the need) |
