@odoo/o-spreadsheet 16.0.20 → 16.0.22

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.
@@ -319,7 +319,16 @@ const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY;
319
319
  const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
320
320
  const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
321
321
  const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
322
+ const CACHE = {};
322
323
  function parseDateTime(str) {
324
+ if (CACHE[str]) {
325
+ return CACHE[str];
326
+ }
327
+ const date = _parseDateTime(str);
328
+ CACHE[str] = date;
329
+ return date;
330
+ }
331
+ function _parseDateTime(str) {
323
332
  str = str.trim();
324
333
  let time;
325
334
  const timeMatch = str.match(timeRegexp);
@@ -2045,8 +2054,9 @@ class RangeImpl {
2045
2054
  }
2046
2055
  get zone() {
2047
2056
  const { left, top, bottom, right } = this._zone;
2048
- if (right !== undefined && bottom !== undefined)
2049
- return { left, top, right, bottom };
2057
+ if (right !== undefined && bottom !== undefined) {
2058
+ return this._zone;
2059
+ }
2050
2060
  else if (bottom === undefined && right !== undefined) {
2051
2061
  return { right, top, left, bottom: this.getSheetSize(this.sheetId).height - 1 };
2052
2062
  }
@@ -3297,6 +3307,9 @@ exports.CommandResult = void 0;
3297
3307
  CommandResult[CommandResult["InvalidQuantity"] = 86] = "InvalidQuantity";
3298
3308
  })(exports.CommandResult || (exports.CommandResult = {}));
3299
3309
 
3310
+ function isMatrix(x) {
3311
+ return Array.isArray(x) && Array.isArray(x[0]);
3312
+ }
3300
3313
  var DIRECTION;
