y-prosemirror
Advanced tools
Comparing version 0.3.3 to 0.3.4
@@ -7,4 +7,7 @@ /** | ||
export const yCursorPluginKey: PluginKey<any, any>; | ||
export function createDecorations(state: any, awareness: any): any; | ||
export function yCursorPlugin(awareness: any): any; | ||
export function defaultCursorBuilder(user: any): HTMLSpanElement; | ||
export function createDecorations(state: any, awareness: any, createCursor: any): any; | ||
export function yCursorPlugin(awareness: any, { cursorBuilder }?: { | ||
cursorBuilder?: (arg0: any) => HTMLElement; | ||
}): any; | ||
import { PluginKey } from "prosemirror-state"; |
{ | ||
"name": "y-prosemirror", | ||
"version": "0.3.3", | ||
"version": "0.3.4", | ||
"description": "Prosemirror bindings for Yjs", | ||
@@ -5,0 +5,0 @@ "main": "./dist/y-prosemirror.cjs", |
@@ -43,4 +43,86 @@ # y-prosemirror | ||
#### Remote Cursors | ||
The shared cursors depend on the Awareness instance that is exported by most providers. The Awareness protocol handles non-permanent data like the number of users, their user names, their cursor location, and their colors. You can change the name and color of the user like this: | ||
```js | ||
example.binding.awareness.setLocalStateField('user', { color: '#008833', name: 'My real name' }) | ||
``` | ||
In order to render cursor information you need to embed custom CSS for the user icon. This is a template that you can use for styling cursor information. | ||
```css | ||
/* this is a rough fix for the first cursor position when the first paragraph is empty */ | ||
.ProseMirror > .ProseMirror-yjs-cursor:first-child { | ||
margin-top: 16px; | ||
} | ||
.ProseMirror p:first-child, .ProseMirror h1:first-child, .ProseMirror h2:first-child, .ProseMirror h3:first-child, .ProseMirror h4:first-child, .ProseMirror h5:first-child, .ProseMirror h6:first-child { | ||
margin-top: 16px | ||
} | ||
/* This gives the remote user caret. The colors are automatically overwritten*/ | ||
.ProseMirror-yjs-cursor { | ||
position: relative; | ||
margin-left: -1px; | ||
margin-right: -1px; | ||
border-left: 1px solid black; | ||
border-right: 1px solid black; | ||
border-color: orange; | ||
word-break: normal; | ||
pointer-events: none; | ||
} | ||
/* This renders the username above the caret */ | ||
.ProseMirror-yjs-cursor > div { | ||
position: absolute; | ||
top: -1.05em; | ||
left: -1px; | ||
font-size: 13px; | ||
background-color: rgb(250, 129, 0); | ||
font-family: serif; | ||
font-style: normal; | ||
font-weight: normal; | ||
line-height: normal; | ||
user-select: none; | ||
color: white; | ||
padding-left: 2px; | ||
padding-right: 2px; | ||
white-space: nowrap; | ||
} | ||
``` | ||
You can also overwrite the default Widget dom by specifying a cursor builder in the yCursorPlugin | ||
```js | ||
/** | ||
* This function receives the remote users "user" awareness state. | ||
*/ | ||
export const myCursorBuilder = user => { | ||
const cursor = document.createElement('span') | ||
cursor.classList.add('ProseMirror-yjs-cursor') | ||
cursor.setAttribute('style', `border-color: ${user.color}`) | ||
const userDiv = document.createElement('div') | ||
userDiv.setAttribute('style', `background-color: ${user.color}`) | ||
userDiv.insertBefore(document.createTextNode(user.name), null) | ||
cursor.insertBefore(userDiv, null) | ||
return cursor | ||
} | ||
const prosemirrorView = new EditorView(document.querySelector('#editor'), { | ||
state: EditorState.create({ | ||
schema, | ||
plugins: [ | ||
ySyncPlugin(type), | ||
yCursorPlugin(provider.awareness, { cursorBuilder: myCursorBuilder }), | ||
yUndoPlugin(), | ||
keymap({ | ||
'Mod-z': undo, | ||
'Mod-y': redo, | ||
'Mod-Shift-z': redo | ||
}) | ||
].concat(exampleSetup({ schema })) | ||
}) | ||
}) | ||
``` | ||
### License | ||
[The MIT License](./LICENSE) © Kevin Jahns |
@@ -19,2 +19,19 @@ | ||
/** | ||
* Default generator for a cursor element | ||
* | ||
* @param {any} user user data | ||
* @return HTMLElement | ||
*/ | ||
export const defaultCursorBuilder = user => { | ||
const cursor = document.createElement('span') | ||
cursor.classList.add('ProseMirror-yjs-cursor') | ||
cursor.setAttribute('style', `border-color: ${user.color}`) | ||
const userDiv = document.createElement('div') | ||
userDiv.setAttribute('style', `background-color: ${user.color}`) | ||
userDiv.insertBefore(document.createTextNode(user.name), null) | ||
cursor.insertBefore(userDiv, null) | ||
return cursor | ||
} | ||
/** | ||
* @param {any} state | ||
@@ -24,3 +41,3 @@ * @param {Awareness} awareness | ||
*/ | ||
export const createDecorations = (state, awareness) => { | ||
export const createDecorations = (state, awareness, createCursor) => { | ||
const ystate = ySyncPluginKey.getState(state) | ||
@@ -51,12 +68,3 @@ const y = ystate.doc | ||
head = math.min(head, maxsize) | ||
decorations.push(Decoration.widget(head, () => { | ||
const cursor = document.createElement('span') | ||
cursor.classList.add('ProseMirror-yjs-cursor') | ||
cursor.setAttribute('style', `border-color: ${user.color}`) | ||
const userDiv = document.createElement('div') | ||
userDiv.setAttribute('style', `background-color: ${user.color}`) | ||
userDiv.insertBefore(document.createTextNode(user.name), null) | ||
cursor.insertBefore(userDiv, null) | ||
return cursor | ||
}, { key: clientId + '', side: 10 })) | ||
decorations.push(Decoration.widget(head, () => createCursor(user), { key: clientId + '', side: 10 })) | ||
const from = math.min(anchor, head) | ||
@@ -77,9 +85,11 @@ const to = math.max(anchor, head) | ||
* @param {Awareness} awareness | ||
* @param {object} [opts] | ||
* @param {function(any):HTMLElement} [opts.cursorBuilder] | ||
* @return {any} | ||
*/ | ||
export const yCursorPlugin = awareness => new Plugin({ | ||
export const yCursorPlugin = (awareness, { cursorBuilder = defaultCursorBuilder } = {}) => new Plugin({ | ||
key: yCursorPluginKey, | ||
state: { | ||
init (_, state) { | ||
return createDecorations(state, awareness) | ||
return createDecorations(state, awareness, cursorBuilder) | ||
}, | ||
@@ -90,3 +100,3 @@ apply (tr, prevState, oldState, newState) { | ||
if ((ystate && ystate.isChangeOrigin) || (yCursorState && yCursorState.awarenessUpdated)) { | ||
return createDecorations(newState, awareness) | ||
return createDecorations(newState, awareness, cursorBuilder) | ||
} | ||
@@ -93,0 +103,0 @@ return prevState.map(tr.mapping, tr.doc) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
3180168
29647
128