Initial implementation of `onHover` (#448)
Adds a basic implementation of action modifiers, allowing for dynamic event handling. For testing, adds a trivial `onHover` example.
This commit is contained in:
parent
8788fd64e9
commit
da66063918
|
@ -0,0 +1,31 @@
|
|||
// Copyright 2021 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.
|
||||
/// Underscore is present in the name for SwiftUI compatibility.
|
||||
public struct _HoverActionModifier: ViewModifier {
|
||||
public var hover: ((Bool) -> ())?
|
||||
|
||||
public typealias Body = Never
|
||||
}
|
||||
|
||||
extension ModifiedContent
|
||||
where Content: View, Modifier == _HoverActionModifier
|
||||
{
|
||||
var hover: ((Bool) -> ())? { modifier.hover }
|
||||
}
|
||||
|
||||
public extension View {
|
||||
func onHover(perform action: ((Bool) -> ())?) -> some View {
|
||||
modifier(_HoverActionModifier(hover: action))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2021 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.
|
||||
|
||||
import TokamakCore
|
||||
|
||||
public protocol DOMActionModifier {
|
||||
var listeners: [String: Listener] { get }
|
||||
}
|
||||
|
||||
extension ModifiedContent
|
||||
where Content: AnyDynamicHTML, Modifier: DOMActionModifier
|
||||
{
|
||||
// Merge listeners
|
||||
var listeners: [String: Listener] {
|
||||
var attr = content.listeners
|
||||
for (key, val) in modifier.listeners {
|
||||
if let prev = attr[key] {
|
||||
attr[key] = { input in
|
||||
val(input)
|
||||
prev(input)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return attr
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2021 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.
|
||||
|
||||
import TokamakCore
|
||||
|
||||
extension _HoverActionModifier: DOMActionModifier {
|
||||
public var listeners: [String: Listener] {
|
||||
[
|
||||
"mouseover":
|
||||
{ _ in hover?(true) },
|
||||
"mouseout":
|
||||
{ _ in hover?(false) },
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2021 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.
|
||||
|
||||
import TokamakCore
|
||||
|
||||
// TOOD: Add _AnyModifiedActionContent similar to TokamakStaticHTML/ModifiedContent.swift?
|
||||
extension ModifiedContent: DOMPrimitive where Content: View, Modifier: DOMActionModifier {
|
||||
public var renderedBody: AnyView {
|
||||
// TODO: Combine DOM nodes when possible, rather than generating arbitrary new ones
|
||||
AnyView(DynamicHTML("div", listeners: modifier.listeners) {
|
||||
content
|
||||
})
|
||||
}
|
||||
}
|
|
@ -15,8 +15,8 @@
|
|||
#if canImport(SnapshotTesting)
|
||||
import SnapshotTesting
|
||||
|
||||
extension Snapshotting where Value == String, Format == String {
|
||||
public static let html = Snapshotting(pathExtension: "html", diffing: .lines)
|
||||
public extension Snapshotting where Value == String, Format == String {
|
||||
static let html = Snapshotting(pathExtension: "html", diffing: .lines)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue