Skip to content

Commit

Permalink
Make format toolbar and sidebar share styles, configurations and views
Browse files Browse the repository at this point in the history
  • Loading branch information
danielsaidi committed Feb 16, 2024
1 parent 91ea919 commit fb7d7ec
Show file tree
Hide file tree
Showing 13 changed files with 378 additions and 257 deletions.
3 changes: 2 additions & 1 deletion RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ 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` has new configuration and style type.
* `RichTextFormatToolbar` has new configuration and style types.
* `RichTextFormatSidebar` has new configuration and style types.
* `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
103 changes: 47 additions & 56 deletions Sources/RichTextKit/Format/RichTextFormatSidebar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// 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 || macOS || os(visionOS)
Expand All @@ -17,103 +17,82 @@ import SwiftUI
should also be made to look good on iPadOS in landscape, to
let us use it instead of the ``RichTextFormatSheet``.
*/
public struct RichTextFormatSidebar: View {
public struct RichTextFormatSidebar: RichTextFormatToolbarBase {

/**
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
}

public typealias Configuration = RichTextFormatToolbar.Configuration

@ObservedObject
private var context: RichTextContext

let config: Configuration

/// The sidebar spacing.
public var spacing = 10.0

/// The color pickers to use.
public var colorPickers: [RichTextColor]
@Environment(\.richTextFormatToolbarStyle)
var style

public var body: some View {
VStack(alignment: .leading, spacing: spacing) {
VStack(alignment: .leading, spacing: style.spacing) {
SidebarSection {
RichTextFont.Picker(selection: $context.fontName, fontSize: 12)
fontPicker(value: $context.fontName)
HStack {
RichTextStyle.ToggleGroup(context: context)
RichTextFont.SizePickerStack(context: context)
styleToggleGroup(for: context)
Spacer()
fontSizePicker(for: context)
}
}

Divider()

SidebarSection {
RichTextAlignment.Picker(selection: $context.textAlignment)
.pickerStyle(.segmented)
alignmentPicker(value: $context.textAlignment)
HStack {
RichTextAction.ButtonGroup(
context: context,
actions: [.decreaseIndent(), .increaseIndent()]
)
if hasSuperscriptSupport {
RichTextAction.ButtonGroup(
context: context,
actions: [
.increaseSuperscript(),
.decreaseSuperscript()
]
)
}
superscriptButtons(for: context, greedy: true)
indentButtons(for: context, greedy: true)
}
}

Divider()

SidebarSection {
VStack(spacing: 4) {
ForEach(colorPickers) {
RichTextColor.Picker(
type: $0,
value: context.binding(for: $0),
quickColors: .quickPickerColors
)
}
if hasColorPickers {
SidebarSection {
colorPickers(for: context)
}
.padding(.trailing, -8)
Divider()
}
.font(.callout)
.padding(.trailing, -8)

Spacer()
}
.padding(8)
.padding(style.padding - 2)
.background(Color.white.opacity(0.05))
}
}

private extension RichTextFormatSidebar {

var hasSuperscriptSupport: Bool {
#if macOS
return true
#else
return false
#endif
}
}

private struct SidebarSection<Content: View>: View {

@ViewBuilder
let content: () -> Content

@Environment(\.richTextFormatToolbarStyle)
var style

var body: some View {
VStack(alignment: .leading, spacing: 10) {
VStack(alignment: .leading, spacing: style.spacing) {
content()
Divider()
}
}
}
Expand All @@ -126,13 +105,25 @@ struct RichTextFormatSidebar_Previews: PreviewProvider {
private var context = RichTextContext()

var body: some View {
RichTextFormatSidebar(context: context)
RichTextFormatSidebar(
context: context,
config: .init(
alignments: [.left, .right],
colorPickers: [.foreground],
colorPickersDisclosed: [],
fontPicker: true,
fontSizePicker: true,
indentButtons: true,
styles: .all,
superscriptButtons: true
)
)
}
}

static var previews: some View {
Preview()
.frame(width: 350)
.frame(minWidth: 350)
}
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// RichTextFormatToolbar+Configuration.swift
// RichTextKit
//
// Created by Daniel Saidi on 2024-02-16.
// Copyright © 2024 Daniel Saidi. All rights reserved.
//

import SwiftUI

public extension RichTextFormatToolbar {

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

public init(
alignments: [RichTextAlignment] = .all,
colorPickers: [RichTextColor] = [.foreground],
colorPickersDisclosed: [RichTextColor] = [],
fontPicker: Bool = true,
fontSizePicker: Bool = true,
indentButtons: Bool = true,
styles: [RichTextStyle] = .all,
superscriptButtons: Bool = true
) {
self.alignments = alignments
self.colorPickers = colorPickers
self.colorPickersDisclosed = colorPickersDisclosed
self.fontPicker = fontPicker
self.fontSizePicker = fontSizePicker
self.indentButtons = indentButtons
self.styles = styles
#if macOS
self.superscriptButtons = superscriptButtons
#else
self.superscriptButtons = false
#endif
}

public var alignments: [RichTextAlignment]
public var colorPickers: [RichTextColor]
public var colorPickersDisclosed: [RichTextColor]
public var fontPicker: Bool
public var fontSizePicker: Bool
public var indentButtons: Bool
public var styles: [RichTextStyle]
public var superscriptButtons: Bool
}
}

public extension RichTextFormatToolbar.Configuration {

/// The standard rich text format toolbar configuration.
static var standard = Self.init()
}
58 changes: 58 additions & 0 deletions Sources/RichTextKit/Format/RichTextFormatToolbar+Style.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//
// RichTextFormatToolbar+Style.swift
// RichTextKit
//
// Created by Daniel Saidi on 2024-02-16.
// Copyright © 2024 Daniel Saidi. All rights reserved.
//

import SwiftUI

public extension RichTextFormatToolbar {

/// This struct can be used to style a format sheet.
///
/// Don't specify a font picker height if the toolbar is
/// used in a sheet. Use detents to the toolbar's height.
struct Style {

public init(
fontPickerHeight: CGFloat? = nil,
padding: Double = 10,
spacing: Double = 10
) {
self.fontPickerHeight = fontPickerHeight
self.padding = padding
self.spacing = spacing
}

public var fontPickerHeight: CGFloat?
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 }
}
}
Loading

0 comments on commit fb7d7ec

Please sign in to comment.