### Install JupyterLab Extension Source: https://github.com/quantstack/yjs-widgets/blob/main/examples/simple-yjs-widget/README.md Use this command to install the simple-yjs-widget extension via pip. Ensure Node.js and JupyterLab are installed first. ```bash pip install . ``` -------------------------------- ### Install yjs-widgets in development mode Source: https://github.com/quantstack/yjs-widgets/blob/main/CONTRIBUTING.md Use these commands to clone the repository, install the package, and link it to JupyterLab for development. ```bash # Clone the repo to your local environment # Change directory to the yjs-widgets directory # Install package in development mode pip install -e . # Link your development version of the extension with JupyterLab jupyter labextension develop . --overwrite # Rebuild extension Typescript source after making changes jlpm run build ``` -------------------------------- ### Install yjs-widgets via pip Source: https://github.com/quantstack/yjs-widgets/blob/main/README.md Use this command to install the package in your environment. ```bash pip install yjs-widgets ``` -------------------------------- ### JupyterYDoc: Synchronized Attribute Storage Source: https://context7.com/quantstack/yjs-widgets/llms.txt Demonstrates setting, getting, and listening for attribute changes in a synchronized document using JupyterYDoc. Ensure Yjs is imported. ```typescript import { JupyterYDoc } from 'yjs-widgets'; import * as Y from 'yjs'; const ydoc = new Y.Doc(); const sharedDoc = new JupyterYDoc( { create_ydoc: true, ymodel_name: 'TestWidget' }, ydoc ); // Set and get attributes (changes sync automatically) sharedDoc.setAttr('title', 'My Document'); sharedDoc.setAttr('count', 42); sharedDoc.setAttr('items', ['a', 'b', 'c']); console.log(sharedDoc.getAttr('title')); // 'My Document' console.log(sharedDoc.getAttr('count')); // 42 // Get all attributes const allAttrs = sharedDoc.attrs; console.log(allAttrs); // { title: 'My Document', count: 42, items: ['a', 'b', 'c'] } // Listen for attribute changes sharedDoc.attrsChanged.connect((doc, changes) => { for (const [key, change] of changes.entries()) { if (change.action === 'add') { console.log(`Added ${key}:`, change.newValue); } else if (change.action === 'update') { console.log(`Updated ${key}:`, change.oldValue, '->', change.newValue); } else if (change.action === 'delete') { console.log(`Deleted ${key}`); } } }); // Remove an attribute sharedDoc.removeAttr('count'); // Clean up sharedDoc.dispose(); ``` -------------------------------- ### Instantiate and Display Widget Source: https://github.com/quantstack/yjs-widgets/blob/main/examples/simple-yjs-widget/notebooks/simple.ipynb Create an instance of the custom widget and display it. ```python w = MyWidget() w ``` -------------------------------- ### Import Widget and reactive Source: https://github.com/quantstack/yjs-widgets/blob/main/examples/simple-yjs-widget/notebooks/simple.ipynb Import the necessary classes from the ypywidgets library. ```python from ypywidgets import Widget, reactive ``` -------------------------------- ### Watch for source changes Source: https://github.com/quantstack/yjs-widgets/blob/main/CONTRIBUTING.md Run these commands in separate terminals to enable automatic rebuilding of the extension during development. ```bash # Watch the source directory in one terminal, automatically rebuilding when needed jlpm run watch # Run JupyterLab in another terminal jupyter lab ``` -------------------------------- ### IJupyterYWidgetManager Interface Source: https://context7.com/quantstack/yjs-widgets/llms.txt Central manager for registering widgets and handling kernel connections. ```APIDOC ## IJupyterYWidgetManager Interface ### Description Central manager for registering widgets and handling kernel connections. ### Methods - **registerKernel(kernel: Kernel.IKernelConnection)**: Register a kernel connection for widget communication. - **registerWidget(name: string, yModelFactory: IJupyterYModelFactory, yWidgetFactory: IJupyterYWidgetFactory)**: Register a widget type with its model and view factories. - **getWidgetModel(kernelId: string, commId: string)**: Retrieve a widget model by kernel and comm IDs. - **getWidgetFactory(modelName: string)**: Get the widget factory for a given model name. ``` -------------------------------- ### Generate source maps for debugging Source: https://github.com/quantstack/yjs-widgets/blob/main/CONTRIBUTING.md Use this command to disable minimization and generate source maps for JupyterLab core extensions. ```bash jupyter lab build --minimize=False ``` -------------------------------- ### Configure Notebook Renderer Plugin Source: https://context7.com/quantstack/yjs-widgets/llms.txt Registers a MIME renderer for the 'application/vnd.jupyter.ywidget-view+json' type to enable Yjs widget display in notebook output cells. ```typescript import { notebookRenderer } from 'yjs-widgets'; // Plugin configuration const plugin: JupyterFrontEndPlugin = { id: 'jupyterywidget:notebookRenderer', autoStart: true, requires: [IRenderMimeRegistry, INotebookTracker, IJupyterYWidgetManager], activate: ( app: JupyterFrontEnd, rendermime: IRenderMimeRegistry, nbTracker: INotebookTracker, wmManager: IJupyterYWidgetManager ) => { // Registers renderer for 'application/vnd.jupyter.ywidget-view+json' MIME type // Automatically handles widget display in notebook cells } }; // The MIME type used for Yjs widgets const MIME_TYPE = 'application/vnd.jupyter.ywidget-view+json'; // Widget output format expected from Python: // { // "application/vnd.jupyter.ywidget-view+json": { // "model_id": "abc123..." // } // } ``` -------------------------------- ### Uninstall yjs-widgets Source: https://github.com/quantstack/yjs-widgets/blob/main/examples/simple-yjs-widget/CONTRIBUTING.md Removes the extension package from the Python environment. ```bash pip uninstall simple-yjs-widget ``` -------------------------------- ### Define a Reactive Widget Source: https://github.com/quantstack/yjs-widgets/blob/main/examples/simple-yjs-widget/notebooks/simple.ipynb Define a custom widget class inheriting from Widget and using reactive properties. ```python class MyWidget(Widget): foo = reactive("") bar = reactive("") ``` -------------------------------- ### Create Collaborative Counter Widget Source: https://context7.com/quantstack/yjs-widgets/llms.txt Implement a collaborative counter widget by defining a class that extends IJupyterYWidget. Initialize shared attributes, listen for changes, and create the UI with event handlers for increment, decrement, and reset actions. ```typescript import * as YjsWidgets from 'yjs-widgets'; import { JupyterFrontEnd, JupyterFrontEndPlugin } from '@jupyterlab/application'; // Step 1: Define your widget class implementing IJupyterYWidget class CounterWidget implements YjsWidgets.IJupyterYWidget { yModel: YjsWidgets.IJupyterYModel; node: HTMLElement; constructor(yModel: YjsWidgets.IJupyterYModel, node: HTMLElement) { this.yModel = yModel; this.node = node; // Initialize attributes if they don't exist if (this.yModel.sharedModel.getAttr('count') === undefined) { this.yModel.sharedModel.setAttr('count', 0); } // Listen for attribute changes from any connected client this.yModel.sharedModel.attrsChanged.connect(() => { this._render(); }); // Create the UI this._createUI(); this._render(); } private _createUI(): void { this.node.innerHTML = `

