Replace notes textarea with collaborative CodeMirror editor
- CodeMirror 6 + y-codemirror.next for proper character-level Yjs sync (replaces delete-all/insert-all textarea binding) - Remote cursor awareness: colored carets with participant names - Line wrapping, placeholder text, history (undo/redo) - Awareness user fields include colorLight for cursor selection tint Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
360bd87de2
commit
5f21564a19
3 changed files with 243 additions and 46 deletions
|
|
@ -1,66 +1,106 @@
|
|||
import { useEffect, useRef, useCallback } from "react";
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { EditorView, keymap, placeholder } from "@codemirror/view";
|
||||
import { EditorState } from "@codemirror/state";
|
||||
import { defaultKeymap, history, historyKeymap } from "@codemirror/commands";
|
||||
import { syntaxHighlighting, defaultHighlightStyle } from "@codemirror/language";
|
||||
import { yCollab } from "y-codemirror.next";
|
||||
import type { YjsState } from "~/lib/use-yjs";
|
||||
|
||||
interface NotesPanelProps {
|
||||
yjs: YjsState;
|
||||
}
|
||||
|
||||
const theme = EditorView.theme({
|
||||
"&": {
|
||||
height: "100%",
|
||||
fontSize: "13px",
|
||||
},
|
||||
".cm-editor": {
|
||||
height: "100%",
|
||||
},
|
||||
".cm-scroller": {
|
||||
overflow: "auto",
|
||||
fontFamily: "inherit",
|
||||
},
|
||||
".cm-content": {
|
||||
padding: "12px",
|
||||
caretColor: "#1f2937",
|
||||
},
|
||||
".cm-line": {
|
||||
lineHeight: "1.5",
|
||||
},
|
||||
"&.cm-focused": {
|
||||
outline: "none",
|
||||
},
|
||||
// Remote cursor styling
|
||||
".cm-ySelectionInfo": {
|
||||
fontSize: "10px",
|
||||
fontFamily: "system-ui, sans-serif",
|
||||
padding: "1px 4px",
|
||||
borderRadius: "3px",
|
||||
opacity: "0.9",
|
||||
fontWeight: "500",
|
||||
position: "absolute",
|
||||
top: "-1.2em",
|
||||
left: "-1px",
|
||||
whiteSpace: "nowrap",
|
||||
},
|
||||
});
|
||||
|
||||
export function NotesPanel({ yjs }: NotesPanelProps) {
|
||||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
const isLocalChange = useRef(false);
|
||||
const { t } = useTranslation("planner");
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const viewRef = useRef<EditorView | null>(null);
|
||||
|
||||
// Sync Y.Text → textarea
|
||||
useEffect(() => {
|
||||
const textarea = textareaRef.current;
|
||||
if (!textarea) return;
|
||||
if (!containerRef.current) return;
|
||||
|
||||
// Set initial value
|
||||
textarea.value = yjs.notes.toString();
|
||||
// Set awareness user fields for cursor display
|
||||
const localState = yjs.awareness.getLocalState() as Record<string, unknown> | null;
|
||||
const user = localState?.user as { name: string; color: string } | undefined;
|
||||
if (user) {
|
||||
yjs.awareness.setLocalStateField("user", {
|
||||
...user,
|
||||
colorLight: user.color + "30",
|
||||
});
|
||||
}
|
||||
|
||||
const observer = () => {
|
||||
if (isLocalChange.current) return;
|
||||
const pos = textarea.selectionStart;
|
||||
textarea.value = yjs.notes.toString();
|
||||
textarea.selectionStart = pos;
|
||||
textarea.selectionEnd = pos;
|
||||
const state = EditorState.create({
|
||||
extensions: [
|
||||
keymap.of([...defaultKeymap, ...historyKeymap]),
|
||||
history(),
|
||||
syntaxHighlighting(defaultHighlightStyle),
|
||||
EditorView.lineWrapping,
|
||||
placeholder(t("notes.placeholder")),
|
||||
theme,
|
||||
yCollab(yjs.notes, yjs.awareness, {
|
||||
undoManager: yjs.undoManager,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
const view = new EditorView({
|
||||
state,
|
||||
parent: containerRef.current,
|
||||
});
|
||||
|
||||
viewRef.current = view;
|
||||
|
||||
return () => {
|
||||
view.destroy();
|
||||
viewRef.current = null;
|
||||
};
|
||||
|
||||
yjs.notes.observe(observer);
|
||||
return () => yjs.notes.unobserve(observer);
|
||||
}, [yjs.notes]);
|
||||
|
||||
// textarea → Y.Text
|
||||
const handleInput = useCallback(
|
||||
(e: React.FormEvent<HTMLTextAreaElement>) => {
|
||||
const textarea = e.currentTarget;
|
||||
const newValue = textarea.value;
|
||||
const currentValue = yjs.notes.toString();
|
||||
|
||||
if (newValue === currentValue) return;
|
||||
|
||||
isLocalChange.current = true;
|
||||
yjs.doc.transact(() => {
|
||||
yjs.notes.delete(0, yjs.notes.length);
|
||||
yjs.notes.insert(0, newValue);
|
||||
}, "local");
|
||||
isLocalChange.current = false;
|
||||
},
|
||||
[yjs.notes, yjs.doc],
|
||||
);
|
||||
}, [yjs]);
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-col">
|
||||
<div className="border-b border-gray-200 px-4 py-3">
|
||||
<h2 className="text-sm font-medium text-gray-900">Notes</h2>
|
||||
</div>
|
||||
<div className="flex-1 p-2">
|
||||
<textarea
|
||||
ref={textareaRef}
|
||||
onInput={handleInput}
|
||||
className="h-full w-full resize-none rounded border border-gray-200 p-3 text-sm text-gray-700 placeholder-gray-400 focus:border-blue-300 focus:outline-none"
|
||||
placeholder="Add notes for this session..."
|
||||
/>
|
||||
<h2 className="text-sm font-medium text-gray-900">
|
||||
{t("sidebar.notes")}
|
||||
</h2>
|
||||
</div>
|
||||
<div ref={containerRef} className="flex-1 overflow-hidden" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@
|
|||
"lint": "eslint ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@codemirror/commands": "^6.10.3",
|
||||
"@codemirror/language": "^6.12.3",
|
||||
"@codemirror/state": "^6.6.0",
|
||||
"@codemirror/view": "^6.41.0",
|
||||
"@geoman-io/leaflet-geoman-free": "^2.19.3",
|
||||
"@react-router/node": "catalog:",
|
||||
"@react-router/serve": "catalog:",
|
||||
|
|
@ -22,6 +26,7 @@
|
|||
"@trails-cool/map": "workspace:*",
|
||||
"@trails-cool/types": "workspace:*",
|
||||
"@trails-cool/ui": "workspace:*",
|
||||
"codemirror": "^6.0.2",
|
||||
"drizzle-orm": "catalog:",
|
||||
"isbot": "^5.1.37",
|
||||
"lib0": "^0.2.117",
|
||||
|
|
@ -31,6 +36,7 @@
|
|||
"react-dom": "catalog:",
|
||||
"react-router": "catalog:",
|
||||
"ws": "^8.20.0",
|
||||
"y-codemirror.next": "^0.3.5",
|
||||
"y-protocols": "^1.0.7",
|
||||
"y-websocket": "^3.0.0",
|
||||
"yjs": "^13.6.30"
|
||||
|
|
|
|||
151
pnpm-lock.yaml
generated
151
pnpm-lock.yaml
generated
|
|
@ -285,6 +285,18 @@ importers:
|
|||
|
||||
apps/planner:
|
||||
dependencies:
|
||||
'@codemirror/commands':
|
||||
specifier: ^6.10.3
|
||||
version: 6.10.3
|
||||
'@codemirror/language':
|
||||
specifier: ^6.12.3
|
||||
version: 6.12.3
|
||||
'@codemirror/state':
|
||||
specifier: ^6.6.0
|
||||
version: 6.6.0
|
||||
'@codemirror/view':
|
||||
specifier: ^6.41.0
|
||||
version: 6.41.0
|
||||
'@geoman-io/leaflet-geoman-free':
|
||||
specifier: ^2.19.3
|
||||
version: 2.19.3(leaflet@1.9.4)
|
||||
|
|
@ -318,6 +330,9 @@ importers:
|
|||
'@trails-cool/ui':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/ui
|
||||
codemirror:
|
||||
specifier: ^6.0.2
|
||||
version: 6.0.2
|
||||
drizzle-orm:
|
||||
specifier: 'catalog:'
|
||||
version: 0.45.2(@opentelemetry/api@1.9.1)(@types/pg@8.15.6)(postgres@3.4.9)
|
||||
|
|
@ -345,6 +360,9 @@ importers:
|
|||
ws:
|
||||
specifier: ^8.20.0
|
||||
version: 8.20.0
|
||||
y-codemirror.next:
|
||||
specifier: ^0.3.5
|
||||
version: 0.3.5(@codemirror/state@6.6.0)(@codemirror/view@6.41.0)(yjs@13.6.30)
|
||||
y-protocols:
|
||||
specifier: ^1.0.7
|
||||
version: 1.0.7(yjs@13.6.30)
|
||||
|
|
@ -588,6 +606,27 @@ packages:
|
|||
resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==}
|
||||
hasBin: true
|
||||
|
||||
'@codemirror/autocomplete@6.20.1':
|
||||
resolution: {integrity: sha512-1cvg3Vz1dSSToCNlJfRA2WSI4ht3K+WplO0UMOgmUYPivCyy2oueZY6Lx7M9wThm7SDUBViRmuT+OG/i8+ON9A==}
|
||||
|
||||
'@codemirror/commands@6.10.3':
|
||||
resolution: {integrity: sha512-JFRiqhKu+bvSkDLI+rUhJwSxQxYb759W5GBezE8Uc8mHLqC9aV/9aTC7yJSqCtB3F00pylrLCwnyS91Ap5ej4Q==}
|
||||
|
||||
'@codemirror/language@6.12.3':
|
||||
resolution: {integrity: sha512-QwCZW6Tt1siP37Jet9Tb02Zs81TQt6qQrZR2H+eGMcFsL1zMrk2/b9CLC7/9ieP1fjIUMgviLWMmgiHoJrj+ZA==}
|
||||
|
||||
'@codemirror/lint@6.9.5':
|
||||
resolution: {integrity: sha512-GElsbU9G7QT9xXhpUg1zWGmftA/7jamh+7+ydKRuT0ORpWS3wOSP0yT1FOlIZa7mIJjpVPipErsyvVqB9cfTFA==}
|
||||
|
||||
'@codemirror/search@6.6.0':
|
||||
resolution: {integrity: sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw==}
|
||||
|
||||
'@codemirror/state@6.6.0':
|
||||
resolution: {integrity: sha512-4nbvra5R5EtiCzr9BTHiTLc+MLXK2QGiAVYMyi8PkQd3SR+6ixar/Q/01Fa21TBIDOZXgeWV4WppsQolSreAPQ==}
|
||||
|
||||
'@codemirror/view@6.41.0':
|
||||
resolution: {integrity: sha512-6H/qadXsVuDY219Yljhohglve8xf4B8xJkVOEWfA5uiYKiTFppjqsvsfR5iPA0RbvRBoOyTZpbLIxe9+0UR8xA==}
|
||||
|
||||
'@csstools/color-helpers@6.0.2':
|
||||
resolution: {integrity: sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==}
|
||||
engines: {node: '>=20.19.0'}
|
||||
|
|
@ -1185,6 +1224,18 @@ packages:
|
|||
'@levischuck/tiny-cbor@0.2.11':
|
||||
resolution: {integrity: sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow==}
|
||||
|
||||
'@lezer/common@1.5.2':
|
||||
resolution: {integrity: sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ==}
|
||||
|
||||
'@lezer/highlight@1.2.3':
|
||||
resolution: {integrity: sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==}
|
||||
|
||||
'@lezer/lr@1.4.8':
|
||||
resolution: {integrity: sha512-bPWa0Pgx69ylNlMlPvBPryqeLYQjyJjqPx+Aupm5zydLIF3NE+6MMLT8Yi23Bd9cif9VS00aUebn+6fDIGBcDA==}
|
||||
|
||||
'@marijn/find-cluster-break@1.0.2':
|
||||
resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==}
|
||||
|
||||
'@mjackson/node-fetch-server@0.2.0':
|
||||
resolution: {integrity: sha512-EMlH1e30yzmTpGLQjlFmaDAjyOeZhng1/XCd7DExR8PNAnG/G1tyruZxEoUe11ClnwGhGrtsdnyyUx1frSzjng==}
|
||||
|
||||
|
|
@ -2368,6 +2419,9 @@ packages:
|
|||
cjs-module-lexer@2.2.0:
|
||||
resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==}
|
||||
|
||||
codemirror@6.0.2:
|
||||
resolution: {integrity: sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==}
|
||||
|
||||
colorette@2.0.20:
|
||||
resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
|
||||
|
||||
|
|
@ -2404,6 +2458,9 @@ packages:
|
|||
resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
crelt@1.0.6:
|
||||
resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==}
|
||||
|
||||
cross-spawn@7.0.6:
|
||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||
engines: {node: '>= 8'}
|
||||
|
|
@ -3627,6 +3684,9 @@ packages:
|
|||
resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
style-mod@4.1.3:
|
||||
resolution: {integrity: sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==}
|
||||
|
||||
sweepline-intersections@1.5.0:
|
||||
resolution: {integrity: sha512-AoVmx72QHpKtItPu72TzFL+kcYjd67BPLDoR0LarIk+xyaRg+pDTMFXndIEvZf9xEKnJv6JdhgRMnocoG0D3AQ==}
|
||||
|
||||
|
|
@ -3909,6 +3969,9 @@ packages:
|
|||
resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
w3c-keyname@2.2.8:
|
||||
resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==}
|
||||
|
||||
w3c-xmlserializer@5.0.0:
|
||||
resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==}
|
||||
engines: {node: '>=18'}
|
||||
|
|
@ -3974,6 +4037,13 @@ packages:
|
|||
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
|
||||
engines: {node: '>=0.4'}
|
||||
|
||||
y-codemirror.next@0.3.5:
|
||||
resolution: {integrity: sha512-VluNu3e5HfEXybnypnsGwKAj+fKLd4iAnR7JuX1Sfyydmn1jCBS5wwEL/uS04Ch2ib0DnMAOF6ZRR/8kK3wyGw==}
|
||||
peerDependencies:
|
||||
'@codemirror/state': ^6.0.0
|
||||
'@codemirror/view': ^6.0.0
|
||||
yjs: ^13.5.6
|
||||
|
||||
y-protocols@1.0.7:
|
||||
resolution: {integrity: sha512-YSVsLoXxO67J6eE/nV4AtFtT3QEotZf5sK5BHxFBXso7VDUT3Tx07IfA6hsu5Q5OmBdMkQVmFZ9QOA7fikWvnw==}
|
||||
engines: {node: '>=16.0.0', npm: '>=8.0.0'}
|
||||
|
|
@ -4209,6 +4279,52 @@ snapshots:
|
|||
dependencies:
|
||||
css-tree: 3.2.1
|
||||
|
||||
'@codemirror/autocomplete@6.20.1':
|
||||
dependencies:
|
||||
'@codemirror/language': 6.12.3
|
||||
'@codemirror/state': 6.6.0
|
||||
'@codemirror/view': 6.41.0
|
||||
'@lezer/common': 1.5.2
|
||||
|
||||
'@codemirror/commands@6.10.3':
|
||||
dependencies:
|
||||
'@codemirror/language': 6.12.3
|
||||
'@codemirror/state': 6.6.0
|
||||
'@codemirror/view': 6.41.0
|
||||
'@lezer/common': 1.5.2
|
||||
|
||||
'@codemirror/language@6.12.3':
|
||||
dependencies:
|
||||
'@codemirror/state': 6.6.0
|
||||
'@codemirror/view': 6.41.0
|
||||
'@lezer/common': 1.5.2
|
||||
'@lezer/highlight': 1.2.3
|
||||
'@lezer/lr': 1.4.8
|
||||
style-mod: 4.1.3
|
||||
|
||||
'@codemirror/lint@6.9.5':
|
||||
dependencies:
|
||||
'@codemirror/state': 6.6.0
|
||||
'@codemirror/view': 6.41.0
|
||||
crelt: 1.0.6
|
||||
|
||||
'@codemirror/search@6.6.0':
|
||||
dependencies:
|
||||
'@codemirror/state': 6.6.0
|
||||
'@codemirror/view': 6.41.0
|
||||
crelt: 1.0.6
|
||||
|
||||
'@codemirror/state@6.6.0':
|
||||
dependencies:
|
||||
'@marijn/find-cluster-break': 1.0.2
|
||||
|
||||
'@codemirror/view@6.41.0':
|
||||
dependencies:
|
||||
'@codemirror/state': 6.6.0
|
||||
crelt: 1.0.6
|
||||
style-mod: 4.1.3
|
||||
w3c-keyname: 2.2.8
|
||||
|
||||
'@csstools/color-helpers@6.0.2': {}
|
||||
|
||||
'@csstools/css-calc@3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)':
|
||||
|
|
@ -4573,6 +4689,18 @@ snapshots:
|
|||
|
||||
'@levischuck/tiny-cbor@0.2.11': {}
|
||||
|
||||
'@lezer/common@1.5.2': {}
|
||||
|
||||
'@lezer/highlight@1.2.3':
|
||||
dependencies:
|
||||
'@lezer/common': 1.5.2
|
||||
|
||||
'@lezer/lr@1.4.8':
|
||||
dependencies:
|
||||
'@lezer/common': 1.5.2
|
||||
|
||||
'@marijn/find-cluster-break@1.0.2': {}
|
||||
|
||||
'@mjackson/node-fetch-server@0.2.0': {}
|
||||
|
||||
'@napi-rs/wasm-runtime@1.1.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)':
|
||||
|
|
@ -5935,6 +6063,16 @@ snapshots:
|
|||
|
||||
cjs-module-lexer@2.2.0: {}
|
||||
|
||||
codemirror@6.0.2:
|
||||
dependencies:
|
||||
'@codemirror/autocomplete': 6.20.1
|
||||
'@codemirror/commands': 6.10.3
|
||||
'@codemirror/language': 6.12.3
|
||||
'@codemirror/lint': 6.9.5
|
||||
'@codemirror/search': 6.6.0
|
||||
'@codemirror/state': 6.6.0
|
||||
'@codemirror/view': 6.41.0
|
||||
|
||||
colorette@2.0.20: {}
|
||||
|
||||
compressible@2.0.18:
|
||||
|
|
@ -5969,6 +6107,8 @@ snapshots:
|
|||
|
||||
cookie@1.1.1: {}
|
||||
|
||||
crelt@1.0.6: {}
|
||||
|
||||
cross-spawn@7.0.6:
|
||||
dependencies:
|
||||
path-key: 3.1.1
|
||||
|
|
@ -7158,6 +7298,8 @@ snapshots:
|
|||
|
||||
strip-json-comments@5.0.3: {}
|
||||
|
||||
style-mod@4.1.3: {}
|
||||
|
||||
sweepline-intersections@1.5.0:
|
||||
dependencies:
|
||||
tinyqueue: 2.0.3
|
||||
|
|
@ -7368,6 +7510,8 @@ snapshots:
|
|||
|
||||
void-elements@3.1.0: {}
|
||||
|
||||
w3c-keyname@2.2.8: {}
|
||||
|
||||
w3c-xmlserializer@5.0.0:
|
||||
dependencies:
|
||||
xml-name-validator: 5.0.0
|
||||
|
|
@ -7416,6 +7560,13 @@ snapshots:
|
|||
|
||||
xtend@4.0.2: {}
|
||||
|
||||
y-codemirror.next@0.3.5(@codemirror/state@6.6.0)(@codemirror/view@6.41.0)(yjs@13.6.30):
|
||||
dependencies:
|
||||
'@codemirror/state': 6.6.0
|
||||
'@codemirror/view': 6.41.0
|
||||
lib0: 0.2.117
|
||||
yjs: 13.6.30
|
||||
|
||||
y-protocols@1.0.7(yjs@13.6.30):
|
||||
dependencies:
|
||||
lib0: 0.2.117
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue