stimulus_plumbers 0.3.0 → 0.3.1

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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/lib/stimulus_plumbers/components/action_list/section.rb +6 -5
  4. data/lib/stimulus_plumbers/components/action_list.rb +3 -3
  5. data/lib/stimulus_plumbers/components/calendar/month/turbo/days_of_month.rb +10 -8
  6. data/lib/stimulus_plumbers/components/card/section.rb +3 -3
  7. data/lib/stimulus_plumbers/components/card.rb +3 -3
  8. data/lib/stimulus_plumbers/components/combobox/autocomplete.rb +8 -14
  9. data/lib/stimulus_plumbers/components/combobox/date.rb +6 -2
  10. data/lib/stimulus_plumbers/components/combobox/dropdown.rb +6 -2
  11. data/lib/stimulus_plumbers/components/combobox/popover.rb +9 -5
  12. data/lib/stimulus_plumbers/components/combobox/time.rb +1 -1
  13. data/lib/stimulus_plumbers/components/combobox/trigger.rb +20 -11
  14. data/lib/stimulus_plumbers/components/combobox.rb +33 -23
  15. data/lib/stimulus_plumbers/components/divider.rb +16 -0
  16. data/lib/stimulus_plumbers/components/popover/builder.rb +2 -2
  17. data/lib/stimulus_plumbers/form/builder.rb +39 -43
  18. data/lib/stimulus_plumbers/form/field.rb +96 -45
  19. data/lib/stimulus_plumbers/form/fields/error.rb +2 -2
  20. data/lib/stimulus_plumbers/form/fields/fieldset.rb +54 -0
  21. data/lib/stimulus_plumbers/form/fields/group.rb +2 -2
  22. data/lib/stimulus_plumbers/form/fields/hint.rb +2 -2
  23. data/lib/stimulus_plumbers/form/fields/input_group.rb +25 -0
  24. data/lib/stimulus_plumbers/form/fields/inputs/choice.rb +69 -0
  25. data/lib/stimulus_plumbers/form/fields/inputs/datetime.rb +81 -0
  26. data/lib/stimulus_plumbers/form/fields/inputs/file.rb +22 -0
  27. data/lib/stimulus_plumbers/form/fields/inputs/password.rb +59 -0
  28. data/lib/stimulus_plumbers/form/fields/inputs/search.rb +102 -0
  29. data/lib/stimulus_plumbers/form/fields/inputs/select/grouped.rb +56 -0
  30. data/lib/stimulus_plumbers/form/fields/inputs/select/timezone.rb +59 -0
  31. data/lib/stimulus_plumbers/form/fields/inputs/select/weekday.rb +45 -0
  32. data/lib/stimulus_plumbers/form/fields/inputs/select.rb +91 -0
  33. data/lib/stimulus_plumbers/form/fields/inputs/submit.rb +25 -0
  34. data/lib/stimulus_plumbers/form/fields/inputs/text.rb +37 -0
  35. data/lib/stimulus_plumbers/form/fields/inputs/text_area.rb +22 -0
  36. data/lib/stimulus_plumbers/form/fields/label.rb +13 -9
  37. data/lib/stimulus_plumbers/helpers/calendar_helper.rb +1 -1
  38. data/lib/stimulus_plumbers/helpers/combobox_helper.rb +29 -36
  39. data/lib/stimulus_plumbers/helpers/divider_helper.rb +11 -0
  40. data/lib/stimulus_plumbers/helpers.rb +2 -0
  41. data/lib/stimulus_plumbers/themes/base.rb +1 -0
  42. data/lib/stimulus_plumbers/themes/schema.rb +7 -1
  43. data/lib/stimulus_plumbers/version.rb +1 -1
  44. data/lib/stimulus_plumbers.rb +4 -2
  45. metadata +17 -11
  46. data/lib/stimulus_plumbers/form/fields/choice.rb +0 -25
  47. data/lib/stimulus_plumbers/form/fields/combobox.rb +0 -44
  48. data/lib/stimulus_plumbers/form/fields/file.rb +0 -16
  49. data/lib/stimulus_plumbers/form/fields/password.rb +0 -55
  50. data/lib/stimulus_plumbers/form/fields/renderer.rb +0 -55
  51. data/lib/stimulus_plumbers/form/fields/search.rb +0 -54
  52. data/lib/stimulus_plumbers/form/fields/select.rb +0 -33
  53. data/lib/stimulus_plumbers/form/fields/submit.rb +0 -23
  54. data/lib/stimulus_plumbers/form/fields/text.rb +0 -33
  55. data/lib/stimulus_plumbers/form/fields/text_area.rb +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 24b44f53bd74bf3d60b97cbf5957a3f759f1f67f9e107a0073283c84d042ec4d
