@odoo/o-spreadsheet 16.5.0-alpha.0 → 16.5.0-alpha.2

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.
@@ -109,8 +109,8 @@
109
109
  const HEADER_BORDER_COLOR = "#C0C0C0";
110
110
  const CELL_BORDER_COLOR = "#E2E3E3";
111
111
  const BACKGROUND_CHART_COLOR = "#FFFFFF";
112
- const MENU_ITEM_DISABLED_COLOR = "#CACACA";
113
112
  const BG_HOVER_COLOR = "#EBEBEB";
113
+ const DISABLED_TEXT_COLOR = "#CACACA";
114
114
  const DEFAULT_COLOR_SCALE_MIDPOINT_COLOR = 0xb6d7a8;
115
115
  const LINK_COLOR = "#01666b";
116
116
  const FILTERS_COLOR = "#188038";
@@ -1185,7 +1185,7 @@
1185
1185
  const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
1186
1186
  const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
1187
1187
  const dateSeparatorsRegex = /\/|-|\s/;
1188
- const dateRegexp = /^(\d{1,4})[\/-\s](\d{1,2})([\/-\s](\d{1,4}))?$/;
1188
+ const dateRegexp = /^(\d{1,4})[\/-\s](\d{1,4})([\/-\s](\d{1,4}))?$/;
1189
1189
  const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
1190
1190
  function isDateTime(str, locale) {
1191
1191
  return parseDateTime(str, locale) !== null;
@@ -1246,6 +1246,10 @@
1246
1246
  }
1247
1247
  const localeDateType = getLocaleDateFormatType(locale);
1248
1248
  if (!part3) {
1249
+ if (part2.length > 2) {
1250
+ // e.g. 11/2023
1251
+ return { month: part1, year: part2, day: undefined, dateString, type: localeDateType };
1252
+ }
1249
1253
  if (localeDateType === "dmy") {
1250
1254
  return { day: part1, month: part2, year: part3, dateString, type: "dmy" };
1251
1255
  }
@@ -2992,11 +2996,18 @@
2992
2996
  constructor(args, getSheetSize) {
2993
2997
  this.getSheetSize = getSheetSize;
2994
2998
  this._zone = args.zone;
2995
- this.parts = args.parts;
2996
2999
  this.prefixSheet = args.prefixSheet;
2997
3000
  this.invalidXc = args.invalidXc;
2998
3001
  this.sheetId = args.sheetId;
2999
3002
  this.invalidSheetName = args.invalidSheetName;
3003
+ let _fixedParts = [...args.parts];
3004
+ if (args.parts.length === 1 && getZoneArea(this.zone) > 1) {
3005
+ _fixedParts.push({ ...args.parts[0] });
3006
+ }
3007
+ else if (args.parts.length === 2 && getZoneArea(this.zone) === 1) {
3008
+ _fixedParts.pop();
3009
+ }
3010
+ this.parts = _fixedParts;
3000
3011
  }
3001
3012
  static fromRange(range, getters) {
3002
3013
  if (range instanceof RangeImpl) {
@@ -4046,13 +4057,10 @@
4046
4057
  "START",
4047
4058
  "ACTIVATE_SHEET",
4048
4059
  "COPY",
4049
- "PREPARE_SELECTION_INPUT_EXPANSION",
4050
- "STOP_SELECTION_INPUT",
4051
4060
  "RESIZE_SHEETVIEW",
4052
4061
  "SET_VIEWPORT_OFFSET",
4053
4062
  "SELECT_SEARCH_NEXT_MATCH",
4054
4063
  "SELECT_SEARCH_PREVIOUS_MATCH",
4055
- "REFRESH_SEARCH",
4056
4064
  "UPDATE_SEARCH",
4057
4065
  "CLEAR_SEARCH",
4058
4066
  "EVALUATE_CELLS",
@@ -5124,8 +5132,7 @@
5124
5132
  return { cellData: {} };
5125
5133
  }
5126
5134
  const sheetId = data.sheetId;
5127
- const ranges = getters.createAdaptedRanges(cell.dependencies, x, y, sheetId);
5128
- const content = getters.buildFormulaContent(sheetId, cell, ranges);
5135
+ const content = getters.getTranslatedCellFormula(sheetId, x, y, cell.compiledFormula, cell.dependencies);
5129
5136
  return {
5130
5137
  cellData: {
5131
5138
  border: data.border,
@@ -5991,7 +5998,7 @@
5991
5998
  }
5992
5999
  }
5993
6000
  &.disabled {
5994
- color: ${MENU_ITEM_DISABLED_COLOR};
6001
+ color: ${DISABLED_TEXT_COLOR};
5995
6002
  cursor: not-allowed;
5996
6003
  }
5997
6004
  }
@@ -22417,6 +22424,18 @@
22417
22424
  style[tool] = !style[tool];
22418
22425
  this.closeMenus();
22419
22426
  }
22427
+ onKeydown(event) {
22428
+ if (event.key === "F4") {
22429
+ const target = event.target;
22430
+ const update = this.env.model.getters.getCycledReference({ start: target.selectionStart ?? 0, end: target.selectionEnd ?? 0 }, target.value);
22431
+ if (!update) {
22432
+ return;
22433
+ }
22434
+ target.value = update.content;
22435
+ target.setSelectionRange(update.selection.start, update.selection.end);
22436
+ target.dispatchEvent(new Event("input"));
22437
+ }
22438
+ }
22420
22439
  setColor(target, color) {
22421
22440
  this.state.rules.cellIs.style[target] = color;
22422
22441
  this.closeMenus();
@@ -22691,6 +22710,7 @@
22691
22710
  state = owl.useState(this.initialState());
22692
22711
  debounceTimeoutId;
22693
22712
  showFormulaState = false;
22713
+ debouncedUpdateSearch;
22694
22714
  findAndReplaceRef = owl.useRef("findAndReplace");
22695
22715
  get hasSearchResult() {
22696
22716
  return this.env.model.getters.getCurrentSelectedMatchIndex() !== null;
@@ -22700,11 +22720,16 @@
22700
22720
  }
22701
22721
  setup() {
22702
22722
  this.showFormulaState = this.env.model.getters.shouldShowFormulas();
22723
+ this.debouncedUpdateSearch = debounce(this.updateSearch.bind(this), 200);
22703
22724
  owl.onMounted(() => this.focusInput());
22704
22725
  owl.onWillUnmount(() => {
22705
22726
  this.env.model.dispatch("CLEAR_SEARCH");
22706
22727
  this.env.model.dispatch("SET_FORMULA_VISIBILITY", { show: this.showFormulaState });
22707
22728
  });
22729
+ owl.useEffect(() => {
22730
+ this.state.searchOptions.searchFormulas = this.env.model.getters.shouldShowFormulas();
22731
+ this.searchFormulas();
22732
+ }, () => [this.env.model.getters.shouldShowFormulas()]);
22708
22733
  }
22709
22734
  onInput(ev) {
22710
22735
  this.state.toSearch = ev.target.value;
@@ -22724,10 +22749,6 @@
22724
22749
  this.replace();
22725
22750
  }
22726
22751
  }
