@odoo/o-spreadsheet 18.5.0-alpha.6 → 18.5.0-alpha.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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 18.5.0-alpha.6
6
- * @date 2025-08-05T06:27:49.505Z
7
- * @hash 67e091f
5
+ * @version 18.5.0-alpha.7
6
+ * @date 2025-08-08T11:00:44.117Z
7
+ * @hash 1019d55
8
8
  */
9
9
 
10
10
  'use strict';
@@ -2657,6 +2657,7 @@ const readonlyAllowedCommands = new Set([
2657
2657
  "SET_FORMULA_VISIBILITY",
2658
2658
  "UPDATE_FILTER",
2659
2659
  "UPDATE_CHART",
2660
+ "UPDATE_CAROUSEL_ACTIVE_ITEM",
2660
2661
  ]);
2661
2662
  const coreTypes = new Set([
2662
2663
  /** CELLS */
@@ -2699,6 +2700,8 @@ const coreTypes = new Set([
2699
2700
  "CREATE_FIGURE",
2700
2701
  "DELETE_FIGURE",
2701
2702
  "UPDATE_FIGURE",
2703
+ "CREATE_CAROUSEL",
2704
+ "UPDATE_CAROUSEL",
2702
2705
  /** FORMATTING */
2703
2706
  "SET_FORMATTING",
2704
2707
  "CLEAR_FORMATTING",
@@ -2708,6 +2711,7 @@ const coreTypes = new Set([
2708
2711
  /** CHART */
2709
2712
  "CREATE_CHART",
2710
2713
  "UPDATE_CHART",
2714
+ "DELETE_CHART",
2711
2715
  /** FILTERS */
2712
2716
  "CREATE_TABLE",
2713
2717
  "REMOVE_TABLE",
@@ -2902,6 +2906,7 @@ exports.CommandResult = void 0;
2902
2906
  CommandResult["InvalidColor"] = "InvalidColor";
2903
2907
  CommandResult["InvalidPivotDataSet"] = "InvalidPivotDataSet";
2904
2908
  CommandResult["InvalidPivotCustomField"] = "InvalidPivotCustomField";
2909
+ CommandResult["MissingFigureArguments"] = "MissingFigureArguments";
2905
2910
  })(exports.CommandResult || (exports.CommandResult = {}));
2906
2911
 
2907
2912
  const availableConditionalFormatOperators = new Set([
@@ -9222,7 +9227,7 @@ class ChartClipboardHandler extends AbstractFigureClipboardHandler {
9222
9227
  return;
9223
9228
  }
9224
9229
  const copiedFigure = { ...figure };
9225
- const chart = this.getters.getChart(data.figureId);
9230
+ const chart = this.getters.getChartFromFigureId(data.figureId);
9226
9231
  if (!chart) {
9227
9232
  throw new Error(`No chart for the given id: ${data.figureId}`);
9228
9233
  }
@@ -9258,6 +9263,7 @@ class ChartClipboardHandler extends AbstractFigureClipboardHandler {
9258
9263
  }
9259
9264
  this.dispatch("CREATE_CHART", {
9260
9265
  figureId,
9266
+ chartId: figureId,
9261
9267
  sheetId,
9262
9268
  definition: copy.getDefinition(),
9263
9269
  col,
@@ -22998,7 +23004,7 @@ chartJsExtensionRegistry.add("sunburstHoverPlugin", {
22998
23004
  class ChartJsComponent extends owl.Component {
22999
23005
  static template = "o-spreadsheet-ChartJsComponent";
23000
23006
  static props = {
23001
- figureUI: Object,
23007
+ chartId: String,
23002
23008
  isFullScreen: { type: Boolean, optional: true },
23003
23009
  };
23004
23010
  canvas = owl.useRef("graphContainer");
@@ -23013,7 +23019,7 @@ class ChartJsComponent extends owl.Component {
23013
23019
  return `background-color: ${this.background}`;
23014
23020
  }
23015
23021
  get chartRuntime() {
23016
- const runtime = this.env.model.getters.getChartRuntime(this.props.figureUI.id);
23022
+ const runtime = this.env.model.getters.getChartRuntime(this.props.chartId);
23017
23023
  if (!("chartJsConfig" in runtime)) {
23018
23024
  throw new Error("Unsupported chart runtime");
23019
23025
  }
@@ -23051,7 +23057,7 @@ class ChartJsComponent extends owl.Component {
23051
23057
  }
23052
23058
  createChart(chartData) {
23053
23059
  if (this.env.model.getters.isDashboard() && this.animationStore) {
23054
- const chartType = this.env.model.getters.getChart(this.props.figureUI.id)?.type;
23060
+ const chartType = this.env.model.getters.getChart(this.props.chartId)?.type;
23055
23061
  if (chartType && this.animationStore.animationPlayed[this.animationFigureId] !== chartType) {
23056
23062
  chartData = this.enableAnimationInChartData(chartData);
23057
23063
  this.animationStore.disableAnimationForChart(this.animationFigureId, chartType);
@@ -23063,7 +23069,7 @@ class ChartJsComponent extends owl.Component {
23063
23069
  }
23064
23070
  updateChartJs(chartData) {
23065
23071
  if (this.env.model.getters.isDashboard()) {
23066
- const chartType = this.env.model.getters.getChart(this.props.figureUI.id)?.type;
23072
+ const chartType = this.env.model.getters.getChart(this.props.chartId)?.type;
23067
23073
  if (chartType && this.hasChartDataChanged() && this.animationStore) {
23068
23074
  chartData = this.enableAnimationInChartData(chartData);
23069
23075
  this.animationStore.disableAnimationForChart(this.animationFigureId, chartType);
@@ -23091,9 +23097,7 @@ class ChartJsComponent extends owl.Component {
23091
23097
  };
23092
23098
  }
23093
23099
  get animationFigureId() {
23094
- return this.props.isFullScreen
23095
- ? this.props.figureUI.id + "-fullscreen"
23096
- : this.props.figureUI.id;
23100
+ return this.props.isFullScreen ? this.props.chartId + "-fullscreen" : this.props.chartId;
23097
23101
  }
23098
23102
  }
23099
23103
 
@@ -23758,14 +23762,14 @@ class ScorecardChartConfigBuilder {
23758
23762
  class ScorecardChart extends owl.Component {
23759
23763
  static template = "o-spreadsheet-ScorecardChart";
23760
23764
  static props = {
23761
- figureUI: Object,
23765
+ chartId: String,
23762
23766
  };
23763
23767
  canvas = owl.useRef("chartContainer");
23764
23768
  get runtime() {
23765
- return this.env.model.getters.getChartRuntime(this.props.figureUI.id);
23769
+ return this.env.model.getters.getChartRuntime(this.props.chartId);
23766
23770
  }
23767
23771
  get title() {
23768
- const title = this.env.model.getters.getChartDefinition(this.props.figureUI.id).title.text ?? "";
23772
+ const title = this.env.model.getters.getChartDefinition(this.props.chartId).title.text ?? "";
23769
23773
  // chart titles are extracted from .json files and they are translated at runtime here
23770
23774
  return _t(title);
23771
23775
  }
@@ -27087,13 +27091,13 @@ const ANIMATION_DURATION = 1000;
27087
27091
  class GaugeChartComponent extends owl.Component {
27088
27092
  static template = "o-spreadsheet-GaugeChartComponent";
27089
27093
  static props = {
27090
- figureUI: Object,
27094
+ chartId: String,
27091
27095
  isFullScreen: { type: Boolean, optional: true },
27092
27096
  };
27093
27097
  canvas = owl.useRef("chartContainer");
27094
27098
  animationStore;
27095
27099
  get runtime() {
27096
- return this.env.model.getters.getChartRuntime(this.props.figureUI.id);
27100
+ return this.env.model.getters.getChartRuntime(this.props.chartId);
27097
27101
  }
27098
27102
  setup() {
27099
27103
  if (this.env.model.getters.isDashboard()) {
@@ -27141,9 +27145,7 @@ class GaugeChartComponent extends owl.Component {
27141
27145
  return this.canvas.el;
27142
27146
  }
27143
27147
  get animationFigureId() {
27144
- return this.props.isFullScreen
27145
- ? this.props.figureUI.id + "-fullscreen"
27146
- : this.props.figureUI.id;
27148
+ return this.props.isFullScreen ? this.props.chartId + "-fullscreen" : this.props.chartId;
27147
27149
  }
27148
27150
  }
27149
27151
  /**
@@ -29432,7 +29434,7 @@ chartSubtypeRegistry
29432
29434
  */
29433
29435
  function chartFactory(getters) {
29434
29436
  const builders = chartRegistry.getAll().sort((a, b) => a.sequence - b.sequence);
29435
- function createChart(id, definition, sheetId) {
29437
+ function createChart(figureId, definition, sheetId) {
29436
29438
  const builder = builders.find((builder) => builder.match(definition.type));
29437
29439
  if (!builder) {
29438
29440
  throw new Error(`No builder for this chart: ${definition.type}`);
@@ -29783,6 +29785,8 @@ function getDefaultXLSXStructure(data) {
29783
29785
  return {
29784
29786
  relsFiles: [],
29785
29787
  sharedStrings: [],
29788
+ chartIds: [],
29789
+ imageIds: [],
29786
29790
  // default Values that will always be part of the style sheet
29787
29791
  styles: [
29788
29792
  {
@@ -29860,6 +29864,10 @@ function escapeQueryNameSpaces(query) {
29860
29864
  }
29861
29865
 
29862
29866
  function getChartMenuActions(figureId, onFigureDeleted, env) {
29867
+ const chartId = env.model.getters.getChartIdFromFigureId(figureId);
29868
+ if (!chartId) {
29869
+ return [];
29870
+ }
29863
29871
  const menuItemSpecs = [
29864
29872
  {
29865
29873
  id: "edit",
@@ -29882,8 +29890,8 @@ function getChartMenuActions(figureId, onFigureDeleted, env) {
29882
29890
  execute: async () => {
29883
29891
  const figureSheetId = env.model.getters.getFigureSheetId(figureId);
29884
29892
  const figure = env.model.getters.getFigure(figureSheetId, figureId);
29885
- const chartType = env.model.getters.getChartType(figureId);
29886
- const runtime = env.model.getters.getChartRuntime(figureId);
29893
+ const chartType = env.model.getters.getChartType(chartId);
29894
+ const runtime = env.model.getters.getChartRuntime(chartId);
29887
29895
  const imageUrl = chartToImageUrl(runtime, figure, chartType);
29888
29896
  const innerHTML = `<img src="${xmlEscape(imageUrl)}" />`;
29889
29897
  const blob = await chartToImageFile(runtime, figure, chartType);
@@ -29903,8 +29911,8 @@ function getChartMenuActions(figureId, onFigureDeleted, env) {
29903
29911
  execute: async () => {
29904
29912
  const figureSheetId = env.model.getters.getFigureSheetId(figureId);
29905
29913
  const figure = env.model.getters.getFigure(figureSheetId, figureId);
29906
- const chartType = env.model.getters.getChartType(figureId);
29907
- const runtime = env.model.getters.getChartRuntime(figureId);
29914
+ const chartType = env.model.getters.getChartType(chartId);
29915
+ const runtime = env.model.getters.getChartRuntime(chartId);
29908
29916
  const url = chartToImageUrl(runtime, figure, chartType);
29909
29917
  downloadFile(url, "chart");
29910
29918
  },
@@ -29963,6 +29971,35 @@ function getImageMenuActions(figureId, onFigureDeleted, env) {
29963
29971
  ];
29964
29972
  return createActions(menuItemSpecs);
29965
29973
  }
29974
+ function getCarouselMenuActions(figureId, onFigureDeleted, env) {
29975
+ const menuItemSpecs = [
29976
+ {
29977
+ id: "edit_carousel",
29978
+ name: _t("Edit carousel"),
29979
+ sequence: 1,
29980
+ execute: () => {
29981
+ env.model.dispatch("SELECT_FIGURE", { figureId });
29982
+ env.openSidePanel("CarouselPanel", { figureId });
29983
+ },
29984
+ icon: "o-spreadsheet-Icon.EDIT",
29985
+ isEnabled: (env) => !env.isSmall,
29986
+ },
29987
+ {
29988
+ id: "edit_chart",
29989
+ name: _t("Edit chart"),
29990
+ sequence: 1,
29991
+ execute: () => {
29992
+ env.model.dispatch("SELECT_FIGURE", { figureId });
29993
+ env.openSidePanel("ChartPanel", {});
29994
+ },
29995
+ icon: "o-spreadsheet-Icon.EDIT",
29996
+ isEnabled: (env) => !env.isSmall,
29997
+ isVisible: (env) => env.model.getters.getSelectedCarouselItem(figureId)?.type === "chart",
29998
+ },
29999
+ getDeleteMenuItem(figureId, onFigureDeleted, env),
30000
+ ];
30001
+ return createActions(menuItemSpecs).filter((action) => env.model.getters.isReadonly() ? action.isReadonlyAllowed : true);
30002
+ }
29966
30003
  function getCopyMenuItem(figureId, env, copiedNotificationMessage) {
29967
30004
  return {
29968
30005
  id: "copy",
@@ -30011,6 +30048,103 @@ function getDeleteMenuItem(figureId, onFigureDeleted, env) {
30011
30048
  };
30012
30049
  }
30013
30050
 
30051
+ const CAROUSEL_DEFAULT_CHART_DEFINITION = {
30052
+ type: "bar",
30053
+ title: {},
30054
+ stacked: false,
30055
+ dataSetsHaveTitle: false,
30056
+ dataSets: [],
30057
+ legendPosition: "top",
30058
+ };
30059
+ function getCarouselItemPreview(getters, item) {
30060
+ if (item.type === "carouselDataView") {
30061
+ return "o-spreadsheet-Icon.LIST";
30062
+ }
30063
+ const definition = getters.getChartDefinition(item.chartId);
30064
+ const matchedChart = chartSubtypeRegistry.getAll().find((c) => c.matcher?.(definition)) ||
30065
+ chartSubtypeRegistry.get(definition.type);
30066
+ return matchedChart.preview;
30067
+ }
30068
+ function getCarouselItemTitle(getters, item) {
30069
+ if (item.title) {
30070
+ return item.title;
30071
+ }
30072
+ if (item.type === "carouselDataView") {
30073
+ return _t("Data");
30074
+ }
30075
+ const definition = getters.getChartDefinition(item.chartId);
30076
+ const matchedChart = chartSubtypeRegistry.getAll().find((c) => c.matcher?.(definition)) ||
30077
+ chartSubtypeRegistry.get(definition.type);
30078
+ return matchedChart.displayName;
30079
+ }
30080
+
30081
+ class CarouselFigure extends owl.Component {
30082
+ static template = "o-spreadsheet-CarouselFigure";
30083
+ static props = {
30084
+ figureUI: Object,
30085
+ onFigureDeleted: Function,
30086
+ editFigureStyle: { type: Function, optional: true },
30087
+ };
30088
+ static components = {};
30089
+ setup() {
30090
+ owl.useEffect(() => {
30091
+ if (this.selectedCarouselItem?.type === "carouselDataView") {
30092
+ this.props.editFigureStyle?.({ "pointer-events": "none" });
30093
+ }
30094
+ else {
30095
+ this.props.editFigureStyle?.({ "pointer-events": "auto" });
30096
+ }
30097
+ });
30098
+ }
30099
+ get carousel() {
30100
+ return this.env.model.getters.getCarousel(this.props.figureUI.id);
30101
+ }
30102
+ get selectedCarouselItem() {
30103
+ return this.env.model.getters.getSelectedCarouselItem(this.props.figureUI.id);
30104
+ }
30105
+ get chartComponent() {
30106
+ const selectedItem = this.selectedCarouselItem;
30107
+ if (selectedItem?.type !== "chart") {
30108
+ throw new Error("Selected item is not a chart");
30109
+ }
30110
+ const type = this.env.model.getters.getChartType(selectedItem.chartId);
30111
+ const component = chartComponentRegistry.get(type);
30112
+ if (!component) {
30113
+ throw new Error(`Component is not defined for type ${type}`);
30114
+ }
30115
+ return component;
30116
+ }
30117
+ onCarouselDoubleClick() {
30118
+ this.env.model.dispatch("SELECT_FIGURE", { figureId: this.props.figureUI.id });
30119
+ this.env.openSidePanel("CarouselPanel", { figureId: this.props.figureUI.id });
30120
+ }
30121
+ isItemSelected(item) {
30122
+ const selectedItem = this.selectedCarouselItem;
30123
+ return deepEquals(selectedItem, item);
30124
+ }
30125
+ getItemTitle(item) {
30126
+ return getCarouselItemTitle(this.env.model.getters, item);
30127
+ }
30128
+ onCarouselTabClick(item) {
30129
+ this.env.model.dispatch("UPDATE_CAROUSEL_ACTIVE_ITEM", {
30130
+ figureId: this.props.figureUI.id,
30131
+ sheetId: this.env.model.getters.getActiveSheetId(),
30132
+ item,
30133
+ });
30134
+ if (item.type === "carouselDataView" &&
30135
+ this.env.model.getters.getSelectedFigureId() === this.props.figureUI.id) {
30136
+ this.env.model.dispatch("SELECT_FIGURE", { figureId: null });
30137
+ }
30138
+ }
30139
+ get headerStyle() {
30140
+ const cssProperties = {};
30141
+ if (this.selectedCarouselItem?.type === "carouselDataView") {
30142
+ cssProperties["background-color"] = "#ffffff";
30143
+ }
30144
+ return cssPropertiesToCss(cssProperties);
30145
+ }
30146
+ }
30147
+
30014
30148
  class FullScreenChartStore extends SpreadsheetStore {
30015
30149
  mutators = ["toggleFullScreenChart"];
30016
30150
  fullScreenFigure = undefined;
@@ -30795,9 +30929,9 @@ class ChartDashboardMenuStore extends SpreadsheetStore {
30795
30929
  this.originalChartDefinition = this.getters.getChartDefinition(chartId);
30796
30930
  }
30797
30931
  updateType(type) {
30798
- const figureId = this.chartId;
30799
- const currentDefinition = this.getters.getChartDefinition(figureId);
30800
- if (currentDefinition.type === type) {
30932
+ const chartId = this.chartId;
30933
+ const currentDefinition = this.getters.getChartDefinition(chartId);
30934
+ if (currentDefinition?.type === type) {
30801
30935
  return;
30802
30936
  }
30803
30937
  let definition;
@@ -30807,7 +30941,7 @@ class ChartDashboardMenuStore extends SpreadsheetStore {
30807
30941
  else {
30808
30942
  const newChartInfo = chartSubtypeRegistry.get(type);
30809
30943
  const ChartClass = chartRegistry.get(newChartInfo.chartType);
30810
- const chartCreationContext = this.getters.getContextCreationChart(figureId);
30944
+ const chartCreationContext = this.getters.getContextCreationChart(chartId);
30811
30945
  if (!chartCreationContext)
30812
30946
  return;
30813
30947
  definition = {
@@ -30817,7 +30951,8 @@ class ChartDashboardMenuStore extends SpreadsheetStore {
30817
30951
  }
30818
30952
  this.model.dispatch("UPDATE_CHART", {
30819
30953
  definition,
30820
- figureId,
30954
+ chartId,
30955
+ figureId: this.getters.getFigureIdFromChartId(chartId),
30821
30956
  sheetId: this.getters.getActiveSheetId(),
30822
30957
  });
30823
30958
  }
@@ -30838,17 +30973,17 @@ class ChartDashboardMenuStore extends SpreadsheetStore {
30838
30973
  class ChartDashboardMenu extends owl.Component {
30839
30974
  static template = "o-spreadsheet-ChartDashboardMenu";
30840
30975
  static components = { MenuPopover };
30841
- static props = { figureUI: Object };
30976
+ static props = { chartId: String };
30842
30977
  fullScreenFigureStore;
30843
30978
  store;
30844
30979
  menuState = owl.useState({ isOpen: false, anchorRect: null, menuItems: [] });
30845
30980
  setup() {
30846
30981
  super.setup();
30847
- this.store = useLocalStore(ChartDashboardMenuStore, this.props.figureUI.id);
30982
+ this.store = useLocalStore(ChartDashboardMenuStore, this.props.chartId);
30848
30983
  this.fullScreenFigureStore = useStore(FullScreenChartStore);
30849
- owl.onWillUpdateProps(({ figureUI }) => {
30850
- if (figureUI.id !== this.props.figureUI.id) {
30851
- this.store.reset(figureUI.id);
30984
+ owl.onWillUpdateProps(({ chartId }) => {
30985
+ if (chartId !== this.props.chartId) {
30986
+ this.store.reset(chartId);
30852
30987
  }
30853
30988
  });
30854
30989
  }
@@ -30856,26 +30991,28 @@ class ChartDashboardMenu extends owl.Component {
30856
30991
  return [this.fullScreenMenuItem, ...this.store.changeChartTypeMenuItems].filter(isDefined);
30857
30992
  }
30858
30993
  get backgroundColor() {
30859
- const color = this.env.model.getters.getChartDefinition(this.props.figureUI.id).background;
30994
+ const color = this.env.model.getters.getChartDefinition(this.props.chartId).background;
30860
30995
  return "background-color: " + (color || BACKGROUND_CHART_COLOR);
30861
30996
  }
30862
30997
  openContextMenu(ev) {
30863
30998
  this.menuState.isOpen = true;
30864
30999
  this.menuState.anchorRect = { x: ev.clientX, y: ev.clientY, width: 0, height: 0 };
30865
- this.menuState.menuItems = getChartMenuActions(this.props.figureUI.id, () => { }, this.env);
31000
+ const figureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
31001
+ this.menuState.menuItems = getChartMenuActions(figureId, () => { }, this.env);
30866
31002
  }
30867
31003
  get fullScreenMenuItem() {
30868
- const definition = this.env.model.getters.getChartDefinition(this.props.figureUI.id);
31004
+ const definition = this.env.model.getters.getChartDefinition(this.props.chartId);
31005
+ const figureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
30869
31006
  if (definition.type === "scorecard") {
30870
31007
  return undefined;
30871
31008
  }
30872
- if (this.props.figureUI.id === this.fullScreenFigureStore.fullScreenFigure?.id) {
31009
+ if (this.props.chartId === this.fullScreenFigureStore.fullScreenFigure?.id) {
30873
31010
  return {
30874
31011
  id: "fullScreenChart",
30875
31012
  label: _t("Exit Full Screen"),
30876
31013
  iconClass: "fa fa-compress",
30877
31014
  onClick: () => {
30878
- this.fullScreenFigureStore.toggleFullScreenChart(this.props.figureUI.id);
31015
+ this.fullScreenFigureStore.toggleFullScreenChart(figureId);
30879
31016
  },
30880
31017
  };
30881
31018
  }
@@ -30884,7 +31021,7 @@ class ChartDashboardMenu extends owl.Component {
30884
31021
  label: _t("Full Screen"),
30885
31022
  iconClass: "fa fa-expand",
30886
31023
  onClick: () => {
30887
- this.fullScreenFigureStore.toggleFullScreenChart(this.props.figureUI.id);
31024
+ this.fullScreenFigureStore.toggleFullScreenChart(figureId);
30888
31025
  },
30889
31026
  };
30890
31027
  }
@@ -30905,6 +31042,7 @@ class ChartFigure extends owl.Component {
30905
31042
  static props = {
30906
31043
  figureUI: Object,
30907
31044
  onFigureDeleted: Function,
31045
+ editFigureStyle: { type: Function, optional: true },
30908
31046
  };
30909
31047
  static components = { ChartDashboardMenu };
30910
31048
  onDoubleClick() {
@@ -30912,7 +31050,14 @@ class ChartFigure extends owl.Component {
30912
31050
  this.env.openSidePanel("ChartPanel");
30913
31051
  }
30914
31052
  get chartType() {
30915
- return this.env.model.getters.getChartType(this.props.figureUI.id);
31053
+ return this.env.model.getters.getChartType(this.chartId);
31054
+ }
31055
+ get chartId() {
31056
+ const chartId = this.env.model.getters.getChartIdFromFigureId(this.props.figureUI.id);
31057
+ if (!chartId) {
31058
+ throw new Error(`No chart found for figure ID: ${this.props.figureUI.id}`);
31059
+ }
31060
+ return chartId;
30916
31061
  }
30917
31062
  get chartComponent() {
30918
31063
  const type = this.chartType;
@@ -30929,6 +31074,7 @@ class ImageFigure extends owl.Component {
30929
31074
  static props = {
30930
31075
  figureUI: Object,
30931
31076
  onFigureDeleted: Function,
31077
+ editFigureStyle: { type: Function, optional: true },
30932
31078
  };
30933
31079
  static components = {};
30934
31080
  // ---------------------------------------------------------------------------
@@ -30955,6 +31101,10 @@ figureRegistry.add("image", {
30955
31101
  borderWidth: 0,
30956
31102
  menuBuilder: getImageMenuActions,
30957
31103
  });
31104
+ figureRegistry.add("carousel", {
31105
+ Component: CarouselFigure,
31106
+ menuBuilder: getCarouselMenuActions,
31107
+ });
30958
31108
 
30959
31109
  // -----------------------------------------------------------------------------
30960
31110
  // STYLE
@@ -30981,6 +31131,7 @@ css /*SCSS*/ `
30981
31131
  .o-figure-wrapper {
30982
31132
  position: absolute;
30983
31133
  box-sizing: content-box;
31134
+ pointer-events: auto;
30984
31135
 
30985
31136
  .o-fig-anchor {
30986
31137
  z-index: ${ComponentsImportance.FigureAnchor};
@@ -31039,6 +31190,7 @@ class FigureComponent extends owl.Component {
31039
31190
  static props = {
31040
31191
  figureUI: Object,
31041
31192
  style: { type: String, optional: true },
31193
+ class: { type: String, optional: true },
31042
31194
  onFigureDeleted: { type: Function, optional: true },
31043
31195
  onMouseDown: { type: Function, optional: true },
31044
31196
  onClickAnchor: { type: Function, optional: true },
@@ -31051,6 +31203,7 @@ class FigureComponent extends owl.Component {
31051
31203
  };
31052
31204
  menuState = owl.useState({ isOpen: false, anchorRect: null, menuItems: [] });
31053
31205
  figureRef = owl.useRef("figure");
31206
+ figureWrapperRef = owl.useRef("figureWrapper");
31054
31207
  menuButtonRef = owl.useRef("menuButton");
31055
31208
  borderWidth;
31056
31209
  get isSelected() {
@@ -31243,6 +31396,13 @@ class FigureComponent extends owl.Component {
31243
31396
  .get(this.props.figureUI.tag)
31244
31397
  .menuBuilder(this.props.figureUI.id, this.props.onFigureDeleted, this.env);
31245
31398
  }
31399
+ editWrapperStyle(properties) {
31400
+ if (this.figureWrapperRef.el) {
31401
+ for (const property in properties) {
31402
+ this.figureWrapperRef.el.style.setProperty(property, properties[property] || null);
31403
+ }
31404
+ }
31405
+ }
31246
31406
  }
31247
31407
 
31248
31408
  class DelayedHoveredCellStore extends SpreadsheetStore {
@@ -38775,16 +38935,15 @@ function pushElement(property, propertyList) {
38775
38935
  reverseLookup.set(canonical, maxId);
38776
38936
  return maxId;
38777
38937
  }
38778
- const chartIds = [];
38779
38938
  /**
38780
38939
  * Convert a chart o-spreadsheet id to a xlsx id which
38781
38940
  * are unsigned integers (starting from 1).
38782
38941
  */
38783
- function convertChartId(chartId) {
38784
- const xlsxId = chartIds.findIndex((id) => id === chartId);
38942
+ function convertChartId(chartId, construct) {
38943
+ const xlsxId = construct.chartIds.findIndex((id) => id === chartId);
38785
38944
  if (xlsxId === -1) {
38786
- chartIds.push(chartId);
38787
- return chartIds.length;
38945
+ construct.chartIds.push(chartId);
38946
+ return construct.chartIds.length;
38788
38947
  }
38789
38948
  return xlsxId + 1;
38790
38949
  }
@@ -41179,6 +41338,8 @@ class XlsxReader {
41179
41338
  sheets: sheets,
41180
41339
  sharedStrings,
41181
41340
  externalBooks,
41341
+ chartIds: [],
41342
+ imageIds: [],
41182
41343
  };
41183
41344
  }
41184
41345
  buildXlsxFileStructure() {
@@ -41856,6 +42017,18 @@ migrationStepRegistry
41856
42017
  }
41857
42018
  return data;
41858
42019
  },
42020
+ })
42021
+ .add("18.5.1", {
42022
+ migrate(data) {
42023
+ for (const sheet of data.sheets || []) {
42024
+ for (const figure of sheet.figures || []) {
42025
+ if (figure.tag === "chart") {
42026
+ figure.data.chartId = figure.id;
42027
+ }
42028
+ }
42029
+ }
42030
+ return data;
42031
+ },
41859
42032
  });
41860
42033
  function fixOverlappingFilters(data) {
41861
42034
  for (const sheet of data.sheets || []) {
@@ -42109,7 +42282,12 @@ function fixChartDefinitions(data, initialMessages) {
42109
42282
  sheet.figures?.forEach((figure) => {
42110
42283
  if (figure.tag === "chart") {
42111
42284
  // chart definition
42112
- map[figure.id] = figure.data;
42285
+ if (data.version && compareVersions(String(data.version), "18.5.1") <= 0) {
42286
+ map[figure.data.chartId] = figure.data;
42287
+ }
42288
+ else {
42289
+ map[figure.id] = figure.data;
42290
+ }
42113
42291
  }
42114
42292
  });
42115
42293
  }
@@ -42120,20 +42298,20 @@ function fixChartDefinitions(data, initialMessages) {
42120
42298
  let command = cmd;
42121
42299
  switch (cmd.type) {
42122
42300
  case "CREATE_CHART":
42123
- map[cmd.figureId] = cmd.definition;
42301
+ map[cmd.chartId] = cmd.definition;
42124
42302
  break;
42125
42303
  case "UPDATE_CHART":
42126
- if (!map[cmd.figureId]) {
42304
+ if (!map[cmd.chartId]) {
42127
42305
  /** the chart does not exist on the map, it might have been created after a duplicate sheet.
42128
42306
  * We don't have access to the definition, so we skip the command.
42129
42307
  */
42130
- console.log(`Fix chart definition: chart with id ${cmd.figureId} not found.`);
42308
+ console.log(`Fix chart definition: chart with id ${cmd.chartId} not found.`);
42131
42309
  continue;
42132
42310
  }
42133
- const definition = map[cmd.figureId];
42311
+ const definition = map[cmd.chartId];
42134
42312
  const newDefinition = { ...definition, ...cmd.definition };
42135
42313
  command = { ...cmd, definition: newDefinition };
42136
- map[cmd.figureId] = newDefinition;
42314
+ map[cmd.chartId] = newDefinition;
42137
42315
  break;
42138
42316
  }
42139
42317
  commands.push(command);
@@ -42706,6 +42884,7 @@ const CREATE_CHART = (env) => {
42706
42884
  const result = env.model.dispatch("CREATE_CHART", {
42707
42885
  sheetId,
42708
42886
  figureId,
42887
+ chartId: figureId,
42709
42888
  col,
42710
42889
  row,
42711
42890
  offset,
@@ -42717,6 +42896,26 @@ const CREATE_CHART = (env) => {
42717
42896
  env.openSidePanel("ChartPanel");
42718
42897
  }
42719
42898
  };
42899
+ const CREATE_CAROUSEL = (env) => {
42900
+ const getters = env.model.getters;
42901
+ const figureId = env.model.uuidGenerator.smallUuid();
42902
+ const sheetId = getters.getActiveSheetId();
42903
+ const size = { width: DEFAULT_FIGURE_WIDTH, height: DEFAULT_FIGURE_HEIGHT };
42904
+ const { col, row, offset } = centerFigurePosition(getters, size);
42905
+ const result = env.model.dispatch("CREATE_CAROUSEL", {
42906
+ sheetId,
42907
+ figureId,
42908
+ col,
42909
+ row,
42910
+ offset,
42911
+ size,
42912
+ definition: { items: [] },
42913
+ });
42914
+ if (result.isSuccessful) {
42915
+ env.model.dispatch("SELECT_FIGURE", { figureId });
42916
+ env.openSidePanel("CarouselPanel", { figureId });
42917
+ }
42918
+ };
42720
42919
  //------------------------------------------------------------------------------
42721
42920
  // Pivots
42722
42921
  //------------------------------------------------------------------------------
@@ -43968,6 +44167,12 @@ const insertChart = {
43968
44167
  isEnabled: (env) => !env.isSmall,
43969
44168
  icon: "o-spreadsheet-Icon.INSERT_CHART",
43970
44169
  };
44170
+ const insertCarousel = {
44171
+ name: _t("Carousel"),
44172
+ execute: CREATE_CAROUSEL,
44173
+ isEnabled: (env) => !env.isSmall,
44174
+ icon: "o-spreadsheet-Icon.CAROUSEL",
44175
+ };
43971
44176
  const insertPivot = {
43972
44177
  name: _t("Pivot table"),
43973
44178
  execute: CREATE_PIVOT,
@@ -48058,6 +48263,7 @@ class FiguresContainer extends owl.Component {
48058
48263
  horizontalSnap: undefined,
48059
48264
  verticalSnap: undefined,
48060
48265
  cancelDnd: undefined,
48266
+ overlappingCarousel: undefined,
48061
48267
  });
48062
48268
  setup() {
48063
48269
  owl.onMounted(() => {
@@ -48080,6 +48286,7 @@ class FiguresContainer extends owl.Component {
48080
48286
  this.dnd.draggedFigure = undefined;
48081
48287
  this.dnd.horizontalSnap = undefined;
48082
48288
  this.dnd.verticalSnap = undefined;
48289
+ this.dnd.overlappingCarousel = undefined;
48083
48290
  this.dnd.cancelDnd = undefined;
48084
48291
  }
48085
48292
  });
@@ -48218,26 +48425,46 @@ class FiguresContainer extends owl.Component {
48218
48425
  const currentMousePosition = { x: ev.clientX, y: ev.clientY };
48219
48426
  const draggedFigure = dragFigureForMove(currentMousePosition, initialMousePosition, initialFigure, maxDimensions, initialScrollPosition, getters.getActiveSheetScrollInfo());
48220
48427
  const otherFigures = this.getOtherFigures(initialFigure.id);
48221
- const snapResult = snapForMove(getters, draggedFigure, otherFigures);
48222
- this.dnd.draggedFigure = snapResult.snappedFigure;
48223
- this.dnd.horizontalSnap = this.getSnap(snapResult.horizontalSnapLine);
48224
- this.dnd.verticalSnap = this.getSnap(snapResult.verticalSnapLine);
48428
+ const overlappingCarousel = this.getCarouselOverlappingChart(draggedFigure, otherFigures);
48429
+ this.dnd.overlappingCarousel = overlappingCarousel;
48430
+ if (!overlappingCarousel) {
48431
+ const snapResult = snapForMove(getters, draggedFigure, otherFigures);
48432
+ this.dnd.draggedFigure = snapResult.snappedFigure;
48433
+ this.dnd.horizontalSnap = this.getSnap(snapResult.horizontalSnapLine);
48434
+ this.dnd.verticalSnap = this.getSnap(snapResult.verticalSnapLine);
48435
+ }
48436
+ else {
48437
+ this.dnd.draggedFigure = draggedFigure;
48438
+ this.dnd.horizontalSnap = undefined;
48439
+ this.dnd.verticalSnap = undefined;
48440
+ }
48225
48441
  };
48226
48442
  const onMouseUp = (ev) => {
48227
48443
  if (!this.dnd.draggedFigure) {
48228
48444
  return;
48229
48445
  }
48230
48446
  const { col, row, offset } = this.env.model.getters.getPositionAnchorOffset(this.dnd.draggedFigure);
48447
+ if (!this.dnd.overlappingCarousel) {
48448
+ this.env.model.dispatch("UPDATE_FIGURE", {
48449
+ sheetId,
48450
+ figureId: figureUI.id,
48451
+ offset,
48452
+ col,
48453
+ row,
48454
+ });
48455
+ }
48456
+ else {
48457
+ this.env.model.dispatch("ADD_FIGURE_CHART_TO_CAROUSEL", {
48458
+ sheetId,
48459
+ carouselFigureId: this.dnd.overlappingCarousel.id,
48460
+ chartFigureId: figureUI.id,
48461
+ });
48462
+ this.props.onFigureDeleted();
48463
+ }
48231
48464
  this.dnd.draggedFigure = undefined;
48232
48465
  this.dnd.horizontalSnap = undefined;
48233
48466
  this.dnd.verticalSnap = undefined;
48234
- this.env.model.dispatch("UPDATE_FIGURE", {
48235
- sheetId,
48236
- figureId: figureUI.id,
48237
- offset,
48238
- col,
48239
- row,
48240
- });
48467
+ this.dnd.overlappingCarousel = undefined;
48241
48468
  };
48242
48469
  this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
48243
48470
  }
@@ -48289,6 +48516,7 @@ class FiguresContainer extends owl.Component {
48289
48516
  this.dnd.draggedFigure = undefined;
48290
48517
  this.dnd.horizontalSnap = undefined;
48291
48518
  this.dnd.verticalSnap = undefined;
48519
+ this.dnd.overlappingCarousel = undefined;
48292
48520
  };
48293
48521
  this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
48294
48522
  }
@@ -48305,10 +48533,15 @@ class FiguresContainer extends owl.Component {
48305
48533
  if (figureUI.id !== this.dnd.draggedFigure?.id)
48306
48534
  return "";
48307
48535
  return cssPropertiesToCss({
48308
- opacity: "0.9",
48536
+ opacity: this.dnd.overlappingCarousel?.id ? "0.6" : "0.9",
48309
48537
  cursor: "grabbing",
48310
48538
  });
48311
48539
  }
48540
+ getFigureClass(figureUI) {
48541
+ if (figureUI.id !== this.dnd.overlappingCarousel?.id)
48542
+ return "";
48543
+ return "o-add-to-carousel";
48544
+ }
48312
48545
  getSnap(snapLine) {
48313
48546
  if (!snapLine || !this.dnd.draggedFigure)
48314
48547
  return undefined;
@@ -48355,6 +48588,20 @@ class FiguresContainer extends owl.Component {
48355
48588
  });
48356
48589
  }
48357
48590
  }
48591
+ getCarouselOverlappingChart(figureUI, otherFigures) {
48592
+ if (figureUI.tag !== "chart") {
48593
+ return undefined;
48594
+ }
48595
+ const minimumOverlap = 20; // Minimum overlap in pixels to consider a carousel overlapping
48596
+ const carousels = otherFigures.filter((f) => f.tag === "carousel");
48597
+ return carousels.find((carousel) => {
48598
+ const xOverlap = Math.max(0, Math.min(figureUI.x + figureUI.width, carousel.x + carousel.width) -
48599
+ Math.max(figureUI.x, carousel.x));
48600
+ const yOverlap = Math.max(0, Math.min(figureUI.y + figureUI.height, carousel.y + carousel.height) -
48601
+ Math.max(figureUI.y, carousel.y));
48602
+ return xOverlap >= minimumOverlap && yOverlap >= minimumOverlap;
48603
+ });
48604
+ }
48358
48605
  }
48359
48606
 
48360
48607
  css /* scss */ `
@@ -51037,6 +51284,226 @@ class Selection extends owl.Component {
51037
51284
  }
51038
51285
  }
51039
51286
 
51287
+ function useAutofocus({ refName }) {
51288
+ const ref = owl.useRef(refName);
51289
+ owl.useEffect((el) => {
51290
+ el?.focus();
51291
+ }, () => [ref.el]);
51292
+ }
51293
+
51294
+ css /* scss */ `
51295
+ .o-spreadsheet {
51296
+ .os-input {
51297
+ border-width: 0 0 1px 0;
51298
+ border-color: transparent;
51299
+ outline: none;
51300
+ text-overflow: ellipsis;
51301
+ color: ${TEXT_BODY};
51302
+ }
51303
+ .os-input:hover,
51304
+ .os-input:focus {
51305
+ border-color: ${GRAY_300};
51306
+ }
51307
+ }
51308
+ `;
51309
+ class TextInput extends owl.Component {
51310
+ static template = "o-spreadsheet-TextInput";
51311
+ static props = {
51312
+ value: String,
51313
+ onChange: Function,
51314
+ class: {
51315
+ type: String,
51316
+ optional: true,
51317
+ },
51318
+ id: {
51319
+ type: String,
51320
+ optional: true,
51321
+ },
51322
+ placeholder: {
51323
+ type: String,
51324
+ optional: true,
51325
+ },
51326
+ autofocus: {
51327
+ type: Boolean,
51328
+ optional: true,
51329
+ },
51330
+ };
51331
+ inputRef = owl.useRef("input");
51332
+ setup() {
51333
+ owl.useExternalListener(window, "click", (ev) => {
51334
+ if (ev.target !== this.inputRef.el && this.inputRef.el?.value !== this.props.value) {
51335
+ this.save();
51336
+ }
51337
+ }, { capture: true });
51338
+ if (this.props.autofocus) {
51339
+ useAutofocus({ refName: "input" });
51340
+ }
51341
+ }
51342
+ onKeyDown(ev) {
51343
+ switch (ev.key) {
51344
+ case "Enter":
51345
+ this.save();
51346
+ ev.preventDefault();
51347
+ ev.stopPropagation();
51348
+ break;
51349
+ case "Escape":
51350
+ if (this.inputRef.el) {
51351
+ this.inputRef.el.value = this.props.value;
51352
+ this.inputRef.el.blur();
51353
+ }
51354
+ ev.preventDefault();
51355
+ ev.stopPropagation();
51356
+ break;
51357
+ }
51358
+ }
51359
+ save() {
51360
+ const currentValue = (this.inputRef.el?.value || "").trim();
51361
+ if (currentValue !== this.props.value) {
51362
+ this.props.onChange(currentValue);
51363
+ }
51364
+ this.inputRef.el?.blur();
51365
+ }
51366
+ onMouseDown(ev) {
51367
+ // Stop the event if the input is not focused, we handle everything in onMouseUp
51368
+ if (ev.target !== document.activeElement) {
51369
+ ev.preventDefault();
51370
+ ev.stopPropagation();
51371
+ }
51372
+ }
51373
+ onMouseUp(ev) {
51374
+ const target = ev.target;
51375
+ if (target !== document.activeElement) {
51376
+ target.focus();
51377
+ target.select();
51378
+ ev.preventDefault();
51379
+ ev.stopPropagation();
51380
+ }
51381
+ }
51382
+ }
51383
+
51384
+ class CarouselPanel extends owl.Component {
51385
+ static template = "o-spreadsheet-CarouselPanel";
51386
+ static props = { onCloseSidePanel: Function, figureId: String };
51387
+ static components = { TextInput };
51388
+ dragAndDrop = useDragAndDropListItems();
51389
+ previewListRef = owl.useRef("previewList");
51390
+ setup() {
51391
+ let lastCarouselItems = [...this.carouselItems];
51392
+ owl.onWillUpdateProps(() => {
51393
+ if (!deepEquals(this.carouselItems, lastCarouselItems)) {
51394
+ this.dragAndDrop.cancel();
51395
+ }
51396
+ lastCarouselItems = [...this.carouselItems];
51397
+ });
51398
+ }
51399
+ get carouselItems() {
51400
+ return this.env.model.getters.getCarousel(this.props.figureId).items;
51401
+ }
51402
+ getPreviewDivStyle(item) {
51403
+ return this.dragAndDrop.itemsStyle[this.getItemId(item)] || "";
51404
+ }
51405
+ getItemId(item) {
51406
+ return item.type === "chart" ? item.chartId : "transparent-carousel";
51407
+ }
51408
+ addNewChartToCarousel() {
51409
+ this.env.model.dispatch("ADD_NEW_CHART_TO_CAROUSEL", {
51410
+ figureId: this.props.figureId,
51411
+ sheetId: this.env.model.getters.getActiveSheetId(),
51412
+ });
51413
+ }
51414
+ get hasDataView() {
51415
+ return this.carouselItems.some((item) => item.type === "carouselDataView");
51416
+ }
51417
+ addDataViewToCarousel() {
51418
+ const carousel = this.env.model.getters.getCarousel(this.props.figureId);
51419
+ this.env.model.dispatch("UPDATE_CAROUSEL", {
51420
+ figureId: this.props.figureId,
51421
+ sheetId: this.env.model.getters.getActiveSheetId(),
51422
+ definition: { items: [...carousel.items, { type: "carouselDataView" }] },
51423
+ });
51424
+ }
51425
+ activateCarouselItem(item) {
51426
+ this.env.model.dispatch("UPDATE_CAROUSEL_ACTIVE_ITEM", {
51427
+ figureId: this.props.figureId,
51428
+ sheetId: this.env.model.getters.getActiveSheetId(),
51429
+ item,
51430
+ });
51431
+ }
51432
+ editCarouselItem(item) {
51433
+ if (item.type === "chart") {
51434
+ this.activateCarouselItem(item);
51435
+ this.env.model.dispatch("SELECT_FIGURE", { figureId: this.props.figureId });
51436
+ this.env.openSidePanel("ChartPanel", { chartId: item.chartId });
51437
+ }
51438
+ }
51439
+ renameCarouselItem(item, newName) {
51440
+ const trimmedName = newName.trim();
51441
+ if (!trimmedName || trimmedName === this.getItemTitle(item).toString()) {
51442
+ return;
51443
+ }
51444
+ const items = [...this.carouselItems];
51445
+ const itemIndex = this.carouselItems.findIndex((itm) => deepEquals(itm, item));
51446
+ if (itemIndex !== -1) {
51447
+ items[itemIndex] = { ...item, title: trimmedName };
51448
+ this.env.model.dispatch("UPDATE_CAROUSEL", {
51449
+ figureId: this.props.figureId,
51450
+ sheetId: this.env.model.getters.getActiveSheetId(),
51451
+ definition: { items },
51452
+ });
51453
+ }
51454
+ }
51455
+ deleteCarouselItem(item) {
51456
+ const carousel = this.env.model.getters.getCarousel(this.props.figureId);
51457
+ const items = carousel.items.filter((itm) => !deepEquals(itm, item));
51458
+ this.env.model.dispatch("UPDATE_CAROUSEL", {
51459
+ figureId: this.props.figureId,
51460
+ sheetId: this.env.model.getters.getActiveSheetId(),
51461
+ definition: { items },
51462
+ });
51463
+ }
51464
+ onDragHandleMouseDown(item, event) {
51465
+ if (event.button !== 0)
51466
+ return;
51467
+ const previewRects = Array.from(this.previewListRef.el.children).map((previewEl) => getBoundingRectAsPOJO(previewEl));
51468
+ const items = this.carouselItems.map((item, index) => ({
51469
+ id: this.getItemId(item),
51470
+ size: previewRects[index].height,
51471
+ position: previewRects[index].y,
51472
+ }));
51473
+ this.dragAndDrop.start("vertical", {
51474
+ draggedItemId: this.getItemId(item),
51475
+ initialMousePosition: event.clientY,
51476
+ items: items,
51477
+ scrollableContainerEl: this.previewListRef.el,
51478
+ onDragEnd: (itemId, finalIndex) => this.onDragEnd(item, finalIndex),
51479
+ });
51480
+ }
51481
+ onDragEnd(item, finalIndex) {
51482
+ const originalIndex = this.carouselItems.findIndex((itm) => deepEquals(itm, item));
51483
+ if (originalIndex === -1 || originalIndex === finalIndex) {
51484
+ return;
51485
+ }
51486
+ const carousel = this.env.model.getters.getCarousel(this.props.figureId);
51487
+ const items = [...carousel.items];
51488
+ items.splice(originalIndex, 1);
51489
+ items.splice(finalIndex, 0, item);
51490
+ this.env.model.dispatch("UPDATE_CAROUSEL", {
51491
+ figureId: this.props.figureId,
51492
+ sheetId: this.env.model.getters.getActiveSheetId(),
51493
+ definition: { items },
51494
+ });
51495
+ }
51496
+ getItemTitle(item) {
51497
+ return getCarouselItemTitle(this.env.model.getters, item);
51498
+ }
51499
+ getItemPreview(item) {
51500
+ return getCarouselItemPreview(this.env.model.getters, item);
51501
+ }
51502
+ get carouselAddChartInfoMessage() {
51503
+ return _t("Add a chart to the carousel. You can also add a chart by dragging and dropping it over the carousel figure.");
51504
+ }
51505
+ }
51506
+
51040
51507
  class ChartDataSeries extends owl.Component {
51041
51508
  static template = "o-spreadsheet.ChartDataSeries";
51042
51509
  static components = { SelectionInput, Section };
@@ -51103,7 +51570,7 @@ class GenericChartConfigPanel extends owl.Component {
51103
51570
  ChartErrorSection,
51104
51571
  };
51105
51572
  static props = {
51106
- figureId: String,
51573
+ chartId: String,
51107
51574
  definition: Object,
51108
51575
  updateChart: Function,
51109
51576
  canUpdateChart: Function,
@@ -51161,7 +51628,7 @@ class GenericChartConfigPanel extends owl.Component {
51161
51628
  ];
51162
51629
  }
51163
51630
  onUpdateDataSetsHaveTitle(dataSetsHaveTitle) {
51164
- this.props.updateChart(this.props.figureId, {
51631
+ this.props.updateChart(this.props.chartId, {
51165
51632
  dataSetsHaveTitle,
51166
51633
  });
51167
51634
  }
@@ -51233,7 +51700,7 @@ class GenericChartConfigPanel extends owl.Component {
51233
51700
  return;
51234
51701
  }
51235
51702
  const labelRange = dataSets.length > 1 ? dataSets.shift().dataRange : "";
51236
- this.props.updateChart(this.props.figureId, {
51703
+ this.props.updateChart(this.props.chartId, {
51237
51704
  labelRange,
51238
51705
  dataSets,
51239
51706
  });
@@ -51250,7 +51717,7 @@ class GenericChartConfigPanel extends owl.Component {
51250
51717
  ...this.dataSets?.[i],
51251
51718
  dataRange,
51252
51719
  }));
51253
- this.state.datasetDispatchResult = this.props.canUpdateChart(this.props.figureId, {
51720
+ this.state.datasetDispatchResult = this.props.canUpdateChart(this.props.chartId, {
51254
51721
  dataSets: this.dataSets,
51255
51722
  });
51256
51723
  }
@@ -51262,7 +51729,7 @@ class GenericChartConfigPanel extends owl.Component {
51262
51729
  backgroundColor: colors[i],
51263
51730
  ...this.dataSets[i],
51264
51731
  }));
51265
- this.state.datasetDispatchResult = this.props.updateChart(this.props.figureId, {
51732
+ this.state.datasetDispatchResult = this.props.updateChart(this.props.chartId, {
51266
51733
  dataSets: this.dataSets,
51267
51734
  });
51268
51735
  }
@@ -51275,18 +51742,18 @@ class GenericChartConfigPanel extends owl.Component {
51275
51742
  ...ds,
51276
51743
  }))
51277
51744
  .filter((_, i) => i !== index);
51278
- this.state.datasetDispatchResult = this.props.updateChart(this.props.figureId, {
51745
+ this.state.datasetDispatchResult = this.props.updateChart(this.props.chartId, {
51279
51746
  dataSets: this.dataSets,
51280
51747
  });
51281
51748
  }
51282
51749
  onDataSeriesConfirmed() {
51283
51750
  this.dataSets = this.splitRanges;
51284
51751
  this.datasetOrientation = this.computeDatasetOrientation();
51285
- this.state.datasetDispatchResult = this.props.updateChart(this.props.figureId, {
51752
+ this.state.datasetDispatchResult = this.props.updateChart(this.props.chartId, {
51286
51753
  dataSets: this.dataSets,
51287
51754
  });
51288
51755
  if (this.state.datasetDispatchResult.isSuccessful) {
51289
- this.dataSets = this.env.model.getters.getChartDefinition(this.props.figureId).dataSets;
51756
+ this.dataSets = this.env.model.getters.getChartDefinition(this.props.chartId).dataSets;
51290
51757
  }
51291
51758
  }
51292
51759
  get splitRanges() {
@@ -51377,12 +51844,12 @@ class GenericChartConfigPanel extends owl.Component {
51377
51844
  */
51378
51845
  onLabelRangeChanged(ranges) {
51379
51846
  this.labelRange = ranges[0];
51380
- this.state.labelsDispatchResult = this.props.canUpdateChart(this.props.figureId, {
51847
+ this.state.labelsDispatchResult = this.props.canUpdateChart(this.props.chartId, {
51381
51848
  labelRange: this.labelRange,
51382
51849
  });
51383
51850
  }
51384
51851
  onLabelRangeConfirmed() {
51385
- this.state.labelsDispatchResult = this.props.updateChart(this.props.figureId, {
51852
+ this.state.labelsDispatchResult = this.props.updateChart(this.props.chartId, {
51386
51853
  labelRange: this.labelRange,
51387
51854
  });
51388
51855
  }
@@ -51390,7 +51857,7 @@ class GenericChartConfigPanel extends owl.Component {
51390
51857
  return this.labelRange || "";
51391
51858
  }
51392
51859
  onUpdateAggregated(aggregated) {
51393
- this.props.updateChart(this.props.figureId, {
51860
+ this.props.updateChart(this.props.chartId, {
51394
51861
  aggregated,
51395
51862
  });
51396
51863
  }
@@ -51422,7 +51889,8 @@ class GenericChartConfigPanel extends owl.Component {
51422
51889
  }
51423
51890
  const zonesBySheetName = {};
51424
51891
  const transposedDatasets = [];
51425
- const figureSheetId = getters.getFigureSheetId(this.props.figureId);
51892
+ const figureId = getters.getFigureIdFromChartId(this.props.chartId);
51893
+ const figureSheetId = getters.getFigureSheetId(figureId);
51426
51894
  let name = getters.getActiveSheet().name;
51427
51895
  if (figureSheetId) {
51428
51896
  name = getters.getSheet(figureSheetId).name;
@@ -51482,7 +51950,7 @@ class BarConfigPanel extends GenericChartConfigPanel {
51482
51950
  : this.chartTerms.StackedColumnChart;
51483
51951
  }
51484
51952
  onUpdateStacked(stacked) {
51485
- this.props.updateChart(this.props.figureId, {
51953
+ this.props.updateChart(this.props.chartId, {
51486
51954
  stacked,
51487
51955
  });
51488
51956
  }
@@ -51976,7 +52444,7 @@ class ChartTitle extends owl.Component {
51976
52444
  class AxisDesignEditor extends owl.Component {
51977
52445
  static template = "o-spreadsheet-AxisDesignEditor";
51978
52446
  static components = { Section, ChartTitle, BadgeSelection };
51979
- static props = { figureId: String, definition: Object, updateChart: Function, axesList: Array };
52447
+ static props = { chartId: String, definition: Object, updateChart: Function, axesList: Array };
51980
52448
  state = owl.useState({ currentAxis: "x" });
51981
52449
  defaultFontSize = CHART_AXIS_TITLE_FONT_SIZE;
51982
52450
  get axisTitleStyle() {
@@ -52001,7 +52469,7 @@ class AxisDesignEditor extends owl.Component {
52001
52469
  text,
52002
52470
  },
52003
52471
  };
52004
- this.props.updateChart(this.props.figureId, { axesDesign });
52472
+ this.props.updateChart(this.props.chartId, { axesDesign });
52005
52473
  }
52006
52474
  updateAxisTitleStyle(style) {
52007
52475
  const axesDesign = deepCopy(this.props.definition.axesDesign) ?? {};
@@ -52009,7 +52477,7 @@ class AxisDesignEditor extends owl.Component {
52009
52477
  ...axesDesign[this.state.currentAxis],
52010
52478
  title: style,
52011
52479
  };
52012
- this.props.updateChart(this.props.figureId, { axesDesign });
52480
+ this.props.updateChart(this.props.chartId, { axesDesign });
52013
52481
  }
52014
52482
  }
52015
52483
 
@@ -52062,7 +52530,7 @@ class GeneralDesignEditor extends owl.Component {
52062
52530
  RadioSelection,
52063
52531
  };
52064
52532
  static props = {
52065
- figureId: String,
52533
+ chartId: String,
52066
52534
  definition: Object,
52067
52535
  updateChart: Function,
52068
52536
  canUpdateChart: Function,
@@ -52086,17 +52554,17 @@ class GeneralDesignEditor extends owl.Component {
52086
52554
  this.state.activeTool = isOpen ? "" : tool;
52087
52555
  }
52088
52556
  updateBackgroundColor(color) {
52089
- this.props.updateChart(this.props.figureId, {
52557
+ this.props.updateChart(this.props.chartId, {
52090
52558
  background: color,
52091
52559
  });
52092
52560
  }
52093
52561
  updateTitle(newTitle) {
52094
52562
  const title = { ...this.title, text: newTitle };
52095
- this.props.updateChart(this.props.figureId, { title });
52563
+ this.props.updateChart(this.props.chartId, { title });
52096
52564
  }
52097
52565
  updateChartTitleStyle(style) {
52098
52566
  const title = { ...this.title, ...style };
52099
- this.props.updateChart(this.props.figureId, { title });
52567
+ this.props.updateChart(this.props.chartId, { title });
52100
52568
  this.state.activeTool = "";
52101
52569
  }
52102
52570
  }
@@ -52107,13 +52575,13 @@ class ChartLegend extends owl.Component {
52107
52575
  Section,
52108
52576
  };
52109
52577
  static props = {
52110
- figureId: String,
52578
+ chartId: String,
52111
52579
  definition: Object,
52112
52580
  updateChart: Function,
52113
52581
  canUpdateChart: Function,
52114
52582
  };
52115
52583
  updateLegendPosition(ev) {
52116
- this.props.updateChart(this.props.figureId, {
52584
+ this.props.updateChart(this.props.chartId, {
52117
52585
  legendPosition: ev.target.value,
52118
52586
  });
52119
52587
  }
@@ -52127,7 +52595,7 @@ class SeriesDesignEditor extends owl.Component {
52127
52595
  RoundColorPicker,
52128
52596
  };
52129
52597
  static props = {
52130
- figureId: String,
52598
+ chartId: String,
52131
52599
  definition: Object,
52132
52600
  updateChart: Function,
52133
52601
  canUpdateChart: Function,
@@ -52135,7 +52603,7 @@ class SeriesDesignEditor extends owl.Component {
52135
52603
  };
52136
52604
  state = owl.useState({ index: 0 });
52137
52605
  getDataSeries() {
52138
- const runtime = this.env.model.getters.getChartRuntime(this.props.figureId);
52606
+ const runtime = this.env.model.getters.getChartRuntime(this.props.chartId);
52139
52607
  if (!runtime || !("chartJsConfig" in runtime)) {
52140
52608
  return [];
52141
52609
  }
@@ -52154,7 +52622,7 @@ class SeriesDesignEditor extends owl.Component {
52154
52622
  ...dataSets[this.state.index],
52155
52623
  backgroundColor: color,
52156
52624
  };
52157
- this.props.updateChart(this.props.figureId, { dataSets });
52625
+ this.props.updateChart(this.props.chartId, { dataSets });
52158
52626
  }
52159
52627
  getDataSeriesColor() {
52160
52628
  const dataSets = this.props.definition.dataSets;
@@ -52174,7 +52642,7 @@ class SeriesDesignEditor extends owl.Component {
52174
52642
  ...dataSets[this.state.index],
52175
52643
  label,
52176
52644
  };
52177
- this.props.updateChart(this.props.figureId, { dataSets });
52645
+ this.props.updateChart(this.props.chartId, { dataSets });
52178
52646
  }
52179
52647
  getDataSeriesLabel() {
52180
52648
  const dataSets = this.props.definition.dataSets;
@@ -52192,7 +52660,7 @@ class SeriesWithAxisDesignEditor extends owl.Component {
52192
52660
  RoundColorPicker,
52193
52661
  };
52194
52662
  static props = {
52195
- figureId: String,
52663
+ chartId: String,
52196
52664
  definition: Object,
52197
52665
  canUpdateChart: Function,
52198
52666
  updateChart: Function,
@@ -52208,7 +52676,7 @@ class SeriesWithAxisDesignEditor extends owl.Component {
52208
52676
  ...dataSets[index],
52209
52677
  yAxisId: axis === "left" ? "y" : "y1",
52210
52678
  };
52211
- this.props.updateChart(this.props.figureId, { dataSets });
52679
+ this.props.updateChart(this.props.chartId, { dataSets });
52212
52680
  }
52213
52681
  getDataSerieAxis(index) {
52214
52682
  const dataSets = this.props.definition.dataSets;
@@ -52234,7 +52702,7 @@ class SeriesWithAxisDesignEditor extends owl.Component {
52234
52702
  display,
52235
52703
  },
52236
52704
  };
52237
- this.props.updateChart(this.props.figureId, { dataSets });
52705
+ this.props.updateChart(this.props.chartId, { dataSets });
52238
52706
  }
52239
52707
  getTrendLineConfiguration(index) {
52240
52708
  const dataSets = this.props.definition.dataSets;
@@ -52275,7 +52743,7 @@ class SeriesWithAxisDesignEditor extends owl.Component {
52275
52743
  this.updateTrendLineValue(index, { order: parseInt(element.value) });
52276
52744
  }
52277
52745
  getMaxPolynomialDegree(index) {
52278
- const runtime = this.env.model.getters.getChartRuntime(this.props.figureId);
52746
+ const runtime = this.env.model.getters.getChartRuntime(this.props.chartId);
52279
52747
  return Math.min(10, runtime.chartJsConfig.data.datasets[index].data.length - 1);
52280
52748
  }
52281
52749
  get defaultWindowSize() {
@@ -52317,7 +52785,7 @@ class SeriesWithAxisDesignEditor extends owl.Component {
52317
52785
  ...config,
52318
52786
  },
52319
52787
  };
52320
- this.props.updateChart(this.props.figureId, { dataSets });
52788
+ this.props.updateChart(this.props.chartId, { dataSets });
52321
52789
  }
52322
52790
  }
52323
52791
 
@@ -52327,7 +52795,7 @@ class ChartShowValues extends owl.Component {
52327
52795
  Checkbox,
52328
52796
  };
52329
52797
  static props = {
52330
- figureId: String,
52798
+ chartId: String,
52331
52799
  definition: Object,
52332
52800
  updateChart: Function,
52333
52801
  canUpdateChart: Function,
@@ -52347,7 +52815,7 @@ class ChartWithAxisDesignPanel extends owl.Component {
52347
52815
  ChartShowValues,
52348
52816
  };
52349
52817
  static props = {
52350
- figureId: String,
52818
+ chartId: String,
52351
52819
  definition: Object,
52352
52820
  canUpdateChart: Function,
52353
52821
  updateChart: Function,
@@ -52371,7 +52839,7 @@ class ChartShowDataMarkers extends owl.Component {
52371
52839
  Checkbox,
52372
52840
  };
52373
52841
  static props = {
52374
- figureId: String,
52842
+ chartId: String,
52375
52843
  definition: Object,
52376
52844
  updateChart: Function,
52377
52845
  canUpdateChart: Function,
@@ -52398,7 +52866,7 @@ class ComboChartDesignPanel extends ChartWithAxisDesignPanel {
52398
52866
  ...dataSets[index],
52399
52867
  type,
52400
52868
  };
52401
- this.props.updateChart(this.props.figureId, { dataSets });
52869
+ this.props.updateChart(this.props.chartId, { dataSets });
52402
52870
  }
52403
52871
  getDataSeriesType(index) {
52404
52872
  const dataSets = this.props.definition.dataSets;
@@ -52434,7 +52902,7 @@ class FunnelChartConfigPanel extends GenericChartConfigPanel {
52434
52902
  ];
52435
52903
  }
52436
52904
  onUpdateCumulative(cumulative) {
52437
- this.props.updateChart(this.props.figureId, {
52905
+ this.props.updateChart(this.props.chartId, {
52438
52906
  cumulative,
52439
52907
  });
52440
52908
  }
@@ -52450,13 +52918,13 @@ class FunnelChartDesignPanel extends owl.Component {
52450
52918
  Section,
52451
52919
  };
52452
52920
  static props = {
52453
- figureId: String,
52921
+ chartId: String,
52454
52922
  definition: Object,
52455
52923
  updateChart: Function,
52456
52924
  canUpdateChart: Function,
52457
52925
  };
52458
52926
  getFunnelColorItems() {
52459
- const runtime = this.env.model.getters.getChartRuntime(this.props.figureId);
52927
+ const runtime = this.env.model.getters.getChartRuntime(this.props.chartId);
52460
52928
  const labels = (runtime.chartJsConfig.data.labels || []);
52461
52929
  const colors = getFunnelLabelColors(labels, this.props.definition.funnelColors);
52462
52930
  return labels.map((label, index) => ({
@@ -52466,7 +52934,7 @@ class FunnelChartDesignPanel extends owl.Component {
52466
52934
  }
52467
52935
  updateFunnelItemColor(index, color) {
52468
52936
  const funnelColors = replaceItemAtIndex(this.props.definition.funnelColors || [], color, index);
52469
- this.props.updateChart(this.props.figureId, { funnelColors });
52937
+ this.props.updateChart(this.props.chartId, { funnelColors });
52470
52938
  }
52471
52939
  }
52472
52940
 
@@ -52474,7 +52942,7 @@ class GaugeChartConfigPanel extends owl.Component {
52474
52942
  static template = "o-spreadsheet-GaugeChartConfigPanel";
52475
52943
  static components = { ChartErrorSection, ChartDataSeries };
52476
52944
  static props = {
52477
- figureId: String,
52945
+ chartId: String,
52478
52946
  definition: Object,
52479
52947
  updateChart: Function,
52480
52948
  canUpdateChart: Function,
@@ -52492,12 +52960,12 @@ class GaugeChartConfigPanel extends owl.Component {
52492
52960
  }
52493
52961
  onDataRangeChanged(ranges) {
52494
52962
  this.dataRange = ranges[0];
52495
- this.state.dataRangeDispatchResult = this.props.canUpdateChart(this.props.figureId, {
52963
+ this.state.dataRangeDispatchResult = this.props.canUpdateChart(this.props.chartId, {
52496
52964
  dataRange: this.dataRange,
52497
52965
  });
52498
52966
  }
52499
52967
  updateDataRange() {
52500
- this.state.dataRangeDispatchResult = this.props.updateChart(this.props.figureId, {
52968
+ this.state.dataRangeDispatchResult = this.props.updateChart(this.props.chartId, {
52501
52969
  dataRange: this.dataRange,
52502
52970
  });
52503
52971
  }
@@ -52556,7 +53024,7 @@ class GaugeChartDesignPanel extends owl.Component {
52556
53024
  StandaloneComposer,
52557
53025
  };
52558
53026
  static props = {
52559
- figureId: String,
53027
+ chartId: String,
52560
53028
  definition: Object,
52561
53029
  updateChart: Function,
52562
53030
  canUpdateChart: { type: Function, optional: true },
@@ -52597,7 +53065,7 @@ class GaugeChartDesignPanel extends owl.Component {
52597
53065
  updateSectionRule(sectionRule) {
52598
53066
  this.state.sectionRuleCancelledReasons = [];
52599
53067
  this.state.sectionRuleCancelledReasons.push(...this.checkSectionRuleFormulasAreValid(this.state.sectionRule));
52600
- const dispatchResult = this.props.updateChart(this.props.figureId, {
53068
+ const dispatchResult = this.props.updateChart(this.props.chartId, {
52601
53069
  sectionRule,
52602
53070
  });
52603
53071
  if (dispatchResult.isSuccessful) {
@@ -52660,9 +53128,9 @@ class GaugeChartDesignPanel extends owl.Component {
52660
53128
  return tryToNumber(toScalar(evaluatedValue), locale) !== undefined;
52661
53129
  }
52662
53130
  get sheetId() {
52663
- const chart = this.env.model.getters.getChart(this.props.figureId);
53131
+ const chart = this.env.model.getters.getChart(this.props.chartId);
52664
53132
  if (!chart) {
52665
- throw new Error("Chart not found with id " + this.props.figureId);
53133
+ throw new Error("Chart not found with id " + this.props.chartId);
52666
53134
  }
52667
53135
  return chart.sheetId;
52668
53136
  }
@@ -52672,13 +53140,13 @@ class GeoChartRegionSelectSection extends owl.Component {
52672
53140
  static template = "o-spreadsheet-GeoChartRegionSelectSection";
52673
53141
  static components = { Section };
52674
53142
  static props = {
52675
- figureId: String,
53143
+ chartId: String,
52676
53144
  definition: Object,
52677
53145
  updateChart: Function,
52678
53146
  };
52679
53147
  updateSelectedRegion(ev) {
52680
53148
  const value = ev.target.value;
52681
- this.props.updateChart(this.props.figureId, { region: value });
53149
+ this.props.updateChart(this.props.chartId, { region: value });
52682
53150
  }
52683
53151
  get availableRegions() {
52684
53152
  return this.env.model.getters.getGeoChartAvailableRegions();
@@ -52728,14 +53196,14 @@ class GeoChartDesignPanel extends ChartWithAxisDesignPanel {
52728
53196
  : this.updateColorScale(value);
52729
53197
  }
52730
53198
  updateColorScale(colorScale) {
52731
- this.props.updateChart(this.props.figureId, { colorScale });
53199
+ this.props.updateChart(this.props.chartId, { colorScale });
52732
53200
  }
52733
53201
  updateMissingValueColor(color) {
52734
- this.props.updateChart(this.props.figureId, { missingValueColor: color });
53202
+ this.props.updateChart(this.props.chartId, { missingValueColor: color });
52735
53203
  }
52736
53204
  updateLegendPosition(ev) {
52737
53205
  const value = ev.target.value;
52738
- this.props.updateChart(this.props.figureId, { legendPosition: value });
53206
+ this.props.updateChart(this.props.chartId, { legendPosition: value });
52739
53207
  }
52740
53208
  get selectedColorScale() {
52741
53209
  return typeof this.props.definition.colorScale === "object"
@@ -52784,7 +53252,7 @@ class HierarchicalChartConfigPanel extends GenericChartConfigPanel {
52784
53252
  class LineConfigPanel extends GenericChartConfigPanel {
52785
53253
  static template = "o-spreadsheet-LineConfigPanel";
52786
53254
  get canTreatLabelsAsText() {
52787
- const chart = this.env.model.getters.getChart(this.props.figureId);
53255
+ const chart = this.env.model.getters.getChart(this.props.chartId);
52788
53256
  if (chart && chart instanceof LineChart) {
52789
53257
  return canChartParseLabels(chart.getDefinition(), chart.dataSets, chart.labelRange, this.env.model.getters);
52790
53258
  }
@@ -52809,17 +53277,17 @@ class LineConfigPanel extends GenericChartConfigPanel {
52809
53277
  return options;
52810
53278
  }
52811
53279
  onUpdateLabelsAsText(labelsAsText) {
52812
- this.props.updateChart(this.props.figureId, {
53280
+ this.props.updateChart(this.props.chartId, {
52813
53281
  labelsAsText,
52814
53282
  });
52815
53283
  }
52816
53284
  onUpdateStacked(stacked) {
52817
- this.props.updateChart(this.props.figureId, {
53285
+ this.props.updateChart(this.props.chartId, {
52818
53286
  stacked,
52819
53287
  });
52820
53288
  }
52821
53289
  onUpdateCumulative(cumulative) {
52822
- this.props.updateChart(this.props.figureId, {
53290
+ this.props.updateChart(this.props.chartId, {
52823
53291
  cumulative,
52824
53292
  });
52825
53293
  }
@@ -52856,13 +53324,13 @@ class PieChartDesignPanel extends owl.Component {
52856
53324
  PieHoleSize,
52857
53325
  };
52858
53326
  static props = {
52859
- figureId: String,
53327
+ chartId: String,
52860
53328
  definition: Object,
52861
53329
  updateChart: Function,
52862
53330
  canUpdateChart: { type: Function, optional: true },
52863
53331
  };
52864
53332
  onPieHoleSizeChange(pieHolePercentage) {
52865
- this.props.updateChart(this.props.figureId, {
53333
+ this.props.updateChart(this.props.chartId, {
52866
53334
  ...this.props.definition,
52867
53335
  pieHolePercentage,
52868
53336
  });
@@ -52883,7 +53351,7 @@ class RadarChartDesignPanel extends owl.Component {
52883
53351
  ChartShowDataMarkers,
52884
53352
  };
52885
53353
  static props = {
52886
- figureId: String,
53354
+ chartId: String,
52887
53355
  definition: Object,
52888
53356
  canUpdateChart: Function,
52889
53357
  updateChart: Function,
@@ -52893,14 +53361,14 @@ class RadarChartDesignPanel extends owl.Component {
52893
53361
  class ScatterConfigPanel extends GenericChartConfigPanel {
52894
53362
  static template = "o-spreadsheet-ScatterConfigPanel";
52895
53363
  get canTreatLabelsAsText() {
52896
- const chart = this.env.model.getters.getChart(this.props.figureId);
53364
+ const chart = this.env.model.getters.getChart(this.props.chartId);
52897
53365
  if (chart && chart instanceof ScatterChart) {
52898
53366
  return canChartParseLabels(chart.getDefinition(), chart.dataSets, chart.labelRange, this.env.model.getters);
52899
53367
  }
52900
53368
  return false;
52901
53369
  }
52902
53370
  onUpdateLabelsAsText(labelsAsText) {
52903
- this.props.updateChart(this.props.figureId, {
53371
+ this.props.updateChart(this.props.chartId, {
52904
53372
  labelsAsText,
52905
53373
  });
52906
53374
  }
@@ -52922,7 +53390,7 @@ class ScorecardChartConfigPanel extends owl.Component {
52922
53390
  static template = "o-spreadsheet-ScorecardChartConfigPanel";
52923
53391
  static components = { SelectionInput, ChartErrorSection, Section };
52924
53392
  static props = {
52925
- figureId: String,
53393
+ chartId: String,
52926
53394
  definition: Object,
52927
53395
  updateChart: Function,
52928
53396
  canUpdateChart: Function,
@@ -52948,12 +53416,12 @@ class ScorecardChartConfigPanel extends owl.Component {
52948
53416
  }
52949
53417
  onKeyValueRangeChanged(ranges) {
52950
53418
  this.keyValue = ranges[0];
52951
- this.state.keyValueDispatchResult = this.props.canUpdateChart(this.props.figureId, {
53419
+ this.state.keyValueDispatchResult = this.props.canUpdateChart(this.props.chartId, {
52952
53420
  keyValue: this.keyValue,
52953
53421
  });
52954
53422
  }
52955
53423
  updateKeyValueRange() {
52956
- this.state.keyValueDispatchResult = this.props.updateChart(this.props.figureId, {
53424
+ this.state.keyValueDispatchResult = this.props.updateChart(this.props.chartId, {
52957
53425
  keyValue: this.keyValue,
52958
53426
  });
52959
53427
  }
@@ -52962,12 +53430,12 @@ class ScorecardChartConfigPanel extends owl.Component {
52962
53430
  }
52963
53431
  onBaselineRangeChanged(ranges) {
52964
53432
  this.baseline = ranges[0];
52965
- this.state.baselineDispatchResult = this.props.canUpdateChart(this.props.figureId, {
53433
+ this.state.baselineDispatchResult = this.props.canUpdateChart(this.props.chartId, {
52966
53434
  baseline: this.baseline,
52967
53435
  });
52968
53436
  }
52969
53437
  updateBaselineRange() {
52970
- this.state.baselineDispatchResult = this.props.updateChart(this.props.figureId, {
53438
+ this.state.baselineDispatchResult = this.props.updateChart(this.props.chartId, {
52971
53439
  baseline: this.baseline,
52972
53440
  });
52973
53441
  }
@@ -52975,7 +53443,7 @@ class ScorecardChartConfigPanel extends owl.Component {
52975
53443
  return this.baseline || "";
52976
53444
  }
52977
53445
  updateBaselineMode(ev) {
52978
- this.props.updateChart(this.props.figureId, { baselineMode: ev.target.value });
53446
+ this.props.updateChart(this.props.chartId, { baselineMode: ev.target.value });
52979
53447
  }
52980
53448
  }
52981
53449
 
@@ -52990,7 +53458,7 @@ class ScorecardChartDesignPanel extends owl.Component {
52990
53458
  ChartTitle,
52991
53459
  };
52992
53460
  static props = {
52993
- figureId: String,
53461
+ chartId: String,
52994
53462
  definition: Object,
52995
53463
  updateChart: Function,
52996
53464
  canUpdateChart: { type: Function, optional: true },
@@ -53007,7 +53475,7 @@ class ScorecardChartDesignPanel extends owl.Component {
53007
53475
  return SCORECARD_CHART_TITLE_FONT_SIZE;
53008
53476
  }
53009
53477
  updateHumanizeNumbers(humanize) {
53010
- this.props.updateChart(this.props.figureId, { humanize });
53478
+ this.props.updateChart(this.props.chartId, { humanize });
53011
53479
  }
53012
53480
  translate(term) {
53013
53481
  return _t(term);
@@ -53015,13 +53483,13 @@ class ScorecardChartDesignPanel extends owl.Component {
53015
53483
  setColor(color, colorPickerId) {
53016
53484
  switch (colorPickerId) {
53017
53485
  case "backgroundColor":
53018
- this.props.updateChart(this.props.figureId, { background: color });
53486
+ this.props.updateChart(this.props.chartId, { background: color });
53019
53487
  break;
53020
53488
  case "baselineColorDown":
53021
- this.props.updateChart(this.props.figureId, { baselineColorDown: color });
53489
+ this.props.updateChart(this.props.chartId, { baselineColorDown: color });
53022
53490
  break;
53023
53491
  case "baselineColorUp":
53024
- this.props.updateChart(this.props.figureId, { baselineColorUp: color });
53492
+ this.props.updateChart(this.props.chartId, { baselineColorUp: color });
53025
53493
  break;
53026
53494
  }
53027
53495
  }
@@ -53040,22 +53508,22 @@ class ScorecardChartDesignPanel extends owl.Component {
53040
53508
  };
53041
53509
  }
53042
53510
  setKeyText(text) {
53043
- this.props.updateChart(this.props.figureId, {
53511
+ this.props.updateChart(this.props.chartId, {
53044
53512
  keyDescr: { ...this.props.definition.keyDescr, text },
53045
53513
  });
53046
53514
  }
53047
53515
  updateKeyStyle(style) {
53048
53516
  const keyDescr = { ...this.keyStyle, ...style };
53049
- this.props.updateChart(this.props.figureId, { keyDescr });
53517
+ this.props.updateChart(this.props.chartId, { keyDescr });
53050
53518
  }
53051
53519
  setBaselineText(text) {
53052
- this.props.updateChart(this.props.figureId, {
53520
+ this.props.updateChart(this.props.chartId, {
53053
53521
  baselineDescr: { ...this.props.definition.baselineDescr, text },
53054
53522
  });
53055
53523
  }
53056
53524
  updateBaselineStyle(style) {
53057
53525
  const baselineDescr = { ...this.baselineStyle, ...style };
53058
- this.props.updateChart(this.props.figureId, { baselineDescr });
53526
+ this.props.updateChart(this.props.chartId, { baselineDescr });
53059
53527
  }
53060
53528
  }
53061
53529
 
@@ -53073,7 +53541,7 @@ class SunburstChartDesignPanel extends owl.Component {
53073
53541
  PieHoleSize,
53074
53542
  };
53075
53543
  static props = {
53076
- figureId: String,
53544
+ chartId: String,
53077
53545
  definition: Object,
53078
53546
  updateChart: Function,
53079
53547
  canUpdateChart: { type: Function, optional: true },
@@ -53086,18 +53554,18 @@ class SunburstChartDesignPanel extends owl.Component {
53086
53554
  return this.props.definition.showLabels ?? SunburstChartDefaults.showLabels;
53087
53555
  }
53088
53556
  get groupColors() {
53089
- const figureId = this.props.figureId;
53090
- const runtime = this.env.model.getters.getChartRuntime(figureId);
53557
+ const chartId = this.props.chartId;
53558
+ const runtime = this.env.model.getters.getChartRuntime(chartId);
53091
53559
  const dataset = runtime.chartJsConfig.data.datasets[0];
53092
53560
  return dataset?.groupColors || [];
53093
53561
  }
53094
53562
  onGroupColorChanged(index, color) {
53095
53563
  const colors = deepCopy(this.props.definition.groupColors) ?? [];
53096
53564
  colors[index] = color;
53097
- this.props.updateChart(this.props.figureId, { groupColors: colors });
53565
+ this.props.updateChart(this.props.chartId, { groupColors: colors });
53098
53566
  }
53099
53567
  onPieHoleSizeChange(pieHolePercentage) {
53100
- this.props.updateChart(this.props.figureId, {
53568
+ this.props.updateChart(this.props.chartId, {
53101
53569
  ...this.props.definition,
53102
53570
  pieHolePercentage,
53103
53571
  });
@@ -53111,7 +53579,7 @@ class TreeMapCategoryColors extends owl.Component {
53111
53579
  RoundColorPicker,
53112
53580
  };
53113
53581
  static props = {
53114
- figureId: String,
53582
+ chartId: String,
53115
53583
  definition: Object,
53116
53584
  onColorChanged: Function,
53117
53585
  };
@@ -53123,7 +53591,7 @@ class TreeMapCategoryColors extends owl.Component {
53123
53591
  return coloringOptions;
53124
53592
  }
53125
53593
  getTreeGroupAndColors() {
53126
- const runtime = this.env.model.getters.getChartRuntime(this.props.figureId);
53594
+ const runtime = this.env.model.getters.getChartRuntime(this.props.chartId);
53127
53595
  const config = runtime.chartJsConfig;
53128
53596
  return config.data.datasets[0]?.groupColors || [];
53129
53597
  }
@@ -53144,7 +53612,7 @@ class TreeMapColorScale extends owl.Component {
53144
53612
  static template = "o-spreadsheet-TreeMapColorScale";
53145
53613
  static components = { RoundColorPicker };
53146
53614
  static props = {
53147
- figureId: String,
53615
+ chartId: String,
53148
53616
  definition: Object,
53149
53617
  onColorChanged: Function,
53150
53618
  };
@@ -53186,7 +53654,7 @@ class TreeMapChartDesignPanel extends owl.Component {
53186
53654
  TreeMapColorScale,
53187
53655
  };
53188
53656
  static props = {
53189
- figureId: String,
53657
+ chartId: String,
53190
53658
  definition: Object,
53191
53659
  updateChart: Function,
53192
53660
  canUpdateChart: { type: Function, optional: true },
@@ -53210,15 +53678,15 @@ class TreeMapChartDesignPanel extends owl.Component {
53210
53678
  }
53211
53679
  changeColoringOption(option) {
53212
53680
  const coloringOptions = option === "categoryColor" ? this.savedColors.categoryColors : this.savedColors.colorScale;
53213
- this.props.updateChart(this.props.figureId, { coloringOptions });
53681
+ this.props.updateChart(this.props.chartId, { coloringOptions });
53214
53682
  }
53215
53683
  onCategoryColorChange(coloringOptions) {
53216
53684
  this.savedColors.categoryColors = coloringOptions;
53217
- this.props.updateChart(this.props.figureId, { coloringOptions });
53685
+ this.props.updateChart(this.props.chartId, { coloringOptions });
53218
53686
  }
53219
53687
  onColorScaleChange(coloringOptions) {
53220
53688
  this.savedColors.colorScale = coloringOptions;
53221
- this.props.updateChart(this.props.figureId, { coloringOptions });
53689
+ this.props.updateChart(this.props.chartId, { coloringOptions });
53222
53690
  }
53223
53691
  get coloringOptionChoices() {
53224
53692
  return [
@@ -53242,23 +53710,23 @@ class WaterfallChartDesignPanel extends owl.Component {
53242
53710
  ChartLegend,
53243
53711
  };
53244
53712
  static props = {
53245
- figureId: String,
53713
+ chartId: String,
53246
53714
  definition: Object,
53247
53715
  updateChart: Function,
53248
53716
  canUpdateChart: { type: Function, optional: true },
53249
53717
  };
53250
53718
  axisChoices = CHART_AXIS_CHOICES;
53251
53719
  onUpdateShowSubTotals(showSubTotals) {
53252
- this.props.updateChart(this.props.figureId, { showSubTotals });
53720
+ this.props.updateChart(this.props.chartId, { showSubTotals });
53253
53721
  }
53254
53722
  onUpdateShowConnectorLines(showConnectorLines) {
53255
- this.props.updateChart(this.props.figureId, { showConnectorLines });
53723
+ this.props.updateChart(this.props.chartId, { showConnectorLines });
53256
53724
  }
53257
53725
  onUpdateFirstValueAsSubtotal(firstValueAsSubtotal) {
53258
- this.props.updateChart(this.props.figureId, { firstValueAsSubtotal });
53726
+ this.props.updateChart(this.props.chartId, { firstValueAsSubtotal });
53259
53727
  }
53260
53728
  updateColor(colorName, color) {
53261
- this.props.updateChart(this.props.figureId, { [colorName]: color });
53729
+ this.props.updateChart(this.props.chartId, { [colorName]: color });
53262
53730
  }
53263
53731
  get axesList() {
53264
53732
  return [
@@ -53279,7 +53747,7 @@ class WaterfallChartDesignPanel extends owl.Component {
53279
53747
  CHART_WATERFALL_SUBTOTAL_COLOR);
53280
53748
  }
53281
53749
  updateVerticalAxisPosition(value) {
53282
- this.props.updateChart(this.props.figureId, {
53750
+ this.props.updateChart(this.props.chartId, {
53283
53751
  verticalAxisPosition: value,
53284
53752
  });
53285
53753
  }
@@ -53381,7 +53849,7 @@ css /* scss */ `
53381
53849
  class ChartTypePicker extends owl.Component {
53382
53850
  static template = "o-spreadsheet-ChartTypePicker";
53383
53851
  static components = { Section, Popover };
53384
- static props = { figureId: String, chartPanelStore: Object };
53852
+ static props = { chartId: String, chartPanelStore: Object };
53385
53853
  categories = chartCategories;
53386
53854
  chartTypeByCategories = {};
53387
53855
  popoverRef = owl.useRef("popoverRef");
@@ -53406,14 +53874,14 @@ class ChartTypePicker extends owl.Component {
53406
53874
  this.closePopover();
53407
53875
  }
53408
53876
  onTypeChange(type) {
53409
- this.props.chartPanelStore.changeChartType(this.props.figureId, type);
53877
+ this.props.chartPanelStore.changeChartType(this.props.chartId, type);
53410
53878
  this.closePopover();
53411
53879
  }
53412
- getChartDefinition(figureId) {
53413
- return this.env.model.getters.getChartDefinition(figureId);
53880
+ getChartDefinition(chartId) {
53881
+ return this.env.model.getters.getChartDefinition(chartId);
53414
53882
  }
53415
53883
  getSelectedChartSubtypeProperties() {
53416
- const definition = this.getChartDefinition(this.props.figureId);
53884
+ const definition = this.getChartDefinition(this.props.chartId);
53417
53885
  const matchedChart = chartSubtypeRegistry
53418
53886
  .getAll()
53419
53887
  .find((c) => c.matcher?.(definition) || false);
@@ -53445,34 +53913,36 @@ class MainChartPanelStore extends SpreadsheetStore {
53445
53913
  activatePanel(panel) {
53446
53914
  this.panel = panel;
53447
53915
  }
53448
- changeChartType(figureId, newDisplayType) {
53449
- const currentCreationContext = this.getters.getContextCreationChart(figureId);
53450
- const savedCreationContext = this.creationContexts[figureId] || {};
53916
+ changeChartType(chartId, newDisplayType) {
53917
+ const currentCreationContext = this.getters.getContextCreationChart(chartId);
53918
+ const savedCreationContext = this.creationContexts[chartId] || {};
53451
53919
  let newRanges = currentCreationContext?.range;
53452
53920
  if (newRanges?.every((range, i) => deepEquals(range, savedCreationContext.range?.[i]))) {
53453
53921
  newRanges = Object.assign([], savedCreationContext.range, currentCreationContext?.range);
53454
53922
  }
53455
- this.creationContexts[figureId] = {
53923
+ this.creationContexts[chartId] = {
53456
53924
  ...savedCreationContext,
53457
53925
  ...currentCreationContext,
53458
53926
  range: newRanges,
53459
53927
  };
53928
+ const figureId = this.getters.getFigureIdFromChartId(chartId);
53460
53929
  const sheetId = this.getters.getFigureSheetId(figureId);
53461
53930
  if (!sheetId) {
53462
53931
  return;
53463
53932
  }
53464
- const definition = this.getChartDefinitionFromContextCreation(figureId, newDisplayType);
53933
+ const definition = this.getChartDefinitionFromContextCreation(chartId, newDisplayType);
53465
53934
  this.model.dispatch("UPDATE_CHART", {
53466
53935
  definition,
53936
+ chartId,
53467
53937
  figureId,
53468
53938
  sheetId,
53469
53939
  });
53470
53940
  }
53471
- getChartDefinitionFromContextCreation(figureId, newDisplayType) {
53941
+ getChartDefinitionFromContextCreation(chartId, newDisplayType) {
53472
53942
  const newChartInfo = chartSubtypeRegistry.get(newDisplayType);
53473
53943
  const ChartClass = chartRegistry.get(newChartInfo.chartType);
53474
53944
  return {
53475
- ...ChartClass.getChartDefinitionFromContextCreation(this.creationContexts[figureId]),
53945
+ ...ChartClass.getChartDefinitionFromContextCreation(this.creationContexts[chartId]),
53476
53946
  ...newChartInfo.subtypeDefinition,
53477
53947
  };
53478
53948
  }
@@ -53513,15 +53983,15 @@ css /* scss */ `
53513
53983
  class ChartPanel extends owl.Component {
53514
53984
  static template = "o-spreadsheet-ChartPanel";
53515
53985
  static components = { Section, ChartTypePicker };
53516
- static props = { onCloseSidePanel: Function, figureId: String };
53986
+ static props = { onCloseSidePanel: Function, chartId: String };
53517
53987
  panelContentRef;
53518
53988
  scrollPositions = {
53519
53989
  configuration: 0,
53520
53990
  design: 0,
53521
53991
  };
53522
53992
  store;
53523
- get figureId() {
53524
- return this.props.figureId;
53993
+ get chartId() {
53994
+ return this.props.chartId;
53525
53995
  }
53526
53996
  setup() {
53527
53997
  this.store = useLocalStore(MainChartPanelStore);
@@ -53541,45 +54011,49 @@ class ChartPanel extends owl.Component {
53541
54011
  }
53542
54012
  this.store.activatePanel(panel);
53543
54013
  }
53544
- updateChart(figureId, updateDefinition) {
53545
- if (figureId !== this.figureId) {
54014
+ updateChart(chartId, updateDefinition) {
54015
+ const figureId = this.env.model.getters.getFigureIdFromChartId(chartId);
54016
+ if (chartId !== this.chartId) {
53546
54017
  return;
53547
54018
  }
53548
54019
  const definition = {
53549
- ...this.getChartDefinition(this.figureId),
54020
+ ...this.getChartDefinition(this.chartId),
53550
54021
  ...updateDefinition,
53551
54022
  };
53552
54023
  return this.env.model.dispatch("UPDATE_CHART", {
53553
54024
  definition,
54025
+ chartId,
53554
54026
  figureId,
53555
54027
  sheetId: this.env.model.getters.getFigureSheetId(figureId),
53556
54028
  });
53557
54029
  }
53558
- canUpdateChart(figureId, updateDefinition) {
53559
- if (figureId !== this.figureId || !this.env.model.getters.isChartDefined(figureId)) {
54030
+ canUpdateChart(chartId, updateDefinition) {
54031
+ const figureId = this.env.model.getters.getFigureIdFromChartId(chartId);
54032
+ if (chartId !== this.chartId || !this.env.model.getters.isChartDefined(chartId)) {
53560
54033
  return;
53561
54034
  }
53562
54035
  const definition = {
53563
- ...this.getChartDefinition(this.figureId),
54036
+ ...this.getChartDefinition(this.chartId),
53564
54037
  ...updateDefinition,
53565
54038
  };
53566
54039
  return this.env.model.canDispatch("UPDATE_CHART", {
53567
54040
  definition,
54041
+ chartId,
53568
54042
  figureId,
53569
54043
  sheetId: this.env.model.getters.getFigureSheetId(figureId),
53570
54044
  });
53571
54045
  }
53572
54046
  onTypeChange(type) {
53573
- if (!this.figureId) {
54047
+ if (!this.chartId) {
53574
54048
  return;
53575
54049
  }
53576
- this.store.changeChartType(this.figureId, type);
54050
+ this.store.changeChartType(this.chartId, type);
53577
54051
  }
53578
54052
  get chartPanel() {
53579
- if (!this.figureId) {
54053
+ if (!this.chartId) {
53580
54054
  throw new Error("Chart not defined.");
53581
54055
  }
53582
- const type = this.env.model.getters.getChartType(this.figureId);
54056
+ const type = this.env.model.getters.getChartType(this.chartId);
53583
54057
  if (!type) {
53584
54058
  throw new Error("Chart not defined.");
53585
54059
  }
@@ -53589,8 +54063,8 @@ class ChartPanel extends owl.Component {
53589
54063
  }
53590
54064
  return chartPanel;
53591
54065
  }
53592
- getChartDefinition(figureId) {
53593
- return this.env.model.getters.getChartDefinition(figureId);
54066
+ getChartDefinition(chartId) {
54067
+ return this.env.model.getters.getChartDefinition(chartId);
53594
54068
  }
53595
54069
  }
53596
54070
 
@@ -55592,103 +56066,6 @@ class PivotDeferUpdate extends owl.Component {
55592
56066
  }
55593
56067
  }
55594
56068
 
55595
- function useAutofocus({ refName }) {
55596
- const ref = owl.useRef(refName);
55597
- owl.useEffect((el) => {
55598
- el?.focus();
55599
- }, () => [ref.el]);
55600
- }
55601
-
55602
- css /* scss */ `
55603
- .o-spreadsheet {
55604
- .os-input {
55605
- border-width: 0 0 1px 0;
55606
- border-color: transparent;
55607
- outline: none;
55608
- text-overflow: ellipsis;
55609
- color: ${TEXT_BODY};
55610
- }
55611
- .os-input:hover,
55612
- .os-input:focus {
55613
- border-color: ${GRAY_300};
55614
- }
55615
- }
55616
- `;
55617
- class TextInput extends owl.Component {
55618
- static template = "o-spreadsheet-TextInput";
55619
- static props = {
55620
- value: String,
55621
- onChange: Function,
55622
- class: {
55623
- type: String,
55624
- optional: true,
55625
- },
55626
- id: {
55627
- type: String,
55628
- optional: true,
55629
- },
55630
- placeholder: {
55631
- type: String,
55632
- optional: true,
55633
- },
55634
- autofocus: {
55635
- type: Boolean,
55636
- optional: true,
55637
- },
55638
- };
55639
- inputRef = owl.useRef("input");
55640
- setup() {
55641
- owl.useExternalListener(window, "click", (ev) => {
55642
- if (ev.target !== this.inputRef.el && this.inputRef.el?.value !== this.props.value) {
55643
- this.save();
55644
- }
55645
- }, { capture: true });
55646
- if (this.props.autofocus) {
55647
- useAutofocus({ refName: "input" });
55648
- }
55649
- }
55650
- onKeyDown(ev) {
55651
- switch (ev.key) {
55652
- case "Enter":
55653
- this.save();
55654
- ev.preventDefault();
55655
- ev.stopPropagation();
55656
- break;
55657
- case "Escape":
55658
- if (this.inputRef.el) {
55659
- this.inputRef.el.value = this.props.value;
55660
- this.inputRef.el.blur();
55661
- }
55662
- ev.preventDefault();
55663
- ev.stopPropagation();
55664
- break;
55665
- }
55666
- }
55667
- save() {
55668
- const currentValue = (this.inputRef.el?.value || "").trim();
55669
- if (currentValue !== this.props.value) {
55670
- this.props.onChange(currentValue);
55671
- }
55672
- this.inputRef.el?.blur();
55673
- }
55674
- onMouseDown(ev) {
55675
- // Stop the event if the input is not focused, we handle everything in onMouseUp
55676
- if (ev.target !== document.activeElement) {
55677
- ev.preventDefault();
55678
- ev.stopPropagation();
55679
- }
55680
- }
55681
- onMouseUp(ev) {
55682
- const target = ev.target;
55683
- if (target !== document.activeElement) {
55684
- target.focus();
55685
- target.select();
55686
- ev.preventDefault();
55687
- ev.stopPropagation();
55688
- }
55689
- }
55690
- }
55691
-
55692
56069
  class PivotCustomGroupsCollapsible extends owl.Component {
55693
56070
  static template = "o-spreadsheet-PivotCustomGroupsCollapsible";
55694
56071
  static props = {
@@ -57803,11 +58180,12 @@ sidePanelRegistry.add("ChartPanel", {
57803
58180
  title: _t("Chart"),
57804
58181
  Body: ChartPanel,
57805
58182
  computeState: (getters, initialProps) => {
57806
- const figureId = getters.getSelectedFigureId() ?? initialProps.figureId;
57807
- if (!getters.isChartDefined(figureId)) {
58183
+ const figureId = getters.getSelectedFigureId();
58184
+ const chartId = figureId ? getters.getChartIdFromFigureId(figureId) : initialProps.chartId;
58185
+ if (!chartId || !getters.isChartDefined(chartId)) {
57808
58186
  return { isOpen: false };
57809
58187
  }
57810
- return { isOpen: true, props: { figureId } };
58188
+ return { isOpen: true, props: { chartId } };
57811
58189
  },
57812
58190
  });
57813
58191
  sidePanelRegistry.add("FindAndReplace", {
@@ -57895,6 +58273,17 @@ sidePanelRegistry.add("PivotMeasureDisplayPanel", {
57895
58273
  }
57896
58274
  },
57897
58275
  });
58276
+ sidePanelRegistry.add("CarouselPanel", {
58277
+ title: _t("Carousel"),
58278
+ Body: CarouselPanel,
58279
+ computeState: (getters, initialProps) => {
58280
+ const figureId = initialProps.figureId || getters.getSelectedFigureId();
58281
+ if (!figureId || !getters.doesCarouselExist(figureId)) {
58282
+ return { isOpen: false };
58283
+ }
58284
+ return { isOpen: true, props: { figureId } };
58285
+ },
58286
+ });
57898
58287
 
57899
58288
  class ScreenWidthStore {
57900
58289
  mutators = ["setSmallThreshhold"];
@@ -58856,7 +59245,7 @@ class FullScreenChart extends owl.Component {
58856
59245
  let lastFigureId = undefined;
58857
59246
  owl.onWillUpdateProps(() => {
58858
59247
  if (lastFigureId !== this.figureUI?.id) {
58859
- animationStore.enableAnimationForChart(this.figureUI?.id + "-fullscreen");
59248
+ animationStore.enableAnimationForChart(this.chartId + "-fullscreen");
58860
59249
  }
58861
59250
  lastFigureId = this.figureUI?.id;
58862
59251
  });
@@ -58865,6 +59254,11 @@ class FullScreenChart extends owl.Component {
58865
59254
  get figureUI() {
58866
59255
  return this.fullScreenChartStore.fullScreenFigure;
58867
59256
  }
59257
+ get chartId() {
59258
+ if (!this.figureUI)
59259
+ return undefined;
59260
+ return this.env.model.getters.getChartIdFromFigureId(this.figureUI?.id);
59261
+ }
58868
59262
  exitFullScreen() {
58869
59263
  if (this.figureUI) {
58870
59264
  this.fullScreenChartStore.toggleFullScreenChart(this.figureUI.id);
@@ -58876,9 +59270,9 @@ class FullScreenChart extends owl.Component {
58876
59270
  }
58877
59271
  }
58878
59272
  get chartComponent() {
58879
- if (!this.figureUI)
59273
+ if (!this.chartId)
58880
59274
  return undefined;
58881
- const type = this.env.model.getters.getChartType(this.figureUI.id);
59275
+ const type = this.env.model.getters.getChartType(this.chartId);
58882
59276
  const component = chartComponentRegistry.get(type);
58883
59277
  if (!component) {
58884
59278
  throw new Error(`Component is not defined for type ${type}`);
@@ -60537,6 +60931,7 @@ class ChartPlugin extends CorePlugin {
60537
60931
  "getChartType",
60538
60932
  "getChartIds",
60539
60933
  "getChart",
60934
+ "getFigureIdFromChartId",
60540
60935
  "getContextCreationChart",
60541
60936
  ];
60542
60937
  charts = {};
@@ -60544,7 +60939,11 @@ class ChartPlugin extends CorePlugin {
60544
60939
  validateChartDefinition = (cmd) => validateChartDefinition(this, cmd.definition);
60545
60940
  adaptRanges(applyChange) {
60546
60941
  for (const [chartId, chart] of Object.entries(this.charts)) {
60547
- this.history.update("charts", chartId, chart?.updateRanges(applyChange));
60942
+ if (!chart) {
60943
+ continue;
60944
+ }
60945
+ const newChart = chart.chart.updateRanges(applyChange);
60946
+ this.history.update("charts", chartId, newChart ? { figureId: chart.figureId, chart: newChart } : undefined);
60548
60947
  }
60549
60948
  }
60550
60949
  // ---------------------------------------------------------------------------
@@ -60553,9 +60952,11 @@ class ChartPlugin extends CorePlugin {
60553
60952
  allowDispatch(cmd) {
60554
60953
  switch (cmd.type) {
60555
60954
  case "CREATE_CHART":
60556
- return this.checkValidations(cmd, this.chainValidations(this.validateChartDefinition, this.checkChartDuplicate));
60955
+ return this.checkValidations(cmd, this.chainValidations(this.checkFigureArguments, this.validateChartDefinition, this.checkChartDuplicate));
60557
60956
  case "UPDATE_CHART":
60558
60957
  return this.checkValidations(cmd, this.chainValidations(this.validateChartDefinition, this.checkChartExists, this.checkChartChanged));
60958
+ case "DELETE_CHART":
60959
+ return this.checkChartExists(cmd);
60559
60960
  default:
60560
60961
  return "Success" /* CommandResult.Success */;
60561
60962
  }
@@ -60563,37 +60964,61 @@ class ChartPlugin extends CorePlugin {
60563
60964
  handle(cmd) {
60564
60965
  switch (cmd.type) {
60565
60966
  case "CREATE_CHART":
60566
- this.addFigure(cmd.figureId, cmd.sheetId, cmd.col, cmd.row, cmd.offset, cmd.size);
60567
- this.addChart(cmd.figureId, cmd.definition);
60967
+ const { col, row, offset, size, sheetId, figureId } = cmd;
60968
+ // If figure position is not defined, it means that the figure already exist (see allowDispatch)
60969
+ if (!this.getters.getFigure(sheetId, figureId) &&
60970
+ offset !== undefined &&
60971
+ col !== undefined &&
60972
+ row !== undefined) {
60973
+ this.addFigure(figureId, sheetId, col, row, offset, size);
60974
+ }
60975
+ this.addChart(cmd.figureId, cmd.chartId, cmd.definition);
60568
60976
  break;
60569
60977
  case "UPDATE_CHART": {
60570
- this.addChart(cmd.figureId, cmd.definition);
60978
+ this.addChart(cmd.figureId, cmd.chartId, cmd.definition);
60571
60979
  break;
60572
60980
  }
60573
60981
  case "DUPLICATE_SHEET": {
60574
- const sheetFiguresFrom = this.getters.getFigures(cmd.sheetId);
60575
- for (const fig of sheetFiguresFrom) {
60576
- if (fig.tag === "chart") {
60577
- const figureIdBase = fig.id.split(FIGURE_ID_SPLITTER).pop();
60578
- const duplicatedFigureId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${figureIdBase}`;
60579
- const chart = this.charts[fig.id]?.duplicateInDuplicatedSheet(cmd.sheetIdTo);
60580
- if (chart) {
60581
- this.dispatch("CREATE_CHART", {
60582
- figureId: duplicatedFigureId,
60583
- col: fig.col,
60584
- row: fig.row,
60585
- offset: fig.offset,
60586
- size: { width: fig.width, height: fig.height },
60587
- definition: chart.getDefinition(),
60588
- sheetId: cmd.sheetIdTo,
60589
- });
60590
- }
60982
+ for (const chartId of this.getChartIds(cmd.sheetId)) {
60983
+ const { chart, figureId } = this.charts[chartId] || {};
60984
+ if (!chart || !figureId) {
60985
+ continue;
60986
+ }
60987
+ const fig = this.getters.getFigure(cmd.sheetId, figureId);
60988
+ if (!fig) {
60989
+ continue;
60990
+ }
60991
+ const figureIdBase = figureId.split(FIGURE_ID_SPLITTER).pop();
60992
+ const duplicatedFigureId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${figureIdBase}`;
60993
+ const chartIdBase = chartId.split(FIGURE_ID_SPLITTER).pop();
60994
+ const duplicatedChartId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${chartIdBase}`;
60995
+ const newChart = chart.duplicateInDuplicatedSheet(cmd.sheetIdTo);
60996
+ if (newChart) {
60997
+ this.dispatch("CREATE_CHART", {
60998
+ figureId: duplicatedFigureId,
60999
+ chartId: duplicatedChartId,
61000
+ col: fig.col,
61001
+ row: fig.row,
61002
+ offset: fig.offset,
61003
+ size: { width: fig.width, height: fig.height },
61004
+ definition: newChart.getDefinition(),
61005
+ sheetId: cmd.sheetIdTo,
61006
+ });
60591
61007
  }
60592
61008
  }
60593
61009
  break;
60594
61010
  }
60595
61011
  case "DELETE_FIGURE":
60596
- this.history.update("charts", cmd.figureId, undefined);
61012
+ for (const chartId in this.charts) {
61013
+ if (this.charts[chartId]?.figureId === cmd.figureId) {
61014
+ this.dispatch("DELETE_CHART", { chartId, sheetId: cmd.sheetId });
61015
+ }
61016
+ }
61017
+ break;
61018
+ case "DELETE_CHART":
61019
+ if (this.isChartDefined(cmd.chartId)) {
61020
+ this.history.update("charts", cmd.chartId, undefined);
61021
+ }
60597
61022
  break;
60598
61023
  case "DELETE_SHEET":
60599
61024
  for (const id of this.getChartIds(cmd.sheetId)) {
@@ -60605,31 +61030,37 @@ class ChartPlugin extends CorePlugin {
60605
61030
  // ---------------------------------------------------------------------------
60606
61031
  // Getters
60607
61032
  // ---------------------------------------------------------------------------
60608
- getContextCreationChart(figureId) {
60609
- return this.charts[figureId]?.getContextCreation();
61033
+ getContextCreationChart(chartId) {
61034
+ return this.charts[chartId]?.chart.getContextCreation();
60610
61035
  }
60611
- getChart(figureId) {
60612
- return this.charts[figureId];
61036
+ getChart(chartId) {
61037
+ return this.charts[chartId]?.chart;
60613
61038
  }
60614
- getChartType(figureId) {
60615
- const type = this.charts[figureId]?.type;
61039
+ getFigureIdFromChartId(chartId) {
61040
+ if (!this.charts[chartId]) {
61041
+ throw new Error(`Chart with id ${chartId} does not exist.`);
61042
+ }
61043
+ return this.charts[chartId].figureId;
61044
+ }
61045
+ getChartType(chartId) {
61046
+ const type = this.charts[chartId]?.chart.type;
60616
61047
  if (!type) {
60617
61048
  throw new Error("Chart not defined.");
60618
61049
  }
60619
61050
  return type;
60620
61051
  }
60621
- isChartDefined(figureId) {
60622
- return figureId in this.charts && this.charts !== undefined;
61052
+ isChartDefined(chartId) {
61053
+ return chartId in this.charts && this.charts !== undefined;
60623
61054
  }
60624
61055
  getChartIds(sheetId) {
60625
61056
  return Object.entries(this.charts)
60626
- .filter(([, chart]) => chart?.sheetId === sheetId)
61057
+ .filter(([, chart]) => chart?.chart.sheetId === sheetId)
60627
61058
  .map(([id]) => id);
60628
61059
  }
60629
- getChartDefinition(figureId) {
60630
- const definition = this.charts[figureId]?.getDefinition();
61060
+ getChartDefinition(chartId) {
61061
+ const definition = this.charts[chartId]?.chart.getDefinition();
60631
61062
  if (!definition) {
60632
- throw new Error(`There is no chart with the given figureId: ${figureId}`);
61063
+ throw new Error(`There is no chart with the given id: ${chartId}`);
60633
61064
  }
60634
61065
  return definition;
60635
61066
  }
@@ -60644,7 +61075,16 @@ class ChartPlugin extends CorePlugin {
60644
61075
  // figure data should be external IMO => chart should be in sheet.chart
60645
61076
  // instead of in figure.data
60646
61077
  if (figure.tag === "chart") {
60647
- this.charts[figure.id] = this.createChart(figure.id, figure.data, sheet.id);
61078
+ const chartId = figure.data.chartId;
61079
+ const chart = this.createChart(figure.id, figure.data, sheet.id);
61080
+ this.charts[chartId] = { chart, figureId: figure.id };
61081
+ }
61082
+ else if (figure.tag === "carousel") {
61083
+ for (const chartId in figure.data.chartDefinitions || {}) {
61084
+ const chartDefinition = figure.data.chartDefinitions[chartId];
61085
+ const chart = this.createChart(figure.id, chartDefinition, sheet.id);
61086
+ this.charts[chartId] = { chart, figureId: figure.id };
61087
+ }
60648
61088
  }
60649
61089
  }
60650
61090
  }
@@ -60658,13 +61098,23 @@ class ChartPlugin extends CorePlugin {
60658
61098
  const figures = [];
60659
61099
  for (const sheetFigure of sheetFigures) {
60660
61100
  const figure = sheetFigure;
60661
- if (figure && figure.tag === "chart") {
60662
- const data = this.charts[figure.id]?.getDefinition();
61101
+ const chartId = Object.keys(this.charts).find((chartId) => this.charts[chartId]?.figureId === sheetFigure.id);
61102
+ if (figure && figure.tag === "chart" && chartId) {
61103
+ const data = this.charts[chartId]?.chart.getDefinition();
60663
61104
  if (data) {
60664
- figure.data = data;
61105
+ figure.data = { ...data, chartId };
60665
61106
  figures.push(figure);
60666
61107
  }
60667
61108
  }
61109
+ else if (figure && figure.tag === "carousel") {
61110
+ const chartIds = Object.keys(this.charts).filter((chartId) => this.charts[chartId]?.figureId === sheetFigure.id);
61111
+ const data = {};
61112
+ for (const chartId of chartIds) {
61113
+ data[chartId] = this.charts[chartId]?.chart.getDefinition();
61114
+ }
61115
+ figure.data = { chartDefinitions: data };
61116
+ figures.push(figure);
61117
+ }
60668
61118
  else {
60669
61119
  figures.push(figure);
60670
61120
  }
@@ -60697,27 +61147,40 @@ class ChartPlugin extends CorePlugin {
60697
61147
  * Add a chart in the local state. If a chart already exists, this chart is
60698
61148
  * replaced
60699
61149
  */
60700
- addChart(id, definition) {
60701
- const sheetId = this.getters.getFigureSheetId(id);
61150
+ addChart(figureId, chartId, definition) {
61151
+ const sheetId = this.getters.getFigureSheetId(figureId);
60702
61152
  if (sheetId) {
60703
- this.history.update("charts", id, this.createChart(id, definition, sheetId));
61153
+ const chart = this.createChart(figureId, definition, sheetId);
61154
+ this.history.update("charts", chartId, { figureId, chart });
60704
61155
  }
60705
61156
  }
60706
61157
  checkChartDuplicate(cmd) {
60707
- return this.getters.getFigureSheetId(cmd.figureId)
61158
+ return this.isChartDefined(cmd.chartId)
60708
61159
  ? "DuplicatedChartId" /* CommandResult.DuplicatedChartId */
60709
61160
  : "Success" /* CommandResult.Success */;
60710
61161
  }
60711
61162
  checkChartExists(cmd) {
60712
- return this.isChartDefined(cmd.figureId)
61163
+ return this.isChartDefined(cmd.chartId)
60713
61164
  ? "Success" /* CommandResult.Success */
60714
61165
  : "ChartDoesNotExist" /* CommandResult.ChartDoesNotExist */;
60715
61166
  }
60716
61167
  checkChartChanged(cmd) {
60717
- return deepEquals(this.getChartDefinition(cmd.figureId), cmd.definition)
61168
+ if (cmd.figureId !== this.charts[cmd.chartId]?.figureId) {
61169
+ return "Success" /* CommandResult.Success */;
61170
+ }
61171
+ return deepEquals(this.getChartDefinition(cmd.chartId), cmd.definition)
60718
61172
  ? "NoChanges" /* CommandResult.NoChanges */
60719
61173
  : "Success" /* CommandResult.Success */;
60720
61174
  }
61175
+ /** If the command would create a new figure, there need to be a position & offset defined in the command */
61176
+ checkFigureArguments(cmd) {
61177
+ if (this.getters.getFigure(cmd.sheetId, cmd.figureId)) {
61178
+ return "Success" /* CommandResult.Success */;
61179
+ }
61180
+ return cmd.offset !== undefined && cmd.col !== undefined && cmd.row !== undefined
61181
+ ? "Success" /* CommandResult.Success */
61182
+ : "MissingFigureArguments" /* CommandResult.MissingFigureArguments */;
61183
+ }
60721
61184
  }
60722
61185
 
60723
61186
  // -----------------------------------------------------------------------------
@@ -61571,6 +62034,23 @@ class FigurePlugin extends CorePlugin {
61571
62034
  this.onRowRemove(cmd.sheetId);
61572
62035
  }
61573
62036
  break;
62037
+ case "DUPLICATE_SHEET": {
62038
+ for (const figureId in this.figures[cmd.sheetId]) {
62039
+ const fig = this.figures[cmd.sheetId]?.[figureId];
62040
+ if (!fig) {
62041
+ continue;
62042
+ }
62043
+ const figureIdBase = figureId.split(FIGURE_ID_SPLITTER).pop();
62044
+ const duplicatedFigureId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${figureIdBase}`;
62045
+ this.dispatch("CREATE_FIGURE", {
62046
+ figureId: duplicatedFigureId,
62047
+ ...fig,
62048
+ size: { width: fig.width, height: fig.height },
62049
+ sheetId: cmd.sheetIdTo,
62050
+ });
62051
+ }
62052
+ break;
62053
+ }
61574
62054
  }
61575
62055
  }
61576
62056
  onColRemove(sheetId) {
@@ -61682,6 +62162,9 @@ class FigurePlugin extends CorePlugin {
61682
62162
  const figure = { ...this.getFigure(sheetId, figureId), ...update };
61683
62163
  for (const [key, value] of Object.entries(update)) {
61684
62164
  switch (key) {
62165
+ case "tag":
62166
+ this.history.update("figures", sheetId, figure.id, key, value);
62167
+ break;
61685
62168
  case "offset":
61686
62169
  this.history.update("figures", sheetId, figure.id, key, value);
61687
62170
  break;
@@ -62109,7 +62592,9 @@ class ImagePlugin extends CorePlugin {
62109
62592
  handle(cmd) {
62110
62593
  switch (cmd.type) {
62111
62594
  case "CREATE_IMAGE":
62112
- this.addFigure(cmd.figureId, cmd.sheetId, cmd.col, cmd.row, cmd.offset, cmd.size);
62595
+ if (!this.getters.getFigure(cmd.sheetId, cmd.figureId)) {
62596
+ this.addFigure(cmd.figureId, cmd.sheetId, cmd.col, cmd.row, cmd.offset, cmd.size);
62597
+ }
62113
62598
  this.history.update("images", cmd.sheetId, cmd.figureId, cmd.definition);
62114
62599
  this.syncedImages.add(cmd.definition.path);
62115
62600
  break;
@@ -64247,6 +64732,122 @@ class TablePlugin extends CorePlugin {
64247
64732
  }
64248
64733
  }
64249
64734
 
64735
+ class CarouselPlugin extends CorePlugin {
64736
+ static getters = ["getCarousel", "doesCarouselExist"];
64737
+ carousels = {};
64738
+ allowDispatch(cmd) {
64739
+ switch (cmd.type) {
64740
+ case "CREATE_CAROUSEL": {
64741
+ if (this.getters.getFigure(cmd.sheetId, cmd.figureId)) {
64742
+ return "DuplicatedFigureId" /* CommandResult.DuplicatedFigureId */;
64743
+ }
64744
+ return "Success" /* CommandResult.Success */;
64745
+ }
64746
+ case "UPDATE_CAROUSEL": {
64747
+ if (!this.carousels[cmd.sheetId]?.[cmd.figureId]) {
64748
+ return "InvalidFigureId" /* CommandResult.InvalidFigureId */;
64749
+ }
64750
+ return "Success" /* CommandResult.Success */;
64751
+ }
64752
+ }
64753
+ return "Success" /* CommandResult.Success */;
64754
+ }
64755
+ handle(cmd) {
64756
+ switch (cmd.type) {
64757
+ case "CREATE_CAROUSEL":
64758
+ if (!this.getters.getFigure(cmd.sheetId, cmd.figureId)) {
64759
+ this.dispatch("CREATE_FIGURE", { ...cmd, tag: "carousel" });
64760
+ }
64761
+ this.history.update("carousels", cmd.sheetId, cmd.figureId, cmd.definition);
64762
+ break;
64763
+ case "UPDATE_CAROUSEL":
64764
+ this.removeDeletedCharts(cmd, this.getters.getCarousel(cmd.figureId).items);
64765
+ this.history.update("carousels", cmd.sheetId, cmd.figureId, cmd.definition);
64766
+ break;
64767
+ case "DUPLICATE_SHEET": {
64768
+ const sheetFiguresFrom = this.getters.getFigures(cmd.sheetId);
64769
+ for (const fig of sheetFiguresFrom) {
64770
+ if (fig.tag === "carousel") {
64771
+ const figureIdBase = fig.id.split(FIGURE_ID_SPLITTER).pop();
64772
+ const duplicatedFigureId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${figureIdBase}`;
64773
+ const carousel = this.getCarousel(fig.id);
64774
+ if (carousel) {
64775
+ const size = { width: fig.width, height: fig.height };
64776
+ this.dispatch("CREATE_CAROUSEL", {
64777
+ sheetId: cmd.sheetIdTo,
64778
+ figureId: duplicatedFigureId,
64779
+ offset: fig.offset,
64780
+ col: fig.col,
64781
+ row: fig.row,
64782
+ size,
64783
+ definition: {
64784
+ items: carousel.items.map((item) => {
64785
+ if (item.type === "carouselDataView") {
64786
+ return { type: "carouselDataView" };
64787
+ }
64788
+ const chartIdBase = item.chartId.split(FIGURE_ID_SPLITTER).pop();
64789
+ const newChartId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${chartIdBase}`;
64790
+ return { type: "chart", chartId: newChartId };
64791
+ }),
64792
+ },
64793
+ });
64794
+ }
64795
+ }
64796
+ }
64797
+ break;
64798
+ }
64799
+ case "DELETE_FIGURE":
64800
+ this.history.update("carousels", cmd.sheetId, cmd.figureId, undefined);
64801
+ break;
64802
+ case "DELETE_SHEET":
64803
+ this.history.update("carousels", cmd.sheetId, undefined);
64804
+ break;
64805
+ }
64806
+ }
64807
+ doesCarouselExist(figureId) {
64808
+ for (const sheetId in this.carousels) {
64809
+ if (this.carousels[sheetId]?.[figureId]) {
64810
+ return true;
64811
+ }
64812
+ }
64813
+ throw false;
64814
+ }
64815
+ getCarousel(figureId) {
64816
+ for (const sheetId in this.carousels) {
64817
+ if (this.carousels[sheetId]?.[figureId]) {
64818
+ return this.carousels[sheetId][figureId];
64819
+ }
64820
+ }
64821
+ throw new Error(`There is no carousel with the given figureId: ${figureId}`);
64822
+ }
64823
+ removeDeletedCharts(cmd, oldItems) {
64824
+ const newChartIds = new Set(cmd.definition.items.filter((item) => item.type === "chart").map((item) => item.chartId));
64825
+ for (const item of oldItems) {
64826
+ if (item.type === "chart" && !newChartIds.has(item.chartId)) {
64827
+ this.dispatch("DELETE_CHART", { chartId: item.chartId, sheetId: cmd.sheetId });
64828
+ }
64829
+ }
64830
+ }
64831
+ import(data) {
64832
+ for (const sheet of data.sheets) {
64833
+ const carousels = (sheet.figures || []).filter((figure) => figure.tag === "carousel");
64834
+ for (const carousel of carousels) {
64835
+ this.history.update("carousels", sheet.id, carousel.id, { items: carousel.data.items });
64836
+ }
64837
+ }
64838
+ }
64839
+ export(data) {
64840
+ for (const sheet of data.sheets) {
64841
+ const carousels = sheet.figures.filter((figure) => figure.tag === "carousel");
64842
+ for (const carousel of carousels) {
64843
+ if (this.carousels[sheet.id]?.[carousel.id]) {
64844
+ carousel.data = { ...carousel.data, ...this.carousels[sheet.id]?.[carousel.id] };
64845
+ }
64846
+ }
64847
+ }
64848
+ }
64849
+ }
64850
+
64250
64851
  class HeaderGroupingPlugin extends CorePlugin {
64251
64852
  static getters = [
64252
64853
  "getHeaderGroups",
@@ -67202,7 +67803,7 @@ class CustomColorsPlugin extends CoreViewPlugin {
67202
67803
  break;
67203
67804
  case "UPDATE_CHART":
67204
67805
  case "CREATE_CHART":
67205
- this.tryToAddColors(this.getChartColors(cmd.figureId));
67806
+ this.tryToAddColors(this.getChartColors(cmd.chartId));
67206
67807
  break;
67207
67808
  case "UPDATE_CELL":
67208
67809
  case "ADD_CONDITIONAL_FORMAT":
@@ -67334,8 +67935,10 @@ class EvaluationChartPlugin extends CoreViewPlugin {
67334
67935
  switch (cmd.type) {
67335
67936
  case "UPDATE_CHART":
67336
67937
  case "CREATE_CHART":
67337
- case "DELETE_FIGURE":
67338
- this.charts[cmd.figureId] = undefined;
67938
+ this.charts[cmd.chartId] = undefined;
67939
+ break;
67940
+ case "DELETE_CHART":
67941
+ this.charts[cmd.chartId] = undefined;
67339
67942
  break;
67340
67943
  case "DELETE_SHEET":
67341
67944
  for (const chartId in this.charts) {
@@ -67346,15 +67949,15 @@ class EvaluationChartPlugin extends CoreViewPlugin {
67346
67949
  break;
67347
67950
  }
67348
67951
  }
67349
- getChartRuntime(figureId) {
67350
- if (!this.charts[figureId]) {
67351
- const chart = this.getters.getChart(figureId);
67952
+ getChartRuntime(chartId) {
67953
+ if (!this.charts[chartId]) {
67954
+ const chart = this.getters.getChart(chartId);
67352
67955
  if (!chart) {
67353
- throw new Error(`No chart for the given id: ${figureId}`);
67956
+ throw new Error(`No chart for the given id: ${chartId}`);
67354
67957
  }
67355
- this.charts[figureId] = this.createRuntimeChart(chart);
67958
+ this.charts[chartId] = this.createRuntimeChart(chart);
67356
67959
  }
67357
- return this.charts[figureId];
67960
+ return this.charts[chartId];
67358
67961
  }
67359
67962
  /**
67360
67963
  * Get the background and textColor of a chart based on the color of the first cell of the main range of the chart.
@@ -67389,8 +67992,14 @@ class EvaluationChartPlugin extends CoreViewPlugin {
67389
67992
  if (!figure || figure.tag !== "chart") {
67390
67993
  continue;
67391
67994
  }
67392
- const figureId = figure.id;
67393
- const figureData = this.getters.getChart(figureId)?.getDefinitionForExcel(this.getters);
67995
+ const chartId = this.getters
67996
+ .getChartIds(sheet.id)
67997
+ .find((chartId) => this.getters.getFigureIdFromChartId(chartId) === figure.id);
67998
+ if (!chartId) {
67999
+ continue;
68000
+ }
68001
+ const chart = this.getters.getChart(chartId);
68002
+ const figureData = chart?.getDefinitionForExcel(this.getters);
67394
68003
  if (figureData) {
67395
68004
  figures.push({
67396
68005
  ...figure,
@@ -67398,12 +68007,11 @@ class EvaluationChartPlugin extends CoreViewPlugin {
67398
68007
  });
67399
68008
  }
67400
68009
  else {
67401
- const chart = this.getters.getChart(figureId);
67402
68010
  if (!chart) {
67403
68011
  continue;
67404
68012
  }
67405
- const type = this.getters.getChartType(figureId);
67406
- const runtime = this.getters.getChartRuntime(figureId);
68013
+ const type = this.getters.getChartType(chartId);
68014
+ const runtime = this.getters.getChartRuntime(chartId);
67407
68015
  const img = chartToImageUrl(runtime, figure, type);
67408
68016
  if (img) {
67409
68017
  sheet.images.push({
@@ -70537,7 +71145,9 @@ const specificRangeTransformRegistry = new SpecificRangeTransformRegistry();
70537
71145
  otRegistry.addTransformation("ADD_COLUMNS_ROWS", ["ADD_COLUMNS_ROWS"], addHeadersTransformation);
70538
71146
  otRegistry.addTransformation("REMOVE_COLUMNS_ROWS", ["ADD_COLUMNS_ROWS"], addHeadersTransformation);
70539
71147
  otRegistry.addTransformation("DELETE_SHEET", ["MOVE_RANGES"], transformTargetSheetId);
70540
- otRegistry.addTransformation("DELETE_FIGURE", ["UPDATE_FIGURE", "UPDATE_CHART"], updateChartFigure);
71148
+ otRegistry.addTransformation("DELETE_FIGURE", ["UPDATE_FIGURE", "UPDATE_CHART", "UPDATE_CAROUSEL"], updateChartFigure);
71149
+ otRegistry.addTransformation("DELETE_CHART", ["UPDATE_CHART"], updateChartOnChartDelete);
71150
+ otRegistry.addTransformation("DELETE_CHART", ["UPDATE_CAROUSEL"], updateCarouselOnChartDelete);
70541
71151
  otRegistry.addTransformation("CREATE_SHEET", ["CREATE_SHEET"], createSheetTransformation);
70542
71152
  otRegistry.addTransformation("ADD_MERGE", ["ADD_MERGE", "REMOVE_MERGE"], mergeTransformation);
70543
71153
  otRegistry.addTransformation("ADD_COLUMNS_ROWS", ["FREEZE_COLUMNS", "FREEZE_ROWS"], freezeTransformation);
@@ -70590,6 +71200,21 @@ function updateChartFigure(toTransform, executed) {
70590
71200
  }
70591
71201
  return toTransform;
70592
71202
  }
71203
+ function updateChartOnChartDelete(toTransform, executed) {
71204
+ if (toTransform.chartId === executed.chartId) {
71205
+ return undefined;
71206
+ }
71207
+ return toTransform;
71208
+ }
71209
+ function updateCarouselOnChartDelete(toTransform, executed) {
71210
+ return {
71211
+ ...toTransform,
71212
+ definition: {
71213
+ ...toTransform.definition,
71214
+ items: toTransform.definition.items.filter((item) => !(item.type === "chart" && item.chartId === executed.chartId)),
71215
+ },
71216
+ };
71217
+ }
70593
71218
  function createSheetTransformation(toTransform, executed) {
70594
71219
  if (toTransform.sheetId === executed.sheetId) {
70595
71220
  toTransform = { ...toTransform, sheetId: `${toTransform.sheetId}~` };
@@ -72984,9 +73609,11 @@ function repeatRangeDependantCommand(getters, command) {
72984
73609
 
72985
73610
  const uuidGenerator = new UuidGenerator();
72986
73611
  function repeatCreateChartCommand(getters, cmd) {
73612
+ const id = uuidGenerator.smallUuid();
72987
73613
  return {
72988
73614
  ...repeatSheetDependantCommand(getters, cmd),
72989
- figureId: uuidGenerator.smallUuid(),
73615
+ figureId: id,
73616
+ chartId: id,
72990
73617
  };
72991
73618
  }
72992
73619
  function repeatCreateImageCommand(getters, cmd) {
@@ -76196,6 +76823,123 @@ class SheetViewPlugin extends UIPlugin {
76196
76823
  }
76197
76824
  }
76198
76825
 
76826
+ class CarouselUIPlugin extends UIPlugin {
76827
+ static getters = [
76828
+ "getSelectedCarouselItem",
76829
+ "getChartFromFigureId",
76830
+ "getChartIdFromFigureId",
76831
+ ];
76832
+ uuidGenerator = new UuidGenerator();
76833
+ carouselStates = {};
76834
+ handle(cmd) {
76835
+ switch (cmd.type) {
76836
+ case "ADD_NEW_CHART_TO_CAROUSEL":
76837
+ this.addNewChartToCarousel(cmd.figureId, cmd.sheetId);
76838
+ break;
76839
+ case "ADD_FIGURE_CHART_TO_CAROUSEL":
76840
+ this.addFigureChartToCarousel(cmd.carouselFigureId, cmd.chartFigureId, cmd.sheetId);
76841
+ break;
76842
+ case "UPDATE_CAROUSEL_ACTIVE_ITEM":
76843
+ this.carouselStates[cmd.figureId] = cmd.item;
76844
+ break;
76845
+ case "DELETE_FIGURE":
76846
+ delete this.carouselStates[cmd.figureId];
76847
+ break;
76848
+ case "UPDATE_CAROUSEL":
76849
+ this.fixWrongCarouselState(cmd.figureId);
76850
+ break;
76851
+ case "DELETE_CHART":
76852
+ case "UNDO":
76853
+ case "REDO":
76854
+ case "DELETE_SHEET":
76855
+ for (const figureId in this.carouselStates) {
76856
+ this.fixWrongCarouselState(figureId);
76857
+ }
76858
+ break;
76859
+ }
76860
+ }
76861
+ getSelectedCarouselItem(figureId) {
76862
+ const carousel = this.getters.getCarousel(figureId);
76863
+ if (!carousel.items.length) {
76864
+ return undefined;
76865
+ }
76866
+ return this.carouselStates[figureId] ? this.carouselStates[figureId] : carousel.items[0];
76867
+ }
76868
+ getChartFromFigureId(figureId) {
76869
+ const sheetId = this.getters.getFigureSheetId(figureId);
76870
+ if (!sheetId) {
76871
+ return undefined;
76872
+ }
76873
+ const chartId = this.getChartIdFromFigureId(figureId);
76874
+ return chartId ? this.getters.getChart(chartId) : undefined;
76875
+ }
76876
+ getChartIdFromFigureId(figureId) {
76877
+ const sheetId = this.getters.getFigureSheetId(figureId);
76878
+ if (!sheetId) {
76879
+ return undefined;
76880
+ }
76881
+ const figure = this.getters.getFigure(sheetId, figureId);
76882
+ if (!figure || (figure.tag !== "chart" && figure.tag !== "carousel")) {
76883
+ return undefined;
76884
+ }
76885
+ if (figure.tag === "carousel") {
76886
+ const carouselItem = this.getSelectedCarouselItem(figureId);
76887
+ return carouselItem?.type === "chart" ? carouselItem.chartId : undefined;
76888
+ }
76889
+ return this.getters
76890
+ .getChartIds(sheetId)
76891
+ .find((chartId) => this.getters.getFigureIdFromChartId(chartId) === figureId);
76892
+ }
76893
+ fixWrongCarouselState(figureId) {
76894
+ if (!this.getters.doesCarouselExist(figureId)) {
76895
+ delete this.carouselStates[figureId];
76896
+ return;
76897
+ }
76898
+ const carousel = this.getters.getCarousel(figureId);
76899
+ if (!carousel) {
76900
+ delete this.carouselStates[figureId];
76901
+ return;
76902
+ }
76903
+ if (!this.carouselStates[figureId]) {
76904
+ this.carouselStates[figureId] = carousel.items[0];
76905
+ }
76906
+ else if (carousel.items.length === 0) {
76907
+ delete this.carouselStates[figureId];
76908
+ }
76909
+ else if (!carousel.items.some((item) => deepEquals(item, this.carouselStates[figureId]))) {
76910
+ this.carouselStates[figureId] = carousel.items[0];
76911
+ }
76912
+ }
76913
+ addNewChartToCarousel(figureId, sheetId) {
76914
+ const carousel = this.getters.getCarousel(figureId);
76915
+ const chartId = this.uuidGenerator.smallUuid();
76916
+ this.dispatch("CREATE_CHART", {
76917
+ chartId,
76918
+ figureId,
76919
+ sheetId,
76920
+ definition: CAROUSEL_DEFAULT_CHART_DEFINITION,
76921
+ });
76922
+ const definition = { items: [...carousel.items, { type: "chart", chartId }] };
76923
+ this.dispatch("UPDATE_CAROUSEL", { sheetId, figureId, definition });
76924
+ }
76925
+ addFigureChartToCarousel(figureId, chartFigureId, sheetId) {
76926
+ const chartId = this.getChartIdFromFigureId(chartFigureId);
76927
+ if (!chartId) {
76928
+ return;
76929
+ }
76930
+ const carousel = this.getters.getCarousel(figureId);
76931
+ const definition = { items: [...carousel.items, { type: "chart", chartId }] };
76932
+ this.dispatch("UPDATE_CAROUSEL", { sheetId, figureId, definition });
76933
+ this.dispatch("UPDATE_CHART", {
76934
+ sheetId,
76935
+ chartId,
76936
+ figureId,
76937
+ definition: this.getters.getChartDefinition(chartId),
76938
+ });
76939
+ this.dispatch("DELETE_FIGURE", { sheetId, figureId: chartFigureId });
76940
+ }
76941
+ }
76942
+
76199
76943
  class HeaderPositionsUIPlugin extends UIPlugin {
76200
76944
  static getters = ["getColDimensions", "getRowDimensions", "getColRowOffset"];
76201
76945
  headerPositions = {};
@@ -76327,6 +77071,7 @@ const corePluginRegistry = new Registry()
76327
77071
  .add("conditional formatting", ConditionalFormatPlugin)
76328
77072
  .add("figures", FigurePlugin)
76329
77073
  .add("chart", ChartPlugin)
77074
+ .add("carousel", CarouselPlugin)
76330
77075
  .add("image", ImagePlugin)
76331
77076
  .add("pivot_core", PivotCorePlugin)
76332
77077
  .add("spreadsheet_pivot_core", SpreadsheetPivotCorePlugin)
@@ -76359,7 +77104,8 @@ const statefulUIPluginRegistry = new Registry()
76359
77104
  .add("table_computed_style", TableComputedStylePlugin)
76360
77105
  .add("header_positions", HeaderPositionsUIPlugin)
76361
77106
  .add("viewport", SheetViewPlugin)
76362
- .add("clipboard", ClipboardPlugin);
77107
+ .add("clipboard", ClipboardPlugin)
77108
+ .add("carousel_ui", CarouselUIPlugin);
76363
77109
  // Plugins which have a derived state from core data
76364
77110
  const coreViewsPluginRegistry = new Registry()
76365
77111
  .add("evaluation", EvaluationPlugin)
@@ -77312,6 +78058,10 @@ topbarMenuRegistry
77312
78058
  .addChild("insert_chart", ["insert"], {
77313
78059
  ...insertChart,
77314
78060
  sequence: 50,
78061
+ })
78062
+ .addChild("insert_carousel", ["insert"], {
78063
+ ...insertCarousel,
78064
+ sequence: 51,
77315
78065
  })
77316
78066
  .addChild("insert_pivot", ["insert"], {
77317
78067
  ...insertPivot,
@@ -83694,7 +84444,7 @@ function commonDataValidationAttributes(dvRule) {
83694
84444
  ];
83695
84445
  }
83696
84446
 
83697
- function createDrawing(drawingRelIds, sheet, figures) {
84447
+ function createDrawing(drawingRelIds, sheet, figures, construct) {
83698
84448
  const namespaces = [
83699
84449
  ["xmlns:xdr", NAMESPACE.drawing],
83700
84450
  ["xmlns:r", RELATIONSHIP_NSR],
@@ -83705,7 +84455,7 @@ function createDrawing(drawingRelIds, sheet, figures) {
83705
84455
  for (const [figureIndex, figure] of Object.entries(figures)) {
83706
84456
  switch (figure?.tag) {
83707
84457
  case "chart":
83708
- figuresNodes.push(createChartDrawing(figure, sheet, drawingRelIds[figureIndex]));
84458
+ figuresNodes.push(createChartDrawing(figure, sheet, drawingRelIds[figureIndex], construct));
83709
84459
  break;
83710
84460
  case "image":
83711
84461
  figuresNodes.push(createImageDrawing(figure, sheet, drawingRelIds[figureIndex]));
@@ -83767,10 +84517,10 @@ function figureCoordinates(headers, anchor, offset) {
83767
84517
  offset: convertDotValueToEMU(offset - currentPosition + FIGURE_BORDER_WIDTH),
83768
84518
  };
83769
84519
  }
83770
- function createChartDrawing(figure, sheet, chartRelId) {
84520
+ function createChartDrawing(figure, sheet, chartRelId, construct) {
83771
84521
  // position
83772
84522
  const { from, to } = convertFigureData(figure, sheet);
83773
- const chartId = convertChartId(figure.id);
84523
+ const chartId = convertChartId(figure.id, construct);
83774
84524
  const cNvPrAttrs = [
83775
84525
  ["id", chartId],
83776
84526
  ["name", `Chart ${chartId}`],
@@ -84433,7 +85183,7 @@ function createWorksheets(data, construct) {
84433
85183
  let drawingNode = escapeXml ``;
84434
85184
  const drawingRelIds = [];
84435
85185
  for (const chart of sheet.charts) {
84436
- const xlsxChartId = convertChartId(chart.id);
85186
+ const xlsxChartId = convertChartId(chart.id, construct);
84437
85187
  const chartRelId = addRelsToFile(construct.relsFiles, `xl/drawings/_rels/drawing${sheetIndex}.xml.rels`, {
84438
85188
  target: `../charts/chart${xlsxChartId}.xml`,
84439
85189
  type: XLSX_RELATION_TYPE.chart,
@@ -84467,7 +85217,7 @@ function createWorksheets(data, construct) {
84467
85217
  target: `../drawings/drawing${sheetIndex}.xml`,
84468
85218
  type: XLSX_RELATION_TYPE.drawing,
84469
85219
  });
84470
- files.push(createXMLFile(createDrawing(drawingRelIds, sheet, drawings), `xl/drawings/drawing${sheetIndex}.xml`, "drawing"));
85220
+ files.push(createXMLFile(createDrawing(drawingRelIds, sheet, drawings, construct), `xl/drawings/drawing${sheetIndex}.xml`, "drawing"));
84471
85221
  drawingNode = escapeXml /*xml*/ `<drawing r:id="${drawingRelId}" />`;
84472
85222
  }
84473
85223
  const sheetXml = escapeXml /*xml*/ `
@@ -85450,6 +86200,7 @@ const constants = {
85450
86200
  HIGHLIGHT_COLOR,
85451
86201
  PIVOT_TABLE_CONFIG,
85452
86202
  ChartTerms,
86203
+ FIGURE_ID_SPLITTER,
85453
86204
  };
85454
86205
  const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
85455
86206
 
@@ -85504,6 +86255,6 @@ exports.tokenColors = tokenColors;
85504
86255
  exports.tokenize = tokenize;
85505
86256
 
85506
86257
 
85507
- __info__.version = "18.5.0-alpha.6";
85508
- __info__.date = "2025-08-05T06:27:49.505Z";
85509
- __info__.hash = "67e091f";
86258
+ __info__.version = "18.5.0-alpha.7";
86259
+ __info__.date = "2025-08-08T11:00:44.117Z";
86260
+ __info__.hash = "1019d55";