@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.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { stringifyDataIndex, getValueByDataIndex, clamp, resolveCanvasScrollbarAxis, copyTextSync, copyText, exportTableToXlsx, formatPreciseNumber, addPreciseNumbers, comparePreciseNumbers, isSameDataIndex, dividePreciseNumber, exportTableToTxt, exportTableToCsv, downloadJsonFile, mapRowsToExportRecords, copyJson, copyRows, parseNumberValue, formatNumberValue, formatPercentValue, formatScientificValue, formatChineseNumber, parseChineseNumber, normalizeDecimalPlaces, roundPreciseNumber, isDateTimeFormatPattern, formatDateTimeValue, formatCustomNumberPattern, isPointInRect as isPointInRect$1 } from '@canvas-components/utils';
|
|
2
2
|
import { drawBarcodeToCanvas } from '@canvas-components/barcode';
|
|
3
3
|
import { drawCanvasChartToCanvas, resolveCanvasChartOption, getCanvasChartRenderer, resolveCanvasChartTooltipText } from '@canvas-components/chart';
|
|
4
|
+
import * as antDesignIcons from '@ant-design/icons-svg';
|
|
4
5
|
import { drawQrCodeToCanvas } from '@canvas-components/qrcode';
|
|
5
6
|
import { dispatchCanvasDebugNode } from '@canvas-components/stats';
|
|
6
7
|
|
|
@@ -4532,7 +4533,7 @@ function drawImagePlaceholder(ctx, x, y, width, height, backgroundColor = PLACEH
|
|
|
4532
4533
|
ctx.fill();
|
|
4533
4534
|
}
|
|
4534
4535
|
|
|
4535
|
-
// src/rendering/
|
|
4536
|
+
// src/rendering/icons/draw-symbol.ts
|
|
4536
4537
|
var SYMBOL_COLOR_MAP = {
|
|
4537
4538
|
star: "#fadb14",
|
|
4538
4539
|
sun: "#faad14",
|
|
@@ -4556,6 +4557,11 @@ function drawCellSymbol(ctx, params) {
|
|
|
4556
4557
|
return;
|
|
4557
4558
|
}
|
|
4558
4559
|
appendCellSymbolPath(ctx, type, x, y, size);
|
|
4560
|
+
if (fillRatio >= 1) {
|
|
4561
|
+
ctx.fillStyle = activeColor;
|
|
4562
|
+
ctx.fill("evenodd");
|
|
4563
|
+
return;
|
|
4564
|
+
}
|
|
4559
4565
|
ctx.fillStyle = inactiveColor;
|
|
4560
4566
|
ctx.fill("evenodd");
|
|
4561
4567
|
if (fillRatio <= 0) {
|
|
@@ -4603,6 +4609,12 @@ function drawStatusSymbol(ctx, params) {
|
|
|
4603
4609
|
ctx.lineJoin = "round";
|
|
4604
4610
|
ctx.lineWidth = Math.max(size * 0.12, 1.5);
|
|
4605
4611
|
appendStatusSymbolPath(ctx, type, x, y, size);
|
|
4612
|
+
if (fillRatio >= 1) {
|
|
4613
|
+
ctx.strokeStyle = activeColor;
|
|
4614
|
+
ctx.stroke();
|
|
4615
|
+
ctx.restore();
|
|
4616
|
+
return;
|
|
4617
|
+
}
|
|
4606
4618
|
ctx.strokeStyle = inactiveColor;
|
|
4607
4619
|
ctx.stroke();
|
|
4608
4620
|
if (fillRatio > 0) {
|
|
@@ -4666,6 +4678,838 @@ function appendMoonPath(ctx, x, y, size) {
|
|
|
4666
4678
|
ctx.closePath();
|
|
4667
4679
|
}
|
|
4668
4680
|
|
|
4681
|
+
// src/rendering/icons/icon-stroke.ts
|
|
4682
|
+
function resolveIconStroke(ctx) {
|
|
4683
|
+
const identity = (value) => value;
|
|
4684
|
+
const fallback = { width: 2, snapX: identity, snapY: identity };
|
|
4685
|
+
const transform = ctx.getTransform?.();
|
|
4686
|
+
if (!transform || ![
|
|
4687
|
+
transform.a,
|
|
4688
|
+
transform.b,
|
|
4689
|
+
transform.c,
|
|
4690
|
+
transform.d,
|
|
4691
|
+
transform.e,
|
|
4692
|
+
transform.f
|
|
4693
|
+
].every(Number.isFinite))
|
|
4694
|
+
return fallback;
|
|
4695
|
+
if (Math.abs(transform.b) > 1e-8 || Math.abs(transform.c) > 1e-8 || transform.a <= 0 || Math.abs(transform.a - transform.d) > 1e-8)
|
|
4696
|
+
return fallback;
|
|
4697
|
+
const scale = transform.a;
|
|
4698
|
+
const pixels = Math.max(1, Math.round(2 * scale));
|
|
4699
|
+
const phase = pixels % 2 / 2;
|
|
4700
|
+
const snap = (value, translation) => (Math.round(value * scale + translation - phase) + phase - translation) / scale;
|
|
4701
|
+
return {
|
|
4702
|
+
width: pixels / scale,
|
|
4703
|
+
snapX: (value) => snap(value, transform.e),
|
|
4704
|
+
snapY: (value) => snap(value, transform.f)
|
|
4705
|
+
};
|
|
4706
|
+
}
|
|
4707
|
+
var listTableBuiltinIconNames = [
|
|
4708
|
+
"star",
|
|
4709
|
+
"sun",
|
|
4710
|
+
"moon",
|
|
4711
|
+
"check",
|
|
4712
|
+
"close",
|
|
4713
|
+
"circle",
|
|
4714
|
+
"check-circle",
|
|
4715
|
+
"close-circle",
|
|
4716
|
+
"clock-circle",
|
|
4717
|
+
"info-circle",
|
|
4718
|
+
"question-circle",
|
|
4719
|
+
"warning",
|
|
4720
|
+
"loading",
|
|
4721
|
+
"plus",
|
|
4722
|
+
"minus",
|
|
4723
|
+
"plus-circle",
|
|
4724
|
+
"minus-circle",
|
|
4725
|
+
"up",
|
|
4726
|
+
"down",
|
|
4727
|
+
"left",
|
|
4728
|
+
"right",
|
|
4729
|
+
"arrow-up",
|
|
4730
|
+
"arrow-down",
|
|
4731
|
+
"arrow-left",
|
|
4732
|
+
"arrow-right",
|
|
4733
|
+
"search",
|
|
4734
|
+
"edit",
|
|
4735
|
+
"delete",
|
|
4736
|
+
"copy",
|
|
4737
|
+
"save",
|
|
4738
|
+
"upload",
|
|
4739
|
+
"download",
|
|
4740
|
+
"reload",
|
|
4741
|
+
"ellipsis",
|
|
4742
|
+
"file",
|
|
4743
|
+
"file-text",
|
|
4744
|
+
"file-pdf",
|
|
4745
|
+
"folder",
|
|
4746
|
+
"folder-open",
|
|
4747
|
+
"picture",
|
|
4748
|
+
"user",
|
|
4749
|
+
"team",
|
|
4750
|
+
"calendar",
|
|
4751
|
+
"filter",
|
|
4752
|
+
"sort-ascending",
|
|
4753
|
+
"sort-descending",
|
|
4754
|
+
"link",
|
|
4755
|
+
"eye",
|
|
4756
|
+
"lock",
|
|
4757
|
+
"unlock",
|
|
4758
|
+
"home",
|
|
4759
|
+
"mail",
|
|
4760
|
+
"setting",
|
|
4761
|
+
"header-sort",
|
|
4762
|
+
"header-sort-ascending",
|
|
4763
|
+
"header-sort-descending",
|
|
4764
|
+
"header-filter",
|
|
4765
|
+
"header-fixed"
|
|
4766
|
+
];
|
|
4767
|
+
var listTableAntdIconNames = Object.keys(
|
|
4768
|
+
antDesignIcons
|
|
4769
|
+
);
|
|
4770
|
+
var listTableIconNames = [
|
|
4771
|
+
...listTableBuiltinIconNames,
|
|
4772
|
+
...listTableAntdIconNames
|
|
4773
|
+
];
|
|
4774
|
+
function getAntdIconDefinition(name) {
|
|
4775
|
+
return Object.prototype.hasOwnProperty.call(antDesignIcons, name) ? antDesignIcons[name] : void 0;
|
|
4776
|
+
}
|
|
4777
|
+
|
|
4778
|
+
// src/rendering/icons/svg-path.ts
|
|
4779
|
+
function parseSvgPath(source) {
|
|
4780
|
+
const output = [];
|
|
4781
|
+
let offset = 0, command = "", previous = "", x = 0, y = 0, startX = 0, startY = 0, controlX = 0, controlY = 0;
|
|
4782
|
+
const skip = () => {
|
|
4783
|
+
while (/[\s,]/.test(source[offset] ?? "!") && offset < source.length)
|
|
4784
|
+
offset++;
|
|
4785
|
+
};
|
|
4786
|
+
const number = (flag = false) => {
|
|
4787
|
+
skip();
|
|
4788
|
+
const match = source.slice(offset).match(flag ? /^[01]/ : /^[-+]?(?:\d*\.\d+|\d+\.?\d*)(?:[eE][-+]?\d+)?/);
|
|
4789
|
+
if (!match) throw new Error(`\u65E0\u6548 SVG \u8DEF\u5F84\u53C2\u6570\uFF0C\u4F4D\u7F6E ${offset}`);
|
|
4790
|
+
offset += match[0].length;
|
|
4791
|
+
const value = Number(match[0]);
|
|
4792
|
+
if (!Number.isFinite(value)) throw new Error("SVG \u8DEF\u5F84\u5305\u542B\u975E\u6709\u9650\u5750\u6807");
|
|
4793
|
+
return value;
|
|
4794
|
+
};
|
|
4795
|
+
while (offset < source.length) {
|
|
4796
|
+
skip();
|
|
4797
|
+
if (offset >= source.length) break;
|
|
4798
|
+
if (/[a-z]/i.test(source[offset])) command = source[offset++];
|
|
4799
|
+
else if (!command) throw new Error(`\u7F3A\u5C11 SVG \u8DEF\u5F84\u547D\u4EE4\uFF0C\u4F4D\u7F6E ${offset}`);
|
|
4800
|
+
const upper = command.toUpperCase();
|
|
4801
|
+
const relative = upper !== command;
|
|
4802
|
+
const point = () => [
|
|
4803
|
+
number() + (relative ? x : 0),
|
|
4804
|
+
number() + (relative ? y : 0)
|
|
4805
|
+
];
|
|
4806
|
+
if (upper === "Z") {
|
|
4807
|
+
output.push({ op: "Z", args: [] });
|
|
4808
|
+
x = startX;
|
|
4809
|
+
y = startY;
|
|
4810
|
+
command = "";
|
|
4811
|
+
} else if (upper === "M" || upper === "L") {
|
|
4812
|
+
const target = point();
|
|
4813
|
+
output.push({ op: upper, args: target });
|
|
4814
|
+
[x, y] = target;
|
|
4815
|
+
if (upper === "M") {
|
|
4816
|
+
startX = x;
|
|
4817
|
+
startY = y;
|
|
4818
|
+
command = relative ? "l" : "L";
|
|
4819
|
+
}
|
|
4820
|
+
} else if (upper === "H" || upper === "V") {
|
|
4821
|
+
const value = number();
|
|
4822
|
+
if (upper === "H") x = value + (relative ? x : 0);
|
|
4823
|
+
else y = value + (relative ? y : 0);
|
|
4824
|
+
output.push({ op: "L", args: [x, y] });
|
|
4825
|
+
} else if (upper === "C" || upper === "S") {
|
|
4826
|
+
const first = upper === "C" ? point() : [
|
|
4827
|
+
/[CS]/.test(previous) ? 2 * x - controlX : x,
|
|
4828
|
+
/[CS]/.test(previous) ? 2 * y - controlY : y
|
|
4829
|
+
];
|
|
4830
|
+
const second = point();
|
|
4831
|
+
const target = point();
|
|
4832
|
+
output.push({ op: "C", args: [...first, ...second, ...target] });
|
|
4833
|
+
[controlX, controlY] = second;
|
|
4834
|
+
[x, y] = target;
|
|
4835
|
+
} else if (upper === "Q" || upper === "T") {
|
|
4836
|
+
const control = upper === "Q" ? point() : [
|
|
4837
|
+
/[QT]/.test(previous) ? 2 * x - controlX : x,
|
|
4838
|
+
/[QT]/.test(previous) ? 2 * y - controlY : y
|
|
4839
|
+
];
|
|
4840
|
+
const target = point();
|
|
4841
|
+
output.push({ op: "Q", args: [...control, ...target] });
|
|
4842
|
+
[controlX, controlY] = control;
|
|
4843
|
+
[x, y] = target;
|
|
4844
|
+
} else if (upper === "A") {
|
|
4845
|
+
const rx = number(), ry = number(), rotation = number(), large = number(true), sweep = number(true);
|
|
4846
|
+
const target = point();
|
|
4847
|
+
output.push(
|
|
4848
|
+
...arcCommands(
|
|
4849
|
+
x,
|
|
4850
|
+
y,
|
|
4851
|
+
rx,
|
|
4852
|
+
ry,
|
|
4853
|
+
rotation,
|
|
4854
|
+
large,
|
|
4855
|
+
sweep,
|
|
4856
|
+
target[0],
|
|
4857
|
+
target[1]
|
|
4858
|
+
)
|
|
4859
|
+
);
|
|
4860
|
+
[x, y] = target;
|
|
4861
|
+
} else throw new Error(`\u4E0D\u652F\u6301\u7684 SVG \u8DEF\u5F84\u547D\u4EE4 ${command}`);
|
|
4862
|
+
previous = upper;
|
|
4863
|
+
}
|
|
4864
|
+
return output;
|
|
4865
|
+
}
|
|
4866
|
+
function arcCommands(x1, y1, rx, ry, rotation, large, sweep, x2, y2) {
|
|
4867
|
+
if (x1 === x2 && y1 === y2) return [];
|
|
4868
|
+
rx = Math.abs(rx);
|
|
4869
|
+
ry = Math.abs(ry);
|
|
4870
|
+
if (!rx || !ry) return [{ op: "L", args: [x2, y2] }];
|
|
4871
|
+
const phi = rotation * Math.PI / 180, cos = Math.cos(phi), sin = Math.sin(phi);
|
|
4872
|
+
const px = cos * (x1 - x2) / 2 + sin * (y1 - y2) / 2;
|
|
4873
|
+
const py = -sin * (x1 - x2) / 2 + cos * (y1 - y2) / 2;
|
|
4874
|
+
const scale = Math.max(
|
|
4875
|
+
1,
|
|
4876
|
+
Math.sqrt(px * px / (rx * rx) + py * py / (ry * ry))
|
|
4877
|
+
);
|
|
4878
|
+
rx *= scale;
|
|
4879
|
+
ry *= scale;
|
|
4880
|
+
const denominator = rx * rx * py * py + ry * ry * px * px;
|
|
4881
|
+
const factor = (large === sweep ? -1 : 1) * Math.sqrt(Math.max(0, (rx * rx * ry * ry - denominator) / denominator));
|
|
4882
|
+
const cxp = factor * rx * py / ry, cyp = -factor * ry * px / rx;
|
|
4883
|
+
const cx = cos * cxp - sin * cyp + (x1 + x2) / 2, cy = sin * cxp + cos * cyp + (y1 + y2) / 2;
|
|
4884
|
+
const start = Math.atan2((py - cyp) / ry, (px - cxp) / rx);
|
|
4885
|
+
const finish = Math.atan2((-py - cyp) / ry, (-px - cxp) / rx);
|
|
4886
|
+
let delta = finish - start;
|
|
4887
|
+
if (sweep && delta < 0) delta += Math.PI * 2;
|
|
4888
|
+
if (!sweep && delta > 0) delta -= Math.PI * 2;
|
|
4889
|
+
const count = Math.max(1, Math.ceil(Math.abs(delta) / (Math.PI / 2)));
|
|
4890
|
+
const step = delta / count;
|
|
4891
|
+
const point = (angle) => [
|
|
4892
|
+
cx + rx * cos * Math.cos(angle) - ry * sin * Math.sin(angle),
|
|
4893
|
+
cy + rx * sin * Math.cos(angle) + ry * cos * Math.sin(angle)
|
|
4894
|
+
];
|
|
4895
|
+
const derivative = (angle) => [
|
|
4896
|
+
-rx * cos * Math.sin(angle) - ry * sin * Math.cos(angle),
|
|
4897
|
+
-rx * sin * Math.sin(angle) + ry * cos * Math.cos(angle)
|
|
4898
|
+
];
|
|
4899
|
+
return Array.from({ length: count }, (_, index) => {
|
|
4900
|
+
const a = start + step * index, b = a + step, k = 4 / 3 * Math.tan(step / 4);
|
|
4901
|
+
const p = point(a), q = point(b), dp = derivative(a), dq = derivative(b);
|
|
4902
|
+
return {
|
|
4903
|
+
op: "C",
|
|
4904
|
+
args: [
|
|
4905
|
+
p[0] + k * dp[0],
|
|
4906
|
+
p[1] + k * dp[1],
|
|
4907
|
+
q[0] - k * dq[0],
|
|
4908
|
+
q[1] - k * dq[1],
|
|
4909
|
+
...index === count - 1 ? [x2, y2] : q
|
|
4910
|
+
]
|
|
4911
|
+
};
|
|
4912
|
+
});
|
|
4913
|
+
}
|
|
4914
|
+
function traceSvgPath(ctx, commands) {
|
|
4915
|
+
ctx.beginPath();
|
|
4916
|
+
for (const { op, args: a } of commands) {
|
|
4917
|
+
if (op === "M") ctx.moveTo(a[0], a[1]);
|
|
4918
|
+
else if (op === "L") ctx.lineTo(a[0], a[1]);
|
|
4919
|
+
else if (op === "C") ctx.bezierCurveTo(a[0], a[1], a[2], a[3], a[4], a[5]);
|
|
4920
|
+
else if (op === "Q") ctx.quadraticCurveTo(a[0], a[1], a[2], a[3]);
|
|
4921
|
+
else ctx.closePath();
|
|
4922
|
+
}
|
|
4923
|
+
}
|
|
4924
|
+
|
|
4925
|
+
// src/rendering/icons/draw-antd-icon.ts
|
|
4926
|
+
var pathCache = /* @__PURE__ */ new Map();
|
|
4927
|
+
var CACHE_LIMIT = 256;
|
|
4928
|
+
function secondaryColor(primary) {
|
|
4929
|
+
let hex = primary.replace(/^#/, "");
|
|
4930
|
+
if (/^[\da-f]{3}$/i.test(hex))
|
|
4931
|
+
hex = [...hex].map((char) => char + char).join("");
|
|
4932
|
+
if (!/^[\da-f]{6}$/i.test(hex)) return "#e6f4ff";
|
|
4933
|
+
const channels = [0, 2, 4].map(
|
|
4934
|
+
(start) => Math.round(255 * 0.85 + parseInt(hex.slice(start, start + 2), 16) * 0.15)
|
|
4935
|
+
);
|
|
4936
|
+
return `rgb(${channels.join(",")})`;
|
|
4937
|
+
}
|
|
4938
|
+
function drawAntdIcon(ctx, params) {
|
|
4939
|
+
const definition = getAntdIconDefinition(params.type);
|
|
4940
|
+
if (!definition) return false;
|
|
4941
|
+
const primary = Array.isArray(params.twoToneColor) ? params.twoToneColor[0] : params.twoToneColor ?? params.color;
|
|
4942
|
+
const secondary = Array.isArray(params.twoToneColor) ? params.twoToneColor[1] : secondaryColor(primary);
|
|
4943
|
+
const root = typeof definition.icon === "function" ? definition.icon(primary, secondary) : definition.icon;
|
|
4944
|
+
const [vx, vy, vw, vh] = (root.attrs.viewBox ?? "0 0 1024 1024").split(/[\s,]+/).map(Number);
|
|
4945
|
+
ctx.save();
|
|
4946
|
+
try {
|
|
4947
|
+
const scale = params.size / Math.max(vw, vh);
|
|
4948
|
+
ctx.translate(
|
|
4949
|
+
params.x + (params.size - vw * scale) / 2,
|
|
4950
|
+
params.y + (params.size - vh * scale) / 2
|
|
4951
|
+
);
|
|
4952
|
+
ctx.scale(scale, scale);
|
|
4953
|
+
ctx.translate(-vx, -vy);
|
|
4954
|
+
drawNode(ctx, root, primary);
|
|
4955
|
+
} finally {
|
|
4956
|
+
ctx.restore();
|
|
4957
|
+
}
|
|
4958
|
+
return true;
|
|
4959
|
+
}
|
|
4960
|
+
function drawNode(ctx, node, inheritedColor) {
|
|
4961
|
+
if (node.tag === "defs" || node.tag === "style") return;
|
|
4962
|
+
const color = node.attrs.fill ?? inheritedColor;
|
|
4963
|
+
ctx.save();
|
|
4964
|
+
try {
|
|
4965
|
+
const opacity = Number(node.attrs["fill-opacity"] ?? 1);
|
|
4966
|
+
ctx.globalAlpha *= Number.isFinite(opacity) ? Math.max(0, Math.min(opacity, 1)) : 1;
|
|
4967
|
+
if (node.tag === "path" && node.attrs.d && color !== "none") {
|
|
4968
|
+
ctx.fillStyle = color === "currentColor" ? inheritedColor : color;
|
|
4969
|
+
const data = node.attrs.d;
|
|
4970
|
+
let entry = pathCache.get(data);
|
|
4971
|
+
if (entry) pathCache.delete(data);
|
|
4972
|
+
else if (typeof Path2D === "function") {
|
|
4973
|
+
try {
|
|
4974
|
+
entry = { path: new Path2D(data) };
|
|
4975
|
+
} catch {
|
|
4976
|
+
entry = { commands: parseSvgPath(data) };
|
|
4977
|
+
}
|
|
4978
|
+
} else entry = { commands: parseSvgPath(data) };
|
|
4979
|
+
pathCache.set(data, entry);
|
|
4980
|
+
if (pathCache.size > CACHE_LIMIT)
|
|
4981
|
+
pathCache.delete(pathCache.keys().next().value);
|
|
4982
|
+
const rule = node.attrs["fill-rule"] === "evenodd" ? "evenodd" : "nonzero";
|
|
4983
|
+
if (entry.path) ctx.fill(entry.path, rule);
|
|
4984
|
+
else {
|
|
4985
|
+
traceSvgPath(ctx, entry.commands);
|
|
4986
|
+
ctx.fill(rule);
|
|
4987
|
+
}
|
|
4988
|
+
}
|
|
4989
|
+
for (const child of node.children ?? []) drawNode(ctx, child, color);
|
|
4990
|
+
} finally {
|
|
4991
|
+
ctx.restore();
|
|
4992
|
+
}
|
|
4993
|
+
}
|
|
4994
|
+
|
|
4995
|
+
// src/rendering/icons/draw-header-action-icon.ts
|
|
4996
|
+
var FILTER_ICON_VIEWBOX_SIZE = 1024;
|
|
4997
|
+
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";
|
|
4998
|
+
var FIXED_PIN_VIEWBOX_SIZE = 1024;
|
|
4999
|
+
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";
|
|
5000
|
+
var filterIconPath = null;
|
|
5001
|
+
var fixedPinPath = null;
|
|
5002
|
+
function drawHeaderActionGlyph(ctx, rect, actionType, color = "#8c8c8c", sortOrder = null, activeColor = "#1677ff") {
|
|
5003
|
+
ctx.save();
|
|
5004
|
+
ctx.strokeStyle = color;
|
|
5005
|
+
ctx.fillStyle = color;
|
|
5006
|
+
if (actionType === "sort") {
|
|
5007
|
+
ctx.beginPath();
|
|
5008
|
+
ctx.fillStyle = sortOrder === "ascend" ? activeColor : color;
|
|
5009
|
+
ctx.moveTo(rect.x + rect.width / 2, rect.y + 1);
|
|
5010
|
+
ctx.lineTo(rect.x + rect.width - 2, rect.y + 6);
|
|
5011
|
+
ctx.lineTo(rect.x + 2, rect.y + 6);
|
|
5012
|
+
ctx.closePath();
|
|
5013
|
+
ctx.fill();
|
|
5014
|
+
ctx.beginPath();
|
|
5015
|
+
ctx.fillStyle = sortOrder === "descend" ? activeColor : color;
|
|
5016
|
+
ctx.moveTo(rect.x + 2, rect.y + rect.height - 6);
|
|
5017
|
+
ctx.lineTo(rect.x + rect.width - 2, rect.y + rect.height - 6);
|
|
5018
|
+
ctx.lineTo(rect.x + rect.width / 2, rect.y + rect.height - 1);
|
|
5019
|
+
ctx.closePath();
|
|
5020
|
+
ctx.fill();
|
|
5021
|
+
} else if (actionType === "filter") {
|
|
5022
|
+
drawFilterIcon(ctx, rect);
|
|
5023
|
+
} else {
|
|
5024
|
+
drawFixedPinIcon(ctx, rect);
|
|
5025
|
+
}
|
|
5026
|
+
ctx.restore();
|
|
5027
|
+
}
|
|
5028
|
+
function drawFilterIcon(ctx, rect) {
|
|
5029
|
+
const iconWidth = rect.width * 0.92;
|
|
5030
|
+
const iconHeight = rect.height * 0.7;
|
|
5031
|
+
const offsetX = rect.x + (rect.width - iconWidth) / 2;
|
|
5032
|
+
const offsetY = rect.y + (rect.height - iconHeight) / 2;
|
|
5033
|
+
const path = resolveIconPath("filter");
|
|
5034
|
+
if (path) {
|
|
5035
|
+
ctx.save();
|
|
5036
|
+
ctx.translate(offsetX, offsetY);
|
|
5037
|
+
ctx.scale(
|
|
5038
|
+
iconWidth / FILTER_ICON_VIEWBOX_SIZE,
|
|
5039
|
+
iconHeight / FILTER_ICON_VIEWBOX_SIZE
|
|
5040
|
+
);
|
|
5041
|
+
ctx.fill(path);
|
|
5042
|
+
ctx.restore();
|
|
5043
|
+
return;
|
|
5044
|
+
}
|
|
5045
|
+
ctx.beginPath();
|
|
5046
|
+
ctx.moveTo(offsetX, offsetY);
|
|
5047
|
+
ctx.lineTo(offsetX + iconWidth, offsetY);
|
|
5048
|
+
ctx.lineTo(offsetX + iconWidth * 0.62, offsetY + iconHeight * 0.52);
|
|
5049
|
+
ctx.lineTo(offsetX + iconWidth * 0.62, offsetY + iconHeight);
|
|
5050
|
+
ctx.lineTo(offsetX + iconWidth * 0.38, offsetY + iconHeight * 0.88);
|
|
5051
|
+
ctx.lineTo(offsetX + iconWidth * 0.38, offsetY + iconHeight * 0.52);
|
|
5052
|
+
ctx.closePath();
|
|
5053
|
+
ctx.fill();
|
|
5054
|
+
}
|
|
5055
|
+
function drawFixedPinIcon(ctx, rect) {
|
|
5056
|
+
const iconSize = Math.min(rect.width, rect.height) * 0.92;
|
|
5057
|
+
const offsetX = rect.x + (rect.width - iconSize) / 2;
|
|
5058
|
+
const offsetY = rect.y + (rect.height - iconSize) / 2;
|
|
5059
|
+
const scale = iconSize / FIXED_PIN_VIEWBOX_SIZE;
|
|
5060
|
+
const path = resolveIconPath("fixed");
|
|
5061
|
+
if (path) {
|
|
5062
|
+
ctx.save();
|
|
5063
|
+
ctx.translate(offsetX, offsetY);
|
|
5064
|
+
ctx.scale(scale, scale);
|
|
5065
|
+
ctx.fill(path);
|
|
5066
|
+
ctx.restore();
|
|
5067
|
+
return;
|
|
5068
|
+
}
|
|
5069
|
+
ctx.beginPath();
|
|
5070
|
+
ctx.moveTo(offsetX + iconSize * 0.68, offsetY);
|
|
5071
|
+
ctx.lineTo(offsetX + iconSize, offsetY + iconSize * 0.32);
|
|
5072
|
+
ctx.lineTo(offsetX + iconSize * 0.78, offsetY + iconSize * 0.34);
|
|
5073
|
+
ctx.lineTo(offsetX + iconSize * 0.62, offsetY + iconSize * 0.64);
|
|
5074
|
+
ctx.lineTo(offsetX + iconSize * 0.74, offsetY + iconSize * 0.76);
|
|
5075
|
+
ctx.lineTo(offsetX + iconSize * 0.52, offsetY + iconSize * 0.82);
|
|
5076
|
+
ctx.lineTo(offsetX + iconSize * 0.16, offsetY + iconSize);
|
|
5077
|
+
ctx.lineTo(offsetX + iconSize * 0.34, offsetY + iconSize * 0.64);
|
|
5078
|
+
ctx.lineTo(offsetX + iconSize * 0.2, offsetY + iconSize * 0.5);
|
|
5079
|
+
ctx.lineTo(offsetX + iconSize * 0.5, offsetY + iconSize * 0.34);
|
|
5080
|
+
ctx.closePath();
|
|
5081
|
+
ctx.fill();
|
|
5082
|
+
}
|
|
5083
|
+
function resolveIconPath(type) {
|
|
5084
|
+
if (typeof Path2D === "undefined") return null;
|
|
5085
|
+
if (type === "filter") {
|
|
5086
|
+
filterIconPath ?? (filterIconPath = new Path2D(FILTER_ICON_PATH_DATA));
|
|
5087
|
+
return filterIconPath;
|
|
5088
|
+
}
|
|
5089
|
+
fixedPinPath ?? (fixedPinPath = new Path2D(FIXED_PIN_PATH_DATA));
|
|
5090
|
+
return fixedPinPath;
|
|
5091
|
+
}
|
|
5092
|
+
|
|
5093
|
+
// src/rendering/icons/draw-icon.ts
|
|
5094
|
+
function resolveIconColor(type, fallback = "#1f2329") {
|
|
5095
|
+
if (isLegacy(type)) return resolveCellSymbolColor(type);
|
|
5096
|
+
if (type === "check-circle") return "#52c41a";
|
|
5097
|
+
if (type === "close-circle") return "#ff4d4f";
|
|
5098
|
+
if (type === "warning") return "#faad14";
|
|
5099
|
+
if (type === "info-circle" || type === "question-circle") return "#1677ff";
|
|
5100
|
+
if (type.endsWith("TwoTone")) return "#1677ff";
|
|
5101
|
+
if (type.startsWith("header-")) return "#8c8c8c";
|
|
5102
|
+
return fallback;
|
|
5103
|
+
}
|
|
5104
|
+
function isLegacy(type) {
|
|
5105
|
+
return type === "star" || type === "sun" || type === "moon" || type === "check" || type === "close";
|
|
5106
|
+
}
|
|
5107
|
+
function drawIcon(ctx, params) {
|
|
5108
|
+
const { type, x, y, size } = params;
|
|
5109
|
+
if (![x, y, size].every(Number.isFinite) || size <= 0) return;
|
|
5110
|
+
const color = params.color ?? resolveIconColor(type);
|
|
5111
|
+
if (drawAntdIcon(ctx, { ...params, color })) return;
|
|
5112
|
+
ctx.save();
|
|
5113
|
+
try {
|
|
5114
|
+
if (type.startsWith("header-")) {
|
|
5115
|
+
ctx.translate(x, y);
|
|
5116
|
+
ctx.scale(size / 14, size / 14);
|
|
5117
|
+
drawHeaderActionGlyph(
|
|
5118
|
+
ctx,
|
|
5119
|
+
{ x: 0, y: 0, width: 14, height: 14 },
|
|
5120
|
+
type === "header-filter" ? "filter" : type === "header-fixed" ? "fixed" : "sort",
|
|
5121
|
+
color,
|
|
5122
|
+
type === "header-sort-ascending" ? "ascend" : type === "header-sort-descending" ? "descend" : null,
|
|
5123
|
+
params.color ?? "#1677ff"
|
|
5124
|
+
);
|
|
5125
|
+
return;
|
|
5126
|
+
}
|
|
5127
|
+
if (isLegacy(type)) {
|
|
5128
|
+
drawCellSymbol(ctx, {
|
|
5129
|
+
type,
|
|
5130
|
+
x,
|
|
5131
|
+
y,
|
|
5132
|
+
size,
|
|
5133
|
+
activeColor: color,
|
|
5134
|
+
inactiveColor: color,
|
|
5135
|
+
fillRatio: 1
|
|
5136
|
+
});
|
|
5137
|
+
return;
|
|
5138
|
+
}
|
|
5139
|
+
ctx.translate(x, y);
|
|
5140
|
+
ctx.scale(size / 24, size / 24);
|
|
5141
|
+
ctx.strokeStyle = color;
|
|
5142
|
+
ctx.fillStyle = color;
|
|
5143
|
+
const stroke = resolveIconStroke(ctx);
|
|
5144
|
+
ctx.lineWidth = stroke.width;
|
|
5145
|
+
ctx.lineCap = "round";
|
|
5146
|
+
ctx.lineJoin = "round";
|
|
5147
|
+
ctx.setLineDash([]);
|
|
5148
|
+
appendIconPath(ctx, type, stroke);
|
|
5149
|
+
ctx.stroke();
|
|
5150
|
+
} finally {
|
|
5151
|
+
ctx.restore();
|
|
5152
|
+
}
|
|
5153
|
+
}
|
|
5154
|
+
function appendIconPath(ctx, type, stroke) {
|
|
5155
|
+
const line = (...points) => {
|
|
5156
|
+
const aligned = [...points];
|
|
5157
|
+
for (let i = 2; i < points.length; i += 2) {
|
|
5158
|
+
if (points[i - 2] === points[i])
|
|
5159
|
+
aligned[i - 2] = aligned[i] = stroke.snapX(points[i]);
|
|
5160
|
+
if (points[i - 1] === points[i + 1])
|
|
5161
|
+
aligned[i - 1] = aligned[i + 1] = stroke.snapY(points[i + 1]);
|
|
5162
|
+
}
|
|
5163
|
+
ctx.moveTo(aligned[0], aligned[1]);
|
|
5164
|
+
for (let i = 2; i < aligned.length; i += 2)
|
|
5165
|
+
ctx.lineTo(aligned[i], aligned[i + 1]);
|
|
5166
|
+
};
|
|
5167
|
+
const rect = (x, y, width, height) => {
|
|
5168
|
+
const left = stroke.snapX(x);
|
|
5169
|
+
const top = stroke.snapY(y);
|
|
5170
|
+
ctx.rect(
|
|
5171
|
+
left,
|
|
5172
|
+
top,
|
|
5173
|
+
stroke.snapX(x + width) - left,
|
|
5174
|
+
stroke.snapY(y + height) - top
|
|
5175
|
+
);
|
|
5176
|
+
};
|
|
5177
|
+
const circle = (x = 12, y = 12, r = 9) => {
|
|
5178
|
+
ctx.moveTo(x + r, y);
|
|
5179
|
+
ctx.arc(x, y, r, 0, Math.PI * 2);
|
|
5180
|
+
};
|
|
5181
|
+
const plus = () => {
|
|
5182
|
+
line(7, 12, 17, 12);
|
|
5183
|
+
line(12, 7, 12, 17);
|
|
5184
|
+
};
|
|
5185
|
+
const check = () => line(7, 12, 10.5, 15.5, 17, 8.5);
|
|
5186
|
+
const cross = () => {
|
|
5187
|
+
line(8, 8, 16, 16);
|
|
5188
|
+
line(16, 8, 8, 16);
|
|
5189
|
+
};
|
|
5190
|
+
const file = () => {
|
|
5191
|
+
line(5, 3, 14, 3, 19, 8, 19, 21, 5, 21, 5, 3);
|
|
5192
|
+
line(14, 3, 14, 8, 19, 8);
|
|
5193
|
+
};
|
|
5194
|
+
ctx.beginPath();
|
|
5195
|
+
switch (type) {
|
|
5196
|
+
case "circle":
|
|
5197
|
+
circle();
|
|
5198
|
+
break;
|
|
5199
|
+
case "check-circle":
|
|
5200
|
+
circle();
|
|
5201
|
+
check();
|
|
5202
|
+
break;
|
|
5203
|
+
case "close-circle":
|
|
5204
|
+
circle();
|
|
5205
|
+
cross();
|
|
5206
|
+
break;
|
|
5207
|
+
case "clock-circle":
|
|
5208
|
+
circle();
|
|
5209
|
+
line(12, 6, 12, 12, 16, 14);
|
|
5210
|
+
break;
|
|
5211
|
+
case "info-circle":
|
|
5212
|
+
circle();
|
|
5213
|
+
line(12, 11, 12, 17);
|
|
5214
|
+
circle(12, 7, 0.4);
|
|
5215
|
+
break;
|
|
5216
|
+
case "question-circle":
|
|
5217
|
+
circle();
|
|
5218
|
+
ctx.moveTo(9, 8);
|
|
5219
|
+
ctx.bezierCurveTo(9, 4, 18, 6, 14, 11);
|
|
5220
|
+
line(14, 11, 12, 13, 12, 14);
|
|
5221
|
+
circle(12, 17, 0.4);
|
|
5222
|
+
break;
|
|
5223
|
+
case "warning":
|
|
5224
|
+
line(12, 3, 22, 20, 2, 20, 12, 3);
|
|
5225
|
+
line(12, 9, 12, 13);
|
|
5226
|
+
circle(12, 17, 0.4);
|
|
5227
|
+
break;
|
|
5228
|
+
case "loading":
|
|
5229
|
+
ctx.arc(12, 12, 9, -Math.PI / 2, Math.PI);
|
|
5230
|
+
break;
|
|
5231
|
+
case "plus":
|
|
5232
|
+
plus();
|
|
5233
|
+
break;
|
|
5234
|
+
case "minus":
|
|
5235
|
+
line(5, 12, 19, 12);
|
|
5236
|
+
break;
|
|
5237
|
+
case "plus-circle":
|
|
5238
|
+
circle();
|
|
5239
|
+
plus();
|
|
5240
|
+
break;
|
|
5241
|
+
case "minus-circle":
|
|
5242
|
+
circle();
|
|
5243
|
+
line(7, 12, 17, 12);
|
|
5244
|
+
break;
|
|
5245
|
+
case "up":
|
|
5246
|
+
line(5, 15, 12, 8, 19, 15);
|
|
5247
|
+
break;
|
|
5248
|
+
case "down":
|
|
5249
|
+
line(5, 9, 12, 16, 19, 9);
|
|
5250
|
+
break;
|
|
5251
|
+
case "left":
|
|
5252
|
+
line(15, 5, 8, 12, 15, 19);
|
|
5253
|
+
break;
|
|
5254
|
+
case "right":
|
|
5255
|
+
line(9, 5, 16, 12, 9, 19);
|
|
5256
|
+
break;
|
|
5257
|
+
case "arrow-up":
|
|
5258
|
+
line(12, 21, 12, 3);
|
|
5259
|
+
line(5, 10, 12, 3, 19, 10);
|
|
5260
|
+
break;
|
|
5261
|
+
case "arrow-down":
|
|
5262
|
+
line(12, 3, 12, 21);
|
|
5263
|
+
line(5, 14, 12, 21, 19, 14);
|
|
5264
|
+
break;
|
|
5265
|
+
case "arrow-left":
|
|
5266
|
+
line(21, 12, 3, 12);
|
|
5267
|
+
line(10, 5, 3, 12, 10, 19);
|
|
5268
|
+
break;
|
|
5269
|
+
case "arrow-right":
|
|
5270
|
+
line(3, 12, 21, 12);
|
|
5271
|
+
line(14, 5, 21, 12, 14, 19);
|
|
5272
|
+
break;
|
|
5273
|
+
case "search":
|
|
5274
|
+
circle(10, 10, 6.5);
|
|
5275
|
+
line(15, 15, 21, 21);
|
|
5276
|
+
break;
|
|
5277
|
+
case "edit":
|
|
5278
|
+
line(4, 15, 16, 3, 21, 8, 9, 20, 3, 21, 4, 15);
|
|
5279
|
+
line(13, 6, 18, 11);
|
|
5280
|
+
break;
|
|
5281
|
+
case "delete":
|
|
5282
|
+
line(3, 6, 21, 6);
|
|
5283
|
+
line(8, 6, 8, 3, 16, 3, 16, 6);
|
|
5284
|
+
line(5, 6, 6, 21, 18, 21, 19, 6);
|
|
5285
|
+
line(10, 10, 10, 17);
|
|
5286
|
+
line(14, 10, 14, 17);
|
|
5287
|
+
break;
|
|
5288
|
+
case "copy":
|
|
5289
|
+
rect(8, 8, 13, 13);
|
|
5290
|
+
line(16, 5, 16, 3, 3, 3, 3, 16, 5, 16);
|
|
5291
|
+
break;
|
|
5292
|
+
case "save":
|
|
5293
|
+
line(3, 3, 17, 3, 21, 7, 21, 21, 3, 21, 3, 3);
|
|
5294
|
+
rect(7, 3, 9, 6);
|
|
5295
|
+
rect(7, 14, 10, 7);
|
|
5296
|
+
break;
|
|
5297
|
+
case "upload":
|
|
5298
|
+
line(12, 17, 12, 3);
|
|
5299
|
+
line(7, 8, 12, 3, 17, 8);
|
|
5300
|
+
line(3, 16, 3, 21, 21, 21, 21, 16);
|
|
5301
|
+
break;
|
|
5302
|
+
case "download":
|
|
5303
|
+
line(12, 3, 12, 17);
|
|
5304
|
+
line(7, 12, 12, 17, 17, 12);
|
|
5305
|
+
line(3, 16, 3, 21, 21, 21, 21, 16);
|
|
5306
|
+
break;
|
|
5307
|
+
case "reload": {
|
|
5308
|
+
const end = Math.PI * 11 / 6;
|
|
5309
|
+
ctx.arc(12, 12, 8, Math.PI / 6, end);
|
|
5310
|
+
const tipX = 12 + 8 * Math.cos(end);
|
|
5311
|
+
const tipY = 12 + 8 * Math.sin(end);
|
|
5312
|
+
const arrowAngle = end + Math.PI / 2 - Math.PI / 9;
|
|
5313
|
+
const tangentX = Math.cos(arrowAngle);
|
|
5314
|
+
const tangentY = Math.sin(arrowAngle);
|
|
5315
|
+
const baseX = tipX - tangentX * 4;
|
|
5316
|
+
const baseY = tipY - tangentY * 4;
|
|
5317
|
+
line(
|
|
5318
|
+
baseX - tangentY * 3,
|
|
5319
|
+
baseY + tangentX * 3,
|
|
5320
|
+
tipX,
|
|
5321
|
+
tipY,
|
|
5322
|
+
baseX + tangentY * 3,
|
|
5323
|
+
baseY - tangentX * 3
|
|
5324
|
+
);
|
|
5325
|
+
break;
|
|
5326
|
+
}
|
|
5327
|
+
case "ellipsis":
|
|
5328
|
+
circle(5, 12, 1);
|
|
5329
|
+
circle(12, 12, 1);
|
|
5330
|
+
circle(19, 12, 1);
|
|
5331
|
+
break;
|
|
5332
|
+
case "file":
|
|
5333
|
+
file();
|
|
5334
|
+
break;
|
|
5335
|
+
case "file-text":
|
|
5336
|
+
file();
|
|
5337
|
+
line(8, 12, 16, 12);
|
|
5338
|
+
line(8, 16, 16, 16);
|
|
5339
|
+
break;
|
|
5340
|
+
case "file-pdf":
|
|
5341
|
+
file();
|
|
5342
|
+
line(8, 17, 8, 11, 11, 11, 12, 12, 12, 14, 8, 14);
|
|
5343
|
+
line(14, 17, 14, 12, 17, 12);
|
|
5344
|
+
line(14, 14.5, 16, 14.5);
|
|
5345
|
+
break;
|
|
5346
|
+
case "folder":
|
|
5347
|
+
line(2, 5, 9, 5, 11, 8, 22, 8, 22, 20, 2, 20, 2, 5);
|
|
5348
|
+
break;
|
|
5349
|
+
case "folder-open":
|
|
5350
|
+
line(2, 18, 2, 5, 9, 5, 11, 8, 20, 8, 20, 10);
|
|
5351
|
+
line(2, 20, 6, 11, 22, 11, 18, 20, 2, 20);
|
|
5352
|
+
break;
|
|
5353
|
+
case "picture":
|
|
5354
|
+
rect(3, 3, 18, 18);
|
|
5355
|
+
circle(8, 8, 2);
|
|
5356
|
+
line(3, 19, 9, 13, 13, 16, 17, 11, 21, 15);
|
|
5357
|
+
break;
|
|
5358
|
+
case "user":
|
|
5359
|
+
circle(12, 7, 4);
|
|
5360
|
+
ctx.moveTo(4, 21);
|
|
5361
|
+
ctx.bezierCurveTo(4, 10, 20, 10, 20, 21);
|
|
5362
|
+
break;
|
|
5363
|
+
case "team":
|
|
5364
|
+
circle(9, 7, 3.5);
|
|
5365
|
+
ctx.moveTo(2, 21);
|
|
5366
|
+
ctx.bezierCurveTo(2, 11, 16, 11, 16, 21);
|
|
5367
|
+
ctx.moveTo(17, 4);
|
|
5368
|
+
ctx.arc(17, 7, 3, -Math.PI / 2, Math.PI / 2);
|
|
5369
|
+
ctx.moveTo(18, 14);
|
|
5370
|
+
ctx.bezierCurveTo(22, 14, 22, 18, 22, 21);
|
|
5371
|
+
break;
|
|
5372
|
+
case "calendar":
|
|
5373
|
+
rect(3, 5, 18, 16);
|
|
5374
|
+
line(3, 10, 21, 10);
|
|
5375
|
+
line(8, 2, 8, 7);
|
|
5376
|
+
line(16, 2, 16, 7);
|
|
5377
|
+
line(7, 14, 10, 14);
|
|
5378
|
+
line(14, 14, 17, 14);
|
|
5379
|
+
line(7, 17, 10, 17);
|
|
5380
|
+
break;
|
|
5381
|
+
case "filter":
|
|
5382
|
+
line(3, 3, 21, 3, 14, 12, 14, 20, 10, 22, 10, 12, 3, 3);
|
|
5383
|
+
break;
|
|
5384
|
+
case "sort-ascending":
|
|
5385
|
+
line(4, 6, 18, 6);
|
|
5386
|
+
line(4, 12, 13, 12);
|
|
5387
|
+
line(4, 18, 8, 18);
|
|
5388
|
+
line(19, 10, 19, 21);
|
|
5389
|
+
line(16, 18, 19, 21, 22, 18);
|
|
5390
|
+
break;
|
|
5391
|
+
case "sort-descending":
|
|
5392
|
+
line(4, 6, 8, 6);
|
|
5393
|
+
line(4, 12, 13, 12);
|
|
5394
|
+
line(4, 18, 15, 18);
|
|
5395
|
+
line(19, 3, 19, 14);
|
|
5396
|
+
line(16, 6, 19, 3, 22, 6);
|
|
5397
|
+
break;
|
|
5398
|
+
case "link":
|
|
5399
|
+
line(8, 16, 16, 8);
|
|
5400
|
+
ctx.moveTo(10, 6);
|
|
5401
|
+
ctx.bezierCurveTo(16, -2, 26, 8, 18, 14);
|
|
5402
|
+
ctx.moveTo(14, 18);
|
|
5403
|
+
ctx.bezierCurveTo(8, 26, -2, 16, 6, 10);
|
|
5404
|
+
break;
|
|
5405
|
+
case "eye":
|
|
5406
|
+
ctx.moveTo(2, 12);
|
|
5407
|
+
ctx.bezierCurveTo(8, 2, 16, 2, 22, 12);
|
|
5408
|
+
ctx.bezierCurveTo(16, 22, 8, 22, 2, 12);
|
|
5409
|
+
circle(12, 12, 3);
|
|
5410
|
+
break;
|
|
5411
|
+
case "lock":
|
|
5412
|
+
rect(5, 10, 14, 11);
|
|
5413
|
+
ctx.moveTo(8, 10);
|
|
5414
|
+
ctx.lineTo(8, 7);
|
|
5415
|
+
ctx.arc(12, 7, 4, Math.PI, Math.PI * 2);
|
|
5416
|
+
ctx.lineTo(16, 10);
|
|
5417
|
+
line(12, 14, 12, 17);
|
|
5418
|
+
break;
|
|
5419
|
+
case "unlock":
|
|
5420
|
+
rect(5, 10, 14, 11);
|
|
5421
|
+
ctx.moveTo(8, 10);
|
|
5422
|
+
ctx.lineTo(8, 6);
|
|
5423
|
+
ctx.arc(12, 6, 4, Math.PI, Math.PI * 2);
|
|
5424
|
+
line(12, 14, 12, 17);
|
|
5425
|
+
break;
|
|
5426
|
+
case "home":
|
|
5427
|
+
line(2, 11, 12, 2, 22, 11);
|
|
5428
|
+
line(5, 9, 5, 21, 19, 21, 19, 9);
|
|
5429
|
+
line(9, 21, 9, 14, 15, 14, 15, 21);
|
|
5430
|
+
break;
|
|
5431
|
+
case "mail":
|
|
5432
|
+
rect(3, 5, 18, 14);
|
|
5433
|
+
line(3, 5, 12, 13, 21, 5);
|
|
5434
|
+
break;
|
|
5435
|
+
case "setting": {
|
|
5436
|
+
for (let i = 0; i <= 32; i++) {
|
|
5437
|
+
const angle = i / 32 * Math.PI * 2;
|
|
5438
|
+
const radius = i % 4 < 2 ? 10 : 8;
|
|
5439
|
+
const x = 12 + radius * Math.cos(angle);
|
|
5440
|
+
const y = 12 + radius * Math.sin(angle);
|
|
5441
|
+
if (!i) ctx.moveTo(x, y);
|
|
5442
|
+
else ctx.lineTo(x, y);
|
|
5443
|
+
}
|
|
5444
|
+
ctx.closePath();
|
|
5445
|
+
circle(12, 12, 3.5);
|
|
5446
|
+
break;
|
|
5447
|
+
}
|
|
5448
|
+
}
|
|
5449
|
+
}
|
|
5450
|
+
|
|
5451
|
+
// src/rendering/icons/draw-timeline-marker.ts
|
|
5452
|
+
var COLORS = {
|
|
5453
|
+
blue: "#1677ff",
|
|
5454
|
+
green: "#52c41a",
|
|
5455
|
+
red: "#ff4d4f",
|
|
5456
|
+
gray: "#8c8c8c"
|
|
5457
|
+
};
|
|
5458
|
+
function drawTimelineMarker(ctx, item, x, y, size, filled) {
|
|
5459
|
+
const color = COLORS[item.color ?? "blue"] ?? item.color ?? COLORS.blue;
|
|
5460
|
+
const radius = size / 2;
|
|
5461
|
+
ctx.save();
|
|
5462
|
+
try {
|
|
5463
|
+
if (item.loading) {
|
|
5464
|
+
drawIcon(ctx, {
|
|
5465
|
+
type: "loading",
|
|
5466
|
+
x: x - radius,
|
|
5467
|
+
y: y - radius,
|
|
5468
|
+
size,
|
|
5469
|
+
color
|
|
5470
|
+
});
|
|
5471
|
+
return;
|
|
5472
|
+
}
|
|
5473
|
+
const icon = item.icon ?? "circle";
|
|
5474
|
+
const type = icon === "cross" ? "close" : icon === "clock" ? "clock-circle" : icon;
|
|
5475
|
+
if (!filled && type.endsWith("-circle")) {
|
|
5476
|
+
const iconSize = size * 4 / 3;
|
|
5477
|
+
drawIcon(ctx, {
|
|
5478
|
+
type,
|
|
5479
|
+
x: x - iconSize / 2,
|
|
5480
|
+
y: y - iconSize / 2,
|
|
5481
|
+
size: iconSize,
|
|
5482
|
+
color
|
|
5483
|
+
});
|
|
5484
|
+
return;
|
|
5485
|
+
}
|
|
5486
|
+
ctx.strokeStyle = color;
|
|
5487
|
+
ctx.fillStyle = color;
|
|
5488
|
+
ctx.lineWidth = 2;
|
|
5489
|
+
ctx.beginPath();
|
|
5490
|
+
ctx.arc(x, y, radius, 0, Math.PI * 2);
|
|
5491
|
+
if (filled) ctx.fill();
|
|
5492
|
+
else ctx.stroke();
|
|
5493
|
+
if (icon === "circle") return;
|
|
5494
|
+
drawIcon(ctx, {
|
|
5495
|
+
type,
|
|
5496
|
+
x: x - size * 0.36,
|
|
5497
|
+
y: y - size * 0.36,
|
|
5498
|
+
size: size * 0.72,
|
|
5499
|
+
color: filled ? "#fff" : color
|
|
5500
|
+
});
|
|
5501
|
+
} finally {
|
|
5502
|
+
ctx.restore();
|
|
5503
|
+
}
|
|
5504
|
+
}
|
|
5505
|
+
|
|
5506
|
+
// src/rendering/icons/file-type-icon.ts
|
|
5507
|
+
function createFileTypeIconSource(filename) {
|
|
5508
|
+
const extension = (filename.split(".").length > 1 ? filename.split(".").pop() : "FILE").toUpperCase().replace(/[^A-Z0-9]/g, "").slice(0, 4) || "FILE";
|
|
5509
|
+
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>`;
|
|
5510
|
+
return `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
|
5511
|
+
}
|
|
5512
|
+
|
|
4669
5513
|
// src/rendering/cell-content/draw-icon-content.ts
|
|
4670
5514
|
var DEFAULT_ICON_SIZE = 20;
|
|
4671
5515
|
function drawBodyIconContent(params) {
|
|
@@ -4685,17 +5529,16 @@ function drawBodyIconContent(params) {
|
|
|
4685
5529
|
const size = Math.min(width, height);
|
|
4686
5530
|
const left = cursorX + (width - size) / 2;
|
|
4687
5531
|
const top = rect.y + (rect.height - size) / 2;
|
|
4688
|
-
const color = content.style?.color ?? content.color ??
|
|
5532
|
+
const color = content.style?.color ?? content.color ?? (content.icon.startsWith("header-") ? void 0 : resolveIconColor(content.icon, params.theme?.textColor));
|
|
4689
5533
|
ctx.save();
|
|
4690
5534
|
ctx.globalAlpha *= resolveContentOpacity(content);
|
|
4691
|
-
|
|
5535
|
+
drawIcon(ctx, {
|
|
4692
5536
|
type: content.icon,
|
|
4693
5537
|
x: left,
|
|
4694
5538
|
y: top,
|
|
4695
5539
|
size,
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
fillRatio: 1
|
|
5540
|
+
color,
|
|
5541
|
+
twoToneColor: content.twoToneColor
|
|
4699
5542
|
});
|
|
4700
5543
|
ctx.restore();
|
|
4701
5544
|
if (content.onClick || content.cursor) {
|
|
@@ -7494,7 +8337,7 @@ function resolveHeaderTextLayout(params) {
|
|
|
7494
8337
|
Math.min(baseX - textLeft, textRight - baseX) * 2,
|
|
7495
8338
|
0
|
|
7496
8339
|
);
|
|
7497
|
-
if (centeredWidth >= 12) {
|
|
8340
|
+
if (centeredWidth >= Math.max(params.contentWidth ?? 0, 12)) {
|
|
7498
8341
|
return {
|
|
7499
8342
|
align,
|
|
7500
8343
|
x: baseX,
|
|
@@ -7553,12 +8396,6 @@ var ACTION_GAP2 = 4;
|
|
|
7553
8396
|
var ACTION_SIZE2 = 14;
|
|
7554
8397
|
var ACTION_PADDING_INLINE2 = 10;
|
|
7555
8398
|
var GRID_LINE_OFFSET = 0.5;
|
|
7556
|
-
var FILTER_ICON_VIEWBOX_SIZE = 1024;
|
|
7557
|
-
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";
|
|
7558
|
-
var FIXED_PIN_VIEWBOX_SIZE = 1024;
|
|
7559
|
-
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";
|
|
7560
|
-
var filterIconPath = null;
|
|
7561
|
-
var fixedPinPath = null;
|
|
7562
8399
|
var EMPTY_RANGE_HIGHLIGHT = {
|
|
7563
8400
|
selectedColumnRange: null
|
|
7564
8401
|
};
|
|
@@ -7954,9 +8791,14 @@ function isSameRect(left, right) {
|
|
|
7954
8791
|
}
|
|
7955
8792
|
function drawResizeHandles(params, rect, columnKey, fixed) {
|
|
7956
8793
|
if (params.isResizable(columnKey)) {
|
|
8794
|
+
const rightHandleRect = getResizeHandleRect(params, rect, "right");
|
|
8795
|
+
const keys = params.leafColumnKeys;
|
|
8796
|
+
if (keys?.[keys.length - 1] === columnKey) {
|
|
8797
|
+
rightHandleRect.width += 5;
|
|
8798
|
+
}
|
|
7957
8799
|
params.descriptors.push({
|
|
7958
8800
|
kind: "resize-handle",
|
|
7959
|
-
rect:
|
|
8801
|
+
rect: rightHandleRect,
|
|
7960
8802
|
columnKey,
|
|
7961
8803
|
resizeEdge: "right",
|
|
7962
8804
|
fixed
|
|
@@ -8040,95 +8882,13 @@ function drawHeaderActionIcon(ctx, rect, actionType, active, hovered = false, se
|
|
|
8040
8882
|
ctx.fill();
|
|
8041
8883
|
ctx.restore();
|
|
8042
8884
|
}
|
|
8043
|
-
|
|
8044
|
-
|
|
8045
|
-
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
|
|
8049
|
-
|
|
8050
|
-
ctx.moveTo(rect.x + rect.width / 2, rect.y + 1);
|
|
8051
|
-
ctx.lineTo(rect.x + rect.width - 2, rect.y + 6);
|
|
8052
|
-
ctx.lineTo(rect.x + 2, rect.y + 6);
|
|
8053
|
-
ctx.closePath();
|
|
8054
|
-
ctx.fill();
|
|
8055
|
-
ctx.beginPath();
|
|
8056
|
-
ctx.fillStyle = sortOrder === "descend" ? "#1677ff" : "#8c8c8c";
|
|
8057
|
-
ctx.moveTo(rect.x + 2, rect.y + rect.height - 6);
|
|
8058
|
-
ctx.lineTo(rect.x + rect.width - 2, rect.y + rect.height - 6);
|
|
8059
|
-
ctx.lineTo(rect.x + rect.width / 2, rect.y + rect.height - 1);
|
|
8060
|
-
ctx.closePath();
|
|
8061
|
-
ctx.fill();
|
|
8062
|
-
} else if (actionType === "filter") {
|
|
8063
|
-
drawFilterIcon(ctx, rect);
|
|
8064
|
-
} else {
|
|
8065
|
-
drawFixedPinIcon(ctx, rect);
|
|
8066
|
-
}
|
|
8067
|
-
ctx.restore();
|
|
8068
|
-
}
|
|
8069
|
-
function drawFilterIcon(ctx, rect) {
|
|
8070
|
-
const iconWidth = rect.width * 0.92;
|
|
8071
|
-
const iconHeight = rect.height * 0.7;
|
|
8072
|
-
const offsetX = rect.x + (rect.width - iconWidth) / 2;
|
|
8073
|
-
const offsetY = rect.y + (rect.height - iconHeight) / 2;
|
|
8074
|
-
const path = resolveIconPath("filter");
|
|
8075
|
-
if (path) {
|
|
8076
|
-
ctx.save();
|
|
8077
|
-
ctx.translate(offsetX, offsetY);
|
|
8078
|
-
ctx.scale(
|
|
8079
|
-
iconWidth / FILTER_ICON_VIEWBOX_SIZE,
|
|
8080
|
-
iconHeight / FILTER_ICON_VIEWBOX_SIZE
|
|
8081
|
-
);
|
|
8082
|
-
ctx.fill(path);
|
|
8083
|
-
ctx.restore();
|
|
8084
|
-
return;
|
|
8085
|
-
}
|
|
8086
|
-
ctx.beginPath();
|
|
8087
|
-
ctx.moveTo(offsetX, offsetY);
|
|
8088
|
-
ctx.lineTo(offsetX + iconWidth, offsetY);
|
|
8089
|
-
ctx.lineTo(offsetX + iconWidth * 0.62, offsetY + iconHeight * 0.52);
|
|
8090
|
-
ctx.lineTo(offsetX + iconWidth * 0.62, offsetY + iconHeight);
|
|
8091
|
-
ctx.lineTo(offsetX + iconWidth * 0.38, offsetY + iconHeight * 0.88);
|
|
8092
|
-
ctx.lineTo(offsetX + iconWidth * 0.38, offsetY + iconHeight * 0.52);
|
|
8093
|
-
ctx.closePath();
|
|
8094
|
-
ctx.fill();
|
|
8095
|
-
}
|
|
8096
|
-
function drawFixedPinIcon(ctx, rect) {
|
|
8097
|
-
const iconSize = Math.min(rect.width, rect.height) * 0.92;
|
|
8098
|
-
const offsetX = rect.x + (rect.width - iconSize) / 2;
|
|
8099
|
-
const offsetY = rect.y + (rect.height - iconSize) / 2;
|
|
8100
|
-
const scale = iconSize / FIXED_PIN_VIEWBOX_SIZE;
|
|
8101
|
-
const path = resolveIconPath("fixed");
|
|
8102
|
-
if (path) {
|
|
8103
|
-
ctx.save();
|
|
8104
|
-
ctx.translate(offsetX, offsetY);
|
|
8105
|
-
ctx.scale(scale, scale);
|
|
8106
|
-
ctx.fill(path);
|
|
8107
|
-
ctx.restore();
|
|
8108
|
-
return;
|
|
8109
|
-
}
|
|
8110
|
-
ctx.beginPath();
|
|
8111
|
-
ctx.moveTo(offsetX + iconSize * 0.68, offsetY);
|
|
8112
|
-
ctx.lineTo(offsetX + iconSize, offsetY + iconSize * 0.32);
|
|
8113
|
-
ctx.lineTo(offsetX + iconSize * 0.78, offsetY + iconSize * 0.34);
|
|
8114
|
-
ctx.lineTo(offsetX + iconSize * 0.62, offsetY + iconSize * 0.64);
|
|
8115
|
-
ctx.lineTo(offsetX + iconSize * 0.74, offsetY + iconSize * 0.76);
|
|
8116
|
-
ctx.lineTo(offsetX + iconSize * 0.52, offsetY + iconSize * 0.82);
|
|
8117
|
-
ctx.lineTo(offsetX + iconSize * 0.16, offsetY + iconSize);
|
|
8118
|
-
ctx.lineTo(offsetX + iconSize * 0.34, offsetY + iconSize * 0.64);
|
|
8119
|
-
ctx.lineTo(offsetX + iconSize * 0.2, offsetY + iconSize * 0.5);
|
|
8120
|
-
ctx.lineTo(offsetX + iconSize * 0.5, offsetY + iconSize * 0.34);
|
|
8121
|
-
ctx.closePath();
|
|
8122
|
-
ctx.fill();
|
|
8123
|
-
}
|
|
8124
|
-
function resolveIconPath(type) {
|
|
8125
|
-
if (typeof Path2D === "undefined") return null;
|
|
8126
|
-
if (type === "filter") {
|
|
8127
|
-
filterIconPath ?? (filterIconPath = new Path2D(FILTER_ICON_PATH_DATA));
|
|
8128
|
-
return filterIconPath;
|
|
8129
|
-
}
|
|
8130
|
-
fixedPinPath ?? (fixedPinPath = new Path2D(FIXED_PIN_PATH_DATA));
|
|
8131
|
-
return fixedPinPath;
|
|
8885
|
+
drawHeaderActionGlyph(
|
|
8886
|
+
ctx,
|
|
8887
|
+
rect,
|
|
8888
|
+
actionType,
|
|
8889
|
+
actionType === "sort" ? "#8c8c8c" : active ? "#1677ff" : "#8c8c8c",
|
|
8890
|
+
sortOrder
|
|
8891
|
+
);
|
|
8132
8892
|
}
|
|
8133
8893
|
function drawHeaderContent(ctx, contents, x, y, maxWidth, align, requestRender) {
|
|
8134
8894
|
const gap = 4;
|
|
@@ -10882,6 +11642,131 @@ function applyTextContentStyle(ctx, content, fallbackColor, theme) {
|
|
|
10882
11642
|
ctx.textBaseline = "alphabetic";
|
|
10883
11643
|
ctx.textAlign = "left";
|
|
10884
11644
|
}
|
|
11645
|
+
|
|
11646
|
+
// src/features/editing/cascader-display.ts
|
|
11647
|
+
function normalizeCascaderDisplayPaths(options, values, strategy) {
|
|
11648
|
+
const index = /* @__PURE__ */ new Map();
|
|
11649
|
+
const visit = (items, parent, disabled = false) => items.map((item) => {
|
|
11650
|
+
const path = [...parent, item.value];
|
|
11651
|
+
const blocked = disabled || !!item.disabled;
|
|
11652
|
+
const children = visit(item.children ?? [], path, blocked);
|
|
11653
|
+
const node = {
|
|
11654
|
+
path,
|
|
11655
|
+
children,
|
|
11656
|
+
leaves: blocked ? [] : children.length ? children.flatMap((child) => child.leaves) : [JSON.stringify(path)]
|
|
11657
|
+
};
|
|
11658
|
+
index.set(JSON.stringify(path), node);
|
|
11659
|
+
return node;
|
|
11660
|
+
});
|
|
11661
|
+
const roots = visit(options, []);
|
|
11662
|
+
const selected = /* @__PURE__ */ new Set();
|
|
11663
|
+
const preserved = /* @__PURE__ */ new Map();
|
|
11664
|
+
for (const path of values) {
|
|
11665
|
+
const key = JSON.stringify(path);
|
|
11666
|
+
const leaves = index.get(key)?.leaves;
|
|
11667
|
+
if (!leaves?.length) preserved.set(key, path);
|
|
11668
|
+
else leaves.forEach((leaf) => selected.add(leaf));
|
|
11669
|
+
}
|
|
11670
|
+
const result = [];
|
|
11671
|
+
const collect = (node) => {
|
|
11672
|
+
if (node.leaves.length && node.leaves.every((leaf) => selected.has(leaf)) && (strategy === "SHOW_PARENT" || !node.children.length))
|
|
11673
|
+
result.push(node.path);
|
|
11674
|
+
else node.children.forEach(collect);
|
|
11675
|
+
};
|
|
11676
|
+
roots.forEach(collect);
|
|
11677
|
+
return [...result, ...preserved.values()];
|
|
11678
|
+
}
|
|
11679
|
+
|
|
11680
|
+
// src/features/upload/upload-preview.ts
|
|
11681
|
+
var localUrls = /* @__PURE__ */ new WeakMap();
|
|
11682
|
+
var ownedUrls = /* @__PURE__ */ new Set();
|
|
11683
|
+
function canPreviewUploadPdf(file) {
|
|
11684
|
+
return (file.type?.toLowerCase() === "application/pdf" || /\.pdf$/i.test(file.name)) && Boolean(resolveRemoteUrl(file.url) || file.originFileObj);
|
|
11685
|
+
}
|
|
11686
|
+
function previewUploadPdf(file) {
|
|
11687
|
+
if (typeof window === "undefined" || !canPreviewUploadPdf(file)) return;
|
|
11688
|
+
let url = resolveRemoteUrl(file.url);
|
|
11689
|
+
if (!url && file.originFileObj) {
|
|
11690
|
+
const raw = file.originFileObj;
|
|
11691
|
+
url = localUrls.get(raw);
|
|
11692
|
+
if (!url) {
|
|
11693
|
+
url = URL.createObjectURL(
|
|
11694
|
+
raw.type === "application/pdf" ? raw : raw.slice(0, raw.size, "application/pdf")
|
|
11695
|
+
);
|
|
11696
|
+
localUrls.set(raw, url);
|
|
11697
|
+
if (!ownedUrls.size) {
|
|
11698
|
+
window.addEventListener(
|
|
11699
|
+
"pagehide",
|
|
11700
|
+
() => {
|
|
11701
|
+
ownedUrls.forEach((source) => URL.revokeObjectURL(source));
|
|
11702
|
+
ownedUrls.clear();
|
|
11703
|
+
localUrls = /* @__PURE__ */ new WeakMap();
|
|
11704
|
+
},
|
|
11705
|
+
{ once: true }
|
|
11706
|
+
);
|
|
11707
|
+
}
|
|
11708
|
+
ownedUrls.add(url);
|
|
11709
|
+
}
|
|
11710
|
+
}
|
|
11711
|
+
if (url) window.open(url, "_blank", "noopener,noreferrer");
|
|
11712
|
+
}
|
|
11713
|
+
function resolveRemoteUrl(source) {
|
|
11714
|
+
if (!source || typeof window === "undefined") return void 0;
|
|
11715
|
+
try {
|
|
11716
|
+
const url = new URL(source, window.location.href);
|
|
11717
|
+
return ["http:", "https:", "blob:"].includes(url.protocol) ? url.href : void 0;
|
|
11718
|
+
} catch {
|
|
11719
|
+
return void 0;
|
|
11720
|
+
}
|
|
11721
|
+
}
|
|
11722
|
+
|
|
11723
|
+
// src/features/upload/upload-display.ts
|
|
11724
|
+
function normalizeUploadFiles(value) {
|
|
11725
|
+
return Array.isArray(value) ? value.filter((file) => file && typeof file.name === "string").map((file, index) => ({ ...file, uid: String(file.uid ?? index) })) : [];
|
|
11726
|
+
}
|
|
11727
|
+
function isUploadImage(file) {
|
|
11728
|
+
return file.type?.startsWith("image/") || /\.(png|jpe?g|gif|webp|bmp|avif|svg)$/i.test(file.name);
|
|
11729
|
+
}
|
|
11730
|
+
function uploadImageSource(file) {
|
|
11731
|
+
const source = file.thumbUrl || file.url || "";
|
|
11732
|
+
return /^(https?:|blob:|data:image\/)/i.test(source) || /^(\/|\.\/|\.\.\/)/.test(source) ? source : "";
|
|
11733
|
+
}
|
|
11734
|
+
function resolveUploadContents(value, editable = false) {
|
|
11735
|
+
return normalizeUploadFiles(value).flatMap((file) => {
|
|
11736
|
+
const src = isUploadImage(file) ? uploadImageSource(file) : "";
|
|
11737
|
+
if (src)
|
|
11738
|
+
return [
|
|
11739
|
+
{
|
|
11740
|
+
type: "image",
|
|
11741
|
+
src,
|
|
11742
|
+
alt: file.name,
|
|
11743
|
+
style: { width: 24, height: 24 }
|
|
11744
|
+
}
|
|
11745
|
+
];
|
|
11746
|
+
const preview = canPreviewUploadPdf(file) ? { cursor: "pointer", onClick: () => previewUploadPdf(file) } : {};
|
|
11747
|
+
const directPreview = editable ? {} : preview;
|
|
11748
|
+
return [
|
|
11749
|
+
{
|
|
11750
|
+
type: "image",
|
|
11751
|
+
src: createFileTypeIconSource(file.name),
|
|
11752
|
+
preview: false,
|
|
11753
|
+
...directPreview,
|
|
11754
|
+
style: { width: 24, height: 24 }
|
|
11755
|
+
},
|
|
11756
|
+
{ type: "text", text: file.name, ...directPreview },
|
|
11757
|
+
...editable && preview.onClick ? [
|
|
11758
|
+
{
|
|
11759
|
+
type: "button",
|
|
11760
|
+
text: "\u9884\u89C8",
|
|
11761
|
+
buttonType: "link",
|
|
11762
|
+
...preview
|
|
11763
|
+
}
|
|
11764
|
+
] : []
|
|
11765
|
+
];
|
|
11766
|
+
});
|
|
11767
|
+
}
|
|
11768
|
+
|
|
11769
|
+
// src/features/editing/editing-utils.ts
|
|
10885
11770
|
function canEditCell(column, context) {
|
|
10886
11771
|
if (!column || column.key === ROW_SELECTION_COLUMN_KEY || column.key === ROW_SELECTOR_COLUMN_KEY || column.key === EXPAND_COLUMN_KEY) {
|
|
10887
11772
|
return false;
|
|
@@ -10915,7 +11800,13 @@ function getColumnEditConfig(column, context) {
|
|
|
10915
11800
|
max: resolvedFormItemProps.max,
|
|
10916
11801
|
step: resolvedFormItemProps.step,
|
|
10917
11802
|
options: resolvedFormItemProps.options,
|
|
11803
|
+
treeData: resolvedFormItemProps.treeData,
|
|
11804
|
+
upload: resolvedFormItemProps.upload,
|
|
11805
|
+
treeDefaultExpandAll: resolvedFormItemProps.treeDefaultExpandAll,
|
|
11806
|
+
treeDefaultExpandedKeys: resolvedFormItemProps.treeDefaultExpandedKeys,
|
|
10918
11807
|
changeOnSelect: resolvedFormItemProps.changeOnSelect,
|
|
11808
|
+
multiple: resolvedFormItemProps.multiple,
|
|
11809
|
+
showCheckedStrategy: resolvedFormItemProps.showCheckedStrategy,
|
|
10919
11810
|
expandTrigger: resolvedFormItemProps.expandTrigger,
|
|
10920
11811
|
allowClear: resolvedFormItemProps.allowClear,
|
|
10921
11812
|
displayRender: resolvedFormItemProps.displayRender,
|
|
@@ -10952,16 +11843,43 @@ function resolveFormattedCellText(params) {
|
|
|
10952
11843
|
if (formatter === "") {
|
|
10953
11844
|
return "";
|
|
10954
11845
|
}
|
|
11846
|
+
if (resolvedFormItemProps?.valueType === "upload") {
|
|
11847
|
+
return normalizeUploadFiles(value).map((file) => file.name).join("\u3001");
|
|
11848
|
+
}
|
|
11849
|
+
if (resolvedFormItemProps?.valueType === "tree-select") {
|
|
11850
|
+
const titles = /* @__PURE__ */ new Map();
|
|
11851
|
+
const pending = [...resolvedFormItemProps.treeData ?? []];
|
|
11852
|
+
while (pending.length) {
|
|
11853
|
+
const node = pending.pop();
|
|
11854
|
+
titles.set(node.value, node.title);
|
|
11855
|
+
if (node.children) pending.push(...node.children);
|
|
11856
|
+
}
|
|
11857
|
+
const values = resolvedFormItemProps.multiple ? Array.isArray(value) ? value : [] : [value];
|
|
11858
|
+
return [
|
|
11859
|
+
...new Set(
|
|
11860
|
+
values.filter(
|
|
11861
|
+
(part) => typeof part === "string" || typeof part === "number"
|
|
11862
|
+
)
|
|
11863
|
+
)
|
|
11864
|
+
].map((part) => titles.get(part) ?? String(part)).join("\uFF1B");
|
|
11865
|
+
}
|
|
10955
11866
|
if (resolvedFormItemProps?.valueType === "cascader" && Array.isArray(value)) {
|
|
10956
|
-
|
|
10957
|
-
|
|
10958
|
-
|
|
10959
|
-
const
|
|
10960
|
-
|
|
10961
|
-
|
|
10962
|
-
|
|
10963
|
-
|
|
10964
|
-
|
|
11867
|
+
const formatPath = (path) => {
|
|
11868
|
+
let options = resolvedFormItemProps.options ?? [];
|
|
11869
|
+
const selectedOptions = [];
|
|
11870
|
+
const labels = path.map((part) => {
|
|
11871
|
+
const option = options.find((item) => item.value === part);
|
|
11872
|
+
options = option?.children ?? [];
|
|
11873
|
+
if (option) selectedOptions.push(option);
|
|
11874
|
+
return option?.label ?? String(part ?? "");
|
|
11875
|
+
});
|
|
11876
|
+
return resolvedFormItemProps.displayRender?.(labels, selectedOptions) ?? labels.join(" / ");
|
|
11877
|
+
};
|
|
11878
|
+
return resolvedFormItemProps.multiple ? normalizeCascaderDisplayPaths(
|
|
11879
|
+
resolvedFormItemProps.options ?? [],
|
|
11880
|
+
value.filter(Array.isArray),
|
|
11881
|
+
resolvedFormItemProps.showCheckedStrategy ?? "SHOW_PARENT"
|
|
11882
|
+
).map(formatPath).join("\uFF1B") : formatPath(value);
|
|
10965
11883
|
}
|
|
10966
11884
|
if (Array.isArray(value) && (resolvedFormItemProps?.valueType === "date-range" || resolvedFormItemProps?.valueType === "datetime-range" || resolvedFormItemProps?.valueType === "timerange")) {
|
|
10967
11885
|
const [start = "", end = ""] = value;
|
|
@@ -11054,6 +11972,196 @@ function resolveColumnFormItemProps(column, context) {
|
|
|
11054
11972
|
return column.formItemProps;
|
|
11055
11973
|
}
|
|
11056
11974
|
|
|
11975
|
+
// src/rendering/cell-content/draw-timeline-content.ts
|
|
11976
|
+
function positive(value, fallback) {
|
|
11977
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
11978
|
+
}
|
|
11979
|
+
function timelineItems(content) {
|
|
11980
|
+
const items = content.items ?? [];
|
|
11981
|
+
return content.reverse ? [...items].reverse() : items;
|
|
11982
|
+
}
|
|
11983
|
+
function timelinePlainText(content) {
|
|
11984
|
+
return timelineItems(content).map((item) => [item.title, item.content].filter(Boolean).join(" ")).join("\n");
|
|
11985
|
+
}
|
|
11986
|
+
function measureTimelineWidth(content) {
|
|
11987
|
+
return positive(content.style?.width ?? content.width, 220);
|
|
11988
|
+
}
|
|
11989
|
+
function wrap(ctx, text, width) {
|
|
11990
|
+
const lines = [];
|
|
11991
|
+
for (const paragraph of String(text ?? "").split(/\r?\n/)) {
|
|
11992
|
+
let line = "";
|
|
11993
|
+
for (const character of paragraph) {
|
|
11994
|
+
if (line && ctx.measureText(line + character).width > width) {
|
|
11995
|
+
lines.push(line);
|
|
11996
|
+
line = "";
|
|
11997
|
+
}
|
|
11998
|
+
line += character;
|
|
11999
|
+
}
|
|
12000
|
+
lines.push(line);
|
|
12001
|
+
}
|
|
12002
|
+
return lines;
|
|
12003
|
+
}
|
|
12004
|
+
function layoutTimeline(ctx, content, theme, availableWidth = measureTimelineWidth(content)) {
|
|
12005
|
+
const width = Math.max(
|
|
12006
|
+
1,
|
|
12007
|
+
Math.min(measureTimelineWidth(content), availableWidth)
|
|
12008
|
+
);
|
|
12009
|
+
const fontSize = positive(
|
|
12010
|
+
resolveContentFontSize(content, theme.fontSize),
|
|
12011
|
+
theme.fontSize
|
|
12012
|
+
);
|
|
12013
|
+
const font = buildCanvasFont({
|
|
12014
|
+
fontSize,
|
|
12015
|
+
fontFamily: resolveContentFontFamily(content, theme),
|
|
12016
|
+
fontWeight: resolveContentFontWeight(content)
|
|
12017
|
+
});
|
|
12018
|
+
const lineHeight = Math.ceil(fontSize * 1.5);
|
|
12019
|
+
const dot = Math.min(positive(content.dotSize, 16), lineHeight);
|
|
12020
|
+
const gap = typeof content.itemGap === "number" && Number.isFinite(content.itemGap) ? Math.max(0, content.itemGap) : 12;
|
|
12021
|
+
const items = timelineItems(content);
|
|
12022
|
+
const mode = content.mode ?? "start";
|
|
12023
|
+
const paired = mode === "alternate" || items.some(
|
|
12024
|
+
(item) => item.title || item.position && item.position !== mode
|
|
12025
|
+
);
|
|
12026
|
+
const axis = paired ? width / 2 : mode === "end" ? width - dot / 2 - 1 : dot / 2 + 1;
|
|
12027
|
+
const gutter = dot / 2 + 8;
|
|
12028
|
+
const leftWidth = Math.max(1, axis - gutter);
|
|
12029
|
+
const rightWidth = Math.max(1, width - axis - gutter);
|
|
12030
|
+
let height = 0;
|
|
12031
|
+
ctx.save();
|
|
12032
|
+
ctx.font = font;
|
|
12033
|
+
const nodes = items.map((item, index) => {
|
|
12034
|
+
const position = item.position ?? (mode === "alternate" ? index % 2 ? "end" : "start" : mode);
|
|
12035
|
+
const onRight = position === "start";
|
|
12036
|
+
const textWidth = onRight ? rightWidth : leftWidth;
|
|
12037
|
+
const titleWidth = onRight ? leftWidth : rightWidth;
|
|
12038
|
+
const lines = wrap(ctx, item.content, textWidth);
|
|
12039
|
+
const titles = item.title ? wrap(ctx, item.title, titleWidth) : [];
|
|
12040
|
+
const nodeHeight = Math.max(lines.length, titles.length, 1) * lineHeight;
|
|
12041
|
+
const node = {
|
|
12042
|
+
item,
|
|
12043
|
+
onRight,
|
|
12044
|
+
lines,
|
|
12045
|
+
titles,
|
|
12046
|
+
y: height,
|
|
12047
|
+
height: nodeHeight,
|
|
12048
|
+
textWidth,
|
|
12049
|
+
titleWidth
|
|
12050
|
+
};
|
|
12051
|
+
height += nodeHeight + (index < items.length - 1 ? gap : 0);
|
|
12052
|
+
return node;
|
|
12053
|
+
});
|
|
12054
|
+
ctx.restore();
|
|
12055
|
+
return {
|
|
12056
|
+
width,
|
|
12057
|
+
height,
|
|
12058
|
+
font,
|
|
12059
|
+
fontSize,
|
|
12060
|
+
lineHeight,
|
|
12061
|
+
dot,
|
|
12062
|
+
axis,
|
|
12063
|
+
gutter,
|
|
12064
|
+
nodes
|
|
12065
|
+
};
|
|
12066
|
+
}
|
|
12067
|
+
function drawBodyTimelineContent(params) {
|
|
12068
|
+
const {
|
|
12069
|
+
ctx,
|
|
12070
|
+
content,
|
|
12071
|
+
theme,
|
|
12072
|
+
rect,
|
|
12073
|
+
cursorX,
|
|
12074
|
+
descriptors,
|
|
12075
|
+
column,
|
|
12076
|
+
rowIndex,
|
|
12077
|
+
contentIndex,
|
|
12078
|
+
frozen
|
|
12079
|
+
} = params;
|
|
12080
|
+
const layout = layoutTimeline(ctx, content, theme, rect.width);
|
|
12081
|
+
if (!layout.nodes.length) return;
|
|
12082
|
+
const top = rect.y + Math.max(0, (rect.height - layout.height) / 2);
|
|
12083
|
+
const axis = cursorX + layout.axis;
|
|
12084
|
+
ctx.save();
|
|
12085
|
+
ctx.beginPath();
|
|
12086
|
+
ctx.rect(cursorX, top, layout.width, Math.min(layout.height, rect.height));
|
|
12087
|
+
ctx.clip();
|
|
12088
|
+
ctx.globalAlpha *= resolveContentOpacity(content);
|
|
12089
|
+
ctx.font = layout.font;
|
|
12090
|
+
ctx.textBaseline = "middle";
|
|
12091
|
+
layout.nodes.forEach((node, index) => {
|
|
12092
|
+
const centerY = top + node.y + layout.lineHeight / 2;
|
|
12093
|
+
const next = layout.nodes[index + 1];
|
|
12094
|
+
if (next) {
|
|
12095
|
+
ctx.strokeStyle = content.lineColor ?? theme.borderColor;
|
|
12096
|
+
ctx.lineWidth = 1;
|
|
12097
|
+
ctx.setLineDash(node.item.loading || next.item.loading ? [3, 3] : []);
|
|
12098
|
+
ctx.beginPath();
|
|
12099
|
+
ctx.moveTo(axis, centerY + layout.dot / 2 + 2);
|
|
12100
|
+
ctx.lineTo(
|
|
12101
|
+
axis,
|
|
12102
|
+
top + next.y + layout.lineHeight / 2 - layout.dot / 2 - 2
|
|
12103
|
+
);
|
|
12104
|
+
ctx.stroke();
|
|
12105
|
+
ctx.setLineDash([]);
|
|
12106
|
+
}
|
|
12107
|
+
drawTimelineMarker(
|
|
12108
|
+
ctx,
|
|
12109
|
+
node.item,
|
|
12110
|
+
axis,
|
|
12111
|
+
centerY,
|
|
12112
|
+
layout.dot,
|
|
12113
|
+
content.variant === "filled"
|
|
12114
|
+
);
|
|
12115
|
+
const drawLines = (lines, right, width, color) => {
|
|
12116
|
+
const x = right ? axis + layout.gutter : cursorX;
|
|
12117
|
+
ctx.save();
|
|
12118
|
+
ctx.beginPath();
|
|
12119
|
+
ctx.rect(x, top + node.y, width, node.height);
|
|
12120
|
+
ctx.clip();
|
|
12121
|
+
ctx.fillStyle = color;
|
|
12122
|
+
ctx.textAlign = right ? "left" : "right";
|
|
12123
|
+
lines.forEach(
|
|
12124
|
+
(line, lineIndex) => ctx.fillText(
|
|
12125
|
+
line,
|
|
12126
|
+
right ? x : axis - layout.gutter,
|
|
12127
|
+
centerY + lineIndex * layout.lineHeight
|
|
12128
|
+
)
|
|
12129
|
+
);
|
|
12130
|
+
ctx.restore();
|
|
12131
|
+
};
|
|
12132
|
+
drawLines(
|
|
12133
|
+
node.lines,
|
|
12134
|
+
node.onRight,
|
|
12135
|
+
node.textWidth,
|
|
12136
|
+
content.style?.color ?? theme.textColor
|
|
12137
|
+
);
|
|
12138
|
+
drawLines(
|
|
12139
|
+
node.titles,
|
|
12140
|
+
!node.onRight,
|
|
12141
|
+
node.titleWidth,
|
|
12142
|
+
content.titleColor ?? theme.mutedTextColor ?? theme.textColor
|
|
12143
|
+
);
|
|
12144
|
+
});
|
|
12145
|
+
ctx.restore();
|
|
12146
|
+
descriptors.push({
|
|
12147
|
+
kind: "body-content",
|
|
12148
|
+
rect: {
|
|
12149
|
+
x: cursorX,
|
|
12150
|
+
y: top,
|
|
12151
|
+
width: layout.width,
|
|
12152
|
+
height: Math.min(layout.height, rect.height)
|
|
12153
|
+
},
|
|
12154
|
+
rowIndex,
|
|
12155
|
+
columnKey: column.key,
|
|
12156
|
+
fixed: column.fixed,
|
|
12157
|
+
frozen,
|
|
12158
|
+
contentIndex,
|
|
12159
|
+
contentKey: content.key,
|
|
12160
|
+
cursor: content.cursor ?? (content.onClick ? "pointer" : void 0),
|
|
12161
|
+
tooltipText: timelinePlainText(content)
|
|
12162
|
+
});
|
|
12163
|
+
}
|
|
12164
|
+
|
|
11057
12165
|
// src/rendering/cell-content/cell-content-renderer.ts
|
|
11058
12166
|
var CONTENT_HORIZONTAL_PADDING = 12;
|
|
11059
12167
|
var CONTENT_GAP = 8;
|
|
@@ -11071,6 +12179,12 @@ function resolveRawBodyCellContents(params) {
|
|
|
11071
12179
|
if (rendered != null) {
|
|
11072
12180
|
return normalizeCellContents(rendered);
|
|
11073
12181
|
}
|
|
12182
|
+
if (resolveColumnFormItemProps(column, { value, record, rowIndex })?.valueType === "upload") {
|
|
12183
|
+
return resolveUploadContents(
|
|
12184
|
+
value,
|
|
12185
|
+
canEditCell(column, { value, record, rowIndex })
|
|
12186
|
+
);
|
|
12187
|
+
}
|
|
11074
12188
|
const formattedText = resolveFormattedCellText({
|
|
11075
12189
|
column,
|
|
11076
12190
|
value,
|
|
@@ -11146,6 +12260,11 @@ function resolveRawBodyCellContents(params) {
|
|
|
11146
12260
|
}
|
|
11147
12261
|
] : [];
|
|
11148
12262
|
}
|
|
12263
|
+
if (column.cellType === "timeline") {
|
|
12264
|
+
return [
|
|
12265
|
+
{ type: "timeline", items: Array.isArray(value) ? value : [] }
|
|
12266
|
+
];
|
|
12267
|
+
}
|
|
11149
12268
|
if (column.cellType === "progress") {
|
|
11150
12269
|
const numericValue = typeof value === "number" ? value : typeof value === "string" ? Number(value) : 0;
|
|
11151
12270
|
return [
|
|
@@ -11233,6 +12352,9 @@ function normalizeDrawableCellContents(contents) {
|
|
|
11233
12352
|
).map(normalizeCellContentItem);
|
|
11234
12353
|
}
|
|
11235
12354
|
function normalizeCellContentItem(content) {
|
|
12355
|
+
if (content.type === "timeline") {
|
|
12356
|
+
return { ...content, style: { ...content.style, display: "block" } };
|
|
12357
|
+
}
|
|
11236
12358
|
if (content.type !== "money") {
|
|
11237
12359
|
return content;
|
|
11238
12360
|
}
|
|
@@ -11478,7 +12600,12 @@ function drawBodyCellContents(params) {
|
|
|
11478
12600
|
);
|
|
11479
12601
|
return void 0;
|
|
11480
12602
|
}
|
|
11481
|
-
const lineHeight = getBodyCellContentsLineHeight(
|
|
12603
|
+
const lineHeight = getBodyCellContentsLineHeight(
|
|
12604
|
+
contents,
|
|
12605
|
+
theme,
|
|
12606
|
+
ctx,
|
|
12607
|
+
availableWidth
|
|
12608
|
+
);
|
|
11482
12609
|
const layout = layoutBodyCellContents({
|
|
11483
12610
|
ctx,
|
|
11484
12611
|
contents,
|
|
@@ -11651,7 +12778,12 @@ function measureBodyCellContentsHeight(params) {
|
|
|
11651
12778
|
if (availableWidth <= 0) {
|
|
11652
12779
|
return paddingBlock * 2;
|
|
11653
12780
|
}
|
|
11654
|
-
const lineHeight = getBodyCellContentsLineHeight(
|
|
12781
|
+
const lineHeight = getBodyCellContentsLineHeight(
|
|
12782
|
+
contents,
|
|
12783
|
+
theme,
|
|
12784
|
+
ctx,
|
|
12785
|
+
availableWidth
|
|
12786
|
+
);
|
|
11655
12787
|
const layout = layoutBodyCellContents({
|
|
11656
12788
|
ctx,
|
|
11657
12789
|
contents,
|
|
@@ -12130,6 +13262,7 @@ function drawExpandedBodyContent(params) {
|
|
|
12130
13262
|
if (content.type === "icon") {
|
|
12131
13263
|
drawBodyIconContent({
|
|
12132
13264
|
ctx,
|
|
13265
|
+
theme,
|
|
12133
13266
|
rect,
|
|
12134
13267
|
content,
|
|
12135
13268
|
contentIndex,
|
|
@@ -12202,6 +13335,21 @@ function drawExpandedBodyContent(params) {
|
|
|
12202
13335
|
});
|
|
12203
13336
|
return;
|
|
12204
13337
|
}
|
|
13338
|
+
if (content.type === "timeline") {
|
|
13339
|
+
drawBodyTimelineContent({
|
|
13340
|
+
ctx,
|
|
13341
|
+
rect,
|
|
13342
|
+
content,
|
|
13343
|
+
contentIndex,
|
|
13344
|
+
cursorX,
|
|
13345
|
+
rowIndex,
|
|
13346
|
+
column,
|
|
13347
|
+
theme,
|
|
13348
|
+
frozen,
|
|
13349
|
+
descriptors
|
|
13350
|
+
});
|
|
13351
|
+
return;
|
|
13352
|
+
}
|
|
12205
13353
|
if (content.type === "progress") {
|
|
12206
13354
|
drawBodyProgressContent({
|
|
12207
13355
|
ctx,
|
|
@@ -12377,6 +13525,7 @@ function measureExpandedContentWidth(ctx, content, theme) {
|
|
|
12377
13525
|
if (content.type === "button") {
|
|
12378
13526
|
return measureButtonContentWidth(ctx, content, theme);
|
|
12379
13527
|
}
|
|
13528
|
+
if (content.type === "timeline") return measureTimelineWidth(content);
|
|
12380
13529
|
if (content.type === "progress") {
|
|
12381
13530
|
return measureProgressContentWidth(ctx, content, theme);
|
|
12382
13531
|
}
|
|
@@ -12431,9 +13580,16 @@ function getBodyCellContentsLineGap(contents, lineHeight) {
|
|
|
12431
13580
|
}
|
|
12432
13581
|
return tagHeight > 0 ? Math.max(CONTENT_GAP - (lineHeight - tagHeight), 0) : 0;
|
|
12433
13582
|
}
|
|
12434
|
-
function getBodyCellContentsLineHeight(contents, theme) {
|
|
13583
|
+
function getBodyCellContentsLineHeight(contents, theme, ctx, availableWidth) {
|
|
12435
13584
|
let lineHeight = theme.fontSize + 8;
|
|
12436
13585
|
contents.forEach((item) => {
|
|
13586
|
+
if (item.type === "timeline") {
|
|
13587
|
+
lineHeight = Math.max(
|
|
13588
|
+
lineHeight,
|
|
13589
|
+
layoutTimeline(ctx, item, theme, availableWidth).height
|
|
13590
|
+
);
|
|
13591
|
+
return;
|
|
13592
|
+
}
|
|
12437
13593
|
if (item.type === "arrow") {
|
|
12438
13594
|
lineHeight = Math.max(lineHeight, measureArrowContentHeight(item));
|
|
12439
13595
|
return;
|
|
@@ -12508,6 +13664,15 @@ function getBodyCellContentsLineHeight(contents, theme) {
|
|
|
12508
13664
|
return lineHeight;
|
|
12509
13665
|
}
|
|
12510
13666
|
function truncateExpandedContent(ctx, content, theme, maxWidth, withEllipsis) {
|
|
13667
|
+
if (content.type === "timeline") {
|
|
13668
|
+
return maxWidth > 0 ? {
|
|
13669
|
+
...content,
|
|
13670
|
+
style: {
|
|
13671
|
+
...content.style,
|
|
13672
|
+
width: Math.min(measureTimelineWidth(content), maxWidth)
|
|
13673
|
+
}
|
|
13674
|
+
} : null;
|
|
13675
|
+
}
|
|
12511
13676
|
if (content.type === "text" || content.type === "link") {
|
|
12512
13677
|
const nextText = fitTextToWidth(
|
|
12513
13678
|
getBreakableContentText(content),
|
|
@@ -12657,6 +13822,7 @@ function buildBodyContentsPlainText(contents) {
|
|
|
12657
13822
|
if (content.type === "progress") {
|
|
12658
13823
|
return content.text ?? `${Math.round(resolveProgressPercent(content))}%`;
|
|
12659
13824
|
}
|
|
13825
|
+
if (content.type === "timeline") return timelinePlainText(content);
|
|
12660
13826
|
if (content.type === "chart") {
|
|
12661
13827
|
return resolveChartContentPlainText(content);
|
|
12662
13828
|
}
|
|
@@ -12971,6 +14137,7 @@ function isCellContentDisabled(content) {
|
|
|
12971
14137
|
if (content.type === "button") {
|
|
12972
14138
|
return content.disabled === true;
|
|
12973
14139
|
}
|
|
14140
|
+
if (content.type === "timeline") return false;
|
|
12974
14141
|
if (content.type === "progress") {
|
|
12975
14142
|
return false;
|
|
12976
14143
|
}
|
|
@@ -16422,6 +17589,11 @@ function getCellClipboardText(record, rowIndex, column) {
|
|
|
16422
17589
|
if (column.cellType === "checkbox" || column.cellType === "radio") {
|
|
16423
17590
|
return String(Boolean(value));
|
|
16424
17591
|
}
|
|
17592
|
+
if (column.cellType === "timeline") {
|
|
17593
|
+
return timelinePlainText({
|
|
17594
|
+
items: Array.isArray(value) ? value : []
|
|
17595
|
+
});
|
|
17596
|
+
}
|
|
16425
17597
|
return resolveFormattedCellText({
|
|
16426
17598
|
column,
|
|
16427
17599
|
value,
|
|
@@ -16572,7 +17744,7 @@ async function copyRowJsonContent(params) {
|
|
|
16572
17744
|
}
|
|
16573
17745
|
async function exportAllRowsJsonContent(params) {
|
|
16574
17746
|
await downloadJsonFile({
|
|
16575
|
-
fileName: buildTableExportFileName("json"),
|
|
17747
|
+
fileName: params.fileName?.trim() || buildTableExportFileName("json"),
|
|
16576
17748
|
data: mapRowsToExportRecords({
|
|
16577
17749
|
rows: params.rows,
|
|
16578
17750
|
columns: buildExportColumns(params.columns)
|
|
@@ -16581,14 +17753,14 @@ async function exportAllRowsJsonContent(params) {
|
|
|
16581
17753
|
}
|
|
16582
17754
|
async function exportAllRowsCsvContent(params) {
|
|
16583
17755
|
await exportTableToCsv({
|
|
16584
|
-
fileName: buildTableExportFileName("csv"),
|
|
17756
|
+
fileName: params.fileName?.trim() || buildTableExportFileName("csv"),
|
|
16585
17757
|
rows: params.rows,
|
|
16586
17758
|
columns: buildExportColumns(params.columns)
|
|
16587
17759
|
});
|
|
16588
17760
|
}
|
|
16589
17761
|
async function exportAllRowsTxtContent(params) {
|
|
16590
17762
|
await exportTableToTxt({
|
|
16591
|
-
fileName: buildTableExportFileName("txt"),
|
|
17763
|
+
fileName: params.fileName?.trim() || buildTableExportFileName("txt"),
|
|
16592
17764
|
rows: params.rows,
|
|
16593
17765
|
columns: buildExportColumns(params.columns)
|
|
16594
17766
|
});
|
|
@@ -16658,6 +17830,7 @@ function cellContentToClipboardText(content) {
|
|
|
16658
17830
|
if (content.type === "progress") {
|
|
16659
17831
|
return content.text ?? `${Math.round(resolveProgressClipboardPercent(content))}%`;
|
|
16660
17832
|
}
|
|
17833
|
+
if (content.type === "timeline") return timelinePlainText(content);
|
|
16661
17834
|
if (content.type === "chart") {
|
|
16662
17835
|
return resolveChartContentPlainText(content);
|
|
16663
17836
|
}
|
|
@@ -16870,17 +18043,21 @@ var ListTableContentActionController = class {
|
|
|
16870
18043
|
constructor(options) {
|
|
16871
18044
|
__publicField(this, "options");
|
|
16872
18045
|
__publicField(this, "exportTaskRunning", false);
|
|
18046
|
+
__publicField(this, "exportNamePending", false);
|
|
16873
18047
|
this.options = options;
|
|
16874
18048
|
}
|
|
16875
18049
|
/**
|
|
16876
18050
|
* 异步导出全部原始数据为 XLSX。
|
|
16877
18051
|
*/
|
|
16878
18052
|
exportXlsx(options) {
|
|
18053
|
+
options = { ...this.options.getOptions().exportOptions, ...options };
|
|
16879
18054
|
this.startExportTask(
|
|
16880
|
-
() => exportAllRowsXlsxContent({
|
|
18055
|
+
(fileName) => exportAllRowsXlsxContent({
|
|
16881
18056
|
rows: this.options.getOptions().dataSource,
|
|
16882
18057
|
columns: this.options.getLeafColumns(),
|
|
16883
18058
|
...options,
|
|
18059
|
+
includeSummary: options?.includeSummary ?? this.options.getSummaryVisible?.() ?? false,
|
|
18060
|
+
fileName: fileName ?? options?.fileName,
|
|
16884
18061
|
onProgress: (progress) => {
|
|
16885
18062
|
const fileLabel = progress.fileCount && progress.fileCount > 1 ? `\uFF08\u7B2C ${progress.fileIndex}/${progress.fileCount} \u4EFD\uFF09` : "";
|
|
16886
18063
|
this.options.overlayController.showLoading(
|
|
@@ -16890,16 +18067,55 @@ var ListTableContentActionController = class {
|
|
|
16890
18067
|
}
|
|
16891
18068
|
}),
|
|
16892
18069
|
"\u6B63\u5728\u5BFC\u51FA XLSX\u2026",
|
|
16893
|
-
options?.onError
|
|
18070
|
+
options?.onError,
|
|
18071
|
+
options?.fileName?.trim() ? `${options.fileName.trim().replace(/\.xlsx$/i, "")}.xlsx` : buildTableExportFileName("xlsx"),
|
|
18072
|
+
options?.promptFileName
|
|
16894
18073
|
);
|
|
16895
18074
|
}
|
|
16896
|
-
startExportTask(task, text, onError) {
|
|
16897
|
-
if (this.exportTaskRunning) {
|
|
18075
|
+
startExportTask(task, text, onError, defaultFileName, promptFileName = this.options.getOptions().exportOptions?.promptFileName ?? true) {
|
|
18076
|
+
if (this.exportTaskRunning || this.exportNamePending) {
|
|
18077
|
+
return;
|
|
18078
|
+
}
|
|
18079
|
+
if (defaultFileName !== void 0 && promptFileName) {
|
|
18080
|
+
this.exportNamePending = true;
|
|
18081
|
+
const notify = this.options.getOptions().ui?.onExportNameRequest;
|
|
18082
|
+
let settled = false;
|
|
18083
|
+
const close = () => {
|
|
18084
|
+
settled = true;
|
|
18085
|
+
this.exportNamePending = false;
|
|
18086
|
+
notify?.(null);
|
|
18087
|
+
};
|
|
18088
|
+
const request = {
|
|
18089
|
+
fileName: defaultFileName,
|
|
18090
|
+
onConfirm: (value) => {
|
|
18091
|
+
if (settled || !value.trim()) return;
|
|
18092
|
+
close();
|
|
18093
|
+
const extension = defaultFileName.match(
|
|
18094
|
+
/\.(xlsx|csv|txt|json)$/i
|
|
18095
|
+
)?.[0];
|
|
18096
|
+
const name = extension && !value.trim().toLowerCase().endsWith(extension.toLowerCase()) ? `${value.trim()}${extension}` : value.trim();
|
|
18097
|
+
this.startExportTask(() => task(name), text, onError);
|
|
18098
|
+
},
|
|
18099
|
+
onCancel: () => {
|
|
18100
|
+
if (!settled) close();
|
|
18101
|
+
}
|
|
18102
|
+
};
|
|
18103
|
+
if (notify) notify(request);
|
|
18104
|
+
else if (typeof window !== "undefined" && typeof window.prompt === "function") {
|
|
18105
|
+
const extension = defaultFileName.match(/\.(xlsx|csv|txt|json)$/i)?.[0] ?? "";
|
|
18106
|
+
const baseName = extension ? defaultFileName.slice(0, -extension.length) : defaultFileName;
|
|
18107
|
+
const value = window.prompt(
|
|
18108
|
+
`\u8BF7\u8F93\u5165\u5BFC\u51FA\u6587\u4EF6\u540D\u79F0\uFF08\u56FA\u5B9A\u540E\u7F00\uFF1A${extension}\uFF09`,
|
|
18109
|
+
baseName
|
|
18110
|
+
);
|
|
18111
|
+
if (value == null || !value.trim()) request.onCancel();
|
|
18112
|
+
else request.onConfirm(`${value.trim()}${extension}`);
|
|
18113
|
+
} else request.onConfirm(defaultFileName);
|
|
16898
18114
|
return;
|
|
16899
18115
|
}
|
|
16900
18116
|
this.exportTaskRunning = true;
|
|
16901
18117
|
this.options.overlayController.showLoading(text);
|
|
16902
|
-
void task().catch((error) => {
|
|
18118
|
+
void Promise.resolve().then(() => task(defaultFileName)).catch((error) => {
|
|
16903
18119
|
if (error?.name === "AbortError") return;
|
|
16904
18120
|
console.error("[ListTable] Failed to export table data:", error);
|
|
16905
18121
|
onError?.(error);
|
|
@@ -17177,6 +18393,312 @@ function setValueByDataIndex(record, dataIndex, value) {
|
|
|
17177
18393
|
return true;
|
|
17178
18394
|
}
|
|
17179
18395
|
|
|
18396
|
+
// src/features/upload/upload-editor.ts
|
|
18397
|
+
function createUploadEditor(params) {
|
|
18398
|
+
const config = params.config ?? {};
|
|
18399
|
+
let files = normalizeUploadFiles(params.value);
|
|
18400
|
+
let alive = true;
|
|
18401
|
+
let pending = 0;
|
|
18402
|
+
let sequence = 0;
|
|
18403
|
+
const requests = /* @__PURE__ */ new Map();
|
|
18404
|
+
const readers = /* @__PURE__ */ new Set();
|
|
18405
|
+
const root = document.createElement("div");
|
|
18406
|
+
root.setAttribute("role", "dialog");
|
|
18407
|
+
root.setAttribute("aria-label", "\u4E0A\u4F20\u9644\u4EF6");
|
|
18408
|
+
root.tabIndex = -1;
|
|
18409
|
+
const width = Math.min(360, Math.max(200, window.innerWidth - 16));
|
|
18410
|
+
Object.assign(root.style, {
|
|
18411
|
+
position: "fixed",
|
|
18412
|
+
zIndex: "10000",
|
|
18413
|
+
boxSizing: "border-box",
|
|
18414
|
+
width: `${width}px`,
|
|
18415
|
+
left: `${Math.max(8, Math.min(params.rect.x, window.innerWidth - width - 8))}px`,
|
|
18416
|
+
top: `${Math.max(8, Math.min(params.rect.y, window.innerHeight - 280))}px`,
|
|
18417
|
+
maxHeight: "calc(100vh - 16px)",
|
|
18418
|
+
overflow: "auto",
|
|
18419
|
+
padding: "12px",
|
|
18420
|
+
background: "#fff",
|
|
18421
|
+
color: "#1f2937",
|
|
18422
|
+
border: "1px solid #d9e1ec",
|
|
18423
|
+
borderRadius: "6px",
|
|
18424
|
+
boxShadow: "0 6px 24px #0002",
|
|
18425
|
+
font: "13px sans-serif"
|
|
18426
|
+
});
|
|
18427
|
+
for (const event of [
|
|
18428
|
+
"pointerdown",
|
|
18429
|
+
"mousedown",
|
|
18430
|
+
"click",
|
|
18431
|
+
"dblclick",
|
|
18432
|
+
"contextmenu"
|
|
18433
|
+
])
|
|
18434
|
+
root.addEventListener(event, (e) => e.stopPropagation());
|
|
18435
|
+
const title = document.createElement("div");
|
|
18436
|
+
title.textContent = "\u4E0A\u4F20\u9644\u4EF6";
|
|
18437
|
+
title.style.fontWeight = "600";
|
|
18438
|
+
const list = document.createElement("div");
|
|
18439
|
+
Object.assign(list.style, {
|
|
18440
|
+
maxHeight: "180px",
|
|
18441
|
+
overflow: "auto",
|
|
18442
|
+
margin: "10px 0"
|
|
18443
|
+
});
|
|
18444
|
+
const message = document.createElement("div");
|
|
18445
|
+
message.setAttribute("role", "status");
|
|
18446
|
+
message.style.color = "#c53030";
|
|
18447
|
+
const input = document.createElement("input");
|
|
18448
|
+
input.type = "file";
|
|
18449
|
+
input.accept = config.accept ?? "";
|
|
18450
|
+
input.multiple = config.multiple ?? false;
|
|
18451
|
+
input.hidden = true;
|
|
18452
|
+
const actions = document.createElement("div");
|
|
18453
|
+
Object.assign(actions.style, {
|
|
18454
|
+
display: "flex",
|
|
18455
|
+
gap: "8px",
|
|
18456
|
+
marginTop: "10px",
|
|
18457
|
+
flexWrap: "wrap"
|
|
18458
|
+
});
|
|
18459
|
+
const button = (label, callback) => {
|
|
18460
|
+
const element = document.createElement("button");
|
|
18461
|
+
element.type = "button";
|
|
18462
|
+
element.textContent = label;
|
|
18463
|
+
Object.assign(element.style, {
|
|
18464
|
+
padding: "4px 10px",
|
|
18465
|
+
border: "1px solid #cbd5e1",
|
|
18466
|
+
background: "#fff",
|
|
18467
|
+
borderRadius: "4px",
|
|
18468
|
+
cursor: "pointer",
|
|
18469
|
+
color: "inherit"
|
|
18470
|
+
});
|
|
18471
|
+
element.onclick = callback;
|
|
18472
|
+
return element;
|
|
18473
|
+
};
|
|
18474
|
+
const choose = button("\u9009\u62E9\u6587\u4EF6", () => input.click());
|
|
18475
|
+
const done = button("\u5B8C\u6210", () => {
|
|
18476
|
+
if (!pending) params.onCommit();
|
|
18477
|
+
});
|
|
18478
|
+
const cancel = button("\u53D6\u6D88", params.onCancel);
|
|
18479
|
+
actions.append(choose, done, cancel);
|
|
18480
|
+
root.append(title, list, message, input, actions);
|
|
18481
|
+
function render() {
|
|
18482
|
+
if (!alive) return;
|
|
18483
|
+
list.replaceChildren();
|
|
18484
|
+
done.disabled = pending > 0;
|
|
18485
|
+
if (!files.length) list.textContent = "\u6682\u65E0\u9644\u4EF6";
|
|
18486
|
+
for (const file of files) {
|
|
18487
|
+
const row = document.createElement("div");
|
|
18488
|
+
Object.assign(row.style, {
|
|
18489
|
+
display: "flex",
|
|
18490
|
+
alignItems: "center",
|
|
18491
|
+
gap: "8px",
|
|
18492
|
+
padding: "6px 0"
|
|
18493
|
+
});
|
|
18494
|
+
const source = isUploadImage(file) ? uploadImageSource(file) : "";
|
|
18495
|
+
if (source) {
|
|
18496
|
+
const image = document.createElement("img");
|
|
18497
|
+
image.src = source;
|
|
18498
|
+
image.alt = file.name;
|
|
18499
|
+
Object.assign(image.style, {
|
|
18500
|
+
width: "32px",
|
|
18501
|
+
height: "32px",
|
|
18502
|
+
objectFit: "contain"
|
|
18503
|
+
});
|
|
18504
|
+
row.append(image);
|
|
18505
|
+
}
|
|
18506
|
+
const label = document.createElement("span");
|
|
18507
|
+
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"}`;
|
|
18508
|
+
Object.assign(label.style, {
|
|
18509
|
+
flex: "1",
|
|
18510
|
+
minWidth: "0",
|
|
18511
|
+
overflowWrap: "anywhere"
|
|
18512
|
+
});
|
|
18513
|
+
row.append(label);
|
|
18514
|
+
if (canPreviewUploadPdf(file)) {
|
|
18515
|
+
row.append(button("\u9884\u89C8", () => previewUploadPdf(file)));
|
|
18516
|
+
}
|
|
18517
|
+
if (file.status === "error" && file.originFileObj)
|
|
18518
|
+
row.append(button("\u91CD\u8BD5", () => upload(file)));
|
|
18519
|
+
row.append(
|
|
18520
|
+
button("\u79FB\u9664", () => {
|
|
18521
|
+
requests.get(file.uid)?.();
|
|
18522
|
+
files = files.filter((item) => item !== file);
|
|
18523
|
+
render();
|
|
18524
|
+
})
|
|
18525
|
+
);
|
|
18526
|
+
list.append(row);
|
|
18527
|
+
}
|
|
18528
|
+
}
|
|
18529
|
+
function upload(file) {
|
|
18530
|
+
if (!alive || !file.originFileObj || !config.action && !config.customRequest)
|
|
18531
|
+
return;
|
|
18532
|
+
requests.get(file.uid)?.();
|
|
18533
|
+
const raw = file.originFileObj;
|
|
18534
|
+
let active = true;
|
|
18535
|
+
let abort;
|
|
18536
|
+
pending++;
|
|
18537
|
+
file.status = "uploading";
|
|
18538
|
+
file.percent = 0;
|
|
18539
|
+
const finish = () => {
|
|
18540
|
+
active = false;
|
|
18541
|
+
pending--;
|
|
18542
|
+
requests.delete(file.uid);
|
|
18543
|
+
};
|
|
18544
|
+
requests.set(file.uid, () => {
|
|
18545
|
+
if (!active) return;
|
|
18546
|
+
finish();
|
|
18547
|
+
abort?.();
|
|
18548
|
+
});
|
|
18549
|
+
const onError = (error) => {
|
|
18550
|
+
if (!active || !alive) return;
|
|
18551
|
+
finish();
|
|
18552
|
+
file.status = "error";
|
|
18553
|
+
file.error = error.message || "\u4E0A\u4F20\u5931\u8D25";
|
|
18554
|
+
render();
|
|
18555
|
+
};
|
|
18556
|
+
const onSuccess = (response) => {
|
|
18557
|
+
if (!active || !alive) return;
|
|
18558
|
+
try {
|
|
18559
|
+
const url = config.getResponseUrl ? config.getResponseUrl(response, raw) : response && typeof response === "object" && "url" in response && typeof response.url === "string" ? response.url : void 0;
|
|
18560
|
+
file.url = url ?? file.url;
|
|
18561
|
+
file.response = response;
|
|
18562
|
+
file.status = "done";
|
|
18563
|
+
file.percent = 100;
|
|
18564
|
+
finish();
|
|
18565
|
+
render();
|
|
18566
|
+
} catch (error) {
|
|
18567
|
+
onError(error instanceof Error ? error : new Error(String(error)));
|
|
18568
|
+
}
|
|
18569
|
+
};
|
|
18570
|
+
const onProgress = (percent) => {
|
|
18571
|
+
if (alive && active) {
|
|
18572
|
+
file.percent = Math.max(0, Math.min(100, percent));
|
|
18573
|
+
render();
|
|
18574
|
+
}
|
|
18575
|
+
};
|
|
18576
|
+
try {
|
|
18577
|
+
if (config.customRequest) {
|
|
18578
|
+
const handle = config.customRequest({
|
|
18579
|
+
file: raw,
|
|
18580
|
+
onProgress,
|
|
18581
|
+
onSuccess,
|
|
18582
|
+
onError
|
|
18583
|
+
});
|
|
18584
|
+
abort = handle ? () => handle.abort() : void 0;
|
|
18585
|
+
} else {
|
|
18586
|
+
const xhr = new XMLHttpRequest();
|
|
18587
|
+
abort = () => xhr.abort();
|
|
18588
|
+
xhr.open("POST", config.action);
|
|
18589
|
+
xhr.withCredentials = config.withCredentials ?? false;
|
|
18590
|
+
for (const [key, value] of Object.entries(config.headers ?? {}))
|
|
18591
|
+
xhr.setRequestHeader(key, value);
|
|
18592
|
+
xhr.upload.onprogress = (event) => {
|
|
18593
|
+
if (event.lengthComputable)
|
|
18594
|
+
onProgress(event.loaded / event.total * 100);
|
|
18595
|
+
};
|
|
18596
|
+
xhr.onerror = () => onError(new Error("\u7F51\u7EDC\u9519\u8BEF\uFF0C\u4E0A\u4F20\u5931\u8D25"));
|
|
18597
|
+
xhr.onabort = () => onError(new Error("\u4E0A\u4F20\u5DF2\u53D6\u6D88"));
|
|
18598
|
+
xhr.onload = () => {
|
|
18599
|
+
if (xhr.status < 200 || xhr.status >= 300)
|
|
18600
|
+
return onError(new Error(`\u4E0A\u4F20\u5931\u8D25 (${xhr.status})`));
|
|
18601
|
+
let response = xhr.responseText;
|
|
18602
|
+
try {
|
|
18603
|
+
response = JSON.parse(xhr.responseText);
|
|
18604
|
+
} catch {
|
|
18605
|
+
}
|
|
18606
|
+
onSuccess(response);
|
|
18607
|
+
};
|
|
18608
|
+
const body = new FormData();
|
|
18609
|
+
for (const [key, value] of Object.entries(config.data ?? {}))
|
|
18610
|
+
body.append(key, value);
|
|
18611
|
+
body.append(config.name ?? "file", raw);
|
|
18612
|
+
xhr.send(body);
|
|
18613
|
+
}
|
|
18614
|
+
} catch (error) {
|
|
18615
|
+
onError(error instanceof Error ? error : new Error(String(error)));
|
|
18616
|
+
}
|
|
18617
|
+
render();
|
|
18618
|
+
}
|
|
18619
|
+
input.onchange = async () => {
|
|
18620
|
+
const selected = Array.from(input.files ?? []);
|
|
18621
|
+
input.value = "";
|
|
18622
|
+
message.textContent = "";
|
|
18623
|
+
pending++;
|
|
18624
|
+
render();
|
|
18625
|
+
for (const raw of selected) {
|
|
18626
|
+
try {
|
|
18627
|
+
if (config.maxSize && raw.size > config.maxSize)
|
|
18628
|
+
throw new Error(`${raw.name} \u8D85\u8FC7\u6587\u4EF6\u5927\u5C0F\u9650\u5236`);
|
|
18629
|
+
const allowed = await config.beforeUpload?.(raw);
|
|
18630
|
+
if (!alive) break;
|
|
18631
|
+
const max = Math.max(1, config.maxCount ?? Infinity);
|
|
18632
|
+
if (max === 1) {
|
|
18633
|
+
for (const file2 of files) requests.get(file2.uid)?.();
|
|
18634
|
+
files = [];
|
|
18635
|
+
}
|
|
18636
|
+
if (files.length >= max) throw new Error(`\u6700\u591A\u9009\u62E9 ${max} \u4E2A\u6587\u4EF6`);
|
|
18637
|
+
const file = {
|
|
18638
|
+
uid: `upload-${Date.now()}-${++sequence}`,
|
|
18639
|
+
name: raw.name,
|
|
18640
|
+
type: raw.type,
|
|
18641
|
+
size: raw.size,
|
|
18642
|
+
originFileObj: raw,
|
|
18643
|
+
status: "selected"
|
|
18644
|
+
};
|
|
18645
|
+
files.push(file);
|
|
18646
|
+
if (isUploadImage(file)) {
|
|
18647
|
+
const reader = new FileReader();
|
|
18648
|
+
readers.add(reader);
|
|
18649
|
+
pending++;
|
|
18650
|
+
reader.onload = () => {
|
|
18651
|
+
if (alive && files.includes(file)) {
|
|
18652
|
+
file.thumbUrl = String(reader.result);
|
|
18653
|
+
render();
|
|
18654
|
+
}
|
|
18655
|
+
};
|
|
18656
|
+
reader.onloadend = () => {
|
|
18657
|
+
readers.delete(reader);
|
|
18658
|
+
pending--;
|
|
18659
|
+
render();
|
|
18660
|
+
};
|
|
18661
|
+
reader.readAsDataURL(raw);
|
|
18662
|
+
}
|
|
18663
|
+
if (allowed !== false) upload(file);
|
|
18664
|
+
} catch (error) {
|
|
18665
|
+
if (alive)
|
|
18666
|
+
message.textContent = error instanceof Error ? error.message : String(error);
|
|
18667
|
+
}
|
|
18668
|
+
}
|
|
18669
|
+
pending--;
|
|
18670
|
+
render();
|
|
18671
|
+
};
|
|
18672
|
+
root.onkeydown = (event) => {
|
|
18673
|
+
event.stopPropagation();
|
|
18674
|
+
if (event.key === "Escape") {
|
|
18675
|
+
event.preventDefault();
|
|
18676
|
+
params.onCancel();
|
|
18677
|
+
}
|
|
18678
|
+
if (event.key === "Tab") {
|
|
18679
|
+
const items = Array.from(
|
|
18680
|
+
root.querySelectorAll("button:not(:disabled)")
|
|
18681
|
+
);
|
|
18682
|
+
const next = items[(items.indexOf(document.activeElement) + (event.shiftKey ? -1 : 1) + items.length) % items.length];
|
|
18683
|
+
event.preventDefault();
|
|
18684
|
+
next?.focus();
|
|
18685
|
+
}
|
|
18686
|
+
};
|
|
18687
|
+
document.body.append(root);
|
|
18688
|
+
render();
|
|
18689
|
+
return {
|
|
18690
|
+
element: root,
|
|
18691
|
+
focus: () => choose.focus(),
|
|
18692
|
+
getValue: () => files,
|
|
18693
|
+
destroy: () => {
|
|
18694
|
+
alive = false;
|
|
18695
|
+
for (const abort of [...requests.values()]) abort();
|
|
18696
|
+
for (const reader of readers) reader.abort();
|
|
18697
|
+
root.remove();
|
|
18698
|
+
}
|
|
18699
|
+
};
|
|
18700
|
+
}
|
|
18701
|
+
|
|
17180
18702
|
// src/features/editing/editing-feature.ts
|
|
17181
18703
|
var DEFAULT_EDITOR_PADDING_INLINE = 12;
|
|
17182
18704
|
function openCellEditingSession(params) {
|
|
@@ -17228,6 +18750,7 @@ function openCellEditingSession(params) {
|
|
|
17228
18750
|
}
|
|
17229
18751
|
const editorConfig = resolveEditorConfig(editConfig);
|
|
17230
18752
|
const editingValue = initialValue === void 0 ? currentValue : initialValue;
|
|
18753
|
+
const selectOnFocus = !(initialValue !== void 0 && (currentValue == null || currentValue === ""));
|
|
17231
18754
|
const hostRect = toHostRect ? toHostRect(descriptor.rect) : descriptor.rect;
|
|
17232
18755
|
const zoom = typeof theme.contentZoom === "number" && Number.isFinite(theme.contentZoom) && theme.contentZoom > 0 ? theme.contentZoom : 1;
|
|
17233
18756
|
const paddingInline = (column.cellStyle?.paddingInline ?? DEFAULT_EDITOR_PADDING_INLINE) * zoom;
|
|
@@ -17241,10 +18764,26 @@ function openCellEditingSession(params) {
|
|
|
17241
18764
|
paddingBlock,
|
|
17242
18765
|
contentZoom: zoom
|
|
17243
18766
|
};
|
|
18767
|
+
if (editorConfig.valueType === "upload" && typeof document !== "undefined") {
|
|
18768
|
+
const session2 = createUploadEditor({
|
|
18769
|
+
value: editingValue,
|
|
18770
|
+
config: editorConfig.upload,
|
|
18771
|
+
rect: toViewportRect(descriptor.rect),
|
|
18772
|
+
onCommit: () => onCommit(),
|
|
18773
|
+
onCancel
|
|
18774
|
+
});
|
|
18775
|
+
session2.focus();
|
|
18776
|
+
return {
|
|
18777
|
+
...session2,
|
|
18778
|
+
rowIndex,
|
|
18779
|
+
columnKey
|
|
18780
|
+
};
|
|
18781
|
+
}
|
|
17244
18782
|
if (onEditorRequest) {
|
|
17245
18783
|
let nextValue = editingValue;
|
|
17246
18784
|
onEditorRequest({
|
|
17247
18785
|
editorKey: JSON.stringify([rowIndex, columnKey]),
|
|
18786
|
+
selectOnFocus,
|
|
17248
18787
|
rect: toViewportRect(descriptor.rect),
|
|
17249
18788
|
clipRect: getViewportClipRect?.() ?? void 0,
|
|
17250
18789
|
hostRect,
|
|
@@ -17274,6 +18813,7 @@ function openCellEditingSession(params) {
|
|
|
17274
18813
|
return null;
|
|
17275
18814
|
}
|
|
17276
18815
|
const session = editorFactory.createCellEditorSession({
|
|
18816
|
+
selectOnFocus,
|
|
17277
18817
|
rect: toViewportRect(descriptor.rect),
|
|
17278
18818
|
clipRect: getViewportClipRect?.() ?? void 0,
|
|
17279
18819
|
hostRect,
|
|
@@ -17310,7 +18850,13 @@ function resolveEditorConfig(config) {
|
|
|
17310
18850
|
max: config.max,
|
|
17311
18851
|
min: config.min,
|
|
17312
18852
|
options: config.options,
|
|
18853
|
+
treeData: config.treeData,
|
|
18854
|
+
treeDefaultExpandAll: config.treeDefaultExpandAll,
|
|
18855
|
+
treeDefaultExpandedKeys: config.treeDefaultExpandedKeys,
|
|
17313
18856
|
changeOnSelect: config.changeOnSelect,
|
|
18857
|
+
multiple: config.multiple,
|
|
18858
|
+
showCheckedStrategy: config.showCheckedStrategy,
|
|
18859
|
+
upload: config.upload,
|
|
17314
18860
|
expandTrigger: config.expandTrigger,
|
|
17315
18861
|
allowClear: config.allowClear,
|
|
17316
18862
|
displayRender: config.displayRender,
|
|
@@ -17503,6 +19049,7 @@ var ListTableEditingController = class {
|
|
|
17503
19049
|
__publicField(this, "nestedEditingSource", null);
|
|
17504
19050
|
__publicField(this, "validationMessages", /* @__PURE__ */ new Map());
|
|
17505
19051
|
__publicField(this, "validationTaskId", 0);
|
|
19052
|
+
__publicField(this, "editingRequestId", 0);
|
|
17506
19053
|
this.options = options;
|
|
17507
19054
|
}
|
|
17508
19055
|
hasSession() {
|
|
@@ -17514,6 +19061,18 @@ var ListTableEditingController = class {
|
|
|
17514
19061
|
open(rowIndex, columnKey, initialValue) {
|
|
17515
19062
|
this.close(false);
|
|
17516
19063
|
this.options.clearBodyTooltip();
|
|
19064
|
+
const requestId = this.editingRequestId;
|
|
19065
|
+
const openVisibleEditor = () => {
|
|
19066
|
+
if (requestId !== this.editingRequestId) return;
|
|
19067
|
+
this.openVisibleCell(rowIndex, columnKey, initialValue);
|
|
19068
|
+
};
|
|
19069
|
+
if (this.ensureCellVisibleForEditing(rowIndex, columnKey, openVisibleEditor)) {
|
|
19070
|
+
return;
|
|
19071
|
+
}
|
|
19072
|
+
openVisibleEditor();
|
|
19073
|
+
}
|
|
19074
|
+
/** 使用滚动完成后的描述符定位编辑器,避免浏览器移动整个画布宿主。 */
|
|
19075
|
+
openVisibleCell(rowIndex, columnKey, initialValue) {
|
|
17517
19076
|
const zoom = this.options.getTableZoom() > 0 ? this.options.getTableZoom() : 1;
|
|
17518
19077
|
const theme = this.options.getTheme();
|
|
17519
19078
|
const configuredRowHeight = this.options.getOptions().rowHeight;
|
|
@@ -17669,40 +19228,14 @@ var ListTableEditingController = class {
|
|
|
17669
19228
|
void this.validateCellTargets(session.rowIndex, session.columnKey);
|
|
17670
19229
|
this.close(false);
|
|
17671
19230
|
this.options.requestRender();
|
|
17672
|
-
if (
|
|
17673
|
-
if (
|
|
17674
|
-
this.options.focusTable?.();
|
|
17675
|
-
return;
|
|
17676
|
-
}
|
|
17677
|
-
this.options.setSelection?.(nextTarget);
|
|
17678
|
-
const revealTarget = () => {
|
|
17679
|
-
this.options.requestRender();
|
|
19231
|
+
if (!nextTarget) {
|
|
19232
|
+
if (direction === "up" || direction === "down") {
|
|
17680
19233
|
this.options.focusTable?.();
|
|
17681
|
-
};
|
|
17682
|
-
const scrolled2 = this.ensureCellVisibleForEditing(
|
|
17683
|
-
nextTarget.rowIndex,
|
|
17684
|
-
nextTarget.columnKey,
|
|
17685
|
-
revealTarget
|
|
17686
|
-
);
|
|
17687
|
-
if (!scrolled2) {
|
|
17688
|
-
revealTarget();
|
|
17689
19234
|
}
|
|
17690
19235
|
return;
|
|
17691
19236
|
}
|
|
17692
|
-
if (!nextTarget) {
|
|
17693
|
-
return;
|
|
17694
|
-
}
|
|
17695
19237
|
this.options.setSelection?.(nextTarget);
|
|
17696
|
-
|
|
17697
|
-
nextTarget.rowIndex,
|
|
17698
|
-
nextTarget.columnKey,
|
|
17699
|
-
() => {
|
|
17700
|
-
this.open(nextTarget.rowIndex, nextTarget.columnKey);
|
|
17701
|
-
}
|
|
17702
|
-
);
|
|
17703
|
-
if (!scrolled) {
|
|
17704
|
-
this.open(nextTarget.rowIndex, nextTarget.columnKey);
|
|
17705
|
-
}
|
|
19238
|
+
this.open(nextTarget.rowIndex, nextTarget.columnKey);
|
|
17706
19239
|
}
|
|
17707
19240
|
/**
|
|
17708
19241
|
* 确保目标可编辑单元格完整进入视口。
|
|
@@ -17741,11 +19274,15 @@ var ListTableEditingController = class {
|
|
|
17741
19274
|
targetLeft: leftChanged ? nextLeft : scroll.left,
|
|
17742
19275
|
targetTop: topChanged ? nextTop : scroll.top,
|
|
17743
19276
|
duration: 240,
|
|
17744
|
-
onComplete:
|
|
19277
|
+
onComplete: () => {
|
|
19278
|
+
this.options.requestRender();
|
|
19279
|
+
onVisible?.();
|
|
19280
|
+
}
|
|
17745
19281
|
});
|
|
17746
19282
|
return true;
|
|
17747
19283
|
}
|
|
17748
19284
|
close(_keepFocusState = false) {
|
|
19285
|
+
this.editingRequestId++;
|
|
17749
19286
|
this.editingSession = closeCellEditingSession(this.editingSession);
|
|
17750
19287
|
this.editingSource = null;
|
|
17751
19288
|
this.nestedEditingSource = null;
|
|
@@ -24656,41 +26193,50 @@ function createListTableContextMenuActions(params) {
|
|
|
24656
26193
|
onExportJson: () => {
|
|
24657
26194
|
params.hideMenu();
|
|
24658
26195
|
params.startExportTask(
|
|
24659
|
-
() => exportAllRowsJsonContent({
|
|
26196
|
+
(fileName) => exportAllRowsJsonContent({
|
|
26197
|
+
fileName,
|
|
24660
26198
|
rows: params.getAllRows(),
|
|
24661
26199
|
columns: params.getColumns()
|
|
24662
26200
|
}),
|
|
24663
|
-
"\u6B63\u5728\u5BFC\u51FA JSON\u2026"
|
|
26201
|
+
"\u6B63\u5728\u5BFC\u51FA JSON\u2026",
|
|
26202
|
+
buildTableExportFileName("json")
|
|
24664
26203
|
);
|
|
24665
26204
|
},
|
|
24666
26205
|
onExportCsv: () => {
|
|
24667
26206
|
params.hideMenu();
|
|
24668
26207
|
params.startExportTask(
|
|
24669
|
-
() => exportAllRowsCsvContent({
|
|
26208
|
+
(fileName) => exportAllRowsCsvContent({
|
|
26209
|
+
fileName,
|
|
24670
26210
|
rows: params.getAllRows(),
|
|
24671
26211
|
columns: params.getColumns()
|
|
24672
26212
|
}),
|
|
24673
|
-
"\u6B63\u5728\u5BFC\u51FA CSV\u2026"
|
|
26213
|
+
"\u6B63\u5728\u5BFC\u51FA CSV\u2026",
|
|
26214
|
+
buildTableExportFileName("csv")
|
|
24674
26215
|
);
|
|
24675
26216
|
},
|
|
24676
26217
|
onExportTxt: () => {
|
|
24677
26218
|
params.hideMenu();
|
|
24678
26219
|
params.startExportTask(
|
|
24679
|
-
() => exportAllRowsTxtContent({
|
|
26220
|
+
(fileName) => exportAllRowsTxtContent({
|
|
26221
|
+
fileName,
|
|
24680
26222
|
rows: params.getAllRows(),
|
|
24681
26223
|
columns: params.getColumns()
|
|
24682
26224
|
}),
|
|
24683
|
-
"\u6B63\u5728\u5BFC\u51FA TXT\u2026"
|
|
26225
|
+
"\u6B63\u5728\u5BFC\u51FA TXT\u2026",
|
|
26226
|
+
buildTableExportFileName("txt")
|
|
24684
26227
|
);
|
|
24685
26228
|
},
|
|
24686
26229
|
onExportXlsx: () => {
|
|
24687
26230
|
params.hideMenu();
|
|
24688
26231
|
params.startExportTask(
|
|
24689
|
-
() => exportAllRowsXlsxContent({
|
|
26232
|
+
(fileName) => exportAllRowsXlsxContent({
|
|
26233
|
+
includeSummary: params.getExportSummaryEnabled?.() ?? false,
|
|
26234
|
+
fileName,
|
|
24690
26235
|
rows: params.getAllRows(),
|
|
24691
26236
|
columns: params.getColumns()
|
|
24692
26237
|
}),
|
|
24693
|
-
"\u6B63\u5728\u5BFC\u51FA XLSX\u2026"
|
|
26238
|
+
"\u6B63\u5728\u5BFC\u51FA XLSX\u2026",
|
|
26239
|
+
buildTableExportFileName("xlsx")
|
|
24694
26240
|
);
|
|
24695
26241
|
},
|
|
24696
26242
|
onFreezeRow: params.onFreezeRow,
|
|
@@ -25262,6 +26808,7 @@ function showHeaderContextMenu(params) {
|
|
|
25262
26808
|
rowCount: getRows().length,
|
|
25263
26809
|
columnCount: getColumns().length,
|
|
25264
26810
|
actions: createListTableContextMenuActions({
|
|
26811
|
+
getExportSummaryEnabled: params.getExportSummaryEnabled,
|
|
25265
26812
|
getRows,
|
|
25266
26813
|
getAllRows,
|
|
25267
26814
|
getColumns,
|
|
@@ -25372,9 +26919,9 @@ function updateHeaderActionTooltip(params) {
|
|
|
25372
26919
|
tooltip.show(tooltipPoint.x, tooltipPoint.y, text);
|
|
25373
26920
|
}
|
|
25374
26921
|
function showDragTooltip(params) {
|
|
25375
|
-
const { tooltip, toViewportPoint, x, y, text } = params;
|
|
26922
|
+
const { tooltip, toViewportPoint, x, y, text, variant } = params;
|
|
25376
26923
|
const point = toViewportPoint(x, y + 16);
|
|
25377
|
-
tooltip.show(point.x, point.y, text);
|
|
26924
|
+
tooltip.show(point.x, point.y, text, variant);
|
|
25378
26925
|
}
|
|
25379
26926
|
|
|
25380
26927
|
// src/shared/utils/hit-result.ts
|
|
@@ -26827,6 +28374,11 @@ var ListTableEventController = class {
|
|
|
26827
28374
|
event.clientY
|
|
26828
28375
|
);
|
|
26829
28376
|
const result = this.host.resolvePointerHit(position.x, position.y);
|
|
28377
|
+
if (result.area === "resize-handle" && result.columnKey) {
|
|
28378
|
+
event.preventDefault();
|
|
28379
|
+
void this.autoFitColumnWidths(result.columnKey);
|
|
28380
|
+
return;
|
|
28381
|
+
}
|
|
26830
28382
|
if (this.tryOpenNestedTableEditor(result, 2)) {
|
|
26831
28383
|
return;
|
|
26832
28384
|
}
|
|
@@ -26909,6 +28461,7 @@ var ListTableEventController = class {
|
|
|
26909
28461
|
},
|
|
26910
28462
|
getRows: () => this.host.getDisplayData(),
|
|
26911
28463
|
getAllRows: () => this.host.options.dataSource,
|
|
28464
|
+
getExportSummaryEnabled: () => Boolean(this.host.currentRenderSnapshot?.hasSummary),
|
|
26912
28465
|
onCopyImage: (scope) => this.copyImage(scope, event),
|
|
26913
28466
|
onExportImage: (scope) => this.copyImage(scope, event, true),
|
|
26914
28467
|
canCopySelectionImage: resolveImageSelection(this.host) != null,
|
|
@@ -26932,8 +28485,8 @@ var ListTableEventController = class {
|
|
|
26932
28485
|
getColumns: () => this.host.leafColumns,
|
|
26933
28486
|
getHeaderTree: () => this.host.headerTree,
|
|
26934
28487
|
getFrozenRowPosition: (rowIndex) => this.host.getFrozenRowPosition(rowIndex),
|
|
26935
|
-
startExportTask: (task, text) => {
|
|
26936
|
-
this.host.startExportTask(task, text);
|
|
28488
|
+
startExportTask: (task, text, defaultFileName) => {
|
|
28489
|
+
this.host.startExportTask(task, text, defaultFileName);
|
|
26937
28490
|
},
|
|
26938
28491
|
contentDownload: this.host.resolveContentDownloadAction(hitContent),
|
|
26939
28492
|
onSelectHeader: (columnKey, rect) => {
|
|
@@ -27563,7 +29116,8 @@ var ListTableEventController = class {
|
|
|
27563
29116
|
toViewportPoint: (x, y) => this.host.toViewportPoint(x, y),
|
|
27564
29117
|
x: dragPos.x,
|
|
27565
29118
|
y: dragPos.y,
|
|
27566
|
-
text: `${resizeResult.column.title}: ${resizeResult.nextWidth}px
|
|
29119
|
+
text: `${resizeResult.column.title}: ${resizeResult.nextWidth}px`,
|
|
29120
|
+
variant: "resize"
|
|
27567
29121
|
});
|
|
27568
29122
|
}
|
|
27569
29123
|
this.host.scheduleRender();
|
|
@@ -28082,10 +29636,11 @@ var ListTableEventController = class {
|
|
|
28082
29636
|
const actions = createListTableContextMenuActions({
|
|
28083
29637
|
getRows: () => resolveNestedTableDisplayRows(content, getNestedState()),
|
|
28084
29638
|
getAllRows: () => content.dataSource,
|
|
29639
|
+
getExportSummaryEnabled: () => getNestedState()?.summaryVisible === true,
|
|
28085
29640
|
getColumns: () => columns,
|
|
28086
29641
|
getHeaderTree: () => headerTree,
|
|
28087
29642
|
hideMenu,
|
|
28088
|
-
startExportTask: (task, text) => this.host.startExportTask(task, text),
|
|
29643
|
+
startExportTask: (task, text, defaultFileName) => this.host.startExportTask(task, text, defaultFileName),
|
|
28089
29644
|
onFreezeRow: () => {
|
|
28090
29645
|
},
|
|
28091
29646
|
onUnfreezeRow: () => {
|
|
@@ -29477,7 +31032,17 @@ function createListTableEventHost(core) {
|
|
|
29477
31032
|
return snapshot?.columnSegments ?? core.columnSegments;
|
|
29478
31033
|
},
|
|
29479
31034
|
persistColumnConfig: () => core.persistenceController.persistColumnConfig(),
|
|
29480
|
-
startExportTask: (task, text) =>
|
|
31035
|
+
startExportTask: (task, text, defaultFileName) => {
|
|
31036
|
+
const configured = core.options.exportOptions?.fileName?.trim();
|
|
31037
|
+
const extension = defaultFileName?.match(/\.(xlsx|csv|txt|json)$/i)?.[0];
|
|
31038
|
+
const fileName = configured && extension ? configured.replace(/\.(xlsx|csv|txt|json)$/i, "") + extension : defaultFileName;
|
|
31039
|
+
core.contentActionController.startExportTask(
|
|
31040
|
+
task,
|
|
31041
|
+
text,
|
|
31042
|
+
void 0,
|
|
31043
|
+
fileName
|
|
31044
|
+
);
|
|
31045
|
+
},
|
|
29481
31046
|
resolveContentDownloadAction: (content) => core.contentActionController.resolveContentDownloadAction(
|
|
29482
31047
|
content
|
|
29483
31048
|
)
|
|
@@ -33178,6 +34743,7 @@ function assembleListTableCoreControllers(core, options) {
|
|
|
33178
34743
|
requestRender: () => render()
|
|
33179
34744
|
});
|
|
33180
34745
|
core.contentActionController = new ListTableContentActionController({
|
|
34746
|
+
getSummaryVisible: () => Boolean(getCurrentRenderSnapshot()?.hasSummary),
|
|
33181
34747
|
getOptions: () => core.options,
|
|
33182
34748
|
getLeafColumns: () => core.leafColumns,
|
|
33183
34749
|
overlayController: core.overlayController,
|
|
@@ -33939,6 +35505,6 @@ __publicField(ListTable, "SELECTION_COLUMN", SELECTION_COLUMN);
|
|
|
33939
35505
|
/** `SELECTION_COLUMN` 的语义化别名。 */
|
|
33940
35506
|
__publicField(ListTable, "ROW_SELECTION_COLUMN", ROW_SELECTION_COLUMN);
|
|
33941
35507
|
|
|
33942
|
-
export { EXPAND_COLUMN, ListTable, ROW_SELECTION_COLUMN, SELECTION_COLUMN, getListTableStoredPageSize, resetListTableStoredColumnConfig };
|
|
35508
|
+
export { EXPAND_COLUMN, ListTable, ROW_SELECTION_COLUMN, SELECTION_COLUMN, getListTableStoredPageSize, listTableAntdIconNames, listTableBuiltinIconNames, listTableIconNames, resetListTableStoredColumnConfig };
|
|
33943
35509
|
//# sourceMappingURL=index.js.map
|
|
33944
35510
|
//# sourceMappingURL=index.js.map
|