# `Issho.Motion`
[🔗](https://github.com/hattoriai/issho/blob/v0.4.0/lib/issho/motion.ex#L1)

How an agent moves on the page, so that the people can follow it: it
goes to where it works, presses, drags and lets go, and clicks, as a
hand would. Only where it goes is sent, once for each gesture; each
browser draws the way there on its own page, and the agent waits as long
as that takes before its change lands.

A gesture's target is a place of a document, in the document's own terms
(`%{"doc" => "notebook:7/body", "at" => at}`: a caret, a node, a cell),
or an element of the app's page that it named (`%{"anchor" => "edit"}`,
the element with `data-issho-anchor="edit"`). Components' tools move
their agents with it; an app's own tools too:

    # An app's tool: the agent goes to the button, clicks it, then acts.
    :ok = Issho.Motion.click(participant, %{"anchor" => "new-page"})
    {:ok, page} = Pages.create(...)

## When it moves

An agent moves only for someone who can see it. Each browser of the
room says what it shows (the page in the foreground, the documents of
its components on the screen, whether its person wants motion): when no
person of the room shows the target, or none wants motion, the agent is
there at once. A browser that says nothing, or a person who follows the
agent, counts as watching: the agent rather moves for no one than skips
someone who looks.

## Time

A gesture takes `flight` milliseconds to another document or element,
`step` within the same one (each browser fits its own way into it).
A tool call has a `budget`: its gestures together never take longer, the
later ones shorter, then at once.

    config :issho, Issho.Motion,
      travel: true,     # false: agents are there at once, everywhere
      flight: 450,
      step: 300,
      click: 150,       # the moment on a click before what it does
      budget: 3_000     # the most a tool call's gestures take, together

A component may move its agents or not (Kotoba's, Masu's and Hakushi's
`travel`); this one setting turns motion off for all of them.

# `gesture`

```elixir
@type gesture() :: :move | :press | :drag | :release | :click | :navigate
```

A gesture: `:move` to go there, `:press` and `:release` around a `:drag`, `:click`, and `:navigate` (`navigate/2`).

# `target`

```elixir
@type target() :: %{required(String.t()) =&gt; term()}
```

Where a gesture goes: a place of a document, or an element of the page.

# `click`

```elixir
@spec click(GenServer.server(), target(), keyword()) :: :ok | {:error, term()}
```

Goes to a target and clicks it: the people see it ring.

# `drag`

```elixir
@spec drag(GenServer.server(), target(), target(), keyword()) ::
  :ok | {:error, term()}
```

Selects as a drag does: pressed at `from`, let go at `to` (a range of
the same document), in two gestures.

# `go`

```elixir
@spec go(GenServer.server(), target(), keyword()) :: :ok | {:error, term()}
```

Goes to a target. Options: `:gesture` (`:move`), `:place` (whether a
document's target is also the agent's place, its selection there:
true), `:travel` (a component's own setting: true), and `:block`, the
component's own keys of the target's document that change with the
gesture, in the same message (a canvas's cursor and selection, under
the document in `blocks`: `Issho.Awareness`). `:aware` is the same for
Issho's own top-level keys.

# `navigate`

```elixir
@spec navigate(GenServer.server(), String.t()) :: :ok | {:error, term()}
```

Goes to another page of the app, by its path (`"/pages/2"`): the people
who follow the agent go there too, their browsers as if they had
followed a link. It does not change the rooms the agent is in: to work
in the documents of that page, it joins its room. Only a path of the app
(starting with a single `/`) goes.

# `pause`

```elixir
@spec pause(GenServer.server(), target(), non_neg_integer(), keyword()) :: :ok
```

A moment on a target, before what the agent does there, so that the
people see what will change: taken only when someone sees it, within
the tool call's budget. Options: `:travel`.

# `travel?`

```elixir
@spec travel?() :: boolean()
```

Whether agents move at all (`config :issho, Issho.Motion, travel: false` turns it off).

# `watched?`

```elixir
@spec watched?(GenServer.server(), target()) :: boolean()
```

Whether anyone of the room may see the agent go to a target, and wants
to: a person whose browser shows it (its page in the foreground, and
for a document's target, the document's component on the screen),
whose browser says nothing of what it shows, or who follows the agent.

# `within`

```elixir
@spec within(non_neg_integer() | nil, (-&gt; result)) :: result when result: term()
```

Runs a function with the time budget of a tool call: the gestures it
makes together never take longer. `Issho.Tools` runs each tool so.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
