stimulus_plumbers 0.3.2 → 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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +72 -0
  3. data/README.md +3 -1
  4. data/app/assets/javascripts/stimulus-plumbers/controllers.manifest.json +273 -0
  5. data/app/assets/javascripts/stimulus-plumbers/stimulus-plumbers-controllers.es.js +269 -160
  6. data/app/assets/javascripts/stimulus-plumbers/stimulus-plumbers-controllers.umd.js +1 -1
  7. data/app/assets/stylesheets/stimulus_plumbers/tokens.css +56 -13
  8. data/config/locales/en.yml +10 -0
  9. data/lib/stimulus_plumbers/components/avatar.rb +24 -17
  10. data/lib/stimulus_plumbers/components/button/group.rb +15 -4
  11. data/lib/stimulus_plumbers/components/button/slots.rb +11 -0
  12. data/lib/stimulus_plumbers/components/button.rb +45 -11
  13. data/lib/stimulus_plumbers/components/calendar/turbo/days_of_month.rb +151 -0
  14. data/lib/stimulus_plumbers/components/calendar/turbo/days_of_week.rb +62 -0
  15. data/lib/stimulus_plumbers/components/calendar/turbo/months_of_year.rb +99 -0
  16. data/lib/stimulus_plumbers/components/calendar/turbo/years_of_decade.rb +86 -0
  17. data/lib/stimulus_plumbers/components/calendar/turbo.rb +65 -0
  18. data/lib/stimulus_plumbers/components/calendar.rb +70 -26
  19. data/lib/stimulus_plumbers/components/card/slots.rb +26 -0
  20. data/lib/stimulus_plumbers/components/card.rb +56 -10
  21. data/lib/stimulus_plumbers/components/combobox/builder.rb +45 -0
  22. data/lib/stimulus_plumbers/components/combobox/date/navigation.rb +72 -0
  23. data/lib/stimulus_plumbers/components/combobox/date/navigator.rb +25 -0
  24. data/lib/stimulus_plumbers/components/combobox/date.rb +37 -23
  25. data/lib/stimulus_plumbers/components/combobox/dropdown.rb +30 -21
  26. data/lib/stimulus_plumbers/components/combobox/options/option.rb +8 -2
  27. data/lib/stimulus_plumbers/components/combobox/options/option_group.rb +8 -2
  28. data/lib/stimulus_plumbers/components/combobox/options.rb +9 -5
  29. data/lib/stimulus_plumbers/components/combobox/time/drum.rb +8 -2
  30. data/lib/stimulus_plumbers/components/combobox/time.rb +50 -47
  31. data/lib/stimulus_plumbers/components/combobox/trigger.rb +62 -14
  32. data/lib/stimulus_plumbers/components/combobox/typeahead.rb +96 -0
  33. data/lib/stimulus_plumbers/components/combobox.rb +62 -38
  34. data/lib/stimulus_plumbers/components/divider.rb +25 -4
  35. data/lib/stimulus_plumbers/components/icon.rb +11 -17
  36. data/lib/stimulus_plumbers/components/input_group.rb +29 -0
  37. data/lib/stimulus_plumbers/components/link/slots.rb +11 -0
  38. data/lib/stimulus_plumbers/components/link.rb +63 -0
  39. data/lib/stimulus_plumbers/components/list/item/slots.rb +13 -0
  40. data/lib/stimulus_plumbers/components/list/item.rb +83 -0
  41. data/lib/stimulus_plumbers/components/list/section.rb +73 -0
  42. data/lib/stimulus_plumbers/components/list.rb +31 -0
  43. data/lib/stimulus_plumbers/components/popover/panel.rb +32 -0
  44. data/lib/stimulus_plumbers/components/popover/trigger.rb +27 -0
  45. data/lib/stimulus_plumbers/components/popover.rb +44 -14
  46. data/lib/stimulus_plumbers/engine.rb +1 -0
  47. data/lib/stimulus_plumbers/form/base.rb +103 -0
  48. data/lib/stimulus_plumbers/form/builder.rb +71 -24
  49. data/lib/stimulus_plumbers/form/field.rb +56 -88
  50. data/lib/stimulus_plumbers/form/fields/error.rb +1 -1
  51. data/lib/stimulus_plumbers/form/fields/fieldset.rb +11 -8
  52. data/lib/stimulus_plumbers/form/fields/hint.rb +1 -1
  53. data/lib/stimulus_plumbers/form/fields/inputs/checkbox.rb +115 -0
  54. data/lib/stimulus_plumbers/form/fields/inputs/combobox.rb +24 -0
  55. data/lib/stimulus_plumbers/form/fields/inputs/datetime.rb +42 -48
  56. data/lib/stimulus_plumbers/form/fields/inputs/file.rb +9 -8
  57. data/lib/stimulus_plumbers/form/fields/inputs/password.rb +32 -25
  58. data/lib/stimulus_plumbers/form/fields/inputs/radio.rb +60 -0
  59. data/lib/stimulus_plumbers/form/fields/inputs/search.rb +34 -57
  60. data/lib/stimulus_plumbers/form/fields/inputs/select/grouped.rb +22 -29
  61. data/lib/stimulus_plumbers/form/fields/inputs/select/timezone.rb +3 -44
  62. data/lib/stimulus_plumbers/form/fields/inputs/select/weekday.rb +3 -28
  63. data/lib/stimulus_plumbers/form/fields/inputs/select.rb +62 -49
  64. data/lib/stimulus_plumbers/form/fields/inputs/submit.rb +10 -7
  65. data/lib/stimulus_plumbers/form/fields/inputs/text.rb +29 -22
  66. data/lib/stimulus_plumbers/form/fields/inputs/text_area.rb +9 -8
  67. data/lib/stimulus_plumbers/form/fields/label/floating.rb +41 -0
  68. data/lib/stimulus_plumbers/form/fields/label.rb +9 -3
  69. data/lib/stimulus_plumbers/form/fields/renderer.rb +39 -0
  70. data/lib/stimulus_plumbers/helpers/avatar_helper.rb +2 -2
  71. data/lib/stimulus_plumbers/helpers/button_helper.rb +4 -8
  72. data/lib/stimulus_plumbers/helpers/calendar_helper.rb +14 -11
  73. data/lib/stimulus_plumbers/helpers/calendar_turbo_helper.rb +49 -11
  74. data/lib/stimulus_plumbers/helpers/card_helper.rb +2 -12
  75. data/lib/stimulus_plumbers/helpers/combobox_helper.rb +27 -47
  76. data/lib/stimulus_plumbers/helpers/divider_helper.rb +2 -2
  77. data/lib/stimulus_plumbers/helpers/icon_helper.rb +11 -0
  78. data/lib/stimulus_plumbers/helpers/link_helper.rb +11 -0
  79. data/lib/stimulus_plumbers/helpers/list_helper.rb +11 -0
  80. data/lib/stimulus_plumbers/helpers/plumber_helper.rb +3 -6
  81. data/lib/stimulus_plumbers/helpers/popover_helper.rb +2 -2
  82. data/lib/stimulus_plumbers/helpers.rb +6 -2
  83. data/lib/stimulus_plumbers/logger.rb +4 -3
  84. data/lib/stimulus_plumbers/plumber/base.rb +6 -1
  85. data/lib/stimulus_plumbers/plumber/dispatcher/klass_proxy.rb +4 -3
  86. data/lib/stimulus_plumbers/plumber/dispatcher/method_call.rb +4 -3
  87. data/lib/stimulus_plumbers/plumber/dispatcher.rb +4 -4
  88. data/lib/stimulus_plumbers/plumber/options/aria.rb +17 -0
  89. data/lib/stimulus_plumbers/plumber/options/html.rb +29 -0
  90. data/lib/stimulus_plumbers/plumber/options/stimulus.rb +29 -0
  91. data/lib/stimulus_plumbers/plumber/options/theme.rb +19 -0
  92. data/lib/stimulus_plumbers/plumber/options/token_list.rb +29 -0
  93. data/lib/stimulus_plumbers/plumber/renderer.rb +136 -41
  94. data/lib/stimulus_plumbers/plumber/slots.rb +74 -0
  95. data/lib/stimulus_plumbers/themes/base.rb +20 -23
  96. data/lib/stimulus_plumbers/themes/icons/external.rb +60 -0
  97. data/lib/stimulus_plumbers/themes/icons/registry.rb +36 -0
  98. data/lib/stimulus_plumbers/themes/schema/avatar/ranges.rb +13 -0
  99. data/lib/stimulus_plumbers/themes/schema/button/ranges.rb +16 -0
  100. data/lib/stimulus_plumbers/themes/schema/card/ranges.rb +13 -0
  101. data/lib/stimulus_plumbers/themes/schema/form/checkbox/ranges.rb +16 -0
  102. data/lib/stimulus_plumbers/themes/schema/form/radio/ranges.rb +16 -0
  103. data/lib/stimulus_plumbers/themes/schema/form/ranges.rb +1 -2
  104. data/lib/stimulus_plumbers/themes/schema/icon.rb +57 -15
  105. data/lib/stimulus_plumbers/themes/schema/link/ranges.rb +14 -0
  106. data/lib/stimulus_plumbers/themes/schema/ranges.rb +1 -5
  107. data/lib/stimulus_plumbers/themes/schema.rb +142 -67
  108. data/lib/stimulus_plumbers/version.rb +1 -1
  109. data/lib/stimulus_plumbers.rb +22 -17
  110. metadata +46 -17
  111. data/lib/stimulus_plumbers/components/action_list/item.rb +0 -27
  112. data/lib/stimulus_plumbers/components/action_list/section.rb +0 -22
  113. data/lib/stimulus_plumbers/components/action_list.rb +0 -23
  114. data/lib/stimulus_plumbers/components/calendar/month/turbo/days_of_month.rb +0 -145
  115. data/lib/stimulus_plumbers/components/calendar/month/turbo/days_of_week.rb +0 -39
  116. data/lib/stimulus_plumbers/components/calendar/month/turbo.rb +0 -55
  117. data/lib/stimulus_plumbers/components/card/section.rb +0 -25
  118. data/lib/stimulus_plumbers/components/combobox/autocomplete.rb +0 -47
  119. data/lib/stimulus_plumbers/components/combobox/popover.rb +0 -24
  120. data/lib/stimulus_plumbers/components/date_picker/navigation.rb +0 -41
  121. data/lib/stimulus_plumbers/components/date_picker/navigator.rb +0 -31
  122. data/lib/stimulus_plumbers/components/popover/builder.rb +0 -25
  123. data/lib/stimulus_plumbers/form/fields/input_group.rb +0 -25
  124. data/lib/stimulus_plumbers/form/fields/inputs/choice.rb +0 -69
  125. data/lib/stimulus_plumbers/helpers/action_list_helper.rb +0 -25
  126. data/lib/stimulus_plumbers/plumber/html_options.rb +0 -52
