off_topic

Tip: Hover the links for short summaries!

Starting apps

application, component, script

Making subscriptions

none, from, element, batch, dep, map, watch

Keyboard

on_key_press, on_key_down, on_key_up

Pointer

on_click, on_pointer_move, on_pointer_down, on_pointer_up, on_pointer_cancel, on_wheel

Browser

window_size, screen_orientation, window_scroll, scroll_to, page_state, window_hover, title, meta, body_class, prevent_unload

DOM

element_size, element_scroll, element_scroll_to, scroll_into_view, element_visible focus, blur, on

Component

aria, pseudo_state, form_value

Preferences

colour_scheme, contrast, reduced_motion, breakpoints, tailwind_breakpoints, language, local_storage, session_storage, set_local_storage, set_session_storage

Time

now, here, after, every, on_idle

Connections

online, server_sent_events, websocket, websocket_send

Advanced

init, update, view remote, command, watching, including, throttle, delay, root

Types

The user’s preferred color scheme.

pub type ColourScheme {
  Dark
  Light
}

Constructors

  • Dark
  • Light

The user’s preferred contrast level.

pub type ContrastPreference {
  MoreContrast
  LessContrast
  ForcedContrast
  NoContrastPreference
}

Constructors

  • MoreContrast
  • LessContrast
  • ForcedContrast
  • NoContrastPreference

An opaque value off_topic uses to detect when a subscription’s inputs have changed and it needs to be restarted.

Create one with dep.

pub type Dependency =
  @internal Dependency

A keyboard event payload.

pub type Key {
  Key(
    key: String,
    code: String,
    ctrl: Bool,
    alt: Bool,
    meta: Bool,
    shift: Bool,
  )
}

Constructors

  • Key(
      key: String,
      code: String,
      ctrl: Bool,
      alt: Bool,
      meta: Bool,
      shift: Bool,
    )

The subscription runtime’s wrapper around your application message type.

Use with init, update, and view when wiring up off_topic manually instead of through application.

pub type Message(message) =
  @internal Message(message)

The subscription runtime’s wrapper around your application model.

Use with init, update, and view when wiring up off_topic manually instead of through application.

pub type Model(model, message) =
  @internal Model(model, message)

The user’s motion sensitivity preference.

pub type MotionPreference {
  ReduceMotion
  NoMotionPreference
}

Constructors

  • ReduceMotion
  • NoMotionPreference

The current browser page lifecycle state.

Transitions follow the Page Lifecycle API. Frozen pages may resume or be silently discarded by the browser; Terminated is always final. The Discarded lifecycle state is absent because the browser unloads discarded pages without firing any events.

pub type PageState {
  Active
  Passive
  Hidden
  Frozen
  Terminated
}

Constructors

  • Active

    Visible and has input focus.

  • Passive

    Visible but does not have input focus.

  • Hidden

    Not visible, and not frozen, discarded, or terminated.

  • Frozen

    Browser has suspended execution to conserve resources; may resume or be discarded silently.

  • Terminated

    Page has started unloading and will not resume.

A pointer event payload.

pub type Pointer {
  Pointer(
    x: Int,
    y: Int,
    button: Int,
    pointer_type: PointerType,
    pointer_id: Int,
    is_primary: Bool,
    pressure: Float,
    tilt_x: Int,
    tilt_y: Int,
    ctrl: Bool,
    alt: Bool,
    meta: Bool,
    shift: Bool,
  )
}

Constructors

  • Pointer(
      x: Int,
      y: Int,
      button: Int,
      pointer_type: PointerType,
      pointer_id: Int,
      is_primary: Bool,
      pressure: Float,
      tilt_x: Int,
      tilt_y: Int,
      ctrl: Bool,
      alt: Bool,
      meta: Bool,
      shift: Bool,
    )

The pointing device type reported by a pointer event.

pub type PointerType {
  Mouse
  Pen
  Touch
}

Constructors

  • Mouse

    Standard mouse or trackpad.

  • Pen

    Stylus or digital pen.

  • Touch

    Touchscreen finger contact.

The screen orientation reported by the browser.

pub type ScreenOrientation {
  PortraitPrimary
  PortraitSecondary
  LandscapePrimary
  LandscapeSecondary
}

Constructors

  • PortraitPrimary

    Portrait with the top of the device facing up.

  • PortraitSecondary

    Portrait with the top of the device facing down (upside-down).

  • LandscapePrimary

    Landscape with the top of the device facing right.

  • LandscapeSecondary

    Landscape with the top of the device facing left.

The block or inline alignment for scroll_into_view.

pub type ScrollAlignment {
  Start
  Center
  End
  Nearest
}

Constructors

  • Start
  • Center
  • End
  • Nearest

The scroll animation style.

pub type ScrollBehaviour {
  Smooth
  Instant
  Auto
}

Constructors

  • Smooth
  • Instant
  • Auto

An active listener that dispatches messages to your Lustre application.

Build subscriptions with the functions in this module and return them from your application’s subscriptions callback. Use batch to combine multiple subscriptions, and none to return an empty one.

pub type Subscription(message) =
  @internal Subscription(message)

A Tailwind CSS responsive breakpoint.

pub type TailwindBreakpoint {
  Xs
  Sm
  Md
  Lg
  Xl
  Xxl
}

Constructors

  • Xs
  • Sm
  • Md
  • Lg
  • Xl
  • Xxl

The DOM target to attach an event listener to.

See also: on, target

pub type Target {
  Host
  Root
  Window
  Document
}

Constructors

  • Host

    The shadow host of the Lustre component (custom element).

  • Root

    The element Lustre is mounted on.

  • Window

    The browser window.

  • Document

    The document.

A frame received from a WebSocket connection.

pub type WebsocketMessage {
  TextFrame(data: String)
  BinaryFrame(data: BitArray)
}

Constructors

  • TextFrame(data: String)
  • BinaryFrame(data: BitArray)

A wheel event payload.

pub type Wheel {
  Wheel(
    delta_x: Float,
    delta_y: Float,
    delta_z: Float,
    delta_mode: WheelDeltaMode,
    ctrl: Bool,
    alt: Bool,
    meta: Bool,
    shift: Bool,
  )
}

Constructors

  • Wheel(
      delta_x: Float,
      delta_y: Float,
      delta_z: Float,
      delta_mode: WheelDeltaMode,
      ctrl: Bool,
      alt: Bool,
      meta: Bool,
      shift: Bool,
    )

Scroll-wheel delta units reported by the browser.

The browser decides which unit it uses; the most common is Pixel. Never assume the delta is in Pixel mode without checking delta_mode.

pub type WheelDeltaMode {
  Pixel
  Line
  Page
}

Constructors

  • Pixel
  • Line
  • Page

Values

pub fn after(
  duration: duration.Duration,
  send message: message,
) -> effect.Effect(message)

Dispatch a message after a delay.

See also: every, now

pub fn application(
  init init: fn(flags) -> #(model, effect.Effect(message)),
  update update: fn(model, message) -> #(
    model,
    effect.Effect(message),
  ),
  subscriptions subscriptions: fn(model) -> Subscription(message),
  view view: fn(model) -> element.Element(message),
) -> lustre.App(flags, Model(model, message), Message(message))

Create a Lustre application with subscription support.

A drop-in replacement for lustre.application that adds a subscriptions callback. The returned App is passed directly to lustre.start or lustre.start_server_component.

See also: component, init, update, view

pub fn aria(
  name name: String,
  value value: String,
) -> Subscription(message)

Sync a single ARIA property on the component host’s ElementInternals.

name is attribute-style ("role", "aria-expanded", "aria-label", …); off_topic converts it to the camelCase ElementInternals property and sets it on the host’s ElementInternals. Does nothing outside a component context.

See also: pseudo_state, form_value

pub fn batch(
  list: List(Subscription(message)),
) -> Subscription(message)

Combine a list of subscriptions into one.

See also: none

pub fn blur() -> effect.Effect(message)

Blur (unfocus) the currently focused element.

See also: focus

pub fn body_class(class_name: String) -> Subscription(message)

Add a CSS class to the document body.

The class is removed when the subscription stops or the class name changes.

See also: title

