@sci-grid/core 1.0.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/dist/index.js ADDED
@@ -0,0 +1,894 @@
1
+ var L = Object.defineProperty;
2
+ var $ = (m, t, e) => t in m ? L(m, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : m[t] = e;
3
+ var p = (m, t, e) => $(m, typeof t != "symbol" ? t + "" : t, e);
4
+ class D {
5
+ constructor(t) {
6
+ p(this, "canvas");
7
+ p(this, "ctx");
8
+ p(this, "dpr");
9
+ this.canvas = t;
10
+ const e = t.getContext("2d", { alpha: !1 });
11
+ if (!e) throw new Error("Could not get 2d context");
12
+ this.ctx = e, this.dpr = window.devicePixelRatio || 1;
13
+ }
14
+ resize(t, e) {
15
+ this.canvas.width = t * this.dpr, this.canvas.height = e * this.dpr, this.canvas.style.width = `${t}px`, this.canvas.style.height = `${e}px`, this.ctx.scale(this.dpr, this.dpr);
16
+ }
17
+ render(t, e, s) {
18
+ const { ctx: i } = this, { width: r, height: n, scrollX: o, scrollY: l, selectedRows: h, selectionMode: a, headerHeight: u } = t;
19
+ i.fillStyle = e.backgroundColor, i.fillRect(0, 0, r, n);
20
+ const c = e.showRowNumbers ? e.rowNumbersWidth : 0, g = Math.max(0, Math.floor(l / e.rowHeight)), d = Math.min(
21
+ s.getRowCount() - 1,
22
+ Math.ceil((l + n) / e.rowHeight)
23
+ ), C = [], f = t.columnOffsets;
24
+ let v = 0, y = f.length - 2, S = 0;
25
+ for (; v <= y; ) {
26
+ const w = v + y >> 1;
27
+ f[w + 1] > o ? (S = w, y = w - 1) : v = w + 1;
28
+ }
29
+ for (let w = S; w < s.getColumnCount(); w++) {
30
+ const b = t.columnOrder[w] ?? w, x = t.columnWidths[b] ?? e.columnWidth, R = c - o + f[w];
31
+ if (R < r)
32
+ C.push({ index: b, x: R, width: x });
33
+ else
34
+ break;
35
+ }
36
+ i.font = e.font, i.textBaseline = "middle", i.save(), i.beginPath(), i.rect(c, u, r - c, n - u), i.clip();
37
+ for (let w = g; w <= d; w++) {
38
+ const b = Math.floor(w * e.rowHeight - l + u);
39
+ e.alternateRowColor && w % 2 === 1 && (i.fillStyle = e.alternateRowColor, i.fillRect(c, b, r - c, e.rowHeight));
40
+ for (const x of C) {
41
+ const { index: R, x: H, width: O } = x, W = t.reorderingCol !== null && t.columnOrder[t.reorderingCol] === R;
42
+ W && (i.globalAlpha = 0.2);
43
+ let E = !1;
44
+ if (a === "all")
45
+ E = !0;
46
+ else
47
+ for (const T of t.selectionRanges)
48
+ if (w >= T.startRow && w <= T.endRow && R >= T.startCol && R <= T.endCol) {
49
+ E = !0;
50
+ break;
51
+ }
52
+ E && (i.fillStyle = e.selectionColor, i.fillRect(H, b, O, e.rowHeight));
53
+ const z = s.getCellData(w, R), A = s.getHeader(R);
54
+ this.drawCellContent(i, z, A, H, b, O, e.rowHeight, e, E && a === "cell"), i.strokeStyle = e.gridLineColor, i.lineWidth = 1, i.strokeRect(H, b, O, e.rowHeight), W && (i.globalAlpha = 1);
55
+ }
56
+ }
57
+ if (i.restore(), e.showRowNumbers) {
58
+ i.fillStyle = e.rowNumberBackground, i.fillRect(0, u, c, n), i.fillStyle = e.rowNumberTextColor, i.strokeStyle = e.gridLineColor, i.textAlign = "left";
59
+ for (let w = g; w <= d; w++) {
60
+ const b = Math.floor(w * e.rowHeight - l + u);
61
+ h.has(w) && (a === "row" || a === "cell") && (i.fillStyle = e.selectionColor, i.fillRect(0, b, c, e.rowHeight)), i.strokeRect(0, b, c, e.rowHeight), i.fillStyle = e.rowNumberTextColor, i.fillText((w + 1).toString(), e.cellPadding, b + e.rowHeight / 2);
62
+ }
63
+ }
64
+ this.renderHeader(t, e, s, c), e.showRowNumbers && (i.fillStyle = e.headerBackground, i.fillRect(0, 0, c, u), i.strokeStyle = e.gridLineColor, i.strokeRect(0, 0, c, u)), this.renderReorderingOverlay(t, e, s, c);
65
+ }
66
+ renderHeader(t, e, s, i) {
67
+ const { width: r, headerHeight: n, scrollX: o, columnOrder: l, reorderingCol: h } = t, a = this.ctx;
68
+ a.save(), a.beginPath(), a.rect(i, 0, r - i, n), a.clip(), a.fillStyle = e.headerBackground, a.fillRect(i, 0, r - i, n);
69
+ const u = t.columnOffsets;
70
+ let c = 0, g = u.length - 2, d = 0;
71
+ for (; c <= g; ) {
72
+ const f = c + g >> 1;
73
+ u[f + 1] > o ? (d = f, g = f - 1) : c = f + 1;
74
+ }
75
+ const C = s.getColumnCount();
76
+ for (let f = d; f < C; f++) {
77
+ const v = l[f] ?? f, y = t.columnWidths[v] ?? e.columnWidth, S = i - o + u[f];
78
+ if (S < r) {
79
+ const w = s.getHeader(v), b = h === f;
80
+ b && (a.globalAlpha = 0.2), a.strokeStyle = e.gridLineColor, a.strokeRect(S, 0, y, n), this.drawHeaderContent(w, S, 0, y, n, e), b && (a.globalAlpha = 1);
81
+ } else
82
+ break;
83
+ }
84
+ a.restore();
85
+ }
86
+ drawHeaderContent(t, e, s, i, r, n) {
87
+ var g;
88
+ const o = this.ctx, l = n.headerSubTextCount;
89
+ let h = r, a = 0;
90
+ if (l === 1 ? (h = r * 0.75, a = r * 0.25) : l === 2 && (h = r * 0.5, a = r * 0.25), o.save(), o.beginPath(), o.rect(e, s, i, r), o.clip(), l > 0 && (o.strokeStyle = n.headerDividerColor || n.gridLineColor, o.lineWidth = 1, o.globalAlpha = n.headerDividerAlpha ?? 0.2, o.beginPath(), o.moveTo(e, s + h), o.lineTo(e + i, s + h), o.stroke(), l === 2 && (o.beginPath(), o.moveTo(e, s + h + a), o.lineTo(e + i, s + h + a), o.stroke()), o.globalAlpha = 1), t.markIcon && (o.fillStyle = ((g = n.headerTitleStyle) == null ? void 0 : g.color) || n.headerTextColor, o.font = "bold 14px sans-serif", o.textAlign = "right", o.textBaseline = "top", o.fillText(t.markIcon, e + i - 5, s + 4)), t.sortOrder) {
91
+ o.fillStyle = n.headerTextColor, o.font = "10px sans-serif", o.textAlign = "right", o.textBaseline = "middle";
92
+ const d = t.sortOrder === "asc" ? "▲" : "▼";
93
+ o.fillText(d, e + i - (t.markIcon ? 20 : 8), s + (l === 0 ? r / 2 : h / 2));
94
+ }
95
+ const u = n.cellPadding;
96
+ o.textAlign = "left", o.textBaseline = "middle";
97
+ const c = n.headerTitleStyle;
98
+ if (o.font = (c == null ? void 0 : c.font) || n.headerFont, o.fillStyle = (c == null ? void 0 : c.color) || n.headerTextColor, o.globalAlpha = (c == null ? void 0 : c.alpha) ?? 1, o.fillText(t.name || "", e + u, s + h / 2), l >= 1) {
99
+ const d = n.headerUnitsStyle;
100
+ o.font = (d == null ? void 0 : d.font) || `italic ${Math.max(6, Math.floor(r / 6))}px Inter, sans-serif`, o.fillStyle = (d == null ? void 0 : d.color) || n.headerTextColor, o.globalAlpha = (d == null ? void 0 : d.alpha) ?? 0.6;
101
+ const C = t.units || n.headerPlaceholder;
102
+ o.fillText(C, e + u, s + h + a / 2);
103
+ }
104
+ if (l === 2) {
105
+ const d = n.headerDescriptionStyle;
106
+ o.font = (d == null ? void 0 : d.font) || `italic ${Math.max(6, Math.floor(r / 8))}px Inter, sans-serif`, o.fillStyle = (d == null ? void 0 : d.color) || n.headerTextColor, o.globalAlpha = (d == null ? void 0 : d.alpha) ?? 0.6;
107
+ const C = t.description || n.headerPlaceholder;
108
+ o.fillText(C, e + u, s + h + a + a / 2);
109
+ }
110
+ o.restore();
111
+ }
112
+ renderReorderingOverlay(t, e, s, i) {
113
+ const { ctx: r } = this, { height: n, headerHeight: o, scrollX: l, scrollY: h } = t;
114
+ if (t.reorderingTarget !== null) {
115
+ let a = i - l;
116
+ for (let d = 0; d < t.reorderingTarget; d++) {
117
+ const C = t.columnOrder[d];
118
+ C !== void 0 ? a += t.columnWidths[C] ?? e.columnWidth : a += e.columnWidth;
119
+ }
120
+ const u = s.getRowCount() * e.rowHeight + o - h, c = Math.min(n, Math.max(o, u)), g = e.dragHandleColor || "#4facfe";
121
+ r.save(), r.strokeStyle = g, r.lineWidth = 4, r.beginPath(), r.moveTo(a, 0), r.lineTo(a, c), r.stroke(), r.restore();
122
+ }
123
+ if (t.reorderingCol !== null && t.reorderingX !== null) {
124
+ const a = t.columnOrder[t.reorderingCol] ?? t.reorderingCol, u = t.columnWidths[a] ?? e.columnWidth, c = t.reorderingX - u / 2;
125
+ r.save(), r.globalAlpha = 0.6, r.fillStyle = e.headerBackground, r.fillRect(c, 0, u, o), r.strokeStyle = "#4facfe", r.strokeRect(c, 0, u, o);
126
+ const g = s.getHeader(a);
127
+ this.drawHeaderContent(g, c, 0, u, o, e);
128
+ const d = Math.max(0, Math.floor(h / e.rowHeight)), C = Math.min(
129
+ s.getRowCount() - 1,
130
+ Math.ceil((h + n) / e.rowHeight)
131
+ );
132
+ r.fillStyle = "rgba(18, 18, 20, 0.8)", r.fillRect(c, o, u, n - o);
133
+ for (let f = d; f <= C; f++) {
134
+ const v = Math.floor(f * e.rowHeight - h + o), y = s.getCellData(f, a);
135
+ y != null && (r.fillStyle = e.textColor, r.font = e.font, r.fillText(y.toString(), c + e.cellPadding, v + e.rowHeight / 2)), r.strokeStyle = "rgba(79, 172, 254, 0.3)", r.strokeRect(c, v, u, e.rowHeight);
136
+ }
137
+ r.restore();
138
+ }
139
+ }
140
+ drawCellContent(t, e, s, i, r, n, o, l, h) {
141
+ const a = s.type || "text", u = l.cellPadding, c = h ? l.selectedTextColor : l.textColor;
142
+ if (a === "checkbox") {
143
+ const d = i + (n - 14) / 2, C = r + (o - 14) / 2, f = !!e;
144
+ t.beginPath(), t.rect(d, C, 14, 14), t.strokeStyle = "#999", t.stroke(), f && (t.fillStyle = "#4facfe", t.fillRect(d + 2, C + 2, 10, 10));
145
+ return;
146
+ }
147
+ if (a === "progress") {
148
+ const g = typeof e == "number" ? Math.min(100, Math.max(0, e)) : 0, d = o * 0.6, C = r + (o - d) / 2, f = n - u * 2, v = i + u;
149
+ t.fillStyle = l.alternateRowColor || "#e0e0e033", t.fillRect(v, C, f, d), t.fillStyle = "#4facfe", t.fillRect(v, C, f * (g / 100), d), t.fillStyle = c, t.font = "10px sans-serif", t.textAlign = "center", t.fillText(`${g}%`, i + n / 2, r + o / 2);
150
+ return;
151
+ }
152
+ if (a === "sparkline" && Array.isArray(e)) {
153
+ const g = e;
154
+ if (g.length > 1) {
155
+ const d = n - u * 2, C = o * 0.6, f = i + u, v = r + (o - C) / 2, y = Math.min(...g), w = Math.max(...g) - y || 1;
156
+ t.save(), t.beginPath(), t.strokeStyle = "#4facfe", t.lineWidth = 1.5, g.forEach((b, x) => {
157
+ const R = f + x / (g.length - 1) * d, H = v + C - (b - y) / w * C;
158
+ x === 0 ? t.moveTo(R, H) : t.lineTo(R, H);
159
+ }), t.stroke(), t.restore();
160
+ }
161
+ return;
162
+ }
163
+ if (e != null) {
164
+ t.fillStyle = c, t.textAlign = a === "numeric" ? "right" : "left", t.font = l.font;
165
+ const g = e.toString(), d = a === "numeric" ? i + n - u : i + u;
166
+ t.fillText(g, d, r + o / 2);
167
+ }
168
+ if (a === "select") {
169
+ t.fillStyle = c, t.globalAlpha = 0.5, t.beginPath();
170
+ const g = i + n - 15, d = r + o / 2 - 2;
171
+ t.moveTo(g, d), t.lineTo(g + 8, d), t.lineTo(g + 4, d + 5), t.fill(), t.globalAlpha = 1;
172
+ }
173
+ }
174
+ }
175
+ class N {
176
+ constructor(t, e, s, i) {
177
+ p(this, "container");
178
+ p(this, "shadow");
179
+ p(this, "onScroll");
180
+ p(this, "onMouseDown");
181
+ p(this, "onDoubleClick");
182
+ p(this, "styleId", "scigrid-scroll-style-" + Math.random().toString(36).substr(2, 9));
183
+ p(this, "MAX_BROWSER_SIZE", 15e6);
184
+ p(this, "scaleX", 1);
185
+ p(this, "scaleY", 1);
186
+ this.container = t, this.onScroll = e, this.onMouseDown = s, this.onDoubleClick = i, this.shadow = document.createElement("div"), this.shadow.style.position = "absolute", this.shadow.style.top = "0", this.shadow.style.left = "0", this.shadow.style.width = "1px", this.shadow.style.height = "1px", this.shadow.style.pointerEvents = "none", this.container.style.overflow = "auto", this.container.style.position = "relative", this.container.appendChild(this.shadow), this.setupEvents(), this.injectScrollStyle();
187
+ }
188
+ injectScrollStyle() {
189
+ this.container.classList.add(this.styleId);
190
+ const t = document.createElement("style");
191
+ t.id = this.styleId, t.innerHTML = `
192
+ .${this.styleId} {
193
+ scrollbar-width: thin;
194
+ scrollbar-color: rgba(155, 155, 155, 0.5) transparent;
195
+ }
196
+ .${this.styleId}::-webkit-scrollbar {
197
+ width: 10px;
198
+ height: 10px;
199
+ }
200
+ .${this.styleId}::-webkit-scrollbar-track {
201
+ background: transparent;
202
+ }
203
+ .${this.styleId}::-webkit-scrollbar-thumb {
204
+ background-color: rgba(155, 155, 155, 0.5);
205
+ border-radius: 6px;
206
+ border: 2px solid transparent;
207
+ background-clip: content-box;
208
+ }
209
+ .${this.styleId}::-webkit-scrollbar-thumb:hover {
210
+ background-color: rgba(155, 155, 155, 0.8);
211
+ }
212
+ .${this.styleId}::-webkit-scrollbar-corner {
213
+ background: transparent;
214
+ }
215
+ `, document.head.appendChild(t);
216
+ }
217
+ updateScrollStyle(t, e) {
218
+ const s = document.getElementById(this.styleId);
219
+ if (s && (t || e)) {
220
+ const i = t || "rgba(155, 155, 155, 0.5)", r = e || "transparent";
221
+ s.innerHTML = `
222
+ .${this.styleId} {
223
+ scrollbar-width: thin;
224
+ scrollbar-color: ${i} ${r};
225
+ }
226
+ .${this.styleId}::-webkit-scrollbar {
227
+ width: 10px;
228
+ height: 10px;
229
+ }
230
+ .${this.styleId}::-webkit-scrollbar-track {
231
+ background: ${r};
232
+ }
233
+ .${this.styleId}::-webkit-scrollbar-thumb {
234
+ background-color: ${i};
235
+ border-radius: 6px;
236
+ border: 2px solid ${r === "transparent" ? "transparent" : r};
237
+ background-clip: content-box;
238
+ }
239
+ .${this.styleId}::-webkit-scrollbar-thumb:hover {
240
+ opacity: 0.8;
241
+ }
242
+ .${this.styleId}::-webkit-scrollbar-corner {
243
+ background: ${r};
244
+ }
245
+ `;
246
+ }
247
+ }
248
+ updateVirtualSize(t, e) {
249
+ const s = this.container.clientWidth || 100, i = this.container.clientHeight || 100, r = Math.min(t, this.MAX_BROWSER_SIZE), n = Math.min(e, this.MAX_BROWSER_SIZE);
250
+ this.scaleX = (t - s) / Math.max(1, r - s), this.scaleY = (e - i) / Math.max(1, n - i), this.shadow.style.width = `${r}px`, this.shadow.style.height = `${n}px`;
251
+ }
252
+ setScroll(t, e) {
253
+ this.container.scrollLeft = t / (this.scaleX || 1), this.container.scrollTop = e / (this.scaleY || 1);
254
+ }
255
+ scrollToCell(t, e, s, i) {
256
+ const r = this.container.scrollLeft * this.scaleX, n = this.container.scrollTop * this.scaleY, o = this.container.clientWidth, l = this.container.clientHeight;
257
+ let h = r, a = n;
258
+ t < r ? h = t : t + s > r + o && (h = t + s - o), e < n ? a = e : e + i > n + l && (a = e + i - l), (h !== r || a !== n) && this.setScroll(h, a);
259
+ }
260
+ setupEvents() {
261
+ let t = 0, e = 0;
262
+ this.container.addEventListener("scroll", () => {
263
+ const s = Math.round(this.container.scrollLeft * this.scaleX), i = Math.round(this.container.scrollTop * this.scaleY);
264
+ (s !== t || i !== e) && (t = s, e = i, this.onScroll({
265
+ scrollX: s,
266
+ scrollY: i
267
+ }));
268
+ }, { passive: !0 }), this.container.addEventListener("mousedown", (s) => {
269
+ this.onMouseDown(s);
270
+ }), this.container.addEventListener("dblclick", (s) => {
271
+ this.onDoubleClick(s);
272
+ });
273
+ }
274
+ }
275
+ class P {
276
+ constructor(t, e, s, i) {
277
+ this.state = t, this.provider = e, this.config = s, this.invalidate = i;
278
+ }
279
+ updateSelection(t, e, s, i, r) {
280
+ if (this.state.selectionMode = t, t === "all") {
281
+ this.state.selectionRanges = [{
282
+ startRow: 0,
283
+ endRow: this.provider.getRowCount() - 1,
284
+ startCol: 0,
285
+ endCol: this.provider.getColumnCount() - 1
286
+ }], this.state.anchorRow = 0, this.state.anchorCol = 0, this.populateLookupSets(), this.invalidate(), this.notifySelectionChange();
287
+ return;
288
+ }
289
+ if (e === null && t !== "column" || s === null && t !== "row") return;
290
+ const n = e ?? 0, o = s ?? 0;
291
+ !i && !r && (this.state.selectionRanges = []), r && this.state.anchorRow !== null && this.state.anchorCol !== null ? this.handleRangeSelection(t, n, o, i) : this.handlePivotSelection(t, n, o, i), this.populateLookupSets(), this.notifySelectionChange();
292
+ }
293
+ handleRangeSelection(t, e, s, i) {
294
+ const r = t === "column" ? 0 : Math.min(e, this.state.anchorRow), n = t === "column" ? this.provider.getRowCount() - 1 : Math.max(e, this.state.anchorRow), o = t === "row" ? 0 : Math.min(s, this.state.anchorCol), l = t === "row" ? this.provider.getColumnCount() - 1 : Math.max(s, this.state.anchorCol), h = { startRow: r, endRow: n, startCol: o, endCol: l };
295
+ i ? this.state.selectionRanges.length > 0 ? this.state.selectionRanges[this.state.selectionRanges.length - 1] = h : this.state.selectionRanges.push(h) : this.state.selectionRanges = [h];
296
+ }
297
+ handlePivotSelection(t, e, s, i) {
298
+ const r = {
299
+ startRow: t === "column" ? 0 : e,
300
+ endRow: t === "column" ? this.provider.getRowCount() - 1 : e,
301
+ startCol: t === "row" ? 0 : s,
302
+ endCol: t === "row" ? this.provider.getColumnCount() - 1 : s
303
+ };
304
+ if (i) {
305
+ const n = this.state.selectionRanges.findIndex(
306
+ (o) => o.startRow === r.startRow && o.endRow === r.endRow && o.startCol === r.startCol && o.endCol === r.endCol
307
+ );
308
+ n !== -1 ? this.state.selectionRanges.splice(n, 1) : this.state.selectionRanges.push(r);
309
+ } else
310
+ this.state.selectionRanges = [r];
311
+ this.state.anchorRow = e, this.state.anchorCol = s;
312
+ }
313
+ populateLookupSets() {
314
+ this.state.selectedRows.clear(), this.state.selectedCols.clear();
315
+ for (const t of this.state.selectionRanges) {
316
+ for (let e = t.startRow; e <= t.endRow; e++) this.state.selectedRows.add(e);
317
+ for (let e = t.startCol; e <= t.endCol; e++) this.state.selectedCols.add(e);
318
+ }
319
+ }
320
+ notifySelectionChange() {
321
+ this.config.onSelectionChange && this.config.onSelectionChange({
322
+ mode: this.state.selectionMode,
323
+ ranges: [...this.state.selectionRanges],
324
+ anchorRow: this.state.anchorRow,
325
+ anchorCol: this.state.anchorCol
326
+ });
327
+ }
328
+ }
329
+ class Y {
330
+ constructor(t, e, s, i) {
331
+ this.state = t, this.provider = e, this.config = s, this.actions = i;
332
+ }
333
+ handleKeyDown(t, e) {
334
+ if (e) return;
335
+ let s = this.state.anchorRow ?? 0, i = this.state.anchorCol ?? 0;
336
+ const r = this.provider.getRowCount(), n = this.provider.getColumnCount();
337
+ let o = this.state.columnOrder.indexOf(i);
338
+ switch (o === -1 && (o = i), t.key) {
339
+ case "ArrowUp":
340
+ s = Math.max(0, s - 1);
341
+ break;
342
+ case "ArrowDown":
343
+ s = Math.min(r - 1, s + 1);
344
+ break;
345
+ case "ArrowLeft":
346
+ o = Math.max(0, o - 1);
347
+ break;
348
+ case "ArrowRight":
349
+ o = Math.min(n - 1, o + 1);
350
+ break;
351
+ case "PageUp":
352
+ s = Math.max(0, s - Math.floor(this.state.height / this.config.rowHeight));
353
+ break;
354
+ case "PageDown":
355
+ s = Math.min(r - 1, s + Math.floor(this.state.height / this.config.rowHeight));
356
+ break;
357
+ case "Home":
358
+ o = 0, t.ctrlKey && (s = 0);
359
+ break;
360
+ case "End":
361
+ o = n - 1, t.ctrlKey && (s = r - 1);
362
+ break;
363
+ case "c":
364
+ if (t.ctrlKey || t.metaKey) {
365
+ this.actions.copyToClipboard();
366
+ return;
367
+ }
368
+ return;
369
+ default:
370
+ return;
371
+ }
372
+ i = this.state.columnOrder[o] ?? o, t.preventDefault(), this.actions.updateSelection("cell", s, i, t.ctrlKey, t.shiftKey), this.actions.scrollToCell(s, i), this.actions.render();
373
+ }
374
+ }
375
+ const I = {
376
+ Y: 1e24,
377
+ Z: 1e21,
378
+ E: 1e18,
379
+ P: 1e15,
380
+ T: 1e12,
381
+ G: 1e9,
382
+ M: 1e6,
383
+ k: 1e3,
384
+ h: 100,
385
+ da: 10,
386
+ d: 0.1,
387
+ c: 0.01,
388
+ m: 1e-3,
389
+ u: 1e-6,
390
+ μ: 1e-6,
391
+ n: 1e-9,
392
+ p: 1e-12,
393
+ f: 1e-15,
394
+ a: 1e-18,
395
+ z: 1e-21,
396
+ y: 1e-24
397
+ };
398
+ function B(m) {
399
+ if (typeof m != "string") return parseFloat(m);
400
+ const t = m.trim();
401
+ if (!t) return NaN;
402
+ const e = /^([+-]?\d*\.?\d+(?:[eE][+-]?\d+)?)\s*([YZEPTGMkhdacmuμnpfaz y]?)([a-zA-Z]*)$/, s = t.match(e);
403
+ if (!s) return parseFloat(t);
404
+ const [i, r, n] = s;
405
+ let o = parseFloat(r);
406
+ return n && I[n] && (o *= I[n]), o;
407
+ }
408
+ class K {
409
+ constructor(t, e, s, i, r) {
410
+ p(this, "editor", null);
411
+ this.uiLayer = t, this.provider = e, this.config = s, this.state = i, this.helpers = r;
412
+ }
413
+ get activeEditor() {
414
+ return this.editor;
415
+ }
416
+ closeEditor() {
417
+ if (this.editor) {
418
+ const t = this.editor;
419
+ this.editor = null, t.remove();
420
+ }
421
+ }
422
+ openHeaderEditor(t, e) {
423
+ const s = this.provider.getHeader(t), i = e === 0 ? s.name || "" : e === 1 ? s.units || "" : s.description || "", r = this.state.columnOrder.indexOf(t), n = r === -1 ? t : r, o = this.helpers.getColumnOffset(n) - this.state.scrollX + (this.config.showRowNumbers ? this.config.rowNumbersWidth : 0), { titleH: l, subH: h } = this.getHeaderHeights(), a = e === 0 ? 0 : e === 1 ? l : l + h, u = e === 0 ? l : h, c = document.createElement("input");
424
+ this.editor = c, c.type = "text", c.value = i, Object.assign(c.style, {
425
+ position: "absolute",
426
+ left: `${o}px`,
427
+ top: `${a}px`,
428
+ width: `${this.helpers.getColumnWidth(t)}px`,
429
+ height: `${u}px`,
430
+ boxSizing: "border-box",
431
+ border: "2px solid #4facfe",
432
+ outline: "none",
433
+ zIndex: "100",
434
+ pointerEvents: "auto",
435
+ backgroundColor: this.config.headerBackground,
436
+ padding: `0 ${this.config.cellPadding}px`
437
+ });
438
+ const g = () => {
439
+ var C, f;
440
+ if (!this.editor) return;
441
+ const d = { ...s };
442
+ e === 0 ? d.name = c.value : e === 1 ? d.units = c.value : d.description = c.value, (f = (C = this.provider).setHeader) == null || f.call(C, t, d), this.closeEditor(), this.helpers.invalidate();
443
+ };
444
+ c.onblur = g, c.onkeydown = (d) => {
445
+ d.key === "Enter" && g(), d.key === "Escape" && this.closeEditor();
446
+ }, this.uiLayer.appendChild(c), setTimeout(() => {
447
+ this.editor === c && (c.focus(), c.select());
448
+ }, 0);
449
+ }
450
+ getHeaderHeights() {
451
+ const t = this.state.headerHeight;
452
+ return this.config.headerSubTextCount === 1 ? { titleH: t * 0.75, subH: t * 0.25 } : this.config.headerSubTextCount === 2 ? { titleH: t * 0.5, subH: t * 0.25 } : { titleH: t, subH: 0 };
453
+ }
454
+ openCellEditor(t, e) {
455
+ if (!this.provider.setCellData) return;
456
+ const s = this.state.columnOrder.indexOf(e), i = s === -1 ? e : s, r = this.helpers.getColumnOffset(i) - this.state.scrollX + (this.config.showRowNumbers ? this.config.rowNumbersWidth : 0), n = t * this.config.rowHeight - this.state.scrollY + this.state.headerHeight;
457
+ this.provider.getHeader(e).type === "select" ? this.renderSelectEditor(t, e, r, n) : this.renderTextEditor(t, e, r, n);
458
+ }
459
+ renderTextEditor(t, e, s, i) {
460
+ var o;
461
+ const r = document.createElement("input");
462
+ this.editor = r, r.value = ((o = this.provider.getCellData(t, e)) == null ? void 0 : o.toString()) || "", Object.assign(r.style, {
463
+ position: "absolute",
464
+ left: `${s}px`,
465
+ top: `${i}px`,
466
+ zIndex: "10",
467
+ width: `${this.helpers.getColumnWidth(e)}px`,
468
+ height: `${this.config.rowHeight}px`,
469
+ boxSizing: "border-box",
470
+ border: "2px solid #4facfe",
471
+ outline: "none",
472
+ padding: `${this.config.cellPadding}px`,
473
+ pointerEvents: "auto"
474
+ });
475
+ const n = () => {
476
+ if (this.editor) {
477
+ let l = r.value;
478
+ if (this.provider.getHeader(e).type === "numeric") {
479
+ const a = B(r.value);
480
+ isNaN(a) || (l = a);
481
+ }
482
+ this.provider.setCellData(t, e, l), this.closeEditor(), this.helpers.invalidate();
483
+ }
484
+ };
485
+ r.onkeydown = (l) => {
486
+ l.key === "Enter" && n(), l.key === "Escape" && this.closeEditor();
487
+ }, r.onblur = n, this.uiLayer.appendChild(r), setTimeout(() => {
488
+ r.focus(), r.select();
489
+ }, 0);
490
+ }
491
+ renderSelectEditor(t, e, s, i) {
492
+ var l;
493
+ const r = document.createElement("div");
494
+ this.editor = r;
495
+ const n = ((l = this.provider.getCellData(t, e)) == null ? void 0 : l.toString()) || "";
496
+ r.setAttribute("data-value", n), Object.assign(r.style, {
497
+ position: "absolute",
498
+ left: `${s}px`,
499
+ top: `${i}px`,
500
+ zIndex: "1000",
501
+ width: `${this.helpers.getColumnWidth(e)}px`,
502
+ height: `${this.config.rowHeight}px`,
503
+ pointerEvents: "auto"
504
+ });
505
+ const o = document.createElement("ul");
506
+ Object.assign(o.style, {
507
+ position: "absolute",
508
+ top: "100%",
509
+ left: "0",
510
+ width: "100%",
511
+ maxHeight: "200px",
512
+ overflowY: "auto",
513
+ margin: "0",
514
+ padding: "0",
515
+ listStyle: "none",
516
+ backgroundColor: this.config.headerBackground,
517
+ border: `1px solid ${this.config.gridLineColor}`
518
+ }), (this.provider.getHeader(e).selectOptions || []).forEach((h) => {
519
+ const a = document.createElement("li");
520
+ a.textContent = h, a.style.padding = "6px 10px", a.style.cursor = "pointer", a.onclick = (u) => {
521
+ u.stopPropagation(), this.provider.setCellData(t, e, h), this.closeEditor(), this.helpers.invalidate();
522
+ }, o.appendChild(a);
523
+ }), r.appendChild(o), this.uiLayer.appendChild(r), r.tabIndex = 0, r.onkeydown = (h) => {
524
+ h.key === "Escape" && this.closeEditor();
525
+ }, setTimeout(() => r.focus(), 0);
526
+ }
527
+ }
528
+ function k(m, t, e) {
529
+ return e === -1 ? t.rowNumbersWidth : m.columnWidths[e] ?? t.columnWidth;
530
+ }
531
+ function X(m, t) {
532
+ return m.columnOffsets[t] ?? m.columnOffsets[m.columnOffsets.length - 1] ?? 0;
533
+ }
534
+ function M(m, t) {
535
+ const e = m.columnOffsets;
536
+ if (!e || e.length === 0) return -1;
537
+ let s = 0, i = e.length - 2;
538
+ for (; s <= i; ) {
539
+ const n = s + i >> 1, o = e[n], l = e[n + 1];
540
+ if (t >= o && t < l) return n;
541
+ t < o ? i = n - 1 : s = n + 1;
542
+ }
543
+ const r = e[e.length - 1] || 0;
544
+ return t >= r ? Math.max(0, e.length - 2) : -1;
545
+ }
546
+ class _ {
547
+ constructor(t, e, s, i, r) {
548
+ this.canvas = t, this.state = e, this.provider = s, this.config = i, this.actions = r;
549
+ }
550
+ handleHit(t, e) {
551
+ this.actions.closeEditor();
552
+ const s = this.canvas.getBoundingClientRect(), i = t.clientX - s.left, r = t.clientY - s.top, n = this.config.showRowNumbers ? this.config.rowNumbersWidth : 0, o = t.ctrlKey || t.metaKey, l = t.shiftKey;
553
+ if (this.config.showRowNumbers && Math.abs(i - n) < 5) {
554
+ t.preventDefault(), this.actions.startResizing(-1, t);
555
+ return;
556
+ }
557
+ if (i < n && r < this.state.headerHeight)
558
+ this.actions.updateSelection("all", null, null, !1, !1);
559
+ else if (r < this.state.headerHeight && i >= n)
560
+ this.handleHeaderHit(i - n + this.state.scrollX, r, e, o, l, t);
561
+ else if (i < n && r >= this.state.headerHeight) {
562
+ const h = Math.floor((r - this.state.headerHeight + this.state.scrollY) / this.config.rowHeight);
563
+ h >= 0 && h < this.provider.getRowCount() && this.actions.updateSelection("row", h, null, o, l);
564
+ } else
565
+ this.handleCellHit(i, r, n, e, o, l);
566
+ this.actions.render();
567
+ }
568
+ handleHeaderHit(t, e, s, i, r, n) {
569
+ const o = this.getHeaderHit(t, e);
570
+ if (o.colIndex === -1) return;
571
+ const l = this.state.columnOrder[o.colIndex] ?? o.colIndex, h = this.provider.getHeader(l);
572
+ o.type === "edge" && h.isResizable !== !1 && this.config.allowResizing ? (n.preventDefault(), this.actions.startResizing(l, n)) : o.type === "handle" && (s ? (n.preventDefault(), this.actions.openHeaderEditor(l, o.subIndex || 0)) : (this.actions.updateSelection("column", null, l, i, r), n.preventDefault(), this.actions.startReordering(o.colIndex, n)));
573
+ }
574
+ handleCellHit(t, e, s, i, r, n) {
575
+ const o = Math.floor((e - this.state.headerHeight + this.state.scrollY) / this.config.rowHeight), l = t - s + this.state.scrollX, h = M(this.state, l), a = this.state.columnOrder[h] ?? h;
576
+ if (o < 0 || o >= this.provider.getRowCount() || h === -1) return;
577
+ const u = this.provider.getHeader(a);
578
+ if (u.type === "checkbox" && !i && this.provider.setCellData && (this.provider.setCellData(o, a, !this.provider.getCellData(o, a)), this.actions.invalidate()), n)
579
+ this.actions.updateSelection("cell", o, a, r, n);
580
+ else if (i)
581
+ u.type !== "progress" && u.type !== "checkbox" && this.actions.openEditor(o, a);
582
+ else {
583
+ this.actions.setSelecting(!0), this.actions.updateSelection("cell", o, a, r, n);
584
+ const c = () => {
585
+ this.actions.setSelecting(!1), window.removeEventListener("mouseup", c);
586
+ };
587
+ window.addEventListener("mouseup", c);
588
+ }
589
+ }
590
+ getHeaderHit(t, e) {
591
+ let s = 0;
592
+ const i = this.state.headerHeight, { titleH: r, subH: n } = this.getHeaderHeights(i);
593
+ for (let o = 0; o < this.state.columnOrder.length; o++) {
594
+ const l = k(this.state, this.config, this.state.columnOrder[o]);
595
+ if (t >= s && t <= s + l) {
596
+ if (t >= s + l - 5) return { type: "edge", colIndex: o };
597
+ if (o > 0 && t <= s + 5) return { type: "edge", colIndex: o - 1 };
598
+ let h = 0;
599
+ return e > r && (h = e < r + n ? 1 : 2), { type: "handle", colIndex: o, subIndex: h };
600
+ }
601
+ s += l;
602
+ }
603
+ return { type: "handle", colIndex: -1 };
604
+ }
605
+ getHeaderHeights(t) {
606
+ return this.config.headerSubTextCount === 1 ? { titleH: t * 0.75, subH: t * 0.25 } : this.config.headerSubTextCount === 2 ? { titleH: t * 0.5, subH: t * 0.25 } : { titleH: t, subH: 0 };
607
+ }
608
+ }
609
+ class j {
610
+ constructor(t, e, s, i, r) {
611
+ this.canvas = t, this.state = e, this.provider = s, this.config = i, this.actions = r;
612
+ }
613
+ startResizing(t, e) {
614
+ this.state.resizingCol = t;
615
+ const s = e.clientX, i = k(this.state, this.config, t), r = (o) => {
616
+ const l = Math.max(30, i + (o.clientX - s));
617
+ t === -1 ? this.config.rowNumbersWidth = l : this.state.columnWidths[t] = l, this.actions.updateVirtualSize(), this.actions.invalidate();
618
+ }, n = () => {
619
+ this.state.resizingCol = null, window.removeEventListener("mousemove", r), window.removeEventListener("mouseup", n), this.actions.saveState();
620
+ };
621
+ window.addEventListener("mousemove", r), window.addEventListener("mouseup", n);
622
+ }
623
+ startReordering(t, e) {
624
+ const s = e.clientX;
625
+ let i = !1;
626
+ const r = (o) => {
627
+ if (!i && Math.abs(o.clientX - s) > 3 && (i = !0, this.state.reorderingCol = t), !i) return;
628
+ const l = this.canvas.getBoundingClientRect(), h = o.clientX - l.left;
629
+ this.state.reorderingX = h;
630
+ const a = M(this.state, h - (this.config.showRowNumbers ? this.config.rowNumbersWidth : 0) + this.state.scrollX);
631
+ a !== -1 && (this.state.reorderingTarget = a), this.actions.invalidate();
632
+ }, n = () => {
633
+ i ? this.state.reorderingTarget !== null && this.state.reorderingCol !== null && this.commitReorder() : this.handleHeaderClick(t), this.state.reorderingCol = this.state.reorderingTarget = this.state.reorderingX = null, window.removeEventListener("mousemove", r), window.removeEventListener("mouseup", n), this.actions.saveState();
634
+ };
635
+ window.addEventListener("mousemove", r), window.addEventListener("mouseup", n);
636
+ }
637
+ handleHeaderClick(t) {
638
+ const e = this.state.columnOrder[t] ?? t, s = this.provider.getHeader(e);
639
+ if (s.isSortable !== !1 && this.config.onSort) {
640
+ const i = s.sortOrder === "asc" ? "desc" : s.sortOrder === "desc" ? null : "asc";
641
+ this.config.onSort(e, i);
642
+ }
643
+ }
644
+ commitReorder() {
645
+ const t = [...this.state.columnOrder];
646
+ if (t.length === 0) for (let i = 0; i < this.provider.getColumnCount(); i++) t.push(i);
647
+ const e = t.splice(this.state.reorderingCol, 1)[0];
648
+ let s = this.state.reorderingTarget;
649
+ s > this.state.reorderingCol && s--, t.splice(s, 0, e), this.state.columnOrder = t, this.actions.updateSelection("column", null, e, !1, !1);
650
+ }
651
+ }
652
+ class F {
653
+ constructor(t, e, s) {
654
+ this.state = t, this.provider = e, this.config = s;
655
+ }
656
+ saveState() {
657
+ if (!this.config.persistenceKey) return;
658
+ const t = { columnOrder: this.state.columnOrder, columnWidths: this.state.columnWidths };
659
+ localStorage.setItem(`scigrid_state_${this.config.persistenceKey}`, JSON.stringify(t));
660
+ }
661
+ loadState() {
662
+ if (!this.config.persistenceKey) return null;
663
+ const t = localStorage.getItem(`scigrid_state_${this.config.persistenceKey}`);
664
+ try {
665
+ return t ? JSON.parse(t) : null;
666
+ } catch {
667
+ return null;
668
+ }
669
+ }
670
+ copyToClipboard() {
671
+ const t = this.state.selectionRanges;
672
+ if (t.length === 0) return;
673
+ let e = 1 / 0, s = -1 / 0, i = 1 / 0, r = -1 / 0;
674
+ for (const o of t)
675
+ e = Math.min(e, o.startRow), s = Math.max(s, o.endRow), i = Math.min(i, o.startCol), r = Math.max(r, o.endCol);
676
+ let n = "";
677
+ for (let o = e; o <= s; o++) {
678
+ const l = [];
679
+ for (let h = i; h <= r; h++) {
680
+ let a = !1;
681
+ for (const c of t) if (o >= c.startRow && o <= c.endRow && h >= c.startCol && h <= c.endCol) {
682
+ a = !0;
683
+ break;
684
+ }
685
+ const u = a ? this.provider.getCellData(o, h) : "";
686
+ l.push(u != null ? `"${u.toString().replace(/"/g, '""')}"` : "");
687
+ }
688
+ n += l.join(" ") + `
689
+ `;
690
+ }
691
+ navigator.clipboard.writeText(n).catch((o) => console.error("Copy failed:", o));
692
+ }
693
+ }
694
+ class U {
695
+ constructor(t, e, s = {}) {
696
+ p(this, "canvas");
697
+ p(this, "renderer");
698
+ p(this, "scroller");
699
+ p(this, "selection");
700
+ p(this, "keyboard");
701
+ p(this, "editors");
702
+ p(this, "mouse");
703
+ p(this, "drags");
704
+ p(this, "data");
705
+ p(this, "uiLayer");
706
+ p(this, "config");
707
+ p(this, "state", {
708
+ scrollX: 0,
709
+ scrollY: 0,
710
+ width: 0,
711
+ height: 0,
712
+ headerHeight: 60,
713
+ columnWidths: {},
714
+ columnOrder: [],
715
+ columnOffsets: [0],
716
+ selectedRows: /* @__PURE__ */ new Set(),
717
+ selectedCols: /* @__PURE__ */ new Set(),
718
+ selectionRanges: [],
719
+ anchorRow: null,
720
+ anchorCol: null,
721
+ resizingCol: null,
722
+ reorderingCol: null,
723
+ reorderingTarget: null,
724
+ reorderingX: null,
725
+ hoveredCol: null,
726
+ selectionMode: "cell"
727
+ });
728
+ p(this, "lastRange", { start: -1, end: -1 });
729
+ p(this, "isDirty", !1);
730
+ p(this, "isSelecting", !1);
731
+ this.container = t, this.provider = e, this.config = {
732
+ rowHeight: 25,
733
+ columnWidth: 100,
734
+ headerHeight: 30,
735
+ showRowNumbers: !0,
736
+ rowNumbersWidth: 40,
737
+ headerSubTextCount: 0,
738
+ headerPlaceholder: "-",
739
+ allowResizing: !0,
740
+ allowFiltering: !0,
741
+ backgroundColor: "#ffffff",
742
+ gridLineColor: "#e0e0e0",
743
+ textColor: "#333333",
744
+ font: "12px Inter, sans-serif",
745
+ headerBackground: "#f3f3f3",
746
+ headerTextColor: "#333333",
747
+ headerFont: "bold 12px Inter, sans-serif",
748
+ rowNumberBackground: "#f9f9f9",
749
+ rowNumberTextColor: "#666666",
750
+ selectionColor: "rgba(0, 120, 215, 0.3)",
751
+ selectedTextColor: "#000000",
752
+ cellPadding: 5,
753
+ ...s
754
+ }, this.state.headerHeight = this.config.headerHeight, this.initDOM(), this.renderer = new D(this.canvas), this.initManagers(), this.scroller = new N(this.container, (i) => this.updateScroll(i), (i) => this.mouse.handleHit(i, !1), (i) => this.mouse.handleHit(i, !0)), this.init();
755
+ }
756
+ initDOM() {
757
+ Object.assign(this.container.style, {
758
+ overflow: "auto",
759
+ position: "relative",
760
+ outline: "none",
761
+ userSelect: "none",
762
+ webkitUserSelect: "none"
763
+ }), this.container.tabIndex = 0, this.container.setAttribute("role", "grid"), this.container.setAttribute("aria-label", "Data Grid"), this.updateAriaCounts();
764
+ const t = document.createElement("div");
765
+ Object.assign(t.style, { position: "sticky", top: "0", left: "0", width: "100%", height: "100%", zIndex: "10" }), this.container.appendChild(t), this.canvas = document.createElement("canvas"), Object.assign(this.canvas.style, { position: "absolute", top: "0", left: "0", display: "block", zIndex: "1" }), t.appendChild(this.canvas), this.uiLayer = document.createElement("div"), Object.assign(this.uiLayer.style, { position: "absolute", top: "0", left: "0", width: "100%", height: "100%", zIndex: "2", pointerEvents: "none" }), t.appendChild(this.uiLayer);
766
+ }
767
+ updateAriaCounts() {
768
+ this.container.setAttribute("aria-rowcount", (this.provider.getRowCount() + 1).toString()), this.container.setAttribute("aria-colcount", this.provider.getColumnCount().toString());
769
+ }
770
+ initManagers() {
771
+ this.selection = new P(this.state, this.provider, this.config, () => this.invalidate()), this.data = new F(this.state, this.provider, this.config);
772
+ const t = {
773
+ getColumnWidth: (e) => k(this.state, this.config, e),
774
+ getColumnOffset: (e) => X(this.state, e),
775
+ invalidate: () => this.invalidate()
776
+ };
777
+ this.editors = new K(this.uiLayer, this.provider, this.config, this.state, t), this.drags = new j(this.canvas, this.state, this.provider, this.config, {
778
+ invalidate: () => this.invalidate(),
779
+ updateSelection: (e, s, i, r, n) => this.selection.updateSelection(e, s, i, r, n),
780
+ updateVirtualSize: () => this.updateVirtualSize(),
781
+ saveState: () => this.data.saveState()
782
+ }), this.mouse = new _(this.canvas, this.state, this.provider, this.config, {
783
+ updateSelection: (e, s, i, r, n) => this.selection.updateSelection(e, s, i, r, n),
784
+ invalidate: () => this.invalidate(),
785
+ render: () => this.render(),
786
+ startResizing: (e, s) => this.drags.startResizing(e, s),
787
+ startReordering: (e, s) => this.drags.startReordering(e, s),
788
+ openEditor: (e, s) => this.editors.openCellEditor(e, s),
789
+ openHeaderEditor: (e, s) => this.editors.openHeaderEditor(e, s),
790
+ closeEditor: () => this.editors.closeEditor(),
791
+ setSelecting: (e) => this.isSelecting = e
792
+ }), this.keyboard = new Y(this.state, this.provider, this.config, {
793
+ updateSelection: (e, s, i, r, n) => this.selection.updateSelection(e, s, i, r, n),
794
+ scrollToCell: (e, s) => this.scrollToCell(e, s),
795
+ copyToClipboard: () => this.data.copyToClipboard(),
796
+ render: () => this.render()
797
+ });
798
+ }
799
+ init() {
800
+ const t = this.data.loadState();
801
+ if (t && (this.state.columnOrder = t.columnOrder || [], this.state.columnWidths = t.columnWidths || {}), this.state.columnOrder.length === 0) for (let e = 0; e < this.provider.getColumnCount(); e++) this.state.columnOrder.push(e);
802
+ new ResizeObserver((e) => e.forEach((s) => this.resize(Math.floor(s.contentRect.width), Math.floor(s.contentRect.height)))).observe(this.container), this.container.addEventListener("keydown", (e) => this.keyboard.handleKeyDown(e, !!this.editors.activeEditor)), this.container.addEventListener("mousemove", (e) => this.handleMouseMove(e)), window.addEventListener("mousedown", (e) => {
803
+ this.editors.activeEditor && !this.editors.activeEditor.contains(e.target) && !this.container.contains(e.target) && this.editors.closeEditor();
804
+ }), window.addEventListener("mousemove", (e) => this.handleWindowMouseMove(e)), window.addEventListener("mouseup", () => this.handleWindowMouseUp()), this.updateVirtualSize(), this.requestAnimationFrame();
805
+ }
806
+ resize(t, e) {
807
+ this.state.width = t, this.state.height = e, this.renderer.resize(t, e), this.invalidate();
808
+ }
809
+ updateVirtualSize() {
810
+ const t = this.provider.getColumnCount(), e = new Array(t + 1);
811
+ let s = 0;
812
+ e[0] = 0;
813
+ for (let i = 0; i < t; i++)
814
+ s += k(this.state, this.config, this.state.columnOrder[i] ?? i), e[i + 1] = s;
815
+ this.state.columnOffsets = e, this.scroller.updateVirtualSize((this.config.showRowNumbers ? this.config.rowNumbersWidth : 0) + s, this.provider.getRowCount() * this.config.rowHeight + this.state.headerHeight);
816
+ }
817
+ handleMouseMove(t) {
818
+ if (this.state.resizingCol !== null || this.state.reorderingCol !== null) {
819
+ this.container.style.cursor = this.state.resizingCol !== null ? "col-resize" : "grabbing";
820
+ return;
821
+ }
822
+ const e = this.config.showRowNumbers ? this.config.rowNumbersWidth : 0, s = this.canvas.getBoundingClientRect(), i = t.clientX - s.left, r = t.clientY - s.top;
823
+ if (this.config.showRowNumbers && r < this.state.headerHeight && Math.abs(i - e) < 5) {
824
+ this.container.style.cursor = "col-resize";
825
+ return;
826
+ }
827
+ const n = i - e + this.state.scrollX;
828
+ if ((r >= this.state.headerHeight || i < e) && this.state.hoveredCol !== null && (this.state.hoveredCol = null, this.render()), r < this.state.headerHeight && i >= e) {
829
+ const o = M(this.state, n), l = this.state.columnOrder[o] ?? o;
830
+ this.state.hoveredCol !== l && (this.state.hoveredCol = l, this.render()), this.container.style.cursor = "grab";
831
+ } else this.container.style.cursor = "default";
832
+ }
833
+ handleWindowMouseMove(t) {
834
+ if (this.isSelecting) {
835
+ const e = this.config.showRowNumbers ? this.config.rowNumbersWidth : 0, s = this.canvas.getBoundingClientRect(), i = t.clientX - s.left, r = t.clientY - s.top, n = i - e + this.state.scrollX, o = Math.max(0, Math.min(this.provider.getRowCount() - 1, Math.floor((r - this.state.headerHeight + this.state.scrollY) / this.config.rowHeight))), l = M(this.state, n);
836
+ l !== -1 && (this.selection.updateSelection("cell", o, this.state.columnOrder[l] ?? l, t.ctrlKey, !0), this.render());
837
+ }
838
+ }
839
+ handleWindowMouseUp() {
840
+ this.isSelecting && (this.isSelecting = !1, this.render());
841
+ }
842
+ getColumnAt(t) {
843
+ return M(this.state, t);
844
+ }
845
+ getColumnOffset(t) {
846
+ return X(this.state, t);
847
+ }
848
+ getColumnWidth(t) {
849
+ return k(this.state, this.config, t);
850
+ }
851
+ saveState() {
852
+ this.data.saveState();
853
+ }
854
+ scrollToCell(t, e) {
855
+ const s = this.state.columnOrder.indexOf(e);
856
+ this.scroller.scrollToCell(this.getColumnOffset(s === -1 ? e : s) + (this.config.showRowNumbers ? this.config.rowNumbersWidth : 0), t * this.config.rowHeight + this.state.headerHeight, this.getColumnWidth(e), this.config.rowHeight);
857
+ }
858
+ invalidate() {
859
+ this.isDirty = !0;
860
+ }
861
+ render() {
862
+ if (this.provider.onRowsNeeded) {
863
+ const t = Math.floor(this.state.scrollY / this.config.rowHeight), e = Math.ceil((this.state.scrollY + this.state.height) / this.config.rowHeight);
864
+ (Math.abs(t - this.lastRange.start) > 5 || Math.abs(e - this.lastRange.end) > 5) && (this.lastRange = { start: t, end: e }, this.provider.onRowsNeeded(Math.max(0, t - 50), Math.min(this.provider.getRowCount() - 1, e + 50)));
865
+ }
866
+ this.renderer.render(this.state, this.config, this.provider), this.isDirty = !1;
867
+ }
868
+ renderNow() {
869
+ this.render();
870
+ }
871
+ requestAnimationFrame() {
872
+ const t = () => {
873
+ this.isDirty && this.render(), requestAnimationFrame(t);
874
+ };
875
+ requestAnimationFrame(t);
876
+ }
877
+ updateProvider(t) {
878
+ this.provider = t, this.state.columnOrder = [];
879
+ for (let e = 0; e < t.getColumnCount(); e++) this.state.columnOrder.push(e);
880
+ this.updateVirtualSize(), this.updateAriaCounts(), this.invalidate();
881
+ }
882
+ updateConfig(t) {
883
+ this.config = { ...this.config, ...t }, this.state.headerHeight = this.config.headerHeight, this.editors.closeEditor(), this.scroller.updateScrollStyle(this.config.scrollbarThumbColor, this.config.scrollbarColor), this.updateVirtualSize(), this.invalidate();
884
+ }
885
+ updateScroll(t) {
886
+ t.scrollX !== void 0 && (this.state.scrollX = t.scrollX), t.scrollY !== void 0 && (this.state.scrollY = t.scrollY), this.editors.closeEditor(), this.render();
887
+ }
888
+ destroy() {
889
+ this.container.innerHTML = "";
890
+ }
891
+ }
892
+ export {
893
+ U as SciGrid
894
+ };