22727
- onFocusSidePanel() {
22728
- this.state.searchOptions.searchFormulas = this.env.model.getters.shouldShowFormulas();
22729
- this.env.model.dispatch("REFRESH_SEARCH");
22730
- }
22731
22752
  searchFormulas() {
22732
22753
  this.env.model.dispatch("SET_FORMULA_VISIBILITY", {
22733
22754
  show: this.state.searchOptions.searchFormulas,
@@ -22746,13 +22767,6 @@
22746
22767
  searchOptions: this.state.searchOptions,
22747
22768
  });
22748
22769
  }
22749
- debouncedUpdateSearch() {
22750
- clearTimeout(this.debounceTimeoutId);
22751
- this.debounceTimeoutId = setTimeout(() => {
22752
- this.updateSearch();
22753
- this.debounceTimeoutId = undefined;
22754
- }, 400);
22755
- }
22756
22770
  replace() {
22757
22771
  this.env.model.dispatch("REPLACE_SEARCH", {
22758
22772
  replaceWith: this.state.replaceWith,
@@ -24692,6 +24706,15 @@
24692
24706
  y = initialFigure.y - deltaY;
24693
24707
  }
24694
24708
  }
24709
+ // Restrict resizing if x or y reaches header boundaries
24710
+ if (x < 0) {
24711
+ width += x;
24712
+ x = 0;
24713
+ }
24714
+ if (y < 0) {
24715
+ height += y;
24716
+ y = 0;
24717
+ }
24695
24718
  return { ...initialFigure, x, y, width, height };
24696
24719
  }
24697
24720
 
@@ -25284,10 +25307,29 @@
25284
25307
  setPosition(undefined, undefined);
25285
25308
  }
25286
25309
  }
25310
+ function onMouseLeave(e) {
25311
+ const x = e.offsetX;
25312
+ const y = e.offsetY;
25313
+ const gridRect = getBoundingRectAsPOJO(gridRef.el);
25314
+ if (y < 0 || y > gridRect.height || x < 0 || x > gridRect.width) {
25315
+ return updateMousePosition(e);
25316
+ }
25317
+ else {
25318
+ return pause();
25319
+ }
25320
+ }
25287
25321
  useRefListener(gridRef, "mousemove", updateMousePosition);
25288
- useRefListener(gridRef, "mouseleave", pause);
25322
+ useRefListener(gridRef, "mouseleave", onMouseLeave);
25289
25323
  useRefListener(gridRef, "mouseenter", resume);
25290
25324
  useRefListener(gridRef, "mousedown", recompute);
25325
+ owl.useExternalListener(window, "click", handleGlobalClick);
25326
+ function handleGlobalClick(e) {
25327
+ const target = e.target;
25328
+ const grid = gridRef.el;
25329
+ if (!grid.contains(target)) {
25330
+ setPosition(undefined, undefined);
25331
+ }
25332
+ }
25291
25333
  function setPosition(col, row) {
25292
25334
  if (col !== hoveredPosition.col || row !== hoveredPosition.row) {
25293
25335
  hoveredPosition.col = col;
@@ -25611,7 +25653,6 @@
25611
25653
  const mouseUpSelect = () => {
25612
25654
  this.state.isSelecting = false;
25613
25655
  this.lastSelectedElementIndex = null;
25614
- this.env.model.dispatch(ev.ctrlKey ? "PREPARE_SELECTION_INPUT_EXPANSION" : "STOP_SELECTION_INPUT");
25615
25656
  this._computeGrabDisplay(ev);
25616
25657
  };
25617
25658
  dragAndDropBeyondTheViewport(this.env, mouseMoveSelect, mouseUpSelect);
@@ -26176,9 +26217,7 @@
26176
26217
  let lastCol = isLeft ? z.left : z.right;
26177
26218
  let lastRow = isTop ? z.top : z.bottom;
26178
26219
  let currentZone = z;
26179
- this.env.model.dispatch("START_CHANGE_HIGHLIGHT", {
26180
- range: this.env.model.getters.getRangeDataFromZone(activeSheetId, currentZone),
26181
- });
26220
+ this.env.model.dispatch("START_CHANGE_HIGHLIGHT", { zone: currentZone });
26182
26221
  const mouseMove = (col, row) => {
26183
26222
  if (lastCol !== col || lastRow !== row) {
26184
26223
  lastCol = clip(col === -1 ? lastCol : col, 0, this.env.model.getters.getNumberCols(activeSheetId) - 1);
@@ -26189,21 +26228,17 @@
26189
26228
  right: Math.max(pivotCol, lastCol),
26190
26229
  bottom: Math.max(pivotRow, lastRow),
26191
26230
  };
26192
- newZone = this.env.model.getters.expandZone(activeSheetId, newZone);
26193
26231
  if (!isEqual(newZone, currentZone)) {
26194
- this.env.model.dispatch("CHANGE_HIGHLIGHT", {
26195
- range: this.env.model.getters.getRangeFromZone(activeSheetId, this.env.model.getters.getUnboundedZone(activeSheetId, newZone)).rangeData,
26196
- });
26232
+ this.env.model.selection.selectZone({
26233
+ cell: { col: newZone.left, row: newZone.top },
26234
+ zone: newZone,
26235
+ }, { unbounded: true });
26197
26236
  currentZone = newZone;
26198
26237
  }
26199
26238
  }
26200
26239
  };
26201
26240
  const mouseUp = () => {
26202
26241
  this.highlightState.shiftingMode = "none";
26203
- // To do:
26204
- // Command used here to restore focus to the current composer,
26205
- // to be changed when refactoring the 'edition' plugin
26206
- this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
26207
26242
  };
26208
26243
  dragAndDropBeyondTheViewport(this.env, mouseMove, mouseUp);
26209
26244
  }
@@ -26219,9 +26254,7 @@
26219
26254
  const deltaRowMin = -z.top;
