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
@@ -1,149 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module StimulusPlumbers
4
- module Components
5
- class Calendar
6
- module Month
7
- class Turbo
8
- class DaysOfMonth < Plumber::Base
9
- DAYS_IN_WEEK = 7
10
-
11
- attr_reader :date, :today, :selectable, :selected_date, :show_other_months
12
-
13
- def initialize(
14
- template,
15
- date: Date.today,
16
- today: Date.today,
17
- selectable: false,
18
- selected_date: nil,
19
- show_other_months: false
20
- )
21
- super(template)
22
- @date = date
23
- @today = today
24
- @selectable = selectable
25
- @selected_date = selected_date
26
- @show_other_months = show_other_months
27
- end
28
-
29
- def render(...)
30
- render_days_of_month(...)
31
- end
32
-
33
- private
34
-
35
- def render_days_of_month(**html_options)
36
- html_options = merge_html_options(
37
- { classes: theme.resolve(:calendar_days_of_month).fetch(:classes, "") },
38
- html_options
39
- )
40
- template.content_tag(:div, **html_options, role: "rowgroup") { weeks_of_month }
41
- end
42
-
43
- def weeks_of_month
44
- week_options = merge_html_options(
45
- { classes: theme.resolve(:calendar_week).fetch(:classes, "") },
46
- { role: "row" }
47
- )
48
- template.safe_join(
49
- build_days.each_slice(DAYS_IN_WEEK).map do |days|
50
- template.content_tag(:div, **week_options) { days_in_week(days) }
51
- end
52
- )
53
- end
54
-
55
- def focus_day
56
- @focus_day ||= if selected_date_in_current_month?
57
- selected_date
58
- elsif today_in_current_month?
59
- today
60
- else
61
- date.beginning_of_month
62
- end
63
- end
64
-
65
- def build_days
66
- first = date.beginning_of_month
67
- last = date.end_of_month
68
- current_days = first.upto(last).to_a
69
- prev_filler_days(first) + current_days + next_filler_days(last, current_days.length)
70
- end
71
-
72
- def prev_filler_days(first_day_of_month)
73
- week_start = first_day_of_month - first_day_of_month.wday
74
- week_start.upto(first_day_of_month - 1).to_a
75
- end
76
-
77
- def next_filler_days(last_day_of_month, days_in_month)
78
- week_start_offset = last_day_of_month.beginning_of_month.wday
79
- total = week_start_offset + days_in_month
80
- next_count = (DAYS_IN_WEEK - (total % DAYS_IN_WEEK)) % DAYS_IN_WEEK
81
- next_count.positive? ? (last_day_of_month + 1).upto(last_day_of_month + next_count).to_a : []
82
- end
83
-
84
- def selected_date_in_current_month?
85
- selected_date&.month == date.month && selected_date&.year == date.year
86
- end
87
-
88
- def today_in_current_month?
89
- today.month == date.month && today.year == date.year
90
- end
91
-
92
- def days_in_week(days)
93
- template.safe_join(
94
- days.map do |day|
95
- if day.month == date.month
96
- current_month_day_cell(day)
97
- elsif show_other_months
98
- other_month_day_cell(day)
99
- else
100
- hidden_day_cell(day)
101
- end
102
- end
103
- )
104
- end
105
-
106
- def hidden_day_cell(date)
107
- template.content_tag(:span, role: "gridcell", tabindex: -1, aria: { hidden: "true" }) do
108
- template.content_tag(:time, nil, datetime: date.iso8601)
109
- end
110
- end
111
-
112
- def current_month_day_cell(date)
113
- tag = selectable ? :button : :span
114
- template.content_tag(tag, **day_cell_html_options(date, today)) do
115
- template.content_tag(:time, date.day.to_s, datetime: date.iso8601)
116
- end
117
- end
118
-
119
- def day_cell_html_options(date, today)
120
- is_today = date == today
121
- selected = selected_date && date == selected_date
122
- merge_html_options(
123
- { classes: theme.resolve(:calendar_day).fetch(:classes, "") },
124
- {
125
- role: "gridcell",
126
- tabindex: date == focus_day ? 0 : -1,
127
- aria: {
128
- current: is_today ? "date" : nil,
129
- selected: if selectable then selected ? "true" : "false" end
130
- }
131
- }
132
- )
133
- end
134
-
135
- def other_month_day_cell(date)
136
- options = merge_html_options(
137
- { classes: theme.resolve(:calendar_day, outside: true).fetch(:classes, "") },
138
- { role: "gridcell", tabindex: -1, aria: { disabled: "true", selected: "false" } }
139
- )
140
- template.content_tag(:span, **options) do
141
- template.content_tag(:time, date.day.to_s, datetime: date.iso8601)
142
- end
143
- end
144
- end
145
- end
146
- end
147
- end
148
- end
149
- end
@@ -1,43 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module StimulusPlumbers
4
- module Components
5
- class Calendar
6
- module Month
7
- class Turbo
8
- class DaysOfWeek < Plumber::Base
9
- def render(...)
10
- render_days_of_week(...)
11
- end
12
-
13
- private
14
-
15
- def render_days_of_week(**kwargs)
16
- html_options = merge_html_options(
17
- { classes: theme.resolve(:calendar_days_of_week).fetch(:classes, "") },
18
- kwargs
19
- )
20
- template.content_tag(:div, **html_options) { days_of_week }
21
- end
22
-
23
- def days_of_week
24
- week_options = merge_html_options(
25
- { classes: theme.resolve(:calendar_week).fetch(:classes, "") },
26
- { role: "row" }
27
- )
28
- template.content_tag(:div, **week_options) do
29
- template.safe_join(
30
- day_names.map { |abbr, full| template.content_tag(:span, abbr, role: "columnheader", abbr: full) }
31
- )
32
- end
33
- end
34
-
35
- def day_names
36
- I18n.t("date.abbr_day_names").zip(I18n.t("date.day_names"))
37
- end
38
- end
39
- end
40
- end
41
- end
42
- end
43
- end
@@ -1,59 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module StimulusPlumbers
4
- module Components
5
- class Calendar
6
- module Month
7
- class Turbo < Plumber::Base
8
- STIMULUS_CONTROLLER = "calendar-month-observer"
9
-
10
- def render(...)
11
- render_turbo(...)
12
- end
13
-
14
- private
15
-
16
- def render_turbo(
17
- date: Date.today,
18
- today: Date.today,
19
- selectable: false,
20
- selected_date: nil,
21
- show_other_months: false,
22
- **kwargs
23
- )
24
- html_options = merge_html_options(
25
- {
26
- classes: theme.resolve(:calendar).fetch(:classes, ""),
27
- data: { controller: STIMULUS_CONTROLLER, action: "click->#{STIMULUS_CONTROLLER}#select" }
28
- },
29
- kwargs
30
- )
31
-
32
- template.content_tag(:div, role: "grid", **html_options) do
33
- template.safe_join(
34
- [
35
- days_of_week,
36
- days_of_month(
37
- date: date,
38
- today: today,
39
- selectable: selectable,
40
- selected_date: selected_date,
41
- show_other_months: show_other_months
42
- )
43
- ]
44
- )
45
- end
46
- end
47
-
48
- def days_of_week(**kwargs)
49
- Turbo::DaysOfWeek.new(template).render(**kwargs)
50
- end
51
-
52
- def days_of_month(**kwargs)
53
- Turbo::DaysOfMonth.new(template, **kwargs).render
54
- end
55
- end
56
- end
57
- end
58
- end
59
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module StimulusPlumbers
4
- module Components
5
- class Card
6
- class Section < Plumber::Base
7
- def render(...)
8
- render_section(...)
9
- end
10
-
11
- private
12
-
13
- def render_section(title: nil, title_tag: :h3, **kwargs, &block)
14
- html_options = merge_html_options(
15
- { classes: theme.resolve(:card_section).fetch(:classes, "") },
16
- kwargs
17
- )
18
-
19
- template.content_tag(:div, **html_options) do
20
- template.safe_join(
21
- [
22
- (template.content_tag(title_tag, title) if title.present?),
23
- template.capture(&block)
24
- ]
25
- )
26
- end
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module StimulusPlumbers
4
- module Components
5
- class Combobox
6
- class Popover < Plumber::Base
7
- def render(...)
8
- render_popover(...)
9
- end
10
-
11
- private
12
-
13
- def render_popover(
14
- stimulus_controller:,
15
- id:,
16
- tag: :div,
17
- role: nil,
18
- label: nil,
19
- labelledby: nil,
20
- content: nil,
21
- data: {},
22
- **kwargs,
23
- &block
24
- )
25
- opts = {}
26
- opts[:role] = role if role
27
- if labelledby
28
- opts[:aria] = { labelledby: labelledby }
29
- elsif label
30
- opts[:aria] = { label: label }
31
- end
32
-
33
- html_options = merge_html_options(
34
- { id: id, hidden: "" },
35
- { data: { "#{stimulus_controller}_target": "popover" } },
36
- { data: data },
37
- opts,
38
- kwargs
39
- )
40
-
41
- html_content = block_given? ? template.capture(id, &block) : content
42
- template.content_tag(tag, html_content, **html_options)
43
- end
44
- end
45
- end
46
- end
47
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module StimulusPlumbers
4
- module Components
5
- module DatePicker
6
- class Navigation < Plumber::Base
7
- def render(step:, stimulus_controller:, **kwargs)
8
- html_options = merge_html_options(
9
- { classes: theme.resolve(:calendar_navigation).fetch(:classes, ""), aria: { label: "DatePicker Navigation" } },
10
- kwargs
11
- )
12
-
13
- template.content_tag(:nav, **html_options) do
14
- template.safe_join(navigators(stimulus_controller, step))
15
- end
16
- end
17
-
18
- private
19
-
20
- def navigators(stimulus_controller, step)
21
- [
22
- navigator(stimulus_controller, target: "previous", icon: "arrow-left", label: ["previous", step].join(" ").titleize),
23
- navigator(stimulus_controller, target: "day", label: "Day"),
24
- navigator(stimulus_controller, target: "month", label: "Month"),
25
- navigator(stimulus_controller, target: "year", label: "Year"),
26
- navigator(stimulus_controller, target: "next", icon: "arrow-right", label: ["next", step].join(" ").titleize)
27
- ]
28
- end
29
-
30
- def navigator(stimulus_controller, target:, label:, icon: nil)
31
- opts = {
32
- aria: { label: label },
33
- data: { "#{stimulus_controller}-target" => target }
34
- }
35
- opts[:icon] = icon if icon
36
- Navigator.new(template).render(**opts)
37
- end
38
- end
39
- end
40
- end
41
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module StimulusPlumbers
4
- module Components
5
- module DatePicker
6
- class Navigator < Plumber::Base
7
- def render(...)
8
- render_navigator(...)
9
- end
10
-
11
- private
12
-
13
- def render_navigator(icon: nil, **kwargs)
14
- html_options = merge_html_options(
15
- { classes: theme.resolve(:calendar_navigation_navigator).fetch(:classes, "") },
16
- kwargs
17
- )
18
- Components::Button.new(template).render(variant: :ghost, size: nil, icon_leading: icon, **html_options)
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module StimulusPlumbers
4
- module Components
5
- class Popover
6
- class Builder
7
- attr_reader :activator_html, :content_html
8
-
9
- def initialize(template)
10
- @template = template
11
- @activator_html = nil
12
- @content_html = nil
13
- end
14
-
15
- def activator(&block)
16
- @activator_html = @template.capture(&block)
17
- end
18
-
19
- def content(&block)
20
- @content_html = @template.capture(&block)
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,69 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module StimulusPlumbers
4
- module Form
5
- module Fields
6
- module Inputs
7
- module Choice
8
- def check_box(attribute, options = {}, checked_value = "1", unchecked_value = "0")
9
- options[:layout] ||= :inline
10
- Field.new(@template, **options).render(
11
- object,
12
- attribute,
13
- input_id: field_id(attribute)
14
- ) do |html_opts, opts, error|
15
- html_options = merge_html_options(opts, html_opts, field_theme(:form_checkbox, error: error))
16
- super(attribute, html_options, checked_value, unchecked_value)
17
- end
18
- end
19
-
20
- def collection_check_boxes(
21
- attribute,
22
- collection,
23
- value_method,
24
- text_method,
25
- options = {},
26
- html_options = {},
27
- &block
28
- )
29
- options[:layout] ||= :inline
30
- field = Field.new(@template, **options)
31
- render_fieldset(attribute, field) do |error|
32
- item_opts = merge_html_options(html_options, field_theme(:form_checkbox, error: error))
33
- super(attribute, collection, value_method, text_method, {}, item_opts, &block)
34
- end
35
- end
36
-
37
- def radio_button(attribute, tag_value, options = {})
38
- options[:layout] ||= :inline
39
- Field.new(@template, **options).render(
40
- object,
41
- attribute,
42
- input_id: field_id(attribute, tag_value)
43
- ) do |html_opts, opts, error|
44
- html_options = merge_html_options(opts, html_opts, field_theme(:form_radio, error: error))
45
- super(attribute, tag_value, html_options)
46
- end
47
- end
48
-
49
- def collection_radio_buttons(
50
- attribute,
51
- collection,
52
- value_method,
53
- text_method,
54
- options = {},
55
- html_options = {},
56
- &block
57
- )
58
- options[:layout] ||= :inline
59
- field = Field.new(@template, **options)
60
- render_fieldset(attribute, field) do |error|
61
- item_opts = merge_html_options(html_options, field_theme(:form_radio, error: error))
62
- super(attribute, collection, value_method, text_method, {}, item_opts, &block)
63
- end
64
- end
65
- end
66
- end
67
- end
68
- end
69
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module StimulusPlumbers
4
- module Helpers
5
- module ActionListHelper
6
- def sp_action_list(...)
7
- action_list_renderer.render(...)
8
- end
9
-
10
- def sp_action_list_section(...)
11
- action_list_renderer.section(...)
12
- end
13
-
14
- def sp_action_list_item(content = nil, **kwargs, &block)
15
- action_list_renderer.item(content, **kwargs, &block)
16
- end
17
-
18
- private
19
-
20
- def action_list_renderer
21
- Components::ActionList.new(self)
22
- end
23
- end
24
- end
25
- end
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "active_support/concern"
4
-
5
- module StimulusPlumbers
6
- module Plumber
7
- module HtmlOptions
8
- extend ActiveSupport::Concern
9
-
10
- def merge_html_options(*hashes)
11
- class_value = merge_string_option(*extract_classes(*hashes)).presence
12
- merged_data = merge_data_options(*hashes.map { |h| h[:data] || {} })
13
- rest = hashes.map { |h| h.except(:class, :classes, :data) }.reduce({}, :deep_merge)
14
-
15
- result = class_value ? rest.merge(class: class_value) : rest
16
- merged_data.present? ? result.merge(data: merged_data) : result
17
- end
18
-
19
- def extract_classes(*hashes)
20
- hashes.flat_map { |h| [h[:class], h[:classes]] }
21
- end
22
-
23
- STIMULUS_SPACEJOIN_KEYS = %i[controller action].freeze
24
-
25
- def merge_data_options(*hashes, spacejoin: STIMULUS_SPACEJOIN_KEYS)
26
- hashes.reduce({}) do |acc, d|
27
- acc.merge(d) do |key, old_val, new_val|
28
- if spacejoin.include?(key.to_sym)
29
- merge_string_option(old_val, new_val).presence || new_val
30
- else
31
- new_val
32
- end
33
- end
34
- end
35
- end
36
-
37
- def merge_string_option(*parts, delimiter: " ")
38
- tokens = parts.flat_map { |part| normalize_part(part, delimiter) }
39
- tokens.compact.uniq.join(delimiter)
40
- end
41
-
42
- def normalize_part(value, delimiter)
43
- case value
44
- when String then value.present? ? value.split(delimiter) : []
45
- when Hash then value.filter_map { |key, val| key if val }
46
- when Array then [merge_string_option(*value).presence]
47
- else []
48
- end
49
- end
50
- end
51
- end
52
- end