@odoo/o-spreadsheet 19.1.0-alpha.2 → 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.2
6
- * @date 2025-09-19T07:26:49.306Z
7
- * @hash 8cc543d
5
+ * @version 19.1.0-alpha.4
6
+ * @date 2025-10-07T10:03:20.917Z
7
+ * @hash b7cfed8
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -592,7 +592,6 @@
592
592
  const BACKGROUND_HEADER_SELECTED_COLOR = "#E8EAED";
593
593
  const BACKGROUND_HEADER_ACTIVE_COLOR = "#595959";
594
594
  const TEXT_HEADER_COLOR = "#666666";
595
- const FIGURE_BORDER_COLOR = "#c9ccd2";
596
595
  const SELECTION_BORDER_COLOR = "#3266ca";
597
596
  const HEADER_BORDER_COLOR = "#C0C0C0";
598
597
  const CELL_BORDER_COLOR = "#E2E3E3";
@@ -600,7 +599,6 @@
600
599
  const DEFAULT_COLOR_SCALE_MIDPOINT_COLOR = 0xb6d7a8;
601
600
  const LINK_COLOR = HIGHLIGHT_COLOR;
602
601
  const FILTERS_COLOR = "#188038";
603
- const HEADER_GROUPING_BORDER_COLOR = "#999";
604
602
  const FROZEN_PANE_HEADER_BORDER_COLOR = "#BCBCBC";
605
603
  const FROZEN_PANE_BORDER_COLOR = "#DADFE8";
606
604
  const COMPOSER_ASSISTANT_COLOR = "#9B359B";
@@ -843,22 +841,6 @@
843
841
  // Miscellaneous
844
842
  //------------------------------------------------------------------------------
845
843
  const sanitizeSheetNameRegex = new RegExp(FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX, "g");
846
- /**
847
- * Remove quotes from a quoted string
848
- * ```js
849
- * removeStringQuotes('"Hello"')
850
- * > 'Hello'
851
- * ```
852
- */
853
- function removeStringQuotes(str) {
854
- if (str[0] === '"') {
855
- str = str.slice(1);
856
- }
857
- if (str[str.length - 1] === '"' && str[str.length - 2] !== "\\") {
858
- return str.slice(0, str.length - 1);
859
- }
860
- return str;
861
- }
862
844
  function isCloneable(obj) {
863
845
  return "clone" in obj && obj.clone instanceof Function;
864
846
  }
@@ -927,6 +909,13 @@
927
909
  function getUnquotedSheetName(sheetName) {
928
910
  return unquote(sheetName, "'");
929
911
  }
912
+ /**
913
+ * Remove quotes from a quoted string
914
+ * ```js
915
+ * unquote('"Hello"')
916
+ * > 'Hello'
917
+ * ```
918
+ */
930
919
  function unquote(string, quoteChar = '"') {
931
920
  if (string.startsWith(quoteChar)) {
932
921
  string = string.slice(1);
@@ -1331,9 +1320,7 @@
1331
1320
  return newArray;
1332
1321
  }
1333
1322
  function insertItemsAtIndex(array, items, index) {
1334
- const newArray = [...array];
1335
- newArray.splice(index, 0, ...items);
1336
- return newArray;
1323
+ return array.slice(0, index).concat(items).concat(array.slice(index));
1337
1324
  }
1338
1325
  function replaceItemAtIndex(array, newItem, index) {
1339
1326
  const newArray = [...array];
@@ -5583,7 +5570,7 @@
5583
5570
  * Replace in place tokens "mm" and "m" that denote minutes in date format with "MM" to avoid confusion with months.
5584
5571
  *
5585
5572
  * As per OpenXML specification, in date formats if a date token "m" or "mm" is followed by a date token "s" or
5586
- * preceded by a data token "h", then it's not a month but an minute.
5573
+ * preceded by a data token "h", then it's not a month but a minute.
5587
5574
  */
5588
5575
  function convertTokensToMinutesInDateFormat(tokens) {
5589
5576
  const dateParts = tokens.filter((token) => token.type === "DATE_PART");
@@ -5626,6 +5613,9 @@
5626
5613
  case "REPEATED_CHAR":
5627
5614
  format += "*" + token.value;
5628
5615
  break;
5616
+ case "DATE_PART":
5617
+ format += token.value === "MM" ? "mm" : token.value; // Convert "MM" back to "mm" for minutes
5618
+ break;
5629
5619
  default:
5630
5620
  format += token.value;
5631
5621
  }
@@ -5699,7 +5689,7 @@
5699
5689
  return value;
5700
5690
  }
5701
5691
  const internalFormat = parseFormat(format);
5702
- const formatToApply = internalFormat.text || internalFormat.positive;
5692
+ const formatToApply = getFormatToApply(value, internalFormat).format;
5703
5693
  if (!formatToApply || formatToApply.type !== "text") {
5704
5694
  return value;
5705
5695
  }
@@ -5710,16 +5700,15 @@
5710
5700
  format = createDefaultFormat(value);
5711
5701
  }
5712
5702
  const internalFormat = parseFormat(format);
5713
- if (internalFormat.positive.type === "text") {
5714
- return applyTextInternalFormat(value.toString(), internalFormat.positive, formatWidth);
5703
+ const { format: formatToApply, isNegativeFormat } = getFormatToApply(value, internalFormat);
5704
+ if (!formatToApply) {
5705
+ return value.toString();
5715
5706
  }
5716
- let formatToApply = internalFormat.positive;
5717
- if (value < 0 && internalFormat.negative) {
5718
- formatToApply = internalFormat.negative;
5719
- value = -value;
5707
+ if (formatToApply.type === "text") {
5708
+ return applyTextInternalFormat(value.toString(), formatToApply, formatWidth);
5720
5709
  }
5721
- else if (value === 0 && internalFormat.zero) {
5722
- formatToApply = internalFormat.zero;
5710
+ if (isNegativeFormat) {
5711
+ value = Math.abs(value);
5723
5712
  }
5724
5713
  if (formatToApply.type === "date") {
5725
5714
  return repeatCharToFitWidth(applyDateTimeFormat(value, formatToApply), formatWidth);
@@ -5731,6 +5720,31 @@
5731
5720
  return "";
5732
5721
  }
5733
5722
  }
5723
+ function getFormatToApply(value, internalFormat) {
5724
+ let formatToApply = undefined;
5725
+ let isNegativeFormat = false;
5726
+ switch (typeof value) {
5727
+ case "number":
5728
+ if (value < 0 && internalFormat.negative) {
5729
+ formatToApply = internalFormat.negative;
5730
+ isNegativeFormat = true;
5731
+ }
5732
+ else if (value === 0 && internalFormat.zero) {
5733
+ formatToApply = internalFormat.zero;
5734
+ }
5735
+ else {
5736
+ formatToApply = internalFormat.positive;
5737
+ }
5738
+ break;
5739
+ case "string":
5740
+ const format = internalFormat.text || internalFormat.positive;
5741
+ if (format.type === "text") {
5742
+ formatToApply = format;
5743
+ }
5744
+ break;
5745
+ }
5746
+ return { format: formatToApply, isNegativeFormat };
5747
+ }
5734
5748
  function applyTextInternalFormat(value, internalFormat, formatWidth) {
5735
5749
  let formattedValue = "";
5736
5750
  for (const token of internalFormat.tokens) {
@@ -6342,6 +6356,27 @@
6342
6356
  return false;
6343
6357
  }
6344
6358
  }
6359
+ function formatHasRepeatedChar(value, format) {
6360
+ if (!format) {
6361
+ return false;
6362
+ }
6363
+ try {
6364
+ const internalFormat = parseFormat(format);
6365
+ const { format: formatToApply } = getFormatToApply(value, internalFormat);
6366
+ if (formatToApply?.type === "text" || formatToApply?.type === "date") {
6367
+ const tokens = formatToApply.tokens;
6368
+ return tokens.some((token) => token.type === "REPEATED_CHAR");
6369
+ }
6370
+ else if (formatToApply?.type === "number") {
6371
+ return (formatToApply.integerPart.some((token) => token.type === "REPEATED_CHAR") ||
6372
+ (formatToApply.decimalPart
6373
+ ? formatToApply.decimalPart.some((token) => token.type === "REPEATED_CHAR")
6374
+ : false));
6375
+ }
6376
+ }
6377
+ catch { }
6378
+ return false;
6379
+ }
6345
6380
 
6346
6381
  function evaluateLiteral(literalCell, localeFormat, position) {
6347
6382
  const value = isTextFormat(localeFormat.format) && literalCell.parsedValue !== null
@@ -18636,7 +18671,7 @@ stores.inject(MyMetaStore, storeInstance);
18636
18671
  case "STRING":
18637
18672
  return {
18638
18673
  type: "STRING",
18639
- value: removeStringQuotes(current.value),
18674
+ value: unquote(current.value),
18640
18675
  tokenStartIndex: current.tokenIndex,
18641
18676
  tokenEndIndex: current.tokenIndex,
18642
18677
  };
@@ -22393,7 +22428,7 @@ stores.inject(MyMetaStore, storeInstance);
22393
22428
  dependencies.push(token.value);
22394
22429
  break;
22395
22430
  case "STRING":
22396
- const value = removeStringQuotes(token.value);
22431
+ const value = unquote(token.value);
22397
22432
  literalValues.strings.push({ value });
22398
22433
  break;
22399
22434
  case "NUMBER": {
@@ -24645,6 +24680,7 @@ stores.inject(MyMetaStore, storeInstance);
24645
24680
  static template = "o-spreadsheet-ScorecardChart";
24646
24681
  static props = {
24647
24682
  chartId: String,
24683
+ isFullScreen: { type: Boolean, optional: true },
24648
24684
  };
24649
24685
  canvas = owl.useRef("chartContainer");
24650
24686
  get runtime() {
@@ -26564,7 +26600,7 @@ stores.inject(MyMetaStore, storeInstance);
26564
26600
  },
26565
26601
  pointLabels: {
26566
26602
  color: chartFontColor(definition.background),
26567
- callback: truncateLabel,
26603
+ callback: (label) => truncateLabel(label),
26568
26604
  },
26569
26605
  suggestedMin: minValue < 0 ? minValue - 1 : 0,
26570
26606
  },
@@ -27408,26 +27444,6 @@ stores.inject(MyMetaStore, storeInstance);
27408
27444
  return { chartJsConfig: config, background: chart.background || BACKGROUND_CHART_COLOR };
27409
27445
  }
27410
27446
 
27411
- class FullScreenChartStore extends SpreadsheetStore {
27412
- mutators = ["toggleFullScreenChart"];
27413
- fullScreenFigure = undefined;
27414
- toggleFullScreenChart(figureId) {
27415
- if (this.fullScreenFigure?.id === figureId) {
27416
- this.fullScreenFigure = undefined;
27417
- }
27418
- else {
27419
- this.makeFullScreen(figureId);
27420
- }
27421
- }
27422
- makeFullScreen(figureId) {
27423
- const sheetId = this.getters.getActiveSheetId();
27424
- const figure = this.getters.getFigure(sheetId, figureId);
27425
- if (figure) {
27426
- this.fullScreenFigure = { ...figure, x: 0, y: 0, width: 0, height: 0 };
27427
- }
27428
- }
27429
- }
27430
-
27431
27447
  const TREND_LINE_AXES_IDS = [TREND_LINE_XAXIS_ID, MOVING_AVERAGE_TREND_LINE_XAXIS_ID];
27432
27448
  const ZOOMABLE_AXIS_IDS = ["x", ...TREND_LINE_AXES_IDS];
27433
27449
  class ZoomableChartStore extends SpreadsheetStore {
@@ -27592,7 +27608,6 @@ stores.inject(MyMetaStore, storeInstance);
27592
27608
  class ZoomableChartJsComponent extends ChartJsComponent {
27593
27609
  static template = "o-spreadsheet-ZoomableChartJsComponent";
27594
27610
  store;
27595
- fullScreenChartStore;
27596
27611
  masterChartCanvas = owl.useRef("masterChartCanvas");
27597
27612
  masterChart;
27598
27613
  mode;
@@ -27603,7 +27618,6 @@ stores.inject(MyMetaStore, storeInstance);
27603
27618
  removeEventListeners = () => { };
27604
27619
  setup() {
27605
27620
  this.store = useStore(ZoomableChartStore);
27606
- this.fullScreenChartStore = useStore(FullScreenChartStore);
27607
27621
  super.setup();
27608
27622
  }
27609
27623
  unmount() {
@@ -27618,12 +27632,8 @@ stores.inject(MyMetaStore, storeInstance);
27618
27632
  `;
27619
27633
  }
27620
27634
  get sliceable() {
27621
- if (this.env.isDashboard()) {
27622
- const fullScreenFigureId = this.fullScreenChartStore.fullScreenFigure?.id;
27623
- const chartFigureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
27624
- if (fullScreenFigureId === chartFigureId) {
27625
- return true;
27626
- }
27635
+ if (this.props.isFullScreen) {
27636
+ return true;
27627
27637
  }
27628
27638
  const definition = this.env.model.getters.getChartDefinition(this.props.chartId);
27629
27639
  return ("zoomable" in definition && definition?.zoomable) ?? false;
@@ -27686,9 +27696,6 @@ stores.inject(MyMetaStore, storeInstance);
27686
27696
  const xMax = Math.max(...xValues);
27687
27697
  return { xMin, xMax };
27688
27698
  }
27689
- get shouldAnimate() {
27690
- return this.env.model.getters.isDashboard() && !this.sliceable;
27691
- }
27692
27699
  createChart(chartRuntime) {
27693
27700
  const chartData = chartRuntime.chartJsConfig;
27694
27701
  this.isBarChart = chartData.type === "bar";
@@ -27707,6 +27714,9 @@ stores.inject(MyMetaStore, storeInstance);
27707
27714
  const masterChartCtx = this.masterChartCanvas.el.getContext("2d");
27708
27715
  this.masterChart = new window.Chart(masterChartCtx, this.getMasterChartConfiguration(chartRuntime["masterChartConfig"]));
27709
27716
  this.resetAxesLimits();
27717
+ if (this.chart?.options) {
27718
+ this.chart.options.animation = false;
27719
+ }
27710
27720
  }
27711
27721
  updateChartJs(chartRuntime) {
27712
27722
  const chartData = chartRuntime.chartJsConfig;
@@ -27740,6 +27750,9 @@ stores.inject(MyMetaStore, storeInstance);
27740
27750
  }
27741
27751
  }
27742
27752
  this.resetAxesLimits();
27753
+ if (this.chart?.options) {
27754
+ this.chart.options.animation = false;
27755
+ }
27743
27756
  }
27744
27757
  resetAxesLimits() {
27745
27758
  if (!this.chart) {
@@ -27837,7 +27850,7 @@ stores.inject(MyMetaStore, storeInstance);
27837
27850
  onPointerDownInMasterChart(ev) {
27838
27851
  this.removeEventListeners();
27839
27852
  const position = ev.offsetX;
27840
- if (!this.masterChart?.chartArea || !this.chart?.scales.x) {
27853
+ if (!this.masterChart?.chartArea || !this.chart?.scales?.x) {
27841
27854
  return;
27842
27855
  }
27843
27856
  const { left, right, top, bottom } = this.masterChart.chartArea;
@@ -31395,6 +31408,26 @@ stores.inject(MyMetaStore, storeInstance);
31395
31408
  return matchedChart.displayName;
31396
31409
  }
31397
31410
 
31411
+ class FullScreenFigureStore extends SpreadsheetStore {
31412
+ mutators = ["toggleFullScreenFigure"];
31413
+ fullScreenFigure = undefined;
31414
+ toggleFullScreenFigure(figureId) {
31415
+ if (this.fullScreenFigure?.id === figureId) {
31416
+ this.fullScreenFigure = undefined;
31417
+ }
31418
+ else {
31419
+ this.makeFullScreen(figureId);
31420
+ }
31421
+ }
31422
+ makeFullScreen(figureId) {
31423
+ const sheetId = this.getters.getActiveSheetId();
31424
+ const figure = this.getters.getFigure(sheetId, figureId);
31425
+ if (figure) {
31426
+ this.fullScreenFigure = { ...figure, x: 0, y: 0, width: 0, height: 0 };
31427
+ }
31428
+ }
31429
+ }
31430
+
31398
31431
  /**
31399
31432
  * This file is largely inspired by owl 1.
31400
31433
  * `css` tag has been removed from owl 2 without workaround to manage css.
@@ -32132,12 +32165,13 @@ stores.inject(MyMetaStore, storeInstance);
32132
32165
  class ChartDashboardMenu extends owl.Component {
32133
32166
  static template = "o-spreadsheet-ChartDashboardMenu";
32134
32167
  static components = { MenuPopover };
32135
- static props = { chartId: String };
32168
+ static props = { chartId: String, hasFullScreenButton: { type: Boolean, optional: true } };
32169
+ static defaultProps = { hasFullScreenButton: true };
32136
32170
  fullScreenFigureStore;
32137
32171
  menuState = owl.useState({ isOpen: false, anchorRect: null, menuItems: [] });
32138
32172
  setup() {
32139
32173
  super.setup();
32140
- this.fullScreenFigureStore = useStore(FullScreenChartStore);
32174
+ this.fullScreenFigureStore = useStore(FullScreenFigureStore);
32141
32175
  }
32142
32176
  getMenuItems() {
32143
32177
  return [this.fullScreenMenuItem].filter(isDefined);
@@ -32153,6 +32187,9 @@ stores.inject(MyMetaStore, storeInstance);
32153
32187
  this.menuState.menuItems = getChartMenuActions(figureId, () => { }, this.env);
32154
32188
  }
32155
32189
  get fullScreenMenuItem() {
32190
+ if (!this.props.hasFullScreenButton) {
32191
+ return undefined;
32192
+ }
32156
32193
  const definition = this.env.model.getters.getChartDefinition(this.props.chartId);
32157
32194
  const figureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
32158
32195
  if (definition.type === "scorecard") {
@@ -32164,7 +32201,7 @@ stores.inject(MyMetaStore, storeInstance);
32164
32201
  label: isFullScreen ? _t("Exit Full Screen") : _t("Full Screen"),
32165
32202
  class: `text-muted fa ${isFullScreen ? "fa-compress" : "fa-expand"}`,
32166
32203
  onClick: () => {
32167
- this.fullScreenFigureStore.toggleFullScreenChart(figureId);
32204
+ this.fullScreenFigureStore.toggleFullScreenFigure(figureId);
32168
32205
  },
32169
32206
  };
32170
32207
  }
@@ -32176,6 +32213,7 @@ stores.inject(MyMetaStore, storeInstance);
32176
32213
  figureUI: Object,
32177
32214
  onFigureDeleted: Function,
32178
32215
  editFigureStyle: { type: Function, optional: true },
32216
+ isFullScreen: { type: Boolean, optional: true },
32179
32217
  };
32180
32218
  static components = { ChartDashboardMenu, MenuPopover };
32181
32219
  carouselTabsRef = owl.useRef("carouselTabs");
@@ -32183,8 +32221,10 @@ stores.inject(MyMetaStore, storeInstance);
32183
32221
  menuState = owl.useState({ isOpen: false, anchorRect: null, menuItems: [] });
32184
32222
  hiddenItems = [];
32185
32223
  animationStore;
32224
+ fullScreenFigureStore;
32186
32225
  setup() {
32187
32226
  this.animationStore = useStore(ChartAnimationStore);
32227
+ this.fullScreenFigureStore = useStore(FullScreenFigureStore);
32188
32228
  owl.useEffect(() => {
32189
32229
  if (this.selectedCarouselItem?.type === "carouselDataView") {
32190
32230
  this.props.editFigureStyle?.({ "pointer-events": "none" });
@@ -32231,18 +32271,19 @@ stores.inject(MyMetaStore, storeInstance);
32231
32271
  item,
32232
32272
  });
32233
32273
  if (item.type === "chart") {
32234
- this.animationStore?.enableAnimationForChart(item.chartId);
32274
+ const animationChartId = item.chartId + (this.props.isFullScreen ? "-fullscreen" : "");
32275
+ this.animationStore?.enableAnimationForChart(animationChartId);
32235
32276
  }
32236
32277
  }
32237
32278
  get headerStyle() {
32238
32279
  const cssProperties = {};
32239
- if (this.selectedCarouselItem?.type === "carouselDataView") {
32240
- cssProperties["background-color"] = "#ffffff";
32241
- }
32242
- else if (this.selectedCarouselItem?.type === "chart") {
32280
+ if (this.selectedCarouselItem?.type === "chart") {
32243
32281
  const chart = this.env.model.getters.getChartRuntime(this.selectedCarouselItem.chartId);
32244
32282
  cssProperties["background-color"] = chart.background;
32245
32283
  }
32284
+ else {
32285
+ cssProperties["background-color"] = "#ffffff";
32286
+ }
32246
32287
  return cssPropertiesToCss(cssProperties);
32247
32288
  }
32248
32289
  get title() {
@@ -32295,6 +32336,17 @@ stores.inject(MyMetaStore, storeInstance);
32295
32336
  this.menuState.anchorRect = rect;
32296
32337
  this.menuState.menuItems = createActions(menuItems);
32297
32338
  }
32339
+ toggleFullScreen() {
32340
+ if (this.selectedCarouselItem?.type === "chart") {
32341
+ this.fullScreenFigureStore.toggleFullScreenFigure(this.props.figureUI.id);
32342
+ }
32343
+ }
32344
+ get fullScreenButtonTitle() {
32345
+ return this.props.isFullScreen ? _t("Exit Full Screen") : _t("Full Screen");
32346
+ }
32347
+ get visibleCarouselItems() {
32348
+ return this.carousel.items.filter((item) => item.type === "carouselDataView" && this.props.isFullScreen ? false : true);
32349
+ }
32298
32350
  }
32299
32351
 
32300
32352
  class ChartFigure extends owl.Component {
@@ -32303,6 +32355,7 @@ stores.inject(MyMetaStore, storeInstance);
32303
32355
  figureUI: Object,
32304
32356
  onFigureDeleted: Function,
32305
32357
  editFigureStyle: { type: Function, optional: true },
32358
+ isFullScreen: { type: Boolean, optional: true },
32306
32359
  };
32307
32360
  static components = { ChartDashboardMenu };
32308
32361
  onDoubleClick() {
@@ -32405,9 +32458,7 @@ stores.inject(MyMetaStore, storeInstance);
32405
32458
  return this.isSelected ? ACTIVE_BORDER_WIDTH : this.borderWidth;
32406
32459
  }
32407
32460
  getBorderStyle(position) {
32408
- const borderWidth = this.getBorderWidth();
32409
- const borderColor = this.isSelected ? SELECTION_BORDER_COLOR : FIGURE_BORDER_COLOR;
32410
- return `border-${position}: ${borderWidth}px solid ${borderColor};`;
32461
+ return `border-${position}-width: ${this.getBorderWidth()}px;`;
32411
32462
  }
32412
32463
  get wrapperStyle() {
32413
32464
  const { x, y, width, height } = this.props.figureUI;
@@ -51343,6 +51394,9 @@ stores.inject(MyMetaStore, storeInstance);
51343
51394
  }
51344
51395
  const { align } = this.getters.getCellStyle(position);
51345
51396
  const evaluatedCell = this.getters.getEvaluatedCell(position);
51397
+ if (formatHasRepeatedChar(evaluatedCell.value, evaluatedCell.format)) {
51398
+ return "left";
51399
+ }
51346
51400
  if (isOverflowing && evaluatedCell.type === CellValueType.number) {
51347
51401
  return align !== "center" ? "left" : align;
51348
51402
  }
@@ -56814,7 +56868,7 @@ stores.inject(MyMetaStore, storeInstance);
56814
56868
  return undefined;
56815
56869
  }
56816
56870
  get isCalculatedMeasureInvalid() {
56817
- return this.env.model.getters.getMeasureCompiledFormula(this.props.measure).isBadExpression;
56871
+ return compile(this.props.measure.computedBy?.formula ?? "").isBadExpression;
56818
56872
  }
56819
56873
  }
56820
56874
 
@@ -59529,16 +59583,16 @@ stores.inject(MyMetaStore, storeInstance);
59529
59583
  }
59530
59584
  }
59531
59585
 
59532
- class FullScreenChart extends owl.Component {
59533
- static template = "o-spreadsheet-FullScreenChart";
59586
+ class FullScreenFigure extends owl.Component {
59587
+ static template = "o-spreadsheet-FullScreenFigure";
59534
59588
  static props = {};
59535
- static components = { ChartDashboardMenu };
59536
- fullScreenChartStore;
59537
- ref = owl.useRef("fullScreenChart");
59589
+ static components = { ChartFigure };
59590
+ fullScreenFigureStore;
59591
+ ref = owl.useRef("fullScreenFigure");
59538
59592
  spreadsheetRect = useSpreadsheetRect();
59539
59593
  figureRegistry = figureRegistry;
59540
59594
  setup() {
59541
- this.fullScreenChartStore = useStore(FullScreenChartStore);
59595
+ this.fullScreenFigureStore = useStore(FullScreenFigureStore);
59542
59596
  const animationStore = useStore(ChartAnimationStore);
59543
59597
  let lastFigureId = undefined;
59544
59598
  owl.onWillUpdateProps(() => {
@@ -59550,7 +59604,7 @@ stores.inject(MyMetaStore, storeInstance);
59550
59604
  owl.useEffect((el) => el?.focus(), () => [this.ref.el]);
59551
59605
  }
59552
59606
  get figureUI() {
59553
- return this.fullScreenChartStore.fullScreenFigure;
59607
+ return this.fullScreenFigureStore.fullScreenFigure;
59554
59608
  }
59555
59609
  get chartId() {
59556
59610
  if (!this.figureUI)
@@ -59559,7 +59613,7 @@ stores.inject(MyMetaStore, storeInstance);
59559
59613
  }
59560
59614
  exitFullScreen() {
59561
59615
  if (this.figureUI) {
59562
- this.fullScreenChartStore.toggleFullScreenChart(this.figureUI.id);
59616
+ this.fullScreenFigureStore.toggleFullScreenFigure(this.figureUI.id);
59563
59617
  }
59564
59618
  }
59565
59619
  onKeyDown(ev) {
@@ -59567,15 +59621,10 @@ stores.inject(MyMetaStore, storeInstance);
59567
59621
  this.exitFullScreen();
59568
59622
  }
59569
59623
  }
59570
- get chartComponent() {
59571
- if (!this.chartId)
59624
+ get figureComponent() {
59625
+ if (!this.figureUI)
59572
59626
  return undefined;
59573
- const type = this.env.model.getters.getChartType(this.chartId);
59574
- const component = chartComponentRegistry.get(type);
59575
- if (!component) {
59576
- throw new Error(`Component is not defined for type ${type}`);
59577
- }
59578
- return component;
59627
+ return figureRegistry.get(this.figureUI.tag).Component;
59579
59628
  }
59580
59629
  }
59581
59630
 
@@ -62278,11 +62327,11 @@ stores.inject(MyMetaStore, storeInstance);
62278
62327
  break;
62279
62328
  }
62280
62329
  case "ADD_COLUMNS_ROWS": {
62281
- const sizes = [...this.sizes[cmd.sheetId][cmd.dimension]];
62330
+ const sizes = this.sizes[cmd.sheetId][cmd.dimension];
62282
62331
  const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
62283
62332
  const baseSize = sizes[cmd.base];
62284
- sizes.splice(addIndex, 0, ...Array(cmd.quantity).fill(baseSize));
62285
- this.history.update("sizes", cmd.sheetId, cmd.dimension, sizes);
62333
+ const newSizes = insertItemsAtIndex(sizes, Array(cmd.quantity).fill(baseSize), addIndex);
62334
+ this.history.update("sizes", cmd.sheetId, cmd.dimension, newSizes);
62286
62335
  break;
62287
62336
  }
62288
62337
  case "RESIZE_COLUMNS_ROWS":
@@ -62433,9 +62482,8 @@ stores.inject(MyMetaStore, storeInstance);
62433
62482
  break;
62434
62483
  }
62435
62484
  case "ADD_COLUMNS_ROWS": {
62436
- const hiddenHeaders = [...this.hiddenHeaders[cmd.sheetId][cmd.dimension]];
62437
62485
  const addIndex = getAddHeaderStartIndex(cmd.position, cmd.base);
62438
- hiddenHeaders.splice(addIndex, 0, ...Array(cmd.quantity).fill(false));
62486
+ const hiddenHeaders = insertItemsAtIndex([...this.hiddenHeaders[cmd.sheetId][cmd.dimension]], Array(cmd.quantity).fill(false), addIndex);
62439
62487
  this.history.update("hiddenHeaders", cmd.sheetId, cmd.dimension, hiddenHeaders);
62440
62488
  break;
62441
62489
  }
@@ -66619,12 +66667,12 @@ stores.inject(MyMetaStore, storeInstance);
66619
66667
  this.rTrees[sheetId].remove(item, this.rtreeItemComparer);
66620
66668
  }
66621
66669
  rtreeItemComparer(left, right) {
66622
- return (left.data === right.data &&
66623
- left.boundingBox.sheetId === right.boundingBox.sheetId &&
66670
+ return (left.boundingBox.sheetId === right.boundingBox.sheetId &&
66624
66671
  left.boundingBox?.zone.left === right.boundingBox.zone.left &&
66625
66672
  left.boundingBox?.zone.top === right.boundingBox.zone.top &&
66626
66673
  left.boundingBox?.zone.right === right.boundingBox.zone.right &&
66627
- left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom);
66674
+ left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom &&
66675
+ deepEquals(left.data, right.data));
66628
66676
  }
66629
66677
  }
66630
66678
  /**
@@ -72879,7 +72927,10 @@ stores.inject(MyMetaStore, storeInstance);
72879
72927
  return "Success" /* CommandResult.Success */;
72880
72928
  }
72881
72929
  checkArrayFormulaInSortZone({ sheetId, zone }) {
72882
- const arrayFormulaInZone = positions(zone).some(({ col, row }) => this.getters.getArrayFormulaSpreadingOn({ sheetId, col, row }));
72930
+ const arrayFormulaInZone = positions(zone).some(({ col, row }) => {
72931
+ const originPosition = this.getters.getArrayFormulaSpreadingOn({ sheetId, col, row });
72932
+ return originPosition && !deepEquals(originPosition, { sheetId, col, row });
72933
+ });
72883
72934
  return arrayFormulaInZone ? "SortZoneWithArrayFormulas" /* CommandResult.SortZoneWithArrayFormulas */ : "Success" /* CommandResult.Success */;
72884
72935
  }
72885
72936
  /**
@@ -79469,8 +79520,8 @@ stores.inject(MyMetaStore, storeInstance);
79469
79520
  left: `calc(50% - 1px)`, // -1px: we want the border to be on the center
79470
79521
  width: `30%`,
79471
79522
  height: `calc(100% - ${groupBox.headerRect.height / 2}px)`,
79472
- "border-left": `1px solid ${HEADER_GROUPING_BORDER_COLOR}`,
79473
- "border-bottom": groupBox.isEndHidden ? "" : `1px solid ${HEADER_GROUPING_BORDER_COLOR}`,
79523
+ "border-left": `1px solid`,
79524
+ "border-bottom": groupBox.isEndHidden ? "" : `1px solid`,
79474
79525
  });
79475
79526
  }
79476
79527
  get groupHeaderStyle() {
@@ -79522,8 +79573,8 @@ stores.inject(MyMetaStore, storeInstance);
79522
79573
  left: `${groupBox.headerRect.width / 2}px`,
79523
79574
  width: `calc(100% - ${groupBox.headerRect.width / 2}px)`,
79524
79575
  height: `30%`,
79525
- "border-top": `1px solid ${HEADER_GROUPING_BORDER_COLOR}`,
79526
- "border-right": groupBox.isEndHidden ? "" : `1px solid ${HEADER_GROUPING_BORDER_COLOR}`,
79576
+ "border-top": `1px solid`,
79577
+ "border-right": groupBox.isEndHidden ? "" : `1px solid`,
79527
79578
  });
79528
79579
  }
79529
79580
  get groupHeaderStyle() {
@@ -79860,6 +79911,9 @@ stores.inject(MyMetaStore, storeInstance);
79860
79911
  ? this.composerFocusStore.focusMode
79861
79912
  : "inactive";
79862
79913
  }
79914
+ get showFxIcon() {
79915
+ return this.focus === "inactive" && !this.composerStore.currentContent;
79916
+ }
79863
79917
  get rect() {
79864
79918
  return this.composerRef.el
79865
79919
  ? getBoundingRectAsPOJO(this.composerRef.el)
@@ -79902,13 +79956,6 @@ stores.inject(MyMetaStore, storeInstance);
79902
79956
  }
79903
79957
 
79904
79958
  const COMPOSER_MAX_HEIGHT = 300;
79905
- /* svg free of use from https://uxwing.com/formula-fx-icon/ */
79906
- // FIXME This svg is hardcoded in the css file. We should find a better way to handle it.
79907
- // const FX_SVG = /*xml*/ `
79908
- // <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 121.8 122.9' width='16' height='16' focusable='false'>
79909
- // <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'/>
79910
- // </svg>
79911
- // `;
79912
79959
  class TopBarComposer extends owl.Component {
79913
79960
  static template = "o-spreadsheet-TopBarComposer";
79914
79961
  static props = {};
@@ -79935,6 +79982,9 @@ stores.inject(MyMetaStore, storeInstance);
79935
79982
  ? this.composerFocusStore.focusMode
79936
79983
  : "inactive";
79937
79984
  }
79985
+ get showFxIcon() {
79986
+ return this.focus === "inactive" && !this.composerStore.currentContent;
79987
+ }
79938
79988
  get composerStyle() {
79939
79989
  const style = {
79940
79990
  padding: "5px 0px 5px 8px",
@@ -80872,7 +80922,7 @@ stores.inject(MyMetaStore, storeInstance);
80872
80922
  SidePanels,
80873
80923
  SpreadsheetDashboard,
80874
80924
  HeaderGroupContainer,
80875
- FullScreenChart,
80925
+ FullScreenFigure,
80876
80926
  };
80877
80927
  sidePanel;
80878
80928
  spreadsheetRef = owl.useRef("spreadsheet");
@@ -85596,6 +85646,7 @@ stores.inject(MyMetaStore, storeInstance);
85596
85646
  Grid,
85597
85647
  GridOverlay,
85598
85648
  ScorecardChart,
85649
+ GaugeChartComponent,
85599
85650
  LineConfigPanel,
85600
85651
  BarConfigPanel,
85601
85652
  PieChartDesignPanel,
@@ -85634,7 +85685,7 @@ stores.inject(MyMetaStore, storeInstance);
85634
85685
  RadioSelection,
85635
85686
  GeoChartRegionSelectSection,
85636
85687
  ChartDashboardMenu,
85637
- FullScreenChart,
85688
+ FullScreenFigure,
85638
85689
  };
85639
85690
  const hooks = {
85640
85691
  useDragAndDropListItems,
@@ -85734,9 +85785,9 @@ stores.inject(MyMetaStore, storeInstance);
85734
85785
  exports.tokenize = tokenize;
85735
85786
 
85736
85787
 
85737
- __info__.version = "19.1.0-alpha.2";
85738
- __info__.date = "2025-09-19T07:26:49.306Z";
85739
- __info__.hash = "8cc543d";
85788
+ __info__.version = "19.1.0-alpha.4";
85789
+ __info__.date = "2025-10-07T10:03:20.917Z";
85790
+ __info__.hash = "b7cfed8";
85740
85791
 
85741
85792
 
85742
85793
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);