amber_component 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d81663eb6f3cd153cb0a277a0114f8cce4e2140f40685f23a688a60c8ce86226
4
- data.tar.gz: 32abb3383e052466435f318e1f8c4010adfa5f3d7e93e588e7e2842ff7cd59e6
3
+ metadata.gz: 3fe50a4aaf1482572196e8ae5fd9fd7e2f04ef1ee07b9b5275b0454623e54a6d
4
+ data.tar.gz: 17c1e2848263efac38a029621d26a8d2eae5b4b3d47d2c9eaf8e040b14fe3eae
5
5
  SHA512:
6
- metadata.gz: 4a3df277a91914b6a148cc72c1b3981f78c420e773b408c8555a8915424d11667c804f113c2a1fd76bce751083607086ab660f1634855fcec686bc433b875c12
7
- data.tar.gz: 330efd82e1589a4804f72f4dcb1df1f9a9b90696ce2dfb542c69b91dd1b0a5b7797736c9fa8ce461f73ff7bb16a3966a8ed00b8340c6d047d289acde976240cc
6
+ metadata.gz: e566cb7199d6d8c890081557ed20ac02410085992b036b6a603e909a62ac6fb6af0e853910ab02ac087fd8e3bcaf398d59496e7172ac1233d843206785b15509
7
+ data.tar.gz: 3b8bb6257ba09f3f6fbf98c68a128ab99adfa289e8ee3d674de744052b4b69f7b06c0e5f43a5e7bb4ae54533a78728fea15ba2534b947b4e730869b5e09b8932
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- amber_component (1.0.0)
4
+ amber_component (1.1.0)
5
5
  actionview (>= 6)
6
6
  activemodel (>= 6)
7
7
  activesupport (>= 6)
data/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  # AmberComponent
11
11
 
