stimulus_plumbers 0.3.2 → 0.3.3

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  3. data/README.md +3 -1
  4. data/app/assets/javascripts/stimulus-plumbers/stimulus-plumbers-controllers.es.js +78 -52
  5. data/app/assets/javascripts/stimulus-plumbers/stimulus-plumbers-controllers.umd.js +1 -1
  6. data/app/assets/stylesheets/stimulus_plumbers/tokens.css +13 -6
  7. data/lib/stimulus_plumbers/components/action_list/item.rb +13 -10
  8. data/lib/stimulus_plumbers/components/action_list/section.rb +7 -1
  9. data/lib/stimulus_plumbers/components/action_list.rb +14 -8
  10. data/lib/stimulus_plumbers/components/avatar.rb +11 -5
  11. data/lib/stimulus_plumbers/components/button/group.rb +7 -1
  12. data/lib/stimulus_plumbers/components/button.rb +48 -10
  13. data/lib/stimulus_plumbers/components/calendar/month/turbo/days_of_month.rb +9 -5
  14. data/lib/stimulus_plumbers/components/calendar/month/turbo/days_of_week.rb +7 -3
  15. data/lib/stimulus_plumbers/components/calendar/month/turbo.rb +7 -3
  16. data/lib/stimulus_plumbers/components/calendar.rb +4 -1
  17. data/lib/stimulus_plumbers/components/card/section.rb +7 -1
  18. data/lib/stimulus_plumbers/components/card.rb +11 -5
  19. data/lib/stimulus_plumbers/components/combobox/date.rb +7 -3
  20. data/lib/stimulus_plumbers/components/combobox/dropdown.rb +7 -1
  21. data/lib/stimulus_plumbers/components/combobox/options/option.rb +7 -1
  22. data/lib/stimulus_plumbers/components/combobox/options/option_group.rb +7 -1
  23. data/lib/stimulus_plumbers/components/combobox/options.rb +9 -5
  24. data/lib/stimulus_plumbers/components/combobox/popover.rb +30 -7
  25. data/lib/stimulus_plumbers/components/combobox/time/drum.rb +7 -1
  26. data/lib/stimulus_plumbers/components/combobox/time.rb +7 -3
  27. data/lib/stimulus_plumbers/components/combobox/trigger.rb +50 -7
  28. data/lib/stimulus_plumbers/components/combobox/{autocomplete.rb → typeahead.rb} +7 -5
  29. data/lib/stimulus_plumbers/components/combobox.rb +10 -6
  30. data/lib/stimulus_plumbers/components/date_picker/navigation.rb +1 -1
  31. data/lib/stimulus_plumbers/components/date_picker/navigator.rb +7 -15
  32. data/lib/stimulus_plumbers/components/divider.rb +23 -3
  33. data/lib/stimulus_plumbers/components/icon.rb +6 -16
  34. data/lib/stimulus_plumbers/components/input_group.rb +29 -0
  35. data/lib/stimulus_plumbers/components/popover.rb +7 -3
  36. data/lib/stimulus_plumbers/form/builder.rb +1 -1
  37. data/lib/stimulus_plumbers/form/fields/inputs/datetime.rb +24 -12
  38. data/lib/stimulus_plumbers/form/fields/inputs/password.rb +3 -3
  39. data/lib/stimulus_plumbers/form/fields/inputs/search.rb +10 -10
  40. data/lib/stimulus_plumbers/form/fields/inputs/select/grouped.rb +21 -17
  41. data/lib/stimulus_plumbers/form/fields/inputs/select/timezone.rb +7 -5
  42. data/lib/stimulus_plumbers/form/fields/inputs/select/weekday.rb +7 -9
  43. data/lib/stimulus_plumbers/form/fields/inputs/select.rb +40 -28
  44. data/lib/stimulus_plumbers/helpers/action_list_helper.rb +6 -6
  45. data/lib/stimulus_plumbers/helpers/avatar_helper.rb +2 -2
  46. data/lib/stimulus_plumbers/helpers/button_helper.rb +4 -8
  47. data/lib/stimulus_plumbers/helpers/calendar_helper.rb +13 -10
  48. data/lib/stimulus_plumbers/helpers/calendar_turbo_helper.rb +2 -16
  49. data/lib/stimulus_plumbers/helpers/card_helper.rb +4 -4
  50. data/lib/stimulus_plumbers/helpers/combobox_helper.rb +36 -23
  51. data/lib/stimulus_plumbers/helpers/divider_helper.rb +2 -2
  52. data/lib/stimulus_plumbers/helpers/popover_helper.rb +2 -2
  53. data/lib/stimulus_plumbers/themes/base.rb +15 -16
  54. data/lib/stimulus_plumbers/themes/icons/external.rb +60 -0
  55. data/lib/stimulus_plumbers/themes/icons/registry.rb +36 -0
  56. data/lib/stimulus_plumbers/themes/schema/icon.rb +57 -15
  57. data/lib/stimulus_plumbers/themes/schema/ranges.rb +2 -2
  58. data/lib/stimulus_plumbers/themes/schema.rb +59 -55
  59. data/lib/stimulus_plumbers/version.rb +1 -1
  60. data/lib/stimulus_plumbers.rb +2 -2
  61. metadata +5 -3
  62. data/lib/stimulus_plumbers/form/fields/input_group.rb +0 -25
