@canvas-components/react-pivot-table 0.2.16 → 0.2.18

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.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { CSSProperties, ReactNode, ForwardedRef, PropsWithChildren } from 'react';
3
- import { PivotTableOptions, PivotField, PivotFieldLayout, PivotModel, PivotTable, PivotSelectionState, PivotFilterState, PivotSortRule, PivotCellAddress, PivotAxis, PivotFilterAxis, PivotDimensionFilter, PivotFilterOptionItem, PivotExportOptions, PivotTableStateSnapshot } from '@canvas-components/pivot-table';
3
+ import { PivotTableOptions, PivotField, PivotFieldLayout, PivotTable, PivotModel, PivotSelectionState, PivotFilterState, PivotSortRule, PivotCellAddress, PivotAxis, PivotFilterAxis, PivotDimensionFilter, PivotFilterOptionItem, PivotExportOptions, PivotTableStateSnapshot } from '@canvas-components/pivot-table';
4
4
 
5
5
  /** PivotTable 自定义字段面板配置。 */
6
6
  interface ReactPivotTableCustomizationOptions<RecordType = Record<string, unknown>> {
@@ -33,6 +33,7 @@ interface ReactPivotTableProps<RecordType = Record<string, unknown>> extends Omi
33
33
  }
34
34
  /** ReactPivotTable 实例方法。 */
