@odoo/o-spreadsheet 16.2.1 → 16.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -116,88 +116,88 @@ const FILTERS_COLOR = "#188038";
116
116
  const BACKGROUND_HEADER_FILTER_COLOR = "#E6F4EA";
117
117
  const BACKGROUND_HEADER_SELECTED_FILTER_COLOR = "#CEEAD6";
118
118
  const SEPARATOR_COLOR = "#E0E2E4";
119
- // Color picker
119
+ // Color picker defaults as upper case HEX to match `toHex`helper
120
120
  const COLOR_PICKER_DEFAULTS = [
121
121
  "#000000",
122
122
  "#434343",
123
123
  "#666666",
124
124
  "#999999",
125
- "#b7b7b7",
126
- "#cccccc",
127
- "#d9d9d9",
128
- "#efefef",
129
- "#f3f3f3",
130
- "#ffffff",
125
+ "#B7B7B7",
126
+ "#CCCCCC",
127
+ "#D9D9D9",
128
+ "#EFEFEF",
129
+ "#F3F3F3",
130
+ "#FFFFFF",
131
131
  "#980000",
132
- "#ff0000",
133
- "#ff9900",
134
- "#ffff00",
135
- "#00ff00",
136
- "#00ffff",
137
- "#4a86e8",
138
- "#0000ff",
139
- "#9900ff",
140
- "#ff00ff",
141
- "#e6b8af",
142
- "#f4cccc",
143
- "#fce5cd",
144
- "#fff2cc",
145
- "#d9ead3",
146
- "#d0e0e3",
147
- "#c9daf8",
148
- "#cfe2f3",
149
- "#d9d2e9",
150
- "#ead1dc",
151
- "#dd7e6b",
152
- "#ea9999",
153
- "#f9cb9c",
154
- "#ffe599",
155
- "#b6d7a8",
156
- "#a2c4c9",
157
- "#a4c2f4",
158
- "#9fc5e8",
159
- "#b4a7d6",
160
- "#d5a6bd",
161
- "#cc4125",
162
- "#e06666",
163
- "#f6b26b",
164
- "#ffd966",
165
- "#93c47d",
166
- "#76a5af",
167
- "#6d9eeb",
168
- "#6fa8dc",
169
- "#8e7cc3",
170
- "#c27ba0",
171
- "#a61c00",
172
- "#cc0000",
173
- "#e69138",
174
- "#f1c232",
175
- "#6aa84f",
176
- "#45818e",
177
- "#3c78d8",
178
- "#3d85c6",
179
- "#674ea7",
180
- "#a64d79",
181
- "#85200c",
132
+ "#FF0000",
133
+ "#FF9900",
134
+ "#FFFF00",
135
+ "#00FF00",
136
+ "#00FFFF",
137
+ "#4A86E8",
138
+ "#0000FF",
139
+ "#9900FF",
140
+ "#FF00FF",
141
+ "#E6B8AF",
142
+ "#F4CCCC",
143
+ "#FCE5CD",
144
+ "#FFF2CC",
145
+ "#D9EAD3",
146
+ "#D0E0E3",
147
+ "#C9DAF8",
148
+ "#CFE2F3",
149
+ "#D9D2E9",
150
+ "#EAD1DC",
151
+ "#DD7E6B",
152
+ "#EA9999",
153
+ "#F9CB9C",
154
+ "#FFE599",
155
+ "#B6D7A8",
156
+ "#A2C4C9",
157
+ "#A4C2F4",
158
+ "#9FC5E8",
159
+ "#B4A7D6",
160
+ "#D5A6BD",
161
+ "#CC4125",
162
+ "#E06666",
163
+ "#F6B26B",
164
+ "#FFD966",
165
+ "#93C47D",
166
+ "#76A5AF",
167
+ "#6D9EEB",
168
+ "#6FA8DC",
169
+ "#8E7CC3",
170
+ "#C27BA0",
171
+ "#A61C00",
172
+ "#CC0000",
173
+ "#E69138",
174
+ "#F1C232",
175
+ "#6AA84F",
176
+ "#45818E",
177
+ "#3C78D8",
178
+ "#3D85C6",
179
+ "#674EA7",
180
+ "#A64D79",
181
+ "#85200C",
182
182
  "#990000",
183
- "#b45f06",
184
- "#bf9000",
185
- "#38761d",
186
- "#134f5c",
187
- "#1155cc",
188
- "#0b5394",
189
- "#351c75",
190
- "#741b47",
191
- "#5b0f00",
183
+ "#B45F06",
184
+ "#BF9000",
185
+ "#38761D",
186
+ "#134F5C",
187
+ "#1155CC",
188
+ "#0B5394",
189
+ "#351C75",
190
+ "#741B47",
191
+ "#5B0F00",
192
192
  "#660000",
193
- "#783f04",
194
- "#7f6000",
195
- "#274e13",
196
- "#0c343d",
197
- "#1c4587",
193
+ "#783F04",
194
+ "#7F6000",
195
+ "#274E13",
196
+ "#0C343D",
197
+ "#1C4587",
198
198
  "#073763",
199
- "#20124d",
200
- "#4c1130",
199
+ "#20124D",
200
+ "#4C1130",
201
201
  ];
202
202
  // Dimensions
203
203
  const MIN_ROW_HEIGHT = 10;
@@ -237,7 +237,7 @@ const DEFAULT_FONT = "'Roboto', arial";
237
237
  const DEFAULT_BORDER_DESC = ["thin", "#000"];
238
238
  const DEFAULT_FILTER_BORDER_DESC = ["thin", FILTERS_COLOR];
