@servicetitan/marketing-ui 6.0.0 → 6.0.1
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/pie-chart/components/pie.d.ts.map +1 -1
- package/dist/components/charts/pie-chart/components/pie.js +3 -2
- 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 +1 -1
- package/dist/components/stat/stat-card.js.map +1 -1
- package/package.json +2 -2
- package/src/components/charts/pie-chart/components/pie.tsx +7 -9
- package/src/components/stat/stat-card.tsx +11 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pie.d.ts","sourceRoot":"","sources":["../../../../../src/components/charts/pie-chart/components/pie.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkC,EAAE,EAAY,MAAM,OAAO,CAAC;AAKrE,OAAO,EAAE,0BAA0B,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"pie.d.ts","sourceRoot":"","sources":["../../../../../src/components/charts/pie-chart/components/pie.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkC,EAAE,EAAY,MAAM,OAAO,CAAC;AAKrE,OAAO,EAAE,0BAA0B,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAoK5F,eAAO,MAAM,GAAG,EAAE,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,EAAE,CAAC;IACb,cAAc,CAAC,EAAE,0BAA0B,CAAC;IAC5C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACvC,CA2HA,CAAC"}
|
|
@@ -79,7 +79,8 @@ const PieSvg = ({ pieces, selectedIndex, radiusRelative })=>{
|
|
|
79
79
|
const piePiece = pieces.find((p)=>p.points);
|
|
80
80
|
const innerR = piePiece ? Math.hypot(piePiece.points[3][0], piePiece.points[3][1]) : 0;
|
|
81
81
|
const outerR = piePiece ? Math.hypot(piePiece.points[1][0], piePiece.points[1][1]) : 0;
|
|
82
|
-
const
|
|
82
|
+
const nonZeroPieces = pieces.filter((p)=>p.points && p.path);
|
|
83
|
+
const boundaries = nonZeroPieces.map((p)=>{
|
|
83
84
|
const [outerX, outerY] = p.points[1];
|
|
84
85
|
const len = Math.hypot(outerX, outerY) || 1;
|
|
85
86
|
return {
|
|
@@ -98,7 +99,7 @@ const PieSvg = ({ pieces, selectedIndex, radiusRelative })=>{
|
|
|
98
99
|
piece: p,
|
|
99
100
|
selected: i === selectedIndex
|
|
100
101
|
}, p.id) : null),
|
|
101
|
-
|
|
102
|
+
nonZeroPieces.length > 1 && innerR > 0 && outerR > 0 && /*#__PURE__*/ _jsxs(Fragment, {
|
|
102
103
|
children: [
|
|
103
104
|
/*#__PURE__*/ _jsx("defs", {
|
|
104
105
|
children: /*#__PURE__*/ _jsxs("mask", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/components/charts/pie-chart/components/pie.tsx"],"sourcesContent":["import { useCallback, useMemo, useState, FC, Fragment } from 'react';\nimport { tokens } from '@servicetitan/tokens/core';\nimport { BodyText, Popover, Stack } from '@servicetitan/design-system';\n\nimport { useClientRect } from '../../../../utils/use-client-rect';\nimport { PieChartPopoverContentType, PiePiece, PopoverDirection } from '../utils/interface';\nimport { ColorTag } from '../../common';\n\nconst chartPadding = 8;\nconst px = (value?: number) => `${value ?? 0}px`;\nconst GAP_PX = 4;\n\nconst PiePieceSvg: FC<{\n piece: PiePiece;\n selected?: boolean;\n}> = ({ piece: { id, color, points, text, path }, selected }) =>\n points && path ? (\n <g id={id}>\n {selected && (\n <path\n d={path}\n fill={tokens.colorWhite}\n stroke={tokens.colorBlue200}\n strokeOpacity=\"50%\"\n strokeWidth=\"3\"\n paintOrder=\"stroke\"\n />\n )}\n <path d={path} fill={color} />\n {points[4] && (\n <g transform={`translate(${points[4][0]}, ${points[4][1]})`} pointerEvents=\"none\">\n {(() => {\n const fontSize = 3;\n const height = 6;\n const radius = height / 2;\n\n const width = Math.max(8, text.length);\n\n return (\n <Fragment>\n <rect\n x={-width / 2}\n y={-height / 2}\n width={width}\n height={height}\n rx={radius}\n ry={radius}\n fill=\"rgba(255,255,255,0.80)\"\n strokeWidth={0.6}\n />\n <text\n x=\"0\"\n y=\"0\"\n fontSize={fontSize}\n fontWeight={600}\n textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n fill={tokens.colorBlack}\n >\n {text}\n </text>\n </Fragment>\n );\n })()}\n </g>\n )}\n </g>\n ) : null;\n\nconst PiePieceHover: FC<{\n piece: PiePiece;\n onMouse(id: string, isEnter: boolean): void;\n}> = ({ piece, onMouse }) => {\n const onMouseEnter = useCallback(() => onMouse(piece.id, true), [onMouse, piece.id]);\n const onMouseLeave = useCallback(() => onMouse(piece.id, false), [onMouse, piece.id]);\n\n return (\n <path\n d={piece.path}\n fill=\"white\"\n opacity=\"0\"\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n />\n );\n};\n\nconst PieSvg: FC<{\n pieces: PiePiece[];\n selectedIndex: number;\n radiusRelative: number;\n}> = ({ pieces, selectedIndex, radiusRelative }) => {\n const piePiece = pieces.find(p => p.points);\n const innerR = piePiece ? Math.hypot(piePiece.points![3][0], piePiece.points![3][1]) : 0;\n const outerR = piePiece ? Math.hypot(piePiece.points![1][0], piePiece.points![1][1]) : 0;\n\n const boundaries = pieces\n .filter(p => p.points)\n .map(p => {\n const [outerX, outerY] = p.points![1];\n const len = Math.hypot(outerX, outerY) || 1;\n return { x: outerX / len, y: outerY / len };\n });\n\n return (\n <svg\n className=\"position-absolute\"\n style={{ inset: `${chartPadding}px` }}\n viewBox={`-${radiusRelative} -${radiusRelative} ${radiusRelative * 2} ${radiusRelative * 2}`}\n >\n {pieces.map((p, i) =>\n p.path ? <PiePieceSvg piece={p} key={p.id} selected={i === selectedIndex} /> : null\n )}\n\n {pieces.length > 1 && innerR > 0 && outerR > 0 && (\n <Fragment>\n <defs>\n <mask id=\"ring-mask\">\n <rect\n x={-outerR}\n y={-outerR}\n width={outerR * 2}\n height={outerR * 2}\n fill=\"black\"\n />\n <circle cx=\"0\" cy=\"0\" r={outerR} fill=\"white\" />\n <circle cx=\"0\" cy=\"0\" r={innerR} fill=\"black\" />\n </mask>\n </defs>\n <g mask=\"url(#ring-mask)\" pointerEvents=\"none\">\n {boundaries.map(boundary => (\n <line\n key={`sep-${boundary.x}-${boundary.y}`}\n x1={boundary.x * innerR}\n y1={boundary.y * innerR}\n x2={boundary.x * outerR}\n y2={boundary.y * outerR}\n stroke=\"#fff\"\n strokeWidth={GAP_PX}\n vectorEffect=\"non-scaling-stroke\"\n strokeLinecap=\"round\"\n />\n ))}\n </g>\n </Fragment>\n )}\n {selectedIndex >= 0 && selectedIndex < pieces.length && (\n <use xlinkHref={`#${pieces[selectedIndex].id}`} />\n )}\n </svg>\n );\n};\n\nconst PieSvgHover: FC<{\n pieces: PiePiece[];\n radiusRelative: number;\n onMouse(id: string, isEnter: boolean): void;\n}> = ({ pieces, onMouse, radiusRelative }) => (\n <svg\n className=\"position-absolute z-global-nav\"\n style={{ inset: px(chartPadding) }}\n viewBox={\n `-${radiusRelative} -${radiusRelative} ` + `${radiusRelative * 2} ${radiusRelative * 2}`\n }\n >\n {pieces.map(p =>\n p.path ? <PiePieceHover piece={p} key={p.id} onMouse={onMouse} /> : null\n )}\n </svg>\n);\n\nexport const Pie: FC<{\n title: string;\n pieces: PiePiece[];\n radiusRelative: number;\n content?: FC;\n popoverContent?: PieChartPopoverContentType;\n hideTitles?: boolean;\n popoverDirection?: PopoverDirection;\n}> = ({\n pieces,\n popoverContent: PopoverContent,\n content: PieContent,\n radiusRelative,\n hideTitles,\n popoverDirection,\n}) => {\n const [selectedIndex, setSelectedIndex] = useState(-1);\n const [rect, ref] = useClientRect();\n\n const onMouse = useCallback(\n (id: string, isEnter: boolean) => {\n setSelectedIndex(isEnter ? pieces.findIndex(p => p.id === id) : -1);\n },\n [pieces, setSelectedIndex]\n );\n\n const container = useMemo(() => {\n const height = rect?.height ?? 0;\n\n return {\n height,\n internal: height ? height - chartPadding * 2 : 0,\n styles: height\n ? {\n width: px(Math.max(250, height)),\n }\n : {},\n };\n }, [rect]);\n\n const triggersStyles = useMemo(\n () =>\n container.height\n ? pieces.map(p =>\n p.points\n ? {\n key: p.key,\n top: px(\n (container.height * (radiusRelative + p.points[4][1])) /\n (radiusRelative * 2)\n ),\n left: px(\n (container.height * (radiusRelative + p.points[4][0])) /\n (radiusRelative * 2) +\n 20\n ),\n }\n : { top: '', left: '' }\n )\n : [],\n [pieces, container, radiusRelative]\n );\n\n return (\n <div ref={ref} style={container.styles} className=\"position-relative h-100\">\n {pieces.every(p => !p.path) ? (\n <Stack className=\"h-100\" justifyContent=\"center\" alignItems=\"center\">\n No Data\n </Stack>\n ) : (\n <Fragment>\n {triggersStyles\n .filter(ts => !!ts.left && !!ts.top)\n .map((ts, ind) => (\n <div key={ts.left + ts.top} style={ts} className=\"position-absolute\">\n {(!!PopoverContent || !hideTitles) && (\n <Popover\n portal\n trigger={<span> </span>}\n open={selectedIndex === ind}\n direction={popoverDirection}\n padding=\"s\"\n width=\"auto\"\n >\n {selectedIndex === ind && (\n <Stack\n direction=\"column\"\n data-cy={`customer-lead-rate-section-${ts.key}-popover`}\n >\n {!hideTitles && (\n <Stack alignItems=\"center\">\n <ColorTag\n label=\"\"\n color={pieces[ind].color}\n />\n <BodyText size=\"small\" bold>\n {pieces[ind].title}\n </BodyText>\n </Stack>\n )}\n {!!PopoverContent && (\n <Stack.Item className=\"m-l-1\">\n <PopoverContent\n index={ind}\n data={pieces[ind]?.data}\n text={pieces[ind]?.text}\n value={pieces[ind]?.value}\n />\n </Stack.Item>\n )}\n </Stack>\n )}\n </Popover>\n )}\n </div>\n ))}\n {!!PieContent && <PieContent />}\n <PieSvg\n pieces={pieces}\n selectedIndex={selectedIndex}\n radiusRelative={radiusRelative}\n />\n <PieSvgHover\n pieces={pieces}\n onMouse={onMouse}\n radiusRelative={radiusRelative}\n />\n </Fragment>\n )}\n </div>\n );\n};\n"],"names":["useCallback","useMemo","useState","Fragment","tokens","BodyText","Popover","Stack","useClientRect","ColorTag","chartPadding","px","value","GAP_PX","PiePieceSvg","piece","id","color","points","text","path","selected","g","d","fill","colorWhite","stroke","colorBlue200","strokeOpacity","strokeWidth","paintOrder","transform","pointerEvents","fontSize","height","radius","width","Math","max","length","rect","x","y","rx","ry","fontWeight","textAnchor","dominantBaseline","colorBlack","PiePieceHover","onMouse","onMouseEnter","onMouseLeave","opacity","PieSvg","pieces","selectedIndex","radiusRelative","piePiece","find","p","innerR","hypot","outerR","boundaries","filter","map","outerX","outerY","len","svg","className","style","inset","viewBox","i","defs","mask","circle","cx","cy","r","boundary","line","x1","y1","x2","y2","vectorEffect","strokeLinecap","use","xlinkHref","PieSvgHover","Pie","popoverContent","PopoverContent","content","PieContent","hideTitles","popoverDirection","setSelectedIndex","ref","isEnter","findIndex","container","internal","styles","triggersStyles","key","top","left","div","every","justifyContent","alignItems","ts","ind","portal","trigger","span","open","direction","padding","data-cy","label","size","bold","title","Item","index","data"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/components/charts/pie-chart/components/pie.tsx"],"sourcesContent":["import { useCallback, useMemo, useState, FC, Fragment } from 'react';\nimport { tokens } from '@servicetitan/tokens/core';\nimport { BodyText, Popover, Stack } from '@servicetitan/design-system';\n\nimport { useClientRect } from '../../../../utils/use-client-rect';\nimport { PieChartPopoverContentType, PiePiece, PopoverDirection } from '../utils/interface';\nimport { ColorTag } from '../../common';\n\nconst chartPadding = 8;\nconst px = (value?: number) => `${value ?? 0}px`;\nconst GAP_PX = 4;\n\nconst PiePieceSvg: FC<{\n piece: PiePiece;\n selected?: boolean;\n}> = ({ piece: { id, color, points, text, path }, selected }) =>\n points && path ? (\n <g id={id}>\n {selected && (\n <path\n d={path}\n fill={tokens.colorWhite}\n stroke={tokens.colorBlue200}\n strokeOpacity=\"50%\"\n strokeWidth=\"3\"\n paintOrder=\"stroke\"\n />\n )}\n <path d={path} fill={color} />\n {points[4] && (\n <g transform={`translate(${points[4][0]}, ${points[4][1]})`} pointerEvents=\"none\">\n {(() => {\n const fontSize = 3;\n const height = 6;\n const radius = height / 2;\n\n const width = Math.max(8, text.length);\n\n return (\n <Fragment>\n <rect\n x={-width / 2}\n y={-height / 2}\n width={width}\n height={height}\n rx={radius}\n ry={radius}\n fill=\"rgba(255,255,255,0.80)\"\n strokeWidth={0.6}\n />\n <text\n x=\"0\"\n y=\"0\"\n fontSize={fontSize}\n fontWeight={600}\n textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n fill={tokens.colorBlack}\n >\n {text}\n </text>\n </Fragment>\n );\n })()}\n </g>\n )}\n </g>\n ) : null;\n\nconst PiePieceHover: FC<{\n piece: PiePiece;\n onMouse(id: string, isEnter: boolean): void;\n}> = ({ piece, onMouse }) => {\n const onMouseEnter = useCallback(() => onMouse(piece.id, true), [onMouse, piece.id]);\n const onMouseLeave = useCallback(() => onMouse(piece.id, false), [onMouse, piece.id]);\n\n return (\n <path\n d={piece.path}\n fill=\"white\"\n opacity=\"0\"\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n />\n );\n};\n\nconst PieSvg: FC<{\n pieces: PiePiece[];\n selectedIndex: number;\n radiusRelative: number;\n}> = ({ pieces, selectedIndex, radiusRelative }) => {\n const piePiece = pieces.find(p => p.points);\n const innerR = piePiece ? Math.hypot(piePiece.points![3][0], piePiece.points![3][1]) : 0;\n const outerR = piePiece ? Math.hypot(piePiece.points![1][0], piePiece.points![1][1]) : 0;\n\n const nonZeroPieces = pieces.filter(p => p.points && p.path);\n const boundaries = nonZeroPieces.map(p => {\n const [outerX, outerY] = p.points![1];\n const len = Math.hypot(outerX, outerY) || 1;\n return { x: outerX / len, y: outerY / len };\n });\n\n return (\n <svg\n className=\"position-absolute\"\n style={{ inset: `${chartPadding}px` }}\n viewBox={`-${radiusRelative} -${radiusRelative} ${radiusRelative * 2} ${radiusRelative * 2}`}\n >\n {pieces.map((p, i) =>\n p.path ? <PiePieceSvg piece={p} key={p.id} selected={i === selectedIndex} /> : null\n )}\n {nonZeroPieces.length > 1 && innerR > 0 && outerR > 0 && (\n <Fragment>\n <defs>\n <mask id=\"ring-mask\">\n <rect\n x={-outerR}\n y={-outerR}\n width={outerR * 2}\n height={outerR * 2}\n fill=\"black\"\n />\n <circle cx=\"0\" cy=\"0\" r={outerR} fill=\"white\" />\n <circle cx=\"0\" cy=\"0\" r={innerR} fill=\"black\" />\n </mask>\n </defs>\n <g mask=\"url(#ring-mask)\" pointerEvents=\"none\">\n {boundaries.map(boundary => (\n <line\n key={`sep-${boundary.x}-${boundary.y}`}\n x1={boundary.x * innerR}\n y1={boundary.y * innerR}\n x2={boundary.x * outerR}\n y2={boundary.y * outerR}\n stroke=\"#fff\"\n strokeWidth={GAP_PX}\n vectorEffect=\"non-scaling-stroke\"\n strokeLinecap=\"round\"\n />\n ))}\n </g>\n </Fragment>\n )}\n {selectedIndex >= 0 && selectedIndex < pieces.length && (\n <use xlinkHref={`#${pieces[selectedIndex].id}`} />\n )}\n </svg>\n );\n};\n\nconst PieSvgHover: FC<{\n pieces: PiePiece[];\n radiusRelative: number;\n onMouse(id: string, isEnter: boolean): void;\n}> = ({ pieces, onMouse, radiusRelative }) => (\n <svg\n className=\"position-absolute z-global-nav\"\n style={{ inset: px(chartPadding) }}\n viewBox={\n `-${radiusRelative} -${radiusRelative} ` + `${radiusRelative * 2} ${radiusRelative * 2}`\n }\n >\n {pieces.map(p =>\n p.path ? <PiePieceHover piece={p} key={p.id} onMouse={onMouse} /> : null\n )}\n </svg>\n);\n\nexport const Pie: FC<{\n title: string;\n pieces: PiePiece[];\n radiusRelative: number;\n content?: FC;\n popoverContent?: PieChartPopoverContentType;\n hideTitles?: boolean;\n popoverDirection?: PopoverDirection;\n}> = ({\n pieces,\n popoverContent: PopoverContent,\n content: PieContent,\n radiusRelative,\n hideTitles,\n popoverDirection,\n}) => {\n const [selectedIndex, setSelectedIndex] = useState(-1);\n const [rect, ref] = useClientRect();\n\n const onMouse = useCallback(\n (id: string, isEnter: boolean) => {\n setSelectedIndex(isEnter ? pieces.findIndex(p => p.id === id) : -1);\n },\n [pieces, setSelectedIndex]\n );\n\n const container = useMemo(() => {\n const height = rect?.height ?? 0;\n\n return {\n height,\n internal: height ? height - chartPadding * 2 : 0,\n styles: height\n ? {\n width: px(Math.max(250, height)),\n }\n : {},\n };\n }, [rect]);\n\n const triggersStyles = useMemo(\n () =>\n container.height\n ? pieces.map(p =>\n p.points\n ? {\n key: p.key,\n top: px(\n (container.height * (radiusRelative + p.points[4][1])) /\n (radiusRelative * 2)\n ),\n left: px(\n (container.height * (radiusRelative + p.points[4][0])) /\n (radiusRelative * 2) +\n 20\n ),\n }\n : { top: '', left: '' }\n )\n : [],\n [pieces, container, radiusRelative]\n );\n\n return (\n <div ref={ref} style={container.styles} className=\"position-relative h-100\">\n {pieces.every(p => !p.path) ? (\n <Stack className=\"h-100\" justifyContent=\"center\" alignItems=\"center\">\n No Data\n </Stack>\n ) : (\n <Fragment>\n {triggersStyles\n .filter(ts => !!ts.left && !!ts.top)\n .map((ts, ind) => (\n <div key={ts.left + ts.top} style={ts} className=\"position-absolute\">\n {(!!PopoverContent || !hideTitles) && (\n <Popover\n portal\n trigger={<span> </span>}\n open={selectedIndex === ind}\n direction={popoverDirection}\n padding=\"s\"\n width=\"auto\"\n >\n {selectedIndex === ind && (\n <Stack\n direction=\"column\"\n data-cy={`customer-lead-rate-section-${ts.key}-popover`}\n >\n {!hideTitles && (\n <Stack alignItems=\"center\">\n <ColorTag\n label=\"\"\n color={pieces[ind].color}\n />\n <BodyText size=\"small\" bold>\n {pieces[ind].title}\n </BodyText>\n </Stack>\n )}\n {!!PopoverContent && (\n <Stack.Item className=\"m-l-1\">\n <PopoverContent\n index={ind}\n data={pieces[ind]?.data}\n text={pieces[ind]?.text}\n value={pieces[ind]?.value}\n />\n </Stack.Item>\n )}\n </Stack>\n )}\n </Popover>\n )}\n </div>\n ))}\n {!!PieContent && <PieContent />}\n <PieSvg\n pieces={pieces}\n selectedIndex={selectedIndex}\n radiusRelative={radiusRelative}\n />\n <PieSvgHover\n pieces={pieces}\n onMouse={onMouse}\n radiusRelative={radiusRelative}\n />\n </Fragment>\n )}\n </div>\n );\n};\n"],"names":["useCallback","useMemo","useState","Fragment","tokens","BodyText","Popover","Stack","useClientRect","ColorTag","chartPadding","px","value","GAP_PX","PiePieceSvg","piece","id","color","points","text","path","selected","g","d","fill","colorWhite","stroke","colorBlue200","strokeOpacity","strokeWidth","paintOrder","transform","pointerEvents","fontSize","height","radius","width","Math","max","length","rect","x","y","rx","ry","fontWeight","textAnchor","dominantBaseline","colorBlack","PiePieceHover","onMouse","onMouseEnter","onMouseLeave","opacity","PieSvg","pieces","selectedIndex","radiusRelative","piePiece","find","p","innerR","hypot","outerR","nonZeroPieces","filter","boundaries","map","outerX","outerY","len","svg","className","style","inset","viewBox","i","defs","mask","circle","cx","cy","r","boundary","line","x1","y1","x2","y2","vectorEffect","strokeLinecap","use","xlinkHref","PieSvgHover","Pie","popoverContent","PopoverContent","content","PieContent","hideTitles","popoverDirection","setSelectedIndex","ref","isEnter","findIndex","container","internal","styles","triggersStyles","key","top","left","div","every","justifyContent","alignItems","ts","ind","portal","trigger","span","open","direction","padding","data-cy","label","size","bold","title","Item","index","data"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stat-card.d.ts","sourceRoot":"","sources":["../../../src/components/stat/stat-card.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,SAAS,EAAY,MAAM,OAAO,CAAC;AAEhD,OAAO,EAEH,mBAAmB,EAKtB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAe,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAmCtE,UAAU,aAAa;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,eAAO,MAAM,QAAQ,EAAE,EAAE,CAAC,aAAa,
|
|
1
|
+
{"version":3,"file":"stat-card.d.ts","sourceRoot":"","sources":["../../../src/components/stat/stat-card.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,SAAS,EAAY,MAAM,OAAO,CAAC;AAEhD,OAAO,EAEH,mBAAmB,EAKtB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAe,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAmCtE,UAAU,aAAa;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,eAAO,MAAM,QAAQ,EAAE,EAAE,CAAC,aAAa,CA0EtC,CAAC;AAEF,MAAM,WAAW,aAAa;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,eAAO,MAAM,QAAQ,EAAE,EAAE,CAAC,aAAa,CAyEtC,CAAC"}
|
|
@@ -36,7 +36,7 @@ export const StatDiff = ({ value, prev, size, format, inverted, neutral, classNa
|
|
|
36
36
|
const [absDiff, diffPercent, isIncrease] = calculateDiff(value !== null && value !== void 0 ? value : 0, prev !== null && prev !== void 0 ? prev : 0, percents);
|
|
37
37
|
const diff = absDiff === 0 ? '' : /*#__PURE__*/ _jsx(Icon, {
|
|
38
38
|
svg: isIncrease ? TrendingUpSVG : TrendingDownSVG,
|
|
39
|
-
color: isIncrease ? 'green' : 'red',
|
|
39
|
+
color: neutral ? 'neutral-200' : inverted ? isIncrease ? 'red' : 'green' : isIncrease ? 'green' : 'red',
|
|
40
40
|
className: "m-r-half m-t-half"
|
|
41
41
|
});
|
|
42
42
|
let text = '';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/stat/stat-card.tsx"],"sourcesContent":["import { FC, ReactNode, useState } from 'react';\nimport classNames from 'classnames';\nimport {\n BodyText,\n BodyTextPropsStrict,\n Eyebrow,\n Popover,\n Stack,\n Tooltip,\n} from '@servicetitan/design-system';\nimport * as Styles from './stat-card.module.less';\nimport { formatValue, NumberFormatter } from '../../utils/formatters';\nimport { Icon } from '@servicetitan/anvil2';\nimport TrendingUpSVG from '@servicetitan/anvil2/assets/icons/material/round/trending_up.svg';\nimport TrendingDownSVG from '@servicetitan/anvil2/assets/icons/material/round/trending_down.svg';\n\nconst calculateDiff = (\n value: number,\n prev: number,\n percents?: boolean\n): [number, number, boolean] => {\n const diff = (value - prev) * (percents ? 100 : 1);\n const absDiff = Math.abs(diff);\n let diffPercent = 0;\n\n if (percents) {\n diffPercent = diff;\n } else if (absDiff) {\n diffPercent = prev ? (100 * absDiff) / prev : 100;\n }\n\n return [absDiff, diffPercent, diff >= 0];\n};\n\nconst formatDifference = (value: number, isPlus: boolean, format: NumberFormatter): string => {\n return (isPlus ? '+' : '-') + formatValue(value, format);\n};\n\nconst formatDifferencePercentage = (value: number, isPlus: boolean): string => {\n if (!value) {\n return '';\n }\n\n return (isPlus ? '+' : '-') + formatValue(value, 'percent-100');\n};\n\ninterface StatDiffProps {\n value?: number;\n prev?: number;\n size?: BodyTextPropsStrict['size'];\n format: NumberFormatter;\n inverted?: boolean;\n neutral?: boolean;\n className?: string;\n diffPercentOnly?: boolean;\n}\n\nexport const StatDiff: FC<StatDiffProps> = ({\n value,\n prev,\n size,\n format,\n inverted,\n neutral,\n className,\n diffPercentOnly = false,\n}) => {\n const percents = format === 'percent';\n const [absDiff, diffPercent, isIncrease] = calculateDiff(value ?? 0, prev ?? 0, percents);\n const diff =\n absDiff === 0 ? (\n ''\n ) : (\n <Icon\n svg={isIncrease ? TrendingUpSVG : TrendingDownSVG}\n color={isIncrease ? 'green' : 'red'}\n className=\"m-r-half m-t-half\"\n />\n );\n let text = '';\n\n if (percents) {\n text += formatDifferencePercentage(absDiff, isIncrease);\n } else {\n const diffPercentage = formatDifferencePercentage(diffPercent, isIncrease);\n\n if (diffPercentOnly) {\n text += `${diffPercentage}`;\n } else {\n text += `${formatDifference(absDiff, isIncrease, format)}`;\n\n if (diffPercent !== 0) {\n text += ` (${diffPercentage})`;\n }\n }\n }\n\n return (\n <Stack\n className={classNames(Styles.statDiff, className)}\n justifyContent=\"center\"\n alignItems=\"center\"\n >\n <Stack.Item>\n <span>{diff}</span>\n </Stack.Item>\n <Stack.Item>\n <BodyText\n size={size ?? 'small'}\n data-cy=\"stat-diff-value\"\n className={classNames({\n 'c-red-500': !neutral && (inverted ? isIncrease : !isIncrease),\n 'c-green-500': !neutral && (inverted ? !isIncrease : isIncrease),\n 'c-neutral-200': !!neutral,\n })}\n >\n {value === undefined ? '\\u00A0' : text}\n </BodyText>\n </Stack.Item>\n </Stack>\n );\n};\n\nexport interface StatCardProps {\n title: string;\n description?: string;\n popoverContent?: ReactNode;\n value?: number;\n prev?: number;\n percent?: boolean;\n money?: boolean;\n rate?: boolean;\n clean?: boolean;\n inverted?: boolean;\n neutral?: boolean;\n fill?: boolean;\n valueOnly?: boolean;\n className?: string;\n diffPercentOnly?: boolean;\n}\n\nexport const StatCard: FC<StatCardProps> = ({\n title,\n description,\n popoverContent,\n value,\n percent,\n money,\n rate,\n prev,\n clean,\n inverted,\n neutral,\n fill,\n valueOnly,\n className,\n diffPercentOnly = false,\n}) => {\n const [popoverShown, setPopoverShown] = useState(false);\n const format = money ? 'money' : percent ? 'percent' : rate ? 'rate' : 'number';\n const val = value === undefined ? '\\u00A0' : formatValue(value, format);\n\n const eyebrow = (\n <Eyebrow\n className={classNames(Styles.title, 'ta-center')}\n data-cy={`marketing-stat-${title}-title`}\n onMouseEnter={() => {\n setPopoverShown(true);\n }}\n >\n {title}\n </Eyebrow>\n );\n\n return (\n <Stack\n direction=\"column\"\n alignItems=\"center\"\n className={classNames(\n 'p-y-3',\n {\n 'bg-white border-radius-2 border': !clean,\n 'flex-grow-1 flex-basis-0': fill,\n },\n className\n )}\n onMouseLeave={() => setPopoverShown(false)}\n >\n {popoverContent ? (\n <Popover open={popoverShown} trigger={eyebrow}>\n {popoverContent}\n </Popover>\n ) : description ? (\n <Tooltip text={description} data-cy={`marketing-stat-${title}-tooltip`}>\n {eyebrow}\n </Tooltip>\n ) : (\n eyebrow\n )}\n <BodyText className=\"fs-6-i ff-display\" data-cy={`marketing-stat-${title}-value`}>\n {val}\n </BodyText>\n {!valueOnly && (\n <StatDiff\n value={value}\n prev={prev}\n format={format}\n inverted={inverted}\n neutral={neutral}\n diffPercentOnly={diffPercentOnly}\n />\n )}\n </Stack>\n );\n};\n"],"names":["useState","classNames","BodyText","Eyebrow","Popover","Stack","Tooltip","Styles","formatValue","Icon","TrendingUpSVG","TrendingDownSVG","calculateDiff","value","prev","percents","diff","absDiff","Math","abs","diffPercent","formatDifference","isPlus","format","formatDifferencePercentage","StatDiff","size","inverted","neutral","className","diffPercentOnly","isIncrease","svg","color","text","diffPercentage","statDiff","justifyContent","alignItems","Item","span","data-cy","undefined","StatCard","title","description","popoverContent","percent","money","rate","clean","fill","valueOnly","popoverShown","setPopoverShown","val","eyebrow","onMouseEnter","direction","onMouseLeave","open","trigger"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/stat/stat-card.tsx"],"sourcesContent":["import { FC, ReactNode, useState } from 'react';\nimport classNames from 'classnames';\nimport {\n BodyText,\n BodyTextPropsStrict,\n Eyebrow,\n Popover,\n Stack,\n Tooltip,\n} from '@servicetitan/design-system';\nimport * as Styles from './stat-card.module.less';\nimport { formatValue, NumberFormatter } from '../../utils/formatters';\nimport { Icon } from '@servicetitan/anvil2';\nimport TrendingUpSVG from '@servicetitan/anvil2/assets/icons/material/round/trending_up.svg';\nimport TrendingDownSVG from '@servicetitan/anvil2/assets/icons/material/round/trending_down.svg';\n\nconst calculateDiff = (\n value: number,\n prev: number,\n percents?: boolean\n): [number, number, boolean] => {\n const diff = (value - prev) * (percents ? 100 : 1);\n const absDiff = Math.abs(diff);\n let diffPercent = 0;\n\n if (percents) {\n diffPercent = diff;\n } else if (absDiff) {\n diffPercent = prev ? (100 * absDiff) / prev : 100;\n }\n\n return [absDiff, diffPercent, diff >= 0];\n};\n\nconst formatDifference = (value: number, isPlus: boolean, format: NumberFormatter): string => {\n return (isPlus ? '+' : '-') + formatValue(value, format);\n};\n\nconst formatDifferencePercentage = (value: number, isPlus: boolean): string => {\n if (!value) {\n return '';\n }\n\n return (isPlus ? '+' : '-') + formatValue(value, 'percent-100');\n};\n\ninterface StatDiffProps {\n value?: number;\n prev?: number;\n size?: BodyTextPropsStrict['size'];\n format: NumberFormatter;\n inverted?: boolean;\n neutral?: boolean;\n className?: string;\n diffPercentOnly?: boolean;\n}\n\nexport const StatDiff: FC<StatDiffProps> = ({\n value,\n prev,\n size,\n format,\n inverted,\n neutral,\n className,\n diffPercentOnly = false,\n}) => {\n const percents = format === 'percent';\n const [absDiff, diffPercent, isIncrease] = calculateDiff(value ?? 0, prev ?? 0, percents);\n const diff =\n absDiff === 0 ? (\n ''\n ) : (\n <Icon\n svg={isIncrease ? TrendingUpSVG : TrendingDownSVG}\n color={\n neutral\n ? 'neutral-200'\n : inverted\n ? isIncrease\n ? 'red'\n : 'green'\n : isIncrease\n ? 'green'\n : 'red'\n }\n className=\"m-r-half m-t-half\"\n />\n );\n let text = '';\n\n if (percents) {\n text += formatDifferencePercentage(absDiff, isIncrease);\n } else {\n const diffPercentage = formatDifferencePercentage(diffPercent, isIncrease);\n\n if (diffPercentOnly) {\n text += `${diffPercentage}`;\n } else {\n text += `${formatDifference(absDiff, isIncrease, format)}`;\n\n if (diffPercent !== 0) {\n text += ` (${diffPercentage})`;\n }\n }\n }\n\n return (\n <Stack\n className={classNames(Styles.statDiff, className)}\n justifyContent=\"center\"\n alignItems=\"center\"\n >\n <Stack.Item>\n <span>{diff}</span>\n </Stack.Item>\n <Stack.Item>\n <BodyText\n size={size ?? 'small'}\n data-cy=\"stat-diff-value\"\n className={classNames({\n 'c-red-500': !neutral && (inverted ? isIncrease : !isIncrease),\n 'c-green-500': !neutral && (inverted ? !isIncrease : isIncrease),\n 'c-neutral-200': !!neutral,\n })}\n >\n {value === undefined ? '\\u00A0' : text}\n </BodyText>\n </Stack.Item>\n </Stack>\n );\n};\n\nexport interface StatCardProps {\n title: string;\n description?: string;\n popoverContent?: ReactNode;\n value?: number;\n prev?: number;\n percent?: boolean;\n money?: boolean;\n rate?: boolean;\n clean?: boolean;\n inverted?: boolean;\n neutral?: boolean;\n fill?: boolean;\n valueOnly?: boolean;\n className?: string;\n diffPercentOnly?: boolean;\n}\n\nexport const StatCard: FC<StatCardProps> = ({\n title,\n description,\n popoverContent,\n value,\n percent,\n money,\n rate,\n prev,\n clean,\n inverted,\n neutral,\n fill,\n valueOnly,\n className,\n diffPercentOnly = false,\n}) => {\n const [popoverShown, setPopoverShown] = useState(false);\n const format = money ? 'money' : percent ? 'percent' : rate ? 'rate' : 'number';\n const val = value === undefined ? '\\u00A0' : formatValue(value, format);\n\n const eyebrow = (\n <Eyebrow\n className={classNames(Styles.title, 'ta-center')}\n data-cy={`marketing-stat-${title}-title`}\n onMouseEnter={() => {\n setPopoverShown(true);\n }}\n >\n {title}\n </Eyebrow>\n );\n\n return (\n <Stack\n direction=\"column\"\n alignItems=\"center\"\n className={classNames(\n 'p-y-3',\n {\n 'bg-white border-radius-2 border': !clean,\n 'flex-grow-1 flex-basis-0': fill,\n },\n className\n )}\n onMouseLeave={() => setPopoverShown(false)}\n >\n {popoverContent ? (\n <Popover open={popoverShown} trigger={eyebrow}>\n {popoverContent}\n </Popover>\n ) : description ? (\n <Tooltip text={description} data-cy={`marketing-stat-${title}-tooltip`}>\n {eyebrow}\n </Tooltip>\n ) : (\n eyebrow\n )}\n <BodyText className=\"fs-6-i ff-display\" data-cy={`marketing-stat-${title}-value`}>\n {val}\n </BodyText>\n {!valueOnly && (\n <StatDiff\n value={value}\n prev={prev}\n format={format}\n inverted={inverted}\n neutral={neutral}\n diffPercentOnly={diffPercentOnly}\n />\n )}\n </Stack>\n );\n};\n"],"names":["useState","classNames","BodyText","Eyebrow","Popover","Stack","Tooltip","Styles","formatValue","Icon","TrendingUpSVG","TrendingDownSVG","calculateDiff","value","prev","percents","diff","absDiff","Math","abs","diffPercent","formatDifference","isPlus","format","formatDifferencePercentage","StatDiff","size","inverted","neutral","className","diffPercentOnly","isIncrease","svg","color","text","diffPercentage","statDiff","justifyContent","alignItems","Item","span","data-cy","undefined","StatCard","title","description","popoverContent","percent","money","rate","clean","fill","valueOnly","popoverShown","setPopoverShown","val","eyebrow","onMouseEnter","direction","onMouseLeave","open","trigger"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@servicetitan/marketing-ui",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.1",
|
|
4
4
|
"description": "Marketing UI component and utils",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -53,5 +53,5 @@
|
|
|
53
53
|
"less": true,
|
|
54
54
|
"webpack": false
|
|
55
55
|
},
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "231fbedc1ec501f5e88216dab08c1cd20192579d"
|
|
57
57
|
}
|
|
@@ -94,13 +94,12 @@ const PieSvg: FC<{
|
|
|
94
94
|
const innerR = piePiece ? Math.hypot(piePiece.points![3][0], piePiece.points![3][1]) : 0;
|
|
95
95
|
const outerR = piePiece ? Math.hypot(piePiece.points![1][0], piePiece.points![1][1]) : 0;
|
|
96
96
|
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
});
|
|
97
|
+
const nonZeroPieces = pieces.filter(p => p.points && p.path);
|
|
98
|
+
const boundaries = nonZeroPieces.map(p => {
|
|
99
|
+
const [outerX, outerY] = p.points![1];
|
|
100
|
+
const len = Math.hypot(outerX, outerY) || 1;
|
|
101
|
+
return { x: outerX / len, y: outerY / len };
|
|
102
|
+
});
|
|
104
103
|
|
|
105
104
|
return (
|
|
106
105
|
<svg
|
|
@@ -111,8 +110,7 @@ const PieSvg: FC<{
|
|
|
111
110
|
{pieces.map((p, i) =>
|
|
112
111
|
p.path ? <PiePieceSvg piece={p} key={p.id} selected={i === selectedIndex} /> : null
|
|
113
112
|
)}
|
|
114
|
-
|
|
115
|
-
{pieces.length > 1 && innerR > 0 && outerR > 0 && (
|
|
113
|
+
{nonZeroPieces.length > 1 && innerR > 0 && outerR > 0 && (
|
|
116
114
|
<Fragment>
|
|
117
115
|
<defs>
|
|
118
116
|
<mask id="ring-mask">
|
|
@@ -73,7 +73,17 @@ export const StatDiff: FC<StatDiffProps> = ({
|
|
|
73
73
|
) : (
|
|
74
74
|
<Icon
|
|
75
75
|
svg={isIncrease ? TrendingUpSVG : TrendingDownSVG}
|
|
76
|
-
color={
|
|
76
|
+
color={
|
|
77
|
+
neutral
|
|
78
|
+
? 'neutral-200'
|
|
79
|
+
: inverted
|
|
80
|
+
? isIncrease
|
|
81
|
+
? 'red'
|
|
82
|
+
: 'green'
|
|
83
|
+
: isIncrease
|
|
84
|
+
? 'green'
|
|
85
|
+
: 'red'
|
|
86
|
+
}
|
|
77
87
|
className="m-r-half m-t-half"
|
|
78
88
|
/>
|
|
79
89
|
);
|