26220
26255
  const deltaRowMax = this.env.model.getters.getNumberRows(activeSheetId) - z.bottom - 1;
26221
26256
  let currentZone = z;
26222
- this.env.model.dispatch("START_CHANGE_HIGHLIGHT", {
26223
- range: this.env.model.getters.getRangeDataFromZone(activeSheetId, currentZone),
26224
- });
26257
+ this.env.model.dispatch("START_CHANGE_HIGHLIGHT", { zone: currentZone });
26225
26258
  let lastCol = initCol;
26226
26259
  let lastRow = initRow;
26227
26260
  const mouseMove = (col, row) => {
@@ -26236,21 +26269,17 @@
26236
26269
  right: z.right + deltaCol,
26237
26270
  bottom: z.bottom + deltaRow,
26238
26271
  };
26239
- newZone = this.env.model.getters.expandZone(activeSheetId, newZone);
26240
26272
  if (!isEqual(newZone, currentZone)) {
26241
- this.env.model.dispatch("CHANGE_HIGHLIGHT", {
26242
- range: this.env.model.getters.getRangeFromZone(activeSheetId, this.env.model.getters.getUnboundedZone(activeSheetId, newZone)).rangeData,
26243
- });
26273
+ this.env.model.selection.selectZone({
26274
+ cell: { col: newZone.left, row: newZone.top },
26275
+ zone: newZone,
26276
+ }, { unbounded: true });
26244
26277
  currentZone = newZone;
26245
26278
  }
26246
26279
  }
26247
26280
  };
26248
26281
  const mouseUp = () => {
26249
26282
  this.highlightState.shiftingMode = "none";
26250
- // To do:
26251
- // Command used here to restore focus to the current composer,
26252
- // to be changed when refactoring the 'edition' plugin
26253
- this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
26254
26283
  };
26255
26284
  dragAndDropBeyondTheViewport(this.env, mouseMove, mouseUp);
26256
26285
  }
@@ -26743,9 +26772,6 @@
26743
26772
  // Zone selection with mouse
26744
26773
  // ---------------------------------------------------------------------------
26745
26774
  onCellClicked(col, row, { ctrlKey, shiftKey }) {
26746
- if (ctrlKey) {
26747
- this.env.model.dispatch("PREPARE_SELECTION_INPUT_EXPANSION");
26748
- }
26749
26775
  if (this.env.model.getters.hasOpenedPopover()) {
26750
26776
  this.closeOpenedPopover();
26751
26777
  }
@@ -26771,7 +26797,6 @@
26771
26797
  }
26772
26798
  };
