@mx-cartographer/experiences 9.4.59 → 9.4.60

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 (89) hide show
  1. package/CHANGELOG.md +34 -1
  2. package/dist/core/api/BeatApi.d.ts +6 -0
  3. package/dist/core/api/BeatApi.es.js +1 -1
  4. package/dist/core/api/BeatApi.es.js.map +1 -1
  5. package/dist/core/stores/CategoryStore.d.ts +7 -0
  6. package/dist/core/stores/CategoryStore.es.js +18 -7
  7. package/dist/core/stores/CategoryStore.es.js.map +1 -1
  8. package/dist/core/types/Beat.d.ts +6 -0
  9. package/dist/core/types/Beat.es.js.map +1 -1
  10. package/dist/core/types/Insights.d.ts +127 -5
  11. package/dist/core/types/InsightsInstanceSlotData.d.ts +1 -13
  12. package/dist/core/types/InsightsInstanceSlotData.es.js.map +1 -1
  13. package/dist/core/types/index.d.ts +1 -2
  14. package/dist/insights-v2/actionBlocks/ContactSupportActionBlock.d.ts +31 -0
  15. package/dist/insights-v2/actionBlocks/ContactSupportActionBlock.es.js +22 -0
  16. package/dist/insights-v2/actionBlocks/ContactSupportActionBlock.es.js.map +1 -0
  17. package/dist/insights-v2/actionBlocks/TransactionDetailsBlock/useTransactionDetailsBlock.d.ts +10 -9
  18. package/dist/insights-v2/actionBlocks/TransactionDetailsBlock/useTransactionDetailsBlock.es.js +7 -7
  19. package/dist/insights-v2/actionBlocks/TransactionDetailsBlock/useTransactionDetailsBlock.es.js.map +1 -1
  20. package/dist/insights-v2/beatActions.d.ts +7 -0
  21. package/dist/insights-v2/beatActions.es.js.map +1 -1
  22. package/dist/insights-v2/blocks/ChartBlocks/BarchartBlock/BarchartBlock.es.js +8 -8
  23. package/dist/insights-v2/blocks/ComponentBlocks/TransactionBlock/TransactionBlock.d.ts +30 -3
  24. package/dist/insights-v2/blocks/ComponentBlocks/TransactionBlock/TransactionBlock.es.js +67 -24
  25. package/dist/insights-v2/blocks/ComponentBlocks/TransactionBlock/TransactionBlock.es.js.map +1 -1
  26. package/dist/insights-v2/blocks/ComponentBlocks/TransactionBlock/index.d.ts +1 -1
  27. package/dist/insights-v2/components/BadgedTile.d.ts +22 -0
  28. package/dist/insights-v2/components/BadgedTile.es.js +46 -0
  29. package/dist/insights-v2/components/BadgedTile.es.js.map +1 -0
  30. package/dist/insights-v2/components/BaseLayout.es.js +113 -92
  31. package/dist/insights-v2/components/BaseLayout.es.js.map +1 -1
  32. package/dist/insights-v2/components/CompactInsightCard.d.ts +31 -0
  33. package/dist/insights-v2/components/CompactInsightCard.es.js +129 -0
  34. package/dist/insights-v2/components/CompactInsightCard.es.js.map +1 -0
  35. package/dist/insights-v2/components/Footer.d.ts +1 -4
  36. package/dist/insights-v2/components/Footer.es.js +30 -21
  37. package/dist/insights-v2/components/Footer.es.js.map +1 -1
  38. package/dist/insights-v2/components/Header.es.js +10 -10
  39. package/dist/insights-v2/components/Header.es.js.map +1 -1
  40. package/dist/insights-v2/components/InsightErrorCard.d.ts +19 -0
  41. package/dist/insights-v2/components/InsightErrorCard.es.js +45 -0
  42. package/dist/insights-v2/components/InsightErrorCard.es.js.map +1 -0
  43. package/dist/insights-v2/components/InsightTransactionRow.es.js +19 -15
  44. package/dist/insights-v2/components/InsightTransactionRow.es.js.map +1 -1
  45. package/dist/insights-v2/components/LogoFromGuid.d.ts +26 -0
  46. package/dist/insights-v2/components/LogoFromGuid.es.js +48 -0
  47. package/dist/insights-v2/components/LogoFromGuid.es.js.map +1 -0
  48. package/dist/insights-v2/components/StatusBadge.d.ts +16 -0
  49. package/dist/insights-v2/components/StatusBadge.es.js +29 -0
  50. package/dist/insights-v2/components/StatusBadge.es.js.map +1 -0
  51. package/dist/insights-v2/components/StatusPill.d.ts +11 -2
  52. package/dist/insights-v2/components/StatusPill.es.js +25 -13
  53. package/dist/insights-v2/components/StatusPill.es.js.map +1 -1
  54. package/dist/insights-v2/components/SubHeader.es.js +7 -5
  55. package/dist/insights-v2/components/SubHeader.es.js.map +1 -1
  56. package/dist/insights-v2/components/TransactionListCard.es.js +11 -11
  57. package/dist/insights-v2/components/TransactionListCard.es.js.map +1 -1
  58. package/dist/insights-v2/components/shared/EntityLogo.d.ts +26 -0
  59. package/dist/insights-v2/components/shared/EntityLogo.es.js +33 -0
  60. package/dist/insights-v2/components/shared/EntityLogo.es.js.map +1 -0
  61. package/dist/insights-v2/index.d.ts +6 -0
  62. package/dist/insights-v2/index.es.js +95 -81
  63. package/dist/insights-v2/mappings/actionBlocksKey.d.ts +1 -0
  64. package/dist/insights-v2/mappings/actionBlocksKey.es.js +2 -1
  65. package/dist/insights-v2/mappings/actionBlocksKey.es.js.map +1 -1
  66. package/dist/insights-v2/mappings/blocks.es.js +50 -44
  67. package/dist/insights-v2/mappings/blocks.es.js.map +1 -1
  68. package/dist/insights-v2/resolveInsightRender.d.ts +30 -0
  69. package/dist/insights-v2/resolveInsightRender.es.js +10 -0
  70. package/dist/insights-v2/resolveInsightRender.es.js.map +1 -0
  71. package/dist/microinsights/cards/InsightCard.es.js +83 -39
  72. package/dist/microinsights/cards/InsightCard.es.js.map +1 -1
  73. package/dist/microinsights/carousel/BeatList.es.js +24 -24
  74. package/dist/microinsights/carousel/BeatList.es.js.map +1 -1
  75. package/dist/notifications/components/NotificationBadge.es.js +12 -10
  76. package/dist/notifications/components/NotificationBadge.es.js.map +1 -1
  77. package/dist/notifications/components/NotificationCard.es.js +27 -18
  78. package/dist/notifications/components/NotificationCard.es.js.map +1 -1
  79. package/dist/transactions/components/shared/TransactionDetails.d.ts +7 -0
  80. package/dist/transactions/components/shared/TransactionDetails.es.js +159 -143
  81. package/dist/transactions/components/shared/TransactionDetails.es.js.map +1 -1
  82. package/dist/transactions/components/shared/TransactionInsightTag.d.ts +26 -0
  83. package/dist/transactions/components/shared/TransactionInsightTag.es.js +53 -0
  84. package/dist/transactions/components/shared/TransactionInsightTag.es.js.map +1 -0
  85. package/dist/transactions/components/shared/transactionlist/TransactionRow.es.js +30 -39
  86. package/dist/transactions/components/shared/transactionlist/TransactionRow.es.js.map +1 -1
  87. package/dist/transactions/components/shared/transactiontable/cells/AmountCell.es.js +15 -15
  88. package/dist/transactions/components/shared/transactiontable/cells/AmountCell.es.js.map +1 -1
  89. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Header.es.js","names":[],"sources":["../../../src/insights-v2/components/Header.tsx"],"sourcesContent":["import Stack from '@mui/material/Stack'\n\nimport { H3 } from '@mxenabled/mxui'\n\nimport SubHeader from './SubHeader'\nimport InsightOptionsMenu from './InsightOptionsMenu'\nimport { useBeatActions } from '../beatActions'\nimport type { Subtitle } from '../../core'\n\ninterface HeaderProps {\n isMini: boolean\n subtitle?: Subtitle\n title: string\n}\n\nconst Header = ({ isMini, subtitle, title }: HeaderProps) => {\n // The overflow menu appears only when the host wired a menu handler and this\n // isn't the compact/mini layout. Handlers are delivered via context.\n const { onMenuAction } = useBeatActions()\n\n return (\n <Stack sx={{ gap: 4, pb: 12, pl: 16, pr: 16, pt: 16 }}>\n <Stack sx={{ alignItems: 'center', flexDirection: 'row', justifyContent: 'space-between' }}>\n <H3>{title}</H3>\n {!isMini && onMenuAction && <InsightOptionsMenu />}\n </Stack>\n\n {/* Sub Header */}\n {subtitle && <SubHeader subtitle={subtitle} />}\n </Stack>\n )\n}\n\nexport default Header\n"],"mappings":";;;;;;AAeA,IAAM,IAAA,CAAU,EAAE,QAAA,GAAQ,UAAA,GAAU,OAAA,EAAA,MAAyB;AAG3D,QAAM,EAAE,cAAA,EAAA,IAAiB,EAAe;AAExC,SACE,gBAAA,EAAC,GAAD;AAAA,IAAO,IAAI;AAAA,MAAE,KAAK;AAAA,MAAG,IAAI;AAAA,MAAI,IAAI;AAAA,MAAI,IAAI;AAAA,MAAI,IAAI;AAAA,IAAG;AAAA,IAApD,UAAA,CACE,gBAAA,EAAC,GAAD;AAAA,MAAO,IAAI;AAAA,QAAE,YAAY;AAAA,QAAU,eAAe;AAAA,QAAO,gBAAgB;AAAA,MAAgB;AAAA,MAAzF,UAAA,CACE,gBAAA,EAAC,GAAD,EAAA,UAAK,EAAU,CAAA,GACd,CAAC,KAAU,KAAgB,gBAAA,EAAC,GAAD,CAAqB,CAAA,CAC5C;AAAA,IAGN,CAAA,GAAA,KAAY,gBAAA,EAAC,GAAD,EAAqB,UAAA,EAAW,CAAA,CACxC;AAAA;AAEX"}
1
+ {"version":3,"file":"Header.es.js","names":[],"sources":["../../../src/insights-v2/components/Header.tsx"],"sourcesContent":["import Stack from '@mui/material/Stack'\n\nimport { H3 } from '@mxenabled/mxui'\n\nimport SubHeader from './SubHeader'\nimport InsightOptionsMenu from './InsightOptionsMenu'\nimport { useBeatActions } from '../beatActions'\nimport type { Subtitle } from '../../core'\n\ninterface HeaderProps {\n isMini: boolean\n subtitle?: Subtitle\n title: string\n}\n\nconst Header = ({ isMini, subtitle, title }: HeaderProps) => {\n // The overflow menu appears only when the host wired a menu handler and this\n // isn't the compact/mini layout. Handlers are delivered via context.\n const { onMenuAction } = useBeatActions()\n\n return (\n <Stack sx={{ gap: 4, pb: 12, pl: 16, pr: 16, pt: 16 }}>\n <Stack\n sx={{ alignItems: 'flex-start', flexDirection: 'row', justifyContent: 'space-between' }}\n >\n <H3>{title}</H3>\n {!isMini && onMenuAction && <InsightOptionsMenu />}\n </Stack>\n\n {/* Sub Header */}\n {subtitle && <SubHeader subtitle={subtitle} />}\n </Stack>\n )\n}\n\nexport default Header\n"],"mappings":";;;;;;AAeA,IAAM,IAAA,CAAU,EAAE,QAAA,GAAQ,UAAA,GAAU,OAAA,EAAA,MAAyB;AAG3D,QAAM,EAAE,cAAA,EAAA,IAAiB,EAAe;AAExC,SACE,gBAAA,EAAC,GAAD;AAAA,IAAO,IAAI;AAAA,MAAE,KAAK;AAAA,MAAG,IAAI;AAAA,MAAI,IAAI;AAAA,MAAI,IAAI;AAAA,MAAI,IAAI;AAAA,IAAG;AAAA,IAApD,UAAA,CACE,gBAAA,EAAC,GAAD;AAAA,MACE,IAAI;AAAA,QAAE,YAAY;AAAA,QAAc,eAAe;AAAA,QAAO,gBAAgB;AAAA,MAAgB;AAAA,MADxF,UAAA,CAGE,gBAAA,EAAC,GAAD,EAAA,UAAK,EAAU,CAAA,GACd,CAAC,KAAU,KAAgB,gBAAA,EAAC,GAAD,CAAqB,CAAA,CAC5C;AAAA,IAGN,CAAA,GAAA,KAAY,gBAAA,EAAC,GAAD,EAAqB,UAAA,EAAW,CAAA,CACxC;AAAA;AAEX"}
@@ -0,0 +1,19 @@
1
+ import { Beat } from '../../core';
2
+ export interface InsightErrorCardProps {
3
+ /** The flagged beat whose envelope is missing. Only `guid` and `template` are read. */
4
+ beat: Pick<Beat, 'guid' | 'template'>;
5
+ /**
6
+ * `card` (default) draws the feed card frame. `plain` renders only the message, for a surface
7
+ * that already supplies its own frame (the details-drawer slot above the account block).
8
+ */
9
+ variant?: 'card' | 'plain';
10
+ }
11
+ /**
12
+ * The `error` branch of `resolveInsightRender` (`insights_v2.2.md` §7.1): a flagged insight whose
13
+ * envelope did not arrive. Shows the copy store's generic error, never a CTA, and reports the
14
+ * failure once per beat (guid + template) through the host's error handler so on-call sees it —
15
+ * the legacy copy fields on such a beat are filled from the same V2 copy block, so without this the
16
+ * beat would render as a plausible-looking legacy card and the failure would never surface.
17
+ */
18
+ declare const InsightErrorCard: ({ beat, variant }: InsightErrorCardProps) => import("react/jsx-runtime").JSX.Element;
19
+ export default InsightErrorCard;
@@ -0,0 +1,45 @@
1
+ import { useError as d, useGlobalCopyStore as m } from "../../common/context/hooks.es.js";
2
+ import { useEffect as p, useRef as a } from "react";
3
+ import { Text as u } from "@mxenabled/mxui";
4
+ import { jsx as e } from "react/jsx-runtime";
5
+ import c from "@mui/material/Box";
6
+ import l from "@mui/material/Card";
7
+ var E = ({ beat: r, variant: s = "card" }) => {
8
+ const { onError: o } = d(), n = m(), t = a(null);
9
+ p(() => {
10
+ t.current !== r.guid && (t.current = r.guid, o(/* @__PURE__ */ new Error(`Insights 2.0 beat ${r.guid} (${r.template}) is flagged but has no envelope`), {
11
+ beat_guid: r.guid,
12
+ template: r.template
13
+ }, "insights_v2_missing_envelope"));
14
+ }, [
15
+ r.guid,
16
+ r.template,
17
+ o
18
+ ]);
19
+ const i = /* @__PURE__ */ e(u, {
20
+ color: "text.secondary",
21
+ variant: "body2",
22
+ children: n.common?.error_message ?? ""
23
+ });
24
+ return s === "plain" ? /* @__PURE__ */ e(c, {
25
+ "data-testid": "insight-error-card",
26
+ sx: {
27
+ px: 16,
28
+ py: 12
29
+ },
30
+ children: i
31
+ }) : /* @__PURE__ */ e(l, {
32
+ "data-testid": "insight-error-card",
33
+ sx: {
34
+ mb: 16,
35
+ px: 16,
36
+ py: 16
37
+ },
38
+ children: i
39
+ });
40
+ };
41
+ export {
42
+ E as default
43
+ };
44
+
45
+ //# sourceMappingURL=InsightErrorCard.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InsightErrorCard.es.js","names":[],"sources":["../../../src/insights-v2/components/InsightErrorCard.tsx"],"sourcesContent":["import { useEffect, useRef } from 'react'\n\nimport Box from '@mui/material/Box'\nimport Card from '@mui/material/Card'\n\nimport { Text } from '@mxenabled/mxui'\n\nimport { useError, useGlobalCopyStore } from '../../common'\nimport type { Beat } from '../../core'\n\nexport interface InsightErrorCardProps {\n /** The flagged beat whose envelope is missing. Only `guid` and `template` are read. */\n beat: Pick<Beat, 'guid' | 'template'>\n /**\n * `card` (default) draws the feed card frame. `plain` renders only the message, for a surface\n * that already supplies its own frame (the details-drawer slot above the account block).\n */\n variant?: 'card' | 'plain'\n}\n\n/**\n * The `error` branch of `resolveInsightRender` (`insights_v2.2.md` §7.1): a flagged insight whose\n * envelope did not arrive. Shows the copy store's generic error, never a CTA, and reports the\n * failure once per beat (guid + template) through the host's error handler so on-call sees it —\n * the legacy copy fields on such a beat are filled from the same V2 copy block, so without this the\n * beat would render as a plausible-looking legacy card and the failure would never surface.\n */\nconst InsightErrorCard = ({ beat, variant = 'card' }: InsightErrorCardProps) => {\n const { onError } = useError()\n const copy = useGlobalCopyStore()\n const reportedGuid = useRef<string | null>(null)\n\n useEffect(() => {\n if (reportedGuid.current === beat.guid) return\n reportedGuid.current = beat.guid\n\n onError(\n new Error(`Insights 2.0 beat ${beat.guid} (${beat.template}) is flagged but has no envelope`),\n { beat_guid: beat.guid, template: beat.template },\n 'insights_v2_missing_envelope',\n )\n }, [beat.guid, beat.template, onError])\n\n const message = (\n <Text color=\"text.secondary\" variant=\"body2\">\n {copy.common?.error_message ?? ''}\n </Text>\n )\n\n if (variant === 'plain') {\n return (\n <Box data-testid=\"insight-error-card\" sx={{ px: 16, py: 12 }}>\n {message}\n </Box>\n )\n }\n\n return (\n <Card data-testid=\"insight-error-card\" sx={{ mb: 16, px: 16, py: 16 }}>\n {message}\n </Card>\n )\n}\n\nexport default InsightErrorCard\n"],"mappings":";;;;;;AA2BA,IAAM,IAAA,CAAoB,EAAE,MAAA,GAAM,SAAA,IAAU,OAAA,MAAoC;AAC9E,QAAM,EAAE,SAAA,EAAA,IAAY,EAAS,GACvB,IAAO,EAAmB,GAC1B,IAAe,EAAsB,IAAI;AAE/C,EAAA,EAAA,MAAgB;AACd,IAAI,EAAa,YAAY,EAAK,SAClC,EAAa,UAAU,EAAK,MAE5B,EACE,oBAAI,MAAM,qBAAqB,EAAK,IAAA,KAAS,EAAK,QAAA,kCAA0C,GAC5F;AAAA,MAAE,WAAW,EAAK;AAAA,MAAM,UAAU,EAAK;AAAA,IAAS,GAChD,8BACF;AAAA,EACF,GAAG;AAAA,IAAC,EAAK;AAAA,IAAM,EAAK;AAAA,IAAU;AAAA,EAAO,CAAC;AAEtC,QAAM,IACJ,gBAAA,EAAC,GAAD;AAAA,IAAM,OAAM;AAAA,IAAiB,SAAQ;AAAA,IAClC,UAAA,EAAK,QAAQ,iBAAiB;AAAA,EAC3B,CAAA;AAGR,SAAI,MAAY,UAEZ,gBAAA,EAAC,GAAD;AAAA,IAAK,eAAY;AAAA,IAAqB,IAAI;AAAA,MAAE,IAAI;AAAA,MAAI,IAAI;AAAA,IAAG;AAAA,IACxD,UAAA;AAAA,EACE,CAAA,IAKP,gBAAA,EAAC,GAAD;AAAA,IAAM,eAAY;AAAA,IAAqB,IAAI;AAAA,MAAE,IAAI;AAAA,MAAI,IAAI;AAAA,MAAI,IAAI;AAAA,IAAG;AAAA,IACjE,UAAA;AAAA,EACG,CAAA;AAEV"}
@@ -1,8 +1,8 @@
1
1
  import t from "@mui/material/Stack";
2
- import { Text as e } from "@mxenabled/mxui";
3
- import { jsx as r, jsxs as i } from "react/jsx-runtime";
4
- import d from "@mui/material/Box";
5
- var p = ({ amount: n, amountColor: a = "text.primary", leading: o, subtitle: l, title: x, sx: c }) => /* @__PURE__ */ i(t, {
2
+ import { Text as i } from "@mxenabled/mxui";
3
+ import { jsx as r, jsxs as e } from "react/jsx-runtime";
4
+ import m from "@mui/material/Box";
5
+ var f = ({ amount: o, amountColor: a = "text.primary", leading: n, subtitle: l, title: x, sx: c }) => /* @__PURE__ */ e(t, {
6
6
  sx: {
7
7
  alignItems: "flex-start",
8
8
  flexDirection: "row",
@@ -12,7 +12,7 @@ var p = ({ amount: n, amountColor: a = "text.primary", leading: o, subtitle: l,
12
12
  width: "100%",
13
13
  ...c
14
14
  },
15
- children: [/* @__PURE__ */ i(t, {
15
+ children: [/* @__PURE__ */ e(t, {
16
16
  sx: {
17
17
  alignItems: "center",
18
18
  flexDirection: "row",
@@ -20,33 +20,37 @@ var p = ({ amount: n, amountColor: a = "text.primary", leading: o, subtitle: l,
20
20
  gap: 12,
21
21
  minWidth: 0
22
22
  },
23
- children: [o && /* @__PURE__ */ r(d, {
23
+ children: [n && /* @__PURE__ */ r(m, {
24
24
  sx: { flexShrink: 0 },
25
- children: o
26
- }), /* @__PURE__ */ i(t, {
25
+ children: n
26
+ }), /* @__PURE__ */ e(t, {
27
27
  sx: { minWidth: 0 },
28
- children: [/* @__PURE__ */ r(e, {
28
+ children: [/* @__PURE__ */ r(i, {
29
29
  bold: !0,
30
30
  truncate: !0,
31
31
  variant: "body1",
32
32
  children: x
33
- }), /* @__PURE__ */ r(e, {
34
- color: "text.secondary",
33
+ }), /* @__PURE__ */ r(i, {
34
+ color: "text.primary",
35
35
  truncate: !0,
36
36
  variant: "caption",
37
37
  children: l
38
38
  })]
39
39
  })]
40
- }), /* @__PURE__ */ r(e, {
40
+ }), /* @__PURE__ */ r(i, {
41
41
  bold: !0,
42
42
  color: a,
43
- sx: { flexShrink: 0 },
43
+ sx: {
44
+ flexShrink: 0,
45
+ fontVariantNumeric: "lining-nums tabular-nums",
46
+ letterSpacing: "-0.15px"
47
+ },
44
48
  variant: "body1",
45
- children: n
49
+ children: o
46
50
  })]
47
51
  });
48
52
  export {
49
- p as default
53
+ f as default
50
54
  };
51
55
 
52
56
  //# sourceMappingURL=InsightTransactionRow.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"InsightTransactionRow.es.js","names":[],"sources":["../../../src/insights-v2/components/InsightTransactionRow.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\n\nimport Box from '@mui/material/Box'\nimport Stack from '@mui/material/Stack'\nimport type { SxProps } from '@mui/material/styles'\n\nimport { Text } from '@mxenabled/mxui'\n\nexport interface InsightTransactionRowProps {\n /** Leading visual: merchant/institution logo, category icon, or date badge. */\n leading?: ReactNode\n /** Primary line (e.g. merchant, payee, transaction name). */\n title: ReactNode\n /** Secondary line beneath the title (e.g. category). */\n subtitle: ReactNode\n /** Trailing amount, pre-formatted by the caller. */\n amount: ReactNode\n /** Theme token for the amount text (e.g. 'success.main' for credits). */\n amountColor?: string\n sx?: SxProps\n}\n\n/**\n * A single transaction/list row for the insights-v2 transaction-list family:\n * leading visual + title/subtitle on the left, amount on the right. Named\n * `InsightTransactionRow` to avoid colliding with the transactions widget's\n * public `TransactionRow` export.\n */\nconst InsightTransactionRow = ({\n amount,\n amountColor = 'text.primary',\n leading,\n subtitle,\n title,\n sx,\n}: InsightTransactionRowProps) => (\n <Stack\n sx={{\n // The amount shares the title's top line while the subtitle sits below, so\n // the row is top-aligned and the inner left group is centered.\n alignItems: 'flex-start',\n flexDirection: 'row',\n gap: 16,\n px: 16,\n py: 14,\n width: '100%',\n ...sx,\n }}\n >\n <Stack sx={{ alignItems: 'center', flexDirection: 'row', flexGrow: 1, gap: 12, minWidth: 0 }}>\n {leading && <Box sx={{ flexShrink: 0 }}>{leading}</Box>}\n <Stack sx={{ minWidth: 0 }}>\n <Text bold={true} truncate={true} variant=\"body1\">\n {title}\n </Text>\n <Text color=\"text.secondary\" truncate={true} variant=\"caption\">\n {subtitle}\n </Text>\n </Stack>\n </Stack>\n <Text bold={true} color={amountColor} sx={{ flexShrink: 0 }} variant=\"body1\">\n {amount}\n </Text>\n </Stack>\n)\n\nexport default InsightTransactionRow\n"],"mappings":";;;;AA4BA,IAAM,IAAA,CAAyB,EAC7B,QAAA,GACA,aAAA,IAAc,gBACd,SAAA,GACA,UAAA,GACA,OAAA,GACA,IAAA,EAAA,MAEA,gBAAA,EAAC,GAAD;AAAA,EACE,IAAI;AAAA,IAGF,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,GAAG;AAAA,EACL;AAAA,EAXF,UAAA,CAaE,gBAAA,EAAC,GAAD;AAAA,IAAO,IAAI;AAAA,MAAE,YAAY;AAAA,MAAU,eAAe;AAAA,MAAO,UAAU;AAAA,MAAG,KAAK;AAAA,MAAI,UAAU;AAAA,IAAE;AAAA,IAA3F,UAAA,CACG,KAAW,gBAAA,EAAC,GAAD;AAAA,MAAK,IAAI,EAAE,YAAY,EAAE;AAAA,MAAI,UAAA;AAAA,IAAa,CAAA,GACtD,gBAAA,EAAC,GAAD;AAAA,MAAO,IAAI,EAAE,UAAU,EAAE;AAAA,MAAzB,UAAA,CACE,gBAAA,EAAC,GAAD;AAAA,QAAM,MAAM;AAAA,QAAM,UAAU;AAAA,QAAM,SAAQ;AAAA,QACvC,UAAA;AAAA,MACG,CAAA,GACN,gBAAA,EAAC,GAAD;AAAA,QAAM,OAAM;AAAA,QAAiB,UAAU;AAAA,QAAM,SAAQ;AAAA,QAClD,UAAA;AAAA,MACG,CAAA,CACD;AAAA,IACF,CAAA,CAAA;AAAA,EACP,CAAA,GAAA,gBAAA,EAAC,GAAD;AAAA,IAAM,MAAM;AAAA,IAAM,OAAO;AAAA,IAAa,IAAI,EAAE,YAAY,EAAE;AAAA,IAAG,SAAQ;AAAA,IAClE,UAAA;AAAA,EACG,CAAA,CACD"}
1
+ {"version":3,"file":"InsightTransactionRow.es.js","names":[],"sources":["../../../src/insights-v2/components/InsightTransactionRow.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\n\nimport Box from '@mui/material/Box'\nimport Stack from '@mui/material/Stack'\nimport type { SxProps } from '@mui/material/styles'\n\nimport { Text } from '@mxenabled/mxui'\n\nexport interface InsightTransactionRowProps {\n /** Leading visual: merchant/institution logo, category icon, or date badge. */\n leading?: ReactNode\n /** Primary line (e.g. merchant, payee, transaction name). */\n title: ReactNode\n /** Secondary line beneath the title (e.g. category). */\n subtitle: ReactNode\n /** Trailing amount, pre-formatted by the caller. */\n amount: ReactNode\n /** Theme token for the amount text (e.g. 'success.main' for credits). */\n amountColor?: string\n sx?: SxProps\n}\n\n/**\n * A single transaction/list row for the insights-v2 transaction-list family:\n * leading visual + title/subtitle on the left, amount on the right. Named\n * `InsightTransactionRow` to avoid colliding with the transactions widget's\n * public `TransactionRow` export.\n */\nconst InsightTransactionRow = ({\n amount,\n amountColor = 'text.primary',\n leading,\n subtitle,\n title,\n sx,\n}: InsightTransactionRowProps) => (\n <Stack\n sx={{\n // The amount shares the title's top line while the subtitle sits below, so\n // the row is top-aligned and the inner left group is centered.\n alignItems: 'flex-start',\n flexDirection: 'row',\n gap: 16,\n px: 16,\n py: 14,\n width: '100%',\n ...sx,\n }}\n >\n <Stack sx={{ alignItems: 'center', flexDirection: 'row', flexGrow: 1, gap: 12, minWidth: 0 }}>\n {leading && <Box sx={{ flexShrink: 0 }}>{leading}</Box>}\n <Stack sx={{ minWidth: 0 }}>\n <Text bold={true} truncate={true} variant=\"body1\">\n {title}\n </Text>\n <Text color=\"text.primary\" truncate={true} variant=\"caption\">\n {subtitle}\n </Text>\n </Stack>\n </Stack>\n {/* Figma `typography/body1 (bold tabular)`: tabular figures so amounts align column-wise. */}\n <Text\n bold={true}\n color={amountColor}\n sx={{\n flexShrink: 0,\n fontVariantNumeric: 'lining-nums tabular-nums',\n letterSpacing: '-0.15px',\n }}\n variant=\"body1\"\n >\n {amount}\n </Text>\n </Stack>\n)\n\nexport default InsightTransactionRow\n"],"mappings":";;;;AA4BA,IAAM,IAAA,CAAyB,EAC7B,QAAA,GACA,aAAA,IAAc,gBACd,SAAA,GACA,UAAA,GACA,OAAA,GACA,IAAA,EAAA,MAEA,gBAAA,EAAC,GAAD;AAAA,EACE,IAAI;AAAA,IAGF,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,GAAG;AAAA,EACL;AAAA,EAXF,UAAA,CAaE,gBAAA,EAAC,GAAD;AAAA,IAAO,IAAI;AAAA,MAAE,YAAY;AAAA,MAAU,eAAe;AAAA,MAAO,UAAU;AAAA,MAAG,KAAK;AAAA,MAAI,UAAU;AAAA,IAAE;AAAA,IAA3F,UAAA,CACG,KAAW,gBAAA,EAAC,GAAD;AAAA,MAAK,IAAI,EAAE,YAAY,EAAE;AAAA,MAAI,UAAA;AAAA,IAAa,CAAA,GACtD,gBAAA,EAAC,GAAD;AAAA,MAAO,IAAI,EAAE,UAAU,EAAE;AAAA,MAAzB,UAAA,CACE,gBAAA,EAAC,GAAD;AAAA,QAAM,MAAM;AAAA,QAAM,UAAU;AAAA,QAAM,SAAQ;AAAA,QACvC,UAAA;AAAA,MACG,CAAA,GACN,gBAAA,EAAC,GAAD;AAAA,QAAM,OAAM;AAAA,QAAe,UAAU;AAAA,QAAM,SAAQ;AAAA,QAChD,UAAA;AAAA,MACG,CAAA,CACD;AAAA,IACF,CAAA,CAAA;AAAA,EAEP,CAAA,GAAA,gBAAA,EAAC,GAAD;AAAA,IACE,MAAM;AAAA,IACN,OAAO;AAAA,IACP,IAAI;AAAA,MACF,YAAY;AAAA,MACZ,oBAAoB;AAAA,MACpB,eAAe;AAAA,IACjB;AAAA,IACA,SAAQ;AAAA,IAEP,UAAA;AAAA,EACG,CAAA,CACD"}
@@ -0,0 +1,26 @@
1
+ import { LogoRef } from '../../core';
2
+ export declare const isLogoGuid: (guid?: string | null) => guid is string;
3
+ export interface LogoFromGuidProps {
4
+ /** The envelope's logo object: `{ guid, fallback_guid?, alt? }`. */
5
+ logo?: Pick<LogoRef, 'alt' | 'fallback_guid' | 'guid'> | null;
6
+ /** Rendered square size in px (32 on rows, 40 on the compact card, 33 on the notification row). */
7
+ size: number;
8
+ className?: string;
9
+ }
10
+ /**
11
+ * One component for every V2 logo. The envelope sends a single `{ guid, fallback_guid?, alt? }`
12
+ * object whose prefix says what it is; this maps it onto the mxui component's props and renders
13
+ * nothing — never a guess — for anything else (`PARENT-ENTITY`, an `ACT-`/`BGT-` guid, an empty guid).
14
+ *
15
+ * The fallback chain is mxui's, not ours: asset for `guid` → category tile for `fallback_guid`
16
+ * (`MerchantLogo`'s `categoryGuid`, applied only when it is a `CAT-` guid because a category tile is
17
+ * the only fallback `MerchantLogo` has) → `alt`. Nothing here probes whether an asset exists.
18
+ *
19
+ * Categories are walked up to their top-level parent before reaching mxui: `CategoryIcon` only knows
20
+ * the top-level guids and silently shows the Uncategorized glyph for a sub-category (identity until
21
+ * categories load). That applies to a `CAT-` logo and to a merchant's `fallback_guid` alike.
22
+ */
23
+ declare const LogoFromGuid: (({ className, logo, size }: LogoFromGuidProps) => import("react/jsx-runtime").JSX.Element | null) & {
24
+ displayName: string;
25
+ };
26
+ export default LogoFromGuid;
@@ -0,0 +1,48 @@
1
+ import { useCategoryStore as a } from "../../common/context/hooks.es.js";
2
+ import { logoFromRef as d } from "./shared/EntityLogo.es.js";
3
+ import { observer as g } from "mobx-react-lite";
4
+ import { CategoryIcon as l, InstitutionLogo as m, MerchantLogo as c } from "@mxenabled/mxui";
5
+ import { jsx as n } from "react/jsx-runtime";
6
+ import f from "@mui/material/Box";
7
+ var s = /^(MCH|CAT|INS)-/, _ = (o) => !!o && s.test(o), C = g(({ className: o, logo: i, size: r }) => {
8
+ const { getTopLevelCategoryGuid: u } = a();
9
+ if (!i || !_(i.guid)) return null;
10
+ const t = d({
11
+ alt: i.alt,
12
+ fallback_guid: i.fallback_guid,
13
+ guid: i.guid
14
+ });
15
+ if (!t) return null;
16
+ let e = null;
17
+ return t.merchant_guid ? e = /* @__PURE__ */ n(c, {
18
+ alt: t.merchant_name ?? "",
19
+ categoryGuid: t.category_guid ? u(t.category_guid) : "",
20
+ merchantGuid: t.merchant_guid,
21
+ size: r
22
+ }) : t.institution_guid ? e = /* @__PURE__ */ n(m, {
23
+ alt: t.institution_name ?? "",
24
+ institutionGuid: t.institution_guid,
25
+ size: r
26
+ }) : t.category_guid && (e = /* @__PURE__ */ n(l, {
27
+ categoryGuid: u(t.category_guid),
28
+ size: r
29
+ })), e ? /* @__PURE__ */ n(f, {
30
+ className: o,
31
+ "data-testid": "logo-from-guid",
32
+ sx: {
33
+ alignItems: "center",
34
+ display: "flex",
35
+ flexShrink: 0,
36
+ height: r,
37
+ justifyContent: "center",
38
+ width: r
39
+ },
40
+ children: e
41
+ }) : null;
42
+ });
43
+ export {
44
+ C as default,
45
+ _ as isLogoGuid
46
+ };
47
+
48
+ //# sourceMappingURL=LogoFromGuid.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LogoFromGuid.es.js","names":[],"sources":["../../../src/insights-v2/components/LogoFromGuid.tsx"],"sourcesContent":["import { observer } from 'mobx-react-lite'\n\nimport Box from '@mui/material/Box'\n\nimport { CategoryIcon, InstitutionLogo, MerchantLogo } from '@mxenabled/mxui'\n\nimport { useCategoryStore } from '../../common'\nimport type { LogoRef } from '../../core'\nimport { logoFromRef } from './shared/EntityLogo'\n\n/**\n * The guid prefixes that name a logo entity. A prefix heuristic by design: the V2 envelope carries\n * the entity only in the guid, and the notification row relies on non-insight rows carrying account\n * or budget guids and legacy insight rows carrying the `\"PARENT-ENTITY\"` sentinel. Exported beside\n * the component so a caller's branch (`NotificationCard`) and the dispatch here cannot drift apart.\n */\nconst LOGO_GUID_PREFIX = /^(MCH|CAT|INS)-/\n\nexport const isLogoGuid = (guid?: string | null): guid is string =>\n !!guid && LOGO_GUID_PREFIX.test(guid)\n\nexport interface LogoFromGuidProps {\n /** The envelope's logo object: `{ guid, fallback_guid?, alt? }`. */\n logo?: Pick<LogoRef, 'alt' | 'fallback_guid' | 'guid'> | null\n /** Rendered square size in px (32 on rows, 40 on the compact card, 33 on the notification row). */\n size: number\n className?: string\n}\n\n/**\n * One component for every V2 logo. The envelope sends a single `{ guid, fallback_guid?, alt? }`\n * object whose prefix says what it is; this maps it onto the mxui component's props and renders\n * nothing — never a guess — for anything else (`PARENT-ENTITY`, an `ACT-`/`BGT-` guid, an empty guid).\n *\n * The fallback chain is mxui's, not ours: asset for `guid` → category tile for `fallback_guid`\n * (`MerchantLogo`'s `categoryGuid`, applied only when it is a `CAT-` guid because a category tile is\n * the only fallback `MerchantLogo` has) → `alt`. Nothing here probes whether an asset exists.\n *\n * Categories are walked up to their top-level parent before reaching mxui: `CategoryIcon` only knows\n * the top-level guids and silently shows the Uncategorized glyph for a sub-category (identity until\n * categories load). That applies to a `CAT-` logo and to a merchant's `fallback_guid` alike.\n */\nconst LogoFromGuid = observer(({ className, logo, size }: LogoFromGuidProps) => {\n const { getTopLevelCategoryGuid } = useCategoryStore()\n\n if (!logo || !isLogoGuid(logo.guid)) return null\n\n // Guid-only on purpose: `logoFromRef` lets a status `icon` win over `guid`, which is right for a\n // row but would silently turn this component into an icon renderer.\n const resolved = logoFromRef({\n alt: logo.alt,\n fallback_guid: logo.fallback_guid,\n guid: logo.guid,\n })\n\n if (!resolved) return null\n\n let content: React.ReactNode = null\n\n if (resolved.merchant_guid) {\n content = (\n <MerchantLogo\n alt={resolved.merchant_name ?? ''}\n categoryGuid={resolved.category_guid ? getTopLevelCategoryGuid(resolved.category_guid) : ''}\n merchantGuid={resolved.merchant_guid}\n size={size}\n />\n )\n } else if (resolved.institution_guid) {\n content = (\n <InstitutionLogo\n alt={resolved.institution_name ?? ''}\n institutionGuid={resolved.institution_guid}\n size={size}\n />\n )\n } else if (resolved.category_guid) {\n content = (\n <CategoryIcon categoryGuid={getTopLevelCategoryGuid(resolved.category_guid)} size={size} />\n )\n }\n\n if (!content) return null\n\n return (\n <Box\n className={className}\n data-testid=\"logo-from-guid\"\n sx={{\n alignItems: 'center',\n display: 'flex',\n flexShrink: 0,\n height: size,\n justifyContent: 'center',\n width: size,\n }}\n >\n {content}\n </Box>\n )\n})\n\nexport default LogoFromGuid\n"],"mappings":";;;;;;AAgBA,IAAM,IAAmB,mBAEZ,IAAA,CAAc,MACzB,CAAC,CAAC,KAAQ,EAAiB,KAAK,CAAI,GAuBhC,IAAe,EAAA,CAAU,EAAE,WAAA,GAAW,MAAA,GAAM,MAAA,EAAA,MAA8B;AAC9E,QAAM,EAAE,yBAAA,EAAA,IAA4B,EAAiB;AAErD,MAAI,CAAC,KAAQ,CAAC,EAAW,EAAK,IAAI,EAAG,QAAO;AAI5C,QAAM,IAAW,EAAY;AAAA,IAC3B,KAAK,EAAK;AAAA,IACV,eAAe,EAAK;AAAA,IACpB,MAAM,EAAK;AAAA,EACb,CAAC;AAED,MAAI,CAAC,EAAU,QAAO;AAEtB,MAAI,IAA2B;AAyB/B,SAvBI,EAAS,gBACX,IACE,gBAAA,EAAC,GAAD;AAAA,IACE,KAAK,EAAS,iBAAiB;AAAA,IAC/B,cAAc,EAAS,gBAAgB,EAAwB,EAAS,aAAa,IAAI;AAAA,IACzF,cAAc,EAAS;AAAA,IACjB,MAAA;AAAA,EACP,CAAA,IAEM,EAAS,mBAClB,IACE,gBAAA,EAAC,GAAD;AAAA,IACE,KAAK,EAAS,oBAAoB;AAAA,IAClC,iBAAiB,EAAS;AAAA,IACpB,MAAA;AAAA,EACP,CAAA,IAEM,EAAS,kBAClB,IACE,gBAAA,EAAC,GAAD;AAAA,IAAc,cAAc,EAAwB,EAAS,aAAa;AAAA,IAAS,MAAA;AAAA,EAAO,CAAA,IAIzF,IAGH,gBAAA,EAAC,GAAD;AAAA,IACa,WAAA;AAAA,IACX,eAAY;AAAA,IACZ,IAAI;AAAA,MACF,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,gBAAgB;AAAA,MAChB,OAAO;AAAA,IACT;AAAA,IAEC,UAAA;AAAA,EACE,CAAA,IAhBc;AAkBvB,CAAC"}
@@ -0,0 +1,16 @@
1
+ export type StatusTone = 'warning' | 'error';
2
+ interface StatusBadgeProps {
3
+ /** Which palette the glyph takes: `warning` (Large Transaction) or `error` (Duplicate Payment). */
4
+ tone: StatusTone;
5
+ /**
6
+ * Accessible name. Omit — the default — to mark the badge decorative: today the envelope carries
7
+ * no words for it, and the card's description already says what it means.
8
+ */
9
+ label?: string;
10
+ }
11
+ /**
12
+ * The small status glyph badging a `<BadgedTile>`'s corner: a filled `error` symbol on a white
13
+ * disc, tinted by `tone`. Figma 1941:111897 (Embedded | Large Transaction).
14
+ */
15
+ declare const StatusBadge: ({ label, tone }: StatusBadgeProps) => import("react/jsx-runtime").JSX.Element;
16
+ export default StatusBadge;
@@ -0,0 +1,29 @@
1
+ import { Icon as a } from "@mxenabled/mx-icons";
2
+ import { jsx as t } from "react/jsx-runtime";
3
+ import i from "@mui/material/Box";
4
+ var e = 20, m = ({ label: r, tone: o }) => /* @__PURE__ */ t(i, {
5
+ "aria-hidden": r ? void 0 : !0,
6
+ "aria-label": r,
7
+ "data-testid": "status-badge",
8
+ role: r ? "img" : void 0,
9
+ sx: {
10
+ alignItems: "center",
11
+ bgcolor: "background.paper",
12
+ borderRadius: "100px",
13
+ display: "flex",
14
+ height: e,
15
+ justifyContent: "center",
16
+ width: e
17
+ },
18
+ children: /* @__PURE__ */ t(a, {
19
+ color: o,
20
+ fill: !0,
21
+ name: "error",
22
+ size: e
23
+ })
24
+ });
25
+ export {
26
+ m as default
27
+ };
28
+
29
+ //# sourceMappingURL=StatusBadge.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatusBadge.es.js","names":[],"sources":["../../../src/insights-v2/components/StatusBadge.tsx"],"sourcesContent":["import Box from '@mui/material/Box'\n\nimport { Icon } from '@mxenabled/mx-icons'\n\n/** Figma 1941:111897: the badge is 20px, drawn on the card's surface so it reads over the tile. */\nconst BADGE_SIZE = 20\n\nexport type StatusTone = 'warning' | 'error'\n\ninterface StatusBadgeProps {\n /** Which palette the glyph takes: `warning` (Large Transaction) or `error` (Duplicate Payment). */\n tone: StatusTone\n /**\n * Accessible name. Omit — the default — to mark the badge decorative: today the envelope carries\n * no words for it, and the card's description already says what it means.\n */\n label?: string\n}\n\n/**\n * The small status glyph badging a `<BadgedTile>`'s corner: a filled `error` symbol on a white\n * disc, tinted by `tone`. Figma 1941:111897 (Embedded | Large Transaction).\n */\nconst StatusBadge = ({ label, tone }: StatusBadgeProps) => (\n <Box\n aria-hidden={label ? undefined : true}\n aria-label={label}\n data-testid=\"status-badge\"\n role={label ? 'img' : undefined}\n sx={{\n alignItems: 'center',\n // The disc behind the glyph: the symbol's own ring is transparent over the tile without it.\n bgcolor: 'background.paper',\n borderRadius: '100px',\n display: 'flex',\n height: BADGE_SIZE,\n justifyContent: 'center',\n width: BADGE_SIZE,\n }}\n >\n <Icon color={tone} fill={true} name=\"error\" size={BADGE_SIZE} />\n </Box>\n)\n\nexport default StatusBadge\n"],"mappings":";;;AAKA,IAAM,IAAa,IAkBb,IAAA,CAAe,EAAE,OAAA,GAAO,MAAA,EAAA,MAC5B,gBAAA,EAAC,GAAD;AAAA,EACE,eAAa,IAAQ,SAAY;AAAA,EACjC,cAAY;AAAA,EACZ,eAAY;AAAA,EACZ,MAAM,IAAQ,QAAQ;AAAA,EACtB,IAAI;AAAA,IACF,YAAY;AAAA,IAEZ,SAAS;AAAA,IACT,cAAc;AAAA,IACd,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,OAAO;AAAA,EACT;AAAA,EAEA,UAAA,gBAAA,EAAC,GAAD;AAAA,IAAM,OAAO;AAAA,IAAM,MAAM;AAAA,IAAM,MAAK;AAAA,IAAQ,MAAM;AAAA,EAAa,CAAA;AAC5D,CAAA"}
@@ -1,4 +1,4 @@
1
- import { ReactNode } from 'react';
1
+ import { ReactNode, SyntheticEvent } from 'react';
2
2
  import { SxProps } from '@mui/material/styles';
3
3
  interface StatusPillProps {
4
4
  /** Pill label. */
@@ -11,6 +11,15 @@ interface StatusPillProps {
11
11
  borderColor?: string;
12
12
  /** Label color token. */
13
13
  labelColor?: string;
14
+ /** Label typography. Default `subtitle2`; the transaction-row pill uses `caption`. */
15
+ labelVariant?: 'subtitle2' | 'caption';
16
+ /**
17
+ * Makes the pill tappable (the transaction-row pill posts the beat to the host). The pill then
18
+ * exposes `role="button"`, is focusable, and also fires on Enter and Space, so the handler gets a
19
+ * mouse or a keyboard event.
20
+ */
21
+ onClick?: (event: SyntheticEvent<HTMLDivElement>) => void;
22
+ 'data-testid'?: string;
14
23
  sx?: SxProps;
15
24
  }
16
25
  /**
@@ -22,5 +31,5 @@ interface StatusPillProps {
22
31
  * `typography/subtitle2` label — regular weight, NOT bold). Reusable for any
23
32
  * inline status.
24
33
  */
25
- declare const StatusPill: ({ bgcolor, borderColor, icon, label, labelColor, sx, }: StatusPillProps) => import("react/jsx-runtime").JSX.Element;
34
+ declare const StatusPill: ({ bgcolor, borderColor, icon, label, labelColor, labelVariant, onClick, sx, "data-testid": testId, }: StatusPillProps) => import("react/jsx-runtime").JSX.Element;
26
35
  export default StatusPill;
@@ -1,30 +1,42 @@
1
- import { STATUS_SUCCESS_TOKENS as r } from "./statusTokens.es.js";
2
- import s from "@mui/material/Stack";
3
- import { Text as m } from "@mxenabled/mxui";
4
- import { jsx as x, jsxs as p } from "react/jsx-runtime";
5
- var c = ({ bgcolor: o = r.bgcolor, borderColor: t = r.borderColor, icon: e, label: i, labelColor: l = r.textColor, sx: a }) => /* @__PURE__ */ p(s, {
1
+ import { STATUS_SUCCESS_TOKENS as o } from "./statusTokens.es.js";
2
+ import u from "@mui/material/Stack";
3
+ import { Text as p } from "@mxenabled/mxui";
4
+ import { jsx as x, jsxs as m } from "react/jsx-runtime";
5
+ var h = ({ bgcolor: e = o.bgcolor, borderColor: i = o.borderColor, icon: a, label: l, labelColor: d = o.textColor, labelVariant: s = "subtitle2", onClick: t, sx: n, "data-testid": f }) => /* @__PURE__ */ m(u, {
6
+ "data-testid": f,
7
+ onClick: t,
8
+ onKeyDown: t ? (r) => {
9
+ r.target === r.currentTarget && (r.key !== "Enter" && r.key !== " " || (r.preventDefault(), r.stopPropagation(), t?.(r)));
10
+ } : void 0,
11
+ role: t ? "button" : void 0,
6
12
  sx: {
7
13
  alignItems: "center",
8
14
  alignSelf: "flex-start",
9
- bgcolor: o,
15
+ bgcolor: e,
10
16
  border: "1px solid",
11
- borderColor: t,
17
+ borderColor: i,
12
18
  borderRadius: 999,
13
19
  flexDirection: "row",
14
20
  gap: 6,
15
21
  minHeight: 24,
16
22
  px: 16,
17
23
  py: 2,
18
- ...a
24
+ ...t && { "&:focus-visible": {
25
+ outline: "2px solid",
26
+ outlineColor: "info.main",
27
+ outlineOffset: 2
28
+ } },
29
+ ...n
19
30
  },
20
- children: [e, /* @__PURE__ */ x(m, {
21
- color: l,
22
- variant: "subtitle2",
23
- children: i
31
+ tabIndex: t ? 0 : void 0,
32
+ children: [a, /* @__PURE__ */ x(p, {
33
+ color: d,
34
+ variant: s,
35
+ children: l
24
36
  })]
25
37
  });
26
38
  export {
27
- c as default
39
+ h as default
28
40
  };
29
41
 
30
42
  //# sourceMappingURL=StatusPill.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"StatusPill.es.js","names":[],"sources":["../../../src/insights-v2/components/StatusPill.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\n\nimport Stack from '@mui/material/Stack'\nimport type { SxProps } from '@mui/material/styles'\n\nimport { Text } from '@mxenabled/mxui'\n\nimport { STATUS_SUCCESS_TOKENS } from './statusTokens'\n\ninterface StatusPillProps {\n /** Pill label. */\n label: ReactNode\n /** Optional leading icon (e.g. a check-circle). */\n icon?: ReactNode\n /** Pill background color token. */\n bgcolor?: string\n /** Pill border color token. */\n borderColor?: string\n /** Label color token. */\n labelColor?: string\n sx?: SxProps\n}\n\n/**\n * A small rounded status pill: optional icon + label on a tinted, bordered\n * surface.\n *\n * Figma: the \"Categorized\" pill in Peer-to-Peer Categorization (`success.100`\n * bg, `success.main` border, radius 999, 24px tall, check icon + `success.darker`\n * `typography/subtitle2` label — regular weight, NOT bold). Reusable for any\n * inline status.\n */\nconst StatusPill = ({\n bgcolor = STATUS_SUCCESS_TOKENS.bgcolor,\n borderColor = STATUS_SUCCESS_TOKENS.borderColor,\n icon,\n label,\n labelColor = STATUS_SUCCESS_TOKENS.textColor,\n sx,\n}: StatusPillProps) => (\n <Stack\n sx={{\n alignItems: 'center',\n alignSelf: 'flex-start',\n bgcolor,\n border: '1px solid',\n borderColor,\n borderRadius: 999,\n flexDirection: 'row',\n gap: 6,\n minHeight: 24,\n px: 16,\n py: 2,\n ...sx,\n }}\n >\n {icon}\n <Text color={labelColor} variant=\"subtitle2\">\n {label}\n </Text>\n </Stack>\n)\n\nexport default StatusPill\n"],"mappings":";;;;AAgCA,IAAM,IAAA,CAAc,EAClB,SAAA,IAAU,EAAsB,SAChC,aAAA,IAAc,EAAsB,aACpC,MAAA,GACA,OAAA,GACA,YAAA,IAAa,EAAsB,WACnC,IAAA,EAAA,MAEA,gBAAA,EAAC,GAAD;AAAA,EACE,IAAI;AAAA,IACF,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,SAAA;AAAA,IACA,QAAQ;AAAA,IACR,aAAA;AAAA,IACA,cAAc;AAAA,IACd,eAAe;AAAA,IACf,KAAK;AAAA,IACL,WAAW;AAAA,IACX,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,GAAG;AAAA,EACL;AAAA,EAdF,UAAA,CAgBG,GACD,gBAAA,EAAC,GAAD;AAAA,IAAM,OAAO;AAAA,IAAY,SAAQ;AAAA,IAC9B,UAAA;AAAA,EACG,CAAA,CACD"}
1
+ {"version":3,"file":"StatusPill.es.js","names":[],"sources":["../../../src/insights-v2/components/StatusPill.tsx"],"sourcesContent":["import type { KeyboardEvent, ReactNode, SyntheticEvent } from 'react'\n\nimport Stack from '@mui/material/Stack'\nimport type { SxProps } from '@mui/material/styles'\n\nimport { Text } from '@mxenabled/mxui'\n\nimport { STATUS_SUCCESS_TOKENS } from './statusTokens'\n\ninterface StatusPillProps {\n /** Pill label. */\n label: ReactNode\n /** Optional leading icon (e.g. a check-circle). */\n icon?: ReactNode\n /** Pill background color token. */\n bgcolor?: string\n /** Pill border color token. */\n borderColor?: string\n /** Label color token. */\n labelColor?: string\n /** Label typography. Default `subtitle2`; the transaction-row pill uses `caption`. */\n labelVariant?: 'subtitle2' | 'caption'\n /**\n * Makes the pill tappable (the transaction-row pill posts the beat to the host). The pill then\n * exposes `role=\"button\"`, is focusable, and also fires on Enter and Space, so the handler gets a\n * mouse or a keyboard event.\n */\n onClick?: (event: SyntheticEvent<HTMLDivElement>) => void\n 'data-testid'?: string\n sx?: SxProps\n}\n\n/**\n * A small rounded status pill: optional icon + label on a tinted, bordered\n * surface.\n *\n * Figma: the \"Categorized\" pill in Peer-to-Peer Categorization (`success.100`\n * bg, `success.main` border, radius 999, 24px tall, check icon + `success.darker`\n * `typography/subtitle2` label — regular weight, NOT bold). Reusable for any\n * inline status.\n */\nconst StatusPill = ({\n bgcolor = STATUS_SUCCESS_TOKENS.bgcolor,\n borderColor = STATUS_SUCCESS_TOKENS.borderColor,\n icon,\n label,\n labelColor = STATUS_SUCCESS_TOKENS.textColor,\n labelVariant = 'subtitle2',\n onClick,\n sx,\n 'data-testid': testId,\n}: StatusPillProps) => {\n // Only when the pill itself has focus: a key pressed inside it would be a child's own. Stopping\n // the event keeps a clickable row around the pill from also acting on the same keystroke.\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (event.target !== event.currentTarget) return\n if (event.key !== 'Enter' && event.key !== ' ') return\n\n event.preventDefault()\n event.stopPropagation()\n onClick?.(event)\n }\n\n return (\n <Stack\n data-testid={testId}\n onClick={onClick}\n onKeyDown={onClick ? handleKeyDown : undefined}\n role={onClick ? 'button' : undefined}\n sx={{\n alignItems: 'center',\n alignSelf: 'flex-start',\n bgcolor,\n border: '1px solid',\n borderColor,\n borderRadius: 999,\n flexDirection: 'row',\n gap: 6,\n minHeight: 24,\n px: 16,\n py: 2,\n // The same focus ring the theme's MuiButton draws.\n ...(onClick && {\n '&:focus-visible': { outline: '2px solid', outlineColor: 'info.main', outlineOffset: 2 },\n }),\n ...sx,\n }}\n tabIndex={onClick ? 0 : undefined}\n >\n {icon}\n <Text color={labelColor} variant={labelVariant}>\n {label}\n </Text>\n </Stack>\n )\n}\n\nexport default StatusPill\n"],"mappings":";;;;AAyCA,IAAM,IAAA,CAAc,EAClB,SAAA,IAAU,EAAsB,SAChC,aAAA,IAAc,EAAsB,aACpC,MAAA,GACA,OAAA,GACA,YAAA,IAAa,EAAsB,WACnC,cAAA,IAAe,aACf,SAAA,GACA,IAAA,GACA,eAAe,EAAA,MAcb,gBAAA,EAAC,GAAD;AAAA,EACE,eAAa;AAAA,EACJ,SAAA;AAAA,EACT,WAAW,IAbT,CAAiB,MAAyC;AAC9D,IAAI,EAAM,WAAW,EAAM,kBACvB,EAAM,QAAQ,WAAW,EAAM,QAAQ,QAE3C,EAAM,eAAe,GACrB,EAAM,gBAAgB,GACtB,IAAU,CAAK;AAAA,EACjB,IAMyC;AAAA,EACrC,MAAM,IAAU,WAAW;AAAA,EAC3B,IAAI;AAAA,IACF,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,SAAA;AAAA,IACA,QAAQ;AAAA,IACR,aAAA;AAAA,IACA,cAAc;AAAA,IACd,eAAe;AAAA,IACf,KAAK;AAAA,IACL,WAAW;AAAA,IACX,IAAI;AAAA,IACJ,IAAI;AAAA,IAEJ,GAAI,KAAW,EACb,mBAAmB;AAAA,MAAE,SAAS;AAAA,MAAa,cAAc;AAAA,MAAa,eAAe;AAAA,IAAE,EACzF;AAAA,IACA,GAAG;AAAA,EACL;AAAA,EACA,UAAU,IAAU,IAAI;AAAA,EAvB1B,UAAA,CAyBG,GACD,gBAAA,EAAC,GAAD;AAAA,IAAM,OAAO;AAAA,IAAY,SAAS;AAAA,IAC/B,UAAA;AAAA,EACG,CAAA,CACD"}
@@ -1,12 +1,12 @@
1
1
  import n from "@mui/material/Stack";
2
- import { CategoryIcon as a, InstitutionLogo as u, MerchantLogo as o, Text as c } from "@mxenabled/mxui";
2
+ import { CategoryIcon as a, InstitutionLogo as u, MerchantLogo as c, Text as o } from "@mxenabled/mxui";
3
3
  import { Icon as s } from "@mxenabled/mx-icons";
4
4
  import { jsx as r, jsxs as d } from "react/jsx-runtime";
5
5
  var m = (t) => t ? t.logo_name ? /* @__PURE__ */ r(s, {
6
6
  name: t.logo_name,
7
7
  size: 16,
8
8
  sx: { color: t.logo_color }
9
- }) : t.merchant_guid ? /* @__PURE__ */ r(o, {
9
+ }) : t.merchant_guid ? /* @__PURE__ */ r(c, {
10
10
  alt: t.merchant_name,
11
11
  categoryGuid: t.category_guid,
12
12
  merchantGuid: t.merchant_guid,
@@ -18,7 +18,7 @@ var m = (t) => t ? t.logo_name ? /* @__PURE__ */ r(s, {
18
18
  }) : t.category_guid ? /* @__PURE__ */ r(a, {
19
19
  categoryGuid: t.category_guid,
20
20
  size: 16
21
- }) : null : null, y = ({ subtitle: t }) => {
21
+ }) : null : null, p = ({ subtitle: t }) => {
22
22
  const { logo: e, text: i } = t;
23
23
  return /* @__PURE__ */ d(n, {
24
24
  sx: {
@@ -26,15 +26,17 @@ var m = (t) => t ? t.logo_name ? /* @__PURE__ */ r(s, {
26
26
  flexDirection: "row",
27
27
  gap: 8
28
28
  },
29
- children: [m(e), /* @__PURE__ */ r(c, {
29
+ children: [m(e), /* @__PURE__ */ r(o, {
30
30
  color: "text.secondary",
31
+ sx: { letterSpacing: "0.52px" },
32
+ uppercase: !0,
31
33
  variant: "body2",
32
34
  children: i
33
35
  })]
34
36
  });
35
37
  };
36
38
  export {
37
- y as default
39
+ p as default
38
40
  };
39
41
 
40
42
  //# sourceMappingURL=SubHeader.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SubHeader.es.js","names":[],"sources":["../../../src/insights-v2/components/SubHeader.tsx"],"sourcesContent":["import Stack from '@mui/material/Stack'\n\nimport { CategoryIcon, InstitutionLogo, MerchantLogo, Text } from '@mxenabled/mxui'\nimport { Icon } from '@mxenabled/mx-icons'\nimport type { Logo, Subtitle } from '../../core'\n\ninterface SubHeaderProps {\n subtitle: Subtitle\n}\n\n// TODO: Ask backend to send the correct guid (institution_guid, merchant_guid, or category_guid)\n// per beat's logo, matching what that beat's subtitle is actually about.\nconst renderLogo = (logo: Logo | undefined) => {\n if (!logo) return null\n\n if (logo.logo_name) {\n return <Icon name={logo.logo_name} size={16} sx={{ color: logo.logo_color }} />\n }\n\n if (logo.merchant_guid) {\n return (\n <MerchantLogo\n alt={logo.merchant_name as string}\n categoryGuid={logo.category_guid as string}\n merchantGuid={logo.merchant_guid}\n size={16}\n />\n )\n }\n\n if (logo.institution_guid) {\n return (\n <InstitutionLogo\n alt={logo.institution_name as string}\n institutionGuid={logo.institution_guid}\n size={16}\n />\n )\n }\n\n if (logo.category_guid) {\n return <CategoryIcon categoryGuid={logo.category_guid} size={16} />\n }\n\n return null\n}\n\nconst SubHeader = ({ subtitle }: SubHeaderProps) => {\n const { logo, text } = subtitle\n\n return (\n <Stack sx={{ alignItems: 'center', flexDirection: 'row', gap: 8 }}>\n {renderLogo(logo)}\n <Text color=\"text.secondary\" variant=\"body2\">\n {text}\n </Text>\n </Stack>\n )\n}\n\nexport default SubHeader\n"],"mappings":";;;;AAYA,IAAM,IAAA,CAAc,MACb,IAED,EAAK,YACA,gBAAA,EAAC,GAAD;AAAA,EAAM,MAAM,EAAK;AAAA,EAAW,MAAM;AAAA,EAAI,IAAI,EAAE,OAAO,EAAK,WAAW;AAAI,CAAA,IAG5E,EAAK,gBAEL,gBAAA,EAAC,GAAD;AAAA,EACE,KAAK,EAAK;AAAA,EACV,cAAc,EAAK;AAAA,EACnB,cAAc,EAAK;AAAA,EACnB,MAAM;AACP,CAAA,IAID,EAAK,mBAEL,gBAAA,EAAC,GAAD;AAAA,EACE,KAAK,EAAK;AAAA,EACV,iBAAiB,EAAK;AAAA,EACtB,MAAM;AACP,CAAA,IAID,EAAK,gBACA,gBAAA,EAAC,GAAD;AAAA,EAAc,cAAc,EAAK;AAAA,EAAe,MAAM;AAAK,CAAA,IAG7D,OA/BW,MAkCd,IAAA,CAAa,EAAE,UAAA,EAAA,MAA+B;AAClD,QAAM,EAAE,MAAA,GAAM,MAAA,EAAA,IAAS;AAEvB,SACE,gBAAA,EAAC,GAAD;AAAA,IAAO,IAAI;AAAA,MAAE,YAAY;AAAA,MAAU,eAAe;AAAA,MAAO,KAAK;AAAA,IAAE;AAAA,IAAhE,UAAA,CACG,EAAW,CAAI,GAChB,gBAAA,EAAC,GAAD;AAAA,MAAM,OAAM;AAAA,MAAiB,SAAQ;AAAA,MAClC,UAAA;AAAA,IACG,CAAA,CACD;AAAA;AAEX"}
1
+ {"version":3,"file":"SubHeader.es.js","names":[],"sources":["../../../src/insights-v2/components/SubHeader.tsx"],"sourcesContent":["import Stack from '@mui/material/Stack'\n\nimport { CategoryIcon, InstitutionLogo, MerchantLogo, Text } from '@mxenabled/mxui'\nimport { Icon } from '@mxenabled/mx-icons'\nimport type { Logo, Subtitle } from '../../core'\n\ninterface SubHeaderProps {\n subtitle: Subtitle\n}\n\n// TODO: Ask backend to send the correct guid (institution_guid, merchant_guid, or category_guid)\n// per beat's logo, matching what that beat's subtitle is actually about.\nconst renderLogo = (logo: Logo | undefined) => {\n if (!logo) return null\n\n if (logo.logo_name) {\n return <Icon name={logo.logo_name} size={16} sx={{ color: logo.logo_color }} />\n }\n\n if (logo.merchant_guid) {\n return (\n <MerchantLogo\n alt={logo.merchant_name as string}\n categoryGuid={logo.category_guid as string}\n merchantGuid={logo.merchant_guid}\n size={16}\n />\n )\n }\n\n if (logo.institution_guid) {\n return (\n <InstitutionLogo\n alt={logo.institution_name as string}\n institutionGuid={logo.institution_guid}\n size={16}\n />\n )\n }\n\n if (logo.category_guid) {\n return <CategoryIcon categoryGuid={logo.category_guid} size={16} />\n }\n\n return null\n}\n\nconst SubHeader = ({ subtitle }: SubHeaderProps) => {\n const { logo, text } = subtitle\n\n return (\n <Stack sx={{ alignItems: 'center', flexDirection: 'row', gap: 8 }}>\n {renderLogo(logo)}\n {/* Figma `typography/body2 (upper)`: uppercased with 0.52px tracking. */}\n <Text\n color=\"text.secondary\"\n sx={{ letterSpacing: '0.52px' }}\n uppercase={true}\n variant=\"body2\"\n >\n {text}\n </Text>\n </Stack>\n )\n}\n\nexport default SubHeader\n"],"mappings":";;;;AAYA,IAAM,IAAA,CAAc,MACb,IAED,EAAK,YACA,gBAAA,EAAC,GAAD;AAAA,EAAM,MAAM,EAAK;AAAA,EAAW,MAAM;AAAA,EAAI,IAAI,EAAE,OAAO,EAAK,WAAW;AAAI,CAAA,IAG5E,EAAK,gBAEL,gBAAA,EAAC,GAAD;AAAA,EACE,KAAK,EAAK;AAAA,EACV,cAAc,EAAK;AAAA,EACnB,cAAc,EAAK;AAAA,EACnB,MAAM;AACP,CAAA,IAID,EAAK,mBAEL,gBAAA,EAAC,GAAD;AAAA,EACE,KAAK,EAAK;AAAA,EACV,iBAAiB,EAAK;AAAA,EACtB,MAAM;AACP,CAAA,IAID,EAAK,gBACA,gBAAA,EAAC,GAAD;AAAA,EAAc,cAAc,EAAK;AAAA,EAAe,MAAM;AAAK,CAAA,IAG7D,OA/BW,MAkCd,IAAA,CAAa,EAAE,UAAA,EAAA,MAA+B;AAClD,QAAM,EAAE,MAAA,GAAM,MAAA,EAAA,IAAS;AAEvB,SACE,gBAAA,EAAC,GAAD;AAAA,IAAO,IAAI;AAAA,MAAE,YAAY;AAAA,MAAU,eAAe;AAAA,MAAO,KAAK;AAAA,IAAE;AAAA,IAAhE,UAAA,CACG,EAAW,CAAI,GAEhB,gBAAA,EAAC,GAAD;AAAA,MACE,OAAM;AAAA,MACN,IAAI,EAAE,eAAe,SAAS;AAAA,MAC9B,WAAW;AAAA,MACX,SAAQ;AAAA,MAEP,UAAA;AAAA,IACG,CAAA,CACD;AAAA;AAEX"}
@@ -18,20 +18,20 @@ var w = (n) => n === "primary" ? {
18
18
  py: 4
19
19
  }
20
20
  } : {
21
- radius: "4px",
21
+ radius: "8px",
22
22
  borderColor: "divider",
23
23
  headerBg: "background.default",
24
- headerColor: "text.secondary",
24
+ headerColor: "text.primary",
25
25
  headerBold: !0,
26
26
  headerInsideBorder: !0,
27
27
  headerSx: {
28
- minHeight: 40,
28
+ minHeight: 36,
29
29
  px: 16,
30
30
  py: 2
31
31
  }
32
- }, H = ({ background: n, footer: l, header: a, rows: m, variant: g = "default", sx: b }) => {
32
+ }, H = ({ background: n, footer: l, header: i, rows: m, variant: g = "default", sx: b }) => {
33
33
  if (m.length === 0) return null;
34
- const e = w(g), i = !!n, o = i ? "8px" : e.radius, s = !!a && !i && e.headerInsideBorder, c = a ? /* @__PURE__ */ r(t, {
34
+ const e = w(g), a = !!n, o = a ? "8px" : e.radius, s = !!i && !a && e.headerInsideBorder, c = i ? /* @__PURE__ */ r(t, {
35
35
  sx: {
36
36
  bgcolor: e.headerBg,
37
37
  justifyContent: "center",
@@ -41,12 +41,12 @@ var w = (n) => n === "primary" ? {
41
41
  bold: e.headerBold,
42
42
  color: e.headerColor,
43
43
  variant: "caption",
44
- children: a
44
+ children: i
45
45
  })
46
46
  }) : null, f = l ? /* @__PURE__ */ d(x, { children: [/* @__PURE__ */ r(p, {}), /* @__PURE__ */ d(t, {
47
47
  sx: {
48
48
  alignItems: "center",
49
- bgcolor: i ? "background.paper" : "background.default",
49
+ bgcolor: a ? "background.paper" : "background.default",
50
50
  flexDirection: "row",
51
51
  justifyContent: "space-between",
52
52
  minHeight: 40,
@@ -73,7 +73,7 @@ var w = (n) => n === "primary" ? {
73
73
  });
74
74
  return /* @__PURE__ */ d(t, {
75
75
  sx: {
76
- ...i ? {
76
+ ...a ? {
77
77
  background: n,
78
78
  p: 16
79
79
  } : {
@@ -92,14 +92,14 @@ var w = (n) => n === "primary" ? {
92
92
  children: c
93
93
  }), /* @__PURE__ */ d(t, {
94
94
  sx: {
95
- ...i ? { bgcolor: "background.paper" } : {
95
+ ...a ? { bgcolor: "background.paper" } : {
96
96
  border: "1px solid",
97
97
  borderColor: e.borderColor
98
98
  },
99
99
  borderBottomLeftRadius: o,
100
100
  borderBottomRightRadius: o,
101
- borderTopLeftRadius: s || !a ? o : 0,
102
- borderTopRightRadius: s || !a ? o : 0,
101
+ borderTopLeftRadius: s || !i ? o : 0,
102
+ borderTopRightRadius: s || !i ? o : 0,
103
103
  overflow: "hidden",
104
104
  width: "100%"
105
105
  },
@@ -1 +1 @@
1
- {"version":3,"file":"TransactionListCard.es.js","names":[],"sources":["../../../src/insights-v2/components/TransactionListCard.tsx"],"sourcesContent":["import { Fragment, type ReactNode } from 'react'\n\nimport Box from '@mui/material/Box'\nimport Divider from '@mui/material/Divider'\nimport Stack from '@mui/material/Stack'\nimport type { SxProps } from '@mui/material/styles'\n\nimport { Text } from '@mxenabled/mxui'\n\nimport InsightTransactionRow, { type InsightTransactionRowProps } from './InsightTransactionRow'\n\nexport interface FooterRow {\n label: ReactNode\n amount: ReactNode\n amountColor?: string\n}\n\ntype TransactionListCardVariant = 'default' | 'primary'\n\ninterface TransactionListCardProps {\n /** Optional header label above the rows (e.g. \"{Date}\", \"3 transactions\"). */\n header?: ReactNode\n /** One or more transaction rows. */\n rows: InsightTransactionRowProps[]\n /** Optional summary/total row rendered beneath a divider. */\n footer?: FooterRow\n /**\n * Card style:\n * - `default` — grey utility header, hairline border, radius 4.\n * - `primary` — filled `primary.main` header with white text and a matching\n * border, radius 8 (Figma \"Multi\" variant).\n *\n * In both cases the header is borderless; the border wraps the content block\n * below it.\n */\n variant?: TransactionListCardVariant\n /**\n * Optional background applied to the Slot behind the card. Must be a valid CSS\n * background string (gradient or color in CSS format); MUI theme tokens are\n * not resolved here (this is the CSS `background` shorthand, not `bgcolor`), so\n * use a CSS color literal instead. When set, the inner card renders borderless\n * on a white surface inside the padded Slot (Figma HSA Deposit).\n */\n background?: string\n sx?: SxProps\n}\n\nconst getVariantStyles = (variant: TransactionListCardVariant) => {\n switch (variant) {\n case 'primary':\n // Borderless filled header on top of the bordered rows block.\n return {\n radius: '8px',\n borderColor: 'primary.main',\n headerBg: 'primary.main',\n headerColor: 'primary.contrastText',\n headerBold: false,\n headerInsideBorder: false,\n headerSx: { minHeight: 24, px: 12, py: 4 } as const,\n }\n default:\n // A single border wraps the card; the grey header sits inside it.\n return {\n radius: '4px',\n borderColor: 'divider',\n headerBg: 'background.default',\n headerColor: 'text.secondary',\n headerBold: true,\n headerInsideBorder: true,\n headerSx: { minHeight: 40, px: 16, py: 2 } as const,\n }\n }\n}\n\n/**\n * List card composing an optional header label, one or more\n * `InsightTransactionRow`s (divided), and an optional footer/total row.\n * `variant` supplies the Figma design defaults for the two card styles.\n *\n * Scope is the Content section only; Header/Description are out of scope.\n */\nconst TransactionListCard = ({\n background,\n footer,\n header,\n rows,\n variant = 'default',\n sx,\n}: TransactionListCardProps) => {\n // rows usually comes from mapped API data, so an empty array is reachable and\n // would render a broken border shell; render nothing instead.\n if (rows.length === 0) return null\n\n const styles = getVariantStyles(variant)\n const hasBackground = Boolean(background)\n const radius = hasBackground ? '8px' : styles.radius\n // The header sits inside the border only for the bordered `default` variant;\n // for `primary`/backgrounded cards it sits above a separately-bordered body.\n const headerInsideBorder = Boolean(header) && !hasBackground && styles.headerInsideBorder\n\n const headerBlock = header ? (\n <Stack sx={{ bgcolor: styles.headerBg, justifyContent: 'center', ...styles.headerSx }}>\n <Text bold={styles.headerBold} color={styles.headerColor} variant=\"caption\">\n {header}\n </Text>\n </Stack>\n ) : null\n\n const footerBlock = footer ? (\n <>\n <Divider />\n <Stack\n sx={{\n alignItems: 'center',\n bgcolor: hasBackground ? 'background.paper' : 'background.default',\n flexDirection: 'row',\n justifyContent: 'space-between',\n minHeight: 40,\n px: 16,\n py: 2,\n }}\n >\n <Text color=\"text.secondary\" variant=\"caption\">\n {footer.label}\n </Text>\n <Text bold={true} color={footer.amountColor ?? 'text.primary'} variant=\"body2\">\n {footer.amount}\n </Text>\n </Stack>\n </>\n ) : null\n\n const rowsBlock = (\n <Stack role=\"list\" sx={{ width: '100%' }}>\n {rows.map((row, index) => (\n // Static, caller-ordered list that may contain identical rows, so the\n // array index is the correct key (a content-based key would collide).\n // eslint-disable-next-line react/no-array-index-key\n <Fragment key={index}>\n {index > 0 && <Divider role=\"presentation\" />}\n <Box role=\"listitem\">\n <InsightTransactionRow {...row} />\n </Box>\n </Fragment>\n ))}\n </Stack>\n )\n\n return (\n <Stack\n sx={{\n ...(hasBackground ? { background, p: 16 } : { pt: 8, px: 16 }),\n width: '100%',\n ...sx,\n }}\n >\n {/* Header above the border for `primary`/backgrounded cards; top-rounded. */}\n {!headerInsideBorder && headerBlock && (\n <Stack\n sx={{\n borderTopLeftRadius: radius,\n borderTopRightRadius: radius,\n overflow: 'hidden',\n }}\n >\n {headerBlock}\n </Stack>\n )}\n\n <Stack\n sx={{\n ...(hasBackground\n ? { bgcolor: 'background.paper' }\n : { border: '1px solid', borderColor: styles.borderColor }),\n borderBottomLeftRadius: radius,\n borderBottomRightRadius: radius,\n borderTopLeftRadius: headerInsideBorder || !header ? radius : 0,\n borderTopRightRadius: headerInsideBorder || !header ? radius : 0,\n overflow: 'hidden',\n width: '100%',\n }}\n >\n {/* Header inside the border for the `default` table variant. */}\n {headerInsideBorder && (\n <>\n {headerBlock}\n <Divider />\n </>\n )}\n {rowsBlock}\n {footerBlock}\n </Stack>\n </Stack>\n )\n}\n\nexport default TransactionListCard\n"],"mappings":"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"}
1
+ {"version":3,"file":"TransactionListCard.es.js","names":[],"sources":["../../../src/insights-v2/components/TransactionListCard.tsx"],"sourcesContent":["import { Fragment, type ReactNode } from 'react'\n\nimport Box from '@mui/material/Box'\nimport Divider from '@mui/material/Divider'\nimport Stack from '@mui/material/Stack'\nimport type { SxProps } from '@mui/material/styles'\n\nimport { Text } from '@mxenabled/mxui'\n\nimport InsightTransactionRow, { type InsightTransactionRowProps } from './InsightTransactionRow'\n\nexport interface FooterRow {\n label: ReactNode\n amount: ReactNode\n amountColor?: string\n}\n\ntype TransactionListCardVariant = 'default' | 'primary'\n\ninterface TransactionListCardProps {\n /** Optional header label above the rows (e.g. \"{Date}\", \"3 transactions\"). */\n header?: ReactNode\n /** One or more transaction rows. */\n rows: InsightTransactionRowProps[]\n /** Optional summary/total row rendered beneath a divider. */\n footer?: FooterRow\n /**\n * Card style:\n * - `default` — grey utility header, hairline border, radius 4.\n * - `primary` — filled `primary.main` header with white text and a matching\n * border, radius 8 (Figma \"Multi\" variant).\n *\n * In both cases the header is borderless; the border wraps the content block\n * below it.\n */\n variant?: TransactionListCardVariant\n /**\n * Optional background applied to the Slot behind the card. Must be a valid CSS\n * background string (gradient or color in CSS format); MUI theme tokens are\n * not resolved here (this is the CSS `background` shorthand, not `bgcolor`), so\n * use a CSS color literal instead. When set, the inner card renders borderless\n * on a white surface inside the padded Slot (Figma HSA Deposit).\n */\n background?: string\n sx?: SxProps\n}\n\nconst getVariantStyles = (variant: TransactionListCardVariant) => {\n switch (variant) {\n case 'primary':\n // Borderless filled header on top of the bordered rows block.\n return {\n radius: '8px',\n borderColor: 'primary.main',\n headerBg: 'primary.main',\n headerColor: 'primary.contrastText',\n headerBold: false,\n headerInsideBorder: false,\n headerSx: { minHeight: 24, px: 12, py: 4 } as const,\n }\n default:\n // A single border wraps the card; the grey header sits inside it.\n return {\n radius: '8px',\n borderColor: 'divider',\n headerBg: 'background.default',\n headerColor: 'text.primary',\n headerBold: true,\n headerInsideBorder: true,\n headerSx: { minHeight: 36, px: 16, py: 2 } as const,\n }\n }\n}\n\n/**\n * List card composing an optional header label, one or more\n * `InsightTransactionRow`s (divided), and an optional footer/total row.\n * `variant` supplies the Figma design defaults for the two card styles.\n *\n * Scope is the Content section only; Header/Description are out of scope.\n */\nconst TransactionListCard = ({\n background,\n footer,\n header,\n rows,\n variant = 'default',\n sx,\n}: TransactionListCardProps) => {\n // rows usually comes from mapped API data, so an empty array is reachable and\n // would render a broken border shell; render nothing instead.\n if (rows.length === 0) return null\n\n const styles = getVariantStyles(variant)\n const hasBackground = Boolean(background)\n const radius = hasBackground ? '8px' : styles.radius\n // The header sits inside the border only for the bordered `default` variant;\n // for `primary`/backgrounded cards it sits above a separately-bordered body.\n const headerInsideBorder = Boolean(header) && !hasBackground && styles.headerInsideBorder\n\n const headerBlock = header ? (\n <Stack sx={{ bgcolor: styles.headerBg, justifyContent: 'center', ...styles.headerSx }}>\n <Text bold={styles.headerBold} color={styles.headerColor} variant=\"caption\">\n {header}\n </Text>\n </Stack>\n ) : null\n\n const footerBlock = footer ? (\n <>\n <Divider />\n <Stack\n sx={{\n alignItems: 'center',\n bgcolor: hasBackground ? 'background.paper' : 'background.default',\n flexDirection: 'row',\n justifyContent: 'space-between',\n minHeight: 40,\n px: 16,\n py: 2,\n }}\n >\n <Text color=\"text.secondary\" variant=\"caption\">\n {footer.label}\n </Text>\n <Text bold={true} color={footer.amountColor ?? 'text.primary'} variant=\"body2\">\n {footer.amount}\n </Text>\n </Stack>\n </>\n ) : null\n\n const rowsBlock = (\n <Stack role=\"list\" sx={{ width: '100%' }}>\n {rows.map((row, index) => (\n // Static, caller-ordered list that may contain identical rows, so the\n // array index is the correct key (a content-based key would collide).\n // eslint-disable-next-line react/no-array-index-key\n <Fragment key={index}>\n {index > 0 && <Divider role=\"presentation\" />}\n <Box role=\"listitem\">\n <InsightTransactionRow {...row} />\n </Box>\n </Fragment>\n ))}\n </Stack>\n )\n\n return (\n <Stack\n sx={{\n ...(hasBackground ? { background, p: 16 } : { pt: 8, px: 16 }),\n width: '100%',\n ...sx,\n }}\n >\n {/* Header above the border for `primary`/backgrounded cards; top-rounded. */}\n {!headerInsideBorder && headerBlock && (\n <Stack\n sx={{\n borderTopLeftRadius: radius,\n borderTopRightRadius: radius,\n overflow: 'hidden',\n }}\n >\n {headerBlock}\n </Stack>\n )}\n\n <Stack\n sx={{\n ...(hasBackground\n ? { bgcolor: 'background.paper' }\n : { border: '1px solid', borderColor: styles.borderColor }),\n borderBottomLeftRadius: radius,\n borderBottomRightRadius: radius,\n borderTopLeftRadius: headerInsideBorder || !header ? radius : 0,\n borderTopRightRadius: headerInsideBorder || !header ? radius : 0,\n overflow: 'hidden',\n width: '100%',\n }}\n >\n {/* Header inside the border for the `default` table variant. */}\n {headerInsideBorder && (\n <>\n {headerBlock}\n <Divider />\n </>\n )}\n {rowsBlock}\n {footerBlock}\n </Stack>\n </Stack>\n )\n}\n\nexport default TransactionListCard\n"],"mappings":"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"}