@odoo/o-spreadsheet 19.5.0-alpha.12 → 19.5.0-alpha.14

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.
Files changed (39) hide show
  1. package/dist/o_spreadsheet.cjs +625 -563
  2. package/dist/o_spreadsheet.css +38 -22
  3. package/dist/o_spreadsheet.esm.js +625 -563
  4. package/dist/o_spreadsheet.iife.js +625 -563
  5. package/dist/o_spreadsheet.min.iife.js +300 -300
  6. package/dist/o_spreadsheet.xml +80 -67
  7. package/dist/types/components/figures/figure_container/figure_container.d.ts +6 -2
  8. package/dist/types/components/helpers/figure_drag_helper.d.ts +3 -3
  9. package/dist/types/components/helpers/figure_snap_helper.d.ts +8 -3
  10. package/dist/types/components/link/link_editor/link_editor.d.ts +1 -0
  11. package/dist/types/components/side_panel/carousel_panel/carousel_panel.d.ts +1 -1
  12. package/dist/types/components/side_panel/chart/chart_type_picker_popover/chart_type_picker_popover.d.ts +12 -12
  13. package/dist/types/components/side_panel/chart/scorecard_chart_panel/scorecard_chart_config_panel.d.ts +6 -10
  14. package/dist/types/components/side_panel/find_and_replace/find_and_replace.d.ts +1 -0
  15. package/dist/types/components/side_panel/find_and_replace/find_and_replace_store.d.ts +2 -1
  16. package/dist/types/components/side_panel/table_style_editor_panel/table_style_editor_panel.d.ts +2 -0
  17. package/dist/types/constants.d.ts +0 -1
  18. package/dist/types/helpers/color_themes.d.ts +2 -0
  19. package/dist/types/helpers/figures/chart.d.ts +3 -2
  20. package/dist/types/helpers/figures/charts/chart_common.d.ts +2 -2
  21. package/dist/types/helpers/figures/charts/chart_ui_common.d.ts +3 -3
  22. package/dist/types/helpers/figures/charts/runtime/chart_data_extractor.d.ts +11 -10
  23. package/dist/types/helpers/owl3_helpers.d.ts +4 -0
  24. package/dist/types/index.d.ts +0 -1
  25. package/dist/types/owl3_compatibility_layer.d.ts +1 -14
  26. package/dist/types/plugins/ui_core_views/evaluation_chart.d.ts +6 -5
  27. package/dist/types/plugins/ui_feature/chart_ui.d.ts +6 -0
  28. package/dist/types/plugins/ui_feature/color_theme.d.ts +0 -3
  29. package/dist/types/registries/chart_registry.d.ts +2 -2
  30. package/dist/types/registries/figures_registry.d.ts +1 -1
  31. package/dist/types/stores/main_viewport_store.d.ts +3 -0
  32. package/dist/types/stores/viewports_store.d.ts +0 -1
  33. package/dist/types/types/chart/chart.d.ts +3 -1
  34. package/dist/types/types/chart/scorecard_chart.d.ts +3 -4
  35. package/dist/types/types/commands.d.ts +15 -17
  36. package/dist/types/types/getters.d.ts +2 -1
  37. package/dist/types/types/model.d.ts +2 -1
  38. package/dist/types/types/rendering.d.ts +2 -0
  39. package/package.json +4 -3
@@ -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.5.0-alpha.12
6
- * @date 2026-08-19T09:47:03.774Z
7
- * @hash 68ca68e
5
+ * @version 19.5.0-alpha.14
6
+ * @date 2026-08-29T09:17:09.184Z
7
+ * @hash e8ad6ad
8
8
  */
9
9
 
10
10
  (function(exports, _odoo_owl) {
@@ -403,7 +403,13 @@ _odoo_owl = __toESM(_odoo_owl, 1);
403
403
  if (isEnabled(env)) return item.execute(env, isMiddleClick);
404
404
  } : void 0,
405
405
  children: children ? (env) => {
406
- return children.map((child) => typeof child === "function" ? child(env) : child).flat().map(createAction).sort((a, b) => a.sequence - b.sequence);
406
+ const uniqueChildren = {};
407
+ children.flatMap((child) => typeof child === "function" ? child(env) : child).forEach((childSpec) => {
408
+ const childAction = createAction(childSpec);
409
+ if (uniqueChildren[childAction.id]) throw new Error(`Duplicate child action id "${childAction.id}" in action "${itemId}".`);
410
+ uniqueChildren[childAction.id] = childAction;
411
+ });
412
+ return Object.values(uniqueChildren).sort((a, b) => a.sequence - b.sequence);
407
413
  } : () => [],
408
414
  isReadonlyAllowed: item.isReadonlyAllowed || false,
409
415
  isEnabledOnLockedSheet: item.isEnabledOnLockedSheet || false,
@@ -2633,7 +2639,6 @@ stores.inject(MyMetaStore, storeInstance);
2633
2639
  *
2634
2640
  * 1. Update template directives:
2635
2641
  * - replace `t-portal` → `t-custom-portal`
2636
- * - replace `t-model` → `t-custom-model`
2637
2642
  *
2638
2643
  * 2. Load this file immediately after Owl 3.
2639
2644
  *
@@ -2648,35 +2653,23 @@ stores.inject(MyMetaStore, storeInstance);
2648
2653
  * Gradually remove the compatibility layer by migrating to native Owl 3:
2649
2654
  *
2650
2655
  * - replace `t-custom-portal` with proper Owl 3 portal usage
2651
- * - replace `t-custom-model` with `t-model` + signals
2652
2656
  * - convert `useLayoutEffect` back to `useEffect` where appropriate
2653
2657
  *
2654
2658
  * The end goal is to eliminate all compatibility shims.
2655
2659
  */
2656
- const { __ODOO_COMPATIBILITY_LAYER_ADDED__, blockDom: blockDom$1, config, onMounted: onMounted$26, onPatched: onPatched$5, onWillUnmount: onWillUnmount$20, App: OwlApp, Component: OwlComponent, EnvPlugin: OwlEnvPlugin, useChildEnv: OwlUseChildEnv, useChildSubEnv: OwlUseChildSubEnv, useComponent: OwlUseComponent, useEnv: OwlUseEnv, useExternalListener: OwlUseExternalListener, useLayoutEffect: OwlUseLayoutEffect, useSubEnv: OwlUseSubEnv, Plugin, plugin, props, providePlugins, useScope, xml: xml$5 } = _odoo_owl;
2660
+ const { __ODOO_COMPATIBILITY_LAYER_ADDED__, blockDom: blockDom$1, config, onMounted: onMounted$26, onPatched: onPatched$5, onWillUnmount: onWillUnmount$20, App: OwlApp, Component: OwlComponent, EnvPlugin: OwlEnvPlugin, useComponent: OwlUseComponent, useEnv: OwlUseEnv, useLayoutEffect: OwlUseLayoutEffect, useSubEnv: OwlUseSubEnv, Plugin, usePlugin, useProps: useProps$171, providePlugins, useScope, xml: xml$5 } = _odoo_owl;
2657
2661
  const isOdooCompatLoaded = __ODOO_COMPATIBILITY_LAYER_ADDED__ === true;
2658
2662
  var _Component = class extends OwlComponent {
2659
- static template = "";
2660
2663
  env;
2661
2664
  constructor(node) {
2662
2665
  super(node);
2663
- this.env = useChildEnv();
2664
- this.__owl__ = node;
2666
+ this.env = _useEnv();
2665
2667
  }
2666
2668
  setup() {}
2667
- render(deep = false) {
2668
- this.__owl__.render(deep === true);
2669
- }
2670
2669
  };
2671
2670
  function _useComponent() {
2672
2671
  return useScope().component;
2673
2672
  }
2674
- function _useExternalListener(target, eventName, handler, eventParams) {
2675
- const node = useScope();
2676
- const boundHandler = handler.bind(node.component);
2677
- onMounted$26(() => target.addEventListener(eventName, boundHandler, eventParams));
2678
- onWillUnmount$20(() => target.removeEventListener(eventName, boundHandler, eventParams));
2679
- }
2680
2673
  function onWillRender(cb) {
2681
2674
  const node = useScope();
2682
2675
  const renderFn = node.renderFn;
@@ -2714,27 +2707,14 @@ stores.inject(MyMetaStore, storeInstance);
2714
2707
  env = config("env") ?? {};
2715
2708
  };
2716
2709
  function _useEnv() {
2717
- return useScope().component.env;
2718
- }
2719
- function provideEnv(env) {
2720
- providePlugins([_EnvPlugin], { env });
2721
- return env;
2722
- }
2723
- function extendEnv(extension) {
2724
- const env = useChildEnv();
2725
- const subEnv = Object.create(env);
2726
- Object.defineProperties(subEnv, Object.getOwnPropertyDescriptors(extension));
2727
- return provideEnv(subEnv);
2710
+ return usePlugin(_EnvPlugin).env;
2728
2711
  }
2729
2712
  function _useSubEnv(extension) {
2730
- const component = useScope().component;
2731
- component.env = extendEnv(extension);
2732
- }
2733
- function _useChildSubEnv(extension) {
2734
- extendEnv(extension);
2735
- }
2736
- function _useChildEnv() {
2737
- return plugin(_EnvPlugin).env;
2713
+ const subEnv = Object.create(_useEnv());
2714
+ Object.defineProperties(subEnv, Object.getOwnPropertyDescriptors(extension));
2715
+ providePlugins([_EnvPlugin], { env: subEnv });
2716
+ const component = _useComponent();
2717
+ component.env = subEnv;
2738
2718
  }
2739
2719
  var VPortal = class extends blockDom$1.text("").constructor {
2740
2720
  /**
@@ -2783,7 +2763,7 @@ stores.inject(MyMetaStore, storeInstance);
2783
2763
  static template = xml$5`<t t-call-slot="default"/>`;
2784
2764
  constructor(node) {
2785
2765
  super(node);
2786
- this.props = props();
2766
+ this.props = useProps$171();
2787
2767
  this.__owl__ = node;
2788
2768
  }
2789
2769
  setup() {
@@ -2816,18 +2796,6 @@ stores.inject(MyMetaStore, storeInstance);
2816
2796
  /**
2817
2797
  * @param {HTMLElement} node
2818
2798
  * @param {string} value
2819
- * @param {string[]} modifiers
2820
- */
2821
- model: (node, value, modifiers) => {
2822
- let attribute = "t-model";
2823
- for (const modifier of modifiers) attribute += `.${modifier}`;
2824
- const getter = `() => ${value}`;
2825
- const setter = `(nv) => {${value} = nv;}`;
2826
- node.setAttribute(attribute, `__globals__.createModelSignal(${getter}, ${setter})`);
2827
- },
2828
- /**
2829
- * @param {HTMLElement} node
2830
- * @param {string} value
2831
2799
  */
2832
2800
  portal: (node, value) => {
2833
2801
  if (node.nodeName.toLowerCase() !== "t") throw new Error("t-custom-portal should be on a 't' element");
@@ -2856,11 +2824,6 @@ set(value) {
2856
2824
  refInfo.values[refId] = value;
2857
2825
  } };
2858
2826
  },
2859
- /**
2860
- * @param {Function} getter
2861
- * @param {Function} setter
2862
- */
2863
- createModelSignal: (getter, setter) => Object.assign(getter, { set: setter }),
2864
2827
  Portal
2865
2828
  };
