@odoo/o-spreadsheet 17.4.15 → 17.4.17

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.
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 17.4.15
6
- * @date 2024-12-05T10:40:45.905Z
7
- * @hash 9b13f22
5
+ * @version 17.4.17
6
+ * @date 2025-01-14T11:34:44.930Z
7
+ * @hash fd2a7ab
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -766,6 +766,7 @@ function removeFalsyAttributes(obj) {
766
766
  * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes
767
767
  */
768
768
  const whiteSpaceSpecialCharacters = [
769
+ " ",
769
770
  "\t",
770
771
  "\f",
771
772
  "\v",
@@ -780,17 +781,15 @@ const whiteSpaceSpecialCharacters = [
780
781
  String.fromCharCode(parseInt("3000", 16)),
781
782
  String.fromCharCode(parseInt("feff", 16)),
782
783
  ];
783
- const whiteSpaceRegexp = new RegExp(whiteSpaceSpecialCharacters.join("|") + "|(\r\n|\r|\n)", "g");
784
+ const whiteSpaceRegexp = new RegExp(whiteSpaceSpecialCharacters.join("|"), "g");
785
+ const newLineRegexp = /(\r\n|\r)/g;
784
786
  /**
785
- * Replace all the special spaces in a string (non-breaking, tabs, ...) by normal spaces, and all the
786
- * different newlines types by \n.
787
+ * Replace all different newlines characters by \n
787
788
  */
788
- function replaceSpecialSpaces(text) {
789
+ function replaceNewLines(text) {
789
790
  if (!text)
790
791
  return "";
791
- if (!whiteSpaceRegexp.test(text))
792
- return text;
793
- return text.replace(whiteSpaceRegexp, (match, newLine) => (newLine ? NEWLINE : " "));
792
+ return text.replace(newLineRegexp, NEWLINE);
794
793
  }
795
794
  /**
796
795
  * Determine if the numbers are consecutive.
@@ -5682,7 +5681,7 @@ class BorderClipboardHandler extends AbstractCellClipboardHandler {
5682
5681
  const POSTFIX_UNARY_OPERATORS = ["%"];
5683
5682
  const OPERATORS = "+,-,*,/,:,=,<>,>=,>,<=,<,^,&".split(",").concat(POSTFIX_UNARY_OPERATORS);
5684
5683
  function tokenize(str, locale = DEFAULT_LOCALE) {
5685
- str = replaceSpecialSpaces(str);
5684
+ str = replaceNewLines(str);
5686
5685
  const chars = new TokenizingChars(str);
5687
5686
  const result = [];
5688
5687
  while (!chars.isOver()) {
@@ -5829,12 +5828,12 @@ function tokenizeSpace(chars) {
5829
5828
  if (length) {
5830
5829
  return { type: "SPACE", value: NEWLINE.repeat(length) };
5831
5830
  }
5832
- while (chars.current === " ") {
5833
- length++;
5834
- chars.shift();
5831
+ let spaces = "";
5832
+ while (chars.current && chars.current.match(whiteSpaceRegexp)) {
5833
+ spaces += chars.shift();
5835
5834
  }
5836
- if (length) {
5837
- return { type: "SPACE", value: " ".repeat(length) };
5835
+ if (spaces) {
5836
+ return { type: "SPACE", value: spaces };
5838
5837
  }
5839
5838
  return null;
5840
5839
  }
@@ -20366,6 +20365,17 @@ const TEXT = {
20366
20365
  },
20367
20366
  isExported: true,
20368
20367
  };
20368
+ // -----------------------------------------------------------------------------
20369
+ // VALUE
20370
+ // -----------------------------------------------------------------------------
20371
+ const VALUE = {
20372
+ description: _t("Converts a string to a numeric value."),
20373
+ args: [arg("value (number)", _t("the string to be converted"))],
20374
+ compute: function (value) {
20375
+ return toNumber(value, this.locale);
20376
+ },
20377
+ isExported: true,
20378
+ };
20369
20379
 
20370
20380
  var text = /*#__PURE__*/Object.freeze({
20371
20381
  __proto__: null,
@@ -20388,7 +20398,8 @@ var text = /*#__PURE__*/Object.freeze({
20388
20398
  TEXT: TEXT,
20389
20399
  TEXTJOIN: TEXTJOIN,
20390
20400
  TRIM: TRIM,
20391
- UPPER: UPPER
20401
+ UPPER: UPPER,
20402
+ VALUE: VALUE
20392
20403
  });
20393
20404
 
20394
20405
  // -----------------------------------------------------------------------------
@@ -20645,14 +20656,11 @@ autoCompleteProviders.add("functions", {
20645
20656
  });
20646
20657
 
20647
20658
  class DOMFocusableElementStore {
20648
- mutators = ["setFocusableElement", "focus"];
20659
+ mutators = ["setFocusableElement"];
20649
20660
  focusableElement = undefined;
20650
20661
  setFocusableElement(element) {
20651
20662
  this.focusableElement = element;
20652
20663
  }
20653
- focus() {
20654
- this.focusableElement?.focus();
20655
- }
20656
20664
  }
20657
20665
 
20658
20666
  /**
@@ -24680,7 +24688,11 @@ function createGaugeChartRuntime(chart, getters) {
24680
24688
  colors.push(chartColors.upperColor);
24681
24689
  return {
24682
24690
  background: getters.getStyleOfSingleCellChart(chart.background, dataRange).background,
24683
- title: chart.title ?? { text: "" },
24691
+ title: {
24692
+ ...chart.title,
24693
+ // chart titles are extracted from .json files and they are translated at runtime here
24694
+ text: _t(chart.title.text ?? ""),
24695
+ },
24684
24696
  minValue: {
24685
24697
  value: minValue,
24686
24698
  label: formatValue(minValue, { locale, format }),
@@ -38564,6 +38576,7 @@ css /* scss */ `
38564
38576
  }
38565
38577
  }
38566
38578
  `;
38579
+ const DEFAULT_TABLE_STYLE_COLOR = "#3C78D8";
38567
38580
  class TableStyleEditorPanel extends Component {
38568
38581
  static template = "o-spreadsheet-TableStyleEditorPanel";
38569
38582
  static components = { Section, RoundColorPicker, TableStylePreview };
@@ -38582,7 +38595,7 @@ class TableStyleEditorPanel extends Component {
38582
38595
  : null;
38583
38596
  return {
38584
38597
  pickerOpened: false,
38585
- primaryColor: editedStyle?.primaryColor || "#3C78D8",
38598
+ primaryColor: editedStyle?.primaryColor || DEFAULT_TABLE_STYLE_COLOR,
38586
38599
  selectedTemplateName: editedStyle?.templateName || "lightColoredText",
38587
38600
  styleName: editedStyle?.displayName || this.env.model.getters.getNewCustomTableStyleName(),
38588
38601
  };
@@ -38591,7 +38604,7 @@ class TableStyleEditorPanel extends Component {
38591
38604
  this.state.pickerOpened = !this.state.pickerOpened;
38592
38605
  }
38593
38606
  onColorPicked(color) {
38594
- this.state.primaryColor = color;
38607
+ this.state.primaryColor = isColorValid(color) ? color : DEFAULT_TABLE_STYLE_COLOR;
38595
38608
  this.state.pickerOpened = false;
38596
38609
  }
38597
38610
  onTemplatePicked(templateName) {
@@ -39419,7 +39432,7 @@ class GridComposer extends Component {
39419
39432
  this.isEditing = isEditing;
39420
39433
  if (!isEditing) {
39421
39434
  this.rect = this.defaultRect;
39422
- this.DOMFocusableElementStore.focus();
39435
+ this.DOMFocusableElementStore.focusableElement?.focus();
39423
39436
  return;
39424
39437
  }
39425
39438
  const position = this.env.model.getters.getActivePosition();
@@ -39938,6 +39951,7 @@ class FiguresContainer extends Component {
39938
39951
  draggedFigure: undefined,
39939
39952
  horizontalSnap: undefined,
39940
39953
  verticalSnap: undefined,
39954
+ cancelDnd: undefined,
39941
39955
  });
39942
39956
  setup() {
39943
39957
  onMounted(() => {
@@ -39950,12 +39964,28 @@ class FiguresContainer extends Component {
39950
39964
  // new rendering
39951
39965
  this.render();
39952
39966
  });
39967
+ onWillUpdateProps(() => {
39968
+ const sheetId = this.env.model.getters.getActiveSheetId();
39969
+ const draggedFigureId = this.dnd.draggedFigure?.id;
39970
+ if (draggedFigureId && !this.env.model.getters.getFigure(sheetId, draggedFigureId)) {
39971
+ if (this.dnd.cancelDnd) {
39972
+ this.dnd.cancelDnd();
39973
+ }
39974
+ this.dnd.draggedFigure = undefined;
39975
+ this.dnd.horizontalSnap = undefined;
39976
+ this.dnd.verticalSnap = undefined;
39977
+ this.dnd.cancelDnd = undefined;
39978
+ }
39979
+ });
39953
39980
  }
39954
39981
  getVisibleFigures() {
39955
39982
  const visibleFigures = this.env.model.getters.getVisibleFigures();
39956
39983
  if (this.dnd.draggedFigure &&
39957
39984
  !visibleFigures.some((figure) => figure.id === this.dnd.draggedFigure?.id)) {
39958
- visibleFigures.push(this.env.model.getters.getFigure(this.env.model.getters.getActiveSheetId(), this.dnd.draggedFigure?.id));
39985
+ const draggedFigure = this.env.model.getters.getFigure(this.env.model.getters.getActiveSheetId(), this.dnd.draggedFigure?.id);
39986
+ if (draggedFigure) {
39987
+ visibleFigures.push(draggedFigure);
39988
+ }
39959
39989
  }
39960
39990
  return visibleFigures;
39961
39991
  }
@@ -40074,7 +40104,7 @@ class FiguresContainer extends Component {
40074
40104
  this.dnd.verticalSnap = undefined;
40075
40105
  this.env.model.dispatch("UPDATE_FIGURE", { sheetId, id: figure.id, x, y });
40076
40106
  };
40077
- startDnd(onMouseMove, onMouseUp);
40107
+ this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
40078
40108
  }
40079
40109
  /**
40080
40110
  * Initialize the resize of a figure with mouse movements
@@ -40122,7 +40152,7 @@ class FiguresContainer extends Component {
40122
40152
  this.dnd.horizontalSnap = undefined;
40123
40153
  this.dnd.verticalSnap = undefined;
40124
40154
  };
40125
- startDnd(onMouseMove, onMouseUp);
40155
+ this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
40126
40156
  }
40127
40157
  getOtherFigures(figId) {
40128
40158
  return this.getVisibleFigures().filter((f) => f.id !== figId);
@@ -42442,7 +42472,7 @@ class Grid extends Component {
42442
42472
  this.cellPopovers = useStore(CellPopoverStore);
42443
42473
  useEffect(() => {
42444
42474
  if (!this.sidePanel.isOpen) {
42445
- this.DOMFocusableElementStore.focus();
42475
+ this.DOMFocusableElementStore.focusableElement?.focus();
42446
42476
  }
42447
42477
  }, () => [this.sidePanel.isOpen]);
42448
42478
  }
@@ -42646,7 +42676,7 @@ class Grid extends Component {
42646
42676
  focusDefaultElement() {
42647
42677
  if (!this.env.model.getters.getSelectedFigureId() &&
42648
42678
  this.composerStore.editionMode === "inactive") {
42649
- this.DOMFocusableElementStore.focus();
42679
+ this.DOMFocusableElementStore.focusableElement?.focus();
42650
42680
  }
42651
42681
  }
42652
42682
  get gridEl() {
@@ -44263,7 +44293,7 @@ function extractStyle(cell, data) {
44263
44293
  vertical: style.verticalAlign
44264
44294
  ? V_ALIGNMENT_EXPORT_CONVERSION_MAP[style.verticalAlign]
44265
44295
  : undefined,
44266
- wrapText: style.wrapping === "wrap" || undefined,
44296
+ wrapText: style.wrapping === "wrap" || cell.content?.includes(NEWLINE) ? true : undefined,
44267
44297
  },
44268
44298
  };
44269
44299
  styles.font["strike"] = !!style?.strikethrough || undefined;
@@ -44486,7 +44516,7 @@ function convertFigure(figure, id, sheetData) {
44486
44516
  return undefined;
44487
44517
  }
44488
44518
  function isChartData(data) {
44489
- return "dataSets" in data;
44519
+ return "dataSets" in data && data.dataSets.length > 0;
44490
44520
  }
44491
44521
  function isImageData(data) {
44492
44522
  return "imageSrc" in data;
@@ -44724,9 +44754,8 @@ function convertRows(sheet, numberOfRows, headerGroups) {
44724
44754
  }
44725
44755
  return rows;
44726
44756
  }
44727
- /** Remove newlines (\n) in shared strings, We do not support them */
44728
44757
  function convertSharedStrings(xlsxSharedStrings) {
44729
- return xlsxSharedStrings.map((str) => str.replace(/\n/g, ""));
44758
+ return xlsxSharedStrings.map(replaceNewLines);
44730
44759
  }
44731
44760
  function convertCells(sheet, data, sheetDims, warningManager) {
44732
44761
  const cells = {};
@@ -45495,15 +45524,10 @@ class XlsxMiscExtractor extends XlsxBaseExtractor {
45495
45524
  getSharedStrings() {
45496
45525
  return this.mapOnElements({ parent: this.rootFile.file.xml, query: "si" }, (ssElement) => {
45497
45526
  // Shared string can either be a simple text, or a rich text (text with formatting, possibly in multiple parts)
45498
- if (ssElement.children[0].tagName === "t") {
45499
- return this.extractTextContent(ssElement) || "";
45500
- }
45501
45527
  // We don't support rich text formatting, we'll only extract the text
45502
- else {
45503
- return this.mapOnElements({ parent: ssElement, query: "t" }, (textElement) => {
45504
- return this.extractTextContent(textElement) || "";
45505
- }).join("");
45506
- }
45528
+ return this.mapOnElements({ parent: ssElement, query: "t" }, (textElement) => {
45529
+ return this.extractTextContent(textElement) || "";
45530
+ }).join("");
45507
45531
  });
45508
45532
  }
45509
45533
  }
@@ -47377,10 +47401,34 @@ class BordersPlugin extends CorePlugin {
47377
47401
  const elements = [...cmd.elements].sort((a, b) => b - a);
47378
47402
  for (const group of groupConsecutive(elements)) {
47379
47403
  if (cmd.dimension === "COL") {
47380
- this.shiftBordersHorizontally(cmd.sheetId, group[group.length - 1] + 1, -group.length);
47404
+ if (group[0] >= this.getters.getNumberCols(cmd.sheetId)) {
47405
+ for (let row = 0; row < this.getters.getNumberRows(cmd.sheetId); row++) {
47406
+ this.history.update("borders", cmd.sheetId, group[0] + 1, row, "vertical", undefined);
47407
+ }
47408
+ }
47409
+ if (group[group.length - 1] === 0) {
47410
+ for (let row = 0; row < this.getters.getNumberRows(cmd.sheetId); row++) {
47411
+ this.history.update("borders", cmd.sheetId, 0, row, "vertical", undefined);
47412
+ }
47413
+ }
47414
+ const zone = this.getters.getColsZone(cmd.sheetId, group[group.length - 1] + 1, group[0]);
47415
+ this.clearInsideBorders(cmd.sheetId, [zone]);
47416
+ this.shiftBordersHorizontally(cmd.sheetId, group[0] + 1, -group.length);
47381
47417
  }
47382
47418
  else {
47383
- this.shiftBordersVertically(cmd.sheetId, group[group.length - 1] + 1, -group.length);
47419
+ if (group[0] >= this.getters.getNumberRows(cmd.sheetId)) {
47420
+ for (let col = 0; col < this.getters.getNumberCols(cmd.sheetId); col++) {
47421
+ this.history.update("borders", cmd.sheetId, col, group[0] + 1, "horizontal", undefined);
47422
+ }
47423
+ }
47424
+ if (group[group.length - 1] === 0) {
47425
+ for (let col = 0; col < this.getters.getNumberCols(cmd.sheetId); col++) {
47426
+ this.history.update("borders", cmd.sheetId, col, 0, "horizontal", undefined);
47427
+ }
47428
+ }
47429
+ const zone = this.getters.getRowsZone(cmd.sheetId, group[group.length - 1] + 1, group[0]);
47430
+ this.clearInsideBorders(cmd.sheetId, [zone]);
47431
+ this.shiftBordersVertically(cmd.sheetId, group[0] + 1, -group.length);
47384
47432
  }
47385
47433
  }
47386
47434
  break;
@@ -47687,6 +47735,18 @@ class BordersPlugin extends CorePlugin {
47687
47735
  }
47688
47736
  }
47689
47737
  }
47738
+ /**
47739
+ * Remove the borders inside of a zone
47740
+ */
47741
+ clearInsideBorders(sheetId, zones) {
47742
+ for (let zone of zones) {
47743
+ for (let row = zone.top; row <= zone.bottom; row++) {
47744
+ for (let col = zone.left; col <= zone.right; col++) {
47745
+ this.history.update("borders", sheetId, col, row, undefined);
47746
+ }
47747
+ }
47748
+ }
47749
+ }
47690
47750
  /**
47691
47751
  * Add a border to the existing one to a cell
47692
47752
  */
@@ -48234,7 +48294,7 @@ class CellPlugin extends CorePlugin {
48234
48294
  const before = this.getters.getCell({ sheetId, col, row });
48235
48295
  const hasContent = "content" in after || "formula" in after;
48236
48296
  // Compute the new cell properties
48237
- const afterContent = hasContent ? replaceSpecialSpaces(after?.content) : before?.content || "";
48297
+ const afterContent = hasContent ? replaceNewLines(after?.content) : before?.content || "";
48238
48298
  let style;
48239
48299
  if (after.style !== undefined) {
48240
48300
  style = after.style || undefined;
@@ -51095,6 +51155,9 @@ class SheetPlugin extends CorePlugin {
51095
51155
  };
51096
51156
  }
51097
51157
  getUnboundedZone(sheetId, zone) {
51158
+ if (zone.bottom === undefined || zone.right === undefined) {
51159
+ return zone;
51160
+ }
51098
51161
  const isFullRow = zone.left === 0 && zone.right === this.getNumberCols(sheetId) - 1;
51099
51162
  const isFullCol = zone.top === 0 && zone.bottom === this.getNumberRows(sheetId) - 1;
51100
51163
  return {
@@ -57513,6 +57576,9 @@ class Session extends EventBus {
57513
57576
  }
57514
57577
  }
57515
57578
  this.acknowledge(message);
57579
+ if (message.type === "REMOTE_REVISION" && message.clientId === this.clientId) {
57580
+ return;
57581
+ }
57516
57582
  this.trigger("collaborative-event-received");
57517
57583
  }
57518
57584
  onClientMoved(message) {
@@ -61304,6 +61370,7 @@ class SheetViewPlugin extends UIPlugin {
61304
61370
  break;
61305
61371
  case "DELETE_SHEET":
61306
61372
  this.cleanViewports();
61373
+ this.sheetsWithDirtyViewports.delete(cmd.sheetId);
61307
61374
  break;
61308
61375
  case "ACTIVATE_SHEET":
61309
61376
  this.sheetsWithDirtyViewports.add(cmd.sheetIdTo);
@@ -62265,11 +62332,6 @@ class BottomBarSheet extends Component {
62265
62332
  editionState = "initializing";
62266
62333
  DOMFocusableElementStore;
62267
62334
  setup() {
62268
- onMounted(() => {
62269
- if (this.isSheetActive) {
62270
- this.scrollToSheet();
62271
- }
62272
- });
62273
62335
  onPatched(() => {
62274
62336
  if (this.sheetNameRef.el && this.state.isEditing && this.editionState === "initializing") {
62275
62337
  this.editionState = "editing";
@@ -62277,6 +62339,11 @@ class BottomBarSheet extends Component {
62277
62339
  }
62278
62340
  });
62279
62341
  this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
62342
+ useEffect((sheetId) => {
62343
+ if (this.props.sheetId === sheetId) {
62344
+ this.scrollToSheet();
62345
+ }
62346
+ }, () => [this.env.model.getters.getActiveSheetId()]);
62280
62347
  }
62281
62348
  focusInputAndSelectContent() {
62282
62349
  if (!this.state.isEditing || !this.sheetNameRef.el)
@@ -62288,7 +62355,10 @@ class BottomBarSheet extends Component {
62288
62355
  }
62289
62356
  }
62290
62357
  scrollToSheet() {
62291
- this.sheetDivRef.el?.scrollIntoView?.();
62358
+ this.sheetDivRef.el?.scrollIntoView?.({
62359
+ behavior: "smooth",
62360
+ inline: "nearest",
62361
+ });
62292
62362
  }
62293
62363
  onFocusOut() {
62294
62364
  if (this.state.isEditing && this.editionState !== "initializing") {
@@ -62318,11 +62388,11 @@ class BottomBarSheet extends Component {
62318
62388
  if (ev.key === "Enter") {
62319
62389
  ev.preventDefault();
62320
62390
  this.stopEdition();
62321
- this.DOMFocusableElementStore.focus();
62391
+ this.DOMFocusableElementStore.focusableElement?.focus();
62322
62392
  }
62323
62393
  if (ev.key === "Escape") {
62324
62394
  this.cancelEdition();
62325
- this.DOMFocusableElementStore.focus();
62395
+ this.DOMFocusableElementStore.focusableElement?.focus();
62326
62396
  }
62327
62397
  }
62328
62398
  onMouseEventSheetName(ev) {
@@ -63727,7 +63797,6 @@ css /* scss */ `
63727
63797
  height: fit-content;
63728
63798
  margin-top: -1px;
63729
63799
  border: 1px solid;
63730
- z-index: ${ComponentsImportance.TopBarComposer};
63731
63800
 
63732
63801
  .o-composer:empty:not(:focus):not(.active)::before {
63733
63802
  content: url("data:image/svg+xml,${encodeURIComponent(FX_SVG)}");
@@ -63769,6 +63838,7 @@ class TopBarComposer extends Component {
63769
63838
  }
63770
63839
  return cssPropertiesToCss({
63771
63840
  "border-color": SELECTION_BORDER_COLOR,
63841
+ "z-index": String(ComponentsImportance.TopBarComposer),
63772
63842
  });
63773
63843
  }
63774
63844
  get delimitation() {
@@ -67857,7 +67927,12 @@ function createSharedStrings(strings) {
67857
67927
  ["count", strings.length],
67858
67928
  ["uniqueCount", strings.length],
67859
67929
  ];
67860
- const stringNodes = strings.map((string) => escapeXml /*xml*/ `<si><t>${string}</t></si>`);
67930
+ const stringNodes = strings.map((string) => {
67931
+ if (string.trim() !== string) {
67932
+ return escapeXml /*xml*/ `<si><t xml:space="preserve">${string}</t></si>`;
67933
+ }
67934
+ return escapeXml /*xml*/ `<si><t>${string}</t></si>`;
67935
+ });
67861
67936
  const xml = escapeXml /*xml*/ `
67862
67937
  <sst ${formatAttributes(namespaces)}>
67863
67938
  ${joinXmlNodes(stringNodes)}
@@ -68594,6 +68669,8 @@ const helpers = {
68594
68669
  areDomainArgsFieldsValid,
68595
68670
  formatTickValue,
68596
68671
  sanitizeSheetName,
68672
+ isNumber,
68673
+ isDateTime,
68597
68674
  };
68598
68675
  const links = {
68599
68676
  isMarkdownLink,
@@ -68681,6 +68758,6 @@ const constants = {
68681
68758
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
68682
68759
 
68683
68760
 
68684
- __info__.version = "17.4.15";
68685
- __info__.date = "2024-12-05T10:40:45.905Z";
68686
- __info__.hash = "9b13f22";
68761
+ __info__.version = "17.4.17";
68762
+ __info__.date = "2025-01-14T11:34:44.930Z";
68763
+ __info__.hash = "fd2a7ab";