Skip to content

Commit ab37160

Browse files
authored
Merge branch 'superlistapp:main' into feature/allow-scrolling-within-super-text-field
2 parents a2cf922 + 4c7472b commit ab37160

File tree

102 files changed

+4743
-500
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+4743
-500
lines changed

super_editor/clones/quill/lib/editor/blockquote_component.dart

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class FeatherBlockquoteComponentBuilder extends BlockquoteComponentBuilder {
2828
selectionColor: componentViewModel.selectionColor,
2929
highlightWhenEmpty: componentViewModel.highlightWhenEmpty,
3030
composingRegion: componentViewModel.composingRegion,
31-
showComposingUnderline: componentViewModel.showComposingUnderline,
31+
showComposingRegionUnderline: componentViewModel.showComposingRegionUnderline,
3232
);
3333
}
3434
}
@@ -48,7 +48,7 @@ class FeatherBlockquoteComponent extends StatelessWidget {
4848
required this.borderRadius,
4949
this.highlightWhenEmpty = false,
5050
this.composingRegion,
51-
this.showComposingUnderline = false,
51+
this.showComposingRegionUnderline = false,
5252
this.showDebugPaint = false,
5353
});
5454

@@ -62,7 +62,7 @@ class FeatherBlockquoteComponent extends StatelessWidget {
6262
final BorderRadius borderRadius;
6363
final bool highlightWhenEmpty;
6464
final TextRange? composingRegion;
65-
final bool showComposingUnderline;
65+
final bool showComposingRegionUnderline;
6666
final bool showDebugPaint;
6767

6868
@override
@@ -84,11 +84,20 @@ class FeatherBlockquoteComponent extends StatelessWidget {
8484
textSelection: textSelection,
8585
selectionColor: selectionColor,
8686
highlightWhenEmpty: highlightWhenEmpty,
87-
composingRegion: composingRegion,
88-
showComposingUnderline: showComposingUnderline,
87+
underlines: _createUnderlines(),
8988
showDebugPaint: showDebugPaint,
9089
),
9190
),
9291
);
9392
}
93+
94+
List<Underlines> _createUnderlines() {
95+
return [
96+
if (composingRegion != null && showComposingRegionUnderline)
97+
Underlines(
98+
style: const StraightUnderlineStyle(),
99+
underlines: [composingRegion!],
100+
),
101+
];
102+
}
94103
}

super_editor/clones/quill/lib/editor/code_component.dart

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ class FeatherCodeComponentBuilder implements ComponentBuilder {
6161
textSelection: componentViewModel.selection,
6262
selectionColor: componentViewModel.selectionColor,
6363
highlightWhenEmpty: componentViewModel.highlightWhenEmpty,
64-
composingRegion: componentViewModel.composingRegion,
65-
showComposingUnderline: componentViewModel.showComposingUnderline,
64+
underlines: componentViewModel.createUnderlines(),
6665
);
6766
}
6867
}
@@ -81,9 +80,17 @@ class CodeBlockComponentViewModel extends SingleColumnLayoutComponentViewModel w
8180
this.selection,
8281
required this.selectionColor,
8382
this.highlightWhenEmpty = false,
84-
this.composingRegion,
85-
this.showComposingUnderline = false,
86-
});
83+
TextRange? composingRegion,
84+
bool showComposingRegionUnderline = false,
85+
UnderlineStyle spellingErrorUnderlineStyle = const SquiggleUnderlineStyle(color: Color(0xFFFF0000)),
86+
List<TextRange> spellingErrors = const <TextRange>[],
87+
}) {
88+
this.composingRegion = composingRegion;
89+
this.showComposingRegionUnderline = showComposingRegionUnderline;
90+
91+
this.spellingErrorUnderlineStyle = spellingErrorUnderlineStyle;
92+
this.spellingErrors = spellingErrors;
93+
}
8794