pub fn breakpoints(
  fallback fallback: String,
  breakpoints pairs: List(#(Int, String)),
  send message: fn(String) -> message,
) -> Subscription(message)

Dispatch the current active breakpoint label, then again whenever it changes.

Pairs are matched largest-first, returning the label whose min_width the window satisfies, or fallback when none match.

See also: window_size, tailwind_breakpoints

pub fn colour_scheme(
  send message: fn(ColourScheme) -> msg,
) -> Subscription(msg)

Dispatch the current color scheme preference, then again whenever it changes.

See also: contrast, reduced_motion

pub fn command(
  name: String,
  params: List(json.Json),
) -> effect.Effect(message)

Dispatch a named browser command through the off_topic client runtime. SC

The server-component counterpart to effect.from: dispatches an off-topic:command event that the ot-client-runtime web component routes to the registered window.OffTopic.commands[name] handler on the client.

For the built-in commands (set_local_storage, scroll_to, etc.) both paths are handled automatically — use those directly. Reserve command for custom handlers you register yourself.

See also: remote

pub fn component(
  init init: fn(Nil) -> #(model, effect.Effect(message)),
  update update: fn(model, message) -> #(
    model,
    effect.Effect(message),
  ),
  subscriptions subscriptions: fn(model) -> Subscription(message),
  view view: fn(model) -> element.Element(message),
  options options: List(component.Option(message)),
) -> lustre.App(Nil, Model(model, message), Message(message))

Create a Lustre component that runs the off_topic subscription runtime. This is the component equivalent of application.

If you’re using component options, swap your import to off_topic/component, offering the same API.

See also: application

pub fn contrast(
  send message: fn(ContrastPreference) -> msg,
) -> Subscription(msg)

Dispatch the current contrast preference, then again whenever it changes.

See also: colour_scheme, reduced_motion

pub fn delay(
  subscription: Subscription(message),
  wait duration: duration.Duration,
) -> Subscription(message)

Hold a subscription’s message until the subscription has been quiet for duration.

When combined with throttle, the throttle pass-through fires immediately and a delayed message is also queued for the final event in each burst.

See also: throttle

pub fn dep(value: any) -> Dependency

Wrap a value as a subscription dependency.

off_topic restarts a subscription whenever any of its dependency values change. When making your own subscriptions, keep in mind that you should typically not pass the message callback as a dependency.

See also: from, watching

pub fn element(
  watching dependencies: List(Dependency),
  run callback: fn(fn(message) -> Nil, dynamic.Dynamic) -> fn() -> Nil,
) -> Subscription(message)

Build a subscription with access to the Lustre root element. JS

Like from, but the setup callback also receives the DOM element that Lustre is mounted on, allowing you to attach listeners scoped to that element rather than the window or document.

See also: from, resource

pub fn element_scroll(
  selector selector: String,
  send message: fn(Int, Int) -> msg,
) -> Subscription(msg)

Dispatch the scroll position of an element, then again whenever it changes.

Pass root to observe the component mount point, or any CSS selector for a descendant.

See also: window_scroll, element_size, element_visible

pub fn element_scroll_to(
  selector selector: String,
  x x: Int,
  y y: Int,
  behaviour behaviour: ScrollBehaviour,
) -> effect.Effect(message)

Scroll an element to a specific position.

x and y are pixel offsets within the scrollable element. Pass root to target the component mount point, or any CSS selector for a descendant.

See also: element_scroll, scroll_to

pub fn element_size(
  selector selector: String,
  send message: fn(Int, Int) -> msg,
) -> Subscription(msg)

Dispatch the size of an element, then again whenever it changes.

Pass root to observe the component mount point, or any CSS selector for a descendant.

See also: window_size, tailwind_breakpoints, element_scroll, element_visible

pub fn element_visible(
  selector selector: String,
  send message: fn(Bool) -> msg,
) -> Subscription(msg)

Dispatch whether an element intersects the viewport, then again whenever it changes.

Useful for infinite scroll sentinels and lazy load / pause-on-hide patterns.

See also: element_size, element_scroll

pub fn every(
  every interval: duration.Duration,
  immediate immediate: Bool,
  on_elapsed handle_elapsed: fn(timestamp.Timestamp) -> message,
) -> Subscription(message)

Dispatch a message on a repeating interval.

