@canvas-components/react-pivot-table 0.2.4 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -8,74 +8,237 @@ var reactDom = require('react-dom');
8
8
  var chart = require('@canvas-components/chart');
9
9
 
10
10
  // src/components/react-pivot-table.tsx
11
+
12
+ // #style-inject:#style-inject
13
+ function styleInject(css, { insertAt } = {}) {
14
+ if (!css || typeof document === "undefined") return;
15
+ const head = document.head || document.getElementsByTagName("head")[0];
16
+ const style = document.createElement("style");
17
+ style.type = "text/css";
18
+ if (insertAt === "top") {
19
+ if (head.firstChild) {
20
+ head.insertBefore(style, head.firstChild);
21
+ } else {
22
+ head.appendChild(style);
23
+ }
24
+ } else {
25
+ head.appendChild(style);
26
+ }
27
+ if (style.styleSheet) {
28
+ style.styleSheet.cssText = css;
29
+ } else {
30
+ style.appendChild(document.createTextNode(css));
31
+ }
32
+ }
33
+
34
+ // src/features/context-menu/pivot-context-menu.css
35
+ styleInject(".react-pivot-table-menu-action {\n transition: background-color 0.2s ease, color 0.2s ease;\n}\n.react-pivot-table-menu-action:hover {\n background: #f3f4f6 !important;\n}\n.react-pivot-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-pivot-table-menu-action:hover .react-pivot-table-menu-chevron,\n.react-pivot-table-menu-chevron-active {\n border-color: #6b7280;\n transform: rotate(135deg);\n}\n");
36
+ var CONTEXT_MENU_SURFACE_STYLE = {
37
+ padding: 8,
38
+ background: "#ffffff",
39
+ boxShadow: "0 8px 24px rgba(15, 23, 42, 0.16)"
40
+ };
11
41
  function PivotContextMenu(props) {
12
42
  const { request } = props;
43
+ const [menuOpen, setMenuOpen] = react.useState(true);
44
+ react.useEffect(() => {
45
+ if (request) setMenuOpen(true);
46
+ }, [request]);
13
47
  if (!request) return null;
14
48
  return /* @__PURE__ */ jsxRuntime.jsx(
15
49
  reactComponents.ReactPopup,
16
50
  {
17
- open: true,
51
+ open: menuOpen,
18
52
  anchorRect: { x: request.x, y: request.y, width: 0, height: 0 },
19
53
  offset: 4,
20
54
  matchAnchorWidth: false,
21
- minWidth: 180,
55
+ minWidth: 260,
22
56
  onOpenChange: (open) => {
57
+ setMenuOpen(open);
23
58
  if (!open) request.onClose();
24
59
  },
25
- surfaceStyle: { padding: 6 },
26
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "grid", minWidth: 180 }, children: [
60
+ surfaceStyle: { ...CONTEXT_MENU_SURFACE_STYLE, width: 260 },
61
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
62
+ request.title ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "6px 10px", color: "#8f959e", fontSize: 12 }, children: request.title }) : null,
27
63
  /* @__PURE__ */ jsxRuntime.jsx(
28
- MenuButton,
64
+ MenuSubmenu,
29
65
  {
30
- label: "\u590D\u5236\u5355\u5143\u683C",
31
- onClick: request.onCopy,
32
- close: request.onClose
66
+ label: "\u590D\u5236",
67
+ items: [
68
+ {
69
+ key: "copy-cell",
70
+ label: request.target === "header" ? "\u590D\u5236\u8868\u5934" : "\u590D\u5236\u5355\u5143\u683C",
71
+ onClick: request.onCopy
72
+ },
73
+ {
74
+ key: "copy-selection",
75
+ label: "\u590D\u5236\u9009\u533A",
76
+ onClick: request.target === "header" ? void 0 : request.onCopySelection
77
+ }
78
+ ],
79
+ children: request.target !== "header" ? /* @__PURE__ */ jsxRuntime.jsx(CustomSelectionMenu, { request }) : null
33
80
  }
34
81
  ),
35
- request.onCopySelection ? /* @__PURE__ */ jsxRuntime.jsx(
36
- MenuButton,
37
- {
38
- label: "\u590D\u5236\u9009\u533A",
39
- onClick: request.onCopySelection,
40
- close: request.onClose
41
- }
42
- ) : null,
43
- /* @__PURE__ */ jsxRuntime.jsx(
44
- CustomSelectionMenu,
82
+ request.target === "header" ? /* @__PURE__ */ jsxRuntime.jsx(HeaderMenu, { request }) : null,
83
+ request.target === "summary" ? /* @__PURE__ */ jsxRuntime.jsx(
84
+ SummaryMenu,
45
85
  {
46
86
  request
47
87
  },
48
- `${request.x}-${request.y}`
49
- ),
50
- /* @__PURE__ */ jsxRuntime.jsx(
51
- MenuButton,
52
- {
53
- label: "\u5BFC\u51FA CSV",
54
- onClick: request.onExportCsv,
55
- close: request.onClose
56
- }
57
- ),
88
+ `${request.indicatorKey}-${request.x}-${request.y}`
89
+ ) : null,
90
+ /* @__PURE__ */ jsxRuntime.jsx(DataFormatMenu, { request }),
91
+ /* @__PURE__ */ jsxRuntime.jsx(DensityMenu, { request }),
58
92
  /* @__PURE__ */ jsxRuntime.jsx(
59
- MenuButton,
93
+ MenuSubmenu,
60
94
  {
61
- label: "\u5BFC\u51FA XLSX",
62
- onClick: request.onExportXlsx,
63
- close: request.onClose
95
+ label: "\u5BFC\u51FA",
96
+ items: [
97
+ {
98
+ key: "export-csv",
99
+ label: "\u5BFC\u51FA CSV",
100
+ onClick: request.onExportCsv
101
+ },
102
+ {
103
+ key: "export-xlsx",
104
+ label: "\u5BFC\u51FA XLSX",
105
+ onClick: request.onExportXlsx
106
+ }
107
+ ]
64
108
  }
65
109
  ),
66
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "8px 10px", color: "#8f959e", fontSize: 12 }, children: [
110
+ request.recordCount != null ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "8px 10px", color: "#8f959e", fontSize: 12 }, children: [
67
111
  "\u4E0B\u94BB\u8BB0\u5F55 ",
68
112
  request.recordCount,
69
113
  " \u6761"
70
- ] })
114
+ ] }) : null
71
115
  ] })
