Skip to content

Commit

Permalink
Add manual component installation instructions (#142)
Browse files Browse the repository at this point in the history
  • Loading branch information
stephannv authored Nov 21, 2024
1 parent 3a068ff commit 48bc8af
Show file tree
Hide file tree
Showing 4 changed files with 270 additions and 32 deletions.
39 changes: 8 additions & 31 deletions app/components/component_setup/cli_steps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,39 +12,16 @@ def initialize(component_name:)
def view_template
div(class: "max-w-2xl mx-auto w-full py-10 space-y-6") do
Heading(level: 4, class: "pb-4 border-b") { "Using RubyUI CLI" }
Text do
"We provide a Ruby gem with useful generators to help you to setup RubyUI components in your apps."
end

render Steps::Builder.new do |steps|
steps.add_step do
render Steps::Container do
Text(size: "4", weight: "semibold") do
plain "Add RubyUI gem to your Gemfile if you don't have it yet"
end

code = <<~CODE
bundle add ruby_ui --group development --require false
CODE
div(class: "w-full") do
Codeblock(code, syntax: :javascript)
end
end
end
steps.add_step do
render Steps::Container do
Text(size: "4", weight: "semibold") do
"Run the install command"
end
Text(size: "4", weight: "semibold") do
"Run the install command"
end

code = <<~CODE
rails g ruby_ui:component #{component_name.camelcase}
CODE
div(class: "w-full") do
Codeblock(code, syntax: :javascript)
end
end
end
code = <<~CODE
rails g ruby_ui:component #{component_name.camelcase}
CODE
div(class: "w-full") do
Codeblock(code, syntax: :javascript)
end
end
end
Expand Down
220 changes: 220 additions & 0 deletions app/components/component_setup/manual_steps.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
module Components
module ComponentSetup
class ManualSteps < Components::Base
def initialize(component_name:)
@component_name = component_name
@dependencies = RubyUI::FileManager.dependencies(@component_name)
end

private

attr_reader :component_name, :dependencies

def view_template
div(class: "max-w-2xl mx-auto w-full py-10 space-y-6") do
Heading(level: 4, class: "pb-4 border-b") { "Manual installation" }

render Steps::Builder.new do |steps|
main_component_step(steps)
related_component_steps(steps)
stimulus_controller_steps(steps)
js_dependencies_steps(steps)
ruby_dependencies_steps(steps)
component_dependencies_steps(steps)
end
end
end

def main_component_step(steps)
main_component_code = RubyUI::FileManager.main_component_code(component_name)

return if main_component_code.blank?

steps.add_step do
render Steps::Container do
Text(size: "4", weight: "semibold") do
plain "Add "
InlineCode(class: "whitespace-nowrap") { "RubyUI::#{component_name.camelcase}" }
plain " to "
InlineCode(class: "whitespace-nowrap") { "app/components/ruby_ui/#{component_name.underscore}.rb" }
end

div(class: "w-full") do
Codeblock(main_component_code, syntax: :ruby)
end
end
end
end

def related_component_steps(steps)
related_component_file_paths = RubyUI::FileManager.related_component_file_paths(component_name)

return if related_component_file_paths.empty?

related_component_file_paths.each do |component_path|
related_component_class = component_path.split("/").last.delete_suffix(".rb").camelcase
related_component_file_name = component_path.split("/").last
related_component_code = RubyUI::FileManager.component_code(component_path)
steps.add_step do
render Steps::Container do
Text(size: "4", weight: "semibold") do
plain "Add "
InlineCode(class: "whitespace-nowrap") { "RubyUI::#{related_component_class}" }
plain " to "
InlineCode(class: "whitespace-nowrap") { "app/components/ruby_ui/#{component_name.underscore}/#{related_component_file_name}" }
end

div(class: "w-full") do
Codeblock(related_component_code, syntax: :ruby)
end
end
end
end
end

def stimulus_controller_steps(steps)
stimulus_controller_file_paths = RubyUI::FileManager.stimulus_controller_file_paths(component_name)

return if stimulus_controller_file_paths.empty?

stimulus_controller_file_paths.each do |controller_path|
controller_file_name = controller_path.split("/").last
controller_code = RubyUI::FileManager.component_code(controller_path)
steps.add_step do
render Steps::Container do
Text(size: "4", weight: "semibold") do
plain "Add "
InlineCode(class: "whitespace-nowrap") { controller_file_name }
plain " to "
InlineCode(class: "whitespace-nowrap") { "app/javascript/controllers/ruby_ui/#{controller_file_name}" }
end

div(class: "w-full") do
Codeblock(controller_code, syntax: :javascript)
end
end
end
end

steps.add_step do
render Steps::Container do
Text(size: "4", weight: "semibold") do
plain "Update the Stimulus controllers manifest file"
end

Alert(variant: :destructive) do
AlertTitle { "Importmap!" }
AlertDescription { "You don't need to run this command if you are using Importmap" }
end

div(class: "w-full") do
Codeblock("rake stimulus:manifest:update", syntax: :javascript)
end
end
end
end

def js_dependencies_steps(steps)
return unless dependencies["js_packages"].present?

dependencies["js_packages"].each do |js_package|
steps.add_step do
code = <<~CODE
// with yarn
yarn add #{js_package}
// with npm
npm install #{js_package}
// with importmaps
#{pin_importmap_instructions(js_package)}
CODE

render Steps::Container do
Text(size: "4", weight: "semibold") do
plain "Install "
InlineCode(class: "whitespace-nowrap") { js_package }
plain " Javascript dependency"
end

div(class: "w-full") do
Codeblock(code, syntax: :javascript)
end
end
end
end
end

def ruby_dependencies_steps(steps)
return unless dependencies["gems"].present?

dependencies["gems"].each do |gem|
steps.add_step do
code = <<~CODE
bundle add #{gem}
CODE

render Steps::Container do
Text(size: "4", weight: "semibold") do
plain "Install "
InlineCode(class: "whitespace-nowrap") { gem }
plain " Ruby gem"
end

div(class: "w-full") do
Codeblock(code, syntax: :javascript)
end
end
end
end
end

def component_dependencies_steps(steps)
return unless dependencies["components"].present?

steps.add_step do
render Steps::Container do
Text(size: "4", weight: "semibold") do
plain "Install required components"
end

Text do
plain "Component "
InlineCode(class: "whitespace-nowrap") { component_name.camelcase }
plain " relies on the following RubyUI components. Refer to their individual installation guides for setup instructions:"
end

TypographyList do
dependencies["components"].each do |component|
TypographyListItem do
Link(size: :lg, target: "_blank", href: public_send(:"docs_#{component.underscore}_path")) do
span(class: "font-bold") { component.camelcase }
span { " - Installation guide" }
end
end
end
end
end
end
end

# Temporary solution while we don't remove
# motion adn tippy.js dependencies
def pin_importmap_instructions(js_package)
case js_package
when "motion"
<<~CODE
// Add to your config/importmap.rb
pin "motion", to: "https://cdn.jsdelivr.net/npm/[email protected]/+esm"
CODE
when "tippy.js"
<<~CODE
// Add to your config/importmap.rb
pin "tippy.js", to: "https://cdn.jsdelivr.net/npm/[email protected]/+esm"
pin "@popperjs/core", to: "https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/+esm"\n
CODE
else
"bin/importmap pin #{js_package}"
end
end
end
end
end
2 changes: 1 addition & 1 deletion app/components/component_setup/tabs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def view_template
end

TabsContent(value: "manual") do
Text { "Coming soon" }
render ManualSteps.new(component_name:)
end
end
end
Expand Down
41 changes: 41 additions & 0 deletions app/lib/ruby_ui/file_manager.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module RubyUI
module FileManager
extend self

def main_component_code(component_name)
component_code main_component_file_path(component_name)
end

def component_code(file_path)
File.read(file_path) if File.exist?(file_path)
end

def main_component_file_path(component_name)
component_name = component_name.underscore
File.join(component_folder(component_name), "#{component_name}.rb")
end

def related_component_file_paths(component_name)
Dir[File.join(component_folder(component_name), "*.rb")] - [main_component_file_path(component_name)]
end

def stimulus_controller_file_paths(component_name)
Dir[File.join(component_folder(component_name), "*.js")]
end

def component_folder(component_name)
component_name = component_name.underscore
File.join(gem_path, "lib", "ruby_ui", component_name)
end

def dependencies(component_name)
DEPENDENCIES[component_name.underscore].to_h
end

def gem_path
@gem_path ||= Gem::Specification.find_by_name("ruby_ui").gem_dir
end

DEPENDENCIES = YAML.load_file(File.join(gem_path, "lib/generators/ruby_ui/dependencies.yml")).freeze
end
end

0 comments on commit 48bc8af

Please sign in to comment.