@odoo/o-spreadsheet 17.4.0-alpha.1 → 17.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.
@@ -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.4.0-alpha.1
7
- * @date 2024-06-03T15:30:28.283Z
8
- * @hash cb56c37
6
+ * @version 17.4.0-alpha.3
7
+ * @date 2024-06-10T09:38:53.982Z
8
+ * @hash a45ed6a
9
9
  */
10
10
 
11
11
  'use strict';
@@ -311,7 +311,10 @@ function deepCopy(obj) {
311
311
  * Check if the object is a plain old javascript object.
312
312
  */
313
313
  function isPlainObject(obj) {
314
- return typeof obj === "object" && obj?.constructor === Object;
314
+ return (typeof obj === "object" &&
315
+ obj !== null &&
316
+ // obj.constructor can be undefined when there's no prototype (`Object.create(null, {})`)
317
+ (obj?.constructor === Object || obj?.constructor === undefined));
315
318
  }
316
319
  /**
317
320
  * Sanitize the name of a sheet, by eventually removing quotes
@@ -18377,6 +18380,131 @@ var logical = /*#__PURE__*/Object.freeze({
18377
18380
  const supportedPivotExplodedFormulaRegistry = new Registry();
18378
18381
  supportedPivotExplodedFormulaRegistry.add("SPREADSHEET", false);
18379
18382
 
18383
+ const AGGREGATOR_NAMES = {
18384
+ count: _t("Count"),
18385
+ count_distinct: _t("Count Distinct"),
18386
+ bool_and: _t("Boolean And"),
18387
+ bool_or: _t("Boolean Or"),
18388
+ max: _t("Maximum"),
18389
+ min: _t("Minimum"),
18390
+ avg: _t("Average"),
18391
+ sum: _t("Sum"),
18392
+ };
18393
+ const NUMBER_CHAR_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
18394
+ const AGGREGATORS_BY_FIELD_TYPE = {
18395
+ integer: NUMBER_CHAR_AGGREGATORS,
18396
+ char: NUMBER_CHAR_AGGREGATORS,
18397
+ //TODO Support for date and boolean
18398
+ };
18399
+ const AGGREGATORS = {};
18400
+ for (const type in AGGREGATORS_BY_FIELD_TYPE) {
18401
+ AGGREGATORS[type] = {};
18402
+ for (const aggregator of AGGREGATORS_BY_FIELD_TYPE[type]) {
18403
+ AGGREGATORS[type][aggregator] = AGGREGATOR_NAMES[aggregator];
18404
+ }
18405
+ }
18406
+ const AGGREGATORS_FN = {
18407
+ count: {
18408
+ fn: (args) => countAny([args]),
18409
+ format: () => "0",
18410
+ },
18411
+ count_distinct: {
18412
+ fn: (args) => countUnique([args]),
18413
+ format: () => "0",
18414
+ },
18415
+ bool_and: {
18416
+ fn: (args) => boolAnd([args]).result,
18417
+ format: () => undefined,
18418
+ },
18419
+ bool_or: {
18420
+ fn: (args) => boolOr([args]).result,
18421
+ format: () => undefined,
18422
+ },
18423
+ max: {
18424
+ fn: (args, locale) => max([args], locale),
18425
+ format: inferFormat,
18426
+ },
18427
+ min: {
18428
+ fn: (args, locale) => min([args], locale),
18429
+ format: inferFormat,
18430
+ },
18431
+ avg: {
18432
+ fn: (args, locale) => average([args], locale),
18433
+ format: inferFormat,
18434
+ },
18435
+ sum: {
18436
+ fn: (args, locale) => sum([args], locale),
18437
+ format: inferFormat,
18438
+ },
18439
+ };
18440
+ /**
18441
+ * Build a pivot formula expression
18442
+ */
18443
+ function makePivotFormula(formula, args) {
18444
+ return `=${formula}(${args
18445
+ .map((arg) => {
18446
+ const stringIsNumber = typeof arg == "string" && !isNaN(Number(arg)) && Number(arg).toString() === arg;
18447
+ const convertToNumber = typeof arg == "number" || stringIsNumber;
18448
+ return convertToNumber ? `${arg}` : `"${arg.toString().replace(/"/g, '\\"')}"`;
18449
+ })
18450
+ .join(",")})`;
18451
+ }
18452
+ /**
18453
+ * Given an object of form {"1": {...}, "2": {...}, ...} get the maximum ID used
18454
+ * in this object
18455
+ * If the object has no keys, return 0
18456
+ *
18457
+ */
18458
+ function getMaxObjectId(o) {
18459
+ const keys = Object.keys(o);
18460
+ if (!keys.length) {
18461
+ return 0;
18462
+ }
18463
+ const nums = keys.map((id) => parseInt(id, 10));
18464
+ const max = Math.max(...nums);
18465
+ return max;
18466
+ }
18467
+ const ALL_PERIODS = {
18468
+ year: _t("Year"),
18469
+ quarter: _t("Quarter"),
18470
+ month: _t("Month"),
18471
+ week: _t("Week"),
18472
+ day: _t("Day"),
18473
+ year_number: _t("Year"),
18474
+ quarter_number: _t("Quarter"),
18475
+ month_number: _t("Month"),
18476
+ iso_week_number: _t("Week"),
18477
+ day_of_month: _t("Day of Month"),
18478
+ };
18479
+ const DATE_FIELDS = ["date", "datetime"];
18480
+ /**
18481
+ * Parse a dimension string into a pivot dimension definition.
18482
+ * e.g "create_date:month" => { name: "create_date", granularity: "month" }
18483
+ */
18484
+ function parseDimension(dimension) {
18485
+ const [name, granularity] = dimension.split(":");
18486
+ if (granularity) {
18487
+ return { name, granularity };
18488
+ }
18489
+ return { name };
18490
+ }
18491
+ function isDateField(field) {
18492
+ return DATE_FIELDS.includes(field.type);
18493
+ }
18494
+ function toPivotDomain(domainStr) {
18495
+ if (domainStr.length % 2 !== 0) {
18496
+ throw new Error("Invalid domain: odd number of elements");
18497
+ }
18498
+ const domain = [];
18499
+ for (let i = 0; i < domainStr.length - 1; i += 2) {
18500
+ domain.push({ field: domainStr[i], value: domainStr[i + 1] });
18501
+ }
18502
+ return domain;
18503
+ }
18504
+ function flatPivotDomain(domain) {
18505
+ return domain.flatMap((arg) => [arg.field, arg.value]);
18506
+ }
18507
+
18380
18508
  /**
18381
18509
  * Get the pivot ID from the formula pivot ID.
18382
18510
  */
@@ -18856,13 +18984,13 @@ const PIVOT_VALUE = {
18856
18984
  arg("domain_field_name (string,optional,repeating)", _t("Field name.")),
18857
18985
  arg("domain_value (string,optional,repeating)", _t("Value.")),
18858
18986
  ],
18859
- compute: function (formulaId, measureName, ...domain) {
18987
+ compute: function (formulaId, measureName, ...domainArgs) {
18860
18988
  const _pivotFormulaId = toString(formulaId);
18861
- const measure = toString(measureName);
18862
- const domainArgs = domain.map(toString);
18989
+ const _measure = toString(measureName);
18990
+ const _domainArgs = domainArgs.map(toString);
18863
18991
  const pivotId = getPivotId(_pivotFormulaId, this.getters);
18864
- assertMeasureExist(pivotId, measure, this.getters);
18865
- assertDomainLength(domainArgs);
18992
+ assertMeasureExist(pivotId, _measure, this.getters);
18993
+ assertDomainLength(_domainArgs);
18866
18994
  const pivot = this.getters.getPivot(pivotId);
18867
18995
  const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
18868
18996
  if (!supportedPivotExplodedFormulaRegistry.get(coreDefinition.type)) {
@@ -18876,8 +19004,9 @@ const PIVOT_VALUE = {
18876
19004
  if (error) {
18877
19005
  return error;
18878
19006
  }
18879
- const { value, format } = pivot.getPivotCellValueAndFormat(measure, domainArgs);
18880
- if (!value && !this.getters.areDomainArgsFieldsValid(pivotId, domainArgs)) {
19007
+ const domain = toPivotDomain(_domainArgs);
19008
+ const { value, format } = pivot.getPivotCellValueAndFormat(_measure, domain);
19009
+ if (!value && !this.getters.areDomainArgsFieldsValid(pivotId, domain)) {
18881
19010
  return {
18882
19011
  value: CellErrorType.GenericError,
18883
19012
  message: _t("Dimensions don't match the pivot definition"),
@@ -18894,11 +19023,11 @@ const PIVOT_HEADER = {
18894
19023
  arg("domain_field_name (string,optional,repeating)", _t("Field name.")),
18895
19024
  arg("domain_value (string,optional,repeating)", _t("Value.")),
18896
19025
  ],
18897
- compute: function (pivotId, ...domain) {
19026
+ compute: function (pivotId, ...domainArgs) {
18898
19027
  const _pivotFormulaId = toString(pivotId);
18899
- const domainArgs = domain.map(toString);
19028
+ const _domainArgs = domainArgs.map(toString);
18900
19029
  const _pivotId = getPivotId(_pivotFormulaId, this.getters);
18901
- assertDomainLength(domainArgs);
19030
+ assertDomainLength(_domainArgs);
18902
19031
  const pivot = this.getters.getPivot(_pivotId);
18903
19032
  const coreDefinition = this.getters.getPivotCoreDefinition(_pivotId);
18904
19033
  if (!supportedPivotExplodedFormulaRegistry.get(coreDefinition.type)) {
@@ -18912,18 +19041,23 @@ const PIVOT_HEADER = {
18912
19041
  if (error) {
18913
19042
  return error;
18914
19043
  }
18915
- const fieldName = domainArgs.at(-2);
18916
- const valueArg = domainArgs.at(-1);
18917
- if (!this.getters.areDomainArgsFieldsValid(_pivotId, fieldName === "measure" ? domainArgs.slice(0, -2) : domainArgs)) {
19044
+ const domain = toPivotDomain(_domainArgs);
19045
+ const lastNode = domain.at(-1);
19046
+ if (!this.getters.areDomainArgsFieldsValid(_pivotId, lastNode?.field === "measure" ? domain.slice(0, -1) : domain)) {
18918
19047
  return {
18919
19048
  value: CellErrorType.GenericError,
18920
19049
  message: _t("Dimensions don't match the pivot definition"),
18921
19050
  };
18922
19051
  }
18923
- const { value, format } = pivot.getPivotHeaderValueAndFormat(domainArgs);
19052
+ if (lastNode?.field === "measure") {
19053
+ return pivot.getPivotMeasureValue(toString(lastNode.value), domain);
19054
+ }
19055
+ const { value, format } = pivot.getPivotHeaderValueAndFormat(domain);
18924
19056
  return {
18925
19057
  value,
18926
- format: !fieldName || fieldName === "measure" || valueArg === "false" ? undefined : format,
19058
+ format: !lastNode || lastNode.field === "measure" || lastNode.value === "false"
19059
+ ? undefined
19060
+ : format,
18927
19061
  };
18928
19062
  },
18929
19063
  returns: ["NUMBER", "STRING"],
@@ -18936,11 +19070,14 @@ const PIVOT = {
18936
19070
  arg("include_total (boolean, default=TRUE)", _t("Whether to include total/sub-totals or not.")),
18937
19071
  arg("include_column_titles (boolean, default=TRUE)", _t("Whether to include the column titles or not.")),
18938
19072
  ],
18939
- compute: function (pivotId, rowCount = { value: 10000 }, includeTotal = { value: true }, includeColumnHeaders = { value: true }) {
18940
- const _pivotFormulaId = toString(pivotId);
18941
- const _pivotId = getPivotId(_pivotFormulaId, this.getters);
18942
- const pivot = this.getters.getPivot(_pivotId);
18943
- const coreDefinition = this.getters.getPivotCoreDefinition(_pivotId);
19073
+ compute: function (pivotFormulaId, rowCount = { value: 10000 }, includeTotal = { value: true }, includeColumnHeaders = { value: true }) {
19074
+ const _pivotFormulaId = toString(pivotFormulaId);
19075
+ const _rowCount = toNumber(rowCount, this.locale);
19076
+ const _includeColumnHeaders = toBoolean(includeColumnHeaders);
19077
+ const _includedTotal = toBoolean(includeTotal);
19078
+ const pivotId = getPivotId(_pivotFormulaId, this.getters);
19079
+ const pivot = this.getters.getPivot(pivotId);
19080
+ const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
18944
19081
  addPivotDependencies(this, coreDefinition);
18945
19082
  pivot.init({ reload: pivot.needsReevaluation });
18946
19083
  const error = pivot.assertIsValid({ throwOnError: false });
@@ -18948,11 +19085,9 @@ const PIVOT = {
18948
19085
  return error;
18949
19086
  }
18950
19087
  const table = pivot.getTableStructure();
18951
- const _includeColumnHeaders = toBoolean(includeColumnHeaders);
18952
- const cells = table.getPivotCells(toBoolean(includeTotal), _includeColumnHeaders);
19088
+ const cells = table.getPivotCells(_includedTotal, _includeColumnHeaders);
18953
19089
  const headerRows = _includeColumnHeaders ? table.columns.length : 0;
18954
- const pivotTitle = this.getters.getPivotDisplayName(_pivotId);
18955
- const _rowCount = toNumber(rowCount, this.locale);
19090
+ const pivotTitle = this.getters.getPivotDisplayName(pivotId);
18956
19091
  if (_rowCount < 0) {
18957
19092
  throw new EvaluationError(_t("The number of rows must be positive."));
18958
19093
  }
@@ -18967,17 +19102,23 @@ const PIVOT = {
18967
19102
  result[col] = [];
18968
19103
  for (const row of tableRows) {
18969
19104
  const pivotCell = cells[col][row];
18970
- if (!pivotCell.domain) {
18971
- result[col].push({ value: "", format: undefined });
18972
- }
18973
- else if (pivotCell.isHeader) {
18974
- result[col].push(pivot.getPivotHeaderValueAndFormat(pivotCell.domain));
18975
- }
18976
- else {
18977
- if (!pivotCell.measure) {
18978
- throw new Error("Measure is missing");
18979
- }
18980
- result[col].push(pivot.getPivotCellValueAndFormat(pivotCell.measure, pivotCell.domain));
19105
+ switch (pivotCell.type) {
19106
+ case "EMPTY":
19107
+ result[col].push({ value: "" });
19108
+ break;
19109
+ case "HEADER":
19110
+ const domain = pivotCell.domain;
19111
+ const lastNode = domain.at(-1);
19112
+ if (lastNode?.field === "measure") {
19113
+ result[col].push(pivot.getPivotMeasureValue(toString(lastNode.value), domain));
19114
+ }
19115
+ else {
19116
+ result[col].push(pivot.getPivotHeaderValueAndFormat(domain));
19117
+ }
19118
+ break;
19119
+ case "VALUE":
19120
+ result[col].push(pivot.getPivotCellValueAndFormat(pivotCell.measure, pivotCell.domain));
19121
+ break;
18981
19122
  }
18982
19123
  }
18983
19124
  }
@@ -20902,8 +21043,15 @@ class Composer extends owl.Component {
20902
21043
  }
20903
21044
  onPaste(ev) {
20904
21045
  if (this.composerStore.editionMode !== "inactive") {
21046
+ // let the browser clipboard work
20905
21047
  ev.stopPropagation();
20906
21048
  }
21049
+ else {
21050
+ // the user meant to paste in the sheet, not open the composer with the pasted content
21051
+ // While we're not editing, we still have the focus and should therefore prevent
21052
+ // the native "paste" to occur.
21053
+ ev.preventDefault();
21054
+ }
20907
21055
  }
20908
21056
  /*
20909
21057
  * Triggered automatically by the content-editable between the keydown and key up
@@ -20912,9 +21060,6 @@ class Composer extends owl.Component {
20912
21060
  if (!this.shouldProcessInputEvents) {
20913
21061
  return;
20914
21062
  }
20915
- if (ev.inputType === "insertFromPaste" && this.composerStore.editionMode === "inactive") {
20916
- return;
20917
- }
20918
21063
  ev.stopPropagation();
20919
21064
  let content;
20920
21065
  if (this.composerStore.editionMode === "inactive") {
@@ -21567,132 +21712,8 @@ function getFunctionsFromAST(ast, functionNames) {
21567
21712
  }
21568
21713
 
21569
21714
  const PIVOT_FUNCTIONS = ["PIVOT.VALUE", "PIVOT.HEADER", "PIVOT"];
21570
- const AGGREGATOR_NAMES = {
21571
- count: _t("Count"),
21572
- count_distinct: _t("Count Distinct"),
21573
- bool_and: _t("Boolean And"),
21574
- bool_or: _t("Boolean Or"),
21575
- max: _t("Maximum"),
21576
- min: _t("Minimum"),
21577
- avg: _t("Average"),
21578
- sum: _t("Sum"),
21579
- };
21580
- const NUMBER_CHAR_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
21581
- const AGGREGATORS_BY_FIELD_TYPE = {
21582
- integer: NUMBER_CHAR_AGGREGATORS,
21583
- char: NUMBER_CHAR_AGGREGATORS,
21584
- //TODO Support for date and boolean
21585
- };
21586
- const AGGREGATORS = {};
21587
- for (const type in AGGREGATORS_BY_FIELD_TYPE) {
21588
- AGGREGATORS[type] = {};
21589
- for (const aggregator of AGGREGATORS_BY_FIELD_TYPE[type]) {
21590
- AGGREGATORS[type][aggregator] = AGGREGATOR_NAMES[aggregator];
21591
- }
21592
- }
21593
- const AGGREGATORS_FN = {
21594
- count: {
21595
- fn: (args) => countAny([args]),
21596
- format: () => "0",
21597
- },
21598
- count_distinct: {
21599
- fn: (args) => countUnique([args]),
21600
- format: () => "0",
21601
- },
21602
- bool_and: {
21603
- fn: (args) => boolAnd([args]).result,
21604
- format: () => undefined,
21605
- },
21606
- bool_or: {
21607
- fn: (args) => boolOr([args]).result,
21608
- format: () => undefined,
21609
- },
21610
- max: {
21611
- fn: (args, locale) => max([args], locale),
21612
- format: inferFormat,
21613
- },
21614
- min: {
21615
- fn: (args, locale) => min([args], locale),
21616
- format: inferFormat,
21617
- },
21618
- avg: {
21619
- fn: (args, locale) => average([args], locale),
21620
- format: inferFormat,
21621
- },
21622
- sum: {
21623
- fn: (args, locale) => sum([args], locale),
21624
- format: inferFormat,
21625
- },
21626
- };
21627
- /**
21628
- * Build a pivot formula expression
21629
- */
21630
- function makePivotFormula(formula, args) {
21631
- return `=${formula}(${args
21632
- .map((arg) => {
21633
- const stringIsNumber = typeof arg == "string" && !isNaN(Number(arg)) && Number(arg).toString() === arg;
21634
- const convertToNumber = typeof arg == "number" || stringIsNumber;
21635
- return convertToNumber ? `${arg}` : `"${arg.toString().replace(/"/g, '\\"')}"`;
21636
- })
21637
- .join(",")})`;
21638
- }
21639
- /**
21640
- * Given an object of form {"1": {...}, "2": {...}, ...} get the maximum ID used
21641
- * in this object
21642
- * If the object has no keys, return 0
21643
- *
21644
- */
21645
- function getMaxObjectId(o) {
21646
- const keys = Object.keys(o);
21647
- if (!keys.length) {
21648
- return 0;
21649
- }
21650
- const nums = keys.map((id) => parseInt(id, 10));
21651
- const max = Math.max(...nums);
21652
- return max;
21653
- }
21654
- /**
21655
- * Get the first Pivot function description of the given formula.
21656
- */
21657
- function getFirstPivotFunction(tokens) {
21658
- return getFunctionsFromTokens(tokens, PIVOT_FUNCTIONS)[0];
21659
- }
21660
- /**
21661
- * Parse a spreadsheet formula and detect the number of PIVOT functions that are
21662
- * present in the given formula.
21663
- */
21664
- function getNumberOfPivotFunctions(tokens) {
21665
- return getFunctionsFromTokens(tokens, PIVOT_FUNCTIONS).length;
21666
- }
21667
- const ALL_PERIODS = {
21668
- year: _t("Year"),
21669
- quarter: _t("Quarter"),
21670
- month: _t("Month"),
21671
- week: _t("Week"),
21672
- day: _t("Day"),
21673
- year_number: _t("Year"),
21674
- quarter_number: _t("Quarter"),
21675
- month_number: _t("Month"),
21676
- iso_week_number: _t("Week"),
21677
- day_of_month: _t("Day of Month"),
21678
- };
21679
- const DATE_FIELDS = ["date", "datetime"];
21680
- /**
21681
- * Parse a dimension string into a pivot dimension definition.
21682
- * e.g "create_date:month" => { name: "create_date", granularity: "month" }
21683
- */
21684
- function parseDimension(dimension) {
21685
- const [name, granularity] = dimension.split(":");
21686
- if (granularity) {
21687
- return { name, granularity };
21688
- }
21689
- return { name };
21690
- }
21691
- function isDateField(field) {
21692
- return DATE_FIELDS.includes(field.type);
21693
- }
21694
21715
  /**
21695
- * Create a proposal entry for the compose autocomplete
21716
+ * Create a proposal entry for the compose autowcomplete
21696
21717
  * to insert a field name string in a formula.
21697
21718
  */
21698
21719
  function makeFieldProposal(field, granularity) {
@@ -21748,15 +21769,18 @@ function extractFormulaIdFromToken(tokenAtCursor) {
21748
21769
  }
21749
21770
  return idAst.value;
21750
21771
  }
21751
- function toDomainArgs(domainStr) {
21752
- if (domainStr.length % 2 !== 0) {
21753
- throw new Error("Invalid domain: odd number of elements");
21754
- }
21755
- const domain = [];
21756
- for (let i = 0; i < domainStr.length - 1; i += 2) {
21757
- domain.push({ field: domainStr[i], value: domainStr[i + 1] });
21758
- }
21759
- return domain;
21772
+ /**
21773
+ * Get the first Pivot function description of the given formula.
21774
+ */
21775
+ function getFirstPivotFunction(tokens) {
21776
+ return getFunctionsFromTokens(tokens, PIVOT_FUNCTIONS)[0];
21777
+ }
21778
+ /**
21779
+ * Parse a spreadsheet formula and detect the number of PIVOT functions that are
21780
+ * present in the given formula.
21781
+ */
21782
+ function getNumberOfPivotFunctions(tokens) {
21783
+ return getFunctionsFromTokens(tokens, PIVOT_FUNCTIONS).length;
21760
21784
  }
21761
21785
 
21762
21786
  autoCompleteProviders.add("pivot_ids", {
@@ -25323,8 +25347,7 @@ function zoneToRect(zone) {
25323
25347
  */
25324
25348
  function useSpreadsheetRect() {
25325
25349
  const position = owl.useState({ x: 0, y: 0, width: 0, height: 0 });
25326
- let spreadsheetElement = document.querySelector(".o-spreadsheet");
25327
- updatePosition();
25350
+ let spreadsheetElement = null;
25328
25351
  function updatePosition() {
25329
25352
  if (!spreadsheetElement) {
25330
25353
  spreadsheetElement = document.querySelector(".o-spreadsheet");
@@ -32784,7 +32807,7 @@ css /* scss */ `
32784
32807
  vertical-align: middle;