72
116
  }
73
117
  );
74
118
  }
119
+ function HeaderMenu(props) {
120
+ const { request } = props;
121
+ const hasSort = request.onSortAsc || request.onSortDesc || request.onClearSort;
122
+ const hasExpand = request.onExpand || request.onCollapse || request.onExpandAll || request.onCollapseAll;
123
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
124
+ hasSort ? /* @__PURE__ */ jsxRuntime.jsx(
125
+ MenuSubmenu,
126
+ {
127
+ label: "\u6392\u5E8F",
128
+ items: [
129
+ {
130
+ key: "sort-asc",
131
+ label: "\u5347\u5E8F",
132
+ selected: request.sortDirection === "asc",
133
+ onClick: request.onSortAsc
134
+ },
135
+ {
136
+ key: "sort-desc",
137
+ label: "\u964D\u5E8F",
138
+ selected: request.sortDirection === "desc",
139
+ onClick: request.onSortDesc
140
+ },
141
+ {
142
+ key: "sort-clear",
143
+ label: "\u53D6\u6D88\u6392\u5E8F",
144
+ onClick: request.onClearSort
145
+ }
146
+ ]
147
+ }
148
+ ) : null,
149
+ request.onOpenFilter ? /* @__PURE__ */ jsxRuntime.jsx(MenuAction, { label: "\u6253\u5F00\u7B5B\u9009\u9762\u677F", onClick: request.onOpenFilter }) : null,
150
+ hasExpand ? /* @__PURE__ */ jsxRuntime.jsx(
151
+ MenuSubmenu,
152
+ {
153
+ label: "\u5C55\u5F00/\u6298\u53E0",
154
+ items: [
155
+ {
156
+ key: "toggle-current",
157
+ label: request.expanded ? "\u6298\u53E0\u5F53\u524D\u9879" : "\u5C55\u5F00\u5F53\u524D\u9879",
158
+ onClick: request.expanded ? request.onCollapse : request.onExpand
159
+ },
160
+ {
161
+ key: "expand-all",
162
+ label: "\u5168\u90E8\u5C55\u5F00",
163
+ onClick: request.onExpandAll
164
+ },
165
+ {
166
+ key: "collapse-all",
167
+ label: "\u5168\u90E8\u6298\u53E0",
168
+ onClick: request.onCollapseAll
169
+ }
170
+ ]
171
+ }
172
+ ) : null
173
+ ] });
174
+ }
175
+ function SummaryMenu(props) {
176
+ const { request } = props;
177
+ const [precision, setPrecision] = react.useState(
178
+ request.summaryPrecision ?? null
179
+ );
180
+ const aggregators = [
181
+ ["sum", "\u6C42\u548C"],
182
+ ["avg", "\u5E73\u5747\u503C"],
183
+ ["count", "\u8BA1\u6570"],
184
+ ["distinctCount", "\u53BB\u91CD\u8BA1\u6570"],
185
+ ["min", "\u6700\u5C0F\u503C"],
186
+ ["max", "\u6700\u5927\u503C"]
187
+ ];
188
+ if (!request.onChangeSummaryAggregator) return null;
189
+ return /* @__PURE__ */ jsxRuntime.jsx(
190
+ MenuSubmenu,
191
+ {
192
+ label: "\u6C47\u603B\u65B9\u5F0F",
193
+ items: aggregators.map(([value, label]) => ({
194
+ key: `summary-${value}`,
195
+ label,
196
+ selected: request.summaryAggregator === value,
197
+ onClick: () => {
198
+ request.onChangeSummaryAggregator?.(value);
199
+ request.onClose();
200
+ }
201
+ })),
202
+ footer: request.onChangeSummaryPrecision ? /* @__PURE__ */ jsxRuntime.jsxs(
203
+ "div",
204
+ {
205
+ style: {
206
+ display: "grid",
207
+ gridTemplateColumns: "72px 1fr",
208
+ gap: 8,
209
+ alignItems: "center",
210
+ marginTop: 4,
211
+ padding: "10px 10px 4px",
212
+ borderTop: "1px solid #e5e7eb"
213
+ },
214
+ children: [
215
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#374151", fontSize: 13 }, children: "\u5C0F\u6570\u4F4D\u6570" }),
216
+ /* @__PURE__ */ jsxRuntime.jsx(
217
+ reactComponents.ReactInputNumber,
218
+ {
219
+ value: precision,
220
+ min: 0,
221
+ max: 20,
222
+ step: 1,
223
+ precision: 0,
224
+ placeholder: "\u81EA\u52A8",
225
+ onChange: (value) => {
226
+ setPrecision(value);
227
+ request.onChangeSummaryPrecision?.(value ?? void 0);
228
+ }
229
+ }
230
+ )
231
+ ]
232
+ }
233
+ ) : null
234
+ }
235
+ );
236
+ }
237
+ function MenuDivider() {
238
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: 1, margin: "6px 0", background: "#f0f0f0" } });
239
+ }
75
240
  function CustomSelectionMenu(props) {
76
241
  const { request } = props;
77
- const triggerRef = react.useRef(null);
78
- const [open, setOpen] = react.useState(false);
79
242
  const [range, setRange] = react.useState(
80
243
  request.customSelection ?? {
81
244
  startRow: 1,
@@ -93,104 +256,79 @@ function CustomSelectionMenu(props) {
93
256
  [key]: value == null ? 1 : Math.floor(value)
94
257
  }));
95
258
  };
