@odoo/o-spreadsheet 16.2.1 → 16.2.2

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.
@@ -112,88 +112,88 @@ const FILTERS_COLOR = "#188038";
112
112
  const BACKGROUND_HEADER_FILTER_COLOR = "#E6F4EA";
113
113
  const BACKGROUND_HEADER_SELECTED_FILTER_COLOR = "#CEEAD6";
114
114
  const SEPARATOR_COLOR = "#E0E2E4";
115
- // Color picker
115
+ // Color picker defaults as upper case HEX to match `toHex`helper
116
116
  const COLOR_PICKER_DEFAULTS = [
117
117
  "#000000",
118
118
  "#434343",
119
119
  "#666666",
120
120
  "#999999",
121
- "#b7b7b7",
122
- "#cccccc",
123
- "#d9d9d9",
124
- "#efefef",
125
- "#f3f3f3",
126
- "#ffffff",
121
+ "#B7B7B7",
122
+ "#CCCCCC",
123
+ "#D9D9D9",
124
+ "#EFEFEF",
125
+ "#F3F3F3",
126
+ "#FFFFFF",
127
127
  "#980000",
128
- "#ff0000",
129
- "#ff9900",
130
- "#ffff00",
131
- "#00ff00",
132
- "#00ffff",
133
- "#4a86e8",
134
- "#0000ff",
135
- "#9900ff",
136
- "#ff00ff",
137
- "#e6b8af",
138
- "#f4cccc",
139
- "#fce5cd",
140
- "#fff2cc",
141
- "#d9ead3",
142
- "#d0e0e3",
143
- "#c9daf8",
144
- "#cfe2f3",
145
- "#d9d2e9",
146
- "#ead1dc",
147
- "#dd7e6b",
148
- "#ea9999",
149
- "#f9cb9c",
150
- "#ffe599",
151
- "#b6d7a8",
152
- "#a2c4c9",
153
- "#a4c2f4",
154
- "#9fc5e8",
155
- "#b4a7d6",
156
- "#d5a6bd",
157
- "#cc4125",
158
- "#e06666",
159
- "#f6b26b",
160
- "#ffd966",
161
- "#93c47d",
162
- "#76a5af",
163
- "#6d9eeb",
164
- "#6fa8dc",
165
- "#8e7cc3",
166
- "#c27ba0",
167
- "#a61c00",
168
- "#cc0000",
169
- "#e69138",
170
- "#f1c232",
171
- "#6aa84f",
172
- "#45818e",
173
- "#3c78d8",
174
- "#3d85c6",
175
- "#674ea7",
176
- "#a64d79",
177
- "#85200c",
128
+ "#FF0000",
129
+ "#FF9900",
130
+ "#FFFF00",
131
+ "#00FF00",
132
+ "#00FFFF",
133
+ "#4A86E8",
134
+ "#0000FF",
135
+ "#9900FF",
136
+ "#FF00FF",
137
+ "#E6B8AF",
138
+ "#F4CCCC",
139
+ "#FCE5CD",
140
+ "#FFF2CC",
141
+ "#D9EAD3",
142
+ "#D0E0E3",
143
+ "#C9DAF8",
144
+ "#CFE2F3",
145
+ "#D9D2E9",
146
+ "#EAD1DC",
147
+ "#DD7E6B",
148
+ "#EA9999",
149
+ "#F9CB9C",
150
+ "#FFE599",
151
+ "#B6D7A8",
152
+ "#A2C4C9",
153
+ "#A4C2F4",
154
+ "#9FC5E8",
155
+ "#B4A7D6",
156
+ "#D5A6BD",
157
+ "#CC4125",
158
+ "#E06666",
159
+ "#F6B26B",
160
+ "#FFD966",
161
+ "#93C47D",
162
+ "#76A5AF",
163
+ "#6D9EEB",
164
+ "#6FA8DC",
165
+ "#8E7CC3",
166
+ "#C27BA0",
167
+ "#A61C00",
168
+ "#CC0000",
169
+ "#E69138",
170
+ "#F1C232",
171
+ "#6AA84F",
172
+ "#45818E",
173
+ "#3C78D8",
174
+ "#3D85C6",
175
+ "#674EA7",
176
+ "#A64D79",
177
+ "#85200C",
178
178
  "#990000",
179
- "#b45f06",
180
- "#bf9000",
181
- "#38761d",
182
- "#134f5c",
183
- "#1155cc",
184
- "#0b5394",
185
- "#351c75",
186
- "#741b47",
187
- "#5b0f00",
179
+ "#B45F06",
180
+ "#BF9000",
181
+ "#38761D",
182
+ "#134F5C",
183
+ "#1155CC",
184
+ "#0B5394",
185
+ "#351C75",
186
+ "#741B47",
187
+ "#5B0F00",
188
188
  "#660000",
189
- "#783f04",
190
- "#7f6000",
191
- "#274e13",
192
- "#0c343d",
193
- "#1c4587",
189
+ "#783F04",
190
+ "#7F6000",
191
+ "#274E13",
192
+ "#0C343D",
193
+ "#1C4587",
194
194
  "#073763",
195
- "#20124d",
196
- "#4c1130",
195
+ "#20124D",
196
+ "#4C1130",
197
197
  ];
