@odoo/o-spreadsheet 17.2.1 → 17.3.0-alpha.1

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.1
7
- * @date 2024-03-25T09:41:58.737Z
8
- * @hash f97284c
6
+ * @version 17.3.0-alpha.1
7
+ * @date 2024-03-25T09:43:36.072Z
8
+ * @hash 4095c41
9
9
  */
10
10
 
11
11
  (function (exports, owl) {
@@ -4202,6 +4202,10 @@
4202
4202
  function positionToZone(position) {
4203
4203
  return { left: position.col, right: position.col, top: position.row, bottom: position.row };
4204
4204
  }
4205
+ /** Transform a zone into a zone with only its top-left position */
4206
+ function zoneToTopLeft(zone) {
4207
+ return { ...zone, right: zone.left, bottom: zone.top };
4208
+ }
4205
4209
  function isFullRow(zone) {
4206
4210
  return zone.right === undefined;
4207
4211
  }
@@ -4241,6 +4245,16 @@
4241
4245
  }
4242
4246
  return set;
4243
4247
  }
4248
+ function unionPositionsToZone(positions) {
4249
+ const zone = { top: Infinity, left: Infinity, bottom: -Infinity, right: -Infinity };
4250
+ for (const { col, row } of positions) {
4251
+ zone.top = Math.min(zone.top, row);
4252
+ zone.left = Math.min(zone.left, col);
4253
+ zone.bottom = Math.max(zone.bottom, row);
4254
+ zone.right = Math.max(zone.right, col);
4255
+ }
4256
+ return zone;
4257
+ }
4244
4258
 