2866
2829
  var _App = class extends OwlApp {
@@ -2886,7 +2849,7 @@ set(value) {
2886
2849
  createRoot(component, config = {}) {
2887
2850
  if (config.env) component = { [component.name]: class extends component {
2888
2851
  constructor(node) {
2889
- provideEnv(config.env);
2852
+ providePlugins([_EnvPlugin], { env: config.env });
2890
2853
  super(node);
2891
2854
  }
2892
2855
  } }[component.name];
@@ -2895,13 +2858,10 @@ set(value) {
2895
2858
  };
2896
2859
  const Component = isOdooCompatLoaded ? OwlComponent : _Component;
2897
2860
  const useComponent = isOdooCompatLoaded ? OwlUseComponent : _useComponent;
2898
- const useExternalListener = isOdooCompatLoaded ? OwlUseExternalListener : _useExternalListener;
2899
2861
  const useLayoutEffect = isOdooCompatLoaded ? OwlUseLayoutEffect : _useLayoutEffect;
2900
2862
  const EnvPlugin = isOdooCompatLoaded ? OwlEnvPlugin : _EnvPlugin;
2901
2863
  const useEnv = isOdooCompatLoaded ? OwlUseEnv : _useEnv;
2902
2864
  const useSubEnv = isOdooCompatLoaded ? OwlUseSubEnv : _useSubEnv;
2903
- const useChildEnv = isOdooCompatLoaded ? OwlUseChildEnv : _useChildEnv;
2904
- const useChildSubEnv = isOdooCompatLoaded ? OwlUseChildSubEnv : _useChildSubEnv;
2905
2865
  const App$1 = isOdooCompatLoaded ? OwlApp : _App;
2906
2866
 
2907
2867
  //#endregion
@@ -5409,7 +5369,7 @@ set(value) {
5409
5369
  }
5410
5370
  function humanizeNumber({ value, format }, locale) {
5411
5371
  const numberValue = tryToNumber(value, locale);
5412
- if (numberValue === void 0) return "";
5372
+ if (numberValue === void 0) return value?.toString() || "";
5413
5373
  let numberFormat = format;
5414
5374
  if (Math.abs(numberValue) < 1e3) {
5415
5375
  const hasDecimal = numberValue % 1 !== 0;
@@ -7945,7 +7905,8 @@ set(value) {
7945
7905
  "UPDATE_CHART",
7946
7906
  "UPDATE_CHART_REGION",
7947
7907
  "UPDATE_CAROUSEL_ACTIVE_ITEM",
7948
- "UPDATE_PIVOT"
7908
+ "UPDATE_PIVOT",
7909
+ "UPDATE_COLOR_SCHEME"
7949
7910
  ]);
7950
7911
  const lockedSheetAllowedCommands = /* @__PURE__ */ new Set([
7951
7912
  "LOCK_SHEET",
@@ -8124,8 +8085,6 @@ set(value) {
8124
8085
  CommandResult["InvalidXRange"] = "InvalidXRange";
8125
8086
  CommandResult["InvalidLabelRange"] = "InvalidLabelRange";
8126
8087
  CommandResult["InvalidBubbleSizeRange"] = "InvalidBubbleSizeRange";
8127
- CommandResult["InvalidScorecardKeyValue"] = "InvalidScorecardKeyValue";
8128
- CommandResult["InvalidScorecardBaseline"] = "InvalidScorecardBaseline";
8129
8088
  CommandResult["InvalidGaugeDataRange"] = "InvalidGaugeDataRange";
8130
8089
  CommandResult["EmptyGaugeRangeMin"] = "EmptyGaugeRangeMin";
8131
8090
  CommandResult["GaugeRangeMinNaN"] = "GaugeRangeMinNaN";
@@ -9991,6 +9950,46 @@ set(value) {
9991
9950
  ];
9992
9951
  const CONTENT_TYPES_FILE = "[Content_Types].xml";
9993
9952
 
9953
+ //#endregion
9954
+ //#region src/helpers/color_themes.ts
9955
+ const FROZEN_PANE_HEADER_BORDER_COLOR = "#BCBCBC";
9956
+ const FROZEN_PANE_BORDER_COLOR = "#DADFE8";
9957
+ const HEADER_BORDER_COLOR = "#C0C0C0";
9958
+ const TEXT_HEADER_COLOR = "#666666";
9959
+ const BACKGROUND_HEADER_COLOR = "#F8F9FA";
9960
+ const BACKGROUND_HEADER_SELECTED_COLOR = "#E8EAED";
9961
+ const BACKGROUND_HEADER_ACTIVE_COLOR = "#595959";
9962
+ const COLOR_THEMES = {
9963
+ light: {
9964
+ colorThemeName: "light",
9965
+ backgroundColor: "#FFFFFF",
9966
+ gridBorderColor: "#CECFCF",
9967
+ headerBackgroundColor: BACKGROUND_HEADER_COLOR,
9968
+ headerActiveBackgroundColor: BACKGROUND_HEADER_ACTIVE_COLOR,
9969
+ headerSelectedBackgroundColor: BACKGROUND_HEADER_SELECTED_COLOR,
9970
+ headerTextColor: TEXT_HEADER_COLOR,
9971
+ headerBorderColor: HEADER_BORDER_COLOR,
9972
+ frozenPaneBorderColor: FROZEN_PANE_BORDER_COLOR,
9973
+ frozenPaneHeaderBorderColor: FROZEN_PANE_HEADER_BORDER_COLOR,
9974
+ singleCellSelectionBackgroundColor: "#F3F7FE",
9975
+ multipleCellsSelectionBackgroundColor: "#E9F0FF"
9976
+ },
9977
+ dark: {
9978
+ colorThemeName: "dark",
9979
+ backgroundColor: adaptForDarkMode("#1A1C2E"),
9980
+ gridBorderColor: adaptForDarkMode("#6B706F"),
9981
+ headerBackgroundColor: adaptForDarkMode("#262A36"),
9982
+ headerActiveBackgroundColor: adaptForDarkMode("#3A4052"),
9983
+ headerSelectedBackgroundColor: adaptForDarkMode("#4E566E"),
9984
+ headerTextColor: adaptForDarkMode("#A1A6B3"),
9985
+ headerBorderColor: adaptForDarkMode("#7A7F91"),
9986
+ frozenPaneBorderColor: adaptForDarkMode("#7A7F91"),
9987
+ frozenPaneHeaderBorderColor: adaptForDarkMode("#9FA5BD"),
9988
+ singleCellSelectionBackgroundColor: adaptForDarkMode("#696E8044"),
9989
+ multipleCellsSelectionBackgroundColor: adaptForDarkMode("#828AA044")
9990
+ }
9991
+ };
9992
+
9994
9993
  //#endregion
9995
9994
  //#region src/helpers/figures/charts/chart_common.ts
9996
9995
  const TREND_LINE_XAXIS_ID = "x1";
@@ -10212,9 +10211,8 @@ set(value) {
10212
10211
  function isTrendLineAxis(axisID) {
10213
10212
  return axisID === "x1" || axisID === "xMovingAverage";
10214
10213
  }
10215
- function getChartBackgroundColor({ background }, getters) {
10216
- const defaultColor = getters.getSpreadsheetTheme().backgroundColor;
10217
- if (!background) return defaultColor;
10214
+ function getChartBackgroundColor({ background }, colorThemeName) {
10215
+ if (!background) return COLOR_THEMES[colorThemeName].backgroundColor;
10218
10216
  return background;
10219
10217
  }
10220
10218
 
@@ -12012,6 +12010,110 @@ set(value) {
12012
12010
  }
12013
12011
  };
12014
12012
 
12013
+ //#endregion
12014
+ //#region src/functions/helper_matrices.ts
12015
+ function getUnitMatrix(n) {
12016
+ const matrix = Array(n);
12017
+ for (let i = 0; i < n; i++) {
12018
+ matrix[i] = Array(n).fill(0);
12019
+ matrix[i][i] = 1;
12020
+ }
12021
+ return matrix;
12022
+ }
12023
+ /**
12024
+ * Invert a matrix and compute its determinant using Gaussian Elimination.
12025
+ *
12026
+ * The Matrix should be a square matrix, and should be indexed [col][row] instead of the
12027
+ * standard mathematical indexing [row][col].
12028
+ */
12029
+ function invertMatrix(M) {
12030
+ if (M.length < 1 || M[0].length < 1) throw new Error("invertMatrix: an empty matrix cannot be inverted.");
12031
+ if (M.length !== M[0].length) throw new Error("invertMatrix: only square matrices are invertible");
12032
+ let determinant = 1;
12033
+ const dim = M.length;
12034
+ const I = getUnitMatrix(dim);
12035
+ const C = M.map((row) => row.slice());
12036
+ for (let pivot = 0; pivot < dim; pivot++) {
12037
+ let diagonalElement = C[pivot][pivot];
12038
+ if (diagonalElement === 0) {
12039
+ for (let row = pivot + 1; row < dim; row++) if (C[pivot][row] !== 0) {
12040
+ swapMatrixRows(C, pivot, row);
12041
+ swapMatrixRows(I, pivot, row);
12042
+ determinant *= -1;
12043
+ break;
12044
+ }
12045
+ diagonalElement = C[pivot][pivot];
12046
+ if (diagonalElement === 0) return { determinant: 0 };
12047
+ }
12048
+ for (let col = 0; col < dim; col++) {
12049
+ C[col][pivot] = C[col][pivot] / diagonalElement;
12050
+ I[col][pivot] = I[col][pivot] / diagonalElement;
12051
+ }
12052
+ determinant *= diagonalElement;
12053
+ for (let row = 0; row < dim; row++) {
12054
+ if (row === pivot) continue;
12055
+ const e = C[pivot][row];
12056
+ for (let col = 0; col < dim; col++) {
12057
+ C[col][row] -= e * C[col][pivot];
12058
+ I[col][row] -= e * I[col][pivot];
12059
+ }
12060
+ }
12061
+ }
12062
+ return {
12063
+ inverted: I,
12064
+ determinant
12065
+ };
12066
+ }
12067
+ function swapMatrixRows(matrix, row1, row2) {
12068
+ for (let i = 0; i < matrix.length; i++) {
12069
+ const tmp = matrix[i][row1];
12070
+ matrix[i][row1] = matrix[i][row2];
12071
+ matrix[i][row2] = tmp;
12072
+ }
12073
+ }
12074
+ /**
12075
+ * Matrix multiplication of 2 matrices.
12076
+ * ex: matrix1 : n x l, matrix2 : m x n => result : m x l
12077
+ *
12078
+ * Note: we use indexing [col][row] instead of the standard mathematical notation [row][col]
12079
+ */
12080
+ function multiplyMatrices(matrix1, matrix2) {
12081
+ if (matrix1.length < 1 || matrix2.length < 1) throw new Error("multiplyMatrices: empty matrices cannot be multiplied.");
12082
+ if (matrix1.length !== matrix2[0].length) throw new Error("multiplyMatrices: incompatible matrices size.");
12083
+ const rowsM1 = matrix1[0].length;
12084
+ const colsM2 = matrix2.length;
12085
+ const n = matrix1.length;
12086
+ const result = Array(colsM2);
12087
+ for (let col = 0; col < colsM2; col++) {
12088
+ result[col] = Array(rowsM1);
12089
+ for (let row = 0; row < rowsM1; row++) {
12090
+ let sum = 0;
12091
+ for (let k = 0; k < n; k++) sum += matrix1[k][row] * matrix2[col][k];
12092
+ result[col][row] = sum;
12093
+ }
12094
+ }
12095
+ return result;
12096
+ }
12097
+ /**
12098
+ * Return the input if it's a scalar or the first element of the input if it's a matrix.
12099
+ */
12100
+ function toScalar(arg) {
12101
+ if (!isMatrix(arg)) return arg;
12102
+ if (!isSingleElementMatrix(arg)) throw new Error("The value should be a scalar or a 1x1 matrix");
12103
+ return arg[0][0];
12104
+ }
12105
+ function isSingleElementMatrix(matrix) {
12106
+ return matrix.length === 1 && matrix[0].length === 1;
12107
+ }
12108
+ function isMultipleElementMatrix(arg) {
12109
+ return isMatrix(arg) && !isSingleElementMatrix(arg);
12110
+ }
12111
+ function getMatrixArgIndices(args) {
12112
+ const indices = [];
12113
+ for (let i = 0; i < args.length; i++) if (isMultipleElementMatrix(args[i])) indices.push(i);
12114
+ return indices;
12115
+ }
12116
+
12015
12117
  //#endregion
12016
12118
  //#region src/helpers/figures/charts/abstract_chart.ts
12017
12119
  var AbstractChart = class {
@@ -12027,11 +12129,42 @@ set(value) {
12027
12129
 
12028
12130
  //#endregion
12029
12131
  //#region src/helpers/figures/charts/scorecard_chart.ts
12132
+ function getData$1(value, getters, sheetId) {
12133
+ if (!value) return {
12134
+ scalar: void 0,
12135
+ range: void 0
12136
+ };
12137
+ if (!isFormula(value)) return {
12138
+ scalar: { value },
12139
+ range: void 0
12140
+ };
12141
+ const result = getters.evaluateFormulaResult(sheetId, value);
12142
+ let scalar = isMultipleElementMatrix(result) ? result[0][0] : toScalar(result);
12143
+ let range = void 0;
12144
+ const xc = getFormulaRangeXc(value);
12145
+ if (xc) {
12146
+ range = createValidRange(getters, sheetId, xc);
12147
+ if (range) {
12148
+ if (getters.getEvaluatedCell({
12149
+ sheetId: range.sheetId,
12150
+ col: range.zone.left,
12151
+ row: range.zone.top
12152
+ }).type === "empty") scalar = void 0;
12153
+ }
12154
+ }
12155
+ return {
12156
+ scalar,
12157
+ range
12158
+ };
12159
+ }
12030
12160
  function getBaselineText(baseline, keyValue, baselineMode, humanizeNumbers, locale) {
12031
12161
  if (!baseline) return "";
12032
- else if (baselineMode === "text" || keyValue?.type !== "number" || baseline.type !== "number") {
12162
+ else if (baselineMode === "text" || typeof keyValue?.value !== "number" || typeof baseline.value !== "number") {
12033
12163
  if (humanizeNumbers) return humanizeNumber(baseline, locale);
12034
- return baseline.formattedValue;
12164
+ return formatValue(baseline.value, {
12165
+ format: baseline.format,
12166
+ locale
12167
+ });
12035
12168
  }
12036
12169
  let { value, format } = baseline;
12037
12170
  if (baselineMode === "progress") {
@@ -12052,29 +12185,31 @@ set(value) {
12052
12185
  locale
12053
12186
  });
12054
12187
  }
12055
- function getKeyValueText(keyValueCell, humanizeNumbers, locale) {
12056
- if (!keyValueCell) return "";
12057
- if (humanizeNumbers) return humanizeNumber(keyValueCell, locale);
12058
- return keyValueCell.formattedValue ?? String(keyValueCell.value ?? "");
12188
+ function getKeyValueText(keyValue, humanizeNumbers, locale) {
12189
+ if (keyValue?.value === void 0 || keyValue?.value === null) return "";
12190
+ if (humanizeNumbers) return humanizeNumber(keyValue, locale);
12191
+ return keyValue.format ? formatValue(keyValue.value, {
12192
+ format: keyValue.format,
12193
+ locale
12194
+ }) : String(keyValue.value ?? "");
12059
12195
  }
12060
12196
  function getBaselineColor(baseline, baselineMode, keyValue, colorUp, colorDown) {
12061
- if (baselineMode === "text" || baselineMode === "progress" || baseline?.type !== "number" || keyValue?.type !== "number") return;
12197
+ if (baselineMode === "text" || baselineMode === "progress" || typeof baseline?.value !== "number" || typeof keyValue?.value !== "number") return;
12062
12198
  const diff = keyValue.value - baseline.value;
12063
12199
  if (diff > 0) return colorUp;
12064
12200
  else if (diff < 0) return colorDown;
12065
12201
  }
12066
12202
  function getBaselineArrowDirection(baseline, keyValue, baselineMode) {
12067
- if (baselineMode === "text" || baseline?.type !== "number" || keyValue?.type !== "number") return "neutral";
12203
+ if (baselineMode === "text" || typeof baseline?.value !== "number" || typeof keyValue?.value !== "number") return "neutral";
12068
12204
  const diff = keyValue.value - baseline.value;
12069
12205
  if (diff > 0) return "up";
12070
12206
  else if (diff < 0) return "down";
12071
12207
  return "neutral";
12072
12208
  }
12073
- function checkKeyValue(definition) {
12074
- return definition.keyValue && !rangeReference.test(definition.keyValue) ? "InvalidScorecardKeyValue" : "Success";
12075
- }
12076
- function checkBaseline(definition) {
12077
- return definition.baseline && !rangeReference.test(definition.baseline) ? "InvalidScorecardBaseline" : "Success";
12209
+ function getFormulaRangeXc(formula) {
12210
+ if (!formula || !isFormula(formula)) return;
12211
+ const content = formula.slice(1);
12212
+ return rangeReference.test(content) ? content : void 0;
12078
12213
  }
12079
12214
  const Path2DConstructor = globalThis.Path2D;
12080
12215
  const arrowDownPath = Path2DConstructor && new Path2DConstructor("M8.6 4.8a.5.5 0 0 1 0 .75l-3.9 3.9a.5 .5 0 0 1 -.75 0l-3.8 -3.9a.5 .5 0 0 1 0 -.75l.4-.4a.5.5 0 0 1 .75 0l2.3 2.4v-5.7c0-.25.25-.5.5-.5h.6c.25 0 .5.25.5.5v5.8l2.3 -2.4a.5.5 0 0 1 .75 0z");
@@ -12091,84 +12226,76 @@ set(value) {
12091
12226
  "baselineColorUp",
12092
12227
  "baselineColorDown"
12093
12228
  ],
12094
- fromStrDefinition(definition, sheetId, getters) {
12095
- const baseline = createValidRange(getters, sheetId, definition.baseline);
12096
- const keyValue = createValidRange(getters, sheetId, definition.keyValue);
12229
+ fromStrDefinition: (definition) => definition,
12230
+ validateDefinition(validator, definition) {
12231
+ return "Success";
12232
+ },
12233
+ copyInSheetId: (definition, sheetIdFrom, sheetIdTo, getters) => {
12234
+ const adaptFormula = (formula) => getters.copyFormulaStringForSheet(sheetIdFrom, sheetIdTo, formula, "keepSameReference");
12097
12235
  return {
12098
12236
  ...definition,
12099
- baseline,
12100
- keyValue
12237
+ keyValue: definition.keyValue ? adaptFormula(definition.keyValue) : definition.keyValue,
12238
+ baseline: definition.baseline ? adaptFormula(definition.baseline) : definition.baseline
12101
12239
  };
12102
12240
  },
12103
- validateDefinition(validator, definition) {
12104
- return validator.checkValidations(definition, checkKeyValue, checkBaseline);
12105
- },
12106
- copyInSheetId: (definition) => definition,
12107
12241
  getDefinitionFromContextCreation(context, dataSourceBuilder) {
12242
+ const dataRange = context.dataSource?.type === "range" ? context.dataSource?.dataSets?.[0]?.dataRange : void 0;
12243
+ const keyValue = (context.scorecardKeyValueFormula === void 0 || getFormulaRangeXc(context.scorecardKeyValueFormula)) && dataRange ? `=${dataRange}` : context.scorecardKeyValueFormula;
12244
+ const baseline = (context.scorecardBaselineFormula === void 0 || getFormulaRangeXc(context.scorecardBaselineFormula)) && context.auxiliaryRange ? `=${context.auxiliaryRange}` : context.scorecardBaselineFormula;
12108
12245
  return {
12109
12246
  background: context.background,
12110
12247
  type: "scorecard",
12111
- keyValue: context.dataSource?.type === "range" ? context.dataSource?.dataSets?.[0]?.dataRange : void 0,
12248
+ keyValue,
12112
12249
  title: context.title || { text: "" },
12113
12250
  baselineMode: DEFAULT_SCORECARD_BASELINE_MODE,
12114
12251
  baselineColorUp: DEFAULT_SCORECARD_BASELINE_COLOR_UP,
12115
12252
  baselineColorDown: DEFAULT_SCORECARD_BASELINE_COLOR_DOWN,
12116
- baseline: context.auxiliaryRange || "",
12253
+ baseline,
12117
12254
  humanize: context.humanize,
12118
12255
  annotationLink: context.annotationLink,
12119
12256
  annotationText: context.annotationText
12120
12257
  };
12121
12258
  },
12122
- transformDefinition(definition, chartSheetId, { adaptRangeString }) {
12259
+ transformDefinition(definition, chartSheetId, { adaptFormulaString }) {
12123
12260
  let baseline;
12124
12261
  let keyValue;
12125
- if (definition.baseline) {
12126
- const { changeType, range: adaptedRange } = adaptRangeString(chartSheetId, definition.baseline);
12127
- if (changeType !== "REMOVE") baseline = adaptedRange;
12128
- }
12129
- if (definition.keyValue) {
12130
- const { changeType, range: adaptedRange } = adaptRangeString(chartSheetId, definition.keyValue);
12131
- if (changeType !== "REMOVE") keyValue = adaptedRange;
12132
- }
12133
- return {
12134
- ...definition,
12135
- baseline,
12136
- keyValue
12137
- };
12138
- },
12139
- duplicateInDuplicatedSheet(definition, sheetIdFrom, sheetIdTo) {
12140
- const baseline = duplicateLabelRangeInDuplicatedSheet(sheetIdFrom, sheetIdTo, definition.baseline);
12141
- const keyValue = duplicateLabelRangeInDuplicatedSheet(sheetIdFrom, sheetIdTo, definition.keyValue);
12262
+ if (definition.baseline) baseline = adaptFormulaString(chartSheetId, definition.baseline);
12263
+ if (definition.keyValue) keyValue = adaptFormulaString(chartSheetId, definition.keyValue);
12142
12264
  return {
12143
12265
  ...definition,
12144
12266
  baseline,
12145
12267
  keyValue
12146
12268
  };
12147
12269
  },
12148
- toStrDefinition(definition, sheetId, getters) {
12270
+ duplicateInDuplicatedSheet(definition, sheetIdFrom, sheetIdTo, getters) {
12271
+ const adaptFormula = (formula) => getters.copyFormulaStringForSheet(sheetIdFrom, sheetIdTo, formula, "moveReference");
12149
12272
  return {
12150
12273
  ...definition,
12151
- keyValue: definition.keyValue ? getters.getRangeString(definition.keyValue, sheetId) : void 0,
12152
- baseline: definition.baseline ? getters.getRangeString(definition.baseline, sheetId) : void 0
12274
+ keyValue: definition.keyValue ? adaptFormula(definition.keyValue) : definition.keyValue,
12275
+ baseline: definition.baseline ? adaptFormula(definition.baseline) : definition.baseline
12153
12276
  };
12154
12277
  },
12278
+ toStrDefinition: (definition) => definition,
12155
12279
  getContextCreation(definition, dataSource) {
12280
+ const keyValueXc = getFormulaRangeXc(definition.keyValue);
12156
12281
  return {
12157
12282
  ...definition,
12158
12283
  dataSource: {
12159
12284
  type: "range",
12160
- dataSets: definition.keyValue ? [{
12161
- dataRange: definition.keyValue,
12285
+ dataSets: keyValueXc ? [{
12286
+ dataRange: keyValueXc,
12162
12287
  dataSetId: "0"
12163
12288
  }] : []
12164
12289
  },
12165
- auxiliaryRange: definition.baseline
12290
+ auxiliaryRange: getFormulaRangeXc(definition.baseline),
12291
+ scorecardKeyValueFormula: definition.keyValue,
12292
+ scorecardBaselineFormula: definition.baseline
12166
12293
  };
12167
12294
  },
12168
12295
  getDefinitionForExcel: () => void 0,
12169
- updateRanges(definition, adapterFunctions) {
12170
- const baseline = adaptChartRange(definition.baseline, adapterFunctions);
12171
- const keyValue = adaptChartRange(definition.keyValue, adapterFunctions);
12296
+ updateRanges(definition, adapterFunctions, sheetId) {
12297
+ const baseline = definition.baseline ? adapterFunctions.adaptFormulaString(sheetId, definition.baseline) : definition.baseline;
12298
+ const keyValue = definition.keyValue ? adapterFunctions.adaptFormulaString(sheetId, definition.keyValue) : definition.keyValue;
12172
12299
  if (definition.baseline === baseline && definition.keyValue === keyValue) return definition;
12173
12300
  return {
12174
12301
  ...definition,
@@ -12176,32 +12303,21 @@ set(value) {
12176
12303
  keyValue
12177
12304
  };
12178
12305
  },
12179
- getFormulas: () => [],
12180
- getRuntime(getters, definition) {
12306
+ getFormulas(getters, sheetId, definition) {
12307
+ const formulas = [];
12308
+ if (definition.keyValue && isFormula(definition.keyValue)) formulas.push(CompiledFormula.Compile(definition.keyValue, sheetId, getters));
12309
+ if (definition.baseline && isFormula(definition.baseline)) formulas.push(CompiledFormula.Compile(definition.baseline, sheetId, getters));
12310
+ return formulas;
12311
+ },
12312
+ getRuntime(getters, definition, _dataExtractor, sheetId, eventHandlers, colorThemeName) {
12181
12313
  let formattedKeyValue = "";
12182
- let keyValueCell;
12314
+ const { scalar: keyValue, range: keyValueRange } = getData$1(definition.keyValue, getters, sheetId);
12183
12315
  const locale = getters.getLocale();
12184
- if (definition.keyValue) {
12185
- const keyValuePosition = {
12186
- sheetId: definition.keyValue.sheetId,
12187
- col: definition.keyValue.zone.left,
12188
- row: definition.keyValue.zone.top
12189
- };
12190
- keyValueCell = getters.getEvaluatedCell(keyValuePosition);
12191
- formattedKeyValue = getKeyValueText(keyValueCell, definition.humanize ?? true, locale);
12192
- }
12193
- let baselineCell;
12194
- const baseline = definition.baseline;
12195
- if (baseline) {
12196
- const baselinePosition = {
12197
- sheetId: baseline.sheetId,
12198
- col: baseline.zone.left,
12199
- row: baseline.zone.top
12200
- };
12201
- baselineCell = getters.getEvaluatedCell(baselinePosition);
12202
- }
12203
- const { background, fontColor } = getters.getStyleOfSingleCellChart(definition.background, definition.keyValue);
12204
- const baselineDisplay = getBaselineText(baselineCell, keyValueCell, definition.baselineMode, definition.humanize ?? true, locale);
12316
+ if (keyValue !== null && keyValue !== void 0) formattedKeyValue = getKeyValueText(keyValue, definition.humanize ?? true, locale);
12317
+ else formattedKeyValue = "";
12318
+ const { scalar: baseline, range: baselineRange } = getData$1(definition.baseline, getters, sheetId);
12319
+ const { background, fontColor } = getters.getStyleOfSingleCellChart(definition.background, keyValueRange, colorThemeName);
12320
+ const baselineDisplay = getBaselineText(baseline, keyValue, definition.baselineMode, definition.humanize ?? true, locale);
12205
12321
  const baselineValue = definition.baselineMode === "progress" && isNumber(baselineDisplay, locale) ? toNumber(baselineDisplay, locale) : 0;
12206
12322
  const title = definition.title;
12207
12323
  return {
@@ -12212,16 +12328,16 @@ set(value) {
12212
12328
  keyValue: formattedKeyValue,
12213
12329
  keyDescr: definition.keyDescr?.text ? getters.dynamicTranslate(definition.keyDescr.text) : "",
12214
12330
  baselineDisplay,
12215
- baselineArrow: getBaselineArrowDirection(baselineCell, keyValueCell, definition.baselineMode),
12216
- baselineColor: getBaselineColor(baselineCell, definition.baselineMode, keyValueCell, definition.baselineColorUp, definition.baselineColorDown),
12331
+ baselineArrow: getBaselineArrowDirection(baseline, keyValue, definition.baselineMode),
12332
+ baselineColor: getBaselineColor(baseline, definition.baselineMode, keyValue, definition.baselineColorUp, definition.baselineColorDown),
12217
12333
  baselineDescr: definition.baselineMode !== "progress" && definition.baselineDescr?.text ? getters.dynamicTranslate(definition.baselineDescr.text) : "",
12218
12334
  fontColor,
12219
12335
  background,
12220
12336
  baselineStyle: {
12221
- ...definition.baselineMode !== "percentage" && definition.baselineMode !== "progress" && baseline ? getters.getCellComputedStyle({
12222
- sheetId: baseline.sheetId,
12223
- col: baseline.zone.left,
12224
- row: baseline.zone.top
12337
+ ...definition.baselineMode !== "percentage" && definition.baselineMode !== "progress" && baselineRange ? getters.getCellComputedStyle({
12338
+ sheetId: baselineRange.sheetId,
12339
+ col: baselineRange.zone.left,
12340
+ row: baselineRange.zone.top
12225
12341
  }) : void 0,
12226
12342
  fontSize: definition.baselineDescr?.fontSize,
12227
12343
  align: definition.baselineDescr?.align
@@ -12231,10 +12347,10 @@ set(value) {
12231
12347
  ...definition.baselineDescr
12232
12348
  },
12233
12349
  keyValueStyle: {
12234
- ...definition.keyValue ? getters.getCellComputedStyle({
12235
- sheetId: definition.keyValue.sheetId,
12236
- col: definition.keyValue.zone.left,
12237
- row: definition.keyValue.zone.top
12350
+ ...keyValueRange ? getters.getCellComputedStyle({
12351
+ sheetId: keyValueRange.sheetId,
12352
+ col: keyValueRange.zone.left,
12353
+ row: keyValueRange.zone.top
12238
12354
  }) : void 0,
12239
12355
  fontSize: definition.keyDescr?.fontSize,
12240
12356
  align: definition.keyDescr?.align
@@ -13736,33 +13852,8 @@ set(value) {
13736
13852
  displayedSheetId = this.model.getters.getActiveSheetId();
13737
13853
  constructor(get) {
13738
13854
  super(get);
13739
- this.model.selection.observe(this, { handleEvent: this.handleEvent.bind(this) });
13740
- this.onDispose(() => {
13741
- this.model.selection.unobserve(this);
13742
- });
13743
13855
  this.viewports.resetViewports(this.displayedSheetId);
13744
13856
  }
13745
- handleEvent(event) {
13746
- const eventSheetId = this.getters.getActiveSheetId();
13747
- if (event.options.scrollIntoView) {
13748
- const oldZone = event.previousAnchor.zone;
13749
- const newZone = event.anchor.zone;
13750
- const isUpdateAnchorEvent = event.mode === "updateAnchor";
13751
- const sameZone = isEqual(oldZone, newZone);
13752
- let { col, row } = isUpdateAnchorEvent && sameZone ? event.anchor.cell : findCellInNewZone(oldZone, newZone);
13753
- if (isUpdateAnchorEvent && !sameZone) {
13754
- const { top, bottom, left, right } = this.viewports.getMainInternalViewport(eventSheetId);
13755
- if (oldZone.left === newZone.left && oldZone.right === newZone.right) col = left > col || col > right ? left : col;
13756
- if (oldZone.top === newZone.top && oldZone.bottom === newZone.bottom) row = top > row || row > bottom ? top : row;
13757
- }
13758
- col = Math.min(col, this.getters.getNumberCols(eventSheetId) - 1);
13759
- row = Math.min(row, this.getters.getNumberRows(eventSheetId) - 1);
13760
- if (!this.sheetsWithDirtyViewports.has(eventSheetId)) this.viewports.refreshViewport(eventSheetId, {
13761
- col,
13762
- row
13763
- });
13764
- }
13765
- }
13766
13857
  handle(cmd) {
13767
13858
  if (invalidateEvaluationCommands.has(cmd.type)) for (const sheetId of this.getters.getSheetIds()) this.sheetsWithDirtyViewports.add(sheetId);
13768
13859
  switch (cmd.type) {
@@ -13862,6 +13953,7 @@ set(value) {
13862
13953
  this.shiftVertically(topRowDims.end - boundaryTopY - viewportHeight);
13863
13954
  }
13864
13955
  scrollToCell(sheetId, col, row) {
13956
+ if (this.sheetsWithDirtyViewports.has(sheetId)) return;
13865
13957
  this.viewports.refreshViewport(sheetId, {
13866
13958
  col,
13867
13959
  row
@@ -14464,22 +14556,35 @@ set(value) {
14464
14556
  const step = length / maxPoints;
14465
14557
  return Array.from({ length: maxPoints }, (_, i) => Math.min(length - 1, Math.floor(i * step)));
14466
14558
  }
14467
- async function chartToImageUrl(runtime, figure, type) {
14559
+ async function chartToImageUrl(runtime, figure, type, colorThemeName = "light") {
14468
14560
  try {
14469
14561
  const canvas = createRenderingSurface(figure.width, figure.height);
14470
14562
  const cleanup = drawChartOnCanvas(canvas, runtime, figure, type);
14471
- const imageUrl = await canvasToObjectUrl(canvas);
14563
+ const imageUrl = await canvasToObjectUrl(colorThemeName === "dark" ? applyDarkMode(canvas) : canvas);
14472
14564
  cleanup();
14473
14565
  return imageUrl;
14474
14566
  } catch (error) {
14475
14567
  console.log("Error exporting chart to image URL: " + error.message);
14476
14568
  }
14477
14569
  }
14478
- async function chartToImageFile(runtime, figure, type) {
14570
+ /**
14571
+ * Charts are drawn with pre-inverted colors (see `adaptForDarkMode`) because they are displayed
14572
+ * through the `os-theme-dependant` CSS filter. An exported image doesn't get that filter, so it
14573
+ * has to be applied to the pixels to obtain what is actually displayed on screen.
14574
+ */
14575
+ function applyDarkMode(canvas) {
14576
+ const filtered = createRenderingSurface(canvas.width, canvas.height);
14577
+ const ctx = filtered.getContext("2d");
14578
+ if (!ctx || !("filter" in ctx)) return canvas;
14579
+ ctx.filter = DARK_MODE_FILTER_STRING;
14580
+ ctx.drawImage(canvas, 0, 0);
14581
+ return filtered;
14582
+ }
14583
+ async function chartToImageFile(runtime, figure, type, colorThemeName = "light") {
14479
14584
  try {
14480
14585
  const canvas = createRenderingSurface(figure.width, figure.height);
14481
14586
  const cleanup = drawChartOnCanvas(canvas, runtime, figure, type);
14482
- const chartBlob = await canvasToBlob(canvas);
14587
+ const chartBlob = await canvasToBlob(colorThemeName === "dark" ? applyDarkMode(canvas) : canvas);
14483
14588
  cleanup();
14484
14589
  return chartBlob;
14485
14590
  } catch (error) {
@@ -14787,7 +14892,7 @@ set(value) {
14787
14892
  const chartId = env.model.getters.getChartIdFromFigureId(figureId);
14788
14893
  if (!chartId) return;
14789
14894
  const chartType = env.model.getters.getChartType(chartId);
14790
- const blob = await chartToImageFile(env.model.getters.getChartRuntime(chartId), figure, chartType);
14895
+ const blob = await chartToImageFile(env.model.getters.getChartRuntime(chartId), figure, chartType, env.model.getters.getSpreadsheetTheme().colorThemeName);
14791
14896
  if (!blob) return;
14792
14897
  const image = await new Promise((resolve) => {
14793
14898
  const reader = new FileReader();
@@ -14824,7 +14929,7 @@ set(value) {
14824
14929
  const chartId = env.model.getters.getChartIdFromFigureId(figureId);
14825
14930
  if (!chartId) return;
14826
14931
  const chartType = env.model.getters.getChartType(chartId);
14827
- const url = await chartToImageUrl(env.model.getters.getChartRuntime(chartId), figure, chartType);
14932
+ const url = await chartToImageUrl(env.model.getters.getChartRuntime(chartId), figure, chartType, env.model.getters.getSpreadsheetTheme().colorThemeName);
14828
14933
  if (!url) return;
14829
14934
  downloadFile(url, "chart");
14830
14935
  },
@@ -16373,8 +16478,8 @@ set(value) {
16373
16478
  useLayoutEffect(() => {
16374
16479
  if (!this.props.disableKeyboardNavigation && !this.state.hoveredMenu && !this.subMenu.isOpen) this.menuRef()?.focus();
16375
16480
  });
16376
- useExternalListener(window, "click", this.onExternalClick, { capture: true });
16377
- useExternalListener(window, "contextmenu", this.onExternalClick, { capture: true });
16481
+ (0, _odoo_owl.useListener)(window, "click", this.onExternalClick.bind(this), { capture: true });
16482
+ (0, _odoo_owl.useListener)(window, "contextmenu", this.onExternalClick.bind(this), { capture: true });
16378
16483
  (0, _odoo_owl.onWillUpdateProps)((nextProps) => {
16379
16484
  if (nextProps.menuItems !== this.props.menuItems) this.closeSubMenu();
16380
16485
  });
@@ -16954,110 +17059,6 @@ set(value) {
16954
17059
  }
16955
17060
  const expectNumberGreaterThanOrEqualToOne = (value) => _t("The function [[FUNCTION_NAME]] expects a number value to be greater than or equal to 1, but receives %s.", value);
16956
17061
 
16957
- //#endregion
16958
- //#region src/functions/helper_matrices.ts
16959
- function getUnitMatrix(n) {
16960
- const matrix = Array(n);
16961
- for (let i = 0; i < n; i++) {
16962
- matrix[i] = Array(n).fill(0);
16963
- matrix[i][i] = 1;
16964
- }
16965
- return matrix;
16966
- }
16967
- /**
16968
- * Invert a matrix and compute its determinant using Gaussian Elimination.
16969
- *
16970
- * The Matrix should be a square matrix, and should be indexed [col][row] instead of the
16971
- * standard mathematical indexing [row][col].
16972
- */
16973
- function invertMatrix(M) {
16974
- if (M.length < 1 || M[0].length < 1) throw new Error("invertMatrix: an empty matrix cannot be inverted.");
16975
- if (M.length !== M[0].length) throw new Error("invertMatrix: only square matrices are invertible");
16976
- let determinant = 1;
16977
- const dim = M.length;
16978
- const I = getUnitMatrix(dim);
16979
- const C = M.map((row) => row.slice());
16980
- for (let pivot = 0; pivot < dim; pivot++) {
16981
- let diagonalElement = C[pivot][pivot];
16982
- if (diagonalElement === 0) {
16983
- for (let row = pivot + 1; row < dim; row++) if (C[pivot][row] !== 0) {
16984
- swapMatrixRows(C, pivot, row);
16985
- swapMatrixRows(I, pivot, row);
16986
- determinant *= -1;
16987
- break;
16988
- }
16989
- diagonalElement = C[pivot][pivot];
16990
- if (diagonalElement === 0) return { determinant: 0 };
16991
- }
16992
- for (let col = 0; col < dim; col++) {
16993
- C[col][pivot] = C[col][pivot] / diagonalElement;
16994
- I[col][pivot] = I[col][pivot] / diagonalElement;
16995
- }
16996
- determinant *= diagonalElement;
16997
- for (let row = 0; row < dim; row++) {
16998
- if (row === pivot) continue;
16999
- const e = C[pivot][row];
17000
- for (let col = 0; col < dim; col++) {
17001
- C[col][row] -= e * C[col][pivot];
17002
- I[col][row] -= e * I[col][pivot];
17003
- }
17004
- }
17005
- }
17006
- return {
17007
- inverted: I,
17008
- determinant
17009
- };
17010
- }
17011
- function swapMatrixRows(matrix, row1, row2) {
17012
- for (let i = 0; i < matrix.length; i++) {
17013
- const tmp = matrix[i][row1];
17014
- matrix[i][row1] = matrix[i][row2];
17015
- matrix[i][row2] = tmp;
17016
- }
17017
- }
17018
- /**
17019
- * Matrix multiplication of 2 matrices.
17020
- * ex: matrix1 : n x l, matrix2 : m x n => result : m x l
17021
- *
17022
- * Note: we use indexing [col][row] instead of the standard mathematical notation [row][col]
17023
- */
17024
- function multiplyMatrices(matrix1, matrix2) {
17025
- if (matrix1.length < 1 || matrix2.length < 1) throw new Error("multiplyMatrices: empty matrices cannot be multiplied.");
17026
- if (matrix1.length !== matrix2[0].length) throw new Error("multiplyMatrices: incompatible matrices size.");
17027
- const rowsM1 = matrix1[0].length;
17028
- const colsM2 = matrix2.length;
17029
- const n = matrix1.length;
17030
- const result = Array(colsM2);
17031
- for (let col = 0; col < colsM2; col++) {
17032
- result[col] = Array(rowsM1);
17033
- for (let row = 0; row < rowsM1; row++) {
17034
- let sum = 0;
17035
- for (let k = 0; k < n; k++) sum += matrix1[k][row] * matrix2[col][k];
17036
- result[col][row] = sum;
17037
- }
17038
- }
17039
- return result;
17040
- }
17041
- /**
17042
- * Return the input if it's a scalar or the first element of the input if it's a matrix.
17043
- */
17044
- function toScalar(arg) {
17045
- if (!isMatrix(arg)) return arg;
17046
- if (!isSingleElementMatrix(arg)) throw new Error("The value should be a scalar or a 1x1 matrix");
17047
- return arg[0][0];
17048
- }
17049
- function isSingleElementMatrix(matrix) {
17050
- return matrix.length === 1 && matrix[0].length === 1;
17051
- }
17052
- function isMultipleElementMatrix(arg) {
17053
- return isMatrix(arg) && !isSingleElementMatrix(arg);
17054
- }
17055
- function getMatrixArgIndices(args) {
17056
- const indices = [];
17057
- for (let i = 0; i < args.length; i++) if (isMultipleElementMatrix(args[i])) indices.push(i);
17058
- return indices;
17059
- }
17060
-
17061
17062
  //#endregion
17062
17063
  //#region src/functions/helper_statistical.ts
17063
17064
  function assertSameNumberOfElements(...args) {
@@ -18208,8 +18209,6 @@ set(value) {
18208
18209
  Unexpected: _t("The chart definition is invalid for an unknown reason"),
18209
18210
  ["InvalidDataSet"]: _t("The dataset is invalid"),
18210
18211
  ["InvalidLabelRange"]: _t("Labels are invalid"),
18211
- ["InvalidScorecardKeyValue"]: _t("The key value is invalid"),
18212
- ["InvalidScorecardBaseline"]: _t("The baseline value is invalid"),
18213
18212
  ["InvalidGaugeDataRange"]: _t("The data range is invalid"),
18214
18213
  ["EmptyGaugeRangeMin"]: _t("A minimum range limit value is needed"),
18215
18214
  ["GaugeRangeMinNaN"]: _t("The minimum range limit value must be a number"),
@@ -20984,7 +20983,7 @@ set(value) {
20984
20983
  setup() {
20985
20984
  this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
20986
20985
  this.viewStore = useStore(ViewportsStore);
20987
- useExternalListener(window, "click", this.onExternalClick, { capture: true });
20986
+ (0, _odoo_owl.useListener)(window, "click", this.onExternalClick.bind(this), { capture: true });
20988
20987
  }
20989
20988
  get addRowsPosition() {
20990
20989
  const { scrollY } = this.viewStore.activeSheetScrollInfo;
@@ -21515,7 +21514,7 @@ set(value) {
21515
21514
  (0, _odoo_owl.useListener)(gridRef, "mouseenter", resume);
21516
21515
  (0, _odoo_owl.useListener)(gridRef, "pointerdown", recompute);
21517
21516
  (0, _odoo_owl.useListener)(gridRef, "pointerdown", (ev) => env.isMobile() && updateMousePosition(withZoom(env, ev)));
21518
- useExternalListener(window, "click", handleGlobalClick);
21517
+ (0, _odoo_owl.useListener)(window, "click", handleGlobalClick);
21519
21518
  function handleGlobalClick(e) {
21520
21519
  const target = e.target;
21521
21520
  const grid = gridRef();
@@ -21886,7 +21885,7 @@ set(value) {
21886
21885
  };
21887
21886
  }
21888
21887
  function getDataFilterIcon(isActive, isHighContrast, isHovered) {
21889
- const symbolPath = isActive ? "M18.6 3.5H4.29c-.7 0-1.06.85-.56 1.35l6.1 6.1v6.8c0 .26.13.5.34.65l2.64 1.85a.79.79 0 0 0 1.25-.65v-8.64l6.1-6.1a.79.79 0 0 0-.56-1.35" : "M 339.667 681 L 510.333 681 L 510.333 595.667 L 339.667 595.667 L 339.667 681 Z M 41 169 L 41 254.333 L 809 254.333 L 809 169 L 41 169 Z M 169 467.667 L 681 467.667 L 681 382.333 L 169 382.333 L 169 467.667 Z";
21888
+ const symbolPath = isActive ? "M 11 20 Q 10.575 20 10.2875 19.7125 T 10 19 L 10 13 L 4.2 5.6 Q 3.825 5.1 4.0875 4.55 T 5 4 L 19 4 Q 19.65 4 19.9125 4.55 T 19.8 5.6 L 14 13 L 14 19 Q 14 19.425 13.7125 19.7125 T 13 20 L 11 20 Z" : "M 339.667 681 L 510.333 681 L 510.333 595.667 L 339.667 595.667 L 339.667 681 Z M 41 169 L 41 254.333 L 809 254.333 L 809 169 L 41 169 Z M 169 467.667 L 681 467.667 L 681 382.333 L 169 382.333 L 169 467.667 Z";
21890
21889
  const hoverBackgroundPath = isActive ? "M0,0 h24 v24 h-24" : "M0,0 h850 v850 h-850";
21891
21890
  const colors = {
21892
21891
  iconColor: FILTERS_COLOR,
@@ -23519,7 +23518,7 @@ set(value) {
23519
23518
  hoveredValue: void 0
23520
23519
  });
23521
23520
  setup() {
23522
- useExternalListener(window, "pointerdown", this.onExternalClick, { capture: true });
23521
+ (0, _odoo_owl.useListener)(window, "pointerdown", this.onExternalClick.bind(this), { capture: true });
23523
23522
  useLayoutEffect(() => {
23524
23523
  const el = this.dropdownRef();
23525
23524
  if (el) el.style.width = `${this.selectRef()?.offsetWidth}px`;
@@ -23621,7 +23620,7 @@ set(value) {
23621
23620
  });
23622
23621
  static components = { Popover };
23623
23622
  setup() {
23624
- useExternalListener(window, "click", this.onExternalClick, { capture: true });
23623
+ (0, _odoo_owl.useListener)(window, "click", this.onExternalClick.bind(this), { capture: true });
23625
23624
  }
23626
23625
  infoRef = _odoo_owl.signal.ref();
23627
23626
  get popoverProps() {
@@ -24031,6 +24030,7 @@ set(value) {
24031
24030
  Component: ChartFigure,
24032
24031
  SidePanelComponent: "ChartPanel",
24033
24032
  menuBuilder: getChartMenuActions,
24033
+ minFigSize: 80,
24034
24034
  borderWidth: (getters) => getters.isDashboard() ? 0 : 1,
24035
24035
  hasShadow: (getters) => getters.isDashboard(),
24036
24036
  isRounded: (getters) => getters.isDashboard(),
@@ -24049,6 +24049,7 @@ set(value) {
24049
24049
  figureRegistry.add("carousel", {
24050
24050
  Component: CarouselFigure,
24051
24051
  menuBuilder: getCarouselMenuActions,
24052
+ minFigSize: 80,
24052
24053
  borderWidth: (getters) => getters.isDashboard() ? 0 : 1,
24053
24054
  hasShadow: (getters) => getters.isDashboard(),
24054
24055
  isRounded: (getters) => getters.isDashboard(),
@@ -24181,7 +24182,7 @@ set(value) {
24181
24182
  ...this.positionInBoundary(sheetId, this.env.model.getters.getFigureUI(sheetId, figure), ev.key, ev.shiftKey)
24182
24183
  });
24183
24184
  }
24184
- this.env.model.dispatch("MOVE_FIGURES", { figures });
24185
+ this.env.model.dispatch("UPDATE_FIGURES", { figures });
24185
24186
  ev.preventDefault();
24186
24187
  ev.stopPropagation();
24187
24188
  break;
@@ -29279,6 +29280,20 @@ set(value) {
29279
29280
  figure.data.chartDefinitions[chartId] = upgrade(definition);
29280
29281
  }
29281
29282
  return data;
29283
+ } }).add("19.5.1", { migrate(data) {
29284
+ function upgrade(definition) {
29285
+ if (definition.type !== "scorecard") return definition;
29286
+ definition = { ...definition };
29287
+ if (definition.keyValue) definition.keyValue = `=${definition.keyValue}`;
29288
+ if (definition.baseline) definition.baseline = `=${definition.baseline}`;
29289
+ return definition;
29290
+ }
29291
+ for (const sheet of data.sheets || []) for (const figure of sheet.figures || []) if (figure.tag === "chart") figure.data = upgrade(figure.data);
29292
+ else if (figure.tag === "carousel") for (const chartId in figure.data.chartDefinitions) {
29293
+ const definition = figure.data.chartDefinitions[chartId];
29294
+ figure.data.chartDefinitions[chartId] = upgrade(definition);
29295
+ }
29296
+ return data;
29282
29297
  } });
29283
29298
  function fixOverlappingFilters(data) {
29284
29299
  for (const sheet of data.sheets || []) {
@@ -29951,7 +29966,7 @@ set(value) {
29951
29966
  return {
29952
29967
  type: "scorecard",
29953
29968
  title: {},
29954
- keyValue: getUnboundRange(getters, zone),
29969
+ keyValue: `=${getUnboundRange(getters, zone)}`,
29955
29970
  background: cell?.style?.fillColor,
29956
29971
  baselineMode: DEFAULT_SCORECARD_BASELINE_MODE,
29957
29972
  baselineColorUp: DEFAULT_SCORECARD_BASELINE_COLOR_UP,
@@ -30912,7 +30927,7 @@ set(value) {
30912
30927
  getFormulas(getters) {
30913
30928
  return this.chartTypeBuilder.getFormulas(getters, this.sheetId, this.definition);
30914
30929
  }
30915
- getRuntime(getters, chartId) {
30930
+ getRuntime(getters, chartId, colorThemeName) {
30916
30931
  const dataSource = this.dataSource;
30917
30932
  const dataExtractors = dataSource ? {
30918
30933
  extractData: () => this.dataSourceBuilder.extractData(dataSource, chartId, getters),
@@ -30932,7 +30947,7 @@ set(value) {
30932
30947
  return this.dataSourceBuilder.onDataSetClick?.(this.definition.type, chartId, event, items, chartJsChart, getters);
30933
30948
  },
30934
30949
  onHover: (event, items, chartJsChart) => this.dataSourceBuilder.onDataSetHover?.(this.definition.type, chartId, event, items, chartJsChart)
30935
- });
30950
+ }, colorThemeName);
30936
30951
  }
30937
30952
  static deleteInvalidKeys(definition) {
30938
30953
  definition = { ...definition };
@@ -32195,7 +32210,7 @@ set(value) {
32195
32210
  DOMFocusableElementStore;
32196
32211
  setup() {
32197
32212
  this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
32198
- useExternalListener(window, "click", this.onExternalClick, { capture: true });
32213
+ (0, _odoo_owl.useListener)(window, "click", this.onExternalClick.bind(this), { capture: true });
32199
32214
  (0, _odoo_owl.onWillUpdateProps)((nextProps) => {
32200
32215
  const input = this.inputRef();
32201
32216
  if (input && document.activeElement !== input) input.value = nextProps.currentValue;
@@ -32296,7 +32311,7 @@ set(value) {
32296
32311
  });
32297
32312
  openedEl = null;
32298
32313
  setup() {
32299
- useExternalListener(window, "click", this.onExternalClick);
32314
+ (0, _odoo_owl.useListener)(window, "click", this.onExternalClick.bind(this));
32300
32315
  }
32301
32316
  state = (0, _odoo_owl.proxy)({ activeTool: "" });
32302
32317
  updateFontSize(fontSize) {
@@ -33390,7 +33405,7 @@ set(value) {
33390
33405
  state;
33391
33406
  setup() {
33392
33407
  this.state = (0, _odoo_owl.proxy)({ pickerOpened: false });
33393
- useExternalListener(window, "click", this.closePicker);
33408
+ (0, _odoo_owl.useListener)(window, "click", this.closePicker.bind(this));
33394
33409
  }
33395
33410
  closePicker() {
33396
33411
  this.state.pickerOpened = false;
@@ -34013,7 +34028,7 @@ set(value) {
34013
34028
  //#region src/helpers/figures/charts/runtime/chart_data_extractor.ts
34014
34029
  const EMPTY$1 = Object.freeze({ value: null });
34015
34030
  const ZERO = Object.freeze({ value: 0 });
34016
- function getBarChartData(definition, { labelValues, dataSetsValues }, getters) {
34031
+ function getBarChartData(definition, { labelValues, dataSetsValues }, getters, colorThemeName) {
34017
34032
  const locale = getters.getLocale();
34018
34033
  let labels = labelValues.map(({ value, format }) => formatValue(value, {
34019
34034
  format,
@@ -34045,7 +34060,7 @@ set(value) {
34045
34060
  labels,
34046
34061
  locale: getters.getLocale(),
34047
34062
  topPadding: getTopPaddingForDashboard(definition, getters),
34048
- background: getChartBackgroundColor(definition, getters)
34063
+ background: getChartBackgroundColor(definition, colorThemeName)
34049
34064
  };
34050
34065
  }
34051
34066
  function getDateTimeLabel(value, stamp) {
@@ -34104,7 +34119,7 @@ set(value) {
34104
34119
  labels: xValues.map((v) => ({ value: getDateTimeLabel(v, horizontalGroupBy) }))
34105
34120
  };
34106
34121
  }
34107
- function getCalendarChartData(definition, { labelValues, dataSetsValues }, getters) {
34122
+ function getCalendarChartData(definition, { labelValues, dataSetsValues }, getters, colorThemeName) {
34108
34123
  let labels = labelValues;
34109
34124
  const locale = getters.getLocale();
34110
34125
  const countEntries = dataSetsValues.length === 0;
@@ -34117,14 +34132,14 @@ set(value) {
34117
34132
  labels: labels.map(({ value }) => String(value ?? "")),
34118
34133
  locale: getters.getLocale(),
34119
34134
  topPadding: getTopPaddingForDashboard(definition, getters),
34120
- background: getChartBackgroundColor(definition, getters)
34135
+ background: getChartBackgroundColor(definition, colorThemeName)
34121
34136
  };
34122
34137
  }
34123
- function getPyramidChartData(definition, { labelValues, dataSetsValues }, getters) {
34138
+ function getPyramidChartData(definition, { labelValues, dataSetsValues }, getters, colorThemeName) {
34124
34139
  const barChartData = getBarChartData(definition, {
34125
34140
  labelValues,
34126
34141
  dataSetsValues: dataSetsValues.slice(0, 2)
34127
- }, getters);
34142
+ }, getters, colorThemeName);
34128
34143
  const barDataset = barChartData.dataSetsValues.filter((ds) => !ds.hidden);
34129
34144
  const pyramidDatasetValues = [];
34130
34145
  if (barDataset[0]) {
@@ -34146,7 +34161,7 @@ set(value) {
34146
34161
  dataSetsValues: pyramidDatasetValues
34147
34162
  };
34148
34163
  }
34149
- function getLineChartData(definition, { labelValues, dataSetsValues }, getters) {
34164
+ function getLineChartData(definition, { labelValues, dataSetsValues }, getters, colorThemeName) {
34150
34165
  const axisType = getChartAxisType(definition, {
34151
34166
  labelValues,
34152
34167
  dataSetsValues
@@ -34182,10 +34197,10 @@ set(value) {
34182
34197
  trendDataSetsValues,
34183
34198
  axisType,
34184
34199
  topPadding: getTopPaddingForDashboard(definition, getters),
34185
- background: getChartBackgroundColor(definition, getters)
34200
+ background: getChartBackgroundColor(definition, colorThemeName)
34186
34201
  };
34187
34202
  }
34188
- function getPieChartData(definition, { labelValues, dataSetsValues }, getters) {
34203
+ function getPieChartData(definition, { labelValues, dataSetsValues }, getters, colorThemeName) {
34189
34204
  let labels = labelValues.map(({ value, format }) => formatValue(value, {
34190
34205
  format,
34191
34206
  locale: getters.getLocale()
@@ -34200,10 +34215,10 @@ set(value) {
34200
34215
  labels,
34201
34216
  locale: getters.getLocale(),
34202
34217
  topPadding: getTopPaddingForDashboard(definition, getters),
34203
- background: getChartBackgroundColor(definition, getters)
34218
+ background: getChartBackgroundColor(definition, colorThemeName)
34204
34219
  };
34205
34220
  }
34206
- function getRadarChartData(definition, { labelValues, dataSetsValues }, getters) {
34221
+ function getRadarChartData(definition, { labelValues, dataSetsValues }, getters, colorThemeName) {
34207
34222
  let labels = labelValues.map(({ value, format }) => formatValue(value, {
34208
34223
  format,
34209
34224
  locale: getters.getLocale()
@@ -34216,10 +34231,10 @@ set(value) {
34216
34231
  axisFormats,
34217
34232
  labels,
34218
34233
  locale: getters.getLocale(),
34219
- background: getChartBackgroundColor(definition, getters)
34234
+ background: getChartBackgroundColor(definition, colorThemeName)
34220
34235
  };
34221
34236
  }
34222
- function getGeoChartData(definition, { labelValues, dataSetsValues }, getters) {
34237
+ function getGeoChartData(definition, { labelValues, dataSetsValues }, getters, colorThemeName) {
34223
34238
  dataSetsValues = dataSetsValues.slice(0, 1);
34224
34239
  let labels = labelValues.map(({ value, format }) => formatValue(value, {
34225
34240
  format,
@@ -34235,10 +34250,10 @@ set(value) {
34235
34250
  availableRegions: getters.getGeoChartAvailableRegions(),
34236
34251
  geoFeatureNameToId: getters.geoFeatureNameToId,
34237
34252
  getGeoJsonFeatures: getters.getGeoJsonFeatures,
34238
- background: getChartBackgroundColor(definition, getters)
34253
+ background: getChartBackgroundColor(definition, colorThemeName)
34239
34254
  };
34240
34255
  }
34241
- function getFunnelChartData(definition, { labelValues, dataSetsValues }, getters) {
34256
+ function getFunnelChartData(definition, { labelValues, dataSetsValues }, getters, colorThemeName) {
34242
34257
  let labels = labelValues.map(({ value, format }) => formatValue(value, {
34243
34258
  format,
34244
34259
  locale: getters.getLocale()
@@ -34252,10 +34267,10 @@ set(value) {
34252
34267
  axisFormats: { x: format },
34253
34268
  labels,
34254
34269
  locale: getters.getLocale(),
34255
- background: getChartBackgroundColor(definition, getters)
34270
+ background: getChartBackgroundColor(definition, colorThemeName)
34256
34271
  };
34257
34272
  }
34258
- function getHierarchalChartData(definition, { labelValues, dataSetsValues }, getters) {
34273
+ function getHierarchalChartData(definition, { labelValues, dataSetsValues }, getters, colorThemeName) {
34259
34274
  let labels = labelValues;
34260
34275
  ({labels, dataSetsValues} = filterValuesWithDifferentSigns(labels, dataSetsValues));
34261
34276
  ({labels, dataSetsValues} = filterInvalidHierarchicalPoints(labels, dataSetsValues));
@@ -34264,12 +34279,12 @@ set(value) {
34264
34279
  axisFormats: { y: getChartLabelFormat(labels) },
34265
34280
  labels: labels.map(({ value }) => String(value ?? "")),
34266
34281
  locale: getters.getLocale(),
34267
- background: getChartBackgroundColor(definition, getters)
34282
+ background: getChartBackgroundColor(definition, colorThemeName)
34268
34283
  };
34269
34284
  }
34270
- function getBubbleChartData(definition, getters) {
34285
+ function getBubbleChartData(definition, getters, colorThemeName) {
34271
34286
  const chartData = getBubbleChartSourceData(definition, getters);
34272
- const data = getLineChartData(definition, chartData, getters);
34287
+ const data = getLineChartData(definition, chartData, getters, colorThemeName);
34273
34288
  let labelValues = definition.labelRange ? getters.getVisibleRangeValues(definition.labelRange) : [];
34274
34289
  let sizeValues = definition.sizeRange ? getters.getVisibleRangeValues(definition.sizeRange) : [];
34275
34290
  if (chartData.shouldRemoveFirstLabel) {
@@ -35271,9 +35286,9 @@ set(value) {
35271
35286
  `;
35272
35287
  let app;
35273
35288
  function renderToString(templateName, context = {}) {
35274
- return render(templateName, context).innerHTML;
35289
+ return render$1(templateName, context).innerHTML;
35275
35290
  }
35276
- function render(templateName, context = {}) {
35291
+ function render$1(templateName, context = {}) {
35277
35292
  if (!app) app = new _odoo_owl.App({
35278
35293
  templates,
35279
35294
  translateFn: _t
@@ -35638,8 +35653,8 @@ set(value) {
35638
35653
  verticalAxis: getDefinedAxis(definition)
35639
35654
  };
35640
35655
  },
35641
- getRuntime(getters, definition, { extractData }, sheetId, eventHandlers) {
35642
- const chartData = getBarChartData(definition, extractData(), getters);
35656
+ getRuntime(getters, definition, { extractData }, sheetId, eventHandlers, colorThemeName) {
35657
+ const chartData = getBarChartData(definition, extractData(), getters, colorThemeName);
35643
35658
  return {
35644
35659
  chartJsConfig: {
35645
35660
  type: "bar",
@@ -35827,7 +35842,7 @@ set(value) {
35827
35842
  definition.sectionRule.upperInflectionPoint.value
35828
35843
  ].filter((value) => value.startsWith("=")).map((formula) => CompiledFormula.Compile(formula, sheetId, getters));
35829
35844
  },
35830
- getRuntime(getters, definition, dataSource, sheetId) {
35845
+ getRuntime(getters, definition, dataSource, sheetId, eventHandlers, colorThemeName) {
35831
35846
  const locale = getters.getLocale();
35832
35847
  const chartColors = definition.sectionRule.colors;
35833
35848
  let gaugeValue = void 0;
@@ -35848,7 +35863,7 @@ set(value) {
35848
35863
  }
35849
35864
  let minValue = getFormulaNumberValue(sheetId, definition.sectionRule.rangeMin, getters);
35850
35865
  let maxValue = getFormulaNumberValue(sheetId, definition.sectionRule.rangeMax, getters);
35851
- if (minValue === void 0 || maxValue === void 0) return getInvalidGaugeRuntime(definition, getters);
35866
+ if (minValue === void 0 || maxValue === void 0) return getInvalidGaugeRuntime(definition, getters, colorThemeName);
35852
35867
  if (maxValue < minValue) [minValue, maxValue] = [maxValue, minValue];
35853
35868
  const lowerPoint = definition.sectionRule.lowerInflectionPoint;
35854
35869
  const upperPoint = definition.sectionRule.upperInflectionPoint;
@@ -35880,7 +35895,7 @@ set(value) {
35880
35895
  }
35881
35896
  colors.push(chartColors.upperColor);
35882
35897
  return {
35883
- background: getters.getStyleOfSingleCellChart(definition.background, dataRange).background,
35898
+ background: getters.getStyleOfSingleCellChart(definition.background, dataRange, colorThemeName).background,
35884
35899
  title: {
35885
35900
  ...title,
35886
35901
  text: title.text ? getters.dynamicTranslate(title.text) : ""
@@ -35914,9 +35929,9 @@ set(value) {
35914
35929
  const value = getters.evaluateFormula(sheetId, formula);
35915
35930
  return isMultipleElementMatrix(value) ? void 0 : tryToNumber(toScalar(value), getters.getLocale());
35916
35931
  }
35917
- function getInvalidGaugeRuntime(definition, getters) {
35932
+ function getInvalidGaugeRuntime(definition, getters, colorThemeName) {
35918
35933
  return {
35919
- background: getters.getStyleOfSingleCellChart(definition.background, definition.dataRange).background,
35934
+ background: getters.getStyleOfSingleCellChart(definition.background, definition.dataRange, colorThemeName).background,
35920
35935
  title: definition.title ?? { text: "" },
35921
35936
  minValue: {
35922
35937
  value: 0,
@@ -36010,8 +36025,8 @@ set(value) {
36010
36025
  verticalAxis: getDefinedAxis(definition)
36011
36026
  };
36012
36027
  },
36013
- getRuntime(getters, definition, { extractData }, sheetId, eventHandlers) {
36014
- const chartData = getLineChartData(definition, extractData(), getters);
36028
+ getRuntime(getters, definition, { extractData }, sheetId, eventHandlers, colorThemeName) {
36029
+ const chartData = getLineChartData(definition, extractData(), getters, colorThemeName);
36015
36030
  return {
36016
36031
  chartJsConfig: {
36017
36032
  type: "line",
@@ -36092,8 +36107,8 @@ set(value) {
36092
36107
  labelRange
36093
36108
  };
36094
36109
  },
36095
- getRuntime(getters, definition, { extractData }, sheetId, eventHandlers) {
36096
- const chartData = getPieChartData(definition, extractData(), getters);
36110
+ getRuntime(getters, definition, { extractData }, sheetId, eventHandlers, colorThemeName) {
36111
+ const chartData = getPieChartData(definition, extractData(), getters, colorThemeName);
36097
36112
  return { chartJsConfig: {
36098
36113
  type: definition.isDoughnut ? "doughnut" : "pie",
36099
36114
  data: {
@@ -36169,8 +36184,8 @@ set(value) {
36169
36184
  };
36170
36185
  },
36171
36186
  getDefinitionForExcel: () => void 0,
36172
- getRuntime(getters, definition, { extractData }, sheetId, eventHandlers) {
36173
- const chartData = getBarChartData(definition, extractData(), getters);
36187
+ getRuntime(getters, definition, { extractData }, sheetId, eventHandlers, colorThemeName) {
36188
+ const chartData = getBarChartData(definition, extractData(), getters, colorThemeName);
36174
36189
  const { labels, datasets } = getWaterfallDatasetAndLabels(definition, chartData);
36175
36190
  return { chartJsConfig: {
36176
36191
  type: "bar",
@@ -36937,7 +36952,7 @@ set(value) {
36937
36952
  getGroupByOptions() {
36938
36953
  const sheetId = this.env.model.getters.getFigureSheetId(this.env.model.getters.getFigureIdFromChartId(this.props.chartId));
36939
36954
  const definition = SpreadsheetChart.fromStrDefinition(this.env.model.getters, sheetId, this.props.definition).getRangeDefinition();
36940
- const labels = getBarChartData(definition, getChartData(this.env.model.getters, definition.dataSource), this.env.model.getters).labels.filter((l) => isDateTime(l, DEFAULT_LOCALE));
36955
+ const labels = getBarChartData(definition, getChartData(this.env.model.getters, definition.dataSource), this.env.model.getters, this.env.model.getters.getSpreadsheetTheme().colorThemeName).labels.filter((l) => isDateTime(l, DEFAULT_LOCALE));
36941
36956
  if (labels.length === 0) return [];
36942
36957
  const dates = labels.map((label) => toJsDate(label, this.env.model.getters.getLocale()));
36943
36958
  const uniqueYears = /* @__PURE__ */ new Set();
@@ -37001,7 +37016,7 @@ set(value) {
37001
37016
  });
37002
37017
  popoverRef = _odoo_owl.signal.ref(HTMLTableElement);
37003
37018
  setup() {
37004
- useExternalListener(window, "click", this.closePopover);
37019
+ (0, _odoo_owl.useListener)(window, "click", this.closePopover.bind(this));
37005
37020
  }
37006
37021
  get currentColorScale() {
37007
37022
  return this.props.definition.colorScale || schemeToColorScale("oranges");
@@ -39649,10 +39664,10 @@ set(value) {
39649
39664
  var ScorecardChartConfigPanel = class extends Component {
39650
39665
  static template = "o-spreadsheet-ScorecardChartConfigPanel";
39651
39666
  static components = {
39652
- SelectionInput,
39653
39667
  ChartErrorSection,
39654
39668
  Section,
39655
- Select
39669
+ Select,
39670
+ StandaloneComposer
39656
39671
  };
39657
39672
  props = (0, _odoo_owl.useProps)(chartSidePanelPropsDefinition);
39658
39673
  state = (0, _odoo_owl.proxy)({
@@ -39664,30 +39679,18 @@ set(value) {
39664
39679
  get errorMessages() {
39665
39680
  return [...this.state.keyValueDispatchResult?.reasons || [], ...this.state.baselineDispatchResult?.reasons || []].filter((reason) => reason !== "NoChanges").map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
39666
39681
  }
39667
- get isKeyValueInvalid() {
39668
- return !!this.state.keyValueDispatchResult?.isCancelledBecause("InvalidScorecardKeyValue");
39669
- }
39670
- get isBaselineInvalid() {
39671
- return !!this.state.baselineDispatchResult?.isCancelledBecause("InvalidScorecardBaseline");
39672
- }
39673
- onKeyValueRangeChanged(ranges) {
39674
- this.keyValue = ranges[0];
39675
- this.state.keyValueDispatchResult = this.props.canUpdateChart(this.props.chartId, { keyValue: this.keyValue });
39676
- }
39677
- updateKeyValueRange() {
39682
+ onConfirmKeyValue(keyValue) {
39683
+ this.keyValue = keyValue;
39678
39684
  this.state.keyValueDispatchResult = this.props.updateChart(this.props.chartId, { keyValue: this.keyValue });
39679
39685
  }
39680
- getKeyValueRange() {
39686
+ getKeyValue() {
39681
39687
  return this.keyValue || "";
39682
39688
  }
39683
- onBaselineRangeChanged(ranges) {
39684
- this.baseline = ranges[0];
39685
- this.state.baselineDispatchResult = this.props.canUpdateChart(this.props.chartId, { baseline: this.baseline });
39686
- }
39687
- updateBaselineRange() {
39689
+ onConfirmBaseline(baseline) {
39690
+ this.baseline = baseline;
39688
39691
  this.state.baselineDispatchResult = this.props.updateChart(this.props.chartId, { baseline: this.baseline });
39689
39692
  }
39690
- getBaselineRange() {
39693
+ getBaseline() {
39691
39694
  return this.baseline || "";
39692
39695
  }
39693
39696
  updateBaselineMode(baselineMode) {
@@ -40144,6 +40147,7 @@ set(value) {
40144
40147
  changeChartType(chartId, newDisplayType) {
40145
40148
  const currentCreationContext = this.getters.getContextCreationChart(chartId);
40146
40149
  const savedCreationContext = this.creationContexts[chartId] || {};
40150
+ const auxiliaryRange = currentCreationContext && "auxiliaryRange" in currentCreationContext ? currentCreationContext.auxiliaryRange : savedCreationContext.auxiliaryRange;
40147
40151
  let dataSetStyles = savedCreationContext.dataSetStyles ?? currentCreationContext?.dataSetStyles;
40148
40152
  let dataSource = {
40149
40153
  ...savedCreationContext.dataSource,
@@ -40165,7 +40169,8 @@ set(value) {
40165
40169
  dataSetsHaveTitle: false,
40166
40170
  ...savedCreationContext.dataSource,
40167
40171
  ...currentCreationContext?.dataSource,
40168
- dataSets: newRanges ?? []
40172
+ dataSets: newRanges ?? [],
40173
+ labelRange: auxiliaryRange
40169
40174
  };
40170
40175
  }
40171
40176
  this.creationContexts[chartId] = {
@@ -40194,7 +40199,7 @@ set(value) {
40194
40199
  dataSetsStartWithSameRanges(currentDataSets, savedDataSets, currentStyles, savedStyles) {
40195
40200
  return currentDataSets.every((ds, i) => {
40196
40201
  const savedDs = savedDataSets[i];
40197
- return deepEquals(ds.dataRange, savedDs.dataRange) && deepEquals(currentStyles?.[ds.dataSetId], savedStyles?.[savedDs.dataSetId]);
40202
+ return deepEquals(ds.dataRange, savedDs?.dataRange) && deepEquals(currentStyles?.[ds.dataSetId], savedStyles?.[savedDs?.dataSetId]);
40198
40203
  });
40199
40204
  }
40200
40205
  /**
@@ -42030,7 +42035,7 @@ set(value) {
42030
42035
  useLayoutEffect((sheetId, isCfRemoved) => {
42031
42036
  if (this.activeSheetId !== sheetId || isCfRemoved) this.env.replaceSidePanel("ConditionalFormatting", `ConditionalFormattingEditor_${this.props.cf.id}`);
42032
42037
  }, () => [this.env.model.getters.getActiveSheetId(), this.isEditedCfRemoved]);
42033
- useExternalListener(window, "click", () => this.store.closeMenus());
42038
+ (0, _odoo_owl.useListener)(window, "click", () => this.store.closeMenus());
42034
42039
  }
42035
42040
  get isEditedCfRemoved() {
42036
42041
  return !Boolean(this.env.model.getters.getConditionalFormats(this.activeSheetId).find((cf) => cf.id === this.props.cf.id));
@@ -42303,7 +42308,7 @@ set(value) {
42303
42308
  canvas.className = "w-100 h-100";
42304
42309
  container.appendChild(canvas);
42305
42310
  spreadsheet.appendChild(container);
42306
- destroyChart = drawChartOnCanvas(canvas, SpreadsheetChart.fromStrDefinition(getters, sheetId, definition).getRuntime(getters, "newChart"), {
42311
+ destroyChart = drawChartOnCanvas(canvas, SpreadsheetChart.fromStrDefinition(getters, sheetId, definition).getRuntime(getters, "newChart", getters.getSpreadsheetTheme().colorThemeName), {
42307
42312
  width,
42308
42313
  height
42309
42314
  }, definition.type, zoom);
@@ -42384,7 +42389,7 @@ set(value) {
42384
42389
  getChartConfiguration() {
42385
42390
  const getters = this.env.model.getters;
42386
42391
  const activeSheetId = getters.getActiveSheetId();
42387
- const runtime = SpreadsheetChart.fromStrDefinition(getters, activeSheetId, this.props.definition).getRuntime(getters, "myChart");
42392
+ const runtime = SpreadsheetChart.fromStrDefinition(getters, activeSheetId, this.props.definition).getRuntime(getters, "myChart", getters.getSpreadsheetTheme().colorThemeName);
42388
42393
  if (!("chartJsConfig" in runtime)) return null;
42389
42394
  let config = runtime.chartJsConfig;
42390
42395
  const existingScales = config.options?.scales ?? {};
@@ -42451,7 +42456,7 @@ set(value) {
42451
42456
  const canvas = this.chartCanvasRef();
42452
42457
  if (!canvas) return;
42453
42458
  const getters = this.env.model.getters;
42454
- let runtime = SpreadsheetChart.fromStrDefinition(getters, getters.getActiveSheetId(), this.props.definition).getRuntime(getters, "myChart");
42459
+ let runtime = SpreadsheetChart.fromStrDefinition(getters, getters.getActiveSheetId(), this.props.definition).getRuntime(getters, "myChart", getters.getSpreadsheetTheme().colorThemeName);
42455
42460
  const { type } = this.props.definition;
42456
42461
  if (type === "scorecard") {
42457
42462
  const rect = canvas.getBoundingClientRect();
@@ -42714,8 +42719,8 @@ set(value) {
42714
42719
  {
42715
42720
  description: _t("Highlights the most recent value compared to the previous one."),
42716
42721
  isApplicable: ({ rowCount }) => rowCount < 3,
42717
- build: (ctx) => scorecardChart(ctx.title, ctx.lastCellXC, {
42718
- baseline: ctx.prevCellXC,
42722
+ build: (ctx) => scorecardChart(ctx.title, `=${ctx.lastCellXC}`, {
42723
+ baseline: ctx.prevCellXC ? `=${ctx.prevCellXC}` : void 0,
42719
42724
  baselineMode: "difference"
42720
42725
  })
42721
42726
  },
@@ -42748,8 +42753,8 @@ set(value) {
42748
42753
  {
42749
42754
  description: _t("Shows the last percentage value with its baseline."),
42750
42755
  isApplicable: ({ rowCount }) => rowCount < 3,
42751
- build: (ctx) => scorecardChart(ctx.title, ctx.lastCellXC, {
42752
- baseline: ctx.prevCellXC,
42756
+ build: (ctx) => scorecardChart(ctx.title, `=${ctx.lastCellXC}`, {
42757
+ baseline: ctx.prevCellXC ? `=${ctx.prevCellXC}` : void 0,
42753
42758
  baselineMode: "percentage"
42754
42759
  })
42755
42760
  },
@@ -42778,7 +42783,7 @@ set(value) {
42778
42783
  const SINGLE_DATE_COLUMN_SUGGESTIONS = [{
42779
42784
  description: _t("Shows the last date value."),
42780
42785
  isApplicable: ({ rowCount }) => rowCount === 1,
42781
- build: (ctx) => scorecardChart(ctx.title, ctx.lastCellXC)
42786
+ build: (ctx) => scorecardChart(ctx.title, `=${ctx.lastCellXC}`)
42782
42787
  }];
42783
42788
  /** Pattern D — Single categorical column */
42784
42789
  const SINGLE_CATEGORICAL_COLUMN_SUGGESTIONS = [
@@ -42812,7 +42817,7 @@ set(value) {
42812
42817
  const SINGLE_LABEL_COLUMN_SUGGESTIONS = [{
42813
42818
  description: _t("Displays a key performance indicator."),
42814
42819
  isApplicable: ({ rowCount }) => rowCount === 1,
42815
- build: (ctx) => scorecardChart(ctx.title, ctx.lastCellXC, {
42820
+ build: (ctx) => scorecardChart(ctx.title, `=${ctx.lastCellXC}`, {
42816
42821
  baselineMode: "text",
42817
42822
  humanize: false
42818
42823
  })
@@ -42870,8 +42875,8 @@ set(value) {
42870
42875
  {
42871
42876
  description: _t("Highlights the second metric compared to the first one."),
42872
42877
  isApplicable: ({ rowCount1, rowCount2 }) => rowCount1 === 1 && rowCount2 === 1,
42873
- build: (ctx) => scorecardChart(ctx.title, ctx.lastCellXC, {
42874
- baseline: ctx.prevCellXC,
42878
+ build: (ctx) => scorecardChart(ctx.title, `=${ctx.lastCellXC}`, {
42879
+ baseline: ctx.prevCellXC ? `=${ctx.prevCellXC}` : void 0,
42875
42880
  baselineMode: "difference"
42876
42881
  })
42877
42882
  },
@@ -42929,10 +42934,10 @@ set(value) {
42929
42934
  {
42930
42935
  description: _t("Highlights the most recent value for the named entity."),
42931
42936
  isApplicable: ({ rowCount }) => rowCount === 1,
42932
- build: (ctx) => scorecardChart("", ctx.lastCellXC, {
42937
+ build: (ctx) => scorecardChart("", `=${ctx.lastCellXC}`, {
42933
42938
  humanize: false,
42934
42939
  baselineMode: "text",
42935
- baseline: ctx.prevCellXC
42940
+ baseline: ctx.prevCellXC ? `=${ctx.prevCellXC}` : void 0
42936
42941
  })
42937
42942
  },
42938
42943
  {
@@ -43933,6 +43938,7 @@ set(value) {
43933
43938
  mutators = [
43934
43939
  "updateSearchOptions",
43935
43940
  "updateSearchContent",
43941
+ "updateReplaceContent",
43936
43942
  "searchFormulas",
43937
43943
  "selectPreviousMatch",
43938
43944
  "selectNextMatch",
@@ -43985,6 +43991,9 @@ set(value) {
43985
43991
  updateSearchContent(toSearch) {
43986
43992
  this._updateSearch(toSearch, this.searchOptions);
43987
43993
  }
43994
+ updateReplaceContent(toReplace) {
43995
+ this.toReplace = toReplace;
43996
+ }
43988
43997
  updateSearchOptions(searchOptions) {
43989
43998
  this._updateSearch(this.toSearch, {
43990
43999
  ...this.searchOptions,
@@ -44342,7 +44351,7 @@ set(value) {
44342
44351
  get currentSheetMatchesCount() {
44343
44352
  const { activeSheetMatchesCount: count, activeSheetHiddenMatchesCount: hidden, searchOptions } = this.store;
44344
44353
  const sheetName = this.env.model.getters.getSheetName(this.env.model.getters.getActiveSheetId());
44345
- let label = count === 1 ? _t("1 match in %(sheetName)s", { sheetName }) : _t("%(count)s matches in %(sheetName)s", {
44354
+ let label = count === 1 ? _t("1 match in '%(sheetName)s'", { sheetName }) : _t("%(count)s matches in '%(sheetName)s'", {
44346
44355
  count,
44347
44356
  sheetName
44348
44357
  });
@@ -44354,10 +44363,10 @@ set(value) {
44354
44363
  if (!range) return "";
44355
44364
  const { specificRangeMatchesCount: count, specificRangeHiddenMatchesCount: hidden, searchOptions } = this.store;
44356
44365
  const { sheetId, zone } = range;
44357
- let label = count === 1 ? _t("1 match in range %(range)s of %(sheetName)s", {
44366
+ let label = count === 1 ? _t("1 match in range %(range)s of '%(sheetName)s'", {
44358
44367
  range: zoneToXc(zone),
44359
44368
  sheetName: this.env.model.getters.getSheetName(sheetId)
44360
- }) : _t("%(count)s matches in range %(range)s of %(sheetName)s", {
44369
+ }) : _t("%(count)s matches in range %(range)s of '%(sheetName)s'", {
44361
44370
  count,
44362
44371
  range: zoneToXc(zone),
44363
44372
  sheetName: this.env.model.getters.getSheetName(sheetId)
@@ -44385,7 +44394,7 @@ set(value) {
44385
44394
  (0, _odoo_owl.onMounted)(() => this.searchInputRef()?.focus());
44386
44395
  (0, _odoo_owl.onWillUnmount)(() => this.updateSearchContent.stopDebounce());
44387
44396
  this.updateSearchContent = debounce(this.store.updateSearchContent, 200);
44388
- useExternalListener(window, "keydown", (ev) => {
44397
+ (0, _odoo_owl.useListener)(window, "keydown", (ev) => {
44389
44398
  const code = keyboardEventToShortcutString(ev);
44390
44399
  if (code === "Ctrl+F" || code === "Ctrl+H") {
44391
44400
  this.searchInputRef()?.focus();
@@ -44400,6 +44409,9 @@ set(value) {
44400
44409
  onSearchInput(ev) {
44401
44410
  this.updateSearchContent(ev.target.value);
44402
44411
  }
44412
+ onReplaceInput(ev) {
44413
+ this.store.updateReplaceContent(ev.target.value);
44414
+ }
44403
44415
  onKeydownPanel(ev) {
44404
44416
  if (ev.key === "Escape") {
44405
44417
  ev.preventDefault();
@@ -45980,7 +45992,7 @@ set(value) {
45980
45992
  buttonFilter = _odoo_owl.signal.ref();
45981
45993
  popover;
45982
45994
  setup() {
45983
- useExternalListener(window, "click", (ev) => {
45995
+ (0, _odoo_owl.useListener)(window, "click", (ev) => {
45984
45996
  if (!isChildEvent(this.buttonFilter(), ev)) this.popover.isOpen = false;
45985
45997
  });
45986
45998
  (0, _odoo_owl.onWillUpdateProps)((nextProps) => {
@@ -46114,7 +46126,7 @@ set(value) {
46114
46126
  setup() {
46115
46127
  this.autoComplete = useLocalStore(AutoCompleteStore);
46116
46128
  this.autoComplete.useProvider(this.getProvider());
46117
- useExternalListener(window, "click", (ev) => {
46129
+ (0, _odoo_owl.useListener)(window, "click", (ev) => {
46118
46130
  if (ev.target !== this.buttonRef()) this.popover.isOpen = false;
46119
46131
  });
46120
46132
  useAutofocus(this.autofocusRef);
@@ -48492,7 +48504,7 @@ set(value) {
48492
48504
  tableStyleListRef = _odoo_owl.signal.ref();
48493
48505
  state = (0, _odoo_owl.proxy)({ selectedCategory: this.initialSelectedCategory });
48494
48506
  setup() {
48495
- useExternalListener(window, "click", this.onExternalClick, { capture: true });
48507
+ (0, _odoo_owl.useListener)(window, "click", this.onExternalClick.bind(this), { capture: true });
48496
48508
  }
48497
48509
  onExternalClick(ev) {
48498
48510
  const el = this.tableStyleListRef();
@@ -49707,7 +49719,8 @@ set(value) {
49707
49719
  static components = {
49708
49720
  Section,
49709
49721
  RoundColorPicker,
49710
- TableStylePreview
49722
+ TableStylePreview,
49723
+ TextInput
49711
49724
  };
49712
49725
  props = (0, _odoo_owl.useProps)({
49713
49726
  onCloseSidePanel: types.function(),
@@ -49716,7 +49729,7 @@ set(value) {
49716
49729
  });
49717
49730
  state = (0, _odoo_owl.proxy)(this.getInitialState());
49718
49731
  setup() {
49719
- useExternalListener(window, "click", () => this.state.pickerOpened = false);
49732
+ (0, _odoo_owl.useListener)(window, "click", () => this.state.pickerOpened = false);
49720
49733
  }
49721
49734
  getInitialState() {
49722
49735
  const editedStyle = this.props.styleId ? this.env.model.getters.getTableStyle(this.props.styleId) : null;
@@ -53593,6 +53606,15 @@ set(value) {
53593
53606
  }
53594
53607
  };
53595
53608
 
53609
+ //#endregion
53610
+ //#region src/helpers/owl3_helpers.ts
53611
+ /**
53612
+ * Comes from https://github.com/odoo/odoo/blob/master/addons/web/static/src/owl2/utils.js
53613
+ */
53614
+ function render(component, deep = false) {
53615
+ component.__owl__.render(deep);
53616
+ }
53617
+
53596
53618
  //#endregion
53597
53619
  //#region src/components/helpers/figure_drag_helper.ts
53598
53620
  function dragFigureForMove({ x: mouseX, y: mouseY }, { x: mouseInitialX, y: mouseInitialY }, initialFigures, { maxX, maxY }, { scrollX: initialScrollX, scrollY: initialScrollY }, { scrollX, scrollY }) {
@@ -53610,19 +53632,19 @@ set(value) {
53610
53632
  };
53611
53633
  });
53612
53634
  }
53613
- function dragFigureForResize(initialFigure, dirX, dirY, { x: mouseX, y: mouseY }, { x: mouseInitialX, y: mouseInitialY }, keepRatio, minFigSize, { scrollX: initialScrollX, scrollY: initialScrollY }, { scrollX, scrollY }, { maxX, maxY }) {
53614
- let { x, y, width, height } = initialFigure;
53635
+ function dragFigureForResize(initialRect, dirX, dirY, { x: mouseX, y: mouseY }, { x: mouseInitialX, y: mouseInitialY }, keepRatio, minFigSize, { scrollX: initialScrollX, scrollY: initialScrollY }, { scrollX, scrollY }, { maxX, maxY }) {
53636
+ let { x, y, width, height } = initialRect;
53615
53637
  if (keepRatio && dirX !== 0 && dirY !== 0) {
53616
- const deltaX = Math.min(dirX * (mouseInitialX - mouseX + scrollX - initialScrollX), width - minFigSize);
53617
- const deltaY = Math.min(dirY * (mouseInitialY - mouseY + scrollY - initialScrollY), height - minFigSize);
53638
+ const deltaX = Math.min(dirX * (mouseInitialX - mouseX + scrollX - initialScrollX), width - minFigSize.width);
53639
+ const deltaY = Math.min(dirY * (mouseInitialY - mouseY + scrollY - initialScrollY), height - minFigSize.height);
53618
53640
  const fraction = Math.min(deltaX / width, deltaY / height);
53619
53641
  if (dirX < 0) x = x + width * fraction;
53620
53642
  if (dirY < 0) y = y + height * fraction;
53621
53643
  width = width * (1 - fraction);
53622
53644
  height = height * (1 - fraction);
53623
53645
  } else {
53624
- const deltaX = Math.max(dirX * (mouseX - mouseInitialX + scrollX - initialScrollX), minFigSize - width);
53625
- const deltaY = Math.max(dirY * (mouseY - mouseInitialY + scrollY - initialScrollY), minFigSize - height);
53646
+ const deltaX = Math.max(dirX * (mouseX - mouseInitialX + scrollX - initialScrollX), minFigSize.width - width);
53647
+ const deltaY = Math.max(dirY * (mouseY - mouseInitialY + scrollY - initialScrollY), minFigSize.height - height);
53626
53648
  width = width + deltaX;
53627
53649
  height = height + deltaY;
53628
53650
  if (dirX < 0) x = x - deltaX;
@@ -53637,7 +53659,6 @@ set(value) {
53637
53659
  y = -scrollY;
53638
53660
  } else if (y + height > maxY) height = maxY - y;
53639
53661
  return {
53640
- ...initialFigure,
53641
53662
  x,
53642
53663
  y,
53643
53664
  width,
@@ -53700,29 +53721,30 @@ set(value) {
53700
53721
  * Try to snap the given figure to the other figures when resizing the figure, and return the snapped
53701
53722
  * figure and the possible snap lines, if any were found
53702
53723
  */
53703
- function snapForResize(env, resizeDirX, resizeDirY, figureToSnap, otherFigures) {
53704
- const verticalSnapLine = getSnapLine(env, figureToSnap, [resizeDirX === -1 ? "left" : "right"], otherFigures, ["right", "left"]);
53724
+ function snapForResize(env, resizeDirX, resizeDirY, rect, otherFigures) {
53725
+ const verticalSnapLine = getSnapLine(env, rect, [resizeDirX === -1 ? "left" : "right"], otherFigures, ["right", "left"]);
53726
+ const horizontalSnapLine = getSnapLine(env, rect, [resizeDirY === -1 ? "top" : "bottom"], otherFigures, ["bottom", "top"]);
53705
53727
  if (verticalSnapLine) {
53706
- if (resizeDirX === 1) figureToSnap.width -= verticalSnapLine.snapOffset;
53728
+ if (resizeDirX === 1) rect.width -= verticalSnapLine.snapOffset;
53707
53729
  else if (resizeDirX === -1) {
53708
- figureToSnap.x -= verticalSnapLine.snapOffset;
53709
- figureToSnap.width += verticalSnapLine.snapOffset;
53730
+ rect.x -= verticalSnapLine.snapOffset;
53731
+ rect.width += verticalSnapLine.snapOffset;
53710
53732
  }
53711
53733
  }
53712
- const horizontalSnapLine = getSnapLine(env, figureToSnap, [resizeDirY === -1 ? "top" : "bottom"], otherFigures, ["bottom", "top"]);
53713
53734
  if (horizontalSnapLine) {
53714
- if (resizeDirY === 1) figureToSnap.height -= horizontalSnapLine.snapOffset;
53735
+ if (resizeDirY === 1) rect.height -= horizontalSnapLine.snapOffset;
53715
53736
  else if (resizeDirY === -1) {
53716
- figureToSnap.y -= horizontalSnapLine.snapOffset;
53717
- figureToSnap.height += horizontalSnapLine.snapOffset;
53737
+ rect.y -= horizontalSnapLine.snapOffset;
53738
+ rect.height += horizontalSnapLine.snapOffset;
53718
53739
  }
53719
53740
  }
53720
- figureToSnap.x = Math.round(figureToSnap.x);
53721
- figureToSnap.y = Math.round(figureToSnap.y);
53722
- figureToSnap.height = Math.round(figureToSnap.height);
53723
- figureToSnap.width = Math.round(figureToSnap.width);
53724
53741
  return {
53725
- snappedFigures: [figureToSnap],
53742
+ snappedRect: {
53743
+ x: Math.round(rect.x),
53744
+ y: Math.round(rect.y),
53745
+ width: Math.round(rect.width),
53746
+ height: Math.round(rect.height)
53747
+ },
53726
53748
  verticalSnapLine,
53727
53749
  horizontalSnapLine
53728
53750
  };
@@ -53913,7 +53935,7 @@ set(value) {
53913
53935
  this.zoomStore = useStore(ZoomStore);
53914
53936
  this.chartDragStore = useStore(ChartDragStore);
53915
53937
  (0, _odoo_owl.onMounted)(() => {
53916
- this.render();
53938
+ render(this);
53917
53939
  });
53918
53940
  (0, _odoo_owl.onWillUpdateProps)(() => {
53919
53941
  const sheetId = this.env.model.getters.getActiveSheetId();
@@ -53987,6 +54009,13 @@ set(value) {
53987
54009
  get selectedRectStyle() {
53988
54010
  return this.dnd.selectedRect ? this.rectToCss(this.dnd.selectedRect) : "";
53989
54011
  }
54012
+ get maxDimensions() {
54013
+ const sheetId = this.env.model.getters.getActiveSheetId();
54014
+ return {
54015
+ maxX: this.env.model.getters.getColDimensions(sheetId, this.env.model.getters.getNumberCols(sheetId) - 1).end,
54016
+ maxY: this.env.model.getters.getRowDimensions(sheetId, this.env.model.getters.getNumberRows(sheetId) - 1).end
54017
+ };
54018
+ }
53990
54019
  getInverseViewportPositionStyle(container) {
53991
54020
  const { scrollX, scrollY } = this.viewStore.activeSheetScrollInfo;
53992
54021
  const { x: viewportX, y: viewportY } = this.viewStore.mainViewportCoordinates;
@@ -54044,12 +54073,9 @@ set(value) {
54044
54073
  y: ev.clientY / zoom
54045
54074
  };
54046
54075
  const initialScrollPosition = this.viewStore.activeSheetScrollInfo;
54076
+ const maxDimensions = this.maxDimensions;
54047
54077
  const initialFigures = this.env.model.getters.getSelectedFigureIds().map((id) => this.env.model.getters.getFigure(sheetId, id)).filter(isDefined).map((f) => this.env.model.getters.getFigureUI(sheetId, f)).map(this.toBottomRightViewport.bind(this));
54048
54078
  const draggedFigureId = figureUI.id;
54049
- const maxDimensions = {
54050
- maxX: this.env.model.getters.getColDimensions(sheetId, this.env.model.getters.getNumberCols(sheetId) - 1).end,
54051
- maxY: this.env.model.getters.getRowDimensions(sheetId, this.env.model.getters.getNumberRows(sheetId) - 1).end
54052
- };
54053
54079
  let hasStartedDnd = false;
54054
54080
  let overlappingChartOrCarousel = void 0;
54055
54081
  const onMouseMove = (ev) => {
@@ -54096,7 +54122,7 @@ set(value) {
54096
54122
  ...this.viewStore.viewports.getPositionAnchorOffset(sheetId, f)
54097
54123
  };
54098
54124
  }) || [];
54099
- this.env.model.dispatch("MOVE_FIGURES", { figures: payloads });
54125
+ this.env.model.dispatch("UPDATE_FIGURES", { figures: payloads });
54100
54126
  } else {
54101
54127
  const overlappingFigureId = overlappingChartOrCarousel.id;
54102
54128
  const chartFigureIds = this.dnd.selectedFigures?.map((f) => f.id) || [];
@@ -54121,7 +54147,7 @@ set(value) {
54121
54147
  this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
54122
54148
  }
54123
54149
  /**
54124
- * Initialize the resize of a figure with mouse movements
54150
+ * Initialize the resize of the selected figures with mouse movements
54125
54151
  *
54126
54152
  * @param dirX X direction of the resize. -1 : resize from the left border of the figure, 0 : no resize in X, 1 :
54127
54153
  * resize from the right border of the figure
@@ -54129,44 +54155,78 @@ set(value) {
54129
54155
  * resize from the bottom border of the figure
54130
54156
  * @param ev Mouse Event
54131
54157
  */
54132
- startResize(figureUI, dirX, dirY, ev) {
54158
+ resizeAllSelectedFigures(dirX, dirY, ev) {
54133
54159
  ev.stopPropagation();
54134
- const initialScrollPosition = this.viewStore.activeSheetScrollInfo;
54135
- const keepRatio = figureRegistry.get(figureUI.tag).keepRatio || false;
54136
- const minFigSize = figureRegistry.get(figureUI.tag).minFigSize || 80;
54137
- const zoom = this.zoomStore.zoomLevel;
54138
54160
  const sheetId = this.env.model.getters.getActiveSheetId();
54161
+ const zoom = this.zoomStore.zoomLevel;
54139
54162
  const initialMousePosition = {
54140
54163
  x: ev.clientX / zoom,
54141
54164
  y: ev.clientY / zoom
54142
54165
  };
54143
- const maxDimensions = {
54144
- maxX: this.env.model.getters.getColDimensions(sheetId, this.env.model.getters.getNumberCols(sheetId) - 1).end,
54145
- maxY: this.env.model.getters.getRowDimensions(sheetId, this.env.model.getters.getNumberRows(sheetId) - 1).end
54146
- };
54166
+ const initialScrollPosition = this.viewStore.activeSheetScrollInfo;
54167
+ const maxDimensions = this.maxDimensions;
54168
+ const selectedFiguresIds = this.env.model.getters.getSelectedFigureIds();
54169
+ const initialFigures = selectedFiguresIds.map((id) => this.env.model.getters.getFigure(sheetId, id)).filter(isDefined).map((figure) => this.env.model.getters.getFigureUI(sheetId, figure)).map(this.toBottomRightViewport.bind(this));
54170
+ const mutlipleFiguresSelected = selectedFiguresIds.length > 1;
54171
+ const otherFiguresUI = this.getOtherFigures(selectedFiguresIds);
54172
+ if (initialFigures.length === 0) return;
54173
+ let minAggregateSize;
54174
+ if (mutlipleFiguresSelected) {
54175
+ const widthScaleMax = Math.max(...initialFigures.map((f) => {
54176
+ return figureRegistry.get(f.tag).minFigSize / f.width;
54177
+ }));
54178
+ const heightScaleMax = Math.max(...initialFigures.map((f) => {
54179
+ return figureRegistry.get(f.tag).minFigSize / f.height;
54180
+ }));
54181
+ const initialAggregateRect = rectUnion(...initialFigures);
54182
+ minAggregateSize = {
54183
+ width: Math.round(initialAggregateRect.width * widthScaleMax),
54184
+ height: Math.round(initialAggregateRect.height * heightScaleMax)
54185
+ };
54186
+ } else {
54187
+ const minFigSize = figureRegistry.get(initialFigures[0].tag).minFigSize;
54188
+ minAggregateSize = {
54189
+ width: minFigSize,
54190
+ height: minFigSize
54191
+ };
54192
+ }
54147
54193
  const onMouseMove = (ev) => {
54148
- const draggedFigure = dragFigureForResize(figureUI, dirX, dirY, {
54194
+ const currentMousePosition = {
54149
54195
  x: ev.clientX / zoom,
54150
54196
  y: ev.clientY / zoom
54151
- }, initialMousePosition, keepRatio, minFigSize, initialScrollPosition, this.viewStore.activeSheetScrollInfo, maxDimensions);
54152
- const otherFigures = this.getOtherFigures([figureUI.id]);
54153
- const snapResult = snapForResize(this.env, dirX, dirY, draggedFigure, otherFigures);
54154
- this.dnd.draggedFigure = snapResult.snappedFigures[0];
54155
- this.dnd.selectedFigures = [this.dnd.draggedFigure];
54156
- this.dnd.selectedRect = void 0;
54157
- this.dnd.horizontalSnap = this.getSnap(snapResult.horizontalSnapLine);
54158
- this.dnd.verticalSnap = this.getSnap(snapResult.verticalSnapLine);
54197
+ };
54198
+ const keepRatio = mutlipleFiguresSelected || ev.shiftKey ? true : figureRegistry.get(initialFigures[0].tag).keepRatio || false;
54199
+ const initialRect = rectUnion(...initialFigures);
54200
+ const resizedRect = dragFigureForResize(initialRect, dirX, dirY, currentMousePosition, initialMousePosition, keepRatio, minAggregateSize, initialScrollPosition, this.viewStore.activeSheetScrollInfo, maxDimensions);
54201
+ const { snappedRect, verticalSnapLine, horizontalSnapLine } = snapForResize(this.env, dirX, dirY, resizedRect, otherFiguresUI);
54202
+ const scaleX = snappedRect.width / initialRect.width;
54203
+ const scaleY = snappedRect.height / initialRect.height;
54204
+ const snappedFigures = initialFigures.map((figureUI) => ({
54205
+ ...figureUI,
54206
+ x: Math.round(snappedRect.x + (figureUI.x - initialRect.x) * scaleX),
54207
+ y: Math.round(snappedRect.y + (figureUI.y - initialRect.y) * scaleY),
54208
+ width: Math.round(figureUI.width * scaleX),
54209
+ height: Math.round(figureUI.height * scaleY)
54210
+ }));
54211
+ this.dnd.draggedFigure = snappedFigures[0];
54212
+ this.dnd.selectedFigures = snappedFigures;
54213
+ this.dnd.selectedRect = this.getDndFigureRect();
54214
+ this.dnd.horizontalSnap = this.getSnap(horizontalSnapLine);
54215
+ this.dnd.verticalSnap = this.getSnap(verticalSnapLine);
54159
54216
  };
54160
- const onMouseUp = (ev) => {
54161
- if (!this.dnd.draggedFigure) return;
54162
- const update = this.viewStore.viewports.getPositionAnchorOffset(this.env.model.getters.getActiveSheetId(), this.dnd.draggedFigure);
54163
- if (dirX) update.width = this.dnd.draggedFigure.width;
54164
- if (dirY) update.height = this.dnd.draggedFigure.height;
54165
- this.env.model.dispatch("UPDATE_FIGURE", {
54166
- sheetId: this.env.model.getters.getActiveSheetId(),
54167
- figureId: figureUI.id,
54168
- ...update
54217
+ const onMouseUp = () => {
54218
+ if (!this.dnd.selectedFigures) return;
54219
+ const dispatchPayload = this.dnd.selectedFigures.map((figureUI) => {
54220
+ const update = this.viewStore.viewports.getPositionAnchorOffset(sheetId, figureUI);
54221
+ if (dirX) update.width = figureUI.width;
54222
+ if (dirY) update.height = figureUI.height;
54223
+ return {
54224
+ sheetId,
54225
+ figureId: figureUI.id,
54226
+ ...update
54227
+ };
54169
54228
  });
54229
+ this.env.model.dispatch("UPDATE_FIGURES", { figures: dispatchPayload });
54170
54230
  this.dnd.draggedFigure = void 0;
54171
54231
  this.dnd.selectedFigures = void 0;
54172
54232
  this.dnd.selectedRect = void 0;
@@ -54829,7 +54889,7 @@ set(value) {
54829
54889
  passive: false,
54830
54890
  capture: false
54831
54891
  });
54832
- useExternalListener(window, "pointerup", onPointerUp, {
54892
+ (0, _odoo_owl.useListener)(window, "pointerup", onPointerUp, {
54833
54893
  passive: false,
54834
54894
  capture: true
54835
54895
  });
@@ -55393,10 +55453,10 @@ set(value) {
55393
55453
  this.checkboxToggleStore = useStore(CheckboxToggleStore);
55394
55454
  useStore(ArrayFormulaHighlight);
55395
55455
  this.automaticSumStore = useLocalStore(AutomaticSumStore);
55396
- useChildSubEnv({ getPopoverContainerRect: () => this.getGridRect() });
55397
- useExternalListener(document.body, "cut", this.copy.bind(this, true));
55398
- useExternalListener(document.body, "copy", this.copy.bind(this, false));
55399
- useExternalListener(document.body, "paste", this.paste);
55456
+ useSubEnv({ getPopoverContainerRect: () => this.getGridRect() });
55457
+ (0, _odoo_owl.useListener)(document.body, "cut", this.copy.bind(this, true));
55458
+ (0, _odoo_owl.useListener)(document.body, "copy", this.copy.bind(this, false));
55459
+ (0, _odoo_owl.useListener)(document.body, "paste", this.paste.bind(this));
55400
55460
  (0, _odoo_owl.onMounted)(() => this.focusDefaultElement());
55401
55461
  this.props.exposeFocus(() => this.focusDefaultElement());
55402
55462
  useGridDrawing({
@@ -64527,36 +64587,37 @@ set(value) {
64527
64587
  //#endregion
64528
64588
  //#region src/plugins/ui_core_views/evaluation_chart.ts
64529
64589
  var EvaluationChartPlugin = class extends CoreViewPlugin {
64530
- static getters = ["getChartRuntime", "getStyleOfSingleCellChart"];
64590
+ static getters = ["getStyleOfSingleCellChart", "getChartRuntimeWithTheme"];
64531
64591
  charts = {};
64532
64592
  handle(cmd) {
64533
- if (invalidateEvaluationCommands.has(cmd.type) || invalidateCFEvaluationCommands.has(cmd.type) || invalidateChartEvaluationCommands.has(cmd.type)) for (const chartId in this.charts) this.charts[chartId] = void 0;
64593
+ if (invalidateEvaluationCommands.has(cmd.type) || invalidateCFEvaluationCommands.has(cmd.type) || invalidateChartEvaluationCommands.has(cmd.type)) for (const chartId in this.charts) this.charts[chartId] = {};
64534
64594
  switch (cmd.type) {
64535
64595
  case "UPDATE_CHART":
64536
64596
  case "CREATE_CHART":
64537
- this.charts[cmd.chartId] = void 0;
64597
+ this.charts[cmd.chartId] = {};
64538
64598
  break;
64539
64599
  case "DELETE_CHART":
64540
- this.charts[cmd.chartId] = void 0;
64600
+ this.charts[cmd.chartId] = {};
64541
64601
  break;
64542
64602
  case "DELETE_SHEET":
64543
- for (const chartId in this.charts) if (!this.getters.isChartDefined(chartId)) this.charts[chartId] = void 0;
64603
+ for (const chartId in this.charts) if (!this.getters.isChartDefined(chartId)) this.charts[chartId] = {};
64544
64604
  break;
64545
64605
  }
64546
64606
  }
64547
- getChartRuntime(chartId) {
64548
- if (!this.charts[chartId]) {
64607
+ getChartRuntimeWithTheme(chartId, colorThemeName) {
64608
+ if (!this.charts[chartId]) this.charts[chartId] = {};
64609
+ if (!this.charts[chartId][colorThemeName]) {
64549
64610
  const chart = this.getters.getChart(chartId);
64550
64611
  if (!chart) throw new Error(`No chart for the given id: ${chartId}`);
64551
- this.charts[chartId] = this.createRuntimeChart(chartId, chart);
64612
+ this.charts[chartId][colorThemeName] = this.createRuntimeChart(chartId, chart, colorThemeName);
64552
64613
  }
64553
- return this.charts[chartId];
64614
+ return this.charts[chartId][colorThemeName];
64554
64615
  }
64555
64616
  /**
64556
64617
  * Get the background and textColor of a chart based on the color of the first cell of the main range of the chart.
64557
64618
  */
64558
- getStyleOfSingleCellChart(chartBackground, mainRange) {
64559
- const themeBackground = this.getters.getSpreadsheetTheme().backgroundColor;
64619
+ getStyleOfSingleCellChart(chartBackground, mainRange, colorThemeName) {
64620
+ const themeBackground = COLOR_THEMES[colorThemeName].backgroundColor;
64560
64621
  if (chartBackground) return {
64561
64622
  background: chartBackground,
64562
64623
  fontColor: chartFontColor(chartBackground)
@@ -64597,7 +64658,7 @@ set(value) {
64597
64658
  else {
64598
64659
  if (!chart) continue;
64599
64660
  const type = this.getters.getChartType(chartId);
64600
- const img = await chartToImageUrl(this.getters.getChartRuntime(chartId), figure, type);
64661
+ const img = await chartToImageUrl(this.getChartRuntimeWithTheme(chartId, "light"), figure, type);
64601
64662
  if (img) sheet.images.push({
64602
64663
  ...figure,
64603
64664
  tag: "image",
@@ -64615,9 +64676,9 @@ set(value) {
64615
64676
  sheet.charts = figures;
64616
64677
  }
64617
64678
  }
64618
- createRuntimeChart(chartId, chart) {
64679
+ createRuntimeChart(chartId, chart, colorThemeName) {
64619
64680
  const definition = chart.getRangeDefinition();
64620
- const runtime = chart.getRuntime(this.getters, chartId);
64681
+ const runtime = chart.getRuntime(this.getters, chartId, colorThemeName);
64621
64682
  if ("chartJsConfig" in runtime && /line|combo|bar|scatter|waterfall/.test(definition.type)) {
64622
64683
  const chartJsConfig = runtime.chartJsConfig;
64623
64684
  runtime["masterChartConfig"] = generateMasterChartConfig(chartJsConfig);
@@ -65983,6 +66044,39 @@ set(value) {
65983
66044
  }
65984
66045
  };
65985
66046
 
66047
+ //#endregion
66048
+ //#region src/plugins/ui_plugin.ts
66049
+ /**
66050
+ * UI plugins handle any transient data required to display a spreadsheet.
66051
+ * They can draw on the grid canvas.
66052
+ */
66053
+ var UIPlugin = class extends BasePlugin {
66054
+ static layers = [];
66055
+ getters;
66056
+ ui;
66057
+ selection;
66058
+ dispatch;
66059
+ canDispatch;
66060
+ constructor({ getters, stateObserver, dispatch, canDispatch, uiActions, selection }) {
66061
+ super(stateObserver);
66062
+ this.getters = getters;
66063
+ this.ui = uiActions;
66064
+ this.selection = selection;
66065
+ this.dispatch = dispatch;
66066
+ this.canDispatch = canDispatch;
66067
+ }
66068
+ drawLayer(ctx, layer) {}
66069
+ };
66070
+
66071
+ //#endregion
66072
+ //#region src/plugins/ui_feature/chart_ui.ts
66073
+ var ChartUIPlugin = class extends UIPlugin {
66074
+ static getters = ["getChartRuntime"];
66075
+ getChartRuntime(chartId) {
66076
+ return this.getters.getChartRuntimeWithTheme(chartId, this.getters.getSpreadsheetTheme().colorThemeName);
66077
+ }
66078
+ };
66079
+
65986
66080
  //#endregion
65987
66081
  //#region src/helpers/range_adapter_functions.ts
65988
66082
  function getRangeAdapterFunctions(executedCommand) {
@@ -66972,30 +67066,6 @@ set(value) {
66972
67066
  }
66973
67067
  };
66974
67068
 
66975
- //#endregion
66976
- //#region src/plugins/ui_plugin.ts
66977
- /**
66978
- * UI plugins handle any transient data required to display a spreadsheet.
66979
- * They can draw on the grid canvas.
66980
- */
66981
- var UIPlugin = class extends BasePlugin {
66982
- static layers = [];
66983
- getters;
66984
- ui;
66985
- selection;
66986
- dispatch;
66987
- canDispatch;
66988
- constructor({ getters, stateObserver, dispatch, canDispatch, uiActions, selection }) {
66989
- super(stateObserver);
66990
- this.getters = getters;
66991
- this.ui = uiActions;
66992
- this.selection = selection;
66993
- this.dispatch = dispatch;
66994
- this.canDispatch = canDispatch;
66995
- }
66996
- drawLayer(ctx, layer) {}
66997
- };
66998
-
66999
67069
  //#endregion
67000
67070
  //#region src/plugins/ui_feature/collaborative.ts
67001
67071
  var CollaborativePlugin = class extends UIPlugin {
@@ -67079,41 +67149,6 @@ set(value) {
67079
67149
 
67080
67150
  //#endregion
67081
67151
  //#region src/plugins/ui_feature/color_theme.ts
67082
- const FROZEN_PANE_HEADER_BORDER_COLOR = "#BCBCBC";
67083
- const FROZEN_PANE_BORDER_COLOR = "#DADFE8";
67084
- const HEADER_BORDER_COLOR = "#C0C0C0";
67085
- const TEXT_HEADER_COLOR = "#666666";
67086
- const BACKGROUND_HEADER_COLOR = "#F8F9FA";
67087
- const BACKGROUND_HEADER_SELECTED_COLOR = "#E8EAED";
67088
- const BACKGROUND_HEADER_ACTIVE_COLOR = "#595959";
67089
- const COLOR_THEMES = {
67090
- light: {
67091
- backgroundColor: "#FFFFFF",
67092
- gridBorderColor: "#CECFCF",
67093
- headerBackgroundColor: BACKGROUND_HEADER_COLOR,
67094
- headerActiveBackgroundColor: BACKGROUND_HEADER_ACTIVE_COLOR,
67095
- headerSelectedBackgroundColor: BACKGROUND_HEADER_SELECTED_COLOR,
67096
- headerTextColor: TEXT_HEADER_COLOR,
67097
- headerBorderColor: HEADER_BORDER_COLOR,
67098
- frozenPaneBorderColor: FROZEN_PANE_BORDER_COLOR,
67099
- frozenPaneHeaderBorderColor: FROZEN_PANE_HEADER_BORDER_COLOR,
67100
- singleCellSelectionBackgroundColor: "#F3F7FE",
67101
- multipleCellsSelectionBackgroundColor: "#E9F0FF"
67102
- },
67103
- dark: {
67104
- backgroundColor: adaptForDarkMode("#1A1C2E"),
67105
- gridBorderColor: adaptForDarkMode("#6B706F"),
67106
- headerBackgroundColor: adaptForDarkMode("#262A36"),
67107
- headerActiveBackgroundColor: adaptForDarkMode("#3A4052"),
67108
- headerSelectedBackgroundColor: adaptForDarkMode("#4E566E"),
67109
- headerTextColor: adaptForDarkMode("#A1A6B3"),
67110
- headerBorderColor: adaptForDarkMode("#7A7F91"),
67111
- frozenPaneBorderColor: adaptForDarkMode("#7A7F91"),
67112
- frozenPaneHeaderBorderColor: adaptForDarkMode("#9FA5BD"),
67113
- singleCellSelectionBackgroundColor: adaptForDarkMode("#696E8044"),
67114
- multipleCellsSelectionBackgroundColor: adaptForDarkMode("#828AA044")
67115
- }
67116
- };
67117
67152
  var ColorThemeUIPlugin = class extends UIPlugin {
67118
67153
  static getters = ["isDarkMode", "getSpreadsheetTheme"];
67119
67154
  colorScheme;
@@ -69384,7 +69419,7 @@ set(value) {
69384
69419
  static getters = ["getFigureUI"];
69385
69420
  allowDispatch(cmd) {
69386
69421
  switch (cmd.type) {
69387
- case "MOVE_FIGURES":
69422
+ case "UPDATE_FIGURES":
69388
69423
  for (const updateFigurePayload of cmd.figures) {
69389
69424
  const result = this.canDispatch("UPDATE_FIGURE", updateFigurePayload);
69390
69425
  if (!result.isSuccessful) return result.reasons;
@@ -69408,7 +69443,7 @@ set(value) {
69408
69443
  }
69409
69444
  handle(cmd) {
69410
69445
  switch (cmd.type) {
69411
- case "MOVE_FIGURES":
69446
+ case "UPDATE_FIGURES":
69412
69447
  for (const updateFigurePayload of cmd.figures) this.dispatch("UPDATE_FIGURE", updateFigurePayload);
69413
69448
  break;
69414
69449
  case "DELETE_FIGURES":
@@ -70555,7 +70590,7 @@ set(value) {
70555
70590
  //#endregion
70556
70591
  //#region src/plugins/plugin_registries.ts
70557
70592
  const corePluginRegistry = new Registry().add("settings", SettingsPlugin).add("sheet", SheetPlugin).add("header grouping", HeaderGroupingPlugin).add("header visibility", HeaderVisibilityPlugin).add("tables", TablePlugin).add("dataValidation", DataValidationPlugin).add("cell", CellPlugin).add("default", DefaultPlugin).add("merge", MergePlugin).add("headerSize", HeaderSizePlugin).add("borders", BordersPlugin).add("conditional formatting", ConditionalFormatPlugin).add("figures", FigurePlugin).add("chart", ChartPlugin).add("carousel", CarouselPlugin).add("image", ImagePlugin).add("named_ranges", NamedRangesPlugin).add("pivot_core", PivotCorePlugin).add("spreadsheet_pivot_core", SpreadsheetPivotCorePlugin).add("tableStyle", TableStylePlugin);
70558
- const featurePluginRegistry = new Registry().add("ui_sheet", SheetUIPlugin).add("ui_options", UIOptionsPlugin).add("sort", SortPlugin).add("format", FormatPlugin).add("insert_pivot", InsertPivotPlugin).add("pivot_presence", PivotPresencePlugin).add("subtotal_evaluation", SubtotalEvaluationPlugin).add("collaborative", CollaborativePlugin).add("history", HistoryPlugin).add("datavalidation_insert", DataValidationInsertionPlugin).add("dynamic_translate", DynamicTranslate).add("geo_features", GeoFeaturePlugin).add("color_theme", ColorThemeUIPlugin).add("lock_sheet", LockSheetPlugin);
70593
+ const featurePluginRegistry = new Registry().add("ui_sheet", SheetUIPlugin).add("ui_options", UIOptionsPlugin).add("sort", SortPlugin).add("format", FormatPlugin).add("insert_pivot", InsertPivotPlugin).add("pivot_presence", PivotPresencePlugin).add("subtotal_evaluation", SubtotalEvaluationPlugin).add("collaborative", CollaborativePlugin).add("history", HistoryPlugin).add("datavalidation_insert", DataValidationInsertionPlugin).add("dynamic_translate", DynamicTranslate).add("geo_features", GeoFeaturePlugin).add("color_theme", ColorThemeUIPlugin).add("lock_sheet", LockSheetPlugin).add("chart_ui", ChartUIPlugin);
70559
70594
  const statefulUIPluginRegistry = new Registry().add("selection", GridSelectionPlugin).add("evaluation_filter", FilterEvaluationPlugin).add("header_visibility_ui", HeaderVisibilityUIPlugin).add("cell_computed_style", CellComputedStylePlugin).add("table_computed_style", TableComputedStylePlugin).add("header_positions", HeaderPositionsUIPlugin).add("clipboard", ClipboardPlugin).add("carousel_ui", CarouselUIPlugin).add("figure_ui", FigureUIPlugin);
70560
70595
  const coreViewsPluginRegistry = new Registry().add("evaluation", EvaluationPlugin).add("evaluation_chart", EvaluationChartPlugin).add("fingerprints", FingerprintPlugin).add("evaluation_cf", EvaluationConditionalFormatPlugin).add("row_size", HeaderSizeUIPlugin).add("data_validation_ui", EvaluationDataValidationPlugin).add("dynamic_tables", DynamicTablesPlugin).add("custom_colors", CustomColorsPlugin).add("pivot_ui", PivotUIPlugin).add("cell_icon", CellIconPlugin).add("formula_tracker", FormulaTrackerPlugin);
70561
70596
 
@@ -71497,6 +71532,31 @@ set(value) {
71497
71532
  var MainViewportStore = class extends SpreadsheetStore {
71498
71533
  viewStore = this.get(ViewportsStore);
71499
71534
  sheetIdAtFinalize = void 0;
71535
+ constructor(get) {
71536
+ super(get);
71537
+ this.model.selection.observe(this, { handleEvent: this.handleEvent.bind(this) });
71538
+ this.onDispose(() => {
71539
+ this.model.selection.unobserve(this);
71540
+ });
71541
+ }
71542
+ handleEvent(event) {
71543
+ const eventSheetId = this.getters.getActiveSheetId();
71544
+ if (event.options.scrollIntoView) {
71545
+ const oldZone = event.previousAnchor.zone;
71546
+ const newZone = event.anchor.zone;
71547
+ const isUpdateAnchorEvent = event.mode === "updateAnchor";
71548
+ const sameZone = isEqual(oldZone, newZone);
71549
+ let { col, row } = isUpdateAnchorEvent && sameZone ? event.anchor.cell : findCellInNewZone(oldZone, newZone);
71550
+ if (isUpdateAnchorEvent && !sameZone) {
71551
+ const { top, bottom, left, right } = this.viewStore.viewports.getMainInternalViewport(eventSheetId);
71552
+ if (oldZone.left === newZone.left && oldZone.right === newZone.right) col = left > col || col > right ? left : col;
71553
+ if (oldZone.top === newZone.top && oldZone.bottom === newZone.bottom) row = top > row || row > bottom ? top : row;
71554
+ }
71555
+ col = Math.min(col, this.getters.getNumberCols(eventSheetId) - 1);
71556
+ row = Math.min(row, this.getters.getNumberRows(eventSheetId) - 1);
71557
+ this.viewStore.scrollToCell(eventSheetId, col, row);
71558
+ }
71559
+ }
71500
71560
  handle(cmd) {
71501
71561
  switch (cmd.type) {
71502
71562
  case "UNDO":
@@ -71886,7 +71946,7 @@ set(value) {
71886
71946
  DOMFocusableElementStore;
71887
71947
  setup() {
71888
71948
  this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
71889
- useExternalListener(window, "click", this.onExternalClick.bind(this), { capture: true });
71949
+ (0, _odoo_owl.useListener)(window, "click", this.onExternalClick.bind(this), { capture: true });
71890
71950
  useLayoutEffect(() => {}, () => [this.state.isEditing]);
71891
71951
  (0, _odoo_owl.onPatched)(() => {
71892
71952
  if (this.sheetNameRef() && this.state.isEditing && this.editionState === "initializing") {
@@ -72450,7 +72510,7 @@ set(value) {
72450
72510
  this.zoomStore = useStore(ZoomStore);
72451
72511
  useLocalStore(HoveredTableStore);
72452
72512
  const rendererStore = useLocalStore(RendererStore, OrderedLayers().filter((layer) => layer !== "Headers"));
72453
- useChildSubEnv({ getPopoverContainerRect: () => this.zoomStore.getZoomedRect(this.getGridRect()) });
72513
+ useSubEnv({ getPopoverContainerRect: () => this.zoomStore.getZoomedRect(this.getGridRect()) });
72454
72514
  useGridDrawing({
72455
72515
  canvasRef: this.canvasRef,
72456
72516
  rendererStore,
@@ -72522,13 +72582,12 @@ set(value) {
72522
72582
  return this.env.model.getters.getColDimensions(sheetId, right).end;
72523
72583
  }
72524
72584
  get dashboardStyle() {
72525
- const style = { zoom: this.zoomStore.cssZoom };
72526
- if (this.env.model.getters.getActiveSheet().backgroundColor) style["background-color"] = "transparent";
72527
- return cssPropertiesToCss(style);
72585
+ return cssPropertiesToCss({ zoom: this.zoomStore.cssZoom });
72528
72586
  }
72529
72587
  get backgroundStyle() {
72530
72588
  const sheet = this.env.model.getters.getActiveSheet();
72531
- return sheet.backgroundColor ? cssPropertiesToCss({ "background-color": sheet.backgroundColor }) : "";
72589
+ const theme = this.env.model.getters.getSpreadsheetTheme();
72590
+ return cssPropertiesToCss({ "background-color": sheet.backgroundColor || theme.backgroundColor });
72532
72591
  }
72533
72592
  };
72534
72593
 
@@ -72874,7 +72933,7 @@ set(value) {
72874
72933
  parentState: void 0
72875
72934
  });
72876
72935
  setup() {
72877
- useExternalListener(window, "click", this.onExternalClick, { capture: true });
72936
+ (0, _odoo_owl.useListener)(window, "click", this.onExternalClick.bind(this), { capture: true });
72878
72937
  (0, _odoo_owl.onMounted)(this.updateShadows);
72879
72938
  }
72880
72939
  onExternalClick(ev) {
@@ -73528,7 +73587,7 @@ set(value) {
73528
73587
  setup() {
73529
73588
  this.printStore = useLocalStore(SpreadsheetPrintStore);
73530
73589
  let styleElement = null;
73531
- useExternalListener(window, "beforeprint", () => {
73590
+ (0, _odoo_owl.useListener)(window, "beforeprint", () => {
73532
73591
  styleElement = document.createElement("style");
73533
73592
  styleElement.id = "o-spreadsheet-print-style";
73534
73593
  const size = `${this.printStore.pageLayout} ${this.printStore.orientation}`;
@@ -73541,7 +73600,7 @@ set(value) {
73541
73600
  styleElement = null;
73542
73601
  }
73543
73602
  };
73544
- useExternalListener(window, "afterprint", () => removePrintStyle());
73603
+ (0, _odoo_owl.useListener)(window, "afterprint", () => removePrintStyle());
73545
73604
  (0, _odoo_owl.onWillUnmount)(() => removePrintStyle());
73546
73605
  }
73547
73606
  get pageStyle() {
@@ -74530,8 +74589,8 @@ set(value) {
74530
74589
  this.composerFocusStore = useStore(ComposerFocusStore);
74531
74590
  this.fingerprints = useStore(FormulaFingerprintStore);
74532
74591
  this.topBarToolStore = useStore(TopBarToolStore);
74533
- useExternalListener(window, "click", this.onExternalClick);
74534
- useExternalListener(window, "keydown", this.onKeydown);
74592
+ (0, _odoo_owl.useListener)(window, "click", this.onExternalClick.bind(this));
74593
+ (0, _odoo_owl.useListener)(window, "keydown", this.onKeydown.bind(this));
74535
74594
  this.menus = topbarMenuRegistry.getMenuItems();
74536
74595
  let lastWidth;
74537
74596
  const updateVisibility = () => {
@@ -74858,9 +74917,9 @@ set(value) {
74858
74917
  const el = this.spreadsheetRef();
74859
74918
  if (el && !el.contains(document.activeElement) && document.activeElement?.contains(el)) this.focusGrid();
74860
74919
  });
74861
- useExternalListener(window, "resize", () => this.render(true));
74862
- useExternalListener(document.body, "wheel", () => {});
74863
- useExternalListener(window, "keydown", async (event) => {
74920
+ (0, _odoo_owl.useListener)(window, "resize", () => render(this, true));
74921
+ (0, _odoo_owl.useListener)(document.body, "wheel", () => {});
74922
+ (0, _odoo_owl.useListener)(window, "keydown", async (event) => {
74864
74923
  if (keyboardEventToShortcutString(event) === "Ctrl+P") {
74865
74924
  this.state.printModeEnabled = true;
74866
74925
  event.stopPropagation();
@@ -74880,11 +74939,11 @@ set(value) {
74880
74939
  resizeObserver.observe(el);
74881
74940
  return () => resizeObserver.disconnect();
74882
74941
  });
74883
- const render = batched(this.render.bind(this, true));
74942
+ const batchedRender = batched(() => render(this, true));
74884
74943
  (0, _odoo_owl.onMounted)(() => {
74885
74944
  this.bindModelEvents();
74886
74945
  this.checkViewportSize();
74887
- stores.on("store-updated", this, render);
74946
+ stores.on("store-updated", this, batchedRender);
74888
74947
  });
74889
74948
  (0, _odoo_owl.onWillUnmount)(() => {
74890
74949
  this.unbindModelEvents();
@@ -74896,7 +74955,7 @@ set(value) {
74896
74955
  });
74897
74956
  }
74898
74957
  bindModelEvents() {
74899
- this.model.on("update", this, () => this.render(true));
74958
+ this.model.on("update", this, () => render(this, true));
74900
74959
  this.model.on("command-rejected", this, ({ result }) => {
74901
74960
  if (result.isCancelledBecause("SheetLocked")) this.notificationStore.notifyUser({
74902
74961
  type: "info",
@@ -80969,6 +81028,10 @@ set(value) {
80969
81028
  this.computeLinks();
80970
81029
  (0, _odoo_owl.onMounted)(() => this.urlInput()?.focus());
80971
81030
  }
81031
+ onLinkUrlInput(ev) {
81032
+ this.state.url = ev.target.value;
81033
+ this.computeLinks();
81034
+ }
80972
81035
  computeLinks() {
80973
81036
  this.state.selectedIndex = null;
80974
81037
  this.state.linksByCategory = this.linkProposalByCategory;
@@ -81668,8 +81731,8 @@ set(value) {
81668
81731
  };
81669
81732
  },
81670
81733
  copyInSheetId: (definition) => definition,
81671
- getRuntime(getters, definition) {
81672
- const chartData = getBubbleChartData(definition, getters);
81734
+ getRuntime(getters, definition, chartDataExtractors, sheetId, eventHandlers, colorThemeName) {
81735
+ const chartData = getBubbleChartData(definition, getters, colorThemeName);
81673
81736
  return { chartJsConfig: {
81674
81737
  type: "line",
81675
81738
  data: {
@@ -81744,8 +81807,8 @@ set(value) {
81744
81807
  };
81745
81808
  },
81746
81809
  getDefinitionForExcel: () => void 0,
81747
- getRuntime(getters, definition, { extractData }) {
81748
- const chartData = getCalendarChartData(definition, extractData(), getters);
81810
+ getRuntime(getters, definition, { extractData }, sheetId, eventHandlers, colorThemeName) {
81811
+ const chartData = getCalendarChartData(definition, extractData(), getters, colorThemeName);
81749
81812
  const { labels, datasets } = getCalendarChartDatasetAndLabels(definition, chartData);
81750
81813
  return { chartJsConfig: {
81751
81814
  type: "calendar",
@@ -81831,8 +81894,8 @@ set(value) {
81831
81894
  annotationLink: context.annotationLink
81832
81895
  };
81833
81896
  },
81834
- getRuntime(getters, definition, { extractData }, sheetId, eventHandlers) {
81835
- const chartData = getBarChartData(definition, extractData(), getters);
81897
+ getRuntime(getters, definition, { extractData }, sheetId, eventHandlers, colorThemeName) {
81898
+ const chartData = getBarChartData(definition, extractData(), getters, colorThemeName);
81836
81899
  return {
81837
81900
  chartJsConfig: {
81838
81901
  type: "bar",
@@ -81908,8 +81971,8 @@ set(value) {
81908
81971
  };
81909
81972
  },
81910
81973
  getDefinitionForExcel: () => void 0,
81911
- getRuntime(getters, definition, { extractData }, sheetId, eventHandlers) {
81912
- const chartData = getFunnelChartData(definition, extractData(), getters);
81974
+ getRuntime(getters, definition, { extractData }, sheetId, eventHandlers, colorThemeName) {
81975
+ const chartData = getFunnelChartData(definition, extractData(), getters, colorThemeName);
81913
81976
  return { chartJsConfig: {
81914
81977
  type: "funnel",
81915
81978
  data: {
@@ -81971,8 +82034,8 @@ set(value) {
81971
82034
  };
81972
82035
  },
81973
82036
  getDefinitionForExcel: () => void 0,
81974
- getRuntime(getters, definition, { extractData }, sheetId, eventHandlers) {
81975
- const chartData = getGeoChartData(definition, extractData(), getters);
82037
+ getRuntime(getters, definition, { extractData }, sheetId, eventHandlers, colorThemeName) {
82038
+ const chartData = getGeoChartData(definition, extractData(), getters, colorThemeName);
81976
82039
  return { chartJsConfig: {
81977
82040
  type: "choropleth",
81978
82041
  data: { datasets: getGeoChartDatasets(definition, chartData) },
@@ -82041,7 +82104,7 @@ set(value) {
82041
82104
  },
82042
82105
  getDefinitionForExcel(getters, definition, { dataSets, labelRange }) {
82043
82106
  if (definition.dataSource.type !== "range") return;
82044
- const chartData = getPyramidChartData(definition, getChartData(getters, definition.dataSource), getters);
82107
+ const chartData = getPyramidChartData(definition, getChartData(getters, definition.dataSource), getters, "light");
82045
82108
  const { dataSetsValues } = chartData;
82046
82109
  const maxValue = Math.max(...dataSetsValues.map((dataSet) => Math.max(...dataSet.data.map((cell) => isNumberResult(cell) ? Math.abs(cell.value) : -Infinity))));
82047
82110
  return {
@@ -82055,8 +82118,8 @@ set(value) {
82055
82118
  maxValue
82056
82119
  };
82057
82120
  },
82058
- getRuntime(getters, definition, { extractData }, sheetId, eventHandlers) {
82059
- const chartData = getPyramidChartData(definition, extractData(), getters);
82121
+ getRuntime(getters, definition, { extractData }, sheetId, eventHandlers, colorThemeName) {
82122
+ const chartData = getPyramidChartData(definition, extractData(), getters, colorThemeName);
82060
82123
  return {
82061
82124
  chartJsConfig: {
82062
82125
  type: "bar",
@@ -82138,8 +82201,8 @@ set(value) {
82138
82201
  labelRange
82139
82202
  };
82140
82203
  },
82141
- getRuntime(getters, definition, { extractData }, sheetId, eventHandlers) {
82142
- const chartData = getRadarChartData(definition, extractData(), getters);
82204
+ getRuntime(getters, definition, { extractData }, sheetId, eventHandlers, colorThemeName) {
82205
+ const chartData = getRadarChartData(definition, extractData(), getters, colorThemeName);
82143
82206
  return {
82144
82207
  chartJsConfig: {
82145
82208
  type: "radar",
@@ -82219,8 +82282,8 @@ set(value) {
82219
82282
  verticalAxis: getDefinedAxis(definition)
82220
82283
  };
82221
82284
  },
82222
- getRuntime(getters, definition, { extractData }, sheetId, eventHandlers) {
82223
- const chartData = getLineChartData(definition, extractData(), getters);
82285
+ getRuntime(getters, definition, { extractData }, sheetId, eventHandlers, colorThemeName) {
82286
+ const chartData = getLineChartData(definition, extractData(), getters, colorThemeName);
82224
82287
  return {
82225
82288
  chartJsConfig: {
82226
82289
  type: "line",
@@ -82298,8 +82361,8 @@ set(value) {
82298
82361
  };
82299
82362
  },
82300
82363
  getDefinitionForExcel: () => void 0,
82301
- getRuntime(getters, definition, { extractHierarchicalData }, sheetId, eventHandlers) {
82302
- const chartData = getHierarchalChartData(definition, extractHierarchicalData(), getters);
82364
+ getRuntime(getters, definition, { extractHierarchicalData }, sheetId, eventHandlers, colorThemeName) {
82365
+ const chartData = getHierarchalChartData(definition, extractHierarchicalData(), getters, colorThemeName);
82303
82366
  return { chartJsConfig: {
82304
82367
  type: "doughnut",
82305
82368
  data: { datasets: getSunburstChartDatasets(definition, chartData) },
@@ -82372,8 +82435,8 @@ set(value) {
82372
82435
  };
82373
82436
  },
82374
82437
  getDefinitionForExcel: () => void 0,
82375
- getRuntime(getters, definition, { extractHierarchicalData }, sheetId, eventHandlers) {
82376
- const chartData = getHierarchalChartData(definition, extractHierarchicalData(), getters);
82438
+ getRuntime(getters, definition, { extractHierarchicalData }, sheetId, eventHandlers, colorThemeName) {
82439
+ const chartData = getHierarchalChartData(definition, extractHierarchicalData(), getters, colorThemeName);
82377
82440
  return { chartJsConfig: {
82378
82441
  type: "treemap",
82379
82442
  data: {
@@ -90860,7 +90923,6 @@ set(value) {
90860
90923
  };
90861
90924
  const compatibility = {
90862
90925
  Component,
90863
- useExternalListener,
90864
90926
  EnvPlugin,
90865
90927
  App: App$1
90866
90928
  };
@@ -91010,8 +91072,8 @@ exports.stores = stores;
91010
91072
  exports.tokenColors = tokenColors;
91011
91073
  exports.tokenize = tokenize;
91012
91074
 
91013
- __info__.version = "19.5.0-alpha.12";
91014
- __info__.date = "2026-08-19T09:47:03.774Z";
91015
- __info__.hash = "68ca68e";
91075
+ __info__.version = "19.5.0-alpha.14";
91076
+ __info__.date = "2026-08-29T09:17:09.184Z";
91077
+ __info__.hash = "e8ad6ad";
91016
91078
 
91017
91079
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);