Packages
surface
0.6.0
0.12.3
0.12.2
0.12.1
0.12.0
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.1
0.1.0
0.1.0-alpha.2
0.1.0-alpha.1
0.1.0-alpha.0
A component based library for Phoenix LiveView
Current section
Files
Jump to
Current section
Files
lib/surface/component.ex
defmodule Surface.Component do
@moduledoc """
Defines a stateless component.
## Example
defmodule Button do
use Surface.Component
prop click, :event
def render(assigns) do
~F"\""
<button class="button" :on-click={@click}>
<#slot/>
</button>
"\""
end
end
> **Note**: Stateless components cannot handle Phoenix LiveView events.
If you need to handle them, please use a `Surface.LiveComponent` instead.
"""
alias Surface.IOHelper
@callback render(assigns :: Socket.assigns()) :: Phoenix.LiveView.Rendered.t()
defmacro __using__(opts \\ []) do
slot_name = Keyword.get(opts, :slot)
if slot_name do
validate_slot_name!(slot_name, __CALLER__)
end
slot_name = slot_name && String.to_atom(slot_name)
quote do
@before_compile Surface.Renderer
@before_compile unquote(__MODULE__)
use Phoenix.Component
@behaviour unquote(__MODULE__)
use Surface.BaseComponent, type: unquote(__MODULE__)
use Surface.API, include: [:prop, :slot, :data]
import Phoenix.HTML
alias Surface.Components.{Context, Raw}
alias Surface.Components.Dynamic.Component
@doc "Built-in assign"
data inner_block, :fun
if unquote(slot_name) != nil do
Module.put_attribute(__MODULE__, :__slot_name__, unquote(slot_name))
def __slot_name__ do
unquote(slot_name)
end
end
end
end
defp validate_slot_name!(name, caller) do
if !is_binary(name) do
message = "invalid value for option :slot. Expected a string, got: #{inspect(name)}"
IOHelper.compile_error(message, caller.file, caller.line)
end
end
defmacro __before_compile__(env) do
quoted_render(env)
end
defp quoted_render(env) do
if !Module.defines?(env.module, {:__slot_name__, 0}) ||
Module.defines?(env.module, {:render, 1}) do
quote do
@doc false
def __renderless__? do
false
end
end
else
quote do
@doc false
def __renderless__? do
true
end
def render(var!(assigns)) do
~F()
end
end
end
end
end