32785
32808
  }
32786
32809
  .o_cf_radio_item {
32787
- margin-right: 10%;
32810
+ margin-right: 30px;
32788
32811
  }
32789
32812
  .radio input:checked {
32790
32813
  color: #e9ecef;
@@ -32804,6 +32827,9 @@ css /* scss */ `
32804
32827
  }
32805
32828
  margin-top: 10px;
32806
32829
  display: flex;
32830
+ .form-check {
32831
+ padding-left: 1rem;
32832
+ }
32807
32833
  }
32808
32834
  .o-section-subtitle:first-child {
32809
32835
  margin-top: 0px;
@@ -32812,7 +32838,7 @@ css /* scss */ `
32812
32838
  font-size: 12px;
32813
32839
  line-height: 1.5;
32814
32840
  .o-selection-cf {
32815
- margin-bottom: 3%;
32841
+ margin-bottom: 9px;
32816
32842
  }
32817
32843
  .o-cell-content {
32818
32844
  font-size: 12px;
@@ -32853,7 +32879,7 @@ css /* scss */ `
32853
32879
  width: 100%;
32854
32880
  }
32855
32881
  .o-threshold-value {
32856
- margin-left: 2%;
32882
+ margin-left: 6px;
32857
32883
  width: 20%;
32858
32884
  min-width: 0px; // input overflows in Firefox otherwise
32859
32885
  }
@@ -32882,8 +32908,8 @@ css /* scss */ `
32882
32908
  justify-content: space-between;
32883
32909
  .o-cf-icon {
32884
32910
  display: inline;
32885
- margin-left: 1%;
32886
- margin-right: 1%;
32911
+ margin-left: 3px;
32912
+ margin-right: 3px;
32887
32913
  }
32888
32914
  svg {
32889
32915
  vertical-align: baseline;
@@ -32906,7 +32932,7 @@ css /* scss */ `
32906
32932
  }
32907
32933
  table {
32908
32934
  table-layout: fixed;
32909
- margin-top: 2%;
32935
+ margin-top: 6px;
32910
32936
  display: table;
32911
32937
  text-align: left;
32912
32938
  font-size: 12px;
@@ -32936,8 +32962,8 @@ css /* scss */ `
32936
32962
  }
32937
32963
  }
32938
32964
  .o-cf-iconset-reverse {
32939
- margin-bottom: 2%;
32940
- margin-top: 2%;
32965
+ margin-bottom: 6px;
32966
+ margin-top: 6px;
32941
32967
  .o-cf-label {
32942
32968
  display: inline-block;
32943
32969
  vertical-align: bottom;
@@ -34525,6 +34551,33 @@ class EditableName extends owl.Component {
34525
34551
  }
34526
34552
  }
34527
34553
 
34554
+ css /* scss */ `
34555
+ .pivot-defer-update {
34556
+ min-height: 35px;
34557
+ background-color: #f8f9fa;
34558
+ }
34559
+ `;
34560
+ class PivotDeferUpdate extends owl.Component {
34561
+ static template = "o-spreadsheet-PivotDeferUpdate";
34562
+ static props = {
34563
+ deferUpdate: Boolean,
34564
+ isDirty: Boolean,
34565
+ toggleDeferUpdate: Function,
34566
+ discard: Function,
34567
+ apply: Function,
34568
+ };
34569
+ static components = {
34570
+ Section,
34571
+ Checkbox,
34572
+ };
34573
+ get deferUpdatesLabel() {
34574
+ return _t("Defer updates");
34575
+ }
34576
+ get deferUpdatesTooltip() {
34577
+ return _t("Changing the pivot definition requires to reload the data. It may take some time.");
34578
+ }
34579
+ }
34580
+
34528
34581
  function useAutofocus({ refName }) {
34529
34582
  const ref = owl.useRef(refName);
34530
34583
  owl.useEffect((el) => {
@@ -34644,6 +34697,10 @@ css /* scss */ `
34644
34697
  select > option {
34645
34698
  background-color: white;
34646
34699
  }
34700
+
34701
+ .pivot-dim-operator-label {
34702
+ min-width: 120px;
34703
+ }
34647
34704
  }
34648
34705
  `;
34649
34706
  class PivotDimension extends owl.Component {
@@ -34884,7 +34941,7 @@ class PivotRuntimeDefinition {
34884
34941
  getMeasure(name) {
34885
34942
  const measure = this.measures.find((measure) => measure.name === name);
34886
34943
  if (!measure) {
34887
- throw new EvaluationError(_t("Field %s does not exist", name));
34944
+ throw new EvaluationError(_t("Field %s is not a measure", name));
34888
34945
  }
34889
34946
  return measure;
34890
34947
  }
@@ -35010,10 +35067,9 @@ class SpreadsheetPivotTable {
35010
35067
  columns;
35011
35068
  rows;
35012
35069
  measures;
35013
- rowTitle;
35014
35070
  maxIndent;
35015
35071
  pivotCells = {};
35016
- constructor(columns, rows, measures, rowTitle = "") {
35072
+ constructor(columns, rows, measures) {
35017
35073
  this.columns = columns.map((row) => {
35018
35074
  // offset in the pivot table
35019
35075
  // starts at 1 because the first column is the row title
@@ -35026,7 +35082,6 @@ class SpreadsheetPivotTable {
35026
35082
  });
35027
35083
  this.rows = rows;
35028
35084
  this.measures = measures;
35029
- this.rowTitle = rowTitle;
35030
35085
  this.maxIndent = Math.max(...this.rows.map((row) => row.indent));
35031
35086
  }
35032
35087
  /**
@@ -35068,26 +35123,23 @@ class SpreadsheetPivotTable {
35068
35123
  }
35069
35124
  getPivotCell(col, row, includeTotal = true) {
35070
35125
  const colHeadersHeight = this.columns.length;
35071
- if (col === 0 && row === colHeadersHeight - 1) {
35072
- return { content: this.rowTitle, isHeader: true };
35073
- }
35074
- else if (row <= colHeadersHeight - 1) {
35126
+ if (row <= colHeadersHeight - 1) {
35075
35127
  const domain = this.getColHeaderDomain(col, row);
35076
- return { domain, isHeader: true };
35128
+ return domain ? { type: "HEADER", domain } : { type: "EMPTY" };
35077
35129
  }
35078
35130
  else if (col === 0) {
35079
35131
  const rowIndex = row - colHeadersHeight;
35080
35132
  const domain = this.getRowDomain(rowIndex);
35081
- return { domain, isHeader: true };
35133
+ return { type: "HEADER", domain };
35082
35134
  }
35083
35135
  else {
35084
35136
  const rowIndex = row - colHeadersHeight;
35085
35137
  if (!includeTotal && this.isTotalRow(rowIndex)) {
35086
- return { isHeader: false };
35138
+ return { type: "EMPTY" };
35087
35139
  }
35088
35140
  const domain = [...this.getRowDomain(rowIndex), ...this.getColDomain(col)];
35089
35141
  const measure = this.getColMeasure(col);
35090
- return { domain, isHeader: false, measure };
35142
+ return { type: "VALUE", domain, measure };
35091
35143
  }
35092
35144
  }
35093
35145
  getColHeaderDomain(col, row) {
@@ -35100,24 +35152,32 @@ class SpreadsheetPivotTable {
35100
35152
  return undefined;
35101
35153
  }
35102
35154
  for (let i = 0; i < pivotCol.fields.length; i++) {
35103
- domain.push(pivotCol.fields[i]);
35104
- domain.push(pivotCol.values[i]);
35155
+ domain.push({
35156
+ field: pivotCol.fields[i],
35157
+ value: pivotCol.values[i],
35158
+ });
35105
35159
  }
35106
35160
  return domain;
35107
35161
  }
35108
35162
  getColDomain(col) {
35109
35163
  const domain = this.getColHeaderDomain(col, this.columns.length - 1);
35110
- return domain ? domain.slice(0, -2) : []; // slice: remove measure and value
35164
+ return domain ? domain.slice(0, -1) : []; // slice: remove measure and value
35111
35165
  }
35112
35166
  getColMeasure(col) {
35113
35167
  const domain = this.getColHeaderDomain(col, this.columns.length - 1);
35114
- return domain?.at(-1);
35168
+ const measure = domain?.at(-1)?.value;
35169
+ if (measure === undefined) {
35170
+ throw new Error("Measure isd missing");
35171
+ }
35172
+ return measure.toString();
35115
35173
  }
35116
35174
  getRowDomain(row) {
35117
35175
  const domain = [];
35118
35176
  for (let i = 0; i < this.rows[row].fields.length; i++) {
35119
- domain.push(this.rows[row].fields[i]);
35120
- domain.push(this.rows[row].values[i]);
35177
+ domain.push({
35178
+ field: this.rows[row].fields[i],
35179
+ value: this.rows[row].values[i],
35180
+ });
35121
35181
  }
35122
35182
  return domain;
35123
35183
  }
@@ -35126,7 +35186,6 @@ class SpreadsheetPivotTable {
35126
35186
  cols: this.columns,
35127
35187
  rows: this.rows,
35128
35188
  measures: this.measures,
35129
- rowTitle: this.rowTitle,
35130
35189
  };
35131
35190
  }
35132
35191
  }
@@ -35146,8 +35205,7 @@ function dataEntriesToSpreadsheetPivotTable(dataEntries, definition) {
35146
35205
  indent: 0,
35147
35206
  });
35148
35207
  const measureNames = definition.measures.map((m) => m.name);
35149
- const rowTitle = rows.length > 0 ? rows[0].values[0] : "";
35150
- return new SpreadsheetPivotTable(cols, rows, measureNames, rowTitle);
35208
+ return new SpreadsheetPivotTable(cols, rows, measureNames);
35151
35209
  }
35152
35210
  // -----------------------------------------------------------------------------
35153
35211
  // ROWS
@@ -35490,7 +35548,10 @@ class SpreadsheetPivot {
35490
35548
  }
35491
35549
  get definition() {
35492
35550
  if (!this._definition) {
35493
- throw new Error("Pivot not loaded yet");
35551
+ this.init();
35552
+ }
35553
+ if (!this._definition) {
35554
+ throw new Error("Pivot definition should be defined at this point.");
35494
35555
  }
35495
35556
  return this._definition;
35496
35557
  }
@@ -35539,15 +35600,16 @@ class SpreadsheetPivot {
35539
35600
  getMeasure(name) {
35540
35601
  return this.definition.getMeasure(name);
35541
35602
  }
35542
- getPivotHeaderValueAndFormat(domainStr) {
35543
- const domain = toDomainArgs(domainStr);
35603
+ getPivotMeasureValue(name) {
35604
+ return {
35605
+ value: this.getMeasure(name).displayName,
35606
+ };
35607
+ }
35608
+ getPivotHeaderValueAndFormat(domain) {
35544
35609
  const lastNode = domain.at(-1);
35545
35610
  if (!lastNode) {
35546
35611
  return { value: _t("Total") };
35547
35612
  }
35548
- if (lastNode.field === "measure") {
35549
- return { value: this.getMeasure(lastNode.value).displayName };
35550
- }
35551
35613
  const dimension = this.getDimension(lastNode.field);
35552
35614
  const cells = this.filterDataEntriesFromDomain(this.dataEntries, domain);
35553
35615
  const finalCell = cells[0]?.[dimension.nameWithGranularity];
@@ -35575,8 +35637,7 @@ class SpreadsheetPivot {
35575
35637
  format: finalCell.format,
35576
35638
  };
35577
35639
  }
35578
- getPivotCellValueAndFormat(measure, domainStr) {
35579
- const domain = toDomainArgs(domainStr);
35640
+ getPivotCellValueAndFormat(measure, domain) {
35580
35641
  const dataEntries = this.filterDataEntriesFromDomain(this.dataEntries, domain);
35581
35642
  if (dataEntries.length === 0) {
35582
35643
  return { value: "" };
@@ -35972,12 +36033,12 @@ class PivotSpreadsheetSidePanel extends owl.Component {
35972
36033
  SelectionInput,
35973
36034
  EditableName,
35974
36035
  Checkbox,
36036
+ PivotDeferUpdate,
35975
36037
  };
35976
36038
  store;
35977
36039
  state;
35978
36040
  setup() {
35979
36041
  this.store = useLocalStore(PivotSidePanelStore, this.props.pivotId);
35980
- this.pivot.init();
35981
36042
  this.state = owl.useState({
35982
36043
  range: undefined,
35983
36044
  rangeHasChanged: false,
@@ -36010,12 +36071,6 @@ class PivotSpreadsheetSidePanel extends owl.Component {
36010
36071
  get definition() {
36011
36072
  return this.store.definition;
36012
36073
  }
36013
- get deferUpdatesLabel() {
36014
- return _t("Defer updates");
36015
- }
36016
- get deferUpdatesTooltip() {
36017
- return _t("Changing the pivot definition requires to reload the data. It may take some time.");
36018
- }
36019
36074
  onSelectionChanged(ranges) {
36020
36075
  this.state.rangeHasChanged = true;
36021
36076
  this.state.range = ranges[0];
@@ -36854,7 +36909,7 @@ css /* scss */ `
36854
36909
  }
36855
36910
 
36856
36911
  .o-table-style-list-item {
36857
- padding: 3px;
36912
+ padding: 3px 2px;
36858
36913
  margin: 2px 1px;
36859
36914
 
36860
36915
  .o-table-style-picker-preview {
@@ -36875,10 +36930,10 @@ class TableStylePicker extends owl.Component {
36875
36930
  const styles = Object.keys(allStyles).filter((key) => allStyles[key].category === selectedStyleCategory);
36876
36931
  const selectedStyleIndex = styles.indexOf(this.props.table.config.styleId);
36877
36932
  if (selectedStyleIndex === -1) {
36878
- return styles.slice(0, 4);
36933
+ return selectedStyleIndex;
36879
36934
  }
36880
36935
  const index = Math.floor(selectedStyleIndex / 4) * 4;
36881
- return styles.slice(index, index + 4);
36936
+ return styles.slice(index);
36882
36937
  }
36883
36938
  onStylePicked(styleId) {
36884
36939
  const sheetId = this.env.model.getters.getActiveSheetId();
@@ -37918,10 +37973,7 @@ class GridComposer extends owl.Component {
37918
37973
  }
37919
37974
  get containerStyle() {
37920
37975
  if (this.composerStore.editionMode === "inactive") {
37921
- return `
37922
- position: absolute;
37923
- z-index: -1000;
37924
- `;
37976
+ return `z-index: -1000;`;
37925
37977
  }
37926
37978
  const isFormula = this.composerStore.currentContent.startsWith("=");
37927
37979
  const cell = this.env.model.getters.getActiveCell();
@@ -40765,10 +40817,13 @@ class VerticalScrollBar extends owl.Component {
40765
40817
  }
40766
40818
  }
40767
40819
 
40820
+ const DEFAULT_SIDE_PANEL_SIZE = 350;
40821
+ const MIN_SHEET_VIEW_WIDTH = 150;
40768
40822
  class SidePanelStore extends SpreadsheetStore {
40769
- mutators = ["open", "toggle", "close"];
40823
+ mutators = ["open", "toggle", "close", "changePanelSize", "resetPanelSize"];
40770
40824
  initialPanelProps = {};
40771
40825
  componentTag = "";
40826
+ panelSize = DEFAULT_SIDE_PANEL_SIZE;
40772
40827
  get isOpen() {
40773
40828
  if (!this.componentTag) {
40774
40829
  return false;
@@ -40813,6 +40868,20 @@ class SidePanelStore extends SpreadsheetStore {
40813
40868
  this.initialPanelProps = {};
40814
40869
  this.componentTag = "";
40815
40870
  }
40871
+ changePanelSize(size, spreadsheetElWidth) {
40872
+ if (size < DEFAULT_SIDE_PANEL_SIZE) {
40873
+ this.panelSize = DEFAULT_SIDE_PANEL_SIZE;
40874
+ }
40875
+ else if (size > spreadsheetElWidth - MIN_SHEET_VIEW_WIDTH) {
40876
+ this.panelSize = Math.max(spreadsheetElWidth - MIN_SHEET_VIEW_WIDTH, DEFAULT_SIDE_PANEL_SIZE);
40877
+ }
40878
+ else {
40879
+ this.panelSize = size;
40880
+ }
40881
+ }
40882
+ resetPanelSize() {
40883
+ this.panelSize = DEFAULT_SIDE_PANEL_SIZE;
40884
+ }
40816
40885
  computeState(componentTag, panelProps) {
40817
40886
  const customComputeState = sidePanelRegistry.get(componentTag).computeState;
40818
40887
  if (!customComputeState) {
@@ -41933,7 +42002,7 @@ class XLSXImportWarningManager {
41933
42002
  }
41934
42003
  }
41935
42004
 
41936
- const SUPPORTED_BORDER_STYLES = ["thin"];
42005
+ const SUPPORTED_BORDER_STYLES = ["thin", "medium", "thick", "dashed", "dotted"];
41937
42006
  const SUPPORTED_HORIZONTAL_ALIGNMENTS = [
41938
42007
  "general",
41939
42008
  "left",
@@ -51072,8 +51141,8 @@ class PivotCorePlugin extends CorePlugin {
51072
51141
  case "INSERT_PIVOT": {
51073
51142
  const { sheetId, col, row, pivotId, table } = cmd;
51074
51143
  const position = { sheetId, col, row };
51075
- const { cols, rows, measures, rowTitle } = table;
51076
- const spTable = new SpreadsheetPivotTable(cols, rows, measures, rowTitle);
51144
+ const { cols, rows, measures } = table;
51145
+ const spTable = new SpreadsheetPivotTable(cols, rows, measures);
51077
51146
  const formulaId = this.getPivotFormulaId(pivotId);
51078
51147
  this.insertPivot(position, formulaId, spTable);
51079
51148
  break;
@@ -51202,13 +51271,18 @@ class PivotCorePlugin extends CorePlugin {
51202
51271
  }
51203
51272
  }
51204
51273
  addPivotFormula(position, formulaId, pivotCell) {
51205
- const formula = pivotCell.isHeader ? "PIVOT.HEADER" : "PIVOT.VALUE";
51206
- const args = pivotCell.domain
51207
- ? [formulaId, pivotCell.measure, ...pivotCell.domain].filter(isDefined)
51208
- : undefined;
51274
+ let content = undefined;
51275
+ switch (pivotCell.type) {
51276
+ case "HEADER":
51277
+ content = makePivotFormula("PIVOT.HEADER", [formulaId, ...flatPivotDomain(pivotCell.domain)].filter(isDefined));
51278
+ break;
51279
+ case "VALUE":
51280
+ content = makePivotFormula("PIVOT.VALUE", [formulaId, pivotCell.measure, ...flatPivotDomain(pivotCell.domain)].filter(isDefined));
51281
+ break;
51282
+ }
51209
51283
  this.dispatch("UPDATE_CELL", {
51210
51284
  ...position,
51211
- content: pivotCell.content || (args ? makePivotFormula(formula, args) : undefined),
51285
+ content,
51212
51286
  });
51213
51287
  }
51214
51288
  getPivotCore(pivotId) {
@@ -51227,7 +51301,7 @@ class PivotCorePlugin extends CorePlugin {
51227
51301
  import(data) {
51228
51302
  if (data.pivots) {
51229
51303
  for (const [id, pivot] of Object.entries(data.pivots)) {
51230
- this.addPivot(id, deepCopy(pivot), pivot.formulaId);
51304
+ this.addPivot(id, pivot, pivot.formulaId);
51231
51305
  }
51232
51306
  }
51233
51307
  this.history.update("nextFormulaId", data.pivotNextId || getMaxObjectId(this.pivots) + 1);
@@ -54568,17 +54642,21 @@ class PivotUIPlugin extends UIPlugin {
54568
54642
  const pivotCol = position.col - mainPosition.col;
54569
54643
  const pivotRow = position.row - mainPosition.row;
54570
54644
  const pivotCell = pivotCells[pivotCol][pivotRow];
54571
- const domain = pivotCell.domain;
54572
- if (domain?.at(-2) === "measure") {
54573
- return domain.slice(0, -2);
54645
+ if (pivotCell.type === "EMPTY") {
54646
+ return undefined;
54647
+ }
54648
+ let domain = pivotCell.domain;
54649
+ if (domain.at(-1)?.field === "measure") {
54650
+ domain = domain.slice(0, -1);
54574
54651
  }
54575
- return domain;
54652
+ return { domainArgs: domain, isHeader: pivotCell.type === "HEADER" };
54576
54653
  }
54577
- const domain = args.slice(functionName === "PIVOT.VALUE" ? 2 : 1);
54578
- if (domain.at(-2) === "measure") {
54579
- return domain.slice(0, -2);
54654
+ let domain = toPivotDomain(args.slice(functionName === "PIVOT.VALUE" ? 2 : 1).map((x) => `${x}`));
54655
+ if (domain.at(-1)?.field === "measure") {
54656
+ domain = domain.slice(0, -1);
54580
54657
  }
54581
- return domain;
54658
+ const isHeader = functionName === "PIVOT.HEADER";
54659
+ return { domainArgs: domain, isHeader };
54582
54660
  }
54583
54661
  getPivot(pivotId) {
54584
54662
  return this.pivots[pivotId];
@@ -54591,9 +54669,9 @@ class PivotUIPlugin extends UIPlugin {
54591
54669
  * a pivot function are valid according to the pivot definition.
54592
54670
  * e.g. =PIVOT.VALUE(1,"revenue","country_id",...,"create_date:month",...,"source_id",...)
54593
54671
  */
54594
- areDomainArgsFieldsValid(pivotId, domainArgs) {
54595
- const dimensions = domainArgs
54596
- .filter((arg, index) => index % 2 === 0)
54672
+ areDomainArgsFieldsValid(pivotId, domain) {
54673
+ const dimensions = domain
54674
+ .map((node) => node.field)
54597
54675
  .map((name) => (name.startsWith("#") ? name.slice(1) : name));
54598
54676
  let argIndex = 0;
54599
54677
  let definitionIndex = 0;
@@ -61607,6 +61685,10 @@ css /* scss */ `
61607
61685
  }
61608
61686
  }
61609
61687
  }
61688
+ .o-sidePanelBody-container {
61689
+ /* This overwrites the min-height: auto; of flex. Without this, a flex div cannot be smaller than its children */
61690
+ min-height: 0;
61691
+ }
61610
61692
  .o-sidePanelBody {
61611
61693
  overflow: auto;
61612
61694
  width: 100%;
@@ -61685,24 +61767,6 @@ css /* scss */ `
61685
61767
  text-align: left;
61686
61768
  }
61687
61769
 
61688
- .o-inflection {
61689
- table {
61690
- table-layout: fixed;
61691
- margin-top: 2%;
61692
- display: table;
61693
- text-align: left;
61694
- font-size: 12px;
61695
- line-height: 18px;
61696
- width: 100%;
61697
- }
61698
- input,
61699
- select {
61700
- width: 100%;
61701
- height: 100%;
61702
- box-sizing: border-box;
61703
- }
61704
- }
61705
-
61706
61770
  .o-sidePanel-tools {
61707
61771
  color: #333;
61708
61772
  font-size: 13px;
@@ -61721,12 +61785,25 @@ css /* scss */ `
61721
61785
  }
61722
61786
  }
61723
61787
  }
61788
+
61789
+ .o-sidePanel-handle-container {
61790
+ width: 8px;
61791
+ }
61792
+ .o-sidePanel-handle {
61793
+ cursor: col-resize;
61794
+ color: #a9a9a9;
61795
+ .o-icon {
61796
+ height: 25px;
61797
+ margin-left: -5px;
61798
+ }
61799
+ }
61724
61800
  }
61725
61801
  `;
61726
61802
  class SidePanel extends owl.Component {
61727
61803
  static template = "o-spreadsheet-SidePanel";
61728
61804
  static props = {};
61729
61805
  sidePanelStore;
61806
+ spreadsheetRect = useSpreadsheetRect();
61730
61807
  setup() {
61731
61808
  this.sidePanelStore = useStore(SidePanelStore);
61732
61809
  owl.useEffect((isOpen) => {
@@ -61747,6 +61824,20 @@ class SidePanel extends owl.Component {
61747
61824
  ? panel.title(this.env, this.sidePanelStore.panelProps)
61748
61825
  : panel.title;
61749
61826
  }
61827
+ startHandleDrag(ev) {
61828
+ const startingCursor = document.body.style.cursor;
61829
+ const startSize = this.sidePanelStore.panelSize;
61830
+ const startPosition = ev.clientX;
61831
+ const onMouseMove = (ev) => {
61832
+ document.body.style.cursor = "col-resize";
61833
+ const newSize = startSize + startPosition - ev.clientX;
61834
+ this.sidePanelStore.changePanelSize(newSize, this.spreadsheetRect.width);
61835
+ };
61836
+ const cleanUp = () => {
61837
+ document.body.style.cursor = startingCursor;
61838
+ };
61839
+ startDnd(onMouseMove, cleanUp);
61840
+ }
61750
61841
  }
61751
61842
 
61752
61843
  css /* scss */ `
@@ -62530,7 +62621,6 @@ css /* scss */ `
62530
62621
  .o-spreadsheet {
62531
62622
  position: relative;
62532
62623
  display: grid;
62533
- grid-template-columns: auto 350px;
62534
62624
  color: #333;
62535
62625
  font-size: 14px;
62536
62626
 
@@ -62728,6 +62818,7 @@ class Spreadsheet extends owl.Component {
62728
62818
  };
62729
62819
  sidePanel;
62730
62820
  spreadsheetRef = owl.useRef("spreadsheet");
62821
+ spreadsheetRect = useSpreadsheetRect();
62731
62822
  _focusGrid;
62732
62823
  keyDownMapping;
62733
62824
  isViewportTooSmall = false;
@@ -62737,10 +62828,15 @@ class Spreadsheet extends owl.Component {
62737
62828
  return this.props.model;
62738
62829
  }
62739
62830
  getStyle() {
62831
+ const properties = {};
62740
62832
  if (this.env.isDashboard()) {
62741
- return `grid-template-rows: auto;`;
62833
+ properties["grid-template-rows"] = `auto`;
62834
+ }
62835
+ else {
62836
+ properties["grid-template-rows"] = `${TOPBAR_HEIGHT}px auto ${BOTTOMBAR_HEIGHT + 1}px`;
62742
62837
  }
62743
- return `grid-template-rows: ${TOPBAR_HEIGHT}px auto ${BOTTOMBAR_HEIGHT + 1}px`;
62838
+ properties["grid-template-columns"] = `auto ${this.sidePanel.panelSize}px`;
62839
+ return cssPropertiesToCss(properties);
62744
62840
  }
62745
62841
  setup() {
62746
62842
  const stores = useStoreProvider();
@@ -62800,14 +62896,19 @@ class Spreadsheet extends owl.Component {
62800
62896
  owl.onMounted(() => {
62801
62897
  this.checkViewportSize();
62802
62898
  stores.on("store-updated", this, render);
62899
+ resizeObserver.observe(this.spreadsheetRef.el);
62803
62900
  });
62804
62901
  owl.onWillUnmount(() => {
62805
62902
  this.unbindModelEvents();
62806
62903
  stores.off("store-updated", this);
62904
+ resizeObserver.disconnect();
62807
62905
  });
62808
62906
  owl.onPatched(() => {
62809
62907
  this.checkViewportSize();
62810
62908
  });
62909
+ const resizeObserver = new ResizeObserver(() => {
62910
+ this.sidePanel.changePanelSize(this.sidePanel.panelSize, this.spreadsheetRect.width);
62911
+ });
62811
62912
  }
62812
62913
  bindModelEvents() {
62813
62914
  this.model.on("update", this, () => this.render(true));
@@ -66862,6 +66963,8 @@ const helpers = {
66862
66963
  insertTokenAfterLeftParenthesis,
66863
66964
  mergeContiguousZones,
66864
66965
  getPivotHighlights,
66966
+ toPivotDomain,
66967
+ flatPivotDomain,
66865
66968
  pivotTimeAdapter,
66866
66969
  UNDO_REDO_PIVOT_COMMANDS,
66867
66970
  };
@@ -66906,6 +67009,7 @@ const components = {
66906
67009
  PivotDimension,
66907
67010
  PivotLayoutConfigurator,
66908
67011
  EditableName,
67012
+ PivotDeferUpdate,
66909
67013
  };
66910
67014
  const hooks = {
66911
67015
  useDragAndDropListItems,
@@ -66989,6 +67093,6 @@ exports.tokenColors = tokenColors;
66989
67093
  exports.tokenize = tokenize;
66990
67094
 
66991
67095
 
66992
- __info__.version = "17.4.0-alpha.1";
66993
- __info__.date = "2024-06-03T15:30:28.283Z";
66994
- __info__.hash = "cb56c37";
67096
+ __info__.version = "17.4.0-alpha.3";
67097
+ __info__.date = "2024-06-10T09:38:53.982Z";
67098
+ __info__.hash = "a45ed6a";