4
- data.tar.gz: 3a25d7f60c7e1060ad50702ecf1246a92a0c1aff61ece5c3b5d00b4d84e14b02
3
+ metadata.gz: c557f72e3e2b4e915105a333d712b8427e57ecec626110af9e38f712691c8277
4
+ data.tar.gz: 42b56777469d4d1a0bf9c92ce40161db2503da7d364e64bd4206ed83c05dc27e
5
5
  SHA512:
6
- metadata.gz: 1d63614d10f54fe15f692b7047c4ab638151b979fd1e4491fc2d7d9df5f8f2131eb0525e49d57ca482204a2bf3850953f24704a2262afad7c0c45cb6b7b0bdc8
7
- data.tar.gz: edbf1b318041423db316becab23d992ae44d215ae0ad4df73fa2953c8f22c2106879d4d6c55d766f3d25c96899a29c1a00104cc10ff95e60615b0061aafd97db
6
+ metadata.gz: 90f2d539e2fc47ac6859d02b615c5df35ed21317a4cf05543e26a82ebd07aa064a908af93eac974297676f0cb986b09b56aae1cc176fb322c3b79823875166c1
7
+ data.tar.gz: 48f00840cdc3e721a5ae204891817587c4c505d64b561767b4e906b6d7b899a862d7a4f4a32a09d44e77d6688fccf29838d8a6120c36613a57d4555ff5e907cb
data/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [conventional commits](https://www.conventionalcommits.org/) for commit guidelines.
4
4
 
5
+ ---
6
+ ## [0.3.1](https://github.com/ryancyq/stimulus-plumbers/compare/stimulus-plumbers-rails/v0.3.0..stimulus-plumbers-rails/v0.3.1) - 2026-05-19
7
+
8
+ ### Features
9
+
10
+ - form input group + fieldset ([#75](https://github.com/ryancyq/stimulus-plumbers/issues/75)) - ([b18916f](https://github.com/ryancyq/stimulus-plumbers/commit/b18916f2dcf004ae358a598ce54f28231b069af3)) - Ryan Chang
11
+
5
12
  ---
6
13
  ## [0.3.0](https://github.com/ryancyq/stimulus-plumbers/compare/stimulus-plumbers-rails/v0.2.9..stimulus-plumbers-rails/v0.3.0) - 2026-05-18
7
14
 
@@ -5,13 +5,14 @@ module StimulusPlumbers
5
5
  class ActionList
6
6
  class Section < Plumber::Base
7
7
  def render(title: nil, **kwargs, &block)
8
- html_options = merge_html_options(kwargs)
9
- template.content_tag(:div, **html_options) do
8
+ template.content_tag(:li, **kwargs) do
9
+ ul_opts = {}
10
+ ul_opts[:aria] = { label: title } if title.present?
10
11
  template.safe_join(
11
12
  [
12
- (template.content_tag(:p, title) if title.present?),
13
- template.content_tag(:ul, template.capture(&block))
14
- ].compact
13
+ (template.content_tag(:span, title, aria: { hidden: "true" }) if title.present?),
14
+ template.content_tag(:ul, template.capture(&block), **ul_opts)
15
+ ]
15
16
  )
16
17
  end
17
18
  end
@@ -3,12 +3,12 @@
3
3
  module StimulusPlumbers
4
4
  module Components
5
5
  class ActionList < Plumber::Base
6
- def render(**kwargs, &block)
6
+ def render(role: "list", **kwargs, &block)
7
7
  html_options = merge_html_options(
8
- { classes: theme.resolve(:action_list).fetch(:classes, "") },
8
+ { role: role, classes: theme.resolve(:action_list).fetch(:classes, "") },
9
9
  kwargs
10
10
  )
11
- template.content_tag(:div, template.capture(&block), **html_options)
11
+ template.content_tag(:ul, template.capture(&block), **html_options)
12
12
  end
13
13
 
14
14
  def section(title: nil, **kwargs, &block)
@@ -115,15 +115,17 @@ module StimulusPlumbers
115
115
  def day_cell_html_options(date, today)
116
116
  is_today = date == today
117
117
  selected = selected_date && date == selected_date
118
- {
119
- classes: theme.resolve(:calendar_day, today: is_today, selected: selected).fetch(:classes, ""),
120
- role: "gridcell",
121
- tabindex: date == focus_day ? 0 : -1,
122
- aria: {
123
- current: is_today ? "date" : nil,
124
- selected: if selectable then selected ? "true" : "false" end
118
+ merge_html_options(
119
+ { classes: theme.resolve(:calendar_day, today: is_today, selected: selected).fetch(:classes, "") },
120
+ {
121
+ role: "gridcell",
122
+ tabindex: date == focus_day ? 0 : -1,
123
+ aria: {
124
+ current: is_today ? "date" : nil,
125
+ selected: if selectable then selected ? "true" : "false" end
126
+ }
125
127
  }
126
- }
128
+ )
127
129
  end
128
130
 
129
131
  def other_month_day_cell(date)
@@ -4,7 +4,7 @@ module StimulusPlumbers
4
4
  module Components
5
5
  class Card
6
6
  class Section < Plumber::Base
7
- def render(title: nil, **kwargs, &block)
7
+ def render(title: nil, title_tag: :h3, **kwargs, &block)
8
8
  html_options = merge_html_options(
9
9
  { classes: theme.resolve(:card_section).fetch(:classes, "") },
10
10
  kwargs
@@ -13,9 +13,9 @@ module StimulusPlumbers
13
13
  template.content_tag(:div, **html_options) do
14
14
  template.safe_join(
15
15
  [
16
- (template.content_tag(:h3, title) if title.present?),
16
+ (template.content_tag(title_tag, title) if title.present?),
17
17
  template.capture(&block)
18
- ].compact
18
+ ]
19
19
  )
20
20
  end
21
21
  end
@@ -3,7 +3,7 @@
3
3
  module StimulusPlumbers
4
4
  module Components
5
5
  class Card < Plumber::Base
6
- def render(title: nil, **kwargs, &block)
6
+ def render(title: nil, title_tag: :h2, **kwargs, &block)
7
7
  html_options = merge_html_options(
8
8
  { classes: theme.resolve(:card).fetch(:classes, "") },
9
9
  kwargs
@@ -12,9 +12,9 @@ module StimulusPlumbers
12
12
  template.content_tag(:div, **html_options) do
13
13
  template.safe_join(
14
14
  [
15
- (template.content_tag(:h2, title) if title.present?),
15
+ (template.content_tag(title_tag, title) if title.present?),
16
16
  template.capture(&block)
17
- ].compact
17
+ ]
18
18
  )
19
19
  end
20
20
  end
@@ -10,24 +10,18 @@ module StimulusPlumbers
10
10
  )
11
11
  end
12
12
 
13
- def render(options: [], value: nil, label: nil, **_kwargs)
14
- template.safe_join([listbox(options, value, label), loading, empty])
13
+ def render(options: [], value: nil, label: nil, labelledby: nil)
14
+ template.safe_join(
15
+ [
16
+ Dropdown.new(template).render(options: options, value: value, label: label, labelledby: labelledby),
17
+ loading,
18
+ empty
19
+ ]
20
+ )
15
21
  end
16
22
 
17
23
  private
18
24
 
19
- def listbox(options, value, label)
20
- attrs = merge_html_options(
21
- { classes: theme.resolve(:combobox_listbox).fetch(:classes, "") },
22
- { role: "listbox", data: { "#{Dropdown::STIMULUS_CONTROLLER}_target": "listbox" } }
23
- )
24
- attrs[:aria] = { label: label } if label
25
-
26
- template.content_tag(:ul, **attrs) do
27
- Options.new(template).render(options, value: value)
28
- end
29
- end
30
-
31
25
  def loading
32
26
  template.content_tag(
33
27
  :div,
@@ -14,8 +14,12 @@ module StimulusPlumbers
14
14
  }
15
15
  end
16
16
 
17
- def render(value: nil, **_kwargs)
18
- calendar_id = "combobox_date_#{SecureRandom.hex(8)}_calendar"
17
+ def self.calendar_id_for(popover_id)
18
+ [popover_id, "calendar"].compact.join("_")
19
+ end
20
+
21
+ def render(value: nil, popover_id: nil)
22
+ calendar_id = self.class.calendar_id_for(popover_id)
19
23
 
20
24
  data = {
21
25
  controller: STIMULUS_CONTROLLER,
@@ -21,12 +21,16 @@ module StimulusPlumbers
21
21
  }
22
22
  end
23
23
 
24
- def render(options: [], value: nil, label: nil, **_kwargs)
24
+ def render(options: [], value: nil, label: nil, labelledby: nil)
25
25
  listbox_attrs = merge_html_options(
26
26
  { classes: theme.resolve(:combobox_listbox).fetch(:classes, "") },
27
27
  { role: "listbox", data: { "#{STIMULUS_CONTROLLER}_target": "listbox" } }
28
28
  )
29
- listbox_attrs[:aria] = { label: label } if label
29
+ if labelledby
30
+ listbox_attrs[:aria] = { labelledby: labelledby }
31
+ elsif label
32
+ listbox_attrs[:aria] = { label: label }
33
+ end
30
34
 
31
35
  template.content_tag(:ul, **listbox_attrs) do
32
36
  Options.new(template).render(options, value: value)
@@ -4,14 +4,18 @@ module StimulusPlumbers
4
4
  module Components
5
5
  class Combobox
6
6
  class Popover < Plumber::Base
7
- def render(stimulus_controller:, id:, tag: :div, role: nil, label: nil, content: nil, data: {}, **_rest, &block)
8
- base_data = { "#{stimulus_controller}_target": "popover" }
7
+ def render(stimulus_controller:, id:, tag: :div, role: nil, label: nil, labelledby: nil, content: nil, data: {}, &block)
8
+ stimulus_data = { "#{stimulus_controller}_target": "popover" }
9
9
 
10
- attrs = { id: id, hidden: "", data: merge_data_options(base_data, data.symbolize_keys) }
10
+ attrs = { id: id, hidden: "", data: merge_data_options(stimulus_data, data) }
11
11
  attrs[:role] = role if role
12
- attrs[:aria] = { label: label } if label
12
+ if labelledby
13
+ attrs[:aria] = { labelledby: labelledby }
14
+ elsif label
15
+ attrs[:aria] = { label: label }
16
+ end
13
17
 
14
- html_content = block_given? ? template.capture(&block) : content
18
+ html_content = block_given? ? template.capture(id, &block) : content
15
19
  template.content_tag(tag, **attrs) { html_content }
16
20
  end
17
21
  end
@@ -12,7 +12,7 @@ module StimulusPlumbers
12
12
  }
13
13
  end
14
14
 
15
- def render(format: :h12, step: 1, value: nil, **_kwargs)
15
+ def render(format: :h12, step: 1, value: nil)
16
16
  @format = format
17
17
  @step = [1, step.to_i].max
18
18
  @time = parse_time(value)
@@ -11,26 +11,35 @@ module StimulusPlumbers
11
11
  readonly: true,
12
12
  aria_autocomplete: nil,
13
13
  aria_label: nil,
14
+ aria: {},
15
+ id: nil,
14
16
  data: {},
15
- **_rest
17
+ **kwargs
16
18
  )