239
239
  // DateTimeRegex
240
- const DATETIME_FORMAT = /[ymd:]/;
240
+ const DATETIME_FORMAT = /[ymdhs:]/;
241
241
  // Ranges
242
242
  const INCORRECT_RANGE_STRING = CellErrorType.InvalidReference;
243
243
  // Max Number of history steps kept in memory
@@ -274,11 +274,12 @@ var ComponentsImportance;
274
274
  ComponentsImportance[ComponentsImportance["Highlight"] = 5] = "Highlight";
275
275
  ComponentsImportance[ComponentsImportance["Figure"] = 10] = "Figure";
276
276
  ComponentsImportance[ComponentsImportance["ScrollBar"] = 15] = "ScrollBar";
277
- ComponentsImportance[ComponentsImportance["Dropdown"] = 16] = "Dropdown";
277
+ ComponentsImportance[ComponentsImportance["GridPopover"] = 19] = "GridPopover";
278
278
  ComponentsImportance[ComponentsImportance["GridComposer"] = 20] = "GridComposer";
279
- ComponentsImportance[ComponentsImportance["TopBarComposer"] = 21] = "TopBarComposer";
279
+ ComponentsImportance[ComponentsImportance["Dropdown"] = 21] = "Dropdown";
280
280
  ComponentsImportance[ComponentsImportance["IconPicker"] = 25] = "IconPicker";
281
- ComponentsImportance[ComponentsImportance["Popover"] = 30] = "Popover";
281
+ ComponentsImportance[ComponentsImportance["TopBarComposer"] = 30] = "TopBarComposer";
282
+ ComponentsImportance[ComponentsImportance["Popover"] = 35] = "Popover";
282
283
  ComponentsImportance[ComponentsImportance["ChartAnchor"] = 1000] = "ChartAnchor";
283
284
  })(ComponentsImportance || (ComponentsImportance = {}));
284
285
  const DEFAULT_SHEETVIEW_SIZE = 1000;
@@ -705,8 +706,9 @@ function getDefaultCellHeight(cell) {
705
706
  return DEFAULT_CELL_HEIGHT;
706
707
  }
707
708
  const fontSize = computeTextFontSizeInPixels(cell.style);
708
- const multiLineText = cell.content.split(NEWLINE);
709
- return computeTextLinesHeight(fontSize, multiLineText.length) + 2 * PADDING_AUTORESIZE_VERTICAL;
709
+ // the number of lines should be computed from the formula result, but it's not evaluated at this point
710
+ const numberOfLines = cell.isFormula ? 1 : cell.content.split(NEWLINE).length;
711
+ return computeTextLinesHeight(fontSize, numberOfLines) + 2 * PADDING_AUTORESIZE_VERTICAL;
710
712
  }
