Bonfire.UI.Common (Bonfire v1.0.0-social-rc.1.19)

View Source

A library of common utils and helpers used across Bonfire extensions

  • Many common functions for web UIs
  • Common and generic re-usable components
  • Etc

Handy commands

Copyright (c) 2022 Bonfire Contributors

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://www.gnu.org/licenses/.

Summary

Functions

Like update_many_async/3, but to run several update/preload functions in parallel

Warning: this will set assigns for any/all users who subscribe to them. You want to cast_self/2 instead if dealing with user-specific actions or private data.

Creates a JS command to click all elements matching the specified data-id within a container.

Creates a JS command to click all elements matching the specified data-id within a container.

copies the go param into a query string, if any

Generates a deterministic DOM ID based on component type, object ID, context, and parent ID.

Generate a query string adding a go redirection path to the URI (for redirecting somewhere after auth flows). It is recommended to use set_go_after/2 where possible instead.

Hides element using LiveView JS when connected, vanilla JS when not.

Creates a JavaScript function call that executes LiveView JS when connected, vanilla JS when not.

Combines LiveView JS and vanilla JS into a hybrid command that works whether the socket is connected or not.

Shows element using LiveView JS when connected, vanilla JS when not.

Toggles element visibility using LiveView JS when connected, vanilla JS when not.

Generates vanilla JavaScript for DOM manipulation with optional selector targeting.

Special LiveView helper function which allows loading LiveComponents in regular Phoenix views: live_render_component(@conn, MyLiveComponent)

Inserts one or many items in an existing stream. See Phoenix.LiveView.stream_insert/4 for opts.

Generates a random DOM ID.

Renders a HEEx template inline in a controller.

Subscribe to assigns targeted at the current account/user

Save a go redirection path in the session (for redirecting somewhere after auth flows)

Checks if the socket is connected.

Run a function and expects tuple. If anything else is returned, like an error, a flash message is shown to the user.

Functions

assign_error(socket, msg, pid \\ self())

assign_flash(socket_or_conn, type, message, assigns \\ %{}, pid \\ self())

assign_generic(socket_or_conn, assigns)

assign_generic(socket, key, value)

assign_generic_global(conn, assigns)

assign_global(socket, assigns)

assign_global(socket, key, value)

assigns(socket)

assigns_clean(tuple)

assigns_merge(assigns, new)

assigns_merge(socket, assigns, new)

assigns_minimal(assigns)

assigns_subscribe(socket, assign_names)

batch_update_many_async(assigns_sockets, many_opts, opts)

Like update_many_async/3, but to run several update/preload functions in parallel

batch_update_many_async(current_user, assigns_sockets, many_opts, opts)

can?(subject, verbs, object, opts \\ [])

cast_public(socket, assigns_to_broadcast)

Warning: this will set assigns for any/all users who subscribe to them. You want to cast_self/2 instead if dealing with user-specific actions or private data.

cast_self(socket, assigns_to_broadcast)

click_elements(container_selector, selector \\ "a")

Creates a JS command to click all elements matching the specified data-id within a container.

Parameters

  • container_selector - CSS selector for the container element
  • selector - The type of element or CSS selector to match (defaults to "a")

Example

click_elements_with_data_id("#user_list", "a.follow_button")

click_with_data_id(container_selector, element_type \\ "a", data_id)

Creates a JS command to click all elements matching the specified data-id within a container.

Parameters

  • container_selector - CSS selector for the container element
  • data_id - The value of the data-id attribute to match (eg. "follow")
  • element_type - The type of element to match (defaults to "a")

Example

click_elements_with_data_id("#user_list", "follow", "button")

component_data(module)

component_props(module)

copy_go(arg1)

copies the go param into a query string, if any

current_url(socket_or_assigns, default \\ nil, recursing \\ false)

current_user_or_remote_interaction(socket, verb, object)

declared_extension()

Callback implementation for Bonfire.Common.ExtensionModule.declared_extension/0.

deterministic_dom_id(component_type, object, context \\ nil, parent_id \\ nil)

Generates a deterministic DOM ID based on component type, object ID, context, and parent ID.

Parameters

  • component_type: The type or name of the component
  • object_id: The ID of the object being displayed
  • context: The context where the component is displayed (optional)
  • parent_id: The ID of the parent component (optional)

Returns

A string with format: component_type_context_object_id_parent_id

Examples

iex> deterministic_dom_id("modal", "post123", "feed", "container456")
"modal_feed_post123_container456"

iex> deterministic_dom_id("dropdown", "user789")
"dropdown_user789"

filename_for_module_template(module)

go_query(url)

Generate a query string adding a go redirection path to the URI (for redirecting somewhere after auth flows). It is recommended to use set_go_after/2 where possible instead.

hero_icons_list()

js_hide(opts \\ [])

Hides element using LiveView JS when connected, vanilla JS when not.

Options

Same as Phoenix.LiveView.JS.hide/1:

  • :to - DOM selector to hide. Defaults to the clicked element.

Examples

<button onclick={js_hide()}>Hide self</button>
<button onclick={js_hide(to: "#error")}>Hide error</button>

js_hybrid(lv_js, vanilla_js)

Creates a JavaScript function call that executes LiveView JS when connected, vanilla JS when not.

