defmodule Surface.Components.Link do @moduledoc """ Generates a link to the given URL. Provides similar capabilities to Phoenix's built-in `link/2` function. Options `label` and `class` can be set directly and will override anything in `opts`. All other options are forwarded to the underlying tag. ## Examples ``` user ``` """ use Surface.Component use Surface.Components.Events import Surface.Components.Utils @doc "The page to link to" prop to, :any, required: true @doc "The method to use with the link" prop method, :atom, default: :get @doc "Id to apply to the link" prop id, :string @doc "Class or classes to apply to the link" prop class, :css_class @doc """ The label for the generated `` element, if no content (default slot) is provided. """ prop label, :string @doc """ Additional attributes to add onto the generated element """ prop opts, :keyword, default: [] @doc """ The content of the generated `` element. If no content is provided, the value of property `label` is used instead. """ slot default def render(assigns) do unless assigns[:default] || assigns[:label] || Keyword.get(assigns.opts, :label) do raise ArgumentError, " requires a label prop or contents in the default slot" end to = valid_destination!(assigns.to, "") events = events_to_opts(assigns) opts = link_method(assigns.method, to, assigns.opts) assigns = assign(assigns, to: to, opts: events ++ opts) ~F""" <#slot>{@label} """ end defp link_method(method, to, opts) do if method == :get do skip_csrf(opts) else {csrf_data, opts} = csrf_data(to, opts) data = opts |> Keyword.get(:data, []) |> Keyword.merge(csrf_data) |> Keyword.merge(method: method, to: to) Keyword.merge(opts, data: data, rel: "nofollow") end end end