@rcarls/rc-virtual-canvas 0.1.0

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/dist/demo.css ADDED
@@ -0,0 +1,85 @@
1
+ *, *::before, *::after {
2
+ box-sizing: border-box;
3
+ }
4
+
5
+ :root {
6
+ color-scheme: light dark;
7
+ --rc-accent: Highlight; /* Chrome doesn't support AccentColor on the open web */
8
+ }
9
+
10
+ @supports (color: AccentColor) {
11
+ :root {
12
+ --rc-accent: AccentColor;
13
+ }
14
+ }
15
+
16
+ [data-theme="light"] { color-scheme: light; }
17
+ [data-theme="dark"] { color-scheme: dark; }
18
+
19
+ [data-theme="solarized-light"] {
20
+ color-scheme: light;
21
+ --rc-surface: #fdf6e3;
22
+ --rc-text: #657b83;
23
+ --rc-border: 1px solid #93a1a1;
24
+ --rc-shadow: 0 2px 8px rgba(0, 0, 0, .12);
25
+ }
26
+
27
+ [data-theme="solarized-dark"] {
28
+ color-scheme: dark;
29
+ --rc-surface: #002b36;
30
+ --rc-text: #839496;
31
+ --rc-border: 1px solid #586e75;
32
+ --rc-shadow: 0 2px 8px rgba(0, 0, 0, .3);
33
+ }
34
+
35
+ body {
36
+ font-family: system-ui, sans-serif;
37
+ margin: 0;
38
+ }
39
+
40
+ .demo-page {
41
+ max-width: 60rem;
42
+ margin: 0 auto;
43
+ padding: 2rem 1.5rem;
44
+ }
45
+
46
+ .demo-controls {
47
+ display: flex;
48
+ align-items: center;
49
+ gap: 1rem;
50
+ margin-bottom: 2rem;
51
+ padding-bottom: 1rem;
52
+ border-bottom: 1px solid ButtonBorder;
53
+ }
54
+
55
+ .demo-controls .demo-title {
56
+ flex: 1;
57
+ }
58
+
59
+ .demo-controls h1 {
60
+ margin: 0 0 0.15rem;
61
+ font-size: 1.5rem;
62
+ }
63
+
64
+ .demo-controls a {
65
+ font-size: 0.8rem;
66
+ }
67
+
68
+ .demo-section {
69
+ margin-bottom: 2rem;
70
+ }
71
+
72
+ .demo-section h2 {
73
+ margin: 0 0 0.5rem;
74
+ }
75
+
76
+ .theme-picker {
77
+ padding: 0.35em 0.75em;
78
+ font-family: inherit;
79
+ font-size: 0.8rem;
80
+ cursor: pointer;
81
+ border: 1px solid ButtonBorder;
82
+ border-radius: 4px;
83
+ background: Canvas;
84
+ color: CanvasText;
85
+ }
package/dist/demo.js ADDED
@@ -0,0 +1,40 @@
1
+ const THEMES = ['', 'light', 'dark', 'solarized-light', 'solarized-dark'];
2
+ const LABELS = ['Auto', 'Light', 'Dark', 'Solarized ☀', 'Solarized ☾'];
3
+
4
+ const stored = localStorage.getItem('rc-demo-theme') ?? '';
5
+ applyTheme(stored);
6
+
7
+ function applyTheme(theme) {
8
+ if (theme) {
9
+ document.documentElement.dataset.theme = theme;
10
+ } else {
11
+ delete document.documentElement.dataset.theme;
12
+ }
13
+ }
14
+
15
+ function currentIndex() {
16
+ const current = document.documentElement.dataset.theme ?? '';
17
+ const idx = THEMES.indexOf(current);
18
+ return idx === -1 ? 0 : idx;
19
+ }
20
+
21
+ function updateButtons() {
22
+ const label = LABELS[currentIndex()];
23
+ document.querySelectorAll('.theme-picker').forEach((btn) => {
24
+ btn.textContent = label;
25
+ });
26
+ }
27
+
28
+ window.cycleTheme = function () {
29
+ const next = THEMES[(currentIndex() + 1) % THEMES.length];
30
+ applyTheme(next);
31
+ localStorage.setItem('rc-demo-theme', next);
32
+ updateButtons();
33
+ };
34
+
35
+ document.addEventListener('DOMContentLoaded', () => {
36
+ updateButtons();
37
+ document.querySelectorAll('.theme-picker').forEach((btn) => {
38
+ btn.addEventListener('click', window.cycleTheme);
39
+ });
40
+ });
@@ -0,0 +1,323 @@
1
+ import { css as _, LitElement as p, html as g } from "lit";
2
+ import { property as h, query as u, state as l } from "lit/decorators.js";
3
+ import { styleMap as b } from "lit/directives/style-map.js";
4
+ const w = _`
5
+ *,
6
+ *::before,
7
+ *::after {
8
+ box-sizing: border-box;
9
+ }
10
+
11
+ :host {
12
+ position: relative;
13
+ display: block;
14
+ width: max-content;
15
+ line-height: 0; /* remove extra space under slotted <canvas> element(s) */
16
+ }
17
+
18
+ :host([hidden]) {
19
+ display: none;
20
+ }
21
+
22
+ #root {
23
+ position: absolute;
24
+ top: 0;
25
+ left: 0;
26
+ width: 100%;
27
+ height: 100%;
28
+
29
+ overflow: auto;
30
+ scrollbar-width: var(--rc-virtual-canvas-scrollbar-width, thin);
31
+ }
32
+
33
+ #root::-webkit-scrollbar {
34
+ width: var(--rc-virtual-canvas-scrollbar-size, auto);
35
+ height: var(--rc-virtual-canvas-scrollbar-size, auto);
36
+ }
37
+
38
+ #root::-webkit-scrollbar-thumb {
39
+ background: var(--rc-virtual-canvas-scrollbar-thumb-background, ButtonFace);
40
+ }
41
+
42
+ #root::-webkit-scrollbar-button {
43
+ background: var(--rc-virtual-canvas-scrollbar-button-background, ButtonFace);
44
+ }
45
+
46
+ #root::-webkit-scrollbar-track {
47
+ background: var(--rc-virtual-canvas-scrollbar-track-background, Canvas);
48
+ }
49
+
50
+ #placeholder {
51
+ pointer-events: none;
52
+ }
53
+
54
+ #overlay {
55
+ position: sticky;
56
+ left: 0;
57
+ top: 0;
58
+ z-index: 1;
59
+ display: block;
60
+ width: 100%;
61
+ height: 0;
62
+ pointer-events: none;
63
+ }
64
+
65
+ ::slotted([slot='overlay']) {
66
+ pointer-events: auto;
67
+ }
68
+
69
+ ::slotted(canvas) {
70
+ image-rendering: var(--rc-virtual-canvas-image-rendering, auto);
71
+ }
72
+ `;
73
+ var m = Object.defineProperty, f = Object.getOwnPropertyDescriptor, o = (r, t, e, i) => {
74
+ for (var s = i > 1 ? void 0 : i ? f(t, e) : t, a = r.length - 1, d; a >= 0; a--)
75
+ (d = r[a]) && (s = (i ? d(t, e, s) : d(s)) || s);
76
+ return i && s && m(t, e, s), s;
77
+ };
78
+ function c(r) {
79
+ return Object.freeze({
80
+ x: r.x,
81
+ y: r.y,
82
+ width: r.width,
83
+ height: r.height
84
+ });
85
+ }
86
+ const v = class v extends p {
87
+ constructor() {
88
+ super(...arguments), this._rafHandle = 0, this._handledPointerEvents = /* @__PURE__ */ new WeakSet(), this._boundUpdate = (t) => this._update(t), this._boundPointerEvent = (t) => this._onPointerEvent(t), this._contentWidth = 0, this._contentHeight = 0, this.autoResizeCanvas = !0, this.renderMode = "continuous", this.imageRendering = "auto", this._$canvas = null, this._viewRect = {
89
+ x: 0,
90
+ y: 0,
91
+ width: 0,
92
+ height: 0
93
+ }, this._contentRect = {
94
+ x: 0,
95
+ y: 0,
96
+ width: 0,
97
+ height: 0
98
+ }, this._resizeObserver = new ResizeObserver(
99
+ (t) => {
100
+ for (const e of t) {
101
+ const i = Array.isArray(
102
+ e.devicePixelContentBoxSize
103
+ ) ? e.devicePixelContentBoxSize[0] : e.devicePixelContentBoxSize;
104
+ this._viewRect.width = this._getMeasuredCanvasWidth(
105
+ i?.inlineSize ?? Math.round(e.contentRect.width * window.devicePixelRatio)
106
+ ), this._viewRect.height = this._getMeasuredCanvasHeight(
107
+ i?.blockSize ?? Math.round(e.contentRect.height * window.devicePixelRatio)
108
+ ), this._syncCanvasBackingStore(), this._scheduleRender("viewport-change");
109
+ }
110
+ }
111
+ );
112
+ }
113
+ set contentWidth(t) {
114
+ const e = this._contentWidth;
115
+ this._contentWidth = t, this._contentRect.width = this._contentWidth, this.requestUpdate("contentWidth", e), this._scheduleRender("viewport-change");
116
+ }
117
+ get contentWidth() {
118
+ return this._contentWidth;
119
+ }
120
+ set contentHeight(t) {
121
+ const e = this._contentHeight;
122
+ this._contentHeight = t, this._contentRect.height = this._contentHeight, this.requestUpdate("contentHeight", e), this._scheduleRender("viewport-change");
123
+ }
124
+ get contentHeight() {
125
+ return this._contentHeight;
126
+ }
127
+ _onScroll() {
128
+ this._viewRect.x = this._$root.scrollLeft, this._viewRect.y = this._$root.scrollTop, this._scheduleRender("viewport-change");
129
+ }
130
+ _onSlotChange(t) {
131
+ this._resizeObserver.disconnect(), this._$canvas = t.currentTarget.assignedElements().filter((e) => e instanceof HTMLCanvasElement).at(0) ?? null, this._$canvas != null && (this._viewRect = {
132
+ x: this._$root.scrollLeft ?? 0,
133
+ y: this._$root.scrollTop ?? 0,
134
+ width: this._getMeasuredCanvasWidth(this._$canvas.clientWidth),
135
+ height: this._getMeasuredCanvasHeight(this._$canvas.clientHeight)
136
+ }, this._syncCanvasBackingStore(), this._resizeObserver.observe(this._$canvas, {
137
+ box: "device-pixel-content-box"
138
+ }), this._scheduleRender("viewport-change"));
139
+ }
140
+ getViewRect() {
141
+ return c(this._viewRect);
142
+ }
143
+ scrollToContent(t, e, i = {}) {
144
+ this._$root.scrollTo({
145
+ ...i,
146
+ left: t,
147
+ top: e
148
+ }), this._viewRect.x = this._$root.scrollLeft, this._viewRect.y = this._$root.scrollTop, this._scheduleRender("viewport-change");
149
+ }
150
+ centerOnContent(t, e, i = {}) {
151
+ this.scrollToContent(
152
+ t - this._$root.clientWidth * 0.5,
153
+ e - this._$root.clientHeight * 0.5,
154
+ i
155
+ );
156
+ }
157
+ clientToContent(t, e) {
158
+ const i = this._getCanvasClientRect(), s = this._getViewportScaleX(i), a = this._getViewportScaleY(i);
159
+ return Object.freeze({
160
+ x: this._viewRect.x + (t - i.left) * s,
161
+ y: this._viewRect.y + (e - i.top) * a
162
+ });
163
+ }
164
+ contentToClient(t, e) {
165
+ const i = this._getCanvasClientRect(), s = this._getViewportScaleX(i), a = this._getViewportScaleY(i);
166
+ return Object.freeze({
167
+ x: i.left + (t - this._viewRect.x) / s,
168
+ y: i.top + (e - this._viewRect.y) / a
169
+ });
170
+ }
171
+ requestRender(t = "manual") {
172
+ this._scheduleRender(t);
173
+ }
174
+ _onPointerEvent(t) {
175
+ if (this._handledPointerEvents.has(t) || this._isOverlayEvent(t)) return;
176
+ this._handledPointerEvents.add(t);
177
+ const e = this.clientToContent(t.clientX, t.clientY);
178
+ this.dispatchEvent(
179
+ new CustomEvent("rc-virtual-canvas-pointer", {
180
+ bubbles: !0,
181
+ composed: !0,
182
+ cancelable: !0,
183
+ detail: {
184
+ type: t.type,
185
+ clientX: t.clientX,
186
+ clientY: t.clientY,
187
+ contentX: e.x,
188
+ contentY: e.y,
189
+ viewRect: c(this._viewRect),
190
+ button: t.button,
191
+ buttons: t.buttons,
192
+ altKey: t.altKey,
193
+ ctrlKey: t.ctrlKey,
194
+ shiftKey: t.shiftKey,
195
+ metaKey: t.metaKey,
196
+ sourceEvent: t
197
+ }
198
+ })
199
+ ) || t.preventDefault();
200
+ }
201
+ _isOverlayEvent(t) {
202
+ return t.composedPath().some(
203
+ (e) => e instanceof HTMLSlotElement && e.name === "overlay"
204
+ );
205
+ }
206
+ _update(t) {
207
+ if (this._rafHandle = 0, !this.isConnected || this._$canvas == null)
208
+ return;
209
+ const e = this._pendingRenderReason ?? (this.renderMode === "continuous" ? "animation-frame" : "manual");
210
+ this._pendingRenderReason = void 0, this.dispatchEvent(
211
+ new CustomEvent("rc-virtual-canvas-render", {
212
+ bubbles: !0,
213
+ composed: !0,
214
+ detail: {
215
+ time: t,
216
+ reason: e,
217
+ viewRect: c(this._viewRect),
218
+ contentRect: c(this._contentRect)
219
+ }
220
+ })
221
+ ), this.renderMode === "continuous" && this._scheduleRender("animation-frame");
222
+ }
223
+ connectedCallback() {
224
+ super.connectedCallback(), this.addEventListener("pointerdown", this._boundPointerEvent), this.addEventListener("pointermove", this._boundPointerEvent), this.addEventListener("pointerup", this._boundPointerEvent), this.addEventListener("click", this._boundPointerEvent), this.addEventListener("dblclick", this._boundPointerEvent), this.addEventListener("contextmenu", this._boundPointerEvent), this._rafHandle && (cancelAnimationFrame(this._rafHandle), this._rafHandle = 0), this.renderMode === "continuous" && this._scheduleRender("animation-frame");
225
+ }
226
+ disconnectedCallback() {
227
+ super.disconnectedCallback(), cancelAnimationFrame(this._rafHandle), this._rafHandle = 0, this._resizeObserver.disconnect(), this.removeEventListener("pointerdown", this._boundPointerEvent), this.removeEventListener("pointermove", this._boundPointerEvent), this.removeEventListener("pointerup", this._boundPointerEvent), this.removeEventListener("click", this._boundPointerEvent), this.removeEventListener("dblclick", this._boundPointerEvent), this.removeEventListener("contextmenu", this._boundPointerEvent);
228
+ }
229
+ updated(t) {
230
+ t.has("renderMode") && (this.renderMode === "continuous" ? this._scheduleRender("animation-frame") : this._pendingRenderReason === "animation-frame" ? (this._rafHandle && (cancelAnimationFrame(this._rafHandle), this._rafHandle = 0), this._pendingRenderReason = void 0) : this.renderMode === "viewport-change" && this._scheduleRender("viewport-change")), t.has("autoResizeCanvas") && this._syncCanvasBackingStore(), t.has("imageRendering") && this.style.setProperty(
231
+ "--rc-virtual-canvas-image-rendering",
232
+ this.imageRendering
233
+ );
234
+ }
235
+ _scheduleRender(t) {
236
+ this.renderMode === "manual" && t !== "manual" || this.renderMode === "viewport-change" && t === "animation-frame" || (this._pendingRenderReason = t, !(!this.isConnected || this._rafHandle) && (this._rafHandle = window.requestAnimationFrame(this._boundUpdate)));
237
+ }
238
+ _syncCanvasBackingStore() {
239
+ if (!this.autoResizeCanvas || this._$canvas == null)
240
+ return;
241
+ const t = Math.max(0, Math.round(this._viewRect.width)), e = Math.max(0, Math.round(this._viewRect.height));
242
+ this._$canvas.width !== t && (this._$canvas.width = t), this._$canvas.height !== e && (this._$canvas.height = e);
243
+ }
244
+ _getCanvasClientRect() {
245
+ return this._$canvas == null ? this.getBoundingClientRect() : this._$canvas.getBoundingClientRect();
246
+ }
247
+ _getMeasuredCanvasWidth(t) {
248
+ return !this.autoResizeCanvas && this._$canvas && this._$canvas.width > 0 ? this._$canvas.width : t;
249
+ }
250
+ _getMeasuredCanvasHeight(t) {
251
+ return !this.autoResizeCanvas && this._$canvas && this._$canvas.height > 0 ? this._$canvas.height : t;
252
+ }
253
+ _getViewportScaleX(t) {
254
+ return t.width > 0 ? this._viewRect.width / t.width : 1;
255
+ }
256
+ _getViewportScaleY(t) {
257
+ return t.height > 0 ? this._viewRect.height / t.height : 1;
258
+ }
259
+ render() {
260
+ return g`
261
+ <div
262
+ id="root"
263
+ part="scroller"
264
+ @scroll=${this._onScroll}
265
+ @pointerdown=${this._onPointerEvent}
266
+ @pointermove=${this._onPointerEvent}
267
+ @pointerup=${this._onPointerEvent}
268
+ @click=${this._onPointerEvent}
269
+ @dblclick=${this._onPointerEvent}
270
+ @contextmenu=${this._onPointerEvent}
271
+ >
272
+ <div id="overlay" part="overlay">
273
+ <slot name="overlay"></slot>
274
+ </div>
275
+ <div
276
+ id="placeholder"
277
+ style=${b({
278
+ width: `${this.contentWidth}px`,
279
+ height: `${this.contentHeight}px`
280
+ })}
281
+ ></div>
282
+ </div>
283
+
284
+ <slot @slotchange=${this._onSlotChange}></slot>
285
+ `;
286
+ }
287
+ };
288
+ v.styles = [w];
289
+ let n = v;
290
+ o([
291
+ h({ type: Number })
292
+ ], n.prototype, "contentWidth", 1);
293
+ o([
294
+ h({ type: Number })
295
+ ], n.prototype, "contentHeight", 1);
296
+ o([
297
+ h({ attribute: "auto-resize-canvas", type: Boolean })
298
+ ], n.prototype, "autoResizeCanvas", 2);
299
+ o([
300
+ h({ attribute: "render-mode" })
301
+ ], n.prototype, "renderMode", 2);
302
+ o([
303
+ h({ attribute: "image-rendering" })
304
+ ], n.prototype, "imageRendering", 2);
305
+ o([
306
+ u("#root", !0)
307
+ ], n.prototype, "_$root", 2);
308
+ o([
309
+ u("#placeholder", !0)
310
+ ], n.prototype, "_$placeholder", 2);
311
+ o([
312
+ l()
313
+ ], n.prototype, "_$canvas", 2);
314
+ o([
315
+ l()
316
+ ], n.prototype, "_viewRect", 2);
317
+ o([
318
+ l()
319
+ ], n.prototype, "_contentRect", 2);
320
+ export {
321
+ n as R
322
+ };
323
+ //# sourceMappingURL=rc-virtual-canvas-BJQbqNEu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rc-virtual-canvas-BJQbqNEu.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\nexport type RCVirtualCanvasViewRect = Readonly<{\n x: number;\n y: number;\n width: number;\n height: number;\n}>;\n\nexport type RCVirtualCanvasRenderMode =\n | 'continuous'\n | 'viewport-change'\n | 'manual';\n\nexport type RCVirtualCanvasRenderReason =\n | 'animation-frame'\n | 'viewport-change'\n | 'manual';\n\nexport type RCVirtualCanvasPoint = Readonly<{\n x: number;\n y: number;\n}>;\n\nexport type RCVirtualCanvasPointerInit = {\n type: string;\n clientX: number;\n clientY: number;\n contentX: number;\n contentY: number;\n viewRect: RCVirtualCanvasViewRect;\n button: number;\n buttons: number;\n altKey: boolean;\n ctrlKey: boolean;\n shiftKey: boolean;\n metaKey: boolean;\n sourceEvent: PointerEvent | MouseEvent;\n};\n\nexport type RCVirtualCanvasImageRendering =\n | 'auto'\n | 'crisp-edges'\n | 'pixelated';\n\nexport type RCVirtualCanvasRenderInit = {\n time: DOMHighResTimeStamp;\n reason: RCVirtualCanvasRenderReason;\n viewRect: RCVirtualCanvasViewRect;\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\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 * An accessible virtual scrollable canvas component.\n *\n * @slot - The HTMLCanvasElement\n * @slot overlay - Optional viewport-positioned content rendered inside the\n * scroll container above the canvas.\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) =>\n 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 @query('#root', true)\n protected _$root!: HTMLDivElement;\n\n @query('#placeholder', true)\n protected _$placeholder!: HTMLDivElement;\n\n @state()\n protected _$canvas: HTMLCanvasElement | null = null;\n\n @state()\n protected _viewRect = {\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n };\n\n @state()\n protected _contentRect = {\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n };\n\n protected _resizeObserver = new ResizeObserver(\n (entries: ResizeObserverEntry[]) => {\n for (const entry of entries) {\n const devicePixelBoxSize = Array.isArray(\n entry.devicePixelContentBoxSize,\n )\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 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\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 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 this._scheduleRender('viewport-change');\n }\n }\n\n getViewRect() {\n return createRectSnapshot(this._viewRect);\n }\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 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 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 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 requestRender(reason: RCVirtualCanvasRenderReason = 'manual') {\n this._scheduleRender(reason);\n }\n\n protected _onPointerEvent(event: PointerEvent | MouseEvent) {\n if (this._handledPointerEvents.has(event)) return;\n if (this._isOverlayEvent(event)) return;\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.composedPath().some((node) =>\n node instanceof HTMLSlotElement\n && node.name === 'overlay',\n );\n }\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 = 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 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 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 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 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(\n '--rc-virtual-canvas-image-rendering',\n this.imageRendering,\n );\n }\n }\n\n private _scheduleRender(reason: RCVirtualCanvasRenderReason) {\n if (this.renderMode === 'manual' && reason !== 'manual') {\n return;\n }\n\n if (\n this.renderMode === 'viewport-change'\n && reason === 'animation-frame'\n ) {\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\n ? this._viewRect.width / canvasRect.width\n : 1;\n }\n\n private _getViewportScaleY(canvasRect: DOMRect) {\n return canvasRect.height > 0\n ? this._viewRect.height / canvasRect.height\n : 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 <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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"}
@@ -0,0 +1,6 @@
1
+ import { R as a } from "./rc-virtual-canvas-BJQbqNEu.js";
2
+ customElements.get("rc-virtual-canvas") || customElements.define("rc-virtual-canvas", a);
3
+ export {
4
+ a as RCVirtualCanvas
5
+ };
6
+ //# sourceMappingURL=rc-virtual-canvas-define.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rc-virtual-canvas-define.js","sources":["../src/define.ts"],"sourcesContent":["import { RCVirtualCanvas } from './index.js';\n\ncustomElements.get('rc-virtual-canvas') || customElements.define('rc-virtual-canvas', RCVirtualCanvas);\n\nexport * from './index.js';\n"],"names":["RCVirtualCanvas"],"mappings":";AAEA,eAAe,IAAI,mBAAmB,KAAK,eAAe,OAAO,qBAAqBA,CAAe;"}
@@ -0,0 +1,5 @@
1
+ import { R as o } from "./rc-virtual-canvas-BJQbqNEu.js";
2
+ export {
3
+ o as RCVirtualCanvas
4
+ };
5
+ //# sourceMappingURL=rc-virtual-canvas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rc-virtual-canvas.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -0,0 +1 @@
1
+ export * from './index.js';
@@ -0,0 +1 @@
1
+ export * from './rc-virtual-canvas';
@@ -0,0 +1,125 @@
1
+ import { LitElement } from 'lit';
2
+ export type RCVirtualCanvasViewRect = Readonly<{
3
+ x: number;
4
+ y: number;
5
+ width: number;
6
+ height: number;
7
+ }>;
8
+ export type RCVirtualCanvasRenderMode = 'continuous' | 'viewport-change' | 'manual';
9
+ export type RCVirtualCanvasRenderReason = 'animation-frame' | 'viewport-change' | 'manual';
10
+ export type RCVirtualCanvasPoint = Readonly<{
11
+ x: number;
12
+ y: number;
13
+ }>;
14
+ export type RCVirtualCanvasPointerInit = {
15
+ type: string;
16
+ clientX: number;
17
+ clientY: number;
18
+ contentX: number;
19
+ contentY: number;
20
+ viewRect: RCVirtualCanvasViewRect;
21
+ button: number;
22
+ buttons: number;
23
+ altKey: boolean;
24
+ ctrlKey: boolean;
25
+ shiftKey: boolean;
26
+ metaKey: boolean;
27
+ sourceEvent: PointerEvent | MouseEvent;
28
+ };
29
+ export type RCVirtualCanvasImageRendering = 'auto' | 'crisp-edges' | 'pixelated';
30
+ export type RCVirtualCanvasRenderInit = {
31
+ time: DOMHighResTimeStamp;
32
+ reason: RCVirtualCanvasRenderReason;
33
+ viewRect: RCVirtualCanvasViewRect;
34
+ contentRect: RCVirtualCanvasViewRect;
35
+ };
36
+ declare global {
37
+ interface HTMLElementTagNameMap {
38
+ 'rc-virtual-canvas': RCVirtualCanvas;
39
+ }
40
+ interface HTMLElementEventMap {
41
+ 'rc-virtual-canvas-render': CustomEvent<RCVirtualCanvasRenderInit>;
42
+ 'rc-virtual-canvas-pointer': CustomEvent<RCVirtualCanvasPointerInit>;
43
+ }
44
+ }
45
+ /**
46
+ * An accessible virtual scrollable canvas component.
47
+ *
48
+ * @slot - The HTMLCanvasElement
49
+ * @slot overlay - Optional viewport-positioned content rendered inside the
50
+ * scroll container above the canvas.
51
+ * @fires rc-virtual-canvas-render - Fires with viewport data when the canvas should redraw.
52
+ * @fires rc-virtual-canvas-pointer - Fires pointer/mouse input mapped to virtual content coordinates.
53
+ */
54
+ export declare class RCVirtualCanvas extends LitElement {
55
+ static styles: import('lit').CSSResult[];
56
+ private _rafHandle;
57
+ private _pendingRenderReason?;
58
+ private readonly _handledPointerEvents;
59
+ private readonly _boundUpdate;
60
+ private readonly _boundPointerEvent;
61
+ /** Pixel width of the virtual content */
62
+ set contentWidth(val: number);
63
+ get contentWidth(): number;
64
+ protected _contentWidth: number;
65
+ /** Pixel height of the virtual content */
66
+ set contentHeight(val: number);
67
+ get contentHeight(): number;
68
+ protected _contentHeight: number;
69
+ /** When true, keep the slotted canvas backing store aligned to the viewport. */
70
+ autoResizeCanvas: boolean;
71
+ /** Controls when render events are dispatched. */
72
+ renderMode: RCVirtualCanvasRenderMode;
73
+ /** Convenience image-rendering value applied to the slotted canvas. */
74
+ imageRendering: RCVirtualCanvasImageRendering;
75
+ protected _$root: HTMLDivElement;
76
+ protected _$placeholder: HTMLDivElement;
77
+ protected _$canvas: HTMLCanvasElement | null;
78
+ protected _viewRect: {
79
+ x: number;
80
+ y: number;
81
+ width: number;
82
+ height: number;
83
+ };
84
+ protected _contentRect: {
85
+ x: number;
86
+ y: number;
87
+ width: number;
88
+ height: number;
89
+ };
90
+ protected _resizeObserver: ResizeObserver;
91
+ protected _onScroll(): void;
92
+ protected _onSlotChange(e: Event): void;
93
+ getViewRect(): Readonly<{
94
+ x: number;
95
+ y: number;
96
+ width: number;
97
+ height: number;
98
+ }>;
99
+ scrollToContent(x: number, y: number, options?: ScrollOptions): void;
100
+ centerOnContent(x: number, y: number, options?: ScrollOptions): void;
101
+ clientToContent(clientX: number, clientY: number): Readonly<{
102
+ x: number;
103
+ y: number;
104
+ }>;
105
+ contentToClient(x: number, y: number): Readonly<{
106
+ x: number;
107
+ y: number;
108
+ }>;
109
+ requestRender(reason?: RCVirtualCanvasRenderReason): void;
110
+ protected _onPointerEvent(event: PointerEvent | MouseEvent): void;
111
+ private _isOverlayEvent;
112
+ protected _update(time: DOMHighResTimeStamp): void;
113
+ connectedCallback(): void;
114
+ disconnectedCallback(): void;
115
+ protected updated(changed: Map<string, unknown>): void;
116
+ private _scheduleRender;
117
+ private _syncCanvasBackingStore;
118
+ private _getCanvasClientRect;
119
+ private _getMeasuredCanvasWidth;
120
+ private _getMeasuredCanvasHeight;
121
+ private _getViewportScaleX;
122
+ private _getViewportScaleY;
123
+ render(): import('lit').TemplateResult<1>;
124
+ }
125
+ export default RCVirtualCanvas;
@@ -0,0 +1,2 @@
1
+ export declare const virtualCanvasStyles: import('lit').CSSResult;
2
+ export default virtualCanvasStyles;
File without changes