Skip to content

Commit

Permalink
Make sheet presentation opt-in for format toolbar
Browse files Browse the repository at this point in the history
  • Loading branch information
danielsaidi committed Feb 15, 2024
1 parent 9bce899 commit 5aa68af
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 57 deletions.
7 changes: 6 additions & 1 deletion RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,18 @@ By deprecating these functions, we can simplify the library in 1.0, and focus mo
* `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.
* `RichTextFormatToolbar` has new configuration and style 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.
* `RichTextViewComponent` has a new `toggleRichTextStyle` function.
* `RichTextViewComponent` now handles superscript changes properly.

### 🚨 Important

* `RichTextFormatToolbar` is no longer navigation wrapped by default.
* `RichTextFormatToolbar` has a new `asSheet()` function that does this.

### 💡 Adjustments

* `RichTextColor` `icon` is no longer optional.
Expand Down
189 changes: 133 additions & 56 deletions Sources/RichTextKit/Format/RichTextFormatSheet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ import SwiftUI
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.
You can style this view by applying a style anywhere in the
view hierarchy, using `.richTextFormatToolbarStyle`.
*/
public struct RichTextFormatToolbar: View {

Expand All @@ -38,56 +41,38 @@ public struct RichTextFormatToolbar: View {

@ObservedObject
private var context: RichTextContext

@Environment(\.presentationMode)
private var presentationMode

/// The sheet padding.
public var padding = 10.0

/// The sheet top offset.
public var topOffset = -35.0

@Environment(\.richTextFormatToolbarStyle)
private var style

/// The configuration to use.
private let config: Configuration

public var body: some View {
VStack(spacing: 0) {
fontPicker
toolbar
}
}
}

public extension RichTextFormatToolbar {

/// Convert the toolbar to a sheet, with a close button.
func asSheet(
dismiss: @escaping () -> Void
) -> some View {
NavigationView {
VStack(spacing: 0) {
fontPicker
VStack(spacing: padding) {
VStack {
fontRow
paragraphRow
Divider()
}.padding(.horizontal, padding)
VStack(spacing: padding) {
ForEach(config.colorPickers) {
RichTextColor.Picker(
type: $0,
value: context.binding(for: $0),
quickColors: .quickPickerColors
)
}
}.padding(.leading, padding)
}
.padding(.vertical, padding)
.environment(\.sizeCategory, .medium)
.background(background)
}
.withAutomaticToolbarRole()
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
EmptyView()
}
ToolbarItem(placement: .navigationBarTrailing) {
Button(RTKL10n.done.text) {
presentationMode.wrappedValue.dismiss()
self
.padding(.top, -35)
.withAutomaticToolbarRole()
.toolbar {
ToolbarItem(placement: .confirmationAction) {
Button(RTKL10n.done.text, action: dismiss)
}
}
}
.navigationTitle("")
.navigationBarTitleDisplayMode(.inline)
.navigationTitle("")
.navigationBarTitleDisplayMode(.inline)
}
.navigationViewStyle(.stack)
}
Expand Down Expand Up @@ -117,6 +102,70 @@ public extension RichTextFormatToolbar.Configuration {
static var standard = Self.init()
}

public extension RichTextFormatToolbar {

/// This struct can be used to style a format sheet.
struct Style {

public init(
padding: Double = 10,
spacing: Double = 10
) {
self.padding = padding
self.spacing = spacing
}

public var padding: Double
public var spacing: Double
}

/// This environment key defines a format toolbar style.
struct StyleKey: EnvironmentKey {

public static let defaultValue = RichTextFormatToolbar.Style()
}
}

public extension View {

/// Apply a rich text format toolbar style.
func richTextFormatToolbarStyle(
_ style: RichTextFormatToolbar.Style
) -> some View {
self.environment(\.richTextFormatToolbarStyle, style)
}
}

public extension EnvironmentValues {

/// This environment value defines format toolbar styles.
var richTextFormatToolbarStyle: RichTextFormatToolbar.Style {
get { self [RichTextFormatToolbar.StyleKey.self] }
set { self [RichTextFormatToolbar.StyleKey.self] = newValue }
}
}

private extension RichTextFormatToolbar {

@ViewBuilder
var fontPicker: some View {
if config.fontPicker {
RichTextFont.ListPicker(selection: $context.fontName)
Divider()
}
}

var toolbar: some View {
VStack(spacing: style.spacing) {
controls
colorPickers
}
.padding(.vertical, style.padding)
.environment(\.sizeCategory, .medium)
.background(background)
}
}

private extension RichTextFormatToolbar {

var background: some View {
Expand All @@ -126,16 +175,31 @@ private extension RichTextFormatToolbar {
.edgesIgnoringSafeArea(.all)
}

var controls: some View {
VStack(spacing: style.spacing) {
fontRow
paragraphRow
}
.padding(.horizontal, style.padding)
}

@ViewBuilder
var fontPicker: some View {
if config.fontPicker {
RichTextFont.ListPicker(selection: $context.fontName)
.offset(y: topOffset)
.padding(.bottom, topOffset)
Divider()
var colorPickers: some View {
if !config.colorPickers.isEmpty {
VStack(spacing: style.spacing) {
Divider()
ForEach(config.colorPickers) {
RichTextColor.Picker(
type: $0,
value: context.binding(for: $0),
quickColors: .quickPickerColors
)
}
}
.padding(.leading, style.padding)
}
}

var fontRow: some View {
HStack {
styleButtons
Expand Down Expand Up @@ -186,18 +250,31 @@ private extension View {
struct RichTextFormatToolbar_Previews: PreviewProvider {

struct Preview: View {

@StateObject
private var context = RichTextContext()

@State
private var isSheetPresented = false

var body: some View {
RichTextFormatToolbar(
context: context,
config: .init(
colorPickers: [.foreground],
fontPicker: false
Button("Toggle sheet") {
isSheetPresented.toggle()
}
.sheet(isPresented: $isSheetPresented) {
RichTextFormatToolbar(
context: context,
config: .init(
colorPickers: [.foreground],
fontPicker: true
)
)
)
.asSheet { isSheetPresented = false }
.richTextFormatToolbarStyle(.init(
padding: 10,
spacing: 10
))
}
}
}

Expand Down

0 comments on commit 5aa68af

Please sign in to comment.