@odoo/o-spreadsheet 19.1.0-alpha.3 → 19.1.0-alpha.4

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.1.0-alpha.3
6
- * @date 2025-09-23T12:37:52.238Z
7
- * @hash ce2b07a
5
+ * @version 19.1.0-alpha.4
6
+ * @date 2025-10-07T10:03:20.917Z
7
+ * @hash b7cfed8
8
8
  */
9
9
 
10
10
  'use strict';
@@ -593,7 +593,6 @@ const BACKGROUND_HEADER_COLOR = "#F8F9FA";
593
593
  const BACKGROUND_HEADER_SELECTED_COLOR = "#E8EAED";
594
594
  const BACKGROUND_HEADER_ACTIVE_COLOR = "#595959";
595
595
  const TEXT_HEADER_COLOR = "#666666";
596
- const FIGURE_BORDER_COLOR = "#c9ccd2";
597
596
  const SELECTION_BORDER_COLOR = "#3266ca";
598
597
  const HEADER_BORDER_COLOR = "#C0C0C0";
599
598
  const CELL_BORDER_COLOR = "#E2E3E3";
@@ -601,7 +600,6 @@ const BACKGROUND_CHART_COLOR = "#FFFFFF";
601
600
  const DEFAULT_COLOR_SCALE_MIDPOINT_COLOR = 0xb6d7a8;
602
601
  const LINK_COLOR = HIGHLIGHT_COLOR;
603
602
  const FILTERS_COLOR = "#188038";
604
- const HEADER_GROUPING_BORDER_COLOR = "#999";
605
603
  const FROZEN_PANE_HEADER_BORDER_COLOR = "#BCBCBC";
606
604
  const FROZEN_PANE_BORDER_COLOR = "#DADFE8";
607
605
  const COMPOSER_ASSISTANT_COLOR = "#9B359B";
@@ -844,22 +842,6 @@ const DRAG_THRESHOLD = 5; // in pixels, to avoid unwanted drag when clicking
844
842
  // Miscellaneous
845
843
  //------------------------------------------------------------------------------
846
844
  const sanitizeSheetNameRegex = new RegExp(FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX, "g");
847
- /**
848
- * Remove quotes from a quoted string
849
- * ```js
850
- * removeStringQuotes('"Hello"')
851
- * > 'Hello'
852
- * ```
853
- */
854
- function removeStringQuotes(str) {
855
- if (str[0] === '"') {
856
- str = str.slice(1);
857
- }
858
- if (str[str.length - 1] === '"' && str[str.length - 2] !== "\\") {
859
- return str.slice(0, str.length - 1);
860
- }
861
- return str;
862
- }
863
845
  function isCloneable(obj) {
864
846
  return "clone" in obj && obj.clone instanceof Function;
865
847
  }
