@mx-cartographer/experiences 9.4.4 → 9.4.6

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 (31) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/insights-v2/blocks/ChartBlocks/BarchartBlock/layout.es.js +1 -1
  3. package/dist/insights-v2/blocks/ChartBlocks/BarchartBlock/layout.es.js.map +1 -1
  4. package/dist/insights-v2/blocks/ChartBlocks/BarchartBlock/utils.es.js +20 -19
  5. package/dist/insights-v2/blocks/ChartBlocks/BarchartBlock/utils.es.js.map +1 -1
  6. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/DoubleBarChartBlock.d.ts +8 -0
  7. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/DoubleBarChartBlock.es.js +24 -0
  8. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/DoubleBarChartBlock.es.js.map +1 -0
  9. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/comparisonUtils.d.ts +9 -0
  10. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/comparisonUtils.es.js +43 -0
  11. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/comparisonUtils.es.js.map +1 -0
  12. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/index.d.ts +1 -1
  13. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/layout.es.js +1 -1
  14. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/layout.es.js.map +1 -1
  15. package/dist/insights-v2/{blocks/ChartBlocks/DoubleBarChartBlock → components/chartblocks}/ChartLegend.d.ts +1 -1
  16. package/dist/insights-v2/{blocks/ChartBlocks/DoubleBarChartBlock → components/chartblocks}/ChartLegend.es.js +12 -12
  17. package/dist/insights-v2/components/chartblocks/ChartLegend.es.js.map +1 -0
  18. package/dist/insights-v2/{blocks/ChartBlocks/DoubleBarChartBlock → components/chartblocks}/CustomDoubleBar.d.ts +1 -1
  19. package/dist/insights-v2/components/chartblocks/CustomDoubleBar.es.js.map +1 -0
  20. package/dist/insights-v2/components/chartblocks/DoubleBarChart.d.ts +17 -0
  21. package/dist/insights-v2/components/chartblocks/DoubleBarChart.es.js +118 -0
  22. package/dist/insights-v2/components/chartblocks/DoubleBarChart.es.js.map +1 -0
  23. package/dist/insights-v2/index.es.js +1 -1
  24. package/dist/insights-v2/mappings/blocks.es.js +1 -1
  25. package/package.json +8 -1
  26. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/ChartLegend.es.js.map +0 -1
  27. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/CustomDoubleBar.es.js.map +0 -1
  28. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/DoubleBarChart.d.ts +0 -2
  29. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/DoubleBarChart.es.js +0 -125
  30. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/DoubleBarChart.es.js.map +0 -1
  31. /package/dist/insights-v2/{blocks/ChartBlocks/DoubleBarChartBlock → components/chartblocks}/CustomDoubleBar.es.js +0 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ ## [9.4.5] - 08-27-2026
2
+
3
+ - **ADDED** - Transaction History action block (part 1): chart-to-drilldown wiring. `BarchartBlock` and `DoubleBarChartBlock` now invoke `openChartDrilldown` on a bar click, forwarding the clicked column (`chartBarIndex`) and sub-series (`tabIndex`) to the shared insights-v2 action drawer so a tapped bar opens the matching transaction history slice (WEC-1701)
4
+ - **CHANGED** - Decoupled `DoubleBarChart` into a pure, prop-driven presentational component (`bars`/`colors`/`legends`/`onBarClick`); the card block `DoubleBarChartBlock` now owns data shaping (`buildComparisonSeries`) and palette resolution and injects the click behavior, keeping the chart reusable across the card and the drill-down (WEC-1701)
5
+ - **ADDED** - `./insights-v2` package export so consumers can import the module and its blocks directly (WEC-1701)
6
+ - **FIXED** - Date-only strings (e.g. `2026-03-01`) were parsed as UTC midnight and rolled the month label back a month in negative-offset timezones (EST/CST/MST/PST); `comparisonUtils` and `BarchartBlock/utils` now wrap date strings with `parseISO` before formatting, so North-American users see the correct month and `comparisonUtils.test.ts` no longer fails outside UTC/IST (WEC-1701)
7
+ - **FIXED** - Double-bar aria labels read the main and comparison bars identically (same month + amount template); each series now carries its localized name (`localized_label`, falling back to the stable `label` key) through a `_3{}` copy slot so screen-reader users can distinguish the two bars, without synthesizing copy in the client (WEC-1701)
8
+ - **FIXED** - `buildComparisonSeries` now drops rows with an unparseable date and sorts columns via `parseISO`, so malformed wire data can't produce a `NaN` comparator that scrambles column order (and the `chartBarIndex` forwarded to the drill-down) (WEC-1701)
9
+ - **CHANGED** - `ChartLegend` (insights-v2) now uses a data-driven key (`label ?? index`) instead of the array index
10
+ - **NOTE** - First of a multi-part delivery of the Transaction History action block; this part lands the reusable double-bar chart, the drill-down click contract shared by both chart cards, and the `./insights-v2` export that later parts build on
11
+
1
12
  ## [9.4.4] - 08-26-2026
2
13
 
3
14
  - **CHANGED** - Investments widget now disables (not hides) the Allocation and Analysis tabs, with an explanatory tooltip, when the selected accounts have no data to render; the active tab resets to Overview if it becomes disabled
@@ -1,6 +1,6 @@
1
1
  var o = (a) => ({
2
2
  SavingsAccountBalancesSummary: { color: a.palette.success.main },
3
- MonthlySpendComparison: { color: a.palette.chart.chart5 }
3
+ MonthlySpendComparison: { color: a.palette.chart.chart2 }
4
4
  });
5
5
  export {
6
6
  o as getLayoutConfig
@@ -1 +1 @@
1
- {"version":3,"file":"layout.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ChartBlocks/BarchartBlock/layout.ts"],"sourcesContent":["import { type Theme } from '@mui/material/styles'\nexport const getLayoutConfig = (theme: Theme) => {\n return {\n SavingsAccountBalancesSummary: {\n color: theme.palette.success.main,\n },\n MonthlySpendComparison: {\n color: theme.palette.chart.chart5,\n },\n }\n}\n"],"mappings":"AACA,IAAa,IAAA,CAAmB,OACvB;AAAA,EACL,+BAA+B,EAC7B,OAAO,EAAM,QAAQ,QAAQ,KAC/B;AAAA,EACA,wBAAwB,EACtB,OAAO,EAAM,QAAQ,MAAM,OAC7B;AACF"}
1
+ {"version":3,"file":"layout.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ChartBlocks/BarchartBlock/layout.ts"],"sourcesContent":["import { type Theme } from '@mui/material/styles'\nexport const getLayoutConfig = (theme: Theme) => {\n return {\n SavingsAccountBalancesSummary: {\n color: theme.palette.success.main,\n },\n MonthlySpendComparison: {\n color: theme.palette.chart.chart2,\n },\n }\n}\n"],"mappings":"AACA,IAAa,IAAA,CAAmB,OACvB;AAAA,EACL,+BAA+B,EAC7B,OAAO,EAAM,QAAQ,QAAQ,KAC/B;AAAA,EACA,wBAAwB,EACtB,OAAO,EAAM,QAAQ,MAAM,OAC7B;AACF"}
@@ -1,34 +1,35 @@
1
- import { buildDynamicCopy as m } from "../../../../core/utils/Localization.es.js";
1
+ import { buildDynamicCopy as n } from "../../../../core/utils/Localization.es.js";
2
2
  import { DATE_FORMATS_INTL as i, formatDate as u } from "../../../../core/constants/DateFormats.es.js";
3
3
  import { getCategoryColor as C } from "../../../../core/utils/CategoryUtil.es.js";