35
35
  interface ReactPivotTableRef<RecordType = Record<string, unknown>> {
36
+ autoFitColumnWidths: PivotTable<RecordType>["autoFitColumnWidths"];
36
37
  getPivotModel: () => PivotModel<RecordType> | null;
37
38
  getVisibleRowNodes: () => ReturnType<PivotTable<RecordType>["getVisibleRowNodes"]>;
38
39
  getVisibleColumnNodes: () => ReturnType<PivotTable<RecordType>["getVisibleColumnNodes"]>;
@@ -58,6 +59,8 @@ interface ReactPivotTableRef<RecordType = Record<string, unknown>> {
58
59
  expandAll: (axis?: PivotAxis | "both") => number;
59
60
  collapseAll: (axis?: PivotAxis | "both") => number;
60
61
  setDimensionFilter: (axis: PivotFilterAxis, dimensionKey: string, filter: PivotDimensionFilter | null) => PivotFilterState | null;
62
+ setIndicatorFilter: (indicatorKey: string, columnPathKey: string, filter: PivotDimensionFilter | null) => PivotFilterState | null;
63
+ getIndicatorFilterOptions: (indicatorKey: string, columnPathKey: string) => PivotFilterOptionItem[];
61
64
  getDimensionFilterOptions: (axis: PivotFilterAxis, dimensionKey: string) => PivotFilterOptionItem[];
62
65
  resetFilters: () => PivotFilterState | null;
63
66
  setDimensionSort: (axis: PivotAxis, dimensionKey: string, direction: "asc" | "desc" | null) => PivotSortRule[];
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { CSSProperties, ReactNode, ForwardedRef, PropsWithChildren } from 'react';
3
- import { PivotTableOptions, PivotField, PivotFieldLayout, PivotModel, PivotTable, PivotSelectionState, PivotFilterState, PivotSortRule, PivotCellAddress, PivotAxis, PivotFilterAxis, PivotDimensionFilter, PivotFilterOptionItem, PivotExportOptions, PivotTableStateSnapshot } from '@canvas-components/pivot-table';
3
+ import { PivotTableOptions, PivotField, PivotFieldLayout, PivotTable, PivotModel, PivotSelectionState, PivotFilterState, PivotSortRule, PivotCellAddress, PivotAxis, PivotFilterAxis, PivotDimensionFilter, PivotFilterOptionItem, PivotExportOptions, PivotTableStateSnapshot } from '@canvas-components/pivot-table';
4
4
 
5
5
  /** PivotTable 自定义字段面板配置。 */
6
6
  interface ReactPivotTableCustomizationOptions<RecordType = Record<string, unknown>> {
@@ -33,6 +33,7 @@ interface ReactPivotTableProps<RecordType = Record<string, unknown>> extends Omi
33
33
  }
34
34
  /** ReactPivotTable 实例方法。 */
35
35
  interface ReactPivotTableRef<RecordType = Record<string, unknown>> {
36
+ autoFitColumnWidths: PivotTable<RecordType>["autoFitColumnWidths"];
36
37
  getPivotModel: () => PivotModel<RecordType> | null;
37
38
  getVisibleRowNodes: () => ReturnType<PivotTable<RecordType>["getVisibleRowNodes"]>;
38
39
  getVisibleColumnNodes: () => ReturnType<PivotTable<RecordType>["getVisibleColumnNodes"]>;
@@ -58,6 +59,8 @@ interface ReactPivotTableRef<RecordType = Record<string, unknown>> {
58
59
  expandAll: (axis?: PivotAxis | "both") => number;
59
60
  collapseAll: (axis?: PivotAxis | "both") => number;
60
61
  setDimensionFilter: (axis: PivotFilterAxis, dimensionKey: string, filter: PivotDimensionFilter | null) => PivotFilterState | null;
62
+ setIndicatorFilter: (indicatorKey: string, columnPathKey: string, filter: PivotDimensionFilter | null) => PivotFilterState | null;
63
+ getIndicatorFilterOptions: (indicatorKey: string, columnPathKey: string) => PivotFilterOptionItem[];
61
64
  getDimensionFilterOptions: (axis: PivotFilterAxis, dimensionKey: string) => PivotFilterOptionItem[];
62
65
  resetFilters: () => PivotFilterState | null;
63
66
  setDimensionSort: (axis: PivotAxis, dimensionKey: string, direction: "asc" | "desc" | null) => PivotSortRule[];
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createContext, forwardRef, useMemo, useRef, useState, useEffect, useImperativeHandle, useContext, Fragment as Fragment$1 } from 'react';
2
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
- import { ReactResizablePanels, ReactFilterPanel, ReactPopup, ReactCheckbox, ReactInput, ReactSelect, ReactInputNumber } from '@canvas-components/react-components';
3
+ import { ReactResizablePanels, ReactFilterPanel, ReactPopup, ReactCheckbox, ReactModal, 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';
@@ -30,11 +30,12 @@ function styleInject(css, { insertAt } = {}) {
30
30
  }
31
31
 
32
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");
33
+ styleInject(".react-pivot-table-menu-action {\n font-size: inherit;\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
34
  var CONTEXT_MENU_SURFACE_STYLE = {
35
35
  padding: 8,
36
36
  background: "#ffffff",
37
- boxShadow: "0 8px 24px rgba(15, 23, 42, 0.16)"
37
+ boxShadow: "0 8px 24px rgba(15, 23, 42, 0.16)",
38
+ fontSize: 14
38
39
  };
39
40
  function PivotContextMenu(props) {
40
41
  const { request } = props;
@@ -144,7 +145,29 @@ function HeaderMenu(props) {
144
145
  ]
145
146
  }
146
147
  ) : null,
147
- request.onOpenFilter ? /* @__PURE__ */ jsx(MenuAction, { label: "\u6253\u5F00\u7B5B\u9009\u9762\u677F", onClick: request.onOpenFilter }) : null,
148
+ request.onAutoFitCurrentColumn || request.onAutoFitAllColumns ? /* @__PURE__ */ jsx(
149
+ MenuSubmenu,
150
+ {
151
+ label: "\u81EA\u52A8\u8C03\u6574\u5217\u5BBD",
152
+ items: [
153
+ {
154
+ key: "auto-fit-current",
155
+ label: "\u5F53\u524D\u5217",
156
+ onClick: request.onAutoFitCurrentColumn
157
+ },
158
+ {
159
+ key: "auto-fit-all",
160
+ label: "\u5168\u90E8\u5217",
161
+ onClick: request.onAutoFitAllColumns
162
+ },
163
+ {
164
+ key: "auto-fit-fill-container",
165
+ label: "\u81EA\u52A8\u94FA\u6EE1\u5BB9\u5668",
166
+ onClick: request.onAutoFitFillContainer
167
+ }
168
+ ]
169
+ }
170
+ ) : null,
148
171
  hasExpand ? /* @__PURE__ */ jsx(
149
172
  MenuSubmenu,
150
173
  {
@@ -172,14 +195,35 @@ function HeaderMenu(props) {
172
195
  }
173
196
  function SummaryMenu(props) {
174
197
  const { request } = props;
198
+ const [title, setTitle] = useState(request.summaryTitle ?? "");
175
199
  const [precision, setPrecision] = useState(
176
200
  request.summaryPrecision ?? null
177
201
  );
202
+ const [roundingMode, setRoundingMode] = useState(
203
+ request.summaryRoundingMode ?? "round"
204
+ );
205
+ const [preserveTrailingZeros, setPreserveTrailingZeros] = useState(
206
+ request.summaryPreserveTrailingZeros ?? false
207
+ );
208
+ useEffect(() => {
209
+ setTitle(request.summaryTitle ?? "");
210
+ setPrecision(request.summaryPrecision ?? null);
211
+ setRoundingMode(request.summaryRoundingMode ?? "round");
212
+ setPreserveTrailingZeros(request.summaryPreserveTrailingZeros ?? false);
213
+ }, [
214
+ request.indicatorKey,
215
+ request.summaryTitle,
216
+ request.summaryPrecision,
217
+ request.summaryRoundingMode,
218
+ request.summaryPreserveTrailingZeros
219
+ ]);
178
220
  const aggregators = [
179
221
  ["sum", "\u6C42\u548C"],
180
222
  ["avg", "\u5E73\u5747\u503C"],
181
223
  ["count", "\u8BA1\u6570"],
182
224
  ["distinctCount", "\u53BB\u91CD\u8BA1\u6570"],
225
+ ["rowCount", "\u884C\u6570"],
226
+ ["mergedRowCount", "\u5408\u5E76\u884C\u6570"],
183
227
  ["min", "\u6700\u5C0F\u503C"],
184
228
  ["max", "\u6700\u5927\u503C"]
185
229
  ];
@@ -188,15 +232,62 @@ function SummaryMenu(props) {
188
232
  MenuSubmenu,
189
233
  {
190
234
  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();
235
+ minWidth: 268,
236
+ header: request.onChangeSummaryTitle ? /* @__PURE__ */ jsxs(
237
+ "div",
238
+ {
239
+ style: {
240
+ display: "grid",
241
+ gridTemplateColumns: "56px 1fr",
242
+ gap: 8,
243
+ alignItems: "center",
244
+ padding: "2px 10px 10px",
245
+ marginBottom: 4,
246
+ borderBottom: "1px solid #e5e7eb"
247
+ },
248
+ children: [
249
+ /* @__PURE__ */ jsx("span", { style: { color: "#374151", fontSize: 14 }, children: "\u6807\u9898\uFF1A" }),
250
+ /* @__PURE__ */ jsx(
251
+ ReactInput,
252
+ {
253
+ value: title,
254
+ placeholder: "\u8BF7\u8F93\u5165\u6807\u9898",
255
+ onChange: (event) => {
256
+ setTitle(event.target.value);
257
+ request.onChangeSummaryTitle?.(event.target.value);
258
+ }
259
+ }
260
+ )
261
+ ]
198
262
  }
199
- })),
263
+ ) : void 0,
264
+ items: [
265
+ ...aggregators.map(([value, label]) => ({
266
+ key: `summary-${value}`,
267
+ label,
268
+ selected: !request.summaryDisabled && request.summaryAggregator === value,
269
+ onClick: () => {
270
+ request.onChangeSummaryAggregator?.(value);
271
+ request.onClose();
272
+ }
273
+ })),
274
+ {
275
+ key: "summary-prefix",
276
+ label: "\u5C55\u793A\u6C47\u603B\u65B9\u5F0F\u524D\u7F00",
277
+ separatorBefore: true,
278
+ selected: request.summaryShowTypePrefix !== false,
279
+ disabled: request.summaryDisabled,
280
+ onClick: () => request.onChangeSummaryShowTypePrefix?.(
281
+ request.summaryShowTypePrefix === false
282
+ )
283
+ },
284
+ {
285
+ key: "summary-clear",
286
+ label: "\u53D6\u6D88\u6C47\u603B",
287
+ separatorBefore: true,
288
+ onClick: request.onClearSummary
289
+ }
290
+ ],
200
291
  footer: request.onChangeSummaryPrecision ? /* @__PURE__ */ jsxs(
201
292
  "div",
202
293
  {
@@ -210,7 +301,7 @@ function SummaryMenu(props) {
210
301
  borderTop: "1px solid #e5e7eb"
211
302
  },
212
303
  children: [
213
- /* @__PURE__ */ jsx("span", { style: { color: "#374151", fontSize: 13 }, children: "\u5C0F\u6570\u4F4D\u6570" }),
304
+ /* @__PURE__ */ jsx("span", { style: { color: "#374151", fontSize: 14 }, children: "\u5C0F\u6570\u4F4D\u6570" }),
214
305
  /* @__PURE__ */ jsx(
215
306
  ReactInputNumber,
216
307
  {
@@ -219,10 +310,42 @@ function SummaryMenu(props) {
219
310
  max: 20,
220
311
  step: 1,
221
312
  precision: 0,
222
- placeholder: "\u81EA\u52A8",
313
+ placeholder: "\u9ED8\u8BA4",
314
+ onChange: setPrecision,
315
+ onCommit: (value) => request.onChangeSummaryPrecision?.(value ?? void 0)
316
+ }
317
+ ),
318
+ /* @__PURE__ */ jsx("span", { style: { color: "#374151", fontSize: 14 }, children: "\u53D6\u6574\u65B9\u5F0F" }),
319
+ /* @__PURE__ */ jsx(
320
+ ReactSelect,
321
+ {
322
+ value: roundingMode,
323
+ options: [
324
+ { label: "\u56DB\u820D\u4E94\u5165", value: "round" },
325
+ { label: "\u5411\u4E0B\u53D6\u6574", value: "floor" },
326
+ { label: "\u5411\u4E0A\u53D6\u6574", value: "ceil" },
327
+ { label: "\u820D\u53BB\u4E0D\u5904\u7406", value: "truncate" }
328
+ ],
329
+ onChange: (value) => {
330
+ const mode = value;
331
+ setRoundingMode(mode);
332
+ request.onChangeSummaryRoundingMode?.(mode);
333
+ }
334
+ }
335
+ ),
336
+ /* @__PURE__ */ jsx("span", { style: { color: "#374151", fontSize: 14 }, children: "\u4FDD\u7559\u65E0\u6548\u96F6" }),
337
+ /* @__PURE__ */ jsx(
338
+ ReactSelect,
339
+ {
340
+ value: preserveTrailingZeros ? "true" : "false",
341
+ options: [
342
+ { label: "\u4E0D\u4FDD\u7559", value: "false" },
343
+ { label: "\u4FDD\u7559", value: "true" }
344
+ ],
223
345
  onChange: (value) => {
224
- setPrecision(value);
225
- request.onChangeSummaryPrecision?.(value ?? void 0);
346
+ const enabled = value === "true";
347
+ setPreserveTrailingZeros(enabled);
348
+ request.onChangeSummaryPreserveTrailingZeros?.(enabled);
226
349
  }
227
350
  }
228
351
  )
@@ -419,7 +542,7 @@ function MenuAction(props) {
419
542
  );
420
543
  }
421
544
  function MenuSubmenu(props) {
422
- const { label, items, footer, children, minWidth = 220 } = props;
545
+ const { label, items, footer, header, children, minWidth = 220 } = props;
423
546
  const menuItems = items.filter((item) => item.onClick || item.disabled);
424
547
  const reserveSelectionIcon = menuItems.some(
425
548
  (item) => typeof item.selected === "boolean"
@@ -427,7 +550,7 @@ function MenuSubmenu(props) {
427
550
  const triggerRef = useRef(null);
428
551
  const [open, setOpen] = useState(false);
429
552
  const closeTimerRef = useRef(null);
430
- if (!menuItems.length && !footer && !children) return null;
553
+ if (!menuItems.length && !footer && !header && !children) return null;
431
554
  const clearCloseTimer = () => {
432
555
  if (closeTimerRef.current != null) {
433
556
  window.clearTimeout(closeTimerRef.current);
@@ -494,6 +617,7 @@ function MenuSubmenu(props) {
494
617
  onOpenChange: setOpen,
495
618
  surfaceStyle: { ...CONTEXT_MENU_SURFACE_STYLE, width: minWidth },
496
619
  children: /* @__PURE__ */ jsxs("div", { onMouseEnter: clearCloseTimer, onMouseLeave: scheduleClose, children: [
620
+ header,
497
621
  menuItems.map((item) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
498
622
  item.separatorBefore ? /* @__PURE__ */ jsx(MenuDivider, {}) : null,
499
623
  /* @__PURE__ */ jsx(
@@ -690,6 +814,58 @@ function DataFormatMenu(props) {
690
814
  }
691
815
  );
692
816
  }
817
+ function PivotExportNameDialog({
818
+ request
819
+ }) {
820
+ const extension = request.fileName.match(/\.(xlsx|csv)$/i)?.[0] ?? "";
821
+ const [fileName, setFileName] = useState(
822
+ extension ? request.fileName.slice(0, -extension.length) : request.fileName
823
+ );
824
+ const [invalid, setInvalid] = useState(false);
825
+ const confirm = () => {
826
+ if (!fileName.trim()) {
827
+ setInvalid(true);
828
+ return;
829
+ }
830
+ request.onConfirm(`${fileName.trim()}${extension}`);
831
+ };
832
+ return /* @__PURE__ */ jsxs(
833
+ ReactModal,
834
+ {
835
+ open: true,
836
+ title: "\u5BFC\u51FA\u6587\u4EF6",
837
+ width: 420,
838
+ fullscreenable: false,
839
+ onCancel: request.onCancel,
840
+ onOk: confirm,
841
+ okText: "\u5BFC\u51FA",
842
+ cancelText: "\u53D6\u6D88",
843
+ children: [
844
+ /* @__PURE__ */ jsxs("label", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
845
+ "\u6587\u4EF6\u540D\u79F0",
846
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
847
+ /* @__PURE__ */ jsx(
848
+ ReactInput,
849
+ {
850
+ autoFocus: true,
851
+ value: fileName,
852
+ placeholder: "\u8BF7\u8F93\u5165\u6587\u4EF6\u540D\u79F0",
853
+ onFocus: (event) => event.target.select(),
854
+ onChange: (event) => {
855
+ setFileName(event.target.value);
856
+ setInvalid(false);
857
+ },
858
+ onPressEnter: confirm
859
+ }
860
+ ),
861
+ /* @__PURE__ */ jsx("span", { "aria-label": "\u6587\u4EF6\u540E\u7F00", style: { flexShrink: 0 }, children: extension })
862
+ ] })
863
+ ] }),
864
+ invalid ? /* @__PURE__ */ jsx("div", { role: "alert", style: { color: "#ff4d4f", marginTop: 8 }, children: "\u8BF7\u8F93\u5165\u6587\u4EF6\u540D\u79F0" }) : null
865
+ ]
866
+ }
867
+ );
868
+ }
693
869
  function PivotTooltip(props) {
694
870
  const { request } = props;
695
871
  if (!request) return null;
@@ -1222,7 +1398,9 @@ var aggregatorOptions = [
1222
1398
  { label: "\u5E73\u5747\u503C", value: "avg" },
1223
1399
  { label: "\u6700\u5927\u503C", value: "max" },
1224
1400
  { label: "\u6700\u5C0F\u503C", value: "min" },
1225
- { label: "\u53BB\u91CD\u8BA1\u6570", value: "distinctCount" }
1401
+ { label: "\u53BB\u91CD\u8BA1\u6570", value: "distinctCount" },
1402
+ { label: "\u884C\u6570", value: "rowCount" },
1403
+ { label: "\u5408\u5E76\u884C\u6570", value: "mergedRowCount" }
1226
1404
  ];
1227
1405
  var popupStyle = {
1228
1406
  padding: 0,
@@ -1710,6 +1888,7 @@ function ReactPivotTableInner(props, ref) {
1710
1888
  const [densityOverride, setDensityOverride] = useState(null);
1711
1889
  const [filterRequest, setFilterRequest] = useState(null);
1712
1890
  const [contextMenuRequest, setContextMenuRequest] = useState(null);
1891
+ const [exportNameRequest, setExportNameRequest] = useState(null);
1713
1892
  const [tooltipRequest, setTooltipRequest] = useState(null);
1714
1893
  const panelOpen = customizationOptions?.open ?? internalPanelOpen;
1715
1894
  const fieldLayout = customizationOptions?.layout ?? internalLayout;
@@ -1750,6 +1929,7 @@ function ReactPivotTableInner(props, ref) {
1750
1929
  title: override.title ?? field.title,
1751
1930
  indicator: {
1752
1931
  ...field.indicator,
1932
+ ...override,
1753
1933
  title: override.title ?? field.indicator?.title,
1754
1934
  aggregator: override.aggregator ?? field.indicator?.aggregator,
1755
1935
  precision: "precision" in override ? override.precision : field.indicator?.precision,
@@ -1769,6 +1949,7 @@ function ReactPivotTableInner(props, ref) {
1769
1949
  if (!override) return indicator;
1770
1950
  return {
1771
1951
  ...indicator,
1952
+ ...override,
1772
1953
  title: override.title ?? indicator.title,
1773
1954
  aggregator: override.aggregator ?? indicator.aggregator,
1774
1955
  precision: "precision" in override ? override.precision : indicator.precision,
@@ -1788,6 +1969,9 @@ function ReactPivotTableInner(props, ref) {
1788
1969
  rowHeight: densityOverride == null ? tableOptions.rowHeight : resolveDensityRowHeight(densityOverride),
1789
1970
  indicators: customizedOptions?.indicators ?? overriddenIndicators,
1790
1971
  ui: {
1972
+ onExportNameRequest: (request) => {
1973
+ setExportNameRequest(request);
1974
+ },
1791
1975
  onFilterPanelRequest: setFilterRequest,
1792
1976
  onContextMenuRequest: (request) => {
1793
1977
  if (request) {
@@ -1802,8 +1986,35 @@ function ReactPivotTableInner(props, ref) {
1802
1986
  onChangeDataFormat: fieldKey == null ? void 0 : (dataFormat) => updateField(fieldKey, { dataFormat })
1803
1987
  };
1804
1988
  if (request.target === "summary" && fieldKey != null) {
1805
- enhancedRequest.onChangeSummaryAggregator = (aggregator) => updateField(fieldKey, { aggregator });
1806
- enhancedRequest.onChangeSummaryPrecision = (precision) => updateField(fieldKey, { precision });
1989
+ const changeSummary = (patch, menuPatch) => {
1990
+ updateField(fieldKey, patch);
1991
+ setContextMenuRequest(
1992
+ (current) => current?.target === "summary" && current.indicatorKey === fieldKey ? { ...current, ...menuPatch } : current
1993
+ );
1994
+ };
1995
+ enhancedRequest.onChangeSummaryAggregator = (aggregator) => changeSummary(
1996
+ {
1997
+ aggregator,
1998
+ summaryAggregator: aggregator,
1999
+ summaryDisabled: false
2000
+ },
2001
+ { summaryAggregator: aggregator, summaryDisabled: false }
2002
+ );
2003
+ enhancedRequest.onChangeSummaryPrecision = (precision) => changeSummary({ precision }, { summaryPrecision: precision });
2004
+ enhancedRequest.onChangeSummaryTitle = (summaryTitle) => changeSummary({ summaryTitle }, { summaryTitle });
2005
+ enhancedRequest.onChangeSummaryShowTypePrefix = (summaryShowTypePrefix) => changeSummary(
2006
+ { summaryShowTypePrefix },
2007
+ { summaryShowTypePrefix }
2008
+ );
2009
+ enhancedRequest.onChangeSummaryRoundingMode = (summaryRoundingMode) => changeSummary({ summaryRoundingMode }, { summaryRoundingMode });
2010
+ enhancedRequest.onChangeSummaryPreserveTrailingZeros = (summaryPreserveTrailingZeros) => changeSummary(
2011
+ { summaryPreserveTrailingZeros },
2012
+ { summaryPreserveTrailingZeros }
2013
+ );
2014
+ enhancedRequest.onClearSummary = () => changeSummary(
2015
+ { summaryDisabled: true },
2016
+ { summaryDisabled: true }
2017
+ );
1807
2018
  }
1808
2019
  setContextMenuRequest(enhancedRequest);
1809
2020
  return;
@@ -1823,10 +2034,10 @@ function ReactPivotTableInner(props, ref) {
1823
2034
  };
1824
2035
  const sharedFilterRequest = useMemo(() => {
1825
2036
  if (!filterRequest) return null;
1826
- const { axis, dimensionKey } = filterRequest;
2037
+ const { axis, dimensionKey, columnPathKey } = filterRequest;
1827
2038
  return toSharedFilterRequest(filterRequest, (value) => {
1828
2039
  setFilterRequest(
1829
- (current) => current?.axis === axis && current.dimensionKey === dimensionKey ? { ...current, value } : current
2040
+ (current) => current?.axis === axis && current.dimensionKey === dimensionKey && current.columnPathKey === columnPathKey ? { ...current, value } : current
1830
2041
  );
1831
2042
  });
1832
2043
  }, [filterRequest]);
@@ -1877,6 +2088,7 @@ function ReactPivotTableInner(props, ref) {
1877
2088
  title: patch.title ?? field.title,
1878
2089
  indicator: {
1879
2090
  ...field.indicator,
2091
+ ...patch,
1880
2092
  title: patch.title ?? field.indicator?.title,
1881
2093
  aggregator: patch.aggregator ?? field.indicator?.aggregator,
1882
2094
  precision: "precision" in patch ? patch.precision : field.indicator?.precision,
@@ -1928,6 +2140,7 @@ function ReactPivotTableInner(props, ref) {
1928
2140
  useImperativeHandle(
1929
2141
  ref,
1930
2142
  () => ({
2143
+ autoFitColumnWidths: (target, fillContainer) => tableRef.current?.autoFitColumnWidths(target, fillContainer) ?? false,
1931
2144
  getPivotModel: () => tableRef.current?.getPivotModel() ?? null,
1932
2145
  getVisibleRowNodes: () => tableRef.current?.getVisibleRowNodes() ?? [],
1933
2146
  getVisibleColumnNodes: () => tableRef.current?.getVisibleColumnNodes() ?? [],
@@ -1949,6 +2162,15 @@ function ReactPivotTableInner(props, ref) {
1949
2162
  expandAll: (axis) => tableRef.current?.expandAll(axis) ?? 0,
1950
2163
  collapseAll: (axis) => tableRef.current?.collapseAll(axis) ?? 0,
1951
2164
  setDimensionFilter: (axis, dimensionKey, filter) => tableRef.current?.setDimensionFilter(axis, dimensionKey, filter) ?? null,
2165
+ setIndicatorFilter: (indicatorKey, columnPathKey, filter) => tableRef.current?.setIndicatorFilter(
2166
+ indicatorKey,
2167
+ columnPathKey,
2168
+ filter
2169
+ ) ?? null,
2170
+ getIndicatorFilterOptions: (indicatorKey, columnPathKey) => tableRef.current?.getIndicatorFilterOptions(
2171
+ indicatorKey,
2172
+ columnPathKey
2173
+ ) ?? [],
1952
2174
  getDimensionFilterOptions: (axis, dimensionKey) => tableRef.current?.getDimensionFilterOptions(axis, dimensionKey) ?? [],
1953
2175
  resetFilters: () => tableRef.current?.resetFilters() ?? null,
1954
2176
  setDimensionSort: (axis, dimensionKey, direction) => tableRef.current?.setDimensionSort(axis, dimensionKey, direction) ?? [],
@@ -2063,6 +2285,7 @@ function ReactPivotTableInner(props, ref) {
2063
2285
  ),
2064
2286
  /* @__PURE__ */ jsx(ReactFilterPanel, { request: sharedFilterRequest }),
2065
2287
  /* @__PURE__ */ jsx(PivotContextMenu, { request: contextMenuRequest }),
2288
+ exportNameRequest ? /* @__PURE__ */ jsx(PivotExportNameDialog, { request: exportNameRequest }) : null,
2066
2289
  /* @__PURE__ */ jsx(PivotTooltip, { request: tooltipRequest })
2067
2290
  ] });
2068
2291
  }