@@ -1,145 +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(**kwargs)
30
- html_options = merge_html_options(
31
- { classes: theme.resolve(:calendar_days_of_month).fetch(:classes, "") },
32
- kwargs
33
- )
34
- template.content_tag(:div, **html_options, role: "rowgroup") { weeks_of_month }
35
- end
36
-
37
- private
38
-
39
- def weeks_of_month
40
- week_options = merge_html_options(
41
- { classes: theme.resolve(:calendar_week).fetch(:classes, "") },
42
- { role: "row" }
43
- )
44
- template.safe_join(
45
- build_days.each_slice(DAYS_IN_WEEK).map do |days|
46
- template.content_tag(:div, **week_options) { days_in_week(days) }
47
- end
48
- )
49
- end
50
-
51
- def focus_day
52
- @focus_day ||= if selected_date_in_current_month?
53
- selected_date
54
- elsif today_in_current_month?
55
- today
56
- else
57
- date.beginning_of_month
58
- end
59
- end
60
-
61
- def build_days
62
- first = date.beginning_of_month
63
- last = date.end_of_month
64
- current_days = first.upto(last).to_a
65
- prev_filler_days(first) + current_days + next_filler_days(last, current_days.length)
66
- end
67
-
68
- def prev_filler_days(first_day_of_month)
69
- week_start = first_day_of_month - first_day_of_month.wday
70
- week_start.upto(first_day_of_month - 1).to_a
71
- end
72
-
73
- def next_filler_days(last_day_of_month, days_in_month)
74
- week_start_offset = last_day_of_month.beginning_of_month.wday
75
- total = week_start_offset + days_in_month
76
- next_count = (DAYS_IN_WEEK - (total % DAYS_IN_WEEK)) % DAYS_IN_WEEK
77
- next_count.positive? ? (last_day_of_month + 1).upto(last_day_of_month + next_count).to_a : []
78
- end
79
-
80
- def selected_date_in_current_month?
81
- selected_date&.month == date.month && selected_date&.year == date.year
82
- end
83
-
84
- def today_in_current_month?
85
- today.month == date.month && today.year == date.year
86
- end
87
-
88
- def days_in_week(days)
89
- template.safe_join(
90
- days.map do |day|
91
- if day.month == date.month
92
- current_month_day_cell(day)
93
- elsif show_other_months
94
- other_month_day_cell(day)
95
- else
96
- hidden_day_cell(day)
97
- end
98
- end
99
- )
100
- end
101
-
102
- def hidden_day_cell(date)
103
- template.content_tag(:span, role: "gridcell", tabindex: -1, aria: { hidden: "true" }) do
104
- template.content_tag(:time, nil, datetime: date.iso8601)
105
- end
106
- end
107
-
108
- def current_month_day_cell(date)
109
- tag = selectable ? :button : :span
110
- template.content_tag(tag, **day_cell_html_options(date, today)) do
111
- template.content_tag(:time, date.day.to_s, datetime: date.iso8601)
112
- end
113
- end
114
-
115
- def day_cell_html_options(date, today)
116
- is_today = date == today
117
- selected = selected_date && date == selected_date
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
- }
127
- }
128
- )
129
- end
130
-
131
- def other_month_day_cell(date)
132
- options = merge_html_options(
133
- { classes: theme.resolve(:calendar_day, outside: true).fetch(:classes, "") },
134
- { role: "gridcell", tabindex: -1, aria: { disabled: "true", selected: "false" } }
135
- )
136
- template.content_tag(:span, **options) do
137
- template.content_tag(:time, date.day.to_s, datetime: date.iso8601)
138
- end
139
- end
140
- end
141
- end
142
- end
143
- end
144
- end
145
- end
@@ -1,39 +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(**kwargs)
10
- html_options = merge_html_options(
11
- { classes: theme.resolve(:calendar_days_of_week).fetch(:classes, "") },
12
- kwargs
13
- )
14
- template.content_tag(:div, **html_options) { days_of_week }
15
- end
16
-
17
- private
18
-
19
- def days_of_week
20
- week_options = merge_html_options(
21
- { classes: theme.resolve(:calendar_week).fetch(:classes, "") },
22
- { role: "row" }
23
- )
24
- template.content_tag(:div, **week_options) do
25
- template.safe_join(
26
- day_names.map { |abbr, full| template.content_tag(:span, abbr, role: "columnheader", abbr: full) }
27
- )
28
- end
29
- end
30
-
31
- def day_names
32
- I18n.t("date.abbr_day_names").zip(I18n.t("date.day_names"))
33
- end
34
- end
35
- end
36
- end
37
- end
38
- end
39
- end
@@ -1,55 +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
- date: Date.today,
12
- today: Date.today,
13
- selectable: false,
14
- selected_date: nil,
15
- show_other_months: false,
16
- **kwargs
17
- )
18
- html_options = merge_html_options(
19
- {
20
- classes: theme.resolve(:calendar).fetch(:classes, ""),
21
- data: { controller: STIMULUS_CONTROLLER, action: "click->#{STIMULUS_CONTROLLER}#select" }
22
- },
23
- kwargs
24
- )
25
-
26
- template.content_tag(:div, role: "grid", **html_options) do
27
- template.safe_join(
28
- [
29
- days_of_week,
30
- days_of_month(
31
- date: date,
32
- today: today,
33
- selectable: selectable,
34
- selected_date: selected_date,
35
- show_other_months: show_other_months
36
- )
37
- ]
38
- )
39
- end
40
- end
41
-
42
- private
43
-
44
- def days_of_week(**kwargs)
45
- Turbo::DaysOfWeek.new(template).render(**kwargs)
46
- end
47
-
48
- def days_of_month(**kwargs)
49
- Turbo::DaysOfMonth.new(template, **kwargs).render
50
- end
51
- end
52
- end
53
- end
54
- end
55
- end
@@ -1,25 +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(title: nil, title_tag: :h3, **kwargs, &block)
8
- html_options = merge_html_options(
9
- { classes: theme.resolve(:card_section).fetch(:classes, "") },
10
- kwargs
11
- )
12
-
13
- template.content_tag(:div, **html_options) do
14
- template.safe_join(
15
- [
16
- (template.content_tag(title_tag, title) if title.present?),
17
- template.capture(&block)
18
- ]
19
- )
20
- end
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module StimulusPlumbers
4
- module Components
5
- class Combobox
6
- class Autocomplete < Plumber::Base
7
- def self.default_opts
8
- Dropdown.default_opts.deep_merge(
9
- trigger: { aria_autocomplete: "list", readonly: false }
10
- )
11
- end
12
-
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
- )
21
- end
22
-
23
- private
24
-
25
- def loading
26
- template.content_tag(
27
- :div,
28
- **merge_html_options(
29
- { classes: theme.resolve(:combobox_autocomplete_loading).fetch(:classes, "") },
30
- { hidden: "", aria: { live: "polite" }, data: { "#{Dropdown::STIMULUS_CONTROLLER}_target": "loading" } }
31
- )
32
- ) { "" }
33
- end
34
-
35
- def empty
36
- template.content_tag(
37
- :div,
38
- **merge_html_options(
39
- { classes: theme.resolve(:combobox_autocomplete_empty).fetch(:classes, "") },
40
- { hidden: "", role: "status", data: { "#{Dropdown::STIMULUS_CONTROLLER}_target": "empty" } }
41
- )
42
- ) { "No results" }
43
- end
44
- end
45
- end
46
- end
47
- end
@@ -1,24 +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(stimulus_controller:, id:, tag: :div, role: nil, label: nil, labelledby: nil, content: nil, data: {}, &block)
8
- stimulus_data = { "#{stimulus_controller}_target": "popover" }
9
-
10
- attrs = { id: id, hidden: "", data: merge_data_options(stimulus_data, data) }
11
- attrs[:role] = role if role
12
- if labelledby
13
- attrs[:aria] = { labelledby: labelledby }
14
- elsif label
15
- attrs[:aria] = { label: label }
16
- end
17
-
18
- html_content = block_given? ? template.capture(id, &block) : content
19
- template.content_tag(tag, **attrs) { html_content }
20
- end
21
- end
22
- end
23
- end
24
- 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_options] = { name: icon } if icon
36
- Navigator.new(template).render(**opts)
37
- end
38
- end
39
- end
40
- end
41
- end
@@ -1,31 +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(icon_options: nil, **kwargs)
8
- html_options = merge_html_options(
9
- { classes: theme.resolve(:calendar_navigation_navigator).fetch(:classes, "") },
10
- kwargs
11
- )
12
-
13
- if icon_options.nil?
14
- template.content_tag(:button, nil, **html_options)
15
- else
16
- template.content_tag(:button, icon(icon_options), **html_options)
17
- end
18
- end
19
-
20
- private
21
-
22
- def icon(icon_options)
23
- Icon.new(template).render(
24
- classes: theme.resolve(:calendar_navigation_navigator_icon).fetch(:classes, ""),
25
- **icon_options
26
- )
27
- end
28
- end
29
- end
30
- end
31
- 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,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module StimulusPlumbers
4
- module Form
5
- module Fields
6
- class InputGroup < Plumber::Base
7
- def render(leading: nil, trailing: nil, error: false, **wrapper_opts, &block)
8
- html_options = merge_html_options(
9
- theme.resolve(:form_input_group, error: error),
10
- wrapper_opts
11
- )
12
- template.content_tag(:div, **html_options) do
13
- template.safe_join(
14
- [
15
- leading.respond_to?(:call) ? leading.call : leading,
16
- template.capture(&block),
17
- trailing.respond_to?(:call) ? trailing.call : trailing
18
- ]
19
- )
20
- end
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(**html_options, &block)
7
- action_list_renderer.render(**html_options, &block)
8
- end
9
-
10
- def sp_action_list_section(title: nil, **html_options, &block)
11
- action_list_renderer.section(title: title, **html_options, &block)
12
- end
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)
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