stimulus_plumbers 0.3.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +45 -0
  3. data/app/assets/javascripts/stimulus-plumbers/controllers.manifest.json +273 -0
  4. data/app/assets/javascripts/stimulus-plumbers/stimulus-plumbers-controllers.es.js +228 -145
  5. data/app/assets/javascripts/stimulus-plumbers/stimulus-plumbers-controllers.umd.js +1 -1
  6. data/app/assets/stylesheets/stimulus_plumbers/tokens.css +43 -7
  7. data/config/locales/en.yml +10 -0
  8. data/lib/stimulus_plumbers/components/avatar.rb +14 -13
  9. data/lib/stimulus_plumbers/components/button/group.rb +9 -4
  10. data/lib/stimulus_plumbers/components/button/slots.rb +11 -0
  11. data/lib/stimulus_plumbers/components/button.rb +30 -34
  12. data/lib/stimulus_plumbers/components/calendar/turbo/days_of_month.rb +151 -0
  13. data/lib/stimulus_plumbers/components/calendar/turbo/days_of_week.rb +62 -0
  14. data/lib/stimulus_plumbers/components/calendar/turbo/months_of_year.rb +99 -0
  15. data/lib/stimulus_plumbers/components/calendar/turbo/years_of_decade.rb +86 -0
  16. data/lib/stimulus_plumbers/components/calendar/turbo.rb +65 -0
  17. data/lib/stimulus_plumbers/components/calendar.rb +70 -29
  18. data/lib/stimulus_plumbers/components/card/slots.rb +26 -0
  19. data/lib/stimulus_plumbers/components/card.rb +54 -14
  20. data/lib/stimulus_plumbers/components/combobox/builder.rb +45 -0
  21. data/lib/stimulus_plumbers/components/combobox/date/navigation.rb +72 -0
  22. data/lib/stimulus_plumbers/components/combobox/date/navigator.rb +25 -0
  23. data/lib/stimulus_plumbers/components/combobox/date.rb +34 -24
  24. data/lib/stimulus_plumbers/components/combobox/dropdown.rb +27 -24
  25. data/lib/stimulus_plumbers/components/combobox/options/option.rb +1 -1
  26. data/lib/stimulus_plumbers/components/combobox/options/option_group.rb +1 -1
  27. data/lib/stimulus_plumbers/components/combobox/time/drum.rb +1 -1
  28. data/lib/stimulus_plumbers/components/combobox/time.rb +48 -49
  29. data/lib/stimulus_plumbers/components/combobox/trigger.rb +17 -12
  30. data/lib/stimulus_plumbers/components/combobox/typeahead.rb +63 -16
  31. data/lib/stimulus_plumbers/components/combobox.rb +58 -38
  32. data/lib/stimulus_plumbers/components/divider.rb +9 -8
  33. data/lib/stimulus_plumbers/components/icon.rb +5 -1
  34. data/lib/stimulus_plumbers/components/link/slots.rb +11 -0
  35. data/lib/stimulus_plumbers/components/link.rb +63 -0
  36. data/lib/stimulus_plumbers/components/list/item/slots.rb +13 -0
  37. data/lib/stimulus_plumbers/components/list/item.rb +83 -0
  38. data/lib/stimulus_plumbers/components/list/section.rb +73 -0
  39. data/lib/stimulus_plumbers/components/list.rb +31 -0
  40. data/lib/stimulus_plumbers/components/popover/panel.rb +32 -0
  41. data/lib/stimulus_plumbers/components/popover/trigger.rb +27 -0
  42. data/lib/stimulus_plumbers/components/popover.rb +44 -18
  43. data/lib/stimulus_plumbers/engine.rb +1 -0
  44. data/lib/stimulus_plumbers/form/base.rb +103 -0
  45. data/lib/stimulus_plumbers/form/builder.rb +71 -24
  46. data/lib/stimulus_plumbers/form/field.rb +56 -88
  47. data/lib/stimulus_plumbers/form/fields/error.rb +1 -1
  48. data/lib/stimulus_plumbers/form/fields/fieldset.rb +11 -8
  49. data/lib/stimulus_plumbers/form/fields/hint.rb +1 -1
  50. data/lib/stimulus_plumbers/form/fields/inputs/checkbox.rb +115 -0
  51. data/lib/stimulus_plumbers/form/fields/inputs/combobox.rb +24 -0
  52. data/lib/stimulus_plumbers/form/fields/inputs/datetime.rb +40 -58
  53. data/lib/stimulus_plumbers/form/fields/inputs/file.rb +9 -8
  54. data/lib/stimulus_plumbers/form/fields/inputs/password.rb +30 -23
  55. data/lib/stimulus_plumbers/form/fields/inputs/radio.rb +60 -0
  56. data/lib/stimulus_plumbers/form/fields/inputs/search.rb +31 -54
  57. data/lib/stimulus_plumbers/form/fields/inputs/select/grouped.rb +22 -33
  58. data/lib/stimulus_plumbers/form/fields/inputs/select/timezone.rb +3 -46
  59. data/lib/stimulus_plumbers/form/fields/inputs/select/weekday.rb +3 -26
  60. data/lib/stimulus_plumbers/form/fields/inputs/select.rb +62 -61
  61. data/lib/stimulus_plumbers/form/fields/inputs/submit.rb +10 -7
  62. data/lib/stimulus_plumbers/form/fields/inputs/text.rb +29 -22
  63. data/lib/stimulus_plumbers/form/fields/inputs/text_area.rb +9 -8
  64. data/lib/stimulus_plumbers/form/fields/label/floating.rb +41 -0
  65. data/lib/stimulus_plumbers/form/fields/label.rb +9 -3
  66. data/lib/stimulus_plumbers/form/fields/renderer.rb +39 -0
  67. data/lib/stimulus_plumbers/helpers/button_helper.rb +1 -1
  68. data/lib/stimulus_plumbers/helpers/calendar_helper.rb +2 -2
  69. data/lib/stimulus_plumbers/helpers/calendar_turbo_helper.rb +56 -4
  70. data/lib/stimulus_plumbers/helpers/card_helper.rb +1 -11
  71. data/lib/stimulus_plumbers/helpers/combobox_helper.rb +27 -60
  72. data/lib/stimulus_plumbers/helpers/icon_helper.rb +11 -0
  73. data/lib/stimulus_plumbers/helpers/link_helper.rb +11 -0
  74. data/lib/stimulus_plumbers/helpers/list_helper.rb +11 -0
  75. data/lib/stimulus_plumbers/helpers/plumber_helper.rb +3 -6
  76. data/lib/stimulus_plumbers/helpers.rb +6 -2
  77. data/lib/stimulus_plumbers/logger.rb +4 -3
  78. data/lib/stimulus_plumbers/plumber/base.rb +6 -1
  79. data/lib/stimulus_plumbers/plumber/dispatcher/klass_proxy.rb +4 -3
  80. data/lib/stimulus_plumbers/plumber/dispatcher/method_call.rb +4 -3
  81. data/lib/stimulus_plumbers/plumber/dispatcher.rb +4 -4
  82. data/lib/stimulus_plumbers/plumber/options/aria.rb +17 -0
  83. data/lib/stimulus_plumbers/plumber/options/html.rb +29 -0
  84. data/lib/stimulus_plumbers/plumber/options/stimulus.rb +29 -0
  85. data/lib/stimulus_plumbers/plumber/options/theme.rb +19 -0
  86. data/lib/stimulus_plumbers/plumber/options/token_list.rb +29 -0
  87. data/lib/stimulus_plumbers/plumber/renderer.rb +136 -41
  88. data/lib/stimulus_plumbers/plumber/slots.rb +74 -0
  89. data/lib/stimulus_plumbers/themes/base.rb +5 -7
  90. data/lib/stimulus_plumbers/themes/schema/avatar/ranges.rb +13 -0
  91. data/lib/stimulus_plumbers/themes/schema/button/ranges.rb +16 -0
  92. data/lib/stimulus_plumbers/themes/schema/card/ranges.rb +13 -0
  93. data/lib/stimulus_plumbers/themes/schema/form/checkbox/ranges.rb +16 -0
  94. data/lib/stimulus_plumbers/themes/schema/form/radio/ranges.rb +16 -0
  95. data/lib/stimulus_plumbers/themes/schema/form/ranges.rb +1 -2
  96. data/lib/stimulus_plumbers/themes/schema/link/ranges.rb +14 -0
  97. data/lib/stimulus_plumbers/themes/schema/ranges.rb +1 -5
  98. data/lib/stimulus_plumbers/themes/schema.rb +119 -48
  99. data/lib/stimulus_plumbers/version.rb +1 -1
  100. data/lib/stimulus_plumbers.rb +20 -15
  101. metadata +42 -15
  102. data/lib/stimulus_plumbers/components/action_list/item.rb +0 -30
  103. data/lib/stimulus_plumbers/components/action_list/section.rb +0 -28
  104. data/lib/stimulus_plumbers/components/action_list.rb +0 -29
  105. data/lib/stimulus_plumbers/components/calendar/month/turbo/days_of_month.rb +0 -149
  106. data/lib/stimulus_plumbers/components/calendar/month/turbo/days_of_week.rb +0 -43
  107. data/lib/stimulus_plumbers/components/calendar/month/turbo.rb +0 -59
  108. data/lib/stimulus_plumbers/components/card/section.rb +0 -31
  109. data/lib/stimulus_plumbers/components/combobox/popover.rb +0 -47
  110. data/lib/stimulus_plumbers/components/date_picker/navigation.rb +0 -41
  111. data/lib/stimulus_plumbers/components/date_picker/navigator.rb +0 -23
  112. data/lib/stimulus_plumbers/components/popover/builder.rb +0 -25
  113. data/lib/stimulus_plumbers/form/fields/inputs/choice.rb +0 -69
  114. data/lib/stimulus_plumbers/helpers/action_list_helper.rb +0 -25
  115. data/lib/stimulus_plumbers/plumber/html_options.rb +0 -52
