Conflict-free Replicated Data Type (CRDT) framework for real-time collaborative applications
Observable CRDT types for different collaborative editing scenarios with automatic conflict resolution. These types form the core of Yjs's collaborative functionality, enabling multiple users to edit the same data structures simultaneously without conflicts.
Shared array type that supports collaborative insertions, deletions, and modifications with automatic conflict resolution.
/**
* Shared array implementation that maintains order across concurrent modifications
*/
class YArray<T = any> {
constructor();
/** Number of items in the array */
readonly length: number;
/** Create YArray from existing JavaScript array */
static from<T>(items: Array<T>): YArray<T>;
}Array Modification Methods:
/**
* Insert items at the specified index
* @param index - Position to insert at
* @param content - Array of items to insert
*/
insert(index: number, content: Array<T>): void;
/**
* Append items to the end of the array
* @param content - Array of items to append
*/
push(content: Array<T>): void;
/**
* Prepend items to the beginning of the array
* @param content - Array of items to prepend
*/
unshift(content: Array<T>): void;
/**
* Delete items starting at index
* @param index - Starting position for deletion
* @param length - Number of items to delete (default: 1)
*/
delete(index: number, length?: number): void;Array Access Methods:
/**
* Get item at the specified index
* @param index - Index of item to retrieve
* @returns Item at index or undefined
*/
get(index: number): T;
/**
* Convert to JavaScript Array
* @returns JavaScript array with current contents
*/
toArray(): Array<T>;
/**
* Get slice of array as JavaScript Array
* @param start - Start index (default: 0)
* @param end - End index (default: length)
* @returns Slice as JavaScript array
*/
slice(start?: number, end?: number): Array<T>;
/**
* Convert to JSON representation
* @returns JSON array
*/
toJSON(): Array<any>;Array Iteration Methods:
/**
* Execute function for each item in the array
* @param f - Function to execute for each item
*/
forEach(f: (item: T, index: number, array: YArray<T>) => void): void;
/**
* Create new array with results of calling function on every item
* @param f - Function to call on each item
* @returns New JavaScript array with mapped values
*/
map<M>(f: (item: T, index: number, array: YArray<T>) => M): Array<M>;
/**
* Iterator support for for...of loops
*/
[Symbol.iterator](): IterableIterator<T>;Usage Examples:
import * as Y from "yjs";
const doc = new Y.Doc();
const yarray = doc.getArray<string>("fruits");
// Add items
yarray.push(["apple", "banana"]);
yarray.insert(1, ["orange"]);
yarray.unshift(["grape"]);
// Access items
console.log(yarray.get(0)); // "grape"
console.log(yarray.toArray()); // ["grape", "apple", "orange", "banana"]
// Iterate
yarray.forEach((fruit, index) => {
console.log(`${index}: ${fruit}`);
});
// Use with for...of
for (const fruit of yarray) {
console.log(fruit);
}
// Create from existing array
const existingFruits = ["cherry", "peach"];
const yarrFromExisting = Y.Array.from(existingFruits);Shared map/object type that supports collaborative key-value operations with automatic conflict resolution.
/**
* Shared map implementation for key-value storage
*/
class YMap<T = any> {
constructor(entries?: Iterable<readonly [string, any]>);
/** Number of key-value pairs in the map */
readonly size: number;
}Map Modification Methods:
/**
* Set a key-value pair in the map
* @param key - Key to set
* @param value - Value to associate with key
* @returns The value that was set
*/
set<VAL>(key: string, value: VAL): VAL;
/**
* Delete a key-value pair from the map
* @param key - Key to delete
*/
delete(key: string): void;
/**
* Remove all key-value pairs from the map
*/
clear(): void;Map Access Methods:
/**
* Get value associated with key
* @param key - Key to look up
* @returns Value or undefined if key doesn't exist
*/
get(key: string): T | undefined;
/**
* Check if key exists in the map
* @param key - Key to check for
* @returns True if key exists
*/
has(key: string): boolean;
/**
* Convert to JSON object
* @returns Plain JavaScript object
*/
toJSON(): { [key: string]: any };Map Iteration Methods:
/**
* Get iterator over all keys
* @returns Iterator of keys
*/
keys(): IterableIterator<string>;
/**
* Get iterator over all values
* @returns Iterator of values
*/
values(): IterableIterator<T>;
/**
* Get iterator over all key-value pairs
* @returns Iterator of [key, value] pairs
*/
entries(): IterableIterator<[string, T]>;
/**
* Execute function for each key-value pair
* @param f - Function to execute for each entry
*/
forEach(f: (value: T, key: string, map: YMap<T>) => void): void;
/**
* Iterator support for for...of loops over entries
*/
[Symbol.iterator](): IterableIterator<[string, T]>;Usage Examples:
import * as Y from "yjs";
const doc = new Y.Doc();
const ymap = doc.getMap<any>("settings");
// Set values
ymap.set("theme", "dark");
ymap.set("fontSize", 14);
ymap.set("autoSave", true);
// Get values
console.log(ymap.get("theme")); // "dark"
console.log(ymap.has("fontSize")); // true
// Iterate over entries
ymap.forEach((value, key) => {
console.log(`${key}: ${value}`);
});
// Use for...of with entries
for (const [key, value] of ymap) {
console.log(`${key} = ${value}`);
}
// Create from existing entries
const initialSettings = [
["language", "en"],
["region", "US"]
] as const;
const ymapFromEntries = new Y.Map(initialSettings);Rich text type with formatting support for collaborative text editing scenarios.
/**
* Shared text implementation with rich formatting support
*/
class YText {
constructor(string?: string);
/** Length of the text in characters */
readonly length: number;
}Text Modification Methods:
/**
* Insert text at the specified position
* @param index - Position to insert at
* @param text - Text to insert
* @param attributes - Optional formatting attributes
*/
insert(index: number, text: string, attributes?: TextAttributes): void;
/**
* Insert an embedded object at the specified position
* @param index - Position to insert at
* @param embed - Object or AbstractType to embed
* @param attributes - Optional formatting attributes
*/
insertEmbed(index: number, embed: Object | AbstractType<any>, attributes?: TextAttributes): void;
/**
* Delete text starting at index
* @param index - Starting position for deletion
* @param length - Number of characters to delete
*/
delete(index: number, length: number): void;
/**
* Apply formatting to a range of text
* @param index - Starting position
* @param length - Length of range to format
* @param attributes - Formatting attributes to apply
*/
format(index: number, length: number, attributes: TextAttributes): void;Text Attribute Methods:
/**
* Remove an attribute from the entire text type
* @param attributeName - Name of attribute to remove
*/
removeAttribute(attributeName: string): void;
/**
* Set an attribute on the entire text type
* @param attributeName - Name of attribute to set
* @param attributeValue - Value to set
*/
setAttribute(attributeName: string, attributeValue: any): void;
/**
* Get an attribute from the text type
* @param attributeName - Name of attribute to get
* @returns Attribute value or undefined
*/
getAttribute(attributeName: string): any;
/**
* Get all attributes from the text type
* @returns Object with all attributes
*/
getAttributes(): { [key: string]: any };Delta Integration Methods:
/**
* Apply a Quill Delta to the text
* @param delta - Delta operations to apply
* @param options - Options for applying delta
*/
applyDelta(delta: Array<any>, options?: { sanitize?: boolean }): void;
/**
* Convert text to Quill Delta format
* @param snapshot - Optional snapshot for historical state
* @param prevSnapshot - Optional previous snapshot for diff
* @param computeYChange - Optional function to compute Y-specific changes
* @returns Delta representation
*/
toDelta(snapshot?: Snapshot, prevSnapshot?: Snapshot, computeYChange?: Function): any;Text Access Methods:
/**
* Get plain text content without formatting
* @returns Plain text string
*/
toString(): string;
/**
* Convert to JSON (returns plain text)
* @returns Plain text string
*/
toJSON(): string;
/**
* Create a copy of the text
* @returns New YText instance with same content
*/
clone(): YText;Usage Examples:
import * as Y from "yjs";
const doc = new Y.Doc();
const ytext = doc.getText("document");
// Insert plain text
ytext.insert(0, "Hello World!");
// Insert with formatting
ytext.insert(5, " Beautiful", { bold: true, color: "blue" });
// Apply formatting to existing text
ytext.format(0, 5, { italic: true });
// Delete text
ytext.delete(5, 10); // Remove " Beautiful"
// Work with embeds
const imageEmbed = { type: "image", src: "photo.jpg" };
ytext.insertEmbed(ytext.length, imageEmbed);
// Convert to plain text
console.log(ytext.toString()); // "Hello World!"
// Work with Quill Delta
const delta = [
{ insert: "Hello " },
{ insert: "World", attributes: { bold: true } },
{ insert: "!\n" }
];
ytext.applyDelta(delta);
// Get as delta
const currentDelta = ytext.toDelta();
console.log(currentDelta);interface TextAttributes {
[key: string]: any;
bold?: boolean;
italic?: boolean;
underline?: boolean;
color?: string;
backgroundColor?: string;
fontSize?: number;
fontFamily?: string;
}
interface ArraySearchMarker {
readonly p: Item;
readonly index: number;
readonly timestamp: number;
}Install with Tessl CLI
npx tessl i tessl/npm-yjs