@servicetitan/marketing-ui 6.0.1 → 6.1.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.
- package/dist/components/charts/funnel-chart/components/funnel-chart.d.ts.map +1 -1
- package/dist/components/charts/funnel-chart/components/funnel-chart.js +1 -2
- package/dist/components/charts/funnel-chart/components/funnel-chart.js.map +1 -1
- package/dist/components/charts/funnel-chart/components/funnel-svg.js +3 -3
- package/dist/components/charts/funnel-chart/components/funnel-svg.js.map +1 -1
- package/dist/components/charts/line-chart/components/body.js +2 -2
- package/dist/components/charts/line-chart/components/body.js.map +1 -1
- package/dist/components/charts/line-chart/components/hover-popover.d.ts.map +1 -1
- package/dist/components/charts/line-chart/components/hover-popover.js +69 -44
- package/dist/components/charts/line-chart/components/hover-popover.js.map +1 -1
- package/dist/components/charts/line-chart/components/hover-popover.module.less +26 -1
- package/dist/components/charts/line-chart/components/hover-popover.module.less.d.ts +3 -0
- package/dist/components/charts/line-chart/components/stuff.js +2 -1
- package/dist/components/charts/line-chart/components/stuff.js.map +1 -1
- package/dist/components/charts/line-chart/components/svg-bars.js +1 -1
- package/dist/components/charts/line-chart/components/svg-bars.js.map +1 -1
- package/dist/components/charts/pie-chart/components/pie-chart.js +1 -0
- package/dist/components/charts/pie-chart/components/pie-chart.js.map +1 -1
- package/dist/components/charts/pie-chart/components/pie-chart.module.less +8 -0
- package/dist/components/charts/pie-chart/components/pie-chart.module.less.d.ts +2 -0
- package/dist/components/charts/pie-chart/components/pie.d.ts.map +1 -1
- package/dist/components/charts/pie-chart/components/pie.js +2 -0
- package/dist/components/charts/pie-chart/components/pie.js.map +1 -1
- package/dist/components/stat/stat-card.d.ts.map +1 -1
- package/dist/components/stat/stat-card.js +2 -2
- package/dist/components/stat/stat-card.js.map +1 -1
- package/package.json +2 -2
- package/src/components/charts/funnel-chart/components/funnel-chart.tsx +0 -1
- package/src/components/charts/funnel-chart/components/funnel-svg.tsx +3 -3
- package/src/components/charts/line-chart/components/body.tsx +1 -1
- package/src/components/charts/line-chart/components/hover-popover.module.less +26 -1
- package/src/components/charts/line-chart/components/hover-popover.module.less.d.ts +3 -0
- package/src/components/charts/line-chart/components/hover-popover.tsx +85 -47
- package/src/components/charts/line-chart/components/stuff.tsx +1 -1
- package/src/components/charts/line-chart/components/svg-bars.tsx +1 -1
- package/src/components/charts/pie-chart/components/pie-chart.module.less +8 -0
- package/src/components/charts/pie-chart/components/pie-chart.module.less.d.ts +2 -0
- package/src/components/charts/pie-chart/components/pie-chart.tsx +1 -1
- package/src/components/charts/pie-chart/components/pie.tsx +2 -0
- package/src/components/stat/stat-card.tsx +1 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback, useMemo, FC,
|
|
1
|
+
import { useCallback, useMemo, useRef, useLayoutEffect, useState, FC, CSSProperties } from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import { observer } from 'mobx-react';
|
|
4
4
|
import { useDependencies } from '@servicetitan/react-ioc';
|
|
@@ -11,6 +11,9 @@ import * as Styles from './hover-popover.module.less';
|
|
|
11
11
|
import { ColorTag } from '../../common';
|
|
12
12
|
import { Text } from '@servicetitan/anvil2';
|
|
13
13
|
|
|
14
|
+
const CHART_HEIGHT_PX = 400;
|
|
15
|
+
const OFFSET_PX = 16;
|
|
16
|
+
|
|
14
17
|
export const HoverPopover: FC = observer(() => {
|
|
15
18
|
const [
|
|
16
19
|
{
|
|
@@ -25,6 +28,7 @@ export const HoverPopover: FC = observer(() => {
|
|
|
25
28
|
},
|
|
26
29
|
svgStore,
|
|
27
30
|
] = useDependencies(LineChartStore, SvgStore);
|
|
31
|
+
const isChartLeftSide = hoveredIndex < periods.length / 2;
|
|
28
32
|
|
|
29
33
|
const formatDateTitle = useMemo(() => periodDateTitleFormatter[resolution], [resolution]);
|
|
30
34
|
const formatValue = useCallback(
|
|
@@ -34,15 +38,48 @@ export const HoverPopover: FC = observer(() => {
|
|
|
34
38
|
title,
|
|
35
39
|
[display]
|
|
36
40
|
);
|
|
37
|
-
const popoverStyle = useMemo(() => {
|
|
38
|
-
const pos = svgStore.periodX(hoveredIndex);
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
const popRef = useRef<HTMLDivElement | null>(null);
|
|
43
|
+
const [popH, setPopH] = useState(0);
|
|
44
|
+
|
|
45
|
+
useLayoutEffect(() => {
|
|
46
|
+
if (!popRef.current) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const rect = popRef.current.getBoundingClientRect();
|
|
50
|
+
if (rect.height && Math.abs(rect.height - popH) > 0.5) {
|
|
51
|
+
setPopH(rect.height);
|
|
42
52
|
}
|
|
53
|
+
}, [hoveredIndex, metrics, display, popH]);
|
|
54
|
+
|
|
55
|
+
const popoverStyle = useMemo<CSSProperties>(() => {
|
|
56
|
+
const posX = svgStore.periodX(hoveredIndex);
|
|
57
|
+
|
|
58
|
+
const yHeights = metrics
|
|
59
|
+
.filter(m => m.values[hoveredIndex] !== undefined)
|
|
60
|
+
.map(m => svgStore.periodY(m, hoveredIndex));
|
|
61
|
+
|
|
62
|
+
const barHeight = yHeights.length
|
|
63
|
+
? stackedTotals
|
|
64
|
+
? yHeights.reduce((a, b) => a + b, 0)
|
|
65
|
+
: Math.max(...yHeights)
|
|
66
|
+
: 0;
|
|
67
|
+
const barHeightPercentRaw = svgStore.fpy(Math.max(0, Math.min(100, barHeight)));
|
|
68
|
+
const barHeightPercent = Math.max(0, Math.min(100, Number(barHeightPercentRaw) || 0));
|
|
43
69
|
|
|
44
|
-
|
|
45
|
-
|
|
70
|
+
const barTopPositionPx = (barHeightPercent / 100) * CHART_HEIGHT_PX;
|
|
71
|
+
const availableSpaceBelow = Math.max(0, CHART_HEIGHT_PX - barTopPositionPx - popH);
|
|
72
|
+
const popoverOffsetPx = Math.min(OFFSET_PX, availableSpaceBelow);
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
top: `${barHeightPercent}%`,
|
|
76
|
+
transform: `translateY(${popoverOffsetPx}px)`,
|
|
77
|
+
position: 'absolute',
|
|
78
|
+
...(isChartLeftSide
|
|
79
|
+
? { left: `${svgStore.fpx(posX + 2)}%` }
|
|
80
|
+
: { right: `${svgStore.fpx(102 - posX)}%` }),
|
|
81
|
+
};
|
|
82
|
+
}, [svgStore, hoveredIndex, isChartLeftSide, metrics, stackedTotals, popH]);
|
|
46
83
|
|
|
47
84
|
if (hoveredIndex < 0 || hoveredIndex >= periods.length) {
|
|
48
85
|
return null;
|
|
@@ -52,47 +89,48 @@ export const HoverPopover: FC = observer(() => {
|
|
|
52
89
|
const partialWeek = !!period.partial;
|
|
53
90
|
|
|
54
91
|
return (
|
|
55
|
-
<
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
92
|
+
<div
|
|
93
|
+
ref={popRef}
|
|
94
|
+
className={classNames(Styles.popover, 'border border-radius-1 p-1')}
|
|
95
|
+
style={popoverStyle}
|
|
96
|
+
>
|
|
60
97
|
<div
|
|
61
|
-
className={classNames(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
<Text size="small" variant="headline" el="h6">
|
|
65
|
-
{stackedTotals
|
|
66
|
-
? `${formattedTotalAt(hoveredIndex)} ${totalLabel} | ${formatDateTitle(period)}`
|
|
67
|
-
: formatDateTitle(period)}
|
|
68
|
-
</Text>
|
|
69
|
-
{partialWeek && (
|
|
70
|
-
<BodyText size="xsmall" subdued>
|
|
71
|
-
Partial week
|
|
72
|
-
</BodyText>
|
|
98
|
+
className={classNames(
|
|
99
|
+
Styles.arrow,
|
|
100
|
+
isChartLeftSide ? Styles.arrowLeft : Styles.arrowRight
|
|
73
101
|
)}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
102
|
+
/>
|
|
103
|
+
<Text size="small" variant="headline" el="h6">
|
|
104
|
+
{stackedTotals
|
|
105
|
+
? `${formattedTotalAt(hoveredIndex)} ${totalLabel} | ${formatDateTitle(period)}`
|
|
106
|
+
: formatDateTitle(period)}
|
|
107
|
+
</Text>
|
|
108
|
+
{partialWeek && (
|
|
109
|
+
<BodyText size="xsmall" subdued>
|
|
110
|
+
Partial week
|
|
111
|
+
</BodyText>
|
|
112
|
+
)}
|
|
113
|
+
{metrics.map(
|
|
114
|
+
m =>
|
|
115
|
+
m.values[hoveredIndex] !== undefined && (
|
|
116
|
+
<ColorTag
|
|
117
|
+
small
|
|
118
|
+
label={formatValue(m.title, m.values[hoveredIndex], m.isRight)}
|
|
119
|
+
color={m.color}
|
|
120
|
+
key={m.title}
|
|
121
|
+
className="m-t-1"
|
|
122
|
+
dashed={m.opts?.dashed}
|
|
123
|
+
pattern={m.opts?.pattern}
|
|
124
|
+
outlineColor={m.opts?.outlineColor}
|
|
125
|
+
strokeColor={m.opts?.strokeColor}
|
|
126
|
+
colorTagClassName={
|
|
127
|
+
m.opts?.pattern === 'outline'
|
|
128
|
+
? Styles.colorTagOutlined
|
|
129
|
+
: Styles.colorTag
|
|
130
|
+
}
|
|
131
|
+
/>
|
|
132
|
+
)
|
|
133
|
+
)}
|
|
134
|
+
</div>
|
|
97
135
|
);
|
|
98
136
|
});
|
|
@@ -99,7 +99,7 @@ export const SvgBars: FC<SvgBarsProps> = observer(
|
|
|
99
99
|
const TOP_RADIUS = 1;
|
|
100
100
|
const xLeft = +fpx(x - barWidth / 2);
|
|
101
101
|
const yTop = +fpy(stackedBarHeight) + (values.length - 2);
|
|
102
|
-
const height = +fpx(value.val);
|
|
102
|
+
const height = j === values.length - 1 ? +fpx(value.val - 2) : +fpx(value.val);
|
|
103
103
|
const width = +fpx(barWidth);
|
|
104
104
|
|
|
105
105
|
const r = j === 0 ? TOP_RADIUS : 0; // radius must be numeric
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
max-width: 120px;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
.title-wrapper-color-tags {
|
|
8
|
+
max-width: 380px;
|
|
9
|
+
}
|
|
10
|
+
|
|
7
11
|
.percent-text-wrapper {
|
|
8
12
|
width: 32px;
|
|
9
13
|
height: 32px;
|
|
@@ -16,3 +20,7 @@
|
|
|
16
20
|
margin: @spacing-0 auto;
|
|
17
21
|
box-shadow: 0 0 0 1px @color-neutral-0 inset;
|
|
18
22
|
}
|
|
23
|
+
|
|
24
|
+
.popover {
|
|
25
|
+
background-color: @color-neutral-30;
|
|
26
|
+
}
|
|
@@ -28,7 +28,7 @@ const PieTitles: FC<{ title: string; pieces: PiePiece[] }> = ({ title, pieces })
|
|
|
28
28
|
</div>
|
|
29
29
|
</div>
|
|
30
30
|
) : (
|
|
31
|
-
<Flex direction="row" gap={8}>
|
|
31
|
+
<Flex direction="row" gap={8} className={Styles.titleWrapperColorTags}>
|
|
32
32
|
{pieces.map(piece => (
|
|
33
33
|
<ColorTag key={piece.title} label={piece.title} color={piece.color} />
|
|
34
34
|
))}
|
|
@@ -5,6 +5,7 @@ import { BodyText, Popover, Stack } from '@servicetitan/design-system';
|
|
|
5
5
|
import { useClientRect } from '../../../../utils/use-client-rect';
|
|
6
6
|
import { PieChartPopoverContentType, PiePiece, PopoverDirection } from '../utils/interface';
|
|
7
7
|
import { ColorTag } from '../../common';
|
|
8
|
+
import * as Styles from './pie-chart.module.less';
|
|
8
9
|
|
|
9
10
|
const chartPadding = 8;
|
|
10
11
|
const px = (value?: number) => `${value ?? 0}px`;
|
|
@@ -250,6 +251,7 @@ export const Pie: FC<{
|
|
|
250
251
|
direction={popoverDirection}
|
|
251
252
|
padding="s"
|
|
252
253
|
width="auto"
|
|
254
|
+
className={Styles.popover}
|
|
253
255
|
>
|
|
254
256
|
{selectedIndex === ind && (
|
|
255
257
|
<Stack
|
|
@@ -84,7 +84,6 @@ export const StatDiff: FC<StatDiffProps> = ({
|
|
|
84
84
|
? 'green'
|
|
85
85
|
: 'red'
|
|
86
86
|
}
|
|
87
|
-
className="m-r-half m-t-half"
|
|
88
87
|
/>
|
|
89
88
|
);
|
|
90
89
|
let text = '';
|
|
@@ -111,7 +110,7 @@ export const StatDiff: FC<StatDiffProps> = ({
|
|
|
111
110
|
justifyContent="center"
|
|
112
111
|
alignItems="center"
|
|
113
112
|
>
|
|
114
|
-
<Stack.Item>
|
|
113
|
+
<Stack.Item className="m-r-half m-t-half">
|
|
115
114
|
<span>{diff}</span>
|
|
116
115
|
</Stack.Item>
|
|
117
116
|
<Stack.Item>
|