jet_ui 0.2.7 → 0.2.8
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 +10 -0
- data/README.md +30 -0
- data/lib/generators/jet_ui/install/install_generator.rb +110 -44
- data/lib/generators/jet_ui/js_runtime.rb +81 -0
- data/lib/jet_ui/engine.rb +0 -1
- data/lib/jet_ui/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7d81819a27f5eda163c7f4dd9d8b12973ae46cc82932cd1f272b59f40e2bf55d
|
|
4
|
+
data.tar.gz: de6951399df6add4915be32c9d55f1cdc1a9b1be4e090039f4d055bed24f4987
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9259ec8446ed0c0c6d6f790ad00c27e9f24c93cd065a3d6bba7fe07a5068b079ea1e70de6e70b47d37a2e4ecf25c211bca85a3ec1c940d991215273710aba7f1
|
|
7
|
+
data.tar.gz: e2c5e84a989af0b3e935e4f39bb0cfa3c0653e235f5839fe23ee39736349b749cba938b20f3511ad620f09d65ceaff27e92638d5b3f8d1506cea6ab4e61649fc
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.8] - 2026-07-09
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- `@jetrockets/jet-ui` npm package for Vite/esbuild/Webpack users — import Stimulus controllers without vendoring
|
|
14
|
+
- `JsRuntime` module for auto-detecting JS bundler (Vite, esbuild, Webpack) vs importmap
|
|
15
|
+
- `jet_ui:install` generator now detects runtime and prints runtime-specific setup instructions
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- Importmap crash (`Errno::EISDIR`) — removed invalid directory path from `importmap.paths`
|
|
19
|
+
|
|
10
20
|
## [0.2.7] - 2026-05-29
|
|
11
21
|
|
|
12
22
|
### Added
|
data/README.md
CHANGED
|
@@ -37,6 +37,36 @@ The generator:
|
|
|
37
37
|
|
|
38
38
|
When the gem is updated, both CSS and JS are picked up automatically — no further changes needed. Safe to re-run after upgrades.
|
|
39
39
|
|
|
40
|
+
### Alternative: npm package (Vite)
|
|
41
|
+
|
|
42
|
+
The above (importmap) setup needs no npm install — the gem ships the controllers itself. If your app bundles JavaScript with Vite instead, run the install generator: it detects Vite, **installs the `@jetrockets/jet_ui` npm package** for you (running `yarn add @jetrockets/jet_ui`, or the npm/pnpm/bun equivalent it detects), and prints the wiring steps:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
rails generate jet_ui:install
|
|
46
|
+
# detects Vite → runs: yarn add @jetrockets/jet_ui
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Then register the controllers you use (`@hotwired/stimulus` is a peer dependency):
|
|
50
|
+
|
|
51
|
+
```javascript
|
|
52
|
+
import { ModalController } from "@jetrockets/jet_ui"
|
|
53
|
+
|
|
54
|
+
application.register("modal", ModalController)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Import the component styles in your Tailwind/CSS entry point:
|
|
58
|
+
|
|
59
|
+
```css
|
|
60
|
+
@import "@jetrockets/jet_ui/css";
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Or, if you'd rather manage styles through the bundler than the Rails asset pipeline, import the CSS straight from JavaScript:
|
|
64
|
+
|
|
65
|
+
```javascript
|
|
66
|
+
import "@jetrockets/jet_ui/css" // all component styles
|
|
67
|
+
import "@jetrockets/jet_ui/css/btn.css" // a single component
|
|
68
|
+
```
|
|
69
|
+
|
|
40
70
|
## Usage
|
|
41
71
|
|
|
42
72
|
The `jet_ui` helper is available in all views:
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'rails/generators'
|
|
4
4
|
require_relative '../eject/eject_generator'
|
|
5
|
+
require_relative '../js_runtime'
|
|
5
6
|
|
|
6
7
|
module JetUi
|
|
7
8
|
module Generators
|
|
@@ -12,24 +13,28 @@ module JetUi
|
|
|
12
13
|
class InstallGenerator < Rails::Generators::Base
|
|
13
14
|
source_root File.expand_path('templates', __dir__)
|
|
14
15
|
|
|
16
|
+
class_option :skip_install, type: :boolean, default: false,
|
|
17
|
+
desc: 'Vite apps: skip running the package manager install, just print the command'
|
|
18
|
+
|
|
15
19
|
desc <<~DESC
|
|
16
20
|
JetUi is a ViewComponent-based UI library for Rails — #{EjectGenerator::MANIFEST.size} ready-made
|
|
17
21
|
components styled with Tailwind CSS v4, matching the design system at
|
|
18
22
|
ui.jetrockets.com.
|
|
19
23
|
|
|
20
|
-
This generator
|
|
24
|
+
This generator detects how your app manages JavaScript and sets JetUi up
|
|
25
|
+
accordingly — no flags needed:
|
|
21
26
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
• Importmap apps — injects the gem's CSS @import into your Tailwind source
|
|
28
|
+
and adds eagerLoadControllersFrom("jet_ui", application) to your Stimulus
|
|
29
|
+
controllers index. Controllers are auto-registered, no npm needed.
|
|
25
30
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
• Vite apps — installs the npm package with your package manager and
|
|
32
|
+
prints the controller registration and stylesheet @import. Vite apps own
|
|
33
|
+
their JS/CSS entry points, so those are not modified automatically.
|
|
29
34
|
|
|
30
|
-
Safe to run multiple times — already-configured steps are skipped.
|
|
35
|
+
Safe to run multiple times — already-configured importmap steps are skipped.
|
|
31
36
|
|
|
32
|
-
|
|
37
|
+
Importmap Tailwind source files detected for the CSS @import:
|
|
33
38
|
app/assets/tailwind/application.css
|
|
34
39
|
app/assets/stylesheets/application.tailwind.css
|
|
35
40
|
app/assets/stylesheets/application.postcss.css
|
|
@@ -41,40 +46,19 @@ module JetUi
|
|
|
41
46
|
rails generate jet_ui:install
|
|
42
47
|
DESC
|
|
43
48
|
|
|
44
|
-
def
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
else
|
|
50
|
-
# Tailwind CSS v4: import each file with an absolute path so the
|
|
51
|
-
# Tailwind CLI can process @apply directives at build time.
|
|
52
|
-
append_to_file file, tailwind_imports
|
|
53
|
-
say " Injected JetUi imports into #{file}", :green
|
|
54
|
-
end
|
|
55
|
-
else
|
|
56
|
-
say ' Could not detect a Tailwind CSS source file.', :yellow
|
|
57
|
-
say ' Add the following to your Tailwind CSS source manually:', :yellow
|
|
58
|
-
say tailwind_imports, :yellow
|
|
49
|
+
def show_runtime
|
|
50
|
+
case js_runtime
|
|
51
|
+
when :importmap then say ' Detected importmap — wiring JetUi via the gem.', :green
|
|
52
|
+
when :vite then say ' Detected Vite — wiring JetUi via the npm package.', :green
|
|
53
|
+
else say ' Could not detect importmap or Vite — printing both setups.', :yellow
|
|
59
54
|
end
|
|
60
55
|
end
|
|
61
56
|
|
|
62
|
-
def
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
say %( eagerLoadControllersFrom("jet_ui", application)), :yellow
|
|
68
|
-
return
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
if File.read(path).include?('jet_ui')
|
|
72
|
-
say " JetUi controllers already registered in #{JS_CONTROLLERS_FILE}", :yellow
|
|
73
|
-
else
|
|
74
|
-
insert_into_file JS_CONTROLLERS_FILE, after: /eagerLoadControllersFrom\("controllers".*\n/ do
|
|
75
|
-
%(eagerLoadControllersFrom("jet_ui", application)\n)
|
|
76
|
-
end
|
|
77
|
-
say " Registered JetUi controllers in #{JS_CONTROLLERS_FILE}", :green
|
|
57
|
+
def setup
|
|
58
|
+
case js_runtime
|
|
59
|
+
when :importmap then setup_importmap
|
|
60
|
+
when :vite then setup_vite
|
|
61
|
+
else setup_unknown
|
|
78
62
|
end
|
|
79
63
|
end
|
|
80
64
|
|
|
@@ -96,6 +80,8 @@ module JetUi
|
|
|
96
80
|
say " rails generate jet_ui:eject btn card\n"
|
|
97
81
|
end
|
|
98
82
|
|
|
83
|
+
NPM_PACKAGE = '@jetrockets/jet_ui'
|
|
84
|
+
|
|
99
85
|
JS_CONTROLLERS_FILE = 'app/javascript/controllers/index.js'
|
|
100
86
|
|
|
101
87
|
TAILWIND_SOURCE_FILES = %w[
|
|
@@ -106,10 +92,94 @@ module JetUi
|
|
|
106
92
|
|
|
107
93
|
private
|
|
108
94
|
|
|
95
|
+
def js_runtime
|
|
96
|
+
@js_runtime ||= JsRuntime.detect(destination_root)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# --- importmap: auto-wire from the gem -------------------------------
|
|
100
|
+
|
|
101
|
+
def setup_importmap
|
|
102
|
+
inject_importmap_css
|
|
103
|
+
inject_importmap_controllers
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def inject_importmap_css
|
|
107
|
+
file = tailwind_source_file
|
|
108
|
+
unless file
|
|
109
|
+
say ' Could not detect a Tailwind CSS source file.', :yellow
|
|
110
|
+
say ' Add the following to your Tailwind CSS source manually:', :yellow
|
|
111
|
+
say gem_css_import, :yellow
|
|
112
|
+
return
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
if File.read(File.join(destination_root, file)).include?('jet_ui')
|
|
116
|
+
say " JetUi CSS already imported in #{file}", :yellow
|
|
117
|
+
else
|
|
118
|
+
# Tailwind CSS v4: import the gem's stylesheet by absolute path so the
|
|
119
|
+
# Tailwind CLI can process its @apply directives at build time.
|
|
120
|
+
append_to_file file, gem_css_import
|
|
121
|
+
say " Injected JetUi CSS into #{file}", :green
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def inject_importmap_controllers
|
|
126
|
+
path = File.join(destination_root, JS_CONTROLLERS_FILE)
|
|
127
|
+
unless File.exist?(path)
|
|
128
|
+
say ' No Stimulus controllers index found — add this line to it manually:', :yellow
|
|
129
|
+
say %( eagerLoadControllersFrom("jet_ui", application)), :yellow
|
|
130
|
+
return
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
if File.read(path).include?('jet_ui')
|
|
134
|
+
say " JetUi controllers already registered in #{JS_CONTROLLERS_FILE}", :yellow
|
|
135
|
+
else
|
|
136
|
+
insert_into_file JS_CONTROLLERS_FILE, after: /eagerLoadControllersFrom\("controllers".*\n/ do
|
|
137
|
+
%(eagerLoadControllersFrom("jet_ui", application)\n)
|
|
138
|
+
end
|
|
139
|
+
say " Registered JetUi controllers in #{JS_CONTROLLERS_FILE}", :green
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# --- vite: install the package, but never touch the app's entry points ---
|
|
144
|
+
|
|
145
|
+
def setup_vite
|
|
146
|
+
install_npm_package
|
|
147
|
+
say ' Ensure @hotwired/stimulus is installed — it is a peer dependency the controllers import.', :yellow
|
|
148
|
+
say ' Register the controllers you use, in your Stimulus controllers index:'
|
|
149
|
+
say %( import { ModalController, DrawerController } from "#{NPM_PACKAGE}")
|
|
150
|
+
say %( application.register("modal", ModalController))
|
|
151
|
+
say %( application.register("drawer", DrawerController))
|
|
152
|
+
say ' Import the styles, in your Tailwind/CSS entry point:'
|
|
153
|
+
say %( @import "#{NPM_PACKAGE}/css";)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def install_npm_package
|
|
157
|
+
command = JsRuntime.install_command(destination_root, NPM_PACKAGE)
|
|
158
|
+
if options[:skip_install]
|
|
159
|
+
say ' Skipped install — run it yourself:', :yellow
|
|
160
|
+
say " #{command}"
|
|
161
|
+
else
|
|
162
|
+
say " Installing #{NPM_PACKAGE}…", :green
|
|
163
|
+
run command
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def setup_unknown
|
|
168
|
+
say ' Importmap apps — add to your Stimulus controllers index:', :yellow
|
|
169
|
+
say %( eagerLoadControllersFrom("jet_ui", application))
|
|
170
|
+
say ' Vite apps — install the npm package and import its styles:', :yellow
|
|
171
|
+
say " #{JsRuntime.install_command(destination_root, NPM_PACKAGE)}"
|
|
172
|
+
say %( @import "#{NPM_PACKAGE}/css";)
|
|
173
|
+
end
|
|
174
|
+
|
|
109
175
|
def tailwind_source_file
|
|
110
176
|
TAILWIND_SOURCE_FILES.find { |f| File.exist?(File.join(destination_root, f)) }
|
|
111
177
|
end
|
|
112
178
|
|
|
179
|
+
def gem_css_import
|
|
180
|
+
%(\n@import "#{File.join(gem_stylesheets_path, 'jet_ui.css')}";\n)
|
|
181
|
+
end
|
|
182
|
+
|
|
113
183
|
def gem_stylesheets_path
|
|
114
184
|
spec = begin
|
|
115
185
|
Gem::Specification.find_by_name('jet_ui')
|
|
@@ -119,10 +189,6 @@ module JetUi
|
|
|
119
189
|
base = spec&.gem_dir || File.expand_path('../../../../..', __dir__)
|
|
120
190
|
File.join(base, 'app/assets/stylesheets')
|
|
121
191
|
end
|
|
122
|
-
|
|
123
|
-
def tailwind_imports
|
|
124
|
-
%(\n@import "#{File.join(gem_stylesheets_path, 'jet_ui.css')}";\n)
|
|
125
|
-
end
|
|
126
192
|
end
|
|
127
193
|
end
|
|
128
194
|
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module JetUi
|
|
6
|
+
module Generators
|
|
7
|
+
# Detects how a host application manages its JavaScript, so the install
|
|
8
|
+
# generator can wire JetUi the right way without asking: pin controllers via
|
|
9
|
+
# importmap, or point the app at the npm package for Vite.
|
|
10
|
+
module JsRuntime
|
|
11
|
+
VITE_CONFIGS = %w[
|
|
12
|
+
vite.config.js vite.config.mjs vite.config.ts
|
|
13
|
+
config/vite.json
|
|
14
|
+
].freeze
|
|
15
|
+
|
|
16
|
+
# Ordered: the first lockfile found wins.
|
|
17
|
+
PACKAGE_MANAGERS = {
|
|
18
|
+
'bun.lockb' => :bun,
|
|
19
|
+
'pnpm-lock.yaml' => :pnpm,
|
|
20
|
+
'yarn.lock' => :yarn,
|
|
21
|
+
'package-lock.json' => :npm
|
|
22
|
+
}.freeze
|
|
23
|
+
|
|
24
|
+
module_function
|
|
25
|
+
|
|
26
|
+
# Vite wins when both are present: a working Vite config is a stronger
|
|
27
|
+
# signal than a leftover config/importmap.rb.
|
|
28
|
+
def detect(root)
|
|
29
|
+
return :vite if vite?(root)
|
|
30
|
+
return :importmap if importmap?(root)
|
|
31
|
+
|
|
32
|
+
:unknown
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def vite?(root)
|
|
36
|
+
VITE_CONFIGS.any? { |file| File.exist?(File.join(root, file)) } ||
|
|
37
|
+
package_json_vite?(root)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def importmap?(root)
|
|
41
|
+
File.exist?(File.join(root, 'config/importmap.rb'))
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def package_manager(root)
|
|
45
|
+
PACKAGE_MANAGERS.each { |lock, name| return name if File.exist?(File.join(root, lock)) }
|
|
46
|
+
package_manager_field(root) || :npm
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# corepack's `"packageManager": "yarn@4.5.0"` — the declared manager when
|
|
50
|
+
# there's no lockfile yet (e.g. a fresh vite_rails clone).
|
|
51
|
+
def package_manager_field(root)
|
|
52
|
+
path = File.join(root, 'package.json')
|
|
53
|
+
return unless File.exist?(path)
|
|
54
|
+
|
|
55
|
+
field = JSON.parse(File.read(path))['packageManager']
|
|
56
|
+
return unless field
|
|
57
|
+
|
|
58
|
+
PACKAGE_MANAGERS.values.find { |name| name.to_s == field.split('@').first }
|
|
59
|
+
rescue JSON::ParserError
|
|
60
|
+
nil
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def install_command(root, package)
|
|
64
|
+
manager = package_manager(root)
|
|
65
|
+
verb = manager == :npm ? 'install' : 'add'
|
|
66
|
+
|
|
67
|
+
"#{manager} #{verb} #{package}"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def package_json_vite?(root)
|
|
71
|
+
path = File.join(root, 'package.json')
|
|
72
|
+
return false unless File.exist?(path)
|
|
73
|
+
|
|
74
|
+
deps = JSON.parse(File.read(path)).values_at('dependencies', 'devDependencies').compact
|
|
75
|
+
deps.flat_map(&:keys).include?('vite')
|
|
76
|
+
rescue JSON::ParserError
|
|
77
|
+
false
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
data/lib/jet_ui/engine.rb
CHANGED
data/lib/jet_ui/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jet_ui
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- JetRockets
|
|
@@ -635,6 +635,7 @@ files:
|
|
|
635
635
|
- app/helpers/jet_ui_helper.rb
|
|
636
636
|
- lib/generators/jet_ui/eject/eject_generator.rb
|
|
637
637
|
- lib/generators/jet_ui/install/install_generator.rb
|
|
638
|
+
- lib/generators/jet_ui/js_runtime.rb
|
|
638
639
|
- lib/jet_ui.rb
|
|
639
640
|
- lib/jet_ui/engine.rb
|
|
640
641
|
- lib/jet_ui/version.rb
|