@odoo/o-spreadsheet 17.2.7 → 17.2.9
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.js +367 -217
- package/dist/o-spreadsheet.d.ts +90 -85
- package/dist/o-spreadsheet.esm.js +368 -218
- package/dist/o-spreadsheet.iife.js +367 -217
- package/dist/o-spreadsheet.iife.min.js +286 -286
- package/dist/o_spreadsheet.xml +3 -3
- package/package.json +2 -2
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
5
5
|
* @see https://github.com/odoo/o-spreadsheet
|
|
6
|
-
* @version 17.2.
|
|
7
|
-
* @date 2024-
|
|
8
|
-
* @hash
|
|
6
|
+
* @version 17.2.9
|
|
7
|
+
* @date 2024-06-03T14:56:21.684Z
|
|
8
|
+
* @hash 086af6d
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
'use strict';
|
|
@@ -504,6 +504,26 @@ function debounce(func, wait, immediate) {
|
|
|
504
504
|
};
|
|
505
505
|
return debounced;
|
|
506
506
|
}
|
|
507
|
+
/**
|
|
508
|
+
* Creates a batched version of a callback so that all calls to it in the same
|
|
509
|
+
* microtick will only call the original callback once.
|
|
510
|
+
*
|
|
511
|
+
* @param callback the callback to batch
|
|
512
|
+
* @returns a batched version of the original callback
|
|
513
|
+
*
|
|
514
|
+
* Copied from odoo/owl repo.
|
|
515
|
+
*/
|
|
516
|
+
function batched(callback) {
|
|
517
|
+
let scheduled = false;
|
|
518
|
+
return async (...args) => {
|
|
519
|
+
if (!scheduled) {
|
|
520
|
+
scheduled = true;
|
|
521
|
+
await Promise.resolve();
|
|
522
|
+
scheduled = false;
|
|
523
|
+
callback(...args);
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
}
|
|
507
527
|
/*
|
|
508
528
|
* Concatenate an array of strings.
|
|
509
529
|
*/
|
|
@@ -578,8 +598,9 @@ function deepEquals(o1, o2, ignoreFunctions) {
|
|
|
578
598
|
return false;
|
|
579
599
|
}
|
|
580
600
|
else {
|
|
581
|
-
if (ignoreFunctions && typeOfO1Key === "function")
|
|
582
|
-
|
|
601
|
+
if (ignoreFunctions && typeOfO1Key === "function") {
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
583
604
|
if (o1[key] !== o2[key])
|
|
584
605
|
return false;
|
|
585
606
|
}
|
|
@@ -1830,7 +1851,7 @@ class LazyTranslatedString extends String {
|
|
|
1830
1851
|
}
|
|
1831
1852
|
valueOf() {
|
|
1832
1853
|
const str = super.valueOf();
|
|
1833
|
-
return _loaded() ? sprintf(_translate(str), ...this.values) : str;
|
|
1854
|
+
return _loaded() ? sprintf(_translate(str), ...this.values) : sprintf(str, ...this.values);
|
|
1834
1855
|
}
|
|
1835
1856
|
toString() {
|
|
1836
1857
|
return this.valueOf();
|
|
@@ -2639,7 +2660,7 @@ function evaluatePredicate(value, criterion) {
|
|
|
2639
2660
|
return false;
|
|
2640
2661
|
}
|
|
2641
2662
|
if (typeof operand === "number" && operator === "=") {
|
|
2642
|
-
return toString(
|
|
2663
|
+
return value.toString() === operand.toString();
|
|
2643
2664
|
}
|
|
2644
2665
|
if (operator === "<>" || operator === "=") {
|
|
2645
2666
|
let result;
|
|
@@ -2699,14 +2720,13 @@ function visitMatchingRanges(args, cb, locale, isQuery = false) {
|
|
|
2699
2720
|
if (countArg % 2 === 1) {
|
|
2700
2721
|
throw new EvaluationError(_t("Function [[FUNCTION_NAME]] expects criteria_range and criterion to be in pairs."));
|
|
2701
2722
|
}
|
|
2702
|
-
const
|
|
2703
|
-
const
|
|
2723
|
+
const firstArg = toMatrix(args[0]);
|
|
2724
|
+
const dimRow = firstArg.length;
|
|
2725
|
+
const dimCol = firstArg[0].length;
|
|
2704
2726
|
let predicates = [];
|
|
2705
2727
|
for (let i = 0; i < countArg - 1; i += 2) {
|
|
2706
|
-
const criteriaRange = args[i];
|
|
2707
|
-
if (
|
|
2708
|
-
criteriaRange.length !== dimRow ||
|
|
2709
|
-
criteriaRange[0].length !== dimCol) {
|
|
2728
|
+
const criteriaRange = toMatrix(args[i]);
|
|
2729
|
+
if (criteriaRange.length !== dimRow || criteriaRange[0].length !== dimCol) {
|
|
2710
2730
|
throw new EvaluationError(_t("Function [[FUNCTION_NAME]] expects criteria_range to have the same dimension"));
|
|
2711
2731
|
}
|
|
2712
2732
|
const description = toString(args[i + 1]);
|
|
@@ -2720,7 +2740,7 @@ function visitMatchingRanges(args, cb, locale, isQuery = false) {
|
|
|
2720
2740
|
for (let j = 0; j < dimCol; j++) {
|
|
2721
2741
|
let validatedPredicates = true;
|
|
2722
2742
|
for (let k = 0; k < countArg - 1; k += 2) {
|
|
2723
|
-
const criteriaValue = args[k][i][j].value;
|
|
2743
|
+
const criteriaValue = toMatrix(args[k])[i][j].value;
|
|
2724
2744
|
const criterion = predicates[k / 2];
|
|
2725
2745
|
validatedPredicates = evaluatePredicate(criteriaValue ?? undefined, criterion);
|
|
2726
2746
|
if (!validatedPredicates) {
|
|
@@ -4437,8 +4457,11 @@ function copyRangeWithNewSheetId(sheetIdFrom, sheetIdTo, range) {
|
|
|
4437
4457
|
/**
|
|
4438
4458
|
* Create a range from a xc. If the xc is empty, this function returns undefined.
|
|
4439
4459
|
*/
|
|
4440
|
-
function
|
|
4441
|
-
|
|
4460
|
+
function createValidRange(getters, sheetId, xc) {
|
|
4461
|
+
if (!xc)
|
|
4462
|
+
return;
|
|
4463
|
+
const range = getters.getRangeFromSheetXC(sheetId, xc);
|
|
4464
|
+
return !(range.invalidSheetName || range.invalidXc) ? range : undefined;
|
|
4442
4465
|
}
|
|
4443
4466
|
/**
|
|
4444
4467
|
* Spread multiple colrows zone to one row/col zone and add a many new input range as needed.
|
|
@@ -8014,10 +8037,66 @@ function getDateCriterionFormattedValues(criterion, getters) {
|
|
|
8014
8037
|
});
|
|
8015
8038
|
}
|
|
8016
8039
|
|
|
8040
|
+
/**
|
|
8041
|
+
* This is a generic event bus based on the Owl event bus.
|
|
8042
|
+
* This bus however ensures type safety across events and subscription callbacks.
|
|
8043
|
+
*/
|
|
8044
|
+
class EventBus {
|
|
8045
|
+
subscriptions = {};
|
|
8046
|
+
/**
|
|
8047
|
+
* Add a listener for the 'eventType' events.
|
|
8048
|
+
*
|
|
8049
|
+
* Note that the 'owner' of this event can be anything, but will more likely
|
|
8050
|
+
* be a component or a class. The idea is that the callback will be called with
|
|
8051
|
+
* the proper owner bound.
|
|
8052
|
+
*
|
|
8053
|
+
* Also, the owner should be kind of unique. This will be used to remove the
|
|
8054
|
+
* listener.
|
|
8055
|
+
*/
|
|
8056
|
+
on(type, owner, callback) {
|
|
8057
|
+
if (!callback) {
|
|
8058
|
+
throw new Error("Missing callback");
|
|
8059
|
+
}
|
|
8060
|
+
if (!this.subscriptions[type]) {
|
|
8061
|
+
this.subscriptions[type] = [];
|
|
8062
|
+
}
|
|
8063
|
+
this.subscriptions[type].push({
|
|
8064
|
+
owner,
|
|
8065
|
+
callback,
|
|
8066
|
+
});
|
|
8067
|
+
}
|
|
8068
|
+
/**
|
|
8069
|
+
* Emit an event of type 'eventType'. Any extra arguments will be passed to
|
|
8070
|
+
* the listeners callback.
|
|
8071
|
+
*/
|
|
8072
|
+
trigger(type, payload) {
|
|
8073
|
+
const subs = this.subscriptions[type] || [];
|
|
8074
|
+
for (let i = 0, iLen = subs.length; i < iLen; i++) {
|
|
8075
|
+
const sub = subs[i];
|
|
8076
|
+
sub.callback.call(sub.owner, payload);
|
|
8077
|
+
}
|
|
8078
|
+
}
|
|
8079
|
+
/**
|
|
8080
|
+
* Remove a listener
|
|
8081
|
+
*/
|
|
8082
|
+
off(eventType, owner) {
|
|
8083
|
+
const subs = this.subscriptions[eventType];
|
|
8084
|
+
if (subs) {
|
|
8085
|
+
this.subscriptions[eventType] = subs.filter((s) => s.owner !== owner);
|
|
8086
|
+
}
|
|
8087
|
+
}
|
|
8088
|
+
/**
|
|
8089
|
+
* Remove all subscriptions.
|
|
8090
|
+
*/
|
|
8091
|
+
clear() {
|
|
8092
|
+
this.subscriptions = {};
|
|
8093
|
+
}
|
|
8094
|
+
}
|
|
8095
|
+
|
|
8017
8096
|
/**
|
|
8018
8097
|
* A type-safe dependency container
|
|
8019
8098
|
*/
|
|
8020
|
-
class DependencyContainer {
|
|
8099
|
+
class DependencyContainer extends EventBus {
|
|
8021
8100
|
dependencies = new Map();
|
|
8022
8101
|
factory = new StoreFactory(this.get.bind(this));
|
|
8023
8102
|
/**
|
|
@@ -8094,15 +8173,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
8094
8173
|
}
|
|
8095
8174
|
return MetaStore;
|
|
8096
8175
|
}
|
|
8097
|
-
class
|
|
8176
|
+
class DisposableStore {
|
|
8098
8177
|
get;
|
|
8178
|
+
disposeCallbacks = [];
|
|
8099
8179
|
constructor(get) {
|
|
8100
8180
|
this.get = get;
|
|
8101
|
-
return owl.reactive(this);
|
|
8102
8181
|
}
|
|
8103
|
-
}
|
|
8104
|
-
class DisposableStore extends ReactiveStore {
|
|
8105
|
-
disposeCallbacks = [];
|
|
8106
8182
|
onDispose(callback) {
|
|
8107
8183
|
this.disposeCallbacks.push(callback);
|
|
8108
8184
|
}
|
|
@@ -8122,7 +8198,10 @@ function useStoreProvider() {
|
|
|
8122
8198
|
const container = new DependencyContainer();
|
|
8123
8199
|
owl.useSubEnv({
|
|
8124
8200
|
__spreadsheet_stores__: container,
|
|
8125
|
-
getStore:
|
|
8201
|
+
getStore: (Store) => {
|
|
8202
|
+
const store = container.get(Store);
|
|
8203
|
+
return proxifyStoreMutation(store, () => container.trigger("store-updated"));
|
|
8204
|
+
},
|
|
8126
8205
|
});
|
|
8127
8206
|
return container;
|
|
8128
8207
|
}
|
|
@@ -8132,14 +8211,57 @@ function useStoreProvider() {
|
|
|
8132
8211
|
function useStore(Store) {
|
|
8133
8212
|
const env = owl.useEnv();
|
|
8134
8213
|
const container = getDependencyContainer(env);
|
|
8135
|
-
|
|
8214
|
+
const store = container.get(Store);
|
|
8215
|
+
return useStoreRenderProxy(container, store);
|
|
8136
8216
|
}
|
|
8137
8217
|
function useLocalStore(Store, ...args) {
|
|
8138
8218
|
const env = owl.useEnv();
|
|
8139
8219
|
const container = getDependencyContainer(env);
|
|
8140
|
-
const store =
|
|
8220
|
+
const store = container.instantiate(Store, ...args);
|
|
8141
8221
|
owl.onWillUnmount(() => store.dispose());
|
|
8142
|
-
return store;
|
|
8222
|
+
return useStoreRenderProxy(container, store);
|
|
8223
|
+
}
|
|
8224
|
+
/**
|
|
8225
|
+
* Trigger an event to re-render the app (deep render) when
|
|
8226
|
+
* a store is mutated by invoking one of its mutator methods.
|
|
8227
|
+
*/
|
|
8228
|
+
function useStoreRenderProxy(container, store) {
|
|
8229
|
+
const component = owl.useComponent();
|
|
8230
|
+
const proxy = proxifyStoreMutation(store, () => {
|
|
8231
|
+
if (owl.status(component) === "mounted") {
|
|
8232
|
+
container.trigger("store-updated");
|
|
8233
|
+
}
|
|
8234
|
+
});
|
|
8235
|
+
return proxy;
|
|
8236
|
+
}
|
|
8237
|
+
/**
|
|
8238
|
+
* Creates a proxied version of a store object with mutation tracking.
|
|
8239
|
+
* Whenever a mutator method of the store is called, the provided callback function is invoked.
|
|
8240
|
+
*/
|
|
8241
|
+
function proxifyStoreMutation(store, callback) {
|
|
8242
|
+
const proxy = new Proxy(store, {
|
|
8243
|
+
get(target, property, receiver) {
|
|
8244
|
+
const thisStore = target;
|
|
8245
|
+
// The third argument is `thisStore` (target) instead of `receiver`.
|
|
8246
|
+
// The goal is to always have the same `this` value in getter functions
|
|
8247
|
+
// (when `target[property]` is an accessor property).
|
|
8248
|
+
// `thisStore` is always the same object reference. `receiver` however is the
|
|
8249
|
+
// object on which the property is called, which is the Proxy object which is different for each component.
|
|
8250
|
+
const value = Reflect.get(target, property, thisStore);
|
|
8251
|
+
if (store.mutators.includes(property)) {
|
|
8252
|
+
const functionProxy = new Proxy(value, {
|
|
8253
|
+
// trap the function call
|
|
8254
|
+
apply(target, thisArg, argArray) {
|
|
8255
|
+
Reflect.apply(target, thisStore, argArray);
|
|
8256
|
+
callback();
|
|
8257
|
+
},
|
|
8258
|
+
});
|
|
8259
|
+
return functionProxy;
|
|
8260
|
+
}
|
|
8261
|
+
return value;
|
|
8262
|
+
},
|
|
8263
|
+
});
|
|
8264
|
+
return proxy;
|
|
8143
8265
|
}
|
|
8144
8266
|
function getDependencyContainer(env) {
|
|
8145
8267
|
const container = env.__spreadsheet_stores__;
|
|
@@ -8151,7 +8273,8 @@ function getDependencyContainer(env) {
|
|
|
8151
8273
|
|
|
8152
8274
|
const ModelStore = createAbstractStore("Model");
|
|
8153
8275
|
|
|
8154
|
-
class RendererStore
|
|
8276
|
+
class RendererStore {
|
|
8277
|
+
mutators = ["register", "unRegister"];
|
|
8155
8278
|
renderers = {};
|
|
8156
8279
|
register(renderer) {
|
|
8157
8280
|
if (!renderer.renderingLayers.length) {
|
|
@@ -8185,7 +8308,7 @@ class RendererStore extends ReactiveStore {
|
|
|
8185
8308
|
class SpreadsheetStore extends DisposableStore {
|
|
8186
8309
|
// cast the model store as Model to allow model.dispatch to return the DispatchResult
|
|
8187
8310
|
model = this.get(ModelStore);
|
|
8188
|
-
getters =
|
|
8311
|
+
getters = this.model.getters;
|
|
8189
8312
|
renderer = this.get(RendererStore);
|
|
8190
8313
|
constructor(get) {
|
|
8191
8314
|
super(get);
|
|
@@ -8232,6 +8355,7 @@ function drawHighlight(renderingContext, highlight, rect) {
|
|
|
8232
8355
|
}
|
|
8233
8356
|
|
|
8234
8357
|
class HighlightStore extends SpreadsheetStore {
|
|
8358
|
+
mutators = ["register", "unRegister"];
|
|
8235
8359
|
providers = [];
|
|
8236
8360
|
constructor(get) {
|
|
8237
8361
|
super(get);
|
|
@@ -8262,7 +8386,7 @@ class HighlightStore extends SpreadsheetStore {
|
|
|
8262
8386
|
this.providers.push(highlightProvider);
|
|
8263
8387
|
}
|
|
8264
8388
|
unRegister(highlightProvider) {
|
|
8265
|
-
this.providers = this.providers.filter((h) =>
|
|
8389
|
+
this.providers = this.providers.filter((h) => h !== highlightProvider);
|
|
8266
8390
|
}
|
|
8267
8391
|
drawLayer(ctx, layer) {
|
|
8268
8392
|
if (layer === "Highlights") {
|
|
@@ -8278,6 +8402,16 @@ const NotificationStore = createAbstractStore("Notifications");
|
|
|
8278
8402
|
|
|
8279
8403
|
const CELL_DELETED_MESSAGE = _t("The cell you are trying to edit has been deleted.");
|
|
8280
8404
|
class ComposerStore extends SpreadsheetStore {
|
|
8405
|
+
mutators = [
|
|
8406
|
+
"startEdition",
|
|
8407
|
+
"setCurrentContent",
|
|
8408
|
+
"stopEdition",
|
|
8409
|
+
"stopComposerRangeSelection",
|
|
8410
|
+
"cancelEdition",
|
|
8411
|
+
"cycleReferences",
|
|
8412
|
+
"changeComposerCursorSelection",
|
|
8413
|
+
"replaceComposerCursorSelection",
|
|
8414
|
+
];
|
|
8281
8415
|
col = 0;
|
|
8282
8416
|
row = 0;
|
|
8283
8417
|
editionMode = "inactive";
|
|
@@ -8292,9 +8426,9 @@ class ComposerStore extends SpreadsheetStore {
|
|
|
8292
8426
|
highlightStore = this.get(HighlightStore);
|
|
8293
8427
|
constructor(get) {
|
|
8294
8428
|
super(get);
|
|
8295
|
-
this.highlightStore.register(
|
|
8429
|
+
this.highlightStore.register(this);
|
|
8296
8430
|
this.onDispose(() => {
|
|
8297
|
-
this.highlightStore.unRegister(
|
|
8431
|
+
this.highlightStore.unRegister(this);
|
|
8298
8432
|
});
|
|
8299
8433
|
}
|
|
8300
8434
|
canStopEdition() {
|
|
@@ -8421,7 +8555,7 @@ class ComposerStore extends SpreadsheetStore {
|
|
|
8421
8555
|
if (this.isSelectingRange) {
|
|
8422
8556
|
this.editionMode = "editing";
|
|
8423
8557
|
}
|
|
8424
|
-
this.model.selection.resetAnchor(
|
|
8558
|
+
this.model.selection.resetAnchor(this, {
|
|
8425
8559
|
cell: { col: left, row: top },
|
|
8426
8560
|
zone: cmd.zone,
|
|
8427
8561
|
});
|
|
@@ -8439,7 +8573,7 @@ class ComposerStore extends SpreadsheetStore {
|
|
|
8439
8573
|
row: activePosition.row,
|
|
8440
8574
|
});
|
|
8441
8575
|
const zone = this.getters.expandZone(cmd.sheetIdTo, positionToZone({ col, row }));
|
|
8442
|
-
this.model.selection.resetAnchor(
|
|
8576
|
+
this.model.selection.resetAnchor(this, { cell: { col, row }, zone });
|
|
8443
8577
|
}
|
|
8444
8578
|
break;
|
|
8445
8579
|
case "DELETE_SHEET":
|
|
@@ -8538,7 +8672,7 @@ class ComposerStore extends SpreadsheetStore {
|
|
|
8538
8672
|
startComposerRangeSelection() {
|
|
8539
8673
|
if (this.sheetId === this.getters.getActiveSheetId()) {
|
|
8540
8674
|
const zone = positionToZone({ col: this.col, row: this.row });
|
|
8541
|
-
this.model.selection.resetAnchor(
|
|
8675
|
+
this.model.selection.resetAnchor(this, {
|
|
8542
8676
|
cell: { col: this.col, row: this.row },
|
|
8543
8677
|
zone,
|
|
8544
8678
|
});
|
|
@@ -8567,7 +8701,7 @@ class ComposerStore extends SpreadsheetStore {
|
|
|
8567
8701
|
this.setContent(str || this.initialContent, selection);
|
|
8568
8702
|
this.colorIndexByRange = {};
|
|
8569
8703
|
const zone = positionToZone({ col: this.col, row: this.row });
|
|
8570
|
-
this.model.selection.capture(
|
|
8704
|
+
this.model.selection.capture(this, { cell: { col: this.col, row: this.row }, zone }, {
|
|
8571
8705
|
handleEvent: this.handleEvent.bind(this),
|
|
8572
8706
|
release: () => {
|
|
8573
8707
|
this._stopEdition();
|
|
@@ -8675,7 +8809,7 @@ class ComposerStore extends SpreadsheetStore {
|
|
|
8675
8809
|
return;
|
|
8676
8810
|
}
|
|
8677
8811
|
this.editionMode = "inactive";
|
|
8678
|
-
this.model.selection.release(
|
|
8812
|
+
this.model.selection.release(this);
|
|
8679
8813
|
}
|
|
8680
8814
|
/**
|
|
8681
8815
|
* Reset the current content to the active cell content
|
|
@@ -8997,6 +9131,7 @@ class ComposerStore extends SpreadsheetStore {
|
|
|
8997
9131
|
}
|
|
8998
9132
|
|
|
8999
9133
|
class ComposerFocusStore extends SpreadsheetStore {
|
|
9134
|
+
mutators = ["focusTopBarComposer", "focusGridComposerContent", "focusGridComposerCell"];
|
|
9000
9135
|
composerStore = this.get(ComposerStore);
|
|
9001
9136
|
topBarFocus = "inactive";
|
|
9002
9137
|
gridFocusMode = "inactive";
|
|
@@ -9513,8 +9648,8 @@ let ScorecardChart$1 = class ScorecardChart extends AbstractChart {
|
|
|
9513
9648
|
type = "scorecard";
|
|
9514
9649
|
constructor(definition, sheetId, getters) {
|
|
9515
9650
|
super(definition, sheetId, getters);
|
|
9516
|
-
this.keyValue =
|
|
9517
|
-
this.baseline =
|
|
9651
|
+
this.keyValue = createValidRange(getters, sheetId, definition.keyValue);
|
|
9652
|
+
this.baseline = createValidRange(getters, sheetId, definition.baseline);
|
|
9518
9653
|
this.baselineMode = definition.baselineMode;
|
|
9519
9654
|
this.baselineDescr = definition.baselineDescr;
|
|
9520
9655
|
this.background = definition.background;
|
|
@@ -10084,6 +10219,9 @@ function makeArg(str, description) {
|
|
|
10084
10219
|
if (types.some((t) => t.startsWith("RANGE"))) {
|
|
10085
10220
|
result.acceptMatrix = true;
|
|
10086
10221
|
}
|
|
10222
|
+
if (types.every((t) => t.startsWith("RANGE"))) {
|
|
10223
|
+
result.acceptMatrixOnly = true;
|
|
10224
|
+
}
|
|
10087
10225
|
return result;
|
|
10088
10226
|
}
|
|
10089
10227
|
/**
|
|
@@ -10365,11 +10503,16 @@ const CHOOSECOLS = {
|
|
|
10365
10503
|
compute: function (array, ...columns) {
|
|
10366
10504
|
const _array = toMatrix(array);
|
|
10367
10505
|
const _columns = flattenRowFirst(columns, (item) => toInteger(item?.value, this.locale));
|
|
10368
|
-
|
|
10506
|
+
const argOutOfRange = _columns.filter((col) => col === 0 || _array.length < Math.abs(col));
|
|
10507
|
+
assert(() => argOutOfRange.length === 0, _t("The columns arguments must be between -%s and %s (got %s), excluding 0.", _array.length.toString(), _array.length.toString(), argOutOfRange.join(",")));
|
|
10369
10508
|
const result = Array(_columns.length);
|
|
10370
10509
|
for (let col = 0; col < _columns.length; col++) {
|
|
10371
|
-
|
|
10372
|
-
|
|
10510
|
+
if (_columns[col] > 0) {
|
|
10511
|
+
result[col] = _array[_columns[col] - 1]; // -1 because columns arguments are 1-indexed
|
|
10512
|
+
}
|
|
10513
|
+
else {
|
|
10514
|
+
result[col] = _array[_array.length + _columns[col]];
|
|
10515
|
+
}
|
|
10373
10516
|
}
|
|
10374
10517
|
return result;
|
|
10375
10518
|
},
|
|
@@ -10390,8 +10533,14 @@ const CHOOSEROWS = {
|
|
|
10390
10533
|
const _array = toMatrix(array);
|
|
10391
10534
|
const _rows = flattenRowFirst(rows, (item) => toInteger(item?.value, this.locale));
|
|
10392
10535
|
const _nbColumns = _array.length;
|
|
10393
|
-
|
|
10394
|
-
|
|
10536
|
+
const argOutOfRange = _rows.filter((row) => row === 0 || _array[0].length < Math.abs(row));
|
|
10537
|
+
assert(() => argOutOfRange.length === 0, _t("The rows arguments must be between -%s and %s (got %s), excluding 0.", _array[0].length.toString(), _array[0].length.toString(), argOutOfRange.join(",")));
|
|
10538
|
+
return generateMatrix(_nbColumns, _rows.length, (col, row) => {
|
|
10539
|
+
if (_rows[row] > 0) {
|
|
10540
|
+
return _array[col][_rows[row] - 1]; // -1 because columns arguments are 1-indexed
|
|
10541
|
+
}
|
|
10542
|
+
return _array[col][_array[col].length + _rows[row]];
|
|
10543
|
+
});
|
|
10395
10544
|
},
|
|
10396
10545
|
isExported: true,
|
|
10397
10546
|
};
|
|
@@ -11299,7 +11448,7 @@ const COUNTUNIQUEIFS = {
|
|
|
11299
11448
|
compute: function (range, ...args) {
|
|
11300
11449
|
let uniqueValues = new Set();
|
|
11301
11450
|
visitMatchingRanges(args, (i, j) => {
|
|
11302
|
-
const data = range[i][j];
|
|
11451
|
+
const data = range[i]?.[j];
|
|
11303
11452
|
if (isDefined(data)) {
|
|
11304
11453
|
uniqueValues.add(data.value);
|
|
11305
11454
|
}
|
|
@@ -11929,7 +12078,7 @@ const SUMIF = {
|
|
|
11929
12078
|
}
|
|
11930
12079
|
let sum = 0;
|
|
11931
12080
|
visitMatchingRanges([criteriaRange, criterion], (i, j) => {
|
|
11932
|
-
const value = sumRange[i][j]
|
|
12081
|
+
const value = sumRange[i]?.[j]?.value;
|
|
11933
12082
|
if (typeof value === "number") {
|
|
11934
12083
|
sum += value;
|
|
11935
12084
|
}
|
|
@@ -11954,7 +12103,7 @@ const SUMIFS = {
|
|
|
11954
12103
|
compute: function (sumRange, ...criters) {
|
|
11955
12104
|
let sum = 0;
|
|
11956
12105
|
visitMatchingRanges(criters, (i, j) => {
|
|
11957
|
-
const value = sumRange[i][j]
|
|
12106
|
+
const value = sumRange[i]?.[j]?.value;
|
|
11958
12107
|
if (typeof value === "number") {
|
|
11959
12108
|
sum += value;
|
|
11960
12109
|
}
|
|
@@ -12501,7 +12650,7 @@ const AVERAGEIF = {
|
|
|
12501
12650
|
let count = 0;
|
|
12502
12651
|
let sum = 0;
|
|
12503
12652
|
visitMatchingRanges([criteriaRange, criterion], (i, j) => {
|
|
12504
|
-
const value = _averageRange[i][j]
|
|
12653
|
+
const value = _averageRange[i]?.[j]?.value;
|
|
12505
12654
|
if (typeof value === "number") {
|
|
12506
12655
|
count += 1;
|
|
12507
12656
|
sum += value;
|
|
@@ -12530,7 +12679,7 @@ const AVERAGEIFS = {
|
|
|
12530
12679
|
let count = 0;
|
|
12531
12680
|
let sum = 0;
|
|
12532
12681
|
visitMatchingRanges(args, (i, j) => {
|
|
12533
|
-
const value = _averageRange[i][j]
|
|
12682
|
+
const value = _averageRange[i]?.[j]?.value;
|
|
12534
12683
|
if (typeof value === "number") {
|
|
12535
12684
|
count += 1;
|
|
12536
12685
|
sum += value;
|
|
@@ -12835,7 +12984,7 @@ const MAXIFS = {
|
|
|
12835
12984
|
compute: function (range, ...args) {
|
|
12836
12985
|
let result = -Infinity;
|
|
12837
12986
|
visitMatchingRanges(args, (i, j) => {
|
|
12838
|
-
const value = range[i][j]
|
|
12987
|
+
const value = range[i]?.[j]?.value;
|
|
12839
12988
|
if (typeof value === "number") {
|
|
12840
12989
|
result = result < value ? value : result;
|
|
12841
12990
|
}
|
|
@@ -12918,7 +13067,7 @@ const MINIFS = {
|
|
|
12918
13067
|
compute: function (range, ...args) {
|
|
12919
13068
|
let result = Infinity;
|
|
12920
13069
|
visitMatchingRanges(args, (i, j) => {
|
|
12921
|
-
const value = range[i][j]
|
|
13070
|
+
const value = range[i]?.[j]?.value;
|
|
12922
13071
|
if (typeof value === "number") {
|
|
12923
13072
|
result = result > value ? value : result;
|
|
12924
13073
|
}
|
|
@@ -18670,6 +18819,9 @@ function addInputHandling(descr) {
|
|
|
18670
18819
|
}
|
|
18671
18820
|
args[i] = arg[0][0];
|
|
18672
18821
|
}
|
|
18822
|
+
if (!isMatrix(arg) && argDefinition.acceptMatrixOnly) {
|
|
18823
|
+
throw new BadExpressionError(_t("Function [[FUNCTION_NAME]] expects the parameter '%s' to be reference to a cell or range.", (i + 1).toString()));
|
|
18824
|
+
}
|
|
18673
18825
|
}
|
|
18674
18826
|
return descr.compute.apply(this, args);
|
|
18675
18827
|
}
|
|
@@ -19672,7 +19824,7 @@ class BarChart extends AbstractChart {
|
|
|
19672
19824
|
constructor(definition, sheetId, getters) {
|
|
19673
19825
|
super(definition, sheetId, getters);
|
|
19674
19826
|
this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
|
|
19675
|
-
this.labelRange =
|
|
19827
|
+
this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
|
|
19676
19828
|
this.background = definition.background;
|
|
19677
19829
|
this.verticalAxisPosition = definition.verticalAxisPosition;
|
|
19678
19830
|
this.legendPosition = definition.legendPosition;
|
|
@@ -19916,7 +20068,7 @@ class GaugeChart extends AbstractChart {
|
|
|
19916
20068
|
type = "gauge";
|
|
19917
20069
|
constructor(definition, sheetId, getters) {
|
|
19918
20070
|
super(definition, sheetId, getters);
|
|
19919
|
-
this.dataRange =
|
|
20071
|
+
this.dataRange = createValidRange(this.getters, this.sheetId, definition.dataRange);
|
|
19920
20072
|
this.sectionRule = definition.sectionRule;
|
|
19921
20073
|
this.background = definition.background;
|
|
19922
20074
|
}
|
|
@@ -20437,7 +20589,7 @@ class LineChart extends AbstractChart {
|
|
|
20437
20589
|
constructor(definition, sheetId, getters) {
|
|
20438
20590
|
super(definition, sheetId, getters);
|
|
20439
20591
|
this.dataSets = createDataSets(this.getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
|
|
20440
|
-
this.labelRange =
|
|
20592
|
+
this.labelRange = createValidRange(this.getters, sheetId, definition.labelRange);
|
|
20441
20593
|
this.background = definition.background;
|
|
20442
20594
|
this.verticalAxisPosition = definition.verticalAxisPosition;
|
|
20443
20595
|
this.legendPosition = definition.legendPosition;
|
|
@@ -20552,7 +20704,7 @@ class PieChart extends AbstractChart {
|
|
|
20552
20704
|
constructor(definition, sheetId, getters) {
|
|
20553
20705
|
super(definition, sheetId, getters);
|
|
20554
20706
|
this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
|
|
20555
|
-
this.labelRange =
|
|
20707
|
+
this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
|
|
20556
20708
|
this.background = definition.background;
|
|
20557
20709
|
this.legendPosition = definition.legendPosition;
|
|
20558
20710
|
this.aggregated = definition.aggregated;
|
|
@@ -20754,7 +20906,7 @@ class ScatterChart extends AbstractChart {
|
|
|
20754
20906
|
constructor(definition, sheetId, getters) {
|
|
20755
20907
|
super(definition, sheetId, getters);
|
|
20756
20908
|
this.dataSets = createDataSets(this.getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
|
|
20757
|
-
this.labelRange =
|
|
20909
|
+
this.labelRange = createValidRange(this.getters, sheetId, definition.labelRange);
|
|
20758
20910
|
this.background = definition.background;
|
|
20759
20911
|
this.verticalAxisPosition = definition.verticalAxisPosition;
|
|
20760
20912
|
this.legendPosition = definition.legendPosition;
|
|
@@ -20840,13 +20992,6 @@ function createScatterChartRuntime(chart, getters) {
|
|
|
20840
20992
|
// have less options than the line chart (it only works with linear labels)
|
|
20841
20993
|
chartJsConfig.type = "line";
|
|
20842
20994
|
const configOptions = chartJsConfig.options;
|
|
20843
|
-
configOptions.elements = {
|
|
20844
|
-
point: {
|
|
20845
|
-
radius: 3,
|
|
20846
|
-
hoverRadius: 3,
|
|
20847
|
-
hitRadius: 8,
|
|
20848
|
-
},
|
|
20849
|
-
};
|
|
20850
20995
|
const locale = getters.getLocale();
|
|
20851
20996
|
configOptions.plugins.tooltip.callbacks.title = () => "";
|
|
20852
20997
|
configOptions.plugins.tooltip.callbacks.label = (tooltipItem) => {
|
|
@@ -21453,6 +21598,7 @@ function interactiveAddMerge(env, sheetId, target) {
|
|
|
21453
21598
|
}
|
|
21454
21599
|
|
|
21455
21600
|
class HoveredCellStore extends SpreadsheetStore {
|
|
21601
|
+
mutators = ["clear", "hover"];
|
|
21456
21602
|
col;
|
|
21457
21603
|
row;
|
|
21458
21604
|
handle(cmd) {
|
|
@@ -21472,6 +21618,7 @@ class HoveredCellStore extends SpreadsheetStore {
|
|
|
21472
21618
|
}
|
|
21473
21619
|
|
|
21474
21620
|
class CellPopoverStore extends SpreadsheetStore {
|
|
21621
|
+
mutators = ["open", "close"];
|
|
21475
21622
|
persistentPopover;
|
|
21476
21623
|
hoveredCell = this.get(HoveredCellStore);
|
|
21477
21624
|
handle(cmd) {
|
|
@@ -25963,12 +26110,13 @@ function updateSelectionWithArrowKeys(ev, selection) {
|
|
|
25963
26110
|
|
|
25964
26111
|
// The name is misleading and can be confused with the DOM focus.
|
|
25965
26112
|
class FocusStore {
|
|
26113
|
+
mutators = ["focus", "unfocus"];
|
|
25966
26114
|
focusedElement = null;
|
|
25967
26115
|
focus(element) {
|
|
25968
26116
|
this.focusedElement = element;
|
|
25969
26117
|
}
|
|
25970
26118
|
unfocus(element) {
|
|
25971
|
-
if (this.focusedElement &&
|
|
26119
|
+
if (this.focusedElement && this.focusedElement === element) {
|
|
25972
26120
|
this.focusedElement = null;
|
|
25973
26121
|
}
|
|
25974
26122
|
}
|
|
@@ -25984,6 +26132,16 @@ class FocusStore {
|
|
|
25984
26132
|
class SelectionInputStore extends SpreadsheetStore {
|
|
25985
26133
|
initialRanges;
|
|
25986
26134
|
inputHasSingleRange;
|
|
26135
|
+
mutators = [
|
|
26136
|
+
"resetWithRanges",
|
|
26137
|
+
"focusById",
|
|
26138
|
+
"unfocus",
|
|
26139
|
+
"addEmptyRange",
|
|
26140
|
+
"removeRange",
|
|
26141
|
+
"changeRange",
|
|
26142
|
+
"reset",
|
|
26143
|
+
"confirm",
|
|
26144
|
+
];
|
|
25987
26145
|
ranges = [];
|
|
25988
26146
|
focusedRangeIndex = null;
|
|
25989
26147
|
inputSheetId;
|
|
@@ -26043,7 +26201,7 @@ class SelectionInputStore extends SpreadsheetStore {
|
|
|
26043
26201
|
row: 0,
|
|
26044
26202
|
});
|
|
26045
26203
|
const zone = this.getters.expandZone(cmd.sheetIdTo, positionToZone({ col, row }));
|
|
26046
|
-
this.model.selection.resetAnchor(
|
|
26204
|
+
this.model.selection.resetAnchor(this, { cell: { col, row }, zone });
|
|
26047
26205
|
}
|
|
26048
26206
|
break;
|
|
26049
26207
|
}
|
|
@@ -26062,7 +26220,7 @@ class SelectionInputStore extends SpreadsheetStore {
|
|
|
26062
26220
|
if (focusIndex !== -1) {
|
|
26063
26221
|
this.focus(focusIndex);
|
|
26064
26222
|
const { left, top } = newZone;
|
|
26065
|
-
this.model.selection.resetAnchor(
|
|
26223
|
+
this.model.selection.resetAnchor(this, {
|
|
26066
26224
|
cell: { col: left, row: top },
|
|
26067
26225
|
zone: newZone,
|
|
26068
26226
|
});
|
|
@@ -26153,7 +26311,7 @@ class SelectionInputStore extends SpreadsheetStore {
|
|
|
26153
26311
|
}
|
|
26154
26312
|
get hasMainFocus() {
|
|
26155
26313
|
const focusedElement = this.focusStore.focusedElement;
|
|
26156
|
-
return !!focusedElement &&
|
|
26314
|
+
return !!focusedElement && focusedElement === this;
|
|
26157
26315
|
}
|
|
26158
26316
|
get highlights() {
|
|
26159
26317
|
if (!this.hasMainFocus) {
|
|
@@ -26182,7 +26340,7 @@ class SelectionInputStore extends SpreadsheetStore {
|
|
|
26182
26340
|
unfocus() {
|
|
26183
26341
|
this.focusedRangeIndex = null;
|
|
26184
26342
|
this.focusStore.unfocus(this);
|
|
26185
|
-
this.model.selection.release(
|
|
26343
|
+
this.model.selection.release(this);
|
|
26186
26344
|
}
|
|
26187
26345
|
captureSelection() {
|
|
26188
26346
|
if (this.focusedRangeIndex === null) {
|
|
@@ -26191,7 +26349,7 @@ class SelectionInputStore extends SpreadsheetStore {
|
|
|
26191
26349
|
const range = this.ranges[this.focusedRangeIndex];
|
|
26192
26350
|
const sheetId = this.getters.getActiveSheetId();
|
|
26193
26351
|
const zone = this.getters.getRangeFromSheetXC(sheetId, range?.xc || "A1").zone;
|
|
26194
|
-
this.model.selection.capture(
|
|
26352
|
+
this.model.selection.capture(this, { cell: { col: zone.left, row: zone.top }, zone }, {
|
|
26195
26353
|
handleEvent: this.handleEvent.bind(this),
|
|
26196
26354
|
release: this.unfocus.bind(this),
|
|
26197
26355
|
});
|
|
@@ -26667,7 +26825,7 @@ class LineBarPieConfigPanel extends owl.Component {
|
|
|
26667
26825
|
}
|
|
26668
26826
|
const getters = this.env.model.getters;
|
|
26669
26827
|
const sheetId = getters.getActiveSheetId();
|
|
26670
|
-
const labelRange =
|
|
26828
|
+
const labelRange = createValidRange(getters, sheetId, this.labelRange);
|
|
26671
26829
|
const dataSets = createDataSets(getters, this.dataSeriesRanges, sheetId, this.props.definition.dataSetsHaveTitle);
|
|
26672
26830
|
if (dataSets.length) {
|
|
26673
26831
|
return dataSets[0].dataRange.zone.top + 1;
|
|
@@ -26696,15 +26854,23 @@ class BarConfigPanel extends LineBarPieConfigPanel {
|
|
|
26696
26854
|
}
|
|
26697
26855
|
}
|
|
26698
26856
|
|
|
26857
|
+
/**
|
|
26858
|
+
* Start listening to pointer events and apply the given callbacks.
|
|
26859
|
+
*
|
|
26860
|
+
* @returns A function to remove the listeners.
|
|
26861
|
+
*/
|
|
26699
26862
|
function startDnd(onMouseMove, onMouseUp, onMouseDown = () => { }) {
|
|
26700
|
-
const
|
|
26701
|
-
onMouseUp(ev);
|
|
26863
|
+
const removeListeners = () => {
|
|
26702
26864
|
window.removeEventListener("pointerdown", onMouseDown);
|
|
26703
26865
|
window.removeEventListener("pointerup", _onMouseUp);
|
|
26704
26866
|
window.removeEventListener("dragstart", _onDragStart);
|
|
26705
26867
|
window.removeEventListener("pointermove", onMouseMove);
|
|
26706
26868
|
window.removeEventListener("wheel", onMouseMove);
|
|
26707
26869
|
};
|
|
26870
|
+
const _onMouseUp = (ev) => {
|
|
26871
|
+
onMouseUp(ev);
|
|
26872
|
+
removeListeners();
|
|
26873
|
+
};
|
|
26708
26874
|
function _onDragStart(ev) {
|
|
26709
26875
|
ev.preventDefault();
|
|
26710
26876
|
}
|
|
@@ -26716,6 +26882,7 @@ function startDnd(onMouseMove, onMouseUp, onMouseDown = () => { }) {
|
|
|
26716
26882
|
// preventDefault() is not allowed in passive event handler.
|
|
26717
26883
|
// https://chromestatus.com/feature/6662647093133312
|
|
26718
26884
|
window.addEventListener("wheel", onMouseMove, { passive: false });
|
|
26885
|
+
return removeListeners;
|
|
26719
26886
|
}
|
|
26720
26887
|
/**
|
|
26721
26888
|
* Function to be used during a pointerdown event, this function allows to
|
|
@@ -27659,6 +27826,7 @@ chartSidePanelComponentRegistry
|
|
|
27659
27826
|
});
|
|
27660
27827
|
|
|
27661
27828
|
class MainChartPanelStore extends SpreadsheetStore {
|
|
27829
|
+
mutators = ["activatePanel"];
|
|
27662
27830
|
panel = "configuration";
|
|
27663
27831
|
activatePanel(panel) {
|
|
27664
27832
|
this.panel = panel;
|
|
@@ -27909,6 +28077,7 @@ function useDragAndDropListItems() {
|
|
|
27909
28077
|
state.itemsStyle = {};
|
|
27910
28078
|
document.body.style.cursor = previousCursor;
|
|
27911
28079
|
args.onCancel?.();
|
|
28080
|
+
cleanUp();
|
|
27912
28081
|
};
|
|
27913
28082
|
const onDragEnd = (itemId, indexAtEnd) => {
|
|
27914
28083
|
state.draggedItemId = undefined;
|
|
@@ -27929,7 +28098,8 @@ function useDragAndDropListItems() {
|
|
|
27929
28098
|
onDragEnd,
|
|
27930
28099
|
onCancel: state.cancel,
|
|
27931
28100
|
});
|
|
27932
|
-
startDnd(dndHelper.onMouseMove.bind(dndHelper), dndHelper.onMouseUp.bind(dndHelper));
|
|
28101
|
+
const stopListening = startDnd(dndHelper.onMouseMove.bind(dndHelper), dndHelper.onMouseUp.bind(dndHelper));
|
|
28102
|
+
cleanupFns.push(stopListening);
|
|
27933
28103
|
const onScroll = dndHelper.onScroll.bind(dndHelper);
|
|
27934
28104
|
args.containerEl.addEventListener("scroll", onScroll);
|
|
27935
28105
|
cleanupFns.push(() => args.containerEl.removeEventListener("scroll", onScroll));
|
|
@@ -28006,7 +28176,7 @@ class DOMDndHelper {
|
|
|
28006
28176
|
this.moveDraggedItemToPosition(this.currentMousePosition + this.scrollOffset);
|
|
28007
28177
|
}
|
|
28008
28178
|
onMouseMove(ev) {
|
|
28009
|
-
if (ev.button
|
|
28179
|
+
if (ev.button > 1) {
|
|
28010
28180
|
this.onCancel();
|
|
28011
28181
|
return;
|
|
28012
28182
|
}
|
|
@@ -28197,14 +28367,14 @@ function useHoveredElement(ref) {
|
|
|
28197
28367
|
|
|
28198
28368
|
function useHighlightsOnHover(ref, highlightProvider) {
|
|
28199
28369
|
const hoverState = useHoveredElement(ref);
|
|
28200
|
-
const
|
|
28370
|
+
const stores = useStoreProvider();
|
|
28201
28371
|
useHighlights({
|
|
28202
28372
|
get highlights() {
|
|
28203
28373
|
return hoverState.hovered ? highlightProvider.highlights : [];
|
|
28204
28374
|
},
|
|
28205
28375
|
});
|
|
28206
28376
|
owl.useEffect(() => {
|
|
28207
|
-
|
|
28377
|
+
stores.trigger("store-updated");
|
|
28208
28378
|
}, () => [hoverState.hovered]);
|
|
28209
28379
|
}
|
|
28210
28380
|
function useHighlights(highlightProvider) {
|
|
@@ -29660,6 +29830,14 @@ var Direction;
|
|
|
29660
29830
|
Direction[Direction["next"] = 1] = "next";
|
|
29661
29831
|
})(Direction || (Direction = {}));
|
|
29662
29832
|
class FindAndReplaceStore extends SpreadsheetStore {
|
|
29833
|
+
mutators = [
|
|
29834
|
+
"updateSearchOptions",
|
|
29835
|
+
"updateSearchContent",
|
|
29836
|
+
"searchFormulas",
|
|
29837
|
+
"selectPreviousMatch",
|
|
29838
|
+
"selectNextMatch",
|
|
29839
|
+
"replace",
|
|
29840
|
+
];
|
|
29663
29841
|
allSheetsMatches = [];
|
|
29664
29842
|
activeSheetMatches = [];
|
|
29665
29843
|
specificRangeMatches = [];
|
|
@@ -29684,11 +29862,11 @@ class FindAndReplaceStore extends SpreadsheetStore {
|
|
|
29684
29862
|
this.initialShowFormulaState = this.model.getters.shouldShowFormulas();
|
|
29685
29863
|
this.searchOptions.searchFormulas = this.initialShowFormulaState;
|
|
29686
29864
|
const highlightStore = get(HighlightStore);
|
|
29687
|
-
highlightStore.register(
|
|
29865
|
+
highlightStore.register(this);
|
|
29688
29866
|
this.onDispose(() => {
|
|
29689
29867
|
this.model.dispatch("SET_FORMULA_VISIBILITY", { show: this.initialShowFormulaState });
|
|
29690
29868
|
this.updateSearchContent.stopDebounce();
|
|
29691
|
-
highlightStore.unRegister(
|
|
29869
|
+
highlightStore.unRegister(this);
|
|
29692
29870
|
});
|
|
29693
29871
|
}
|
|
29694
29872
|
get searchMatches() {
|
|
@@ -31168,14 +31346,14 @@ class FigureComponent extends owl.Component {
|
|
|
31168
31346
|
}
|
|
31169
31347
|
onKeyDown(ev) {
|
|
31170
31348
|
const figure = this.props.figure;
|
|
31171
|
-
|
|
31349
|
+
const keyDownShortcut = keyboardEventToShortcutString(ev);
|
|
31350
|
+
switch (keyDownShortcut) {
|
|
31172
31351
|
case "Delete":
|
|
31173
31352
|
this.env.model.dispatch("DELETE_FIGURE", {
|
|
31174
31353
|
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
31175
31354
|
id: figure.id,
|
|
31176
31355
|
});
|
|
31177
31356
|
this.props.onFigureDeleted();
|
|
31178
|
-
ev.stopPropagation();
|
|
31179
31357
|
ev.preventDefault();
|
|
31180
31358
|
ev.stopPropagation();
|
|
31181
31359
|
break;
|
|
@@ -31196,7 +31374,22 @@ class FigureComponent extends owl.Component {
|
|
|
31196
31374
|
x: figure.x + delta[0],
|
|
31197
31375
|
y: figure.y + delta[1],
|
|
31198
31376
|
});
|
|
31377
|
+
ev.preventDefault();
|
|
31378
|
+
ev.stopPropagation();
|
|
31379
|
+
break;
|
|
31380
|
+
case "Ctrl+A":
|
|
31381
|
+
// Maybe in the future we will implement a way to select all figures
|
|
31382
|
+
ev.preventDefault();
|
|
31199
31383
|
ev.stopPropagation();
|
|
31384
|
+
break;
|
|
31385
|
+
case "Ctrl+Y":
|
|
31386
|
+
case "Ctrl+Z":
|
|
31387
|
+
if (keyDownShortcut === "Ctrl+Y") {
|
|
31388
|
+
this.env.model.dispatch("REQUEST_REDO");
|
|
31389
|
+
}
|
|
31390
|
+
else if (keyDownShortcut === "Ctrl+Z") {
|
|
31391
|
+
this.env.model.dispatch("REQUEST_UNDO");
|
|
31392
|
+
}
|
|
31200
31393
|
ev.preventDefault();
|
|
31201
31394
|
ev.stopPropagation();
|
|
31202
31395
|
break;
|
|
@@ -31331,6 +31524,7 @@ unGroupHeadersMenuRegistry
|
|
|
31331
31524
|
});
|
|
31332
31525
|
|
|
31333
31526
|
class DOMFocusableElementStore {
|
|
31527
|
+
mutators = ["setFocusableElement", "focus"];
|
|
31334
31528
|
focusableElement = undefined;
|
|
31335
31529
|
setFocusableElement(element) {
|
|
31336
31530
|
this.focusableElement = element;
|
|
@@ -32067,7 +32261,7 @@ class Composer extends owl.Component {
|
|
|
32067
32261
|
"Ctrl+Enter": this.processNewLineEvent,
|
|
32068
32262
|
Escape: this.processEscapeKey,
|
|
32069
32263
|
F2: () => console.warn("Not implemented"),
|
|
32070
|
-
F4: this.processF4Key,
|
|
32264
|
+
F4: (ev) => this.processF4Key(ev),
|
|
32071
32265
|
Tab: (ev) => this.processTabKey(ev, "right"),
|
|
32072
32266
|
"Shift+Tab": (ev) => this.processTabKey(ev, "left"),
|
|
32073
32267
|
};
|
|
@@ -32189,7 +32383,8 @@ class Composer extends owl.Component {
|
|
|
32189
32383
|
processEscapeKey() {
|
|
32190
32384
|
this.composerStore.cancelEdition();
|
|
32191
32385
|
}
|
|
32192
|
-
processF4Key() {
|
|
32386
|
+
processF4Key(ev) {
|
|
32387
|
+
ev.stopPropagation();
|
|
32193
32388
|
this.composerStore.cycleReferences();
|
|
32194
32389
|
this.processContent();
|
|
32195
32390
|
}
|
|
@@ -34392,13 +34587,6 @@ class GridRenderer {
|
|
|
34392
34587
|
this.getters = get(ModelStore).getters;
|
|
34393
34588
|
this.renderer = get(RendererStore);
|
|
34394
34589
|
this.renderer.register(this);
|
|
34395
|
-
/**
|
|
34396
|
-
* Mark the instance as raw to avoid reactivity as this class is instanciated
|
|
34397
|
-
* as a Store by `useGridDrawing` (which casts it as reactive).
|
|
34398
|
-
*
|
|
34399
|
-
* Calling `this.` on a reactive instance is significantly slower than on a raw object.
|
|
34400
|
-
*/
|
|
34401
|
-
owl.markRaw(this);
|
|
34402
34590
|
}
|
|
34403
34591
|
get renderingLayers() {
|
|
34404
34592
|
return ["Background", "Headers"];
|
|
@@ -35028,7 +35216,7 @@ class GridRenderer {
|
|
|
35028
35216
|
function useGridDrawing(refName, model, canvasSize) {
|
|
35029
35217
|
const canvasRef = owl.useRef(refName);
|
|
35030
35218
|
owl.useEffect(drawGrid);
|
|
35031
|
-
const
|
|
35219
|
+
const rendererStore = useStore(RendererStore);
|
|
35032
35220
|
useStore(GridRenderer);
|
|
35033
35221
|
function drawGrid() {
|
|
35034
35222
|
const canvas = canvasRef.el;
|
|
@@ -35056,7 +35244,11 @@ function useGridDrawing(refName, model, canvasSize) {
|
|
|
35056
35244
|
ctx.scale(dpr, dpr);
|
|
35057
35245
|
for (const layer of OrderedLayers()) {
|
|
35058
35246
|
model.drawLayer(renderingContext, layer);
|
|
35059
|
-
|
|
35247
|
+
// @ts-ignore 'drawLayer' is not declated as a mutator because:
|
|
35248
|
+
// it does not mutate anything. Most importantly it's used
|
|
35249
|
+
// during rendering. Invoking a mutator during rendering would
|
|
35250
|
+
// trigger another rendering, ultimately resulting in an infinite loop.
|
|
35251
|
+
rendererStore.drawLayer(renderingContext, layer);
|
|
35060
35252
|
}
|
|
35061
35253
|
}
|
|
35062
35254
|
}
|
|
@@ -35458,6 +35650,7 @@ class VerticalScrollBar extends owl.Component {
|
|
|
35458
35650
|
}
|
|
35459
35651
|
|
|
35460
35652
|
class SidePanelStore extends SpreadsheetStore {
|
|
35653
|
+
mutators = ["open", "toggle", "close"];
|
|
35461
35654
|
initialPanelProps = {};
|
|
35462
35655
|
componentTag = "";
|
|
35463
35656
|
get isOpen() {
|
|
@@ -40984,12 +41177,6 @@ function compileTokens(tokens) {
|
|
|
40984
41177
|
// detect when an argument need to be evaluated as a meta argument
|
|
40985
41178
|
const isMeta = argTypes.includes("META");
|
|
40986
41179
|
const hasRange = argTypes.some((t) => isRangeType(t));
|
|
40987
|
-
const isRangeOnly = argTypes.every((t) => isRangeType(t));
|
|
40988
|
-
if (isRangeOnly) {
|
|
40989
|
-
if (!isRangeInput(currentArg)) {
|
|
40990
|
-
throw new BadExpressionError(_t("Function %s expects the parameter %s to be reference to a cell or range, not a %s.", functionName, (i + 1).toString(), currentArg.type.toLowerCase()));
|
|
40991
|
-
}
|
|
40992
|
-
}
|
|
40993
41180
|
compiledArgs.push(compileAST(currentArg, isMeta, hasRange, {
|
|
40994
41181
|
functionName,
|
|
40995
41182
|
paramIndex: i + 1,
|
|
@@ -41160,16 +41347,6 @@ function assertEnoughArgs(ast) {
|
|
|
41160
41347
|
function isRangeType(type) {
|
|
41161
41348
|
return type.startsWith("RANGE");
|
|
41162
41349
|
}
|
|
41163
|
-
function isRangeInput(arg) {
|
|
41164
|
-
if (arg.type === "REFERENCE") {
|
|
41165
|
-
return true;
|
|
41166
|
-
}
|
|
41167
|
-
if (arg.type === "FUNCALL") {
|
|
41168
|
-
const fnDef = functions$1[arg.value.toUpperCase()];
|
|
41169
|
-
return fnDef && isRangeType(fnDef.returns[0]);
|
|
41170
|
-
}
|
|
41171
|
-
return false;
|
|
41172
|
-
}
|
|
41173
41350
|
|
|
41174
41351
|
const functions = functionRegistry.content;
|
|
41175
41352
|
function isExportableToExcel(tokens) {
|
|
@@ -43286,7 +43463,12 @@ class MergePlugin extends CorePlugin {
|
|
|
43286
43463
|
* if they have at least a common cell
|
|
43287
43464
|
*/
|
|
43288
43465
|
doesIntersectMerge(sheetId, zone) {
|
|
43289
|
-
|
|
43466
|
+
for (const merge of this.getMerges(sheetId)) {
|
|
43467
|
+
if (overlap(zone, merge)) {
|
|
43468
|
+
return true;
|
|
43469
|
+
}
|
|
43470
|
+
}
|
|
43471
|
+
return false;
|
|
43290
43472
|
}
|
|
43291
43473
|
/**
|
|
43292
43474
|
* Returns true if two columns have at least one merge in common
|
|
@@ -43902,6 +44084,9 @@ class RangeAdapter {
|
|
|
43902
44084
|
if (range.invalidXc) {
|
|
43903
44085
|
return range.invalidXc;
|
|
43904
44086
|
}
|
|
44087
|
+
if (!this.getters.tryGetSheet(range.sheetId)) {
|
|
44088
|
+
return CellErrorType.InvalidReference;
|
|
44089
|
+
}
|
|
43905
44090
|
if (range.zone.bottom - range.zone.top < 0 || range.zone.right - range.zone.left < 0) {
|
|
43906
44091
|
return CellErrorType.InvalidReference;
|
|
43907
44092
|
}
|
|
@@ -47286,7 +47471,6 @@ class PositionSet {
|
|
|
47286
47471
|
*
|
|
47287
47472
|
*/
|
|
47288
47473
|
class SpreadingRelation {
|
|
47289
|
-
createEmptyPositionSet;
|
|
47290
47474
|
/**
|
|
47291
47475
|
* Internal structure:
|
|
47292
47476
|
* For something like
|
|
@@ -47317,9 +47501,6 @@ class SpreadingRelation {
|
|
|
47317
47501
|
*/
|
|
47318
47502
|
resultsToArrayFormulas = new PositionMap();
|
|
47319
47503
|
arrayFormulasToResults = new PositionMap();
|
|
47320
|
-
constructor(createEmptyPositionSet) {
|
|
47321
|
-
this.createEmptyPositionSet = createEmptyPositionSet;
|
|
47322
|
-
}
|
|
47323
47504
|
getFormulaPositionsSpreadingOn(resultPosition) {
|
|
47324
47505
|
return this.resultsToArrayFormulas.get(resultPosition) || EMPTY_ARRAY;
|
|
47325
47506
|
}
|
|
@@ -47338,13 +47519,13 @@ class SpreadingRelation {
|
|
|
47338
47519
|
*/
|
|
47339
47520
|
addRelation({ arrayFormulaPosition, resultPosition, }) {
|
|
47340
47521
|
if (!this.resultsToArrayFormulas.has(resultPosition)) {
|
|
47341
|
-
this.resultsToArrayFormulas.set(resultPosition,
|
|
47522
|
+
this.resultsToArrayFormulas.set(resultPosition, []);
|
|
47342
47523
|
}
|
|
47343
|
-
this.resultsToArrayFormulas.get(resultPosition)?.
|
|
47524
|
+
this.resultsToArrayFormulas.get(resultPosition)?.push(arrayFormulaPosition);
|
|
47344
47525
|
if (!this.arrayFormulasToResults.has(arrayFormulaPosition)) {
|
|
47345
|
-
this.arrayFormulasToResults.set(arrayFormulaPosition,
|
|
47526
|
+
this.arrayFormulasToResults.set(arrayFormulaPosition, []);
|
|
47346
47527
|
}
|
|
47347
|
-
this.arrayFormulasToResults.get(arrayFormulaPosition)?.
|
|
47528
|
+
this.arrayFormulasToResults.get(arrayFormulaPosition)?.push(resultPosition);
|
|
47348
47529
|
}
|
|
47349
47530
|
hasArrayFormulaResult(position) {
|
|
47350
47531
|
return this.resultsToArrayFormulas.has(position);
|
|
@@ -47365,7 +47546,7 @@ class Evaluator {
|
|
|
47365
47546
|
evaluatedCells = new PositionMap();
|
|
47366
47547
|
formulaDependencies = lazy(new FormulaDependencyGraph(this.createEmptyPositionSet.bind(this)));
|
|
47367
47548
|
blockedArrayFormulas = new PositionSet({});
|
|
47368
|
-
spreadingRelations = new SpreadingRelation(
|
|
47549
|
+
spreadingRelations = new SpreadingRelation();
|
|
47369
47550
|
constructor(context, getters) {
|
|
47370
47551
|
this.context = context;
|
|
47371
47552
|
this.getters = getters;
|
|
@@ -47442,7 +47623,7 @@ class Evaluator {
|
|
|
47442
47623
|
}
|
|
47443
47624
|
buildDependencyGraph() {
|
|
47444
47625
|
this.blockedArrayFormulas = this.createEmptyPositionSet();
|
|
47445
|
-
this.spreadingRelations = new SpreadingRelation(
|
|
47626
|
+
this.spreadingRelations = new SpreadingRelation();
|
|
47446
47627
|
this.formulaDependencies = lazy(() => {
|
|
47447
47628
|
const dependencies = [...this.getAllCells()].flatMap((position) => this.getDirectDependencies(position)
|
|
47448
47629
|
.filter((range) => !range.invalidSheetName && !range.invalidXc)
|
|
@@ -47931,16 +48112,22 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
47931
48112
|
let newContent = undefined;
|
|
47932
48113
|
let newFormat = undefined;
|
|
47933
48114
|
let isExported = true;
|
|
48115
|
+
const exportedSheetData = data.sheets.find((sheet) => sheet.id === position.sheetId);
|
|
47934
48116
|
const formulaCell = this.getCorrespondingFormulaCell(position);
|
|
47935
48117
|
if (formulaCell) {
|
|
47936
48118
|
isExported = isExportableToExcel(formulaCell.compiledFormula.tokens);
|
|
47937
48119
|
isFormula = isExported;
|
|
47938
48120
|
if (!isExported) {
|
|
47939
|
-
|
|
47940
|
-
|
|
48121
|
+
// If the cell contains a non-exported formula and that is evaluates to
|
|
48122
|
+
// nothing* ,we don't export it.
|
|
48123
|
+
// * non-falsy value are relevant and so are 0 and FALSE, which only leaves
|
|
48124
|
+
// the empty string.
|
|
48125
|
+
if (value !== "") {
|
|
48126
|
+
newContent = (value ?? "").toString();
|
|
48127
|
+
newFormat = evaluatedCell.format;
|
|
48128
|
+
}
|
|
47941
48129
|
}
|
|
47942
48130
|
}
|
|
47943
|
-
const exportedSheetData = data.sheets.find((sheet) => sheet.id === position.sheetId);
|
|
47944
48131
|
const exportedCellData = exportedSheetData.cells[xc] || {};
|
|
47945
48132
|
const format = newFormat
|
|
47946
48133
|
? getItemId(newFormat, data.formats)
|
|
@@ -49606,62 +49793,6 @@ class AutomaticSumPlugin extends UIPlugin {
|
|
|
49606
49793
|
}
|
|
49607
49794
|
}
|
|
49608
49795
|
|
|
49609
|
-
/**
|
|
49610
|
-
* This is a generic event bus based on the Owl event bus.
|
|
49611
|
-
* This bus however ensures type safety across events and subscription callbacks.
|
|
49612
|
-
*/
|
|
49613
|
-
class EventBus {
|
|
49614
|
-
subscriptions = {};
|
|
49615
|
-
/**
|
|
49616
|
-
* Add a listener for the 'eventType' events.
|
|
49617
|
-
*
|
|
49618
|
-
* Note that the 'owner' of this event can be anything, but will more likely
|
|
49619
|
-
* be a component or a class. The idea is that the callback will be called with
|
|
49620
|
-
* the proper owner bound.
|
|
49621
|
-
*
|
|
49622
|
-
* Also, the owner should be kind of unique. This will be used to remove the
|
|
49623
|
-
* listener.
|
|
49624
|
-
*/
|
|
49625
|
-
on(type, owner, callback) {
|
|
49626
|
-
if (!callback) {
|
|
49627
|
-
throw new Error("Missing callback");
|
|
49628
|
-
}
|
|
49629
|
-
if (!this.subscriptions[type]) {
|
|
49630
|
-
this.subscriptions[type] = [];
|
|
49631
|
-
}
|
|
49632
|
-
this.subscriptions[type].push({
|
|
49633
|
-
owner,
|
|
49634
|
-
callback,
|
|
49635
|
-
});
|
|
49636
|
-
}
|
|
49637
|
-
/**
|
|
49638
|
-
* Emit an event of type 'eventType'. Any extra arguments will be passed to
|
|
49639
|
-
* the listeners callback.
|
|
49640
|
-
*/
|
|
49641
|
-
trigger(type, payload) {
|
|
49642
|
-
const subs = this.subscriptions[type] || [];
|
|
49643
|
-
for (let i = 0, iLen = subs.length; i < iLen; i++) {
|
|
49644
|
-
const sub = subs[i];
|
|
49645
|
-
sub.callback.call(sub.owner, payload);
|
|
49646
|
-
}
|
|
49647
|
-
}
|
|
49648
|
-
/**
|
|
49649
|
-
* Remove a listener
|
|
49650
|
-
*/
|
|
49651
|
-
off(eventType, owner) {
|
|
49652
|
-
const subs = this.subscriptions[eventType];
|
|
49653
|
-
if (subs) {
|
|
49654
|
-
this.subscriptions[eventType] = subs.filter((s) => s.owner !== owner);
|
|
49655
|
-
}
|
|
49656
|
-
}
|
|
49657
|
-
/**
|
|
49658
|
-
* Remove all subscriptions.
|
|
49659
|
-
*/
|
|
49660
|
-
clear() {
|
|
49661
|
-
this.subscriptions = {};
|
|
49662
|
-
}
|
|
49663
|
-
}
|
|
49664
|
-
|
|
49665
49796
|
/*
|
|
49666
49797
|
* This file contains the specifics transformations
|
|
49667
49798
|
*/
|
|
@@ -51986,7 +52117,7 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
51986
52117
|
paintFormatStatus = "inactive";
|
|
51987
52118
|
originSheetId;
|
|
51988
52119
|
copiedData;
|
|
51989
|
-
_isCutOperation;
|
|
52120
|
+
_isCutOperation = false;
|
|
51990
52121
|
// ---------------------------------------------------------------------------
|
|
51991
52122
|
// Command Handling
|
|
51992
52123
|
// ---------------------------------------------------------------------------
|
|
@@ -51998,14 +52129,17 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
51998
52129
|
case "PASTE_FROM_OS_CLIPBOARD": {
|
|
51999
52130
|
const copiedData = this.convertOSClipboardData(cmd.text);
|
|
52000
52131
|
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
52001
|
-
return this.isPasteAllowed(cmd.target, copiedData, { pasteOption });
|
|
52132
|
+
return this.isPasteAllowed(cmd.target, copiedData, { pasteOption, isCutOperation: false });
|
|
52002
52133
|
}
|
|
52003
52134
|
case "PASTE": {
|
|
52004
52135
|
if (!this.copiedData) {
|
|
52005
52136
|
return "EmptyClipboard" /* CommandResult.EmptyClipboard */;
|
|
52006
52137
|
}
|
|
52007
52138
|
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
52008
|
-
return this.isPasteAllowed(cmd.target, this.copiedData, {
|
|
52139
|
+
return this.isPasteAllowed(cmd.target, this.copiedData, {
|
|
52140
|
+
pasteOption: pasteOption,
|
|
52141
|
+
isCutOperation: this._isCutOperation,
|
|
52142
|
+
});
|
|
52009
52143
|
}
|
|
52010
52144
|
case "COPY_PASTE_CELLS_ABOVE": {
|
|
52011
52145
|
const zones = this.getters.getSelectedZones();
|
|
@@ -52023,13 +52157,13 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
52023
52157
|
}
|
|
52024
52158
|
case "INSERT_CELL": {
|
|
52025
52159
|
const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
|
|
52026
|
-
const copiedData = this.copy(
|
|
52027
|
-
return this.isPasteAllowed(paste, copiedData, {});
|
|
52160
|
+
const copiedData = this.copy(cut);
|
|
52161
|
+
return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
|
|
52028
52162
|
}
|
|
52029
52163
|
case "DELETE_CELL": {
|
|
52030
52164
|
const { cut, paste } = this.getDeleteCellsTargets(cmd.zone, cmd.shiftDimension);
|
|
52031
|
-
const copiedData = this.copy(
|
|
52032
|
-
return this.isPasteAllowed(paste, copiedData, {});
|
|
52165
|
+
const copiedData = this.copy(cut);
|
|
52166
|
+
return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
|
|
52033
52167
|
}
|
|
52034
52168
|
case "ACTIVATE_PAINT_FORMAT": {
|
|
52035
52169
|
if (this.paintFormatStatus !== "inactive") {
|
|
@@ -52047,23 +52181,27 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
52047
52181
|
const zones = this.getters.getSelectedZones();
|
|
52048
52182
|
this.status = "visible";
|
|
52049
52183
|
this.originSheetId = this.getters.getActiveSheetId();
|
|
52050
|
-
this.copiedData = this.copy(
|
|
52184
|
+
this.copiedData = this.copy(zones);
|
|
52185
|
+
this._isCutOperation = cmd.type === "CUT";
|
|
52051
52186
|
break;
|
|
52052
52187
|
case "PASTE_FROM_OS_CLIPBOARD": {
|
|
52188
|
+
this._isCutOperation = false;
|
|
52053
52189
|
this.copiedData = this.convertOSClipboardData(cmd.text);
|
|
52054
52190
|
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
52055
|
-
this.paste(cmd.target, {
|
|
52191
|
+
this.paste(cmd.target, this.copiedData, {
|
|
52056
52192
|
pasteOption,
|
|
52057
52193
|
selectTarget: true,
|
|
52194
|
+
isCutOperation: false,
|
|
52058
52195
|
});
|
|
52059
52196
|
this.status = "invisible";
|
|
52060
52197
|
break;
|
|
52061
52198
|
}
|
|
52062
52199
|
case "PASTE": {
|
|
52063
52200
|
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
52064
|
-
this.paste(cmd.target, {
|
|
52201
|
+
this.paste(cmd.target, this.copiedData, {
|
|
52065
52202
|
pasteOption,
|
|
52066
52203
|
selectTarget: true,
|
|
52204
|
+
isCutOperation: this._isCutOperation,
|
|
52067
52205
|
});
|
|
52068
52206
|
if (this.paintFormatStatus === "oneOff") {
|
|
52069
52207
|
this.paintFormatStatus = "inactive";
|
|
@@ -52084,9 +52222,9 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
52084
52222
|
top: multipleRowsInSelection ? zone.top : zone.top - 1,
|
|
52085
52223
|
};
|
|
52086
52224
|
this.originSheetId = this.getters.getActiveSheetId();
|
|
52087
|
-
|
|
52088
|
-
this.paste([zone], {
|
|
52089
|
-
|
|
52225
|
+
const copiedData = this.copy([copyTarget]);
|
|
52226
|
+
this.paste([zone], copiedData, {
|
|
52227
|
+
isCutOperation: false,
|
|
52090
52228
|
selectTarget: true,
|
|
52091
52229
|
});
|
|
52092
52230
|
}
|
|
@@ -52101,9 +52239,9 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
52101
52239
|
left: multipleColsInSelection ? zone.left : zone.left - 1,
|
|
52102
52240
|
};
|
|
52103
52241
|
this.originSheetId = this.getters.getActiveSheetId();
|
|
52104
|
-
|
|
52105
|
-
this.paste([zone], {
|
|
52106
|
-
|
|
52242
|
+
const copiedData = this.copy([copyTarget]);
|
|
52243
|
+
this.paste([zone], copiedData, {
|
|
52244
|
+
isCutOperation: false,
|
|
52107
52245
|
selectTarget: true,
|
|
52108
52246
|
});
|
|
52109
52247
|
}
|
|
@@ -52119,20 +52257,20 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
52119
52257
|
}
|
|
52120
52258
|
break;
|
|
52121
52259
|
}
|
|
52122
|
-
|
|
52123
|
-
this.paste(paste, {});
|
|
52260
|
+
const copiedData = this.copy(cut);
|
|
52261
|
+
this.paste(paste, copiedData, { isCutOperation: true });
|
|
52124
52262
|
break;
|
|
52125
52263
|
}
|
|
52126
52264
|
case "INSERT_CELL": {
|
|
52127
52265
|
const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
|
|
52128
|
-
|
|
52129
|
-
this.paste(paste, {});
|
|
52266
|
+
const copiedData = this.copy(cut);
|
|
52267
|
+
this.paste(paste, copiedData, { isCutOperation: true });
|
|
52130
52268
|
break;
|
|
52131
52269
|
}
|
|
52132
52270
|
case "ADD_COLUMNS_ROWS": {
|
|
52133
52271
|
this.status = "invisible";
|
|
52134
52272
|
// If we add a col/row inside or before the cut area, we invalidate the clipboard
|
|
52135
|
-
if (this._isCutOperation !== true) {
|
|
52273
|
+
if (this._isCutOperation !== true || cmd.sheetId !== this.copiedData?.sheetId) {
|
|
52136
52274
|
return;
|
|
52137
52275
|
}
|
|
52138
52276
|
const isClipboardDirty = this.isColRowDirtyingClipboard(cmd.position === "before" ? cmd.base : cmd.base + 1, cmd.dimension);
|
|
@@ -52144,7 +52282,7 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
52144
52282
|
case "REMOVE_COLUMNS_ROWS": {
|
|
52145
52283
|
this.status = "invisible";
|
|
52146
52284
|
// If we remove a col/row inside or before the cut area, we invalidate the clipboard
|
|
52147
|
-
if (this._isCutOperation !== true) {
|
|
52285
|
+
if (this._isCutOperation !== true || cmd.sheetId !== this.copiedData?.sheetId) {
|
|
52148
52286
|
return;
|
|
52149
52287
|
}
|
|
52150
52288
|
for (let el of cmd.elements) {
|
|
@@ -52158,7 +52296,8 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
52158
52296
|
break;
|
|
52159
52297
|
}
|
|
52160
52298
|
case "REPEAT_PASTE": {
|
|
52161
|
-
this.paste(cmd.target, {
|
|
52299
|
+
this.paste(cmd.target, this.copiedData, {
|
|
52300
|
+
isCutOperation: false,
|
|
52162
52301
|
pasteOption: cmd.pasteOption,
|
|
52163
52302
|
selectTarget: true,
|
|
52164
52303
|
});
|
|
@@ -52166,7 +52305,7 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
52166
52305
|
}
|
|
52167
52306
|
case "ACTIVATE_PAINT_FORMAT": {
|
|
52168
52307
|
const zones = this.getters.getSelectedZones();
|
|
52169
|
-
this.copiedData = this.copy(
|
|
52308
|
+
this.copiedData = this.copy(zones);
|
|
52170
52309
|
this.status = "visible";
|
|
52171
52310
|
if (cmd.persistent) {
|
|
52172
52311
|
this.paintFormatStatus = "persistent";
|
|
@@ -52197,7 +52336,6 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
52197
52336
|
}
|
|
52198
52337
|
}
|
|
52199
52338
|
convertOSClipboardData(clipboardData) {
|
|
52200
|
-
this._isCutOperation = false;
|
|
52201
52339
|
const handlers = clipboardHandlersRegistries.figureHandlers
|
|
52202
52340
|
.getAll()
|
|
52203
52341
|
.map((handler) => new handler(this.getters, this.dispatch));
|
|
@@ -52235,7 +52373,6 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
52235
52373
|
for (const handler of this.selectClipboardHandlers(copiedData)) {
|
|
52236
52374
|
const result = handler.isPasteAllowed(this.getters.getActiveSheetId(), target, copiedData, {
|
|
52237
52375
|
...options,
|
|
52238
|
-
isCutOperation: this.isCutOperation(),
|
|
52239
52376
|
});
|
|
52240
52377
|
if (result !== "Success" /* CommandResult.Success */) {
|
|
52241
52378
|
return result;
|
|
@@ -52258,9 +52395,8 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
52258
52395
|
}
|
|
52259
52396
|
return false;
|
|
52260
52397
|
}
|
|
52261
|
-
copy(
|
|
52398
|
+
copy(zones) {
|
|
52262
52399
|
let copiedData = {};
|
|
52263
|
-
this._isCutOperation = operation === "CUT";
|
|
52264
52400
|
const clipboardData = this.getClipboardData(zones);
|
|
52265
52401
|
for (const handler of this.selectClipboardHandlers(clipboardData)) {
|
|
52266
52402
|
const data = handler.copy(clipboardData);
|
|
@@ -52268,8 +52404,8 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
52268
52404
|
}
|
|
52269
52405
|
return copiedData;
|
|
52270
52406
|
}
|
|
52271
|
-
paste(zones, options) {
|
|
52272
|
-
if (!
|
|
52407
|
+
paste(zones, copiedData, options) {
|
|
52408
|
+
if (!copiedData) {
|
|
52273
52409
|
return;
|
|
52274
52410
|
}
|
|
52275
52411
|
let zone = undefined;
|
|
@@ -52277,12 +52413,9 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
52277
52413
|
let target = {
|
|
52278
52414
|
zones,
|
|
52279
52415
|
};
|
|
52280
|
-
const handlers = this.selectClipboardHandlers(
|
|
52416
|
+
const handlers = this.selectClipboardHandlers(copiedData);
|
|
52281
52417
|
for (const handler of handlers) {
|
|
52282
|
-
const currentTarget = handler.getPasteTarget(zones,
|
|
52283
|
-
...options,
|
|
52284
|
-
isCutOperation: this.isCutOperation(),
|
|
52285
|
-
});
|
|
52418
|
+
const currentTarget = handler.getPasteTarget(zones, copiedData, options);
|
|
52286
52419
|
if (currentTarget.figureId) {
|
|
52287
52420
|
target.figureId = currentTarget.figureId;
|
|
52288
52421
|
}
|
|
@@ -52298,7 +52431,7 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
52298
52431
|
if (zone !== undefined) {
|
|
52299
52432
|
this.addMissingDimensions(this.getters.getActiveSheetId(), zone.right - zone.left + 1, zone.bottom - zone.top + 1, zone.left, zone.top);
|
|
52300
52433
|
}
|
|
52301
|
-
handlers.forEach((handler) => handler.paste(target,
|
|
52434
|
+
handlers.forEach((handler) => handler.paste(target, copiedData, options));
|
|
52302
52435
|
if (!options?.selectTarget) {
|
|
52303
52436
|
return;
|
|
52304
52437
|
}
|
|
@@ -54768,6 +54901,7 @@ class BottomBarSheet extends owl.Component {
|
|
|
54768
54901
|
sheetDivRef = owl.useRef("sheetDiv");
|
|
54769
54902
|
sheetNameRef = owl.useRef("sheetNameSpan");
|
|
54770
54903
|
editionState = "initializing";
|
|
54904
|
+
DOMFocusableElementStore;
|
|
54771
54905
|
setup() {
|
|
54772
54906
|
owl.onMounted(() => {
|
|
54773
54907
|
if (this.isSheetActive) {
|
|
@@ -54780,6 +54914,7 @@ class BottomBarSheet extends owl.Component {
|
|
|
54780
54914
|
this.focusInputAndSelectContent();
|
|
54781
54915
|
}
|
|
54782
54916
|
});
|
|
54917
|
+
this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
|
|
54783
54918
|
}
|
|
54784
54919
|
focusInputAndSelectContent() {
|
|
54785
54920
|
if (!this.state.isEditing || !this.sheetNameRef.el)
|
|
@@ -54821,9 +54956,11 @@ class BottomBarSheet extends owl.Component {
|
|
|
54821
54956
|
if (ev.key === "Enter") {
|
|
54822
54957
|
ev.preventDefault();
|
|
54823
54958
|
this.stopEdition();
|
|
54959
|
+
this.DOMFocusableElementStore.focus();
|
|
54824
54960
|
}
|
|
54825
54961
|
if (ev.key === "Escape") {
|
|
54826
54962
|
this.cancelEdition();
|
|
54963
|
+
this.DOMFocusableElementStore.focus();
|
|
54827
54964
|
}
|
|
54828
54965
|
}
|
|
54829
54966
|
onClickSheetName(ev) {
|
|
@@ -56779,16 +56916,25 @@ class Spreadsheet extends owl.Component {
|
|
|
56779
56916
|
}
|
|
56780
56917
|
}, () => [this.env.model.getters.getActiveSheetId()]);
|
|
56781
56918
|
owl.useExternalListener(window, "resize", () => this.render(true));
|
|
56919
|
+
// For some reason, the wheel event is not properly registered inside templates
|
|
56920
|
+
// in Chromium-based browsers based on chromium 125
|
|
56921
|
+
// This hack ensures the event declared in the template is properly registered/working
|
|
56922
|
+
owl.useExternalListener(document.body, "wheel", () => { });
|
|
56782
56923
|
this.bindModelEvents();
|
|
56783
56924
|
owl.onWillUpdateProps((nextProps) => {
|
|
56784
56925
|
if (nextProps.model !== this.props.model) {
|
|
56785
56926
|
throw new Error("Changing the props model is not supported at the moment.");
|
|
56786
56927
|
}
|
|
56787
56928
|
});
|
|
56929
|
+
const render = batched(this.render.bind(this, true));
|
|
56788
56930
|
owl.onMounted(() => {
|
|
56789
56931
|
this.checkViewportSize();
|
|
56932
|
+
stores.on("store-updated", this, render);
|
|
56933
|
+
});
|
|
56934
|
+
owl.onWillUnmount(() => {
|
|
56935
|
+
this.unbindModelEvents();
|
|
56936
|
+
stores.off("store-updated", this);
|
|
56790
56937
|
});
|
|
56791
|
-
owl.onWillUnmount(() => this.unbindModelEvents());
|
|
56792
56938
|
owl.onPatched(() => {
|
|
56793
56939
|
this.checkViewportSize();
|
|
56794
56940
|
});
|
|
@@ -59537,7 +59683,11 @@ function addRows(construct, data, sheet) {
|
|
|
59537
59683
|
let cellNode = escapeXml ``;
|
|
59538
59684
|
// Either formula or static value inside the cell
|
|
59539
59685
|
if (cell.isFormula) {
|
|
59540
|
-
|
|
59686
|
+
const res = addFormula(cell);
|
|
59687
|
+
if (!res) {
|
|
59688
|
+
continue;
|
|
59689
|
+
}
|
|
59690
|
+
({ attrs: additionalAttrs, node: cellNode } = res);
|
|
59541
59691
|
}
|
|
59542
59692
|
else if (cell.content && isMarkdownLink(cell.content)) {
|
|
59543
59693
|
const { label } = parseMarkdownLink(cell.content);
|
|
@@ -60617,6 +60767,6 @@ exports.tokenColors = tokenColors;
|
|
|
60617
60767
|
exports.tokenize = tokenize;
|
|
60618
60768
|
|
|
60619
60769
|
|
|
60620
|
-
__info__.version = "17.2.
|
|
60621
|
-
__info__.date = "2024-
|
|
60622
|
-
__info__.hash = "
|
|
60770
|
+
__info__.version = "17.2.9";
|
|
60771
|
+
__info__.date = "2024-06-03T14:56:21.684Z";
|
|
60772
|
+
__info__.hash = "086af6d";
|