Skip to content

Commit

Permalink
Rename format sheet and sidebar
Browse files Browse the repository at this point in the history
  • Loading branch information
danielsaidi committed Mar 4, 2024
1 parent 31c259f commit 5ab1087
Show file tree
Hide file tree
Showing 7 changed files with 397 additions and 377 deletions.
14 changes: 8 additions & 6 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ This release removes all deprecated code and cleans up the library.
* Many localization keys have been renamed to be easier to use.

* `RichTextContextFocusedValueKey` has been renamed to `RichTextContext.FocusedValueKey`.
* `RichTextEditor` is now configured and styled with modifiers instead of the initializer.
* `RichTextFont` pickers are now configured with a shared modifier instead of the initializer.
* `RichTextFont` size picker is now configured with a shared modifier instead of the initializer.
* `RichTextFormat` components arre now configured with a shared modifier instead of the initializer.
* `RichTextLine` spacing picker is now configured with a shared modifier instead of the initializer.
* `RichTextKeyboardToolbar` is now configured and styled with two modifiers instead of the initializer.
* `RichTextEditor` is now configured and styled with modifiers instead of the init.
* `RichTextFont` pickers are now configured with a shared modifier instead of the init.
* `RichTextFont` size picker is now configured with a shared modifier instead of the init.
* `RichTextFormat` components are now configured with a shared modifier instead of the init.
* `RichTextFormatSheet` has been renamed to `RichTextFormat.Sheet` to trim SDK surface area.
* `RichTextFormatSidebar` has been renamed to `RichTextFormat.Sidebar` to trim SDK surface area.
* `RichTextLine.SpacingPicker` is now configured with a shared view modifier instead of the init.
* `RichTextKeyboardToolbar` is now configured and styled with two view modifiers instead of the init.



Expand Down
182 changes: 182 additions & 0 deletions Sources/RichTextKit/Format/RichTextFormat+Sheet.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
//
// RichTextFormat+Sheet.swift
// RichTextKit
//
// Created by Daniel Saidi on 2022-12-13.
// Copyright © 2022-2024 Daniel Saidi. All rights reserved.
//

#if iOS || macOS || os(visionOS)
import SwiftUI

public extension RichTextFormat {

/**
This sheet contains a font picker and a bottom toolbar.

You can configure and style the view by applying config
and style view modifiers to your view hierarchy:

```swift
VStack {
...
}
.richTextFormatSheetStyle(...)
.richTextFormatSheetConfig(...)
```
*/
struct Sheet: RichTextFormatToolbarBase {

/**
Create a rich text format sheet.

- Parameters:
- context: The context to apply changes to.
*/
public init(
context: RichTextContext
) {
self._context = ObservedObject(wrappedValue: context)
}

public typealias Config = RichTextFormatToolbar.Config
public typealias Style = RichTextFormatToolbar.Style

@ObservedObject
private var context: RichTextContext

@Environment(\.richTextFormatSheetConfig)
var config

@Environment(\.richTextFormatSheetStyle)
var style

@Environment(\.dismiss)
private var dismiss

@Environment(\.horizontalSizeClass)
private var horizontalSizeClass

public var body: some View {
NavigationView {
VStack(spacing: 0) {
RichTextFont.ListPicker(
selection: $context.fontName
)
Divider()
RichTextFormatToolbar(
context: context
)
.richTextFormatToolbarConfig(config)
}
.padding(.top, -35)
.toolbar {
ToolbarItem(placement: .confirmationAction) {
Button(RTKL10n.done.text) {
dismiss()
}
}
}
.navigationTitle("")
#if iOS
.navigationBarTitleDisplayMode(.inline)
#endif
}
#if iOS
.navigationViewStyle(.stack)
#endif
}
}
}

public extension View {

/// Apply a rich text format sheet config.
func richTextFormatSheetConfig(
_ value: RichTextFormat.Sheet.Config
) -> some View {
self.environment(\.richTextFormatSheetConfig, value)
}

/// Apply a rich text format sheet style.
func richTextFormatSheetStyle(
_ value: RichTextFormat.Sheet.Style
) -> some View {
self.environment(\.richTextFormatSheetStyle, value)
}
}

private extension RichTextFormat.Sheet.Config {

struct Key: EnvironmentKey {

static let defaultValue = RichTextFormat.Sheet.Config()
}
}

private extension RichTextFormat.Sheet.Style {

struct Key: EnvironmentKey {

static let defaultValue = RichTextFormat.Sheet.Style()
}
}

public extension EnvironmentValues {

/// This value can bind to a format sheet config.
var richTextFormatSheetConfig: RichTextFormat.Sheet.Config {
get { self [RichTextFormat.Sheet.Config.Key.self] }
set { self [RichTextFormat.Sheet.Config.Key.self] = newValue }
}

/// This value can bind to a format sheet style.
var richTextFormatSheetStyle: RichTextFormat.Sheet.Style {
get { self [RichTextFormat.Sheet.Style.Key.self] }
set { self [RichTextFormat.Sheet.Style.Key.self] = newValue }
}
}

