@odoo/o-spreadsheet 19.4.0-alpha.6 → 19.4.0-alpha.7
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.
- package/dist/o_spreadsheet.cjs +609 -325
- package/dist/o_spreadsheet.css +3 -3
- package/dist/o_spreadsheet.esm.js +609 -325
- package/dist/o_spreadsheet.iife.js +609 -325
- package/dist/o_spreadsheet.min.iife.js +273 -274
- package/dist/o_spreadsheet.xml +3 -3
- package/dist/types/formulas/code_builder.d.ts +19 -5
- package/dist/types/helpers/figures/charts/runtime/chart_highlight.d.ts +9 -0
- package/dist/types/helpers/figures/charts/runtime/chartjs_legend.d.ts +12 -10
- package/dist/types/helpers/figures/charts/runtime/chartjs_scales.d.ts +11 -12
- package/dist/types/helpers/pivot/pivot_composer_helpers.d.ts +4 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/plugins/ui_core_views/pivot_ui.d.ts +17 -8
- package/package.json +1 -1
|
@@ -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.4.0-alpha.
|
|
6
|
-
* @date 2026-05-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 19.4.0-alpha.7
|
|
6
|
+
* @date 2026-05-20T14:40:27.236Z
|
|
7
|
+
* @hash 7ee566f
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function(exports, _odoo_owl) {
|
|
@@ -141,17 +141,234 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
141
141
|
};
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region src/components/helpers/dom_helpers.ts
|
|
146
|
+
const macRegex = /Mac/i;
|
|
147
|
+
let zoomCssDoesNotAffectBoundingRect = false;
|
|
148
|
+
function defineZoomCssImpactOnBoundingRect() {
|
|
149
|
+
const div = document.createElement("div");
|
|
150
|
+
div.setAttribute("style", `width:10px;height:1px;zoom:2;position:absolute;z-index:-10000`);
|
|
151
|
+
document.body.appendChild(div);
|
|
152
|
+
zoomCssDoesNotAffectBoundingRect = div.getBoundingClientRect().width !== 20;
|
|
153
|
+
document.body.removeChild(div);
|
|
154
|
+
}
|
|
155
|
+
(0, _odoo_owl.whenReady)(defineZoomCssImpactOnBoundingRect);
|
|
156
|
+
const MODIFIER_KEYS = [
|
|
157
|
+
"Shift",
|
|
158
|
+
"Control",
|
|
159
|
+
"Alt",
|
|
160
|
+
"Meta"
|
|
161
|
+
];
|
|
162
|
+
/**
|
|
163
|
+
* Return true if the event was triggered from
|
|
164
|
+
* a child element.
|
|
165
|
+
*/
|
|
166
|
+
function isChildEvent(parent, ev) {
|
|
167
|
+
if (!parent) return false;
|
|
168
|
+
return !!ev.target && parent.contains(ev.target);
|
|
169
|
+
}
|
|
170
|
+
function gridOverlayPosition(zoom = 1) {
|
|
171
|
+
const spreadsheetElement = document.querySelector(".o-grid-overlay");
|
|
172
|
+
const result = spreadsheetElement && zoomCorrectedElementRect(spreadsheetElement, zoom);
|
|
173
|
+
if (!result) throw new Error("Can't find spreadsheet position");
|
|
174
|
+
return result;
|
|
175
|
+
}
|
|
176
|
+
function zoomCorrectedElementRect(el, zoomLevel) {
|
|
177
|
+
const zoomedElement = el.closest(".o-zoomable");
|
|
178
|
+
let targetEl;
|
|
179
|
+
let zoom = 1;
|
|
180
|
+
if (zoomedElement) {
|
|
181
|
+
targetEl = zoomedElement;
|
|
182
|
+
zoom = zoomCssDoesNotAffectBoundingRect ? zoomLevel : 1;
|
|
183
|
+
} else targetEl = el;
|
|
184
|
+
const rect = targetEl.getBoundingClientRect();
|
|
185
|
+
return {
|
|
186
|
+
x: rect.x * zoom,
|
|
187
|
+
y: rect.y * zoom,
|
|
188
|
+
width: rect.width * zoom,
|
|
189
|
+
height: rect.height * zoom
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function getRefBoundingRect(ref) {
|
|
193
|
+
if (!ref.el) return {
|
|
194
|
+
x: 0,
|
|
195
|
+
y: 0,
|
|
196
|
+
width: 0,
|
|
197
|
+
height: 0
|
|
198
|
+
};
|
|
199
|
+
return getBoundingRectAsPOJO(ref.el);
|
|
200
|
+
}
|
|
201
|
+
function getBoundingRectAsPOJO(el) {
|
|
202
|
+
const rect = el.getBoundingClientRect();
|
|
203
|
+
return {
|
|
204
|
+
x: rect.x,
|
|
205
|
+
y: rect.y,
|
|
206
|
+
width: rect.width,
|
|
207
|
+
height: rect.height
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Iterate over all the children of `el` in the dom tree starting at `el`, depth first.
|
|
212
|
+
*/
|
|
213
|
+
function* iterateChildren(el) {
|
|
214
|
+
yield el;
|
|
215
|
+
if (el.hasChildNodes()) for (const child of el.childNodes) yield* iterateChildren(child);
|
|
216
|
+
}
|
|
217
|
+
function getOpenedMenus() {
|
|
218
|
+
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
219
|
+
}
|
|
220
|
+
function getCurrentSelection(el) {
|
|
221
|
+
const { startElement, endElement, startSelectionOffset, endSelectionOffset } = getStartAndEndSelection(el);
|
|
222
|
+
return {
|
|
223
|
+
start: findSelectionIndex(el, startElement, startSelectionOffset),
|
|
224
|
+
end: findSelectionIndex(el, endElement, endSelectionOffset)
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
function getStartAndEndSelection(el) {
|
|
228
|
+
const selection = document.getSelection();
|
|
229
|
+
return {
|
|
230
|
+
startElement: selection.anchorNode || el,
|
|
231
|
+
startSelectionOffset: selection.anchorOffset,
|
|
232
|
+
endElement: selection.focusNode || el,
|
|
233
|
+
endSelectionOffset: selection.focusOffset
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Computes the text 'index' inside this.el based on the currently selected node and its offset.
|
|
238
|
+
* The selected node is either a Text node or an Element node.
|
|
239
|
+
*
|
|
240
|
+
* case 1 -Text node:
|
|
241
|
+
* the offset is the number of characters from the start of the node. We have to add this offset to the
|
|
242
|
+
* content length of all previous nodes.
|
|
243
|
+
*
|
|
244
|
+
* case 2 - Element node:
|
|
245
|
+
* the offset is the number of child nodes before the selected node. We have to add the content length of
|
|
246
|
+
* all the nodes prior to the selected node as well as the content of the child node before the offset.
|
|
247
|
+
*
|
|
248
|
+
* See the MDN documentation for more details.
|
|
249
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
|
|
250
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Range/endOffset
|
|
251
|
+
*
|
|
252
|
+
*/
|
|
253
|
+
function findSelectionIndex(el, nodeToFind, nodeOffset) {
|
|
254
|
+
let usedCharacters = 0;
|
|
255
|
+
const it = iterateChildren(el);
|
|
256
|
+
let current = it.next();
|
|
257
|
+
let isFirstParagraph = true;
|
|
258
|
+
while (!current.done && current.value !== nodeToFind) {
|
|
259
|
+
if (!current.value.hasChildNodes()) {
|
|
260
|
+
if (current.value.textContent) usedCharacters += current.value.textContent.length;
|
|
261
|
+
}
|
|
262
|
+
if (current.value.nodeName === "P" || current.value.nodeName === "DIV" && current.value !== el) if (isFirstParagraph) isFirstParagraph = false;
|
|
263
|
+
else usedCharacters++;
|
|
264
|
+
current = it.next();
|
|
265
|
+
}
|
|
266
|
+
if (current.value !== nodeToFind)
|
|
267
|
+
/** This situation can happen if the code is called while the selection is not currently on the element.
|
|
268
|
+
* In this case, we return 0 because we don't know the size of the text before the selection.
|
|
269
|
+
*
|
|
270
|
+
* A known occurrence is triggered since the introduction of commit d4663158 (PR #2038).
|
|
271
|
+
*/
|
|
272
|
+
return 0;
|
|
273
|
+
else if (!current.value.hasChildNodes()) usedCharacters += nodeOffset;
|
|
274
|
+
else {
|
|
275
|
+
const children = [...current.value.childNodes].slice(0, nodeOffset);
|
|
276
|
+
usedCharacters += children.reduce((acc, child, index) => {
|
|
277
|
+
if (child.textContent !== null) {
|
|
278
|
+
let chars = child.textContent.length;
|
|
279
|
+
if (child.nodeName === "P" && index !== children.length - 1) chars++;
|
|
280
|
+
return acc + chars;
|
|
281
|
+
} else return acc;
|
|
282
|
+
}, 0);
|
|
283
|
+
}
|
|
284
|
+
if (nodeToFind.nodeName === "P" && !isFirstParagraph && nodeToFind.textContent === "") usedCharacters++;
|
|
285
|
+
return usedCharacters;
|
|
286
|
+
}
|
|
287
|
+
const letterRegex = /^[a-zA-Z]$/;
|
|
288
|
+
/**
|
|
289
|
+
* Transform a keyboard event into a shortcut string that represent this event. The letters keys will be uppercased.
|
|
290
|
+
*
|
|
291
|
+
* @argument ev - The keyboard event to transform
|
|
292
|
+
* @argument mode - Use either ev.key of ev.code to get the string shortcut
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* event : { ctrlKey: true, key: "a" } => "Ctrl+A"
|
|
296
|
+
* event : { shift: true, alt: true, key: "Home" } => "Alt+Shift+Home"
|
|
297
|
+
*/
|
|
298
|
+
function keyboardEventToShortcutString(ev, mode = "key") {
|
|
299
|
+
let keyDownString = "";
|
|
300
|
+
if (!MODIFIER_KEYS.includes(ev.key)) {
|
|
301
|
+
if (isCtrlKey(ev)) keyDownString += "Ctrl+";
|
|
302
|
+
if (ev.altKey) keyDownString += "Alt+";
|
|
303
|
+
if (ev.shiftKey) keyDownString += "Shift+";
|
|
304
|
+
}
|
|
305
|
+
const key = mode === "key" ? ev.key : ev.code;
|
|
306
|
+
keyDownString += letterRegex.test(key) ? key.toUpperCase() : key;
|
|
307
|
+
return keyDownString;
|
|
308
|
+
}
|
|
309
|
+
function isMacOS() {
|
|
310
|
+
return Boolean(macRegex.test(navigator.userAgent));
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* @param {KeyboardEvent | MouseEvent} ev
|
|
314
|
+
* @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
|
|
315
|
+
* On Mac, this is the "meta" or "command" key.
|
|
316
|
+
*/
|
|
317
|
+
function isCtrlKey(ev) {
|
|
318
|
+
return isMacOS() || isIOS() ? ev.metaKey : ev.ctrlKey;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* @param {MouseEvent} ev - The mouse event.
|
|
322
|
+
* @returns {boolean} Returns true if the event was triggered by a middle-click
|
|
323
|
+
* or a Ctrl + Click (Cmd + Click on Mac).
|
|
324
|
+
*/
|
|
325
|
+
function isMiddleClickOrCtrlClick(ev) {
|
|
326
|
+
return ev.button === 1 || isCtrlKey(ev) && ev.button === 0;
|
|
327
|
+
}
|
|
328
|
+
function downloadFile(dataUrl, fileName) {
|
|
329
|
+
const a = document.createElement("a");
|
|
330
|
+
a.href = dataUrl;
|
|
331
|
+
a.download = fileName;
|
|
332
|
+
document.body.appendChild(a);
|
|
333
|
+
a.click();
|
|
334
|
+
document.body.removeChild(a);
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Detects if the current browser is Firefox
|
|
338
|
+
*/
|
|
339
|
+
function isBrowserFirefox() {
|
|
340
|
+
return /Firefox/i.test(navigator.userAgent);
|
|
341
|
+
}
|
|
342
|
+
function maxTouchPoints() {
|
|
343
|
+
return navigator.maxTouchPoints || 1;
|
|
344
|
+
}
|
|
345
|
+
function isAndroid() {
|
|
346
|
+
return /Android/i.test(navigator.userAgent);
|
|
347
|
+
}
|
|
348
|
+
function isIOS() {
|
|
349
|
+
return /(iPad|iPhone|iPod)/i.test(navigator.userAgent) || navigator.platform === "MacIntel" && maxTouchPoints() > 1;
|
|
350
|
+
}
|
|
351
|
+
function isOtherMobileOS() {
|
|
352
|
+
return /(webOS|BlackBerry|Windows Phone)/i.test(navigator.userAgent);
|
|
353
|
+
}
|
|
354
|
+
function isMobileOS() {
|
|
355
|
+
return isAndroid() || isIOS() || isOtherMobileOS();
|
|
356
|
+
}
|
|
357
|
+
|
|
144
358
|
//#endregion
|
|
145
359
|
//#region src/actions/action.ts
|
|
146
360
|
function createActions(menuItems) {
|
|
147
361
|
return menuItems.map(createAction).sort((a, b) => a.sequence - b.sequence);
|
|
148
362
|
}
|
|
363
|
+
function adaptShortcutMacOs(shortcut) {
|
|
364
|
+
return shortcut.replace("Ctrl", "⌘").replace("Alt", "⌃");
|
|
365
|
+
}
|
|
149
366
|
let nextItemId = 1;
|
|
150
367
|
function createAction(item) {
|
|
151
368
|
const name = item.name;
|
|
152
369
|
const children = item.children;
|
|
153
370
|
const description = item.description;
|
|
154
|
-
const shortcut = item.shortcut;
|
|
371
|
+
const shortcut = item.shortcut && isMacOS() ? adaptShortcutMacOs(item.shortcut) : item.shortcut;
|
|
155
372
|
const icon = item.icon;
|
|
156
373
|
const secondaryIcon = item.secondaryIcon;
|
|
157
374
|
const itemId = item.id || nextItemId++;
|
|
@@ -5033,36 +5250,77 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
5033
5250
|
} else args[i] = arg[0][0];
|
|
5034
5251
|
}
|
|
5035
5252
|
}
|
|
5036
|
-
|
|
5037
|
-
const
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5253
|
+
const argsToFocus = argTargeting(descr, args.length);
|
|
5254
|
+
const argDefinitions = new Array(args.length);
|
|
5255
|
+
for (let k = 0; k < args.length; k++) argDefinitions[k] = descr.args[argsToFocus[k].index];
|
|
5256
|
+
if (countVectorizedCol === 1 && countVectorizedRow === 1) return errorHandlingCompute(descr, context, args, argDefinitions);
|
|
5257
|
+
const argsBuffer = new Array(args.length);
|
|
5258
|
+
const argGetters = [];
|
|
5259
|
+
const vectorizedIndices = [];
|
|
5260
|
+
for (let k = 0; k < args.length; k++) {
|
|
5261
|
+
const arg = args[k];
|
|
5262
|
+
switch (vectorArgsType?.[k]) {
|
|
5263
|
+
case "matrix":
|
|
5264
|
+
argGetters.push((i, j) => arg[i][j]);
|
|
5265
|
+
vectorizedIndices.push(k);
|
|
5266
|
+
break;
|
|
5267
|
+
case "horizontal":
|
|
5268
|
+
argGetters.push((i) => arg[i][0]);
|
|
5269
|
+
vectorizedIndices.push(k);
|
|
5270
|
+
break;
|
|
5271
|
+
case "vertical":
|
|
5272
|
+
argGetters.push((_i, j) => arg[0][j]);
|
|
5273
|
+
vectorizedIndices.push(k);
|
|
5274
|
+
break;
|
|
5275
|
+
case void 0:
|
|
5276
|
+
argsBuffer[k] = arg;
|
|
5277
|
+
break;
|
|
5043
5278
|
}
|
|
5044
|
-
}
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5279
|
+
}
|
|
5280
|
+
const nbVectorized = vectorizedIndices.length;
|
|
5281
|
+
const result = new Array(countVectorizedCol);
|
|
5282
|
+
for (let col = 0; col < countVectorizedCol; col++) {
|
|
5283
|
+
const column = new Array(countVectorizedRow);
|
|
5284
|
+
result[col] = column;
|
|
5285
|
+
for (let row = 0; row < countVectorizedRow; row++) {
|
|
5286
|
+
if (col > vectorizedColLimit - 1 || row > vectorizedRowLimit - 1) {
|
|
5287
|
+
column[row] = new NotAvailableError(_t("Array arguments to [[FUNCTION_NAME]] are of different size."));
|
|
5288
|
+
continue;
|
|
5289
|
+
}
|
|
5290
|
+
for (let k = 0; k < nbVectorized; k++) argsBuffer[vectorizedIndices[k]] = argGetters[k](col, row);
|
|
5291
|
+
const singleCellComputeResult = errorHandlingCompute(descr, context, argsBuffer, argDefinitions);
|
|
5292
|
+
column[row] = isMatrix(singleCellComputeResult) ? singleCellComputeResult[0][0] : singleCellComputeResult;
|
|
5293
|
+
}
|
|
5294
|
+
}
|
|
5295
|
+
return result;
|
|
5050
5296
|
}
|
|
5051
5297
|
function computeFunctionToObject(descr, context, args) {
|
|
5052
5298
|
if (context.debug) {
|
|
5053
5299
|
debugger;
|
|
5054
5300
|
context.debug = false;
|
|
5055
5301
|
}
|
|
5056
|
-
const
|
|
5302
|
+
const compute = descr.compute;
|
|
5303
|
+
let result;
|
|
5304
|
+
switch (args.length) {
|
|
5305
|
+
case 1:
|
|
5306
|
+
result = compute.call(context, args[0]);
|
|
5307
|
+
break;
|
|
5308
|
+
case 2:
|
|
5309
|
+
result = compute.call(context, args[0], args[1]);
|
|
5310
|
+
break;
|
|
5311
|
+
case 3:
|
|
5312
|
+
result = compute.call(context, args[0], args[1], args[2]);
|
|
5313
|
+
break;
|
|
5314
|
+
default: result = compute.apply(context, args);
|
|
5315
|
+
}
|
|
5057
5316
|
if (!isMatrix(result)) return isFunctionResultObject(result) ? result : { value: result };
|
|
5058
5317
|
if (isFunctionResultObject(result[0][0])) return result;
|
|
5059
5318
|
return matrixMap(result, (row) => ({ value: row }));
|
|
5060
5319
|
}
|
|
5061
|
-
function errorHandlingCompute(descr, context, args) {
|
|
5062
|
-
const argsToFocus = argTargeting(descr, args.length);
|
|
5320
|
+
function errorHandlingCompute(descr, context, args, argDefinitions) {
|
|
5063
5321
|
for (let i = 0; i < args.length; i++) {
|
|
5064
5322
|
const arg = args[i];
|
|
5065
|
-
if (!
|
|
5323
|
+
if (!argDefinitions[i].acceptErrors && !isMatrix(arg) && isEvaluationError(arg?.value)) return arg;
|
|
5066
5324
|
}
|
|
5067
5325
|
try {
|
|
5068
5326
|
return computeFunctionToObject(descr, context, args);
|
|
@@ -6261,8 +6519,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
6261
6519
|
changeType: "NONE",
|
|
6262
6520
|
range
|
|
6263
6521
|
};
|
|
6522
|
+
const isUnboundedAtEnd = range.unboundedZone[end] === void 0;
|
|
6523
|
+
if (isUnboundedAtEnd && !range.unboundedZone.hasHeader) return {
|
|
6524
|
+
changeType: "RESIZE",
|
|
6525
|
+
range: createAdaptedRange(range, dimension, "RESIZE", cmd.quantity)
|
|
6526
|
+
};
|
|
6264
6527
|
if (cmd.position === "after") {
|
|
6265
|
-
if (range.zone[start] <= cmd.base && cmd.base < range.zone[end]) return {
|
|
6528
|
+
if (range.zone[start] <= cmd.base && (cmd.base < range.zone[end] || isUnboundedAtEnd)) return {
|
|
6266
6529
|
changeType: "RESIZE",
|
|
6267
6530
|
range: createAdaptedRange(range, dimension, "RESIZE", cmd.quantity)
|
|
6268
6531
|
};
|
|
@@ -6508,40 +6771,65 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
6508
6771
|
|
|
6509
6772
|
//#endregion
|
|
6510
6773
|
//#region src/formulas/code_builder.ts
|
|
6774
|
+
var JsString = class extends String {};
|
|
6775
|
+
/**
|
|
6776
|
+
* Creates a JsString from a raw string, bypassing the template string interpolation checks.
|
|
6777
|
+
* This can lead to security vulnerabilities if the string is not trusted!
|
|
6778
|
+
*/
|
|
6779
|
+
function dangerouslyCreateJsStr(trustedStr) {
|
|
6780
|
+
return new JsString(trustedStr);
|
|
6781
|
+
}
|
|
6782
|
+
/**
|
|
6783
|
+
* Creates a JsString from a template string, ensuring that all interpolated values are safe.
|
|
6784
|
+
*/
|
|
6785
|
+
function jsStr(strings, ...values) {
|
|
6786
|
+
let str = "";
|
|
6787
|
+
for (let i = 0; i < strings.length; i++) {
|
|
6788
|
+
const value = values[i];
|
|
6789
|
+
if (i >= values.length) str += strings[i];
|
|
6790
|
+
else if (isSafeJsValue(value)) str += strings[i] + value;
|
|
6791
|
+
else if (Array.isArray(value) && value.every(isSafeJsValue)) str += strings[i] + value.map((v) => v.toString()).join(",");
|
|
6792
|
+
else throw new Error(`Invalid interpolated value at index ${i}: ${value}`);
|
|
6793
|
+
}
|
|
6794
|
+
return dangerouslyCreateJsStr(str);
|
|
6795
|
+
}
|
|
6796
|
+
function isSafeJsValue(value) {
|
|
6797
|
+
return value instanceof JsString || typeof value === "number" || typeof value === "boolean";
|
|
6798
|
+
}
|
|
6511
6799
|
var FunctionCodeBuilder = class {
|
|
6512
6800
|
scope;
|
|
6513
|
-
code =
|
|
6801
|
+
code = [];
|
|
6514
6802
|
constructor(scope = new Scope()) {
|
|
6515
6803
|
this.scope = scope;
|
|
6516
6804
|
}
|
|
6517
6805
|
append(...lines) {
|
|
6518
|
-
|
|
6806
|
+
for (const line of lines) if (line instanceof FunctionCodeImpl) this.code.push(...line.code);
|
|
6807
|
+
else if (line instanceof JsString) this.code.push(line);
|
|
6808
|
+
else throw new Error(`Invalid line: ${line}`);
|
|
6519
6809
|
}
|
|
6520
6810
|
return(expression) {
|
|
6811
|
+
if (!isSafeJsValue(expression)) throw new Error(`Expected JsString, got ${expression}`);
|
|
6521
6812
|
return new FunctionCodeImpl(this.scope, this.code, expression);
|
|
6522
6813
|
}
|
|
6523
6814
|
toString() {
|
|
6524
|
-
return indentCode(this.code);
|
|
6815
|
+
return indentCode(this.code.join("\n"));
|
|
6525
6816
|
}
|
|
6526
6817
|
};
|
|
6527
6818
|
var FunctionCodeImpl = class {
|
|
6528
6819
|
scope;
|
|
6529
|
-
returnExpression;
|
|
6530
6820
|
code;
|
|
6821
|
+
returnExpression;
|
|
6531
6822
|
constructor(scope, code, returnExpression) {
|
|
6532
6823
|
this.scope = scope;
|
|
6824
|
+
this.code = code;
|
|
6533
6825
|
this.returnExpression = returnExpression;
|
|
6534
|
-
this.code = indentCode(code);
|
|
6535
|
-
}
|
|
6536
|
-
toString() {
|
|
6537
|
-
return this.code;
|
|
6538
6826
|
}
|
|
6539
6827
|
assignResultToVariable() {
|
|
6540
6828
|
if (this.scope.isAlreadyDeclared(this.returnExpression)) return this;
|
|
6541
6829
|
const variableName = this.scope.nextVariableName();
|
|
6542
6830
|
const code = new FunctionCodeBuilder(this.scope);
|
|
6543
|
-
code.append(this.code);
|
|
6544
|
-
code.append(`const ${variableName} = ${this.returnExpression};`);
|
|
6831
|
+
code.append(...this.code);
|
|
6832
|
+
code.append(jsStr`const ${variableName} = ${this.returnExpression};`);
|
|
6545
6833
|
return code.return(variableName);
|
|
6546
6834
|
}
|
|
6547
6835
|
};
|
|
@@ -6549,12 +6837,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
6549
6837
|
nextId = 1;
|
|
6550
6838
|
declaredVariables = /* @__PURE__ */ new Set();
|
|
6551
6839
|
nextVariableName() {
|
|
6552
|
-
const name = `_${this.nextId++}`;
|
|
6553
|
-
this.declaredVariables.add(name);
|
|
6840
|
+
const name = jsStr`_${this.nextId++}`;
|
|
6841
|
+
this.declaredVariables.add(name.toString());
|
|
6554
6842
|
return name;
|
|
6555
6843
|
}
|
|
6556
6844
|
isAlreadyDeclared(name) {
|
|
6557
|
-
return this.declaredVariables.has(name);
|
|
6845
|
+
return this.declaredVariables.has(name.toString());
|
|
6558
6846
|
}
|
|
6559
6847
|
};
|
|
6560
6848
|
/**
|
|
@@ -6771,6 +7059,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
6771
7059
|
try {
|
|
6772
7060
|
return compileTokensOrThrow(tokens);
|
|
6773
7061
|
} catch (error) {
|
|
7062
|
+
if (!(error instanceof EvaluationError)) throw error;
|
|
6774
7063
|
return {
|
|
6775
7064
|
tokens,
|
|
6776
7065
|
literalValues: {
|
|
@@ -6801,7 +7090,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
6801
7090
|
const compiledAST = compileAST(ast);
|
|
6802
7091
|
const code = new FunctionCodeBuilder();
|
|
6803
7092
|
code.append(compiledAST);
|
|
6804
|
-
code.append(`return ${compiledAST.returnExpression};`);
|
|
7093
|
+
code.append(jsStr`return ${compiledAST.returnExpression};`);
|
|
6805
7094
|
functionCache[cacheKey] = new Function("deps", "ref", "range", "getSymbolValue", "ctx", code.toString());
|
|
6806
7095
|
/**
|
|
6807
7096
|
* This function compile the function arguments. It is mostly straightforward,
|
|
@@ -6834,19 +7123,21 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
6834
7123
|
function compileAST(ast, hasRange = false) {
|
|
6835
7124
|
const code = new FunctionCodeBuilder(scope);
|
|
6836
7125
|
if (ast.debug) {
|
|
6837
|
-
code.append(
|
|
6838
|
-
code.append(`ctx["debug"] = true;`);
|
|
7126
|
+
code.append(jsStr`debugger;`);
|
|
7127
|
+
code.append(jsStr`ctx["debug"] = true;`);
|
|
6839
7128
|
}
|
|
6840
7129
|
switch (ast.type) {
|
|
6841
|
-
case "BOOLEAN": return code.return(`{ value: ${ast.value} }`);
|
|
6842
|
-
case "NUMBER": return code.return(`this.literalValues.numbers[${numberCount++}]`);
|
|
6843
|
-
case "STRING": return code.return(`this.literalValues.strings[${stringCount++}]`);
|
|
6844
|
-
case "REFERENCE": return code.return(`${ast.value.includes(":") || hasRange ? `range` : `ref`}(deps[${dependencyCount++}])`);
|
|
7130
|
+
case "BOOLEAN": return code.return(jsStr`{ value: ${ast.value} }`);
|
|
7131
|
+
case "NUMBER": return code.return(jsStr`this.literalValues.numbers[${numberCount++}]`);
|
|
7132
|
+
case "STRING": return code.return(jsStr`this.literalValues.strings[${stringCount++}]`);
|
|
7133
|
+
case "REFERENCE": return code.return(jsStr`${ast.value.includes(":") || hasRange ? jsStr`range` : jsStr`ref`}(deps[${dependencyCount++}])`);
|
|
6845
7134
|
case "FUNCALL":
|
|
6846
7135
|
const args = compileFunctionArgs(ast).map((arg) => arg.assignResultToVariable());
|
|
6847
7136
|
code.append(...args);
|
|
6848
7137
|
const fnName = ast.value.toUpperCase();
|
|
6849
|
-
|
|
7138
|
+
if (!Object.hasOwn(functions$1, fnName)) throw new Error(`Unknown function: "${fnName}"`);
|
|
7139
|
+
const jsFnName = dangerouslyCreateJsStr(fnName);
|
|
7140
|
+
return code.return(jsStr`ctx['${jsFnName}'](${args.map((arg) => arg.returnExpression)})`);
|
|
6850
7141
|
case "ARRAY": return compileAST({
|
|
6851
7142
|
type: "FUNCALL",
|
|
6852
7143
|
value: "ARRAY.LITERAL",
|
|
@@ -6861,23 +7152,25 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
6861
7152
|
tokenEndIndex: 0
|
|
6862
7153
|
});
|
|
6863
7154
|
case "UNARY_OPERATION": {
|
|
6864
|
-
|
|
7155
|
+
if (!Object.hasOwn(UNARY_OPERATOR_MAP, ast.value)) throw new Error(`Unknown operator: "${ast.value}"`);
|
|
7156
|
+
const fnName = dangerouslyCreateJsStr(UNARY_OPERATOR_MAP[ast.value]);
|
|
6865
7157
|
const operand = compileAST(ast.operand, ast.value === "#").assignResultToVariable();
|
|
6866
7158
|
code.append(operand);
|
|
6867
|
-
return code.return(`ctx['${fnName}'](${operand.returnExpression})`);
|
|
7159
|
+
return code.return(jsStr`ctx['${fnName}'](${operand.returnExpression})`);
|
|
6868
7160
|
}
|
|
6869
7161
|
case "BIN_OPERATION": {
|
|
6870
|
-
|
|
7162
|
+
if (!Object.hasOwn(OPERATOR_MAP, ast.value)) throw new Error(`Unknown operator: "${ast.value}"`);
|
|
7163
|
+
const fnName = dangerouslyCreateJsStr(OPERATOR_MAP[ast.value]);
|
|
6871
7164
|
const left = compileAST(ast.left, false).assignResultToVariable();
|
|
6872
7165
|
const right = compileAST(ast.right, false).assignResultToVariable();
|
|
6873
7166
|
code.append(left);
|
|
6874
7167
|
code.append(right);
|
|
6875
|
-
return code.return(`ctx['${fnName}'](${left.returnExpression}, ${right.returnExpression})`);
|
|
7168
|
+
return code.return(jsStr`ctx['${fnName}'](${left.returnExpression}, ${right.returnExpression})`);
|
|
6876
7169
|
}
|
|
6877
7170
|
case "SYMBOL":
|
|
6878
7171
|
const symbolIndex = symbols.indexOf(ast.value);
|
|
6879
|
-
return code.return(`getSymbolValue(this.symbols[${symbolIndex}], ${hasRange})`);
|
|
6880
|
-
case "EMPTY": return code.return(
|
|
7172
|
+
return code.return(jsStr`getSymbolValue(this.symbols[${symbolIndex}], ${hasRange})`);
|
|
7173
|
+
case "EMPTY": return code.return(jsStr`undefined`);
|
|
6881
7174
|
}
|
|
6882
7175
|
}
|
|
6883
7176
|
}
|
|
@@ -11554,220 +11847,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
11554
11847
|
}
|
|
11555
11848
|
};
|
|
11556
11849
|
|
|
11557
|
-
//#endregion
|
|
11558
|
-
//#region src/components/helpers/dom_helpers.ts
|
|
11559
|
-
const macRegex = /Mac/i;
|
|
11560
|
-
let zoomCssDoesNotAffectBoundingRect = false;
|
|
11561
|
-
function defineZoomCssImpactOnBoundingRect() {
|
|
11562
|
-
const div = document.createElement("div");
|
|
11563
|
-
div.setAttribute("style", `width:10px;height:1px;zoom:2;position:absolute;z-index:-10000`);
|
|
11564
|
-
document.body.appendChild(div);
|
|
11565
|
-
zoomCssDoesNotAffectBoundingRect = div.getBoundingClientRect().width !== 20;
|
|
11566
|
-
document.body.removeChild(div);
|
|
11567
|
-
}
|
|
11568
|
-
(0, _odoo_owl.whenReady)(defineZoomCssImpactOnBoundingRect);
|
|
11569
|
-
const MODIFIER_KEYS = [
|
|
11570
|
-
"Shift",
|
|
11571
|
-
"Control",
|
|
11572
|
-
"Alt",
|
|
11573
|
-
"Meta"
|
|
11574
|
-
];
|
|
11575
|
-
/**
|
|
11576
|
-
* Return true if the event was triggered from
|
|
11577
|
-
* a child element.
|
|
11578
|
-
*/
|
|
11579
|
-
function isChildEvent(parent, ev) {
|
|
11580
|
-
if (!parent) return false;
|
|
11581
|
-
return !!ev.target && parent.contains(ev.target);
|
|
11582
|
-
}
|
|
11583
|
-
function gridOverlayPosition(zoom = 1) {
|
|
11584
|
-
const spreadsheetElement = document.querySelector(".o-grid-overlay");
|
|
11585
|
-
const result = spreadsheetElement && zoomCorrectedElementRect(spreadsheetElement, zoom);
|
|
11586
|
-
if (!result) throw new Error("Can't find spreadsheet position");
|
|
11587
|
-
return result;
|
|
11588
|
-
}
|
|
11589
|
-
function zoomCorrectedElementRect(el, zoomLevel) {
|
|
11590
|
-
const zoomedElement = el.closest(".o-zoomable");
|
|
11591
|
-
let targetEl;
|
|
11592
|
-
let zoom = 1;
|
|
11593
|
-
if (zoomedElement) {
|
|
11594
|
-
targetEl = zoomedElement;
|
|
11595
|
-
zoom = zoomCssDoesNotAffectBoundingRect ? zoomLevel : 1;
|
|
11596
|
-
} else targetEl = el;
|
|
11597
|
-
const rect = targetEl.getBoundingClientRect();
|
|
11598
|
-
return {
|
|
11599
|
-
x: rect.x * zoom,
|
|
11600
|
-
y: rect.y * zoom,
|
|
11601
|
-
width: rect.width * zoom,
|
|
11602
|
-
height: rect.height * zoom
|
|
11603
|
-
};
|
|
11604
|
-
}
|
|
11605
|
-
function getRefBoundingRect(ref) {
|
|
11606
|
-
if (!ref.el) return {
|
|
11607
|
-
x: 0,
|
|
11608
|
-
y: 0,
|
|
11609
|
-
width: 0,
|
|
11610
|
-
height: 0
|
|
11611
|
-
};
|
|
11612
|
-
return getBoundingRectAsPOJO(ref.el);
|
|
11613
|
-
}
|
|
11614
|
-
function getBoundingRectAsPOJO(el) {
|
|
11615
|
-
const rect = el.getBoundingClientRect();
|
|
11616
|
-
return {
|
|
11617
|
-
x: rect.x,
|
|
11618
|
-
y: rect.y,
|
|
11619
|
-
width: rect.width,
|
|
11620
|
-
height: rect.height
|
|
11621
|
-
};
|
|
11622
|
-
}
|
|
11623
|
-
/**
|
|
11624
|
-
* Iterate over all the children of `el` in the dom tree starting at `el`, depth first.
|
|
11625
|
-
*/
|
|
11626
|
-
function* iterateChildren(el) {
|
|
11627
|
-
yield el;
|
|
11628
|
-
if (el.hasChildNodes()) for (const child of el.childNodes) yield* iterateChildren(child);
|
|
11629
|
-
}
|
|
11630
|
-
function getOpenedMenus() {
|
|
11631
|
-
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
11632
|
-
}
|
|
11633
|
-
function getCurrentSelection(el) {
|
|
11634
|
-
const { startElement, endElement, startSelectionOffset, endSelectionOffset } = getStartAndEndSelection(el);
|
|
11635
|
-
return {
|
|
11636
|
-
start: findSelectionIndex(el, startElement, startSelectionOffset),
|
|
11637
|
-
end: findSelectionIndex(el, endElement, endSelectionOffset)
|
|
11638
|
-
};
|
|
11639
|
-
}
|
|
11640
|
-
function getStartAndEndSelection(el) {
|
|
11641
|
-
const selection = document.getSelection();
|
|
11642
|
-
return {
|
|
11643
|
-
startElement: selection.anchorNode || el,
|
|
11644
|
-
startSelectionOffset: selection.anchorOffset,
|
|
11645
|
-
endElement: selection.focusNode || el,
|
|
11646
|
-
endSelectionOffset: selection.focusOffset
|
|
11647
|
-
};
|
|
11648
|
-
}
|
|
11649
|
-
/**
|
|
11650
|
-
* Computes the text 'index' inside this.el based on the currently selected node and its offset.
|
|
11651
|
-
* The selected node is either a Text node or an Element node.
|
|
11652
|
-
*
|
|
11653
|
-
* case 1 -Text node:
|
|
11654
|
-
* the offset is the number of characters from the start of the node. We have to add this offset to the
|
|
11655
|
-
* content length of all previous nodes.
|
|
11656
|
-
*
|
|
11657
|
-
* case 2 - Element node:
|
|
11658
|
-
* the offset is the number of child nodes before the selected node. We have to add the content length of
|
|
11659
|
-
* all the nodes prior to the selected node as well as the content of the child node before the offset.
|
|
11660
|
-
*
|
|
11661
|
-
* See the MDN documentation for more details.
|
|
11662
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
|
|
11663
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/Range/endOffset
|
|
11664
|
-
*
|
|
11665
|
-
*/
|
|
11666
|
-
function findSelectionIndex(el, nodeToFind, nodeOffset) {
|
|
11667
|
-
let usedCharacters = 0;
|
|
11668
|
-
const it = iterateChildren(el);
|
|
11669
|
-
let current = it.next();
|
|
11670
|
-
let isFirstParagraph = true;
|
|
11671
|
-
while (!current.done && current.value !== nodeToFind) {
|
|
11672
|
-
if (!current.value.hasChildNodes()) {
|
|
11673
|
-
if (current.value.textContent) usedCharacters += current.value.textContent.length;
|
|
11674
|
-
}
|
|
11675
|
-
if (current.value.nodeName === "P" || current.value.nodeName === "DIV" && current.value !== el) if (isFirstParagraph) isFirstParagraph = false;
|
|
11676
|
-
else usedCharacters++;
|
|
11677
|
-
current = it.next();
|
|
11678
|
-
}
|
|
11679
|
-
if (current.value !== nodeToFind)
|
|
11680
|
-
/** This situation can happen if the code is called while the selection is not currently on the element.
|
|
11681
|
-
* In this case, we return 0 because we don't know the size of the text before the selection.
|
|
11682
|
-
*
|
|
11683
|
-
* A known occurrence is triggered since the introduction of commit d4663158 (PR #2038).
|
|
11684
|
-
*/
|
|
11685
|
-
return 0;
|
|
11686
|
-
else if (!current.value.hasChildNodes()) usedCharacters += nodeOffset;
|
|
11687
|
-
else {
|
|
11688
|
-
const children = [...current.value.childNodes].slice(0, nodeOffset);
|
|
11689
|
-
usedCharacters += children.reduce((acc, child, index) => {
|
|
11690
|
-
if (child.textContent !== null) {
|
|
11691
|
-
let chars = child.textContent.length;
|
|
11692
|
-
if (child.nodeName === "P" && index !== children.length - 1) chars++;
|
|
11693
|
-
return acc + chars;
|
|
11694
|
-
} else return acc;
|
|
11695
|
-
}, 0);
|
|
11696
|
-
}
|
|
11697
|
-
if (nodeToFind.nodeName === "P" && !isFirstParagraph && nodeToFind.textContent === "") usedCharacters++;
|
|
11698
|
-
return usedCharacters;
|
|
11699
|
-
}
|
|
11700
|
-
const letterRegex = /^[a-zA-Z]$/;
|
|
11701
|
-
/**
|
|
11702
|
-
* Transform a keyboard event into a shortcut string that represent this event. The letters keys will be uppercased.
|
|
11703
|
-
*
|
|
11704
|
-
* @argument ev - The keyboard event to transform
|
|
11705
|
-
* @argument mode - Use either ev.key of ev.code to get the string shortcut
|
|
11706
|
-
*
|
|
11707
|
-
* @example
|
|
11708
|
-
* event : { ctrlKey: true, key: "a" } => "Ctrl+A"
|
|
11709
|
-
* event : { shift: true, alt: true, key: "Home" } => "Alt+Shift+Home"
|
|
11710
|
-
*/
|
|
11711
|
-
function keyboardEventToShortcutString(ev, mode = "key") {
|
|
11712
|
-
let keyDownString = "";
|
|
11713
|
-
if (!MODIFIER_KEYS.includes(ev.key)) {
|
|
11714
|
-
if (isCtrlKey(ev)) keyDownString += "Ctrl+";
|
|
11715
|
-
if (ev.altKey) keyDownString += "Alt+";
|
|
11716
|
-
if (ev.shiftKey) keyDownString += "Shift+";
|
|
11717
|
-
}
|
|
11718
|
-
const key = mode === "key" ? ev.key : ev.code;
|
|
11719
|
-
keyDownString += letterRegex.test(key) ? key.toUpperCase() : key;
|
|
11720
|
-
return keyDownString;
|
|
11721
|
-
}
|
|
11722
|
-
function isMacOS() {
|
|
11723
|
-
return Boolean(macRegex.test(navigator.userAgent));
|
|
11724
|
-
}
|
|
11725
|
-
/**
|
|
11726
|
-
* @param {KeyboardEvent | MouseEvent} ev
|
|
11727
|
-
* @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
|
|
11728
|
-
* On Mac, this is the "meta" or "command" key.
|
|
11729
|
-
*/
|
|
11730
|
-
function isCtrlKey(ev) {
|
|
11731
|
-
return isMacOS() || isIOS() ? ev.metaKey : ev.ctrlKey;
|
|
11732
|
-
}
|
|
11733
|
-
/**
|
|
11734
|
-
* @param {MouseEvent} ev - The mouse event.
|
|
11735
|
-
* @returns {boolean} Returns true if the event was triggered by a middle-click
|
|
11736
|
-
* or a Ctrl + Click (Cmd + Click on Mac).
|
|
11737
|
-
*/
|
|
11738
|
-
function isMiddleClickOrCtrlClick(ev) {
|
|
11739
|
-
return ev.button === 1 || isCtrlKey(ev) && ev.button === 0;
|
|
11740
|
-
}
|
|
11741
|
-
function downloadFile(dataUrl, fileName) {
|
|
11742
|
-
const a = document.createElement("a");
|
|
11743
|
-
a.href = dataUrl;
|
|
11744
|
-
a.download = fileName;
|
|
11745
|
-
document.body.appendChild(a);
|
|
11746
|
-
a.click();
|
|
11747
|
-
document.body.removeChild(a);
|
|
11748
|
-
}
|
|
11749
|
-
/**
|
|
11750
|
-
* Detects if the current browser is Firefox
|
|
11751
|
-
*/
|
|
11752
|
-
function isBrowserFirefox() {
|
|
11753
|
-
return /Firefox/i.test(navigator.userAgent);
|
|
11754
|
-
}
|
|
11755
|
-
function maxTouchPoints() {
|
|
11756
|
-
return navigator.maxTouchPoints || 1;
|
|
11757
|
-
}
|
|
11758
|
-
function isAndroid() {
|
|
11759
|
-
return /Android/i.test(navigator.userAgent);
|
|
11760
|
-
}
|
|
11761
|
-
function isIOS() {
|
|
11762
|
-
return /(iPad|iPhone|iPod)/i.test(navigator.userAgent) || navigator.platform === "MacIntel" && maxTouchPoints() > 1;
|
|
11763
|
-
}
|
|
11764
|
-
function isOtherMobileOS() {
|
|
11765
|
-
return /(webOS|BlackBerry|Windows Phone)/i.test(navigator.userAgent);
|
|
11766
|
-
}
|
|
11767
|
-
function isMobileOS() {
|
|
11768
|
-
return isAndroid() || isIOS() || isOtherMobileOS();
|
|
11769
|
-
}
|
|
11770
|
-
|
|
11771
11850
|
//#endregion
|
|
11772
11851
|
//#region src/components/helpers/zoom.ts
|
|
11773
11852
|
/**
|
|
@@ -11852,6 +11931,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
11852
11931
|
window.devicePixelRatio
|
|
11853
11932
|
];
|
|
11854
11933
|
});
|
|
11934
|
+
const resizeObserver = new ResizeObserver(() => this.createChart());
|
|
11935
|
+
(0, _odoo_owl.onMounted)(() => resizeObserver.observe(this.canvas.el));
|
|
11936
|
+
(0, _odoo_owl.onWillUnmount)(() => resizeObserver.disconnect());
|
|
11855
11937
|
}
|
|
11856
11938
|
createChart() {
|
|
11857
11939
|
const canvas = this.canvas.el;
|
|
@@ -13543,6 +13625,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13543
13625
|
window.devicePixelRatio
|
|
13544
13626
|
];
|
|
13545
13627
|
});
|
|
13628
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
13629
|
+
if (animation) {
|
|
13630
|
+
animation.stop();
|
|
13631
|
+
animation = null;
|
|
13632
|
+
}
|
|
13633
|
+
drawGaugeChart(this.canvasEl, this.runtime, this.env.model.getters.getViewportZoomLevel());
|
|
13634
|
+
});
|
|
13635
|
+
(0, _odoo_owl.onMounted)(() => resizeObserver.observe(this.canvas.el));
|
|
13636
|
+
(0, _odoo_owl.onWillUnmount)(() => resizeObserver.disconnect());
|
|
13546
13637
|
}
|
|
13547
13638
|
drawGaugeWithAnimation() {
|
|
13548
13639
|
drawGaugeChart(this.canvasEl, {
|
|
@@ -23477,7 +23568,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23477
23568
|
};
|
|
23478
23569
|
const insertTable = {
|
|
23479
23570
|
name: () => _t("Table"),
|
|
23480
|
-
|
|
23571
|
+
shortcut: "Alt+T",
|
|
23481
23572
|
execute: INSERT_TABLE,
|
|
23482
23573
|
isVisible: (env) => IS_SELECTION_CONTINUOUS(env) && !env.model.getters.getFirstTableInSelection(),
|
|
23483
23574
|
isEnabled: (env) => !env.isSmall,
|
|
@@ -23526,7 +23617,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23526
23617
|
};
|
|
23527
23618
|
const insertLink = {
|
|
23528
23619
|
name: _t("Link"),
|
|
23529
|
-
|
|
23620
|
+
shortcut: "Ctrl+Shift+K",
|
|
23530
23621
|
execute: INSERT_LINK,
|
|
23531
23622
|
icon: "o-spreadsheet-Icon.INSERT_LINK"
|
|
23532
23623
|
};
|
|
@@ -23585,7 +23676,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23585
23676
|
};
|
|
23586
23677
|
const insertSheet = {
|
|
23587
23678
|
name: _t("Insert sheet"),
|
|
23588
|
-
|
|
23679
|
+
shortcut: "Shift+F11",
|
|
23589
23680
|
execute: (env) => {
|
|
23590
23681
|
const activeSheetId = env.model.getters.getActiveSheetId();
|
|
23591
23682
|
const position = env.model.getters.getSheetIds().indexOf(activeSheetId) + 1;
|
|
@@ -27734,6 +27825,74 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27734
27825
|
} };
|
|
27735
27826
|
}
|
|
27736
27827
|
|
|
27828
|
+
//#endregion
|
|
27829
|
+
//#region src/helpers/figures/charts/runtime/chart_highlight.ts
|
|
27830
|
+
const HIGHLIGHT_TRANSPARENCY = .2;
|
|
27831
|
+
function highlightComboChartItem(item, dataSets) {
|
|
27832
|
+
const index = item.datasetIndex;
|
|
27833
|
+
for (let i = 0; i < dataSets.length; i++) {
|
|
27834
|
+
if (i === index) continue;
|
|
27835
|
+
const dataset = dataSets[i];
|
|
27836
|
+
for (const key of ["borderColor", "backgroundColor"]) {
|
|
27837
|
+
if (!(key in dataset)) continue;
|
|
27838
|
+
dataset[key] = setColorAlpha(dataset[key], i === index ? 1 : HIGHLIGHT_TRANSPARENCY);
|
|
27839
|
+
}
|
|
27840
|
+
}
|
|
27841
|
+
}
|
|
27842
|
+
function resetComboChartHighlights(dataSets) {
|
|
27843
|
+
for (const dataset of dataSets) for (const key of ["borderColor", "backgroundColor"]) {
|
|
27844
|
+
if (!(key in dataset)) continue;
|
|
27845
|
+
dataset[key] = setColorAlpha(dataset[key], 1);
|
|
27846
|
+
}
|
|
27847
|
+
}
|
|
27848
|
+
function highlightLineChartItem(item, dataSets) {
|
|
27849
|
+
const index = item.datasetIndex;
|
|
27850
|
+
for (let i = 0; i < dataSets.length; i++) {
|
|
27851
|
+
const dataset = dataSets[i];
|
|
27852
|
+
const color = setColorAlpha(dataset.borderColor, i === index ? 1 : HIGHLIGHT_TRANSPARENCY);
|
|
27853
|
+
dataset.borderColor = color;
|
|
27854
|
+
dataset.pointBackgroundColor = color;
|
|
27855
|
+
dataset.backgroundColor = setColorAlpha(dataset.backgroundColor, LINE_FILL_TRANSPARENCY * (i === index ? 1 : HIGHLIGHT_TRANSPARENCY));
|
|
27856
|
+
}
|
|
27857
|
+
}
|
|
27858
|
+
function resetLineChartHighlights(dataSets) {
|
|
27859
|
+
for (const dataset of dataSets) {
|
|
27860
|
+
const color = setColorAlpha(dataset.borderColor, 1);
|
|
27861
|
+
dataset.borderColor = color;
|
|
27862
|
+
dataset.pointBackgroundColor = color;
|
|
27863
|
+
dataset.backgroundColor = setColorAlpha(dataset.backgroundColor, LINE_FILL_TRANSPARENCY);
|
|
27864
|
+
}
|
|
27865
|
+
}
|
|
27866
|
+
function toggleLineBarDataVisibility(chart, item) {
|
|
27867
|
+
const index = item.datasetIndex;
|
|
27868
|
+
if (index === void 0) return;
|
|
27869
|
+
if (chart.isDatasetVisible(index)) chart.hide(index);
|
|
27870
|
+
else chart.show(index);
|
|
27871
|
+
}
|
|
27872
|
+
function highlightPieChartItem(item, dataSets) {
|
|
27873
|
+
for (const dataset of dataSets) {
|
|
27874
|
+
const backgroundColors = dataset.backgroundColor;
|
|
27875
|
+
if (!backgroundColors) return;
|
|
27876
|
+
backgroundColors.forEach((color, i, colors) => {
|
|
27877
|
+
colors[i] = setColorAlpha(color, i === item.index ? 1 : HIGHLIGHT_TRANSPARENCY);
|
|
27878
|
+
});
|
|
27879
|
+
}
|
|
27880
|
+
}
|
|
27881
|
+
function resetPieChartHighlights(dataSets) {
|
|
27882
|
+
for (const dataset of dataSets) {
|
|
27883
|
+
const backgroundColors = dataset.backgroundColor;
|
|
27884
|
+
if (!backgroundColors) return;
|
|
27885
|
+
backgroundColors.forEach((color, i, colors) => {
|
|
27886
|
+
colors[i] = setColorAlpha(color, 1);
|
|
27887
|
+
});
|
|
27888
|
+
}
|
|
27889
|
+
}
|
|
27890
|
+
function togglePieDataVisibility(chart, item) {
|
|
27891
|
+
const index = item.index;
|
|
27892
|
+
if (index === void 0) return;
|
|
27893
|
+
chart.toggleDataVisibility(index);
|
|
27894
|
+
}
|
|
27895
|
+
|
|
27737
27896
|
//#endregion
|
|
27738
27897
|
//#region src/helpers/figures/charts/runtime/chartjs_legend.ts
|
|
27739
27898
|
function getLegendDisplayOptions({ legendPosition }) {
|
|
@@ -27744,7 +27903,20 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27744
27903
|
}
|
|
27745
27904
|
function getBarChartLegend(definition, args) {
|
|
27746
27905
|
return {
|
|
27747
|
-
...
|
|
27906
|
+
...getInteractiveLegendConfig({
|
|
27907
|
+
highlightItem: highlightComboChartItem,
|
|
27908
|
+
unHighlightItems: resetComboChartHighlights,
|
|
27909
|
+
toggleDataVisibility: toggleLineBarDataVisibility
|
|
27910
|
+
}),
|
|
27911
|
+
...getLegendDisplayOptions(definition),
|
|
27912
|
+
...getCustomLegendLabels(chartFontColor(definition.background), {
|
|
27913
|
+
pointStyle: "rect",
|
|
27914
|
+
lineWidth: 3
|
|
27915
|
+
})
|
|
27916
|
+
};
|
|
27917
|
+
}
|
|
27918
|
+
function getPyramidChartLegend(definition, args) {
|
|
27919
|
+
return {
|
|
27748
27920
|
...getLegendDisplayOptions(definition),
|
|
27749
27921
|
...getCustomLegendLabels(chartFontColor(definition.background), {
|
|
27750
27922
|
pointStyle: "rect",
|
|
@@ -27757,7 +27929,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27757
27929
|
const pointStyle = filled ? "rect" : "line";
|
|
27758
27930
|
const lineWidth = filled ? 2 : 3;
|
|
27759
27931
|
return {
|
|
27760
|
-
...
|
|
27932
|
+
...getInteractiveLegendConfig({
|
|
27933
|
+
highlightItem: highlightLineChartItem,
|
|
27934
|
+
unHighlightItems: resetLineChartHighlights,
|
|
27935
|
+
toggleDataVisibility: toggleLineBarDataVisibility
|
|
27936
|
+
}),
|
|
27761
27937
|
...getLegendDisplayOptions(definition),
|
|
27762
27938
|
...getCustomLegendLabels(chartFontColor(definition.background), {
|
|
27763
27939
|
pointStyle,
|
|
@@ -27770,6 +27946,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27770
27946
|
const colors = getPieColors(new ColorGenerator(Math.max(0, ...dataSetsValues.map((ds) => ds?.data?.length ?? 0)), definition.slicesColors), dataSetsValues);
|
|
27771
27947
|
const fontColor = chartFontColor(definition.background);
|
|
27772
27948
|
return {
|
|
27949
|
+
...getInteractiveLegendConfig({
|
|
27950
|
+
highlightItem: highlightPieChartItem,
|
|
27951
|
+
unHighlightItems: resetPieChartHighlights,
|
|
27952
|
+
toggleDataVisibility: togglePieDataVisibility
|
|
27953
|
+
}),
|
|
27773
27954
|
...getLegendDisplayOptions(definition),
|
|
27774
27955
|
labels: {
|
|
27775
27956
|
usePointStyle: true,
|
|
@@ -27779,7 +27960,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27779
27960
|
fillStyle: colors[index],
|
|
27780
27961
|
pointStyle: "rect",
|
|
27781
27962
|
lineWidth: 2,
|
|
27782
|
-
fontColor
|
|
27963
|
+
fontColor,
|
|
27964
|
+
index,
|
|
27965
|
+
hidden: !c.getDataVisibility?.(index)
|
|
27783
27966
|
})) || []).filter((label) => label.text),
|
|
27784
27967
|
filter: (legendItem, data) => {
|
|
27785
27968
|
return "datasetIndex" in legendItem ? !data.datasets[legendItem.datasetIndex].hidden : true;
|
|
@@ -27789,9 +27972,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27789
27972
|
}
|
|
27790
27973
|
function getScatterChartLegend(definition, args) {
|
|
27791
27974
|
return {
|
|
27792
|
-
...
|
|
27975
|
+
...getInteractiveLegendConfig({
|
|
27976
|
+
highlightItem: highlightLineChartItem,
|
|
27977
|
+
unHighlightItems: resetLineChartHighlights,
|
|
27978
|
+
toggleDataVisibility: toggleLineBarDataVisibility
|
|
27979
|
+
}),
|
|
27793
27980
|
...getLegendDisplayOptions(definition),
|
|
27794
|
-
...
|
|
27981
|
+
...getScatterPlotLegendLabels(chartFontColor(definition.background), {
|
|
27795
27982
|
pointStyle: "circle",
|
|
27796
27983
|
strokeStyle: definition.background || "#ffffff",
|
|
27797
27984
|
lineWidth: 8
|
|
@@ -27812,7 +27999,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27812
27999
|
}
|
|
27813
28000
|
function getComboChartLegend(definition, args) {
|
|
27814
28001
|
return {
|
|
27815
|
-
...
|
|
28002
|
+
...getInteractiveLegendConfig({
|
|
28003
|
+
highlightItem: highlightComboChartItem,
|
|
28004
|
+
unHighlightItems: resetComboChartHighlights,
|
|
28005
|
+
toggleDataVisibility: toggleLineBarDataVisibility
|
|
28006
|
+
}),
|
|
27816
28007
|
...getLegendDisplayOptions(definition),
|
|
27817
28008
|
...getCustomLegendLabels(chartFontColor(definition.background), { lineWidth: 3 })
|
|
27818
28009
|
};
|
|
@@ -27861,7 +28052,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27861
28052
|
const pointStyle = fill ? "rect" : "line";
|
|
27862
28053
|
const lineWidth = fill ? 2 : 3;
|
|
27863
28054
|
return {
|
|
27864
|
-
...
|
|
28055
|
+
...getInteractiveLegendConfig({
|
|
28056
|
+
highlightItem: highlightLineChartItem,
|
|
28057
|
+
unHighlightItems: resetLineChartHighlights,
|
|
28058
|
+
toggleDataVisibility: toggleLineBarDataVisibility
|
|
28059
|
+
}),
|
|
27865
28060
|
...getLegendDisplayOptions(definition),
|
|
27866
28061
|
...getCustomLegendLabels(chartFontColor(definition.background), {
|
|
27867
28062
|
pointStyle,
|
|
@@ -27891,29 +28086,44 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27891
28086
|
}
|
|
27892
28087
|
};
|
|
27893
28088
|
}
|
|
27894
|
-
|
|
27895
|
-
|
|
27896
|
-
|
|
27897
|
-
|
|
27898
|
-
|
|
27899
|
-
|
|
27900
|
-
|
|
27901
|
-
|
|
27902
|
-
|
|
27903
|
-
|
|
27904
|
-
|
|
27905
|
-
|
|
27906
|
-
|
|
27907
|
-
|
|
27908
|
-
|
|
27909
|
-
|
|
27910
|
-
|
|
27911
|
-
|
|
27912
|
-
|
|
27913
|
-
|
|
27914
|
-
|
|
28089
|
+
function getInteractiveLegendConfig({ highlightItem, unHighlightItems, toggleDataVisibility }) {
|
|
28090
|
+
return {
|
|
28091
|
+
onHover: (event, item, legend) => {
|
|
28092
|
+
if (!item.hidden) {
|
|
28093
|
+
const datasets = legend.chart.data.datasets;
|
|
28094
|
+
highlightItem(item, datasets);
|
|
28095
|
+
legend.chart.update();
|
|
28096
|
+
}
|
|
28097
|
+
const target = event.native?.target;
|
|
28098
|
+
if (target && target instanceof HTMLElement) target.style.cursor = "pointer";
|
|
28099
|
+
},
|
|
28100
|
+
onLeave: (event, item, legend) => {
|
|
28101
|
+
if (!item.hidden) {
|
|
28102
|
+
const datasets = legend.chart.data.datasets;
|
|
28103
|
+
unHighlightItems(datasets);
|
|
28104
|
+
legend.chart.update();
|
|
28105
|
+
}
|
|
28106
|
+
const target = event.native?.target;
|
|
28107
|
+
if (target && target instanceof HTMLElement) target.style.cursor = "default";
|
|
28108
|
+
},
|
|
28109
|
+
onClick: (event, item, legend) => {
|
|
28110
|
+
if (event.type !== "click" || !legend.legendItems) return;
|
|
28111
|
+
if (legend.chart.options.animation) legend.chart.options.animation = false;
|
|
28112
|
+
toggleDataVisibility(legend.chart, item);
|
|
28113
|
+
if (!item.hidden) unHighlightItems(legend.chart.data.datasets);
|
|
28114
|
+
else highlightItem(item, legend.chart.data.datasets);
|
|
28115
|
+
legend.chart.update();
|
|
28116
|
+
event.native.preventDefault();
|
|
28117
|
+
event.native.stopPropagation();
|
|
28118
|
+
}
|
|
28119
|
+
};
|
|
28120
|
+
}
|
|
27915
28121
|
const INTERACTIVE_LEGEND_CONFIG_FOR_BUBBLE_CHART = {
|
|
27916
|
-
...
|
|
28122
|
+
...getInteractiveLegendConfig({
|
|
28123
|
+
highlightItem: highlightLineChartItem,
|
|
28124
|
+
unHighlightItems: resetLineChartHighlights,
|
|
28125
|
+
toggleDataVisibility: toggleLineBarDataVisibility
|
|
28126
|
+
}),
|
|
27917
28127
|
onClick: (event, legendItem, legend) => {
|
|
27918
28128
|
if (event.type !== "click") return;
|
|
27919
28129
|
const index = legendItem.datasetIndex;
|
|
@@ -27980,6 +28190,37 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27980
28190
|
filter: (legendItem, data) => true
|
|
27981
28191
|
} };
|
|
27982
28192
|
}
|
|
28193
|
+
function getScatterPlotLegendLabels(fontColor, legendLabelConfig) {
|
|
28194
|
+
return { labels: {
|
|
28195
|
+
color: fontColor,
|
|
28196
|
+
usePointStyle: true,
|
|
28197
|
+
generateLabels: (chart) => chart.data.datasets.map((dataset, index) => {
|
|
28198
|
+
if (isTrendLineAxis(dataset["xAxisID"])) return {
|
|
28199
|
+
text: truncateLabel(dataset.label),
|
|
28200
|
+
fontColor,
|
|
28201
|
+
strokeStyle: dataset.borderColor,
|
|
28202
|
+
hidden: !chart.isDatasetVisible(index),
|
|
28203
|
+
pointStyle: "line",
|
|
28204
|
+
datasetIndex: index,
|
|
28205
|
+
lineWidth: 3
|
|
28206
|
+
};
|
|
28207
|
+
return {
|
|
28208
|
+
text: truncateLabel(dataset.label),
|
|
28209
|
+
fontColor,
|
|
28210
|
+
strokeStyle: dataset.borderColor,
|
|
28211
|
+
fillStyle: dataset["pointBackgroundColor"],
|
|
28212
|
+
hidden: !chart.isDatasetVisible(index),
|
|
28213
|
+
pointStyle: "circle",
|
|
28214
|
+
datasetIndex: index,
|
|
28215
|
+
lineWidth: 8,
|
|
28216
|
+
...legendLabelConfig
|
|
28217
|
+
};
|
|
28218
|
+
}).filter((label) => label.text),
|
|
28219
|
+
filter: (legendItem, data) => {
|
|
28220
|
+
return "datasetIndex" in legendItem ? !data.datasets[legendItem.datasetIndex].hidden : true;
|
|
28221
|
+
}
|
|
28222
|
+
} };
|
|
28223
|
+
}
|
|
27983
28224
|
|
|
27984
28225
|
//#endregion
|
|
27985
28226
|
//#region src/types/chart/sunburst_chart.ts
|
|
@@ -29619,11 +29860,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29619
29860
|
type: "range",
|
|
29620
29861
|
dataSets: [],
|
|
29621
29862
|
dataSetsHaveTitle: false,
|
|
29863
|
+
labelRange: context.auxiliaryRange,
|
|
29622
29864
|
...context.dataSource
|
|
29623
29865
|
};
|
|
29624
29866
|
},
|
|
29625
29867
|
fromHierarchicalContextCreation(context) {
|
|
29626
|
-
if (context.dataSource?.type !== "range" || context.hierarchicalDataSource
|
|
29868
|
+
if (context.dataSource?.type !== "range" || context.hierarchicalDataSource !== void 0 && context.hierarchicalDataSource.type !== "range") return {
|
|
29627
29869
|
type: "range",
|
|
29628
29870
|
dataSets: [],
|
|
29629
29871
|
dataSetsHaveTitle: false
|
|
@@ -37615,7 +37857,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37615
37857
|
col,
|
|
37616
37858
|
row
|
|
37617
37859
|
};
|
|
37618
|
-
if (
|
|
37860
|
+
if (getters.getPivotIdsFromPosition(position).includes(pivotId)) positions.push(position);
|
|
37619
37861
|
}
|
|
37620
37862
|
return positions;
|
|
37621
37863
|
}
|
|
@@ -39689,6 +39931,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
39689
39931
|
function getFirstPivotFunction(compiledFormula, getters) {
|
|
39690
39932
|
return compiledFormula.getFunctionsFromTokens(PIVOT_FUNCTIONS, getters)[0];
|
|
39691
39933
|
}
|
|
39934
|
+
function getPivotFunctions(compiledFormula, getters) {
|
|
39935
|
+
return compiledFormula.getFunctionsFromTokens(PIVOT_FUNCTIONS, getters);
|
|
39936
|
+
}
|
|
39692
39937
|
/**
|
|
39693
39938
|
* Parse a spreadsheet formula and detect the number of PIVOT functions that are
|
|
39694
39939
|
* present in the given formula.
|
|
@@ -49292,6 +49537,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
49292
49537
|
getPieChartLegend: () => getPieChartLegend,
|
|
49293
49538
|
getPieChartTooltip: () => getPieChartTooltip,
|
|
49294
49539
|
getPyramidChartData: () => getPyramidChartData,
|
|
49540
|
+
getPyramidChartLegend: () => getPyramidChartLegend,
|
|
49295
49541
|
getPyramidChartScales: () => getPyramidChartScales,
|
|
49296
49542
|
getPyramidChartShowValues: () => getPyramidChartShowValues,
|
|
49297
49543
|
getPyramidChartTooltip: () => getPyramidChartTooltip,
|
|
@@ -57971,6 +58217,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57971
58217
|
"getFirstPivotFunction",
|
|
57972
58218
|
"getPivotCellSortDirection",
|
|
57973
58219
|
"getPivotIdFromPosition",
|
|
58220
|
+
"getPivotIdsFromPosition",
|
|
57974
58221
|
"getPivotCellFromPosition",
|
|
57975
58222
|
"generateNewCalculatedMeasureName",
|
|
57976
58223
|
"isPivotUnused",
|
|
@@ -58030,37 +58277,52 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
58030
58277
|
}
|
|
58031
58278
|
}
|
|
58032
58279
|
/**
|
|
58033
|
-
* Get the id of the pivot at the given position. Returns undefined if there
|
|
58280
|
+
* Get the id of the first pivot in the formula at the given position. Returns undefined if there
|
|
58034
58281
|
* is no pivot at this position
|
|
58035
58282
|
*/
|
|
58036
58283
|
getPivotIdFromPosition(position) {
|
|
58284
|
+
return this.getPivotIdsFromPosition(position)[0];
|
|
58285
|
+
}
|
|
58286
|
+
/**
|
|
58287
|
+
* Get all of the ids of the pivot present in the formula at the given position.
|
|
58288
|
+
*/
|
|
58289
|
+
getPivotIdsFromPosition(position) {
|
|
58037
58290
|
const cell = this.getters.getCorrespondingFormulaCell(position);
|
|
58038
|
-
if (cell && cell.isFormula)
|
|
58039
|
-
|
|
58040
|
-
|
|
58041
|
-
|
|
58042
|
-
|
|
58043
|
-
|
|
58044
|
-
|
|
58291
|
+
if (cell && cell.isFormula) return this.getPivotIdsFromFormula(position.sheetId, cell.compiledFormula);
|
|
58292
|
+
return [];
|
|
58293
|
+
}
|
|
58294
|
+
getPivotIdsFromFormula(sheetId, formula) {
|
|
58295
|
+
return this.getPivotFunctions(sheetId, formula).map((pivotFunction) => {
|
|
58296
|
+
const pivotId = pivotFunction.args[0]?.toString();
|
|
58297
|
+
return pivotId && this.getters.getPivotId(pivotId);
|
|
58298
|
+
}).filter(isDefined);
|
|
58045
58299
|
}
|
|
58046
58300
|
isSpillPivotFormula(position) {
|
|
58047
58301
|
const cell = this.getters.getCorrespondingFormulaCell(position);
|
|
58048
58302
|
if (cell && cell.isFormula) return this.getFirstPivotFunction(position.sheetId, cell.compiledFormula)?.functionName === "PIVOT";
|
|
58049
58303
|
return false;
|
|
58050
58304
|
}
|
|
58051
|
-
|
|
58052
|
-
const
|
|
58053
|
-
if (!
|
|
58054
|
-
const
|
|
58055
|
-
|
|
58056
|
-
functionName,
|
|
58057
|
-
|
|
58305
|
+
getPivotFunctions(sheetId, formula) {
|
|
58306
|
+
const pivotFunctions = getPivotFunctions(formula, this.getters);
|
|
58307
|
+
if (!pivotFunctions.length) return [];
|
|
58308
|
+
const evaluatedPivotFunctions = [];
|
|
58309
|
+
for (const pivotFunction of pivotFunctions) {
|
|
58310
|
+
const { functionName, args } = pivotFunction;
|
|
58311
|
+
const evaluatedArgs = args.map((argAst) => {
|
|
58058
58312
|
if (argAst.type === "EMPTY") return;
|
|
58059
58313
|
else if (argAst.type === "STRING" || argAst.type === "BOOLEAN" || argAst.type === "NUMBER") return argAst.value;
|
|
58060
58314
|
const argsString = astToFormula(argAst);
|
|
58061
58315
|
return this.getters.evaluateFormula(sheetId, argsString);
|
|
58062
|
-
})
|
|
58063
|
-
|
|
58316
|
+
});
|
|
58317
|
+
evaluatedPivotFunctions.push({
|
|
58318
|
+
functionName,
|
|
58319
|
+
args: evaluatedArgs
|
|
58320
|
+
});
|
|
58321
|
+
}
|
|
58322
|
+
return evaluatedPivotFunctions;
|
|
58323
|
+
}
|
|
58324
|
+
getFirstPivotFunction(sheetId, formula) {
|
|
58325
|
+
return this.getPivotFunctions(sheetId, formula)[0];
|
|
58064
58326
|
}
|
|
58065
58327
|
/**
|
|
58066
58328
|
* Returns the domain args of a pivot formula from a position.
|
|
@@ -58166,8 +58428,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
58166
58428
|
const unusedPivots = new Set(this.getters.getPivotIds());
|
|
58167
58429
|
for (const sheetId of this.getters.getSheetIds()) for (const cell of this.getters.getCells(sheetId)) {
|
|
58168
58430
|
const position = this.getters.getCellPosition(cell.id);
|
|
58169
|
-
const
|
|
58170
|
-
|
|
58431
|
+
const pivotIds = this.getPivotIdsFromPosition(position);
|
|
58432
|
+
for (const pivotId of pivotIds) {
|
|
58171
58433
|
unusedPivots.delete(pivotId);
|
|
58172
58434
|
if (!unusedPivots.size) {
|
|
58173
58435
|
this.unusedPivotsInFormulas = [];
|
|
@@ -58175,6 +58437,21 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
58175
58437
|
}
|
|
58176
58438
|
}
|
|
58177
58439
|
}
|
|
58440
|
+
for (const pivotId of this.getters.getPivotIds()) {
|
|
58441
|
+
const pivot = this.getters.getPivot(pivotId);
|
|
58442
|
+
for (const measure of pivot.definition.measures) if (measure.computedBy) {
|
|
58443
|
+
const { sheetId } = measure.computedBy;
|
|
58444
|
+
const formula = this.getters.getMeasureCompiledFormula(pivotId, measure);
|
|
58445
|
+
const relatedPivotIds = this.getPivotIdsFromFormula(sheetId, formula);
|
|
58446
|
+
for (const relatedPivotId of relatedPivotIds) {
|
|
58447
|
+
unusedPivots.delete(relatedPivotId);
|
|
58448
|
+
if (!unusedPivots.size) {
|
|
58449
|
+
this.unusedPivotsInFormulas = [];
|
|
58450
|
+
return [];
|
|
58451
|
+
}
|
|
58452
|
+
}
|
|
58453
|
+
}
|
|
58454
|
+
}
|
|
58178
58455
|
this.unusedPivotsInFormulas = [...unusedPivots];
|
|
58179
58456
|
return this.unusedPivotsInFormulas;
|
|
58180
58457
|
}
|
|
@@ -62851,12 +63128,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
62851
63128
|
const chartId = this.getChartIdFromFigureId(chartFigureId);
|
|
62852
63129
|
if (!chartId) return;
|
|
62853
63130
|
const carousel = this.getters.getCarousel(figureId);
|
|
63131
|
+
const newItem = {
|
|
63132
|
+
type: "chart",
|
|
63133
|
+
chartId
|
|
63134
|
+
};
|
|
62854
63135
|
const definition = {
|
|
62855
63136
|
...carousel,
|
|
62856
|
-
items: [...carousel.items,
|
|
62857
|
-
type: "chart",
|
|
62858
|
-
chartId
|
|
62859
|
-
}]
|
|
63137
|
+
items: [...carousel.items, newItem]
|
|
62860
63138
|
};
|
|
62861
63139
|
this.dispatch("UPDATE_CAROUSEL", {
|
|
62862
63140
|
sheetId,
|
|
@@ -62873,6 +63151,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
62873
63151
|
sheetId,
|
|
62874
63152
|
figureId: chartFigureId
|
|
62875
63153
|
});
|
|
63154
|
+
this.dispatch("UPDATE_CAROUSEL_ACTIVE_ITEM", {
|
|
63155
|
+
figureId,
|
|
63156
|
+
sheetId,
|
|
63157
|
+
item: newItem
|
|
63158
|
+
});
|
|
62876
63159
|
}
|
|
62877
63160
|
duplicateCarouselChart({ carouselId, chartId, sheetId, duplicatedChartId }) {
|
|
62878
63161
|
const chart = this.getters.getChart(chartId);
|
|
@@ -77214,7 +77497,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
77214
77497
|
scales: getPyramidChartScales(definition, chartData),
|
|
77215
77498
|
plugins: {
|
|
77216
77499
|
title: getChartTitle(definition, getters),
|
|
77217
|
-
legend:
|
|
77500
|
+
legend: getPyramidChartLegend(definition, chartData),
|
|
77218
77501
|
tooltip: getPyramidChartTooltip(definition, chartData),
|
|
77219
77502
|
chartShowValuesPlugin: getPyramidChartShowValues(definition, chartData),
|
|
77220
77503
|
background: { color: chartData.background }
|
|
@@ -85691,7 +85974,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
85691
85974
|
FIGURE_ID_SPLITTER: "??",
|
|
85692
85975
|
GRID_ICON_EDGE_LENGTH: 17,
|
|
85693
85976
|
GRID_ICON_MARGIN: 2,
|
|
85694
|
-
CHART_TYPES
|
|
85977
|
+
CHART_TYPES,
|
|
85978
|
+
DARK_MODE_FILTER_STRING
|
|
85695
85979
|
};
|
|
85696
85980
|
const chartHelpers = {
|
|
85697
85981
|
...helpers_index_exports$1,
|
|
@@ -85792,8 +86076,8 @@ exports.stores = stores;
|
|
|
85792
86076
|
exports.tokenColors = tokenColors;
|
|
85793
86077
|
exports.tokenize = tokenize;
|
|
85794
86078
|
|
|
85795
|
-
__info__.version = "19.4.0-alpha.
|
|
85796
|
-
__info__.date = "2026-05-
|
|
85797
|
-
__info__.hash = "
|
|
86079
|
+
__info__.version = "19.4.0-alpha.7";
|
|
86080
|
+
__info__.date = "2026-05-20T14:40:27.236Z";
|
|
86081
|
+
__info__.hash = "7ee566f";
|
|
85798
86082
|
|
|
85799
86083
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|