@odoo/o-spreadsheet 17.2.0-alpha.4 → 17.2.0-alpha.5

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.
@@ -3,9 +3,9 @@
3
3
  /**
4
4
  * This file is generated by o-spreadsheet build tools. Do not edit it.
5
5
  * @see https://github.com/odoo/o-spreadsheet
6
- * @version 17.2.0-alpha.4
7
- * @date 2024-02-09T13:10:23.460Z
8
- * @hash 1b33cf4
6
+ * @version 17.2.0-alpha.5
7
+ * @date 2024-02-16T14:27:52.323Z
8
+ * @hash 0c69dd8
9
9
  */
10
10
 
11
11
  (function (exports, owl) {
@@ -454,8 +454,8 @@
454
454
  * If the given item does not exist in the dictionary, it creates one with a new id.
455
455
  */
456
456
  function getItemId(item, itemsDic) {
457
- for (let [key, value] of Object.entries(itemsDic)) {
458
- if (deepEquals(value, item)) {
457
+ for (const key in itemsDic) {
458
+ if (deepEquals(itemsDic[key], item)) {
459
459
  return parseInt(key, 10);
460
460
  }
461
461
  }
@@ -559,11 +559,13 @@
559
559
  if (typeof o1 !== "object")
560
560
  return o1 === o2;
561
561
  // Objects can have different keys if the values are undefined
562
- const keys = new Set();
563
- Object.keys(o1).forEach((key) => keys.add(key));
564
- Object.keys(o2).forEach((key) => keys.add(key));
565
- for (let key of keys) {
566
- if (typeof o1[key] !== typeof o1[key])
562
+ for (const key in o2) {
563
+ if (!(key in o1) && o2[key] !== undefined) {
564
+ return false;
565
+ }
566
+ }
567
+ for (const key in o1) {
568
+ if (typeof o1[key] !== typeof o2[key])
567
569
  return false;
568
570
  if (typeof o1[key] === "object") {
569
571
  if (!deepEquals(o1[key], o2[key]))
@@ -633,18 +635,18 @@
633
635
  return true;
634
636
  }
635
637
  class JetSet extends Set {
636
- add(...iterable) {
638
+ addMany(iterable) {
637
639
  for (const element of iterable) {
638
640
  super.add(element);
639
641
  }
640
642
  return this;
641
643
  }
642
- delete(...iterable) {
643
- let deleted = false;
644
+ deleteMany(iterable) {
645
+ let wasDeleted = false;
644
646
  for (const element of iterable) {
645
- deleted ||= super.delete(element);
647
+ wasDeleted ||= super.delete(element);
646
648
  }
647
- return deleted;
649
+ return wasDeleted;
648
650
  }
649
651
  }
650
652
  /**
@@ -1946,7 +1948,7 @@
1946
1948
  * Static helper which returns a successful DispatchResult
1947
1949
  */
1948
1950
  static get Success() {
1949
- return new DispatchResult();
1951
+ return SUCCESS;
1950
1952
  }
1951
1953
  get isSuccessful() {
1952
1954
  return this.reasons.length === 0;
@@ -1959,6 +1961,7 @@
1959
1961
  return this.reasons.includes(reason);
1960
1962
  }
1961
1963
  }
1964
+ const SUCCESS = new DispatchResult();
1962
1965
  exports.CommandResult = void 0;
1963
1966
  (function (CommandResult) {
1964
1967
  CommandResult["Success"] = "Success";
@@ -2265,7 +2268,7 @@
2265
2268
  .normalize("NFD")
2266
2269
  .replace(/[\u0300-\u036f]/g, "");
2267
2270
  });
2268
- const expectBooleanValueError = (value) => _t("The function [[FUNCTION_NAME]] expects a boolean value, but '%s' is a text, and cannot be coerced to a number.", value);
2271
+ const expectBooleanValueError = (value) => _t("The function [[FUNCTION_NAME]] expects a boolean value, but '%s' is a text, and cannot be coerced to a boolean.", value);
2269
2272
  function toBoolean(data) {
2270
2273
  const value = toValue(data);
2271
2274
  switch (typeof value) {
@@ -7529,6 +7532,9 @@
7529
7532
  * Also useful for mocking a store.
7530
7533
  */
7531
7534
  inject(Store, instance) {
7535
+ if (this.dependencies.has(Store) && this.dependencies.get(Store) !== instance) {
7536
+ throw new Error(`Store ${Store.name} already has an instance`);
7537
+ }
7532
7538
  this.dependencies.set(Store, instance);
7533
7539
  }
7534
7540
  /**
@@ -11357,8 +11363,10 @@ stores.inject(MyMetaStore, storeInstance);
11357
11363
  };
11358
11364
  static components = {};
11359
11365
  onDoubleClick() {
11360
- this.env.model.dispatch("SELECT_FIGURE", { id: this.props.figure.id });
11361
- this.env.openSidePanel("ChartPanel");
11366
+ const result = this.env.model.dispatch("SELECT_FIGURE", { id: this.props.figure.id });
11367
+ if (result.isSuccessful) {
11368
+ this.env.openSidePanel("ChartPanel");
11369
+ }
11362
11370
  }
11363
11371
  get chartType() {
11364
11372
  return this.env.model.getters.getChartType(this.props.figure.id);
@@ -13915,6 +13923,12 @@ stores.inject(MyMetaStore, storeInstance);
13915
13923
  let { col, row } = env.model.getters.getActivePosition();
13916
13924
  env.getStore(CellPopoverStore).open({ col, row }, "LinkEditor");
13917
13925
  };
13926
+ const INSERT_LINK_NAME = (env) => {
13927
+ const sheetId = env.model.getters.getActiveSheetId();
13928
+ const { col, row } = env.model.getters.getActivePosition();
13929
+ const cell = env.model.getters.getEvaluatedCell({ sheetId, col, row });
13930
+ return cell && cell.link ? _t("Edit link") : _t("Insert link");
13931
+ };
13918
13932
  //------------------------------------------------------------------------------
13919
13933
  // Filters action
13920
13934
  //------------------------------------------------------------------------------
@@ -21721,6 +21735,68 @@ stores.inject(MyMetaStore, storeInstance);
21721
21735
  isExported: true,
21722
21736
  };
21723
21737
  // -----------------------------------------------------------------------------
21738
+ // INDEX
21739
+ // -----------------------------------------------------------------------------
21740
+ const INDIRECT = {
21741
+ description: _t("Returns the content of a cell, specified by a string."),
21742
+ args: [
21743
+ arg("reference (string)", _t("The range of cells from which the values are returned.")),
21744
+ arg("use_a1_notation (boolean, default=TRUE)", _t("A boolean indicating whether to use A1 style notation (TRUE) or R1C1 style notation (FALSE).")),
21745
+ ],
21746
+ returns: ["ANY"],
21747
+ compute: function (reference, useA1Notation = { value: true }) {
21748
+ let _reference = reference?.value?.toString();
21749
+ if (!_reference) {
21750
+ throw new InvalidReferenceError(_t("Reference should be defined."));
21751
+ }
21752
+ const _useA1Notation = toBoolean(useA1Notation);
21753
+ if (!_useA1Notation) {
21754
+ throw new EvaluationError(_t("R1C1 notation is not supported."));
21755
+ }
21756
+ const sheetId = this.__originSheetId;
21757
+ let originPosition;
21758
+ const __originCellXC = this.__originCellXC?.();
21759
+ if (__originCellXC) {
21760
+ const cellZone = toZone(__originCellXC);
21761
+ originPosition = {
21762
+ sheetId,
21763
+ col: cellZone.left,
21764
+ row: cellZone.top,
21765
+ };
21766
+ // The following line is used to reset the dependencies of the cell, to avoid
21767
+ // keeping dependencies from previous evaluation of the INDIRECT formula (i.e.
21768
+ // in case the reference has been changed).
21769
+ this.updateDependencies?.(originPosition);
21770
+ }
21771
+ const range = this.getters.getRangeFromSheetXC(sheetId, _reference);
21772
+ if (range === undefined || range.invalidXc || range.invalidSheetName) {
21773
+ throw new InvalidReferenceError();
21774
+ }
21775
+ if (originPosition) {
21776
+ this.addDependencies?.(originPosition, [range]);
21777
+ }
21778
+ const values = [];
21779
+ for (let col = range.zone.left; col <= range.zone.right; col++) {
21780
+ const colValues = [];
21781
+ for (let row = range.zone.top; row <= range.zone.bottom; row++) {
21782
+ const position = { sheetId: range.sheetId, col, row };
21783
+ // The below 'value' is typed as CellValue because the evaluateFormula will have to
21784
+ // evaluate a string containing the A1 reference of a single cell, so this will
21785
+ // return a CellValue.
21786
+ const value = this.getters.evaluateFormula(range.sheetId, toXC(col, row));
21787
+ const evaluatedCell = this.getters.getEvaluatedCell(position);
21788
+ colValues.push({
21789
+ ...evaluatedCell,
21790
+ value,
21791
+ });
21792
+ }
21793
+ values.push(colValues);
21794
+ }
21795
+ return values.length === 1 && values[0].length === 1 ? values[0][0] : values;
21796
+ },
21797
+ isExported: true,
21798
+ };
21799
+ // -----------------------------------------------------------------------------
21724
21800
  // LOOKUP
21725
21801
  // -----------------------------------------------------------------------------
21726
21802
  const LOOKUP = {
@@ -21926,6 +22002,7 @@ stores.inject(MyMetaStore, storeInstance);
21926
22002
  COLUMNS: COLUMNS,
21927
22003
  HLOOKUP: HLOOKUP,
21928
22004
  INDEX: INDEX,
22005
+ INDIRECT: INDIRECT,
21929
22006
  LOOKUP: LOOKUP,
21930
22007
  MATCH: MATCH,
21931
22008
  ROW: ROW,
@@ -22901,7 +22978,7 @@ stores.inject(MyMetaStore, storeInstance);
22901
22978
  };
22902
22979
  const insertFunction = {
22903
22980
  name: _t("Function"),
22904
- icon: "o-spreadsheet-Icon.SHOW_HIDE_FORMULA",
22981
+ icon: "o-spreadsheet-Icon.FORMULA",
22905
22982
  };
22906
22983
  const insertFunctionSum = {
22907
22984
  name: _t("SUM"),
@@ -23123,7 +23200,7 @@ stores.inject(MyMetaStore, storeInstance);
23123
23200
  })
23124
23201
  .add("insert_link", {
23125
23202
  ...insertLink,
23126
- name: _t("Insert link"),
23203
+ name: INSERT_LINK_NAME,
23127
23204
  sequence: 150,
23128
23205
  separator: true,
23129
23206
  });
@@ -23788,9 +23865,7 @@ stores.inject(MyMetaStore, storeInstance);
23788
23865
  isReadonlyAllowed: true,
23789
23866
  };
23790
23867
  const viewGridlines = {
23791
- name: (env) => env.model.getters.getGridLinesVisibility(env.model.getters.getActiveSheetId())
23792
- ? _t("Hide gridlines")
23793
- : _t("Show gridlines"),
23868
+ name: _t("Gridlines"),
23794
23869
  execute: (env) => {
23795
23870
  const sheetId = env.model.getters.getActiveSheetId();
23796
23871
  env.model.dispatch("SET_GRID_LINES_VISIBILITY", {
@@ -23798,13 +23873,16 @@ stores.inject(MyMetaStore, storeInstance);
23798
23873
  areGridLinesVisible: !env.model.getters.getGridLinesVisibility(sheetId),
23799
23874
  });
23800
23875
  },
23801
- icon: "o-spreadsheet-Icon.SHOW_HIDE_GRID",
23876
+ isActive: (env) => {
23877
+ const sheetId = env.model.getters.getActiveSheetId();
23878
+ return env.model.getters.getGridLinesVisibility(sheetId);
23879
+ },
23802
23880
  };
23803
23881
  const viewFormulas = {
23804
- name: (env) => env.model.getters.shouldShowFormulas() ? "Hide formulas" : _t("Show formulas"),
23882
+ name: _t("Formulas"),
23883
+ isActive: (env) => env.model.getters.shouldShowFormulas(),
23805
23884
  execute: (env) => env.model.dispatch("SET_FORMULA_VISIBILITY", { show: !env.model.getters.shouldShowFormulas() }),
23806
23885
  isReadonlyAllowed: true,
23807
- icon: "o-spreadsheet-Icon.SHOW_HIDE_FORMULA",
23808
23886
  };
23809
23887
  const createRemoveFilter = {
23810
23888
  name: (env) => selectionContainsFilter(env) ? _t("Remove selected filters") : _t("Create filter"),
@@ -24361,13 +24439,18 @@ stores.inject(MyMetaStore, storeInstance);
24361
24439
  isVisible: (env) => canUngroupHeaders(env, "ROW"),
24362
24440
  sequence: 20,
24363
24441
  })
24364
- .addChild("view_gridlines", ["view"], {
24442
+ .addChild("show", ["view"], {
24443
+ name: _t("Show"),
24444
+ sequence: 1,
24445
+ icon: "o-spreadsheet-Icon.SHOW",
24446
+ })
24447
+ .addChild("view_gridlines", ["view", "show"], {
24365
24448
  ...viewGridlines,
24366
- sequence: 15,
24449
+ sequence: 5,
24367
24450
  })
24368
- .addChild("view_formulas", ["view"], {
24451
+ .addChild("view_formulas", ["view", "show"], {
24369
24452
  ...viewFormulas,
24370
- sequence: 20,
24453
+ sequence: 10,
24371
24454
  })
24372
24455
  // ---------------------------------------------------------------------
24373
24456
  // INSERT MENU ITEMS
@@ -25350,6 +25433,17 @@ stores.inject(MyMetaStore, storeInstance);
25350
25433
  onValueSelected: Function,
25351
25434
  onValueHovered: Function,
25352
25435
  };
25436
+ autoCompleteListRef = owl.useRef("autoCompleteList");
25437
+ setup() {
25438
+ owl.useEffect(() => {
25439
+ const selectedIndex = this.props.selectedIndex;
25440
+ if (selectedIndex === undefined) {
25441
+ return;
25442
+ }
25443
+ const selectedElement = this.autoCompleteListRef.el?.children[selectedIndex];
25444
+ selectedElement?.scrollIntoView?.({ block: "nearest" });
25445
+ }, () => [this.props.selectedIndex, this.autoCompleteListRef.el]);
25446
+ }
25353
25447
  }
25354
25448
 
25355
25449
  class ContentEditableHelper {
@@ -25794,6 +25888,7 @@ stores.inject(MyMetaStore, storeInstance);
25794
25888
  position: absolute;
25795
25889
  margin: 1px 4px;
25796
25890
  pointer-events: none;
25891
+ overflow: auto;
25797
25892
 
25798
25893
  .o-semi-bold {
25799
25894
  /** FIXME: to remove in favor of Bootstrap
@@ -25853,7 +25948,10 @@ stores.inject(MyMetaStore, storeInstance);
25853
25948
  if (this.props.delimitation && this.props.rect) {
25854
25949
  const { x: cellX, y: cellY, height: cellHeight } = this.props.rect;
25855
25950
  const remainingHeight = this.props.delimitation.height - (cellY + cellHeight);
25951
+ assistantStyle["max-height"] = `${remainingHeight}px`;
25856
25952
  if (cellY > remainingHeight) {
25953
+ const availableSpaceAbove = cellY;
25954
+ assistantStyle["max-height"] = `${availableSpaceAbove}px`;
25857
25955
  // render top
25858
25956
  // We compensate 2 px of margin on the assistant style + 1px for design reasons
25859
25957
  assistantStyle.top = `-3px`;
@@ -29458,6 +29556,34 @@ stores.inject(MyMetaStore, storeInstance);
29458
29556
  }
29459
29557
  }
29460
29558
 
29559
+ class SidePanelStore extends SpreadsheetStore {
29560
+ isOpen = false;
29561
+ panelProps = {};
29562
+ componentTag = "";
29563
+ open(componentTag, panelProps = {}) {
29564
+ if (this.isOpen && componentTag !== this.componentTag) {
29565
+ this.panelProps?.onCloseSidePanel?.();
29566
+ }
29567
+ this.componentTag = componentTag;
29568
+ this.panelProps = panelProps;
29569
+ this.isOpen = true;
29570
+ }
29571
+ toggle(componentTag, panelProps) {
29572
+ if (this.isOpen && componentTag === this.componentTag) {
29573
+ this.close();
29574
+ }
29575
+ else {
29576
+ this.open(componentTag, panelProps);
29577
+ }
29578
+ }
29579
+ close() {
29580
+ this.panelProps.onCloseSidePanel?.();
29581
+ this.isOpen = false;
29582
+ this.panelProps = {};
29583
+ this.componentTag = "";
29584
+ }
29585
+ }
29586
+
29461
29587
  const registries$1 = {
29462
29588
  ROW: rowMenuRegistry,
29463
29589
  COL: colMenuRegistry,
@@ -29471,7 +29597,6 @@ stores.inject(MyMetaStore, storeInstance);
29471
29597
  class Grid extends owl.Component {
29472
29598
  static template = "o-spreadsheet-Grid";
29473
29599
  static props = {
29474
- sidePanelIsOpen: Boolean,
29475
29600
  exposeFocus: Function,
29476
29601
  };
29477
29602
  static components = {
@@ -29500,6 +29625,7 @@ stores.inject(MyMetaStore, storeInstance);
29500
29625
  onMouseWheel;
29501
29626
  canvasPosition;
29502
29627
  hoveredCell;
29628
+ sidePanel;
29503
29629
  setup() {
29504
29630
  this.highlightStore = useStore(HighlightStore);
29505
29631
  this.menuState = owl.useState({
@@ -29513,6 +29639,7 @@ stores.inject(MyMetaStore, storeInstance);
29513
29639
  this.composerStore = useStore(ComposerStore);
29514
29640
  this.composerFocusStore = useStore(ComposerFocusStore);
29515
29641
  this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
29642
+ this.sidePanel = useStore(SidePanelStore);
29516
29643
  owl.useChildSubEnv({ getPopoverContainerRect: () => this.getGridRect() });
29517
29644
  owl.useExternalListener(document.body, "cut", this.copy.bind(this, true));
29518
29645
  owl.useExternalListener(document.body, "copy", this.copy.bind(this, false));
@@ -29525,6 +29652,11 @@ stores.inject(MyMetaStore, storeInstance);
29525
29652
  this.hoveredCell.clear();
29526
29653
  });
29527
29654
  this.cellPopovers = useStore(CellPopoverStore);
29655
+ owl.useEffect(() => {
29656
+ if (!this.sidePanel.isOpen) {
29657
+ this.DOMFocusableElementStore.focus();
29658
+ }
29659
+ }, () => [this.sidePanel.isOpen]);
29528
29660
  }
29529
29661
  onCellHovered({ col, row }) {
29530
29662
  this.hoveredCell.hover({ col, row });
@@ -30901,6 +31033,7 @@ stores.inject(MyMetaStore, storeInstance);
30901
31033
  value: { type: Boolean, optional: true },
30902
31034
  className: { type: String, optional: true },
30903
31035
  name: { type: String, optional: true },
31036
+ title: { type: String, optional: true },
30904
31037
  onChange: Function,
30905
31038
  };
30906
31039
  static defaultProps = { value: false };
@@ -31912,6 +32045,35 @@ stores.inject(MyMetaStore, storeInstance);
31912
32045
  design: ScorecardChartDesignPanel,
31913
32046
  });
31914
32047
 
32048
+ class MainChartPanelStore extends SpreadsheetStore {
32049
+ sidePanel = this.get(SidePanelStore);
32050
+ figureId;
32051
+ panel = "configuration";
32052
+ constructor(get, figureId) {
32053
+ super(get);
32054
+ this.figureId = figureId;
32055
+ }
32056
+ handle(cmd) {
32057
+ switch (cmd.type) {
32058
+ case "DELETE_FIGURE":
32059
+ if (this.sidePanel.componentTag === "ChartPanel" && this.figureId === cmd.id) {
32060
+ this.sidePanel.close();
32061
+ }
32062
+ break;
32063
+ case "SELECT_FIGURE":
32064
+ if (cmd.id) {
32065
+ this.figureId = cmd.id;
32066
+ }
32067
+ else if (this.sidePanel.componentTag === "ChartPanel") {
32068
+ this.sidePanel.close();
32069
+ }
32070
+ }
32071
+ }
32072
+ activatePanel(panel) {
32073
+ this.panel = panel;
32074
+ }
32075
+ }
32076
+
31915
32077
  css /* scss */ `
31916
32078
  .o-chart {
31917
32079
  .o-panel {
@@ -31940,37 +32102,19 @@ stores.inject(MyMetaStore, storeInstance);
31940
32102
  static template = "o-spreadsheet-ChartPanel";
31941
32103
  static components = { Section };
31942
32104
  static props = { onCloseSidePanel: Function };
31943
- state;
32105
+ store;
31944
32106
  get figureId() {
31945
- return this.state.figureId;
32107
+ return this.store.figureId;
31946
32108
  }
31947
32109
  setup() {
31948
- const selectedFigureId = this.env.model.getters.getSelectedFigureId();
31949
- if (!selectedFigureId) {
31950
- this.props.onCloseSidePanel();
31951
- return;
31952
- }
31953
- this.state = owl.useState({
31954
- panel: "configuration",
31955
- figureId: selectedFigureId,
31956
- });
31957
- owl.onWillUpdateProps(() => {
31958
- const selectedFigureId = this.env.model.getters.getSelectedFigureId();
31959
- if (selectedFigureId && selectedFigureId !== this.state.figureId) {
31960
- this.state.figureId = selectedFigureId;
31961
- }
31962
- if (!this.env.model.getters.isChartDefined(this.figureId)) {
31963
- this.props.onCloseSidePanel();
31964
- return;
31965
- }
31966
- });
32110
+ this.store = useLocalStore(MainChartPanelStore, this.env.model.getters.getSelectedFigureId());
31967
32111
  }
31968
32112
  updateChart(figureId, updateDefinition) {
31969
32113
  if (figureId !== this.figureId) {
31970
32114
  return;
31971
32115
  }
31972
32116
  const definition = {
31973
- ...this.getChartDefinition(),
32117
+ ...this.getChartDefinition(this.figureId),
31974
32118
  ...updateDefinition,
31975
32119
  };
31976
32120
  return this.env.model.dispatch("UPDATE_CHART", {
@@ -31984,7 +32128,7 @@ stores.inject(MyMetaStore, storeInstance);
31984
32128
  return;
31985
32129
  }
31986
32130
  const definition = {
31987
- ...this.getChartDefinition(),
32131
+ ...this.getChartDefinition(this.figureId),
31988
32132
  ...updateDefinition,
31989
32133
  };
31990
32134
  return this.env.model.canDispatch("UPDATE_CHART", {
@@ -31994,6 +32138,9 @@ stores.inject(MyMetaStore, storeInstance);
31994
32138
  });
31995
32139
  }
31996
32140
  onTypeChange(type) {
32141
+ if (!this.figureId) {
32142
+ return;
32143
+ }
31997
32144
  const context = this.env.model.getters.getContextCreationChart(this.figureId);
31998
32145
  if (!context) {
31999
32146
  throw new Error("Chart not defined.");
@@ -32006,6 +32153,9 @@ stores.inject(MyMetaStore, storeInstance);
32006
32153
  });
32007
32154
  }
32008
32155
  get chartPanel() {
32156
+ if (!this.figureId) {
32157
+ throw new Error("Chart not defined.");
32158
+ }
32009
32159
  const type = this.env.model.getters.getChartType(this.figureId);
32010
32160
  if (!type) {
32011
32161
  throw new Error("Chart not defined.");
@@ -32016,15 +32166,12 @@ stores.inject(MyMetaStore, storeInstance);
32016
32166
  }
32017
32167
  return chartPanel;
32018
32168
  }
32019
- getChartDefinition(figureId = this.figureId) {
32169
+ getChartDefinition(figureId) {
32020
32170
  return this.env.model.getters.getChartDefinition(figureId);
32021
32171
  }
32022
32172
  get chartTypes() {
32023
32173
  return getChartTypes();
32024
32174
  }
32025
- activatePanel(panel) {
32026
- this.state.panel = panel;
32027
- }
32028
32175
  }
32029
32176
 
32030
32177
  const BORDER_COLOR = "#8B008B";
@@ -32118,7 +32265,7 @@ stores.inject(MyMetaStore, storeInstance);
32118
32265
  }
32119
32266
  finalize() {
32120
32267
  if (this.isSearchDirty) {
32121
- this.refreshSearch();
32268
+ this.refreshSearch(false);
32122
32269
  this.isSearchDirty = false;
32123
32270
  }
32124
32271
  }
@@ -32150,10 +32297,10 @@ stores.inject(MyMetaStore, storeInstance);
32150
32297
  /**
32151
32298
  * refresh the matches according to the current search options
32152
32299
  */
32153
- refreshSearch() {
32300
+ refreshSearch(jumpToMatchSheet = true) {
32154
32301
  this.selectedMatchIndex = null;
32155
32302
  this.findMatches();
32156
- this.selectNextCell(Direction.current);
32303
+ this.selectNextCell(Direction.current, jumpToMatchSheet);
32157
32304
  }
32158
32305
  getSheetsInSearchOrder() {
32159
32306
  switch (this.searchOptions.searchScope) {
@@ -32223,7 +32370,7 @@ stores.inject(MyMetaStore, storeInstance);
32223
32370
  * It is also used to keep coherence between the selected searchMatch
32224
32371
  * and selectedMatchIndex.
32225
32372
  */
32226
- selectNextCell(indexChange) {
32373
+ selectNextCell(indexChange, jumpToMatchSheet = true) {
32227
32374
  const matches = this.searchMatches;
32228
32375
  if (!matches.length) {
32229
32376
  this.selectedMatchIndex = null;
@@ -32249,7 +32396,7 @@ stores.inject(MyMetaStore, storeInstance);
32249
32396
  this.selectedMatchIndex = nextIndex;
32250
32397
  const selectedMatch = matches[nextIndex];
32251
32398
  // Switch to the sheet where the match is located
32252
- if (this.getters.getActiveSheetId() !== selectedMatch.sheetId) {
32399
+ if (jumpToMatchSheet && this.getters.getActiveSheetId() !== selectedMatch.sheetId) {
32253
32400
  this.model.dispatch("ACTIVATE_SHEET", {
32254
32401
  sheetIdFrom: this.getters.getActiveSheetId(),
32255
32402
  sheetIdTo: selectedMatch.sheetId,
@@ -36966,22 +37113,7 @@ stores.inject(MyMetaStore, storeInstance);
36966
37113
  }
36967
37114
  }
36968
37115
  export(data) {
36969
- // Borders
36970
- let borderId = 0;
36971
37116
  const borders = {};
36972
- /**
36973
- * Get the id of the given border. If the border does not exist, it creates
36974
- * one.
36975
- */
36976
- function getBorderId(border) {
36977
- for (let [key, value] of Object.entries(borders)) {
36978
- if (deepEquals(value, border)) {
36979
- return parseInt(key, 10);
36980
- }
36981
- }
36982
- borders[++borderId] = border;
36983
- return borderId;
36984
- }
36985
37117
  for (let sheet of data.sheets) {
36986
37118
  for (let col = 0; col < sheet.colNumber; col++) {
36987
37119
  for (let row = 0; row < sheet.rowNumber; row++) {
@@ -36989,7 +37121,7 @@ stores.inject(MyMetaStore, storeInstance);
36989
37121
  if (border) {
36990
37122
  const xc = toXC(col, row);
36991
37123
  const cell = sheet.cells[xc];
36992
- const borderId = getBorderId(border);
37124
+ const borderId = getItemId(border, borders);
36993
37125
  if (cell) {
36994
37126
  cell.border = borderId;
36995
37127
  }
@@ -37686,9 +37818,9 @@ stores.inject(MyMetaStore, storeInstance);
37686
37818
  allowDispatch(cmd) {
37687
37819
  switch (cmd.type) {
37688
37820
  case "UPDATE_CELL":
37689
- return this.checkCellOutOfSheet(cmd);
37821
+ return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessUpdateCell);
37690
37822
  case "CLEAR_CELL":
37691
- return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
37823
+ return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessClearCell);
37692
37824
  default:
37693
37825
  return "Success" /* CommandResult.Success */;
37694
37826
  }
@@ -37858,8 +37990,8 @@ stores.inject(MyMetaStore, storeInstance);
37858
37990
  }
37859
37991
  removeDefaultStyleValues(style) {
37860
37992
  const cleanedStyle = { ...style };
37861
- for (const [property, defaultValue] of Object.entries(DEFAULT_STYLE)) {
37862
- if (cleanedStyle[property] === defaultValue) {
37993
+ for (const property in DEFAULT_STYLE) {
37994
+ if (cleanedStyle[property] === DEFAULT_STYLE[property]) {
37863
37995
  delete cleanedStyle[property];
37864
37996
  }
37865
37997
  }
@@ -38015,10 +38147,7 @@ stores.inject(MyMetaStore, storeInstance);
38015
38147
  else {
38016
38148
  style = before ? before.style : undefined;
38017
38149
  }
38018
- const locale = this.getters.getLocale();
38019
- let format = ("format" in after ? after.format : before && before.format) ||
38020
- detectDateFormat(afterContent, locale) ||
38021
- detectNumberFormat(afterContent);
38150
+ const format = "format" in after ? after.format : before && before.format;
38022
38151
  /* Read the following IF as:
38023
38152
  * we need to remove the cell if it is completely empty, but we can know if it completely empty if:
38024
38153
  * - the command says the new content is empty and has no border/format/style
@@ -38059,6 +38188,7 @@ stores.inject(MyMetaStore, storeInstance);
38059
38188
  }
38060
38189
  createLiteralCell(id, content, format, style) {
38061
38190
  const locale = this.getters.getLocale();
38191
+ format = format || detectDateFormat(content, locale) || detectNumberFormat(content);
38062
38192
  if (format !== PLAIN_TEXT_FORMAT && !isEvaluationError(content)) {
38063
38193
  content = toString(parseLiteral(content, locale));
38064
38194
  }
@@ -38131,6 +38261,18 @@ stores.inject(MyMetaStore, storeInstance);
38131
38261
  }
38132
38262
  return "Success" /* CommandResult.Success */;
38133
38263
  }
38264
+ checkUselessUpdateCell(cmd) {
38265
+ const cell = this.getters.getCell(cmd);
38266
+ const hasContent = "content" in cmd || "formula" in cmd;
38267
+ const hasStyle = "style" in cmd;
38268
+ const hasFormat = "format" in cmd;
38269
+ if ((!hasContent || cell?.content === cmd.content) &&
38270
+ (!hasStyle || deepEquals(cell?.style, cmd.style)) &&
38271
+ (!hasFormat || cell?.format === cmd.format)) {
38272
+ return "NoChanges" /* CommandResult.NoChanges */;
38273
+ }
38274
+ return "Success" /* CommandResult.Success */;
38275
+ }
38134
38276
  }
38135
38277
  class FormulaCellWithDependencies {
38136
38278
  id;
@@ -42946,7 +43088,15 @@ stores.inject(MyMetaStore, storeInstance);
42946
43088
  if (!this.rTrees[sheetId]) {
42947
43089
  return;
42948
43090
  }
42949
- this.rTrees[sheetId].remove(item, deepEquals);
43091
+ this.rTrees[sheetId].remove(item, this.rtreeItemComparer);
43092
+ }
43093
+ rtreeItemComparer(left, right) {
43094
+ return (left.data == right.data &&
43095
+ left.boundingBox.sheetId === right.boundingBox.sheetId &&
43096
+ left.boundingBox?.zone.left === right.boundingBox.zone.left &&
43097
+ left.boundingBox?.zone.top === right.boundingBox.zone.top &&
43098
+ left.boundingBox?.zone.right === right.boundingBox.zone.right &&
43099
+ left.boundingBox?.zone.bottom === right.boundingBox.zone.bottom);
42950
43100
  }
42951
43101
  }
42952
43102
  /**
@@ -43024,7 +43174,7 @@ stores.inject(MyMetaStore, storeInstance);
43024
43174
  const queue = Array.from(ranges).reverse();
43025
43175
  while (queue.length > 0) {
43026
43176
  const range = queue.pop();
43027
- visited.add(...this.encoder.encodeBoundingBox(range));
43177
+ visited.addMany(this.encoder.encodeBoundingBox(range));
43028
43178
  const impactedPositionIds = this.rTree.search(range).map((dep) => dep.data);
43029
43179
  for (const positionId of impactedPositionIds) {
43030
43180
  if (!visited.has(positionId)) {
@@ -43032,7 +43182,7 @@ stores.inject(MyMetaStore, storeInstance);
43032
43182
  }
43033
43183
  }
43034
43184
  }
43035
- visited.delete(...ranges.flatMap((r) => this.encoder.encodeBoundingBox(r)));
43185
+ visited.deleteMany(ranges.flatMap((r) => this.encoder.encodeBoundingBox(r)));
43036
43186
  return visited;
43037
43187
  }
43038
43188
  }
@@ -43118,6 +43268,7 @@ stores.inject(MyMetaStore, storeInstance);
43118
43268
  const MAX_ITERATION = 30;
43119
43269
  const ERROR_CYCLE_CELL = createEvaluatedCell(new CircularDependencyError());
43120
43270
  const EMPTY_CELL = createEvaluatedCell({ value: null });
43271
+ const EVAL_CONTEXT_INDEX = 2;
43121
43272
  class Evaluator {
43122
43273
  context;
43123
43274
  getters;
@@ -43163,17 +43314,24 @@ stores.inject(MyMetaStore, storeInstance);
43163
43314
  const dependencies = this.getDirectDependencies(positionId);
43164
43315
  this.formulaDependencies().addDependencies(positionId, dependencies);
43165
43316
  }
43317
+ addDependencies(position, dependencies) {
43318
+ const positionId = this.encoder.encode(position);
43319
+ this.formulaDependencies().addDependencies(positionId, dependencies);
43320
+ }
43166
43321
  updateCompilationParameters() {
43167
43322
  // rebuild the compilation parameters (with a clean cache)
43168
43323
  this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
43324
+ this.compilationParams[EVAL_CONTEXT_INDEX].updateDependencies =
43325
+ this.updateDependencies.bind(this);
43326
+ this.compilationParams[EVAL_CONTEXT_INDEX].addDependencies = this.addDependencies.bind(this);
43169
43327
  }
43170
43328
  evaluateCells(positions) {
43171
43329
  const cells = positions.map((p) => this.encoder.encode(p));
43172
43330
  const cellsToCompute = new JetSet(cells);
43173
43331
  const arrayFormulasPositionIds = this.getArrayFormulasImpactedByChangesOf(cells);
43174
- cellsToCompute.add(...this.getCellsDependingOn(cells));
43175
- cellsToCompute.add(...arrayFormulasPositionIds);
43176
- cellsToCompute.add(...this.getCellsDependingOn(arrayFormulasPositionIds));
43332
+ cellsToCompute.addMany(this.getCellsDependingOn(cells));
43333
+ cellsToCompute.addMany(arrayFormulasPositionIds);
43334
+ cellsToCompute.addMany(this.getCellsDependingOn(arrayFormulasPositionIds));
43177
43335
  this.evaluate(cellsToCompute);
43178
43336
  }
43179
43337
  getArrayFormulasImpactedByChangesOf(positionIds) {
@@ -43187,7 +43345,7 @@ stores.inject(MyMetaStore, storeInstance);
43187
43345
  }
43188
43346
  if (!content) {
43189
43347
  // The previous content could have blocked some array formulas
43190
- impactedPositionIds.add(...this.getArrayFormulasBlockedByOrSpreadingOn(positionId));
43348
+ impactedPositionIds.addMany(this.getArrayFormulasBlockedByOrSpreadingOn(positionId));
43191
43349
  }
43192
43350
  }
43193
43351
  return impactedPositionIds;
@@ -43239,7 +43397,7 @@ stores.inject(MyMetaStore, storeInstance);
43239
43397
  }
43240
43398
  const arrayFormulas = this.spreadingRelations.getFormulaPositionsSpreadingOn(positionId);
43241
43399
  const cells = new JetSet(arrayFormulas);
43242
- cells.add(...this.getCellsDependingOn(arrayFormulas));
43400
+ cells.addMany(this.getCellsDependingOn(arrayFormulas));
43243
43401
  return cells;
43244
43402
  }
43245
43403
  nextPositionsToUpdate = new JetSet();
@@ -43367,7 +43525,7 @@ stores.inject(MyMetaStore, storeInstance);
43367
43525
  this.setEvaluatedCell(positionId, evaluatedCell);
43368
43526
  // check if formula dependencies present in the spread zone
43369
43527
  // if so, they need to be recomputed
43370
- this.nextPositionsToUpdate.add(...this.getCellsDependingOn([positionId]));
43528
+ this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([positionId]));
43371
43529
  };
43372
43530
  }
43373
43531
  invalidateSpreading(positionId) {
@@ -43382,8 +43540,8 @@ stores.inject(MyMetaStore, storeInstance);
43382
43540
  continue;
43383
43541
  }
43384
43542
  this.evaluatedCells.delete(child);
43385
- this.nextPositionsToUpdate.add(...this.getCellsDependingOn([child]));
43386
- this.nextPositionsToUpdate.add(...this.getArrayFormulasBlockedByOrSpreadingOn(child));
43543
+ this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([child]));
43544
+ this.nextPositionsToUpdate.addMany(this.getArrayFormulasBlockedByOrSpreadingOn(child));
43387
43545
  }
43388
43546
  this.spreadingRelations.removeNode(positionId);
43389
43547
  }
@@ -43512,15 +43670,15 @@ stores.inject(MyMetaStore, storeInstance);
43512
43670
  }
43513
43671
  }
43514
43672
  function updateEvalContextAndExecute(compiledFormula, compilationParams, sheetId, cellId) {
43515
- compilationParams[2].__originCellXC = lazy(() => {
43673
+ compilationParams[EVAL_CONTEXT_INDEX].__originCellXC = lazy(() => {
43516
43674
  if (!cellId) {
43517
43675
  return undefined;
43518
43676
  }
43519
43677
  // compute the value lazily for performance reasons
43520
- const position = compilationParams[2].getters.getCellPosition(cellId);
43678
+ const position = compilationParams[EVAL_CONTEXT_INDEX].getters.getCellPosition(cellId);
43521
43679
  return toXC(position.col, position.row);
43522
43680
  });
43523
- compilationParams[2].__originSheetId = sheetId;
43681
+ compilationParams[EVAL_CONTEXT_INDEX].__originSheetId = sheetId;
43524
43682
  return compiledFormula.execute(compiledFormula.dependencies, ...compilationParams);
43525
43683
  }
43526
43684
 
@@ -43850,8 +44008,13 @@ stores.inject(MyMetaStore, storeInstance);
43850
44008
  */
43851
44009
  class CustomColorsPlugin extends UIPlugin {
43852
44010
  customColors = {};
44011
+ configCustomColors;
43853
44012
  shouldUpdateColors = false;
43854
44013
  static getters = ["getCustomColors"];
44014
+ constructor(config) {
44015
+ super(config);
44016
+ this.configCustomColors = config.customColors;
44017
+ }
43855
44018
  handle(cmd) {
43856
44019
  switch (cmd.type) {
43857
44020
  case "UPDATE_CELL":
@@ -43873,7 +44036,7 @@ stores.inject(MyMetaStore, storeInstance);
43873
44036
  }
43874
44037
  }
43875
44038
  getCustomColors() {
43876
- let usedColors = [];
44039
+ let usedColors = this.configCustomColors;
43877
44040
  for (const sheetId of this.getters.getSheetIds()) {
43878
44041
  usedColors = usedColors.concat(this.getColorsFromCells(sheetId), this.getFormattingColors(sheetId), this.getChartColors(sheetId));
43879
44042
  }
@@ -46846,7 +47009,7 @@ stores.inject(MyMetaStore, storeInstance);
46846
47009
  "getCellText",
46847
47010
  "getCellMultiLineText",
46848
47011
  "getContiguousZone",
46849
- "isCellEmpty",
47012
+ "isEvaluatedCellEmpty",
46850
47013
  ];
46851
47014
  ctx = document.createElement("canvas").getContext("2d");
46852
47015
  // ---------------------------------------------------------------------------
@@ -46974,14 +47137,26 @@ stores.inject(MyMetaStore, storeInstance);
46974
47137
  return zone;
46975
47138
  }
46976
47139
  /**
46977
- * Check if a cell is empty. If the cell is part of a merge,
46978
- * check if the merge containing the cell is empty.
47140
+ * Checks if a cell evaluated value is empty. If the cell is part of a merge,
47141
+ * the check applies to the main cell of the merge.
46979
47142
  */
46980
- isCellEmpty(position) {
47143
+ //TODORAR this does not fit the new scheme where a cell with an empty string is not empty anymore
47144
+ // this means the navigation was acually altered with the recent change
47145
+ // remove the getter and put it back in selection processor as nobody uses it
47146
+ isEvaluatedCellEmpty(position) {
46981
47147
  const mainPosition = this.getters.getMainCellPosition(position);
46982
47148
  const cell = this.getters.getEvaluatedCell(mainPosition);
46983
47149
  return cell.type === CellValueType.empty;
46984
47150
  }
47151
+ /**
47152
+ * Checks if a cell is empty (i.e. does not have a content or a formula does not spread over it).
47153
+ * If the cell is part of a merge, the check applies to the main cell of the merge.
47154
+ */
47155
+ isCellEmpty(position) {
47156
+ const mainPosition = this.getters.getMainCellPosition(position);
47157
+ return !(this.getters.getCorrespondingFormulaCell(mainPosition) ||
47158
+ this.getters.getCell(mainPosition)?.content);
47159
+ }
46985
47160
  getColMaxWidth(sheetId, index) {
46986
47161
  const cellsPositions = positions(this.getters.getColsZone(sheetId, index, index));
46987
47162
  const sizes = cellsPositions.map((position) => this.getCellWidth({ sheetId, ...position }));
@@ -51516,7 +51691,7 @@ stores.inject(MyMetaStore, storeInstance);
51516
51691
  if (ev.key === "Enter") {
51517
51692
  ev.preventDefault();
51518
51693
  ev.stopPropagation();
51519
- this.store.selectNextMatch();
51694
+ ev.shiftKey ? this.store.selectPreviousMatch() : this.store.selectNextMatch();
51520
51695
  }
51521
51696
  }
51522
51697
  onKeydownReplace(ev) {
@@ -53212,22 +53387,20 @@ stores.inject(MyMetaStore, storeInstance);
53212
53387
  `;
53213
53388
  class SidePanel extends owl.Component {
53214
53389
  static template = "o-spreadsheet-SidePanel";
53215
- static props = {
53216
- component: String,
53217
- panelProps: { type: Object, optional: true },
53218
- onCloseSidePanel: Function,
53219
- };
53220
- state;
53390
+ static props = {};
53391
+ sidePanelStore;
53221
53392
  setup() {
53222
- this.state = owl.useState({
53223
- panel: sidePanelRegistry.get(this.props.component),
53224
- });
53225
- owl.onWillUpdateProps((nextProps) => (this.state.panel = sidePanelRegistry.get(nextProps.component)));
53393
+ this.sidePanelStore = useStore(SidePanelStore);
53394
+ }
53395
+ get panel() {
53396
+ return sidePanelRegistry.get(this.sidePanelStore.componentTag);
53397
+ }
53398
+ close() {
53399
+ this.sidePanelStore.close();
53226
53400
  }
53227
53401
  getTitle() {
53228
- return typeof this.state.panel.title === "function"
53229
- ? this.state.panel.title(this.env)
53230
- : this.state.panel.title;
53402
+ const panel = this.panel;
53403
+ return typeof panel.title === "function" ? panel.title(this.env) : panel.title;
53231
53404
  }
53232
53405
  }
53233
53406
 
@@ -54161,10 +54334,13 @@ stores.inject(MyMetaStore, storeInstance);
54161
54334
  }
54162
54335
  setup() {
54163
54336
  const stores = useStoreProvider();
54164
- this.sidePanel = owl.useState({ isOpen: false, panelProps: {} });
54337
+ stores.inject(ModelStore, this.model);
54338
+ this.notificationStore = useStore(NotificationStore);
54339
+ this.composerFocusStore = useStore(ComposerFocusStore);
54340
+ this.sidePanel = useStore(SidePanelStore);
54165
54341
  this.keyDownMapping = {
54166
- "CTRL+H": () => this.toggleSidePanel("FindAndReplace", {}),
54167
- "CTRL+F": () => this.toggleSidePanel("FindAndReplace", {}),
54342
+ "CTRL+H": () => this.sidePanel.toggle("FindAndReplace", {}),
54343
+ "CTRL+F": () => this.sidePanel.toggle("FindAndReplace", {}),
54168
54344
  };
54169
54345
  const fileStore = this.model.config.external.fileStore;
54170
54346
  owl.useSubEnv({
@@ -54173,11 +54349,10 @@ stores.inject(MyMetaStore, storeInstance);
54173
54349
  loadCurrencies: this.model.config.external.loadCurrencies,
54174
54350
  loadLocales: this.model.config.external.loadLocales,
54175
54351
  isDashboard: () => this.model.getters.isDashboard(),
54176
- openSidePanel: this.openSidePanel.bind(this),
54177
- toggleSidePanel: this.toggleSidePanel.bind(this),
54352
+ openSidePanel: this.sidePanel.open.bind(this.sidePanel),
54353
+ toggleSidePanel: this.sidePanel.toggle.bind(this.sidePanel),
54178
54354
  clipboard: this.env.clipboard || instantiateClipboard(),
54179
54355
  startCellEdition: (content) => this.composerFocusStore.focusGridComposerCell(content),
54180
- //TODORAR: make a store out of this
54181
54356
  });
54182
54357
  owl.useEffect(() => {
54183
54358
  /**
@@ -54206,9 +54381,6 @@ stores.inject(MyMetaStore, storeInstance);
54206
54381
  owl.onPatched(() => {
54207
54382
  this.checkViewportSize();
54208
54383
  });
54209
- stores.inject(ModelStore, this.model);
54210
- this.notificationStore = useStore(NotificationStore);
54211
- this.composerFocusStore = useStore(ComposerFocusStore);
54212
54384
  }
54213
54385
  bindModelEvents() {
54214
54386
  this.model.on("update", this, () => this.render(true));
@@ -54241,28 +54413,6 @@ stores.inject(MyMetaStore, storeInstance);
54241
54413
  this.isViewportTooSmall = false;
54242
54414
  }
54243
54415
  }
54244
- openSidePanel(panel, panelProps) {
54245
- if (this.sidePanel.isOpen && panel !== this.sidePanel.component) {
54246
- this.sidePanel.panelProps?.onCloseSidePanel?.();
54247
- }
54248
- this.sidePanel.component = panel;
54249
- this.sidePanel.panelProps = panelProps;
54250
- this.sidePanel.isOpen = true;
54251
- }
54252
- closeSidePanel() {
54253
- this.sidePanel.isOpen = false;
54254
- this.focusGrid();
54255
- this.sidePanel.panelProps?.onCloseSidePanel?.();
54256
- }
54257
- toggleSidePanel(panel, panelProps) {
54258
- if (this.sidePanel.isOpen && panel === this.sidePanel.component) {
54259
- this.sidePanel.isOpen = false;
54260
- this.focusGrid();
54261
- }
54262
- else {
54263
- this.openSidePanel(panel, panelProps);
54264
- }
54265
- }
54266
54416
  focusGrid() {
54267
54417
  if (!this._focusGrid) {
54268
54418
  return;
@@ -55691,8 +55841,8 @@ stores.inject(MyMetaStore, storeInstance);
55691
55841
  let currentPosition = startPosition;
55692
55842
  // If both the current cell and the next cell are not empty, we want to go to the end of the cluster
55693
55843
  const nextCellPosition = this.getNextCellPosition(startPosition, dim, dir);
55694
- let mode = !this.getters.isCellEmpty({ ...currentPosition, sheetId }) &&
55695
- !this.getters.isCellEmpty({ ...nextCellPosition, sheetId })
55844
+ let mode = !this.isCellSkippableInCluster({ ...currentPosition, sheetId }) &&
55845
+ !this.isCellSkippableInCluster({ ...nextCellPosition, sheetId })
55696
55846
  ? "endOfCluster"
55697
55847
  : "nextCluster";
55698
55848
  while (true) {
@@ -55702,7 +55852,7 @@ stores.inject(MyMetaStore, storeInstance);
55702
55852
  currentPosition.row === nextCellPosition.row) {
55703
55853
  break;
55704
55854
  }
55705
- const isNextCellEmpty = this.getters.isCellEmpty({ ...nextCellPosition, sheetId });
55855
+ const isNextCellEmpty = this.isCellSkippableInCluster({ ...nextCellPosition, sheetId });
55706
55856
  if (mode === "endOfCluster" && isNextCellEmpty) {
55707
55857
  break;
55708
55858
  }
@@ -55733,6 +55883,11 @@ stores.inject(MyMetaStore, storeInstance);
55733
55883
  getPosition() {
55734
55884
  return { ...this.anchor.cell };
55735
55885
  }
55886
+ isCellSkippableInCluster(position) {
55887
+ const mainPosition = this.getters.getMainCellPosition(position);
55888
+ const cell = this.getters.getEvaluatedCell(mainPosition);
55889
+ return (cell.type === CellValueType.empty || (cell.type === CellValueType.text && cell.value === ""));
55890
+ }
55736
55891
  }
55737
55892
 
55738
55893
  class StateObserver {
@@ -57599,6 +57754,7 @@ stores.inject(MyMetaStore, storeInstance);
57599
57754
  snapshotRequested: false,
57600
57755
  notifyUI: (payload) => this.trigger("notify-ui", payload),
57601
57756
  raiseBlockingErrorUI: (text) => this.trigger("raise-error-ui", { text }),
57757
+ customColors: config.customColors || [],
57602
57758
  };
57603
57759
  }
57604
57760
  setupExternalConfig(external) {
@@ -57630,6 +57786,7 @@ stores.inject(MyMetaStore, storeInstance);
57630
57786
  uiActions: this.config,
57631
57787
  session: this.session,
57632
57788
  defaultCurrencyFormat: this.config.defaultCurrencyFormat,
57789
+ customColors: this.config.customColors || [],
57633
57790
  };
57634
57791
  }
57635
57792
  // ---------------------------------------------------------------------------
@@ -57929,6 +58086,10 @@ stores.inject(MyMetaStore, storeInstance);
57929
58086
  deepEquals,
57930
58087
  overlap,
57931
58088
  union,
58089
+ isInside,
58090
+ deepCopy,
58091
+ expandZoneOnInsertion,
58092
+ reduceZoneOnDeletion,
57932
58093
  };
57933
58094
  const links = {
57934
58095
  isMarkdownLink,
@@ -57983,6 +58144,9 @@ stores.inject(MyMetaStore, storeInstance);
57983
58144
  RendererStore,
57984
58145
  SelectionInputStore,
57985
58146
  SpreadsheetStore,
58147
+ useStore,
58148
+ useLocalStore,
58149
+ SidePanelStore,
57986
58150
  };
57987
58151
  function addFunction(functionName, functionDescription) {
57988
58152
  functionRegistry.add(functionName, functionDescription);
@@ -57995,7 +58159,9 @@ stores.inject(MyMetaStore, storeInstance);
57995
58159
  SECONDARY_COLOR,
57996
58160
  };
57997
58161
 
58162
+ exports.AbstractCellClipboardHandler = AbstractCellClipboardHandler;
57998
58163
  exports.AbstractChart = AbstractChart;
58164
+ exports.AbstractFigureClipboardHandler = AbstractFigureClipboardHandler;
57999
58165
  exports.CellErrorType = CellErrorType;
58000
58166
  exports.CorePlugin = CorePlugin;
58001
58167
  exports.DispatchResult = DispatchResult;
@@ -58035,9 +58201,9 @@ stores.inject(MyMetaStore, storeInstance);
58035
58201
  exports.tokenize = tokenize;
58036
58202
 
58037
58203
 
58038
- __info__.version = "17.2.0-alpha.4";
58039
- __info__.date = "2024-02-09T13:10:23.460Z";
58040
- __info__.hash = "1b33cf4";
58204
+ __info__.version = "17.2.0-alpha.5";
58205
+ __info__.date = "2024-02-16T14:27:52.323Z";
58206
+ __info__.hash = "0c69dd8";
58041
58207
 
58042
58208
 
58043
58209
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);