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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +72 -0
- data/README.md +3 -1
- data/app/assets/javascripts/stimulus-plumbers/controllers.manifest.json +273 -0
- data/app/assets/javascripts/stimulus-plumbers/stimulus-plumbers-controllers.es.js +269 -160
- data/app/assets/javascripts/stimulus-plumbers/stimulus-plumbers-controllers.umd.js +1 -1
- data/app/assets/stylesheets/stimulus_plumbers/tokens.css +56 -13
- data/config/locales/en.yml +10 -0
- data/lib/stimulus_plumbers/components/avatar.rb +24 -17
- data/lib/stimulus_plumbers/components/button/group.rb +15 -4
- data/lib/stimulus_plumbers/components/button/slots.rb +11 -0
- data/lib/stimulus_plumbers/components/button.rb +45 -11
- data/lib/stimulus_plumbers/components/calendar/turbo/days_of_month.rb +151 -0
- data/lib/stimulus_plumbers/components/calendar/turbo/days_of_week.rb +62 -0
- data/lib/stimulus_plumbers/components/calendar/turbo/months_of_year.rb +99 -0
- data/lib/stimulus_plumbers/components/calendar/turbo/years_of_decade.rb +86 -0
- data/lib/stimulus_plumbers/components/calendar/turbo.rb +65 -0
- data/lib/stimulus_plumbers/components/calendar.rb +70 -26
- data/lib/stimulus_plumbers/components/card/slots.rb +26 -0
- data/lib/stimulus_plumbers/components/card.rb +56 -10
- data/lib/stimulus_plumbers/components/combobox/builder.rb +45 -0
- data/lib/stimulus_plumbers/components/combobox/date/navigation.rb +72 -0
- data/lib/stimulus_plumbers/components/combobox/date/navigator.rb +25 -0
- data/lib/stimulus_plumbers/components/combobox/date.rb +37 -23
- data/lib/stimulus_plumbers/components/combobox/dropdown.rb +30 -21
- data/lib/stimulus_plumbers/components/combobox/options/option.rb +8 -2
- data/lib/stimulus_plumbers/components/combobox/options/option_group.rb +8 -2
- data/lib/stimulus_plumbers/components/combobox/options.rb +9 -5
- data/lib/stimulus_plumbers/components/combobox/time/drum.rb +8 -2
- data/lib/stimulus_plumbers/components/combobox/time.rb +50 -47
- data/lib/stimulus_plumbers/components/combobox/trigger.rb +62 -14
- data/lib/stimulus_plumbers/components/combobox/typeahead.rb +96 -0
- data/lib/stimulus_plumbers/components/combobox.rb +62 -38
- data/lib/stimulus_plumbers/components/divider.rb +25 -4
- data/lib/stimulus_plumbers/components/icon.rb +11 -17
- data/lib/stimulus_plumbers/components/input_group.rb +29 -0
- data/lib/stimulus_plumbers/components/link/slots.rb +11 -0
- data/lib/stimulus_plumbers/components/link.rb +63 -0
- data/lib/stimulus_plumbers/components/list/item/slots.rb +13 -0
- data/lib/stimulus_plumbers/components/list/item.rb +83 -0
- data/lib/stimulus_plumbers/components/list/section.rb +73 -0
- data/lib/stimulus_plumbers/components/list.rb +31 -0
- data/lib/stimulus_plumbers/components/popover/panel.rb +32 -0
- data/lib/stimulus_plumbers/components/popover/trigger.rb +27 -0
- data/lib/stimulus_plumbers/components/popover.rb +44 -14
- data/lib/stimulus_plumbers/engine.rb +1 -0
- data/lib/stimulus_plumbers/form/base.rb +103 -0
- data/lib/stimulus_plumbers/form/builder.rb +71 -24
- data/lib/stimulus_plumbers/form/field.rb +56 -88
- data/lib/stimulus_plumbers/form/fields/error.rb +1 -1
- data/lib/stimulus_plumbers/form/fields/fieldset.rb +11 -8
- data/lib/stimulus_plumbers/form/fields/hint.rb +1 -1
- data/lib/stimulus_plumbers/form/fields/inputs/checkbox.rb +115 -0
- data/lib/stimulus_plumbers/form/fields/inputs/combobox.rb +24 -0
- data/lib/stimulus_plumbers/form/fields/inputs/datetime.rb +42 -48
- data/lib/stimulus_plumbers/form/fields/inputs/file.rb +9 -8
- data/lib/stimulus_plumbers/form/fields/inputs/password.rb +32 -25
- data/lib/stimulus_plumbers/form/fields/inputs/radio.rb +60 -0
- data/lib/stimulus_plumbers/form/fields/inputs/search.rb +34 -57
- data/lib/stimulus_plumbers/form/fields/inputs/select/grouped.rb +22 -29
- data/lib/stimulus_plumbers/form/fields/inputs/select/timezone.rb +3 -44
- data/lib/stimulus_plumbers/form/fields/inputs/select/weekday.rb +3 -28
- data/lib/stimulus_plumbers/form/fields/inputs/select.rb +62 -49
- data/lib/stimulus_plumbers/form/fields/inputs/submit.rb +10 -7
- data/lib/stimulus_plumbers/form/fields/inputs/text.rb +29 -22
- data/lib/stimulus_plumbers/form/fields/inputs/text_area.rb +9 -8
- data/lib/stimulus_plumbers/form/fields/label/floating.rb +41 -0
- data/lib/stimulus_plumbers/form/fields/label.rb +9 -3
- data/lib/stimulus_plumbers/form/fields/renderer.rb +39 -0
- data/lib/stimulus_plumbers/helpers/avatar_helper.rb +2 -2
- data/lib/stimulus_plumbers/helpers/button_helper.rb +4 -8
- data/lib/stimulus_plumbers/helpers/calendar_helper.rb +14 -11
- data/lib/stimulus_plumbers/helpers/calendar_turbo_helper.rb +49 -11
- data/lib/stimulus_plumbers/helpers/card_helper.rb +2 -12
- data/lib/stimulus_plumbers/helpers/combobox_helper.rb +27 -47
- data/lib/stimulus_plumbers/helpers/divider_helper.rb +2 -2
- data/lib/stimulus_plumbers/helpers/icon_helper.rb +11 -0
- data/lib/stimulus_plumbers/helpers/link_helper.rb +11 -0
- data/lib/stimulus_plumbers/helpers/list_helper.rb +11 -0
- data/lib/stimulus_plumbers/helpers/plumber_helper.rb +3 -6
- data/lib/stimulus_plumbers/helpers/popover_helper.rb +2 -2
- data/lib/stimulus_plumbers/helpers.rb +6 -2
- data/lib/stimulus_plumbers/logger.rb +4 -3
- data/lib/stimulus_plumbers/plumber/base.rb +6 -1
- data/lib/stimulus_plumbers/plumber/dispatcher/klass_proxy.rb +4 -3
- data/lib/stimulus_plumbers/plumber/dispatcher/method_call.rb +4 -3
- data/lib/stimulus_plumbers/plumber/dispatcher.rb +4 -4
- data/lib/stimulus_plumbers/plumber/options/aria.rb +17 -0
- data/lib/stimulus_plumbers/plumber/options/html.rb +29 -0
- data/lib/stimulus_plumbers/plumber/options/stimulus.rb +29 -0
- data/lib/stimulus_plumbers/plumber/options/theme.rb +19 -0
- data/lib/stimulus_plumbers/plumber/options/token_list.rb +29 -0
- data/lib/stimulus_plumbers/plumber/renderer.rb +136 -41
- data/lib/stimulus_plumbers/plumber/slots.rb +74 -0
- data/lib/stimulus_plumbers/themes/base.rb +20 -23
- data/lib/stimulus_plumbers/themes/icons/external.rb +60 -0
- data/lib/stimulus_plumbers/themes/icons/registry.rb +36 -0
- data/lib/stimulus_plumbers/themes/schema/avatar/ranges.rb +13 -0
- data/lib/stimulus_plumbers/themes/schema/button/ranges.rb +16 -0
- data/lib/stimulus_plumbers/themes/schema/card/ranges.rb +13 -0
- data/lib/stimulus_plumbers/themes/schema/form/checkbox/ranges.rb +16 -0
- data/lib/stimulus_plumbers/themes/schema/form/radio/ranges.rb +16 -0
- data/lib/stimulus_plumbers/themes/schema/form/ranges.rb +1 -2
- data/lib/stimulus_plumbers/themes/schema/icon.rb +57 -15
- data/lib/stimulus_plumbers/themes/schema/link/ranges.rb +14 -0
- data/lib/stimulus_plumbers/themes/schema/ranges.rb +1 -5
- data/lib/stimulus_plumbers/themes/schema.rb +142 -67
- data/lib/stimulus_plumbers/version.rb +1 -1
- data/lib/stimulus_plumbers.rb +22 -17
- metadata +46 -17
- data/lib/stimulus_plumbers/components/action_list/item.rb +0 -27
- data/lib/stimulus_plumbers/components/action_list/section.rb +0 -22
- data/lib/stimulus_plumbers/components/action_list.rb +0 -23
- data/lib/stimulus_plumbers/components/calendar/month/turbo/days_of_month.rb +0 -145
- data/lib/stimulus_plumbers/components/calendar/month/turbo/days_of_week.rb +0 -39
- data/lib/stimulus_plumbers/components/calendar/month/turbo.rb +0 -55
- data/lib/stimulus_plumbers/components/card/section.rb +0 -25
- data/lib/stimulus_plumbers/components/combobox/autocomplete.rb +0 -47
- data/lib/stimulus_plumbers/components/combobox/popover.rb +0 -24
- data/lib/stimulus_plumbers/components/date_picker/navigation.rb +0 -41
- data/lib/stimulus_plumbers/components/date_picker/navigator.rb +0 -31
- data/lib/stimulus_plumbers/components/popover/builder.rb +0 -25
- data/lib/stimulus_plumbers/form/fields/input_group.rb +0 -25
- data/lib/stimulus_plumbers/form/fields/inputs/choice.rb +0 -69
- data/lib/stimulus_plumbers/helpers/action_list_helper.rb +0 -25
- data/lib/stimulus_plumbers/plumber/html_options.rb +0 -52
|
@@ -3,63 +3,43 @@
|
|
|
3
3
|
module StimulusPlumbers
|
|
4
4
|
module Helpers
|
|
5
5
|
module ComboboxHelper
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
opts = Components::Combobox::Date.default_opts.deep_merge(
|
|
9
|
-
input: { value: value },
|
|
10
|
-
trigger: { id: id, aria_label: label }.compact
|
|
11
|
-
)
|
|
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)
|
|
12
8
|
Components::Combobox.new(self).render(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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)
|
|
18
23
|
end
|
|
19
24
|
end
|
|
20
25
|
|
|
21
|
-
def sp_combobox_dropdown(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
input: { value: value },
|
|
25
|
-
trigger: { id: id, aria_label: label }.compact
|
|
26
|
-
)
|
|
27
|
-
Components::Combobox.new(self).render(**opts, **html_options) do
|
|
28
|
-
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)
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
def
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
input: { value: value },
|
|
36
|
-
trigger: { id: id, aria_label: label }.compact,
|
|
37
|
-
popover: { data: url ? { combobox_dropdown_url_value: url } : {} }
|
|
38
|
-
)
|
|
39
|
-
Components::Combobox.new(self).render(
|
|
40
|
-
**opts,
|
|
41
|
-
data: {
|
|
42
|
-
input_combobox_combobox_dropdown_outlet: "##{Components::Combobox.popover_id_for(id)}",
|
|
43
|
-
action: "input->input-combobox#onInput"
|
|
44
|
-
},
|
|
45
|
-
**html_options
|
|
46
|
-
) do
|
|
47
|
-
Components::Combobox::Autocomplete.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)
|
|
48
35
|
end
|
|
49
36
|
end
|
|
50
37
|
|
|
51
|
-
def sp_combobox_time(format: :h12,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
)
|
|
57
|
-
Components::Combobox.new(self).render(
|
|
58
|
-
**opts,
|
|
59
|
-
data: { input_format_type_value: "time", input_format_options_value: { format: format }.to_json },
|
|
60
|
-
**html_options
|
|
61
|
-
) do
|
|
62
|
-
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)
|
|
63
43
|
end
|
|
64
44
|
end
|
|
65
45
|
end
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
module StimulusPlumbers
|
|
4
4
|
module Helpers
|
|
5
5
|
module DividerHelper
|
|
6
|
-
def sp_divider(**
|
|
7
|
-
Components::Divider.new(self).render(**
|
|
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,12 +3,9 @@
|
|
|
3
3
|
module StimulusPlumbers
|
|
4
4
|
module Helpers
|
|
5
5
|
module PlumberHelper
|
|
6
|
-
def sp_dom_id(record = nil, suffix
|
|
7
|
-
|
|
8
|
-
|
|
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
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
module StimulusPlumbers
|
|
4
4
|
module Helpers
|
|
5
5
|
module PopoverHelper
|
|
6
|
-
def sp_popover(
|
|
7
|
-
popover_renderer.render(
|
|
6
|
+
def sp_popover(...)
|
|
7
|
+
popover_renderer.render(...)
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
private
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "helpers/plumber_helper"
|
|
4
|
-
require_relative "helpers/
|
|
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
|
|
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
|
|
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
|
|
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
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/concern"
|
|
4
|
+
require_relative "token_list"
|
|
5
|
+
|
|
6
|
+
module StimulusPlumbers
|
|
7
|
+
module Plumber
|
|
8
|
+
module Options
|
|
9
|
+
module Stimulus
|
|
10
|
+
extend ActiveSupport::Concern
|
|
11
|
+
include TokenList
|
|
12
|
+
|
|
13
|
+
STIMULUS_SPACEJOIN_KEYS = %i[controller action].freeze
|
|
14
|
+
|
|
15
|
+
def merge_stimulus_data(*hashes, spacejoin: STIMULUS_SPACEJOIN_KEYS)
|
|
16
|
+
hashes.reduce({}) do |acc, d|
|
|
17
|
+
acc.merge(d) do |key, old_val, new_val|
|
|
18
|
+
if spacejoin.include?(key.to_sym)
|
|
19
|
+
merge_token_list(old_val, new_val).presence || new_val
|
|
20
|
+
else
|
|
21
|
+
new_val
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/concern"
|
|
4
|
+
require_relative "token_list"
|
|
5
|
+
|
|
6
|
+
module StimulusPlumbers
|
|
7
|
+
module Plumber
|
|
8
|
+
module Options
|
|
9
|
+
module Theme
|
|
10
|
+
extend ActiveSupport::Concern
|
|
11
|
+
include TokenList
|
|
12
|
+
|
|
13
|
+
def merge_theme_options(*hashes)
|
|
14
|
+
merge_token_list(*hashes.flat_map { |h| [h[:class], h[:classes]] }).presence
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/concern"
|
|
4
|
+
|
|
5
|
+
module StimulusPlumbers
|
|
6
|
+
module Plumber
|
|
7
|
+
module Options
|
|
8
|
+
module TokenList
|
|
9
|
+
extend ActiveSupport::Concern
|
|
10
|
+
|
|
11
|
+
def merge_token_list(*parts, delimiter: " ")
|
|
12
|
+
tokens = parts.flat_map { |part| normalize_part(part, delimiter) }
|
|
13
|
+
tokens.compact.uniq.join(delimiter)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def normalize_part(value, delimiter)
|
|
19
|
+
case value
|
|
20
|
+
when String then value.present? ? value.split(delimiter) : []
|
|
21
|
+
when Hash then value.filter_map { |key, val| key if val }
|
|
22
|
+
when Array then [merge_token_list(*value).presence]
|
|
23
|
+
else []
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "active_support/concern"
|
|
4
|
+
require_relative "dispatcher"
|
|
4
5
|
|
|
5
6
|
module StimulusPlumbers
|
|
6
7
|
module Plumber
|
|
@@ -11,78 +12,172 @@ module StimulusPlumbers
|
|
|
11
12
|
class_attribute :renderers, instance_writer: false, default: {}
|
|
12
13
|
end
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
def set_slots
|
|
16
|
+
@set_slots ||= {}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def slot_renderable?(name)
|
|
20
|
+
slots = set_slots[name]
|
|
21
|
+
return false if slots.nil?
|
|
22
|
+
return false if slots.is_a?(StimulusPlumbers::Plumber::Slots) && slots.none?
|
|
23
|
+
return false if slots.is_a?(Array) && slots.empty?
|
|
24
|
+
|
|
25
|
+
true
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def slot_kwargs_for(name)
|
|
29
|
+
case set_slots[name]
|
|
30
|
+
when StimulusPlumbers::Plumber::Slots then { slot: set_slots[name] }
|
|
31
|
+
when Array
|
|
32
|
+
values = set_slots[name]
|
|
33
|
+
{ value: values.one? ? values.first : values }
|
|
34
|
+
else {}
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def slot_block_for(name)
|
|
39
|
+
slots = set_slots[name]
|
|
40
|
+
slots if slots.is_a?(Proc)
|
|
41
|
+
end
|
|
19
42
|
|
|
43
|
+
module ClassMethods
|
|
44
|
+
def renders(method_name, with: nil, slots: nil, by: nil, &block)
|
|
45
|
+
validate!(method_name, with, slots, by, block_given?)
|
|
20
46
|
with = block if block_given?
|
|
21
47
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
48
|
+
if slots.present?
|
|
49
|
+
by = Class.new(StimulusPlumbers::Plumber::Slots)
|
|
50
|
+
by.slot(*slots)
|
|
51
|
+
end
|
|
52
|
+
self.renderers = renderers.merge(method_name => { with: with, by: by })
|
|
25
53
|
|
|
26
|
-
|
|
27
|
-
|
|
54
|
+
generate_renderer_method(method_name)
|
|
55
|
+
generate_slot_method(method_name)
|
|
28
56
|
end
|
|
29
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
30
57
|
|
|
31
58
|
private
|
|
32
59
|
|
|
33
|
-
|
|
34
|
-
|
|
60
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
61
|
+
def validate!(method_name, with, slots, by, has_block)
|
|
62
|
+
raise ArgumentError, "method_name must be a Symbol" unless method_name.is_a?(Symbol)
|
|
63
|
+
raise ArgumentError, "provide either with: or a block, not both" if with && has_block
|
|
64
|
+
raise ArgumentError, "slots: requires with:" if slots && with.nil? && !has_block
|
|
65
|
+
raise ArgumentError, "by: requires with:" if by && with.nil?
|
|
66
|
+
raise ArgumentError, "slots: and by: are mutually exclusive" if slots && by
|
|
67
|
+
raise ArgumentError, "by: must be a Class" if by && !by.is_a?(Class)
|
|
68
|
+
|
|
69
|
+
with_proc_or_symbol = with.is_a?(Proc) || with.is_a?(Symbol)
|
|
70
|
+
with_klazz = with.is_a?(Module) || with.is_a?(String)
|
|
71
|
+
raise ArgumentError, "with: must be a Symbol/Proc/Class" unless with_proc_or_symbol || with_klazz || has_block
|
|
35
72
|
end
|
|
73
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
36
74
|
|
|
37
|
-
def
|
|
38
|
-
generated_renderer_methods.
|
|
39
|
-
# def method_name(*args, **kwargs)
|
|
40
|
-
# renderer = renderers.fetch(:method_name, {})
|
|
41
|
-
#
|
|
42
|
-
# unless renderer.present?
|
|
43
|
-
# raise ArgumentError, "#method_name not found in renderer" unless defined?(super)
|
|
44
|
-
# super
|
|
45
|
-
# end
|
|
46
|
-
#
|
|
47
|
-
# dispatcher = StimulusPlumbers::Plumber::Dispatcher.build(
|
|
48
|
-
# renderer, *args, method_name: :#{method_name}, init_args: [template], **kwargs
|
|
49
|
-
# )
|
|
50
|
-
# raise ArgumentError, "invalid renderer, got: \#{renderer.inspect}" unless dispatcher
|
|
51
|
-
#
|
|
52
|
-
# dispatcher.call(self)
|
|
53
|
-
# end
|
|
54
|
-
#{renderer_method_template(method_name)}
|
|
55
|
-
RUBY
|
|
75
|
+
def generated_renderer_methods
|
|
76
|
+
@generated_renderer_methods ||= Module.new.tap { |mod| prepend mod }
|
|
56
77
|
end
|
|
57
78
|
|
|
58
79
|
def generate_renderer_method(method_name)
|
|
80
|
+
return eval_renderer_method(method_name) if ActiveSupport.version < "7.2"
|
|
81
|
+
|
|
59
82
|
require "active_support/code_generator"
|
|
60
83
|
ActiveSupport::CodeGenerator.batch(generated_renderer_methods, __FILE__, __LINE__) do |owner|
|
|
61
|
-
owner.define_cached_method(method_name, namespace: :plumber_renderers) do |batch|
|
|
84
|
+
owner.define_cached_method(:"render_#{method_name}", namespace: :plumber_renderers) do |batch|
|
|
62
85
|
batch << renderer_method_template(method_name)
|
|
63
86
|
end
|
|
64
87
|
end
|
|
65
88
|
end
|
|
66
89
|
|
|
90
|
+
def eval_renderer_method(method_name)
|
|
91
|
+
generated_renderer_methods.module_eval(renderer_method_template(method_name), __FILE__, __LINE__)
|
|
92
|
+
end
|
|
93
|
+
|
|
67
94
|
def renderer_method_template(method_name)
|
|
68
95
|
<<-RUBY
|
|
69
|
-
def #{method_name}(*args, **kwargs)
|
|
70
|
-
|
|
96
|
+
def render_#{method_name}(*args, **kwargs)
|
|
97
|
+
return nil unless slot_renderable?(:#{method_name})
|
|
71
98
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
99
|
+
renderer = renderers.fetch(:#{method_name}, {})
|
|
100
|
+
target = renderer[:with]
|
|
101
|
+
unless target
|
|
102
|
+
raise ArgumentError, "#render_#{method_name} not found" unless defined?(super)
|
|
103
|
+
return super
|
|
75
104
|
end
|
|
76
105
|
|
|
77
106
|
dispatcher = StimulusPlumbers::Plumber::Dispatcher.build(
|
|
78
|
-
|
|
107
|
+
target, *args,
|
|
108
|
+
init_args: [template],
|
|
109
|
+
init_kwargs: {},
|
|
110
|
+
method_name: :render,
|
|
111
|
+
**kwargs,
|
|
112
|
+
**slot_kwargs_for(:#{method_name}),
|
|
113
|
+
&slot_block_for(:#{method_name})
|
|
79
114
|
)
|
|
80
|
-
raise ArgumentError, "invalid renderer
|
|
81
|
-
|
|
115
|
+
raise ArgumentError, "invalid renderer for :#{method_name}" unless dispatcher
|
|
82
116
|
dispatcher.call(self)
|
|
83
117
|
end
|
|
84
118
|
RUBY
|
|
85
119
|
end
|
|
120
|
+
|
|
121
|
+
def generated_slot_methods
|
|
122
|
+
@generated_slot_methods ||= Module.new.tap { |mod| prepend mod }
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def generate_slot_method(method_name)
|
|
126
|
+
return eval_slot_method(method_name) if ActiveSupport.version < "7.2"
|
|
127
|
+
|
|
128
|
+
require "active_support/code_generator"
|
|
129
|
+
ActiveSupport::CodeGenerator.batch(generated_slot_methods, __FILE__, __LINE__) do |owner|
|
|
130
|
+
owner.define_cached_method(:"with_#{method_name}", namespace: :plumber_renderers) do |batch|
|
|
131
|
+
batch << slot_setter_template(method_name)
|
|
132
|
+
end
|
|
133
|
+
owner.define_cached_method(:"#{method_name}", namespace: :plumber_renderers) do |batch|
|
|
134
|
+
batch << slot_getter_template(method_name)
|
|
135
|
+
end
|
|
136
|
+
owner.define_cached_method(:"#{method_name}?", namespace: :plumber_renderers) do |batch|
|
|
137
|
+
batch << slot_predicate_template(method_name)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def eval_slot_method(method_name)
|
|
143
|
+
generated_slot_methods.module_eval(slot_setter_template(method_name), __FILE__, __LINE__)
|
|
144
|
+
generated_slot_methods.module_eval(slot_getter_template(method_name), __FILE__, __LINE__)
|
|
145
|
+
generated_slot_methods.module_eval(slot_predicate_template(method_name), __FILE__, __LINE__)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def slot_setter_template(method_name)
|
|
149
|
+
<<-RUBY
|
|
150
|
+
def with_#{method_name}(*values, &block)
|
|
151
|
+
klass = renderers.dig(:#{method_name}, :by)
|
|
152
|
+
if klass && block_given? && !block.arity.zero?
|
|
153
|
+
builder = klass.new
|
|
154
|
+
block.call(builder)
|
|
155
|
+
set_slots[:#{method_name}] = builder
|
|
156
|
+
elsif block_given?
|
|
157
|
+
set_slots[:#{method_name}] = block
|
|
158
|
+
else
|
|
159
|
+
set_slots[:#{method_name}] = values
|
|
160
|
+
end
|
|
161
|
+
nil
|
|
162
|
+
end
|
|
163
|
+
RUBY
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def slot_getter_template(method_name)
|
|
167
|
+
<<-RUBY
|
|
168
|
+
def #{method_name}
|
|
169
|
+
set_slots[:#{method_name}]
|
|
170
|
+
end
|
|
171
|
+
RUBY
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def slot_predicate_template(method_name)
|
|
175
|
+
<<-RUBY
|
|
176
|
+
def #{method_name}?
|
|
177
|
+
slot_renderable?(:#{method_name})
|
|
178
|
+
end
|
|
179
|
+
RUBY
|
|
180
|
+
end
|
|
86
181
|
end
|
|
87
182
|
end
|
|
88
183
|
end
|