|
| 1 | +--- |
| 2 | +id: pointer |
| 3 | +title: Pointer |
| 4 | +--- |
| 5 | + |
| 6 | +```ts |
| 7 | +pointer(input: PointerInput): Promise<void> |
| 8 | +``` |
| 9 | + |
| 10 | +The `pointer` API allows to simulate interactions with pointer devices. It |
| 11 | +accepts a single pointer action or an array of them. |
| 12 | + |
| 13 | +```ts |
| 14 | +type PointerInput = PointerActionInput | Array<PointerActionInput> |
| 15 | +``` |
| 16 | +
|
| 17 | +> Our primary target audience tests per `jest` in a `jsdom` environment and there |
| 18 | +is no layout in `jsdom`. This means that different from your browser the |
| 19 | +elements don't exist in a specific position, layer and size. |
| 20 | +We don't try to determine if the pointer action you describe is possible at that |
| 21 | +position in your layout. |
| 22 | +
|
| 23 | +## Pointer action |
| 24 | +
|
| 25 | +There are two types of actions: press and move. |
| 26 | +
|
| 27 | +### <a name="press" href="#"/>Pressing a button or touching the screen |
| 28 | +
|
| 29 | +A pointer action is a press action if it defines a key to be pressed, to be |
| 30 | +released, or both. |
| 31 | +
|
| 32 | +```js |
| 33 | +pointer({keys: '[MouseLeft]'}) |
| 34 | +``` |
| 35 | +
|
| 36 | +You can declare multiple press actions (on the same position) at once which will |
| 37 | +be resolved to multiple actions internally. If you don't need to declare any |
| 38 | +other properties you can also just supply the `keys` string. |
| 39 | +
|
| 40 | +```js |
| 41 | +pointer({keys: '[MouseLeft][MouseRight]'}) |
| 42 | +// or |
| 43 | +pointer('[MouseLeft][MouseRight]') |
| 44 | +``` |
| 45 | +
|
| 46 | +In order to press a button without releasing it, the button name is suffixed with |
| 47 | +`>`. |
| 48 | +For just releasing a previously pressed button, the tag is started with `/`. |
| 49 | +
|
| 50 | +```js |
| 51 | +pointer('[MouseLeft>]') // press the left mouse button |
| 52 | +pointer('[/MouseLeft]') // release the left mouse button |
| 53 | +``` |
| 54 | +
|
| 55 | +Which buttons are available depends on the [`pointerMap`](options#pointermap). |
| 56 | +
|
| 57 | +### <a name="move" href="#"/>Moving a pointer |
| 58 | +
|
| 59 | +Every pointer action that is not a press action describes a pointer movement. |
| 60 | +
|
| 61 | +You can declare which pointer is moved per `pointerName` property. This defaults |
| 62 | +to `mouse`. |
| 63 | +
|
| 64 | +Note that the `mouse` pointer (`pointerId: 1`) is also the only pointer that |
| 65 | +always exists and has a position. A `touch` pointer only exists while the screen |
| 66 | +is touched and receives a new `pointerId` every time. For these pointers, we use |
| 67 | +the "button" name from the press action as `pointerName`. |
| 68 | +
|
| 69 | +```js |
| 70 | +pointer([ |
| 71 | + // touch the screen at element1 |
| 72 | + {keys: '[TouchA>]', target: element1}, |
| 73 | + // move the touch pointer to element2 |
| 74 | + {pointerName: 'TouchA', target: element2}, |
| 75 | + // release the touch pointer at the last position (element2) |
| 76 | + {keys: '[/TouchA]'}, |
| 77 | +]) |
| 78 | +``` |
| 79 | +
|
| 80 | +## Pointer position |
| 81 | +
|
| 82 | +### PointerTarget |
| 83 | +
|
| 84 | +```ts |
| 85 | +interface PointerTarget { |
| 86 | + target: Element |
| 87 | + coords?: PointerCoords |
| 88 | +} |
| 89 | +``` |
| 90 | + |
| 91 | +The `PointerTarget` props allows to describe the position of the pointer on the |
| 92 | +document. |
| 93 | +The `coords` you provide are applied as-is to the resulting |
| 94 | +[`MouseEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent) and |
| 95 | +can be omitted. |
| 96 | +The `target` should be the element receiving the pointer input in the browser. |
| 97 | +This is the topmost element that can receive pointer event at those coordinates. |
| 98 | + |
| 99 | +### SelectionTarget |
| 100 | + |
| 101 | +```ts |
| 102 | +interface SelectionTarget { |
| 103 | + node?: Node |
| 104 | + offset?: number |
| 105 | +} |
| 106 | +``` |
| 107 | + |
| 108 | +Pointer actions can alter the selection in the document. |
| 109 | +In the browser every pointer position corresponds with a DOM position. This is a |
| 110 | +DOM node and a DOM offset which usually translates to the character closest to |
| 111 | +the pointer position. |
| 112 | +As all character in a no-layout environment are in the same layout position we |
| 113 | +assume a pointer position to be closest to the last descendant of the pointer |
| 114 | +`target`. |
| 115 | + |
| 116 | +If you provide `offset`, we assume the pointer position to be closest to the |
| 117 | +`offset-th` character of `target.textContent`. |
| 118 | + |
| 119 | +If you also provide `node`, we treat `node` and `offset` as the exact DOM |
| 120 | +position to be used for any selection. |
| 121 | + |
| 122 | +```jsx |
| 123 | +// element: <div><span>foo</span><span>bar</span></div> |
| 124 | +// | marking the cursor. |
| 125 | +// [ ] marking a selection. |
| 126 | + |
| 127 | +pointer({target: element, offset: 2, keys: '[MouseLeft]'}) |
| 128 | +// => <div><span>fo|o</span><span>bar</span></div> |
| 129 | + |
| 130 | +pointer([ |
| 131 | + {target: element, offset: 2, keys: '[MouseLeft>]'}, |
| 132 | + {offset: 5}, |
| 133 | +]) |
| 134 | +// => <div><span>fo[o</span><span>ba]r</span></div> |
| 135 | + |
| 136 | +pointer({target: element, node: element, offset: 1, keys: '[MouseLeft]'}) |
| 137 | +// => <div><span>foo</span>|<span>bar</span></div> |
| 138 | +``` |
0 commit comments