@@ -28,7 +28,7 @@ module StimulusPlumbers
28
28
  url: url,
29
29
  clearable: clearable
30
30
  ) do |combobox_opts, input_id, current_value|
31
- render_search_autocomplete(attribute, input_id, combobox_opts, error, choices, current_value)
31
+ render_search_typeahead(attribute, input_id, combobox_opts, error, choices, current_value)
32
32
  end
33
33
  end
34
34
  end
@@ -37,7 +37,7 @@ module StimulusPlumbers
37
37
  private
38
38
 
39
39
  def render_search_input(html_opts, opts, error, clearable:, &block)
40
- data = clearable ? { data: { input_search_target: "input" } } : {}
40
+ data = clearable ? { data: { input_clearable_target: "input" } } : {}
41
41
  html_options = merge_html_options(opts, html_opts, field_theme(:form_input, error: error), data)
42
42
  input_html = @template.capture(html_options, &block)
43
43
 
@@ -46,16 +46,16 @@ module StimulusPlumbers
46
46
  render_input_group(
47
47
  trailing: method(:clear_button),
48
48
  error: !!error,
49
- **merge_html_options(field_theme(:form_input_search), { data: { controller: "input-search" } })
49
+ **merge_html_options(field_theme(:form_input_clearable), { data: { controller: "input-clearable" } })
50
50
  ) { input_html }
51
51
  end
52
52
 
53
53
  def render_search_combobox(attribute, html_opts, error, url:, clearable:, &block)
54
54
  current_value = object.respond_to?(attribute) ? object.public_send(attribute) : nil
55
55
  input_id = html_opts[:id]
56
- opts = Components::Combobox::Autocomplete.default_opts.deep_merge(
56
+ opts = Components::Combobox::Typeahead.default_opts.deep_merge(
57
57
  input: { value: current_value },
58
- trigger: { data: clearable ? { input_search_target: "input" } : {}, aria: html_opts[:aria] },
58
+ trigger: { data: clearable ? { input_clearable_target: "input" } : {}, aria: html_opts[:aria] },
59
59
  popover: { data: url ? { combobox_dropdown_url_value: url } : {} }
60
60
  )
61
61
 
@@ -65,11 +65,11 @@ module StimulusPlumbers
65
65
  render_input_group(
66
66
  trailing: method(:clear_button),
67
67
  error: !!error,
68
- **merge_html_options(field_theme(:form_input_search), { data: { controller: "input-search" } })
68
+ **merge_html_options(field_theme(:form_input_clearable), { data: { controller: "input-clearable" } })
69
69
  ) { combobox_html }
70
70
  end
71
71
 
72
- def render_search_autocomplete(attribute, input_id, combobox_opts, error, choices, current_value)
72
+ def render_search_typeahead(attribute, input_id, combobox_opts, error, choices, current_value)
73
73
  render_combobox(
74
74
  attribute,
75
75
  input_id: input_id,
@@ -79,18 +79,18 @@ module StimulusPlumbers
79
79
  input_combobox_combobox_dropdown_outlet: "##{Components::Combobox.popover_id_for(input_id)}",
80
80
  action: "input->input-combobox#onInput"
81
81
  }
82
- ) { Components::Combobox::Autocomplete.new(@template).render(options: choices, value: current_value, labelledby: Field.label_id(input_id)) }
82
+ ) { Components::Combobox::Typeahead.new(@template).render(options: choices, value: current_value, labelledby: Field.label_id(input_id)) }
83
83
  end
