@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
package/dist/o_spreadsheet.cjs
CHANGED
|
@@ -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
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
@@ -140,17 +140,234 @@ if (typeof globalThis.document === "undefined") {
|
|
|
140
140
|
};
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
+
//#endregion
|
|
144
|
+
//#region src/components/helpers/dom_helpers.ts
|
|
145
|
+
const macRegex = /Mac/i;
|
|
146
|
+
let zoomCssDoesNotAffectBoundingRect = false;
|
|
147
|
+
function defineZoomCssImpactOnBoundingRect() {
|
|
148
|
+
const div = document.createElement("div");
|
|
149
|
+
div.setAttribute("style", `width:10px;height:1px;zoom:2;position:absolute;z-index:-10000`);
|
|
150
|
+
document.body.appendChild(div);
|
|
151
|
+
zoomCssDoesNotAffectBoundingRect = div.getBoundingClientRect().width !== 20;
|
|
152
|
+
document.body.removeChild(div);
|
|
153
|
+
}
|
|
154
|
+
(0, _odoo_owl.whenReady)(defineZoomCssImpactOnBoundingRect);
|
|
155
|
+
const MODIFIER_KEYS = [
|
|
156
|
+
"Shift",
|
|
157
|
+
"Control",
|
|
158
|
+
"Alt",
|
|
159
|
+
"Meta"
|
|
160
|
+
];
|
|
161
|
+
/**
|
|
162
|
+
* Return true if the event was triggered from
|
|
163
|
+
* a child element.
|
|
164
|
+
*/
|
|
165
|
+
function isChildEvent(parent, ev) {
|
|
166
|
+
if (!parent) return false;
|
|
167
|
+
return !!ev.target && parent.contains(ev.target);
|
|
168
|
+
}
|
|
169
|
+
function gridOverlayPosition(zoom = 1) {
|
|
170
|
+
const spreadsheetElement = document.querySelector(".o-grid-overlay");
|
|
171
|
+
const result = spreadsheetElement && zoomCorrectedElementRect(spreadsheetElement, zoom);
|
|
172
|
+
if (!result) throw new Error("Can't find spreadsheet position");
|
|
173
|
+
return result;
|
|
174
|
+
}
|
|
175
|
+
function zoomCorrectedElementRect(el, zoomLevel) {
|
|
176
|
+
const zoomedElement = el.closest(".o-zoomable");
|
|
177
|
+
let targetEl;
|
|
178
|
+
let zoom = 1;
|
|
179
|
+
if (zoomedElement) {
|
|
180
|
+
targetEl = zoomedElement;
|
|
181
|
+
zoom = zoomCssDoesNotAffectBoundingRect ? zoomLevel : 1;
|
|
182
|
+
} else targetEl = el;
|
|
183
|
+
const rect = targetEl.getBoundingClientRect();
|
|
184
|
+
return {
|
|
185
|
+
x: rect.x * zoom,
|
|
186
|
+
y: rect.y * zoom,
|
|
187
|
+
width: rect.width * zoom,
|
|
188
|
+
height: rect.height * zoom
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function getRefBoundingRect(ref) {
|
|
192
|
+
if (!ref.el) return {
|
|
193
|
+
x: 0,
|
|
194
|
+
y: 0,
|
|
195
|
+
width: 0,
|
|
196
|
+
height: 0
|
|
197
|
+
};
|
|
198
|
+
return getBoundingRectAsPOJO(ref.el);
|
|
199
|
+
}
|
|
200
|
+
function getBoundingRectAsPOJO(el) {
|
|
201
|
+
const rect = el.getBoundingClientRect();
|
|
202
|
+
return {
|
|
203
|
+
x: rect.x,
|
|
204
|
+
y: rect.y,
|
|
205
|
+
width: rect.width,
|
|
206
|
+
height: rect.height
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Iterate over all the children of `el` in the dom tree starting at `el`, depth first.
|
|
211
|
+
*/
|
|
212
|
+
function* iterateChildren(el) {
|
|
213
|
+
yield el;
|
|
214
|
+
if (el.hasChildNodes()) for (const child of el.childNodes) yield* iterateChildren(child);
|
|
215
|
+
}
|
|
216
|
+
function getOpenedMenus() {
|
|
217
|
+
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
218
|
+
}
|
|
219
|
+
function getCurrentSelection(el) {
|
|
220
|
+
const { startElement, endElement, startSelectionOffset, endSelectionOffset } = getStartAndEndSelection(el);
|
|
221
|
+
return {
|
|
222
|
+
start: findSelectionIndex(el, startElement, startSelectionOffset),
|
|
223
|
+
end: findSelectionIndex(el, endElement, endSelectionOffset)
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function getStartAndEndSelection(el) {
|
|
227
|
+
const selection = document.getSelection();
|
|
228
|
+
return {
|
|
229
|
+
startElement: selection.anchorNode || el,
|
|
230
|
+
startSelectionOffset: selection.anchorOffset,
|
|
231
|
+
endElement: selection.focusNode || el,
|
|
232
|
+
endSelectionOffset: selection.focusOffset
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Computes the text 'index' inside this.el based on the currently selected node and its offset.
|
|
237
|
+
* The selected node is either a Text node or an Element node.
|
|
238
|
+
*
|
|
239
|
+
* case 1 -Text node:
|
|
240
|
+
* the offset is the number of characters from the start of the node. We have to add this offset to the
|
|
241
|
+
* content length of all previous nodes.
|
|
242
|
+
*
|
|
243
|
+
* case 2 - Element node:
|
|
244
|
+
* the offset is the number of child nodes before the selected node. We have to add the content length of
|
|
245
|
+
* all the nodes prior to the selected node as well as the content of the child node before the offset.
|
|
246
|
+
*
|
|
247
|
+
* See the MDN documentation for more details.
|
|
248
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
|
|
249
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Range/endOffset
|
|
250
|
+
*
|
|
251
|
+
*/
|
|
252
|
+
function findSelectionIndex(el, nodeToFind, nodeOffset) {
|
|
253
|
+
let usedCharacters = 0;
|
|
254
|
+
const it = iterateChildren(el);
|
|
255
|
+
let current = it.next();
|
|
256
|
+
let isFirstParagraph = true;
|
|
257
|
+
while (!current.done && current.value !== nodeToFind) {
|
|
258
|
+
if (!current.value.hasChildNodes()) {
|
|
259
|
+
if (current.value.textContent) usedCharacters += current.value.textContent.length;
|
|
260
|
+
}
|
|
261
|
+
if (current.value.nodeName === "P" || current.value.nodeName === "DIV" && current.value !== el) if (isFirstParagraph) isFirstParagraph = false;
|
|
262
|
+
else usedCharacters++;
|
|
263
|
+
current = it.next();
|
|
264
|
+
}
|
|
265
|
+
if (current.value !== nodeToFind)
|
|
266
|
+
/** This situation can happen if the code is called while the selection is not currently on the element.
|
|
267
|
+
* In this case, we return 0 because we don't know the size of the text before the selection.
|
|
268
|
+
*
|
|
269
|
+
* A known occurrence is triggered since the introduction of commit d4663158 (PR #2038).
|
|
270
|
+
*/
|
|
271
|
+
return 0;
|
|
272
|
+
else if (!current.value.hasChildNodes()) usedCharacters += nodeOffset;
|
|
273
|
+
else {
|
|
274
|
+
const children = [...current.value.childNodes].slice(0, nodeOffset);
|
|
275
|
+
usedCharacters += children.reduce((acc, child, index) => {
|
|
276
|
+
if (child.textContent !== null) {
|
|
277
|
+
let chars = child.textContent.length;
|
|
278
|
+
if (child.nodeName === "P" && index !== children.length - 1) chars++;
|
|
279
|
+
return acc + chars;
|
|
280
|
+
} else return acc;
|
|
281
|
+
}, 0);
|
|
282
|
+
}
|
|
283
|
+
if (nodeToFind.nodeName === "P" && !isFirstParagraph && nodeToFind.textContent === "") usedCharacters++;
|
|
284
|
+
return usedCharacters;
|
|
285
|
+
}
|
|
286
|
+
const letterRegex = /^[a-zA-Z]$/;
|
|
287
|
+
/**
|
|
288
|
+
* Transform a keyboard event into a shortcut string that represent this event. The letters keys will be uppercased.
|
|
289
|
+
*
|
|
290
|
+
* @argument ev - The keyboard event to transform
|
|
291
|
+
* @argument mode - Use either ev.key of ev.code to get the string shortcut
|
|
292
|
+
*
|
|
293
|
+
* @example
|
|
294
|
+
* event : { ctrlKey: true, key: "a" } => "Ctrl+A"
|
|
295
|
+
* event : { shift: true, alt: true, key: "Home" } => "Alt+Shift+Home"
|
|
296
|
+
*/
|
|
297
|
+
function keyboardEventToShortcutString(ev, mode = "key") {
|
|
298
|
+
let keyDownString = "";
|
|
299
|
+
if (!MODIFIER_KEYS.includes(ev.key)) {
|
|
300
|
+
if (isCtrlKey(ev)) keyDownString += "Ctrl+";
|
|
301
|
+
if (ev.altKey) keyDownString += "Alt+";
|
|
302
|
+
if (ev.shiftKey) keyDownString += "Shift+";
|
|
303
|
+
}
|
|
304
|
+
const key = mode === "key" ? ev.key : ev.code;
|
|
305
|
+
keyDownString += letterRegex.test(key) ? key.toUpperCase() : key;
|
|
306
|
+
return keyDownString;
|
|
307
|
+
}
|
|
308
|
+
function isMacOS() {
|
|
309
|
+
return Boolean(macRegex.test(navigator.userAgent));
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* @param {KeyboardEvent | MouseEvent} ev
|
|
313
|
+
* @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
|
|
314
|
+
* On Mac, this is the "meta" or "command" key.
|
|
315
|
+
*/
|
|
316
|
+
function isCtrlKey(ev) {
|
|
317
|
+
return isMacOS() || isIOS() ? ev.metaKey : ev.ctrlKey;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* @param {MouseEvent} ev - The mouse event.
|
|
321
|
+
* @returns {boolean} Returns true if the event was triggered by a middle-click
|
|
322
|
+
* or a Ctrl + Click (Cmd + Click on Mac).
|
|
323
|
+
*/
|
|
324
|
+
function isMiddleClickOrCtrlClick(ev) {
|
|
325
|
+
return ev.button === 1 || isCtrlKey(ev) && ev.button === 0;
|
|
326
|
+
}
|
|
327
|
+
function downloadFile(dataUrl, fileName) {
|
|
328
|
+
const a = document.createElement("a");
|
|
329
|
+
a.href = dataUrl;
|
|
330
|
+
a.download = fileName;
|
|
331
|
+
document.body.appendChild(a);
|
|
332
|
+
a.click();
|
|
333
|
+
document.body.removeChild(a);
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Detects if the current browser is Firefox
|
|
337
|
+
*/
|
|
338
|
+
function isBrowserFirefox() {
|
|
339
|
+
return /Firefox/i.test(navigator.userAgent);
|
|
340
|
+
}
|
|
341
|
+
function maxTouchPoints() {
|
|
342
|
+
return navigator.maxTouchPoints || 1;
|
|
343
|
+
}
|
|
344
|
+
function isAndroid() {
|
|
345
|
+
return /Android/i.test(navigator.userAgent);
|
|
346
|
+
}
|
|
347
|
+
function isIOS() {
|
|
348
|
+
return /(iPad|iPhone|iPod)/i.test(navigator.userAgent) || navigator.platform === "MacIntel" && maxTouchPoints() > 1;
|
|
349
|
+
}
|
|
350
|
+
function isOtherMobileOS() {
|
|
351
|
+
return /(webOS|BlackBerry|Windows Phone)/i.test(navigator.userAgent);
|
|
352
|
+
}
|
|
353
|
+
function isMobileOS() {
|
|
354
|
+
return isAndroid() || isIOS() || isOtherMobileOS();
|
|
355
|
+
}
|
|
356
|
+
|
|
143
357
|
//#endregion
|
|
144
358
|
//#region src/actions/action.ts
|
|
145
359
|
function createActions(menuItems) {
|
|
146
360
|
return menuItems.map(createAction).sort((a, b) => a.sequence - b.sequence);
|
|
147
361
|
}
|
|
362
|
+
function adaptShortcutMacOs(shortcut) {
|
|
363
|
+
return shortcut.replace("Ctrl", "⌘").replace("Alt", "⌃");
|
|
364
|
+
}
|
|
148
365
|
let nextItemId = 1;
|
|
149
366
|
function createAction(item) {
|
|
150
367
|
const name = item.name;
|
|
151
368
|
const children = item.children;
|
|
152
369
|
const description = item.description;
|
|
153
|
-
const shortcut = item.shortcut;
|
|
370
|
+
const shortcut = item.shortcut && isMacOS() ? adaptShortcutMacOs(item.shortcut) : item.shortcut;
|
|
154
371
|
const icon = item.icon;
|
|
155
372
|
const secondaryIcon = item.secondaryIcon;
|
|
156
373
|
const itemId = item.id || nextItemId++;
|
|
@@ -5032,36 +5249,77 @@ function applyVectorization(context, descr, args, acceptToVectorize = void 0) {
|
|
|
5032
5249
|
} else args[i] = arg[0][0];
|
|
5033
5250
|
}
|
|
5034
5251
|
}
|
|
5035
|
-
|
|
5036
|
-
const
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5252
|
+
const argsToFocus = argTargeting(descr, args.length);
|
|
5253
|
+
const argDefinitions = new Array(args.length);
|
|
5254
|
+
for (let k = 0; k < args.length; k++) argDefinitions[k] = descr.args[argsToFocus[k].index];
|
|
5255
|
+
if (countVectorizedCol === 1 && countVectorizedRow === 1) return errorHandlingCompute(descr, context, args, argDefinitions);
|
|
5256
|
+
const argsBuffer = new Array(args.length);
|
|
5257
|
+
const argGetters = [];
|
|
5258
|
+
const vectorizedIndices = [];
|
|
5259
|
+
for (let k = 0; k < args.length; k++) {
|
|
5260
|
+
const arg = args[k];
|
|
5261
|
+
switch (vectorArgsType?.[k]) {
|
|
5262
|
+
case "matrix":
|
|
5263
|
+
argGetters.push((i, j) => arg[i][j]);
|
|
5264
|
+
vectorizedIndices.push(k);
|
|
5265
|
+
break;
|
|
5266
|
+
case "horizontal":
|
|
5267
|
+
argGetters.push((i) => arg[i][0]);
|
|
5268
|
+
vectorizedIndices.push(k);
|
|
5269
|
+
break;
|
|
5270
|
+
case "vertical":
|
|
5271
|
+
argGetters.push((_i, j) => arg[0][j]);
|
|
5272
|
+
vectorizedIndices.push(k);
|
|
5273
|
+
break;
|
|
5274
|
+
case void 0:
|
|
5275
|
+
argsBuffer[k] = arg;
|
|
5276
|
+
break;
|
|
5042
5277
|
}
|
|
5043
|
-
}
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5278
|
+
}
|
|
5279
|
+
const nbVectorized = vectorizedIndices.length;
|
|
5280
|
+
const result = new Array(countVectorizedCol);
|
|
5281
|
+
for (let col = 0; col < countVectorizedCol; col++) {
|
|
5282
|
+
const column = new Array(countVectorizedRow);
|
|
5283
|
+
result[col] = column;
|
|
5284
|
+
for (let row = 0; row < countVectorizedRow; row++) {
|
|
5285
|
+
if (col > vectorizedColLimit - 1 || row > vectorizedRowLimit - 1) {
|
|
5286
|
+
column[row] = new NotAvailableError(_t("Array arguments to [[FUNCTION_NAME]] are of different size."));
|
|
5287
|
+
continue;
|
|
5288
|
+
}
|
|
5289
|
+
for (let k = 0; k < nbVectorized; k++) argsBuffer[vectorizedIndices[k]] = argGetters[k](col, row);
|
|
5290
|
+
const singleCellComputeResult = errorHandlingCompute(descr, context, argsBuffer, argDefinitions);
|
|
5291
|
+
column[row] = isMatrix(singleCellComputeResult) ? singleCellComputeResult[0][0] : singleCellComputeResult;
|
|
5292
|
+
}
|
|
5293
|
+
}
|
|
5294
|
+
return result;
|
|
5049
5295
|
}
|
|
5050
5296
|
function computeFunctionToObject(descr, context, args) {
|
|
5051
5297
|
if (context.debug) {
|
|
5052
5298
|
debugger;
|
|
5053
5299
|
context.debug = false;
|
|
5054
5300
|
}
|
|
5055
|
-
const
|
|
5301
|
+
const compute = descr.compute;
|
|
5302
|
+
let result;
|
|
5303
|
+
switch (args.length) {
|
|
5304
|
+
case 1:
|
|
5305
|
+
result = compute.call(context, args[0]);
|
|
5306
|
+
break;
|
|
5307
|
+
case 2:
|
|
5308
|
+
result = compute.call(context, args[0], args[1]);
|
|
5309
|
+
break;
|
|
5310
|
+
case 3:
|
|
5311
|
+
result = compute.call(context, args[0], args[1], args[2]);
|
|
5312
|
+
break;
|
|
5313
|
+
default: result = compute.apply(context, args);
|
|
5314
|
+
}
|
|
5056
5315
|
if (!isMatrix(result)) return isFunctionResultObject(result) ? result : { value: result };
|
|
5057
5316
|
if (isFunctionResultObject(result[0][0])) return result;
|
|
5058
5317
|
return matrixMap(result, (row) => ({ value: row }));
|
|
5059
5318
|
}
|
|
5060
|
-
function errorHandlingCompute(descr, context, args) {
|
|
5061
|
-
const argsToFocus = argTargeting(descr, args.length);
|
|
5319
|
+
function errorHandlingCompute(descr, context, args, argDefinitions) {
|
|
5062
5320
|
for (let i = 0; i < args.length; i++) {
|
|
5063
5321
|
const arg = args[i];
|
|
5064
|
-
if (!
|
|
5322
|
+
if (!argDefinitions[i].acceptErrors && !isMatrix(arg) && isEvaluationError(arg?.value)) return arg;
|
|
5065
5323
|
}
|
|
5066
5324
|
try {
|
|
5067
5325
|
return computeFunctionToObject(descr, context, args);
|
|
@@ -6260,8 +6518,13 @@ function getApplyRangeChangeAddColRow(cmd) {
|
|
|
6260
6518
|
changeType: "NONE",
|
|
6261
6519
|
range
|
|
6262
6520
|
};
|
|
6521
|
+
const isUnboundedAtEnd = range.unboundedZone[end] === void 0;
|
|
6522
|
+
if (isUnboundedAtEnd && !range.unboundedZone.hasHeader) return {
|
|
6523
|
+
changeType: "RESIZE",
|
|
6524
|
+
range: createAdaptedRange(range, dimension, "RESIZE", cmd.quantity)
|
|
6525
|
+
};
|
|
6263
6526
|
if (cmd.position === "after") {
|
|
6264
|
-
if (range.zone[start] <= cmd.base && cmd.base < range.zone[end]) return {
|
|
6527
|
+
if (range.zone[start] <= cmd.base && (cmd.base < range.zone[end] || isUnboundedAtEnd)) return {
|
|
6265
6528
|
changeType: "RESIZE",
|
|
6266
6529
|
range: createAdaptedRange(range, dimension, "RESIZE", cmd.quantity)
|
|
6267
6530
|
};
|
|
@@ -6507,40 +6770,65 @@ function getRange(sheetXC, sheetId) {
|
|
|
6507
6770
|
|
|
6508
6771
|
//#endregion
|
|
6509
6772
|
//#region src/formulas/code_builder.ts
|
|
6773
|
+
var JsString = class extends String {};
|
|
6774
|
+
/**
|
|
6775
|
+
* Creates a JsString from a raw string, bypassing the template string interpolation checks.
|
|
6776
|
+
* This can lead to security vulnerabilities if the string is not trusted!
|
|
6777
|
+
*/
|
|
6778
|
+
function dangerouslyCreateJsStr(trustedStr) {
|
|
6779
|
+
return new JsString(trustedStr);
|
|
6780
|
+
}
|
|
6781
|
+
/**
|
|
6782
|
+
* Creates a JsString from a template string, ensuring that all interpolated values are safe.
|
|
6783
|
+
*/
|
|
6784
|
+
function jsStr(strings, ...values) {
|
|
6785
|
+
let str = "";
|
|
6786
|
+
for (let i = 0; i < strings.length; i++) {
|
|
6787
|
+
const value = values[i];
|
|
6788
|
+
if (i >= values.length) str += strings[i];
|
|
6789
|
+
else if (isSafeJsValue(value)) str += strings[i] + value;
|
|
6790
|
+
else if (Array.isArray(value) && value.every(isSafeJsValue)) str += strings[i] + value.map((v) => v.toString()).join(",");
|
|
6791
|
+
else throw new Error(`Invalid interpolated value at index ${i}: ${value}`);
|
|
6792
|
+
}
|
|
6793
|
+
return dangerouslyCreateJsStr(str);
|
|
6794
|
+
}
|
|
6795
|
+
function isSafeJsValue(value) {
|
|
6796
|
+
return value instanceof JsString || typeof value === "number" || typeof value === "boolean";
|
|
6797
|
+
}
|
|
6510
6798
|
var FunctionCodeBuilder = class {
|
|
6511
6799
|
scope;
|
|
6512
|
-
code =
|
|
6800
|
+
code = [];
|
|
6513
6801
|
constructor(scope = new Scope()) {
|
|
6514
6802
|
this.scope = scope;
|
|
6515
6803
|
}
|
|
6516
6804
|
append(...lines) {
|
|
6517
|
-
|
|
6805
|
+
for (const line of lines) if (line instanceof FunctionCodeImpl) this.code.push(...line.code);
|
|
6806
|
+
else if (line instanceof JsString) this.code.push(line);
|
|
6807
|
+
else throw new Error(`Invalid line: ${line}`);
|
|
6518
6808
|
}
|
|
6519
6809
|
return(expression) {
|
|
6810
|
+
if (!isSafeJsValue(expression)) throw new Error(`Expected JsString, got ${expression}`);
|
|
6520
6811
|
return new FunctionCodeImpl(this.scope, this.code, expression);
|
|
6521
6812
|
}
|
|
6522
6813
|
toString() {
|
|
6523
|
-
return indentCode(this.code);
|
|
6814
|
+
return indentCode(this.code.join("\n"));
|
|
6524
6815
|
}
|
|
6525
6816
|
};
|
|
6526
6817
|
var FunctionCodeImpl = class {
|
|
6527
6818
|
scope;
|
|
6528
|
-
returnExpression;
|
|
6529
6819
|
code;
|
|
6820
|
+
returnExpression;
|
|
6530
6821
|
constructor(scope, code, returnExpression) {
|
|
6531
6822
|
this.scope = scope;
|
|
6823
|
+
this.code = code;
|
|
6532
6824
|
this.returnExpression = returnExpression;
|
|
6533
|
-
this.code = indentCode(code);
|
|
6534
|
-
}
|
|
6535
|
-
toString() {
|
|
6536
|
-
return this.code;
|
|
6537
6825
|
}
|
|
6538
6826
|
assignResultToVariable() {
|
|
6539
6827
|
if (this.scope.isAlreadyDeclared(this.returnExpression)) return this;
|
|
6540
6828
|
const variableName = this.scope.nextVariableName();
|
|
6541
6829
|
const code = new FunctionCodeBuilder(this.scope);
|
|
6542
|
-
code.append(this.code);
|
|
6543
|
-
code.append(`const ${variableName} = ${this.returnExpression};`);
|
|
6830
|
+
code.append(...this.code);
|
|
6831
|
+
code.append(jsStr`const ${variableName} = ${this.returnExpression};`);
|
|
6544
6832
|
return code.return(variableName);
|
|
6545
6833
|
}
|
|
6546
6834
|
};
|
|
@@ -6548,12 +6836,12 @@ var Scope = class {
|
|
|
6548
6836
|
nextId = 1;
|
|
6549
6837
|
declaredVariables = /* @__PURE__ */ new Set();
|
|
6550
6838
|
nextVariableName() {
|
|
6551
|
-
const name = `_${this.nextId++}`;
|
|
6552
|
-
this.declaredVariables.add(name);
|
|
6839
|
+
const name = jsStr`_${this.nextId++}`;
|
|
6840
|
+
this.declaredVariables.add(name.toString());
|
|
6553
6841
|
return name;
|
|
6554
6842
|
}
|
|
6555
6843
|
isAlreadyDeclared(name) {
|
|
6556
|
-
return this.declaredVariables.has(name);
|
|
6844
|
+
return this.declaredVariables.has(name.toString());
|
|
6557
6845
|
}
|
|
6558
6846
|
};
|
|
6559
6847
|
/**
|
|
@@ -6770,6 +7058,7 @@ function compileTokens(tokens) {
|
|
|
6770
7058
|
try {
|
|
6771
7059
|
return compileTokensOrThrow(tokens);
|
|
6772
7060
|
} catch (error) {
|
|
7061
|
+
if (!(error instanceof EvaluationError)) throw error;
|
|
6773
7062
|
return {
|
|
6774
7063
|
tokens,
|
|
6775
7064
|
literalValues: {
|
|
@@ -6800,7 +7089,7 @@ function compileTokensOrThrow(tokens) {
|
|
|
6800
7089
|
const compiledAST = compileAST(ast);
|
|
6801
7090
|
const code = new FunctionCodeBuilder();
|
|
6802
7091
|
code.append(compiledAST);
|
|
6803
|
-
code.append(`return ${compiledAST.returnExpression};`);
|
|
7092
|
+
code.append(jsStr`return ${compiledAST.returnExpression};`);
|
|
6804
7093
|
functionCache[cacheKey] = new Function("deps", "ref", "range", "getSymbolValue", "ctx", code.toString());
|
|
6805
7094
|
/**
|
|
6806
7095
|
* This function compile the function arguments. It is mostly straightforward,
|
|
@@ -6833,19 +7122,21 @@ function compileTokensOrThrow(tokens) {
|
|
|
6833
7122
|
function compileAST(ast, hasRange = false) {
|
|
6834
7123
|
const code = new FunctionCodeBuilder(scope);
|
|
6835
7124
|
if (ast.debug) {
|
|
6836
|
-
code.append(
|
|
6837
|
-
code.append(`ctx["debug"] = true;`);
|
|
7125
|
+
code.append(jsStr`debugger;`);
|
|
7126
|
+
code.append(jsStr`ctx["debug"] = true;`);
|
|
6838
7127
|
}
|
|
6839
7128
|
switch (ast.type) {
|
|
6840
|
-
case "BOOLEAN": return code.return(`{ value: ${ast.value} }`);
|
|
6841
|
-
case "NUMBER": return code.return(`this.literalValues.numbers[${numberCount++}]`);
|
|
6842
|
-
case "STRING": return code.return(`this.literalValues.strings[${stringCount++}]`);
|
|
6843
|
-
case "REFERENCE": return code.return(`${ast.value.includes(":") || hasRange ? `range` : `ref`}(deps[${dependencyCount++}])`);
|
|
7129
|
+
case "BOOLEAN": return code.return(jsStr`{ value: ${ast.value} }`);
|
|
7130
|
+
case "NUMBER": return code.return(jsStr`this.literalValues.numbers[${numberCount++}]`);
|
|
7131
|
+
case "STRING": return code.return(jsStr`this.literalValues.strings[${stringCount++}]`);
|
|
7132
|
+
case "REFERENCE": return code.return(jsStr`${ast.value.includes(":") || hasRange ? jsStr`range` : jsStr`ref`}(deps[${dependencyCount++}])`);
|
|
6844
7133
|
case "FUNCALL":
|
|
6845
7134
|
const args = compileFunctionArgs(ast).map((arg) => arg.assignResultToVariable());
|
|
6846
7135
|
code.append(...args);
|
|
6847
7136
|
const fnName = ast.value.toUpperCase();
|
|
6848
|
-
|
|
7137
|
+
if (!Object.hasOwn(functions$1, fnName)) throw new Error(`Unknown function: "${fnName}"`);
|
|
7138
|
+
const jsFnName = dangerouslyCreateJsStr(fnName);
|
|
7139
|
+
return code.return(jsStr`ctx['${jsFnName}'](${args.map((arg) => arg.returnExpression)})`);
|
|
6849
7140
|
case "ARRAY": return compileAST({
|
|
6850
7141
|
type: "FUNCALL",
|
|
6851
7142
|
value: "ARRAY.LITERAL",
|
|
@@ -6860,23 +7151,25 @@ function compileTokensOrThrow(tokens) {
|
|
|
6860
7151
|
tokenEndIndex: 0
|
|
6861
7152
|
});
|
|
6862
7153
|
case "UNARY_OPERATION": {
|
|
6863
|
-
|
|
7154
|
+
if (!Object.hasOwn(UNARY_OPERATOR_MAP, ast.value)) throw new Error(`Unknown operator: "${ast.value}"`);
|
|
7155
|
+
const fnName = dangerouslyCreateJsStr(UNARY_OPERATOR_MAP[ast.value]);
|
|
6864
7156
|
const operand = compileAST(ast.operand, ast.value === "#").assignResultToVariable();
|
|
6865
7157
|
code.append(operand);
|
|
6866
|
-
return code.return(`ctx['${fnName}'](${operand.returnExpression})`);
|
|
7158
|
+
return code.return(jsStr`ctx['${fnName}'](${operand.returnExpression})`);
|
|
6867
7159
|
}
|
|
6868
7160
|
case "BIN_OPERATION": {
|
|
6869
|
-
|
|
7161
|
+
if (!Object.hasOwn(OPERATOR_MAP, ast.value)) throw new Error(`Unknown operator: "${ast.value}"`);
|
|
7162
|
+
const fnName = dangerouslyCreateJsStr(OPERATOR_MAP[ast.value]);
|
|
6870
7163
|
const left = compileAST(ast.left, false).assignResultToVariable();
|
|
6871
7164
|
const right = compileAST(ast.right, false).assignResultToVariable();
|
|
6872
7165
|
code.append(left);
|
|
6873
7166
|
code.append(right);
|
|
6874
|
-
return code.return(`ctx['${fnName}'](${left.returnExpression}, ${right.returnExpression})`);
|
|
7167
|
+
return code.return(jsStr`ctx['${fnName}'](${left.returnExpression}, ${right.returnExpression})`);
|
|
6875
7168
|
}
|
|
6876
7169
|
case "SYMBOL":
|
|
6877
7170
|
const symbolIndex = symbols.indexOf(ast.value);
|
|
6878
|
-
return code.return(`getSymbolValue(this.symbols[${symbolIndex}], ${hasRange})`);
|
|
6879
|
-
case "EMPTY": return code.return(
|
|
7171
|
+
return code.return(jsStr`getSymbolValue(this.symbols[${symbolIndex}], ${hasRange})`);
|
|
7172
|
+
case "EMPTY": return code.return(jsStr`undefined`);
|
|
6880
7173
|
}
|
|
6881
7174
|
}
|
|
6882
7175
|
}
|
|
@@ -11553,220 +11846,6 @@ var ScorecardChartConfigBuilder = class {
|
|
|
11553
11846
|
}
|
|
11554
11847
|
};
|
|
11555
11848
|
|
|
11556
|
-
//#endregion
|
|
11557
|
-
//#region src/components/helpers/dom_helpers.ts
|
|
11558
|
-
const macRegex = /Mac/i;
|
|
11559
|
-
let zoomCssDoesNotAffectBoundingRect = false;
|
|
11560
|
-
function defineZoomCssImpactOnBoundingRect() {
|
|
11561
|
-
const div = document.createElement("div");
|
|
11562
|
-
div.setAttribute("style", `width:10px;height:1px;zoom:2;position:absolute;z-index:-10000`);
|
|
11563
|
-
document.body.appendChild(div);
|
|
11564
|
-
zoomCssDoesNotAffectBoundingRect = div.getBoundingClientRect().width !== 20;
|
|
11565
|
-
document.body.removeChild(div);
|
|
11566
|
-
}
|
|
11567
|
-
(0, _odoo_owl.whenReady)(defineZoomCssImpactOnBoundingRect);
|
|
11568
|
-
const MODIFIER_KEYS = [
|
|
11569
|
-
"Shift",
|
|
11570
|
-
"Control",
|
|
11571
|
-
"Alt",
|
|
11572
|
-
"Meta"
|
|
11573
|
-
];
|
|
11574
|
-
/**
|
|
11575
|
-
* Return true if the event was triggered from
|
|
11576
|
-
* a child element.
|
|
11577
|
-
*/
|
|
11578
|
-
function isChildEvent(parent, ev) {
|
|
11579
|
-
if (!parent) return false;
|
|
11580
|
-
return !!ev.target && parent.contains(ev.target);
|
|
11581
|
-
}
|
|
11582
|
-
function gridOverlayPosition(zoom = 1) {
|
|
11583
|
-
const spreadsheetElement = document.querySelector(".o-grid-overlay");
|
|
11584
|
-
const result = spreadsheetElement && zoomCorrectedElementRect(spreadsheetElement, zoom);
|
|
11585
|
-
if (!result) throw new Error("Can't find spreadsheet position");
|
|
11586
|
-
return result;
|
|
11587
|
-
}
|
|
11588
|
-
function zoomCorrectedElementRect(el, zoomLevel) {
|
|
11589
|
-
const zoomedElement = el.closest(".o-zoomable");
|
|
11590
|
-
let targetEl;
|
|
11591
|
-
let zoom = 1;
|
|
11592
|
-
if (zoomedElement) {
|
|
11593
|
-
targetEl = zoomedElement;
|
|
11594
|
-
zoom = zoomCssDoesNotAffectBoundingRect ? zoomLevel : 1;
|
|
11595
|
-
} else targetEl = el;
|
|
11596
|
-
const rect = targetEl.getBoundingClientRect();
|
|
11597
|
-
return {
|
|
11598
|
-
x: rect.x * zoom,
|
|
11599
|
-
y: rect.y * zoom,
|
|
11600
|
-
width: rect.width * zoom,
|
|
11601
|
-
height: rect.height * zoom
|
|
11602
|
-
};
|
|
11603
|
-
}
|
|
11604
|
-
function getRefBoundingRect(ref) {
|
|
11605
|
-
if (!ref.el) return {
|
|
11606
|
-
x: 0,
|
|
11607
|
-
y: 0,
|
|
11608
|
-
width: 0,
|
|
11609
|
-
height: 0
|
|
11610
|
-
};
|
|
11611
|
-
return getBoundingRectAsPOJO(ref.el);
|
|
11612
|
-
}
|
|
11613
|
-
function getBoundingRectAsPOJO(el) {
|
|
11614
|
-
const rect = el.getBoundingClientRect();
|
|
11615
|
-
return {
|
|
11616
|
-
x: rect.x,
|
|
11617
|
-
y: rect.y,
|
|
11618
|
-
width: rect.width,
|
|
11619
|
-
height: rect.height
|
|
11620
|
-
};
|
|
11621
|
-
}
|
|
11622
|
-
/**
|
|
11623
|
-
* Iterate over all the children of `el` in the dom tree starting at `el`, depth first.
|
|
11624
|
-
*/
|
|
11625
|
-
function* iterateChildren(el) {
|
|
11626
|
-
yield el;
|
|
11627
|
-
if (el.hasChildNodes()) for (const child of el.childNodes) yield* iterateChildren(child);
|
|
11628
|
-
}
|
|
11629
|
-
function getOpenedMenus() {
|
|
11630
|
-
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
11631
|
-
}
|
|
11632
|
-
function getCurrentSelection(el) {
|
|
11633
|
-
const { startElement, endElement, startSelectionOffset, endSelectionOffset } = getStartAndEndSelection(el);
|
|
11634
|
-
return {
|
|
11635
|
-
start: findSelectionIndex(el, startElement, startSelectionOffset),
|
|
11636
|
-
end: findSelectionIndex(el, endElement, endSelectionOffset)
|
|
11637
|
-
};
|
|
11638
|
-
}
|
|
11639
|
-
function getStartAndEndSelection(el) {
|
|
11640
|
-
const selection = document.getSelection();
|
|
11641
|
-
return {
|
|
11642
|
-
startElement: selection.anchorNode || el,
|
|
11643
|
-
startSelectionOffset: selection.anchorOffset,
|
|
11644
|
-
endElement: selection.focusNode || el,
|
|
11645
|
-
endSelectionOffset: selection.focusOffset
|
|
11646
|
-
};
|
|
11647
|
-
}
|
|
11648
|
-
/**
|
|
11649
|
-
* Computes the text 'index' inside this.el based on the currently selected node and its offset.
|
|
11650
|
-
* The selected node is either a Text node or an Element node.
|
|
11651
|
-
*
|
|
11652
|
-
* case 1 -Text node:
|
|
11653
|
-
* the offset is the number of characters from the start of the node. We have to add this offset to the
|
|
11654
|
-
* content length of all previous nodes.
|
|
11655
|
-
*
|
|
11656
|
-
* case 2 - Element node:
|
|
11657
|
-
* the offset is the number of child nodes before the selected node. We have to add the content length of
|
|
11658
|
-
* all the nodes prior to the selected node as well as the content of the child node before the offset.
|
|
11659
|
-
*
|
|
11660
|
-
* See the MDN documentation for more details.
|
|
11661
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
|
|
11662
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/Range/endOffset
|
|
11663
|
-
*
|
|
11664
|
-
*/
|
|
11665
|
-
function findSelectionIndex(el, nodeToFind, nodeOffset) {
|
|
11666
|
-
let usedCharacters = 0;
|
|
11667
|
-
const it = iterateChildren(el);
|
|
11668
|
-
let current = it.next();
|
|
11669
|
-
let isFirstParagraph = true;
|
|
11670
|
-
while (!current.done && current.value !== nodeToFind) {
|
|
11671
|
-
if (!current.value.hasChildNodes()) {
|
|
11672
|
-
if (current.value.textContent) usedCharacters += current.value.textContent.length;
|
|
11673
|
-
}
|
|
11674
|
-
if (current.value.nodeName === "P" || current.value.nodeName === "DIV" && current.value !== el) if (isFirstParagraph) isFirstParagraph = false;
|
|
11675
|
-
else usedCharacters++;
|
|
11676
|
-
current = it.next();
|
|
11677
|
-
}
|
|
11678
|
-
if (current.value !== nodeToFind)
|
|
11679
|
-
/** This situation can happen if the code is called while the selection is not currently on the element.
|
|
11680
|
-
* In this case, we return 0 because we don't know the size of the text before the selection.
|
|
11681
|
-
*
|
|
11682
|
-
* A known occurrence is triggered since the introduction of commit d4663158 (PR #2038).
|
|
11683
|
-
*/
|
|
11684
|
-
return 0;
|
|
11685
|
-
else if (!current.value.hasChildNodes()) usedCharacters += nodeOffset;
|
|
11686
|
-
else {
|
|
11687
|
-
const children = [...current.value.childNodes].slice(0, nodeOffset);
|
|
11688
|
-
usedCharacters += children.reduce((acc, child, index) => {
|
|
11689
|
-
if (child.textContent !== null) {
|
|
11690
|
-
let chars = child.textContent.length;
|
|
11691
|
-
if (child.nodeName === "P" && index !== children.length - 1) chars++;
|
|
11692
|
-
return acc + chars;
|
|
11693
|
-
} else return acc;
|
|
11694
|
-
}, 0);
|
|
11695
|
-
}
|
|
11696
|
-
if (nodeToFind.nodeName === "P" && !isFirstParagraph && nodeToFind.textContent === "") usedCharacters++;
|
|
11697
|
-
return usedCharacters;
|
|
11698
|
-
}
|
|
11699
|
-
const letterRegex = /^[a-zA-Z]$/;
|
|
11700
|
-
/**
|
|
11701
|
-
* Transform a keyboard event into a shortcut string that represent this event. The letters keys will be uppercased.
|
|
11702
|
-
*
|
|
11703
|
-
* @argument ev - The keyboard event to transform
|
|
11704
|
-
* @argument mode - Use either ev.key of ev.code to get the string shortcut
|
|
11705
|
-
*
|
|
11706
|
-
* @example
|
|
11707
|
-
* event : { ctrlKey: true, key: "a" } => "Ctrl+A"
|
|
11708
|
-
* event : { shift: true, alt: true, key: "Home" } => "Alt+Shift+Home"
|
|
11709
|
-
*/
|
|
11710
|
-
function keyboardEventToShortcutString(ev, mode = "key") {
|
|
11711
|
-
let keyDownString = "";
|
|
11712
|
-
if (!MODIFIER_KEYS.includes(ev.key)) {
|
|
11713
|
-
if (isCtrlKey(ev)) keyDownString += "Ctrl+";
|
|
11714
|
-
if (ev.altKey) keyDownString += "Alt+";
|
|
11715
|
-
if (ev.shiftKey) keyDownString += "Shift+";
|
|
11716
|
-
}
|
|
11717
|
-
const key = mode === "key" ? ev.key : ev.code;
|
|
11718
|
-
keyDownString += letterRegex.test(key) ? key.toUpperCase() : key;
|
|
11719
|
-
return keyDownString;
|
|
11720
|
-
}
|
|
11721
|
-
function isMacOS() {
|
|
11722
|
-
return Boolean(macRegex.test(navigator.userAgent));
|
|
11723
|
-
}
|
|
11724
|
-
/**
|
|
11725
|
-
* @param {KeyboardEvent | MouseEvent} ev
|
|
11726
|
-
* @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
|
|
11727
|
-
* On Mac, this is the "meta" or "command" key.
|
|
11728
|
-
*/
|
|
11729
|
-
function isCtrlKey(ev) {
|
|
11730
|
-
return isMacOS() || isIOS() ? ev.metaKey : ev.ctrlKey;
|
|
11731
|
-
}
|
|
11732
|
-
/**
|
|
11733
|
-
* @param {MouseEvent} ev - The mouse event.
|
|
11734
|
-
* @returns {boolean} Returns true if the event was triggered by a middle-click
|
|
11735
|
-
* or a Ctrl + Click (Cmd + Click on Mac).
|
|
11736
|
-
*/
|
|
11737
|
-
function isMiddleClickOrCtrlClick(ev) {
|
|
11738
|
-
return ev.button === 1 || isCtrlKey(ev) && ev.button === 0;
|
|
11739
|
-
}
|
|
11740
|
-
function downloadFile(dataUrl, fileName) {
|
|
11741
|
-
const a = document.createElement("a");
|
|
11742
|
-
a.href = dataUrl;
|
|
11743
|
-
a.download = fileName;
|
|
11744
|
-
document.body.appendChild(a);
|
|
11745
|
-
a.click();
|
|
11746
|
-
document.body.removeChild(a);
|
|
11747
|
-
}
|
|
11748
|
-
/**
|
|
11749
|
-
* Detects if the current browser is Firefox
|
|
11750
|
-
*/
|
|
11751
|
-
function isBrowserFirefox() {
|
|
11752
|
-
return /Firefox/i.test(navigator.userAgent);
|
|
11753
|
-
}
|
|
11754
|
-
function maxTouchPoints() {
|
|
11755
|
-
return navigator.maxTouchPoints || 1;
|
|
11756
|
-
}
|
|
11757
|
-
function isAndroid() {
|
|
11758
|
-
return /Android/i.test(navigator.userAgent);
|
|
11759
|
-
}
|
|
11760
|
-
function isIOS() {
|
|
11761
|
-
return /(iPad|iPhone|iPod)/i.test(navigator.userAgent) || navigator.platform === "MacIntel" && maxTouchPoints() > 1;
|
|
11762
|
-
}
|
|
11763
|
-
function isOtherMobileOS() {
|
|
11764
|
-
return /(webOS|BlackBerry|Windows Phone)/i.test(navigator.userAgent);
|
|
11765
|
-
}
|
|
11766
|
-
function isMobileOS() {
|
|
11767
|
-
return isAndroid() || isIOS() || isOtherMobileOS();
|
|
11768
|
-
}
|
|
11769
|
-
|
|
11770
11849
|
//#endregion
|
|
11771
11850
|
//#region src/components/helpers/zoom.ts
|
|
11772
11851
|
/**
|
|
@@ -11851,6 +11930,9 @@ var ScorecardChart = class extends _odoo_owl.Component {
|
|
|
11851
11930
|
window.devicePixelRatio
|
|
11852
11931
|
];
|
|
11853
11932
|
});
|
|
11933
|
+
const resizeObserver = new ResizeObserver(() => this.createChart());
|
|
11934
|
+
(0, _odoo_owl.onMounted)(() => resizeObserver.observe(this.canvas.el));
|
|
11935
|
+
(0, _odoo_owl.onWillUnmount)(() => resizeObserver.disconnect());
|
|
11854
11936
|
}
|
|
11855
11937
|
createChart() {
|
|
11856
11938
|
const canvas = this.canvas.el;
|
|
@@ -13542,6 +13624,15 @@ var GaugeChartComponent = class extends _odoo_owl.Component {
|
|
|
13542
13624
|
window.devicePixelRatio
|
|
13543
13625
|
];
|
|
13544
13626
|
});
|
|
13627
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
13628
|
+
if (animation) {
|
|
13629
|
+
animation.stop();
|
|
13630
|
+
animation = null;
|
|
13631
|
+
}
|
|
13632
|
+
drawGaugeChart(this.canvasEl, this.runtime, this.env.model.getters.getViewportZoomLevel());
|
|
13633
|
+
});
|
|
13634
|
+
(0, _odoo_owl.onMounted)(() => resizeObserver.observe(this.canvas.el));
|
|
13635
|
+
(0, _odoo_owl.onWillUnmount)(() => resizeObserver.disconnect());
|
|
13545
13636
|
}
|
|
13546
13637
|
drawGaugeWithAnimation() {
|
|
13547
13638
|
drawGaugeChart(this.canvasEl, {
|
|
@@ -23476,7 +23567,7 @@ const insertImage = {
|
|
|
23476
23567
|
};
|
|
23477
23568
|
const insertTable = {
|
|
23478
23569
|
name: () => _t("Table"),
|
|
23479
|
-
|
|
23570
|
+
shortcut: "Alt+T",
|
|
23480
23571
|
execute: INSERT_TABLE,
|
|
23481
23572
|
isVisible: (env) => IS_SELECTION_CONTINUOUS(env) && !env.model.getters.getFirstTableInSelection(),
|
|
23482
23573
|
isEnabled: (env) => !env.isSmall,
|
|
@@ -23525,7 +23616,7 @@ const categoriesFunctionListMenuBuilder = () => {
|
|
|
23525
23616
|
};
|
|
23526
23617
|
const insertLink = {
|
|
23527
23618
|
name: _t("Link"),
|
|
23528
|
-
|
|
23619
|
+
shortcut: "Ctrl+Shift+K",
|
|
23529
23620
|
execute: INSERT_LINK,
|
|
23530
23621
|
icon: "o-spreadsheet-Icon.INSERT_LINK"
|
|
23531
23622
|
};
|
|
@@ -23584,7 +23675,7 @@ const insertDropdown = {
|
|
|
23584
23675
|
};
|
|
23585
23676
|
const insertSheet = {
|
|
23586
23677
|
name: _t("Insert sheet"),
|
|
23587
|
-
|
|
23678
|
+
shortcut: "Shift+F11",
|
|
23588
23679
|
execute: (env) => {
|
|
23589
23680
|
const activeSheetId = env.model.getters.getActiveSheetId();
|
|
23590
23681
|
const position = env.model.getters.getSheetIds().indexOf(activeSheetId) + 1;
|
|
@@ -27733,6 +27824,74 @@ function getCalendarChartLayout(definition, args) {
|
|
|
27733
27824
|
} };
|
|
27734
27825
|
}
|
|
27735
27826
|
|
|
27827
|
+
//#endregion
|
|
27828
|
+
//#region src/helpers/figures/charts/runtime/chart_highlight.ts
|
|
27829
|
+
const HIGHLIGHT_TRANSPARENCY = .2;
|
|
27830
|
+
function highlightComboChartItem(item, dataSets) {
|
|
27831
|
+
const index = item.datasetIndex;
|
|
27832
|
+
for (let i = 0; i < dataSets.length; i++) {
|
|
27833
|
+
if (i === index) continue;
|
|
27834
|
+
const dataset = dataSets[i];
|
|
27835
|
+
for (const key of ["borderColor", "backgroundColor"]) {
|
|
27836
|
+
if (!(key in dataset)) continue;
|
|
27837
|
+
dataset[key] = setColorAlpha(dataset[key], i === index ? 1 : HIGHLIGHT_TRANSPARENCY);
|
|
27838
|
+
}
|
|
27839
|
+
}
|
|
27840
|
+
}
|
|
27841
|
+
function resetComboChartHighlights(dataSets) {
|
|
27842
|
+
for (const dataset of dataSets) for (const key of ["borderColor", "backgroundColor"]) {
|
|
27843
|
+
if (!(key in dataset)) continue;
|
|
27844
|
+
dataset[key] = setColorAlpha(dataset[key], 1);
|
|
27845
|
+
}
|
|
27846
|
+
}
|
|
27847
|
+
function highlightLineChartItem(item, dataSets) {
|
|
27848
|
+
const index = item.datasetIndex;
|
|
27849
|
+
for (let i = 0; i < dataSets.length; i++) {
|
|
27850
|
+
const dataset = dataSets[i];
|
|
27851
|
+
const color = setColorAlpha(dataset.borderColor, i === index ? 1 : HIGHLIGHT_TRANSPARENCY);
|
|
27852
|
+
dataset.borderColor = color;
|
|
27853
|
+
dataset.pointBackgroundColor = color;
|
|
27854
|
+
dataset.backgroundColor = setColorAlpha(dataset.backgroundColor, LINE_FILL_TRANSPARENCY * (i === index ? 1 : HIGHLIGHT_TRANSPARENCY));
|
|
27855
|
+
}
|
|
27856
|
+
}
|
|
27857
|
+
function resetLineChartHighlights(dataSets) {
|
|
27858
|
+
for (const dataset of dataSets) {
|
|
27859
|
+
const color = setColorAlpha(dataset.borderColor, 1);
|
|
27860
|
+
dataset.borderColor = color;
|
|
27861
|
+
dataset.pointBackgroundColor = color;
|
|
27862
|
+
dataset.backgroundColor = setColorAlpha(dataset.backgroundColor, LINE_FILL_TRANSPARENCY);
|
|
27863
|
+
}
|
|
27864
|
+
}
|
|
27865
|
+
function toggleLineBarDataVisibility(chart, item) {
|
|
27866
|
+
const index = item.datasetIndex;
|
|
27867
|
+
if (index === void 0) return;
|
|
27868
|
+
if (chart.isDatasetVisible(index)) chart.hide(index);
|
|
27869
|
+
else chart.show(index);
|
|
27870
|
+
}
|
|
27871
|
+
function highlightPieChartItem(item, dataSets) {
|
|
27872
|
+
for (const dataset of dataSets) {
|
|
27873
|
+
const backgroundColors = dataset.backgroundColor;
|
|
27874
|
+
if (!backgroundColors) return;
|
|
27875
|
+
backgroundColors.forEach((color, i, colors) => {
|
|
27876
|
+
colors[i] = setColorAlpha(color, i === item.index ? 1 : HIGHLIGHT_TRANSPARENCY);
|
|
27877
|
+
});
|
|
27878
|
+
}
|
|
27879
|
+
}
|
|
27880
|
+
function resetPieChartHighlights(dataSets) {
|
|
27881
|
+
for (const dataset of dataSets) {
|
|
27882
|
+
const backgroundColors = dataset.backgroundColor;
|
|
27883
|
+
if (!backgroundColors) return;
|
|
27884
|
+
backgroundColors.forEach((color, i, colors) => {
|
|
27885
|
+
colors[i] = setColorAlpha(color, 1);
|
|
27886
|
+
});
|
|
27887
|
+
}
|
|
27888
|
+
}
|
|
27889
|
+
function togglePieDataVisibility(chart, item) {
|
|
27890
|
+
const index = item.index;
|
|
27891
|
+
if (index === void 0) return;
|
|
27892
|
+
chart.toggleDataVisibility(index);
|
|
27893
|
+
}
|
|
27894
|
+
|
|
27736
27895
|
//#endregion
|
|
27737
27896
|
//#region src/helpers/figures/charts/runtime/chartjs_legend.ts
|
|
27738
27897
|
function getLegendDisplayOptions({ legendPosition }) {
|
|
@@ -27743,7 +27902,20 @@ function getLegendDisplayOptions({ legendPosition }) {
|
|
|
27743
27902
|
}
|
|
27744
27903
|
function getBarChartLegend(definition, args) {
|
|
27745
27904
|
return {
|
|
27746
|
-
...
|
|
27905
|
+
...getInteractiveLegendConfig({
|
|
27906
|
+
highlightItem: highlightComboChartItem,
|
|
27907
|
+
unHighlightItems: resetComboChartHighlights,
|
|
27908
|
+
toggleDataVisibility: toggleLineBarDataVisibility
|
|
27909
|
+
}),
|
|
27910
|
+
...getLegendDisplayOptions(definition),
|
|
27911
|
+
...getCustomLegendLabels(chartFontColor(definition.background), {
|
|
27912
|
+
pointStyle: "rect",
|
|
27913
|
+
lineWidth: 3
|
|
27914
|
+
})
|
|
27915
|
+
};
|
|
27916
|
+
}
|
|
27917
|
+
function getPyramidChartLegend(definition, args) {
|
|
27918
|
+
return {
|
|
27747
27919
|
...getLegendDisplayOptions(definition),
|
|
27748
27920
|
...getCustomLegendLabels(chartFontColor(definition.background), {
|
|
27749
27921
|
pointStyle: "rect",
|
|
@@ -27756,7 +27928,11 @@ function getLineChartLegend(definition, args) {
|
|
|
27756
27928
|
const pointStyle = filled ? "rect" : "line";
|
|
27757
27929
|
const lineWidth = filled ? 2 : 3;
|
|
27758
27930
|
return {
|
|
27759
|
-
...
|
|
27931
|
+
...getInteractiveLegendConfig({
|
|
27932
|
+
highlightItem: highlightLineChartItem,
|
|
27933
|
+
unHighlightItems: resetLineChartHighlights,
|
|
27934
|
+
toggleDataVisibility: toggleLineBarDataVisibility
|
|
27935
|
+
}),
|
|
27760
27936
|
...getLegendDisplayOptions(definition),
|
|
27761
27937
|
...getCustomLegendLabels(chartFontColor(definition.background), {
|
|
27762
27938
|
pointStyle,
|
|
@@ -27769,6 +27945,11 @@ function getPieChartLegend(definition, args) {
|
|
|
27769
27945
|
const colors = getPieColors(new ColorGenerator(Math.max(0, ...dataSetsValues.map((ds) => ds?.data?.length ?? 0)), definition.slicesColors), dataSetsValues);
|
|
27770
27946
|
const fontColor = chartFontColor(definition.background);
|
|
27771
27947
|
return {
|
|
27948
|
+
...getInteractiveLegendConfig({
|
|
27949
|
+
highlightItem: highlightPieChartItem,
|
|
27950
|
+
unHighlightItems: resetPieChartHighlights,
|
|
27951
|
+
toggleDataVisibility: togglePieDataVisibility
|
|
27952
|
+
}),
|
|
27772
27953
|
...getLegendDisplayOptions(definition),
|
|
27773
27954
|
labels: {
|
|
27774
27955
|
usePointStyle: true,
|
|
@@ -27778,7 +27959,9 @@ function getPieChartLegend(definition, args) {
|
|
|
27778
27959
|
fillStyle: colors[index],
|
|
27779
27960
|
pointStyle: "rect",
|
|
27780
27961
|
lineWidth: 2,
|
|
27781
|
-
fontColor
|
|
27962
|
+
fontColor,
|
|
27963
|
+
index,
|
|
27964
|
+
hidden: !c.getDataVisibility?.(index)
|
|
27782
27965
|
})) || []).filter((label) => label.text),
|
|
27783
27966
|
filter: (legendItem, data) => {
|
|
27784
27967
|
return "datasetIndex" in legendItem ? !data.datasets[legendItem.datasetIndex].hidden : true;
|
|
@@ -27788,9 +27971,13 @@ function getPieChartLegend(definition, args) {
|
|
|
27788
27971
|
}
|
|
27789
27972
|
function getScatterChartLegend(definition, args) {
|
|
27790
27973
|
return {
|
|
27791
|
-
...
|
|
27974
|
+
...getInteractiveLegendConfig({
|
|
27975
|
+
highlightItem: highlightLineChartItem,
|
|
27976
|
+
unHighlightItems: resetLineChartHighlights,
|
|
27977
|
+
toggleDataVisibility: toggleLineBarDataVisibility
|
|
27978
|
+
}),
|
|
27792
27979
|
...getLegendDisplayOptions(definition),
|
|
27793
|
-
...
|
|
27980
|
+
...getScatterPlotLegendLabels(chartFontColor(definition.background), {
|
|
27794
27981
|
pointStyle: "circle",
|
|
27795
27982
|
strokeStyle: definition.background || "#ffffff",
|
|
27796
27983
|
lineWidth: 8
|
|
@@ -27811,7 +27998,11 @@ function getBubbleChartLegend(definition, args) {
|
|
|
27811
27998
|
}
|
|
27812
27999
|
function getComboChartLegend(definition, args) {
|
|
27813
28000
|
return {
|
|
27814
|
-
...
|
|
28001
|
+
...getInteractiveLegendConfig({
|
|
28002
|
+
highlightItem: highlightComboChartItem,
|
|
28003
|
+
unHighlightItems: resetComboChartHighlights,
|
|
28004
|
+
toggleDataVisibility: toggleLineBarDataVisibility
|
|
28005
|
+
}),
|
|
27815
28006
|
...getLegendDisplayOptions(definition),
|
|
27816
28007
|
...getCustomLegendLabels(chartFontColor(definition.background), { lineWidth: 3 })
|
|
27817
28008
|
};
|
|
@@ -27860,7 +28051,11 @@ function getRadarChartLegend(definition, args) {
|
|
|
27860
28051
|
const pointStyle = fill ? "rect" : "line";
|
|
27861
28052
|
const lineWidth = fill ? 2 : 3;
|
|
27862
28053
|
return {
|
|
27863
|
-
...
|
|
28054
|
+
...getInteractiveLegendConfig({
|
|
28055
|
+
highlightItem: highlightLineChartItem,
|
|
28056
|
+
unHighlightItems: resetLineChartHighlights,
|
|
28057
|
+
toggleDataVisibility: toggleLineBarDataVisibility
|
|
28058
|
+
}),
|
|
27864
28059
|
...getLegendDisplayOptions(definition),
|
|
27865
28060
|
...getCustomLegendLabels(chartFontColor(definition.background), {
|
|
27866
28061
|
pointStyle,
|
|
@@ -27890,29 +28085,44 @@ function getSunburstChartLegend(definition, args) {
|
|
|
27890
28085
|
}
|
|
27891
28086
|
};
|
|
27892
28087
|
}
|
|
27893
|
-
|
|
27894
|
-
|
|
27895
|
-
|
|
27896
|
-
|
|
27897
|
-
|
|
27898
|
-
|
|
27899
|
-
|
|
27900
|
-
|
|
27901
|
-
|
|
27902
|
-
|
|
27903
|
-
|
|
27904
|
-
|
|
27905
|
-
|
|
27906
|
-
|
|
27907
|
-
|
|
27908
|
-
|
|
27909
|
-
|
|
27910
|
-
|
|
27911
|
-
|
|
27912
|
-
|
|
27913
|
-
|
|
28088
|
+
function getInteractiveLegendConfig({ highlightItem, unHighlightItems, toggleDataVisibility }) {
|
|
28089
|
+
return {
|
|
28090
|
+
onHover: (event, item, legend) => {
|
|
28091
|
+
if (!item.hidden) {
|
|
28092
|
+
const datasets = legend.chart.data.datasets;
|
|
28093
|
+
highlightItem(item, datasets);
|
|
28094
|
+
legend.chart.update();
|
|
28095
|
+
}
|
|
28096
|
+
const target = event.native?.target;
|
|
28097
|
+
if (target && target instanceof HTMLElement) target.style.cursor = "pointer";
|
|
28098
|
+
},
|
|
28099
|
+
onLeave: (event, item, legend) => {
|
|
28100
|
+
if (!item.hidden) {
|
|
28101
|
+
const datasets = legend.chart.data.datasets;
|
|
28102
|
+
unHighlightItems(datasets);
|
|
28103
|
+
legend.chart.update();
|
|
28104
|
+
}
|
|
28105
|
+
const target = event.native?.target;
|
|
28106
|
+
if (target && target instanceof HTMLElement) target.style.cursor = "default";
|
|
28107
|
+
},
|
|
28108
|
+
onClick: (event, item, legend) => {
|
|
28109
|
+
if (event.type !== "click" || !legend.legendItems) return;
|
|
28110
|
+
if (legend.chart.options.animation) legend.chart.options.animation = false;
|
|
28111
|
+
toggleDataVisibility(legend.chart, item);
|
|
28112
|
+
if (!item.hidden) unHighlightItems(legend.chart.data.datasets);
|
|
28113
|
+
else highlightItem(item, legend.chart.data.datasets);
|
|
28114
|
+
legend.chart.update();
|
|
28115
|
+
event.native.preventDefault();
|
|
28116
|
+
event.native.stopPropagation();
|
|
28117
|
+
}
|
|
28118
|
+
};
|
|
28119
|
+
}
|
|
27914
28120
|
const INTERACTIVE_LEGEND_CONFIG_FOR_BUBBLE_CHART = {
|
|
27915
|
-
...
|
|
28121
|
+
...getInteractiveLegendConfig({
|
|
28122
|
+
highlightItem: highlightLineChartItem,
|
|
28123
|
+
unHighlightItems: resetLineChartHighlights,
|
|
28124
|
+
toggleDataVisibility: toggleLineBarDataVisibility
|
|
28125
|
+
}),
|
|
27916
28126
|
onClick: (event, legendItem, legend) => {
|
|
27917
28127
|
if (event.type !== "click") return;
|
|
27918
28128
|
const index = legendItem.datasetIndex;
|
|
@@ -27979,6 +28189,37 @@ function getBubbleChartLegendLabels(fontColor, legendLabelConfig, labels) {
|
|
|
27979
28189
|
filter: (legendItem, data) => true
|
|
27980
28190
|
} };
|
|
27981
28191
|
}
|
|
28192
|
+
function getScatterPlotLegendLabels(fontColor, legendLabelConfig) {
|
|
28193
|
+
return { labels: {
|
|
28194
|
+
color: fontColor,
|
|
28195
|
+
usePointStyle: true,
|
|
28196
|
+
generateLabels: (chart) => chart.data.datasets.map((dataset, index) => {
|
|
28197
|
+
if (isTrendLineAxis(dataset["xAxisID"])) return {
|
|
28198
|
+
text: truncateLabel(dataset.label),
|
|
28199
|
+
fontColor,
|
|
28200
|
+
strokeStyle: dataset.borderColor,
|
|
28201
|
+
hidden: !chart.isDatasetVisible(index),
|
|
28202
|
+
pointStyle: "line",
|
|
28203
|
+
datasetIndex: index,
|
|
28204
|
+
lineWidth: 3
|
|
28205
|
+
};
|
|
28206
|
+
return {
|
|
28207
|
+
text: truncateLabel(dataset.label),
|
|
28208
|
+
fontColor,
|
|
28209
|
+
strokeStyle: dataset.borderColor,
|
|
28210
|
+
fillStyle: dataset["pointBackgroundColor"],
|
|
28211
|
+
hidden: !chart.isDatasetVisible(index),
|
|
28212
|
+
pointStyle: "circle",
|
|
28213
|
+
datasetIndex: index,
|
|
28214
|
+
lineWidth: 8,
|
|
28215
|
+
...legendLabelConfig
|
|
28216
|
+
};
|
|
28217
|
+
}).filter((label) => label.text),
|
|
28218
|
+
filter: (legendItem, data) => {
|
|
28219
|
+
return "datasetIndex" in legendItem ? !data.datasets[legendItem.datasetIndex].hidden : true;
|
|
28220
|
+
}
|
|
28221
|
+
} };
|
|
28222
|
+
}
|
|
27982
28223
|
|
|
27983
28224
|
//#endregion
|
|
27984
28225
|
//#region src/types/chart/sunburst_chart.ts
|
|
@@ -29618,11 +29859,12 @@ const ChartRangeDataSourceHandler = {
|
|
|
29618
29859
|
type: "range",
|
|
29619
29860
|
dataSets: [],
|
|
29620
29861
|
dataSetsHaveTitle: false,
|
|
29862
|
+
labelRange: context.auxiliaryRange,
|
|
29621
29863
|
...context.dataSource
|
|
29622
29864
|
};
|
|
29623
29865
|
},
|
|
29624
29866
|
fromHierarchicalContextCreation(context) {
|
|
29625
|
-
if (context.dataSource?.type !== "range" || context.hierarchicalDataSource
|
|
29867
|
+
if (context.dataSource?.type !== "range" || context.hierarchicalDataSource !== void 0 && context.hierarchicalDataSource.type !== "range") return {
|
|
29626
29868
|
type: "range",
|
|
29627
29869
|
dataSets: [],
|
|
29628
29870
|
dataSetsHaveTitle: false
|
|
@@ -37614,7 +37856,7 @@ function getVisiblePivotCellPositions(getters, pivotId) {
|
|
|
37614
37856
|
col,
|
|
37615
37857
|
row
|
|
37616
37858
|
};
|
|
37617
|
-
if (
|
|
37859
|
+
if (getters.getPivotIdsFromPosition(position).includes(pivotId)) positions.push(position);
|
|
37618
37860
|
}
|
|
37619
37861
|
return positions;
|
|
37620
37862
|
}
|
|
@@ -39688,6 +39930,9 @@ const PIVOT_FUNCTIONS = [
|
|
|
39688
39930
|
function getFirstPivotFunction(compiledFormula, getters) {
|
|
39689
39931
|
return compiledFormula.getFunctionsFromTokens(PIVOT_FUNCTIONS, getters)[0];
|
|
39690
39932
|
}
|
|
39933
|
+
function getPivotFunctions(compiledFormula, getters) {
|
|
39934
|
+
return compiledFormula.getFunctionsFromTokens(PIVOT_FUNCTIONS, getters);
|
|
39935
|
+
}
|
|
39691
39936
|
/**
|
|
39692
39937
|
* Parse a spreadsheet formula and detect the number of PIVOT functions that are
|
|
39693
39938
|
* present in the given formula.
|
|
@@ -49291,6 +49536,7 @@ var helpers_index_exports = /* @__PURE__ */ __exportAll({
|
|
|
49291
49536
|
getPieChartLegend: () => getPieChartLegend,
|
|
49292
49537
|
getPieChartTooltip: () => getPieChartTooltip,
|
|
49293
49538
|
getPyramidChartData: () => getPyramidChartData,
|
|
49539
|
+
getPyramidChartLegend: () => getPyramidChartLegend,
|
|
49294
49540
|
getPyramidChartScales: () => getPyramidChartScales,
|
|
49295
49541
|
getPyramidChartShowValues: () => getPyramidChartShowValues,
|
|
49296
49542
|
getPyramidChartTooltip: () => getPyramidChartTooltip,
|
|
@@ -58154,6 +58400,7 @@ var PivotUIPlugin = class extends CoreViewPlugin {
|
|
|
58154
58400
|
"getFirstPivotFunction",
|
|
58155
58401
|
"getPivotCellSortDirection",
|
|
58156
58402
|
"getPivotIdFromPosition",
|
|
58403
|
+
"getPivotIdsFromPosition",
|
|
58157
58404
|
"getPivotCellFromPosition",
|
|
58158
58405
|
"generateNewCalculatedMeasureName",
|
|
58159
58406
|
"isPivotUnused",
|
|
@@ -58213,37 +58460,52 @@ var PivotUIPlugin = class extends CoreViewPlugin {
|
|
|
58213
58460
|
}
|
|
58214
58461
|
}
|
|
58215
58462
|
/**
|
|
58216
|
-
* Get the id of the pivot at the given position. Returns undefined if there
|
|
58463
|
+
* Get the id of the first pivot in the formula at the given position. Returns undefined if there
|
|
58217
58464
|
* is no pivot at this position
|
|
58218
58465
|
*/
|
|
58219
58466
|
getPivotIdFromPosition(position) {
|
|
58467
|
+
return this.getPivotIdsFromPosition(position)[0];
|
|
58468
|
+
}
|
|
58469
|
+
/**
|
|
58470
|
+
* Get all of the ids of the pivot present in the formula at the given position.
|
|
58471
|
+
*/
|
|
58472
|
+
getPivotIdsFromPosition(position) {
|
|
58220
58473
|
const cell = this.getters.getCorrespondingFormulaCell(position);
|
|
58221
|
-
if (cell && cell.isFormula)
|
|
58222
|
-
|
|
58223
|
-
|
|
58224
|
-
|
|
58225
|
-
|
|
58226
|
-
|
|
58227
|
-
|
|
58474
|
+
if (cell && cell.isFormula) return this.getPivotIdsFromFormula(position.sheetId, cell.compiledFormula);
|
|
58475
|
+
return [];
|
|
58476
|
+
}
|
|
58477
|
+
getPivotIdsFromFormula(sheetId, formula) {
|
|
58478
|
+
return this.getPivotFunctions(sheetId, formula).map((pivotFunction) => {
|
|
58479
|
+
const pivotId = pivotFunction.args[0]?.toString();
|
|
58480
|
+
return pivotId && this.getters.getPivotId(pivotId);
|
|
58481
|
+
}).filter(isDefined);
|
|
58228
58482
|
}
|
|
58229
58483
|
isSpillPivotFormula(position) {
|
|
58230
58484
|
const cell = this.getters.getCorrespondingFormulaCell(position);
|
|
58231
58485
|
if (cell && cell.isFormula) return this.getFirstPivotFunction(position.sheetId, cell.compiledFormula)?.functionName === "PIVOT";
|
|
58232
58486
|
return false;
|
|
58233
58487
|
}
|
|
58234
|
-
|
|
58235
|
-
const
|
|
58236
|
-
if (!
|
|
58237
|
-
const
|
|
58238
|
-
|
|
58239
|
-
functionName,
|
|
58240
|
-
|
|
58488
|
+
getPivotFunctions(sheetId, formula) {
|
|
58489
|
+
const pivotFunctions = getPivotFunctions(formula, this.getters);
|
|
58490
|
+
if (!pivotFunctions.length) return [];
|
|
58491
|
+
const evaluatedPivotFunctions = [];
|
|
58492
|
+
for (const pivotFunction of pivotFunctions) {
|
|
58493
|
+
const { functionName, args } = pivotFunction;
|
|
58494
|
+
const evaluatedArgs = args.map((argAst) => {
|
|
58241
58495
|
if (argAst.type === "EMPTY") return;
|
|
58242
58496
|
else if (argAst.type === "STRING" || argAst.type === "BOOLEAN" || argAst.type === "NUMBER") return argAst.value;
|
|
58243
58497
|
const argsString = astToFormula(argAst);
|
|
58244
58498
|
return this.getters.evaluateFormula(sheetId, argsString);
|
|
58245
|
-
})
|
|
58246
|
-
|
|
58499
|
+
});
|
|
58500
|
+
evaluatedPivotFunctions.push({
|
|
58501
|
+
functionName,
|
|
58502
|
+
args: evaluatedArgs
|
|
58503
|
+
});
|
|
58504
|
+
}
|
|
58505
|
+
return evaluatedPivotFunctions;
|
|
58506
|
+
}
|
|
58507
|
+
getFirstPivotFunction(sheetId, formula) {
|
|
58508
|
+
return this.getPivotFunctions(sheetId, formula)[0];
|
|
58247
58509
|
}
|
|
58248
58510
|
/**
|
|
58249
58511
|
* Returns the domain args of a pivot formula from a position.
|
|
@@ -58349,8 +58611,8 @@ var PivotUIPlugin = class extends CoreViewPlugin {
|
|
|
58349
58611
|
const unusedPivots = new Set(this.getters.getPivotIds());
|
|
58350
58612
|
for (const sheetId of this.getters.getSheetIds()) for (const cell of this.getters.getCells(sheetId)) {
|
|
58351
58613
|
const position = this.getters.getCellPosition(cell.id);
|
|
58352
|
-
const
|
|
58353
|
-
|
|
58614
|
+
const pivotIds = this.getPivotIdsFromPosition(position);
|
|
58615
|
+
for (const pivotId of pivotIds) {
|
|
58354
58616
|
unusedPivots.delete(pivotId);
|
|
58355
58617
|
if (!unusedPivots.size) {
|
|
58356
58618
|
this.unusedPivotsInFormulas = [];
|
|
@@ -58358,6 +58620,21 @@ var PivotUIPlugin = class extends CoreViewPlugin {
|
|
|
58358
58620
|
}
|
|
58359
58621
|
}
|
|
58360
58622
|
}
|
|
58623
|
+
for (const pivotId of this.getters.getPivotIds()) {
|
|
58624
|
+
const pivot = this.getters.getPivot(pivotId);
|
|
58625
|
+
for (const measure of pivot.definition.measures) if (measure.computedBy) {
|
|
58626
|
+
const { sheetId } = measure.computedBy;
|
|
58627
|
+
const formula = this.getters.getMeasureCompiledFormula(pivotId, measure);
|
|
58628
|
+
const relatedPivotIds = this.getPivotIdsFromFormula(sheetId, formula);
|
|
58629
|
+
for (const relatedPivotId of relatedPivotIds) {
|
|
58630
|
+
unusedPivots.delete(relatedPivotId);
|
|
58631
|
+
if (!unusedPivots.size) {
|
|
58632
|
+
this.unusedPivotsInFormulas = [];
|
|
58633
|
+
return [];
|
|
58634
|
+
}
|
|
58635
|
+
}
|
|
58636
|
+
}
|
|
58637
|
+
}
|
|
58361
58638
|
this.unusedPivotsInFormulas = [...unusedPivots];
|
|
58362
58639
|
return this.unusedPivotsInFormulas;
|
|
58363
58640
|
}
|
|
@@ -63034,12 +63311,13 @@ var CarouselUIPlugin = class extends UIPlugin {
|
|
|
63034
63311
|
const chartId = this.getChartIdFromFigureId(chartFigureId);
|
|
63035
63312
|
if (!chartId) return;
|
|
63036
63313
|
const carousel = this.getters.getCarousel(figureId);
|
|
63314
|
+
const newItem = {
|
|
63315
|
+
type: "chart",
|
|
63316
|
+
chartId
|
|
63317
|
+
};
|
|
63037
63318
|
const definition = {
|
|
63038
63319
|
...carousel,
|
|
63039
|
-
items: [...carousel.items,
|
|
63040
|
-
type: "chart",
|
|
63041
|
-
chartId
|
|
63042
|
-
}]
|
|
63320
|
+
items: [...carousel.items, newItem]
|
|
63043
63321
|
};
|
|
63044
63322
|
this.dispatch("UPDATE_CAROUSEL", {
|
|
63045
63323
|
sheetId,
|
|
@@ -63056,6 +63334,11 @@ var CarouselUIPlugin = class extends UIPlugin {
|
|
|
63056
63334
|
sheetId,
|
|
63057
63335
|
figureId: chartFigureId
|
|
63058
63336
|
});
|
|
63337
|
+
this.dispatch("UPDATE_CAROUSEL_ACTIVE_ITEM", {
|
|
63338
|
+
figureId,
|
|
63339
|
+
sheetId,
|
|
63340
|
+
item: newItem
|
|
63341
|
+
});
|
|
63059
63342
|
}
|
|
63060
63343
|
duplicateCarouselChart({ carouselId, chartId, sheetId, duplicatedChartId }) {
|
|
63061
63344
|
const chart = this.getters.getChart(chartId);
|
|
@@ -77397,7 +77680,7 @@ const PyramidChart = {
|
|
|
77397
77680
|
scales: getPyramidChartScales(definition, chartData),
|
|
77398
77681
|
plugins: {
|
|
77399
77682
|
title: getChartTitle(definition, getters),
|
|
77400
|
-
legend:
|
|
77683
|
+
legend: getPyramidChartLegend(definition, chartData),
|
|
77401
77684
|
tooltip: getPyramidChartTooltip(definition, chartData),
|
|
77402
77685
|
chartShowValuesPlugin: getPyramidChartShowValues(definition, chartData),
|
|
77403
77686
|
background: { color: chartData.background }
|
|
@@ -85874,7 +86157,8 @@ const constants = {
|
|
|
85874
86157
|
FIGURE_ID_SPLITTER: "??",
|
|
85875
86158
|
GRID_ICON_EDGE_LENGTH: 17,
|
|
85876
86159
|
GRID_ICON_MARGIN: 2,
|
|
85877
|
-
CHART_TYPES
|
|
86160
|
+
CHART_TYPES,
|
|
86161
|
+
DARK_MODE_FILTER_STRING
|
|
85878
86162
|
};
|
|
85879
86163
|
const chartHelpers = {
|
|
85880
86164
|
...helpers_index_exports$1,
|
|
@@ -85975,6 +86259,6 @@ exports.stores = stores;
|
|
|
85975
86259
|
exports.tokenColors = tokenColors;
|
|
85976
86260
|
exports.tokenize = tokenize;
|
|
85977
86261
|
|
|
85978
|
-
__info__.version = "19.4.0-alpha.
|
|
85979
|
-
__info__.date = "2026-05-
|
|
85980
|
-
__info__.hash = "
|
|
86262
|
+
__info__.version = "19.4.0-alpha.7";
|
|
86263
|
+
__info__.date = "2026-05-20T14:40:27.236Z";
|
|
86264
|
+
__info__.hash = "7ee566f";
|