@odoo/o-spreadsheet 16.4.0-alpha.2 → 16.4.0-alpha.3

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.
@@ -5218,14 +5218,6 @@ function* iterateChildren(el) {
5218
5218
  }
5219
5219
  }
5220
5220
  }
5221
- function getElementScrollTop(el) {
5222
- return el?.scrollTop || 0;
5223
- }
5224
- function setElementScrollTop(el, scroll) {
5225
- if (!el)
5226
- return;
5227
- el.scrollTop = scroll;
5228
- }
5229
5221
  function getOpenedMenus() {
5230
5222
  return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
5231
5223
  }
@@ -17943,7 +17935,7 @@ class LineBarPieConfigPanel extends Component {
17943
17935
  return !!this.state.labelsDispatchResult?.isCancelledBecause(33 /* CommandResult.InvalidLabelRange */);
17944
17936
  }
17945
17937
  onUpdateDataSetsHaveTitle(ev) {
17946
- this.props.updateChart({
17938
+ this.props.updateChart(this.props.figureId, {
17947
17939
  dataSetsHaveTitle: ev.target.checked,
17948
17940
  });
17949
17941
  }
@@ -17956,7 +17948,7 @@ class LineBarPieConfigPanel extends Component {
17956
17948
  }
17957
17949
  onDataSeriesConfirmed() {
17958
17950
  this.dataSeriesRanges = spreadRange(this.dataSeriesRanges);
17959
- this.state.datasetDispatchResult = this.props.updateChart({
17951
+ this.state.datasetDispatchResult = this.props.updateChart(this.props.figureId, {
17960
17952
  dataSets: this.dataSeriesRanges,
17961
17953
  });
17962
17954
  }
@@ -17971,7 +17963,7 @@ class LineBarPieConfigPanel extends Component {
17971
17963
  this.labelRange = ranges[0];
17972
17964
  }
17973
17965
  onLabelRangeConfirmed() {
17974
- this.state.labelsDispatchResult = this.props.updateChart({
17966
+ this.state.labelsDispatchResult = this.props.updateChart(this.props.figureId, {
17975
17967
  labelRange: this.labelRange,
17976
17968
  });
17977
17969
  }
@@ -17979,7 +17971,7 @@ class LineBarPieConfigPanel extends Component {
17979
17971
  return this.labelRange || "";
17980
17972
  }
17981
17973
  onUpdateAggregated(ev) {
17982
- this.props.updateChart({
17974
+ this.props.updateChart(this.props.figureId, {
17983
17975
  aggregated: ev.target.checked,
17984
17976
  });
17985
17977
  }
@@ -18009,12 +18001,12 @@ LineBarPieConfigPanel.props = {
18009
18001
  class BarConfigPanel extends LineBarPieConfigPanel {
18010
18002
  static template = "o-spreadsheet-BarConfigPanel";
18011
18003
  onUpdateStacked(ev) {
18012
- this.props.updateChart({
18004
+ this.props.updateChart(this.props.figureId, {
18013
18005
  stacked: ev.target.checked,
18014
18006
  });
18015
18007
  }
18016
18008
  onUpdateAggregated(ev) {
18017
- this.props.updateChart({
18009
+ this.props.updateChart(this.props.figureId, {
18018
18010
  aggregated: ev.target.checked,
18019
18011
  });
18020
18012
  }
@@ -18351,17 +18343,17 @@ class LineBarPieDesignPanel extends Component {
18351
18343
  this.state.fillColorTool = !this.state.fillColorTool;
18352
18344
  }
18353
18345
  updateBackgroundColor(color) {
18354
- this.props.updateChart({
18346
+ this.props.updateChart(this.props.figureId, {
18355
18347
  background: color,
18356
18348
  });
18357
18349
  }
18358
18350
  updateTitle(ev) {
18359
- this.props.updateChart({
18351
+ this.props.updateChart(this.props.figureId, {
18360
18352
  title: ev.target.value,
18361
18353
  });
18362
18354
  }
18363
18355
  updateSelect(attr, ev) {
18364
- this.props.updateChart({
18356
+ this.props.updateChart(this.props.figureId, {
18365
18357
  [attr]: ev.target.value,
18366
18358
  });
18367
18359
  }
@@ -18394,7 +18386,7 @@ class GaugeChartConfigPanel extends Component {
18394
18386
  this.dataRange = ranges[0];
18395
18387
  }
18396
18388
  updateDataRange() {
18397
- this.state.dataRangeDispatchResult = this.props.updateChart({
18389
+ this.state.dataRangeDispatchResult = this.props.updateChart(this.props.figureId, {
18398
18390
  dataRange: this.dataRange,
18399
18391
  });
18400
18392
  }
@@ -18455,12 +18447,12 @@ class GaugeChartDesignPanel extends Component {
18455
18447
  }
18456
18448
  updateBackgroundColor(color) {
18457
18449
  this.state.openedMenu = undefined;
18458
- this.props.updateChart({
18450
+ this.props.updateChart(this.props.figureId, {
18459
18451
  background: color,
18460
18452
  });
18461
18453
  }
18462
18454
  updateTitle(ev) {
18463
- this.props.updateChart({
18455
+ this.props.updateChart(this.props.figureId, {
18464
18456
  title: ev.target.value,
18465
18457
  });
18466
18458
  }
@@ -18525,7 +18517,7 @@ class GaugeChartDesignPanel extends Component {
18525
18517
  }
18526
18518
  }
18527
18519
  updateSectionRule(sectionRule) {
18528
- this.state.sectionRuleDispatchResult = this.props.updateChart({
18520
+ this.state.sectionRuleDispatchResult = this.props.updateChart(this.props.figureId, {
18529
18521
  sectionRule,
18530
18522
  });
18531
18523
  }
@@ -18549,17 +18541,17 @@ class LineConfigPanel extends LineBarPieConfigPanel {
18549
18541
  return false;
18550
18542
  }
18551
18543
  onUpdateLabelsAsText(ev) {
18552
- this.props.updateChart({
18544
+ this.props.updateChart(this.props.figureId, {
18553
18545
  labelsAsText: ev.target.checked,
18554
18546
  });
18555
18547
  }
18556
18548
  onUpdateStacked(ev) {
18557
- this.props.updateChart({
18549
+ this.props.updateChart(this.props.figureId, {
18558
18550
  stacked: ev.target.checked,
18559
18551
  });
18560
18552
  }
18561
18553
  onUpdateAggregated(ev) {
18562
- this.props.updateChart({
18554
+ this.props.updateChart(this.props.figureId, {
18563
18555
  aggregated: ev.target.checked,
18564
18556
  });
18565
18557
  }
@@ -18595,7 +18587,7 @@ class ScorecardChartConfigPanel extends Component {
18595
18587
  this.keyValue = ranges[0];
18596
18588
  }
18597
18589
  updateKeyValueRange() {
18598
- this.state.keyValueDispatchResult = this.props.updateChart({
18590
+ this.state.keyValueDispatchResult = this.props.updateChart(this.props.figureId, {
18599
18591
  keyValue: this.keyValue,
18600
18592
  });
18601
18593
  }
@@ -18606,7 +18598,7 @@ class ScorecardChartConfigPanel extends Component {
18606
18598
  this.baseline = ranges[0];
18607
18599
  }
18608
18600
  updateBaselineRange() {
18609
- this.state.baselineDispatchResult = this.props.updateChart({
18601
+ this.state.baselineDispatchResult = this.props.updateChart(this.props.figureId, {
18610
18602
  baseline: this.baseline,
18611
18603
  });
18612
18604
  }
@@ -18614,7 +18606,7 @@ class ScorecardChartConfigPanel extends Component {
18614
18606
  return this.baseline || "";
18615
18607
  }
18616
18608
  updateBaselineMode(ev) {
18617
- this.props.updateChart({ baselineMode: ev.target.value });
18609
+ this.props.updateChart(this.props.figureId, { baselineMode: ev.target.value });
18618
18610
  }
18619
18611
  }
18620
18612
  ScorecardChartConfigPanel.props = {
@@ -18633,12 +18625,12 @@ class ScorecardChartDesignPanel extends Component {
18633
18625
  useExternalListener(window, "click", this.closeMenus);
18634
18626
  }
18635
18627
  updateTitle(ev) {
18636
- this.props.updateChart({
18628
+ this.props.updateChart(this.props.figureId, {
18637
18629
  title: ev.target.value,
18638
18630
  });
18639
18631
  }
18640
18632
  updateBaselineDescr(ev) {
18641
- this.props.updateChart({ baselineDescr: ev.target.value });
18633
+ this.props.updateChart(this.props.figureId, { baselineDescr: ev.target.value });
18642
18634
  }
18643
18635
  toggleColorPicker(colorPickerId) {
18644
18636
  if (this.state.openedColorPicker === colorPickerId) {
@@ -18651,13 +18643,13 @@ class ScorecardChartDesignPanel extends Component {
18651
18643
  setColor(color, colorPickerId) {
18652
18644
  switch (colorPickerId) {
18653
18645
  case "backgroundColor":
18654
- this.props.updateChart({ background: color });
18646
+ this.props.updateChart(this.props.figureId, { background: color });
18655
18647
  break;
18656
18648
  case "baselineColorDown":
18657
- this.props.updateChart({ baselineColorDown: color });
18649
+ this.props.updateChart(this.props.figureId, { baselineColorDown: color });
18658
18650
  break;
18659
18651
  case "baselineColorUp":
18660
- this.props.updateChart({ baselineColorUp: color });
18652
+ this.props.updateChart(this.props.figureId, { baselineColorUp: color });
18661
18653
  break;
18662
18654
  }
18663
18655
  this.closeMenus();
@@ -18722,13 +18714,9 @@ css /* scss */ `
18722
18714
  class ChartPanel extends Component {
18723
18715
  static template = "o-spreadsheet-ChartPanel";
18724
18716
  state;
18725
- shouldUpdateChart = true;
18726
18717
  get figureId() {
18727
18718
  return this.state.figureId;
18728
18719
  }
18729
- get sheetId() {
18730
- return this.state.sheetId;
18731
- }
18732
18720
  setup() {
18733
18721
  const selectedFigureId = this.env.model.getters.getSelectedFigureId();
18734
18722
  if (!selectedFigureId) {
@@ -18738,17 +18726,11 @@ class ChartPanel extends Component {
18738
18726
  this.state = useState({
18739
18727
  panel: "configuration",
18740
18728
  figureId: selectedFigureId,
18741
- sheetId: this.env.model.getters.getActiveSheetId(),
18742
18729
  });
18743
18730
  onWillUpdateProps(() => {
18744
18731
  const selectedFigureId = this.env.model.getters.getSelectedFigureId();
18745
18732
  if (selectedFigureId && selectedFigureId !== this.state.figureId) {
18746
18733
  this.state.figureId = selectedFigureId;
18747
- this.state.sheetId = this.env.model.getters.getActiveSheetId();
18748
- this.shouldUpdateChart = false;
18749
- }
18750
- else {
18751
- this.shouldUpdateChart = true;
18752
18734
  }
18753
18735
  if (!this.env.model.getters.isChartDefined(this.figureId)) {
18754
18736
  this.props.onCloseSidePanel();
@@ -18756,8 +18738,8 @@ class ChartPanel extends Component {
18756
18738
  }
18757
18739
  });
18758
18740
  }
18759
- updateChart(updateDefinition) {
18760
- if (!this.shouldUpdateChart) {
18741
+ updateChart(figureId, updateDefinition) {
18742
+ if (figureId !== this.figureId) {
18761
18743
  return;
18762
18744
  }
18763
18745
  const definition = {
@@ -18766,8 +18748,8 @@ class ChartPanel extends Component {
18766
18748
  };
18767
18749
  return this.env.model.dispatch("UPDATE_CHART", {
18768
18750
  definition,
18769
- id: this.figureId,
18770
- sheetId: this.sheetId,
18751
+ id: figureId,
18752
+ sheetId: this.env.model.getters.getFigureSheetId(figureId),
18771
18753
  });
18772
18754
  }
18773
18755
  onTypeChange(type) {
@@ -18779,7 +18761,7 @@ class ChartPanel extends Component {
18779
18761
  this.env.model.dispatch("UPDATE_CHART", {
18780
18762
  definition,
18781
18763
  id: this.figureId,
18782
- sheetId: this.sheetId,
18764
+ sheetId: this.env.model.getters.getFigureSheetId(this.figureId),
18783
18765
  });
18784
18766
  }
18785
18767
  get chartPanel() {
@@ -20575,12 +20557,23 @@ class ContentEditableHelper {
20575
20557
  */
20576
20558
  selectRange(start, end) {
20577
20559
  let selection = window.getSelection();
20578
- this.removeSelection();
20579
- let range = document.createRange();
20560
+ const { start: currentStart, end: currentEnd } = this.getCurrentSelection();
20561
+ if (currentStart === start && currentEnd === end) {
20562
+ return;
20563
+ }
20564
+ const currentRange = selection.getRangeAt(0);
20565
+ let range;
20566
+ if (this.el.contains(currentRange.startContainer)) {
20567
+ range = currentRange;
20568
+ }
20569
+ else {
20570
+ range = document.createRange();
20571
+ selection.removeAllRanges();
20572
+ selection.addRange(range);
20573
+ }
20580
20574
  if (start == end && start === 0) {
20581
20575
  range.setStart(this.el, 0);
20582
20576
  range.setEnd(this.el, 0);
20583
- selection.addRange(range);
20584
20577
  }
20585
20578
  else {
20586
20579
  const textLength = this.getText().length;
@@ -20596,7 +20589,6 @@ class ContentEditableHelper {
20596
20589
  let startNode = this.findChildAtCharacterIndex(start);
20597
20590
  let endNode = this.findChildAtCharacterIndex(end);
20598
20591
  range.setStart(startNode.node, startNode.offset);
20599
- selection.addRange(range);
20600
20592
  selection.extend(endNode.node, endNode.offset);
20601
20593
  }
20602
20594
  }
@@ -20636,26 +20628,54 @@ class ContentEditableHelper {
20636
20628
  return { node: previous, offset: usedCharacters };
20637
20629
  }
20638
20630
  /**
20639
- * Sets (or Replaces all) the text inside the root element in the form of distinctive
20631
+ * Sets (or Replaces all) the text inside the root element in the form of distinctive paragraphs and
20640
20632
  * span for each element provided in `contents`.
20641
20633
  *
20634
+ * The function will apply the diff between the current content and the new content to avoid the systematic
20635
+ * destruction of DOM elements which interferes with IME[1]
20636
+ *
20637
+ * Each line of text will be encapsulated in a paragraph element.
20642
20638
  * Each span will have its own fontcolor and specific class if provided in the HtmlContent object.
20639
+ *
20640
+ * [1] https://developer.mozilla.org/en-US/docs/Glossary/Input_method_editor
20643
20641
  */
20644
20642
  setText(contents) {
20645
- this.el.innerHTML = "";
20646
20643
  if (contents.length === 0) {
20644
+ this.removeAll();
20647
20645
  return;
20648
20646
  }
20649
- for (const line of contents) {
20650
- const p = document.createElement("p");
20651
- // Empty line
20652
- if (line.length === 0 || line.every((content) => !content.value && !content.class)) {
20653
- p.appendChild(document.createElement("br"));
20654
- this.el.appendChild(p);
20655
- continue;
20647
+ const childElements = Array.from(this.el.childNodes);
20648
+ const contentLength = contents.length;
20649
+ for (let i = 0; i < contentLength; i++) {
20650
+ const line = contents[i];
20651
+ const childElement = childElements[i];
20652
+ let newChild = false;
20653
+ let p;
20654
+ if (childElement && childElement.nodeName === "P") {
20655
+ p = childElement;
20656
20656
  }
20657
- for (const content of line) {
20657
+ else {
20658
+ newChild = true;
20659
+ p = document.createElement("p");
20660
+ }
20661
+ const lineLength = line.length;
20662
+ const existingChildren = Array.from(p.childNodes);
20663
+ for (let j = 0; j < lineLength; j++) {
20664
+ const content = line[j];
20665
+ const child = existingChildren[j];
20666
+ // child nodes can be multiple types of nodes: Span, Text, Div, etc...
20667
+ // We can only modify a node in place if it has the same type as the content
20668
+ // that we would insert, which are spans.
20669
+ // Otherwise, it means that the node has been input by the user, through the keyboard or a copy/paste
20670
+ // @ts-ignore (somehow required because jest does not like child.tagName despite the prior check)
20671
+ const childIsSpan = child && "tagName" in child && child.tagName === "SPAN";
20672
+ if (childIsSpan && compareContentToSpanElement(content, child)) {
20673
+ continue;
20674
+ }
20675
+ // this is an empty line in the content
20658
20676
  if (!content.value && !content.class) {
20677
+ if (child)
20678
+ p.removeChild(child);
20659
20679
  continue;
20660
20680
  }
20661
20681
  const span = document.createElement("span");
@@ -20664,9 +20684,38 @@ class ContentEditableHelper {
20664
20684
  if (content.class) {
20665
20685
  span.classList.add(content.class);
20666
20686
  }
20687
+ if (child) {
20688
+ p.replaceChild(span, child);
20689
+ }
20690
+ else {
20691
+ p.appendChild(span);
20692
+ }
20693
+ }
20694
+ if (existingChildren.length > lineLength) {
20695
+ for (let i = lineLength; i < existingChildren.length; i++) {
20696
+ p.removeChild(existingChildren[i]);
20697
+ }
20698
+ }
20699
+ // Empty line
20700
+ if (!p.hasChildNodes()) {
20701
+ const span = document.createElement("span");
20702
+ span.appendChild(document.createElement("br"));
20667
20703
  p.appendChild(span);
20668
20704
  }
20669
- this.el.appendChild(p);
20705
+ // replace p if necessary
20706
+ if (newChild) {
20707
+ if (childElement) {
20708
+ this.el.replaceChild(p, childElement);
20709
+ }
20710
+ else {
20711
+ this.el.appendChild(p);
20712
+ }
20713
+ }
20714
+ }
20715
+ if (childElements.length > contentLength) {
20716
+ for (let i = contentLength; i < childElements.length; i++) {
20717
+ this.el.removeChild(childElements[i]);
20718
+ }
20670
20719
  }
20671
20720
  }
20672
20721
  scrollSelectionIntoView() {
@@ -20676,13 +20725,6 @@ class ContentEditableHelper {
20676
20725
  const element = focusedNode instanceof HTMLElement ? focusedNode : focusedNode.parentElement;
20677
20726
  element?.scrollIntoView({ block: "nearest" });
20678
20727
  }
20679
- /**
20680
- * remove the current selection of the user
20681
- * */
20682
- removeSelection() {
20683
- let selection = window.getSelection();
20684
- selection.removeAllRanges();
20685
- }
20686
20728
  removeAll() {
20687
20729
  if (this.el) {
20688
20730
  while (this.el.firstChild) {
@@ -20812,6 +20854,14 @@ class ContentEditableHelper {
20812
20854
  }
20813
20855
  return text;
20814
20856
  }
20857
+ }
20858
+ function compareContentToSpanElement(content, node) {
20859
+ const contentColor = content.color ? toHex(content.color) : "";
20860
+ const nodeColor = node.style?.color ? toHex(node.style.color) : "";
20861
+ const sameColor = contentColor === nodeColor;
20862
+ const sameClass = deepEquals([content.class], [...node.classList]);
20863
+ const sameContent = node.innerText === content.value;
20864
+ return sameColor && sameClass && sameContent;
20815
20865
  }
20816
20866
 
20817
20867
  // -----------------------------------------------------------------------------
@@ -20957,7 +21007,6 @@ class Composer extends Component {
20957
21007
  functionDescription: {},
20958
21008
  argToFocus: 0,
20959
21009
  });
20960
- isKeyStillDown = false;
20961
21010
  compositionActive = false;
20962
21011
  get assistantStyle() {
20963
21012
  if (this.props.delimitation && this.props.rect) {
@@ -20992,21 +21041,18 @@ class Composer extends Component {
20992
21041
  F2: () => console.warn("Not implemented"),
20993
21042
  F4: this.processF4Key,
20994
21043
  Tab: (ev) => this.processTabKey(ev),
21044
+ " ": (ev) => this.processSpaceKey(ev),
20995
21045
  };
20996
21046
  setup() {
20997
21047
  onMounted(() => {
20998
21048
  const el = this.composerRef.el;
20999
21049
  this.contentHelper.updateEl(el);
21000
- this.processContent();
21001
- this.contentHelper.scrollSelectionIntoView();
21002
21050
  });
21003
21051
  onWillUnmount(() => {
21004
21052
  this.props.onComposerUnmounted?.();
21005
21053
  });
21006
- onPatched(() => {
21007
- if (!this.isKeyStillDown) {
21008
- this.processContent();
21009
- }
21054
+ useEffect(() => {
21055
+ this.processContent();
21010
21056
  });
21011
21057
  }
21012
21058
  // ---------------------------------------------------------------------------
@@ -21059,32 +21105,25 @@ class Composer extends Component {
21059
21105
  return;
21060
21106
  }
21061
21107
  }
21062
- else {
21063
- // when completing with tab, if there is no value to complete, the active cell will be moved to the right.
21064
- // we can't let the model think that it is for a ref selection.
21065
- // todo: check if this can be removed someday
21066
- this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
21067
- }
21068
21108
  const direction = ev.shiftKey ? "left" : "right";
21069
21109
  this.env.model.dispatch("STOP_EDITION");
21070
21110
  this.env.model.selection.moveAnchorCell(direction, 1);
21071
21111
  }
21112
+ processSpaceKey(ev) {
21113
+ if (ev.ctrlKey) {
21114
+ ev.preventDefault();
21115
+ ev.stopPropagation();
21116
+ this.showAutocomplete("");
21117
+ this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
21118
+ }
21119
+ }
21072
21120
  processEnterKey(ev) {
21073
21121
  ev.preventDefault();
21074
21122
  ev.stopPropagation();
21075
21123
  if (ev.altKey || ev.ctrlKey) {
21076
- const selection = this.contentHelper.getCurrentSelection();
21077
- const currentContent = this.env.model.getters.getCurrentContent();
21078
- const content = currentContent.slice(0, selection.start) + NEWLINE + currentContent.slice(selection.end);
21079
- this.env.model.dispatch("SET_CURRENT_CONTENT", {
21080
- content,
21081
- selection: { start: selection.start + 1, end: selection.start + 1 },
21082
- });
21083
- this.processContent();
21084
- this.contentHelper.scrollSelectionIntoView();
21124
+ this.composerRef.el?.dispatchEvent(new InputEvent("input", { inputType: "insertParagraph", bubbles: true, isComposing: false }));
21085
21125
  return;
21086
21126
  }
21087
- this.isKeyStillDown = false;
21088
21127
  if (this.autoCompleteState.showProvider) {
21089
21128
  const autoCompleteValue = this.autoCompleteState.values[this.autoCompleteState.selectedIndex]?.text;
21090
21129
  if (autoCompleteValue) {
@@ -21117,56 +21156,42 @@ class Composer extends Component {
21117
21156
  else {
21118
21157
  ev.stopPropagation();
21119
21158
  }
21120
- const { start, end } = this.contentHelper.getCurrentSelection();
21121
- if (!this.env.model.getters.isSelectingForComposer() &&
21122
- !(ev.key === "Enter" && (ev.altKey || ev.ctrlKey))) {
21123
- this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", { start, end });
21124
- this.isKeyStillDown = true;
21125
- }
21126
21159
  }
21127
21160
  /*
21128
21161
  * Triggered automatically by the content-editable between the keydown and key up
21129
21162
  * */
21130
- onInput() {
21163
+ onInput(ev) {
21131
21164
  if (this.props.focus === "inactive" || !this.shouldProcessInputEvents) {
21132
21165
  return;
21133
21166
  }
21167
+ let content = this.contentHelper.getText();
21168
+ let selection = this.contentHelper.getCurrentSelection();
21169
+ if (ev.inputType === "insertParagraph") {
21170
+ const start = Math.min(selection.start, selection.end);
21171
+ const end = Math.max(selection.start, selection.end);
21172
+ content = content.slice(0, start) + NEWLINE + content.slice(end);
21173
+ selection = { start: start + 1, end: start + 1 };
21174
+ }
21134
21175
  this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
21135
21176
  this.env.model.dispatch("SET_CURRENT_CONTENT", {
21136
- content: this.contentHelper.getText(),
21137
- selection: this.contentHelper.getCurrentSelection(),
21177
+ content,
21178
+ selection,
21138
21179
  });
21180
+ this.processTokenAtCursor();
21139
21181
  }
21140
- onKeyup(ev) {
21141
- this.isKeyStillDown = false;
21142
- if (this.props.focus === "inactive" ||
21143
- ["Control", "Alt", "Shift", "Tab", "Enter", "F4"].includes(ev.key)) {
21144
- return;
21145
- }
21146
- if (this.autoCompleteState.showProvider && ["ArrowUp", "ArrowDown"].includes(ev.key)) {
21147
- return; // already processed in keydown
21148
- }
21149
- if (this.env.model.getters.isSelectingForComposer() &&
21150
- ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(ev.key)) {
21151
- return; // already processed in keydown
21152
- }
21153
- ev.preventDefault();
21154
- ev.stopPropagation();
21155
- this.autoCompleteState.showProvider = false;
21156
- if (ev.ctrlKey && ev.key === " ") {
21157
- this.showAutocomplete("");
21158
- this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
21159
- return;
21160
- }
21161
- const { start: oldStart, end: oldEnd } = this.env.model.getters.getComposerSelection();
21162
- const { start, end } = this.contentHelper.getCurrentSelection();
21163
- if (start !== oldStart || end !== oldEnd) {
21164
- this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", this.contentHelper.getCurrentSelection());
21182
+ onKeyup() {
21183
+ if (this.contentHelper.el === document.activeElement) {
21184
+ const { start: oldStart, end: oldEnd } = this.env.model.getters.getComposerSelection();
21185
+ const { start, end } = this.contentHelper.getCurrentSelection();
21186
+ if (start !== oldStart || end !== oldEnd) {
21187
+ this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", { start, end });
21188
+ }
21165
21189
  }
21166
- this.processTokenAtCursor();
21167
- this.processContent();
21168
21190
  }
21169
21191
  showAutocomplete(searchTerm) {
21192
+ if (!this.env.model.getters.getCurrentContent().startsWith("=")) {
21193
+ return;
21194
+ }
21170
21195
  this.autoCompleteState.showProvider = true;
21171
21196
  let values = Object.entries(functionRegistry.content)
21172
21197
  .filter(([_, { hidden }]) => !hidden)
@@ -21186,13 +21211,6 @@ class Composer extends Component {
21186
21211
  this.autoCompleteState.values = values.slice(0, 10);
21187
21212
  this.autoCompleteState.selectedIndex = 0;
21188
21213
  }
21189
- onMousedown(ev) {
21190
- if (ev.button > 0) {
21191
- // not main button, probably a context menu
21192
- return;
21193
- }
21194
- this.contentHelper.removeSelection();
21195
- }
21196
21214
  onClick() {
21197
21215
  if (this.env.model.getters.isReadonly()) {
21198
21216
  return;
@@ -21205,9 +21223,6 @@ class Composer extends Component {
21205
21223
  this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", newSelection);
21206
21224
  this.processTokenAtCursor();
21207
21225
  }
21208
- onBlur() {
21209
- this.isKeyStillDown = false;
21210
- }
21211
21226
  // ---------------------------------------------------------------------------
21212
21227
  // Private
21213
21228
  // ---------------------------------------------------------------------------
@@ -21215,22 +21230,19 @@ class Composer extends Component {
21215
21230
  if (this.compositionActive) {
21216
21231
  return;
21217
21232
  }
21218
- const oldScroll = getElementScrollTop(this.composerRef.el);
21219
- this.contentHelper.removeAll(); // removes the content of the composer, to be added just after
21220
21233
  this.shouldProcessInputEvents = false;
21221
21234
  if (this.props.focus !== "inactive") {
21222
21235
  this.contentHelper.el.focus();
21223
- this.contentHelper.selectRange(0, 0); // move the cursor inside the composer at 0 0.
21224
21236
  }
21225
21237
  const content = this.getContentLines();
21238
+ this.contentHelper.setText(content);
21226
21239
  if (content.length !== 0 && content.length[0] !== 0) {
21227
- this.contentHelper.setText(content);
21228
- const { start, end } = this.env.model.getters.getComposerSelection();
21229
21240
  if (this.props.focus !== "inactive") {
21230
21241
  // Put the cursor back where it was before the rendering
21242
+ const { start, end } = this.env.model.getters.getComposerSelection();
21231
21243
  this.contentHelper.selectRange(start, end);
21232
21244
  }
21233
- setElementScrollTop(this.composerRef.el, oldScroll);
21245
+ this.contentHelper.scrollSelectionIntoView();
21234
21246
  }
21235
21247
  this.shouldProcessInputEvents = true;
21236
21248
  }
@@ -21485,8 +21497,8 @@ class GridComposer extends Component {
21485
21497
  height: el.clientHeight,
21486
21498
  };
21487
21499
  this.composerState.delimitation = {
21488
- width: el.parentElement.clientWidth,
21489
- height: el.parentElement.clientHeight,
21500
+ width: this.props.gridDims.width,
21501
+ height: this.props.gridDims.height,
21490
21502
  };
21491
21503
  });
21492
21504
  onWillUpdateProps(() => {
@@ -23204,7 +23216,7 @@ class Highlight extends Component {
23204
23216
  shiftingMode: "none",
23205
23217
  });
23206
23218
  onResizeHighlight(isLeft, isTop) {
23207
- const activeSheet = this.env.model.getters.getActiveSheet();
23219
+ const activeSheetId = this.env.model.getters.getActiveSheetId();
23208
23220
  this.highlightState.shiftingMode = "isResizing";
23209
23221
  const z = this.props.zone;
23210
23222
  const pivotCol = isLeft ? z.right : z.left;
@@ -23213,11 +23225,10 @@ class Highlight extends Component {
23213
23225
  let lastRow = isTop ? z.top : z.bottom;
23214
23226
  let currentZone = z;
23215
23227
  this.env.model.dispatch("START_CHANGE_HIGHLIGHT", {
23216
- range: this.env.model.getters.getRangeDataFromZone(activeSheet.id, currentZone),
23228
+ range: this.env.model.getters.getRangeDataFromZone(activeSheetId, currentZone),
23217
23229
  });
23218
23230
  const mouseMove = (col, row) => {
23219
23231
  if (lastCol !== col || lastRow !== row) {
23220
- const activeSheetId = this.env.model.getters.getActiveSheetId();
23221
23232
  lastCol = clip(col === -1 ? lastCol : col, 0, this.env.model.getters.getNumberCols(activeSheetId) - 1);
23222
23233
  lastRow = clip(row === -1 ? lastRow : row, 0, this.env.model.getters.getNumberRows(activeSheetId) - 1);
23223
23234
  let newZone = {
@@ -23229,7 +23240,7 @@ class Highlight extends Component {
23229
23240
  newZone = this.env.model.getters.expandZone(activeSheetId, newZone);
23230
23241
  if (!isEqual(newZone, currentZone)) {
23231
23242
  this.env.model.dispatch("CHANGE_HIGHLIGHT", {
23232
- range: this.env.model.getters.getRangeDataFromZone(activeSheet.id, newZone),
23243
+ range: this.env.model.getters.getRangeFromZone(activeSheetId, this.env.model.getters.getUnboundedZone(activeSheetId, newZone)).rangeData,
23233
23244
  });
23234
23245
  currentZone = newZone;
23235
23246
  }
@@ -23276,7 +23287,7 @@ class Highlight extends Component {
23276
23287
  newZone = this.env.model.getters.expandZone(activeSheetId, newZone);
23277
23288
  if (!isEqual(newZone, currentZone)) {
23278
23289
  this.env.model.dispatch("CHANGE_HIGHLIGHT", {
23279
- range: this.env.model.getters.getRangeDataFromZone(activeSheetId, newZone),
23290
+ range: this.env.model.getters.getRangeFromZone(activeSheetId, this.env.model.getters.getUnboundedZone(activeSheetId, newZone)).rangeData,
23280
23291
  });
23281
23292
  currentZone = newZone;
23282
23293
  }
@@ -24598,6 +24609,16 @@ const XLSX_INDEXED_COLORS = {
24598
24609
  63: "333333",
24599
24610
  64: "000000",
24600
24611
  65: "FFFFFF", // system background
24612
+ };
24613
+ const IMAGE_MIMETYPE_EXTENSION_MAPPING = {
24614
+ "image/avif": "avif",
24615
+ "image/bmp": "bmp",
24616
+ "image/gif": "gif",
24617
+ "image/vnd.microsoft.icon": "ico",
24618
+ "image/jpeg": "jpeg",
24619
+ "image/png": "png",
24620
+ "image/tiff": "tiff",
24621
+ "image/webp": "webp",
24601
24622
  };
24602
24623
 
24603
24624
  /**
@@ -27080,6 +27101,11 @@ function createOverride(partName, contentType) {
27080
27101
  <Override ContentType="${contentType}" PartName="${partName}" />
27081
27102
  `;
27082
27103
  }
27104
+ function createDefaultXMLElement(extension, contentType) {
27105
+ return escapeXml /*xml*/ `
27106
+ <Default Extension="${extension}" ContentType="${contentType}" />
27107
+ `;
27108
+ }
27083
27109
  function joinXmlNodes(xmlNodes) {
27084
27110
  return new XMLString(xmlNodes.join("\n"));
27085
27111
  }
@@ -31521,6 +31547,7 @@ class MergePlugin extends CorePlugin {
31521
31547
  "getMerge",
31522
31548
  "getMergesInZone",
31523
31549
  "isSingleCellOrMerge",
31550
+ "getSelectionRangeString",
31524
31551
  ];
31525
31552
  nextId = 1;
31526
31553
  merges = {};
@@ -31608,6 +31635,26 @@ class MergePlugin extends CorePlugin {
31608
31635
  .map((mergeId) => this.getMergeById(sheetId, mergeId))
31609
31636
  .filter(isDefined$1);
31610
31637
  }
31638
+ /**
31639
+ * Same as `getRangeString` but add all necessary merge to the range to make it a valid selection
31640
+ */
31641
+ getSelectionRangeString(range, forSheetId) {
31642
+ const rangeImpl = RangeImpl.fromRange(range, this.getters);
31643
+ const expandedZone = this.getters.expandZone(rangeImpl.sheetId, rangeImpl.zone);
31644
+ const expandedRange = rangeImpl.clone({
31645
+ zone: {
31646
+ ...expandedZone,
31647
+ bottom: rangeImpl.isFullCol ? undefined : expandedZone.bottom,
31648
+ right: rangeImpl.isFullRow ? undefined : expandedZone.right,
31649
+ },
31650
+ });
31651
+ const rangeString = this.getters.getRangeString(expandedRange, forSheetId);
31652
+ if (this.isSingleCellOrMerge(rangeImpl.sheetId, rangeImpl.zone)) {
31653
+ const { sheetName, xc } = splitReference(rangeString);
31654
+ return `${sheetName !== undefined ? getCanonicalSheetName(sheetName) + "!" : ""}${xc.split(":")[0]}`;
31655
+ }
31656
+ return rangeString;
31657
+ }
31611
31658
  /**
31612
31659
  * Return true if the zone intersects an existing merge:
31613
31660
  * if they have at least a common cell
@@ -31940,12 +31987,12 @@ class RangeAdapter {
31940
31987
  }
31941
31988
  static getters = [
31942
31989
  "getRangeString",
31943
- "getSelectionRangeString",
31944
31990
  "getRangeFromSheetXC",
31945
31991
  "createAdaptedRanges",
31946
31992
  "getRangeDataFromXc",
31947
31993
  "getRangeDataFromZone",
31948
31994
  "getRangeFromRangeData",
31995
+ "getRangeFromZone",
31949
31996
  ];
31950
31997
  // ---------------------------------------------------------------------------
31951
31998
  // Command Handling
@@ -32194,21 +32241,6 @@ class RangeAdapter {
32194
32241
  const rangeInterface = { prefixSheet, zone, sheetId, invalidSheetName, parts };
32195
32242
  return new RangeImpl(rangeInterface, this.getters.getSheetSize).orderZone();
32196
32243
  }
32197
- /**
32198
- * Same as `getRangeString` but add all necessary merge to the range to make it a valid selection
32199
- */
32200
- getSelectionRangeString(range, forSheetId) {
32201
- const rangeImpl = RangeImpl.fromRange(range, this.getters);
32202
- const expandedZone = this.getters.expandZone(rangeImpl.sheetId, rangeImpl.zone);
32203
- const expandedRange = rangeImpl.clone({
32204
- zone: {
32205
- ...expandedZone,
32206
- bottom: rangeImpl.isFullCol ? undefined : expandedZone.bottom,
32207
- right: rangeImpl.isFullRow ? undefined : expandedZone.right,
32208
- },
32209
- });
32210
- return this.getRangeString(expandedRange, forSheetId);
32211
- }
32212
32244
  /**
32213
32245
  * Gets the string that represents the range as it is at the moment of the call.
32214
32246
  * The string will be prefixed with the sheet name if the call specified a sheet id in `forSheetId`
@@ -32265,6 +32297,17 @@ class RangeAdapter {
32265
32297
  getRangeDataFromZone(sheetId, zone) {
32266
32298
  return { _sheetId: sheetId, _zone: zone };
32267
32299
  }
32300
+ getRangeFromZone(sheetId, zone) {
32301
+ return new RangeImpl({
32302
+ sheetId,
32303
+ zone,
32304
+ parts: [
32305
+ { colFixed: false, rowFixed: false },
32306
+ { colFixed: false, rowFixed: false },
32307
+ ],
32308
+ prefixSheet: false,
32309
+ }, this.getters.getSheetSize);
32310
+ }
32268
32311
  getRangeFromRangeData(data) {
32269
32312
  const rangeInterface = {
32270
32313
  prefixSheet: false,
@@ -32350,6 +32393,7 @@ class SheetPlugin extends CorePlugin {
32350
32393
  "getPaneDivisions",
32351
32394
  "checkZonesExistInSheet",
32352
32395
  "getCommandZones",
32396
+ "getUnboundedZone",
32353
32397
  ];
32354
32398
  sheetIdsMapName = {};
32355
32399
  orderedSheetIds = [];
@@ -32675,6 +32719,16 @@ class SheetPlugin extends CorePlugin {
32675
32719
  right: this.getNumberCols(sheetId) - 1,
32676
32720
  };
32677
32721
  }
32722
+ getUnboundedZone(sheetId, zone) {
32723
+ const isFullRow = zone.left === 0 && zone.right === this.getNumberCols(sheetId) - 1;
32724
+ const isFullCol = zone.top === 0 && zone.bottom === this.getNumberRows(sheetId) - 1;
32725
+ return {
32726
+ ...zone,
32727
+ bottom: isFullCol ? undefined : zone.bottom,
32728
+ // cannot be unbounded in the 2 dimensions at once
32729
+ right: isFullRow && !isFullCol ? undefined : zone.right,
32730
+ };
32731
+ }
32678
32732
  getPaneDivisions(sheetId) {
32679
32733
  return this.getSheet(sheetId).panes;
32680
32734
  }
@@ -38725,11 +38779,11 @@ class SelectionInputPlugin extends UIPlugin {
38725
38779
  return 0 /* CommandResult.Success */;
38726
38780
  }
38727
38781
  handleEvent(event) {
38728
- const xc = zoneToXc(event.anchor.zone);
38729
38782
  const inputSheetId = this.activeSheet;
38730
38783
  const sheetId = this.getters.getActiveSheetId();
38731
- const sheetName = this.getters.getSheetName(sheetId);
38732
- this.add([sheetId === inputSheetId ? xc : `${getCanonicalSheetName(sheetName)}!${xc}`]);
38784
+ const zone = event.anchor.zone;
38785
+ const range = this.getters.getRangeFromZone(sheetId, event.type === "HeadersSelected" ? this.getters.getUnboundedZone(sheetId, zone) : zone);
38786
+ this.add([this.getters.getSelectionRangeString(range, inputSheetId)]);
38733
38787
  }
38734
38788
  handle(cmd) {
38735
38789
  switch (cmd.type) {
@@ -41187,12 +41241,20 @@ class EditionPlugin extends UIPlugin {
41187
41241
  if (this.mode !== "selecting") {
41188
41242
  return;
41189
41243
  }
41244
+ const sheetId = this.getters.getActiveSheetId();
41245
+ let unboundedZone;
41246
+ if (event.type === "HeadersSelected") {
41247
+ unboundedZone = this.getters.getUnboundedZone(sheetId, event.anchor.zone);
41248
+ }
41249
+ else {
41250
+ unboundedZone = event.anchor.zone;
41251
+ }
41190
41252
  switch (event.mode) {
41191
41253
  case "newAnchor":
41192
- this.insertSelectedRange(event.anchor.zone);
41254
+ this.insertSelectedRange(unboundedZone);
41193
41255
  break;
41194
41256
  default:
41195
- this.replaceSelectedRanges(event.anchor.zone);
41257
+ this.replaceSelectedRanges(unboundedZone);
41196
41258
  break;
41197
41259
  }
41198
41260
  }
@@ -41249,7 +41311,9 @@ class EditionPlugin extends UIPlugin {
41249
41311
  }
41250
41312
  break;
41251
41313
  case "START_CHANGE_HIGHLIGHT":
41314
+ // FIXME: thiws whole ordeal could be handled with the Selection Processor which would extend the feature to selection inputs
41252
41315
  this.dispatch("STOP_COMPOSER_RANGE_SELECTION");
41316
+ // FIXME: we should check range SheetId compared to this.activeSheetId r maybe not have a sheetId in the payload ??
41253
41317
  const range = this.getters.getRangeFromRangeData(cmd.range);
41254
41318
  const previousRefToken = this.currentTokens
41255
41319
  .filter((token) => token.type === "REFERENCE")
@@ -41603,14 +41667,11 @@ class EditionPlugin extends UIPlugin {
41603
41667
  const ref = this.getZoneReference(zone);
41604
41668
  this.replaceText(ref, this.selectionInitialStart, this.selectionEnd);
41605
41669
  }
41606
- getZoneReference(zone, fixedParts = [{ colFixed: false, rowFixed: false }]) {
41670
+ getZoneReference(zone) {
41671
+ const inputSheetId = this.getters.getCurrentEditedCell().sheetId;
41607
41672
  const sheetId = this.getters.getActiveSheetId();
41608
- let selectedXc = this.getters.zoneToXC(sheetId, zone, fixedParts);
41609
- if (this.getters.getCurrentEditedCell().sheetId !== this.getters.getActiveSheetId()) {
41610
- const sheetName = getCanonicalSheetName(this.getters.getSheetName(this.getters.getActiveSheetId()));
41611
- selectedXc = `${sheetName}!${selectedXc}`;
41612
- }
41613
- return selectedXc;
41673
+ const range = this.getters.getRangeFromZone(sheetId, zone);
41674
+ return this.getters.getSelectionRangeString(range, inputSheetId);
41614
41675
  }
41615
41676
  getRangeReference(range, fixedParts = [{ colFixed: false, rowFixed: false }]) {
41616
41677
  let _fixedParts = [...fixedParts];
@@ -42464,7 +42525,7 @@ class ImageProvider {
42464
42525
  const file = await this.getImageFromUser();
42465
42526
  const path = await this.fileStore.upload(file);
42466
42527
  const size = await this.getImageSize(path);
42467
- return { path, size };
42528
+ return { path, size, mimetype: file.type };
42468
42529
  }
42469
42530
  getImageFromUser() {
42470
42531
  return new Promise((resolve, reject) => {
@@ -47531,8 +47592,7 @@ function createWorksheets(data, construct) {
47531
47592
  // Figures and Charts
47532
47593
  let drawingNode = escapeXml ``;
47533
47594
  const drawingRelIds = [];
47534
- const charts = sheet.charts;
47535
- for (const chart of charts) {
47595
+ for (const chart of sheet.charts) {
47536
47596
  const xlsxChartId = convertChartId(chart.id);
47537
47597
  const chartRelId = addRelsToFile(construct.relsFiles, `xl/drawings/_rels/drawing${sheetIndex}.xml.rels`, {
47538
47598
  target: `../charts/chart${xlsxChartId}.xml`,
@@ -47541,20 +47601,27 @@ function createWorksheets(data, construct) {
47541
47601
  drawingRelIds.push(chartRelId);
47542
47602
  files.push(createXMLFile(createChart(chart, sheetIndex, data), `xl/charts/chart${xlsxChartId}.xml`, "chart"));
47543
47603
  }
47544
- const images = sheet.images;
47545
- for (const image of images) {
47604
+ for (const image of sheet.images) {
47605
+ const mimeType = image.data.mimetype;
47606
+ if (mimeType === undefined)
47607
+ continue;
47608
+ const extension = IMAGE_MIMETYPE_EXTENSION_MAPPING[mimeType];
47609
+ // only support exporting images with mimetypes specified in the mapping
47610
+ if (extension === undefined)
47611
+ continue;
47546
47612
  const xlsxImageId = convertImageId(image.id);
47613
+ let imageFileName = `image${xlsxImageId}.${extension}`;
47547
47614
  const imageRelId = addRelsToFile(construct.relsFiles, `xl/drawings/_rels/drawing${sheetIndex}.xml.rels`, {
47548
- target: `../media/image${xlsxImageId}`,
47615
+ target: `../media/${imageFileName}`,
47549
47616
  type: XLSX_RELATION_TYPE.image,
47550
47617
  });
47551
47618
  drawingRelIds.push(imageRelId);
47552
47619
  files.push({
47553
- path: `xl/media/image${xlsxImageId}`,
47554
- imagePath: image.data.path,
47620
+ path: `xl/media/${imageFileName}`,
47621
+ imageSrc: image.data.path,
47555
47622
  });
47556
47623
  }
47557
- const drawings = [...charts, ...images];
47624
+ const drawings = [...sheet.charts, ...sheet.images];
47558
47625
  if (drawings.length) {
47559
47626
  const drawingRelId = addRelsToFile(construct.relsFiles, `xl/worksheets/_rels/sheet${sheetIndex}.xml.rels`, {
47560
47627
  target: `../drawings/drawing${sheetIndex}.xml`,
@@ -47673,6 +47740,8 @@ function createRelsFiles(relsFiles) {
47673
47740
  }
47674
47741
  function createContentTypes(files) {
47675
47742
  const overrideNodes = [];
47743
+ // hard-code supported image mimetypes
47744
+ const imageDefaultNodes = Object.entries(IMAGE_MIMETYPE_EXTENSION_MAPPING).map(([mimetype, extension]) => createDefaultXMLElement(extension, mimetype));
47676
47745
  for (const file of files) {
47677
47746
  if ("contentType" in file && file.contentType) {
47678
47747
  overrideNodes.push(createOverride("/" + file.path, CONTENT_TYPES[file.contentType]));
@@ -47688,6 +47757,7 @@ function createContentTypes(files) {
47688
47757
  ];
47689
47758
  const xml = escapeXml /*xml*/ `
47690
47759
  <Types xmlns="${NAMESPACE["Types"]}">
47760
+ ${joinXmlNodes(Object.values(imageDefaultNodes))}
47691
47761
  <Default ${formatAttributes(relsAttributes)} />
47692
47762
  <Default ${formatAttributes(xmlAttributes)} />
47693
47763
  ${joinXmlNodes(overrideNodes)}
@@ -47779,7 +47849,7 @@ class Model extends EventBus {
47779
47849
  this.coreGetters.getRangeDataFromXc = this.range.getRangeDataFromXc.bind(this.range);
47780
47850
  this.coreGetters.getRangeDataFromZone = this.range.getRangeDataFromZone.bind(this.range);
47781
47851
  this.coreGetters.getRangeFromRangeData = this.range.getRangeFromRangeData.bind(this.range);
47782
- this.coreGetters.getSelectionRangeString = this.range.getSelectionRangeString.bind(this.range);
47852
+ this.coreGetters.getRangeFromZone = this.range.getRangeFromZone.bind(this.range);
47783
47853
  this.getters = {
47784
47854
  isReadonly: () => this.config.mode === "readonly" || this.config.mode === "dashboard",
47785
47855
  isDashboard: () => this.config.mode === "dashboard",
@@ -48270,6 +48340,6 @@ function addFunction(functionName, functionDescription) {
48270
48340
  export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, links, load, parse, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
48271
48341
 
48272
48342
 
48273
- __info__.version = '16.4.0-alpha.2';
48274
- __info__.date = '2023-05-26T13:40:49.561Z';
48275
- __info__.hash = '82328ad';
48343
+ __info__.version = '16.4.0-alpha.3';
48344
+ __info__.date = '2023-06-02T10:13:30.127Z';
48345
+ __info__.hash = '059d66a';