198
198
  // Dimensions
199
199
  const MIN_ROW_HEIGHT = 10;
@@ -233,7 +233,7 @@ const DEFAULT_FONT = "'Roboto', arial";
233
233
  const DEFAULT_BORDER_DESC = ["thin", "#000"];
234
234
  const DEFAULT_FILTER_BORDER_DESC = ["thin", FILTERS_COLOR];
235
235
  // DateTimeRegex
236
- const DATETIME_FORMAT = /[ymd:]/;
236
+ const DATETIME_FORMAT = /[ymdhs:]/;
237
237
  // Ranges
238
238
  const INCORRECT_RANGE_STRING = CellErrorType.InvalidReference;
239
239
  // Max Number of history steps kept in memory
@@ -270,11 +270,12 @@ var ComponentsImportance;
270
270
  ComponentsImportance[ComponentsImportance["Highlight"] = 5] = "Highlight";
271
271
  ComponentsImportance[ComponentsImportance["Figure"] = 10] = "Figure";
272
272
  ComponentsImportance[ComponentsImportance["ScrollBar"] = 15] = "ScrollBar";
273
- ComponentsImportance[ComponentsImportance["Dropdown"] = 16] = "Dropdown";
273
+ ComponentsImportance[ComponentsImportance["GridPopover"] = 19] = "GridPopover";
274
274
  ComponentsImportance[ComponentsImportance["GridComposer"] = 20] = "GridComposer";
275
- ComponentsImportance[ComponentsImportance["TopBarComposer"] = 21] = "TopBarComposer";
275
+ ComponentsImportance[ComponentsImportance["Dropdown"] = 21] = "Dropdown";
276
276
  ComponentsImportance[ComponentsImportance["IconPicker"] = 25] = "IconPicker";
277
- ComponentsImportance[ComponentsImportance["Popover"] = 30] = "Popover";
277
+ ComponentsImportance[ComponentsImportance["TopBarComposer"] = 30] = "TopBarComposer";
278
+ ComponentsImportance[ComponentsImportance["Popover"] = 35] = "Popover";
278
279
  ComponentsImportance[ComponentsImportance["ChartAnchor"] = 1000] = "ChartAnchor";
279
280
  })(ComponentsImportance || (ComponentsImportance = {}));
280
281
  const DEFAULT_SHEETVIEW_SIZE = 1000;
@@ -701,8 +702,9 @@ function getDefaultCellHeight(cell) {
701
702
  return DEFAULT_CELL_HEIGHT;
702
703
  }
703
704
  const fontSize = computeTextFontSizeInPixels(cell.style);
704
- const multiLineText = cell.content.split(NEWLINE);
705
- return computeTextLinesHeight(fontSize, multiLineText.length) + 2 * PADDING_AUTORESIZE_VERTICAL;
705
+ // the number of lines should be computed from the formula result, but it's not evaluated at this point
706
+ const numberOfLines = cell.isFormula ? 1 : cell.content.split(NEWLINE).length;
707
+ return computeTextLinesHeight(fontSize, numberOfLines) + 2 * PADDING_AUTORESIZE_VERTICAL;
706
708
  }
