TappablePadding.swift 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. //
  2. // TappablePadding.swift
  3. // ark_ui_basic_extension
  4. import Foundation
  5. // FIXME: import ark_ui_basic
  6. #if canImport(SwiftUI)
  7. public import SwiftUI
  8. struct TappablePadding: ViewModifier {
  9. let edges: Edge.Set
  10. let insets: EdgeInsets?
  11. let perform: () -> Void
  12. init(edges: Edge.Set = .all, insets: EdgeInsets?, perform: @escaping () -> Void) {
  13. self.edges = edges
  14. self.insets = insets
  15. self.perform = perform
  16. }
  17. private var insetsValue: EdgeInsets {
  18. EdgeInsets(
  19. top: edges.contains(.top) ? insets?.top ?? .zero : .zero,
  20. leading: edges.contains(.leading) ? insets?.leading ?? .zero : .zero,
  21. bottom: edges.contains(.bottom) ? insets?.bottom ?? .zero : .zero,
  22. trailing: edges.contains(.trailing) ? insets?.trailing ?? .zero : .zero
  23. )
  24. }
  25. func body(content: Content) -> some View {
  26. content
  27. .padding(insetsValue)
  28. .contentShape(Rectangle())
  29. .onTapGesture(perform: perform)
  30. .padding(insetsValue.inverted)
  31. }
  32. }
  33. extension EdgeInsets {
  34. var inverted: EdgeInsets {
  35. .init(top: -top, leading: -leading, bottom: -bottom, trailing: -trailing)
  36. }
  37. init(_all all: CGFloat) {
  38. self.init(top: all, leading: all, bottom: all, trailing: all)
  39. }
  40. }
  41. extension View {
  42. public func tappablePadding(
  43. _ insets: EdgeInsets,
  44. perform: @escaping () -> Void
  45. ) -> some View {
  46. modifier(TappablePadding(insets: insets, perform: perform))
  47. }
  48. public func tappablePadding(
  49. _ edges: Edge.Set = .all,
  50. _ length: CGFloat?,
  51. perform: @escaping () -> Void
  52. ) -> some View {
  53. let insets = length.map { EdgeInsets(_all: $0) }
  54. return modifier(TappablePadding(edges: edges, insets: insets, perform: perform))
  55. }
  56. public func tappablePadding(
  57. _ length: CGFloat,
  58. perform: @escaping () -> Void
  59. ) -> some View {
  60. tappablePadding(.all, length, perform: perform)
  61. }
  62. }
  63. @available(iOS 15, macOS 12, *)
  64. #Preview {
  65. HStack(spacing: 20) {
  66. Text("Test 1")
  67. .background { Color.yellow }
  68. .padding(EdgeInsets())
  69. .tappablePadding(.all, 20.0) {
  70. print("Test 1")
  71. }
  72. Text("Test 2")
  73. .background { Color.red }
  74. .onTapGesture {
  75. print("Test 2")
  76. }
  77. }
  78. .padding(20)
  79. .background { Color.blue }
  80. }
  81. #endif