Collaborative Counter

0
`; // Attach event handlers this.node.querySelector('#increment-btn')?.addEventListener('click', () => { const count = this.yModel.sharedModel.getAttr('count') as number; this.yModel.sharedModel.setAttr('count', count + 1); }); this.node.querySelector('#decrement-btn')?.addEventListener('click', () => { const count = this.yModel.sharedModel.getAttr('count') as number; this.yModel.sharedModel.setAttr('count', count - 1); }); this.node.querySelector('#reset-btn')?.addEventListener('click', () => { this.yModel.sharedModel.setAttr('count', 0); }); } private _render(): void { const count = this.yModel.sharedModel.getAttr('count') as number; const display = this.node.querySelector('#count-display'); if (display) { display.textContent = String(count); } } dispose(): void { // Clean up event listeners and resources this.node.innerHTML = ''; } } ``` -------------------------------- ### IJupyterYModel Interface Source: https://context7.com/quantstack/yjs-widgets/llms.txt The primary interface for Yjs-backed widget models, managing the shared document and lifecycle signals. ```APIDOC ## IJupyterYModel Interface ### Description Represents a Yjs-backed model for widgets, providing access to the shared document and synchronization signals. ### Properties - **yModelName** (string) - The name identifier for this model type. - **isDisposed** (boolean) - Whether the model has been disposed. - **sharedModel** (IJupyterYDoc) - Access to the shared Yjs document wrapper. - **sharedAttrsChanged** (ISignal) - Signal emitted when shared attributes change. - **disposed** (ISignal) - Signal emitted when the model is disposed. - **ready** (Promise) - Promise that resolves when the model is ready. ``` -------------------------------- ### Implement a Custom Yjs Widget Model and View Source: https://context7.com/quantstack/yjs-widgets/llms.txt Extends JupyterYModel to manage shared Yjs types and implements IJupyterYWidget to render the state on a canvas. Requires registration via the IJupyterYWidgetManager plugin. ```typescript import * as YjsWidgets from 'yjs-widgets'; import * as Y from 'yjs'; import { JupyterFrontEnd, JupyterFrontEndPlugin } from '@jupyterlab/application'; // Custom model with additional Yjs shared types class DrawingModel extends YjsWidgets.JupyterYModel { private _strokes: Y.Array; constructor(commMetadata: { [key: string]: any }) { super(commMetadata); } protected async initialize(commMetadata: { [key: string]: any }) { await super.initialize(commMetadata); // Initialize custom shared types after ydoc is created this._strokes = this.ydoc.getArray('strokes'); } get strokes(): Y.Array { return this._strokes; } addStroke(stroke: { points: number[][]; color: string; width: number }): void { this._strokes.push([stroke]); } clearStrokes(): void { this._strokes.delete(0, this._strokes.length); } } // Widget using the custom model class DrawingWidget implements YjsWidgets.IJupyterYWidget { yModel: DrawingModel; node: HTMLElement; private _canvas: HTMLCanvasElement; private _ctx: CanvasRenderingContext2D; constructor(yModel: DrawingModel, node: HTMLElement) { this.yModel = yModel; this.node = node; // Create canvas this._canvas = document.createElement('canvas'); this._canvas.width = 400; this._canvas.height = 300; this._canvas.style.border = '1px solid #ccc'; this._ctx = this._canvas.getContext('2d')!; this.node.appendChild(this._canvas); // Observe changes to strokes array this.yModel.strokes.observe(() => { this._redraw(); }); // Initial render this._redraw(); } private _redraw(): void { this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); this.yModel.strokes.forEach((stroke: any) => { if (stroke.points.length < 2) return; this._ctx.beginPath(); this._ctx.strokeStyle = stroke.color; this._ctx.lineWidth = stroke.width; this._ctx.moveTo(stroke.points[0][0], stroke.points[0][1]); for (let i = 1; i < stroke.points.length; i++) { this._ctx.lineTo(stroke.points[i][0], stroke.points[i][1]); } this._ctx.stroke(); }); } dispose(): void { this.node.innerHTML = ''; } } // Plugin registration const drawingPlugin: JupyterFrontEndPlugin = { id: 'my-extension:drawing-widget', autoStart: true, requires: [YjsWidgets.IJupyterYWidgetManager], activate: ( app: JupyterFrontEnd, widgetManager: YjsWidgets.IJupyterYWidgetManager ): void => { widgetManager.registerWidget('DrawingWidget', DrawingModel, DrawingWidget); } }; export default [drawingPlugin]; ``` -------------------------------- ### Uninstall yjs-widgets Source: https://github.com/quantstack/yjs-widgets/blob/main/CONTRIBUTING.md Remove the package using pip. ```bash pip uninstall yjs-widgets ``` -------------------------------- ### IJupyterYWidget Interface Source: https://context7.com/quantstack/yjs-widgets/llms.txt Interface that custom widgets must implement to work with the yjs-widgets system. ```APIDOC ## IJupyterYWidget Interface ### Description Interface that custom widgets must implement to work with the yjs-widgets system. ### Properties - **node (HTMLElement)**: The HTML element where the widget renders. - **yModel (IJupyterYModel)**: Reference to the underlying Yjs model. ### Methods - **dispose() (Optional)**: Cleanup method. ``` -------------------------------- ### Implement and Use JupyterYModel Source: https://context7.com/quantstack/yjs-widgets/llms.txt Extend JupyterYModel to create custom models or use it directly to manage shared attributes and lifecycle. ```typescript import { JupyterYModel } from 'yjs-widgets'; // Creating a custom model by extending JupyterYModel class CustomYModel extends JupyterYModel { constructor(commMetadata: { [key: string]: any }) { super(commMetadata); } // Override to customize Yjs document creation ydocFactory(commMetadata: { [key: string]: any }): Y.Doc { const doc = new Y.Doc(); // Add custom shared types doc.getMap('customData'); return doc; } } // Usage example const model = new JupyterYModel({ ymodel_name: 'MyWidget', create_ydoc: true }); // Wait for model to be ready await model.ready; // Access model properties console.log(model.yModelName); // 'MyWidget' console.log(model.isDisposed); // false console.log(model.ydoc); // Y.Doc instance // Manage attributes model.addAttr('counter', 0); model.addAttr('label', 'Hello'); model.removeAttr('counter'); // Listen for changes model.sharedAttrsChanged.connect((sender, changes) => { changes.forEach((change, key) => { console.log(`Attribute ${key} changed:`, change); }); }); // Clean up model.dispose(); ``` -------------------------------- ### YCommProvider for Kernel Synchronization Source: https://context7.com/quantstack/yjs-widgets/llms.txt Handles bidirectional Yjs document synchronization over Jupyter kernel comm channels. It automatically manages sending and receiving document updates and awareness messages. ```typescript import { YCommProvider, YMessageType } from 'yjs-widgets'; import { Kernel } from '@jupyterlab/services'; import * as Y from 'yjs'; // Message types for Yjs protocol enum YMessageType { SYNC = 0, // Document synchronization messages AWARENESS = 1 // User awareness/presence messages } // Create a comm provider for a widget class YCommProvider implements IDisposable { constructor(options: { comm: Kernel.IComm; ydoc: Y.Doc }) { // Automatically: // - Listens for document updates and sends to kernel // - Receives updates from kernel and applies to local doc // - Handles initial sync handshake } // Access the Yjs document get doc(): Y.Doc; // Check if initial sync is complete get synced(): boolean; // Check if provider is disposed get isDisposed(): boolean; // Clean up and close comm dispose(): void; } // Internal usage (automatically created by WidgetModelRegistry) const comm = kernel.createComm('ywidget', commId); const ydoc = new Y.Doc(); const provider = new YCommProvider({ comm, ydoc }); // The provider automatically handles: // 1. Sending sync step 1 on connection // 2. Responding to sync step 2 from kernel // 3. Broadcasting local updates to kernel // 4. Applying remote updates from kernel ``` -------------------------------- ### Define IJupyterYModel Interface Source: https://context7.com/quantstack/yjs-widgets/llms.txt The primary interface for Yjs-backed widget models, providing access to shared documents and lifecycle signals. ```typescript import { IJupyterYModel } from 'yjs-widgets'; import { MapChange } from '@jupyter/ydoc'; import { ISignal } from '@lumino/signaling'; import * as Y from 'yjs'; interface IJupyterYModel extends IDisposable { // The name identifier for this model type yModelName: string; // Whether the model has been disposed isDisposed: boolean; // Access to the shared Yjs document wrapper sharedModel: IJupyterYDoc; // Signal emitted when shared attributes change sharedAttrsChanged: ISignal; // Signal emitted when the model is disposed disposed: ISignal; // Promise that resolves when model is ready ready: Promise; } ``` -------------------------------- ### IJupyterYDoc Interface Source: https://context7.com/quantstack/yjs-widgets/llms.txt Interface for the shared Yjs document wrapper that manages synchronized attributes across clients. ```APIDOC ## IJupyterYDoc Interface ### Description Interface for the shared Yjs document wrapper that manages synchronized attributes. ### Methods - **getAttr(key: string)** - Get a specific attribute value. - **setAttr(key: string, value: any)** - Set an attribute value (synchronized across clients). - **removeAttr(key: string)** - Remove an attribute. ### Properties - **attrs** (JSONObject | null) - Get all attributes as a JSON object. - **attrsChanged** (ISignal) - Signal emitted when attributes change. - **ydoc** (Y.Doc) - Access to the underlying Yjs document. - **commMetadata** (object) - Comm metadata from the kernel. ``` -------------------------------- ### Register Counter Widget Plugin Source: https://context7.com/quantstack/yjs-widgets/llms.txt Register the custom CounterWidget with the JupyterLab application's widget manager. This involves defining a JupyterFrontEndPlugin that specifies the widget's ID, activation logic, and dependencies. ```typescript // Step 2: Create and export the JupyterLab plugin const counterPlugin: JupyterFrontEndPlugin = { id: 'my-extension:counter-widget', autoStart: true, requires: [YjsWidgets.IJupyterYWidgetManager], activate: ( app: JupyterFrontEnd, widgetManager: YjsWidgets.IJupyterYWidgetManager ): void => { // Register the widget with the manager widgetManager.registerWidget( 'CounterWidget', // Widget name (must match Python side) YjsWidgets.JupyterYModel, // Model factory CounterWidget // Widget factory ); console.log('CounterWidget registered successfully'); } }; export default [counterPlugin]; ``` -------------------------------- ### Implement and register a custom widget Source: https://github.com/quantstack/yjs-widgets/blob/main/README.md Defines a widget class that reacts to Yjs model attribute changes and registers it with the JupyterYWidgetManager. ```typescript import { IJupyterYModel } from './types'; import { JupyterYModel } from './model'; import { IJupyterYWidgetManager } from './notebookrenderer/types'; import { JupyterFrontEnd, JupyterFrontEndPlugin } from '@jupyterlab/application'; class MyWidget { constructor(yModel: IJupyterYModel, node: HTMLElement) { this.yModel = yModel; this.node = node; yModel.sharedModel.attrsChanged.connect(() => { this._attrsChanged(); }); node.textContent = 'Hello world!'; } _attrsChanged(): void { const foo: string = this.yModel.sharedModel.getAttr('foo') as string; const bar: string = this.yModel.sharedModel.getAttr('bar') as string; this.node.textContent = `foo=${foo}, bar=${bar}`; } yModel: IJupyterYModel; node: HTMLElement; } export const foo: JupyterFrontEndPlugin = { id: 'foo:bar', autoStart: true, requires: [IJupyterYWidgetManager], activate: (app: JupyterFrontEnd, wm: IJupyterYWidgetManager): void => { wm.registerWidget('MyWidget', JupyterYModel, MyWidget); } }; ``` -------------------------------- ### IJupyterYWidgetManager Interface Definition Source: https://context7.com/quantstack/yjs-widgets/llms.txt Defines the interface for managing Jupyter widgets, including registering kernels and widgets, and retrieving widget models. ```typescript import { IJupyterYWidgetManager, IJupyterYModelFactory, IJupyterYWidgetFactory } from 'yjs-widgets'; import { Kernel } from '@jupyterlab/services'; interface IJupyterYWidgetManager { // Register a kernel connection for widget communication registerKernel(kernel: Kernel.IKernelConnection): void; // Register a widget type with its model and view factories registerWidget( name: string, yModelFactory: IJupyterYModelFactory, yWidgetFactory: IJupyterYWidgetFactory ): void; // Retrieve a widget model by kernel and comm IDs getWidgetModel(kernelId: string, commId: string): IJupyterYModel | undefined; // Get the widget factory for a given model name getWidgetFactory(modelName: string): IJupyterYWidgetFactory | undefined; } ``` -------------------------------- ### Update Reactive Property 'foo' Source: https://github.com/quantstack/yjs-widgets/blob/main/examples/simple-yjs-widget/notebooks/simple.ipynb Assign a new value to the reactive property 'foo'. ```python w.foo = 3 ``` -------------------------------- ### Define IJupyterYDoc Interface Source: https://context7.com/quantstack/yjs-widgets/llms.txt Interface for the shared Yjs document wrapper, used for synchronized attribute management. ```typescript import { IJupyterYDoc } from 'yjs-widgets'; import { JSONObject } from '@lumino/coreutils'; interface IJupyterYDoc extends IDisposable { // Get all attributes as a JSON object attrs: JSONObject | null; // Get a specific attribute value getAttr(key: string): any; // Set an attribute value (synchronized across clients) setAttr(key: string, value: any): void; // Remove an attribute removeAttr(key: string): void; // Signal emitted when attributes change attrsChanged: ISignal; // Access to the underlying Yjs document ydoc: Y.Doc; // Comm metadata from the kernel commMetadata: { [key: string]: any }; // Signal emitted when disposed disposed: ISignal; } ``` -------------------------------- ### Yjs Widget Manager Plugin Source: https://context7.com/quantstack/yjs-widgets/llms.txt Provides the IJupyterYWidgetManager service for dependency injection. Use this plugin to register and manage Yjs-based Jupyter widgets within your JupyterFrontEnd application. ```typescript import { yWidgetManager, IJupyterYWidgetManager } from 'yjs-widgets'; import { Token } from '@lumino/coreutils'; // Service token for dependency injection const IJupyterYWidgetManager = new Token( 'yjs-widgets:IJupyterYWidgetManager', 'A manager of Yjs-based Jupyter widgets.' ); // Plugin configuration const plugin: JupyterFrontEndPlugin = { id: 'yjs-widgets:yWidgetManagerPlugin', autoStart: true, requires: [], optional: [INotebookTracker, IConsoleTracker], provides: IJupyterYWidgetManager, activate: ( app: JupyterFrontEnd, notebookTracker?: INotebookTracker, consoleTracker?: IConsoleTracker ): IJupyterYWidgetManager => { // Creates and returns the widget manager // Automatically handles kernel registration for notebooks and consoles } }; // Usage: require IJupyterYWidgetManager in your plugin const myPlugin: JupyterFrontEndPlugin = { id: 'my-extension:plugin', requires: [IJupyterYWidgetManager], activate: (app: JupyterFrontEnd, manager: IJupyterYWidgetManager) => { // Use the manager to register widgets } }; ``` -------------------------------- ### JupyterYDoc Class Source: https://context7.com/quantstack/yjs-widgets/llms.txt The JupyterYDoc class provides synchronized attribute storage using Yjs Maps, allowing for automatic state synchronization. ```APIDOC ## JupyterYDoc Class ### Description Implementation that provides synchronized attribute storage using Yjs Maps. ### Methods - **setAttr(key: string, value: any)**: Sets an attribute value. - **getAttr(key: string)**: Retrieves an attribute value. - **removeAttr(key: string)**: Removes an attribute. - **dispose()**: Cleans up the document instance. ### Properties - **attrs**: Returns all current attributes. - **attrsChanged**: Signal emitted when attributes are modified. ``` -------------------------------- ### IJupyterYWidget Interface Definition Source: https://context7.com/quantstack/yjs-widgets/llms.txt Specifies the interface that custom widgets must implement to integrate with the yjs-widgets system, including node, yModel, and optional dispose methods. ```typescript import { IJupyterYWidget, IJupyterYModel } from 'yjs-widgets'; interface IJupyterYWidget { // The HTML element where the widget renders node: HTMLElement; // Reference to the underlying Yjs model yModel: IJupyterYModel; // Optional cleanup method dispose?(): void; } ``` -------------------------------- ### Update Reactive Property 'bar' Source: https://github.com/quantstack/yjs-widgets/blob/main/examples/simple-yjs-widget/notebooks/simple.ipynb Assign a new value to the reactive property 'bar'. ```python w.bar = 4 ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.