@@ -928,6 +910,13 @@ function isPlainObject(obj) {
928
910
  function getUnquotedSheetName(sheetName) {
929
911
  return unquote(sheetName, "'");
930
912
  }
913
+ /**
914
+ * Remove quotes from a quoted string
915
+ * ```js
916
+ * unquote('"Hello"')
917
+ * > 'Hello'
918
+ * ```
919
+ */
931
920
  function unquote(string, quoteChar = '"') {
932
921
  if (string.startsWith(quoteChar)) {
933
922
  string = string.slice(1);
@@ -1332,9 +1321,7 @@ function removeIndexesFromArray(array, indexes) {
1332
1321
  return newArray;
1333
1322
  }
1334
1323
  function insertItemsAtIndex(array, items, index) {
1335
- const newArray = [...array];
1336
- newArray.splice(index, 0, ...items);
1337
- return newArray;
1324
+ return array.slice(0, index).concat(items).concat(array.slice(index));
1338
1325
  }
1339
1326
  function replaceItemAtIndex(array, newItem, index) {
1340
1327
  const newArray = [...array];
@@ -5584,7 +5571,7 @@ function tokensToTextInternalFormat(tokens) {
5584
5571
  * Replace in place tokens "mm" and "m" that denote minutes in date format with "MM" to avoid confusion with months.
5585
5572
  *
5586
5573
  * As per OpenXML specification, in date formats if a date token "m" or "mm" is followed by a date token "s" or
5587
- * preceded by a data token "h", then it's not a month but an minute.
5574
+ * preceded by a data token "h", then it's not a month but a minute.
5588
5575
  */
5589
5576
  function convertTokensToMinutesInDateFormat(tokens) {
5590
5577
  const dateParts = tokens.filter((token) => token.type === "DATE_PART");
@@ -5627,6 +5614,9 @@ function internalFormatPartToFormat(internalFormat) {
5627
5614
  case "REPEATED_CHAR":
5628
5615
  format += "*" + token.value;
5629
5616
  break;
5617
+ case "DATE_PART":
5618
+ format += token.value === "MM" ? "mm" : token.value; // Convert "MM" back to "mm" for minutes
5619
+ break;
5630
5620
  default:
5631
5621
  format += token.value;
5632
5622
  }
@@ -5700,7 +5690,7 @@ function formatValue(value, { format, locale, formatWidth }) {
5700
5690
  return value;
5701
5691
  }
5702
5692
  const internalFormat = parseFormat(format);
5703
- const formatToApply = internalFormat.text || internalFormat.positive;
5693
+ const formatToApply = getFormatToApply(value, internalFormat).format;
5704
5694
  if (!formatToApply || formatToApply.type !== "text") {
5705
5695
  return value;
5706
5696
  }
@@ -5711,16 +5701,15 @@ function formatValue(value, { format, locale, formatWidth }) {
5711
5701
  format = createDefaultFormat(value);
5712
5702
  }
5713
5703
  const internalFormat = parseFormat(format);
5714
- if (internalFormat.positive.type === "text") {
5715
- return applyTextInternalFormat(value.toString(), internalFormat.positive, formatWidth);
5704
+ const { format: formatToApply, isNegativeFormat } = getFormatToApply(value, internalFormat);
5705
+ if (!formatToApply) {
5706
+ return value.toString();
5716
5707
  }
5717
- let formatToApply = internalFormat.positive;
5718
- if (value < 0 && internalFormat.negative) {
5719
- formatToApply = internalFormat.negative;
5720
- value = -value;
5708
+ if (formatToApply.type === "text") {
5709
+ return applyTextInternalFormat(value.toString(), formatToApply, formatWidth);
5721
5710
  }
5722
- else if (value === 0 && internalFormat.zero) {
5723
- formatToApply = internalFormat.zero;
5711
+ if (isNegativeFormat) {
5712
+ value = Math.abs(value);
5724
5713
  }
5725
5714
  if (formatToApply.type === "date") {
5726
5715
  return repeatCharToFitWidth(applyDateTimeFormat(value, formatToApply), formatWidth);
@@ -5732,6 +5721,31 @@ function formatValue(value, { format, locale, formatWidth }) {
5732
5721
  return "";
5733
5722
  }
5734
5723
  }
5724
+ function getFormatToApply(value, internalFormat) {
5725
+ let formatToApply = undefined;
5726
+ let isNegativeFormat = false;
5727
+ switch (typeof value) {
5728
+ case "number":
5729
+ if (value < 0 && internalFormat.negative) {
5730
+ formatToApply = internalFormat.negative;
5731
+ isNegativeFormat = true;
5732
+ }
5733
+ else if (value === 0 && internalFormat.zero) {
5734
+ formatToApply = internalFormat.zero;
5735
+ }
5736
+ else {
5737
+ formatToApply = internalFormat.positive;
5738
+ }
5739
+ break;
5740
+ case "string":
5741
+ const format = internalFormat.text || internalFormat.positive;
5742
+ if (format.type === "text") {
5743
+ formatToApply = format;
5744
+ }
5745
+ break;
5746
+ }
5747
+ return { format: formatToApply, isNegativeFormat };
5748
+ }
5735
5749
  function applyTextInternalFormat(value, internalFormat, formatWidth) {
5736
5750
  let formattedValue = "";
5737
5751
  for (const token of internalFormat.tokens) {
@@ -6343,6 +6357,27 @@ function isTextFormat(format) {
6343
6357
  return false;
6344
6358
  }
6345
6359
  }
6360
+ function formatHasRepeatedChar(value, format) {
6361
+ if (!format) {
6362
+ return false;
6363
+ }
6364
+ try {
6365
+ const internalFormat = parseFormat(format);
6366
+ const { format: formatToApply } = getFormatToApply(value, internalFormat);
6367
+ if (formatToApply?.type === "text" || formatToApply?.type === "date") {
6368
+ const tokens = formatToApply.tokens;
6369
+ return tokens.some((token) => token.type === "REPEATED_CHAR");
6370
+ }
6371
+ else if (formatToApply?.type === "number") {
6372
+ return (formatToApply.integerPart.some((token) => token.type === "REPEATED_CHAR") ||
6373
+ (formatToApply.decimalPart
6374
+ ? formatToApply.decimalPart.some((token) => token.type === "REPEATED_CHAR")
6375
+ : false));
6376
+ }
6377
+ }
6378
+ catch { }
6379
+ return false;
6380
+ }
6346
6381
 
6347
6382
  function evaluateLiteral(literalCell, localeFormat, position) {
6348
6383
  const value = isTextFormat(localeFormat.format) && literalCell.parsedValue !== null
@@ -18637,7 +18672,7 @@ function parseOperand(tokens) {
18637
18672
  case "STRING":
18638
18673
  return {
18639
18674
  type: "STRING",
18640
- value: removeStringQuotes(current.value),
18675
+ value: unquote(current.value),
18641
18676
  tokenStartIndex: current.tokenIndex,
18642
18677
  tokenEndIndex: current.tokenIndex,
18643
18678
  };
@@ -22394,7 +22429,7 @@ function formulaArguments(tokens) {
22394
22429
  dependencies.push(token.value);
22395
22430
  break;
22396
22431
  case "STRING":
22397
- const value = removeStringQuotes(token.value);
22432
+ const value = unquote(token.value);
22398
22433
  literalValues.strings.push({ value });
22399
22434
  break;
22400
22435
  case "NUMBER": {
@@ -24646,6 +24681,7 @@ class ScorecardChart extends owl.Component {
24646
24681
  static template = "o-spreadsheet-ScorecardChart";
24647
24682
  static props = {
24648
24683
  chartId: String,
24684
+ isFullScreen: { type: Boolean, optional: true },
24649
24685
  };
24650
24686
  canvas = owl.useRef("chartContainer");
24651
24687
  get runtime() {
@@ -27409,26 +27445,6 @@ function createBarChartRuntime(chart, getters) {
27409
27445
  return { chartJsConfig: config, background: chart.background || BACKGROUND_CHART_COLOR };
27410
27446
  }
27411
27447
 
27412
- class FullScreenChartStore extends SpreadsheetStore {
27413
- mutators = ["toggleFullScreenChart"];
27414
- fullScreenFigure = undefined;
27415
- toggleFullScreenChart(figureId) {
27416
- if (this.fullScreenFigure?.id === figureId) {
27417
- this.fullScreenFigure = undefined;
27418
- }
27419
- else {
27420
- this.makeFullScreen(figureId);
27421
- }
27422
- }
27423
- makeFullScreen(figureId) {
27424
- const sheetId = this.getters.getActiveSheetId();
27425
- const figure = this.getters.getFigure(sheetId, figureId);
27426
- if (figure) {
27427
- this.fullScreenFigure = { ...figure, x: 0, y: 0, width: 0, height: 0 };
27428
- }
27429
- }
27430
- }
27431
-
27432
27448
  const TREND_LINE_AXES_IDS = [TREND_LINE_XAXIS_ID, MOVING_AVERAGE_TREND_LINE_XAXIS_ID];
27433
27449
  const ZOOMABLE_AXIS_IDS = ["x", ...TREND_LINE_AXES_IDS];
27434
27450
  class ZoomableChartStore extends SpreadsheetStore {
@@ -27593,7 +27609,6 @@ chartJsExtensionRegistry.add("zoomWindowPlugin", {
27593
27609
  class ZoomableChartJsComponent extends ChartJsComponent {
27594
27610
  static template = "o-spreadsheet-ZoomableChartJsComponent";
27595
27611
  store;
27596
- fullScreenChartStore;
27597
27612
  masterChartCanvas = owl.useRef("masterChartCanvas");
27598
27613
  masterChart;
27599
27614
  mode;
@@ -27604,7 +27619,6 @@ class ZoomableChartJsComponent extends ChartJsComponent {
27604
27619
  removeEventListeners = () => { };
27605
27620
  setup() {
27606
27621
  this.store = useStore(ZoomableChartStore);
27607
- this.fullScreenChartStore = useStore(FullScreenChartStore);
27608
27622
  super.setup();
27609
27623
  }
27610
27624
  unmount() {
@@ -27619,12 +27633,8 @@ class ZoomableChartJsComponent extends ChartJsComponent {
27619
27633
  `;
27620
27634
  }
27621
27635
  get sliceable() {
27622
- if (this.env.isDashboard()) {
27623
- const fullScreenFigureId = this.fullScreenChartStore.fullScreenFigure?.id;
27624
- const chartFigureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
27625
- if (fullScreenFigureId === chartFigureId) {
27626
- return true;
27627
- }
27636
+ if (this.props.isFullScreen) {
27637
+ return true;
27628
27638
  }
27629
27639
  const definition = this.env.model.getters.getChartDefinition(this.props.chartId);
27630
27640
  return ("zoomable" in definition && definition?.zoomable) ?? false;
@@ -27687,9 +27697,6 @@ class ZoomableChartJsComponent extends ChartJsComponent {
27687
27697
  const xMax = Math.max(...xValues);
27688
27698
  return { xMin, xMax };
27689
27699
  }
27690
- get shouldAnimate() {
27691
- return this.env.model.getters.isDashboard() && !this.sliceable;
27692
- }
27693
27700
  createChart(chartRuntime) {
27694
27701
  const chartData = chartRuntime.chartJsConfig;
27695
27702
  this.isBarChart = chartData.type === "bar";
@@ -27708,6 +27715,9 @@ class ZoomableChartJsComponent extends ChartJsComponent {
27708
27715
  const masterChartCtx = this.masterChartCanvas.el.getContext("2d");
27709
27716
  this.masterChart = new window.Chart(masterChartCtx, this.getMasterChartConfiguration(chartRuntime["masterChartConfig"]));
27710
27717
  this.resetAxesLimits();
27718
+ if (this.chart?.options) {
27719
+ this.chart.options.animation = false;
27720
+ }
27711
27721
  }
27712
27722
  updateChartJs(chartRuntime) {
27713
27723
  const chartData = chartRuntime.chartJsConfig;
@@ -27741,6 +27751,9 @@ class ZoomableChartJsComponent extends ChartJsComponent {
27741
27751
  }
27742
27752
  }
27743
27753
  this.resetAxesLimits();
27754
+ if (this.chart?.options) {
27755
+ this.chart.options.animation = false;
27756
+ }
27744
27757
  }
27745
27758
  resetAxesLimits() {
27746
27759
  if (!this.chart) {
@@ -27838,7 +27851,7 @@ class ZoomableChartJsComponent extends ChartJsComponent {
27838
27851
  onPointerDownInMasterChart(ev) {
27839
27852
  this.removeEventListeners();
27840
27853
  const position = ev.offsetX;
27841
- if (!this.masterChart?.chartArea || !this.chart?.scales.x) {
27854
+ if (!this.masterChart?.chartArea || !this.chart?.scales?.x) {
27842
27855
  return;
27843
27856
  }
27844
27857
  const { left, right, top, bottom } = this.masterChart.chartArea;
@@ -31396,6 +31409,26 @@ function getCarouselItemTitle(getters, item) {
31396
31409
  return matchedChart.displayName;
31397
31410
  }
31398
31411
 
31412
+ class FullScreenFigureStore extends SpreadsheetStore {
31413
+ mutators = ["toggleFullScreenFigure"];
31414
+ fullScreenFigure = undefined;
31415
+ toggleFullScreenFigure(figureId) {
31416
+ if (this.fullScreenFigure?.id === figureId) {
31417
+ this.fullScreenFigure = undefined;
31418
+ }
31419
+ else {
31420
+ this.makeFullScreen(figureId);
31421
+ }
31422
+ }
31423
+ makeFullScreen(figureId) {
31424
+ const sheetId = this.getters.getActiveSheetId();
31425
+ const figure = this.getters.getFigure(sheetId, figureId);
31426
+ if (figure) {
31427
+ this.fullScreenFigure = { ...figure, x: 0, y: 0, width: 0, height: 0 };
31428
+ }
31429
+ }
31430
+ }
31431
+
31399
31432
  /**
31400
31433
  * This file is largely inspired by owl 1.
31401
31434
  * `css` tag has been removed from owl 2 without workaround to manage css.
@@ -32133,12 +32166,13 @@ class MenuPopover extends owl.Component {
32133
32166
  class ChartDashboardMenu extends owl.Component {
32134
32167
  static template = "o-spreadsheet-ChartDashboardMenu";
32135
32168
  static components = { MenuPopover };
32136
- static props = { chartId: String };
32169
+ static props = { chartId: String, hasFullScreenButton: { type: Boolean, optional: true } };
32170
+ static defaultProps = { hasFullScreenButton: true };
32137
32171
  fullScreenFigureStore;
32138
32172
  menuState = owl.useState({ isOpen: false, anchorRect: null, menuItems: [] });
32139
32173
  setup() {
32140
32174
  super.setup();
32141
- this.fullScreenFigureStore = useStore(FullScreenChartStore);
32175
+ this.fullScreenFigureStore = useStore(FullScreenFigureStore);
32142
32176
  }
32143
32177
  getMenuItems() {
32144
32178
  return [this.fullScreenMenuItem].filter(isDefined);
@@ -32154,6 +32188,9 @@ class ChartDashboardMenu extends owl.Component {
32154
32188
  this.menuState.menuItems = getChartMenuActions(figureId, () => { }, this.env);
32155
32189
  }
32156
32190
  get fullScreenMenuItem() {
32191
+ if (!this.props.hasFullScreenButton) {
32192
+ return undefined;
32193
+ }
32157
32194
  const definition = this.env.model.getters.getChartDefinition(this.props.chartId);
32158
32195
  const figureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
32159
32196
  if (definition.type === "scorecard") {
@@ -32165,7 +32202,7 @@ class ChartDashboardMenu extends owl.Component {
32165
32202
  label: isFullScreen ? _t("Exit Full Screen") : _t("Full Screen"),
32166
32203
  class: `text-muted fa ${isFullScreen ? "fa-compress" : "fa-expand"}`,
32167
32204
  onClick: () => {
32168
- this.fullScreenFigureStore.toggleFullScreenChart(figureId);
32205
+ this.fullScreenFigureStore.toggleFullScreenFigure(figureId);
32169
32206
  },
32170
32207
  };
32171
32208
  }
@@ -32177,6 +32214,7 @@ class CarouselFigure extends owl.Component {
32177
32214
  figureUI: Object,
32178
32215
  onFigureDeleted: Function,
32179
32216
  editFigureStyle: { type: Function, optional: true },
32217
+ isFullScreen: { type: Boolean, optional: true },
32180
32218
  };
32181
32219
  static components = { ChartDashboardMenu, MenuPopover };
32182
32220
  carouselTabsRef = owl.useRef("carouselTabs");
@@ -32184,8 +32222,10 @@ class CarouselFigure extends owl.Component {
32184
32222
  menuState = owl.useState({ isOpen: false, anchorRect: null, menuItems: [] });
32185
32223
  hiddenItems = [];
32186
32224
  animationStore;
32225
+ fullScreenFigureStore;
32187
32226
  setup() {
32188
32227
  this.animationStore = useStore(ChartAnimationStore);
32228
+ this.fullScreenFigureStore = useStore(FullScreenFigureStore);
32189
32229
  owl.useEffect(() => {
32190
32230
  if (this.selectedCarouselItem?.type === "carouselDataView") {
32191
32231
  this.props.editFigureStyle?.({ "pointer-events": "none" });
@@ -32232,7 +32272,8 @@ class CarouselFigure extends owl.Component {
32232
32272
  item,
32233
32273
  });
32234
32274
  if (item.type === "chart") {
32235
- this.animationStore?.enableAnimationForChart(item.chartId);
32275
+ const animationChartId = item.chartId + (this.props.isFullScreen ? "-fullscreen" : "");
32276
+ this.animationStore?.enableAnimationForChart(animationChartId);
32236
32277
  }
32237
32278
  }
32238
32279
  get headerStyle() {
@@ -32296,6 +32337,17 @@ class CarouselFigure extends owl.Component {
32296
32337
  this.menuState.anchorRect = rect;
32297
32338
  this.menuState.menuItems = createActions(menuItems);
32298
32339
  }
32340
+ toggleFullScreen() {
32341
+ if (this.selectedCarouselItem?.type === "chart") {
32342
+ this.fullScreenFigureStore.toggleFullScreenFigure(this.props.figureUI.id);
32343
+ }
32344
+ }
32345
+ get fullScreenButtonTitle() {
32346
+ return this.props.isFullScreen ? _t("Exit Full Screen") : _t("Full Screen");
32347
+ }
32348
+ get visibleCarouselItems() {
32349
+ return this.carousel.items.filter((item) => item.type === "carouselDataView" && this.props.isFullScreen ? false : true);
32350
+ }
32299
32351
  }
32300
32352
 
32301
32353
  class ChartFigure extends owl.Component {
@@ -32304,6 +32356,7 @@ class ChartFigure extends owl.Component {
32304
32356
  figureUI: Object,
32305
32357
  onFigureDeleted: Function,
32306
32358
  editFigureStyle: { type: Function, optional: true },
32359
+ isFullScreen: { type: Boolean, optional: true },
32307
32360
  };
32308
32361
  static components = { ChartDashboardMenu };
32309
32362
  onDoubleClick() {
@@ -32406,9 +32459,7 @@ class FigureComponent extends owl.Component {
32406
32459
  return this.isSelected ? ACTIVE_BORDER_WIDTH : this.borderWidth;
32407
32460
  }
32408
32461
  getBorderStyle(position) {
32409
- const borderWidth = this.getBorderWidth();
32410
- const borderColor = this.isSelected ? SELECTION_BORDER_COLOR : FIGURE_BORDER_COLOR;
32411
- return `border-${position}: ${borderWidth}px solid ${borderColor};`;
32462
+ return `border-${position}-width: ${this.getBorderWidth()}px;`;
32412
32463
  }
32413
32464
  get wrapperStyle() {
32414
32465
  const { x, y, width, height } = this.props.figureUI;
@@ -51344,6 +51395,9 @@ class GridRenderer extends SpreadsheetStore {
51344
51395
  }
51345
51396
  const { align } = this.getters.getCellStyle(position);
51346
51397
  const evaluatedCell = this.getters.getEvaluatedCell(position);
51398
+ if (formatHasRepeatedChar(evaluatedCell.value, evaluatedCell.format)) {
51399
+ return "left";
51400
+ }
51347
51401
  if (isOverflowing && evaluatedCell.type === CellValueType.number) {
51348
51402
  return align !== "center" ? "left" : align;
51349
51403
  }
@@ -56815,7 +56869,7 @@ class PivotMeasureEditor extends owl.Component {
56815
56869
  return undefined;
56816
56870
  }
56817
56871
  get isCalculatedMeasureInvalid() {
56818
- return this.env.model.getters.getMeasureCompiledFormula(this.props.measure).isBadExpression;
56872
+ return compile(this.props.measure.computedBy?.formula ?? "").isBadExpression;
56819
56873
  }
56820
56874
  }
56821
56875
 
@@ -59530,16 +59584,16 @@ class ClickableCellSortIcon extends owl.Component {
59530
59584
  }
59531
59585
  }
59532
59586
 
59533
- class FullScreenChart extends owl.Component {
59534
- static template = "o-spreadsheet-FullScreenChart";
59587
+ class FullScreenFigure extends owl.Component {
59588
+ static template = "o-spreadsheet-FullScreenFigure";
59535
59589
  static props = {};
59536
- static components = { ChartDashboardMenu };
59537
- fullScreenChartStore;
59538
- ref = owl.useRef("fullScreenChart");
59590
+ static components = { ChartFigure };
59591
+ fullScreenFigureStore;
59592
+ ref = owl.useRef("fullScreenFigure");
59539
59593
  spreadsheetRect = useSpreadsheetRect();
59540
59594
  figureRegistry = figureRegistry;
59541
59595
  setup() {
59542
- this.fullScreenChartStore = useStore(FullScreenChartStore);
59596
+ this.fullScreenFigureStore = useStore(FullScreenFigureStore);
59543
59597
  const animationStore = useStore(ChartAnimationStore);
59544
59598
  let lastFigureId = undefined;
59545
59599
  owl.onWillUpdateProps(() => {
@@ -59551,7 +59605,7 @@ class FullScreenChart extends owl.Component {
59551
59605
  owl.useEffect((el) => el?.focus(), () => [this.ref.el]);
59552
59606
  }
59553
59607
  get figureUI() {
59554
- return this.fullScreenChartStore.fullScreenFigure;
59608
+ return this.fullScreenFigureStore.fullScreenFigure;
59555
59609
  }
59556
59610
  get chartId() {
59557
59611
  if (!this.figureUI)
@@ -59560,7 +59614,7 @@ class FullScreenChart extends owl.Component {
59560
59614
  }
59561
59615
  exitFullScreen() {
59562
59616
  if (this.figureUI) {
59563
- this.fullScreenChartStore.toggleFullScreenChart(this.figureUI.id);
59617
+ this.fullScreenFigureStore.toggleFullScreenFigure(this.figureUI.id);
59564
59618
  }
59565
59619
  }
59566
59620
  onKeyDown(ev) {
@@ -59568,15 +59622,10 @@ class FullScreenChart extends owl.Component {
59568
59622
  this.exitFullScreen();
59569
59623
  }
59570
59624
  }
59571
- get chartComponent() {
59572
- if (!this.chartId)
59625
+ get figureComponent() {
59626
+ if (!this.figureUI)
59573
59627
  return undefined;
59574
- const type = this.env.model.getters.getChartType(this.chartId);
59575
- const component = chartComponentRegistry.get(type);
59576
- if (!component) {
59577
- throw new Error(`Component is not defined for type ${type}`);
59578
- }
59579
- return component;
59628
+ return figureRegistry.get(this.figureUI.tag).Component;
59580
59629
  }
59581
59630
  }
59582
59631
 
@@ -62279,11 +62328,11 @@ class HeaderSizePlugin extends CorePlugin {
62279
62328
  break;
62280
62329
  }
62281
62330
  case "ADD_COLUMNS_ROWS": {
62282
- const sizes = [...this.sizes[cmd.sheetId][cmd.dimension]];
62331
+ const sizes = this.sizes[cmd.sheetId][cmd.dimension];
62283
62332
  const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
62284
62333
  const baseSize = sizes[cmd.base];
62285
- sizes.splice(addIndex, 0, ...Array(cmd.quantity).fill(baseSize));
62286
- this.history.update("sizes", cmd.sheetId, cmd.dimension, sizes);
62334
+ const newSizes = insertItemsAtIndex(sizes, Array(cmd.quantity).fill(baseSize), addIndex);
62335
+ this.history.update("sizes", cmd.sheetId, cmd.dimension, newSizes);
62287
62336
  break;
62288
62337
  }
62289
62338
  case "RESIZE_COLUMNS_ROWS":
@@ -62434,9 +62483,8 @@ class HeaderVisibilityPlugin extends CorePlugin {
62434
62483
  break;
62435
62484
  }
62436
62485
  case "ADD_COLUMNS_ROWS": {
62437
- const hiddenHeaders = [...this.hiddenHeaders[cmd.sheetId][cmd.dimension]];
62438
62486
  const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
62439
- hiddenHeaders.splice(addIndex, 0, ...Array(cmd.quantity).fill(false));
62487
+ const hiddenHeaders = insertItemsAtIndex([...this.hiddenHeaders[cmd.sheetId][cmd.dimension]], Array(cmd.quantity).fill(false), addIndex);
62440
62488
  this.history.update("hiddenHeaders", cmd.sheetId, cmd.dimension, hiddenHeaders);
62441
62489
  break;
62442
62490
  }
@@ -66620,12 +66668,12 @@ class SpreadsheetRTree {
66620
66668
  this.rTrees[sheetId].remove(item, this.rtreeItemComparer);
66621
66669
  }
66622
66670
  rtreeItemComparer(left, right) {
66623
- return (left.data === right.data &&
66624
- left.boundingBox.sheetId === right.boundingBox.sheetId &&
66671
+ return (left.boundingBox.sheetId === right.boundingBox.sheetId &&
66625
66672
  left.boundingBox?.zone.left === right.boundingBox.zone.left &&
66626
66673
  left.boundingBox?.zone.top === right.boundingBox.zone.top &&
66627
66674
  left.boundingBox?.zone.right === right.boundingBox.zone.right &&
66628
- left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom);
66675
+ left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom &&
66676
+ deepEquals(left.data, right.data));
66629
66677
  }
66630
66678
  }
66631
66679
  /**
@@ -79473,8 +79521,8 @@ class RowGroup extends AbstractHeaderGroup {
79473
79521
  left: `calc(50% - 1px)`, // -1px: we want the border to be on the center
79474
79522
  width: `30%`,
79475
79523
  height: `calc(100% - ${groupBox.headerRect.height / 2}px)`,
79476
- "border-left": `1px solid ${HEADER_GROUPING_BORDER_COLOR}`,
79477
- "border-bottom": groupBox.isEndHidden ? "" : `1px solid ${HEADER_GROUPING_BORDER_COLOR}`,
79524
+ "border-left": `1px solid`,
79525
+ "border-bottom": groupBox.isEndHidden ? "" : `1px solid`,
79478
79526
  });
79479
79527
  }
79480
79528
  get groupHeaderStyle() {
@@ -79526,8 +79574,8 @@ class ColGroup extends AbstractHeaderGroup {
79526
79574
  left: `${groupBox.headerRect.width / 2}px`,
79527
79575
  width: `calc(100% - ${groupBox.headerRect.width / 2}px)`,
79528
79576
  height: `30%`,
79529
- "border-top": `1px solid ${HEADER_GROUPING_BORDER_COLOR}`,
79530
- "border-right": groupBox.isEndHidden ? "" : `1px solid ${HEADER_GROUPING_BORDER_COLOR}`,
79577
+ "border-top": `1px solid`,
79578
+ "border-right": groupBox.isEndHidden ? "" : `1px solid`,
79531
79579
  });
79532
79580
  }
79533
79581
  get groupHeaderStyle() {
@@ -79864,6 +79912,9 @@ class SmallBottomBar extends owl.Component {
79864
79912
  ? this.composerFocusStore.focusMode
79865
79913
  : "inactive";
79866
79914
  }
79915
+ get showFxIcon() {
79916
+ return this.focus === "inactive" && !this.composerStore.currentContent;
79917
+ }
79867
79918
  get rect() {
79868
79919
  return this.composerRef.el
79869
79920
  ? getBoundingRectAsPOJO(this.composerRef.el)
@@ -79906,13 +79957,6 @@ class SmallBottomBar extends owl.Component {
79906
79957
  }
79907
79958
 
79908
79959
  const COMPOSER_MAX_HEIGHT = 300;
79909
- /* svg free of use from https://uxwing.com/formula-fx-icon/ */
79910
- // FIXME This svg is hardcoded in the css file. We should find a better way to handle it.
79911
- // const FX_SVG = /*xml*/ `
79912
- // <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 121.8 122.9' width='16' height='16' focusable='false'>
79913
- // <path d='m28 34-4 5v2h10l-6 40c-4 22-6 28-7 30-2 2-3 3-5 3-3 0-7-2-9-4H4c-2 2-4 4-4 7s4 6 8 6 9-2 15-8c8-7 13-17 18-39l7-35 13-1 3-6H49c4-23 7-27 11-27 2 0 5 2 8 6h4c1-1 4-4 4-7 0-2-3-6-9-6-5 0-13 4-20 10-6 7-9 14-11 24h-8zm41 16c4-5 7-7 8-7s2 1 5 9l3 12c-7 11-12 17-16 17l-3-1-2-1c-3 0-6 3-6 7s3 7 7 7c6 0 12-6 22-23l3 10c3 9 6 13 10 13 5 0 11-4 18-15l-3-4c-4 6-7 8-8 8-2 0-4-3-6-10l-5-15 8-10 6-4 3 1 3 2c2 0 6-3 6-7s-2-7-6-7c-6 0-11 5-21 20l-2-6c-3-9-5-14-9-14-5 0-12 6-18 15l3 3z' fill='#BDBDBD'/>
79914
- // </svg>
79915
- // `;
79916
79960
  class TopBarComposer extends owl.Component {
79917
79961
  static template = "o-spreadsheet-TopBarComposer";
79918
79962
  static props = {};
@@ -79939,6 +79983,9 @@ class TopBarComposer extends owl.Component {
79939
79983
  ? this.composerFocusStore.focusMode
79940
79984
  : "inactive";
79941
79985
  }
79986
+ get showFxIcon() {
79987
+ return this.focus === "inactive" && !this.composerStore.currentContent;
79988
+ }
79942
79989
  get composerStyle() {
79943
79990
  const style = {
79944
79991
  padding: "5px 0px 5px 8px",
@@ -80876,7 +80923,7 @@ class Spreadsheet extends owl.Component {
80876
80923
  SidePanels,
80877
80924
  SpreadsheetDashboard,
80878
80925
  HeaderGroupContainer,
80879
- FullScreenChart,
80926
+ FullScreenFigure,
80880
80927
  };
80881
80928
  sidePanel;
80882
80929
  spreadsheetRef = owl.useRef("spreadsheet");
@@ -85600,6 +85647,7 @@ const components = {
85600
85647
  Grid,
85601
85648
  GridOverlay,
85602
85649
  ScorecardChart,
85650
+ GaugeChartComponent,
85603
85651
  LineConfigPanel,
85604
85652
  BarConfigPanel,
85605
85653
  PieChartDesignPanel,
@@ -85638,7 +85686,7 @@ const components = {
85638
85686
  RadioSelection,
85639
85687
  GeoChartRegionSelectSection,
85640
85688
  ChartDashboardMenu,
85641
- FullScreenChart,
85689
+ FullScreenFigure,
85642
85690
  };
85643
85691
  const hooks = {
85644
85692
  useDragAndDropListItems,
@@ -85738,6 +85786,6 @@ exports.tokenColors = tokenColors;
85738
85786
  exports.tokenize = tokenize;
85739
85787
 
85740
85788
 
85741
- __info__.version = "19.1.0-alpha.3";
85742
- __info__.date = "2025-09-23T12:37:52.238Z";
85743
- __info__.hash = "ce2b07a";
85789
+ __info__.version = "19.1.0-alpha.4";
85790
+ __info__.date = "2025-10-07T10:03:20.917Z";
85791
+ __info__.hash = "b7cfed8";