@odoo/o-spreadsheet 19.5.0-alpha.19 → 19.5.0-alpha.20

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.
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 19.5.0-alpha.19
6
- * @date 2026-09-10T05:38:44.935Z
7
- * @hash 2b1e397
5
+ * @version 19.5.0-alpha.20
6
+ * @date 2026-09-16T08:02:11.430Z
7
+ * @hash 4784627
8
8
  */
9
9
 
10
10
  import * as owl from "@odoo/owl";
@@ -8828,7 +8828,7 @@ function getHueRotateMatrix(degrees) {
8828
8828
  * stored in the theme so that, after the dark-mode CSS filter is applied, the
8829
8829
  * desired color is actually shown.
8830
8830
  *
8831
- * This function computes the exact inverse of the DARK_MODE_FILTER chain.
8831
+ * This function computes an approximate inverse of the DARK_MODE_FILTER chain.
8832
8832
  */
8833
8833
  function adaptForDarkMode(displayedColor) {
8834
8834
  const { r, g, b, a } = colorToRGBA(displayedColor);
@@ -9976,34 +9976,49 @@ const TEXT_HEADER_COLOR = "#666666";
9976
9976
  const BACKGROUND_HEADER_COLOR = "#F8F9FA";
9977
9977
  const BACKGROUND_HEADER_SELECTED_COLOR = "#E8EAED";
9978
9978
  const BACKGROUND_HEADER_ACTIVE_COLOR = "#595959";
9979
+ function adaptColorsForDarkMode(colors) {
9980
+ return Object.fromEntries(Object.entries(colors).map(([key, color]) => [key, adaptForDarkMode(color)]));
9981
+ }
9982
+ const LIGHT_COLORS = {
9983
+ chartBackgroundColor: "#FFFFFF",
9984
+ gridBorderColor: "#CECFCF",
9985
+ gridBorderColorOnDefaultBackground: "#E2E3E3",
9986
+ headerBackgroundColor: BACKGROUND_HEADER_COLOR,
9987
+ headerActiveBackgroundColor: BACKGROUND_HEADER_ACTIVE_COLOR,
9988
+ headerSelectedBackgroundColor: BACKGROUND_HEADER_SELECTED_COLOR,
9989
+ headerTextColor: TEXT_HEADER_COLOR,
9990
+ headerBorderColor: HEADER_BORDER_COLOR,
9991
+ frozenPaneBorderColor: FROZEN_PANE_BORDER_COLOR,
9992
+ frozenPaneHeaderBorderColor: FROZEN_PANE_HEADER_BORDER_COLOR,
9993
+ singleCellSelectionBackgroundColor: "#D2E1FB44",
9994
+ multipleCellsSelectionBackgroundColor: "#ACC7FF44"
9995
+ };
9996
+ /** Every color defined explicitely in the dark theme is expected to be subject to color-inverter mask applied
9997
+ * through the css class `os-theme-dependant`. They are therefore pre-inverted for dark mode.
9998
+ * Note that according to `adaptForDarkMode` documentation, the resulting color will be an approximation of the pre-inverted color.
9999
+ */
10000
+ const DARK_DISPLAYED_COLORS = {
10001
+ chartBackgroundColor: "#25262b",
10002
+ gridBorderColor: "#6B706F",
10003
+ gridBorderColorOnDefaultBackground: "#4F5254",
10004
+ headerBackgroundColor: "#262A36",
10005
+ headerActiveBackgroundColor: "#3A4052",
10006
+ headerSelectedBackgroundColor: "#4E566E",
10007
+ headerTextColor: "#A1A6B3",
10008
+ headerBorderColor: "#7A7F91",
10009
+ frozenPaneBorderColor: "#7A7F91",
10010
+ frozenPaneHeaderBorderColor: "#9FA5BD",
10011
+ singleCellSelectionBackgroundColor: "#696E8044",
10012
+ multipleCellsSelectionBackgroundColor: "#828AA044"
10013
+ };
9979
10014
  const COLOR_THEMES = {
9980
10015
  light: {
9981
10016
  colorThemeName: "light",
9982
- backgroundColor: "#FFFFFF",
9983
- gridBorderColor: "#CECFCF",
9984
- headerBackgroundColor: BACKGROUND_HEADER_COLOR,
9985
- headerActiveBackgroundColor: BACKGROUND_HEADER_ACTIVE_COLOR,
9986
- headerSelectedBackgroundColor: BACKGROUND_HEADER_SELECTED_COLOR,
9987
- headerTextColor: TEXT_HEADER_COLOR,
9988
- headerBorderColor: HEADER_BORDER_COLOR,
9989
- frozenPaneBorderColor: FROZEN_PANE_BORDER_COLOR,
9990
- frozenPaneHeaderBorderColor: FROZEN_PANE_HEADER_BORDER_COLOR,
9991
- singleCellSelectionBackgroundColor: "#F3F7FE",
9992
- multipleCellsSelectionBackgroundColor: "#E9F0FF"
10017
+ ...LIGHT_COLORS
9993
10018
  },
9994
10019
  dark: {
9995
10020
  colorThemeName: "dark",
9996
- backgroundColor: adaptForDarkMode("#1A1C2E"),
9997
- gridBorderColor: adaptForDarkMode("#6B706F"),
9998
- headerBackgroundColor: adaptForDarkMode("#262A36"),
9999
- headerActiveBackgroundColor: adaptForDarkMode("#3A4052"),
10000
- headerSelectedBackgroundColor: adaptForDarkMode("#4E566E"),
10001
- headerTextColor: adaptForDarkMode("#A1A6B3"),
10002
- headerBorderColor: adaptForDarkMode("#7A7F91"),
10003
- frozenPaneBorderColor: adaptForDarkMode("#7A7F91"),
10004
- frozenPaneHeaderBorderColor: adaptForDarkMode("#9FA5BD"),
10005
- singleCellSelectionBackgroundColor: adaptForDarkMode("#696E8044"),
10006
- multipleCellsSelectionBackgroundColor: adaptForDarkMode("#828AA044")
10021
+ ...adaptColorsForDarkMode(DARK_DISPLAYED_COLORS)
10007
10022
  }
10008
10023
  };
10009
10024
 
@@ -10229,7 +10244,7 @@ function isTrendLineAxis(axisID) {
10229
10244
  return axisID === "x1" || axisID === "xMovingAverage";
10230
10245
  }
10231
10246
  function getChartBackgroundColor({ background }, colorThemeName) {
10232
- if (!background) return COLOR_THEMES[colorThemeName].backgroundColor;
10247
+ if (!background) return COLOR_THEMES[colorThemeName].chartBackgroundColor;
10233
10248
  return background;
10234
10249
  }
10235
10250
 
@@ -14202,7 +14217,7 @@ const GAUGE_PADDING_TOP = 10;
14202
14217
  const GAUGE_PADDING_BOTTOM = 20;
14203
14218
  const GAUGE_LABELS_FONT_SIZE = 12;
14204
14219
  const GAUGE_DEFAULT_VALUE_FONT_SIZE = 80;
14205
- const GAUGE_BACKGROUND_COLOR = "#F3F2F1";
14220
+ const GAUGE_BACKGROUND_COLOR = "#F8F8F8";
14206
14221
  const GAUGE_INFLECTION_LABEL_BOTTOM_MARGIN = 6;
14207
14222
  const GAUGE_TITLE_SECTION_HEIGHT = 25;
14208
14223
  function drawGaugeChart(canvas, runtime, zoom = 1, dimensions, options) {
@@ -24537,8 +24552,8 @@ var ClickableCellSortIcon = class extends Component {
24537
24552
  }
24538
24553
  getBackgroundColor(cellStyle) {
24539
24554
  const overlayColor = this.hoveredCellOverlayStore.overlayColors.get(this.props.position);
24540
- if (overlayColor) return blendColors(cellStyle.fillColor || "#FFFFFF", overlayColor);
24541
- return cellStyle.fillColor || "#FFFFFF";
24555
+ if (overlayColor) return cellStyle.fillColor ? blendColors(cellStyle.fillColor, overlayColor) : overlayColor;
24556
+ return cellStyle.fillColor;
24542
24557
  }
24543
24558
  };
24544
24559
 
@@ -28300,8 +28315,11 @@ var GridRenderer = class extends DisposableStore {
28300
28315
  drawGlobalBackground(renderingContext) {
28301
28316
  const { ctx, viewports } = renderingContext;
28302
28317
  const { width, height } = viewports.getSheetViewDimensionWithHeaders();
28303
- ctx.fillStyle = this.getBackgroundColor(renderingContext);
28304
- ctx.fillRect(0, 0, width + CANVAS_SHIFT, height + CANVAS_SHIFT);
28318
+ const fillStyle = this.getBackgroundColor(renderingContext);
28319
+ if (fillStyle) {
28320
+ ctx.fillStyle = fillStyle;
28321
+ ctx.fillRect(0, 0, width + CANVAS_SHIFT, height + CANVAS_SHIFT);
28322
+ } else ctx.clearRect(0, 0, width + CANVAS_SHIFT, height + CANVAS_SHIFT);
28305
28323
  }
28306
28324
  drawBackground(renderingContext, boxes) {
28307
28325
  const { ctx, thinLineWidth } = renderingContext;
@@ -28310,7 +28328,8 @@ var GridRenderer = class extends DisposableStore {
28310
28328
  if (areGridLinesVisible) {
28311
28329
  const theme = this.getters.getSpreadsheetTheme();
28312
28330
  const background = this.getBackgroundColor(renderingContext);
28313
- ctx.strokeStyle = setColorAlpha(blendColors(theme.gridBorderColor + "aa", background + "50"), 1);
28331
+ if (background) ctx.strokeStyle = setColorAlpha(blendColors(theme.gridBorderColor + "aa", toHex(background) + "50"), 1);
28332
+ else ctx.strokeStyle = theme.gridBorderColorOnDefaultBackground;
28314
28333
  ctx.lineWidth = thinLineWidth;
28315
28334
  for (const box of boxes) {
28316
28335
  if (box.style.hideGridLines) continue;
@@ -28320,9 +28339,11 @@ var GridRenderer = class extends DisposableStore {
28320
28339
  }
28321
28340
  drawCellBackground(renderingContext, boxes) {
28322
28341
  const { ctx } = renderingContext;
28342
+ const backgroundColor = this.getBackgroundColor(renderingContext);
28343
+ const background = backgroundColor ? toHex(backgroundColor) : void 0;
28323
28344
  for (const box of boxes) {
28324
28345
  const style = box.style;
28325
- if (style.fillColor && toHex(style.fillColor) !== toHex(this.getBackgroundColor(renderingContext))) {
28346
+ if (style.fillColor && toHex(style.fillColor) !== background) {
28326
28347
  ctx.fillStyle = toHex(style.fillColor);
28327
28348
  ctx.fillRect(box.x - CANVAS_SHIFT, box.y - CANVAS_SHIFT, box.width + CANVAS_SHIFT * 2, box.height + CANVAS_SHIFT * 2);
28328
28349
  }
@@ -28336,7 +28357,8 @@ var GridRenderer = class extends DisposableStore {
28336
28357
  ctx.fillRect(box.x, y, width, height);
28337
28358
  }
28338
28359
  if (box.overlayColor) {
28339
- ctx.fillStyle = blendColors(style.fillColor || this.getBackgroundColor(renderingContext), box.overlayColor);
28360
+ const backdrop = style.fillColor || this.getBackgroundColor(renderingContext);
28361
+ ctx.fillStyle = backdrop ? blendColors(backdrop, box.overlayColor) : box.overlayColor;
28340
28362
  ctx.fillRect(box.x - CANVAS_SHIFT, box.y - CANVAS_SHIFT, box.width + CANVAS_SHIFT * 2, box.height + CANVAS_SHIFT * 2);
28341
28363
  }
28342
28364
  if (box?.chip) {
@@ -28364,6 +28386,7 @@ var GridRenderer = class extends DisposableStore {
28364
28386
  }
28365
28387
  drawOverflowingCellBackground(renderingContext, boxes) {
28366
28388
  const { ctx, thinLineWidth } = renderingContext;
28389
+ const background = this.getBackgroundColor(renderingContext);
28367
28390
  for (const box of boxes) if (box.content && box.isOverflow) {
28368
28391
  const align = box.content.align || "left";
28369
28392
  let x;
@@ -28381,8 +28404,10 @@ var GridRenderer = class extends DisposableStore {
28381
28404
  x = (box.clipRect?.x || box.x + box.width / 2 - box.content.width / 2) + thinLineWidth / 2;
28382
28405
  width = clipWidth - 2 * thinLineWidth;
28383
28406
  }
28384
- ctx.fillStyle = this.getBackgroundColor(renderingContext);
28385
- ctx.fillRect(x, y, width, height);
28407
+ if (background) {
28408
+ ctx.fillStyle = background;
28409
+ ctx.fillRect(x, y, width, height);
28410
+ } else ctx.clearRect(x, y, width, height);
28386
28411
  }
28387
28412
  }
28388
28413
  drawBorders(renderingContext, boxes) {
@@ -28552,7 +28577,7 @@ var GridRenderer = class extends DisposableStore {
28552
28577
  ctx.textBaseline = "middle";
28553
28578
  ctx.lineWidth = thinLineWidth;
28554
28579
  ctx.strokeStyle = theme.headerTextColor;
28555
- ctx.fillStyle = this.getters.getSpreadsheetTheme().backgroundColor;
28580
+ ctx.fillStyle = theme.headerBackgroundColor;
28556
28581
  ctx.fillRect(0, 0, 48, height);
28557
28582
  ctx.fillRect(0, 0, width, 26);
28558
28583
  for (const col of visibleCols) {
@@ -29001,7 +29026,7 @@ var GridRenderer = class extends DisposableStore {
29001
29026
  }
29002
29027
  }
29003
29028
  getBackgroundColor(renderingContext) {
29004
- return this.getters.getSheet(renderingContext.sheetId).backgroundColor || this.getters.getSpreadsheetTheme().backgroundColor;
29029
+ return this.getters.getSheet(renderingContext.sheetId).backgroundColor;
29005
29030
  }
29006
29031
  };
29007
29032
 
@@ -29014,7 +29039,7 @@ function useGridDrawing({ canvasRef, renderingCtx, rendererStore, changeCanvasSi
29014
29039
  function drawGrid() {
29015
29040
  const canvas = canvasRef();
29016
29041
  if (!canvas) return;
29017
- const ctx = canvas.getContext("2d", { alpha: false });
29042
+ const ctx = canvas.getContext("2d", { alpha: true });
29018
29043
  const renderingContext = {
29019
29044
  ctx,
29020
29045
  thinLineWidth: .4,
@@ -29257,7 +29282,7 @@ var StandaloneViewportStore = class extends SpreadsheetStore {
29257
29282
  viewports: this.viewStore.viewports,
29258
29283
  hideGridLines: this.getters.isDashboard(),
29259
29284
  hideFrozenPaneBorder: true,
29260
- dpr: 1,
29285
+ dpr: window.devicePixelRatio || 1,
29261
29286
  selectedZones: [],
29262
29287
  activeCols: /* @__PURE__ */ new Set(),
29263
29288
  activeRows: /* @__PURE__ */ new Set(),
@@ -29819,7 +29844,7 @@ var CarouselFigure = class extends Component {
29819
29844
  }
29820
29845
  get carouselStyle() {
29821
29846
  const cssProperties = {};
29822
- const backgroundColor = this.env.model.getters.getSpreadsheetTheme().backgroundColor;
29847
+ const backgroundColor = this.env.model.getters.getSpreadsheetTheme().chartBackgroundColor;
29823
29848
  if (this.selectedCarouselItem?.type === "chart") {
29824
29849
  const chart = this.env.model.getters.getChartRuntime(this.selectedCarouselItem.chartId);
29825
29850
  if ("background" in chart && chart.background) cssProperties["background-color"] = chart.background;
@@ -42776,7 +42801,7 @@ function analyzeColumn(zone, getters) {
42776
42801
  if (!cells.length) return {
42777
42802
  zone,
42778
42803
  type: "empty",
42779
- hasHeader: false,
42804
+ headerInZone: false,
42780
42805
  rowCount: 0,
42781
42806
  uniqueCount: 0,
42782
42807
  uniqueRatio: 0,
@@ -42784,16 +42809,34 @@ function analyzeColumn(zone, getters) {
42784
42809
  };
42785
42810
  const firstCell = cells[0];
42786
42811
  const rest = cells.slice(1);
42787
- const hasHeader = firstCell.type === "text" && rest.some((c) => c.type !== "text");
42788
- const dataCells = hasHeader ? rest : cells;
42812
+ let title;
42813
+ let dataCells = [];
42814
+ let headerInZone = false;
42815
+ let analyzedZone = zone;
42816
+ const tableHeaderPosition = getColumnTableHeaderPosition(sheetId, zone, getters);
42817
+ if (tableHeaderPosition) {
42818
+ title = getters.getCellText(tableHeaderPosition) || void 0;
42819
+ dataCells = cells.filter((c) => c.position && c.position.row > tableHeaderPosition.row);
42820
+ headerInZone = !!title && tableHeaderPosition.row >= zone.top && tableHeaderPosition.row <= zone.bottom;
42821
+ if (headerInZone) analyzedZone = {
42822
+ top: tableHeaderPosition.row,
42823
+ bottom: zone.bottom,
42824
+ left: zone.left,
42825
+ right: zone.right
42826
+ };
42827
+ } else if (firstCell.type === "text" && rest.some((c) => c.type !== "text")) {
42828
+ title = firstCell.value;
42829
+ dataCells = rest;
42830
+ headerInZone = true;
42831
+ } else dataCells = cells;
42789
42832
  const numericValues = dataCells.filter((c) => c.type === "number").map((c) => c.value);
42790
42833
  const allVals = dataCells.map((c) => String(c.value ?? ""));
42791
42834
  const uniqueCount = new Set(allVals).size;
42792
42835
  return {
42793
- zone,
42836
+ zone: analyzedZone,
42794
42837
  type: computeColumnType(dataCells),
42795
- header: hasHeader ? firstCell.value : void 0,
42796
- hasHeader,
42838
+ title,
42839
+ headerInZone,
42797
42840
  rowCount: dataCells.length,
42798
42841
  uniqueCount,
42799
42842
  uniqueRatio: allVals.length > 0 ? uniqueCount / allVals.length : 0,
@@ -42819,6 +42862,33 @@ function computeColumnType(cells) {
42819
42862
  }
42820
42863
  return "empty";
42821
42864
  }
42865
+ function getColumnTableHeaderPosition(sheetId, zone, getters) {
42866
+ if (zone.left !== zone.right) return;
42867
+ const tables = getters.getTablesOverlappingZones(sheetId, [zone]);
42868
+ if (tables.length !== 1) return;
42869
+ const table = tables[0];
42870
+ const firstCell = {
42871
+ sheetId,
42872
+ col: zone.left,
42873
+ row: zone.top
42874
+ };
42875
+ const lastCell = {
42876
+ sheetId,
42877
+ col: zone.left,
42878
+ row: zone.bottom
42879
+ };
42880
+ if (firstCell.row < table.range.zone.top || lastCell.row > table.range.zone.bottom) {
42881
+ const cells = getters.getEvaluatedCellsInZone(sheetId, zone).filter((c) => c.type !== "empty");
42882
+ for (const cell of cells) if (cell.position && !isInside(cell.position.col, cell.position.row, table.range.zone)) return;
42883
+ }
42884
+ const numberOfHeaders = table.config.numberOfHeaders;
42885
+ if (numberOfHeaders === 0) return;
42886
+ return {
42887
+ sheetId,
42888
+ col: zone.left,
42889
+ row: table.range.zone.top + numberOfHeaders - 1
42890
+ };
42891
+ }
42822
42892
 
42823
42893
  //#endregion
42824
42894
  //#region src/helpers/figures/charts/charts_suggestions_constants.ts
@@ -43063,6 +43133,10 @@ const SINGLE_DATE_COLUMN_SUGGESTIONS = [{
43063
43133
  description: _t("Shows the last date value."),
43064
43134
  isApplicable: ({ rowCount }) => rowCount === 1,
43065
43135
  build: (ctx) => scorecardChart(ctx.title, `=${ctx.lastCellXC}`)
43136
+ }, {
43137
+ description: _t("Shows occurrences for each time slot."),
43138
+ isApplicable: ({ rowCount }) => rowCount > 1,
43139
+ build: (ctx) => calendarChart(ctx.title, ctx.source)
43066
43140
  }];
43067
43141
  /** Pattern D — Single categorical column */
43068
43142
  const SINGLE_CATEGORICAL_COLUMN_SUGGESTIONS = [
@@ -43373,7 +43447,7 @@ const LABEL_VS_MULTIPLE_NUMBERS_SUGGESTIONS = [
43373
43447
  isApplicable: ({ numColsCount }) => numColsCount === 3,
43374
43448
  build: (ctx) => {
43375
43449
  const bubble = ctx.bubble;
43376
- return bubbleChart(ctx.title, bubble.xRange, bubble.yRanges, bubble.sizeRange, bubble.labelRange, bubble.hasTitle);
43450
+ return bubbleChart(ctx.title, bubble.xRange, bubble.yRanges, bubble.sizeRange, bubble.labelRange, bubble.headerInZone);
43377
43451
  }
43378
43452
  }
43379
43453
  ];
@@ -43470,8 +43544,8 @@ function matchesShape(pattern, shape) {
43470
43544
  });
43471
43545
  }
43472
43546
  function isPyramidLike(numCol1, numCol2) {
43473
- const h1 = numCol1.header ?? "";
43474
- const h2 = numCol2.header ?? "";
43547
+ const h1 = numCol1.title ?? "";
43548
+ const h2 = numCol2.title ?? "";
43475
43549
  return PYRAMID_HEADER_KEYWORD_PATTERNS.some((re) => re.test(h1) || re.test(h2));
43476
43550
  }
43477
43551
  /** Returns the first and last cell XC coordinates, and the second-to-last cell XC coordinate if it exists. */
@@ -43492,25 +43566,26 @@ function interestingCellsXc(col) {
43492
43566
  prevCellXC: prevCellPosition ? toXC(prevCellPosition?.col, prevCellPosition?.row) : void 0
43493
43567
  };
43494
43568
  }
43495
- function getCategoryHeader(getters, catCol) {
43496
- let catHeader = catCol.header ?? "";
43497
- if (!catHeader && catCol.rowCount > 0) {
43569
+ function getCategoryHeader(getters, catCol, headerInZone) {
43570
+ if (catCol.title) return catCol.title;
43571
+ if (headerInZone && catCol.rowCount > 0) {
43498
43572
  const { left, top } = catCol.zone;
43499
- catHeader = (getters.getEvaluatedCell({
43573
+ const cellValue = getters.getEvaluatedCell({
43500
43574
  sheetId: getters.getActiveSheetId(),
43501
43575
  col: left,
43502
43576
  row: top
43503
- })?.value || _t("Category")).toString();
43577
+ })?.value;
43578
+ if (cellValue) return cellValue.toString();
43504
43579
  }
43505
- return catHeader;
43580
+ return _t("Category");
43506
43581
  }
43507
43582
  /** Pattern A — Single numeric column */
43508
43583
  function buildSingleNumberContext([col], getters) {
43509
- const title = col.header ?? "";
43584
+ const title = col.title ?? "";
43510
43585
  const { firstCellXC, lastCellXC, prevCellXC } = interestingCellsXc(col);
43511
43586
  return {
43512
43587
  title,
43513
- source: rangeSource([dataset(col.zone, getters)], col.hasHeader),
43588
+ source: rangeSource([dataset(col.zone, getters)], col.headerInZone),
43514
43589
  rowCount: col.rowCount,
43515
43590
  firstCellXC,
43516
43591
  lastCellXC,
@@ -43519,10 +43594,9 @@ function buildSingleNumberContext([col], getters) {
43519
43594
  }
43520
43595
  /** Pattern B — Single percentage column */
43521
43596
  function buildSinglePercentageContext([col], getters) {
43522
- const hasTitle = col.hasHeader;
43523
- const title = col.header ?? "";
43597
+ const title = col.title ?? "";
43524
43598
  const { firstCellXC, lastCellXC, prevCellXC } = interestingCellsXc(col);
43525
- const source = rangeSource([dataset(col.zone, getters)], hasTitle);
43599
+ const source = rangeSource([dataset(col.zone, getters)], col.headerInZone);
43526
43600
  const isAboveOne = (col.maxValue ?? 0) > 1;
43527
43601
  return {
43528
43602
  title,
@@ -43535,22 +43609,24 @@ function buildSinglePercentageContext([col], getters) {
43535
43609
  };
43536
43610
  }
43537
43611
  /** Pattern C — Single date column */
43538
- function buildSingleDateContext([col]) {
43612
+ function buildSingleDateContext([col], getters) {
43539
43613
  const { lastCellXC } = interestingCellsXc(col);
43614
+ const labelRange = getUnboundRange(getters, col.zone);
43615
+ const source = rangeSource([dataset(col.zone, getters)], col.headerInZone, labelRange);
43540
43616
  return {
43541
- title: col.header ?? "",
43617
+ title: col.title ?? "",
43542
43618
  lastCellXC,
43543
- rowCount: col.rowCount
43619
+ rowCount: col.rowCount,
43620
+ source
43544
43621
  };
43545
43622
  }
43546
43623
  /** Pattern D — Single categorical column */
43547
43624
  function buildSingleCategoricalContext([col], getters) {
43548
- const hasTitle = col.hasHeader;
43549
- const title = col.header ?? "";
43625
+ const title = col.title ?? "";
43550
43626
  const range = getUnboundRange(getters, col.zone);
43551
43627
  return {
43552
43628
  title,
43553
- source: rangeSource([dataset(col.zone, getters)], hasTitle, range),
43629
+ source: rangeSource([dataset(col.zone, getters)], col.headerInZone, range),
43554
43630
  range
43555
43631
  };
43556
43632
  }
@@ -43558,7 +43634,7 @@ function buildSingleCategoricalContext([col], getters) {
43558
43634
  function buildSingleLabelContext([col]) {
43559
43635
  const { lastCellXC } = interestingCellsXc(col);
43560
43636
  return {
43561
- title: "",
43637
+ title: col.title ?? "",
43562
43638
  lastCellXC,
43563
43639
  rowCount: col.rowCount
43564
43640
  };
@@ -43566,37 +43642,37 @@ function buildSingleLabelContext([col]) {
43566
43642
  /** Pattern F — Categorical + Number */
43567
43643
  function buildCategoricalVsNumberContext([catCol, numCol], getters) {
43568
43644
  const labelRange = getUnboundRange(getters, catCol.zone);
43569
- const hasTitle = numCol.hasHeader;
43570
- const categoryHeader = hasTitle ? getCategoryHeader(getters, catCol) : _t("Category");
43645
+ const headerInZone = numCol.headerInZone;
43646
+ const categoryHeader = getCategoryHeader(getters, catCol, headerInZone);
43571
43647
  return {
43572
- title: numCol.header ? _t("%(numberHeader)s by %(categoryHeader)s", {
43573
- numberHeader: numCol.header,
43648
+ title: numCol.title ? _t("%(numberHeader)s by %(categoryHeader)s", {
43649
+ numberHeader: numCol.title,
43574
43650
  categoryHeader
43575
43651
  }) : "",
43576
- source: rangeSource([dataset(numCol.zone, getters)], hasTitle, labelRange),
43577
- treemapSource: rangeSource([dataset(catCol.zone, getters)], hasTitle, getUnboundRange(getters, numCol.zone))
43652
+ source: rangeSource([dataset(numCol.zone, getters)], headerInZone, labelRange),
43653
+ treemapSource: rangeSource([dataset(catCol.zone, getters)], headerInZone, getUnboundRange(getters, numCol.zone))
43578
43654
  };
43579
43655
  }
43580
43656
  /** Patterns G & J — Date + Number or Date + Percentage */
43581
43657
  function buildDateVsSeriesContext([dateCol, seriesCol], getters) {
43582
43658
  const isPercentage = seriesCol.type === "percentage";
43583
43659
  const labelRange = getUnboundRange(getters, dateCol.zone);
43584
- const hasTitle = isDatasetTitled(getters, dateCol.zone);
43660
+ const headerInZone = isDatasetTitled(getters, dateCol.zone);
43585
43661
  return {
43586
- title: seriesCol.header ? _t("%(seriesHeader)s over time", { seriesHeader: seriesCol.header }) : "",
43587
- source: rangeSource([dataset(seriesCol.zone, getters)], hasTitle, labelRange),
43662
+ title: seriesCol.title ? _t("%(seriesHeader)s over time", { seriesHeader: seriesCol.title }) : "",
43663
+ source: rangeSource([dataset(seriesCol.zone, getters)], headerInZone, labelRange),
43588
43664
  isPercentage
43589
43665
  };
43590
43666
  }
43591
43667
  /** Pattern H — Number + Number */
43592
43668
  function buildNumberVsNumberContext([col1, col2], getters) {
43593
- const title = col1.header && col2.header ? _t("%(col2Header)s vs %(col1Header)s", {
43594
- col2Header: col2.header,
43595
- col1Header: col1.header
43669
+ const title = col1.title && col2.title ? _t("%(col2Header)s vs %(col1Header)s", {
43670
+ col2Header: col2.title,
43671
+ col1Header: col1.title
43596
43672
  }) : "";
43597
- const hasTitle = col1.hasHeader || col2.hasHeader;
43598
- const source2 = rangeSource([dataset(col2.zone, getters)], col2.hasHeader, getUnboundRange(getters, col1.zone));
43599
- const sourceBoth = rangeSource([dataset(col1.zone, getters, "0"), dataset(col2.zone, getters, "1")], hasTitle);
43673
+ const headerInZone = col1.headerInZone || col2.headerInZone;
43674
+ const source2 = rangeSource([dataset(col2.zone, getters)], col2.headerInZone, getUnboundRange(getters, col1.zone));
43675
+ const sourceBoth = rangeSource([dataset(col1.zone, getters, "0"), dataset(col2.zone, getters, "1")], headerInZone);
43600
43676
  const { lastCellXC } = interestingCellsXc(col2);
43601
43677
  const { lastCellXC: prevCellXC } = interestingCellsXc(col1);
43602
43678
  return {
@@ -43612,26 +43688,25 @@ function buildNumberVsNumberContext([col1, col2], getters) {
43612
43688
  /** Pattern I — Categorical + Percentage */
43613
43689
  function buildCategoricalVsPercentageContext([catCol, pctCol], getters) {
43614
43690
  const labelRange = getUnboundRange(getters, catCol.zone);
43615
- const hasTitle = pctCol.hasHeader;
43616
- const categoryHeader = hasTitle ? getCategoryHeader(getters, catCol) : _t("Category");
43691
+ const headerInZone = pctCol.headerInZone;
43692
+ const categoryHeader = getCategoryHeader(getters, catCol, headerInZone);
43617
43693
  return {
43618
- title: pctCol.header ? _t("%(percentageHeader)s by %(categoryHeader)s", {
43619
- percentageHeader: pctCol.header,
43694
+ title: pctCol.title ? _t("%(percentageHeader)s by %(categoryHeader)s", {
43695
+ percentageHeader: pctCol.title,
43620
43696
  categoryHeader
43621
43697
  }) : "",
43622
- source: rangeSource([dataset(pctCol.zone, getters)], hasTitle, labelRange),
43698
+ source: rangeSource([dataset(pctCol.zone, getters)], headerInZone, labelRange),
43623
43699
  rowCount: catCol.rowCount
43624
43700
  };
43625
43701
  }
43626
43702
  /** Pattern K — Label + Number */
43627
43703
  function buildLabelVsNumberContext([labelCol, numCol], getters) {
43628
43704
  const labelRange = getUnboundRange(getters, labelCol.zone);
43629
- const hasTitle = numCol.hasHeader;
43630
- const title = numCol.header ? _t("%(numberHeader)s by %(labelHeader)s", {
43631
- numberHeader: numCol.header,
43632
- labelHeader: labelCol.header ?? _t("Name")
43705
+ const title = numCol.title ? _t("%(numberHeader)s by %(labelHeader)s", {
43706
+ numberHeader: numCol.title,
43707
+ labelHeader: labelCol.title ?? _t("Name")
43633
43708
  }) : "";
43634
- const source = rangeSource([dataset(numCol.zone, getters)], hasTitle, labelRange);
43709
+ const source = rangeSource([dataset(numCol.zone, getters)], numCol.headerInZone, labelRange);
43635
43710
  const { lastCellXC } = interestingCellsXc(numCol);
43636
43711
  const { lastCellXC: prevCellXC } = interestingCellsXc(labelCol);
43637
43712
  return {
@@ -43645,66 +43720,66 @@ function buildLabelVsNumberContext([labelCol, numCol], getters) {
43645
43720
  /** Pattern M — Categorical + Multiple Numbers */
43646
43721
  function buildCategoricalVsMultipleNumbersContext([catCol, ...numCols], getters) {
43647
43722
  const labelRange = getUnboundRange(getters, catCol.zone);
43648
- const hasTitle = numCols.some((c) => c.hasHeader);
43649
- const categoryHeader = hasTitle ? getCategoryHeader(getters, catCol) : "";
43723
+ const headerInZone = numCols.some((c) => c.headerInZone);
43724
+ const categoryHeader = getCategoryHeader(getters, catCol, headerInZone);
43650
43725
  return {
43651
- title: hasTitle ? _t("Multi-series By %(categoryHeader)s", { categoryHeader }) : "",
43652
- source: rangeSource(numCols.map((c, i) => dataset(c.zone, getters, String(i))), hasTitle, labelRange),
43726
+ title: headerInZone ? _t("Multi-series By %(categoryHeader)s", { categoryHeader }) : "",
43727
+ source: rangeSource(numCols.map((c, i) => dataset(c.zone, getters, String(i))), headerInZone, labelRange),
43653
43728
  rowCount: catCol.rowCount
43654
43729
  };
43655
43730
  }
43656
43731
  /** Pattern N — Date + Multiple Numbers */
43657
43732
  function buildDateVsMultipleNumbersContext([dateCol, ...numCols], getters) {
43658
43733
  const labelRange = getUnboundRange(getters, dateCol.zone);
43659
- const hasTitle = numCols.some((c) => c.hasHeader) || isDatasetTitled(getters, dateCol.zone);
43734
+ const headerInZone = numCols.some((c) => c.headerInZone) || isDatasetTitled(getters, dateCol.zone);
43660
43735
  return {
43661
- title: numCols.length === 1 && numCols[0].header ? _t("%(header)s over time", { header: numCols[0].header }) : "",
43662
- source: rangeSource(numCols.map((c, i) => dataset(c.zone, getters, String(i))), hasTitle, labelRange)
43736
+ title: numCols.length === 1 && numCols[0].title ? _t("%(header)s over time", { header: numCols[0].title }) : "",
43737
+ source: rangeSource(numCols.map((c, i) => dataset(c.zone, getters, String(i))), headerInZone, labelRange)
43663
43738
  };
43664
43739
  }
43665
43740
  /** Pattern O — Categorical + Categorical + Number */
43666
43741
  function buildMultipleCategoricalsVsNumberContext([cat1, cat2, numCol], getters) {
43667
- const title = numCol.header ? _t("%(numHeader)s by %(cat1Header)s and %(cat2Header)s", {
43668
- numHeader: numCol.header,
43669
- cat1Header: cat1.header ?? _t("Level 1"),
43670
- cat2Header: cat2.header ?? _t("Level 2")
43742
+ const title = numCol.title ? _t("%(numHeader)s by %(cat1Header)s and %(cat2Header)s", {
43743
+ numHeader: numCol.title,
43744
+ cat1Header: cat1.title ?? _t("Level 1"),
43745
+ cat2Header: cat2.title ?? _t("Level 2")
43671
43746
  }) : "";
43672
- const hasTitle = numCol.hasHeader;
43747
+ const headerInZone = numCol.headerInZone;
43673
43748
  return {
43674
43749
  title,
43675
- hierarchySource: rangeSource([dataset(cat1.zone, getters, "0"), dataset(cat2.zone, getters, "1")], hasTitle, getUnboundRange(getters, numCol.zone)),
43676
- barSource: rangeSource([dataset(numCol.zone, getters)], hasTitle, getUnboundRange(getters, cat1.zone))
43750
+ hierarchySource: rangeSource([dataset(cat1.zone, getters, "0"), dataset(cat2.zone, getters, "1")], headerInZone, getUnboundRange(getters, numCol.zone)),
43751
+ barSource: rangeSource([dataset(numCol.zone, getters)], headerInZone, getUnboundRange(getters, cat1.zone))
43677
43752
  };
43678
43753
  }
43679
43754
  /** Pattern P — Categorical + Date + Number */
43680
43755
  function buildCategoricalDateNumberContext([catCol, dateCol, numCol], getters) {
43681
43756
  const dateRange = getUnboundRange(getters, dateCol.zone);
43682
43757
  const catRange = getUnboundRange(getters, catCol.zone);
43683
- const hasTitle = numCol.hasHeader;
43684
- const catHeader = hasTitle ? getCategoryHeader(getters, catCol) : _t("Category");
43758
+ const headerInZone = numCol.headerInZone;
43759
+ const catHeader = getCategoryHeader(getters, catCol, headerInZone);
43685
43760
  return {
43686
- title: numCol.header ? _t("%(numHeader)s by %(catHeader)s over %(dateHeader)s", {
43687
- numHeader: numCol.header,
43761
+ title: numCol.title ? _t("%(numHeader)s by %(catHeader)s over %(dateHeader)s", {
43762
+ numHeader: numCol.title,
43688
43763
  catHeader,
43689
- dateHeader: dateCol.header ?? _t("Time")
43764
+ dateHeader: dateCol.title ?? _t("Time")
43690
43765
  }) : "",
43691
- sourceByDate: rangeSource([dataset(numCol.zone, getters)], hasTitle, dateRange),
43692
- sourceByCat: rangeSource([dataset(numCol.zone, getters)], hasTitle, catRange)
43766
+ sourceByDate: rangeSource([dataset(numCol.zone, getters)], headerInZone, dateRange),
43767
+ sourceByCat: rangeSource([dataset(numCol.zone, getters)], headerInZone, catRange)
43693
43768
  };
43694
43769
  }
43695
43770
  /** Pattern Q — Label + Multiple Numbers */
43696
43771
  function buildLabelVsMultipleNumbersContext([labelCol, ...numCols], getters) {
43697
43772
  const labelRange = getUnboundRange(getters, labelCol.zone);
43698
- const hasTitle = numCols.some((c) => c.hasHeader);
43699
- const title = labelCol.header ? _t("By %(header)s", { header: labelCol.header }) : "";
43700
- const source = rangeSource(numCols.map((c, i) => dataset(c.zone, getters, String(i))), hasTitle, labelRange);
43701
- const scatterSource = rangeSource([dataset(numCols[1].zone, getters)], numCols[1].hasHeader, getUnboundRange(getters, numCols[0].zone));
43773
+ const headerInZone = numCols.some((c) => c.headerInZone);
43774
+ const title = labelCol.title ? _t("By %(title)s", { title: labelCol.title }) : "";
43775
+ const source = rangeSource(numCols.map((c, i) => dataset(c.zone, getters, String(i))), headerInZone, labelRange);
43776
+ const scatterSource = rangeSource([dataset(numCols[1].zone, getters)], numCols[1].headerInZone, getUnboundRange(getters, numCols[0].zone));
43702
43777
  const bubble = numCols.length === 3 ? {
43703
43778
  xRange: getUnboundRange(getters, numCols[0].zone),
43704
43779
  yRanges: [getUnboundRange(getters, numCols[1].zone)],
43705
43780
  sizeRange: getUnboundRange(getters, numCols[2].zone),
43706
43781
  labelRange,
43707
- hasTitle
43782
+ headerInZone
43708
43783
  } : void 0;
43709
43784
  return {
43710
43785
  title,
@@ -43718,25 +43793,25 @@ function buildLabelVsMultipleNumbersContext([labelCol, ...numCols], getters) {
43718
43793
  /** Pattern R — Categorical + Two Numbers (Population Pyramid or Grouped) */
43719
43794
  function buildCategoricalTwoNumbersContext([catCol, numCol1, numCol2], getters) {
43720
43795
  const catRange = getUnboundRange(getters, catCol.zone);
43721
- const hasTitle = numCol1.hasHeader || numCol2.hasHeader;
43722
- const catHeader = hasTitle ? getCategoryHeader(getters, catCol) : _t("Category");
43723
- const title = numCol1.header && numCol2.header ? _t("%(num1Header)s vs %(num2Header)s by %(catHeader)s", {
43724
- num1Header: numCol1.header,
43725
- num2Header: numCol2.header,
43796
+ const headerInZone = numCol1.headerInZone || numCol2.headerInZone;
43797
+ const catHeader = getCategoryHeader(getters, catCol, headerInZone);
43798
+ const title = numCol1.title && numCol2.title ? _t("%(num1Header)s vs %(num2Header)s by %(catHeader)s", {
43799
+ num1Header: numCol1.title,
43800
+ num2Header: numCol2.title,
43726
43801
  catHeader
43727
43802
  }) : "";
43728
43803
  const isPyramid = isPyramidLike(numCol1, numCol2);
43729
43804
  return {
43730
43805
  title,
43731
- sourceBoth: rangeSource([dataset(numCol1.zone, getters, "0"), dataset(numCol2.zone, getters, "1")], hasTitle, catRange),
43806
+ sourceBoth: rangeSource([dataset(numCol1.zone, getters, "0"), dataset(numCol2.zone, getters, "1")], headerInZone, catRange),
43732
43807
  isPyramid
43733
43808
  };
43734
43809
  }
43735
43810
  /** Pattern S — Many Numbers (3+ numeric columns, no categorical/date) */
43736
43811
  function buildManyNumbersContext(cols, getters) {
43737
- const title = cols.every((c) => c.hasHeader) ? cols.map((c) => c.header).join(" / ") : "";
43738
- const hasTitle = cols.some((c) => c.hasHeader);
43739
- const source = rangeSource(cols.map((c, i) => dataset(c.zone, getters, String(i))), hasTitle);
43812
+ const title = cols.every((c) => c.headerInZone) ? cols.map((c) => c.title).join(" / ") : "";
43813
+ const headerInZone = cols.some((c) => c.headerInZone);
43814
+ const source = rangeSource(cols.map((c, i) => dataset(c.zone, getters, String(i))), headerInZone);
43740
43815
  const { lastCellXC } = interestingCellsXc(cols[2]);
43741
43816
  const { lastCellXC: firstCellXC } = interestingCellsXc(cols[0]);
43742
43817
  const { lastCellXC: secondCellXC } = interestingCellsXc(cols[1]);
@@ -43751,6 +43826,7 @@ function buildManyNumbersContext(cols, getters) {
43751
43826
  };
43752
43827
  }
43753
43828
  const NUMBER_OR_PERCENTAGE = ["number", "percentage"];
43829
+ const CATEGORICAL_OR_BOOLEAN = ["categorical", "boolean"];
43754
43830
  const EXACT_PATTERNS = [
43755
43831
  {
43756
43832
  pattern: { leadingTypes: ["number"] },
@@ -43768,7 +43844,7 @@ const EXACT_PATTERNS = [
43768
43844
  suggestions: SINGLE_DATE_COLUMN_SUGGESTIONS
43769
43845
  },
43770
43846
  {
43771
- pattern: { leadingTypes: ["categorical"] },
43847
+ pattern: { leadingTypes: [CATEGORICAL_OR_BOOLEAN] },
43772
43848
  buildContext: buildSingleCategoricalContext,
43773
43849
  suggestions: SINGLE_CATEGORICAL_COLUMN_SUGGESTIONS
43774
43850
  },
@@ -43778,7 +43854,7 @@ const EXACT_PATTERNS = [
43778
43854
  suggestions: SINGLE_LABEL_COLUMN_SUGGESTIONS
43779
43855
  },
43780
43856
  {
43781
- pattern: { leadingTypes: ["categorical", "number"] },
43857
+ pattern: { leadingTypes: [CATEGORICAL_OR_BOOLEAN, "number"] },
43782
43858
  buildContext: buildCategoricalVsNumberContext,
43783
43859
  suggestions: CATEGORICAL_VS_NUMBER_SUGGESTIONS
43784
43860
  },
@@ -43793,7 +43869,7 @@ const EXACT_PATTERNS = [
43793
43869
  suggestions: NUMBER_VS_NUMBER_SUGGESTIONS
43794
43870
  },
43795
43871
  {
43796
- pattern: { leadingTypes: ["categorical", "percentage"] },
43872
+ pattern: { leadingTypes: [CATEGORICAL_OR_BOOLEAN, "percentage"] },
43797
43873
  buildContext: buildCategoricalVsPercentageContext,
43798
43874
  suggestions: CATEGORICAL_VS_PERCENTAGE_SUGGESTIONS
43799
43875
  },
@@ -43809,8 +43885,8 @@ const EXACT_PATTERNS = [
43809
43885
  },
43810
43886
  {
43811
43887
  pattern: { leadingTypes: [
43812
- "categorical",
43813
- "categorical",
43888
+ CATEGORICAL_OR_BOOLEAN,
43889
+ CATEGORICAL_OR_BOOLEAN,
43814
43890
  "number"
43815
43891
  ] },
43816
43892
  buildContext: buildMultipleCategoricalsVsNumberContext,
@@ -43818,7 +43894,7 @@ const EXACT_PATTERNS = [
43818
43894
  },
43819
43895
  {
43820
43896
  pattern: { leadingTypes: [
43821
- "categorical",
43897
+ CATEGORICAL_OR_BOOLEAN,
43822
43898
  "label",
43823
43899
  "number"
43824
43900
  ] },
@@ -43827,7 +43903,7 @@ const EXACT_PATTERNS = [
43827
43903
  },
43828
43904
  {
43829
43905
  pattern: { leadingTypes: [
43830
- "categorical",
43906
+ CATEGORICAL_OR_BOOLEAN,
43831
43907
  "date",
43832
43908
  NUMBER_OR_PERCENTAGE
43833
43909
  ] },
@@ -43836,7 +43912,7 @@ const EXACT_PATTERNS = [
43836
43912
  },
43837
43913
  {
43838
43914
  pattern: { leadingTypes: [
43839
- "categorical",
43915
+ CATEGORICAL_OR_BOOLEAN,
43840
43916
  NUMBER_OR_PERCENTAGE,
43841
43917
  NUMBER_OR_PERCENTAGE
43842
43918
  ] },
@@ -57231,7 +57307,7 @@ function pivot_presentation_default(PivotClass) {
57231
57307
  return this.strictMeasureValueToNumber(comparedValue);
57232
57308
  }
57233
57309
  getPivotValueCells(measureId) {
57234
- return this.getCollapsedTableStructure().getPivotCells().map((col) => col.filter((cell) => cell.type === "VALUE" && cell.measure === measureId)).filter((col) => col.length > 0);
57310
+ return this.getExpandedTableStructure().getPivotCells().map((col) => col.filter((cell) => cell.type === "VALUE" && cell.measure === measureId)).filter((col) => col.length > 0);
57235
57311
  }
57236
57312
  measureValueToNumber(result) {
57237
57313
  if (typeof result.value === "number") return result.value;
@@ -65927,7 +66003,7 @@ var EvaluationChartPlugin = class extends EvaluationPlugin {
65927
66003
  * Get the background and textColor of a chart based on the color of the first cell of the main range of the chart.
65928
66004
  */
65929
66005
  getStyleOfSingleCellChart(chartBackground, mainRange, colorThemeName) {
65930
- const themeBackground = COLOR_THEMES[colorThemeName].backgroundColor;
66006
+ const themeBackground = COLOR_THEMES[colorThemeName].chartBackgroundColor;
65931
66007
  if (chartBackground) return {
65932
66008
  background: chartBackground,
65933
66009
  fontColor: chartFontColor(chartBackground)
@@ -66981,14 +67057,12 @@ var SubtotalEvaluationPlugin = class extends EvaluationPlugin {
66981
67057
  var UIPlugin = class extends BasePlugin {
66982
67058
  static layers = [];
66983
67059
  getters;
66984
- ui;
66985
67060
  selection;
66986
67061
  dispatch;
66987
67062
  canDispatch;
66988
- constructor({ getters, stateObserver, dispatch, canDispatch, uiActions, selection }) {
67063
+ constructor({ getters, stateObserver, dispatch, canDispatch, selection }) {
66989
67064
  super(stateObserver);
66990
67065
  this.getters = getters;
66991
- this.ui = uiActions;
66992
67066
  this.selection = selection;
66993
67067
  this.dispatch = dispatch;
66994
67068
  this.canDispatch = canDispatch;
@@ -72457,9 +72531,7 @@ var SpreadsheetDashboard = class extends Component {
72457
72531
  return cssPropertiesToCss({ zoom: this.zoomStore.cssZoom });
72458
72532
  }
72459
72533
  get backgroundStyle() {
72460
- const sheet = this.env.model.getters.getActiveSheet();
72461
- const theme = this.env.model.getters.getSpreadsheetTheme();
72462
- return cssPropertiesToCss({ "background-color": sheet.backgroundColor || theme.backgroundColor });
72534
+ return cssPropertiesToCss({ "background-color": this.env.model.getters.getActiveSheet().backgroundColor });
72463
72535
  }
72464
72536
  };
72465
72537
 
@@ -73065,7 +73137,7 @@ var FigureRendererStore = class extends DisposableStore {
73065
73137
  ctx.beginPath();
73066
73138
  ctx.rect(figureRect.x, figureRect.y, figureRect.width, figureRect.height);
73067
73139
  ctx.clip();
73068
- ctx.fillStyle = chartDefinition?.background || this.getters.getSpreadsheetTheme().backgroundColor;
73140
+ ctx.fillStyle = chartDefinition?.background || this.getters.getSpreadsheetTheme().chartBackgroundColor;
73069
73141
  ctx.fillRect(figureRect.x, figureRect.y, figureRect.width, figureRect.height);
73070
73142
  const title = {
73071
73143
  ...DEFAULT_CAROUSEL_TITLE_STYLE,
@@ -74973,14 +75045,10 @@ var Spreadsheet = class extends Component {
74973
75045
  sticky: false
74974
75046
  });
74975
75047
  });
74976
- this.model.on("notify-ui", this, (notification) => this.notificationStore.notifyUser(notification));
74977
- this.model.on("raise-error-ui", this, ({ text }) => this.notificationStore.raiseError(text));
74978
75048
  }
74979
75049
  unbindModelEvents() {
74980
75050
  this.model.off("update", this);
74981
75051
  this.model.off("command-rejected", this);
74982
- this.model.off("notify-ui", this);
74983
- this.model.off("raise-error-ui", this);
74984
75052
  }
74985
75053
  checkViewportSize() {
74986
75054
  const { xRatio, yRatio } = this.viewStore.viewports.getFrozenSheetViewRatio(this.viewStore.displayedSheetId);
@@ -79395,8 +79463,6 @@ var Model = class Model extends EventBus {
79395
79463
  client,
79396
79464
  moveClient: () => {},
79397
79465
  snapshotRequested: false,
79398
- notifyUI: (payload) => this.trigger("notify-ui", payload),
79399
- raiseBlockingErrorUI: (text) => this.trigger("raise-error-ui", { text }),
79400
79466
  customColors: config.customColors || []
79401
79467
  };
79402
79468
  }
@@ -79440,7 +79506,6 @@ var Model = class Model extends EventBus {
79440
79506
  selection: this.selection,
79441
79507
  moveClient: this.session.move.bind(this.session),
79442
79508
  custom: this.config.custom,
79443
- uiActions: this.config,
79444
79509
  session: this.session,
79445
79510
  defaultCurrency: this.config.defaultCurrency,
79446
79511
  customColors: this.config.customColors || [],
@@ -79576,7 +79641,15 @@ var Model = class Model extends EventBus {
79576
79641
  dispatchFromEvaluationPlugin = (type, payload) => {
79577
79642
  const command = createCommand(type, payload);
79578
79643
  if (!isDispatcheableEvaluationCommand(command)) throw new Error(`An evaluation plugin cannot dispatch non-evaluation commands (${type})`);
79644
+ if (this.status !== 0) {
79645
+ this.dispatchToHandlers(this.evaluationHandlers, command);
79646
+ return DispatchResult.Success;
79647
+ }
79648
+ this.status = 3;
79579
79649
  this.dispatchToHandlers(this.evaluationHandlers, command);
79650
+ this.finalize();
79651
+ this.status = 0;
79652
+ this.trigger("update");
79580
79653
  return DispatchResult.Success;
79581
79654
  };
79582
79655
  /**
@@ -82116,7 +82189,7 @@ const BubbleChart = {
82116
82189
  legend: getBubbleChartLegend(definition, chartData),
82117
82190
  tooltip: getBubbleChartTooltip(definition, chartData),
82118
82191
  chartShowValuesPlugin: getChartShowValues(definition, chartData),
82119
- background: { color: definition.background }
82192
+ background: { color: chartData.background }
82120
82193
  }
82121
82194
  }
82122
82195
  } };
@@ -91356,6 +91429,6 @@ const chartHelpers = {
91356
91429
  //#endregion
91357
91430
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, BadExpressionError, CHART_TYPES, CellErrorType, CellValueType, CircularDependencyError, ClientDisconnectedError, ClipboardMIMEType, CommandResult, CompiledFormula, CorePlugin, DEFAULT_LOCALE, DEFAULT_LOCALES, DEFAULT_LOCALE_DIGIT_GROUPING, DIRECTION, DispatchResult, DivisionByZeroError, EvaluationError, EvaluationPlugin, InvalidReferenceError, LocalTransportService, Model, NEXT_VALUE, NotAvailableError, NumberTooLargeError, OrderedLayers, PREVIOUS_VALUE, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, SplillBlockedError, Spreadsheet, SpreadsheetPivotTable, UIPlugin, UnknownFunctionError, __info__, addFunction, addRenderingLayer, astToFormula, availableConditionalFormatOperators, availableDataValidationOperators, availableFiltersOperators, borderPositions, borderStyles, canExecuteInReadonly, categories, chartHelpers, compatibility, components, composerFocusTypes, constants, convertAstNodes, coreTypes, createAutocompleteArgumentsProvider, dispatcheableEvaluationCommandTypes, errorTypes, evaluationCommandTypes, filterDateCriterionOperators, filterNumberCriterionOperators, filterTextCriterionOperators, findCellInNewZone, functionCache, getCaretDownSvg, getCaretUpSvg, helpers, hooks, invalidSubtotalFormulasCommands, invalidateBordersCommands, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, isCoreCommand, isDispatcheableEvaluationCommand, isEvaluationCommand, isHeadersDependant, isMatrix, isPositionDependent, isRangeDependant, isSheetDependent, isTargetDependent, isZoneDependent, iterateAstNodes, links, load, lockedSheetAllowedCommands, owlPlugins, parse, parseTokens, readonlyAllowedCommands, registries, schemeToColorScale, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
91358
91431
 
91359
- __info__.version = "19.5.0-alpha.19";
91360
- __info__.date = "2026-09-10T05:38:44.935Z";
91361
- __info__.hash = "2b1e397";
91432
+ __info__.version = "19.5.0-alpha.20";
91433
+ __info__.date = "2026-09-16T08:02:11.430Z";
91434
+ __info__.hash = "4784627";