@bikdotai/bik-component-library 0.0.859 → 0.0.860-beta.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.
Files changed (65) hide show
  1. package/README.md +9 -0
  2. package/dist/cjs/components/analytics-chips-and-dropdowns/AnalyticsTrend.js +1 -1
  3. package/dist/cjs/components/analytics-chips-and-dropdowns/AnalyticsTrend.js.map +1 -1
  4. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/ChartLayout.js +2 -0
  5. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/ChartLayout.js.map +1 -0
  6. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/ComparisonBarChart/ComparisonBarChart.js +2 -0
  7. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/ComparisonBarChart/ComparisonBarChart.js.map +1 -0
  8. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/ComparisonBarChart/ComparisonBarChart.styled.js +50 -0
  9. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/ComparisonBarChart/ComparisonBarChart.styled.js.map +1 -0
  10. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/FunnelChart/FunnelChart.js +2 -0
  11. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/FunnelChart/FunnelChart.js.map +1 -0
  12. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/FunnelChart/FunnelChart.styled.js +43 -0
  13. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/FunnelChart/FunnelChart.styled.js.map +1 -0
  14. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/FunnelChart/funnelGeometry.js +2 -0
  15. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/FunnelChart/funnelGeometry.js.map +1 -0
  16. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/HorizontalBarGraph/HorizontalGraph.js +1 -1
  17. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/HorizontalBarGraph/HorizontalGraph.js.map +1 -1
  18. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/StackedBarChart/StackedBarChart.js +1 -1
  19. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/StackedBarChart/StackedBarChart.js.map +1 -1
  20. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/StackedBarChart/StackedBarChart.model.js.map +1 -1
  21. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/chartPalette.js +2 -0
  22. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/chartPalette.js.map +1 -0
  23. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/formatChartValue.js +2 -0
  24. package/dist/cjs/components/analytics-chips-and-dropdowns/chart/formatChartValue.js.map +1 -0
  25. package/dist/cjs/index.js +1 -1
  26. package/dist/esm/components/analytics-chips-and-dropdowns/AnalyticsTrend.d.ts +3 -0
  27. package/dist/esm/components/analytics-chips-and-dropdowns/AnalyticsTrend.js +182 -172
  28. package/dist/esm/components/analytics-chips-and-dropdowns/AnalyticsTrend.js.map +1 -1
  29. package/dist/esm/components/analytics-chips-and-dropdowns/chart/ChartLayout.d.ts +16 -0
  30. package/dist/esm/components/analytics-chips-and-dropdowns/chart/ChartLayout.js +69 -0
  31. package/dist/esm/components/analytics-chips-and-dropdowns/chart/ChartLayout.js.map +1 -0
  32. package/dist/esm/components/analytics-chips-and-dropdowns/chart/ComparisonBarChart/ComparisonBarChart.d.ts +3 -0
  33. package/dist/esm/components/analytics-chips-and-dropdowns/chart/ComparisonBarChart/ComparisonBarChart.js +110 -0
  34. package/dist/esm/components/analytics-chips-and-dropdowns/chart/ComparisonBarChart/ComparisonBarChart.js.map +1 -0
  35. package/dist/esm/components/analytics-chips-and-dropdowns/chart/ComparisonBarChart/ComparisonBarChart.model.d.ts +21 -0
  36. package/dist/esm/components/analytics-chips-and-dropdowns/chart/ComparisonBarChart/ComparisonBarChart.styled.d.ts +16 -0
  37. package/dist/esm/components/analytics-chips-and-dropdowns/chart/ComparisonBarChart/ComparisonBarChart.styled.js +61 -0
  38. package/dist/esm/components/analytics-chips-and-dropdowns/chart/ComparisonBarChart/ComparisonBarChart.styled.js.map +1 -0
  39. package/dist/esm/components/analytics-chips-and-dropdowns/chart/FunnelChart/FunnelChart.d.ts +3 -0
  40. package/dist/esm/components/analytics-chips-and-dropdowns/chart/FunnelChart/FunnelChart.js +109 -0
  41. package/dist/esm/components/analytics-chips-and-dropdowns/chart/FunnelChart/FunnelChart.js.map +1 -0
  42. package/dist/esm/components/analytics-chips-and-dropdowns/chart/FunnelChart/FunnelChart.model.d.ts +19 -0
  43. package/dist/esm/components/analytics-chips-and-dropdowns/chart/FunnelChart/FunnelChart.styled.d.ts +16 -0
  44. package/dist/esm/components/analytics-chips-and-dropdowns/chart/FunnelChart/FunnelChart.styled.js +54 -0
  45. package/dist/esm/components/analytics-chips-and-dropdowns/chart/FunnelChart/FunnelChart.styled.js.map +1 -0
  46. package/dist/esm/components/analytics-chips-and-dropdowns/chart/FunnelChart/funnelGeometry.d.ts +23 -0
  47. package/dist/esm/components/analytics-chips-and-dropdowns/chart/FunnelChart/funnelGeometry.js +48 -0
  48. package/dist/esm/components/analytics-chips-and-dropdowns/chart/FunnelChart/funnelGeometry.js.map +1 -0
  49. package/dist/esm/components/analytics-chips-and-dropdowns/chart/HorizontalBarGraph/HorizontalGraph.js +16 -15
  50. package/dist/esm/components/analytics-chips-and-dropdowns/chart/HorizontalBarGraph/HorizontalGraph.js.map +1 -1
  51. package/dist/esm/components/analytics-chips-and-dropdowns/chart/StackedBarChart/StackedBarChart.js +1 -1
  52. package/dist/esm/components/analytics-chips-and-dropdowns/chart/StackedBarChart/StackedBarChart.js.map +1 -1
  53. package/dist/esm/components/analytics-chips-and-dropdowns/chart/StackedBarChart/StackedBarChart.model.d.ts +1 -0
  54. package/dist/esm/components/analytics-chips-and-dropdowns/chart/StackedBarChart/StackedBarChart.model.js.map +1 -1
  55. package/dist/esm/components/analytics-chips-and-dropdowns/chart/chartPalette.d.ts +3 -0
  56. package/dist/esm/components/analytics-chips-and-dropdowns/chart/chartPalette.js +18 -0
  57. package/dist/esm/components/analytics-chips-and-dropdowns/chart/chartPalette.js.map +1 -0
  58. package/dist/esm/components/analytics-chips-and-dropdowns/chart/formatChartValue.d.ts +4 -0
  59. package/dist/esm/components/analytics-chips-and-dropdowns/chart/formatChartValue.js +13 -0
  60. package/dist/esm/components/analytics-chips-and-dropdowns/chart/formatChartValue.js.map +1 -0
  61. package/dist/esm/components/analytics-chips-and-dropdowns/index.d.ts +4 -0
  62. package/dist/esm/icons/index.d.ts +25 -25
  63. package/dist/esm/index.js +383 -379
  64. package/dist/esm/index.js.map +1 -1
  65. package/package.json +1 -1
