Add ScrollView (#128)
* Add ScrollView * Root styles for ScrollView and Stack
This commit is contained in:
parent
0e910756c0
commit
98a107f7fe
|
@ -0,0 +1,31 @@
|
|||
// Copyright 2020 Tokamak contributors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Created by Carson Katri on 06/29/2020.
|
||||
//
|
||||
|
||||
public enum Axis: Int8, CaseIterable {
|
||||
case horizontal
|
||||
case vertical
|
||||
|
||||
public struct Set: OptionSet {
|
||||
public let rawValue: Int8
|
||||
public init(rawValue: Int8) {
|
||||
self.rawValue = rawValue
|
||||
}
|
||||
|
||||
public static let horizontal: Axis.Set = .init(rawValue: 1 << 0)
|
||||
public static let vertical: Axis.Set = .init(rawValue: 1 << 1)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2020 Tokamak contributors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Created by Carson Katri on 06/29/2020.
|
||||
//
|
||||
|
||||
public struct ScrollView<Content>: View where Content: View {
|
||||
public let content: Content
|
||||
public let axes: Axis.Set
|
||||
public let showsIndicators: Bool
|
||||
|
||||
public init(_ axes: Axis.Set = .vertical, showsIndicators: Bool = true, @ViewBuilder content: () -> Content) {
|
||||
self.axes = axes
|
||||
self.showsIndicators = showsIndicators
|
||||
self.content = content()
|
||||
}
|
||||
|
||||
public var body: Never {
|
||||
neverBody("ScrollView")
|
||||
}
|
||||
}
|
||||
|
||||
extension ScrollView: ParentView {
|
||||
public var children: [AnyView] {
|
||||
(content as? GroupView)?.children ?? [AnyView(content)]
|
||||
}
|
||||
}
|
|
@ -49,6 +49,8 @@ public final class DOMNode: Target {
|
|||
}
|
||||
|
||||
let log = JSObjectRef.global.console.object!.log.function!
|
||||
let document = JSObjectRef.global.document.object!
|
||||
let head = document.head.object!
|
||||
|
||||
public final class DOMRenderer: Renderer {
|
||||
public private(set) var reconciler: StackReconciler<DOMRenderer>?
|
||||
|
@ -57,7 +59,12 @@ public final class DOMRenderer: Renderer {
|
|||
|
||||
public init<V: View>(_ view: V, _ ref: JSObjectRef) {
|
||||
rootRef = ref
|
||||
rootRef.style = "display: flex; width: 100%; height: 100%; justify-content: center; align-items: center;"
|
||||
rootRef.style = "display: flex; width: 100%; height: 100%; justify-content: center; align-items: center; overflow: hidden;"
|
||||
|
||||
let rootStyle = document.createElement!("style").object!
|
||||
rootStyle.innerHTML = .string(tokamakStyles)
|
||||
_ = head.appendChild!(rootStyle)
|
||||
|
||||
reconciler = StackReconciler(
|
||||
view: view,
|
||||
target: DOMNode(view, ref),
|
||||
|
|
|
@ -32,6 +32,8 @@ extension _FrameLayout: DOMViewModifier {
|
|||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
"""]
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +50,8 @@ extension _FlexFrameLayout: DOMViewModifier {
|
|||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
"""]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2020 Tokamak contributors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
let tokamakStyles = """
|
||||
._tokamak-stack > * {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
._tokamak-scrollview-hideindicators {
|
||||
scrollbar-color: transparent;
|
||||
scrollbar-width: 0;
|
||||
}
|
||||
._tokamak-scrollview-hideindicators::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
"""
|
|
@ -39,6 +39,7 @@ extension HStack: ViewDeferredToRenderer, SpacerContainer {
|
|||
\(hasSpacer ? "width: 100%;" : "")
|
||||
\(fillCrossAxis ? "height: 100%;" : "")
|
||||
""",
|
||||
"class": "_tokamak-stack",
|
||||
]) { content })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright 2020 Tokamak contributors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Created by Carson Katri on 06/29/2020.
|
||||
//
|
||||
|
||||
import TokamakCore
|
||||
|
||||
public typealias ScrollView = TokamakCore.ScrollView
|
||||
|
||||
extension ScrollView: ViewDeferredToRenderer, SpacerContainer {
|
||||
var axis: SpacerContainerAxis {
|
||||
if axes.contains(.horizontal) {
|
||||
return .horizontal
|
||||
} else {
|
||||
return .vertical
|
||||
}
|
||||
}
|
||||
|
||||
public var deferredBody: AnyView {
|
||||
let scrollX = axes.contains(.horizontal)
|
||||
let scrollY = axes.contains(.vertical)
|
||||
return AnyView(HTML("div", [
|
||||
"style": """
|
||||
\(scrollX ? "overflow-x: auto; width: 100%;" : "overflow-x: hidden;")
|
||||
\(scrollY ? "overflow-y: auto; height: 100%;" : "overflow-y: hidden;")
|
||||
\(fillCrossAxis && scrollX ? "height: 100%;" : "")
|
||||
\(fillCrossAxis && scrollY ? "width: 100%;" : "")
|
||||
""",
|
||||
"class": !showsIndicators ? "_tokamak-scrollview-hideindicators" : "",
|
||||
]) {
|
||||
content
|
||||
})
|
||||
}
|
||||
}
|
|
@ -39,6 +39,7 @@ extension VStack: ViewDeferredToRenderer, SpacerContainer {
|
|||
\(hasSpacer ? "height: 100%;" : "")
|
||||
\(fillCrossAxis ? "width: 100%;" : "")
|
||||
""",
|
||||
"class": "_tokamak-stack",
|
||||
]) { content })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,23 +31,28 @@ struct CustomModifier: ViewModifier {
|
|||
|
||||
let div = document.createElement!("div").object!
|
||||
let renderer = DOMRenderer(
|
||||
VStack {
|
||||
Counter(count: 5, limit: 15)
|
||||
ZStack {
|
||||
Text("I'm on bottom")
|
||||
Text("I'm forced to the top")
|
||||
.zIndex(1)
|
||||
Text("I'm on top")
|
||||
ScrollView(showsIndicators: false) {
|
||||
HStack {
|
||||
Spacer()
|
||||
}
|
||||
VStack {
|
||||
Counter(count: 5, limit: 15)
|
||||
ZStack {
|
||||
Text("I'm on bottom")
|
||||
Text("I'm forced to the top")
|
||||
.zIndex(1)
|
||||
Text("I'm on top")
|
||||
}
|
||||
.padding(20)
|
||||
ForEachDemo()
|
||||
TextDemo()
|
||||
SVGCircle()
|
||||
.frame(width: 25, height: 25)
|
||||
TextFieldDemo()
|
||||
SpacerDemo()
|
||||
Spacer()
|
||||
Text("Forced to bottom.")
|
||||
}
|
||||
.padding(20)
|
||||
ForEachDemo()
|
||||
TextDemo()
|
||||
SVGCircle()
|
||||
.frame(width: 25, height: 25)
|
||||
TextFieldDemo()
|
||||
SpacerDemo()
|
||||
Spacer()
|
||||
Text("Forced to bottom.")
|
||||
},
|
||||
div
|
||||
)
|
||||
|
|
|
@ -85,7 +85,7 @@ Table columns:
|
|||
| --- | ------------------------------------------------------------------------------------------ | :-: |
|
||||
| | [List](https://developer.apple.com/documentation/swiftui/list) | |
|
||||
| 🚧 | [ForEach](https://developer.apple.com/documentation/swiftui/foreach) | |
|
||||
| | [ScrollView](https://developer.apple.com/documentation/swiftui/scrollview) | |
|
||||
| 🚧 | [ScrollView](https://developer.apple.com/documentation/swiftui/scrollview) | |
|
||||
| | [ScrollViewReader](https://developer.apple.com/documentation/swiftui/scrollviewreader) | β |
|
||||
| | [ScrollViewProxy](https://developer.apple.com/documentation/swiftui/scrollviewproxy) | β |
|
||||
| | [DynamicViewContent](https://developer.apple.com/documentation/swiftui/dynamicviewcontent) | β |
|
||||
|
|
Loading…
Reference in New Issue