@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.
Files changed (40) hide show
  1. package/dist/components/charts/funnel-chart/components/funnel-chart.d.ts.map +1 -1
  2. package/dist/components/charts/funnel-chart/components/funnel-chart.js +1 -2
  3. package/dist/components/charts/funnel-chart/components/funnel-chart.js.map +1 -1
  4. package/dist/components/charts/funnel-chart/components/funnel-svg.js +3 -3
  5. package/dist/components/charts/funnel-chart/components/funnel-svg.js.map +1 -1
  6. package/dist/components/charts/line-chart/components/body.js +2 -2
  7. package/dist/components/charts/line-chart/components/body.js.map +1 -1
  8. package/dist/components/charts/line-chart/components/hover-popover.d.ts.map +1 -1
  9. package/dist/components/charts/line-chart/components/hover-popover.js +69 -44
  10. package/dist/components/charts/line-chart/components/hover-popover.js.map +1 -1
  11. package/dist/components/charts/line-chart/components/hover-popover.module.less +26 -1
  12. package/dist/components/charts/line-chart/components/hover-popover.module.less.d.ts +3 -0
  13. package/dist/components/charts/line-chart/components/stuff.js +2 -1
  14. package/dist/components/charts/line-chart/components/stuff.js.map +1 -1
  15. package/dist/components/charts/line-chart/components/svg-bars.js +1 -1
  16. package/dist/components/charts/line-chart/components/svg-bars.js.map +1 -1
  17. package/dist/components/charts/pie-chart/components/pie-chart.js +1 -0
  18. package/dist/components/charts/pie-chart/components/pie-chart.js.map +1 -1
  19. package/dist/components/charts/pie-chart/components/pie-chart.module.less +8 -0
  20. package/dist/components/charts/pie-chart/components/pie-chart.module.less.d.ts +2 -0
  21. package/dist/components/charts/pie-chart/components/pie.d.ts.map +1 -1
  22. package/dist/components/charts/pie-chart/components/pie.js +2 -0
  23. package/dist/components/charts/pie-chart/components/pie.js.map +1 -1
  24. package/dist/components/stat/stat-card.d.ts.map +1 -1
  25. package/dist/components/stat/stat-card.js +2 -2
  26. package/dist/components/stat/stat-card.js.map +1 -1
  27. package/package.json +2 -2
  28. package/src/components/charts/funnel-chart/components/funnel-chart.tsx +0 -1
  29. package/src/components/charts/funnel-chart/components/funnel-svg.tsx +3 -3
  30. package/src/components/charts/line-chart/components/body.tsx +1 -1
  31. package/src/components/charts/line-chart/components/hover-popover.module.less +26 -1
  32. package/src/components/charts/line-chart/components/hover-popover.module.less.d.ts +3 -0
  33. package/src/components/charts/line-chart/components/hover-popover.tsx +85 -47
  34. package/src/components/charts/line-chart/components/stuff.tsx +1 -1
  35. package/src/components/charts/line-chart/components/svg-bars.tsx +1 -1
  36. package/src/components/charts/pie-chart/components/pie-chart.module.less +8 -0
  37. package/src/components/charts/pie-chart/components/pie-chart.module.less.d.ts +2 -0
  38. package/src/components/charts/pie-chart/components/pie-chart.tsx +1 -1
  39. package/src/components/charts/pie-chart/components/pie.tsx +2 -0
  40. package/src/components/stat/stat-card.tsx +1 -2
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/components/charts/line-chart/components/svg-bars.tsx"],"sourcesContent":["import { FC } from 'react';\nimport { observer } from 'mobx-react';\nimport { useDependencies } from '@servicetitan/react-ioc';\nimport { ChartMetric } from '../utils/internal-interfaces';\nimport { keyVal } from '../utils/key';\nimport { SvgStore } from '../stores/svg.store';\n\ninterface SvgBarsProps {\n metrics: ChartMetric[];\n isStackedBarChart?: boolean;\n isGroupedBarChart?: boolean;\n}\n\nexport const SvgBars: FC<SvgBarsProps> = observer(\n ({ metrics, isStackedBarChart, isGroupedBarChart }) => {\n const [store] = useDependencies(SvgStore);\n const { fpx, fpy, barWidth, length } = store;\n const barWidthHalf = barWidth / 2;\n const paths = [];\n\n const patternDefs = metrics\n .filter(m => m.opts?.pattern === 'striped')\n .map(m => {\n const rotation = 20;\n const tileW = 0.6;\n const tileH = 0.6;\n const stripeWidth = Math.max(0.1, Math.floor(tileW / 20));\n const tintOpacity = 0.06;\n\n return (\n <pattern\n key={`pattern-${m.id}`}\n id={`stripe-pattern-${m.id}`}\n patternUnits=\"userSpaceOnUse\"\n width={tileW}\n height={tileH}\n patternTransform={`rotate(${rotation})`}\n >\n <rect width={tileW} height={tileH} fill={m.color} opacity={tintOpacity} />\n <rect width={stripeWidth} height={tileH} fill={m.color} />\n </pattern>\n );\n });\n\n for (let i = 0; i < length; i++) {\n const x = store.periodX(i);\n const values = metrics.map(m => ({\n id: m.id,\n color: m.valuesOpts?.[i]?.color ?? m.color,\n opacity: m.opacity,\n val: store.periodY(m, i),\n pattern: m.opts?.pattern,\n strokeColor: m.opts?.strokeColor,\n outlineColor: m.opts?.outlineColor,\n value: m.values[i],\n }));\n\n if (isStackedBarChart) {\n const spacingBetweenSegments = 1; // Approximately 4px in SVG coordinates\n const totalSpacing = (values.length - 1) * spacingBetweenSegments;\n let stackedBarHeight =\n values.reduce((sum, curr) => sum + curr.val, 0) + totalSpacing;\n\n const totalValue = values.reduce((sum, curr) => sum + curr.value, 0);\n if (totalValue > 0) {\n const yTop = +fpy(stackedBarHeight);\n const scaleX = 0.3;\n const scaleY = 1;\n\n paths.push(\n <g\n key={`total-${i}`}\n transform={`translate(${x},${yTop}) scale(${scaleX},${scaleY})`}\n pointerEvents=\"none\"\n >\n <text\n x={0}\n y={0}\n textAnchor=\"middle\"\n dominantBaseline=\"alphabetic\"\n fontSize=\"2.5\"\n fontWeight={600}\n fill=\"#111827\"\n stroke=\"white\"\n strokeWidth={0.8}\n paintOrder=\"stroke\"\n fontFamily=\"Nunito Sans\"\n >\n {Math.round(totalValue)}\n </text>\n </g>\n );\n }\n\n for (let j = 0; j < values.length; j++) {\n const value = values[j];\n stackedBarHeight -= spacingBetweenSegments;\n\n const TOP_RADIUS = 1;\n const xLeft = +fpx(x - barWidth / 2);\n const yTop = +fpy(stackedBarHeight) + (values.length - 2);\n const height = +fpx(value.val);\n const width = +fpx(barWidth);\n\n const r = j === 0 ? TOP_RADIUS : 0; // radius must be numeric\n\n const d = [\n `M ${xLeft} ${yTop + height}`, // bottom-left\n `L ${xLeft} ${yTop + r}`, // up left edge\n `Q ${xLeft} ${yTop} ${xLeft + r / 2} ${yTop}`, // top-left corner\n `L ${xLeft + width - r / 2} ${yTop}`, // across top\n `Q ${xLeft + width} ${yTop} ${xLeft + width} ${yTop + r}`, // top-right corner\n `L ${xLeft + width} ${yTop + height}`, // down right edge\n 'Z',\n ].join(' ');\n paths.push(\n <path\n key={keyVal(value.id, i)}\n d={d}\n fill={\n value.pattern === 'striped'\n ? `url(#stripe-pattern-${value.id})`\n : value.color\n }\n stroke={\n value.pattern === 'outline'\n ? value.outlineColor\n : (value.strokeColor ?? value.color)\n }\n strokeWidth={1}\n vectorEffect=\"non-scaling-stroke\"\n strokeLinejoin=\"round\"\n />\n );\n\n stackedBarHeight -= value.val;\n }\n } else if (isGroupedBarChart) {\n for (let j = 0; j < values.length; j++) {\n const groupedBarX = (j * barWidth) / values.length;\n const value = values[j];\n\n paths.push(\n <rect\n key={keyVal(value.id, i)}\n x={x + groupedBarX - barWidthHalf}\n y={fpy(value.val)}\n width={barWidth / values.length - 0.1}\n height={fpx(value.val)}\n fill={value.color}\n opacity={value.opacity}\n />\n );\n }\n } else {\n values.sort((a, b) => b.val - a.val);\n for (const value of values) {\n paths.push(\n <rect\n key={keyVal(value.id, i)}\n x={fpx(x - barWidthHalf)}\n y={fpy(value.val)}\n width={fpx(barWidth)}\n height={fpx(value.val)}\n fill={value.color}\n />\n );\n }\n }\n }\n\n return (\n <g>\n {patternDefs.length > 0 && <defs>{patternDefs}</defs>}\n {paths}\n </g>\n );\n }\n);\n\ninterface SvgBarsHoverProps {\n onHover(ind: number): void;\n onLeave(ind: number): void;\n}\n\nexport const SvgBarsHover: FC<SvgBarsHoverProps> = observer(({ onHover, onLeave }) => {\n const [store] = useDependencies(SvgStore);\n const { fpx, fpy, barWidth, length } = store;\n const barWidthHalf = barWidth / 2;\n const paths = [];\n\n for (let i = 0; i < length; i++) {\n const x = store.periodX(i);\n\n paths.push(\n <rect\n key={keyVal('_', i)}\n onMouseEnter={() => onHover(i)}\n onMouseLeave={() => onLeave(i)}\n x={fpx(x - barWidthHalf)}\n y={fpy(100)}\n width={fpx(barWidth)}\n height=\"100%\"\n fill=\"white\"\n fillOpacity=\"0\"\n />\n );\n }\n\n return <g>{paths}</g>;\n});\n"],"names":["observer","useDependencies","keyVal","SvgStore","SvgBars","metrics","isStackedBarChart","isGroupedBarChart","store","fpx","fpy","barWidth","length","barWidthHalf","paths","patternDefs","filter","m","opts","pattern","map","rotation","tileW","tileH","stripeWidth","Math","max","floor","tintOpacity","id","patternUnits","width","height","patternTransform","rect","fill","color","opacity","i","x","periodX","values","valuesOpts","val","periodY","strokeColor","outlineColor","value","spacingBetweenSegments","totalSpacing","stackedBarHeight","reduce","sum","curr","totalValue","yTop","scaleX","scaleY","push","g","transform","pointerEvents","text","y","textAnchor","dominantBaseline","fontSize","fontWeight","stroke","strokeWidth","paintOrder","fontFamily","round","j","TOP_RADIUS","xLeft","r","d","join","path","vectorEffect","strokeLinejoin","groupedBarX","sort","a","b","defs","SvgBarsHover","onHover","onLeave","onMouseEnter","onMouseLeave","fillOpacity"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/components/charts/line-chart/components/svg-bars.tsx"],"sourcesContent":["import { FC } from 'react';\nimport { observer } from 'mobx-react';\nimport { useDependencies } from '@servicetitan/react-ioc';\nimport { ChartMetric } from '../utils/internal-interfaces';\nimport { keyVal } from '../utils/key';\nimport { SvgStore } from '../stores/svg.store';\n\ninterface SvgBarsProps {\n metrics: ChartMetric[];\n isStackedBarChart?: boolean;\n isGroupedBarChart?: boolean;\n}\n\nexport const SvgBars: FC<SvgBarsProps> = observer(\n ({ metrics, isStackedBarChart, isGroupedBarChart }) => {\n const [store] = useDependencies(SvgStore);\n const { fpx, fpy, barWidth, length } = store;\n const barWidthHalf = barWidth / 2;\n const paths = [];\n\n const patternDefs = metrics\n .filter(m => m.opts?.pattern === 'striped')\n .map(m => {\n const rotation = 20;\n const tileW = 0.6;\n const tileH = 0.6;\n const stripeWidth = Math.max(0.1, Math.floor(tileW / 20));\n const tintOpacity = 0.06;\n\n return (\n <pattern\n key={`pattern-${m.id}`}\n id={`stripe-pattern-${m.id}`}\n patternUnits=\"userSpaceOnUse\"\n width={tileW}\n height={tileH}\n patternTransform={`rotate(${rotation})`}\n >\n <rect width={tileW} height={tileH} fill={m.color} opacity={tintOpacity} />\n <rect width={stripeWidth} height={tileH} fill={m.color} />\n </pattern>\n );\n });\n\n for (let i = 0; i < length; i++) {\n const x = store.periodX(i);\n const values = metrics.map(m => ({\n id: m.id,\n color: m.valuesOpts?.[i]?.color ?? m.color,\n opacity: m.opacity,\n val: store.periodY(m, i),\n pattern: m.opts?.pattern,\n strokeColor: m.opts?.strokeColor,\n outlineColor: m.opts?.outlineColor,\n value: m.values[i],\n }));\n\n if (isStackedBarChart) {\n const spacingBetweenSegments = 1; // Approximately 4px in SVG coordinates\n const totalSpacing = (values.length - 1) * spacingBetweenSegments;\n let stackedBarHeight =\n values.reduce((sum, curr) => sum + curr.val, 0) + totalSpacing;\n\n const totalValue = values.reduce((sum, curr) => sum + curr.value, 0);\n if (totalValue > 0) {\n const yTop = +fpy(stackedBarHeight);\n const scaleX = 0.3;\n const scaleY = 1;\n\n paths.push(\n <g\n key={`total-${i}`}\n transform={`translate(${x},${yTop}) scale(${scaleX},${scaleY})`}\n pointerEvents=\"none\"\n >\n <text\n x={0}\n y={0}\n textAnchor=\"middle\"\n dominantBaseline=\"alphabetic\"\n fontSize=\"2.5\"\n fontWeight={600}\n fill=\"#111827\"\n stroke=\"white\"\n strokeWidth={0.8}\n paintOrder=\"stroke\"\n fontFamily=\"Nunito Sans\"\n >\n {Math.round(totalValue)}\n </text>\n </g>\n );\n }\n\n for (let j = 0; j < values.length; j++) {\n const value = values[j];\n stackedBarHeight -= spacingBetweenSegments;\n\n const TOP_RADIUS = 1;\n const xLeft = +fpx(x - barWidth / 2);\n const yTop = +fpy(stackedBarHeight) + (values.length - 2);\n const height = j === values.length - 1 ? +fpx(value.val - 2) : +fpx(value.val);\n const width = +fpx(barWidth);\n\n const r = j === 0 ? TOP_RADIUS : 0; // radius must be numeric\n\n const d = [\n `M ${xLeft} ${yTop + height}`, // bottom-left\n `L ${xLeft} ${yTop + r}`, // up left edge\n `Q ${xLeft} ${yTop} ${xLeft + r / 2} ${yTop}`, // top-left corner\n `L ${xLeft + width - r / 2} ${yTop}`, // across top\n `Q ${xLeft + width} ${yTop} ${xLeft + width} ${yTop + r}`, // top-right corner\n `L ${xLeft + width} ${yTop + height}`, // down right edge\n 'Z',\n ].join(' ');\n paths.push(\n <path\n key={keyVal(value.id, i)}\n d={d}\n fill={\n value.pattern === 'striped'\n ? `url(#stripe-pattern-${value.id})`\n : value.color\n }\n stroke={\n value.pattern === 'outline'\n ? value.outlineColor\n : (value.strokeColor ?? value.color)\n }\n strokeWidth={1}\n vectorEffect=\"non-scaling-stroke\"\n strokeLinejoin=\"round\"\n />\n );\n\n stackedBarHeight -= value.val;\n }\n } else if (isGroupedBarChart) {\n for (let j = 0; j < values.length; j++) {\n const groupedBarX = (j * barWidth) / values.length;\n const value = values[j];\n\n paths.push(\n <rect\n key={keyVal(value.id, i)}\n x={x + groupedBarX - barWidthHalf}\n y={fpy(value.val)}\n width={barWidth / values.length - 0.1}\n height={fpx(value.val)}\n fill={value.color}\n opacity={value.opacity}\n />\n );\n }\n } else {\n values.sort((a, b) => b.val - a.val);\n for (const value of values) {\n paths.push(\n <rect\n key={keyVal(value.id, i)}\n x={fpx(x - barWidthHalf)}\n y={fpy(value.val)}\n width={fpx(barWidth)}\n height={fpx(value.val)}\n fill={value.color}\n />\n );\n }\n }\n }\n\n return (\n <g>\n {patternDefs.length > 0 && <defs>{patternDefs}</defs>}\n {paths}\n </g>\n );\n }\n);\n\ninterface SvgBarsHoverProps {\n onHover(ind: number): void;\n onLeave(ind: number): void;\n}\n\nexport const SvgBarsHover: FC<SvgBarsHoverProps> = observer(({ onHover, onLeave }) => {\n const [store] = useDependencies(SvgStore);\n const { fpx, fpy, barWidth, length } = store;\n const barWidthHalf = barWidth / 2;\n const paths = [];\n\n for (let i = 0; i < length; i++) {\n const x = store.periodX(i);\n\n paths.push(\n <rect\n key={keyVal('_', i)}\n onMouseEnter={() => onHover(i)}\n onMouseLeave={() => onLeave(i)}\n x={fpx(x - barWidthHalf)}\n y={fpy(100)}\n width={fpx(barWidth)}\n height=\"100%\"\n fill=\"white\"\n fillOpacity=\"0\"\n />\n );\n }\n\n return <g>{paths}</g>;\n});\n"],"names":["observer","useDependencies","keyVal","SvgStore","SvgBars","metrics","isStackedBarChart","isGroupedBarChart","store","fpx","fpy","barWidth","length","barWidthHalf","paths","patternDefs","filter","m","opts","pattern","map","rotation","tileW","tileH","stripeWidth","Math","max","floor","tintOpacity","id","patternUnits","width","height","patternTransform","rect","fill","color","opacity","i","x","periodX","values","valuesOpts","val","periodY","strokeColor","outlineColor","value","spacingBetweenSegments","totalSpacing","stackedBarHeight","reduce","sum","curr","totalValue","yTop","scaleX","scaleY","push","g","transform","pointerEvents","text","y","textAnchor","dominantBaseline","fontSize","fontWeight","stroke","strokeWidth","paintOrder","fontFamily","round","j","TOP_RADIUS","xLeft","r","d","join","path","vectorEffect","strokeLinejoin","groupedBarX","sort","a","b","defs","SvgBarsHover","onHover","onLeave","onMouseEnter","onMouseLeave","fillOpacity"],"mappings":"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"}
@@ -37,6 +37,7 @@ const PieTitles = ({ title, pieces })=>{
37
37
  }) : /*#__PURE__*/ _jsx(Flex, {
38
38
  direction: "row",
39
39
  gap: 8,
40
+ className: Styles.titleWrapperColorTags,
40
41
  children: pieces.map((piece)=>/*#__PURE__*/ _jsx(ColorTag, {
41
42
  label: piece.title,
42
43
  color: piece.color
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/components/charts/pie-chart/components/pie-chart.tsx"],"sourcesContent":["import { useMemo, FC } from 'react';\nimport { BodyText, Stack, StatusLight } from '@servicetitan/design-system';\nimport { PieChartProps, PiePiece } from '../utils/interface';\nimport { convertSessionsToPieces, radiusRelativeDefault } from '../utils/const';\nimport { Pie } from './pie';\nimport { Flex } from '@servicetitan/anvil2';\nimport classNames from 'classnames';\nimport * as Styles from './pie-chart.module.less';\nimport { ColorTag } from '../../common';\n\nconst PieTitles: FC<{ title: string; pieces: PiePiece[] }> = ({ title, pieces }) => {\n return pieces.length > 2 ? (\n <div className={classNames(Styles.titleWrapper, 'of-y-auto p-t-2')}>\n <div>\n {!!pieces.length && (\n <Stack.Item className=\"p-l-1 p-b-1\">\n <BodyText bold>{title}</BodyText>\n </Stack.Item>\n )}\n {pieces.map(piece => (\n <Stack key={piece.title} alignItems=\"center\">\n <StatusLight color={piece.color} />\n <BodyText className=\"c-neutral-90\" size=\"medium\">\n {piece.title}\n </BodyText>\n </Stack>\n ))}\n </div>\n </div>\n ) : (\n <Flex direction=\"row\" gap={8}>\n {pieces.map(piece => (\n <ColorTag key={piece.title} label={piece.title} color={piece.color} />\n ))}\n </Flex>\n );\n};\n\nexport const PieChart: FC<PieChartProps> = ({\n height,\n width,\n title,\n sections,\n popoverContent,\n content,\n radiusRelative = radiusRelativeDefault,\n popoverDirection = 'rb',\n hideTitles = false,\n}) => {\n const pieces = useMemo(\n () => convertSessionsToPieces(sections, radiusRelative),\n [sections, radiusRelative]\n );\n const style = useMemo(() => ({ height, width }), [height, width]);\n\n return (\n <Stack direction={pieces.length > 2 ? 'row' : 'column'}>\n <div style={style}>\n <Pie\n title={title}\n pieces={pieces}\n content={content}\n popoverContent={popoverContent}\n popoverDirection={popoverDirection}\n radiusRelative={radiusRelative}\n hideTitles={hideTitles}\n />\n </div>\n {!hideTitles && <PieTitles title={title} pieces={pieces} />}\n </Stack>\n );\n};\n"],"names":["useMemo","BodyText","Stack","StatusLight","convertSessionsToPieces","radiusRelativeDefault","Pie","Flex","classNames","Styles","ColorTag","PieTitles","title","pieces","length","div","className","titleWrapper","Item","bold","map","piece","alignItems","color","size","direction","gap","label","PieChart","height","width","sections","popoverContent","content","radiusRelative","popoverDirection","hideTitles","style"],"mappings":";AAAA,SAASA,OAAO,QAAY,QAAQ;AACpC,SAASC,QAAQ,EAAEC,KAAK,EAAEC,WAAW,QAAQ,8BAA8B;AAE3E,SAASC,uBAAuB,EAAEC,qBAAqB,QAAQ,iBAAiB;AAChF,SAASC,GAAG,QAAQ,QAAQ;AAC5B,SAASC,IAAI,QAAQ,uBAAuB;AAC5C,OAAOC,gBAAgB,aAAa;AACpC,YAAYC,YAAY,0BAA0B;AAClD,SAASC,QAAQ,QAAQ,eAAe;AAExC,MAAMC,YAAuD,CAAC,EAAEC,KAAK,EAAEC,MAAM,EAAE;IAC3E,OAAOA,OAAOC,MAAM,GAAG,kBACnB,KAACC;QAAIC,WAAWR,WAAWC,OAAOQ,YAAY,EAAE;kBAC5C,cAAA,MAACF;;gBACI,CAAC,CAACF,OAAOC,MAAM,kBACZ,KAACZ,MAAMgB,IAAI;oBAACF,WAAU;8BAClB,cAAA,KAACf;wBAASkB,IAAI;kCAAEP;;;gBAGvBC,OAAOO,GAAG,CAACC,CAAAA,sBACR,MAACnB;wBAAwBoB,YAAW;;0CAChC,KAACnB;gCAAYoB,OAAOF,MAAME,KAAK;;0CAC/B,KAACtB;gCAASe,WAAU;gCAAeQ,MAAK;0CACnCH,MAAMT,KAAK;;;uBAHRS,MAAMT,KAAK;;;uBAUnC,KAACL;QAAKkB,WAAU;QAAMC,KAAK;kBACtBb,OAAOO,GAAG,CAACC,CAAAA,sBACR,KAACX;gBAA2BiB,OAAON,MAAMT,KAAK;gBAAEW,OAAOF,MAAME,KAAK;eAAnDF,MAAMT,KAAK;;AAI1C;AAEA,OAAO,MAAMgB,WAA8B,CAAC,EACxCC,MAAM,EACNC,KAAK,EACLlB,KAAK,EACLmB,QAAQ,EACRC,cAAc,EACdC,OAAO,EACPC,iBAAiB7B,qBAAqB,EACtC8B,mBAAmB,IAAI,EACvBC,aAAa,KAAK,EACrB;IACG,MAAMvB,SAASb,QACX,IAAMI,wBAAwB2B,UAAUG,iBACxC;QAACH;QAAUG;KAAe;IAE9B,MAAMG,QAAQrC,QAAQ,IAAO,CAAA;YAAE6B;YAAQC;QAAM,CAAA,GAAI;QAACD;QAAQC;KAAM;IAEhE,qBACI,MAAC5B;QAAMuB,WAAWZ,OAAOC,MAAM,GAAG,IAAI,QAAQ;;0BAC1C,KAACC;gBAAIsB,OAAOA;0BACR,cAAA,KAAC/B;oBACGM,OAAOA;oBACPC,QAAQA;oBACRoB,SAASA;oBACTD,gBAAgBA;oBAChBG,kBAAkBA;oBAClBD,gBAAgBA;oBAChBE,YAAYA;;;YAGnB,CAACA,4BAAc,KAACzB;gBAAUC,OAAOA;gBAAOC,QAAQA;;;;AAG7D,EAAE"}
1
+ {"version":3,"sources":["../../../../../src/components/charts/pie-chart/components/pie-chart.tsx"],"sourcesContent":["import { useMemo, FC } from 'react';\nimport { BodyText, Stack, StatusLight } from '@servicetitan/design-system';\nimport { PieChartProps, PiePiece } from '../utils/interface';\nimport { convertSessionsToPieces, radiusRelativeDefault } from '../utils/const';\nimport { Pie } from './pie';\nimport { Flex } from '@servicetitan/anvil2';\nimport classNames from 'classnames';\nimport * as Styles from './pie-chart.module.less';\nimport { ColorTag } from '../../common';\n\nconst PieTitles: FC<{ title: string; pieces: PiePiece[] }> = ({ title, pieces }) => {\n return pieces.length > 2 ? (\n <div className={classNames(Styles.titleWrapper, 'of-y-auto p-t-2')}>\n <div>\n {!!pieces.length && (\n <Stack.Item className=\"p-l-1 p-b-1\">\n <BodyText bold>{title}</BodyText>\n </Stack.Item>\n )}\n {pieces.map(piece => (\n <Stack key={piece.title} alignItems=\"center\">\n <StatusLight color={piece.color} />\n <BodyText className=\"c-neutral-90\" size=\"medium\">\n {piece.title}\n </BodyText>\n </Stack>\n ))}\n </div>\n </div>\n ) : (\n <Flex direction=\"row\" gap={8} className={Styles.titleWrapperColorTags}>\n {pieces.map(piece => (\n <ColorTag key={piece.title} label={piece.title} color={piece.color} />\n ))}\n </Flex>\n );\n};\n\nexport const PieChart: FC<PieChartProps> = ({\n height,\n width,\n title,\n sections,\n popoverContent,\n content,\n radiusRelative = radiusRelativeDefault,\n popoverDirection = 'rb',\n hideTitles = false,\n}) => {\n const pieces = useMemo(\n () => convertSessionsToPieces(sections, radiusRelative),\n [sections, radiusRelative]\n );\n const style = useMemo(() => ({ height, width }), [height, width]);\n\n return (\n <Stack direction={pieces.length > 2 ? 'row' : 'column'}>\n <div style={style}>\n <Pie\n title={title}\n pieces={pieces}\n content={content}\n popoverContent={popoverContent}\n popoverDirection={popoverDirection}\n radiusRelative={radiusRelative}\n hideTitles={hideTitles}\n />\n </div>\n {!hideTitles && <PieTitles title={title} pieces={pieces} />}\n </Stack>\n );\n};\n"],"names":["useMemo","BodyText","Stack","StatusLight","convertSessionsToPieces","radiusRelativeDefault","Pie","Flex","classNames","Styles","ColorTag","PieTitles","title","pieces","length","div","className","titleWrapper","Item","bold","map","piece","alignItems","color","size","direction","gap","titleWrapperColorTags","label","PieChart","height","width","sections","popoverContent","content","radiusRelative","popoverDirection","hideTitles","style"],"mappings":";AAAA,SAASA,OAAO,QAAY,QAAQ;AACpC,SAASC,QAAQ,EAAEC,KAAK,EAAEC,WAAW,QAAQ,8BAA8B;AAE3E,SAASC,uBAAuB,EAAEC,qBAAqB,QAAQ,iBAAiB;AAChF,SAASC,GAAG,QAAQ,QAAQ;AAC5B,SAASC,IAAI,QAAQ,uBAAuB;AAC5C,OAAOC,gBAAgB,aAAa;AACpC,YAAYC,YAAY,0BAA0B;AAClD,SAASC,QAAQ,QAAQ,eAAe;AAExC,MAAMC,YAAuD,CAAC,EAAEC,KAAK,EAAEC,MAAM,EAAE;IAC3E,OAAOA,OAAOC,MAAM,GAAG,kBACnB,KAACC;QAAIC,WAAWR,WAAWC,OAAOQ,YAAY,EAAE;kBAC5C,cAAA,MAACF;;gBACI,CAAC,CAACF,OAAOC,MAAM,kBACZ,KAACZ,MAAMgB,IAAI;oBAACF,WAAU;8BAClB,cAAA,KAACf;wBAASkB,IAAI;kCAAEP;;;gBAGvBC,OAAOO,GAAG,CAACC,CAAAA,sBACR,MAACnB;wBAAwBoB,YAAW;;0CAChC,KAACnB;gCAAYoB,OAAOF,MAAME,KAAK;;0CAC/B,KAACtB;gCAASe,WAAU;gCAAeQ,MAAK;0CACnCH,MAAMT,KAAK;;;uBAHRS,MAAMT,KAAK;;;uBAUnC,KAACL;QAAKkB,WAAU;QAAMC,KAAK;QAAGV,WAAWP,OAAOkB,qBAAqB;kBAChEd,OAAOO,GAAG,CAACC,CAAAA,sBACR,KAACX;gBAA2BkB,OAAOP,MAAMT,KAAK;gBAAEW,OAAOF,MAAME,KAAK;eAAnDF,MAAMT,KAAK;;AAI1C;AAEA,OAAO,MAAMiB,WAA8B,CAAC,EACxCC,MAAM,EACNC,KAAK,EACLnB,KAAK,EACLoB,QAAQ,EACRC,cAAc,EACdC,OAAO,EACPC,iBAAiB9B,qBAAqB,EACtC+B,mBAAmB,IAAI,EACvBC,aAAa,KAAK,EACrB;IACG,MAAMxB,SAASb,QACX,IAAMI,wBAAwB4B,UAAUG,iBACxC;QAACH;QAAUG;KAAe;IAE9B,MAAMG,QAAQtC,QAAQ,IAAO,CAAA;YAAE8B;YAAQC;QAAM,CAAA,GAAI;QAACD;QAAQC;KAAM;IAEhE,qBACI,MAAC7B;QAAMuB,WAAWZ,OAAOC,MAAM,GAAG,IAAI,QAAQ;;0BAC1C,KAACC;gBAAIuB,OAAOA;0BACR,cAAA,KAAChC;oBACGM,OAAOA;oBACPC,QAAQA;oBACRqB,SAASA;oBACTD,gBAAgBA;oBAChBG,kBAAkBA;oBAClBD,gBAAgBA;oBAChBE,YAAYA;;;YAGnB,CAACA,4BAAc,KAAC1B;gBAAUC,OAAOA;gBAAOC,QAAQA;;;;AAG7D,EAAE"}
@@ -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
+ }
@@ -1,4 +1,6 @@
1
1
  export const __esModule: true;
2
2
  export const percentTextWrapper: string;
3
+ export const popover: string;
3
4
  export const titleWrapper: string;
5
+ export const titleWrapperColorTags: string;
4
6
 
@@ -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;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"}
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;AAqK5F,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,CA4HA,CAAC"}
@@ -4,6 +4,7 @@ import { tokens } from '@servicetitan/tokens/core';
4
4
  import { BodyText, Popover, Stack } from '@servicetitan/design-system';
5
5
  import { useClientRect } from '../../../../utils/use-client-rect';
6
6
  import { ColorTag } from '../../common';
7
+ import * as Styles from './pie-chart.module.less';
7
8
  const chartPadding = 8;
8
9
  const px = (value)=>`${value !== null && value !== void 0 ? value : 0}px`;
9
10
  const GAP_PX = 4;
@@ -219,6 +220,7 @@ export const Pie = ({ pieces, popoverContent: PopoverContent, content: PieConten
219
220
  direction: popoverDirection,
220
221
  padding: "s",
221
222
  width: "auto",
223
+ className: Styles.popover,
222
224
  children: selectedIndex === ind && /*#__PURE__*/ _jsxs(Stack, {
223
225
  direction: "column",
224
226
  "data-cy": `customer-lead-rate-section-${ts.key}-popover`,
@@ -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 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":";AAAA,SAASA,WAAW,EAAEC,OAAO,EAAEC,QAAQ,EAAMC,QAAQ,QAAQ,QAAQ;AACrE,SAASC,MAAM,QAAQ,4BAA4B;AACnD,SAASC,QAAQ,EAAEC,OAAO,EAAEC,KAAK,QAAQ,8BAA8B;AAEvE,SAASC,aAAa,QAAQ,oCAAoC;AAElE,SAASC,QAAQ,QAAQ,eAAe;AAExC,MAAMC,eAAe;AACrB,MAAMC,KAAK,CAACC,QAAmB,GAAGA,kBAAAA,mBAAAA,QAAS,EAAE,EAAE,CAAC;AAChD,MAAMC,SAAS;AAEf,MAAMC,cAGD,CAAC,EAAEC,OAAO,EAAEC,EAAE,EAAEC,KAAK,EAAEC,MAAM,EAAEC,IAAI,EAAEC,IAAI,EAAE,EAAEC,QAAQ,EAAE,GACxDH,UAAUE,qBACN,MAACE;QAAEN,IAAIA;;YACFK,0BACG,KAACD;gBACGG,GAAGH;gBACHI,MAAMpB,OAAOqB,UAAU;gBACvBC,QAAQtB,OAAOuB,YAAY;gBAC3BC,eAAc;gBACdC,aAAY;gBACZC,YAAW;;0BAGnB,KAACV;gBAAKG,GAAGH;gBAAMI,MAAMP;;YACpBC,MAAM,CAAC,EAAE,kBACN,KAACI;gBAAES,WAAW,CAAC,UAAU,EAAEb,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAEA,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;gBAAEc,eAAc;0BACtE,AAAC,CAAA;oBACE,MAAMC,WAAW;oBACjB,MAAMC,SAAS;oBACf,MAAMC,SAASD,SAAS;oBAExB,MAAME,QAAQC,KAAKC,GAAG,CAAC,GAAGnB,KAAKoB,MAAM;oBAErC,qBACI,MAACpC;;0CACG,KAACqC;gCACGC,GAAG,CAACL,QAAQ;gCACZM,GAAG,CAACR,SAAS;gCACbE,OAAOA;gCACPF,QAAQA;gCACRS,IAAIR;gCACJS,IAAIT;gCACJX,MAAK;gCACLK,aAAa;;0CAEjB,KAACV;gCACGsB,GAAE;gCACFC,GAAE;gCACFT,UAAUA;gCACVY,YAAY;gCACZC,YAAW;gCACXC,kBAAiB;gCACjBvB,MAAMpB,OAAO4C,UAAU;0CAEtB7B;;;;gBAIjB,CAAA;;;SAIZ;AAER,MAAM8B,gBAGD,CAAC,EAAElC,KAAK,EAAEmC,OAAO,EAAE;IACpB,MAAMC,eAAenD,YAAY,IAAMkD,QAAQnC,MAAMC,EAAE,EAAE,OAAO;QAACkC;QAASnC,MAAMC,EAAE;KAAC;IACnF,MAAMoC,eAAepD,YAAY,IAAMkD,QAAQnC,MAAMC,EAAE,EAAE,QAAQ;QAACkC;QAASnC,MAAMC,EAAE;KAAC;IAEpF,qBACI,KAACI;QACGG,GAAGR,MAAMK,IAAI;QACbI,MAAK;QACL6B,SAAQ;QACRF,cAAcA;QACdC,cAAcA;;AAG1B;AAEA,MAAME,SAID,CAAC,EAAEC,MAAM,EAAEC,aAAa,EAAEC,cAAc,EAAE;IAC3C,MAAMC,WAAWH,OAAOI,IAAI,CAACC,CAAAA,IAAKA,EAAE1C,MAAM;IAC1C,MAAM2C,SAASH,WAAWrB,KAAKyB,KAAK,CAACJ,SAASxC,MAAM,AAAC,CAAC,EAAE,CAAC,EAAE,EAAEwC,SAASxC,MAAM,AAAC,CAAC,EAAE,CAAC,EAAE,IAAI;IACvF,MAAM6C,SAASL,WAAWrB,KAAKyB,KAAK,CAACJ,SAASxC,MAAM,AAAC,CAAC,EAAE,CAAC,EAAE,EAAEwC,SAASxC,MAAM,AAAC,CAAC,EAAE,CAAC,EAAE,IAAI;IAEvF,MAAM8C,gBAAgBT,OAAOU,MAAM,CAACL,CAAAA,IAAKA,EAAE1C,MAAM,IAAI0C,EAAExC,IAAI;IAC3D,MAAM8C,aAAaF,cAAcG,GAAG,CAACP,CAAAA;QACjC,MAAM,CAACQ,QAAQC,OAAO,GAAGT,EAAE1C,MAAM,AAAC,CAAC,EAAE;QACrC,MAAMoD,MAAMjC,KAAKyB,KAAK,CAACM,QAAQC,WAAW;QAC1C,OAAO;YAAE5B,GAAG2B,SAASE;YAAK5B,GAAG2B,SAASC;QAAI;IAC9C;IAEA,qBACI,MAACC;QACGC,WAAU;QACVC,OAAO;YAAEC,OAAO,GAAGhE,aAAa,EAAE,CAAC;QAAC;QACpCiE,SAAS,CAAC,CAAC,EAAElB,eAAe,EAAE,EAAEA,eAAe,CAAC,EAAEA,iBAAiB,EAAE,CAAC,EAAEA,iBAAiB,GAAG;;YAE3FF,OAAOY,GAAG,CAAC,CAACP,GAAGgB,IACZhB,EAAExC,IAAI,iBAAG,KAACN;oBAAYC,OAAO6C;oBAAcvC,UAAUuD,MAAMpB;mBAAtBI,EAAE5C,EAAE,IAAsC;YAElFgD,cAAczB,MAAM,GAAG,KAAKsB,SAAS,KAAKE,SAAS,mBAChD,MAAC5D;;kCACG,KAAC0E;kCACG,cAAA,MAACC;4BAAK9D,IAAG;;8CACL,KAACwB;oCACGC,GAAG,CAACsB;oCACJrB,GAAG,CAACqB;oCACJ3B,OAAO2B,SAAS;oCAChB7B,QAAQ6B,SAAS;oCACjBvC,MAAK;;8CAET,KAACuD;oCAAOC,IAAG;oCAAIC,IAAG;oCAAIC,GAAGnB;oCAAQvC,MAAK;;8CACtC,KAACuD;oCAAOC,IAAG;oCAAIC,IAAG;oCAAIC,GAAGrB;oCAAQrC,MAAK;;;;;kCAG9C,KAACF;wBAAEwD,MAAK;wBAAkB9C,eAAc;kCACnCkC,WAAWC,GAAG,CAACgB,CAAAA,yBACZ,KAACC;gCAEGC,IAAIF,SAAS1C,CAAC,GAAGoB;gCACjByB,IAAIH,SAASzC,CAAC,GAAGmB;gCACjB0B,IAAIJ,SAAS1C,CAAC,GAAGsB;gCACjByB,IAAIL,SAASzC,CAAC,GAAGqB;gCACjBrC,QAAO;gCACPG,aAAahB;gCACb4E,cAAa;gCACbC,eAAc;+BART,CAAC,IAAI,EAAEP,SAAS1C,CAAC,CAAC,CAAC,EAAE0C,SAASzC,CAAC,EAAE;;;;YAczDc,iBAAiB,KAAKA,gBAAgBD,OAAOhB,MAAM,kBAChD,KAACoD;gBAAIC,WAAW,CAAC,CAAC,EAAErC,MAAM,CAACC,cAAc,CAACxC,EAAE,EAAE;;;;AAI9D;AAEA,MAAM6E,cAID,CAAC,EAAEtC,MAAM,EAAEL,OAAO,EAAEO,cAAc,EAAE,iBACrC,KAACc;QACGC,WAAU;QACVC,OAAO;YAAEC,OAAO/D,GAAGD;QAAc;QACjCiE,SACI,CAAC,CAAC,EAAElB,eAAe,EAAE,EAAEA,eAAe,CAAC,CAAC,GAAG,GAAGA,iBAAiB,EAAE,CAAC,EAAEA,iBAAiB,GAAG;kBAG3FF,OAAOY,GAAG,CAACP,CAAAA,IACRA,EAAExC,IAAI,iBAAG,KAAC6B;gBAAclC,OAAO6C;gBAAcV,SAASA;eAAfU,EAAE5C,EAAE,IAAyB;;AAKhF,OAAO,MAAM8E,MAQR,CAAC,EACFvC,MAAM,EACNwC,gBAAgBC,cAAc,EAC9BC,SAASC,UAAU,EACnBzC,cAAc,EACd0C,UAAU,EACVC,gBAAgB,EACnB;IACG,MAAM,CAAC5C,eAAe6C,iBAAiB,GAAGnG,SAAS,CAAC;IACpD,MAAM,CAACsC,MAAM8D,IAAI,GAAG9F;IAEpB,MAAM0C,UAAUlD,YACZ,CAACgB,IAAYuF;QACTF,iBAAiBE,UAAUhD,OAAOiD,SAAS,CAAC5C,CAAAA,IAAKA,EAAE5C,EAAE,KAAKA,MAAM,CAAC;IACrE,GACA;QAACuC;QAAQ8C;KAAiB;IAG9B,MAAMI,YAAYxG,QAAQ;YACPuC;QAAf,MAAMN,SAASM,CAAAA,eAAAA,iBAAAA,2BAAAA,KAAMN,MAAM,cAAZM,0BAAAA,eAAgB;QAE/B,OAAO;YACHN;YACAwE,UAAUxE,SAASA,SAASxB,eAAe,IAAI;YAC/CiG,QAAQzE,SACF;gBACIE,OAAOzB,GAAG0B,KAAKC,GAAG,CAAC,KAAKJ;YAC5B,IACA,CAAC;QACX;IACJ,GAAG;QAACM;KAAK;IAET,MAAMoE,iBAAiB3G,QACnB,IACIwG,UAAUvE,MAAM,GACVqB,OAAOY,GAAG,CAACP,CAAAA,IACPA,EAAE1C,MAAM,GACF;gBACI2F,KAAKjD,EAAEiD,GAAG;gBACVC,KAAKnG,GACD,AAAC8F,UAAUvE,MAAM,GAAIuB,CAAAA,iBAAiBG,EAAE1C,MAAM,CAAC,EAAE,CAAC,EAAE,AAAD,IAC9CuC,CAAAA,iBAAiB,CAAA;gBAE1BsD,MAAMpG,GACF,AAAC8F,UAAUvE,MAAM,GAAIuB,CAAAA,iBAAiBG,EAAE1C,MAAM,CAAC,EAAE,CAAC,EAAE,AAAD,IAC9CuC,CAAAA,iBAAiB,CAAA,IAClB;YAEZ,IACA;gBAAEqD,KAAK;gBAAIC,MAAM;YAAG,KAE9B,EAAE,EACZ;QAACxD;QAAQkD;QAAWhD;KAAe;IAGvC,qBACI,KAACuD;QAAIV,KAAKA;QAAK7B,OAAOgC,UAAUE,MAAM;QAAEnC,WAAU;kBAC7CjB,OAAO0D,KAAK,CAACrD,CAAAA,IAAK,CAACA,EAAExC,IAAI,kBACtB,KAACb;YAAMiE,WAAU;YAAQ0C,gBAAe;YAASC,YAAW;sBAAS;2BAIrE,MAAChH;;gBACIyG,eACI3C,MAAM,CAACmD,CAAAA,KAAM,CAAC,CAACA,GAAGL,IAAI,IAAI,CAAC,CAACK,GAAGN,GAAG,EAClC3C,GAAG,CAAC,CAACiD,IAAIC;wBA+BgC9D,aACAA,cACCA;yCAhCvC,KAACyD;wBAA2BvC,OAAO2C;wBAAI5C,WAAU;kCAC5C,AAAC,CAAA,CAAC,CAACwB,kBAAkB,CAACG,UAAS,mBAC5B,KAAC7F;4BACGgH,MAAM;4BACNC,uBAAS,KAACC;0CAAK;;4BACfC,MAAMjE,kBAAkB6D;4BACxBK,WAAWtB;4BACXuB,SAAQ;4BACRvF,OAAM;sCAELoB,kBAAkB6D,qBACf,MAAC9G;gCACGmH,WAAU;gCACVE,WAAS,CAAC,2BAA2B,EAAER,GAAGP,GAAG,CAAC,QAAQ,CAAC;;oCAEtD,CAACV,4BACE,MAAC5F;wCAAM4G,YAAW;;0DACd,KAAC1G;gDACGoH,OAAM;gDACN5G,OAAOsC,MAAM,CAAC8D,IAAI,CAACpG,KAAK;;0DAE5B,KAACZ;gDAASyH,MAAK;gDAAQC,IAAI;0DACtBxE,MAAM,CAAC8D,IAAI,CAACW,KAAK;;;;oCAI7B,CAAC,CAAChC,gCACC,KAACzF,MAAM0H,IAAI;wCAACzD,WAAU;kDAClB,cAAA,KAACwB;4CACGkC,OAAOb;4CACPc,IAAI,GAAE5E,cAAAA,MAAM,CAAC8D,IAAI,cAAX9D,kCAAAA,YAAa4E,IAAI;4CACvBhH,IAAI,GAAEoC,eAAAA,MAAM,CAAC8D,IAAI,cAAX9D,mCAAAA,aAAapC,IAAI;4CACvBP,KAAK,GAAE2C,eAAAA,MAAM,CAAC8D,IAAI,cAAX9D,mCAAAA,aAAa3C,KAAK;;;;;;uBAhC/CwG,GAAGL,IAAI,GAAGK,GAAGN,GAAG;;gBA0CjC,CAAC,CAACZ,4BAAc,KAACA;8BAClB,KAAC5C;oBACGC,QAAQA;oBACRC,eAAeA;oBACfC,gBAAgBA;;8BAEpB,KAACoC;oBACGtC,QAAQA;oBACRL,SAASA;oBACTO,gBAAgBA;;;;;AAMxC,EAAE"}
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';\nimport * as Styles from './pie-chart.module.less';\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 className={Styles.popover}\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","Styles","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","popover","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,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"}
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,CAyEtC,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,8 +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: neutral ? 'neutral-200' : inverted ? isIncrease ? 'red' : 'green' : isIncrease ? 'green' : 'red',
40
- className: "m-r-half m-t-half"
39
+ color: neutral ? 'neutral-200' : inverted ? isIncrease ? 'red' : 'green' : isIncrease ? 'green' : 'red'
41
40
  });
42
41
  let text = '';
43
42
  if (percents) {
@@ -59,6 +58,7 @@ export const StatDiff = ({ value, prev, size, format, inverted, neutral, classNa
59
58
  alignItems: "center",
60
59
  children: [
61
60
  /*#__PURE__*/ _jsx(Stack.Item, {
61
+ className: "m-r-half m-t-half",
62
62
  children: /*#__PURE__*/ _jsx("span", {
63
63
  children: diff
64
64
  })
@@ -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={\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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"}
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 />\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 className=\"m-r-half m-t-half\">\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.1",
3
+ "version": "6.1.0",
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": "231fbedc1ec501f5e88216dab08c1cd20192579d"
56
+ "gitHead": "b2f96c9cebfe80c20a790d4a9490d2642224bc64"
57
57
  }
@@ -29,7 +29,6 @@ export const FunnelChart: FC<FunnelChartProps> = ({
29
29
  const rightStyles = useMemo(
30
30
  () => ({
31
31
  left: `${100 - topSideLength}%`,
32
- width: `${topSideLength}%`,
33
32
  }),
34
33
  [topSideLength]
35
34
  );
@@ -35,8 +35,8 @@ export const FunnelPyramidSvg: FC<FunnelPyramidSvgProps> = ({
35
35
  yt: yStep * ind,
36
36
  yb: ind === len - 1 ? 100 : yStep * (ind + 1),
37
37
  xtl: xOffset + lStep * ind,
38
- xtr: 100 - lStep * ind,
39
- xbr: 100 - lStep * (ind + 1),
38
+ xtr: 99 - lStep * ind,
39
+ xbr: 99 - lStep * (ind + 1),
40
40
  xbl: xOffset + lStep * (ind + 1),
41
41
  c: color,
42
42
  };
@@ -102,7 +102,7 @@ export const FunnelPyramidSvg: FC<FunnelPyramidSvgProps> = ({
102
102
  section.xtr,
103
103
  section.xbr,
104
104
  section.xbl,
105
- section.yt,
105
+ section.yt + 1,
106
106
  section.yb,
107
107
  isTop,
108
108
  isBottom,
@@ -102,7 +102,7 @@ export const Body: FC<{ classNameTitle?: string }> = provide({ singletons: [SvgS
102
102
  />
103
103
  )}
104
104
  {display.metricsTitlePosition === 'bottom' && (
105
- <Stack direction="row" justifyContent="center" className="p-3">
105
+ <Stack direction="row" justifyContent="flex-start" className="p-t-3 p-x-5">
106
106
  <MetricsTitle metrics={metrics} />
107
107
  </Stack>
108
108
  )}
@@ -16,7 +16,32 @@
16
16
  .popover {
17
17
  position: absolute;
18
18
  width: 200px;
19
- top: 20%;
19
+ transform: rotate(45deg);
20
+ top: 12px;
21
+ z-index: 1000;
22
+ background-color: @color-neutral-30;
23
+ border: 1px solid @color-neutral-60;
24
+ }
25
+
26
+ .arrow {
27
+ position: absolute;
28
+ width: 8px;
29
+ height: 8px;
30
+ background-color: @color-neutral-30;
31
+ border-left: 1px solid @color-neutral-60;
32
+ border-top: 1px solid @color-neutral-60;
33
+ top: 50%;
34
+ z-index: 1;
35
+ }
36
+
37
+ .arrow-left {
38
+ left: -6px;
39
+ transform: rotate(-45deg);
40
+ }
41
+
42
+ .arrow-right {
43
+ right: -6px;
44
+ transform: rotate(135deg);
20
45
  }
21
46
 
22
47
  .color-tag {
@@ -1,4 +1,7 @@
1
1
  export const __esModule: true;
2
+ export const arrow: string;
3
+ export const arrowLeft: string;
4
+ export const arrowRight: string;
2
5
  export const colorTag: string;
3
6
  export const colorTagOutlined: string;
4
7
  export const line: string;