Skip to content

Commit b2d97b6

Browse files
committed
Add rich text view configuration type
1 parent 3b98f7e commit b2d97b6

File tree

8 files changed

+104
-45
lines changed

8 files changed

+104
-45
lines changed

Demo/iOS/EditorScreen.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,11 @@ struct EditorScreen: View {
4040
private extension EditorScreen {
4141

4242
var editor: some View {
43-
RichTextEditor(text: $text, context: context) {
43+
RichTextEditor(
44+
text: $text,
45+
context: context,
46+
config: .init(isScrollingEnabled: false)
47+
) {
4448
$0.textContentInset = CGSize(width: 10, height: 20)
4549
}
4650
.background(Material.regular)

Demo/macOS/EditorScreen.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ struct EditorScreen: View {
4545
private extension EditorScreen {
4646

4747
var editor: some View {
48-
RichTextEditor(text: $text, context: context) {
48+
RichTextEditor(
49+
text: $text,
50+
context: context,
51+
config: .init(isScrollingEnabled: false)
52+
) {
4953
$0.textContentInset = CGSize(width: 10, height: 20)
5054
}
5155
.frame(minWidth: 400)

RELEASE_NOTES.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@ Until then, minor updates may remove deprecated features and introduce breaking
1111

1212
Thanks to [@ropellanda][ropellanda], RichTextKit now supports Vision OS.
1313

14+
Thanks to [@screenworker][screenworker], RichTextEditor now has a `config` that can disable scrolling.
15+
1416
### ✨ Features
1517

1618
* `Image` has a new rich text-specific image builders.
19+
* `RichTextEditor` has a new `config` value parameter that can disable scrolling.
20+
* `RichTextView` has a new `configuration` property that can disable scrolling.
1721

1822
### 🗑️ Deprecations
1923

@@ -481,3 +485,4 @@ RichTextKit adds extensive support for a bunch of rich text features:
481485
[Mcrich23]: https://github.com/Mcrich23
482486
[msrutek-paylocity]: https://github.com/msrutek-paylocity
483487
[ropellanda]: https://github.com/ropellanda
488+
[screenworker]: https://github.com/screenworker

Sources/RichTextKit/Context/RichTextContext.swift

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -185,14 +185,7 @@ public extension RichTextContext {
185185
highlightedRange = range
186186
}
187187

188-
/**
189-
Paste an image into the text view, at a certain index.
190-
191-
- Parameters:
192-
- image: The image to paste.
193-
- index: The index to paste at, by default the `selectedRange` location.
194-
- moveCursorToPastedContent: Whether or not to move the cursor to the end of the pasted content, by default `false`.
195-
*/
188+
/// Paste an image into the editor, at a certain index.
196189
func pasteImage(
197190
_ image: ImageRepresentable,
198191
at index: Int? = nil,
@@ -202,15 +195,8 @@ public extension RichTextContext {
202195
shouldPasteImage = (image, index, moveCursorToPastedContent)
203196
}
204197

205-
/**
206-
Paste images into the text view, at a certain index.
207-
208-
- Parameters:
209-
- images: The images to paste.
210-
- index: The index to paste at, by default the `selectedRange` location.
211-
- moveCursorToPastedContent: Whether or not to move the cursor to the end of the pasted content, by default `false`.
212-
*/
213-
func pasteImage(
198+
/// Paste images into the editor, at a certain index.
199+
func pasteImages(
214200
_ images: [ImageRepresentable],
215201
at index: Int? = nil,
216202
moveCursorToPastedContent: Bool = false
@@ -219,14 +205,7 @@ public extension RichTextContext {
219205
shouldPasteImages = (images, index, moveCursorToPastedContent)
220206
}
221207

222-
/**
223-
Paste text into the text view, at a certain index.
224-
225-
- Parameters:
226-
- text: The text to paste.
227-
- index: The index to paste at, by default the `selectedRange` location.
228-
- moveCursorToPastedContent: Whether or not to move the cursor to the end of the pasted content, by default `false`.
229-
*/
208+
/// Paste text into the editor, at a certain index.
230209
func pasteText(
231210
_ text: String,
232211
at index: Int? = nil,

Sources/RichTextKit/RichTextEditor.swift

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ import SwiftUI
1818

1919
You can use the provided context to trigger and observe any
2020
changes to the text editor. Note that changing the value of
21-
the `text` binding will not (yet) update this editor. Until
22-
it is fixed, use `setAttributedString(to:)` to set the rich
23-
text or plain string to another value.
21+
the `text` binding will not yet update the editor. Until it
22+
is fixed, use `setAttributedString(to:)`.
2423

2524
Since the view wraps a native `UIKit` or `AppKit` text view,
2625
you can't apply `.toolbar` modifiers to it, like you can do
@@ -51,33 +50,33 @@ public struct RichTextEditor: ViewRepresentable {
5150
- Parameters:
5251
- text: The rich text to edit.
5352
- context: The rich text context to use.
53+
- config: The rich text configuration to use, by deafult `standard`.
5454
- format: The rich text data format, by default ``RichTextDataFormat/archivedData``.
5555
*/
5656
public init(
5757
text: Binding<NSAttributedString>,
5858
context: RichTextContext,
59+
config: RichTextView.Configuration = .standard,
5960
format: RichTextDataFormat = .archivedData,
6061
viewConfiguration: @escaping ViewConfiguration = { _ in }
6162
) {
6263
self.text = text
63-
self._richTextContext = ObservedObject(wrappedValue: context)
64+
self.config = config
65+
self._context = ObservedObject(wrappedValue: context)
6466
self.format = format
6567
self.viewConfiguration = viewConfiguration
6668
}
6769

6870
public typealias ViewConfiguration = (RichTextViewComponent) -> Void
69-
70-
71-
private var format: RichTextDataFormat
72-
73-
private var text: Binding<NSAttributedString>
74-
71+
7572
@ObservedObject
76-
private var richTextContext: RichTextContext
77-
73+
private var context: RichTextContext
74+
75+
private var text: Binding<NSAttributedString>
76+
private let config: RichTextView.Configuration
77+
private var format: RichTextDataFormat
7878
private var viewConfiguration: ViewConfiguration
7979

80-
8180
#if iOS || os(tvOS) || os(visionOS)
8281
public let textView = RichTextView()
8382
#endif
@@ -95,24 +94,26 @@ public struct RichTextEditor: ViewRepresentable {
9594
RichTextCoordinator(
9695
text: text,
9796
textView: textView,
98-
richTextContext: richTextContext
97+
richTextContext: context
9998
)
10099
}
101100

102101

103102
#if iOS || os(tvOS) || os(visionOS)
104103
public func makeUIView(context: Context) -> some UIView {
105104
textView.setup(with: text.wrappedValue, format: format)
105+
textView.configuration = config
106106
viewConfiguration(textView)
107107
return textView
108108
}
109109

110110
public func updateUIView(_ view: UIViewType, context: Context) {}
111-
#endif
112-
113-
#if macOS
111+
112+
#else
113+
114114
public func makeNSView(context: Context) -> some NSView {
115115
textView.setup(with: text.wrappedValue, format: format)
116+
textView.configuration = config
116117
viewConfiguration(textView)
117118
return scrollView
118119
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//
2+
// RichTextView+Config.swift
3+
// RichTextKit
4+
//
5+
// Created by Daniel Saidi on 2024-01-16.
6+
// Copyright © 2024 Daniel Saidi. All rights reserved.
7+
//
8+
9+
#if iOS || macOS || os(tvOS) || os(visionOS)
10+
import SwiftUI
11+
12+
public extension RichTextView {
13+
14+
/**
15+
This type can be used to configure a ``RichTextEditor``.
16+
*/
17+
struct Configuration {
18+
19+
/**
20+
Create a custom configuration.
21+
22+
- Parameters:
23+
- isScrollingEnabled: Whether or not the editor should scroll, by default `true`.
24+
*/
25+
public init(
26+
isScrollingEnabled: Bool = true
27+
) {
28+
self.isScrollingEnabled = isScrollingEnabled
29+
}
30+
31+
/// Whether or not the editor should scroll.
32+
public var isScrollingEnabled: Bool
33+
}
34+
}
35+
36+
public extension RichTextView.Configuration {
37+
38+
/// Get a standard rich text editor configuration.
39+
static var standard: Self { .init() }
40+
}
41+
#endif

Sources/RichTextKit/RichTextView_AppKit.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ import AppKit
2626
open class RichTextView: NSTextView, RichTextViewComponent {
2727

2828
// MARK: - Properties
29+
30+
/// The configuration to use by the rich text view.
31+
public var configuration: Configuration = .standard
2932

3033
/// The style to use when highlighting text in the view.
3134
public var highlightingStyle: RichTextHighlightingStyle = .standard
@@ -74,6 +77,21 @@ open class RichTextView: NSTextView, RichTextViewComponent {
7477

7578
return super.performDragOperation(draggingInfo)
7679
}
80+
81+
open override func scrollWheel(with event: NSEvent) {
82+
83+
if configuration.isScrollingEnabled {
84+
return super.scrollWheel(with: event)
85+
}
86+
87+
// 1st nextResponder is NSClipView
88+
// 2nd nextResponder is NSScrollView
89+
// 3rd nextResponder is NSResponder SwiftUIPlatformViewHost
90+
self.nextResponder?
91+
.nextResponder?
92+
.nextResponder?
93+
.scrollWheel(with: event)
94+
}
7795

7896

7997
// MARK: - Setup

Sources/RichTextKit/RichTextView_UIKit.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,14 @@ open class RichTextView: UITextView, RichTextViewComponent {
4747

4848

4949
// MARK: - Properties
50-
50+
51+
/// The configuration to use by the rich text view.
52+
public var configuration: Configuration = .standard {
53+
didSet {
54+
isScrollEnabled = configuration.isScrollingEnabled
55+
}
56+
}
57+
5158
/// The style to use when highlighting text in the view.
5259
public var highlightingStyle: RichTextHighlightingStyle = .standard
5360

0 commit comments

Comments
 (0)