96
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
259
+ return /* @__PURE__ */ jsxRuntime.jsx(MenuSubmenu, { label: "\u590D\u5236\u81EA\u5B9A\u4E49\u9009\u533A", items: [], minWidth: 250, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: 6 }, children: [
260
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#6b7280", fontSize: 12, marginBottom: 6 }, children: "\u8F93\u5165\u8D77\u59CB\u4F4D\u7F6E\u548C\u7ED3\u675F\u4F4D\u7F6E" }),
261
+ /* @__PURE__ */ jsxRuntime.jsxs(
262
+ "div",
263
+ {
264
+ style: {
265
+ display: "grid",
266
+ gridTemplateColumns: "38px 1fr 1fr",
267
+ gap: 6,
268
+ marginBottom: 4,
269
+ color: "#6b7280",
270
+ fontSize: 12,
271
+ textAlign: "center"
272
+ },
273
+ children: [
274
+ /* @__PURE__ */ jsxRuntime.jsx("span", {}),
275
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u884C" }),
276
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u5217" })
277
+ ]
278
+ }
279
+ ),
97
280
  /* @__PURE__ */ jsxRuntime.jsx(
98
- "button",
281
+ CustomSelectionRow,
99
282
  {
100
- ref: triggerRef,
101
- type: "button",
102
- onClick: () => setOpen((value) => !value),
103
- style: menuButtonStyle,
104
- children: "\u590D\u5236\u81EA\u5B9A\u4E49\u9009\u533A"
283
+ label: "\u8D77\u59CB",
284
+ row: range.startRow,
285
+ column: range.startColumn,
286
+ maxRow: range.rowCount,
287
+ maxColumn: range.columnCount,
288
+ onRowChange: (value) => update("startRow", value),
289
+ onColumnChange: (value) => update("startColumn", value)
105
290
  }
106
291
  ),
107
292
  /* @__PURE__ */ jsxRuntime.jsx(
108
- reactComponents.ReactPopup,
293
+ CustomSelectionRow,
109
294
  {
110
- open,
111
- anchorRef: triggerRef,
112
- placement: "rightTop",
113
- offset: 2,
114
- minWidth: 250,
115
- onOpenChange: setOpen,
116
- surfaceStyle: { padding: 6, width: 250 },
117
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: 6 }, children: [
118
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#6b7280", fontSize: 12, marginBottom: 6 }, children: "\u8F93\u5165\u8D77\u59CB\u4F4D\u7F6E\u548C\u7ED3\u675F\u4F4D\u7F6E" }),
119
- /* @__PURE__ */ jsxRuntime.jsxs(
120
- "div",
121
- {
122
- style: {
123
- display: "grid",
124
- gridTemplateColumns: "38px 1fr 1fr",
125
- gap: 6,
126
- marginBottom: 4,
127
- color: "#6b7280",
128
- fontSize: 12,
129
- textAlign: "center"
130
- },
131
- children: [
132
- /* @__PURE__ */ jsxRuntime.jsx("span", {}),
133
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u884C" }),
134
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u5217" })
135
- ]
136
- }
137
- ),
138
- /* @__PURE__ */ jsxRuntime.jsx(
139
- CustomSelectionRow,
140
- {
141
- label: "\u8D77\u59CB",
142
- row: range.startRow,
143
- column: range.startColumn,
144
- maxRow: range.rowCount,
145
- maxColumn: range.columnCount,
146
- onRowChange: (value) => update("startRow", value),
147
- onColumnChange: (value) => update("startColumn", value)
148
- }
149
- ),
150
- /* @__PURE__ */ jsxRuntime.jsx(
151
- CustomSelectionRow,
152
- {
153
- label: "\u7ED3\u675F",
154
- row: range.endRow,
155
- column: range.endColumn,
156
- maxRow: range.rowCount,
157
- maxColumn: range.columnCount,
158
- onRowChange: (value) => update("endRow", value),
159
- onColumnChange: (value) => update("endColumn", value)
160
- }
161
- ),
162
- /* @__PURE__ */ jsxRuntime.jsx(
163
- "button",
164
- {
165
- type: "button",
166
- style: {
167
- display: "block",
168
- width: "100%",
169
- height: 32,
170
- marginTop: 6,
171
- border: "none",
172
- borderRadius: 4,
173
- background: "#1677ff",
174
- color: "#fff",
175
- cursor: "pointer"
176
- },
177
- onClick: () => {
178
- request.onCopyCustomSelection?.({
179
- startRow: range.startRow,
180
- startColumn: range.startColumn,
181
- endRow: range.endRow,
182
- endColumn: range.endColumn
183
- });
184
- setOpen(false);
185
- request.onClose();
186
- },
187
- children: "\u590D\u5236"
188
- }
189
- )
190
- ] })
295
+ label: "\u7ED3\u675F",
296
+ row: range.endRow,
297
+ column: range.endColumn,
298
+ maxRow: range.rowCount,
299
+ maxColumn: range.columnCount,
300
+ onRowChange: (value) => update("endRow", value),
301
+ onColumnChange: (value) => update("endColumn", value)
302
+ }
303
+ ),
304
+ /* @__PURE__ */ jsxRuntime.jsx(
305
+ "button",
306
+ {
307
+ type: "button",
308
+ style: {
309
+ display: "block",
310
+ width: "100%",
311
+ height: 32,
312
+ marginTop: 6,
313
+ border: "none",
314
+ borderRadius: 4,
315
+ background: "#1677ff",
316
+ color: "#fff",
317
+ cursor: "pointer"
318
+ },
319
+ onClick: () => {
320
+ request.onCopyCustomSelection?.({
321
+ startRow: range.startRow,
322
+ startColumn: range.startColumn,
323
+ endRow: range.endRow,
324
+ endColumn: range.endColumn
325
+ });
326
+ request.onClose();
327
+ },
328
+ children: "\u590D\u5236"
191
329
  }
192
330
  )
193
- ] });
331
+ ] }) });
194
332
  }
195
333
  function CustomSelectionRow(props) {
196
334
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -233,27 +371,324 @@ function CustomSelectionRow(props) {
233
371
  }
234
372
  );
235
373
  }