4
- import { formatCurrency as n } from "../../../../core/utils/NumberFormatting.es.js";
5
- import { getLayoutConfig as A } from "./layout.es.js";
6
- var p = {
4
+ import { formatCurrency as m } from "../../../../core/utils/NumberFormatting.es.js";
5
+ import { getLayoutConfig as p } from "./layout.es.js";
6
+ import { parseISO as A } from "date-fns/parseISO";
7
+ var O = {
7
8
  CATEGORY_COLOR: "CategoryColor",
8
9
  SAVINGS_ACCOUNT_BALANCES_SUMMARY: "SavingsAccountBalancesSummary",
9
10
  MONTHLY_SPEND_COMPARISON: "MonthlySpendComparison"
10
- }, y = (a) => a ? a.data ? a.data.map((t) => {
11
+ }, l = (t) => t ? t.data ? t.data.map((o) => {
11
12
  const r = {};
12
- return a.names?.map((o, e) => {
13
- r[o] = t[e];
13
+ return t.names?.map((a, e) => {
14
+ r[a] = o[e];
14
15
  }), r;
15
- }) : [] : [], S = (a, t) => a.map((r) => {
16
- const o = u(r.date, i.MONTH_SHORT);
16
+ }) : [] : [], y = (t, o) => [...t].sort((r, a) => new Date(r.date).getTime() - new Date(a.date).getTime()).map((r) => {
17
+ const a = u(A(r.date), i.MONTH_SHORT);
17
18
  return {
18
- ariaLabel: m(t, o, n(r.amount, "0.00")),
19
- label: o,
19
+ ariaLabel: n(o, a, m(r.amount, "0.00")),
20
+ label: a,
20
21
  value: r.amount,
21
- formattedAmount: n(r.amount, "0,0")
22
+ formattedAmount: m(r.amount, "0,0")
22
23
  };
23
- }), R = (a, t, r) => {
24
- const { variant: o } = a, e = A(r);
25
- return o === p.CATEGORY_COLOR && t.category_guid ? { color: C(t.category_guid, r) } : { color: e[o]?.color ?? r.palette.primary.main };
24
+ }), s = (t, o, r) => {
25
+ const { variant: a } = t, e = p(r);
26
+ return a === O.CATEGORY_COLOR && o.category_guid ? { color: C(o.category_guid, r) } : { color: e[a]?.color ?? r.palette.primary.main };
26
27
  };
27
28
  export {
28
- p as BAR_CHART_VARIANTS,
29
- R as barChartVariant,
30
- S as buildChartData,
31
- y as buildDataSeries
29
+ O as BAR_CHART_VARIANTS,
30
+ s as barChartVariant,
31
+ y as buildChartData,
32
+ l as buildDataSeries
32
33
  };
33
34
 
34
35
  //# sourceMappingURL=utils.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ChartBlocks/BarchartBlock/utils.ts"],"sourcesContent":["import { type Theme } from '@mui/material/styles'\n\nimport { getCategoryColor } from '../../../../core/utils/CategoryUtil'\nimport { buildDynamicCopy } from '../../../../core/utils/Localization'\nimport { formatCurrency } from '../../../../core/utils/NumberFormatting'\nimport { DATE_FORMATS_INTL, formatDate } from '../../../../core/constants'\nimport type { DataSeries, InstanceSlot } from '../../../../core'\nimport type { InsightsInstanceSlotData } from '../../../../core/types/InsightsInstanceSlotData'\nimport { getLayoutConfig } from './layout'\n\nexport const BAR_CHART_VARIANTS = {\n CATEGORY_COLOR: 'CategoryColor',\n SAVINGS_ACCOUNT_BALANCES_SUMMARY: 'SavingsAccountBalancesSummary',\n MONTHLY_SPEND_COMPARISON: 'MonthlySpendComparison',\n}\n\nexport const buildDataSeries = (data: DataSeries | undefined) => {\n if (!data) {\n return []\n }\n\n if (data.data) {\n return data.data.map((d) => {\n const item: any = {}\n\n data.names?.map((name, index) => {\n item[name] = d[index]\n })\n return item\n })\n } else {\n return []\n }\n}\n\nexport const buildChartData = (dataSeries: any[], ariaLabel: string) => {\n const data = dataSeries.map((total) => {\n const label = formatDate(total.date, DATE_FORMATS_INTL.MONTH_SHORT)\n\n return {\n ariaLabel: buildDynamicCopy(ariaLabel, label, formatCurrency(total.amount, '0.00')) as string,\n label,\n value: total.amount,\n formattedAmount: formatCurrency(total.amount, '0,0'),\n }\n })\n\n return data\n}\n\nexport const barChartVariant = (\n instanceSlot: InstanceSlot,\n instanceSlotData: InsightsInstanceSlotData,\n theme: Theme,\n) => {\n const { variant } = instanceSlot\n const barChartLayout = getLayoutConfig(theme)\n if (variant === BAR_CHART_VARIANTS.CATEGORY_COLOR && instanceSlotData.category_guid) {\n const categoryColor = getCategoryColor(instanceSlotData.category_guid, theme)\n return {\n color: categoryColor,\n }\n }\n return {\n color:\n barChartLayout[variant as keyof typeof barChartLayout]?.color ?? theme.palette.primary.main,\n }\n}\n"],"mappings":";;;;;AAUA,IAAa,IAAqB;AAAA,EAChC,gBAAgB;AAAA,EAChB,kCAAkC;AAAA,EAClC,0BAA0B;AAC5B,GAEa,IAAA,CAAmB,MACzB,IAID,EAAK,OACA,EAAK,KAAK,IAAA,CAAK,MAAM;AAC1B,QAAM,IAAY,CAAC;AAEnB,SAAA,EAAK,OAAO,IAAA,CAAK,GAAM,MAAU;AAC/B,IAAA,EAAK,CAAA,IAAQ,EAAE,CAAA;AAAA,EACjB,CAAC,GACM;AACT,CAAC,IAEM,CAAC,IAbD,CAAC,GAiBC,IAAA,CAAkB,GAAmB,MACnC,EAAW,IAAA,CAAK,MAAU;AACrC,QAAM,IAAQ,EAAW,EAAM,MAAM,EAAkB,WAAW;AAElE,SAAO;AAAA,IACL,WAAW,EAAiB,GAAW,GAAO,EAAe,EAAM,QAAQ,MAAM,CAAC;AAAA,IAClF,OAAA;AAAA,IACA,OAAO,EAAM;AAAA,IACb,iBAAiB,EAAe,EAAM,QAAQ,KAAK;AAAA,EACrD;AACF,CAEO,GAGI,IAAA,CACX,GACA,GACA,MACG;AACH,QAAM,EAAE,SAAA,EAAA,IAAY,GACd,IAAiB,EAAgB,CAAK;AAC5C,SAAI,MAAY,EAAmB,kBAAkB,EAAiB,gBAE7D,EACL,OAFoB,EAAiB,EAAiB,eAAe,CAE9D,EACT,IAEK,EACL,OACE,EAAe,CAAA,GAAyC,SAAS,EAAM,QAAQ,QAAQ,KAC3F;AACF"}
1
+ {"version":3,"file":"utils.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ChartBlocks/BarchartBlock/utils.ts"],"sourcesContent":["import { type Theme } from '@mui/material/styles'\n\nimport { parseISO } from 'date-fns/parseISO'\n\nimport { getCategoryColor } from '../../../../core/utils/CategoryUtil'\nimport { buildDynamicCopy } from '../../../../core/utils/Localization'\nimport { formatCurrency } from '../../../../core/utils/NumberFormatting'\nimport { DATE_FORMATS_INTL, formatDate } from '../../../../core/constants'\nimport type { DataSeries, InstanceSlot } from '../../../../core'\nimport type { InsightsInstanceSlotData } from '../../../../core/types/InsightsInstanceSlotData'\nimport { getLayoutConfig } from './layout'\n\nexport const BAR_CHART_VARIANTS = {\n CATEGORY_COLOR: 'CategoryColor',\n SAVINGS_ACCOUNT_BALANCES_SUMMARY: 'SavingsAccountBalancesSummary',\n MONTHLY_SPEND_COMPARISON: 'MonthlySpendComparison',\n}\n\nexport const buildDataSeries = (data: DataSeries | undefined) => {\n if (!data) {\n return []\n }\n\n if (data.data) {\n return data.data.map((d) => {\n const item: any = {}\n\n data.names?.map((name, index) => {\n item[name] = d[index]\n })\n return item\n })\n } else {\n return []\n }\n}\n\nexport const buildChartData = (dataSeries: any[], ariaLabel: string) => {\n // Bars render oldest→newest (Jan→Dec, left→right, per Figma). The single-bar backend sends\n // data_series newest-first, so normalize date-ascending here — the single source of truth for both\n // the card (BarchartBlock) and the drill-down. This keeps their bar/tab indices aligned, which the\n // card relies on when it forwards a clicked bar index straight to the drill-down (openChartDrilldown).\n const data = [...dataSeries]\n .sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime())\n .map((total) => {\n const label = formatDate(parseISO(total.date), DATE_FORMATS_INTL.MONTH_SHORT)\n\n return {\n ariaLabel: buildDynamicCopy(\n ariaLabel,\n label,\n formatCurrency(total.amount, '0.00'),\n ) as string,\n label,\n value: total.amount,\n formattedAmount: formatCurrency(total.amount, '0,0'),\n }\n })\n\n return data\n}\n\nexport const barChartVariant = (\n instanceSlot: InstanceSlot,\n instanceSlotData: InsightsInstanceSlotData,\n theme: Theme,\n) => {\n const { variant } = instanceSlot\n const barChartLayout = getLayoutConfig(theme)\n if (variant === BAR_CHART_VARIANTS.CATEGORY_COLOR && instanceSlotData.category_guid) {\n const categoryColor = getCategoryColor(instanceSlotData.category_guid, theme)\n return {\n color: categoryColor,\n }\n }\n return {\n color:\n barChartLayout[variant as keyof typeof barChartLayout]?.color ?? theme.palette.primary.main,\n }\n}\n"],"mappings":";;;;;;AAYA,IAAa,IAAqB;AAAA,EAChC,gBAAgB;AAAA,EAChB,kCAAkC;AAAA,EAClC,0BAA0B;AAC5B,GAEa,IAAA,CAAmB,MACzB,IAID,EAAK,OACA,EAAK,KAAK,IAAA,CAAK,MAAM;AAC1B,QAAM,IAAY,CAAC;AAEnB,SAAA,EAAK,OAAO,IAAA,CAAK,GAAM,MAAU;AAC/B,IAAA,EAAK,CAAA,IAAQ,EAAE,CAAA;AAAA,EACjB,CAAC,GACM;AACT,CAAC,IAEM,CAAC,IAbD,CAAC,GAiBC,IAAA,CAAkB,GAAmB,MAKnC,CAAC,GAAG,CAAU,EACxB,KAAA,CAAM,GAAG,MAAM,IAAI,KAAK,EAAE,IAAI,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,EACtE,IAAA,CAAK,MAAU;AACd,QAAM,IAAQ,EAAW,EAAS,EAAM,IAAI,GAAG,EAAkB,WAAW;AAE5E,SAAO;AAAA,IACL,WAAW,EACT,GACA,GACA,EAAe,EAAM,QAAQ,MAAM,CACrC;AAAA,IACA,OAAA;AAAA,IACA,OAAO,EAAM;AAAA,IACb,iBAAiB,EAAe,EAAM,QAAQ,KAAK;AAAA,EACrD;AACF,CAEK,GAGI,IAAA,CACX,GACA,GACA,MACG;AACH,QAAM,EAAE,SAAA,EAAA,IAAY,GACd,IAAiB,EAAgB,CAAK;AAC5C,SAAI,MAAY,EAAmB,kBAAkB,EAAiB,gBAE7D,EACL,OAFoB,EAAiB,EAAiB,eAAe,CAE9D,EACT,IAEK,EACL,OACE,EAAe,CAAA,GAAyC,SAAS,EAAM,QAAQ,QAAQ,KAC3F;AACF"}
@@ -0,0 +1,8 @@
1
+ import { BlockProps } from '../../types';
2
+ /**
3
+ * Card block for the double-bar chart. Mirrors BarchartBlock: it builds the shaped series
4
+ * (buildComparisonSeries) and resolves the card palette (getLayoutConfig), then renders the reusable
5
+ * DoubleBarChart and injects the card click behavior \u2014 open the shared drawer scoped to this beat
6
+ * (chartBarIndex = clicked column, tabIndex = clicked sub-series).
7
+ */
8
+ export declare const DoubleBarChartBlock: ({ payload: { instance_slot, instance_slot_data, widget_type }, beatGuid, }: BlockProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,24 @@
1
+ import { useInsightsV2Store as h } from "../../../../common/context/hooks.es.js";
2
+ import { DoubleBarChart as u } from "../../../components/chartblocks/DoubleBarChart.es.js";
3
+ import { buildComparisonSeries as b } from "./comparisonUtils.es.js";
4
+ import { getLayoutConfig as C } from "./layout.es.js";
5
+ import { jsx as B } from "react/jsx-runtime";
6
+ import { useTheme as g } from "@mui/material/styles";
7
+ var L = ({ payload: { instance_slot: o, instance_slot_data: r, widget_type: t }, beatGuid: a = "" }) => {
8
+ const e = g(), { openChartDrilldown: i } = h(), { variant: n } = o, { ariaLabel: s = "", data_series: m, legends: l } = r, c = b(m, s), p = C(e, n)?.color ?? [];
9
+ return /* @__PURE__ */ B(u, {
10
+ bars: c,
11
+ colors: p,
12
+ isMini: t === "mini",
13
+ legends: l,
14
+ onBarClick: (d, f) => i(a, {
15
+ chartBarIndex: d,
16
+ tabIndex: f
17
+ })
18
+ });
19
+ };
20
+ export {
21
+ L as DoubleBarChartBlock
22
+ };
23
+
24
+ //# sourceMappingURL=DoubleBarChartBlock.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DoubleBarChartBlock.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/DoubleBarChartBlock.tsx"],"sourcesContent":["import { useTheme } from '@mui/material/styles'\n\nimport { useInsightsV2Store } from '../../../../common'\nimport type { DataSeries } from '../../../../core'\nimport { DoubleBarChart } from '../../../components/chartblocks/DoubleBarChart'\n\nimport type { BlockProps } from '../../types'\n\nimport { buildComparisonSeries } from './comparisonUtils'\nimport { getLayoutConfig } from './layout'\n\n/**\n * Card block for the double-bar chart. Mirrors BarchartBlock: it builds the shaped series\n * (buildComparisonSeries) and resolves the card palette (getLayoutConfig), then renders the reusable\n * DoubleBarChart and injects the card click behavior \\u2014 open the shared drawer scoped to this beat\n * (chartBarIndex = clicked column, tabIndex = clicked sub-series).\n */\nexport const DoubleBarChartBlock = ({\n payload: { instance_slot, instance_slot_data, widget_type },\n beatGuid = '',\n}: BlockProps) => {\n const theme = useTheme()\n const { openChartDrilldown } = useInsightsV2Store()\n const { variant } = instance_slot\n const { ariaLabel = '', data_series, legends } = instance_slot_data\n const bars = buildComparisonSeries(data_series as DataSeries, ariaLabel)\n // getLayoutConfig returns undefined for an unknown/unsupported variant; fall back to an empty\n // palette so an unregistered beat can't throw on mount.\n const colors = getLayoutConfig(theme, variant)?.color ?? []\n\n return (\n <DoubleBarChart\n bars={bars}\n colors={colors}\n isMini={widget_type === 'mini'}\n legends={legends}\n onBarClick={(columnIndex, subIndex) =>\n openChartDrilldown(beatGuid, { chartBarIndex: columnIndex, tabIndex: subIndex })\n }\n />\n )\n}\n"],"mappings":";;;;;;AAiBA,IAAa,IAAA,CAAuB,EAClC,SAAS,EAAE,eAAA,GAAe,oBAAA,GAAoB,aAAA,EAAA,GAC9C,UAAA,IAAW,GAAA,MACK;AAChB,QAAM,IAAQ,EAAS,GACjB,EAAE,oBAAA,EAAA,IAAuB,EAAmB,GAC5C,EAAE,SAAA,EAAA,IAAY,GACd,EAAE,WAAA,IAAY,IAAI,aAAA,GAAa,SAAA,EAAA,IAAY,GAC3C,IAAO,EAAsB,GAA2B,CAAS,GAGjE,IAAS,EAAgB,GAAO,CAAO,GAAG,SAAS,CAAC;AAE1D,SACE,gBAAA,EAAC,GAAD;AAAA,IACQ,MAAA;AAAA,IACE,QAAA;AAAA,IACR,QAAQ,MAAgB;AAAA,IACf,SAAA;AAAA,IACT,YAAA,CAAa,GAAa,MACxB,EAAmB,GAAU;AAAA,MAAE,eAAe;AAAA,MAAa,UAAU;AAAA,IAAS,CAAC;AAAA,EAElF,CAAA;AAEL"}
@@ -0,0 +1,9 @@
1
+ import { DataSeries } from '../../../../core';
2
+ import { DataSet } from '../../../../core/types/InsightsInstanceSlotData';
3
+ /**
4
+ * Reshapes a flat comparison data_series into one shaped bar per month, sorted ascending by date —
5
+ * the double-bar equivalent of buildChartData. Each month has exactly two contiguous rows; the
6
+ * Income row becomes the comparison series and the other becomes main, regardless of wire order.
7
+ * Months are then sorted ascending so the chart's bar index and the axis line up.
8
+ */
9
+ export declare const buildComparisonSeries: (data: DataSeries | undefined, ariaLabel?: string) => DataSet[];
@@ -0,0 +1,43 @@
1
+ import { buildDynamicCopy as c } from "../../../../core/utils/Localization.es.js";
2
+ import { DATE_FORMATS_INTL as p, formatDate as u } from "../../../../core/constants/DateFormats.es.js";
3
+ import { formatCurrency as i } from "../../../../core/utils/NumberFormatting.es.js";
4
+ import { buildDataSeries as h } from "../BarchartBlock/utils.es.js";
5
+ import { parseISO as n } from "date-fns/parseISO";
6
+ import { isValid as N } from "date-fns/isValid";
7
+ var S = "income", T = (e) => String(e?.label ?? "").toLowerCase() === S, y = (e) => typeof e?.date == "string" && N(n(e.date)), b = (e) => String(e?.localized_label ?? e?.label ?? ""), g = (e) => {
8
+ const o = typeof e == "number" ? e : Number(e);
9
+ return Number.isFinite(o) ? o : 0;
10
+ }, v = (e, o = "") => {
11
+ const l = h(e).filter(y);
12
+ if (l.length === 0) return [];
13
+ const m = /* @__PURE__ */ new Map();
14
+ for (const t of l) {
15
+ const r = String(t.date).slice(0, 7), a = m.get(r);
16
+ a ? a.push(t) : m.set(r, [t]);
17
+ }
18
+ const f = [...m.values()].filter((t) => t.length === 2);
19
+ return f.length === 0 ? [] : f.map((t) => {
20
+ const r = t.find(T) ?? t[t.length - 1];
21
+ return {
22
+ mainRow: t.find((a) => a !== r) ?? t[0],
23
+ comparisonRow: r
24
+ };
25
+ }).sort(({ mainRow: t }, { mainRow: r }) => n(t.date).getTime() - n(r.date).getTime()).map(({ mainRow: t, comparisonRow: r }) => {
26
+ const a = g(t.amount), s = g(r.amount), d = u(n(t.date), p.MONTH_LONG);
27
+ return {
28
+ ariaLabelMain: c(o, d, i(a, "0,0.00"), b(t)),
29
+ ariaLabelComparison: c(o, d, i(s, "0,0.00"), b(r)),
30
+ comparison: s,
31
+ date: t.date,
32
+ formattedComparison: i(s, "0,0"),
33
+ formattedMain: i(a, "0,0"),
34
+ label: u(n(t.date), p.MONTH_SHORT),
35
+ main: a
36
+ };
37
+ });
38
+ };
39
+ export {
40
+ v as buildComparisonSeries
41
+ };
42
+
43
+ //# sourceMappingURL=comparisonUtils.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comparisonUtils.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/comparisonUtils.ts"],"sourcesContent":["import { isValid } from 'date-fns/isValid'\nimport { parseISO } from 'date-fns/parseISO'\n\nimport { DATE_FORMATS_INTL, formatDate } from '../../../../core/constants'\nimport type { DataSeries } from '../../../../core'\nimport type { DataSet } from '../../../../core/types/InsightsInstanceSlotData'\nimport { buildDynamicCopy } from '../../../../core/utils/Localization'\nimport { formatCurrency } from '../../../../core/utils/NumberFormatting'\nimport { buildDataSeries } from '../BarchartBlock/utils'\n\n// The comparison (second) series across every double-bar variant is Income (spend/savings/debt/\n// cost-of-living are all \"X to Income\"). `label` is the stable, non-localized category key, so we\n// key off it rather than row position — the wire lists income first within some months.\nconst INCOME_LABEL = 'income'\nconst isIncomeRow = (row: { label?: string }): boolean =>\n String(row?.label ?? '').toLowerCase() === INCOME_LABEL\n\n// A date-only wire string ('2026-03-01') is a valid ISO date; anything the backend sends that\n// parseISO can't turn into a real Date is dropped before it can poison the ascending sort with a\n// NaN comparator (which would scramble column order — and the chartBarIndex the card forwards to the\n// drilldown on click).\nconst hasValidDate = (row: { date?: string }): boolean =>\n typeof row?.date === 'string' && isValid(parseISO(row.date))\n\n// The series name shown to screen readers. `localized_label` should be coming from the backend's already-localized\n// display name; Document the backend contract inline so the fallback intent is explicit:\n// `localized_label` is expected on every beat whose ariaLabel template uses _3{}.\n// `label` ('income'/'spend') is an English-only fallback for dev/error scenarios.\nconst seriesName = (row: { localized_label?: string; label?: string }): string =>\n String(row?.localized_label ?? row?.label ?? '')\n\n// `amount` is wire data and only loosely typed. `?? 0` guards a missing value but not a non-numeric\n// one (a stray string/null would render as NaN in the bar and the aria label), so coerce and fall\n// back to 0 unless the result is a finite number.\nconst toAmount = (value: unknown): number => {\n const parsed = typeof value === 'number' ? value : Number(value)\n return Number.isFinite(parsed) ? parsed : 0\n}\n\n/**\n * Reshapes a flat comparison data_series into one shaped bar per month, sorted ascending by date —\n * the double-bar equivalent of buildChartData. Each month has exactly two contiguous rows; the\n * Income row becomes the comparison series and the other becomes main, regardless of wire order.\n * Months are then sorted ascending so the chart's bar index and the axis line up.\n */\nexport const buildComparisonSeries = (data: DataSeries | undefined, ariaLabel = ''): DataSet[] => {\n // Guard the wire data before shaping it: `data_series` is type-asserted upstream, not validated, so\n // drop any row without a parseable date rather than let it flow into the sort/group logic.\n const flat = buildDataSeries(data).filter(hasValidDate)\n if (flat.length === 0) {\n return []\n }\n\n // Bucket rows by calendar month (YYYY-MM), not the exact date string, so a month whose rows carry\n // different day-of-month values (e.g. 2026-01-01 vs 2026-01-15) still groups into one bar rather\n // than two size-1 groups that are then dropped as malformed. First-seen order is preserved so the\n // ascending date sort below is stable.\n const byDate = new Map<string, any[]>()\n for (const row of flat) {\n const monthKey = String(row.date).slice(0, 7)\n const group = byDate.get(monthKey)\n if (group) group.push(row)\n else byDate.set(monthKey, [row])\n }\n\n // Keep only well-formed months (exactly one main + one comparison row). A month that lost a row to\n // the date guard above, or arrived malformed, is dropped on its own instead of blanking the whole\n // chart; return [] only when no valid month remains.\n const groups = [...byDate.values()].filter((group) => group.length === 2)\n if (groups.length === 0) {\n return []\n }\n\n return groups\n .map((group) => {\n // Income is always the comparison series; the remaining row is the main category. Fall back to\n // wire order (first = main, last = comparison) if no row is labeled income.\n const comparisonRow = group.find(isIncomeRow) ?? group[group.length - 1]\n const mainRow = group.find((row) => row !== comparisonRow) ?? group[0]\n return { mainRow, comparisonRow }\n })\n .sort(\n ({ mainRow: a }, { mainRow: b }) => parseISO(a.date).getTime() - parseISO(b.date).getTime(),\n )\n .map(({ mainRow, comparisonRow }) => {\n const main = toAmount(mainRow.amount)\n const comparison = toAmount(comparisonRow.amount)\n const monthLong = formatDate(parseISO(mainRow.date), DATE_FORMATS_INTL.MONTH_LONG)\n\n return {\n // The series name is passed as a third copy slot (_3{}) so a screen-reader user can tell the\n // main bar from the comparison bar. The backend template controls whether/where it renders;\n // when the template only has _1{}/_2{} the extra arg is ignored (no invented text).\n ariaLabelMain: buildDynamicCopy(\n ariaLabel,\n monthLong,\n formatCurrency(main, '0,0.00'),\n seriesName(mainRow),\n ) as string,\n ariaLabelComparison: buildDynamicCopy(\n ariaLabel,\n monthLong,\n formatCurrency(comparison, '0,0.00'),\n seriesName(comparisonRow),\n ) as string,\n comparison,\n date: mainRow.date,\n formattedComparison: formatCurrency(comparison, '0,0'),\n formattedMain: formatCurrency(main, '0,0'),\n label: formatDate(parseISO(mainRow.date), DATE_FORMATS_INTL.MONTH_SHORT),\n main,\n }\n })\n}\n"],"mappings":";;;;;;AAaA,IAAM,IAAe,UACf,IAAA,CAAe,MACnB,OAAO,GAAK,SAAS,EAAE,EAAE,YAAY,MAAM,GAMvC,IAAA,CAAgB,MACpB,OAAO,GAAK,QAAS,YAAY,EAAQ,EAAS,EAAI,IAAI,CAAC,GAMvD,IAAA,CAAc,MAClB,OAAO,GAAK,mBAAmB,GAAK,SAAS,EAAE,GAK3C,IAAA,CAAY,MAA2B;AAC3C,QAAM,IAAS,OAAO,KAAU,WAAW,IAAQ,OAAO,CAAK;AAC/D,SAAO,OAAO,SAAS,CAAM,IAAI,IAAS;AAC5C,GAQa,IAAA,CAAyB,GAA8B,IAAY,OAAkB;AAGhG,QAAM,IAAO,EAAgB,CAAI,EAAE,OAAO,CAAY;AACtD,MAAI,EAAK,WAAW,EAClB,QAAO,CAAC;AAOV,QAAM,IAAS,oBAAI,IAAmB;AACtC,aAAW,KAAO,GAAM;AACtB,UAAM,IAAW,OAAO,EAAI,IAAI,EAAE,MAAM,GAAG,CAAC,GACtC,IAAQ,EAAO,IAAI,CAAQ;AACjC,IAAI,IAAO,EAAM,KAAK,CAAG,IACpB,EAAO,IAAI,GAAU,CAAC,CAAG,CAAC;AAAA,EACjC;AAKA,QAAM,IAAS,CAAC,GAAG,EAAO,OAAO,CAAC,EAAE,OAAA,CAAQ,MAAU,EAAM,WAAW,CAAC;AACxE,SAAI,EAAO,WAAW,IACb,CAAC,IAGH,EACJ,IAAA,CAAK,MAAU;AAGd,UAAM,IAAgB,EAAM,KAAK,CAAW,KAAK,EAAM,EAAM,SAAS,CAAA;AAEtE,WAAO;AAAA,MAAE,SADO,EAAM,KAAA,CAAM,MAAQ,MAAQ,CAAa,KAAK,EAAM,CAAA;AAAA,MAClD,eAAA;AAAA,IAAc;AAAA,EAClC,CAAC,EACA,KAAA,CACE,EAAE,SAAS,EAAA,GAAK,EAAE,SAAS,EAAA,MAAQ,EAAS,EAAE,IAAI,EAAE,QAAQ,IAAI,EAAS,EAAE,IAAI,EAAE,QAAQ,CAC5F,EACC,IAAA,CAAK,EAAE,SAAA,GAAS,eAAA,EAAA,MAAoB;AACnC,UAAM,IAAO,EAAS,EAAQ,MAAM,GAC9B,IAAa,EAAS,EAAc,MAAM,GAC1C,IAAY,EAAW,EAAS,EAAQ,IAAI,GAAG,EAAkB,UAAU;AAEjF,WAAO;AAAA,MAIL,eAAe,EACb,GACA,GACA,EAAe,GAAM,QAAQ,GAC7B,EAAW,CAAO,CACpB;AAAA,MACA,qBAAqB,EACnB,GACA,GACA,EAAe,GAAY,QAAQ,GACnC,EAAW,CAAa,CAC1B;AAAA,MACA,YAAA;AAAA,MACA,MAAM,EAAQ;AAAA,MACd,qBAAqB,EAAe,GAAY,KAAK;AAAA,MACrD,eAAe,EAAe,GAAM,KAAK;AAAA,MACzC,OAAO,EAAW,EAAS,EAAQ,IAAI,GAAG,EAAkB,WAAW;AAAA,MACvE,MAAA;AAAA,IACF;AAAA,EACF,CAAC;AACL"}
@@ -1 +1 @@
1
- export * from './DoubleBarChart';
1
+ export * from './DoubleBarChartBlock';
@@ -1,6 +1,6 @@
1
1
  var a = (t, o) => ({
2
2
  SpendToIncome: { color: [t.palette.categories.billsUtilities, t.palette.chart.chart1] },
3
- DebtToIncome: { color: [t.palette.chart.chart1, t.palette.chart.chart5] },
3
+ DebtToIncome: { color: [t.palette.chart.chart5, t.palette.chart.chart1] },
4
4
  SavingsToIncome: { color: [t.palette.chartMono.chartMono5, t.palette.chartMono.chartMono3] }
5
5
  })[o];
6
6
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"layout.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/layout.ts"],"sourcesContent":["import type { Theme } from '@mui/material/styles'\n\nexport const getLayoutConfig = (theme: Theme, variant: string | null) => {\n const config = {\n SpendToIncome: {\n color: [theme.palette.categories.billsUtilities, theme.palette.chart.chart1] as string[],\n },\n DebtToIncome: {\n color: [theme.palette.chart.chart1, theme.palette.chart.chart5] as string[],\n },\n SavingsToIncome: {\n color: [theme.palette.chartMono.chartMono5, theme.palette.chartMono.chartMono3] as string[],\n },\n }\n return config[variant as keyof typeof config]\n}\n"],"mappings":"AAEA,IAAa,IAAA,CAAmB,GAAc,OAYrC;AAAA,EAVL,eAAe,EACb,OAAO,CAAC,EAAM,QAAQ,WAAW,gBAAgB,EAAM,QAAQ,MAAM,MAAM,EAC7E;AAAA,EACA,cAAc,EACZ,OAAO,CAAC,EAAM,QAAQ,MAAM,QAAQ,EAAM,QAAQ,MAAM,MAAM,EAChE;AAAA,EACA,iBAAiB,EACf,OAAO,CAAC,EAAM,QAAQ,UAAU,YAAY,EAAM,QAAQ,UAAU,UAAU,EAChF;AAEK,GAAO,CAAA"}
1
+ {"version":3,"file":"layout.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/layout.ts"],"sourcesContent":["import type { Theme } from '@mui/material/styles'\n\nexport const getLayoutConfig = (theme: Theme, variant: string | null) => {\n const config = {\n SpendToIncome: {\n color: [theme.palette.categories.billsUtilities, theme.palette.chart.chart1] as string[],\n },\n DebtToIncome: {\n color: [theme.palette.chart.chart5, theme.palette.chart.chart1] as string[],\n },\n SavingsToIncome: {\n color: [theme.palette.chartMono.chartMono5, theme.palette.chartMono.chartMono3] as string[],\n },\n }\n return config[variant as keyof typeof config]\n}\n"],"mappings":"AAEA,IAAa,IAAA,CAAmB,GAAc,OAYrC;AAAA,EAVL,eAAe,EACb,OAAO,CAAC,EAAM,QAAQ,WAAW,gBAAgB,EAAM,QAAQ,MAAM,MAAM,EAC7E;AAAA,EACA,cAAc,EACZ,OAAO,CAAC,EAAM,QAAQ,MAAM,QAAQ,EAAM,QAAQ,MAAM,MAAM,EAChE;AAAA,EACA,iBAAiB,EACf,OAAO,CAAC,EAAM,QAAQ,UAAU,YAAY,EAAM,QAAQ,UAAU,UAAU,EAChF;AAEK,GAAO,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { SxProps } from '@mui/material/styles';
2
- import { LegendProps } from '../../../../core/types/InsightsInstanceSlotData';
2
+ import { LegendProps } from '../../../core/types/InsightsInstanceSlotData';
3
3
  export interface LegendComponentProps {
4
4
  legendItems: LegendProps[];
5
5
  legendStyle?: SxProps;
@@ -1,7 +1,7 @@
1
- import a from "@mui/material/Stack";
2
- import { Text as c } from "@mxenabled/mxui";
3
- import { jsx as t, jsxs as n } from "react/jsx-runtime";
4
- var f = ({ legendItems: h, legendStyle: l }) => /* @__PURE__ */ t(a, {
1
+ import n from "@mui/material/Stack";
2
+ import { Text as l } from "@mxenabled/mxui";
3
+ import { jsx as t, jsxs as a } from "react/jsx-runtime";
4
+ var f = ({ legendItems: h, legendStyle: o }) => /* @__PURE__ */ t(n, {
5
5
  sx: {
6
6
  alignItems: "flex-start",
7
7
  flexDirection: "row",
@@ -9,9 +9,9 @@ var f = ({ legendItems: h, legendStyle: l }) => /* @__PURE__ */ t(a, {
9
9
  justifyContent: "flex-start",
10
10
  py: 4,
11
11
  width: "100%",
12
- ...l
12
+ ...o
13
13
  },
14
- children: h.map(({ color: o, label: e, formattedAmount: i }, r) => e && /* @__PURE__ */ n(a, {
14
+ children: h.map(({ color: c, label: r, formattedAmount: i }, e) => r && /* @__PURE__ */ a(n, {
15
15
  sx: {
16
16
  alignItems: "center",
17
17
  flexDirection: "row",
@@ -19,27 +19,27 @@ var f = ({ legendItems: h, legendStyle: l }) => /* @__PURE__ */ t(a, {
19
19
  },
20
20
  children: [/* @__PURE__ */ t("svg", {
21
21
  "aria-hidden": "true",
22
- "aria-labelledby": r === 0 ? "chartLegendLabel" : e,
22
+ "aria-labelledby": e === 0 ? "chartLegendLabel" : r,
23
23
  fill: "none",
24
24
  height: "12",
25
25
  role: "figure",
26
26
  width: "12",
27
27
  children: /* @__PURE__ */ t("rect", {
28
- fill: o,
28
+ fill: c,
29
29
  height: "12",
30
30
  rx: "2",
31
31
  width: "12"
32
32
  })
33
- }), /* @__PURE__ */ n(c, {
34
- id: r === 0 ? "chartLegendLabel" : e,
33
+ }), /* @__PURE__ */ a(l, {
34
+ id: e === 0 ? "chartLegendLabel" : r,
35
35
  variant: "caption",
36
36
  children: [
37
- e,
37
+ r,
38
38
  " ",
39
39
  i ? `: ${i}` : ""
40
40
  ]
41
41
  })]
42
- }, r))
42
+ }, r ?? e))
43
43
  });
44
44
  export {
45
45
  f as Legend
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChartLegend.es.js","names":[],"sources":["../../../../src/insights-v2/components/chartblocks/ChartLegend.tsx"],"sourcesContent":["import { Text } from '@mxenabled/mxui'\n\nimport Stack from '@mui/material/Stack'\n\nimport type { SxProps } from '@mui/material/styles'\nimport type { LegendProps } from '../../../core/types/InsightsInstanceSlotData'\n\nexport interface LegendComponentProps {\n legendItems: LegendProps[]\n legendStyle?: SxProps\n}\n\nexport const Legend = ({ legendItems, legendStyle }: LegendComponentProps) => {\n return (\n <Stack\n sx={{\n alignItems: 'flex-start',\n flexDirection: 'row',\n gap: 24,\n justifyContent: 'flex-start',\n py: 4,\n width: '100%',\n ...legendStyle,\n }}\n >\n {legendItems.map(\n ({ color, label, formattedAmount }, index) =>\n label && (\n <Stack key={label ?? index} sx={{ alignItems: 'center', flexDirection: 'row', gap: 8 }}>\n <svg\n aria-hidden=\"true\"\n aria-labelledby={index === 0 ? 'chartLegendLabel' : label}\n fill=\"none\"\n height=\"12\"\n role=\"figure\"\n width=\"12\"\n >\n <rect fill={color} height=\"12\" rx=\"2\" width=\"12\" />\n </svg>\n <Text id={index === 0 ? 'chartLegendLabel' : label} variant=\"caption\">\n {label} {formattedAmount ? `: ${formattedAmount}` : ''}\n </Text>\n </Stack>\n ),\n )}\n </Stack>\n )\n}\n"],"mappings":";;;AAYA,IAAa,IAAA,CAAU,EAAE,aAAA,GAAa,aAAA,EAAA,MAElC,gBAAA,EAAC,GAAD;AAAA,EACE,IAAI;AAAA,IACF,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,KAAK;AAAA,IACL,gBAAgB;AAAA,IAChB,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,GAAG;AAAA,EACL;AAAA,EAEC,UAAA,EAAY,IAAA,CACV,EAAE,OAAA,GAAO,OAAA,GAAO,iBAAA,EAAA,GAAmB,MAClC,KACE,gBAAA,EAAC,GAAD;AAAA,IAA4B,IAAI;AAAA,MAAE,YAAY;AAAA,MAAU,eAAe;AAAA,MAAO,KAAK;AAAA,IAAE;AAAA,IAArF,UAAA,CACE,gBAAA,EAAC,OAAD;AAAA,MACE,eAAY;AAAA,MACZ,mBAAiB,MAAU,IAAI,qBAAqB;AAAA,MACpD,MAAK;AAAA,MACL,QAAO;AAAA,MACP,MAAK;AAAA,MACL,OAAM;AAAA,MAEN,UAAA,gBAAA,EAAC,QAAD;AAAA,QAAM,MAAM;AAAA,QAAO,QAAO;AAAA,QAAK,IAAG;AAAA,QAAI,OAAM;AAAA,MAAM,CAAA;AAAA,IAC/C,CAAA,GACL,gBAAA,EAAC,GAAD;AAAA,MAAM,IAAI,MAAU,IAAI,qBAAqB;AAAA,MAAO,SAAQ;AAAA,MAA5D,UAAA;AAAA,QACG;AAAA,QAAM;AAAA,QAAE,IAAkB,KAAK,CAAA,KAAoB;AAAA,MAChD;AAAA,IACD,CAAA,CAAA;AAAA,EAdK,GAAA,KAAS,CAcd,CAEb;AACK,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { DataSet } from '../../../../core/types/InsightsInstanceSlotData';
2
+ import { DataSet } from '../../../core/types/InsightsInstanceSlotData';
3
3
  interface BarStyleProps extends React.CSSProperties {
4
4
  x?: number;
5
5
  y?: number;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CustomDoubleBar.es.js","names":[],"sources":["../../../../src/insights-v2/components/chartblocks/CustomDoubleBar.tsx"],"sourcesContent":["import React from 'react'\nimport type { DataSet } from '../../../core/types/InsightsInstanceSlotData'\n\ninterface BarStyleProps extends React.CSSProperties {\n x?: number\n y?: number\n}\n\ninterface CustomDoubleBarPlotMXUIProps {\n color: string\n data: DataSet[]\n series: Series\n style: BarStyleProps\n}\n\ninterface Series {\n index: number\n type: number\n}\n\nexport const CustomDoubleBarPlotMXUI = ({\n color,\n data,\n series,\n style,\n ...restProps\n}: CustomDoubleBarPlotMXUIProps) => {\n const rectRef = React.useRef<SVGRectElement>(null)\n\n React.useLayoutEffect(() => {\n const resizeObserver = new ResizeObserver(() => {\n window.requestAnimationFrame(() => {\n if (rectRef.current) {\n const { width } = rectRef.current.getBoundingClientRect()\n\n const xValue = width / 2\n const textElement = rectRef.current.querySelector('text')\n if (textElement) {\n textElement.setAttribute('transform', `translate(${xValue}, -8)`)\n }\n }\n })\n })\n\n if (rectRef.current) resizeObserver.observe(rectRef.current)\n return () => {\n if (rectRef.current) resizeObserver.unobserve(rectRef.current)\n }\n }, [])\n\n const { ariaLabelComparison, ariaLabelMain } = data[series.index]\n\n const ariaLabel = series.type === 0 ? ariaLabelMain : ariaLabelComparison\n\n const rectStyle = {\n ...style,\n transition: 'all 0.3s ease-in-out',\n }\n\n // Create path with rounded top corners (10px radius) and square bottom corners\n const pathBarWidth = (style.width as number) || 0\n const pathBarHeight = (style.height as number) || 0\n const pathX = (style.x as number) || 0\n const pathY = (style.y as number) || 0\n const radius = 4\n\n const pathData = `\n M ${pathX + radius},${pathY}\n L ${pathX + pathBarWidth - radius},${pathY}\n Q ${pathX + pathBarWidth},${pathY} ${pathX + pathBarWidth},${pathY + radius}\n L ${pathX + pathBarWidth},${pathY + pathBarHeight}\n L ${pathX},${pathY + pathBarHeight}\n L ${pathX},${pathY + radius}\n Q ${pathX},${pathY} ${pathX + radius},${pathY}\n Z\n `.trim()\n\n return (\n <g aria-label={ariaLabel}>\n <path {...restProps} d={pathData} fill={color} style={rectStyle} />\n </g>\n )\n}\n"],"mappings":";;AAoBA,IAAa,IAAA,CAA2B,EACtC,OAAA,GACA,MAAA,GACA,QAAA,GACA,OAAA,GACA,GAAG,EAAA,MAC+B;AAClC,QAAM,IAAU,EAAM,OAAuB,IAAI;AAEjD,EAAA,EAAM,gBAAA,MAAsB;AAC1B,UAAM,IAAiB,IAAI,eAAA,MAAqB;AAC9C,aAAO,sBAAA,MAA4B;AACjC,YAAI,EAAQ,SAAS;AACnB,gBAAM,EAAE,OAAA,EAAA,IAAU,EAAQ,QAAQ,sBAAsB,GAElD,IAAS,IAAQ,GACjB,IAAc,EAAQ,QAAQ,cAAc,MAAM;AACxD,UAAI,KACF,EAAY,aAAa,aAAa,aAAa,CAAA,OAAa;AAAA,QAEpE;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,WAAI,EAAQ,WAAS,EAAe,QAAQ,EAAQ,OAAO,GAC3D,MAAa;AACX,MAAI,EAAQ,WAAS,EAAe,UAAU,EAAQ,OAAO;AAAA,IAC/D;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,EAAE,qBAAA,GAAqB,eAAA,EAAA,IAAkB,EAAK,EAAO,KAAA,GAErD,IAAY,EAAO,SAAS,IAAI,IAAgB,GAEhD,IAAY;AAAA,IAChB,GAAG;AAAA,IACH,YAAY;AAAA,EACd,GAGM,IAAgB,EAAM,SAAoB,GAC1C,IAAiB,EAAM,UAAqB,GAC5C,IAAS,EAAM,KAAgB,GAC/B,IAAS,EAAM,KAAgB,GAC/B,IAAS,GAET,IAAW;AAAA,QACX,IAAQ,CAAA,IAAU,CAAA;AAAA,QAClB,IAAQ,IAAe,CAAA,IAAU,CAAA;AAAA,QACjC,IAAQ,CAAA,IAAgB,CAAA,IAAS,IAAQ,CAAA,IAAgB,IAAQ,CAAA;AAAA,QACjE,IAAQ,CAAA,IAAgB,IAAQ,CAAA;AAAA,QAChC,CAAA,IAAS,IAAQ,CAAA;AAAA,QACjB,CAAA,IAAS,IAAQ,CAAA;AAAA,QACjB,CAAA,IAAS,CAAA,IAAS,IAAQ,CAAA,IAAU,CAAA;AAAA;AAAA,IAExC,KAAK;AAEP,SACE,gBAAA,EAAC,KAAD;AAAA,IAAG,cAAY;AAAA,IACb,UAAA,gBAAA,EAAC,QAAD;AAAA,MAAM,GAAI;AAAA,MAAW,GAAG;AAAA,MAAU,MAAM;AAAA,MAAO,OAAO;AAAA,IAAY,CAAA;AAAA,EACjE,CAAA;AAEP"}
@@ -0,0 +1,17 @@
1
+ import { Legends } from '../../../core';
2
+ import { DataSet, LegendProps } from '../../../core/types/InsightsInstanceSlotData';
3
+ interface DoubleBarChartProps {
4
+ bars: DataSet[];
5
+ colors: string[];
6
+ legends?: (Legends | LegendProps)[];
7
+ isMini?: boolean;
8
+ onBarClick: (columnIndex: number, subIndex: number) => void;
9
+ }
10
+ /**
11
+ * Pure double-bar chart (month columns x main/comparison). Presentational and self-contained \u2014 it
12
+ * receives shaped data + palette as props and reports clicks via onBarClick, holding no store,
13
+ * selection, or data-shaping of its own. This mirrors BarChartV2; the DoubleBarChartBlock card
14
+ * wrapper builds the data and injects the store behavior, exactly as BarchartBlock wraps BarChartV2.
15
+ */
16
+ export declare const DoubleBarChart: ({ bars, colors, legends, isMini, onBarClick, }: DoubleBarChartProps) => import("react/jsx-runtime").JSX.Element;
17
+ export {};
@@ -0,0 +1,118 @@
1
+ import { EmptyBarChart as b } from "./EmptyBarChart.es.js";
2
+ import { useContainerDimensions as C } from "../../hooks/useContainerDimensions.es.js";
3
+ import { CustomDoubleBarPlotMXUI as k } from "./CustomDoubleBar.es.js";
4
+ import { Legend as w } from "./ChartLegend.es.js";
5
+ import S from "react";
6
+ import A from "@mui/material/Stack";
7
+ import { jsx as o, jsxs as m } from "react/jsx-runtime";
8
+ import I from "@mui/material/Box";
9
+ import { BarPlot as B } from "@mui/x-charts/BarChart";
10
+ import { ChartContainer as R } from "@mui/x-charts/ChartContainer";
11
+ import { ChartsXAxis as L } from "@mui/x-charts/ChartsXAxis";
12
+ var E = ({ bars: r, colors: n, legends: d, isMini: l = !1, onBarClick: h }) => {
13
+ const s = r.length - 1, p = 5e-3, f = 0.16, c = S.useRef(null), { height: y, width: x } = C(c), g = ({ dataIndex: e, seriesId: t }) => {
14
+ h(e, Number(t.split("-").pop()));
15
+ }, i = d?.map((e, t) => ({
16
+ color: n[t] ?? "transparent",
17
+ ...e
18
+ }));
19
+ return r.length > 0 ? /* @__PURE__ */ m(A, {
20
+ sx: {
21
+ mb: 0,
22
+ width: "100%",
23
+ p: 0
24
+ },
25
+ children: [/* @__PURE__ */ o(I, {
26
+ ref: c,
27
+ sx: {
28
+ height: l ? 120 : 172,
29
+ touchAction: "pan-y",
30
+ width: "100%",
31
+ p: 0,
32
+ m: 0,
33
+ "& svg": {
34
+ touchAction: "pan-y",
35
+ userSelect: "none"
36
+ },
37
+ "& .recharts-wrapper": { touchAction: "pan-y" }
38
+ },
39
+ children: /* @__PURE__ */ m(R, {
40
+ colors: n,
41
+ dataset: r,
42
+ height: y,
43
+ margin: {
44
+ bottom: 16,
45
+ left: 24,
46
+ right: 24,
47
+ top: 0
48
+ },
49
+ series: [{
50
+ dataKey: "main",
51
+ type: "bar"
52
+ }, {
53
+ dataKey: "comparison",
54
+ type: "bar"
55
+ }],
56
+ width: x,
57
+ xAxis: [{
58
+ barGapRatio: p,
59
+ categoryGapRatio: f,
60
+ dataKey: "label",
61
+ scaleType: "band"
62
+ }],
63
+ yAxis: [{ width: 0 }],
64
+ children: [/* @__PURE__ */ o(L, {
65
+ disableTicks: !1,
66
+ slots: { axisTickLabel: ({ text: e, ...t }) => {
67
+ const a = r[s]?.label;
68
+ return /* @__PURE__ */ o("text", {
69
+ ...t,
70
+ style: {
71
+ ...t.style,
72
+ fontWeight: a === e ? 700 : 400
73
+ },
74
+ children: e
75
+ });
76
+ } },
77
+ sx: { ".MuiChartsAxis-line": { stroke: "border.darker" } },
78
+ tickLabelStyle: {
79
+ fontSize: 11,
80
+ fill: "text.secondary",
81
+ fontWeight: 400
82
+ }
83
+ }), /* @__PURE__ */ o(B, {
84
+ onItemClick: (e, { dataIndex: t, seriesId: a }) => g({
85
+ dataIndex: t,
86
+ seriesId: a.toString()
87
+ }),
88
+ slots: { bar: (e) => {
89
+ const { ownerState: t, ...a } = e, u = s === t.dataIndex ? t.color : `${t.color}50`;
90
+ return /* @__PURE__ */ o(k, {
91
+ ...a,
92
+ color: u,
93
+ data: r,
94
+ series: {
95
+ index: t.dataIndex,
96
+ type: Number(t.id?.toString().split("-").pop() ?? 0)
97
+ },
98
+ style: {
99
+ height: e.height,
100
+ x: e.x,
101
+ y: e.y,
102
+ width: e.width
103
+ }
104
+ });
105
+ } }
106
+ })]
107
+ })
108
+ }), i && !l && i.length > 0 && /* @__PURE__ */ o(w, {
109
+ legendItems: i,
110
+ legendStyle: { ml: 24 }
111
+ })]
112
+ }) : /* @__PURE__ */ o(b, {});
113
+ };
114
+ export {
115
+ E as DoubleBarChart
116
+ };
117
+
118
+ //# sourceMappingURL=DoubleBarChart.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DoubleBarChart.es.js","names":[],"sources":["../../../../src/insights-v2/components/chartblocks/DoubleBarChart.tsx"],"sourcesContent":["import React from 'react'\n\nimport Box from '@mui/material/Box'\nimport Stack from '@mui/material/Stack'\n\nimport { BarPlot } from '@mui/x-charts/BarChart'\nimport { ChartContainer } from '@mui/x-charts/ChartContainer'\nimport { ChartsXAxis } from '@mui/x-charts/ChartsXAxis'\n\nimport { useContainerDimensions } from '../../hooks/useContainerDimensions'\nimport type { Legends } from '../../../core'\nimport type { DataSet, LegendProps } from '../../../core/types/InsightsInstanceSlotData'\n\nimport { CustomDoubleBarPlotMXUI } from './CustomDoubleBar'\nimport { Legend } from './ChartLegend'\nimport { EmptyBarChart } from './EmptyBarChart'\n\ninterface DoubleBarChartProps {\n // Shaped comparison series (one entry per month column), built by the caller (buildComparisonSeries)\n // \\u2014 mirroring how BarchartBlock builds `data` for BarChartV2.\n bars: DataSet[]\n // Two-entry palette [main, comparison]. Resolved by the caller (the card via getLayoutConfig). This\n // prop is the only color hook \\u2014 getLayoutConfig itself is never modified.\n colors: string[]\n // Same shape as instance_slot_data.legends; mapped onto the palette below.\n legends?: (Legends | LegendProps)[]\n isMini?: boolean\n // Called on a bar click with the clicked column and its sub-series (0 = main, 1 = comparison); the\n // caller decides what a click does (card opens the drawer, drill-down updates its selection).\n onBarClick: (columnIndex: number, subIndex: number) => void\n}\n\n/**\n * Pure double-bar chart (month columns x main/comparison). Presentational and self-contained \\u2014 it\n * receives shaped data + palette as props and reports clicks via onBarClick, holding no store,\n * selection, or data-shaping of its own. This mirrors BarChartV2; the DoubleBarChartBlock card\n * wrapper builds the data and injects the store behavior, exactly as BarchartBlock wraps BarChartV2.\n */\nexport const DoubleBarChart = ({\n bars,\n colors,\n legends,\n isMini = false,\n onBarClick,\n}: DoubleBarChartProps) => {\n // The most recent (last) column is emphasized; the others are dimmed.\n const selectedTabIndex = bars.length - 1\n const barGapRatio = 0.005\n const categoryGapRatio = 0.16\n\n const containerRef = React.useRef<HTMLDivElement>(null)\n const { height, width } = useContainerDimensions(containerRef)\n\n const handleBarClick = ({ dataIndex, seriesId }: { dataIndex: number; seriesId: string }) => {\n const seriesType = Number(seriesId.split('-').pop())\n onBarClick(dataIndex, seriesType)\n }\n\n // colors can be empty for an unregistered variant (getLayoutConfig miss); fall back to transparent\n // so a swatch never renders as default-black.\n const legendItems = legends?.map((legend, index) => ({\n color: colors[index] ?? 'transparent',\n ...legend,\n })) as LegendProps[]\n\n return bars.length > 0 ? (\n <Stack sx={{ mb: 0, width: '100%', p: 0 }}>\n <Box\n ref={containerRef}\n sx={{\n height: isMini ? 120 : 172,\n touchAction: 'pan-y',\n width: '100%',\n p: 0,\n m: 0,\n '& svg': {\n touchAction: 'pan-y',\n userSelect: 'none',\n },\n '& .recharts-wrapper': {\n touchAction: 'pan-y',\n },\n }}\n >\n <ChartContainer\n colors={colors}\n dataset={bars as any[]}\n height={height}\n margin={{\n bottom: 16,\n left: 24,\n right: 24,\n top: 0,\n }}\n series={[\n { dataKey: 'main', type: 'bar' },\n { dataKey: 'comparison', type: 'bar' },\n ]}\n width={width}\n xAxis={[\n {\n barGapRatio,\n categoryGapRatio,\n dataKey: 'label',\n scaleType: 'band',\n },\n ]}\n yAxis={[{ width: 0 }]}\n >\n <ChartsXAxis\n disableTicks={false}\n slots={{\n axisTickLabel: ({ text, ...restProps }) => {\n const selectedLabel = bars[selectedTabIndex]?.label\n return (\n <text\n {...restProps}\n style={\n {\n ...restProps.style,\n fontWeight: selectedLabel === text ? 700 : 400,\n } as React.CSSProperties\n }\n >\n {text}\n </text>\n )\n },\n }}\n sx={{\n '.MuiChartsAxis-line': {\n stroke: 'border.darker',\n },\n }}\n tickLabelStyle={{\n fontSize: 11,\n fill: 'text.secondary',\n fontWeight: 400,\n }}\n />\n <BarPlot\n onItemClick={(_, { dataIndex, seriesId }) =>\n handleBarClick({ dataIndex, seriesId: seriesId.toString() })\n }\n slots={{\n bar: (props) => {\n const { ownerState, ...defaultProps } = props\n const isSelected = selectedTabIndex === ownerState.dataIndex\n const barColor = isSelected ? ownerState.color : `${ownerState.color}50`\n\n return (\n <CustomDoubleBarPlotMXUI\n {...defaultProps}\n color={barColor}\n data={bars}\n series={{\n index: ownerState.dataIndex,\n type: Number(ownerState.id?.toString().split('-').pop() ?? 0),\n }}\n style={{\n height: props.height,\n x: props.x,\n y: props.y,\n width: props.width,\n }}\n />\n )\n },\n }}\n />\n </ChartContainer>\n </Box>\n\n {legendItems && !isMini && legendItems.length > 0 && (\n <Legend legendItems={legendItems} legendStyle={{ ml: 24 }} />\n )}\n </Stack>\n ) : (\n <EmptyBarChart />\n )\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { BAR_CHART_VARIANTS as o, barChartVariant as t, buildChartData as m, buildDataSeries as i } from "./blocks/ChartBlocks/BarchartBlock/utils.es.js";
2
2
  import { BarchartBlock as p } from "./blocks/ChartBlocks/BarchartBlock/BarchartBlock.es.js";
3
- import { DoubleBarChartBlock as e } from "./blocks/ChartBlocks/DoubleBarChartBlock/DoubleBarChart.es.js";
3
+ import { DoubleBarChartBlock as e } from "./blocks/ChartBlocks/DoubleBarChartBlock/DoubleBarChartBlock.es.js";
4
4
  import n from "./blocks/ChartBlocks/DonutChartBlock/DonutChartBlock.es.js";
5
5
  import s from "./blocks/ChartBlocks/DoubleProgressBarBlock/DoubleProgressBarBlock.es.js";
6
6
  import g from "./blocks/ComponentBlocks/AccountBlock/AccountBlock.es.js";
@@ -1,5 +1,5 @@
1
1
  import { BarchartBlock as o } from "../blocks/ChartBlocks/BarchartBlock/BarchartBlock.es.js";
2
- import { DoubleBarChartBlock as r } from "../blocks/ChartBlocks/DoubleBarChartBlock/DoubleBarChart.es.js";
2
+ import { DoubleBarChartBlock as r } from "../blocks/ChartBlocks/DoubleBarChartBlock/DoubleBarChartBlock.es.js";
3
3
  import t from "../blocks/ChartBlocks/DonutChartBlock/DonutChartBlock.es.js";
4
4
  import c from "../blocks/ChartBlocks/DoubleProgressBarBlock/DoubleProgressBarBlock.es.js";
5
5
  import l from "../blocks/ComponentBlocks/AccountBlock/AccountBlock.es.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mx-cartographer/experiences",
3
- "version": "9.4.4",
3
+ "version": "9.4.6",
4
4
  "description": "Library containing experience widgets",
5
5
  "author": "MX",
6
6
  "license": "MIT",
@@ -61,6 +61,10 @@
61
61
  "import": "./dist/insights/index.es.js",
62
62
  "types": "./dist/insights/index.d.ts"
63
63
  },
64
+ "./insights-v2": {
65
+ "import": "./dist/insights-v2/index.es.js",
66
+ "types": "./dist/insights-v2/index.d.ts"
67
+ },
64
68
  "./investments": {
65
69
  "import": "./dist/investments/index.es.js",
66
70
  "types": "./dist/investments/index.d.ts"
@@ -143,6 +147,9 @@
143
147
  "insights": [
144
148
  "./dist/insights/index.d.ts"
145
149
  ],
150
+ "insights-v2": [
151
+ "./dist/insights-v2/index.d.ts"
152
+ ],
146
153
  "investments": [
147
154
  "./dist/investments/index.d.ts"
148
155
  ],
@@ -1 +0,0 @@
1
- {"version":3,"file":"ChartLegend.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/ChartLegend.tsx"],"sourcesContent":["import { Text } from '@mxenabled/mxui'\n\nimport Stack from '@mui/material/Stack'\n\nimport type { SxProps } from '@mui/material/styles'\nimport type { LegendProps } from '../../../../core/types/InsightsInstanceSlotData'\n\nexport interface LegendComponentProps {\n legendItems: LegendProps[]\n legendStyle?: SxProps\n}\n\nexport const Legend = ({ legendItems, legendStyle }: LegendComponentProps) => {\n return (\n <Stack\n sx={{\n alignItems: 'flex-start',\n flexDirection: 'row',\n gap: 24,\n justifyContent: 'flex-start',\n py: 4,\n width: '100%',\n ...legendStyle,\n }}\n >\n {legendItems.map(\n ({ color, label, formattedAmount }, index) =>\n label && (\n <Stack key={index} sx={{ alignItems: 'center', flexDirection: 'row', gap: 8 }}>\n <svg\n aria-hidden=\"true\"\n aria-labelledby={index === 0 ? 'chartLegendLabel' : label}\n fill=\"none\"\n height=\"12\"\n role=\"figure\"\n width=\"12\"\n >\n <rect fill={color} height=\"12\" rx=\"2\" width=\"12\" />\n </svg>\n <Text id={index === 0 ? 'chartLegendLabel' : label} variant=\"caption\">\n {label} {formattedAmount ? `: ${formattedAmount}` : ''}\n </Text>\n </Stack>\n ),\n )}\n </Stack>\n )\n}\n"],"mappings":";;;AAYA,IAAa,IAAA,CAAU,EAAE,aAAA,GAAa,aAAA,EAAA,MAElC,gBAAA,EAAC,GAAD;AAAA,EACE,IAAI;AAAA,IACF,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,KAAK;AAAA,IACL,gBAAgB;AAAA,IAChB,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,GAAG;AAAA,EACL;AAAA,EAEC,UAAA,EAAY,IAAA,CACV,EAAE,OAAA,GAAO,OAAA,GAAO,iBAAA,EAAA,GAAmB,MAClC,KACE,gBAAA,EAAC,GAAD;AAAA,IAAmB,IAAI;AAAA,MAAE,YAAY;AAAA,MAAU,eAAe;AAAA,MAAO,KAAK;AAAA,IAAE;AAAA,IAA5E,UAAA,CACE,gBAAA,EAAC,OAAD;AAAA,MACE,eAAY;AAAA,MACZ,mBAAiB,MAAU,IAAI,qBAAqB;AAAA,MACpD,MAAK;AAAA,MACL,QAAO;AAAA,MACP,MAAK;AAAA,MACL,OAAM;AAAA,MAEN,UAAA,gBAAA,EAAC,QAAD;AAAA,QAAM,MAAM;AAAA,QAAO,QAAO;AAAA,QAAK,IAAG;AAAA,QAAI,OAAM;AAAA,MAAM,CAAA;AAAA,IAC/C,CAAA,GACL,gBAAA,EAAC,GAAD;AAAA,MAAM,IAAI,MAAU,IAAI,qBAAqB;AAAA,MAAO,SAAQ;AAAA,MAA5D,UAAA;AAAA,QACG;AAAA,QAAM;AAAA,QAAE,IAAkB,KAAK,CAAA,KAAoB;AAAA,MAChD;AAAA,IACD,CAAA,CAAA;AAAA,EAdK,GAAA,CAcL,CAEb;AACK,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"CustomDoubleBar.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/CustomDoubleBar.tsx"],"sourcesContent":["import React from 'react'\nimport type { DataSet } from '../../../../core/types/InsightsInstanceSlotData'\n\ninterface BarStyleProps extends React.CSSProperties {\n x?: number\n y?: number\n}\n\ninterface CustomDoubleBarPlotMXUIProps {\n color: string\n data: DataSet[]\n series: Series\n style: BarStyleProps\n}\n\ninterface Series {\n index: number\n type: number\n}\n\nexport const CustomDoubleBarPlotMXUI = ({\n color,\n data,\n series,\n style,\n ...restProps\n}: CustomDoubleBarPlotMXUIProps) => {\n const rectRef = React.useRef<SVGRectElement>(null)\n\n React.useLayoutEffect(() => {\n const resizeObserver = new ResizeObserver(() => {\n window.requestAnimationFrame(() => {\n if (rectRef.current) {\n const { width } = rectRef.current.getBoundingClientRect()\n\n const xValue = width / 2\n const textElement = rectRef.current.querySelector('text')\n if (textElement) {\n textElement.setAttribute('transform', `translate(${xValue}, -8)`)\n }\n }\n })\n })\n\n if (rectRef.current) resizeObserver.observe(rectRef.current)\n return () => {\n if (rectRef.current) resizeObserver.unobserve(rectRef.current)\n }\n }, [])\n\n const { ariaLabelComparison, ariaLabelMain } = data[series.index]\n\n const ariaLabel = series.type === 0 ? ariaLabelMain : ariaLabelComparison\n\n const rectStyle = {\n ...style,\n transition: 'all 0.3s ease-in-out',\n }\n\n // Create path with rounded top corners (10px radius) and square bottom corners\n const pathBarWidth = (style.width as number) || 0\n const pathBarHeight = (style.height as number) || 0\n const pathX = (style.x as number) || 0\n const pathY = (style.y as number) || 0\n const radius = 4\n\n const pathData = `\n M ${pathX + radius},${pathY}\n L ${pathX + pathBarWidth - radius},${pathY}\n Q ${pathX + pathBarWidth},${pathY} ${pathX + pathBarWidth},${pathY + radius}\n L ${pathX + pathBarWidth},${pathY + pathBarHeight}\n L ${pathX},${pathY + pathBarHeight}\n L ${pathX},${pathY + radius}\n Q ${pathX},${pathY} ${pathX + radius},${pathY}\n Z\n `.trim()\n\n return (\n <g aria-label={ariaLabel}>\n <path {...restProps} d={pathData} fill={color} style={rectStyle} />\n </g>\n )\n}\n"],"mappings":";;AAoBA,IAAa,IAAA,CAA2B,EACtC,OAAA,GACA,MAAA,GACA,QAAA,GACA,OAAA,GACA,GAAG,EAAA,MAC+B;AAClC,QAAM,IAAU,EAAM,OAAuB,IAAI;AAEjD,EAAA,EAAM,gBAAA,MAAsB;AAC1B,UAAM,IAAiB,IAAI,eAAA,MAAqB;AAC9C,aAAO,sBAAA,MAA4B;AACjC,YAAI,EAAQ,SAAS;AACnB,gBAAM,EAAE,OAAA,EAAA,IAAU,EAAQ,QAAQ,sBAAsB,GAElD,IAAS,IAAQ,GACjB,IAAc,EAAQ,QAAQ,cAAc,MAAM;AACxD,UAAI,KACF,EAAY,aAAa,aAAa,aAAa,CAAA,OAAa;AAAA,QAEpE;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,WAAI,EAAQ,WAAS,EAAe,QAAQ,EAAQ,OAAO,GAC3D,MAAa;AACX,MAAI,EAAQ,WAAS,EAAe,UAAU,EAAQ,OAAO;AAAA,IAC/D;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,EAAE,qBAAA,GAAqB,eAAA,EAAA,IAAkB,EAAK,EAAO,KAAA,GAErD,IAAY,EAAO,SAAS,IAAI,IAAgB,GAEhD,IAAY;AAAA,IAChB,GAAG;AAAA,IACH,YAAY;AAAA,EACd,GAGM,IAAgB,EAAM,SAAoB,GAC1C,IAAiB,EAAM,UAAqB,GAC5C,IAAS,EAAM,KAAgB,GAC/B,IAAS,EAAM,KAAgB,GAC/B,IAAS,GAET,IAAW;AAAA,QACX,IAAQ,CAAA,IAAU,CAAA;AAAA,QAClB,IAAQ,IAAe,CAAA,IAAU,CAAA;AAAA,QACjC,IAAQ,CAAA,IAAgB,CAAA,IAAS,IAAQ,CAAA,IAAgB,IAAQ,CAAA;AAAA,QACjE,IAAQ,CAAA,IAAgB,IAAQ,CAAA;AAAA,QAChC,CAAA,IAAS,IAAQ,CAAA;AAAA,QACjB,CAAA,IAAS,IAAQ,CAAA;AAAA,QACjB,CAAA,IAAS,CAAA,IAAS,IAAQ,CAAA,IAAU,CAAA;AAAA;AAAA,IAExC,KAAK;AAEP,SACE,gBAAA,EAAC,KAAD;AAAA,IAAG,cAAY;AAAA,IACb,UAAA,gBAAA,EAAC,QAAD;AAAA,MAAM,GAAI;AAAA,MAAW,GAAG;AAAA,MAAU,MAAM;AAAA,MAAO,OAAO;AAAA,IAAY,CAAA;AAAA,EACjE,CAAA;AAEP"}
@@ -1,2 +0,0 @@
1
- import { BlockProps } from '../../types';
2
- export declare const DoubleBarChartBlock: ({ payload: { instance_slot, instance_slot_data, widget_type }, beatGuid, }: BlockProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,125 +0,0 @@
1
- import { useInsightsV2Store as B } from "../../../../common/context/hooks.es.js";
2
- import { EmptyBarChart as A } from "../../../components/chartblocks/EmptyBarChart.es.js";
3
- import { useContainerDimensions as v } from "../../../hooks/useContainerDimensions.es.js";
4
- import { CustomDoubleBarPlotMXUI as T } from "./CustomDoubleBar.es.js";
5
- import { Legend as L } from "./ChartLegend.es.js";
6
- import { getLayoutConfig as R } from "./layout.es.js";
7
- import D from "react";
8
- import K from "@mui/material/Stack";
9
- import { jsx as r, jsxs as d } from "react/jsx-runtime";
10
- import { useTheme as M } from "@mui/material/styles";
11
- import j from "@mui/material/Box";
12
- import { BarPlot as G } from "@mui/x-charts/BarChart";
13
- import { ChartContainer as N } from "@mui/x-charts/ChartContainer";
14
- import { ChartsXAxis as P } from "@mui/x-charts/ChartsXAxis";
15
- var Y = ({ payload: { instance_slot: h, instance_slot_data: s, widget_type: p }, beatGuid: f = "" }) => {
16
- const { openChartDrilldown: y } = B(), l = p === "mini", { variant: g } = h, { data_series: i, legends: x } = s, a = i.length - 1, b = 5e-3, u = 0.16, C = M(), c = R(C, g).color, m = D.useRef(null), { height: I, width: k } = v(m), w = ({ dataIndex: e, seriesId: t }) => {
17
- const o = Number(t.split("-").pop());
18
- y(f, {
19
- chartBarIndex: e,
20
- tabIndex: o
21
- });
22
- }, n = x?.map((e, t) => ({
23
- color: c[t],
24
- ...e
25
- }));
26
- return i.length > 0 ? /* @__PURE__ */ d(K, {
27
- sx: {
28
- mb: 0,
29
- width: "100%",
30
- p: 0
31
- },
32
- children: [/* @__PURE__ */ r(j, {
33
- ref: m,
34
- sx: {
35
- height: l ? 120 : 172,
36
- touchAction: "pan-y",
37
- width: "100%",
38
- p: 0,
39
- m: 0,
40
- "& svg": {
41
- touchAction: "pan-y",
42
- userSelect: "none"
43
- },
44
- "& .recharts-wrapper": { touchAction: "pan-y" }
45
- },
46
- children: /* @__PURE__ */ d(N, {
47
- colors: c,
48
- dataset: i,
49
- height: I,
50
- margin: {
51
- bottom: 16,
52
- left: 24,
53
- right: 24,
54
- top: 0
55
- },
56
- series: [{
57
- dataKey: "main",
58
- type: "bar"
59
- }, {
60
- dataKey: "comparison",
61
- type: "bar"
62
- }],
63
- width: k,
64
- xAxis: [{
65
- barGapRatio: b,
66
- categoryGapRatio: u,
67
- dataKey: "label",
68
- scaleType: "band"
69
- }],
70
- yAxis: [{ width: 0 }],
71
- children: [/* @__PURE__ */ r(P, {
72
- disableTicks: !1,
73
- slots: { axisTickLabel: ({ text: e, ...t }) => {
74
- const o = a !== void 0 ? s.data_series[a]?.label : void 0;
75
- return /* @__PURE__ */ r("text", {
76
- ...t,
77
- style: {
78
- ...t.style,
79
- fontWeight: o === e ? 700 : 400
80
- },
81
- children: e
82
- });
83
- } },
84
- sx: { ".MuiChartsAxis-line": { stroke: "border.darker" } },
85
- tickLabelStyle: {
86
- fontSize: 11,
87
- fill: "text.secondary",
88
- fontWeight: 400
89
- }
90
- }), /* @__PURE__ */ r(G, {
91
- onItemClick: (e, { dataIndex: t, seriesId: o }) => w({
92
- dataIndex: t,
93
- seriesId: o.toString()
94
- }),
95
- slots: { bar: (e) => {
96
- const { ownerState: t, ...o } = e, S = a === void 0 || a === t.dataIndex ? t.color : `${t.color}50`;
97
- return /* @__PURE__ */ r(T, {
98
- ...o,
99
- color: S,
100
- data: i,
101
- series: {
102
- index: t.dataIndex,
103
- type: Number(t.id?.toString().split("-").pop() ?? 0)
104
- },
105
- style: {
106
- height: e.height,
107
- x: e.x,
108
- y: e.y,
109
- width: e.width
110
- }
111
- });
112
- } }
113
- })]
114
- })
115
- }), n && !l && n.length > 0 && /* @__PURE__ */ r(L, {
116
- legendItems: n,
117
- legendStyle: { ml: 24 }
118
- })]
119
- }) : /* @__PURE__ */ r(A, {});
120
- };
121
- export {
122
- Y as DoubleBarChartBlock
123
- };
124
-
125
- //# sourceMappingURL=DoubleBarChart.es.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DoubleBarChart.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/DoubleBarChart.tsx"],"sourcesContent":["import React from 'react'\n\nimport Box from '@mui/material/Box'\nimport Stack from '@mui/material/Stack'\n\nimport { BarPlot } from '@mui/x-charts/BarChart'\nimport { ChartContainer } from '@mui/x-charts/ChartContainer'\nimport { ChartsXAxis } from '@mui/x-charts/ChartsXAxis'\nimport { useTheme } from '@mui/material/styles'\n\nimport { useInsightsV2Store } from '../../../../common'\nimport { useContainerDimensions } from '../../../hooks/useContainerDimensions'\nimport { BlockProps } from '../../types'\n\nimport { CustomDoubleBarPlotMXUI } from './CustomDoubleBar'\nimport { Legend } from './ChartLegend'\nimport { getLayoutConfig } from './layout'\nimport { EmptyBarChart } from '../../../components/chartblocks/EmptyBarChart'\nimport type { DataSet } from '../../../../core/types/InsightsInstanceSlotData'\nimport type { LegendProps } from '../../../../core/types/InsightsInstanceSlotData'\n\nexport const DoubleBarChartBlock = ({\n payload: { instance_slot, instance_slot_data, widget_type },\n beatGuid = '',\n}: BlockProps) => {\n const { openChartDrilldown } = useInsightsV2Store()\n const isMini = widget_type === 'mini'\n const { variant } = instance_slot\n const { data_series, legends } = instance_slot_data\n const selectedTabIndex = (data_series! as DataSet[]).length - 1\n const barGapRatio = 0.005\n const categoryGapRatio = 0.16\n\n const theme = useTheme()\n const colors = getLayoutConfig(theme, variant).color\n\n const containerRef = React.useRef<HTMLDivElement>(null)\n const { height, width } = useContainerDimensions(containerRef)\n\n const handleBarClick = ({ dataIndex, seriesId }: { dataIndex: number; seriesId: string }) => {\n const seriesType = Number(seriesId.split('-').pop())\n // chartBarIndex carries the clicked date column (same meaning as\n // BarchartBlock's chartBarIndex); tabIndex carries the clicked sub-series\n // within that column (0 = main, 1 = comparison).\n openChartDrilldown(beatGuid, {\n chartBarIndex: dataIndex,\n tabIndex: seriesType,\n })\n }\n\n const legendItems = legends?.map((legend, index) => ({\n color: colors[index],\n ...legend,\n })) as LegendProps[]\n\n //\n return (data_series as DataSet[]).length > 0 ? (\n <Stack sx={{ mb: 0, width: '100%', p: 0 }}>\n <Box\n ref={containerRef}\n sx={{\n height: isMini ? 120 : 172,\n touchAction: 'pan-y',\n width: '100%',\n p: 0,\n m: 0,\n '& svg': {\n touchAction: 'pan-y',\n userSelect: 'none',\n },\n '& .recharts-wrapper': {\n touchAction: 'pan-y',\n },\n }}\n >\n <ChartContainer\n colors={colors}\n dataset={data_series as any[]}\n height={height}\n margin={{\n bottom: 16,\n left: 24,\n right: 24,\n top: 0,\n }}\n series={[\n { dataKey: 'main', type: 'bar' },\n { dataKey: 'comparison', type: 'bar' },\n ]}\n width={width}\n xAxis={[\n {\n barGapRatio,\n categoryGapRatio,\n dataKey: 'label',\n scaleType: 'band',\n },\n ]}\n yAxis={[{ width: 0 }]}\n >\n <ChartsXAxis\n disableTicks={false}\n slots={{\n axisTickLabel: ({ text, ...restProps }) => {\n const selectedLabel =\n selectedTabIndex !== undefined\n ? (instance_slot_data.data_series as DataSet[])[selectedTabIndex]?.label\n : undefined\n return (\n <text\n {...restProps}\n style={\n {\n ...restProps.style,\n fontWeight: selectedLabel === text ? 700 : 400,\n } as React.CSSProperties\n }\n >\n {text}\n </text>\n )\n },\n }}\n sx={{\n '.MuiChartsAxis-line': {\n stroke: 'border.darker',\n },\n }}\n tickLabelStyle={{\n fontSize: 11,\n fill: 'text.secondary',\n fontWeight: 400,\n }}\n />\n <BarPlot\n onItemClick={(_, { dataIndex, seriesId }) =>\n handleBarClick({ dataIndex, seriesId: seriesId.toString() })\n }\n slots={{\n bar: (props) => {\n const { ownerState, ...defaultProps } = props\n const isSelected =\n selectedTabIndex === undefined || selectedTabIndex === ownerState.dataIndex\n const barColor = isSelected ? ownerState.color : `${ownerState.color}50`\n\n return (\n <CustomDoubleBarPlotMXUI\n {...defaultProps}\n color={barColor}\n data={data_series as DataSet[]}\n series={{\n index: ownerState.dataIndex,\n type: Number(ownerState.id?.toString().split('-').pop() ?? 0),\n }}\n style={{\n height: props.height,\n x: props.x,\n y: props.y,\n width: props.width,\n }}\n />\n )\n },\n }}\n />\n </ChartContainer>\n </Box>\n\n {legendItems && !isMini && legendItems.length > 0 && (\n <Legend legendItems={legendItems} legendStyle={{ ml: 24 }} />\n )}\n </Stack>\n ) : (\n <EmptyBarChart />\n )\n}\n"],"mappings":"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"}