@@ -5,31 +5,38 @@ module StimulusPlumbers
5
5
  module Fields
6
6
  module Inputs
7
7
  module Text
8
- FIELD_TYPES = %i[
9
- color_field
10
- datetime_local_field
11
- email_field
12
- month_field
13
- number_field
14
- range_field
15
- telephone_field
16
- text_field
17
- url_field
18
- week_field
19
- ].freeze
8
+ TEXT_FIELD_METHODS = {
9
+ text: :text_field,
10
+ email: :email_field,
11
+ number: :number_field,
12
+ url: :url_field,
13
+ tel: :telephone_field,
14
+ color: :color_field,
15
+ month: :month_field,
16
+ week: :week_field,
17
+ range: :range_field,
18
+ datetime_local: :datetime_local_field
19
+ }.freeze
20
20
 
21
- FIELD_TYPES.each do |method_name|
22
- define_method(method_name) do |attribute, options = {}|
23
- Field.new(@template, **options).render(
24
- object,
25
- attribute,
26
- input_id: field_id(attribute)
27
- ) do |html_opts, opts, error|
28
- html_options = merge_html_options(opts, html_opts, field_theme(:form_input, error: error))
29
- super(attribute, html_options)
30
- end
21
+ TEXT_FIELD_METHODS.each_value do |template_method|
22
+ define_method(template_method) do |attribute, options = {}|
23
+ html_options = merge_html_options(theme.resolve(:form_field_input), options)
24
+ super(attribute, html_options)
31
25
  end
