phlex-stimulus 0.2.0 → 0.3.0
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 +126 -12
- data/lib/generators/phlex/stimulus/install/install_generator.rb +1 -0
- data/lib/generators/phlex/stimulus/install/templates/app/javascript/controllers/chain_controller.ts.erb +9 -0
- data/lib/generators/phlex/stimulus/install/templates/app/javascript/utils/misc.ts.erb +10 -1
- data/lib/phlex/stimulus/components/base.rb +22 -0
- data/lib/phlex/stimulus/components/controller.rb +90 -2
- data/lib/phlex/stimulus/version.rb +1 -1
- data/lib/tapioca/dsl/compilers/phlex_controller.rb +53 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f7130b1b0657eb83abc485ee417ef0df2f26179c78a8eb4dbdd507e94f42350d
|
|
4
|
+
data.tar.gz: 4edb623ff5c547ed266a26c8bd3f612d0ecd86869f102c851dda10c26fca6f0d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a94440b690254ad5a75deb5b6c4b9b6a7ba3bf069ce66e6448ca478b463e2b48739f70f479a7f224fc53d79104ec62f3802417de5e24498ca3484a108687dbb5
|
|
7
|
+
data.tar.gz: d3888457777dc1807b7c9d437a82c7086a0a5d9a098a5d397304754a4e07b64f75e3b47948a5410fd973e0d39a682953d4e94bcc55944deceaa4d5cb7e1c4edb
|
data/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
Add changes in new features here. Do not change the gem's version in pull/merge requests.
|
|
11
11
|
|
|
12
|
+
## [0.3.0] - 18.08.2026
|
|
13
|
+
|
|
14
|
+
[Diff](https://github.com/espago/phlex-stimulus/compare/v0.2.0...v0.3.0)
|
|
15
|
+
|
|
16
|
+
- Expand action parameter support
|
|
17
|
+
- Add `Components::Controller#merge` method for easily merging hashes
|
|
18
|
+
- Add a new action parameter definition DSL
|
|
19
|
+
- Add `_target_anchor` helpers to make attaching controller targets to DOM elements easier
|
|
20
|
+
- Add action `_on` helpers to attach controller actions to DOM event easier and more typesafe with action parameters
|
|
21
|
+
|
|
12
22
|
## [0.2.0] - 29.07.2026
|
|
13
23
|
|
|
14
24
|
[Diff](https://github.com/espago/phlex-stimulus/compare/v0.1.3...v0.2.0)
|
data/README.md
CHANGED
|
@@ -58,6 +58,10 @@ module Components
|
|
|
58
58
|
self.controller_name = 'summary'
|
|
59
59
|
|
|
60
60
|
actions :redirect # => defines SummaryController.redirect_action #=> "summary#redirect"
|
|
61
|
+
action :loadItem do # defines an action with action parameters
|
|
62
|
+
param :id # required action parameter
|
|
63
|
+
param :async, optional: true # optional action parameter
|
|
64
|
+
end
|
|
61
65
|
targets :body # => defines SummaryController.body_target #=> "body"
|
|
62
66
|
|
|
63
67
|
#: (title: String) -> void
|
|
@@ -81,11 +85,31 @@ You can render a controller like any other Phlex component:
|
|
|
81
85
|
|
|
82
86
|
```ruby
|
|
83
87
|
render SummaryController.new(title: 'Report') do
|
|
84
|
-
# define an action
|
|
88
|
+
# define an action with parameters
|
|
89
|
+
button(data: merge(SummaryController.load_item_on('click', id: '25'), other: 'data')) { 'Go' }
|
|
90
|
+
|
|
91
|
+
# define an action without param checking
|
|
85
92
|
button(data: { action: event('click', SummaryController.redirect_action) }) { 'Go' }
|
|
86
93
|
|
|
87
94
|
# define a target
|
|
88
|
-
div(data:
|
|
95
|
+
div(data: merge(SummaryController.body_target_anchor, other: "data")) do
|
|
96
|
+
plan "Foo"
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
This is the same as:
|
|
102
|
+
|
|
103
|
+
```rb
|
|
104
|
+
div(data: { controller: 'summary', title: 'Report' }) do
|
|
105
|
+
# define an action with parameters
|
|
106
|
+
button(data: { action: 'click->summary#loadItem', 'summary-id-param' => '25', other: 'data' }) { 'Go' }
|
|
107
|
+
|
|
108
|
+
# define an action
|
|
109
|
+
button(data: { action: 'click->summary#redirect', other: 'data' }) { 'Go' }
|
|
110
|
+
|
|
111
|
+
# define a target
|
|
112
|
+
div(data: { 'summary-target' => 'body', other: 'data' }) do
|
|
89
113
|
plan "Foo"
|
|
90
114
|
end
|
|
91
115
|
end
|
|
@@ -93,6 +117,47 @@ end
|
|
|
93
117
|
|
|
94
118
|
### Controller component helpers
|
|
95
119
|
|
|
120
|
+
#### `_on`
|
|
121
|
+
|
|
122
|
+
Each action you define will result in a corresponding `_on` method being available in Ruby.
|
|
123
|
+
Sorbet is fully aware of these methods thanks to a tapioca compiler.
|
|
124
|
+
|
|
125
|
+
These methods return an anchor hash that can be used as a value in `data:` to attach the
|
|
126
|
+
action with parameters to a DOM event on a particular DOM element.
|
|
127
|
+
|
|
128
|
+
You can read more about actions [here](https://stimulus.hotwired.dev/reference/actions).
|
|
129
|
+
|
|
130
|
+
```rb
|
|
131
|
+
class SummaryController < Controller
|
|
132
|
+
self.controller_name = 'summary'
|
|
133
|
+
|
|
134
|
+
actions :exit
|
|
135
|
+
|
|
136
|
+
action :loadItem do
|
|
137
|
+
param :id
|
|
138
|
+
param :async, optional: true
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
SummaryController.exit_on('click') #=> { action: "click->summary#exit" }
|
|
143
|
+
SummaryController.load_item_on('click', id: "25") #=> { action: "click->summary#loadItem", "summary-id-param" => "25" }
|
|
144
|
+
SummaryController.load_item_on('click', id: "25", async: "true") #=> { action: "click->summary#loadItem", "summary-id-param" => "25", "summary-async-param" => "true" }
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
This can be used to attach an action to an HTML element with full type safety including action params.
|
|
148
|
+
|
|
149
|
+
```rb
|
|
150
|
+
div(data: SummaryController.exit_on('click'))
|
|
151
|
+
div(data: merge(SummaryController.load_item_on('click', id: "69"), other: "data"))
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
This is the same as:
|
|
155
|
+
|
|
156
|
+
```rb
|
|
157
|
+
div(data: { action: 'click->summary#exit' })
|
|
158
|
+
div(data: { action: 'click->summary#loadItem', 'summary-id-param' => '69', other: 'data' })
|
|
159
|
+
```
|
|
160
|
+
|
|
96
161
|
#### `_action`
|
|
97
162
|
|
|
98
163
|
Each action you define will result in a corresponding `_action` method being available in Ruby.
|
|
@@ -126,14 +191,12 @@ This is the same as:
|
|
|
126
191
|
div(data: { action: 'click->summary#foo' })
|
|
127
192
|
```
|
|
128
193
|
|
|
129
|
-
#### `
|
|
194
|
+
#### `_target_anchor`
|
|
130
195
|
|
|
131
|
-
Each target you define will result in a corresponding `
|
|
196
|
+
Each target you define will result in a corresponding `_target_anchor` method being available in Ruby.
|
|
132
197
|
Sorbet is fully aware of these methods thanks to a tapioca compiler.
|
|
133
198
|
|
|
134
|
-
These methods
|
|
135
|
-
They exist only so that sorbet can check if the actions your using when building HTML elements
|
|
136
|
-
actually exist.
|
|
199
|
+
These methods return a hash that can be used to attach the target.
|
|
137
200
|
|
|
138
201
|
You can read more about targets [here](https://stimulus.hotwired.dev/reference/targets).
|
|
139
202
|
|
|
@@ -144,13 +207,13 @@ class SummaryController < Controller
|
|
|
144
207
|
targets :foo
|
|
145
208
|
end
|
|
146
209
|
|
|
147
|
-
SummaryController.
|
|
210
|
+
SummaryController.foo_target_anchor #=> { "summary-target" => "foo" }
|
|
148
211
|
```
|
|
149
212
|
|
|
150
213
|
You would use it like so to attach a target with full type safety:
|
|
151
214
|
|
|
152
215
|
```rb
|
|
153
|
-
div(data:
|
|
216
|
+
div(data: SummaryController.foo_target_anchor)
|
|
154
217
|
```
|
|
155
218
|
|
|
156
219
|
This is the same as:
|
|
@@ -159,6 +222,19 @@ This is the same as:
|
|
|
159
222
|
div(data: { 'summary-target' => 'foo' })
|
|
160
223
|
```
|
|
161
224
|
|
|
225
|
+
You can use `merge` to add other keys alongside the anchor to `data`.
|
|
226
|
+
|
|
227
|
+
```rb
|
|
228
|
+
div(data: merge(SummaryController.foo_target_anchor, bar: 'elo'))
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
This is the same as:
|
|
232
|
+
|
|
233
|
+
```rb
|
|
234
|
+
div(data: { 'summary-target' => 'foo', bar: 'elo' })
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
|
|
162
238
|
#### `target_key`
|
|
163
239
|
|
|
164
240
|
This method returns the key that can be used to attach targets to the controller.
|
|
@@ -185,6 +261,39 @@ This is the same as:
|
|
|
185
261
|
div(data: { 'summary-target' => 'foo' })
|
|
186
262
|
```
|
|
187
263
|
|
|
264
|
+
#### `_target`
|
|
265
|
+
|
|
266
|
+
Each target you define will result in a corresponding `_target` method being available in Ruby.
|
|
267
|
+
Sorbet is fully aware of these methods thanks to a tapioca compiler.
|
|
268
|
+
|
|
269
|
+
These methods just return the name of the target so they may seem pointless.
|
|
270
|
+
They exist only so that sorbet can check if the actions your using when building HTML elements
|
|
271
|
+
actually exist.
|
|
272
|
+
|
|
273
|
+
You can read more about targets [here](https://stimulus.hotwired.dev/reference/targets).
|
|
274
|
+
|
|
275
|
+
```rb
|
|
276
|
+
class SummaryController < Controller
|
|
277
|
+
self.controller_name = 'summary'
|
|
278
|
+
|
|
279
|
+
targets :foo
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
SummaryController.foo_target #=> "foo"
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
You would use it like so to attach a target with full type safety:
|
|
286
|
+
|
|
287
|
+
```rb
|
|
288
|
+
div(data: { SummaryController.target_key => SummaryController.foo_target })
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
This is the same as:
|
|
292
|
+
|
|
293
|
+
```rb
|
|
294
|
+
div(data: { 'summary-target' => 'foo' })
|
|
295
|
+
```
|
|
296
|
+
|
|
188
297
|
#### `dispatched`
|
|
189
298
|
|
|
190
299
|
This method helps you get the names of custom events dispatched by a stimulus controller.
|
|
@@ -207,7 +316,7 @@ div(data: { action: event(SummaryController.dispatched('redirected'), OtherContr
|
|
|
207
316
|
This is the same as:
|
|
208
317
|
|
|
209
318
|
```rb
|
|
210
|
-
div(data: { 'summary:redirected
|
|
319
|
+
div(data: { action: 'summary:redirected->other#do' })
|
|
211
320
|
```
|
|
212
321
|
|
|
213
322
|
#### `param`
|
|
@@ -233,7 +342,7 @@ div(
|
|
|
233
342
|
data: {
|
|
234
343
|
action: event('click', SummaryController.foo_action),
|
|
235
344
|
# will be available as `event.id` in the action
|
|
236
|
-
SummaryController.param('id') => 35,
|
|
345
|
+
SummaryController.param('id') => '35',
|
|
237
346
|
},
|
|
238
347
|
)
|
|
239
348
|
```
|
|
@@ -241,7 +350,12 @@ div(
|
|
|
241
350
|
This is the same as:
|
|
242
351
|
|
|
243
352
|
```rb
|
|
244
|
-
div(
|
|
353
|
+
div(
|
|
354
|
+
data: {
|
|
355
|
+
action: 'click->summary#foo',
|
|
356
|
+
'summary-id-param' => '35',
|
|
357
|
+
},
|
|
358
|
+
)
|
|
245
359
|
```
|
|
246
360
|
|
|
247
361
|
### Component Helpers
|
|
@@ -44,6 +44,7 @@ module Phlex::Stimulus::Generators
|
|
|
44
44
|
remove_file File.join(destination_root, 'app/javascript/application.js')
|
|
45
45
|
copy_template 'app/javascript/application.ts'
|
|
46
46
|
|
|
47
|
+
remove_file File.join(destination_root, 'app/javascript/controllers/hello_controller.js')
|
|
47
48
|
remove_file File.join(destination_root, 'app/javascript/controllers/application.js')
|
|
48
49
|
copy_template 'app/javascript/controllers/application.ts'
|
|
49
50
|
|
|
@@ -10,6 +10,7 @@ import { Controller } from "@hotwired/stimulus"
|
|
|
10
10
|
**/
|
|
11
11
|
class ChainController extends Controller<HTMLElement> {
|
|
12
12
|
controllerChain!: string
|
|
13
|
+
disconnected: boolean | undefined
|
|
13
14
|
|
|
14
15
|
async connect() {
|
|
15
16
|
let dataset = this.element.dataset
|
|
@@ -17,6 +18,10 @@ class ChainController extends Controller<HTMLElement> {
|
|
|
17
18
|
|
|
18
19
|
let i = 0
|
|
19
20
|
for (let controllerName of this.controllerChain.split(' ')) {
|
|
21
|
+
if (this.disconnected) {
|
|
22
|
+
return
|
|
23
|
+
}
|
|
24
|
+
|
|
20
25
|
let controllerTemplate = this.element.querySelector(`template.${controllerName}-template-${i}`) as HTMLTemplateElement
|
|
21
26
|
let controllerElement = document.importNode(controllerTemplate.content, true)
|
|
22
27
|
let readyPromise = addEventPromise(this.element, `${controllerName}:ready`)
|
|
@@ -27,6 +32,10 @@ class ChainController extends Controller<HTMLElement> {
|
|
|
27
32
|
i++
|
|
28
33
|
}
|
|
29
34
|
}
|
|
35
|
+
|
|
36
|
+
disconnect(): void {
|
|
37
|
+
this.disconnected = true
|
|
38
|
+
}
|
|
30
39
|
}
|
|
31
40
|
|
|
32
41
|
application.register("chain", ChainController)
|
|
@@ -32,6 +32,15 @@ export function sleep(timeout: number | undefined): Promise<void> {
|
|
|
32
32
|
*/
|
|
33
33
|
export function addEventPromise(target: EventTarget, type: string): Promise<Event> {
|
|
34
34
|
return new Promise((resolve) => {
|
|
35
|
-
|
|
35
|
+
const aborter = new AbortController()
|
|
36
|
+
|
|
37
|
+
target.addEventListener(
|
|
38
|
+
type,
|
|
39
|
+
(event) => {
|
|
40
|
+
aborter.abort()
|
|
41
|
+
resolve(event)
|
|
42
|
+
},
|
|
43
|
+
{ signal: aborter.signal },
|
|
44
|
+
)
|
|
36
45
|
})
|
|
37
46
|
}
|
|
@@ -7,6 +7,18 @@ module Phlex::Stimulus
|
|
|
7
7
|
#
|
|
8
8
|
# @abstract
|
|
9
9
|
class Base < Phlex::HTML
|
|
10
|
+
class << self
|
|
11
|
+
# Constructs a Stimulus event hook string
|
|
12
|
+
# eg.
|
|
13
|
+
#
|
|
14
|
+
# event('click', 'summary#redirect') #=> "click->summary#redirect"
|
|
15
|
+
#
|
|
16
|
+
#: (String, String) -> String
|
|
17
|
+
def event(event_name, full_action_name)
|
|
18
|
+
"#{event_name}->#{full_action_name}"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
10
22
|
def h = view_context
|
|
11
23
|
|
|
12
24
|
#: -> String
|
|
@@ -70,6 +82,16 @@ module Phlex::Stimulus
|
|
|
70
82
|
alias strlist class_list
|
|
71
83
|
alias strlist! class_list!
|
|
72
84
|
|
|
85
|
+
# Merges the given list of hashes (with optional nils)
|
|
86
|
+
# into a single hash.
|
|
87
|
+
#
|
|
88
|
+
#: [K, V] (*Hash[K, V]?) -> Hash[K, V]
|
|
89
|
+
def merge(*hashes)
|
|
90
|
+
hashes.each_with_object({}) do |elem, acc|
|
|
91
|
+
acc.merge!(elem) if elem
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
73
95
|
#: (String) -> bool
|
|
74
96
|
def image_exists?(path)
|
|
75
97
|
Boolean(h.resolve_asset_path(path))
|
|
@@ -13,11 +13,14 @@ module Phlex::Stimulus
|
|
|
13
13
|
attr_reader :component
|
|
14
14
|
#: String
|
|
15
15
|
attr_reader :action_name
|
|
16
|
+
#: Array[ActionParamDefinition]
|
|
17
|
+
attr_reader :params
|
|
16
18
|
|
|
17
|
-
#: (component: singleton(Controller), action_name: String) -> void
|
|
18
|
-
def initialize(component:, action_name:)
|
|
19
|
+
#: (component: singleton(Controller), action_name: String, ?params: Array[ActionParamDefinition]) -> void
|
|
20
|
+
def initialize(component:, action_name:, params: [])
|
|
19
21
|
@component = component
|
|
20
22
|
@action_name = action_name
|
|
23
|
+
@params = params
|
|
21
24
|
end
|
|
22
25
|
|
|
23
26
|
#: -> String
|
|
@@ -34,6 +37,36 @@ module Phlex::Stimulus
|
|
|
34
37
|
def ruby_action_method_name
|
|
35
38
|
"#{ruby_name}_action"
|
|
36
39
|
end
|
|
40
|
+
|
|
41
|
+
#: -> String
|
|
42
|
+
def ruby_on_method_name
|
|
43
|
+
"#{ruby_name}_on"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Define a new parameter for the controller action.
|
|
47
|
+
#
|
|
48
|
+
#: (Symbol, ?optional: bool) -> ActionParamDefinition
|
|
49
|
+
def param(name, optional: false)
|
|
50
|
+
p = ActionParamDefinition.new(action: self, param_name: name.to_s, optional: optional)
|
|
51
|
+
params << p
|
|
52
|
+
p
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class ActionParamDefinition
|
|
57
|
+
#: ActionDefinition
|
|
58
|
+
attr_reader :action
|
|
59
|
+
#: String
|
|
60
|
+
attr_reader :param_name
|
|
61
|
+
#: bool
|
|
62
|
+
attr_reader :optional
|
|
63
|
+
|
|
64
|
+
#: (action: ActionDefinition, param_name: String, ?optional: bool) -> void
|
|
65
|
+
def initialize(action:, param_name:, optional: false)
|
|
66
|
+
@action = action
|
|
67
|
+
@param_name = param_name
|
|
68
|
+
@optional = optional
|
|
69
|
+
end
|
|
37
70
|
end
|
|
38
71
|
|
|
39
72
|
class TargetDefinition
|
|
@@ -57,6 +90,11 @@ module Phlex::Stimulus
|
|
|
57
90
|
def ruby_target_method_name
|
|
58
91
|
"#{ruby_name}_target"
|
|
59
92
|
end
|
|
93
|
+
|
|
94
|
+
#: -> String
|
|
95
|
+
def ruby_target_anchor_method_name
|
|
96
|
+
"#{ruby_name}_target_anchor"
|
|
97
|
+
end
|
|
60
98
|
end
|
|
61
99
|
|
|
62
100
|
class << self
|
|
@@ -120,9 +158,51 @@ module Phlex::Stimulus
|
|
|
120
158
|
"data-#{target_key}"
|
|
121
159
|
end
|
|
122
160
|
|
|
161
|
+
# Register an action with parameters that exists on the Stimulus controller.
|
|
162
|
+
#
|
|
163
|
+
# action :foo do
|
|
164
|
+
# param :id
|
|
165
|
+
# param :title, optional: true
|
|
166
|
+
# end
|
|
167
|
+
#
|
|
168
|
+
#: (Symbol) ?{ [self: ActionDefinition] -> void } -> void
|
|
169
|
+
def action(name, &block)
|
|
170
|
+
action_def = ActionDefinition.new(
|
|
171
|
+
component: self,
|
|
172
|
+
action_name: name.to_s,
|
|
173
|
+
)
|
|
174
|
+
action_defs << action_def
|
|
175
|
+
action_def.instance_eval(&block) if block
|
|
176
|
+
|
|
177
|
+
eval_buff = String.new
|
|
178
|
+
eval_buff << <<~RUBY
|
|
179
|
+
def #{action_def.ruby_action_method_name}
|
|
180
|
+
"\#{controller_name}##{name}"
|
|
181
|
+
end
|
|
182
|
+
RUBY
|
|
183
|
+
|
|
184
|
+
eval_buff << "\ndef #{action_def.ruby_on_method_name}(event_name"
|
|
185
|
+
action_def.params.each do |param|
|
|
186
|
+
eval_buff << ", #{param.param_name}:"
|
|
187
|
+
eval_buff << ' nil' if param.optional
|
|
188
|
+
end
|
|
189
|
+
eval_buff << ")\n"
|
|
190
|
+
|
|
191
|
+
eval_buff << "{ action: event(event_name, #{action_def.ruby_action_method_name}), "
|
|
192
|
+
action_def.params.each do |param|
|
|
193
|
+
eval_buff << "param(#{param.param_name.inspect}) => #{param.param_name}, "
|
|
194
|
+
end
|
|
195
|
+
eval_buff << "}.compact\n"
|
|
196
|
+
eval_buff << "end\n"
|
|
197
|
+
|
|
198
|
+
instance_eval eval_buff, __FILE__, __LINE__
|
|
199
|
+
end
|
|
200
|
+
|
|
123
201
|
# Register actions that exist on the Stimulus controller.
|
|
124
202
|
# Will define typed getter methods for each action.
|
|
125
203
|
#
|
|
204
|
+
# actions :foo, :bar
|
|
205
|
+
#
|
|
126
206
|
#: (*Symbol) -> void
|
|
127
207
|
def actions(*actions)
|
|
128
208
|
actions.each do |action|
|
|
@@ -136,6 +216,10 @@ module Phlex::Stimulus
|
|
|
136
216
|
def #{action_def.ruby_action_method_name}
|
|
137
217
|
"\#{controller_name}##{action}"
|
|
138
218
|
end
|
|
219
|
+
|
|
220
|
+
def #{action_def.ruby_on_method_name}(event_name)
|
|
221
|
+
{ action: event(event_name, #{action_def.ruby_action_method_name}) }
|
|
222
|
+
end
|
|
139
223
|
RUBY
|
|
140
224
|
end
|
|
141
225
|
end
|
|
@@ -157,6 +241,10 @@ module Phlex::Stimulus
|
|
|
157
241
|
def #{target_def.ruby_target_method_name}
|
|
158
242
|
#{target_str.inspect}
|
|
159
243
|
end
|
|
244
|
+
|
|
245
|
+
def #{target_def.ruby_target_anchor_method_name}
|
|
246
|
+
{ target_key => #{target_str.inspect} }
|
|
247
|
+
end
|
|
160
248
|
RUBY
|
|
161
249
|
end
|
|
162
250
|
end
|
|
@@ -50,6 +50,42 @@ module Tapioca
|
|
|
50
50
|
return_type: 'String',
|
|
51
51
|
comments: comments,
|
|
52
52
|
)
|
|
53
|
+
|
|
54
|
+
comments = [
|
|
55
|
+
RBI::Comment.new(
|
|
56
|
+
<<~DOC,
|
|
57
|
+
Returns na anchor hash that can be used to attach `#{action.action_name}`
|
|
58
|
+
action on `#{action.component.controller_name.inspect}` Stimulus controller
|
|
59
|
+
to a particular DOM event.
|
|
60
|
+
DOC
|
|
61
|
+
),
|
|
62
|
+
]
|
|
63
|
+
mod.create_method(
|
|
64
|
+
action.ruby_on_method_name,
|
|
65
|
+
comments: comments,
|
|
66
|
+
) do |method|
|
|
67
|
+
method.add_param('event_name')
|
|
68
|
+
action.params.each do |param|
|
|
69
|
+
if param.optional
|
|
70
|
+
method.add_kw_opt_param(param.param_name, 'nil')
|
|
71
|
+
else
|
|
72
|
+
method.add_kw_param(param.param_name)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
method.add_sig do |sig|
|
|
77
|
+
sig.return_type = 'T::Hash[T.any(Symbol, String), String]'
|
|
78
|
+
|
|
79
|
+
sig.add_param('event_name', 'String')
|
|
80
|
+
action.params.each do |param|
|
|
81
|
+
if param.optional
|
|
82
|
+
sig.add_param(param.param_name, 'T.nilable(String)')
|
|
83
|
+
else
|
|
84
|
+
sig.add_param(param.param_name, 'String')
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
53
89
|
end
|
|
54
90
|
|
|
55
91
|
targets = constant.target_defs.sort_by(&:target_name)
|
|
@@ -69,6 +105,23 @@ module Tapioca
|
|
|
69
105
|
return_type: 'String',
|
|
70
106
|
comments: comments,
|
|
71
107
|
)
|
|
108
|
+
|
|
109
|
+
comments = [
|
|
110
|
+
RBI::Comment.new(
|
|
111
|
+
<<~DOC,
|
|
112
|
+
Returns an anchor hash for `#{target.target_name}`
|
|
113
|
+
target on `#{target.component.controller_name.inspect}` Stimulus controller
|
|
114
|
+
that can be used to attach this target to a particular DOM element.
|
|
115
|
+
|
|
116
|
+
Result: `{ #{constant.target_key} => #{target.target_name.inspect} }`
|
|
117
|
+
DOC
|
|
118
|
+
),
|
|
119
|
+
]
|
|
120
|
+
mod.create_method(
|
|
121
|
+
target.ruby_target_anchor_method_name,
|
|
122
|
+
return_type: 'T::Hash[String, String]',
|
|
123
|
+
comments: comments,
|
|
124
|
+
)
|
|
72
125
|
end
|
|
73
126
|
|
|
74
127
|
end
|