Packages
phoenix_kit
1.7.125
1.7.208
1.7.207
1.7.206
1.7.205
1.7.204
1.7.203
1.7.202
1.7.201
1.7.200
1.7.199
1.7.198
1.7.197
1.7.196
1.7.194
1.7.193
1.7.192
1.7.191
1.7.190
1.7.189
1.7.187
1.7.186
1.7.185
1.7.184
1.7.183
1.7.182
1.7.181
1.7.180
1.7.179
1.7.178
1.7.177
1.7.176
1.7.175
1.7.174
1.7.173
1.7.172
1.7.171
1.7.170
1.7.169
1.7.168
1.7.167
1.7.166
1.7.165
1.7.164
1.7.162
1.7.161
1.7.160
1.7.159
1.7.157
1.7.156
1.7.155
1.7.154
1.7.153
1.7.152
1.7.151
1.7.150
1.7.149
1.7.146
1.7.145
1.7.144
1.7.143
1.7.138
1.7.133
1.7.132
1.7.131
1.7.130
1.7.128
1.7.126
1.7.125
1.7.121
1.7.120
1.7.119
1.7.118
1.7.117
1.7.116
1.7.115
1.7.114
1.7.113
1.7.112
1.7.111
1.7.110
1.7.109
1.7.108
1.7.107
1.7.106
1.7.105
1.7.104
1.7.103
1.7.102
1.7.101
1.7.100
1.7.99
1.7.98
1.7.97
1.7.96
1.7.95
1.7.94
1.7.93
1.7.92
1.7.91
1.7.90
1.7.89
1.7.88
1.7.87
1.7.86
1.7.85
1.7.84
1.7.83
1.7.82
1.7.81
1.7.80
1.7.79
1.7.78
1.7.77
1.7.76
1.7.75
1.7.74
1.7.71
1.7.70
1.7.69
1.7.66
1.7.65
1.7.64
1.7.63
1.7.62
1.7.61
1.7.59
1.7.58
1.7.57
1.7.56
1.7.55
1.7.54
1.7.53
1.7.52
1.7.51
1.7.49
1.7.44
1.7.43
1.7.42
1.7.41
1.7.39
1.7.38
1.7.37
1.7.36
1.7.34
1.7.33
1.7.31
1.7.30
1.7.29
1.7.28
1.7.27
1.7.26
1.7.25
1.7.24
1.7.23
1.7.22
1.7.21
1.7.20
1.7.19
1.7.18
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.20
1.6.19
1.6.18
1.6.17
1.6.16
1.6.15
1.6.14
1.6.13
1.6.12
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.5.2
1.5.1
1.5.0
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.2
1.3.1
1.3.0
1.2.10
1.2.9
1.2.8
1.2.7
1.2.5
1.2.4
1.2.2
1.2.1
1.2.0
1.1.0
1.0.0
A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more
Current section
Files
Jump to
Current section
Files
lib/phoenix_kit_web/components/media_browser/embed.ex
defmodule PhoenixKitWeb.Components.MediaBrowser.Embed do
@moduledoc """
One-line embedder for `PhoenixKitWeb.Components.MediaBrowser`.
LiveView uploads must live on the parent socket (not the LiveComponent),
so embedding the MediaBrowser requires three small pieces of plumbing on
the parent: an `allow_upload`, a `"validate"` event stub for the upload
channel, and a `handle_info` delegator for component→parent messages.
This module bundles all three into a single `use` call.
## Usage
defmodule MyAppWeb.MediaPage do
use MyAppWeb, :live_view
use PhoenixKitWeb.Components.MediaBrowser.Embed
def mount(_params, _session, socket) do
{:ok, socket}
end
end
Then in the template:
<.live_component
module={PhoenixKitWeb.Components.MediaBrowser}
id="media-browser"
parent_uploads={@uploads}
/>
## What gets injected
* `on_mount` — calls `MediaBrowser.setup_uploads/1` so `@uploads.media_files`
is available on every mount of this LiveView.
* Fallback `handle_event("validate", _, socket)` — absorbs the upload
channel's `phx-change` events. User-defined clauses with other event
names still win because they are defined first.
* Fallback `handle_info({MediaBrowser, _, _}, socket)` — forwards to
`MediaBrowser.handle_parent_info/2` for component registration and
upload piping.
* Fallback `handle_info({:leaf_changed, _}, socket)` — routes
Leaf editor content updates from the sidebar comments (when
PhoenixKitComments is installed) to
`PhoenixKitComments.Web.CommentsComponent.forward_leaf_event/2`.
Without this, comment Leaf editors render but the typed
content never reaches the server. The clause only injects
when `PhoenixKitComments.Web.CommentsComponent` is loaded —
otherwise it's compiled away. User-defined `:leaf_changed`
clauses (e.g. for a post-content editor on the same page)
still win because they are defined first.
All fallbacks are injected via `@before_compile`, so user clauses
declared earlier in the module match before them.
"""
alias PhoenixKitWeb.Components.MediaBrowser
def on_mount(:default, _params, _session, socket) do
{:cont, MediaBrowser.setup_uploads(socket)}
end
defmacro __using__(_opts) do
quote do
on_mount({PhoenixKitWeb.Components.MediaBrowser.Embed, :default})
@before_compile PhoenixKitWeb.Components.MediaBrowser.Embed
end
end
defmacro __before_compile__(_env) do
# Fully-qualified references on purpose: this code is injected into the
# caller's module, where aliasing from Embed wouldn't be in scope.
#
# The leaf-forwarder is always injected (not gated at MACRO-compile
# time on Code.ensure_loaded?) because phoenix_kit_comments may not be
# loaded yet when phoenix_kit compiles — they're sibling deps with no
# compile-order guarantee. Runtime `Code.ensure_loaded?` inside the
# clause does the right thing: when the comments package is installed,
# the event is forwarded; when it isn't, the clause is a no-op.
quote do
require Logger
def handle_event("validate", _params, socket), do: {:noreply, socket}
# credo:disable-for-next-line Credo.Check.Design.AliasUsage
def handle_info(
{PhoenixKitWeb.Components.MediaBrowser, _, _} = msg,
socket
) do
# credo:disable-for-next-line Credo.Check.Design.AliasUsage
PhoenixKitWeb.Components.MediaBrowser.handle_parent_info(msg, socket)
end
def handle_info({:leaf_changed, _} = msg, socket) do
# credo:disable-for-next-line Credo.Check.Design.AliasUsage
mod = PhoenixKitComments.Web.CommentsComponent
if Code.ensure_loaded?(mod) and function_exported?(mod, :forward_leaf_event, 2) do
# `apply/3` (instead of `mod.forward_leaf_event(...)`) so the
# call doesn't compile-time-bind to a module that may not be
# available — phoenix_kit_comments is an optional sibling
# dep with no compile-order guarantee.
# credo:disable-for-next-line Credo.Check.Refactor.Apply
case apply(mod, :forward_leaf_event, [msg, socket]) do
{:noreply, _} = result ->
result
:pass ->
{:noreply, socket}
other ->
# Optional cross-package contract: forward_leaf_event/2 is
# expected to return {:noreply, socket} or :pass. Anything
# else shouldn't crash the host LiveView — degrade gracefully
# and log so a contract drift in phoenix_kit_comments is
# diagnosable.
Logger.warning(
"PhoenixKitComments.Web.CommentsComponent.forward_leaf_event/2 " <>
"returned an unexpected value (#{inspect(other)}); ignoring."
)
{:noreply, socket}
end
else
{:noreply, socket}
end
end
end
end
end