Class: HakumiComponents::BaseComponent
- Inherits:
-
ViewComponent::Base
- Object
- ViewComponent::Base
- HakumiComponents::BaseComponent
show all
- Extended by:
- T::Sig
- Defined in:
- app/components/hakumi_components/base_component.rb
Direct Known Subclasses
AdminPanel::Component, Affix::Component, Alert::Component, Anchor::Component, Anchor::Link::Component, Autocomplete::Component, Avatar::Component, HakumiComponents::Badge::Component, HakumiComponents::Breadcrumb::Component, HakumiComponents::Breadcrumb::Item::Component, HakumiComponents::Button::Component, Calendar::Component, Card::Component, Card::Grid::Component, Card::Meta::Component, Carousel::Component, Cascader::Component, Checkbox::Component, Checkbox::Group::Component, Collapse::Component, Collapse::Panel::Component, ColorPicker::Component, Container::Component, DatePicker::Component, DatePicker::RangePicker, Descriptions::Component, Descriptions::Item::Component, Divider::Component, Drawer::Component, Dropdown::Component, Dropdown::Divider::Component, Dropdown::Item::Component, Empty::Component, Flex::Component, FloatButton::BackTop::Component, FloatButton::Component, FloatButton::Group::Component, FloatButton::GroupCluster::Component, Form::Item::Component, Grid::Col::Component, Grid::Row::Component, Icon::Component, Image::Component, Image::PreviewGroup::Component, Input::Component, Input::TextArea::Component, InputNumber::Component, Layout::Component, Layout::Content::Component, Layout::Footer::Component, Layout::Header::Component, Layout::Sider::Component, Mentions::Component, Menu::Component, Menu::Divider::Component, Menu::Group::Component, Menu::Item::Component, Menu::SubMenu::Component, Message::Component, Modal::Component, Modal::Confirm::Component, Modal::StatusComponent, Notification::Component, Pagination::Component, Popconfirm::Component, Popover::Component, Progress::Component, QrCode::Component, Radio::Component, Radio::Group::Component, Rate::Component, Result::Component, Segmented::Component, Select::Component, Skeleton::Avatar::Component, Skeleton::Button::Component, Skeleton::Component, Skeleton::Image::Component, Skeleton::Input::Component, Skeleton::Node::Component, Slider::Component, Space::Compact::Component, Space::Component, Spin::Component, Splitter::Component, Splitter::Panel::Component, Statistic::Component, Steps::Component, Steps::Item::Component, Switch::Component, Table::Column::Component, Table::ColumnGroup::Component, Table::Component, Tabs::Component, Tabs::Item::Component, Tag::Component, Tag::Group::Component, TimePicker::Component, Timeline::Component, Timeline::Item::Component, Tooltip::Component, Tour::Component, Transfer::Component, Tree::Component, TreeSelect::Component, Typography::BaseComponent, Upload::Component
Constant Summary
collapse
- SizeValue =
T.type_alias { T.any(Types::HtmlKey, Integer) }
- DimensionInput =
T.type_alias { T.nilable(T.any(Numeric, String)) }
- I18nOptionValue =
T.type_alias { Types::ValidationComparable }
- DateLikeValue =
T.type_alias { T.any(Date, Time, DateTime, ActiveSupport::TimeWithZone) }
- DateInput =
T.type_alias { T.nilable(T.any(DateLikeValue, Types::HtmlKey)) }
- SymbolInput =
T.type_alias { T.nilable(Types::HtmlKey) }
- PresenceArray =
T.type_alias { T::Array[HakumiComponents::Types::FormFieldScalar] }
- ControllerOptions =
T.type_alias { T.any(ActionController::Parameters, Types::HtmlAttributes) }
- PresenceScalar =
T.type_alias { T.any(Types::ValidationPrimitive, DateLikeValue) }
- HtmlPayloadInput =
T.type_alias { T.any(ActionController::Parameters, Types::DataAttributes, Types::HtmlClassList) }
- PresenceValue =
T.type_alias do
T.nilable(T.any(
Types::Renderable,
PresenceScalar,
PresenceArray
))
end
- RawHtmlInput =
T.type_alias do
T.nilable(T.any(
Types::HtmlPrimitive,
HtmlPayloadInput
))
end
- SIZES =
T.let(%i[small default large].freeze, T::Array[Symbol])
Class Method Summary
collapse
Instance Method Summary
collapse
-
#append_data_token(existing, token) ⇒ Object
-
#build_inline_style(styles) ⇒ Object
-
#cast_boolean(value) ⇒ Object
-
#class_names(base, modifiers = {}, extras = []) ⇒ Object
-
#component_classes(base, modifiers = {}, attributes = {}) ⇒ Object
-
#data_attributes_from(value) ⇒ Object
-
#dimension_to_css(value) ⇒ Object
-
#ensure_dom_id!(attrs) ⇒ Object
-
#generate_id(prefix, length: 4) ⇒ Object
-
#html_classes(attributes) ⇒ Object
-
#html_style(attributes) ⇒ Object
-
#i18n_scope ⇒ Object
-
#merge_attributes(defaults = {}, overrides = {}) ⇒ Object
-
#render_value(value) ⇒ Object
-
#size_to_pixels(size, mapping = {}) ⇒ Object
-
#stimulus_attrs(controller, values = {}) ⇒ Object
-
#t_default(key, default:, **options) ⇒ Object
-
#translate_with_default(key, default:, **options) ⇒ Object
-
#validate_inclusion!(prop, allowed) ⇒ Object
-
#validate_required!(*props) ⇒ Object
-
#value_present?(value) ⇒ Boolean
Class Method Details
.boolean_html_param(value) ⇒ Object
210
211
212
213
214
215
|
# File 'app/components/hakumi_components/base_component.rb', line 210
def self.boolean_html_param(value)
scalar = html_primitive_param(value)
return nil if scalar.nil?
cast_boolean(scalar)
end
|
.cast_boolean(value) ⇒ Object
184
185
186
|
# File 'app/components/hakumi_components/base_component.rb', line 184
def self.cast_boolean(value)
BOOLEAN_CASTER.cast(value)
end
|
.float_html_param(value) ⇒ Object
233
234
235
236
237
238
|
# File 'app/components/hakumi_components/base_component.rb', line 233
def self.float_html_param(value)
return value.to_f if value.is_a?(String)
return value.to_f if value.is_a?(Numeric)
nil
end
|
.html_param(params, key) ⇒ Object
205
206
207
|
# File 'app/components/hakumi_components/base_component.rb', line 205
def self.html_param(params, key)
coerce_html_attribute_value(params[key])
end
|
.html_primitive_param(value) ⇒ Object
189
190
191
192
193
194
195
196
197
|
# File 'app/components/hakumi_components/base_component.rb', line 189
def self.html_primitive_param(value)
return value if value.is_a?(String)
return value if value.is_a?(Symbol)
return value if value.is_a?(TrueClass)
return value if value.is_a?(FalseClass)
return value if value.is_a?(Numeric)
nil
end
|
.integer_html_param(value) ⇒ Object
225
226
227
228
229
230
|
# File 'app/components/hakumi_components/base_component.rb', line 225
def self.integer_html_param(value)
return value if value.is_a?(Integer)
return value.to_i if value.is_a?(String)
nil
end
|
.string_html_param(value) ⇒ Object
241
242
243
244
245
246
247
|
# File 'app/components/hakumi_components/base_component.rb', line 241
def self.string_html_param(value)
return nil if value.nil?
return value if value.is_a?(String)
return value.to_s if value.is_a?(Symbol) || value.is_a?(Numeric)
nil
end
|
.string_or_symbol_array_html_param(value) ⇒ Object
250
251
252
253
254
255
256
257
258
259
260
|
# File 'app/components/hakumi_components/base_component.rb', line 250
def self.string_or_symbol_array_html_param(value)
return nil unless value.is_a?(Array)
entries = T.let([], Types::StringOrSymbolArray)
value.each do |entry|
next if entry.nil?
entries << entry
end
entries
end
|
.symbol_html_param(value) ⇒ Object
218
219
220
221
222
|
# File 'app/components/hakumi_components/base_component.rb', line 218
def self.symbol_html_param(value)
return value.to_sym if value.is_a?(String) || value.is_a?(Symbol)
nil
end
|
Instance Method Details
#append_data_token(existing, token) ⇒ Object
174
175
176
177
178
|
# File 'app/components/hakumi_components/base_component.rb', line 174
def append_data_token(existing, token)
return token unless existing.is_a?(String) && existing.present?
[ existing, token ].join(" ")
end
|
#build_inline_style(styles) ⇒ Object
316
317
318
319
320
321
322
323
324
325
326
327
|
# File 'app/components/hakumi_components/base_component.rb', line 316
def build_inline_style(styles)
return nil if styles.respond_to?(:blank?) && styles.blank?
style_array = if styles.is_a?(Hash)
styles.compact.map { |key, value| "#{key}: #{value}" }
else
Array(styles).compact
end
return nil if style_array.empty?
style_array.join("; ")
end
|
#cast_boolean(value) ⇒ Object
311
312
313
|
# File 'app/components/hakumi_components/base_component.rb', line 311
def cast_boolean(value)
self.class.cast_boolean(value)
end
|
#class_names(base, modifiers = {}, extras = []) ⇒ Object
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
# File 'app/components/hakumi_components/base_component.rb', line 35
def class_names(base, modifiers = {}, = [])
classes = [ "hakumi-#{base}" ]
modifiers.each do |key, value|
next if value.nil? || value == false
if value == true
classes << "hakumi-#{base}-#{key}"
else
classes << "hakumi-#{base}-#{key}-#{value}"
end
end
classes.concat(Array().compact)
classes.join(" ")
end
|
#component_classes(base, modifiers = {}, attributes = {}) ⇒ Object
338
339
340
|
# File 'app/components/hakumi_components/base_component.rb', line 338
def component_classes(base, modifiers = {}, attributes = {})
class_names(base, modifiers, html_classes(attributes))
end
|
#data_attributes_from(value) ⇒ Object
163
164
165
166
167
168
169
170
171
|
# File 'app/components/hakumi_components/base_component.rb', line 163
def data_attributes_from(value)
attrs = T.let({}, Types::DataAttributes)
return attrs unless value.is_a?(Hash)
value.each do |key, entry|
attrs[key] = entry
end
attrs
end
|
#dimension_to_css(value) ⇒ Object
141
142
143
144
145
146
147
148
|
# File 'app/components/hakumi_components/base_component.rb', line 141
def dimension_to_css(value)
return nil if value.nil?
return value if value.is_a?(String) && value.strip.present?
return "#{value}px" if value.is_a?(Numeric)
string = value.to_s.strip
string.empty? ? nil : string
end
|
#ensure_dom_id!(attrs) ⇒ Object
108
109
110
111
112
113
114
115
116
117
|
# File 'app/components/hakumi_components/base_component.rb', line 108
def ensure_dom_id!(attrs)
data = attrs[:data]
controllers = data.is_a?(Hash) ? data[:controller] : nil
return unless controllers.is_a?(String) && !controllers.empty?
id = attrs[:id]
return if id.is_a?(String) && !id.empty?
attrs[:id] = generate_id("hakumi-component")
end
|
#generate_id(prefix, length: 4) ⇒ Object
120
121
122
|
# File 'app/components/hakumi_components/base_component.rb', line 120
def generate_id(prefix, length: 4)
"#{prefix}_#{SecureRandom.hex(length)}"
end
|
#html_classes(attributes) ⇒ Object
330
331
332
333
334
335
|
# File 'app/components/hakumi_components/base_component.rb', line 330
def html_classes(attributes)
value = attributes[:class]
return value if value.is_a?(String) || value.is_a?(Array)
nil
end
|
#html_style(attributes) ⇒ Object
343
344
345
346
|
# File 'app/components/hakumi_components/base_component.rb', line 343
def html_style(attributes)
value = attributes[:style]
value.is_a?(String) ? value : nil
end
|
#i18n_scope ⇒ Object
359
360
361
362
363
364
365
366
367
368
369
370
|
# File 'app/components/hakumi_components/base_component.rb', line 359
def i18n_scope
@i18n_scope = T.let(@i18n_scope, T.nilable(String)) unless instance_variable_defined?(:@i18n_scope)
@i18n_scope ||= begin
class_name = self.class.name
raise "#{self.class} must have a name for i18n scope" if class_name.nil?
class_name
.delete_suffix("::Component")
.underscore
.tr("/", ".")
end
end
|
#merge_attributes(defaults = {}, overrides = {}) ⇒ Object
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
# File 'app/components/hakumi_components/base_component.rb', line 53
def merge_attributes(defaults = {}, overrides = {})
merged = T.let(defaults.deep_dup, Types::HtmlAttributes)
if defaults[:class] && overrides[:class]
merged[:class] = [ defaults[:class], overrides[:class] ].join(" ")
elsif overrides[:class]
merged[:class] = overrides[:class]
end
if defaults[:style] && overrides[:style]
merged[:style] = [ defaults[:style].to_s.chomp(";"), overrides[:style] ].join("; ")
elsif overrides[:style]
merged[:style] = overrides[:style]
end
merged_data = merge_attribute_hash(defaults[:data], overrides[:data])
merged[:data] = merged_data if merged_data
merged_aria = merge_attribute_hash(defaults[:aria], overrides[:aria])
merged[:aria] = merged_aria if merged_aria
merged.merge!(overrides.except(:aria, :class, :data, :style))
ensure_dom_id!(merged)
merged
end
|
#render_value(value) ⇒ Object
125
126
127
128
129
130
131
132
|
# File 'app/components/hakumi_components/base_component.rb', line 125
def render_value(value)
return nil unless value.present?
return value if value.is_a?(String) || value.is_a?(ActiveSupport::SafeBuffer)
return value.to_s if value.is_a?(ViewComponent::Slot)
return render(value) if value.respond_to?(:render_in)
nil
end
|
#size_to_pixels(size, mapping = {}) ⇒ Object
135
136
137
138
|
# File 'app/components/hakumi_components/base_component.rb', line 135
def size_to_pixels(size, mapping = {})
return size if size.is_a?(Integer)
mapping[size.to_sym] || size
end
|
#stimulus_attrs(controller, values = {}) ⇒ Object
151
152
153
154
155
156
157
158
159
160
|
# File 'app/components/hakumi_components/base_component.rb', line 151
def stimulus_attrs(controller, values = {})
data = T.let({ "controller" => controller }, Types::StimulusData)
values.each do |key, value|
next if value.nil?
serialized = value.is_a?(Array) || value.is_a?(Hash) ? value.to_json : value
data["#{controller}-#{key.to_s.underscore.dasherize}-value"] = serialized
end
data
end
|
#t_default(key, default:, **options) ⇒ Object
354
355
356
|
# File 'app/components/hakumi_components/base_component.rb', line 354
def t_default(key, default:, **options)
I18n.t(key, scope: i18n_scope, default: default, **options)
end
|
#translate_with_default(key, default:, **options) ⇒ Object
349
350
351
|
# File 'app/components/hakumi_components/base_component.rb', line 349
def translate_with_default(key, default:, **options)
I18n.t(key, scope: i18n_scope, default: default, **options)
end
|
#validate_inclusion!(prop, allowed) ⇒ Object
99
100
101
102
103
104
105
|
# File 'app/components/hakumi_components/base_component.rb', line 99
def validate_inclusion!(prop, allowed)
value = instance_variable_get("@#{prop}")
return if value.nil?
return if allowed.include?(value)
raise ArgumentError, "#{prop} must be one of #{allowed.inspect}, got #{value.inspect}"
end
|
#validate_required!(*props) ⇒ Object
91
92
93
94
95
96
|
# File 'app/components/hakumi_components/base_component.rb', line 91
def validate_required!(*props)
props.each do |prop|
value = instance_variable_get("@#{prop}")
raise ArgumentError, "#{prop} is required" unless value_present?(value)
end
end
|
#value_present?(value) ⇒ Boolean
82
83
84
85
86
87
88
|
# File 'app/components/hakumi_components/base_component.rb', line 82
def value_present?(value)
return false if value.nil? || value == false
return !value.empty? if value.is_a?(String)
return !value.empty? if value.is_a?(Array)
true
end
|