The callback receives the current timestamp at each tick. When immediate is True, the first tick fires immediately on subscribe; otherwise the first tick fires after the first interval has elapsed.

See also: after

pub fn focus(selector selector: String) -> effect.Effect(message)

Focus the first element matching selector.

See also: blur

pub fn form_value(
  value value: option.Option(String),
) -> Subscription(message)

Sync the form-associated element’s submitted value.

The component has to have the form_associated option set. Does nothing outside a component context.

See also: aria, pseudo_state

pub fn from(
  watching dependencies: List(Dependency),
  run callback: fn(fn(message) -> Nil) -> fn() -> Nil,
) -> Subscription(message)

Build a subscription from an arbitrary setup callback.

The callback receives a dispatch function and must return a cleanup function that will be called when the subscription is torn down. off_topic restarts the subscription whenever any value in dependencies changes.

For the exact rules on when and how subscriptions and their cleanup functions fire, see the guide.

See also: element, resource

pub fn here(
  on_timezone_offset handle_timezone_offset: fn(duration.Duration) -> message,
) -> Subscription(message)

Dispatch the current timezone offset, then again whenever it changes.

Always dispatches the browser’s local timezone offset, even in server components — the server’s timezone is never used.

See also: now

pub fn including(
  subscription: Subscription(message),
  paths: List(String),
) -> Subscription(message)

Specify which fields are forwarded from a remote subscription’s events.

Remote subscriptions have to explicitely list all fields they want to forward to the server. Has no effect on non-Remote subscriptions.

See also: remote

pub fn init(
  flags flags: flags,
  init init: fn(flags) -> #(model, effect.Effect(message)),
) -> #(Model(model, message), effect.Effect(Message(message)))

The low-level counterpart to application, for use when you need to compose off_topic into an existing lustre.application manually.

See also: update, view, application

pub fn language(
  send message: fn(String) -> msg,
) -> Subscription(msg)

Dispatch the current navigator language, then again whenever it changes.

Dispatches a BCP 47 language tag such as "en-US".

pub fn local_storage(
  key key: String,
  send message: fn(option.Option(String)) -> msg,
) -> Subscription(msg)

Dispatch the current value of a localStorage key, then again whenever it changes.

Dispatches None when the key is absent and Some(value) otherwise. Only detects changes made in other tabs or windows — updates made in the current page are not forwarded by the browser’s storage event unless set_local_storage is called with notify: True.

See also: session_storage, set_local_storage

pub fn map(
  subscription: Subscription(a),
  with tagger: fn(a) -> b,
) -> Subscription(b)

Transform the messages a subscription dispatches.

pub fn meta(
  name name: String,
  content content: String,
) -> Subscription(message)

Update or insert a <meta name="…" content="…"> tag.

See also: title

pub fn none() -> Subscription(message)

A subscription that never fires.

See also: batch

pub fn now(
  send message: fn(timestamp.Timestamp) -> message,
) -> effect.Effect(message)

Dispatch the current timestamp.

See also: here, after, every

pub fn on(
  on target: Target,
  event name: String,
  run decoder: decode.Decoder(message),
) -> Subscription(message)

Subscribe to a DOM event on a target element.

pub fn on_click(
  send message: fn(Pointer) -> message,
) -> Subscription(message)

Subscribe to click events on the document.

See also: on_pointer_down, on_pointer_up

pub fn on_idle(
  after timeout: duration.Duration,
  send message: fn(Bool) -> msg,
) -> Subscription(msg)

Dispatch a message when the user becomes idle or active.

Starts a timer that resets on any interaction with the current document. Dispatches True when the timer elapses with no activity, and False when activity resumes.

See also: page_state, window_hover

pub fn on_key_down(
  send message: fn(Key) -> message,
) -> Subscription(message)

Subscribe to keydown events on the document.

See also: on_key_press, on_key_up

pub fn on_key_press(
  send message: fn(Key) -> message,
) -> Subscription(message)

Subscribe to keypress events on the document.

See also: on_key_down, on_key_up

pub fn on_key_up(
  send message: fn(Key) -> message,
) -> Subscription(message)

Subscribe to keyup events on the document.

See also: on_key_press, on_key_down

pub fn on_pointer_cancel(
  send message: fn(Pointer) -> message,
) -> Subscription(message)

