Skip to content

Commit

Permalink
Rename format sheet and add configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
danielsaidi committed Feb 15, 2024
1 parent 4c32341 commit 9bce899
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 48 deletions.
7 changes: 5 additions & 2 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ By deprecating these functions, we can simplify the library in 1.0, and focus mo

* `FontRepresentable` has new extensions.
* `RichTextAction` has a new `label` property.
* `RichTextCommand.ActionButtonGroup` has many new initializers.
* `RichTextCommand.FormatMenu` is more configurable than before.
* `RichTextCommand.ActionButtonGroup` has new inits.
* `RichTextCommand.FormatMenu` is a lot more configurable.
* `RichTextFormatToolbar` is now available on all platforms.
* `RichTextFormatToolbar` now has a custom configuration type.
* `RichTextKeyboardToolbar` has a new config to always be shown.
* `RichTextView` has a new theme that lets you define its style.
* `RichTextViewComponent` has a new `hasRichTextStyle` function.
Expand Down Expand Up @@ -55,6 +57,7 @@ By deprecating these functions, we can simplify the library in 1.0, and focus mo
* `RichTextContext` replaces individual styles with a single `styles`.
* `RichTextContext` `userActionPublisher` is renamed to `actionPublisher`.
* `RichTextCoordinator` functions calling `handle(_:)` have been deprecated.
* `RichTextFormatSheet` has been renamed to `RichTextFormatToolbar`.
* `RTKL10n.bundle` has been deprecated since we can use the `.module` bundle.

### 💥 Breaking Changes
Expand Down
117 changes: 77 additions & 40 deletions Sources/RichTextKit/Format/RichTextFormatSheet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,37 @@
// RichTextKit
//
// Created by Daniel Saidi on 2022-12-13.
// Copyright © 2022-2023 Daniel Saidi. All rights reserved.
// Copyright © 2022-2024 Daniel Saidi. All rights reserved.
//

#if iOS || os(visionOS)
import SwiftUI