84
84
 
85
85
  def clear_button
86
86
  Components::Button.new(@template).render(
87
- "",
87
+ icon_leading: "close",
88
88
  **merge_html_options(
89
89
  field_theme(:form_button_clear),
90
90
  {
91
91
  aria: { label: "Clear search" },
92
92
  hidden: true,
93
- data: { input_search_target: "clear", action: "click->input-search#clear" }
93
+ data: { input_clearable_target: "clear", action: "click->input-clearable#clear" }
94
94
  }
95
95
  )
96
96
  )
@@ -16,13 +16,11 @@ module StimulusPlumbers
16
16
  options = {},
17
17
  html_options = {}
18
18
  )
19
- html_native = options.delete(:html_native) { false }
20
- Field.new(@template, **options).render(
21
- object,
22
- attribute,
23
- input_id: field_id(attribute)
24
- ) do |html_opts, opts, error|
25
- merged_html_opts = merge_html_options(html_options, html_opts, field_theme(:form_select, error: error))
19
+ html_native = options.delete(:html_native) { false }
20
+ icon_leading = options.delete(:icon_leading)
21
+ icon_trailing = options.delete(:icon_trailing) { "chevron-down" }
22
+ icons = { icon_leading: icon_leading, icon_trailing: icon_trailing }
23
+ with_select_field(attribute, options, html_options) do |opts, merged, error|
26
24
  if html_native
27
25
  super(
28
26
  attribute,
@@ -32,23 +30,29 @@ module StimulusPlumbers
32
30
  option_key_method,
33
31
  option_value_method,
34
32
  opts,
35
- merged_html_opts
33
+ merged
36
34
  )
37
35
  else
38
- render_select_dropdown(attribute, opts, merged_html_opts, err: error) do
39
- collection.map do |group|
40
- {
41
- label: group.public_send(group_label_method),
42
- options: group.public_send(group_method).map do |item|
43
- [item.public_send(option_value_method), item.public_send(option_key_method)]
44
- end
45
- }
46
- end
36
+ render_select_dropdown(attribute, opts, merged, err: error, **icons) do
37
+ build_grouped_choices(collection, group_label_method, group_method, option_key_method, option_value_method)
47
38
  end
48
39
  end
49
40
  end
50
41
  end
51
42
  end
43
+
44
+ private
45
+
46
+ def build_grouped_choices(collection, group_label_method, group_method, option_key_method, option_value_method)
47
+ collection.map do |group|
48
+ {
49
+ label: group.public_send(group_label_method),
50
+ options: group.public_send(group_method).map do |item|
51
+ [item.public_send(option_value_method), item.public_send(option_key_method)]
52
+ end
53
+ }
54
+ end
55
+ end
52
56
  end
53
57
  end
54
58
  end
@@ -7,13 +7,15 @@ module StimulusPlumbers
7
7
  module Select
8
8
  module Timezone
9
9
  def time_zone_select(attribute, priority_zones = nil, options = {}, html_options = {})
10
- html_native = options.delete(:html_native) { false }
11
- Field.new(@template, **options).render(object, attribute, input_id: field_id(attribute)) do |html_opts, opts, error|
12
- merged_html_opts = merge_html_options(html_options, html_opts, field_theme(:form_select, error: error))
10
+ html_native = options.delete(:html_native) { false }
11
+ icon_leading = options.delete(:icon_leading)
12
+ icon_trailing = options.delete(:icon_trailing) { "chevron-down" }
13
+ icons = { icon_leading: icon_leading, icon_trailing: icon_trailing }
14
+ with_select_field(attribute, options, html_options) do |opts, merged, error|
13
15
  if html_native
