diff --git a/examples/simple-yjs-widget/notebooks/simple.ipynb b/examples/simple-yjs-widget/notebooks/simple.ipynb index a588359..2f66e2a 100644 --- a/examples/simple-yjs-widget/notebooks/simple.ipynb +++ b/examples/simple-yjs-widget/notebooks/simple.ipynb @@ -7,64 +7,23 @@ "metadata": {}, "outputs": [], "source": [ + "from ypywidgets import Reactive\n", "from ypywidgets.comm import CommWidget\n", - "from pycrdt import Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6d9538c9-4858-4c9d-b347-18965660115d", - "metadata": {}, - "outputs": [], - "source": [ - "class MySlider(CommWidget):\n", - " def __init__(self, value=50, min=0, max=100, step=1):\n", - " super().__init__(\n", - " comm_metadata={\n", - " \"ymodel_name\": \"MySlider\",\n", - " \"create_ydoc\": True,\n", - " }\n", - " )\n", "\n", - " self.ydoc[\"state\"] = self._state = Map()\n", "\n", - " self.min = min\n", - " self.max = max\n", - " self.step = step\n", - " self.value = value\n", - "\n", - " @property\n", - " def value(self):\n", - " return self._state['value']\n", - "\n", - " @value.setter\n", - " def value(self, v):\n", - " self._state['value'] = v\n", - "\n", - " @property\n", - " def min(self):\n", - " return self._state['min']\n", - "\n", - " @min.setter\n", - " def min(self, v):\n", - " self._state['min'] = v\n", - "\n", - " @property\n", - " def max(self):\n", - " return self._state['max']\n", - "\n", - " @max.setter\n", - " def max(self, v):\n", - " self._state['max'] = v\n", - "\n", - " @property\n", - " def step(self):\n", - " return self._state['step']\n", + "class MySlider(CommWidget):\n", + " value = Reactive[int](50)\n", + " min = Reactive[int](0)\n", + " max = Reactive[int](100)\n", + " step = Reactive[int](1)\n", "\n", - " @step.setter\n", - " def step(self, v):\n", - " self._state['step'] = v" + " @value.watch\n", + " def _watch_value(self, old, new):\n", + " # Watch the value of the slider, and print the new value change\n", + " #\n", + " # From JupyterLab, show the log console with info level to see the print\n", + " # \"Ctrl + Shift + C\" then type \"Log Console\" to expand that panel\n", + " print(f\"value changed: '{old}'->'{new}'\")" ] }, { @@ -121,32 +80,11 @@ { "cell_type": "code", "execution_count": null, - "id": "55896ccc-a128-4abf-a34d-4a50272946dd", - "metadata": {}, - "outputs": [], - "source": [ - "w2 = MySlider(max=200, step=2, value=152)\n", - "w2" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c54528b0-6eae-4601-b6f6-ab2f31630815", - "metadata": {}, - "outputs": [], - "source": [ - "w2.value" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "23380f74-83ea-4409-a990-a0b8958dde2b", + "id": "dc6f7a60-2426-4c04-8e4e-ceb0ab728c3a", "metadata": {}, "outputs": [], "source": [ - "w2.value" + "w.max = 200" ] } ], diff --git a/examples/simple-yjs-widget/src/index.ts b/examples/simple-yjs-widget/src/index.ts index e9df237..297e388 100644 --- a/examples/simple-yjs-widget/src/index.ts +++ b/examples/simple-yjs-widget/src/index.ts @@ -1,49 +1,46 @@ import { IJupyterYModel, JupyterYModel, - IJupyterYWidgetManager + IJupyterYWidgetManager, + IJupyterYDoc } from 'yjs-widgets'; -import * as Y from 'yjs'; - import { JupyterFrontEnd, JupyterFrontEndPlugin } from '@jupyterlab/application'; +import { MapChange } from '@jupyter/ydoc'; class MySlider { constructor(yModel: IJupyterYModel, node: HTMLElement) { this.yModel = yModel; this.node = node; - this.state = this.yModel.sharedModel.ydoc.getMap('state'); - - this.state.observe(this._stateChanged.bind(this)); - this.slider = document.createElement('input'); this.slider.setAttribute('type', 'range'); - this.slider.min = this.state.get('min'); - this.slider.max = this.state.get('max'); - this.slider.value = this.state.get('value'); - this.slider.step = this.state.get('step'); + this.yModel.sharedModel.attrsChanged.connect(this._stateChanged.bind(this)); + + this.slider.min = this.yModel.sharedModel.getAttr('min'); + this.slider.max = this.yModel.sharedModel.getAttr('max'); + this.slider.value = this.yModel.sharedModel.getAttr('value'); + this.slider.step = this.yModel.sharedModel.getAttr('step'); this.slider.onchange = this._sliderChanged.bind(this); node.appendChild(this.slider); } - _stateChanged(change: Y.YMapEvent): void { - for (const key of change.keysChanged) { - this.slider[key] = change.target.toJSON()[key]; + _stateChanged(_: IJupyterYDoc, change: MapChange): void { + for (const key of change.keys()) { + this.slider[key] = this.yModel.sharedModel.getAttr(key); } } _sliderChanged(): void { - this.state.set('value', parseInt(this.slider.value ?? '50')); + this.yModel.sharedModel.setAttr('value', parseInt(this.slider.value ?? '50')); } - state: Y.Map; yModel: IJupyterYModel; node: HTMLElement; slider: HTMLInputElement;