8895
@override
8996
AttributedText text;
@@ -99,10 +106,6 @@ class CodeBlockComponentViewModel extends SingleColumnLayoutComponentViewModel w
99106
Color selectionColor;
100107
@override
101108
bool highlightWhenEmpty;
102-
@override
103-
TextRange? composingRegion;
104-
@override
105-
bool showComposingUnderline;
106109

107110
Color backgroundColor;
108111
BorderRadius borderRadius;
@@ -130,7 +133,9 @@ class CodeBlockComponentViewModel extends SingleColumnLayoutComponentViewModel w
130133
selectionColor: selectionColor,
131134
highlightWhenEmpty: highlightWhenEmpty,
132135
composingRegion: composingRegion,
133-
showComposingUnderline: showComposingUnderline,
136+
showComposingRegionUnderline: showComposingRegionUnderline,
137+
spellingErrorUnderlineStyle: spellingErrorUnderlineStyle,
138+
spellingErrors: List.from(spellingErrors),
134139
);
135140
}
136141

@@ -150,7 +155,7 @@ class CodeBlockComponentViewModel extends SingleColumnLayoutComponentViewModel w
150155
selectionColor == other.selectionColor &&
151156
highlightWhenEmpty == other.highlightWhenEmpty &&
152157
composingRegion == other.composingRegion &&
153-
showComposingUnderline == other.showComposingUnderline;
158+
showComposingRegionUnderline == other.showComposingRegionUnderline;
154159

155160
@override
156161
int get hashCode =>
@@ -165,7 +170,7 @@ class CodeBlockComponentViewModel extends SingleColumnLayoutComponentViewModel w
165170
selectionColor.hashCode ^
166171
highlightWhenEmpty.hashCode ^
167172
composingRegion.hashCode ^
168-
showComposingUnderline.hashCode;
173+
showComposingRegionUnderline.hashCode;
169174
}
170175

171176
class CodeBlockComponent extends StatelessWidget {
@@ -180,8 +185,7 @@ class CodeBlockComponent extends StatelessWidget {
180185
required this.backgroundColor,
181186
required this.borderRadius,
182187
this.highlightWhenEmpty = false,
183-
this.composingRegion,
184-
this.showComposingUnderline = false,
188+
this.underlines = const [],
185189
this.showDebugPaint = false,
186190
});
187191

@@ -194,8 +198,9 @@ class CodeBlockComponent extends StatelessWidget {
194198
final Color backgroundColor;
195199
final BorderRadius borderRadius;
196200
final bool highlightWhenEmpty;
197-
final TextRange? composingRegion;
198-
final bool showComposingUnderline;
201+
202+
final List<Underlines> underlines;
203+
199204
final bool showDebugPaint;
200205

201206
@override
@@ -216,8 +221,7 @@ class CodeBlockComponent extends StatelessWidget {
216221
textSelection: textSelection,
217222
selectionColor: selectionColor,
218223
highlightWhenEmpty: highlightWhenEmpty,
219-
composingRegion: composingRegion,
220-
showComposingUnderline: showComposingUnderline,
224+
underlines: underlines,
221225
showDebugPaint: showDebugPaint,
222226
),
223227
),

super_editor/clones/quill/pubspec.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ dependency_overrides:
2828
path: ../../../super_editor_quill
2929
super_editor_markdown:
3030
path: ../../../super_editor_markdown
31+
super_text_layout:
32+
path: ../../../super_text_layout
3133

3234
dev_dependencies:
3335
flutter_test:

super_editor/example/lib/demos/components/demo_text_with_hint.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ class HeaderWithHintComponentBuilder implements ComponentBuilder {
192192
textSelection: textSelection,
193193
selectionColor: componentViewModel.selectionColor,
194194
composingRegion: componentViewModel.composingRegion,
195-
showComposingUnderline: componentViewModel.showComposingUnderline,
195+
showComposingUnderline: componentViewModel.showComposingRegionUnderline,
196196
);
197197
}
198198
}

