Skip to content

Commit 835ce5d

Browse files
Fix slider implementation (#26)
* Fix slider implementation * Update examples/simple-yjs-widget/notebooks/simple.ipynb Co-authored-by: David Brochart <david.brochart@gmail.com> * Handle review comment --------- Co-authored-by: David Brochart <david.brochart@gmail.com>
1 parent 836004f commit 835ce5d

2 files changed

Lines changed: 28 additions & 93 deletions

File tree

examples/simple-yjs-widget/notebooks/simple.ipynb

Lines changed: 15 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -7,64 +7,23 @@
77
"metadata": {},
88
"outputs": [],
99
"source": [
10+
"from ypywidgets import Reactive\n",
1011
"from ypywidgets.comm import CommWidget\n",
11-
"from pycrdt import Map"
12-
]
13-
},
14-
{
15-
"cell_type": "code",
16-
"execution_count": null,
17-
"id": "6d9538c9-4858-4c9d-b347-18965660115d",
18-
"metadata": {},
19-
"outputs": [],
20-
"source": [
21-
"class MySlider(CommWidget):\n",
22-
" def __init__(self, value=50, min=0, max=100, step=1):\n",
23-
" super().__init__(\n",
24-
" comm_metadata={\n",
25-
" \"ymodel_name\": \"MySlider\",\n",
26-
" \"create_ydoc\": True,\n",
27-
" }\n",
28-
" )\n",
2912
"\n",
30-
" self.ydoc[\"state\"] = self._state = Map()\n",
3113
"\n",
32-
" self.min = min\n",
33-
" self.max = max\n",
34-
" self.step = step\n",
35-
" self.value = value\n",
36-
"\n",
37-
" @property\n",
38-
" def value(self):\n",
39-
" return self._state['value']\n",
40-
"\n",
41-
" @value.setter\n",
42-
" def value(self, v):\n",
43-
" self._state['value'] = v\n",
44-
"\n",
45-
" @property\n",
46-
" def min(self):\n",
47-
" return self._state['min']\n",
48-
"\n",
49-
" @min.setter\n",
50-
" def min(self, v):\n",
51-
" self._state['min'] = v\n",
52-
"\n",
53-
" @property\n",
54-
" def max(self):\n",
55-
" return self._state['max']\n",
56-
"\n",
57-
" @max.setter\n",
58-
" def max(self, v):\n",
59-
" self._state['max'] = v\n",
60-
"\n",
61-
" @property\n",
62-
" def step(self):\n",
63-
" return self._state['step']\n",
14+
"class MySlider(CommWidget):\n",
15+
" value = Reactive[int](50)\n",
16+
" min = Reactive[int](0)\n",
17+
" max = Reactive[int](100)\n",
18+
" step = Reactive[int](1)\n",
6419
"\n",
65-
" @step.setter\n",
66-
" def step(self, v):\n",
67-
" self._state['step'] = v"
20+
" @value.watch\n",
21+
" def _watch_value(self, old, new):\n",
22+
" # Watch the value of the slider, and print the new value change\n",
23+
" #\n",
24+
" # From JupyterLab, show the log console with info level to see the print\n",
25+
" # \"Ctrl + Shift + C\" then type \"Log Console\" to expand that panel\n",
26+
" print(f\"value changed: '{old}'->'{new}'\")"
6827
]
6928
},
7029
{
@@ -121,32 +80,11 @@
12180
{
12281
"cell_type": "code",
12382
"execution_count": null,
124-
"id": "55896ccc-a128-4abf-a34d-4a50272946dd",
125-
"metadata": {},
126-
"outputs": [],
127-
"source": [
128-
"w2 = MySlider(max=200, step=2, value=152)\n",
129-
"w2"
130-
]
131-
},
132-
{
133-
"cell_type": "code",
134-
"execution_count": null,
135-
"id": "c54528b0-6eae-4601-b6f6-ab2f31630815",
136-
"metadata": {},
137-
"outputs": [],
138-
"source": [
139-
"w2.value"
140-
]
141-
},
142-
{
143-
"cell_type": "code",
144-
"execution_count": null,
145-
"id": "23380f74-83ea-4409-a990-a0b8958dde2b",
83+
"id": "dc6f7a60-2426-4c04-8e4e-ceb0ab728c3a",
14684
"metadata": {},
14785
"outputs": [],
14886
"source": [
149-
"w2.value"
87+
"w.max = 200"
15088
]
15189
}
15290
],

examples/simple-yjs-widget/src/index.ts

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,46 @@
11
import {
22
IJupyterYModel,
33
JupyterYModel,
4-
IJupyterYWidgetManager
4+
IJupyterYWidgetManager,
5+
IJupyterYDoc
56
} from 'yjs-widgets';
67

7-
import * as Y from 'yjs';
8-
98
import {
109
JupyterFrontEnd,
1110
JupyterFrontEndPlugin
1211
} from '@jupyterlab/application';
12+
import { MapChange } from '@jupyter/ydoc';
1313

1414
class MySlider {
1515
constructor(yModel: IJupyterYModel, node: HTMLElement) {
1616
this.yModel = yModel;
1717
this.node = node;
1818

19-
this.state = this.yModel.sharedModel.ydoc.getMap('state');
20-
21-
this.state.observe(this._stateChanged.bind(this));
22-
2319
this.slider = document.createElement('input');
2420
this.slider.setAttribute('type', 'range');
2521

26-
this.slider.min = this.state.get('min');
27-
this.slider.max = this.state.get('max');
28-
this.slider.value = this.state.get('value');
29-
this.slider.step = this.state.get('step');
22+
this.yModel.sharedModel.attrsChanged.connect(this._stateChanged.bind(this));
23+
24+
this.slider.min = this.yModel.sharedModel.getAttr('min');
25+
this.slider.max = this.yModel.sharedModel.getAttr('max');
26+
this.slider.value = this.yModel.sharedModel.getAttr('value');
27+
this.slider.step = this.yModel.sharedModel.getAttr('step');
3028

3129
this.slider.onchange = this._sliderChanged.bind(this);
3230

3331
node.appendChild(this.slider);
3432
}
3533

36-
_stateChanged(change: Y.YMapEvent<any>): void {
37-
for (const key of change.keysChanged) {
38-
this.slider[key] = change.target.toJSON()[key];
34+
_stateChanged(_: IJupyterYDoc, change: MapChange): void {
35+
for (const key of change.keys()) {
36+
this.slider[key] = this.yModel.sharedModel.getAttr(key);
3937
}
4038
}
4139

4240
_sliderChanged(): void {
43-
this.state.set('value', parseInt(this.slider.value ?? '50'));
41+
this.yModel.sharedModel.setAttr('value', parseInt(this.slider.value ?? '50'));
4442
}
4543

46-
state: Y.Map<any>;
4744
yModel: IJupyterYModel;
4845
node: HTMLElement;
4946
slider: HTMLInputElement;

0 commit comments

Comments
 (0)