17
- base_data = {
19
+ stimulus_data = {
18
20
  "#{stimulus_controller}_target": "trigger",
19
21
  input_format_target: "input",
20
22
  action: "focus->#{stimulus_controller}#open keydown.esc->#{stimulus_controller}#close"
21
23
  }
22
24
 
23
- aria = { haspopup: haspopup, expanded: "false", controls: popover_id }
24
- aria[:autocomplete] = aria_autocomplete if aria_autocomplete
25
- aria[:label] = aria_label if aria_label
25
+ trigger_aria = { haspopup: haspopup, expanded: "false", controls: popover_id }
26
+ trigger_aria[:autocomplete] = aria_autocomplete if aria_autocomplete
27
+ trigger_aria[:label] = aria_label if aria_label
26
28
 
27
- html_options = merge_html_options(
28
- { classes: theme.resolve(:combobox_trigger).fetch(:classes, "") },
29
- { type: "text", readonly: (readonly ? true : nil), role: "combobox", aria: aria,
30
- data: merge_data_options(base_data, data.symbolize_keys)
31
- }
29
+ template.tag.input(
30
+ **merge_html_options(
31
+ { classes: theme.resolve(:combobox_trigger).fetch(:classes, "") },
32
+ {
33
+ id: id,
34
+ type: "text",
35
+ readonly: (readonly ? true : nil),
36
+ role: "combobox",
37
+ aria: trigger_aria.deep_merge(aria),
38
+ data: merge_data_options(stimulus_data, data)
39
+ },
40
+ kwargs
41
+ )
32
42
  )
33
- template.tag.input(**html_options)
34
43
  end
35
44
  end
36
45
  end
@@ -7,52 +7,62 @@ module StimulusPlumbers
7
7
  FORMAT_CONTROLLER = "input-format"
8
8
  FORMAT_ACTION = "input-combobox:changed->input-format#format"
9
9
 
10
- def render(base_id:, options: {}, **kwargs)
11
- popover_id = "#{base_id}_popover"
12
- initial_value = options.dig(:input, :value)
13
-
14
- base_data = {
15
- controller: "#{STIMULUS_CONTROLLER} #{FORMAT_CONTROLLER}",
16
- action: FORMAT_ACTION
17
- }
18
- base_data[:input_combobox_value_value] = initial_value if initial_value.present?
10
+ def self.popover_id_for(trigger_id)
11
+ [trigger_id, "popover"].compact.join("_")
12
+ end
19
13
 
20
- html_options = merge_html_options({ data: base_data }, kwargs)
14
+ def render(trigger: {}, input: {}, popover: {}, **kwargs, &block)
15
+ popover_id = self.class.popover_id_for(trigger[:id])
16
+ initial_value = input[:value]
17
+ haspopup = popover.delete(:haspopup) { popover[:role] || "dialog" }
18
+ html_options = merge_html_options({ data: build_stimulus_data(initial_value) }, kwargs)
21
19
 
22
20
  template.content_tag(:div, **html_options) do
23
21
  template.safe_join(
24
22
  [
25
- trigger(popover_id, options),
26
- hidden_input(options.fetch(:input, {})),
27
- popover(popover_id, options)
23
+ combobox_trigger(popover_id, trigger, haspopup),
24
+ hidden_input(input),
25
+ combobox_popover(popover_id, popover, &block)
28
26
  ]
29
27
  )
30
28
  end
31
29
  end
32
30
 
33
- def trigger(popover_id, options)
34
- haspopup = options.dig(:popover, :haspopup) || options.dig(:popover, :role) || "dialog"
31
+ private
32
+
33
+ def build_stimulus_data(initial_value)
34
+ {
35
+ controller: "#{STIMULUS_CONTROLLER} #{FORMAT_CONTROLLER}",
36
+ action: FORMAT_ACTION
37
+ }.tap do |data|
38
+ data[:input_combobox_value_value] = initial_value if initial_value.present?
39
+ end
40
+ end
41
+
42
+ def combobox_trigger(popover_id, trigger, haspopup)
35
43
  Combobox::Trigger.new(template).render(
36
44
  stimulus_controller: STIMULUS_CONTROLLER,
37
45
  popover_id: popover_id,
38
46
  haspopup: haspopup,
39
- **options.fetch(:trigger, {})
47
+ **trigger
40
48
  )
41
49
  end
42
50
 
43
- def popover(popover_id, options)
51
+ def combobox_popover(popover_id, popover, &block)
44
52
  Combobox::Popover.new(template).render(
45
53
  stimulus_controller: STIMULUS_CONTROLLER,
46
54
  id: popover_id,
47
- **options.fetch(:popover, {})
55
+ **popover,
56
+ &block
48
57
  )
49
58
  end
50
59
 
51
- private
52
-
53
- def hidden_input(opts)
54
- data = { "#{STIMULUS_CONTROLLER}_target": "value" }.merge(opts.fetch(:data, {}))
55
- template.tag.input(type: "hidden", name: opts[:name], value: opts[:value], data: data)
60
+ def hidden_input(input)
61
+ stimulus_data = merge_html_options(
62
+ { "#{STIMULUS_CONTROLLER}_target": "value" },
63
+ input.fetch(:data, {})
64
+ )
65
+ template.tag.input(type: "hidden", name: input[:name], value: input[:value], data: stimulus_data)
56
66
  end
57
67
  end
58
68
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StimulusPlumbers
4
+ module Components
5
+ class Divider < Plumber::Base
6
+ def render(**kwargs)
7
+ html_options = merge_html_options(
8
+ { classes: theme.resolve(:divider).fetch(:classes, "") },
9
+ kwargs
10
+ )
11
+
12
+ template.tag.hr(**html_options)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -8,8 +8,8 @@ module StimulusPlumbers
8
8
 
9
9
  def initialize(template)
10
10
  @template = template
11
- @activator_html = "".html_safe
12
- @content_html = "".html_safe
11
+ @activator_html = nil
12
+ @content_html = nil
13
13
  end
14
14
 
15
15
  def activator(&block)
@@ -3,63 +3,59 @@
3
3
  require "action_view/version"
4
4
 
5
5
  require_relative "field"
6
- require_relative "fields/choice"
7
- require_relative "fields/combobox"
8
- require_relative "fields/file"
9
- require_relative "fields/password"
10
- require_relative "fields/renderer"
11
- require_relative "fields/search"
12
- require_relative "fields/select"
13
- require_relative "fields/text"
14
- require_relative "fields/text_area"
15
- require_relative "fields/submit"
6
+ require_relative "fields/fieldset"
7
+ require_relative "fields/inputs/choice"
8
+ require_relative "fields/inputs/datetime"
9
+ require_relative "fields/inputs/file"
10
+ require_relative "fields/inputs/password"
11
+ require_relative "fields/inputs/search"
12
+ require_relative "fields/inputs/select"
13
+ require_relative "fields/inputs/select/grouped"
14
+ require_relative "fields/inputs/select/timezone"
15
+ require_relative "fields/inputs/select/weekday"
16
+ require_relative "fields/inputs/submit"
17
+ require_relative "fields/inputs/text"
18
+ require_relative "fields/inputs/text_area"
16
19
  require_relative "../plumber/html_options"
17
20
 
18
21
  module StimulusPlumbers
19
22
  module Form
20
23
  class Builder < ActionView::Helpers::FormBuilder
21
24
  include Plumber::HtmlOptions
22
- include Fields::Choice
23
- include Fields::Combobox
24
- include Fields::File
25
- include Fields::Password
26
- include Fields::Search
27
- include Fields::Select
28
- include Fields::Submit
29
- include Fields::Text
30
- include Fields::TextArea
25
+ include Fields::Inputs::Choice
26
+ include Fields::Inputs::Datetime
27
+ include Fields::Inputs::File
28
+ include Fields::Inputs::Password
29
+ include Fields::Inputs::Search
30
+ include Fields::Inputs::Select
31
+ include Fields::Inputs::Select::Grouped
32
+ include Fields::Inputs::Select::Timezone
33
+ include Fields::Inputs::Select::Weekday
34
+ include Fields::Inputs::Submit
35
+ include Fields::Inputs::Text
36
+ include Fields::Inputs::TextArea
31
37
 
32
38
  private
33
39
 
34
- def build_field(attribute, form_field_opts, input_id: field_id(attribute))
35
- Field.new(
36
- object: object,
37
- attribute: attribute,
38
- input_id: input_id,
39
- label: form_field_opts[:label],
40
- details: form_field_opts[:details],
41
- error: form_field_opts[:error],
42
- required: form_field_opts.fetch(:required, false),
43
- label_visibility: form_field_opts.fetch(:label_visibility, :visible),
44
- layout: form_field_opts.fetch(:layout, :stacked)
45
- )
40
+ def render_fieldset(attribute, field, &block)
41
+ Fields::Fieldset.new(@template).render(object, attribute, field_id(attribute), field, &block)
46
42
  end
47
43
 
48
- def render_field(field, input_html)
49
- Fields::Renderer.new(@template, theme, field).call(input_html)
44
+ def render_input_group(error:, leading: nil, trailing: nil, **wrapper_opts, &block)
45
+ Fields::InputGroup.new(@template).render(leading: leading, trailing: trailing, error: error, **wrapper_opts, &block)
50
46
  end
51
47
 
52
- def build_input_group(input_tag, field, trailing:, **wrapper_opts)
53
- @template.content_tag(
54
- :div,
55
- input_tag.html_safe + trailing,
56
- class: field_theme(:form_input_group, error: field.error?)[:class],
57
- **wrapper_opts
48
+ def render_combobox(attribute, input_id:, opts:, err:, **wrapper_opts, &block)
49
+ combobox_opts = opts.deep_merge(
50
+ input: { name: field_name(attribute) },
51
+ trigger: { id: input_id }
58
52
  )
59
- end
60
53
 
61
- def extract_options(options)
62
- [options.except(*Field::OPTIONS), options.slice(*Field::OPTIONS)]
54
+ Components::Combobox.new(@template).render(
55
+ **combobox_opts,
56
+ **merge_html_options(wrapper_opts, field_theme(:form_combobox, error: err)),
57
+ &block
58
+ )
63
59
  end
64
60
 
65
61
  def field_theme(key, **variants)
@@ -71,7 +67,7 @@ module StimulusPlumbers
71
67
  end
72
68
 
73
69
  # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
74
- if ActionView.version < "7.0"
70
+ if ActionView.version < Gem::Version.new("7.0")
75
71
  # field_id was added in Rails 7.0, backports it to Rails 6.1.
76
72
  # https://github.com/rails/rails/blob/2d670320f7b02ae879545d5202f0633841b8f196/actionview/lib/action_view/helpers/form_helper.rb#L1777
77
73
  # https://github.com/rails/rails/blob/2d670320f7b02ae879545d5202f0633841b8f196/actionview/lib/action_view/helpers/form_tag_helper.rb#L101