@sproutsocial/seeds-react-data-viz 0.7.32 → 0.14.0

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.
@@ -0,0 +1,1154 @@
1
+ // src/components/ColorBox/ColorBox.tsx
2
+ import { css } from "styled-components";
3
+ import { Box } from "@sproutsocial/seeds-react-box";
4
+
5
+ // ../seeds-react-theme-provider/dist/index.mjs
6
+ import "react";
7
+ import {
8
+ ThemeProvider as BaseThemeProvider,
9
+ createGlobalStyle
10
+ } from "styled-components";
11
+ import { theme } from "@sproutsocial/seeds-react-theme";
12
+ import { jsx, jsxs } from "react/jsx-runtime";
13
+ var GlobalTokenStyles = createGlobalStyle`
14
+ :root {
15
+ --color-container-bg-ai-generated: radial-gradient(
16
+ circle at bottom left,
17
+ color-mix(in srgb, #205bc3, transparent 80%) 0%,
18
+ color-mix(in srgb, #6f5ed3, transparent 80%) 61%,
19
+ color-mix(in srgb, #f282f5, transparent 80%) 100%
20
+ ), #f3f4f4;
21
+ }
22
+ `;
23
+
24
+ // src/components/ColorBox/ColorBox.tsx
25
+ import "@sproutsocial/seeds-react-theme";
26
+ import { jsx as jsx2 } from "react/jsx-runtime";
27
+ var ColorBox = ({
28
+ display = "inline-block",
29
+ height = "16px",
30
+ width = "16px",
31
+ minWidth = width,
32
+ borderRadius = "400",
33
+ ...props
34
+ }) => {
35
+ return /* @__PURE__ */ jsx2(
36
+ Box,
37
+ {
38
+ ...props,
39
+ display,
40
+ height,
41
+ width,
42
+ minWidth,
43
+ borderRadius,
44
+ css: css`
45
+ cursor: ${(props2) => props2?.onClick ? "pointer" : "default"};
46
+ `
47
+ }
48
+ );
49
+ };
50
+
51
+ // src/components/ColorBox/DatavizColorBox.tsx
52
+ import styled from "styled-components";
53
+ import { theme as theme2 } from "@sproutsocial/seeds-react-theme";
54
+ var DatavizColorBox = styled(ColorBox).attrs(
55
+ ({ colorIndex }) => ({
56
+ style: {
57
+ background: getDatavizColor(colorIndex),
58
+ opacity: getDatavizOpacity(colorIndex)
59
+ }
60
+ })
61
+ )``;
62
+ var getDatavizColor = (colorIndex) => theme2.colors.DATAVIZ_COLORS_LIST[colorIndex % theme2.colors.DATAVIZ_COLORS_LIST.length] || "";
63
+ var getDatavizOpacity = (colorIndex) => {
64
+ const opacitySteps = [1, 0.6, 0.4, 0.2];
65
+ const opacityStep = Math.floor(colorIndex / theme2.colors.DATAVIZ_COLORS_LIST.length) % opacitySteps.length;
66
+ return opacitySteps[opacityStep];
67
+ };
68
+ var getDatavizColorWithAlpha = (colorIndex) => {
69
+ const color = getDatavizColor(colorIndex);
70
+ const opacity = getDatavizOpacity(colorIndex);
71
+ if (opacity < 0 || opacity > 1) {
72
+ return color;
73
+ }
74
+ return `${color}${Math.floor(opacity * 255).toString(16).padStart(2, "0")}`;
75
+ };
76
+
77
+ // src/components/ColorBox/NetworkColorBox.tsx
78
+ import NETWORK_COLORS from "@sproutsocial/seeds-networkcolor";
79
+ import { jsx as jsx3 } from "react/jsx-runtime";
80
+ var NetworkColorBox = ({
81
+ networkColor,
82
+ ...props
83
+ }) => {
84
+ return /* @__PURE__ */ jsx3(ColorBox, { ...props, bg: NETWORK_COLORS[networkColor] });
85
+ };
86
+
87
+ // src/components/ChartLegend/components/ChartLegendLabel.tsx
88
+ import styled2 from "styled-components";
89
+ import { memo } from "react";
90
+ import { Box as Box2 } from "@sproutsocial/seeds-react-box";
91
+ import { Text } from "@sproutsocial/seeds-react-text";
92
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
93
+ var StyledBox = styled2(Box2)`
94
+ list-style: none;
95
+ display: flex;
96
+ align-items: center;
97
+ gap: ${({ theme: theme6 }) => theme6.space[300]};
98
+ `;
99
+ var ChartLegendLabel = memo(
100
+ function ChartLegendLabel2({
101
+ children,
102
+ color = "#CCC",
103
+ containerBoxProps = {}
104
+ }) {
105
+ return /* @__PURE__ */ jsxs2(StyledBox, { ...containerBoxProps, children: [
106
+ /* @__PURE__ */ jsx4(ColorBox, { bg: color }),
107
+ /* @__PURE__ */ jsx4(Text, { as: "div", fontSize: 200, color: "text.subtext", children })
108
+ ] });
109
+ }
110
+ );
111
+
112
+ // src/components/ChartLegend/ChartLegend.tsx
113
+ import { memo as memo2 } from "react";
114
+ import { Box as Box3 } from "@sproutsocial/seeds-react-box";
115
+ import { theme as theme3 } from "@sproutsocial/seeds-react-theme";
116
+ import { jsx as jsx5 } from "react/jsx-runtime";
117
+ var ChartLegend = memo2(function ChartLegend2({
118
+ legendLabels,
119
+ containerBoxProps = {},
120
+ stacked = false
121
+ }) {
122
+ return /* @__PURE__ */ jsx5(
123
+ Box3,
124
+ {
125
+ as: "ul",
126
+ "aria-hidden": "true",
127
+ display: "flex",
128
+ justifyContent: "center",
129
+ flexDirection: stacked ? "column" : "row",
130
+ flexWrap: "wrap",
131
+ columnGap: 450,
132
+ rowGap: 200,
133
+ m: 0,
134
+ p: 0,
135
+ ...containerBoxProps,
136
+ children: legendLabels.map(({ color, content }, index) => /* @__PURE__ */ jsx5(
137
+ ChartLegendLabel,
138
+ {
139
+ color: color || theme3.colors.DATAVIZ_COLORS_LIST[index],
140
+ containerBoxProps: { as: "li" },
141
+ children: content
142
+ },
143
+ `chart-legend-label-${index}`
144
+ ))
145
+ }
146
+ );
147
+ });
148
+
149
+ // src/components/ChartTooltip/ChartTooltip.tsx
150
+ import { memo as memo3 } from "react";
151
+ import styled3 from "styled-components";
152
+ import { Box as Box4 } from "@sproutsocial/seeds-react-box";
153
+ import { jsx as jsx6 } from "react/jsx-runtime";
154
+ var StyledBox2 = styled3(Box4)`
155
+ .Icon,
156
+ .logo {
157
+ stroke: none;
158
+ }
159
+ `;
160
+ var ChartTooltip = memo3(function ChartTooltip2({
161
+ children
162
+ }) {
163
+ return /* @__PURE__ */ jsx6(
164
+ StyledBox2,
165
+ {
166
+ bg: "container.background.base",
167
+ boxShadow: "medium",
168
+ border: 500,
169
+ borderColor: "container.border.base",
170
+ borderRadius: 500,
171
+ p: 400,
172
+ minWidth: 285,
173
+ children: /* @__PURE__ */ jsx6(Box4, { display: "flex", flexDirection: "column", gap: 350, children })
174
+ }
175
+ );
176
+ });
177
+
178
+ // src/components/ChartTooltip/components/ChartTooltipFooter.tsx
179
+ import { memo as memo4 } from "react";
180
+ import { Box as Box5 } from "@sproutsocial/seeds-react-box";
181
+ import { jsx as jsx7 } from "react/jsx-runtime";
182
+ var ChartTooltipFooter = memo4(
183
+ function ChartTooltipFooter2({ children }) {
184
+ return /* @__PURE__ */ jsx7(
185
+ Box5,
186
+ {
187
+ borderTop: 500,
188
+ borderColor: "container.border.base",
189
+ mx: -400,
190
+ mb: -200,
191
+ px: 400,
192
+ pt: 350,
193
+ children
194
+ }
195
+ );
196
+ }
197
+ );
198
+
199
+ // src/components/ChartTooltip/components/ChartTooltipHeader.tsx
200
+ import { memo as memo5 } from "react";
201
+ import { Box as Box6 } from "@sproutsocial/seeds-react-box";
202
+ import { jsx as jsx8 } from "react/jsx-runtime";
203
+ var ChartTooltipHeader = memo5(
204
+ function ChartTooltipHeader2({ children }) {
205
+ return /* @__PURE__ */ jsx8(
206
+ Box6,
207
+ {
208
+ borderBottom: 500,
209
+ borderColor: "container.border.base",
210
+ mx: -400,
211
+ mt: -200,
212
+ px: 400,
213
+ pb: 350,
214
+ children
215
+ }
216
+ );
217
+ }
218
+ );
219
+
220
+ // src/components/ChartTooltip/components/ChartTooltipPortal.tsx
221
+ import { memo as memo6, useState, useRef, useEffect } from "react";
222
+ import { createPortal } from "react-dom";
223
+ var generateChartTooltipPortalId = (chartId) => `highcharts-custom-tooltip-${chartId}`;
224
+ var ChartTooltipPortal = memo6(
225
+ function ChartTooltipPortal2({
226
+ chart,
227
+ renderContent
228
+ }) {
229
+ const isInitialized = useRef(false);
230
+ const [node, setNode] = useState(null);
231
+ const [context, setContext] = useState(null);
232
+ useEffect(() => {
233
+ const formatter = function() {
234
+ if (!isInitialized.current) {
235
+ isInitialized.current = true;
236
+ chart.tooltip.refresh.apply(chart.tooltip, [this.point]);
237
+ chart.tooltip.hide(0);
238
+ }
239
+ setContext(this);
240
+ return `<div id="${generateChartTooltipPortalId(
241
+ chart.index
242
+ )}" role='tooltip'></div>`;
243
+ };
244
+ chart.update({ tooltip: { formatter } });
245
+ }, [chart]);
246
+ useEffect(() => {
247
+ if (context?.series?.chart?.tooltip) {
248
+ const tooltip = context.series.chart.tooltip;
249
+ const textElement = tooltip.label.text.element;
250
+ tooltip.label.box.attr({
251
+ height: textElement.offsetHeight,
252
+ width: textElement.offsetWidth
253
+ });
254
+ setNode(
255
+ document.getElementById(generateChartTooltipPortalId(chart.index))
256
+ );
257
+ }
258
+ }, [context, chart.index]);
259
+ return node && context ? createPortal(renderContent(context), node) : null;
260
+ }
261
+ );
262
+
263
+ // src/components/ChartTable/ChartTable.tsx
264
+ import { memo as memo7 } from "react";
265
+ import styled4 from "styled-components";
266
+ import { Text as Text2 } from "@sproutsocial/seeds-react-text";
267
+ import { Table as SeedsTable } from "@sproutsocial/seeds-react-table";
268
+ import { jsx as jsx9 } from "react/jsx-runtime";
269
+ var StyledSeedsTable = styled4(SeedsTable)`
270
+ tbody tr:last-child {
271
+ border-bottom: none;
272
+ }
273
+ tr:last-child td,
274
+ tr:last-child th {
275
+ padding-bottom: 0;
276
+ }
277
+ tr:first-child td,
278
+ tr:first-child th {
279
+ padding-top: 0;
280
+ }
281
+ tr th {
282
+ padding-left: 0;
283
+ }
284
+ tr td:last-child {
285
+ padding-right: 0;
286
+ }
287
+ `;
288
+ var StyledSeedsTableRow = styled4(SeedsTable.TableRow)`
289
+ ${({ $isAppendedRow, theme: theme6 }) => $isAppendedRow ? `border-top: 2px solid ${theme6.colors.container.border.base}` : ""}
290
+ `;
291
+ var ChartTable = memo7(function ChartTable2({
292
+ rows
293
+ }) {
294
+ if (!rows || rows.length === 0) {
295
+ return null;
296
+ }
297
+ return /* @__PURE__ */ jsx9(StyledSeedsTable, { children: /* @__PURE__ */ jsx9(SeedsTable.TableBody, { children: rows.map(({ cells, isAppendedRow }, rowIndex) => {
298
+ if (!cells || cells.length === 0) {
299
+ return null;
300
+ }
301
+ return /* @__PURE__ */ jsx9(
302
+ StyledSeedsTableRow,
303
+ {
304
+ $isAppendedRow: isAppendedRow,
305
+ children: cells.map(
306
+ ({ content, align = "left", colSpan = 1 }, cellIndex) => {
307
+ const uniqueIdentifier = `chart-tooltip-table-cell-${cellIndex}`;
308
+ return /* @__PURE__ */ jsx9(
309
+ SeedsTable.Cell,
310
+ {
311
+ id: uniqueIdentifier,
312
+ scope: cellIndex === 0 ? "row" : void 0,
313
+ align,
314
+ colSpan,
315
+ py: 200,
316
+ children: /* @__PURE__ */ jsx9(Text2.SmallBodyCopy, { as: "div", children: content })
317
+ },
318
+ uniqueIdentifier
319
+ );
320
+ }
321
+ )
322
+ },
323
+ `chart-tooltip-table-row-${rowIndex}`
324
+ );
325
+ }) }) });
326
+ });
327
+
328
+ // src/components/ChartTooltip/components/ChartTooltipTable.tsx
329
+ import { memo as memo8 } from "react";
330
+ import { jsx as jsx10 } from "react/jsx-runtime";
331
+ var ChartTooltipTable = memo8(
332
+ function ChartTooltipTable2({ rows }) {
333
+ return /* @__PURE__ */ jsx10(ChartTable, { rows });
334
+ }
335
+ );
336
+
337
+ // src/components/ChartTooltip/components/ChartTooltipTitle.tsx
338
+ import { memo as memo9 } from "react";
339
+ import { Text as Text3 } from "@sproutsocial/seeds-react-text";
340
+ import { jsx as jsx11 } from "react/jsx-runtime";
341
+ var ChartTooltipTitle = memo9(
342
+ function ChartTooltipTitle2({ children }) {
343
+ return /* @__PURE__ */ jsx11(Text3.SmallSubHeadline, { as: "p", children });
344
+ }
345
+ );
346
+
347
+ // src/helpers/transformDataToSeries.ts
348
+ var transformDataToSeries = ({
349
+ data
350
+ }, type) => {
351
+ const hasCategoricalData = data.some(
352
+ (series) => series.points.some((point) => typeof point.x === "string")
353
+ );
354
+ return data.map((dataItem, dataIndex) => {
355
+ const points = dataItem.points || [];
356
+ const dataPoints = points.map((point, pointsIndex) => {
357
+ let enableMarker = false;
358
+ const isFirstPoint = pointsIndex === 0;
359
+ const isLastPoint = pointsIndex === points.length - 1;
360
+ const previousY = isFirstPoint ? null : points[pointsIndex - 1].y;
361
+ const nextY = isLastPoint ? null : points[pointsIndex + 1].y;
362
+ if (isFirstPoint && nextY === null) {
363
+ enableMarker = true;
364
+ } else if (isLastPoint && previousY === null) {
365
+ enableMarker = true;
366
+ } else if (previousY === null && nextY === null) {
367
+ enableMarker = true;
368
+ }
369
+ return {
370
+ x: hasCategoricalData ? pointsIndex : point.x,
371
+ y: point.y,
372
+ marker: {
373
+ enabled: enableMarker ? enableMarker : void 0,
374
+ symbol: enableMarker ? "circle" : void 0
375
+ },
376
+ // For categorical data, store the original category name
377
+ ...hasCategoricalData && { name: point.x }
378
+ };
379
+ });
380
+ return {
381
+ colorIndex: dataIndex,
382
+ data: dataPoints,
383
+ name: dataItem.name,
384
+ type
385
+ };
386
+ });
387
+ };
388
+
389
+ // src/helpers/transformTimeSeriesTooltipData.ts
390
+ import { theme as theme4 } from "@sproutsocial/seeds-react-theme";
391
+ var transformTimeSeriesTooltipData = ({
392
+ context,
393
+ data
394
+ }) => {
395
+ return (context.series.chart.series || []).map((series, index) => {
396
+ const pointIndex = context.point.index;
397
+ const y = series?.points?.[pointIndex]?.y;
398
+ return {
399
+ color: data[index]?.styles?.color || theme4.colors.DATAVIZ_COLORS_LIST[index],
400
+ ...data[index]?.icon ? { icon: data[index]?.icon } : {},
401
+ name: series.name,
402
+ value: typeof y === "number" ? y : null
403
+ };
404
+ });
405
+ };
406
+
407
+ // src/helpers/yAxisLabelFormatter.ts
408
+ import { formatDuration } from "@sproutsocial/seeds-react-duration";
409
+ import { formatNumeral } from "@sproutsocial/seeds-react-numeral";
410
+ var yAxisLabelFormatter = ({
411
+ numberLocale,
412
+ textLocale,
413
+ tickPositions,
414
+ value,
415
+ currency = "USD",
416
+ numberFormat = "decimal"
417
+ }) => {
418
+ const numberValue = Number(value);
419
+ if (numberValue === 0) {
420
+ return formatNumeral({
421
+ locale: numberLocale,
422
+ number: numberValue
423
+ });
424
+ }
425
+ if (numberFormat === "duration") {
426
+ return formatDuration({
427
+ display: "narrow",
428
+ locale: textLocale,
429
+ milliseconds: numberValue
430
+ });
431
+ }
432
+ const maxValue = tickPositions && tickPositions.length > 0 ? tickPositions[tickPositions.length - 1] : void 0;
433
+ const abbreviate = typeof maxValue === "number" && maxValue > 9999 ? 1e3 : true;
434
+ return formatNumeral({
435
+ abbreviate,
436
+ currency,
437
+ format: numberFormat,
438
+ locale: numberLocale,
439
+ number: numberValue
440
+ });
441
+ };
442
+
443
+ // src/helpers/xAxisLabelFormatter.ts
444
+ var getDatePartsInTimezone = (date, timezone) => {
445
+ const formatter = new Intl.DateTimeFormat("en-US", {
446
+ year: "numeric",
447
+ month: "numeric",
448
+ day: "numeric",
449
+ timeZone: timezone
450
+ });
451
+ const parts = formatter.formatToParts(date);
452
+ return {
453
+ day: parseInt(parts.find((p) => p.type === "day")?.value ?? "0", 10),
454
+ month: parseInt(parts.find((p) => p.type === "month")?.value ?? "0", 10),
455
+ year: parseInt(parts.find((p) => p.type === "year")?.value ?? "0", 10)
456
+ };
457
+ };
458
+ var xAxisLabelFormatter = ({
459
+ textLocale,
460
+ tickPositions = [],
461
+ unitName,
462
+ value,
463
+ // optional
464
+ timeFormat = "12",
465
+ timezone = "UTC"
466
+ }) => {
467
+ if (typeof value === "string") {
468
+ return `<span>${value}</span>`;
469
+ }
470
+ const tickIndex = tickPositions.indexOf(value);
471
+ const isFirst = tickIndex === 0;
472
+ const previousValue = tickPositions[tickIndex - 1];
473
+ const valueDate = new Date(value);
474
+ const valueParts = getDatePartsInTimezone(valueDate, timezone);
475
+ const previousValueDate = previousValue ? new Date(previousValue) : void 0;
476
+ const previousValueParts = previousValueDate ? getDatePartsInTimezone(previousValueDate, timezone) : void 0;
477
+ let firstPartOptions = {};
478
+ let secondPartOptions = {};
479
+ switch (unitName) {
480
+ case "hour":
481
+ firstPartOptions = timeFormat === "24" ? { hour: "numeric", minute: "numeric", hour12: false } : { hour: "numeric" };
482
+ if (isFirst || valueParts.day !== previousValueParts?.day) {
483
+ secondPartOptions = { day: "numeric", month: "short" };
484
+ }
485
+ break;
486
+ case "day":
487
+ case "week":
488
+ firstPartOptions = { day: "numeric" };
489
+ if (isFirst || valueParts.month !== previousValueParts?.month) {
490
+ secondPartOptions = { month: "short" };
491
+ }
492
+ break;
493
+ case "month":
494
+ firstPartOptions = { month: "short" };
495
+ if (isFirst || valueParts.year !== previousValueParts?.year) {
496
+ secondPartOptions = { year: "numeric" };
497
+ }
498
+ break;
499
+ case "year":
500
+ firstPartOptions = { year: "numeric" };
501
+ break;
502
+ default:
503
+ firstPartOptions = {};
504
+ break;
505
+ }
506
+ const firstPart = new Intl.DateTimeFormat(textLocale, {
507
+ ...firstPartOptions,
508
+ timeZone: timezone
509
+ }).format(valueDate);
510
+ const secondPart = Object.keys(secondPartOptions).length > 0 ? new Intl.DateTimeFormat(textLocale, {
511
+ ...secondPartOptions,
512
+ timeZone: timezone
513
+ }).format(valueDate) : void 0;
514
+ return `<span>${firstPart}</span>${secondPart ? `<span>${secondPart}</span>` : ""}`;
515
+ };
516
+
517
+ // src/helpers/isHourlyTimeData.ts
518
+ function isHourlyTimeData(data) {
519
+ if (!data.length) return false;
520
+ const xVals = data.flatMap((series) => series.points.map((p) => p.x));
521
+ if (!xVals.length) return false;
522
+ if (xVals.some((x) => typeof x === "string")) return false;
523
+ const dates = xVals.map((x) => {
524
+ const d = new Date(x);
525
+ return `${d.getUTCFullYear()}-${d.getUTCMonth()}-${d.getUTCDate()}`;
526
+ });
527
+ const uniqueDates = new Set(dates);
528
+ if (uniqueDates.size !== 1) return false;
529
+ return xVals.every((x) => {
530
+ const d = new Date(x);
531
+ const hour = d.getUTCHours();
532
+ const minutes = d.getUTCMinutes();
533
+ const seconds = d.getUTCSeconds();
534
+ return hour >= 0 && hour <= 23 && minutes === 0 && seconds === 0;
535
+ });
536
+ }
537
+
538
+ // src/helpers/isCategoricalHourData.ts
539
+ function isCategoricalHourData(data) {
540
+ if (!data.length) return false;
541
+ const xVals = data.flatMap((series) => series.points.map((p) => p.x));
542
+ if (!xVals.length) return false;
543
+ if (xVals.some((x) => typeof x !== "string")) return false;
544
+ const hour12Pattern = /^\d{1,2} (AM|PM)$/;
545
+ const hour24Pattern = /^([01]?\d|2[0-3]):([0-5]\d)$/;
546
+ const stringValues = xVals;
547
+ const allMatch12Hour = stringValues.every((x) => hour12Pattern.test(x));
548
+ const allMatch24Hour = stringValues.every((x) => hour24Pattern.test(x));
549
+ return allMatch12Hour || allMatch24Hour;
550
+ }
551
+
552
+ // src/helpers/getStorybookRandomColor.ts
553
+ var getStorybookRandomColor = () => {
554
+ const letters = "0123456789ABCDEF";
555
+ let color = "#";
556
+ for (let i = 0; i < 6; i++) {
557
+ color += letters[Math.floor(Math.random() * 16)];
558
+ }
559
+ return color;
560
+ };
561
+
562
+ // src/helpers/getStorybookCategoricalData.ts
563
+ var getStorybookCategoricalData = ({
564
+ showNulls,
565
+ showNegativeValues,
566
+ numberOfSeries,
567
+ yAxisMax,
568
+ showCustomColors,
569
+ showDashedLines,
570
+ categoryType
571
+ }) => {
572
+ const categoryOptions = {
573
+ hours: [
574
+ "12 AM",
575
+ "1 AM",
576
+ "2 AM",
577
+ "3 AM",
578
+ "4 AM",
579
+ "5 AM",
580
+ "6 AM",
581
+ "7 AM",
582
+ "8 AM",
583
+ "9 AM",
584
+ "10 AM",
585
+ "11 AM",
586
+ "12 PM",
587
+ "1 PM",
588
+ "2 PM",
589
+ "3 PM",
590
+ "4 PM",
591
+ "5 PM",
592
+ "6 PM",
593
+ "7 PM",
594
+ "8 PM",
595
+ "9 PM",
596
+ "10 PM",
597
+ "11 PM"
598
+ ],
599
+ hours24: [
600
+ "00:00",
601
+ "01:00",
602
+ "02:00",
603
+ "03:00",
604
+ "04:00",
605
+ "05:00",
606
+ "06:00",
607
+ "07:00",
608
+ "08:00",
609
+ "09:00",
610
+ "10:00",
611
+ "11:00",
612
+ "12:00",
613
+ "13:00",
614
+ "14:00",
615
+ "15:00",
616
+ "16:00",
617
+ "17:00",
618
+ "18:00",
619
+ "19:00",
620
+ "20:00",
621
+ "21:00",
622
+ "22:00",
623
+ "23:00"
624
+ ],
625
+ days: [
626
+ "Monday",
627
+ "Tuesday",
628
+ "Wednesday",
629
+ "Thursday",
630
+ "Friday",
631
+ "Saturday",
632
+ "Sunday"
633
+ ],
634
+ months: [
635
+ "January",
636
+ "February",
637
+ "March",
638
+ "April",
639
+ "May",
640
+ "June",
641
+ "July",
642
+ "August",
643
+ "September",
644
+ "October",
645
+ "November",
646
+ "December"
647
+ ],
648
+ custom: [
649
+ "Category A",
650
+ "Category B",
651
+ "Category C",
652
+ "Category D",
653
+ "Category E"
654
+ ]
655
+ };
656
+ const categories = categoryOptions[categoryType];
657
+ const numberOfPoints = categories.length;
658
+ return [...Array(numberOfSeries).keys()].map((seriesIndex) => {
659
+ let nullsArray = [];
660
+ if (showNulls) {
661
+ const nullsArrayLength = Math.floor(numberOfPoints / 5);
662
+ nullsArray = [...Array(nullsArrayLength)].map(
663
+ () => Math.floor(Math.random() * numberOfPoints)
664
+ );
665
+ }
666
+ return {
667
+ points: categories.map((category, pointIndex) => {
668
+ const showNull = nullsArray && nullsArray.length > 0 ? nullsArray.includes(pointIndex) : false;
669
+ const randomValue = Math.random();
670
+ const positiveOrNegativeYAxisMax = showNegativeValues ? randomValue < 0.5 ? -yAxisMax : yAxisMax : yAxisMax;
671
+ return {
672
+ x: category,
673
+ y: showNull ? null : Math.floor(randomValue * positiveOrNegativeYAxisMax)
674
+ };
675
+ }),
676
+ name: `Series ${seriesIndex + 1}`,
677
+ styles: {
678
+ color: showCustomColors ? getStorybookRandomColor() : void 0,
679
+ pattern: showDashedLines ? "dashed" : "solid"
680
+ }
681
+ };
682
+ });
683
+ };
684
+
685
+ // src/helpers/getStorybookSparseTimelineData.ts
686
+ var getStorybookSparseTimelineData = ({
687
+ showNulls,
688
+ showNegativeValues,
689
+ numberOfSeries,
690
+ yAxisMax,
691
+ showCustomColors,
692
+ showDashedLines,
693
+ numberOfPoints = 5,
694
+ timeSpanHours = 24
695
+ }) => {
696
+ const seriesNames = [
697
+ "Posts Published",
698
+ "Comments",
699
+ "Likes",
700
+ "Shares",
701
+ "Clicks",
702
+ "Views",
703
+ "Saves",
704
+ "Reposts",
705
+ "Mentions",
706
+ "Reactions"
707
+ ];
708
+ const baseDate = /* @__PURE__ */ new Date("2024-01-01T00:00:00Z");
709
+ const timeSpanMs = timeSpanHours * 60 * 60 * 1e3;
710
+ return [...Array(numberOfSeries).keys()].map((seriesIndex) => {
711
+ let nullsArray = [];
712
+ if (showNulls) {
713
+ const nullsArrayLength = Math.floor(numberOfPoints / 5);
714
+ nullsArray = [...Array(nullsArrayLength)].map(
715
+ () => Math.floor(Math.random() * numberOfPoints)
716
+ );
717
+ }
718
+ const timestamps = [...Array(numberOfPoints)].map(() => {
719
+ const randomOffset = Math.random() * timeSpanMs;
720
+ return baseDate.getTime() + randomOffset;
721
+ }).sort((a, b) => a - b);
722
+ return {
723
+ points: timestamps.map((timestamp, pointIndex) => {
724
+ const showNull = nullsArray && nullsArray.length > 0 ? nullsArray.includes(pointIndex) : false;
725
+ const randomValue = Math.random();
726
+ const positiveOrNegativeYAxisMax = showNegativeValues ? randomValue < 0.5 ? -yAxisMax : yAxisMax : yAxisMax;
727
+ return {
728
+ x: timestamp,
729
+ y: showNull ? null : Math.floor(randomValue * positiveOrNegativeYAxisMax)
730
+ };
731
+ }),
732
+ name: seriesNames[seriesIndex] || `Series ${seriesIndex + 1}`,
733
+ styles: {
734
+ color: showCustomColors ? getStorybookRandomColor() : void 0,
735
+ pattern: showDashedLines ? "dashed" : "solid"
736
+ }
737
+ };
738
+ });
739
+ };
740
+
741
+ // src/constants/chartOptions.ts
742
+ import _ from "lodash";
743
+ var baseChartOptions = {
744
+ chart: {
745
+ animation: false,
746
+ styledMode: true
747
+ },
748
+ credits: {
749
+ enabled: false
750
+ },
751
+ exporting: {
752
+ enabled: false,
753
+ fallbackToExportServer: false
754
+ },
755
+ legend: {
756
+ enabled: false
757
+ },
758
+ title: {
759
+ text: void 0
760
+ },
761
+ tooltip: {
762
+ hideDelay: 0,
763
+ outside: true,
764
+ padding: 0,
765
+ shape: "rect",
766
+ shared: true,
767
+ useHTML: true
768
+ }
769
+ };
770
+ var TIME_SERIES_CHART_HEIGHT = 275;
771
+ var timeSeriesChartOptions = _.merge({}, baseChartOptions, {
772
+ annotations: [
773
+ {
774
+ draggable: "",
775
+ labelOptions: {
776
+ useHTML: true,
777
+ padding: 0
778
+ // removes "left" property padding created by highcharts so that label is centered
779
+ }
780
+ }
781
+ ],
782
+ chart: {
783
+ // events.click is set at the component level because of the optional onClick prop
784
+ height: TIME_SERIES_CHART_HEIGHT,
785
+ spacing: [5, 1, 0, 2]
786
+ },
787
+ plotOptions: {
788
+ series: {
789
+ animation: false,
790
+ clip: false,
791
+ marker: {
792
+ enabled: false,
793
+ states: {
794
+ hover: {
795
+ enabled: false
796
+ }
797
+ }
798
+ }
799
+ }
800
+ },
801
+ xAxis: {
802
+ crosshair: {
803
+ zIndex: 3
804
+ },
805
+ minPadding: 0,
806
+ // must be handled dynamically instead of css
807
+ maxPadding: 0,
808
+ // must be handled dynamically instead of css
809
+ type: "datetime",
810
+ labels: {
811
+ useHTML: true
812
+ // formatter is set at the component level because of the required text locale prop
813
+ }
814
+ },
815
+ yAxis: {
816
+ labels: {
817
+ useHTML: true
818
+ // formatter is set at the component level because of the optional yAxisLabelFormatter prop
819
+ },
820
+ softMax: 0,
821
+ softMin: 0,
822
+ title: {
823
+ text: void 0
824
+ },
825
+ plotLines: [
826
+ /* Adds a custom plotLine at y=0 to represent the chart baseline.
827
+ This approach allows full control over the line's appearance (e.g., color, z-index),
828
+ unlike relying on the default xAxis line, which always renders at the bottom of the chart
829
+ even when y=0 appears elsewhere (e.g., with negative values).
830
+ */
831
+ {
832
+ className: "y-axis-zero-line",
833
+ value: 0,
834
+ zIndex: 3
835
+ // ensures the line appears over the default y=0 line, which we can't seleect as specifically
836
+ }
837
+ ]
838
+ }
839
+ });
840
+ var lineChartOptions = _.merge({}, timeSeriesChartOptions, {
841
+ // plotOptions.spline.events.click is set at the component level because of the optional onClick prop
842
+ });
843
+ var areaChartOptions = _.merge({}, timeSeriesChartOptions, {
844
+ plotOptions: {
845
+ areaspline: {
846
+ // events.click is set at the component level because of the optional onClick prop
847
+ stacking: "normal"
848
+ }
849
+ }
850
+ });
851
+ var columnChartOptions = _.merge({}, timeSeriesChartOptions, {
852
+ plotOptions: {
853
+ column: {
854
+ stacking: "normal",
855
+ pointPadding: 0.25,
856
+ groupPadding: 0.25,
857
+ borderRadius: 4
858
+ }
859
+ },
860
+ xAxis: {
861
+ crosshair: false
862
+ },
863
+ yAxis: {
864
+ plotLines: [
865
+ {
866
+ // For stacked column charts with visible borders (e.g., white for contrast),
867
+ // we raise the zIndex of the y=0 plotLine to ensure it remains visible
868
+ // and isn't visually covered by overlapping column borders.
869
+ zIndex: 5
870
+ }
871
+ ]
872
+ }
873
+ });
874
+ var VERTICAL_BAR_CHART_DEFAULT_SERIES_LIMIT = 10;
875
+ var DONUT_CHART_HALO_SIZE = 10;
876
+ var DONUT_CHART_HEIGHT = 250 + DONUT_CHART_HALO_SIZE * 2;
877
+ var DONUT_CHART_WIDTH = DONUT_CHART_HEIGHT;
878
+ var donutChartOptions = _.merge({}, baseChartOptions, {
879
+ chart: {
880
+ height: DONUT_CHART_HEIGHT,
881
+ spacing: [0, 0, 0, 0]
882
+ },
883
+ plotOptions: {
884
+ pie: {
885
+ animation: false,
886
+ borderRadius: 0,
887
+ // must be handled here instead of css because of path rendering
888
+ dataLabels: {
889
+ enabled: false
890
+ },
891
+ innerSize: "50%"
892
+ }
893
+ }
894
+ });
895
+
896
+ // src/styles/chartStyles.ts
897
+ import { css as css2, createGlobalStyle as createGlobalStyle2 } from "styled-components";
898
+ import { theme as theme5 } from "@sproutsocial/seeds-react-theme";
899
+ import "highcharts/css/highcharts.css";
900
+ var GlobalChartStyleOverrides = createGlobalStyle2`
901
+ // USAGE NOTE:
902
+ // Put general styles in baseChartStyles instead when possible to avoid excessive global styling.
903
+ // This global component is only for styles that can't override highcharts defaults when scoped.
904
+
905
+ .highcharts-tooltip-container {
906
+ z-index: 7 !important;
907
+ }
908
+ .highcharts-tooltip-box {
909
+ fill: transparent !important;
910
+ }
911
+ `;
912
+ var baseChartStyles = css2`
913
+ --highcharts-background-color: ${({ theme: theme6 }) => theme6.colors.container.background.base};
914
+
915
+ // set color variables and map to each series
916
+ ${({ $colors }) => $colors.map((color, index) => {
917
+ const chartColor = color || theme5.colors.DATAVIZ_COLORS_LIST[index];
918
+ return `
919
+ // map colors to custom assigned colors or fallback to default data viz color rotation
920
+ --highcharts-color-${index}: ${chartColor};
921
+
922
+ // highcharts already accounts for 10 series, but if we have more, we need to add them
923
+ .highcharts-color-${index} {
924
+ color: var(--highcharts-color-${index});
925
+ stroke: var(--highcharts-color-${index});
926
+ fill: var(--highcharts-color-${index});
927
+ }`;
928
+ }).join("\n")}
929
+
930
+ // set overall chart background color
931
+ .highcharts-background {
932
+ fill: ${({ theme: theme6 }) => theme6.colors.container.background.base};
933
+ }
934
+
935
+ g.highcharts-annotation-label {
936
+ display: none;
937
+ }
938
+
939
+ div.highcharts-annotation-label {
940
+ top: 0 !important;
941
+ transform: translateX(-50%); // centers the label on the targeted axis point
942
+ pointer-events: none; // prevents tooltip hover from being interrupted by this element since it renders after on the dom
943
+ }
944
+ `;
945
+ var timeSeriesChartStyles = css2`
946
+ ${baseChartStyles}
947
+
948
+ // vertical crosshair styles
949
+ .highcharts-crosshair {
950
+ stroke: ${({ theme: theme6 }) => theme6.colors.container.border.decorative.neutral};
951
+ stroke-width: 1;
952
+ }
953
+
954
+ // axis and gridline styles
955
+ .highcharts-grid-line {
956
+ stroke: ${({ theme: theme6 }) => theme6.colors.container.border.base};
957
+ }
958
+
959
+ .highcharts-axis-line {
960
+ stroke: ${({ theme: theme6 }) => theme6.colors.container.border.base};
961
+ }
962
+
963
+ .highcharts-tick {
964
+ stroke: none;
965
+ }
966
+ .highcharts-xaxis-labels,
967
+ .highcharts-yaxis-labels {
968
+ // v1 HTML labels (useHTML: true). v2 SVG label styles live in
969
+ // charts/shared/styles.ts (axisLabelV2Styles) — don't add v2 rules here.
970
+ > span {
971
+ font-family: ${({ theme: theme6 }) => theme6.fontFamily};
972
+ ${({ theme: theme6 }) => theme6.typography[100]};
973
+ font-weight: ${({ theme: theme6 }) => theme6.fontWeights.normal};
974
+ color: ${({ theme: theme6 }) => theme6.colors.text.subtext};
975
+ }
976
+ }
977
+ .highcharts-xaxis-labels {
978
+ // v1 HTML stacked labels (useHTML: true). v2 SVG stacked-label styles live
979
+ // in charts/shared/styles.ts (axisLabelV2Styles).
980
+ > span {
981
+ display: flex;
982
+ flex-direction: column;
983
+ align-items: center;
984
+ > span:nth-of-type(2) {
985
+ font-weight: ${({ theme: theme6 }) => theme6.fontWeights.semibold};
986
+ }
987
+ }
988
+ }
989
+
990
+ // we don't want to drop the opacity when another item is hovered
991
+ .highcharts-series-inactive {
992
+ opacity: 1;
993
+ }
994
+
995
+ // apply cursor pointer when click functionality is turned on
996
+ ${({ $hasOnClick }) => $hasOnClick && `
997
+ .highcharts-series,
998
+ .highcharts-point {
999
+ cursor: pointer;
1000
+ }
1001
+ .highcharts-plot-background,
1002
+ .highcharts-crosshair,
1003
+ .highcharts-grid-line {
1004
+ fill: transparent;
1005
+ cursor: pointer;
1006
+ }`}
1007
+
1008
+ path.highcharts-plot-line.y-axis-zero-line {
1009
+ stroke: ${({ theme: theme6 }) => theme6.colors.container.border.decorative.neutral};
1010
+ }
1011
+ `;
1012
+ var lineChartStyles = css2`
1013
+ ${timeSeriesChartStyles}
1014
+
1015
+ // set the line stroke
1016
+ .highcharts-graph {
1017
+ stroke-width: 3;
1018
+ }
1019
+
1020
+ // dashed line styles
1021
+ ${({ $patterns }) => $patterns.map((pattern, index) => {
1022
+ return pattern === "dashed" ? `
1023
+ // highcharts already accounts for 10 series, but if we have more, we need to add them
1024
+ .highcharts-series-${index} {
1025
+ stroke-dasharray: 2, 8;
1026
+ }` : "";
1027
+ })}
1028
+ `;
1029
+ var areaChartStyles = css2`
1030
+ ${timeSeriesChartStyles}
1031
+
1032
+ // don't need to show a stroke for the line part of each area
1033
+ .highcharts-graph {
1034
+ stroke-width: 0;
1035
+ }
1036
+
1037
+ // fill areas to full opacity
1038
+ .highcharts-area {
1039
+ fill-opacity: 1;
1040
+ }
1041
+ `;
1042
+ var donutChartStyles = css2`
1043
+ ${baseChartStyles}
1044
+
1045
+ // remove 250ms fade in/out when hovering over different donut chart slices
1046
+ .highcharts-point {
1047
+ transition: opacity 0s;
1048
+ }
1049
+
1050
+ // remove stroke on donut slices
1051
+ .highcharts-pie-series .highcharts-point {
1052
+ stroke: none;
1053
+ }
1054
+
1055
+ // don't reduce opacity when hovering
1056
+ .highcharts-point-hover {
1057
+ fill-opacity: none;
1058
+ }
1059
+
1060
+ // apply cursor pointer when click functionality is turned on
1061
+ ${({ $hasOnClick }) => $hasOnClick && `
1062
+ .highcharts-series,
1063
+ .highcharts-point {
1064
+ cursor: pointer;
1065
+ }
1066
+ .highcharts-plot-background,
1067
+ .highcharts-crosshair,
1068
+ .highcharts-grid-line {
1069
+ fill: transparent;
1070
+ cursor: pointer;
1071
+ }`}
1072
+ `;
1073
+
1074
+ // src/components/ChartLegend/components/ChartLegendLabelContentWithIcon.tsx
1075
+ import { memo as memo10 } from "react";
1076
+ import { Box as Box7 } from "@sproutsocial/seeds-react-box";
1077
+ import { jsxs as jsxs3 } from "react/jsx-runtime";
1078
+ var ChartLegendLabelContentWithIcon = memo10(
1079
+ function ChartLegendLabelContentWithIcon2({
1080
+ children,
1081
+ icon
1082
+ }) {
1083
+ return icon ? /* @__PURE__ */ jsxs3(Box7, { display: "flex", alignItems: "center", gap: 200, children: [
1084
+ icon,
1085
+ children
1086
+ ] }) : children;
1087
+ }
1088
+ );
1089
+
1090
+ // src/components/VerticalBarChart/styles.ts
1091
+ import { css as css3 } from "styled-components";
1092
+ var verticalBarChartStyles = css3`
1093
+ ${timeSeriesChartStyles}
1094
+
1095
+ /*
1096
+ When the chart container is hovered, reduce the opacity of all columns.
1097
+ Then, for the column that is being hovered, restore its opacity.
1098
+ This gives the effect of fading out the non-hovered columns.
1099
+ */
1100
+ .highcharts-container:hover .highcharts-point {
1101
+ fill-opacity: 0.3;
1102
+ }
1103
+
1104
+ .highcharts-point.column-hover {
1105
+ fill-opacity: 1 !important;
1106
+ }
1107
+ `;
1108
+
1109
+ export {
1110
+ ColorBox,
1111
+ DatavizColorBox,
1112
+ getDatavizColor,
1113
+ getDatavizOpacity,
1114
+ getDatavizColorWithAlpha,
1115
+ NetworkColorBox,
1116
+ ChartLegendLabel,
1117
+ ChartLegend,
1118
+ ChartLegendLabelContentWithIcon,
1119
+ ChartTooltip,
1120
+ ChartTooltipFooter,
1121
+ ChartTooltipHeader,
1122
+ generateChartTooltipPortalId,
1123
+ ChartTooltipPortal,
1124
+ ChartTable,
1125
+ ChartTooltipTable,
1126
+ ChartTooltipTitle,
1127
+ transformDataToSeries,
1128
+ transformTimeSeriesTooltipData,
1129
+ yAxisLabelFormatter,
1130
+ xAxisLabelFormatter,
1131
+ isHourlyTimeData,
1132
+ isCategoricalHourData,
1133
+ getStorybookCategoricalData,
1134
+ getStorybookSparseTimelineData,
1135
+ baseChartOptions,
1136
+ TIME_SERIES_CHART_HEIGHT,
1137
+ timeSeriesChartOptions,
1138
+ lineChartOptions,
1139
+ areaChartOptions,
1140
+ columnChartOptions,
1141
+ VERTICAL_BAR_CHART_DEFAULT_SERIES_LIMIT,
1142
+ DONUT_CHART_HALO_SIZE,
1143
+ DONUT_CHART_HEIGHT,
1144
+ DONUT_CHART_WIDTH,
1145
+ donutChartOptions,
1146
+ GlobalChartStyleOverrides,
1147
+ baseChartStyles,
1148
+ timeSeriesChartStyles,
1149
+ lineChartStyles,
1150
+ areaChartStyles,
1151
+ donutChartStyles,
1152
+ verticalBarChartStyles
1153
+ };
1154
+ //# sourceMappingURL=chunk-CDBW4SOR.js.map