@odoo/o-spreadsheet 19.1.0-alpha.10 → 19.1.0-alpha.12

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 19.1.0-alpha.10
6
- * @date 2025-10-30T12:26:30.196Z
7
- * @hash d0b65e9
5
+ * @version 19.1.0-alpha.12
6
+ * @date 2025-11-12T14:17:07.713Z
7
+ * @hash 6fefc9c
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -157,6 +157,8 @@
157
157
  const MENU_WIDTH = 250;
158
158
  const MENU_VERTICAL_PADDING = 6;
159
159
  const DESKTOP_MENU_ITEM_HEIGHT = 26;
160
+ // Zoom
161
+ const ZOOM_VALUES = [50, 75, 100, 125, 150, 200];
160
162
  // Style
161
163
  const DEFAULT_STYLE = {
162
164
  align: "left",
@@ -246,7 +248,7 @@
246
248
  fontSize: CHART_TITLE_FONT_SIZE,
247
249
  color: TEXT_BODY,
248
250
  };
249
- const DEFAULT_TOKEN_COLOR = "#000000";
251
+ const DEFAULT_TOKEN_COLOR = "light-dark(#000000, #ffffff)";
250
252
  const functionColor = DEFAULT_TOKEN_COLOR;
251
253
  const operatorColor = "#3da4ab";
