class __attribute__()

in ComponentKit/Components/ButtonComponentBuilder.h [28:697]


class __attribute__((__may_alias__)) ButtonComponentBuilder
    : public ComponentBuilderBaseSizeOnly<ButtonComponentBuilder, PropsBitmap> {
 public:
  ButtonComponentBuilder() = default;

  ~ButtonComponentBuilder() = default;

  /**
   An action that will be triggered when the button is tapped.
   */
  auto &action(CKAction<UIEvent *> a)
  {
    constexpr auto actionIsNotSet = !PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::action);
    static_assert(actionIsNotSet, "Property 'action' is already set.");
    _action = std::move(a);
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::action> &>(*this);
  }

  /**
   The title of the button for \c UIControlStateNormal .

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &title(NS_RELEASES_ARGUMENT NSString *t)
  {
    constexpr auto titleOverridesExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!titleOverridesExistingOptions, "Setting 'title' overrides existing options");
    _titles[UIControlStateNormal] = t;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   The title of the button for a given control state.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &title(NS_RELEASES_ARGUMENT NSString *t, UIControlState s)
  {
    constexpr auto titleOverridesExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!titleOverridesExistingOptions, "Setting 'title' overrides existing options");
    _titles[s] = t;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   The title of the button for different states.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &titles(const CKButtonComponentStateMap<NSString *>::Map &m)
  {
    constexpr auto titlesOverrideExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!titlesOverrideExistingOptions, "Setting 'titles' overrides existing options");
    _titles = m;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   The title color of the button for \c UIControlStateNormal .

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &titleColor(NS_RELEASES_ARGUMENT UIColor *c)
  {
    constexpr auto titleColorOverridesExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!titleColorOverridesExistingOptions, "Setting 'titleColor' overrides existing options");
    _titleColors[UIControlStateNormal] = c;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   The title color of the button for a given control state.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &titleColor(NS_RELEASES_ARGUMENT UIColor *c, UIControlState s)
  {
    constexpr auto titleColorOverridesExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!titleColorOverridesExistingOptions, "Setting 'titleColor' overrides existing options");
    _titleColors[s] = c;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   Title colors of the button for given states.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &titleColors(const CKButtonComponentStateMap<UIColor *>::Map &m)
  {
    constexpr auto titleColorsOverrideExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!titleColorsOverrideExistingOptions, "Setting 'titleColors' overrides existing options");
    _titleColors = m;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   The image of the button for \c UIControlStateNormal .

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &image(NS_RELEASES_ARGUMENT UIImage *i)
  {
    constexpr auto imageOverridesExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!imageOverridesExistingOptions, "Setting 'image' overrides existing options");
    _images[UIControlStateNormal] = i;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   The image of the button for a given control state.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &image(NS_RELEASES_ARGUMENT UIImage *i, UIControlState s)
  {
    constexpr auto imageOverridesExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!imageOverridesExistingOptions, "Setting 'image' overrides existing options");
    _images[s] = i;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   The images of the button for different states.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &images(const CKButtonComponentStateMap<UIImage *>::Map &m)
  {
    constexpr auto imagesOverrideExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!imagesOverrideExistingOptions, "Setting 'images' overrides existing options");
    _images = m;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   The background image of the button for \c UIControlStateNormal .

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &backgroundImage(NS_RELEASES_ARGUMENT UIImage *i)
  {
    constexpr auto backgroundImageOverridesExistingOptions =
      PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!backgroundImageOverridesExistingOptions, "Setting 'backgroundImage' overrides existing options");
    _backgroundImages[UIControlStateNormal] = i;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   The background image of the button for a given control state.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &backgroundImage(NS_RELEASES_ARGUMENT UIImage *i, UIControlState s)
  {
    constexpr auto backgroundImageOverridesExistingOptions =
      PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!backgroundImageOverridesExistingOptions, "Setting 'backgroundImage' overrides existing options");
    _backgroundImages[s] = i;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   The background images of the button for different states.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &backgroundImages(const CKButtonComponentStateMap<UIImage *>::Map &m)
  {
    constexpr auto backgroundImagesOverrideExistingOptions =
      PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!backgroundImagesOverrideExistingOptions, "Setting 'backgroundImages' overrides existing options");
    _backgroundImages = m;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   The title font the button.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &titleFont(NS_RELEASES_ARGUMENT UIFont *f)
  {
    constexpr auto titleFontOverridesExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!titleFontOverridesExistingOptions, "Setting 'titleFont' overrides existing options");
    _options.titleFont = f;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   The title alignment

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &titleAlignment(NSTextAlignment a)
  {
    constexpr auto titleAlignmentOverridesExistingOptions =
      PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!titleAlignmentOverridesExistingOptions, "Setting 'titleAlignment' overrides existing options");
    _options.titleAlignment = a;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   Whether the button is selected. Default is \c NO .

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &selected(BOOL s)
  {
    constexpr auto selectedOverridesExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!selectedOverridesExistingOptions, "Setting 'selected' overrides existing options");
    _options.selected = s;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   Whether the button is enabled. Default is \c YES .

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &enabled(BOOL e)
  {
    constexpr auto enabledOverridesExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!enabledOverridesExistingOptions, "Setting 'enabled' overrides existing options");
    _options.enabled = e;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   The maximum number of lines to use for rendering text. Default is 1 .

   @warning Setting \c numberOfLines to 0 or less can create unpredictible behaviour between displaying the label and
   the buttons size. \c UIButton 's \c titleLabel property isn't bound to the bounds of it's housing \c UIButton, which
   can lead to the text displaying incorrectly.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &numberOfLines(NSInteger n)
  {
    constexpr auto numberOfLinesOverridesExistingOptions =
      PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!numberOfLinesOverridesExistingOptions, "Setting 'numberOfLines' overrides existing options");
    _options.numberOfLines = n;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   The line break mode for the title label. Default is \c NSLineBreakByTruncatingMiddle .

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &lineBreakMode(NSLineBreakMode m)
  {
    constexpr auto lineBreakModeOverridesExistingOptions =
      PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!lineBreakModeOverridesExistingOptions, "Setting 'lineBreakMode' overrides existing options");
    _options.lineBreakMode = m;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   The inset or outset margins for the rectangle around the button's content. Default is \c UIEdgeInsetsZero .

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &contentEdgeInsets(UIEdgeInsets i)
  {
    constexpr auto contentEdgeInsetsOverridesExistingOptions =
      PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!contentEdgeInsetsOverridesExistingOptions, "Setting 'contentEdgeInsets' overrides existing options");
    _options.contentEdgeInsets = i;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   The inset or outset margins for the rectangle around the button's title text. Default is \c UIEdgeInsetsZero .

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &titleEdgeInsets(UIEdgeInsets i)
  {
    constexpr auto titleEdgeInsetsOverridesExistingOptions =
      PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!titleEdgeInsetsOverridesExistingOptions, "Setting 'titleEdgeInsets' overrides existing options");
    _options.titleEdgeInsets = i;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   The inset or outset margins for the rectangle around the button's image. Default is \c UIEdgeInsetsZero .

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &imageEdgeInsets(UIEdgeInsets i)
  {
    constexpr auto imageEdgeInsetsOverridesExistingOptions =
      PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!imageEdgeInsetsOverridesExistingOptions, "Setting 'imageEdgeInsets' overrides existing options");
    _options.imageEdgeInsets = i;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   The outset for tap target expansion Default is \c UIEdgeInsetsZero .

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &tapTargetExpansion(UIEdgeInsets i)
  {
    constexpr auto tapTargetExpansionOverridesExistingOptions =
      PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!tapTargetExpansionOverridesExistingOptions,
                  "Setting 'tapTargetExpansion' overrides existing options");
    _options.tapTargetExpansion = i;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   Specifies the options for the component.

   @note Calling this method on a builder that already has any of the options set will trigger a compilation error.
   */
  auto &options(const CKButtonComponentOptions &opts)
  {
    constexpr auto optionsOverrideExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::anyOption);
    static_assert(!optionsOverrideExistingOptions, "Setting options overrides existing options");
    _options = opts;
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::options> &>(*this);
  }

  /**
   Specifies a background color that a view for the component should have.

   @param c A background color to set

   @note Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &backgroundColor(NS_RELEASES_ARGUMENT UIColor *c)
  {
    constexpr auto backgroundColorOverridesExistingOptions =
      PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!backgroundColorOverridesExistingOptions, "Setting 'backgroundColor' overrides existing options");
    _options.attributes.insert({ @selector(setBackgroundColor:), c });
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   Specifies whether a view for the component should ignore user events.

   @param enabled A Boolean value that determines whether user events are ignored

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &userInteractionEnabled(bool enabled)
  {
    constexpr auto userInteractionEnabledOverridesExistingOptions =
      PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!userInteractionEnabledOverridesExistingOptions,
                  "Setting 'userInteractionEnabled' overrides existing options");
    _options.attributes.insert({ @selector(setUserInteractionEnabled:), enabled });
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   Specifies whether subviews of a view for the component should be confined to its bounds.

   @param clip A Boolean value that determines whether subviews are confined

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &clipsToBounds(bool clip)
  {
    constexpr auto clipsToBoundsOverridesExistingOptions =
      PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!clipsToBoundsOverridesExistingOptions, "Setting 'clipsToBounds' overrides existing options");
    _options.attributes.insert({ @selector(setClipsToBounds:), clip });
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   Specifies the alpha value for this component's view.

   @param a A floating-point number in the range 0.0 to 1.0, where 0.0 represents totally transparent and 1.0 represents
   totally opaque.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &alpha(CGFloat a)
  {
    constexpr auto alphaOverridesExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!alphaOverridesExistingOptions, "Setting 'alpha' overrides existing options");
    _options.attributes.insert({ @selector(setAlpha:), a });
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   Specifies the width of the border for this component's view.

   @param w The border width. When this value is greater than 0.0, the view draws a border using the current borderColor
   value.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &borderWidth(CGFloat w)
  {
    constexpr auto borderWidthOverridesExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!borderWidthOverridesExistingOptions, "Setting 'borderWidth' overrides existing options");
    _options.attributes.insert({ CKComponentViewAttribute::LayerAttribute(@selector(setBorderWidth:)), w });
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   Specifies the color of the border for this component's view.

   @param c A @c UIColor value that determines the border color. The default value of this property is an opaque black.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &borderColor(NS_RELEASES_ARGUMENT UIColor *c)
  {
    constexpr auto borderColorOverridesExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!borderColorOverridesExistingOptions, "Setting 'borderColor' overrides existing options");
    _options.attributes.insert({ CKComponentViewAttribute::LayerAttribute(@selector(setBorderColor:)), (id)c.CGColor });
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   Specifies the radius to use when drawing rounded corners for the component's view background.

   @param r A floating point value that determines the radius. Setting the radius to a value greater than 0.0 causes the
   view to begin drawing rounded corners on its background.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &cornerRadius(CGFloat r)
  {
    constexpr auto cornerRadiusOverridesExistingOptions =
      PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!cornerRadiusOverridesExistingOptions, "Setting 'cornerRadius' overrides existing options");
    _options.attributes.insert({ CKComponentViewAttribute::LayerAttribute(@selector(setCornerRadius:)), r });
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   Specifies the action that should be sent when the user performs a single tap gesture on the component's view.

   @param a A @c CKAction instance to be sent when the gesture is recognized.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &onTap(CKAction<UIGestureRecognizer *> a)
  {
    constexpr auto onTapOverridesExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!onTapOverridesExistingOptions, "Setting 'onTap' overrides existing options");
    _options.attributes.insert(CKComponentTapGestureAttribute(a));
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   Specifies a selector that should be sent up the responder chain when the component's view receives any event that
   matches a given event mask.

   @param events  Events that should trigger the action.
   @param action  A selector to send.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &onControlEvents(UIControlEvents events, SEL action)
  {
    constexpr auto onControlEventsOverridesExistingOptions =
      PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!onControlEventsOverridesExistingOptions, "Setting 'onControlEvents' overrides existing options");
    _options.attributes.insert(CKComponentActionAttribute(action, events));
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   Specifies an action that should be invoked when the component's view receives any event that
   matches a given event mask.

   @param events  Events that should trigger the action.
   @param action  An action to invoke.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &onControlEvents(UIControlEvents events, CKAction<> action)
  {
    constexpr auto onControlEventsOverridesExistingOptions =
      PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!onControlEventsOverridesExistingOptions, "Setting 'onControlEvents' overrides existing options");
    _options.attributes.insert(CKComponentActionAttribute(action, events));
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   Used to determine how a view lays out its content when its bounds change. The default is @c
   UIViewContentModeScaleToFill .

   @param m A mode to set.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &contentMode(UIViewContentMode m)
  {
    constexpr auto contentModeOverridesExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!contentModeOverridesExistingOptions, "Setting 'contentMode' overrides existing options");
    _options.attributes.insert({ @selector(setContentMode:), m });
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   Sets a value for an arbitrary view property by specifying a selector that corresponds to the property setter and the
   value.

   @param attr A selector corresponding to a setter.
   @param value A value to set.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &attribute(SEL attr, NS_RELEASES_ARGUMENT id value)
  {
    constexpr auto attributeOverridesExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!attributeOverridesExistingOptions, "Setting 'attribute' overrides existing options");
    _options.attributes.insert({attr, value});
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   Sets a value for an arbitrary view property by specifying a complete attribute descriptor and a value.

   @param attr An view attribute descriptor.
   @param value A value to set. Both expressions of boxable types, such as @c int or @c CGFloat, and ObjC objects are
   supported.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &attribute(const CKComponentViewAttribute &attr, const CKBoxedValue &value)
  {
    constexpr auto attributeOverridesExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!attributeOverridesExistingOptions, "Setting 'attribute' overrides existing options");
    _options.attributes.insert({attr, value});
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   Adds a complete attribute / value pair to the component view configuration, mostly for convenience for helper
   functions that return both an attribute and a value.

   @param v An attribute / value pair.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &attribute(const CKComponentViewAttributeValue &v)
  {
    constexpr auto attributeOverridesExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!attributeOverridesExistingOptions, "Setting 'attribute' overrides existing options");
    _options.attributes.insert(v);
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   Specifies a complete attribute map for a view of this component.

   @param a  The attribute map to set.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &attributes(CKViewComponentAttributeValueMap a)
  {
    constexpr auto attributesOverrideExistingOptions = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!attributesOverrideExistingOptions, "Setting 'attributes' overrides existing options");
    _options.attributes = std::move(a);
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

  /**
   Specifies an accessibility configuration for a view of this component, which will be applied when accessibility is
   enabled.

   @param c  Accessibility configuration to set.

   @note  Calling this method on a builder that already has a complete set of options specified using \c options() will
   trigger a compilation error.
   */
  auto &accessibilityContext(RCAccessibilityContext c)
  {
    constexpr auto accessibilityContextOverridesExistingOptions =
      PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options);
    static_assert(!accessibilityContextOverridesExistingOptions,
                  "Setting 'accessibilityContext' overrides existing options");
    _options.accessibilityContext = std::move(c);
    return reinterpret_cast<ButtonComponentBuilder<PropsBitmap | ButtonComponentPropId::anyOption> &>(*this);
  }

 private:
  friend BuilderBase<ButtonComponentBuilder, PropsBitmap>;

  /**
  Creates a new component instance with specified properties.

  @note  This method must @b not be called more than once on a given component builder instance.
  */
  NS_RETURNS_RETAINED auto _build() noexcept -> CKButtonComponent *
  {
    constexpr auto actionIsSet = PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::action);
    static_assert(actionIsSet, "Required property 'action' is not set.");

    if (!PropBitmap::isSet(PropsBitmap, ButtonComponentPropId::options)) {
      // Only set these when a complete `CKButtonComponentOptions` struct wasn't specified explicitly.
      _options.titles = std::move(_titles);
      _options.titleColors = std::move(_titleColors);
      _options.images = std::move(_images);
      _options.backgroundImages = std::move(_backgroundImages);

      if (PropBitmap::isSet(PropsBitmap, ComponentBuilderBasePropId::size)) {
        _options.size = this->_size;
      }
    }

    return [[CKButtonComponent alloc] initWithAction:std::move(_action) options:std::move(_options)];
  }

 private:
  CKButtonComponentStateMap<NSString *>::Map _titles{};
  CKButtonComponentStateMap<UIColor *>::Map _titleColors{};
  CKButtonComponentStateMap<UIImage *>::Map _images{};
  CKButtonComponentStateMap<UIImage *>::Map _backgroundImages{};

  CKAction<UIEvent *> _action{};
  CKButtonComponentOptions _options{};
};