         }
     }
     
-    /// Computes the frame of the text background view.
-    ///
-    /// If `textBackgroundViewContainsClearButton` is `true`, the clear button will be included in the frame.
-    ///
-    /// - Returns: The frame
-    private func computeTextBackgroundViewFrame() -> CGRect {
-        
-        let insetX = -horizontalTextPadding
-        let insetY = -verticalTextPadding
-        let textRect = textAndEditingRect(forBounds: bounds)
-        let frame: CGRect
-        
-        if textBackgroundViewContainsClearButton {
-            let clearButtonRect = self.clearButtonRect(forBounds: bounds)
-            frame = textRect.union(clearButtonRect).insetBy(dx: insetX, dy: insetY)
+    private var isRightViewVisible: Bool {
+        
+        guard rightView != nil else { return false }
+        return isOverlayVisible(with: rightViewMode)
+    }
+    
+    private func isOverlayVisible(with viewMode: UITextField.ViewMode) -> Bool {
+        
+        switch viewMode {
+        case .always:
+            return true
+        case .whileEditing:
+            return isEditing
+        case .unlessEditing:
+            return !isEditing
+        case .never:
+            return false
+        }
+    }
+    
+    // MARK: Clear button
+    
+    /// Whether the clear button is displayed to the left or to the right of the text.
+    private var clearButtonPosition: HorizontalPosition {
+        
+        if textAlignment == .natural && UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft {
+            return .left
         } else {
-            frame = textRect.insetBy(dx: insetX, dy: insetY)
-        }
-        
-        return frame
-    }
-    
-    /// The padding applied to the left and right of the text rectangle. Can be
-    /// used to reserve more space for the `textBackgroundView`.
-    @IBInspectable open var horizontalTextPadding: CGFloat = 0.0 {
-        didSet {
-            setNeedsUpdateConstraints()
-        }
-    }
-    
-    /// The padding applied to the top and bottom of the text rectangle. Can be
-    /// used to reserve more space for the `textBackgroundView`.
-    @IBInspectable open var verticalTextPadding: CGFloat = 0.0 {
-        didSet {
-            setNeedsUpdateConstraints()
-        }
+            return .right
+        }
+    }
+    
+    private func isClearButtonVisible() -> Bool {
+        
+        return isOverlayVisible(with: clearButtonMode)
     }
     
     // MARK: - Init

    
    private func leftAlignedPlaceholderTranslation() -> CGFloat {
        
        return 0.5 * (1.0 - placeholderScaleWhenEditing) * placeholderLabel.bounds.width * -1.0
    }
    
    private func rightAlignedPlaceholderTranslation() -> CGFloat {
        
        return 0.5 * (1.0 - placeholderScaleWhenEditing) * placeholderLabel.bounds.width
    }
    
    private func placeholderTransformForBasePosition() -> CATransform3D {

        placeholderLabel.layer.removeAllAnimations()
        
        let animation = CABasicAnimation(keyPath: "transform")
        animation.duration = placeholderAnimationDuration ?? Constants.defaultPlaceholderAnimationDuration
        animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)
        let fromValue = placeholderLabel.layer.presentation()?.transform ?? placeholderLabel.layer.transform
        animation.fromValue = fromValue