3301
3314
  (function (DIRECTION) {
3302
3315
  DIRECTION["UP"] = "up";
@@ -17069,6 +17082,36 @@ const HLOOKUP = {
17069
17082
  isExported: true,
17070
17083
  };
17071
17084
  // -----------------------------------------------------------------------------
17085
+ // INDEX
17086
+ // -----------------------------------------------------------------------------
17087
+ const INDEX = {
17088
+ description: _lt(`Returns the content of a cell, specified by row and column offset.`),
17089
+ args: args(`
17090
+ reference (any, range) ${_lt("The range of cells from which the value is returned.")}
17091
+ row (number) ${_lt("The index of the row to be returned from within the reference range of cells.")}
17092
+ column (number) ${_lt("The index of the column to be returned from within the reference range of cells.")}
17093
+ `),
17094
+ returns: ["ANY"],
17095
+ computeFormat: (reference, row, column) => {
17096
+ var _a;
17097
+ const _row = toNumber(row.value);
17098
+ const _column = toNumber(column.value);
17099
+ return (_a = reference[_column - 1][_row - 1]) === null || _a === void 0 ? void 0 : _a.format;
17100
+ },
17101
+ compute: function (reference, row, column) {
17102
+ const _reference = isMatrix(reference) ? reference : [[reference]];
17103
+ const _row = toNumber(row);
17104
+ const _column = toNumber(column);
17105
+ assert(() => _column >= 0 &&
17106
+ _column - 1 < _reference.length &&
17107
+ _row >= 0 &&
17108
+ _row - 1 < _reference[0].length, _lt("Index out of range."));
17109
+ assert(() => row !== 0 && column !== 0, _lt("This function can only return a single cell value, not an array. Provide valid row and column indices."));
17110
+ return _reference[_column - 1][_row - 1];
17111
+ },
17112
+ isExported: true,
17113
+ };
17114
+ // -----------------------------------------------------------------------------
17072
17115
  // LOOKUP
17073
17116
  // -----------------------------------------------------------------------------
17074
17117
  const LOOKUP = {
@@ -17257,6 +17300,7 @@ var lookup = /*#__PURE__*/Object.freeze({
17257
17300
  COLUMN: COLUMN,
17258
17301
  COLUMNS: COLUMNS,
17259
17302
  HLOOKUP: HLOOKUP,
17303
+ INDEX: INDEX,
17260
17304
  LOOKUP: LOOKUP,
17261
17305
  MATCH: MATCH,
17262
17306
  ROW: ROW,
@@ -21577,7 +21621,14 @@ class AbstractResizer extends owl.Component {
21577
21621
  return;
21578
21622
  }
21579
21623
  if (this.state.waitingForMove === true) {
21580
- this.startMovement(ev);
21624
+ if (!this.env.model.getters.isGridSelectionActive()) {
21625
+ this._selectElement(index, false);
21626
+ }
21627
+ else {
21628
+ // FIXME: Consider reintroducing this feature for all type of selection if we find
21629
+ // a way to have the grid selection follow the other selections evolution
21630
+ this.startMovement(ev);
21631
+ }
21581
21632
  return;
21582
21633
  }
21583
21634
  if (this.env.model.getters.getEditionMode() === "editing") {
@@ -25189,12 +25240,15 @@ function createXMLFile(doc, path, contentType) {
25189
25240
  };
25190
25241
  }
25191
25242
  function xmlEscape(str) {
25192
- return String(str)
25243
+ return (String(str)
25193
25244
  .replace(/\&/g, "&amp;")
25194
25245
  .replace(/\</g, "&lt;")
25195
25246
  .replace(/\>/g, "&gt;")
25196
25247
  .replace(/\"/g, "&quot;")
25197
- .replace(/\'/g, "&apos;");
25248
+ .replace(/\'/g, "&apos;")
25249
+ // Delete all ASCII control characters except for TAB (\x09), LF (\x0A) and CR (\x0D)
25250
+ // They are not valid at all in XML 1.0 (even escaped)
25251
+ .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, ""));
25198
25252
  }
25199
25253
  function formatAttributes(attrs) {
25200
25254
  return new XMLString(attrs.map(([key, val]) => `${key}="${xmlEscape(val)}"`).join(" "));
@@ -27732,10 +27786,11 @@ class CellPlugin extends CorePlugin {
27732
27786
  * Reconstructs the original formula string based on a normalized form and its dependencies
27733
27787
  */
27734
27788
  buildFormulaContent(sheetId, cell, dependencies) {
27735
- const ranges = dependencies || [...cell.dependencies];
27789
+ const ranges = dependencies || cell.dependencies;
27790
+ let rangeIndex = 0;
27736
27791
  return concat(cell.compiledFormula.tokens.map((token) => {
27737
27792
  if (token.type === "REFERENCE") {
27738
- const range = ranges.shift();
27793
+ const range = ranges[rangeIndex++];
27739
27794
  return this.getters.getRangeString(range, sheetId);
27740
27795
  }
27741
27796
  return token.value;
@@ -33058,6 +33113,10 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
33058
33113
  }
33059
33114
  currentRanges = currentRanges.concat(toAdd);
33060
33115
  const newRangesXC = recomputeZones(currentRanges, toRemove);
33116
+ if (newRangesXC.length === 0) {
33117
+ this.dispatch("REMOVE_CONDITIONAL_FORMAT", { id: cf.id, sheetId });
33118
+ return;
33119
+ }
33061
33120
  this.dispatch("ADD_CONDITIONAL_FORMAT", {
33062
33121
  cf: {
33063
33122
  id: cf.id,
@@ -34640,6 +34699,9 @@ class GridSelectionPlugin extends UIPlugin {
34640
34699
  // ---------------------------------------------------------------------------
34641
34700
  // Getters
34642
34701
  // ---------------------------------------------------------------------------
34702
+ isGridSelectionActive() {
34703
+ return this.selection.isListening(this);
34704
+ }
34643
34705
  getActiveSheet() {
34644
34706
  return this.activeSheet;
34645
34707
  }
@@ -34710,11 +34772,18 @@ class GridSelectionPlugin extends UIPlugin {
34710
34772
  }
34711
34773
  }
34712
34774
  getStatisticFnResults() {
34775
+ const sheetId = this.getters.getActiveSheetId();
34713
34776
  // get deduplicated cells in zones
34714
34777
  const cells = new Set(this.gridSelection.zones
34715
- .map((zone) => this.getters.getCellsInZone(this.getters.getActiveSheetId(), zone))
34778
+ .map((zone) => this.getters.getCellsInZone(sheetId, zone))
34716
34779
  .flat()
34717
- .filter((cell) => cell !== undefined));
34780
+ .filter((cell) => {
34781
+ if (!cell) {
34782
+ return false;
34783
+ }
34784
+ const { col, row } = this.getters.getCellPosition(cell === null || cell === void 0 ? void 0 : cell.id);
34785
+ return !this.getters.isRowHidden(sheetId, row) && !this.getters.isColHidden(sheetId, col);
34786
+ }));
34718
34787
  let cellsTypes = new Set();
34719
34788
  let cellsValues = [];
34720
34789
  for (let cell of cells) {
@@ -35016,6 +35085,7 @@ GridSelectionPlugin.getters = [
35016
35085
  "getSheetPosition",
35017
35086
  "isSelected",
35018
35087
  "getElementsFromSelection",
35088
+ "isGridSelectionActive",
35019
35089
  ];
35020
35090
 
35021
35091
  const uuidGenerator = new UuidGenerator();
@@ -40727,6 +40797,9 @@ class SelectionStreamProcessor {
40727
40797
  anchor: { zone, cell: this.anchor.cell },
40728
40798
  });
40729
40799
  }
40800
+ isListening(owner) {
40801
+ return this.stream.isListening(owner);
40802
+ }
40730
40803
  /**
40731
40804
  * Process a new anchor selection event. If the new anchor is inside
40732
40805
  * the sheet boundaries, the event is pushed to the event stream to
@@ -42924,6 +42997,6 @@ exports.setTranslationMethod = setTranslationMethod;
42924
42997
  exports.tokenize = tokenize;
42925
42998
 
42926
42999
 
42927
- __info__.version = '16.0.20';
42928
- __info__.date = '2023-10-03T12:43:02.601Z';
42929
- __info__.hash = '3be5a75';
43000
+ __info__.version = '16.0.22';
43001
+ __info__.date = '2023-10-19T14:18:55.223Z';
43002
+ __info__.hash = '7f76b56';
@@ -278,7 +278,7 @@ declare class RangeImpl implements Range {
278
278
  constructor(args: ConstructorArgs, getSheetSize: (sheetId: UID) => ZoneDimension);
279
279
  static fromRange(range: Range, getters: CoreGetters): RangeImpl;
280
280
  get unboundedZone(): UnboundedZone;
281
- get zone(): Zone;
281
+ get zone(): Readonly<Zone>;
282
282
  static getRangeParts(xc: string, zone: UnboundedZone): RangePart[];
283
283
  get isFullCol(): boolean;
284
284
  get isFullRow(): boolean;
@@ -373,6 +373,7 @@ interface SelectionProcessor {
373
373
  selectRow(index: number, mode: "overrideSelection" | "updateAnchor" | "newAnchor"): DispatchResult;
374
374
  selectAll(): DispatchResult;
375
375
  loopSelection(): DispatchResult;
376
+ isListening(owner: unknown): boolean;
376
377
  }
377
378
  /**
378
379
  * Processes all selection updates (usually from user inputs) and emits an event
@@ -439,6 +440,7 @@ declare class SelectionStreamProcessor implements SelectionProcessor, StatefulSt
439
440
  * Select the entire sheet
440
441
  */
441
442
  selectAll(): DispatchResult;
443
+ isListening(owner: unknown): boolean;
442
444
  /**
443
445
  * Process a new anchor selection event. If the new anchor is inside
444
446
  * the sheet boundaries, the event is pushed to the event stream to
@@ -4047,7 +4049,7 @@ declare class RendererPlugin extends UIPlugin {
4047
4049
  */
4048
4050
  declare class GridSelectionPlugin extends UIPlugin {
4049
4051
  static layers: LAYERS[];
4050
- static getters: readonly ["getActiveSheet", "getActiveSheetId", "getActiveCell", "getActiveCols", "getActiveRows", "getCurrentStyle", "getSelectedZones", "getSelectedZone", "getStatisticFnResults", "getAggregate", "getSelectedFigureId", "getSelection", "getPosition", "getSheetPosition", "isSelected", "getElementsFromSelection"];
4052
+ static getters: readonly ["getActiveSheet", "getActiveSheetId", "getActiveCell", "getActiveCols", "getActiveRows", "getCurrentStyle", "getSelectedZones", "getSelectedZone", "getStatisticFnResults", "getAggregate", "getSelectedFigureId", "getSelection", "getPosition", "getSheetPosition", "isSelected", "getElementsFromSelection", "isGridSelectionActive"];
4051
4053
  private gridSelection;
4052
4054
  private selectedFigureId;
4053
4055
  private sheetsData;
@@ -4057,6 +4059,7 @@ declare class GridSelectionPlugin extends UIPlugin {
4057
4059
  allowDispatch(cmd: Command): CommandResult;
4058
4060
  private handleEvent;
4059
4061
  handle(cmd: Command): void;
4062
+ isGridSelectionActive(): boolean;
4060
4063
  getActiveSheet(): Readonly<Sheet>;
4061
4064
  getActiveSheetId(): UID;
4062
4065
  getActiveCell(): Cell | undefined;
@@ -315,7 +315,16 @@ const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY;
315
315
  const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
316
316
  const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
317
317
  const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
318
+ const CACHE = {};
318
319
  function parseDateTime(str) {
320
+ if (CACHE[str]) {
321
+ return CACHE[str];
322
+ }
323
+ const date = _parseDateTime(str);
324
+ CACHE[str] = date;
325
+ return date;
326
+ }
327
+ function _parseDateTime(str) {
319
328
  str = str.trim();
320
329
  let time;
321
330
  const timeMatch = str.match(timeRegexp);
@@ -2041,8 +2050,9 @@ class RangeImpl {
2041
2050
  }
2042
2051
  get zone() {
2043
2052
  const { left, top, bottom, right } = this._zone;
2044
- if (right !== undefined && bottom !== undefined)
2045
- return { left, top, right, bottom };
2053
+ if (right !== undefined && bottom !== undefined) {
2054
+ return this._zone;
2055
+ }
2046
2056
  else if (bottom === undefined && right !== undefined) {
2047
2057
  return { right, top, left, bottom: this.getSheetSize(this.sheetId).height - 1 };
2048
2058
  }
@@ -3293,6 +3303,9 @@ var CommandResult;
3293
3303
  CommandResult[CommandResult["InvalidQuantity"] = 86] = "InvalidQuantity";
3294
3304
  })(CommandResult || (CommandResult = {}));
3295
3305
 
3306
+ function isMatrix(x) {
3307
+ return Array.isArray(x) && Array.isArray(x[0]);
3308
+ }
3296
3309
  var DIRECTION;
3297
3310
  (function (DIRECTION) {
3298
3311
  DIRECTION["UP"] = "up";
@@ -17065,6 +17078,36 @@ const HLOOKUP = {
17065
17078
  isExported: true,
17066
17079
  };
17067
17080
  // -----------------------------------------------------------------------------
17081
+ // INDEX
17082
+ // -----------------------------------------------------------------------------
17083
+ const INDEX = {
17084
+ description: _lt(`Returns the content of a cell, specified by row and column offset.`),
17085
+ args: args(`
17086
+ reference (any, range) ${_lt("The range of cells from which the value is returned.")}
17087
+ row (number) ${_lt("The index of the row to be returned from within the reference range of cells.")}
17088
+ column (number) ${_lt("The index of the column to be returned from within the reference range of cells.")}
17089
+ `),
17090
+ returns: ["ANY"],
17091
+ computeFormat: (reference, row, column) => {
17092
+ var _a;
17093
+ const _row = toNumber(row.value);
17094
+ const _column = toNumber(column.value);
17095
+ return (_a = reference[_column - 1][_row - 1]) === null || _a === void 0 ? void 0 : _a.format;
17096
+ },
17097
+ compute: function (reference, row, column) {
17098
+ const _reference = isMatrix(reference) ? reference : [[reference]];
17099
+ const _row = toNumber(row);
17100
+ const _column = toNumber(column);
17101
+ assert(() => _column >= 0 &&
17102
+ _column - 1 < _reference.length &&
17103
+ _row >= 0 &&
17104
+ _row - 1 < _reference[0].length, _lt("Index out of range."));
17105
+ assert(() => row !== 0 && column !== 0, _lt("This function can only return a single cell value, not an array. Provide valid row and column indices."));
17106
+ return _reference[_column - 1][_row - 1];
17107
+ },
17108
+ isExported: true,
17109
+ };
17110
+ // -----------------------------------------------------------------------------
17068
17111
  // LOOKUP
17069
17112
  // -----------------------------------------------------------------------------
17070
17113
  const LOOKUP = {
@@ -17253,6 +17296,7 @@ var lookup = /*#__PURE__*/Object.freeze({
17253
17296
  COLUMN: COLUMN,
17254
17297
  COLUMNS: COLUMNS,
17255
17298
  HLOOKUP: HLOOKUP,
17299
+ INDEX: INDEX,
17256
17300
  LOOKUP: LOOKUP,
17257
17301
  MATCH: MATCH,
17258
17302
  ROW: ROW,
@@ -21573,7 +21617,14 @@ class AbstractResizer extends Component {
21573
21617
  return;
21574
21618
  }
21575
21619
  if (this.state.waitingForMove === true) {
21576
- this.startMovement(ev);
21620
+ if (!this.env.model.getters.isGridSelectionActive()) {
21621
+ this._selectElement(index, false);
21622
+ }
21623
+ else {
21624
+ // FIXME: Consider reintroducing this feature for all type of selection if we find
21625
+ // a way to have the grid selection follow the other selections evolution
21626
+ this.startMovement(ev);
21627
+ }
21577
21628
  return;
21578
21629
  }
21579
21630
  if (this.env.model.getters.getEditionMode() === "editing") {
@@ -25185,12 +25236,15 @@ function createXMLFile(doc, path, contentType) {
25185
25236
  };
25186
25237
  }
25187
25238
  function xmlEscape(str) {
25188
- return String(str)
25239
+ return (String(str)
25189
25240
  .replace(/\&/g, "&amp;")
25190
25241
  .replace(/\</g, "&lt;")
25191
25242
  .replace(/\>/g, "&gt;")
25192
25243
  .replace(/\"/g, "&quot;")
25193
- .replace(/\'/g, "&apos;");
25244
+ .replace(/\'/g, "&apos;")
25245
+ // Delete all ASCII control characters except for TAB (\x09), LF (\x0A) and CR (\x0D)
25246
+ // They are not valid at all in XML 1.0 (even escaped)
25247
+ .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, ""));
25194
25248
  }
25195
25249
  function formatAttributes(attrs) {
25196
25250
  return new XMLString(attrs.map(([key, val]) => `${key}="${xmlEscape(val)}"`).join(" "));
@@ -27728,10 +27782,11 @@ class CellPlugin extends CorePlugin {
27728
27782
  * Reconstructs the original formula string based on a normalized form and its dependencies
27729
27783
  */
27730
27784
  buildFormulaContent(sheetId, cell, dependencies) {
27731
- const ranges = dependencies || [...cell.dependencies];
27785
+ const ranges = dependencies || cell.dependencies;
27786
+ let rangeIndex = 0;
27732
27787
  return concat(cell.compiledFormula.tokens.map((token) => {
27733
27788
  if (token.type === "REFERENCE") {
27734
- const range = ranges.shift();
27789
+ const range = ranges[rangeIndex++];
27735
27790
  return this.getters.getRangeString(range, sheetId);
27736
27791
  }
27737
27792
  return token.value;
@@ -33054,6 +33109,10 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
33054
33109
  }
33055
33110
  currentRanges = currentRanges.concat(toAdd);
33056
33111
  const newRangesXC = recomputeZones(currentRanges, toRemove);
33112
+ if (newRangesXC.length === 0) {
33113
+ this.dispatch("REMOVE_CONDITIONAL_FORMAT", { id: cf.id, sheetId });
33114
+ return;
33115
+ }
33057
33116
  this.dispatch("ADD_CONDITIONAL_FORMAT", {
33058
33117
  cf: {
33059
33118
  id: cf.id,
@@ -34636,6 +34695,9 @@ class GridSelectionPlugin extends UIPlugin {
34636
34695
  // ---------------------------------------------------------------------------
34637
34696
  // Getters
34638
34697
  // ---------------------------------------------------------------------------
34698
+ isGridSelectionActive() {
34699
+ return this.selection.isListening(this);
34700
+ }
34639
34701
  getActiveSheet() {
34640
34702
  return this.activeSheet;
34641
34703
  }
@@ -34706,11 +34768,18 @@ class GridSelectionPlugin extends UIPlugin {
34706
34768
  }
34707
34769
  }
34708
34770
  getStatisticFnResults() {
34771
+ const sheetId = this.getters.getActiveSheetId();
34709
34772
  // get deduplicated cells in zones
34710
34773
  const cells = new Set(this.gridSelection.zones
34711
- .map((zone) => this.getters.getCellsInZone(this.getters.getActiveSheetId(), zone))
34774
+ .map((zone) => this.getters.getCellsInZone(sheetId, zone))
34712
34775
  .flat()
34713
- .filter((cell) => cell !== undefined));
34776
+ .filter((cell) => {
34777
+ if (!cell) {
34778
+ return false;
34779
+ }
34780
+ const { col, row } = this.getters.getCellPosition(cell === null || cell === void 0 ? void 0 : cell.id);
34781
+ return !this.getters.isRowHidden(sheetId, row) && !this.getters.isColHidden(sheetId, col);
34782
+ }));
34714
34783
  let cellsTypes = new Set();
34715
34784
  let cellsValues = [];
34716
34785
  for (let cell of cells) {
@@ -35012,6 +35081,7 @@ GridSelectionPlugin.getters = [
35012
35081
  "getSheetPosition",
35013
35082
  "isSelected",
35014
35083
  "getElementsFromSelection",
35084
+ "isGridSelectionActive",
35015
35085
  ];
35016
35086
 
35017
35087
  const uuidGenerator = new UuidGenerator();
@@ -40723,6 +40793,9 @@ class SelectionStreamProcessor {
40723
40793
  anchor: { zone, cell: this.anchor.cell },
40724
40794
  });
40725
40795
  }
40796
+ isListening(owner) {
40797
+ return this.stream.isListening(owner);
40798
+ }
40726
40799
  /**
40727
40800
  * Process a new anchor selection event. If the new anchor is inside
40728
40801
  * the sheet boundaries, the event is pushed to the event stream to
@@ -42892,6 +42965,6 @@ function addFunction(functionName, functionDescription) {
42892
42965
  export { AbstractChart, CommandResult, CorePlugin, DATETIME_FORMAT, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, cellTypes, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, load, parse, readonlyAllowedCommands, registries, setTranslationMethod, tokenize };
42893
42966
 
42894
42967
 
42895
- __info__.version = '16.0.20';
42896
- __info__.date = '2023-10-03T12:43:02.601Z';
42897
- __info__.hash = '3be5a75';
42968
+ __info__.version = '16.0.22';
42969
+ __info__.date = '2023-10-19T14:18:55.223Z';
42970
+ __info__.hash = '7f76b56';
@@ -316,7 +316,16 @@
316
316
  const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
317
317
  const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
318
318
  const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
319
+ const CACHE = {};
319
320
  function parseDateTime(str) {
321
+ if (CACHE[str]) {
322
+ return CACHE[str];
323
+ }
324
+ const date = _parseDateTime(str);
325
+ CACHE[str] = date;
326
+ return date;
327
+ }
328
+ function _parseDateTime(str) {
320
329
  str = str.trim();
321
330
  let time;
322
331
  const timeMatch = str.match(timeRegexp);
@@ -2042,8 +2051,9 @@
2042
2051
  }
2043
2052
  get zone() {
2044
2053
  const { left, top, bottom, right } = this._zone;
2045
- if (right !== undefined && bottom !== undefined)
2046
- return { left, top, right, bottom };
2054
+ if (right !== undefined && bottom !== undefined) {
2055
+ return this._zone;
2056
+ }
2047
2057
  else if (bottom === undefined && right !== undefined) {
2048
2058
  return { right, top, left, bottom: this.getSheetSize(this.sheetId).height - 1 };
2049
2059
  }
@@ -3294,6 +3304,9 @@
3294
3304
  CommandResult[CommandResult["InvalidQuantity"] = 86] = "InvalidQuantity";
3295
3305
  })(exports.CommandResult || (exports.CommandResult = {}));
3296
3306
 
3307
+ function isMatrix(x) {
3308
+ return Array.isArray(x) && Array.isArray(x[0]);
3309
+ }
3297
3310
  var DIRECTION;
3298
3311
  (function (DIRECTION) {
3299
3312
  DIRECTION["UP"] = "up";
@@ -17066,6 +17079,36 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
17066
17079
  isExported: true,
17067
17080
  };
17068
17081
  // -----------------------------------------------------------------------------
17082
+ // INDEX
17083
+ // -----------------------------------------------------------------------------
17084
+ const INDEX = {
17085
+ description: _lt(`Returns the content of a cell, specified by row and column offset.`),
17086
+ args: args(`
17087
+ reference (any, range) ${_lt("The range of cells from which the value is returned.")}
17088
+ row (number) ${_lt("The index of the row to be returned from within the reference range of cells.")}
17089
+ column (number) ${_lt("The index of the column to be returned from within the reference range of cells.")}
17090
+ `),
17091
+ returns: ["ANY"],
17092
+ computeFormat: (reference, row, column) => {
17093
+ var _a;
17094
+ const _row = toNumber(row.value);
17095
+ const _column = toNumber(column.value);
17096
+ return (_a = reference[_column - 1][_row - 1]) === null || _a === void 0 ? void 0 : _a.format;
17097
+ },
17098
+ compute: function (reference, row, column) {
17099
+ const _reference = isMatrix(reference) ? reference : [[reference]];
17100
+ const _row = toNumber(row);
17101
+ const _column = toNumber(column);
17102
+ assert(() => _column >= 0 &&
17103
+ _column - 1 < _reference.length &&
17104
+ _row >= 0 &&
17105
+ _row - 1 < _reference[0].length, _lt("Index out of range."));
17106
+ assert(() => row !== 0 && column !== 0, _lt("This function can only return a single cell value, not an array. Provide valid row and column indices."));
17107
+ return _reference[_column - 1][_row - 1];
17108
+ },
17109
+ isExported: true,
17110
+ };
17111
+ // -----------------------------------------------------------------------------
17069
17112
  // LOOKUP
17070
17113
  // -----------------------------------------------------------------------------
17071
17114
  const LOOKUP = {
@@ -17254,6 +17297,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
17254
17297
  COLUMN: COLUMN,
17255
17298
  COLUMNS: COLUMNS,
17256
17299
  HLOOKUP: HLOOKUP,
17300
+ INDEX: INDEX,
17257
17301
  LOOKUP: LOOKUP,
17258
17302
  MATCH: MATCH,
17259
17303
  ROW: ROW,
@@ -21574,7 +21618,14 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
21574
21618
  return;
21575
21619
  }
21576
21620
  if (this.state.waitingForMove === true) {
21577
- this.startMovement(ev);
21621
+ if (!this.env.model.getters.isGridSelectionActive()) {
21622
+ this._selectElement(index, false);
21623
+ }
21624
+ else {
21625
+ // FIXME: Consider reintroducing this feature for all type of selection if we find
21626
+ // a way to have the grid selection follow the other selections evolution
21627
+ this.startMovement(ev);
21628
+ }
21578
21629
  return;
21579
21630
  }
21580
21631
  if (this.env.model.getters.getEditionMode() === "editing") {
@@ -25186,12 +25237,15 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
25186
25237
  };
25187
25238
  }
25188
25239
  function xmlEscape(str) {
25189
- return String(str)
25240
+ return (String(str)
25190
25241
  .replace(/\&/g, "&amp;")
25191
25242
  .replace(/\</g, "&lt;")
25192
25243
  .replace(/\>/g, "&gt;")
25193
25244
  .replace(/\"/g, "&quot;")
25194
- .replace(/\'/g, "&apos;");
25245
+ .replace(/\'/g, "&apos;")
25246
+ // Delete all ASCII control characters except for TAB (\x09), LF (\x0A) and CR (\x0D)
25247
+ // They are not valid at all in XML 1.0 (even escaped)
25248
+ .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, ""));
25195
25249
  }
25196
25250
  function formatAttributes(attrs) {
25197
25251
  return new XMLString(attrs.map(([key, val]) => `${key}="${xmlEscape(val)}"`).join(" "));
@@ -27729,10 +27783,11 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
27729
27783
  * Reconstructs the original formula string based on a normalized form and its dependencies
27730
27784
  */
27731
27785
  buildFormulaContent(sheetId, cell, dependencies) {
27732
- const ranges = dependencies || [...cell.dependencies];
27786
+ const ranges = dependencies || cell.dependencies;
27787
+ let rangeIndex = 0;
27733
27788
  return concat(cell.compiledFormula.tokens.map((token) => {
27734
27789
  if (token.type === "REFERENCE") {
27735
- const range = ranges.shift();
27790
+ const range = ranges[rangeIndex++];
27736
27791
  return this.getters.getRangeString(range, sheetId);
27737
27792
  }
27738
27793
  return token.value;
@@ -33055,6 +33110,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
33055
33110
  }
33056
33111
  currentRanges = currentRanges.concat(toAdd);
33057
33112
  const newRangesXC = recomputeZones(currentRanges, toRemove);
33113
+ if (newRangesXC.length === 0) {
33114
+ this.dispatch("REMOVE_CONDITIONAL_FORMAT", { id: cf.id, sheetId });
33115
+ return;
33116
+ }
33058
33117
  this.dispatch("ADD_CONDITIONAL_FORMAT", {
33059
33118
  cf: {
33060
33119
  id: cf.id,
@@ -34637,6 +34696,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
34637
34696
  // ---------------------------------------------------------------------------
34638
34697
  // Getters
34639
34698
  // ---------------------------------------------------------------------------
34699
+ isGridSelectionActive() {
34700
+ return this.selection.isListening(this);
34701
+ }
34640
34702
  getActiveSheet() {
34641
34703
  return this.activeSheet;
34642
34704
  }
@@ -34707,11 +34769,18 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
34707
34769
  }
34708
34770
  }
34709
34771
  getStatisticFnResults() {
34772
+ const sheetId = this.getters.getActiveSheetId();
34710
34773
  // get deduplicated cells in zones
34711
34774
  const cells = new Set(this.gridSelection.zones
34712
- .map((zone) => this.getters.getCellsInZone(this.getters.getActiveSheetId(), zone))
34775
+ .map((zone) => this.getters.getCellsInZone(sheetId, zone))
34713
34776
  .flat()
34714
- .filter((cell) => cell !== undefined));
34777
+ .filter((cell) => {
34778
+ if (!cell) {
34779
+ return false;
34780
+ }
34781
+ const { col, row } = this.getters.getCellPosition(cell === null || cell === void 0 ? void 0 : cell.id);
34782
+ return !this.getters.isRowHidden(sheetId, row) && !this.getters.isColHidden(sheetId, col);
34783
+ }));
34715
34784
  let cellsTypes = new Set();
34716
34785
  let cellsValues = [];
34717
34786
  for (let cell of cells) {
@@ -35013,6 +35082,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
35013
35082
  "getSheetPosition",
35014
35083
  "isSelected",
35015
35084
  "getElementsFromSelection",
35085
+ "isGridSelectionActive",
35016
35086
  ];
35017
35087
 
35018
35088
  const uuidGenerator = new UuidGenerator();
@@ -40724,6 +40794,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
40724
40794
  anchor: { zone, cell: this.anchor.cell },
40725
40795
  });
40726
40796
  }
40797
+ isListening(owner) {
40798
+ return this.stream.isListening(owner);
40799
+ }
40727
40800
  /**
40728
40801
  * Process a new anchor selection event. If the new anchor is inside
40729
40802
  * the sheet boundaries, the event is pushed to the event stream to
@@ -42923,9 +42996,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42923
42996
  Object.defineProperty(exports, '__esModule', { value: true });
42924
42997
 
42925
42998
 
42926
- __info__.version = '16.0.20';
42927
- __info__.date = '2023-10-03T12:43:02.601Z';
42928
- __info__.hash = '3be5a75';
42999
+ __info__.version = '16.0.22';
43000
+ __info__.date = '2023-10-19T14:18:55.223Z';
43001
+ __info__.hash = '7f76b56';
42929
43002
 
42930
43003
 
42931
43004
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);