jupyterlab_advanced_image_viewer_extension 1.0.6 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,7 +18,7 @@ The viewer toolbar adds zoom in / out / fit controls and a `help` link that list
18
18
 
19
19
  - **Fit to screen** - every image opens scaled to fit the panel (same result as the stock viewer), and reset returns to that fit
20
20
  - **Wheel zoom** - scroll to zoom in and out, anchored at the cursor; zoom out as far as you like
21
- - **Drag to pan** - hold and drag to move around a zoomed-in image
21
+ - **Drag to pan** - hold and drag to move the image at any zoom (canvas-style); the grab cursor is always available and Fit recenters
22
22
  - **Toolbar controls** - zoom in, zoom out, and reset-to-fit buttons on the viewer toolbar
23
23
  - **Arrow-key navigation** - Left and Right open the previous and next image in the same folder, advancing within one viewer instead of opening new tabs
24
24
 
@@ -7,7 +7,6 @@ export declare class ViewerController {
7
7
  private panning;
8
8
  private start;
9
9
  private zoomStep;
10
- private ro;
11
10
  private disposed;
12
11
  constructor(host: HTMLElement, img: HTMLImageElement, zoomStep: number);
13
12
  setZoomStep(zoomStep: number): void;
@@ -18,12 +17,9 @@ export declare class ViewerController {
18
17
  private onWheel;
19
18
  zoomIn(): void;
20
19
  zoomOut(): void;
21
- private canPan;
22
- private clampPan;
23
20
  private onDown;
24
21
  private onMove;
25
22
  private onUp;
26
- private onResize;
27
23
  private updateCursor;
28
24
  private apply;
29
25
  dispose(): void;
package/lib/controller.js CHANGED
@@ -23,9 +23,6 @@ export class ViewerController {
23
23
  this.zoomAt(factor, e.clientX - r.left, e.clientY - r.top);
24
24
  };
25
25
  this.onDown = (e) => {
26
- if (!this.canPan()) {
27
- return;
28
- }
29
26
  e.preventDefault();
30
27
  this.panning = true;
31
28
  this.start = { x: e.clientX, y: e.clientY, tx: this.tx, ty: this.ty };
@@ -39,7 +36,6 @@ export class ViewerController {
39
36
  }
40
37
  this.tx = this.start.tx + (e.clientX - this.start.x);
41
38
  this.ty = this.start.ty + (e.clientY - this.start.y);
42
- this.clampPan();
43
39
  this.apply();
44
40
  };
45
41
  this.onUp = () => {
@@ -65,8 +61,6 @@ export class ViewerController {
65
61
  this.layer = layer;
66
62
  this.host.addEventListener('wheel', this.onWheel, { passive: false });
67
63
  this.host.addEventListener('mousedown', this.onDown);
68
- this.ro = new ResizeObserver(() => this.onResize());
69
- this.ro.observe(this.host);
70
64
  this.apply();
71
65
  }
72
66
  setZoomStep(zoomStep) {
@@ -99,7 +93,6 @@ export class ViewerController {
99
93
  this.tx = ax - cx - k * (ax - cx - this.tx);
100
94
  this.ty = ay - cy - k * (ay - cy - this.ty);
101
95
  this.s = sNew;
102
- this.clampPan();
103
96
  this.apply();
104
97
  }
105
98
  zoomIn() {
@@ -110,24 +103,10 @@ export class ViewerController {
110
103
  const { vw, vh } = this.viewport();
111
104
  this.zoomAt(1 / (1 + this.zoomStep), vw / 2, vh / 2);
112
105
  }
113
- canPan() {
114
- return this.s > 1;
115
- }
116
- // Bound the translate to the overflow implied by the zoom so the image
117
- // cannot be panned out of view. Range collapses to 0 as s approaches 1.
118
- clampPan() {
119
- const { vw, vh } = this.viewport();
120
- const mx = (Math.max(this.s, 1) - 1) * vw * 0.5;
121
- const my = (Math.max(this.s, 1) - 1) * vh * 0.5;
122
- this.tx = Math.min(mx, Math.max(-mx, this.tx));
123
- this.ty = Math.min(my, Math.max(-my, this.ty));
124
- }
125
- onResize() {
126
- this.clampPan();
127
- this.apply();
128
- }
106
+ // Pan is always available (canvas-style): show grab normally, grabbing
107
+ // while a drag is in progress (apply() re-runs on every pan move).
129
108
  updateCursor() {
130
- this.host.style.cursor = this.canPan() ? 'grab' : 'default';
109
+ this.host.style.cursor = this.panning ? 'grabbing' : 'grab';
131
110
  }
132
111
  apply() {
133
112
  this.layer.style.transformOrigin = 'center center';
@@ -139,7 +118,6 @@ export class ViewerController {
139
118
  return;
140
119
  }
141
120
  this.disposed = true;
142
- this.ro.disconnect();
143
121
  this.host.removeEventListener('wheel', this.onWheel);
144
122
  this.host.removeEventListener('mousedown', this.onDown);
145
123
  window.removeEventListener('mousemove', this.onMove);
package/lib/index.js CHANGED
@@ -52,7 +52,7 @@ const plugin = {
52
52
  '<p class="jp-AdvancedImageViewer-help-section">This extension</p>',
53
53
  '<ul>',
54
54
  '<li><b>Wheel up / down</b> - zoom in / out at the cursor</li>',
55
- '<li><b>Click and drag</b> - pan a zoomed-in image</li>',
55
+ '<li><b>Click and drag</b> - pan the image at any zoom</li>',
56
56
  '<li><b>Toolbar buttons</b> - zoom in, zoom out, reset to fit</li>',
57
57
  '<li><b>Left / Right arrows</b> - previous / next image in the folder</li>',
58
58
  '</ul>',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jupyterlab_advanced_image_viewer_extension",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "JupyterLab extension for advanced image viewing: fit-to-screen, cursor-anchored wheel zoom, drag-to-pan, and Left/Right arrow keys to move to the previous and next image in a folder",
5
5
  "keywords": [
6
6
  "jupyter",
package/src/controller.ts CHANGED
@@ -19,7 +19,6 @@ export class ViewerController {
19
19
  private panning = false;
20
20
  private start = { x: 0, y: 0, tx: 0, ty: 0 };
21
21
  private zoomStep: number;
22
- private ro: ResizeObserver;
23
22
  private disposed = false;
24
23
 
25
24
  constructor(host: HTMLElement, img: HTMLImageElement, zoomStep: number) {
@@ -40,8 +39,6 @@ export class ViewerController {
40
39
  this.layer = layer;
41
40
  this.host.addEventListener('wheel', this.onWheel, { passive: false });
42
41
  this.host.addEventListener('mousedown', this.onDown);
43
- this.ro = new ResizeObserver(() => this.onResize());
44
- this.ro.observe(this.host);
45
42
  this.apply();
46
43
  }
47
44
 
@@ -79,7 +76,6 @@ export class ViewerController {
79
76
  this.tx = ax - cx - k * (ax - cx - this.tx);
80
77
  this.ty = ay - cy - k * (ay - cy - this.ty);
81
78
  this.s = sNew;
82
- this.clampPan();
83
79
  this.apply();
84
80
  }
85
81
 
@@ -100,24 +96,7 @@ export class ViewerController {
100
96
  this.zoomAt(1 / (1 + this.zoomStep), vw / 2, vh / 2);
101
97
  }
102
98
 
103
- private canPan(): boolean {
104
- return this.s > 1;
105
- }
106
-
107
- // Bound the translate to the overflow implied by the zoom so the image
108
- // cannot be panned out of view. Range collapses to 0 as s approaches 1.
109
- private clampPan(): void {
110
- const { vw, vh } = this.viewport();
111
- const mx = (Math.max(this.s, 1) - 1) * vw * 0.5;
112
- const my = (Math.max(this.s, 1) - 1) * vh * 0.5;
113
- this.tx = Math.min(mx, Math.max(-mx, this.tx));
114
- this.ty = Math.min(my, Math.max(-my, this.ty));
115
- }
116
-
117
99
  private onDown = (e: MouseEvent): void => {
118
- if (!this.canPan()) {
119
- return;
120
- }
121
100
  e.preventDefault();
122
101
  this.panning = true;
123
102
  this.start = { x: e.clientX, y: e.clientY, tx: this.tx, ty: this.ty };
@@ -132,7 +111,6 @@ export class ViewerController {
132
111
  }
133
112
  this.tx = this.start.tx + (e.clientX - this.start.x);
134
113
  this.ty = this.start.ty + (e.clientY - this.start.y);
135
- this.clampPan();
136
114
  this.apply();
137
115
  };
138
116
 
@@ -143,13 +121,10 @@ export class ViewerController {
143
121
  window.removeEventListener('mouseup', this.onUp);
144
122
  };
145
123
 
146
- private onResize(): void {
147
- this.clampPan();
148
- this.apply();
149
- }
150
-
124
+ // Pan is always available (canvas-style): show grab normally, grabbing
125
+ // while a drag is in progress (apply() re-runs on every pan move).
151
126
  private updateCursor(): void {
152
- this.host.style.cursor = this.canPan() ? 'grab' : 'default';
127
+ this.host.style.cursor = this.panning ? 'grabbing' : 'grab';
153
128
  }
154
129
 
155
130
  private apply(): void {
@@ -163,7 +138,6 @@ export class ViewerController {
163
138
  return;
164
139
  }
165
140
  this.disposed = true;
166
- this.ro.disconnect();
167
141
  this.host.removeEventListener('wheel', this.onWheel);
168
142
  this.host.removeEventListener('mousedown', this.onDown);
169
143
  window.removeEventListener('mousemove', this.onMove);
package/src/index.ts CHANGED
@@ -89,7 +89,7 @@ const plugin: JupyterFrontEndPlugin<void> = {
89
89
  '<p class="jp-AdvancedImageViewer-help-section">This extension</p>',
90
90
  '<ul>',
91
91
  '<li><b>Wheel up / down</b> - zoom in / out at the cursor</li>',
92
- '<li><b>Click and drag</b> - pan a zoomed-in image</li>',
92
+ '<li><b>Click and drag</b> - pan the image at any zoom</li>',
93
93
  '<li><b>Toolbar buttons</b> - zoom in, zoom out, reset to fit</li>',
94
94
  '<li><b>Left / Right arrows</b> - previous / next image in the folder</li>',
95
95
  '</ul>',