Class: LocoMotion::ComponentConfig

Inherits:
Object
  • Object
show all
Includes:
LocoMotion::Concerns::InspectableComponent
Defined in:
lib/loco_motion/component_config.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from LocoMotion::Concerns::InspectableComponent

#build_inspect_string

Constructor Details

#initialize(component, **kws) ⇒ ComponentConfig

Returns a new instance of ComponentConfig.



9
10
11
12
13
14
15
16
17
18
19
# File 'lib/loco_motion/component_config.rb', line 9

def initialize(component, **kws)
  @component = component
  @options = kws

  @parts = {}
  @modifiers = (kws[:modifiers] || [kws[:modifier]]).compact
  @size = kws[:size]

  build
  validate
end

Instance Attribute Details

#componentObject (readonly)

Returns the value of attribute component.



7
8
9
# File 'lib/loco_motion/component_config.rb', line 7

def component
  @component
end

#modifiersObject (readonly)

Returns the value of attribute modifiers.



7
8
9
# File 'lib/loco_motion/component_config.rb', line 7

def modifiers
  @modifiers
end

#optionsObject (readonly)

Returns the value of attribute options.



7
8
9
# File 'lib/loco_motion/component_config.rb', line 7

def options
  @options
end

#partsObject (readonly)

Returns the value of attribute parts.



7
8
9
# File 'lib/loco_motion/component_config.rb', line 7

def parts
  @parts
end

#sizeObject (readonly)

Returns the value of attribute size.



7
8
9
# File 'lib/loco_motion/component_config.rb', line 7

def size
  @size
end

Instance Method Details

#add_aria(part_name, aria) ⇒ Object

Adds default ‘aria-*` attributes to the requested component part. This is a convenience wrapper around #add_html that nests the given hash under the `aria:` key, so `add_aria(:component, label: “Save”)` renders `aria-label=“Save”`.



123
124
125
# File 'lib/loco_motion/component_config.rb', line 123

def add_aria(part_name, aria)
  add_html(part_name, { aria: aria }) if aria
end

#add_css(part_name, css) ⇒ Object

Adds default CSS to the requested component part.



106
107
108
# File 'lib/loco_motion/component_config.rb', line 106

def add_css(part_name, css)
  @parts[part_name][:default_css] << css if css
end

#add_data(part_name, data) ⇒ Object

Adds default ‘data-*` attributes to the requested component part. This is a convenience wrapper around #add_html that nests the given hash under the `data:` key, so `add_data(:component, foo: “bar”)` renders `data-foo=“bar”`.



133
134
135
# File 'lib/loco_motion/component_config.rb', line 133

def add_data(part_name, data)
  add_html(part_name, { data: data }) if data
end

#add_html(part_name, html) ⇒ Object

Adds default HTML to the requested component part.



113
114
115
# File 'lib/loco_motion/component_config.rb', line 113

def add_html(part_name, html)
  @parts[part_name][:default_html] = @parts[part_name][:default_html].deep_merge(html) if html
end

#add_stimulus_controller(part_name, controller_name) ⇒ Object

Add a default Stimulus (Javascript) controller to the requested component part.



140
141
142
143
144
# File 'lib/loco_motion/component_config.rb', line 140

def add_stimulus_controller(part_name, controller_name)
  @parts[part_name] ||= {}
  @parts[part_name][:default_stimulus_controllers] ||= []
  @parts[part_name][:default_stimulus_controllers] << controller_name
end

#buildObject



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/loco_motion/component_config.rb', line 21

def build
  # Allow users to pass css/html for a specific part (i.e. modal_dialog)
  @component.component_parts.each do |part, defaults|
    @parts[part] = {
      default_css: [],
      default_html: {},
      default_tag_name: defaults[:tag_name] || :div,
      default_stimulus_controllers: [],

      user_css: @options["#{part}_css".to_sym] || [],
      user_html: @options["#{part}_html".to_sym] || {},
      user_tag_name: @options["#{part}_tag_name".to_sym],
      user_stimulus_controllers: @options["#{part}_controllers".to_sym] || []
    }

    # Allow users to pass `{part}_aria` / `{part}_data` as a shorthand for
    # nesting `aria:` / `data:` hashes inside `{part}_html`.
    part_aria = @options["#{part}_aria".to_sym]
    part_data = @options["#{part}_data".to_sym]

    @parts[part][:user_html] = @parts[part][:user_html].deep_merge(aria: part_aria) if part_aria
    @parts[part][:user_html] = @parts[part][:user_html].deep_merge(data: part_data) if part_data
  end

  # Allow useres to pass some shortened attributes for the component part
  merge_user_options!(**@options)