236
- var menuButtonStyle = {
237
- height: 34,
238
- padding: "0 10px",
239
- border: 0,
240
- borderRadius: 4,
241
- background: "transparent",
242
- color: "#1f2329",
243
- textAlign: "left",
244
- cursor: "pointer"
245
- };
246
- function MenuButton(props) {
247
- return /* @__PURE__ */ jsxRuntime.jsx(
374
+ function MenuAction(props) {
375
+ const { label, preview, onClick, selected, disabled, reserveSelectionIcon } = props;
376
+ if (!onClick && !disabled) return null;
377
+ return /* @__PURE__ */ jsxRuntime.jsxs(
248
378
  "button",
249
379
  {
250
380
  type: "button",
251
- onClick: () => {
252
- props.onClick();
253
- props.close();
381
+ onClick: disabled ? void 0 : onClick,
382
+ disabled,
383
+ className: "react-pivot-table-menu-action",
384
+ style: {
385
+ display: "flex",
386
+ alignItems: "center",
387
+ width: "100%",
388
+ height: 32,
389
+ padding: "0 10px",
390
+ border: "none",
391
+ borderRadius: 8,
392
+ background: "transparent",
393
+ color: disabled ? "#9ca3af" : "#374151",
394
+ textAlign: "left",
395
+ cursor: disabled ? "default" : "pointer"
254
396
  },
255
- style: menuButtonStyle,
256
- children: props.label
397
+ children: [
398
+ reserveSelectionIcon ? /* @__PURE__ */ jsxRuntime.jsx(
399
+ "span",
400
+ {
401
+ "aria-hidden": "true",
402
+ style: {
403
+ width: 16,
404
+ flex: "0 0 16px",
405
+ marginRight: 6,
406
+ textAlign: "center"
407
+ },
408
+ children: selected ? "\u2713" : ""
409
+ }
410
+ ) : null,
411
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { flex: 1, whiteSpace: "nowrap" }, children: label }),
412
+ preview ? /* @__PURE__ */ jsxRuntime.jsx(
413
+ "span",
414
+ {
415
+ style: { marginLeft: 16, color: "#9ca3af", whiteSpace: "nowrap" },
416
+ children: preview
417
+ }
418
+ ) : null
419
+ ]
420
+ }
421
+ );
422
+ }
423
+ function MenuSubmenu(props) {
424
+ const { label, items, footer, children, minWidth = 220 } = props;
425
+ const menuItems = items.filter((item) => item.onClick || item.disabled);
426
+ const reserveSelectionIcon = menuItems.some(
427
+ (item) => typeof item.selected === "boolean"
428
+ );
429
+ const triggerRef = react.useRef(null);
430
+ const [open, setOpen] = react.useState(false);
431
+ const closeTimerRef = react.useRef(null);
432
+ if (!menuItems.length && !footer && !children) return null;
433
+ const clearCloseTimer = () => {
434
+ if (closeTimerRef.current != null) {
435
+ window.clearTimeout(closeTimerRef.current);
436
+ closeTimerRef.current = null;
437
+ }
438
+ };
439
+ const scheduleClose = () => {
440
+ clearCloseTimer();
441
+ closeTimerRef.current = window.setTimeout(() => {
442
+ setOpen(false);
443
+ closeTimerRef.current = null;
444
+ }, 120);
445
+ };
446
+ return /* @__PURE__ */ jsxRuntime.jsxs(
447
+ "div",
448
+ {
449
+ onMouseEnter: () => {
450
+ clearCloseTimer();
451
+ setOpen(true);
452
+ },
453
+ onMouseLeave: scheduleClose,
454
+ children: [
455
+ /* @__PURE__ */ jsxRuntime.jsxs(
456
+ "button",
457
+ {
458
+ ref: triggerRef,
459
+ type: "button",
460
+ onClick: () => setOpen((value) => !value),
461
+ className: "react-pivot-table-menu-action react-pivot-table-menu-action-submenu",
462
+ style: {
463
+ display: "flex",
464
+ alignItems: "center",
465
+ justifyContent: "space-between",
466
+ width: "100%",
467
+ height: 32,
468
+ padding: "0 10px",
469
+ border: "none",
470
+ borderRadius: 8,
471
+ background: "transparent",
472
+ color: "#374151",
473
+ textAlign: "left",
474
+ cursor: "pointer"
475
+ },
476
+ children: [
477
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: label }),
478
+ /* @__PURE__ */ jsxRuntime.jsx(
479
+ "span",
480
+ {
481
+ className: `react-pivot-table-menu-chevron${open ? " react-pivot-table-menu-chevron-active" : ""}`,
482
+ "aria-hidden": "true"
483
+ }
484
+ )
485
+ ]
486
+ }
487
+ ),
488
+ /* @__PURE__ */ jsxRuntime.jsx(
489
+ reactComponents.ReactPopup,
490
+ {
491
+ open,
492
+ anchorRef: triggerRef,
493
+ placement: "rightTop",
494
+ offset: 2,
495
+ minWidth,
496
+ onOpenChange: setOpen,
497
+ surfaceStyle: { ...CONTEXT_MENU_SURFACE_STYLE, width: minWidth },
498
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { onMouseEnter: clearCloseTimer, onMouseLeave: scheduleClose, children: [
499
+ menuItems.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
500
+ item.separatorBefore ? /* @__PURE__ */ jsxRuntime.jsx(MenuDivider, {}) : null,
501
+ /* @__PURE__ */ jsxRuntime.jsx(
502
+ MenuAction,
503
+ {
504
+ label: item.label,
505
+ preview: item.preview,
506
+ selected: item.selected,
507
+ disabled: item.disabled,
508
+ onClick: item.onClick,
509
+ reserveSelectionIcon
510
+ }
511
+ )
512
+ ] }, item.key)),
513
+ children,
514
+ footer
515
+ ] })
516
+ }
517
+ )
518
+ ]
519
+ }
520
+ );
521
+ }
522
+ function DensityMenu(props) {
523
+ const { request } = props;
524
+ if (!request.onChangeDensity) return null;
525
+ return /* @__PURE__ */ jsxRuntime.jsx(
526
+ MenuSubmenu,
527
+ {
528
+ label: "\u8868\u683C\u5BC6\u5EA6",
529
+ items: [
530
+ {
531
+ key: "density-comfortable",
532
+ label: "\u5BBD\u677E",
533
+ selected: request.density === "comfortable",
534
+ onClick: () => request.onChangeDensity?.("comfortable")
535
+ },
536
+ {
537
+ key: "density-middle",
538
+ label: "\u4E2D\u7B49",
539
+ selected: request.density === "middle",
540
+ onClick: () => request.onChangeDensity?.("middle")
541
+ },
542
+ {
543
+ key: "density-compact",
544
+ label: "\u7D27\u51D1",
545
+ selected: request.density === "compact",
546
+ onClick: () => request.onChangeDensity?.("compact")
547
+ },
548
+ {
549
+ key: "density-ultra-compact",
550
+ label: "\u8D85\u7D27\u51D1",
551
+ selected: request.density === "ultra-compact",
552
+ onClick: () => request.onChangeDensity?.("ultra-compact")
553
+ },
554
+ {
555
+ key: "density-auto",
556
+ label: "\u81EA\u9002\u5E94",
557
+ selected: request.density === "auto",
558
+ onClick: () => request.onChangeDensity?.("auto")
559
+ }
560
+ ]
561
+ }
562
+ );
563
+ }
564
+ function DataFormatMenu(props) {
565
+ const { request } = props;
566
+ if (!request.onChangeDataFormat) return null;
567
+ const formats = [
568
+ { key: "default", label: "\u5E38\u89C4", value: "default" },
569
+ { key: "text", label: "\u7EAF\u6587\u672C", value: "text" },
570
+ {
571
+ key: "number",
572
+ label: "\u6570\u5B57",
573
+ preview: "1024",
574
+ value: "number",
575
+ separatorBefore: true
576
+ },
577
+ {
578
+ key: "thousands",
579
+ label: "\u6570\u5B57\uFF08\u5343\u5206\u4F4D\uFF09",
580
+ preview: "1,024",
581
+ value: "thousands"
582
+ },
583
+ {
584
+ key: "decimal",
585
+ label: "\u6570\u5B57\uFF08\u5343\u5206\u4F4D\uFF0C\u5C0F\u6570\u70B9\uFF09",
586
+ preview: "1,024.56",
587
+ value: "decimal"
588
+ },
589
+ {
590
+ key: "percent",
591
+ label: "\u767E\u5206\u6BD4",
592
+ preview: "10%",
593
+ value: "percent",
594
+ separatorBefore: true
595
+ },
596
+ {
597
+ key: "percentDecimal",
598
+ label: "\u767E\u5206\u6BD4\uFF08\u5C0F\u6570\u70B9\uFF09",
599
+ preview: "10.24%",
600
+ value: "percentDecimal"
601
+ },
602
+ {
603
+ key: "scientific",
604
+ label: "\u79D1\u5B66\u8BB0\u6570",
605
+ preview: "1.02E+003",
606
+ value: "scientific"
607
+ },
608
+ {
609
+ key: "numberToChineseUpper",
610
+ label: "\u6570\u5B57\u8F6C\u5927\u5199",
611
+ preview: "\u7396\u62FE\u58F9\u4E07\u634C\u4EDF",
612
+ value: "numberToChineseUpper"
613
+ },
614
+ {
615
+ key: "chineseUpperToNumber",
616
+ label: "\u5927\u5199\u8F6C\u6570\u5B57",
617
+ preview: "918000",
618
+ value: "chineseUpperToNumber"
619
+ },
620
+ {
621
+ key: "cny",
622
+ label: "\u4EBA\u6C11\u5E01",
623
+ preview: "\xA51,024",
624
+ value: "cny",
625
+ separatorBefore: true
626
+ },
627
+ {
628
+ key: "cnyDecimal",
629
+ label: "\u4EBA\u6C11\u5E01\uFF08\u5C0F\u6570\u70B9\uFF09",
630
+ preview: "\xA51,024.56",
631
+ value: "cnyDecimal"
632
+ },
633
+ { key: "usd", label: "\u7F8E\u5143", preview: "$1,024", value: "usd" },
634
+ {
635
+ key: "usdDecimal",
636
+ label: "\u7F8E\u5143\uFF08\u5C0F\u6570\u70B9\uFF09",
637
+ preview: "$1,024.56",
638
+ value: "usdDecimal"
639
+ },
640
+ {
641
+ key: "dateSlash",
642
+ label: "\u65E5\u671F\uFF08\u659C\u6760\uFF09",
643
+ preview: "2017/08/01",
644
+ value: "dateSlash",
645
+ separatorBefore: true
646
+ },
647
+ {
648
+ key: "dateDash",
649
+ label: "\u65E5\u671F\uFF08\u77ED\u6A2A\u7EBF\uFF09",
650
+ preview: "2017-08-01",
651
+ value: "dateDash"
652
+ },
653
+ {
654
+ key: "dateFullCN",
655
+ label: "\u65E5\u671F\uFF08\u4E2D\u6587\uFF09",
656
+ preview: "2017\u5E748\u67081\u65E5",
657
+ value: "dateFullCN"
658
+ },
659
+ { key: "time", label: "\u65F6\u95F4", preview: "23:24:25", value: "time" },
660
+ {
661
+ key: "timeShort",
662
+ label: "\u65F6\u95F4\uFF08\u5206\uFF09",
663
+ preview: "23:24",
664
+ value: "timeShort"
665
+ },
666
+ {
667
+ key: "datetime",
668
+ label: "\u65E5\u671F\u65F6\u95F4",
669
+ preview: "2017/08/01 23:24:25",
670
+ value: "datetime"
671
+ },
672
+ {
673
+ key: "datetime12",
674
+ label: "\u65E5\u671F\u65F6\u95F4\uFF08\u4E0A\u4E0B\uFF09",
675
+ preview: "2017/08/01 \u4E0B\u534811:24",
676
+ value: "datetime12"
677
+ }
678
+ ];
679
+ return /* @__PURE__ */ jsxRuntime.jsx(
680
+ MenuSubmenu,
681
+ {
682
+ label: "\u683C\u5F0F",
683
+ minWidth: 340,
684
+ items: formats.map((item) => ({
685
+ key: `data-format-${item.key}`,
686
+ label: item.label,
687
+ preview: "preview" in item ? item.preview : void 0,
688
+ separatorBefore: "separatorBefore" in item ? item.separatorBefore : void 0,
689
+ selected: request.dataFormat === item.value,
690
+ onClick: () => request.onChangeDataFormat?.(item.value)
691
+ }))
257
692
  }
258
693
  );
259
694
  }
