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