draw-table-vue 0.7.0 → 0.8.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/package.json +3 -3
- package/dist/draw-table-vue.css +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.es.js +0 -753
- package/dist/index.umd.js +0 -1
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "draw-table-vue",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"main": "./dist/draw-table.umd.js",
|
|
5
5
|
"module": "./dist/draw-table.es.js",
|
|
6
|
-
"types": "./dist/draw-table
|
|
6
|
+
"types": "./dist/draw-table.d.ts",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": {
|
|
9
|
-
"types": "./dist/draw-table
|
|
9
|
+
"types": "./dist/draw-table.d.ts",
|
|
10
10
|
"import": "./dist/draw-table.es.js",
|
|
11
11
|
"require": "./dist/draw-table.umd.js",
|
|
12
12
|
"default": "./dist/draw-table.es.js"
|
package/dist/draw-table-vue.css
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.canvas-table-container[data-v-34fbfef2]{width:100%;height:100%;border:1px solid #ebeef5;box-sizing:border-box}.canvas-wrapper[data-v-34fbfef2]{background:#fff}.scrollbar[data-v-34fbfef2]{position:absolute;overflow:auto;z-index:10}.scrollbar.horizontal[data-v-34fbfef2]{bottom:0;left:0;right:0;height:12px}.scrollbar.vertical[data-v-34fbfef2]{top:0;right:0;bottom:0;width:12px}.scrollbar[data-v-34fbfef2]::-webkit-scrollbar{width:8px;height:8px}.scrollbar[data-v-34fbfef2]::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:4px}.scrollbar[data-v-34fbfef2]::-webkit-scrollbar-thumb:hover{background:#a8a8a8}.table-overlays[data-v-34fbfef2]{z-index:5}.edit-btn[data-v-34fbfef2]{width:20px;height:20px;background:#fff;border:1px solid #dcdfe6;border-radius:4px;display:flex;align-items:center;justify-content:center;cursor:pointer;color:#409eff;box-shadow:0 2px 4px #0000001a}.edit-btn[data-v-34fbfef2]:hover{background:#f5f7fa}.header-menu-overlay[data-v-34fbfef2]{position:absolute;inset:0;pointer-events:auto;z-index:20}.header-menu[data-v-34fbfef2]{background:#fff;border:1px solid #ebeef5;border-radius:4px;box-shadow:0 2px 12px #0000001a;padding:5px 0;min-width:120px}.menu-item[data-v-34fbfef2]{padding:8px 12px;cursor:pointer;display:flex;align-items:center;gap:8px;font-size:14px}.menu-item[data-v-34fbfef2]:hover{background:#f5f7fa;color:#409eff}.edit-dialog-popover[data-v-34fbfef2]{background:#fff;border-radius:4px;width:300px;box-shadow:0 2px 12px #0000001a;border:1px solid #ebeef5;display:flex;flex-direction:column;z-index:2000}.popover-click-mask[data-v-34fbfef2]{position:fixed;inset:0;z-index:1999}.edit-dialog-content[data-v-34fbfef2]{padding:12px}.edit-dialog-footer[data-v-34fbfef2]{padding:8px 12px;border-top:1px solid #ebeef5;display:flex;justify-content:flex-end;gap:8px}button.small[data-v-34fbfef2]{padding:4px 12px;font-size:12px}button.primary[data-v-34fbfef2]{background:#409eff;color:#fff;border-color:#409eff}
|
package/dist/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {}
|
package/dist/index.es.js
DELETED
|
@@ -1,753 +0,0 @@
|
|
|
1
|
-
import { defineComponent as J, ref as k, shallowRef as vt, computed as M, onMounted as gt, onUnmounted as mt, watch as O, openBlock as P, createElementBlock as z, createElementVNode as H, withModifiers as D, normalizeStyle as T, createCommentVNode as I, Fragment as U, renderList as q, toDisplayString as G, createBlock as Q, resolveDynamicComponent as wt, Teleport as pt, createVNode as yt, unref as Ct, h as B } from "vue";
|
|
2
|
-
class Rt {
|
|
3
|
-
ctx;
|
|
4
|
-
canvas;
|
|
5
|
-
columns = [];
|
|
6
|
-
data = [];
|
|
7
|
-
options = {
|
|
8
|
-
rowHeight: 40,
|
|
9
|
-
headerHeight: 48,
|
|
10
|
-
border: !0,
|
|
11
|
-
stripe: !0,
|
|
12
|
-
multiSelect: !1,
|
|
13
|
-
fixedHeader: !0,
|
|
14
|
-
renderExpand: () => null,
|
|
15
|
-
spanMethod: () => {
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
scrollX = 0;
|
|
19
|
-
scrollY = 0;
|
|
20
|
-
width = 0;
|
|
21
|
-
height = 0;
|
|
22
|
-
// Layout info
|
|
23
|
-
columnPositions = [];
|
|
24
|
-
rowOffsets = [];
|
|
25
|
-
totalWidth = 0;
|
|
26
|
-
totalHeight = 0;
|
|
27
|
-
fixedLeftWidth = 0;
|
|
28
|
-
summaryRows = [];
|
|
29
|
-
expandedRowKeys = /* @__PURE__ */ new Set();
|
|
30
|
-
selectedRowKeys = /* @__PURE__ */ new Set();
|
|
31
|
-
imageCache = /* @__PURE__ */ new Map();
|
|
32
|
-
hoverHeaderIndex = -1;
|
|
33
|
-
flattenedColumns = [];
|
|
34
|
-
columnLevels = 0;
|
|
35
|
-
constructor(t) {
|
|
36
|
-
this.canvas = t;
|
|
37
|
-
const i = t.getContext("2d");
|
|
38
|
-
if (!i) throw new Error("Could not get canvas context");
|
|
39
|
-
this.ctx = i;
|
|
40
|
-
}
|
|
41
|
-
destroy() {
|
|
42
|
-
this.imageCache.forEach((t) => {
|
|
43
|
-
t.onload = null, t.onerror = null, t.src = "";
|
|
44
|
-
}), this.imageCache.clear(), this.data = [], this.columns = [], this.summaryRows = [];
|
|
45
|
-
}
|
|
46
|
-
setExpandedRows(t) {
|
|
47
|
-
this.expandedRowKeys = new Set(t), this.calculateLayout(), this.render();
|
|
48
|
-
}
|
|
49
|
-
setData(t) {
|
|
50
|
-
this.data = t, this.calculateLayout(), this.render();
|
|
51
|
-
}
|
|
52
|
-
setColumns(t) {
|
|
53
|
-
this.columns = t, this.flattenColumns(), this.calculateLayout(), this.render();
|
|
54
|
-
}
|
|
55
|
-
flattenColumns() {
|
|
56
|
-
this.flattenedColumns = [], this.columnLevels = 0;
|
|
57
|
-
const t = (s, r = 0) => {
|
|
58
|
-
this.columnLevels = Math.max(this.columnLevels, r + 1), s.forEach((o) => {
|
|
59
|
-
o.children && o.children.length > 0 ? t(o.children, r + 1) : this.flattenedColumns.push(o);
|
|
60
|
-
});
|
|
61
|
-
};
|
|
62
|
-
t(this.columns);
|
|
63
|
-
const i = 40;
|
|
64
|
-
this.columnLevels > 1 ? this.options.headerHeight = this.columnLevels * i : this.options.headerHeight = 48;
|
|
65
|
-
}
|
|
66
|
-
setOptions(t) {
|
|
67
|
-
this.options = { ...this.options, ...t }, this.calculateLayout(), this.render();
|
|
68
|
-
}
|
|
69
|
-
resize(t, i) {
|
|
70
|
-
this.width = t, this.height = i;
|
|
71
|
-
const s = window.devicePixelRatio || 1;
|
|
72
|
-
this.canvas.width = t * s, this.canvas.height = i * s, this.canvas.style.width = `${t}px`, this.canvas.style.height = `${i}px`, this.ctx.resetTransform(), this.ctx.scale(s, s), this.render();
|
|
73
|
-
}
|
|
74
|
-
scrollTo(t, i) {
|
|
75
|
-
this.scrollX = t, this.scrollY = i, this.render();
|
|
76
|
-
}
|
|
77
|
-
calculateLayout() {
|
|
78
|
-
let t = 0;
|
|
79
|
-
this.columnPositions = [0];
|
|
80
|
-
let i = 0;
|
|
81
|
-
this.flattenedColumns.forEach((o) => {
|
|
82
|
-
const l = o.width || 100;
|
|
83
|
-
t += l, this.columnPositions.push(t), (o.fixed === "left" || o.fixed === !0) && (i = t);
|
|
84
|
-
}), this.totalWidth = t, this.fixedLeftWidth = i;
|
|
85
|
-
let s = 0;
|
|
86
|
-
this.rowOffsets = [0];
|
|
87
|
-
const { rowHeight: r } = this.options;
|
|
88
|
-
this.data.forEach((o) => {
|
|
89
|
-
s += r, this.expandedRowKeys.has(o.id) && (s += r * 3), this.rowOffsets.push(s);
|
|
90
|
-
}), this.totalHeight = s, this.calculateSummaries();
|
|
91
|
-
}
|
|
92
|
-
getRowRange(t = 20) {
|
|
93
|
-
const { headerHeight: i } = this.options, s = this.summaryRows.length * this.options.rowHeight, r = this.height - i - s, o = this.scrollY, l = o + r;
|
|
94
|
-
let n = 0;
|
|
95
|
-
for (; n < this.rowOffsets.length && (this.rowOffsets[n + 1] ?? 0) < o; )
|
|
96
|
-
n++;
|
|
97
|
-
let a = n;
|
|
98
|
-
for (; a < this.rowOffsets.length && (this.rowOffsets[a] ?? 0) < l; )
|
|
99
|
-
a++;
|
|
100
|
-
return {
|
|
101
|
-
startRow: Math.max(0, n - t),
|
|
102
|
-
endRow: Math.min(this.data.length, a + 1)
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
calculateSummaries() {
|
|
106
|
-
this.summaryRows = [];
|
|
107
|
-
const t = /* @__PURE__ */ new Map();
|
|
108
|
-
this.flattenedColumns.forEach((i, s) => {
|
|
109
|
-
i.summary && i.summary.forEach((r) => {
|
|
110
|
-
try {
|
|
111
|
-
const o = r(this.data);
|
|
112
|
-
if (o && o.label) {
|
|
113
|
-
const { label: l, value: n } = o;
|
|
114
|
-
t.has(l) || t.set(l, new Array(this.flattenedColumns.length).fill("")), t.get(l)[s] = n;
|
|
115
|
-
}
|
|
116
|
-
} catch (o) {
|
|
117
|
-
console.error("Summary calculation error:", o);
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
}), t.forEach((i, s) => {
|
|
121
|
-
i[0] = s, this.summaryRows.push(i);
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
render() {
|
|
125
|
-
this.ctx.clearRect(0, 0, this.width, this.height), this.drawBody(), this.drawFixedLeftBody(), this.drawHeader(), this.drawSummaryRows();
|
|
126
|
-
}
|
|
127
|
-
getColumnWidth(t) {
|
|
128
|
-
return t.children && t.children.length > 0 ? t.children.reduce((s, r) => s + this.getColumnWidth(r), 0) : t.width || 100;
|
|
129
|
-
}
|
|
130
|
-
isColumnFixed(t) {
|
|
131
|
-
return t.fixed === "left" || t.fixed === "right" || t.fixed === !0 ? !0 : t.children && t.children.length > 0 ? t.children.some((i) => this.isColumnFixed(i)) : !1;
|
|
132
|
-
}
|
|
133
|
-
drawHeader() {
|
|
134
|
-
const { headerHeight: t } = this.options, i = this.columnLevels > 1 ? 40 : t;
|
|
135
|
-
this.ctx.save(), this.ctx.fillStyle = "#f5f7fa", this.ctx.fillRect(0, 0, this.width, t);
|
|
136
|
-
const s = (r, o, l, n, a) => {
|
|
137
|
-
let e = o;
|
|
138
|
-
r.forEach((c) => {
|
|
139
|
-
const f = this.getColumnWidth(c), d = this.isColumnFixed(c);
|
|
140
|
-
if (a !== d) {
|
|
141
|
-
e += f;
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
const v = !c.children || c.children.length === 0, g = v ? (this.columnLevels - n) * i : i, R = a ? e : e - this.scrollX;
|
|
145
|
-
(a || R + f > this.fixedLeftWidth && R < this.width) && (a || (this.ctx.save(), this.ctx.beginPath(), this.ctx.rect(this.fixedLeftWidth, 0, this.width - this.fixedLeftWidth, t), this.ctx.clip()), this.drawHeaderCell(c, R, f, g, l, v), a || this.ctx.restore()), c.children && c.children.length > 0 && s(c.children, e, l + i, n + 1, a), e += f;
|
|
146
|
-
});
|
|
147
|
-
};
|
|
148
|
-
s(this.columns, 0, 0, 0, !1), s(this.columns, 0, 0, 0, !0), this.ctx.restore();
|
|
149
|
-
}
|
|
150
|
-
setHoverHeader(t) {
|
|
151
|
-
this.hoverHeaderIndex !== t && (this.hoverHeaderIndex = t, this.render());
|
|
152
|
-
}
|
|
153
|
-
setSelectedRows(t) {
|
|
154
|
-
this.selectedRowKeys = new Set(t), this.render();
|
|
155
|
-
}
|
|
156
|
-
drawHeaderCell(t, i, s, r, o, l) {
|
|
157
|
-
if (this.ctx.save(), this.ctx.beginPath(), this.ctx.rect(i, o, s, r), this.ctx.clip(), this.ctx.fillStyle = "#f5f7fa", this.ctx.fillRect(i, o, s, r), this.options.border && (this.ctx.strokeStyle = "#ebeef5", this.ctx.lineWidth = 1, this.ctx.strokeRect(i + 0.5, o + 0.5, s, r)), t.type === "selection") {
|
|
158
|
-
const n = this.data.length > 0 && this.selectedRowKeys.size === this.data.length;
|
|
159
|
-
this.drawCheckboxCell(n, i, o, s, r, "center");
|
|
160
|
-
} else {
|
|
161
|
-
this.ctx.fillStyle = "#303133", this.ctx.font = "bold 14px sans-serif", this.ctx.textBaseline = "middle";
|
|
162
|
-
const n = t.align || (l ? "left" : "center");
|
|
163
|
-
this.ctx.textAlign = n;
|
|
164
|
-
let a = i + 10;
|
|
165
|
-
n === "center" && (a = i + s / 2), n === "right" && (a = i + s - 24);
|
|
166
|
-
const e = t.title || "";
|
|
167
|
-
if (this.ctx.fillText(e, a, o + r / 2), l && t.type !== "selection" && t.type !== "expand") {
|
|
168
|
-
const c = this.flattenedColumns.indexOf(t);
|
|
169
|
-
if (this.hoverHeaderIndex === c) {
|
|
170
|
-
this.ctx.fillStyle = "#909399", this.ctx.beginPath();
|
|
171
|
-
const f = i + s - 18, d = o + r / 2;
|
|
172
|
-
this.ctx.arc(f, d - 4, 1.5, 0, Math.PI * 2), this.ctx.arc(f, d, 1.5, 0, Math.PI * 2), this.ctx.arc(f, d + 4, 1.5, 0, Math.PI * 2), this.ctx.fill();
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
this.ctx.restore();
|
|
177
|
-
}
|
|
178
|
-
getHeaderAt(t, i) {
|
|
179
|
-
const { headerHeight: s } = this.options;
|
|
180
|
-
if (i > s) return null;
|
|
181
|
-
const r = this.columnLevels > 1 ? 40 : s, o = (n, a, e, c) => {
|
|
182
|
-
let f = a;
|
|
183
|
-
for (const d of n) {
|
|
184
|
-
const v = this.isColumnFixed(d);
|
|
185
|
-
if (c !== v) {
|
|
186
|
-
f += this.getColumnWidth(d);
|
|
187
|
-
continue;
|
|
188
|
-
}
|
|
189
|
-
const g = this.getColumnWidth(d), R = !d.children || d.children.length === 0, y = R ? (this.columnLevels - e) * r : r, C = e * r, S = c ? f : f - this.scrollX;
|
|
190
|
-
if (!c && S < this.fixedLeftWidth) {
|
|
191
|
-
f += g;
|
|
192
|
-
continue;
|
|
193
|
-
}
|
|
194
|
-
if (t >= S && t < S + g && i >= C && i < C + y) {
|
|
195
|
-
const w = R && d.type !== "selection" && d.type !== "expand" && t >= S + g - 24;
|
|
196
|
-
return {
|
|
197
|
-
column: d,
|
|
198
|
-
rect: { x: S, y: C, width: g, height: y },
|
|
199
|
-
isMenu: w
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
if (d.children && d.children.length > 0) {
|
|
203
|
-
const w = o(d.children, f, e + 1, c);
|
|
204
|
-
if (w) return w;
|
|
205
|
-
}
|
|
206
|
-
f += g;
|
|
207
|
-
}
|
|
208
|
-
return null;
|
|
209
|
-
}, l = o(this.columns, 0, 0, !0);
|
|
210
|
-
return l || o(this.columns, 0, 0, !1);
|
|
211
|
-
}
|
|
212
|
-
drawBody() {
|
|
213
|
-
const { headerHeight: t } = this.options, { startRow: i, endRow: s } = this.getRowRange(this.height), r = this.summaryRows.length * this.options.rowHeight;
|
|
214
|
-
this.ctx.save(), this.ctx.beginPath(), this.ctx.rect(this.fixedLeftWidth, t, this.width - this.fixedLeftWidth, this.height - t - r), this.ctx.clip();
|
|
215
|
-
const o = /* @__PURE__ */ new Set(), l = [];
|
|
216
|
-
for (let n = i; n < s; n++) {
|
|
217
|
-
const a = this.data[n];
|
|
218
|
-
if (!a) continue;
|
|
219
|
-
const e = (this.rowOffsets[n] ?? 0) - this.scrollY + t, c = (this.rowOffsets[n + 1] ?? 0) - (this.rowOffsets[n] ?? 0), f = n % 2 === 1 && this.options.stripe ? "#fafafa" : "#fff";
|
|
220
|
-
if (this.flattenedColumns.forEach((d, v) => {
|
|
221
|
-
if (d.fixed === "left" || d.fixed === !0 || o.has(`${n},${v}`)) return;
|
|
222
|
-
const g = (this.columnPositions[v] ?? 0) - this.scrollX, R = (this.columnPositions[v + 1] ?? 0) - (this.columnPositions[v] ?? 0), y = this.options.spanMethod({ row: n, column: d, rowIndex: n, columnIndex: v });
|
|
223
|
-
if (y) {
|
|
224
|
-
const { rowspan: C, colspan: S } = y;
|
|
225
|
-
if (C === 0 || S === 0) return;
|
|
226
|
-
const w = (this.columnPositions[v + S] ?? this.totalWidth) - (this.columnPositions[v] ?? 0), L = (this.rowOffsets[n + C] ?? this.totalHeight) - (this.rowOffsets[n] ?? 0);
|
|
227
|
-
for (let b = 0; b < C; b++)
|
|
228
|
-
for (let Y = 0; Y < S; Y++)
|
|
229
|
-
o.add(`${n + b},${v + Y}`);
|
|
230
|
-
l.push({ col: d, val: a[d.key || ""], x: g, y: e, w, h: L, r: n, c: v, bgColor: f });
|
|
231
|
-
} else
|
|
232
|
-
this.ctx.fillStyle = f, this.ctx.fillRect(g, e, R, this.options.rowHeight), this.drawCell(d, a[d.key || ""], g, e, R, this.options.rowHeight, n), this.options.border && (this.ctx.strokeStyle = "#ebeef5", this.ctx.strokeRect(g + 0.5, e + 0.5, R, this.options.rowHeight));
|
|
233
|
-
}), this.expandedRowKeys.has(a.id)) {
|
|
234
|
-
const d = e + this.options.rowHeight, v = c - this.options.rowHeight;
|
|
235
|
-
this.ctx.fillStyle = "#fdfdfd", this.ctx.fillRect(0, d, this.width, v), this.options.border && (this.ctx.strokeStyle = "#ebeef5", this.ctx.beginPath(), this.ctx.moveTo(0, d), this.ctx.lineTo(this.width, d), this.ctx.stroke()), this.drawExpandPlaceholder(a, this.fixedLeftWidth - this.scrollX, d, this.totalWidth - this.fixedLeftWidth, v);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
l.forEach(({ col: n, val: a, x: e, y: c, w: f, h: d, r: v, bgColor: g }) => {
|
|
239
|
-
this.ctx.fillStyle = g, this.ctx.fillRect(e, c, f, d), this.drawCell(n, a, e, c, f, d, v), this.options.border && (this.ctx.strokeStyle = "#ebeef5", this.ctx.strokeRect(e + 0.5, c + 0.5, f, d));
|
|
240
|
-
}), this.ctx.restore();
|
|
241
|
-
}
|
|
242
|
-
drawFixedLeftBody() {
|
|
243
|
-
const { headerHeight: t } = this.options, { startRow: i, endRow: s } = this.getRowRange(this.height), r = this.summaryRows.length * this.options.rowHeight;
|
|
244
|
-
this.ctx.save(), this.ctx.beginPath(), this.ctx.rect(0, t, this.fixedLeftWidth, this.height - t - r), this.ctx.clip();
|
|
245
|
-
const o = /* @__PURE__ */ new Set(), l = [];
|
|
246
|
-
for (let n = i; n < s; n++) {
|
|
247
|
-
const a = this.data[n];
|
|
248
|
-
if (!a) continue;
|
|
249
|
-
const e = (this.rowOffsets[n] ?? 0) - this.scrollY + t, c = n % 2 === 1 && this.options.stripe ? "#fafafa" : "#fff";
|
|
250
|
-
this.flattenedColumns.forEach((f, d) => {
|
|
251
|
-
if (!(f.fixed === "left" || f.fixed === !0) || o.has(`${n},${d}`)) return;
|
|
252
|
-
const v = this.columnPositions[d] ?? 0, g = (this.columnPositions[d + 1] ?? 0) - (this.columnPositions[d] ?? 0), R = this.options.spanMethod({ row: n, column: f, rowIndex: n, columnIndex: d });
|
|
253
|
-
if (R) {
|
|
254
|
-
const { rowspan: y, colspan: C } = R;
|
|
255
|
-
if (y === 0 || C === 0) return;
|
|
256
|
-
const S = (this.columnPositions[d + C] ?? this.fixedLeftWidth) - (this.columnPositions[d] ?? 0), w = (this.rowOffsets[n + y] ?? this.totalHeight) - (this.rowOffsets[n] ?? 0);
|
|
257
|
-
for (let L = 0; L < y; L++)
|
|
258
|
-
for (let b = 0; b < C; b++)
|
|
259
|
-
o.add(`${n + L},${d + b}`);
|
|
260
|
-
l.push({ col: f, val: a[f.key || ""], x: v, y: e, w: S, h: w, r: n, c: d, bgColor: c });
|
|
261
|
-
} else
|
|
262
|
-
this.ctx.fillStyle = c, this.ctx.fillRect(v, e, g, this.options.rowHeight), this.drawCell(f, a[f.key || ""], v, e, g, this.options.rowHeight, n), this.options.border && (this.ctx.strokeStyle = "#ebeef5", this.ctx.strokeRect(v + 0.5, e + 0.5, g, this.options.rowHeight));
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
l.forEach(({ col: n, val: a, x: e, y: c, w: f, h: d, r: v, bgColor: g }) => {
|
|
266
|
-
this.ctx.fillStyle = g, this.ctx.fillRect(e, c, f, d), this.drawCell(n, a, e, c, f, d, v), this.options.border && (this.ctx.strokeStyle = "#ebeef5", this.ctx.strokeRect(e + 0.5, c + 0.5, f, d));
|
|
267
|
-
}), this.ctx.restore();
|
|
268
|
-
}
|
|
269
|
-
drawExpandPlaceholder(t, i, s, r, o) {
|
|
270
|
-
this.ctx.save(), this.ctx.fillStyle = "#fef0f0", this.ctx.fillRect(i, s, r, o), this.ctx.fillStyle = "#f56c6c", this.ctx.font = "italic 12px sans-serif", this.ctx.textAlign = "center", this.ctx.fillText(`Expanded content for row ${t.id} (Rendered via h function in overlay)`, i + r / 2, s + o / 2), this.ctx.restore();
|
|
271
|
-
}
|
|
272
|
-
drawSummaryRows() {
|
|
273
|
-
if (this.summaryRows.length === 0) return;
|
|
274
|
-
const { rowHeight: t } = this.options, i = this.summaryRows.length * t, s = this.height - i;
|
|
275
|
-
this.ctx.save(), this.ctx.fillStyle = "#fdf6ec", this.ctx.fillRect(0, s, this.width, i);
|
|
276
|
-
let r = 0;
|
|
277
|
-
for (let o = 0; o < this.flattenedColumns.length; o++) {
|
|
278
|
-
const l = this.flattenedColumns[o];
|
|
279
|
-
if (l && (l.type === "selection" || l.type === "expand" || l.key === "id"))
|
|
280
|
-
r++;
|
|
281
|
-
else
|
|
282
|
-
break;
|
|
283
|
-
}
|
|
284
|
-
r === 0 && (r = 1), this.summaryRows.forEach((o, l) => {
|
|
285
|
-
const n = s + l * t;
|
|
286
|
-
this.ctx.save(), this.ctx.beginPath(), this.ctx.rect(this.fixedLeftWidth, n, this.width - this.fixedLeftWidth, t), this.ctx.clip(), this.flattenedColumns.forEach((a, e) => {
|
|
287
|
-
if (a.fixed === "left" || a.fixed === !0 || e < r) return;
|
|
288
|
-
const c = (this.columnPositions[e] ?? 0) - this.scrollX, f = (this.columnPositions[e + 1] ?? 0) - (this.columnPositions[e] ?? 0);
|
|
289
|
-
this.drawTextCell(o[e], c, n, f, t, a.align), this.options.border && (this.ctx.strokeStyle = "#ebeef5", this.ctx.strokeRect(c + 0.5, n + 0.5, f, t));
|
|
290
|
-
}), this.ctx.restore(), this.flattenedColumns.forEach((a, e) => {
|
|
291
|
-
if (a.fixed === "left" || a.fixed === !0) {
|
|
292
|
-
const c = this.columnPositions[e] ?? 0, f = (this.columnPositions[e + 1] ?? 0) - (this.columnPositions[e] ?? 0);
|
|
293
|
-
if (e === 0) {
|
|
294
|
-
const d = (this.columnPositions[r] ?? this.fixedLeftWidth) - (this.columnPositions[0] ?? 0);
|
|
295
|
-
this.ctx.save(), this.ctx.font = "bold 13px sans-serif", this.ctx.fillStyle = "#e6a23c", this.drawTextCell(o[0], c, n, d, t, "center"), this.ctx.restore(), this.options.border && (this.ctx.strokeStyle = "#ebeef5", this.ctx.strokeRect(c + 0.5, n + 0.5, d, t));
|
|
296
|
-
} else {
|
|
297
|
-
if (e < r)
|
|
298
|
-
return;
|
|
299
|
-
this.drawTextCell(o[e], c, n, f, t, a.align), this.options.border && (this.ctx.strokeStyle = "#ebeef5", this.ctx.strokeRect(c + 0.5, n + 0.5, f, t));
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
|
-
}), this.ctx.restore();
|
|
304
|
-
}
|
|
305
|
-
drawCell(t, i, s, r, o, l, n) {
|
|
306
|
-
if (this.ctx.save(), this.ctx.beginPath(), this.ctx.rect(s, r, o, l), this.ctx.clip(), t.renderCell)
|
|
307
|
-
this.drawTextCell(i, s, r, o, l, t.align);
|
|
308
|
-
else
|
|
309
|
-
switch (t.type) {
|
|
310
|
-
case "expand":
|
|
311
|
-
this.drawExpandButton(s + (o - 16) / 2, r + (this.options.rowHeight - 16) / 2, this.expandedRowKeys.has(this.data[n]?.id ?? ""));
|
|
312
|
-
break;
|
|
313
|
-
case "selection":
|
|
314
|
-
const a = this.selectedRowKeys.has(this.data[n]?.id ?? "");
|
|
315
|
-
this.drawCheckboxCell(a, s, r, o, this.options.rowHeight, "center");
|
|
316
|
-
break;
|
|
317
|
-
case "image":
|
|
318
|
-
this.drawImageCell(i, s, r, o, l, t.align);
|
|
319
|
-
break;
|
|
320
|
-
case "checkbox":
|
|
321
|
-
this.drawCheckboxCell(i, s, r, o, l, t.align);
|
|
322
|
-
break;
|
|
323
|
-
case "radio":
|
|
324
|
-
this.drawRadioCell(i, s, r, o, l, t.align);
|
|
325
|
-
break;
|
|
326
|
-
case "switch":
|
|
327
|
-
this.drawSwitchCell(i, s, r, o, l, t.align);
|
|
328
|
-
break;
|
|
329
|
-
case "color-picker":
|
|
330
|
-
this.drawColorPickerCell(i, s, r, o, l, t.align);
|
|
331
|
-
break;
|
|
332
|
-
case "tags":
|
|
333
|
-
this.drawTagsCell(i, s, r, o, l);
|
|
334
|
-
break;
|
|
335
|
-
default:
|
|
336
|
-
this.drawTextCell(i, s, r, o, l, t.align);
|
|
337
|
-
break;
|
|
338
|
-
}
|
|
339
|
-
this.ctx.restore();
|
|
340
|
-
}
|
|
341
|
-
drawExpandButton(t, i, s) {
|
|
342
|
-
this.ctx.save(), this.ctx.translate(t + 8, i + 8), s && this.ctx.rotate(Math.PI / 2), this.ctx.strokeStyle = "#909399", this.ctx.lineWidth = 2, this.ctx.beginPath(), this.ctx.moveTo(-3, -5), this.ctx.lineTo(3, 0), this.ctx.lineTo(-3, 5), this.ctx.stroke(), this.ctx.restore();
|
|
343
|
-
}
|
|
344
|
-
drawTextCell(t, i, s, r, o, l) {
|
|
345
|
-
this.ctx.fillStyle = "#606266", this.ctx.font = "14px sans-serif", this.ctx.textAlign = l || "left", this.ctx.textBaseline = "middle";
|
|
346
|
-
let n = i + 10;
|
|
347
|
-
l === "center" && (n = i + r / 2), l === "right" && (n = i + r - 10);
|
|
348
|
-
const a = t == null ? "" : String(t);
|
|
349
|
-
this.ctx.fillText(a, n, s + o / 2);
|
|
350
|
-
}
|
|
351
|
-
drawImageCell(t, i, s, r, o, l) {
|
|
352
|
-
if (!t) return;
|
|
353
|
-
const n = String(t), a = Math.min(r, o) - 10;
|
|
354
|
-
let e = i + 5;
|
|
355
|
-
l === "center" && (e = i + (r - a) / 2), l === "right" && (e = i + r - a - 5);
|
|
356
|
-
let c = this.imageCache.get(n);
|
|
357
|
-
c || (c = new Image(), c.src = n, this.imageCache.set(n, c), c.onload = () => this.render(), c.onerror = () => {
|
|
358
|
-
console.error(`Failed to load image: ${n}`), this.imageCache.delete(n);
|
|
359
|
-
}), c.complete && c.naturalWidth > 0 ? this.ctx.drawImage(c, e, s + (o - a) / 2, a, a) : (this.ctx.fillStyle = "#f5f7fa", this.ctx.fillRect(e, s + (o - a) / 2, a, a));
|
|
360
|
-
}
|
|
361
|
-
drawCheckboxCell(t, i, s, r, o, l) {
|
|
362
|
-
let a = i + 10;
|
|
363
|
-
l === "center" && (a = i + (r - 16) / 2), l === "right" && (a = i + r - 16 - 10);
|
|
364
|
-
const e = s + (o - 16) / 2;
|
|
365
|
-
this.ctx.strokeStyle = t ? "#409eff" : "#dcdfe6", this.ctx.fillStyle = t ? "#409eff" : "#fff", this.ctx.lineWidth = 1, this.ctx.strokeRect(a + 0.5, e + 0.5, 16, 16), t && (this.ctx.fillRect(a + 1, e + 1, 15, 15), this.ctx.strokeStyle = "#fff", this.ctx.beginPath(), this.ctx.moveTo(a + 4, e + 8), this.ctx.lineTo(a + 7, e + 11), this.ctx.lineTo(a + 12, e + 5), this.ctx.stroke());
|
|
366
|
-
}
|
|
367
|
-
drawRadioCell(t, i, s, r, o, l) {
|
|
368
|
-
let a = i + 10;
|
|
369
|
-
l === "center" && (a = i + (r - 16) / 2), l === "right" && (a = i + r - 16 - 10);
|
|
370
|
-
const e = s + (o - 16) / 2, c = a + 16 / 2, f = e + 16 / 2;
|
|
371
|
-
this.ctx.strokeStyle = t ? "#409eff" : "#dcdfe6", this.ctx.fillStyle = "#fff", this.ctx.beginPath(), this.ctx.arc(c, f, 16 / 2, 0, Math.PI * 2), this.ctx.stroke(), this.ctx.fill(), t && (this.ctx.fillStyle = "#409eff", this.ctx.beginPath(), this.ctx.arc(c, f, 16 / 4, 0, Math.PI * 2), this.ctx.fill());
|
|
372
|
-
}
|
|
373
|
-
drawSwitchCell(t, i, s, r, o, l) {
|
|
374
|
-
let e = i + 10;
|
|
375
|
-
l === "center" && (e = i + (r - 32) / 2), l === "right" && (e = i + r - 32 - 10);
|
|
376
|
-
const c = s + (o - 16) / 2;
|
|
377
|
-
this.ctx.fillStyle = t ? "#13ce66" : "#ff4949", this.ctx.beginPath(), this.ctx.roundRect?.(e, c, 32, 16, 16 / 2), this.ctx.fill(), this.ctx.fillStyle = "#fff", this.ctx.beginPath();
|
|
378
|
-
const f = t ? e + 32 - 16 + 2 : e + 2;
|
|
379
|
-
this.ctx.arc(f + 12 / 2, c + 16 / 2, 12 / 2, 0, Math.PI * 2), this.ctx.fill();
|
|
380
|
-
}
|
|
381
|
-
drawColorPickerCell(t, i, s, r, o, l) {
|
|
382
|
-
let a = i + 10;
|
|
383
|
-
l === "center" && (a = i + (r - 20) / 2), l === "right" && (a = i + r - 20 - 10);
|
|
384
|
-
const e = s + (o - 20) / 2;
|
|
385
|
-
this.ctx.fillStyle = t || "#000", this.ctx.fillRect(a, e, 20, 20), this.ctx.strokeStyle = "#dcdfe6", this.ctx.strokeRect(a + 0.5, e + 0.5, 20, 20);
|
|
386
|
-
}
|
|
387
|
-
drawTagsCell(t, i, s, r, o) {
|
|
388
|
-
if (!Array.isArray(t)) return;
|
|
389
|
-
let l = i + 5;
|
|
390
|
-
const n = 20, a = 5, e = 12;
|
|
391
|
-
t.forEach((c) => {
|
|
392
|
-
const f = String(c);
|
|
393
|
-
this.ctx.font = `${e}px sans-serif`;
|
|
394
|
-
const v = this.ctx.measureText(f).width + a * 2;
|
|
395
|
-
if (l + v > i + r - 5) return;
|
|
396
|
-
const g = s + (o - n) / 2;
|
|
397
|
-
this.ctx.fillStyle = "#ecf5ff", this.ctx.strokeStyle = "#d9ecff", this.ctx.beginPath(), this.ctx.roundRect?.(l, g, v, n, 4), this.ctx.fill(), this.ctx.stroke(), this.ctx.fillStyle = "#409eff", this.ctx.textAlign = "center", this.ctx.fillText(f, l + v / 2, g + n - e / 2), l += v + 5;
|
|
398
|
-
});
|
|
399
|
-
}
|
|
400
|
-
getCellAt(t, i) {
|
|
401
|
-
const { headerHeight: s } = this.options;
|
|
402
|
-
if (i < s) return null;
|
|
403
|
-
const { startRow: r, endRow: o } = this.getRowRange(this.height);
|
|
404
|
-
for (let l = r; l < o; l++) {
|
|
405
|
-
const n = this.data[l];
|
|
406
|
-
if (!n) continue;
|
|
407
|
-
const a = (this.rowOffsets[l] ?? 0) - this.scrollY + s, e = (this.rowOffsets[l + 1] ?? 0) - (this.rowOffsets[l] ?? 0);
|
|
408
|
-
if (i >= a && i < a + e)
|
|
409
|
-
for (let c = 0; c < this.flattenedColumns.length; c++) {
|
|
410
|
-
const f = this.flattenedColumns[c], d = (this.columnPositions[c + 1] ?? 0) - (this.columnPositions[c] ?? 0);
|
|
411
|
-
let v = 0;
|
|
412
|
-
if (f.fixed === "left" || f.fixed === !0)
|
|
413
|
-
v = this.columnPositions[c] ?? 0;
|
|
414
|
-
else if (v = (this.columnPositions[c] ?? 0) - this.scrollX, v < this.fixedLeftWidth) continue;
|
|
415
|
-
if (t >= v && t < v + d) {
|
|
416
|
-
const g = f.type === "expand", R = f.type === "selection";
|
|
417
|
-
return {
|
|
418
|
-
row: l,
|
|
419
|
-
col: c,
|
|
420
|
-
rect: { x: v, y: a, width: d, height: e },
|
|
421
|
-
column: f,
|
|
422
|
-
data: n,
|
|
423
|
-
isExpandBtn: g,
|
|
424
|
-
isSelection: R
|
|
425
|
-
};
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
return null;
|
|
430
|
-
}
|
|
431
|
-
getRowOffsets() {
|
|
432
|
-
return this.rowOffsets;
|
|
433
|
-
}
|
|
434
|
-
getScrollX() {
|
|
435
|
-
return this.scrollX;
|
|
436
|
-
}
|
|
437
|
-
getScrollY() {
|
|
438
|
-
return this.scrollY;
|
|
439
|
-
}
|
|
440
|
-
getFixedLeftWidth() {
|
|
441
|
-
return this.fixedLeftWidth;
|
|
442
|
-
}
|
|
443
|
-
getTotalWidth() {
|
|
444
|
-
return this.totalWidth;
|
|
445
|
-
}
|
|
446
|
-
getTotalHeight() {
|
|
447
|
-
return this.totalHeight;
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
const St = ["onClick"], bt = { class: "icon" }, kt = { class: "label" }, Ht = { class: "edit-dialog-content" }, Et = /* @__PURE__ */ J({
|
|
451
|
-
__name: "CanvasTable",
|
|
452
|
-
props: {
|
|
453
|
-
columns: {},
|
|
454
|
-
data: {},
|
|
455
|
-
options: {}
|
|
456
|
-
},
|
|
457
|
-
emits: ["update:data", "select-change", "header-command"],
|
|
458
|
-
setup(X, { emit: t }) {
|
|
459
|
-
const i = J({
|
|
460
|
-
props: ["vnode"],
|
|
461
|
-
setup(h) {
|
|
462
|
-
return () => h.vnode;
|
|
463
|
-
}
|
|
464
|
-
}), s = X, r = t, o = k(null), l = k(null), n = k(null), a = k(null), e = vt(null), c = k(0), f = k(0), d = k(0), v = k(0), g = k(0), R = k(0), y = k(null), C = k(null), S = k(null), w = k(/* @__PURE__ */ new Set()), L = k(/* @__PURE__ */ new Set()), b = k(null), Y = M(() => ({
|
|
465
|
-
width: "100%",
|
|
466
|
-
height: "100%",
|
|
467
|
-
position: "relative",
|
|
468
|
-
overflow: "hidden"
|
|
469
|
-
})), Z = M(() => ({
|
|
470
|
-
position: "absolute",
|
|
471
|
-
top: 0,
|
|
472
|
-
left: 0,
|
|
473
|
-
pointerEvents: "none",
|
|
474
|
-
width: "100%",
|
|
475
|
-
height: "100%"
|
|
476
|
-
})), j = M(() => {
|
|
477
|
-
if (!y.value) return {};
|
|
478
|
-
const { rect: h } = y.value;
|
|
479
|
-
return {
|
|
480
|
-
position: "absolute",
|
|
481
|
-
left: `${h.x + h.width - 24}px`,
|
|
482
|
-
top: `${h.y + (h.height - 20) / 2}px`,
|
|
483
|
-
pointerEvents: "auto"
|
|
484
|
-
};
|
|
485
|
-
}), tt = M(() => {
|
|
486
|
-
if (!C.value || !l.value) return {};
|
|
487
|
-
const h = l.value.getBoundingClientRect(), { rect: x } = C.value;
|
|
488
|
-
let u = h.top + x.y + x.height + 5, m = h.left + x.x;
|
|
489
|
-
const p = 300;
|
|
490
|
-
return m + p > window.innerWidth && (m = window.innerWidth - p - 20), {
|
|
491
|
-
position: "fixed",
|
|
492
|
-
top: `${u}px`,
|
|
493
|
-
left: `${m}px`,
|
|
494
|
-
zIndex: 2e3,
|
|
495
|
-
pointerEvents: "auto"
|
|
496
|
-
};
|
|
497
|
-
}), et = M(() => {
|
|
498
|
-
if (!b.value) return {};
|
|
499
|
-
const { rect: h } = b.value;
|
|
500
|
-
return {
|
|
501
|
-
position: "absolute",
|
|
502
|
-
left: `${h.x + h.width - 120}px`,
|
|
503
|
-
top: `${h.y + h.height}px`,
|
|
504
|
-
pointerEvents: "auto"
|
|
505
|
-
};
|
|
506
|
-
}), st = M(() => {
|
|
507
|
-
if (!b.value) return [];
|
|
508
|
-
const { column: h } = b.value, x = [
|
|
509
|
-
{
|
|
510
|
-
label: "Fix to Left",
|
|
511
|
-
onCommand: (u) => {
|
|
512
|
-
const m = s.columns.findIndex((p) => p.key === u.key);
|
|
513
|
-
s.columns.forEach((p, E) => {
|
|
514
|
-
E <= m && (p.fixed = "left");
|
|
515
|
-
}), e.value?.setColumns(s.columns);
|
|
516
|
-
}
|
|
517
|
-
},
|
|
518
|
-
{
|
|
519
|
-
label: "Unfix",
|
|
520
|
-
onCommand: (u) => {
|
|
521
|
-
u.fixed = !1, e.value?.setColumns(s.columns);
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
];
|
|
525
|
-
return h.renderHeaderMenu ? h.renderHeaderMenu(h, x) : x;
|
|
526
|
-
}), it = (h) => {
|
|
527
|
-
b.value && (h.onCommand(b.value.column), b.value = null);
|
|
528
|
-
}, K = (h) => {
|
|
529
|
-
if (!l.value || !e.value) return;
|
|
530
|
-
const x = l.value.getBoundingClientRect(), u = h.clientX - x.left, m = h.clientY - x.top, p = e.value.getHeaderAt(u, m);
|
|
531
|
-
if (p) {
|
|
532
|
-
const E = s.columns.findIndex((W) => W.key === p.column.key);
|
|
533
|
-
e.value.setHoverHeader(E), p.isMenu || p.column.type === "selection" ? l.value.style.cursor = "pointer" : l.value.style.cursor = "default";
|
|
534
|
-
} else
|
|
535
|
-
e.value.setHoverHeader(-1), l.value.style.cursor = "default";
|
|
536
|
-
y.value = e.value.getCellAt(u, m), y.value && (y.value.isExpandBtn || y.value.isSelection) && (l.value.style.cursor = "pointer");
|
|
537
|
-
}, V = (h) => {
|
|
538
|
-
if (!l.value || !e.value) return;
|
|
539
|
-
const x = l.value.getBoundingClientRect(), u = h.clientX - x.left, m = h.clientY - x.top, p = e.value.getHeaderAt(u, m);
|
|
540
|
-
if (p) {
|
|
541
|
-
p.isMenu ? b.value = { column: p.column, rect: p.rect } : p.column.type === "selection" && (w.value.size === s.data.length ? w.value.clear() : s.data.forEach((xt) => w.value.add(xt.id)), e.value.setSelectedRows(Array.from(w.value)), r("select-change", Array.from(w.value)));
|
|
542
|
-
return;
|
|
543
|
-
}
|
|
544
|
-
const E = e.value.getCellAt(u, m);
|
|
545
|
-
if (E) {
|
|
546
|
-
if (E.isExpandBtn) {
|
|
547
|
-
lt(E.data.id);
|
|
548
|
-
return;
|
|
549
|
-
}
|
|
550
|
-
const W = E.data.id;
|
|
551
|
-
if (E.isSelection) {
|
|
552
|
-
w.value.has(W) ? w.value.delete(W) : w.value.add(W), e.value.setSelectedRows(Array.from(w.value)), r("select-change", Array.from(w.value));
|
|
553
|
-
return;
|
|
554
|
-
}
|
|
555
|
-
s.options?.multiSelect ? w.value.has(W) ? w.value.delete(W) : w.value.add(W) : (w.value.clear(), w.value.add(W)), r("select-change", Array.from(w.value));
|
|
556
|
-
}
|
|
557
|
-
}, N = (h) => {
|
|
558
|
-
if (!l.value || !e.value) return;
|
|
559
|
-
const x = l.value.getBoundingClientRect(), u = h.clientX - x.left, m = h.clientY - x.top, p = e.value.getCellAt(u, m);
|
|
560
|
-
p && p.column.renderEdit && F(p);
|
|
561
|
-
}, F = (h) => {
|
|
562
|
-
C.value = h, S.value = JSON.parse(JSON.stringify(h.data));
|
|
563
|
-
}, lt = (h) => {
|
|
564
|
-
L.value.has(h) ? L.value.delete(h) : L.value.add(h), e.value?.setExpandedRows(Array.from(L.value)), $();
|
|
565
|
-
}, A = () => {
|
|
566
|
-
C.value = null, S.value = null;
|
|
567
|
-
}, nt = () => {
|
|
568
|
-
if (C.value && S.value) {
|
|
569
|
-
const h = C.value.data.id, x = s.data.findIndex((u) => u.id === h);
|
|
570
|
-
if (x !== -1) {
|
|
571
|
-
const u = [...s.data];
|
|
572
|
-
u[x] = S.value, r("update:data", u), e.value?.setData(u);
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
A();
|
|
576
|
-
}, ot = (h) => !h.column.renderEdit || !S.value ? null : h.column.renderEdit(S.value, (x, u, m) => u && (typeof u == "string" || Array.isArray(u) || u.__v_isVNode) ? B(x, null, u) : B(x, u, m)), rt = (h) => {
|
|
577
|
-
if (!e.value) return {};
|
|
578
|
-
const x = s.data.findIndex((W) => W.id === h);
|
|
579
|
-
if (x === -1) return {};
|
|
580
|
-
const u = e.value.getRowOffsets(), m = (u[x] ?? 0) - R.value + (s.options?.headerHeight || 48), p = (u[x + 1] ?? 0) - (u[x] ?? 0) - (s.options?.rowHeight || 40), E = e.value.getFixedLeftWidth();
|
|
581
|
-
return {
|
|
582
|
-
position: "absolute",
|
|
583
|
-
top: `${m + (s.options?.rowHeight || 40)}px`,
|
|
584
|
-
left: `${E}px`,
|
|
585
|
-
width: `${d.value - E}px`,
|
|
586
|
-
height: `${p}px`,
|
|
587
|
-
pointerEvents: "auto",
|
|
588
|
-
overflow: "hidden",
|
|
589
|
-
backgroundColor: "#fff",
|
|
590
|
-
borderBottom: "1px solid #ebeef5",
|
|
591
|
-
// Sync inner scrolling content
|
|
592
|
-
display: "flex"
|
|
593
|
-
};
|
|
594
|
-
}, at = () => ({
|
|
595
|
-
marginLeft: `-${g.value}px`,
|
|
596
|
-
minWidth: `${c.value - e.value?.getFixedLeftWidth()}px`
|
|
597
|
-
}), ct = (h) => {
|
|
598
|
-
const x = s.data.find((u) => u.id === h);
|
|
599
|
-
return !x || !s.options?.renderExpand ? null : B("div", { style: at() }, [
|
|
600
|
-
s.options.renderExpand(x, (u, m, p) => m && (typeof m == "string" || Array.isArray(m) || m.__v_isVNode) ? B(u, null, m) : B(u, m, p))
|
|
601
|
-
]);
|
|
602
|
-
}, ht = (h) => {
|
|
603
|
-
const x = h.target;
|
|
604
|
-
g.value = x.scrollLeft, e.value?.scrollTo(g.value, R.value), y.value = null;
|
|
605
|
-
}, dt = (h) => {
|
|
606
|
-
const x = h.target;
|
|
607
|
-
R.value = x.scrollTop, e.value?.scrollTo(g.value, R.value), y.value = null;
|
|
608
|
-
}, ft = (h) => {
|
|
609
|
-
if (!a.value || !n.value) return;
|
|
610
|
-
const x = h.deltaY, u = h.shiftKey ? h.deltaY : h.deltaX;
|
|
611
|
-
a.value.scrollTop += x, n.value.scrollLeft += u;
|
|
612
|
-
}, ut = (h) => {
|
|
613
|
-
const x = h[0];
|
|
614
|
-
if (!x || !e.value) return;
|
|
615
|
-
const { width: u, height: m } = x.contentRect;
|
|
616
|
-
d.value = u, v.value = m, e.value.resize(u, m), $();
|
|
617
|
-
}, $ = () => {
|
|
618
|
-
e.value && (c.value = e.value.getTotalWidth(), f.value = e.value.getTotalHeight());
|
|
619
|
-
};
|
|
620
|
-
let _ = null;
|
|
621
|
-
return gt(() => {
|
|
622
|
-
l.value && (e.value = new Rt(l.value), e.value.setColumns(s.columns), e.value.setData(s.data), e.value.setOptions(s.options || {}), $(), _ = new ResizeObserver(ut), o.value && _.observe(o.value), l.value.addEventListener("mousemove", K), l.value.addEventListener("mousedown", V), l.value.addEventListener("dblclick", N));
|
|
623
|
-
}), mt(() => {
|
|
624
|
-
_?.disconnect(), l.value?.removeEventListener("mousemove", K), l.value?.removeEventListener("mousedown", V), l.value?.removeEventListener("dblclick", N), e.value?.destroy(), e.value = null;
|
|
625
|
-
}), O(() => s.columns, (h) => {
|
|
626
|
-
e.value?.setColumns(h), $();
|
|
627
|
-
}, { deep: !0 }), O(() => s.data, (h) => {
|
|
628
|
-
e.value?.setData(h), $();
|
|
629
|
-
}, { deep: !0 }), O(() => s.options, (h) => {
|
|
630
|
-
h && e.value?.setOptions(h);
|
|
631
|
-
}, { deep: !0 }), (h, x) => (P(), z("div", {
|
|
632
|
-
class: "canvas-table-container",
|
|
633
|
-
ref_key: "containerRef",
|
|
634
|
-
ref: o
|
|
635
|
-
}, [
|
|
636
|
-
H("div", {
|
|
637
|
-
class: "canvas-wrapper",
|
|
638
|
-
style: T(Y.value),
|
|
639
|
-
onWheel: D(ft, ["prevent"])
|
|
640
|
-
}, [
|
|
641
|
-
H("canvas", {
|
|
642
|
-
ref_key: "canvasRef",
|
|
643
|
-
ref: l
|
|
644
|
-
}, null, 512),
|
|
645
|
-
H("div", {
|
|
646
|
-
class: "scrollbar horizontal",
|
|
647
|
-
ref_key: "hScrollRef",
|
|
648
|
-
ref: n,
|
|
649
|
-
onScroll: ht
|
|
650
|
-
}, [
|
|
651
|
-
H("div", {
|
|
652
|
-
style: T({ width: c.value + "px", height: "1px" })
|
|
653
|
-
}, null, 4)
|
|
654
|
-
], 544),
|
|
655
|
-
H("div", {
|
|
656
|
-
class: "scrollbar vertical",
|
|
657
|
-
ref_key: "vScrollRef",
|
|
658
|
-
ref: a,
|
|
659
|
-
onScroll: dt
|
|
660
|
-
}, [
|
|
661
|
-
H("div", {
|
|
662
|
-
style: T({ height: f.value + "px", width: "1px" })
|
|
663
|
-
}, null, 4)
|
|
664
|
-
], 544),
|
|
665
|
-
H("div", {
|
|
666
|
-
class: "table-overlays",
|
|
667
|
-
style: T(Z.value)
|
|
668
|
-
}, [
|
|
669
|
-
y.value && y.value.column.renderEdit ? (P(), z("div", {
|
|
670
|
-
key: 0,
|
|
671
|
-
class: "edit-btn",
|
|
672
|
-
style: T(j.value),
|
|
673
|
-
onClick: x[0] || (x[0] = D((u) => F(y.value), ["stop"]))
|
|
674
|
-
}, [...x[2] || (x[2] = [
|
|
675
|
-
H("svg", {
|
|
676
|
-
viewBox: "0 0 24 24",
|
|
677
|
-
width: "14",
|
|
678
|
-
height: "14"
|
|
679
|
-
}, [
|
|
680
|
-
H("path", {
|
|
681
|
-
fill: "currentColor",
|
|
682
|
-
d: "M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"
|
|
683
|
-
})
|
|
684
|
-
], -1)
|
|
685
|
-
])], 4)) : I("", !0),
|
|
686
|
-
b.value ? (P(), z("div", {
|
|
687
|
-
key: 1,
|
|
688
|
-
class: "header-menu-overlay",
|
|
689
|
-
onClick: x[1] || (x[1] = D((u) => b.value = null, ["self"]))
|
|
690
|
-
}, [
|
|
691
|
-
H("div", {
|
|
692
|
-
class: "header-menu",
|
|
693
|
-
style: T(et.value)
|
|
694
|
-
}, [
|
|
695
|
-
(P(!0), z(U, null, q(st.value, (u) => (P(), z("div", {
|
|
696
|
-
key: u.label,
|
|
697
|
-
class: "menu-item",
|
|
698
|
-
onClick: (m) => it(u)
|
|
699
|
-
}, [
|
|
700
|
-
H("span", bt, G(u.icon || "•"), 1),
|
|
701
|
-
H("span", kt, G(u.label), 1)
|
|
702
|
-
], 8, St))), 128))
|
|
703
|
-
], 4)
|
|
704
|
-
])) : I("", !0),
|
|
705
|
-
(P(!0), z(U, null, q(L.value, (u) => (P(), z("div", {
|
|
706
|
-
key: u,
|
|
707
|
-
class: "expand-row-overlay",
|
|
708
|
-
style: T(rt(u))
|
|
709
|
-
}, [
|
|
710
|
-
(P(), Q(wt(ct(u))))
|
|
711
|
-
], 4))), 128)),
|
|
712
|
-
(P(), Q(pt, { to: "body" }, [
|
|
713
|
-
C.value ? (P(), z("div", {
|
|
714
|
-
key: 0,
|
|
715
|
-
class: "edit-dialog-popover",
|
|
716
|
-
style: T(tt.value)
|
|
717
|
-
}, [
|
|
718
|
-
H("div", Ht, [
|
|
719
|
-
yt(Ct(i), {
|
|
720
|
-
vnode: ot(C.value)
|
|
721
|
-
}, null, 8, ["vnode"])
|
|
722
|
-
]),
|
|
723
|
-
H("div", { class: "edit-dialog-footer" }, [
|
|
724
|
-
H("button", {
|
|
725
|
-
class: "small",
|
|
726
|
-
onClick: A
|
|
727
|
-
}, "Cancel"),
|
|
728
|
-
H("button", {
|
|
729
|
-
class: "small primary",
|
|
730
|
-
onClick: nt
|
|
731
|
-
}, "Save")
|
|
732
|
-
])
|
|
733
|
-
], 4)) : I("", !0),
|
|
734
|
-
C.value ? (P(), z("div", {
|
|
735
|
-
key: 1,
|
|
736
|
-
class: "popover-click-mask",
|
|
737
|
-
onClick: A
|
|
738
|
-
})) : I("", !0)
|
|
739
|
-
]))
|
|
740
|
-
], 4)
|
|
741
|
-
], 36)
|
|
742
|
-
], 512));
|
|
743
|
-
}
|
|
744
|
-
}), Wt = (X, t) => {
|
|
745
|
-
const i = X.__vccOpts || X;
|
|
746
|
-
for (const [s, r] of t)
|
|
747
|
-
i[s] = r;
|
|
748
|
-
return i;
|
|
749
|
-
}, Pt = /* @__PURE__ */ Wt(Et, [["__scopeId", "data-v-34fbfef2"]]);
|
|
750
|
-
export {
|
|
751
|
-
Rt as CanvasRenderer,
|
|
752
|
-
Pt as CanvasTable
|
|
753
|
-
};
|
package/dist/index.umd.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(function(L,s){typeof exports=="object"&&typeof module<"u"?s(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],s):(L=typeof globalThis<"u"?globalThis:L||self,s(L.DrawTable={},L.Vue))})(this,(function(L,s){"use strict";class X{ctx;canvas;columns=[];data=[];options={rowHeight:40,headerHeight:48,border:!0,stripe:!0,multiSelect:!1,fixedHeader:!0,renderExpand:()=>null,spanMethod:()=>{}};scrollX=0;scrollY=0;width=0;height=0;columnPositions=[];rowOffsets=[];totalWidth=0;totalHeight=0;fixedLeftWidth=0;summaryRows=[];expandedRowKeys=new Set;selectedRowKeys=new Set;imageCache=new Map;hoverHeaderIndex=-1;flattenedColumns=[];columnLevels=0;constructor(t){this.canvas=t;const l=t.getContext("2d");if(!l)throw new Error("Could not get canvas context");this.ctx=l}destroy(){this.imageCache.forEach(t=>{t.onload=null,t.onerror=null,t.src=""}),this.imageCache.clear(),this.data=[],this.columns=[],this.summaryRows=[]}setExpandedRows(t){this.expandedRowKeys=new Set(t),this.calculateLayout(),this.render()}setData(t){this.data=t,this.calculateLayout(),this.render()}setColumns(t){this.columns=t,this.flattenColumns(),this.calculateLayout(),this.render()}flattenColumns(){this.flattenedColumns=[],this.columnLevels=0;const t=(i,c=0)=>{this.columnLevels=Math.max(this.columnLevels,c+1),i.forEach(r=>{r.children&&r.children.length>0?t(r.children,c+1):this.flattenedColumns.push(r)})};t(this.columns);const l=40;this.columnLevels>1?this.options.headerHeight=this.columnLevels*l:this.options.headerHeight=48}setOptions(t){this.options={...this.options,...t},this.calculateLayout(),this.render()}resize(t,l){this.width=t,this.height=l;const i=window.devicePixelRatio||1;this.canvas.width=t*i,this.canvas.height=l*i,this.canvas.style.width=`${t}px`,this.canvas.style.height=`${l}px`,this.ctx.resetTransform(),this.ctx.scale(i,i),this.render()}scrollTo(t,l){this.scrollX=t,this.scrollY=l,this.render()}calculateLayout(){let t=0;this.columnPositions=[0];let l=0;this.flattenedColumns.forEach(r=>{const n=r.width||100;t+=n,this.columnPositions.push(t),(r.fixed==="left"||r.fixed===!0)&&(l=t)}),this.totalWidth=t,this.fixedLeftWidth=l;let i=0;this.rowOffsets=[0];const{rowHeight:c}=this.options;this.data.forEach(r=>{i+=c,this.expandedRowKeys.has(r.id)&&(i+=c*3),this.rowOffsets.push(i)}),this.totalHeight=i,this.calculateSummaries()}getRowRange(t=20){const{headerHeight:l}=this.options,i=this.summaryRows.length*this.options.rowHeight,c=this.height-l-i,r=this.scrollY,n=r+c;let o=0;for(;o<this.rowOffsets.length&&(this.rowOffsets[o+1]??0)<r;)o++;let a=o;for(;a<this.rowOffsets.length&&(this.rowOffsets[a]??0)<n;)a++;return{startRow:Math.max(0,o-t),endRow:Math.min(this.data.length,a+1)}}calculateSummaries(){this.summaryRows=[];const t=new Map;this.flattenedColumns.forEach((l,i)=>{l.summary&&l.summary.forEach(c=>{try{const r=c(this.data);if(r&&r.label){const{label:n,value:o}=r;t.has(n)||t.set(n,new Array(this.flattenedColumns.length).fill("")),t.get(n)[i]=o}}catch(r){console.error("Summary calculation error:",r)}})}),t.forEach((l,i)=>{l[0]=i,this.summaryRows.push(l)})}render(){this.ctx.clearRect(0,0,this.width,this.height),this.drawBody(),this.drawFixedLeftBody(),this.drawHeader(),this.drawSummaryRows()}getColumnWidth(t){return t.children&&t.children.length>0?t.children.reduce((i,c)=>i+this.getColumnWidth(c),0):t.width||100}isColumnFixed(t){return t.fixed==="left"||t.fixed==="right"||t.fixed===!0?!0:t.children&&t.children.length>0?t.children.some(l=>this.isColumnFixed(l)):!1}drawHeader(){const{headerHeight:t}=this.options,l=this.columnLevels>1?40:t;this.ctx.save(),this.ctx.fillStyle="#f5f7fa",this.ctx.fillRect(0,0,this.width,t);const i=(c,r,n,o,a)=>{let e=r;c.forEach(h=>{const u=this.getColumnWidth(h),f=this.isColumnFixed(h);if(a!==f){e+=u;return}const g=!h.children||h.children.length===0,p=g?(this.columnLevels-o)*l:l,S=a?e:e-this.scrollX;(a||S+u>this.fixedLeftWidth&&S<this.width)&&(a||(this.ctx.save(),this.ctx.beginPath(),this.ctx.rect(this.fixedLeftWidth,0,this.width-this.fixedLeftWidth,t),this.ctx.clip()),this.drawHeaderCell(h,S,u,p,n,g),a||this.ctx.restore()),h.children&&h.children.length>0&&i(h.children,e,n+l,o+1,a),e+=u})};i(this.columns,0,0,0,!1),i(this.columns,0,0,0,!0),this.ctx.restore()}setHoverHeader(t){this.hoverHeaderIndex!==t&&(this.hoverHeaderIndex=t,this.render())}setSelectedRows(t){this.selectedRowKeys=new Set(t),this.render()}drawHeaderCell(t,l,i,c,r,n){if(this.ctx.save(),this.ctx.beginPath(),this.ctx.rect(l,r,i,c),this.ctx.clip(),this.ctx.fillStyle="#f5f7fa",this.ctx.fillRect(l,r,i,c),this.options.border&&(this.ctx.strokeStyle="#ebeef5",this.ctx.lineWidth=1,this.ctx.strokeRect(l+.5,r+.5,i,c)),t.type==="selection"){const o=this.data.length>0&&this.selectedRowKeys.size===this.data.length;this.drawCheckboxCell(o,l,r,i,c,"center")}else{this.ctx.fillStyle="#303133",this.ctx.font="bold 14px sans-serif",this.ctx.textBaseline="middle";const o=t.align||(n?"left":"center");this.ctx.textAlign=o;let a=l+10;o==="center"&&(a=l+i/2),o==="right"&&(a=l+i-24);const e=t.title||"";if(this.ctx.fillText(e,a,r+c/2),n&&t.type!=="selection"&&t.type!=="expand"){const h=this.flattenedColumns.indexOf(t);if(this.hoverHeaderIndex===h){this.ctx.fillStyle="#909399",this.ctx.beginPath();const u=l+i-18,f=r+c/2;this.ctx.arc(u,f-4,1.5,0,Math.PI*2),this.ctx.arc(u,f,1.5,0,Math.PI*2),this.ctx.arc(u,f+4,1.5,0,Math.PI*2),this.ctx.fill()}}}this.ctx.restore()}getHeaderAt(t,l){const{headerHeight:i}=this.options;if(l>i)return null;const c=this.columnLevels>1?40:i,r=(o,a,e,h)=>{let u=a;for(const f of o){const g=this.isColumnFixed(f);if(h!==g){u+=this.getColumnWidth(f);continue}const p=this.getColumnWidth(f),S=!f.children||f.children.length===0,C=S?(this.columnLevels-e)*c:c,k=e*c,R=h?u:u-this.scrollX;if(!h&&R<this.fixedLeftWidth){u+=p;continue}if(t>=R&&t<R+p&&l>=k&&l<k+C){const y=S&&f.type!=="selection"&&f.type!=="expand"&&t>=R+p-24;return{column:f,rect:{x:R,y:k,width:p,height:C},isMenu:y}}if(f.children&&f.children.length>0){const y=r(f.children,u,e+1,h);if(y)return y}u+=p}return null},n=r(this.columns,0,0,!0);return n||r(this.columns,0,0,!1)}drawBody(){const{headerHeight:t}=this.options,{startRow:l,endRow:i}=this.getRowRange(this.height),c=this.summaryRows.length*this.options.rowHeight;this.ctx.save(),this.ctx.beginPath(),this.ctx.rect(this.fixedLeftWidth,t,this.width-this.fixedLeftWidth,this.height-t-c),this.ctx.clip();const r=new Set,n=[];for(let o=l;o<i;o++){const a=this.data[o];if(!a)continue;const e=(this.rowOffsets[o]??0)-this.scrollY+t,h=(this.rowOffsets[o+1]??0)-(this.rowOffsets[o]??0),u=o%2===1&&this.options.stripe?"#fafafa":"#fff";if(this.flattenedColumns.forEach((f,g)=>{if(f.fixed==="left"||f.fixed===!0||r.has(`${o},${g}`))return;const p=(this.columnPositions[g]??0)-this.scrollX,S=(this.columnPositions[g+1]??0)-(this.columnPositions[g]??0),C=this.options.spanMethod({row:o,column:f,rowIndex:o,columnIndex:g});if(C){const{rowspan:k,colspan:R}=C;if(k===0||R===0)return;const y=(this.columnPositions[g+R]??this.totalWidth)-(this.columnPositions[g]??0),W=(this.rowOffsets[o+k]??this.totalHeight)-(this.rowOffsets[o]??0);for(let b=0;b<k;b++)for(let P=0;P<R;P++)r.add(`${o+b},${g+P}`);n.push({col:f,val:a[f.key||""],x:p,y:e,w:y,h:W,r:o,c:g,bgColor:u})}else this.ctx.fillStyle=u,this.ctx.fillRect(p,e,S,this.options.rowHeight),this.drawCell(f,a[f.key||""],p,e,S,this.options.rowHeight,o),this.options.border&&(this.ctx.strokeStyle="#ebeef5",this.ctx.strokeRect(p+.5,e+.5,S,this.options.rowHeight))}),this.expandedRowKeys.has(a.id)){const f=e+this.options.rowHeight,g=h-this.options.rowHeight;this.ctx.fillStyle="#fdfdfd",this.ctx.fillRect(0,f,this.width,g),this.options.border&&(this.ctx.strokeStyle="#ebeef5",this.ctx.beginPath(),this.ctx.moveTo(0,f),this.ctx.lineTo(this.width,f),this.ctx.stroke()),this.drawExpandPlaceholder(a,this.fixedLeftWidth-this.scrollX,f,this.totalWidth-this.fixedLeftWidth,g)}}n.forEach(({col:o,val:a,x:e,y:h,w:u,h:f,r:g,bgColor:p})=>{this.ctx.fillStyle=p,this.ctx.fillRect(e,h,u,f),this.drawCell(o,a,e,h,u,f,g),this.options.border&&(this.ctx.strokeStyle="#ebeef5",this.ctx.strokeRect(e+.5,h+.5,u,f))}),this.ctx.restore()}drawFixedLeftBody(){const{headerHeight:t}=this.options,{startRow:l,endRow:i}=this.getRowRange(this.height),c=this.summaryRows.length*this.options.rowHeight;this.ctx.save(),this.ctx.beginPath(),this.ctx.rect(0,t,this.fixedLeftWidth,this.height-t-c),this.ctx.clip();const r=new Set,n=[];for(let o=l;o<i;o++){const a=this.data[o];if(!a)continue;const e=(this.rowOffsets[o]??0)-this.scrollY+t,h=o%2===1&&this.options.stripe?"#fafafa":"#fff";this.flattenedColumns.forEach((u,f)=>{if(!(u.fixed==="left"||u.fixed===!0)||r.has(`${o},${f}`))return;const g=this.columnPositions[f]??0,p=(this.columnPositions[f+1]??0)-(this.columnPositions[f]??0),S=this.options.spanMethod({row:o,column:u,rowIndex:o,columnIndex:f});if(S){const{rowspan:C,colspan:k}=S;if(C===0||k===0)return;const R=(this.columnPositions[f+k]??this.fixedLeftWidth)-(this.columnPositions[f]??0),y=(this.rowOffsets[o+C]??this.totalHeight)-(this.rowOffsets[o]??0);for(let W=0;W<C;W++)for(let b=0;b<k;b++)r.add(`${o+W},${f+b}`);n.push({col:u,val:a[u.key||""],x:g,y:e,w:R,h:y,r:o,c:f,bgColor:h})}else this.ctx.fillStyle=h,this.ctx.fillRect(g,e,p,this.options.rowHeight),this.drawCell(u,a[u.key||""],g,e,p,this.options.rowHeight,o),this.options.border&&(this.ctx.strokeStyle="#ebeef5",this.ctx.strokeRect(g+.5,e+.5,p,this.options.rowHeight))})}n.forEach(({col:o,val:a,x:e,y:h,w:u,h:f,r:g,bgColor:p})=>{this.ctx.fillStyle=p,this.ctx.fillRect(e,h,u,f),this.drawCell(o,a,e,h,u,f,g),this.options.border&&(this.ctx.strokeStyle="#ebeef5",this.ctx.strokeRect(e+.5,h+.5,u,f))}),this.ctx.restore()}drawExpandPlaceholder(t,l,i,c,r){this.ctx.save(),this.ctx.fillStyle="#fef0f0",this.ctx.fillRect(l,i,c,r),this.ctx.fillStyle="#f56c6c",this.ctx.font="italic 12px sans-serif",this.ctx.textAlign="center",this.ctx.fillText(`Expanded content for row ${t.id} (Rendered via h function in overlay)`,l+c/2,i+r/2),this.ctx.restore()}drawSummaryRows(){if(this.summaryRows.length===0)return;const{rowHeight:t}=this.options,l=this.summaryRows.length*t,i=this.height-l;this.ctx.save(),this.ctx.fillStyle="#fdf6ec",this.ctx.fillRect(0,i,this.width,l);let c=0;for(let r=0;r<this.flattenedColumns.length;r++){const n=this.flattenedColumns[r];if(n&&(n.type==="selection"||n.type==="expand"||n.key==="id"))c++;else break}c===0&&(c=1),this.summaryRows.forEach((r,n)=>{const o=i+n*t;this.ctx.save(),this.ctx.beginPath(),this.ctx.rect(this.fixedLeftWidth,o,this.width-this.fixedLeftWidth,t),this.ctx.clip(),this.flattenedColumns.forEach((a,e)=>{if(a.fixed==="left"||a.fixed===!0||e<c)return;const h=(this.columnPositions[e]??0)-this.scrollX,u=(this.columnPositions[e+1]??0)-(this.columnPositions[e]??0);this.drawTextCell(r[e],h,o,u,t,a.align),this.options.border&&(this.ctx.strokeStyle="#ebeef5",this.ctx.strokeRect(h+.5,o+.5,u,t))}),this.ctx.restore(),this.flattenedColumns.forEach((a,e)=>{if(a.fixed==="left"||a.fixed===!0){const h=this.columnPositions[e]??0,u=(this.columnPositions[e+1]??0)-(this.columnPositions[e]??0);if(e===0){const f=(this.columnPositions[c]??this.fixedLeftWidth)-(this.columnPositions[0]??0);this.ctx.save(),this.ctx.font="bold 13px sans-serif",this.ctx.fillStyle="#e6a23c",this.drawTextCell(r[0],h,o,f,t,"center"),this.ctx.restore(),this.options.border&&(this.ctx.strokeStyle="#ebeef5",this.ctx.strokeRect(h+.5,o+.5,f,t))}else{if(e<c)return;this.drawTextCell(r[e],h,o,u,t,a.align),this.options.border&&(this.ctx.strokeStyle="#ebeef5",this.ctx.strokeRect(h+.5,o+.5,u,t))}}})}),this.ctx.restore()}drawCell(t,l,i,c,r,n,o){if(this.ctx.save(),this.ctx.beginPath(),this.ctx.rect(i,c,r,n),this.ctx.clip(),t.renderCell)this.drawTextCell(l,i,c,r,n,t.align);else switch(t.type){case"expand":this.drawExpandButton(i+(r-16)/2,c+(this.options.rowHeight-16)/2,this.expandedRowKeys.has(this.data[o]?.id??""));break;case"selection":const a=this.selectedRowKeys.has(this.data[o]?.id??"");this.drawCheckboxCell(a,i,c,r,this.options.rowHeight,"center");break;case"image":this.drawImageCell(l,i,c,r,n,t.align);break;case"checkbox":this.drawCheckboxCell(l,i,c,r,n,t.align);break;case"radio":this.drawRadioCell(l,i,c,r,n,t.align);break;case"switch":this.drawSwitchCell(l,i,c,r,n,t.align);break;case"color-picker":this.drawColorPickerCell(l,i,c,r,n,t.align);break;case"tags":this.drawTagsCell(l,i,c,r,n);break;default:this.drawTextCell(l,i,c,r,n,t.align);break}this.ctx.restore()}drawExpandButton(t,l,i){this.ctx.save(),this.ctx.translate(t+8,l+8),i&&this.ctx.rotate(Math.PI/2),this.ctx.strokeStyle="#909399",this.ctx.lineWidth=2,this.ctx.beginPath(),this.ctx.moveTo(-3,-5),this.ctx.lineTo(3,0),this.ctx.lineTo(-3,5),this.ctx.stroke(),this.ctx.restore()}drawTextCell(t,l,i,c,r,n){this.ctx.fillStyle="#606266",this.ctx.font="14px sans-serif",this.ctx.textAlign=n||"left",this.ctx.textBaseline="middle";let o=l+10;n==="center"&&(o=l+c/2),n==="right"&&(o=l+c-10);const a=t==null?"":String(t);this.ctx.fillText(a,o,i+r/2)}drawImageCell(t,l,i,c,r,n){if(!t)return;const o=String(t),a=Math.min(c,r)-10;let e=l+5;n==="center"&&(e=l+(c-a)/2),n==="right"&&(e=l+c-a-5);let h=this.imageCache.get(o);h||(h=new Image,h.src=o,this.imageCache.set(o,h),h.onload=()=>this.render(),h.onerror=()=>{console.error(`Failed to load image: ${o}`),this.imageCache.delete(o)}),h.complete&&h.naturalWidth>0?this.ctx.drawImage(h,e,i+(r-a)/2,a,a):(this.ctx.fillStyle="#f5f7fa",this.ctx.fillRect(e,i+(r-a)/2,a,a))}drawCheckboxCell(t,l,i,c,r,n){let a=l+10;n==="center"&&(a=l+(c-16)/2),n==="right"&&(a=l+c-16-10);const e=i+(r-16)/2;this.ctx.strokeStyle=t?"#409eff":"#dcdfe6",this.ctx.fillStyle=t?"#409eff":"#fff",this.ctx.lineWidth=1,this.ctx.strokeRect(a+.5,e+.5,16,16),t&&(this.ctx.fillRect(a+1,e+1,15,15),this.ctx.strokeStyle="#fff",this.ctx.beginPath(),this.ctx.moveTo(a+4,e+8),this.ctx.lineTo(a+7,e+11),this.ctx.lineTo(a+12,e+5),this.ctx.stroke())}drawRadioCell(t,l,i,c,r,n){let a=l+10;n==="center"&&(a=l+(c-16)/2),n==="right"&&(a=l+c-16-10);const e=i+(r-16)/2,h=a+16/2,u=e+16/2;this.ctx.strokeStyle=t?"#409eff":"#dcdfe6",this.ctx.fillStyle="#fff",this.ctx.beginPath(),this.ctx.arc(h,u,16/2,0,Math.PI*2),this.ctx.stroke(),this.ctx.fill(),t&&(this.ctx.fillStyle="#409eff",this.ctx.beginPath(),this.ctx.arc(h,u,16/4,0,Math.PI*2),this.ctx.fill())}drawSwitchCell(t,l,i,c,r,n){let e=l+10;n==="center"&&(e=l+(c-32)/2),n==="right"&&(e=l+c-32-10);const h=i+(r-16)/2;this.ctx.fillStyle=t?"#13ce66":"#ff4949",this.ctx.beginPath(),this.ctx.roundRect?.(e,h,32,16,16/2),this.ctx.fill(),this.ctx.fillStyle="#fff",this.ctx.beginPath();const u=t?e+32-16+2:e+2;this.ctx.arc(u+12/2,h+16/2,12/2,0,Math.PI*2),this.ctx.fill()}drawColorPickerCell(t,l,i,c,r,n){let a=l+10;n==="center"&&(a=l+(c-20)/2),n==="right"&&(a=l+c-20-10);const e=i+(r-20)/2;this.ctx.fillStyle=t||"#000",this.ctx.fillRect(a,e,20,20),this.ctx.strokeStyle="#dcdfe6",this.ctx.strokeRect(a+.5,e+.5,20,20)}drawTagsCell(t,l,i,c,r){if(!Array.isArray(t))return;let n=l+5;const o=20,a=5,e=12;t.forEach(h=>{const u=String(h);this.ctx.font=`${e}px sans-serif`;const g=this.ctx.measureText(u).width+a*2;if(n+g>l+c-5)return;const p=i+(r-o)/2;this.ctx.fillStyle="#ecf5ff",this.ctx.strokeStyle="#d9ecff",this.ctx.beginPath(),this.ctx.roundRect?.(n,p,g,o,4),this.ctx.fill(),this.ctx.stroke(),this.ctx.fillStyle="#409eff",this.ctx.textAlign="center",this.ctx.fillText(u,n+g/2,p+o-e/2),n+=g+5})}getCellAt(t,l){const{headerHeight:i}=this.options;if(l<i)return null;const{startRow:c,endRow:r}=this.getRowRange(this.height);for(let n=c;n<r;n++){const o=this.data[n];if(!o)continue;const a=(this.rowOffsets[n]??0)-this.scrollY+i,e=(this.rowOffsets[n+1]??0)-(this.rowOffsets[n]??0);if(l>=a&&l<a+e)for(let h=0;h<this.flattenedColumns.length;h++){const u=this.flattenedColumns[h],f=(this.columnPositions[h+1]??0)-(this.columnPositions[h]??0);let g=0;if(u.fixed==="left"||u.fixed===!0)g=this.columnPositions[h]??0;else if(g=(this.columnPositions[h]??0)-this.scrollX,g<this.fixedLeftWidth)continue;if(t>=g&&t<g+f){const p=u.type==="expand",S=u.type==="selection";return{row:n,col:h,rect:{x:g,y:a,width:f,height:e},column:u,data:o,isExpandBtn:p,isSelection:S}}}}return null}getRowOffsets(){return this.rowOffsets}getScrollX(){return this.scrollX}getScrollY(){return this.scrollY}getFixedLeftWidth(){return this.fixedLeftWidth}getTotalWidth(){return this.totalWidth}getTotalHeight(){return this.totalHeight}}const N=["onClick"],I={class:"icon"},A={class:"label"},O={class:"edit-dialog-content"},D=((z,t)=>{const l=z.__vccOpts||z;for(const[i,c]of t)l[i]=c;return l})(s.defineComponent({__name:"CanvasTable",props:{columns:{},data:{},options:{}},emits:["update:data","select-change","header-command"],setup(z,{emit:t}){const l=s.defineComponent({props:["vnode"],setup(d){return()=>d.vnode}}),i=z,c=t,r=s.ref(null),n=s.ref(null),o=s.ref(null),a=s.ref(null),e=s.shallowRef(null),h=s.ref(0),u=s.ref(0),f=s.ref(0),g=s.ref(0),p=s.ref(0),S=s.ref(0),C=s.ref(null),k=s.ref(null),R=s.ref(null),y=s.ref(new Set),W=s.ref(new Set),b=s.ref(null),P=s.computed(()=>({width:"100%",height:"100%",position:"relative",overflow:"hidden"})),K=s.computed(()=>({position:"absolute",top:0,left:0,pointerEvents:"none",width:"100%",height:"100%"})),F=s.computed(()=>{if(!C.value)return{};const{rect:d}=C.value;return{position:"absolute",left:`${d.x+d.width-24}px`,top:`${d.y+(d.height-20)/2}px`,pointerEvents:"auto"}}),J=s.computed(()=>{if(!k.value||!n.value)return{};const d=n.value.getBoundingClientRect(),{rect:m}=k.value;let x=d.top+m.y+m.height+5,w=d.left+m.x;const v=300;return w+v>window.innerWidth&&(w=window.innerWidth-v-20),{position:"fixed",top:`${x}px`,left:`${w}px`,zIndex:2e3,pointerEvents:"auto"}}),U=s.computed(()=>{if(!b.value)return{};const{rect:d}=b.value;return{position:"absolute",left:`${d.x+d.width-120}px`,top:`${d.y+d.height}px`,pointerEvents:"auto"}}),q=s.computed(()=>{if(!b.value)return[];const{column:d}=b.value,m=[{label:"Fix to Left",onCommand:x=>{const w=i.columns.findIndex(v=>v.key===x.key);i.columns.forEach((v,H)=>{H<=w&&(v.fixed="left")}),e.value?.setColumns(i.columns)}},{label:"Unfix",onCommand:x=>{x.fixed=!1,e.value?.setColumns(i.columns)}}];return d.renderHeaderMenu?d.renderHeaderMenu(d,m):m}),G=d=>{b.value&&(d.onCommand(b.value.column),b.value=null)},Y=d=>{if(!n.value||!e.value)return;const m=n.value.getBoundingClientRect(),x=d.clientX-m.left,w=d.clientY-m.top,v=e.value.getHeaderAt(x,w);if(v){const H=i.columns.findIndex(E=>E.key===v.column.key);e.value.setHoverHeader(H),v.isMenu||v.column.type==="selection"?n.value.style.cursor="pointer":n.value.style.cursor="default"}else e.value.setHoverHeader(-1),n.value.style.cursor="default";C.value=e.value.getCellAt(x,w),C.value&&(C.value.isExpandBtn||C.value.isSelection)&&(n.value.style.cursor="pointer")},V=d=>{if(!n.value||!e.value)return;const m=n.value.getBoundingClientRect(),x=d.clientX-m.left,w=d.clientY-m.top,v=e.value.getHeaderAt(x,w);if(v){v.isMenu?b.value={column:v.column,rect:v.rect}:v.column.type==="selection"&&(y.value.size===i.data.length?y.value.clear():i.data.forEach(rt=>y.value.add(rt.id)),e.value.setSelectedRows(Array.from(y.value)),c("select-change",Array.from(y.value)));return}const H=e.value.getCellAt(x,w);if(H){if(H.isExpandBtn){Q(H.data.id);return}const E=H.data.id;if(H.isSelection){y.value.has(E)?y.value.delete(E):y.value.add(E),e.value.setSelectedRows(Array.from(y.value)),c("select-change",Array.from(y.value));return}i.options?.multiSelect?y.value.has(E)?y.value.delete(E):y.value.add(E):(y.value.clear(),y.value.add(E)),c("select-change",Array.from(y.value))}},_=d=>{if(!n.value||!e.value)return;const m=n.value.getBoundingClientRect(),x=d.clientX-m.left,w=d.clientY-m.top,v=e.value.getCellAt(x,w);v&&v.column.renderEdit&&$(v)},$=d=>{k.value=d,R.value=JSON.parse(JSON.stringify(d.data))},Q=d=>{W.value.has(d)?W.value.delete(d):W.value.add(d),e.value?.setExpandedRows(Array.from(W.value)),B()},T=()=>{k.value=null,R.value=null},Z=()=>{if(k.value&&R.value){const d=k.value.data.id,m=i.data.findIndex(x=>x.id===d);if(m!==-1){const x=[...i.data];x[m]=R.value,c("update:data",x),e.value?.setData(x)}}T()},j=d=>!d.column.renderEdit||!R.value?null:d.column.renderEdit(R.value,(m,x,w)=>x&&(typeof x=="string"||Array.isArray(x)||x.__v_isVNode)?s.h(m,null,x):s.h(m,x,w)),tt=d=>{if(!e.value)return{};const m=i.data.findIndex(E=>E.id===d);if(m===-1)return{};const x=e.value.getRowOffsets(),w=(x[m]??0)-S.value+(i.options?.headerHeight||48),v=(x[m+1]??0)-(x[m]??0)-(i.options?.rowHeight||40),H=e.value.getFixedLeftWidth();return{position:"absolute",top:`${w+(i.options?.rowHeight||40)}px`,left:`${H}px`,width:`${f.value-H}px`,height:`${v}px`,pointerEvents:"auto",overflow:"hidden",backgroundColor:"#fff",borderBottom:"1px solid #ebeef5",display:"flex"}},et=()=>({marginLeft:`-${p.value}px`,minWidth:`${h.value-e.value?.getFixedLeftWidth()}px`}),st=d=>{const m=i.data.find(x=>x.id===d);return!m||!i.options?.renderExpand?null:s.h("div",{style:et()},[i.options.renderExpand(m,(x,w,v)=>w&&(typeof w=="string"||Array.isArray(w)||w.__v_isVNode)?s.h(x,null,w):s.h(x,w,v))])},it=d=>{const m=d.target;p.value=m.scrollLeft,e.value?.scrollTo(p.value,S.value),C.value=null},lt=d=>{const m=d.target;S.value=m.scrollTop,e.value?.scrollTo(p.value,S.value),C.value=null},nt=d=>{if(!a.value||!o.value)return;const m=d.deltaY,x=d.shiftKey?d.deltaY:d.deltaX;a.value.scrollTop+=m,o.value.scrollLeft+=x},ot=d=>{const m=d[0];if(!m||!e.value)return;const{width:x,height:w}=m.contentRect;f.value=x,g.value=w,e.value.resize(x,w),B()},B=()=>{e.value&&(h.value=e.value.getTotalWidth(),u.value=e.value.getTotalHeight())};let M=null;return s.onMounted(()=>{n.value&&(e.value=new X(n.value),e.value.setColumns(i.columns),e.value.setData(i.data),e.value.setOptions(i.options||{}),B(),M=new ResizeObserver(ot),r.value&&M.observe(r.value),n.value.addEventListener("mousemove",Y),n.value.addEventListener("mousedown",V),n.value.addEventListener("dblclick",_))}),s.onUnmounted(()=>{M?.disconnect(),n.value?.removeEventListener("mousemove",Y),n.value?.removeEventListener("mousedown",V),n.value?.removeEventListener("dblclick",_),e.value?.destroy(),e.value=null}),s.watch(()=>i.columns,d=>{e.value?.setColumns(d),B()},{deep:!0}),s.watch(()=>i.data,d=>{e.value?.setData(d),B()},{deep:!0}),s.watch(()=>i.options,d=>{d&&e.value?.setOptions(d)},{deep:!0}),(d,m)=>(s.openBlock(),s.createElementBlock("div",{class:"canvas-table-container",ref_key:"containerRef",ref:r},[s.createElementVNode("div",{class:"canvas-wrapper",style:s.normalizeStyle(P.value),onWheel:s.withModifiers(nt,["prevent"])},[s.createElementVNode("canvas",{ref_key:"canvasRef",ref:n},null,512),s.createElementVNode("div",{class:"scrollbar horizontal",ref_key:"hScrollRef",ref:o,onScroll:it},[s.createElementVNode("div",{style:s.normalizeStyle({width:h.value+"px",height:"1px"})},null,4)],544),s.createElementVNode("div",{class:"scrollbar vertical",ref_key:"vScrollRef",ref:a,onScroll:lt},[s.createElementVNode("div",{style:s.normalizeStyle({height:u.value+"px",width:"1px"})},null,4)],544),s.createElementVNode("div",{class:"table-overlays",style:s.normalizeStyle(K.value)},[C.value&&C.value.column.renderEdit?(s.openBlock(),s.createElementBlock("div",{key:0,class:"edit-btn",style:s.normalizeStyle(F.value),onClick:m[0]||(m[0]=s.withModifiers(x=>$(C.value),["stop"]))},[...m[2]||(m[2]=[s.createElementVNode("svg",{viewBox:"0 0 24 24",width:"14",height:"14"},[s.createElementVNode("path",{fill:"currentColor",d:"M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"})],-1)])],4)):s.createCommentVNode("",!0),b.value?(s.openBlock(),s.createElementBlock("div",{key:1,class:"header-menu-overlay",onClick:m[1]||(m[1]=s.withModifiers(x=>b.value=null,["self"]))},[s.createElementVNode("div",{class:"header-menu",style:s.normalizeStyle(U.value)},[(s.openBlock(!0),s.createElementBlock(s.Fragment,null,s.renderList(q.value,x=>(s.openBlock(),s.createElementBlock("div",{key:x.label,class:"menu-item",onClick:w=>G(x)},[s.createElementVNode("span",I,s.toDisplayString(x.icon||"•"),1),s.createElementVNode("span",A,s.toDisplayString(x.label),1)],8,N))),128))],4)])):s.createCommentVNode("",!0),(s.openBlock(!0),s.createElementBlock(s.Fragment,null,s.renderList(W.value,x=>(s.openBlock(),s.createElementBlock("div",{key:x,class:"expand-row-overlay",style:s.normalizeStyle(tt(x))},[(s.openBlock(),s.createBlock(s.resolveDynamicComponent(st(x))))],4))),128)),(s.openBlock(),s.createBlock(s.Teleport,{to:"body"},[k.value?(s.openBlock(),s.createElementBlock("div",{key:0,class:"edit-dialog-popover",style:s.normalizeStyle(J.value)},[s.createElementVNode("div",O,[s.createVNode(s.unref(l),{vnode:j(k.value)},null,8,["vnode"])]),s.createElementVNode("div",{class:"edit-dialog-footer"},[s.createElementVNode("button",{class:"small",onClick:T},"Cancel"),s.createElementVNode("button",{class:"small primary",onClick:Z},"Save")])],4)):s.createCommentVNode("",!0),k.value?(s.openBlock(),s.createElementBlock("div",{key:1,class:"popover-click-mask",onClick:T})):s.createCommentVNode("",!0)]))],4)],36)],512))}}),[["__scopeId","data-v-34fbfef2"]]);L.CanvasRenderer=X,L.CanvasTable=D,Object.defineProperty(L,Symbol.toStringTag,{value:"Module"})}));
|