@@ -288,28 +723,6 @@ function PivotTooltip(props) {
288
723
  );
289
724
  }
290
725
 
291
- // #style-inject:#style-inject
292
- function styleInject(css, { insertAt } = {}) {
293
- if (!css || typeof document === "undefined") return;
294
- const head = document.head || document.getElementsByTagName("head")[0];
295
- const style = document.createElement("style");
296
- style.type = "text/css";
297
- if (insertAt === "top") {
298
- if (head.firstChild) {
299
- head.insertBefore(style, head.firstChild);
300
- } else {
301
- head.appendChild(style);
302
- }
303
- } else {
304
- head.appendChild(style);
305
- }
306
- if (style.styleSheet) {
307
- style.styleSheet.cssText = css;
308
- } else {
309
- style.appendChild(document.createTextNode(css));
310
- }
311
- }
312
-
313
726
  // src/features/field-panel/pivot-field-panel.css
314
727
  styleInject('.react-pivot-table-customization {\n position: relative;\n overflow: hidden;\n}\n.react-pivot-table-customization__table {\n position: relative;\n min-width: 0;\n min-height: 0;\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n.react-pivot-table-customization__panel-column {\n flex-grow: 0 !important;\n overflow: hidden;\n}\n.react-pivot-table-customization__chart-column {\n flex-grow: 0 !important;\n overflow: hidden;\n}\n.react-pivot-field-panel {\n display: flex;\n width: 100%;\n min-width: 280px;\n height: 100%;\n flex-direction: column;\n overflow: hidden;\n background: #fff;\n color: #1f2329;\n font-family:\n "Segoe UI",\n "Microsoft YaHei",\n sans-serif;\n font-size: 13px;\n box-sizing: border-box;\n}\n.react-pivot-field-panel button,\n.react-pivot-field-panel input,\n.react-pivot-field-panel select {\n font: inherit;\n}\n.react-pivot-field-panel__header {\n display: flex;\n height: 42px;\n flex: 0 0 42px;\n align-items: center;\n justify-content: space-between;\n padding: 0 10px 0 14px;\n border-bottom: 1px solid #edf0f2;\n background: #fff;\n}\n.react-pivot-field-panel__icon-button {\n display: inline-flex;\n width: 24px;\n height: 24px;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: 0;\n background: transparent;\n color: #646a73;\n cursor: pointer;\n font: 18px/24px "Segoe UI", sans-serif;\n}\n.react-pivot-field-panel__icon-button:hover {\n background: #f2f3f5;\n color: #d14343;\n}\n.react-pivot-field-panel__layout {\n width: 100%;\n height: auto;\n min-height: 0;\n flex: 1 1 0;\n overflow: hidden;\n}\n.react-pivot-field-panel__layout > .canvas-react-resizable-panels-item > .canvas-react-resizable-panel {\n overflow: hidden;\n}\n.react-pivot-field-panel__section {\n height: 100%;\n padding: 10px 12px 0;\n box-sizing: border-box;\n}\n.react-pivot-field-panel__section--fields,\n.react-pivot-field-panel__section--areas {\n display: flex;\n min-height: 0;\n flex-direction: column;\n}\n.react-pivot-field-panel__section--fields {\n padding-bottom: 6px;\n}\n.react-pivot-field-panel__section--areas {\n padding-bottom: 12px;\n}\n.react-pivot-field-panel__section-title {\n margin-bottom: 5px;\n font-weight: 600;\n}\n.react-pivot-field-panel__hint {\n margin-bottom: 8px;\n color: #646a73;\n font-size: 12px;\n}\n.react-pivot-field-panel__search {\n display: flex;\n height: 32px;\n align-items: center;\n gap: 8px;\n padding: 0 9px;\n border: 1px solid #d5d9de;\n border-radius: 3px;\n background: #fff;\n box-sizing: border-box;\n}\n.react-pivot-field-panel__search > span {\n width: 12px;\n height: 12px;\n border: 1.5px solid #4f5660;\n border-radius: 50%;\n position: relative;\n}\n.react-pivot-field-panel__search > span::after {\n position: absolute;\n right: -4px;\n bottom: -3px;\n width: 5px;\n height: 1.5px;\n background: #4f5660;\n content: "";\n transform: rotate(45deg);\n}\n.react-pivot-field-panel__search input {\n min-width: 0;\n flex: 1;\n border: 0;\n outline: 0;\n color: #1f2329;\n}\n.react-pivot-field-panel__field-list {\n min-height: 0;\n flex: 1;\n margin-top: 6px;\n overflow: auto;\n border: 1px solid #dfe3e7;\n border-radius: 3px;\n background: #fff;\n}\n.react-pivot-field-panel__field,\n.react-pivot-field-panel__area-field {\n display: grid;\n height: 28px;\n align-items: center;\n column-gap: 6px;\n box-sizing: border-box;\n}\n.react-pivot-field-panel__field {\n grid-template-columns: 10px 16px minmax(0, 1fr);\n padding: 0 8px 0 6px;\n}\n.react-pivot-field-panel__field:hover {\n background: #f5f8fb;\n}\n.react-pivot-field-panel__field[data-dragging] {\n opacity: 0.45;\n}\n.react-pivot-field-panel__field > span:nth-of-type(2),\n.react-pivot-field-panel__area-field > span:nth-of-type(2) {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.react-pivot-field-panel__drag {\n width: 8px;\n height: 12px;\n cursor: grab;\n background-image:\n radial-gradient(\n circle at 2px 2px,\n #8f959e 1px,\n transparent 1.2px);\n background-position: 0 0;\n background-size: 4px 4px;\n background-repeat: repeat;\n}\n.react-pivot-field-panel__empty,\n.react-pivot-field-panel__area-empty {\n display: grid;\n height: 100%;\n place-items: center;\n color: #8f959e;\n font-size: 12px;\n}\n.react-pivot-field-panel__areas {\n display: grid;\n min-height: 0;\n flex: 1;\n grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\n grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);\n gap: 8px;\n}\n.react-pivot-field-panel__area-wrap {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex-direction: column;\n}\n.react-pivot-field-panel__area-title {\n display: grid;\n height: 25px;\n grid-template-columns: minmax(0, 1fr);\n align-items: center;\n gap: 5px;\n color: #3f454d;\n}\n.react-pivot-field-panel__area {\n min-height: 0;\n flex: 1;\n overflow: auto;\n border: 1px solid #dfe3e7;\n border-radius: 3px;\n background: #fff;\n}\n.react-pivot-field-panel__area[data-dragging] {\n border-color: #2f78d0;\n background: #f7faff;\n}\n.react-pivot-field-panel__area-field {\n grid-template-columns: 9px minmax(0, 1fr) 18px;\n padding: 0 7px 0 5px;\n}\n.react-pivot-field-panel__area-field:hover {\n background: #f5f8fb;\n}\n.react-pivot-field-panel__area-field-menu {\n display: grid;\n width: 18px;\n height: 22px;\n padding: 0;\n place-items: center;\n border: 0;\n background: transparent;\n color: #646a73;\n cursor: pointer;\n}\n.react-pivot-field-panel__area-field-menu:hover {\n color: #1f2329;\n background: #e9edf2;\n}\n.react-pivot-field-panel__area-field-menu > span {\n width: 0;\n height: 0;\n border-top: 5px solid currentColor;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.react-pivot-field-menu {\n min-width: 176px;\n padding: 5px 0;\n color: #1f2329;\n font:\n 13px "Segoe UI",\n "Microsoft YaHei",\n sans-serif;\n}\n.react-pivot-field-menu__item {\n display: block;\n width: 100%;\n height: 30px;\n padding: 0 12px;\n border: 0;\n background: transparent;\n color: inherit;\n text-align: left;\n cursor: pointer;\n}\n.react-pivot-field-menu__item:hover:not(:disabled) {\n background: #e9f2fc;\n}\n.react-pivot-field-menu__item:disabled {\n color: #a7abb2;\n cursor: default;\n}\n.react-pivot-field-menu__item[data-danger] {\n color: #c9372c;\n}\n.react-pivot-field-menu__separator {\n height: 1px;\n margin: 4px 0;\n background: #e1e4e8;\n}\n.react-pivot-field-settings {\n display: grid;\n min-width: 260px;\n gap: 12px;\n padding: 14px;\n color: #1f2329;\n font:\n 13px "Segoe UI",\n "Microsoft YaHei",\n sans-serif;\n}\n.react-pivot-field-settings label {\n display: grid;\n gap: 5px;\n color: #515761;\n}\n.react-pivot-field-settings__name-input,\n.react-pivot-field-settings__aggregator {\n height: 30px;\n font: inherit;\n}\n.react-pivot-field-settings__actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n.react-pivot-field-settings__actions button {\n height: 30px;\n padding: 0 14px;\n border: 1px solid #bfc4cb;\n border-radius: 3px;\n background: #fff;\n cursor: pointer;\n}\n.react-pivot-field-settings__actions button.is-primary {\n border-color: #2f78d0;\n background: #2f78d0;\n color: #fff;\n}\n');