Subscribe to pointer cancel events on the document.

Fires when the browser interrupts a pointer sequence — for example when a touch is cancelled by an incoming phone call or the pointer leaves the browser window mid-drag.

See also: on_pointer_down, on_pointer_up

pub fn on_pointer_down(
  send message: fn(Pointer) -> message,
) -> Subscription(message)

Subscribe to pointer down events on the document.

See also: on_pointer_up, on_click

pub fn on_pointer_move(
  send message: fn(Pointer) -> message,
) -> Subscription(message)

Subscribe to pointer move events on the document.

See also: on_pointer_down, on_pointer_up

pub fn on_pointer_up(
  send message: fn(Pointer) -> message,
) -> Subscription(message)

Subscribe to pointer up events on the document.

See also: on_pointer_down, on_click

pub fn on_wheel(
  send message: fn(Wheel) -> message,
) -> Subscription(message)

Subscribe to wheel events on the document.

See also: window_scroll

pub fn online(send message: fn(Bool) -> msg) -> Subscription(msg)

Dispatch the current network status, then again whenever it changes.

Dispatches True when online and False when offline.

pub fn page_state(
  send handle_page_state: fn(PageState) -> message,
) -> Subscription(message)

Dispatch the current page lifecycle state, then again whenever it changes.

No initial dispatch fires when the page starts in the Active state, which is the common case on load. If the page is already Passive or Hidden at subscription setup, the current state dispatches immediately.

pub fn prevent_unload(
  prevent enabled: Bool,
  send message: message,
) -> Subscription(message)

Block the user from immediately leaving the page when enabled, showing a simple popup instead.

Useful for when your page has unsaved changes that you don’t want users to accidentily lose.

pub fn pseudo_state(
  name name: String,
  checked checked: Bool,
) -> Subscription(message)

Sync a single CSS custom state on the component host. Does nothing outside a component context.

See also: aria, form_value

pub fn reduced_motion(
  send message: fn(MotionPreference) -> msg,
) -> Subscription(msg)

Dispatch the current motion preference, then again whenever it changes.

See also: colour_scheme, contrast

pub fn remote(
  name name: String,
  with params: List(json.Json),
  run decoder: decode.Decoder(message),
) -> Subscription(message)

Build a subscription that runs on the server component client.

See also: including

pub const root: String

CSS selector for the component mount point.

Pass root as the selector argument to any element-scoped subscription to target the Lustre component mount element.

See also: target, element_size, element_scroll, element_visible

pub fn screen_orientation(
  send message: fn(ScreenOrientation) -> msg,
) -> Subscription(msg)

Dispatch the current screen orientation, then again whenever it changes.

pub fn script() -> element.Element(msg)

Inline the server component runtime as a <script> tag.

Prefer serving the pre-built file from off_topic’s priv/static directory when possible. This inline version is useful for development or when you do not control the HTML document.

pub fn scroll_into_view(
  selector selector: String,
  block block: ScrollAlignment,
  inline inline: ScrollAlignment,
  behaviour behaviour: ScrollBehaviour,
) -> effect.Effect(message)

Scroll the first element matching selector into view.

See also: scroll_to

pub fn scroll_to(
  x x: Int,
  y y: Int,
  behaviour behaviour: ScrollBehaviour,
) -> effect.Effect(message)

Scroll the window to a specific position.

x and y are pixel offsets from the top-left corner of the document.

See also: window_scroll, scroll_into_view

pub fn server_sent_events(
  url url: String,
  on_open opened: msg,
  on_message message: fn(String, String) -> msg,
  on_error errored: msg,
) -> Subscription(msg)

Subscribe to a Server-Sent Events stream. JS

Opens an EventSource at url and sends on_message(id, data) to your update function for each incoming message. The connection is closed when the subscription is torn down and reopened whenever url changes.

on_open fires on the initial connection and on every successful reconnect. on_error fires when the connection is lost, before the next retry.

pub fn session_storage(
  key key: String,
  send message: fn(option.Option(String)) -> msg,
) -> Subscription(msg)

Dispatch the current value of a sessionStorage key, then again whenever it changes.