14
- super(attribute, priority_zones, opts, merged_html_opts)
16
+ super(attribute, priority_zones, opts, merged)
15
17
  else
16
- render_select_dropdown(attribute, opts, merged_html_opts, err: error) do
18
+ render_select_dropdown(attribute, opts, merged, err: error, **icons) do
17
19
  model = opts.delete(:model) { ActiveSupport::TimeZone }
18
20
  build_zone_choices(priority_zones, model.all)
19
21
  end
@@ -8,17 +8,15 @@ module StimulusPlumbers
8
8
  module Weekday
9
9
  if ActionView.version >= Gem::Version.new("7.1")
10
10
  def weekday_select(attribute, options = {}, html_options = {})
11
- html_native = options.delete(:html_native) { false }
12
- Field.new(@template, **options).render(
13
- object,
14
- attribute,
15
- input_id: field_id(attribute)
16
- ) do |html_opts, opts, error|
17
- merged_html_opts = merge_html_options(html_options, html_opts, field_theme(:form_select, error: error))
11
+ html_native = options.delete(:html_native) { false }
12
+ icon_leading = options.delete(:icon_leading)
13
+ icon_trailing = options.delete(:icon_trailing) { "chevron-down" }
14
+ icons = { icon_leading: icon_leading, icon_trailing: icon_trailing }
15
+ with_select_field(attribute, options, html_options) do |opts, merged, error|
18
16
  if html_native
19
- super(attribute, opts, merged_html_opts)
17
+ super(attribute, opts, merged)
20
18
  else
21
- render_select_dropdown(attribute, opts, merged_html_opts, err: error) do
19
+ render_select_dropdown(attribute, opts, merged, err: error, **icons) do
22
20
  build_weekday_choices(opts)
23
21
  end
24
22
  end
@@ -6,17 +6,17 @@ module StimulusPlumbers
6
6
  module Inputs
7
7
  module Select
8
8
  def select(attribute, choices = nil, options = {}, html_options = {})
9
- html_native = options.delete(:html_native) { false }
10
- Field.new(@template, **options).render(
11
- object,
12
- attribute,
13
- input_id: field_id(attribute)
14
- ) do |html_opts, opts, error|
15
- merged_html_opts = merge_html_options(html_options, html_opts, field_theme(:form_select, error: error))
9
+ html_native = options.delete(:html_native) { false }
10
+ icon_leading = options.delete(:icon_leading)
11
+ icon_trailing = options.delete(:icon_trailing) { "chevron-down" }
12
+ icons = { icon_leading: icon_leading, icon_trailing: icon_trailing }
13
+ with_select_field(attribute, options, html_options) do |opts, merged, error|
16
14
  if html_native
17
- super(attribute, choices, opts, merged_html_opts)
15
+ super(attribute, choices, opts, merged)
18
16
  else
19
- render_select_dropdown(attribute, opts, merged_html_opts, err: error) { Array(choices) }
17
+ render_select_dropdown(attribute, opts, merged, err: error, **icons) do
18
+ Array(choices)
19
+ end
20
20
  end
21
21
  end
22
22
  end
@@ -29,17 +29,15 @@ module StimulusPlumbers
29
29
  options = {},
30
30
  html_options = {}
31
31
  )
32
- html_native = options.delete(:html_native) { false }
33
- Field.new(@template, **options).render(
34
- object,
35
- attribute,
36
- input_id: field_id(attribute)
37
- ) do |html_opts, opts, error|
38
- merged_html_opts = merge_html_options(html_options, html_opts, field_theme(:form_select, error: error))
32
+ html_native = options.delete(:html_native) { false }
33
+ icon_leading = options.delete(:icon_leading)
34
+ icon_trailing = options.delete(:icon_trailing) { "chevron-down" }
35
+ icons = { icon_leading: icon_leading, icon_trailing: icon_trailing }
36
+ with_select_field(attribute, options, html_options) do |opts, merged, error|
39
37
  if html_native
