@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
  'use strict';
@@ -2231,17 +2231,7 @@ function toZoneWithoutBoundaryChanges(xc) {
2231
2231
  */
2232
2232
  function toUnboundedZone(xc) {
2233
2233
  const zone = toZoneWithoutBoundaryChanges(xc);
2234
- if (zone.right !== undefined && zone.right < zone.left) {
2235
- const tmp = zone.left;
2236
- zone.left = zone.right;
2237
- zone.right = tmp;
2238
- }
2239
- if (zone.bottom !== undefined && zone.bottom < zone.top) {
2240
- const tmp = zone.top;
2241
- zone.top = zone.bottom;
2242
- zone.bottom = tmp;
2243
- }
2244
- return zone;
2234
+ return reorderZone(zone);
2245
2235
  }
2246
2236
  /**
2247
2237
  * Convert from a cartesian reference to a Zone.
@@ -2515,11 +2505,11 @@ function positions(zone) {
2515
2505
  return positions;
2516
2506
  }
2517
2507
  function reorderZone(zone) {
2518
- if (zone.left > zone.right) {
2519
- zone = { left: zone.right, right: zone.left, top: zone.top, bottom: zone.bottom };
2508
+ if (zone.right !== undefined && zone.left > zone.right) {
2509
+ zone = { ...zone, left: zone.right, right: zone.left };
2520
2510
  }
2521
- if (zone.top > zone.bottom) {
2522
- zone = { left: zone.left, right: zone.right, top: zone.bottom, bottom: zone.top };
2511
+ if (zone.bottom !== undefined && zone.top > zone.bottom) {
2512
+ zone = { ...zone, top: zone.bottom, bottom: zone.top };
2523
2513
  }
2524
2514
  return zone;
2525
2515
  }
@@ -3424,12 +3414,12 @@ function isTargetDependent(cmd) {
3424
3414
  function isRangeDependant(cmd) {
3425
3415
  return "ranges" in cmd;
3426
3416
  }
3427
- function isZoneDependent(cmd) {
3428
- return "zone" in cmd;
3429
- }
3430
3417
  function isPositionDependent(cmd) {
3431
3418
  return "col" in cmd && "row" in cmd && "sheetId" in cmd;
3432
3419
  }
3420
+ function isZoneDependent(cmd) {
3421
+ return "sheetId" in cmd && "zone" in cmd;
3422
+ }
3433
3423
  const invalidateEvaluationCommands = new Set([
3434
3424
  "RENAME_SHEET",
3435
3425
  "DELETE_SHEET",
@@ -3441,6 +3431,7 @@ const invalidateEvaluationCommands = new Set([
3441
3431
  "REDO",
3442
3432
  "ADD_MERGE",
3443
3433
  "REMOVE_MERGE",
3434
+ "DUPLICATE_SHEET",
3444
3435
  "UPDATE_LOCALE",
3445
3436
  "ADD_PIVOT",
3446
3437
  "UPDATE_PIVOT",
@@ -3470,7 +3461,6 @@ const invalidateChartEvaluationCommands = new Set([
3470
3461
  ]);
3471
3462
  const invalidateDependenciesCommands = new Set(["MOVE_RANGES"]);
3472
3463
  const invalidateCFEvaluationCommands = new Set([
3473
- "DUPLICATE_SHEET",
3474
3464
  "EVALUATE_CELLS",
3475
3465
  "ADD_CONDITIONAL_FORMAT",
3476
3466
  "REMOVE_CONDITIONAL_FORMAT",
@@ -3640,6 +3630,7 @@ exports.CommandResult = void 0;
3640
3630
  CommandResult["InvalidRange"] = "InvalidRange";
3641
3631
  CommandResult["InvalidZones"] = "InvalidZones";
3642
3632
  CommandResult["InvalidSheetId"] = "InvalidSheetId";
3633
+ CommandResult["InvalidCellId"] = "InvalidCellId";
3643
3634
  CommandResult["InvalidFigureId"] = "InvalidFigureId";
3644
3635
  CommandResult["InputAlreadyFocused"] = "InputAlreadyFocused";
3645
3636
  CommandResult["MaximumRangesReached"] = "MaximumRangesReached";
@@ -4469,7 +4460,7 @@ function dichotomicSearch(data, target, mode, sortOrder, rangeLength, getValueIn
4469
4460
  * @param reverseSearch if true, search in the array starting from the end.
4470
4461
 
4471
4462
  */
4472
- function linearSearch(data, target, mode, numberOfValues, getValueInData, reverseSearch = false) {
4463
+ function linearSearch(data, target, mode, numberOfValues, getValueInData, lookupCaches, reverseSearch = false) {
4473
4464
  if (target === undefined || target.value === null) {
4474
4465
  return -1;
4475
4466
  }
@@ -4478,17 +4469,48 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
4478
4469
  }
4479
4470
  const _target = normalizeValue(target.value);
4480
4471
  const getValue = reverseSearch
4481
- ? (data, i) => getValueInData(data, numberOfValues - i - 1)
4482
- : getValueInData;
4472
+ ? (data, i) => normalizeValue(getValueInData(data, numberOfValues - i - 1))
4473
+ : (data, i) => normalizeValue(getValueInData(data, i));
4474
+ // first check if the target is in the cache
4475
+ const isNotWildcardTarget = mode !== "wildcard" ||
4476
+ typeof _target !== "string" ||
4477
+ !(_target.includes("*") || _target.includes("?"));
4478
+ if (lookupCaches && isNotWildcardTarget) {
4479
+ const searchMode = reverseSearch ? "reverseSearch" : "forwardSearch";
4480
+ let cache = lookupCaches[searchMode].get(data);
4481
+ if (cache === undefined) {
4482
+ // build the cache for all the values
4483
+ cache = new Map();
4484
+ for (let i = 0; i < numberOfValues; i++) {
4485
+ const value = getValue(data, i) ?? null;
4486
+ if (!cache.has(value)) {
4487
+ cache.set(value, i);
4488
+ }
4489
+ }
4490
+ lookupCaches[searchMode].set(data, cache);
4491
+ }
4492
+ if (cache.has(_target)) {
4493
+ const resultIndex = cache.get(_target);
4494
+ return reverseSearch ? numberOfValues - resultIndex - 1 : resultIndex;
4495
+ }
4496
+ if (mode === "strict") {
4497
+ return -1;
4498
+ }
4499
+ }
4500
+ // else perform the linear search
4501
+ const resultIndex = _linearSearch(data, _target, mode, numberOfValues, getValue);
4502
+ return reverseSearch && resultIndex !== -1 ? numberOfValues - resultIndex - 1 : resultIndex;
4503
+ }
4504
+ function _linearSearch(data, _target, mode, numberOfValues, getNormalizeValue) {
4483
4505
  let indexMatchTarget = (i) => {
4484
- return normalizeValue(getValue(data, i)) === _target;
4506
+ return getNormalizeValue(data, i) === _target;
4485
4507
  };
4486
4508
  if (mode === "wildcard" &&
4487
4509
  typeof _target === "string" &&
4488
4510
  (_target.includes("*") || _target.includes("?"))) {
4489
4511
  const regExp = wildcardToRegExp(_target);
4490
4512
  indexMatchTarget = (i) => {
4491
- const value = normalizeValue(getValue(data, i));
4513
+ const value = getNormalizeValue(data, i);
4492
4514
  if (typeof value === "string") {
4493
4515
  return regExp.test(value);
4494
4516
  }
@@ -4499,7 +4521,7 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
4499
4521
  let closestMatchIndex = -1;
4500
4522
  if (mode === "nextSmaller") {
4501
4523
  indexMatchTarget = (i) => {
4502
- const value = normalizeValue(getValue(data, i));
4524
+ const value = getNormalizeValue(data, i);
4503
4525
  if ((!closestMatch && compareCellValues(_target, value) >= 0) ||
4504
4526
  (compareCellValues(_target, value) >= 0 && compareCellValues(value, closestMatch) > 0)) {
4505
4527
  closestMatch = value;
@@ -4510,7 +4532,7 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
4510
4532
  }
4511
4533
  if (mode === "nextGreater") {
4512
4534
  indexMatchTarget = (i) => {
4513
- const value = normalizeValue(getValue(data, i));
4535
+ const value = getNormalizeValue(data, i);
4514
4536
  if ((!closestMatch && compareCellValues(_target, value) <= 0) ||
4515
4537
  (compareCellValues(_target, value) <= 0 && compareCellValues(value, closestMatch) < 0)) {
4516
4538
  closestMatch = value;
@@ -4521,12 +4543,10 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
4521
4543
  }
4522
4544
  for (let i = 0; i < numberOfValues; i++) {
4523
4545
  if (indexMatchTarget(i)) {
4524
- return reverseSearch ? numberOfValues - i - 1 : i;
4546
+ return i;
4525
4547
  }
4526
4548
  }
4527
- return reverseSearch && closestMatchIndex !== -1
4528
- ? numberOfValues - closestMatchIndex - 1
4529
- : closestMatchIndex;
4549
+ return closestMatchIndex;
4530
4550
  }
4531
4551
  /**
4532
4552
  * Normalize a value.
@@ -6500,10 +6520,11 @@ class UuidGenerator {
6500
6520
  *
6501
6521
  */
6502
6522
  smallUuid() {
6503
- //@ts-ignore
6504
- if (window.crypto && window.crypto.getRandomValues) {
6505
- //@ts-ignore
6506
- return ([1e7] + -1e3).replace(/[018]/g, (c) => (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16));
6523
+ if (window.crypto) {
6524
+ return "10000000-1000".replace(/[01]/g, (c) => {
6525
+ const n = Number(c);
6526
+ return (n ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (n / 4)))).toString(16);
6527
+ });
6507
6528
  }
6508
6529
  else {
6509
6530
  // mainly for jest and other browsers that do not have the crypto functionality
@@ -6518,10 +6539,11 @@ class UuidGenerator {
6518
6539
  * This method should be used when you need to avoid collisions at all costs, like the id of a revision.
6519
6540
  */
6520
6541
  uuidv4() {
6521
- //@ts-ignore
6522
- if (window.crypto && window.crypto.getRandomValues) {
6523
- //@ts-ignore
6524
- return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16));
6542
+ if (window.crypto) {
6543
+ return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c) => {
6544
+ const n = Number(c);
6545
+ return (n ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (n / 4)))).toString(16);
6546
+ });
6525
6547
  }
6526
6548
  else {
6527
6549
  // mainly for jest and other browsers that do not have the crypto functionality
@@ -12238,6 +12260,25 @@ const LN = {
12238
12260
  isExported: true,
12239
12261
  };
12240
12262
  // -----------------------------------------------------------------------------
12263
+ // LOG
12264
+ // -----------------------------------------------------------------------------
12265
+ const LOG = {
12266
+ description: _t("The logarithm of a number, for a given base."),
12267
+ args: [
12268
+ arg("value (number)", _t("The value for which to calculate the logarithm.")),
12269
+ arg("base (number, default=10)", _t("The base of the logarithm.")),
12270
+ ],
12271
+ compute: function (value, base = { value: 10 }) {
12272
+ const _value = toNumber(value, this.locale);
12273
+ const _base = toNumber(base, this.locale);
12274
+ assert(() => _value > 0, _t("The value (%s) must be strictly positive.", _value.toString()));
12275
+ assert(() => _base > 0, _t("The base (%s) must be strictly positive.", _base.toString()));
12276
+ assert(() => _base !== 1, _t("The base must be different from 1."));
12277
+ return Math.log10(_value) / Math.log10(_base);
12278
+ },
12279
+ isExported: true,
12280
+ };
12281
+ // -----------------------------------------------------------------------------
12241
12282
  // MOD
12242
12283
  // -----------------------------------------------------------------------------
12243
12284
  function mod(dividend, divisor) {
@@ -12777,6 +12818,7 @@ var math = /*#__PURE__*/Object.freeze({
12777
12818
  ISODD: ISODD,
12778
12819
  ISO_CEILING: ISO_CEILING,
12779
12820
  LN: LN,
12821
+ LOG: LOG,
12780
12822
  MOD: MOD,
12781
12823
  MUNIT: MUNIT,
12782
12824
  ODD: ODD,
@@ -18675,7 +18717,7 @@ const HLOOKUP = {
18675
18717
  const _isSorted = toBoolean(isSorted.value);
18676
18718
  const colIndex = _isSorted
18677
18719
  ? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range.length, getValueFromRange)
18678
- : linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange);
18720
+ : linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange, this.lookupCaches);
18679
18721
  const col = _range[colIndex];
18680
18722
  if (col === undefined) {
18681
18723
  return valueNotAvailable(searchKey);
@@ -18830,7 +18872,7 @@ const MATCH = {
18830
18872
  index = dichotomicSearch(_range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
18831
18873
  break;
18832
18874
  case 0:
18833
- index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement);
18875
+ index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement, this.lookupCaches);
18834
18876
  break;
18835
18877
  case -1:
18836
18878
  index = dichotomicSearch(_range, searchKey, "nextGreater", "desc", rangeLen, getElement);
@@ -18898,7 +18940,7 @@ const VLOOKUP = {
18898
18940
  const _isSorted = toBoolean(isSorted.value);
18899
18941
  const rowIndex = _isSorted
18900
18942
  ? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range[0].length, getValueFromRange)
18901
- : linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange);
18943
+ : linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange, this.lookupCaches);
18902
18944
  const value = _range[_index - 1][rowIndex];
18903
18945
  if (value === undefined) {
18904
18946
  return valueNotAvailable(searchKey);
@@ -18954,7 +18996,7 @@ const XLOOKUP = {
18954
18996
  const reverseSearch = _searchMode === -1;
18955
18997
  const index = _searchMode === 2 || _searchMode === -2
18956
18998
  ? dichotomicSearch(_lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
18957
- : linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, reverseSearch);
18999
+ : linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, this.lookupCaches, reverseSearch);
18958
19000
  if (index !== -1) {
18959
19001
  return lookupDirection === "col"
18960
19002
  ? _returnRange.map((col) => [col[index]])
@@ -28293,7 +28335,7 @@ function getBarChartData(definition, dataSets, labelRange, getters) {
28293
28335
  }
28294
28336
  function getPyramidChartData(definition, dataSets, labelRange, getters) {
28295
28337
  const barChartData = getBarChartData(definition, dataSets, labelRange, getters);
28296
- const barDataset = barChartData.dataSetsValues;
28338
+ const barDataset = barChartData.dataSetsValues.filter((ds) => !ds.hidden);
28297
28339
  const pyramidDatasetValues = [];
28298
28340
  if (barDataset[0]) {
28299
28341
  const pyramidData = barDataset[0].data.map((value) => (value > 0 ? value : 0));
@@ -28770,10 +28812,8 @@ function getChartDatasetFormat(getters, allDataSets, axis) {
28770
28812
  function getChartDatasetValues(getters, dataSets) {
28771
28813
  const datasetValues = [];
28772
28814
  for (const [dsIndex, ds] of Object.entries(dataSets)) {
28773
- if (getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left)) {
28774
- continue;
28775
- }
28776
28815
  let label;
28816
+ let hidden = getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left);
28777
28817
  if (ds.labelCell) {
28778
28818
  const labelRange = ds.labelCell;
28779
28819
  const cell = labelRange
@@ -28800,9 +28840,9 @@ function getChartDatasetValues(getters, dataSets) {
28800
28840
  data.fill(1);
28801
28841
  }
28802
28842
  else if (data.every((cell) => cell === undefined || cell === null || !isNumber(cell.toString(), DEFAULT_LOCALE))) {
28803
- continue;
28843
+ hidden = true;
28804
28844
  }
28805
- datasetValues.push({ data, label });
28845
+ datasetValues.push({ data, label, hidden });
28806
28846
  }
28807
28847
  return datasetValues;
28808
28848
  }
@@ -28813,12 +28853,13 @@ function getBarChartDatasets(definition, args) {
28813
28853
  const colors = getChartColorsGenerator(definition, dataSetsValues.length);
28814
28854
  const trendDatasets = [];
28815
28855
  for (const index in dataSetsValues) {
28816
- let { label, data } = dataSetsValues[index];
28856
+ let { label, data, hidden } = dataSetsValues[index];
28817
28857
  label = definition.dataSets?.[index].label || label;
28818
28858
  const backgroundColor = colors.next();
28819
28859
  const dataset = {
28820
28860
  label,
28821
28861
  data,
28862
+ hidden,
28822
28863
  borderColor: definition.background || BACKGROUND_CHART_COLOR,
28823
28864
  borderWidth: definition.stacked ? 1 : 0,
28824
28865
  backgroundColor,
@@ -28851,6 +28892,9 @@ function getWaterfallDatasetAndLabels(definition, args) {
28851
28892
  const labelsWithSubTotals = [];
28852
28893
  let lastValue = 0;
28853
28894
  for (const dataSetsValue of dataSetsValues) {
28895
+ if (dataSetsValue.hidden) {
28896
+ continue;
28897
+ }
28854
28898
  for (let i = 0; i < dataSetsValue.data.length; i++) {
28855
28899
  const data = dataSetsValue.data[i];
28856
28900
  labelsWithSubTotals.push(labels[i]);
@@ -28886,7 +28930,7 @@ function getLineChartDatasets(definition, args) {
28886
28930
  const trendDatasets = [];
28887
28931
  const colors = getChartColorsGenerator(definition, dataSetsValues.length);
28888
28932
  for (let index = 0; index < dataSetsValues.length; index++) {
28889
- let { label, data } = dataSetsValues[index];
28933
+ let { label, data, hidden } = dataSetsValues[index];
28890
28934
  label = definition.dataSets?.[index].label || label;
28891
28935
  const color = colors.next();
28892
28936
  if (axisType && ["linear", "time"].includes(axisType)) {
@@ -28896,6 +28940,7 @@ function getLineChartDatasets(definition, args) {
28896
28940
  const dataset = {
28897
28941
  label,
28898
28942
  data,
28943
+ hidden,
28899
28944
  tension: 0, // 0 -> render straight lines, which is much faster
28900
28945
  borderColor: color,
28901
28946
  backgroundColor: areaChart ? setColorAlpha(color, LINE_FILL_TRANSPARENCY) : color,
@@ -28928,11 +28973,13 @@ function getPieChartDatasets(definition, args) {
28928
28973
  const dataSets = [];
28929
28974
  const dataSetsLength = Math.max(0, ...dataSetsValues.map((ds) => ds?.data?.length ?? 0));
28930
28975
  const backgroundColor = getPieColors(new ColorGenerator(dataSetsLength), dataSetsValues);
28931
- for (const { label, data } of dataSetsValues) {
28976
+ for (const { label, data, hidden } of dataSetsValues) {
28977
+ if (hidden)
28978
+ continue;
28932
28979
  const dataset = {
28933
28980
  label,
28934
28981
  data,
28935
- borderColor: BACKGROUND_CHART_COLOR,
28982
+ borderColor: definition.background || "#FFFFFF",
28936
28983
  backgroundColor,
28937
28984
  hoverOffset: 30,
28938
28985
  };
@@ -28946,7 +28993,7 @@ function getComboChartDatasets(definition, args) {
28946
28993
  const colors = getChartColorsGenerator(definition, dataSetsValues.length);
28947
28994
  const trendDatasets = [];
28948
28995
  for (let index = 0; index < dataSetsValues.length; index++) {
28949
- let { label, data } = dataSetsValues[index];
28996
+ let { label, data, hidden } = dataSetsValues[index];
28950
28997
  label = definition.dataSets?.[index].label || label;
28951
28998
  const design = definition.dataSets?.[index];
28952
28999
  const color = colors.next();
@@ -28954,6 +29001,7 @@ function getComboChartDatasets(definition, args) {
28954
29001
  const dataset = {
28955
29002
  label: label,
28956
29003
  data,
29004
+ hidden,
28957
29005
  borderColor: color,
28958
29006
  backgroundColor: color,
28959
29007
  yAxisID: definition.dataSets?.[index].yAxisId || "y",
@@ -28978,7 +29026,7 @@ function getRadarChartDatasets(definition, args) {
28978
29026
  const fill = definition.fillArea ?? false;
28979
29027
  const colors = getChartColorsGenerator(definition, dataSetsValues.length);
28980
29028
  for (let i = 0; i < dataSetsValues.length; i++) {
28981
- let { label, data } = dataSetsValues[i];
29029
+ let { label, data, hidden } = dataSetsValues[i];
28982
29030
  if (definition.dataSets?.[i]?.label) {
28983
29031
  label = definition.dataSets[i].label;
28984
29032
  }
@@ -28986,6 +29034,7 @@ function getRadarChartDatasets(definition, args) {
28986
29034
  const dataset = {
28987
29035
  label,
28988
29036
  data,
29037
+ hidden,
28989
29038
  borderColor,
28990
29039
  backgroundColor: borderColor,
28991
29040
  };
@@ -29131,6 +29180,11 @@ function getPieChartLegend(definition, args) {
29131
29180
  hidden: false,
29132
29181
  lineWidth: 2,
29133
29182
  })),
29183
+ filter: (legendItem, data) => {
29184
+ return "datasetIndex" in legendItem
29185
+ ? !data.datasets[legendItem.datasetIndex].hidden
29186
+ : true;
29187
+ },
29134
29188
  },
29135
29189
  };
29136
29190
  }
@@ -29192,6 +29246,11 @@ function getWaterfallChartLegend(definition, args) {
29192
29246
  }
29193
29247
  return legendValues;
29194
29248
  },
29249
+ filter: (legendItem, data) => {
29250
+ return "datasetIndex" in legendItem
29251
+ ? !data.datasets[legendItem.datasetIndex].hidden
29252
+ : true;
29253
+ },
29195
29254
  },
29196
29255
  onClick: () => { }, // Disables click interaction with the waterfall chart legend items
29197
29256
  };
@@ -29275,6 +29334,11 @@ function getCustomLegendLabels(fontColor, legendLabelConfig) {
29275
29334
  ...legendLabelConfig,
29276
29335
  };
29277
29336
  }),
29337
+ filter: (legendItem, data) => {
29338
+ return "datasetIndex" in legendItem
29339
+ ? !data.datasets[legendItem.datasetIndex].hidden
29340
+ : true;
29341
+ },
29278
29342
  },
29279
29343
  };
29280
29344
  }
@@ -29608,7 +29672,7 @@ const templates = /* xml */ `
29608
29672
  <div
29609
29673
  class="o-chart-custom-tooltip border rounded px-2 py-1 pe-none mw-100 position-absolute text-nowrap shadow opacity-100">
29610
29674
  <table class="overflow-hidden m-0">
29611
- <thead>
29675
+ <thead t-if="title">
29612
29676
  <tr>
29613
29677
  <th class="o-tooltip-title align-baseline border-0 text-truncate" t-esc="title" t-attf-style="max-width: {{ labelsMaxWidth }}"/>
29614
29678
  </tr>
@@ -29669,8 +29733,8 @@ function getBarChartTooltip(definition, args) {
29669
29733
  ? undefined
29670
29734
  : "";
29671
29735
  },
29736
+ beforeLabel: (tooltipItem) => tooltipItem.dataset?.label || tooltipItem.label,
29672
29737
  label: function (tooltipItem) {
29673
- const xLabel = tooltipItem.dataset?.label || tooltipItem.label;
29674
29738
  const horizontalChart = definition.horizontal;
29675
29739
  let yLabel = horizontalChart ? tooltipItem.parsed.x : tooltipItem.parsed.y;
29676
29740
  if (yLabel === undefined || yLabel === null) {
@@ -29678,7 +29742,7 @@ function getBarChartTooltip(definition, args) {
29678
29742
  }
29679
29743
  const axisId = horizontalChart ? tooltipItem.dataset.xAxisID : tooltipItem.dataset.yAxisID;
29680
29744
  const yLabelStr = formatChartDatasetValue(args.axisFormats, args.locale)(yLabel, axisId);
29681
- return xLabel ? `${xLabel}: ${yLabelStr}` : yLabelStr;
29745
+ return yLabelStr;
29682
29746
  },
29683
29747
  },
29684
29748
  };
@@ -29703,21 +29767,18 @@ function getLineChartTooltip(definition, args) {
29703
29767
  const formattedX = formatValue(label, { locale, format: labelFormat });
29704
29768
  const axisId = tooltipItem.dataset.yAxisID || "y";
29705
29769
  const formattedY = formatValue(dataSetPoint, { locale, format: axisFormats?.[axisId] });
29706
- const dataSetTitle = tooltipItem.dataset.label;
29707
- return formattedX
29708
- ? `${dataSetTitle}: (${formattedX}, ${formattedY})`
29709
- : `${dataSetTitle}: ${formattedY}`;
29770
+ return formattedX ? `(${formattedX}, ${formattedY})` : `${formattedY}`;
29710
29771
  };
29711
29772
  }
29712
29773
  else {
29713
29774
  tooltip.callbacks.label = function (tooltipItem) {
29714
- const xLabel = tooltipItem.dataset?.label || tooltipItem.label;
29715
29775
  const yLabel = tooltipItem.parsed.y;
29716
29776
  const axisId = tooltipItem.dataset.yAxisID;
29717
29777
  const yLabelStr = formatChartDatasetValue(axisFormats, locale)(yLabel, axisId);
29718
- return xLabel ? `${xLabel}: ${yLabelStr}` : yLabelStr;
29778
+ return yLabelStr;
29719
29779
  };
29720
29780
  }
29781
+ tooltip.callbacks.beforeLabel = (tooltipItem) => tooltipItem.dataset?.label || tooltipItem.label;
29721
29782
  tooltip.callbacks.title = function (tooltipItems) {
29722
29783
  const displayTooltipTitle = axisType !== "linear" &&
29723
29784
  tooltipItems.some((item) => item.dataset.xAxisID !== TREND_LINE_XAXIS_ID);
@@ -29735,17 +29796,15 @@ function getPieChartTooltip(definition, args) {
29735
29796
  title: function (tooltipItems) {
29736
29797
  return tooltipItems[0].dataset.label;
29737
29798
  },
29799
+ beforeLabel: (tooltipItem) => tooltipItem.label || tooltipItem.dataset.label,
29738
29800
  label: function (tooltipItem) {
29739
29801
  const data = tooltipItem.dataset.data;
29740
29802
  const dataIndex = tooltipItem.dataIndex;
29741
29803
  const percentage = calculatePercentage(data, dataIndex);
29742
- const xLabel = tooltipItem.label || tooltipItem.dataset.label;
29743
29804
  const yLabel = tooltipItem.parsed.y ?? tooltipItem.parsed;
29744
29805
  const toolTipFormat = !format && yLabel >= 1000 ? "#,##" : format;
29745
29806
  const yLabelStr = formatValue(yLabel, { format: toolTipFormat, locale });
29746
- return xLabel
29747
- ? `${xLabel}: ${yLabelStr} (${percentage}%)`
29748
- : `${yLabelStr} (${percentage}%)`;
29807
+ return `${yLabelStr} (${percentage}%)`;
29749
29808
  },
29750
29809
  },
29751
29810
  };
@@ -29758,16 +29817,17 @@ function getWaterfallChartTooltip(definition, args) {
29758
29817
  enabled: false,
29759
29818
  external: customTooltipHandler,
29760
29819
  callbacks: {
29761
- label: function (tooltipItem) {
29762
- const [lastValue, currentValue] = tooltipItem.raw;
29763
- const yLabel = currentValue - lastValue;
29820
+ beforeLabel: function (tooltipItem) {
29764
29821
  const dataSeriesIndex = labels.length
29765
29822
  ? Math.floor(tooltipItem.dataIndex / labels.length)
29766
29823
  : 0;
29767
- const dataSeriesLabel = dataSeriesLabels[dataSeriesIndex];
29824
+ return dataSeriesLabels[dataSeriesIndex];
29825
+ },
29826
+ label: function (tooltipItem) {
29827
+ const [lastValue, currentValue] = tooltipItem.raw;
29828
+ const yLabel = currentValue - lastValue;
29768
29829
  const toolTipFormat = !format && Math.abs(yLabel) > 1000 ? "#,##" : format;
29769
- const yLabelStr = formatValue(yLabel, { format: toolTipFormat, locale });
29770
- return dataSeriesLabel ? `${dataSeriesLabel}: ${yLabelStr}` : yLabelStr;
29830
+ return formatValue(yLabel, { format: toolTipFormat, locale });
29771
29831
  },
29772
29832
  },
29773
29833
  };
@@ -29791,11 +29851,10 @@ function getRadarChartTooltip(definition, args) {
29791
29851
  enabled: false,
29792
29852
  external: customTooltipHandler,
29793
29853
  callbacks: {
29854
+ beforeLabel: (tooltipItem) => tooltipItem.dataset?.label || tooltipItem.label,
29794
29855
  label: function (tooltipItem) {
29795
- const xLabel = tooltipItem.dataset?.label || tooltipItem.label;
29796
29856
  const yLabel = tooltipItem.parsed.r;
29797
- const formattedY = formatValue(yLabel, { format: axisFormats?.r, locale });
29798
- return xLabel ? `${xLabel}: ${formattedY}` : formattedY;
29857
+ return formatValue(yLabel, { format: axisFormats?.r, locale });
29799
29858
  },
29800
29859
  },
29801
29860
  };
@@ -29810,13 +29869,12 @@ function getGeoChartTooltip(definition, args) {
29810
29869
  return tooltipItem.raw.value !== undefined;
29811
29870
  },
29812
29871
  callbacks: {
29872
+ beforeLabel: (tooltipItem) => tooltipItem.raw.feature.properties.name,
29813
29873
  label: function (tooltipItem) {
29814
29874
  const rawItem = tooltipItem.raw;
29815
- const xLabel = rawItem.feature.properties.name;
29816
29875
  const yLabel = rawItem.value;
29817
29876
  const toolTipFormat = !format && Math.abs(yLabel) >= 1000 ? "#,##" : format;
29818
- const yLabelStr = formatValue(yLabel, { format: toolTipFormat, locale });
29819
- return xLabel ? `${xLabel}: ${yLabelStr}` : yLabelStr;
29877
+ return formatValue(yLabel, { format: toolTipFormat, locale });
29820
29878
  },
29821
29879
  },
29822
29880
  };
@@ -29836,7 +29894,8 @@ function customTooltipHandler({ chart, tooltip }) {
29836
29894
  return;
29837
29895
  }
29838
29896
  const tooltipItems = tooltip.body.map((body, index) => {
29839
- let [label, value] = body.lines[0].split(":").map((str) => str.trim());
29897
+ let label = body.before[0];
29898
+ let value = body.lines[0];
29840
29899
  if (!value) {
29841
29900
  value = label;
29842
29901
  label = "";
@@ -38920,7 +38979,7 @@ css /* scss */ `
38920
38979
  .o-font-size-editor {
38921
38980
  height: calc(100% - 4px);
38922
38981
  input.o-font-size {
38923
- outline-color: ${SELECTION_BORDER_COLOR};
38982
+ outline: none;
38924
38983
  height: 20px;
38925
38984
  width: 23px;
38926
38985
  }
@@ -51628,8 +51687,8 @@ class Border extends owl.Component {
51628
51687
  css /* scss */ `
51629
51688
  .o-corner {
51630
51689
  position: absolute;
51631
- height: 6px;
51632
- width: 6px;
51690
+ height: 8px;
51691
+ width: 8px;
51633
51692
  border: 1px solid white;
51634
51693
  }
51635
51694
  .o-corner-nw,
@@ -53466,6 +53525,10 @@ class CellPlugin extends CorePlugin {
53466
53525
  return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessUpdateCell);
53467
53526
  case "CLEAR_CELL":
53468
53527
  return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessClearCell);
53528
+ case "UPDATE_CELL_POSITION":
53529
+ return !cmd.cellId || this.cells[cmd.sheetId]?.[cmd.cellId]
53530
+ ? "Success" /* CommandResult.Success */
53531
+ : "InvalidCellId" /* CommandResult.InvalidCellId */;
53469
53532
  default:
53470
53533
  return "Success" /* CommandResult.Success */;
53471
53534
  }
@@ -53510,6 +53573,9 @@ class CellPlugin extends CorePlugin {
53510
53573
  case "DELETE_CONTENT":
53511
53574
  this.clearZones(cmd.sheetId, cmd.target);
53512
53575
  break;
53576
+ case "DELETE_SHEET": {
53577
+ this.history.update("cells", cmd.sheetId, undefined);
53578
+ }
53513
53579
  }
53514
53580
  }
53515
53581
  clearZones(sheetId, zones) {
@@ -54300,6 +54366,9 @@ class ConditionalFormatPlugin extends CorePlugin {
54300
54366
  allowDispatch(cmd) {
54301
54367
  switch (cmd.type) {
54302
54368
  case "ADD_CONDITIONAL_FORMAT":
54369
+ if (cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId))) {
54370
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
54371
+ }
54303
54372
  return this.checkValidations(cmd, this.checkCFRule, this.checkEmptyRange, this.checkCFHasChanged);
54304
54373
  case "CHANGE_CONDITIONAL_FORMAT_PRIORITY":
54305
54374
  return this.checkValidPriorityChange(cmd.cfId, cmd.delta, cmd.sheetId);
@@ -54716,8 +54785,17 @@ class DataValidationPlugin extends CorePlugin {
54716
54785
  allowDispatch(cmd) {
54717
54786
  switch (cmd.type) {
54718
54787
  case "ADD_DATA_VALIDATION_RULE":
54788
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
54789
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
54790
+ }
54791
+ if (cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId))) {
54792
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
54793
+ }
54719
54794
  return this.checkValidations(cmd, this.chainValidations(this.checkEmptyRange, this.checkValidRange, this.checkCriterionTypeIsValid, this.checkCriterionHasValidNumberOfValues, this.checkCriterionValuesAreValid));
54720
54795
  case "REMOVE_DATA_VALIDATION_RULE":
54796
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
54797
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
54798
+ }
54721
54799
  if (!this.rules[cmd.sheetId].find((rule) => rule.id === cmd.id)) {
54722
54800
  return "UnknownDataValidationRule" /* CommandResult.UnknownDataValidationRule */;
54723
54801
  }
@@ -54944,6 +55022,7 @@ class DataValidationPlugin extends CorePlugin {
54944
55022
  class FigurePlugin extends CorePlugin {
54945
55023
  static getters = ["getFigures", "getFigure", "getFigureSheetId"];
54946
55024
  figures = {};
55025
+ insertionOrders = []; // TODO use a list in master
54947
55026
  // ---------------------------------------------------------------------------
54948
55027
  // Command Handling
54949
55028
  // ---------------------------------------------------------------------------
@@ -55046,11 +55125,14 @@ class FigurePlugin extends CorePlugin {
55046
55125
  }
55047
55126
  addFigure(figure, sheetId) {
55048
55127
  this.history.update("figures", sheetId, figure.id, figure);
55128
+ this.history.update("insertionOrders", this.insertionOrders.length, figure.id);
55049
55129
  }
55050
55130
  deleteSheet(sheetId) {
55131
+ this.history.update("insertionOrders", this.insertionOrders.filter((id) => !this.figures[sheetId]?.[id]));
55051
55132
  this.history.update("figures", sheetId, undefined);
55052
55133
  }
55053
55134
  removeFigure(id, sheetId) {
55135
+ this.history.update("insertionOrders", this.insertionOrders.filter((figureId) => figureId !== id));
55054
55136
  this.history.update("figures", sheetId, id, undefined);
55055
55137
  }
55056
55138
  checkFigureExists(sheetId, figureId) {
@@ -55069,7 +55151,14 @@ class FigurePlugin extends CorePlugin {
55069
55151
  // Getters
55070
55152
  // ---------------------------------------------------------------------------
55071
55153
  getFigures(sheetId) {
55072
- return Object.values(this.figures[sheetId] || {}).filter(isDefined);
55154
+ const figures = [];
55155
+ for (const figureId of this.insertionOrders) {
55156
+ const figure = this.figures[sheetId]?.[figureId];
55157
+ if (figure) {
55158
+ figures.push(figure);
55159
+ }
55160
+ }
55161
+ return figures;
55073
55162
  }
55074
55163
  getFigure(sheetId, figureId) {
55075
55164
  return this.figures[sheetId]?.[figureId];
@@ -55082,11 +55171,9 @@ class FigurePlugin extends CorePlugin {
55082
55171
  // ---------------------------------------------------------------------------
55083
55172
  import(data) {
55084
55173
  for (let sheet of data.sheets) {
55085
- const figures = {};
55086
- sheet.figures.forEach((figure) => {
55087
- figures[figure.id] = figure;
55088
- });
55089
- this.figures[sheet.id] = figures;
55174
+ for (const figure of sheet.figures) {
55175
+ this.addFigure(figure, sheet.id);
55176
+ }
55090
55177
  }
55091
55178
  }
55092
55179
  export(data) {
@@ -56546,6 +56633,9 @@ class SheetPlugin extends CorePlugin {
56546
56633
  case "CREATE_SHEET": {
56547
56634
  return this.checkValidations(cmd, this.checkSheetName, this.checkSheetPosition);
56548
56635
  }
56636
+ case "DUPLICATE_SHEET": {
56637
+ return this.sheets[cmd.sheetIdTo] ? "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */ : "Success" /* CommandResult.Success */;
56638
+ }
56549
56639
  case "MOVE_SHEET":
56550
56640
  try {
56551
56641
  const currentIndex = this.orderedSheetIds.findIndex((id) => id === cmd.sheetId);
@@ -57348,14 +57438,18 @@ class SheetPlugin extends CorePlugin {
57348
57438
  checkZonesAreInSheet(cmd) {
57349
57439
  if (!("sheetId" in cmd))
57350
57440
  return "Success" /* CommandResult.Success */;
57441
+ if ("ranges" in cmd &&
57442
+ cmd.ranges.some((rangeData) => rangeData._sheetId !== "" && !this.getters.tryGetSheet(rangeData._sheetId))) {
57443
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
57444
+ }
57351
57445
  return this.checkZonesExistInSheet(cmd.sheetId, this.getCommandZones(cmd));
57352
57446
  }
57353
57447
  }
57354
57448
 
57355
- let nextTableId = 1;
57356
57449
  class TablePlugin extends CorePlugin {
57357
57450
  static getters = ["getCoreTable", "getCoreTables", "getCoreTableMatchingTopLeft"];
57358
57451
  tables = {};
57452
+ nextTableId = 1;
57359
57453
  adaptRanges(applyChange, sheetId) {
57360
57454
  const sheetIds = sheetId ? [sheetId] : this.getters.getSheetIds();
57361
57455
  for (const sheetId of sheetIds) {
@@ -57367,6 +57461,9 @@ class TablePlugin extends CorePlugin {
57367
57461
  allowDispatch(cmd) {
57368
57462
  switch (cmd.type) {
57369
57463
  case "CREATE_TABLE":
57464
+ if (cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId) || rangeData._sheetId !== cmd.sheetId)) {
57465
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
57466
+ }
57370
57467
  const zones = cmd.ranges.map((rangeData) => this.getters.getRangeFromRangeData(rangeData).zone);
57371
57468
  if (!areZonesContinuous(zones)) {
57372
57469
  return "NonContinuousTargets" /* CommandResult.NonContinuousTargets */;
@@ -57420,7 +57517,7 @@ class TablePlugin extends CorePlugin {
57420
57517
  const union = this.getters.getRangesUnion(ranges);
57421
57518
  const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, union.zone);
57422
57519
  this.dispatch("REMOVE_MERGE", { sheetId: cmd.sheetId, target: mergesInTarget });
57423
- const id = `${nextTableId++}`;
57520
+ const id = this.consumeNextId();
57424
57521
  const config = cmd.config || DEFAULT_TABLE_CONFIG;
57425
57522
  const newTable = cmd.tableType === "dynamic"
57426
57523
  ? this.createDynamicTable(id, union, config)
@@ -57573,7 +57670,7 @@ class TablePlugin extends CorePlugin {
57573
57670
  filters = [];
57574
57671
  for (const i of range(zone.left, zone.right + 1)) {
57575
57672
  const filterZone = { ...zone, left: i, right: i };
57576
- const uid = `${nextTableId++}`;
57673
+ const uid = this.consumeNextId();
57577
57674
  filters.push(this.createFilterFromZone(uid, tableRange.sheetId, filterZone, config));
57578
57675
  }
57579
57676
  }
@@ -57638,7 +57735,7 @@ class TablePlugin extends CorePlugin {
57638
57735
  ? table.filters.find((f) => f.col === i)
57639
57736
  : undefined;
57640
57737
  const filterZone = { ...tableZone, left: i, right: i };
57641
- const filterId = oldFilter?.id || `${nextTableId++}`;
57738
+ const filterId = oldFilter?.id || this.consumeNextId();
57642
57739
  filters.push(this.createFilterFromZone(filterId, tableRange.sheetId, filterZone, config));
57643
57740
  }
57644
57741
  }
@@ -57739,7 +57836,7 @@ class TablePlugin extends CorePlugin {
57739
57836
  if (filters.length < zoneToDimension(tableZone).numberOfCols) {
57740
57837
  for (let col = tableZone.left; col <= tableZone.right; col++) {
57741
57838
  if (!filters.find((filter) => filter.col === col)) {
57742
- const uid = `${nextTableId++}`;
57839
+ const uid = this.consumeNextId();
57743
57840
  const filterZone = { ...tableZone, left: col, right: col };
57744
57841
  filters.push(this.createFilterFromZone(uid, sheetId, filterZone, table.config));
57745
57842
  }
@@ -57749,13 +57846,18 @@ class TablePlugin extends CorePlugin {
57749
57846
  const newTable = this.createStaticTable(table.id, table.type, newTableRange, table.config, filters);
57750
57847
  this.history.update("tables", sheetId, table.id, newTable);
57751
57848
  }
57849
+ consumeNextId() {
57850
+ const id = `${this.nextTableId}`;
57851
+ this.history.update("nextTableId", this.nextTableId + 1);
57852
+ return id;
57853
+ }
57752
57854
  // ---------------------------------------------------------------------------
57753
57855
  // Import/Export
57754
57856
  // ---------------------------------------------------------------------------
57755
57857
  import(data) {
57756
57858
  for (const sheet of data.sheets) {
57757
57859
  for (const tableData of sheet.tables || []) {
57758
- const uuid = `${nextTableId++}`;
57860
+ const uuid = this.consumeNextId();
57759
57861
  const tableConfig = tableData.config || DEFAULT_TABLE_CONFIG;
57760
57862
  const range = this.getters.getRangeFromSheetXC(sheet.id, tableData.range);
57761
57863
  const tableType = tableData.type || "static";
@@ -57803,7 +57905,10 @@ class HeaderGroupingPlugin extends CorePlugin {
57803
57905
  allowDispatch(cmd) {
57804
57906
  switch (cmd.type) {
57805
57907
  case "GROUP_HEADERS": {
57806
- const { start, end } = cmd;
57908
+ const { start, end, sheetId } = cmd;
57909
+ if (!this.getters.tryGetSheet(sheetId)) {
57910
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
57911
+ }
57807
57912
  if (!this.getters.doesHeadersExist(cmd.sheetId, cmd.dimension, [start, end])) {
57808
57913
  return "InvalidHeaderGroupStartEnd" /* CommandResult.InvalidHeaderGroupStartEnd */;
57809
57914
  }
@@ -57816,7 +57921,10 @@ class HeaderGroupingPlugin extends CorePlugin {
57816
57921
  break;
57817
57922
  }
57818
57923
  case "UNGROUP_HEADERS": {
57819
- const { start, end } = cmd;
57924
+ const { start, end, sheetId } = cmd;
57925
+ if (!this.getters.tryGetSheet(sheetId)) {
57926
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
57927
+ }
57820
57928
  if (!this.getters.doesHeadersExist(cmd.sheetId, cmd.dimension, [start, end])) {
57821
57929
  return "InvalidHeaderGroupStartEnd" /* CommandResult.InvalidHeaderGroupStartEnd */;
57822
57930
  }
@@ -57827,6 +57935,9 @@ class HeaderGroupingPlugin extends CorePlugin {
57827
57935
  }
57828
57936
  case "UNFOLD_HEADER_GROUP":
57829
57937
  case "FOLD_HEADER_GROUP":
57938
+ if (!this.getters.tryGetSheet(cmd.sheetId)) {
57939
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
57940
+ }
57830
57941
  const group = this.findGroupWithStartEnd(cmd.sheetId, cmd.dimension, cmd.start, cmd.end);
57831
57942
  if (!group) {
57832
57943
  return "UnknownHeaderGroup" /* CommandResult.UnknownHeaderGroup */;
@@ -58227,6 +58338,9 @@ class PivotCorePlugin extends CorePlugin {
58227
58338
  return this.checkDuplicatedMeasureIds(cmd.pivot);
58228
58339
  }
58229
58340
  case "UPDATE_PIVOT": {
58341
+ if (!(cmd.pivotId in this.pivots)) {
58342
+ return "PivotIdNotFound" /* CommandResult.PivotIdNotFound */;
58343
+ }
58230
58344
  if (deepEquals(cmd.pivot, this.pivots[cmd.pivotId]?.definition)) {
58231
58345
  return "NoChanges" /* CommandResult.NoChanges */;
58232
58346
  }
@@ -58243,6 +58357,8 @@ class PivotCorePlugin extends CorePlugin {
58243
58357
  return "EmptyName" /* CommandResult.EmptyName */;
58244
58358
  }
58245
58359
  break;
58360
+ case "REMOVE_PIVOT":
58361
+ case "DUPLICATE_PIVOT":
58246
58362
  case "INSERT_PIVOT": {
58247
58363
  if (!(cmd.pivotId in this.pivots)) {
58248
58364
  return "PivotIdNotFound" /* CommandResult.PivotIdNotFound */;
@@ -58292,7 +58408,7 @@ class PivotCorePlugin extends CorePlugin {
58292
58408
  break;
58293
58409
  }
58294
58410
  case "UPDATE_PIVOT": {
58295
- this.history.update("pivots", cmd.pivotId, "definition", cmd.pivot);
58411
+ this.history.update("pivots", cmd.pivotId, "definition", deepCopy(cmd.pivot));
58296
58412
  this.compileCalculatedMeasures(cmd.pivot.measures);
58297
58413
  break;
58298
58414
  }
@@ -58363,7 +58479,7 @@ class PivotCorePlugin extends CorePlugin {
58363
58479
  // Private
58364
58480
  // -------------------------------------------------------------------------
58365
58481
  addPivot(pivotId, pivot, formulaId = this.nextFormulaId.toString()) {
58366
- this.history.update("pivots", pivotId, { definition: pivot, formulaId });
58482
+ this.history.update("pivots", pivotId, { definition: deepCopy(pivot), formulaId });
58367
58483
  this.compileCalculatedMeasures(pivot.measures);
58368
58484
  this.history.update("formulaIds", formulaId, pivotId);
58369
58485
  this.history.update("nextFormulaId", this.nextFormulaId + 1);
@@ -59933,6 +60049,10 @@ class Evaluator {
59933
60049
  this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
59934
60050
  this.compilationParams.evalContext.updateDependencies = this.updateDependencies.bind(this);
59935
60051
  this.compilationParams.evalContext.addDependencies = this.addDependencies.bind(this);
60052
+ this.compilationParams.evalContext.lookupCaches = {
60053
+ forwardSearch: new Map(),
60054
+ reverseSearch: new Map(),
60055
+ };
59936
60056
  }
59937
60057
  createEmptyPositionSet() {
59938
60058
  const sheetSizes = {};
@@ -63281,6 +63401,9 @@ function updateChartRangesTransformation(toTransform, executed) {
63281
63401
  };
63282
63402
  }
63283
63403
  function createSheetTransformation(toTransform, executed) {
63404
+ if (toTransform.sheetId === executed.sheetId) {
63405
+ toTransform = { ...toTransform, sheetId: `${toTransform.sheetId}~` };
63406
+ }
63284
63407
  if (toTransform.name === executed.name) {
63285
63408
  return {
63286
63409
  ...toTransform,
@@ -63924,15 +64047,6 @@ class Session extends EventBus {
63924
64047
  }
63925
64048
  this.sendPendingMessage();
63926
64049
  }
63927
- dropPendingRevision(revisionId) {
63928
- this.revisions.drop(revisionId);
63929
- const revisionIds = this.pendingMessages
63930
- .filter((message) => message.type === "REMOTE_REVISION")
63931
- .map((message) => message.nextRevisionId);
63932
- this.trigger("pending-revisions-dropped", { revisionIds });
63933
- this.waitingAck = false;
63934
- this.waitingUndoRedoAck = false;
63935
- }
63936
64050
  /**
63937
64051
  * Send the next pending message
63938
64052
  */
@@ -63941,15 +64055,14 @@ class Session extends EventBus {
63941
64055
  if (!message)
63942
64056
  return;
63943
64057
  if (message.type === "REMOTE_REVISION") {
63944
- const revision = this.revisions.get(message.nextRevisionId);
64058
+ let revision = this.revisions.get(message.nextRevisionId);
63945
64059
  if (revision.commands.length === 0) {
63946
64060
  /**
63947
- * The command is empty, we have to drop all the next local revisions
64061
+ * The command is empty, we have to rebase all the next local revisions
63948
64062
  * to avoid issues with undo/redo
63949
64063
  */
63950
- this.dropPendingRevision(revision.id);
63951
- this.pendingMessages = [];
63952
- return;
64064
+ this.revisions.rebase(revision.id);
64065
+ revision = this.revisions.get(message.nextRevisionId);
63953
64066
  }
63954
64067
  message = {
63955
64068
  ...message,
@@ -63985,18 +64098,16 @@ class Session extends EventBus {
63985
64098
  case "REVISION_UNDONE": {
63986
64099
  this.waitingAck = false;
63987
64100
  this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
63988
- const pendingRemoteRevisions = this.pendingMessages.filter((message) => message.type === "REMOTE_REVISION");
63989
- const firstTransformedRevisionIndex = pendingRemoteRevisions.findIndex((message) => !deepEquals(message.commands, this.revisions.get(message.nextRevisionId).commands));
63990
- if (firstTransformedRevisionIndex !== -1) {
64101
+ const firstPendingRevisionId = this.pendingMessages.findIndex((message) => message.type === "REMOTE_REVISION");
64102
+ if (firstPendingRevisionId !== -1) {
63991
64103
  /**
63992
64104
  * Some revisions undergo transformations that may cause issues with
63993
64105
  * undo/redo if the transformation is destructive (we don't get back
63994
64106
  * the original command by transforming it with the inverse).
63995
- * To prevent these problems, we must discard all subsequent local
64107
+ * To prevent these problems, we must rebase all subsequent local
63996
64108
  * revisions.
63997
64109
  */
63998
- this.dropPendingRevision(this.pendingMessages[firstTransformedRevisionIndex].nextRevisionId);
63999
- this.pendingMessages = this.pendingMessages.slice(0, firstTransformedRevisionIndex);
64110
+ this.revisions.rebase(this.pendingMessages[firstPendingRevisionId].nextRevisionId);
64000
64111
  }
64001
64112
  this.serverRevisionId = message.nextRevisionId;
64002
64113
  this.processedRevisions.add(message.nextRevisionId);
@@ -65118,6 +65229,10 @@ class SheetUIPlugin extends UIPlugin {
65118
65229
  */
65119
65230
  checkZonesAreInSheet(cmd) {
65120
65231
  const sheetId = "sheetId" in cmd ? cmd.sheetId : this.getters.tryGetActiveSheetId();
65232
+ if ("ranges" in cmd &&
65233
+ cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId))) {
65234
+ return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
65235
+ }
65121
65236
  const zones = this.getters.getCommandZones(cmd);
65122
65237
  if (!sheetId && zones.length > 0) {
65123
65238
  return "NoActiveSheet" /* CommandResult.NoActiveSheet */;
@@ -65672,7 +65787,6 @@ class HistoryPlugin extends UIPlugin {
65672
65787
  super(config);
65673
65788
  this.session = config.session;
65674
65789
  this.session.on("new-local-state-update", this, this.onNewLocalStateUpdate);
65675
- this.session.on("pending-revisions-dropped", this, ({ revisionIds }) => this.drop(revisionIds));
65676
65790
  this.session.on("snapshot", this, () => {
65677
65791
  this.undoStack = [];
65678
65792
  this.redoStack = [];
@@ -65742,10 +65856,6 @@ class HistoryPlugin extends UIPlugin {
65742
65856
  const lastNonRedoRevision = this.getPossibleRevisionToRepeat();
65743
65857
  return canRepeatRevision(lastNonRedoRevision);
65744
65858
  }
65745
- drop(revisionIds) {
65746
- this.undoStack = this.undoStack.filter((id) => !revisionIds.includes(id));
65747
- this.redoStack = [];
65748
- }
65749
65859
  onNewLocalStateUpdate({ id }) {
65750
65860
  this.undoStack.push(id);
65751
65861
  this.redoStack = [];
@@ -68420,7 +68530,9 @@ class HeaderPositionsUIPlugin extends UIPlugin {
68420
68530
  case "UNGROUP_HEADERS":
68421
68531
  case "GROUP_HEADERS":
68422
68532
  case "CREATE_SHEET":
68423
- this.headerPositions[cmd.sheetId] = this.computeHeaderPositionsOfSheet(cmd.sheetId);
68533
+ if (this.getters.tryGetSheet(cmd.sheetId)) {
68534
+ this.headerPositions[cmd.sheetId] = this.computeHeaderPositionsOfSheet(cmd.sheetId);
68535
+ }
68424
68536
  break;
68425
68537
  case "DUPLICATE_SHEET":
68426
68538
  this.headerPositions[cmd.sheetIdTo] = deepCopy(this.headerPositions[cmd.sheetId]);
@@ -68428,12 +68540,14 @@ class HeaderPositionsUIPlugin extends UIPlugin {
68428
68540
  }
68429
68541
  }
68430
68542
  finalize() {
68431
- if (this.isDirty) {
68432
- for (const sheetId of this.getters.getSheetIds()) {
68543
+ for (const sheetId of this.getters.getSheetIds()) {
68544
+ // sheets can be created without this plugin being aware of it
68545
+ // in concurrent situations.
68546
+ if (this.isDirty || !this.headerPositions[sheetId]) {
68433
68547
  this.headerPositions[sheetId] = this.computeHeaderPositionsOfSheet(sheetId);
68434
68548
  }
68435
- this.isDirty = false;
68436
68549
  }
68550
+ this.isDirty = false;
68437
68551
  }
68438
68552
  /**
68439
68553
  * Returns the size, start and end coordinates of a column on an unfolded sheet
@@ -70274,6 +70388,10 @@ const FX_SVG = /*xml*/ `
70274
70388
  </svg>
70275
70389
  `;
70276
70390
  css /* scss */ `
70391
+ .o-topbar-composer-container {
70392
+ height: ${TOPBAR_TOOLBAR_HEIGHT}px;
70393
+ }
70394
+
70277
70395
  .o-topbar-composer {
70278
70396
  height: fit-content;
70279
70397
  margin-top: -1px;
@@ -71837,9 +71955,16 @@ class SelectiveHistory {
71837
71955
  this.fastForward();
71838
71956
  this.insert(redoId, this.buildEmpty(redoId), insertAfter);
71839
71957
  }
71840
- drop(operationId) {
71958
+ rebase(operationId) {
71959
+ const operation = this.get(operationId);
71960
+ const execution = [...this.tree.execution(this.HEAD_BRANCH).startAfter(operationId)];
71841
71961
  this.revertBefore(operationId);
71962
+ const baseId = this.HEAD_OPERATION.id;
71842
71963
  this.tree.drop(operationId);
71964
+ this.insert(operationId, operation, baseId);
71965
+ for (const { operation } of execution) {
71966
+ this.insert(operation.id, operation.data, this.HEAD_OPERATION.id);
71967
+ }
71843
71968
  }
71844
71969
  /**
71845
71970
  * Revert the state as it was *before* the given operation was executed.
@@ -74967,6 +75092,11 @@ class Model extends EventBus {
74967
75092
  dispatch: (command) => {
74968
75093
  const result = this.checkDispatchAllowed(command);
74969
75094
  if (!result.isSuccessful) {
75095
+ // core views plugins need to be invalidated
75096
+ this.dispatchToHandlers(this.coreHandlers, {
75097
+ type: "UNDO",
75098
+ commands: [command],
75099
+ });
74970
75100
  return;
74971
75101
  }
74972
75102
  this.isReplayingCommand = true;
@@ -75533,6 +75663,6 @@ exports.tokenColors = tokenColors;
75533
75663
  exports.tokenize = tokenize;
75534
75664
 
75535
75665
 
75536
- __info__.version = "18.2.0-alpha.8";
75537
- __info__.date = "2025-02-14T08:40:13.286Z";
75538
- __info__.hash = "19d45d9";
75666
+ __info__.version = "18.2.1";
75667
+ __info__.date = "2025-02-25T06:03:13.262Z";
75668
+ __info__.hash = "3b4b5c9";