shadcn-rails 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +66 -2
- data/README.md +21 -8
- data/__mocks__/@floating-ui/dom.js +67 -0
- data/app/assets/javascripts/shadcn/controllers/combobox_controller.js +23 -2
- data/app/assets/javascripts/shadcn/controllers/context_menu_controller.js +4 -31
- data/app/assets/javascripts/shadcn/controllers/dropdown_controller.js +32 -41
- data/app/assets/javascripts/shadcn/controllers/hover_card_controller.js +29 -55
- data/app/assets/javascripts/shadcn/controllers/popover_controller.js +29 -54
- data/app/assets/javascripts/shadcn/controllers/select_controller.js +26 -8
- data/app/assets/javascripts/shadcn/controllers/tooltip_controller.js +28 -59
- data/app/assets/javascripts/shadcn/index.js +7 -1
- data/app/assets/javascripts/shadcn/utils/floating.js +179 -0
- data/app/assets/stylesheets/shadcn/base.css +32 -0
- data/app/components/shadcn/accordion_component.html.erb +8 -0
- data/app/components/shadcn/accordion_component.rb +6 -15
- data/app/components/shadcn/alert_component.html.erb +6 -0
- data/app/components/shadcn/alert_component.rb +0 -18
- data/app/components/shadcn/alert_dialog_component.html.erb +12 -0
- data/app/components/shadcn/alert_dialog_component.rb +7 -27
- data/app/components/shadcn/aspect_ratio_component.html.erb +7 -0
- data/app/components/shadcn/aspect_ratio_component.rb +4 -19
- data/app/components/shadcn/avatar_component.html.erb +20 -0
- data/app/components/shadcn/avatar_component.rb +8 -36
- data/app/components/shadcn/badge_component.html.erb +1 -0
- data/app/components/shadcn/badge_component.rb +0 -11
- data/app/components/shadcn/base_component.rb +15 -2
- data/app/components/shadcn/breadcrumb_component.html.erb +5 -0
- data/app/components/shadcn/breadcrumb_component.rb +6 -16
- data/app/components/shadcn/button_component.html.erb +18 -0
- data/app/components/shadcn/button_component.rb +1 -41
- data/app/components/shadcn/card_component.html.erb +8 -0
- data/app/components/shadcn/card_component.rb +2 -6
- data/app/components/shadcn/checkbox_component.html.erb +32 -0
- data/app/components/shadcn/checkbox_component.rb +4 -43
- data/app/components/shadcn/collapsible_component.html.erb +8 -0
- data/app/components/shadcn/collapsible_component.rb +6 -15
- data/app/components/shadcn/context_menu_component.html.erb +11 -0
- data/app/components/shadcn/context_menu_component.rb +6 -26
- data/app/components/shadcn/dialog_component.html.erb +14 -0
- data/app/components/shadcn/dialog_component.rb +8 -29
- data/app/components/shadcn/drawer_component.html.erb +12 -0
- data/app/components/shadcn/drawer_component.rb +7 -27
- data/app/components/shadcn/dropdown_menu_component.html.erb +14 -0
- data/app/components/shadcn/dropdown_menu_component.rb +9 -29
- data/app/components/shadcn/field_component.rb +7 -8
- data/app/components/shadcn/hover_card_component.html.erb +12 -0
- data/app/components/shadcn/hover_card_component.rb +7 -26
- data/app/components/shadcn/input_component.html.erb +18 -0
- data/app/components/shadcn/input_component.rb +2 -27
- data/app/components/shadcn/input_otp_component.rb +3 -3
- data/app/components/shadcn/kbd_component.html.erb +1 -0
- data/app/components/shadcn/kbd_component.rb +3 -10
- data/app/components/shadcn/label_component.html.erb +3 -0
- data/app/components/shadcn/label_component.rb +2 -18
- data/app/components/shadcn/menubar_component.html.erb +6 -0
- data/app/components/shadcn/menubar_component.rb +4 -15
- data/app/components/shadcn/native_select_component.html.erb +22 -0
- data/app/components/shadcn/native_select_component.rb +9 -39
- data/app/components/shadcn/navigation_menu_component.html.erb +6 -0
- data/app/components/shadcn/navigation_menu_component.rb +4 -15
- data/app/components/shadcn/pagination_component.html.erb +5 -0
- data/app/components/shadcn/pagination_component.rb +11 -15
- data/app/components/shadcn/popover_component.html.erb +15 -0
- data/app/components/shadcn/popover_component.rb +10 -30
- data/app/components/shadcn/progress_component.html.erb +13 -0
- data/app/components/shadcn/progress_component.rb +6 -26
- data/app/components/shadcn/radio_group_component.html.erb +8 -0
- data/app/components/shadcn/radio_group_component.rb +12 -26
- data/app/components/shadcn/scroll_area_component.html.erb +7 -0
- data/app/components/shadcn/scroll_area_component.rb +4 -16
- data/app/components/shadcn/select_component.html.erb +46 -0
- data/app/components/shadcn/select_component.rb +6 -80
- data/app/components/shadcn/separator_component.html.erb +5 -0
- data/app/components/shadcn/separator_component.rb +6 -14
- data/app/components/shadcn/sheet_component.html.erb +12 -0
- data/app/components/shadcn/sheet_component.rb +7 -27
- data/app/components/shadcn/sidebar_component.rb +2 -2
- data/app/components/shadcn/skeleton_component.html.erb +1 -0
- data/app/components/shadcn/skeleton_component.rb +4 -2
- data/app/components/shadcn/slider_component.html.erb +12 -0
- data/app/components/shadcn/slider_component.rb +2 -21
- data/app/components/shadcn/spinner_component.html.erb +18 -0
- data/app/components/shadcn/spinner_component.rb +2 -30
- data/app/components/shadcn/switch_component.html.erb +72 -0
- data/app/components/shadcn/switch_component.rb +4 -82
- data/app/components/shadcn/table_component.html.erb +9 -0
- data/app/components/shadcn/table_component.rb +2 -10
- data/app/components/shadcn/tabs_component.html.erb +8 -0
- data/app/components/shadcn/tabs_component.rb +4 -17
- data/app/components/shadcn/textarea_component.html.erb +13 -0
- data/app/components/shadcn/textarea_component.rb +6 -22
- data/app/components/shadcn/toast_component.html.erb +36 -0
- data/app/components/shadcn/toast_component.rb +6 -54
- data/app/components/shadcn/toggle_component.html.erb +12 -0
- data/app/components/shadcn/toggle_component.rb +6 -21
- data/app/components/shadcn/toggle_group_component.html.erb +14 -0
- data/app/components/shadcn/toggle_group_component.rb +6 -29
- data/app/components/shadcn/tooltip_component.html.erb +20 -0
- data/app/components/shadcn/tooltip_component.rb +13 -38
- data/lib/generators/shadcn/add/USAGE +24 -0
- data/lib/generators/shadcn/add/add_generator.rb +279 -0
- data/lib/generators/shadcn/install/USAGE +22 -0
- data/lib/generators/shadcn/install/install_generator.rb +8 -3
- data/lib/generators/shadcn/install/templates/initializer.rb.tt +7 -27
- data/lib/generators/shadcn/install/templates/shadcn.yml.tt +15 -31
- data/lib/shadcn/rails/version.rb +1 -1
- metadata +47 -45
- data/.dockerignore +0 -40
- data/CLAUDE.md +0 -612
- data/PROGRESS.md +0 -495
- data/Rakefile +0 -95
- data/__tests__/controllers/__snapshots__/calendar_controller.test.js.snap +0 -13
- data/__tests__/controllers/__snapshots__/popover_controller.test.js.snap +0 -46
- data/__tests__/controllers/__snapshots__/sheet_controller.test.js.snap +0 -111
- data/__tests__/controllers/__snapshots__/tabs_controller.test.js.snap +0 -27
- data/__tests__/controllers/accordion_controller.test.js +0 -904
- data/__tests__/controllers/calendar_controller.test.js +0 -1370
- data/__tests__/controllers/carousel_controller.test.js +0 -912
- data/__tests__/controllers/checkbox_controller.test.js +0 -454
- data/__tests__/controllers/collapsible_controller.test.js +0 -407
- data/__tests__/controllers/combobox_controller.test.js +0 -971
- data/__tests__/controllers/context_menu_controller.test.js +0 -905
- data/__tests__/controllers/date_picker_controller.test.js +0 -636
- data/__tests__/controllers/dialog_controller.test.js +0 -878
- data/__tests__/controllers/drawer_controller.test.js +0 -995
- data/__tests__/controllers/menubar_controller.test.js +0 -737
- data/__tests__/controllers/navigation_menu_controller.test.js +0 -599
- data/__tests__/controllers/popover_controller.test.js +0 -982
- data/__tests__/controllers/radio_group_controller.test.js +0 -640
- data/__tests__/controllers/resizable_controller.test.js +0 -680
- data/__tests__/controllers/select_controller.test.js +0 -678
- data/__tests__/controllers/sheet_controller.test.js +0 -986
- data/__tests__/controllers/slider_controller.test.js +0 -1036
- data/__tests__/controllers/switch_controller.test.js +0 -424
- data/__tests__/controllers/tabs_controller.test.js +0 -907
- data/__tests__/controllers/toggle_group_controller.test.js +0 -839
- data/__tests__/controllers/tooltip_controller.test.js +0 -808
- data/__tests__/helpers/stimulus-test-helper.js +0 -203
- data/babel.config.cjs +0 -5
- data/bin/bump +0 -321
- data/bin/console +0 -11
- data/bin/release +0 -205
- data/bin/setup +0 -8
- data/bin/test +0 -75
- data/jest.config.js +0 -19
- data/jest.setup.js +0 -8
- data/lib/generators/shadcn/component/component_generator.rb +0 -188
- data/lib/generators/shadcn/theme/theme_generator.rb +0 -128
- data/package-lock.json +0 -7438
- data/package.json +0 -71
- data/rollup.config.js +0 -29
data/bin/release
DELETED
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
# Release script for shadcn-rails
|
|
5
|
-
# Publishes both Ruby gem and npm package
|
|
6
|
-
#
|
|
7
|
-
# Usage:
|
|
8
|
-
# bin/release # Release current version
|
|
9
|
-
# bin/release --dry-run # Show what would be released without publishing
|
|
10
|
-
|
|
11
|
-
require "json"
|
|
12
|
-
require "open3"
|
|
13
|
-
|
|
14
|
-
VERSION_FILE = File.expand_path("../lib/shadcn/rails/version.rb", __dir__)
|
|
15
|
-
PACKAGE_JSON = File.expand_path("../package.json", __dir__)
|
|
16
|
-
GEMSPEC_FILE = File.expand_path("../shadcn-rails.gemspec", __dir__)
|
|
17
|
-
|
|
18
|
-
class Release
|
|
19
|
-
def initialize(dry_run: false)
|
|
20
|
-
@dry_run = dry_run
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def run
|
|
24
|
-
puts "\n🚀 shadcn-rails Release\n"
|
|
25
|
-
puts "=" * 50
|
|
26
|
-
|
|
27
|
-
check_clean_working_directory
|
|
28
|
-
check_versions_in_sync
|
|
29
|
-
run_tests
|
|
30
|
-
build_packages
|
|
31
|
-
publish_packages unless @dry_run
|
|
32
|
-
create_github_release unless @dry_run
|
|
33
|
-
|
|
34
|
-
puts "\n✅ Release complete!"
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
private
|
|
38
|
-
|
|
39
|
-
def ruby_version
|
|
40
|
-
content = File.read(VERSION_FILE)
|
|
41
|
-
content.match(/VERSION = "(.+?)"/)[1]
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def npm_version
|
|
45
|
-
package = JSON.parse(File.read(PACKAGE_JSON))
|
|
46
|
-
package["version"]
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def check_clean_working_directory
|
|
50
|
-
step "Checking working directory"
|
|
51
|
-
|
|
52
|
-
status, = run_command("git status --porcelain")
|
|
53
|
-
unless status.empty?
|
|
54
|
-
error "Working directory is not clean. Please commit or stash changes."
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
success "Working directory is clean"
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def check_versions_in_sync
|
|
61
|
-
step "Checking version sync"
|
|
62
|
-
|
|
63
|
-
rv = ruby_version
|
|
64
|
-
nv = npm_version
|
|
65
|
-
|
|
66
|
-
if rv != nv
|
|
67
|
-
error "Versions are out of sync!\n Ruby: #{rv}\n npm: #{nv}\n\nRun: bin/bump-version #{rv}"
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
@version = rv
|
|
71
|
-
success "Versions in sync: #{@version}"
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def run_tests
|
|
75
|
-
step "Running tests"
|
|
76
|
-
|
|
77
|
-
_, success = run_command("bin/test", stream: true)
|
|
78
|
-
error "Tests failed" unless success
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def build_packages
|
|
82
|
-
step "Building packages"
|
|
83
|
-
|
|
84
|
-
# Build npm package
|
|
85
|
-
puts " Building npm package..."
|
|
86
|
-
_, success = run_command("npm run build")
|
|
87
|
-
error "npm build failed" unless success
|
|
88
|
-
|
|
89
|
-
# Build gem
|
|
90
|
-
puts " Building gem..."
|
|
91
|
-
_, success = run_command("gem build #{GEMSPEC_FILE}")
|
|
92
|
-
error "gem build failed" unless success
|
|
93
|
-
|
|
94
|
-
@gem_file = "shadcn-rails-#{@version}.gem"
|
|
95
|
-
unless File.exist?(@gem_file)
|
|
96
|
-
error "Gem file not found: #{@gem_file}"
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
success "Packages built successfully"
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def publish_packages
|
|
103
|
-
step "Publishing packages"
|
|
104
|
-
|
|
105
|
-
# Publish to RubyGems
|
|
106
|
-
puts " Publishing to RubyGems..."
|
|
107
|
-
_, success = run_command("gem push #{@gem_file}")
|
|
108
|
-
unless success
|
|
109
|
-
puts " ⚠️ Failed to publish gem (may need: gem signin)"
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
# Publish to npm
|
|
113
|
-
puts " Publishing to npm..."
|
|
114
|
-
_, success = run_command("npm publish")
|
|
115
|
-
unless success
|
|
116
|
-
puts " ⚠️ Failed to publish to npm (may need: npm login)"
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
# Clean up gem file
|
|
120
|
-
File.delete(@gem_file) if File.exist?(@gem_file)
|
|
121
|
-
|
|
122
|
-
success "Packages published"
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
def create_github_release
|
|
126
|
-
step "Creating GitHub release"
|
|
127
|
-
|
|
128
|
-
# Check if gh CLI is available
|
|
129
|
-
_, success = run_command("which gh")
|
|
130
|
-
unless success
|
|
131
|
-
puts " ⚠️ GitHub CLI not found. Skipping GitHub release."
|
|
132
|
-
puts " Install with: brew install gh"
|
|
133
|
-
return
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
# Create tag if it doesn't exist
|
|
137
|
-
tag = "v#{@version}"
|
|
138
|
-
_, tag_exists = run_command("git rev-parse #{tag}")
|
|
139
|
-
|
|
140
|
-
unless tag_exists
|
|
141
|
-
puts " Creating tag #{tag}..."
|
|
142
|
-
run_command("git tag #{tag}")
|
|
143
|
-
run_command("git push origin #{tag}")
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
# Create GitHub release
|
|
147
|
-
puts " Creating GitHub release..."
|
|
148
|
-
changelog_section = extract_changelog_section
|
|
149
|
-
|
|
150
|
-
run_command(%(gh release create #{tag} --title "v#{@version}" --notes "#{changelog_section}" #{@gem_file}))
|
|
151
|
-
|
|
152
|
-
success "GitHub release created"
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
def extract_changelog_section
|
|
156
|
-
return "Release v#{@version}" unless File.exist?("CHANGELOG.md")
|
|
157
|
-
|
|
158
|
-
content = File.read("CHANGELOG.md")
|
|
159
|
-
# Extract section for current version
|
|
160
|
-
match = content.match(/## \[#{Regexp.escape(@version)}\].*?\n(.*?)(?=\n## \[|$)/m)
|
|
161
|
-
match ? match[1].strip : "Release v#{@version}"
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
def step(message)
|
|
165
|
-
puts "\n📦 #{message}..."
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
def success(message)
|
|
169
|
-
puts " ✓ #{message}"
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
def error(message)
|
|
173
|
-
puts "\n❌ Error: #{message}"
|
|
174
|
-
exit 1
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
def run_command(cmd, stream: false)
|
|
178
|
-
if @dry_run && cmd.match?(/gem push|npm publish|gh release|git tag|git push/)
|
|
179
|
-
puts " [DRY RUN] Would run: #{cmd}"
|
|
180
|
-
return ["", true]
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
if stream
|
|
184
|
-
success = system(cmd)
|
|
185
|
-
["", success]
|
|
186
|
-
else
|
|
187
|
-
output, status = Open3.capture2e(cmd)
|
|
188
|
-
[output.strip, status.success?]
|
|
189
|
-
end
|
|
190
|
-
end
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
# Parse arguments
|
|
194
|
-
dry_run = ARGV.include?("--dry-run")
|
|
195
|
-
|
|
196
|
-
if ARGV.include?("--help") || ARGV.include?("-h")
|
|
197
|
-
puts "Usage: bin/release [options]"
|
|
198
|
-
puts ""
|
|
199
|
-
puts "Options:"
|
|
200
|
-
puts " --dry-run Show what would be released without publishing"
|
|
201
|
-
puts " --help Show this help message"
|
|
202
|
-
exit 0
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
Release.new(dry_run: dry_run).run
|
data/bin/setup
DELETED
data/bin/test
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
# Run all tests (Ruby and JavaScript)
|
|
5
|
-
#
|
|
6
|
-
# Usage:
|
|
7
|
-
# bin/test # Run all tests
|
|
8
|
-
# bin/test ruby # Run only Ruby tests
|
|
9
|
-
# bin/test js # Run only JavaScript tests
|
|
10
|
-
|
|
11
|
-
require "open3"
|
|
12
|
-
|
|
13
|
-
class TestRunner
|
|
14
|
-
def initialize(filter: nil)
|
|
15
|
-
@filter = filter
|
|
16
|
-
@failed = false
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def run
|
|
20
|
-
puts "\n🧪 Running tests\n"
|
|
21
|
-
puts "=" * 50
|
|
22
|
-
|
|
23
|
-
run_ruby_tests if @filter.nil? || @filter == "ruby"
|
|
24
|
-
run_js_tests if @filter.nil? || @filter == "js"
|
|
25
|
-
|
|
26
|
-
puts "\n" + "=" * 50
|
|
27
|
-
if @failed
|
|
28
|
-
puts "❌ Some tests failed"
|
|
29
|
-
exit 1
|
|
30
|
-
else
|
|
31
|
-
puts "✅ All tests passed"
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
private
|
|
36
|
-
|
|
37
|
-
def run_ruby_tests
|
|
38
|
-
step "Ruby tests"
|
|
39
|
-
success = system("bundle exec rake test")
|
|
40
|
-
@failed = true unless success
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def run_js_tests
|
|
44
|
-
step "JavaScript tests"
|
|
45
|
-
success = system("npm test")
|
|
46
|
-
@failed = true unless success
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def step(name)
|
|
50
|
-
puts "\n→ #{name}\n\n"
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# Parse arguments
|
|
55
|
-
filter = case ARGV[0]
|
|
56
|
-
when "ruby", "rb"
|
|
57
|
-
"ruby"
|
|
58
|
-
when "js", "javascript", "node"
|
|
59
|
-
"js"
|
|
60
|
-
when "-h", "--help"
|
|
61
|
-
puts "Usage: bin/test [ruby|js]"
|
|
62
|
-
puts ""
|
|
63
|
-
puts " bin/test Run all tests"
|
|
64
|
-
puts " bin/test ruby Run only Ruby tests"
|
|
65
|
-
puts " bin/test js Run only JavaScript tests"
|
|
66
|
-
exit 0
|
|
67
|
-
when nil
|
|
68
|
-
nil
|
|
69
|
-
else
|
|
70
|
-
puts "Unknown filter: #{ARGV[0]}"
|
|
71
|
-
puts "Use: bin/test [ruby|js]"
|
|
72
|
-
exit 1
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
TestRunner.new(filter: filter).run
|
data/jest.config.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/** @type {import('jest').Config} */
|
|
2
|
-
export default {
|
|
3
|
-
testEnvironment: 'jsdom',
|
|
4
|
-
testMatch: ['**/__tests__/**/*.test.js'],
|
|
5
|
-
moduleFileExtensions: ['js', 'json'],
|
|
6
|
-
transform: {
|
|
7
|
-
'^.+\\.js$': 'babel-jest'
|
|
8
|
-
},
|
|
9
|
-
transformIgnorePatterns: [
|
|
10
|
-
'/node_modules/(?!@hotwired/stimulus|stimulus-use)'
|
|
11
|
-
],
|
|
12
|
-
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
|
|
13
|
-
collectCoverageFrom: [
|
|
14
|
-
'app/assets/javascripts/shadcn/controllers/**/*.js',
|
|
15
|
-
'!**/node_modules/**'
|
|
16
|
-
],
|
|
17
|
-
coverageDirectory: 'coverage',
|
|
18
|
-
verbose: true
|
|
19
|
-
}
|
data/jest.setup.js
DELETED
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "rails/generators"
|
|
4
|
-
require "rails/generators/base"
|
|
5
|
-
|
|
6
|
-
module Shadcn
|
|
7
|
-
module Generators
|
|
8
|
-
# Generator for adding individual shadcn components
|
|
9
|
-
# Usage: rails generate shadcn:component button card dialog
|
|
10
|
-
class ComponentGenerator < Rails::Generators::Base
|
|
11
|
-
source_root File.expand_path("templates", __dir__)
|
|
12
|
-
|
|
13
|
-
argument :components, type: :array, default: [], banner: "component [component ...]"
|
|
14
|
-
|
|
15
|
-
class_option :all, type: :boolean, default: false,
|
|
16
|
-
desc: "Install all available components"
|
|
17
|
-
class_option :list, type: :boolean, default: false,
|
|
18
|
-
desc: "List all available components"
|
|
19
|
-
|
|
20
|
-
desc "Adds shadcn-rails components to your application"
|
|
21
|
-
|
|
22
|
-
# List of all available components
|
|
23
|
-
AVAILABLE_COMPONENTS = %w[
|
|
24
|
-
accordion
|
|
25
|
-
alert
|
|
26
|
-
avatar
|
|
27
|
-
badge
|
|
28
|
-
button
|
|
29
|
-
card
|
|
30
|
-
checkbox
|
|
31
|
-
collapsible
|
|
32
|
-
dialog
|
|
33
|
-
dropdown_menu
|
|
34
|
-
input
|
|
35
|
-
label
|
|
36
|
-
popover
|
|
37
|
-
progress
|
|
38
|
-
scroll_area
|
|
39
|
-
select
|
|
40
|
-
separator
|
|
41
|
-
sheet
|
|
42
|
-
skeleton
|
|
43
|
-
switch
|
|
44
|
-
table
|
|
45
|
-
tabs
|
|
46
|
-
textarea
|
|
47
|
-
toast
|
|
48
|
-
tooltip
|
|
49
|
-
].freeze
|
|
50
|
-
|
|
51
|
-
def validate_components
|
|
52
|
-
if options[:list]
|
|
53
|
-
display_available_components
|
|
54
|
-
exit 0
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
if options[:all]
|
|
58
|
-
@components_to_install = AVAILABLE_COMPONENTS
|
|
59
|
-
else
|
|
60
|
-
validate_requested_components
|
|
61
|
-
@components_to_install = components
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def display_installation_plan
|
|
66
|
-
say ""
|
|
67
|
-
say "Installing #{@components_to_install.length} component(s):", :green
|
|
68
|
-
@components_to_install.each { |c| say " - #{c}" }
|
|
69
|
-
say ""
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def install_components
|
|
73
|
-
@components_to_install.each do |component|
|
|
74
|
-
install_component(component)
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def display_usage_examples
|
|
79
|
-
say ""
|
|
80
|
-
say "=" * 60, :green
|
|
81
|
-
say " Components installed successfully!", :green
|
|
82
|
-
say "=" * 60, :green
|
|
83
|
-
say ""
|
|
84
|
-
say "Example usage:", :yellow
|
|
85
|
-
|
|
86
|
-
@components_to_install.first(3).each do |component|
|
|
87
|
-
display_component_example(component)
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
say ""
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
private
|
|
94
|
-
|
|
95
|
-
def display_available_components
|
|
96
|
-
say ""
|
|
97
|
-
say "Available shadcn-rails components:", :green
|
|
98
|
-
say ""
|
|
99
|
-
AVAILABLE_COMPONENTS.each { |c| say " - #{c}" }
|
|
100
|
-
say ""
|
|
101
|
-
say "Usage: rails generate shadcn:component button card dialog"
|
|
102
|
-
say " rails generate shadcn:component --all"
|
|
103
|
-
say ""
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def validate_requested_components
|
|
107
|
-
if components.empty?
|
|
108
|
-
say "Error: Please specify at least one component or use --all", :red
|
|
109
|
-
say ""
|
|
110
|
-
display_available_components
|
|
111
|
-
exit 1
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
invalid = components - AVAILABLE_COMPONENTS
|
|
115
|
-
if invalid.any?
|
|
116
|
-
say "Error: Unknown component(s): #{invalid.join(', ')}", :red
|
|
117
|
-
say ""
|
|
118
|
-
display_available_components
|
|
119
|
-
exit 1
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
def install_component(name)
|
|
124
|
-
# Components are already available from the gem
|
|
125
|
-
# This generator just confirms installation and provides usage info
|
|
126
|
-
say " ✓ #{name.titleize}Component is available", :green
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def display_component_example(component)
|
|
130
|
-
case component
|
|
131
|
-
when "button"
|
|
132
|
-
say <<~EXAMPLE
|
|
133
|
-
|
|
134
|
-
Button:
|
|
135
|
-
<%= render Shadcn::ButtonComponent.new(variant: :primary) do %>
|
|
136
|
-
Click me
|
|
137
|
-
<% end %>
|
|
138
|
-
EXAMPLE
|
|
139
|
-
when "card"
|
|
140
|
-
say <<~EXAMPLE
|
|
141
|
-
|
|
142
|
-
Card:
|
|
143
|
-
<%= render Shadcn::CardComponent.new do |card| %>
|
|
144
|
-
<% card.with_header do %>
|
|
145
|
-
<% card.with_title { "Card Title" } %>
|
|
146
|
-
<% end %>
|
|
147
|
-
<% card.with_content { "Card content" } %>
|
|
148
|
-
<% end %>
|
|
149
|
-
EXAMPLE
|
|
150
|
-
when "dialog"
|
|
151
|
-
say <<~EXAMPLE
|
|
152
|
-
|
|
153
|
-
Dialog:
|
|
154
|
-
<%= render Shadcn::DialogComponent.new do |dialog| %>
|
|
155
|
-
<% dialog.with_trigger do %>
|
|
156
|
-
<%= render Shadcn::ButtonComponent.new { "Open" } %>
|
|
157
|
-
<% end %>
|
|
158
|
-
<% dialog.with_content do |content| %>
|
|
159
|
-
<% content.with_title { "Dialog Title" } %>
|
|
160
|
-
Dialog content here
|
|
161
|
-
<% end %>
|
|
162
|
-
<% end %>
|
|
163
|
-
EXAMPLE
|
|
164
|
-
when "input"
|
|
165
|
-
say <<~EXAMPLE
|
|
166
|
-
|
|
167
|
-
Input:
|
|
168
|
-
<%= render Shadcn::LabelComponent.new(for: "email") { "Email" } %>
|
|
169
|
-
<%= render Shadcn::InputComponent.new(
|
|
170
|
-
type: "email",
|
|
171
|
-
id: "email",
|
|
172
|
-
name: "email",
|
|
173
|
-
placeholder: "Enter your email"
|
|
174
|
-
) %>
|
|
175
|
-
EXAMPLE
|
|
176
|
-
else
|
|
177
|
-
say <<~EXAMPLE
|
|
178
|
-
|
|
179
|
-
#{component.titleize}:
|
|
180
|
-
<%= render Shadcn::#{component.camelize}Component.new do %>
|
|
181
|
-
Content here
|
|
182
|
-
<% end %>
|
|
183
|
-
EXAMPLE
|
|
184
|
-
end
|
|
185
|
-
end
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
end
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "rails/generators"
|
|
4
|
-
require "rails/generators/base"
|
|
5
|
-
|
|
6
|
-
module Shadcn
|
|
7
|
-
module Generators
|
|
8
|
-
# Generator for switching or customizing themes
|
|
9
|
-
# Usage: rails generate shadcn:theme slate
|
|
10
|
-
class ThemeGenerator < Rails::Generators::Base
|
|
11
|
-
source_root File.expand_path("templates", __dir__)
|
|
12
|
-
|
|
13
|
-
argument :theme_name, type: :string, default: "neutral",
|
|
14
|
-
banner: "theme_name"
|
|
15
|
-
|
|
16
|
-
class_option :list, type: :boolean, default: false,
|
|
17
|
-
desc: "List all available themes"
|
|
18
|
-
|
|
19
|
-
desc "Changes the shadcn-rails theme or creates a custom theme"
|
|
20
|
-
|
|
21
|
-
AVAILABLE_THEMES = %w[neutral slate stone zinc gray].freeze
|
|
22
|
-
|
|
23
|
-
def validate_theme
|
|
24
|
-
if options[:list]
|
|
25
|
-
display_available_themes
|
|
26
|
-
exit 0
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
unless AVAILABLE_THEMES.include?(theme_name)
|
|
30
|
-
say "Error: Unknown theme '#{theme_name}'", :red
|
|
31
|
-
display_available_themes
|
|
32
|
-
exit 1
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def update_initializer
|
|
37
|
-
initializer_path = "config/initializers/shadcn.rb"
|
|
38
|
-
|
|
39
|
-
if File.exist?(initializer_path)
|
|
40
|
-
gsub_file initializer_path,
|
|
41
|
-
/config\.base_color = ["']?\w+["']?/,
|
|
42
|
-
"config.base_color = \"#{theme_name}\""
|
|
43
|
-
say "Updated initializer to use '#{theme_name}' theme", :green
|
|
44
|
-
else
|
|
45
|
-
say "Initializer not found. Run 'rails generate shadcn:install' first.", :yellow
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def update_config_file
|
|
50
|
-
config_path = "config/shadcn.yml"
|
|
51
|
-
|
|
52
|
-
if File.exist?(config_path)
|
|
53
|
-
gsub_file config_path,
|
|
54
|
-
/base_color: \w+/,
|
|
55
|
-
"base_color: #{theme_name}"
|
|
56
|
-
say "Updated shadcn.yml to use '#{theme_name}' theme", :green
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def update_stylesheet
|
|
61
|
-
# Check for theme import in stylesheet
|
|
62
|
-
stylesheet_path = "app/assets/stylesheets/application.tailwind.css"
|
|
63
|
-
|
|
64
|
-
if File.exist?(stylesheet_path)
|
|
65
|
-
content = File.read(stylesheet_path)
|
|
66
|
-
|
|
67
|
-
# Remove existing theme import
|
|
68
|
-
AVAILABLE_THEMES.each do |theme|
|
|
69
|
-
next if theme == "neutral" # neutral uses base.css
|
|
70
|
-
gsub_file stylesheet_path, /@import ["']shadcn\/themes\/#{theme}["'];\n?/, ""
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
# Add new theme import if not neutral
|
|
74
|
-
unless theme_name == "neutral"
|
|
75
|
-
inject_into_file stylesheet_path, after: '@import "shadcn/base";' do
|
|
76
|
-
"\n@import \"shadcn/themes/#{theme_name}\";"
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
say "Updated stylesheet with '#{theme_name}' theme", :green
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def display_completion_message
|
|
85
|
-
say ""
|
|
86
|
-
say "Theme changed to '#{theme_name}'!", :green
|
|
87
|
-
say ""
|
|
88
|
-
say "The following colors are now active:", :yellow
|
|
89
|
-
display_theme_preview(theme_name)
|
|
90
|
-
say ""
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
private
|
|
94
|
-
|
|
95
|
-
def display_available_themes
|
|
96
|
-
say ""
|
|
97
|
-
say "Available themes:", :green
|
|
98
|
-
say ""
|
|
99
|
-
AVAILABLE_THEMES.each do |theme|
|
|
100
|
-
say " - #{theme}"
|
|
101
|
-
end
|
|
102
|
-
say ""
|
|
103
|
-
say "Usage: rails generate shadcn:theme slate"
|
|
104
|
-
say ""
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def display_theme_preview(theme)
|
|
108
|
-
case theme
|
|
109
|
-
when "neutral"
|
|
110
|
-
say " Primary: Pure black/white"
|
|
111
|
-
say " Style: Clean, minimal"
|
|
112
|
-
when "slate"
|
|
113
|
-
say " Primary: Cool blue-gray"
|
|
114
|
-
say " Style: Professional, corporate"
|
|
115
|
-
when "stone"
|
|
116
|
-
say " Primary: Warm gray-brown"
|
|
117
|
-
say " Style: Earthy, natural"
|
|
118
|
-
when "zinc"
|
|
119
|
-
say " Primary: Cool gray"
|
|
120
|
-
say " Style: Modern, sleek"
|
|
121
|
-
when "gray"
|
|
122
|
-
say " Primary: True gray"
|
|
123
|
-
say " Style: Neutral, balanced"
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
end
|
|
128
|
-
end
|