@rcarls/rc-virtual-canvas 0.3.2 → 0.4.1
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/CHANGELOG.md +28 -0
- package/README.md +5 -5
- package/dist/custom-elements.json +78 -22
- package/dist/{rc-virtual-canvas-CUVahMP7.js → rc-virtual-canvas-BSpF0tcY.js} +20 -10
- package/dist/rc-virtual-canvas-BSpF0tcY.js.map +1 -0
- package/dist/rc-virtual-canvas-define.js +1 -1
- package/dist/rc-virtual-canvas.js +1 -1
- package/dist/types/rc-virtual-canvas.d.ts +38 -15
- package/package.json +2 -2
- package/dist/rc-virtual-canvas-CUVahMP7.js.map +0 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# @rcarls/rc-virtual-canvas
|
|
2
|
+
|
|
3
|
+
## 0.4.1
|
|
4
|
+
|
|
5
|
+
## 0.4.0
|
|
6
|
+
|
|
7
|
+
### Patch Changes
|
|
8
|
+
|
|
9
|
+
- 037b1b3: Add try/catch for ResizeObserver.observe() for WebKit TypeError
|
|
10
|
+
- d49cde9: Fix `contentWidth`/`contentHeight` so their HTML attributes are `content-width`/`content-height`,
|
|
11
|
+
matching every other multi-word attribute in the library. They previously had no kebab-case
|
|
12
|
+
mapping, so `<rc-virtual-canvas content-width="...">` was silently ignored.
|
|
13
|
+
|
|
14
|
+
## 0.3.2
|
|
15
|
+
|
|
16
|
+
## 0.3.1
|
|
17
|
+
|
|
18
|
+
## 0.3.0
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- Add read-only `canvasScaleX` and `canvasScaleY` getters.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- Update package metadata, README intro, and docs links.
|
|
27
|
+
|
|
28
|
+
## 0.2.0
|
package/README.md
CHANGED
|
@@ -27,15 +27,15 @@ import { RCVirtualCanvas } from '@rcarls/rc-virtual-canvas'; // named class e
|
|
|
27
27
|
|
|
28
28
|
## Basic usage
|
|
29
29
|
|
|
30
|
-
Place a `<canvas>` inside the component. Set `
|
|
30
|
+
Place a `<canvas>` inside the component. Set `content-width` and `content-height` to the
|
|
31
31
|
total size of your virtual content. On each `rc-virtual-canvas-render` event, use
|
|
32
32
|
`detail.viewRect` to determine which portion of that content is visible and draw accordingly.
|
|
33
33
|
|
|
34
34
|
```html
|
|
35
35
|
<rc-virtual-canvas
|
|
36
36
|
id="vc"
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
content-width="4000"
|
|
38
|
+
content-height="3000"
|
|
39
39
|
style="width: 800px; height: 600px;"
|
|
40
40
|
>
|
|
41
41
|
<canvas id="canvas" width="800" height="600"></canvas>
|
|
@@ -67,8 +67,8 @@ that triggers native scroll events.
|
|
|
67
67
|
|
|
68
68
|
| Property | Attribute | Type | Default | Description |
|
|
69
69
|
|---|---|---|---|---|
|
|
70
|
-
| `contentWidth` | `
|
|
71
|
-
| `contentHeight` | `
|
|
70
|
+
| `contentWidth` | `content-width` | `number` | `0` | Total pixel width of the virtual content |
|
|
71
|
+
| `contentHeight` | `content-height` | `number` | `0` | Total pixel height of the virtual content |
|
|
72
72
|
| `autoResizeCanvas` | `auto-resize-canvas` | `boolean` | `true` | Keeps the slotted canvas backing store aligned to the measured viewport |
|
|
73
73
|
| `renderMode` | `render-mode` | `'continuous' \| 'viewport-change' \| 'manual'` | `'continuous'` | Controls when render events are dispatched |
|
|
74
74
|
| `imageRendering` | `image-rendering` | `'auto' \| 'crisp-edges' \| 'pixelated'` | `'auto'` | Convenience value applied to the slotted canvas via `image-rendering` |
|
|
@@ -48,6 +48,48 @@
|
|
|
48
48
|
"kind": "class",
|
|
49
49
|
"description": "A scrollable virtual canvas component.",
|
|
50
50
|
"name": "RCVirtualCanvas",
|
|
51
|
+
"cssProperties": [
|
|
52
|
+
{
|
|
53
|
+
"description": "`scrollbar-width` of the internal scroll container.",
|
|
54
|
+
"name": "--rc-virtual-canvas-scrollbar-width",
|
|
55
|
+
"default": "thin"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"description": "WebKit scrollbar thickness.",
|
|
59
|
+
"name": "--rc-virtual-canvas-scrollbar-size",
|
|
60
|
+
"default": "auto"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"description": "WebKit scrollbar thumb color.",
|
|
64
|
+
"name": "--rc-virtual-canvas-scrollbar-thumb-background",
|
|
65
|
+
"default": "ButtonFace"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"description": "WebKit scrollbar button color.",
|
|
69
|
+
"name": "--rc-virtual-canvas-scrollbar-button-background",
|
|
70
|
+
"default": "ButtonFace"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"description": "WebKit scrollbar track color.",
|
|
74
|
+
"name": "--rc-virtual-canvas-scrollbar-track-background",
|
|
75
|
+
"default": "Canvas"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"description": "`image-rendering` applied to the slotted canvas; kept in sync with the `imageRendering` property.",
|
|
79
|
+
"name": "--rc-virtual-canvas-image-rendering",
|
|
80
|
+
"default": "auto"
|
|
81
|
+
}
|
|
82
|
+
],
|
|
83
|
+
"cssParts": [
|
|
84
|
+
{
|
|
85
|
+
"description": "Internal scroll container that owns the virtual content scroll range.",
|
|
86
|
+
"name": "scroller"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"description": "Viewport-positioned overlay container rendered inside the scroll container.",
|
|
90
|
+
"name": "overlay"
|
|
91
|
+
}
|
|
92
|
+
],
|
|
51
93
|
"slots": [
|
|
52
94
|
{
|
|
53
95
|
"description": "The HTMLCanvasElement",
|
|
@@ -65,7 +107,7 @@
|
|
|
65
107
|
"type": {
|
|
66
108
|
"text": "number"
|
|
67
109
|
},
|
|
68
|
-
"privacy": "
|
|
110
|
+
"privacy": "protected",
|
|
69
111
|
"default": "0"
|
|
70
112
|
},
|
|
71
113
|
{
|
|
@@ -74,32 +116,32 @@
|
|
|
74
116
|
"type": {
|
|
75
117
|
"text": "RCVirtualCanvasRenderReason | undefined"
|
|
76
118
|
},
|
|
77
|
-
"privacy": "
|
|
119
|
+
"privacy": "protected"
|
|
78
120
|
},
|
|
79
121
|
{
|
|
80
122
|
"kind": "field",
|
|
81
123
|
"name": "_handledPointerEvents",
|
|
82
|
-
"privacy": "
|
|
124
|
+
"privacy": "protected",
|
|
83
125
|
"readonly": true,
|
|
84
126
|
"default": "new WeakSet<Event>()"
|
|
85
127
|
},
|
|
86
128
|
{
|
|
87
129
|
"kind": "field",
|
|
88
130
|
"name": "_boundUpdate",
|
|
89
|
-
"privacy": "
|
|
131
|
+
"privacy": "protected",
|
|
90
132
|
"readonly": true
|
|
91
133
|
},
|
|
92
134
|
{
|
|
93
135
|
"kind": "field",
|
|
94
136
|
"name": "_boundPointerEvent",
|
|
95
|
-
"privacy": "
|
|
137
|
+
"privacy": "protected",
|
|
96
138
|
"readonly": true
|
|
97
139
|
},
|
|
98
140
|
{
|
|
99
141
|
"kind": "field",
|
|
100
142
|
"name": "contentWidth",
|
|
101
143
|
"description": "Pixel width of the virtual content",
|
|
102
|
-
"attribute": "
|
|
144
|
+
"attribute": "content-width"
|
|
103
145
|
},
|
|
104
146
|
{
|
|
105
147
|
"kind": "field",
|
|
@@ -107,14 +149,14 @@
|
|
|
107
149
|
"type": {
|
|
108
150
|
"text": "number"
|
|
109
151
|
},
|
|
110
|
-
"privacy": "
|
|
152
|
+
"privacy": "private",
|
|
111
153
|
"default": "0"
|
|
112
154
|
},
|
|
113
155
|
{
|
|
114
156
|
"kind": "field",
|
|
115
157
|
"name": "contentHeight",
|
|
116
158
|
"description": "Pixel height of the virtual content",
|
|
117
|
-
"attribute": "
|
|
159
|
+
"attribute": "content-height"
|
|
118
160
|
},
|
|
119
161
|
{
|
|
120
162
|
"kind": "field",
|
|
@@ -122,7 +164,7 @@
|
|
|
122
164
|
"type": {
|
|
123
165
|
"text": "number"
|
|
124
166
|
},
|
|
125
|
-
"privacy": "
|
|
167
|
+
"privacy": "private",
|
|
126
168
|
"default": "0"
|
|
127
169
|
},
|
|
128
170
|
{
|
|
@@ -230,6 +272,20 @@
|
|
|
230
272
|
],
|
|
231
273
|
"description": "Replaces canvas tracking and re-registers the resize observer when slot content changes"
|
|
232
274
|
},
|
|
275
|
+
{
|
|
276
|
+
"kind": "method",
|
|
277
|
+
"name": "_observeCanvasResize",
|
|
278
|
+
"privacy": "protected",
|
|
279
|
+
"parameters": [
|
|
280
|
+
{
|
|
281
|
+
"name": "$canvas",
|
|
282
|
+
"type": {
|
|
283
|
+
"text": "HTMLCanvasElement"
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
],
|
|
287
|
+
"description": "Observes canvas size with DPR-accurate boxes when the browser supports them"
|
|
288
|
+
},
|
|
233
289
|
{
|
|
234
290
|
"kind": "method",
|
|
235
291
|
"name": "getViewRect",
|
|
@@ -385,7 +441,7 @@
|
|
|
385
441
|
{
|
|
386
442
|
"kind": "method",
|
|
387
443
|
"name": "_isOverlayEvent",
|
|
388
|
-
"privacy": "
|
|
444
|
+
"privacy": "protected",
|
|
389
445
|
"return": {
|
|
390
446
|
"type": {
|
|
391
447
|
"text": "boolean"
|
|
@@ -418,7 +474,7 @@
|
|
|
418
474
|
{
|
|
419
475
|
"kind": "method",
|
|
420
476
|
"name": "_scheduleRender",
|
|
421
|
-
"privacy": "
|
|
477
|
+
"privacy": "protected",
|
|
422
478
|
"parameters": [
|
|
423
479
|
{
|
|
424
480
|
"name": "reason",
|
|
@@ -431,17 +487,17 @@
|
|
|
431
487
|
{
|
|
432
488
|
"kind": "method",
|
|
433
489
|
"name": "_syncCanvasBackingStore",
|
|
434
|
-
"privacy": "
|
|
490
|
+
"privacy": "protected"
|
|
435
491
|
},
|
|
436
492
|
{
|
|
437
493
|
"kind": "method",
|
|
438
494
|
"name": "_getCanvasClientRect",
|
|
439
|
-
"privacy": "
|
|
495
|
+
"privacy": "protected"
|
|
440
496
|
},
|
|
441
497
|
{
|
|
442
498
|
"kind": "method",
|
|
443
499
|
"name": "_getMeasuredCanvasWidth",
|
|
444
|
-
"privacy": "
|
|
500
|
+
"privacy": "protected",
|
|
445
501
|
"parameters": [
|
|
446
502
|
{
|
|
447
503
|
"name": "fallbackWidth",
|
|
@@ -454,7 +510,7 @@
|
|
|
454
510
|
{
|
|
455
511
|
"kind": "method",
|
|
456
512
|
"name": "_getMeasuredCanvasHeight",
|
|
457
|
-
"privacy": "
|
|
513
|
+
"privacy": "protected",
|
|
458
514
|
"parameters": [
|
|
459
515
|
{
|
|
460
516
|
"name": "fallbackHeight",
|
|
@@ -467,7 +523,7 @@
|
|
|
467
523
|
{
|
|
468
524
|
"kind": "method",
|
|
469
525
|
"name": "_getViewportScaleX",
|
|
470
|
-
"privacy": "
|
|
526
|
+
"privacy": "protected",
|
|
471
527
|
"parameters": [
|
|
472
528
|
{
|
|
473
529
|
"name": "canvasRect",
|
|
@@ -480,7 +536,7 @@
|
|
|
480
536
|
{
|
|
481
537
|
"kind": "method",
|
|
482
538
|
"name": "_getViewportScaleY",
|
|
483
|
-
"privacy": "
|
|
539
|
+
"privacy": "protected",
|
|
484
540
|
"parameters": [
|
|
485
541
|
{
|
|
486
542
|
"name": "canvasRect",
|
|
@@ -509,40 +565,40 @@
|
|
|
509
565
|
],
|
|
510
566
|
"attributes": [
|
|
511
567
|
{
|
|
512
|
-
"name": "contentWidth",
|
|
513
568
|
"description": "Pixel width of the virtual content",
|
|
569
|
+
"name": "content-width",
|
|
514
570
|
"fieldName": "contentWidth"
|
|
515
571
|
},
|
|
516
572
|
{
|
|
517
|
-
"name": "contentHeight",
|
|
518
573
|
"description": "Pixel height of the virtual content",
|
|
574
|
+
"name": "content-height",
|
|
519
575
|
"fieldName": "contentHeight"
|
|
520
576
|
},
|
|
521
577
|
{
|
|
578
|
+
"description": "When true, keep the slotted canvas backing store aligned to the viewport.",
|
|
522
579
|
"name": "auto-resize-canvas",
|
|
523
580
|
"type": {
|
|
524
581
|
"text": "boolean"
|
|
525
582
|
},
|
|
526
583
|
"default": "true",
|
|
527
|
-
"description": "When true, keep the slotted canvas backing store aligned to the viewport.",
|
|
528
584
|
"fieldName": "autoResizeCanvas"
|
|
529
585
|
},
|
|
530
586
|
{
|
|
587
|
+
"description": "Controls when render events are dispatched.",
|
|
531
588
|
"name": "render-mode",
|
|
532
589
|
"type": {
|
|
533
590
|
"text": "RCVirtualCanvasRenderMode"
|
|
534
591
|
},
|
|
535
592
|
"default": "'continuous'",
|
|
536
|
-
"description": "Controls when render events are dispatched.",
|
|
537
593
|
"fieldName": "renderMode"
|
|
538
594
|
},
|
|
539
595
|
{
|
|
596
|
+
"description": "Convenience image-rendering value applied to the slotted canvas.",
|
|
540
597
|
"name": "image-rendering",
|
|
541
598
|
"type": {
|
|
542
599
|
"text": "RCVirtualCanvasImageRendering"
|
|
543
600
|
},
|
|
544
601
|
"default": "'auto'",
|
|
545
|
-
"description": "Convenience image-rendering value applied to the slotted canvas.",
|
|
546
602
|
"fieldName": "imageRendering"
|
|
547
603
|
}
|
|
548
604
|
],
|
|
@@ -70,10 +70,10 @@ const w = _`
|
|
|
70
70
|
image-rendering: var(--rc-virtual-canvas-image-rendering, auto);
|
|
71
71
|
}
|
|
72
72
|
`;
|
|
73
|
-
var
|
|
74
|
-
for (var s = i > 1 ? void 0 : i ?
|
|
73
|
+
var R = Object.defineProperty, m = Object.getOwnPropertyDescriptor, o = (r, t, e, i) => {
|
|
74
|
+
for (var s = i > 1 ? void 0 : i ? m(t, e) : t, a = r.length - 1, l; a >= 0; a--)
|
|
75
75
|
(l = r[a]) && (s = (i ? l(t, e, s) : l(s)) || s);
|
|
76
|
-
return i && s &&
|
|
76
|
+
return i && s && R(t, e, s), s;
|
|
77
77
|
};
|
|
78
78
|
function c(r) {
|
|
79
79
|
return Object.freeze({
|
|
@@ -126,14 +126,24 @@ const v = class v extends p {
|
|
|
126
126
|
}
|
|
127
127
|
/** Replaces canvas tracking and re-registers the resize observer when slot content changes */
|
|
128
128
|
_onSlotChange(t) {
|
|
129
|
-
this._resizeObserver.disconnect(), this._$canvas = t.currentTarget.assignedElements().filter((e) => e instanceof HTMLCanvasElement)
|
|
129
|
+
this._resizeObserver.disconnect(), this._$canvas = t.currentTarget.assignedElements().filter((e) => e instanceof HTMLCanvasElement)[0] ?? null, this._$canvas != null && (this._viewRect = {
|
|
130
130
|
x: this._$root.scrollLeft ?? 0,
|
|
131
131
|
y: this._$root.scrollTop ?? 0,
|
|
132
132
|
width: this._getMeasuredCanvasWidth(this._$canvas.clientWidth),
|
|
133
133
|
height: this._getMeasuredCanvasHeight(this._$canvas.clientHeight)
|
|
134
|
-
}, this._syncCanvasBackingStore(), this.
|
|
135
|
-
|
|
136
|
-
|
|
134
|
+
}, this._syncCanvasBackingStore(), this._observeCanvasResize(this._$canvas), this._scheduleRender("viewport-change"));
|
|
135
|
+
}
|
|
136
|
+
/** Observes canvas size with DPR-accurate boxes when the browser supports them */
|
|
137
|
+
_observeCanvasResize(t) {
|
|
138
|
+
try {
|
|
139
|
+
this._resizeObserver.observe(t, {
|
|
140
|
+
box: "device-pixel-content-box"
|
|
141
|
+
});
|
|
142
|
+
} catch (e) {
|
|
143
|
+
if (!(e instanceof TypeError))
|
|
144
|
+
throw e;
|
|
145
|
+
this._resizeObserver.observe(t);
|
|
146
|
+
}
|
|
137
147
|
}
|
|
138
148
|
/**
|
|
139
149
|
* Returns a frozen snapshot of the current viewport rectangle.
|
|
@@ -373,10 +383,10 @@ const v = class v extends p {
|
|
|
373
383
|
v.styles = [w];
|
|
374
384
|
let n = v;
|
|
375
385
|
o([
|
|
376
|
-
h({ type: Number })
|
|
386
|
+
h({ type: Number, attribute: "content-width" })
|
|
377
387
|
], n.prototype, "contentWidth", 1);
|
|
378
388
|
o([
|
|
379
|
-
h({ type: Number })
|
|
389
|
+
h({ type: Number, attribute: "content-height" })
|
|
380
390
|
], n.prototype, "contentHeight", 1);
|
|
381
391
|
o([
|
|
382
392
|
h({ attribute: "auto-resize-canvas", type: Boolean })
|
|
@@ -405,4 +415,4 @@ o([
|
|
|
405
415
|
export {
|
|
406
416
|
n as R
|
|
407
417
|
};
|
|
408
|
-
//# sourceMappingURL=rc-virtual-canvas-
|
|
418
|
+
//# sourceMappingURL=rc-virtual-canvas-BSpF0tcY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rc-virtual-canvas-BSpF0tcY.js","sources":["../src/rc-virtual-canvas.styles.ts","../src/rc-virtual-canvas.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const virtualCanvasStyles = css`\n *,\n *::before,\n *::after {\n box-sizing: border-box;\n }\n\n :host {\n position: relative;\n display: block;\n width: max-content;\n line-height: 0; /* remove extra space under slotted <canvas> element(s) */\n }\n\n :host([hidden]) {\n display: none;\n }\n\n #root {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n overflow: auto;\n scrollbar-width: var(--rc-virtual-canvas-scrollbar-width, thin);\n }\n\n #root::-webkit-scrollbar {\n width: var(--rc-virtual-canvas-scrollbar-size, auto);\n height: var(--rc-virtual-canvas-scrollbar-size, auto);\n }\n\n #root::-webkit-scrollbar-thumb {\n background: var(--rc-virtual-canvas-scrollbar-thumb-background, ButtonFace);\n }\n\n #root::-webkit-scrollbar-button {\n background: var(--rc-virtual-canvas-scrollbar-button-background, ButtonFace);\n }\n\n #root::-webkit-scrollbar-track {\n background: var(--rc-virtual-canvas-scrollbar-track-background, Canvas);\n }\n\n #placeholder {\n pointer-events: none;\n }\n\n #overlay {\n position: sticky;\n left: 0;\n top: 0;\n z-index: 1;\n display: block;\n width: 100%;\n height: 0;\n pointer-events: none;\n }\n\n ::slotted([slot='overlay']) {\n pointer-events: auto;\n }\n\n ::slotted(canvas) {\n image-rendering: var(--rc-virtual-canvas-image-rendering, auto);\n }\n`;\n\nexport default virtualCanvasStyles;\n","import { LitElement, html } from 'lit';\nimport { property, query, state } from 'lit/decorators.js';\nimport { styleMap } from 'lit/directives/style-map.js';\n\nimport virtualCanvasStyles from './rc-virtual-canvas.styles';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'rc-virtual-canvas': RCVirtualCanvas;\n }\n\n interface HTMLElementEventMap {\n 'rc-virtual-canvas-render': CustomEvent<RCVirtualCanvasRenderInit>;\n 'rc-virtual-canvas-pointer': CustomEvent<RCVirtualCanvasPointerInit>;\n }\n}\n\n/**\n * Scrollable virtual canvas for rendering large coordinate-space content.\n *\n * `x` and `y` are scroll offsets in CSS pixels; `width` and `height` are the canvas\n * backing-store dimensions in device pixels (DPR-accurate when `autoResizeCanvas` is `true`).\n */\nexport type RCVirtualCanvasViewRect = Readonly<{\n /** Scroll offset x in content space (CSS px) */\n x: number;\n\n /** Scroll offset y in content space (CSS px) */\n y: number;\n\n /** Visible width in device pixels */\n width: number;\n\n /** Visible height in device pixels */\n height: number;\n}>;\n\n/** Controls when `rc-virtual-canvas-render` events are dispatched */\nexport type RCVirtualCanvasRenderMode = 'continuous' | 'viewport-change' | 'manual';\n\n/** Identifies what triggered a render event */\nexport type RCVirtualCanvasRenderReason = 'animation-frame' | 'viewport-change' | 'manual';\n\n/** Content-space coordinate pair returned by coordinate-conversion methods */\nexport type RCVirtualCanvasPoint = Readonly<{\n /** Content space x coordinate in CSS pixels */\n x: number;\n\n /** Content space y coordinate in CSS pixels */\n y: number;\n}>;\n\n/**\n * Detail shape for `rc-virtual-canvas-pointer` events.\n *\n * Carries the source event's coordinates in both browser-client and content space,\n * along with all modifier key state.\n */\nexport type RCVirtualCanvasPointerInit = {\n /** DOM event type (e.g. `'pointerdown'`, `'click'`) */\n type: string;\n\n /** Browser client x coordinate from the source event */\n clientX: number;\n\n /** Browser client y coordinate from the source event */\n clientY: number;\n\n /** Content x coordinate mapped through the current backing-store scale */\n contentX: number;\n\n /** Content y coordinate mapped through the current backing-store scale */\n contentY: number;\n\n /** Frozen viewport snapshot at the moment the pointer event fired */\n viewRect: RCVirtualCanvasViewRect;\n\n /** Mouse button index from the source event */\n button: number;\n\n /** Active button bitmask from the source event */\n buttons: number;\n\n /** Whether the Alt key was held */\n altKey: boolean;\n\n /** Whether the Ctrl key was held */\n ctrlKey: boolean;\n\n /** Whether the Shift key was held */\n shiftKey: boolean;\n\n /** Whether the Meta key was held */\n metaKey: boolean;\n\n /** The original DOM event that produced this detail */\n sourceEvent: PointerEvent | MouseEvent;\n};\n\n/** CSS `image-rendering` value applied to the slotted canvas */\nexport type RCVirtualCanvasImageRendering = 'auto' | 'crisp-edges' | 'pixelated';\n\n/** Detail shape for `rc-virtual-canvas-render` events */\nexport type RCVirtualCanvasRenderInit = {\n /** High-resolution timestamp from `requestAnimationFrame` */\n time: DOMHighResTimeStamp;\n\n /** What triggered this render */\n reason: RCVirtualCanvasRenderReason;\n\n /** Frozen snapshot of the viewport for this frame */\n viewRect: RCVirtualCanvasViewRect;\n\n /** Frozen snapshot of the full content bounds for this frame */\n contentRect: RCVirtualCanvasViewRect;\n};\n\nfunction createRectSnapshot(rect: RCVirtualCanvasViewRect) {\n return Object.freeze({\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n });\n}\n\n/**\n * A scrollable virtual canvas component.\n *\n * @see {@link https://richardcarls.github.io/rc-webcomponents/components/rc-virtual-canvas rc-virtual-canvas docs}\n *\n * @slot - The HTMLCanvasElement\n * @slot overlay - Optional viewport-positioned content rendered inside the\n * scroll container above the canvas.\n *\n * @fires rc-virtual-canvas-render - Fires with viewport data when the canvas should redraw.\n * @fires rc-virtual-canvas-pointer - Fires pointer/mouse input mapped to virtual content coordinates.\n *\n * @csspart scroller - Internal scroll container that owns the virtual content scroll range.\n * @csspart overlay - Viewport-positioned overlay container rendered inside the scroll container.\n *\n * @attr content-width - Total pixel width of the virtual content.\n * @attr content-height - Total pixel height of the virtual content.\n * @attr auto-resize-canvas - Keep the slotted canvas backing store aligned to the viewport.\n * @attr render-mode - Controls when render events are dispatched.\n * @attr image-rendering - Convenience `image-rendering` value applied to the slotted canvas.\n *\n * @cssprop [--rc-virtual-canvas-scrollbar-width=thin] - `scrollbar-width` of the internal\n * scroll container.\n * @cssprop [--rc-virtual-canvas-scrollbar-size=auto] - WebKit scrollbar thickness.\n * @cssprop [--rc-virtual-canvas-scrollbar-thumb-background=ButtonFace] - WebKit scrollbar\n * thumb color.\n * @cssprop [--rc-virtual-canvas-scrollbar-button-background=ButtonFace] - WebKit scrollbar\n * button color.\n * @cssprop [--rc-virtual-canvas-scrollbar-track-background=Canvas] - WebKit scrollbar\n * track color.\n * @cssprop [--rc-virtual-canvas-image-rendering=auto] - `image-rendering` applied to the\n * slotted canvas; kept in sync with the `imageRendering` property.\n */\nexport class RCVirtualCanvas extends LitElement {\n static styles = [virtualCanvasStyles];\n\n protected _rafHandle: number = 0;\n protected _pendingRenderReason?: RCVirtualCanvasRenderReason;\n protected readonly _handledPointerEvents = new WeakSet<Event>();\n\n // Stored bound reference so the same closure is used for scheduling and\n // cancellation — `bind()` returns a new function every call.\n protected readonly _boundUpdate = (time: DOMHighResTimeStamp) => this._update(time);\n\n protected readonly _boundPointerEvent = (event: PointerEvent | MouseEvent) =>\n this._onPointerEvent(event);\n\n /** Pixel width of the virtual content */\n @property({ type: Number, attribute: 'content-width' })\n set contentWidth(val: number) {\n const oldValue = this._contentWidth;\n\n this._contentWidth = val;\n\n this._contentRect.width = this._contentWidth;\n this.requestUpdate('contentWidth', oldValue);\n this._scheduleRender('viewport-change');\n }\n get contentWidth() {\n return this._contentWidth;\n }\n private _contentWidth: number = 0;\n\n /** Pixel height of the virtual content */\n @property({ type: Number, attribute: 'content-height' })\n set contentHeight(val: number) {\n const oldValue = this._contentHeight;\n\n this._contentHeight = val;\n\n this._contentRect.height = this._contentHeight;\n this.requestUpdate('contentHeight', oldValue);\n this._scheduleRender('viewport-change');\n }\n get contentHeight() {\n return this._contentHeight;\n }\n private _contentHeight: number = 0;\n\n /** When true, keep the slotted canvas backing store aligned to the viewport. */\n @property({ attribute: 'auto-resize-canvas', type: Boolean })\n autoResizeCanvas: boolean = true;\n\n /** Controls when render events are dispatched. */\n @property({ attribute: 'render-mode' })\n renderMode: RCVirtualCanvasRenderMode = 'continuous';\n\n /** Convenience image-rendering value applied to the slotted canvas. */\n @property({ attribute: 'image-rendering' })\n imageRendering: RCVirtualCanvasImageRendering = 'auto';\n\n /** Shadow DOM scroll container that owns pointer interaction and native scrolling */\n @query('#root', true)\n protected _$root!: HTMLDivElement;\n\n /** Absolutely-positioned div that establishes the virtual scroll range */\n @query('#placeholder', true)\n protected _$placeholder!: HTMLDivElement;\n\n /** Currently-tracked slotted canvas element; `null` when no canvas is slotted */\n @state()\n protected _$canvas: HTMLCanvasElement | null = null;\n\n /** Mutable current-frame viewport geometry; call `getViewRect()` for a frozen snapshot */\n @state()\n protected _viewRect = {\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n };\n\n /** Mutable content bounds; updated when `contentWidth` or `contentHeight` change */\n @state()\n protected _contentRect = {\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n };\n\n /** Watches the slotted canvas for DPR-accurate dimension changes */\n protected _resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]) => {\n for (const entry of entries) {\n const devicePixelBoxSize = Array.isArray(entry.devicePixelContentBoxSize)\n ? entry.devicePixelContentBoxSize[0]\n : entry.devicePixelContentBoxSize;\n\n this._viewRect.width = this._getMeasuredCanvasWidth(\n devicePixelBoxSize?.inlineSize ??\n Math.round(entry.contentRect.width * window.devicePixelRatio),\n );\n\n this._viewRect.height = this._getMeasuredCanvasHeight(\n devicePixelBoxSize?.blockSize ??\n Math.round(entry.contentRect.height * window.devicePixelRatio),\n );\n\n this._syncCanvasBackingStore();\n this._scheduleRender('viewport-change');\n }\n });\n\n /** Reads scroll position from the root container and schedules a render */\n protected _onScroll() {\n this._viewRect.x = this._$root.scrollLeft;\n this._viewRect.y = this._$root.scrollTop;\n\n this._scheduleRender('viewport-change');\n }\n\n /** Replaces canvas tracking and re-registers the resize observer when slot content changes */\n protected _onSlotChange(e: Event) {\n this._resizeObserver.disconnect();\n\n this._$canvas =\n (e.currentTarget as HTMLSlotElement)\n .assignedElements()\n .filter((el) => el instanceof HTMLCanvasElement)\n [0] ?? null;\n\n if (this._$canvas != null) {\n this._viewRect = {\n x: this._$root.scrollLeft ?? 0,\n y: this._$root.scrollTop ?? 0,\n width: this._getMeasuredCanvasWidth(this._$canvas.clientWidth),\n height: this._getMeasuredCanvasHeight(this._$canvas.clientHeight),\n };\n\n this._syncCanvasBackingStore();\n this._observeCanvasResize(this._$canvas);\n\n this._scheduleRender('viewport-change');\n }\n }\n\n /** Observes canvas size with DPR-accurate boxes when the browser supports them */\n protected _observeCanvasResize($canvas: HTMLCanvasElement) {\n try {\n this._resizeObserver.observe($canvas, {\n box: 'device-pixel-content-box',\n });\n } catch (error) {\n if (!(error instanceof TypeError)) {\n throw error;\n }\n\n this._resizeObserver.observe($canvas);\n }\n }\n\n /**\n * Returns a frozen snapshot of the current viewport rectangle.\n *\n * Safe to keep between frames — the returned object will not be mutated\n * by future scroll or resize work.\n */\n getViewRect() {\n return createRectSnapshot(this._viewRect);\n }\n\n /**\n * Scrolls so the content coordinate is at the viewport origin.\n *\n * @param x - Content x coordinate in CSS pixels\n * @param y - Content y coordinate in CSS pixels\n * @param options - Native scroll options passed to scrollTo\n */\n scrollToContent(x: number, y: number, options: ScrollOptions = {}) {\n this._$root.scrollTo({\n ...options,\n left: x,\n top: y,\n });\n\n this._viewRect.x = this._$root.scrollLeft;\n this._viewRect.y = this._$root.scrollTop;\n this._scheduleRender('viewport-change');\n }\n\n /**\n * Scrolls so the content coordinate is centered in the viewport.\n *\n * @param x - Content x coordinate in CSS pixels\n * @param y - Content y coordinate in CSS pixels\n * @param options - Native scroll options passed to scrollTo\n */\n centerOnContent(x: number, y: number, options: ScrollOptions = {}) {\n this.scrollToContent(\n x - this._$root.clientWidth * 0.5,\n y - this._$root.clientHeight * 0.5,\n options,\n );\n }\n\n /**\n * Converts browser client coordinates to content coordinates using the current\n * backing-store scale.\n *\n * @param clientX - Browser client x coordinate (e.g. from a pointer event)\n * @param clientY - Browser client y coordinate\n *\n * @example\n * vc.addEventListener('pointerdown', (e) => {\n * const { x, y } = vc.clientToContent(e.clientX, e.clientY);\n * placeMarkerAt(x, y);\n * });\n */\n clientToContent(clientX: number, clientY: number) {\n const canvasRect = this._getCanvasClientRect();\n const scaleX = this._getViewportScaleX(canvasRect);\n const scaleY = this._getViewportScaleY(canvasRect);\n\n return Object.freeze({\n x: this._viewRect.x + (clientX - canvasRect.left) * scaleX,\n y: this._viewRect.y + (clientY - canvasRect.top) * scaleY,\n });\n }\n\n /**\n * Converts content coordinates back to browser client coordinates.\n *\n * @param x - Content x coordinate in CSS pixels\n * @param y - Content y coordinate in CSS pixels\n *\n * @example\n * const { x, y } = vc.contentToClient(contentX, contentY);\n * tooltip.style.left = `${x}px`;\n * tooltip.style.top = `${y}px`;\n */\n contentToClient(x: number, y: number) {\n const canvasRect = this._getCanvasClientRect();\n const scaleX = this._getViewportScaleX(canvasRect);\n const scaleY = this._getViewportScaleY(canvasRect);\n\n return Object.freeze({\n x: canvasRect.left + (x - this._viewRect.x) / scaleX,\n y: canvasRect.top + (y - this._viewRect.y) / scaleY,\n });\n }\n\n /**\n * Queues a render event on the next animation frame.\n *\n * Required when `renderMode` is `'manual'`. In other modes the component\n * schedules renders automatically; calling this with reason `'animation-frame'`\n * is a no-op when `renderMode` is `'viewport-change'`.\n *\n * @param reason - Render reason reported in the event detail\n */\n requestRender(reason: RCVirtualCanvasRenderReason = 'manual') {\n this._scheduleRender(reason);\n }\n\n /**\n * Ratio of canvas backing-store pixels to CSS pixels along the x-axis.\n *\n * Equals `devicePixelRatio` when `autoResizeCanvas` is `true`. Use as the x-scale\n * factor in `ctx.scale()` to draw at CSS pixel resolution.\n *\n * @example\n * vc.addEventListener('rc-virtual-canvas-render', ({ detail: { viewRect } }) => {\n * ctx.save();\n * ctx.scale(vc.canvasScaleX, vc.canvasScaleY);\n * drawScene(ctx, viewRect);\n * ctx.restore();\n * });\n */\n get canvasScaleX(): number {\n const canvasRect = this._getCanvasClientRect();\n\n return this._getViewportScaleX(canvasRect);\n }\n\n /**\n * Ratio of canvas backing-store pixels to CSS pixels along the y-axis.\n *\n * Equals `devicePixelRatio` when `autoResizeCanvas` is `true`. Use as the y-scale\n * factor in `ctx.scale()` to draw at CSS pixel resolution.\n */\n get canvasScaleY(): number {\n const canvasRect = this._getCanvasClientRect();\n\n return this._getViewportScaleY(canvasRect);\n }\n\n /** Maps pointer and mouse events to content coordinates and dispatches `rc-virtual-canvas-pointer` */\n protected _onPointerEvent(event: PointerEvent | MouseEvent) {\n if (this._handledPointerEvents.has(event)) {\n return;\n }\n\n if (this._isOverlayEvent(event)) {\n return;\n }\n\n this._handledPointerEvents.add(event);\n\n const contentPoint = this.clientToContent(event.clientX, event.clientY);\n\n const shouldContinue = this.dispatchEvent(\n new CustomEvent<RCVirtualCanvasPointerInit>('rc-virtual-canvas-pointer', {\n bubbles: true,\n composed: true,\n cancelable: true,\n detail: {\n type: event.type,\n clientX: event.clientX,\n clientY: event.clientY,\n contentX: contentPoint.x,\n contentY: contentPoint.y,\n viewRect: createRectSnapshot(this._viewRect),\n button: event.button,\n buttons: event.buttons,\n altKey: event.altKey,\n ctrlKey: event.ctrlKey,\n shiftKey: event.shiftKey,\n metaKey: event.metaKey,\n sourceEvent: event,\n },\n }),\n );\n\n if (!shouldContinue) event.preventDefault();\n }\n\n protected _isOverlayEvent(event: Event): boolean {\n return event\n .composedPath()\n .some(($node) => $node instanceof HTMLSlotElement && $node.name === 'overlay');\n }\n\n /**\n * RAF callback. Dispatches `rc-virtual-canvas-render` and re-schedules in continuous mode.\n *\n * @param time - High-resolution timestamp from `requestAnimationFrame`\n */\n protected _update(time: DOMHighResTimeStamp) {\n this._rafHandle = 0;\n\n if (!this.isConnected || this._$canvas == null) {\n return;\n }\n\n const reason =\n this._pendingRenderReason ??\n (this.renderMode === 'continuous' ? 'animation-frame' : 'manual');\n\n this._pendingRenderReason = undefined;\n\n this.dispatchEvent(\n new CustomEvent<RCVirtualCanvasRenderInit>('rc-virtual-canvas-render', {\n bubbles: true,\n composed: true,\n detail: {\n time,\n reason,\n viewRect: createRectSnapshot(this._viewRect),\n contentRect: createRectSnapshot(this._contentRect),\n },\n }),\n );\n\n if (this.renderMode === 'continuous') {\n this._scheduleRender('animation-frame');\n }\n }\n\n /** Registers pointer event listeners and starts rendering in continuous mode */\n override connectedCallback() {\n super.connectedCallback();\n\n this.addEventListener('pointerdown', this._boundPointerEvent);\n this.addEventListener('pointermove', this._boundPointerEvent);\n this.addEventListener('pointerup', this._boundPointerEvent);\n this.addEventListener('click', this._boundPointerEvent);\n this.addEventListener('dblclick', this._boundPointerEvent);\n this.addEventListener('contextmenu', this._boundPointerEvent);\n\n if (this._rafHandle) {\n cancelAnimationFrame(this._rafHandle);\n this._rafHandle = 0;\n }\n\n if (this.renderMode === 'continuous') {\n this._scheduleRender('animation-frame');\n }\n }\n\n /** Cancels any pending animation frame, disconnects the resize observer, and removes pointer listeners */\n override disconnectedCallback() {\n super.disconnectedCallback();\n\n cancelAnimationFrame(this._rafHandle);\n this._rafHandle = 0;\n this._resizeObserver.disconnect();\n\n this.removeEventListener('pointerdown', this._boundPointerEvent);\n this.removeEventListener('pointermove', this._boundPointerEvent);\n this.removeEventListener('pointerup', this._boundPointerEvent);\n this.removeEventListener('click', this._boundPointerEvent);\n this.removeEventListener('dblclick', this._boundPointerEvent);\n this.removeEventListener('contextmenu', this._boundPointerEvent);\n }\n\n /** Reacts to `renderMode`, `autoResizeCanvas`, and `imageRendering` property changes */\n protected override updated(changed: Map<string, unknown>) {\n if (changed.has('renderMode')) {\n if (this.renderMode === 'continuous') {\n this._scheduleRender('animation-frame');\n } else if (this._pendingRenderReason === 'animation-frame') {\n if (this._rafHandle) {\n cancelAnimationFrame(this._rafHandle);\n\n this._rafHandle = 0;\n }\n\n this._pendingRenderReason = undefined;\n } else if (this.renderMode === 'viewport-change') {\n this._scheduleRender('viewport-change');\n }\n }\n\n if (changed.has('autoResizeCanvas')) {\n this._syncCanvasBackingStore();\n }\n\n if (changed.has('imageRendering')) {\n this.style.setProperty('--rc-virtual-canvas-image-rendering', this.imageRendering);\n }\n }\n\n protected _scheduleRender(reason: RCVirtualCanvasRenderReason) {\n if (this.renderMode === 'manual' && reason !== 'manual') {\n return;\n }\n\n if (this.renderMode === 'viewport-change' && reason === 'animation-frame') {\n return;\n }\n\n this._pendingRenderReason = reason;\n\n if (!this.isConnected || this._rafHandle) {\n return;\n }\n\n this._rafHandle = window.requestAnimationFrame(this._boundUpdate);\n }\n\n protected _syncCanvasBackingStore() {\n if (!this.autoResizeCanvas || this._$canvas == null) {\n return;\n }\n\n const width = Math.max(0, Math.round(this._viewRect.width));\n const height = Math.max(0, Math.round(this._viewRect.height));\n\n if (this._$canvas.width !== width) {\n this._$canvas.width = width;\n }\n\n if (this._$canvas.height !== height) {\n this._$canvas.height = height;\n }\n }\n\n protected _getCanvasClientRect() {\n if (this._$canvas == null) {\n return this.getBoundingClientRect();\n }\n\n return this._$canvas.getBoundingClientRect();\n }\n\n protected _getMeasuredCanvasWidth(fallbackWidth: number) {\n if (!this.autoResizeCanvas && this._$canvas && this._$canvas.width > 0) {\n return this._$canvas.width;\n }\n\n return fallbackWidth;\n }\n\n protected _getMeasuredCanvasHeight(fallbackHeight: number) {\n if (!this.autoResizeCanvas && this._$canvas && this._$canvas.height > 0) {\n return this._$canvas.height;\n }\n\n return fallbackHeight;\n }\n\n protected _getViewportScaleX(canvasRect: DOMRect) {\n return canvasRect.width > 0 ? this._viewRect.width / canvasRect.width : 1;\n }\n\n protected _getViewportScaleY(canvasRect: DOMRect) {\n return canvasRect.height > 0 ? this._viewRect.height / canvasRect.height : 1;\n }\n\n render() {\n return html`\n <div\n id=\"root\"\n part=\"scroller\"\n @scroll=${this._onScroll}\n @pointerdown=${this._onPointerEvent}\n @pointermove=${this._onPointerEvent}\n @pointerup=${this._onPointerEvent}\n @click=${this._onPointerEvent}\n @dblclick=${this._onPointerEvent}\n @contextmenu=${this._onPointerEvent}\n >\n <div id=\"overlay\" part=\"overlay\">\n <slot name=\"overlay\"></slot>\n </div>\n\n <div\n id=\"placeholder\"\n style=${styleMap({\n width: `${this.contentWidth}px`,\n height: `${this.contentHeight}px`,\n })}\n ></div>\n </div>\n\n <slot @slotchange=${this._onSlotChange}></slot>\n `;\n }\n}\n\nexport default RCVirtualCanvas;\n"],"names":["virtualCanvasStyles","css","createRectSnapshot","rect","_RCVirtualCanvas","LitElement","time","event","entries","entry","devicePixelBoxSize","val","oldValue","e","el","$canvas","error","x","y","options","clientX","clientY","canvasRect","scaleX","scaleY","reason","contentPoint","$node","changed","width","height","fallbackWidth","fallbackHeight","html","styleMap","RCVirtualCanvas","__decorateClass","property","query","state"],"mappings":"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"}
|
|
@@ -93,22 +93,43 @@ export type RCVirtualCanvasRenderInit = {
|
|
|
93
93
|
*
|
|
94
94
|
* @fires rc-virtual-canvas-render - Fires with viewport data when the canvas should redraw.
|
|
95
95
|
* @fires rc-virtual-canvas-pointer - Fires pointer/mouse input mapped to virtual content coordinates.
|
|
96
|
+
*
|
|
97
|
+
* @csspart scroller - Internal scroll container that owns the virtual content scroll range.
|
|
98
|
+
* @csspart overlay - Viewport-positioned overlay container rendered inside the scroll container.
|
|
99
|
+
*
|
|
100
|
+
* @attr content-width - Total pixel width of the virtual content.
|
|
101
|
+
* @attr content-height - Total pixel height of the virtual content.
|
|
102
|
+
* @attr auto-resize-canvas - Keep the slotted canvas backing store aligned to the viewport.
|
|
103
|
+
* @attr render-mode - Controls when render events are dispatched.
|
|
104
|
+
* @attr image-rendering - Convenience `image-rendering` value applied to the slotted canvas.
|
|
105
|
+
*
|
|
106
|
+
* @cssprop [--rc-virtual-canvas-scrollbar-width=thin] - `scrollbar-width` of the internal
|
|
107
|
+
* scroll container.
|
|
108
|
+
* @cssprop [--rc-virtual-canvas-scrollbar-size=auto] - WebKit scrollbar thickness.
|
|
109
|
+
* @cssprop [--rc-virtual-canvas-scrollbar-thumb-background=ButtonFace] - WebKit scrollbar
|
|
110
|
+
* thumb color.
|
|
111
|
+
* @cssprop [--rc-virtual-canvas-scrollbar-button-background=ButtonFace] - WebKit scrollbar
|
|
112
|
+
* button color.
|
|
113
|
+
* @cssprop [--rc-virtual-canvas-scrollbar-track-background=Canvas] - WebKit scrollbar
|
|
114
|
+
* track color.
|
|
115
|
+
* @cssprop [--rc-virtual-canvas-image-rendering=auto] - `image-rendering` applied to the
|
|
116
|
+
* slotted canvas; kept in sync with the `imageRendering` property.
|
|
96
117
|
*/
|
|
97
118
|
export declare class RCVirtualCanvas extends LitElement {
|
|
98
119
|
static styles: import('lit').CSSResult[];
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
120
|
+
protected _rafHandle: number;
|
|
121
|
+
protected _pendingRenderReason?: RCVirtualCanvasRenderReason;
|
|
122
|
+
protected readonly _handledPointerEvents: WeakSet<Event>;
|
|
123
|
+
protected readonly _boundUpdate: (time: DOMHighResTimeStamp) => void;
|
|
124
|
+
protected readonly _boundPointerEvent: (event: PointerEvent | MouseEvent) => void;
|
|
104
125
|
/** Pixel width of the virtual content */
|
|
105
126
|
set contentWidth(val: number);
|
|
106
127
|
get contentWidth(): number;
|
|
107
|
-
|
|
128
|
+
private _contentWidth;
|
|
108
129
|
/** Pixel height of the virtual content */
|
|
109
130
|
set contentHeight(val: number);
|
|
110
131
|
get contentHeight(): number;
|
|
111
|
-
|
|
132
|
+
private _contentHeight;
|
|
112
133
|
/** When true, keep the slotted canvas backing store aligned to the viewport. */
|
|
113
134
|
autoResizeCanvas: boolean;
|
|
114
135
|
/** Controls when render events are dispatched. */
|
|
@@ -141,6 +162,8 @@ export declare class RCVirtualCanvas extends LitElement {
|
|
|
141
162
|
protected _onScroll(): void;
|
|
142
163
|
/** Replaces canvas tracking and re-registers the resize observer when slot content changes */
|
|
143
164
|
protected _onSlotChange(e: Event): void;
|
|
165
|
+
/** Observes canvas size with DPR-accurate boxes when the browser supports them */
|
|
166
|
+
protected _observeCanvasResize($canvas: HTMLCanvasElement): void;
|
|
144
167
|
/**
|
|
145
168
|
* Returns a frozen snapshot of the current viewport rectangle.
|
|
146
169
|
*
|
|
@@ -235,7 +258,7 @@ export declare class RCVirtualCanvas extends LitElement {
|
|
|
235
258
|
get canvasScaleY(): number;
|
|
236
259
|
/** Maps pointer and mouse events to content coordinates and dispatches `rc-virtual-canvas-pointer` */
|
|
237
260
|
protected _onPointerEvent(event: PointerEvent | MouseEvent): void;
|
|
238
|
-
|
|
261
|
+
protected _isOverlayEvent(event: Event): boolean;
|
|
239
262
|
/**
|
|
240
263
|
* RAF callback. Dispatches `rc-virtual-canvas-render` and re-schedules in continuous mode.
|
|
241
264
|
*
|
|
@@ -248,13 +271,13 @@ export declare class RCVirtualCanvas extends LitElement {
|
|
|
248
271
|
disconnectedCallback(): void;
|
|
249
272
|
/** Reacts to `renderMode`, `autoResizeCanvas`, and `imageRendering` property changes */
|
|
250
273
|
protected updated(changed: Map<string, unknown>): void;
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
274
|
+
protected _scheduleRender(reason: RCVirtualCanvasRenderReason): void;
|
|
275
|
+
protected _syncCanvasBackingStore(): void;
|
|
276
|
+
protected _getCanvasClientRect(): DOMRect;
|
|
277
|
+
protected _getMeasuredCanvasWidth(fallbackWidth: number): number;
|
|
278
|
+
protected _getMeasuredCanvasHeight(fallbackHeight: number): number;
|
|
279
|
+
protected _getViewportScaleX(canvasRect: DOMRect): number;
|
|
280
|
+
protected _getViewportScaleY(canvasRect: DOMRect): number;
|
|
258
281
|
render(): import('lit').TemplateResult<1>;
|
|
259
282
|
}
|
|
260
283
|
export default RCVirtualCanvas;
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.4.1",
|
|
7
7
|
"description": "Scrollable virtual canvas for rendering large coordinate-space content.",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
@@ -60,4 +60,4 @@
|
|
|
60
60
|
"peerDependencies": {
|
|
61
61
|
"lit": "^3.0.0"
|
|
62
62
|
}
|
|
63
|
-
}
|
|
63
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rc-virtual-canvas-CUVahMP7.js","sources":["../src/rc-virtual-canvas.styles.ts","../src/rc-virtual-canvas.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const virtualCanvasStyles = css`\n *,\n *::before,\n *::after {\n box-sizing: border-box;\n }\n\n :host {\n position: relative;\n display: block;\n width: max-content;\n line-height: 0; /* remove extra space under slotted <canvas> element(s) */\n }\n\n :host([hidden]) {\n display: none;\n }\n\n #root {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n overflow: auto;\n scrollbar-width: var(--rc-virtual-canvas-scrollbar-width, thin);\n }\n\n #root::-webkit-scrollbar {\n width: var(--rc-virtual-canvas-scrollbar-size, auto);\n height: var(--rc-virtual-canvas-scrollbar-size, auto);\n }\n\n #root::-webkit-scrollbar-thumb {\n background: var(--rc-virtual-canvas-scrollbar-thumb-background, ButtonFace);\n }\n\n #root::-webkit-scrollbar-button {\n background: var(--rc-virtual-canvas-scrollbar-button-background, ButtonFace);\n }\n\n #root::-webkit-scrollbar-track {\n background: var(--rc-virtual-canvas-scrollbar-track-background, Canvas);\n }\n\n #placeholder {\n pointer-events: none;\n }\n\n #overlay {\n position: sticky;\n left: 0;\n top: 0;\n z-index: 1;\n display: block;\n width: 100%;\n height: 0;\n pointer-events: none;\n }\n\n ::slotted([slot='overlay']) {\n pointer-events: auto;\n }\n\n ::slotted(canvas) {\n image-rendering: var(--rc-virtual-canvas-image-rendering, auto);\n }\n`;\n\nexport default virtualCanvasStyles;\n","import { LitElement, html } from 'lit';\nimport { property, query, state } from 'lit/decorators.js';\nimport { styleMap } from 'lit/directives/style-map.js';\n\nimport virtualCanvasStyles from './rc-virtual-canvas.styles';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'rc-virtual-canvas': RCVirtualCanvas;\n }\n\n interface HTMLElementEventMap {\n 'rc-virtual-canvas-render': CustomEvent<RCVirtualCanvasRenderInit>;\n 'rc-virtual-canvas-pointer': CustomEvent<RCVirtualCanvasPointerInit>;\n }\n}\n\n/**\n * Scrollable virtual canvas for rendering large coordinate-space content.\n *\n * `x` and `y` are scroll offsets in CSS pixels; `width` and `height` are the canvas\n * backing-store dimensions in device pixels (DPR-accurate when `autoResizeCanvas` is `true`).\n */\nexport type RCVirtualCanvasViewRect = Readonly<{\n /** Scroll offset x in content space (CSS px) */\n x: number;\n\n /** Scroll offset y in content space (CSS px) */\n y: number;\n\n /** Visible width in device pixels */\n width: number;\n\n /** Visible height in device pixels */\n height: number;\n}>;\n\n/** Controls when `rc-virtual-canvas-render` events are dispatched */\nexport type RCVirtualCanvasRenderMode = 'continuous' | 'viewport-change' | 'manual';\n\n/** Identifies what triggered a render event */\nexport type RCVirtualCanvasRenderReason = 'animation-frame' | 'viewport-change' | 'manual';\n\n/** Content-space coordinate pair returned by coordinate-conversion methods */\nexport type RCVirtualCanvasPoint = Readonly<{\n /** Content space x coordinate in CSS pixels */\n x: number;\n\n /** Content space y coordinate in CSS pixels */\n y: number;\n}>;\n\n/**\n * Detail shape for `rc-virtual-canvas-pointer` events.\n *\n * Carries the source event's coordinates in both browser-client and content space,\n * along with all modifier key state.\n */\nexport type RCVirtualCanvasPointerInit = {\n /** DOM event type (e.g. `'pointerdown'`, `'click'`) */\n type: string;\n\n /** Browser client x coordinate from the source event */\n clientX: number;\n\n /** Browser client y coordinate from the source event */\n clientY: number;\n\n /** Content x coordinate mapped through the current backing-store scale */\n contentX: number;\n\n /** Content y coordinate mapped through the current backing-store scale */\n contentY: number;\n\n /** Frozen viewport snapshot at the moment the pointer event fired */\n viewRect: RCVirtualCanvasViewRect;\n\n /** Mouse button index from the source event */\n button: number;\n\n /** Active button bitmask from the source event */\n buttons: number;\n\n /** Whether the Alt key was held */\n altKey: boolean;\n\n /** Whether the Ctrl key was held */\n ctrlKey: boolean;\n\n /** Whether the Shift key was held */\n shiftKey: boolean;\n\n /** Whether the Meta key was held */\n metaKey: boolean;\n\n /** The original DOM event that produced this detail */\n sourceEvent: PointerEvent | MouseEvent;\n};\n\n/** CSS `image-rendering` value applied to the slotted canvas */\nexport type RCVirtualCanvasImageRendering = 'auto' | 'crisp-edges' | 'pixelated';\n\n/** Detail shape for `rc-virtual-canvas-render` events */\nexport type RCVirtualCanvasRenderInit = {\n /** High-resolution timestamp from `requestAnimationFrame` */\n time: DOMHighResTimeStamp;\n\n /** What triggered this render */\n reason: RCVirtualCanvasRenderReason;\n\n /** Frozen snapshot of the viewport for this frame */\n viewRect: RCVirtualCanvasViewRect;\n\n /** Frozen snapshot of the full content bounds for this frame */\n contentRect: RCVirtualCanvasViewRect;\n};\n\nfunction createRectSnapshot(rect: RCVirtualCanvasViewRect) {\n return Object.freeze({\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n });\n}\n\n/**\n * A scrollable virtual canvas component.\n *\n * @see {@link https://richardcarls.github.io/rc-webcomponents/components/rc-virtual-canvas rc-virtual-canvas docs}\n *\n * @slot - The HTMLCanvasElement\n * @slot overlay - Optional viewport-positioned content rendered inside the\n * scroll container above the canvas.\n *\n * @fires rc-virtual-canvas-render - Fires with viewport data when the canvas should redraw.\n * @fires rc-virtual-canvas-pointer - Fires pointer/mouse input mapped to virtual content coordinates.\n */\nexport class RCVirtualCanvas extends LitElement {\n static styles = [virtualCanvasStyles];\n\n private _rafHandle: number = 0;\n private _pendingRenderReason?: RCVirtualCanvasRenderReason;\n private readonly _handledPointerEvents = new WeakSet<Event>();\n\n // Stored bound reference so the same closure is used for scheduling and\n // cancellation — `bind()` returns a new function every call.\n private readonly _boundUpdate = (time: DOMHighResTimeStamp) => this._update(time);\n\n private readonly _boundPointerEvent = (event: PointerEvent | MouseEvent) =>\n this._onPointerEvent(event);\n\n /** Pixel width of the virtual content */\n @property({ type: Number })\n set contentWidth(val: number) {\n const oldValue = this._contentWidth;\n\n this._contentWidth = val;\n\n this._contentRect.width = this._contentWidth;\n this.requestUpdate('contentWidth', oldValue);\n this._scheduleRender('viewport-change');\n }\n get contentWidth() {\n return this._contentWidth;\n }\n protected _contentWidth: number = 0;\n\n /** Pixel height of the virtual content */\n @property({ type: Number })\n set contentHeight(val: number) {\n const oldValue = this._contentHeight;\n\n this._contentHeight = val;\n\n this._contentRect.height = this._contentHeight;\n this.requestUpdate('contentHeight', oldValue);\n this._scheduleRender('viewport-change');\n }\n get contentHeight() {\n return this._contentHeight;\n }\n protected _contentHeight: number = 0;\n\n /** When true, keep the slotted canvas backing store aligned to the viewport. */\n @property({ attribute: 'auto-resize-canvas', type: Boolean })\n autoResizeCanvas: boolean = true;\n\n /** Controls when render events are dispatched. */\n @property({ attribute: 'render-mode' })\n renderMode: RCVirtualCanvasRenderMode = 'continuous';\n\n /** Convenience image-rendering value applied to the slotted canvas. */\n @property({ attribute: 'image-rendering' })\n imageRendering: RCVirtualCanvasImageRendering = 'auto';\n\n /** Shadow DOM scroll container that owns pointer interaction and native scrolling */\n @query('#root', true)\n protected _$root!: HTMLDivElement;\n\n /** Absolutely-positioned div that establishes the virtual scroll range */\n @query('#placeholder', true)\n protected _$placeholder!: HTMLDivElement;\n\n /** Currently-tracked slotted canvas element; `null` when no canvas is slotted */\n @state()\n protected _$canvas: HTMLCanvasElement | null = null;\n\n /** Mutable current-frame viewport geometry; call `getViewRect()` for a frozen snapshot */\n @state()\n protected _viewRect = {\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n };\n\n /** Mutable content bounds; updated when `contentWidth` or `contentHeight` change */\n @state()\n protected _contentRect = {\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n };\n\n /** Watches the slotted canvas for DPR-accurate dimension changes */\n protected _resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]) => {\n for (const entry of entries) {\n const devicePixelBoxSize = Array.isArray(entry.devicePixelContentBoxSize)\n ? entry.devicePixelContentBoxSize[0]\n : entry.devicePixelContentBoxSize;\n\n this._viewRect.width = this._getMeasuredCanvasWidth(\n devicePixelBoxSize?.inlineSize ??\n Math.round(entry.contentRect.width * window.devicePixelRatio),\n );\n\n this._viewRect.height = this._getMeasuredCanvasHeight(\n devicePixelBoxSize?.blockSize ??\n Math.round(entry.contentRect.height * window.devicePixelRatio),\n );\n\n this._syncCanvasBackingStore();\n this._scheduleRender('viewport-change');\n }\n });\n\n /** Reads scroll position from the root container and schedules a render */\n protected _onScroll() {\n this._viewRect.x = this._$root.scrollLeft;\n this._viewRect.y = this._$root.scrollTop;\n\n this._scheduleRender('viewport-change');\n }\n\n /** Replaces canvas tracking and re-registers the resize observer when slot content changes */\n protected _onSlotChange(e: Event) {\n this._resizeObserver.disconnect();\n\n this._$canvas =\n (e.currentTarget as HTMLSlotElement)\n .assignedElements()\n .filter((el) => el instanceof HTMLCanvasElement)\n .at(0) ?? null;\n\n if (this._$canvas != null) {\n this._viewRect = {\n x: this._$root.scrollLeft ?? 0,\n y: this._$root.scrollTop ?? 0,\n width: this._getMeasuredCanvasWidth(this._$canvas.clientWidth),\n height: this._getMeasuredCanvasHeight(this._$canvas.clientHeight),\n };\n\n this._syncCanvasBackingStore();\n this._resizeObserver.observe(this._$canvas, {\n box: 'device-pixel-content-box',\n });\n\n this._scheduleRender('viewport-change');\n }\n }\n\n /**\n * Returns a frozen snapshot of the current viewport rectangle.\n *\n * Safe to keep between frames — the returned object will not be mutated\n * by future scroll or resize work.\n */\n getViewRect() {\n return createRectSnapshot(this._viewRect);\n }\n\n /**\n * Scrolls so the content coordinate is at the viewport origin.\n *\n * @param x - Content x coordinate in CSS pixels\n * @param y - Content y coordinate in CSS pixels\n * @param options - Native scroll options passed to scrollTo\n */\n scrollToContent(x: number, y: number, options: ScrollOptions = {}) {\n this._$root.scrollTo({\n ...options,\n left: x,\n top: y,\n });\n\n this._viewRect.x = this._$root.scrollLeft;\n this._viewRect.y = this._$root.scrollTop;\n this._scheduleRender('viewport-change');\n }\n\n /**\n * Scrolls so the content coordinate is centered in the viewport.\n *\n * @param x - Content x coordinate in CSS pixels\n * @param y - Content y coordinate in CSS pixels\n * @param options - Native scroll options passed to scrollTo\n */\n centerOnContent(x: number, y: number, options: ScrollOptions = {}) {\n this.scrollToContent(\n x - this._$root.clientWidth * 0.5,\n y - this._$root.clientHeight * 0.5,\n options,\n );\n }\n\n /**\n * Converts browser client coordinates to content coordinates using the current\n * backing-store scale.\n *\n * @param clientX - Browser client x coordinate (e.g. from a pointer event)\n * @param clientY - Browser client y coordinate\n *\n * @example\n * vc.addEventListener('pointerdown', (e) => {\n * const { x, y } = vc.clientToContent(e.clientX, e.clientY);\n * placeMarkerAt(x, y);\n * });\n */\n clientToContent(clientX: number, clientY: number) {\n const canvasRect = this._getCanvasClientRect();\n const scaleX = this._getViewportScaleX(canvasRect);\n const scaleY = this._getViewportScaleY(canvasRect);\n\n return Object.freeze({\n x: this._viewRect.x + (clientX - canvasRect.left) * scaleX,\n y: this._viewRect.y + (clientY - canvasRect.top) * scaleY,\n });\n }\n\n /**\n * Converts content coordinates back to browser client coordinates.\n *\n * @param x - Content x coordinate in CSS pixels\n * @param y - Content y coordinate in CSS pixels\n *\n * @example\n * const { x, y } = vc.contentToClient(contentX, contentY);\n * tooltip.style.left = `${x}px`;\n * tooltip.style.top = `${y}px`;\n */\n contentToClient(x: number, y: number) {\n const canvasRect = this._getCanvasClientRect();\n const scaleX = this._getViewportScaleX(canvasRect);\n const scaleY = this._getViewportScaleY(canvasRect);\n\n return Object.freeze({\n x: canvasRect.left + (x - this._viewRect.x) / scaleX,\n y: canvasRect.top + (y - this._viewRect.y) / scaleY,\n });\n }\n\n /**\n * Queues a render event on the next animation frame.\n *\n * Required when `renderMode` is `'manual'`. In other modes the component\n * schedules renders automatically; calling this with reason `'animation-frame'`\n * is a no-op when `renderMode` is `'viewport-change'`.\n *\n * @param reason - Render reason reported in the event detail\n */\n requestRender(reason: RCVirtualCanvasRenderReason = 'manual') {\n this._scheduleRender(reason);\n }\n\n /**\n * Ratio of canvas backing-store pixels to CSS pixels along the x-axis.\n *\n * Equals `devicePixelRatio` when `autoResizeCanvas` is `true`. Use as the x-scale\n * factor in `ctx.scale()` to draw at CSS pixel resolution.\n *\n * @example\n * vc.addEventListener('rc-virtual-canvas-render', ({ detail: { viewRect } }) => {\n * ctx.save();\n * ctx.scale(vc.canvasScaleX, vc.canvasScaleY);\n * drawScene(ctx, viewRect);\n * ctx.restore();\n * });\n */\n get canvasScaleX(): number {\n const canvasRect = this._getCanvasClientRect();\n\n return this._getViewportScaleX(canvasRect);\n }\n\n /**\n * Ratio of canvas backing-store pixels to CSS pixels along the y-axis.\n *\n * Equals `devicePixelRatio` when `autoResizeCanvas` is `true`. Use as the y-scale\n * factor in `ctx.scale()` to draw at CSS pixel resolution.\n */\n get canvasScaleY(): number {\n const canvasRect = this._getCanvasClientRect();\n\n return this._getViewportScaleY(canvasRect);\n }\n\n /** Maps pointer and mouse events to content coordinates and dispatches `rc-virtual-canvas-pointer` */\n protected _onPointerEvent(event: PointerEvent | MouseEvent) {\n if (this._handledPointerEvents.has(event)) {\n return;\n }\n\n if (this._isOverlayEvent(event)) {\n return;\n }\n\n this._handledPointerEvents.add(event);\n\n const contentPoint = this.clientToContent(event.clientX, event.clientY);\n\n const shouldContinue = this.dispatchEvent(\n new CustomEvent<RCVirtualCanvasPointerInit>('rc-virtual-canvas-pointer', {\n bubbles: true,\n composed: true,\n cancelable: true,\n detail: {\n type: event.type,\n clientX: event.clientX,\n clientY: event.clientY,\n contentX: contentPoint.x,\n contentY: contentPoint.y,\n viewRect: createRectSnapshot(this._viewRect),\n button: event.button,\n buttons: event.buttons,\n altKey: event.altKey,\n ctrlKey: event.ctrlKey,\n shiftKey: event.shiftKey,\n metaKey: event.metaKey,\n sourceEvent: event,\n },\n }),\n );\n\n if (!shouldContinue) event.preventDefault();\n }\n\n private _isOverlayEvent(event: Event): boolean {\n return event\n .composedPath()\n .some((node) => node instanceof HTMLSlotElement && node.name === 'overlay');\n }\n\n /**\n * RAF callback. Dispatches `rc-virtual-canvas-render` and re-schedules in continuous mode.\n *\n * @param time - High-resolution timestamp from `requestAnimationFrame`\n */\n protected _update(time: DOMHighResTimeStamp) {\n this._rafHandle = 0;\n\n if (!this.isConnected || this._$canvas == null) {\n return;\n }\n\n const reason =\n this._pendingRenderReason ??\n (this.renderMode === 'continuous' ? 'animation-frame' : 'manual');\n\n this._pendingRenderReason = undefined;\n\n this.dispatchEvent(\n new CustomEvent<RCVirtualCanvasRenderInit>('rc-virtual-canvas-render', {\n bubbles: true,\n composed: true,\n detail: {\n time,\n reason,\n viewRect: createRectSnapshot(this._viewRect),\n contentRect: createRectSnapshot(this._contentRect),\n },\n }),\n );\n\n if (this.renderMode === 'continuous') {\n this._scheduleRender('animation-frame');\n }\n }\n\n /** Registers pointer event listeners and starts rendering in continuous mode */\n override connectedCallback() {\n super.connectedCallback();\n\n this.addEventListener('pointerdown', this._boundPointerEvent);\n this.addEventListener('pointermove', this._boundPointerEvent);\n this.addEventListener('pointerup', this._boundPointerEvent);\n this.addEventListener('click', this._boundPointerEvent);\n this.addEventListener('dblclick', this._boundPointerEvent);\n this.addEventListener('contextmenu', this._boundPointerEvent);\n\n if (this._rafHandle) {\n cancelAnimationFrame(this._rafHandle);\n this._rafHandle = 0;\n }\n\n if (this.renderMode === 'continuous') {\n this._scheduleRender('animation-frame');\n }\n }\n\n /** Cancels any pending animation frame, disconnects the resize observer, and removes pointer listeners */\n override disconnectedCallback() {\n super.disconnectedCallback();\n\n cancelAnimationFrame(this._rafHandle);\n this._rafHandle = 0;\n this._resizeObserver.disconnect();\n\n this.removeEventListener('pointerdown', this._boundPointerEvent);\n this.removeEventListener('pointermove', this._boundPointerEvent);\n this.removeEventListener('pointerup', this._boundPointerEvent);\n this.removeEventListener('click', this._boundPointerEvent);\n this.removeEventListener('dblclick', this._boundPointerEvent);\n this.removeEventListener('contextmenu', this._boundPointerEvent);\n }\n\n /** Reacts to `renderMode`, `autoResizeCanvas`, and `imageRendering` property changes */\n protected override updated(changed: Map<string, unknown>) {\n if (changed.has('renderMode')) {\n if (this.renderMode === 'continuous') {\n this._scheduleRender('animation-frame');\n } else if (this._pendingRenderReason === 'animation-frame') {\n if (this._rafHandle) {\n cancelAnimationFrame(this._rafHandle);\n\n this._rafHandle = 0;\n }\n\n this._pendingRenderReason = undefined;\n } else if (this.renderMode === 'viewport-change') {\n this._scheduleRender('viewport-change');\n }\n }\n\n if (changed.has('autoResizeCanvas')) {\n this._syncCanvasBackingStore();\n }\n\n if (changed.has('imageRendering')) {\n this.style.setProperty('--rc-virtual-canvas-image-rendering', this.imageRendering);\n }\n }\n\n private _scheduleRender(reason: RCVirtualCanvasRenderReason) {\n if (this.renderMode === 'manual' && reason !== 'manual') {\n return;\n }\n\n if (this.renderMode === 'viewport-change' && reason === 'animation-frame') {\n return;\n }\n\n this._pendingRenderReason = reason;\n\n if (!this.isConnected || this._rafHandle) {\n return;\n }\n\n this._rafHandle = window.requestAnimationFrame(this._boundUpdate);\n }\n\n private _syncCanvasBackingStore() {\n if (!this.autoResizeCanvas || this._$canvas == null) {\n return;\n }\n\n const width = Math.max(0, Math.round(this._viewRect.width));\n const height = Math.max(0, Math.round(this._viewRect.height));\n\n if (this._$canvas.width !== width) {\n this._$canvas.width = width;\n }\n\n if (this._$canvas.height !== height) {\n this._$canvas.height = height;\n }\n }\n\n private _getCanvasClientRect() {\n if (this._$canvas == null) {\n return this.getBoundingClientRect();\n }\n\n return this._$canvas.getBoundingClientRect();\n }\n\n private _getMeasuredCanvasWidth(fallbackWidth: number) {\n if (!this.autoResizeCanvas && this._$canvas && this._$canvas.width > 0) {\n return this._$canvas.width;\n }\n\n return fallbackWidth;\n }\n\n private _getMeasuredCanvasHeight(fallbackHeight: number) {\n if (!this.autoResizeCanvas && this._$canvas && this._$canvas.height > 0) {\n return this._$canvas.height;\n }\n\n return fallbackHeight;\n }\n\n private _getViewportScaleX(canvasRect: DOMRect) {\n return canvasRect.width > 0 ? this._viewRect.width / canvasRect.width : 1;\n }\n\n private _getViewportScaleY(canvasRect: DOMRect) {\n return canvasRect.height > 0 ? this._viewRect.height / canvasRect.height : 1;\n }\n\n render() {\n return html`\n <div\n id=\"root\"\n part=\"scroller\"\n @scroll=${this._onScroll}\n @pointerdown=${this._onPointerEvent}\n @pointermove=${this._onPointerEvent}\n @pointerup=${this._onPointerEvent}\n @click=${this._onPointerEvent}\n @dblclick=${this._onPointerEvent}\n @contextmenu=${this._onPointerEvent}\n >\n <div id=\"overlay\" part=\"overlay\">\n <slot name=\"overlay\"></slot>\n </div>\n\n <div\n id=\"placeholder\"\n style=${styleMap({\n width: `${this.contentWidth}px`,\n height: `${this.contentHeight}px`,\n })}\n ></div>\n </div>\n\n <slot @slotchange=${this._onSlotChange}></slot>\n `;\n }\n}\n\nexport default RCVirtualCanvas;\n"],"names":["virtualCanvasStyles","css","createRectSnapshot","rect","_RCVirtualCanvas","LitElement","time","event","entries","entry","devicePixelBoxSize","val","oldValue","e","el","x","y","options","clientX","clientY","canvasRect","scaleX","scaleY","reason","contentPoint","node","changed","width","height","fallbackWidth","fallbackHeight","html","styleMap","RCVirtualCanvas","__decorateClass","property","query","state"],"mappings":"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"}
|