Escapes quotes in both JS strings and wraps them in a JS_exec.call() function.

Parameters

  • lv_js - A Phoenix.LiveView.JS command or encoded string
  • vanilla_js - A vanilla JavaScript string

js_hybrid_action(lv_js, vanilla_js, opts)

Combines LiveView JS and vanilla JS into a hybrid command that works whether the socket is connected or not.

Takes a LiveView JS command and vanilla JS action with options, then creates a hybrid function call.

Parameters

  • lv_js - A Phoenix.LiveView.JS command
  • vanilla_js - A string representing the vanilla JS action (e.g., "toggle('hidden')")
  • opts - Options including :to selector

js_show(opts \\ [])

Shows element using LiveView JS when connected, vanilla JS when not.

Options

Same as Phoenix.LiveView.JS.show/1:

  • :to - DOM selector to show. Defaults to the clicked element.

Examples

<button onclick={js_show()}>Show self</button>
<button onclick={js_show(to: "#modal")}>Show modal</button>

js_toggle(opts \\ [])

Toggles element visibility using LiveView JS when connected, vanilla JS when not.

Options

Same as Phoenix.LiveView.JS.toggle/1:

  • :to - DOM selector to toggle. Defaults to the clicked element.

Examples

<button onclick={js_toggle()}>Toggle self</button>
<button onclick={js_toggle(to: "#content")}>Toggle content</button>

js_vanilla_action(action, opts)

Generates vanilla JavaScript for DOM manipulation with optional selector targeting.

Creates JavaScript that either operates on the current element (this) or targets elements via querySelector.

Parameters

  • action - The classList action to perform (e.g., "toggle('hidden')", "add('active')")
  • opts - Options including :to for element selector

Examples

iex> js_vanilla_action("toggle('hidden')", [])
"this.classList.toggle('hidden')"

iex> js_vanilla_action("add('active')", to: "#button")
"document.querySelectorAll('#button').forEach(el => el.classList.add('active'))"

iex> js_vanilla_action("remove('disabled')", to: ".form-input")
"document.querySelectorAll('.form-input').forEach(el => el.classList.remove('disabled'))"

live_aliases(aliases, path, live_view, action \\ nil, opts \\ [])

(macro)

live_render_component(conn, load_live_component)

Special LiveView helper function which allows loading LiveComponents in regular Phoenix views: live_render_component(@conn, MyLiveComponent)

TODO: deduplicate if same as render_inline

live_render_with_conn(conn, live_view)

live_upload_files(module \\ nil, upload_field \\ :files, current_user, metadata, socket)

markdown(content)

maybe_apply_or_ret(assigns, mod, fun)

maybe_assign(socket, key, value)

maybe_assign_context(socket, ret)

maybe_component(module, context \\ [])

maybe_consume_uploaded_entries(socket, key, fun)

maybe_consume_uploaded_entry(socket, key, fun)

maybe_cute_gif()

maybe_last_sentry_event_id()

maybe_push_event(socket, name, data)

maybe_send_update(component, id, assigns, opts \\ [])

maybe_stream_insert(socket, name, items, opts)

Inserts one or many items in an existing stream. See Phoenix.LiveView.stream_insert/4 for opts.

module_default_assigns(module)

opts_for_update_many_async(arg, opts)

patch_to(socket_or_conn, to \\ nil, opts \\ [])

path_fallback(socket_or_conn, opts)

random_dom_id()

Generates a random DOM ID.

DEPRECATED: Use deterministic_dom_id/4 instead for consistent IDs across renders.

redirect_self(to)

redirect_to(socket_or_conn, to \\ nil, opts \\ [])

redirect_to_previous_go(conn, params, default, current_path)

render_inline(conn, template)

(macro)

Renders a HEEx template inline in a controller.

Example

use Bonfire.UI.Common.Web, :controller
use Phoenix.Component

def index(conn, _) do
  render_inline conn, ~H"<u><%= @current_user.name %></u>"
end

render_sface_or_native(opts \\ [])

(macro)

rich(content, opts \\ [])

self_subscribe(socket, assign_names)

Subscribe to assigns targeted at the current account/user

send_self(socket \\ nil, assigns)

send_self_global(socket \\ nil, assigns)

set_go_after(conn, path \\ nil)

Save a go redirection path in the session (for redirecting somewhere after auth flows)

socket_connected?(socket)

Checks if the socket is connected.

Examples

iex> socket_connected?(%{socket_connected?: true})
true

iex> socket_connected?(%{socket_connected?: false})
false

iex> socket_connected?(%{__context__: %{socket_connected?: true}})
true

iex> socket_connected?(%Phoenix.LiveView.Socket{transport_pid: 1})
true

iex> socket_connected?(%Phoenix.LiveView.Socket{transport_pid: nil})
false

templated(content, data \\ %{})

templated_or_remote_markdown(content, data \\ nil)

the_object(assigns)

undead_mount(socket, fun)

Run a function and expects tuple. If anything else is returned, like an error, a flash message is shown to the user.

undead_on_mount(socket, fun)

undead_render(assigns, fun)

undead_update(socket, fun)

uniq_assign(list_of_components, field)

update_many_async(assigns_sockets, opts)

update_many_async(current_user, assigns_sockets, opts)

user_socket_connected?(socket_or_assigns)