711
713
  function computeTextWidth(context, text, style) {
712
714
  context.save();
@@ -1058,6 +1060,8 @@ function replaceSpecialSpaces(text) {
1058
1060
  return text;
1059
1061
  }
1060
1062
 
1063
+ const RBA_REGEX = /rgba?\(|\s+|\)/gi;
1064
+ const HEX_MATCH = /^#([A-F\d]{2}){3,4}$/g;
1061
1065
  const colors$1 = [
1062
1066
  "#eb6d00",
1063
1067
  "#0074d9",
@@ -1083,7 +1087,10 @@ function colorNumberString(color) {
1083
1087
  }
1084
1088
  /**
1085
1089
  * Converts any CSS color value to a standardized hex6 value.
1086
- * Accepts: hex3, hex6, hex8 and rgb (rgba is not supported)
1090
+ * Accepts: hex3, hex6, hex8, rgb[1] and rgba[1].
1091
+ *
1092
+ * [1] under the form rgb(r, g, b, a?) or rgba(r, g, b, a?)
1093
+ * with r,g,b ∈ [0, 255] and a ∈ [0, 1]
1087
1094
  *
1088
1095
  * toHex("#ABC")
1089
1096
  * >> "#AABBCC"
@@ -1094,27 +1101,31 @@ function colorNumberString(color) {
1094
1101
  * toHex("rgb(30, 80, 16)")
1095
1102
  * >> "#1E5010"
1096
1103
  *
1104
+ * * toHex("rgb(30, 80, 16, 0.5)")
1105
+ * >> "#1E501080"
1106
+ *
1097
1107
  */
1098
1108
  function toHex(color) {
1099
- if (color.includes("rgba")) {
1100
- throw new Error(`rgba() conversion currently not supported: ${color}`);
1109
+ let hexColor = color;
1110
+ if (color.startsWith("rgb")) {
1111
+ hexColor = rgbaStringToHex(color);
1101
1112
  }
1102
- if (color.includes("rgb")) {
1103
- return rgbToHex6(color);
1104
- }
1105
- color = color.replace("#", "").toUpperCase();
1106
- if (color.length === 3 || color.length === 4) {
1107
- color = color.split("").reduce((acc, h) => acc + h + h, "");
1113
+ else {
1114
+ hexColor = color.replace("#", "").toUpperCase();
1115
+ if (hexColor.length === 3 || hexColor.length === 4) {
1116
+ hexColor = hexColor.split("").reduce((acc, h) => acc + h + h, "");
1117
+ }
1118
+ hexColor = `#${hexColor}`;
1108
1119
  }
1109
- if (color.replace(/[a-f0-9]/gi, "") !== "") {
1110
- throw new Error("invalid color");
1120
+ if (!hexColor.match(HEX_MATCH)) {
1121
+ throw new Error(`invalid color input: ${color}`);
1111
1122
  }
1112
- return "#" + color;
1123
+ return hexColor;
1113
1124
  }
1114
1125
  function isColorValid(color) {
1115
1126
  try {
1116
- const { r, g, b, a } = colorToRGBA(color);
1117
- return (isColorValueValid(r) && isColorValueValid(g) && isColorValueValid(b) && isColorValueValid(a));
1127
+ toHex(color);
1128
+ return true;
1118
1129
  }
1119
1130
  catch (error) {
1120
1131
  return false;
@@ -1147,15 +1158,29 @@ function relativeLuminance(color) {
1147
1158
  /**
1148
1159
  * Convert a CSS rgb color string to a standardized hex6 color value.
1149
1160
  *
1150
- * rgbToHex6("rgb(30, 80, 16)")
1161
+ * rgbaStringToHex("rgb(30, 80, 16)")
1151
1162
  * >> "#1E5010"
1163
+ *
1164
+ * rgbaStringToHex("rgba(30, 80, 16, 0.5)")
1165
+ * >> "#1E501080"
1166
+ *
1167
+ * DOES NOT SUPPORT NON INTEGER RGB VALUES
1152
1168
  */
1153
- function rgbToHex6(color) {
1154
- return ("#" +
1155
- concat(color
1156
- .slice(4, -1)
1157
- .split(",")
1158
- .map((valueString) => parseInt(valueString, 10).toString(16).padStart(2, "0"))).toUpperCase());
1169
+ function rgbaStringToHex(color) {
1170
+ const stringVals = color.replace(RBA_REGEX, "").split(",");
1171
+ let alphaHex = 255;
1172
+ if (stringVals.length !== 3 && stringVals.length !== 4) {
1173
+ throw new Error("invalid color");
1174
+ }
1175
+ else if (stringVals.length === 4) {
1176
+ const alpha = parseFloat(stringVals.pop() || "1");
1177
+ alphaHex = Math.round((alpha || 1) * 255);
1178
+ }
1179
+ const vals = stringVals.map((val) => parseInt(val, 10));
1180
+ if (alphaHex !== 255) {
1181
+ vals.push(alphaHex);
1182
+ }
1183
+ return "#" + concat(vals.map((value) => value.toString(16).padStart(2, "0"))).toUpperCase();
1159
1184
  }
1160
1185
  /**
1161
1186
  * RGBA to HEX representation (#RRGGBBAA).
@@ -1177,7 +1202,7 @@ function rgbaToHex(rgba) {
1177
1202
  a = "0" + a;
1178
1203
  if (a === "ff")
1179
1204
  a = "";
1180
- return "#" + r + g + b + a;
1205
+ return ("#" + r + g + b + a).toUpperCase();
1181
1206
  }
1182
1207
  /**
1183
1208
  * Color string to RGBA representation
@@ -1298,6 +1323,9 @@ function rgbaToHSLA(rgba) {
1298
1323
  s = +(s * 100).toFixed(1);
1299
1324
  l = +(l * 100).toFixed(1);
1300
1325
  return { a: rgba.a, h, s, l };
1326
+ }
1327
+ function isSameColor(color1, color2) {
1328
+ return isColorValid(color1) && isColorValid(color2) && toHex(color1) === toHex(color2);
1301
1329
  }
1302
1330
 
1303
1331
  /** Reference of a cell (eg. A1, $B$5) */
@@ -1449,7 +1477,7 @@ function scrollDelay(value) {
1449
1477
  * formula, commas are used to separate arguments
1450
1478
  * - it does not support % symbol, in formulas % is an operator
1451
1479
  */
1452
- const formulaNumberRegexp = /^-?\d+(\.?\d*(e\d+)?)?|^-?\.\d+/;
1480
+ const formulaNumberRegexp = /(^-?\d+(\.?\d*(e\d+)?)?|^-?\.\d+)(?!\w|!)/;
1453
1481
  const pIntegerAndDecimals = "(\\d+(,\\d{3,})*(\\.\\d*)?)"; // pattern that match integer number with or without decimal digits
1454
1482
  const pOnlyDecimals = "(\\.\\d+)"; // pattern that match only expression with decimal digits
1455
1483
  const pScientificFormat = "(e(\\+|-)?\\d+)?"; // pattern that match scientific format between zero and one time (should be placed before pPercentFormat)
@@ -3055,6 +3083,7 @@ const CHART_PADDING_RATIO = 0.02;
3055
3083
  const LINE_HEIGHT = 1.2;
3056
3084
  css /* scss */ `
3057
3085
  div.o-scorecard {
3086
+ font-family: ${DEFAULT_FONT};
3058
3087
  user-select: none;
3059
3088
  background-color: white;
3060
3089
  display: flex;
@@ -5105,6 +5134,11 @@ class Popover extends owl.Component {
5105
5134
  this.currentPosition = newPosition;
5106
5135
  });
5107
5136
  }
5137
+ get popoverStyle() {
5138
+ return cssPropertiesToCss({
5139
+ "z-index": `${this.props.zIndex}`,
5140
+ });
5141
+ }
5108
5142
  }
5109
5143
  Popover.template = "o-spreadsheet-Popover";
5110
5144
  Popover.defaultProps = {
@@ -5113,6 +5147,7 @@ Popover.defaultProps = {
5113
5147
  onMouseWheel: () => { },
5114
5148
  onPopoverMoved: () => { },
5115
5149
  onPopoverHidden: () => { },
5150
+ zIndex: ComponentsImportance.Popover,
5116
5151
  };
5117
5152
  Popover.props = {
5118
5153
  anchorRect: Object,
@@ -5124,6 +5159,7 @@ Popover.props = {
5124
5159
  onMouseWheel: { type: Function, optional: true },
5125
5160
  onPopoverHidden: { type: Function, optional: true },
5126
5161
  onPopoverMoved: { type: Function, optional: true },
5162
+ zIndex: { type: Number, optional: true },
5127
5163
  slots: Object,
5128
5164
  };
5129
5165
  class PopoverPositionContext {
@@ -17014,6 +17050,9 @@ class ColorPicker extends owl.Component {
17014
17050
  top,
17015
17051
  });
17016
17052
  }
17053
+ isSameColor(color1, color2) {
17054
+ return isSameColor(color1, color2);
17055
+ }
17017
17056
  }
17018
17057
  ColorPicker.template = "o-spreadsheet-ColorPicker";
17019
17058
  ColorPicker.defaultProps = {
@@ -19255,6 +19294,8 @@ class ContentEditableHelper {
19255
19294
  start = 0;
19256
19295
  if (end > textLength)
19257
19296
  end = textLength;
19297
+ if (start > textLength)
19298
+ start = textLength;
19258
19299
  }
19259
19300
  let startNode = this.findChildAtCharacterIndex(start);
19260
19301
  let endNode = this.findChildAtCharacterIndex(end);
@@ -19524,6 +19565,7 @@ css /* scss */ `
19524
19565
  padding-right: 2px;
19525
19566
 
19526
19567
  box-sizing: border-box;
19568
+ font-family: ${DEFAULT_FONT};
19527
19569
 
19528
19570
  caret-color: black;
19529
19571
  padding-left: 3px;
@@ -20793,6 +20835,10 @@ GridOverlay.props = {
20793
20835
  };
20794
20836
 
20795
20837
  class GridPopover extends owl.Component {
20838
+ constructor() {
20839
+ super(...arguments);
20840
+ this.zIndex = ComponentsImportance.GridPopover;
20841
+ }
20796
20842
  get cellPopover() {
20797
20843
  const popover = this.env.model.getters.getCellPopover(this.props.hoveredCell);
20798
20844
  if (!popover.isOpen) {
@@ -22157,6 +22203,10 @@ class Grid extends owl.Component {
22157
22203
  }
22158
22204
  }
22159
22205
  onInput(ev) {
22206
+ // the user meant to paste in the sheet, not open the composer with the pasted content
22207
+ if (!ev.isComposing && ev.inputType === "insertFromPaste") {
22208
+ return;
22209
+ }
22160
22210
  if (ev.data) {
22161
22211
  // if the user types a character on the grid, it means he wants to start composing the selected cell with that
22162
22212
  // character
@@ -23005,6 +23055,70 @@ function fixXlsxUnicode(str) {
23005
23055
  });
23006
23056
  }
23007
23057
 
23058
+ 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;
23059
+ /**
23060
+ * Convert excel format to o_spreadsheet format
23061
+ *
23062
+ * Excel format are defined in openXML §18.8.31
23063
+ */
23064
+ function convertXlsxFormat(numFmtId, formats, warningManager) {
23065
+ var _a, _b, _c;
23066
+ if (numFmtId === 0) {
23067
+ return undefined;
23068
+ }
23069
+ // Format is either defined in the imported data, or the formatId is defined in openXML §18.8.30
23070
+ let format = XLSX_FORMATS_CONVERSION_MAP[numFmtId] || ((_a = formats.find((f) => f.id === numFmtId)) === null || _a === void 0 ? void 0 : _a.format);
23071
+ if (format) {
23072
+ try {
23073
+ let convertedFormat = format.replace(/(.*?);.*/, "$1"); // only take first part of multi-part format
23074
+ convertedFormat = convertedFormat.replace(/\[(.*)-[A-Z0-9]{3}\]/g, "[$1]"); // remove currency and locale/date system/number system info (ECMA §18.8.31)
23075
+ convertedFormat = convertedFormat.replace(/\[\$\]/g, ""); // remove empty bocks
23076
+ // Quotes in format escape sequences of characters. ATM we only support [$...] blocks to escape characters, and only one of them per format
23077
+ const numberOfQuotes = ((_b = convertedFormat.match(/"/g)) === null || _b === void 0 ? void 0 : _b.length) || 0;
23078
+ const numberOfOpenBrackets = ((_c = convertedFormat.match(/\[/g)) === null || _c === void 0 ? void 0 : _c.length) || 0;
23079
+ if (numberOfQuotes / 2 + numberOfOpenBrackets > 1) {
23080
+ throw new Error("Multiple escaped blocks in format");
23081
+ }
23082
+ convertedFormat = convertedFormat.replace(/"(.*)"/g, "[$$$1]"); // replace '"..."' by '[$...]'
23083
+ convertedFormat = convertedFormat.replace(/_.{1}/g, ""); // _ == ignore width of next char for align purposes. Not supported ATM
23084
+ convertedFormat = convertedFormat.replace(/\*.{1}/g, ""); // * == repeat next character enough to fill the line. Not supported ATM
23085
+ convertedFormat = convertedFormat.replace(/\\ /g, " "); // unescape spaces
23086
+ convertedFormat = convertedFormat.replace(/\\./g, (match) => match[1]); // unescape other characters
23087
+ if (isXlsxDateFormat(convertedFormat)) {
23088
+ convertedFormat = convertDateFormat$1(convertedFormat);
23089
+ }
23090
+ if (isFormatSupported(convertedFormat)) {
23091
+ return convertedFormat;
23092
+ }
23093
+ }
23094
+ catch (e) { }
23095
+ }
23096
+ warningManager.generateNotSupportedWarning(WarningTypes.NumFmtIdNotSupported, format || `nmFmtId ${numFmtId}`);
23097
+ return undefined;
23098
+ }
23099
+ function isFormatSupported(format) {
23100
+ try {
23101
+ formatValue(0, format);
23102
+ return true;
23103
+ }
23104
+ catch (e) {
23105
+ return false;
23106
+ }
23107
+ }
23108
+ function isXlsxDateFormat(format) {
23109
+ return format.match(XLSX_DATE_FORMAT_REGEX) !== null;
23110
+ }
23111
+ function convertDateFormat$1(format) {
23112
+ // Some of these aren't defined neither in the OpenXML spec not the Xlsx extension of OpenXML,
23113
+ // but can still occur and are supported by Excel/Google sheets
23114
+ format = format.toLowerCase();
23115
+ format = format.replace(/mmmmm/g, "mmm");
23116
+ format = format.replace(/am\/pm|a\/m/g, "a");
23117
+ format = format.replace(/hhhh/g, "hh");
23118
+ format = format.replace(/\bh\b/g, "hh");
23119
+ return format;
23120
+ }
23121
+
23008
23122
  function convertBorders(data, warningManager) {
23009
23123
  const borderArray = data.borders.map((border) => {
23010
23124
  addBorderWarnings(border, warningManager);
@@ -23067,41 +23181,6 @@ function convertFormats(data, warningManager) {
23067
23181
  }
23068
23182
  return arrayToObject(formats, 1);
23069
23183
  }
23070
- /**
23071
- * Convert excel format to o_spreadsheet format
23072
- *
23073
- * Excel format are defined in openXML §18.8.31
23074
- */
23075
- function convertXlsxFormat(numFmtId, formats, warningManager) {
23076
- var _a, _b, _c;
23077
- if (numFmtId === 0) {
23078
- return undefined;
23079
- }
23080
- // Format is either defined in the imported data, or the formatId is defined in openXML §18.8.30
23081
- let format = XLSX_FORMATS_CONVERSION_MAP[numFmtId] || ((_a = formats.find((f) => f.id === numFmtId)) === null || _a === void 0 ? void 0 : _a.format);
23082
- if (format) {
23083
- try {
23084
- let convertedFormat = format.replace(/(.*?);.*/, "$1"); // only take first part of multi-part format
23085
- convertedFormat = convertedFormat.replace(/\[(.*)-[A-Z0-9]{3}\]/g, "[$1]"); // remove currency and locale/date system/number system info (ECMA §18.8.31)
23086
- convertedFormat = convertedFormat.replace(/\[\$\]/g, ""); // remove empty bocks
23087
- // Quotes in format escape sequences of characters. ATM we only support [$...] blocks to escape characters, and only one of them per format
23088
- const numberOfQuotes = ((_b = convertedFormat.match(/"/g)) === null || _b === void 0 ? void 0 : _b.length) || 0;
23089
- const numberOfOpenBrackets = ((_c = convertedFormat.match(/\[/g)) === null || _c === void 0 ? void 0 : _c.length) || 0;
23090
- if (numberOfQuotes / 2 + numberOfOpenBrackets > 1) {
23091
- throw new Error("Multiple escaped blocks in format");
23092
- }
23093
- convertedFormat = convertedFormat.replace(/"(.*)"/g, "[$$$1]"); // replace '"..."' by '[$...]'
23094
- convertedFormat = convertedFormat.replace(/_.{1}/g, ""); // _ == ignore with of next char for align purposes. Not supported ATM
23095
- convertedFormat = convertedFormat.replace(/\*.{1}/g, ""); // * == repeat next character enough to fill the line. Not supported ATM
23096
- convertedFormat = convertedFormat.replace(/\\ /g, " "); // unescape spaces
23097
- formatValue(0, convertedFormat);
23098
- return convertedFormat;
23099
- }
23100
- catch (e) { }
23101
- }
23102
- warningManager.generateNotSupportedWarning(WarningTypes.NumFmtIdNotSupported, format || `nmFmtId ${numFmtId}`);
23103
- return undefined;
23104
- }
23105
23184
  // ---------------------------------------------------------------------------
23106
23185
  // Warnings
23107
23186
  // ---------------------------------------------------------------------------
@@ -31400,9 +31479,7 @@ class CustomColorsPlugin extends UIPlugin {
31400
31479
  // remove duplicates first to check validity on a reduced
31401
31480
  // set of colors, then normalize to HEX and remove duplicates
31402
31481
  // again
31403
- [...new Set([...usedColors, ...this.customColors])]
31404
- .filter(isColorValid)
31405
- .map((c) => toHex(c).toLowerCase())),
31482
+ [...new Set([...usedColors, ...this.customColors])].filter(isColorValid).map(toHex)),
31406
31483
  ]).filter((color) => !COLOR_PICKER_DEFAULTS.includes(color));
31407
31484
  }
31408
31485
  getColorsFromCells(cells) {
@@ -31463,7 +31540,7 @@ class CustomColorsPlugin extends UIPlugin {
31463
31540
  return [...chartsColors];
31464
31541
  }
31465
31542
  tryToAddColor(color) {
31466
- const formattedColor = toHex(color).toLowerCase();
31543
+ const formattedColor = toHex(color);
31467
31544
  if (color && !COLOR_PICKER_DEFAULTS.includes(formattedColor)) {
31468
31545
  this.customColors.add(formattedColor);
31469
31546
  }
@@ -32478,8 +32555,8 @@ class InternalViewport {
32478
32555
  this.getters = getters;
32479
32556
  this.sheetId = sheetId;
32480
32557
  this.boundaries = boundaries;
32481
- this.width = sizeInGrid.width;
32482
- this.height = sizeInGrid.height;
32558
+ this.viewportWidth = sizeInGrid.width;
32559
+ this.viewportHeight = sizeInGrid.height;
32483
32560
  this.offsetScrollbarX = offsets.x;
32484
32561
  this.offsetScrollbarY = offsets.y;
32485
32562
  this.canScrollVertically = options.canScrollVertically;
@@ -32490,6 +32567,10 @@ class InternalViewport {
32490
32567
  this.adjustViewportOffsetY();
32491
32568
  }
32492
32569
  // PUBLIC
32570
+ /** Returns the maximum size (in Pixels) of the viewport relative to its allocated client size
32571
+ * When the viewport grid size is smaller than its client width (resp. height), it will return
32572
+ * the client width (resp. height).
32573
+ */
32493
32574
  getMaxSize() {
32494
32575
  const lastCol = this.getters.findLastVisibleColRowIndex(this.sheetId, "COL", {
32495
32576
  first: this.boundaries.left,
@@ -32501,20 +32582,24 @@ class InternalViewport {
32501
32582
  });
32502
32583
  const { end: lastColEnd, size: lastColSize } = this.getters.getColDimensions(this.sheetId, lastCol);
32503
32584
  const { end: lastRowEnd, size: lastRowSize } = this.getters.getRowDimensions(this.sheetId, lastRow);
32504
- const leftColIndex = this.searchHeaderIndex("COL", lastColEnd - this.width, 0);
32585
+ const leftColIndex = this.searchHeaderIndex("COL", lastColEnd - this.viewportWidth, 0);
32505
32586
  const leftColSize = this.getters.getColSize(this.sheetId, leftColIndex);
32506
- const leftRowIndex = this.searchHeaderIndex("ROW", lastRowEnd - this.height, 0);
32587
+ const leftRowIndex = this.searchHeaderIndex("ROW", lastRowEnd - this.viewportHeight, 0);
32507
32588
  const topRowSize = this.getters.getRowSize(this.sheetId, leftRowIndex);
32508
- const width = lastColEnd -
32509
- this.offsetCorrectionX +
32510
- (this.canScrollHorizontally
32511
- ? Math.max(DEFAULT_CELL_WIDTH, Math.min(leftColSize, this.width - lastColSize))
32512
- : 0);
32513
- const height = lastRowEnd -
32514
- this.offsetCorrectionY +
32515
- (this.canScrollVertically
32516
- ? Math.max(DEFAULT_CELL_HEIGHT + 5, Math.min(topRowSize, this.height - lastRowSize))
32517
- : 0);
32589
+ let width = lastColEnd - this.offsetCorrectionX;
32590
+ if (this.canScrollHorizontally) {
32591
+ width += Math.max(DEFAULT_CELL_WIDTH, // leave some minimal space to let the user know they scrolled all the way
32592
+ Math.min(leftColSize, this.viewportWidth - lastColSize) // Add pixels that allows the snapping at maximum horizontal scroll
32593
+ );
32594
+ width = Math.max(width, this.viewportWidth); // if the viewport grid size is smaller than its client width, return client width
32595
+ }
32596
+ let height = lastRowEnd - this.offsetCorrectionY;
32597
+ if (this.canScrollVertically) {
32598
+ height += Math.max(DEFAULT_CELL_HEIGHT + 5, // leave some space to let the user know they scrolled all the way
32599
+ Math.min(topRowSize, this.viewportHeight - lastRowSize) // Add pixels that allows the snapping at maximum vertical scroll
32600
+ );
32601
+ height = Math.max(height, this.viewportHeight); // if the viewport grid size is smaller than its client height, return client height
32602
+ }
32518
32603
  return { width, height };
32519
32604
  }
32520
32605
  /**
@@ -32523,7 +32608,7 @@ class InternalViewport {
32523
32608
  * It returns -1 if no column is found.
32524
32609
  */
32525
32610
  getColIndex(x, absolute = false) {
32526
- if (x < this.offsetCorrectionX || x > this.offsetCorrectionX + this.width) {
32611
+ if (x < this.offsetCorrectionX || x > this.offsetCorrectionX + this.viewportWidth) {
32527
32612
  return -1;
32528
32613
  }
32529
32614
  return this.searchHeaderIndex("COL", x - this.offsetCorrectionX, this.left, absolute);
@@ -32534,7 +32619,7 @@ class InternalViewport {
32534
32619
  * It returns -1 if no row is found.
32535
32620
  */
32536
32621
  getRowIndex(y, absolute = false) {
32537
- if (y < this.offsetCorrectionY || y > this.offsetCorrectionY + this.height) {
32622
+ if (y < this.offsetCorrectionY || y > this.offsetCorrectionY + this.viewportHeight) {
32538
32623
  return -1;
32539
32624
  }
32540
32625
  return this.searchHeaderIndex("ROW", y - this.offsetCorrectionY, this.top, absolute);
@@ -32558,48 +32643,66 @@ class InternalViewport {
32558
32643
  this.adjustPositionY(row);
32559
32644
  }
32560
32645
  }
32561
- adjustPositionX(col) {
32646
+ adjustPositionX(targetCol) {
32562
32647
  const sheetId = this.sheetId;
32563
- const { start, end } = this.getters.getColDimensions(sheetId, col);
32564
- while (end > this.offsetX + this.offsetCorrectionX + this.width &&
32565
- this.offsetX + this.offsetCorrectionX < start) {
32566
- this.offsetX = this.getters.getColDimensions(sheetId, this.left).end - this.offsetCorrectionX;
32567
- this.offsetScrollbarX = this.offsetX;
32568
- this.adjustViewportZoneX();
32569
- }
32570
- while (col < this.left) {
32571
- let leftCol;
32572
- for (leftCol = this.left; leftCol >= 0; leftCol--) {
32573
- if (!this.getters.isColHidden(sheetId, leftCol)) {
32648
+ const { end } = this.getters.getColDimensions(sheetId, targetCol);
32649
+ const maxCol = this.getters.getNumberCols(sheetId);
32650
+ if (this.offsetX + this.offsetCorrectionX + this.viewportWidth < end) {
32651
+ for (let col = this.left; this.offsetX + this.offsetCorrectionX + this.viewportWidth < end; col++) {
32652
+ if (col > maxCol) {
32653
+ break;
32654
+ }
32655
+ if (this.getters.isColHidden(sheetId, col)) {
32656
+ continue;
32657
+ }
32658
+ this.offsetX = this.getters.getColDimensions(sheetId, col).end - this.offsetCorrectionX;
32659
+ this.offsetScrollbarX = this.offsetX;
32660
+ this.adjustViewportZoneX();
32661
+ }
32662
+ }
32663
+ else if (this.left > targetCol) {
32664
+ for (let col = this.left; col >= targetCol; col--) {
32665
+ if (col < 0) {
32574
32666
  break;
32575
32667
  }
32668
+ if (this.getters.isColHidden(sheetId, col)) {
32669
+ continue;
32670
+ }
32671
+ this.offsetX = this.getters.getColDimensions(sheetId, col).start - this.offsetCorrectionX;
32672
+ this.offsetScrollbarX = this.offsetX;
32673
+ this.adjustViewportZoneX();
32576
32674
  }
32577
- this.offsetX =
32578
- this.getters.getColDimensions(sheetId, leftCol - 1).start - this.offsetCorrectionX;
32579
- this.offsetScrollbarX = this.offsetX;
32580
- this.adjustViewportZoneX();
32581
32675
  }
32582
32676
  }
32583
- adjustPositionY(row) {
32677
+ adjustPositionY(targetRow) {
32584
32678
  const sheetId = this.sheetId;
32585
- while (this.getters.getRowDimensions(sheetId, row).end >
32586
- this.offsetY + this.height + this.offsetCorrectionY &&
32587
- this.offsetY + this.offsetCorrectionY < this.getters.getRowDimensions(sheetId, row).start) {
32588
- this.offsetY = this.getters.getRowDimensions(sheetId, this.top).end - this.offsetCorrectionY;
32589
- this.offsetScrollbarY = this.offsetY;
32590
- this.adjustViewportZoneY();
32591
- }
32592
- while (row < this.top) {
32593
- let topRow;
32594
- for (topRow = this.top; topRow >= 0; topRow--) {
32595
- if (!this.getters.isRowHidden(sheetId, topRow)) {
32679
+ const { end } = this.getters.getRowDimensions(sheetId, targetRow);
32680
+ const maxRow = this.getters.getNumberRows(sheetId);
32681
+ if (this.offsetY + this.viewportHeight + this.offsetCorrectionY < end) {
32682
+ for (let row = this.top; this.offsetY + this.viewportHeight + this.offsetCorrectionY < end; row++) {
32683
+ if (row > maxRow) {
32596
32684
  break;
32597
32685
  }
32686
+ if (this.getters.isRowHidden(sheetId, row)) {
32687
+ continue;
32688
+ }
32689
+ this.offsetY = this.getters.getRowDimensions(sheetId, row).end - this.offsetCorrectionY;
32690
+ this.offsetScrollbarY = this.offsetY;
32691
+ this.adjustViewportZoneY();
32692
+ }
32693
+ }
32694
+ else if (this.top > targetRow) {
32695
+ for (let row = this.top; row >= targetRow; row--) {
32696
+ if (row < 0) {
32697
+ break;
32698
+ }
32699
+ if (this.getters.isRowHidden(sheetId, row)) {
32700
+ continue;
32701
+ }
32702
+ this.offsetY = this.getters.getRowDimensions(sheetId, row).start - this.offsetCorrectionY;
32703
+ this.offsetScrollbarY = this.offsetY;
32704
+ this.adjustViewportZoneY();
32598
32705
  }
32599
- this.offsetY =
32600
- this.getters.getRowDimensions(sheetId, topRow - 1).start - this.offsetCorrectionY;
32601
- this.offsetScrollbarY = this.offsetY;
32602
- this.adjustViewportZoneY();
32603
32706
  }
32604
32707
  }
32605
32708
  setViewportOffset(offsetX, offsetY) {
@@ -32621,8 +32724,8 @@ class InternalViewport {
32621
32724
  const x = this.getters.getColRowOffset("COL", this.zone.left, targetZone.left) +
32622
32725
  this.offsetCorrectionX;
32623
32726
  const y = this.getters.getColRowOffset("ROW", this.zone.top, targetZone.top) + this.offsetCorrectionY;
32624
- const width = Math.min(this.getters.getColRowOffset("COL", targetZone.left, targetZone.right + 1), this.width);
32625
- const height = Math.min(this.getters.getColRowOffset("ROW", targetZone.top, targetZone.bottom + 1), this.height);
32727
+ const width = Math.min(this.getters.getColRowOffset("COL", targetZone.left, targetZone.right + 1), this.viewportWidth);
32728
+ const height = Math.min(this.getters.getColRowOffset("ROW", targetZone.top, targetZone.bottom + 1), this.viewportHeight);
32626
32729
  return {
32627
32730
  x,
32628
32731
  y,
@@ -32685,12 +32788,12 @@ class InternalViewport {
32685
32788
  adjustViewportOffsetX() {
32686
32789
  if (this.canScrollHorizontally) {
32687
32790
  const { width: viewportWidth } = this.getMaxSize();
32688
- if (this.width + this.offsetScrollbarX > viewportWidth) {
32689
- this.offsetScrollbarX = Math.max(0, viewportWidth - this.width);
32791
+ if (this.viewportWidth + this.offsetScrollbarX > viewportWidth) {
32792
+ this.offsetScrollbarX = Math.max(0, viewportWidth - this.viewportWidth);
32690
32793
  }
32691
32794
  }
32692
32795
  this.left = this.getColIndex(this.offsetScrollbarX, true);
32693
- this.right = this.getColIndex(this.offsetScrollbarX + this.width, true);
32796
+ this.right = this.getColIndex(this.offsetScrollbarX + this.viewportWidth, true);
32694
32797
  if (this.right === -1) {
32695
32798
  this.right = this.boundaries.right;
32696
32799
  }
@@ -32702,12 +32805,12 @@ class InternalViewport {
32702
32805
  adjustViewportOffsetY() {
32703
32806
  if (this.canScrollVertically) {
32704
32807
  const { height: paneHeight } = this.getMaxSize();
32705
- if (this.height + this.offsetScrollbarY > paneHeight) {
32706
- this.offsetScrollbarY = Math.max(0, paneHeight - this.height);
32808
+ if (this.viewportHeight + this.offsetScrollbarY > paneHeight) {
32809
+ this.offsetScrollbarY = Math.max(0, paneHeight - this.viewportHeight);
32707
32810
  }
32708
32811
  }
32709
32812
  this.top = this.getRowIndex(this.offsetScrollbarY, true);
32710
- this.bottom = this.getRowIndex(this.offsetScrollbarY + this.width, true);
32813
+ this.bottom = this.getRowIndex(this.offsetScrollbarY + this.viewportWidth, true);
32711
32814
  if (this.bottom === -1) {
32712
32815
  this.bottom = this.boundaries.bottom;
32713
32816
  }
@@ -32718,7 +32821,7 @@ class InternalViewport {
32718
32821
  adjustViewportZoneX() {
32719
32822
  const sheetId = this.sheetId;
32720
32823
  this.left = this.searchHeaderIndex("COL", this.offsetScrollbarX, this.boundaries.left);
32721
- this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.width, this.left));
32824
+ this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.viewportWidth, this.left));
32722
32825
  if (this.right === -1) {
32723
32826
  this.right = this.getters.getNumberCols(sheetId) - 1;
32724
32827
  }
@@ -32731,7 +32834,7 @@ class InternalViewport {
32731
32834
  adjustViewportZoneY() {
32732
32835
  const sheetId = this.sheetId;
32733
32836
  this.top = this.searchHeaderIndex("ROW", this.offsetScrollbarY, this.boundaries.top);
32734
- this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.height, this.top));
32837
+ this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.viewportHeight, this.top));
32735
32838
  if (this.bottom === -1) {
32736
32839
  this.bottom = this.getters.getNumberRows(sheetId) - 1;
32737
32840
  }
@@ -32994,8 +33097,7 @@ class SheetViewPlugin extends UIPlugin {
32994
33097
  return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => !this.getters.isHeaderHidden(sheetId, "ROW", row));
32995
33098
  }
32996
33099
  /**
32997
- * Return the main viewport maximum size. That is the zone dimension
32998
- * with some bottom and right padding.
33100
+ * Return the main viewport maximum size relative to the client size.
32999
33101
  */
33000
33102
  getMainViewportRect() {
33001
33103
  const sheetId = this.getters.getActiveSheetId();
@@ -33011,8 +33113,8 @@ class SheetViewPlugin extends UIPlugin {
33011
33113
  const { width, height } = this.getMainViewportRect();
33012
33114
  const viewport = this.getMainInternalViewport(sheetId);
33013
33115
  return {
33014
- maxOffsetX: Math.max(0, width - viewport.width + 1),
33015
- maxOffsetY: Math.max(0, height - viewport.height + 1),
33116
+ maxOffsetX: Math.max(0, width - viewport.viewportWidth + 1),
33117
+ maxOffsetY: Math.max(0, height - viewport.viewportHeight + 1),
33016
33118
  };
33017
33119
  }
33018
33120
  getColRowOffsetInViewport(dimension, referenceIndex, index) {
@@ -41125,9 +41227,6 @@ css /* scss */ `
41125
41227
  color: #333;
41126
41228
  }
41127
41229
 
41128
- * {
41129
- font-family: "Roboto", "RobotoDraft", Helvetica, Arial, sans-serif;
41130
- }
41131
41230
  &,
41132
41231
  *,
41133
41232
  *:before,
@@ -44993,6 +45092,6 @@ exports.setTranslationMethod = setTranslationMethod;
44993
45092
  exports.tokenize = tokenize;
44994
45093
 
44995
45094
 
44996
- __info__.version = '16.2.1';
44997
- __info__.date = '2023-03-23T11:35:41.982Z';
44998
- __info__.hash = 'd1e5470';
45095
+ __info__.version = '16.2.3';
45096
+ __info__.date = '2023-04-14T12:47:50.453Z';
45097
+ __info__.hash = '4514375';