@oicl/openbridge-webcomponents 2.0.0-next.94 → 2.0.0-next.95

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.
@@ -33087,6 +33087,60 @@ function generateLegendHTML(legendItems) {
33087
33087
  `
33088
33088
  ).join("");
33089
33089
  }
33090
+ var XValueMode = /* @__PURE__ */ ((XValueMode2) => {
33091
+ XValueMode2["time"] = "time";
33092
+ XValueMode2["number"] = "number";
33093
+ return XValueMode2;
33094
+ })(XValueMode || {});
33095
+ function isTemporalEpochLike(v2) {
33096
+ return typeof v2.epochMilliseconds === "number";
33097
+ }
33098
+ function isTemporalPlainLike(v2) {
33099
+ const t2 = v2;
33100
+ return typeof t2.year === "number" && typeof t2.month === "number" && typeof t2.day === "number";
33101
+ }
33102
+ function normalizeXValue(v2, mode) {
33103
+ if (typeof v2 === "number") {
33104
+ return Number.isFinite(v2) ? v2 : NaN;
33105
+ }
33106
+ if (v2 instanceof Date) {
33107
+ return v2.getTime();
33108
+ }
33109
+ if (typeof v2 === "object" && v2 !== null) {
33110
+ if (isTemporalEpochLike(v2)) return v2.epochMilliseconds;
33111
+ if (isTemporalPlainLike(v2)) {
33112
+ return new Date(
33113
+ v2.year,
33114
+ v2.month - 1,
33115
+ v2.day,
33116
+ v2.hour ?? 0,
33117
+ v2.minute ?? 0,
33118
+ v2.second ?? 0,
33119
+ v2.millisecond ?? 0
33120
+ ).getTime();
33121
+ }
33122
+ return NaN;
33123
+ }
33124
+ if (typeof v2 === "string") {
33125
+ if (v2.trim() === "") return NaN;
33126
+ if (mode === "time") {
33127
+ const parsed = Date.parse(v2);
33128
+ if (Number.isFinite(parsed)) return parsed;
33129
+ }
33130
+ const numeric = Number(v2);
33131
+ return Number.isFinite(numeric) ? numeric : NaN;
33132
+ }
33133
+ return NaN;
33134
+ }
33135
+ function formatXValue(value, mode, relativeToMs) {
33136
+ if (!Number.isFinite(value)) return "";
33137
+ if (mode === "number") return String(value);
33138
+ if (relativeToMs !== void 0 && Number.isFinite(relativeToMs)) {
33139
+ const minutes = Math.round((value - relativeToMs) / 6e4);
33140
+ return `${minutes}min`;
33141
+ }
33142
+ return new Date(value).toLocaleDateString();
33143
+ }
33090
33144
  var TickmarkType$1 = /* @__PURE__ */ ((TickmarkType2) => {
33091
33145
  TickmarkType2["zeroLineThick"] = "zeroLineThick";
33092
33146
  TickmarkType2["zeroLine"] = "zeroLine";
@@ -35037,6 +35091,7 @@ Chart.register(
35037
35091
  var XAxisType = /* @__PURE__ */ ((XAxisType2) => {
35038
35092
  XAxisType2["category"] = "category";
35039
35093
  XAxisType2["time"] = "time";
35094
+ XAxisType2["number"] = "number";
35040
35095
  return XAxisType2;
35041
35096
  })(XAxisType || {});
35042
35097
  var YAxisPosition = /* @__PURE__ */ ((YAxisPosition2) => {
@@ -35179,6 +35234,23 @@ const _ObcChartLineBase = class _ObcChartLineBase extends i$4 {
35179
35234
  }, 16);
35180
35235
  };
35181
35236
  }
35237
+ /** @internal - True when the x-axis positions points by numeric value. */
35238
+ get isNumericXAxis() {
35239
+ return this.xAxisType === "time" || this.xAxisType === "number";
35240
+ }
35241
+ /** @internal - Normalization mode for the current x-axis type. */
35242
+ get xValueMode() {
35243
+ return this.xAxisType === "number" ? XValueMode.number : XValueMode.time;
35244
+ }
35245
+ /** @internal - Warn once per data assignment about unparseable x-values. */
35246
+ warnOnInvalidX(xValues, sourceRef) {
35247
+ const invalid = xValues.filter((x2) => !Number.isFinite(x2)).length;
35248
+ if (invalid === 0 || this.lastWarnedXSource === sourceRef) return;
35249
+ this.lastWarnedXSource = sourceRef;
35250
+ console.warn(
35251
+ `[obc-chart] ${invalid} x value(s) could not be parsed for xAxisType='${this.xAxisType}'; the points render as gaps.`
35252
+ );
35253
+ }
35182
35254
  /**
35183
35255
  * Should fill be applied to this chart?
35184
35256
  * Line graph returns false, area graph returns true.
@@ -36015,8 +36087,8 @@ const _ObcChartLineBase = class _ObcChartLineBase extends i$4 {
36015
36087
  */
36016
36088
  buildDataset(data, index2, chartColors, totalCount = 1) {
36017
36089
  const currentColor = chartColors[index2 % chartColors.length];
36018
- const existingDataset = "data" in data ? data : null;
36019
- const values = existingDataset ? null : data;
36090
+ const existingDataset = Array.isArray(data) ? null : data;
36091
+ const values = Array.isArray(data) ? data : null;
36020
36092
  const borderColor = existingDataset?.borderColor ?? currentColor;
36021
36093
  const fillFlag = existingDataset?.fill ?? this.shouldApplyFill();
36022
36094
  const tension = this.lineMode === "smooth" ? this.DEFAULT_TENSION : 0;
@@ -36064,14 +36136,18 @@ const _ObcChartLineBase = class _ObcChartLineBase extends i$4 {
36064
36136
  return result;
36065
36137
  }
36066
36138
  /**
36067
- * Create threshold mode datasets: invisible baseline + main dataset with above/below fills
36139
+ * Create threshold mode datasets: invisible baseline + main dataset with
36140
+ * above/below fills. Accepts plain values (category mode) or {x, y} points
36141
+ * (time/number mode); the baseline mirrors the input x-positions.
36068
36142
  */
36069
36143
  createThresholdDatasets(values, chartColors) {
36070
- const numericValues = values.map((v2) => Number(v2)).filter((n3) => Number.isFinite(n3));
36071
- const minV = numericValues.length ? Math.min(...numericValues) : 0;
36072
- const maxV = numericValues.length ? Math.max(...numericValues) : 100;
36144
+ const yValues = values.map((v2) => typeof v2 === "number" ? v2 : v2.y).filter((n3) => Number.isFinite(n3));
36145
+ const minV = yValues.length ? Math.min(...yValues) : 0;
36146
+ const maxV = yValues.length ? Math.max(...yValues) : 100;
36073
36147
  const threshold = (minV + maxV) / 2;
36074
- const baselineData = numericValues.map(() => threshold);
36148
+ const baselineData = values.map(
36149
+ (v2) => typeof v2 === "number" ? threshold : { x: v2.x, y: threshold }
36150
+ );
36075
36151
  const lowRaw = LINE_GRAPH_GRID_CONFIG.thresholdLowColorVar;
36076
36152
  const highRaw = LINE_GRAPH_GRID_CONFIG.thresholdHighColorVar;
36077
36153
  const highFill = applyAlphaToColor(this, highRaw, 0.35);
@@ -36097,7 +36173,9 @@ const _ObcChartLineBase = class _ObcChartLineBase extends i$4 {
36097
36173
  return [baselineDataset, main];
36098
36174
  }
36099
36175
  /**
36100
- * Prepare normalized datasets for multi-series charts
36176
+ * Prepare normalized datasets for multi-series charts.
36177
+ * In time/number mode every point's x is normalized (epoch ms / number)
36178
+ * so strings, Dates and Temporal objects position correctly.
36101
36179
  */
36102
36180
  prepareMultiSeriesDatasets() {
36103
36181
  const defaultPalette = this.priority === Priority.enhanced ? CHART_SECTOR_ENHANCED_COLORS : CHART_SECTOR_DEFAULT_COLORS;
@@ -36106,18 +36184,37 @@ const _ObcChartLineBase = class _ObcChartLineBase extends i$4 {
36106
36184
  this.colors,
36107
36185
  defaultPalette
36108
36186
  );
36187
+ const normalized = this.datasets.map((ds) => this.normalizeDatasetX(ds));
36188
+ if (this.isNumericXAxis) {
36189
+ this.warnOnInvalidX(
36190
+ normalized.flatMap(
36191
+ (ds) => (ds.data ?? []).map(
36192
+ (pt) => pt && typeof pt === "object" ? pt.x : 0
36193
+ )
36194
+ ),
36195
+ this.datasets
36196
+ );
36197
+ }
36109
36198
  const totalCount = this.datasets.length;
36110
- return this.datasets.map(
36199
+ return normalized.map(
36111
36200
  (ds, i4) => this.buildDataset(ds, i4, chartColors, totalCount)
36112
36201
  );
36113
36202
  }
36203
+ /** @internal - Return a copy of the dataset with normalized point x-values. */
36204
+ normalizeDatasetX(ds) {
36205
+ if (!this.isNumericXAxis || !ds.data) return ds;
36206
+ const data = ds.data.map(
36207
+ (pt) => pt && typeof pt === "object" && "x" in pt ? { ...pt, x: normalizeXValue(pt.x, this.xValueMode) } : pt
36208
+ );
36209
+ return { ...ds, data };
36210
+ }
36114
36211
  /**
36115
- * Prepare datasets for single-series charts
36116
- * Handles both regular and threshold fill modes
36212
+ * Prepare datasets for single-series charts.
36213
+ * Category mode: labels + numeric values (unchanged legacy path).
36214
+ * Time/number mode: normalized {x, y} points on a linear scale.
36215
+ * Handles both regular and threshold fill modes.
36117
36216
  */
36118
36217
  prepareSingleSeriesDatasets() {
36119
- const values = this.data.map((d2) => d2.value);
36120
- const labels = this.data.map((d2) => d2.label);
36121
36218
  const defaultPalette = this.priority === Priority.enhanced ? CHART_SECTOR_ENHANCED_COLORS : CHART_SECTOR_DEFAULT_COLORS;
36122
36219
  const chartColors = getChartColorsOrDefault(
36123
36220
  this,
@@ -36126,6 +36223,20 @@ const _ObcChartLineBase = class _ObcChartLineBase extends i$4 {
36126
36223
  );
36127
36224
  const fill2 = this.shouldApplyFill();
36128
36225
  const fillMode = this.getFillMode();
36226
+ if (this.isNumericXAxis) {
36227
+ const points2 = this.data.map((d2) => ({
36228
+ x: normalizeXValue(d2.x ?? d2.label ?? NaN, this.xValueMode),
36229
+ y: d2.value
36230
+ }));
36231
+ this.warnOnInvalidX(
36232
+ points2.map((p2) => p2.x),
36233
+ this.data
36234
+ );
36235
+ const datasets2 = fill2 && fillMode === "threshold" ? this.createThresholdDatasets(points2, chartColors) : [this.buildDataset(points2, 0, chartColors)];
36236
+ return { datasets: datasets2, labels: [] };
36237
+ }
36238
+ const values = this.data.map((d2) => d2.value);
36239
+ const labels = this.data.map((d2) => d2.label ?? String(d2.x ?? ""));
36129
36240
  const datasets = fill2 && fillMode === "threshold" ? this.createThresholdDatasets(values, chartColors) : [this.buildDataset(values, 0, chartColors)];
36130
36241
  return { datasets, labels };
36131
36242
  }
@@ -36190,10 +36301,15 @@ const _ObcChartLineBase = class _ObcChartLineBase extends i$4 {
36190
36301
  callbacks: {
36191
36302
  title: () => "",
36192
36303
  label: (context) => {
36193
- const label = context.label ?? "";
36194
36304
  const value = typeof context.parsed === "object" && context.parsed !== null ? context.parsed.y : context.parsed;
36195
36305
  const numericValue = formatNumericValue$1(value, 1, false, 0);
36196
36306
  const unit = this.unit ? `${this.unit}` : "";
36307
+ let label = context.label ?? "";
36308
+ if (this.isNumericXAxis) {
36309
+ const x2 = typeof context.parsed === "object" && context.parsed !== null ? context.parsed.x : NaN;
36310
+ const relativeTo = this.timeDisplay === "minutes" ? refTs : void 0;
36311
+ label = formatXValue(x2, this.xValueMode, relativeTo);
36312
+ }
36197
36313
  return `${label} ${numericValue}${unit}`;
36198
36314
  }
36199
36315
  }
@@ -36208,18 +36324,23 @@ const _ObcChartLineBase = class _ObcChartLineBase extends i$4 {
36208
36324
  * Returns earliest timestamp for 'date' mode, latest for 'minutes' mode.
36209
36325
  */
36210
36326
  computeTimeReference() {
36327
+ if (this.xAxisType !== "time") return void 0;
36211
36328
  const timestamps = [];
36212
36329
  if (this.datasets?.length) {
36213
36330
  this.datasets.forEach((ds) => {
36214
36331
  if (!ds.data) return;
36215
36332
  ds.data.forEach((pt) => {
36216
36333
  if (pt && typeof pt === "object" && "x" in pt) {
36217
- const xVal = pt.x;
36218
- const ts = typeof xVal === "string" ? new Date(String(xVal)).getTime() : Number(xVal);
36334
+ const ts = normalizeXValue(pt.x, XValueMode.time);
36219
36335
  if (Number.isFinite(ts)) timestamps.push(ts);
36220
36336
  }
36221
36337
  });
36222
36338
  });
36339
+ } else if (this.data?.length) {
36340
+ this.data.forEach((d2) => {
36341
+ const ts = normalizeXValue(d2.x ?? d2.label ?? NaN, XValueMode.time);
36342
+ if (Number.isFinite(ts)) timestamps.push(ts);
36343
+ });
36223
36344
  }
36224
36345
  if (!timestamps.length && this.labels?.length) {
36225
36346
  this.labels.forEach((l2) => {
@@ -36269,7 +36390,7 @@ const _ObcChartLineBase = class _ObcChartLineBase extends i$4 {
36269
36390
  const showTicks = showTickMarks && !isTooSmall && this.hasLabelPadding;
36270
36391
  const fontConfig = { family: fontFamily, size: fontSize, weight: fontWeight };
36271
36392
  const x2 = {
36272
- type: this.xAxisType === "time" ? "linear" : "category",
36393
+ type: this.xAxisType === "category" ? "category" : "linear",
36273
36394
  offset: false,
36274
36395
  // Always edge-to-edge (no padding on x-axis)
36275
36396
  grace: 0,
@@ -36293,14 +36414,11 @@ const _ObcChartLineBase = class _ObcChartLineBase extends i$4 {
36293
36414
  maxTicksLimit: this.xTicksLimit,
36294
36415
  stepSize: this.xStepSize,
36295
36416
  callback: (value) => {
36296
- if (this.xAxisType !== "time") return String(value);
36417
+ if (!this.isNumericXAxis) return String(value);
36297
36418
  const n3 = Number(value);
36298
36419
  if (!Number.isFinite(n3)) return String(value);
36299
- if (this.timeDisplay === "minutes" && minX !== void 0 && Number.isFinite(minX)) {
36300
- const minutes = Math.round((n3 - minX) / 6e4);
36301
- return `${minutes}min`;
36302
- }
36303
- return new Date(n3).toLocaleDateString();
36420
+ const relativeTo = this.timeDisplay === "minutes" ? minX : void 0;
36421
+ return formatXValue(n3, this.xValueMode, relativeTo);
36304
36422
  }
36305
36423
  },
36306
36424
  border: {
@@ -37258,6 +37376,7 @@ let ObcGaugeTrend = class extends SetpointMixin(ObcChartLineBase) {
37258
37376
  constructor() {
37259
37377
  super();
37260
37378
  this._isFirstUpdate = false;
37379
+ this._explicitXAxisType = false;
37261
37380
  this.scaleType = ScaleType.regular;
37262
37381
  this.minValue = 0;
37263
37382
  this.maxValue = 100;
@@ -37389,6 +37508,17 @@ let ObcGaugeTrend = class extends SetpointMixin(ObcChartLineBase) {
37389
37508
  return false;
37390
37509
  }
37391
37510
  willUpdate(changed) {
37511
+ if (changed.has("xAxisType") && this.xAxisType !== this._autoAppliedXAxisType && (this.hasUpdated || this.xAxisType !== XAxisType.category)) {
37512
+ this._explicitXAxisType = true;
37513
+ }
37514
+ if (!this._explicitXAxisType && changed.has("data")) {
37515
+ const allHaveX = (this.data?.length ?? 0) > 0 && this.data.every((d2) => d2.x != null);
37516
+ const target = allHaveX ? XAxisType.time : XAxisType.category;
37517
+ if (this.xAxisType !== target) {
37518
+ this._autoAppliedXAxisType = target;
37519
+ this.xAxisType = target;
37520
+ }
37521
+ }
37392
37522
  super.willUpdate(changed);
37393
37523
  if (changed.has("chartMinValue") || changed.has("chartMaxValue") || changed.has("minValue") || changed.has("maxValue")) {
37394
37524
  const chartMin = this.chartMinValue ?? this.minValue;