32
26
  end
27
+
28
+ private
29
+
30
+ TEXT_FIELD_METHODS.each do |as_key, template_method|
31
+ define_method(:"render_#{as_key}_input") do |attribute, html_opts, opts, error, **kwargs|
32
+ render_text(attribute, html_opts, opts, error, template_method, **kwargs)
33
+ end
34
+ end
35
+
36
+ def render_text(attribute, html_opts, opts, error, template_method, **kwargs)
37
+ html_options = merge_html_options(theme.resolve(:form_field_input, error: error), opts, html_opts, kwargs)
38
+ @template.public_send(template_method, @object_name, attribute, objectify_options(html_options))
39
+ end
33
40
  end
34
41
  end
35
42
  end
@@ -6,14 +6,15 @@ module StimulusPlumbers
6
6
  module Inputs
7
7
  module TextArea
8
8
  def text_area(attribute, options = {})
9
- Field.new(@template, **options).render(
10
- object,
11
- attribute,
12
- input_id: field_id(attribute)
13
- ) do |html_opts, opts, error|
14
- html_options = merge_html_options(opts, html_opts, field_theme(:form_textarea, error: error))
15
- super(attribute, html_options)
16
- end
9
+ html_options = merge_html_options(theme.resolve(:form_field_input_textarea), options)
10
+ super(attribute, html_options)
11
+ end
12
+
13
+ private
14
+
15
+ def render_text_area_input(attribute, html_opts, opts, error, **kwargs)
16
+ html_options = merge_html_options(theme.resolve(:form_field_input_textarea, error: error), opts, html_opts, kwargs)
17
+ @template.text_area(@object_name, attribute, objectify_options(html_options))
17
18
  end
