Skip to content

Added OnNewTag, allows to react to Return key in TagTextField, fixed fatal problem with landscape mode #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
45 changes: 45 additions & 0 deletions Sources/TagKit/Views/Generic/HeightReader.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// SwiftUIView.swift
//
//
// Created by Klaus Kneupner on 25/06/2024.
//

import SwiftUI

struct HeightReader: View {
@Binding var height: CGSize

var body: some View {
GeometryReader { geo in
Color.clear
.preference(key: ViewSizeKey.self, value: geo.size)
.onPreferenceChange(ViewSizeKey.self) { value in
self.height = value
}
}
}
}

struct ViewSizeKey: PreferenceKey {
static var defaultValue: CGSize = CGSize(width: 1, height: 1)

static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
value = nextValue()
}
}


#Preview {
struct ContentView: View {
@State private var viewHeight: CGSize = CGSize(width: 1, height: 1)

var body: some View {
ZStack {
HeightReader(height: $viewHeight)
Text("View height: \(viewHeight)")
}
}
}
return ContentView()
}
4 changes: 2 additions & 2 deletions Sources/TagKit/Views/TagCapsuleStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public struct TagCapsuleStyle {

public extension TagCapsuleStyle {

struct Border {
struct Border : Sendable {

/// Create a new tag capsule border style.
///
Expand All @@ -121,7 +121,7 @@ public extension TagCapsuleStyle {

public extension TagCapsuleStyle {

struct Shadow {
struct Shadow : Sendable{

/// Create a new tag capsule shadow style.
///
Expand Down
33 changes: 11 additions & 22 deletions Sources/TagKit/Views/TagList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import SwiftUI


/// This enum specifies supported tag list container types.
public enum TagListContainer {

Expand All @@ -31,6 +32,8 @@ public enum TagListContainer {
You must specify a container type, since the list has to be
rendered differently depending on if it's in a `ScrollView`
or a `VerticalStack`.

You will often want to add a ``onTapGesture(count:perform:)`` inside the `TapViewBuilder`.
*/
public struct TagList<TagView: View>: View {

Expand All @@ -48,14 +51,15 @@ public struct TagList<TagView: View>: View {
horizontalSpacing: CGFloat = 5,
verticalSpacing: CGFloat = 5,
@ViewBuilder tagView: @escaping TagViewBuilder

) {
self.tags = tags
self.container = container
self.horizontalSpacing = horizontalSpacing
self.verticalSpacing = verticalSpacing
self.tagView = tagView
let initialHeight: CGFloat = container == .scrollView ? .zero : .infinity
_totalHeight = State(initialValue: initialHeight)
_viewSize = State(initialValue: CGSize(width: 0, height: initialHeight))
}

private let tags: [String]
Expand All @@ -68,40 +72,33 @@ public struct TagList<TagView: View>: View {

/// This type defines the tag view builder for the list.
public typealias TagViewBuilder = (_ tag: String) -> TagView
@State private var viewSize: CGSize

@State
private var totalHeight: CGFloat

public var body: some View {
if container == .scrollView {
content.frame(height: totalHeight)
content.frame(height: viewSize.height)
} else {
content.frame(maxHeight: totalHeight)
content.frame(maxHeight: viewSize.height)
}
}
}

@MainActor
private extension TagList {

var content: some View {
GeometryReader { geometry in
content(in: geometry)
}
}

func content(in g: GeometryProxy) -> some View {
var width = CGFloat.zero
var height = CGFloat.zero
var lastHeight = CGFloat.zero
let itemCount = tags.count
return ZStack(alignment: .topLeading) {
HeightReader(height: $viewSize)
ForEach(Array(tags.enumerated()), id: \.offset) { index, item in
tagView(item)
.padding([.horizontal], horizontalSpacing)
.padding([.vertical], verticalSpacing)
.alignmentGuide(.leading, computeValue: { d in
if abs(width - d.width) > g.size.width {
if abs(width - d.width) > viewSize.width {
width = 0
height -= lastHeight
}
Expand All @@ -121,18 +118,10 @@ private extension TagList {
}
return result
})
.background(.clear)
}
}
.background(viewHeightReader($totalHeight))
}

func viewHeightReader(_ binding: Binding<CGFloat>) -> some View {
return GeometryReader { geo -> Color in
DispatchQueue.main.async {
binding.wrappedValue = geo.frame(in: .local).size.height
}
return .clear
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions Sources/TagKit/Views/TagTextField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import SwiftUI

This text field will also make it harder to type characters
that are not in the configuration's allowed character set.

You often want to add an ``onSubmit(of:_:)`` on
the use of this View in order to react on new tags.
*/
public struct TagTextField: View {

Expand Down