@embeddable.com/remarkable-ui 0.1.15 → 0.1.16
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.
- package/dist/BarChartDefaultHorizontalPro.js +1 -1
- package/dist/BarChartDefaultPro.js +1 -1
- package/dist/BarChartGroupedHorizontalPro.js +1 -1
- package/dist/BarChartGroupedPro.js +1 -1
- package/dist/BarChartStackedHorizontalPro.js +1 -1
- package/dist/BarChartStackedPro.js +1 -1
- package/dist/ComparisonPeriod.type.emb-BHz2X91i.js +14 -0
- package/dist/ComparisonPeriod.type.emb-BHz2X91i.js.map +1 -0
- package/dist/ComparisonPeriodSelectFieldPro.js +1 -1
- package/dist/DonutChartPro.js +1 -1
- package/dist/DonutLabelChartPro.js +1 -1
- package/dist/KpiChart-B2OqbXRg.js +79 -0
- package/dist/KpiChart-B2OqbXRg.js.map +1 -0
- package/dist/KpiChartNumberComparisonPro.js +58 -50
- package/dist/KpiChartNumberComparisonPro.js.map +1 -1
- package/dist/KpiChartNumberPro.js +1 -1
- package/dist/PieChartPro.js +1 -1
- package/dist/{charts.fillGaps.hooks-BFmuMVNT.js → charts.fillGaps.hooks-C5Gy3QoW.js} +146 -130
- package/dist/charts.fillGaps.hooks-C5Gy3QoW.js.map +1 -0
- package/dist/embeddable-components.json +6 -6
- package/dist/embeddable-theme-2b917.js +1 -1
- package/dist/embeddable-types-4ace4.js +4 -5
- package/dist/embeddable-types.js.map +1 -1
- package/dist/{index-DEzAFKmN.js → index-BOzeG3mG.js} +2 -2
- package/dist/{index-DEzAFKmN.js.map → index-BOzeG3mG.js.map} +1 -1
- package/dist/{index-Dwb4Z6Hd.js → index-Chlmh1dF.js} +2 -2
- package/dist/{index-Dwb4Z6Hd.js.map → index-Chlmh1dF.js.map} +1 -1
- package/dist/{index-BhW48cz5.js → index-CjS39lkd.js} +2 -2
- package/dist/{index-BhW48cz5.js.map → index-CjS39lkd.js.map} +1 -1
- package/dist/index.js +6 -6
- package/dist/{object.utils-C6JIOYmv.js → object.utils-9RGrU0vr.js} +2 -2
- package/dist/object.utils-9RGrU0vr.js.map +1 -0
- package/dist/{pies.utils-CSx7w1mv.js → pies.utils-BecIV2nV.js} +2 -2
- package/dist/{pies.utils-CSx7w1mv.js.map → pies.utils-BecIV2nV.js.map} +1 -1
- package/dist/remarkable-pro/components/charts/bars/bars.utils.d.ts.map +1 -1
- package/dist/remarkable-pro/components/charts/kpis/KpiChartNumberComparisonPro/index.d.ts +1 -0
- package/dist/remarkable-pro/components/charts/kpis/KpiChartNumberComparisonPro/index.d.ts.map +1 -1
- package/dist/remarkable-ui/charts/kpis/KpiChart.d.ts.map +1 -1
- package/dist/remarkable-ui/charts/kpis/KpiChart.types.d.ts +1 -0
- package/dist/remarkable-ui/charts/kpis/KpiChart.types.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/ComparisonPeriod.type.emb-61HEPz26.js +0 -15
- package/dist/ComparisonPeriod.type.emb-61HEPz26.js.map +0 -1
- package/dist/KpiChart-CzUK0Dgw.js +0 -77
- package/dist/KpiChart-CzUK0Dgw.js.map +0 -1
- package/dist/charts.fillGaps.hooks-BFmuMVNT.js.map +0 -1
- package/dist/object.utils-C6JIOYmv.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { B as f, C as O, D as Q, m as I, E as R, F as J, G as X, L as tt, H as et, I as at, J as rt, K as st, M as nt, j as N, N as ot, O as lt, P as it, Q as L, R as ct } from "./component.constants-Bn9l4N1t.js";
|
|
2
2
|
import { useRef as dt, useMemo as ut } from "react";
|
|
3
|
-
import { r as mt, g as W, a as ft, b as H } from "./object.utils-
|
|
3
|
+
import { r as mt, g as W, a as ft, b as H } from "./object.utils-9RGrU0vr.js";
|
|
4
4
|
import { g as Y } from "./formatter.utils-Ba_5cIcm.js";
|
|
5
5
|
import { d as D } from "./utc-B2gCnkBk.js";
|
|
6
6
|
import { useTheme as ht } from "@embeddable.com/react";
|
|
@@ -73,20 +73,20 @@ const j = {
|
|
|
73
73
|
return {
|
|
74
74
|
...t,
|
|
75
75
|
datasets: (e = t.datasets) == null ? void 0 : e.map((a, n) => {
|
|
76
|
-
const
|
|
76
|
+
const s = R[n % R.length], r = {
|
|
77
77
|
...a,
|
|
78
|
-
backgroundColor:
|
|
79
|
-
borderColor:
|
|
78
|
+
backgroundColor: s,
|
|
79
|
+
borderColor: s
|
|
80
80
|
};
|
|
81
|
-
return I(
|
|
81
|
+
return I(r, a);
|
|
82
82
|
})
|
|
83
83
|
};
|
|
84
84
|
}, G = (t, e) => e && t.datasetIndex === t.chart.data.datasets.length - 1 ? "auto" : !1, z = (t, e) => {
|
|
85
|
-
const { datasets: a } = e.chart.data, n = e.dataIndex,
|
|
86
|
-
const
|
|
87
|
-
return
|
|
85
|
+
const { datasets: a } = e.chart.data, n = e.dataIndex, s = a.reduce((r, o) => {
|
|
86
|
+
const l = o.data[n];
|
|
87
|
+
return r + (l || 0);
|
|
88
88
|
}, 0);
|
|
89
|
-
return
|
|
89
|
+
return s > 0 ? s : "";
|
|
90
90
|
}, pt = (t) => I(j, {
|
|
91
91
|
indexAxis: "x",
|
|
92
92
|
plugins: {
|
|
@@ -186,15 +186,15 @@ const j = {
|
|
|
186
186
|
horizontal: e = !1,
|
|
187
187
|
showLegend: a = !1,
|
|
188
188
|
showTooltips: n = !0,
|
|
189
|
-
showValueLabels:
|
|
190
|
-
showTotalLabels:
|
|
191
|
-
} = t,
|
|
192
|
-
return I(
|
|
189
|
+
showValueLabels: s = !1,
|
|
190
|
+
showTotalLabels: r = !1
|
|
191
|
+
} = t, l = (e ? Dt : pt)(t);
|
|
192
|
+
return I(l, {
|
|
193
193
|
layout: {
|
|
194
194
|
padding: {
|
|
195
195
|
// Hack: dataLabels can get cut off if they are at the edge of the chart
|
|
196
|
-
top: !e && (
|
|
197
|
-
right: e && (
|
|
196
|
+
top: !e && (s || r) ? 30 : 0,
|
|
197
|
+
right: e && (s || r) ? 30 : 0
|
|
198
198
|
}
|
|
199
199
|
},
|
|
200
200
|
elements: {
|
|
@@ -206,7 +206,7 @@ const j = {
|
|
|
206
206
|
plugins: {
|
|
207
207
|
legend: { display: a },
|
|
208
208
|
datalabels: {
|
|
209
|
-
display: (c) =>
|
|
209
|
+
display: (c) => s && c.dataset.data[c.dataIndex] !== 0 ? "auto" : !1
|
|
210
210
|
},
|
|
211
211
|
tooltip: {
|
|
212
212
|
enabled: n
|
|
@@ -215,23 +215,23 @@ const j = {
|
|
|
215
215
|
});
|
|
216
216
|
};
|
|
217
217
|
J.register(X, tt, et, at, rt, st, nt);
|
|
218
|
-
const
|
|
219
|
-
const
|
|
220
|
-
const c = it(
|
|
218
|
+
const Ut = ({ data: t, onSegmentClick: e, options: a = {}, ...n }) => {
|
|
219
|
+
const s = dt(null), r = I(yt(n), a), o = (l) => {
|
|
220
|
+
const c = it(l, s);
|
|
221
221
|
e == null || e(c);
|
|
222
222
|
};
|
|
223
223
|
return /* @__PURE__ */ N.jsx("div", { className: ot.chartContainer, children: /* @__PURE__ */ N.jsx(
|
|
224
224
|
lt,
|
|
225
225
|
{
|
|
226
|
-
ref:
|
|
226
|
+
ref: s,
|
|
227
227
|
data: gt(t),
|
|
228
|
-
options:
|
|
228
|
+
options: r,
|
|
229
229
|
onClick: o
|
|
230
230
|
}
|
|
231
231
|
) });
|
|
232
|
-
},
|
|
233
|
-
const a = Y(e), { data: n = [], dimension:
|
|
234
|
-
const
|
|
232
|
+
}, _t = (t, e) => {
|
|
233
|
+
const a = Y(e), { data: n = [], dimension: s, groupDimension: r, measure: o } = t, l = [...new Set(n.map((d) => d[s.name]).filter(Boolean))].sort(), c = [...new Set(n.map((d) => d[r.name]))], u = W(e), h = c.map((d, x) => {
|
|
234
|
+
const v = H(
|
|
235
235
|
`${u}.charts.backgroundColors`,
|
|
236
236
|
d,
|
|
237
237
|
e.charts.backgroundColors ?? R,
|
|
@@ -243,67 +243,83 @@ const Lt = ({ data: t, onSegmentClick: e, options: a = {}, ...n }) => {
|
|
|
243
243
|
x
|
|
244
244
|
);
|
|
245
245
|
return {
|
|
246
|
-
label: a.data(
|
|
247
|
-
backgroundColor:
|
|
246
|
+
label: a.data(r, d),
|
|
247
|
+
backgroundColor: v,
|
|
248
248
|
borderColor: A,
|
|
249
|
-
data:
|
|
250
|
-
const
|
|
251
|
-
(b) => b[
|
|
249
|
+
data: l.map((C) => {
|
|
250
|
+
const k = n.find(
|
|
251
|
+
(b) => b[r.name] === d && b[s.name] === C
|
|
252
252
|
);
|
|
253
|
-
return
|
|
253
|
+
return k ? Number(k[o.name]) : 0;
|
|
254
254
|
})
|
|
255
255
|
};
|
|
256
256
|
});
|
|
257
257
|
return {
|
|
258
|
-
labels:
|
|
258
|
+
labels: l.map((d) => a.data(s, d)),
|
|
259
259
|
datasets: h
|
|
260
260
|
};
|
|
261
|
-
},
|
|
261
|
+
}, Ft = (t, e = mt) => {
|
|
262
262
|
const a = Y(e);
|
|
263
263
|
if (!t.data)
|
|
264
264
|
return {
|
|
265
265
|
labels: [],
|
|
266
266
|
datasets: [{ data: [] }]
|
|
267
267
|
};
|
|
268
|
-
const n = W(e),
|
|
268
|
+
const n = W(e), s = ft(t.data, t.dimension, t.measures, t.maxItems);
|
|
269
269
|
return {
|
|
270
|
-
labels:
|
|
271
|
-
const o =
|
|
272
|
-
return o ===
|
|
270
|
+
labels: s.map((r) => {
|
|
271
|
+
const o = r[t.dimension.name], l = a.data(t.dimension, o);
|
|
272
|
+
return o === l ? ct.t(o) : l;
|
|
273
273
|
}),
|
|
274
|
-
datasets: t.measures.map((
|
|
275
|
-
const
|
|
274
|
+
datasets: t.measures.map((r, o) => {
|
|
275
|
+
const l = H(
|
|
276
276
|
`${n}.charts.backgroundColors`,
|
|
277
|
-
|
|
277
|
+
r.name,
|
|
278
278
|
e.charts.backgroundColors ?? L,
|
|
279
279
|
o
|
|
280
280
|
), c = H(
|
|
281
281
|
`${n}.charts.borderColors`,
|
|
282
|
-
|
|
282
|
+
r.name,
|
|
283
283
|
e.charts.borderColors ?? L,
|
|
284
284
|
o
|
|
285
285
|
);
|
|
286
286
|
return {
|
|
287
|
-
label: a.dimensionOrMeasureTitle(
|
|
288
|
-
data:
|
|
289
|
-
backgroundColor:
|
|
287
|
+
label: a.dimensionOrMeasureTitle(r),
|
|
288
|
+
data: s.map((u) => u[r.name]),
|
|
289
|
+
backgroundColor: l,
|
|
290
290
|
borderColor: c
|
|
291
291
|
};
|
|
292
292
|
})
|
|
293
293
|
};
|
|
294
|
-
},
|
|
295
|
-
const {
|
|
294
|
+
}, Tt = (t, e) => {
|
|
295
|
+
const { datasets: a } = t.chart.data, n = t.dataIndex, s = a.reduce((r, o) => {
|
|
296
|
+
const l = o.data[n];
|
|
297
|
+
return r + (l || 0);
|
|
298
|
+
}, 0);
|
|
299
|
+
return e(s);
|
|
300
|
+
}, $t = (t, e) => {
|
|
301
|
+
const { onBarClicked: a, measure: n, horizontal: s } = t, r = Y(e);
|
|
296
302
|
return {
|
|
297
303
|
plugins: {
|
|
298
304
|
legend: { position: e.charts.legendPosition ?? "bottom" },
|
|
299
305
|
datalabels: {
|
|
300
|
-
|
|
306
|
+
labels: {
|
|
307
|
+
total: {
|
|
308
|
+
formatter: (o, l) => Tt(
|
|
309
|
+
l,
|
|
310
|
+
(c) => r.data(t.measure, c)
|
|
311
|
+
)
|
|
312
|
+
},
|
|
313
|
+
value: {
|
|
314
|
+
formatter: (o) => r.data(t.measure, o)
|
|
315
|
+
}
|
|
316
|
+
}
|
|
301
317
|
},
|
|
302
318
|
tooltip: {
|
|
303
319
|
callbacks: {
|
|
304
320
|
label(o) {
|
|
305
|
-
const
|
|
306
|
-
return `${o.dataset.label || ""}: ${
|
|
321
|
+
const l = o.raw;
|
|
322
|
+
return `${o.dataset.label || ""}: ${r.data(n, l)}`;
|
|
307
323
|
}
|
|
308
324
|
}
|
|
309
325
|
}
|
|
@@ -311,21 +327,21 @@ const Lt = ({ data: t, onSegmentClick: e, options: a = {}, ...n }) => {
|
|
|
311
327
|
scales: {
|
|
312
328
|
x: {
|
|
313
329
|
ticks: {
|
|
314
|
-
...
|
|
315
|
-
callback: (o) =>
|
|
330
|
+
...s && {
|
|
331
|
+
callback: (o) => r.data(n, o)
|
|
316
332
|
}
|
|
317
333
|
}
|
|
318
334
|
},
|
|
319
335
|
y: {
|
|
320
336
|
ticks: {
|
|
321
|
-
...!
|
|
322
|
-
callback: (o) =>
|
|
337
|
+
...!s && {
|
|
338
|
+
callback: (o) => r.data(n, o)
|
|
323
339
|
}
|
|
324
340
|
}
|
|
325
341
|
}
|
|
326
342
|
},
|
|
327
|
-
onClick: (o,
|
|
328
|
-
const u =
|
|
343
|
+
onClick: (o, l, c) => {
|
|
344
|
+
const u = l[0], h = u ? c.data.labels[u.index] : null, d = u ? c.data.datasets[u.datasetIndex].label : null;
|
|
329
345
|
a({
|
|
330
346
|
axisDimensionValue: h,
|
|
331
347
|
groupingDimensionValue: d
|
|
@@ -347,20 +363,20 @@ const Lt = ({ data: t, onSegmentClick: e, options: a = {}, ...n }) => {
|
|
|
347
363
|
quarter: "month",
|
|
348
364
|
// Will be handled specially
|
|
349
365
|
year: "year"
|
|
350
|
-
},
|
|
366
|
+
}, bt = (t) => `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, "0")}-${String(t.getDate()).padStart(2, "0")}`, St = (t) => `${t.getUTCFullYear()}-${String(t.getUTCMonth() + 1).padStart(2, "0")}-${String(t.getUTCDate()).padStart(2, "0")}`, Ot = (t) => t.toISOString().includes("Z"), _ = (t) => Ot(t) ? St(t) : bt(t), xt = (t) => t.startOf("month").month(Math.floor(t.month() / 3) * 3).startOf("month"), F = (t, e) => {
|
|
351
367
|
const a = K(e);
|
|
352
|
-
return e === "week" ? t.startOf("week") : e === "quarter" ?
|
|
353
|
-
},
|
|
354
|
-
var
|
|
355
|
-
const a = (
|
|
368
|
+
return e === "week" ? t.startOf("week") : e === "quarter" ? xt(t) : t.startOf(a);
|
|
369
|
+
}, vt = (t, e) => {
|
|
370
|
+
var s, r;
|
|
371
|
+
const a = (s = t.inputs) == null ? void 0 : s.dateBounds;
|
|
356
372
|
if (!a) return;
|
|
357
373
|
if (a.from && a.to)
|
|
358
374
|
return a;
|
|
359
375
|
const n = a.relativeTimeString;
|
|
360
376
|
if (n) {
|
|
361
|
-
const
|
|
362
|
-
if (
|
|
363
|
-
const c =
|
|
377
|
+
const l = (((r = e == null ? void 0 : e.defaults) == null ? void 0 : r.dateRangesOptions) ?? []).find((c) => c.value === n);
|
|
378
|
+
if (l) {
|
|
379
|
+
const c = l.getRange();
|
|
364
380
|
return {
|
|
365
381
|
from: c.from,
|
|
366
382
|
to: c.to,
|
|
@@ -369,37 +385,37 @@ const Lt = ({ data: t, onSegmentClick: e, options: a = {}, ...n }) => {
|
|
|
369
385
|
}
|
|
370
386
|
}
|
|
371
387
|
}, Ct = (t, e) => {
|
|
372
|
-
const { dimension: a, granularity: n = "day", sortOrder:
|
|
388
|
+
const { dimension: a, granularity: n = "day", sortOrder: s = "asc", dateBounds: r, theme: o } = e, l = r || vt(a, o);
|
|
373
389
|
if (!t || t.length === 0)
|
|
374
390
|
return t;
|
|
375
391
|
if (!(a != null && a.name))
|
|
376
392
|
throw new Error("dimension.name is required");
|
|
377
|
-
const c = kt(a.name, n, t), u = t.map((
|
|
378
|
-
const m =
|
|
393
|
+
const c = kt(a.name, n, t), u = t.map((i) => {
|
|
394
|
+
const m = i[c];
|
|
379
395
|
if (typeof m != "string")
|
|
380
396
|
return null;
|
|
381
397
|
const g = D(m);
|
|
382
|
-
return g.isValid() ? { ...
|
|
398
|
+
return g.isValid() ? { ...i, _parsedDate: g } : null;
|
|
383
399
|
}).filter(
|
|
384
|
-
(
|
|
400
|
+
(i) => i !== null
|
|
385
401
|
);
|
|
386
402
|
if (u.length === 0)
|
|
387
403
|
return console.warn("fillGaps: No valid dates found in data"), t;
|
|
388
404
|
let h, d;
|
|
389
|
-
if (
|
|
390
|
-
const
|
|
405
|
+
if (l) {
|
|
406
|
+
const i = l.from instanceof Date ? l.from : new Date(l.from), m = l.to instanceof Date ? l.to : new Date(l.to);
|
|
391
407
|
if (n === "second" || n === "minute" || n === "hour")
|
|
392
|
-
h = D(
|
|
408
|
+
h = D(i), d = D(m);
|
|
393
409
|
else {
|
|
394
|
-
const g = _(
|
|
410
|
+
const g = _(i), p = _(m);
|
|
395
411
|
h = D(g), d = D(p);
|
|
396
412
|
}
|
|
397
413
|
h = F(h, n), d = F(d, n);
|
|
398
414
|
} else {
|
|
399
|
-
const
|
|
400
|
-
if (!
|
|
415
|
+
const i = u[0];
|
|
416
|
+
if (!i)
|
|
401
417
|
return t;
|
|
402
|
-
let m =
|
|
418
|
+
let m = i._parsedDate, g = i._parsedDate;
|
|
403
419
|
for (let p = 1; p < u.length; p++) {
|
|
404
420
|
const w = u[p];
|
|
405
421
|
if (w) {
|
|
@@ -409,29 +425,29 @@ const Lt = ({ data: t, onSegmentClick: e, options: a = {}, ...n }) => {
|
|
|
409
425
|
}
|
|
410
426
|
h = m, d = g;
|
|
411
427
|
}
|
|
412
|
-
const x = [],
|
|
428
|
+
const x = [], v = K(n), A = h.startOf(v), C = d.startOf(v);
|
|
413
429
|
if (n === "week") {
|
|
414
|
-
let
|
|
415
|
-
for (;
|
|
416
|
-
x.push(
|
|
430
|
+
let i = A;
|
|
431
|
+
for (; i.isBefore(C) || i.isSame(C, "day"); )
|
|
432
|
+
x.push(i), i = i.add(7, "day");
|
|
417
433
|
} else {
|
|
418
|
-
let
|
|
419
|
-
for (;
|
|
420
|
-
x.push(
|
|
434
|
+
let i = A;
|
|
435
|
+
for (; i.isBefore(C) || i.isSame(C, v); )
|
|
436
|
+
x.push(i), n === "quarter" ? i = i.add(3, "month") : i = i.add(1, v);
|
|
421
437
|
}
|
|
422
|
-
const
|
|
423
|
-
u.forEach((
|
|
424
|
-
const m = $(
|
|
425
|
-
|
|
438
|
+
const k = /* @__PURE__ */ new Map();
|
|
439
|
+
u.forEach((i) => {
|
|
440
|
+
const m = $(i._parsedDate);
|
|
441
|
+
k.set(m, i);
|
|
426
442
|
});
|
|
427
443
|
const b = [];
|
|
428
|
-
return x.forEach((
|
|
429
|
-
const m = $(
|
|
444
|
+
return x.forEach((i) => {
|
|
445
|
+
const m = $(i), g = k.get(m);
|
|
430
446
|
if (g) {
|
|
431
447
|
const p = { ...g };
|
|
432
448
|
delete p._parsedDate, b.push(p);
|
|
433
449
|
} else {
|
|
434
|
-
const p =
|
|
450
|
+
const p = wt(t), w = Mt(i, p), S = {
|
|
435
451
|
[c]: w
|
|
436
452
|
}, P = a.name, B = t[0];
|
|
437
453
|
if (B)
|
|
@@ -439,18 +455,18 @@ const Lt = ({ data: t, onSegmentClick: e, options: a = {}, ...n }) => {
|
|
|
439
455
|
M !== c && (M.startsWith(P) && M !== c ? S[M] = w : S[M] = null);
|
|
440
456
|
b.push(S);
|
|
441
457
|
}
|
|
442
|
-
}),
|
|
443
|
-
(
|
|
458
|
+
}), s === "desc" ? b.sort(
|
|
459
|
+
(i, m) => D(m[c]).valueOf() - D(i[c]).valueOf()
|
|
444
460
|
) : b.sort(
|
|
445
|
-
(
|
|
461
|
+
(i, m) => D(i[c]).valueOf() - D(m[c]).valueOf()
|
|
446
462
|
), b;
|
|
447
463
|
}, $ = (t) => t.format("YYYY-MM-DDTHH:mm:ss"), kt = (t, e, a) => {
|
|
448
464
|
if (!a || a.length === 0) return t;
|
|
449
465
|
const n = a[0];
|
|
450
466
|
if (!n) return t;
|
|
451
|
-
const
|
|
452
|
-
return
|
|
453
|
-
},
|
|
467
|
+
const s = `${t}.${e}`;
|
|
468
|
+
return s in n ? s : t;
|
|
469
|
+
}, wt = (t) => {
|
|
454
470
|
if (!(t != null && t.length)) return T.DEFAULT;
|
|
455
471
|
const e = t[0];
|
|
456
472
|
if (!e) return T.DEFAULT;
|
|
@@ -458,60 +474,60 @@ const Lt = ({ data: t, onSegmentClick: e, options: a = {}, ...n }) => {
|
|
|
458
474
|
if (typeof a == "string" && a.includes("T") && a.includes(":"))
|
|
459
475
|
return a.endsWith("Z") ? T.WITH_TIMEZONE : a.includes(".") ? T.WITHOUT_TIMEZONE : T.WITHOUT_MILLISECONDS;
|
|
460
476
|
return T.DEFAULT;
|
|
461
|
-
},
|
|
477
|
+
}, Mt = (t, e) => e.includes("[Z]") ? t.format(T.WITH_TIMEZONE) : e.includes(".SSS") ? t.format(T.WITHOUT_TIMEZONE) : t.format(T.WITHOUT_MILLISECONDS), K = (t) => U[t] || U.day, Wt = (t, e) => {
|
|
462
478
|
const a = ht(), n = ut(() => {
|
|
463
479
|
var u, h;
|
|
464
|
-
const
|
|
465
|
-
if (e.nativeType !== "time" || !
|
|
466
|
-
return
|
|
467
|
-
const
|
|
468
|
-
if (!
|
|
469
|
-
return
|
|
480
|
+
const s = t.data;
|
|
481
|
+
if (e.nativeType !== "time" || !s || s.length === 0)
|
|
482
|
+
return s;
|
|
483
|
+
const r = ((u = e.inputs) == null ? void 0 : u.granularity) || It(s, e);
|
|
484
|
+
if (!r || !(((h = e.inputs) == null ? void 0 : h.dateBounds) ?? Et(s, e, r)))
|
|
485
|
+
return s;
|
|
470
486
|
const c = {
|
|
471
487
|
dimension: e,
|
|
472
|
-
granularity:
|
|
488
|
+
granularity: r,
|
|
473
489
|
sortOrder: "asc",
|
|
474
490
|
theme: a
|
|
475
491
|
};
|
|
476
492
|
try {
|
|
477
|
-
return Ct(
|
|
493
|
+
return Ct(s, c);
|
|
478
494
|
} catch (d) {
|
|
479
|
-
return console.warn("Failed to apply fillGaps to chart data:", d),
|
|
495
|
+
return console.warn("Failed to apply fillGaps to chart data:", d), s;
|
|
480
496
|
}
|
|
481
497
|
}, [t.data, e, a]);
|
|
482
498
|
return {
|
|
483
499
|
...t,
|
|
484
500
|
data: n
|
|
485
501
|
};
|
|
486
|
-
},
|
|
502
|
+
}, Et = (t, e, a) => {
|
|
487
503
|
if (!t || t.length < 2)
|
|
488
504
|
return !1;
|
|
489
|
-
const n = e.name,
|
|
490
|
-
if (
|
|
505
|
+
const n = e.name, s = t.map((o) => o[n]).filter(Boolean).map((o) => new Date(o)).filter((o) => !isNaN(o.getTime())).sort((o, l) => o.getTime() - l.getTime());
|
|
506
|
+
if (s.length < 2)
|
|
491
507
|
return !1;
|
|
492
|
-
const
|
|
493
|
-
for (let o = 1; o <
|
|
494
|
-
const
|
|
495
|
-
if (
|
|
508
|
+
const r = At(a);
|
|
509
|
+
for (let o = 1; o < s.length; o++) {
|
|
510
|
+
const l = s[o], c = s[o - 1];
|
|
511
|
+
if (l && c && l.getTime() - c.getTime() > r * 1.5)
|
|
496
512
|
return !0;
|
|
497
513
|
}
|
|
498
514
|
return !1;
|
|
499
|
-
},
|
|
515
|
+
}, It = (t, e) => {
|
|
500
516
|
if (!t || t.length === 0) return null;
|
|
501
517
|
const a = t[0];
|
|
502
518
|
if (!a) return null;
|
|
503
|
-
const n = e.name,
|
|
504
|
-
(
|
|
519
|
+
const n = e.name, s = Object.keys(a).filter(
|
|
520
|
+
(r) => r.startsWith(n) && r !== n
|
|
505
521
|
);
|
|
506
|
-
for (const
|
|
507
|
-
if (
|
|
508
|
-
if (
|
|
509
|
-
if (
|
|
510
|
-
if (
|
|
511
|
-
if (
|
|
512
|
-
if (
|
|
513
|
-
if (
|
|
514
|
-
if (
|
|
522
|
+
for (const r of s) {
|
|
523
|
+
if (r.includes(".second")) return "second";
|
|
524
|
+
if (r.includes(".minute")) return "minute";
|
|
525
|
+
if (r.includes(".hour")) return "hour";
|
|
526
|
+
if (r.includes(".day")) return "day";
|
|
527
|
+
if (r.includes(".week")) return "week";
|
|
528
|
+
if (r.includes(".month")) return "month";
|
|
529
|
+
if (r.includes(".quarter")) return "quarter";
|
|
530
|
+
if (r.includes(".year")) return "year";
|
|
515
531
|
}
|
|
516
532
|
return null;
|
|
517
533
|
}, Z = 1e3, q = 60 * Z, V = 60 * q, E = 24 * V, y = {
|
|
@@ -526,7 +542,7 @@ const Lt = ({ data: t, onSegmentClick: e, options: a = {}, ...n }) => {
|
|
|
526
542
|
// Approximate
|
|
527
543
|
YEAR: 365 * E
|
|
528
544
|
// Approximate
|
|
529
|
-
},
|
|
545
|
+
}, At = (t) => {
|
|
530
546
|
switch (t) {
|
|
531
547
|
case "second":
|
|
532
548
|
return y.SECOND;
|
|
@@ -549,10 +565,10 @@ const Lt = ({ data: t, onSegmentClick: e, options: a = {}, ...n }) => {
|
|
|
549
565
|
}
|
|
550
566
|
};
|
|
551
567
|
export {
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
568
|
+
Ut as B,
|
|
569
|
+
$t as a,
|
|
570
|
+
_t as b,
|
|
571
|
+
Ft as g,
|
|
572
|
+
Wt as u
|
|
557
573
|
};
|
|
558
|
-
//# sourceMappingURL=charts.fillGaps.hooks-
|
|
574
|
+
//# sourceMappingURL=charts.fillGaps.hooks-C5Gy3QoW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"charts.fillGaps.hooks-C5Gy3QoW.js","sources":["../src/remarkable-ui/charts/bars/bars.constants.ts","../src/remarkable-ui/charts/bars/bars.utils.ts","../src/remarkable-ui/charts/bars/BarChart.tsx","../src/remarkable-pro/components/charts/bars/bars.utils.ts","../src/remarkable-pro/components/charts/charts.fillGaps.utils.ts","../src/remarkable-pro/components/charts/charts.fillGaps.hooks.ts"],"sourcesContent":["import { ChartOptions } from 'chart.js';\nimport { getStyle, getStyleNumber } from '../../styles/styles.utils';\nimport { chartjsOptions } from '../chartjs.constants';\n\nexport const defaultBarChartOptions: Partial<ChartOptions<'bar'>> = {\n ...chartjsOptions,\n scales: {\n x: {\n title: {\n display: true,\n color: getStyle('--em-chart-grid-font-color-default'),\n font: {\n size: getStyleNumber('--em-chart-grid-font-title-size'),\n weight: getStyleNumber('--em-chart-grid-font-title-weight'),\n // TODO: fix family on dedicated ticket\n // family: getStyle('--em-chart-grid-font-font-family'),\n lineHeight: `${getStyleNumber('--em-chart-grid-font-line-height')}px`,\n },\n },\n ticks: {\n font: {\n size: getStyleNumber('--em-chart-grid-font-subtitle-size'),\n weight: getStyleNumber('--em-chart-grid-font-label-weight'),\n // TODO: fix family on dedicated ticket\n // family: getStyle('--em-chart-grid-font-font-family'),\n lineHeight: `${getStyleNumber('--em-chart-grid-font-line-height')}px`,\n },\n },\n grid: {\n display: false,\n color: getStyle('--em-chart-grid-line-color-light'),\n lineWidth: getStyleNumber('--em-chart-grid-line-width-default'),\n },\n border: {\n display: false,\n },\n },\n y: {\n title: {\n display: true,\n color: getStyle('--em-chart-grid-font-color-default'),\n font: {\n size: getStyleNumber('--em-chart-grid-font-title-size'),\n weight: getStyleNumber('--em-chart-grid-font-title-weight'),\n // TODO: fix family on dedicated ticket\n // family: getStyle('--em-chart-grid-font-font-family'),\n lineHeight: `${getStyleNumber('--em-chart-grid-font-line-height')}px`,\n },\n },\n ticks: {\n font: {\n size: getStyleNumber('--em-chart-grid-font-subtitle-size'),\n weight: getStyleNumber('--em-chart-grid-font-label-weight'),\n // TODO: fix family on dedicated ticket\n // family: getStyle('--em-chart-grid-font-font-family'),\n lineHeight: `${getStyleNumber('--em-chart-grid-font-line-height')}px`,\n },\n },\n grid: {\n display: false,\n color: getStyle('--em-chart-grid-line-color-light'),\n lineWidth: getStyleNumber('--em-chart-grid-line-width-default'),\n },\n border: {\n display: false,\n },\n },\n },\n};\n","import { ChartData, ChartOptions } from 'chart.js';\nimport { chartContrastColors } from '../charts.constants';\nimport { getStyle, getStyleNumber } from '../../styles/styles.utils';\nimport { mergician } from 'mergician';\nimport { BarChartConfigurationProps, BarChartHorizontalConfigurationProps } from './bars.types';\nimport { defaultBarChartOptions } from './bars.constants';\nimport { Context } from 'chartjs-plugin-datalabels';\n\nexport const getBarChartData = (data: ChartData<'bar'>): ChartData<'bar'> => {\n return {\n ...data,\n datasets: data.datasets?.map((dataset, index) => {\n const colors = chartContrastColors[index % chartContrastColors.length];\n const defaultDataset = {\n ...dataset,\n backgroundColor: colors,\n borderColor: colors,\n };\n\n return mergician(defaultDataset, dataset) as typeof dataset;\n }),\n };\n};\n\nconst getDatalabelTotalDisplay = (context: Context, showTotalLabels: boolean | undefined) =>\n showTotalLabels && context.datasetIndex === context.chart.data.datasets.length - 1\n ? 'auto'\n : false;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst getDatalabelTotalFormatter = (_value: any, context: Context) => {\n const { datasets } = context.chart.data;\n const i = context.dataIndex;\n\n const total = datasets.reduce((sum, ds) => {\n const val = ds.data[i] as number;\n return sum + (val || 0);\n }, 0);\n\n return total > 0 ? total : '';\n};\n\nconst getBarVerticalChartOptions = (\n config: BarChartConfigurationProps,\n): Partial<ChartOptions<'bar'>> => {\n return mergician(defaultBarChartOptions, {\n indexAxis: 'x',\n plugins: {\n datalabels: {\n labels: {\n total: {\n anchor: (context) => {\n const value = context.dataset.data[context.dataIndex] as number;\n return value >= 0 ? 'end' : 'start';\n },\n align: (context) => {\n const value = context.dataset.data[context.dataIndex] as number;\n return value >= 0 ? 'top' : 'bottom';\n },\n display: (context) => getDatalabelTotalDisplay(context, config.showTotalLabels),\n formatter: getDatalabelTotalFormatter,\n },\n value: {\n anchor: (context) => {\n if (config.stacked) {\n return 'center';\n }\n const value = context.dataset.data[context.dataIndex] as number;\n return value >= 0 ? 'end' : 'start';\n },\n align: (context) => {\n if (config.stacked) {\n return 'center';\n }\n const value = context.dataset.data[context.dataIndex] as number;\n return value >= 0 ? 'top' : 'bottom';\n },\n },\n },\n },\n },\n scales: {\n y: {\n stacked: config.stacked,\n grid: { display: true },\n ticks: {\n color: getStyle('--em-chart-grid-font-color-muted'),\n // ...(config.stacked === 'percentage' && {\n // callback: (value: number | string) => value + '%',\n // }),\n },\n min: config.yAxisRangeMin,\n // max: config.stacked === 'percentage' ? 100 : config.yAxisRangeMax,\n max: config.yAxisRangeMax,\n type: config.showLogarithmicScale ? 'logarithmic' : 'linear',\n title: {\n text: config.yAxisLabel ?? '',\n },\n },\n x: {\n stacked: config.stacked,\n ticks: {\n color: getStyle('--em-chart-grid-font-color-default'),\n },\n reverse: config.reverseXAxis,\n title: {\n text: config.xAxisLabel ?? '',\n },\n },\n },\n } as Partial<ChartOptions<'bar'>>);\n};\n\nconst getBarHorizontalChartOptions = (\n config: BarChartHorizontalConfigurationProps,\n): Partial<ChartOptions<'bar'>> => {\n return mergician(defaultBarChartOptions, {\n indexAxis: 'y',\n plugins: {\n datalabels: {\n labels: {\n total: {\n anchor: (context) => {\n const value = context.dataset.data[context.dataIndex] as number;\n return value >= 0 ? 'end' : 'start';\n },\n align: (context) => {\n const value = context.dataset.data[context.dataIndex] as number;\n return value >= 0 ? 'right' : 'left';\n },\n display: (context) => getDatalabelTotalDisplay(context, config.showTotalLabels),\n formatter: getDatalabelTotalFormatter,\n },\n value: {\n anchor: (context) => {\n if (config.stacked) {\n return 'center';\n }\n const value = context.dataset.data[context.dataIndex] as number;\n return value >= 0 ? 'end' : 'start';\n },\n align: (context) => {\n if (config.stacked) {\n return 'center';\n }\n const value = context.dataset.data[context.dataIndex] as number;\n return value >= 0 ? 'right' : 'left';\n },\n },\n },\n },\n },\n scales: {\n x: {\n stacked: config.stacked,\n grid: { display: true },\n ticks: {\n color: getStyle('--em-chart-grid-font-color-muted'),\n // ...(config.stacked === 'percentage' && {\n // callback: (value: number | string) => value + '%',\n // }),\n },\n min: config.xAxisRangeMin,\n // max: config.stacked === 'percentage' ? 100 : config.xAxisRangeMax,\n max: config.xAxisRangeMax,\n type: config.showLogarithmicScale ? 'logarithmic' : 'linear',\n title: {\n text: config.xAxisLabel ?? '',\n },\n },\n y: {\n stacked: config.stacked,\n ticks: {\n color: getStyle('--em-chart-grid-font-color-default'),\n },\n reverse: config.reverseYAxis,\n title: {\n text: config.yAxisLabel ?? '',\n },\n },\n },\n } as Partial<ChartOptions<'bar'>>);\n};\n\nexport const getBarChartOptions = (\n props: BarChartConfigurationProps,\n): Partial<ChartOptions<'bar'>> => {\n const {\n horizontal = false,\n showLegend = false,\n showTooltips = true,\n showValueLabels = false,\n showTotalLabels = false,\n } = props;\n\n const getOptions = horizontal ? getBarHorizontalChartOptions : getBarVerticalChartOptions;\n const options = getOptions(props);\n\n return mergician(options, {\n layout: {\n padding: {\n // Hack: dataLabels can get cut off if they are at the edge of the chart\n top: !horizontal && (showValueLabels || showTotalLabels) ? 30 : 0,\n right: horizontal && (showValueLabels || showTotalLabels) ? 30 : 0,\n },\n },\n elements: {\n bar: {\n borderRadius: getStyleNumber('--em-chart-style-border-radius-default'),\n // stacked === 'percentage' ? 0 : getStyleNumber('--em-chart-style-border-radius-default'),\n },\n },\n plugins: {\n legend: { display: showLegend },\n datalabels: {\n display: (context) => {\n return showValueLabels && context.dataset.data[context.dataIndex] !== 0 ? 'auto' : false;\n },\n },\n tooltip: {\n enabled: showTooltips,\n },\n },\n } as Partial<ChartOptions<'bar'>>);\n};\n","import { FC, useRef } from 'react';\nimport { Bar } from 'react-chartjs-2';\nimport {\n Chart as ChartJS,\n CategoryScale,\n LinearScale,\n BarElement,\n Title,\n Tooltip,\n Legend,\n LogarithmicScale,\n} from 'chart.js';\nimport { BaseBarChartProps } from './bars.types';\nimport { getSegmentIndexClicked } from '../chartjs.utils';\nimport { getBarChartData, getBarChartOptions } from './bars.utils';\nimport styles from '../charts.module.css';\nimport { mergician } from 'mergician';\n\nChartJS.register(CategoryScale, LinearScale, BarElement, LogarithmicScale, Title, Tooltip, Legend);\n\nexport type BarChartProps = BaseBarChartProps;\n\nexport const BarChart: FC<BarChartProps> = ({ data, onSegmentClick, options = {}, ...props }) => {\n const chartRef = useRef(null);\n\n const barChartOptions = mergician(getBarChartOptions(props), options);\n\n const handleSegmentClick = (event: React.MouseEvent<HTMLCanvasElement>) => {\n const indexClicked = getSegmentIndexClicked(event, chartRef);\n onSegmentClick?.(indexClicked);\n };\n\n return (\n <div className={styles.chartContainer}>\n <Bar\n ref={chartRef}\n data={getBarChartData(data)}\n options={barChartOptions}\n onClick={handleSegmentClick}\n />\n </div>\n );\n};\n","import { DataResponse, Dimension, Measure } from '@embeddable.com/core';\nimport { Theme } from '../../../theme/theme.types';\nimport { remarkableTheme } from '../../../theme/theme.constants';\nimport { ChartData, ChartOptions } from 'chart.js';\nimport { getThemeFormatter } from '../../../theme/formatter/formatter.utils';\nimport { groupTailAsOther } from '../charts.utils';\nimport { i18n } from '../../../theme/i18n/i18n';\nimport { getColor } from '../../../theme/styles/styles.utils';\nimport { chartColors } from '../../../../remarkable-ui';\nimport { getObjectStableKey } from '../../../utils.ts/object.utils';\nimport { chartContrastColors } from '../../../../remarkable-ui/charts/charts.constants';\nimport { Context } from 'chartjs-plugin-datalabels';\n\nexport const getBarStackedChartProData = (\n props: {\n data: DataResponse['data'];\n dimension: Dimension;\n groupDimension: Dimension;\n measure: Measure;\n },\n theme: Theme,\n): ChartData<'bar'> => {\n const themeFormatter = getThemeFormatter(theme);\n const { data = [], dimension, groupDimension, measure } = props;\n\n const axis = [...new Set(data.map((d) => d[dimension.name]).filter(Boolean))].sort();\n\n const groupBy = [...new Set(data.map((d) => d[groupDimension.name]))];\n\n const themeKey = getObjectStableKey(theme);\n\n const datasets = groupBy.map((groupByItem, index) => {\n const backgroundColor = getColor(\n `${themeKey}.charts.backgroundColors`,\n groupByItem,\n theme.charts.backgroundColors ?? chartContrastColors,\n index,\n );\n\n const borderColor = getColor(\n `${themeKey}.charts.borderColors`,\n groupByItem,\n theme.charts.borderColors ?? chartContrastColors,\n index,\n );\n\n return {\n label: themeFormatter.data(groupDimension, groupByItem),\n backgroundColor,\n borderColor,\n data: axis.map((axisItem) => {\n const record = data.find(\n (d) => d[groupDimension.name] === groupByItem && d[dimension.name] === axisItem,\n );\n return record ? Number(record[measure.name]) : 0;\n }),\n };\n });\n\n return {\n labels: axis.map((axisItem) => themeFormatter.data(dimension, axisItem)),\n datasets,\n };\n};\nexport const getBarChartProData = (\n props: {\n data: DataResponse['data'];\n dimension: Dimension;\n measures: Measure[];\n maxItems?: number;\n },\n theme: Theme = remarkableTheme,\n): ChartData<'bar'> => {\n const themeFormatter = getThemeFormatter(theme);\n\n if (!props.data) {\n return {\n labels: [],\n datasets: [{ data: [] }],\n };\n }\n\n const themeKey = getObjectStableKey(theme);\n const groupedData = groupTailAsOther(props.data, props.dimension, props.measures, props.maxItems);\n\n return {\n labels: groupedData.map((item) => {\n const value = item[props.dimension.name];\n const formattedValue = themeFormatter.data(props.dimension, value);\n\n // If formatter did not work, try i18n translation\n if (value === formattedValue) {\n return i18n.t(value);\n }\n return formattedValue;\n }),\n datasets: props.measures.map((measure, index) => {\n const backgroundColor = getColor(\n `${themeKey}.charts.backgroundColors`,\n measure.name,\n theme.charts.backgroundColors ?? chartColors,\n index,\n );\n\n const borderColor = getColor(\n `${themeKey}.charts.borderColors`,\n measure.name,\n theme.charts.borderColors ?? chartColors,\n index,\n );\n\n return {\n label: themeFormatter.dimensionOrMeasureTitle(measure),\n data: groupedData.map((item) => item[measure.name]),\n backgroundColor,\n borderColor,\n };\n }),\n };\n};\n\nconst getBarChartProDatalabelTotalFormatter = (\n context: Context,\n formatter: (value: number) => string,\n) => {\n const { datasets } = context.chart.data;\n const i = context.dataIndex;\n\n const total = datasets.reduce((sum, ds) => {\n const val = ds.data[i] as number;\n return sum + (val || 0);\n }, 0);\n\n return formatter(total);\n};\n\nexport const getBarChartProOptions = (\n options: {\n onBarClicked: (args: {\n axisDimensionValue: string | null;\n groupingDimensionValue: string | null;\n }) => void;\n measure: Measure;\n horizontal: boolean;\n },\n theme: Theme,\n): Partial<ChartOptions<'bar'>> => {\n const { onBarClicked, measure, horizontal } = options;\n\n const themeFormatter = getThemeFormatter(theme);\n return {\n plugins: {\n legend: { position: theme.charts.legendPosition ?? 'bottom' },\n datalabels: {\n labels: {\n total: {\n formatter: (_value: string | number, context: Context) =>\n getBarChartProDatalabelTotalFormatter(context, (value: number) =>\n themeFormatter.data(options.measure, value),\n ),\n },\n value: {\n formatter: (value: string | number) => themeFormatter.data(options.measure, value),\n },\n },\n },\n tooltip: {\n callbacks: {\n label(context) {\n const raw = context.raw as number;\n return `${context.dataset.label || ''}: ${themeFormatter.data(measure, raw)}`;\n },\n },\n },\n },\n scales: {\n x: {\n ticks: {\n ...(horizontal && {\n callback: (value) => themeFormatter.data(measure, value),\n }),\n },\n },\n y: {\n ticks: {\n ...(!horizontal && {\n callback: (value) => themeFormatter.data(measure, value),\n }),\n },\n },\n },\n onClick: (_event, elements, chart) => {\n const element = elements[0];\n const axisDimensionValue = (element ? chart.data.labels![element.index] : null) as\n | string\n | null;\n const groupingDimensionValue = (\n element ? chart.data.datasets[element.datasetIndex]!.label : null\n ) as string | null;\n\n onBarClicked({\n axisDimensionValue,\n groupingDimensionValue,\n });\n },\n };\n};\n","import dayjs from 'dayjs';\nimport {\n DataResponse,\n Dimension,\n Granularity,\n TimeRange,\n TimeRangeDeserializedValue,\n} from '@embeddable.com/core';\nimport { Theme } from '../../theme/theme.types';\n\ntype DataResponseDataRecord = NonNullable<DataResponse['data']>[number];\n\nconst DATE_FORMATS = {\n DEFAULT: 'YYYY-MM-DDTHH:mm:ss.SSS',\n WITH_TIMEZONE: 'YYYY-MM-DDTHH:mm:ss.SSS[Z]',\n WITHOUT_TIMEZONE: 'YYYY-MM-DDTHH:mm:ss.SSS',\n WITHOUT_MILLISECONDS: 'YYYY-MM-DDTHH:mm:ss',\n};\n\n/**\n * Maps granularity to dayjs unit for date manipulation\n */\nconst granularityToDayjsUnitMap: Record<Granularity, dayjs.ManipulateType> = {\n second: 'second',\n minute: 'minute',\n hour: 'hour',\n day: 'day',\n week: 'week',\n month: 'month',\n quarter: 'month', // Will be handled specially\n year: 'year',\n};\n\n/**\n * Formats a Date object as YYYY-MM-DD string in local timezone\n */\nconst formatDateAsString = (date: Date): string => {\n return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;\n};\n\n/**\n * Formats a Date object as YYYY-MM-DD string in UTC timezone\n */\nconst formatDateAsStringUTC = (date: Date): string => {\n return `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, '0')}-${String(date.getUTCDate()).padStart(2, '0')}`;\n};\n\n/**\n * Checks if a date is in UTC format (contains 'Z')\n */\nconst isUTCDate = (date: Date): boolean => {\n return date.toISOString().includes('Z');\n};\n\n/**\n * Formats a date string based on whether it's UTC or local\n */\nconst formatDateString = (date: Date): string => {\n return isUTCDate(date) ? formatDateAsStringUTC(date) : formatDateAsString(date);\n};\n\n/**\n * Gets the quarter start date for a given dayjs date\n */\nconst getQuarterStart = (date: dayjs.Dayjs): dayjs.Dayjs => {\n return date\n .startOf('month')\n .month(Math.floor(date.month() / 3) * 3)\n .startOf('month');\n};\n\n/**\n * Applies granularity-specific start/end logic to dates\n */\nconst applyGranularityBounds = (date: dayjs.Dayjs, granularity: Granularity): dayjs.Dayjs => {\n const unit = granularityToDayjsUnit(granularity);\n\n if (granularity === 'week') {\n return date.startOf('week');\n } else if (granularity === 'quarter') {\n return getQuarterStart(date);\n } else {\n return date.startOf(unit);\n }\n};\n\n/**\n * Resolves date bounds from dimension inputs, handling relative time strings\n */\nconst resolveDateBounds = (dimension: Dimension, theme?: Theme): TimeRange => {\n const dateBounds = dimension.inputs?.dateBounds;\n if (!dateBounds) return undefined;\n\n // If it already has from/to dates, use them directly\n if (dateBounds.from && dateBounds.to) {\n return dateBounds;\n }\n\n // If it has a relativeTimeString, resolve it using theme options\n const relativeTimeString = dateBounds.relativeTimeString;\n if (relativeTimeString) {\n const dateRangeOptions = theme?.defaults?.dateRangesOptions ?? [];\n const matchedOption = dateRangeOptions.find((option) => option.value === relativeTimeString);\n\n if (matchedOption) {\n const range = matchedOption.getRange() as TimeRangeDeserializedValue;\n return {\n from: range.from,\n to: range.to,\n relativeTimeString: relativeTimeString,\n };\n }\n }\n\n return undefined;\n};\n\nexport type FillGapsOptions = {\n dimension: Dimension;\n granularity?: Granularity;\n sortOrder?: 'asc' | 'desc';\n dateBounds?: TimeRangeDeserializedValue;\n theme?: Theme;\n};\n\n/**\n * Fills missing time buckets in a date-series based on granularity and sorting\n *\n * @param data - Array of date records to process\n * @param options - Configuration options for gap filling\n * @returns Array with missing time buckets filled in\n *\n * @example\n * ```typescript\n * const data = [\n * { date: '2024-01-01', value: 10 },\n * { date: '2024-01-03', value: 20 }\n * ];\n * const result = fillGaps(data, {\n * dimension: { name: 'date' },\n * granularity: 'day'\n * });\n * // Result: [{ date: '2024-01-01', value: 10 }, { date: '2024-01-02', value: null }, { date: '2024-01-03', value: 20 }]\n * ```\n */\nexport const fillGaps = (\n data: DataResponse['data'],\n options: FillGapsOptions,\n): DataResponse['data'] => {\n const { dimension, granularity = 'day', sortOrder = 'asc', dateBounds, theme } = options;\n\n // Resolve date bounds from dimension inputs if not provided directly\n const resolvedDateBounds = dateBounds || resolveDateBounds(dimension, theme);\n\n if (!data || data.length === 0) {\n return data;\n }\n\n if (!dimension?.name) {\n throw new Error('dimension.name is required');\n }\n\n // Get the dimension name - use granularity-specific name if available\n const dimensionName = getGranularityDimensionName(dimension.name, granularity, data);\n\n // Parse dates and filter valid ones\n const validData = data\n .map((record) => {\n const dateValue = record[dimensionName];\n if (typeof dateValue !== 'string') {\n return null;\n }\n const parsedDate = dayjs(dateValue);\n return parsedDate.isValid() ? { ...record, _parsedDate: parsedDate } : null;\n })\n .filter(\n (record): record is DataResponseDataRecord & { _parsedDate: dayjs.Dayjs } => record !== null,\n );\n\n if (validData.length === 0) {\n console.warn('fillGaps: No valid dates found in data');\n return data;\n }\n\n // Determine date range\n let minDate: dayjs.Dayjs;\n let maxDate: dayjs.Dayjs;\n\n if (resolvedDateBounds) {\n // Parse dates with timezone-safe approach\n const fromDate =\n resolvedDateBounds.from instanceof Date\n ? resolvedDateBounds.from\n : new Date(resolvedDateBounds.from!);\n const toDate =\n resolvedDateBounds.to instanceof Date\n ? resolvedDateBounds.to\n : new Date(resolvedDateBounds.to!);\n\n // For sub-day granularities, preserve time component\n if (granularity === 'second' || granularity === 'minute' || granularity === 'hour') {\n minDate = dayjs(fromDate);\n maxDate = dayjs(toDate);\n } else {\n // For day+ granularities, extract date only to avoid timezone issues\n const fromDateStr = formatDateString(fromDate);\n const toDateStr = formatDateString(toDate);\n\n minDate = dayjs(fromDateStr);\n maxDate = dayjs(toDateStr);\n }\n\n // Apply granularity-specific start/end logic\n minDate = applyGranularityBounds(minDate, granularity);\n maxDate = applyGranularityBounds(maxDate, granularity);\n } else {\n // Use data range - more efficient single pass\n const firstRecord = validData[0];\n if (!firstRecord) {\n return data;\n }\n\n let min = firstRecord._parsedDate;\n let max = firstRecord._parsedDate;\n\n for (let i = 1; i < validData.length; i++) {\n const record = validData[i];\n if (record) {\n const date = record._parsedDate;\n if (date.isBefore(min)) min = date;\n if (date.isAfter(max)) max = date;\n }\n }\n\n minDate = min;\n maxDate = max;\n }\n\n // Generate all possible dates in the range\n const allDates: dayjs.Dayjs[] = [];\n\n // Normalize both dates to the start of their respective granularity units\n const dayjsUnit = granularityToDayjsUnit(granularity);\n const minDateStart = minDate.startOf(dayjsUnit);\n const maxDateStart = maxDate.startOf(dayjsUnit);\n\n if (granularity === 'week') {\n // For week granularity, start from the first day and add exactly 7 days\n let currentDate = minDateStart;\n while (currentDate.isBefore(maxDateStart) || currentDate.isSame(maxDateStart, 'day')) {\n allDates.push(currentDate);\n currentDate = currentDate.add(7, 'day'); // Add exactly 7 days\n }\n } else {\n // For other granularities, use the standard approach\n let currentDate = minDateStart;\n\n while (currentDate.isBefore(maxDateStart) || currentDate.isSame(maxDateStart, dayjsUnit)) {\n allDates.push(currentDate);\n\n if (granularity === 'quarter') {\n currentDate = currentDate.add(3, 'month');\n } else {\n currentDate = currentDate.add(1, dayjsUnit);\n }\n }\n }\n\n // Create a map of existing data by date\n const existingDataMap = new Map<string, DataResponseDataRecord>();\n validData.forEach((record) => {\n const dateKey = generateDateKey(record._parsedDate);\n existingDataMap.set(dateKey, record);\n });\n\n // Fill gaps\n const result: DataResponse['data'] = [];\n allDates.forEach((date) => {\n const dateKey = generateDateKey(date);\n const existingRecord = existingDataMap.get(dateKey);\n\n if (existingRecord) {\n // Use existing data - exclude internal _parsedDate field\n const cleanRecord = { ...existingRecord };\n delete cleanRecord._parsedDate;\n result.push(cleanRecord);\n } else {\n // Create gap record with zero/null values\n // Use the same date format as the original data\n const dateFormat = getDateFormatFromSample(data);\n const formattedDate = formatDateForGapRecord(date, dateFormat);\n\n const gapRecord: DataResponseDataRecord = {\n [dimensionName]: formattedDate,\n };\n\n // Set all other dimensions to null/zero, but preserve date fields\n const baseDimensionName = dimension.name;\n const sampleRecord = data[0];\n if (sampleRecord) {\n for (const key of Object.keys(sampleRecord)) {\n if (key !== dimensionName) {\n // If this is another date dimension (same base name), use the same date\n if (key.startsWith(baseDimensionName) && key !== dimensionName) {\n gapRecord[key] = formattedDate;\n } else {\n gapRecord[key] = null;\n }\n }\n }\n }\n\n result.push(gapRecord);\n }\n });\n\n // Sort the result\n if (sortOrder === 'desc') {\n result.sort(\n (a, b) =>\n dayjs(b[dimensionName] as string).valueOf() - dayjs(a[dimensionName] as string).valueOf(),\n );\n } else {\n result.sort(\n (a, b) =>\n dayjs(a[dimensionName] as string).valueOf() - dayjs(b[dimensionName] as string).valueOf(),\n );\n }\n\n return result;\n};\n\n/**\n * Generates a consistent date key for mapping\n * Includes time component to support second/minute granularities\n */\nconst generateDateKey = (date: dayjs.Dayjs): string => {\n return date.format('YYYY-MM-DDTHH:mm:ss');\n};\n\n/**\n * Gets the correct dimension name based on granularity\n */\nconst getGranularityDimensionName = (\n baseDimensionName: string,\n granularity: Granularity,\n data: DataResponse['data'],\n): string => {\n if (!data || data.length === 0) return baseDimensionName;\n\n const sampleRecord = data[0];\n if (!sampleRecord) return baseDimensionName;\n\n const granularityKey = `${baseDimensionName}.${granularity}`;\n\n // Check if granularity-specific dimension exists in the data\n if (granularityKey in sampleRecord) {\n return granularityKey;\n }\n\n // Fallback to base dimension name\n return baseDimensionName;\n};\n\n/**\n * Detects the date format from sample data\n */\nconst getDateFormatFromSample = (data: DataResponse['data']): string => {\n if (!data?.length) return DATE_FORMATS.DEFAULT;\n\n const sampleRecord = data[0];\n if (!sampleRecord) return DATE_FORMATS.DEFAULT;\n\n // Look for any date field to determine format\n for (const value of Object.values(sampleRecord)) {\n if (typeof value === 'string' && value.includes('T') && value.includes(':')) {\n if (value.endsWith('Z')) {\n return DATE_FORMATS.WITH_TIMEZONE;\n }\n if (value.includes('.')) {\n return DATE_FORMATS.WITHOUT_TIMEZONE;\n }\n return DATE_FORMATS.WITHOUT_MILLISECONDS;\n }\n }\n\n return DATE_FORMATS.DEFAULT;\n};\n\n/**\n * Formats a date for gap records using the detected format\n */\nconst formatDateForGapRecord = (date: dayjs.Dayjs, dateFormat: string): string => {\n if (dateFormat.includes('[Z]')) {\n return date.format(DATE_FORMATS.WITH_TIMEZONE);\n } else if (dateFormat.includes('.SSS')) {\n return date.format(DATE_FORMATS.WITHOUT_TIMEZONE);\n } else {\n return date.format(DATE_FORMATS.WITHOUT_MILLISECONDS);\n }\n};\n\n/**\n * Maps granularity to dayjs unit\n */\nconst granularityToDayjsUnit = (granularity: Granularity): dayjs.ManipulateType => {\n return granularityToDayjsUnitMap[granularity] || granularityToDayjsUnitMap.day;\n};\n","import { useMemo } from 'react';\nimport { DataResponse, Dimension, Granularity } from '@embeddable.com/core';\nimport { fillGaps, type FillGapsOptions } from './charts.fillGaps.utils';\nimport { useTheme } from '@embeddable.com/react';\nimport { Theme } from '../../theme/theme.types';\n\n/**\n * Hook that automatically applies fillGaps to chart data when beneficial.\n *\n * This hook intelligently fills missing time buckets in date-series data based on:\n * - The granularity from dimension inputs or auto-detected granularity from data\n * - Date bounds from dimension inputs (including relative time strings)\n * - Data sparsity analysis to determine if gap filling is needed\n *\n * @param results - The data response containing the chart data\n * @param dimension - The dimension being used for the chart axis (includes granularity in inputs)\n * @returns Enhanced data with filled time gaps, or original data if no gaps need filling\n */\nexport const useChartDataWithFillGaps = (\n results: DataResponse,\n dimension: Dimension,\n): DataResponse => {\n const theme = useTheme() as Theme;\n\n const data = useMemo(() => {\n const data = results.data;\n\n // Only apply fillGaps if:\n // 1. The dimension is a date/time dimension\n // 2. We have data to process\n if (dimension.nativeType !== 'time' || !data || data.length === 0) {\n return data;\n }\n\n // Get granularity from dimension inputs or auto-detect from data\n const effectiveGranularity =\n dimension.inputs?.granularity || detectGranularityFromData(data, dimension);\n\n if (!effectiveGranularity) {\n return data;\n }\n\n // Check if this looks like a sparse time series that would benefit from fillGaps\n // If dimension has date bounds, always apply fillGaps to ensure the specified range is filled\n const hasDateBounds = dimension.inputs?.dateBounds;\n const shouldApply = hasDateBounds ?? shouldApplyFillGaps(data, dimension, effectiveGranularity);\n\n if (!shouldApply) {\n return data;\n }\n\n // Use the effective granularity\n const options: FillGapsOptions = {\n dimension: dimension,\n granularity: effectiveGranularity,\n sortOrder: 'asc',\n theme: theme,\n };\n\n try {\n return fillGaps(data, options);\n } catch (error) {\n console.warn('Failed to apply fillGaps to chart data:', error);\n return data;\n }\n }, [results.data, dimension, theme]);\n return {\n ...results,\n data,\n };\n};\n\n/**\n * Determines if fillGaps should be applied based on data characteristics.\n *\n * Analyzes the time series data to detect if there are significant gaps that would\n * benefit from gap filling. Uses the expected step size for the given granularity\n * to determine if the data appears sparse.\n *\n * @param data - The chart data to analyze\n * @param dimension - The dimension being used for the time axis\n * @param granularity - The granularity to use for gap analysis (e.g., 'day', 'week')\n * @returns True if gap filling should be applied, false otherwise\n */\nconst shouldApplyFillGaps = (\n data: DataResponse['data'],\n dimension: Dimension,\n granularity: string,\n): boolean => {\n if (!data || data.length < 2) {\n return false; // Too few data points\n }\n\n const dimensionName = dimension.name;\n const dates = data\n .map((record) => record[dimensionName])\n .filter(Boolean)\n .map((dateStr) => new Date(dateStr as string))\n .filter((date) => !isNaN(date.getTime()))\n .sort((a, b) => a.getTime() - b.getTime());\n\n if (dates.length < 2) {\n return false; // Not enough valid dates\n }\n\n // Calculate expected step size based on granularity\n const expectedStepMs = getGranularityStepMs(granularity);\n\n // Check if there are gaps larger than expected step\n for (let i = 1; i < dates.length; i++) {\n const currentDate = dates[i];\n const previousDate = dates[i - 1];\n if (currentDate && previousDate) {\n const actualStep = currentDate.getTime() - previousDate.getTime();\n // If actual step is more than 1.5x the expected step, we have a gap\n if (actualStep > expectedStepMs * 1.5) {\n return true;\n }\n }\n }\n\n return false;\n};\n\n/**\n * Detects granularity from data by examining dimension names in the data.\n *\n * Looks for granularity-specific dimension names (e.g., 'events.date.week')\n * to infer the appropriate granularity for gap filling. Falls back to the\n * base dimension name if no granularity-specific dimension is found.\n *\n * @param data - The chart data to analyze\n * @param dimension - The base dimension being used\n * @returns Detected granularity or null if none can be determined\n */\nconst detectGranularityFromData = (\n data: DataResponse['data'],\n dimension: Dimension,\n): Granularity | null => {\n if (!data || data.length === 0) return null;\n\n const sampleRecord = data[0];\n if (!sampleRecord) return null;\n\n const baseDimensionName = dimension.name;\n\n // Look for granularity-specific dimension names in the data\n const granularityKeys = Object.keys(sampleRecord).filter(\n (key) => key.startsWith(baseDimensionName) && key !== baseDimensionName,\n );\n\n // Check for common granularity patterns\n for (const key of granularityKeys) {\n if (key.includes('.second')) return 'second';\n if (key.includes('.minute')) return 'minute';\n if (key.includes('.hour')) return 'hour';\n if (key.includes('.day')) return 'day';\n if (key.includes('.week')) return 'week';\n if (key.includes('.month')) return 'month';\n if (key.includes('.quarter')) return 'quarter';\n if (key.includes('.year')) return 'year';\n }\n\n // If no granularity-specific dimension found, return null\n return null;\n};\n\nconst SECOND = 1000;\nconst MINUTE = 60 * SECOND;\nconst HOUR = 60 * MINUTE;\nconst DAY = 24 * HOUR;\n\nexport const TIME_CONSTANTS = {\n SECOND,\n MINUTE,\n HOUR,\n DAY,\n WEEK: 7 * DAY,\n MONTH: 30 * DAY, // Approximate\n QUARTER: 90 * DAY, // Approximate\n YEAR: 365 * DAY, // Approximate\n} as const;\n\n/**\n * Gets the expected step size in milliseconds for a given granularity.\n *\n * Returns the expected time interval between consecutive data points for\n * the specified granularity. Used to detect if there are gaps in the\n * time series data that would benefit from gap filling.\n *\n * @param granularity - The time granularity (e.g., 'day', 'week', 'month')\n * @returns Expected step size in milliseconds\n */\nconst getGranularityStepMs = (granularity: string): number => {\n switch (granularity) {\n case 'second':\n return TIME_CONSTANTS.SECOND;\n case 'minute':\n return TIME_CONSTANTS.MINUTE;\n case 'hour':\n return TIME_CONSTANTS.HOUR;\n case 'day':\n return TIME_CONSTANTS.DAY;\n case 'week':\n return TIME_CONSTANTS.WEEK;\n case 'month':\n return TIME_CONSTANTS.MONTH;\n case 'quarter':\n return TIME_CONSTANTS.QUARTER;\n case 'year':\n return TIME_CONSTANTS.YEAR;\n default:\n return TIME_CONSTANTS.DAY; // Default fallback\n }\n};\n"],"names":["defaultBarChartOptions","chartjsOptions","getStyle","getStyleNumber","getBarChartData","data","_a","dataset","index","colors","chartContrastColors","defaultDataset","mergician","getDatalabelTotalDisplay","context","showTotalLabels","getDatalabelTotalFormatter","_value","datasets","i","total","sum","ds","val","getBarVerticalChartOptions","config","getBarHorizontalChartOptions","getBarChartOptions","props","horizontal","showLegend","showTooltips","showValueLabels","options","ChartJS","CategoryScale","LinearScale","BarElement","LogarithmicScale","Title","Tooltip","Legend","BarChart","onSegmentClick","chartRef","useRef","barChartOptions","handleSegmentClick","event","indexClicked","getSegmentIndexClicked","jsx","styles","Bar","getBarStackedChartProData","theme","themeFormatter","getThemeFormatter","dimension","groupDimension","measure","axis","groupBy","themeKey","getObjectStableKey","groupByItem","backgroundColor","getColor","borderColor","axisItem","record","d","getBarChartProData","remarkableTheme","groupedData","groupTailAsOther","item","value","formattedValue","i18n","chartColors","getBarChartProDatalabelTotalFormatter","formatter","getBarChartProOptions","onBarClicked","raw","_event","elements","chart","element","axisDimensionValue","groupingDimensionValue","DATE_FORMATS","granularityToDayjsUnitMap","formatDateAsString","date","formatDateAsStringUTC","isUTCDate","formatDateString","getQuarterStart","applyGranularityBounds","granularity","unit","granularityToDayjsUnit","resolveDateBounds","dateBounds","relativeTimeString","matchedOption","_b","option","range","fillGaps","sortOrder","resolvedDateBounds","dimensionName","getGranularityDimensionName","validData","dateValue","parsedDate","dayjs","minDate","maxDate","fromDate","toDate","fromDateStr","toDateStr","firstRecord","min","max","allDates","dayjsUnit","minDateStart","maxDateStart","currentDate","existingDataMap","dateKey","generateDateKey","result","existingRecord","cleanRecord","dateFormat","getDateFormatFromSample","formattedDate","formatDateForGapRecord","gapRecord","baseDimensionName","sampleRecord","key","a","b","granularityKey","useChartDataWithFillGaps","results","useTheme","useMemo","effectiveGranularity","detectGranularityFromData","shouldApplyFillGaps","error","dates","dateStr","expectedStepMs","getGranularityStepMs","previousDate","granularityKeys","SECOND","MINUTE","HOUR","DAY","TIME_CONSTANTS"],"mappings":"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"}
|