module ViewComponent::Slotable

def define_slot(slot_name, collection:, callable:)

def define_slot(slot_name, collection:, callable:)
  slot = {collection: collection}
  return slot unless callable
  # If callable responds to `render_in`, we set it on the slot as a renderable
  if callable.respond_to?(:method_defined?) && callable.method_defined?(:render_in)
    slot[:renderable] = callable
  elsif callable.is_a?(String)
    # If callable is a string, we assume it's referencing an internal class
    slot[:renderable_class_name] = callable
  elsif callable.respond_to?(:call)
    # If slot doesn't respond to `render_in`, we assume it's a proc,
    # define a method, and save a reference to it to call when setting
    method_name = :"_call_#{slot_name}"
    define_method method_name, &callable
    slot[:renderable_function] = instance_method(method_name)
  else
    raise(InvalidSlotDefinitionError)
  end
  slot
end