bdaralan / BDUIKnit

A Swift Package Manager packed with SwiftUI custom reusable UI components and extensions.
MIT License
25 stars 1 forks source link
swift swiftpm swiftui

BDUIKnit

Swift Package Manager Twitter

BDUIKnit

BDUIKnit is a collection of SwiftUI custom reusable UI components and extensions packed in a Swift Package. BDUIKnit is completely written in Swift with no dependencies. The package is fully documented with some exceptions of internal objects.

Goals

Get Started

Installation

To add BDUIKnit to your project:

Quick Introduction

BDUIKnit follows MVVM design pattern; therefore, most Views will have their corresponding View Models. View models are either class or struct, so use the appropriate @ObservedObject, @State, or @Binding as needed.

New to MVVM? Fear not. Try to read the below codes, if you can make sense of what they are doing, you are ready to use BDUIKnit.

// create a view model that controls the tray view
let trayViewModel = BDButtonTrayViewModel()
trayViewModel.mainItem = createTrayMainItem()
trayViewModel.items = createTrayItems()

trayViewModel.expanded = true
trayViewModel.shouldDisableMainItemWhenExpanded = true

trayViewModel.trayColor = Color(.systemBackground)
trayViewModel.itemActiveColor = Color.accentColor

// pass the view model to the tray view to render
BDButtonTrayView(viewModel: trayViewModel)

// while the tray view is displaying, update the view model
trayViewModel.expanded = false

// the tray view is now collapsed

Documentations

BDButtonTrayView

A tray-like view that is normally pinned to the bottom-trailing of a scene.

Tray item now supports more animations.

Regular Vertical Size Class

BDButtonTrayPreview-1

Compact Vertical Size Class

BDButtonTrayPreview-2

Tray Item Animations

BDButtonTrayItemAnimation

Quick Start:

// Add tray view to a view when content ignores safe area

struct SomeView: View {

    @State private var trayViewModel = BDButtonTrayViewModel()

    var body: some View {
        ZStack {
            SomeContent()
                .edgesIgnoringSafeArea(.all)

            BDButtonTrayView(viewModel: trayViewModel)
                .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomTrailing)
                .padding(16)
                .onAppear(perform: setupTrayViewModel)
        }
    }

    func setupTrayViewModel() {
        // setup tray view model...
    }
}

For sample code, see ButtonTrayViewPreview

BDModalTextField

A text field view intended to be used as a modal presentation sheet when need to get inputs from user.

BDModalTextFieldPreview

Quick Start:

For sample code, see ModalTextFieldPreview

BDModalTextView

A text view intended to be used as a modal presentation sheet when need to get inputs from user.

BDModalTextViewPreview

Quick Start:

For sample code, see ModalTextViewPreview

BDPersist Property Wrapper

A property wrapper that stores value in a given store. For example, UserDefaults.

Quick Start:

// Store username in UserDefaults

@BDPersist(in: .userDefaults, key: "username", default: "")
var username: String
// Add post notification when username changed

static let nUsernameDidChange = Notification.Name("nUsernameDidChange")

@BDPersist(in: .userDefaults, key: "username", default: "", post: nUsernameDidChange)
var username: String
// Use optional value and NSUbiquitousKeyValueStore
// see docs for how to enable ubiquitous store

@BDPersist(in: .ubiquitousStore, key: "highScore", default: nil)
var highScore: Int?
// Use type-safe key

// create an enum
// conform to BDPersistKey
// implement the required prefix property
enum Keys: BDPersistKey {
    var prefix: String { "some.prefix." }
    case autoplay
    case autosave
}

// the key is 'some.prefix.autoplay'
@BDPersist(in: .userDefaults, key: Keys.autoplay, default: true)
var autoplay: Bool

// the key is 'some.prefix.autosave'
@BDPersist(in: .userDefaults, key: Keys.autosave, default: false)
var autosave: Bool
// Use custom store

// conform to BDPersistStorable
// implement required methods
class CustomStore: BDPersistStorable {
    // implementations...
}

@BDPersist(in: .custom(CustomStore()), key: "username", default: "")
var username: String

For sample code, see PersistPropertyWrapperPreview

BDPresentationItem

An object used to present sheet. It provide an easy way to store previous dismissed sheet if needed.

Quick Start

// Example code with Enum conforms to BDPresentationSheetItem

struct UserProfileView: View {

    // conform to BDPresentationSheetItem or Identifiable
    enum Sheet: BDPresentationSheetItem {
        case modalTextField
        case modalTextView
    }

    @State private var sheet = BDPresentationItem<Sheet>()

    var body: some View {
        Form {
            Button("Edit Username") {
                self.sheet.present(.modalTextField)
            }

            Button("Edut UserBio") {
                self.sheet.current = .modalTextView
            }
        }
        .onAppear(perform: setupOnAppear)
        .sheet(item: $sheet.current, onDismiss: sheetDismissed, content: presentationSheet)
    }

    func setupOnAppear() {
        // if need to access sheet.previous on dismissed
        sheet.shouldStorePrevious = true
    }

    func presentationSheet(for sheet: Sheet) -> some View {
        switch sheet {
        case .modalTextField: return AnyView(...)
        case .modalTextView: return AnyView(...)
        }
    }

    func sheetDismissed() {
        if sheet.previous == .modalTextField {
            // do something
        }
    }
}

For sample code, see PresentationItemPreview

Extension

// Create color from hex

Color(hex: "BDA12A") // a Color

UIColor(hex: "#bda12a") // a UIColor

UIColor(hex: "purple") // fatal error: create color with invalid hex: 'purple'