40
- super(attribute, collection, value_method, text_method, opts, merged_html_opts)
38
+ super(attribute, collection, value_method, text_method, opts, merged)
41
39
  else
42
- render_select_dropdown(attribute, opts, merged_html_opts, err: error) do
40
+ render_select_dropdown(attribute, opts, merged, err: error, **icons) do
43
41
  collection.map { |item| [item.public_send(text_method), item.public_send(value_method)] }
44
42
  end
45
43
  end
@@ -48,26 +46,40 @@ module StimulusPlumbers
48
46
 
49
47
  private
50
48
 
51
- def render_select_dropdown(attribute, opts, html_opts, err:)
49
+ def with_select_field(attribute, options, html_options)
50
+ Field.new(@template, **options).render(object, attribute, input_id: field_id(attribute)) do |html_opts, opts, error|
51
+ yield opts, merge_html_options(html_options, html_opts, field_theme(:form_select, error: error)), error
52
+ end
53
+ end
54
+
55
+ def render_select_dropdown(attribute, opts, html_opts, err:, icon_leading:, icon_trailing:)
52
56
  include_blank = opts.delete(:include_blank)
53
57
  prompt = opts.delete(:prompt)
54
58
  current_value = opts.delete(:selected) { object.respond_to?(attribute) ? object.public_send(attribute) : nil }
55
59
  choices = build_select_dropdown_choices(yield(current_value), include_blank: include_blank, prompt: prompt)
56
-
57
- combobox_opts = build_select_dropdown_opts(html_opts, current_value)
60
+ combobox_opts = build_select_dropdown_opts(
61
+ html_opts,
62
+ current_value,
63
+ icon_leading: icon_leading,
64
+ icon_trailing: icon_trailing
65
+ )
58
66
  render_combobox(attribute, input_id: html_opts[:id], opts: combobox_opts, err: err) do
59
- Components::Combobox::Dropdown.new(@template).render(
60
- options: choices,
61
- value: current_value,
62
- labelledby: Field.label_id(html_opts[:id])
63
- )
67
+ render_dropdown_component(choices, current_value, html_opts[:id])
64
68
  end
65
69
  end
66
70
 
67
- def build_select_dropdown_opts(html_opts, current_value)
71
+ def render_dropdown_component(choices, value, input_id)
72
+ Components::Combobox::Dropdown.new(@template).render(
73
+ options: choices,
74
+ value: value,
75
+ labelledby: Field.label_id(input_id)
76
+ )
77
+ end
78
+
79
+ def build_select_dropdown_opts(html_opts, current_value, icon_leading:, icon_trailing:)
68
80
  Components::Combobox::Dropdown.default_opts.deep_merge(
69
81
  input: { value: current_value },
70
- trigger: html_opts
82
+ trigger: html_opts.merge({ icon_leading: icon_leading, icon_trailing: icon_trailing }.compact)
71
83
  )
72
84
  end
73
85
 
@@ -3,16 +3,16 @@
3
3
  module StimulusPlumbers
4
4
  module Helpers
5
5
  module ActionListHelper
6
- def sp_action_list(**html_options, &block)
7
- action_list_renderer.render(**html_options, &block)
6
+ def sp_action_list(...)
7
+ action_list_renderer.render(...)
8
8
  end
9
9
 
10
- def sp_action_list_section(title: nil, **html_options, &block)
11
- action_list_renderer.section(title: title, **html_options, &block)
10
+ def sp_action_list_section(...)
11
+ action_list_renderer.section(...)
12
12
  end
13
13
 
14
- def sp_action_list_item(content = nil, url: nil, external: false, active: false, **html_options, &block)
15
- action_list_renderer.item(content, url: url, external: external, active: active, **html_options, &block)
14
+ def sp_action_list_item(content = nil, **kwargs, &block)
15
+ action_list_renderer.item(content, **kwargs, &block)
16
16
  end
17
17
 
18
18
  private
@@ -3,8 +3,8 @@
3
3
  module StimulusPlumbers
