Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
SethHorsley committed Aug 27, 2024
1 parent 20ab060 commit 49a54c1
Show file tree
Hide file tree
Showing 13 changed files with 460 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.DS_Store
node_modules
/app/assets/builds/*
15 changes: 15 additions & 0 deletions lib/generators/rbui/base_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require "rails/generators"

module RBUI
module Generators
class BaseGenerator < defined?(Rails::Generators::Base) ? Rails::Generators::Base : Object
namespace "rbui:base"

source_root File.join(__dir__, "templates")

def copy_templates
template "base_store_initializer.rb", "config/initializers/rbui.rb"
end
end
end
end
43 changes: 43 additions & 0 deletions lib/generators/rbui/component_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# rails g phlex:component alert
module RBUI
module Generators
class BaseGenerator < defined?(Rails::Generators::Base) ? Rails::Generators::Base : Object
namespace "rbui:component"

if defined?(Rails::Generators::Base)
source_root File.expand_path("../../..", __dir__)
argument :component_name, type: :string, required: true

def copy_component_files
component = component_name.downcase
source_path = "lib/rbui"
destination_path = "app/components/phlex_ui"

if File.directory?(File.join(self.class.source_root, source_path, component))
# If it's a directory, copy the entire directory
directory File.join(source_path, component), File.join(destination_path, component)
puts "Copied directory #{component} to #{destination_path}"
elsif File.exist?(File.join(self.class.source_root, source_path, "#{component}.rb"))
# If it's a single file, copy just the file
copy_file File.join(source_path, "base.rb"), File.join(destination_path, "base.rb")
# copy_file File.join(source_path, "attribute_merger.rb"), File.join(destination_path, "attribute_merger.rb")
copy_file File.join(source_path, "#{component}.rb"), File.join(destination_path, "#{component}.rb")
puts "Copied file #{component}.rb to #{destination_path}"
else
puts "Component '#{component}' not found in phlex_ui gem"
end
end

private

def source_path(component)
"lib/phlex_ui/#{component}"
end
else
def copy_component_files
puts "This generator can only be run in a Rails environment."
end
end
end
end
end
47 changes: 47 additions & 0 deletions lib/generators/rbui/install/dev_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
module RBUI
module Generators
module DevHelper
def dev_helper
say "Add index controller"
run "bin/rails generate controller static index --no-helper --no-assets --no-test-framework --no-jbuilder"

say "Add index view"
run "bin/rails g phlex:view Static::Index"

append_to_file "app/controllers/static_controller.rb", after: " def index" do
"\n render Static::IndexView"
end

insert_into_file "app/views/static/index_view.rb", after: " def template\n" do
<<-RUBY
render PhlexUI::Button.new { "click me" }
br {}
# UI.Button { "click me" }
AlertDialog do
AlertDialogTrigger do
Button { "Show dialog" }
end
AlertDialogContent do
AlertDialogHeader do
AlertDialogTitle { "Are you absolutely sure?" }
AlertDialogDescription { "This action cannot be undone. This will permanently delete your account and remove your data from our servers." }
end
AlertDialogFooter do
AlertDialogCancel { "Cancel" }
AlertDialogAction { "Continue" } # Will probably be a link to a controller action (e.g. delete account)
end
end
end
RUBY
end

say "Add index route"
append_to_file "config/routes.rb", after: "Rails.application.routes.draw do" do
"\n root to: \"static#index\"\n"
end
end
end
end
end
112 changes: 112 additions & 0 deletions lib/generators/rbui/install/install_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
require_relative "dev_helper"
require_relative "install_styles"

module RBUI
module Generators
class InstallGenerator < defined?(Rails::Generators::Base) ? Rails::Generators::Base : Object
namespace "rbui:install"

if defined?(Rails::Generators::Base)
source_root File.expand_path("templates", __dir__)

include RBUI::Generators::DevHelper
include RBUI::Generators::InstallStyles

def add_phlex_rails
say "Checking for Phlex Rails"
if gem_installed?("phlex-rails")
say "Phlex Rails is already installed", :green
else
say "Adding Phlex Rails"
run "bundle add phlex-rails"
end

if yes?("Do you want to run the Phlex installer? (y/n)")
say "Run Phlex install"
run "bin/rails generate phlex:install"
end
end

def install_stuff
if yes?("Do you want to set up the dev test data? (y/n)")
dev_helper
end

say "Checking for Tailwind CSS"
if gem_installed?("tailwindcss-rails")
say "Tailwind CSS is already installed", :green

if yes?("Do you want to run the Tailwind installer? (y/n)")
say "Run Tailwind install"
run "./bin/rails tailwindcss:install"
end
elsif yes?("Do you want us to install Tailwind CSS? (y/n)")
say "Adding Tailwind CSS"
run "./bin/bundle add tailwindcss-rails"

say "Run Tailwind install"
run "./bin/rails tailwindcss:install"
end

install_styles
end

def pin_rbui_js
importmap_binstub = Rails.root.join("bin/importmap")
importmap_config_path = Rails.root.join("config/importmap.rb")
stimulus_path = Rails.root.join("app/javascript/application.js")

if importmap_binstub.exist?
say "Pin rbui-js"
append_to_file importmap_config_path do
%(pin "rbui-js", to: "rbui-js.js"\n)
end
else
say "Add rbui-js package"
# run "yarn add rbui-js"
run "yarn add ../phlex_ui"
run "yarn add phlex_ui"
end

if stimulus_path.exist?
say "Add RBUI Stimulus controllers"
append_to_file stimulus_path do
"\nimport \"rbui-js\";\nimport \"phlex_ui\";\n"
end
run "yarn build"
else
say "Default Stimulus location is missing: app/javascript/controllers/index.js", :red
say " Add to your Stimulus index.js:"
say " import \"rbui-js\""
end
end

def include_rbui
say "Add RBUI to your global component layout"
insert_into_file "app/views/application_view.rb", after: "class ApplicationView < ApplicationComponent\n" do
" include RBUI\n include PhlexUI\n"
end
end

else
def self.source_root
File.expand_path("templates", __dir__)
end

def add_stylesheet_link
puts "This generator can only be run in a Rails environment."
end

def revoke
puts "This generator can only be run in a Rails environment."
end
end

private

def gem_installed?(name)
Gem::Specification.find_all_by_name(name).any?
end
end
end
end
158 changes: 158 additions & 0 deletions lib/generators/rbui/install/install_styles.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
module RBUI
module Generators
module InstallStyles
def install_styles
say "Add tailwind animate"
run "yarn add tailwindcss-animate"

say "update tailwind.config.js"
create_file "config/tailwind.config.js", force: true do
<<~JAVASCRIPT
// For importing tailwind styles from phlex_ui/phlex_ui_pro gem
const execSync = require('child_process').execSync;
// Import phlex_ui gem path (To make sure Tailwind loads classes used by phlex_ui gem)
const outputPhlexUI = execSync('bundle show phlex_ui', { encoding: 'utf-8' });
const phlex_ui_path = outputPhlexUI.trim() + '/**/*.rb';
const defaultTheme = require('tailwindcss/defaultTheme')
module.exports = {
darkMode: ["class"],
content: [
'./app/views/**/*.{erb,haml,html,slim,rb}',
'./app/helpers/**/*.rb',
'./app/assets/stylesheets/**/*.css',
'./app/javascript/**/*.js',
phlex_ui_path
],
theme: {
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px",
},
},
extend: {
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
warning: {
DEFAULT: "hsl(var(--warning))",
foreground: "hsl(var(--warning-foreground))",
},
success: {
DEFAULT: "hsl(var(--success))",
foreground: "hsl(var(--success-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
},
borderRadius: {
lg: `var(--radius)`,
md: `calc(var(--radius) - 2px)`,
sm: "calc(var(--radius) - 4px)",
},
fontFamily: {
sans: defaultTheme.fontFamily.sans,
},
},
},
plugins: [
require("tailwindcss-animate"),
],
}
JAVASCRIPT
end

