@canvas-components/react-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 +2 -0
- package/dist/index.cjs +663 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +664 -21
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -4,9 +4,9 @@ var react = require('react');
|
|
|
4
4
|
var reactDom = require('react-dom');
|
|
5
5
|
var reactComponents = require('@canvas-components/react-components');
|
|
6
6
|
var listTable = require('@canvas-components/list-table');
|
|
7
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
7
8
|
var date = require('@canvas-components/utils/date');
|
|
8
9
|
var number = require('@canvas-components/utils/number');
|
|
9
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
10
10
|
|
|
11
11
|
// #style-inject:#style-inject
|
|
12
12
|
function styleInject(css, { insertAt } = {}) {
|
|
@@ -32,6 +32,328 @@ function styleInject(css, { insertAt } = {}) {
|
|
|
32
32
|
|
|
33
33
|
// src/styles/table-overrides.css
|
|
34
34
|
styleInject(".react-list-table-filter-option {\n transition: background-color 0.2s ease;\n}\n.react-list-table-filter-option:hover {\n background: #f3f4f6;\n}\n.react-list-table-menu-action,\n.react-list-table-menu-row {\n transition: background-color 0.2s ease, color 0.2s ease;\n}\n.react-list-table-menu-action:hover,\n.react-list-table-menu-row:hover {\n background: #f3f4f6 !important;\n}\n.react-list-table-custom-selection-copy {\n transition: background-color 0.2s ease;\n}\n.react-list-table-custom-selection-copy:hover {\n background: #4096ff !important;\n}\n.react-list-table-custom-selection-input > .canvas-react-input-number-handler-down {\n display: none;\n}\n.react-list-table-menu-chevron {\n width: 7px;\n height: 7px;\n flex: 0 0 auto;\n margin-left: 8px;\n border-top: 1.5px solid #9ca3af;\n border-right: 1.5px solid #9ca3af;\n transform: rotate(45deg);\n transform-origin: center;\n transition: transform 0.18s ease, border-color 0.18s ease;\n}\n.react-list-table-menu-action:hover .react-list-table-menu-chevron,\n.react-list-table-menu-row:hover .react-list-table-menu-chevron {\n border-color: #6b7280;\n transform: rotate(135deg);\n}\n.react-list-table-menu-chevron-active {\n border-color: #6b7280;\n transform: rotate(135deg);\n}\n");
|
|
35
|
+
var conditionalOperators = {
|
|
36
|
+
eq: "\u7B49\u4E8E",
|
|
37
|
+
neq: "\u4E0D\u7B49\u4E8E",
|
|
38
|
+
gt: "\u5927\u4E8E",
|
|
39
|
+
gte: "\u5927\u4E8E\u7B49\u4E8E",
|
|
40
|
+
lt: "\u5C0F\u4E8E",
|
|
41
|
+
lte: "\u5C0F\u4E8E\u7B49\u4E8E",
|
|
42
|
+
between: "\u4ECB\u4E8E\uFF08\u542B\u8FB9\u754C\uFF09",
|
|
43
|
+
contains: "\u5305\u542B\u6587\u672C",
|
|
44
|
+
empty: "\u4E3A\u7A7A",
|
|
45
|
+
notEmpty: "\u4E0D\u4E3A\u7A7A"
|
|
46
|
+
};
|
|
47
|
+
function describeConditionalRule(rule) {
|
|
48
|
+
return resolveConditions(rule).map(
|
|
49
|
+
(condition, index) => `${index === 0 ? "" : (condition.relation ?? rule.conditionRelation ?? "and") === "or" ? " \u6216 " : " \u4E14 "}${conditionalOperators[condition.operator]}${condition.operator === "empty" || condition.operator === "notEmpty" ? "" : ` ${condition.value ?? ""}`}${condition.operator === "between" ? ` \uFF5E ${condition.endValue ?? ""}` : ""}`
|
|
50
|
+
).join("");
|
|
51
|
+
}
|
|
52
|
+
function resolveConditions(rule) {
|
|
53
|
+
return rule.conditions ?? (rule.operator ? [
|
|
54
|
+
{
|
|
55
|
+
operator: rule.operator,
|
|
56
|
+
value: rule.value,
|
|
57
|
+
endValue: rule.endValue
|
|
58
|
+
}
|
|
59
|
+
] : []);
|
|
60
|
+
}
|
|
61
|
+
function validateConditionalRule(rule) {
|
|
62
|
+
const conditions = resolveConditions(rule);
|
|
63
|
+
if (!conditions.length) return "\u8BF7\u81F3\u5C11\u6DFB\u52A0\u4E00\u4E2A\u6761\u4EF6\u3002";
|
|
64
|
+
for (const [index, condition] of conditions.entries()) {
|
|
65
|
+
const error = validateCondition(condition);
|
|
66
|
+
if (error) return `\u6761\u4EF6 ${index + 1}\uFF1A${error}`;
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
function validateCondition(rule) {
|
|
71
|
+
if (rule.operator === "empty" || rule.operator === "notEmpty") return null;
|
|
72
|
+
if (String(rule.value ?? "").trim() === "")
|
|
73
|
+
return "\u8BF7\u8F93\u5165\u6BD4\u8F83\u503C\uFF1B\u7A7A\u503C\u8BF7\u4F7F\u7528\u201C\u4E3A\u7A7A\u201D\u6761\u4EF6\u3002";
|
|
74
|
+
if (["gt", "gte", "lt", "lte", "between"].includes(rule.operator)) {
|
|
75
|
+
if (!Number.isFinite(Number(rule.value))) return "\u8BF7\u8F93\u5165\u6709\u6548\u6570\u503C\u3002";
|
|
76
|
+
if (rule.operator === "between" && (String(rule.endValue ?? "").trim() === "" || !Number.isFinite(Number(rule.endValue)) || Number(rule.endValue) < Number(rule.value)))
|
|
77
|
+
return "\u8BF7\u8F93\u5165\u4E0D\u5C0F\u4E8E\u8D77\u59CB\u503C\u7684\u7ED3\u675F\u6570\u503C\u3002";
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
function ConditionalFormatDialog(props) {
|
|
82
|
+
const rules = props.request.conditionalFormats ?? [];
|
|
83
|
+
const [rule, setRule] = react.useState(
|
|
84
|
+
() => props.index == null ? {
|
|
85
|
+
id: `rule-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
86
|
+
operator: "gt",
|
|
87
|
+
value: "",
|
|
88
|
+
backgroundColor: "#fff1b8",
|
|
89
|
+
textColor: "#1f2329"
|
|
90
|
+
} : { ...rules[props.index] }
|
|
91
|
+
);
|
|
92
|
+
const [error, setError] = react.useState(null);
|
|
93
|
+
const conditions = resolveConditions(rule);
|
|
94
|
+
const patch = (value) => {
|
|
95
|
+
setRule((current) => ({ ...current, ...value }));
|
|
96
|
+
setError(null);
|
|
97
|
+
};
|
|
98
|
+
const apply = (next) => {
|
|
99
|
+
props.request.onChangeConditionalFormats?.(next);
|
|
100
|
+
props.onClose();
|
|
101
|
+
};
|
|
102
|
+
const patchCondition = (index, value) => {
|
|
103
|
+
patch({
|
|
104
|
+
conditions: conditions.map(
|
|
105
|
+
(condition, i) => i === index ? { ...condition, ...value } : condition
|
|
106
|
+
)
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
110
|
+
reactComponents.ReactModal,
|
|
111
|
+
{
|
|
112
|
+
open: true,
|
|
113
|
+
title: props.index == null ? "\u65B0\u589E\u6761\u4EF6\u683C\u5F0F\u89C4\u5219" : "\u7F16\u8F91\u6761\u4EF6\u683C\u5F0F\u89C4\u5219",
|
|
114
|
+
width: 460,
|
|
115
|
+
onCancel: props.onClose,
|
|
116
|
+
onOk: () => {
|
|
117
|
+
const message = validateConditionalRule(rule);
|
|
118
|
+
if (message) {
|
|
119
|
+
setError(message);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const next = rules.map((item) => ({ ...item }));
|
|
123
|
+
if (props.index == null) next.push(rule);
|
|
124
|
+
else next[props.index] = rule;
|
|
125
|
+
apply(next);
|
|
126
|
+
},
|
|
127
|
+
okText: "\u4FDD\u5B58\u89C4\u5219",
|
|
128
|
+
cancelText: "\u53D6\u6D88",
|
|
129
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "grid", gap: 14, fontSize: 14 }, children: [
|
|
130
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#64748b" }, children: "\u4EC5\u5F53\u524D\u5217\u751F\u6548\uFF1B\u4ECE\u4E0A\u5230\u4E0B\u5339\u914D\uFF0C\u9996\u6761\u547D\u4E2D\u7684\u80CC\u666F\u751F\u6548\u3002 \u6761\u4EF6\u4E4B\u95F4\u53EF\u5206\u522B\u8BBE\u7F6E\u201C\u4E14 / \u6216\u201D\uFF0C\u4E14\u4F18\u5148\u4E8E\u6216\u3002" }),
|
|
131
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
132
|
+
"\u89C4\u5219\u540D\u79F0\uFF08\u53EF\u9009\uFF09",
|
|
133
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
134
|
+
reactComponents.ReactInput,
|
|
135
|
+
{
|
|
136
|
+
value: rule.name ?? "",
|
|
137
|
+
onChange: (event) => patch({ name: event.target.value })
|
|
138
|
+
}
|
|
139
|
+
)
|
|
140
|
+
] }),
|
|
141
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
142
|
+
"div",
|
|
143
|
+
{
|
|
144
|
+
style: {
|
|
145
|
+
display: "grid",
|
|
146
|
+
gap: 12,
|
|
147
|
+
maxHeight: "35vh",
|
|
148
|
+
overflowY: "auto"
|
|
149
|
+
},
|
|
150
|
+
children: conditions.map((condition, index) => /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
|
|
151
|
+
index > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
152
|
+
reactComponents.ReactSelect,
|
|
153
|
+
{
|
|
154
|
+
"aria-label": `\u6761\u4EF6 ${index} \u4E0E\u6761\u4EF6 ${index + 1} \u7684\u5173\u7CFB`,
|
|
155
|
+
value: condition.relation ?? rule.conditionRelation ?? "and",
|
|
156
|
+
options: [
|
|
157
|
+
{ value: "and", label: "\u4E14" },
|
|
158
|
+
{ value: "or", label: "\u6216" }
|
|
159
|
+
],
|
|
160
|
+
onChange: (value) => patchCondition(index, { relation: value }),
|
|
161
|
+
style: { width: 88, justifySelf: "center" }
|
|
162
|
+
}
|
|
163
|
+
),
|
|
164
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
165
|
+
"div",
|
|
166
|
+
{
|
|
167
|
+
style: {
|
|
168
|
+
display: "grid",
|
|
169
|
+
gap: 8,
|
|
170
|
+
padding: 12,
|
|
171
|
+
border: "1px solid #d9e1ec"
|
|
172
|
+
},
|
|
173
|
+
children: [
|
|
174
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
175
|
+
"div",
|
|
176
|
+
{
|
|
177
|
+
style: {
|
|
178
|
+
display: "flex",
|
|
179
|
+
justifyContent: "space-between",
|
|
180
|
+
alignItems: "center"
|
|
181
|
+
},
|
|
182
|
+
children: [
|
|
183
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
184
|
+
"\u6761\u4EF6 ",
|
|
185
|
+
index + 1
|
|
186
|
+
] }),
|
|
187
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
188
|
+
reactComponents.ReactButton,
|
|
189
|
+
{
|
|
190
|
+
type: "text",
|
|
191
|
+
size: "small",
|
|
192
|
+
disabled: conditions.length === 1,
|
|
193
|
+
"aria-label": `\u5220\u9664\u6761\u4EF6 ${index + 1}`,
|
|
194
|
+
onClick: () => patch({
|
|
195
|
+
conditions: conditions.filter((_, i) => i !== index)
|
|
196
|
+
}),
|
|
197
|
+
children: "\u5220\u9664\u6761\u4EF6"
|
|
198
|
+
}
|
|
199
|
+
)
|
|
200
|
+
]
|
|
201
|
+
}
|
|
202
|
+
),
|
|
203
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
204
|
+
reactComponents.ReactSelect,
|
|
205
|
+
{
|
|
206
|
+
"aria-label": `\u6761\u4EF6 ${index + 1} \u6BD4\u8F83\u65B9\u5F0F`,
|
|
207
|
+
value: condition.operator,
|
|
208
|
+
options: Object.entries(conditionalOperators).map(
|
|
209
|
+
([value, label]) => ({ value, label })
|
|
210
|
+
),
|
|
211
|
+
onChange: (value) => patchCondition(index, {
|
|
212
|
+
operator: value
|
|
213
|
+
})
|
|
214
|
+
}
|
|
215
|
+
),
|
|
216
|
+
condition.operator !== "empty" && condition.operator !== "notEmpty" && /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
217
|
+
"\u6BD4\u8F83\u503C",
|
|
218
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
219
|
+
reactComponents.ReactInput,
|
|
220
|
+
{
|
|
221
|
+
value: String(condition.value ?? ""),
|
|
222
|
+
onChange: (event) => patchCondition(index, { value: event.target.value })
|
|
223
|
+
}
|
|
224
|
+
)
|
|
225
|
+
] }),
|
|
226
|
+
condition.operator === "between" && /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
227
|
+
"\u7ED3\u675F\u503C",
|
|
228
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
229
|
+
reactComponents.ReactInput,
|
|
230
|
+
{
|
|
231
|
+
value: String(condition.endValue ?? ""),
|
|
232
|
+
onChange: (event) => patchCondition(index, { endValue: event.target.value })
|
|
233
|
+
}
|
|
234
|
+
)
|
|
235
|
+
] })
|
|
236
|
+
]
|
|
237
|
+
}
|
|
238
|
+
)
|
|
239
|
+
] }, index))
|
|
240
|
+
}
|
|
241
|
+
),
|
|
242
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
243
|
+
reactComponents.ReactButton,
|
|
244
|
+
{
|
|
245
|
+
onClick: () => patch({
|
|
246
|
+
conditions: [
|
|
247
|
+
...conditions,
|
|
248
|
+
{ operator: "gt", value: "", relation: "and" }
|
|
249
|
+
]
|
|
250
|
+
}),
|
|
251
|
+
children: "\u65B0\u589E\u6761\u4EF6"
|
|
252
|
+
}
|
|
253
|
+
),
|
|
254
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { style: { display: "grid", gap: 4 }, children: [
|
|
255
|
+
"\u5355\u5143\u683C\u80CC\u666F",
|
|
256
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
257
|
+
reactComponents.ReactColorPicker,
|
|
258
|
+
{
|
|
259
|
+
"aria-label": "\u5355\u5143\u683C\u80CC\u666F",
|
|
260
|
+
value: rule.backgroundColor,
|
|
261
|
+
onChange: (backgroundColor) => patch({ backgroundColor })
|
|
262
|
+
}
|
|
263
|
+
)
|
|
264
|
+
] }),
|
|
265
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { style: { display: "grid", gap: 4 }, children: [
|
|
266
|
+
"\u6587\u672C\u989C\u8272",
|
|
267
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
268
|
+
reactComponents.ReactColorPicker,
|
|
269
|
+
{
|
|
270
|
+
"aria-label": "\u6587\u672C\u989C\u8272",
|
|
271
|
+
value: rule.textColor,
|
|
272
|
+
onChange: (textColor) => patch({ textColor })
|
|
273
|
+
}
|
|
274
|
+
)
|
|
275
|
+
] }),
|
|
276
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
277
|
+
"div",
|
|
278
|
+
{
|
|
279
|
+
style: {
|
|
280
|
+
padding: "8px 12px",
|
|
281
|
+
backgroundColor: rule.backgroundColor,
|
|
282
|
+
color: rule.textColor,
|
|
283
|
+
border: "1px solid #d9e1ec"
|
|
284
|
+
},
|
|
285
|
+
children: [
|
|
286
|
+
"\u6837\u5F0F\u9884\u89C8\uFF1A",
|
|
287
|
+
describeConditionalRule(rule)
|
|
288
|
+
]
|
|
289
|
+
}
|
|
290
|
+
),
|
|
291
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("div", { role: "alert", style: { color: "#cf1322" }, children: error }),
|
|
292
|
+
props.index != null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
293
|
+
reactComponents.ReactButton,
|
|
294
|
+
{
|
|
295
|
+
type: "text",
|
|
296
|
+
danger: true,
|
|
297
|
+
onClick: () => apply(rules.filter((_, index) => index !== props.index)),
|
|
298
|
+
children: "\u5220\u9664\u6B64\u89C4\u5219"
|
|
299
|
+
}
|
|
300
|
+
)
|
|
301
|
+
] })
|
|
302
|
+
}
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// src/features/context-menu/cache-menu.ts
|
|
307
|
+
function buildCacheMenuItems(request) {
|
|
308
|
+
const available = request.columnSettingsCacheAvailable === true;
|
|
309
|
+
const items = [];
|
|
310
|
+
const state = {
|
|
311
|
+
disabled: !available,
|
|
312
|
+
title: available ? void 0 : "\u914D\u7F6E storageKey \u540E\u53EF\u7F13\u5B58\u914D\u7F6E"
|
|
313
|
+
};
|
|
314
|
+
if (request.onChangeColumnSettingsCache)
|
|
315
|
+
items.push({
|
|
316
|
+
...state,
|
|
317
|
+
key: "cache-columns",
|
|
318
|
+
label: "\u5217\u8BBE\u7F6E",
|
|
319
|
+
selected: available && request.cacheColumnSettings === true,
|
|
320
|
+
onClick: () => request.onChangeColumnSettingsCache?.(!request.cacheColumnSettings)
|
|
321
|
+
});
|
|
322
|
+
if (request.onChangeCachePreference) {
|
|
323
|
+
const categories = [
|
|
324
|
+
["sort", "\u6392\u5E8F"],
|
|
325
|
+
["filter", "\u7B5B\u9009"],
|
|
326
|
+
["summary", "\u6C47\u603B"],
|
|
327
|
+
["alignment", "\u5BF9\u9F50"],
|
|
328
|
+
["dataFormat", "\u683C\u5F0F"],
|
|
329
|
+
["density", "\u8868\u683C\u5BC6\u5EA6"],
|
|
330
|
+
["zoom", "\u7F29\u653E"]
|
|
331
|
+
];
|
|
332
|
+
for (const [category, label] of categories)
|
|
333
|
+
items.push({
|
|
334
|
+
...state,
|
|
335
|
+
key: `cache-${category}`,
|
|
336
|
+
label,
|
|
337
|
+
selected: available && request.cachePreferences?.[category] !== false,
|
|
338
|
+
onClick: () => request.onChangeCachePreference?.(
|
|
339
|
+
category,
|
|
340
|
+
request.cachePreferences?.[category] === false
|
|
341
|
+
)
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
if (request.onChangeConditionalFormats)
|
|
345
|
+
items.push({
|
|
346
|
+
...state,
|
|
347
|
+
key: "cache-conditional",
|
|
348
|
+
label: "\u5F53\u524D\u5217\u6761\u4EF6\u683C\u5F0F",
|
|
349
|
+
selected: available && request.cacheConditionalFormats !== false,
|
|
350
|
+
onClick: () => request.onChangeConditionalFormats?.(
|
|
351
|
+
request.conditionalFormats ?? [],
|
|
352
|
+
request.cacheConditionalFormats === false
|
|
353
|
+
)
|
|
354
|
+
});
|
|
355
|
+
return items;
|
|
356
|
+
}
|
|
35
357
|
var CONTEXT_MENU_SURFACE_STYLE = {
|
|
36
358
|
padding: 8,
|
|
37
359
|
background: "#ffffff",
|
|
@@ -40,10 +362,22 @@ var CONTEXT_MENU_SURFACE_STYLE = {
|
|
|
40
362
|
function ReactTableContextMenuView(props) {
|
|
41
363
|
const { request } = props;
|
|
42
364
|
const [menuOpen, setMenuOpen] = react.useState(true);
|
|
365
|
+
const [conditionalEditor, setConditionalEditor] = react.useState(null);
|
|
366
|
+
const conditionalDialog = conditionalEditor ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
367
|
+
ConditionalFormatDialog,
|
|
368
|
+
{
|
|
369
|
+
...conditionalEditor,
|
|
370
|
+
onClose: () => {
|
|
371
|
+
setConditionalEditor(null);
|
|
372
|
+
conditionalEditor.request.onClose();
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
) : null;
|
|
43
376
|
const [moreFormatRequest, setMoreFormatRequest] = react.useState(null);
|
|
44
377
|
const [customSelectionRequest, setCustomSelectionRequest] = react.useState(null);
|
|
45
378
|
if (!request) {
|
|
46
379
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
380
|
+
conditionalDialog,
|
|
47
381
|
moreFormatRequest ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
48
382
|
MoreFormatDialog,
|
|
49
383
|
{
|
|
@@ -68,6 +402,7 @@ function ReactTableContextMenuView(props) {
|
|
|
68
402
|
width: 260
|
|
69
403
|
};
|
|
70
404
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
405
|
+
conditionalDialog,
|
|
71
406
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
72
407
|
reactComponents.ReactPopup,
|
|
73
408
|
{
|
|
@@ -77,7 +412,7 @@ function ReactTableContextMenuView(props) {
|
|
|
77
412
|
minWidth: 260,
|
|
78
413
|
onOpenChange: (open) => {
|
|
79
414
|
setMenuOpen(open);
|
|
80
|
-
if (!open && !moreFormatRequest && !customSelectionRequest) {
|
|
415
|
+
if (!open && !moreFormatRequest && !customSelectionRequest && !conditionalEditor) {
|
|
81
416
|
request.onClose();
|
|
82
417
|
}
|
|
83
418
|
},
|
|
@@ -112,7 +447,28 @@ function ReactTableContextMenuView(props) {
|
|
|
112
447
|
key: "copy-selection",
|
|
113
448
|
label: "\u590D\u5236\u9009\u533A",
|
|
114
449
|
onClick: request.onCopySelection
|
|
115
|
-
}
|
|
450
|
+
},
|
|
451
|
+
...request.onCopyImage ? [
|
|
452
|
+
{
|
|
453
|
+
key: "copy-image-all",
|
|
454
|
+
label: "\u590D\u5236\u4E3A\u56FE\u7247 \xB7 \u6240\u6709\u533A\u57DF",
|
|
455
|
+
separatorBefore: true,
|
|
456
|
+
title: "\u5F53\u524D\u5DF2\u52A0\u8F7D\u5E76\u7ECF\u8FC7\u6392\u5E8F\u8FC7\u6EE4\u7684\u5168\u90E8\u6570\u636E\uFF0C\u4E0D\u8BF7\u6C42\u672A\u52A0\u8F7D\u7684\u670D\u52A1\u7AEF\u6570\u636E",
|
|
457
|
+
onClick: () => request.onCopyImage?.("all")
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
key: "copy-image-selection",
|
|
461
|
+
label: "\u590D\u5236\u4E3A\u56FE\u7247 \xB7 \u9009\u4E2D\u533A\u57DF",
|
|
462
|
+
disabled: !request.canCopySelectionImage,
|
|
463
|
+
onClick: () => request.onCopyImage?.("selection")
|
|
464
|
+
},
|
|
465
|
+
{
|
|
466
|
+
key: "copy-image-viewport",
|
|
467
|
+
label: "\u590D\u5236\u4E3A\u56FE\u7247 \xB7 \u89C6\u53E3\u533A\u57DF",
|
|
468
|
+
title: "\u5F53\u524D\u53EF\u89C1\u8868\u683C\uFF0C\u5305\u542B\u8868\u5934\u548C\u6C47\u603B\u884C\uFF0C\u4E0D\u5305\u542B\u5206\u9875\u5668\u548C\u83DC\u5355",
|
|
469
|
+
onClick: () => request.onCopyImage?.("viewport")
|
|
470
|
+
}
|
|
471
|
+
] : []
|
|
116
472
|
],
|
|
117
473
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
118
474
|
CustomSelectionMenu,
|
|
@@ -151,7 +507,26 @@ function ReactTableContextMenuView(props) {
|
|
|
151
507
|
key: "export-json",
|
|
152
508
|
label: "\u5BFC\u51FA JSON",
|
|
153
509
|
onClick: request.onExportJson
|
|
154
|
-
}
|
|
510
|
+
},
|
|
511
|
+
...request.onExportImage ? [
|
|
512
|
+
{
|
|
513
|
+
key: "export-image-all",
|
|
514
|
+
label: "\u5BFC\u51FA\u56FE\u7247 \xB7 \u6240\u6709\u533A\u57DF",
|
|
515
|
+
separatorBefore: true,
|
|
516
|
+
onClick: () => request.onExportImage?.("all")
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
key: "export-image-selection",
|
|
520
|
+
label: "\u5BFC\u51FA\u56FE\u7247 \xB7 \u9009\u4E2D\u533A\u57DF",
|
|
521
|
+
disabled: !request.canCopySelectionImage,
|
|
522
|
+
onClick: () => request.onExportImage?.("selection")
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
key: "export-image-viewport",
|
|
526
|
+
label: "\u5BFC\u51FA\u56FE\u7247 \xB7 \u89C6\u53E3\u533A\u57DF",
|
|
527
|
+
onClick: () => request.onExportImage?.("viewport")
|
|
528
|
+
}
|
|
529
|
+
] : []
|
|
155
530
|
]
|
|
156
531
|
}
|
|
157
532
|
),
|
|
@@ -224,6 +599,41 @@ function ReactTableContextMenuView(props) {
|
|
|
224
599
|
),
|
|
225
600
|
/* @__PURE__ */ jsxRuntime.jsx(SummaryMenu, { request }),
|
|
226
601
|
/* @__PURE__ */ jsxRuntime.jsx(AlignmentMenu, { request }),
|
|
602
|
+
request.onChangeConditionalFormats && /* @__PURE__ */ jsxRuntime.jsx(
|
|
603
|
+
MenuSubmenu,
|
|
604
|
+
{
|
|
605
|
+
label: "\u6761\u4EF6\u683C\u5F0F",
|
|
606
|
+
items: [
|
|
607
|
+
{
|
|
608
|
+
key: "add-rule",
|
|
609
|
+
label: "\u65B0\u589E\u89C4\u5219",
|
|
610
|
+
onClick: () => {
|
|
611
|
+
setConditionalEditor({ request, index: null });
|
|
612
|
+
setMenuOpen(false);
|
|
613
|
+
}
|
|
614
|
+
},
|
|
615
|
+
{
|
|
616
|
+
key: "reset-rules",
|
|
617
|
+
label: "\u91CD\u7F6E\u6761\u4EF6\u683C\u5F0F",
|
|
618
|
+
disabled: !request.conditionalFormats?.length,
|
|
619
|
+
onClick: () => request.onChangeConditionalFormats?.([])
|
|
620
|
+
}
|
|
621
|
+
],
|
|
622
|
+
header: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "grid", gap: 4, paddingBottom: 8 }, children: request.conditionalFormats?.length ? request.conditionalFormats.map((rule, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
623
|
+
MenuAction,
|
|
624
|
+
{
|
|
625
|
+
label: rule.name?.trim() || `\u89C4\u5219 ${index + 1}`,
|
|
626
|
+
colorSwatch: rule.backgroundColor,
|
|
627
|
+
title: `${rule.name?.trim() || `\u89C4\u5219 ${index + 1}`}\uFF1A${describeConditionalRule(rule)}`,
|
|
628
|
+
onClick: () => {
|
|
629
|
+
setConditionalEditor({ request, index });
|
|
630
|
+
setMenuOpen(false);
|
|
631
|
+
}
|
|
632
|
+
},
|
|
633
|
+
rule.id
|
|
634
|
+
)) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#64748b", padding: 8 }, children: "\u6682\u65E0\u89C4\u5219" }) })
|
|
635
|
+
}
|
|
636
|
+
),
|
|
227
637
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
228
638
|
DataFormatMenu,
|
|
229
639
|
{
|
|
@@ -354,6 +764,13 @@ function ReactTableContextMenuView(props) {
|
|
|
354
764
|
}
|
|
355
765
|
),
|
|
356
766
|
/* @__PURE__ */ jsxRuntime.jsx(ZoomMenu, { value: request.zoom ?? 1, onChange: request.onChangeZoom }),
|
|
767
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
768
|
+
MenuSubmenu,
|
|
769
|
+
{
|
|
770
|
+
label: "\u7F13\u5B58\u5230\u672C\u5730",
|
|
771
|
+
items: buildCacheMenuItems(request)
|
|
772
|
+
}
|
|
773
|
+
),
|
|
357
774
|
request.columns?.length && request.onToggleColumn ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
358
775
|
/* @__PURE__ */ jsxRuntime.jsx(MenuDivider, {}),
|
|
359
776
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -400,6 +817,7 @@ function MenuAction(props) {
|
|
|
400
817
|
type: "button",
|
|
401
818
|
onClick: disabled ? void 0 : onClick,
|
|
402
819
|
disabled,
|
|
820
|
+
title: props.title,
|
|
403
821
|
className: "react-list-table-menu-action",
|
|
404
822
|
style: {
|
|
405
823
|
display: "flex",
|
|
@@ -428,7 +846,36 @@ function MenuAction(props) {
|
|
|
428
846
|
children: selected ? "\u2713" : ""
|
|
429
847
|
}
|
|
430
848
|
) : null,
|
|
431
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
849
|
+
props.colorSwatch ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
850
|
+
"span",
|
|
851
|
+
{
|
|
852
|
+
"aria-hidden": "true",
|
|
853
|
+
style: {
|
|
854
|
+
width: 14,
|
|
855
|
+
height: 14,
|
|
856
|
+
flex: "0 0 14px",
|
|
857
|
+
marginRight: 8,
|
|
858
|
+
borderRadius: 2,
|
|
859
|
+
backgroundColor: props.colorSwatch,
|
|
860
|
+
boxShadow: "inset 0 0 0 1px rgba(0, 0, 0, 0.12)"
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
) : null,
|
|
864
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
865
|
+
"span",
|
|
866
|
+
{
|
|
867
|
+
style: {
|
|
868
|
+
flex: 1,
|
|
869
|
+
whiteSpace: "nowrap",
|
|
870
|
+
...props.colorSwatch ? {
|
|
871
|
+
minWidth: 0,
|
|
872
|
+
overflow: "hidden",
|
|
873
|
+
textOverflow: "ellipsis"
|
|
874
|
+
} : null
|
|
875
|
+
},
|
|
876
|
+
children: label
|
|
877
|
+
}
|
|
878
|
+
),
|
|
432
879
|
preview ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
433
880
|
"span",
|
|
434
881
|
{
|
|
@@ -539,6 +986,7 @@ function MenuSubmenu(props) {
|
|
|
539
986
|
MenuAction,
|
|
540
987
|
{
|
|
541
988
|
label: item.label,
|
|
989
|
+
title: item.title,
|
|
542
990
|
preview: item.preview,
|
|
543
991
|
onClick: item.onClick,
|
|
544
992
|
selected: item.selected,
|
|
@@ -1028,13 +1476,7 @@ function CustomSelectionMenu(props) {
|
|
|
1028
1476
|
if (!request.onCopyCustomSelection || !request.customSelection) {
|
|
1029
1477
|
return null;
|
|
1030
1478
|
}
|
|
1031
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1032
|
-
MenuAction,
|
|
1033
|
-
{
|
|
1034
|
-
label: "\u590D\u5236\u81EA\u5B9A\u4E49\u9009\u533A",
|
|
1035
|
-
onClick: props.onOpen
|
|
1036
|
-
}
|
|
1037
|
-
);
|
|
1479
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MenuAction, { label: "\u590D\u5236\u81EA\u5B9A\u4E49\u9009\u533A", onClick: props.onOpen });
|
|
1038
1480
|
}
|
|
1039
1481
|
function CustomSelectionDialog(props) {
|
|
1040
1482
|
const { request } = props;
|
|
@@ -1247,6 +1689,16 @@ function SummaryMenu(props) {
|
|
|
1247
1689
|
selected: request.summaryType === item.value,
|
|
1248
1690
|
onClick: () => request.onChangeSummaryType?.(item.value)
|
|
1249
1691
|
})),
|
|
1692
|
+
{
|
|
1693
|
+
key: "show-summary-type-prefix",
|
|
1694
|
+
label: "\u5C55\u793A\u6C47\u603B\u65B9\u5F0F\u524D\u7F00",
|
|
1695
|
+
separatorBefore: true,
|
|
1696
|
+
selected: request.summaryShowTypePrefix !== false,
|
|
1697
|
+
disabled: !request.summaryType,
|
|
1698
|
+
onClick: request.onChangeSummaryShowTypePrefix ? () => request.onChangeSummaryShowTypePrefix?.(
|
|
1699
|
+
request.summaryShowTypePrefix === false
|
|
1700
|
+
) : void 0
|
|
1701
|
+
},
|
|
1250
1702
|
{
|
|
1251
1703
|
key: "clear-summary",
|
|
1252
1704
|
label: "\u53D6\u6D88\u6C47\u603B",
|
|
@@ -2228,6 +2680,58 @@ var toolButtonStyle = {
|
|
|
2228
2680
|
lineHeight: 1,
|
|
2229
2681
|
cursor: "pointer"
|
|
2230
2682
|
};
|
|
2683
|
+
function ReactListTableExportNameDialog({
|
|
2684
|
+
request
|
|
2685
|
+
}) {
|
|
2686
|
+
const extension = request.fileName.match(/\.(xlsx|csv|txt|json)$/i)?.[0] ?? "";
|
|
2687
|
+
const [fileName, setFileName] = react.useState(
|
|
2688
|
+
extension ? request.fileName.slice(0, -extension.length) : request.fileName
|
|
2689
|
+
);
|
|
2690
|
+
const [invalid, setInvalid] = react.useState(false);
|
|
2691
|
+
const confirm = () => {
|
|
2692
|
+
if (!fileName.trim()) {
|
|
2693
|
+
setInvalid(true);
|
|
2694
|
+
return;
|
|
2695
|
+
}
|
|
2696
|
+
request.onConfirm(`${fileName.trim()}${extension}`);
|
|
2697
|
+
};
|
|
2698
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2699
|
+
reactComponents.ReactModal,
|
|
2700
|
+
{
|
|
2701
|
+
open: true,
|
|
2702
|
+
title: "\u5BFC\u51FA\u6587\u4EF6",
|
|
2703
|
+
width: 420,
|
|
2704
|
+
fullscreenable: false,
|
|
2705
|
+
onCancel: request.onCancel,
|
|
2706
|
+
onOk: confirm,
|
|
2707
|
+
okText: "\u5BFC\u51FA",
|
|
2708
|
+
cancelText: "\u53D6\u6D88",
|
|
2709
|
+
children: [
|
|
2710
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
2711
|
+
"\u6587\u4EF6\u540D\u79F0",
|
|
2712
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
2713
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2714
|
+
reactComponents.ReactInput,
|
|
2715
|
+
{
|
|
2716
|
+
autoFocus: true,
|
|
2717
|
+
value: fileName,
|
|
2718
|
+
placeholder: "\u8BF7\u8F93\u5165\u6587\u4EF6\u540D\u79F0",
|
|
2719
|
+
onFocus: (event) => event.target.select(),
|
|
2720
|
+
onChange: (event) => {
|
|
2721
|
+
setFileName(event.target.value);
|
|
2722
|
+
setInvalid(false);
|
|
2723
|
+
},
|
|
2724
|
+
onPressEnter: confirm
|
|
2725
|
+
}
|
|
2726
|
+
),
|
|
2727
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-label": "\u6587\u4EF6\u540E\u7F00", style: { flexShrink: 0 }, children: extension })
|
|
2728
|
+
] })
|
|
2729
|
+
] }),
|
|
2730
|
+
invalid ? /* @__PURE__ */ jsxRuntime.jsx("div", { role: "alert", style: { color: "#ff4d4f", marginTop: 8 }, children: "\u8BF7\u8F93\u5165\u6587\u4EF6\u540D\u79F0" }) : null
|
|
2731
|
+
]
|
|
2732
|
+
}
|
|
2733
|
+
);
|
|
2734
|
+
}
|
|
2231
2735
|
|
|
2232
2736
|
// src/features/editor/utils.ts
|
|
2233
2737
|
function toNumberValue(value) {
|
|
@@ -2329,12 +2833,16 @@ function ReactTableEditorOverlay(props) {
|
|
|
2329
2833
|
if (!input) {
|
|
2330
2834
|
return;
|
|
2331
2835
|
}
|
|
2332
|
-
focusAndSelectEditorInput(input);
|
|
2836
|
+
focusAndSelectEditorInput(input, request.selectOnFocus);
|
|
2333
2837
|
}, [request]);
|
|
2334
2838
|
return /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactContentScaleProvider, { scale: contentZoom, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: editorHostRef, children: renderEditorByType(request, style) }, request.editorKey) });
|
|
2335
2839
|
}
|
|
2336
2840
|
function renderEditorByType(request, style) {
|
|
2337
2841
|
switch (request.config.valueType ?? "text") {
|
|
2842
|
+
case "tree-select":
|
|
2843
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TreeSelectEditor, { request, style });
|
|
2844
|
+
case "cascader":
|
|
2845
|
+
return /* @__PURE__ */ jsxRuntime.jsx(CascaderEditor, { request, style });
|
|
2338
2846
|
case "number":
|
|
2339
2847
|
return /* @__PURE__ */ jsxRuntime.jsx(NumberEditor, { request, style });
|
|
2340
2848
|
case "input-range":
|
|
@@ -2374,7 +2882,7 @@ function TextEditor(props) {
|
|
|
2374
2882
|
const skipBlurCommitRef = react.useRef(false);
|
|
2375
2883
|
react.useLayoutEffect(() => {
|
|
2376
2884
|
const input = hostRef.current?.querySelector("input");
|
|
2377
|
-
focusAndSelectEditorInput(input);
|
|
2885
|
+
focusAndSelectEditorInput(input, request.selectOnFocus);
|
|
2378
2886
|
}, [request]);
|
|
2379
2887
|
react.useEffect(() => {
|
|
2380
2888
|
setValue(String(request.value ?? ""));
|
|
@@ -2414,7 +2922,7 @@ function NumberEditor(props) {
|
|
|
2414
2922
|
const skipBlurCommitRef = react.useRef(false);
|
|
2415
2923
|
react.useLayoutEffect(() => {
|
|
2416
2924
|
const input = hostRef.current?.querySelector("input");
|
|
2417
|
-
focusAndSelectEditorInput(input);
|
|
2925
|
+
focusAndSelectEditorInput(input, request.selectOnFocus);
|
|
2418
2926
|
}, [request]);
|
|
2419
2927
|
react.useEffect(() => {
|
|
2420
2928
|
setValue(toNumberValue(request.value));
|
|
@@ -2623,6 +3131,94 @@ function DateEditor(props) {
|
|
|
2623
3131
|
}
|
|
2624
3132
|
) });
|
|
2625
3133
|
}
|
|
3134
|
+
function TreeSelectEditor({
|
|
3135
|
+
request,
|
|
3136
|
+
style
|
|
3137
|
+
}) {
|
|
3138
|
+
const [value, setValue] = react.useState(
|
|
3139
|
+
request.value ?? null
|
|
3140
|
+
);
|
|
3141
|
+
const skipBlurCommitRef = react.useRef(false);
|
|
3142
|
+
react.useEffect(() => {
|
|
3143
|
+
setValue(request.value ?? null);
|
|
3144
|
+
}, [request.value]);
|
|
3145
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { style, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3146
|
+
reactComponents.ReactTreeSelect,
|
|
3147
|
+
{
|
|
3148
|
+
autoFocus: true,
|
|
3149
|
+
value,
|
|
3150
|
+
treeData: request.config.treeData,
|
|
3151
|
+
multiple: request.config.multiple,
|
|
3152
|
+
showSearch: request.config.showSearch,
|
|
3153
|
+
treeDefaultExpandAll: request.config.treeDefaultExpandAll,
|
|
3154
|
+
treeDefaultExpandedKeys: request.config.treeDefaultExpandedKeys,
|
|
3155
|
+
allowClear: request.config.allowClear,
|
|
3156
|
+
placeholder: request.config.placeholder,
|
|
3157
|
+
style: getEditorInputStyle(request),
|
|
3158
|
+
onChange: (next, _nodes, info) => {
|
|
3159
|
+
setValue(next);
|
|
3160
|
+
request.onChange(next);
|
|
3161
|
+
if (info.complete && info.trigger !== "clear") {
|
|
3162
|
+
skipBlurCommitRef.current = true;
|
|
3163
|
+
request.onCommit();
|
|
3164
|
+
}
|
|
3165
|
+
},
|
|
3166
|
+
onBlur: (event) => handleEditorBlur(event, skipBlurCommitRef, request),
|
|
3167
|
+
onKeyDown: (event) => {
|
|
3168
|
+
if (event.key === "Tab")
|
|
3169
|
+
handleEditorNavigationKey(event, request, skipBlurCommitRef);
|
|
3170
|
+
if (event.key === "Escape") {
|
|
3171
|
+
skipBlurCommitRef.current = true;
|
|
3172
|
+
handleEditorEscapeKey(event, request);
|
|
3173
|
+
}
|
|
3174
|
+
}
|
|
3175
|
+
}
|
|
3176
|
+
) });
|
|
3177
|
+
}
|
|
3178
|
+
function CascaderEditor({
|
|
3179
|
+
request,
|
|
3180
|
+
style
|
|
3181
|
+
}) {
|
|
3182
|
+
const [value, setValue] = react.useState(Array.isArray(request.value) ? request.value : []);
|
|
3183
|
+
const skipBlurCommitRef = react.useRef(false);
|
|
3184
|
+
react.useEffect(() => {
|
|
3185
|
+
setValue(Array.isArray(request.value) ? request.value : []);
|
|
3186
|
+
}, [request.value]);
|
|
3187
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { style, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3188
|
+
reactComponents.ReactCascader,
|
|
3189
|
+
{
|
|
3190
|
+
value,
|
|
3191
|
+
options: request.config.options,
|
|
3192
|
+
autoFocus: true,
|
|
3193
|
+
placeholder: request.config.placeholder,
|
|
3194
|
+
showSearch: request.config.showSearch,
|
|
3195
|
+
allowClear: request.config.allowClear,
|
|
3196
|
+
changeOnSelect: request.config.changeOnSelect,
|
|
3197
|
+
multiple: request.config.multiple,
|
|
3198
|
+
showCheckedStrategy: request.config.showCheckedStrategy,
|
|
3199
|
+
expandTrigger: request.config.expandTrigger,
|
|
3200
|
+
displayRender: request.config.displayRender,
|
|
3201
|
+
style: getEditorInputStyle(request),
|
|
3202
|
+
onChange: (next, _options, info) => {
|
|
3203
|
+
setValue(next);
|
|
3204
|
+
request.onChange(next);
|
|
3205
|
+
if (info.complete && info.trigger !== "clear") {
|
|
3206
|
+
skipBlurCommitRef.current = true;
|
|
3207
|
+
request.onCommit();
|
|
3208
|
+
}
|
|
3209
|
+
},
|
|
3210
|
+
onBlur: (event) => handleEditorBlur(event, skipBlurCommitRef, request),
|
|
3211
|
+
onKeyDown: (event) => {
|
|
3212
|
+
if (event.key === "Tab")
|
|
3213
|
+
handleEditorNavigationKey(event, request, skipBlurCommitRef);
|
|
3214
|
+
if (event.key === "Escape") {
|
|
3215
|
+
skipBlurCommitRef.current = true;
|
|
3216
|
+
handleEditorEscapeKey(event, request);
|
|
3217
|
+
}
|
|
3218
|
+
}
|
|
3219
|
+
}
|
|
3220
|
+
) });
|
|
3221
|
+
}
|
|
2626
3222
|
function SelectEditor(props) {
|
|
2627
3223
|
const { request, style } = props;
|
|
2628
3224
|
const options = request.config.options ?? [];
|
|
@@ -2953,13 +3549,14 @@ function handleRangeInputTab(event) {
|
|
|
2953
3549
|
focusAndSelectEditorInput(nextInput);
|
|
2954
3550
|
return true;
|
|
2955
3551
|
}
|
|
2956
|
-
function focusAndSelectEditorInput(input) {
|
|
3552
|
+
function focusAndSelectEditorInput(input, selectOnFocus = true) {
|
|
2957
3553
|
if (!input) {
|
|
2958
3554
|
return;
|
|
2959
3555
|
}
|
|
2960
3556
|
input.focus();
|
|
2961
3557
|
try {
|
|
2962
|
-
input.select();
|
|
3558
|
+
if (selectOnFocus) input.select();
|
|
3559
|
+
else input.setSelectionRange(input.value.length, input.value.length);
|
|
2963
3560
|
} catch {
|
|
2964
3561
|
}
|
|
2965
3562
|
}
|
|
@@ -3449,7 +4046,7 @@ function resolveSortableTransform(index, sourceIndex, targetIndex, height) {
|
|
|
3449
4046
|
}
|
|
3450
4047
|
|
|
3451
4048
|
// src/features/toolbar/style.css
|
|
3452
|
-
styleInject('.react-list-table-shell {\n background: #fff;\n font-size: 14px;\n}\n.react-list-table-titlebar {\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 0;\n box-sizing: border-box;\n background: #fff;\n}\n.react-list-table-shell-fullscreen {\n width: 100% !important;\n height: 100% !important;\n}\n.react-list-table-shell-fullscreen .canvas-list-table-root {\n height: 100% !important;\n}\n.react-list-table-title {\n min-width: 0;\n color: #1f2937;\n font-size: 14px;\n font-weight: 600;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.react-list-table-tools {\n display: flex;\n align-items: center;\n gap: 14px;\n color: #475569;\n}\n.react-list-table-tool-wrap {\n position: relative;\n display: inline-flex;\n}\n.react-list-table-tool {\n width: 20px;\n height: 24px;\n padding: 0;\n border: 0;\n color: inherit;\n background: transparent;\n font: 16px/24px sans-serif;\n cursor: pointer;\n}\n.react-list-table-tool:hover {\n color: #1677ff;\n}\n.react-list-table-tool-menu,\n.react-list-table-column-setting {\n position: absolute;\n z-index: 120;\n top: 28px;\n right: 0;\n min-width: 112px;\n padding: 6px;\n border: 1px solid #e5e7eb;\n border-radius: 6px;\n background: #fff;\n box-shadow: 0 8px 24px rgba(15, 23, 42, .14);\n}\n.react-list-table-tool-menu button {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n padding: 6px 10px;\n border: 0;\n border-radius: 4px;\n background: transparent;\n text-align: left;\n cursor: pointer;\n}\n.react-list-table-tool-menu button.active::after {\n content: "\\2713";\n margin-left: 12px;\n font-size: 14px;\n}\n.react-list-table-tool-menu button:hover,\n.react-list-table-tool-menu button.active {\n color: #1677ff;\n background: #e6f4ff;\n}\n.react-list-table-column-setting {\n width: 328px;\n max-height: 360px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n.react-list-table-column-setting-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 4px 6px 8px;\n border-bottom: 1px solid #f0f0f0;\n flex: 0 0 auto;\n}\n.react-list-table-column-setting-head button {\n border: 0;\n color: #1677ff;\n background: transparent;\n cursor: pointer;\n}\n.react-list-table-column-setting-body {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n}\n.react-list-table-column-item {\n display: flex;\n align-items: center;\n gap: 8px;\n justify-content: space-between;\n padding: 7px 6px;\n box-sizing: border-box;\n cursor: pointer;\n}\n.react-list-table-column-main,\n.react-list-table-column-actions {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n}\n.react-list-table-column-main {\n min-width: 0;\n}\n.react-list-table-column-actions {\n flex: 0 0 auto;\n}\n.react-list-table-column-actions > .canvas-react-select-wrap {\n flex: 0 0 96px;\n width: 96px;\n height: 24px;\n}\n.react-list-table-column-label {\n min-width: 64px;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.react-list-table-column-width-input {\n height: 22px;\n padding-inline: 5px;\n}\n.react-list-table-column-fixed-input {\n height: 22px;\n padding-inline: 6px;\n font-size: 14px;\n}\n.react-list-table-column-setting label.dragging {\n opacity: 0.45;\n background: #e6f4ff;\n}\n.react-list-table-column-setting [data-sortable-key].dragging {\n opacity: 0.28;\n}\n.react-list-table-column-drag {\n color: #94a3b8;\n display: inline-flex;\n font-size: 14px;\n cursor: grab;\n user-select: none;\n}\nbody.react-list-table-sorting,\nbody.react-list-table-sorting * {\n cursor: grabbing !important;\n}\n.react-list-table-sort-overlay {\n position: fixed;\n z-index: 1400;\n display: block;\n padding: 0;\n box-sizing: border-box;\n color: #334155;\n background: #fff;\n border: 1px solid #91caff;\n border-radius: 6px;\n box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);\n pointer-events: none;\n}\n.react-list-table-sort-overlay .react-list-table-column-item {\n width: 100%;\n height: 100%;\n}\n');
|
|
4049
|
+
styleInject('.react-list-table-shell {\n background: #fff;\n font-size: 14px;\n}\n.react-list-table-titlebar {\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 0;\n box-sizing: border-box;\n background: #fff;\n}\n.react-list-table-shell-fullscreen {\n width: 100% !important;\n height: 100% !important;\n}\n.react-list-table-shell-fullscreen .canvas-list-table-root {\n height: 100% !important;\n}\n.react-list-table-title {\n min-width: 0;\n color: #1f2937;\n font-size: 14px;\n font-weight: 600;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.react-list-table-tools {\n display: flex;\n align-items: center;\n gap: 14px;\n color: #475569;\n}\n.react-list-table-tool-wrap {\n position: relative;\n display: inline-flex;\n}\n.react-list-table-tool {\n width: 20px;\n height: 24px;\n padding: 0;\n border: 0;\n color: inherit;\n background: transparent;\n font: 16px/24px sans-serif;\n cursor: pointer;\n}\n.react-list-table-tool:hover {\n color: #1677ff;\n}\n.react-list-table-tool-menu,\n.react-list-table-column-setting {\n position: absolute;\n z-index: 120;\n top: 28px;\n right: 0;\n min-width: 112px;\n padding: 6px;\n border: 1px solid #e5e7eb;\n border-radius: 6px;\n background: #fff;\n box-shadow: 0 8px 24px rgba(15, 23, 42, .14);\n}\n.react-list-table-tool-menu button {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n padding: 6px 10px;\n border: 0;\n border-radius: 4px;\n background: transparent;\n text-align: left;\n cursor: pointer;\n}\n.react-list-table-tool-menu button.active::after {\n content: "\\2713";\n margin-left: 12px;\n font-size: 14px;\n}\n.react-list-table-tool-menu button:hover,\n.react-list-table-tool-menu button.active {\n color: #1677ff;\n background: #e6f4ff;\n}\n.react-list-table-column-setting {\n width: 328px;\n max-height: 360px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n.react-list-table-column-setting-head {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n padding: 4px 6px 8px;\n border-bottom: 1px solid #f0f0f0;\n flex: 0 0 auto;\n}\n.react-list-table-column-setting-head button {\n border: 0;\n color: #1677ff;\n background: transparent;\n cursor: pointer;\n}\n.react-list-table-column-setting-body {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n}\n.react-list-table-column-item {\n display: flex;\n align-items: center;\n gap: 8px;\n justify-content: space-between;\n padding: 7px 6px;\n box-sizing: border-box;\n cursor: pointer;\n}\n.react-list-table-column-main,\n.react-list-table-column-actions {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n}\n.react-list-table-column-main {\n min-width: 0;\n}\n.react-list-table-column-actions {\n flex: 0 0 auto;\n}\n.react-list-table-column-actions > .canvas-react-select-wrap {\n flex: 0 0 96px;\n width: 96px;\n height: 24px;\n}\n.react-list-table-column-label {\n min-width: 64px;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.react-list-table-column-width-input {\n height: 22px;\n padding-inline: 5px;\n}\n.react-list-table-column-fixed-input {\n height: 22px;\n padding-inline: 6px;\n font-size: 14px;\n}\n.react-list-table-column-setting label.dragging {\n opacity: 0.45;\n background: #e6f4ff;\n}\n.react-list-table-column-setting [data-sortable-key].dragging {\n opacity: 0.28;\n}\n.react-list-table-column-drag {\n color: #94a3b8;\n display: inline-flex;\n font-size: 14px;\n cursor: grab;\n user-select: none;\n}\nbody.react-list-table-sorting,\nbody.react-list-table-sorting * {\n cursor: grabbing !important;\n}\n.react-list-table-sort-overlay {\n position: fixed;\n z-index: 1400;\n display: block;\n padding: 0;\n box-sizing: border-box;\n color: #334155;\n background: #fff;\n border: 1px solid #91caff;\n border-radius: 6px;\n box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);\n pointer-events: none;\n}\n.react-list-table-sort-overlay .react-list-table-column-item {\n width: 100%;\n height: 100%;\n}\n');
|
|
3453
4050
|
function ReactTableToolbar(props) {
|
|
3454
4051
|
const { toolbar, title } = props;
|
|
3455
4052
|
const [densityOpen, setDensityOpen] = react.useState(false);
|
|
@@ -3566,6 +4163,18 @@ function ReactTableToolbar(props) {
|
|
|
3566
4163
|
children: [
|
|
3567
4164
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "react-list-table-column-setting-head", children: [
|
|
3568
4165
|
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: "\u5217\u8BBE\u7F6E" }),
|
|
4166
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4167
|
+
reactComponents.ReactCheckbox,
|
|
4168
|
+
{
|
|
4169
|
+
checked: props.cacheColumnSettings === true,
|
|
4170
|
+
disabled: !props.columnSettingsCacheAvailable,
|
|
4171
|
+
title: props.columnSettingsCacheAvailable ? "\u7F13\u5B58\u5217\u5BBD\u3001\u663E\u9690\u3001\u56FA\u5B9A\u548C\u987A\u5E8F" : "\u914D\u7F6E storageKey \u540E\u53EF\u7F13\u5B58\u5217\u8BBE\u7F6E",
|
|
4172
|
+
onChange: (event) => props.onColumnSettingsCacheChange?.(
|
|
4173
|
+
event.target.checked
|
|
4174
|
+
),
|
|
4175
|
+
children: "\u7F13\u5B58\u5230\u672C\u5730"
|
|
4176
|
+
}
|
|
4177
|
+
),
|
|
3569
4178
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { marginLeft: "auto" }, children: config.columnSettingHeaderExtra }),
|
|
3570
4179
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: props.onResetColumns, children: "\u91CD\u7F6E" })
|
|
3571
4180
|
] }),
|
|
@@ -3713,9 +4322,14 @@ function useReactListTableState(options) {
|
|
|
3713
4322
|
const [searchRequest, setSearchRequest] = react.useState(null);
|
|
3714
4323
|
const [imagePreviewRequest, setImagePreviewRequest] = react.useState(null);
|
|
3715
4324
|
const [dangerConfirmRequest, setDangerConfirmRequest] = react.useState(null);
|
|
4325
|
+
const [exportNameRequest, setExportNameRequest] = react.useState(null);
|
|
3716
4326
|
const uiOptions = react.useMemo(
|
|
3717
4327
|
() => ({
|
|
3718
4328
|
...options.ui,
|
|
4329
|
+
onExportNameRequest: (request) => {
|
|
4330
|
+
setExportNameRequest(request);
|
|
4331
|
+
options.ui?.onExportNameRequest?.(request);
|
|
4332
|
+
},
|
|
3719
4333
|
onEditorRequest: (request) => {
|
|
3720
4334
|
setEditorRequest(request);
|
|
3721
4335
|
options.ui?.onEditorRequest?.(request);
|
|
@@ -3783,6 +4397,7 @@ function useReactListTableState(options) {
|
|
|
3783
4397
|
setSearchRequest(null);
|
|
3784
4398
|
setImagePreviewRequest(null);
|
|
3785
4399
|
setDangerConfirmRequest(null);
|
|
4400
|
+
setExportNameRequest(null);
|
|
3786
4401
|
};
|
|
3787
4402
|
}, []);
|
|
3788
4403
|
react.useEffect(() => {
|
|
@@ -3804,6 +4419,7 @@ function useReactListTableState(options) {
|
|
|
3804
4419
|
searchRequest,
|
|
3805
4420
|
imagePreviewRequest,
|
|
3806
4421
|
dangerConfirmRequest,
|
|
4422
|
+
exportNameRequest,
|
|
3807
4423
|
closeDangerConfirmRequest: () => {
|
|
3808
4424
|
setDangerConfirmRequest(null);
|
|
3809
4425
|
options.ui?.onDangerConfirmRequest?.(null);
|
|
@@ -3901,12 +4517,15 @@ function ReactListTableInner(props, ref) {
|
|
|
3901
4517
|
stretchColumns,
|
|
3902
4518
|
resizable,
|
|
3903
4519
|
storageKey,
|
|
4520
|
+
cacheColumnSettings,
|
|
4521
|
+
cachePreferences,
|
|
3904
4522
|
draggable,
|
|
3905
4523
|
tableId,
|
|
3906
4524
|
rowDrag,
|
|
3907
4525
|
debug,
|
|
3908
4526
|
title,
|
|
3909
|
-
toolbar
|
|
4527
|
+
toolbar,
|
|
4528
|
+
exportOptions
|
|
3910
4529
|
} = props;
|
|
3911
4530
|
const inheritedDebugEnabled = useReactListTableDebugEnabled();
|
|
3912
4531
|
const resolvedDebug = react.useMemo(
|
|
@@ -3922,6 +4541,10 @@ function ReactListTableInner(props, ref) {
|
|
|
3922
4541
|
);
|
|
3923
4542
|
const [columnConfig, setColumnConfig] = react.useState(() => /* @__PURE__ */ new Map());
|
|
3924
4543
|
const [columnConfigRevision, setColumnConfigRevision] = react.useState(0);
|
|
4544
|
+
const [columnSettingsCacheOverride, setColumnSettingsCacheOverride] = react.useState(null);
|
|
4545
|
+
const resolvedColumnSettingsCache = (columnSettingsCacheOverride?.storageKey === storageKey ? columnSettingsCacheOverride?.value : void 0) ?? cacheColumnSettings ?? true;
|
|
4546
|
+
const [cachePreferencesOverride, setCachePreferencesOverride] = react.useState();
|
|
4547
|
+
const resolvedCachePreferences = (cachePreferencesOverride?.storageKey === storageKey ? cachePreferencesOverride?.value : void 0) ?? cachePreferences;
|
|
3925
4548
|
const [columnConfigResetRevision, setColumnConfigResetRevision] = react.useState(0);
|
|
3926
4549
|
const resolvedColumns = react.useMemo(
|
|
3927
4550
|
() => applyColumnManagerState(
|
|
@@ -3943,6 +4566,7 @@ function ReactListTableInner(props, ref) {
|
|
|
3943
4566
|
);
|
|
3944
4567
|
const options = react.useMemo(() => {
|
|
3945
4568
|
const nextOptions = buildListTableOptions({
|
|
4569
|
+
exportOptions,
|
|
3946
4570
|
width,
|
|
3947
4571
|
height,
|
|
3948
4572
|
emptyText,
|
|
@@ -3975,6 +4599,8 @@ function ReactListTableInner(props, ref) {
|
|
|
3975
4599
|
stretchColumns,
|
|
3976
4600
|
resizable,
|
|
3977
4601
|
storageKey,
|
|
4602
|
+
cacheColumnSettings: resolvedColumnSettingsCache,
|
|
4603
|
+
cachePreferences: resolvedCachePreferences,
|
|
3978
4604
|
draggable,
|
|
3979
4605
|
tableId,
|
|
3980
4606
|
rowDrag,
|
|
@@ -3992,10 +4618,17 @@ function ReactListTableInner(props, ref) {
|
|
|
3992
4618
|
columnConfigResetRevision,
|
|
3993
4619
|
ui: {
|
|
3994
4620
|
...nextOptions.ui,
|
|
3995
|
-
onDensityChange: setDensityOverride
|
|
4621
|
+
onDensityChange: setDensityOverride,
|
|
4622
|
+
onColumnSettingsCacheChange: (value) => setColumnSettingsCacheOverride(
|
|
4623
|
+
(current) => current?.storageKey === storageKey && current?.value === value ? current : { storageKey, value }
|
|
4624
|
+
),
|
|
4625
|
+
onCachePreferencesChange: (next) => setCachePreferencesOverride(
|
|
4626
|
+
(current) => current?.storageKey === storageKey && JSON.stringify(current?.value ?? {}) === JSON.stringify(next) ? current : { storageKey, value: next }
|
|
4627
|
+
)
|
|
3996
4628
|
}
|
|
3997
4629
|
};
|
|
3998
4630
|
}, [
|
|
4631
|
+
exportOptions,
|
|
3999
4632
|
width,
|
|
4000
4633
|
height,
|
|
4001
4634
|
emptyText,
|
|
@@ -4028,6 +4661,8 @@ function ReactListTableInner(props, ref) {
|
|
|
4028
4661
|
stretchColumns,
|
|
4029
4662
|
resizable,
|
|
4030
4663
|
storageKey,
|
|
4664
|
+
resolvedColumnSettingsCache,
|
|
4665
|
+
resolvedCachePreferences,
|
|
4031
4666
|
draggable,
|
|
4032
4667
|
tableId,
|
|
4033
4668
|
rowDrag,
|
|
@@ -4049,6 +4684,7 @@ function ReactListTableInner(props, ref) {
|
|
|
4049
4684
|
searchRequest,
|
|
4050
4685
|
imagePreviewRequest,
|
|
4051
4686
|
dangerConfirmRequest,
|
|
4687
|
+
exportNameRequest,
|
|
4052
4688
|
closeDangerConfirmRequest
|
|
4053
4689
|
} = useReactListTableState(options);
|
|
4054
4690
|
const hasPagination = paginationConfig != null;
|
|
@@ -4096,6 +4732,9 @@ function ReactListTableInner(props, ref) {
|
|
|
4096
4732
|
{
|
|
4097
4733
|
title,
|
|
4098
4734
|
toolbar,
|
|
4735
|
+
cacheColumnSettings: Boolean(storageKey) && resolvedColumnSettingsCache,
|
|
4736
|
+
columnSettingsCacheAvailable: Boolean(storageKey),
|
|
4737
|
+
onColumnSettingsCacheChange: (enabled) => tableRef.current?.setColumnSettingsCache(enabled),
|
|
4099
4738
|
columns: resolvedColumns,
|
|
4100
4739
|
density: resolvedRowHeight ?? 32,
|
|
4101
4740
|
hostRef: shellRef,
|
|
@@ -4225,6 +4864,10 @@ function ReactListTableInner(props, ref) {
|
|
|
4225
4864
|
/* @__PURE__ */ jsxRuntime.jsx(ReactListTableSearchDialog, { request: searchRequest }),
|
|
4226
4865
|
document.body
|
|
4227
4866
|
) : null,
|
|
4867
|
+
exportNameRequest ? reactDom.createPortal(
|
|
4868
|
+
/* @__PURE__ */ jsxRuntime.jsx(ReactListTableExportNameDialog, { request: exportNameRequest }),
|
|
4869
|
+
document.body
|
|
4870
|
+
) : null,
|
|
4228
4871
|
dangerConfirmRequest ? reactDom.createPortal(
|
|
4229
4872
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4230
4873
|
ReactTableDangerConfirmView,
|