super_editor/example/lib/demos/example_editor/example_editor.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class _ExampleEditorState extends State<ExampleEditor> {
5656
_doc = createInitialDocument()..addListener(_onDocumentChange);
5757
_composer = MutableDocumentComposer();
5858
_composer.selectionNotifier.addListener(_hideOrShowToolbar);
59-
_docEditor = createDefaultDocumentEditor(document: _doc, composer: _composer);
59+
_docEditor = createDefaultDocumentEditor(document: _doc, composer: _composer, isHistoryEnabled: true);
6060
_docOps = CommonEditorOperations(
6161
editor: _docEditor,
6262
document: _doc,
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
import 'package:example/demos/in_the_lab/in_the_lab_scaffold.dart';
2+
import 'package:flutter/material.dart';
3+
import 'package:super_editor/super_editor.dart';
4+
5+
class SpellingErrorDecorationsDemo extends StatefulWidget {
6+
const SpellingErrorDecorationsDemo({super.key});
7+
8+
@override
9+
State<SpellingErrorDecorationsDemo> createState() => _SpellingErrorDecorationsDemoState();
10+
}
11+
12+
class _SpellingErrorDecorationsDemoState extends State<SpellingErrorDecorationsDemo> {
13+
late final MutableDocument _document;
14+
late final MutableDocumentComposer _composer;
15+
late final Editor _editor;
16+
17+
// The meaning of a `null` decoration is a desire to set
18+
// the decoration in the stylesheet.
19+
_DecorationType? _decoration = _DecorationType.squiggles;
20+
21+
@override
22+
void initState() {
23+
super.initState();
24+
25+
_document = MutableDocument(nodes: [
26+
ParagraphNode(
27+
id: Editor.createNodeId(),
28+
text: AttributedText(
29+
"SuperEditor cna sytle spelling error attribtions with various decorations, including custom decorations.",
30+
AttributedSpans(
31+
attributions: [
32+
SpanMarker(attribution: spellingErrorAttribution, offset: 12, markerType: SpanMarkerType.start),
33+
SpanMarker(attribution: spellingErrorAttribution, offset: 14, markerType: SpanMarkerType.end),
34+
SpanMarker(attribution: spellingErrorAttribution, offset: 16, markerType: SpanMarkerType.start),
35+
SpanMarker(attribution: spellingErrorAttribution, offset: 20, markerType: SpanMarkerType.end),
36+
SpanMarker(attribution: spellingErrorAttribution, offset: 37, markerType: SpanMarkerType.start),
37+
SpanMarker(attribution: spellingErrorAttribution, offset: 47, markerType: SpanMarkerType.end),
38+
],
39+
),
40+
),
41+
),
42+
]);
43+
_composer = MutableDocumentComposer();
44+
_editor = createDefaultDocumentEditor(document: _document, composer: _composer);
45+
}
46+
47+
@override
48+
Widget build(BuildContext context) {
49+
return InTheLabScaffold(
50+
content: Center(
51+
child: IntrinsicHeight(
52+
child: _buildEditor(),
53+
),
54+
),
55+
supplemental: _buildControlPanel(),
56+
);
57+
}
58+
59+
Widget _buildEditor() {
60+
return SuperEditor(
61+
editor: _editor,
62+
componentBuilders: [
63+
// When `_decoration` is non-null, we apply it directly to our own
64+
// custom component to show direct application. When it's `null`,
65+
// we specify the decoration in the stylesheet and let it flow down
66+
// to the standard components.
67+
//
68+
// As a result, we're able to demo both direct and indirect application
69+
// of the underline style.
70+
if (_decoration != null) //
71+
SpellingErrorParagraphComponentBuilder(_decoration!.style),
72+
...defaultComponentBuilders,
73+
],
74+
stylesheet: defaultStylesheet.copyWith(
75+
addRulesAfter: [
76+
...darkModeStyles,
77+
// When `_decoration` is null, place the underline in the
78+
// stylesheet instead of applying it directly to each component.
79+
if (_decoration == null)
80+
StyleRule(
81+
BlockSelector.all,
82+
(doc, docNode) {
83+
return {
84+
Styles.spellingErrorUnderlineStyle: SquiggleUnderlineStyle(color: Colors.blue),
85+
};
86+
},
87+
),
88+
],
89+
),
90+
documentOverlayBuilders: [
91+
DefaultCaretOverlayBuilder(
92+
caretStyle: CaretStyle().copyWith(color: Colors.redAccent),
93+
),
94+
],
95+
);
96+
}
97+
98+
Widget _buildControlPanel() {
99+
return Padding(
100+
padding: const EdgeInsets.all(24),
101+
child: Column(
102+
mainAxisSize: MainAxisSize.min,
103+
children: [
104+
_buildButton(
105+
label: "From Stylesheet",
106+
isEnabled: _decoration != null,
107+
onPressed: () {
108+
setState(() {
109+
_decoration = null;
110+
});
111+
},
112+
),
113+
const SizedBox(height: 16),
114+
_buildButton(
115+
label: "Line",
116+
isEnabled: _decoration != _DecorationType.line,
117+
onPressed: () {
118+
setState(() {
119+
_decoration = _DecorationType.line;
120+
});
121+
},
122+
),
123+
const SizedBox(height: 16),
124+
_buildButton(
125+
label: "Dots",
126+
isEnabled: _decoration != _DecorationType.dots,
127+
onPressed: () {
128+
setState(() {
129+
_decoration = _DecorationType.dots;
130+
});
131+
},
132+
),
133+
const SizedBox(height: 16),
134+
_buildButton(
135+
label: "Squiggles",
136+
isEnabled: _decoration != _DecorationType.squiggles,
137+
onPressed: () {
138+
setState(() {
139+
_decoration = _DecorationType.squiggles;
140+
});
141+
},
142+
),
143+
],
144+
),
145+
);
146+
}
147+
148+
Widget _buildButton({
149+
required String label,
150+
bool isEnabled = true,
151+
required VoidCallback onPressed,
152+
}) {
153+
return ElevatedButton(
154+
onPressed: isEnabled ? onPressed : null,
155+
child: Text(label),
156+
);
157+
}
158+
}
159+
160+
enum _DecorationType {
161+
line,
162+
dots,
163+
squiggles;
164+
165+
UnderlineStyle get style {
166+
switch (this) {
167+
case _DecorationType.line:
168+
return StraightUnderlineStyle(
169+
color: Colors.red,
170+
);
171+
case _DecorationType.dots:
172+
return DottedUnderlineStyle();
173+
case _DecorationType.squiggles:
174+
return SquiggleUnderlineStyle();
175+
}
176+
}
177+
}
178+
179+
class SpellingErrorParagraphComponentBuilder implements ComponentBuilder {
180+
const SpellingErrorParagraphComponentBuilder(this.underlineStyle);
181+
182+
final UnderlineStyle underlineStyle;
183+
184+
@override
185+
SingleColumnLayoutComponentViewModel? createViewModel(Document document, DocumentNode node) {
186+
final viewModel = ParagraphComponentBuilder().createViewModel(document, node) as ParagraphComponentViewModel?;
187+
if (viewModel == null) {
188+
return null;
189+
}
190+
191+
print("Creating paragraph view model with style: $underlineStyle");
192+
return viewModel
193+
..spellingErrorUnderlineStyle = underlineStyle
194+
..spellingErrors = (node as TextNode)
195+
.text
196+
.getAttributionSpansByFilter((a) => a == spellingErrorAttribution)
197+
.map((a) => TextRange(start: a.start, end: a.end + 1)) // +1 because text range end is exclusive
198+
.toList();
199+
}
200+
201+
@override
202+
ParagraphComponent? createComponent(
203+
SingleColumnDocumentComponentContext componentContext,
204+
SingleColumnLayoutComponentViewModel componentViewModel,
205+
) {
206+
return ParagraphComponentBuilder().createComponent(componentContext, componentViewModel);
207+
}
208+
}

0 commit comments

Comments
 (0)