Rework Example navigation, add LineBreakMode
This commit is contained in:
parent
a5fa21e84d
commit
89cde27de5
|
@ -13,10 +13,17 @@
|
|||
607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; };
|
||||
607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; };
|
||||
607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; };
|
||||
D126CB7421ECF7A60097300E /* GluonApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1E0C86021DA54780042A261 /* GluonApp.swift */; };
|
||||
D1BFAF772215795900845EA0 /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1BFAF762215795900845EA0 /* Router.swift */; };
|
||||
D1BFAF792215800A00845EA0 /* Counter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1BFAF782215800A00845EA0 /* Counter.swift */; };
|
||||
D1BFAF7B22158B4000845EA0 /* List.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1BFAF7A22158B4000845EA0 /* List.swift */; };
|
||||
D1DEEC2922009E8000C525EE /* NavRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1DEEC2822009E8000C525EE /* NavRouter.swift */; };
|
||||
D1E6BCD221AD4CD6002769E3 /* GluonTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1E6BCD121AD4CD6002769E3 /* GluonTest.swift */; };
|
||||
D1F2C3272214407B008358DC /* TableModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1F2C3262214407B008358DC /* TableModal.swift */; };
|
||||
D1F7185322159E09004E5951 /* Controls.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1F7185222159E09004E5951 /* Controls.swift */; };
|
||||
D1F7185522159EAD004E5951 /* DatePickers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1F7185422159EAD004E5951 /* DatePickers.swift */; };
|
||||
D1F7185D2215A4A1004E5951 /* LayerProps.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1F7185C2215A4A1004E5951 /* LayerProps.swift */; };
|
||||
D1F7185F2215A5D0004E5951 /* Constraints.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1F7185E2215A5D0004E5951 /* Constraints.swift */; };
|
||||
D1F718612215A617004E5951 /* Modals.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1F718602215A617004E5951 /* Modals.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
@ -45,10 +52,17 @@
|
|||
8CADEBB8BFF6F2621CA49E8F /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
|
||||
C1B4A8D80770145FDAFEAE64 /* Pods_Gluon_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Gluon_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C6DA99382B6892EAB361742F /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = "<group>"; };
|
||||
D1BFAF762215795900845EA0 /* Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Router.swift; sourceTree = "<group>"; };
|
||||
D1BFAF782215800A00845EA0 /* Counter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Counter.swift; sourceTree = "<group>"; };
|
||||
D1BFAF7A22158B4000845EA0 /* List.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = List.swift; sourceTree = "<group>"; };
|
||||
D1DEEC2822009E8000C525EE /* NavRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavRouter.swift; sourceTree = "<group>"; };
|
||||
D1E0C86021DA54780042A261 /* GluonApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GluonApp.swift; sourceTree = "<group>"; };
|
||||
D1E6BCD121AD4CD6002769E3 /* GluonTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GluonTest.swift; sourceTree = "<group>"; };
|
||||
D1F2C3262214407B008358DC /* TableModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableModal.swift; sourceTree = "<group>"; };
|
||||
D1F7185222159E09004E5951 /* Controls.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Controls.swift; sourceTree = "<group>"; };
|
||||
D1F7185422159EAD004E5951 /* DatePickers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatePickers.swift; sourceTree = "<group>"; };
|
||||
D1F7185C2215A4A1004E5951 /* LayerProps.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayerProps.swift; sourceTree = "<group>"; };
|
||||
D1F7185E2215A5D0004E5951 /* Constraints.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constraints.swift; sourceTree = "<group>"; };
|
||||
D1F718602215A617004E5951 /* Modals.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modals.swift; sourceTree = "<group>"; };
|
||||
E7F808D1B3715FF294877289 /* Pods-Gluon_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Gluon_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-Gluon_Example/Pods-Gluon_Example.release.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
|
@ -98,10 +112,9 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
607FACD51AFB9204008FA782 /* AppDelegate.swift */,
|
||||
D1F7185122159D6E004E5951 /* Examples */,
|
||||
607FACD71AFB9204008FA782 /* ViewController.swift */,
|
||||
D1E0C86021DA54780042A261 /* GluonApp.swift */,
|
||||
D1DEEC2822009E8000C525EE /* NavRouter.swift */,
|
||||
D1F2C3262214407B008358DC /* TableModal.swift */,
|
||||
D1BFAF762215795900845EA0 /* Router.swift */,
|
||||
607FACD91AFB9204008FA782 /* Main.storyboard */,
|
||||
607FACDC1AFB9204008FA782 /* Images.xcassets */,
|
||||
607FACDE1AFB9204008FA782 /* LaunchScreen.xib */,
|
||||
|
@ -155,6 +168,22 @@
|
|||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D1F7185122159D6E004E5951 /* Examples */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D1BFAF7A22158B4000845EA0 /* List.swift */,
|
||||
D1DEEC2822009E8000C525EE /* NavRouter.swift */,
|
||||
D1F2C3262214407B008358DC /* TableModal.swift */,
|
||||
D1BFAF782215800A00845EA0 /* Counter.swift */,
|
||||
D1F7185222159E09004E5951 /* Controls.swift */,
|
||||
D1F7185422159EAD004E5951 /* DatePickers.swift */,
|
||||
D1F7185C2215A4A1004E5951 /* LayerProps.swift */,
|
||||
D1F7185E2215A5D0004E5951 /* Constraints.swift */,
|
||||
D1F718602215A617004E5951 /* Modals.swift */,
|
||||
);
|
||||
path = Examples;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D360275A0620D06017CFB567 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -291,11 +320,18 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D126CB7421ECF7A60097300E /* GluonApp.swift in Sources */,
|
||||
D1BFAF7B22158B4000845EA0 /* List.swift in Sources */,
|
||||
D1F2C3272214407B008358DC /* TableModal.swift in Sources */,
|
||||
607FACD81AFB9204008FA782 /* ViewController.swift in Sources */,
|
||||
D1F7185F2215A5D0004E5951 /* Constraints.swift in Sources */,
|
||||
D1F7185322159E09004E5951 /* Controls.swift in Sources */,
|
||||
D1DEEC2922009E8000C525EE /* NavRouter.swift in Sources */,
|
||||
D1BFAF772215795900845EA0 /* Router.swift in Sources */,
|
||||
607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */,
|
||||
D1F7185D2215A4A1004E5951 /* LayerProps.swift in Sources */,
|
||||
D1BFAF792215800A00845EA0 /* Counter.swift in Sources */,
|
||||
D1F718612215A617004E5951 /* Modals.swift in Sources */,
|
||||
D1F7185522159EAD004E5951 /* DatePickers.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// Constraints.swift
|
||||
// Gluon_Example
|
||||
//
|
||||
// Created by Max Desiatov on 14/02/2019.
|
||||
// Copyright © 2019 Gluon. All rights reserved.
|
||||
//
|
||||
|
||||
import Gluon
|
||||
|
||||
struct Constraints: LeafComponent {
|
||||
typealias Props = Null
|
||||
|
||||
static func render(props: Props, hooks: Hooks) -> AnyNode {
|
||||
let left = hooks.state(0.5 as Float)
|
||||
|
||||
return StackView.node(.init(
|
||||
axis: .vertical,
|
||||
distribution: .fillEqually,
|
||||
Edges.equal(to: .parent)
|
||||
), [
|
||||
Slider.node(.init(
|
||||
value: left.value,
|
||||
valueHandler: Handler(left.set),
|
||||
Style(Width.equal(to: .parent))
|
||||
)),
|
||||
|
||||
View.node(
|
||||
.init(Style(backgroundColor: .red)),
|
||||
Label.node(.init(
|
||||
alignment: .center,
|
||||
textColor: .white,
|
||||
Style(Left.equal(to: .parent, constant: Double(left.value) * 200))
|
||||
), "\(left.value)")
|
||||
),
|
||||
])
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
//
|
||||
// Controls.swift
|
||||
// Gluon_Example
|
||||
//
|
||||
// Created by Max Desiatov on 14/02/2019.
|
||||
// Copyright © 2019 Gluon. All rights reserved.
|
||||
//
|
||||
|
||||
import Gluon
|
||||
|
||||
struct Controls: LeafComponent {
|
||||
typealias Props = Null
|
||||
|
||||
static func render(props: Props, hooks: Hooks) -> AnyNode {
|
||||
let sliding = hooks.state(0.5 as Float)
|
||||
let switchState = hooks.state(true)
|
||||
let stepperState = hooks.state(0.0)
|
||||
let isEnabled = hooks.state(true)
|
||||
|
||||
let children = [
|
||||
StackView.node(
|
||||
.init(
|
||||
alignment: .center,
|
||||
axis: .horizontal,
|
||||
spacing: 10.0
|
||||
), [
|
||||
Switch.node(
|
||||
.init(
|
||||
value: isEnabled.value,
|
||||
valueHandler: Handler(isEnabled.set)
|
||||
)
|
||||
),
|
||||
|
||||
Label.node(
|
||||
.init(alignment: .center),
|
||||
"isEnabled \(isEnabled.value)"
|
||||
),
|
||||
]
|
||||
),
|
||||
|
||||
Slider.node(.init(
|
||||
isEnabled: isEnabled.value,
|
||||
value: sliding.value,
|
||||
valueHandler: Handler(sliding.set),
|
||||
Style(Width.equal(to: .parent))
|
||||
)),
|
||||
|
||||
Label.node(.init(alignment: .center), "\(sliding.value)"),
|
||||
|
||||
StackView.node(
|
||||
.init(
|
||||
alignment: .center,
|
||||
axis: .horizontal,
|
||||
spacing: 10.0
|
||||
), [
|
||||
Switch.node(
|
||||
.init(
|
||||
isEnabled: isEnabled.value,
|
||||
value: switchState.value,
|
||||
valueHandler: Handler(switchState.set)
|
||||
)
|
||||
),
|
||||
|
||||
Label.node(.init(alignment: .center), "\(switchState.value)"),
|
||||
]
|
||||
),
|
||||
|
||||
StackView.node(
|
||||
.init(
|
||||
alignment: .center,
|
||||
axis: .horizontal,
|
||||
spacing: 10.0
|
||||
), [
|
||||
Stepper.node(
|
||||
.init(
|
||||
isEnabled: isEnabled.value,
|
||||
value: stepperState.value,
|
||||
valueHandler: Handler(stepperState.set)
|
||||
)
|
||||
),
|
||||
|
||||
Label.node(.init(alignment: .center), "\(stepperState.value)"),
|
||||
]
|
||||
),
|
||||
]
|
||||
|
||||
return StackView.node(
|
||||
.init(
|
||||
alignment: .center,
|
||||
axis: .vertical,
|
||||
distribution: .fillEqually,
|
||||
Edges.equal(to: .parent)
|
||||
),
|
||||
children
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// Counter.swift
|
||||
// Gluon_Example
|
||||
//
|
||||
// Created by Max Desiatov on 14/02/2019.
|
||||
// Copyright © 2019 Gluon. All rights reserved.
|
||||
//
|
||||
|
||||
import Gluon
|
||||
|
||||
struct Counter: LeafComponent {
|
||||
struct Props: Equatable {
|
||||
let countFrom: Int
|
||||
}
|
||||
|
||||
static func render(props: Counter.Props, hooks: Hooks) -> AnyNode {
|
||||
let count = hooks.state(props.countFrom)
|
||||
|
||||
return StackView.node(.init(
|
||||
alignment: .center,
|
||||
axis: .vertical,
|
||||
distribution: .fillEqually,
|
||||
Edges.equal(to: .parent)
|
||||
), [
|
||||
Button.node(
|
||||
.init(onPress: Handler { count.set { $0 + 1 } }),
|
||||
"Increment"
|
||||
),
|
||||
|
||||
Label.node(.init(alignment: .center), "\(count.value)"),
|
||||
])
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// DatePicker.swift
|
||||
// Gluon_Example
|
||||
//
|
||||
// Created by Max Desiatov on 14/02/2019.
|
||||
// Copyright © 2019 Gluon. All rights reserved.
|
||||
//
|
||||
|
||||
import Gluon
|
||||
|
||||
struct DatePickers: LeafComponent {
|
||||
typealias Props = Null
|
||||
|
||||
static func render(props: Props, hooks: Hooks) -> AnyNode {
|
||||
let currentDateTime = Date()
|
||||
let date = hooks.state(currentDateTime)
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.dateStyle = .medium
|
||||
dateFormatter.timeStyle = .medium
|
||||
let formattedDate = dateFormatter.string(from: date.value)
|
||||
let labelProps = Label.Props(
|
||||
alignment: .center,
|
||||
lineBreakMode: .wordWrap,
|
||||
numberOfLines: 0
|
||||
)
|
||||
|
||||
return StackView.node(.init(
|
||||
axis: .vertical,
|
||||
distribution: .fillEqually,
|
||||
Edges.equal(to: .parent)
|
||||
), [
|
||||
Label.node(
|
||||
labelProps,
|
||||
"\(formattedDate)"
|
||||
),
|
||||
Label.node(
|
||||
labelProps,
|
||||
"This picker doesn't animate state changes in the next picker"
|
||||
),
|
||||
DatePicker.node(
|
||||
.init(
|
||||
value: date.value,
|
||||
valueHandler: Handler(date.set),
|
||||
Style(Width.equal(to: .parent))
|
||||
)
|
||||
),
|
||||
Label.node(
|
||||
labelProps,
|
||||
"This picker animates state changes in the previous picker"
|
||||
),
|
||||
DatePicker.node(
|
||||
.init(
|
||||
isAnimated: false,
|
||||
value: date.value,
|
||||
valueHandler: Handler(date.set),
|
||||
Style(Width.equal(to: .parent))
|
||||
)
|
||||
),
|
||||
])
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// LayerProps.swift
|
||||
// Gluon_Example
|
||||
//
|
||||
// Created by Max Desiatov on 14/02/2019.
|
||||
// Copyright © 2019 Gluon. All rights reserved.
|
||||
//
|
||||
|
||||
import Gluon
|
||||
|
||||
struct LayerProps: LeafComponent {
|
||||
typealias Props = Null
|
||||
|
||||
static func render(props: Null, hooks: Hooks) -> AnyNode {
|
||||
let state = hooks.state(0.5 as Float)
|
||||
|
||||
return
|
||||
StackView.node(.init(
|
||||
axis: .vertical,
|
||||
distribution: .fillEqually,
|
||||
Edges.equal(to: .parent)
|
||||
), [
|
||||
Slider.node(.init(
|
||||
value: state.value,
|
||||
valueHandler: Handler(state.set),
|
||||
Style(Width.equal(to: .parent))
|
||||
)),
|
||||
|
||||
View.node(
|
||||
.init(
|
||||
Style(
|
||||
backgroundColor: .red,
|
||||
borderWidth: Float(state.value * 10),
|
||||
cornerRadius: Float(state.value * 10),
|
||||
opacity: Float(state.value),
|
||||
Width.equal(to: .parent)
|
||||
)
|
||||
),
|
||||
Label.node(.init(
|
||||
alignment: .center,
|
||||
textColor: .white,
|
||||
Style(
|
||||
[Top.equal(to: .parent, constant: Double(state.value) * 100),
|
||||
Left.equal(to: .parent, constant: Double(state.value) * 200)]
|
||||
)
|
||||
), "\(state.value)")
|
||||
),
|
||||
])
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// List.swift
|
||||
// Gluon_Example
|
||||
//
|
||||
// Created by Max Desiatov on 14/02/2019.
|
||||
// Copyright © 2019 Gluon. All rights reserved.
|
||||
//
|
||||
|
||||
import Gluon
|
||||
|
||||
private struct Cells: SimpleCellProvider {
|
||||
static func cell(
|
||||
props: Null,
|
||||
item: AppRoute,
|
||||
path: CellPath
|
||||
) -> AnyNode {
|
||||
return Label.node(.init(Style(
|
||||
[CenterY.equal(to: .parent),
|
||||
Height.equal(to: 44),
|
||||
Leading.equal(to: .parent, constant: 20)]
|
||||
)), "\(item.description)")
|
||||
}
|
||||
|
||||
typealias Props = Null
|
||||
|
||||
typealias Model = [[AppRoute]]
|
||||
}
|
||||
|
||||
struct List: PureLeafComponent {
|
||||
struct Props: Equatable {
|
||||
let model: [AppRoute]
|
||||
let onSelect: Handler<CellPath>
|
||||
}
|
||||
|
||||
static func render(props: Props) -> AnyNode {
|
||||
return ListView<Cells>.node(.init(
|
||||
model: [props.model],
|
||||
onSelect: props.onSelect,
|
||||
Style(Edges.equal(to: .parent))
|
||||
))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
//
|
||||
// Modals.swift
|
||||
// Gluon_Example
|
||||
//
|
||||
// Created by Max Desiatov on 14/02/2019.
|
||||
// Copyright © 2019 Gluon. All rights reserved.
|
||||
//
|
||||
|
||||
import Gluon
|
||||
|
||||
struct NavigationModal: PureLeafComponent {
|
||||
struct Props: Equatable {
|
||||
let isPresented: State<Bool>
|
||||
}
|
||||
|
||||
static func render(props: Props) -> AnyNode {
|
||||
return props.isPresented.value ?
|
||||
ModalPresenter.node(
|
||||
NavigationPresenter<NavRouter>.node(
|
||||
.init(
|
||||
initial: .first,
|
||||
prefersLargeTitles: true,
|
||||
routerProps: .init(
|
||||
onPress: Handler { props.isPresented.set(false) }
|
||||
)
|
||||
)
|
||||
)
|
||||
) : Null.node()
|
||||
}
|
||||
}
|
||||
|
||||
struct SimpleModal: LeafComponent {
|
||||
struct Props: Equatable {
|
||||
let isPresented: State<Bool>
|
||||
}
|
||||
|
||||
private static let colors: [(Color, String)] = [
|
||||
(.white, "white"),
|
||||
(.red, "red"),
|
||||
(.green, "green"),
|
||||
(.blue, "blue"),
|
||||
]
|
||||
|
||||
static func render(props: Props, hooks: Hooks) -> AnyNode {
|
||||
let backgroundColor = hooks.state(0)
|
||||
|
||||
return props.isPresented.value ? ModalPresenter.node(
|
||||
View.node(
|
||||
.init(Style(
|
||||
backgroundColor: colors[backgroundColor.value].0,
|
||||
Edges.equal(to: .parent)
|
||||
)),
|
||||
StackView.node(.init(
|
||||
axis: .vertical,
|
||||
distribution: .fillEqually,
|
||||
Edges.equal(to: .parent)
|
||||
), [
|
||||
Button.node(.init(
|
||||
onPress: Handler { props.isPresented.set(false) }
|
||||
), "Close Modal"),
|
||||
SegmentedControl.node(
|
||||
.init(value: backgroundColor.value,
|
||||
valueHandler: Handler(backgroundColor.set)),
|
||||
colors.map { $0.1 }
|
||||
),
|
||||
])
|
||||
)
|
||||
) : Null.node()
|
||||
}
|
||||
}
|
||||
|
||||
struct Modals: LeafComponent {
|
||||
typealias Props = Null
|
||||
|
||||
static func render(props: Props, hooks: Hooks) -> AnyNode {
|
||||
let isStackModalPresented = hooks.state(false)
|
||||
let isAnimationModalPresented = hooks.state(false)
|
||||
let isTableModalPresented = hooks.state(false)
|
||||
|
||||
return StackView.node(
|
||||
.init(
|
||||
alignment: .center,
|
||||
axis: .vertical,
|
||||
distribution: .fillEqually,
|
||||
Edges.equal(to: .parent)
|
||||
),
|
||||
[
|
||||
Button.node(
|
||||
.init(onPress: Handler { isAnimationModalPresented.set(true) }),
|
||||
"Present Simple Modal"
|
||||
),
|
||||
|
||||
Button.node(
|
||||
.init(onPress: Handler { isStackModalPresented.set(true) }),
|
||||
"Present Navigation Modal"
|
||||
),
|
||||
|
||||
Button.node(
|
||||
.init(onPress: Handler { isTableModalPresented.set(true) }),
|
||||
"Present Table Modal"
|
||||
),
|
||||
|
||||
NavigationModal.node(.init(isPresented: isStackModalPresented)),
|
||||
|
||||
SimpleModal.node(.init(isPresented: isAnimationModalPresented)),
|
||||
|
||||
TableModal.node(.init(isPresented: isTableModalPresented)),
|
||||
]
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,390 +0,0 @@
|
|||
//
|
||||
// GluonApp.swift
|
||||
// Gluon_Example
|
||||
//
|
||||
// Created by Max Desiatov on 31/12/2018.
|
||||
// Copyright © 2018 Max Desiatov. All rights reserved.
|
||||
//
|
||||
|
||||
import Gluon
|
||||
|
||||
struct NavigationModal: PureLeafComponent {
|
||||
struct Props: Equatable {
|
||||
let isPresented: State<Bool>
|
||||
}
|
||||
|
||||
static func render(props: Props) -> AnyNode {
|
||||
return props.isPresented.value ?
|
||||
ModalPresenter.node(
|
||||
NavigationPresenter<NavRouter>.node(
|
||||
.init(
|
||||
initial: .first,
|
||||
prefersLargeTitles: true,
|
||||
routerProps: .init(
|
||||
onPress: Handler { props.isPresented.set(false) }
|
||||
)
|
||||
)
|
||||
)
|
||||
) : Null.node()
|
||||
}
|
||||
}
|
||||
|
||||
struct SimpleModal: LeafComponent {
|
||||
struct Props: Equatable {
|
||||
let isPresented: State<Bool>
|
||||
}
|
||||
|
||||
private static let colors: [(Color, String)] = [
|
||||
(.white, "white"),
|
||||
(.red, "red"),
|
||||
(.green, "green"),
|
||||
(.blue, "blue"),
|
||||
]
|
||||
|
||||
static func render(props: Props, hooks: Hooks) -> AnyNode {
|
||||
let backgroundColor = hooks.state(0)
|
||||
|
||||
return props.isPresented.value ? ModalPresenter.node(
|
||||
View.node(
|
||||
.init(Style(
|
||||
backgroundColor: colors[backgroundColor.value].0,
|
||||
Edges.equal(to: .parent)
|
||||
)),
|
||||
StackView.node(.init(
|
||||
axis: .vertical,
|
||||
distribution: .fillEqually,
|
||||
Edges.equal(to: .parent)
|
||||
), [
|
||||
Button.node(.init(
|
||||
onPress: Handler { props.isPresented.set(false) }
|
||||
), "Close Modal"),
|
||||
SegmentedControl.node(
|
||||
.init(value: backgroundColor.value,
|
||||
valueHandler: Handler(backgroundColor.set)),
|
||||
colors.map { $0.1 }
|
||||
),
|
||||
])
|
||||
)
|
||||
) : Null.node()
|
||||
}
|
||||
}
|
||||
|
||||
struct ConstraintModal: LeafComponent {
|
||||
struct Props: Equatable {
|
||||
let isPresented: State<Bool>
|
||||
}
|
||||
|
||||
static func render(props: Props, hooks: Hooks) -> AnyNode {
|
||||
let left = hooks.state(0.5 as Float)
|
||||
|
||||
return props.isPresented.value ? ModalPresenter.node(
|
||||
View.node(
|
||||
.init(Style(backgroundColor: .white, Edges.equal(to: .parent))),
|
||||
StackView.node(.init(
|
||||
axis: .vertical,
|
||||
distribution: .fillEqually,
|
||||
Edges.equal(to: .parent)
|
||||
), [
|
||||
Button.node(.init(
|
||||
onPress: Handler { props.isPresented.set(false) }
|
||||
), "Close Modal"),
|
||||
Slider.node(.init(
|
||||
value: left.value,
|
||||
valueHandler: Handler(left.set),
|
||||
Style(Width.equal(to: .parent))
|
||||
)),
|
||||
|
||||
View.node(
|
||||
.init(Style(backgroundColor: .red)),
|
||||
Label.node(.init(
|
||||
alignment: .center,
|
||||
textColor: .white,
|
||||
Style(Left.equal(to: .parent, constant: Double(left.value) * 200))
|
||||
), "\(left.value)")
|
||||
),
|
||||
])
|
||||
)
|
||||
) : Null.node()
|
||||
}
|
||||
}
|
||||
|
||||
struct DatePickerModal: LeafComponent {
|
||||
struct Props: Equatable {
|
||||
let isPresented: State<Bool>
|
||||
}
|
||||
|
||||
static func render(props: Props, hooks: Hooks) -> AnyNode {
|
||||
let currentDateTime = Date()
|
||||
let date = hooks.state(currentDateTime)
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.dateStyle = .medium
|
||||
dateFormatter.timeStyle = .medium
|
||||
let formattedDate = dateFormatter.string(from: date.value)
|
||||
return props.isPresented.value ? ModalPresenter.node(
|
||||
View.node(
|
||||
.init(Style(backgroundColor: .white, Edges.equal(to: .parent))),
|
||||
StackView.node(.init(
|
||||
axis: .vertical,
|
||||
distribution: .fillEqually,
|
||||
Edges.equal(to: .parent)
|
||||
), [
|
||||
Button.node(.init(
|
||||
onPress: Handler { props.isPresented.set(false) }
|
||||
), "Close Modal"),
|
||||
Label.node(
|
||||
.init(alignment: .center),
|
||||
"\(formattedDate)"
|
||||
),
|
||||
DatePicker.node(
|
||||
.init(
|
||||
value: date.value,
|
||||
valueHandler: Handler(date.set),
|
||||
Style(Width.equal(to: .parent))
|
||||
)
|
||||
),
|
||||
DatePicker.node(
|
||||
.init(
|
||||
isAnimated: false,
|
||||
value: date.value,
|
||||
valueHandler: Handler(date.set),
|
||||
Style(Width.equal(to: .parent))
|
||||
)
|
||||
),
|
||||
])
|
||||
)
|
||||
) : Null.node()
|
||||
}
|
||||
}
|
||||
|
||||
struct CALayerModal: LeafComponent {
|
||||
struct Props: Equatable {
|
||||
let isPresented: State<Bool>
|
||||
}
|
||||
|
||||
static func render(props: Props, hooks: Hooks) -> AnyNode {
|
||||
let state = hooks.state(0.5 as Float)
|
||||
|
||||
return props.isPresented.value ? ModalPresenter.node(
|
||||
View.node(
|
||||
.init(Style(backgroundColor: .white, Edges.equal(to: .parent))),
|
||||
StackView.node(.init(
|
||||
axis: .vertical,
|
||||
distribution: .fillEqually,
|
||||
Edges.equal(to: .parent)
|
||||
), [
|
||||
Button.node(.init(
|
||||
onPress: Handler { props.isPresented.set(false) }
|
||||
), "Close Modal"),
|
||||
Slider.node(.init(
|
||||
value: state.value,
|
||||
valueHandler: Handler(state.set),
|
||||
Style(Width.equal(to: .parent))
|
||||
)),
|
||||
|
||||
View.node(
|
||||
.init(
|
||||
Style(
|
||||
backgroundColor: .red,
|
||||
borderWidth: Float(state.value * 10),
|
||||
cornerRadius: Float(state.value * 10),
|
||||
opacity: Float(state.value),
|
||||
Width.equal(to: .parent)
|
||||
)
|
||||
),
|
||||
Label.node(.init(
|
||||
alignment: .center,
|
||||
textColor: .white,
|
||||
Style(
|
||||
[Top.equal(to: .parent, constant: Double(state.value) * 100),
|
||||
Left.equal(to: .parent, constant: Double(state.value) * 200)]
|
||||
)
|
||||
), "\(state.value)")
|
||||
),
|
||||
])
|
||||
)
|
||||
) : Null.node()
|
||||
}
|
||||
}
|
||||
|
||||
struct Counter: LeafComponent {
|
||||
struct Props: Equatable {
|
||||
let initial: Int
|
||||
}
|
||||
|
||||
static func render(props: Props, hooks: Hooks) -> AnyNode {
|
||||
let count = hooks.state(props.initial)
|
||||
let sliding = hooks.state(0.5 as Float)
|
||||
let isStackModalPresented = hooks.state(false)
|
||||
let isAnimationModalPresented = hooks.state(false)
|
||||
let isTableModalPresented = hooks.state(false)
|
||||
let isConstraintModalPresented = hooks.state(false)
|
||||
let isDatePickerModalPresented = hooks.state(false)
|
||||
let isCALayerModalPresented = hooks.state(false)
|
||||
let switchState = hooks.state(true)
|
||||
let stepperState = hooks.state(0.0)
|
||||
let isEnabled = hooks.state(true)
|
||||
|
||||
let children = [
|
||||
StackView.node(
|
||||
.init(
|
||||
alignment: .center,
|
||||
axis: .horizontal,
|
||||
spacing: 10.0
|
||||
), [
|
||||
Switch.node(
|
||||
.init(
|
||||
value: isEnabled.value,
|
||||
valueHandler: Handler(isEnabled.set)
|
||||
)
|
||||
),
|
||||
|
||||
Label.node(
|
||||
.init(alignment: .center),
|
||||
"isEnabled \(isEnabled.value)"
|
||||
),
|
||||
]
|
||||
),
|
||||
|
||||
Button.node(
|
||||
.init(
|
||||
isEnabled: isEnabled.value,
|
||||
onPress: Handler { isStackModalPresented.set(true) }
|
||||
),
|
||||
"Present Navigation Modal"
|
||||
),
|
||||
|
||||
Button.node(
|
||||
.init(
|
||||
isEnabled: isEnabled.value,
|
||||
onPress: Handler { isAnimationModalPresented.set(true) }
|
||||
),
|
||||
"Present Simple Modal"
|
||||
),
|
||||
|
||||
Button.node(
|
||||
.init(
|
||||
isEnabled: isEnabled.value,
|
||||
onPress: Handler { isTableModalPresented.set(true) }
|
||||
),
|
||||
"Present Table Modal"
|
||||
),
|
||||
|
||||
Button.node(
|
||||
.init(
|
||||
isEnabled: isEnabled.value,
|
||||
onPress: Handler { isConstraintModalPresented.set(true) }
|
||||
),
|
||||
"Present Constraint Modal"
|
||||
),
|
||||
|
||||
Button.node(
|
||||
.init(
|
||||
isEnabled: isEnabled.value,
|
||||
onPress: Handler { isDatePickerModalPresented.set(true) }
|
||||
),
|
||||
"Present DatePicker Modal"
|
||||
),
|
||||
|
||||
Button.node(
|
||||
.init(
|
||||
isEnabled: isEnabled.value,
|
||||
onPress: Handler { isCALayerModalPresented.set(true) }
|
||||
),
|
||||
"Present Core Animation Layer Modal"
|
||||
),
|
||||
|
||||
NavigationModal.node(.init(isPresented: isStackModalPresented)),
|
||||
|
||||
SimpleModal.node(.init(isPresented: isAnimationModalPresented)),
|
||||
|
||||
TableModal.node(.init(isPresented: isTableModalPresented)),
|
||||
|
||||
ConstraintModal.node(.init(isPresented: isConstraintModalPresented)),
|
||||
|
||||
DatePickerModal.node(.init(isPresented: isDatePickerModalPresented)),
|
||||
|
||||
CALayerModal.node(.init(isPresented: isCALayerModalPresented)),
|
||||
] + (count.value < 15 ? [
|
||||
StackView.node(
|
||||
.init(
|
||||
alignment: .center,
|
||||
axis: .horizontal,
|
||||
spacing: 10.0
|
||||
), [
|
||||
Button.node(
|
||||
.init(
|
||||
isEnabled: isEnabled.value,
|
||||
onPress: Handler { count.set { $0 + 1 } }
|
||||
),
|
||||
"Increment"
|
||||
),
|
||||
|
||||
Label.node(.init(alignment: .center), "\(count.value)"),
|
||||
]
|
||||
),
|
||||
|
||||
Slider.node(.init(
|
||||
isEnabled: isEnabled.value,
|
||||
value: sliding.value,
|
||||
valueHandler: Handler(sliding.set),
|
||||
Style(Width.equal(to: .parent))
|
||||
)),
|
||||
|
||||
Label.node(.init(alignment: .center), "\(sliding.value)"),
|
||||
|
||||
StackView.node(
|
||||
.init(
|
||||
alignment: .center,
|
||||
axis: .horizontal,
|
||||
spacing: 10.0
|
||||
), [
|
||||
Switch.node(
|
||||
.init(
|
||||
isEnabled: isEnabled.value,
|
||||
value: switchState.value,
|
||||
valueHandler: Handler(switchState.set)
|
||||
)
|
||||
),
|
||||
|
||||
Label.node(.init(alignment: .center), "\(switchState.value)"),
|
||||
]
|
||||
),
|
||||
|
||||
StackView.node(
|
||||
.init(
|
||||
alignment: .center,
|
||||
axis: .horizontal,
|
||||
spacing: 10.0
|
||||
), [
|
||||
Stepper.node(
|
||||
.init(
|
||||
isEnabled: isEnabled.value,
|
||||
value: stepperState.value,
|
||||
valueHandler: Handler(stepperState.set)
|
||||
)
|
||||
),
|
||||
|
||||
Label.node(.init(alignment: .center), "\(stepperState.value)"),
|
||||
]
|
||||
),
|
||||
] : [])
|
||||
|
||||
return StackView.node(
|
||||
.init(
|
||||
alignment: .center,
|
||||
axis: .vertical,
|
||||
distribution: .fillEqually,
|
||||
Edges.equal(to: .parent)
|
||||
),
|
||||
children
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
struct App: PureLeafComponent {
|
||||
typealias Props = Null
|
||||
|
||||
static func render(props _: Props) -> AnyNode {
|
||||
return Counter.node(.init(initial: 1))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// RootRouter.swift
|
||||
// Gluon_Example
|
||||
//
|
||||
// Created by Max Desiatov on 14/02/2019.
|
||||
// Copyright © 2019 Gluon. All rights reserved.
|
||||
//
|
||||
|
||||
import Gluon
|
||||
|
||||
enum AppRoute: String, CaseIterable {
|
||||
case list = "Examples"
|
||||
case counter
|
||||
case controls
|
||||
case constraints = "Auto Layout Constraints"
|
||||
case modals = "Modal Presentation"
|
||||
case datePicker = "Date Picker"
|
||||
case layerProps = "Layer Props"
|
||||
}
|
||||
|
||||
extension AppRoute: CustomStringConvertible {
|
||||
var description: String { return rawValue.localizedCapitalized }
|
||||
}
|
||||
|
||||
struct Router: NavigationRouter {
|
||||
typealias Route = AppRoute
|
||||
typealias Props = Null
|
||||
|
||||
static func route(
|
||||
props: Null,
|
||||
route: AppRoute,
|
||||
push: @escaping (AppRoute) -> (),
|
||||
pop: @escaping () -> (),
|
||||
hooks: Hooks
|
||||
) -> AnyNode {
|
||||
let result: AnyNode
|
||||
switch route {
|
||||
case .list:
|
||||
let model = AppRoute.allCases.filter { $0 != .list }
|
||||
result = List.node(.init(
|
||||
model: model,
|
||||
onSelect: Handler { push(model[$0.item]) }
|
||||
))
|
||||
case .counter:
|
||||
result = Counter.node(.init(countFrom: 1))
|
||||
case .controls:
|
||||
result = Controls.node()
|
||||
case .constraints:
|
||||
result = Constraints.node()
|
||||
case .modals:
|
||||
result = Modals.node()
|
||||
case .datePicker:
|
||||
result = DatePickers.node()
|
||||
case .layerProps:
|
||||
result = LayerProps.node()
|
||||
}
|
||||
|
||||
return NavigationItem.node(
|
||||
.init(title: route.description),
|
||||
View.node(
|
||||
.init(Style(backgroundColor: .white, Edges.equal(to: .parent))),
|
||||
result
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ import UIKit
|
|||
|
||||
final class ViewController: GluonViewController {
|
||||
override var node: AnyNode {
|
||||
return App.node()
|
||||
return NavigationPresenter<Router>.node(.init(initial: .list))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,6 +75,8 @@
|
|||
D1EF77812208AEF5008829EC /* NavigationItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1EF77802208AEF5008829EC /* NavigationItem.swift */; };
|
||||
D1EF77852208BB10008829EC /* TabItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1EF77842208BB10008829EC /* TabItem.swift */; };
|
||||
D1EF77862208BB13008829EC /* NavigationItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1EF77822208BAF6008829EC /* NavigationItem.swift */; };
|
||||
D1F718592215A074004E5951 /* LineBreakMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1F718582215A073004E5951 /* LineBreakMode.swift */; };
|
||||
D1F7185B2215A116004E5951 /* LineBreakMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1F7185A2215A116004E5951 /* LineBreakMode.swift */; };
|
||||
OBJ_100 /* Animated.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_48 /* Animated.swift */; };
|
||||
OBJ_101 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_49 /* Button.swift */; };
|
||||
OBJ_102 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_50 /* Label.swift */; };
|
||||
|
@ -229,6 +231,8 @@
|
|||
D1EF77802208AEF5008829EC /* NavigationItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItem.swift; sourceTree = "<group>"; };
|
||||
D1EF77822208BAF6008829EC /* NavigationItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItem.swift; sourceTree = "<group>"; };
|
||||
D1EF77842208BB10008829EC /* TabItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabItem.swift; sourceTree = "<group>"; };
|
||||
D1F718582215A073004E5951 /* LineBreakMode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LineBreakMode.swift; sourceTree = "<group>"; };
|
||||
D1F7185A2215A116004E5951 /* LineBreakMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineBreakMode.swift; sourceTree = "<group>"; };
|
||||
"Gluon::Gluon::Product" /* Gluon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Gluon.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
"Gluon::GluonTestRenderer::Product" /* GluonTestRenderer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = GluonTestRenderer.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
"Gluon::GluonTests::Product" /* GluonTests.xctest */ = {isa = PBXFileReference; lastKnownFileType = file; path = GluonTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
@ -453,6 +457,7 @@
|
|||
OBJ_20 /* Event.swift */,
|
||||
OBJ_21 /* Rectangle.swift */,
|
||||
D1C3A71F21F0C31600C6B884 /* Constraint */,
|
||||
D1F7185A2215A116004E5951 /* LineBreakMode.swift */,
|
||||
);
|
||||
path = Props;
|
||||
sourceTree = "<group>";
|
||||
|
@ -547,11 +552,12 @@
|
|||
D1EF77502205C579008829EC /* Constraint */,
|
||||
OBJ_58 /* Color.swift */,
|
||||
OBJ_59 /* Event.swift */,
|
||||
D1C3A72221F0DC6300C6B884 /* Insets.swift */,
|
||||
D1F718582215A073004E5951 /* LineBreakMode.swift */,
|
||||
OBJ_60 /* Rectangle.swift */,
|
||||
OBJ_61 /* Second.swift */,
|
||||
OBJ_62 /* Style.swift */,
|
||||
OBJ_63 /* TextAlignment.swift */,
|
||||
D1C3A72221F0DC6300C6B884 /* Insets.swift */,
|
||||
);
|
||||
path = Props;
|
||||
sourceTree = "<group>";
|
||||
|
@ -809,6 +815,7 @@
|
|||
A633561D21FB5C5400BCC525 /* Right.swift in Sources */,
|
||||
D1EF77792205FD56008829EC /* Constrainable.swift in Sources */,
|
||||
D1EF777D220745AB008829EC /* BaselineConstraint.swift in Sources */,
|
||||
D1F7185B2215A116004E5951 /* LineBreakMode.swift in Sources */,
|
||||
A633562521FB96EE00BCC525 /* CenterX.swift in Sources */,
|
||||
OBJ_176 /* Slider.swift in Sources */,
|
||||
OBJ_177 /* NavigationController.swift in Sources */,
|
||||
|
@ -853,6 +860,7 @@
|
|||
OBJ_101 /* Button.swift in Sources */,
|
||||
OBJ_102 /* Label.swift in Sources */,
|
||||
A62891FF21F5F07F001BE090 /* Stepper.swift in Sources */,
|
||||
D1F718592215A074004E5951 /* LineBreakMode.swift in Sources */,
|
||||
OBJ_104 /* ModalPresenter.swift in Sources */,
|
||||
D1EC92F021F5B8000026C207 /* ListView.swift in Sources */,
|
||||
D1EF77522205C579008829EC /* Constraint.swift in Sources */,
|
||||
|
|
|
@ -12,15 +12,21 @@ public struct Label: HostComponent {
|
|||
}
|
||||
|
||||
public let alignment: TextAlignment
|
||||
public let lineBreakMode: LineBreakMode
|
||||
public let numberOfLines: Int
|
||||
public let style: Style?
|
||||
public let textColor: Color?
|
||||
|
||||
public init(
|
||||
alignment: TextAlignment = .natural,
|
||||
lineBreakMode: LineBreakMode = .truncateTail,
|
||||
numberOfLines: Int = 1,
|
||||
textColor: Color? = nil,
|
||||
_ style: Style? = nil
|
||||
) {
|
||||
self.alignment = alignment
|
||||
self.lineBreakMode = lineBreakMode
|
||||
self.numberOfLines = numberOfLines
|
||||
self.textColor = textColor
|
||||
self.style = style
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
//
|
||||
// LineBreakMode.swift
|
||||
// Gluon
|
||||
//
|
||||
// Created by Max Desiatov on 14/02/2019.
|
||||
//
|
||||
|
||||
public enum LineBreakMode {
|
||||
case wordWrap
|
||||
case charWrap
|
||||
case clip
|
||||
case truncateHead
|
||||
case truncateTail
|
||||
case truncateMiddle
|
||||
}
|
|
@ -37,6 +37,8 @@ extension Label: UIViewComponent {
|
|||
_ children: String) {
|
||||
let view = box.view
|
||||
view.textAlignment = NSTextAlignment(props.alignment)
|
||||
view.numberOfLines = props.numberOfLines
|
||||
view.lineBreakMode = NSLineBreakMode(props.lineBreakMode)
|
||||
props.textColor.flatMap { view.textColor = UIColor($0) }
|
||||
view.text = children
|
||||
}
|
||||
|
|
|
@ -9,6 +9,9 @@ import Gluon
|
|||
import UIKit
|
||||
|
||||
final class GluonNavigationController: UINavigationController {
|
||||
/// Used to prevent calling `onPop` if this navigation view controller is not
|
||||
/// mounted yet
|
||||
var isMounted = false
|
||||
private let onPop: () -> ()
|
||||
|
||||
init(onPop: @escaping () -> ()) {
|
||||
|
@ -24,6 +27,7 @@ final class GluonNavigationController: UINavigationController {
|
|||
override func didMove(toParent parent: UIViewController?) {
|
||||
super.didMove(toParent: parent)
|
||||
|
||||
guard isMounted else { return }
|
||||
onPop()
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +69,14 @@ extension NavigationController: UIHostComponent {
|
|||
animated: props.presentAnimated,
|
||||
completion: nil)
|
||||
}
|
||||
case let box as ViewBox<UIView>:
|
||||
result.viewController.willMove(toParent: box.viewController)
|
||||
// FIXME: replace with constraints
|
||||
result.viewController.view.frame = box.view.frame
|
||||
box.view.addSubview(result.viewController.view)
|
||||
box.viewController.addChild(result.viewController)
|
||||
result.viewController.didMove(toParent: box.viewController)
|
||||
result.containerViewController.isMounted = true
|
||||
default:
|
||||
parentAssertionFailure()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// LineBreakMode.swift
|
||||
// GluonUIKit
|
||||
//
|
||||
// Created by Max Desiatov on 14/02/2019.
|
||||
//
|
||||
|
||||
import Gluon
|
||||
import UIKit
|
||||
|
||||
extension NSLineBreakMode {
|
||||
public init(_ mode: LineBreakMode) {
|
||||
switch mode {
|
||||
case .wordWrap:
|
||||
self = .byWordWrapping
|
||||
case .charWrap:
|
||||
self = .byCharWrapping
|
||||
case .clip:
|
||||
self = .byClipping
|
||||
case .truncateHead:
|
||||
self = .byTruncatingHead
|
||||
case .truncateTail:
|
||||
self = .byTruncatingTail
|
||||
case .truncateMiddle:
|
||||
self = .byTruncatingMiddle
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue