lib/govuk_design_system_formbuilder/elements/password.rb
module GOVUKDesignSystemFormBuilder
module Elements
class Password < Base
using PrefixableArray
include Traits::Error
include Traits::Hint
include Traits::Label
include Traits::HTMLAttributes
include Traits::HTMLClasses
I18nAttr = Struct.new(:key, :text, :default)
def initialize(builder, object_name, attribute_name, label:, caption:, hint:, form_group:, show_password_text:, hide_password_text:, show_password_aria_label_text:, hide_password_aria_label_text:, password_hidden_announcement_text:, password_shown_announcement_text:, **kwargs, &block)
super(builder, object_name, attribute_name, &block)
@label = label
@caption = caption
@hint = hint
@form_group = form_group
@html_attributes = kwargs
@show_password_text = show_password_text
@hide_password_text = hide_password_text
@show_password_aria_label_text = show_password_aria_label_text
@hide_password_aria_label_text = hide_password_aria_label_text
@password_shown_announcement_text = password_shown_announcement_text
@password_hidden_announcement_text = password_hidden_announcement_text
end
def html
Containers::FormGroup.new(*bound, **form_group_options).html do
safe_join([label_element, hint_element, error_element, password_input_and_button])
end
end
private
def password_input_and_button
tag.div(class: wrapper_classes) do
safe_join([password_input, button])
end
end
def options
{
id: field_id(link_errors: true),
class: classes,
spellcheck: "false",
autocomplete: "current-password",
autocapitalize: "none",
aria: { describedby: combine_references(hint_id, error_id) }
}
end
def form_group_options
{
**@form_group,
**i18n_data,
class: %(#{brand}-password-input),
data: { module: %(#{brand}-password-input) },
}
end
def password_input
@builder.password_field(@attribute_name, attributes(@html_attributes))
end
def classes
build_classes('input', 'password-input__input', 'js-password-input-input', %(password-input--error) => has_errors?).prefix(brand)
end
def wrapper_classes
%w(input__wrapper password-input__wrapper).prefix(brand)
end
def button
tag.button(@show_password_text, **button_options)
end
def button_options
{
data: { module: %(#{brand}-button) },
aria: { label: "Show password", controls: field_id(link_errors: true) },
type: 'button',
hidden: true,
class: %w(button button--secondary password-input__toggle js-password-input-toggle).prefix(brand)
}
end
def i18n_data
[
I18nAttr.new("data-i18n.show-password", @show_password_text, config.default_show_password_text),
I18nAttr.new("data-i18n.hide-password", @hide_password_text, config.default_hide_password_text),
I18nAttr.new("data-i18n.show-password-aria-label", @show_password_aria_label_text, config.default_show_password_aria_label_text),
I18nAttr.new("data-i18n.hide-password-aria-label", @hide_password_aria_label_text, config.default_hide_password_aria_label_text),
I18nAttr.new("data-i18n.password-shown-announcement", @password_shown_announcement_text, config.default_password_shown_announcement_text),
I18nAttr.new("data-i18n.password-hidden-announcement", @password_hidden_announcement_text, config.default_password_hidden_announcement_text),
].each_with_object({}) do |attr, h|
h[attr.key] = attr.text unless attr.text == attr.default
end
end
end
end
end