@odoo/o-spreadsheet 18.2.0-alpha.8 → 18.2.1

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 18.2.0-alpha.8
6
- * @date 2025-02-14T08:40:13.286Z
7
- * @hash 19d45d9
5
+ * @version 18.2.1
6
+ * @date 2025-02-25T06:03:13.262Z
7
+ * @hash 3b4b5c9
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -2229,17 +2229,7 @@ function toZoneWithoutBoundaryChanges(xc) {
2229
2229
  */
2230
2230
  function toUnboundedZone(xc) {
2231
2231
  const zone = toZoneWithoutBoundaryChanges(xc);
2232
- if (zone.right !== undefined && zone.right < zone.left) {
2233
- const tmp = zone.left;
2234
- zone.left = zone.right;
2235
- zone.right = tmp;
2236
- }
2237
- if (zone.bottom !== undefined && zone.bottom < zone.top) {
2238
- const tmp = zone.top;
2239
- zone.top = zone.bottom;
2240
- zone.bottom = tmp;
2241
- }
2242
- return zone;
2232
+ return reorderZone(zone);
2243
2233
  }
2244
2234
  /**
2245
2235
  * Convert from a cartesian reference to a Zone.
@@ -2513,11 +2503,11 @@ function positions(zone) {
2513
2503
  return positions;
2514
2504
  }
2515
2505
  function reorderZone(zone) {
2516
- if (zone.left > zone.right) {
2517
- zone = { left: zone.right, right: zone.left, top: zone.top, bottom: zone.bottom };
2506
+ if (zone.right !== undefined && zone.left > zone.right) {
2507
+ zone = { ...zone, left: zone.right, right: zone.left };
2518
2508
  }
2519
- if (zone.top > zone.bottom) {
2520
- zone = { left: zone.left, right: zone.right, top: zone.bottom, bottom: zone.top };
2509
+ if (zone.bottom !== undefined && zone.top > zone.bottom) {
2510
+ zone = { ...zone, top: zone.bottom, bottom: zone.top };
2521
2511
  }
2522
2512
  return zone;
2523
2513
  }
@@ -3422,12 +3412,12 @@ function isTargetDependent(cmd) {
3422
3412
  function isRangeDependant(cmd) {
3423
3413
  return "ranges" in cmd;
3424
3414
  }
3425
- function isZoneDependent(cmd) {
3426
- return "zone" in cmd;
3427
- }
3428
3415
  function isPositionDependent(cmd) {
3429
3416
  return "col" in cmd && "row" in cmd && "sheetId" in cmd;
3430
3417
  }
3418
+ function isZoneDependent(cmd) {
3419
+ return "sheetId" in cmd && "zone" in cmd;
3420
+ }
3431
3421
  const invalidateEvaluationCommands = new Set([
3432
3422
  "RENAME_SHEET",
3433
3423
  "DELETE_SHEET",
@@ -3439,6 +3429,7 @@ const invalidateEvaluationCommands = new Set([
3439
3429
  "REDO",
3440
3430
  "ADD_MERGE",
3441
3431
  "REMOVE_MERGE",
3432
+ "DUPLICATE_SHEET",
3442
3433
  "UPDATE_LOCALE",
3443
3434
  "ADD_PIVOT",
3444
3435
  "UPDATE_PIVOT",
@@ -3468,7 +3459,6 @@ const invalidateChartEvaluationCommands = new Set([
3468
3459
  ]);
3469
3460
  const invalidateDependenciesCommands = new Set(["MOVE_RANGES"]);
3470
3461
  const invalidateCFEvaluationCommands = new Set([
3471
- "DUPLICATE_SHEET",
3472
3462
  "EVALUATE_CELLS",
3473
3463
  "ADD_CONDITIONAL_FORMAT",
3474
3464
  "REMOVE_CONDITIONAL_FORMAT",
@@ -3638,6 +3628,7 @@ var CommandResult;
3638
3628
  CommandResult["InvalidRange"] = "InvalidRange";
3639
3629
  CommandResult["InvalidZones"] = "InvalidZones";
3640
3630
  CommandResult["InvalidSheetId"] = "InvalidSheetId";
3631
+ CommandResult["InvalidCellId"] = "InvalidCellId";
3641
3632
  CommandResult["InvalidFigureId"] = "InvalidFigureId";
3642
3633
  CommandResult["InputAlreadyFocused"] = "InputAlreadyFocused";
3643
3634
  CommandResult["MaximumRangesReached"] = "MaximumRangesReached";
@@ -4467,7 +4458,7 @@ function dichotomicSearch(data, target, mode, sortOrder, rangeLength, getValueIn
4467
4458
  * @param reverseSearch if true, search in the array starting from the end.
4468
4459
 
4469
4460
  */
4470
- function linearSearch(data, target, mode, numberOfValues, getValueInData, reverseSearch = false) {
4461
+ function linearSearch(data, target, mode, numberOfValues, getValueInData, lookupCaches, reverseSearch = false) {
4471
4462
  if (target === undefined || target.value === null) {
4472
4463
  return -1;
4473
4464
  }
@@ -4476,17 +4467,48 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
4476
4467
  }
4477
4468
  const _target = normalizeValue(target.value);
4478
4469
  const getValue = reverseSearch
4479
- ? (data, i) => getValueInData(data, numberOfValues - i - 1)
4480
- : getValueInData;
4470
+ ? (data, i) => normalizeValue(getValueInData(data, numberOfValues - i - 1))
4471
+ : (data, i) => normalizeValue(getValueInData(data, i));
4472
+ // first check if the target is in the cache
4473
+ const isNotWildcardTarget = mode !== "wildcard" ||
4474
+ typeof _target !== "string" ||
4475
+ !(_target.includes("*") || _target.includes("?"));
4476
+ if (lookupCaches && isNotWildcardTarget) {
4477
+ const searchMode = reverseSearch ? "reverseSearch" : "forwardSearch";
4478
+ let cache = lookupCaches[searchMode].get(data);
4479
+ if (cache === undefined) {
4480
+ // build the cache for all the values
4481
+ cache = new Map();
4482
+ for (let i = 0; i < numberOfValues; i++) {
4483
+ const value = getValue(data, i) ?? null;
4484
+ if (!cache.has(value)) {
4485
+ cache.set(value, i);
4486
+ }
4487
+ }
4488
+ lookupCaches[searchMode].set(data, cache);
4489
+ }
4490
+ if (cache.has(_target)) {
4491
+ const resultIndex = cache.get(_target);
4492
+ return reverseSearch ? numberOfValues - resultIndex - 1 : resultIndex;
4493
+ }
4494
+ if (mode === "strict") {
4495
+ return -1;
4496
+ }
4497
+ }
4498
+ // else perform the linear search
4499
+ const resultIndex = _linearSearch(data, _target, mode, numberOfValues, getValue);
4500
+ return reverseSearch && resultIndex !== -1 ? numberOfValues - resultIndex - 1 : resultIndex;
4501
+ }
4502
+ function _linearSearch(data, _target, mode, numberOfValues, getNormalizeValue) {
4481
4503
  let indexMatchTarget = (i) => {
4482
- return normalizeValue(getValue(data, i)) === _target;
4504
+ return getNormalizeValue(data, i) === _target;
4483
4505
  };
4484
4506
  if (mode === "wildcard" &&
4485
4507
  typeof _target === "string" &&
4486
4508
  (_target.includes("*") || _target.includes("?"))) {
4487
4509
  const regExp = wildcardToRegExp(_target);
4488
4510
  indexMatchTarget = (i) => {
4489
- const value = normalizeValue(getValue(data, i));
4511
+ const value = getNormalizeValue(data, i);
4490
4512
  if (typeof value === "string") {
4491
4513
  return regExp.test(value);
4492
4514
  }
@@ -4497,7 +4519,7 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
4497
4519
  let closestMatchIndex = -1;
4498
4520
  if (mode === "nextSmaller") {
4499
4521
  indexMatchTarget = (i) => {
4500
- const value = normalizeValue(getValue(data, i));
4522
+ const value = getNormalizeValue(data, i);
4501
4523
  if ((!closestMatch && compareCellValues(_target, value) >= 0) ||
4502
4524
  (compareCellValues(_target, value) >= 0 && compareCellValues(value, closestMatch) > 0)) {
4503
4525
  closestMatch = value;
@@ -4508,7 +4530,7 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
4508
4530
  }
4509
4531
  if (mode === "nextGreater") {
4510
4532
  indexMatchTarget = (i) => {
4511
- const value = normalizeValue(getValue(data, i));
4533
+ const value = getNormalizeValue(data, i);
4512
4534
  if ((!closestMatch && compareCellValues(_target, value) <= 0) ||
4513
4535
  (compareCellValues(_target, value) <= 0 && compareCellValues(value, closestMatch) < 0)) {
4514
4536
  closestMatch = value;
@@ -4519,12 +4541,10 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
4519
4541
  }
4520
4542
  for (let i = 0; i < numberOfValues; i++) {
4521
4543
  if (indexMatchTarget(i)) {
4522
- return reverseSearch ? numberOfValues - i - 1 : i;
4544
+ return i;
4523
4545
  }
4524
4546
  }
4525
- return reverseSearch && closestMatchIndex !== -1
4526
- ? numberOfValues - closestMatchIndex - 1
4527
- : closestMatchIndex;
4547
+ return closestMatchIndex;
4528
4548
  }
4529
4549
  /**
4530
4550
  * Normalize a value.
@@ -6498,10 +6518,11 @@ class UuidGenerator {
6498
6518
  *
6499
6519
  */
6500
6520
  smallUuid() {
6501
- //@ts-ignore
6502
- if (window.crypto && window.crypto.getRandomValues) {
6503
- //@ts-ignore
6504
- return ([1e7] + -1e3).replace(/[018]/g, (c) => (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16));
6521
+ if (window.crypto) {
6522
+ return "10000000-1000".replace(/[01]/g, (c) => {
6523
+ const n = Number(c);
6524
+ return (n ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (n / 4)))).toString(16);
6525
+ });
6505
6526
  }
6506
6527
  else {
6507
6528
  // mainly for jest and other browsers that do not have the crypto functionality
@@ -6516,10 +6537,11 @@ class UuidGenerator {
6516
6537
  * This method should be used when you need to avoid collisions at all costs, like the id of a revision.
6517
6538
  */
6518
6539
  uuidv4() {
6519
- //@ts-ignore
6520
- if (window.crypto && window.crypto.getRandomValues) {
6521
- //@ts-ignore
6522
- return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16));
6540
+ if (window.crypto) {
6541
+ return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c) => {
6542
+ const n = Number(c);
6543
+ return (n ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (n / 4)))).toString(16);
6544
+ });
6523
6545
  }
6524
6546
  else {
6525
6547
  // mainly for jest and other browsers that do not have the crypto functionality
@@ -12236,6 +12258,25 @@ const LN = {
12236
12258
  isExported: true,
12237
12259
  };
12238
12260
  // -----------------------------------------------------------------------------
12261
+ // LOG
12262
+ // -----------------------------------------------------------------------------
12263
+ const LOG = {
12264
+ description: _t("The logarithm of a number, for a given base."),
12265
+ args: [
12266
+ arg("value (number)", _t("The value for which to calculate the logarithm.")),
12267
+ arg("base (number, default=10)", _t("The base of the logarithm.")),
12268
+ ],
12269
+ compute: function (value, base = { value: 10 }) {
12270
+ const _value = toNumber(value, this.locale);
12271
+ const _base = toNumber(base, this.locale);
12272
+ assert(() => _value > 0, _t("The value (%s) must be strictly positive.", _value.toString()));
12273
+ assert(() => _base > 0, _t("The base (%s) must be strictly positive.", _base.toString()));
12274
+ assert(() => _base !== 1, _t("The base must be different from 1."));
12275
+ return Math.log10(_value) / Math.log10(_base);
12276
+ },
12277
+ isExported: true,
12278
+ };
12279
+ // -----------------------------------------------------------------------------
12239
12280
  // MOD
12240
12281
  // -----------------------------------------------------------------------------
12241
12282
  function mod(dividend, divisor) {
@@ -12775,6 +12816,7 @@ var math = /*#__PURE__*/Object.freeze({
12775
12816
  ISODD: ISODD,
12776
12817
  ISO_CEILING: ISO_CEILING,
12777
12818
  LN: LN,
12819
+ LOG: LOG,
12778
12820
  MOD: MOD,
12779
12821
  MUNIT: MUNIT,
12780
12822
  ODD: ODD,
@@ -18673,7 +18715,7 @@ const HLOOKUP = {
18673
18715
  const _isSorted = toBoolean(isSorted.value);
18674
18716
  const colIndex = _isSorted
18675
18717
  ? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range.length, getValueFromRange)
18676
- : linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange);
18718
+ : linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange, this.lookupCaches);
18677
18719
  const col = _range[colIndex];
18678
18720
  if (col === undefined) {
18679
18721
  return valueNotAvailable(searchKey);
@@ -18828,7 +18870,7 @@ const MATCH = {
18828
18870
  index = dichotomicSearch(_range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
18829
18871
  break;
18830
18872
  case 0:
18831
- index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement);
18873
+ index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement, this.lookupCaches);
18832
18874
  break;
18833
18875
  case -1:
18834
18876
  index = dichotomicSearch(_range, searchKey, "nextGreater", "desc", rangeLen, getElement);
@@ -18896,7 +18938,7 @@ const VLOOKUP = {
18896
18938
  const _isSorted = toBoolean(isSorted.value);
18897
18939
  const rowIndex = _isSorted
18898
18940
  ? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range[0].length, getValueFromRange)
18899
- : linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange);
18941
+ : linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange, this.lookupCaches);
18900
18942
  const value = _range[_index - 1][rowIndex];
18901
18943
  if (value === undefined) {
18902
18944
  return valueNotAvailable(searchKey);
@@ -18952,7 +18994,7 @@ const XLOOKUP = {
18952
18994
  const reverseSearch = _searchMode === -1;
18953
18995
  const index = _searchMode === 2 || _searchMode === -2
18954
18996
  ? dichotomicSearch(_lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
18955
- : linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, reverseSearch);
18997
+ : linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, this.lookupCaches, reverseSearch);
18956
18998
  if (index !== -1) {
18957
18999
  return lookupDirection === "col"
18958
19000
  ? _returnRange.map((col) => [col[index]])
@@ -28291,7 +28333,7 @@ function getBarChartData(definition, dataSets, labelRange, getters) {
28291
28333
  }
28292
28334
  function getPyramidChartData(definition, dataSets, labelRange, getters) {
28293
28335
  const barChartData = getBarChartData(definition, dataSets, labelRange, getters);
28294
- const barDataset = barChartData.dataSetsValues;
28336
+ const barDataset = barChartData.dataSetsValues.filter((ds) => !ds.hidden);
28295
28337
  const pyramidDatasetValues = [];
28296
28338
  if (barDataset[0]) {
28297
28339
  const pyramidData = barDataset[0].data.map((value) => (value > 0 ? value : 0));
@@ -28768,10 +28810,8 @@ function getChartDatasetFormat(getters, allDataSets, axis) {
28768
28810
  function getChartDatasetValues(getters, dataSets) {
28769
28811
  const datasetValues = [];
28770
28812
  for (const [dsIndex, ds] of Object.entries(dataSets)) {
28771
- if (getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left)) {
28772
- continue;
28773
- }
28774
28813
  let label;
28814
+ let hidden = getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left);
28775
28815
  if (ds.labelCell) {
28776
28816
  const labelRange = ds.labelCell;
28777
28817
  const cell = labelRange
@@ -28798,9 +28838,9 @@ function getChartDatasetValues(getters, dataSets) {
28798
28838
  data.fill(1);
28799
28839
  }
28800
28840
  else if (data.every((cell) => cell === undefined || cell === null || !isNumber(cell.toString(), DEFAULT_LOCALE))) {
28801
- continue;
28841
+ hidden = true;
28802
28842
  }
28803
- datasetValues.push({ data, label });
28843
+ datasetValues.push({ data, label, hidden });
28804
28844
  }
28805
28845
  return datasetValues;
28806
28846
  }
@@ -28811,12 +28851,13 @@ function getBarChartDatasets(definition, args) {
28811
28851
  const colors = getChartColorsGenerator(definition, dataSetsValues.length);
28812
28852
  const trendDatasets = [];
28813
28853
  for (const index in dataSetsValues) {
28814
- let { label, data } = dataSetsValues[index];
28854
+ let { label, data, hidden } = dataSetsValues[index];
28815
28855
  label = definition.dataSets?.[index].label || label;
28816
28856
  const backgroundColor = colors.next();
28817
28857
  const dataset = {
28818
28858
  label,
28819
28859
  data,
28860
+ hidden,
28820
28861
  borderColor: definition.background || BACKGROUND_CHART_COLOR,
28821
28862
  borderWidth: definition.stacked ? 1 : 0,
28822
28863
  backgroundColor,
@@ -28849,6 +28890,9 @@ function getWaterfallDatasetAndLabels(definition, args) {
28849
28890
  const labelsWithSubTotals = [];
28850
28891
  let lastValue = 0;
28851
28892
  for (const dataSetsValue of dataSetsValues) {
28893
+ if (dataSetsValue.hidden) {
28894
+ continue;
28895
+ }
28852
28896
  for (let i = 0; i < dataSetsValue.data.length; i++) {
28853
28897
  const data = dataSetsValue.data[i];
28854
28898
  labelsWithSubTotals.push(labels[i]);
@@ -28884,7 +28928,7 @@ function getLineChartDatasets(definition, args) {
28884
28928
  const trendDatasets = [];
28885
28929
  const colors = getChartColorsGenerator(definition, dataSetsValues.length);
28886
28930
  for (let index = 0; index < dataSetsValues.length; index++) {
28887
- let { label, data } = dataSetsValues[index];
28931
+ let { label, data, hidden } = dataSetsValues[index];
28888
28932
  label = definition.dataSets?.[index].label || label;
28889
28933
  const color = colors.next();
28890
28934
  if (axisType && ["linear", "time"].includes(axisType)) {
@@ -28894,6 +28938,7 @@ function getLineChartDatasets(definition, args) {
28894
28938
  const dataset = {
28895
28939
  label,
28896
28940
  data,
28941
+ hidden,
28897
28942
  tension: 0, // 0 -> render straight lines, which is much faster
28898
28943
  borderColor: color,
28899
28944
  backgroundColor: areaChart ? setColorAlpha(color, LINE_FILL_TRANSPARENCY) : color,
@@ -28926,11 +28971,13 @@ function getPieChartDatasets(definition, args) {
28926
28971
  const dataSets = [];
28927
28972
  const dataSetsLength = Math.max(0, ...dataSetsValues.map((ds) => ds?.data?.length ?? 0));
28928
28973
  const backgroundColor = getPieColors(new ColorGenerator(dataSetsLength), dataSetsValues);
28929
- for (const { label, data } of dataSetsValues) {
28974
+ for (const { label, data, hidden } of dataSetsValues) {
28975
+ if (hidden)
28976
+ continue;
28930
28977
  const dataset = {
28931
28978
  label,
28932
28979
  data,
28933
- borderColor: BACKGROUND_CHART_COLOR,
28980
+ borderColor: definition.background || "#FFFFFF",
28934
28981
  backgroundColor,
28935
28982
  hoverOffset: 30,
28936
28983
  };
@@ -28944,7 +28991,7 @@ function getComboChartDatasets(definition, args) {
28944
28991
  const colors = getChartColorsGenerator(definition, dataSetsValues.length);
28945
28992
  const trendDatasets = [];
28946
28993
  for (let index = 0; index < dataSetsValues.length; index++) {
28947
- let { label, data } = dataSetsValues[index];
28994
+ let { label, data, hidden } = dataSetsValues[index];
28948
28995
  label = definition.dataSets?.[index].label || label;
28949
28996
  const design = definition.dataSets?.[index];
28950
28997
  const color = colors.next();
@@ -28952,6 +28999,7 @@ function getComboChartDatasets(definition, args) {
28952
28999
  const dataset = {
28953
29000
  label: label,
28954
29001
  data,
29002
+ hidden,
28955
29003
  borderColor: color,
28956
29004
  backgroundColor: color,
28957
29005
  yAxisID: definition.dataSets?.[index].yAxisId || "y",
@@ -28976,7 +29024,7 @@ function getRadarChartDatasets(definition, args) {
28976
29024
  const fill = definition.fillArea ?? false;
28977
29025
  const colors = getChartColorsGenerator(definition, dataSetsValues.length);
28978
29026
  for (let i = 0; i < dataSetsValues.length; i++) {
28979
- let { label, data } = dataSetsValues[i];
29027
+ let { label, data, hidden } = dataSetsValues[i];
28980
29028
  if (definition.dataSets?.[i]?.label) {
28981
29029
  label = definition.dataSets[i].label;
28982
29030
  }
@@ -28984,6 +29032,7 @@ function getRadarChartDatasets(definition, args) {
28984
29032
  const dataset = {
28985
29033
  label,
28986
29034
  data,
29035
+ hidden,
28987
29036
  borderColor,
28988
29037
  backgroundColor: borderColor,
28989
29038
  };
@@ -29129,6 +29178,11 @@ function getPieChartLegend(definition, args) {
29129
29178
  hidden: false,
29130
29179
  lineWidth: 2,
29131
29180
  })),
29181
+ filter: (legendItem, data) => {
29182
+ return "datasetIndex" in legendItem
29183
+ ? !data.datasets[legendItem.datasetIndex].hidden
29184
+ : true;
29185
+ },
29132
29186
  },
29133
29187
  };
29134
29188
  }
@@ -29190,6 +29244,11 @@ function getWaterfallChartLegend(definition, args) {
29190
29244
  }
29191
29245
  return legendValues;
29192
29246
  },
29247
+ filter: (legendItem, data) => {
29248
+ return "datasetIndex" in legendItem
29249
+ ? !data.datasets[legendItem.datasetIndex].hidden
29250
+ : true;
29251
+ },
29193
29252
  },
29194
29253
  onClick: () => { }, // Disables click interaction with the waterfall chart legend items
29195
29254
  };
@@ -29273,6 +29332,11 @@ function getCustomLegendLabels(fontColor, legendLabelConfig) {
29273
29332
  ...legendLabelConfig,
29274
29333
  };
29275
29334
  }),
29335
+ filter: (legendItem, data) => {
29336
+ return "datasetIndex" in legendItem
29337
+ ? !data.datasets[legendItem.datasetIndex].hidden
29338
+ : true;
29339
+ },
29276
29340
  },
29277
29341
  };
29278
29342
  }
@@ -29606,7 +29670,7 @@ const templates = /* xml */ `
29606
29670
  <div
29607
29671
  class="o-chart-custom-tooltip border rounded px-2 py-1 pe-none mw-100 position-absolute text-nowrap shadow opacity-100">
29608
29672
  <table class="overflow-hidden m-0">
29609
- <thead>
29673
+ <thead t-if="title">
29610
29674
  <tr>
29611
29675
  <th class="o-tooltip-title align-baseline border-0 text-truncate" t-esc="title" t-attf-style="max-width: {{ labelsMaxWidth }}"/>
29612
29676
  </tr>
@@ -29667,8 +29731,8 @@ function getBarChartTooltip(definition, args) {
29667
29731
  ? undefined
29668
29732
  : "";
29669
29733
  },
29734
+ beforeLabel: (tooltipItem) => tooltipItem.dataset?.label || tooltipItem.label,
29670
29735
  label: function (tooltipItem) {
29671
- const xLabel = tooltipItem.dataset?.label || tooltipItem.label;
29672
29736
  const horizontalChart = definition.horizontal;
29673
29737
  let yLabel = horizontalChart ? tooltipItem.parsed.x : tooltipItem.parsed.y;
29674
29738
  if (yLabel === undefined || yLabel === null) {
@@ -29676,7 +29740,7 @@ function getBarChartTooltip(definition, args) {
29676
29740
  }
29677
29741
  const axisId = horizontalChart ? tooltipItem.dataset.xAxisID : tooltipItem.dataset.yAxisID;
29678
29742
  const yLabelStr = formatChartDatasetValue(args.axisFormats, args.locale)(yLabel, axisId);
29679
- return xLabel ? `${xLabel}: ${yLabelStr}` : yLabelStr;
29743
+ return yLabelStr;
29680
29744
  },
29681
29745
  },
29682
29746
  };
@@ -29701,21 +29765,18 @@ function getLineChartTooltip(definition, args) {
29701
29765
  const formattedX = formatValue(label, { locale, format: labelFormat });
29702
29766
  const axisId = tooltipItem.dataset.yAxisID || "y";
29703
29767
  const formattedY = formatValue(dataSetPoint, { locale, format: axisFormats?.[axisId] });
29704
- const dataSetTitle = tooltipItem.dataset.label;
29705
- return formattedX
29706
- ? `${dataSetTitle}: (${formattedX}, ${formattedY})`
29707
- : `${dataSetTitle}: ${formattedY}`;
29768
+ return formattedX ? `(${formattedX}, ${formattedY})` : `${formattedY}`;
29708
29769
  };
29709
29770
  }
29710
29771
  else {
29711
29772
  tooltip.callbacks.label = function (tooltipItem) {
29712
- const xLabel = tooltipItem.dataset?.label || tooltipItem.label;
29713
29773
  const yLabel = tooltipItem.parsed.y;
29714
29774
  const axisId = tooltipItem.dataset.yAxisID;
29715
29775
  const yLabelStr = formatChartDatasetValue(axisFormats, locale)(yLabel, axisId);
29716
- return xLabel ? `${xLabel}: ${yLabelStr}` : yLabelStr;
29776
+ return yLabelStr;
29717
29777
  };
29718
29778
  }
29779
+ tooltip.callbacks.beforeLabel = (tooltipItem) => tooltipItem.dataset?.label || tooltipItem.label;
29719
29780
  tooltip.callbacks.title = function (tooltipItems) {
29720
29781
  const displayTooltipTitle = axisType !== "linear" &&
29721
29782
  tooltipItems.some((item) => item.dataset.xAxisID !== TREND_LINE_XAXIS_ID);
@@ -29733,17 +29794,15 @@ function getPieChartTooltip(definition, args) {
29733
29794
  title: function (tooltipItems) {
29734
29795
  return tooltipItems[0].dataset.label;
29735
29796
  },
29797
+ beforeLabel: (tooltipItem) => tooltipItem.label || tooltipItem.dataset.label,
29736
29798
  label: function (tooltipItem) {
29737
29799
  const data = tooltipItem.dataset.data;
29738
29800
  const dataIndex = tooltipItem.dataIndex;
29739
29801
  const percentage = calculatePercentage(data, dataIndex);
29740
- const xLabel = tooltipItem.label || tooltipItem.dataset.label;
29741
29802
  const yLabel = tooltipItem.parsed.y ?? tooltipItem.parsed;
29742
29803
  const toolTipFormat = !format && yLabel >= 1000 ? "#,##" : format;
29743
29804
  const yLabelStr = formatValue(yLabel, { format: toolTipFormat, locale });
29744
- return xLabel
29745
- ? `${xLabel}: ${yLabelStr} (${percentage}%)`
29746
- : `${yLabelStr} (${percentage}%)`;
29805
+ return `${yLabelStr} (${percentage}%)`;
29747
29806
  },
29748
29807
  },
29749
29808
  };
@@ -29756,16 +29815,17 @@ function getWaterfallChartTooltip(definition, args) {
29756
29815
  enabled: false,
29757
29816
  external: customTooltipHandler,
29758
29817
  callbacks: {
29759
- label: function (tooltipItem) {
29760
- const [lastValue, currentValue] = tooltipItem.raw;
29761
- const yLabel = currentValue - lastValue;
29818
+ beforeLabel: function (tooltipItem) {
29762
29819
  const dataSeriesIndex = labels.length
29763
29820
  ? Math.floor(tooltipItem.dataIndex / labels.length)
29764
29821
  : 0;
29765
- const dataSeriesLabel = dataSeriesLabels[dataSeriesIndex];
29822
+ return dataSeriesLabels[dataSeriesIndex];
29823
+ },
29824
+ label: function (tooltipItem) {
29825
+ const [lastValue, currentValue] = tooltipItem.raw;
29826
+ const yLabel = currentValue - lastValue;
29766
29827
  const toolTipFormat = !format && Math.abs(yLabel) > 1000 ? "#,##" : format;
29767
- const yLabelStr = formatValue(yLabel, { format: toolTipFormat, locale });
29768
- return dataSeriesLabel ? `${dataSeriesLabel}: ${yLabelStr}` : yLabelStr;
29828
+ return formatValue(yLabel, { format: toolTipFormat, locale });
29769
29829
  },
29770
29830
  },
29771
29831
  };
@@ -29789,11 +29849,10 @@ function getRadarChartTooltip(definition, args) {
29789
29849
  enabled: false,
29790
29850
  external: customTooltipHandler,
29791
29851
  callbacks: {
29852
+ beforeLabel: (tooltipItem) => tooltipItem.dataset?.label || tooltipItem.label,
29792
29853
  label: function (tooltipItem) {
29793
- const xLabel = tooltipItem.dataset?.label || tooltipItem.label;
29794
29854
  const yLabel = tooltipItem.parsed.r;
29795
- const formattedY = formatValue(yLabel, { format: axisFormats?.r, locale });
29796
- return xLabel ? `${xLabel}: ${formattedY}` : formattedY;
29855
+ return formatValue(yLabel, { format: axisFormats?.r, locale });
29797
29856
  },
29798
29857
  },
29799
29858
  };
@@ -29808,13 +29867,12 @@ function getGeoChartTooltip(definition, args) {
29808
29867
  return tooltipItem.raw.value !== undefined;
29809
29868
  },
29810
29869
  callbacks: {
29870
+ beforeLabel: (tooltipItem) => tooltipItem.raw.feature.properties.name,
29811
29871
  label: function (tooltipItem) {
29812
29872
  const rawItem = tooltipItem.raw;
29813
- const xLabel = rawItem.feature.properties.name;
29814
29873
  const yLabel = rawItem.value;
29815
29874
  const toolTipFormat = !format && Math.abs(yLabel) >= 1000 ? "#,##" : format;
29816
- const yLabelStr = formatValue(yLabel, { format: toolTipFormat, locale });
29817
- return xLabel ? `${xLabel}: ${yLabelStr}` : yLabelStr;
29875
+ return formatValue(yLabel, { format: toolTipFormat, locale });
29818
29876
  },
29819
29877
  },
29820
29878
  };
@@ -29834,7 +29892,8 @@ function customTooltipHandler({ chart, tooltip }) {
29834
29892
  return;
29835
29893
  }
29836
29894
  const tooltipItems = tooltip.body.map((body, index) => {
29837
- let [label, value] = body.lines[0].split(":").map((str) => str.trim());
29895
+ let label = body.before[0];
29896
+ let value = body.lines[0];
29838
29897
  if (!value) {
29839
29898
  value = label;
29840
29899
  label = "";
@@ -38918,7 +38977,7 @@ css /* scss */ `
38918
38977
  .o-font-size-editor {
38919
38978
  height: calc(100% - 4px);
38920
38979
  input.o-font-size {
38921
- outline-color: ${SELECTION_BORDER_COLOR};
38980
+ outline: none;
38922
38981
  height: 20px;
38923
38982
  width: 23px;
38924
38983
  }
@@ -51626,8 +51685,8 @@ class Border extends Component {
51626
51685
  css /* scss */ `
51627
51686
  .o-corner {
51628
51687
  position: absolute;
51629
- height: 6px;
51630
- width: 6px;
51688
+ height: 8px;
51689
+ width: 8px;
51631
51690
  border: 1px solid white;
51632
51691
  }
51633
51692
  .o-corner-nw,
@@ -53464,6 +53523,10 @@ class CellPlugin extends CorePlugin {
53464
53523
  return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessUpdateCell);
53465
53524
  case "CLEAR_CELL":
53466
53525
  return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessClearCell);
53526
+ case "UPDATE_CELL_POSITION":
53527
+ return !cmd.cellId || this.cells[cmd.sheetId]?.[cmd.cellId]
53528
+ ? "Success" /* CommandResult.Success */
53529
+ : "InvalidCellId" /* CommandResult.InvalidCellId */;
53467
53530
  default:
53468
53531
  return "Success" /* CommandResult.Success */;
53469
53532
  }
@@ -53508,6 +53571,9 @@ class CellPlugin extends CorePlugin {
53508
53571
  case "DELETE_CONTENT":
53509
53572
  this.clearZones(cmd.sheetId, cmd.target);
53510
53573
  break;
53574
+ case "DELETE_SHEET": {
53575
+ this.history.update("cells", cmd.sheetId, undefined);
53576
+ }
53511
53577
  }
53512
53578
  }
53513
53579
  clearZones(sheetId, zones) {
@@ -54298,6 +54364,9 @@ class ConditionalFormatPlugin extends CorePlugin {
54298
54364
  allowDispatch(cmd) {
54299
54365
  switch (cmd.type) {
54300
54366
  case "ADD_CONDITIONAL_FORMAT":
54367
+ if (cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId))) {
54368
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
54369
+ }
54301
54370
  return this.checkValidations(cmd, this.checkCFRule, this.checkEmptyRange, this.checkCFHasChanged);
54302
54371
  case "CHANGE_CONDITIONAL_FORMAT_PRIORITY":
54303
54372
  return this.checkValidPriorityChange(cmd.cfId, cmd.delta, cmd.sheetId);
@@ -54714,8 +54783,17 @@ class DataValidationPlugin extends CorePlugin {
54714
54783
  allowDispatch(cmd) {
54715
54784
  switch (cmd.type) {
54716
54785
  case "ADD_DATA_VALIDATION_RULE":
54786
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
54787
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
54788
+ }
54789
+ if (cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId))) {
54790
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
54791
+ }
54717
54792
  return this.checkValidations(cmd, this.chainValidations(this.checkEmptyRange, this.checkValidRange, this.checkCriterionTypeIsValid, this.checkCriterionHasValidNumberOfValues, this.checkCriterionValuesAreValid));
54718
54793
  case "REMOVE_DATA_VALIDATION_RULE":
54794
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
54795
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
54796
+ }
54719
54797
  if (!this.rules[cmd.sheetId].find((rule) => rule.id === cmd.id)) {
54720
54798
  return "UnknownDataValidationRule" /* CommandResult.UnknownDataValidationRule */;
54721
54799
  }
@@ -54942,6 +55020,7 @@ class DataValidationPlugin extends CorePlugin {
54942
55020
  class FigurePlugin extends CorePlugin {
54943
55021
  static getters = ["getFigures", "getFigure", "getFigureSheetId"];
54944
55022
  figures = {};
55023
+ insertionOrders = []; // TODO use a list in master
54945
55024
  // ---------------------------------------------------------------------------
54946
55025
  // Command Handling
54947
55026
  // ---------------------------------------------------------------------------
@@ -55044,11 +55123,14 @@ class FigurePlugin extends CorePlugin {
55044
55123
  }
55045
55124
  addFigure(figure, sheetId) {
55046
55125
  this.history.update("figures", sheetId, figure.id, figure);
55126
+ this.history.update("insertionOrders", this.insertionOrders.length, figure.id);
55047
55127
  }
55048
55128
  deleteSheet(sheetId) {
55129
+ this.history.update("insertionOrders", this.insertionOrders.filter((id) => !this.figures[sheetId]?.[id]));
55049
55130
  this.history.update("figures", sheetId, undefined);
55050
55131
  }
55051
55132
  removeFigure(id, sheetId) {
55133
+ this.history.update("insertionOrders", this.insertionOrders.filter((figureId) => figureId !== id));
55052
55134
  this.history.update("figures", sheetId, id, undefined);
55053
55135
  }
55054
55136
  checkFigureExists(sheetId, figureId) {
@@ -55067,7 +55149,14 @@ class FigurePlugin extends CorePlugin {
55067
55149
  // Getters
55068
55150
  // ---------------------------------------------------------------------------
55069
55151
  getFigures(sheetId) {
55070
- return Object.values(this.figures[sheetId] || {}).filter(isDefined);
55152
+ const figures = [];
55153
+ for (const figureId of this.insertionOrders) {
55154
+ const figure = this.figures[sheetId]?.[figureId];
55155
+ if (figure) {
55156
+ figures.push(figure);
55157
+ }
55158
+ }
55159
+ return figures;
55071
55160
  }
55072
55161
  getFigure(sheetId, figureId) {
55073
55162
  return this.figures[sheetId]?.[figureId];
@@ -55080,11 +55169,9 @@ class FigurePlugin extends CorePlugin {
55080
55169
  // ---------------------------------------------------------------------------
55081
55170
  import(data) {
55082
55171
  for (let sheet of data.sheets) {
55083
- const figures = {};
55084
- sheet.figures.forEach((figure) => {
55085
- figures[figure.id] = figure;
55086
- });
55087
- this.figures[sheet.id] = figures;
55172
+ for (const figure of sheet.figures) {
55173
+ this.addFigure(figure, sheet.id);
55174
+ }
55088
55175
  }
55089
55176
  }
55090
55177
  export(data) {
@@ -56544,6 +56631,9 @@ class SheetPlugin extends CorePlugin {
56544
56631
  case "CREATE_SHEET": {
56545
56632
  return this.checkValidations(cmd, this.checkSheetName, this.checkSheetPosition);
56546
56633
  }
56634
+ case "DUPLICATE_SHEET": {
56635
+ return this.sheets[cmd.sheetIdTo] ? "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */ : "Success" /* CommandResult.Success */;
56636
+ }
56547
56637
  case "MOVE_SHEET":
56548
56638
  try {
56549
56639
  const currentIndex = this.orderedSheetIds.findIndex((id) => id === cmd.sheetId);
@@ -57346,14 +57436,18 @@ class SheetPlugin extends CorePlugin {
57346
57436
  checkZonesAreInSheet(cmd) {
57347
57437
  if (!("sheetId" in cmd))
57348
57438
  return "Success" /* CommandResult.Success */;
57439
+ if ("ranges" in cmd &&
57440
+ cmd.ranges.some((rangeData) => rangeData._sheetId !== "" && !this.getters.tryGetSheet(rangeData._sheetId))) {
57441
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
57442
+ }
57349
57443
  return this.checkZonesExistInSheet(cmd.sheetId, this.getCommandZones(cmd));
57350
57444
  }
57351
57445
  }
57352
57446
 
57353
- let nextTableId = 1;
57354
57447
  class TablePlugin extends CorePlugin {
57355
57448
  static getters = ["getCoreTable", "getCoreTables", "getCoreTableMatchingTopLeft"];
57356
57449
  tables = {};
57450
+ nextTableId = 1;
57357
57451
  adaptRanges(applyChange, sheetId) {
57358
57452
  const sheetIds = sheetId ? [sheetId] : this.getters.getSheetIds();
57359
57453
  for (const sheetId of sheetIds) {
@@ -57365,6 +57459,9 @@ class TablePlugin extends CorePlugin {
57365
57459
  allowDispatch(cmd) {
57366
57460
  switch (cmd.type) {
57367
57461
  case "CREATE_TABLE":
57462
+ if (cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId) || rangeData._sheetId !== cmd.sheetId)) {
57463
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
57464
+ }
57368
57465
  const zones = cmd.ranges.map((rangeData) => this.getters.getRangeFromRangeData(rangeData).zone);
57369
57466
  if (!areZonesContinuous(zones)) {
57370
57467
  return "NonContinuousTargets" /* CommandResult.NonContinuousTargets */;
@@ -57418,7 +57515,7 @@ class TablePlugin extends CorePlugin {
57418
57515
  const union = this.getters.getRangesUnion(ranges);
57419
57516
  const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, union.zone);
57420
57517
  this.dispatch("REMOVE_MERGE", { sheetId: cmd.sheetId, target: mergesInTarget });
57421
- const id = `${nextTableId++}`;
57518
+ const id = this.consumeNextId();
57422
57519
  const config = cmd.config || DEFAULT_TABLE_CONFIG;
57423
57520
  const newTable = cmd.tableType === "dynamic"
57424
57521
  ? this.createDynamicTable(id, union, config)
@@ -57571,7 +57668,7 @@ class TablePlugin extends CorePlugin {
57571
57668
  filters = [];
57572
57669
  for (const i of range(zone.left, zone.right + 1)) {
57573
57670
  const filterZone = { ...zone, left: i, right: i };
57574
- const uid = `${nextTableId++}`;
57671
+ const uid = this.consumeNextId();
57575
57672
  filters.push(this.createFilterFromZone(uid, tableRange.sheetId, filterZone, config));
57576
57673
  }
57577
57674
  }
@@ -57636,7 +57733,7 @@ class TablePlugin extends CorePlugin {
57636
57733
  ? table.filters.find((f) => f.col === i)
57637
57734
  : undefined;
57638
57735
  const filterZone = { ...tableZone, left: i, right: i };
57639
- const filterId = oldFilter?.id || `${nextTableId++}`;
57736
+ const filterId = oldFilter?.id || this.consumeNextId();
57640
57737
  filters.push(this.createFilterFromZone(filterId, tableRange.sheetId, filterZone, config));
57641
57738
  }
57642
57739
  }
@@ -57737,7 +57834,7 @@ class TablePlugin extends CorePlugin {
57737
57834
  if (filters.length < zoneToDimension(tableZone).numberOfCols) {
57738
57835
  for (let col = tableZone.left; col <= tableZone.right; col++) {
57739
57836
  if (!filters.find((filter) => filter.col === col)) {
57740
- const uid = `${nextTableId++}`;
57837
+ const uid = this.consumeNextId();
57741
57838
  const filterZone = { ...tableZone, left: col, right: col };
57742
57839
  filters.push(this.createFilterFromZone(uid, sheetId, filterZone, table.config));
57743
57840
  }
@@ -57747,13 +57844,18 @@ class TablePlugin extends CorePlugin {
57747
57844
  const newTable = this.createStaticTable(table.id, table.type, newTableRange, table.config, filters);
57748
57845
  this.history.update("tables", sheetId, table.id, newTable);
57749
57846
  }
57847
+ consumeNextId() {
57848
+ const id = `${this.nextTableId}`;
57849
+ this.history.update("nextTableId", this.nextTableId + 1);
57850
+ return id;
57851
+ }
57750
57852
  // ---------------------------------------------------------------------------
57751
57853
  // Import/Export
57752
57854
  // ---------------------------------------------------------------------------
57753
57855
  import(data) {
57754
57856
  for (const sheet of data.sheets) {
57755
57857
  for (const tableData of sheet.tables || []) {
57756
- const uuid = `${nextTableId++}`;
57858
+ const uuid = this.consumeNextId();
57757
57859
  const tableConfig = tableData.config || DEFAULT_TABLE_CONFIG;
57758
57860
  const range = this.getters.getRangeFromSheetXC(sheet.id, tableData.range);
57759
57861
  const tableType = tableData.type || "static";
@@ -57801,7 +57903,10 @@ class HeaderGroupingPlugin extends CorePlugin {
57801
57903
  allowDispatch(cmd) {
57802
57904
  switch (cmd.type) {
57803
57905
  case "GROUP_HEADERS": {
57804
- const { start, end } = cmd;
57906
+ const { start, end, sheetId } = cmd;
57907
+ if (!this.getters.tryGetSheet(sheetId)) {
57908
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
57909
+ }
57805
57910
  if (!this.getters.doesHeadersExist(cmd.sheetId, cmd.dimension, [start, end])) {
57806
57911
  return "InvalidHeaderGroupStartEnd" /* CommandResult.InvalidHeaderGroupStartEnd */;
57807
57912
  }
@@ -57814,7 +57919,10 @@ class HeaderGroupingPlugin extends CorePlugin {
57814
57919
  break;
57815
57920
  }
57816
57921
  case "UNGROUP_HEADERS": {
57817
- const { start, end } = cmd;
57922
+ const { start, end, sheetId } = cmd;
57923
+ if (!this.getters.tryGetSheet(sheetId)) {
57924
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
57925
+ }
57818
57926
  if (!this.getters.doesHeadersExist(cmd.sheetId, cmd.dimension, [start, end])) {
57819
57927
  return "InvalidHeaderGroupStartEnd" /* CommandResult.InvalidHeaderGroupStartEnd */;
57820
57928
  }
@@ -57825,6 +57933,9 @@ class HeaderGroupingPlugin extends CorePlugin {
57825
57933
  }
57826
57934
  case "UNFOLD_HEADER_GROUP":
57827
57935
  case "FOLD_HEADER_GROUP":
57936
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
57937
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
57938
+ }
57828
57939
  const group = this.findGroupWithStartEnd(cmd.sheetId, cmd.dimension, cmd.start, cmd.end);
57829
57940
  if (!group) {
57830
57941
  return "UnknownHeaderGroup" /* CommandResult.UnknownHeaderGroup */;
@@ -58225,6 +58336,9 @@ class PivotCorePlugin extends CorePlugin {
58225
58336
  return this.checkDuplicatedMeasureIds(cmd.pivot);
58226
58337
  }
58227
58338
  case "UPDATE_PIVOT": {
58339
+ if (!(cmd.pivotId in this.pivots)) {
58340
+ return "PivotIdNotFound" /* CommandResult.PivotIdNotFound */;
58341
+ }
58228
58342
  if (deepEquals(cmd.pivot, this.pivots[cmd.pivotId]?.definition)) {
58229
58343
  return "NoChanges" /* CommandResult.NoChanges */;
58230
58344
  }
@@ -58241,6 +58355,8 @@ class PivotCorePlugin extends CorePlugin {
58241
58355
  return "EmptyName" /* CommandResult.EmptyName */;
58242
58356
  }
58243
58357
  break;
58358
+ case "REMOVE_PIVOT":
58359
+ case "DUPLICATE_PIVOT":
58244
58360
  case "INSERT_PIVOT": {
58245
58361
  if (!(cmd.pivotId in this.pivots)) {
58246
58362
  return "PivotIdNotFound" /* CommandResult.PivotIdNotFound */;
@@ -58290,7 +58406,7 @@ class PivotCorePlugin extends CorePlugin {
58290
58406
  break;
58291
58407
  }
58292
58408
  case "UPDATE_PIVOT": {
58293
- this.history.update("pivots", cmd.pivotId, "definition", cmd.pivot);
58409
+ this.history.update("pivots", cmd.pivotId, "definition", deepCopy(cmd.pivot));
58294
58410
  this.compileCalculatedMeasures(cmd.pivot.measures);
58295
58411
  break;
58296
58412
  }
@@ -58361,7 +58477,7 @@ class PivotCorePlugin extends CorePlugin {
58361
58477
  // Private
58362
58478
  // -------------------------------------------------------------------------
58363
58479
  addPivot(pivotId, pivot, formulaId = this.nextFormulaId.toString()) {
58364
- this.history.update("pivots", pivotId, { definition: pivot, formulaId });
58480
+ this.history.update("pivots", pivotId, { definition: deepCopy(pivot), formulaId });
58365
58481
  this.compileCalculatedMeasures(pivot.measures);
58366
58482
  this.history.update("formulaIds", formulaId, pivotId);
58367
58483
  this.history.update("nextFormulaId", this.nextFormulaId + 1);
@@ -59931,6 +60047,10 @@ class Evaluator {
59931
60047
  this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
59932
60048
  this.compilationParams.evalContext.updateDependencies = this.updateDependencies.bind(this);
59933
60049
  this.compilationParams.evalContext.addDependencies = this.addDependencies.bind(this);
60050
+ this.compilationParams.evalContext.lookupCaches = {
60051
+ forwardSearch: new Map(),
60052
+ reverseSearch: new Map(),
60053
+ };
59934
60054
  }
59935
60055
  createEmptyPositionSet() {
59936
60056
  const sheetSizes = {};
@@ -63279,6 +63399,9 @@ function updateChartRangesTransformation(toTransform, executed) {
63279
63399
  };
63280
63400
  }
63281
63401
  function createSheetTransformation(toTransform, executed) {
63402
+ if (toTransform.sheetId === executed.sheetId) {
63403
+ toTransform = { ...toTransform, sheetId: `${toTransform.sheetId}~` };
63404
+ }
63282
63405
  if (toTransform.name === executed.name) {
63283
63406
  return {
63284
63407
  ...toTransform,
@@ -63922,15 +64045,6 @@ class Session extends EventBus {
63922
64045
  }
63923
64046
  this.sendPendingMessage();
63924
64047
  }
63925
- dropPendingRevision(revisionId) {
63926
- this.revisions.drop(revisionId);
63927
- const revisionIds = this.pendingMessages
63928
- .filter((message) => message.type === "REMOTE_REVISION")
63929
- .map((message) => message.nextRevisionId);
63930
- this.trigger("pending-revisions-dropped", { revisionIds });
63931
- this.waitingAck = false;
63932
- this.waitingUndoRedoAck = false;
63933
- }
63934
64048
  /**
63935
64049
  * Send the next pending message
63936
64050
  */
@@ -63939,15 +64053,14 @@ class Session extends EventBus {
63939
64053
  if (!message)
63940
64054
  return;
63941
64055
  if (message.type === "REMOTE_REVISION") {
63942
- const revision = this.revisions.get(message.nextRevisionId);
64056
+ let revision = this.revisions.get(message.nextRevisionId);
63943
64057
  if (revision.commands.length === 0) {
63944
64058
  /**
63945
- * The command is empty, we have to drop all the next local revisions
64059
+ * The command is empty, we have to rebase all the next local revisions
63946
64060
  * to avoid issues with undo/redo
63947
64061
  */
63948
- this.dropPendingRevision(revision.id);
63949
- this.pendingMessages = [];
63950
- return;
64062
+ this.revisions.rebase(revision.id);
64063
+ revision = this.revisions.get(message.nextRevisionId);
63951
64064
  }
63952
64065
  message = {
63953
64066
  ...message,
@@ -63983,18 +64096,16 @@ class Session extends EventBus {
63983
64096
  case "REVISION_UNDONE": {
63984
64097
  this.waitingAck = false;
63985
64098
  this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
63986
- const pendingRemoteRevisions = this.pendingMessages.filter((message) => message.type === "REMOTE_REVISION");
63987
- const firstTransformedRevisionIndex = pendingRemoteRevisions.findIndex((message) => !deepEquals(message.commands, this.revisions.get(message.nextRevisionId).commands));
63988
- if (firstTransformedRevisionIndex !== -1) {
64099
+ const firstPendingRevisionId = this.pendingMessages.findIndex((message) => message.type === "REMOTE_REVISION");
64100
+ if (firstPendingRevisionId !== -1) {
63989
64101
  /**
63990
64102
  * Some revisions undergo transformations that may cause issues with
63991
64103
  * undo/redo if the transformation is destructive (we don't get back
63992
64104
  * the original command by transforming it with the inverse).
63993
- * To prevent these problems, we must discard all subsequent local
64105
+ * To prevent these problems, we must rebase all subsequent local
63994
64106
  * revisions.
63995
64107
  */
63996
- this.dropPendingRevision(this.pendingMessages[firstTransformedRevisionIndex].nextRevisionId);
63997
- this.pendingMessages = this.pendingMessages.slice(0, firstTransformedRevisionIndex);
64108
+ this.revisions.rebase(this.pendingMessages[firstPendingRevisionId].nextRevisionId);
63998
64109
  }
63999
64110
  this.serverRevisionId = message.nextRevisionId;
64000
64111
  this.processedRevisions.add(message.nextRevisionId);
@@ -65116,6 +65227,10 @@ class SheetUIPlugin extends UIPlugin {
65116
65227
  */
65117
65228
  checkZonesAreInSheet(cmd) {
65118
65229
  const sheetId = "sheetId" in cmd ? cmd.sheetId : this.getters.tryGetActiveSheetId();
65230
+ if ("ranges" in cmd &&
65231
+ cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId))) {
65232
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
65233
+ }
65119
65234
  const zones = this.getters.getCommandZones(cmd);
65120
65235
  if (!sheetId && zones.length > 0) {
65121
65236
  return "NoActiveSheet" /* CommandResult.NoActiveSheet */;
@@ -65670,7 +65785,6 @@ class HistoryPlugin extends UIPlugin {
65670
65785
  super(config);
65671
65786
  this.session = config.session;
65672
65787
  this.session.on("new-local-state-update", this, this.onNewLocalStateUpdate);
65673
- this.session.on("pending-revisions-dropped", this, ({ revisionIds }) => this.drop(revisionIds));
65674
65788
  this.session.on("snapshot", this, () => {
65675
65789
  this.undoStack = [];
65676
65790
  this.redoStack = [];
@@ -65740,10 +65854,6 @@ class HistoryPlugin extends UIPlugin {
65740
65854
  const lastNonRedoRevision = this.getPossibleRevisionToRepeat();
65741
65855
  return canRepeatRevision(lastNonRedoRevision);
65742
65856
  }
65743
- drop(revisionIds) {
65744
- this.undoStack = this.undoStack.filter((id) => !revisionIds.includes(id));
65745
- this.redoStack = [];
65746
- }
65747
65857
  onNewLocalStateUpdate({ id }) {
65748
65858
  this.undoStack.push(id);
65749
65859
  this.redoStack = [];
@@ -68418,7 +68528,9 @@ class HeaderPositionsUIPlugin extends UIPlugin {
68418
68528
  case "UNGROUP_HEADERS":
68419
68529
  case "GROUP_HEADERS":
68420
68530
  case "CREATE_SHEET":
68421
- this.headerPositions[cmd.sheetId] = this.computeHeaderPositionsOfSheet(cmd.sheetId);
68531
+ if (this.getters.tryGetSheet(cmd.sheetId)) {
68532
+ this.headerPositions[cmd.sheetId] = this.computeHeaderPositionsOfSheet(cmd.sheetId);
68533
+ }
68422
68534
  break;
68423
68535
  case "DUPLICATE_SHEET":
68424
68536
  this.headerPositions[cmd.sheetIdTo] = deepCopy(this.headerPositions[cmd.sheetId]);
@@ -68426,12 +68538,14 @@ class HeaderPositionsUIPlugin extends UIPlugin {
68426
68538
  }
68427
68539
  }
68428
68540
  finalize() {
68429
- if (this.isDirty) {
68430
- for (const sheetId of this.getters.getSheetIds()) {
68541
+ for (const sheetId of this.getters.getSheetIds()) {
68542
+ // sheets can be created without this plugin being aware of it
68543
+ // in concurrent situations.
68544
+ if (this.isDirty || !this.headerPositions[sheetId]) {
68431
68545
  this.headerPositions[sheetId] = this.computeHeaderPositionsOfSheet(sheetId);
68432
68546
  }
68433
- this.isDirty = false;
68434
68547
  }
68548
+ this.isDirty = false;
68435
68549
  }
68436
68550
  /**
68437
68551
  * Returns the size, start and end coordinates of a column on an unfolded sheet
@@ -70272,6 +70386,10 @@ const FX_SVG = /*xml*/ `
70272
70386
  </svg>
70273
70387
  `;
70274
70388
  css /* scss */ `
70389
+ .o-topbar-composer-container {
70390
+ height: ${TOPBAR_TOOLBAR_HEIGHT}px;
70391
+ }
70392
+
70275
70393
  .o-topbar-composer {
70276
70394
  height: fit-content;
70277
70395
  margin-top: -1px;
@@ -71835,9 +71953,16 @@ class SelectiveHistory {
71835
71953
  this.fastForward();
71836
71954
  this.insert(redoId, this.buildEmpty(redoId), insertAfter);
71837
71955
  }
71838
- drop(operationId) {
71956
+ rebase(operationId) {
71957
+ const operation = this.get(operationId);
71958
+ const execution = [...this.tree.execution(this.HEAD_BRANCH).startAfter(operationId)];
71839
71959
  this.revertBefore(operationId);
71960
+ const baseId = this.HEAD_OPERATION.id;
71840
71961
  this.tree.drop(operationId);
71962
+ this.insert(operationId, operation, baseId);
71963
+ for (const { operation } of execution) {
71964
+ this.insert(operation.id, operation.data, this.HEAD_OPERATION.id);
71965
+ }
71841
71966
  }
71842
71967
  /**
71843
71968
  * Revert the state as it was *before* the given operation was executed.
@@ -74965,6 +75090,11 @@ class Model extends EventBus {
74965
75090
  dispatch: (command) => {
74966
75091
  const result = this.checkDispatchAllowed(command);
74967
75092
  if (!result.isSuccessful) {
75093
+ // core views plugins need to be invalidated
75094
+ this.dispatchToHandlers(this.coreHandlers, {
75095
+ type: "UNDO",
75096
+ commands: [command],
75097
+ });
74968
75098
  return;
74969
75099
  }
74970
75100
  this.isReplayingCommand = true;
@@ -75486,6 +75616,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
75486
75616
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
75487
75617
 
75488
75618
 
75489
- __info__.version = "18.2.0-alpha.8";
75490
- __info__.date = "2025-02-14T08:40:13.286Z";
75491
- __info__.hash = "19d45d9";
75619
+ __info__.version = "18.2.1";
75620
+ __info__.date = "2025-02-25T06:03:13.262Z";
75621
+ __info__.hash = "3b4b5c9";