707
709
  function computeTextWidth(context, text, style) {
708
710
  context.save();
@@ -1054,6 +1056,8 @@ function replaceSpecialSpaces(text) {
1054
1056
  return text;
1055
1057
  }
1056
1058
 
1059
+ const RBA_REGEX = /rgba?\(|\s+|\)/gi;
1060
+ const HEX_MATCH = /^#([A-F\d]{2}){3,4}$/g;
1057
1061
  const colors$1 = [
1058
1062
  "#eb6d00",
1059
1063
  "#0074d9",
@@ -1079,7 +1083,10 @@ function colorNumberString(color) {
1079
1083
  }
1080
1084
  /**
1081
1085
  * Converts any CSS color value to a standardized hex6 value.
1082
- * Accepts: hex3, hex6, hex8 and rgb (rgba is not supported)
1086
+ * Accepts: hex3, hex6, hex8, rgb[1] and rgba[1].
1087
+ *
1088
+ * [1] under the form rgb(r, g, b, a?) or rgba(r, g, b, a?)
1089
+ * with r,g,b ∈ [0, 255] and a ∈ [0, 1]
1083
1090
  *
1084
1091
  * toHex("#ABC")
1085
1092
  * >> "#AABBCC"
@@ -1090,27 +1097,31 @@ function colorNumberString(color) {
1090
1097
  * toHex("rgb(30, 80, 16)")
1091
1098
  * >> "#1E5010"
1092
1099
  *
1100
+ * * toHex("rgb(30, 80, 16, 0.5)")
1101
+ * >> "#1E501080"
1102
+ *
1093
1103
  */
1094
1104
  function toHex(color) {
1095
- if (color.includes("rgba")) {
1096
- throw new Error(`rgba() conversion currently not supported: ${color}`);
1105
+ let hexColor = color;
1106
+ if (color.startsWith("rgb")) {
1107
+ hexColor = rgbaStringToHex(color);
1097
1108
  }
1098
- if (color.includes("rgb")) {
1099
- return rgbToHex6(color);
1100
- }
1101
- color = color.replace("#", "").toUpperCase();
1102
- if (color.length === 3 || color.length === 4) {
1103
- color = color.split("").reduce((acc, h) => acc + h + h, "");
1109
+ else {
1110
+ hexColor = color.replace("#", "").toUpperCase();
1111
+ if (hexColor.length === 3 || hexColor.length === 4) {
1112
+ hexColor = hexColor.split("").reduce((acc, h) => acc + h + h, "");
1113
+ }
1114
+ hexColor = `#${hexColor}`;
1104
1115
  }
1105
- if (color.replace(/[a-f0-9]/gi, "") !== "") {
1106
- throw new Error("invalid color");
1116
+ if (!hexColor.match(HEX_MATCH)) {
1117
+ throw new Error(`invalid color input: ${color}`);
1107
1118
  }
1108
- return "#" + color;
1119
+ return hexColor;
1109
1120
  }
1110
1121
  function isColorValid(color) {
1111
1122
  try {
1112
- const { r, g, b, a } = colorToRGBA(color);
1113
- return (isColorValueValid(r) && isColorValueValid(g) && isColorValueValid(b) && isColorValueValid(a));
1123
+ toHex(color);
1124
+ return true;
1114
1125
  }
1115
1126
  catch (error) {
1116
1127
  return false;
@@ -1143,15 +1154,29 @@ function relativeLuminance(color) {
1143
1154
  /**
1144
1155
  * Convert a CSS rgb color string to a standardized hex6 color value.
1145
1156
  *
1146
- * rgbToHex6("rgb(30, 80, 16)")
1157
+ * rgbaStringToHex("rgb(30, 80, 16)")
1147
1158
  * >> "#1E5010"
1159
+ *
1160
+ * rgbaStringToHex("rgba(30, 80, 16, 0.5)")
1161
+ * >> "#1E501080"
1162
+ *
1163
+ * DOES NOT SUPPORT NON INTEGER RGB VALUES
1148
1164
  */
1149
- function rgbToHex6(color) {
1150
- return ("#" +
1151
- concat(color
1152
- .slice(4, -1)
1153
- .split(",")
1154
- .map((valueString) => parseInt(valueString, 10).toString(16).padStart(2, "0"))).toUpperCase());
1165
+ function rgbaStringToHex(color) {
1166
+ const stringVals = color.replace(RBA_REGEX, "").split(",");
1167
+ let alphaHex = 255;
1168
+ if (stringVals.length !== 3 && stringVals.length !== 4) {
1169
+ throw new Error("invalid color");
1170
+ }
1171
+ else if (stringVals.length === 4) {
1172
+ const alpha = parseFloat(stringVals.pop() || "1");
1173
+ alphaHex = Math.round((alpha || 1) * 255);
1174
+ }
1175
+ const vals = stringVals.map((val) => parseInt(val, 10));
1176
+ if (alphaHex !== 255) {
1177
+ vals.push(alphaHex);
1178
+ }
1179
+ return "#" + concat(vals.map((value) => value.toString(16).padStart(2, "0"))).toUpperCase();
1155
1180
  }
1156
1181
  /**
1157
1182
  * RGBA to HEX representation (#RRGGBBAA).
@@ -1173,7 +1198,7 @@ function rgbaToHex(rgba) {
1173
1198
  a = "0" + a;
1174
1199
  if (a === "ff")
1175
1200
  a = "";
1176
- return "#" + r + g + b + a;
1201
+ return ("#" + r + g + b + a).toUpperCase();
1177
1202
  }
1178
1203
  /**
1179
1204
  * Color string to RGBA representation
@@ -1294,6 +1319,9 @@ function rgbaToHSLA(rgba) {
1294
1319
  s = +(s * 100).toFixed(1);
1295
1320
  l = +(l * 100).toFixed(1);
1296
1321
  return { a: rgba.a, h, s, l };
1322
+ }
1323
+ function isSameColor(color1, color2) {
1324
+ return isColorValid(color1) && isColorValid(color2) && toHex(color1) === toHex(color2);
1297
1325
  }
1298
1326
 
1299
1327
  /** Reference of a cell (eg. A1, $B$5) */
@@ -1445,7 +1473,7 @@ function scrollDelay(value) {
1445
1473
  * formula, commas are used to separate arguments
1446
1474
  * - it does not support % symbol, in formulas % is an operator
1447
1475
  */
1448
- const formulaNumberRegexp = /^-?\d+(\.?\d*(e\d+)?)?|^-?\.\d+/;
1476
+ const formulaNumberRegexp = /(^-?\d+(\.?\d*(e\d+)?)?|^-?\.\d+)(?!\w|!)/;
1449
1477
  const pIntegerAndDecimals = "(\\d+(,\\d{3,})*(\\.\\d*)?)"; // pattern that match integer number with or without decimal digits
1450
1478
  const pOnlyDecimals = "(\\.\\d+)"; // pattern that match only expression with decimal digits
1451
1479
  const pScientificFormat = "(e(\\+|-)?\\d+)?"; // pattern that match scientific format between zero and one time (should be placed before pPercentFormat)
@@ -3051,6 +3079,7 @@ const CHART_PADDING_RATIO = 0.02;
3051
3079
  const LINE_HEIGHT = 1.2;
3052
3080
  css /* scss */ `
3053
3081
  div.o-scorecard {
3082
+ font-family: ${DEFAULT_FONT};
3054
3083
  user-select: none;
3055
3084
  background-color: white;
3056
3085
  display: flex;
@@ -5101,6 +5130,11 @@ class Popover extends Component {
5101
5130
  this.currentPosition = newPosition;
5102
5131
  });
5103
5132
  }
5133
+ get popoverStyle() {
5134
+ return cssPropertiesToCss({
5135
+ "z-index": `${this.props.zIndex}`,
5136
+ });
5137
+ }
5104
5138
  }
5105
5139
  Popover.template = "o-spreadsheet-Popover";
5106
5140
  Popover.defaultProps = {
@@ -5109,6 +5143,7 @@ Popover.defaultProps = {
5109
5143
  onMouseWheel: () => { },
5110
5144
  onPopoverMoved: () => { },
5111
5145
  onPopoverHidden: () => { },
5146
+ zIndex: ComponentsImportance.Popover,
5112
5147
  };
5113
5148
  Popover.props = {
5114
5149
  anchorRect: Object,
@@ -5120,6 +5155,7 @@ Popover.props = {
5120
5155
  onMouseWheel: { type: Function, optional: true },
5121
5156
  onPopoverHidden: { type: Function, optional: true },
5122
5157
  onPopoverMoved: { type: Function, optional: true },
5158
+ zIndex: { type: Number, optional: true },
5123
5159
  slots: Object,
5124
5160
  };
5125
5161
  class PopoverPositionContext {
@@ -17010,6 +17046,9 @@ class ColorPicker extends Component {
17010
17046
  top,
17011
17047
  });
17012
17048
  }
17049
+ isSameColor(color1, color2) {
17050
+ return isSameColor(color1, color2);
17051
+ }
17013
17052
  }
17014
17053
  ColorPicker.template = "o-spreadsheet-ColorPicker";
17015
17054
  ColorPicker.defaultProps = {
@@ -19251,6 +19290,8 @@ class ContentEditableHelper {
19251
19290
  start = 0;
19252
19291
  if (end > textLength)
19253
19292
  end = textLength;
19293
+ if (start > textLength)
19294
+ start = textLength;
19254
19295
  }
19255
19296
  let startNode = this.findChildAtCharacterIndex(start);
19256
19297
  let endNode = this.findChildAtCharacterIndex(end);
@@ -19520,6 +19561,7 @@ css /* scss */ `
19520
19561
  padding-right: 2px;
19521
19562
 
19522
19563
  box-sizing: border-box;
19564
+ font-family: ${DEFAULT_FONT};
19523
19565
 
19524
19566
  caret-color: black;
19525
19567
  padding-left: 3px;
@@ -20789,6 +20831,10 @@ GridOverlay.props = {
20789
20831
  };
20790
20832
 
20791
20833
  class GridPopover extends Component {
20834
+ constructor() {
20835
+ super(...arguments);
20836
+ this.zIndex = ComponentsImportance.GridPopover;
20837
+ }
20792
20838
  get cellPopover() {
20793
20839
  const popover = this.env.model.getters.getCellPopover(this.props.hoveredCell);
20794
20840
  if (!popover.isOpen) {
@@ -22153,6 +22199,10 @@ class Grid extends Component {
22153
22199
  }
22154
22200
  }
22155
22201
  onInput(ev) {
22202
+ // the user meant to paste in the sheet, not open the composer with the pasted content
22203
+ if (!ev.isComposing && ev.inputType === "insertFromPaste") {
22204
+ return;
22205
+ }
22156
22206
  if (ev.data) {
22157
22207
  // if the user types a character on the grid, it means he wants to start composing the selected cell with that
22158
22208
  // character
@@ -23001,6 +23051,70 @@ function fixXlsxUnicode(str) {
23001
23051
  });
23002
23052
  }
23003
23053
 
23054
+ const XLSX_DATE_FORMAT_REGEX = /^(yy|yyyy|m{1,5}|d{1,4}|h{1,2}|s{1,2}|am\/pm|a\/m|\s|-|\/|\.|:)+$/i;
23055
+ /**
23056
+ * Convert excel format to o_spreadsheet format
23057
+ *
23058
+ * Excel format are defined in openXML §18.8.31
23059
+ */
23060
+ function convertXlsxFormat(numFmtId, formats, warningManager) {
23061
+ var _a, _b, _c;
23062
+ if (numFmtId === 0) {
23063
+ return undefined;
23064
+ }
23065
+ // Format is either defined in the imported data, or the formatId is defined in openXML §18.8.30
23066
+ let format = XLSX_FORMATS_CONVERSION_MAP[numFmtId] || ((_a = formats.find((f) => f.id === numFmtId)) === null || _a === void 0 ? void 0 : _a.format);
23067
+ if (format) {
23068
+ try {
23069
+ let convertedFormat = format.replace(/(.*?);.*/, "$1"); // only take first part of multi-part format
23070
+ convertedFormat = convertedFormat.replace(/\[(.*)-[A-Z0-9]{3}\]/g, "[$1]"); // remove currency and locale/date system/number system info (ECMA §18.8.31)
23071
+ convertedFormat = convertedFormat.replace(/\[\$\]/g, ""); // remove empty bocks
23072
+ // Quotes in format escape sequences of characters. ATM we only support [$...] blocks to escape characters, and only one of them per format
23073
+ const numberOfQuotes = ((_b = convertedFormat.match(/"/g)) === null || _b === void 0 ? void 0 : _b.length) || 0;
23074
+ const numberOfOpenBrackets = ((_c = convertedFormat.match(/\[/g)) === null || _c === void 0 ? void 0 : _c.length) || 0;
23075
+ if (numberOfQuotes / 2 + numberOfOpenBrackets > 1) {
23076
+ throw new Error("Multiple escaped blocks in format");
23077
+ }
23078
+ convertedFormat = convertedFormat.replace(/"(.*)"/g, "[$$$1]"); // replace '"..."' by '[$...]'
23079
+ convertedFormat = convertedFormat.replace(/_.{1}/g, ""); // _ == ignore width of next char for align purposes. Not supported ATM
23080
+ convertedFormat = convertedFormat.replace(/\*.{1}/g, ""); // * == repeat next character enough to fill the line. Not supported ATM
23081
+ convertedFormat = convertedFormat.replace(/\\ /g, " "); // unescape spaces
23082
+ convertedFormat = convertedFormat.replace(/\\./g, (match) => match[1]); // unescape other characters
23083
+ if (isXlsxDateFormat(convertedFormat)) {
23084
+ convertedFormat = convertDateFormat$1(convertedFormat);
23085
+ }
23086
+ if (isFormatSupported(convertedFormat)) {
23087
+ return convertedFormat;
23088
+ }
23089
+ }
23090
+ catch (e) { }
23091
+ }
23092
+ warningManager.generateNotSupportedWarning(WarningTypes.NumFmtIdNotSupported, format || `nmFmtId ${numFmtId}`);
23093
+ return undefined;
23094
+ }
23095
+ function isFormatSupported(format) {
23096
+ try {
23097
+ formatValue(0, format);
23098
+ return true;
23099
+ }
23100
+ catch (e) {
23101
+ return false;
23102
+ }
23103
+ }
23104
+ function isXlsxDateFormat(format) {
23105
+ return format.match(XLSX_DATE_FORMAT_REGEX) !== null;
23106
+ }
23107
+ function convertDateFormat$1(format) {
23108
+ // Some of these aren't defined neither in the OpenXML spec not the Xlsx extension of OpenXML,
23109
+ // but can still occur and are supported by Excel/Google sheets
23110
+ format = format.toLowerCase();
23111
+ format = format.replace(/mmmmm/g, "mmm");
23112
+ format = format.replace(/am\/pm|a\/m/g, "a");
23113
+ format = format.replace(/hhhh/g, "hh");
23114
+ format = format.replace(/\bh\b/g, "hh");
23115
+ return format;
23116
+ }
23117
+
23004
23118
  function convertBorders(data, warningManager) {
23005
23119
  const borderArray = data.borders.map((border) => {
23006
23120
  addBorderWarnings(border, warningManager);
@@ -23063,41 +23177,6 @@ function convertFormats(data, warningManager) {
23063
23177
  }
23064
23178
  return arrayToObject(formats, 1);
23065
23179
  }
23066
- /**
23067
- * Convert excel format to o_spreadsheet format
23068
- *
23069
- * Excel format are defined in openXML §18.8.31
23070
- */
23071
- function convertXlsxFormat(numFmtId, formats, warningManager) {
23072
- var _a, _b, _c;
23073
- if (numFmtId === 0) {
23074
- return undefined;
23075
- }
23076
- // Format is either defined in the imported data, or the formatId is defined in openXML §18.8.30
23077
- let format = XLSX_FORMATS_CONVERSION_MAP[numFmtId] || ((_a = formats.find((f) => f.id === numFmtId)) === null || _a === void 0 ? void 0 : _a.format);
23078
- if (format) {
23079
- try {
23080
- let convertedFormat = format.replace(/(.*?);.*/, "$1"); // only take first part of multi-part format
23081
- convertedFormat = convertedFormat.replace(/\[(.*)-[A-Z0-9]{3}\]/g, "[$1]"); // remove currency and locale/date system/number system info (ECMA §18.8.31)
23082
- convertedFormat = convertedFormat.replace(/\[\$\]/g, ""); // remove empty bocks
23083
- // Quotes in format escape sequences of characters. ATM we only support [$...] blocks to escape characters, and only one of them per format
23084
- const numberOfQuotes = ((_b = convertedFormat.match(/"/g)) === null || _b === void 0 ? void 0 : _b.length) || 0;
23085
- const numberOfOpenBrackets = ((_c = convertedFormat.match(/\[/g)) === null || _c === void 0 ? void 0 : _c.length) || 0;
23086
- if (numberOfQuotes / 2 + numberOfOpenBrackets > 1) {
23087
- throw new Error("Multiple escaped blocks in format");
23088
- }
23089
- convertedFormat = convertedFormat.replace(/"(.*)"/g, "[$$$1]"); // replace '"..."' by '[$...]'
23090
- convertedFormat = convertedFormat.replace(/_.{1}/g, ""); // _ == ignore with of next char for align purposes. Not supported ATM
23091
- convertedFormat = convertedFormat.replace(/\*.{1}/g, ""); // * == repeat next character enough to fill the line. Not supported ATM
23092
- convertedFormat = convertedFormat.replace(/\\ /g, " "); // unescape spaces
23093
- formatValue(0, convertedFormat);
23094
- return convertedFormat;
23095
- }
23096
- catch (e) { }
23097
- }
23098
- warningManager.generateNotSupportedWarning(WarningTypes.NumFmtIdNotSupported, format || `nmFmtId ${numFmtId}`);
23099
- return undefined;
23100
- }
23101
23180
  // ---------------------------------------------------------------------------
23102
23181
  // Warnings
23103
23182
  // ---------------------------------------------------------------------------
@@ -31396,9 +31475,7 @@ class CustomColorsPlugin extends UIPlugin {
31396
31475
  // remove duplicates first to check validity on a reduced
31397
31476
  // set of colors, then normalize to HEX and remove duplicates
31398
31477
  // again
31399
- [...new Set([...usedColors, ...this.customColors])]
31400
- .filter(isColorValid)
31401
- .map((c) => toHex(c).toLowerCase())),
31478
+ [...new Set([...usedColors, ...this.customColors])].filter(isColorValid).map(toHex)),
31402
31479
  ]).filter((color) => !COLOR_PICKER_DEFAULTS.includes(color));
31403
31480
  }
31404
31481
  getColorsFromCells(cells) {
@@ -31459,7 +31536,7 @@ class CustomColorsPlugin extends UIPlugin {
31459
31536
  return [...chartsColors];
31460
31537
  }
31461
31538
  tryToAddColor(color) {
31462
- const formattedColor = toHex(color).toLowerCase();
31539
+ const formattedColor = toHex(color);
31463
31540
  if (color && !COLOR_PICKER_DEFAULTS.includes(formattedColor)) {
31464
31541
  this.customColors.add(formattedColor);
31465
31542
  }
@@ -32474,8 +32551,8 @@ class InternalViewport {
32474
32551
  this.getters = getters;
32475
32552
  this.sheetId = sheetId;
32476
32553
  this.boundaries = boundaries;
32477
- this.width = sizeInGrid.width;
32478
- this.height = sizeInGrid.height;
32554
+ this.viewportWidth = sizeInGrid.width;
32555
+ this.viewportHeight = sizeInGrid.height;
32479
32556
  this.offsetScrollbarX = offsets.x;
32480
32557
  this.offsetScrollbarY = offsets.y;
32481
32558
  this.canScrollVertically = options.canScrollVertically;
@@ -32486,6 +32563,10 @@ class InternalViewport {
32486
32563
  this.adjustViewportOffsetY();
32487
32564
  }
32488
32565
  // PUBLIC
32566
+ /** Returns the maximum size (in Pixels) of the viewport relative to its allocated client size
32567
+ * When the viewport grid size is smaller than its client width (resp. height), it will return
32568
+ * the client width (resp. height).
32569
+ */
32489
32570
  getMaxSize() {
32490
32571
  const lastCol = this.getters.findLastVisibleColRowIndex(this.sheetId, "COL", {
32491
32572
  first: this.boundaries.left,
@@ -32497,20 +32578,24 @@ class InternalViewport {
32497
32578
  });
32498
32579
  const { end: lastColEnd, size: lastColSize } = this.getters.getColDimensions(this.sheetId, lastCol);
32499
32580
  const { end: lastRowEnd, size: lastRowSize } = this.getters.getRowDimensions(this.sheetId, lastRow);
32500
- const leftColIndex = this.searchHeaderIndex("COL", lastColEnd - this.width, 0);
32581
+ const leftColIndex = this.searchHeaderIndex("COL", lastColEnd - this.viewportWidth, 0);
32501
32582
  const leftColSize = this.getters.getColSize(this.sheetId, leftColIndex);
32502
- const leftRowIndex = this.searchHeaderIndex("ROW", lastRowEnd - this.height, 0);
32583
+ const leftRowIndex = this.searchHeaderIndex("ROW", lastRowEnd - this.viewportHeight, 0);
32503
32584
  const topRowSize = this.getters.getRowSize(this.sheetId, leftRowIndex);
32504
- const width = lastColEnd -
32505
- this.offsetCorrectionX +
32506
- (this.canScrollHorizontally
32507
- ? Math.max(DEFAULT_CELL_WIDTH, Math.min(leftColSize, this.width - lastColSize))
32508
- : 0);
32509
- const height = lastRowEnd -
32510
- this.offsetCorrectionY +
32511
- (this.canScrollVertically
32512
- ? Math.max(DEFAULT_CELL_HEIGHT + 5, Math.min(topRowSize, this.height - lastRowSize))
32513
- : 0);
32585
+ let width = lastColEnd - this.offsetCorrectionX;
32586
+ if (this.canScrollHorizontally) {
32587
+ width += Math.max(DEFAULT_CELL_WIDTH, // leave some minimal space to let the user know they scrolled all the way
32588
+ Math.min(leftColSize, this.viewportWidth - lastColSize) // Add pixels that allows the snapping at maximum horizontal scroll
32589
+ );
32590
+ width = Math.max(width, this.viewportWidth); // if the viewport grid size is smaller than its client width, return client width
32591
+ }
32592
+ let height = lastRowEnd - this.offsetCorrectionY;
32593
+ if (this.canScrollVertically) {
32594
+ height += Math.max(DEFAULT_CELL_HEIGHT + 5, // leave some space to let the user know they scrolled all the way
32595
+ Math.min(topRowSize, this.viewportHeight - lastRowSize) // Add pixels that allows the snapping at maximum vertical scroll
32596
+ );
32597
+ height = Math.max(height, this.viewportHeight); // if the viewport grid size is smaller than its client height, return client height
32598
+ }
32514
32599
  return { width, height };
32515
32600
  }
32516
32601
  /**
@@ -32519,7 +32604,7 @@ class InternalViewport {
32519
32604
  * It returns -1 if no column is found.
32520
32605
  */
32521
32606
  getColIndex(x, absolute = false) {
32522
- if (x < this.offsetCorrectionX || x > this.offsetCorrectionX + this.width) {
32607
+ if (x < this.offsetCorrectionX || x > this.offsetCorrectionX + this.viewportWidth) {
32523
32608
  return -1;
32524
32609
  }
32525
32610
  return this.searchHeaderIndex("COL", x - this.offsetCorrectionX, this.left, absolute);
@@ -32530,7 +32615,7 @@ class InternalViewport {
32530
32615
  * It returns -1 if no row is found.
32531
32616
  */
32532
32617
  getRowIndex(y, absolute = false) {
32533
- if (y < this.offsetCorrectionY || y > this.offsetCorrectionY + this.height) {
32618
+ if (y < this.offsetCorrectionY || y > this.offsetCorrectionY + this.viewportHeight) {
32534
32619
  return -1;
32535
32620
  }
32536
32621
  return this.searchHeaderIndex("ROW", y - this.offsetCorrectionY, this.top, absolute);
@@ -32557,7 +32642,7 @@ class InternalViewport {
32557
32642
  adjustPositionX(col) {
32558
32643
  const sheetId = this.sheetId;
32559
32644
  const { start, end } = this.getters.getColDimensions(sheetId, col);
32560
- while (end > this.offsetX + this.offsetCorrectionX + this.width &&
32645
+ while (end > this.offsetX + this.offsetCorrectionX + this.viewportWidth &&
32561
32646
  this.offsetX + this.offsetCorrectionX < start) {
32562
32647
  this.offsetX = this.getters.getColDimensions(sheetId, this.left).end - this.offsetCorrectionX;
32563
32648
  this.offsetScrollbarX = this.offsetX;
@@ -32579,7 +32664,7 @@ class InternalViewport {
32579
32664
  adjustPositionY(row) {
32580
32665
  const sheetId = this.sheetId;
32581
32666
  while (this.getters.getRowDimensions(sheetId, row).end >
32582
- this.offsetY + this.height + this.offsetCorrectionY &&
32667
+ this.offsetY + this.viewportHeight + this.offsetCorrectionY &&
32583
32668
  this.offsetY + this.offsetCorrectionY < this.getters.getRowDimensions(sheetId, row).start) {
32584
32669
  this.offsetY = this.getters.getRowDimensions(sheetId, this.top).end - this.offsetCorrectionY;
32585
32670
  this.offsetScrollbarY = this.offsetY;
@@ -32617,8 +32702,8 @@ class InternalViewport {
32617
32702
  const x = this.getters.getColRowOffset("COL", this.zone.left, targetZone.left) +
32618
32703
  this.offsetCorrectionX;
32619
32704
  const y = this.getters.getColRowOffset("ROW", this.zone.top, targetZone.top) + this.offsetCorrectionY;
32620
- const width = Math.min(this.getters.getColRowOffset("COL", targetZone.left, targetZone.right + 1), this.width);
32621
- const height = Math.min(this.getters.getColRowOffset("ROW", targetZone.top, targetZone.bottom + 1), this.height);
32705
+ const width = Math.min(this.getters.getColRowOffset("COL", targetZone.left, targetZone.right + 1), this.viewportWidth);
32706
+ const height = Math.min(this.getters.getColRowOffset("ROW", targetZone.top, targetZone.bottom + 1), this.viewportHeight);
32622
32707
  return {
32623
32708
  x,
32624
32709
  y,
@@ -32681,12 +32766,12 @@ class InternalViewport {
32681
32766
  adjustViewportOffsetX() {
32682
32767
  if (this.canScrollHorizontally) {
32683
32768
  const { width: viewportWidth } = this.getMaxSize();
32684
- if (this.width + this.offsetScrollbarX > viewportWidth) {
32685
- this.offsetScrollbarX = Math.max(0, viewportWidth - this.width);
32769
+ if (this.viewportWidth + this.offsetScrollbarX > viewportWidth) {
32770
+ this.offsetScrollbarX = Math.max(0, viewportWidth - this.viewportWidth);
32686
32771
  }
32687
32772
  }
32688
32773
  this.left = this.getColIndex(this.offsetScrollbarX, true);
32689
- this.right = this.getColIndex(this.offsetScrollbarX + this.width, true);
32774
+ this.right = this.getColIndex(this.offsetScrollbarX + this.viewportWidth, true);
32690
32775
  if (this.right === -1) {
32691
32776
  this.right = this.boundaries.right;
32692
32777
  }
@@ -32698,12 +32783,12 @@ class InternalViewport {
32698
32783
  adjustViewportOffsetY() {
32699
32784
  if (this.canScrollVertically) {
32700
32785
  const { height: paneHeight } = this.getMaxSize();
32701
- if (this.height + this.offsetScrollbarY > paneHeight) {
32702
- this.offsetScrollbarY = Math.max(0, paneHeight - this.height);
32786
+ if (this.viewportHeight + this.offsetScrollbarY > paneHeight) {
32787
+ this.offsetScrollbarY = Math.max(0, paneHeight - this.viewportHeight);
32703
32788
  }
32704
32789
  }
32705
32790
  this.top = this.getRowIndex(this.offsetScrollbarY, true);
32706
- this.bottom = this.getRowIndex(this.offsetScrollbarY + this.width, true);
32791
+ this.bottom = this.getRowIndex(this.offsetScrollbarY + this.viewportWidth, true);
32707
32792
  if (this.bottom === -1) {
32708
32793
  this.bottom = this.boundaries.bottom;
32709
32794
  }
@@ -32714,7 +32799,7 @@ class InternalViewport {
32714
32799
  adjustViewportZoneX() {
32715
32800
  const sheetId = this.sheetId;
32716
32801
  this.left = this.searchHeaderIndex("COL", this.offsetScrollbarX, this.boundaries.left);
32717
- this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.width, this.left));
32802
+ this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.viewportWidth, this.left));
32718
32803
  if (this.right === -1) {
32719
32804
  this.right = this.getters.getNumberCols(sheetId) - 1;
32720
32805
  }
@@ -32727,7 +32812,7 @@ class InternalViewport {
32727
32812
  adjustViewportZoneY() {
32728
32813
  const sheetId = this.sheetId;
32729
32814
  this.top = this.searchHeaderIndex("ROW", this.offsetScrollbarY, this.boundaries.top);
32730
- this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.height, this.top));
32815
+ this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.viewportHeight, this.top));
32731
32816
  if (this.bottom === -1) {
32732
32817
  this.bottom = this.getters.getNumberRows(sheetId) - 1;
32733
32818
  }
@@ -32990,8 +33075,7 @@ class SheetViewPlugin extends UIPlugin {
32990
33075
  return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => !this.getters.isHeaderHidden(sheetId, "ROW", row));
32991
33076
  }
32992
33077
  /**
32993
- * Return the main viewport maximum size. That is the zone dimension
32994
- * with some bottom and right padding.
33078
+ * Return the main viewport maximum size relative to the client size.
32995
33079
  */
32996
33080
  getMainViewportRect() {
32997
33081
  const sheetId = this.getters.getActiveSheetId();
@@ -33007,8 +33091,8 @@ class SheetViewPlugin extends UIPlugin {
33007
33091
  const { width, height } = this.getMainViewportRect();
33008
33092
  const viewport = this.getMainInternalViewport(sheetId);
33009
33093
  return {
33010
- maxOffsetX: Math.max(0, width - viewport.width + 1),
33011
- maxOffsetY: Math.max(0, height - viewport.height + 1),
33094
+ maxOffsetX: Math.max(0, width - viewport.viewportWidth + 1),
33095
+ maxOffsetY: Math.max(0, height - viewport.viewportHeight + 1),
33012
33096
  };
33013
33097
  }
33014
33098
  getColRowOffsetInViewport(dimension, referenceIndex, index) {
@@ -41121,9 +41205,6 @@ css /* scss */ `
41121
41205
  color: #333;
41122
41206
  }
41123
41207
 
41124
- * {
41125
- font-family: "Roboto", "RobotoDraft", Helvetica, Arial, sans-serif;
41126
- }
41127
41208
  &,
41128
41209
  *,
41129
41210
  *:before,
@@ -44961,6 +45042,6 @@ function addFunction(functionName, functionDescription) {
44961
45042
  export { AbstractChart, CommandResult, CorePlugin, DATETIME_FORMAT, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, links, load, parse, readonlyAllowedCommands, registries, setTranslationMethod, tokenize };
44962
45043
 
44963
45044
 
44964
- __info__.version = '16.2.1';
44965
- __info__.date = '2023-03-23T11:35:41.982Z';
44966
- __info__.hash = 'd1e5470';
45045
+ __info__.version = '16.2.2';
45046
+ __info__.date = '2023-04-13T08:29:22.236Z';
45047
+ __info__.hash = 'a38f31a';