315
728
  function PivotFieldPanel(props) {
@@ -575,7 +988,7 @@ function FieldContextMenu(props) {
575
988
  },
576
989
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "react-pivot-field-menu", role: "menu", children: [
577
990
  /* @__PURE__ */ jsxRuntime.jsx(
578
- MenuAction,
991
+ MenuAction2,
579
992
  {
580
993
  label: "\u4E0A\u79FB",
581
994
  disabled: index <= 0,
@@ -584,7 +997,7 @@ function FieldContextMenu(props) {
584
997
  }
585
998
  ),
586
999
  /* @__PURE__ */ jsxRuntime.jsx(
587
- MenuAction,
1000
+ MenuAction2,
588
1001
  {
589
1002
  label: "\u4E0B\u79FB",
590
1003
  disabled: index < 0 || index >= keys.length - 1,
@@ -593,7 +1006,7 @@ function FieldContextMenu(props) {
593
1006
  }
594
1007
  ),
595
1008
  /* @__PURE__ */ jsxRuntime.jsx(
596
- MenuAction,
1009
+ MenuAction2,
597
1010
  {
598
1011
  label: "\u79FB\u81F3\u5F00\u5934",
599
1012
  disabled: index <= 0,
@@ -602,7 +1015,7 @@ function FieldContextMenu(props) {
602
1015
  }
603
1016
  ),
604
1017
  /* @__PURE__ */ jsxRuntime.jsx(
605
- MenuAction,
1018
+ MenuAction2,
606
1019
  {
607
1020
  label: "\u79FB\u81F3\u672B\u5C3E",
608
1021
  disabled: index === keys.length - 1,
@@ -612,7 +1025,7 @@ function FieldContextMenu(props) {
612
1025
  ),
613
1026
  /* @__PURE__ */ jsxRuntime.jsx(MenuSeparator, {}),
614
1027
  /* @__PURE__ */ jsxRuntime.jsx(
615
- MenuAction,
1028
+ MenuAction2,
616
1029
  {
617
1030
  label: "\u6DFB\u52A0\u5230\u62A5\u8868\u7B5B\u9009",
618
1031
  disabled: state.area === "filter",
@@ -621,7 +1034,7 @@ function FieldContextMenu(props) {
621
1034
  }
622
1035
  ),
623
1036
  /* @__PURE__ */ jsxRuntime.jsx(
624
- MenuAction,
1037
+ MenuAction2,
625
1038
  {
626
1039
  label: "\u6DFB\u52A0\u5230\u884C\u6807\u7B7E",
627
1040
  disabled: state.area === "row",
@@ -630,7 +1043,7 @@ function FieldContextMenu(props) {
630
1043
  }
631
1044
  ),
632
1045
  /* @__PURE__ */ jsxRuntime.jsx(
633
- MenuAction,
1046
+ MenuAction2,
634
1047
  {
635
1048
  label: "\u6DFB\u52A0\u5230\u5217\u6807\u7B7E",
636
1049
  disabled: state.area === "column",
@@ -639,7 +1052,7 @@ function FieldContextMenu(props) {
639
1052
  }
640
1053
  ),
641
1054
  /* @__PURE__ */ jsxRuntime.jsx(
642
- MenuAction,
1055
+ MenuAction2,
643
1056
  {
644
1057
  label: "\u79FB\u52A8\u5230\u503C",
645
1058
  disabled: state.area === "value",
@@ -649,7 +1062,7 @@ function FieldContextMenu(props) {
649
1062
  ),
650
1063
  /* @__PURE__ */ jsxRuntime.jsx(MenuSeparator, {}),
651
1064
  /* @__PURE__ */ jsxRuntime.jsx(
652
- MenuAction,
1065
+ MenuAction2,
653
1066
  {
654
1067
  label: "\u5220\u9664\u5B57\u6BB5",
655
1068
  danger: true,
@@ -658,7 +1071,7 @@ function FieldContextMenu(props) {
658
1071
  }
659
1072
  ),
660
1073
  /* @__PURE__ */ jsxRuntime.jsx(
661
- MenuAction,
1074
+ MenuAction2,
662
1075
  {
663
1076
  label: "\u5B57\u6BB5\u8BBE\u7F6E...",
664
1077
  onClick: () => props.onSettings(state)
@@ -741,7 +1154,7 @@ function FieldSettingsPopup(props) {
741
1154
  }
742
1155
  );
743
1156
  }
744
- function MenuAction(props) {
1157
+ function MenuAction2(props) {
745
1158
  return /* @__PURE__ */ jsxRuntime.jsx(
746
1159
  "button",
747
1160
  {
@@ -1273,6 +1686,7 @@ function ReactPivotTableInner(props, ref) {
1273
1686
  () => customizationOptions?.defaultLayout ?? pivotTable.createEmptyPivotFieldLayout()
1274
1687
  );
1275
1688
  const [fieldOverrides, setFieldOverrides] = react.useState({});
1689
+ const [densityOverride, setDensityOverride] = react.useState(null);
1276
1690
  const [filterRequest, setFilterRequest] = react.useState(null);
1277
1691
  const [contextMenuRequest, setContextMenuRequest] = react.useState(null);
1278
1692
  const [tooltipRequest, setTooltipRequest] = react.useState(null);
@@ -1316,7 +1730,9 @@ function ReactPivotTableInner(props, ref) {
1316
1730
  indicator: {
1317
1731
  ...field.indicator,
1318
1732
  title: override.title ?? field.indicator?.title,
1319
- aggregator: override.aggregator ?? field.indicator?.aggregator
1733
+ aggregator: override.aggregator ?? field.indicator?.aggregator,
1734
+ precision: "precision" in override ? override.precision : field.indicator?.precision,
1735
+ dataFormat: "dataFormat" in override ? override.dataFormat : field.indicator?.dataFormat
1320
1736
  }
1321
1737
  };
1322
1738
  }),
@@ -1326,6 +1742,20 @@ function ReactPivotTableInner(props, ref) {
1326
1742
  () => customizationEnabled ? pivotTable.resolvePivotFieldLayoutOptions(fields, fieldLayout) : null,
1327
1743
  [customizationEnabled, fieldLayout, fields]
1328
1744
  );
1745
+ const overriddenIndicators = react.useMemo(
1746
+ () => tableOptions.indicators.map((indicator) => {
1747
+ const override = fieldOverrides[indicator.key];
1748
+ if (!override) return indicator;
1749
+ return {
1750
+ ...indicator,
1751
+ title: override.title ?? indicator.title,
1752
+ aggregator: override.aggregator ?? indicator.aggregator,
1753
+ precision: "precision" in override ? override.precision : indicator.precision,
1754
+ dataFormat: "dataFormat" in override ? override.dataFormat : indicator.dataFormat
1755
+ };
1756
+ }),
1757
+ [fieldOverrides, tableOptions.indicators]
1758
+ );
1329
1759
  const refreshChartModel = () => {
1330
1760
  const nextModel = tableRef.current?.getPivotModel() ?? null;
1331
1761
  setChartModel((current) => current === nextModel ? current : nextModel);
@@ -1333,9 +1763,31 @@ function ReactPivotTableInner(props, ref) {
1333
1763
  const options = {
1334
1764
  ...tableOptions,
1335
1765
  ...customizedOptions,
1766
+ rowHeight: densityOverride == null ? tableOptions.rowHeight : resolveDensityRowHeight(densityOverride),
1767
+ indicators: customizedOptions?.indicators ?? overriddenIndicators,
1336
1768
  ui: {
1337
1769
  onFilterPanelRequest: setFilterRequest,
1338
- onContextMenuRequest: setContextMenuRequest,
1770
+ onContextMenuRequest: (request) => {
1771
+ if (request) {
1772
+ const nativeChangeDensity = request.onChangeDensity;
1773
+ const fieldKey = request.indicatorKey;
1774
+ const enhancedRequest = {
1775
+ ...request,
1776
+ onChangeDensity: (density) => {
1777
+ nativeChangeDensity?.(density);
1778
+ setDensityOverride(density);
1779
+ },
1780
+ onChangeDataFormat: fieldKey == null ? void 0 : (dataFormat) => updateField(fieldKey, { dataFormat })
1781
+ };
1782
+ if (request.target === "summary" && fieldKey != null) {
1783
+ enhancedRequest.onChangeSummaryAggregator = (aggregator) => updateField(fieldKey, { aggregator });
1784
+ enhancedRequest.onChangeSummaryPrecision = (precision) => updateField(fieldKey, { precision });
1785
+ }
1786
+ setContextMenuRequest(enhancedRequest);
1787
+ return;
1788
+ }
1789
+ setContextMenuRequest(null);
1790
+ },
1339
1791
  onTooltipRequest: setTooltipRequest
1340
1792
  },
1341
1793
  onFilterChange: (event) => {
@@ -1389,7 +1841,7 @@ function ReactPivotTableInner(props, ref) {
1389
1841
  const removeField = (fieldKey) => {
1390
1842
  applyLayout(pivotTable.removePivotField(fieldLayout, fieldKey));
1391
1843
  };
1392
- const updateField = (fieldKey, patch) => {
1844
+ function updateField(fieldKey, patch) {
1393
1845
  setFieldOverrides((current) => ({
1394
1846
  ...current,
1395
1847
  [fieldKey]: { ...current[fieldKey], ...patch }
@@ -1404,11 +1856,13 @@ function ReactPivotTableInner(props, ref) {
1404
1856
  indicator: {
1405
1857
  ...field.indicator,
1406
1858
  title: patch.title ?? field.indicator?.title,
1407
- aggregator: patch.aggregator ?? field.indicator?.aggregator
1859
+ aggregator: patch.aggregator ?? field.indicator?.aggregator,
1860
+ precision: "precision" in patch ? patch.precision : field.indicator?.precision,
1861
+ dataFormat: "dataFormat" in patch ? patch.dataFormat : field.indicator?.dataFormat
1408
1862
  }
1409
1863
  });
1410
1864
  }
1411
- };
1865
+ }
1412
1866
  react.useEffect(() => {
1413
1867
  const container = containerRef.current;
1414
1868
  if (!container) return;
@@ -1590,6 +2044,13 @@ function ReactPivotTableInner(props, ref) {
1590
2044
  /* @__PURE__ */ jsxRuntime.jsx(PivotTooltip, { request: tooltipRequest })
1591
2045
  ] });
1592
2046
  }
2047
+ function resolveDensityRowHeight(density) {
2048
+ if (density === "comfortable") return 56;
2049
+ if (density === "middle") return 48;
2050
+ if (density === "compact") return 32;
2051
+ if (density === "ultra-compact") return 26;
2052
+ return void 0;
2053
+ }
1593
2054
  var ReactPivotTable = react.forwardRef(ReactPivotTableInner);
1594
2055
  function toSharedFilterRequest(request, onValueChange) {
1595
2056
  if (!request) return null;