hotwire_combobox 0.1.10 → 0.1.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/MIT-LICENSE +1 -1
- data/README.md +1 -4
- data/app/assets/javascripts/controllers/hw_combobox_controller.js +55 -211
- data/app/assets/javascripts/helpers.js +52 -0
- data/app/assets/javascripts/models/combobox/actors.js +24 -0
- data/app/assets/javascripts/models/combobox/async_loading.js +7 -0
- data/app/assets/javascripts/models/combobox/autocomplete.js +39 -0
- data/app/assets/javascripts/models/combobox/base.js +3 -0
- data/app/assets/javascripts/models/combobox/dialog.js +50 -0
- data/app/assets/javascripts/models/combobox/filtering.js +57 -0
- data/app/assets/javascripts/models/combobox/navigation.js +39 -0
- data/app/assets/javascripts/models/combobox/options.js +41 -0
- data/app/assets/javascripts/models/combobox/selection.js +62 -0
- data/app/assets/javascripts/models/combobox/toggle.js +104 -0
- data/app/assets/javascripts/models/combobox/validity.js +34 -0
- data/app/assets/javascripts/models/combobox.js +14 -0
- data/app/assets/javascripts/vendor/bodyScrollLock.js +299 -0
- data/app/assets/stylesheets/hotwire_combobox.css +181 -0
- data/app/helpers/hotwire_combobox/helper.rb +62 -73
- data/app/presenters/hotwire_combobox/component.rb +257 -0
- data/app/presenters/hotwire_combobox/listbox/option.rb +53 -0
- data/app/views/hotwire_combobox/_combobox.html.erb +5 -20
- data/app/views/hotwire_combobox/_next_page.turbo_stream.erb +5 -0
- data/app/views/hotwire_combobox/_paginated_options.turbo_stream.erb +7 -0
- data/app/views/hotwire_combobox/_pagination.html.erb +3 -0
- data/app/views/hotwire_combobox/combobox/_dialog.html.erb +7 -0
- data/app/views/hotwire_combobox/combobox/_hidden_field.html.erb +4 -0
- data/app/views/hotwire_combobox/combobox/_input.html.erb +2 -0
- data/app/views/hotwire_combobox/combobox/_paginated_listbox.html.erb +11 -0
- data/lib/hotwire_combobox/engine.rb +12 -2
- data/lib/hotwire_combobox/version.rb +1 -1
- data/lib/hotwire_combobox.rb +4 -2
- metadata +54 -2
@@ -2,104 +2,93 @@ module HotwireCombobox
|
|
2
2
|
module Helper
|
3
3
|
class << self
|
4
4
|
delegate :bypass_convenience_methods?, to: :HotwireCombobox
|
5
|
-
end
|
6
|
-
|
7
|
-
def hw_combobox_options(options)
|
8
|
-
options.map { |option| hw_combobox_option(**option) }
|
9
|
-
end
|
10
|
-
alias_method :combobox_options, :hw_combobox_options unless bypass_convenience_methods?
|
11
5
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
h[:data] = default_hw_combobox_value_field_data
|
17
|
-
h[:value] = form&.object&.public_send(name) || value
|
6
|
+
def hw(method_name)
|
7
|
+
unless bypass_convenience_methods?
|
8
|
+
alias_method method_name.to_s.sub(/^hw_/, ""), method_name
|
9
|
+
end
|
18
10
|
end
|
19
|
-
|
20
|
-
attrs[:type] ||= :text
|
21
|
-
attrs[:role] = :combobox
|
22
|
-
attrs[:id] = hw_combobox_id value_field_attrs[:id]
|
23
|
-
attrs[:data] = default_hw_combobox_data input.fetch(:data, {})
|
24
|
-
attrs[:aria] = default_hw_combobox_aria value_field_attrs, input.fetch(:aria, {})
|
25
|
-
|
26
|
-
render "hotwire_combobox/combobox", options: options,
|
27
|
-
attrs: attrs, value_field_attrs: value_field_attrs,
|
28
|
-
listbox_id: hw_combobox_listbox_id(value_field_attrs[:id]),
|
29
|
-
parent_data: default_hw_combobox_parent_data(attrs, data)
|
30
11
|
end
|
31
|
-
alias_method :combobox_tag, :hw_combobox_tag unless bypass_convenience_methods?
|
32
12
|
|
33
|
-
def
|
34
|
-
|
13
|
+
hw def hw_combobox_style_tag(*args, **kwargs)
|
14
|
+
stylesheet_link_tag HotwireCombobox.stylesheet_path, *args, **kwargs
|
35
15
|
end
|
36
16
|
|
37
|
-
def
|
38
|
-
|
17
|
+
hw def hw_combobox_tag(*args, async_src: nil, options: [], render_in: {}, **kwargs)
|
18
|
+
options = hw_combobox_options options, render_in: render_in
|
19
|
+
src = hw_uri_with_params async_src, format: :turbo_stream
|
20
|
+
component = HotwireCombobox::Component.new self, *args, options: options, async_src: src, **kwargs
|
21
|
+
|
22
|
+
render "hotwire_combobox/combobox", component: component
|
39
23
|
end
|
40
24
|
|
41
|
-
def
|
42
|
-
|
25
|
+
hw def hw_combobox_options(options, render_in: {}, display: :to_combobox_display, **methods)
|
26
|
+
if options.first.is_a? HotwireCombobox::Listbox::Option
|
27
|
+
options
|
28
|
+
else
|
29
|
+
content = if render_in.present?
|
30
|
+
->(object) { render(**render_in.merge(object: object)) }
|
31
|
+
else
|
32
|
+
methods[:content]
|
33
|
+
end
|
34
|
+
|
35
|
+
hw_parse_combobox_options options, **methods.merge(display: display, content: content)
|
36
|
+
end
|
43
37
|
end
|
44
38
|
|
45
|
-
def
|
46
|
-
|
39
|
+
hw def hw_paginated_combobox_options(options, for_id:, src:, next_page:, render_in: {}, **methods)
|
40
|
+
this_page = render("hotwire_combobox/paginated_options", for_id: for_id, options: hw_combobox_options(options, render_in: render_in, **methods), format: :turbo_stream)
|
41
|
+
next_page = render("hotwire_combobox/next_page", src: src, next_page: next_page, format: :turbo_stream)
|
42
|
+
|
43
|
+
safe_join [ this_page, next_page ]
|
47
44
|
end
|
48
45
|
|
49
|
-
def
|
50
|
-
|
46
|
+
hw def hw_listbox_options_id(id)
|
47
|
+
"#{id}-hw-listbox__options"
|
51
48
|
end
|
52
49
|
|
53
50
|
private
|
54
|
-
def
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
def default_hw_combobox_value_field_name(form, name)
|
63
|
-
form&.field_name(name) || name
|
64
|
-
end
|
65
|
-
|
66
|
-
def default_hw_combobox_value_field_data
|
67
|
-
{ "hw-combobox-target": "valueField" }
|
51
|
+
def hw_uri_with_params(url_or_path, **params)
|
52
|
+
URI.parse(url_or_path).tap do |url_or_path|
|
53
|
+
query = URI.decode_www_form(url_or_path.query || "").to_h.merge(params)
|
54
|
+
url_or_path.query = URI.encode_www_form query
|
55
|
+
end.to_s
|
56
|
+
rescue URI::InvalidURIError
|
57
|
+
url_or_path
|
68
58
|
end
|
69
59
|
|
70
|
-
def
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
keydown->hw-combobox#navigate
|
76
|
-
click@window->hw-combobox#closeOnClickOutside
|
77
|
-
focusin@window->hw-combobox#closeOnFocusOutside".squish,
|
78
|
-
"hw-combobox-target": "combobox"
|
60
|
+
def hw_parse_combobox_options(options, **methods)
|
61
|
+
options.map do |option|
|
62
|
+
attrs = option.is_a?(Hash) ? option : hw_option_attrs_for_obj(option, **methods)
|
63
|
+
HotwireCombobox::Listbox::Option.new **attrs
|
64
|
+
end
|
79
65
|
end
|
80
66
|
|
81
|
-
def
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
67
|
+
def hw_option_attrs_for_obj(option, **methods)
|
68
|
+
{}.tap do |attrs|
|
69
|
+
attrs[:id] = hw_call_method_or_proc(option, methods[:id]) if methods[:id]
|
70
|
+
attrs[:value] = hw_call_method_or_proc(option, methods[:value] || :id)
|
71
|
+
attrs[:display] = hw_call_method_or_proc(option, methods[:display]) if methods[:display]
|
72
|
+
attrs[:content] = hw_call_method_or_proc(option, methods[:content]) if methods[:content]
|
73
|
+
end
|
87
74
|
end
|
88
75
|
|
89
|
-
def
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
76
|
+
def hw_call_method_or_proc(object, method_or_proc)
|
77
|
+
if method_or_proc.is_a? Proc
|
78
|
+
method_or_proc.call object
|
79
|
+
else
|
80
|
+
object.public_send method_or_proc
|
81
|
+
end
|
95
82
|
end
|
96
83
|
|
97
|
-
def
|
98
|
-
|
84
|
+
def hw_combobox_next_page_uri(uri, next_page)
|
85
|
+
if next_page
|
86
|
+
hw_uri_with_params uri, page: next_page, q: params[:q], format: :turbo_stream
|
87
|
+
end
|
99
88
|
end
|
100
89
|
|
101
|
-
def
|
102
|
-
|
90
|
+
def hw_combobox_page_stream_action
|
91
|
+
params[:page] ? :append : :update
|
103
92
|
end
|
104
93
|
end
|
105
94
|
end
|
@@ -0,0 +1,257 @@
|
|
1
|
+
class HotwireCombobox::Component
|
2
|
+
attr_reader :async_src, :options, :dialog_label
|
3
|
+
|
4
|
+
def initialize(
|
5
|
+
view, name, value = nil,
|
6
|
+
autocomplete: :both,
|
7
|
+
id: nil,
|
8
|
+
form: nil,
|
9
|
+
name_when_new: nil,
|
10
|
+
open: false,
|
11
|
+
small_width: "640px",
|
12
|
+
async_src: nil,
|
13
|
+
dialog_label: nil,
|
14
|
+
options: [], data: {}, input: {}, **rest)
|
15
|
+
@combobox_attrs = input.reverse_merge(rest).with_indifferent_access
|
16
|
+
|
17
|
+
@view, @autocomplete, @id, @name, @value, @form, @async_src,
|
18
|
+
@name_when_new, @open, @data, @small_width, @options, @dialog_label =
|
19
|
+
view, autocomplete, id, name, value, form, async_src,
|
20
|
+
name_when_new, open, data, small_width, options, dialog_label
|
21
|
+
end
|
22
|
+
|
23
|
+
def fieldset_attrs
|
24
|
+
{
|
25
|
+
class: "hw-combobox",
|
26
|
+
data: fieldset_data
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def hidden_field_attrs
|
32
|
+
{
|
33
|
+
id: hidden_field_id,
|
34
|
+
name: hidden_field_name,
|
35
|
+
data: hidden_field_data,
|
36
|
+
value: hidden_field_value
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def input_attrs
|
42
|
+
nested_attrs = %i[ data aria ]
|
43
|
+
|
44
|
+
{
|
45
|
+
id: input_id,
|
46
|
+
role: :combobox,
|
47
|
+
class: "hw-combobox__input",
|
48
|
+
type: input_type,
|
49
|
+
data: input_data,
|
50
|
+
aria: input_aria
|
51
|
+
}.merge combobox_attrs.except(*nested_attrs)
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def handle_attrs
|
56
|
+
{
|
57
|
+
class: "hw-combobox__handle",
|
58
|
+
data: handle_data
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
def listbox_attrs
|
64
|
+
{
|
65
|
+
id: listbox_id,
|
66
|
+
role: :listbox,
|
67
|
+
class: "hw-combobox__listbox",
|
68
|
+
hidden: "",
|
69
|
+
data: listbox_data
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
def listbox_options_attrs
|
75
|
+
{ id: listbox_options_id }
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
def dialog_attrs
|
80
|
+
{
|
81
|
+
class: "hw-combobox__dialog",
|
82
|
+
role: :dialog,
|
83
|
+
data: dialog_data
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
def dialog_label_attrs
|
88
|
+
{
|
89
|
+
class: "hw-combobox__dialog__label",
|
90
|
+
for: dialog_input_id
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
def dialog_input_attrs
|
95
|
+
{
|
96
|
+
id: dialog_input_id,
|
97
|
+
role: :combobox,
|
98
|
+
class: "hw-combobox__dialog__input",
|
99
|
+
autofocus: "",
|
100
|
+
type: input_type,
|
101
|
+
data: dialog_input_data,
|
102
|
+
aria: dialog_input_aria
|
103
|
+
}
|
104
|
+
end
|
105
|
+
|
106
|
+
def dialog_listbox_attrs
|
107
|
+
{
|
108
|
+
id: dialog_listbox_id,
|
109
|
+
class: "hw-combobox__dialog__listbox",
|
110
|
+
role: :listbox,
|
111
|
+
data: dialog_listbox_data
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
115
|
+
def dialog_focus_trap_attrs
|
116
|
+
{
|
117
|
+
tabindex: "-1",
|
118
|
+
data: dialog_focus_trap_data
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
def paginated?
|
124
|
+
async_src.present?
|
125
|
+
end
|
126
|
+
|
127
|
+
def pagination_attrs
|
128
|
+
{ src: async_src }
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
attr_reader :view, :autocomplete, :id, :name, :value, :form,
|
133
|
+
:name_when_new, :open, :data, :combobox_attrs, :small_width
|
134
|
+
|
135
|
+
def fieldset_data
|
136
|
+
data.reverse_merge \
|
137
|
+
controller: view.token_list("hw-combobox", data[:controller]),
|
138
|
+
hw_combobox_expanded_value: open,
|
139
|
+
hw_combobox_name_when_new_value: name_when_new,
|
140
|
+
hw_combobox_original_name_value: hidden_field_name,
|
141
|
+
hw_combobox_autocomplete_value: autocomplete,
|
142
|
+
hw_combobox_small_viewport_max_width_value: small_width,
|
143
|
+
hw_combobox_async_src_value: async_src,
|
144
|
+
hw_combobox_filterable_attribute_value: "data-filterable-as",
|
145
|
+
hw_combobox_autocompletable_attribute_value: "data-autocompletable-as",
|
146
|
+
hw_combobox_selected_class: "hw-combobox__option--selected"
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
def hidden_field_id
|
151
|
+
id || form&.field_id(name)
|
152
|
+
end
|
153
|
+
|
154
|
+
def hidden_field_name
|
155
|
+
form&.field_name(name) || name
|
156
|
+
end
|
157
|
+
|
158
|
+
def hidden_field_data
|
159
|
+
{ hw_combobox_target: "hiddenField" }
|
160
|
+
end
|
161
|
+
|
162
|
+
def hidden_field_value
|
163
|
+
form&.object&.public_send(name) || value
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
def input_id
|
168
|
+
"#{hidden_field_id}-hw-combobox"
|
169
|
+
end
|
170
|
+
|
171
|
+
def input_type
|
172
|
+
combobox_attrs[:type].to_s.presence_in(%w[ text search ]) || "text"
|
173
|
+
end
|
174
|
+
|
175
|
+
def input_data
|
176
|
+
combobox_attrs.fetch(:data, {}).reverse_merge! \
|
177
|
+
action: "
|
178
|
+
focus->hw-combobox#open
|
179
|
+
input->hw-combobox#filter
|
180
|
+
keydown->hw-combobox#navigate
|
181
|
+
click@window->hw-combobox#closeOnClickOutside
|
182
|
+
focusin@window->hw-combobox#closeOnFocusOutside".squish,
|
183
|
+
hw_combobox_target: "combobox"
|
184
|
+
end
|
185
|
+
|
186
|
+
def input_aria
|
187
|
+
combobox_attrs.fetch(:aria, {}).reverse_merge! \
|
188
|
+
controls: listbox_id,
|
189
|
+
owns: listbox_id,
|
190
|
+
haspopup: "listbox",
|
191
|
+
autocomplete: autocomplete
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
def handle_data
|
196
|
+
{
|
197
|
+
action: "click->hw-combobox#toggle",
|
198
|
+
hw_combobox_target: "handle"
|
199
|
+
}
|
200
|
+
end
|
201
|
+
|
202
|
+
|
203
|
+
def listbox_id
|
204
|
+
"#{hidden_field_id}-hw-listbox"
|
205
|
+
end
|
206
|
+
|
207
|
+
def listbox_data
|
208
|
+
{ hw_combobox_target: "listbox" }
|
209
|
+
end
|
210
|
+
|
211
|
+
|
212
|
+
def listbox_options_id
|
213
|
+
"#{listbox_id}__options"
|
214
|
+
end
|
215
|
+
|
216
|
+
|
217
|
+
def dialog_data
|
218
|
+
{
|
219
|
+
action: "keydown->hw-combobox#navigate",
|
220
|
+
hw_combobox_target: "dialog"
|
221
|
+
}
|
222
|
+
end
|
223
|
+
|
224
|
+
def dialog_input_id
|
225
|
+
"#{hidden_field_id}-hw-dialog-combobox"
|
226
|
+
end
|
227
|
+
|
228
|
+
def dialog_input_data
|
229
|
+
{
|
230
|
+
action: "
|
231
|
+
input->hw-combobox#filter
|
232
|
+
keydown->hw-combobox#navigate
|
233
|
+
click@window->hw-combobox#closeOnClickOutside".squish,
|
234
|
+
hw_combobox_target: "dialogCombobox"
|
235
|
+
}
|
236
|
+
end
|
237
|
+
|
238
|
+
def dialog_input_aria
|
239
|
+
{
|
240
|
+
controls: dialog_listbox_id,
|
241
|
+
owns: dialog_listbox_id,
|
242
|
+
autocomplete: autocomplete
|
243
|
+
}
|
244
|
+
end
|
245
|
+
|
246
|
+
def dialog_listbox_id
|
247
|
+
"#{hidden_field_id}-hw-dialog-listbox"
|
248
|
+
end
|
249
|
+
|
250
|
+
def dialog_listbox_data
|
251
|
+
{ hw_combobox_target: "dialogListbox" }
|
252
|
+
end
|
253
|
+
|
254
|
+
def dialog_focus_trap_data
|
255
|
+
{ hw_combobox_target: "dialogFocusTrap" }
|
256
|
+
end
|
257
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class HotwireCombobox::Listbox::Option
|
2
|
+
def initialize(option)
|
3
|
+
@option = option.is_a?(Hash) ? Data.new(**option) : option
|
4
|
+
end
|
5
|
+
|
6
|
+
def render_in(view_context)
|
7
|
+
view_context.tag.li content, **options
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
Data = Struct.new :id, :value, :display, :content, :filterable_as, :autocompletable_as, keyword_init: true
|
12
|
+
|
13
|
+
attr_reader :option
|
14
|
+
|
15
|
+
def content
|
16
|
+
option.try(:content) || option.try(:display)
|
17
|
+
end
|
18
|
+
|
19
|
+
def options
|
20
|
+
{
|
21
|
+
id: id,
|
22
|
+
role: :option,
|
23
|
+
class: "hw-combobox__option",
|
24
|
+
tabindex: 0,
|
25
|
+
data: data
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def id
|
30
|
+
option.try(:id)
|
31
|
+
end
|
32
|
+
|
33
|
+
def data
|
34
|
+
{
|
35
|
+
action: "click->hw-combobox#selectOption",
|
36
|
+
filterable_as: filterable_as,
|
37
|
+
autocompletable_as: autocompletable_as,
|
38
|
+
value: value
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def filterable_as
|
43
|
+
option.try(:filterable_as) || option.try(:display)
|
44
|
+
end
|
45
|
+
|
46
|
+
def autocompletable_as
|
47
|
+
option.try(:autocompletable_as) || option.try(:display)
|
48
|
+
end
|
49
|
+
|
50
|
+
def value
|
51
|
+
option.try(:value) || option.id
|
52
|
+
end
|
53
|
+
end
|
@@ -1,21 +1,6 @@
|
|
1
|
-
<%= tag.fieldset
|
2
|
-
<%=
|
3
|
-
|
4
|
-
|
5
|
-
<%=
|
6
|
-
|
7
|
-
<%= tag.ul id: listbox_id, hidden: "", role: :listbox,
|
8
|
-
data: { "hw-combobox-target": "listbox" } do |ul| %>
|
9
|
-
<% options.each do |option| %>
|
10
|
-
<%= tag.li hw_listbox_option_content(option),
|
11
|
-
id: hw_listbox_option_id(option),
|
12
|
-
role: :option,
|
13
|
-
style: "cursor: pointer;",
|
14
|
-
data: {
|
15
|
-
"action": "click->hw-combobox#selectOption",
|
16
|
-
"filterable-as": hw_listbox_option_filterable_as(option),
|
17
|
-
"autocompletable-as": hw_listbox_option_autocompletable_as(option),
|
18
|
-
"value": hw_listbox_option_value(option) } %>
|
19
|
-
<% end %>
|
20
|
-
<% end %>
|
1
|
+
<%= tag.fieldset **component.fieldset_attrs do %>
|
2
|
+
<%= render "hotwire_combobox/combobox/hidden_field", component: component %>
|
3
|
+
<%= render "hotwire_combobox/combobox/input", component: component %>
|
4
|
+
<%= render "hotwire_combobox/combobox/paginated_listbox", component: component %>
|
5
|
+
<%= render "hotwire_combobox/combobox/dialog", component: component %>
|
21
6
|
<% end %>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<%= tag.div **component.dialog_focus_trap_attrs %>
|
2
|
+
|
3
|
+
<%= tag.dialog **component.dialog_attrs do %>
|
4
|
+
<%= tag.label component.dialog_label, **component.dialog_label_attrs %>
|
5
|
+
<%= tag.input **component.dialog_input_attrs %>
|
6
|
+
<%= tag.ul **component.dialog_listbox_attrs %>
|
7
|
+
<% end %>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<%= tag.ul **component.listbox_attrs do |ul| %>
|
2
|
+
<%= tag.div **component.listbox_options_attrs do %>
|
3
|
+
<% component.options.each do |option| %>
|
4
|
+
<%= render option %>
|
5
|
+
<% end %>
|
6
|
+
<% end %>
|
7
|
+
|
8
|
+
<% if component.paginated? %>
|
9
|
+
<%= render "hotwire_combobox/pagination", **component.pagination_attrs %>
|
10
|
+
<% end %>
|
11
|
+
<% end %>
|
@@ -3,8 +3,18 @@ module HotwireCombobox
|
|
3
3
|
isolate_namespace HotwireCombobox
|
4
4
|
|
5
5
|
initializer "hotwire_combobox.view_helpers" do
|
6
|
-
ActiveSupport.on_load :
|
7
|
-
|
6
|
+
ActiveSupport.on_load :action_view do
|
7
|
+
include HotwireCombobox::Helper
|
8
|
+
|
9
|
+
unless HotwireCombobox.bypass_convenience_methods?
|
10
|
+
module FormBuilderExtensions
|
11
|
+
def combobox(*args, **kwargs, &block)
|
12
|
+
@template.hw_combobox_tag *args, **kwargs.merge(form: self), &block
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
ActionView::Helpers::FormBuilder.include FormBuilderExtensions
|
17
|
+
end
|
8
18
|
end
|
9
19
|
end
|
10
20
|
|
data/lib/hotwire_combobox.rb
CHANGED
@@ -2,8 +2,6 @@ require "hotwire_combobox/version"
|
|
2
2
|
require "hotwire_combobox/engine"
|
3
3
|
|
4
4
|
module HotwireCombobox
|
5
|
-
Option = Struct.new(:id, :value, :display, :content, :filterable_as, :autocompletable_as)
|
6
|
-
|
7
5
|
mattr_accessor :bypass_convenience_methods
|
8
6
|
@@bypass_convenience_methods = false
|
9
7
|
|
@@ -15,5 +13,9 @@ module HotwireCombobox
|
|
15
13
|
def bypass_convenience_methods?
|
16
14
|
bypass_convenience_methods
|
17
15
|
end
|
16
|
+
|
17
|
+
def stylesheet_path
|
18
|
+
"hotwire_combobox"
|
19
|
+
end
|
18
20
|
end
|
19
21
|
end
|