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