252
254
  const tokenColors = {
@@ -1774,7 +1776,10 @@
1774
1776
  * Check if a zone is inside another
1775
1777
  */
1776
1778
  function isZoneInside(smallZone, biggerZone) {
1777
- return isEqual(union(biggerZone, smallZone), biggerZone);
1779
+ return (smallZone.left >= biggerZone.left &&
1780
+ smallZone.right <= biggerZone.right &&
1781
+ smallZone.top >= biggerZone.top &&
1782
+ smallZone.bottom <= biggerZone.bottom);
1778
1783
  }
1779
1784
  function zoneToDimension(zone) {
1780
1785
  return {
@@ -2286,13 +2291,13 @@
2286
2291
  let optionalArg = 0;
2287
2292
  for (const arg of addDescr.args) {
2288
2293
  countArg++;
2289
- if (!arg.optional && !arg.repeating && !arg.default) {
2294
+ if (!arg.optional && !arg.default) {
2290
2295
  minArg++;
2291
2296
  }
2292
2297
  if (arg.repeating) {
2293
2298
  repeatingArg++;
2294
2299
  }
2295
- if (arg.optional || arg.default) {
2300
+ if ((arg.optional || arg.default) && !arg.repeating) {
2296
2301
  optionalArg++;
2297
2302
  }
2298
2303
  }
@@ -2300,7 +2305,7 @@
2300
2305
  descr.minArgRequired = minArg;
2301
2306
  descr.maxArgPossible = repeatingArg ? Infinity : countArg;
2302
2307
  descr.nbrArgRepeating = repeatingArg;
2303
- descr.nbrArgOptional = optionalArg;
2308
+ descr.nbrOptionalNonRepeatingArgs = optionalArg;
2304
2309
  descr.hidden = addDescr.hidden || false;
2305
2310
  descr.name = name;
2306
2311
  return descr;
@@ -2328,9 +2333,9 @@
2328
2333
  * and rows representing the correspondence with the argument index.
2329
2334
  *
2330
2335
  * The tables are built based on the following conventions:
2331
- * - `m`: Mandatory argument
2332
- * - `o`: Optional argument
2333
- * - `r`: Repeating argument
2336
+ * - `m`: Mandatory argument (count as one argument)
2337
+ * - `o`: Optional argument (count as zero or one argument)
2338
+ * - `r`: Repeating argument (count as one or more arguments)
2334
2339
  *
2335
2340
  *
2336
2341
  * Configuration 1: (m, o) like the CEILING function
@@ -2343,39 +2348,39 @@
2343
2348
  *
2344
2349
  * Configuration 2: (m, m, m, r, r) like the SUMIFS function
2345
2350
  *
2346
- * | | 3 | 5 | 7 | 3 + 2n |
2347
- * |---|---|---|------|------------|
2348
- * | m | 0 | 0 | 0 | 0 |
2349
- * | m | 1 | 1 | 1 | 1 |
2350
- * | m | 2 | 2 | 2 | 2 |
2351
- * | r | | 3 | 3, 5 | 3 + 2n |
2352
- * | r | | 4 | 4, 6 | 3 + 2n + 1 |
2351
+ * | | 5 | 7 | 3 + 2n |
2352
+ * |---|---|------|------------|
2353
+ * | m | 0 | 0 | 0 |
2354
+ * | m | 1 | 1 | 1 |
2355
+ * | m | 2 | 2 | 2 |
2356
+ * | r | 3 | 3, 5 | 3 + 2n |
2357
+ * | r | 4 | 4, 6 | 3 + 2n + 1 |
2353
2358
  *
2354
2359
  *
2355
2360
  * Configuration 3: (m, m, m, r, r, o) like the SWITCH function
2356
2361
  *
2357
- * | | 3 | 4 | 5 | 6 | 7 | 8 | 3 + 2n | 3 + 2n + 1 |
2358
- * |---|---|---|---|---|------|------|------------|----------------|
2359
- * | m | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2360
- * | m | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
2361
- * | m | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
2362
- * | r | | | 3 | 3 | 3, 5 | 3, 5 | 3 + 2n | 3 + 2n |
2363
- * | r | | | 4 | 4 | 4, 6 | 4, 6 | 3 + 2n + 1 | 3 + 2n + 1 |
2364
- * | o | | 3 | | 5 | | 7 | | 3 + 2N + 2 |
2362
+ * | | 5 | 6 | 7 | 8 | 3 + 2n | 3 + 2n + 1 |
2363
+ * |---|---|---|------|------|------------|----------------|
2364
+ * | m | 0 | 0 | 0 | 0 | 0 | 0 |
2365
+ * | m | 1 | 1 | 1 | 1 | 1 | 1 |
2366
+ * | m | 2 | 2 | 2 | 2 | 2 | 2 |
2367
+ * | r | 3 | 3 | 3, 5 | 3, 5 | 3 + 2n | 3 + 2n |
2368
+ * | r | 4 | 4 | 4, 6 | 4, 6 | 3 + 2n + 1 | 3 + 2n + 1 |
2369
+ * | o | | 5 | | 7 | | 3 + 2N + 2 |
2365
2370
  *
2366
2371
  *
2367
2372
  * Configuration 4: (m, o, m, o, r, r, r, m) a complex case to understand subtleties
2368
2373
  *
2369
- * | | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ... |
2370
- * |---|---|---|---|---|---|---|------|------|------|-----|
2371
- * | m | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... |
2372
- * | o | | 1 | 1 | | 1 | 1 | | 1 | 1 | ... |
2373
- * | m | 1 | 2 | 2 | 1 | 2 | 2 | 1 | 2 | 2 | ... |
2374
- * | o | | | 3 | | | 3 | | | 3 | ... |
2375
- * | r | | | | 2 | 3 | 4 | 2, 5 | 3, 6 | 4, 7 | ... |
2376
- * | r | | | | 3 | 4 | 5 | 3, 6 | 4, 7 | 5, 8 | ... |
2377
- * | r | | | | 4 | 5 | 6 | 4, 7 | 5, 8 | 6, 9 | ... |
2378
- * | m | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | ... |
2374
+ * | | 6 | 7 | 8 | 9 | 10 | 11 | ... |
2375
+ * |---|---|---|---|------|------|------|-----|
2376
+ * | m | 0 | 0 | 0 | 0 | 0 | 0 | ... |
2377
+ * | o | | 1 | 1 | | 1 | 1 | ... |
2378
+ * | m | 1 | 2 | 2 | 1 | 2 | 2 | ... |
2379
+ * | o | | | 3 | | | 3 | ... |
2380
+ * | r | 2 | 3 | 4 | 2, 5 | 3, 6 | 4, 7 | ... |
2381
+ * | r | 3 | 4 | 5 | 3, 6 | 4, 7 | 5, 8 | ... |
2382
+ * | r | 4 | 5 | 6 | 4, 7 | 5, 8 | 6, 9 | ... |
2383
+ * | m | 5 | 6 | 7 | 8 | 9 | 10 | ... |
2379
2384
  *
2380
2385
  */
2381
2386
  function argTargeting(functionDescription, nbrArgSupplied) {
@@ -2394,30 +2399,31 @@
2394
2399
  }
2395
2400
  function _argTargeting(functionDescription, nbrArgSupplied) {
2396
2401
  const valueIndexToArgPosition = {};
2397
- const groupsOfRepeatingValues = functionDescription.nbrArgRepeating
2402
+ const groupsOfOptionalRepeatingValues = functionDescription.nbrArgRepeating
2398
2403
  ? Math.floor((nbrArgSupplied - functionDescription.minArgRequired) / functionDescription.nbrArgRepeating)
2399
2404
  : 0;
2400
- const nbrValueRepeating = functionDescription.nbrArgRepeating * groupsOfRepeatingValues;
2401
- const nbrValueOptional = nbrArgSupplied - functionDescription.minArgRequired - nbrValueRepeating;
2405
+ const nbrValueOptionalRepeating = functionDescription.nbrArgRepeating * groupsOfOptionalRepeatingValues;
2406
+ const nbrValueOptional = nbrArgSupplied - functionDescription.minArgRequired - nbrValueOptionalRepeating;
2402
2407
  let countValueSupplied = 0;
2403
2408
  let countValueOptional = 0;
2404
2409
  for (let i = 0; i < functionDescription.args.length; i++) {
2405
2410
  const arg = functionDescription.args[i];
2406
- if (arg.optional || arg.default) {
2411
+ if ((arg.optional || arg.default) && !arg.repeating) {
2407
2412
  if (countValueOptional < nbrValueOptional) {
2408
- valueIndexToArgPosition[countValueSupplied] = i;
2413
+ valueIndexToArgPosition[countValueSupplied] = { index: i };
2409
2414
  countValueSupplied++;
2410
2415
  }
2411
2416
  countValueOptional++;
2412
2417
  continue;
2413
2418
  }
2414
2419
  if (arg.repeating) {
2420
+ const groupOfMandatoryRepeatingValues = arg.optional ? 0 : 1;
2415
2421
  // As we know all repeating arguments are consecutive,
2416
2422
  // --> we will treat all repeating arguments in one go
2417
2423
  // --> the index i will be incremented by the number of repeating values at the end of the loop
2418
- for (let j = 0; j < groupsOfRepeatingValues; j++) {
2424
+ for (let j = 0; j < groupsOfOptionalRepeatingValues + groupOfMandatoryRepeatingValues; j++) {
2419
2425
  for (let k = 0; k < functionDescription.nbrArgRepeating; k++) {
2420
- valueIndexToArgPosition[countValueSupplied] = i + k;
2426
+ valueIndexToArgPosition[countValueSupplied] = { index: i + k, repeatingGroupIndex: j };
2421
2427
  countValueSupplied++;
2422
2428
  }
2423
2429
  }
@@ -2425,7 +2431,7 @@
2425
2431
  continue;
2426
2432
  }
2427
2433
  // End case: it's a required argument
2428
- valueIndexToArgPosition[countValueSupplied] = i;
2434
+ valueIndexToArgPosition[countValueSupplied] = { index: i };
2429
2435
  countValueSupplied++;
2430
2436
  }
2431
2437
  return (argPosition) => {
@@ -2437,7 +2443,7 @@
2437
2443
  //------------------------------------------------------------------------------
2438
2444
  const META_TYPES = ["META", "RANGE<META>"];
2439
2445
  function validateArguments(descr) {
2440
- if (descr.nbrArgRepeating && descr.nbrArgOptional >= descr.nbrArgRepeating) {
2446
+ if (descr.nbrArgRepeating && descr.nbrOptionalNonRepeatingArgs >= descr.nbrArgRepeating) {
2441
2447
  throw new Error(`Function ${descr.name} has more optional arguments than repeatable ones.`);
2442
2448
  }
2443
2449
  let foundRepeating = false;
@@ -4123,7 +4129,7 @@
4123
4129
  const getArgToFocus = argTargeting(descr, args.length);
4124
4130
  //#region Compute vectorisation limits
4125
4131
  for (let i = 0; i < args.length; i++) {
4126
- const argIndex = getArgToFocus(i) ?? -1;
4132
+ const argIndex = getArgToFocus(i).index ?? -1;
4127
4133
  const argDefinition = descr.args[argIndex];
4128
4134
  const arg = args[i];
4129
4135
  if (!isMatrix(arg) && argDefinition.acceptMatrixOnly) {
@@ -4137,7 +4143,7 @@
4137
4143
  for (let i = 0; i < args.length; i++) {
4138
4144
  const arg = args[i];
4139
4145
  const getArgToFocus = argTargeting(descr, args.length);
4140
- const argDefinition = descr.args[getArgToFocus(i) || i];
4146
+ const argDefinition = descr.args[getArgToFocus(i).index ?? i];
4141
4147
  // Early exit if the argument is an error and the function does not accept errors
4142
4148
  // We only check scalar arguments, not matrix arguments for performance reasons.
4143
4149
  // Casting helpers are responsible for handling errors in matrix arguments.
@@ -4405,8 +4411,7 @@
4405
4411
  description: _t$1("Creates a new array from the selected columns in the existing range."),
4406
4412
  args: [
4407
4413
  arg("array (any, range<any>)", _t$1("The array that contains the columns to be returned.")),
4408
- arg("col_num (number, range<number>)", _t$1("The first column index of the columns to be returned.")),
4409
- arg("col_num2 (number, range<number>, repeating)", _t$1("The columns indexes of the columns to be returned.")),
4414
+ arg("col_num (number, range<number>, repeating)", _t$1("The column index of the column to be returned.")),
4410
4415
  ],
4411
4416
  compute: function (array, ...columns) {
4412
4417
  const _array = toMatrix(array);
@@ -4435,8 +4440,7 @@
4435
4440
  description: _t$1("Creates a new array from the selected rows in the existing range."),
4436
4441
  args: [
4437
4442
  arg("array (any, range<any>)", _t$1("The array that contains the rows to be returned.")),
4438
- arg("row_num (number, range<number>)", _t$1("The first row index of the rows to be returned.")),
4439
- arg("row_num2 (number, range<number>, repeating)", _t$1("The rows indexes of the rows to be returned.")),
4443
+ arg("row_num (number, range<number>, repeating)", _t$1("The row index of the row to be returned.")),
4440
4444
  ],
4441
4445
  compute: function (array, ...rows) {
4442
4446
  const _array = toMatrix(array);
@@ -4486,10 +4490,7 @@
4486
4490
  // -----------------------------------------------------------------------------
4487
4491
  const FLATTEN = {
4488
4492
  description: _t$1("Flattens all the values from one or more ranges into a single column."),
4489
- args: [
4490
- arg("range (any, range<any>)", _t$1("The first range to flatten.")),
4491
- arg("range2 (any, range<any>, repeating)", _t$1("Additional ranges to flatten.")),
4492
- ],
4493
+ args: [arg("range (any, range<any>, repeating)", _t$1("The range to flatten."))],
4493
4494
  compute: function (...ranges) {
4494
4495
  return [flattenRowFirst(ranges, (val) => (val === undefined ? { value: "" } : val))];
4495
4496
  },
@@ -4547,10 +4548,7 @@
4547
4548
  // -----------------------------------------------------------------------------
4548
4549
  const HSTACK = {
4549
4550
  description: _t$1("Appends ranges horizontally and in sequence to return a larger array."),
4550
- args: [
4551
- arg("range1 (any, range<any>)", _t$1("The first range to be appended.")),
4552
- arg("range2 (any, range<any>, repeating)", _t$1("Additional ranges to add to range1.")),
4553
- ],
4551
+ args: [arg("range (any, range<any>, repeating)", _t$1("The range to be appended."))],
4554
4552
  compute: function (...ranges) {
4555
4553
  const nbRows = Math.max(...ranges.map((r) => r?.[0]?.length ?? 0));
4556
4554
  const result = [];
@@ -4636,8 +4634,7 @@
4636
4634
  const SUMPRODUCT = {
4637
4635
  description: _t$1("Calculates the sum of the products of corresponding entries in equal-sized ranges."),
4638
4636
  args: [
4639
- arg("range1 (number, range<number>)", _t$1("The first range whose entries will be multiplied with corresponding entries in the other ranges.")),
4640
- arg("range2 (number, range<number>, repeating)", _t$1("The other range whose entries will be multiplied with corresponding entries in the other ranges.")),
4637
+ arg("range (number, range<number>, repeating)", _t$1("The range whose entries will be multiplied with corresponding entries in the other range.")),
4641
4638
  ],
4642
4639
  compute: function (...args) {
4643
4640
  if (!areSameDimensions(...args)) {
@@ -4823,10 +4820,7 @@
4823
4820
  // -----------------------------------------------------------------------------
4824
4821
  const VSTACK = {
4825
4822
  description: _t$1("Appends ranges vertically and in sequence to return a larger array."),
4826
- args: [
4827
- arg("range1 (any, range<any>)", _t$1("The first range to be appended.")),
4828
- arg("range2 (any, range<any>, repeating)", _t$1("Additional ranges to add to range1.")),
4829
- ],
4823
+ args: [arg("range (any, range<any>, repeating)", _t$1("The range to be appended."))],
4830
4824
  compute: function (...ranges) {
4831
4825
  const nbColumns = Math.max(...ranges.map((range) => toMatrix(range).length));
4832
4826
  const nbRows = ranges.reduce((acc, range) => acc + toMatrix(range)[0].length, 0);
@@ -6393,6 +6387,7 @@
6393
6387
  "COPY",
6394
6388
  "RESIZE_SHEETVIEW",
6395
6389
  "SET_VIEWPORT_OFFSET",
6390
+ "SET_ZOOM",
6396
6391
  "EVALUATE_CELLS",
6397
6392
  "EVALUATE_CHARTS",
6398
6393
  "SET_FORMULA_VISIBILITY",
@@ -7108,8 +7103,7 @@
7108
7103
  const COUNTBLANK = {
7109
7104
  description: _t$1("Number of empty values."),
7110
7105
  args: [
7111
- arg("value1 (any, range)", _t$1("The first value or range in which to count the number of blanks.")),
7112
- arg("value2 (any, range, repeating)", _t$1("Additional values or ranges in which to count the number of blanks.")),
7106
+ arg("value (any, range, repeating)", _t$1("Value or range in which to count the number of blanks.")),
7113
7107
  ],
7114
7108
  compute: function (...args) {
7115
7109
  return reduceAny(args, (acc, a) => {
@@ -7151,10 +7145,8 @@
7151
7145
  const COUNTIFS = {
7152
7146
  description: _t$1("Count values depending on multiple criteria."),
7153
7147
  args: [
7154
- arg("criteria_range1 (range)", _t$1("The range to check against criterion1.")),
7155
- arg("criterion1 (string)", _t$1("The pattern or test to apply to criteria_range1.")),
7156
- arg("criteria_range2 (any, range, repeating)", _t$1("Additional ranges over which to evaluate the additional criteria. The filtered set will be the intersection of the sets produced by each criterion-range pair.")),
7157
- arg("criterion2 (string, repeating)", _t$1("Additional criteria to check.")),
7148
+ arg("criteria_range (any, range, repeating)", _t$1("Range over which to evaluate criteria.")),
7149
+ arg("criterion (string, repeating)", _t$1("Criteria to check.")),
7158
7150
  ],
7159
7151
  compute: function (...args) {
7160
7152
  let count = 0;
@@ -7170,10 +7162,7 @@
7170
7162
  // -----------------------------------------------------------------------------
7171
7163
  const COUNTUNIQUE = {
7172
7164
  description: _t$1("Counts number of unique values in a range."),
7173
- args: [
7174
- arg("value1 (any, range)", _t$1("The first value or range to consider for uniqueness.")),
7175
- arg("value2 (any, range, repeating)", _t$1("Additional values or ranges to consider for uniqueness.")),
7176
- ],
7165
+ args: [arg("value (any, range, repeating)", _t$1("Value or range to consider for uniqueness."))],
7177
7166
  compute: function (...args) {
7178
7167
  return countUnique(args);
7179
7168
  },
@@ -7185,10 +7174,8 @@
7185
7174
  description: _t$1("Counts number of unique values in a range, filtered by a set of criteria."),
7186
7175
  args: [
7187
7176
  arg("range (range)", _t$1("The range of cells from which the number of unique values will be counted.")),
7188
- arg("criteria_range1 (range)", _t$1("The range of cells over which to evaluate criterion1.")),
7189
- arg("criterion1 (string)", _t$1("The pattern or test to apply to criteria_range1, such that each cell that evaluates to TRUE will be included in the filtered set.")),
7190
- arg("criteria_range2 (any, range, repeating)", _t$1("Additional ranges over which to evaluate the additional criteria. The filtered set will be the intersection of the sets produced by each criterion-range pair.")),
7191
- arg("criterion2 (string, repeating)", _t$1("The pattern or test to apply to criteria_range2.")),
7177
+ arg("criteria_range (any, range, repeating)", _t$1("Range over which to evaluate criteria.")),
7178
+ arg("criterion (string, repeating)", _t$1("Criteria to check.")),
7192
7179
  ],
7193
7180
  compute: function (range, ...args) {
7194
7181
  const uniqueValues = new Set();
@@ -7544,8 +7531,7 @@
7544
7531
  const PRODUCT = {
7545
7532
  description: _t$1("Result of multiplying a series of numbers together."),
7546
7533
  args: [
7547
- arg("factor1 (number, range<number>)", _t$1("The first number or range to calculate for the product.")),
7548
- arg("factor2 (number, range<number>, repeating)", _t$1("More numbers or ranges to calculate for the product.")),
7534
+ arg("factor (number, range<number>, repeating)", _t$1("Number or range to calculate for the product.")),
7549
7535
  ],
7550
7536
  compute: function (...factors) {
7551
7537
  let count = 0;
@@ -7877,8 +7863,7 @@
7877
7863
  ...subtotalFunctionOptionsIncludeHiddenRows,
7878
7864
  ...subtotalFunctionOptionsExcludeHiddenRows,
7879
7865
  ]),
7880
- arg("ref1 (meta, range<meta>)", _t$1("The range or reference for which you want the subtotal.")),
7881
- arg("ref2 (meta, range<meta>, repeating)", _t$1("Additional ranges or references for which you want the subtotal.")),
7866
+ arg("ref (meta, range<meta>, repeating)", _t$1("Range or reference for which you want the subtotal.")),
7882
7867
  ],
7883
7868
  compute: function (functionCode, ...refs) {
7884
7869
  let code = toInteger(functionCode, this.locale);
@@ -7922,10 +7907,7 @@
7922
7907
  // -----------------------------------------------------------------------------
7923
7908
  const SUM = {
7924
7909
  description: _t$1("Sum of a series of numbers and/or cells."),
7925
- args: [
7926
- arg("value1 (number, range<number>)", _t$1("The first number or range to add together.")),
7927
- arg("value2 (number, range<number>, repeating)", _t$1("Additional numbers or ranges to add to value1.")),
7928
- ],
7910
+ args: [arg("value (number, range<number>, repeating)", _t$1("Number or range to add together."))],
7929
7911
  compute: function (...values) {
7930
7912
  const v1 = values[0];
7931
7913
  return {
@@ -7967,10 +7949,8 @@
7967
7949
  description: _t$1("Sums a range depending on multiple criteria."),
7968
7950
  args: [
7969
7951
  arg("sum_range (range)", _t$1("The range to sum.")),
7970
- arg("criteria_range1 (range)", _t$1("The range to check against criterion1.")),
7971
- arg("criterion1 (string)", _t$1("The pattern or test to apply to criteria_range1.")),
7972
- arg("criteria_range2 (any, range, repeating)", _t$1("Additional ranges to check.")),
7973
- arg("criterion2 (string, repeating)", _t$1("Additional criteria to check.")),
7952
+ arg("criteria_range (any, range, repeating)", _t$1("Range to check.")),
7953
+ arg("criterion (string, repeating)", _t$1("Criteria to check.")),
7974
7954
  ],
7975
7955
  compute: function (sumRange, ...criters) {
7976
7956
  let sum = 0;
@@ -8452,8 +8432,7 @@
8452
8432
  const AVEDEV = {
8453
8433
  description: _t$1("Average magnitude of deviations from mean."),
8454
8434
  args: [
8455
- arg("value1 (number, range<number>)", _t$1("The first value or range of the sample.")),
8456
- arg("value2 (number, range<number>, repeating)", _t$1("Additional values or ranges to include in the sample.")),
8435
+ arg("value (number, range<number>, repeating)", _t$1("Value or range to include in the sample.")),
8457
8436
  ],
8458
8437
  compute: function (...values) {
8459
8438
  let count = 0;
@@ -8475,8 +8454,7 @@
8475
8454
  const AVERAGE = {
8476
8455
  description: _t$1("Numerical average value in a dataset, ignoring text."),
8477
8456
  args: [
8478
- arg("value1 (number, range<number>)", _t$1("The first value or range to consider when calculating the average value.")),
8479
- arg("value2 (number, range<number>, repeating)", _t$1("Additional values or ranges to consider when calculating the average value.")),
8457
+ arg("value (number, range<number>, repeating)", _t$1("Value or range to consider when calculating the average value.")),
8480
8458
  ],
8481
8459
  compute: function (...values) {
8482
8460
  return {
@@ -8494,10 +8472,8 @@
8494
8472
  const AVERAGE_WEIGHTED = {
8495
8473
  description: _t$1("Weighted average."),
8496
8474
  args: [
8497
- arg("values (number, range<number>)", _t$1("Values to average.")),
8498
- arg("weights (number, range<number>)", _t$1("Weights for each corresponding value.")),
8499
- arg("additional_values (number, range<number>, repeating)", _t$1("Additional values to average.")),
8500
- arg("additional_weights (number, range<number>, repeating)", _t$1("Additional weights.")),
8475
+ arg("values (number, range<number>, repeating)", _t$1("Value to average.")),
8476
+ arg("weights (number, range<number>, repeating)", _t$1("Weight for each corresponding value.")),
8501
8477
  ],
8502
8478
  compute: function (...args) {
8503
8479
  let sum = 0;
@@ -8553,8 +8529,7 @@
8553
8529
  const AVERAGEA = {
8554
8530
  description: _t$1("Numerical average value in a dataset."),
8555
8531
  args: [
8556
- arg("value1 (number, range<number>)", _t$1("The first value or range to consider when calculating the average value.")),
8557
- arg("value2 (number, range<number>, repeating)", _t$1("Additional values or ranges to consider when calculating the average value.")),
8532
+ arg("value (number, range<number>, repeating)", _t$1("Value or range to consider when calculating the average value.")),
8558
8533
  ],
8559
8534
  compute: function (...args) {
8560
8535
  let count = 0;
@@ -8607,10 +8582,8 @@
8607
8582
  description: _t$1("Average of values depending on multiple criteria."),
8608
8583
  args: [
8609
8584
  arg("average_range (range)", _t$1("The range to average.")),
8610
- arg("criteria_range1 (range)", _t$1("The range to check against criterion1.")),
8611
- arg("criterion1 (string)", _t$1("The pattern or test to apply to criteria_range1.")),
8612
- arg("criteria_range2 (any, range, repeating)", _t$1("Additional criteria_range and criterion to check.")),
8613
- arg("criterion2 (string, repeating)", _t$1("The pattern or test to apply to criteria_range2.")),
8585
+ arg("criteria_range (any, range, repeating)", _t$1("Range to check.")),
8586
+ arg("criterion (string, repeating)", _t$1("Criterion to check.")),
8614
8587
  ],
8615
8588
  compute: function (averageRange, ...args) {
8616
8589
  const _averageRange = toMatrix(averageRange);
@@ -8636,8 +8609,7 @@
8636
8609
  const COUNT = {
8637
8610
  description: _t$1("The number of numeric values in dataset."),
8638
8611
  args: [
8639
- arg("value1 (number, any, range<number>)", _t$1("The first value or range to consider when counting.")),
8640
- arg("value2 (number, any, range<number>, repeating)", _t$1("Additional values or ranges to consider when counting.")),
8612
+ arg("value (number, any, range<number>, repeating)", _t$1("Value or range to consider when counting.")),
8641
8613
  ],
8642
8614
  compute: function (...values) {
8643
8615
  return countNumbers(values, this.locale);
@@ -8649,10 +8621,7 @@
8649
8621
  // -----------------------------------------------------------------------------
8650
8622
  const COUNTA = {
8651
8623
  description: _t$1("The number of values in a dataset."),
8652
- args: [
8653
- arg("value1 (any, range)", _t$1("The first value or range to consider when counting.")),
8654
- arg("value2 (any, range, repeating)", _t$1("Additional values or ranges to consider when counting.")),
8655
- ],
8624
+ args: [arg("value (any, range, repeating)", _t$1("Value or range to consider when counting."))],
8656
8625
  compute: function (...values) {
8657
8626
  return countAny(values);
8658
8627
  },
@@ -8885,8 +8854,7 @@
8885
8854
  const MAX = {
8886
8855
  description: _t$1("Maximum value in a numeric dataset."),
8887
8856
  args: [
8888
- arg("value1 (number, range<number>)", _t$1("The first value or range to consider when calculating the maximum value.")),
8889
- arg("value2 (number, range<number>, repeating)", _t$1("Additional values or ranges to consider when calculating the maximum value.")),
8857
+ arg("value (number, range<number>, repeating)", _t$1("Value or range to consider when calculating the maximum value.")),
8890
8858
  ],
8891
8859
  compute: function (...values) {
8892
8860
  return max(values, this.locale);
@@ -8899,8 +8867,7 @@
8899
8867
  const MAXA = {
8900
8868
  description: _t$1("Maximum numeric value in a dataset."),
8901
8869
  args: [
8902
- arg("value1 (any, range)", _t$1("The first value or range to consider when calculating the maximum value.")),
8903
- arg("value2 (any, range, repeating)", _t$1("Additional values or ranges to consider when calculating the maximum value.")),
8870
+ arg("value (any, range, repeating)", _t$1("Value or range to consider when calculating the maximum value.")),
8904
8871
  ],
8905
8872
  compute: function (...args) {
8906
8873
  const maxa = reduceNumbersTextAs0(args, (acc, a) => {
@@ -8917,10 +8884,8 @@
8917
8884
  description: _t$1("Returns the maximum value in a range of cells, filtered by a set of criteria."),
8918
8885
  args: [
8919
8886
  arg("range (range)", _t$1("The range of cells from which the maximum will be determined.")),
8920
- arg("criteria_range1 (range)", _t$1("The range of cells over which to evaluate criterion1.")),
8921
- arg("criterion1 (string)", _t$1("The pattern or test to apply to criteria_range1, such that each cell that evaluates to TRUE will be included in the filtered set.")),
8922
- arg("criteria_range2 (any, range, repeating)", _t$1("Additional ranges over which to evaluate the additional criteria. The filtered set will be the intersection of the sets produced by each criterion-range pair.")),
8923
- arg("criterion2 (string, repeating)", _t$1("The pattern or test to apply to criteria_range2.")),
8887
+ arg("criteria_range (any, range, repeating)", _t$1("Range to evaluate criteria.")),
8888
+ arg("criterion (string, repeating)", _t$1("Criteria to check.")),
8924
8889
  ],
8925
8890
  compute: function (range, ...args) {
8926
8891
  let result = -Infinity;
@@ -8940,8 +8905,7 @@
8940
8905
  const MEDIAN = {
8941
8906
  description: _t$1("Median value in a numeric dataset."),
8942
8907
  args: [
8943
- arg("value1 (any, range)", _t$1("The first value or range to consider when calculating the median value.")),
8944
- arg("value2 (any, range, repeating)", _t$1("Additional values or ranges to consider when calculating the median value.")),
8908
+ arg("value (any, range, repeating)", _t$1("Value or range to consider when calculating the median value.")),
8945
8909
  ],
8946
8910
  compute: function (...values) {
8947
8911
  const data = [];
@@ -8961,8 +8925,7 @@
8961
8925
  const MIN = {
8962
8926
  description: _t$1("Minimum value in a numeric dataset."),
8963
8927
  args: [
8964
- arg("value1 (number, range<number>)", _t$1("The first value or range to consider when calculating the minimum value.")),
8965
- arg("value2 (number, range<number>, repeating)", _t$1("Additional values or ranges to consider when calculating the minimum value.")),
8928
+ arg("value (number, range<number>, repeating)", _t$1("Value or range to consider when calculating the minimum value.")),
8966
8929
  ],
8967
8930
  compute: function (...values) {
8968
8931
  return min(values, this.locale);
@@ -8975,8 +8938,7 @@
8975
8938
  const MINA = {
8976
8939
  description: _t$1("Minimum numeric value in a dataset."),
8977
8940
  args: [
8978
- arg("value1 (number, range<number>)", _t$1("The first value or range to consider when calculating the minimum value.")),
8979
- arg("value2 (number, range<number>, repeating)", _t$1("Additional values or ranges to consider when calculating the minimum value.")),
8941
+ arg("value (number, range<number>, repeating)", _t$1("Value or range to consider when calculating the minimum value.")),
8980
8942
  ],
8981
8943
  compute: function (...args) {
8982
8944
  const mina = reduceNumbersTextAs0(args, (acc, a) => {
@@ -8993,10 +8955,8 @@
8993
8955
  description: _t$1("Returns the minimum value in a range of cells, filtered by a set of criteria."),
8994
8956
  args: [
8995
8957
  arg("range (range)", _t$1("The range of cells from which the minimum will be determined.")),
8996
- arg("criteria_range1 (range)", _t$1("The range of cells over which to evaluate criterion1.")),
8997
- arg("criterion1 (string)", _t$1("The pattern or test to apply to criteria_range1, such that each cell that evaluates to TRUE will be included in the filtered set.")),
8998
- arg("criteria_range2 (any, range, repeating)", _t$1("Additional ranges over which to evaluate the additional criteria. The filtered set will be the intersection of the sets produced by each criterion-range pair.")),
8999
- arg("criterion2 (string, repeating)", _t$1("The pattern or test to apply to criteria_range2.")),
8958
+ arg("criteria_range (any, range, repeating)", _t$1("Range to evaluate criteria.")),
8959
+ arg("criterion (string, repeating)", _t$1("Criterion to check.")),
9000
8960
  ],
9001
8961
  compute: function (range, ...args) {
9002
8962
  let result = Infinity;
@@ -9337,8 +9297,7 @@
9337
9297
  const STDEV = {
9338
9298
  description: _t$1("Standard deviation."),
9339
9299
  args: [
9340
- arg("value1 (number, range<number>)", _t$1("The first value or range of the sample.")),
9341
- arg("value2 (number, range<number>, repeating)", _t$1("Additional values or ranges to include in the sample.")),
9300
+ arg("value (number, range<number>, repeating)", _t$1("Value or range to include in the sample.")),
9342
9301
  ],
9343
9302
  compute: function (...args) {
9344
9303
  return Math.sqrt(VAR.compute.bind(this)(...args));
@@ -9351,8 +9310,7 @@
9351
9310
  const STDEV_P = {
9352
9311
  description: _t$1("Standard deviation of entire population."),
9353
9312
  args: [
9354
- arg("value1 (number, range<number>)", _t$1("The first value or range of the population.")),
9355
- arg("value2 (number, range<number>, repeating)", _t$1("Additional values or ranges to include in the population.")),
9313
+ arg("value (number, range<number>, repeating)", _t$1("Value or range to include in the population.")),
9356
9314
  ],
9357
9315
  compute: function (...args) {
9358
9316
  return Math.sqrt(VAR_P.compute.bind(this)(...args));
@@ -9365,8 +9323,7 @@
9365
9323
  const STDEV_S = {
9366
9324
  description: _t$1("Standard deviation."),
9367
9325
  args: [
9368
- arg("value1 (number, range<number>)", _t$1("The first value or range of the sample.")),
9369
- arg("value2 (number, range<number>, repeating)", _t$1("Additional values or ranges to include in the sample.")),
9326
+ arg("value (number, range<number>, repeating)", _t$1("Value or range to include in the sample.")),
9370
9327
  ],
9371
9328
  compute: function (...args) {
9372
9329
  return Math.sqrt(VAR_S.compute.bind(this)(...args));
@@ -9379,8 +9336,7 @@
9379
9336
  const STDEVA = {
9380
9337
  description: _t$1("Standard deviation of sample (text as 0)."),
9381
9338
  args: [
9382
- arg("value1 (number, range<number>)", _t$1("The first value or range of the sample.")),
9383
- arg("value2 (number, range<number>, repeating)", _t$1("Additional values or ranges to include in the sample.")),
9339
+ arg("value (number, range<number>, repeating)", _t$1("Value or range to include in the sample.")),
9384
9340
  ],
9385
9341
  compute: function (...args) {
9386
9342
  return Math.sqrt(VARA.compute.bind(this)(...args));
@@ -9393,8 +9349,7 @@
9393
9349
  const STDEVP = {
9394
9350
  description: _t$1("Standard deviation of entire population."),
9395
9351
  args: [
9396
- arg("value1 (number, range<number>)", _t$1("The first value or range of the population.")),
9397
- arg("value2 (number, range<number>, repeating)", _t$1("Additional values or ranges to include in the population.")),
9352
+ arg("value (number, range<number>, repeating)", _t$1("Value or range to include in the population.")),
9398
9353
  ],
9399
9354
  compute: function (...args) {
9400
9355
  return Math.sqrt(VARP.compute.bind(this)(...args));
@@ -9407,8 +9362,7 @@
9407
9362
  const STDEVPA = {
9408
9363
  description: _t$1("Standard deviation of entire population (text as 0)."),
9409
9364
  args: [
9410
- arg("value1 (number, range<number>)", _t$1("The first value or range of the population.")),
9411
- arg("value2 (number, range<number>, repeating)", _t$1("Additional values or ranges to include in the population.")),
9365
+ arg("value (number, range<number>, repeating)", _t$1("Value or range to include in the population.")),
9412
9366
  ],
9413
9367
  compute: function (...args) {
9414
9368
  return Math.sqrt(VARPA.compute.bind(this)(...args));
@@ -9458,8 +9412,7 @@
9458
9412
  const VAR = {
9459
9413
  description: _t$1("Variance."),
9460
9414
  args: [
9461
- arg("value1 (number, range<number>)", _t$1("The first value or range of the sample.")),
9462
- arg("value2 (number, range<number>, repeating)", _t$1("Additional values or ranges to include in the sample.")),
9415
+ arg("value (number, range<number>, repeating)", _t$1("Value or range to include in the sample.")),
9463
9416
  ],
9464
9417
  compute: function (...args) {
9465
9418
  return variance(args, true, false, this.locale);
@@ -9472,8 +9425,7 @@
9472
9425
  const VAR_P = {
9473
9426
  description: _t$1("Variance of entire population."),
9474
9427
  args: [
9475
- arg("value1 (number, range<number>)", _t$1("The first value or range of the population.")),
9476
- arg("value2 (number, range<number>, repeating)", _t$1("Additional values or ranges to include in the population.")),
9428
+ arg("value (number, range<number>, repeating)", _t$1("Value or range to include in the population.")),
9477
9429
  ],
9478
9430
  compute: function (...args) {
9479
9431
  return variance(args, false, false, this.locale);
@@ -9486,8 +9438,7 @@
9486
9438
  const VAR_S = {
9487
9439
  description: _t$1("Variance."),
9488
9440
  args: [
9489
- arg("value1 (number, range<number>)", _t$1("The first value or range of the sample.")),
9490
- arg("value2 (number, range<number>, repeating)", _t$1("Additional values or ranges to include in the sample.")),
9441
+ arg("value (number, range<number>, repeating)", _t$1("Value or range to include in the sample.")),
9491
9442
  ],
9492
9443
  compute: function (...args) {
9493
9444
  return variance(args, true, false, this.locale);
@@ -9500,8 +9451,7 @@
9500
9451
  const VARA = {
9501
9452
  description: _t$1("Variance of sample (text as 0)."),
9502
9453
  args: [
9503
- arg("value1 (number, range<number>)", _t$1("The first value or range of the sample.")),
9504
- arg("value2 (number, range<number>, repeating)", _t$1("Additional values or ranges to include in the sample.")),
9454
+ arg("value (number, range<number>, repeating)", _t$1("Value or range to include in the sample.")),
9505
9455
  ],
9506
9456
  compute: function (...args) {
9507
9457
  return variance(args, true, true, this.locale);
@@ -9514,8 +9464,7 @@
9514
9464
  const VARP = {
9515
9465
  description: _t$1("Variance of entire population."),
9516
9466
  args: [
9517
- arg("value1 (number, range<number>)", _t$1("The first value or range of the population.")),
9518
- arg("value2 (number, range<number>, repeating)", _t$1("Additional values or ranges to include in the population.")),
9467
+ arg("value (number, range<number>, repeating)", _t$1("Value or range to include in the population.")),
9519
9468
  ],
9520
9469
  compute: function (...args) {
9521
9470
  return variance(args, false, false, this.locale);
@@ -9528,8 +9477,7 @@
9528
9477
  const VARPA = {
9529
9478
  description: _t$1("Variance of entire population (text as 0)."),
9530
9479
  args: [
9531
- arg("value1 (number, range<number>)", _t$1("The first value or range of the population.")),
9532
- arg("value2 (number, range<number>, repeating)", _t$1("Additional values or ranges to include in the population.")),
9480
+ arg("value (number, range<number>, repeating)", _t$1("Value or range to include in the population.")),
9533
9481
  ],
9534
9482
  compute: function (...args) {
9535
9483
  return variance(args, false, true, this.locale);
@@ -11433,8 +11381,7 @@
11433
11381
  // TODO modify args description when vectorization on formulas is available
11434
11382
  args: [
11435
11383
  arg("range (any, range<any>)", _t$1("The data to be filtered.")),
11436
- arg("condition1 (boolean, range<boolean>)", _t$1("A column or row containing true or false values corresponding to the first column or row of range.")),
11437
- arg("condition2 (boolean, range<boolean>, repeating)", _t$1("Additional column or row containing true or false values.")),
11384
+ arg("condition (boolean, range<boolean>, repeating)", _t$1("Column or row containing true or false values corresponding to the range.")),
11438
11385
  ],
11439
11386
  compute: function (range, ...conditions) {
11440
11387
  let _array = toMatrix(range);
@@ -11474,8 +11421,8 @@
11474
11421
  description: _t$1("Sorts the rows of a given array or range by the values in one or more columns."),
11475
11422
  args: [
11476
11423
  arg("range (range)", _t$1("The data to be sorted.")),
11477
- arg("sort_column (any, range<number>, repeating)", _t$1("The index of the column in range or a range outside of range containing the values by which to sort.")),
11478
- arg("is_ascending (boolean, repeating)", _t$1("TRUE or FALSE indicating whether to sort sort_column in ascending order."), [
11424
+ arg("sort_column (any, range<number>, repeating, optional)", _t$1("The index of the column in range or a range outside of range containing the value by which to sort.")),
11425
+ arg("is_ascending (boolean, repeating, optional)", _t$1("TRUE or FALSE indicating whether to sort sort_column in ascending order. FALSE sorts in descending order."), [
11479
11426
  { value: true, label: _t$1("Ascending") },
11480
11427
  { value: false, label: _t$1("Descending") },
11481
11428
  ]),
@@ -11495,8 +11442,8 @@
11495
11442
  arg("range (range)", _t$1("The data to be sorted.")),
11496
11443
  arg("n (number)", _t$1("The number of items to return.")),
11497
11444
  arg("display_ties_mode (number, default=0)", _t$1("A number representing the way to display ties.")),
11498
- arg("sort_column (number, range<number>, repeating)", _t$1("The index of the column in range or a range outside of range containing the values by which to sort.")),
11499
- arg("is_ascending (boolean, repeating)", _t$1("TRUE or FALSE indicating whether to sort sort_column in ascending order."), [
11445
+ arg("sort_column (number, range<number>, repeating, optional)", _t$1("The index of the column in range or a range outside of range containing the value by which to sort.")),
11446
+ arg("is_ascending (boolean, repeating, optional)", _t$1("TRUE or FALSE indicating whether to sort sort_column in ascending order. FALSE sorts in descending order."), [
11500
11447
  { value: true, label: _t$1("Ascending") },
11501
11448
  { value: false, label: _t$1("Descending") },
11502
11449
  ]),
@@ -12764,8 +12711,7 @@
12764
12711
  description: _t$1("The net present value of an investment based on a series of periodic cash flows and a discount rate."),
12765
12712
  args: [
12766
12713
  arg("discount (number)", _t$1("The discount rate of the investment over one period.")),
12767
- arg("cashflow1 (number, range<number>)", _t$1("The first future cash flow.")),
12768
- arg("cashflow2 (number, range<number>, repeating)", _t$1("Additional future cash flows.")),
12714
+ arg("cashflow (number, range<number>, repeating)", _t$1("The future cash flows.")),
12769
12715
  ],
12770
12716
  // to do: replace by dollar format
12771
12717
  compute: function (discount, ...values) {
@@ -14120,8 +14066,7 @@
14120
14066
  const AND = {
14121
14067
  description: _t$1("Logical `and` operator."),
14122
14068
  args: [
14123
- arg("logical_expression1 (boolean, range<boolean>)", _t$1("An expression or reference to a cell containing an expression that represents some logical value, i.e. TRUE or FALSE, or an expression that can be coerced to a logical value.")),
14124
- arg("logical_expression2 (boolean, range<boolean>, repeating)", _t$1("More expressions that represent logical values.")),
14069
+ arg("logical_expression (boolean, range<boolean>, repeating)", _t$1("Expression or reference to a cell containing a logical value (TRUE/FALSE) or an expression that can be coerced to a logical value.")),
14125
14070
  ],
14126
14071
  compute: function (...logicalExpressions) {
14127
14072
  const { result, foundBoolean } = boolAnd(logicalExpressions);
@@ -14204,10 +14149,8 @@
14204
14149
  const IFS = {
14205
14150
  description: _t$1("Returns a value depending on multiple logical expressions."),
14206
14151
  args: [
14207
- arg("condition1 (boolean, range<boolean>)", _t$1("The first condition to be evaluated. This can be a boolean, a number, an array, or a reference to any of those.")),
14208
- arg("value1 (any, range)", _t$1("The returned value if condition1 is TRUE.")),
14209
- arg("condition2 (boolean, any, range, repeating)", _t$1("Additional conditions to be evaluated if the previous ones are FALSE.")),
14210
- arg("value2 (any, range, repeating)", _t$1("Additional values to be returned if their corresponding conditions are TRUE.")),
14152
+ arg("condition (any, range, repeating)", _t$1("The condition to be evaluated. It can be a boolean, a number, an array, or a reference to any of those.")),
14153
+ arg("value (any, range, repeating)", _t$1("The value to be returned if its corresponding condition is TRUE.")),
14211
14154
  ],
14212
14155
  compute: function (...values) {
14213
14156
  if (values.length % 2 !== 0) {
@@ -14246,8 +14189,7 @@
14246
14189
  const OR = {
14247
14190
  description: _t$1("Logical `or` operator."),
14248
14191
  args: [
14249
- arg("logical_expression1 (boolean, range<boolean>)", _t$1("An expression or reference to a cell containing an expression that represents some logical value, i.e. TRUE or FALSE, or an expression that can be coerced to a logical value.")),
14250
- arg("logical_expression2 (boolean, range<boolean>, repeating)", _t$1("More expressions that evaluate to logical values.")),
14192
+ arg("logical_expression (boolean, range<boolean>, repeating)", _t$1("Expression or reference to a cell containing a logical value (TRUE/FALSE) or an expression that can be coerced to a logical value.")),
14251
14193
  ],
14252
14194
  compute: function (...logicalExpressions) {
14253
14195
  const { result, foundBoolean } = boolOr(logicalExpressions);
@@ -14265,10 +14207,8 @@
14265
14207
  description: _t$1("Returns a value by comparing cases to an expression."),
14266
14208
  args: [
14267
14209
  arg("expression (number, boolean, string)", _t$1("The value to be checked.")),
14268
- arg("case1 (number, boolean, string)", _t$1("The first case to be checked against expression.")),
14269
- arg("value1 (any)", _t$1("The corresponding value to be returned if case1 matches expression.")),
14270
- arg("case2 (any, repeating)", _t$1("Additional cases to try if the previous ones don't match expression.")),
14271
- arg("value2 (any, repeating)", _t$1("Additional values to be returned if their corresponding cases match expression.")),
14210
+ arg("case (any, repeating)", _t$1("Case to be checked against expression.")),
14211
+ arg("value (any, repeating)", _t$1("Value to be returned if its corresponding case matches expression.")),
14272
14212
  arg(`default (any, default="empty")`, _t$1("An optional default value to be returned if none of the cases match expression.")),
14273
14213
  ],
14274
14214
  compute: function (expression, ...casesAndValues) {
@@ -14303,8 +14243,7 @@
14303
14243
  const XOR = {
14304
14244
  description: _t$1("Logical `xor` operator."),
14305
14245
  args: [
14306
- arg("logical_expression1 (boolean, range<boolean>)", _t$1("An expression or reference to a cell containing an expression that represents some logical value, i.e. TRUE or FALSE, or an expression that can be coerced to a logical value.")),
14307
- arg("logical_expression2 (boolean, range<boolean>, repeating)", _t$1("More expressions that evaluate to logical values.")),
14246
+ arg("logical_expression (boolean, range<boolean>, repeating)", _t$1("Expression or reference to a cell containing a logical value (TRUE/FALSE) or an expression that can be coerced to a logical value.")),
14308
14247
  ],
14309
14248
  compute: function (...logicalExpressions) {
14310
14249
  let foundBoolean = false;
@@ -15817,8 +15756,8 @@
15817
15756
  args: [
15818
15757
  arg("pivot_id (number,string)", _t$1("ID of the pivot.")),
15819
15758
  arg("measure_name (string)", _t$1("Name of the measure.")),
15820
- arg("domain_field_name (string,repeating)", _t$1("Field name.")),
15821
- arg("domain_value (number,string,boolean,repeating)", _t$1("Value.")),
15759
+ arg("domain_field_name (string,repeating,optional)", _t$1("Field name.")),
15760
+ arg("domain_value (number,string,boolean,repeating,optional)", _t$1("Value.")),
15822
15761
  ],
15823
15762
  compute: function (formulaId, measureName, ...domainArgs) {
15824
15763
  const _pivotFormulaId = toString(formulaId);
@@ -15853,8 +15792,8 @@
15853
15792
  description: _t$1("Get the header of a pivot."),
15854
15793
  args: [
15855
15794
  arg("pivot_id (number,string)", _t$1("ID of the pivot.")),
15856
- arg("domain_field_name (string,repeating)", _t$1("Field name.")),
15857
- arg("domain_value (number,string,value,repeating)", _t$1("Value.")),
15795
+ arg("domain_field_name (string,repeating,optional)", _t$1("Field name.")),
15796
+ arg("domain_value (number,string,value,repeating,optional)", _t$1("Value.")),
15858
15797
  ],
15859
15798
  compute: function (pivotId, ...domainArgs) {
15860
15799
  const _pivotFormulaId = toString(pivotId);
@@ -16725,10 +16664,7 @@
16725
16664
  // -----------------------------------------------------------------------------
16726
16665
  const CONCATENATE = {
16727
16666
  description: _t$1("Appends strings to one another."),
16728
- args: [
16729
- arg("string1 (string, range<string>)", _t$1("The initial string.")),
16730
- arg("string2 (string, range<string>, repeating)", _t$1("More strings to append in sequence.")),
16731
- ],
16667
+ args: [arg("string (string, range<string>, repeating)", _t$1("String to append in sequence."))],
16732
16668
  compute: function (...datas) {
16733
16669
  return reduceAny(datas, (acc, a) => acc + toString(a), "");
16734
16670
  },
@@ -16783,8 +16719,7 @@
16783
16719
  description: _t$1("Concatenates elements of arrays with delimiter."),
16784
16720
  args: [
16785
16721
  arg("delimiter (string)", _t$1("The character or string to place between each concatenated value.")),
16786
- arg("value_or_array1 (string, range<string>)", _t$1("The value or values to be appended using delimiter.")),
16787
- arg("value_or_array2 (string, range<string>, repeating)", _t$1("More values to be appended using delimiter.")),
16722
+ arg("value_or_array (string, range<string>, repeating)", _t$1("Value to be appended using delimiter.")),
16788
16723
  ],
16789
16724
  compute: function (delimiter, ...valuesOrArrays) {
16790
16725
  const _delimiter = toString(delimiter);
@@ -17075,13 +17010,12 @@
17075
17010
  const TEXTJOIN = {
17076
17011
  description: _t$1("Combines text from multiple strings and/or arrays."),
17077
17012
  args: [
17078
- arg("delimiter (string)", _t$1(" A string, possible empty, or a reference to a valid string. If empty, the text will be simply concatenated.")),
17013
+ arg("delimiter (string)", _t$1("A string, possible empty, or a reference to a valid string. If empty, the text will be simply concatenated.")),
17079
17014
  arg("ignore_empty (boolean)", _t$1("A boolean; if TRUE, empty cells selected in the text arguments won't be included in the result."), [
17080
17015
  { value: true, label: _t$1("Ignore empty cells") },
17081
17016
  { value: false, label: _t$1("Include empty cells (default)") },
17082
17017
  ]),
17083
- arg("text1 (string, range<string>)", _t$1("Any text item. This could be a string, or an array of strings in a range.")),
17084
- arg("text2 (string, range<string>, repeating)", _t$1("Additional text item(s).")),
17018
+ arg("texts (string, range<string>, repeating)", _t$1("Text item to join.")),
17085
17019
  ],
17086
17020
  compute: function (delimiter, ignoreEmpty = { value: TEXTJOIN_DEFAULT_IGNORE_EMPTY }, ...textsOrArrays) {
17087
17021
  const _delimiter = toString(delimiter);
@@ -18459,12 +18393,10 @@ stores.inject(MyMetaStore, storeInstance);
18459
18393
  "#00a3a3",
18460
18394
  "#f012be",
18461
18395
  "#3d9970",
18462
- "#111111",
18463
18396
  "#62A300",
18464
18397
  "#ff4136",
18465
18398
  "#949494",
18466
- "#85144b",
18467
- "#001f3f",
18399
+ "#ff5c9d",
18468
18400
  ];
18469
18401
  /*
18470
18402
  * transform a color number (R * 256^2 + G * 256 + B) into classic hex (+alpha) value
@@ -19489,7 +19421,7 @@ stores.inject(MyMetaStore, storeInstance);
19489
19421
  let sheetName = "";
19490
19422
  if (prefixSheet) {
19491
19423
  if (range.invalidSheetName) {
19492
- sheetName = range.invalidSheetName;
19424
+ sheetName = getCanonicalSymbolName(range.invalidSheetName);
19493
19425
  }
19494
19426
  else {
19495
19427
  sheetName = getCanonicalSymbolName(getSheetName(range.sheetId));
@@ -22466,7 +22398,7 @@ stores.inject(MyMetaStore, storeInstance);
22466
22398
  return {
22467
22399
  background: context.background,
22468
22400
  type: "scorecard",
22469
- keyValue: context.range ? context.range[0].dataRange : undefined,
22401
+ keyValue: context.range?.[0]?.dataRange,
22470
22402
  title: context.title || { text: "" },
22471
22403
  baselineMode: DEFAULT_SCORECARD_BASELINE_MODE,
22472
22404
  baselineColorUp: DEFAULT_SCORECARD_BASELINE_COLOR_UP,
@@ -22969,6 +22901,66 @@ stores.inject(MyMetaStore, storeInstance);
22969
22901
  }
22970
22902
  }
22971
22903
 
22904
+ /**
22905
+ * Return a POJO containing the original event as well as the client position and the client offset
22906
+ * where the event would target if the spreadsheet was not zoomed
22907
+ * @param ev unzoomed mouse event
22908
+ * @param originalTargetRect The original target bounding rect the resulting ZoomedMouseEvent offset must refer to
22909
+ * @returns a ZoomedMouseEvent
22910
+ */
22911
+ function withZoom(env, ev, originalTargetRect) {
22912
+ const zoomLevel = env.model.getters.getViewportZoomLevel();
22913
+ if (originalTargetRect === undefined) {
22914
+ originalTargetRect = getZoomTargetBoundingRect(ev);
22915
+ }
22916
+ if (!originalTargetRect)
22917
+ return withNoZoom(ev);
22918
+ const baseOffsetX = ev.clientX - originalTargetRect.left;
22919
+ const baseOffsetY = ev.clientY - originalTargetRect.top;
22920
+ const offsetX = baseOffsetX / zoomLevel;
22921
+ const offsetY = baseOffsetY / zoomLevel;
22922
+ return {
22923
+ ev,
22924
+ clientX: ev.clientX - baseOffsetX + offsetX,
22925
+ clientY: ev.clientY - baseOffsetY + offsetY,
22926
+ offsetX,
22927
+ offsetY,
22928
+ };
22929
+ }
22930
+ function withNoZoom(ev) {
22931
+ return {
22932
+ ev,
22933
+ clientX: ev.clientX,
22934
+ clientY: ev.clientY,
22935
+ offsetX: ev.offsetX,
22936
+ offsetY: ev.offsetY,
22937
+ };
22938
+ }
22939
+ /**
22940
+ * Return a Rect with position and size on the zoomed canvas
22941
+ */
22942
+ function getZoomedRect(zoom, rect) {
22943
+ return {
22944
+ height: rect.height * zoom,
22945
+ width: rect.width * zoom,
22946
+ x: rect.x * zoom,
22947
+ y: rect.y * zoom,
22948
+ };
22949
+ }
22950
+ /**
22951
+ * Returns the bounding rect of the closest or self element who is targetable by a ZoomedMouseEvent
22952
+ */
22953
+ function getZoomTargetBoundingRect(ev) {
22954
+ const target = ev.target;
22955
+ if (!target || !("classList" in target) || !(target instanceof Element)) {
22956
+ return null;
22957
+ }
22958
+ const targetEl = target.classList.contains("o-zoomable") ? target : target.closest(".o-zoomable");
22959
+ if (!targetEl)
22960
+ return null;
22961
+ return targetEl.getBoundingClientRect();
22962
+ }
22963
+
22972
22964
  class ScorecardChart extends owl.Component {
22973
22965
  static template = "o-spreadsheet-ScorecardChart";
22974
22966
  static props = {
@@ -22992,7 +22984,8 @@ stores.inject(MyMetaStore, storeInstance);
22992
22984
  }
22993
22985
  createChart() {
22994
22986
  const canvas = this.canvas.el;
22995
- const config = getScorecardConfiguration(canvas.getBoundingClientRect(), this.runtime);
22987
+ const zoom = this.env.model.getters.getViewportZoomLevel();
22988
+ const config = getScorecardConfiguration(getZoomedRect(1 / zoom, canvas.getBoundingClientRect()), this.runtime);
22996
22989
  drawScoreChart(config, canvas);
22997
22990
  }
22998
22991
  }
@@ -23111,8 +23104,7 @@ stores.inject(MyMetaStore, storeInstance);
23111
23104
  function gridOverlayPosition() {
23112
23105
  const spreadsheetElement = document.querySelector(".o-grid-overlay");
23113
23106
  if (spreadsheetElement) {
23114
- const { top, left } = spreadsheetElement.getBoundingClientRect();
23115
- return { top, left };
23107
+ return spreadsheetElement.getBoundingClientRect();
23116
23108
  }
23117
23109
  throw new Error("Can't find spreadsheet position");
23118
23110
  }
@@ -23330,8 +23322,7 @@ stores.inject(MyMetaStore, storeInstance);
23330
23322
  .filter((ds) => !isTrendLineAxis(ds["xAxisID"]))
23331
23323
  .map((ds) => ({
23332
23324
  ...ds,
23333
- pointRadius: 0,
23334
- showLine: true,
23325
+ pointRadius: ds.showLine === false ? 2 : 0, // Show points only for scatter plots
23335
23326
  })),
23336
23327
  },
23337
23328
  options: {
@@ -23894,9 +23885,13 @@ stores.inject(MyMetaStore, storeInstance);
23894
23885
  if (!blob) {
23895
23886
  return undefined;
23896
23887
  }
23897
- if (!URL.createObjectURL)
23898
- throw new Error("URL.createObjectURL is not supported in this environment");
23899
- return URL.createObjectURL(blob);
23888
+ return new Promise((resolve) => {
23889
+ const f = new FileReader();
23890
+ f.addEventListener("load", () => {
23891
+ resolve(f.result);
23892
+ });
23893
+ f.readAsDataURL(blob);
23894
+ });
23900
23895
  }
23901
23896
 
23902
23897
  /**
@@ -26254,7 +26249,7 @@ stores.inject(MyMetaStore, storeInstance);
26254
26249
  const compiledArgs = [];
26255
26250
  const argToFocus = argTargeting(functionDefinition, args.length);
26256
26251
  for (let i = 0; i < args.length; i++) {
26257
- const argDefinition = functionDefinition.args[argToFocus(i) ?? -1];
26252
+ const argDefinition = functionDefinition.args[argToFocus(i).index ?? -1];
26258
26253
  const currentArg = args[i];
26259
26254
  const argTypes = argDefinition.type || [];
26260
26255
  // detect when an argument need to be evaluated as a meta argument
@@ -26433,12 +26428,15 @@ stores.inject(MyMetaStore, storeInstance);
26433
26428
  }
26434
26429
  if (nbrArgRepeating > 1) {
26435
26430
  const nbrValueRepeating = nbrArgRepeating * Math.floor((nbrArgSupplied - minArgRequired) / nbrArgRepeating);
26436
- const nbrValueRemaining = nbrArgSupplied - minArgRequired - nbrValueRepeating - functionDefinition.nbrArgOptional;
26431
+ const nbrValueRemaining = nbrArgSupplied -
26432
+ minArgRequired -
26433
+ nbrValueRepeating -
26434
+ functionDefinition.nbrOptionalNonRepeatingArgs;
26437
26435
  if (nbrValueRemaining > 0) {
26438
26436
  throw new BadExpressionError(_t$1("Invalid number of arguments for the %(functionName)s function. Repeatable arguments should be supplied in groups of %(nbrArgRepeating)s, with up to %(nbrArgOptional)s optional. Got %(nbrValueRemaining)s too many.", {
26439
26437
  functionName,
26440
26438
  nbrArgRepeating,
26441
- nbrArgOptional: functionDefinition.nbrArgOptional,
26439
+ nbrArgOptional: functionDefinition.nbrOptionalNonRepeatingArgs,
26442
26440
  nbrValueRemaining,
26443
26441
  }));
26444
26442
  }
@@ -44835,8 +44833,24 @@ stores.inject(MyMetaStore, storeInstance);
44835
44833
  case "REFERENCE":
44836
44834
  return ast.value;
44837
44835
  case "FUNCALL":
44838
- const docs = ast.args.map(astToDoc);
44839
- return wrapInParentheses(concat(docs.map((doc, i) => (i < 1 ? doc : concat([", ", line(), doc])))), ast.value);
44836
+ const functionDescription = functionRegistry.get(ast.value.toUpperCase());
44837
+ const getArgToFocus = argTargeting(functionDescription, ast.args.length);
44838
+ const docs = [];
44839
+ let i = 0;
44840
+ while (i < ast.args.length) {
44841
+ const isRepeating = functionDescription.args[getArgToFocus(i).index ?? -1]?.repeating;
44842
+ if (isRepeating) {
44843
+ const repeatingArgSeries = ast.args.slice(i, i + functionDescription.nbrArgRepeating);
44844
+ const docsSeries = repeatingArgSeries.map((arg) => astToDoc(arg));
44845
+ docs.push(group(concat(splitArgsWithCommas(docsSeries))));
44846
+ i += functionDescription.nbrArgRepeating;
44847
+ }
44848
+ else {
44849
+ docs.push(astToDoc(ast.args[i]));
44850
+ i++;
44851
+ }
44852
+ }
44853
+ return wrapInParentheses(concat(splitArgsWithCommas(docs)), ast.value);
44840
44854
  case "UNARY_OPERATION":
44841
44855
  const operandDoc = astToDoc(ast.operand);
44842
44856
  const needParenthesis = ast.postfix
@@ -44862,6 +44876,14 @@ stores.inject(MyMetaStore, storeInstance);
44862
44876
  return "";
44863
44877
  }
44864
44878
  }
44879
+ function splitArgsWithCommas(docs) {
44880
+ const result = docs.length ? [docs[0]] : [];
44881
+ for (let i = 1; i < docs.length; i++) {
44882
+ result.push(", ", line());
44883
+ result.push(docs[i]);
44884
+ }
44885
+ return result;
44886
+ }
44865
44887
  /**
44866
44888
  * Wraps a `Doc` in parentheses (with optional function name).
44867
44889
  */
@@ -46469,6 +46491,7 @@ stores.inject(MyMetaStore, storeInstance);
46469
46491
  isMeasureCandidate: (field) => field.type !== "boolean",
46470
46492
  isGroupable: () => true,
46471
46493
  canHaveCustomGroup: (field) => field.type === "char" && !field.isCustomField,
46494
+ isPivotUnused: () => true,
46472
46495
  });
46473
46496
 
46474
46497
  const UNDO_REDO_PIVOT_COMMANDS = ["ADD_PIVOT", "UPDATE_PIVOT", "REMOVE_PIVOT"];
@@ -46487,7 +46510,7 @@ stores.inject(MyMetaStore, storeInstance);
46487
46510
  "isSpillPivotFormula",
46488
46511
  ];
46489
46512
  pivots = {};
46490
- unusedPivots;
46513
+ unusedPivotsInFormulas;
46491
46514
  custom;
46492
46515
  constructor(config) {
46493
46516
  super(config);
@@ -46527,12 +46550,12 @@ stores.inject(MyMetaStore, storeInstance);
46527
46550
  }
46528
46551
  case "DELETE_SHEET":
46529
46552
  case "UPDATE_CELL": {
46530
- this.unusedPivots = undefined;
46553
+ this.unusedPivotsInFormulas = undefined;
46531
46554
  break;
46532
46555
  }
46533
46556
  case "UNDO":
46534
46557
  case "REDO": {
46535
- this.unusedPivots = undefined;
46558
+ this.unusedPivotsInFormulas = undefined;
46536
46559
  const pivotCommands = cmd.commands.filter(isPivotCommand);
46537
46560
  for (const cmd of pivotCommands) {
46538
46561
  const pivotId = cmd.pivotId;
@@ -46691,7 +46714,9 @@ stores.inject(MyMetaStore, storeInstance);
46691
46714
  return this.pivots[pivotId];
46692
46715
  }
46693
46716
  isPivotUnused(pivotId) {
46694
- return this._getUnusedPivots().includes(pivotId);
46717
+ const { type } = this.getters.getPivot(pivotId);
46718
+ return (this._getUnusedPivotsInFormulas().includes(pivotId) &&
46719
+ pivotRegistry.get(type).isPivotUnused(this.getters, pivotId));
46695
46720
  }
46696
46721
  getPivotCellSortDirection(position) {
46697
46722
  const pivotId = this.getters.getPivotIdFromPosition(position);
@@ -46727,9 +46752,9 @@ stores.inject(MyMetaStore, storeInstance);
46727
46752
  this.pivots[pivotId].onDefinitionChange(definition);
46728
46753
  }
46729
46754
  }
46730
- _getUnusedPivots() {
46731
- if (this.unusedPivots !== undefined) {
46732
- return this.unusedPivots;
46755
+ _getUnusedPivotsInFormulas() {
46756
+ if (this.unusedPivotsInFormulas !== undefined) {
46757
+ return this.unusedPivotsInFormulas;
46733
46758
  }
46734
46759
  const unusedPivots = new Set(this.getters.getPivotIds());
46735
46760
  for (const sheetId of this.getters.getSheetIds()) {
@@ -46739,14 +46764,14 @@ stores.inject(MyMetaStore, storeInstance);
46739
46764
  if (pivotId) {
46740
46765
  unusedPivots.delete(pivotId);
46741
46766
  if (!unusedPivots.size) {
46742
- this.unusedPivots = [];
46767
+ this.unusedPivotsInFormulas = [];
46743
46768
  return [];
46744
46769
  }
46745
46770
  }
46746
46771
  }
46747
46772
  }
46748
- this.unusedPivots = [...unusedPivots];
46749
- return this.unusedPivots;
46773
+ this.unusedPivotsInFormulas = [...unusedPivots];
46774
+ return this.unusedPivotsInFormulas;
46750
46775
  }
46751
46776
  }
46752
46777
 
@@ -52151,6 +52176,7 @@ stores.inject(MyMetaStore, storeInstance);
52151
52176
  "getVisibleFigures",
52152
52177
  "getVisibleRect",
52153
52178
  "getVisibleRectWithoutHeaders",
52179
+ "getVisibleRectWithZoom",
52154
52180
  "getVisibleCellPositions",
52155
52181
  "getColRowOffsetInViewport",
52156
52182
  "getMainViewportCoordinates",
@@ -52166,6 +52192,8 @@ stores.inject(MyMetaStore, storeInstance);
52166
52192
  "getFigureUI",
52167
52193
  "getPositionAnchorOffset",
52168
52194
  "getGridOffset",
52195
+ "getViewportZoomLevel",
52196
+ "getScrollBarWidth",
52169
52197
  ];
52170
52198
  viewports = {};
52171
52199
  /**
@@ -52178,6 +52206,7 @@ stores.inject(MyMetaStore, storeInstance);
52178
52206
  sheetViewHeight = getDefaultSheetViewSize();
52179
52207
  gridOffsetX = 0;
52180
52208
  gridOffsetY = 0;
52209
+ zoomLevel = 1;
52181
52210
  sheetsWithDirtyViewports = new Set();
52182
52211
  shouldAdjustViewports = false;
52183
52212
  // ---------------------------------------------------------------------------
@@ -52244,6 +52273,9 @@ stores.inject(MyMetaStore, storeInstance);
52244
52273
  case "SET_VIEWPORT_OFFSET":
52245
52274
  this.setSheetViewOffset(cmd.offsetX, cmd.offsetY);
52246
52275
  break;
52276
+ case "SET_ZOOM":
52277
+ this.zoomLevel = cmd.zoom || 1;
52278
+ break;
52247
52279
  case "SHIFT_VIEWPORT_DOWN":
52248
52280
  const sheetId = this.getters.getActiveSheetId();
52249
52281
  const { top, viewportHeight, offsetCorrectionY } = this.getMainInternalViewport(sheetId);
@@ -52447,7 +52479,7 @@ stores.inject(MyMetaStore, storeInstance);
52447
52479
  for (const i of relevantIndexes) {
52448
52480
  offset += this.getters.getHeaderSize(sheetId, dimension, i);
52449
52481
  }
52450
- return offset;
52482
+ return offset * this.zoomLevel;
52451
52483
  }
52452
52484
  /**
52453
52485
  * Check if a given position is visible in the viewport.
@@ -52455,6 +52487,9 @@ stores.inject(MyMetaStore, storeInstance);
52455
52487
  isVisibleInViewport({ sheetId, col, row }) {
52456
52488
  return this.getSubViewports(sheetId).some((pane) => pane.isVisible(col, row));
52457
52489
  }
52490
+ getScrollBarWidth() {
52491
+ return SCROLLBAR_WIDTH / this.zoomLevel;
52492
+ }
52458
52493
  // => returns the new offset
52459
52494
  getEdgeScrollCol(x, previousX, startingX) {
52460
52495
  let canEdgeScroll = false;
@@ -52533,6 +52568,18 @@ stores.inject(MyMetaStore, storeInstance);
52533
52568
  const rect = this.getVisibleRectWithoutHeaders(zone);
52534
52569
  return { ...rect, x: rect.x + this.gridOffsetX, y: rect.y + this.gridOffsetY };
52535
52570
  }
52571
+ /**
52572
+ * Computes the coordinates and size to draw the zone on the canvas after it has been zoomed
52573
+ */
52574
+ getVisibleRectWithZoom(zone) {
52575
+ const zoom = this.getViewportZoomLevel();
52576
+ const rect = this.getVisibleRectWithoutHeaders(zone);
52577
+ rect.width = rect.width * zoom;
52578
+ rect.height = rect.height * zoom;
52579
+ rect.x = rect.x * zoom + this.gridOffsetX * zoom;
52580
+ rect.y = rect.y * zoom + this.gridOffsetY * zoom;
52581
+ return rect;
52582
+ }
52536
52583
  /**
52537
52584
  * Computes the coordinates and size to draw the zone without taking the grid offset into account
52538
52585
  */
@@ -52614,6 +52661,9 @@ stores.inject(MyMetaStore, storeInstance);
52614
52661
  };
52615
52662
  });
52616
52663
  }
52664
+ getViewportZoomLevel() {
52665
+ return this.zoomLevel;
52666
+ }
52617
52667
  // ---------------------------------------------------------------------------
52618
52668
  // Private
52619
52669
  // ---------------------------------------------------------------------------
@@ -56875,7 +56925,7 @@ stores.inject(MyMetaStore, storeInstance);
56875
56925
  background: context.background,
56876
56926
  title: context.title || { text: "" },
56877
56927
  type: "gauge",
56878
- dataRange: context.range ? context.range[0].dataRange : undefined,
56928
+ dataRange: context.range?.[0]?.dataRange,
56879
56929
  sectionRule: {
56880
56930
  colors: {
56881
56931
  lowerColor: DEFAULT_GAUGE_LOWER_COLOR,
@@ -58261,22 +58311,26 @@ stores.inject(MyMetaStore, storeInstance);
58261
58311
  }
58262
58312
  onPointerDownInMasterChart(ev) {
58263
58313
  this.removeEventListeners();
58264
- const position = ev.offsetX;
58314
+ const zoomedEvent = withZoom(this.env, ev, this.masterChartCanvas.el?.getBoundingClientRect());
58315
+ const position = zoomedEvent.offsetX;
58265
58316
  if (!this.masterChart?.chartArea || !this.chart?.scales?.x) {
58266
58317
  return;
58267
58318
  }
58268
58319
  const { left, right, top, bottom } = this.masterChart.chartArea;
58269
58320
  const xMax = this.upperBound ?? right;
58270
58321
  const xMin = this.lowerBound ?? left;
58271
- if (position < left - 5 || position > right + 5 || ev.offsetY < top || ev.offsetY > bottom) {
58322
+ if (position < left - 5 ||
58323
+ position > right + 5 ||
58324
+ zoomedEvent.offsetY < top ||
58325
+ zoomedEvent.offsetY > bottom) {
58272
58326
  return;
58273
58327
  }
58274
58328
  ev.preventDefault();
58275
58329
  ev.stopPropagation();
58276
58330
  let startingPositionOnChart, windowSize, startX;
58277
- const startingEventPosition = ev.clientX - (this.masterChartCanvas.el?.getBoundingClientRect().left ?? 0);
58331
+ const startingEventPosition = position;
58278
58332
  if ((xMin !== left || xMax !== right) && position > xMin + 5 && position < xMax - 5) {
58279
- startingPositionOnChart = ev.offsetX - xMin;
58333
+ startingPositionOnChart = zoomedEvent.offsetX - xMin;
58280
58334
  this.mode = "moveInMaster";
58281
58335
  const currentLimits = this.store.currentAxesLimits[this.chartId]?.x;
58282
58336
  windowSize =
@@ -58325,7 +58379,8 @@ stores.inject(MyMetaStore, storeInstance);
58325
58379
  return { min: xMin, max: xMax };
58326
58380
  };
58327
58381
  const onDragFromMasterChart = (ev) => {
58328
- const position = ev.clientX - (this.masterChartCanvas.el?.getBoundingClientRect().left ?? 0);
58382
+ const zoomedEvent = withZoom(this.env, ev, this.masterChartCanvas.el?.getBoundingClientRect());
58383
+ const position = zoomedEvent.offsetX;
58329
58384
  if (Math.abs(position - startingEventPosition) < 5) {
58330
58385
  return;
58331
58386
  }
@@ -58336,7 +58391,8 @@ stores.inject(MyMetaStore, storeInstance);
58336
58391
  };
58337
58392
  const onPointerUpInMasterChart = (ev) => {
58338
58393
  this.removeEventListeners();
58339
- const position = ev.clientX - (this.masterChartCanvas.el?.getBoundingClientRect().left ?? 0);
58394
+ const zoomedEvent = withZoom(this.env, ev, this.masterChartCanvas.el?.getBoundingClientRect());
58395
+ const position = zoomedEvent.offsetX;
58340
58396
  if (Math.abs(position - startingEventPosition) > 5) {
58341
58397
  let { min: xMin, max: xMax } = computeNewAxisLimits(position);
58342
58398
  if (xMin !== undefined && xMax !== undefined) {
@@ -58363,7 +58419,7 @@ stores.inject(MyMetaStore, storeInstance);
58363
58419
  window.addEventListener("pointerup", onPointerUpInMasterChart, true);
58364
58420
  }
58365
58421
  onPointerMoveInMasterChart(ev) {
58366
- const { offsetX: x, offsetY: y } = ev;
58422
+ const { offsetX: x, offsetY: y } = withZoom(this.env, ev, ev.target?.getBoundingClientRect());
58367
58423
  if (this.mode === undefined) {
58368
58424
  const target = ev.target;
58369
58425
  if (!this.masterChart?.chartArea) {
@@ -58396,7 +58452,8 @@ stores.inject(MyMetaStore, storeInstance);
58396
58452
  }
58397
58453
  onDoubleClickInMasterChart(ev) {
58398
58454
  this.mode = undefined;
58399
- const position = ev.offsetX;
58455
+ const zoomedEvent = withZoom(this.env, ev, this.masterChartCanvas.el?.getBoundingClientRect());
58456
+ const position = zoomedEvent.offsetX;
58400
58457
  if (!this.masterChart?.chartArea || !this.chart?.scales.x) {
58401
58458
  return;
58402
58459
  }
@@ -58406,7 +58463,10 @@ stores.inject(MyMetaStore, storeInstance);
58406
58463
  if (upperBound < lowerBound) {
58407
58464
  [upperBound, lowerBound] = [lowerBound, upperBound];
58408
58465
  }
58409
- if (position < left - 5 || position > right + 5 || ev.offsetY < top || ev.offsetY > bottom) {
58466
+ if (position < left - 5 ||
58467
+ position > right + 5 ||
58468
+ zoomedEvent.offsetY < top ||
58469
+ zoomedEvent.offsetY > bottom) {
58410
58470
  return;
58411
58471
  }
58412
58472
  ev.preventDefault();
@@ -58841,7 +58901,7 @@ stores.inject(MyMetaStore, storeInstance);
58841
58901
  });
58842
58902
  }
58843
58903
  drawGaugeWithAnimation() {
58844
- drawGaugeChart(this.canvasEl, { ...this.runtime, animationValue: 0 });
58904
+ drawGaugeChart(this.canvasEl, { ...this.runtime, animationValue: 0 }, undefined);
58845
58905
  const gaugeValue = this.runtime.gaugeValue?.value || 0;
58846
58906
  const upperBound = this.runtime.maxValue.value;
58847
58907
  const finalValue = Math.sign(gaugeValue) * Math.min(Math.abs(gaugeValue), Math.abs(upperBound));
@@ -58849,7 +58909,7 @@ stores.inject(MyMetaStore, storeInstance);
58849
58909
  return null;
58850
58910
  }
58851
58911
  const lowerBound = this.runtime.minValue.value;
58852
- const animation = new Animation(lowerBound, finalValue, ANIMATION_DURATION, (animationValue) => drawGaugeChart(this.canvasEl, { ...this.runtime, animationValue }));
58912
+ const animation = new Animation(lowerBound, finalValue, ANIMATION_DURATION, (animationValue) => drawGaugeChart(this.canvasEl, { ...this.runtime, animationValue }, undefined));
58853
58913
  animation.start();
58854
58914
  return animation;
58855
58915
  }
@@ -60069,7 +60129,13 @@ stores.inject(MyMetaStore, storeInstance);
60069
60129
  onContextMenu(ev) {
60070
60130
  if (this.env.isDashboard())
60071
60131
  return;
60072
- this.openContextMenu({ x: ev.clientX, y: ev.clientY, width: 0, height: 0 });
60132
+ const zoomedMouseEvent = withZoom(this.env, ev);
60133
+ this.openContextMenu({
60134
+ x: zoomedMouseEvent.clientX,
60135
+ y: zoomedMouseEvent.clientY,
60136
+ width: 0,
60137
+ height: 0,
60138
+ });
60073
60139
  }
60074
60140
  showMenu() {
60075
60141
  this.openContextMenu(getRefBoundingRect(this.menuButtonRef));
@@ -61669,7 +61735,7 @@ stores.inject(MyMetaStore, storeInstance);
61669
61735
  }
61670
61736
  getCss(html) {
61671
61737
  return cssPropertiesToCss({
61672
- color: html.color || "#000000",
61738
+ color: html.color,
61673
61739
  background: html.backgroundColor,
61674
61740
  });
61675
61741
  }
@@ -61824,6 +61890,9 @@ stores.inject(MyMetaStore, storeInstance);
61824
61890
  const span = document.createElement("span");
61825
61891
  span.innerText = content.value;
61826
61892
  span.style.color = content.color || "";
61893
+ if (content.opacity !== undefined && content.opacity !== 1) {
61894
+ span.style.opacity = content.opacity.toString();
61895
+ }
61827
61896
  span.addEventListener("mousemove", () => {
61828
61897
  content.onHover?.(getBoundingRectAsPOJO(span));
61829
61898
  });
@@ -61905,7 +61974,7 @@ stores.inject(MyMetaStore, storeInstance);
61905
61974
  else {
61906
61975
  text += NEWLINE;
61907
61976
  }
61908
- emptyParagraph = ["<br>", "<span><br></span>"].includes(current.value.innerHTML);
61977
+ emptyParagraph = isEmptyParagraph(current.value);
61909
61978
  continue;
61910
61979
  }
61911
61980
  if (!current.value.hasChildNodes()) {
@@ -61919,12 +61988,29 @@ stores.inject(MyMetaStore, storeInstance);
61919
61988
  }
61920
61989
  }
61921
61990
  function compareContentToSpanElement(content, node) {
61922
- const contentColor = content.color ? toHex(content.color) : "";
61923
- const nodeColor = node.style?.color ? toHex(node.style.color) : "";
61991
+ const contentColor = content.color || "";
61992
+ const nodeColor = node.style?.color || "";
61993
+ const nodeOpacity = node.style?.opacity || "1";
61924
61994
  const sameColor = contentColor === nodeColor;
61925
61995
  const sameClass = deepEquals$1(content.classes, [...node.classList]);
61926
61996
  const sameContent = node.innerText === content.value;
61927
- return sameColor && sameClass && sameContent;
61997
+ const sameOpacity = (content.opacity ?? 1).toString() === nodeOpacity;
61998
+ return sameColor && sameClass && sameContent && sameOpacity;
61999
+ }
62000
+ const doc = new DOMParser();
62001
+ const brNode = doc.parseFromString("<br>", "text/html").body.firstChild;
62002
+ const spanBrNode = doc.parseFromString("<span><br></span>", "text/html").body.firstChild;
62003
+ function isEmptyParagraph(node) {
62004
+ if (node.childNodes.length > 1)
62005
+ return false;
62006
+ const node2 = node.firstChild?.cloneNode(true);
62007
+ if (!node2)
62008
+ return true;
62009
+ if (!(node2 instanceof Element))
62010
+ return false;
62011
+ node2.removeAttribute("class");
62012
+ node2.removeAttribute("style");
62013
+ return node2.isEqualNode(brNode) || node2.isEqualNode(spanBrNode) || false;
61928
62014
  }
61929
62015
 
61930
62016
  class FunctionDescriptionProvider extends owl.Component {
@@ -61932,6 +62018,7 @@ stores.inject(MyMetaStore, storeInstance);
61932
62018
  static props = {
61933
62019
  functionDescription: Object,
61934
62020
  argsToFocus: Array,
62021
+ repeatingArgGroupIndex: { type: Number, optional: true },
61935
62022
  };
61936
62023
  static components = { Collapse };
61937
62024
  state = owl.useState({
@@ -61943,8 +62030,70 @@ stores.inject(MyMetaStore, storeInstance);
61943
62030
  getContext() {
61944
62031
  return this.props;
61945
62032
  }
61946
- get formulaArgSeparator() {
61947
- return this.env.model.getters.getLocale().formulaArgSeparator + " ";
62033
+ get formulaHeaderContent() {
62034
+ const { functionDescription, repeatingArgGroupIndex, argsToFocus } = this.props;
62035
+ const argSeparator = this.env.model.getters.getLocale().formulaArgSeparator + " ";
62036
+ const result = [
62037
+ { content: functionDescription.name + " ( " },
62038
+ ];
62039
+ for (let i = 0; i < functionDescription.args.length; i++) {
62040
+ const arg = functionDescription.args[i];
62041
+ const isRepeating = arg.repeating;
62042
+ if (i > 0) {
62043
+ result.push({ content: argSeparator });
62044
+ }
62045
+ if (isRepeating) {
62046
+ // treat all repeating args in one go
62047
+ const displayBrackets = arg.optional || (repeatingArgGroupIndex ?? 0) > 0;
62048
+ const repeatingArgNames = functionDescription.args
62049
+ .slice(i, i + functionDescription.nbrArgRepeating)
62050
+ .map((arg) => arg.name);
62051
+ if (repeatingArgGroupIndex) {
62052
+ result.push({ content: "... " + argSeparator });
62053
+ }
62054
+ if (displayBrackets) {
62055
+ result.push({ content: "[" });
62056
+ }
62057
+ for (let idx = 0; idx < repeatingArgNames.length; idx++) {
62058
+ const name = repeatingArgNames[idx];
62059
+ const argIndex = i + idx;
62060
+ const focused = argsToFocus.includes(argIndex);
62061
+ result.push({ content: name + ((repeatingArgGroupIndex ?? 0) + 1), focused });
62062
+ // Add separator after each element except the last
62063
+ if (idx < repeatingArgNames.length - 1) {
62064
+ result.push({ content: argSeparator });
62065
+ }
62066
+ }
62067
+ if (displayBrackets) {
62068
+ result.push({ content: "]" });
62069
+ }
62070
+ result.push({ content: argSeparator + "[" });
62071
+ for (let idx = 0; idx < repeatingArgNames.length; idx++) {
62072
+ const name = repeatingArgNames[idx];
62073
+ result.push({ content: name + ((repeatingArgGroupIndex ?? 0) + 2) });
62074
+ // Add separator after each element except the last
62075
+ if (idx < repeatingArgNames.length - 1) {
62076
+ result.push({ content: argSeparator });
62077
+ }
62078
+ }
62079
+ result.push({ content: "]" + argSeparator + "... " });
62080
+ // Skip the processed repeating args
62081
+ i += functionDescription.nbrArgRepeating - 1;
62082
+ }
62083
+ else {
62084
+ const displayBrackets = arg.optional || arg.default;
62085
+ const focused = argsToFocus.includes(i);
62086
+ if (displayBrackets) {
62087
+ result.push({ content: "[" });
62088
+ }
62089
+ result.push({ content: arg.name, focused });
62090
+ if (displayBrackets) {
62091
+ result.push({ content: "]" });
62092
+ }
62093
+ }
62094
+ }
62095
+ result.push({ content: " )" });
62096
+ return result;
61948
62097
  }
61949
62098
  }
61950
62099
 
@@ -62014,6 +62163,7 @@ stores.inject(MyMetaStore, storeInstance);
62014
62163
  showDescription: false,
62015
62164
  functionDescription: {},
62016
62165
  argsToFocus: [],
62166
+ repeatingArgGroupIndex: 0,
62017
62167
  });
62018
62168
  assistant = owl.useState({
62019
62169
  forcedClosed: false,
@@ -62451,10 +62601,6 @@ stores.inject(MyMetaStore, storeInstance);
62451
62601
  const { end, start } = this.props.composerStore.composerSelection;
62452
62602
  for (let index = 0; index < tokens.length; index++) {
62453
62603
  const token = tokens[index];
62454
- let color = token.color || DEFAULT_TOKEN_COLOR;
62455
- if (token.isBlurred) {
62456
- color = setColorAlpha(color, 0.5);
62457
- }
62458
62604
  const classes = [];
62459
62605
  if (token.type === "REFERENCE" &&
62460
62606
  this.props.composerStore.tokenAtCursor === token &&
@@ -62472,7 +62618,8 @@ stores.inject(MyMetaStore, storeInstance);
62472
62618
  }
62473
62619
  result.push({
62474
62620
  value: token.value,
62475
- color,
62621
+ color: token.color || DEFAULT_TOKEN_COLOR,
62622
+ opacity: token.isBlurred ? 0.5 : 1,
62476
62623
  classes,
62477
62624
  onHover: (rect) => this.onTokenHover(index, rect),
62478
62625
  onStopHover: () => this.onTokenHover(undefined),
@@ -62552,9 +62699,21 @@ stores.inject(MyMetaStore, storeInstance);
62552
62699
  const isParenthesisClosed = this.props.composerStore.currentTokens.some((t) => t.type === "RIGHT_PAREN" && t.parenthesesCode === token.parenthesesCode);
62553
62700
  this.functionDescriptionState.argsToFocus = this.getArgsToFocus(isParenthesisClosed, description, nbrArgSupplied, argPosition);
62554
62701
  this.functionDescriptionState.showDescription = true;
62702
+ this.functionDescriptionState.repeatingArgGroupIndex = this.getRepeatingArgGroupIndex(description, nbrArgSupplied, argPosition);
62555
62703
  }
62556
62704
  }
62557
62705
  }
62706
+ getRepeatingArgGroupIndex(description, nbrArgSupplied, argPosition) {
62707
+ const { minArgRequired, maxArgPossible, nbrArgRepeating } = description;
62708
+ if (!nbrArgRepeating) {
62709
+ return undefined;
62710
+ }
62711
+ const groupsOfOptionalRepeatingValues = nbrArgRepeating
62712
+ ? Math.ceil((nbrArgSupplied - minArgRequired) / nbrArgRepeating)
62713
+ : 0;
62714
+ const nbrArgSuppliedRoundedToGroupOfRepeating = groupsOfOptionalRepeatingValues * nbrArgRepeating + minArgRequired;
62715
+ return (argTargeting(description, Math.max(Math.min(maxArgPossible, nbrArgSuppliedRoundedToGroupOfRepeating), minArgRequired))(argPosition).repeatingGroupIndex ?? 0);
62716
+ }
62558
62717
  /**
62559
62718
  * Compute the arguments to focus depending on the current value position.
62560
62719
  *
@@ -62564,11 +62723,11 @@ stores.inject(MyMetaStore, storeInstance);
62564
62723
  * This function computes all the possible arguments to focus for different numbers of arguments supplied.
62565
62724
  */
62566
62725
  getArgsToFocus(isParenthesisClosed, description, nbrArgSupplied, argPosition) {
62567
- const { nbrArgRepeating, minArgRequired, nbrArgOptional, maxArgPossible } = description;
62726
+ const { nbrArgRepeating, minArgRequired, nbrOptionalNonRepeatingArgs, maxArgPossible } = description;
62568
62727
  // When the parenthesis is closed, we consider the user is done with the function,
62569
62728
  // so we know exactly the number of arguments supplied.
62570
62729
  if (isParenthesisClosed) {
62571
- const focusedArg = argTargeting(description, Math.max(Math.min(maxArgPossible, nbrArgSupplied), minArgRequired))(argPosition);
62730
+ const focusedArg = argTargeting(description, Math.max(Math.min(maxArgPossible, nbrArgSupplied), minArgRequired))(argPosition)?.index;
62572
62731
  return focusedArg !== undefined ? [focusedArg] : [];
62573
62732
  }
62574
62733
  // Otherwise, the user is still typing the formula, so we don't know yet how many arguments the user will supply.
@@ -62577,11 +62736,11 @@ stores.inject(MyMetaStore, storeInstance);
62577
62736
  const maxArgsNumberPossibility = nbrArgRepeating
62578
62737
  ? minArgRequired +
62579
62738
  Math.ceil((minArgsNumberPossibility - minArgRequired) / nbrArgRepeating) * nbrArgRepeating +
62580
- nbrArgOptional
62739
+ nbrOptionalNonRepeatingArgs
62581
62740
  : maxArgPossible;
62582
62741
  const argsToFocus = [];
62583
62742
  for (let i = minArgsNumberPossibility; i <= maxArgsNumberPossibility; i++) {
62584
- const focusedArg = argTargeting(description, i)(argPosition);
62743
+ const focusedArg = argTargeting(description, i)(argPosition)?.index;
62585
62744
  if (focusedArg !== undefined) {
62586
62745
  argsToFocus.push(focusedArg);
62587
62746
  }
@@ -63017,6 +63176,7 @@ stores.inject(MyMetaStore, storeInstance);
63017
63176
  this.highlightStore.register(this);
63018
63177
  this.onDispose(() => {
63019
63178
  this.highlightStore.unRegister(this);
63179
+ this._cancelEdition();
63020
63180
  });
63021
63181
  }
63022
63182
  handleEvent(event) {
@@ -67486,6 +67646,17 @@ stores.inject(MyMetaStore, storeInstance);
67486
67646
  isReadonlyAllowed: true,
67487
67647
  icon: "o-spreadsheet-Icon.IRREGULARITY_MAP",
67488
67648
  };
67649
+ function zoomAction(zoom) {
67650
+ return {
67651
+ name: _t$1("%(zoom_percentage)s%", { zoom_percentage: zoom }),
67652
+ execute: (env) => {
67653
+ env.model.dispatch("SET_ZOOM", { zoom: zoom / 100 });
67654
+ },
67655
+ isActive: (env) => env.model.getters.getViewportZoomLevel() === zoom / 100,
67656
+ isReadonlyAllowed: true,
67657
+ sequence: zoom,
67658
+ };
67659
+ }
67489
67660
  const viewFormulas = {
67490
67661
  name: _t$1("Formulas"),
67491
67662
  isActive: (env) => env.model.getters.shouldShowFormulas(),
@@ -69612,13 +69783,14 @@ stores.inject(MyMetaStore, storeInstance);
69612
69783
  }
69613
69784
  const sheetId = getters.getActiveSheetId();
69614
69785
  const position = gridOverlayPosition();
69786
+ const zoomedMouseEvent = withZoom(env, currentEv, position);
69615
69787
  const { x: offsetCorrectionX, y: offsetCorrectionY } = getters.getMainViewportCoordinates();
69616
69788
  const { top, left, bottom, right } = getters.getActiveMainViewport();
69617
69789
  let { scrollX, scrollY } = getters.getActiveSheetScrollInfo();
69618
69790
  const { xSplit, ySplit } = getters.getPaneDivisions(sheetId);
69619
69791
  let canEdgeScroll = false;
69620
69792
  let timeoutDelay = MAX_DELAY;
69621
- const x = currentEv.clientX - position.left;
69793
+ const x = zoomedMouseEvent.clientX - position.left;
69622
69794
  let colIndex = getters.getColIndex(x);
69623
69795
  if (scrollDirection !== "vertical") {
69624
69796
  const previousX = previousEvClientPosition.clientX - position.left;
@@ -69646,7 +69818,7 @@ stores.inject(MyMetaStore, storeInstance);
69646
69818
  scrollX = getters.getColDimensions(sheetId, newTarget).start - offsetCorrectionX;
69647
69819
  }
69648
69820
  }
69649
- const y = currentEv.clientY - position.top;
69821
+ const y = zoomedMouseEvent.clientY - position.top;
69650
69822
  let rowIndex = getters.getRowIndex(y);
69651
69823
  if (scrollDirection !== "horizontal") {
69652
69824
  const previousY = previousEvClientPosition.clientY - position.top;
@@ -69686,7 +69858,10 @@ stores.inject(MyMetaStore, storeInstance);
69686
69858
  pointerMoveHandler(currentEv);
69687
69859
  }, Math.round(timeoutDelay));
69688
69860
  }
69689
- previousEvClientPosition = { clientX: currentEv.clientX, clientY: currentEv.clientY };
69861
+ previousEvClientPosition = {
69862
+ clientX: zoomedMouseEvent.clientX,
69863
+ clientY: zoomedMouseEvent.clientY,
69864
+ };
69690
69865
  };
69691
69866
  const pointerUpHandler = () => {
69692
69867
  pointerUpCallback?.();
@@ -69728,30 +69903,30 @@ stores.inject(MyMetaStore, storeInstance);
69728
69903
  isVisible: Boolean,
69729
69904
  };
69730
69905
  state = owl.useState({
69731
- position: { left: 0, top: 0 },
69906
+ position: { x: 0, y: 0 },
69732
69907
  handler: false,
69733
69908
  });
69734
69909
  dragNDropGrid = useDragAndDropBeyondTheViewport(this.env);
69735
69910
  get style() {
69736
- const { left, top } = this.props.position;
69911
+ const { x, y } = this.props.position;
69737
69912
  return cssPropertiesToCss({
69738
- top: `${top}px`,
69739
- left: `${left}px`,
69913
+ top: `${y}px`,
69914
+ left: `${x}px`,
69740
69915
  visibility: this.props.isVisible ? "visible" : "hidden",
69741
69916
  });
69742
69917
  }
69743
69918
  get handlerStyle() {
69744
- const { left, top } = this.state.handler ? this.state.position : this.props.position;
69919
+ const { x, y } = this.state.handler ? this.state.position : this.props.position;
69745
69920
  return cssPropertiesToCss({
69746
- top: `${top}px`,
69747
- left: `${left}px`,
69921
+ top: `${y}px`,
69922
+ left: `${x}px`,
69748
69923
  });
69749
69924
  }
69750
69925
  get styleNextValue() {
69751
- const { left, top } = this.state.position;
69926
+ const { x, y } = this.state.position;
69752
69927
  return cssPropertiesToCss({
69753
- top: `${top + 5}px`,
69754
- left: `${left + 15}px`,
69928
+ top: `${y + 5}px`,
69929
+ left: `${x + 15}px`,
69755
69930
  });
69756
69931
  }
69757
69932
  getTooltip() {
@@ -69763,11 +69938,13 @@ stores.inject(MyMetaStore, storeInstance);
69763
69938
  }
69764
69939
  onMouseDown(ev) {
69765
69940
  this.state.handler = true;
69941
+ const zoomedMouseEvent = withZoom(this.env, ev);
69942
+ const zoom = this.env.model.getters.getViewportZoomLevel();
69766
69943
  let lastCol;
69767
69944
  let lastRow;
69768
69945
  const start = {
69769
- left: ev.clientX - this.props.position.left,
69770
- top: ev.clientY - this.props.position.top,
69946
+ x: ev.clientX / zoom - this.props.position.x,
69947
+ y: ev.clientY / zoom - this.props.position.y,
69771
69948
  };
69772
69949
  const onMouseUp = () => {
69773
69950
  this.state.handler = false;
@@ -69776,8 +69953,8 @@ stores.inject(MyMetaStore, storeInstance);
69776
69953
  };
69777
69954
  const onMouseMove = (col, row, ev) => {
69778
69955
  this.state.position = {
69779
- left: ev.clientX - start.left,
69780
- top: ev.clientY - start.top,
69956
+ x: ev.clientX / zoom - start.x,
69957
+ y: ev.clientY / zoom - start.y,
69781
69958
  };
69782
69959
  if (lastCol !== col || lastRow !== row) {
69783
69960
  const activeSheetId = this.env.model.getters.getActiveSheetId();
@@ -69790,7 +69967,7 @@ stores.inject(MyMetaStore, storeInstance);
69790
69967
  }
69791
69968
  }
69792
69969
  };
69793
- this.dragNDropGrid.start(ev, onMouseMove, onMouseUp);
69970
+ this.dragNDropGrid.start(zoomedMouseEvent, onMouseMove, onMouseUp);
69794
69971
  }
69795
69972
  onDblClick() {
69796
69973
  this.env.model.dispatch("AUTOFILL_AUTO");
@@ -70725,7 +70902,8 @@ stores.inject(MyMetaStore, storeInstance);
70725
70902
  return;
70726
70903
  }
70727
70904
  const sheetId = this.env.model.getters.getActiveSheetId();
70728
- const initialMousePosition = { x: ev.clientX, y: ev.clientY };
70905
+ const zoom = this.env.model.getters.getViewportZoomLevel();
70906
+ const initialMousePosition = { x: ev.clientX / zoom, y: ev.clientY / zoom };
70729
70907
  const initialScrollPosition = this.env.model.getters.getActiveSheetScrollInfo();
70730
70908
  const initialFigure = this.toBottomRightViewport(figureUI);
70731
70909
  const maxDimensions = {
@@ -70735,7 +70913,7 @@ stores.inject(MyMetaStore, storeInstance);
70735
70913
  let hasStartedDnd = false;
70736
70914
  const onMouseMove = (ev) => {
70737
70915
  const getters = this.env.model.getters;
70738
- const currentMousePosition = { x: ev.clientX, y: ev.clientY };
70916
+ const currentMousePosition = { x: ev.clientX / zoom, y: ev.clientY / zoom };
70739
70917
  const offsetX = Math.abs(currentMousePosition.x - initialMousePosition.x);
70740
70918
  const offsetY = Math.abs(currentMousePosition.y - initialMousePosition.y);
70741
70919
  if (!hasStartedDnd && offsetX < DRAG_THRESHOLD && offsetY < DRAG_THRESHOLD) {
@@ -70798,17 +70976,18 @@ stores.inject(MyMetaStore, storeInstance);
70798
70976
  */
70799
70977
  startResize(figureUI, dirX, dirY, ev) {
70800
70978
  ev.stopPropagation();
70801
- const initialMousePosition = { x: ev.clientX, y: ev.clientY };
70802
70979
  const initialScrollPosition = this.env.model.getters.getActiveSheetScrollInfo();
70803
70980
  const keepRatio = figureRegistry.get(figureUI.tag).keepRatio || false;
70804
70981
  const minFigSize = figureRegistry.get(figureUI.tag).minFigSize || MIN_FIG_SIZE;
70982
+ const zoom = this.env.model.getters.getViewportZoomLevel();
70805
70983
  const sheetId = this.env.model.getters.getActiveSheetId();
70984
+ const initialMousePosition = { x: ev.clientX / zoom, y: ev.clientY / zoom };
70806
70985
  const maxDimensions = {
70807
70986
  maxX: this.env.model.getters.getColDimensions(sheetId, this.env.model.getters.getNumberCols(sheetId) - 1).end,
70808
70987
  maxY: this.env.model.getters.getRowDimensions(sheetId, this.env.model.getters.getNumberRows(sheetId) - 1).end,
70809
70988
  };
70810
70989
  const onMouseMove = (ev) => {
70811
- const currentMousePosition = { x: ev.clientX, y: ev.clientY };
70990
+ const currentMousePosition = { x: ev.clientX / zoom, y: ev.clientY / zoom };
70812
70991
  const draggedFigure = dragFigureForResize(figureUI, dirX, dirY, currentMousePosition, initialMousePosition, keepRatio, minFigSize, initialScrollPosition, this.env.model.getters.getActiveSheetScrollInfo(), maxDimensions);
70813
70992
  const otherFigures = this.getOtherFigures(figureUI.id);
70814
70993
  const snapResult = snapForResize(this.env.model.getters, dirX, dirY, draggedFigure, otherFigures);
@@ -71220,11 +71399,11 @@ stores.inject(MyMetaStore, storeInstance);
71220
71399
  const row = env.model.getters.getRowIndex(y);
71221
71400
  return { col, row };
71222
71401
  }
71223
- function getOffsetRelativeToOverlay(ev) {
71402
+ function getOffsetRelativeToOverlay(zoomedMouseEvent) {
71224
71403
  const gridRect = getBoundingRectAsPOJO(gridRef.el);
71225
71404
  return {
71226
- x: ev.clientX - gridRect.x,
71227
- y: ev.clientY - gridRect.y,
71405
+ x: zoomedMouseEvent.clientX - gridRect.x,
71406
+ y: zoomedMouseEvent.clientY - gridRect.y,
71228
71407
  };
71229
71408
  }
71230
71409
  const { pause, resume } = useInterval(checkTiming, 200);
@@ -71241,9 +71420,9 @@ stores.inject(MyMetaStore, storeInstance);
71241
71420
  setPosition(col, row);
71242
71421
  }
71243
71422
  }
71244
- function updateMousePosition(e) {
71245
- if (isChildEvent(gridRef.el, e)) {
71246
- ({ x, y } = getOffsetRelativeToOverlay(e));
71423
+ function updateMousePosition(zoomedMouseEvent) {
71424
+ if (isChildEvent(gridRef.el, zoomedMouseEvent.ev)) {
71425
+ ({ x, y } = getOffsetRelativeToOverlay(zoomedMouseEvent));
71247
71426
  lastMoved = Date.now();
71248
71427
  hoveredTable.hover(getPosition());
71249
71428
  }
@@ -71255,20 +71434,21 @@ stores.inject(MyMetaStore, storeInstance);
71255
71434
  }
71256
71435
  }
71257
71436
  function onMouseLeave(e) {
71258
- const { x, y } = getOffsetRelativeToOverlay(e);
71437
+ const zoomedMouseEvent = withZoom(env, e);
71438
+ const { x, y } = getOffsetRelativeToOverlay(zoomedMouseEvent);
71259
71439
  const gridRect = getBoundingRectAsPOJO(gridRef.el);
71260
71440
  if (y < 0 || y > gridRect.height || x < 0 || x > gridRect.width) {
71261
- return updateMousePosition(e);
71441
+ return updateMousePosition(zoomedMouseEvent);
71262
71442
  }
71263
71443
  else {
71264
71444
  return pause();
71265
71445
  }
71266
71446
  }
71267
- useRefListener(gridRef, "pointermove", (ev) => !env.isMobile() && updateMousePosition(ev));
71447
+ useRefListener(gridRef, "pointermove", (ev) => !env.isMobile() && updateMousePosition(withZoom(env, ev)));
71268
71448
  useRefListener(gridRef, "mouseleave", onMouseLeave);
71269
71449
  useRefListener(gridRef, "mouseenter", resume);
71270
71450
  useRefListener(gridRef, "pointerdown", recompute);
71271
- useRefListener(gridRef, "pointerdown", (ev) => env.isMobile() && updateMousePosition(ev));
71451
+ useRefListener(gridRef, "pointerdown", (ev) => env.isMobile() && updateMousePosition(withZoom(env, ev)));
71272
71452
  owl.useExternalListener(window, "click", handleGlobalClick);
71273
71453
  function handleGlobalClick(e) {
71274
71454
  const target = e.target;
@@ -71353,7 +71533,7 @@ stores.inject(MyMetaStore, storeInstance);
71353
71533
  if (this.env.isMobile()) {
71354
71534
  return;
71355
71535
  }
71356
- const icon = this.getInteractiveIconAtEvent(ev);
71536
+ const icon = this.getInteractiveIconAtEvent(withZoom(this.env, ev));
71357
71537
  const hoveredIcon = icon?.type ? { id: icon.type, position: icon.position } : undefined;
71358
71538
  if (!deepEquals$1(hoveredIcon, this.hoveredIconStore.hoveredIcon)) {
71359
71539
  this.hoveredIconStore.setHoveredIcon(hoveredIcon);
@@ -71364,30 +71544,30 @@ stores.inject(MyMetaStore, storeInstance);
71364
71544
  // not main button, probably a context menu
71365
71545
  return;
71366
71546
  }
71367
- this.onCellClicked(ev);
71547
+ this.onCellClicked(withZoom(this.env, ev));
71368
71548
  }
71369
71549
  onClick(ev) {
71370
71550
  if (ev.button > 0 || !this.env.isMobile()) {
71371
71551
  // not main button, probably a context menu
71372
71552
  return;
71373
71553
  }
71374
- this.onCellClicked(ev);
71554
+ this.onCellClicked(withZoom(this.env, ev));
71375
71555
  }
71376
- onCellClicked(ev) {
71556
+ onCellClicked(zoomedMouseEvent) {
71377
71557
  const openedPopover = this.cellPopovers.persistentCellPopover;
71378
- const [col, row] = this.getCartesianCoordinates(ev);
71379
- const clickedIcon = this.getInteractiveIconAtEvent(ev);
71558
+ const [col, row] = this.getCartesianCoordinates(zoomedMouseEvent);
71559
+ const clickedIcon = this.getInteractiveIconAtEvent(zoomedMouseEvent);
71380
71560
  if (clickedIcon) {
71381
71561
  this.env.model.selection.getBackToDefault();
71382
71562
  }
71383
71563
  this.props.onCellClicked(col, row, {
71384
- expandZone: ev.shiftKey,
71385
- addZone: isCtrlKey(ev),
71386
- }, ev);
71564
+ expandZone: zoomedMouseEvent.ev.shiftKey,
71565
+ addZone: isCtrlKey(zoomedMouseEvent.ev),
71566
+ }, zoomedMouseEvent);
71387
71567
  if (clickedIcon?.onClick) {
71388
71568
  clickedIcon.onClick(clickedIcon.position, this.env);
71389
71569
  }
71390
- if (ev.target === this.gridOverlay.el &&
71570
+ if (zoomedMouseEvent.ev.target === this.gridOverlay.el &&
71391
71571
  this.cellPopovers.isOpen &&
71392
71572
  deepEquals$1(openedPopover, this.cellPopovers.persistentCellPopover)) {
71393
71573
  // Only close the popover if props.click/icon.click didn't open a new one
@@ -71396,30 +71576,28 @@ stores.inject(MyMetaStore, storeInstance);
71396
71576
  }
71397
71577
  }
71398
71578
  onDoubleClick(ev) {
71399
- if (this.getInteractiveIconAtEvent(ev)) {
71579
+ const zoomedMouseEvent = withZoom(this.env, ev);
71580
+ if (this.getInteractiveIconAtEvent(zoomedMouseEvent)) {
71400
71581
  return;
71401
71582
  }
71402
- const [col, row] = this.getCartesianCoordinates(ev);
71583
+ const [col, row] = this.getCartesianCoordinates(zoomedMouseEvent);
71403
71584
  this.props.onCellDoubleClicked(col, row);
71404
71585
  }
71405
71586
  onContextMenu(ev) {
71406
- const [col, row] = this.getCartesianCoordinates(ev);
71587
+ const [col, row] = this.getCartesianCoordinates(withZoom(this.env, ev));
71407
71588
  this.props.onCellRightClicked(col, row, { x: ev.clientX, y: ev.clientY });
71408
71589
  }
71409
- getCartesianCoordinates(ev) {
71410
- const gridOverLayRect = getRefBoundingRect(this.gridOverlay);
71411
- const x = ev.clientX - gridOverLayRect.x;
71412
- const y = ev.clientY - gridOverLayRect.y;
71413
- const colIndex = this.env.model.getters.getColIndex(x);
71414
- const rowIndex = this.env.model.getters.getRowIndex(y);
71590
+ getCartesianCoordinates(zoomedMouseEvent) {
71591
+ const colIndex = this.env.model.getters.getColIndex(zoomedMouseEvent.offsetX);
71592
+ const rowIndex = this.env.model.getters.getRowIndex(zoomedMouseEvent.offsetY);
71415
71593
  return [colIndex, rowIndex];
71416
71594
  }
71417
- getInteractiveIconAtEvent(ev) {
71595
+ getInteractiveIconAtEvent(zoomedMouseEvent) {
71418
71596
  const gridOverLayRect = getRefBoundingRect(this.gridOverlay);
71419
71597
  const gridOffset = this.env.model.getters.getGridOffset();
71420
- const x = ev.clientX - gridOverLayRect.x + gridOffset.x;
71421
- const y = ev.clientY - gridOverLayRect.y + gridOffset.y;
71422
- const [col, row] = this.getCartesianCoordinates(ev);
71598
+ const x = zoomedMouseEvent.clientX - gridOverLayRect.x + gridOffset.x;
71599
+ const y = zoomedMouseEvent.clientY - gridOverLayRect.y + gridOffset.y;
71600
+ const [col, row] = this.getCartesianCoordinates(zoomedMouseEvent);
71423
71601
  const sheetId = this.env.model.getters.getActiveSheetId();
71424
71602
  let position = { col, row, sheetId };
71425
71603
  const merge = this.env.model.getters.getMerge(position);
@@ -71454,7 +71632,8 @@ stores.inject(MyMetaStore, storeInstance);
71454
71632
  if (!popover.isOpen) {
71455
71633
  return { isOpen: false };
71456
71634
  }
71457
- const anchorRect = popover.anchorRect;
71635
+ const zoom = this.env.model.getters.getViewportZoomLevel();
71636
+ const anchorRect = getZoomedRect(zoom, popover.anchorRect);
71458
71637
  return {
71459
71638
  ...popover,
71460
71639
  // transform from the "canvas coordinate system" to the "body coordinate system"
@@ -71559,8 +71738,8 @@ stores.inject(MyMetaStore, storeInstance);
71559
71738
  setup() {
71560
71739
  this.composerFocusStore = useStore(ComposerFocusStore);
71561
71740
  }
71562
- _computeHandleDisplay(ev) {
71563
- const position = this._getEvOffset(ev);
71741
+ _computeHandleDisplay(zoomedMouseEvent) {
71742
+ const position = this._getEvOffset(zoomedMouseEvent);
71564
71743
  const elementIndex = this._getElementIndex(position);
71565
71744
  if (elementIndex < 0) {
71566
71745
  return;
@@ -71580,8 +71759,8 @@ stores.inject(MyMetaStore, storeInstance);
71580
71759
  this.state.resizerIsActive = false;
71581
71760
  }
71582
71761
  }
71583
- _computeGrabDisplay(ev) {
71584
- const index = this._getElementIndex(this._getEvOffset(ev));
71762
+ _computeGrabDisplay(zoomedMouseEvent) {
71763
+ const index = this._getElementIndex(this._getEvOffset(zoomedMouseEvent));
71585
71764
  const activeElements = this._getActiveElements();
71586
71765
  const selectedZoneStart = this._getSelectedZoneStart();
71587
71766
  const selectedZoneEnd = this._getSelectedZoneEnd();
@@ -71597,26 +71776,29 @@ stores.inject(MyMetaStore, storeInstance);
71597
71776
  if (this.env.isMobile()) {
71598
71777
  return;
71599
71778
  }
71779
+ const zoomedMouseEvent = withZoom(this.env, ev);
71600
71780
  if (this.state.isResizing || this.state.isMoving || this.state.isSelecting) {
71601
71781
  return;
71602
71782
  }
71603
- this._computeHandleDisplay(ev);
71604
- this._computeGrabDisplay(ev);
71783
+ this._computeHandleDisplay(zoomedMouseEvent);
71784
+ this._computeGrabDisplay(zoomedMouseEvent);
71605
71785
  }
71606
71786
  onMouseLeave() {
71607
71787
  this.state.resizerIsActive = this.state.isResizing;
71608
71788
  this.state.waitingForMove = false;
71609
71789
  }
71610
71790
  onDblClick(ev) {
71791
+ const zoomedMouseEvent = withZoom(this.env, ev);
71611
71792
  this._fitElementSize(this.state.activeElement);
71612
71793
  this.state.isResizing = false;
71613
- this._computeHandleDisplay(ev);
71614
- this._computeGrabDisplay(ev);
71794
+ this._computeHandleDisplay(zoomedMouseEvent);
71795
+ this._computeGrabDisplay(zoomedMouseEvent);
71615
71796
  }
71616
71797
  onMouseDown(ev) {
71617
71798
  this.state.isResizing = true;
71618
71799
  this.state.delta = 0;
71619
- const initialPosition = this._getClientPosition(ev);
71800
+ const zoomedMouseEvent = withZoom(this.env, ev);
71801
+ const initialPosition = this._getClientPosition(zoomedMouseEvent);
71620
71802
  const styleValue = this.state.draggerLinePosition;
71621
71803
  const size = this._getElementSize(this.state.activeElement);
71622
71804
  const minSize = styleValue - size + this.MIN_ELEMENT_SIZE;
@@ -71628,7 +71810,7 @@ stores.inject(MyMetaStore, storeInstance);
71628
71810
  }
71629
71811
  };
71630
71812
  const onMouseMove = (ev) => {
71631
- this.state.delta = this._getClientPosition(ev) - initialPosition;
71813
+ this.state.delta = this._getClientPosition(withZoom(this.env, ev)) - initialPosition;
71632
71814
  this.state.draggerLinePosition = styleValue + this.state.delta;
71633
71815
  if (this.state.draggerLinePosition < minSize) {
71634
71816
  this.state.draggerLinePosition = minSize;
@@ -71649,7 +71831,8 @@ stores.inject(MyMetaStore, storeInstance);
71649
71831
  // not main button, probably a context menu
71650
71832
  return;
71651
71833
  }
71652
- const index = this._getElementIndex(this._getEvOffset(ev));
71834
+ const zoomedMouseEvent = withZoom(this.env, ev);
71835
+ const index = this._getElementIndex(this._getEvOffset(zoomedMouseEvent));
71653
71836
  this._selectElement(index, false);
71654
71837
  }
71655
71838
  select(ev) {
@@ -71660,7 +71843,8 @@ stores.inject(MyMetaStore, storeInstance);
71660
71843
  // not main button, probably a context menu
71661
71844
  return;
71662
71845
  }
71663
- const index = this._getElementIndex(this._getEvOffset(ev));
71846
+ const zoomedMouseEvent = withZoom(this.env, ev);
71847
+ const index = this._getElementIndex(this._getEvOffset(zoomedMouseEvent));
71664
71848
  if (index < 0) {
71665
71849
  return;
71666
71850
  }
@@ -71683,6 +71867,7 @@ stores.inject(MyMetaStore, storeInstance);
71683
71867
  startMovement(ev) {
71684
71868
  this.state.waitingForMove = false;
71685
71869
  this.state.isMoving = true;
71870
+ const zoomedMouseEvent = withZoom(this.env, ev);
71686
71871
  const startDimensions = this._getDimensionsInViewport(this._getSelectedZoneStart());
71687
71872
  const endDimensions = this._getDimensionsInViewport(this._getSelectedZoneEnd());
71688
71873
  const defaultPosition = startDimensions.start;
@@ -71719,9 +71904,10 @@ stores.inject(MyMetaStore, storeInstance);
71719
71904
  if (this.state.base !== this._getSelectedZoneStart()) {
71720
71905
  this._moveElements();
71721
71906
  }
71722
- this._computeGrabDisplay(ev);
71907
+ const zoomedMouseEvent = withZoom(this.env, ev);
71908
+ this._computeGrabDisplay(zoomedMouseEvent);
71723
71909
  };
71724
- this.dragNDropGrid.start(ev, mouseMoveMovement, mouseUpMovement);
71910
+ this.dragNDropGrid.start(zoomedMouseEvent, mouseMoveMovement, mouseUpMovement);
71725
71911
  }
71726
71912
  startSelection(ev, index) {
71727
71913
  if (this.env.isMobile()) {
@@ -71735,6 +71921,7 @@ stores.inject(MyMetaStore, storeInstance);
71735
71921
  this._selectElement(index, isCtrlKey(ev));
71736
71922
  }
71737
71923
  this.lastSelectedElementIndex = index;
71924
+ const zoomedMouseEvent = withZoom(this.env, ev);
71738
71925
  const mouseMoveSelect = (col, row) => {
71739
71926
  const newIndex = this._getType() === "COL" ? col : row;
71740
71927
  if (newIndex !== this.lastSelectedElementIndex && newIndex !== -1) {
@@ -71745,16 +71932,16 @@ stores.inject(MyMetaStore, storeInstance);
71745
71932
  const mouseUpSelect = () => {
71746
71933
  this.state.isSelecting = false;
71747
71934
  this.lastSelectedElementIndex = null;
71748
- this._computeGrabDisplay(ev);
71935
+ this._computeGrabDisplay(zoomedMouseEvent);
71749
71936
  };
71750
- this.dragNDropGrid.start(ev, mouseMoveSelect, mouseUpSelect);
71937
+ this.dragNDropGrid.start(zoomedMouseEvent, mouseMoveSelect, mouseUpSelect);
71751
71938
  }
71752
71939
  onMouseUp(ev) {
71753
71940
  this.lastSelectedElementIndex = null;
71754
71941
  }
71755
71942
  onContextMenu(ev) {
71756
71943
  ev.preventDefault();
71757
- const index = this._getElementIndex(this._getEvOffset(ev));
71944
+ const index = this._getElementIndex(this._getEvOffset(withZoom(this.env, ev)));
71758
71945
  if (index < 0)
71759
71946
  return;
71760
71947
  if (!this._getActiveElements().has(index)) {
@@ -71781,14 +71968,14 @@ stores.inject(MyMetaStore, storeInstance);
71781
71968
  get sheetId() {
71782
71969
  return this.env.model.getters.getActiveSheetId();
71783
71970
  }
71784
- _getEvOffset(ev) {
71785
- return ev.offsetX;
71971
+ _getEvOffset(zoomedMouseEvent) {
71972
+ return zoomedMouseEvent.offsetX;
71786
71973
  }
71787
71974
  _getViewportOffset() {
71788
71975
  return this.env.model.getters.getActiveMainViewport().left;
71789
71976
  }
71790
- _getClientPosition(ev) {
71791
- return ev.clientX;
71977
+ _getClientPosition(zoomedMouseEvent) {
71978
+ return zoomedMouseEvent.clientX;
71792
71979
  }
71793
71980
  _getElementIndex(position) {
71794
71981
  return this.env.model.getters.getColIndex(position);
@@ -71923,14 +72110,14 @@ stores.inject(MyMetaStore, storeInstance);
71923
72110
  get sheetId() {
71924
72111
  return this.env.model.getters.getActiveSheetId();
71925
72112
  }
71926
- _getEvOffset(ev) {
71927
- return ev.offsetY;
72113
+ _getEvOffset(zoomedMouseEvent) {
72114
+ return zoomedMouseEvent.offsetY;
71928
72115
  }
71929
72116
  _getViewportOffset() {
71930
72117
  return this.env.model.getters.getActiveMainViewport().top;
71931
72118
  }
71932
- _getClientPosition(ev) {
71933
- return ev.clientY;
72119
+ _getClientPosition(zoomedMouseEvent) {
72120
+ return zoomedMouseEvent.clientY;
71934
72121
  }
71935
72122
  _getElementIndex(position) {
71936
72123
  return this.env.model.getters.getRowIndex(position);
@@ -72108,6 +72295,9 @@ stores.inject(MyMetaStore, storeInstance);
72108
72295
  break;
72109
72296
  }
72110
72297
  }
72298
+ finalize() {
72299
+ this.zonesWithPreventedAnimationsInNextFrame = recomputeZones(this.zonesWithPreventedAnimationsInNextFrame);
72300
+ }
72111
72301
  get renderingLayers() {
72112
72302
  return ["Background", "Headers"];
72113
72303
  }
@@ -72879,18 +73069,21 @@ stores.inject(MyMetaStore, storeInstance);
72879
73069
  const canvas = canvasRef.el;
72880
73070
  const dpr = window.devicePixelRatio || 1;
72881
73071
  const ctx = canvas.getContext("2d", { alpha: false });
73072
+ const zoom = Math.max(model.getters.getViewportZoomLevel(), 1);
72882
73073
  const thinLineWidth = 0.4 * dpr;
72883
73074
  const renderingContext = {
72884
73075
  ctx,
72885
73076
  dpr,
72886
73077
  thinLineWidth,
72887
73078
  };
72888
- const { width, height } = canvasSize();
73079
+ let { width, height } = canvasSize();
73080
+ width = zoom * width;
73081
+ height = zoom * height;
72889
73082
  canvas.style.width = `${width}px`;
72890
73083
  canvas.style.height = `${height}px`;
72891
73084
  canvas.width = width * dpr;
72892
73085
  canvas.height = height * dpr;
72893
- canvas.setAttribute("style", `width:${width}px;height:${height}px;`);
73086
+ canvas.setAttribute("style", `width:${width}px;height:${height}px;zoom:${1 / zoom}`);
72894
73087
  if (width === 0 || height === 0) {
72895
73088
  return;
72896
73089
  }
@@ -72901,7 +73094,7 @@ stores.inject(MyMetaStore, storeInstance);
72901
73094
  // you need to shift the coordinates by 0.5 perpendicular to the line's direction.
72902
73095
  // http://diveintohtml5.info/canvas.html#pixel-madness
72903
73096
  ctx.translate(-CANVAS_SHIFT, -CANVAS_SHIFT);
72904
- ctx.scale(dpr, dpr);
73097
+ ctx.scale(dpr * zoom, dpr * zoom);
72905
73098
  rendererStore.draw(renderingContext);
72906
73099
  }
72907
73100
  }
@@ -73137,6 +73330,7 @@ stores.inject(MyMetaStore, storeInstance);
73137
73330
  }
73138
73331
  onResizeHighlight(ev, dirX, dirY) {
73139
73332
  const activeSheetId = this.env.model.getters.getActiveSheetId();
73333
+ const zoomedMouseEvent = withZoom(this.env, ev);
73140
73334
  this.highlightState.shiftingMode = "isResizing";
73141
73335
  const z = this.props.range.zone;
73142
73336
  const pivotCol = dirX === 1 ? z.left : z.right;
@@ -73175,11 +73369,12 @@ stores.inject(MyMetaStore, storeInstance);
73175
73369
  const mouseUp = () => {
73176
73370
  this.highlightState.shiftingMode = "none";
73177
73371
  };
73178
- this.dragNDropGrid.start(ev, mouseMove, mouseUp, scrollDirection);
73372
+ this.dragNDropGrid.start(zoomedMouseEvent, mouseMove, mouseUp, scrollDirection);
73179
73373
  }
73180
73374
  onMoveHighlight(ev) {
73181
73375
  this.highlightState.shiftingMode = "isMoving";
73182
73376
  const z = this.props.range.zone;
73377
+ const zoomedMouseEvent = withZoom(this.env, ev);
73183
73378
  const position = gridOverlayPosition();
73184
73379
  const activeSheetId = this.env.model.getters.getActiveSheetId();
73185
73380
  const initCol = this.env.model.getters.getColIndex(ev.clientX - position.left);
@@ -73216,7 +73411,7 @@ stores.inject(MyMetaStore, storeInstance);
73216
73411
  const mouseUp = () => {
73217
73412
  this.highlightState.shiftingMode = "none";
73218
73413
  };
73219
- this.dragNDropGrid.start(ev, mouseMove, mouseUp);
73414
+ this.dragNDropGrid.start(zoomedMouseEvent, mouseMove, mouseUp);
73220
73415
  }
73221
73416
  }
73222
73417
 
@@ -73322,11 +73517,12 @@ stores.inject(MyMetaStore, storeInstance);
73322
73517
  }
73323
73518
  get position() {
73324
73519
  const { x } = this.env.model.getters.getMainViewportRect();
73520
+ const scrollbarWidth = this.env.model.getters.getScrollBarWidth();
73325
73521
  return {
73326
73522
  left: `${this.props.leftOffset + x}px`,
73327
73523
  bottom: "0px",
73328
- height: `${SCROLLBAR_WIDTH}px`,
73329
- right: isBrowserFirefox() ? `${SCROLLBAR_WIDTH}px` : "0",
73524
+ height: `${scrollbarWidth}px`,
73525
+ right: isBrowserFirefox() ? `${scrollbarWidth}px` : "0",
73330
73526
  };
73331
73527
  }
73332
73528
  onScroll(offset) {
@@ -73367,11 +73563,12 @@ stores.inject(MyMetaStore, storeInstance);
73367
73563
  }
73368
73564
  get position() {
73369
73565
  const { y } = this.env.model.getters.getMainViewportRect();
73566
+ const scrollbarWidth = this.env.model.getters.getScrollBarWidth();
73370
73567
  return {
73371
73568
  top: `${this.props.topOffset + y}px`,
73372
73569
  right: "0px",
73373
- width: `${SCROLLBAR_WIDTH}px`,
73374
- bottom: isBrowserFirefox() ? `${SCROLLBAR_WIDTH}px` : "0",
73570
+ width: `${scrollbarWidth}px`,
73571
+ bottom: isBrowserFirefox() ? `${scrollbarWidth}px` : "0",
73375
73572
  };
73376
73573
  }
73377
73574
  onScroll(offset) {
@@ -73580,34 +73777,38 @@ stores.inject(MyMetaStore, storeInstance);
73580
73777
  }
73581
73778
  }
73582
73779
 
73583
- class FontSizeEditor extends owl.Component {
73584
- static template = "o-spreadsheet-FontSizeEditor";
73780
+ class NumberEditor extends owl.Component {
73781
+ static template = "o-spreadsheet-NumberEditor";
73585
73782
  static props = {
73586
- currentFontSize: Number,
73587
- onFontSizeChanged: Function,
73783
+ currentValue: Number,
73784
+ onValueChange: Function,
73588
73785
  onToggle: { type: Function, optional: true },
73589
73786
  onFocusInput: { type: Function, optional: true },
73590
73787
  class: String,
73788
+ valueIcon: { type: String, optional: true },
73789
+ min: Number,
73790
+ max: Number,
73791
+ title: String,
73792
+ valueList: (Array),
73591
73793
  };
73592
73794
  static defaultProps = {
73593
73795
  onFocusInput: () => { },
73594
73796
  };
73595
73797
  static components = { Popover };
73596
- fontSizes = FONT_SIZES;
73597
73798
  dropdown = owl.useState({ isOpen: false });
73598
- inputRef = owl.useRef("inputFontSize");
73599
- rootEditorRef = owl.useRef("FontSizeEditor");
73600
- fontSizeListRef = owl.useRef("fontSizeList");
73799
+ inputRef = owl.useRef("inputNumber");
73800
+ rootEditorRef = owl.useRef("NumberEditor");
73801
+ valueListRef = owl.useRef("numberList");
73601
73802
  setup() {
73602
73803
  owl.useExternalListener(window, "click", this.onExternalClick, { capture: true });
73603
73804
  owl.onWillUpdateProps((nextProps) => {
73604
73805
  if (this.inputRef.el && document.activeElement !== this.inputRef.el) {
73605
- this.inputRef.el.value = nextProps.currentFontSize;
73806
+ this.inputRef.el.value = nextProps.currentValue;
73606
73807
  }
73607
73808
  });
73608
73809
  owl.onMounted(() => {
73609
73810
  if (this.inputRef.el) {
73610
- this.inputRef.el.value = this.props.currentFontSize.toString();
73811
+ this.inputRef.el.value = this.props.currentValue.toString();
73611
73812
  }
73612
73813
  });
73613
73814
  }
@@ -73620,33 +73821,36 @@ stores.inject(MyMetaStore, storeInstance);
73620
73821
  };
73621
73822
  }
73622
73823
  onExternalClick(ev) {
73623
- if (!isChildEvent(this.fontSizeListRef.el, ev) && !isChildEvent(this.rootEditorRef.el, ev)) {
73624
- this.closeFontList();
73824
+ if (!isChildEvent(this.valueListRef.el, ev) && !isChildEvent(this.rootEditorRef.el, ev)) {
73825
+ this.closeList();
73625
73826
  }
73626
73827
  }
73627
- toggleFontList() {
73828
+ toggleList() {
73628
73829
  const isOpen = this.dropdown.isOpen;
73629
73830
  if (!isOpen) {
73630
73831
  this.props.onToggle?.();
73631
73832
  this.inputRef.el.focus();
73632
73833
  }
73633
73834
  else {
73634
- this.closeFontList();
73835
+ this.closeList();
73635
73836
  }
73636
73837
  }
73637
- closeFontList() {
73838
+ closeList() {
73638
73839
  this.dropdown.isOpen = false;
73639
73840
  }
73640
- setSize(fontSizeStr) {
73641
- const fontSize = clip(Math.floor(parseFloat(fontSizeStr)), 1, 400);
73642
- this.props.onFontSizeChanged(fontSize);
73643
- this.closeFontList();
73841
+ setValue(valueStr) {
73842
+ const value = clip(Math.floor(parseFloat(valueStr)), this.props.min, this.props.max);
73843
+ this.props.onValueChange(value);
73844
+ this.closeList();
73644
73845
  }
73645
- setSizeFromInput(ev) {
73646
- this.setSize(ev.target.value);
73846
+ setValueFromInput(ev) {
73847
+ this.setValue(ev.target.value);
73647
73848
  }
73648
- setSizeFromList(fontSizeStr) {
73649
- this.setSize(fontSizeStr);
73849
+ setValueFromList(valueStr) {
73850
+ this.setValue(valueStr);
73851
+ }
73852
+ get currentValue() {
73853
+ return `${this.props.currentValue}`;
73650
73854
  }
73651
73855
  onInputFocused(ev) {
73652
73856
  this.dropdown.isOpen = true;
@@ -73654,17 +73858,33 @@ stores.inject(MyMetaStore, storeInstance);
73654
73858
  }
73655
73859
  onInputKeydown(ev) {
73656
73860
  if (ev.key === "Enter" || ev.key === "Escape") {
73657
- this.closeFontList();
73861
+ this.closeList();
73658
73862
  const target = ev.target;
73659
73863
  // In the case of a ESCAPE key, we get the previous font size back
73660
73864
  if (ev.key === "Escape") {
73661
- target.value = `${this.props.currentFontSize}`;
73865
+ target.value = `${this.props.currentValue}`;
73662
73866
  }
73663
73867
  this.props.onToggle?.();
73664
73868
  }
73665
73869
  }
73666
73870
  }
73667
73871
 
73872
+ class FontSizeEditor extends owl.Component {
73873
+ static template = "o-spreadsheet-FontSizeEditor";
73874
+ static components = { NumberEditor };
73875
+ static props = {
73876
+ currentFontSize: Number,
73877
+ onFontSizeChanged: Function,
73878
+ onToggle: { type: Function, optional: true },
73879
+ onFocusInput: { type: Function, optional: true },
73880
+ class: String,
73881
+ };
73882
+ static defaultProps = {
73883
+ onFocusInput: () => { },
73884
+ };
73885
+ fontSizes = FONT_SIZES;
73886
+ }
73887
+
73668
73888
  class TextStyler extends owl.Component {
73669
73889
  static template = "o-spreadsheet.TextStyler";
73670
73890
  static components = { ColorPickerWidget, ActionButton, FontSizeEditor };
@@ -76681,15 +76901,19 @@ stores.inject(MyMetaStore, storeInstance);
76681
76901
  this.updateConditionalFormat({ rule: this.state.rules.colorScale });
76682
76902
  this.closeMenus();
76683
76903
  }
76684
- getPreviewGradient() {
76904
+ getColorScalePreviewStyle() {
76685
76905
  const rule = this.state.rules.colorScale;
76686
76906
  const minColor = colorNumberToHex(rule.minimum.color);
76687
76907
  const midColor = colorNumberToHex(rule.midpoint?.color || DEFAULT_COLOR_SCALE_MIDPOINT_COLOR);
76688
76908
  const maxColor = colorNumberToHex(rule.maximum.color);
76689
- const baseString = "background-image: linear-gradient(to right, ";
76690
- return rule.midpoint === undefined
76909
+ const baseString = "linear-gradient(to right, ";
76910
+ const backgroundImage = rule.midpoint === undefined
76691
76911
  ? baseString + minColor + ", " + maxColor + ")"
76692
76912
  : baseString + minColor + ", " + midColor + ", " + maxColor + ")";
76913
+ return cssPropertiesToCss({
76914
+ "background-image": backgroundImage,
76915
+ color: "#000",
76916
+ });
76693
76917
  }
76694
76918
  getThresholdColor(threshold) {
76695
76919
  return threshold
@@ -79035,11 +79259,15 @@ stores.inject(MyMetaStore, storeInstance);
79035
79259
  class PivotDesignPanel extends owl.Component {
79036
79260
  static template = "o-spreadsheet-PivotDesignPanel";
79037
79261
  static props = { pivotId: String };
79038
- static components = { Section, Checkbox };
79262
+ static components = { Section, Checkbox, NumberInput };
79039
79263
  store;
79040
79264
  setup() {
79041
79265
  this.store = useLocalStore(PivotSidePanelStore, this.props.pivotId, "neverDefer");
79042
79266
  }
79267
+ updatePivotStyleNumberProperty(valueStr, key) {
79268
+ const value = parseInt(valueStr);
79269
+ this.store.update({ style: { ...this.pivotStyle, [key]: isNaN(value) ? undefined : value } });
79270
+ }
79043
79271
  updatePivotStyleProperty(key, value) {
79044
79272
  this.store.update({ style: { ...this.pivotStyle, [key]: value } });
79045
79273
  }
@@ -80204,6 +80432,7 @@ stores.inject(MyMetaStore, storeInstance);
80204
80432
  const tableZone = this.props.table.range.zone;
80205
80433
  const topLeft = { col: tableZone.left, row: tableZone.top };
80206
80434
  document.body.style.cursor = "nwse-resize";
80435
+ const zoomedMouseEvent = withZoom(this.env, ev);
80207
80436
  const onMouseUp = () => {
80208
80437
  document.body.style.cursor = "";
80209
80438
  const newTableZone = this.state.highlightZone;
@@ -80225,7 +80454,7 @@ stores.inject(MyMetaStore, storeInstance);
80225
80454
  bottom: Math.max(row, topLeft.row),
80226
80455
  };
80227
80456
  };
80228
- this.dragNDropGrid.start(ev, onMouseMove, onMouseUp);
80457
+ this.dragNDropGrid.start(zoomedMouseEvent, onMouseMove, onMouseUp);
80229
80458
  }
80230
80459
  get highlights() {
80231
80460
  if (!this.state.highlightZone)
@@ -80300,7 +80529,9 @@ stores.inject(MyMetaStore, storeInstance);
80300
80529
  this.paintFormatStore = useStore(PaintFormatStore);
80301
80530
  this.clientFocusStore = useStore(ClientFocusStore);
80302
80531
  useStore(ArrayFormulaHighlight);
80303
- owl.useChildSubEnv({ getPopoverContainerRect: () => this.getGridRect() });
80532
+ owl.useChildSubEnv({
80533
+ getPopoverContainerRect: () => getZoomedRect(this.env.model.getters.getViewportZoomLevel(), this.getGridRect()),
80534
+ });
80304
80535
  owl.useExternalListener(document.body, "cut", this.copy.bind(this, true));
80305
80536
  owl.useExternalListener(document.body, "copy", this.copy.bind(this, false));
80306
80537
  owl.useExternalListener(document.body, "paste", this.paste);
@@ -80326,11 +80557,12 @@ stores.inject(MyMetaStore, storeInstance);
80326
80557
  return this.highlightStore.highlights;
80327
80558
  }
80328
80559
  get gridOverlayDimensions() {
80560
+ const scrollbarWidth = this.env.model.getters.getScrollBarWidth();
80329
80561
  return cssPropertiesToCss({
80330
80562
  top: `${HEADER_HEIGHT}px`,
80331
80563
  left: `${HEADER_WIDTH}px`,
80332
- height: `calc(100% - ${HEADER_HEIGHT + SCROLLBAR_WIDTH}px)`,
80333
- width: `calc(100% - ${HEADER_WIDTH + SCROLLBAR_WIDTH}px)`,
80564
+ height: `calc(100% - ${HEADER_HEIGHT + scrollbarWidth}px)`,
80565
+ width: `calc(100% - ${HEADER_WIDTH + scrollbarWidth}px)`,
80334
80566
  });
80335
80567
  }
80336
80568
  onClosePopover() {
@@ -80536,8 +80768,8 @@ stores.inject(MyMetaStore, storeInstance);
80536
80768
  const zone = this.env.model.getters.getSelectedZone();
80537
80769
  const rect = this.env.model.getters.getVisibleRect(zone);
80538
80770
  return {
80539
- left: rect.x + rect.width - AUTOFILL_EDGE_LENGTH / 2,
80540
- top: rect.y + rect.height - AUTOFILL_EDGE_LENGTH / 2,
80771
+ x: rect.x + rect.width - AUTOFILL_EDGE_LENGTH / 2,
80772
+ y: rect.y + rect.height - AUTOFILL_EDGE_LENGTH / 2,
80541
80773
  };
80542
80774
  }
80543
80775
  get isAutofillVisible() {
@@ -80593,8 +80825,8 @@ stores.inject(MyMetaStore, storeInstance);
80593
80825
  // ---------------------------------------------------------------------------
80594
80826
  // Zone selection with mouse
80595
80827
  // ---------------------------------------------------------------------------
80596
- onCellClicked(col, row, modifiers, ev) {
80597
- ev.preventDefault();
80828
+ onCellClicked(col, row, modifiers, zoomedMouseEvent) {
80829
+ zoomedMouseEvent.ev.preventDefault();
80598
80830
  if (this.composerFocusStore.activeComposer.editionMode === "editing") {
80599
80831
  this.composerFocusStore.activeComposer.stopEdition();
80600
80832
  }
@@ -80628,7 +80860,7 @@ stores.inject(MyMetaStore, storeInstance);
80628
80860
  this.paintFormatStore.pasteFormat(this.env.model.getters.getSelectedZones());
80629
80861
  }
80630
80862
  };
80631
- this.dragNDropGrid.start(ev, onMouseMove, onMouseUp);
80863
+ this.dragNDropGrid.start(zoomedMouseEvent, onMouseMove, onMouseUp);
80632
80864
  }
80633
80865
  onCellDoubleClicked(col, row) {
80634
80866
  const sheetId = this.env.model.getters.getActiveSheetId();
@@ -81842,7 +82074,7 @@ stores.inject(MyMetaStore, storeInstance);
81842
82074
  htmlContent: [
81843
82075
  {
81844
82076
  value: value.label,
81845
- color: color ? chipTextColor(color) : undefined,
82077
+ color: chipTextColor(color || GRAY_200),
81846
82078
  backgroundColor: color || GRAY_200,
81847
82079
  classes: ["badge rounded-pill fs-6 fw-normal w-100 mt-1 text-start"],
81848
82080
  },
@@ -82526,6 +82758,7 @@ stores.inject(MyMetaStore, storeInstance);
82526
82758
  .add("file", {
82527
82759
  name: _t$1("File"),
82528
82760
  sequence: 10,
82761
+ isReadonlyAllowed: true,
82529
82762
  })
82530
82763
  .addChild("settings", ["file"], {
82531
82764
  name: _t$1("Settings"),
@@ -82540,6 +82773,7 @@ stores.inject(MyMetaStore, storeInstance);
82540
82773
  .add("edit", {
82541
82774
  name: _t$1("Edit"),
82542
82775
  sequence: 20,
82776
+ isReadonlyAllowed: true,
82543
82777
  })
82544
82778
  .addChild("undo", ["edit"], {
82545
82779
  ...undo,
@@ -82624,6 +82858,7 @@ stores.inject(MyMetaStore, storeInstance);
82624
82858
  .add("view", {
82625
82859
  name: _t$1("View"),
82626
82860
  sequence: 30,
82861
+ isReadonlyAllowed: true,
82627
82862
  })
82628
82863
  .addChild("unfreeze_panes", ["view"], {
82629
82864
  ...unFreezePane,
@@ -82703,6 +82938,11 @@ stores.inject(MyMetaStore, storeInstance);
82703
82938
  .addChild("view_formulas", ["view", "show"], {
82704
82939
  ...viewFormulas,
82705
82940
  sequence: 10,
82941
+ })
82942
+ .addChild("zoom", ["view"], {
82943
+ name: _t$1("Zoom"),
82944
+ sequence: 1,
82945
+ icon: "o-spreadsheet-Icon.ZOOM",
82706
82946
  })
82707
82947
  .addChild("view_irregularity_map", ["view"], {
82708
82948
  ...irregularityMap,
@@ -82715,6 +82955,7 @@ stores.inject(MyMetaStore, storeInstance);
82715
82955
  .add("insert", {
82716
82956
  name: _t$1("Insert"),
82717
82957
  sequence: 40,
82958
+ isReadonlyAllowed: true,
82718
82959
  })
82719
82960
  .addChild("insert_row", ["insert"], {
82720
82961
  ...insertRow,
@@ -82826,7 +83067,11 @@ stores.inject(MyMetaStore, storeInstance);
82826
83067
  // ---------------------------------------------------------------------
82827
83068
  // FORMAT MENU ITEMS
82828
83069
  // ---------------------------------------------------------------------
82829
- .add("format", { name: _t$1("Format"), sequence: 50 })
83070
+ .add("format", {
83071
+ name: _t$1("Format"),
83072
+ sequence: 50,
83073
+ isReadonlyAllowed: true,
83074
+ })
82830
83075
  .addChild("format_number", ["format"], {
82831
83076
  ...formatNumberMenuItemSpec,
82832
83077
  name: _t$1("Number"),
@@ -82918,6 +83163,7 @@ stores.inject(MyMetaStore, storeInstance);
82918
83163
  .add("data", {
82919
83164
  name: _t$1("Data"),
82920
83165
  sequence: 60,
83166
+ isReadonlyAllowed: true,
82921
83167
  })
82922
83168
  .addChild("sort_range", ["data"], {
82923
83169
  ...sortRange,
@@ -82991,6 +83237,10 @@ stores.inject(MyMetaStore, storeInstance);
82991
83237
  })
82992
83238
  .addChild("reinsert_dynamic_pivot", ["data"], reinsertDynamicPivotMenu)
82993
83239
  .addChild("reinsert_static_pivot", ["data"], reinsertStaticPivotMenu);
83240
+ // Zoom
83241
+ ZOOM_VALUES.forEach((zoom) => {
83242
+ topbarMenuRegistry.addChild(`zoom${zoom}`, ["view", "zoom"], zoomAction(zoom));
83243
+ });
82994
83244
 
82995
83245
  const genericRepeatsTransforms = [
82996
83246
  repeatSheetDependantCommand,
@@ -84021,7 +84271,9 @@ stores.inject(MyMetaStore, storeInstance);
84021
84271
  this.gridRef = owl.useRef("grid");
84022
84272
  this.hoveredCell = useStore(DelayedHoveredCellStore);
84023
84273
  this.clickableCellsStore = useStore(ClickableCellsStore);
84024
- owl.useChildSubEnv({ getPopoverContainerRect: () => this.getGridRect() });
84274
+ owl.useChildSubEnv({
84275
+ getPopoverContainerRect: () => getZoomedRect(this.env.model.getters.getViewportZoomLevel(), this.getGridRect()),
84276
+ });
84025
84277
  useGridDrawing("canvas", this.env.model, () => this.env.model.getters.getSheetViewDimension());
84026
84278
  this.onMouseWheel = useWheelHandler((deltaX, deltaY) => {
84027
84279
  this.moveCanvas(deltaX, deltaY);
@@ -85087,6 +85339,35 @@ stores.inject(MyMetaStore, storeInstance);
85087
85339
  }
85088
85340
  }
85089
85341
 
85342
+ class ToolBarZoom extends owl.Component {
85343
+ static template = "o-spreadsheet-TopBarZoom";
85344
+ static components = { NumberEditor };
85345
+ static props = { class: String };
85346
+ topBarToolStore;
85347
+ valueList = ZOOM_VALUES;
85348
+ setup() {
85349
+ this.topBarToolStore = useToolBarDropdownStore();
85350
+ }
85351
+ get currentFontSize() {
85352
+ const zoom = this.env.model.getters.getViewportZoomLevel() || 1;
85353
+ return zoom * 100;
85354
+ }
85355
+ setZoom(fontSize) {
85356
+ this.env.model.dispatch("SET_ZOOM", { zoom: fontSize / 100 });
85357
+ }
85358
+ toggle() {
85359
+ if (this.topBarToolStore.isActive) {
85360
+ this.topBarToolStore.closeDropdowns();
85361
+ }
85362
+ else {
85363
+ this.topBarToolStore.openDropdown();
85364
+ }
85365
+ }
85366
+ onFocusInput() {
85367
+ this.topBarToolStore.openDropdown();
85368
+ }
85369
+ }
85370
+
85090
85371
  const topBarToolBarRegistry = new ToolBarRegistry();
85091
85372
  topBarToolBarRegistry
85092
85373
  .add("edit")
@@ -85120,6 +85401,13 @@ stores.inject(MyMetaStore, storeInstance);
85120
85401
  class: "o-hoverable-button o-toolbar-button",
85121
85402
  },
85122
85403
  sequence: 4,
85404
+ })
85405
+ .addChild("edit", {
85406
+ component: ToolBarZoom,
85407
+ props: {
85408
+ class: "o-menu-item-button o-hoverable-button o-toolbar-button",
85409
+ },
85410
+ sequence: 5,
85123
85411
  })
85124
85412
  .add("numberFormat")
85125
85413
  .addChild("numberFormat", {
@@ -85563,6 +85851,7 @@ stores.inject(MyMetaStore, storeInstance);
85563
85851
  notifyUser: { type: Function, optional: true },
85564
85852
  raiseError: { type: Function, optional: true },
85565
85853
  askConfirmation: { type: Function, optional: true },
85854
+ colorScheme: { type: String, optional: true },
85566
85855
  };
85567
85856
  static components = {
85568
85857
  TopBar,
@@ -85586,6 +85875,7 @@ stores.inject(MyMetaStore, storeInstance);
85586
85875
  }
85587
85876
  getStyle() {
85588
85877
  const properties = {};
85878
+ const scrollbarWidth = this.env.model.getters.getScrollBarWidth();
85589
85879
  if (this.env.isDashboard()) {
85590
85880
  properties["grid-template-rows"] = `auto`;
85591
85881
  }
@@ -85596,6 +85886,8 @@ stores.inject(MyMetaStore, storeInstance);
85596
85886
  ? `${this.sidePanel.totalPanelSize || DEFAULT_SIDE_PANEL_SIZE}px`
85597
85887
  : "auto";
85598
85888
  properties["grid-template-columns"] = `auto ${columnWidth}`;
85889
+ properties["--os-scrollbar-width"] = `${scrollbarWidth}px`;
85890
+ properties["color-scheme"] = this.props.colorScheme;
85599
85891
  return cssPropertiesToCss(properties);
85600
85892
  }
85601
85893
  setup() {
@@ -85724,9 +86016,11 @@ stores.inject(MyMetaStore, storeInstance);
85724
86016
  get gridContainerStyle() {
85725
86017
  const gridColSize = GROUP_LAYER_WIDTH * this.rowLayers.length;
85726
86018
  const gridRowSize = GROUP_LAYER_WIDTH * this.colLayers.length;
86019
+ const zoom = this.env.model.getters.getViewportZoomLevel();
85727
86020
  return cssPropertiesToCss({
85728
86021
  "grid-template-columns": `${gridColSize ? gridColSize + 2 : 0}px auto`, // +2: margins
85729
86022
  "grid-template-rows": `${gridRowSize ? gridRowSize + 2 : 0}px auto`,
86023
+ zoom: `${zoom}`,
85730
86024
  });
85731
86025
  }
85732
86026
  get rowLayers() {
@@ -85738,6 +86032,8 @@ stores.inject(MyMetaStore, storeInstance);
85738
86032
  return this.env.model.getters.getVisibleGroupLayers(sheetId, "COL");
85739
86033
  }
85740
86034
  getGridSize() {
86035
+ const zoom = this.env.model.getters.getViewportZoomLevel();
86036
+ const scrollbarWidth = this.env.model.getters.getScrollBarWidth();
85741
86037
  const topBarHeight = this.spreadsheetRef.el
85742
86038
  ?.querySelector(".o-spreadsheet-topbar-wrapper")
85743
86039
  ?.getBoundingClientRect().height || 0;
@@ -85751,10 +86047,16 @@ stores.inject(MyMetaStore, storeInstance);
85751
86047
  topBarHeight -
85752
86048
  bottomBarHeight;
85753
86049
  return {
85754
- width: Math.max(gridWidth - SCROLLBAR_WIDTH, 0),
85755
- height: Math.max(gridHeight - SCROLLBAR_WIDTH, 0),
86050
+ width: Math.max(gridWidth / zoom - scrollbarWidth, 0),
86051
+ height: Math.max(gridHeight / zoom - scrollbarWidth, 0),
85756
86052
  };
85757
86053
  }
86054
+ getSpreadSheetClasses() {
86055
+ return [
86056
+ this.env.isSmall ? "o-spreadsheet-mobile" : "",
86057
+ this.props.colorScheme === "dark" ? "dark" : "",
86058
+ ].join(" ");
86059
+ }
85758
86060
  }
85759
86061
 
85760
86062
  class ComboChart extends AbstractChart {
@@ -88202,6 +88504,7 @@ stores.inject(MyMetaStore, storeInstance);
88202
88504
  ChartDashboardMenu,
88203
88505
  FullScreenFigure,
88204
88506
  NumberInput,
88507
+ TopBar,
88205
88508
  };
88206
88509
  const hooks = {
88207
88510
  useDragAndDropListItems,
@@ -88305,9 +88608,9 @@ stores.inject(MyMetaStore, storeInstance);
88305
88608
  exports.tokenize = tokenize;
88306
88609
 
88307
88610
 
88308
- __info__.version = "19.1.0-alpha.10";
88309
- __info__.date = "2025-10-30T12:26:30.196Z";
88310
- __info__.hash = "d0b65e9";
88611
+ __info__.version = "19.1.0-alpha.12";
88612
+ __info__.date = "2025-11-12T14:17:07.713Z";
88613
+ __info__.hash = "6fefc9c";
88311
88614
 
88312
88615
 
88313
88616
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);