@fluidframework/react 2.91.0 → 2.92.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/lib/alpha.d.ts +1 -1
- package/lib/beta.d.ts +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/public.d.ts +1 -1
- package/lib/test/text/textEditor.test.js +88 -731
- package/lib/test/text/textEditor.test.js.map +1 -1
- package/lib/text/index.d.ts +3 -2
- package/lib/text/index.d.ts.map +1 -1
- package/lib/text/index.js +1 -2
- package/lib/text/index.js.map +1 -1
- package/lib/text/plain/index.d.ts +1 -1
- package/lib/text/plain/index.d.ts.map +1 -1
- package/lib/text/plain/index.js +1 -1
- package/lib/text/plain/index.js.map +1 -1
- package/lib/text/plain/plainTextView.d.ts +5 -2
- package/lib/text/plain/plainTextView.d.ts.map +1 -1
- package/lib/text/plain/plainTextView.js.map +1 -1
- package/lib/text/plain/plainUtils.d.ts +1 -0
- package/lib/text/plain/plainUtils.d.ts.map +1 -1
- package/lib/text/plain/plainUtils.js +1 -0
- package/lib/text/plain/plainUtils.js.map +1 -1
- package/package.json +14 -16
- package/react.test-files.tar +0 -0
- package/src/index.ts +1 -9
- package/src/text/index.ts +3 -10
- package/src/text/plain/index.ts +1 -1
- package/src/text/plain/plainTextView.tsx +2 -2
- package/src/text/plain/plainUtils.ts +1 -0
- package/tsconfig.json +0 -6
- package/lib/test/mochaHooks.js +0 -13
- package/lib/test/mochaHooks.js.map +0 -1
- package/lib/text/formatted/index.d.ts +0 -6
- package/lib/text/formatted/index.d.ts.map +0 -1
- package/lib/text/formatted/index.js +0 -6
- package/lib/text/formatted/index.js.map +0 -1
- package/lib/text/formatted/quillFormattedView.d.ts +0 -66
- package/lib/text/formatted/quillFormattedView.d.ts.map +0 -1
- package/lib/text/formatted/quillFormattedView.js +0 -520
- package/lib/text/formatted/quillFormattedView.js.map +0 -1
- package/lib/text/plain/quillView.d.ts +0 -22
- package/lib/text/plain/quillView.d.ts.map +0 -1
- package/lib/text/plain/quillView.js +0 -106
- package/lib/text/plain/quillView.js.map +0 -1
- package/src/text/formatted/index.ts +0 -11
- package/src/text/formatted/quillFormattedView.tsx +0 -627
- package/src/text/plain/quillView.tsx +0 -149
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { TextAsTree } from "@fluidframework/tree/internal";
|
|
7
|
-
import Quill from "quill";
|
|
8
|
-
import { type FC, useEffect, useRef } from "react";
|
|
9
|
-
|
|
10
|
-
import type { PropTreeNode } from "../../propNode.js";
|
|
11
|
-
import { withMemoizedTreeObservations } from "../../useTree.js";
|
|
12
|
-
|
|
13
|
-
import { syncTextToTree } from "./plainUtils.js";
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Props for the MainView component.
|
|
17
|
-
* @input @internal
|
|
18
|
-
*/
|
|
19
|
-
export interface MainViewProps {
|
|
20
|
-
root: PropTreeNode<TextAsTree.Tree>;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* A React component for plain text editing.
|
|
25
|
-
* @remarks
|
|
26
|
-
* Uses {@link @fluidframework/tree#TextAsTree.Tree} for the data-model and Quill for the UI.
|
|
27
|
-
* @internal
|
|
28
|
-
*/
|
|
29
|
-
export const MainView: FC<MainViewProps> = ({ root }) => {
|
|
30
|
-
return <TextEditorView root={root} />;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* The text editor view component with Quill integration.
|
|
35
|
-
* Uses TextAsTree for collaborative plain text storage.
|
|
36
|
-
*
|
|
37
|
-
* @remarks
|
|
38
|
-
* This uses withMemoizedTreeObservations to automatically re-render
|
|
39
|
-
* when the tree changes.
|
|
40
|
-
*/
|
|
41
|
-
const TextEditorView = withMemoizedTreeObservations(({ root }: { root: TextAsTree.Tree }) => {
|
|
42
|
-
// DOM element where Quill will mount its editor
|
|
43
|
-
const editorRef = useRef<HTMLDivElement>(null);
|
|
44
|
-
// Quill instance, persisted across renders to avoid re-initialization
|
|
45
|
-
const quillRef = useRef<Quill | null>(null);
|
|
46
|
-
// Guards against update loops between Quill and the tree
|
|
47
|
-
const isUpdatingRef = useRef<boolean>(false);
|
|
48
|
-
|
|
49
|
-
// Access tree content during render to establish observation.
|
|
50
|
-
// The HOC will automatically re-render when this content changes.
|
|
51
|
-
const currentText = root.fullString();
|
|
52
|
-
|
|
53
|
-
// Initialize Quill editor
|
|
54
|
-
useEffect(() => {
|
|
55
|
-
if (editorRef.current && !quillRef.current) {
|
|
56
|
-
const quill = new Quill(editorRef.current, {
|
|
57
|
-
placeholder: "Start typing...",
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
// Set initial content from tree (add trailing newline to match Quill's convention)
|
|
61
|
-
const initialText = root.fullString();
|
|
62
|
-
if (initialText.length > 0) {
|
|
63
|
-
const textWithNewline = initialText.endsWith("\n") ? initialText : `${initialText}\n`;
|
|
64
|
-
quill.setText(textWithNewline);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Listen to local Quill changes
|
|
68
|
-
quill.on("text-change", (_delta, _oldDelta, source) => {
|
|
69
|
-
if (source === "user" && !isUpdatingRef.current) {
|
|
70
|
-
isUpdatingRef.current = true;
|
|
71
|
-
|
|
72
|
-
// Get plain text from Quill and preserve trailing newline
|
|
73
|
-
const newText = quill.getText();
|
|
74
|
-
// TODO: Consider using delta from Quill to compute a more minimal update,
|
|
75
|
-
// and maybe add a debugAssert that the delta actually gets the strings synchronized.
|
|
76
|
-
syncTextToTree(root, newText);
|
|
77
|
-
|
|
78
|
-
isUpdatingRef.current = false;
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
quillRef.current = quill;
|
|
83
|
-
}
|
|
84
|
-
// In React strict mode, effects run twice. The `!quillRef.current` check above
|
|
85
|
-
// makes the second call a no-op, preventing double-initialization of Quill.
|
|
86
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
87
|
-
}, []);
|
|
88
|
-
|
|
89
|
-
// Sync Quill when tree changes externally.
|
|
90
|
-
// We skip this if isUpdatingRef is true, meaning we caused the tree change ourselves
|
|
91
|
-
// via the text-change handler above - in that case Quill already has the correct content.
|
|
92
|
-
// No update is lost because isUpdatingRef is only true synchronously during our own
|
|
93
|
-
// handler execution, so Quill already reflects the change.
|
|
94
|
-
if (quillRef.current && !isUpdatingRef.current) {
|
|
95
|
-
const quillText = quillRef.current.getText();
|
|
96
|
-
// Normalize tree text to match Quill's trailing newline convention
|
|
97
|
-
const treeTextWithNewline = currentText.endsWith("\n") ? currentText : `${currentText}\n`;
|
|
98
|
-
|
|
99
|
-
// Only update if content actually differs (avoids cursor jump on local edits)
|
|
100
|
-
if (quillText !== treeTextWithNewline) {
|
|
101
|
-
isUpdatingRef.current = true;
|
|
102
|
-
|
|
103
|
-
const selection = quillRef.current.getSelection();
|
|
104
|
-
quillRef.current.setText(treeTextWithNewline);
|
|
105
|
-
if (selection) {
|
|
106
|
-
const length = quillRef.current.getLength();
|
|
107
|
-
const newPosition = Math.min(selection.index, length - 1);
|
|
108
|
-
quillRef.current.setSelection(newPosition, 0);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
isUpdatingRef.current = false;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return (
|
|
116
|
-
<div
|
|
117
|
-
className="text-editor-container"
|
|
118
|
-
style={{ height: "100%", display: "flex", flexDirection: "column" }}
|
|
119
|
-
>
|
|
120
|
-
<style>
|
|
121
|
-
{`
|
|
122
|
-
.ql-container {
|
|
123
|
-
height: 100%;
|
|
124
|
-
font-size: 14px;
|
|
125
|
-
}
|
|
126
|
-
.ql-editor {
|
|
127
|
-
height: 100%;
|
|
128
|
-
outline: none;
|
|
129
|
-
}
|
|
130
|
-
.ql-editor.ql-blank::before {
|
|
131
|
-
color: #999;
|
|
132
|
-
font-style: italic;
|
|
133
|
-
}
|
|
134
|
-
`}
|
|
135
|
-
</style>
|
|
136
|
-
<h2 style={{ margin: "10px 0" }}>Collaborative Text Editor</h2>
|
|
137
|
-
<div
|
|
138
|
-
ref={editorRef}
|
|
139
|
-
style={{
|
|
140
|
-
flex: 1,
|
|
141
|
-
minHeight: "300px",
|
|
142
|
-
border: "1px solid #ccc",
|
|
143
|
-
borderRadius: "4px",
|
|
144
|
-
padding: "8px",
|
|
145
|
-
}}
|
|
146
|
-
/>
|
|
147
|
-
</div>
|
|
148
|
-
);
|
|
149
|
-
});
|