Skip to main content

lib/mix/tasks/shadix.init.ex

defmodule Mix.Tasks.Shadix.Init do
  @shortdoc "Initialises Shadix in your Phoenix app (theme CSS + cn helper)"

  @moduledoc """
  Bootstraps Shadix in your Phoenix application by:

  1. Copying `priv/templates/theme.css` to `assets/css/shadix.css`
  2. Installing the `cn` helper module into your components directory
  3. Printing Tailwind `@import` wiring instructions

  ## Usage

      mix shadix.init

  ## Options

    * `--assets-dir` — directory to write `shadix.css` into
      (default: `assets/css`)
    * `--namespace` — base module namespace for components
      (default: `<AppModule>Web.Components.UI`)
    * `--dir` — directory to write component files into
      (default: `lib/<underscored_namespace>`)
    * `--force` — overwrite existing files (default: false)
  """

  use Mix.Task

  @requirements ["app.config"]

  @impl Mix.Task
  def run(args) do
    {opts, _rest, _invalid} =
      OptionParser.parse(args,
        strict: [assets_dir: :string, namespace: :string, dir: :string, force: :boolean]
      )

    namespace = Keyword.get(opts, :namespace) || Shadix.Generator.default_namespace()
    dir = Keyword.get(opts, :dir) || Shadix.Generator.default_dir(namespace)
    assets_dir = Keyword.get(opts, :assets_dir, "assets/css")
    force = Keyword.get(opts, :force, false)

    File.mkdir_p!(dir)
    File.mkdir_p!(assets_dir)

    # 1. Copy theme.css
    theme_source = Application.app_dir(:shadix, "priv/templates/theme.css")
    theme_dest = Path.join(assets_dir, "shadix.css")

    if File.exists?(theme_dest) and not force do
      Mix.shell().info("  skip  #{theme_dest} (already exists; use --force to overwrite)")
    else
      File.copy!(theme_source, theme_dest)
      Mix.shell().info("  write #{theme_dest}")
    end

    # 2. Install cn helper via shadix.add
    Mix.Tasks.Shadix.Add.run(
      ["cn", "--namespace", namespace, "--dir", dir] ++
        if(force, do: ["--force"], else: [])
    )

    # 3. Print Tailwind wiring instructions
    Mix.shell().info("""

    Shadix initialised! Add this import to your app.css (or app entry):

        @import "./shadix.css";

    Then import the cn helper in your components:

        import #{namespace}.Cn
    """)
  end
end