/**
This sheet view provides different text format options, and
is meant to be used on iOS, where space is limited.
The font picker will take up as much height as it can after
the other rows have allocated their height.
This toolbar provides different text format options, and is
meant to be used on iOS, where space is limited.
Consider presenting this view from the bottom in a way that
doesn't cause the underlying text view to dim.
You can provide a custom configuration to adjust the format
options that are presented. When presented, the font picker
will take up the available vertical height.
*/
public struct RichTextFormatSheet: View {
public struct RichTextFormatToolbar: View {

/**
Create a rich text format sheet.
- Parameters:
- context: The context to apply changes to.
- colorPickers: The color pickers to use, by default `.foreground` and `.background`.
- config: The configuration to use, by default `.standard`.
*/
public init(
context: RichTextContext,
colorPickers: [RichTextColor] = [.foreground, .background]
config: Configuration = .standard
) {
self._context = ObservedObject(wrappedValue: context)
self.colorPickers = colorPickers
self.config = config
}

@ObservedObject
Expand All @@ -45,24 +48,21 @@ public struct RichTextFormatSheet: View {
/// The sheet top offset.
public var topOffset = -35.0

/// The color pickers to use.
public var colorPickers: [RichTextColor]
/// The configuration to use.
private let config: Configuration

public var body: some View {
NavigationView {
VStack(spacing: 0) {
RichTextFont.ListPicker(selection: $context.fontName)
.offset(y: topOffset)
.padding(.bottom, topOffset)
Divider()
fontPicker
VStack(spacing: padding) {
VStack {
fontRow
paragraphRow
Divider()
}.padding(.horizontal, padding)
VStack(spacing: padding) {
ForEach(colorPickers) {
ForEach(config.colorPickers) {
RichTextColor.Picker(
type: $0,
value: context.binding(for: $0),
Expand All @@ -88,40 +88,63 @@ public struct RichTextFormatSheet: View {
}
.navigationTitle("")
.navigationBarTitleDisplayMode(.inline)
}.navigationViewStyle(.stack)
}
}

private extension RichTextFormatSheet {

var fontRow: some View {
HStack {
styleButtons
Spacer()
RichTextFont.SizePickerStack(context: context)
.buttonStyle(.bordered)
}
.navigationViewStyle(.stack)
}
}

var paragraphRow: some View {
HStack {
RichTextAlignment.Picker(selection: $context.textAlignment)
.pickerStyle(.segmented)
Spacer()
indentButtons
public extension RichTextFormatToolbar {

/// This struct can be used to configure a format sheet.
struct Configuration {

public init(
colorPickers: [RichTextColor] = [.foreground],
fontPicker: Bool = true
) {
self.colorPickers = colorPickers
self.fontPicker = fontPicker
}

public var colorPickers: [RichTextColor]
public var fontPicker: Bool
}
}

private extension RichTextFormatSheet {
public extension RichTextFormatToolbar.Configuration {

/// The standard rich text format toolbar configuration.
static var standard = Self.init()
}

private extension RichTextFormatToolbar {

var background: some View {
Color.clear
.overlay(Color.primary.opacity(0.1))
.shadow(color: .black.opacity(0.1), radius: 5)
.edgesIgnoringSafeArea(.all)
}

@ViewBuilder
var fontPicker: some View {
if config.fontPicker {
RichTextFont.ListPicker(selection: $context.fontName)
.offset(y: topOffset)
.padding(.bottom, topOffset)
Divider()
}
}

var fontRow: some View {
HStack {
styleButtons
Spacer()
RichTextFont.SizePickerStack(context: context)
.buttonStyle(.bordered)
}
}

@ViewBuilder
var indentButtons: some View {
RichTextAction.ButtonGroup(
Expand All @@ -131,6 +154,15 @@ private extension RichTextFormatSheet {
)
}

var paragraphRow: some View {
HStack {
RichTextAlignment.Picker(selection: $context.textAlignment)
.pickerStyle(.segmented)
Spacer()
indentButtons
}
}

@ViewBuilder
var styleButtons: some View {
RichTextStyle.ToggleGroup(
Expand All @@ -151,20 +183,25 @@ private extension View {
}
}

struct RichTextFormatSheet_Previews: PreviewProvider {
struct RichTextFormatToolbar_Previews: PreviewProvider {

struct Preview: View {

@StateObject
private var context = RichTextContext()

var body: some View {
RichTextFormatSheet(context: context)
RichTextFormatToolbar(
context: context,
config: .init(
colorPickers: [.foreground],
fontPicker: false
)
)
}
}

static var previews: some View {
Preview()
}
}
#endif
12 changes: 6 additions & 6 deletions Sources/RichTextKit/Keyboard/RichTextKeyboardToolbar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public struct RichTextKeyboardToolbar<LeadingButtons: View, TrailingButtons: Vie
- trailingActions: The trailing actions, by default `.dismissKeyboard`.
- leadingButtons: The leading buttons to place after the leading actions.
- trailingButtons: The trailing buttons to place after the trailing actions.
- richTextFormatSheet: The rich text format sheet to use, given the default ``RichTextFormatSheet``.
- richTextFormatSheet: The rich text format sheet to use, given the default ``RichTextFormatToolbar``.
*/
public init(
context: RichTextContext,
Expand All @@ -58,7 +58,7 @@ public struct RichTextKeyboardToolbar<LeadingButtons: View, TrailingButtons: Vie
trailingActions: [RichTextAction] = [.dismissKeyboard],
@ViewBuilder leadingButtons: @escaping () -> LeadingButtons,
@ViewBuilder trailingButtons: @escaping () -> TrailingButtons,
@ViewBuilder richTextFormatSheet: @escaping (RichTextFormatSheet) -> FormatSheet
@ViewBuilder richTextFormatSheet: @escaping (RichTextFormatToolbar) -> FormatSheet
) {
self._context = ObservedObject(wrappedValue: context)
self.leadingActions = leadingActions
Expand All @@ -81,7 +81,7 @@ public struct RichTextKeyboardToolbar<LeadingButtons: View, TrailingButtons: Vie
- trailingActions: The trailing actions, by default `.dismissKeyboard`.
- leadingButtons: The leading buttons to place after the leading actions.
- trailingButtons: The trailing buttons to place after the trailing actions.
- richTextFormatSheet: The rich text format sheet to use, given the default ``RichTextFormatSheet``.
- richTextFormatSheet: The rich text format sheet to use, given the default ``RichTextFormatToolbar``.
*/
public init(
context: RichTextContext,
Expand All @@ -91,7 +91,7 @@ public struct RichTextKeyboardToolbar<LeadingButtons: View, TrailingButtons: Vie
trailingActions: [RichTextAction] = [.dismissKeyboard],
@ViewBuilder leadingButtons: @escaping () -> LeadingButtons,
@ViewBuilder trailingButtons: @escaping () -> TrailingButtons
) where FormatSheet == RichTextFormatSheet {
) where FormatSheet == RichTextFormatToolbar {
self.init(
context: context,
style: style,
Expand All @@ -111,7 +111,7 @@ public struct RichTextKeyboardToolbar<LeadingButtons: View, TrailingButtons: Vie

private let leadingButtons: () -> LeadingButtons
private let trailingButtons: () -> TrailingButtons
private let richTextFormatSheet: (RichTextFormatSheet) -> FormatSheet
private let richTextFormatSheet: (RichTextFormatToolbar) -> FormatSheet

@ObservedObject
private var context: RichTextContext
Expand Down Expand Up @@ -143,7 +143,7 @@ public struct RichTextKeyboardToolbar<LeadingButtons: View, TrailingButtons: Vie
.frame(height: shouldDisplayToolbar ? nil : 0)
.sheet(isPresented: $isFormatSheetPresented) {
richTextFormatSheet(
RichTextFormatSheet(context: context)
RichTextFormatToolbar(context: context)
).prefersMediumSize()
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import SwiftUI

@available(*, deprecated, renamed: "RichTextFormatToolbar")
public typealias RichTextFormatSheet = RichTextFormatToolbar

public extension RichTextFormatToolbar {

init(
context: RichTextContext,
colorPickers: [RichTextColor]
) {
self.init(
context: context,
config: .init(colorPickers: colorPickers)
)
}
}

0 comments on commit 9bce899

Please sign in to comment.