struct RichTextFormat_Sheet_Previews: PreviewProvider {

struct Preview: View {

@StateObject
private var context = RichTextContext()

@State
private var isSheetPresented = false

var body: some View {
VStack(spacing: 0) {
Color.red
Button("Toggle sheet") {
isSheetPresented.toggle()
}
}
.sheet(isPresented: $isSheetPresented) {
RichTextFormat.Sheet(
context: context
)
.richTextFormatSheetConfig(.init(
alignments: .all,
colorPickers: [.foreground, .background],
colorPickersDisclosed: [.stroke],
fontPicker: true,
fontSizePicker: false,
indentButtons: true,
styles: .all
))
}
.richTextFormatToolbarStyle(.init(
padding: 10,
spacing: 10
))
}
}

static var previews: some View {
Preview()
}
}
#endif
193 changes: 193 additions & 0 deletions Sources/RichTextKit/Format/RichTextFormat+Sidebar.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
//
// RichTextFormat+Sidebar.swift
// RichTextKit
//
// Created by Daniel Saidi on 2022-12-13.
// Copyright © 2022-2024 Daniel Saidi. All rights reserved.
//

#if iOS || macOS || os(visionOS)
import SwiftUI

public extension RichTextFormat {

/**
This sidebar view provides various text format options, and
is meant to be used on macOS, in a trailing sidebar.

You can configure and style the view by applying its config
and style view modifiers to your view hierarchy:

```swift
VStack {
...
}
.richTextFormatSidebarStyle(...)
.richTextFormatSidebarConfig(...)
```

> Note: The sidebar is currently designed for macOS, but it
should also be made to look good on iPadOS in landscape, to
let us use it instead of the ``RichTextFormatSheet``.
*/
struct Sidebar: RichTextFormatToolbarBase {

/**
Create a rich text format sheet.

- Parameters:
- context: The context to apply changes to.
*/
public init(
context: RichTextContext
) {
self._context = ObservedObject(wrappedValue: context)
}

public typealias Config = RichTextFormatToolbar.Config
public typealias Style = RichTextFormatToolbar.Style

@ObservedObject
private var context: RichTextContext

@Environment(\.richTextFormatSidebarConfig)
var config

@Environment(\.richTextFormatSidebarStyle)
var style

public var body: some View {
VStack(alignment: .leading, spacing: style.spacing) {
SidebarSection {
fontPicker(value: $context.fontName)
HStack {
styleToggleGroup(for: context)
Spacer()
fontSizePicker(for: context)
}
}

Divider()

SidebarSection {
alignmentPicker(value: $context.textAlignment)
HStack {
lineSpacingPicker(for: context)
}
HStack {
indentButtons(for: context, greedy: true)
superscriptButtons(for: context, greedy: true)
}
}

Divider()

if hasColorPickers {
SidebarSection {
colorPickers(for: context)
}
.padding(.trailing, -8)
Divider()
}

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

private struct SidebarSection<Content: View>: View {

@ViewBuilder
let content: () -> Content

@Environment(\.richTextFormatToolbarStyle)
var style

var body: some View {
VStack(alignment: .leading, spacing: style.spacing) {
content()
}
}
}

public extension View {

/// Apply a rich text format sidebar config.
func richTextFormatSidebarConfig(
_ value: RichTextFormat.Sidebar.Config
) -> some View {
self.environment(\.richTextFormatSidebarConfig, value)
}

/// Apply a rich text format sidebar style.
func richTextFormatSidebarStyle(
_ value: RichTextFormat.Sidebar.Style
) -> some View {
self.environment(\.richTextFormatSidebarStyle, value)
}
}

private extension RichTextFormat.Sidebar.Config {

struct Key: EnvironmentKey {

static let defaultValue = RichTextFormat.Sidebar.Config()
}
}

private extension RichTextFormat.Sidebar.Style {

struct Key: EnvironmentKey {

static let defaultValue = RichTextFormat.Sidebar.Style()
}
}

public extension EnvironmentValues {

/// This value can bind to a format sidebar config.
var richTextFormatSidebarConfig: RichTextFormat.Sidebar.Config {
get { self [RichTextFormat.Sidebar.Config.Key.self] }
set { self [RichTextFormat.Sidebar.Config.Key.self] = newValue }
}

/// This value can bind to a format sidebar style.
var richTextFormatSidebarStyle: RichTextFormat.Sidebar.Style {
get { self [RichTextFormat.Sidebar.Style.Key.self] }
set { self [RichTextFormat.Sidebar.Style.Key.self] = newValue }
}
}

struct RichTextFormat_Sidebar_Previews: PreviewProvider {

struct Preview: View {

@StateObject
private var context = RichTextContext()

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

static var previews: some View {
Preview()
.frame(minWidth: 350)
}
}
#endif
Loading

0 comments on commit 5ab1087

Please sign in to comment.