@@ -0,0 +1,69 @@
1
+ import { jsxs as a, jsx as i } from "react/jsx-runtime";
2
+ import { TitleRegular as s, TitleMedium as c, BodyCaption as p } from "../../TypographyStyle.js";
3
+ import { COLORS as r } from "../../../constants/Theme.js";
4
+ const x = ({
5
+ title: e,
6
+ padding: o,
7
+ gap: d,
8
+ dataTest: t,
9
+ wrapperStyle: l,
10
+ children: n
11
+ }) => /* @__PURE__ */ a(
12
+ "div",
13
+ {
14
+ "data-test": t,
15
+ style: {
16
+ display: "flex",
17
+ flexDirection: "column",
18
+ gap: d,
19
+ width: "100%",
20
+ padding: o,
21
+ borderRadius: 8,
22
+ border: `1px solid ${r.stroke.primary}`,
23
+ backgroundColor: r.surface.standard,
24
+ ...l
25
+ },
26
+ children: [
27
+ e && /* @__PURE__ */ i(s, { color: r.content.primary, children: e }),
28
+ n
29
+ ]
30
+ }
31
+ ), f = ({
32
+ value: e,
33
+ chip: o
34
+ }) => /* @__PURE__ */ a(
35
+ "div",
36
+ {
37
+ style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" },
38
+ children: [
39
+ /* @__PURE__ */ i(
40
+ c,
41
+ {
42
+ color: r.content.primary,
43
+ style: { whiteSpace: "nowrap" },
44
+ children: e
45
+ }
46
+ ),
47
+ o && /* @__PURE__ */ i(
48
+ "div",
49
+ {
50
+ style: {
51
+ display: "inline-flex",
52
+ alignItems: "center",
53
+ padding: "4px 8px",
54
+ borderRadius: 4,
55
+ border: `1px solid ${r.stroke.primary}`,
56
+ backgroundColor: r.surface.subdued,
57
+ whiteSpace: "nowrap"
58
+ },
59
+ children: /* @__PURE__ */ i(p, { color: r.content.secondary, children: o })
60
+ }
61
+ )
62
+ ]
63
+ }
64
+ );
65
+ export {
66
+ x as ChartCard,
67
+ f as ChartValueRow
68
+ };
69
+ //# sourceMappingURL=ChartLayout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChartLayout.js","sources":["../../../../../src/components/analytics-chips-and-dropdowns/chart/ChartLayout.tsx"],"sourcesContent":["import React, { CSSProperties, ReactNode } from 'react';\nimport {\n\tBodyCaption,\n\tTitleMedium,\n\tTitleRegular,\n} from '@src/components/TypographyStyle';\nimport { COLORS } from '@src/constants/Theme';\n\ninterface ChartCardProps {\n\ttitle?: string;\n\tpadding: CSSProperties['padding'];\n\tgap: number;\n\tdataTest: string;\n\twrapperStyle?: CSSProperties;\n\tchildren: ReactNode;\n}\n\nexport const ChartCard: React.FC<ChartCardProps> = ({\n\ttitle,\n\tpadding,\n\tgap,\n\tdataTest,\n\twrapperStyle,\n\tchildren,\n}) => (\n\t<div\n\t\tdata-test={dataTest}\n\t\tstyle={{\n\t\t\tdisplay: 'flex',\n\t\t\tflexDirection: 'column',\n\t\t\tgap,\n\t\t\twidth: '100%',\n\t\t\tpadding,\n\t\t\tborderRadius: 8,\n\t\t\tborder: `1px solid ${COLORS.stroke.primary}`,\n\t\t\tbackgroundColor: COLORS.surface.standard,\n\t\t\t...wrapperStyle,\n\t\t}}\n\t>\n\t\t{title && (\n\t\t\t<TitleRegular color={COLORS.content.primary}>{title}</TitleRegular>\n\t\t)}\n\t\t{children}\n\t</div>\n);\n\ninterface ChartValueRowProps {\n\tvalue: ReactNode;\n\tchip?: ReactNode;\n}\n\nexport const ChartValueRow: React.FC<ChartValueRowProps> = ({\n\tvalue,\n\tchip,\n}) => (\n\t<div\n\t\tstyle={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}\n\t>\n\t\t<TitleMedium\n\t\t\tcolor={COLORS.content.primary}\n\t\t\tstyle={{ whiteSpace: 'nowrap' }}\n\t\t>\n\t\t\t{value}\n\t\t</TitleMedium>\n\t\t{chip && (\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tdisplay: 'inline-flex',\n\t\t\t\t\talignItems: 'center',\n\t\t\t\t\tpadding: '4px 8px',\n\t\t\t\t\tborderRadius: 4,\n\t\t\t\t\tborder: `1px solid ${COLORS.stroke.primary}`,\n\t\t\t\t\tbackgroundColor: COLORS.surface.subdued,\n\t\t\t\t\twhiteSpace: 'nowrap',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<BodyCaption color={COLORS.content.secondary}>{chip}</BodyCaption>\n\t\t\t</div>\n\t\t)}\n\t</div>\n);\n"],"names":["ChartCard","title","padding","gap","dataTest","wrapperStyle","children","jsxs","COLORS","TitleRegular","ChartValueRow","value","chip","jsx","TitleMedium","BodyCaption"],"mappings":";;;AAiBO,MAAMA,IAAsC,CAAC;AAAA,EACnD,OAAAC;AAAA,EACA,SAAAC;AAAA,EACA,KAAAC;AAAA,EACA,UAAAC;AAAA,EACA,cAAAC;AAAA,EACA,UAAAC;AACD,MACC,gBAAAC;AAAA,EAAC;AAAA,EAAA;AAAA,IACA,aAAWH;AAAA,IACX,OAAO;AAAA,MACN,SAAS;AAAA,MACT,eAAe;AAAA,MACf,KAAAD;AAAA,MACA,OAAO;AAAA,MACP,SAAAD;AAAA,MACA,cAAc;AAAA,MACd,QAAQ,aAAaM,EAAO,OAAO,OAAO;AAAA,MAC1C,iBAAiBA,EAAO,QAAQ;AAAA,MAChC,GAAGH;AAAA,IAAA;AAAA,IAGH,UAAA;AAAA,MAAAJ,uBACCQ,GAAA,EAAa,OAAOD,EAAO,QAAQ,SAAU,UAAAP,GAAM;AAAA,MAEpDK;AAAA,IAAA;AAAA,EAAA;AACF,GAQYI,IAA8C,CAAC;AAAA,EAC3D,OAAAC;AAAA,EACA,MAAAC;AACD,MACC,gBAAAL;AAAA,EAAC;AAAA,EAAA;AAAA,IACA,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,GAAG,UAAU,OAAA;AAAA,IAElE,UAAA;AAAA,MAAA,gBAAAM;AAAA,QAACC;AAAA,QAAA;AAAA,UACA,OAAON,EAAO,QAAQ;AAAA,UACtB,OAAO,EAAE,YAAY,SAAA;AAAA,UAEpB,UAAAG;AAAA,QAAA;AAAA,MAAA;AAAA,MAEDC,KACA,gBAAAC;AAAA,QAAC;AAAA,QAAA;AAAA,UACA,OAAO;AAAA,YACN,SAAS;AAAA,YACT,YAAY;AAAA,YACZ,SAAS;AAAA,YACT,cAAc;AAAA,YACd,QAAQ,aAAaL,EAAO,OAAO,OAAO;AAAA,YAC1C,iBAAiBA,EAAO,QAAQ;AAAA,YAChC,YAAY;AAAA,UAAA;AAAA,UAGb,4BAACO,GAAA,EAAY,OAAOP,EAAO,QAAQ,WAAY,UAAAI,EAAA,CAAK;AAAA,QAAA;AAAA,MAAA;AAAA,IACrD;AAAA,EAAA;AAEF;"}
@@ -0,0 +1,3 @@
1
+ import { default as React } from 'react';
2
+ import { ComparisonBarChartI } from './ComparisonBarChart.model';
3
+ export declare const ComparisonBarChart: React.FC<ComparisonBarChartI>;
@@ -0,0 +1,110 @@
1
+ import { jsx as e, jsxs as s } from "react/jsx-runtime";
2
+ import { useMemo as R, useState as g } from "react";
3
+ import { BodyCaption as y } from "../../../TypographyStyle.js";
4
+ import { COLORS as $ } from "../../../../constants/Theme.js";
5
+ import { ChartCard as w, ChartValueRow as A } from "../ChartLayout.js";
6
+ import { pickColor as O, COMPARISON_BAR_COLORS as M } from "../chartPalette.js";
7
+ import { toChartValue as i, formatPercent as S, clamp as k, formatChartValue as T } from "../formatChartValue.js";
8
+ import { BarRowLayout as x, BarLabelColumn as _, BarArea as E, BarTrack as H, BarFill as I, BarTooltip as P, BarTooltipArrow as V } from "./ComparisonBarChart.styled.js";
9
+ const b = Array.from(
10
+ { length: 2 },
11
+ (r, n) => ({ key: `placeholder-${n}`, label: "", value: 0 })
12
+ ), j = ({
13
+ row: { bar: r, fillWidth: n, color: c, percentageLabel: l },
14
+ labelWidth: m,
15
+ barHeight: p,
16
+ showTooltip: h,
17
+ locale: d
18
+ }) => {
19
+ const [u, o] = g(!1);
20
+ return /* @__PURE__ */ s(x, { children: [
21
+ /* @__PURE__ */ s(_, { $width: m, children: [
22
+ /* @__PURE__ */ e(y, { color: $.content.secondary, children: r.label }),
23
+ /* @__PURE__ */ e(
24
+ A,
25
+ {
26
+ value: r.valueLabel ?? T(i(r.value), d),
27
+ chip: l
28
+ }
29
+ )
30
+ ] }),
31
+ /* @__PURE__ */ s(
32
+ E,
33
+ {
34
+ "data-test": `comparison-bar-chart-bar-${r.key}`,
35
+ onMouseEnter: () => o(!0),
36
+ onMouseLeave: () => o(!1),
37
+ $height: p,
38
+ children: [
39
+ /* @__PURE__ */ e(H, { "data-test": `comparison-bar-chart-track-${r.key}`, children: /* @__PURE__ */ e(
40
+ I,
41
+ {
42
+ "data-test": `comparison-bar-chart-fill-${r.key}`,
43
+ $width: n,
44
+ $color: c
45
+ }
46
+ ) }),
47
+ h && u && /* @__PURE__ */ s(
48
+ P,
49
+ {
50
+ "data-test": `comparison-bar-chart-tooltip-${r.key}`,
51
+ $left: k(n / 2, 8, 92),
52
+ children: [
53
+ /* @__PURE__ */ e(V, {}),
54
+ /* @__PURE__ */ e(y, { color: $.content.primaryInverse, children: l })
55
+ ]
56
+ }
57
+ )
58
+ ]
59
+ }
60
+ )
61
+ ] });
62
+ }, Q = ({
63
+ bars: r = [],
64
+ title: n,
65
+ total: c,
66
+ colors: l = M,
67
+ labelWidth: m = 180,
68
+ barHeight: p = 52,
69
+ locale: h,
70
+ showTooltip: d = !0,
71
+ wrapperStyle: u
72
+ }) => {
73
+ const o = r.some((t) => i(t.value) > 0), f = r.length ? r : b, L = R(() => {
74
+ const t = c !== void 0 ? i(c) : f.reduce((a, v) => a + i(v.value), 0);
75
+ return f.map((a, v) => {
76
+ const C = a.percentage ?? (t > 0 ? i(a.value) / t * 100 : 0), B = Number.isFinite(C) ? Math.max(C, 0) : 0;
77
+ return {
78
+ bar: a,
79
+ fillWidth: k(B, 0, 100),
80
+ color: o ? a.color ?? O(l, v) : void 0,
81
+ percentageLabel: o ? a.percentageLabel ?? `${S(B)}%` : ""
82
+ };
83
+ });
84
+ }, [f, c, l, o]);
85
+ return /* @__PURE__ */ e(
86
+ w,
87
+ {
88
+ dataTest: "comparison-bar-chart",
89
+ title: n,
90
+ padding: 24,
91
+ gap: 24,
92
+ wrapperStyle: u,
93
+ children: L.map((t) => /* @__PURE__ */ e(
94
+ j,
95
+ {
96
+ row: t,
97
+ labelWidth: m,
98
+ barHeight: p,
99
+ showTooltip: d && o,
100
+ locale: h
101
+ },
102
+ t.bar.key
103
+ ))
104
+ }
105
+ );
106
+ };
107
+ export {
108
+ Q as ComparisonBarChart
109
+ };
110
+ //# sourceMappingURL=ComparisonBarChart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ComparisonBarChart.js","sources":["../../../../../../src/components/analytics-chips-and-dropdowns/chart/ComparisonBarChart/ComparisonBarChart.tsx"],"sourcesContent":["import React, { useMemo, useState } from 'react';\nimport { BodyCaption } from '@src/components/TypographyStyle';\nimport { COLORS } from '@src/constants/Theme';\nimport { ChartCard, ChartValueRow } from '../ChartLayout';\nimport { COMPARISON_BAR_COLORS, pickColor } from '../chartPalette';\nimport {\n\tclamp,\n\tformatChartValue,\n\tformatPercent,\n\ttoChartValue,\n} from '../formatChartValue';\nimport type {\n\tComparisonBarChartI,\n\tComparisonBarI,\n} from './ComparisonBarChart.model';\nimport {\n\tBarArea,\n\tBarFill,\n\tBarLabelColumn,\n\tBarRowLayout,\n\tBarTooltip,\n\tBarTooltipArrow,\n\tBarTrack,\n} from './ComparisonBarChart.styled';\n\nconst PLACEHOLDER_BARS: ComparisonBarI[] = Array.from(\n\t{ length: 2 },\n\t(_, index) => ({ key: `placeholder-${index}`, label: '', value: 0 }),\n);\n\ninterface PreparedBar {\n\tbar: ComparisonBarI;\n\tfillWidth: number;\n\tcolor?: string;\n\tpercentageLabel: string;\n}\n\ninterface BarRowProps {\n\trow: PreparedBar;\n\tlabelWidth: number;\n\tbarHeight: number;\n\tshowTooltip: boolean;\n\tlocale?: string;\n}\n\nconst BarRow: React.FC<BarRowProps> = ({\n\trow: { bar, fillWidth, color, percentageLabel },\n\tlabelWidth,\n\tbarHeight,\n\tshowTooltip,\n\tlocale,\n}) => {\n\tconst [isHovered, setIsHovered] = useState(false);\n\n\treturn (\n\t\t<BarRowLayout>\n\t\t\t<BarLabelColumn $width={labelWidth}>\n\t\t\t\t<BodyCaption color={COLORS.content.secondary}>{bar.label}</BodyCaption>\n\t\t\t\t<ChartValueRow\n\t\t\t\t\tvalue={\n\t\t\t\t\t\tbar.valueLabel ?? formatChartValue(toChartValue(bar.value), locale)\n\t\t\t\t\t}\n\t\t\t\t\tchip={percentageLabel}\n\t\t\t\t/>\n\t\t\t</BarLabelColumn>\n\n\t\t\t<BarArea\n\t\t\t\tdata-test={`comparison-bar-chart-bar-${bar.key}`}\n\t\t\t\tonMouseEnter={() => setIsHovered(true)}\n\t\t\t\tonMouseLeave={() => setIsHovered(false)}\n\t\t\t\t$height={barHeight}\n\t\t\t>\n\t\t\t\t<BarTrack data-test={`comparison-bar-chart-track-${bar.key}`}>\n\t\t\t\t\t<BarFill\n\t\t\t\t\t\tdata-test={`comparison-bar-chart-fill-${bar.key}`}\n\t\t\t\t\t\t$width={fillWidth}\n\t\t\t\t\t\t$color={color}\n\t\t\t\t\t/>\n\t\t\t\t</BarTrack>\n\t\t\t\t{showTooltip && isHovered && (\n\t\t\t\t\t<BarTooltip\n\t\t\t\t\t\tdata-test={`comparison-bar-chart-tooltip-${bar.key}`}\n\t\t\t\t\t\t$left={clamp(fillWidth / 2, 8, 92)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<BarTooltipArrow />\n\t\t\t\t\t\t<BodyCaption color={COLORS.content.primaryInverse}>\n\t\t\t\t\t\t\t{percentageLabel}\n\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t</BarTooltip>\n\t\t\t\t)}\n\t\t\t</BarArea>\n\t\t</BarRowLayout>\n\t);\n};\n\nexport const ComparisonBarChart: React.FC<ComparisonBarChartI> = ({\n\tbars = [],\n\ttitle,\n\ttotal,\n\tcolors = COMPARISON_BAR_COLORS,\n\tlabelWidth = 180,\n\tbarHeight = 52,\n\tlocale,\n\tshowTooltip = true,\n\twrapperStyle,\n}) => {\n\tconst hasData = bars.some((bar) => toChartValue(bar.value) > 0);\n\tconst visibleBars = bars.length ? bars : PLACEHOLDER_BARS;\n\n\tconst rows = useMemo<PreparedBar[]>(() => {\n\t\tconst denominator =\n\t\t\ttotal !== undefined\n\t\t\t\t? toChartValue(total)\n\t\t\t\t: visibleBars.reduce((sum, bar) => sum + toChartValue(bar.value), 0);\n\n\t\treturn visibleBars.map((bar, index) => {\n\t\t\tconst percentage =\n\t\t\t\tbar.percentage ??\n\t\t\t\t(denominator > 0 ? (toChartValue(bar.value) / denominator) * 100 : 0);\n\t\t\tconst share = Number.isFinite(percentage) ? Math.max(percentage, 0) : 0;\n\t\t\treturn {\n\t\t\t\tbar,\n\t\t\t\tfillWidth: clamp(share, 0, 100),\n\t\t\t\tcolor: hasData ? bar.color ?? pickColor(colors, index) : undefined,\n\t\t\t\tpercentageLabel: hasData\n\t\t\t\t\t? bar.percentageLabel ?? `${formatPercent(share)}%`\n\t\t\t\t\t: '',\n\t\t\t};\n\t\t});\n\t}, [visibleBars, total, colors, hasData]);\n\n\treturn (\n\t\t<ChartCard\n\t\t\tdataTest=\"comparison-bar-chart\"\n\t\t\ttitle={title}\n\t\t\tpadding={24}\n\t\t\tgap={24}\n\t\t\twrapperStyle={wrapperStyle}\n\t\t>\n\t\t\t{rows.map((row) => (\n\t\t\t\t<BarRow\n\t\t\t\t\tkey={row.bar.key}\n\t\t\t\t\trow={row}\n\t\t\t\t\tlabelWidth={labelWidth}\n\t\t\t\t\tbarHeight={barHeight}\n\t\t\t\t\tshowTooltip={showTooltip && hasData}\n\t\t\t\t\tlocale={locale}\n\t\t\t\t/>\n\t\t\t))}\n\t\t</ChartCard>\n\t);\n};\n"],"names":["PLACEHOLDER_BARS","_","index","BarRow","bar","fillWidth","color","percentageLabel","labelWidth","barHeight","showTooltip","locale","isHovered","setIsHovered","useState","BarRowLayout","jsxs","BarLabelColumn","jsx","BodyCaption","COLORS","ChartValueRow","formatChartValue","toChartValue","BarArea","BarTrack","BarFill","BarTooltip","clamp","BarTooltipArrow","ComparisonBarChart","bars","title","total","colors","COMPARISON_BAR_COLORS","wrapperStyle","hasData","visibleBars","rows","useMemo","denominator","sum","percentage","share","pickColor","formatPercent","ChartCard","row"],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { CSSProperties } from 'react';
2
+ export interface ComparisonBarI {
3
+ key: string;
4
+ label: string;
5
+ value: number;
6
+ valueLabel?: string;
7
+ percentage?: number;
8
+ percentageLabel?: string;
9
+ color?: string;
10
+ }
11
+ export interface ComparisonBarChartI {
12
+ bars: ComparisonBarI[];
13
+ title?: string;
14
+ total?: number;
15
+ colors?: string[];
16
+ labelWidth?: number;
17
+ barHeight?: number;
18
+ locale?: string;
19
+ showTooltip?: boolean;
20
+ wrapperStyle?: CSSProperties;
21
+ }
@@ -0,0 +1,16 @@
1
+ export declare const BarRowLayout: import('styled-components').StyledComponent<"div", any, {}, never>;
2
+ export declare const BarLabelColumn: import('styled-components').StyledComponent<"div", any, {
3
+ $width: number;
4
+ }, never>;
5
+ export declare const BarArea: import('styled-components').StyledComponent<"div", any, {
6
+ $height: number;
7
+ }, never>;
8
+ export declare const BarTrack: import('styled-components').StyledComponent<"div", any, {}, never>;
9
+ export declare const BarFill: import('styled-components').StyledComponent<"div", any, {
10
+ $width: number;
11
+ $color?: string | undefined;
12
+ }, never>;
13
+ export declare const BarTooltip: import('styled-components').StyledComponent<"div", any, {
14
+ $left: number;
15
+ }, never>;
16
+ export declare const BarTooltipArrow: import('styled-components').StyledComponent<"div", any, {}, never>;
@@ -0,0 +1,61 @@
1
+ import t from "styled-components";
2
+ import { COLORS as r } from "../../../../constants/Theme.js";
3
+ const a = t.div`
4
+ display: flex;
5
+ align-items: center;
6
+ gap: 32px;
7
+ `, n = t.div`
8
+ width: ${(o) => o.$width}px;
9
+ flex-shrink: 0;
10
+ display: flex;
11
+ flex-direction: column;
12
+ gap: 8px;
13
+ `, p = t.div`
14
+ position: relative;
15
+ flex: 1;
16
+ height: ${(o) => o.$height}px;
17
+ `, s = t.div`
18
+ position: absolute;
19
+ inset: 0;
20
+ border-radius: 4px;
21
+ border: 1px solid ${r.stroke.primary};
22
+ background-color: ${r.surface.standard};
23
+ overflow: hidden;
24
+ `, d = t.div`
25
+ position: absolute;
26
+ top: 0;
27
+ left: 0;
28
+ bottom: 0;
29
+ width: ${(o) => o.$width}%;
30
+ background-color: ${(o) => o.$color ?? "transparent"};
31
+ `, l = t.div`
32
+ position: absolute;
33
+ top: 50%;
34
+ left: ${(o) => o.$left}%;
35
+ transform: translate(-50%, -50%);
36
+ padding: 4px 8px;
37
+ border-radius: 4px;
38
+ background-color: ${r.content.primary};
39
+ box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.12);
40
+ pointer-events: none;
41
+ `, x = t.div`
42
+ position: absolute;
43
+ top: -5px;
44
+ left: 50%;
45
+ transform: translateX(-50%);
46
+ width: 0;
47
+ height: 0;
48
+ border-left: 5px solid transparent;
49
+ border-right: 5px solid transparent;
50
+ border-bottom: 5px solid ${r.content.primary};
51
+ `;
52
+ export {
53
+ p as BarArea,
54
+ d as BarFill,
55
+ n as BarLabelColumn,
56
+ a as BarRowLayout,
57
+ l as BarTooltip,
58
+ x as BarTooltipArrow,
59
+ s as BarTrack
60
+ };
61
+ //# sourceMappingURL=ComparisonBarChart.styled.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ComparisonBarChart.styled.js","sources":["../../../../../../src/components/analytics-chips-and-dropdowns/chart/ComparisonBarChart/ComparisonBarChart.styled.ts"],"sourcesContent":["import styled from 'styled-components';\nimport { COLORS } from '@src/constants/Theme';\n\nexport const BarRowLayout = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 32px;\n`;\n\nexport const BarLabelColumn = styled.div<{ $width: number }>`\n\twidth: ${(props) => props.$width}px;\n\tflex-shrink: 0;\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n`;\n\nexport const BarArea = styled.div<{ $height: number }>`\n\tposition: relative;\n\tflex: 1;\n\theight: ${(props) => props.$height}px;\n`;\n\nexport const BarTrack = styled.div`\n\tposition: absolute;\n\tinset: 0;\n\tborder-radius: 4px;\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tbackground-color: ${COLORS.surface.standard};\n\toverflow: hidden;\n`;\n\nexport const BarFill = styled.div<{ $width: number; $color?: string }>`\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tbottom: 0;\n\twidth: ${(props) => props.$width}%;\n\tbackground-color: ${(props) => props.$color ?? 'transparent'};\n`;\n\nexport const BarTooltip = styled.div<{ $left: number }>`\n\tposition: absolute;\n\ttop: 50%;\n\tleft: ${(props) => props.$left}%;\n\ttransform: translate(-50%, -50%);\n\tpadding: 4px 8px;\n\tborder-radius: 4px;\n\tbackground-color: ${COLORS.content.primary};\n\tbox-shadow: 0px 2px 4px rgba(0, 0, 0, 0.12);\n\tpointer-events: none;\n`;\n\nexport const BarTooltipArrow = styled.div`\n\tposition: absolute;\n\ttop: -5px;\n\tleft: 50%;\n\ttransform: translateX(-50%);\n\twidth: 0;\n\theight: 0;\n\tborder-left: 5px solid transparent;\n\tborder-right: 5px solid transparent;\n\tborder-bottom: 5px solid ${COLORS.content.primary};\n`;\n"],"names":["BarRowLayout","styled","BarLabelColumn","props","BarArea","BarTrack","COLORS","BarFill","BarTooltip","BarTooltipArrow"],"mappings":";;AAGO,MAAMA,IAAeC,EAAO;AAAA;AAAA;AAAA;AAAA,GAMtBC,IAAiBD,EAAO;AAAA,UAC3B,CAACE,MAAUA,EAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,GAOpBC,IAAUH,EAAO;AAAA;AAAA;AAAA,WAGnB,CAACE,MAAUA,EAAM,OAAO;AAAA,GAGtBE,IAAWJ,EAAO;AAAA;AAAA;AAAA;AAAA,qBAIVK,EAAO,OAAO,OAAO;AAAA,qBACrBA,EAAO,QAAQ,QAAQ;AAAA;AAAA,GAI/BC,IAAUN,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA,UAKpB,CAACE,MAAUA,EAAM,MAAM;AAAA,qBACZ,CAACA,MAAUA,EAAM,UAAU,aAAa;AAAA,GAGhDK,IAAaP,EAAO;AAAA;AAAA;AAAA,SAGxB,CAACE,MAAUA,EAAM,KAAK;AAAA;AAAA;AAAA;AAAA,qBAIVG,EAAO,QAAQ,OAAO;AAAA;AAAA;AAAA,GAK9BG,IAAkBR,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BASVK,EAAO,QAAQ,OAAO;AAAA;"}
@@ -0,0 +1,3 @@
1
+ import { default as React } from 'react';
2
+ import { FunnelChartI } from './FunnelChart.model';
3
+ export declare const FunnelChart: React.FC<FunnelChartI>;
@@ -0,0 +1,109 @@
1
+ import { jsx as o, jsxs as y } from "react/jsx-runtime";
2
+ import { useMemo as s } from "react";
3
+ import { BodyTiny as C } from "../../../TypographyStyle.js";
4
+ import { COLORS as S } from "../../../../constants/Theme.js";
5
+ import { ChartCard as k, ChartValueRow as w } from "../ChartLayout.js";
6
+ import { pickColor as g, FUNNEL_BAND_COLORS as E } from "../chartPalette.js";
7
+ import { toChartValue as m, formatPercent as O, formatChartValue as R } from "../formatChartValue.js";
8
+ import { PlotArea as A, BandsSvg as _, SeparatorLine as v, HeaderRow as B, StageHeaderColumn as D, StageLabelRow as N, StageColorDot as P } from "./FunnelChart.styled.js";
9
+ import { buildFunnelLayout as V, FUNNEL_VIEW_WIDTH as L } from "./funnelGeometry.js";
10
+ const F = Array.from(
11
+ { length: 4 },
12
+ (r, n) => ({ key: `placeholder-${n}`, label: "", value: 0 })
13
+ ), T = (r, n) => {
14
+ const a = r[n];
15
+ if (a.percentageLabel !== void 0)
16
+ return a.percentageLabel;
17
+ if (n === 0)
18
+ return m(a.value) > 0 ? "100%" : "";
19
+ const t = a.branchOf ? r.find((u) => u.key === a.branchOf) : r[n - 1], l = m(t?.value);
20
+ if (!t || l === 0)
21
+ return "";
22
+ const h = m(a.value) / l * 100;
23
+ return `${O(h)}% of ${t.label}`;
24
+ }, j = ({
25
+ stage: r,
26
+ color: n,
27
+ chip: a,
28
+ locale: t
29
+ }) => /* @__PURE__ */ y(D, { "data-test": `funnel-chart-header-${r.key}`, children: [
30
+ r.label && /* @__PURE__ */ y(N, { children: [
31
+ /* @__PURE__ */ o(P, { $color: n }),
32
+ /* @__PURE__ */ o(C, { color: S.content.secondary, children: r.label })
33
+ ] }),
34
+ /* @__PURE__ */ o(
35
+ w,
36
+ {
37
+ value: r.valueLabel ?? R(m(r.value), t),
38
+ chip: a
39
+ }
40
+ )
41
+ ] }), K = ({
42
+ stages: r = [],
43
+ title: n,
44
+ plotHeight: a = 291,
45
+ headerHeight: t = 83,
46
+ colors: l = E,
47
+ locale: h,
48
+ wrapperStyle: u
49
+ }) => {
50
+ const c = r.length ? r : F, i = s(
51
+ () => V(c, { plotHeight: a, headerHeight: t }),
52
+ [c, a, t]
53
+ ), p = !i.isEmpty, $ = (e) => `${e / L * 100}%`, d = s(
54
+ () => c.map((e, f) => ({
55
+ stage: e,
56
+ color: p ? e.color ?? g(l, f) : S.content.inactive,
57
+ chip: p ? T(c, f) : ""
58
+ })),
59
+ [c, l, p]
60
+ ), b = s(
61
+ () => new Map(d.map(({ stage: e, color: f }) => [e.key, f])),
62
+ [d]
63
+ );
64
+ return /* @__PURE__ */ o(
65
+ k,
66
+ {
67
+ dataTest: "funnel-chart",
68
+ title: n,
69
+ padding: "18px 24px",
70
+ gap: 14,
71
+ wrapperStyle: { overflow: "hidden", ...u },
72
+ children: /* @__PURE__ */ y(A, { $height: a, children: [
73
+ /* @__PURE__ */ o(
74
+ _,
75
+ {
76
+ width: "100%",
77
+ height: "100%",
78
+ viewBox: `0 0 ${L} ${a}`,
79
+ preserveAspectRatio: "none",
80
+ "aria-hidden": !0,
81
+ children: i.bands.map((e) => /* @__PURE__ */ o(
82
+ "path",
83
+ {
84
+ "data-test": `funnel-chart-band-${e.key}`,
85
+ d: e.d,
86
+ fill: p ? b.get(e.key) : "transparent"
87
+ },
88
+ e.key
89
+ ))
90
+ }
91
+ ),
92
+ i.separators.full.map((e) => /* @__PURE__ */ o(v, { $left: $(e) }, `full-${e}`)),
93
+ i.separators.header.map((e) => /* @__PURE__ */ o(
94
+ v,
95
+ {
96
+ $left: $(e),
97
+ $height: t
98
+ },
99
+ `header-${e}`
100
+ )),
101
+ /* @__PURE__ */ o(B, { $height: t, children: d.map((e) => /* @__PURE__ */ o(j, { ...e, locale: h }, e.stage.key)) })
102
+ ] })
103
+ }
104
+ );
105
+ };
106
+ export {
107
+ K as FunnelChart
108
+ };
109
+ //# sourceMappingURL=FunnelChart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FunnelChart.js","sources":["../../../../../../src/components/analytics-chips-and-dropdowns/chart/FunnelChart/FunnelChart.tsx"],"sourcesContent":["import React, { useMemo } from 'react';\nimport { BodyTiny } from '@src/components/TypographyStyle';\nimport { COLORS } from '@src/constants/Theme';\nimport { ChartCard, ChartValueRow } from '../ChartLayout';\nimport { FUNNEL_BAND_COLORS, pickColor } from '../chartPalette';\nimport {\n\tformatChartValue,\n\tformatPercent,\n\ttoChartValue,\n} from '../formatChartValue';\nimport type { FunnelChartI, FunnelStageI } from './FunnelChart.model';\nimport {\n\tBandsSvg,\n\tHeaderRow,\n\tPlotArea,\n\tSeparatorLine,\n\tStageColorDot,\n\tStageHeaderColumn,\n\tStageLabelRow,\n} from './FunnelChart.styled';\nimport { buildFunnelLayout, FUNNEL_VIEW_WIDTH } from './funnelGeometry';\n\nconst PLACEHOLDER_STAGES: FunnelStageI[] = Array.from(\n\t{ length: 4 },\n\t(_, index) => ({ key: `placeholder-${index}`, label: '', value: 0 }),\n);\n\nconst derivePercentageLabel = (\n\tstages: FunnelStageI[],\n\tindex: number,\n): string => {\n\tconst stage = stages[index];\n\tif (stage.percentageLabel !== undefined) {\n\t\treturn stage.percentageLabel;\n\t}\n\tif (index === 0) {\n\t\treturn toChartValue(stage.value) > 0 ? '100%' : '';\n\t}\n\tconst reference = stage.branchOf\n\t\t? stages.find((candidate) => candidate.key === stage.branchOf)\n\t\t: stages[index - 1];\n\tconst referenceValue = toChartValue(reference?.value);\n\tif (!reference || referenceValue === 0) {\n\t\treturn '';\n\t}\n\tconst share = (toChartValue(stage.value) / referenceValue) * 100;\n\treturn `${formatPercent(share)}% of ${reference.label}`;\n};\n\ninterface StageHeaderProps {\n\tstage: FunnelStageI;\n\tcolor?: string;\n\tchip: string;\n\tlocale?: string;\n}\n\nconst StageHeader: React.FC<StageHeaderProps> = ({\n\tstage,\n\tcolor,\n\tchip,\n\tlocale,\n}) => (\n\t<StageHeaderColumn data-test={`funnel-chart-header-${stage.key}`}>\n\t\t{stage.label && (\n\t\t\t<StageLabelRow>\n\t\t\t\t<StageColorDot $color={color} />\n\t\t\t\t<BodyTiny color={COLORS.content.secondary}>{stage.label}</BodyTiny>\n\t\t\t</StageLabelRow>\n\t\t)}\n\t\t<ChartValueRow\n\t\t\tvalue={\n\t\t\t\tstage.valueLabel ?? formatChartValue(toChartValue(stage.value), locale)\n\t\t\t}\n\t\t\tchip={chip}\n\t\t/>\n\t</StageHeaderColumn>\n);\n\nexport const FunnelChart: React.FC<FunnelChartI> = ({\n\tstages = [],\n\ttitle,\n\tplotHeight = 291,\n\theaderHeight = 83,\n\tcolors = FUNNEL_BAND_COLORS,\n\tlocale,\n\twrapperStyle,\n}) => {\n\tconst visibleStages = stages.length ? stages : PLACEHOLDER_STAGES;\n\n\tconst layout = useMemo(\n\t\t() => buildFunnelLayout(visibleStages, { plotHeight, headerHeight }),\n\t\t[visibleStages, plotHeight, headerHeight],\n\t);\n\n\tconst hasData = !layout.isEmpty;\n\tconst toPercent = (x: number) => `${(x / FUNNEL_VIEW_WIDTH) * 100}%`;\n\n\tconst headers = useMemo(\n\t\t() =>\n\t\t\tvisibleStages.map((stage, index) => ({\n\t\t\t\tstage,\n\t\t\t\tcolor: hasData\n\t\t\t\t\t? stage.color ?? pickColor(colors, index)\n\t\t\t\t\t: COLORS.content.inactive,\n\t\t\t\tchip: hasData ? derivePercentageLabel(visibleStages, index) : '',\n\t\t\t})),\n\t\t[visibleStages, colors, hasData],\n\t);\n\n\tconst colorByStage = useMemo(\n\t\t() => new Map(headers.map(({ stage, color }) => [stage.key, color])),\n\t\t[headers],\n\t);\n\n\treturn (\n\t\t<ChartCard\n\t\t\tdataTest=\"funnel-chart\"\n\t\t\ttitle={title}\n\t\t\tpadding=\"18px 24px\"\n\t\t\tgap={14}\n\t\t\twrapperStyle={{ overflow: 'hidden', ...wrapperStyle }}\n\t\t>\n\t\t\t<PlotArea $height={plotHeight}>\n\t\t\t\t<BandsSvg\n\t\t\t\t\twidth=\"100%\"\n\t\t\t\t\theight=\"100%\"\n\t\t\t\t\tviewBox={`0 0 ${FUNNEL_VIEW_WIDTH} ${plotHeight}`}\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\taria-hidden\n\t\t\t\t>\n\t\t\t\t\t{layout.bands.map((band) => (\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\tkey={band.key}\n\t\t\t\t\t\t\tdata-test={`funnel-chart-band-${band.key}`}\n\t\t\t\t\t\t\td={band.d}\n\t\t\t\t\t\t\tfill={hasData ? colorByStage.get(band.key) : 'transparent'}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</BandsSvg>\n\n\t\t\t\t{layout.separators.full.map((x) => (\n\t\t\t\t\t<SeparatorLine key={`full-${x}`} $left={toPercent(x)} />\n\t\t\t\t))}\n\t\t\t\t{layout.separators.header.map((x) => (\n\t\t\t\t\t<SeparatorLine\n\t\t\t\t\t\tkey={`header-${x}`}\n\t\t\t\t\t\t$left={toPercent(x)}\n\t\t\t\t\t\t$height={headerHeight}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\n\t\t\t\t<HeaderRow $height={headerHeight}>\n\t\t\t\t\t{headers.map((header) => (\n\t\t\t\t\t\t<StageHeader key={header.stage.key} {...header} locale={locale} />\n\t\t\t\t\t))}\n\t\t\t\t</HeaderRow>\n\t\t\t</PlotArea>\n\t\t</ChartCard>\n\t);\n};\n"],"names":["PLACEHOLDER_STAGES","_","index","derivePercentageLabel","stages","stage","toChartValue","reference","candidate","referenceValue","share","formatPercent","StageHeader","color","chip","locale","StageHeaderColumn","StageLabelRow","jsx","StageColorDot","BodyTiny","COLORS","ChartValueRow","formatChartValue","FunnelChart","title","plotHeight","headerHeight","colors","FUNNEL_BAND_COLORS","wrapperStyle","visibleStages","layout","useMemo","buildFunnelLayout","hasData","toPercent","x","FUNNEL_VIEW_WIDTH","headers","pickColor","colorByStage","ChartCard","jsxs","PlotArea","BandsSvg","band","SeparatorLine","HeaderRow","header"],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { CSSProperties } from 'react';
2
+ export interface FunnelStageI {
3
+ key: string;
4
+ label: string;
5
+ value: number;
6
+ valueLabel?: string;
7
+ percentageLabel?: string;
8
+ color?: string;
9
+ branchOf?: string;
10
+ }
11
+ export interface FunnelChartI {
12
+ stages: FunnelStageI[];
13
+ title?: string;
14
+ plotHeight?: number;
15
+ headerHeight?: number;
16
+ colors?: string[];
17
+ locale?: string;
18
+ wrapperStyle?: CSSProperties;
19
+ }
@@ -0,0 +1,16 @@
1
+ export declare const SeparatorLine: import('styled-components').StyledComponent<"div", any, {
2
+ $left: string;
3
+ $height?: number | undefined;
4
+ }, never>;
5
+ export declare const PlotArea: import('styled-components').StyledComponent<"div", any, {
6
+ $height: number;
7
+ }, never>;
8
+ export declare const BandsSvg: import('styled-components').StyledComponent<"svg", any, {}, never>;
9
+ export declare const HeaderRow: import('styled-components').StyledComponent<"div", any, {
10
+ $height: number;
11
+ }, never>;
12
+ export declare const StageHeaderColumn: import('styled-components').StyledComponent<"div", any, {}, never>;
13
+ export declare const StageLabelRow: import('styled-components').StyledComponent<"div", any, {}, never>;
14
+ export declare const StageColorDot: import('styled-components').StyledComponent<"span", any, {
15
+ $color?: string | undefined;
16
+ }, never>;
@@ -0,0 +1,54 @@
1
+ import i from "styled-components";
2
+ import { COLORS as o } from "../../../../constants/Theme.js";
3
+ const p = i.div`
4
+ position: absolute;
5
+ top: 0;
6
+ ${(t) => t.$height === void 0 ? "bottom: 0;" : `height: ${t.$height}px;`}
7
+ left: ${(t) => t.$left};
8
+ width: 1px;
9
+ background-color: ${o.stroke.primary};
10
+ `, r = i.div`
11
+ position: relative;
12
+ width: 100%;
13
+ height: ${(t) => t.$height}px;
14
+ `, l = i.svg`
15
+ position: absolute;
16
+ inset: 0;
17
+ `, n = i.div`
18
+ position: absolute;
19
+ top: 0;
20
+ left: 0;
21
+ right: 0;
22
+ height: ${(t) => t.$height}px;
23
+ display: flex;
24
+ `, s = i.div`
25
+ flex: 1;
26
+ min-width: 0;
27
+ display: flex;
28
+ flex-direction: column;
29
+ gap: 8px;
30
+ align-items: flex-start;
31
+ padding: 0 8px 0 12px;
32
+ `, d = i.div`
33
+ display: flex;
34
+ align-items: center;
35
+ gap: 8px;
36
+ width: 100%;
37
+ opacity: 0.8;
38
+ `, h = i.span`
39
+ width: 16px;
40
+ height: 16px;
41
+ border-radius: 2.667px;
42
+ background-color: ${(t) => t.$color ?? "transparent"};
43
+ flex-shrink: 0;
44
+ `;
45
+ export {
46
+ l as BandsSvg,
47
+ n as HeaderRow,
48
+ r as PlotArea,
49
+ p as SeparatorLine,
50
+ h as StageColorDot,
51
+ s as StageHeaderColumn,
52
+ d as StageLabelRow
53
+ };
54
+ //# sourceMappingURL=FunnelChart.styled.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FunnelChart.styled.js","sources":["../../../../../../src/components/analytics-chips-and-dropdowns/chart/FunnelChart/FunnelChart.styled.ts"],"sourcesContent":["import styled from 'styled-components';\nimport { COLORS } from '@src/constants/Theme';\n\nexport const SeparatorLine = styled.div<{ $left: string; $height?: number }>`\n\tposition: absolute;\n\ttop: 0;\n\t${(props) =>\n\t\tprops.$height === undefined ? 'bottom: 0;' : `height: ${props.$height}px;`}\n\tleft: ${(props) => props.$left};\n\twidth: 1px;\n\tbackground-color: ${COLORS.stroke.primary};\n`;\n\nexport const PlotArea = styled.div<{ $height: number }>`\n\tposition: relative;\n\twidth: 100%;\n\theight: ${(props) => props.$height}px;\n`;\n\nexport const BandsSvg = styled.svg`\n\tposition: absolute;\n\tinset: 0;\n`;\n\nexport const HeaderRow = styled.div<{ $height: number }>`\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\theight: ${(props) => props.$height}px;\n\tdisplay: flex;\n`;\n\nexport const StageHeaderColumn = styled.div`\n\tflex: 1;\n\tmin-width: 0;\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n\talign-items: flex-start;\n\tpadding: 0 8px 0 12px;\n`;\n\nexport const StageLabelRow = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\twidth: 100%;\n\topacity: 0.8;\n`;\n\nexport const StageColorDot = styled.span<{ $color?: string }>`\n\twidth: 16px;\n\theight: 16px;\n\tborder-radius: 2.667px;\n\tbackground-color: ${(props) => props.$color ?? 'transparent'};\n\tflex-shrink: 0;\n`;\n"],"names":["SeparatorLine","styled","props","COLORS","PlotArea","BandsSvg","HeaderRow","StageHeaderColumn","StageLabelRow","StageColorDot"],"mappings":";;AAGO,MAAMA,IAAgBC,EAAO;AAAA;AAAA;AAAA,GAGjC,CAACC,MACFA,EAAM,YAAY,SAAY,eAAe,WAAWA,EAAM,OAAO,KAAK;AAAA,SACnE,CAACA,MAAUA,EAAM,KAAK;AAAA;AAAA,qBAEVC,EAAO,OAAO,OAAO;AAAA,GAG7BC,IAAWH,EAAO;AAAA;AAAA;AAAA,WAGpB,CAACC,MAAUA,EAAM,OAAO;AAAA,GAGtBG,IAAWJ,EAAO;AAAA;AAAA;AAAA,GAKlBK,IAAYL,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA,WAKrB,CAACC,MAAUA,EAAM,OAAO;AAAA;AAAA,GAItBK,IAAoBN,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAU3BO,IAAgBP,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAQvBQ,IAAgBR,EAAO;AAAA;AAAA;AAAA;AAAA,qBAIf,CAACC,MAAUA,EAAM,UAAU,aAAa;AAAA;AAAA;"}
@@ -0,0 +1,23 @@
1
+ export declare const FUNNEL_VIEW_WIDTH = 1000;
2
+ export interface FunnelGeometryStage {
3
+ key: string;
4
+ value: number;
5
+ branchOf?: string;
6
+ }
7
+ export interface FunnelGeometryOptions {
8
+ plotHeight: number;
9
+ headerHeight: number;
10
+ }
11
+ export interface FunnelBandLayout {
12
+ key: string;
13
+ d: string;
14
+ }
15
+ export interface FunnelLayout {
16
+ bands: FunnelBandLayout[];
17
+ separators: {
18
+ full: number[];
19
+ header: number[];
20
+ };
21
+ isEmpty: boolean;
22
+ }
23
+ export declare const buildFunnelLayout: (stages: FunnelGeometryStage[], { plotHeight, headerHeight }: FunnelGeometryOptions) => FunnelLayout;
@@ -0,0 +1,48 @@
1
+ import { toChartValue as x, clamp as k } from "../formatChartValue.js";
2
+ const B = 1e3, a = (n) => Math.round(n * 100) / 100, F = (n) => n.reduce((c, s, o) => {
3
+ const r = c[c.length - 1];
4
+ return s.branchOf && r?.branchOf === s.branchOf ? r.stageIndexes.push(o) : c.push({ branchOf: s.branchOf, stageIndexes: [o] }), c;
5
+ }, []), N = (n, { plotHeight: c, headerHeight: s }) => {
6
+ const o = Math.max(c - s, 0), r = s + o / 2, b = x(n[0]?.value), $ = n.length === 0 || b === 0 || o === 0, p = (t) => a(t / n.length * B), g = (t) => $ ? 0 : k(t / b * o, 0, o), l = F(n);
7
+ let m = 0;
8
+ const h = l.map((t) => {
9
+ const e = p(m);
10
+ return m += t.stageIndexes.length, { x0: e, x1: p(m) };
11
+ }), I = l.map(
12
+ (t) => t.stageIndexes.reduce(
13
+ (e, u) => e + x(n[u].value),
14
+ 0
15
+ )
16
+ ), O = [];
17
+ return l.forEach((t, e) => {
18
+ const { x0: u, x1: T } = h[e], f = I[e], V = I[e + 1] ?? f, E = g(f), L = g(V);
19
+ let i = r - E / 2, d = r - L / 2;
20
+ t.stageIndexes.forEach((y) => {
21
+ const M = f > 0 ? x(n[y].value) / f : 0, v = i + E * M, C = d + L * M;
22
+ O.push({
23
+ key: n[y].key,
24
+ d: [
25
+ `M${u} ${a(i)}`,
26
+ `L${T} ${a(d)}`,
27
+ `L${T} ${a(C)}`,
28
+ `L${u} ${a(v)}`,
29
+ "Z"
30
+ ].join(" ")
31
+ }), i = v, d = C;
32
+ });
33
+ }), {
34
+ bands: O,
35
+ separators: {
36
+ full: h.length ? [h[0].x0, ...h.map((t) => t.x1)] : [],
37
+ header: l.flatMap(
38
+ (t) => t.stageIndexes.slice(1).map((e) => p(e))
39
+ )
40
+ },
41
+ isEmpty: $
42
+ };
43
+ };
44
+ export {
45
+ B as FUNNEL_VIEW_WIDTH,
46
+ N as buildFunnelLayout
47
+ };
48
+ //# sourceMappingURL=funnelGeometry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"funnelGeometry.js","sources":["../../../../../../src/components/analytics-chips-and-dropdowns/chart/FunnelChart/funnelGeometry.ts"],"sourcesContent":["import { clamp, toChartValue } from '../formatChartValue';\n\nexport const FUNNEL_VIEW_WIDTH = 1000;\n\nexport interface FunnelGeometryStage {\n\tkey: string;\n\tvalue: number;\n\tbranchOf?: string;\n}\n\nexport interface FunnelGeometryOptions {\n\tplotHeight: number;\n\theaderHeight: number;\n}\n\nexport interface FunnelBandLayout {\n\tkey: string;\n\td: string;\n}\n\nexport interface FunnelLayout {\n\tbands: FunnelBandLayout[];\n\tseparators: {\n\t\tfull: number[];\n\t\theader: number[];\n\t};\n\tisEmpty: boolean;\n}\n\ninterface ColumnGroup {\n\tbranchOf?: string;\n\tstageIndexes: number[];\n}\n\nconst round = (value: number) => Math.round(value * 100) / 100;\n\n// Consecutive stages sharing a `branchOf` share one column, stacked vertically within it.\nconst groupIntoColumns = (stages: FunnelGeometryStage[]): ColumnGroup[] =>\n\tstages.reduce<ColumnGroup[]>((groups, stage, index) => {\n\t\tconst current = groups[groups.length - 1];\n\t\tif (stage.branchOf && current?.branchOf === stage.branchOf) {\n\t\t\tcurrent.stageIndexes.push(index);\n\t\t} else {\n\t\t\tgroups.push({ branchOf: stage.branchOf, stageIndexes: [index] });\n\t\t}\n\t\treturn groups;\n\t}, []);\n\nexport const buildFunnelLayout = (\n\tstages: FunnelGeometryStage[],\n\t{ plotHeight, headerHeight }: FunnelGeometryOptions,\n): FunnelLayout => {\n\tconst bandArea = Math.max(plotHeight - headerHeight, 0);\n\tconst centerY = headerHeight + bandArea / 2;\n\t// Every height is a fraction of the first stage, so it always fills the full band area.\n\tconst baseValue = toChartValue(stages[0]?.value);\n\tconst isEmpty = stages.length === 0 || baseValue === 0 || bandArea === 0;\n\n\tconst toX = (cellIndex: number) =>\n\t\tround((cellIndex / stages.length) * FUNNEL_VIEW_WIDTH);\n\tconst heightOf = (value: number) =>\n\t\tisEmpty ? 0 : clamp((value / baseValue) * bandArea, 0, bandArea);\n\n\tconst groups = groupIntoColumns(stages);\n\tlet cellCursor = 0;\n\tconst columns = groups.map((group) => {\n\t\tconst x0 = toX(cellCursor);\n\t\tcellCursor += group.stageIndexes.length;\n\t\treturn { x0, x1: toX(cellCursor) };\n\t});\n\n\tconst columnTotals = groups.map((group) =>\n\t\tgroup.stageIndexes.reduce(\n\t\t\t(total, index) => total + toChartValue(stages[index].value),\n\t\t\t0,\n\t\t),\n\t);\n\n\tconst bands: FunnelBandLayout[] = [];\n\tgroups.forEach((group, columnIndex) => {\n\t\tconst { x0, x1 } = columns[columnIndex];\n\t\tconst leftTotal = columnTotals[columnIndex];\n\t\tconst rightTotal = columnTotals[columnIndex + 1] ?? leftTotal;\n\t\tconst leftHeight = heightOf(leftTotal);\n\t\tconst rightHeight = heightOf(rightTotal);\n\n\t\tlet leftTop = centerY - leftHeight / 2;\n\t\tlet rightTop = centerY - rightHeight / 2;\n\n\t\t// Each stage takes its share of the column edge, stacking downward from the previous one,\n\t\t// so a band's left and right edges line up with its neighbours in adjacent columns.\n\t\tgroup.stageIndexes.forEach((stageIndex) => {\n\t\t\tconst share =\n\t\t\t\tleftTotal > 0 ? toChartValue(stages[stageIndex].value) / leftTotal : 0;\n\t\t\tconst leftBottom = leftTop + leftHeight * share;\n\t\t\tconst rightBottom = rightTop + rightHeight * share;\n\t\t\tbands.push({\n\t\t\t\tkey: stages[stageIndex].key,\n\t\t\t\td: [\n\t\t\t\t\t`M${x0} ${round(leftTop)}`,\n\t\t\t\t\t`L${x1} ${round(rightTop)}`,\n\t\t\t\t\t`L${x1} ${round(rightBottom)}`,\n\t\t\t\t\t`L${x0} ${round(leftBottom)}`,\n\t\t\t\t\t'Z',\n\t\t\t\t].join(' '),\n\t\t\t});\n\t\t\tleftTop = leftBottom;\n\t\t\trightTop = rightBottom;\n\t\t});\n\t});\n\n\treturn {\n\t\tbands,\n\t\tseparators: {\n\t\t\tfull: columns.length ? [columns[0].x0, ...columns.map((c) => c.x1)] : [],\n\t\t\theader: groups.flatMap((group) =>\n\t\t\t\tgroup.stageIndexes.slice(1).map((index) => toX(index)),\n\t\t\t),\n\t\t},\n\t\tisEmpty,\n\t};\n};\n"],"names":["FUNNEL_VIEW_WIDTH","round","value","groupIntoColumns","stages","groups","stage","index","current","buildFunnelLayout","plotHeight","headerHeight","bandArea","centerY","baseValue","toChartValue","isEmpty","toX","cellIndex","heightOf","clamp","cellCursor","columns","group","x0","columnTotals","total","bands","columnIndex","x1","leftTotal","rightTotal","leftHeight","rightHeight","leftTop","rightTop","stageIndex","share","leftBottom","rightBottom","c"],"mappings":"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"}