 
     /// :nodoc:
     @objc
-    public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
+    open func textFieldShouldReturn(_ textField: UITextField) -> Bool {
         if textField == lastSubField() && _firstInvalidAutoAdvanceField() == nil {
             // User pressed return in the last field, and all fields are valid
             if delegate?.responds(


    // MARK: UIKeyInput
    /// :nodoc:
    @objc public var hasText: Bool {
        return numberField.hasText || expirationField.hasText || cvcField.hasText
    }

    /// :nodoc:
    @objc
    public func insertText(_ text: String) {
        currentFirstResponderField()?.insertText(text)
    }

    /// :nodoc:
    @objc
    public func deleteBackward() {
        currentFirstResponderField()?.deleteBackward()
    }

    /// :nodoc:
    @objc
    public class func keyPathsForValuesAffectingIsValid() -> Set<String> {
        return Set<String>([
            "viewModel.isValid",
            "viewModel.hasCompleteMetadataForCardNumber",

    /// The current expiration month displayed by the field, as a string. T
    /// This may or may not be a valid entry (i.e. "0") unless `isValid` is true.
    /// It may be also 0-prefixed (i.e. "01" for January).
    @objc open var formattedExpirationMonth: String? {
        return viewModel.expirationMonth
    }
    /// The current expiration year displayed by the field, modulo 100