18
19
  end
19
20
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StimulusPlumbers
4
+ module Form
5
+ module Fields
6
+ class Label
7
+ class Floating < Plumber::Base
8
+ def render(text:, for_id:, id:, type:, required:, error:, &block)
9
+ html_options = merge_html_options(theme.resolve(:form_field_floating_group, type: type))
10
+ label_options = merge_html_options(theme.resolve(:form_field_floating_label, type: type, error: error))
11
+ mark_options = required && merge_html_options(
12
+ { aria: { hidden: true } },
13
+ theme.resolve(:form_field_required_mark)
14
+ )
15
+ template.content_tag(:div, **html_options) do
16
+ template.safe_join(
17
+ [
18
+ template.capture(&block),
19
+ render_label(text, mark_options, for: for_id, id: id, **label_options)
20
+ ]
21
+ )
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def render_label(text, mark_options, **html_options)
28
+ template.content_tag(:label, **html_options) do
29
+ template.safe_join(
30
+ [
31
+ text,
32
+ mark_options ? template.content_tag(:span, "*", **mark_options) : nil
33
+ ]
34
+ )
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -7,10 +7,16 @@ module StimulusPlumbers
7
7
  def render(text:, for_id: nil, id: nil, required: false, hidden: false, tag: :label)
8
8
  mark_options = required && merge_html_options(
9
9
  { aria: { hidden: true } },
10
- theme.resolve(:form_required_mark)
10
+ theme.resolve(:form_field_required_mark)
11
11
  )
