         YGNodeFree(node)
     }
     
-    //TODO Expose 2 methods later
-    fileprivate func calculate(with size: CGSize) -> CGSize {
-        node.calculateLayout(size: size.ygSize, direction: direction)
-        return CGSize(width: node.layoutWidth, height: node.layoutHeight)
-    }
-
-    fileprivate func applyToViews(preserveOrigin: Bool = false, offset: CGPoint = .zero) {
+    
+    public func calculate(constrainedSize: CGSize? = nil, preserveOrigin: Bool = false) {
+        _calculateNode(constrainedSize)
+        _calculateFrame(preserveOrigin: preserveOrigin, offset: .zero)
+    }
+    
+    public func apply() {
+        view?.frame = frame
+        sublayouts.forEach {
+            $0.apply()
+        }
+    }
+    
+    public func layout(preserveOrigin: Bool = false) {
+        calculate(preserveOrigin: preserveOrigin)
+        apply()
+    }
+    
+    fileprivate func _calculateNode(_ size: CGSize? = nil) {
+        let constrainedSize = size ?? view?.frame.size ?? .undefined
+        node.calculateLayout(size: constrainedSize.ygSize, direction: direction)
+    }
+    
+    fileprivate func _calculateFrame(preserveOrigin: Bool = false, offset: CGPoint = .zero) {
         if isEnabled {
             let origin = preserveOrigin ? frame.origin : .zero
             let topLeft = CGPoint(x: node.layoutLeft + offset.x, y: node.layoutTop + offset.y)

        return superlayout == nil
    }
    
    public private(set) var frame: CGRect = .zero {
        didSet {
            view?.frame = frame
        }
    }
    
    public var intrinsicSize: CGSize {
        return calculate(with: .undefined)
    }
    
    internal init(view: UIView? = nil) {

            
            sublayouts.forEach {
                if isView {
                    $0._calculateFrame(preserveOrigin: preserveOrigin, offset: .zero)
                } else {
                    $0._calculateFrame(preserveOrigin: preserveOrigin, offset: frame.origin)
                }
            }
        }
    }
    
}
