stimulus_plumbers 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 +38 -0
- data/README.md +57 -41
- data/app/assets/javascripts/stimulus-plumbers/stimulus-plumbers-controllers.es.js +734 -248
- data/app/assets/javascripts/stimulus-plumbers/stimulus-plumbers-controllers.umd.js +1 -1
- data/lib/stimulus_plumbers/components/combobox/autocomplete.rb +57 -0
- data/lib/stimulus_plumbers/components/combobox/date.rb +52 -0
- data/lib/stimulus_plumbers/components/combobox/dropdown.rb +41 -0
- data/lib/stimulus_plumbers/components/combobox/option.rb +27 -0
- data/lib/stimulus_plumbers/components/combobox/option_group.rb +52 -0
- data/lib/stimulus_plumbers/components/combobox/renderer.rb +78 -0
- data/lib/stimulus_plumbers/components/combobox/time.rb +103 -0
- data/lib/stimulus_plumbers/components/date_picker/navigation.rb +1 -1
- data/lib/stimulus_plumbers/components/plumber/html_options.rb +22 -3
- data/lib/stimulus_plumbers/components/time_picker/renderer.rb +38 -0
- data/lib/stimulus_plumbers/form/builder.rb +57 -12
- data/lib/stimulus_plumbers/form/field_component.rb +12 -10
- data/lib/stimulus_plumbers/form/fields/combobox.rb +41 -0
- data/lib/stimulus_plumbers/form/fields/password.rb +55 -0
- data/lib/stimulus_plumbers/form/fields/renderer.rb +1 -2
- data/lib/stimulus_plumbers/form/fields/search.rb +40 -0
- data/lib/stimulus_plumbers/form/fields/select.rb +8 -2
- data/lib/stimulus_plumbers/form/fields/text.rb +12 -4
- data/lib/stimulus_plumbers/helpers/combobox_helper.rb +74 -0
- data/lib/stimulus_plumbers/helpers.rb +2 -2
- data/lib/stimulus_plumbers/themes/{form.rb → base/form.rb} +6 -2
- data/lib/stimulus_plumbers/themes/base.rb +7 -7
- data/lib/stimulus_plumbers/themes/tailwind/form.rb +10 -6
- data/lib/stimulus_plumbers/version.rb +1 -1
- data/lib/stimulus_plumbers.rb +18 -1
- metadata +21 -10
- data/lib/stimulus_plumbers/components/date_picker/renderer.rb +0 -82
- data/lib/stimulus_plumbers/helpers/date_picker_helper.rb +0 -17
- /data/lib/stimulus_plumbers/themes/{action_list.rb → base/action_list.rb} +0 -0
- /data/lib/stimulus_plumbers/themes/{avatar.rb → base/avatar.rb} +0 -0
- /data/lib/stimulus_plumbers/themes/{button.rb → base/button.rb} +0 -0
- /data/lib/stimulus_plumbers/themes/{calendar.rb → base/calendar.rb} +0 -0
- /data/lib/stimulus_plumbers/themes/{card.rb → base/card.rb} +0 -0
- /data/lib/stimulus_plumbers/themes/{layout.rb → base/layout.rb} +0 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module StimulusPlumbers
|
|
4
|
+
module Components
|
|
5
|
+
module TimePicker
|
|
6
|
+
# Renders a single scrollable drum column (hour, minute, or period) as a listbox.
|
|
7
|
+
class Renderer < Plumber::Base
|
|
8
|
+
CONTROLLER = "combobox-time"
|
|
9
|
+
|
|
10
|
+
def render(items:, label:, target:, selected: nil)
|
|
11
|
+
template.content_tag(
|
|
12
|
+
:ul,
|
|
13
|
+
role: "listbox",
|
|
14
|
+
aria: { label: label },
|
|
15
|
+
data: {
|
|
16
|
+
"#{CONTROLLER}_target": target,
|
|
17
|
+
action: "click->#{CONTROLLER}#select keydown->#{CONTROLLER}#navigate"
|
|
18
|
+
}
|
|
19
|
+
) do
|
|
20
|
+
template.safe_join(items.map { |text, value| render_item(text, value, selected) })
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def render_item(text, value, selected)
|
|
27
|
+
template.content_tag(
|
|
28
|
+
:li,
|
|
29
|
+
text,
|
|
30
|
+
role: "option",
|
|
31
|
+
aria: { selected: value.to_s == selected.to_s ? "true" : "false" },
|
|
32
|
+
data: { value: value }
|
|
33
|
+
)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -3,23 +3,29 @@
|
|
|
3
3
|
require "action_view/version"
|
|
4
4
|
|
|
5
5
|
require_relative "field_component"
|
|
6
|
+
require_relative "fields/choice"
|
|
7
|
+
require_relative "fields/combobox"
|
|
8
|
+
require_relative "fields/file"
|
|
9
|
+
require_relative "fields/password"
|
|
6
10
|
require_relative "fields/renderer"
|
|
11
|
+
require_relative "fields/search"
|
|
12
|
+
require_relative "fields/select"
|
|
7
13
|
require_relative "fields/text"
|
|
8
14
|
require_relative "fields/text_area"
|
|
9
|
-
require_relative "fields/file"
|
|
10
|
-
require_relative "fields/select"
|
|
11
|
-
require_relative "fields/choice"
|
|
12
15
|
require_relative "../components/plumber/html_options"
|
|
13
16
|
|
|
14
17
|
module StimulusPlumbers
|
|
15
18
|
module Form
|
|
16
19
|
class Builder < ActionView::Helpers::FormBuilder
|
|
17
20
|
include Components::Plumber::HtmlOptions
|
|
18
|
-
include Fields::
|
|
19
|
-
include Fields::
|
|
21
|
+
include Fields::Choice
|
|
22
|
+
include Fields::Combobox
|
|
20
23
|
include Fields::File
|
|
24
|
+
include Fields::Password
|
|
25
|
+
include Fields::Search
|
|
21
26
|
include Fields::Select
|
|
22
|
-
include Fields::
|
|
27
|
+
include Fields::Text
|
|
28
|
+
include Fields::TextArea
|
|
23
29
|
|
|
24
30
|
private
|
|
25
31
|
|
|
@@ -41,6 +47,15 @@ module StimulusPlumbers
|
|
|
41
47
|
Fields::Renderer.new(@template, theme, field).call(input_html)
|
|
42
48
|
end
|
|
43
49
|
|
|
50
|
+
def build_input_group(input_tag, field, trailing:, **wrapper_opts)
|
|
51
|
+
@template.content_tag(
|
|
52
|
+
:div,
|
|
53
|
+
input_tag.html_safe + trailing,
|
|
54
|
+
class: field_theme(:form_input_group, error: field.error?)[:class],
|
|
55
|
+
**wrapper_opts
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
|
|
44
59
|
def extract_options(options)
|
|
45
60
|
[options.except(*FieldComponent::OPTIONS), options.slice(*FieldComponent::OPTIONS)]
|
|
46
61
|
end
|
|
@@ -53,15 +68,45 @@ module StimulusPlumbers
|
|
|
53
68
|
StimulusPlumbers.config.theme
|
|
54
69
|
end
|
|
55
70
|
|
|
56
|
-
#
|
|
71
|
+
# rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
|
57
72
|
if ActionView.version < "7.0"
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
73
|
+
# field_id was added in Rails 7.0, backports it to Rails 6.1.
|
|
74
|
+
# https://github.com/rails/rails/blob/2d670320f7b02ae879545d5202f0633841b8f196/actionview/lib/action_view/helpers/form_helper.rb#L1777
|
|
75
|
+
# https://github.com/rails/rails/blob/2d670320f7b02ae879545d5202f0633841b8f196/actionview/lib/action_view/helpers/form_tag_helper.rb#L101
|
|
76
|
+
def field_id(method_name, *suffixes, namespace: @options[:namespace], index: @options[:index])
|
|
77
|
+
object_name = @object_name.respond_to?(:model_name) ? @object_name.model_name.singular : @object_name
|
|
78
|
+
|
|
79
|
+
sanitized_object_name = object_name.to_s.gsub(%r{\]\[|[^-a-zA-Z0-9:.]}, "_").delete_suffix("_")
|
|
80
|
+
sanitized_method_name = method_name.to_s.delete_suffix("?")
|
|
81
|
+
|
|
82
|
+
[
|
|
83
|
+
namespace,
|
|
84
|
+
sanitized_object_name.presence,
|
|
85
|
+
(index unless sanitized_object_name.empty?),
|
|
86
|
+
sanitized_method_name,
|
|
87
|
+
*suffixes
|
|
88
|
+
].tap(&:compact!).join("_")
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# field_name was added in Rails 7.0, backports it to Rails 6.1.
|
|
92
|
+
# https://github.com/rails/rails/blob/2d670320f7b02ae879545d5202f0633841b8f196/actionview/lib/action_view/helpers/form_helper.rb#L1797
|
|
93
|
+
# https://github.com/rails/rails/blob/2d670320f7b02ae879545d5202f0633841b8f196/actionview/lib/action_view/helpers/form_tag_helper.rb#L131
|
|
94
|
+
def field_name(method_name, *method_names, multiple: false, index: @options[:index])
|
|
95
|
+
object_name = @options.fetch(:as) { @object_name }
|
|
96
|
+
|
|
97
|
+
names = method_names.map! { |name| "[#{name}]" }.join
|
|
98
|
+
|
|
99
|
+
# a little duplication to construct fewer strings
|
|
100
|
+
if object_name.blank?
|
|
101
|
+
"#{method_name}#{names}#{"[]" if multiple}"
|
|
102
|
+
elsif index
|
|
103
|
+
"#{object_name}[#{index}][#{method_name}]#{names}#{"[]" if multiple}"
|
|
104
|
+
else
|
|
105
|
+
"#{object_name}[#{method_name}]#{names}#{"[]" if multiple}"
|
|
106
|
+
end
|
|
63
107
|
end
|
|
64
108
|
end
|
|
109
|
+
# rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
|
65
110
|
end
|
|
66
111
|
end
|
|
67
112
|
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module StimulusPlumbers
|
|
4
4
|
module Form
|
|
5
5
|
class FieldComponent
|
|
6
|
-
OPTIONS = %i[label details error required label_visibility layout].freeze
|
|
6
|
+
OPTIONS = %i[label details error required label_visibility layout reveal clearable].freeze
|
|
7
7
|
|
|
8
8
|
attr_reader :object,
|
|
9
9
|
:attribute,
|
|
@@ -14,15 +14,17 @@ module StimulusPlumbers
|
|
|
14
14
|
:label_visibility,
|
|
15
15
|
:layout
|
|
16
16
|
|
|
17
|
-
def initialize(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
17
|
+
def initialize(
|
|
18
|
+
object:,
|
|
19
|
+
attribute:,
|
|
20
|
+
input_id:,
|
|
21
|
+
label: nil,
|
|
22
|
+
details: nil,
|
|
23
|
+
error: nil,
|
|
24
|
+
required: false,
|
|
25
|
+
label_visibility: :visible,
|
|
26
|
+
layout: :stacked
|
|
27
|
+
)
|
|
26
28
|
@object = object
|
|
27
29
|
@attribute = attribute
|
|
28
30
|
@input_id = input_id
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module StimulusPlumbers
|
|
4
|
+
module Form
|
|
5
|
+
module Fields
|
|
6
|
+
module Combobox
|
|
7
|
+
COMPONENT_CLASS = {
|
|
8
|
+
autocomplete: Components::Combobox::Autocomplete,
|
|
9
|
+
date: Components::Combobox::Date,
|
|
10
|
+
dropdown: Components::Combobox::Dropdown,
|
|
11
|
+
time: Components::Combobox::Time
|
|
12
|
+
}.freeze
|
|
13
|
+
|
|
14
|
+
def combobox_field(attribute, type:, options: [], **html_options)
|
|
15
|
+
klass = COMPONENT_CLASS.fetch(type) do
|
|
16
|
+
raise ArgumentError,
|
|
17
|
+
"unsupported combobox type #{type.inspect}. Must be one of: #{COMPONENT_CLASS.keys.join(", ")}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
rails_opts, field_opts = extract_options(html_options)
|
|
21
|
+
field = build_field(attribute, field_opts)
|
|
22
|
+
base_id = field_id(attribute)
|
|
23
|
+
current_value = object&.public_send(attribute)
|
|
24
|
+
|
|
25
|
+
popover = klass.new(@template).render(options: options, value: current_value, **rails_opts)
|
|
26
|
+
opts = klass.default_opts.deep_merge(
|
|
27
|
+
input: { name: field_name(attribute), value: current_value },
|
|
28
|
+
popover: { content: popover }
|
|
29
|
+
)
|
|
30
|
+
wrapper = Components::Combobox::Renderer.new(@template).render(
|
|
31
|
+
base_id: base_id,
|
|
32
|
+
options: opts,
|
|
33
|
+
**field_theme(:form_combobox, error: field.error?),
|
|
34
|
+
**field.html_opts
|
|
35
|
+
)
|
|
36
|
+
render_field(field, wrapper)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module StimulusPlumbers
|
|
4
|
+
module Form
|
|
5
|
+
module Fields
|
|
6
|
+
module Password
|
|
7
|
+
def password_field(attribute, options = {})
|
|
8
|
+
rails_opts, form_field_opts = extract_options(options)
|
|
9
|
+
reveal = form_field_opts.delete(:reveal) { false }
|
|
10
|
+
field = build_field(attribute, form_field_opts)
|
|
11
|
+
|
|
12
|
+
input_html = if reveal
|
|
13
|
+
input_opts = merge_html_options(
|
|
14
|
+
rails_opts,
|
|
15
|
+
field_theme(:form_input_reveal),
|
|
16
|
+
field.html_opts,
|
|
17
|
+
{ "data-input-format-target": "input" }
|
|
18
|
+
)
|
|
19
|
+
build_input_group(
|
|
20
|
+
super(attribute, input_opts),
|
|
21
|
+
field,
|
|
22
|
+
trailing: reveal_button,
|
|
23
|
+
"data-controller": "input-format",
|
|
24
|
+
"data-input-format-type-value": "password"
|
|
25
|
+
)
|
|
26
|
+
else
|
|
27
|
+
html_opts = merge_html_options(
|
|
28
|
+
rails_opts,
|
|
29
|
+
field_theme(:form_input, error: field.error?),
|
|
30
|
+
field.html_opts
|
|
31
|
+
)
|
|
32
|
+
super(attribute, html_opts)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
render_field(field, input_html)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def reveal_button
|
|
41
|
+
@template.content_tag(
|
|
42
|
+
:button,
|
|
43
|
+
"",
|
|
44
|
+
type: "button",
|
|
45
|
+
class: field_theme(:form_button_reveal)[:class],
|
|
46
|
+
"aria-label": "Show password",
|
|
47
|
+
"aria-pressed": "false",
|
|
48
|
+
"data-input-format-target": "toggle",
|
|
49
|
+
"data-action": "click->input-format#toggle"
|
|
50
|
+
)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -23,8 +23,7 @@ module StimulusPlumbers
|
|
|
23
23
|
private
|
|
24
24
|
|
|
25
25
|
def label_html
|
|
26
|
-
klass = theme.resolve(:form_label, required: field.required).fetch(:classes, "")
|
|
27
|
-
klass = "#{klass} sr-only".strip if field.label_hidden?
|
|
26
|
+
klass = theme.resolve(:form_label, required: field.required, hidden: field.label_hidden?).fetch(:classes, "")
|
|
28
27
|
|
|
29
28
|
inner = field.label_text.dup.html_safe
|
|
30
29
|
if field.required
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module StimulusPlumbers
|
|
4
|
+
module Form
|
|
5
|
+
module Fields
|
|
6
|
+
module Search
|
|
7
|
+
def search_field(attribute, options = {})
|
|
8
|
+
rails_opts, form_field_opts = extract_options(options)
|
|
9
|
+
clearable = form_field_opts.delete(:clearable) { false }
|
|
10
|
+
field = build_field(attribute, form_field_opts)
|
|
11
|
+
|
|
12
|
+
html_opts = merge_html_options(
|
|
13
|
+
rails_opts,
|
|
14
|
+
field_theme(:form_input, error: field.error?),
|
|
15
|
+
field.html_opts
|
|
16
|
+
)
|
|
17
|
+
input_html = if clearable
|
|
18
|
+
build_input_group(super(attribute, html_opts), field, trailing: clear_button)
|
|
19
|
+
else
|
|
20
|
+
super(attribute, html_opts)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
render_field(field, input_html)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def clear_button
|
|
29
|
+
@template.content_tag(
|
|
30
|
+
:button,
|
|
31
|
+
"",
|
|
32
|
+
type: "button",
|
|
33
|
+
class: field_theme(:form_button_reveal)[:class],
|
|
34
|
+
"aria-label": "Clear search"
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -11,8 +11,14 @@ module StimulusPlumbers
|
|
|
11
11
|
render_field(field, super(attribute, choices, rails_opts, html_opts))
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def collection_select(
|
|
15
|
-
|
|
14
|
+
def collection_select(
|
|
15
|
+
attribute,
|
|
16
|
+
collection,
|
|
17
|
+
value_method,
|
|
18
|
+
text_method,
|
|
19
|
+
options = {},
|
|
20
|
+
html_options = {}
|
|
21
|
+
)
|
|
16
22
|
rails_opts, form_field_opts = extract_options(options)
|
|
17
23
|
field = build_field(attribute, form_field_opts)
|
|
18
24
|
html_opts = merge_html_options(html_options, field_theme(:form_select, error: field.error?), field.html_opts)
|
|
@@ -5,10 +5,18 @@ module StimulusPlumbers
|
|
|
5
5
|
module Fields
|
|
6
6
|
module Text
|
|
7
7
|
FIELD_TYPES = %i[
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
color_field
|
|
9
|
+
date_field
|
|
10
|
+
datetime_local_field
|
|
11
|
+
email_field
|
|
12
|
+
month_field
|
|
13
|
+
number_field
|
|
14
|
+
range_field
|
|
15
|
+
telephone_field
|
|
16
|
+
text_field
|
|
17
|
+
time_field
|
|
18
|
+
url_field
|
|
19
|
+
week_field
|
|
12
20
|
].freeze
|
|
13
21
|
|
|
14
22
|
FIELD_TYPES.each do |method_name|
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module StimulusPlumbers
|
|
4
|
+
module Helpers
|
|
5
|
+
module ComboboxHelper
|
|
6
|
+
def sp_combobox_date(label: nil, value: nil, **html_options)
|
|
7
|
+
opts = Components::Combobox::Date.default_opts.deep_merge(
|
|
8
|
+
input: { value: value },
|
|
9
|
+
popover: { content: Components::Combobox::Date.new(self).render(value: value) }
|
|
10
|
+
)
|
|
11
|
+
opts = opts.deep_merge(trigger: { aria_label: label }) if label
|
|
12
|
+
Components::Combobox::Renderer.new(self).render(
|
|
13
|
+
base_id: sp_dom_id,
|
|
14
|
+
options: opts,
|
|
15
|
+
data: { input_format_type_value: "date" },
|
|
16
|
+
**html_options
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def sp_combobox_dropdown(label: nil, options: [], value: nil, **html_options)
|
|
21
|
+
opts = Components::Combobox::Dropdown.default_opts.deep_merge(
|
|
22
|
+
input: { value: value },
|
|
23
|
+
popover: { content: Components::Combobox::Dropdown.new(self).render(options: options, value: value, label: label) }
|
|
24
|
+
)
|
|
25
|
+
opts = opts.deep_merge(trigger: { aria_label: label }) if label
|
|
26
|
+
Components::Combobox::Renderer.new(self).render(
|
|
27
|
+
base_id: sp_dom_id,
|
|
28
|
+
options: opts,
|
|
29
|
+
**html_options
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def sp_combobox_autocomplete(label: nil, options: [], value: nil, url: nil, **html_options)
|
|
34
|
+
id = sp_dom_id
|
|
35
|
+
popover_id = "#{id}_popover"
|
|
36
|
+
opts = Components::Combobox::Autocomplete.default_opts.deep_merge(
|
|
37
|
+
input: { value: value },
|
|
38
|
+
popover: {
|
|
39
|
+
content: Components::Combobox::Autocomplete.new(self).render(
|
|
40
|
+
options: options,
|
|
41
|
+
value: value,
|
|
42
|
+
label: label
|
|
43
|
+
),
|
|
44
|
+
data: url ? { combobox_dropdown_url_value: url } : {}
|
|
45
|
+
}
|
|
46
|
+
)
|
|
47
|
+
opts = opts.deep_merge(trigger: { aria_label: label }) if label
|
|
48
|
+
Components::Combobox::Renderer.new(self).render(
|
|
49
|
+
base_id: id,
|
|
50
|
+
options: opts,
|
|
51
|
+
data: {
|
|
52
|
+
input_combobox_combobox_dropdown_outlet: "##{popover_id}",
|
|
53
|
+
action: "input->input-combobox#filter"
|
|
54
|
+
},
|
|
55
|
+
**html_options
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def sp_combobox_time(format: :h12, label: nil, step: 1, value: nil, **html_options)
|
|
60
|
+
opts = Components::Combobox::Time.default_opts.deep_merge(
|
|
61
|
+
input: { value: value },
|
|
62
|
+
popover: { content: Components::Combobox::Time.new(self).render(format: format, step: step, value: value) }
|
|
63
|
+
)
|
|
64
|
+
opts = opts.deep_merge(trigger: { aria_label: label }) if label
|
|
65
|
+
Components::Combobox::Renderer.new(self).render(
|
|
66
|
+
base_id: sp_dom_id,
|
|
67
|
+
options: opts,
|
|
68
|
+
data: { input_format_type_value: "time", input_format_options_value: { format: format }.to_json },
|
|
69
|
+
**html_options
|
|
70
|
+
)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -7,7 +7,7 @@ require_relative "helpers/button_helper"
|
|
|
7
7
|
require_relative "helpers/calendar_helper"
|
|
8
8
|
require_relative "helpers/calendar_turbo_helper"
|
|
9
9
|
require_relative "helpers/card_helper"
|
|
10
|
-
require_relative "helpers/
|
|
10
|
+
require_relative "helpers/combobox_helper"
|
|
11
11
|
require_relative "helpers/popover_helper"
|
|
12
12
|
|
|
13
13
|
module StimulusPlumbers
|
|
@@ -19,7 +19,7 @@ module StimulusPlumbers
|
|
|
19
19
|
include CalendarHelper
|
|
20
20
|
include CalendarTurboHelper
|
|
21
21
|
include CardHelper
|
|
22
|
-
include
|
|
22
|
+
include ComboboxHelper
|
|
23
23
|
include PopoverHelper
|
|
24
24
|
end
|
|
25
25
|
end
|
|
@@ -8,7 +8,10 @@ module StimulusPlumbers
|
|
|
8
8
|
layout: { default: :stacked, range: Schema::Ranges::LAYOUT_RANGE },
|
|
9
9
|
error: { default: false, range: Schema::Ranges::BOOL_RANGE }
|
|
10
10
|
}.freeze,
|
|
11
|
-
form_label: {
|
|
11
|
+
form_label: {
|
|
12
|
+
required: { default: false, range: Schema::Ranges::BOOL_RANGE },
|
|
13
|
+
hidden: { default: false, range: Schema::Ranges::BOOL_RANGE }
|
|
14
|
+
}.freeze,
|
|
12
15
|
form_required_mark: {}.freeze,
|
|
13
16
|
form_details: {}.freeze,
|
|
14
17
|
form_error: {}.freeze,
|
|
@@ -18,7 +21,8 @@ module StimulusPlumbers
|
|
|
18
21
|
form_select: { error: { default: false, range: Schema::Ranges::BOOL_RANGE } }.freeze,
|
|
19
22
|
form_checkbox: { error: { default: false, range: Schema::Ranges::BOOL_RANGE } }.freeze,
|
|
20
23
|
form_radio: { error: { default: false, range: Schema::Ranges::BOOL_RANGE } }.freeze,
|
|
21
|
-
|
|
24
|
+
form_input_group: { error: { default: false, range: Schema::Ranges::BOOL_RANGE } }.freeze,
|
|
25
|
+
form_combobox: { error: { default: false, range: Schema::Ranges::BOOL_RANGE } }.freeze,
|
|
22
26
|
form_input_reveal: {}.freeze,
|
|
23
27
|
form_button_reveal: {}.freeze,
|
|
24
28
|
form_submit: {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "schema/ranges"
|
|
4
|
-
require_relative "action_list"
|
|
5
|
-
require_relative "avatar"
|
|
6
|
-
require_relative "button"
|
|
7
|
-
require_relative "calendar"
|
|
8
|
-
require_relative "card"
|
|
9
|
-
require_relative "form"
|
|
10
|
-
require_relative "layout"
|
|
4
|
+
require_relative "base/action_list"
|
|
5
|
+
require_relative "base/avatar"
|
|
6
|
+
require_relative "base/button"
|
|
7
|
+
require_relative "base/calendar"
|
|
8
|
+
require_relative "base/card"
|
|
9
|
+
require_relative "base/form"
|
|
10
|
+
require_relative "base/layout"
|
|
11
11
|
|
|
12
12
|
module StimulusPlumbers
|
|
13
13
|
module Themes
|
|
@@ -21,8 +21,8 @@ module StimulusPlumbers
|
|
|
21
21
|
CHECKBOX = %w[size-4 rounded border-gray-500 text-blue-700].freeze
|
|
22
22
|
RADIO = %w[size-4 border-gray-500 text-blue-700].freeze
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
INPUT_GROUP_BASE = %w[flex items-center overflow-hidden rounded-md border].freeze
|
|
25
|
+
INPUT_GROUP_BORDER = { error: "border-red-700", default: "border-gray-500" }.freeze
|
|
26
26
|
|
|
27
27
|
INPUT_REVEAL = %w[
|
|
28
28
|
flex-1 border-0 bg-transparent px-3 py-2 text-sm text-gray-900 focus:outline-none
|
|
@@ -38,8 +38,8 @@ module StimulusPlumbers
|
|
|
38
38
|
{ classes: klasses(*GROUP_BASE, layout == :inline ? GROUP_INLINE : "flex-col") }
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
def form_label_classes(**)
|
|
42
|
-
{ classes: klasses(*LABEL) }
|
|
41
|
+
def form_label_classes(hidden: false, **)
|
|
42
|
+
{ classes: klasses(*LABEL, hidden ? "sr-only" : nil) }
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def form_required_mark_classes
|
|
@@ -78,8 +78,12 @@ module StimulusPlumbers
|
|
|
78
78
|
{ classes: klasses(*RADIO) }
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
-
def
|
|
82
|
-
{ classes: klasses(*
|
|
81
|
+
def form_input_group_classes(error: false)
|
|
82
|
+
{ classes: klasses(*INPUT_GROUP_BASE, INPUT_GROUP_BORDER[error ? :error : :default]) }
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def form_combobox_classes(error: false)
|
|
86
|
+
form_input_classes(error: error)
|
|
83
87
|
end
|
|
84
88
|
|
|
85
89
|
def form_input_reveal_classes
|
data/lib/stimulus_plumbers.rb
CHANGED
|
@@ -5,15 +5,18 @@ require_relative "stimulus_plumbers/version"
|
|
|
5
5
|
require "active_support"
|
|
6
6
|
require "active_support/core_ext/string"
|
|
7
7
|
|
|
8
|
+
# -- Core infrastructure --
|
|
8
9
|
require_relative "stimulus_plumbers/configuration"
|
|
9
10
|
require_relative "stimulus_plumbers/helpers"
|
|
10
11
|
require_relative "stimulus_plumbers/logger"
|
|
11
12
|
|
|
13
|
+
# -- Plumber base --
|
|
12
14
|
require_relative "stimulus_plumbers/components/plumber/html_options"
|
|
13
15
|
require_relative "stimulus_plumbers/components/plumber/dispatcher"
|
|
14
16
|
require_relative "stimulus_plumbers/components/plumber/renderer"
|
|
15
17
|
require_relative "stimulus_plumbers/components/plumber/base"
|
|
16
18
|
|
|
19
|
+
# -- UI components --
|
|
17
20
|
require_relative "stimulus_plumbers/components/icon/renderer"
|
|
18
21
|
require_relative "stimulus_plumbers/components/avatar/renderer"
|
|
19
22
|
require_relative "stimulus_plumbers/components/button/renderer"
|
|
@@ -21,15 +24,29 @@ require_relative "stimulus_plumbers/components/card/renderer"
|
|
|
21
24
|
require_relative "stimulus_plumbers/components/action_list/renderer"
|
|
22
25
|
require_relative "stimulus_plumbers/components/popover/renderer"
|
|
23
26
|
|
|
27
|
+
# -- Calendar --
|
|
24
28
|
require_relative "stimulus_plumbers/components/calendar/renderer"
|
|
25
29
|
require_relative "stimulus_plumbers/components/calendar/month/turbo/days_of_week"
|
|
26
30
|
require_relative "stimulus_plumbers/components/calendar/month/turbo/days_of_month"
|
|
27
31
|
require_relative "stimulus_plumbers/components/calendar/month/turbo/renderer"
|
|
28
32
|
|
|
33
|
+
# -- Date picker --
|
|
29
34
|
require_relative "stimulus_plumbers/components/date_picker/navigator"
|
|
30
35
|
require_relative "stimulus_plumbers/components/date_picker/navigation"
|
|
31
|
-
require_relative "stimulus_plumbers/components/date_picker/renderer"
|
|
32
36
|
|
|
37
|
+
# -- Time picker --
|
|
38
|
+
require_relative "stimulus_plumbers/components/time_picker/renderer"
|
|
39
|
+
|
|
40
|
+
# -- Combobox --
|
|
41
|
+
require_relative "stimulus_plumbers/components/combobox/renderer"
|
|
42
|
+
require_relative "stimulus_plumbers/components/combobox/option"
|
|
43
|
+
require_relative "stimulus_plumbers/components/combobox/option_group"
|
|
44
|
+
require_relative "stimulus_plumbers/components/combobox/date"
|
|
45
|
+
require_relative "stimulus_plumbers/components/combobox/dropdown"
|
|
46
|
+
require_relative "stimulus_plumbers/components/combobox/autocomplete"
|
|
47
|
+
require_relative "stimulus_plumbers/components/combobox/time"
|
|
48
|
+
|
|
49
|
+
# -- Form --
|
|
33
50
|
require_relative "stimulus_plumbers/form/field_component"
|
|
34
51
|
require_relative "stimulus_plumbers/form/builder"
|
|
35
52
|
|