Added public/open modifiers, moved example code
This commit is contained in:
parent
0baf0c32ea
commit
c2d1929e37
|
@ -7,18 +7,61 @@
|
|||
//
|
||||
|
||||
import UIKit
|
||||
import Gluon
|
||||
|
||||
class ViewController: UIViewController {
|
||||
final class Counter: Component<NoProps, Counter.State> {
|
||||
struct State: StateType {
|
||||
var counter = 0
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
// Do any additional setup after loading the view, typically from a nib.
|
||||
func onPress() {
|
||||
setState { $0.counter += 1 }
|
||||
}
|
||||
|
||||
lazy var onPressHandler = { Unique { self.onPress() } }()
|
||||
|
||||
func render() -> Node {
|
||||
return View.node {
|
||||
[Button.node(.init(onPress: onPressHandler)) { "Press me" },
|
||||
Label.node { Node("\(state.counter)") }]
|
||||
}
|
||||
|
||||
override func didReceiveMemoryWarning() {
|
||||
super.didReceiveMemoryWarning()
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ViewController: UIViewController {
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
render(node: Counter.node(), container: view)
|
||||
}
|
||||
|
||||
override func didReceiveMemoryWarning() {
|
||||
super.didReceiveMemoryWarning()
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
}
|
||||
|
||||
final class ClassicViewController: UIViewController {
|
||||
private let button = UIButton()
|
||||
private let label = UILabel()
|
||||
|
||||
private var counter = 0
|
||||
|
||||
@objc func onPress() {
|
||||
counter += 1
|
||||
label.text = "\(counter)"
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
label.text = "\(counter)"
|
||||
|
||||
button.addTarget(self, action: #selector(onPress), for: .touchUpInside)
|
||||
|
||||
view.addSubview(button)
|
||||
view.addSubview(label)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,125 +7,142 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
protocol Default {
|
||||
public protocol Default {
|
||||
init()
|
||||
}
|
||||
|
||||
struct Unique<T>: Equatable {
|
||||
public struct Unique<T>: Equatable {
|
||||
private let uuid = UUID()
|
||||
private let boxed: T
|
||||
|
||||
init(_ boxed: T) {
|
||||
public init(_ boxed: T) {
|
||||
self.boxed = boxed
|
||||
}
|
||||
|
||||
static func == (lhs: Unique<T>, rhs: Unique<T>) -> Bool {
|
||||
public static func == (lhs: Unique<T>, rhs: Unique<T>) -> Bool {
|
||||
return lhs.uuid == rhs.uuid
|
||||
}
|
||||
}
|
||||
|
||||
struct NoProps: Equatable, Default {
|
||||
public struct NoProps: Equatable, Default {
|
||||
public init() {}
|
||||
}
|
||||
|
||||
private protocol ComponentType {
|
||||
protocol ComponentType {
|
||||
}
|
||||
|
||||
extension String: ComponentType {
|
||||
}
|
||||
|
||||
class BaseComponent<Props: Equatable>: ComponentType {
|
||||
open class BaseComponent<Props: Equatable>: ComponentType {
|
||||
private(set) var props: Props
|
||||
private(set) var children: [Node]
|
||||
|
||||
required init(props: Props, children: [Node]) {
|
||||
public required init(props: Props, children: [Node]) {
|
||||
self.props = props
|
||||
self.children = children
|
||||
}
|
||||
|
||||
static func node(_ props: Props, childrenFactory: () -> [Node]) -> Node {
|
||||
public static func node(_ props: Props, childrenFactory: () -> [Node]) -> Node {
|
||||
let children = childrenFactory()
|
||||
return Node {
|
||||
self.init(props: props, children: children)
|
||||
}
|
||||
}
|
||||
|
||||
static func node(_ props: Props, childFactory: () -> Node) -> Node {
|
||||
public static func node(_ props: Props, childFactory: () -> Node) -> Node {
|
||||
// applying `childFactory` here to avoid `@escaping` attribute
|
||||
let child = childFactory()
|
||||
return Node { self.init(props: props, children: [child]) }
|
||||
}
|
||||
|
||||
static func node(_ props: Props) -> Node {
|
||||
public static func node(_ props: Props) -> Node {
|
||||
return Node { self.init(props: props, children: []) }
|
||||
}
|
||||
}
|
||||
|
||||
extension BaseComponent where Props: Default {
|
||||
static func node(childrenFactory: () -> [Node]) -> Node {
|
||||
public static func node(childrenFactory: () -> [Node]) -> Node {
|
||||
return self.node(Props(), childrenFactory: childrenFactory)
|
||||
}
|
||||
|
||||
static func node(childFactory: () -> Node) -> Node {
|
||||
public static func node(childFactory: () -> Node) -> Node {
|
||||
return self.node(Props(), childFactory: childFactory)
|
||||
}
|
||||
|
||||
static func node() -> Node {
|
||||
public static func node() -> Node {
|
||||
return Node { self.init(props: Props(), children: []) }
|
||||
}
|
||||
}
|
||||
|
||||
struct Node {
|
||||
public struct Node {
|
||||
fileprivate let factory: () -> ComponentType
|
||||
}
|
||||
|
||||
extension Node: ExpressibleByStringLiteral {
|
||||
init(stringLiteral: String) {
|
||||
public init(stringLiteral: String) {
|
||||
factory = { stringLiteral }
|
||||
}
|
||||
}
|
||||
|
||||
extension Node {
|
||||
init(_ string: String) {
|
||||
public init(_ string: String) {
|
||||
factory = { string }
|
||||
}
|
||||
}
|
||||
|
||||
class View: BaseComponent<NoProps> {
|
||||
public final class View: BaseComponent<NoProps> {
|
||||
}
|
||||
|
||||
class Label: BaseComponent<Label.Props> {
|
||||
struct Props: Equatable, Default {
|
||||
let fontColor = UIColor.black
|
||||
public final class Label: BaseComponent<Label.Props> {
|
||||
public struct Props: Equatable, Default {
|
||||
let fontColor: UIColor
|
||||
|
||||
public init() {
|
||||
fontColor = .black
|
||||
}
|
||||
|
||||
public init(fontColor: UIColor) {
|
||||
self.fontColor = fontColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Button: BaseComponent<Button.Props> {
|
||||
struct Props: Equatable {
|
||||
let backgroundColor = UIColor.white
|
||||
let fontColor = UIColor.black
|
||||
public final class Button: BaseComponent<Button.Props> {
|
||||
public struct Props: Equatable {
|
||||
let backgroundColor: UIColor
|
||||
let fontColor: UIColor
|
||||
let onPress: Unique<() -> ()>
|
||||
|
||||
public init(backgroundColor: UIColor = .white, fontColor: UIColor = .black,
|
||||
onPress: Unique<() -> ()>) {
|
||||
self.backgroundColor = backgroundColor
|
||||
self.fontColor = fontColor
|
||||
self.onPress = onPress
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protocol CompositeComponent {
|
||||
public protocol CompositeComponent {
|
||||
func render() -> Node
|
||||
}
|
||||
|
||||
protocol StateType: Default & Equatable {
|
||||
public protocol StateType: Default & Equatable {
|
||||
}
|
||||
|
||||
class StatefulComponent<Props: Equatable, State: StateType>: BaseComponent<Props> {
|
||||
private(set) var state: State
|
||||
open class StatefulComponent<Props: Equatable, State: StateType>:
|
||||
BaseComponent<Props> {
|
||||
public private(set) var state: State
|
||||
|
||||
required init(props: Props, children: [Node]) {
|
||||
public required init(props: Props, children: [Node]) {
|
||||
state = State()
|
||||
super.init(props: props, children: children)
|
||||
}
|
||||
|
||||
func setState(setter: (inout State) -> ()) {
|
||||
public func setState(setter: (inout State) -> ()) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
typealias Component<P: Equatable, S: StateType> =
|
||||
public typealias Component<P: Equatable, S: StateType> =
|
||||
StatefulComponent<P, S> & CompositeComponent
|
||||
|
|
|
@ -8,46 +8,3 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
final class Counter: Component<NoProps, Counter.State> {
|
||||
struct State: StateType {
|
||||
var counter = 0
|
||||
}
|
||||
|
||||
func onPress() {
|
||||
setState { $0.counter += 1 }
|
||||
}
|
||||
|
||||
lazy var onPressHandler = { Unique { self.onPress() } }()
|
||||
|
||||
func render() -> Node {
|
||||
return View.node {
|
||||
[Button.node(.init(onPress: onPressHandler)) { "Press me" },
|
||||
Label.node { Node("\(state.counter)") }]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class ViewController: UIViewController {
|
||||
private let button = UIButton()
|
||||
private let label = UILabel()
|
||||
|
||||
private var counter = 0
|
||||
|
||||
@objc func onPress() {
|
||||
counter += 1
|
||||
label.text = "\(counter)"
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
label.text = "\(counter)"
|
||||
|
||||
button.addTarget(self, action: #selector(onPress), for: .touchUpInside)
|
||||
|
||||
view.addSubview(button)
|
||||
view.addSubview(label)
|
||||
}
|
||||
}
|
||||
|
||||
// render(node: Test.node(), container: UIView())
|
||||
|
|
|
@ -7,5 +7,5 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
func render(node: Node, container: UIView) {
|
||||
public func render(node: Node, container: UIView) {
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue