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

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.js CHANGED
@@ -1,79 +1,242 @@
1
- import { forwardRef, useRef, useState, useMemo, useEffect, useImperativeHandle } from 'react';
2
- import { createEmptyPivotFieldLayout, createPivotFieldCatalog, resolvePivotDimensionKey, resolvePivotFieldLayoutOptions, PivotTable, loadPivotFieldLayout, getValueByDataIndex, resolvePivotDimensionTitle, findPivotFieldArea, removePivotField, movePivotField, resolvePivotValueFieldTitle, savePivotFieldLayout, createPivotCellKey } from '@canvas-components/pivot-table';
1
+ import { createContext, forwardRef, useMemo, useRef, useState, useEffect, useImperativeHandle, useContext, Fragment as Fragment$1 } from 'react';
2
+ import { createEmptyPivotFieldLayout, createPivotFieldCatalog, resolvePivotDimensionKey, resolvePivotFieldLayoutOptions, PivotTable, loadPivotFieldLayout, DEFAULT_PIVOT_TABLE_DEBUG_OPTIONS, getValueByDataIndex, resolvePivotDimensionTitle, findPivotFieldArea, removePivotField, movePivotField, resolvePivotValueFieldTitle, savePivotFieldLayout, createPivotCellKey } from '@canvas-components/pivot-table';
3
3
  import { ReactResizablePanels, ReactFilterPanel, ReactPopup, ReactCheckbox, ReactInput, ReactSelect, ReactInputNumber } from '@canvas-components/react-components';
4
4
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
5
5
  import { createPortal } from 'react-dom';
6
6
  import { CanvasChart } from '@canvas-components/chart';
7
7
 
8
8
  // src/components/react-pivot-table.tsx
9
+
10
+ // #style-inject:#style-inject
11
+ function styleInject(css, { insertAt } = {}) {
12
+ if (!css || typeof document === "undefined") return;
13
+ const head = document.head || document.getElementsByTagName("head")[0];
14
+ const style = document.createElement("style");
15
+ style.type = "text/css";
16
+ if (insertAt === "top") {
17
+ if (head.firstChild) {
18
+ head.insertBefore(style, head.firstChild);
19
+ } else {
20
+ head.appendChild(style);
21
+ }
22
+ } else {
23
+ head.appendChild(style);
24
+ }
25
+ if (style.styleSheet) {
26
+ style.styleSheet.cssText = css;
27
+ } else {
28
+ style.appendChild(document.createTextNode(css));
29
+ }
30
+ }
31
+
32
+ // src/features/context-menu/pivot-context-menu.css
33
+ 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");
34
+ var CONTEXT_MENU_SURFACE_STYLE = {
35
+ padding: 8,
36
+ background: "#ffffff",
37
+ boxShadow: "0 8px 24px rgba(15, 23, 42, 0.16)"
38
+ };
9
39
  function PivotContextMenu(props) {
10
40
  const { request } = props;
41
+ const [menuOpen, setMenuOpen] = useState(true);
42
+ useEffect(() => {
43
+ if (request) setMenuOpen(true);
44
+ }, [request]);
11
45
  if (!request) return null;
12
46
  return /* @__PURE__ */ jsx(
13
47
  ReactPopup,
14
48
  {
15
- open: true,
49
+ open: menuOpen,
16
50
  anchorRect: { x: request.x, y: request.y, width: 0, height: 0 },
17
51
  offset: 4,
18
52
  matchAnchorWidth: false,
19
- minWidth: 180,
53
+ minWidth: 260,
20
54
  onOpenChange: (open) => {
55
+ setMenuOpen(open);
21
56
  if (!open) request.onClose();
22
57
  },
23
- surfaceStyle: { padding: 6 },
24
- children: /* @__PURE__ */ jsxs("div", { style: { display: "grid", minWidth: 180 }, children: [
58
+ surfaceStyle: { ...CONTEXT_MENU_SURFACE_STYLE, width: 260 },
59
+ children: /* @__PURE__ */ jsxs("div", { children: [
60
+ request.title ? /* @__PURE__ */ jsx("div", { style: { padding: "6px 10px", color: "#8f959e", fontSize: 12 }, children: request.title }) : null,
25
61
  /* @__PURE__ */ jsx(
26
- MenuButton,
62
+ MenuSubmenu,
27
63
  {
28
- label: "\u590D\u5236\u5355\u5143\u683C",
29
- onClick: request.onCopy,
30
- close: request.onClose
64
+ label: "\u590D\u5236",
65
+ items: [
66
+ {
67
+ key: "copy-cell",
68
+ label: request.target === "header" ? "\u590D\u5236\u8868\u5934" : "\u590D\u5236\u5355\u5143\u683C",
69
+ onClick: request.onCopy
70
+ },
71
+ {
72
+ key: "copy-selection",
73
+ label: "\u590D\u5236\u9009\u533A",
74
+ onClick: request.target === "header" ? void 0 : request.onCopySelection
75
+ }
76
+ ],
77
+ children: request.target !== "header" ? /* @__PURE__ */ jsx(CustomSelectionMenu, { request }) : null
31
78
  }
32
79
  ),
33
- request.onCopySelection ? /* @__PURE__ */ jsx(
34
- MenuButton,
35
- {
36
- label: "\u590D\u5236\u9009\u533A",
37
- onClick: request.onCopySelection,
38
- close: request.onClose
39
- }
40
- ) : null,
41
- /* @__PURE__ */ jsx(
42
- CustomSelectionMenu,
80
+ request.target === "header" ? /* @__PURE__ */ jsx(HeaderMenu, { request }) : null,
81
+ request.target === "summary" ? /* @__PURE__ */ jsx(
82
+ SummaryMenu,
43
83
  {
44
84
  request
45
85
  },
46
- `${request.x}-${request.y}`
47
- ),
48
- /* @__PURE__ */ jsx(
49
- MenuButton,
50
- {
51
- label: "\u5BFC\u51FA CSV",
52
- onClick: request.onExportCsv,
53
- close: request.onClose
54
- }
55
- ),
86
+ `${request.indicatorKey}-${request.x}-${request.y}`
87
+ ) : null,
88
+ /* @__PURE__ */ jsx(DataFormatMenu, { request }),
89
+ /* @__PURE__ */ jsx(DensityMenu, { request }),
56
90
  /* @__PURE__ */ jsx(
57
- MenuButton,
91
+ MenuSubmenu,
58
92
  {
59
- label: "\u5BFC\u51FA XLSX",
60
- onClick: request.onExportXlsx,
61
- close: request.onClose
93
+ label: "\u5BFC\u51FA",
94
+ items: [
95
+ {
96
+ key: "export-csv",
97
+ label: "\u5BFC\u51FA CSV",
98
+ onClick: request.onExportCsv
99
+ },
100
+ {
101
+ key: "export-xlsx",
102
+ label: "\u5BFC\u51FA XLSX",
103
+ onClick: request.onExportXlsx
104
+ }
105
+ ]
62
106
  }
63
107
  ),
64
- /* @__PURE__ */ jsxs("div", { style: { padding: "8px 10px", color: "#8f959e", fontSize: 12 }, children: [
108
+ request.recordCount != null ? /* @__PURE__ */ jsxs("div", { style: { padding: "8px 10px", color: "#8f959e", fontSize: 12 }, children: [
65
109
  "\u4E0B\u94BB\u8BB0\u5F55 ",
66
110
  request.recordCount,
67
111
  " \u6761"
68
- ] })
112
+ ] }) : null
69
113
  ] })
70
114
  }
71
115
  );
72
116
  }
117
+ function HeaderMenu(props) {
118
+ const { request } = props;
119
+ const hasSort = request.onSortAsc || request.onSortDesc || request.onClearSort;
120
+ const hasExpand = request.onExpand || request.onCollapse || request.onExpandAll || request.onCollapseAll;
121
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
122
+ hasSort ? /* @__PURE__ */ jsx(
123
+ MenuSubmenu,
124
+ {
125
+ label: "\u6392\u5E8F",
126
+ items: [
127
+ {
128
+ key: "sort-asc",
129
+ label: "\u5347\u5E8F",
130
+ selected: request.sortDirection === "asc",
131
+ onClick: request.onSortAsc
132
+ },
133
+ {
134
+ key: "sort-desc",
135
+ label: "\u964D\u5E8F",
136
+ selected: request.sortDirection === "desc",
137
+ onClick: request.onSortDesc
138
+ },
139
+ {
140
+ key: "sort-clear",
141
+ label: "\u53D6\u6D88\u6392\u5E8F",
142
+ onClick: request.onClearSort
143
+ }
144
+ ]
145
+ }
146
+ ) : null,
147
+ request.onOpenFilter ? /* @__PURE__ */ jsx(MenuAction, { label: "\u6253\u5F00\u7B5B\u9009\u9762\u677F", onClick: request.onOpenFilter }) : null,
148
+ hasExpand ? /* @__PURE__ */ jsx(
149
+ MenuSubmenu,
150
+ {
151
+ label: "\u5C55\u5F00/\u6298\u53E0",
152
+ items: [
153
+ {
154
+ key: "toggle-current",
155
+ label: request.expanded ? "\u6298\u53E0\u5F53\u524D\u9879" : "\u5C55\u5F00\u5F53\u524D\u9879",
156
+ onClick: request.expanded ? request.onCollapse : request.onExpand
157
+ },
158
+ {
159
+ key: "expand-all",
160
+ label: "\u5168\u90E8\u5C55\u5F00",
161
+ onClick: request.onExpandAll
162
+ },
163
+ {
164
+ key: "collapse-all",
165
+ label: "\u5168\u90E8\u6298\u53E0",
166
+ onClick: request.onCollapseAll
167
+ }
168
+ ]
169
+ }
170
+ ) : null
171
+ ] });
172
+ }
173
+ function SummaryMenu(props) {
174
+ const { request } = props;
175
+ const [precision, setPrecision] = useState(
176
+ request.summaryPrecision ?? null
177
+ );
178
+ const aggregators = [
179
+ ["sum", "\u6C42\u548C"],
180
+ ["avg", "\u5E73\u5747\u503C"],
181
+ ["count", "\u8BA1\u6570"],
182
+ ["distinctCount", "\u53BB\u91CD\u8BA1\u6570"],
183
+ ["min", "\u6700\u5C0F\u503C"],
184
+ ["max", "\u6700\u5927\u503C"]
185
+ ];
186
+ if (!request.onChangeSummaryAggregator) return null;
187
+ return /* @__PURE__ */ jsx(
188
+ MenuSubmenu,
189
+ {
190
+ label: "\u6C47\u603B\u65B9\u5F0F",
191
+ items: aggregators.map(([value, label]) => ({
192
+ key: `summary-${value}`,
193
+ label,
194
+ selected: request.summaryAggregator === value,
195
+ onClick: () => {
196
+ request.onChangeSummaryAggregator?.(value);
197
+ request.onClose();
198
+ }
199
+ })),
200
+ footer: request.onChangeSummaryPrecision ? /* @__PURE__ */ jsxs(
201
+ "div",
202
+ {
203
+ style: {
204
+ display: "grid",
205
+ gridTemplateColumns: "72px 1fr",
206
+ gap: 8,
207
+ alignItems: "center",
208
+ marginTop: 4,
209
+ padding: "10px 10px 4px",
210
+ borderTop: "1px solid #e5e7eb"
211
+ },
212
+ children: [
213
+ /* @__PURE__ */ jsx("span", { style: { color: "#374151", fontSize: 13 }, children: "\u5C0F\u6570\u4F4D\u6570" }),
214
+ /* @__PURE__ */ jsx(
215
+ ReactInputNumber,
216
+ {
217
+ value: precision,
218
+ min: 0,
219
+ max: 20,
220
+ step: 1,
221
+ precision: 0,
222
+ placeholder: "\u81EA\u52A8",
223
+ onChange: (value) => {
224
+ setPrecision(value);
225
+ request.onChangeSummaryPrecision?.(value ?? void 0);
226
+ }
227
+ }
228
+ )
229
+ ]
230
+ }
231
+ ) : null
232
+ }
233
+ );
234
+ }
235
+ function MenuDivider() {
236
+ return /* @__PURE__ */ jsx("div", { style: { height: 1, margin: "6px 0", background: "#f0f0f0" } });
237
+ }
73
238
  function CustomSelectionMenu(props) {
74
239
  const { request } = props;
75
- const triggerRef = useRef(null);
76
- const [open, setOpen] = useState(false);
77
240
  const [range, setRange] = useState(
78
241
  request.customSelection ?? {
79
242
  startRow: 1,
@@ -91,104 +254,79 @@ function CustomSelectionMenu(props) {
91
254
  [key]: value == null ? 1 : Math.floor(value)
92
255
  }));
93
256
  };
94
- return /* @__PURE__ */ jsxs("div", { children: [
257
+ return /* @__PURE__ */ jsx(MenuSubmenu, { label: "\u590D\u5236\u81EA\u5B9A\u4E49\u9009\u533A", items: [], minWidth: 250, children: /* @__PURE__ */ jsxs("div", { style: { padding: 6 }, children: [
258
+ /* @__PURE__ */ jsx("div", { style: { color: "#6b7280", fontSize: 12, marginBottom: 6 }, children: "\u8F93\u5165\u8D77\u59CB\u4F4D\u7F6E\u548C\u7ED3\u675F\u4F4D\u7F6E" }),
259
+ /* @__PURE__ */ jsxs(
260
+ "div",
261
+ {
262
+ style: {
263
+ display: "grid",
264
+ gridTemplateColumns: "38px 1fr 1fr",
265
+ gap: 6,
266
+ marginBottom: 4,
267
+ color: "#6b7280",
268
+ fontSize: 12,
269
+ textAlign: "center"
270
+ },
271
+ children: [
272
+ /* @__PURE__ */ jsx("span", {}),
273
+ /* @__PURE__ */ jsx("span", { children: "\u884C" }),
274
+ /* @__PURE__ */ jsx("span", { children: "\u5217" })
275
+ ]
276
+ }
277
+ ),
95
278
  /* @__PURE__ */ jsx(
96
- "button",
279
+ CustomSelectionRow,
97
280
  {
98
- ref: triggerRef,
99
- type: "button",
100
- onClick: () => setOpen((value) => !value),
101
- style: menuButtonStyle,
102
- children: "\u590D\u5236\u81EA\u5B9A\u4E49\u9009\u533A"
281
+ label: "\u8D77\u59CB",
282
+ row: range.startRow,
283
+ column: range.startColumn,
284
+ maxRow: range.rowCount,
285
+ maxColumn: range.columnCount,
286
+ onRowChange: (value) => update("startRow", value),
287
+ onColumnChange: (value) => update("startColumn", value)
103
288
  }
104
289
  ),
105
290
  /* @__PURE__ */ jsx(
106
- ReactPopup,
291
+ CustomSelectionRow,
107
292
  {
108
- open,
109
- anchorRef: triggerRef,
110
- placement: "rightTop",
111
- offset: 2,
112
- minWidth: 250,
113
- onOpenChange: setOpen,
114
- surfaceStyle: { padding: 6, width: 250 },
115
- children: /* @__PURE__ */ jsxs("div", { style: { padding: 6 }, children: [
116
- /* @__PURE__ */ jsx("div", { style: { color: "#6b7280", fontSize: 12, marginBottom: 6 }, children: "\u8F93\u5165\u8D77\u59CB\u4F4D\u7F6E\u548C\u7ED3\u675F\u4F4D\u7F6E" }),
117
- /* @__PURE__ */ jsxs(
118
- "div",
119
- {
120
- style: {
121
- display: "grid",
122
- gridTemplateColumns: "38px 1fr 1fr",
123
- gap: 6,
124
- marginBottom: 4,
125
- color: "#6b7280",
126
- fontSize: 12,
127
- textAlign: "center"
128
- },
129
- children: [
130
- /* @__PURE__ */ jsx("span", {}),
131
- /* @__PURE__ */ jsx("span", { children: "\u884C" }),
132
- /* @__PURE__ */ jsx("span", { children: "\u5217" })
133
- ]
134
- }
135
- ),
136
- /* @__PURE__ */ jsx(
137
- CustomSelectionRow,
138
- {
139
- label: "\u8D77\u59CB",
140
- row: range.startRow,
141
- column: range.startColumn,
142
- maxRow: range.rowCount,
143
- maxColumn: range.columnCount,
144
- onRowChange: (value) => update("startRow", value),
145
- onColumnChange: (value) => update("startColumn", value)
146
- }
147
- ),
148
- /* @__PURE__ */ jsx(
149
- CustomSelectionRow,
150
- {
151
- label: "\u7ED3\u675F",
152
- row: range.endRow,
153
- column: range.endColumn,
154
- maxRow: range.rowCount,
155
- maxColumn: range.columnCount,
156
- onRowChange: (value) => update("endRow", value),
157
- onColumnChange: (value) => update("endColumn", value)
158
- }
159
- ),
160
- /* @__PURE__ */ jsx(
161
- "button",
162
- {
163
- type: "button",
164
- style: {
165
- display: "block",
166
- width: "100%",
167
- height: 32,
168
- marginTop: 6,
169
- border: "none",
170
- borderRadius: 4,
171
- background: "#1677ff",
172
- color: "#fff",
173
- cursor: "pointer"
174
- },
175
- onClick: () => {
176
- request.onCopyCustomSelection?.({
177
- startRow: range.startRow,
178
- startColumn: range.startColumn,
179
- endRow: range.endRow,
180
- endColumn: range.endColumn
181
- });
182
- setOpen(false);
183
- request.onClose();
184
- },
185
- children: "\u590D\u5236"
186
- }
187
- )
188
- ] })
293
+ label: "\u7ED3\u675F",
294
+ row: range.endRow,
295
+ column: range.endColumn,
296
+ maxRow: range.rowCount,
297
+ maxColumn: range.columnCount,
298
+ onRowChange: (value) => update("endRow", value),
299
+ onColumnChange: (value) => update("endColumn", value)
300
+ }
301
+ ),
302
+ /* @__PURE__ */ jsx(
303
+ "button",
304
+ {
305
+ type: "button",
306
+ style: {
307
+ display: "block",
308
+ width: "100%",
309
+ height: 32,
310
+ marginTop: 6,
311
+ border: "none",
312
+ borderRadius: 4,
313
+ background: "#1677ff",
314
+ color: "#fff",
315
+ cursor: "pointer"
316
+ },
317
+ onClick: () => {
318
+ request.onCopyCustomSelection?.({
319
+ startRow: range.startRow,
320
+ startColumn: range.startColumn,
321
+ endRow: range.endRow,
322
+ endColumn: range.endColumn
323
+ });
324
+ request.onClose();
325
+ },
326
+ children: "\u590D\u5236"
189
327
  }
190
328
  )
191
- ] });
329
+ ] }) });
192
330
  }
193
331
  function CustomSelectionRow(props) {
194
332
  return /* @__PURE__ */ jsxs(
@@ -231,27 +369,324 @@ function CustomSelectionRow(props) {
231
369
  }
232
370
  );
233
371
  }
234
- var menuButtonStyle = {
235
- height: 34,
236
- padding: "0 10px",
237
- border: 0,
238
- borderRadius: 4,
239
- background: "transparent",
240
- color: "#1f2329",
241
- textAlign: "left",
242
- cursor: "pointer"
243
- };
244
- function MenuButton(props) {
245
- return /* @__PURE__ */ jsx(
372
+ function MenuAction(props) {
373
+ const { label, preview, onClick, selected, disabled, reserveSelectionIcon } = props;
374
+ if (!onClick && !disabled) return null;
375
+ return /* @__PURE__ */ jsxs(
246
376
  "button",
247
377
  {
248
378
  type: "button",
249
- onClick: () => {
250
- props.onClick();
251
- props.close();
379
+ onClick: disabled ? void 0 : onClick,
380
+ disabled,
381
+ className: "react-pivot-table-menu-action",
382
+ style: {
383
+ display: "flex",
384
+ alignItems: "center",
385
+ width: "100%",
386
+ height: 32,
387
+ padding: "0 10px",
388
+ border: "none",
389
+ borderRadius: 8,
390
+ background: "transparent",
391
+ color: disabled ? "#9ca3af" : "#374151",
392
+ textAlign: "left",
393
+ cursor: disabled ? "default" : "pointer"
252
394
  },
253
- style: menuButtonStyle,
254
- children: props.label
395
+ children: [
396
+ reserveSelectionIcon ? /* @__PURE__ */ jsx(
397
+ "span",
398
+ {
399
+ "aria-hidden": "true",
400
+ style: {
401
+ width: 16,
402
+ flex: "0 0 16px",
403
+ marginRight: 6,
404
+ textAlign: "center"
405
+ },
406
+ children: selected ? "\u2713" : ""
407
+ }
408
+ ) : null,
409
+ /* @__PURE__ */ jsx("span", { style: { flex: 1, whiteSpace: "nowrap" }, children: label }),
410
+ preview ? /* @__PURE__ */ jsx(
411
+ "span",
412
+ {
413
+ style: { marginLeft: 16, color: "#9ca3af", whiteSpace: "nowrap" },
414
+ children: preview
415
+ }
416
+ ) : null
417
+ ]
418
+ }
419
+ );
420
+ }
421
+ function MenuSubmenu(props) {
422
+ const { label, items, footer, children, minWidth = 220 } = props;
423
+ const menuItems = items.filter((item) => item.onClick || item.disabled);
424
+ const reserveSelectionIcon = menuItems.some(
425
+ (item) => typeof item.selected === "boolean"
426
+ );
427
+ const triggerRef = useRef(null);
428
+ const [open, setOpen] = useState(false);
429
+ const closeTimerRef = useRef(null);
430
+ if (!menuItems.length && !footer && !children) return null;
431
+ const clearCloseTimer = () => {
432
+ if (closeTimerRef.current != null) {
433
+ window.clearTimeout(closeTimerRef.current);
434
+ closeTimerRef.current = null;
435
+ }
436
+ };
437
+ const scheduleClose = () => {
438
+ clearCloseTimer();
439
+ closeTimerRef.current = window.setTimeout(() => {
440
+ setOpen(false);
441
+ closeTimerRef.current = null;
442
+ }, 120);
443
+ };
444
+ return /* @__PURE__ */ jsxs(
445
+ "div",
446
+ {
447
+ onMouseEnter: () => {
448
+ clearCloseTimer();
449
+ setOpen(true);
450
+ },
451
+ onMouseLeave: scheduleClose,
452
+ children: [
453
+ /* @__PURE__ */ jsxs(
454
+ "button",
455
+ {
456
+ ref: triggerRef,
457
+ type: "button",
458
+ onClick: () => setOpen((value) => !value),
459
+ className: "react-pivot-table-menu-action react-pivot-table-menu-action-submenu",
460
+ style: {
461
+ display: "flex",
462
+ alignItems: "center",
463
+ justifyContent: "space-between",
464
+ width: "100%",
465
+ height: 32,
466
+ padding: "0 10px",
467
+ border: "none",
468
+ borderRadius: 8,
469
+ background: "transparent",
470
+ color: "#374151",
471
+ textAlign: "left",
472
+ cursor: "pointer"
473
+ },
474
+ children: [
475
+ /* @__PURE__ */ jsx("span", { children: label }),
476
+ /* @__PURE__ */ jsx(
477
+ "span",
478
+ {
479
+ className: `react-pivot-table-menu-chevron${open ? " react-pivot-table-menu-chevron-active" : ""}`,
480
+ "aria-hidden": "true"
481
+ }
482
+ )
483
+ ]
484
+ }
485
+ ),
486
+ /* @__PURE__ */ jsx(
487
+ ReactPopup,
488
+ {
489
+ open,
490
+ anchorRef: triggerRef,
491
+ placement: "rightTop",
492
+ offset: 2,
493
+ minWidth,
494
+ onOpenChange: setOpen,
495
+ surfaceStyle: { ...CONTEXT_MENU_SURFACE_STYLE, width: minWidth },
496
+ children: /* @__PURE__ */ jsxs("div", { onMouseEnter: clearCloseTimer, onMouseLeave: scheduleClose, children: [
497
+ menuItems.map((item) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
498
+ item.separatorBefore ? /* @__PURE__ */ jsx(MenuDivider, {}) : null,
499
+ /* @__PURE__ */ jsx(
500
+ MenuAction,
501
+ {
502
+ label: item.label,
503
+ preview: item.preview,
504
+ selected: item.selected,
505
+ disabled: item.disabled,
506
+ onClick: item.onClick,
507
+ reserveSelectionIcon
508
+ }
509
+ )
510
+ ] }, item.key)),
511
+ children,
512
+ footer
513
+ ] })
514
+ }
515
+ )
516
+ ]
517
+ }
518
+ );
519
+ }
520
+ function DensityMenu(props) {
521
+ const { request } = props;
522
+ if (!request.onChangeDensity) return null;
523
+ return /* @__PURE__ */ jsx(
524
+ MenuSubmenu,
525
+ {
526
+ label: "\u8868\u683C\u5BC6\u5EA6",
527
+ items: [
528
+ {
529
+ key: "density-comfortable",
530
+ label: "\u5BBD\u677E",
531
+ selected: request.density === "comfortable",
532
+ onClick: () => request.onChangeDensity?.("comfortable")
533
+ },
534
+ {
535
+ key: "density-middle",
536
+ label: "\u4E2D\u7B49",
537
+ selected: request.density === "middle",
538
+ onClick: () => request.onChangeDensity?.("middle")
539
+ },
540
+ {
541
+ key: "density-compact",
542
+ label: "\u7D27\u51D1",
543
+ selected: request.density === "compact",
544
+ onClick: () => request.onChangeDensity?.("compact")
545
+ },
546
+ {
547
+ key: "density-ultra-compact",
548
+ label: "\u8D85\u7D27\u51D1",
549
+ selected: request.density === "ultra-compact",
550
+ onClick: () => request.onChangeDensity?.("ultra-compact")
551
+ },
552
+ {
553
+ key: "density-auto",
554
+ label: "\u81EA\u9002\u5E94",
555
+ selected: request.density === "auto",
556
+ onClick: () => request.onChangeDensity?.("auto")
557
+ }
558
+ ]
559
+ }
560
+ );
561
+ }
562
+ function DataFormatMenu(props) {
563
+ const { request } = props;
564
+ if (!request.onChangeDataFormat) return null;
565
+ const formats = [
566
+ { key: "default", label: "\u5E38\u89C4", value: "default" },
567
+ { key: "text", label: "\u7EAF\u6587\u672C", value: "text" },
568
+ {
569
+ key: "number",
570
+ label: "\u6570\u5B57",
571
+ preview: "1024",
572
+ value: "number",
573
+ separatorBefore: true
574
+ },
575
+ {
576
+ key: "thousands",
577
+ label: "\u6570\u5B57\uFF08\u5343\u5206\u4F4D\uFF09",
578
+ preview: "1,024",
579
+ value: "thousands"
580
+ },
581
+ {
582
+ key: "decimal",
583
+ label: "\u6570\u5B57\uFF08\u5343\u5206\u4F4D\uFF0C\u5C0F\u6570\u70B9\uFF09",
584
+ preview: "1,024.56",
585
+ value: "decimal"
586
+ },
587
+ {
588
+ key: "percent",
589
+ label: "\u767E\u5206\u6BD4",
590
+ preview: "10%",
591
+ value: "percent",
592
+ separatorBefore: true
593
+ },
594
+ {
595
+ key: "percentDecimal",
596
+ label: "\u767E\u5206\u6BD4\uFF08\u5C0F\u6570\u70B9\uFF09",
597
+ preview: "10.24%",
598
+ value: "percentDecimal"
599
+ },
600
+ {
601
+ key: "scientific",
602
+ label: "\u79D1\u5B66\u8BB0\u6570",
603
+ preview: "1.02E+003",
604
+ value: "scientific"
605
+ },
606
+ {
607
+ key: "numberToChineseUpper",
608
+ label: "\u6570\u5B57\u8F6C\u5927\u5199",
609
+ preview: "\u7396\u62FE\u58F9\u4E07\u634C\u4EDF",
610
+ value: "numberToChineseUpper"
611
+ },
612
+ {
613
+ key: "chineseUpperToNumber",
614
+ label: "\u5927\u5199\u8F6C\u6570\u5B57",
615
+ preview: "918000",
616
+ value: "chineseUpperToNumber"
617
+ },
618
+ {
619
+ key: "cny",
620
+ label: "\u4EBA\u6C11\u5E01",
621
+ preview: "\xA51,024",
622
+ value: "cny",
623
+ separatorBefore: true
624
+ },
625
+ {
626
+ key: "cnyDecimal",
627
+ label: "\u4EBA\u6C11\u5E01\uFF08\u5C0F\u6570\u70B9\uFF09",
628
+ preview: "\xA51,024.56",
629
+ value: "cnyDecimal"
630
+ },
631
+ { key: "usd", label: "\u7F8E\u5143", preview: "$1,024", value: "usd" },
632
+ {
633
+ key: "usdDecimal",
634
+ label: "\u7F8E\u5143\uFF08\u5C0F\u6570\u70B9\uFF09",
635
+ preview: "$1,024.56",
636
+ value: "usdDecimal"
637
+ },
638
+ {
639
+ key: "dateSlash",
640
+ label: "\u65E5\u671F\uFF08\u659C\u6760\uFF09",
641
+ preview: "2017/08/01",
642
+ value: "dateSlash",
643
+ separatorBefore: true
644
+ },
645
+ {
646
+ key: "dateDash",
647
+ label: "\u65E5\u671F\uFF08\u77ED\u6A2A\u7EBF\uFF09",
648
+ preview: "2017-08-01",
649
+ value: "dateDash"
650
+ },
651
+ {
652
+ key: "dateFullCN",
653
+ label: "\u65E5\u671F\uFF08\u4E2D\u6587\uFF09",
654
+ preview: "2017\u5E748\u67081\u65E5",
655
+ value: "dateFullCN"
656
+ },
657
+ { key: "time", label: "\u65F6\u95F4", preview: "23:24:25", value: "time" },
658
+ {
659
+ key: "timeShort",
660
+ label: "\u65F6\u95F4\uFF08\u5206\uFF09",
661
+ preview: "23:24",
662
+ value: "timeShort"
663
+ },
664
+ {
665
+ key: "datetime",
666
+ label: "\u65E5\u671F\u65F6\u95F4",
667
+ preview: "2017/08/01 23:24:25",
668
+ value: "datetime"
669
+ },
670
+ {
671
+ key: "datetime12",
672
+ label: "\u65E5\u671F\u65F6\u95F4\uFF08\u4E0A\u4E0B\uFF09",
673
+ preview: "2017/08/01 \u4E0B\u534811:24",
674
+ value: "datetime12"
675
+ }
676
+ ];
677
+ return /* @__PURE__ */ jsx(
678
+ MenuSubmenu,
679
+ {
680
+ label: "\u683C\u5F0F",
681
+ minWidth: 340,
682
+ items: formats.map((item) => ({
683
+ key: `data-format-${item.key}`,
684
+ label: item.label,
685
+ preview: "preview" in item ? item.preview : void 0,
686
+ separatorBefore: "separatorBefore" in item ? item.separatorBefore : void 0,
687
+ selected: request.dataFormat === item.value,
688
+ onClick: () => request.onChangeDataFormat?.(item.value)
689
+ }))
255
690
  }
256
691
  );
257
692
  }
@@ -286,28 +721,6 @@ function PivotTooltip(props) {
286
721
  );
287
722
  }
288
723
 
289
- // #style-inject:#style-inject
290
- function styleInject(css, { insertAt } = {}) {
291
- if (!css || typeof document === "undefined") return;
292
- const head = document.head || document.getElementsByTagName("head")[0];
293
- const style = document.createElement("style");
294
- style.type = "text/css";
295
- if (insertAt === "top") {
296
- if (head.firstChild) {
297
- head.insertBefore(style, head.firstChild);
298
- } else {
299
- head.appendChild(style);
300
- }
301
- } else {
302
- head.appendChild(style);
303
- }
304
- if (style.styleSheet) {
305
- style.styleSheet.cssText = css;
306
- } else {
307
- style.appendChild(document.createTextNode(css));
308
- }
309
- }
310
-
311
724
  // src/features/field-panel/pivot-field-panel.css
312
725
  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');
313
726
  function PivotFieldPanel(props) {
@@ -573,7 +986,7 @@ function FieldContextMenu(props) {
573
986
  },
574
987
  children: /* @__PURE__ */ jsxs("div", { className: "react-pivot-field-menu", role: "menu", children: [
575
988
  /* @__PURE__ */ jsx(
576
- MenuAction,
989
+ MenuAction2,
577
990
  {
578
991
  label: "\u4E0A\u79FB",
579
992
  disabled: index <= 0,
@@ -582,7 +995,7 @@ function FieldContextMenu(props) {
582
995
  }
583
996
  ),
584
997
  /* @__PURE__ */ jsx(
585
- MenuAction,
998
+ MenuAction2,
586
999
  {
587
1000
  label: "\u4E0B\u79FB",
588
1001
  disabled: index < 0 || index >= keys.length - 1,
@@ -591,7 +1004,7 @@ function FieldContextMenu(props) {
591
1004
  }
592
1005
  ),
593
1006
  /* @__PURE__ */ jsx(
594
- MenuAction,
1007
+ MenuAction2,
595
1008
  {
596
1009
  label: "\u79FB\u81F3\u5F00\u5934",
597
1010
  disabled: index <= 0,
@@ -600,7 +1013,7 @@ function FieldContextMenu(props) {
600
1013
  }
601
1014
  ),
602
1015
  /* @__PURE__ */ jsx(
603
- MenuAction,
1016
+ MenuAction2,
604
1017
  {
605
1018
  label: "\u79FB\u81F3\u672B\u5C3E",
606
1019
  disabled: index === keys.length - 1,
@@ -610,7 +1023,7 @@ function FieldContextMenu(props) {
610
1023
  ),
611
1024
  /* @__PURE__ */ jsx(MenuSeparator, {}),
612
1025
  /* @__PURE__ */ jsx(
613
- MenuAction,
1026
+ MenuAction2,
614
1027
  {
615
1028
  label: "\u6DFB\u52A0\u5230\u62A5\u8868\u7B5B\u9009",
616
1029
  disabled: state.area === "filter",
@@ -619,7 +1032,7 @@ function FieldContextMenu(props) {
619
1032
  }
620
1033
  ),
621
1034
  /* @__PURE__ */ jsx(
622
- MenuAction,
1035
+ MenuAction2,
623
1036
  {
624
1037
  label: "\u6DFB\u52A0\u5230\u884C\u6807\u7B7E",
625
1038
  disabled: state.area === "row",
@@ -628,7 +1041,7 @@ function FieldContextMenu(props) {
628
1041
  }
629
1042
  ),
630
1043
  /* @__PURE__ */ jsx(
631
- MenuAction,
1044
+ MenuAction2,
632
1045
  {
633
1046
  label: "\u6DFB\u52A0\u5230\u5217\u6807\u7B7E",
634
1047
  disabled: state.area === "column",
@@ -637,7 +1050,7 @@ function FieldContextMenu(props) {
637
1050
  }
638
1051
  ),
639
1052
  /* @__PURE__ */ jsx(
640
- MenuAction,
1053
+ MenuAction2,
641
1054
  {
642
1055
  label: "\u79FB\u52A8\u5230\u503C",
643
1056
  disabled: state.area === "value",
@@ -647,7 +1060,7 @@ function FieldContextMenu(props) {
647
1060
  ),
648
1061
  /* @__PURE__ */ jsx(MenuSeparator, {}),
649
1062
  /* @__PURE__ */ jsx(
650
- MenuAction,
1063
+ MenuAction2,
651
1064
  {
652
1065
  label: "\u5220\u9664\u5B57\u6BB5",
653
1066
  danger: true,
@@ -656,7 +1069,7 @@ function FieldContextMenu(props) {
656
1069
  }
657
1070
  ),
658
1071
  /* @__PURE__ */ jsx(
659
- MenuAction,
1072
+ MenuAction2,
660
1073
  {
661
1074
  label: "\u5B57\u6BB5\u8BBE\u7F6E...",
662
1075
  onClick: () => props.onSettings(state)
@@ -739,7 +1152,7 @@ function FieldSettingsPopup(props) {
739
1152
  }
740
1153
  );
741
1154
  }
742
- function MenuAction(props) {
1155
+ function MenuAction2(props) {
743
1156
  return /* @__PURE__ */ jsx(
744
1157
  "button",
745
1158
  {
@@ -1248,8 +1661,31 @@ function PivotChartCanvas(props) {
1248
1661
  }, [props.chartOption]);
1249
1662
  return /* @__PURE__ */ jsx("div", { ref: containerRef, className: "react-pivot-chart-card__canvas" });
1250
1663
  }
1664
+ var ReactPivotTableDebugContext = createContext(false);
1665
+ function ReactPivotTableDebugProvider(props) {
1666
+ return /* @__PURE__ */ jsx(ReactPivotTableDebugContext.Provider, { value: props.enabled, children: props.children });
1667
+ }
1668
+ function useReactPivotTableDebugEnabled() {
1669
+ return useContext(ReactPivotTableDebugContext);
1670
+ }
1671
+ function resolveReactPivotTableDebugOptions(debug, inheritedEnabled) {
1672
+ if (!inheritedEnabled) return debug;
1673
+ return {
1674
+ ...DEFAULT_PIVOT_TABLE_DEBUG_OPTIONS,
1675
+ ...typeof debug === "object" ? debug : null,
1676
+ enabled: true
1677
+ };
1678
+ }
1251
1679
  function ReactPivotTableInner(props, ref) {
1252
1680
  const { className, style, customization, title, ...tableOptions } = props;
1681
+ const inheritedDebugEnabled = useReactPivotTableDebugEnabled();
1682
+ const resolvedDebug = useMemo(
1683
+ () => resolveReactPivotTableDebugOptions(
1684
+ tableOptions.debug,
1685
+ inheritedDebugEnabled
1686
+ ),
1687
+ [inheritedDebugEnabled, tableOptions.debug]
1688
+ );
1253
1689
  const containerRef = useRef(null);
1254
1690
  const tableRef = useRef(null);
1255
1691
  const customizationOptions = customization && typeof customization === "object" ? customization : void 0;
@@ -1271,6 +1707,7 @@ function ReactPivotTableInner(props, ref) {
1271
1707
  () => customizationOptions?.defaultLayout ?? createEmptyPivotFieldLayout()
1272
1708
  );
1273
1709
  const [fieldOverrides, setFieldOverrides] = useState({});
1710
+ const [densityOverride, setDensityOverride] = useState(null);
1274
1711
  const [filterRequest, setFilterRequest] = useState(null);
1275
1712
  const [contextMenuRequest, setContextMenuRequest] = useState(null);
1276
1713
  const [tooltipRequest, setTooltipRequest] = useState(null);
@@ -1314,7 +1751,9 @@ function ReactPivotTableInner(props, ref) {
1314
1751
  indicator: {
1315
1752
  ...field.indicator,
1316
1753
  title: override.title ?? field.indicator?.title,
1317
- aggregator: override.aggregator ?? field.indicator?.aggregator
1754
+ aggregator: override.aggregator ?? field.indicator?.aggregator,
1755
+ precision: "precision" in override ? override.precision : field.indicator?.precision,
1756
+ dataFormat: "dataFormat" in override ? override.dataFormat : field.indicator?.dataFormat
1318
1757
  }
1319
1758
  };
1320
1759
  }),
@@ -1324,6 +1763,20 @@ function ReactPivotTableInner(props, ref) {
1324
1763
  () => customizationEnabled ? resolvePivotFieldLayoutOptions(fields, fieldLayout) : null,
1325
1764
  [customizationEnabled, fieldLayout, fields]
1326
1765
  );
1766
+ const overriddenIndicators = useMemo(
1767
+ () => tableOptions.indicators.map((indicator) => {
1768
+ const override = fieldOverrides[indicator.key];
1769
+ if (!override) return indicator;
1770
+ return {
1771
+ ...indicator,
1772
+ title: override.title ?? indicator.title,
1773
+ aggregator: override.aggregator ?? indicator.aggregator,
1774
+ precision: "precision" in override ? override.precision : indicator.precision,
1775
+ dataFormat: "dataFormat" in override ? override.dataFormat : indicator.dataFormat
1776
+ };
1777
+ }),
1778
+ [fieldOverrides, tableOptions.indicators]
1779
+ );
1327
1780
  const refreshChartModel = () => {
1328
1781
  const nextModel = tableRef.current?.getPivotModel() ?? null;
1329
1782
  setChartModel((current) => current === nextModel ? current : nextModel);
@@ -1331,9 +1784,32 @@ function ReactPivotTableInner(props, ref) {
1331
1784
  const options = {
1332
1785
  ...tableOptions,
1333
1786
  ...customizedOptions,
1787
+ debug: resolvedDebug,
1788
+ rowHeight: densityOverride == null ? tableOptions.rowHeight : resolveDensityRowHeight(densityOverride),
1789
+ indicators: customizedOptions?.indicators ?? overriddenIndicators,
1334
1790
  ui: {
1335
1791
  onFilterPanelRequest: setFilterRequest,
1336
- onContextMenuRequest: setContextMenuRequest,
1792
+ onContextMenuRequest: (request) => {
1793
+ if (request) {
1794
+ const nativeChangeDensity = request.onChangeDensity;
1795
+ const fieldKey = request.indicatorKey;
1796
+ const enhancedRequest = {
1797
+ ...request,
1798
+ onChangeDensity: (density) => {
1799
+ nativeChangeDensity?.(density);
1800
+ setDensityOverride(density);
1801
+ },
1802
+ onChangeDataFormat: fieldKey == null ? void 0 : (dataFormat) => updateField(fieldKey, { dataFormat })
1803
+ };
1804
+ if (request.target === "summary" && fieldKey != null) {
1805
+ enhancedRequest.onChangeSummaryAggregator = (aggregator) => updateField(fieldKey, { aggregator });
1806
+ enhancedRequest.onChangeSummaryPrecision = (precision) => updateField(fieldKey, { precision });
1807
+ }
1808
+ setContextMenuRequest(enhancedRequest);
1809
+ return;
1810
+ }
1811
+ setContextMenuRequest(null);
1812
+ },
1337
1813
  onTooltipRequest: setTooltipRequest
1338
1814
  },
1339
1815
  onFilterChange: (event) => {
@@ -1387,7 +1863,7 @@ function ReactPivotTableInner(props, ref) {
1387
1863
  const removeField = (fieldKey) => {
1388
1864
  applyLayout(removePivotField(fieldLayout, fieldKey));
1389
1865
  };
1390
- const updateField = (fieldKey, patch) => {
1866
+ function updateField(fieldKey, patch) {
1391
1867
  setFieldOverrides((current) => ({
1392
1868
  ...current,
1393
1869
  [fieldKey]: { ...current[fieldKey], ...patch }
@@ -1402,11 +1878,13 @@ function ReactPivotTableInner(props, ref) {
1402
1878
  indicator: {
1403
1879
  ...field.indicator,
1404
1880
  title: patch.title ?? field.indicator?.title,
1405
- aggregator: patch.aggregator ?? field.indicator?.aggregator
1881
+ aggregator: patch.aggregator ?? field.indicator?.aggregator,
1882
+ precision: "precision" in patch ? patch.precision : field.indicator?.precision,
1883
+ dataFormat: "dataFormat" in patch ? patch.dataFormat : field.indicator?.dataFormat
1406
1884
  }
1407
1885
  });
1408
1886
  }
1409
- };
1887
+ }
1410
1888
  useEffect(() => {
1411
1889
  const container = containerRef.current;
1412
1890
  if (!container) return;
@@ -1588,6 +2066,13 @@ function ReactPivotTableInner(props, ref) {
1588
2066
  /* @__PURE__ */ jsx(PivotTooltip, { request: tooltipRequest })
1589
2067
  ] });
1590
2068
  }
2069
+ function resolveDensityRowHeight(density) {
2070
+ if (density === "comfortable") return 56;
2071
+ if (density === "middle") return 48;
2072
+ if (density === "compact") return 32;
2073
+ if (density === "ultra-compact") return 26;
2074
+ return void 0;
2075
+ }
1591
2076
  var ReactPivotTable = forwardRef(ReactPivotTableInner);
1592
2077
  function toSharedFilterRequest(request, onValueChange) {
1593
2078
  if (!request) return null;
@@ -1751,6 +2236,6 @@ function inferFieldAggregator(records, dataIndex) {
1751
2236
  return typeof value === "number" ? "sum" : "count";
1752
2237
  }
1753
2238
 
1754
- export { ReactPivotTable };
2239
+ export { ReactPivotTable, ReactPivotTableDebugProvider };
1755
2240
  //# sourceMappingURL=index.js.map
1756
2241
  //# sourceMappingURL=index.js.map