12
- AmberComponent is a simple component library which seamlessly hooks into your Rails project and allows you to create simple backend components. They work like mini controllers which are bound with their view and stylesheet.
12
+ AmberComponent is a simple component library which seamlessly hooks into your Rails project and allows you to create simple backend components which consist of a Ruby controller, view, stylesheet and even a JavaScript controller (using [Stimulus](https://stimulus.hotwired.dev/)).
13
13
 
14
14
  Created by [Garbus Beach](https://github.com/garbusbeach) and [Mateusz Drewniak](https://github.com/Verseth).
15
15
 
@@ -33,16 +33,37 @@ If you're using a Rails application there's an installation generator that you s
33
33
  $ bin/rails generate amber_component:install
34
34
  ```
35
35
 
36
+ Amber component supports [Stimulus](https://stimulus.hotwired.dev/) to make your components
37
+ reactive using JavaScript.
38
+
39
+ If you want to use stimulus you should install this gem with the `--stimulus` flag
40
+
41
+ ```sh
42
+ $ bin/rails generate amber_component:install --stimulus
43
+ ```
44
+
36
45
  ## Usage
37
46
 
38
- ## Components
47
+ ### Components
39
48
 
40
- Components are located under `app/components`.
49
+ Components are located under `app/components`. And their tests under `test/components`.
41
50
 
42
51
  Every component consists of:
43
52
  - a Ruby file which defines its properties, encapsulates logic and may implement helper methods (like a controller)
44
53
  - a view/template file (html.erb, haml, slim etc.)
45
54
  - a style file (css, scss, sass etc.)
55
+ - [optional] a JavaScript file with a Stimulus controller (if you installed the gem with `--stimulus`)
56
+
57
+ ```
58
+ app/components/
59
+ ├─ [name]_component.rb
60
+ └─ [name]_component/
61
+ ├─ style.css # may be .sass or .scss
62
+ ├─ view.html.erb
63
+ └─ controller.js # if stimulus is configured
64
+ test/components/
65
+ └─ [name]_component_test.rb
66
+ ```
46
67
 
47
68
  An individual component which implements a button may look like this.
48
69
 
@@ -57,7 +78,9 @@ end
57
78
  ```html
58
79
  <!-- app/components/button_component/view.html.erb -->
59
80
 
60
- <div class="button_component">
81
+ <div class="button_component"
82
+ data-controller="button-component"
83
+ data-action="click->button-component#greet">
61
84
  <%= label %>
62
85
  </div>
63
86
  ```
@@ -76,6 +99,25 @@ end
76
99
  }
77
100
  ```
78
101
 
102
+ If you used the `--stimulus` option when installing the gem, a JS controller will be generated as well.
103
+ ```js
104
+ // app/components/button_component/controller.js
105
+
106
+ import { Controller } from "@hotwired/stimulus"
107
+
108
+ // Read more about Stimulus here https://stimulus.hotwired.dev/
109
+ export default class extends Controller {
110
+ connect() {
111
+ console.log("Stimulus controller 'button-component' is connected!")
112
+ }
113
+
114
+ greet() {
115
+ alert("Hi there!")
116
+ }
117
+ }
118
+
119
+ ```
120
+
79
121
  You can render this component in other components or in a Rails view.
80
122
 
81
123
  ```html
@@ -97,34 +139,69 @@ ButtonComponent.call label: 'Click me!'
97
139
  #=> '<div class="button_component">Click me!</div>'
98
140
  ```
99
141
 
100
- ### Rails helpers inside component templates
142
+ ### Components with namespaces
101
143
 
102
- Component views/template files can make use
103
- of all ActionView helpers and Rails route helpers.
144
+ Components may be defined inside multiple modules/namespaces.
104
145
 
105
- This makes component views very flexible and convenient.
146
+ ```ruby
147
+ # app/components/sign_up/button_component.rb
106
148
 
107
- ```erb
108
- <!-- app/components/login_form_component/view.html.erb -->
149
+ class SignUp::ButtonComponent < AmberComponent::Base
150
+ prop :label, required: true
151
+ end
152
+ ```
109
153
 
110
- <%= form_with url: sign_up_path, class: "login_form_component" do |f| %>
111
- <%= f.label :first_name %>
112
- <%= f.text_field :first_name %>
154
+ ```html
155
+ <!-- app/components/sign_up/button_component/view.html.erb -->
113
156
 
114
- <%= f.label :last_name %>
115
- <%= f.text_field :last_name %>
157
+ <div class="sign_up_button_component">
158
+ <%= label %>
159
+ </div>
160
+ ```
116
161
 
117
- <%= f.label :email, "Email Address" %>
118
- <%= f.text_field :email %>
162
+ ```scss
163
+ // app/components/sign_up/button_component/style.scss
119
164
 
120
- <%= f.label :password %>
121
- <%= f.password_field :password %>
165
+ .sign_up_button_component {
166
+ background-color: indigo;
167
+ border-radius: 1rem;
168
+ transition-duration: 500ms;
122
169
 
123
- <%= f.label :password_confirmation, "Confirm Password" %>
124
- <%= f.password_field :password_confirmation %>
170
+ &:hover {
171
+ background-color: blue;
172
+ }
173
+ }
174
+ ```
125
175
 
126
- <%= f.submit "Create account" %>
127
- <% end %>
176
+ You can render such a component by calling the `::call` method
177
+ on its class, or by using the helper method defined on its parent module.
178
+
179
+ ```ruby
180
+ SignUp::ButtonComponent.call label: 'Sign up!'
181
+ SignUp.button_component label: 'Sign up!'
182
+ ```
183
+
184
+ ### Generating Components
185
+
186
+ You can generate new components by running
187
+
188
+ ```sh
189
+ $ bin/rails generate component [name]
190
+ ```
191
+
192
+ Name of the component may be PascalCased like `FooBar` or snake_cased `foo_bar`
193
+
194
+ This will generate a new component in `app/components/[name]_component.rb` along with a view, stylesheet, test file and a stimulus controller (if configured).
195
+
196
+ ```
197
+ app/components/
198
+ ├─ [name]_component.rb
199
+ └─ [name]_component/
200
+ ├─ style.css
201
+ ├─ view.html.erb
202
+ └─ controller.js # if stimulus is configured
203
+ test/components/
204
+ └─ [name]_component_test.rb
128
205
  ```
129
206
 
130
207
  ### Component properties
@@ -155,39 +232,6 @@ CommentComponent.call body: 'Foo bar', author: User.first
155
232
  comment_component body: 'Foo bar', author: User.first
156
233
  ```
157
234
 
158
- ### Overriding prop getters and setters
159
-
160
- Getters and setters for properties are
161
- defined in a module which means that you can override them and call them with `super`.
162
-
163
- ```ruby
164
- # app/components/priority_icon_component.rb
165
-
166
- class PriorityIconComponent < ApplicationComponent
167
- PriorityStruct = Struct.new :icon, :color
168
-
169
- PRIORITY_MAP = {
170
- low: PriorityStruct.new('fa-solid fa-chevrons-down', 'green'),
171
- medium: PriorityStruct.new('fa-solid fa-chevron-up', 'yellow'),
172
- high: PriorityStruct.new('fa-solid fa-chevrons-up', 'red')
173
- }
174
-
175
- prop :severity, default: -> { :low }
176
-
177
- def severity=(val)
178
- # super will call the original
179
- # implementation of the setter
180
- super(PRIORITY_MAP[val])
181
- end
182
- end
183
- ```
184
-
185
- ```html
186
- <!-- app/components/priority_icon_component/view.html.erb -->
187
-
188
- <i style="color: <%= severity&.color %>;" class="<%= severity&.icon %>"></i>
189
- ```
190
-
191
235
  ### Helper methods
192
236
 
193
237
  Defining helper methods which are available
@@ -239,6 +283,39 @@ end
239
283
  </div>
240
284
  ```
241
285
 
286
+ ### Overriding prop getters and setters
287
+
288
+ Getters and setters for properties are
289
+ defined in a module which means that you can override them and call them with `super`.
290
+
291
+ ```ruby
292
+ # app/components/priority_icon_component.rb
293
+
294
+ class PriorityIconComponent < ApplicationComponent
295
+ PriorityStruct = Struct.new :icon, :color
296
+
297
+ PRIORITY_MAP = {
298
+ low: PriorityStruct.new('fa-solid fa-chevrons-down', 'green'),
299
+ medium: PriorityStruct.new('fa-solid fa-chevron-up', 'yellow'),
300
+ high: PriorityStruct.new('fa-solid fa-chevrons-up', 'red')
301
+ }
302
+
303
+ prop :severity, default: -> { :low }
304
+
305
+ def severity=(val)
306
+ # super will call the original
307
+ # implementation of the setter
308
+ super(PRIORITY_MAP[val])
309
+ end
310
+ end
311
+ ```
312
+
313
+ ```html
314
+ <!-- app/components/priority_icon_component/view.html.erb -->
315
+
316
+ <i style="color: <%= severity&.color %>;" class="<%= severity&.icon %>"></i>
317
+ ```
318
+
242
319
  ### Nested components
243
320
 
244
321
  It's possible to nest components or provide
@@ -304,64 +381,36 @@ In general `block_given?` will return `true` when a block/nested content is pres
304
381
  You can use it to render content conditionally based on
305
382
  whether nested content is present.
306
383
 
307
- ### Components with namespaces
308
-
309
- Components may be defined inside multiple modules/namespaces.
310
-
311
- ```ruby
312
- # app/components/sign_up/button_component.rb
313
-
314
- class SignUp::ButtonComponent < AmberComponent::Base
315
- prop :label, required: true
316
- end
317
- ```
318
-
319
- ```html
320
- <!-- app/components/sign_up/button_component/view.html.erb -->
321
-
322
- <div class="sign_up_button_component">
323
- <%= label %>
324
- </div>
325
- ```
326
-
327
- ```scss
328
- // app/components/sign_up/button_component/style.scss
384
+ ### Rails helpers inside component templates
329
385
 
330
- .sign_up_button_component {
331
- background-color: indigo;
332
- border-radius: 1rem;
333
- transition-duration: 500ms;
386
+ Component views/template files can make use
387
+ of all ActionView helpers and Rails route helpers.
334
388
 
335
- &:hover {
336
- background-color: blue;
337
- }
338
- }
339
- ```
389
+ This makes component views very flexible and convenient.
340
390
 
341
- You can render such a component by calling the `::call` method
342
- on its class, or by using the helper method defined on its parent module.
391
+ ```erb
392
+ <!-- app/components/login_form_component/view.html.erb -->
343
393
 
344
- ```ruby
345
- SignUp::ButtonComponent.call label: 'Sign up!'
346
- SignUp.button_component label: 'Sign up!'
347
- ```
394
+ <%= form_with url: sign_up_path, class: "login_form_component" do |f| %>
395
+ <%= f.label :first_name %>
396
+ <%= f.text_field :first_name %>
348
397
 
349
- ### Generating Components
398
+ <%= f.label :last_name %>
399
+ <%= f.text_field :last_name %>
350
400
 
351
- You an generate new components by running
401
+ <%= f.label :email, "Email Address" %>
402
+ <%= f.text_field :email %>
352
403
 
353
- ```sh
354
- $ bin/rails generate component foo_bar
355
- ```
404
+ <%= f.label :password %>
405
+ <%= f.password_field :password %>
356
406
 
357
- or
407
+ <%= f.label :password_confirmation, "Confirm Password" %>
408
+ <%= f.password_field :password_confirmation %>
358
409
 
359
- ```sh
360
- $ bin/rails generate component FooBar
410
+ <%= f.submit "Create account" %>
411
+ <% end %>
361
412
  ```
362
413
 
363
- This will generate a new component in `app/components/foo_bar_component.rb` along with a view, stylesheet and test file.
364
-
365
414
  ### Testing Components
366
415
 
367
416
  ### Rails
@@ -43,7 +43,4 @@ require_relative "lib/amber_component/version"
43
43
  spec.add_dependency "activesupport", ">= 6"
44
44
  spec.add_dependency "memery", ">= 1.4.1"
45
45
  spec.add_dependency "tilt", ">= 2.0.10"
46
-
47
- # For more information and examples about making a new gem, check out our
48
- # guide at: https://bundler.io/guides/creating_gem.html
49
46
  end
@@ -0,0 +1,30 @@
1
+ const registeredControllers = {}
2
+
3
+ export function eagerLoadAmberComponentControllers(application) {
4
+ const paths = Object.keys(parseImportmapJson()).filter(path => path.match(new RegExp(`/controller$`)))
5
+ paths.forEach(path => registerControllerFromPath(path, application))
6
+ }
7
+
8
+ function parseImportmapJson() {
9
+ return JSON.parse(document.querySelector("script[type=importmap]").text).imports
10
+ }
11
+
12
+ function registerControllerFromPath(path, application) {
13
+ const name = path
14
+ .replace("/controller", "")
15
+ .replace(/\//g, "--")
16
+ .replace(/_/g, "-")
17
+
18
+ if (!(name in registeredControllers)) {
19
+ import(path)
20
+ .then(module => registerController(name, module, application))
21
+ .catch(error => console.error(`Failed to register controller: ${name} (${path})`, error))
22
+ }
23
+ }
24
+
25
+ function registerController(name, module, application) {
26
+ if (!(name in registeredControllers)) {
27
+ application.register(name, module.default)
28
+ registeredControllers[name] = true
29
+ }
30
+ }
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ::AmberComponent
4
+ # Object which stores configuration options
5
+ # for this gem.
6
+ class Configuration
7
+ # @return [Array<Symbol>]
8
+ STIMULUS_INTEGRATIONS = %i[importmap jsbundling webpack esbuild rollup].freeze
9
+
10
+ # How Stimulus.js is bundled in this app.
11
+ # Possible values: `[nil, :importmap, :jsbundling, :webpack, :esbuild, :rollup]`
12
+ # `nil` indicates that stimulus should not be used (default behaviour).
13
+ #
14
+ # @return [Symbol, nil]
15
+ attr_reader :stimulus
16
+
17
+ # How Stimulus.js is bundled in this app.
18
+ # Possible values: `[nil, :importmap, :jsbundling, :webpack, :esbuild, :rollup]`
19
+ # `nil` indicates that stimulus should not be used (default behaviour).
20
+ #
21
+ # @param val [Symbol, String, nil]
22
+ def stimulus=(val)
23
+ val = val&.to_sym
24
+ unless val.nil? || STIMULUS_INTEGRATIONS.include?(val)
25
+ raise(::ArgumentError,
26
+ "Invalid value for `stimulus` bundling. " \
27
+ "Received #{val.inspect}, expected one of #{STIMULUS_INTEGRATIONS.inspect}")
28
+ end
29
+
30
+ @stimulus = val
31
+ end
32
+
33
+ # @return [Boolean]
34
+ def stimulus?
35
+ !@stimulus.nil?
36
+ end
37
+
38
+ # @return [Boolean]
39
+ def stimulus_importmap?
40
+ @stimulus == :importmap
41
+ end
42
+ end
43
+ end
@@ -4,8 +4,10 @@ module ::AmberComponent
4
4
  # Class which hooks into Rails
5
5
  # and configures the application.
6
6
  class Railtie < ::Rails::Railtie
7
- initializer 'amber_component.initialization' do |app|
7
+ initializer 'amber_component.assets' do |app|
8
8
  app.config.assets.paths << (app.root / 'app' / 'components')
9
+ app.config.assets.paths << (ROOT_GEM_PATH / 'assets' / 'javascripts')
10
+ app.config.assets.precompile += %w[amber_component/stimulus_loading.js]
9
11
 
10
12
  next if ::Rails.env.production?
11
13
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ::AmberComponent
4
- VERSION = '1.0.0'
4
+ VERSION = '1.1.0'
5
5
  end
@@ -2,7 +2,11 @@
2
2
 
3
3
  require 'active_support'
4
4
  require 'active_support/core_ext'
5
+ require 'pathname'
5
6
 
7
+ require_relative 'amber_component/configuration'
8
+
9
+ # Root module of the `amber_component` gem.
6
10
  module ::AmberComponent
7
11
  class Error < ::StandardError; end
8
12
  class MissingPropsError < Error; end
@@ -13,6 +17,22 @@ module ::AmberComponent
13
17
  class EmptyViewError < Error; end
14
18
  class UnknownViewTypeError < Error; end
15
19
  class MultipleViewsError < Error; end
20
+
21
+ # @return [Pathname]
22
+ ROOT_GEM_PATH = ::Pathname.new ::File.expand_path('..', __dir__)
23
+
24
+ class << self
25
+ # @return [Configuration]
26
+ def configuration
27
+ @configuration ||= Configuration.new
28
+ end
29
+
30
+ # @yieldparam [Configuration]
31
+ # @return [void]
32
+ def configure
33
+ yield configuration
34
+ end
35
+ end
16
36
  end
17
37
 
18
38
  require_relative 'amber_component/version'
@@ -10,8 +10,14 @@ module ::AmberComponent
10
10
  desc 'Install the AmberComponent gem'
11
11
  source_root ::File.expand_path('templates', __dir__)
12
12
 
13
- # copy rake tasks
14
- def copy_tasks
13
+ # @return [Array<Symbol>]
14
+ STIMULUS_INTEGRATIONS = %i[stimulus importmap jsbundling webpack esbuild rollup].freeze
15
+
16
+ class_option :stimulus,
17
+ desc: "Configure the app to use Stimulus.js wih components to make them interactive " \
18
+ "[options: importmap (default), jsbundling, webpack, esbuild, rollup]"
19
+
20
+ def setup
15
21
  copy_file 'application_component.rb', 'app/components/application_component.rb'
16
22
  copy_file 'application_component_test_case.rb', 'test/application_component_test_case.rb'
17
23
  append_file 'test/test_helper.rb', "require_relative 'application_component_test_case'"
@@ -23,10 +29,87 @@ module ::AmberComponent
23
29
  require_components_css_in 'app/assets/stylesheets/application.css.sass'
24
30
  require_components_css_in 'app/assets/stylesheets/application.scss.sass'
25
31
  require_components_css_in 'app/assets/stylesheets/application.sass.scss'
32
+ configure_stimulus
26
33
  end
27
34
 
28
35
  private
29
36
 
37
+ def configure_stimulus
38
+ stimulus = options[:stimulus]&.to_sym
39
+ return unless stimulus
40
+
41
+ case stimulus
42
+ when :stimulus
43
+ if defined?(::Jsbundling)
44
+ stimulus_integration = :jsbundling
45
+ configure_stimulus_jsbundling
46
+ else
47
+ stimulus_integration = :importmap
48
+ configure_stimulus_importmap
49
+ end
50
+ when :importmap
51
+ stimulus_integration = :importmap
52
+ configure_stimulus_importmap
53
+ when :jsbundling, :webpack, :esbuild, :rollup
54
+ stimulus_integration = :jsbundling
55
+ configure_stimulus_jsbundling
56
+ end
57
+
58
+ create_file 'config/initializers/amber_component.rb', <<~RUBY
59
+ # frozen_string_literal: true
60
+
61
+ ::AmberComponent.configure do |c|
62
+ c.stimulus = :#{stimulus_integration}
63
+ end
64
+ RUBY
65
+ end
66
+
67
+ def configure_stimulus_importmap
68
+ install_importmap
69
+ install_stimulus
70
+ append_file 'config/importmap.rb', <<~RUBY
71
+ pin "@amber_component/stimulus_loading", to: "amber_component/stimulus_loading.js", preload: true
72
+ pin_all_from "app/components"
73
+ RUBY
74
+ append_file 'app/javascript/controllers/index.js', <<~JS
75
+ import { eagerLoadAmberComponentControllers } from "@amber_component/stimulus_loading"
76
+ eagerLoadAmberComponentControllers(application)
77
+ JS
78
+ append_file 'app/assets/config/manifest.js', %(//= link_tree ../../components .js\n)
79
+ end
80
+
81
+ def configure_stimulus_jsbundling
82
+ install_stimulus
83
+ append_file 'app/javascript/application.js', %(import "./controllers/components"\n)
84
+ create_file 'app/javascript/controllers/components.js', <<~JS
85
+ // This file has been created by `amber_component` and will
86
+ // register all stimulus controllers from your components
87
+ import { application } from "./application"
88
+ JS
89
+ end
90
+
91
+ # @return [void]
92
+ def install_importmap
93
+ return if ::File.exist?('config/importmap.rb') && defined?(::Importmap)
94
+
95
+ unless defined?(::Importmap)
96
+ system 'gem install importmap-rails'
97
+ gem 'importmap-rails'
98
+ system 'bundle install'
99
+ end
100
+ rake 'importmap:install'
101
+ end
102
+
103
+ # @return [void]
104
+ def install_stimulus
105
+ return if defined?(::Stimulus)
106
+
107
+ system 'gem install stimulus-rails'
108
+ gem 'stimulus-rails'
109
+ system 'bundle install'
110
+ rake 'stimulus:install'
111
+ end
112
+
30
113
  # @param file_name [String]
31
114
  # @return [void]
32
115
  def require_components_css_in(file_name)
@@ -40,8 +40,10 @@ class AmberComponentGenerator < ::Rails::Generators::NamedBase
40
40
  template 'component_test.rb.erb', "test/components/#{file_path}_test.rb"
41
41
  create_stylesheet
42
42
  create_view
43
+ create_stimulus_controller
43
44
  end
44
45
 
46
+ # @return [String]
45
47
  def file_name
46
48
  name = super
47
49
  return name if name.end_with? '_component'
@@ -51,6 +53,29 @@ class AmberComponentGenerator < ::Rails::Generators::NamedBase
51
53
 
52
54
  private
53
55
 
56
+ # @return [Boolean]
57
+ def stimulus?
58
+ ::AmberComponent.configuration.stimulus?
59
+ end
60
+
61
+ # @return [Boolean]
62
+ def stimulus_importmap?
63
+ ::AmberComponent.configuration.stimulus_importmap?
64
+ end
65
+
66
+ # @return [void]
67
+ def create_stimulus_controller
68
+ return unless stimulus?
69
+
70
+ template 'controller.js.erb', "app/components/#{file_path}/controller.js"
71
+ return if stimulus_importmap?
72
+
73
+ append_file 'app/javascript/controllers/components.js', <<~JS
74
+ import #{stimulus_controller_class_name} from "../../components/#{file_path}/controller"
75
+ application.register("#{stimulus_controller_id}", #{stimulus_controller_class_name})
76
+ JS
77
+ end
78
+
54
79
  # @return [void]
55
80
  def create_view
56
81
  case @view_format
@@ -73,4 +98,14 @@ class AmberComponentGenerator < ::Rails::Generators::NamedBase
73
98
  template 'style.css.erb', "app/components/#{file_path}/style.css"
74
99
  end
75
100
  end
101
+
102
+ # @return [String]
103
+ def stimulus_controller_id
104
+ file_path.gsub('_', '-').gsub('/', '--')
105
+ end
106
+
107
+ # @return [String]
108
+ def stimulus_controller_class_name
109
+ file_path.gsub('/', '_').camelize
110
+ end
76
111
  end
@@ -0,0 +1,12 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+
3
+ // Read more about Stimulus here https://stimulus.hotwired.dev/
4
+ export default class extends Controller {
5
+ connect() {
6
+ console.log("Stimulus controller '<%= stimulus_controller_id %>' is connected!")
7
+ }
8
+
9
+ greet() {
10
+ alert("Hi there!")
11
+ }
12
+ }
@@ -1,9 +1,13 @@
1
- .<%= singular_table_name %>
1
+ .<%= singular_table_name %><%= %({ data: { controller: "#{stimulus_controller_id}" } }) if stimulus? %>
2
2
  %h1
3
3
  Hello from
4
4
  %b
5
5
  <%= class_name %>
6
6
  , initialized at:
7
7
  = @time
8
+ <%- if stimulus? %>
9
+ %button{ data: { action: "click-><%= stimulus_controller_id %>#greet" }
10
+ Greet me
11
+ <% end %>
8
12
  %p
9
13
  = description
@@ -1,7 +1,10 @@
1
- <div class='<%= singular_table_name %>'>
1
+ <div class="<%= singular_table_name %>"<%= %( data-controller="#{stimulus_controller_id}") if stimulus? %>>
2
2
  <h1>
3
3
  Hello from <b><%= class_name %></b>, initialized at: <%%= @time %>
4
4
  </h1>
5
+ <%- if stimulus? %>
6
+ <button data-action="click-><%= stimulus_controller_id %>#greet">Greet me</button>
7
+ <% end %>
5
8
  <p>
6
9
  <%%= description %>
7
10
  </p>
@@ -1,6 +1,10 @@
1
- div.<%= singular_table_name %>
1
+ div.<%= singular_table_name %><%= %( data-controller="#{stimulus_controller_id}") if stimulus? %>
2
2
  h1
3
3
  | Hello from
4
4
  b <%= class_name %>
5
5
  | , initialized at: #{@time}
6
+ <%- if stimulus? %>
7
+ button data-action="click-><%= stimulus_controller_id %>#greet"
8
+ | Greet me
9
+ <% end %>
6
10
  p = description
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amber_component
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ruby-Amber
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2022-11-07 00:00:00.000000000 Z
13
+ date: 2022-11-13 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: actionview
@@ -106,11 +106,13 @@ files:
106
106
  - README.md
107
107
  - Rakefile
108
108
  - amber_component.gemspec
109
+ - assets/javascripts/amber_component/stimulus_loading.js
109
110
  - banner.png
110
111
  - icon.png
111
112
  - lib/amber_component.rb
112
113
  - lib/amber_component/assets.rb
113
114
  - lib/amber_component/base.rb
115
+ - lib/amber_component/configuration.rb
114
116
  - lib/amber_component/helpers.rb
115
117
  - lib/amber_component/helpers/class_helper.rb
116
118
  - lib/amber_component/helpers/component_helper.rb
@@ -133,6 +135,7 @@ files:
133
135
  - lib/generators/component_generator.rb
134
136
  - lib/generators/templates/component.rb.erb
135
137
  - lib/generators/templates/component_test.rb.erb
138
+ - lib/generators/templates/controller.js.erb
136
139
  - lib/generators/templates/style.css.erb
137
140
  - lib/generators/templates/style.sass.erb
138
141
  - lib/generators/templates/style.scss.erb