Dispatches None when the key is absent and Some(value) otherwise. Only detects changes made in other tabs or windows — updates made in the current page are not forwarded by the browser’s storage event unless set_session_storage is called with notify: True.

See also: local_storage

pub fn set_local_storage(
  key key: String,
  value value: option.Option(String),
  notify notify: Bool,
) -> effect.Effect(message)

Write a value to localStorage, or remove the key when value is None.

When notify is True, a synthetic storage event is dispatched so that local_storage subscriptions are notified of the change immediately.

See also: local_storage, set_session_storage

pub fn set_session_storage(
  key key: String,
  value value: option.Option(String),
  notify notify: Bool,
) -> effect.Effect(message)

Write a value to sessionStorage, or remove the key when value is None.

When notify is True, a synthetic storage event is dispatched so that session_storage subscriptions are notified of the change immediately.

See also: session_storage, set_local_storage

pub fn tailwind_breakpoints(
  send message: fn(TailwindBreakpoint) -> message,
) -> Subscription(message)

Dispatch the current Tailwind CSS breakpoint, then again whenever it changes.

See also: breakpoints, window_size

pub fn throttle(
  subscription: Subscription(message),
  wait duration: duration.Duration,
) -> Subscription(message)

Limit how often a subscription dispatches messages.

When a subscription fires more frequently than duration, intermediate messages are dropped. The first message always passes through immediately.

See also: delay

pub fn title(value value: String) -> Subscription(message)

Update the document <title>.

See also: meta

pub fn update(
  model: Model(model, message),
  message: Message(message),
  subscriptions: fn(model) -> Subscription(message),
  update: fn(model, message) -> #(model, effect.Effect(message)),
) -> #(Model(model, message), effect.Effect(Message(message)))

Handle a message in the subscription runtime.

The low-level counterpart to application, for use when you need to compose off_topic into an existing lustre.application manually.

See also: init, view, application

pub fn view(
  model: Model(model, message),
  view: fn(model) -> element.Element(message),
) -> element.Element(Message(message))

Render the application view through the subscription runtime.

The low-level counterpart to application, for use when you need to compose off_topic into an existing lustre.application manually. On the server target, this also injects the ot-client-runtime web component into the rendered output.

See also: init, update, application

pub fn watch(
  watching dependencies: List(Dependency),
  run callback: fn() -> Nil,
) -> Subscription(message)

Run a side effect whenever dependencies change.

The callback fires once at subscription setup and again whenever any dependency changes.

See also: from, resource

pub fn watching(
  subscription: Subscription(message),
  watching dependencies: List(Dependency),
) -> Subscription(message)

Add extra dependencies to a subscription.

off_topic restarts the subscription whenever any dependency changes. Useful when a subscription’s behaviour depends on model values not captured in its own parameters.

See also: dep, from

pub fn websocket(
  url url: String,
  on_open opened: msg,
  on_message message: fn(WebsocketMessage) -> msg,
  on_error errored: fn(String) -> msg,
) -> Subscription(msg)

Subscribe to a WebSocket connection. JS

Connects to url and dispatches messages for each event. Connections are shared — multiple subscriptions to the same URL reuse a single socket. The socket reconnects automatically it drops, as long as the subscription is alive. The connection is closed when the last subscriber unsubscribes.

on_open fires on the initial connection and on every successful reconnect. on_error fires when the connection is lost, before the next retry.

See also: websocket_send

pub fn websocket_send(
  url url: String,
  data data: WebsocketMessage,
) -> effect.Effect(msg)

Send a frame over an open WebSocket connection. JS

Does nothing if there is no active connection for url or if the socket is not yet open.

See also: websocket

pub fn window_hover(
  send message: fn(Bool) -> msg,
) -> Subscription(msg)

Dispatch the current window hover state, then again whenever it changes.

Only reliable when the window has focus; browsers do not consistently deliver pointer events to unfocused windows.

pub fn window_scroll(
  send message: fn(Int, Int) -> msg,
) -> Subscription(msg)

Dispatch the current scroll position, then again whenever it changes.

pub fn window_size(
  send message: fn(Int, Int) -> msg,
) -> Subscription(msg)

Dispatch the current window size, then again whenever it changes.

See also: breakpoints, tailwind_breakpoints

Search Document