say "Add CSS variables"
create_file "app/assets/stylesheets/application.tailwind.css", force: true do
<<~CSS
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 98%;
--secondary: 0 0% 96.1%;
--secondary-foreground: 0 0% 9%;
--muted: 0 0% 96.1%;
--muted-foreground: 0 0% 45.1%;
--accent: 0 0% 96.1%;
--accent-foreground: 0 0% 9%;
--destructive: 350 89% 60%;
--destructive-foreground: 0 0% 100%;
--warning: 38 92% 50%;
--warning-foreground: 0 0% 100%;
--success: 87 100% 37%;
--success-foreground: 0 0% 100%;
--border: 0 0% 89.8%;
--input: 0 0% 89.8%;
--ring: 0 0% 3.9%;
--radius: 0.5rem;
}
.dark {
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 0 0% 9%;
--secondary: 0 0% 14.9%;
--secondary-foreground: 0 0% 98%;
--muted: 0 0% 14.9%;
--muted-foreground: 0 0% 63.9%;
--accent: 0 0% 14.9%;
--accent-foreground: 0 0% 98%;
--destructive: 350 89% 60%;
--destructive-foreground: 0 0% 100%;
--warning: 38 92% 50%;
--warning-foreground: 0 0% 100%;
--success: 84 81% 44%;
--success-foreground: 0 0% 100%;
--border: 0 0% 14.9%;
--input: 0 0% 14.9%;
--ring: 0 0% 83.1%;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
font-feature-settings: "rlig" 1, "calt" 1;
}
}
CSS
end
end
end
end
end
Empty file.
9 changes: 9 additions & 0 deletions lib/generators/rbui/templates/base_store_initializer.rb.tt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
PhlexUI.setup do |config|
# Setting a namespace allows you to access PhlexUI components through this namespace.
# For example, with namespace set to "UI", you can use:
# UI::Button.new instead of PhlexUI::Button.new
# UI::Card.new instead of PhlexUI::Card.new
# This can help avoid naming conflicts and allows for cleaner, more concise code.
# If you prefer to use PhlexUI components directly, you can leave this unset.
config.namespace = "UI"
end
Loading

0 comments on commit 49a54c1

Please sign in to comment.