4
4
  module Helpers
5
5
  module AvatarHelper
6
- def sp_avatar(name: nil, initials: nil, url: nil, color: nil, size: :md, **html_options, &block)
7
- avatar_renderer.render(name: name, initials: initials, url: url, color: color, size: size, **html_options, &block)
6
+ def sp_avatar(...)
7
+ avatar_renderer.render(...)
8
8
  end
9
9
 
10
10
  private
@@ -3,16 +3,12 @@
3
3
  module StimulusPlumbers
4
4
  module Helpers
5
5
  module ButtonHelper
6
- def sp_button(content = nil, url: nil, external: false, variant: :primary, size: :md, **html_options, &block)
7
- button_renderer.render(
8
- content,
9
- url: url, external: external, variant: variant, size: size, **html_options,
10
- &block
11
- )
6
+ def sp_button(content = nil, **kwargs, &block)
7
+ button_renderer.render(content, **kwargs, &block)
12
8
  end
13
9
 
14
- def sp_button_group(alignment: :left, direction: :row, **html_options, &block)
15
- button_renderer.group(alignment: alignment, direction: direction, **html_options, &block)
10
+ def sp_button_group(...)
11
+ button_renderer.group(...)
16
12
  end
17
13
 
18
14
  private
@@ -3,16 +3,19 @@
3
3
  module StimulusPlumbers
4
4
  module Helpers
5
5
  module CalendarHelper
6
- def sp_calendar_month(date: nil, **html_options, &block)
7
- if date
8
- html_options = html_options.deep_merge(
9
- data: {
10
- "calendar-month-year-value": date.year,
11
- "calendar-month-month-value": date.month - 1,
12
- "calendar-month-day-value": date.day
13
- }
14
- )
15
- end
6
+ def sp_calendar_month(**kwargs, &block)
7
+ date = kwargs.delete(:date)
8
+ html_options = if date
9
+ kwargs.deep_merge(
10
+ data: {
11
+ "calendar-month-year-value": date.year,
12
+ "calendar-month-month-value": date.month - 1,
13
+ "calendar-month-day-value": date.day
14
+ }
15
+ )
16
+ else
17
+ kwargs
18
+ end
16
19
  calendar_renderer.month(**html_options, &block)
17
20
  end
18
21
 
@@ -3,22 +3,8 @@
3
3
  module StimulusPlumbers
4
4
  module Helpers
5
5
  module CalendarTurboHelper
6
- def sp_calendar_month_turbo(
7
- date: Date.today,
8
- today: Date.today,
9
- selectable: false,
10
- selected_date: nil,
11
- show_other_months: false,
12
- **html_options
13
- )
14
- calendar_month_turbo_renderer.render(
15
- date: date,
16
- today: today,
17
- selectable: selectable,
18
- selected_date: selected_date,
19
- show_other_months: show_other_months,
20
- **html_options
21
- )
6
+ def sp_calendar_month_turbo(**kwargs)
7
+ calendar_month_turbo_renderer.render(**kwargs)
22
8
  end
23
9
 
24
10
  private
@@ -3,12 +3,12 @@
3
3
  module StimulusPlumbers
4
4
  module Helpers
5
5
  module CardHelper
6
- def sp_card(title: nil, **html_options, &block)
7
- card_renderer.render(title: title, **html_options, &block)
6
+ def sp_card(...)
7
+ card_renderer.render(...)
8
8
  end
9
9
 
10
- def sp_card_section(title: nil, **html_options, &block)
11
- card_renderer.section(title: title, **html_options, &block)
10
+ def sp_card_section(...)
11
+ card_renderer.section(...)
12
12
  end
13
13
 
14
14
  private
@@ -3,37 +3,46 @@
3
3
  module StimulusPlumbers
4
4
  module Helpers
5
5
  module ComboboxHelper