end

#get_part(part_name) ⇒ Object

Returns the part for the reqeust part name or an empty hash if none was found.



92
93
94
# File 'lib/loco_motion/component_config.rb', line 92

def get_part(part_name)
  @parts[part_name] || {}
end

#inspectObject

For now, just return the Hash version for inspect.



194
195
196
# File 'lib/loco_motion/component_config.rb', line 194

def inspect
  build_inspect_string("options", "parts", "modifiers", "size", suffix: ">")
end

#merge_user_options!(**kws) ⇒ Object

Add specific component user options if they pass shortened attributes.



52
53
54
55
56
57
58
59
60
# File 'lib/loco_motion/component_config.rb', line 52

def merge_user_options!(**kws)
  @parts[:component][:user_tag_name] = kws[:tag_name] if kws[:tag_name]
  @parts[:component][:user_css].push(kws[:css]) if kws[:css]
  @parts[:component][:user_html].deep_merge!(kws[:html]) if kws[:html]
  @parts[:component][:user_html].deep_merge!(aria: kws[:aria]) if kws[:aria]
  @parts[:component][:user_html].deep_merge!(data: kws[:data]) if kws[:data]
  @parts[:component][:user_stimulus_controllers].push(kws[:controller]) if kws[:controller]
  @parts[:component][:user_stimulus_controllers].push(kws[:controllers]) if kws[:controllers]
end

#set_tag_name(part_name, tag_name) ⇒ Object

Sets the default tag name for the requested component part.



99
100
101
# File 'lib/loco_motion/component_config.rb', line 99

def set_tag_name(part_name, tag_name)
  @parts[part_name][:default_tag_name] = tag_name if tag_name
end

#smart_merge!(**kws) ⇒ Object

Merge additional options into the defaults config by combining the new options with the existing options, rather than overwriting (where possible).

HTML will be deep merged, CSS will be appended, and tag_name will be overwritten.



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/loco_motion/component_config.rb', line 69

def smart_merge!(**kws)
  @component.component_parts.each_key do |part|
    set_tag_name(part, kws["#{part}_tag_name".to_sym])
    add_css(part, kws["#{part}_css".to_sym])
    add_html(part, kws["#{part}_html".to_sym])
    add_aria(part, kws["#{part}_aria".to_sym])
    add_data(part, kws["#{part}_data".to_sym])

    controllers = kws["#{part}_controllers".to_sym] || []

    controllers.each do |controller_name|
      add_stimulus_controller(part, controller_name)
    end
  end

  # Make sure to merge any user-provided options as well
  merge_user_options!(**kws)
end

#to_hObject

Render a Hash version of the config.



182
183
184
185
186
187
188
189
# File 'lib/loco_motion/component_config.rb', line 182

def to_h
  {
    options: @options,
    parts: @parts,
    modifiers: @modifiers,
    size: @size
  }
end

#valid_partsObject

Return a list of valid parts for the component.



175
176
177
# File 'lib/loco_motion/component_config.rb', line 175

def valid_parts
  @parts.keys
end

#validateObject

Validate the component config and throw errors if there are issues.



149
150
151
# File 'lib/loco_motion/component_config.rb', line 149

def validate
  validate_modifiers
end

#validate_modifiersObject

Validate that all of the modifiers are correct.



156
157
158
159
160
161
162
163
# File 'lib/loco_motion/component_config.rb', line 156

def validate_modifiers
  # Check to make sure they have passed a valid / defined modifier
  (@modifiers || []).each do |modifier|
    if modifier.present? && !@component.valid_modifiers.include?(modifier)
      raise LocoMotion::InvalidModifierError.new(modifier, @component)
    end
  end
end

#validate_part(part_name) ⇒ Object

Validates that the requested part is valid for the component.



168
169
170
# File 'lib/loco_motion/component_config.rb', line 168

def validate_part(part_name)
  raise LocoMotion::UnknownPartError.new(part_name, @component) unless valid_parts.include?(part_name)
end