@canvas-components/list-table 0.3.19 → 0.3.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -2
- package/dist/index.cjs +1757 -168
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +170 -36
- package/dist/index.d.ts +170 -36
- package/dist/index.js +1735 -169
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
package/dist/index.cjs
CHANGED
|
@@ -3,9 +3,30 @@
|
|
|
3
3
|
var utils = require('@canvas-components/utils');
|
|
4
4
|
var barcode = require('@canvas-components/barcode');
|
|
5
5
|
var chart = require('@canvas-components/chart');
|
|
6
|
+
var antDesignIcons = require('@ant-design/icons-svg');
|
|
6
7
|
var qrcode = require('@canvas-components/qrcode');
|
|
7
8
|
var stats = require('@canvas-components/stats');
|
|
8
9
|
|
|
10
|
+
function _interopNamespace(e) {
|
|
11
|
+
if (e && e.__esModule) return e;
|
|
12
|
+
var n = Object.create(null);
|
|
13
|
+
if (e) {
|
|
14
|
+
Object.keys(e).forEach(function (k) {
|
|
15
|
+
if (k !== 'default') {
|
|
16
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
17
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
get: function () { return e[k]; }
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
n.default = e;
|
|
25
|
+
return Object.freeze(n);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
var antDesignIcons__namespace = /*#__PURE__*/_interopNamespace(antDesignIcons);
|
|
29
|
+
|
|
9
30
|
var __defProp = Object.defineProperty;
|
|
10
31
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
11
32
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
@@ -4534,7 +4555,7 @@ function drawImagePlaceholder(ctx, x, y, width, height, backgroundColor = PLACEH
|
|
|
4534
4555
|
ctx.fill();
|
|
4535
4556
|
}
|
|
4536
4557
|
|
|
4537
|
-
// src/rendering/
|
|
4558
|
+
// src/rendering/icons/draw-symbol.ts
|
|
4538
4559
|
var SYMBOL_COLOR_MAP = {
|
|
4539
4560
|
star: "#fadb14",
|
|
4540
4561
|
sun: "#faad14",
|
|
@@ -4558,6 +4579,11 @@ function drawCellSymbol(ctx, params) {
|
|
|
4558
4579
|
return;
|
|
4559
4580
|
}
|
|
4560
4581
|
appendCellSymbolPath(ctx, type, x, y, size);
|
|
4582
|
+
if (fillRatio >= 1) {
|
|
4583
|
+
ctx.fillStyle = activeColor;
|
|
4584
|
+
ctx.fill("evenodd");
|
|
4585
|
+
return;
|
|
4586
|
+
}
|
|
4561
4587
|
ctx.fillStyle = inactiveColor;
|
|
4562
4588
|
ctx.fill("evenodd");
|
|
4563
4589
|
if (fillRatio <= 0) {
|
|
@@ -4605,6 +4631,12 @@ function drawStatusSymbol(ctx, params) {
|
|
|
4605
4631
|
ctx.lineJoin = "round";
|
|
4606
4632
|
ctx.lineWidth = Math.max(size * 0.12, 1.5);
|
|
4607
4633
|
appendStatusSymbolPath(ctx, type, x, y, size);
|
|
4634
|
+
if (fillRatio >= 1) {
|
|
4635
|
+
ctx.strokeStyle = activeColor;
|
|
4636
|
+
ctx.stroke();
|
|
4637
|
+
ctx.restore();
|
|
4638
|
+
return;
|
|
4639
|
+
}
|
|
4608
4640
|
ctx.strokeStyle = inactiveColor;
|
|
4609
4641
|
ctx.stroke();
|
|
4610
4642
|
if (fillRatio > 0) {
|
|
@@ -4668,6 +4700,838 @@ function appendMoonPath(ctx, x, y, size) {
|
|
|
4668
4700
|
ctx.closePath();
|
|
4669
4701
|
}
|
|
4670
4702
|
|
|
4703
|
+
// src/rendering/icons/icon-stroke.ts
|
|
4704
|
+
function resolveIconStroke(ctx) {
|
|
4705
|
+
const identity = (value) => value;
|
|
4706
|
+
const fallback = { width: 2, snapX: identity, snapY: identity };
|
|
4707
|
+
const transform = ctx.getTransform?.();
|
|
4708
|
+
if (!transform || ![
|
|
4709
|
+
transform.a,
|
|
4710
|
+
transform.b,
|
|
4711
|
+
transform.c,
|
|
4712
|
+
transform.d,
|
|
4713
|
+
transform.e,
|
|
4714
|
+
transform.f
|
|
4715
|
+
].every(Number.isFinite))
|
|
4716
|
+
return fallback;
|
|
4717
|
+
if (Math.abs(transform.b) > 1e-8 || Math.abs(transform.c) > 1e-8 || transform.a <= 0 || Math.abs(transform.a - transform.d) > 1e-8)
|
|
4718
|
+
return fallback;
|
|
4719
|
+
const scale = transform.a;
|
|
4720
|
+
const pixels = Math.max(1, Math.round(2 * scale));
|
|
4721
|
+
const phase = pixels % 2 / 2;
|
|
4722
|
+
const snap = (value, translation) => (Math.round(value * scale + translation - phase) + phase - translation) / scale;
|
|
4723
|
+
return {
|
|
4724
|
+
width: pixels / scale,
|
|
4725
|
+
snapX: (value) => snap(value, transform.e),
|
|
4726
|
+
snapY: (value) => snap(value, transform.f)
|
|
4727
|
+
};
|
|
4728
|
+
}
|
|
4729
|
+
var listTableBuiltinIconNames = [
|
|
4730
|
+
"star",
|
|
4731
|
+
"sun",
|
|
4732
|
+
"moon",
|
|
4733
|
+
"check",
|
|
4734
|
+
"close",
|
|
4735
|
+
"circle",
|
|
4736
|
+
"check-circle",
|
|
4737
|
+
"close-circle",
|
|
4738
|
+
"clock-circle",
|
|
4739
|
+
"info-circle",
|
|
4740
|
+
"question-circle",
|
|
4741
|
+
"warning",
|
|
4742
|
+
"loading",
|
|
4743
|
+
"plus",
|
|
4744
|
+
"minus",
|
|
4745
|
+
"plus-circle",
|
|
4746
|
+
"minus-circle",
|
|
4747
|
+
"up",
|
|
4748
|
+
"down",
|
|
4749
|
+
"left",
|
|
4750
|
+
"right",
|
|
4751
|
+
"arrow-up",
|
|
4752
|
+
"arrow-down",
|
|
4753
|
+
"arrow-left",
|
|
4754
|
+
"arrow-right",
|
|
4755
|
+
"search",
|
|
4756
|
+
"edit",
|
|
4757
|
+
"delete",
|
|
4758
|
+
"copy",
|
|
4759
|
+
"save",
|
|
4760
|
+
"upload",
|
|
4761
|
+
"download",
|
|
4762
|
+
"reload",
|
|
4763
|
+
"ellipsis",
|
|
4764
|
+
"file",
|
|
4765
|
+
"file-text",
|
|
4766
|
+
"file-pdf",
|
|
4767
|
+
"folder",
|
|
4768
|
+
"folder-open",
|
|
4769
|
+
"picture",
|
|
4770
|
+
"user",
|
|
4771
|
+
"team",
|
|
4772
|
+
"calendar",
|
|
4773
|
+
"filter",
|
|
4774
|
+
"sort-ascending",
|
|
4775
|
+
"sort-descending",
|
|
4776
|
+
"link",
|
|
4777
|
+
"eye",
|
|
4778
|
+
"lock",
|
|
4779
|
+
"unlock",
|
|
4780
|
+
"home",
|
|
4781
|
+
"mail",
|
|
4782
|
+
"setting",
|
|
4783
|
+
"header-sort",
|
|
4784
|
+
"header-sort-ascending",
|
|
4785
|
+
"header-sort-descending",
|
|
4786
|
+
"header-filter",
|
|
4787
|
+
"header-fixed"
|
|
4788
|
+
];
|
|
4789
|
+
var listTableAntdIconNames = Object.keys(
|
|
4790
|
+
antDesignIcons__namespace
|
|
4791
|
+
);
|
|
4792
|
+
var listTableIconNames = [
|
|
4793
|
+
...listTableBuiltinIconNames,
|
|
4794
|
+
...listTableAntdIconNames
|
|
4795
|
+
];
|
|
4796
|
+
function getAntdIconDefinition(name) {
|
|
4797
|
+
return Object.prototype.hasOwnProperty.call(antDesignIcons__namespace, name) ? antDesignIcons__namespace[name] : void 0;
|
|
4798
|
+
}
|
|
4799
|
+
|
|
4800
|
+
// src/rendering/icons/svg-path.ts
|
|
4801
|
+
function parseSvgPath(source) {
|
|
4802
|
+
const output = [];
|
|
4803
|
+
let offset = 0, command = "", previous = "", x = 0, y = 0, startX = 0, startY = 0, controlX = 0, controlY = 0;
|
|
4804
|
+
const skip = () => {
|
|
4805
|
+
while (/[\s,]/.test(source[offset] ?? "!") && offset < source.length)
|
|
4806
|
+
offset++;
|
|
4807
|
+
};
|
|
4808
|
+
const number = (flag = false) => {
|
|
4809
|
+
skip();
|
|
4810
|
+
const match = source.slice(offset).match(flag ? /^[01]/ : /^[-+]?(?:\d*\.\d+|\d+\.?\d*)(?:[eE][-+]?\d+)?/);
|
|
4811
|
+
if (!match) throw new Error(`\u65E0\u6548 SVG \u8DEF\u5F84\u53C2\u6570\uFF0C\u4F4D\u7F6E ${offset}`);
|
|
4812
|
+
offset += match[0].length;
|
|
4813
|
+
const value = Number(match[0]);
|
|
4814
|
+
if (!Number.isFinite(value)) throw new Error("SVG \u8DEF\u5F84\u5305\u542B\u975E\u6709\u9650\u5750\u6807");
|
|
4815
|
+
return value;
|
|
4816
|
+
};
|
|
4817
|
+
while (offset < source.length) {
|
|
4818
|
+
skip();
|
|
4819
|
+
if (offset >= source.length) break;
|
|
4820
|
+
if (/[a-z]/i.test(source[offset])) command = source[offset++];
|
|
4821
|
+
else if (!command) throw new Error(`\u7F3A\u5C11 SVG \u8DEF\u5F84\u547D\u4EE4\uFF0C\u4F4D\u7F6E ${offset}`);
|
|
4822
|
+
const upper = command.toUpperCase();
|
|
4823
|
+
const relative = upper !== command;
|
|
4824
|
+
const point = () => [
|
|
4825
|
+
number() + (relative ? x : 0),
|
|
4826
|
+
number() + (relative ? y : 0)
|
|
4827
|
+
];
|
|
4828
|
+
if (upper === "Z") {
|
|
4829
|
+
output.push({ op: "Z", args: [] });
|
|
4830
|
+
x = startX;
|
|
4831
|
+
y = startY;
|
|
4832
|
+
command = "";
|
|
4833
|
+
} else if (upper === "M" || upper === "L") {
|
|
4834
|
+
const target = point();
|
|
4835
|
+
output.push({ op: upper, args: target });
|
|
4836
|
+
[x, y] = target;
|
|
4837
|
+
if (upper === "M") {
|
|
4838
|
+
startX = x;
|
|
4839
|
+
startY = y;
|
|
4840
|
+
command = relative ? "l" : "L";
|
|
4841
|
+
}
|
|
4842
|
+
} else if (upper === "H" || upper === "V") {
|
|
4843
|
+
const value = number();
|
|
4844
|
+
if (upper === "H") x = value + (relative ? x : 0);
|
|
4845
|
+
else y = value + (relative ? y : 0);
|
|
4846
|
+
output.push({ op: "L", args: [x, y] });
|
|
4847
|
+
} else if (upper === "C" || upper === "S") {
|
|
4848
|
+
const first = upper === "C" ? point() : [
|
|
4849
|
+
/[CS]/.test(previous) ? 2 * x - controlX : x,
|
|
4850
|
+
/[CS]/.test(previous) ? 2 * y - controlY : y
|
|
4851
|
+
];
|
|
4852
|
+
const second = point();
|
|
4853
|
+
const target = point();
|
|
4854
|
+
output.push({ op: "C", args: [...first, ...second, ...target] });
|
|
4855
|
+
[controlX, controlY] = second;
|
|
4856
|
+
[x, y] = target;
|
|
4857
|
+
} else if (upper === "Q" || upper === "T") {
|
|
4858
|
+
const control = upper === "Q" ? point() : [
|
|
4859
|
+
/[QT]/.test(previous) ? 2 * x - controlX : x,
|
|
4860
|
+
/[QT]/.test(previous) ? 2 * y - controlY : y
|
|
4861
|
+
];
|
|
4862
|
+
const target = point();
|
|
4863
|
+
output.push({ op: "Q", args: [...control, ...target] });
|
|
4864
|
+
[controlX, controlY] = control;
|
|
4865
|
+
[x, y] = target;
|
|
4866
|
+
} else if (upper === "A") {
|
|
4867
|
+
const rx = number(), ry = number(), rotation = number(), large = number(true), sweep = number(true);
|
|
4868
|
+
const target = point();
|
|
4869
|
+
output.push(
|
|
4870
|
+
...arcCommands(
|
|
4871
|
+
x,
|
|
4872
|
+
y,
|
|
4873
|
+
rx,
|
|
4874
|
+
ry,
|
|
4875
|
+
rotation,
|
|
4876
|
+
large,
|
|
4877
|
+
sweep,
|
|
4878
|
+
target[0],
|
|
4879
|
+
target[1]
|
|
4880
|
+
)
|
|
4881
|
+
);
|
|
4882
|
+
[x, y] = target;
|
|
4883
|
+
} else throw new Error(`\u4E0D\u652F\u6301\u7684 SVG \u8DEF\u5F84\u547D\u4EE4 ${command}`);
|
|
4884
|
+
previous = upper;
|
|
4885
|
+
}
|
|
4886
|
+
return output;
|
|
4887
|
+
}
|
|
4888
|
+
function arcCommands(x1, y1, rx, ry, rotation, large, sweep, x2, y2) {
|
|
4889
|
+
if (x1 === x2 && y1 === y2) return [];
|
|
4890
|
+
rx = Math.abs(rx);
|
|
4891
|
+
ry = Math.abs(ry);
|
|
4892
|
+
if (!rx || !ry) return [{ op: "L", args: [x2, y2] }];
|
|
4893
|
+
const phi = rotation * Math.PI / 180, cos = Math.cos(phi), sin = Math.sin(phi);
|
|
4894
|
+
const px = cos * (x1 - x2) / 2 + sin * (y1 - y2) / 2;
|
|
4895
|
+
const py = -sin * (x1 - x2) / 2 + cos * (y1 - y2) / 2;
|
|
4896
|
+
const scale = Math.max(
|
|
4897
|
+
1,
|
|
4898
|
+
Math.sqrt(px * px / (rx * rx) + py * py / (ry * ry))
|
|
4899
|
+
);
|
|
4900
|
+
rx *= scale;
|
|
4901
|
+
ry *= scale;
|
|
4902
|
+
const denominator = rx * rx * py * py + ry * ry * px * px;
|
|
4903
|
+
const factor = (large === sweep ? -1 : 1) * Math.sqrt(Math.max(0, (rx * rx * ry * ry - denominator) / denominator));
|
|
4904
|
+
const cxp = factor * rx * py / ry, cyp = -factor * ry * px / rx;
|
|
4905
|
+
const cx = cos * cxp - sin * cyp + (x1 + x2) / 2, cy = sin * cxp + cos * cyp + (y1 + y2) / 2;
|
|
4906
|
+
const start = Math.atan2((py - cyp) / ry, (px - cxp) / rx);
|
|
4907
|
+
const finish = Math.atan2((-py - cyp) / ry, (-px - cxp) / rx);
|
|
4908
|
+
let delta = finish - start;
|
|
4909
|
+
if (sweep && delta < 0) delta += Math.PI * 2;
|
|
4910
|
+
if (!sweep && delta > 0) delta -= Math.PI * 2;
|
|
4911
|
+
const count = Math.max(1, Math.ceil(Math.abs(delta) / (Math.PI / 2)));
|
|
4912
|
+
const step = delta / count;
|
|
4913
|
+
const point = (angle) => [
|
|
4914
|
+
cx + rx * cos * Math.cos(angle) - ry * sin * Math.sin(angle),
|
|
4915
|
+
cy + rx * sin * Math.cos(angle) + ry * cos * Math.sin(angle)
|
|
4916
|
+
];
|
|
4917
|
+
const derivative = (angle) => [
|
|
4918
|
+
-rx * cos * Math.sin(angle) - ry * sin * Math.cos(angle),
|
|
4919
|
+
-rx * sin * Math.sin(angle) + ry * cos * Math.cos(angle)
|
|
4920
|
+
];
|
|
4921
|
+
return Array.from({ length: count }, (_, index) => {
|
|
4922
|
+
const a = start + step * index, b = a + step, k = 4 / 3 * Math.tan(step / 4);
|
|
4923
|
+
const p = point(a), q = point(b), dp = derivative(a), dq = derivative(b);
|
|
4924
|
+
return {
|
|
4925
|
+
op: "C",
|
|
4926
|
+
args: [
|
|
4927
|
+
p[0] + k * dp[0],
|
|
4928
|
+
p[1] + k * dp[1],
|
|
4929
|
+
q[0] - k * dq[0],
|
|
4930
|
+
q[1] - k * dq[1],
|
|
4931
|
+
...index === count - 1 ? [x2, y2] : q
|
|
4932
|
+
]
|
|
4933
|
+
};
|
|
4934
|
+
});
|
|
4935
|
+
}
|
|
4936
|
+
function traceSvgPath(ctx, commands) {
|
|
4937
|
+
ctx.beginPath();
|
|
4938
|
+
for (const { op, args: a } of commands) {
|
|
4939
|
+
if (op === "M") ctx.moveTo(a[0], a[1]);
|
|
4940
|
+
else if (op === "L") ctx.lineTo(a[0], a[1]);
|
|
4941
|
+
else if (op === "C") ctx.bezierCurveTo(a[0], a[1], a[2], a[3], a[4], a[5]);
|
|
4942
|
+
else if (op === "Q") ctx.quadraticCurveTo(a[0], a[1], a[2], a[3]);
|
|
4943
|
+
else ctx.closePath();
|
|
4944
|
+
}
|
|
4945
|
+
}
|
|
4946
|
+
|
|
4947
|
+
// src/rendering/icons/draw-antd-icon.ts
|
|
4948
|
+
var pathCache = /* @__PURE__ */ new Map();
|
|
4949
|
+
var CACHE_LIMIT = 256;
|
|
4950
|
+
function secondaryColor(primary) {
|
|
4951
|
+
let hex = primary.replace(/^#/, "");
|
|
4952
|
+
if (/^[\da-f]{3}$/i.test(hex))
|
|
4953
|
+
hex = [...hex].map((char) => char + char).join("");
|
|
4954
|
+
if (!/^[\da-f]{6}$/i.test(hex)) return "#e6f4ff";
|
|
4955
|
+
const channels = [0, 2, 4].map(
|
|
4956
|
+
(start) => Math.round(255 * 0.85 + parseInt(hex.slice(start, start + 2), 16) * 0.15)
|
|
4957
|
+
);
|
|
4958
|
+
return `rgb(${channels.join(",")})`;
|
|
4959
|
+
}
|
|
4960
|
+
function drawAntdIcon(ctx, params) {
|
|
4961
|
+
const definition = getAntdIconDefinition(params.type);
|
|
4962
|
+
if (!definition) return false;
|
|
4963
|
+
const primary = Array.isArray(params.twoToneColor) ? params.twoToneColor[0] : params.twoToneColor ?? params.color;
|
|
4964
|
+
const secondary = Array.isArray(params.twoToneColor) ? params.twoToneColor[1] : secondaryColor(primary);
|
|
4965
|
+
const root = typeof definition.icon === "function" ? definition.icon(primary, secondary) : definition.icon;
|
|
4966
|
+
const [vx, vy, vw, vh] = (root.attrs.viewBox ?? "0 0 1024 1024").split(/[\s,]+/).map(Number);
|
|
4967
|
+
ctx.save();
|
|
4968
|
+
try {
|
|
4969
|
+
const scale = params.size / Math.max(vw, vh);
|
|
4970
|
+
ctx.translate(
|
|
4971
|
+
params.x + (params.size - vw * scale) / 2,
|
|
4972
|
+
params.y + (params.size - vh * scale) / 2
|
|
4973
|
+
);
|
|
4974
|
+
ctx.scale(scale, scale);
|
|
4975
|
+
ctx.translate(-vx, -vy);
|
|
4976
|
+
drawNode(ctx, root, primary);
|
|
4977
|
+
} finally {
|
|
4978
|
+
ctx.restore();
|
|
4979
|
+
}
|
|
4980
|
+
return true;
|
|
4981
|
+
}
|
|
4982
|
+
function drawNode(ctx, node, inheritedColor) {
|
|
4983
|
+
if (node.tag === "defs" || node.tag === "style") return;
|
|
4984
|
+
const color = node.attrs.fill ?? inheritedColor;
|
|
4985
|
+
ctx.save();
|
|
4986
|
+
try {
|
|
4987
|
+
const opacity = Number(node.attrs["fill-opacity"] ?? 1);
|
|
4988
|
+
ctx.globalAlpha *= Number.isFinite(opacity) ? Math.max(0, Math.min(opacity, 1)) : 1;
|
|
4989
|
+
if (node.tag === "path" && node.attrs.d && color !== "none") {
|
|
4990
|
+
ctx.fillStyle = color === "currentColor" ? inheritedColor : color;
|
|
4991
|
+
const data = node.attrs.d;
|
|
4992
|
+
let entry = pathCache.get(data);
|
|
4993
|
+
if (entry) pathCache.delete(data);
|
|
4994
|
+
else if (typeof Path2D === "function") {
|
|
4995
|
+
try {
|
|
4996
|
+
entry = { path: new Path2D(data) };
|
|
4997
|
+
} catch {
|
|
4998
|
+
entry = { commands: parseSvgPath(data) };
|
|
4999
|
+
}
|
|
5000
|
+
} else entry = { commands: parseSvgPath(data) };
|
|
5001
|
+
pathCache.set(data, entry);
|
|
5002
|
+
if (pathCache.size > CACHE_LIMIT)
|
|
5003
|
+
pathCache.delete(pathCache.keys().next().value);
|
|
5004
|
+
const rule = node.attrs["fill-rule"] === "evenodd" ? "evenodd" : "nonzero";
|
|
5005
|
+
if (entry.path) ctx.fill(entry.path, rule);
|
|
5006
|
+
else {
|
|
5007
|
+
traceSvgPath(ctx, entry.commands);
|
|
5008
|
+
ctx.fill(rule);
|
|
5009
|
+
}
|
|
5010
|
+
}
|
|
5011
|
+
for (const child of node.children ?? []) drawNode(ctx, child, color);
|
|
5012
|
+
} finally {
|
|
5013
|
+
ctx.restore();
|
|
5014
|
+
}
|
|
5015
|
+
}
|
|
5016
|
+
|
|
5017
|
+
// src/rendering/icons/draw-header-action-icon.ts
|
|
5018
|
+
var FILTER_ICON_VIEWBOX_SIZE = 1024;
|
|
5019
|
+
var FILTER_ICON_PATH_DATA = "M922.366667 114.813333A53.04 53.04 0 0 0 874.666667 85.333333H149.333333a53.333333 53.333333 0 0 0-42.666666 85.333334l277.333333 369.78V917.333333a21.333333 21.333333 0 0 0 29.253333 19.806667l213.333334-85.333333A21.333333 21.333333 0 0 0 640 832V540.446667L917.333333 170.666667a53.04 53.04 0 0 0 5.033334-55.853334z";
|
|
5020
|
+
var FIXED_PIN_VIEWBOX_SIZE = 1024;
|
|
5021
|
+
var FIXED_PIN_PATH_DATA = "M963.925333 326.997333L697.002667 60.074667a25.6 25.6 0 0 0-43.52 21.845333l14.506666 99.498667-273.066666 151.381333c-91.477333-45.738667-170.666667-36.693333-234.496 27.306667a25.941333 25.941333 0 0 0 0 36.352L327.68 563.2 57.685333 930.645333a25.6 25.6 0 0 0 35.84 35.669334l366.250667-270.677334 167.765333 167.936a25.941333 25.941333 0 0 0 36.352 0c79.530667-79.701333 58.538667-165.546667 26.965334-233.813333l152.064-273.066667 99.157333 14.165334a25.6 25.6 0 0 0 26.624-13.824 25.941333 25.941333 0 0 0-4.778667-30.037334z";
|
|
5022
|
+
var filterIconPath = null;
|
|
5023
|
+
var fixedPinPath = null;
|
|
5024
|
+
function drawHeaderActionGlyph(ctx, rect, actionType, color = "#8c8c8c", sortOrder = null, activeColor = "#1677ff") {
|
|
5025
|
+
ctx.save();
|
|
5026
|
+
ctx.strokeStyle = color;
|
|
5027
|
+
ctx.fillStyle = color;
|
|
5028
|
+
if (actionType === "sort") {
|
|
5029
|
+
ctx.beginPath();
|
|
5030
|
+
ctx.fillStyle = sortOrder === "ascend" ? activeColor : color;
|
|
5031
|
+
ctx.moveTo(rect.x + rect.width / 2, rect.y + 1);
|
|
5032
|
+
ctx.lineTo(rect.x + rect.width - 2, rect.y + 6);
|
|
5033
|
+
ctx.lineTo(rect.x + 2, rect.y + 6);
|
|
5034
|
+
ctx.closePath();
|
|
5035
|
+
ctx.fill();
|
|
5036
|
+
ctx.beginPath();
|
|
5037
|
+
ctx.fillStyle = sortOrder === "descend" ? activeColor : color;
|
|
5038
|
+
ctx.moveTo(rect.x + 2, rect.y + rect.height - 6);
|
|
5039
|
+
ctx.lineTo(rect.x + rect.width - 2, rect.y + rect.height - 6);
|
|
5040
|
+
ctx.lineTo(rect.x + rect.width / 2, rect.y + rect.height - 1);
|
|
5041
|
+
ctx.closePath();
|
|
5042
|
+
ctx.fill();
|
|
5043
|
+
} else if (actionType === "filter") {
|
|
5044
|
+
drawFilterIcon(ctx, rect);
|
|
5045
|
+
} else {
|
|
5046
|
+
drawFixedPinIcon(ctx, rect);
|
|
5047
|
+
}
|
|
5048
|
+
ctx.restore();
|
|
5049
|
+
}
|
|
5050
|
+
function drawFilterIcon(ctx, rect) {
|
|
5051
|
+
const iconWidth = rect.width * 0.92;
|
|
5052
|
+
const iconHeight = rect.height * 0.7;
|
|
5053
|
+
const offsetX = rect.x + (rect.width - iconWidth) / 2;
|
|
5054
|
+
const offsetY = rect.y + (rect.height - iconHeight) / 2;
|
|
5055
|
+
const path = resolveIconPath("filter");
|
|
5056
|
+
if (path) {
|
|
5057
|
+
ctx.save();
|
|
5058
|
+
ctx.translate(offsetX, offsetY);
|
|
5059
|
+
ctx.scale(
|
|
5060
|
+
iconWidth / FILTER_ICON_VIEWBOX_SIZE,
|
|
5061
|
+
iconHeight / FILTER_ICON_VIEWBOX_SIZE
|
|
5062
|
+
);
|
|
5063
|
+
ctx.fill(path);
|
|
5064
|
+
ctx.restore();
|
|
5065
|
+
return;
|
|
5066
|
+
}
|
|
5067
|
+
ctx.beginPath();
|
|
5068
|
+
ctx.moveTo(offsetX, offsetY);
|
|
5069
|
+
ctx.lineTo(offsetX + iconWidth, offsetY);
|
|
5070
|
+
ctx.lineTo(offsetX + iconWidth * 0.62, offsetY + iconHeight * 0.52);
|
|
5071
|
+
ctx.lineTo(offsetX + iconWidth * 0.62, offsetY + iconHeight);
|
|
5072
|
+
ctx.lineTo(offsetX + iconWidth * 0.38, offsetY + iconHeight * 0.88);
|
|
5073
|
+
ctx.lineTo(offsetX + iconWidth * 0.38, offsetY + iconHeight * 0.52);
|
|
5074
|
+
ctx.closePath();
|
|
5075
|
+
ctx.fill();
|
|
5076
|
+
}
|
|
5077
|
+
function drawFixedPinIcon(ctx, rect) {
|
|
5078
|
+
const iconSize = Math.min(rect.width, rect.height) * 0.92;
|
|
5079
|
+
const offsetX = rect.x + (rect.width - iconSize) / 2;
|
|
5080
|
+
const offsetY = rect.y + (rect.height - iconSize) / 2;
|
|
5081
|
+
const scale = iconSize / FIXED_PIN_VIEWBOX_SIZE;
|
|
5082
|
+
const path = resolveIconPath("fixed");
|
|
5083
|
+
if (path) {
|
|
5084
|
+
ctx.save();
|
|
5085
|
+
ctx.translate(offsetX, offsetY);
|
|
5086
|
+
ctx.scale(scale, scale);
|
|
5087
|
+
ctx.fill(path);
|
|
5088
|
+
ctx.restore();
|
|
5089
|
+
return;
|
|
5090
|
+
}
|
|
5091
|
+
ctx.beginPath();
|
|
5092
|
+
ctx.moveTo(offsetX + iconSize * 0.68, offsetY);
|
|
5093
|
+
ctx.lineTo(offsetX + iconSize, offsetY + iconSize * 0.32);
|
|
5094
|
+
ctx.lineTo(offsetX + iconSize * 0.78, offsetY + iconSize * 0.34);
|
|
5095
|
+
ctx.lineTo(offsetX + iconSize * 0.62, offsetY + iconSize * 0.64);
|
|
5096
|
+
ctx.lineTo(offsetX + iconSize * 0.74, offsetY + iconSize * 0.76);
|
|
5097
|
+
ctx.lineTo(offsetX + iconSize * 0.52, offsetY + iconSize * 0.82);
|
|
5098
|
+
ctx.lineTo(offsetX + iconSize * 0.16, offsetY + iconSize);
|
|
5099
|
+
ctx.lineTo(offsetX + iconSize * 0.34, offsetY + iconSize * 0.64);
|
|
5100
|
+
ctx.lineTo(offsetX + iconSize * 0.2, offsetY + iconSize * 0.5);
|
|
5101
|
+
ctx.lineTo(offsetX + iconSize * 0.5, offsetY + iconSize * 0.34);
|
|
5102
|
+
ctx.closePath();
|
|
5103
|
+
ctx.fill();
|
|
5104
|
+
}
|
|
5105
|
+
function resolveIconPath(type) {
|
|
5106
|
+
if (typeof Path2D === "undefined") return null;
|
|
5107
|
+
if (type === "filter") {
|
|
5108
|
+
filterIconPath ?? (filterIconPath = new Path2D(FILTER_ICON_PATH_DATA));
|
|
5109
|
+
return filterIconPath;
|
|
5110
|
+
}
|
|
5111
|
+
fixedPinPath ?? (fixedPinPath = new Path2D(FIXED_PIN_PATH_DATA));
|
|
5112
|
+
return fixedPinPath;
|
|
5113
|
+
}
|
|
5114
|
+
|
|
5115
|
+
// src/rendering/icons/draw-icon.ts
|
|
5116
|
+
function resolveIconColor(type, fallback = "#1f2329") {
|
|
5117
|
+
if (isLegacy(type)) return resolveCellSymbolColor(type);
|
|
5118
|
+
if (type === "check-circle") return "#52c41a";
|
|
5119
|
+
if (type === "close-circle") return "#ff4d4f";
|
|
5120
|
+
if (type === "warning") return "#faad14";
|
|
5121
|
+
if (type === "info-circle" || type === "question-circle") return "#1677ff";
|
|
5122
|
+
if (type.endsWith("TwoTone")) return "#1677ff";
|
|
5123
|
+
if (type.startsWith("header-")) return "#8c8c8c";
|
|
5124
|
+
return fallback;
|
|
5125
|
+
}
|
|
5126
|
+
function isLegacy(type) {
|
|
5127
|
+
return type === "star" || type === "sun" || type === "moon" || type === "check" || type === "close";
|
|
5128
|
+
}
|
|
5129
|
+
function drawIcon(ctx, params) {
|
|
5130
|
+
const { type, x, y, size } = params;
|
|
5131
|
+
if (![x, y, size].every(Number.isFinite) || size <= 0) return;
|
|
5132
|
+
const color = params.color ?? resolveIconColor(type);
|
|
5133
|
+
if (drawAntdIcon(ctx, { ...params, color })) return;
|
|
5134
|
+
ctx.save();
|
|
5135
|
+
try {
|
|
5136
|
+
if (type.startsWith("header-")) {
|
|
5137
|
+
ctx.translate(x, y);
|
|
5138
|
+
ctx.scale(size / 14, size / 14);
|
|
5139
|
+
drawHeaderActionGlyph(
|
|
5140
|
+
ctx,
|
|
5141
|
+
{ x: 0, y: 0, width: 14, height: 14 },
|
|
5142
|
+
type === "header-filter" ? "filter" : type === "header-fixed" ? "fixed" : "sort",
|
|
5143
|
+
color,
|
|
5144
|
+
type === "header-sort-ascending" ? "ascend" : type === "header-sort-descending" ? "descend" : null,
|
|
5145
|
+
params.color ?? "#1677ff"
|
|
5146
|
+
);
|
|
5147
|
+
return;
|
|
5148
|
+
}
|
|
5149
|
+
if (isLegacy(type)) {
|
|
5150
|
+
drawCellSymbol(ctx, {
|
|
5151
|
+
type,
|
|
5152
|
+
x,
|
|
5153
|
+
y,
|
|
5154
|
+
size,
|
|
5155
|
+
activeColor: color,
|
|
5156
|
+
inactiveColor: color,
|
|
5157
|
+
fillRatio: 1
|
|
5158
|
+
});
|
|
5159
|
+
return;
|
|
5160
|
+
}
|
|
5161
|
+
ctx.translate(x, y);
|
|
5162
|
+
ctx.scale(size / 24, size / 24);
|
|
5163
|
+
ctx.strokeStyle = color;
|
|
5164
|
+
ctx.fillStyle = color;
|
|
5165
|
+
const stroke = resolveIconStroke(ctx);
|
|
5166
|
+
ctx.lineWidth = stroke.width;
|
|
5167
|
+
ctx.lineCap = "round";
|
|
5168
|
+
ctx.lineJoin = "round";
|
|
5169
|
+
ctx.setLineDash([]);
|
|
5170
|
+
appendIconPath(ctx, type, stroke);
|
|
5171
|
+
ctx.stroke();
|
|
5172
|
+
} finally {
|
|
5173
|
+
ctx.restore();
|
|
5174
|
+
}
|
|
5175
|
+
}
|
|
5176
|
+
function appendIconPath(ctx, type, stroke) {
|
|
5177
|
+
const line = (...points) => {
|
|
5178
|
+
const aligned = [...points];
|
|
5179
|
+
for (let i = 2; i < points.length; i += 2) {
|
|
5180
|
+
if (points[i - 2] === points[i])
|
|
5181
|
+
aligned[i - 2] = aligned[i] = stroke.snapX(points[i]);
|
|
5182
|
+
if (points[i - 1] === points[i + 1])
|
|
5183
|
+
aligned[i - 1] = aligned[i + 1] = stroke.snapY(points[i + 1]);
|
|
5184
|
+
}
|
|
5185
|
+
ctx.moveTo(aligned[0], aligned[1]);
|
|
5186
|
+
for (let i = 2; i < aligned.length; i += 2)
|
|
5187
|
+
ctx.lineTo(aligned[i], aligned[i + 1]);
|
|
5188
|
+
};
|
|
5189
|
+
const rect = (x, y, width, height) => {
|
|
5190
|
+
const left = stroke.snapX(x);
|
|
5191
|
+
const top = stroke.snapY(y);
|
|
5192
|
+
ctx.rect(
|
|
5193
|
+
left,
|
|
5194
|
+
top,
|
|
5195
|
+
stroke.snapX(x + width) - left,
|
|
5196
|
+
stroke.snapY(y + height) - top
|
|
5197
|
+
);
|
|
5198
|
+
};
|
|
5199
|
+
const circle = (x = 12, y = 12, r = 9) => {
|
|
5200
|
+
ctx.moveTo(x + r, y);
|
|
5201
|
+
ctx.arc(x, y, r, 0, Math.PI * 2);
|
|
5202
|
+
};
|
|
5203
|
+
const plus = () => {
|
|
5204
|
+
line(7, 12, 17, 12);
|
|
5205
|
+
line(12, 7, 12, 17);
|
|
5206
|
+
};
|
|
5207
|
+
const check = () => line(7, 12, 10.5, 15.5, 17, 8.5);
|
|
5208
|
+
const cross = () => {
|
|
5209
|
+
line(8, 8, 16, 16);
|
|
5210
|
+
line(16, 8, 8, 16);
|
|
5211
|
+
};
|
|
5212
|
+
const file = () => {
|
|
5213
|
+
line(5, 3, 14, 3, 19, 8, 19, 21, 5, 21, 5, 3);
|
|
5214
|
+
line(14, 3, 14, 8, 19, 8);
|
|
5215
|
+
};
|
|
5216
|
+
ctx.beginPath();
|
|
5217
|
+
switch (type) {
|
|
5218
|
+
case "circle":
|
|
5219
|
+
circle();
|
|
5220
|
+
break;
|
|
5221
|
+
case "check-circle":
|
|
5222
|
+
circle();
|
|
5223
|
+
check();
|
|
5224
|
+
break;
|
|
5225
|
+
case "close-circle":
|
|
5226
|
+
circle();
|
|
5227
|
+
cross();
|
|
5228
|
+
break;
|
|
5229
|
+
case "clock-circle":
|
|
5230
|
+
circle();
|
|
5231
|
+
line(12, 6, 12, 12, 16, 14);
|
|
5232
|
+
break;
|
|
5233
|
+
case "info-circle":
|
|
5234
|
+
circle();
|
|
5235
|
+
line(12, 11, 12, 17);
|
|
5236
|
+
circle(12, 7, 0.4);
|
|
5237
|
+
break;
|
|
5238
|
+
case "question-circle":
|
|
5239
|
+
circle();
|
|
5240
|
+
ctx.moveTo(9, 8);
|
|
5241
|
+
ctx.bezierCurveTo(9, 4, 18, 6, 14, 11);
|
|
5242
|
+
line(14, 11, 12, 13, 12, 14);
|
|
5243
|
+
circle(12, 17, 0.4);
|
|
5244
|
+
break;
|
|
5245
|
+
case "warning":
|
|
5246
|
+
line(12, 3, 22, 20, 2, 20, 12, 3);
|
|
5247
|
+
line(12, 9, 12, 13);
|
|
5248
|
+
circle(12, 17, 0.4);
|
|
5249
|
+
break;
|
|
5250
|
+
case "loading":
|
|
5251
|
+
ctx.arc(12, 12, 9, -Math.PI / 2, Math.PI);
|
|
5252
|
+
break;
|
|
5253
|
+
case "plus":
|
|
5254
|
+
plus();
|
|
5255
|
+
break;
|
|
5256
|
+
case "minus":
|
|
5257
|
+
line(5, 12, 19, 12);
|
|
5258
|
+
break;
|
|
5259
|
+
case "plus-circle":
|
|
5260
|
+
circle();
|
|
5261
|
+
plus();
|
|
5262
|
+
break;
|
|
5263
|
+
case "minus-circle":
|
|
5264
|
+
circle();
|
|
5265
|
+
line(7, 12, 17, 12);
|
|
5266
|
+
break;
|
|
5267
|
+
case "up":
|
|
5268
|
+
line(5, 15, 12, 8, 19, 15);
|
|
5269
|
+
break;
|
|
5270
|
+
case "down":
|
|
5271
|
+
line(5, 9, 12, 16, 19, 9);
|
|
5272
|
+
break;
|
|
5273
|
+
case "left":
|
|
5274
|
+
line(15, 5, 8, 12, 15, 19);
|
|
5275
|
+
break;
|
|
5276
|
+
case "right":
|
|
5277
|
+
line(9, 5, 16, 12, 9, 19);
|
|
5278
|
+
break;
|
|
5279
|
+
case "arrow-up":
|
|
5280
|
+
line(12, 21, 12, 3);
|
|
5281
|
+
line(5, 10, 12, 3, 19, 10);
|
|
5282
|
+
break;
|
|
5283
|
+
case "arrow-down":
|
|
5284
|
+
line(12, 3, 12, 21);
|
|
5285
|
+
line(5, 14, 12, 21, 19, 14);
|
|
5286
|
+
break;
|
|
5287
|
+
case "arrow-left":
|
|
5288
|
+
line(21, 12, 3, 12);
|
|
5289
|
+
line(10, 5, 3, 12, 10, 19);
|
|
5290
|
+
break;
|
|
5291
|
+
case "arrow-right":
|
|
5292
|
+
line(3, 12, 21, 12);
|
|
5293
|
+
line(14, 5, 21, 12, 14, 19);
|
|
5294
|
+
break;
|
|
5295
|
+
case "search":
|
|
5296
|
+
circle(10, 10, 6.5);
|
|
5297
|
+
line(15, 15, 21, 21);
|
|
5298
|
+
break;
|
|
5299
|
+
case "edit":
|
|
5300
|
+
line(4, 15, 16, 3, 21, 8, 9, 20, 3, 21, 4, 15);
|
|
5301
|
+
line(13, 6, 18, 11);
|
|
5302
|
+
break;
|
|
5303
|
+
case "delete":
|
|
5304
|
+
line(3, 6, 21, 6);
|
|
5305
|
+
line(8, 6, 8, 3, 16, 3, 16, 6);
|
|
5306
|
+
line(5, 6, 6, 21, 18, 21, 19, 6);
|
|
5307
|
+
line(10, 10, 10, 17);
|
|
5308
|
+
line(14, 10, 14, 17);
|
|
5309
|
+
break;
|
|
5310
|
+
case "copy":
|
|
5311
|
+
rect(8, 8, 13, 13);
|
|
5312
|
+
line(16, 5, 16, 3, 3, 3, 3, 16, 5, 16);
|
|
5313
|
+
break;
|
|
5314
|
+
case "save":
|
|
5315
|
+
line(3, 3, 17, 3, 21, 7, 21, 21, 3, 21, 3, 3);
|
|
5316
|
+
rect(7, 3, 9, 6);
|
|
5317
|
+
rect(7, 14, 10, 7);
|
|
5318
|
+
break;
|
|
5319
|
+
case "upload":
|
|
5320
|
+
line(12, 17, 12, 3);
|
|
5321
|
+
line(7, 8, 12, 3, 17, 8);
|
|
5322
|
+
line(3, 16, 3, 21, 21, 21, 21, 16);
|
|
5323
|
+
break;
|
|
5324
|
+
case "download":
|
|
5325
|
+
line(12, 3, 12, 17);
|
|
5326
|
+
line(7, 12, 12, 17, 17, 12);
|
|
5327
|
+
line(3, 16, 3, 21, 21, 21, 21, 16);
|
|
5328
|
+
break;
|
|
5329
|
+
case "reload": {
|
|
5330
|
+
const end = Math.PI * 11 / 6;
|
|
5331
|
+
ctx.arc(12, 12, 8, Math.PI / 6, end);
|
|
5332
|
+
const tipX = 12 + 8 * Math.cos(end);
|
|
5333
|
+
const tipY = 12 + 8 * Math.sin(end);
|
|
5334
|
+
const arrowAngle = end + Math.PI / 2 - Math.PI / 9;
|
|
5335
|
+
const tangentX = Math.cos(arrowAngle);
|
|
5336
|
+
const tangentY = Math.sin(arrowAngle);
|
|
5337
|
+
const baseX = tipX - tangentX * 4;
|
|
5338
|
+
const baseY = tipY - tangentY * 4;
|
|
5339
|
+
line(
|
|
5340
|
+
baseX - tangentY * 3,
|
|
5341
|
+
baseY + tangentX * 3,
|
|
5342
|
+
tipX,
|
|
5343
|
+
tipY,
|
|
5344
|
+
baseX + tangentY * 3,
|
|
5345
|
+
baseY - tangentX * 3
|
|
5346
|
+
);
|
|
5347
|
+
break;
|
|
5348
|
+
}
|
|
5349
|
+
case "ellipsis":
|
|
5350
|
+
circle(5, 12, 1);
|
|
5351
|
+
circle(12, 12, 1);
|
|
5352
|
+
circle(19, 12, 1);
|
|
5353
|
+
break;
|
|
5354
|
+
case "file":
|
|
5355
|
+
file();
|
|
5356
|
+
break;
|
|
5357
|
+
case "file-text":
|
|
5358
|
+
file();
|
|
5359
|
+
line(8, 12, 16, 12);
|
|
5360
|
+
line(8, 16, 16, 16);
|
|
5361
|
+
break;
|
|
5362
|
+
case "file-pdf":
|
|
5363
|
+
file();
|
|
5364
|
+
line(8, 17, 8, 11, 11, 11, 12, 12, 12, 14, 8, 14);
|
|
5365
|
+
line(14, 17, 14, 12, 17, 12);
|
|
5366
|
+
line(14, 14.5, 16, 14.5);
|
|
5367
|
+
break;
|
|
5368
|
+
case "folder":
|
|
5369
|
+
line(2, 5, 9, 5, 11, 8, 22, 8, 22, 20, 2, 20, 2, 5);
|
|
5370
|
+
break;
|
|
5371
|
+
case "folder-open":
|
|
5372
|
+
line(2, 18, 2, 5, 9, 5, 11, 8, 20, 8, 20, 10);
|
|
5373
|
+
line(2, 20, 6, 11, 22, 11, 18, 20, 2, 20);
|
|
5374
|
+
break;
|
|
5375
|
+
case "picture":
|
|
5376
|
+
rect(3, 3, 18, 18);
|
|
5377
|
+
circle(8, 8, 2);
|
|
5378
|
+
line(3, 19, 9, 13, 13, 16, 17, 11, 21, 15);
|
|
5379
|
+
break;
|
|
5380
|
+
case "user":
|
|
5381
|
+
circle(12, 7, 4);
|
|
5382
|
+
ctx.moveTo(4, 21);
|
|
5383
|
+
ctx.bezierCurveTo(4, 10, 20, 10, 20, 21);
|
|
5384
|
+
break;
|
|
5385
|
+
case "team":
|
|
5386
|
+
circle(9, 7, 3.5);
|
|
5387
|
+
ctx.moveTo(2, 21);
|
|
5388
|
+
ctx.bezierCurveTo(2, 11, 16, 11, 16, 21);
|
|
5389
|
+
ctx.moveTo(17, 4);
|
|
5390
|
+
ctx.arc(17, 7, 3, -Math.PI / 2, Math.PI / 2);
|
|
5391
|
+
ctx.moveTo(18, 14);
|
|
5392
|
+
ctx.bezierCurveTo(22, 14, 22, 18, 22, 21);
|
|
5393
|
+
break;
|
|
5394
|
+
case "calendar":
|
|
5395
|
+
rect(3, 5, 18, 16);
|
|
5396
|
+
line(3, 10, 21, 10);
|
|
5397
|
+
line(8, 2, 8, 7);
|
|
5398
|
+
line(16, 2, 16, 7);
|
|
5399
|
+
line(7, 14, 10, 14);
|
|
5400
|
+
line(14, 14, 17, 14);
|
|
5401
|
+
line(7, 17, 10, 17);
|
|
5402
|
+
break;
|
|
5403
|
+
case "filter":
|
|
5404
|
+
line(3, 3, 21, 3, 14, 12, 14, 20, 10, 22, 10, 12, 3, 3);
|
|
5405
|
+
break;
|
|
5406
|
+
case "sort-ascending":
|
|
5407
|
+
line(4, 6, 18, 6);
|
|
5408
|
+
line(4, 12, 13, 12);
|
|
5409
|
+
line(4, 18, 8, 18);
|
|
5410
|
+
line(19, 10, 19, 21);
|
|
5411
|
+
line(16, 18, 19, 21, 22, 18);
|
|
5412
|
+
break;
|
|
5413
|
+
case "sort-descending":
|
|
5414
|
+
line(4, 6, 8, 6);
|
|
5415
|
+
line(4, 12, 13, 12);
|
|
5416
|
+
line(4, 18, 15, 18);
|
|
5417
|
+
line(19, 3, 19, 14);
|
|
5418
|
+
line(16, 6, 19, 3, 22, 6);
|
|
5419
|
+
break;
|
|
5420
|
+
case "link":
|
|
5421
|
+
line(8, 16, 16, 8);
|
|
5422
|
+
ctx.moveTo(10, 6);
|
|
5423
|
+
ctx.bezierCurveTo(16, -2, 26, 8, 18, 14);
|
|
5424
|
+
ctx.moveTo(14, 18);
|
|
5425
|
+
ctx.bezierCurveTo(8, 26, -2, 16, 6, 10);
|
|
5426
|
+
break;
|
|
5427
|
+
case "eye":
|
|
5428
|
+
ctx.moveTo(2, 12);
|
|
5429
|
+
ctx.bezierCurveTo(8, 2, 16, 2, 22, 12);
|
|
5430
|
+
ctx.bezierCurveTo(16, 22, 8, 22, 2, 12);
|
|
5431
|
+
circle(12, 12, 3);
|
|
5432
|
+
break;
|
|
5433
|
+
case "lock":
|
|
5434
|
+
rect(5, 10, 14, 11);
|
|
5435
|
+
ctx.moveTo(8, 10);
|
|
5436
|
+
ctx.lineTo(8, 7);
|
|
5437
|
+
ctx.arc(12, 7, 4, Math.PI, Math.PI * 2);
|
|
5438
|
+
ctx.lineTo(16, 10);
|
|
5439
|
+
line(12, 14, 12, 17);
|
|
5440
|
+
break;
|
|
5441
|
+
case "unlock":
|
|
5442
|
+
rect(5, 10, 14, 11);
|
|
5443
|
+
ctx.moveTo(8, 10);
|
|
5444
|
+
ctx.lineTo(8, 6);
|
|
5445
|
+
ctx.arc(12, 6, 4, Math.PI, Math.PI * 2);
|
|
5446
|
+
line(12, 14, 12, 17);
|
|
5447
|
+
break;
|
|
5448
|
+
case "home":
|
|
5449
|
+
line(2, 11, 12, 2, 22, 11);
|
|
5450
|
+
line(5, 9, 5, 21, 19, 21, 19, 9);
|
|
5451
|
+
line(9, 21, 9, 14, 15, 14, 15, 21);
|
|
5452
|
+
break;
|
|
5453
|
+
case "mail":
|
|
5454
|
+
rect(3, 5, 18, 14);
|
|
5455
|
+
line(3, 5, 12, 13, 21, 5);
|
|
5456
|
+
break;
|
|
5457
|
+
case "setting": {
|
|
5458
|
+
for (let i = 0; i <= 32; i++) {
|
|
5459
|
+
const angle = i / 32 * Math.PI * 2;
|
|
5460
|
+
const radius = i % 4 < 2 ? 10 : 8;
|
|
5461
|
+
const x = 12 + radius * Math.cos(angle);
|
|
5462
|
+
const y = 12 + radius * Math.sin(angle);
|
|
5463
|
+
if (!i) ctx.moveTo(x, y);
|
|
5464
|
+
else ctx.lineTo(x, y);
|
|
5465
|
+
}
|
|
5466
|
+
ctx.closePath();
|
|
5467
|
+
circle(12, 12, 3.5);
|
|
5468
|
+
break;
|
|
5469
|
+
}
|
|
5470
|
+
}
|
|
5471
|
+
}
|
|
5472
|
+
|
|
5473
|
+
// src/rendering/icons/draw-timeline-marker.ts
|
|
5474
|
+
var COLORS = {
|
|
5475
|
+
blue: "#1677ff",
|
|
5476
|
+
green: "#52c41a",
|
|
5477
|
+
red: "#ff4d4f",
|
|
5478
|
+
gray: "#8c8c8c"
|
|
5479
|
+
};
|
|
5480
|
+
function drawTimelineMarker(ctx, item, x, y, size, filled) {
|
|
5481
|
+
const color = COLORS[item.color ?? "blue"] ?? item.color ?? COLORS.blue;
|
|
5482
|
+
const radius = size / 2;
|
|
5483
|
+
ctx.save();
|
|
5484
|
+
try {
|
|
5485
|
+
if (item.loading) {
|
|
5486
|
+
drawIcon(ctx, {
|
|
5487
|
+
type: "loading",
|
|
5488
|
+
x: x - radius,
|
|
5489
|
+
y: y - radius,
|
|
5490
|
+
size,
|
|
5491
|
+
color
|
|
5492
|
+
});
|
|
5493
|
+
return;
|
|
5494
|
+
}
|
|
5495
|
+
const icon = item.icon ?? "circle";
|
|
5496
|
+
const type = icon === "cross" ? "close" : icon === "clock" ? "clock-circle" : icon;
|
|
5497
|
+
if (!filled && type.endsWith("-circle")) {
|
|
5498
|
+
const iconSize = size * 4 / 3;
|
|
5499
|
+
drawIcon(ctx, {
|
|
5500
|
+
type,
|
|
5501
|
+
x: x - iconSize / 2,
|
|
5502
|
+
y: y - iconSize / 2,
|
|
5503
|
+
size: iconSize,
|
|
5504
|
+
color
|
|
5505
|
+
});
|
|
5506
|
+
return;
|
|
5507
|
+
}
|
|
5508
|
+
ctx.strokeStyle = color;
|
|
5509
|
+
ctx.fillStyle = color;
|
|
5510
|
+
ctx.lineWidth = 2;
|
|
5511
|
+
ctx.beginPath();
|
|
5512
|
+
ctx.arc(x, y, radius, 0, Math.PI * 2);
|
|
5513
|
+
if (filled) ctx.fill();
|
|
5514
|
+
else ctx.stroke();
|
|
5515
|
+
if (icon === "circle") return;
|
|
5516
|
+
drawIcon(ctx, {
|
|
5517
|
+
type,
|
|
5518
|
+
x: x - size * 0.36,
|
|
5519
|
+
y: y - size * 0.36,
|
|
5520
|
+
size: size * 0.72,
|
|
5521
|
+
color: filled ? "#fff" : color
|
|
5522
|
+
});
|
|
5523
|
+
} finally {
|
|
5524
|
+
ctx.restore();
|
|
5525
|
+
}
|
|
5526
|
+
}
|
|
5527
|
+
|
|
5528
|
+
// src/rendering/icons/file-type-icon.ts
|
|
5529
|
+
function createFileTypeIconSource(filename) {
|
|
5530
|
+
const extension = (filename.split(".").length > 1 ? filename.split(".").pop() : "FILE").toUpperCase().replace(/[^A-Z0-9]/g, "").slice(0, 4) || "FILE";
|
|
5531
|
+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28"><path d="M5 1h12l6 6v20H5z" fill="#eef4ff" stroke="#8caadb"/><path d="M17 1v7h6" fill="none" stroke="#8caadb"/><text x="14" y="20" text-anchor="middle" font-family="sans-serif" font-size="7" fill="#315b91">${extension}</text></svg>`;
|
|
5532
|
+
return `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
|
5533
|
+
}
|
|
5534
|
+
|
|
4671
5535
|
// src/rendering/cell-content/draw-icon-content.ts
|
|
4672
5536
|
var DEFAULT_ICON_SIZE = 20;
|
|
4673
5537
|
function drawBodyIconContent(params) {
|
|
@@ -4687,17 +5551,16 @@ function drawBodyIconContent(params) {
|
|
|
4687
5551
|
const size = Math.min(width, height);
|
|
4688
5552
|
const left = cursorX + (width - size) / 2;
|
|
4689
5553
|
const top = rect.y + (rect.height - size) / 2;
|
|
4690
|
-
const color = content.style?.color ?? content.color ??
|
|
5554
|
+
const color = content.style?.color ?? content.color ?? (content.icon.startsWith("header-") ? void 0 : resolveIconColor(content.icon, params.theme?.textColor));
|
|
4691
5555
|
ctx.save();
|
|
4692
5556
|
ctx.globalAlpha *= resolveContentOpacity(content);
|
|
4693
|
-
|
|
5557
|
+
drawIcon(ctx, {
|
|
4694
5558
|
type: content.icon,
|
|
4695
5559
|
x: left,
|
|
4696
5560
|
y: top,
|
|
4697
5561
|
size,
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
fillRatio: 1
|
|
5562
|
+
color,
|
|
5563
|
+
twoToneColor: content.twoToneColor
|
|
4701
5564
|
});
|
|
4702
5565
|
ctx.restore();
|
|
4703
5566
|
if (content.onClick || content.cursor) {
|
|
@@ -7496,7 +8359,7 @@ function resolveHeaderTextLayout(params) {
|
|
|
7496
8359
|
Math.min(baseX - textLeft, textRight - baseX) * 2,
|
|
7497
8360
|
0
|
|
7498
8361
|
);
|
|
7499
|
-
if (centeredWidth >= 12) {
|
|
8362
|
+
if (centeredWidth >= Math.max(params.contentWidth ?? 0, 12)) {
|
|
7500
8363
|
return {
|
|
7501
8364
|
align,
|
|
7502
8365
|
x: baseX,
|
|
@@ -7555,12 +8418,6 @@ var ACTION_GAP2 = 4;
|
|
|
7555
8418
|
var ACTION_SIZE2 = 14;
|
|
7556
8419
|
var ACTION_PADDING_INLINE2 = 10;
|
|
7557
8420
|
var GRID_LINE_OFFSET = 0.5;
|
|
7558
|
-
var FILTER_ICON_VIEWBOX_SIZE = 1024;
|
|
7559
|
-
var FILTER_ICON_PATH_DATA = "M922.366667 114.813333A53.04 53.04 0 0 0 874.666667 85.333333H149.333333a53.333333 53.333333 0 0 0-42.666666 85.333334l277.333333 369.78V917.333333a21.333333 21.333333 0 0 0 29.253333 19.806667l213.333334-85.333333A21.333333 21.333333 0 0 0 640 832V540.446667L917.333333 170.666667a53.04 53.04 0 0 0 5.033334-55.853334z";
|
|
7560
|
-
var FIXED_PIN_VIEWBOX_SIZE = 1024;
|
|
7561
|
-
var FIXED_PIN_PATH_DATA = "M963.925333 326.997333L697.002667 60.074667a25.6 25.6 0 0 0-43.52 21.845333l14.506666 99.498667-273.066666 151.381333c-91.477333-45.738667-170.666667-36.693333-234.496 27.306667a25.941333 25.941333 0 0 0 0 36.352L327.68 563.2 57.685333 930.645333a25.6 25.6 0 0 0 35.84 35.669334l366.250667-270.677334 167.765333 167.936a25.941333 25.941333 0 0 0 36.352 0c79.530667-79.701333 58.538667-165.546667 26.965334-233.813333l152.064-273.066667 99.157333 14.165334a25.6 25.6 0 0 0 26.624-13.824 25.941333 25.941333 0 0 0-4.778667-30.037334z";
|
|
7562
|
-
var filterIconPath = null;
|
|
7563
|
-
var fixedPinPath = null;
|
|
7564
8421
|
var EMPTY_RANGE_HIGHLIGHT = {
|
|
7565
8422
|
selectedColumnRange: null
|
|
7566
8423
|
};
|
|
@@ -7956,9 +8813,14 @@ function isSameRect(left, right) {
|
|
|
7956
8813
|
}
|
|
7957
8814
|
function drawResizeHandles(params, rect, columnKey, fixed) {
|
|
7958
8815
|
if (params.isResizable(columnKey)) {
|
|
8816
|
+
const rightHandleRect = getResizeHandleRect(params, rect, "right");
|
|
8817
|
+
const keys = params.leafColumnKeys;
|
|
8818
|
+
if (keys?.[keys.length - 1] === columnKey) {
|
|
8819
|
+
rightHandleRect.width += 5;
|
|
8820
|
+
}
|
|
7959
8821
|
params.descriptors.push({
|
|
7960
8822
|
kind: "resize-handle",
|
|
7961
|
-
rect:
|
|
8823
|
+
rect: rightHandleRect,
|
|
7962
8824
|
columnKey,
|
|
7963
8825
|
resizeEdge: "right",
|
|
7964
8826
|
fixed
|
|
@@ -8042,95 +8904,13 @@ function drawHeaderActionIcon(ctx, rect, actionType, active, hovered = false, se
|
|
|
8042
8904
|
ctx.fill();
|
|
8043
8905
|
ctx.restore();
|
|
8044
8906
|
}
|
|
8045
|
-
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
|
|
8049
|
-
|
|
8050
|
-
|
|
8051
|
-
|
|
8052
|
-
ctx.moveTo(rect.x + rect.width / 2, rect.y + 1);
|
|
8053
|
-
ctx.lineTo(rect.x + rect.width - 2, rect.y + 6);
|
|
8054
|
-
ctx.lineTo(rect.x + 2, rect.y + 6);
|
|
8055
|
-
ctx.closePath();
|
|
8056
|
-
ctx.fill();
|
|
8057
|
-
ctx.beginPath();
|
|
8058
|
-
ctx.fillStyle = sortOrder === "descend" ? "#1677ff" : "#8c8c8c";
|
|
8059
|
-
ctx.moveTo(rect.x + 2, rect.y + rect.height - 6);
|
|
8060
|
-
ctx.lineTo(rect.x + rect.width - 2, rect.y + rect.height - 6);
|
|
8061
|
-
ctx.lineTo(rect.x + rect.width / 2, rect.y + rect.height - 1);
|
|
8062
|
-
ctx.closePath();
|
|
8063
|
-
ctx.fill();
|
|
8064
|
-
} else if (actionType === "filter") {
|
|
8065
|
-
drawFilterIcon(ctx, rect);
|
|
8066
|
-
} else {
|
|
8067
|
-
drawFixedPinIcon(ctx, rect);
|
|
8068
|
-
}
|
|
8069
|
-
ctx.restore();
|
|
8070
|
-
}
|
|
8071
|
-
function drawFilterIcon(ctx, rect) {
|
|
8072
|
-
const iconWidth = rect.width * 0.92;
|
|
8073
|
-
const iconHeight = rect.height * 0.7;
|
|
8074
|
-
const offsetX = rect.x + (rect.width - iconWidth) / 2;
|
|
8075
|
-
const offsetY = rect.y + (rect.height - iconHeight) / 2;
|
|
8076
|
-
const path = resolveIconPath("filter");
|
|
8077
|
-
if (path) {
|
|
8078
|
-
ctx.save();
|
|
8079
|
-
ctx.translate(offsetX, offsetY);
|
|
8080
|
-
ctx.scale(
|
|
8081
|
-
iconWidth / FILTER_ICON_VIEWBOX_SIZE,
|
|
8082
|
-
iconHeight / FILTER_ICON_VIEWBOX_SIZE
|
|
8083
|
-
);
|
|
8084
|
-
ctx.fill(path);
|
|
8085
|
-
ctx.restore();
|
|
8086
|
-
return;
|
|
8087
|
-
}
|
|
8088
|
-
ctx.beginPath();
|
|
8089
|
-
ctx.moveTo(offsetX, offsetY);
|
|
8090
|
-
ctx.lineTo(offsetX + iconWidth, offsetY);
|
|
8091
|
-
ctx.lineTo(offsetX + iconWidth * 0.62, offsetY + iconHeight * 0.52);
|
|
8092
|
-
ctx.lineTo(offsetX + iconWidth * 0.62, offsetY + iconHeight);
|
|
8093
|
-
ctx.lineTo(offsetX + iconWidth * 0.38, offsetY + iconHeight * 0.88);
|
|
8094
|
-
ctx.lineTo(offsetX + iconWidth * 0.38, offsetY + iconHeight * 0.52);
|
|
8095
|
-
ctx.closePath();
|
|
8096
|
-
ctx.fill();
|
|
8097
|
-
}
|
|
8098
|
-
function drawFixedPinIcon(ctx, rect) {
|
|
8099
|
-
const iconSize = Math.min(rect.width, rect.height) * 0.92;
|
|
8100
|
-
const offsetX = rect.x + (rect.width - iconSize) / 2;
|
|
8101
|
-
const offsetY = rect.y + (rect.height - iconSize) / 2;
|
|
8102
|
-
const scale = iconSize / FIXED_PIN_VIEWBOX_SIZE;
|
|
8103
|
-
const path = resolveIconPath("fixed");
|
|
8104
|
-
if (path) {
|
|
8105
|
-
ctx.save();
|
|
8106
|
-
ctx.translate(offsetX, offsetY);
|
|
8107
|
-
ctx.scale(scale, scale);
|
|
8108
|
-
ctx.fill(path);
|
|
8109
|
-
ctx.restore();
|
|
8110
|
-
return;
|
|
8111
|
-
}
|
|
8112
|
-
ctx.beginPath();
|
|
8113
|
-
ctx.moveTo(offsetX + iconSize * 0.68, offsetY);
|
|
8114
|
-
ctx.lineTo(offsetX + iconSize, offsetY + iconSize * 0.32);
|
|
8115
|
-
ctx.lineTo(offsetX + iconSize * 0.78, offsetY + iconSize * 0.34);
|
|
8116
|
-
ctx.lineTo(offsetX + iconSize * 0.62, offsetY + iconSize * 0.64);
|
|
8117
|
-
ctx.lineTo(offsetX + iconSize * 0.74, offsetY + iconSize * 0.76);
|
|
8118
|
-
ctx.lineTo(offsetX + iconSize * 0.52, offsetY + iconSize * 0.82);
|
|
8119
|
-
ctx.lineTo(offsetX + iconSize * 0.16, offsetY + iconSize);
|
|
8120
|
-
ctx.lineTo(offsetX + iconSize * 0.34, offsetY + iconSize * 0.64);
|
|
8121
|
-
ctx.lineTo(offsetX + iconSize * 0.2, offsetY + iconSize * 0.5);
|
|
8122
|
-
ctx.lineTo(offsetX + iconSize * 0.5, offsetY + iconSize * 0.34);
|
|
8123
|
-
ctx.closePath();
|
|
8124
|
-
ctx.fill();
|
|
8125
|
-
}
|
|
8126
|
-
function resolveIconPath(type) {
|
|
8127
|
-
if (typeof Path2D === "undefined") return null;
|
|
8128
|
-
if (type === "filter") {
|
|
8129
|
-
filterIconPath ?? (filterIconPath = new Path2D(FILTER_ICON_PATH_DATA));
|
|
8130
|
-
return filterIconPath;
|
|
8131
|
-
}
|
|
8132
|
-
fixedPinPath ?? (fixedPinPath = new Path2D(FIXED_PIN_PATH_DATA));
|
|
8133
|
-
return fixedPinPath;
|
|
8907
|
+
drawHeaderActionGlyph(
|
|
8908
|
+
ctx,
|
|
8909
|
+
rect,
|
|
8910
|
+
actionType,
|
|
8911
|
+
actionType === "sort" ? "#8c8c8c" : active ? "#1677ff" : "#8c8c8c",
|
|
8912
|
+
sortOrder
|
|
8913
|
+
);
|
|
8134
8914
|
}
|
|
8135
8915
|
function drawHeaderContent(ctx, contents, x, y, maxWidth, align, requestRender) {
|
|
8136
8916
|
const gap = 4;
|
|
@@ -10884,6 +11664,131 @@ function applyTextContentStyle(ctx, content, fallbackColor, theme) {
|
|
|
10884
11664
|
ctx.textBaseline = "alphabetic";
|
|
10885
11665
|
ctx.textAlign = "left";
|
|
10886
11666
|
}
|
|
11667
|
+
|
|
11668
|
+
// src/features/editing/cascader-display.ts
|
|
11669
|
+
function normalizeCascaderDisplayPaths(options, values, strategy) {
|
|
11670
|
+
const index = /* @__PURE__ */ new Map();
|
|
11671
|
+
const visit = (items, parent, disabled = false) => items.map((item) => {
|
|
11672
|
+
const path = [...parent, item.value];
|
|
11673
|
+
const blocked = disabled || !!item.disabled;
|
|
11674
|
+
const children = visit(item.children ?? [], path, blocked);
|
|
11675
|
+
const node = {
|
|
11676
|
+
path,
|
|
11677
|
+
children,
|
|
11678
|
+
leaves: blocked ? [] : children.length ? children.flatMap((child) => child.leaves) : [JSON.stringify(path)]
|
|
11679
|
+
};
|
|
11680
|
+
index.set(JSON.stringify(path), node);
|
|
11681
|
+
return node;
|
|
11682
|
+
});
|
|
11683
|
+
const roots = visit(options, []);
|
|
11684
|
+
const selected = /* @__PURE__ */ new Set();
|
|
11685
|
+
const preserved = /* @__PURE__ */ new Map();
|
|
11686
|
+
for (const path of values) {
|
|
11687
|
+
const key = JSON.stringify(path);
|
|
11688
|
+
const leaves = index.get(key)?.leaves;
|
|
11689
|
+
if (!leaves?.length) preserved.set(key, path);
|
|
11690
|
+
else leaves.forEach((leaf) => selected.add(leaf));
|
|
11691
|
+
}
|
|
11692
|
+
const result = [];
|
|
11693
|
+
const collect = (node) => {
|
|
11694
|
+
if (node.leaves.length && node.leaves.every((leaf) => selected.has(leaf)) && (strategy === "SHOW_PARENT" || !node.children.length))
|
|
11695
|
+
result.push(node.path);
|
|
11696
|
+
else node.children.forEach(collect);
|
|
11697
|
+
};
|
|
11698
|
+
roots.forEach(collect);
|
|
11699
|
+
return [...result, ...preserved.values()];
|
|
11700
|
+
}
|
|
11701
|
+
|
|
11702
|
+
// src/features/upload/upload-preview.ts
|
|
11703
|
+
var localUrls = /* @__PURE__ */ new WeakMap();
|
|
11704
|
+
var ownedUrls = /* @__PURE__ */ new Set();
|
|
11705
|
+
function canPreviewUploadPdf(file) {
|
|
11706
|
+
return (file.type?.toLowerCase() === "application/pdf" || /\.pdf$/i.test(file.name)) && Boolean(resolveRemoteUrl(file.url) || file.originFileObj);
|
|
11707
|
+
}
|
|
11708
|
+
function previewUploadPdf(file) {
|
|
11709
|
+
if (typeof window === "undefined" || !canPreviewUploadPdf(file)) return;
|
|
11710
|
+
let url = resolveRemoteUrl(file.url);
|
|
11711
|
+
if (!url && file.originFileObj) {
|
|
11712
|
+
const raw = file.originFileObj;
|
|
11713
|
+
url = localUrls.get(raw);
|
|
11714
|
+
if (!url) {
|
|
11715
|
+
url = URL.createObjectURL(
|
|
11716
|
+
raw.type === "application/pdf" ? raw : raw.slice(0, raw.size, "application/pdf")
|
|
11717
|
+
);
|
|
11718
|
+
localUrls.set(raw, url);
|
|
11719
|
+
if (!ownedUrls.size) {
|
|
11720
|
+
window.addEventListener(
|
|
11721
|
+
"pagehide",
|
|
11722
|
+
() => {
|
|
11723
|
+
ownedUrls.forEach((source) => URL.revokeObjectURL(source));
|
|
11724
|
+
ownedUrls.clear();
|
|
11725
|
+
localUrls = /* @__PURE__ */ new WeakMap();
|
|
11726
|
+
},
|
|
11727
|
+
{ once: true }
|
|
11728
|
+
);
|
|
11729
|
+
}
|
|
11730
|
+
ownedUrls.add(url);
|
|
11731
|
+
}
|
|
11732
|
+
}
|
|
11733
|
+
if (url) window.open(url, "_blank", "noopener,noreferrer");
|
|
11734
|
+
}
|
|
11735
|
+
function resolveRemoteUrl(source) {
|
|
11736
|
+
if (!source || typeof window === "undefined") return void 0;
|
|
11737
|
+
try {
|
|
11738
|
+
const url = new URL(source, window.location.href);
|
|
11739
|
+
return ["http:", "https:", "blob:"].includes(url.protocol) ? url.href : void 0;
|
|
11740
|
+
} catch {
|
|
11741
|
+
return void 0;
|
|
11742
|
+
}
|
|
11743
|
+
}
|
|
11744
|
+
|
|
11745
|
+
// src/features/upload/upload-display.ts
|
|
11746
|
+
function normalizeUploadFiles(value) {
|
|
11747
|
+
return Array.isArray(value) ? value.filter((file) => file && typeof file.name === "string").map((file, index) => ({ ...file, uid: String(file.uid ?? index) })) : [];
|
|
11748
|
+
}
|
|
11749
|
+
function isUploadImage(file) {
|
|
11750
|
+
return file.type?.startsWith("image/") || /\.(png|jpe?g|gif|webp|bmp|avif|svg)$/i.test(file.name);
|
|
11751
|
+
}
|
|
11752
|
+
function uploadImageSource(file) {
|
|
11753
|
+
const source = file.thumbUrl || file.url || "";
|
|
11754
|
+
return /^(https?:|blob:|data:image\/)/i.test(source) || /^(\/|\.\/|\.\.\/)/.test(source) ? source : "";
|
|
11755
|
+
}
|
|
11756
|
+
function resolveUploadContents(value, editable = false) {
|
|
11757
|
+
return normalizeUploadFiles(value).flatMap((file) => {
|
|
11758
|
+
const src = isUploadImage(file) ? uploadImageSource(file) : "";
|
|
11759
|
+
if (src)
|
|
11760
|
+
return [
|
|
11761
|
+
{
|
|
11762
|
+
type: "image",
|
|
11763
|
+
src,
|
|
11764
|
+
alt: file.name,
|
|
11765
|
+
style: { width: 24, height: 24 }
|
|
11766
|
+
}
|
|
11767
|
+
];
|
|
11768
|
+
const preview = canPreviewUploadPdf(file) ? { cursor: "pointer", onClick: () => previewUploadPdf(file) } : {};
|
|
11769
|
+
const directPreview = editable ? {} : preview;
|
|
11770
|
+
return [
|
|
11771
|
+
{
|
|
11772
|
+
type: "image",
|
|
11773
|
+
src: createFileTypeIconSource(file.name),
|
|
11774
|
+
preview: false,
|
|
11775
|
+
...directPreview,
|
|
11776
|
+
style: { width: 24, height: 24 }
|
|
11777
|
+
},
|
|
11778
|
+
{ type: "text", text: file.name, ...directPreview },
|
|
11779
|
+
...editable && preview.onClick ? [
|
|
11780
|
+
{
|
|
11781
|
+
type: "button",
|
|
11782
|
+
text: "\u9884\u89C8",
|
|
11783
|
+
buttonType: "link",
|
|
11784
|
+
...preview
|
|
11785
|
+
}
|
|
11786
|
+
] : []
|
|
11787
|
+
];
|
|
11788
|
+
});
|
|
11789
|
+
}
|
|
11790
|
+
|
|
11791
|
+
// src/features/editing/editing-utils.ts
|
|
10887
11792
|
function canEditCell(column, context) {
|
|
10888
11793
|
if (!column || column.key === ROW_SELECTION_COLUMN_KEY || column.key === ROW_SELECTOR_COLUMN_KEY || column.key === EXPAND_COLUMN_KEY) {
|
|
10889
11794
|
return false;
|
|
@@ -10917,7 +11822,13 @@ function getColumnEditConfig(column, context) {
|
|
|
10917
11822
|
max: resolvedFormItemProps.max,
|
|
10918
11823
|
step: resolvedFormItemProps.step,
|
|
10919
11824
|
options: resolvedFormItemProps.options,
|
|
11825
|
+
treeData: resolvedFormItemProps.treeData,
|
|
11826
|
+
upload: resolvedFormItemProps.upload,
|
|
11827
|
+
treeDefaultExpandAll: resolvedFormItemProps.treeDefaultExpandAll,
|
|
11828
|
+
treeDefaultExpandedKeys: resolvedFormItemProps.treeDefaultExpandedKeys,
|
|
10920
11829
|
changeOnSelect: resolvedFormItemProps.changeOnSelect,
|
|
11830
|
+
multiple: resolvedFormItemProps.multiple,
|
|
11831
|
+
showCheckedStrategy: resolvedFormItemProps.showCheckedStrategy,
|
|
10921
11832
|
expandTrigger: resolvedFormItemProps.expandTrigger,
|
|
10922
11833
|
allowClear: resolvedFormItemProps.allowClear,
|
|
10923
11834
|
displayRender: resolvedFormItemProps.displayRender,
|
|
@@ -10954,16 +11865,43 @@ function resolveFormattedCellText(params) {
|
|
|
10954
11865
|
if (formatter === "") {
|
|
10955
11866
|
return "";
|
|
10956
11867
|
}
|
|
11868
|
+
if (resolvedFormItemProps?.valueType === "upload") {
|
|
11869
|
+
return normalizeUploadFiles(value).map((file) => file.name).join("\u3001");
|
|
11870
|
+
}
|
|
11871
|
+
if (resolvedFormItemProps?.valueType === "tree-select") {
|
|
11872
|
+
const titles = /* @__PURE__ */ new Map();
|
|
11873
|
+
const pending = [...resolvedFormItemProps.treeData ?? []];
|
|
11874
|
+
while (pending.length) {
|
|
11875
|
+
const node = pending.pop();
|
|
11876
|
+
titles.set(node.value, node.title);
|
|
11877
|
+
if (node.children) pending.push(...node.children);
|
|
11878
|
+
}
|
|
11879
|
+
const values = resolvedFormItemProps.multiple ? Array.isArray(value) ? value : [] : [value];
|
|
11880
|
+
return [
|
|
11881
|
+
...new Set(
|
|
11882
|
+
values.filter(
|
|
11883
|
+
(part) => typeof part === "string" || typeof part === "number"
|
|
11884
|
+
)
|
|
11885
|
+
)
|
|
11886
|
+
].map((part) => titles.get(part) ?? String(part)).join("\uFF1B");
|
|
11887
|
+
}
|
|
10957
11888
|
if (resolvedFormItemProps?.valueType === "cascader" && Array.isArray(value)) {
|
|
10958
|
-
|
|
10959
|
-
|
|
10960
|
-
|
|
10961
|
-
const
|
|
10962
|
-
|
|
10963
|
-
|
|
10964
|
-
|
|
10965
|
-
|
|
10966
|
-
|
|
11889
|
+
const formatPath = (path) => {
|
|
11890
|
+
let options = resolvedFormItemProps.options ?? [];
|
|
11891
|
+
const selectedOptions = [];
|
|
11892
|
+
const labels = path.map((part) => {
|
|
11893
|
+
const option = options.find((item) => item.value === part);
|
|
11894
|
+
options = option?.children ?? [];
|
|
11895
|
+
if (option) selectedOptions.push(option);
|
|
11896
|
+
return option?.label ?? String(part ?? "");
|
|
11897
|
+
});
|
|
11898
|
+
return resolvedFormItemProps.displayRender?.(labels, selectedOptions) ?? labels.join(" / ");
|
|
11899
|
+
};
|
|
11900
|
+
return resolvedFormItemProps.multiple ? normalizeCascaderDisplayPaths(
|
|
11901
|
+
resolvedFormItemProps.options ?? [],
|
|
11902
|
+
value.filter(Array.isArray),
|
|
11903
|
+
resolvedFormItemProps.showCheckedStrategy ?? "SHOW_PARENT"
|
|
11904
|
+
).map(formatPath).join("\uFF1B") : formatPath(value);
|
|
10967
11905
|
}
|
|
10968
11906
|
if (Array.isArray(value) && (resolvedFormItemProps?.valueType === "date-range" || resolvedFormItemProps?.valueType === "datetime-range" || resolvedFormItemProps?.valueType === "timerange")) {
|
|
10969
11907
|
const [start = "", end = ""] = value;
|
|
@@ -11056,6 +11994,196 @@ function resolveColumnFormItemProps(column, context) {
|
|
|
11056
11994
|
return column.formItemProps;
|
|
11057
11995
|
}
|
|
11058
11996
|
|
|
11997
|
+
// src/rendering/cell-content/draw-timeline-content.ts
|
|
11998
|
+
function positive(value, fallback) {
|
|
11999
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
12000
|
+
}
|
|
12001
|
+
function timelineItems(content) {
|
|
12002
|
+
const items = content.items ?? [];
|
|
12003
|
+
return content.reverse ? [...items].reverse() : items;
|
|
12004
|
+
}
|
|
12005
|
+
function timelinePlainText(content) {
|
|
12006
|
+
return timelineItems(content).map((item) => [item.title, item.content].filter(Boolean).join(" ")).join("\n");
|
|
12007
|
+
}
|
|
12008
|
+
function measureTimelineWidth(content) {
|
|
12009
|
+
return positive(content.style?.width ?? content.width, 220);
|
|
12010
|
+
}
|
|
12011
|
+
function wrap(ctx, text, width) {
|
|
12012
|
+
const lines = [];
|
|
12013
|
+
for (const paragraph of String(text ?? "").split(/\r?\n/)) {
|
|
12014
|
+
let line = "";
|
|
12015
|
+
for (const character of paragraph) {
|
|
12016
|
+
if (line && ctx.measureText(line + character).width > width) {
|
|
12017
|
+
lines.push(line);
|
|
12018
|
+
line = "";
|
|
12019
|
+
}
|
|
12020
|
+
line += character;
|
|
12021
|
+
}
|
|
12022
|
+
lines.push(line);
|
|
12023
|
+
}
|
|
12024
|
+
return lines;
|
|
12025
|
+
}
|
|
12026
|
+
function layoutTimeline(ctx, content, theme, availableWidth = measureTimelineWidth(content)) {
|
|
12027
|
+
const width = Math.max(
|
|
12028
|
+
1,
|
|
12029
|
+
Math.min(measureTimelineWidth(content), availableWidth)
|
|
12030
|
+
);
|
|
12031
|
+
const fontSize = positive(
|
|
12032
|
+
resolveContentFontSize(content, theme.fontSize),
|
|
12033
|
+
theme.fontSize
|
|
12034
|
+
);
|
|
12035
|
+
const font = buildCanvasFont({
|
|
12036
|
+
fontSize,
|
|
12037
|
+
fontFamily: resolveContentFontFamily(content, theme),
|
|
12038
|
+
fontWeight: resolveContentFontWeight(content)
|
|
12039
|
+
});
|
|
12040
|
+
const lineHeight = Math.ceil(fontSize * 1.5);
|
|
12041
|
+
const dot = Math.min(positive(content.dotSize, 16), lineHeight);
|
|
12042
|
+
const gap = typeof content.itemGap === "number" && Number.isFinite(content.itemGap) ? Math.max(0, content.itemGap) : 12;
|
|
12043
|
+
const items = timelineItems(content);
|
|
12044
|
+
const mode = content.mode ?? "start";
|
|
12045
|
+
const paired = mode === "alternate" || items.some(
|
|
12046
|
+
(item) => item.title || item.position && item.position !== mode
|
|
12047
|
+
);
|
|
12048
|
+
const axis = paired ? width / 2 : mode === "end" ? width - dot / 2 - 1 : dot / 2 + 1;
|
|
12049
|
+
const gutter = dot / 2 + 8;
|
|
12050
|
+
const leftWidth = Math.max(1, axis - gutter);
|
|
12051
|
+
const rightWidth = Math.max(1, width - axis - gutter);
|
|
12052
|
+
let height = 0;
|
|
12053
|
+
ctx.save();
|
|
12054
|
+
ctx.font = font;
|
|
12055
|
+
const nodes = items.map((item, index) => {
|
|
12056
|
+
const position = item.position ?? (mode === "alternate" ? index % 2 ? "end" : "start" : mode);
|
|
12057
|
+
const onRight = position === "start";
|
|
12058
|
+
const textWidth = onRight ? rightWidth : leftWidth;
|
|
12059
|
+
const titleWidth = onRight ? leftWidth : rightWidth;
|
|
12060
|
+
const lines = wrap(ctx, item.content, textWidth);
|
|
12061
|
+
const titles = item.title ? wrap(ctx, item.title, titleWidth) : [];
|
|
12062
|
+
const nodeHeight = Math.max(lines.length, titles.length, 1) * lineHeight;
|
|
12063
|
+
const node = {
|
|
12064
|
+
item,
|
|
12065
|
+
onRight,
|
|
12066
|
+
lines,
|
|
12067
|
+
titles,
|
|
12068
|
+
y: height,
|
|
12069
|
+
height: nodeHeight,
|
|
12070
|
+
textWidth,
|
|
12071
|
+
titleWidth
|
|
12072
|
+
};
|
|
12073
|
+
height += nodeHeight + (index < items.length - 1 ? gap : 0);
|
|
12074
|
+
return node;
|
|
12075
|
+
});
|
|
12076
|
+
ctx.restore();
|
|
12077
|
+
return {
|
|
12078
|
+
width,
|
|
12079
|
+
height,
|
|
12080
|
+
font,
|
|
12081
|
+
fontSize,
|
|
12082
|
+
lineHeight,
|
|
12083
|
+
dot,
|
|
12084
|
+
axis,
|
|
12085
|
+
gutter,
|
|
12086
|
+
nodes
|
|
12087
|
+
};
|
|
12088
|
+
}
|
|
12089
|
+
function drawBodyTimelineContent(params) {
|
|
12090
|
+
const {
|
|
12091
|
+
ctx,
|
|
12092
|
+
content,
|
|
12093
|
+
theme,
|
|
12094
|
+
rect,
|
|
12095
|
+
cursorX,
|
|
12096
|
+
descriptors,
|
|
12097
|
+
column,
|
|
12098
|
+
rowIndex,
|
|
12099
|
+
contentIndex,
|
|
12100
|
+
frozen
|
|
12101
|
+
} = params;
|
|
12102
|
+
const layout = layoutTimeline(ctx, content, theme, rect.width);
|
|
12103
|
+
if (!layout.nodes.length) return;
|
|
12104
|
+
const top = rect.y + Math.max(0, (rect.height - layout.height) / 2);
|
|
12105
|
+
const axis = cursorX + layout.axis;
|
|
12106
|
+
ctx.save();
|
|
12107
|
+
ctx.beginPath();
|
|
12108
|
+
ctx.rect(cursorX, top, layout.width, Math.min(layout.height, rect.height));
|
|
12109
|
+
ctx.clip();
|
|
12110
|
+
ctx.globalAlpha *= resolveContentOpacity(content);
|
|
12111
|
+
ctx.font = layout.font;
|
|
12112
|
+
ctx.textBaseline = "middle";
|
|
12113
|
+
layout.nodes.forEach((node, index) => {
|
|
12114
|
+
const centerY = top + node.y + layout.lineHeight / 2;
|
|
12115
|
+
const next = layout.nodes[index + 1];
|
|
12116
|
+
if (next) {
|
|
12117
|
+
ctx.strokeStyle = content.lineColor ?? theme.borderColor;
|
|
12118
|
+
ctx.lineWidth = 1;
|
|
12119
|
+
ctx.setLineDash(node.item.loading || next.item.loading ? [3, 3] : []);
|
|
12120
|
+
ctx.beginPath();
|
|
12121
|
+
ctx.moveTo(axis, centerY + layout.dot / 2 + 2);
|
|
12122
|
+
ctx.lineTo(
|
|
12123
|
+
axis,
|
|
12124
|
+
top + next.y + layout.lineHeight / 2 - layout.dot / 2 - 2
|
|
12125
|
+
);
|
|
12126
|
+
ctx.stroke();
|
|
12127
|
+
ctx.setLineDash([]);
|
|
12128
|
+
}
|
|
12129
|
+
drawTimelineMarker(
|
|
12130
|
+
ctx,
|
|
12131
|
+
node.item,
|
|
12132
|
+
axis,
|
|
12133
|
+
centerY,
|
|
12134
|
+
layout.dot,
|
|
12135
|
+
content.variant === "filled"
|
|
12136
|
+
);
|
|
12137
|
+
const drawLines = (lines, right, width, color) => {
|
|
12138
|
+
const x = right ? axis + layout.gutter : cursorX;
|
|
12139
|
+
ctx.save();
|
|
12140
|
+
ctx.beginPath();
|
|
12141
|
+
ctx.rect(x, top + node.y, width, node.height);
|
|
12142
|
+
ctx.clip();
|
|
12143
|
+
ctx.fillStyle = color;
|
|
12144
|
+
ctx.textAlign = right ? "left" : "right";
|
|
12145
|
+
lines.forEach(
|
|
12146
|
+
(line, lineIndex) => ctx.fillText(
|
|
12147
|
+
line,
|
|
12148
|
+
right ? x : axis - layout.gutter,
|
|
12149
|
+
centerY + lineIndex * layout.lineHeight
|
|
12150
|
+
)
|
|
12151
|
+
);
|
|
12152
|
+
ctx.restore();
|
|
12153
|
+
};
|
|
12154
|
+
drawLines(
|
|
12155
|
+
node.lines,
|
|
12156
|
+
node.onRight,
|
|
12157
|
+
node.textWidth,
|
|
12158
|
+
content.style?.color ?? theme.textColor
|
|
12159
|
+
);
|
|
12160
|
+
drawLines(
|
|
12161
|
+
node.titles,
|
|
12162
|
+
!node.onRight,
|
|
12163
|
+
node.titleWidth,
|
|
12164
|
+
content.titleColor ?? theme.mutedTextColor ?? theme.textColor
|
|
12165
|
+
);
|
|
12166
|
+
});
|
|
12167
|
+
ctx.restore();
|
|
12168
|
+
descriptors.push({
|
|
12169
|
+
kind: "body-content",
|
|
12170
|
+
rect: {
|
|
12171
|
+
x: cursorX,
|
|
12172
|
+
y: top,
|
|
12173
|
+
width: layout.width,
|
|
12174
|
+
height: Math.min(layout.height, rect.height)
|
|
12175
|
+
},
|
|
12176
|
+
rowIndex,
|
|
12177
|
+
columnKey: column.key,
|
|
12178
|
+
fixed: column.fixed,
|
|
12179
|
+
frozen,
|
|
12180
|
+
contentIndex,
|
|
12181
|
+
contentKey: content.key,
|
|
12182
|
+
cursor: content.cursor ?? (content.onClick ? "pointer" : void 0),
|
|
12183
|
+
tooltipText: timelinePlainText(content)
|
|
12184
|
+
});
|
|
12185
|
+
}
|
|
12186
|
+
|
|
11059
12187
|
// src/rendering/cell-content/cell-content-renderer.ts
|
|
11060
12188
|
var CONTENT_HORIZONTAL_PADDING = 12;
|
|
11061
12189
|
var CONTENT_GAP = 8;
|
|
@@ -11073,6 +12201,12 @@ function resolveRawBodyCellContents(params) {
|
|
|
11073
12201
|
if (rendered != null) {
|
|
11074
12202
|
return normalizeCellContents(rendered);
|
|
11075
12203
|
}
|
|
12204
|
+
if (resolveColumnFormItemProps(column, { value, record, rowIndex })?.valueType === "upload") {
|
|
12205
|
+
return resolveUploadContents(
|
|
12206
|
+
value,
|
|
12207
|
+
canEditCell(column, { value, record, rowIndex })
|
|
12208
|
+
);
|
|
12209
|
+
}
|
|
11076
12210
|
const formattedText = resolveFormattedCellText({
|
|
11077
12211
|
column,
|
|
11078
12212
|
value,
|
|
@@ -11148,6 +12282,11 @@ function resolveRawBodyCellContents(params) {
|
|
|
11148
12282
|
}
|
|
11149
12283
|
] : [];
|
|
11150
12284
|
}
|
|
12285
|
+
if (column.cellType === "timeline") {
|
|
12286
|
+
return [
|
|
12287
|
+
{ type: "timeline", items: Array.isArray(value) ? value : [] }
|
|
12288
|
+
];
|
|
12289
|
+
}
|
|
11151
12290
|
if (column.cellType === "progress") {
|
|
11152
12291
|
const numericValue = typeof value === "number" ? value : typeof value === "string" ? Number(value) : 0;
|
|
11153
12292
|
return [
|
|
@@ -11235,6 +12374,9 @@ function normalizeDrawableCellContents(contents) {
|
|
|
11235
12374
|
).map(normalizeCellContentItem);
|
|
11236
12375
|
}
|
|
11237
12376
|
function normalizeCellContentItem(content) {
|
|
12377
|
+
if (content.type === "timeline") {
|
|
12378
|
+
return { ...content, style: { ...content.style, display: "block" } };
|
|
12379
|
+
}
|
|
11238
12380
|
if (content.type !== "money") {
|
|
11239
12381
|
return content;
|
|
11240
12382
|
}
|
|
@@ -11480,7 +12622,12 @@ function drawBodyCellContents(params) {
|
|
|
11480
12622
|
);
|
|
11481
12623
|
return void 0;
|
|
11482
12624
|
}
|
|
11483
|
-
const lineHeight = getBodyCellContentsLineHeight(
|
|
12625
|
+
const lineHeight = getBodyCellContentsLineHeight(
|
|
12626
|
+
contents,
|
|
12627
|
+
theme,
|
|
12628
|
+
ctx,
|
|
12629
|
+
availableWidth
|
|
12630
|
+
);
|
|
11484
12631
|
const layout = layoutBodyCellContents({
|
|
11485
12632
|
ctx,
|
|
11486
12633
|
contents,
|
|
@@ -11653,7 +12800,12 @@ function measureBodyCellContentsHeight(params) {
|
|
|
11653
12800
|
if (availableWidth <= 0) {
|
|
11654
12801
|
return paddingBlock * 2;
|
|
11655
12802
|
}
|
|
11656
|
-
const lineHeight = getBodyCellContentsLineHeight(
|
|
12803
|
+
const lineHeight = getBodyCellContentsLineHeight(
|
|
12804
|
+
contents,
|
|
12805
|
+
theme,
|
|
12806
|
+
ctx,
|
|
12807
|
+
availableWidth
|
|
12808
|
+
);
|
|
11657
12809
|
const layout = layoutBodyCellContents({
|
|
11658
12810
|
ctx,
|
|
11659
12811
|
contents,
|
|
@@ -12132,6 +13284,7 @@ function drawExpandedBodyContent(params) {
|
|
|
12132
13284
|
if (content.type === "icon") {
|
|
12133
13285
|
drawBodyIconContent({
|
|
12134
13286
|
ctx,
|
|
13287
|
+
theme,
|
|
12135
13288
|
rect,
|
|
12136
13289
|
content,
|
|
12137
13290
|
contentIndex,
|
|
@@ -12204,6 +13357,21 @@ function drawExpandedBodyContent(params) {
|
|
|
12204
13357
|
});
|
|
12205
13358
|
return;
|
|
12206
13359
|
}
|
|
13360
|
+
if (content.type === "timeline") {
|
|
13361
|
+
drawBodyTimelineContent({
|
|
13362
|
+
ctx,
|
|
13363
|
+
rect,
|
|
13364
|
+
content,
|
|
13365
|
+
contentIndex,
|
|
13366
|
+
cursorX,
|
|
13367
|
+
rowIndex,
|
|
13368
|
+
column,
|
|
13369
|
+
theme,
|
|
13370
|
+
frozen,
|
|
13371
|
+
descriptors
|
|
13372
|
+
});
|
|
13373
|
+
return;
|
|
13374
|
+
}
|
|
12207
13375
|
if (content.type === "progress") {
|
|
12208
13376
|
drawBodyProgressContent({
|
|
12209
13377
|
ctx,
|
|
@@ -12379,6 +13547,7 @@ function measureExpandedContentWidth(ctx, content, theme) {
|
|
|
12379
13547
|
if (content.type === "button") {
|
|
12380
13548
|
return measureButtonContentWidth(ctx, content, theme);
|
|
12381
13549
|
}
|
|
13550
|
+
if (content.type === "timeline") return measureTimelineWidth(content);
|
|
12382
13551
|
if (content.type === "progress") {
|
|
12383
13552
|
return measureProgressContentWidth(ctx, content, theme);
|
|
12384
13553
|
}
|
|
@@ -12433,9 +13602,16 @@ function getBodyCellContentsLineGap(contents, lineHeight) {
|
|
|
12433
13602
|
}
|
|
12434
13603
|
return tagHeight > 0 ? Math.max(CONTENT_GAP - (lineHeight - tagHeight), 0) : 0;
|
|
12435
13604
|
}
|
|
12436
|
-
function getBodyCellContentsLineHeight(contents, theme) {
|
|
13605
|
+
function getBodyCellContentsLineHeight(contents, theme, ctx, availableWidth) {
|
|
12437
13606
|
let lineHeight = theme.fontSize + 8;
|
|
12438
13607
|
contents.forEach((item) => {
|
|
13608
|
+
if (item.type === "timeline") {
|
|
13609
|
+
lineHeight = Math.max(
|
|
13610
|
+
lineHeight,
|
|
13611
|
+
layoutTimeline(ctx, item, theme, availableWidth).height
|
|
13612
|
+
);
|
|
13613
|
+
return;
|
|
13614
|
+
}
|
|
12439
13615
|
if (item.type === "arrow") {
|
|
12440
13616
|
lineHeight = Math.max(lineHeight, measureArrowContentHeight(item));
|
|
12441
13617
|
return;
|
|
@@ -12510,6 +13686,15 @@ function getBodyCellContentsLineHeight(contents, theme) {
|
|
|
12510
13686
|
return lineHeight;
|
|
12511
13687
|
}
|
|
12512
13688
|
function truncateExpandedContent(ctx, content, theme, maxWidth, withEllipsis) {
|
|
13689
|
+
if (content.type === "timeline") {
|
|
13690
|
+
return maxWidth > 0 ? {
|
|
13691
|
+
...content,
|
|
13692
|
+
style: {
|
|
13693
|
+
...content.style,
|
|
13694
|
+
width: Math.min(measureTimelineWidth(content), maxWidth)
|
|
13695
|
+
}
|
|
13696
|
+
} : null;
|
|
13697
|
+
}
|
|
12513
13698
|
if (content.type === "text" || content.type === "link") {
|
|
12514
13699
|
const nextText = fitTextToWidth(
|
|
12515
13700
|
getBreakableContentText(content),
|
|
@@ -12659,6 +13844,7 @@ function buildBodyContentsPlainText(contents) {
|
|
|
12659
13844
|
if (content.type === "progress") {
|
|
12660
13845
|
return content.text ?? `${Math.round(resolveProgressPercent(content))}%`;
|
|
12661
13846
|
}
|
|
13847
|
+
if (content.type === "timeline") return timelinePlainText(content);
|
|
12662
13848
|
if (content.type === "chart") {
|
|
12663
13849
|
return resolveChartContentPlainText(content);
|
|
12664
13850
|
}
|
|
@@ -12973,6 +14159,7 @@ function isCellContentDisabled(content) {
|
|
|
12973
14159
|
if (content.type === "button") {
|
|
12974
14160
|
return content.disabled === true;
|
|
12975
14161
|
}
|
|
14162
|
+
if (content.type === "timeline") return false;
|
|
12976
14163
|
if (content.type === "progress") {
|
|
12977
14164
|
return false;
|
|
12978
14165
|
}
|
|
@@ -16424,6 +17611,11 @@ function getCellClipboardText(record, rowIndex, column) {
|
|
|
16424
17611
|
if (column.cellType === "checkbox" || column.cellType === "radio") {
|
|
16425
17612
|
return String(Boolean(value));
|
|
16426
17613
|
}
|
|
17614
|
+
if (column.cellType === "timeline") {
|
|
17615
|
+
return timelinePlainText({
|
|
17616
|
+
items: Array.isArray(value) ? value : []
|
|
17617
|
+
});
|
|
17618
|
+
}
|
|
16427
17619
|
return resolveFormattedCellText({
|
|
16428
17620
|
column,
|
|
16429
17621
|
value,
|
|
@@ -16574,7 +17766,7 @@ async function copyRowJsonContent(params) {
|
|
|
16574
17766
|
}
|
|
16575
17767
|
async function exportAllRowsJsonContent(params) {
|
|
16576
17768
|
await utils.downloadJsonFile({
|
|
16577
|
-
fileName: buildTableExportFileName("json"),
|
|
17769
|
+
fileName: params.fileName?.trim() || buildTableExportFileName("json"),
|
|
16578
17770
|
data: utils.mapRowsToExportRecords({
|
|
16579
17771
|
rows: params.rows,
|
|
16580
17772
|
columns: buildExportColumns(params.columns)
|
|
@@ -16583,14 +17775,14 @@ async function exportAllRowsJsonContent(params) {
|
|
|
16583
17775
|
}
|
|
16584
17776
|
async function exportAllRowsCsvContent(params) {
|
|
16585
17777
|
await utils.exportTableToCsv({
|
|
16586
|
-
fileName: buildTableExportFileName("csv"),
|
|
17778
|
+
fileName: params.fileName?.trim() || buildTableExportFileName("csv"),
|
|
16587
17779
|
rows: params.rows,
|
|
16588
17780
|
columns: buildExportColumns(params.columns)
|
|
16589
17781
|
});
|
|
16590
17782
|
}
|
|
16591
17783
|
async function exportAllRowsTxtContent(params) {
|
|
16592
17784
|
await utils.exportTableToTxt({
|
|
16593
|
-
fileName: buildTableExportFileName("txt"),
|
|
17785
|
+
fileName: params.fileName?.trim() || buildTableExportFileName("txt"),
|
|
16594
17786
|
rows: params.rows,
|
|
16595
17787
|
columns: buildExportColumns(params.columns)
|
|
16596
17788
|
});
|
|
@@ -16660,6 +17852,7 @@ function cellContentToClipboardText(content) {
|
|
|
16660
17852
|
if (content.type === "progress") {
|
|
16661
17853
|
return content.text ?? `${Math.round(resolveProgressClipboardPercent(content))}%`;
|
|
16662
17854
|
}
|
|
17855
|
+
if (content.type === "timeline") return timelinePlainText(content);
|
|
16663
17856
|
if (content.type === "chart") {
|
|
16664
17857
|
return resolveChartContentPlainText(content);
|
|
16665
17858
|
}
|
|
@@ -16872,17 +18065,21 @@ var ListTableContentActionController = class {
|
|
|
16872
18065
|
constructor(options) {
|
|
16873
18066
|
__publicField(this, "options");
|
|
16874
18067
|
__publicField(this, "exportTaskRunning", false);
|
|
18068
|
+
__publicField(this, "exportNamePending", false);
|
|
16875
18069
|
this.options = options;
|
|
16876
18070
|
}
|
|
16877
18071
|
/**
|
|
16878
18072
|
* 异步导出全部原始数据为 XLSX。
|
|
16879
18073
|
*/
|
|
16880
18074
|
exportXlsx(options) {
|
|
18075
|
+
options = { ...this.options.getOptions().exportOptions, ...options };
|
|
16881
18076
|
this.startExportTask(
|
|
16882
|
-
() => exportAllRowsXlsxContent({
|
|
18077
|
+
(fileName) => exportAllRowsXlsxContent({
|
|
16883
18078
|
rows: this.options.getOptions().dataSource,
|
|
16884
18079
|
columns: this.options.getLeafColumns(),
|
|
16885
18080
|
...options,
|
|
18081
|
+
includeSummary: options?.includeSummary ?? this.options.getSummaryVisible?.() ?? false,
|
|
18082
|
+
fileName: fileName ?? options?.fileName,
|
|
16886
18083
|
onProgress: (progress) => {
|
|
16887
18084
|
const fileLabel = progress.fileCount && progress.fileCount > 1 ? `\uFF08\u7B2C ${progress.fileIndex}/${progress.fileCount} \u4EFD\uFF09` : "";
|
|
16888
18085
|
this.options.overlayController.showLoading(
|
|
@@ -16892,16 +18089,55 @@ var ListTableContentActionController = class {
|
|
|
16892
18089
|
}
|
|
16893
18090
|
}),
|
|
16894
18091
|
"\u6B63\u5728\u5BFC\u51FA XLSX\u2026",
|
|
16895
|
-
options?.onError
|
|
18092
|
+
options?.onError,
|
|
18093
|
+
options?.fileName?.trim() ? `${options.fileName.trim().replace(/\.xlsx$/i, "")}.xlsx` : buildTableExportFileName("xlsx"),
|
|
18094
|
+
options?.promptFileName
|
|
16896
18095
|
);
|
|
16897
18096
|
}
|
|
16898
|
-
startExportTask(task, text, onError) {
|
|
16899
|
-
if (this.exportTaskRunning) {
|
|
18097
|
+
startExportTask(task, text, onError, defaultFileName, promptFileName = this.options.getOptions().exportOptions?.promptFileName ?? true) {
|
|
18098
|
+
if (this.exportTaskRunning || this.exportNamePending) {
|
|
18099
|
+
return;
|
|
18100
|
+
}
|
|
18101
|
+
if (defaultFileName !== void 0 && promptFileName) {
|
|
18102
|
+
this.exportNamePending = true;
|
|
18103
|
+
const notify = this.options.getOptions().ui?.onExportNameRequest;
|
|
18104
|
+
let settled = false;
|
|
18105
|
+
const close = () => {
|
|
18106
|
+
settled = true;
|
|
18107
|
+
this.exportNamePending = false;
|
|
18108
|
+
notify?.(null);
|
|
18109
|
+
};
|
|
18110
|
+
const request = {
|
|
18111
|
+
fileName: defaultFileName,
|
|
18112
|
+
onConfirm: (value) => {
|
|
18113
|
+
if (settled || !value.trim()) return;
|
|
18114
|
+
close();
|
|
18115
|
+
const extension = defaultFileName.match(
|
|
18116
|
+
/\.(xlsx|csv|txt|json)$/i
|
|
18117
|
+
)?.[0];
|
|
18118
|
+
const name = extension && !value.trim().toLowerCase().endsWith(extension.toLowerCase()) ? `${value.trim()}${extension}` : value.trim();
|
|
18119
|
+
this.startExportTask(() => task(name), text, onError);
|
|
18120
|
+
},
|
|
18121
|
+
onCancel: () => {
|
|
18122
|
+
if (!settled) close();
|
|
18123
|
+
}
|
|
18124
|
+
};
|
|
18125
|
+
if (notify) notify(request);
|
|
18126
|
+
else if (typeof window !== "undefined" && typeof window.prompt === "function") {
|
|
18127
|
+
const extension = defaultFileName.match(/\.(xlsx|csv|txt|json)$/i)?.[0] ?? "";
|
|
18128
|
+
const baseName = extension ? defaultFileName.slice(0, -extension.length) : defaultFileName;
|
|
18129
|
+
const value = window.prompt(
|
|
18130
|
+
`\u8BF7\u8F93\u5165\u5BFC\u51FA\u6587\u4EF6\u540D\u79F0\uFF08\u56FA\u5B9A\u540E\u7F00\uFF1A${extension}\uFF09`,
|
|
18131
|
+
baseName
|
|
18132
|
+
);
|
|
18133
|
+
if (value == null || !value.trim()) request.onCancel();
|
|
18134
|
+
else request.onConfirm(`${value.trim()}${extension}`);
|
|
18135
|
+
} else request.onConfirm(defaultFileName);
|
|
16900
18136
|
return;
|
|
16901
18137
|
}
|
|
16902
18138
|
this.exportTaskRunning = true;
|
|
16903
18139
|
this.options.overlayController.showLoading(text);
|
|
16904
|
-
void task().catch((error) => {
|
|
18140
|
+
void Promise.resolve().then(() => task(defaultFileName)).catch((error) => {
|
|
16905
18141
|
if (error?.name === "AbortError") return;
|
|
16906
18142
|
console.error("[ListTable] Failed to export table data:", error);
|
|
16907
18143
|
onError?.(error);
|
|
@@ -17179,6 +18415,312 @@ function setValueByDataIndex(record, dataIndex, value) {
|
|
|
17179
18415
|
return true;
|
|
17180
18416
|
}
|
|
17181
18417
|
|
|
18418
|
+
// src/features/upload/upload-editor.ts
|
|
18419
|
+
function createUploadEditor(params) {
|
|
18420
|
+
const config = params.config ?? {};
|
|
18421
|
+
let files = normalizeUploadFiles(params.value);
|
|
18422
|
+
let alive = true;
|
|
18423
|
+
let pending = 0;
|
|
18424
|
+
let sequence = 0;
|
|
18425
|
+
const requests = /* @__PURE__ */ new Map();
|
|
18426
|
+
const readers = /* @__PURE__ */ new Set();
|
|
18427
|
+
const root = document.createElement("div");
|
|
18428
|
+
root.setAttribute("role", "dialog");
|
|
18429
|
+
root.setAttribute("aria-label", "\u4E0A\u4F20\u9644\u4EF6");
|
|
18430
|
+
root.tabIndex = -1;
|
|
18431
|
+
const width = Math.min(360, Math.max(200, window.innerWidth - 16));
|
|
18432
|
+
Object.assign(root.style, {
|
|
18433
|
+
position: "fixed",
|
|
18434
|
+
zIndex: "10000",
|
|
18435
|
+
boxSizing: "border-box",
|
|
18436
|
+
width: `${width}px`,
|
|
18437
|
+
left: `${Math.max(8, Math.min(params.rect.x, window.innerWidth - width - 8))}px`,
|
|
18438
|
+
top: `${Math.max(8, Math.min(params.rect.y, window.innerHeight - 280))}px`,
|
|
18439
|
+
maxHeight: "calc(100vh - 16px)",
|
|
18440
|
+
overflow: "auto",
|
|
18441
|
+
padding: "12px",
|
|
18442
|
+
background: "#fff",
|
|
18443
|
+
color: "#1f2937",
|
|
18444
|
+
border: "1px solid #d9e1ec",
|
|
18445
|
+
borderRadius: "6px",
|
|
18446
|
+
boxShadow: "0 6px 24px #0002",
|
|
18447
|
+
font: "13px sans-serif"
|
|
18448
|
+
});
|
|
18449
|
+
for (const event of [
|
|
18450
|
+
"pointerdown",
|
|
18451
|
+
"mousedown",
|
|
18452
|
+
"click",
|
|
18453
|
+
"dblclick",
|
|
18454
|
+
"contextmenu"
|
|
18455
|
+
])
|
|
18456
|
+
root.addEventListener(event, (e) => e.stopPropagation());
|
|
18457
|
+
const title = document.createElement("div");
|
|
18458
|
+
title.textContent = "\u4E0A\u4F20\u9644\u4EF6";
|
|
18459
|
+
title.style.fontWeight = "600";
|
|
18460
|
+
const list = document.createElement("div");
|
|
18461
|
+
Object.assign(list.style, {
|
|
18462
|
+
maxHeight: "180px",
|
|
18463
|
+
overflow: "auto",
|
|
18464
|
+
margin: "10px 0"
|
|
18465
|
+
});
|
|
18466
|
+
const message = document.createElement("div");
|
|
18467
|
+
message.setAttribute("role", "status");
|
|
18468
|
+
message.style.color = "#c53030";
|
|
18469
|
+
const input = document.createElement("input");
|
|
18470
|
+
input.type = "file";
|
|
18471
|
+
input.accept = config.accept ?? "";
|
|
18472
|
+
input.multiple = config.multiple ?? false;
|
|
18473
|
+
input.hidden = true;
|
|
18474
|
+
const actions = document.createElement("div");
|
|
18475
|
+
Object.assign(actions.style, {
|
|
18476
|
+
display: "flex",
|
|
18477
|
+
gap: "8px",
|
|
18478
|
+
marginTop: "10px",
|
|
18479
|
+
flexWrap: "wrap"
|
|
18480
|
+
});
|
|
18481
|
+
const button = (label, callback) => {
|
|
18482
|
+
const element = document.createElement("button");
|
|
18483
|
+
element.type = "button";
|
|
18484
|
+
element.textContent = label;
|
|
18485
|
+
Object.assign(element.style, {
|
|
18486
|
+
padding: "4px 10px",
|
|
18487
|
+
border: "1px solid #cbd5e1",
|
|
18488
|
+
background: "#fff",
|
|
18489
|
+
borderRadius: "4px",
|
|
18490
|
+
cursor: "pointer",
|
|
18491
|
+
color: "inherit"
|
|
18492
|
+
});
|
|
18493
|
+
element.onclick = callback;
|
|
18494
|
+
return element;
|
|
18495
|
+
};
|
|
18496
|
+
const choose = button("\u9009\u62E9\u6587\u4EF6", () => input.click());
|
|
18497
|
+
const done = button("\u5B8C\u6210", () => {
|
|
18498
|
+
if (!pending) params.onCommit();
|
|
18499
|
+
});
|
|
18500
|
+
const cancel = button("\u53D6\u6D88", params.onCancel);
|
|
18501
|
+
actions.append(choose, done, cancel);
|
|
18502
|
+
root.append(title, list, message, input, actions);
|
|
18503
|
+
function render() {
|
|
18504
|
+
if (!alive) return;
|
|
18505
|
+
list.replaceChildren();
|
|
18506
|
+
done.disabled = pending > 0;
|
|
18507
|
+
if (!files.length) list.textContent = "\u6682\u65E0\u9644\u4EF6";
|
|
18508
|
+
for (const file of files) {
|
|
18509
|
+
const row = document.createElement("div");
|
|
18510
|
+
Object.assign(row.style, {
|
|
18511
|
+
display: "flex",
|
|
18512
|
+
alignItems: "center",
|
|
18513
|
+
gap: "8px",
|
|
18514
|
+
padding: "6px 0"
|
|
18515
|
+
});
|
|
18516
|
+
const source = isUploadImage(file) ? uploadImageSource(file) : "";
|
|
18517
|
+
if (source) {
|
|
18518
|
+
const image = document.createElement("img");
|
|
18519
|
+
image.src = source;
|
|
18520
|
+
image.alt = file.name;
|
|
18521
|
+
Object.assign(image.style, {
|
|
18522
|
+
width: "32px",
|
|
18523
|
+
height: "32px",
|
|
18524
|
+
objectFit: "contain"
|
|
18525
|
+
});
|
|
18526
|
+
row.append(image);
|
|
18527
|
+
}
|
|
18528
|
+
const label = document.createElement("span");
|
|
18529
|
+
label.textContent = `${file.name} \xB7 ${file.status === "uploading" ? `${Math.round(file.percent ?? 0)}%` : file.status === "error" ? file.error || "\u4E0A\u4F20\u5931\u8D25" : file.status === "selected" ? "\u672A\u4E0A\u4F20" : "\u5DF2\u4E0A\u4F20"}`;
|
|
18530
|
+
Object.assign(label.style, {
|
|
18531
|
+
flex: "1",
|
|
18532
|
+
minWidth: "0",
|
|
18533
|
+
overflowWrap: "anywhere"
|
|
18534
|
+
});
|
|
18535
|
+
row.append(label);
|
|
18536
|
+
if (canPreviewUploadPdf(file)) {
|
|
18537
|
+
row.append(button("\u9884\u89C8", () => previewUploadPdf(file)));
|
|
18538
|
+
}
|
|
18539
|
+
if (file.status === "error" && file.originFileObj)
|
|
18540
|
+
row.append(button("\u91CD\u8BD5", () => upload(file)));
|
|
18541
|
+
row.append(
|
|
18542
|
+
button("\u79FB\u9664", () => {
|
|
18543
|
+
requests.get(file.uid)?.();
|
|
18544
|
+
files = files.filter((item) => item !== file);
|
|
18545
|
+
render();
|
|
18546
|
+
})
|
|
18547
|
+
);
|
|
18548
|
+
list.append(row);
|
|
18549
|
+
}
|
|
18550
|
+
}
|
|
18551
|
+
function upload(file) {
|
|
18552
|
+
if (!alive || !file.originFileObj || !config.action && !config.customRequest)
|
|
18553
|
+
return;
|
|
18554
|
+
requests.get(file.uid)?.();
|
|
18555
|
+
const raw = file.originFileObj;
|
|
18556
|
+
let active = true;
|
|
18557
|
+
let abort;
|
|
18558
|
+
pending++;
|
|
18559
|
+
file.status = "uploading";
|
|
18560
|
+
file.percent = 0;
|
|
18561
|
+
const finish = () => {
|
|
18562
|
+
active = false;
|
|
18563
|
+
pending--;
|
|
18564
|
+
requests.delete(file.uid);
|
|
18565
|
+
};
|
|
18566
|
+
requests.set(file.uid, () => {
|
|
18567
|
+
if (!active) return;
|
|
18568
|
+
finish();
|
|
18569
|
+
abort?.();
|
|
18570
|
+
});
|
|
18571
|
+
const onError = (error) => {
|
|
18572
|
+
if (!active || !alive) return;
|
|
18573
|
+
finish();
|
|
18574
|
+
file.status = "error";
|
|
18575
|
+
file.error = error.message || "\u4E0A\u4F20\u5931\u8D25";
|
|
18576
|
+
render();
|
|
18577
|
+
};
|
|
18578
|
+
const onSuccess = (response) => {
|
|
18579
|
+
if (!active || !alive) return;
|
|
18580
|
+
try {
|
|
18581
|
+
const url = config.getResponseUrl ? config.getResponseUrl(response, raw) : response && typeof response === "object" && "url" in response && typeof response.url === "string" ? response.url : void 0;
|
|
18582
|
+
file.url = url ?? file.url;
|
|
18583
|
+
file.response = response;
|
|
18584
|
+
file.status = "done";
|
|
18585
|
+
file.percent = 100;
|
|
18586
|
+
finish();
|
|
18587
|
+
render();
|
|
18588
|
+
} catch (error) {
|
|
18589
|
+
onError(error instanceof Error ? error : new Error(String(error)));
|
|
18590
|
+
}
|
|
18591
|
+
};
|
|
18592
|
+
const onProgress = (percent) => {
|
|
18593
|
+
if (alive && active) {
|
|
18594
|
+
file.percent = Math.max(0, Math.min(100, percent));
|
|
18595
|
+
render();
|
|
18596
|
+
}
|
|
18597
|
+
};
|
|
18598
|
+
try {
|
|
18599
|
+
if (config.customRequest) {
|
|
18600
|
+
const handle = config.customRequest({
|
|
18601
|
+
file: raw,
|
|
18602
|
+
onProgress,
|
|
18603
|
+
onSuccess,
|
|
18604
|
+
onError
|
|
18605
|
+
});
|
|
18606
|
+
abort = handle ? () => handle.abort() : void 0;
|
|
18607
|
+
} else {
|
|
18608
|
+
const xhr = new XMLHttpRequest();
|
|
18609
|
+
abort = () => xhr.abort();
|
|
18610
|
+
xhr.open("POST", config.action);
|
|
18611
|
+
xhr.withCredentials = config.withCredentials ?? false;
|
|
18612
|
+
for (const [key, value] of Object.entries(config.headers ?? {}))
|
|
18613
|
+
xhr.setRequestHeader(key, value);
|
|
18614
|
+
xhr.upload.onprogress = (event) => {
|
|
18615
|
+
if (event.lengthComputable)
|
|
18616
|
+
onProgress(event.loaded / event.total * 100);
|
|
18617
|
+
};
|
|
18618
|
+
xhr.onerror = () => onError(new Error("\u7F51\u7EDC\u9519\u8BEF\uFF0C\u4E0A\u4F20\u5931\u8D25"));
|
|
18619
|
+
xhr.onabort = () => onError(new Error("\u4E0A\u4F20\u5DF2\u53D6\u6D88"));
|
|
18620
|
+
xhr.onload = () => {
|
|
18621
|
+
if (xhr.status < 200 || xhr.status >= 300)
|
|
18622
|
+
return onError(new Error(`\u4E0A\u4F20\u5931\u8D25 (${xhr.status})`));
|
|
18623
|
+
let response = xhr.responseText;
|
|
18624
|
+
try {
|
|
18625
|
+
response = JSON.parse(xhr.responseText);
|
|
18626
|
+
} catch {
|
|
18627
|
+
}
|
|
18628
|
+
onSuccess(response);
|
|
18629
|
+
};
|
|
18630
|
+
const body = new FormData();
|
|
18631
|
+
for (const [key, value] of Object.entries(config.data ?? {}))
|
|
18632
|
+
body.append(key, value);
|
|
18633
|
+
body.append(config.name ?? "file", raw);
|
|
18634
|
+
xhr.send(body);
|
|
18635
|
+
}
|
|
18636
|
+
} catch (error) {
|
|
18637
|
+
onError(error instanceof Error ? error : new Error(String(error)));
|
|
18638
|
+
}
|
|
18639
|
+
render();
|
|
18640
|
+
}
|
|
18641
|
+
input.onchange = async () => {
|
|
18642
|
+
const selected = Array.from(input.files ?? []);
|
|
18643
|
+
input.value = "";
|
|
18644
|
+
message.textContent = "";
|
|
18645
|
+
pending++;
|
|
18646
|
+
render();
|
|
18647
|
+
for (const raw of selected) {
|
|
18648
|
+
try {
|
|
18649
|
+
if (config.maxSize && raw.size > config.maxSize)
|
|
18650
|
+
throw new Error(`${raw.name} \u8D85\u8FC7\u6587\u4EF6\u5927\u5C0F\u9650\u5236`);
|
|
18651
|
+
const allowed = await config.beforeUpload?.(raw);
|
|
18652
|
+
if (!alive) break;
|
|
18653
|
+
const max = Math.max(1, config.maxCount ?? Infinity);
|
|
18654
|
+
if (max === 1) {
|
|
18655
|
+
for (const file2 of files) requests.get(file2.uid)?.();
|
|
18656
|
+
files = [];
|
|
18657
|
+
}
|
|
18658
|
+
if (files.length >= max) throw new Error(`\u6700\u591A\u9009\u62E9 ${max} \u4E2A\u6587\u4EF6`);
|
|
18659
|
+
const file = {
|
|
18660
|
+
uid: `upload-${Date.now()}-${++sequence}`,
|
|
18661
|
+
name: raw.name,
|
|
18662
|
+
type: raw.type,
|
|
18663
|
+
size: raw.size,
|
|
18664
|
+
originFileObj: raw,
|
|
18665
|
+
status: "selected"
|
|
18666
|
+
};
|
|
18667
|
+
files.push(file);
|
|
18668
|
+
if (isUploadImage(file)) {
|
|
18669
|
+
const reader = new FileReader();
|
|
18670
|
+
readers.add(reader);
|
|
18671
|
+
pending++;
|
|
18672
|
+
reader.onload = () => {
|
|
18673
|
+
if (alive && files.includes(file)) {
|
|
18674
|
+
file.thumbUrl = String(reader.result);
|
|
18675
|
+
render();
|
|
18676
|
+
}
|
|
18677
|
+
};
|
|
18678
|
+
reader.onloadend = () => {
|
|
18679
|
+
readers.delete(reader);
|
|
18680
|
+
pending--;
|
|
18681
|
+
render();
|
|
18682
|
+
};
|
|
18683
|
+
reader.readAsDataURL(raw);
|
|
18684
|
+
}
|
|
18685
|
+
if (allowed !== false) upload(file);
|
|
18686
|
+
} catch (error) {
|
|
18687
|
+
if (alive)
|
|
18688
|
+
message.textContent = error instanceof Error ? error.message : String(error);
|
|
18689
|
+
}
|
|
18690
|
+
}
|
|
18691
|
+
pending--;
|
|
18692
|
+
render();
|
|
18693
|
+
};
|
|
18694
|
+
root.onkeydown = (event) => {
|
|
18695
|
+
event.stopPropagation();
|
|
18696
|
+
if (event.key === "Escape") {
|
|
18697
|
+
event.preventDefault();
|
|
18698
|
+
params.onCancel();
|
|
18699
|
+
}
|
|
18700
|
+
if (event.key === "Tab") {
|
|
18701
|
+
const items = Array.from(
|
|
18702
|
+
root.querySelectorAll("button:not(:disabled)")
|
|
18703
|
+
);
|
|
18704
|
+
const next = items[(items.indexOf(document.activeElement) + (event.shiftKey ? -1 : 1) + items.length) % items.length];
|
|
18705
|
+
event.preventDefault();
|
|
18706
|
+
next?.focus();
|
|
18707
|
+
}
|
|
18708
|
+
};
|
|
18709
|
+
document.body.append(root);
|
|
18710
|
+
render();
|
|
18711
|
+
return {
|
|
18712
|
+
element: root,
|
|
18713
|
+
focus: () => choose.focus(),
|
|
18714
|
+
getValue: () => files,
|
|
18715
|
+
destroy: () => {
|
|
18716
|
+
alive = false;
|
|
18717
|
+
for (const abort of [...requests.values()]) abort();
|
|
18718
|
+
for (const reader of readers) reader.abort();
|
|
18719
|
+
root.remove();
|
|
18720
|
+
}
|
|
18721
|
+
};
|
|
18722
|
+
}
|
|
18723
|
+
|
|
17182
18724
|
// src/features/editing/editing-feature.ts
|
|
17183
18725
|
var DEFAULT_EDITOR_PADDING_INLINE = 12;
|
|
17184
18726
|
function openCellEditingSession(params) {
|
|
@@ -17230,6 +18772,7 @@ function openCellEditingSession(params) {
|
|
|
17230
18772
|
}
|
|
17231
18773
|
const editorConfig = resolveEditorConfig(editConfig);
|
|
17232
18774
|
const editingValue = initialValue === void 0 ? currentValue : initialValue;
|
|
18775
|
+
const selectOnFocus = !(initialValue !== void 0 && (currentValue == null || currentValue === ""));
|
|
17233
18776
|
const hostRect = toHostRect ? toHostRect(descriptor.rect) : descriptor.rect;
|
|
17234
18777
|
const zoom = typeof theme.contentZoom === "number" && Number.isFinite(theme.contentZoom) && theme.contentZoom > 0 ? theme.contentZoom : 1;
|
|
17235
18778
|
const paddingInline = (column.cellStyle?.paddingInline ?? DEFAULT_EDITOR_PADDING_INLINE) * zoom;
|
|
@@ -17243,10 +18786,26 @@ function openCellEditingSession(params) {
|
|
|
17243
18786
|
paddingBlock,
|
|
17244
18787
|
contentZoom: zoom
|
|
17245
18788
|
};
|
|
18789
|
+
if (editorConfig.valueType === "upload" && typeof document !== "undefined") {
|
|
18790
|
+
const session2 = createUploadEditor({
|
|
18791
|
+
value: editingValue,
|
|
18792
|
+
config: editorConfig.upload,
|
|
18793
|
+
rect: toViewportRect(descriptor.rect),
|
|
18794
|
+
onCommit: () => onCommit(),
|
|
18795
|
+
onCancel
|
|
18796
|
+
});
|
|
18797
|
+
session2.focus();
|
|
18798
|
+
return {
|
|
18799
|
+
...session2,
|
|
18800
|
+
rowIndex,
|
|
18801
|
+
columnKey
|
|
18802
|
+
};
|
|
18803
|
+
}
|
|
17246
18804
|
if (onEditorRequest) {
|
|
17247
18805
|
let nextValue = editingValue;
|
|
17248
18806
|
onEditorRequest({
|
|
17249
18807
|
editorKey: JSON.stringify([rowIndex, columnKey]),
|
|
18808
|
+
selectOnFocus,
|
|
17250
18809
|
rect: toViewportRect(descriptor.rect),
|
|
17251
18810
|
clipRect: getViewportClipRect?.() ?? void 0,
|
|
17252
18811
|
hostRect,
|
|
@@ -17276,6 +18835,7 @@ function openCellEditingSession(params) {
|
|
|
17276
18835
|
return null;
|
|
17277
18836
|
}
|
|
17278
18837
|
const session = editorFactory.createCellEditorSession({
|
|
18838
|
+
selectOnFocus,
|
|
17279
18839
|
rect: toViewportRect(descriptor.rect),
|
|
17280
18840
|
clipRect: getViewportClipRect?.() ?? void 0,
|
|
17281
18841
|
hostRect,
|
|
@@ -17312,7 +18872,13 @@ function resolveEditorConfig(config) {
|
|
|
17312
18872
|
max: config.max,
|
|
17313
18873
|
min: config.min,
|
|
17314
18874
|
options: config.options,
|
|
18875
|
+
treeData: config.treeData,
|
|
18876
|
+
treeDefaultExpandAll: config.treeDefaultExpandAll,
|
|
18877
|
+
treeDefaultExpandedKeys: config.treeDefaultExpandedKeys,
|
|
17315
18878
|
changeOnSelect: config.changeOnSelect,
|
|
18879
|
+
multiple: config.multiple,
|
|
18880
|
+
showCheckedStrategy: config.showCheckedStrategy,
|
|
18881
|
+
upload: config.upload,
|
|
17316
18882
|
expandTrigger: config.expandTrigger,
|
|
17317
18883
|
allowClear: config.allowClear,
|
|
17318
18884
|
displayRender: config.displayRender,
|
|
@@ -17505,6 +19071,7 @@ var ListTableEditingController = class {
|
|
|
17505
19071
|
__publicField(this, "nestedEditingSource", null);
|
|
17506
19072
|
__publicField(this, "validationMessages", /* @__PURE__ */ new Map());
|
|
17507
19073
|
__publicField(this, "validationTaskId", 0);
|
|
19074
|
+
__publicField(this, "editingRequestId", 0);
|
|
17508
19075
|
this.options = options;
|
|
17509
19076
|
}
|
|
17510
19077
|
hasSession() {
|
|
@@ -17516,6 +19083,18 @@ var ListTableEditingController = class {
|
|
|
17516
19083
|
open(rowIndex, columnKey, initialValue) {
|
|
17517
19084
|
this.close(false);
|
|
17518
19085
|
this.options.clearBodyTooltip();
|
|
19086
|
+
const requestId = this.editingRequestId;
|
|
19087
|
+
const openVisibleEditor = () => {
|
|
19088
|
+
if (requestId !== this.editingRequestId) return;
|
|
19089
|
+
this.openVisibleCell(rowIndex, columnKey, initialValue);
|
|
19090
|
+
};
|
|
19091
|
+
if (this.ensureCellVisibleForEditing(rowIndex, columnKey, openVisibleEditor)) {
|
|
19092
|
+
return;
|
|
19093
|
+
}
|
|
19094
|
+
openVisibleEditor();
|
|
19095
|
+
}
|
|
19096
|
+
/** 使用滚动完成后的描述符定位编辑器,避免浏览器移动整个画布宿主。 */
|
|
19097
|
+
openVisibleCell(rowIndex, columnKey, initialValue) {
|
|
17519
19098
|
const zoom = this.options.getTableZoom() > 0 ? this.options.getTableZoom() : 1;
|
|
17520
19099
|
const theme = this.options.getTheme();
|
|
17521
19100
|
const configuredRowHeight = this.options.getOptions().rowHeight;
|
|
@@ -17671,40 +19250,14 @@ var ListTableEditingController = class {
|
|
|
17671
19250
|
void this.validateCellTargets(session.rowIndex, session.columnKey);
|
|
17672
19251
|
this.close(false);
|
|
17673
19252
|
this.options.requestRender();
|
|
17674
|
-
if (
|
|
17675
|
-
if (
|
|
17676
|
-
this.options.focusTable?.();
|
|
17677
|
-
return;
|
|
17678
|
-
}
|
|
17679
|
-
this.options.setSelection?.(nextTarget);
|
|
17680
|
-
const revealTarget = () => {
|
|
17681
|
-
this.options.requestRender();
|
|
19253
|
+
if (!nextTarget) {
|
|
19254
|
+
if (direction === "up" || direction === "down") {
|
|
17682
19255
|
this.options.focusTable?.();
|
|
17683
|
-
};
|
|
17684
|
-
const scrolled2 = this.ensureCellVisibleForEditing(
|
|
17685
|
-
nextTarget.rowIndex,
|
|
17686
|
-
nextTarget.columnKey,
|
|
17687
|
-
revealTarget
|
|
17688
|
-
);
|
|
17689
|
-
if (!scrolled2) {
|
|
17690
|
-
revealTarget();
|
|
17691
19256
|
}
|
|
17692
19257
|
return;
|
|
17693
19258
|
}
|
|
17694
|
-
if (!nextTarget) {
|
|
17695
|
-
return;
|
|
17696
|
-
}
|
|
17697
19259
|
this.options.setSelection?.(nextTarget);
|
|
17698
|
-
|
|
17699
|
-
nextTarget.rowIndex,
|
|
17700
|
-
nextTarget.columnKey,
|
|
17701
|
-
() => {
|
|
17702
|
-
this.open(nextTarget.rowIndex, nextTarget.columnKey);
|
|
17703
|
-
}
|
|
17704
|
-
);
|
|
17705
|
-
if (!scrolled) {
|
|
17706
|
-
this.open(nextTarget.rowIndex, nextTarget.columnKey);
|
|
17707
|
-
}
|
|
19260
|
+
this.open(nextTarget.rowIndex, nextTarget.columnKey);
|
|
17708
19261
|
}
|
|
17709
19262
|
/**
|
|
17710
19263
|
* 确保目标可编辑单元格完整进入视口。
|
|
@@ -17743,11 +19296,15 @@ var ListTableEditingController = class {
|
|
|
17743
19296
|
targetLeft: leftChanged ? nextLeft : scroll.left,
|
|
17744
19297
|
targetTop: topChanged ? nextTop : scroll.top,
|
|
17745
19298
|
duration: 240,
|
|
17746
|
-
onComplete:
|
|
19299
|
+
onComplete: () => {
|
|
19300
|
+
this.options.requestRender();
|
|
19301
|
+
onVisible?.();
|
|
19302
|
+
}
|
|
17747
19303
|
});
|
|
17748
19304
|
return true;
|
|
17749
19305
|
}
|
|
17750
19306
|
close(_keepFocusState = false) {
|
|
19307
|
+
this.editingRequestId++;
|
|
17751
19308
|
this.editingSession = closeCellEditingSession(this.editingSession);
|
|
17752
19309
|
this.editingSource = null;
|
|
17753
19310
|
this.nestedEditingSource = null;
|
|
@@ -24658,41 +26215,50 @@ function createListTableContextMenuActions(params) {
|
|
|
24658
26215
|
onExportJson: () => {
|
|
24659
26216
|
params.hideMenu();
|
|
24660
26217
|
params.startExportTask(
|
|
24661
|
-
() => exportAllRowsJsonContent({
|
|
26218
|
+
(fileName) => exportAllRowsJsonContent({
|
|
26219
|
+
fileName,
|
|
24662
26220
|
rows: params.getAllRows(),
|
|
24663
26221
|
columns: params.getColumns()
|
|
24664
26222
|
}),
|
|
24665
|
-
"\u6B63\u5728\u5BFC\u51FA JSON\u2026"
|
|
26223
|
+
"\u6B63\u5728\u5BFC\u51FA JSON\u2026",
|
|
26224
|
+
buildTableExportFileName("json")
|
|
24666
26225
|
);
|
|
24667
26226
|
},
|
|
24668
26227
|
onExportCsv: () => {
|
|
24669
26228
|
params.hideMenu();
|
|
24670
26229
|
params.startExportTask(
|
|
24671
|
-
() => exportAllRowsCsvContent({
|
|
26230
|
+
(fileName) => exportAllRowsCsvContent({
|
|
26231
|
+
fileName,
|
|
24672
26232
|
rows: params.getAllRows(),
|
|
24673
26233
|
columns: params.getColumns()
|
|
24674
26234
|
}),
|
|
24675
|
-
"\u6B63\u5728\u5BFC\u51FA CSV\u2026"
|
|
26235
|
+
"\u6B63\u5728\u5BFC\u51FA CSV\u2026",
|
|
26236
|
+
buildTableExportFileName("csv")
|
|
24676
26237
|
);
|
|
24677
26238
|
},
|
|
24678
26239
|
onExportTxt: () => {
|
|
24679
26240
|
params.hideMenu();
|
|
24680
26241
|
params.startExportTask(
|
|
24681
|
-
() => exportAllRowsTxtContent({
|
|
26242
|
+
(fileName) => exportAllRowsTxtContent({
|
|
26243
|
+
fileName,
|
|
24682
26244
|
rows: params.getAllRows(),
|
|
24683
26245
|
columns: params.getColumns()
|
|
24684
26246
|
}),
|
|
24685
|
-
"\u6B63\u5728\u5BFC\u51FA TXT\u2026"
|
|
26247
|
+
"\u6B63\u5728\u5BFC\u51FA TXT\u2026",
|
|
26248
|
+
buildTableExportFileName("txt")
|
|
24686
26249
|
);
|
|
24687
26250
|
},
|
|
24688
26251
|
onExportXlsx: () => {
|
|
24689
26252
|
params.hideMenu();
|
|
24690
26253
|
params.startExportTask(
|
|
24691
|
-
() => exportAllRowsXlsxContent({
|
|
26254
|
+
(fileName) => exportAllRowsXlsxContent({
|
|
26255
|
+
includeSummary: params.getExportSummaryEnabled?.() ?? false,
|
|
26256
|
+
fileName,
|
|
24692
26257
|
rows: params.getAllRows(),
|
|
24693
26258
|
columns: params.getColumns()
|
|
24694
26259
|
}),
|
|
24695
|
-
"\u6B63\u5728\u5BFC\u51FA XLSX\u2026"
|
|
26260
|
+
"\u6B63\u5728\u5BFC\u51FA XLSX\u2026",
|
|
26261
|
+
buildTableExportFileName("xlsx")
|
|
24696
26262
|
);
|
|
24697
26263
|
},
|
|
24698
26264
|
onFreezeRow: params.onFreezeRow,
|
|
@@ -25264,6 +26830,7 @@ function showHeaderContextMenu(params) {
|
|
|
25264
26830
|
rowCount: getRows().length,
|
|
25265
26831
|
columnCount: getColumns().length,
|
|
25266
26832
|
actions: createListTableContextMenuActions({
|
|
26833
|
+
getExportSummaryEnabled: params.getExportSummaryEnabled,
|
|
25267
26834
|
getRows,
|
|
25268
26835
|
getAllRows,
|
|
25269
26836
|
getColumns,
|
|
@@ -25374,9 +26941,9 @@ function updateHeaderActionTooltip(params) {
|
|
|
25374
26941
|
tooltip.show(tooltipPoint.x, tooltipPoint.y, text);
|
|
25375
26942
|
}
|
|
25376
26943
|
function showDragTooltip(params) {
|
|
25377
|
-
const { tooltip, toViewportPoint, x, y, text } = params;
|
|
26944
|
+
const { tooltip, toViewportPoint, x, y, text, variant } = params;
|
|
25378
26945
|
const point = toViewportPoint(x, y + 16);
|
|
25379
|
-
tooltip.show(point.x, point.y, text);
|
|
26946
|
+
tooltip.show(point.x, point.y, text, variant);
|
|
25380
26947
|
}
|
|
25381
26948
|
|
|
25382
26949
|
// src/shared/utils/hit-result.ts
|
|
@@ -26829,6 +28396,11 @@ var ListTableEventController = class {
|
|
|
26829
28396
|
event.clientY
|
|
26830
28397
|
);
|
|
26831
28398
|
const result = this.host.resolvePointerHit(position.x, position.y);
|
|
28399
|
+
if (result.area === "resize-handle" && result.columnKey) {
|
|
28400
|
+
event.preventDefault();
|
|
28401
|
+
void this.autoFitColumnWidths(result.columnKey);
|
|
28402
|
+
return;
|
|
28403
|
+
}
|
|
26832
28404
|
if (this.tryOpenNestedTableEditor(result, 2)) {
|
|
26833
28405
|
return;
|
|
26834
28406
|
}
|
|
@@ -26911,6 +28483,7 @@ var ListTableEventController = class {
|
|
|
26911
28483
|
},
|
|
26912
28484
|
getRows: () => this.host.getDisplayData(),
|
|
26913
28485
|
getAllRows: () => this.host.options.dataSource,
|
|
28486
|
+
getExportSummaryEnabled: () => Boolean(this.host.currentRenderSnapshot?.hasSummary),
|
|
26914
28487
|
onCopyImage: (scope) => this.copyImage(scope, event),
|
|
26915
28488
|
onExportImage: (scope) => this.copyImage(scope, event, true),
|
|
26916
28489
|
canCopySelectionImage: resolveImageSelection(this.host) != null,
|
|
@@ -26934,8 +28507,8 @@ var ListTableEventController = class {
|
|
|
26934
28507
|
getColumns: () => this.host.leafColumns,
|
|
26935
28508
|
getHeaderTree: () => this.host.headerTree,
|
|
26936
28509
|
getFrozenRowPosition: (rowIndex) => this.host.getFrozenRowPosition(rowIndex),
|
|
26937
|
-
startExportTask: (task, text) => {
|
|
26938
|
-
this.host.startExportTask(task, text);
|
|
28510
|
+
startExportTask: (task, text, defaultFileName) => {
|
|
28511
|
+
this.host.startExportTask(task, text, defaultFileName);
|
|
26939
28512
|
},
|
|
26940
28513
|
contentDownload: this.host.resolveContentDownloadAction(hitContent),
|
|
26941
28514
|
onSelectHeader: (columnKey, rect) => {
|
|
@@ -27565,7 +29138,8 @@ var ListTableEventController = class {
|
|
|
27565
29138
|
toViewportPoint: (x, y) => this.host.toViewportPoint(x, y),
|
|
27566
29139
|
x: dragPos.x,
|
|
27567
29140
|
y: dragPos.y,
|
|
27568
|
-
text: `${resizeResult.column.title}: ${resizeResult.nextWidth}px
|
|
29141
|
+
text: `${resizeResult.column.title}: ${resizeResult.nextWidth}px`,
|
|
29142
|
+
variant: "resize"
|
|
27569
29143
|
});
|
|
27570
29144
|
}
|
|
27571
29145
|
this.host.scheduleRender();
|
|
@@ -28084,10 +29658,11 @@ var ListTableEventController = class {
|
|
|
28084
29658
|
const actions = createListTableContextMenuActions({
|
|
28085
29659
|
getRows: () => resolveNestedTableDisplayRows(content, getNestedState()),
|
|
28086
29660
|
getAllRows: () => content.dataSource,
|
|
29661
|
+
getExportSummaryEnabled: () => getNestedState()?.summaryVisible === true,
|
|
28087
29662
|
getColumns: () => columns,
|
|
28088
29663
|
getHeaderTree: () => headerTree,
|
|
28089
29664
|
hideMenu,
|
|
28090
|
-
startExportTask: (task, text) => this.host.startExportTask(task, text),
|
|
29665
|
+
startExportTask: (task, text, defaultFileName) => this.host.startExportTask(task, text, defaultFileName),
|
|
28091
29666
|
onFreezeRow: () => {
|
|
28092
29667
|
},
|
|
28093
29668
|
onUnfreezeRow: () => {
|
|
@@ -29479,7 +31054,17 @@ function createListTableEventHost(core) {
|
|
|
29479
31054
|
return snapshot?.columnSegments ?? core.columnSegments;
|
|
29480
31055
|
},
|
|
29481
31056
|
persistColumnConfig: () => core.persistenceController.persistColumnConfig(),
|
|
29482
|
-
startExportTask: (task, text) =>
|
|
31057
|
+
startExportTask: (task, text, defaultFileName) => {
|
|
31058
|
+
const configured = core.options.exportOptions?.fileName?.trim();
|
|
31059
|
+
const extension = defaultFileName?.match(/\.(xlsx|csv|txt|json)$/i)?.[0];
|
|
31060
|
+
const fileName = configured && extension ? configured.replace(/\.(xlsx|csv|txt|json)$/i, "") + extension : defaultFileName;
|
|
31061
|
+
core.contentActionController.startExportTask(
|
|
31062
|
+
task,
|
|
31063
|
+
text,
|
|
31064
|
+
void 0,
|
|
31065
|
+
fileName
|
|
31066
|
+
);
|
|
31067
|
+
},
|
|
29483
31068
|
resolveContentDownloadAction: (content) => core.contentActionController.resolveContentDownloadAction(
|
|
29484
31069
|
content
|
|
29485
31070
|
)
|
|
@@ -33180,6 +34765,7 @@ function assembleListTableCoreControllers(core, options) {
|
|
|
33180
34765
|
requestRender: () => render()
|
|
33181
34766
|
});
|
|
33182
34767
|
core.contentActionController = new ListTableContentActionController({
|
|
34768
|
+
getSummaryVisible: () => Boolean(getCurrentRenderSnapshot()?.hasSummary),
|
|
33183
34769
|
getOptions: () => core.options,
|
|
33184
34770
|
getLeafColumns: () => core.leafColumns,
|
|
33185
34771
|
overlayController: core.overlayController,
|
|
@@ -33946,6 +35532,9 @@ exports.ListTable = ListTable;
|
|
|
33946
35532
|
exports.ROW_SELECTION_COLUMN = ROW_SELECTION_COLUMN;
|
|
33947
35533
|
exports.SELECTION_COLUMN = SELECTION_COLUMN;
|
|
33948
35534
|
exports.getListTableStoredPageSize = getListTableStoredPageSize;
|
|
35535
|
+
exports.listTableAntdIconNames = listTableAntdIconNames;
|
|
35536
|
+
exports.listTableBuiltinIconNames = listTableBuiltinIconNames;
|
|
35537
|
+
exports.listTableIconNames = listTableIconNames;
|
|
33949
35538
|
exports.resetListTableStoredColumnConfig = resetListTableStoredColumnConfig;
|
|
33950
35539
|
//# sourceMappingURL=index.cjs.map
|
|
33951
35540
|
//# sourceMappingURL=index.cjs.map
|