12
- html_options = merge_html_options(theme.resolve(:form_label, required: required, hidden: hidden))
13
- template.content_tag(tag, for: for_id, id: id, **html_options) do
12
+ html_options = merge_html_options(theme.resolve(:form_field_label, required: required, hidden: hidden))
13
+ render_label(text, mark_options, tag, for: for_id, id: id, **html_options)
14
+ end
15
+
16
+ private
17
+
18
+ def render_label(text, mark_options, tag, **html_options)
19
+ template.content_tag(tag, **html_options) do
14
20
  template.safe_join(
15
21
  [
16
22
  text,
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StimulusPlumbers
4
+ module Form
5
+ module Fields
6
+ module Renderer
7
+ FIELD = {
8
+ text: :render_text_input,
9
+ email: :render_email_input,
10
+ number: :render_number_input,
11
+ url: :render_url_input,
12
+ tel: :render_tel_input,
13
+ color: :render_color_input,
14
+ month: :render_month_input,
15
+ week: :render_week_input,
16
+ range: :render_range_input,
17
+ datetime_local: :render_datetime_local_input,
18
+ text_area: :render_text_area_input,
19
+ file: :render_file_input,
20
+ password: :render_password_input,
21
+ date: :render_combobox_date,
22
+ time: :render_combobox_time,
23
+ select: :render_combobox_dropdown,
24
+ search: :render_combobox_typeahead
25
+ }.freeze
26
+
27
+ COLLECTION = {
28
+ collection_select: :render_collection_combobox_dropdown,
29
+ grouped_collection_select: :render_grouped_collection_combobox_dropdown
30
+ }.freeze
31
+
32
+ CHOICE = {
33
+ radio: :render_collection_radio_button,
34
+ check_box: :render_check_box
35
+ }.freeze
36
+ end
37
+ end
38
+ end
39
+ end
@@ -8,7 +8,7 @@ module StimulusPlumbers
8
8
  end
9
9
 
10
10
  def sp_button_group(...)
11
- button_renderer.group(...)
11
+ Components::Button::Group.new(self).render(...)
12
12
  end
13
13
 
14
14
  private
@@ -3,7 +3,7 @@
3
3
  module StimulusPlumbers
4
4
  module Helpers
5
5
  module CalendarHelper
6
- def sp_calendar_month(**kwargs, &block)
6
+ def sp_calendar_month(**kwargs)
7
7
  date = kwargs.delete(:date)
8
8
  html_options = if date
9
9
  kwargs.deep_merge(
@@ -16,7 +16,7 @@ module StimulusPlumbers
16
16
  else
17
17
  kwargs
18
18
  end
19
- calendar_renderer.month(**html_options, &block)
19
+ calendar_renderer.render(**html_options)
20
20
  end
21
21
 
22
22
  private
@@ -3,14 +3,66 @@
3
3
  module StimulusPlumbers
4
4
  module Helpers
5
5
  module CalendarTurboHelper
6
- def sp_calendar_month_turbo(**kwargs)
7
- calendar_month_turbo_renderer.render(**kwargs)
6
+ def sp_calendar_turbo_month(**kwargs)
7
+ calendar_turbo_renderer.month(**kwargs)
8
+ end
9
+
10
+ def sp_calendar_turbo_year(**kwargs)
11
+ calendar_turbo_renderer.year(**kwargs)
12
+ end
13
+
14
+ def sp_calendar_turbo_decade(**kwargs)
15
+ calendar_turbo_renderer.decade(**kwargs)
16
+ end
17
+
18
+ def sp_calendar_turbo(
19
+ date: Date.today,
20
+ today: Date.today,
21
+ selectable: false,
22
+ selected_date: nil,
23
+ show_other_months: false,
24
+ **kwargs
25
+ )
26
+ safe_join(
27
+ [
28
+ content_tag(
29
+ :turbo_frame,
30
+ id: "calendar-month-frame",
31
+ data: { "combobox-date-target": "monthView" }
32
+ ) do
33
+ calendar_turbo_renderer.month(
34
+ date: date,
35
+ today: today,
36
+ selectable: selectable,
37
+ selected_date: selected_date,
38
+ show_other_months: show_other_months,
39
+ **kwargs
40
+ )
41
+ end,
42
+ content_tag(
43
+ :turbo_frame,
44
+ id: "calendar-year-frame",
45
+ hidden: true,
46
+ data: { "combobox-date-target": "yearView" }
47
+ ) do
48
+ calendar_turbo_renderer.year(date: date, today: today, selected_date: selected_date)
49
+ end,
50
+ content_tag(
51
+ :turbo_frame,
52
+ id: "calendar-decade-frame",
53
+ hidden: true,
54
+ data: { "combobox-date-target": "decadeView" }
55
+ ) do
56
+ calendar_turbo_renderer.decade(date: date, today: today, selected_date: selected_date)
57
+ end
58
+ ]
59
+ )
8
60
  end
9
61
 
10
62
  private
11
63
 
12
- def calendar_month_turbo_renderer
13
- Components::Calendar::Month::Turbo.new(self)
64
+ def calendar_turbo_renderer
65
+ @calendar_turbo_renderer ||= Components::Calendar::Turbo.new(self)
14
66
  end
15
67
  end
16
68
  end
@@ -4,17 +4,7 @@ module StimulusPlumbers
4
4
  module Helpers
5
5
  module CardHelper
6
6
  def sp_card(...)
7
- card_renderer.render(...)
8
- end
9
-
10
- def sp_card_section(...)
11
- card_renderer.section(...)
12
- end
13
-
14
- private
15
-
16
- def card_renderer
17
- Components::Card.new(self)
7
+ Components::Card.new(self).render(...)
18
8
  end
19
9
  end
20
10
  end
@@ -3,76 +3,43 @@
3
3
  module StimulusPlumbers
4
4
  module Helpers
5
5
  module ComboboxHelper
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(
11
- input: { value: value },
12
- trigger: { id: id, aria: ({ label: label } if label), icon_trailing: "calendar" }.compact
13
- )
6
+ # Single entry point; panel type chosen by a block method (c.dropdown/date/...).
7
+ def sp_combobox(value: nil, label: nil, id: nil, close_on_select: nil, **kwargs, &block)
14
8
  Components::Combobox.new(self).render(
15
- **opts,
16
- data: { input_formatter_format_value: "date" },
17
- **kwargs
18
- ) do |popover_id|
19
- Components::Combobox::Date.new(self).render(value: value, popover_id: popover_id)
9
+ id: id || sp_dom_id,
10
+ label: label,
11
+ input: { value: value },
12
+ close_on_select: close_on_select,
13
+ **kwargs,
14
+ &block
15
+ )
16
+ end
17
+
18
+ def sp_combobox_date(value: nil, label: nil, **kwargs)
19
+ sp_combobox(value: value, label: label, **kwargs) do |c|
20
+ panel_opts = { value: value }
21
+ panel_opts[:label] = label if label
22
+ c.date(**panel_opts)
20
23
  end
21
24
  end
22
25
 
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(
29
- input: { value: value },
30
- trigger: { id: id, aria: ({ label: label } if label), icon_trailing: "chevron-down" }.compact
31
- )
32
- Components::Combobox.new(self).render(**opts, **kwargs) do
33
- Components::Combobox::Dropdown.new(self).render(options: options, value: value, label: label)
26
+ def sp_combobox_dropdown(options: [], value: nil, label: nil, **kwargs)
27
+ sp_combobox(value: value, label: label, **kwargs) do |c|
28
+ c.dropdown(options: options, value: value, label: label)
34
29
  end
35
30
  end
36
31
 
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(
44
- input: { value: value },
45
- trigger: { id: id, aria: ({ label: label } if label) }.compact,
46
- popover: { data: url ? { combobox_dropdown_url_value: url } : {} }
47
- )
48
- Components::Combobox.new(self).render(
49
- **opts,
50
- data: {
51
- input_combobox_combobox_dropdown_outlet: "##{Components::Combobox.popover_id_for(id)}",
52
- action: "input->input-combobox#onInput"
53
- },
54
- **kwargs
55
- ) do
56
- Components::Combobox::Typeahead.new(self).render(options: options, value: value, label: label)
32
+ def sp_combobox_typeahead(options: [], value: nil, label: nil, url: nil, **kwargs)
33
+ sp_combobox(value: value, label: label, **kwargs) do |c|
34
+ c.typeahead(options: options, value: value, label: label, url: url)
57
35
  end
58
36
  end
59
37
 
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(
67
- input: { value: value },
68
- trigger: { id: id, aria: ({ label: label } if label), icon_trailing: "clock" }.compact
69
- )
70
- Components::Combobox.new(self).render(
71
- **opts,
72
- data: { input_formatter_format_value: "time", input_formatter_options_value: { format: format }.to_json },
73
- **kwargs
74
- ) do
75
- Components::Combobox::Time.new(self).render(format: format, step: step, value: value)
38
+ def sp_combobox_time(format: :h12, step: 1, value: nil, label: nil, **kwargs)
39
+ sp_combobox(value: value, label: label, **kwargs) do |c|
40
+ panel_opts = { format: format, step: step, value: value }
41
+ panel_opts[:label] = label if label
42
+ c.time(**panel_opts)
76
43
  end
77
44
  end
78
45
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StimulusPlumbers
4
+ module Helpers
5
+ module IconHelper
6
+ def sp_icon(name:, **kwargs)
7
+ Components::Icon.new(self).render(name: name, **kwargs)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StimulusPlumbers
4
+ module Helpers
5
+ module LinkHelper
6
+ def sp_link(content = nil, **kwargs, &block)
7
+ Components::Link.new(self).render(content, **kwargs, &block)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StimulusPlumbers
4
+ module Helpers
5
+ module ListHelper
6
+ def sp_list(...)
7
+ Components::List.new(self).render(...)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -3,12 +3,9 @@
3
3
  module StimulusPlumbers
4
4
  module Helpers
5
5
  module PlumberHelper
6
- def sp_dom_id(record = nil, suffix = nil)
7
- if record
8
- dom_id(record, suffix)
9
- else
10
- "#{suffix}_#{SecureRandom.hex(8)}"
11
- end
6
+ def sp_dom_id(record = nil, prefix: nil, suffix: nil)
7
+ base = record ? dom_id(record, prefix) : SecureRandom.hex(8)
8
+ ["sp", base, suffix].compact.join("_")
12
9
  end
13
10
  end
14
11
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "helpers/plumber_helper"
4
- require_relative "helpers/action_list_helper"
4
+ require_relative "helpers/icon_helper"
5
+ require_relative "helpers/list_helper"
5
6
  require_relative "helpers/avatar_helper"
6
7
  require_relative "helpers/button_helper"
7
8
  require_relative "helpers/calendar_helper"
@@ -9,12 +10,14 @@ require_relative "helpers/calendar_turbo_helper"
9
10
  require_relative "helpers/card_helper"
10
11
  require_relative "helpers/combobox_helper"
11
12
  require_relative "helpers/divider_helper"
13
+ require_relative "helpers/link_helper"
12
14
  require_relative "helpers/popover_helper"
13
15
 
14
16
  module StimulusPlumbers
15
17
  module Helpers
16
18
  include PlumberHelper
17
- include ActionListHelper
19
+ include IconHelper
20
+ include ListHelper
18
21
  include AvatarHelper
19
22
  include ButtonHelper
20
23
  include CalendarHelper
@@ -22,6 +25,7 @@ module StimulusPlumbers
22
25
  include CardHelper
23
26
  include ComboboxHelper
24
27
  include DividerHelper
28
+ include LinkHelper
25
29
  include PopoverHelper
26
30
  end
27
31
  end
@@ -4,17 +4,18 @@ module StimulusPlumbers
4
4
  module Logger
5
5
  LEVELS = %i[debug info warn error].freeze
6
6
 
7
- module_function
8
-
9
7
  LEVELS.each do |level|
10
8
  define_method(level) do |message|
11
9
  tagged = StimulusPlumbers.config.log_formatter.call(message)
12
10
  if defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
13
11
  Rails.logger.public_send(level, tagged)
14
12
  else
15
- warn(tagged)
13
+ # Kernel.warn, not bare `warn` which would recurse into this module's own warn.
14
+ Kernel.warn(tagged)
16
15
  end
17
16
  end
18
17
  end
18
+
19
+ module_function(*LEVELS)
19
20
  end
20
21
  end
@@ -1,9 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "options/html"
4
+ require_relative "options/aria"
5
+ require_relative "renderer"
6
+
3
7
  module StimulusPlumbers
4
8
  module Plumber
5
9
  class Base
6
- include HtmlOptions
10
+ include Options::Html
11
+ include Options::Aria
7
12
  include Renderer
8
13
 
9
14
  attr_reader :template
@@ -4,20 +4,21 @@ module StimulusPlumbers
4
4
  module Plumber
5
5
  module Dispatcher
6
6
  class KlassProxy
7
- attr_reader :klass, :method_name, :args, :kwargs, :init_args, :init_kwargs
7
+ attr_reader :klass, :method_name, :args, :kwargs, :init_args, :init_kwargs, :block
8
8
 
9
- def initialize(klass, method_name, *args, init_args: [], init_kwargs: {}, **kwargs)
9
+ def initialize(klass, method_name, *args, init_args: [], init_kwargs: {}, **kwargs, &block)
10
10
  @klass = klass
11
11
  @method_name = method_name
12
12
  @args = args
13
13
  @kwargs = kwargs
14
14
  @init_args = init_args
15
15
  @init_kwargs = init_kwargs
16
+ @block = block
16
17
  validate!
17
18
  end
18
19
 
19
20
  def call(_target)
20
- klass.new(*init_args, **init_kwargs).public_send(method_name, *args, **kwargs)
21
+ klass.new(*init_args, **init_kwargs).public_send(method_name, *args, **kwargs, &@block)
21
22
  end
22
23
 
23
24
  private
@@ -6,12 +6,13 @@ module StimulusPlumbers
6
6
  class MethodCall
7
7
  include CallableInspector
8
8
 
9
- attr_reader :method_name, :args, :kwargs
9
+ attr_reader :method_name, :args, :kwargs, :block
10
10
 
11
- def initialize(method_name, *args, **kwargs)
11
+ def initialize(method_name, *args, **kwargs, &block)
12
12
  @method_name = method_name
13
13
  @args = args
14
14
  @kwargs = kwargs
15
+ @block = block
15
16
  validate!
16
17
  end
17
18
 
@@ -20,7 +21,7 @@ module StimulusPlumbers
20
21
 
21
22
  method_call = target.method(method_name)
22
23
  dispatched = args_for(method_call)
23
- accepts_kwargs?(method_call) ? method_call.call(*dispatched, **kwargs) : method_call.call(*dispatched)
24
+ accepts_kwargs?(method_call) ? method_call.call(*dispatched, **kwargs, &@block) : method_call.call(*dispatched, &@block)
24
25
  end
25
26
 
26
27
  private
@@ -8,19 +8,19 @@ require_relative "dispatcher/klass_proxy"
8
8
  module StimulusPlumbers
9
9
  module Plumber
10
10
  module Dispatcher
11
- def self.build(callable, *args, method_name: nil, init_args: [], init_kwargs: {}, **kwargs)
11
+ def self.build(callable, *args, method_name: nil, init_args: [], init_kwargs: {}, **kwargs, &block)
12
12
  case callable
13
13
  when Symbol
14
- MethodCall.new(callable, *args, **kwargs)
14
+ MethodCall.new(callable, *args, **kwargs, &block)
15
15
  when Proc
16
16
  InstanceExec.new(callable, *args, **kwargs)
17
17
  when Module
18
- KlassProxy.new(callable, method_name, *args, init_args: init_args, init_kwargs: init_kwargs, **kwargs)
18
+ KlassProxy.new(callable, method_name, *args, init_args: init_args, init_kwargs: init_kwargs, **kwargs, &block)
19
19
  when String
20
20
  klass = callable.safe_constantize
21
21
  raise ArgumentError, "could not resolve class from: #{callable.inspect}" unless klass
22
22
 
23
- KlassProxy.new(klass, method_name, *args, init_args: init_args, init_kwargs: init_kwargs, **kwargs)
23
+ KlassProxy.new(klass, method_name, *args, init_args: init_args, init_kwargs: init_kwargs, **kwargs, &block)
24
24
  end
25
25
  end
26
26
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module StimulusPlumbers
6
+ module Plumber
7
+ module Options
8
+ module Aria
9
+ extend ActiveSupport::Concern
10
+
11
+ def labelled_aria(label, labelledby: nil)
12
+ { label: (label unless labelledby), labelledby: labelledby }.compact
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+ require_relative "theme"
5
+ require_relative "stimulus"
6
+
7
+ module StimulusPlumbers
8
+ module Plumber
9
+ module Options
10
+ module Html
11
+ extend ActiveSupport::Concern
12
+
13
+ included do
14
+ include Theme
15
+ include Stimulus
16
+ end
17
+
18
+ def merge_html_options(*hashes)
19
+ class_value = merge_theme_options(*hashes)
20
+ merged_data = merge_stimulus_data(*hashes.map { |h| h[:data] || {} })
21
+ rest = hashes.map { |h| h.except(:class, :classes, :data) }.reduce({}, :deep_merge)
22
+
23
+ result = class_value ? rest.merge(class: class_value) : rest
24
+ merged_data.present? ? result.merge(data: merged_data) : result
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end