class Primer::Forms::Dsl::Input

:nodoc:

def add_input_aria(key, value)

def add_input_aria(key, value)
  @input_arguments[:aria] ||= {}
  @input_arguments[:aria][key] = if space_delimited_aria_attribute?(key)
                                   aria_join(@input_arguments[:aria][key], *Array(value))
                                 else
                                   value
                                 end
end

def add_input_classes(*class_names)

def add_input_classes(*class_names)
  input_arguments[:class] = class_names(
    input_arguments[:class], *class_names
  )
end

def add_input_data(key, value)

def add_input_data(key, value)
  input_data[key] = value
end

def add_label_classes(*class_names)

def add_label_classes(*class_names)
  label_arguments[:class] = class_names(
    label_arguments[:class], *class_names
  )
end

def aria_join(*values)

def aria_join(*values)
  values = values.flat_map { |v| v.to_s.split }
  values.reject!(&:empty?)
  values.join(" ")
end

def autofocus!

def autofocus!
  input_arguments[:autofocus] = true
end

def caption?

def caption?
  caption.present?
end

def caption_id

def caption_id
  ids[:caption]
end

def caption_template?

def caption_template?
  return false unless form
  form.caption_template?(caption_template_name)
end

def caption_template_name

def caption_template_name
  return nil unless name
  @caption_template_name ||= if respond_to?(:value)
                               :"#{name}_#{value}"
                             else
                               name.to_sym
                             end
end

def disabled?

def disabled?
  !!input_arguments[:disabled]
end

def focusable?

def focusable?
  false
end

def full_width?

def full_width?
  @full_width
end

def hidden?

def hidden?
  !!input_arguments[:hidden]
end

def initialize(builder:, form:, **system_arguments)

def initialize(builder:, form:, **system_arguments)
  @builder = builder
  @form = form
  @input_arguments = system_arguments
  @label_arguments = @input_arguments.delete(:label_arguments) || {}
  @label_arguments[:class] = class_names(
    @label_arguments[:class],
    @input_arguments.fetch(:visually_hide_label, false) ? "sr-only" : nil
  )
  @input_arguments.delete(:visually_hide_label)
  @input_arguments.delete(:class) if @input_arguments[:class].blank?
  @label_arguments.delete(:class) if @label_arguments[:class].blank?
  @caption = @input_arguments.delete(:caption)
  @validation_message = @input_arguments.delete(:validation_message)
  @invalid = @input_arguments.delete(:invalid)
  @full_width = @input_arguments.delete(:full_width)
  @size = @input_arguments.delete(:size)
  # If scope_name_to_model is false, the name of the input for eg. `my_field`
  # will be `my_field` instead of the Rails default of `model[my_field]`.
  #
  # We achieve this by passing the `name` option to Rails form builder
  # methods. These methods will use the passed name if provided instead
  # of generating a scoped one.
  #
  unless @input_arguments.delete(:scope_name_to_model) { true }
    @input_arguments[:name] = name
  end
  # rubocop:enable Style/IfUnlessModifier
  # If scope_id_to_model is false, the name of the input for eg. `my_field`
  # will be `my_field` instead of the Rails default of `model_my_field`.
  #
  # We achieve this by passing the `id` option to Rails form builder
  # methods. These methods will use the passed id if provided instead
  # of generating a scoped one. The id is the name of the field unless
  # explicitly provided in system_arguments.
  #
  # rubocop:disable Style/IfUnlessModifier
  unless @input_arguments.delete(:scope_id_to_model) { true }
    @input_arguments[:id] = @input_arguments.delete(:id) { name }
  end
  # rubocop:enable Style/IfUnlessModifier
  # Whether or not to wrap the component in a FormControl, which renders a
  # label above and validation message beneath the input.
  @form_control = @input_arguments.delete(:form_control) { true }
  @input_arguments[:invalid] = "true" if invalid?
  @base_id = SecureRandom.uuid
  @ids = {}.tap do |id_map|
    id_map[:validation] = "validation-#{@base_id}"
    id_map[:caption] = "caption-#{@base_id}" if caption? || caption_template?
  end
  add_input_aria(:required, true) if required?
  add_input_aria(:invalid, true) if invalid?
  add_input_aria(:describedby, ids.values) if ids.any?
  # avoid browser-native validation, which doesn't match Primer's style
  input_arguments.delete(:required)
end

def input?

def input?
  true
end

def input_data

def input_data
  @input_arguments[:data] ||= {}
end

def invalid?

def invalid?
  !valid?
end

def label

def label
  raise_for_abstract_method!(__method__)
end

def merge_input_arguments!(arguments)

def merge_input_arguments!(arguments)
  arguments.each do |k, v|
    case k
    when :class, :classes, "class", "classes"
      add_input_classes(v)
    when :aria, "aria"
      v.each do |aria_k, aria_v|
        add_input_aria(aria_k, aria_v)
      end
    when :data, "data"
      v.each do |data_k, data_v|
        add_input_data(data_k, data_v)
      end
    else
      @input_arguments[k] = v
    end
  end
end

def name

:nocov:
def name
  raise_for_abstract_method!(__method__)
end

def raise_for_abstract_method!(method_name)

:nocov:
def raise_for_abstract_method!(method_name)
  raise NotImplementedError, "subclasses must implement ##{method_name}."
end

def remove_input_data(key)

:nocov:
def remove_input_data(key)
  input_data.delete(key)
end

def render_caption_template

def render_caption_template
  form.render_caption_template(caption_template_name)
end

def required?

def required?
  input_arguments[:required] ||
    input_arguments[:aria_required] ||
    input_arguments[:"aria-required"] ||
    input_arguments.dig(:aria, :required)
end

def size

def size
  @size ||= SIZE_MAPPINGS.include?(@size) ? @size : DEFAULT_SIZE
end

def space_delimited_aria_attribute?(attrib)

def space_delimited_aria_attribute?(attrib)
  SPACE_DELIMITED_ARIA_ATTRIBUTES.include?(attrib)
end

def to_component

def to_component
  raise_for_abstract_method!(__method__)
end

def type

def type
  raise_for_abstract_method!(__method__)
end

def valid?

def valid?
  validation_messages.empty? && !@invalid
end

def validation_arguments

def validation_arguments
  {
    class: "FormControl-inlineValidation",
    id: validation_id,
    hidden: valid? || validation_messages.empty?
  }
end

def validation_error_icon_target

def validation_error_icon_target
  ""
end

def validation_id

def validation_id
  ids[:validation]
end

def validation_message_arguments

def validation_message_arguments
  {}
end

def validation_messages

def validation_messages
  @validation_messages ||=
    if validation_message
      [validation_message]
    elsif builder.object.respond_to?(:errors)
      name ? builder.object.errors.full_messages_for(name) : []
    else
      []
    end
end

def validation_success_icon_target

def validation_success_icon_target
  ""
end