6
- def sp_combobox_date(label: nil, value: nil, **html_options)
7
- id = sp_dom_id
8
- opts = Components::Combobox::Date.default_opts.deep_merge(
6
+ def sp_combobox_date(**kwargs)
7
+ label = kwargs.delete(:label)
8
+ value = kwargs.delete(:value)
9
+ id = sp_dom_id
10
+ opts = Components::Combobox::Date.default_opts.deep_merge(
9
11
  input: { value: value },
10
- trigger: { id: id, aria_label: label }.compact
12
+ trigger: { id: id, aria: ({ label: label } if label), icon_trailing: "calendar" }.compact
11
13
  )
12
14
  Components::Combobox.new(self).render(
13
15
  **opts,
14
- data: { input_format_type_value: "date" },
15
- **html_options
16
+ data: { input_formatter_format_value: "date" },
17
+ **kwargs
16
18
  ) do |popover_id|
17
19
  Components::Combobox::Date.new(self).render(value: value, popover_id: popover_id)
18
20
  end
19
21
  end
20
22
 
21
- def sp_combobox_dropdown(label: nil, options: [], value: nil, **html_options)
22
- id = sp_dom_id
23
- opts = Components::Combobox::Dropdown.default_opts.deep_merge(
23
+ def sp_combobox_dropdown(**kwargs)
24
+ label = kwargs.delete(:label)
25
+ value = kwargs.delete(:value)
26
+ options = kwargs.delete(:options) { [] }
27
+ id = sp_dom_id
28
+ opts = Components::Combobox::Dropdown.default_opts.deep_merge(
24
29
  input: { value: value },
25
- trigger: { id: id, aria_label: label }.compact
30
+ trigger: { id: id, aria: ({ label: label } if label), icon_trailing: "chevron-down" }.compact
26
31
  )
27
- Components::Combobox.new(self).render(**opts, **html_options) do
32
+ Components::Combobox.new(self).render(**opts, **kwargs) do
28
33
  Components::Combobox::Dropdown.new(self).render(options: options, value: value, label: label)
29
34
  end
30
35
  end
31
36
 
32
- def sp_combobox_autocomplete(label: nil, options: [], value: nil, url: nil, **html_options)
33
- id = sp_dom_id
34
- opts = Components::Combobox::Autocomplete.default_opts.deep_merge(
37
+ def sp_combobox_typeahead(**kwargs)
38
+ label = kwargs.delete(:label)
39
+ value = kwargs.delete(:value)
40
+ options = kwargs.delete(:options) { [] }
41
+ url = kwargs.delete(:url)
42
+ id = sp_dom_id
43
+ opts = Components::Combobox::Typeahead.default_opts.deep_merge(
35
44
  input: { value: value },
36
- trigger: { id: id, aria_label: label }.compact,
45
+ trigger: { id: id, aria: ({ label: label } if label) }.compact,
37
46
  popover: { data: url ? { combobox_dropdown_url_value: url } : {} }
38
47
  )
39
48
  Components::Combobox.new(self).render(
@@ -42,22 +51,26 @@ module StimulusPlumbers
42
51
  input_combobox_combobox_dropdown_outlet: "##{Components::Combobox.popover_id_for(id)}",
43
52
  action: "input->input-combobox#onInput"
44
53
  },
45
- **html_options
54
+ **kwargs
46
55
  ) do
47
- Components::Combobox::Autocomplete.new(self).render(options: options, value: value, label: label)
56
+ Components::Combobox::Typeahead.new(self).render(options: options, value: value, label: label)
48
57
  end
49
58
  end
50
59
 
51
- def sp_combobox_time(format: :h12, label: nil, step: 1, value: nil, **html_options)
52
- id = sp_dom_id
53
- opts = Components::Combobox::Time.default_opts.deep_merge(
60
+ def sp_combobox_time(**kwargs)
61
+ format = kwargs.delete(:format) { :h12 }
62
+ label = kwargs.delete(:label)
63
+ step = kwargs.delete(:step) { 1 }
64
+ value = kwargs.delete(:value)
65
+ id = sp_dom_id
66
+ opts = Components::Combobox::Time.default_opts.deep_merge(
54
67
  input: { value: value },
55
- trigger: { id: id, aria_label: label }.compact
68
+ trigger: { id: id, aria: ({ label: label } if label), icon_trailing: "clock" }.compact
56
69
  )
57
70
  Components::Combobox.new(self).render(
58
71
  **opts,
59
- data: { input_format_type_value: "time", input_format_options_value: { format: format }.to_json },
60
- **html_options
72
+ data: { input_formatter_format_value: "time", input_formatter_options_value: { format: format }.to_json },
73
+ **kwargs
61
74
  ) do
62
75
  Components::Combobox::Time.new(self).render(format: format, step: step, value: value)
63
76
  end
@@ -3,8 +3,8 @@
3
3
  module StimulusPlumbers
4
4
  module Helpers
5
5
  module DividerHelper
6
- def sp_divider(**html_options)
7
- Components::Divider.new(self).render(**html_options)
6
+ def sp_divider(label = nil, **kwargs)
7
+ Components::Divider.new(self).render(label, **kwargs)
8
8
  end
9
9
  end
10
10
  end
@@ -3,8 +3,8 @@
3
3
  module StimulusPlumbers
4
4
  module Helpers
5
5
  module PopoverHelper
6
- def sp_popover(interactive: true, **html_options, &block)
7
- popover_renderer.render(interactive: interactive, **html_options, &block)
6
+ def sp_popover(...)
7
+ popover_renderer.render(...)
8
8
  end
9
9
 
10
10
  private
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "schema"
4
+ require_relative "../plumber/dispatcher"
4
5
 
5
6
  module StimulusPlumbers
6
7
  module Themes
@@ -14,6 +15,7 @@ module StimulusPlumbers
14
15
  **Schema::COMBOBOX,
15
16
  **Schema::FORM,
16
17
  **Schema::ICON,
18
+ **Schema::INPUT_GROUP,
17
19
  **Schema::LAYOUT
18
20
  }.freeze
19
21
 
@@ -33,10 +35,6 @@ module StimulusPlumbers
33
35
  {}
34
36
  end
35
37
 
36
- def icon_range
37
- icons.keys
38
- end
39
-
40
38
  def attribute_names(component)
41
39
  SCHEMA.fetch(component, {}).keys
42
40
  end
@@ -51,36 +49,37 @@ module StimulusPlumbers
51
49
  return {}
52
50
  end
53
51
 
54
- send(method_name, **validate_args(component.to_sym, args))
52
+ send(method_name, **validate(component.to_sym, args))
55
53
  end
56
54
 
57
55
  private
58
56
 
59
- def validate_args(component, args)
57
+ def validate(component, args)
60
58
  schema = SCHEMA.fetch(component, {})
61
59
  args.slice(*schema.keys).each_with_object({}) do |(key, value), result|
62
- result[key] = coerce_arg(component, key, value, schema[key])
60
+ result[key] = cast(component, key, value, schema[key])
63
61
  end
64
62
  end
65
63
 
66
- def coerce_arg(component, key, value, schema)
64
+ def cast(component, key, value, schema)
67
65
  return value unless schema
68
-
69
- range = range_for(schema)
70
- return value if range.empty? || range.include?(value)
66
+ return value if value.nil? || valid?(schema[:validate], value)
71
67
 
72
68
  StimulusPlumbers::Logger.warn(
73
69
  "#{component}##{key} received unknown value #{value.inspect}. " \
74
- "Range: #{schema[:range].inspect}. Falling back to: #{schema[:default].inspect}"
70
+ "Validator: #{schema[:validate].inspect}. Falling back to: #{schema[:default].inspect}"
75
71
  )
76
72
  schema[:default]
77
73
  end
78
74
 
79
- def range_for(schema)
80
- if schema[:range].is_a?(Symbol)
81
- respond_to?(schema[:range], true) ? send(schema[:range]) : []
75
+ def valid?(validator, value)
76
+ return true if validator.nil?
77
+
78
+ if validator.respond_to?(:include?)
79
+ validator.include?(value)
82
80
  else
83
- schema[:range]
81
+ result = Plumber::Dispatcher.build(validator, value).call(self)
82
+ result.respond_to?(:include?) ? result.include?(value) : result
84
83
  end
85
84
  end
86
85
  end