diff --git a/ios/src_library/React Native/RNIComputable/RNIComputableValue.swift b/ios/src_library/React Native/RNIComputable/RNIComputableValue.swift new file mode 100644 index 00000000..b90c1404 --- /dev/null +++ b/ios/src_library/React Native/RNIComputable/RNIComputableValue.swift @@ -0,0 +1,111 @@ +// +// RNIComputableValue.swift +// swift-programmatic-modal +// +// Created by Dominic Go on 5/19/23. +// + +import Foundation + +public struct RNIComputableValue { + + // MARK: - Properties + // ------------------ + + public let mode: RNIComputableValueMode; + + public let offset: RNIComputableOffset?; + + public let minValue: CGFloat?; + public let maxValue: CGFloat?; + + + // MARK: - Internal Functions + // -------------------------- + + + func valueWithOffsets(forValue value: CGFloat) -> CGFloat { + return self.offset?.compute(withValue: value) ?? value; + }; + + func valueWithClamp(forValue value: CGFloat) -> CGFloat { + return value.clamped( + min: self.minValue, + max: self.maxValue + ); + }; + + // MARK: - Functions + // ----------------- + + public func computeRaw( + withTargetValue targetValue: CGFloat, + currentValue: CGFloat + ) -> CGFloat { + switch self.mode { + case .current: + return currentValue; + + case .stretch: + return targetValue; + + case let .constant(constantValue): + return constantValue; + + case let .percent(percentValue): + return percentValue * targetValue; + }; + }; + + public func compute( + withTargetValue targetValue: CGFloat, + currentValue: CGFloat + ) -> CGFloat { + let rawValue = self.computeRaw( + withTargetValue: targetValue, + currentValue: currentValue + ); + + let clampedValue = self.valueWithClamp(forValue: rawValue); + return self.valueWithOffsets(forValue: clampedValue); + }; +}; + +extension RNIComputableValue { + public init?(fromDict dict: NSDictionary){ + guard let mode = RNIComputableValueMode(fromDict: dict) + else { return nil }; + + self.mode = mode; + + self.offset = { + guard let offsetRaw = dict["offset"] as? NSDictionary, + let offset = RNIComputableOffset(fromDict: offsetRaw) + else { return nil }; + + return offset; + }(); + + self.minValue = + Self.getDoubleValue(forDict: dict, withKey: "minValue"); + + self.maxValue = + Self.getDoubleValue(forDict: dict, withKey: "maxValue"); + }; + + public init(mode: RNIComputableValueMode){ + self.mode = mode; + + self.offset = nil; + self.minValue = nil; + self.maxValue = nil; + }; + + static private func getDoubleValue( + forDict dict: NSDictionary, + withKey key: String + ) -> CGFloat? { + guard let number = dict[key] as? NSNumber else { return nil }; + return number.doubleValue; + }; +}; diff --git a/ios/src_library/React Native/RNIComputable/RNIComputableValueMode.swift b/ios/src_library/React Native/RNIComputable/RNIComputableValueMode.swift new file mode 100644 index 00000000..80ac6e56 --- /dev/null +++ b/ios/src_library/React Native/RNIComputable/RNIComputableValueMode.swift @@ -0,0 +1,48 @@ +// +// RNIComputableValueMode.swift +// swift-programmatic-modal +// +// Created by Dominic Go on 5/19/23. +// + +import Foundation + + +public enum RNIComputableValueMode { + case current; + case stretch; + case constant(constantValue: Double); + case percent(percentValue: Double); +}; + +extension RNIComputableValueMode { + public init?(fromDict dict: NSDictionary){ + guard let mode = dict["mode"] as? String else { return nil }; + + switch mode { + case "current": + self = .current; + + case "stretch": + self = .stretch; + + case "constant": + guard let value = dict["constantValue"] as? NSNumber + else { return nil }; + + self = .constant( + constantValue: value.doubleValue + ); + + case "percent": + guard let value = dict["percentValue"] as? NSNumber + else { return nil }; + + self = .percent(percentValue: value.doubleValue); + + default: + return nil; + }; + }; +}; + diff --git a/ios/src_library/React Native/RNIModalView/RNIModalViewController.swift b/ios/src_library/React Native/RNIModalView/RNIModalViewController.swift index 753e946f..941f1640 100644 --- a/ios/src_library/React Native/RNIModalView/RNIModalViewController.swift +++ b/ios/src_library/React Native/RNIModalView/RNIModalViewController.swift @@ -270,7 +270,7 @@ public class RNIModalViewController: UIViewController { ); default: - self.preferredContentSize = computableSize.computeWithOffsets( + self.preferredContentSize = computableSize.compute( withTargetSize: targetSize, currentSize: .zero ); }; diff --git a/src/types/RNIComputable/RNIComputableValue.ts b/src/types/RNIComputable/RNIComputableValue.ts new file mode 100644 index 00000000..25e3e54d --- /dev/null +++ b/src/types/RNIComputable/RNIComputableValue.ts @@ -0,0 +1,27 @@ +/* eslint-disable prettier/prettier */ + +import type { RNIComputableOffset } from './RNIComputableOffset'; + + +type RNIComputableValueShared = { + offset?: RNIComputableOffset; + minValue?: number; + maxValue?: number; +}; + +type RNIComputableValueModeBase = { + mode: 'current'; +} | { + mode: 'stretch'; +} | { + mode: 'constant'; + constantValue: number; +} | { + mode: 'percent'; + percentValue: number; +}; + + +export type RNIComputableValue = + | RNIComputableValueModeBase + & RNIComputableValueShared; diff --git a/src/types/RNIComputable/index.ts b/src/types/RNIComputable/index.ts index 271f5977..6432266b 100644 --- a/src/types/RNIComputable/index.ts +++ b/src/types/RNIComputable/index.ts @@ -1,2 +1,3 @@ export * from './RNIComputableOffset'; export * from './RNIComputableSize'; +export * from './RNIComputableValue';