4245
4259
  class RangeImpl {
4246
4260
  getSheetSize;
@@ -5570,7 +5584,7 @@
5570
5584
  const spreader = this.getters.getArrayFormulaSpreadingOn(position);
5571
5585
  let cell = this.getters.getCell(position);
5572
5586
  const evaluatedCell = this.getters.getEvaluatedCell(position);
5573
- if (spreader) {
5587
+ if (spreader && !deepEquals(spreader, position)) {
5574
5588
  const isSpreaderCopied = rowsIndexes.includes(spreader.row) && columnsIndexes.includes(spreader.col);
5575
5589
  const content = isSpreaderCopied
5576
5590
  ? ""
@@ -6217,19 +6231,25 @@
6217
6231
  tableCellsInRow.push({});
6218
6232
  continue;
6219
6233
  }
6234
+ const coreTable = this.getters.getCoreTable(position);
6235
+ const tableZone = coreTable?.range.zone;
6220
6236
  // Copy whole table
6221
- if (zones.some((z) => isZoneInside(table.range.zone, z))) {
6222
- copiedTablesIds.add(table.id);
6237
+ if (coreTable && tableZone && zones.some((z) => isZoneInside(tableZone, z))) {
6238
+ copiedTablesIds.add(coreTable.id);
6223
6239
  const values = [];
6224
- for (const col of range(table.range.zone.left, table.range.zone.right + 1)) {
6225
- values.push(this.getters.getFilterHiddenValues({ sheetId, col, row: table.range.zone.top }));
6240
+ for (const col of range(tableZone.left, tableZone.right + 1)) {
6241
+ values.push(this.getters.getFilterHiddenValues({ sheetId, col, row: tableZone.top }));
6226
6242
  }
6227
6243
  tableCellsInRow.push({
6228
- table: { filtersValues: values, range: table.range, config: table.config },
6244
+ table: {
6245
+ range: coreTable.range,
6246
+ config: coreTable.config,
6247
+ type: coreTable.type,
6248
+ },
6229
6249
  });
6230
6250
  }
6231
6251
  // Copy only style of cell
6232
- else {
6252
+ else if (table) {
6233
6253
  tableCellsInRow.push({ style: this.getTableStyleToCopy(position) });
6234
6254
  }
6235
6255
  }
@@ -6300,7 +6320,7 @@
6300
6320
  }
6301
6321
  pasteTableCell(sheetId, tableCell, position, options) {
6302
6322
  if (tableCell.table && !options?.pasteOption) {
6303
- const { range: tableRange, filtersValues } = tableCell.table;
6323
+ const { range: tableRange } = tableCell.table;
6304
6324
  const zoneDims = zoneToDimension(tableRange.zone);
6305
6325
  const newTableZone = {
6306
6326
  left: position.col,
@@ -6312,18 +6332,13 @@
6312
6332
  sheetId: position.sheetId,
6313
6333
  ranges: [this.getters.getRangeDataFromZone(sheetId, newTableZone)],
6314
6334
  config: tableCell.table.config,
6335
+ tableType: tableCell.table.type,
6315
6336
  });
6316
- for (const i of range(0, filtersValues.length)) {
6317
- this.dispatch("UPDATE_FILTER", {
6318
- sheetId: position.sheetId,
6319
- col: newTableZone.left + i,
6320
- row: newTableZone.top,
6321
- hiddenValues: filtersValues[i],
6322
- });
6323
- }
6324
6337
  }
6325
6338
  // Do not paste table style if we're inside another table
6326
- if (!this.getters.getTable(position)) {
6339
+ // We cannot check for dynamic tables, because at this point the paste can have changed the evaluation, and the
6340
+ // dynamic tables are not yet computed
6341
+ if (!this.getters.getCoreTable(position)) {
6327
6342
  if (tableCell.style?.style && options?.pasteOption !== "asValue") {
6328
6343
  this.dispatch("UPDATE_CELL", { ...position, style: tableCell.style.style });
6329
6344
  }
@@ -7425,9 +7440,11 @@
7425
7440
  bandedColumns: _t("Banded columns"),
7426
7441
  automaticAutofill: _t("Automatically autofill formulas"),
7427
7442
  totalRow: _t("Total row"),
7443
+ isDynamic: _t("Auto-adjust to formula result"),
7428
7444
  },
7429
7445
  Tooltips: {
7430
7446
  filterWithoutHeader: _t("Cannot have filters without a header row"),
7447
+ isDynamic: _t("For tables based on array formulas only"),
7431
7448
  },
7432
7449
  };
7433
7450
 
@@ -22228,6 +22245,7 @@ stores.inject(MyMetaStore, storeInstance);
22228
22245
  }
22229
22246
  edit() {
22230
22247
  const { col, row } = this.props.cellPosition;
22248
+ this.env.model.selection.selectCell(col, row);
22231
22249
  this.cellPopovers.open({ col, row }, "LinkEditor");
22232
22250
  }
22233
22251
  unlink() {
@@ -23344,13 +23362,20 @@ stores.inject(MyMetaStore, storeInstance);
23344
23362
  * If a single cell is selected, expand the selection to non-empty adjacent cells to create a table.
23345
23363
  */
23346
23364
  function interactiveCreateTable(env, sheetId, tableConfig) {
23347
- const selection = env.model.getters.getSelectedZones();
23348
- if (selection.length === 1 && getZoneArea(selection[0]) === 1) {
23365
+ let target = env.model.getters.getSelectedZones();
23366
+ let isDynamic = env.model.getters.canCreateDynamicTableOnZones(sheetId, target);
23367
+ if (target.length === 1 && !isDynamic && getZoneArea(target[0]) === 1) {
23349
23368
  env.model.selection.selectTableAroundSelection();
23369
+ target = env.model.getters.getSelectedZones();
23370
+ isDynamic = env.model.getters.canCreateDynamicTableOnZones(sheetId, target);
23350
23371
  }
23351
- const target = env.model.getters.getSelectedZones();
23352
23372
  const ranges = target.map((zone) => env.model.getters.getRangeDataFromZone(sheetId, zone));
23353
- const result = env.model.dispatch("CREATE_TABLE", { ranges, sheetId, config: tableConfig });
23373
+ const result = env.model.dispatch("CREATE_TABLE", {
23374
+ ranges,
23375
+ sheetId,
23376
+ config: tableConfig,
23377
+ tableType: isDynamic ? "dynamic" : "static",
23378
+ });
23354
23379
  if (result.isCancelledBecause("TableOverlap" /* CommandResult.TableOverlap */)) {
23355
23380
  env.raiseError(TableTerms.Errors.TableOverlap);
23356
23381
  }
@@ -23798,9 +23823,13 @@ stores.inject(MyMetaStore, storeInstance);
23798
23823
  };
23799
23824
  const DELETE_SELECTED_TABLE = (env) => {
23800
23825
  const position = env.model.getters.getActivePosition();
23826
+ const table = env.model.getters.getTable(position);
23827
+ if (!table) {
23828
+ return;
23829
+ }
23801
23830
  env.model.dispatch("REMOVE_TABLE", {
23802
23831
  sheetId: position.sheetId,
23803
- target: [positionToZone(position)],
23832
+ target: [table.range.zone],
23804
23833
  });
23805
23834
  };
23806
23835
  //------------------------------------------------------------------------------
@@ -30308,6 +30337,24 @@ stores.inject(MyMetaStore, storeInstance);
30308
30337
  const contentZone = { ...tableZone, top: tableZone.top + numberOfHeaders };
30309
30338
  return contentZone.top <= contentZone.bottom ? contentZone : undefined;
30310
30339
  }
30340
+ function getTableTopLeft(table) {
30341
+ const range = table.range;
30342
+ return { row: range.zone.top, col: range.zone.left, sheetId: range.sheetId };
30343
+ }
30344
+ function createFilter(id, range, config, createRange) {
30345
+ const zone = range.zone;
30346
+ if (zone.left !== zone.right) {
30347
+ throw new Error("Can only define a filter on a single column");
30348
+ }
30349
+ const filteredZone = { ...zone, top: zone.top + config.numberOfHeaders };
30350
+ const filteredRange = createRange(range.sheetId, filteredZone);
30351
+ return {
30352
+ id,
30353
+ rangeWithHeaders: range,
30354
+ col: zone.left,
30355
+ filteredRange: filteredZone.top > filteredZone.bottom ? undefined : filteredRange,
30356
+ };
30357
+ }
30311
30358
  function getComputedTableStyle(tableConfig, numberOfCols, numberOfRows) {
30312
30359
  return {
30313
30360
  borders: getAllTableBorders(tableConfig, numberOfCols, numberOfRows),
@@ -30745,6 +30792,11 @@ stores.inject(MyMetaStore, storeInstance);
30745
30792
  color: #ffffff;
30746
30793
  background: #d94b4b;
30747
30794
  }
30795
+
30796
+ .o-info-icon {
30797
+ width: 14px;
30798
+ height: 14px;
30799
+ }
30748
30800
  }
30749
30801
  `;
30750
30802
  class TablePanel extends owl.Component {
@@ -30776,6 +30828,29 @@ stores.inject(MyMetaStore, storeInstance);
30776
30828
  const numberOfHeaders = hasHeaders ? 1 : 0;
30777
30829
  this.updateNumberOfHeaders(numberOfHeaders);
30778
30830
  }
30831
+ updateTableIsDynamic(isDynamic) {
30832
+ const newTableType = isDynamic ? "dynamic" : "forceStatic";
30833
+ if (newTableType === this.props.table.type) {
30834
+ return;
30835
+ }
30836
+ const uiTable = this.env.model.getters.getTable(getTableTopLeft(this.props.table));
30837
+ if (!uiTable) {
30838
+ return;
30839
+ }
30840
+ const sheetId = this.env.model.getters.getActiveSheetId();
30841
+ const result = this.env.model.dispatch("UPDATE_TABLE", {
30842
+ sheetId,
30843
+ zone: this.props.table.range.zone,
30844
+ newTableRange: uiTable.range.rangeData,
30845
+ tableType: newTableType,
30846
+ });
30847
+ const updatedTable = this.env.model.getters.getCoreTable(getTableTopLeft(this.props.table));
30848
+ if (result.isSuccessful && updatedTable) {
30849
+ const newTableRange = updatedTable.range;
30850
+ this.state.tableXc = this.env.model.getters.getRangeString(newTableRange, sheetId);
30851
+ this.state.tableZoneErrors = [];
30852
+ }
30853
+ }
30779
30854
  onChangeNumberOfHeaders(ev) {
30780
30855
  const input = ev.target;
30781
30856
  const numberOfHeaders = parseInt(input.value);
@@ -30799,35 +30874,59 @@ stores.inject(MyMetaStore, storeInstance);
30799
30874
  }
30800
30875
  const sheetId = this.env.model.getters.getActiveSheetId();
30801
30876
  this.state.tableXc = ranges[0];
30877
+ const newTableRange = this.env.model.getters.getRangeFromSheetXC(sheetId, this.state.tableXc);
30802
30878
  this.state.tableZoneErrors = this.env.model.canDispatch("UPDATE_TABLE", {
30803
30879
  sheetId,
30804
30880
  zone: this.props.table.range.zone,
30805
30881
  newTableRange: this.env.model.getters.getRangeDataFromXc(sheetId, this.state.tableXc),
30882
+ tableType: this.getNewTableType(newTableRange.zone),
30806
30883
  }).reasons;
30807
30884
  }
30808
30885
  onRangeConfirmed() {
30809
30886
  const sheetId = this.env.model.getters.getActiveSheetId();
30810
- const newRange = this.env.model.getters.getRangeFromSheetXC(sheetId, this.state.tableXc);
30887
+ let newRange = this.env.model.getters.getRangeFromSheetXC(sheetId, this.state.tableXc);
30888
+ if (getZoneArea(newRange.zone) === 1) {
30889
+ const extendedZone = this.env.model.getters.getContiguousZone(sheetId, newRange.zone);
30890
+ newRange = this.env.model.getters.getRangeFromZone(sheetId, extendedZone);
30891
+ }
30811
30892
  const result = this.env.model.dispatch("UPDATE_TABLE", {
30812
30893
  sheetId,
30813
30894
  zone: this.props.table.range.zone,
30814
30895
  newTableRange: newRange.rangeData,
30896
+ tableType: this.getNewTableType(newRange.zone),
30815
30897
  });
30816
- if (result.isSuccessful) {
30817
- const position = { col: newRange.zone.left, row: newRange.zone.top };
30898
+ const position = { sheetId, col: newRange.zone.left, row: newRange.zone.top };
30899
+ const updatedTable = this.env.model.getters.getCoreTable(position);
30900
+ if (result.isSuccessful && updatedTable) {
30901
+ const newTopLeft = getTableTopLeft(updatedTable);
30818
30902
  this.env.model.selection.selectZone({
30819
- zone: positionToZone(position),
30820
- cell: position,
30903
+ zone: positionToZone(newTopLeft),
30904
+ cell: newTopLeft,
30821
30905
  });
30906
+ const newTableRange = updatedTable.range;
30907
+ this.state.tableXc = this.env.model.getters.getRangeString(newTableRange, sheetId);
30908
+ }
30909
+ else {
30910
+ const oldTableRange = this.props.table.range;
30911
+ this.state.tableXc = this.env.model.getters.getRangeString(oldTableRange, sheetId);
30822
30912
  }
30823
30913
  this.state.tableZoneErrors = [];
30824
- this.state.tableXc = result.isSuccessful
30825
- ? this.state.tableXc
30826
- : this.env.model.getters.getRangeString(this.props.table.range, sheetId);
30827
30914
  }
30828
30915
  deleteTable() {
30829
30916
  const sheetId = this.env.model.getters.getActiveSheetId();
30830
- this.env.model.dispatch("REMOVE_TABLE", { sheetId, target: [this.props.table.range.zone] });
30917
+ this.env.model.dispatch("REMOVE_TABLE", {
30918
+ sheetId,
30919
+ target: [this.props.table.range.zone],
30920
+ });
30921
+ }
30922
+ getNewTableType(newTableZone) {
30923
+ if (this.props.table.type === "forceStatic") {
30924
+ return "forceStatic";
30925
+ }
30926
+ const sheetId = this.env.model.getters.getActiveSheetId();
30927
+ return this.env.model.getters.canCreateDynamicTableOnZones(sheetId, [newTableZone])
30928
+ ? "dynamic"
30929
+ : "static";
30831
30930
  }
30832
30931
  get tableConfig() {
30833
30932
  return this.props.table.config;
@@ -30845,6 +30944,14 @@ stores.inject(MyMetaStore, storeInstance);
30845
30944
  get hasFilterCheckboxTooltip() {
30846
30945
  return this.canHaveFilters ? undefined : TableTerms.Tooltips.filterWithoutHeader;
30847
30946
  }
30947
+ get canBeDynamic() {
30948
+ const sheetId = this.env.model.getters.getActiveSheetId();
30949
+ return (this.props.table.type === "dynamic" ||
30950
+ this.env.model.getters.canCreateDynamicTableOnZones(sheetId, [this.props.table.range.zone]));
30951
+ }
30952
+ get dynamicTableTooltip() {
30953
+ return TableTerms.Tooltips.isDynamic;
30954
+ }
30848
30955
  }
30849
30956
 
30850
30957
  const sidePanelRegistry = new Registry();
@@ -30907,11 +31014,8 @@ stores.inject(MyMetaStore, storeInstance);
30907
31014
  if (!table) {
30908
31015
  return { isOpen: false };
30909
31016
  }
30910
- return {
30911
- isOpen: true,
30912
- props: { table },
30913
- key: table.id,
30914
- };
31017
+ const coreTable = getters.getCoreTable(getTableTopLeft(table));
31018
+ return { isOpen: true, props: { table: coreTable }, key: table.id };
30915
31019
  },
30916
31020
  });
30917
31021
 
@@ -31856,9 +31960,6 @@ stores.inject(MyMetaStore, storeInstance);
31856
31960
  this.assistantState.allowCellSelectionBehind = false;
31857
31961
  }, 2000);
31858
31962
  }
31859
- get formulaArgSeparator() {
31860
- return this.env.model.getters.getLocale().formulaArgSeparator + " ";
31861
- }
31862
31963
  }
31863
31964
 
31864
31965
  const functions$2 = functionRegistry.content;
@@ -32756,8 +32857,7 @@ stores.inject(MyMetaStore, storeInstance);
32756
32857
  };
32757
32858
  getFilterHeadersPositions() {
32758
32859
  const sheetId = this.env.model.getters.getActiveSheetId();
32759
- const headerPositions = this.env.model.getters.getFilterHeaders(sheetId);
32760
- return headerPositions.map((position) => ({ sheetId, ...position }));
32860
+ return this.env.model.getters.getFilterHeaders(sheetId);
32761
32861
  }
32762
32862
  }
32763
32863
 
@@ -44826,22 +44926,12 @@ stores.inject(MyMetaStore, storeInstance);
44826
44926
  }
44827
44927
 
44828
44928
  class TablePlugin extends CorePlugin {
44829
- static getters = [
44830
- "getFilter",
44831
- "getFilters",
44832
- "getTable",
44833
- "getTables",
44834
- "getTablesInZone",
44835
- "getTablesOverlappingZones",
44836
- "getFilterId",
44837
- "getFilterHeaders",
44838
- "isFilterHeader",
44839
- ];
44929
+ static getters = ["getCoreTable", "getCoreTables"];
44840
44930
  tables = {};
44841
44931
  adaptRanges(applyChange, sheetId) {
44842
44932
  const sheetIds = sheetId ? [sheetId] : this.getters.getSheetIds();
44843
44933
  for (const sheetId of sheetIds) {
44844
- for (const table of this.getTables(sheetId)) {
44934
+ for (const table of this.getCoreTables(sheetId)) {
44845
44935
  this.applyRangeChangeOnTable(sheetId, table, applyChange);
44846
44936
  }
44847
44937
  }
@@ -44857,15 +44947,16 @@ stores.inject(MyMetaStore, storeInstance);
44857
44947
  ? "TableOverlap" /* CommandResult.TableOverlap */
44858
44948
  : "Success" /* CommandResult.Success */, (cmd) => this.checkTableConfigUpdateIsValid(cmd.config));
44859
44949
  case "UPDATE_TABLE":
44860
- const updatedTable = this.getTables(cmd.sheetId).find((table) => deepEquals(table.range.zone, cmd.zone));
44950
+ const updatedTable = this.getTableFromZone(cmd.sheetId, cmd.zone);
44861
44951
  if (!updatedTable) {
44862
44952
  return "TableNotFound" /* CommandResult.TableNotFound */;
44863
44953
  }
44864
44954
  return this.checkValidations(cmd, this.checkUpdatedTableZoneIsValid, (cmd) => this.checkTableConfigUpdateIsValid(cmd.config));
44865
44955
  case "ADD_MERGE":
44866
- for (const merge of cmd.target) {
44867
- for (const table of this.getTables(cmd.sheetId)) {
44868
- if (overlap(table.range.zone, merge)) {
44956
+ for (const table of this.getCoreTables(cmd.sheetId)) {
44957
+ const tableZone = table.range.zone;
44958
+ for (const merge of cmd.target) {
44959
+ if (overlap(tableZone, merge)) {
44869
44960
  return "MergeInTable" /* CommandResult.MergeInTable */;
44870
44961
  }
44871
44962
  }
@@ -44887,8 +44978,11 @@ stores.inject(MyMetaStore, storeInstance);
44887
44978
  }
44888
44979
  case "DUPLICATE_SHEET": {
44889
44980
  const newTables = {};
44890
- for (const table of this.getTables(cmd.sheetId)) {
44891
- newTables[table.id] = this.copyTableForSheet(cmd.sheetIdTo, table);
44981
+ for (const table of this.getCoreTables(cmd.sheetId)) {
44982
+ newTables[table.id] =
44983
+ table.type === "dynamic"
44984
+ ? this.copyDynamicTableForSheet(cmd.sheetIdTo, table)
44985
+ : this.copyStaticTableForSheet(cmd.sheetIdTo, table);
44892
44986
  }
44893
44987
  this.history.update("tables", cmd.sheetIdTo, newTables);
44894
44988
  break;
@@ -44899,14 +44993,17 @@ stores.inject(MyMetaStore, storeInstance);
44899
44993
  const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, union.zone);
44900
44994
  this.dispatch("REMOVE_MERGE", { sheetId: cmd.sheetId, target: mergesInTarget });
44901
44995
  const id = this.uuidGenerator.uuidv4();
44902
- const newTable = this.createTable(id, union, cmd.config || DEFAULT_TABLE_CONFIG);
44996
+ const config = cmd.config || DEFAULT_TABLE_CONFIG;
44997
+ const newTable = cmd.tableType === "dynamic"
44998
+ ? this.createDynamicTable(id, union, config)
44999
+ : this.createStaticTable(id, cmd.tableType, union, config);
44903
45000
  this.history.update("tables", cmd.sheetId, newTable.id, newTable);
44904
45001
  break;
44905
45002
  }
44906
45003
  case "REMOVE_TABLE": {
44907
45004
  const tables = {};
44908
- for (const table of this.getTables(cmd.sheetId)) {
44909
- if (cmd.target.every((zone) => !intersection(zone, table.range.zone))) {
45005
+ for (const table of this.getCoreTables(cmd.sheetId)) {
45006
+ if (cmd.target.every((zone) => !intersection(table.range.zone, zone))) {
44910
45007
  tables[table.id] = table;
44911
45008
  }
44912
45009
  }
@@ -44914,23 +45011,15 @@ stores.inject(MyMetaStore, storeInstance);
44914
45011
  break;
44915
45012
  }
44916
45013
  case "UPDATE_TABLE": {
44917
- const table = this.getTables(cmd.sheetId).find((table) => deepEquals(table.range.zone, cmd.zone));
44918
- if (table) {
44919
- const newTableRange = cmd.newTableRange
44920
- ? this.getters.getRangeFromRangeData(cmd.newTableRange)
44921
- : undefined;
44922
- if (newTableRange) {
44923
- const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, newTableRange.zone);
44924
- this.dispatch("REMOVE_MERGE", { sheetId: cmd.sheetId, target: mergesInTarget });
44925
- }
44926
- const newTable = this.updateTable(table, newTableRange, cmd.config);
44927
- this.history.update("tables", cmd.sheetId, table.id, newTable);
44928
- }
45014
+ this.updateTable(cmd);
44929
45015
  break;
44930
45016
  }
44931
45017
  case "UPDATE_CELL": {
44932
45018
  const sheetId = cmd.sheetId;
44933
- for (const table of this.getTables(sheetId)) {
45019
+ for (const table of this.getCoreTables(sheetId)) {
45020
+ if (table.type === "dynamic") {
45021
+ continue;
45022
+ }
44934
45023
  const direction = this.canUpdateCellCmdExtendTable(cmd, table);
44935
45024
  if (direction === "down") {
44936
45025
  this.extendTableDown(sheetId, table);
@@ -44954,62 +45043,24 @@ stores.inject(MyMetaStore, storeInstance);
44954
45043
  }
44955
45044
  }
44956
45045
  }
44957
- getFilters(sheetId) {
44958
- return this.getTables(sheetId)
44959
- .filter((table) => table.config.hasFilters)
44960
- .map((table) => table.filters)
44961
- .flat();
44962
- }
44963
- getTables(sheetId) {
45046
+ getCoreTables(sheetId) {
44964
45047
  return this.tables[sheetId] ? Object.values(this.tables[sheetId]).filter(isDefined$1) : [];
44965
45048
  }
44966
- getFilter(position) {
44967
- const table = this.getTable(position);
44968
- if (!table || !table.config.hasFilters) {
44969
- return undefined;
44970
- }
44971
- return table.filters.find((filter) => filter.col === position.col);
44972
- }
44973
- getFilterId(position) {
44974
- return this.getFilter(position)?.id;
44975
- }
44976
- getTable({ sheetId, col, row }) {
44977
- return this.getTables(sheetId).find((table) => isInside(col, row, table.range.zone));
44978
- }
44979
- /** Get the filter tables that are fully inside the given zone */
44980
- getTablesInZone(sheetId, zone) {
44981
- return this.getTables(sheetId).filter((table) => isZoneInside(table.range.zone, zone));
45049
+ getCoreTable({ sheetId, col, row }) {
45050
+ return this.getCoreTables(sheetId).find((table) => isInside(col, row, table.range.zone));
44982
45051
  }
44983
45052
  getTablesOverlappingZones(sheetId, zones) {
44984
- return this.getTables(sheetId).filter((table) => zones.some((zone) => overlap(table.range.zone, zone)));
44985
- }
44986
- getFilterHeaders(sheetId) {
44987
- const headers = [];
44988
- for (const table of this.getTables(sheetId)) {
44989
- if (!table.config.hasFilters) {
44990
- continue;
44991
- }
44992
- const zone = table.range.zone;
44993
- const row = zone.top;
44994
- for (let col = zone.left; col <= zone.right; col++) {
44995
- headers.push({ col, row });
44996
- }
44997
- }
44998
- return headers;
44999
- }
45000
- isFilterHeader({ sheetId, col, row }) {
45001
- const headers = this.getFilterHeaders(sheetId);
45002
- return headers.some((header) => header.col === col && header.row === row);
45053
+ return this.getCoreTables(sheetId).filter((table) => zones.some((zone) => overlap(table.range.zone, zone)));
45003
45054
  }
45004
45055
  /** Extend a table down one row */
45005
45056
  extendTableDown(sheetId, table) {
45006
45057
  const newRange = this.getters.extendRange(table.range, "ROW", 1);
45007
- this.history.update("tables", sheetId, table.id, this.updateTable(table, newRange));
45058
+ this.history.update("tables", sheetId, table.id, this.updateStaticTable(table, newRange));
45008
45059
  }
45009
45060
  /** Extend a table right one col */
45010
45061
  extendTableRight(sheetId, table) {
45011
45062
  const newRange = this.getters.extendRange(table.range, "COL", 1);
45012
- this.history.update("tables", sheetId, table.id, this.updateTable(table, newRange));
45063
+ this.history.update("tables", sheetId, table.id, this.updateStaticTable(table, newRange));
45013
45064
  }
45014
45065
  /**
45015
45066
  * Check if an UpdateCell command should cause the given table to be extended by one row or col.
@@ -45046,12 +45097,22 @@ stores.inject(MyMetaStore, storeInstance);
45046
45097
  const cellContent = this.getters.getCell(cellPosition)?.content;
45047
45098
  if (cellContent ||
45048
45099
  this.getters.isInMerge(cellPosition) ||
45049
- this.getters.getTable(cellPosition)) {
45100
+ this.getTablesOverlappingZones(sheetId, [positionToZone(position)]).length) {
45050
45101
  return "none";
45051
45102
  }
45052
45103
  }
45053
45104
  return direction;
45054
45105
  }
45106
+ getTableFromZone(sheetId, zone) {
45107
+ for (const table of this.getCoreTables(sheetId)) {
45108
+ const tableZone = table.range.zone;
45109
+ // Only check top left to match dynamic tables
45110
+ if (tableZone.left === zone.left && tableZone.top === zone.top) {
45111
+ return table;
45112
+ }
45113
+ }
45114
+ return undefined;
45115
+ }
45055
45116
  checkUpdatedTableZoneIsValid(cmd) {
45056
45117
  if (!cmd.newTableRange) {
45057
45118
  return "Success" /* CommandResult.Success */;
@@ -45061,7 +45122,11 @@ stores.inject(MyMetaStore, storeInstance);
45061
45122
  if (zoneIsInSheet !== "Success" /* CommandResult.Success */) {
45062
45123
  return zoneIsInSheet;
45063
45124
  }
45064
- const overlappingTables = this.getTablesOverlappingZones(cmd.sheetId, [newTableZone]).filter((table) => !deepEquals(table.range.zone, cmd.zone));
45125
+ const updatedTable = this.getTableFromZone(cmd.sheetId, cmd.zone);
45126
+ if (!updatedTable) {
45127
+ return "TableNotFound" /* CommandResult.TableNotFound */;
45128
+ }
45129
+ const overlappingTables = this.getTablesOverlappingZones(cmd.sheetId, [newTableZone]).filter((table) => table.id !== updatedTable.id);
45065
45130
  return overlappingTables.length ? "TableOverlap" /* CommandResult.TableOverlap */ : "Success" /* CommandResult.Success */;
45066
45131
  }
45067
45132
  checkTableConfigUpdateIsValid(config) {
@@ -45079,7 +45144,7 @@ stores.inject(MyMetaStore, storeInstance);
45079
45144
  }
45080
45145
  return "Success" /* CommandResult.Success */;
45081
45146
  }
45082
- createTable(id, tableRange, config, filters) {
45147
+ createStaticTable(id, type, tableRange, config, filters) {
45083
45148
  const zone = tableRange.zone;
45084
45149
  if (!filters) {
45085
45150
  filters = [];
@@ -45094,9 +45159,51 @@ stores.inject(MyMetaStore, storeInstance);
45094
45159
  range: tableRange,
45095
45160
  filters,
45096
45161
  config,
45162
+ type,
45163
+ };
45164
+ }
45165
+ createDynamicTable(id, tableRange, config) {
45166
+ const zone = zoneToTopLeft(tableRange.zone);
45167
+ return {
45168
+ id,
45169
+ range: this.getters.getRangeFromZone(tableRange.sheetId, zone),
45170
+ config,
45171
+ type: "dynamic",
45097
45172
  };
45098
45173
  }
45099
- updateTable(table, newRange, configUpdate) {
45174
+ updateTable(cmd) {
45175
+ const table = this.getTableFromZone(cmd.sheetId, cmd.zone);
45176
+ if (!table) {
45177
+ return;
45178
+ }
45179
+ const newTableRange = cmd.newTableRange
45180
+ ? this.getters.getRangeFromRangeData(cmd.newTableRange)
45181
+ : undefined;
45182
+ if (newTableRange) {
45183
+ const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, newTableRange.zone);
45184
+ this.dispatch("REMOVE_MERGE", { sheetId: cmd.sheetId, target: mergesInTarget });
45185
+ }
45186
+ const range = newTableRange || table.range;
45187
+ const newConfig = this.updateTableConfig(cmd.config, table.config);
45188
+ const newTableType = cmd.tableType ?? table.type;
45189
+ if ((newTableType === "dynamic" && table.type !== "dynamic") ||
45190
+ (newTableType !== "dynamic" && table.type === "dynamic")) {
45191
+ const newTable = newTableType === "dynamic"
45192
+ ? this.createDynamicTable(table.id, range, newConfig)
45193
+ : this.createStaticTable(table.id, newTableType, range, newConfig);
45194
+ this.history.update("tables", cmd.sheetId, table.id, newTable);
45195
+ }
45196
+ else {
45197
+ const updatedTable = table.type === "dynamic"
45198
+ ? this.updateDynamicTable(table, range, newConfig)
45199
+ : this.updateStaticTable(table, range, newConfig, newTableType);
45200
+ this.history.update("tables", cmd.sheetId, table.id, updatedTable);
45201
+ }
45202
+ }
45203
+ updateStaticTable(table, newRange, configUpdate, newTableType = table.type) {
45204
+ if (newTableType === "dynamic") {
45205
+ throw new Error("Cannot use updateStaticTable to update a dynamic table");
45206
+ }
45100
45207
  const tableRange = newRange ? newRange : table.range;
45101
45208
  const tableZone = tableRange.zone;
45102
45209
  const newConfig = this.updateTableConfig(configUpdate, table.config);
@@ -45117,8 +45224,16 @@ stores.inject(MyMetaStore, storeInstance);
45117
45224
  range: tableRange,
45118
45225
  config,
45119
45226
  filters: filters.length ? filters : table.filters,
45227
+ type: newTableType,
45120
45228
  };
45121
45229
  }
45230
+ updateDynamicTable(table, newRange, newConfig) {
45231
+ const range = newRange
45232
+ ? this.getters.getRangeFromZone(newRange.sheetId, zoneToTopLeft(newRange.zone))
45233
+ : table.range;
45234
+ const config = newConfig ? newConfig : table.config;
45235
+ return { ...table, range, config };
45236
+ }
45122
45237
  /**
45123
45238
  * Update the old config of a table with the new partial config from an UpdateTable command.
45124
45239
  *
@@ -45140,35 +45255,29 @@ stores.inject(MyMetaStore, storeInstance);
45140
45255
  }
45141
45256
  createFilterFromZone(id, sheetId, zone, config) {
45142
45257
  const range = this.getters.getRangeFromZone(sheetId, zone);
45143
- return this.createFilter(id, range, config);
45144
- }
45145
- createFilter(id, range, config) {
45146
- const zone = range.zone;
45147
- if (zone.left !== zone.right) {
45148
- throw new Error("Can only define a filter on a single column");
45149
- }
45150
- const contentZone = getTableContentZone(zone, config);
45151
- const filteredRange = contentZone
45152
- ? this.getters.getRangeFromZone(range.sheetId, contentZone)
45153
- : undefined;
45154
- return {
45155
- id,
45156
- rangeWithHeaders: range,
45157
- col: zone.left,
45158
- filteredRange,
45159
- };
45258
+ return createFilter(id, range, config, this.getters.getRangeFromZone);
45160
45259
  }
45161
- copyTableForSheet(sheetId, table) {
45260
+ copyStaticTableForSheet(sheetId, table) {
45162
45261
  const newRange = this.getters.getRangeFromZone(sheetId, table.range.zone);
45163
45262
  const newFilters = table.filters.map((filter) => {
45164
45263
  const newFilterRange = this.getters.getRangeFromZone(sheetId, filter.rangeWithHeaders.zone);
45165
- return this.createFilter(filter.id, newFilterRange, table.config);
45264
+ return createFilter(filter.id, newFilterRange, table.config, this.getters.getRangeFromZone);
45166
45265
  });
45167
45266
  return {
45168
45267
  id: table.id,
45169
45268
  range: newRange,
45170
45269
  filters: newFilters,
45171
45270
  config: deepCopy(table.config),
45271
+ type: table.type,
45272
+ };
45273
+ }
45274
+ copyDynamicTableForSheet(sheetId, table) {
45275
+ const newRange = this.getters.getRangeFromZone(sheetId, table.range.zone);
45276
+ return {
45277
+ id: table.id,
45278
+ range: newRange,
45279
+ config: deepCopy(table.config),
45280
+ type: "dynamic",
45172
45281
  };
45173
45282
  }
45174
45283
  applyRangeChangeOnTable(sheetId, table, applyChange) {
@@ -45183,6 +45292,11 @@ stores.inject(MyMetaStore, storeInstance);
45183
45292
  default:
45184
45293
  newTableRange = tableRangeChange.range;
45185
45294
  }
45295
+ if (table.type === "dynamic") {
45296
+ const newTable = this.updateDynamicTable(table, newTableRange);
45297
+ this.history.update("tables", sheetId, table.id, newTable);
45298
+ return;
45299
+ }
45186
45300
  const filters = [];
45187
45301
  for (const filter of table.filters) {
45188
45302
  const filterRangeChange = applyChange(filter.rangeWithHeaders);
@@ -45194,7 +45308,7 @@ stores.inject(MyMetaStore, storeInstance);
45194
45308
  break;
45195
45309
  default:
45196
45310
  const newFilterRange = filterRangeChange.range;
45197
- const newFilter = this.createFilter(filter.id, newFilterRange, table.config);
45311
+ const newFilter = createFilter(filter.id, newFilterRange, table.config, this.getters.getRangeFromZone);
45198
45312
  filters.push(newFilter);
45199
45313
  }
45200
45314
  }
@@ -45209,7 +45323,7 @@ stores.inject(MyMetaStore, storeInstance);
45209
45323
  }
45210
45324
  filters.sort((f1, f2) => f1.col - f2.col);
45211
45325
  }
45212
- const newTable = this.createTable(table.id, newTableRange, table.config, filters);
45326
+ const newTable = this.createStaticTable(table.id, table.type, newTableRange, table.config, filters);
45213
45327
  this.history.update("tables", sheetId, table.id, newTable);
45214
45328
  }
45215
45329
  // ---------------------------------------------------------------------------
@@ -45220,16 +45334,20 @@ stores.inject(MyMetaStore, storeInstance);
45220
45334
  for (const tableData of sheet.tables || []) {
45221
45335
  const uuid = this.uuidGenerator.uuidv4();
45222
45336
  const tableConfig = tableData.config || DEFAULT_TABLE_CONFIG;
45223
- const tableRange = this.getters.getRangeFromSheetXC(sheet.id, tableData.range);
45224
- const table = this.createTable(uuid, tableRange, tableConfig);
45337
+ const range = this.getters.getRangeFromSheetXC(sheet.id, tableData.range);
45338
+ const tableType = tableData.type || "static";
45339
+ const table = tableType === "dynamic"
45340
+ ? this.createDynamicTable(uuid, range, tableConfig)
45341
+ : this.createStaticTable(uuid, tableType, range, tableConfig);
45225
45342
  this.history.update("tables", sheet.id, table.id, table);
45226
45343
  }
45227
45344
  }
45228
45345
  }
45229
45346
  export(data) {
45230
45347
  for (const sheet of data.sheets) {
45231
- for (const table of this.getTables(sheet.id)) {
45232
- const tableData = { range: zoneToXc(table.range.zone) };
45348
+ for (const table of this.getCoreTables(sheet.id)) {
45349
+ const range = zoneToXc(table.range.zone);
45350
+ const tableData = { range, type: table.type };
45233
45351
  if (!deepEquals(table.config, DEFAULT_TABLE_CONFIG)) {
45234
45352
  tableData.config = table.config;
45235
45353
  }
@@ -46945,14 +47063,18 @@ stores.inject(MyMetaStore, storeInstance);
46945
47063
  if (!this.spreadingRelations.isArrayFormula(position)) {
46946
47064
  return [];
46947
47065
  }
46948
- return Array.from(this.spreadingRelations.getArrayResultPositions(position));
47066
+ if (this.evaluatedCells.get(position)?.type === CellValueType.error) {
47067
+ return [position];
47068
+ }
47069
+ const spreadPositions = Array.from(this.spreadingRelations.getArrayResultPositions(position));
47070
+ return [position, ...spreadPositions];
46949
47071
  }
46950
47072
  getEvaluatedPositions() {
46951
47073
  return this.evaluatedCells.keys();
46952
47074
  }
46953
47075
  getArrayFormulaSpreadingOn(position) {
46954
47076
  if (!this.spreadingRelations.hasArrayFormulaResult(position)) {
46955
- return undefined;
47077
+ return this.spreadingRelations.isArrayFormula(position) ? position : undefined;
46956
47078
  }
46957
47079
  const arrayFormulas = this.spreadingRelations.getFormulaPositionsSpreadingOn(position);
46958
47080
  return Array.from(arrayFormulas).find((position) => !this.blockedArrayFormulas.has(position));
@@ -47081,6 +47203,7 @@ stores.inject(MyMetaStore, storeInstance);
47081
47203
  if (!this.blockedArrayFormulas.has(position)) {
47082
47204
  this.invalidateSpreading(position);
47083
47205
  }
47206
+ this.spreadingRelations.removeNode(position);
47084
47207
  const cell = this.getters.getCell(position);
47085
47208
  if (cell === undefined) {
47086
47209
  return EMPTY_CELL;
@@ -47191,7 +47314,6 @@ stores.inject(MyMetaStore, storeInstance);
47191
47314
  this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([child]));
47192
47315
  this.nextPositionsToUpdate.addMany(this.getArrayFormulasBlockedByOrSpreadingOn(child));
47193
47316
  }
47194
- this.spreadingRelations.removeNode(position);
47195
47317
  }
47196
47318
  // ----------------------------------------------------------
47197
47319
  // COMMON FUNCTIONALITY
@@ -48289,6 +48411,181 @@ stores.inject(MyMetaStore, storeInstance);
48289
48411
  }
48290
48412
  }
48291
48413
 
48414
+ class DynamicTablesPlugin extends UIPlugin {
48415
+ static getters = [
48416
+ "canCreateDynamicTableOnZones",
48417
+ "doesZonesContainFilter",
48418
+ "getFilter",
48419
+ "getFilters",
48420
+ "getTable",
48421
+ "getTables",
48422
+ "getTablesOverlappingZones",
48423
+ "getFilterId",
48424
+ "getFilterHeaders",
48425
+ "isFilterHeader",
48426
+ ];
48427
+ tables = {};
48428
+ handle(cmd) {
48429
+ if (invalidateEvaluationCommands.has(cmd.type) ||
48430
+ (cmd.type === "UPDATE_CELL" && "content" in cmd) ||
48431
+ cmd.type === "EVALUATE_CELLS") {
48432
+ this.tables = {};
48433
+ return;
48434
+ }
48435
+ switch (cmd.type) {
48436
+ case "CREATE_TABLE":
48437
+ case "REMOVE_TABLE":
48438
+ case "UPDATE_TABLE":
48439
+ case "DELETE_CONTENT":
48440
+ this.tables = {};
48441
+ break;
48442
+ }
48443
+ }
48444
+ finalize() {
48445
+ for (const sheetId of this.getters.getSheetIds()) {
48446
+ if (!this.tables[sheetId]) {
48447
+ this.tables[sheetId] = this.computeTables(sheetId);
48448
+ }
48449
+ }
48450
+ }
48451
+ computeTables(sheetId) {
48452
+ const tables = [];
48453
+ const coreTables = this.getters.getCoreTables(sheetId);
48454
+ // First we create the static tables, so we can use them to compute collision with dynamic tables
48455
+ for (const table of coreTables) {
48456
+ if (table.type === "dynamic")
48457
+ continue;
48458
+ tables.push(table);
48459
+ }
48460
+ const staticTables = [...tables];
48461
+ // Then we create the dynamic tables
48462
+ for (const coreTable of coreTables) {
48463
+ if (coreTable.type !== "dynamic")
48464
+ continue;
48465
+ const table = this.coreTableToTable(sheetId, coreTable);
48466
+ let tableZone = table.range.zone;
48467
+ // Reduce the zone to avoid collision with static tables. Per design, dynamic tables can't overlap with other
48468
+ // dynamic tables, because formulas cannot spread on the same area, so we don't need to check for that.
48469
+ for (const staticTable of staticTables) {
48470
+ if (overlap(tableZone, staticTable.range.zone)) {
48471
+ tableZone = { ...tableZone, right: staticTable.range.zone.left - 1 };
48472
+ }
48473
+ }
48474
+ tables.push({ ...table, range: this.getters.getRangeFromZone(sheetId, tableZone) });
48475
+ }
48476
+ return tables;
48477
+ }
48478
+ getFilters(sheetId) {
48479
+ return this.getTables(sheetId)
48480
+ .filter((table) => table.config.hasFilters)
48481
+ .map((table) => table.filters)
48482
+ .flat();
48483
+ }
48484
+ getTables(sheetId) {
48485
+ return this.tables[sheetId] || [];
48486
+ }
48487
+ getFilter(position) {
48488
+ const table = this.getTable(position);
48489
+ if (!table || !table.config.hasFilters) {
48490
+ return undefined;
48491
+ }
48492
+ return table.filters.find((filter) => filter.col === position.col);
48493
+ }
48494
+ getFilterId(position) {
48495
+ return this.getFilter(position)?.id;
48496
+ }
48497
+ getTable({ sheetId, col, row }) {
48498
+ return this.getTables(sheetId).find((table) => isInside(col, row, table.range.zone));
48499
+ }
48500
+ getTablesOverlappingZones(sheetId, zones) {
48501
+ return this.getTables(sheetId).filter((table) => zones.some((zone) => overlap(table.range.zone, zone)));
48502
+ }
48503
+ doesZonesContainFilter(sheetId, zones) {
48504
+ return this.getTablesOverlappingZones(sheetId, zones).some((table) => table.config.hasFilters);
48505
+ }
48506
+ getFilterHeaders(sheetId) {
48507
+ const headers = [];
48508
+ for (const table of this.getTables(sheetId)) {
48509
+ if (!table.config.hasFilters) {
48510
+ continue;
48511
+ }
48512
+ const zone = table.range.zone;
48513
+ const row = zone.top;
48514
+ for (let col = zone.left; col <= zone.right; col++) {
48515
+ headers.push({ sheetId, col, row });
48516
+ }
48517
+ }
48518
+ return headers;
48519
+ }
48520
+ isFilterHeader({ sheetId, col, row }) {
48521
+ const headers = this.getFilterHeaders(sheetId);
48522
+ return headers.some((header) => header.col === col && header.row === row);
48523
+ }
48524
+ /**
48525
+ * Check if we can create a dynamic table on the given zones.
48526
+ * - The zones must be continuous
48527
+ * - The union of the zones must be either:
48528
+ * - A single cell that contains an array formula
48529
+ * - All the spread cells of a single array formula
48530
+ */
48531
+ canCreateDynamicTableOnZones(sheetId, zones) {
48532
+ if (!areZonesContinuous(zones)) {
48533
+ return false;
48534
+ }
48535
+ const unionZone = union(...zones);
48536
+ const topLeft = { col: unionZone.left, row: unionZone.top, sheetId };
48537
+ const parentSpreadingCell = this.getters.getArrayFormulaSpreadingOn(topLeft);
48538
+ if (!parentSpreadingCell) {
48539
+ return false;
48540
+ }
48541
+ else if (deepEquals(parentSpreadingCell, topLeft) && getZoneArea(unionZone) === 1) {
48542
+ return true;
48543
+ }
48544
+ const spreadPositions = this.getters.getSpreadPositionsOf(parentSpreadingCell);
48545
+ return deepEquals(unionZone, unionPositionsToZone(spreadPositions));
48546
+ }
48547
+ coreTableToTable(sheetId, table) {
48548
+ if (table.type !== "dynamic") {
48549
+ return table;
48550
+ }
48551
+ const tableZone = table.range.zone;
48552
+ const tablePosition = { sheetId, col: tableZone.left, row: tableZone.top };
48553
+ const spreadPositions = this.getters.getSpreadPositionsOf(tablePosition);
48554
+ const zone = spreadPositions.length ? unionPositionsToZone(spreadPositions) : table.range.zone;
48555
+ const range = this.getters.getRangeFromZone(sheetId, zone);
48556
+ const filters = this.getDynamicTableFilters(sheetId, table, zone);
48557
+ return { id: table.id, range, filters, config: table.config };
48558
+ }
48559
+ getDynamicTableFilters(sheetId, table, tableZone) {
48560
+ const filters = [];
48561
+ const { top, bottom, left, right } = tableZone;
48562
+ for (let col = left; col <= right; col++) {
48563
+ const tableColIndex = col - left;
48564
+ const zone = { left: col, right: col, top, bottom };
48565
+ const filter = createFilter(this.getDynamicTableFilterId(table.id, tableColIndex), this.getters.getRangeFromZone(sheetId, zone), table.config, this.getters.getRangeFromZone);
48566
+ filters.push(filter);
48567
+ }
48568
+ return filters;
48569
+ }
48570
+ getDynamicTableFilterId(tableId, tableCol) {
48571
+ return tableId + "_" + tableCol;
48572
+ }
48573
+ exportForExcel(data) {
48574
+ for (const sheet of data.sheets) {
48575
+ for (const tableData of sheet.tables) {
48576
+ const zone = toZone(tableData.range);
48577
+ const topLeft = { sheetId: sheet.id, col: zone.left, row: zone.top };
48578
+ const coreTable = this.getters.getCoreTable(topLeft);
48579
+ const table = this.getTable(topLeft);
48580
+ if (coreTable?.type !== "dynamic" || !table) {
48581
+ continue;
48582
+ }
48583
+ tableData.range = zoneToXc(table.range.zone);
48584
+ }
48585
+ }
48586
+ }
48587
+ }
48588
+
48292
48589
  class HeaderSizeUIPlugin extends UIPlugin {
48293
48590
  static getters = ["getRowSize", "getHeaderSize"];
48294
48591
  tallestCellInRow = {};
@@ -51336,10 +51633,11 @@ stores.inject(MyMetaStore, storeInstance);
51336
51633
  handle(cmd) {
51337
51634
  switch (cmd.type) {
51338
51635
  case "AUTOFILL_TABLE_COLUMN":
51339
- const table = this.getters.getTable(cmd);
51636
+ const table = this.getters.getCoreTable(cmd);
51340
51637
  const cell = this.getters.getCell(cmd);
51341
- if (!table || !table.config.automaticAutofill || !cell?.isFormula)
51638
+ if (!table?.config.automaticAutofill || table.type === "dynamic" || !cell?.isFormula) {
51342
51639
  return;
51640
+ }
51343
51641
  const { col, row } = cmd;
51344
51642
  const tableContentZone = getTableContentZone(table.range.zone, table.config);
51345
51643
  if (tableContentZone && isInside(col, row, tableContentZone)) {
@@ -52068,9 +52366,6 @@ stores.inject(MyMetaStore, storeInstance);
52068
52366
  case "START":
52069
52367
  for (const sheetId of this.getters.getSheetIds()) {
52070
52368
  this.filterValues[sheetId] = {};
52071
- for (const filter of this.getters.getFilters(sheetId)) {
52072
- this.filterValues[sheetId][filter.id] = [];
52073
- }
52074
52369
  }
52075
52370
  break;
52076
52371
  case "CREATE_SHEET":
@@ -52091,16 +52386,7 @@ stores.inject(MyMetaStore, storeInstance);
52091
52386
  this.updateHiddenRows();
52092
52387
  break;
52093
52388
  case "DUPLICATE_SHEET":
52094
- const filterValues = {};
52095
- for (const newFilter of this.getters.getFilters(cmd.sheetIdTo)) {
52096
- const zone = newFilter.rangeWithHeaders.zone;
52097
- filterValues[newFilter.id] = this.getFilterHiddenValues({
52098
- sheetId: cmd.sheetId,
52099
- col: zone.left,
52100
- row: zone.top,
52101
- });
52102
- }
52103
- this.filterValues[cmd.sheetIdTo] = filterValues;
52389
+ this.filterValues[cmd.sheetIdTo] = deepCopy(this.filterValues[cmd.sheetId]);
52104
52390
  break;
52105
52391
  // If we don't handle DELETE_SHEET, on one hand we will have some residual data, on the other hand we keep the data
52106
52392
  // on DELETE_SHEET followed by undo
@@ -54044,8 +54330,9 @@ stores.inject(MyMetaStore, storeInstance);
54044
54330
  .add("evaluation_chart", EvaluationChartPlugin)
54045
54331
  .add("evaluation_cf", EvaluationConditionalFormatPlugin)
54046
54332
  .add("row_size", HeaderSizeUIPlugin)
54047
- .add("custom_colors", CustomColorsPlugin)
54048
- .add("data_validation_ui", EvaluationDataValidationPlugin);
54333
+ .add("data_validation_ui", EvaluationDataValidationPlugin)
54334
+ .add("dynamic_tables", DynamicTablesPlugin)
54335
+ .add("custom_colors", CustomColorsPlugin);
54049
54336
 
54050
54337
  const clickableCellRegistry = new Registry();
54051
54338
  clickableCellRegistry.add("link", {
@@ -60176,9 +60463,9 @@ stores.inject(MyMetaStore, storeInstance);
60176
60463
  exports.tokenize = tokenize;
60177
60464
 
60178
60465
 
60179
- __info__.version = "17.2.1";
60180
- __info__.date = "2024-03-25T09:41:58.737Z";
60181
- __info__.hash = "f97284c";
60466
+ __info__.version = "17.3.0-alpha.1";
60467
+ __info__.date = "2024-03-25T09:43:36.072Z";
60468
+ __info__.hash = "4095c41";
60182
60469
 
60183
60470
 
60184
60471
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);