Expose accessibility configuration on view props (#50)

* Rename StyleProps to ViewProps

* Init new argument order

* Init accessibility

* Add Accessibility.swift to project

* Sort Style init arguments

* Reorder arguments in Example

* Add Props init to StackView

* Fix arguments order in test

* Expose accessibility configuration on view props

* Rename ViewProps to StyleProps
This commit is contained in:
matvii 2019-02-22 13:41:44 +02:00 committed by GitHub
parent 25340c6cda
commit a7ce2fab11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 173 additions and 94 deletions

View File

@ -15,22 +15,22 @@ struct Constraints: LeafComponent {
let left = hooks.state(0.5 as Float)
return StackView.node(.init(
Edges.equal(to: .safeArea),
axis: .vertical,
distribution: .fillEqually,
Edges.equal(to: .safeArea)
distribution: .fillEqually
), [
Slider.node(.init(
Style(Width.equal(to: .parent)),
value: left.value,
valueHandler: Handler(left.set),
Style(Width.equal(to: .parent))
valueHandler: Handler(left.set)
)),
View.node(
.init(Style(backgroundColor: .red)),
Label.node(.init(
Style(Left.equal(to: .parent, constant: Double(left.value) * 200)),
alignment: .center,
textColor: .white,
Style(Left.equal(to: .parent, constant: Double(left.value) * 200))
textColor: .white
), "\(left.value)")
),
])

View File

@ -39,10 +39,10 @@ struct Controls: LeafComponent {
),
Slider.node(.init(
Style(Width.equal(to: .parent)),
isEnabled: isEnabled.value,
value: sliding.value,
valueHandler: Handler(sliding.set),
Style(Width.equal(to: .parent))
valueHandler: Handler(sliding.set)
)),
Label.node(.init(alignment: .center), "\(sliding.value)"),
@ -91,10 +91,10 @@ struct Controls: LeafComponent {
return StackView.node(
.init(
Edges.equal(to: .safeArea),
alignment: .center,
axis: .vertical,
distribution: .fillEqually,
Edges.equal(to: .safeArea)
distribution: .fillEqually
),
children
)

View File

@ -17,10 +17,10 @@ struct Counter: LeafComponent {
let count = hooks.state(props.countFrom)
return StackView.node(.init(
Edges.equal(to: .safeArea),
alignment: .center,
axis: .vertical,
distribution: .fillEqually,
Edges.equal(to: .safeArea)
distribution: .fillEqually
), [
Button.node(
.init(onPress: Handler { count.set { $0 + 1 } }),

View File

@ -25,9 +25,9 @@ struct DatePickers: LeafComponent {
)
return StackView.node(.init(
Edges.equal(to: .safeArea),
axis: .vertical,
distribution: .fillEqually,
Edges.equal(to: .safeArea)
distribution: .fillEqually
), [
Label.node(
labelProps,
@ -39,9 +39,9 @@ struct DatePickers: LeafComponent {
),
DatePicker.node(
.init(
Style(Width.equal(to: .parent)),
value: date.value,
valueHandler: Handler(date.set),
Style(Width.equal(to: .parent))
valueHandler: Handler(date.set)
)
),
Label.node(
@ -50,10 +50,10 @@ struct DatePickers: LeafComponent {
),
DatePicker.node(
.init(
Style(Width.equal(to: .parent)),
isAnimated: false,
value: date.value,
valueHandler: Handler(date.set),
Style(Width.equal(to: .parent))
valueHandler: Handler(date.set)
)
),
])

View File

@ -13,12 +13,15 @@ struct ImageExample: PureLeafComponent {
static func render(props _: Null) -> AnyNode {
return StackView.node(.init(
Edges.equal(to: .safeArea),
alignment: .center,
axis: .vertical,
distribution: .fillEqually,
Edges.equal(to: .safeArea)
distribution: .fillEqually
), [
Image.node(.init(name: "tokamak", Style(contentMode: .scaleAspectFit))),
Image.node(.init(
Style(contentMode: .scaleAspectFit),
name: "tokamak"
)),
])
}
}

View File

@ -16,33 +16,33 @@ struct LayerProps: LeafComponent {
return
StackView.node(.init(
Edges.equal(to: .safeArea),
axis: .vertical,
distribution: .fillEqually,
Edges.equal(to: .safeArea)
distribution: .fillEqually
), [
Slider.node(.init(
Style(Width.equal(to: .parent)),
value: state.value,
valueHandler: Handler(state.set),
Style(Width.equal(to: .parent))
valueHandler: Handler(state.set)
)),
View.node(
.init(
Style(
Width.equal(to: .parent),
backgroundColor: .red,
borderWidth: Float(state.value * 10),
cornerRadius: Float(state.value * 10),
opacity: Float(state.value),
Width.equal(to: .parent)
opacity: Float(state.value)
)
),
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)]
)
),
alignment: .center,
textColor: .white
), "\(state.value)")
),
])

View File

@ -34,11 +34,11 @@ struct List: PureLeafComponent {
static func render(props: Props) -> AnyNode {
return ListView<Cells>.node(.init(
model: [props.model],
onSelect: props.onSelect,
Style([
Edges.equal(to: .parent),
])
]),
model: [props.model],
onSelect: props.onSelect
))
}
}

View File

@ -27,8 +27,8 @@ struct ModalRouter: NavigationRouter {
) -> AnyNode {
let close =
Button.node(.init(
onPress: props.onPress,
Style(Rectangle(.zero, Size(width: 200, height: 200)))
Style(Rectangle(.zero, Size(width: 200, height: 200))),
onPress: props.onPress
), "Close Modal")
switch route {
case .first:
@ -36,12 +36,13 @@ struct ModalRouter: NavigationRouter {
NavigationItem.node(
.init(title: "First", titleMode: .standard),
View.node(
.init(Style(backgroundColor: .white, Edges.equal(to: .parent))), [
.init(Style(Edges.equal(to: .parent), backgroundColor: .white)), [
close,
Button.node(.init(
onPress: Handler { push(.second) },
Style(Rectangle(Point(x: 0, y: 400),
Size(width: 200, height: 200)))
Size(width: 200, height: 200))),
onPress: Handler { push(.second) }
), "Go to Second"),
]
)
@ -51,12 +52,12 @@ struct ModalRouter: NavigationRouter {
NavigationItem.node(
.init(title: "Second", titleMode: .large),
View.node(
.init(Style(backgroundColor: .white, Edges.equal(to: .parent))), [
.init(Style(Edges.equal(to: .parent), backgroundColor: .white)), [
close,
Label.node(.init(
alignment: .center,
Style(Rectangle(Point(x: 0, y: 200),
Size(width: 200, height: 200)))
Size(width: 200, height: 200))),
alignment: .center
), "This is second"),
]
)

View File

@ -47,13 +47,13 @@ struct SimpleModal: LeafComponent {
return props.isPresented.value ? ModalPresenter.node(
View.node(
.init(Style(
backgroundColor: colors[backgroundColor.value].0,
Edges.equal(to: .parent)
Edges.equal(to: .parent),
backgroundColor: colors[backgroundColor.value].0
)),
StackView.node(.init(
Edges.equal(to: .parent),
axis: .vertical,
distribution: .fillEqually,
Edges.equal(to: .parent)
distribution: .fillEqually
), [
Button.node(.init(
onPress: Handler { props.isPresented.set(false) }
@ -79,10 +79,10 @@ struct Modals: LeafComponent {
return StackView.node(
.init(
Edges.equal(to: .safeArea),
alignment: .center,
axis: .vertical,
distribution: .fillEqually,
Edges.equal(to: .safeArea)
distribution: .fillEqually
),
[
Button.node(

View File

@ -39,16 +39,16 @@ struct TableRouter: NavigationRouter {
return NavigationItem.node(
.init(title: "Table"),
ListView<ListProvider>.node(.init(
Style(Edges.equal(to: .parent)),
onSelect: Handler { push(.value($0.item + 1)) },
singleSection: [1, 2, 3],
Style(Edges.equal(to: .parent))
singleSection: [1, 2, 3]
))
)
case let .value(v):
return View.node(
.init(Style(
backgroundColor: .white,
Edges.equal(to: .parent)
Edges.equal(to: .parent),
backgroundColor: .white
)),
Label.node(
.init(Style(Center.equal(to: .parent))),

View File

@ -31,10 +31,10 @@ struct TimerCounter: LeafComponent {
return StackView.node(
.init(
Edges.equal(to: .safeArea),
alignment: .center,
axis: .vertical,
distribution: .fillEqually,
Edges.equal(to: .safeArea)
distribution: .fillEqually
), [
Label.node(
.init(alignment: .center),

View File

@ -64,7 +64,7 @@ struct Router: NavigationRouter {
return NavigationItem.node(
.init(title: route.description),
View.node(
.init(Style(backgroundColor: .white, Edges.equal(to: .parent))),
.init(Style(Edges.equal(to: .parent), backgroundColor: .white)),
result
)
)

View File

@ -17,11 +17,11 @@ public struct Button: HostComponent {
public let isEnabled: Bool
public init(
_ style: Style? = nil,
handlers: [Event: Handler<()>] = [:],
isEnabled: Bool = true,
onPress: Handler<()>? = nil,
titleColor: Color? = nil,
_ style: Style? = nil
titleColor: Color? = nil
) {
var handlers = handlers
if let onPress = onPress {

View File

@ -18,12 +18,12 @@ public struct DatePicker: HostComponent {
public let isAnimated: Bool
public init(
_ style: Style? = nil,
handlers: EventHandlers = [:],
isAnimated: Bool = true,
isEnabled: Bool = true,
value: Date,
valueHandler: Handler<Date>? = nil,
_ style: Style? = nil
valueHandler: Handler<Date>? = nil
) {
self.handlers = handlers
self.style = style

View File

@ -38,11 +38,11 @@ public struct Image: HostComponent {
public let style: Style?
public init(
_ style: Style? = nil,
flipsForRTL: Bool = false,
name: String,
renderingMode: RenderingMode = .automatic,
scale: Double = 1.0,
_ style: Style? = nil
scale: Double = 1.0
) {
source = .name(name)
self.renderingMode = renderingMode
@ -52,11 +52,11 @@ public struct Image: HostComponent {
}
public init(
_ style: Style? = nil,
data: Data,
flipsForRTL: Bool = false,
renderingMode: RenderingMode = .automatic,
scale: Double = 1.0,
_ style: Style? = nil
scale: Double = 1.0
) {
source = .data(data)
self.renderingMode = renderingMode

View File

@ -18,11 +18,11 @@ public struct Label: HostComponent {
public let textColor: Color?
public init(
_ style: Style? = nil,
alignment: TextAlignment = .natural,
lineBreakMode: LineBreakMode = .truncateTail,
numberOfLines: Int = 1,
textColor: Color? = nil,
_ style: Style? = nil
textColor: Color? = nil
) {
self.alignment = alignment
self.lineBreakMode = lineBreakMode

View File

@ -77,10 +77,10 @@ public struct ListView<T: CellProvider>: HostComponent {
public let style: Style?
public init(
_ style: Style? = nil,
cellProps: T.Props,
onSelect: Handler<CellPath>? = nil,
singleSection: T.Model.Element,
_ style: Style? = nil
singleSection: T.Model.Element
) {
self.cellProps = cellProps
model = T.Model.single(section: singleSection)
@ -89,10 +89,10 @@ public struct ListView<T: CellProvider>: HostComponent {
}
public init(
_ style: Style? = nil,
cellProps: T.Props,
onSelect: Handler<CellPath>? = nil,
model: T.Model,
_ style: Style? = nil
onSelect: Handler<CellPath>? = nil
) {
self.cellProps = cellProps
self.model = model
@ -106,9 +106,9 @@ public struct ListView<T: CellProvider>: HostComponent {
extension ListView.Props where T.Props == Null {
public init(
_ style: Style? = nil,
model: T.Model,
onSelect: Handler<CellPath>? = nil,
_ style: Style? = nil
onSelect: Handler<CellPath>? = nil
) {
cellProps = Null()
self.model = model
@ -117,9 +117,9 @@ extension ListView.Props where T.Props == Null {
}
public init(
_ style: Style? = nil,
onSelect: Handler<CellPath>? = nil,
singleSection: T.Model.Element,
_ style: Style? = nil
singleSection: T.Model.Element
) {
cellProps = Null()
model = T.Model.single(section: singleSection)

View File

@ -15,11 +15,11 @@ public struct SegmentedControl: HostComponent {
public let isEnabled: Bool
public init(
_ style: Style? = nil,
handlers: EventHandlers = [:],
isEnabled: Bool = true,
value: Int,
valueHandler: Handler<Int>? = nil,
_ style: Style? = nil
valueHandler: Handler<Int>? = nil
) {
self.handlers = handlers
self.style = style

View File

@ -15,11 +15,11 @@ public struct Slider: HostComponent {
public let isEnabled: Bool
public init(
_ style: Style? = nil,
handlers: EventHandlers = [:],
isEnabled: Bool = true,
value: Float,
valueHandler: Handler<Float>? = nil,
_ style: Style? = nil
valueHandler: Handler<Float>? = nil
) {
self.handlers = handlers
self.style = style

View File

@ -42,11 +42,11 @@ public struct StackView: HostComponent {
public let style: Style?
public init(
_ frame: Rectangle,
alignment: Alignment = .fill,
axis: Axis = .horizontal,
distribution: Distribution = .fill,
spacing: Double = 0,
_ frame: Rectangle
spacing: Double = 0
) {
self.alignment = alignment
self.axis = axis
@ -56,11 +56,11 @@ public struct StackView: HostComponent {
}
public init(
_ constraint: Constraint,
alignment: Alignment = .fill,
axis: Axis = .horizontal,
distribution: Distribution = .fill,
spacing: Double = 0,
_ constraint: Constraint
spacing: Double = 0
) {
self.alignment = alignment
self.axis = axis
@ -69,6 +69,20 @@ public struct StackView: HostComponent {
self.spacing = spacing
}
public init(
_ constraints: [Constraint],
alignment: Alignment = .fill,
axis: Axis = .horizontal,
distribution: Distribution = .fill,
spacing: Double = 0
) {
self.alignment = alignment
self.axis = axis
self.distribution = distribution
style = Style(constraints)
self.spacing = spacing
}
public init(
alignment: Alignment = .fill,
axis: Axis = .horizontal,

View File

@ -20,6 +20,7 @@ public struct Stepper: HostComponent {
public let style: Style?
public init(
_ style: Style? = nil,
autorepeat: Bool = true,
handlers: EventHandlers = [:],
isEnabled: Bool = true,
@ -28,8 +29,7 @@ public struct Stepper: HostComponent {
stepValue: Double = 1.0,
value: Double,
valueHandler: Handler<Double>? = nil,
wraps: Bool = false,
_ style: Style? = nil
wraps: Bool = false
) {
self.autorepeat = autorepeat
self.handlers = handlers

View File

@ -16,12 +16,12 @@ public struct Switch: HostComponent {
public let isAnimated: Bool
public init(
_ style: Style? = nil,
handlers: EventHandlers = [:],
isAnimated: Bool = true,
isEnabled: Bool = true,
value: Bool,
valueHandler: Handler<Bool>? = nil,
_ style: Style? = nil
valueHandler: Handler<Bool>? = nil
) {
self.handlers = handlers
self.style = style

View File

@ -0,0 +1,34 @@
//
// Accessibility.swift
// Tokamak
//
// Created by Matvii Hodovaniuk on 2/21/19.
//
public struct Accessibility: Equatable {
public let identifier: String?
public let language: String?
public let label: String?
public let hint: String?
public let value: String?
public let elementsHidden: Bool
public let isModal: Bool
public init(
elementsHidden: Bool = false,
hint: String? = nil,
isModal: Bool = false,
label: String? = "",
language: String? = nil,
value: String? = "",
identifier: String? = ""
) {
self.elementsHidden = elementsHidden
self.hint = hint
self.isModal = isModal
self.label = label
self.language = language
self.value = value
self.identifier = identifier
}
}

View File

@ -30,6 +30,7 @@ public enum ContentMode {
}
public struct Style: Equatable {
public let accessibility: Accessibility?
public let allowsEdgeAntialiasing: Bool?
public let allowsGroupOpacity: Bool?
public let alpha: Double?
@ -50,6 +51,7 @@ public struct Style: Equatable {
public let layout: Layout?
public init(
accessibility: Accessibility? = nil,
allowsEdgeAntialiasing: Bool? = false,
allowsGroupOpacity: Bool? = true,
alpha: Double? = nil,
@ -68,6 +70,7 @@ public struct Style: Equatable {
shadowOpacity: Float? = 0.0,
shadowRadius: Float? = 3.0
) {
self.accessibility = accessibility
self.allowsEdgeAntialiasing = allowsEdgeAntialiasing
self.allowsGroupOpacity = allowsGroupOpacity
self.alpha = alpha
@ -90,6 +93,8 @@ public struct Style: Equatable {
}
public init(
_ frame: Rectangle,
accessibility: Accessibility? = nil,
allowsEdgeAntialiasing: Bool? = false,
allowsGroupOpacity: Bool? = true,
alpha: Double? = nil,
@ -106,9 +111,9 @@ public struct Style: Equatable {
opacity: Float? = 1.0,
shadowColor: Color? = nil,
shadowOpacity: Float? = 0.0,
shadowRadius: Float? = 3.0,
_ frame: Rectangle
shadowRadius: Float? = 3.0
) {
self.accessibility = accessibility
self.allowsEdgeAntialiasing = allowsEdgeAntialiasing
self.allowsGroupOpacity = allowsGroupOpacity
self.alpha = alpha
@ -131,6 +136,8 @@ public struct Style: Equatable {
}
public init(
_ constraint: Constraint,
accessibility: Accessibility? = nil,
allowsEdgeAntialiasing: Bool? = false,
allowsGroupOpacity: Bool? = true,
alpha: Double? = nil,
@ -147,9 +154,9 @@ public struct Style: Equatable {
opacity: Float? = 1.0,
shadowColor: Color? = nil,
shadowOpacity: Float? = 0.0,
shadowRadius: Float? = 3.0,
_ constraint: Constraint
shadowRadius: Float? = 3.0
) {
self.accessibility = accessibility
self.allowsEdgeAntialiasing = allowsEdgeAntialiasing
self.allowsGroupOpacity = allowsGroupOpacity
self.alpha = alpha
@ -172,6 +179,8 @@ public struct Style: Equatable {
}
public init(
_ constraints: [Constraint],
accessibility: Accessibility? = nil,
allowsEdgeAntialiasing: Bool? = false,
allowsGroupOpacity: Bool? = true,
alpha: Double? = nil,
@ -188,9 +197,9 @@ public struct Style: Equatable {
opacity: Float? = 1.0,
shadowColor: Color? = nil,
shadowOpacity: Float? = 0.0,
shadowRadius: Float? = 3.0,
_ constraints: [Constraint]
shadowRadius: Float? = 3.0
) {
self.accessibility = accessibility
self.allowsEdgeAntialiasing = allowsEdgeAntialiasing
self.allowsGroupOpacity = allowsGroupOpacity
self.alpha = alpha

View File

@ -63,6 +63,16 @@ private func applyStyle<T: UIView, P: StyleProps>(_ target: ViewBox<T>,
()
}
style.accessibility.flatMap {
view.accessibilityElementsHidden = $0.elementsHidden
view.accessibilityHint = $0.hint
view.accessibilityViewIsModal = $0.isModal
view.accessibilityLabel = $0.label
view.accessibilityLanguage = $0.language
view.accessibilityValue = $0.value
view.accessibilityIdentifier = $0.identifier
}
// center has to be updated after `frame`, otherwise `frame` overrides it
style.center.flatMap { view.center = CGPoint($0) }
style.isHidden.flatMap { view.isHidden = $0 }

View File

@ -31,10 +31,14 @@ struct Counter: LeafComponent {
Label.node(.init(), "\(sliding.value)"),
] : []
return StackView.node(.init(axis: .vertical,
distribution: .fillEqually,
Edges.equal(to: .parent)),
children)
return StackView.node(
.init(
Edges.equal(to: .parent),
axis: .vertical,
distribution: .fillEqually
),
children
)
}
}

View File

@ -22,6 +22,7 @@
/* Begin PBXBuildFile section */
A6AB60B5221C70340063F88A /* ContentMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AB60B4221C70340063F88A /* ContentMode.swift */; };
A6D188EC221F1CA300C3947C /* Accessibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6D188EB221F1CA300C3947C /* Accessibility.swift */; };
D1B4F8DB221AFB0E00C53C42 /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1B4F8D9221AFB0800C53C42 /* Image.swift */; };
D1B4F8DD221AFB2B00C53C42 /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1B4F8DC221AFB2B00C53C42 /* Image.swift */; };
OBJ_153 /* AnyEquatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_66 /* AnyEquatable.swift */; };
@ -184,6 +185,7 @@
/* Begin PBXFileReference section */
A6AB60B4221C70340063F88A /* ContentMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentMode.swift; sourceTree = "<group>"; };
A6D188EB221F1CA300C3947C /* Accessibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Accessibility.swift; sourceTree = "<group>"; };
D1B4F8D9221AFB0800C53C42 /* Image.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = "<group>"; };
D1B4F8DC221AFB2B00C53C42 /* Image.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = "<group>"; };
OBJ_10 /* ContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerViewController.swift; sourceTree = "<group>"; };
@ -614,6 +616,7 @@
OBJ_114 /* Second.swift */,
OBJ_115 /* Style.swift */,
OBJ_116 /* TextAlignment.swift */,
A6D188EB221F1CA300C3947C /* Accessibility.swift */,
);
path = Props;
sourceTree = "<group>";
@ -787,6 +790,7 @@
OBJ_176 /* Bottom.swift in Sources */,
OBJ_177 /* Center.swift in Sources */,
D1B4F8DD221AFB2B00C53C42 /* Image.swift in Sources */,
A6D188EC221F1CA300C3947C /* Accessibility.swift in Sources */,
OBJ_178 /* CenterX.swift in Sources */,
OBJ_179 /* CenterY.swift in Sources */,
OBJ_180 /* Constraint.swift in Sources */,