26773
26799
  const onMouseUp = () => {
26774
- this.env.model.dispatch("STOP_SELECTION_INPUT");
26775
26800
  if (this.env.model.getters.isPaintingFormat()) {
26776
26801
  this.env.model.dispatch("PASTE", {
26777
26802
  target: this.env.model.getters.getSelectedZones(),
@@ -31489,8 +31514,8 @@
31489
31514
  "zoneToXC",
31490
31515
  "getCells",
31491
31516
  "getFormulaCellContent",
31517
+ "getTranslatedCellFormula",
31492
31518
  "getCellStyle",
31493
- "buildFormulaContent",
31494
31519
  "getCellById",
31495
31520
  ];
31496
31521
  nextId = 1;
@@ -31689,7 +31714,7 @@
31689
31714
  /*
31690
31715
  * Reconstructs the original formula string based on a normalized form and its dependencies
31691
31716
  */
31692
- buildFormulaContent(sheetId, cell, dependencies) {
31717
+ getFormulaCellContent(sheetId, cell, dependencies) {
31693
31718
  const ranges = dependencies || [...cell.dependencies];
31694
31719
  return concat(cell.compiledFormula.tokens.map((token) => {
31695
31720
  if (token.type === "REFERENCE") {
@@ -31699,8 +31724,15 @@
31699
31724
  return token.value;
31700
31725
  }));
31701
31726
  }
31702
- getFormulaCellContent(sheetId, cell) {
31703
- return this.buildFormulaContent(sheetId, cell);
31727
+ /*
31728
+ * Constructs a formula string based on an initial formula and a translation vector
31729
+ */
31730
+ getTranslatedCellFormula(sheetId, offsetX, offsetY, compiledFormula, dependencies) {
31731
+ const adaptedDependencies = this.getters.createAdaptedRanges(dependencies, offsetX, offsetY, sheetId);
31732
+ return this.getFormulaCellContent(sheetId, {
31733
+ compiledFormula,
31734
+ dependencies: adaptedDependencies,
31735
+ });
31704
31736
  }
31705
31737
  getCellStyle(position) {
31706
31738
  return this.getters.getCell(position)?.style || {};
@@ -31890,7 +31922,7 @@
31890
31922
  */
31891
31923
  createFormulaCellWithDependencies(id, compiledFormula, format, style, sheetId) {
31892
31924
  const dependencies = compiledFormula.dependencies.map((xc) => this.getters.getRangeFromSheetXC(sheetId, xc));
31893
- return new FormulaCellWithDependencies(id, compiledFormula, format, style, dependencies, sheetId, this.buildFormulaContent.bind(this));
31925
+ return new FormulaCellWithDependencies(id, compiledFormula, format, style, dependencies, sheetId, this.getFormulaCellContent.bind(this));
31894
31926
  }
31895
31927
  createErrorFormula(id, content, format, style, error) {
31896
31928
  return {
@@ -31924,19 +31956,19 @@
31924
31956
  style;
31925
31957
  dependencies;
31926
31958
  sheetId;
31927
- buildFormulaContent;
31959
+ getFormulaCellContent;
31928
31960
  isFormula = true;
31929
- constructor(id, compiledFormula, format, style, dependencies, sheetId, buildFormulaContent) {
31961
+ constructor(id, compiledFormula, format, style, dependencies, sheetId, getFormulaCellContent) {
31930
31962
  this.id = id;
31931
31963
  this.compiledFormula = compiledFormula;
31932
31964
  this.format = format;
31933
31965
  this.style = style;
31934
31966
  this.dependencies = dependencies;
31935
31967
  this.sheetId = sheetId;
31936
- this.buildFormulaContent = buildFormulaContent;
31968
+ this.getFormulaCellContent = getFormulaCellContent;
31937
31969
  }
31938
31970
  get content() {
31939
- return this.buildFormulaContent(this.sheetId, {
31971
+ return this.getFormulaCellContent(this.sheetId, {
31940
31972
  dependencies: this.dependencies,
31941
31973
  compiledFormula: this.compiledFormula,
31942
31974
  });
@@ -36451,13 +36483,21 @@
36451
36483
  }
36452
36484
  break;
36453
36485
  case "CellIsRule":
36486
+ const formulas = cf.rule.values.map((value) => value.startsWith("=") ? compile(value) : undefined);
36454
36487
  for (let ref of cf.ranges) {
36455
36488
  const zone = this.getters.getRangeFromSheetXC(sheetId, ref).zone;
36456
36489
  for (let row = zone.top; row <= zone.bottom; row++) {
36457
36490
  for (let col = zone.left; col <= zone.right; col++) {
36458
- const pr = this.rulePredicate[cf.rule.type];
36459
- let cell = this.getters.getEvaluatedCell({ sheetId, col, row });
36460
- if (pr && pr(cell, cf.rule)) {
36491
+ const predicate = this.rulePredicate[cf.rule.type];
36492
+ const target = { sheetId, col, row };
36493
+ const values = cf.rule.values.map((value, i) => {
36494
+ const compiledFormula = formulas[i];
36495
+ if (compiledFormula) {
36496
+ return this.getters.getTranslatedCellFormula(sheetId, col - zone.left, row - zone.top, compiledFormula, compiledFormula.dependencies.map((d) => this.getters.getRangeFromSheetXC(sheetId, d)));
36497
+ }
36498
+ return value;
36499
+ });
36500
+ if (predicate && predicate(target, { ...cf.rule, values })) {
36461
36501
  if (!computedStyle[col])
36462
36502
  computedStyle[col] = [];
36463
36503
  // we must combine all the properties of all the CF rules applied to the given cell
@@ -36625,12 +36665,18 @@
36625
36665
  * Execute the predicate to know if a conditional formatting rule should be applied to a cell
36626
36666
  */
36627
36667
  rulePredicate = {
36628
- CellIsRule: (cell, rule) => {
36668
+ CellIsRule: (target, rule) => {
36669
+ const cell = this.getters.getEvaluatedCell(target);
36629
36670
  if (cell.type === CellValueType.error) {
36630
36671
  return false;
36631
36672
  }
36632
36673
  const locale = this.getters.getLocale();
36633
- const values = rule.values.map((val) => parseLiteral(val, locale));
36674
+ const values = rule.values.map((value) => {
36675
+ if (value.startsWith("=")) {
36676
+ return this.getters.evaluateFormula(target.sheetId, value);
36677
+ }
36678
+ return parseLiteral(value, locale);
36679
+ });
36634
36680
  switch (rule.operator) {
36635
36681
  case "IsEmpty":
36636
36682
  return cell.value.toString().trim() === "";
@@ -38531,6 +38577,7 @@
38531
38577
  searchFormulas: false,
38532
38578
  };
38533
38579
  toSearch = "";
38580
+ isSearchDirty = false;
38534
38581
  // ---------------------------------------------------------------------------
38535
38582
  // Command Handling
38536
38583
  // ---------------------------------------------------------------------------
@@ -38554,18 +38601,33 @@
38554
38601
  case "REPLACE_ALL_SEARCH":
38555
38602
  this.replaceAll(cmd.replaceWith);
38556
38603
  break;
38604
+ case "EVALUATE_CELLS":
38605
+ case "UPDATE_CELL":
38606
+ case "REMOVE_FILTER_TABLE":
38607
+ case "UPDATE_FILTER":
38608
+ this.isSearchDirty = true;
38609
+ break;
38557
38610
  case "UNDO":
38558
38611
  case "REDO":
38559
38612
  case "REMOVE_COLUMNS_ROWS":
38613
+ case "HIDE_COLUMNS_ROWS":
38614
+ case "UNHIDE_COLUMNS_ROWS":
38560
38615
  case "ADD_COLUMNS_ROWS":
38561
- this.clearSearch();
38616
+ case "EVALUATE_CELLS":
38617
+ case "UPDATE_CELL":
38618
+ this.isSearchDirty = true;
38562
38619
  break;
38563
38620
  case "ACTIVATE_SHEET":
38564
- case "REFRESH_SEARCH":
38565
38621
  this.refreshSearch();
38566
38622
  break;
38567
38623
  }
38568
38624
  }
38625
+ finalize() {
38626
+ if (this.isSearchDirty) {
38627
+ this.refreshSearch();
38628
+ this.isSearchDirty = false;
38629
+ }
38630
+ }
38569
38631
  // ---------------------------------------------------------------------------
38570
38632
  // Getters
38571
38633
  // ---------------------------------------------------------------------------
@@ -38621,6 +38683,11 @@
38621
38683
  if (this.toSearch) {
38622
38684
  for (const cell of Object.values(cells)) {
38623
38685
  const { col, row } = this.getters.getCellPosition(cell.id);
38686
+ const isColHidden = this.getters.isColHidden(sheetId, col);
38687
+ const isRowHidden = this.getters.isRowHidden(sheetId, row);
38688
+ if (isColHidden || isRowHidden) {
38689
+ continue;
38690
+ }
38624
38691
  if (cell &&
38625
38692
  this.currentSearchRegex &&
38626
38693
  this.currentSearchRegex.test(this.getSearchableString({ sheetId, col, row }))) {
@@ -38680,37 +38747,32 @@
38680
38747
  // ---------------------------------------------------------------------------
38681
38748
  // Replace
38682
38749
  // ---------------------------------------------------------------------------
38683
- /**
38684
- * Replace the value of the currently selected match
38685
- */
38686
- replace(replaceWith) {
38687
- if (this.selectedMatchIndex === null || !this.currentSearchRegex) {
38750
+ replaceMatch(selectedMatch, replaceWith) {
38751
+ if (!this.currentSearchRegex) {
38688
38752
  return;
38689
38753
  }
38690
- const matches = this.searchMatches;
38691
- const selectedMatch = matches[this.selectedMatchIndex];
38692
38754
  const sheetId = this.getters.getActiveSheetId();
38693
38755
  const cell = this.getters.getCell({ sheetId, ...selectedMatch });
38756
+ const { col, row } = selectedMatch;
38694
38757
  if (cell?.isFormula && !this.searchOptions.searchFormulas) {
38695
- this.selectNextCell(Direction.next);
38758
+ return;
38696
38759
  }
38697
- else {
38698
- const replaceRegex = new RegExp(this.currentSearchRegex.source, this.currentSearchRegex.flags + "g");
38699
- const toReplace = this.getSearchableString({
38700
- sheetId,
38701
- col: selectedMatch.col,
38702
- row: selectedMatch.row,
38703
- });
38704
- const newContent = toReplace.replace(replaceRegex, replaceWith);
38705
- this.dispatch("UPDATE_CELL", {
38706
- sheetId: this.getters.getActiveSheetId(),
38707
- col: selectedMatch.col,
38708
- row: selectedMatch.row,
38709
- content: canonicalizeContent(newContent, this.getters.getLocale()),
38710
- });
38711
- this.searchMatches.splice(this.selectedMatchIndex, 1);
38712
- this.selectNextCell(Direction.current);
38760
+ const replaceRegex = new RegExp(this.currentSearchRegex.source, this.currentSearchRegex.flags + "g");
38761
+ const toReplace = this.getSearchableString({ sheetId, col, row });
38762
+ const content = toReplace.replace(replaceRegex, replaceWith);
38763
+ const canonicalContent = canonicalizeContent(content, this.getters.getLocale());
38764
+ this.dispatch("UPDATE_CELL", { sheetId, col, row, content: canonicalContent });
38765
+ }
38766
+ /**
38767
+ * Replace the value of the currently selected match
38768
+ */
38769
+ replace(replaceWith) {
38770
+ if (this.selectedMatchIndex === null) {
38771
+ return;
38713
38772
  }
38773
+ const selectedMatch = this.searchMatches[this.selectedMatchIndex];
38774
+ this.replaceMatch(selectedMatch, replaceWith);
38775
+ this.selectNextCell(Direction.next);
38714
38776
  }
38715
38777
  /**
38716
38778
  * Apply the replace function to all the matches one time.
@@ -38718,7 +38780,7 @@
38718
38780
  replaceAll(replaceWith) {
38719
38781
  const matchCount = this.searchMatches.length;
38720
38782
  for (let i = 0; i < matchCount; i++) {
38721
- this.replace(replaceWith);
38783
+ this.replaceMatch(this.searchMatches[i], replaceWith);
38722
38784
  }
38723
38785
  }
38724
38786
  getSearchableString(position) {
@@ -39640,8 +39702,7 @@
39640
39702
  static getters = [];
39641
39703
  ranges = [];
39642
39704
  focusedRangeIndex = null;
39643
- activeSheet;
39644
- willAddNewRange = false;
39705
+ inputSheetId;
39645
39706
  constructor(config, initialRanges, inputHasSingleRange) {
39646
39707
  if (inputHasSingleRange && initialRanges.length > 1) {
39647
39708
  throw new Error("Input with a single range cannot be instantiated with several range references.");
@@ -39649,7 +39710,7 @@
39649
39710
  super(config);
39650
39711
  this.inputHasSingleRange = inputHasSingleRange;
39651
39712
  this.insertNewRange(0, initialRanges);
39652
- this.activeSheet = this.getters.getActiveSheetId();
39713
+ this.inputSheetId = this.getters.getActiveSheetId();
39653
39714
  if (this.ranges.length === 0) {
39654
39715
  this.insertNewRange(this.ranges.length, [""]);
39655
39716
  this.focusLast();
@@ -39675,11 +39736,33 @@
39675
39736
  return 0 /* CommandResult.Success */;
39676
39737
  }
39677
39738
  handleEvent(event) {
39678
- const inputSheetId = this.activeSheet;
39679
- const sheetId = this.getters.getActiveSheetId();
39680
- const zone = event.anchor.zone;
39681
- const range = this.getters.getRangeFromZone(sheetId, event.options.unbounded ? this.getters.getUnboundedZone(sheetId, zone) : zone);
39682
- this.add([this.getters.getSelectionRangeString(range, inputSheetId)]);
39739
+ if (this.focusedRangeIndex === null) {
39740
+ return;
39741
+ }
39742
+ const inputSheetId = this.inputSheetId;
39743
+ const activeSheetId = this.getters.getActiveSheetId();
39744
+ const zone = event.options.unbounded
39745
+ ? this.getters.getUnboundedZone(activeSheetId, event.anchor.zone)
39746
+ : event.anchor.zone;
39747
+ const range = this.getters.getRangeFromZone(activeSheetId, zone);
39748
+ const willAddNewRange = event.mode === "newAnchor" &&
39749
+ !this.inputHasSingleRange &&
39750
+ this.ranges[this.focusedRangeIndex].xc.trim() !== "";
39751
+ if (willAddNewRange) {
39752
+ const xc = this.getters.getSelectionRangeString(range, inputSheetId);
39753
+ this.insertNewRange(this.ranges.length, [xc]);
39754
+ this.focusLast();
39755
+ }
39756
+ else {
39757
+ let parts = range.parts;
39758
+ const previousXc = this.ranges[this.focusedRangeIndex].xc.trim();
39759
+ if (previousXc) {
39760
+ parts = this.getters.getRangeFromSheetXC(inputSheetId, previousXc).parts;
39761
+ }
39762
+ const newRange = range.clone({ parts });
39763
+ const xc = this.getters.getSelectionRangeString(newRange, inputSheetId);
39764
+ this.setRange(this.focusedRangeIndex, [xc]);
39765
+ }
39683
39766
  }
39684
39767
  handle(cmd) {
39685
39768
  switch (cmd.type) {
@@ -39715,16 +39798,6 @@
39715
39798
  this.removeRange(index);
39716
39799
  }
39717
39800
  break;
39718
- case "STOP_SELECTION_INPUT":
39719
- this.willAddNewRange = false;
39720
- break;
39721
- case "PREPARE_SELECTION_INPUT_EXPANSION": {
39722
- const index = this.focusedRangeIndex;
39723
- if (index !== null && !this.inputHasSingleRange) {
39724
- this.willAddNewRange = this.ranges[index].xc.trim() !== "";
39725
- }
39726
- break;
39727
- }
39728
39801
  case "ACTIVATE_SHEET": {
39729
39802
  if (cmd.sheetIdFrom !== cmd.sheetIdTo) {
39730
39803
  const { col, row } = this.getters.getNextVisibleCellPosition({
@@ -39735,7 +39808,26 @@
39735
39808
  const zone = this.getters.expandZone(cmd.sheetIdTo, positionToZone({ col, row }));
39736
39809
  this.selection.resetAnchor(this, { cell: { col, row }, zone });
39737
39810
  }
39811
+ break;
39738
39812
  }
39813
+ case "START_CHANGE_HIGHLIGHT":
39814
+ const activeSheetId = this.getters.getActiveSheetId();
39815
+ const newZone = this.getters.expandZone(activeSheetId, cmd.zone);
39816
+ const focusIndex = this.ranges.findIndex((range) => {
39817
+ const { xc, sheetName: sheet } = splitReference(range.xc);
39818
+ const sheetName = sheet || this.getters.getSheetName(this.inputSheetId);
39819
+ if (this.getters.getSheetName(activeSheetId) !== sheetName) {
39820
+ return false;
39821
+ }
39822
+ const refRange = this.getters.getRangeFromSheetXC(activeSheetId, xc);
39823
+ return isEqual(this.getters.expandZone(activeSheetId, refRange.zone), newZone);
39824
+ });
39825
+ if (focusIndex !== -1) {
39826
+ this.focus(focusIndex);
39827
+ const { left, top } = newZone;
39828
+ this.selection.resetAnchor(this, { cell: { col: left, row: top }, zone: newZone });
39829
+ }
39830
+ break;
39739
39831
  }
39740
39832
  }
39741
39833
  // ---------------------------------------------------------------------------
@@ -39764,19 +39856,6 @@
39764
39856
  unfocus() {
39765
39857
  this.focusedRangeIndex = null;
39766
39858
  }
39767
- add(newRanges) {
39768
- if (this.focusedRangeIndex === null || newRanges.length === 0) {
39769
- return;
39770
- }
39771
- if (this.willAddNewRange) {
39772
- this.insertNewRange(this.ranges.length, newRanges);
39773
- this.focusLast();
39774
- this.willAddNewRange = false;
39775
- }
39776
- else {
39777
- this.setRange(this.focusedRangeIndex, newRanges);
39778
- }
39779
- }
39780
39859
  setContent(index, xc) {
39781
39860
  this.ranges[index] = {
39782
39861
  ...this.ranges[index],
@@ -39822,12 +39901,12 @@
39822
39901
  inputToHighlights({ xc, color }) {
39823
39902
  const XCs = this.cleanInputs([xc])
39824
39903
  .filter((range) => this.getters.isRangeValid(range))
39825
- .filter((reference) => this.shouldBeHighlighted(this.activeSheet, reference));
39904
+ .filter((reference) => this.shouldBeHighlighted(this.inputSheetId, reference));
39826
39905
  return XCs.map((xc) => {
39827
39906
  const { sheetName } = splitReference(xc);
39828
39907
  return {
39829
- zone: this.getters.getRangeFromSheetXC(this.activeSheet, xc).zone,
39830
- sheetId: (sheetName && this.getters.getSheetIdByName(sheetName)) || this.activeSheet,
39908
+ zone: this.getters.getRangeFromSheetXC(this.inputSheetId, xc).zone,
39909
+ sheetId: (sheetName && this.getters.getSheetIdByName(sheetName)) || this.inputSheetId,
39831
39910
  color,
39832
39911
  };
39833
39912
  });
@@ -40252,10 +40331,8 @@
40252
40331
  let content = cell.content;
40253
40332
  if (cell.isFormula) {
40254
40333
  const position = this.getters.getCellPosition(cell.id);
40255
- const offsetY = newRow - position.row;
40256
40334
  // we only have a vertical offset
40257
- const ranges = this.getters.createAdaptedRanges(cell.dependencies, 0, offsetY, sheetId);
40258
- content = this.getters.buildFormulaContent(sheetId, cell, ranges);
40335
+ content = this.getters.getTranslatedCellFormula(sheetId, 0, newRow - position.row, cell.compiledFormula, cell.dependencies);
40259
40336
  }
40260
40337
  newCellValues.style = cell.style;
40261
40338
  newCellValues.content = content;
@@ -41362,9 +41439,7 @@
41362
41439
  }
41363
41440
  let content = origin.cell.content;
41364
41441
  if (origin.cell.isFormula && operation === "COPY") {
41365
- const offsetX = col - origin.position.col;
41366
- const offsetY = row - origin.position.row;
41367
- content = this.getUpdatedContent(sheetId, origin.cell, offsetX, offsetY, operation);
41442
+ content = this.getters.getTranslatedCellFormula(sheetId, col - origin.position.col, row - origin.position.row, origin.cell.compiledFormula, origin.cell.dependencies);
41368
41443
  }
41369
41444
  this.dispatch("UPDATE_CELL", {
41370
41445
  ...target,
@@ -41385,13 +41460,6 @@
41385
41460
  }
41386
41461
  }
41387
41462
  }
41388
- /**
41389
- * Get the newly updated formula, after applying offsets
41390
- */
41391
- getUpdatedContent(sheetId, cell, offsetX, offsetY, operation) {
41392
- const ranges = this.getters.createAdaptedRanges(cell.dependencies, offsetX, offsetY, sheetId);
41393
- return this.getters.buildFormulaContent(sheetId, cell, ranges);
41394
- }
41395
41463
  /**
41396
41464
  * If the origin position given is the top left of a merge, merge the target
41397
41465
  * position.
@@ -42133,6 +42201,7 @@
42133
42201
  "getTokenAtCursor",
42134
42202
  "getComposerHighlights",
42135
42203
  "getCurrentEditedCell",
42204
+ "getCycledReference",
42136
42205
  ];
42137
42206
  col = 0;
42138
42207
  row = 0;
@@ -42142,10 +42211,7 @@
42142
42211
  currentTokens = [];
42143
42212
  selectionStart = 0;
42144
42213
  selectionEnd = 0;
42145
- selectionInitialStart = 0;
42146
42214
  initialContent = "";
42147
- previousRef = "";
42148
- previousRange = undefined;
42149
42215
  colorIndexByRange = {};
42150
42216
  // ---------------------------------------------------------------------------
42151
42217
  // Command Handling
@@ -42174,9 +42240,6 @@
42174
42240
  }
42175
42241
  }
42176
42242
  handleEvent(event) {
42177
- if (this.mode !== "selecting") {
42178
- return;
42179
- }
42180
42243
  const sheetId = this.getters.getActiveSheetId();
42181
42244
  let unboundedZone;
42182
42245
  if (event.options.unbounded) {
@@ -42187,10 +42250,17 @@
42187
42250
  }
42188
42251
  switch (event.mode) {
42189
42252
  case "newAnchor":
42190
- this.insertSelectedRange(unboundedZone);
42253
+ if (this.mode === "selecting") {
42254
+ this.insertSelectedRange(unboundedZone);
42255
+ }
42191
42256
  break;
42192
42257
  default:
42193
- this.replaceSelectedRanges(unboundedZone);
42258
+ if (this.mode === "selecting") {
42259
+ this.replaceSelectedRange(unboundedZone);
42260
+ }
42261
+ else {
42262
+ this.updateComposerRange(event.previousAnchor.zone, unboundedZone);
42263
+ }
42194
42264
  break;
42195
42265
  }
42196
42266
  }
@@ -42247,35 +42317,12 @@
42247
42317
  }
42248
42318
  break;
42249
42319
  case "START_CHANGE_HIGHLIGHT":
42250
- // FIXME: thiws whole ordeal could be handled with the Selection Processor which would extend the feature to selection inputs
42251
- this.dispatch("STOP_COMPOSER_RANGE_SELECTION");
42252
- // FIXME: we should check range SheetId compared to this.activeSheetId r maybe not have a sheetId in the payload ??
42253
- const range = this.getters.getRangeFromRangeData(cmd.range);
42254
- const previousRefToken = this.currentTokens
42255
- .filter((token) => token.type === "REFERENCE")
42256
- .find((token) => {
42257
- const { xc, sheetName: sheet } = splitReference(token.value);
42258
- const sheetName = sheet || this.getters.getSheetName(this.sheetId);
42259
- const activeSheetId = this.getters.getActiveSheetId();
42260
- if (this.getters.getSheetName(activeSheetId) !== sheetName) {
42261
- return false;
42262
- }
42263
- const refRange = this.getters.getRangeFromSheetXC(activeSheetId, xc);
42264
- return isEqual(this.getters.expandZone(activeSheetId, refRange.zone), range.zone);
42265
- });
42266
- this.previousRef = previousRefToken.value;
42267
- this.previousRange = this.getters.getRangeFromSheetXC(this.getters.getActiveSheetId(), this.previousRef);
42268
- this.selectionInitialStart = previousRefToken.start;
42269
- break;
42270
- case "CHANGE_HIGHLIGHT":
42271
- const cmdRange = this.getters.getRangeFromRangeData(cmd.range);
42272
- const newRef = this.getRangeReference(cmdRange, this.previousRange.parts);
42273
- this.selectionStart = this.selectionInitialStart;
42274
- this.selectionEnd = this.selectionInitialStart + this.previousRef.length;
42275
- this.replaceSelection(newRef);
42276
- this.previousRef = newRef;
42277
- this.selectionStart = this.currentContent.length;
42278
- this.selectionEnd = this.currentContent.length;
42320
+ const { left, top } = cmd.zone;
42321
+ // changing the highlight can conflit with the 'selecting' mode
42322
+ if (this.isSelectingForComposer()) {
42323
+ this.mode = "editing";
42324
+ }
42325
+ this.selection.resetAnchor(this, { cell: { col: left, row: top }, zone: cmd.zone });
42279
42326
  break;
42280
42327
  case "ACTIVATE_SHEET":
42281
42328
  if (!this.currentContent.startsWith("=")) {
@@ -42359,33 +42406,45 @@
42359
42406
  return this.currentTokens.find((t) => t.start <= start && t.end >= end);
42360
42407
  }
42361
42408
  }
42362
- // ---------------------------------------------------------------------------
42363
- // Misc
42364
- // ---------------------------------------------------------------------------
42365
- cycleReferences() {
42366
- const tokens = this.getTokensInSelection();
42409
+ /**
42410
+ * Return the cycled reference if any (A1 -> $A$1 -> A$1 -> $A1 -> A1)
42411
+ */
42412
+ getCycledReference(selection, content) {
42413
+ const locale = this.getters.getLocale();
42414
+ const currentTokens = content.startsWith("=") ? composerTokenize(content, locale) : [];
42415
+ const tokens = currentTokens.filter((t) => (t.start <= selection.start && t.end >= selection.start) ||
42416
+ (t.start >= selection.start && t.start < selection.end));
42367
42417
  const refTokens = tokens.filter((token) => token.type === "REFERENCE");
42368
- if (refTokens.length === 0)
42418
+ if (refTokens.length === 0) {
42369
42419
  return;
42420
+ }
42370
42421
  const updatedReferences = tokens
42371
42422
  .map(loopThroughReferenceType)
42372
42423
  .map((token) => token.value)
42373
42424
  .join("");
42374
- const content = this.currentContent;
42375
42425
  const start = tokens[0].start;
42376
42426
  const end = tokens[tokens.length - 1].end;
42377
42427
  const newContent = content.slice(0, start) + updatedReferences + content.slice(end);
42378
42428
  const lengthDiff = newContent.length - content.length;
42379
42429
  const startOfTokens = refTokens[0].start;
42380
42430
  const endOfTokens = refTokens[refTokens.length - 1].end + lengthDiff;
42381
- const selection = { start: startOfTokens, end: endOfTokens };
42382
- // Put the selection at the end of the token if we cycled on a single token
42383
- if (refTokens.length === 1 && this.selectionStart === this.selectionEnd) {
42384
- selection.start = selection.end;
42431
+ const newSelection = { start: startOfTokens, end: endOfTokens };
42432
+ if (refTokens.length === 1 && selection.start === selection.end) {
42433
+ newSelection.start = newSelection.end;
42434
+ }
42435
+ return { content: newContent, selection: newSelection };
42436
+ }
42437
+ // ---------------------------------------------------------------------------
42438
+ // Misc
42439
+ // ---------------------------------------------------------------------------
42440
+ cycleReferences() {
42441
+ const updated = this.getCycledReference(this.getComposerSelection(), this.currentContent);
42442
+ if (updated === undefined) {
42443
+ return;
42385
42444
  }
42386
42445
  this.dispatch("SET_CURRENT_CONTENT", {
42387
- content: newContent,
42388
- selection,
42446
+ content: updated.content,
42447
+ selection: updated.selection,
42389
42448
  });
42390
42449
  }
42391
42450
  validateSelection(length, start, end) {
@@ -42433,7 +42492,6 @@
42433
42492
  this.selection.resetAnchor(this, { cell: { col: this.col, row: this.row }, zone });
42434
42493
  }
42435
42494
  this.mode = "selecting";
42436
- this.selectionInitialStart = this.selectionStart;
42437
42495
  }
42438
42496
  /**
42439
42497
  * start the edition of a cell
@@ -42593,19 +42651,49 @@
42593
42651
  const ref = this.getZoneReference(zone);
42594
42652
  if (this.canStartComposerRangeSelection()) {
42595
42653
  this.insertText(ref, start);
42596
- this.selectionInitialStart = start;
42597
42654
  }
42598
42655
  else {
42599
42656
  this.insertText("," + ref, start);
42600
- this.selectionInitialStart = start + 1;
42601
42657
  }
42602
42658
  }
42603
42659
  /**
42604
42660
  * Replace the current reference selected by the new one.
42605
42661
  * */
42606
- replaceSelectedRanges(zone) {
42662
+ replaceSelectedRange(zone) {
42607
42663
  const ref = this.getZoneReference(zone);
42608
- this.replaceText(ref, this.selectionInitialStart, this.selectionEnd);
42664
+ const currentToken = this.getTokenAtCursor();
42665
+ const start = currentToken?.type === "REFERENCE" ? currentToken.start : this.selectionStart;
42666
+ this.replaceText(ref, start, this.selectionEnd);
42667
+ }
42668
+ /**
42669
+ * Replace the reference of the old zone by the new one.
42670
+ */
42671
+ updateComposerRange(oldZone, newZone) {
42672
+ const activeSheetId = this.getters.getActiveSheetId();
42673
+ const tokentAtCursor = this.getTokenAtCursor();
42674
+ const tokens = tokentAtCursor ? [tokentAtCursor, ...this.currentTokens] : this.currentTokens;
42675
+ const previousRefToken = tokens
42676
+ .filter((token) => token.type === "REFERENCE")
42677
+ .find((token) => {
42678
+ const { xc, sheetName: sheet } = splitReference(token.value);
42679
+ const sheetName = sheet || this.getters.getSheetName(this.sheetId);
42680
+ if (this.getters.getSheetName(activeSheetId) !== sheetName) {
42681
+ return false;
42682
+ }
42683
+ const refRange = this.getters.getRangeFromSheetXC(activeSheetId, xc);
42684
+ return isEqual(this.getters.expandZone(activeSheetId, refRange.zone), oldZone);
42685
+ });
42686
+ // this function assumes that the previous range is always found because
42687
+ // it's called when changing a highlight, which exists by definition
42688
+ if (!previousRefToken) {
42689
+ throw new Error("Previous range not found");
42690
+ }
42691
+ const previousRange = this.getters.getRangeFromSheetXC(activeSheetId, previousRefToken.value);
42692
+ this.selectionStart = previousRefToken.start;
42693
+ this.selectionEnd = this.selectionStart + previousRefToken.value.length;
42694
+ const newRange = this.getters.getRangeFromZone(activeSheetId, newZone);
42695
+ const newRef = this.getRangeReference(newRange, previousRange.parts);
42696
+ this.replaceSelection(newRef);
42609
42697
  }
42610
42698
  getZoneReference(zone) {
42611
42699
  const inputSheetId = this.getters.getCurrentEditedCell().sheetId;
@@ -42613,14 +42701,8 @@
42613
42701
  const range = this.getters.getRangeFromZone(sheetId, zone);
42614
42702
  return this.getters.getSelectionRangeString(range, inputSheetId);
42615
42703
  }
42616
- getRangeReference(range, fixedParts = [{ colFixed: false, rowFixed: false }]) {
42704
+ getRangeReference(range, fixedParts) {
42617
42705
  let _fixedParts = [...fixedParts];
42618
- if (fixedParts.length === 1 && getZoneArea(range.zone) > 1) {
42619
- _fixedParts.push({ ...fixedParts[0] });
42620
- }
42621
- else if (fixedParts.length === 2 && getZoneArea(range.zone) === 1) {
42622
- _fixedParts.pop();
42623
- }
42624
42706
  const newRange = range.clone({ parts: _fixedParts });
42625
42707
  return this.getters.getSelectionRangeString(newRange, this.getters.getCurrentEditedCell().sheetId);
42626
42708
  }
@@ -42747,15 +42829,6 @@
42747
42829
  }
42748
42830
  return false;
42749
42831
  }
42750
- /**
42751
- * Return all the tokens between selectionStart and selectionEnd.
42752
- * Includes token that begin right on selectionStart or end right on selectionEnd.
42753
- */
42754
- getTokensInSelection() {
42755
- const start = Math.min(this.selectionStart, this.selectionEnd);
42756
- const end = Math.max(this.selectionStart, this.selectionEnd);
42757
- return this.currentTokens.filter((t) => (t.start <= start && t.end >= start) || (t.start >= start && t.start < end));
42758
- }
42759
42832
  }
42760
42833
 
42761
42834
  class FilterEvaluationPlugin extends UIPlugin {
@@ -45721,6 +45794,11 @@
45721
45794
  .o-sidePanelButton:enabled {
45722
45795
  cursor: pointer;
45723
45796
  }
45797
+
45798
+ .o-sidePanelButton:disabled {
45799
+ color: ${DISABLED_TEXT_COLOR};
45800
+ }
45801
+
45724
45802
  .o-sidePanelButton:last-child {
45725
45803
  margin-right: 0px;
45726
45804
  }
@@ -50284,10 +50362,17 @@
50284
50362
  * It will call `beforeHandle` and `handle`
50285
50363
  */
50286
50364
  dispatchToHandlers(handlers, command) {
50365
+ const isCommandCore = isCoreCommand(command);
50287
50366
  for (const handler of handlers) {
50367
+ if (!isCommandCore && handler instanceof CorePlugin) {
50368
+ continue;
50369
+ }
50288
50370
  handler.beforeHandle(command);
50289
50371
  }
50290
50372
  for (const handler of handlers) {
50373
+ if (!isCommandCore && handler instanceof CorePlugin) {
50374
+ continue;
50375
+ }
50291
50376
  handler.handle(command);
50292
50377
  }
50293
50378
  }
@@ -50473,6 +50558,9 @@
50473
50558
  };
50474
50559
  function addFunction(functionName, functionDescription) {
50475
50560
  functionRegistry.add(functionName, functionDescription);
50561
+ return {
50562
+ addFunction: (fName, fDescription) => addFunction(fName, fDescription),
50563
+ };
50476
50564
  }
50477
50565
  const constants = {
50478
50566
  DEFAULT_LOCALE,
@@ -50515,9 +50603,9 @@
50515
50603
  Object.defineProperty(exports, '__esModule', { value: true });
50516
50604
 
50517
50605
 
50518
- __info__.version = '16.5.0-alpha.0';
50519
- __info__.date = '2023-07-24T06:48:58.196Z';
50520
- __info__.hash = '3ba2c3c';
50606
+ __info__.version = '16.5.0-alpha.2';
50607
+ __info__.date = '2023-08-07T09:02:00.623Z';
50608
+ __info__.hash = 'e74f3ef';
50521
50609
 
50522
50610
 
50523
50611
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);