@odoo/o-spreadsheet 19.5.0-alpha.2 → 19.5.0-alpha.3

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 19.5.0-alpha.2
6
- * @date 2026-07-13T06:26:20.354Z
7
- * @hash a4d2f90
5
+ * @version 19.5.0-alpha.3
6
+ * @date 2026-07-14T10:17:06.949Z
7
+ * @hash c029184
8
8
  */
9
9
 
10
10
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
@@ -1248,6 +1248,12 @@ function defaultDict(def) {
1248
1248
  }
1249
1249
  };
1250
1250
  }
1251
+ function repeat(array, times) {
1252
+ const len = array.length;
1253
+ const result = new Array(len * times);
1254
+ for (let t = 0; t < times; t++) for (let i = 0; i < len; i++) result[t * len + i] = array[i];
1255
+ return result;
1256
+ }
1251
1257
 
1252
1258
  //#endregion
1253
1259
  //#region src/helpers/coordinates.ts
@@ -10133,6 +10139,7 @@ function getChartBackgroundColor({ background }, getters) {
10133
10139
  //#endregion
10134
10140
  //#region src/components/figures/chart/chartJs/chartjs_show_values_plugin.ts
10135
10141
  const MINIMAL_VERTICAL_DISTANCE = 13;
10142
+ const HORIZONTAL_PADDING = 3;
10136
10143
  function isLineOverlayOnBarChart(options, dataset) {
10137
10144
  return options.type === "bar" && dataset.type === "line";
10138
10145
  }
@@ -10142,175 +10149,276 @@ const chartShowValuesPlugin = {
10142
10149
  afterDatasetsDraw(chart, args, options) {
10143
10150
  if (!options.showValues) return;
10144
10151
  if (!chart._metasets?.[0]?.data) return;
10145
- const ctx = chart.ctx;
10146
- ctx.save();
10147
- ctx.textAlign = "center";
10148
- ctx.textBaseline = "middle";
10149
- ctx.miterLimit = 1;
10150
10152
  switch (options.type) {
10151
10153
  case "pie":
10152
- drawPieChartValues(chart, options, ctx);
10154
+ drawPieValues(chart, options);
10153
10155
  break;
10154
10156
  case "line":
10155
10157
  case "scatter":
10158
+ drawLineValues(chart, options);
10159
+ break;
10156
10160
  case "combo":
10157
10161
  case "waterfall":
10162
+ drawComboValues(chart, options);
10163
+ break;
10158
10164
  case "radar":
10159
- drawLineOrBarOrRadarChartValues(chart, options, ctx);
10165
+ drawRadarValues(chart, options);
10160
10166
  break;
10161
10167
  case "bar":
10162
- options.horizontal ? drawHorizontalBarChartValues(chart, options, ctx) : drawLineOrBarOrRadarChartValues(chart, options, ctx);
10168
+ options.horizontal ? drawHorizontalBarValues(chart, options) : drawVerticalBarValues(chart, options);
10163
10169
  break;
10164
10170
  case "pyramid":
10165
- drawHorizontalBarChartValues(chart, options, ctx);
10171
+ drawHorizontalBarValues(chart, options);
10166
10172
  break;
10167
10173
  case "calendar":
10168
- drawBarChartValues(chart, options, ctx);
10174
+ drawCalendarValues(chart, options);
10169
10175
  break;
10170
10176
  case "bubble":
10171
- drawBubbleChartValues(chart, options, ctx);
10177
+ drawBubbleValues(chart, options);
10172
10178
  break;
10173
10179
  case "funnel":
10174
- drawHorizontalBarChartValues(chart, options, ctx);
10180
+ drawFunnelValues(chart, options);
10175
10181
  break;
10176
10182
  }
10177
- ctx.restore();
10178
10183
  }
10179
10184
  };
10180
- function drawTextWithBackground(text, x, y, ctx) {
10181
- ctx.lineWidth = 3;
10182
- ctx.strokeText(text, x, y);
10183
- ctx.lineWidth = 1;
10184
- ctx.fillText(text, x, y);
10185
- }
10186
- function drawLineOrBarOrRadarChartValues(chart, options, ctx) {
10185
+ function drawValues(args) {
10186
+ const { chart, options, getNumberValue, direction } = args;
10187
+ const ctx = chart.ctx;
10188
+ ctx.save();
10189
+ ctx.textAlign = "center";
10190
+ ctx.textBaseline = "middle";
10191
+ ctx.miterLimit = 1;
10187
10192
  const textsPositions = {};
10188
10193
  for (const dataset of chart._metasets) {
10189
- if (isTrendLineAxis(dataset.xAxisID) || dataset.hidden || isLineOverlayOnBarChart(options, dataset)) continue;
10190
- const yAxisScale = chart.scales[dataset.yAxisID];
10194
+ if (isTrendLineAxis(dataset.xAxisID) || dataset.hidden) continue;
10191
10195
  for (let i = 0; i < dataset._parsed.length; i++) {
10192
- const parsedValue = dataset._parsed[i];
10193
- const value = Number(chart.config.type === "radar" ? parsedValue.r : parsedValue.y);
10194
- if (isNaN(value)) continue;
10195
- const point = dataset.data[i];
10196
- const xPosition = point.x;
10197
- let yPosition = 0;
10198
- if (chart.config.type === "line" || chart.config.type === "radar") yPosition = value < 0 ? point.y + 10 : point.y - 10;
10199
- else if (chart.config.type === "bubble") yPosition = point.y;
10200
- else {
10201
- const yZeroLine = yAxisScale.getPixelForValue(0);
10202
- const distanceFromAxisOrigin = Math.abs(yZeroLine - point.y);
10203
- const textHeight = globalThis.Chart?.defaults.font.size ?? 12;
10204
- if (distanceFromAxisOrigin < textHeight) yPosition = value < 0 ? yZeroLine + textHeight / 2 : yZeroLine - textHeight / 2;
10205
- else yPosition = value < 0 ? point.y - point.height / 2 : point.y + point.height / 2;
10206
- }
10207
- if (!textsPositions[xPosition]) textsPositions[xPosition] = [];
10208
- for (const otherPosition of textsPositions[xPosition] || []) if (Math.abs(otherPosition - yPosition) < MINIMAL_VERTICAL_DISTANCE) yPosition = otherPosition + MINIMAL_VERTICAL_DISTANCE * (value < 0 ? 1 : -1);
10209
- textsPositions[xPosition].push(yPosition);
10210
- ctx.fillStyle = point.options.backgroundColor;
10211
- ctx.strokeStyle = options.background(Number(value), dataset, i) || "#ffffff";
10212
- drawTextWithBackground(options.callback(Number(value), dataset, i), xPosition, yPosition, ctx);
10196
+ const numberValue = getNumberValue(dataset, i);
10197
+ if (numberValue === void 0 || isNaN(numberValue)) continue;
10198
+ const chartElement = dataset.data[i];
10199
+ const elementColor = chartElement.options.backgroundColor;
10200
+ if (!elementColor || colorToRGBA(elementColor).a !== 1) continue;
10201
+ const valueToDisplay = options.callback(numberValue, dataset, i);
10202
+ const textSize = getTextDimensions(valueToDisplay, ctx);
10203
+ const callbackArgs = {
10204
+ dataset,
10205
+ chartElement,
10206
+ numberValue,
10207
+ valueIndex: i,
10208
+ textSize,
10209
+ options,
10210
+ chart
10211
+ };
10212
+ const position = args.getValuePosition(callbackArgs);
10213
+ if (args.shouldSkipValue?.(callbackArgs)) continue;
10214
+ if (direction === "vertical") {
10215
+ const key = Math.round(position.x);
10216
+ if (!textsPositions[key]) textsPositions[key] = [];
10217
+ for (const otherPosition of textsPositions[key] || []) if (Math.abs(otherPosition - position.y) < MINIMAL_VERTICAL_DISTANCE) position.y = otherPosition + MINIMAL_VERTICAL_DISTANCE * (numberValue < 0 ? 1 : -1);
10218
+ textsPositions[key].push(position.y);
10219
+ } else {
10220
+ const key = Math.round(position.y);
10221
+ if (!textsPositions[key]) textsPositions[key] = [];
10222
+ for (const otherPosition of textsPositions[key]) if (Math.abs(otherPosition - position.x) < textSize.width) position.x = numberValue < 0 ? otherPosition - textSize.width - HORIZONTAL_PADDING : otherPosition + textSize.width + HORIZONTAL_PADDING;
10223
+ textsPositions[key].push(position.x);
10224
+ }
10225
+ const { strokeColor, textColor } = args.getTextColors(callbackArgs);
10226
+ if (!!strokeColor) {
10227
+ ctx.strokeStyle = strokeColor;
10228
+ ctx.lineWidth = 3;
10229
+ ctx.strokeText(valueToDisplay, position.x, position.y);
10230
+ }
10231
+ ctx.fillStyle = textColor;
10232
+ ctx.lineWidth = 1;
10233
+ ctx.fillText(valueToDisplay, position.x, position.y);
10213
10234
  }
10214
10235
  }
10236
+ ctx.restore();
10215
10237
  }
10216
- function drawBarChartValues(chart, options, ctx) {
10217
- const yMax = chart.chartArea.bottom;
10218
- const yMin = chart.chartArea.top;
10219
- for (const dataset of chart._metasets) {
10220
- if (isTrendLineAxis(dataset.xAxisID) || dataset.hidden) continue;
10221
- const yAxisScale = chart.scales[dataset.yAxisID];
10222
- for (let i = 0; i < dataset._parsed.length; i++) {
10223
- const parsedValue = dataset._parsed[i];
10224
- const value = Number(chart.config.type === "radar" ? parsedValue.r : parsedValue.y);
10225
- if (isNaN(value)) continue;
10226
- const point = dataset.data[i];
10227
- const xPosition = point.x;
10228
- let yPosition = 0;
10229
- const yZeroLine = yAxisScale.getPixelForValue(0);
10230
- const distanceFromAxisOrigin = Math.abs(yZeroLine - point.y);
10231
- const textHeight = globalThis.Chart?.defaults.font.size ?? 12;
10232
- if (distanceFromAxisOrigin < textHeight) yPosition = value < 0 ? yZeroLine + textHeight / 2 : yZeroLine - textHeight / 2;
10233
- else yPosition = value < 0 ? point.y - point.height / 2 : point.y + point.height / 2;
10234
- yPosition = Math.min(yPosition, yMax);
10235
- yPosition = Math.max(yPosition, yMin);
10236
- ctx.strokeStyle = point.options.backgroundColor;
10237
- ctx.fillStyle = options.background(Number(value), dataset, i) || "#ffffff";
10238
- const valueToDisplay = options.callback(Number(value), dataset, i);
10239
- const measures = ctx.measureText(valueToDisplay);
10240
- if (measures.actualBoundingBoxAscent + measures.actualBoundingBoxDescent + 2 > Math.abs(point.height) - 2) continue;
10241
- drawTextWithBackground(valueToDisplay, xPosition, yPosition, ctx);
10242
- }
10243
- }
10244
- }
10245
- function drawBubbleChartValues(chart, options, ctx) {
10246
- const yMax = chart.chartArea.bottom;
10247
- const yMin = chart.chartArea.top;
10248
- const textsPositions = {};
10249
- for (const dataset of chart._metasets) for (let i = 0; i < dataset._parsed.length; i++) {
10250
- const value = dataset._parsed[i].y;
10251
- if (isNaN(value)) continue;
10252
- const point = dataset.data[i];
10253
- const xPosition = point.x;
10254
- let yPosition = Math.max(Math.min(point.y, yMax), yMin);
10255
- if (!textsPositions[xPosition]) textsPositions[xPosition] = [];
10256
- for (const otherPosition of textsPositions[xPosition] || []) if (Math.abs(otherPosition - yPosition) < MINIMAL_VERTICAL_DISTANCE) yPosition = otherPosition + MINIMAL_VERTICAL_DISTANCE * (value < 0 ? 1 : -1);
10257
- textsPositions[xPosition].push(yPosition);
10258
- const color = point.options.backgroundColor ?? "#ffffff";
10259
- if (hexToHSLA(toHex(color)).a === 1) ctx.fillStyle = chartFontColor(color);
10260
- else ctx.fillStyle = "#000000";
10261
- const valueToDisplay = options.callback(Number(value), dataset, i);
10262
- ctx.fillText(valueToDisplay, xPosition, yPosition);
10263
- }
10264
- }
10265
- function drawHorizontalBarChartValues(chart, options, ctx) {
10266
- const textsPositions = {};
10267
- for (const dataset of chart._metasets) {
10268
- if (isTrendLineAxis(dataset.xAxisID) || isLineOverlayOnBarChart(options, dataset)) continue;
10269
- const xZeroLine = chart.scales[dataset.xAxisID].getPixelForValue(0);
10270
- for (let i = 0; i < dataset._parsed.length; i++) {
10271
- const value = Number(dataset._parsed[i].x);
10272
- if (isNaN(value)) continue;
10273
- const displayValue = options.callback(value, dataset, i);
10274
- const point = dataset.data[i];
10275
- const yPosition = point.y;
10276
- const textWidth = computeTextWidth(ctx, displayValue, { fontSize: globalThis.Chart?.defaults.font.size ?? 12 }, "px");
10277
- const distanceFromAxisOrigin = Math.abs(point.x - xZeroLine);
10278
- const PADDING = 3;
10238
+ function drawVerticalBarValues(chart, options) {
10239
+ drawValues({
10240
+ chart,
10241
+ options,
10242
+ direction: "vertical",
10243
+ getNumberValue: (dataset, i) => Number(dataset._parsed[i].y),
10244
+ getValuePosition: getVerticalBarValuePosition,
10245
+ shouldSkipValue: ({ dataset }) => isLineOverlayOnBarChart(options, dataset),
10246
+ getTextColors: chartBackgroundColoredTextWithElementColoredHalo
10247
+ });
10248
+ }
10249
+ function drawRadarValues(chart, options) {
10250
+ drawValues({
10251
+ chart,
10252
+ options,
10253
+ direction: "vertical",
10254
+ getNumberValue: (dataset, i) => Number(dataset._parsed[i].r),
10255
+ getValuePosition: ({ chartElement }) => ({
10256
+ x: chartElement.x,
10257
+ y: chartElement.y - 10
10258
+ }),
10259
+ shouldSkipValue: () => false,
10260
+ getTextColors: chartElementColoredTextWithChartBackgroundHalo
10261
+ });
10262
+ }
10263
+ function drawLineValues(chart, options) {
10264
+ drawValues({
10265
+ chart,
10266
+ options,
10267
+ direction: "vertical",
10268
+ getNumberValue: (dataset, i) => Number(dataset._parsed[i].y),
10269
+ getValuePosition: ({ chartElement }) => ({
10270
+ x: chartElement.x,
10271
+ y: chartElement.y - 10
10272
+ }),
10273
+ shouldSkipValue: () => false,
10274
+ getTextColors: chartElementColoredTextWithChartBackgroundHalo
10275
+ });
10276
+ }
10277
+ function drawComboValues(chart, options) {
10278
+ drawValues({
10279
+ chart,
10280
+ options,
10281
+ direction: "vertical",
10282
+ getNumberValue: (dataset, i) => Number(dataset._parsed[i].y),
10283
+ getValuePosition: (args) => args.dataset.type === "line" ? {
10284
+ x: args.chartElement.x,
10285
+ y: args.chartElement.y - 10
10286
+ } : getVerticalBarValuePosition(args),
10287
+ shouldSkipValue: () => false,
10288
+ getTextColors: (args) => args.dataset.type === "line" ? chartElementColoredTextWithChartBackgroundHalo(args) : chartBackgroundColoredTextWithElementColoredHalo(args)
10289
+ });
10290
+ }
10291
+ function drawCalendarValues(chart, options) {
10292
+ drawValues({
10293
+ chart,
10294
+ options,
10295
+ direction: "vertical",
10296
+ getNumberValue: (dataset, i) => dataset._parsed[i].y,
10297
+ getValuePosition: ({ chartElement }) => ({
10298
+ x: chartElement.x,
10299
+ y: chartElement.y + chartElement.height / 2
10300
+ }),
10301
+ shouldSkipValue: ({ chartElement, textSize }) => textSize.height + 2 > Math.abs(chartElement.height) - 2,
10302
+ getTextColors: ({ chartElement }) => ({
10303
+ strokeColor: void 0,
10304
+ textColor: chartFontColor(chartElement.options.backgroundColor)
10305
+ })
10306
+ });
10307
+ }
10308
+ function drawBubbleValues(chart, options) {
10309
+ const canDrawTextInsideBubble = (chartElement, textSize) => {
10310
+ const radius = chartElement.options.radius ?? globalThis.Chart?.defaults.elements.point.radius ?? 3;
10311
+ return textSize.height < radius * 2;
10312
+ };
10313
+ drawValues({
10314
+ chart,
10315
+ options,
10316
+ direction: "vertical",
10317
+ getNumberValue: (dataset, i) => dataset._parsed[i].y,
10318
+ getValuePosition: ({ chartElement, textSize }) => ({
10319
+ x: chartElement.x,
10320
+ y: canDrawTextInsideBubble(chartElement, textSize) ? chartElement.y : chartElement.y - 10
10321
+ }),
10322
+ shouldSkipValue: () => false,
10323
+ getTextColors: (args) => {
10324
+ return canDrawTextInsideBubble(args.chartElement, args.textSize) ? chartBackgroundColoredTextWithElementColoredHalo(args) : chartElementColoredTextWithChartBackgroundHalo(args);
10325
+ }
10326
+ });
10327
+ }
10328
+ function drawHorizontalBarValues(chart, options) {
10329
+ drawValues({
10330
+ chart,
10331
+ options,
10332
+ direction: "horizontal",
10333
+ getNumberValue: (dataset, i) => dataset._parsed[i].x,
10334
+ getValuePosition: ({ chartElement, numberValue, textSize, dataset }) => {
10335
+ const xZeroLine = chart.scales[dataset.xAxisID].getPixelForValue(0);
10336
+ const distanceFromAxisOrigin = Math.abs(chartElement.x - xZeroLine);
10279
10337
  let xPosition;
10280
- if (distanceFromAxisOrigin < textWidth) xPosition = value < 0 ? xZeroLine - textWidth / 2 - PADDING : xZeroLine + textWidth / 2 + PADDING;
10281
- else xPosition = value < 0 ? point.x + point.width / 2 : point.x - point.width / 2;
10282
- if (!textsPositions[yPosition]) textsPositions[yPosition] = [];
10283
- for (const otherPosition of textsPositions[yPosition]) if (Math.abs(otherPosition - xPosition) < textWidth) xPosition = value < 0 ? otherPosition - textWidth - PADDING : otherPosition + textWidth + PADDING;
10284
- textsPositions[yPosition].push(xPosition);
10285
- ctx.strokeStyle = point.options.backgroundColor;
10286
- ctx.fillStyle = options.background(Number(value), dataset, i) || "#ffffff";
10287
- drawTextWithBackground(displayValue, xPosition, yPosition, ctx);
10288
- }
10289
- }
10290
- }
10291
- function drawPieChartValues(chart, options, ctx) {
10292
- for (const dataset of chart._metasets) for (let i = 0; i < dataset._parsed.length; i++) {
10293
- const value = Number(dataset._parsed[i]);
10294
- if (isNaN(value) || value === 0) continue;
10295
- const bar = dataset.data[i];
10296
- const { startAngle, endAngle, innerRadius, outerRadius } = bar;
10297
- const midAngle = (startAngle + endAngle) / 2;
10298
- const midRadius = (innerRadius + outerRadius) / 2;
10299
- const x = bar.x + midRadius * Math.cos(midAngle);
10300
- const y = bar.y + midRadius * Math.sin(midAngle);
10301
- const displayValue = options.callback(value, dataset, i);
10302
- const textHeight = globalThis.Chart?.defaults.font.size ?? 12;
10303
- const textWidth = computeTextWidth(ctx, displayValue, { fontSize: textHeight }, "px");
10304
- const radius = outerRadius - innerRadius;
10305
- if (textWidth >= radius || radius < textHeight) continue;
10306
- const sliceAngle = endAngle - startAngle;
10307
- const midWidth = 2 * midRadius * Math.tan(sliceAngle / 2);
10308
- if (sliceAngle < Math.PI / 2 && (textWidth >= midWidth || midWidth < textHeight)) continue;
10309
- const background = options.background(Number(value), dataset, i);
10310
- ctx.fillStyle = chartFontColor(background);
10311
- ctx.strokeStyle = background || "#ffffff";
10312
- drawTextWithBackground(displayValue, x, y, ctx);
10313
- }
10338
+ const sign = numberValue < 0 ? -1 : 1;
10339
+ if (distanceFromAxisOrigin < textSize.width) xPosition = xZeroLine + sign * (textSize.width / 2 + HORIZONTAL_PADDING);
10340
+ else xPosition = chartElement.x - sign * (chartElement.width / 2);
10341
+ return {
10342
+ x: xPosition,
10343
+ y: chartElement.y
10344
+ };
10345
+ },
10346
+ shouldSkipValue: ({ dataset }) => isLineOverlayOnBarChart(options, dataset),
10347
+ getTextColors: chartBackgroundColoredTextWithElementColoredHalo
10348
+ });
10349
+ }
10350
+ function drawFunnelValues(chart, options) {
10351
+ drawValues({
10352
+ chart,
10353
+ options,
10354
+ direction: "horizontal",
10355
+ getNumberValue: (dataset, i) => dataset._parsed[i].x,
10356
+ getValuePosition: ({ chartElement }) => ({
10357
+ x: chartElement.x - chartElement.width / 2,
10358
+ y: chartElement.y
10359
+ }),
10360
+ shouldSkipValue: () => false,
10361
+ getTextColors: chartBackgroundColoredTextWithElementColoredHalo
10362
+ });
10363
+ }
10364
+ function drawPieValues(chart, options) {
10365
+ const getSliceDimensions = (chartElement) => {
10366
+ const { startAngle, endAngle, innerRadius, outerRadius } = chartElement;
10367
+ return {
10368
+ midAngle: (startAngle + endAngle) / 2,
10369
+ midRadius: (innerRadius + outerRadius) / 2
10370
+ };
10371
+ };
10372
+ drawValues({
10373
+ chart,
10374
+ options,
10375
+ direction: "vertical",
10376
+ getNumberValue: (dataset, i) => Number(dataset._parsed[i]),
10377
+ getValuePosition: ({ chartElement }) => {
10378
+ const { midAngle, midRadius } = getSliceDimensions(chartElement);
10379
+ return {
10380
+ x: chartElement.x + midRadius * Math.cos(midAngle),
10381
+ y: chartElement.y + midRadius * Math.sin(midAngle)
10382
+ };
10383
+ },
10384
+ shouldSkipValue: ({ chartElement, textSize }) => {
10385
+ const { midRadius } = getSliceDimensions(chartElement);
10386
+ const sliceAngle = chartElement.endAngle - chartElement.startAngle;
10387
+ const midWidth = 2 * midRadius * Math.tan(sliceAngle / 2);
10388
+ return sliceAngle < Math.PI / 2 && (textSize.width >= midWidth || midWidth < textSize.height);
10389
+ },
10390
+ getTextColors: chartBackgroundColoredTextWithElementColoredHalo
10391
+ });
10392
+ }
10393
+ function getTextDimensions(text, ctx) {
10394
+ return computeCachedTextDimension(ctx, text, computeTextFont({ fontSize: globalThis.Chart?.defaults.font.size ?? 12 }, "px"));
10395
+ }
10396
+ function chartBackgroundColoredTextWithElementColoredHalo(args) {
10397
+ const { dataset, numberValue, valueIndex, chartElement, options } = args;
10398
+ return {
10399
+ strokeColor: chartElement.options.backgroundColor,
10400
+ textColor: options.background(numberValue, dataset, valueIndex) || "#ffffff"
10401
+ };
10402
+ }
10403
+ function chartElementColoredTextWithChartBackgroundHalo(args) {
10404
+ const { dataset, numberValue, valueIndex, chartElement, options } = args;
10405
+ return {
10406
+ strokeColor: options.background(numberValue, dataset, valueIndex) || "#ffffff",
10407
+ textColor: chartElement.options.backgroundColor
10408
+ };
10409
+ }
10410
+ function getVerticalBarValuePosition(args) {
10411
+ const { chartElement, numberValue, dataset, textSize, chart } = args;
10412
+ const yZeroLine = chart.scales[dataset.yAxisID].getPixelForValue(0);
10413
+ const distanceFromAxisOrigin = Math.abs(yZeroLine - chartElement.y);
10414
+ const sign = numberValue < 0 ? -1 : 1;
10415
+ let yPosition = 0;
10416
+ if (distanceFromAxisOrigin < textSize.height) yPosition = yZeroLine - sign * (textSize.height / 2);
10417
+ else yPosition = chartElement.y + sign * (chartElement.height / 2);
10418
+ return {
10419
+ x: chartElement.x,
10420
+ y: yPosition
10421
+ };
10314
10422
  }
10315
10423
 
10316
10424
  //#endregion
@@ -11167,6 +11275,7 @@ function getRadarChartDatasets(definition, args) {
11167
11275
  hidden,
11168
11276
  borderColor,
11169
11277
  backgroundColor: borderColor,
11278
+ pointBackgroundColor: borderColor,
11170
11279
  pointRadius: definition.hideDataMarkers ? 0 : 3
11171
11280
  };
11172
11281
  if (fill) {
@@ -28634,23 +28743,11 @@ function getChartShowValues(definition, args) {
28634
28743
  }
28635
28744
  function getCalendarChartShowValues(definition, args) {
28636
28745
  const { locale, axisFormats } = args;
28637
- let background = (_value, dataset, index) => definition.background;
28638
- const values = args.dataSetsValues.flat().flatMap((dsv) => dsv?.data.filter(isNumberResult)).map((cell) => cell.value);
28639
- if (values.length) {
28640
- const min = Math.min(...values);
28641
- const max = Math.max(...values);
28642
- const colorScale = getRuntimeColorScale(definition.colorScale ?? schemeToColorScale("oranges"), min, max);
28643
- background = (_value, dataset, index) => {
28644
- const value = dataset._dataset.values[index];
28645
- if (value === void 0) return definition.background;
28646
- return chartFontColor(colorScale(value));
28647
- };
28648
- }
28649
28746
  return {
28650
28747
  type: "calendar",
28651
28748
  horizontal: false,
28652
28749
  showValues: "showValues" in definition ? !!definition.showValues : false,
28653
- background,
28750
+ background: () => definition.background,
28654
28751
  callback: (_value, dataset, index) => {
28655
28752
  const value = dataset._dataset.values[index];
28656
28753
  return value === void 0 ? "" : humanizeNumber({
@@ -53081,11 +53178,16 @@ var DefaultPlugin = class extends CorePlugin {
53081
53178
  const deltaStyle = {};
53082
53179
  let hasDelta = false;
53083
53180
  const styleSheet = this.style[position.sheetId];
53084
- if (!styleSheet) continue;
53085
53181
  for (const key in newDefaultStyle) {
53086
53182
  if (key in cellStyle) continue;
53087
- const defaults = styleSheet[key];
53088
- if (!defaults) continue;
53183
+ const defaults = styleSheet?.[key];
53184
+ if (!defaults) {
53185
+ if (newDefaultStyle[key] !== DEFAULT_STYLE[key]) {
53186
+ deltaStyle[key] = DEFAULT_STYLE[key];
53187
+ hasDelta = true;
53188
+ }
53189
+ continue;
53190
+ }
53089
53191
  const rowDefault = defaults.rowDefault?.[position.row];
53090
53192
  if (rowDefault !== void 0) {
53091
53193
  if (priorities.shouldUseDefaultRow) {
@@ -53127,7 +53229,8 @@ var DefaultPlugin = class extends CorePlugin {
53127
53229
  for (const key in styleSheet) if (!(key in style)) {
53128
53230
  const defaults = styleSheet[key];
53129
53231
  if (!defaults) continue;
53130
- style[key] = defaults.rowDefault?.[position.row] ?? defaults.colDefault?.[position.col] ?? defaults.sheetDefault;
53232
+ const styleValue = defaults.rowDefault?.[position.row] ?? defaults.colDefault?.[position.col] ?? defaults.sheetDefault;
53233
+ if (styleValue !== void 0) style[key] = styleValue;
53131
53234
  }
53132
53235
  return style;
53133
53236
  }
@@ -77246,8 +77349,8 @@ var DefaultClipboardHandler = class extends AbstractCellClipboardHandler {
77246
77349
  for (const key in DEFAULT_STYLE) {
77247
77350
  content.style[key] = {
77248
77351
  sheetDefault: this.getters.getDefaultStyle(data.sheetId, key, "SHEET", void 0) ?? DEFAULT_STYLE[key],
77249
- colDefault: {},
77250
- rowDefault: {}
77352
+ colDefault: [],
77353
+ rowDefault: []
77251
77354
  };
77252
77355
  let colIndex = 0;
77253
77356
  for (const col of data.columnsIndexes) {
@@ -77264,20 +77367,41 @@ var DefaultClipboardHandler = class extends AbstractCellClipboardHandler {
77264
77367
  }
77265
77368
  return content;
77266
77369
  }
77267
- clearStyleFormat(sheetId, zone) {
77268
- this.dispatch("SET_FORMATTING", {
77269
- sheetId,
77270
- target: [zone],
77271
- format: ""
77272
- });
77370
+ adaptContentToZone(zone, content) {
77371
+ const colRepetition = Math.max(Math.floor((zone.right - zone.left + 1) / content.width), 1);
77372
+ const rowRepetition = Math.max(Math.floor((zone.bottom - zone.top + 1) / content.height), 1);
77373
+ if (colRepetition === 1 && rowRepetition === 1) return content;
77374
+ const newContent = deepCopy(content);
77375
+ newContent.height *= rowRepetition;
77376
+ newContent.width *= colRepetition;
77377
+ if (rowRepetition > 1 && newContent.format.rowDefault) {
77378
+ newContent.format.rowDefault.length = content.height;
77379
+ newContent.format.rowDefault = repeat(newContent.format.rowDefault, rowRepetition);
77380
+ }
77381
+ if (colRepetition > 1 && newContent.format.colDefault) {
77382
+ newContent.format.colDefault.length = content.width;
77383
+ newContent.format.colDefault = repeat(newContent.format.colDefault, colRepetition);
77384
+ }
77385
+ for (const key in content.style) {
77386
+ if (rowRepetition > 1 && newContent.style[key].rowDefault) {
77387
+ newContent.style[key].rowDefault.length = content.height;
77388
+ newContent.style[key].rowDefault = repeat(newContent.style[key].rowDefault, rowRepetition);
77389
+ }
77390
+ if (colRepetition > 1 && newContent.style[key].colDefault) {
77391
+ newContent.style[key].colDefault.length = content.width;
77392
+ newContent.style[key].colDefault = repeat(newContent.style[key].colDefault, colRepetition);
77393
+ }
77394
+ }
77395
+ return newContent;
77273
77396
  }
77274
77397
  paste(target, content, options) {
77275
77398
  const sheetId = target.sheetId;
77276
77399
  if (options.pasteOption === "asValue") return;
77277
77400
  const zones = target.zones;
77278
- if (!options.isCutOperation) for (const zone of zones) for (const pasteZone of splitZoneForPaste(zone, content.width, content.height)) {
77279
- this.pasteStyle(sheetId, pasteZone.left, pasteZone.top, content.width, content.height, content.style);
77280
- this.pasteFormat(sheetId, pasteZone.left, pasteZone.top, content.width, content.height, content.format);
77401
+ if (!options.isCutOperation) for (const zone of zones) {
77402
+ const newContent = this.adaptContentToZone(zone, content);
77403
+ this.pasteStyle(sheetId, zone.left, zone.top, newContent.width, newContent.height, newContent.style);
77404
+ this.pasteFormat(sheetId, zone.left, zone.top, newContent.width, newContent.height, newContent.format);
77281
77405
  }
77282
77406
  else {
77283
77407
  this.clearClippedZones(content);
@@ -77390,7 +77514,7 @@ var DefaultClipboardHandler = class extends AbstractCellClipboardHandler {
77390
77514
  const commands = [];
77391
77515
  for (const [zoneStr, [zone, priority]] of Object.entries(zones)) {
77392
77516
  const format = updateCells[zoneStr];
77393
- commands.push([
77517
+ if (format !== void 0) commands.push([
77394
77518
  priority,
77395
77519
  zone,
77396
77520
  format
@@ -87819,6 +87943,6 @@ exports.stores = stores;
87819
87943
  exports.tokenColors = tokenColors;
87820
87944
  exports.tokenize = tokenize;
87821
87945
 
87822
- __info__.version = "19.5.0-alpha.2";
87823
- __info__.date = "2026-07-13T06:26:20.354Z";
87824
- __info__.hash = "a4d2f90";
87946
+ __info__.version = "19.5.0-alpha.3";
87947
+ __info__.date = "2026-07-14T10:17:06.949Z";
87948
+ __info__.hash = "c029184";
@@ -2,9 +2,9 @@
2
2
  /*
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 19.5.0-alpha.2
6
- * @date 2026-07-13T06:26:22.099Z
7
- * @hash a4d2f90
5
+ * @version 19.5.0-alpha.3
6
+ * @date 2026-07-14T10:17:08.642Z
7
+ * @hash c029184
8
8
  */
9
9
  :root {
10
10
  --os-gray-100: light-dark(#f9fafb, #1b1d26);