Skip to content
This repository has been archived by the owner on Apr 27, 2023. It is now read-only.

Develop #39

Merged
merged 11 commits into from
Oct 3, 2021
2 changes: 1 addition & 1 deletion SalmonUI.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Pod::Spec.new do |spec|

spec.name = "SalmonUI"
spec.version = "4.2.0"
spec.version = "4.3.0"
spec.summary = "Awesome SwiftUI views"

spec.description = <<-DESC
Expand Down
8 changes: 4 additions & 4 deletions SalmonUI.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@
buildSettings = {
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 6;
CURRENT_PROJECT_VERSION = 7;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
Expand All @@ -490,7 +490,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 4.2.0;
MARKETING_VERSION = 4.3.0;
PRODUCT_BUNDLE_IDENTIFIER = io.kamaal.SalmonUI;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand All @@ -506,7 +506,7 @@
buildSettings = {
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 6;
CURRENT_PROJECT_VERSION = 7;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
Expand All @@ -519,7 +519,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 4.2.0;
MARKETING_VERSION = 4.3.0;
PRODUCT_BUNDLE_IDENTIFIER = io.kamaal.SalmonUI;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down
32 changes: 32 additions & 0 deletions Sources/SalmonUI/ViewModifiers/KBindToFrameSize.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// KBindToFrameSize.swift
//
//
// Created by Kamaal M Farah on 03/10/2021.
//

import SwiftUI

public extension View {
func kBindToFrameSize(_ size: Binding<CGSize>) -> some View {
self.modifier(KBindToFrameSize(size: size))
}
}

private struct KBindToFrameSize: ViewModifier {
@Binding var size: CGSize

func body(content: Content) -> some View {
content.overlay(GeometryReader(content: overlay(for:)))
}

func overlay(for geometry: GeometryProxy) -> some View {
let size = geometry.size
if self.size.width != size.width || self.size.height != size.height {
DispatchQueue.main.async {
self.size = geometry.size
}
}
return Text("")
}
}
35 changes: 35 additions & 0 deletions Sources/SalmonUI/Views/KDeletableForEach.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// KDeletableForEach.swift
//
//
// Created by Kamaal M Farah on 03/10/2021.
//

import SwiftUI

struct KDeletableForEach<Data: RandomAccessCollection, ID: Hashable, Content: View>: View {
let data: Data
let id: KeyPath<Data.Element, ID>
let isEditing: Bool
let deleteText: String
let onDelete: (Data.Element) -> Void
let content: (Data.Element) -> Content

var body: some View {
ForEach(data, id: id) { element in
KDeletableView(
isDeleting: .constant(false),
enabled: isEditing,
deleteText: deleteText,
onDelete: { onDelete(element) }) {
content(element)
}
}
}
}

//struct KDeletableForEach_Previews: PreviewProvider {
// static var previews: some View {
// KDeletableForEach()
// }
//}
86 changes: 86 additions & 0 deletions Sources/SalmonUI/Views/KDeletableView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//
// KDeletableView.swift
//
//
// Created by Kamaal M Farah on 03/10/2021.
//

import SwiftUI

public struct KDeletableView<Content: View>: View {
@State private var textSize = CGSize(width: 60, height: 60)

@Binding public var isDeleting: Bool

public let enabled: Bool
public let deleteText: String
public let onDelete: () -> Void
public let content: () -> Content

private let deleteButtonHeight: CGFloat = 68

public init(isDeleting: Binding<Bool>,
enabled: Bool,
deleteText: String = "Delete",
onDelete: @escaping () -> Void,
content: @escaping () -> Content) {
self._isDeleting = isDeleting
self.enabled = enabled
self.deleteText = deleteText
self.onDelete = onDelete
self.content = content
}

public var body: some View {
HStack {
if enabled && !isDeleting {
Button(action: { withAnimation { isDeleting = true } }) {
Image(systemName: "minus.circle.fill")
.foregroundColor(.red)
.padding(.leading, 20)
}
.transition(.move(edge: .leading))
}
content()
if enabled && isDeleting {
Spacer()
Button(action: _onDelete) {
ZStack {
Color.red
Text(deleteText)
.foregroundColor(Color(.systemBackground))
.kBindToFrameSize($textSize)
}
.frame(minWidth: deleteButtonWidth,
maxWidth: deleteButtonWidth,
minHeight: deleteButtonHeight,
maxHeight: deleteButtonHeight)
}
.transition(.move(edge: .trailing))
}
}
.ktakeWidthEagerly(alignment: .leading)
}

private var deleteButtonWidth: CGFloat {
textSize.width + 16
}

private func _onDelete() {
onDelete()
withAnimation { isDeleting = false }
}
}

public extension View {
func kDeletableView(isDeleting: Binding<Bool>, enabled: Bool, onDelete: @escaping () -> Void) -> some View {
KDeletableView(isDeleting: isDeleting, enabled: enabled, onDelete: onDelete, content: { self })
}
}

struct KDeletableView_Previews: PreviewProvider {
static var previews: some View {
Text("Yes delete me")
.kDeletableView(isDeleting: .constant(true), enabled: true, onDelete: { })
}
}