@mx-cartographer/experiences 9.6.14 → 9.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/core/types/Insights.d.ts +3 -2
  3. package/dist/core/types/Insights.es.js.map +1 -1
  4. package/dist/core/types/localization/InsightsFeedCopy.d.ts +2 -0
  5. package/dist/insights-v2/blocks/ComponentBlocks/AccountBlock/AccountBlock.es.js +67 -67
  6. package/dist/insights-v2/blocks/ComponentBlocks/AccountBlock/AccountBlock.es.js.map +1 -1
  7. package/dist/insights-v2/blocks/ComponentBlocks/DebtsBlock/DebtsBlock.d.ts +16 -12
  8. package/dist/insights-v2/blocks/ComponentBlocks/DebtsBlock/DebtsBlock.es.js +67 -46
  9. package/dist/insights-v2/blocks/ComponentBlocks/DebtsBlock/DebtsBlock.es.js.map +1 -1
  10. package/dist/insights-v2/blocks/ComponentBlocks/DebtsBlock/layout.d.ts +17 -0
  11. package/dist/insights-v2/blocks/ComponentBlocks/DebtsBlock/layout.es.js +24 -0
  12. package/dist/insights-v2/blocks/ComponentBlocks/DebtsBlock/layout.es.js.map +1 -0
  13. package/dist/insights-v2/components/BaseLayout.es.js +1 -1
  14. package/dist/insights-v2/components/BaseLayout.es.js.map +1 -1
  15. package/dist/insights-v2/components/TransactionListCard.es.js +15 -14
  16. package/dist/insights-v2/components/TransactionListCard.es.js.map +1 -1
  17. package/dist/insights-v2/components/statusIcon.d.ts +8 -0
  18. package/dist/insights-v2/components/statusIcon.es.js +11 -6
  19. package/dist/insights-v2/components/statusIcon.es.js.map +1 -1
  20. package/dist/insights-v2/ctaActions/ctaPostMessages.es.js +15 -14
  21. package/dist/insights-v2/ctaActions/ctaPostMessages.es.js.map +1 -1
  22. package/dist/insights-v2/index.es.js +18 -18
  23. package/dist/microinsights/cards/InsightCard.es.js +38 -38
  24. package/dist/microinsights/cards/InsightCard.es.js.map +1 -1
  25. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"DebtsBlock.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/DebtsBlock/DebtsBlock.tsx"],"sourcesContent":["import React from 'react'\n\nimport { useGlobalCopyStore } from '../../../../common'\nimport type { InsightsPayload } from '../../../../core'\nimport { DATE_FORMATS_INTL, formatDate } from '../../../../core/constants'\nimport type { DebtsBlockCopy } from '../../../../core/types/localization/InsightsFeedCopy'\nimport { formatCurrency, formatPercentage } from '../../../../core/utils/NumberFormatting'\n\nimport DepositLogo from '../../../components/ComponentBlocks/DepositLogo'\nimport DebtPayoffCard, {\n type DebtPayoffCardStyleProps,\n type DebtPayoffStat,\n} from '../../../components/DebtPayoffCard'\nimport { parseDueDate } from '../UpcomingBillBlock/UpcomingBillBlock'\n\ninterface DebtsBlockProps {\n payload: InsightsPayload\n beatGuid?: string\n}\n\n/** `projected_payoff` look: primary-tinted slot and pill. The card story mirrors it from here. */\nexport const PAYOFF_STYLE: DebtPayoffCardStyleProps = {\n bgcolor: 'primary.lighter',\n pill: { bgcolor: 'primary.lighter', labelColor: 'text.primary' },\n}\n\n/** Account types drawn with the card glyph when there is no institution logo; the rest get the bank. */\nconst CREDIT_CARD_TYPES = new Set(['credit card', 'credit_card', 'creditcard'])\n\nconst iconFor = (accountType?: string) =>\n CREDIT_CARD_TYPES.has((accountType ?? '').trim().toLowerCase())\n ? 'credit_card'\n : 'account_balance'\n\n/** Every label the card renders; a partial namespace counts as missing. */\nconst hasAllLabels = (copy?: DebtsBlockCopy): copy is DebtsBlockCopy =>\n !!copy?.balance_label &&\n !!copy.payoff_date_label &&\n !!copy.monthly_payment_label &&\n !!copy.interest_rate_label\n\n/**\n * Debts component block — the content card for the Debt Payoff Strategies beat.\n *\n * The debt account's facts arrive flat on `instance_slot` (V2 contract — no `instance_slot_data`):\n * the balance (`amount`), `payoff_date`, `monthly_payment`, `interest_rate`, plus the shared\n * account/institution fields. Row labels come from `insights_feed.debts_block` copy, which\n * ships separately: until it has, the card shows the account row only (never an unlabelled number)\n * and warns once per mount so the rollout gap is traceable.\n *\n * `instance_slot.variant` is not read yet: the architecture doc's other Debts branches (Debt\n * Summary, Interest Summary) have no design, so there is one look. Introduce a per-variant\n * registry (`createVariantBlock` + a `layout.ts` table, as `AccountBlock` does) with the second\n * variant, not before.\n */\nconst DebtsBlock = ({ payload }: DebtsBlockProps) => {\n const copy = useGlobalCopyStore().insights_feed?.debts_block\n const labels = hasAllLabels(copy) ? copy : undefined\n const {\n account_name,\n account_type,\n amount,\n institution_guid,\n institution_name,\n interest_rate,\n monthly_payment,\n payoff_date,\n status_text,\n } = payload.instance_slot\n\n React.useEffect(() => {\n if (labels) return\n console.warn(\n `debts_block: ${copy ? 'copy incomplete' : 'copy namespace missing'}; rendering the account row only`,\n )\n }, [copy, labels])\n\n // A row with no value (or an unparseable date) is dropped rather than rendered blank.\n const payoffDate = payoff_date ? parseDueDate(payoff_date) : null\n const stats: DebtPayoffStat[] = []\n if (labels && payoffDate) {\n stats.push({\n label: labels.payoff_date_label,\n value: formatDate(payoffDate, DATE_FORMATS_INTL.MONTH_SHORT_YEAR),\n })\n }\n if (labels && monthly_payment != null) {\n stats.push({\n label: labels.monthly_payment_label,\n value: formatCurrency(monthly_payment, '0,0.00'),\n })\n }\n if (labels && interest_rate != null) {\n // `interest_rate` arrives as a percentage (19.99); Intl's percent style expects a fraction.\n stats.push({ label: labels.interest_rate_label, value: formatPercentage(interest_rate / 100) })\n }\n\n const hasBalance = labels !== undefined && amount != null\n\n return (\n <DebtPayoffCard\n {...PAYOFF_STYLE}\n balance={hasBalance ? formatCurrency(amount, '0,0.00') : undefined}\n balanceLabel={hasBalance ? labels.balance_label : undefined}\n logo={\n <DepositLogo\n iconName={iconFor(account_type)}\n institutionGuid={institution_guid ?? ''}\n institutionName={institution_name ?? ''}\n />\n }\n name={account_name}\n stats={stats}\n statusLabel={status_text}\n subtitle={account_type}\n />\n )\n}\n\nexport default DebtsBlock\n"],"mappings":";;;;;;;;AAqBA,IAAa,IAAyC;AAAA,EACpD,SAAS;AAAA,EACT,MAAM;AAAA,IAAE,SAAS;AAAA,IAAmB,YAAY;AAAA,EAAe;AACjE,GAGM,IAAoB,oBAAI,IAAI;AAAA,EAAC;AAAA,EAAe;AAAA,EAAe;AAAY,CAAC,GAExE,IAAA,CAAW,MACf,EAAkB,KAAK,KAAe,IAAI,KAAK,EAAE,YAAY,CAAC,IAC1D,gBACA,mBAGA,IAAA,CAAgB,MACpB,CAAC,CAAC,GAAM,iBACR,CAAC,CAAC,EAAK,qBACP,CAAC,CAAC,EAAK,yBACP,CAAC,CAAC,EAAK,qBAgBH,IAAA,CAAc,EAAE,SAAA,EAAA,MAA+B;AACnD,QAAM,IAAO,EAAmB,EAAE,eAAe,aAC3C,IAAS,EAAa,CAAI,IAAI,IAAO,QACrC,EACJ,cAAA,GACA,cAAA,GACA,QAAA,GACA,kBAAA,GACA,kBAAA,GACA,eAAA,GACA,iBAAA,GACA,aAAA,GACA,aAAA,EAAA,IACE,EAAQ;AAEZ,EAAA,EAAM,UAAA,MAAgB;AACpB,IAAI,KACJ,QAAQ,KACN,gBAAgB,IAAO,oBAAoB,wBAAA,kCAC7C;AAAA,EACF,GAAG,CAAC,GAAM,CAAM,CAAC;AAGjB,QAAM,IAAa,IAAc,EAAa,CAAW,IAAI,MACvD,IAA0B,CAAC;AACjC,EAAI,KAAU,KACZ,EAAM,KAAK;AAAA,IACT,OAAO,EAAO;AAAA,IACd,OAAO,EAAW,GAAY,EAAkB,gBAAgB;AAAA,EAClE,CAAC,GAEC,KAAU,KAAmB,QAC/B,EAAM,KAAK;AAAA,IACT,OAAO,EAAO;AAAA,IACd,OAAO,EAAe,GAAiB,QAAQ;AAAA,EACjD,CAAC,GAEC,KAAU,KAAiB,QAE7B,EAAM,KAAK;AAAA,IAAE,OAAO,EAAO;AAAA,IAAqB,OAAO,EAAiB,IAAgB,GAAG;AAAA,EAAE,CAAC;AAGhG,QAAM,IAAa,MAAW,UAAa,KAAU;AAErD,SACE,gBAAA,EAAC,GAAD;AAAA,IACE,GAAI;AAAA,IACJ,SAAS,IAAa,EAAe,GAAQ,QAAQ,IAAI;AAAA,IACzD,cAAc,IAAa,EAAO,gBAAgB;AAAA,IAClD,MACE,gBAAA,EAAC,GAAD;AAAA,MACE,UAAU,EAAQ,CAAY;AAAA,MAC9B,iBAAiB,KAAoB;AAAA,MACrC,iBAAiB,KAAoB;AAAA,IACtC,CAAA;AAAA,IAEH,MAAM;AAAA,IACC,OAAA;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACX,CAAA;AAEL"}
1
+ {"version":3,"file":"DebtsBlock.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/DebtsBlock/DebtsBlock.tsx"],"sourcesContent":["import React from 'react'\n\nimport { useTheme } from '@mui/material/styles'\n\nimport { useGlobalCopyStore } from '../../../../common'\nimport { slot, type InsightsPayload, type InstanceSlotRow } from '../../../../core'\nimport { DATE_FORMATS_INTL, formatDate } from '../../../../core/constants'\nimport type { DebtsBlockCopy } from '../../../../core/types/localization/InsightsFeedCopy'\nimport { formatCurrency, formatPercentage } from '../../../../core/utils/NumberFormatting'\n\nimport DepositLogo from '../../../components/ComponentBlocks/DepositLogo'\nimport DebtPayoffCard, { type DebtPayoffStat } from '../../../components/DebtPayoffCard'\nimport LogoFromGuid from '../../../components/LogoFromGuid'\nimport TransactionListCard from '../../../components/TransactionListCard'\nimport { resolveVariantConfig } from '../../resolveVariantConfig'\nimport { parseDueDate } from '../UpcomingBillBlock/UpcomingBillBlock'\n\nimport { DEBTS_LAYOUT, debtsBlockVariant } from './layout'\n\n// The card story reads the block's look from here.\nexport { PAYOFF_STYLE } from './layout'\n\ninterface DebtsBlockProps {\n payload: InsightsPayload\n beatGuid?: string\n}\n\nconst ROW_LOGO_SIZE = 32\n\n/** Account types drawn with the card glyph when there is no institution logo; the rest get the bank. */\nconst CREDIT_CARD_TYPES = new Set(['credit card', 'credit_card', 'creditcard'])\n\nconst iconFor = (accountType?: string) =>\n CREDIT_CARD_TYPES.has((accountType ?? '').trim().toLowerCase())\n ? 'credit_card'\n : 'account_balance'\n\n/** A summary row ditto can draw: an object with a name. Anything else in `series` is skipped. */\nconst isNamedRow = (row: unknown): row is InstanceSlotRow & { primary_text: string } =>\n typeof row === 'object' &&\n row !== null &&\n typeof (row as InstanceSlotRow).primary_text === 'string'\n\n/** Every label the payoff card renders; a partial namespace counts as missing. */\nconst hasAllLabels = (copy?: DebtsBlockCopy): copy is DebtsBlockCopy =>\n !!copy?.balance_label &&\n !!copy.payoff_date_label &&\n !!copy.monthly_payment_label &&\n !!copy.interest_rate_label\n\n/**\n * Debts component block — the content card for the Debt Payoff Strategies beat.\n * `instance_slot.variant` picks the card from `./layout.ts` through `resolveVariantConfig`, as\n * `AccountBlock` does:\n *\n * - `projected_payoff` — one account on the `DebtPayoffCard`. Its facts arrive flat on\n * `instance_slot` (the shape it shipped with): the balance (`amount`), `payoff_date`,\n * `monthly_payment`, `interest_rate`, plus the shared account/institution fields.\n * - `debt_summary` — the beat's several debt accounts on a `TransactionListCard`, read from\n * `instance_slot.data`: one row per account from `series` (pre-localized `logo`, `primary_text`\n * name, `secondary_text` rate, `amount` balance, in the order sent), an optional `header_text`,\n * and the total owed (`amount`) as the footer. With no rows there is nothing to summarize and the\n * block renders nothing.\n *\n * Captions and payoff row labels come from `insights_feed.debts_block` copy, which ships\n * separately. Each variant needs only its own keys: until they have shipped, the card shows what\n * needs no copy (the account row, the summary rows) but never an unlabelled figure, and warns once\n * per mount so the rollout gap is traceable. A row with no value (or an unparseable date) is\n * dropped rather than rendered blank.\n */\nconst DebtsBlock = ({ payload }: DebtsBlockProps) => {\n const theme = useTheme()\n const copy = useGlobalCopyStore().insights_feed?.debts_block\n const { instance_slot } = payload\n const { data, variant } = instance_slot\n\n const layout = resolveVariantConfig(\n DEBTS_LAYOUT,\n variant,\n debtsBlockVariant.ProjectedPayoff,\n 'DebtsBlock',\n )\n const isSummary = layout.card === 'summary'\n\n const labels = hasAllLabels(copy) ? copy : undefined\n const totalLabel = copy?.total_balance_label\n const hasCopy = isSummary ? !!totalLabel : !!labels\n\n React.useEffect(() => {\n if (hasCopy) return\n console.warn(\n `debts_block: ${copy ? 'copy incomplete' : 'copy namespace missing'}; rendering without its labelled figures`,\n )\n }, [copy, hasCopy])\n\n if (isSummary) {\n // `slot()` is an unchecked cast over backend data, so every value is narrowed before use.\n const series = slot<unknown[]>(data, 'series')\n const rows = (Array.isArray(series) ? series : []).filter(isNamedRow).map((row) => ({\n amount: typeof row.amount === 'number' ? formatCurrency(row.amount, '0,0.00') : '',\n leading: <LogoFromGuid logo={row.logo} size={ROW_LOGO_SIZE} />,\n subtitle: typeof row.secondary_text === 'string' ? row.secondary_text : '',\n title: row.primary_text,\n }))\n const header = slot<unknown>(data, 'header_text')\n const total = slot<unknown>(data, 'amount')\n\n return (\n <TransactionListCard\n background={theme.palette.primary.lighter}\n footer={\n totalLabel && typeof total === 'number' && Number.isFinite(total)\n ? { amount: formatCurrency(total, '0,0.00'), label: totalLabel }\n : undefined\n }\n header={typeof header === 'string' ? header : undefined}\n rows={rows}\n />\n )\n }\n\n const {\n account_name,\n account_type,\n amount,\n institution_guid,\n institution_name,\n interest_rate,\n monthly_payment,\n payoff_date,\n status_text,\n } = instance_slot\n\n const stats: DebtPayoffStat[] = []\n if (labels) {\n const payoffDate = payoff_date ? parseDueDate(payoff_date) : null\n if (payoffDate) {\n stats.push({\n label: labels.payoff_date_label,\n value: formatDate(payoffDate, DATE_FORMATS_INTL.MONTH_SHORT_YEAR),\n })\n }\n if (monthly_payment != null) {\n stats.push({\n label: labels.monthly_payment_label,\n value: formatCurrency(monthly_payment, '0,0.00'),\n })\n }\n if (interest_rate != null) {\n // `interest_rate` arrives as a percentage (19.99); Intl's percent style expects a fraction.\n stats.push({\n label: labels.interest_rate_label,\n value: formatPercentage(interest_rate / 100),\n })\n }\n }\n\n const hasBalance = labels !== undefined && amount != null\n\n return (\n <DebtPayoffCard\n {...layout.style}\n balance={hasBalance ? formatCurrency(amount, '0,0.00') : undefined}\n balanceLabel={hasBalance ? labels.balance_label : undefined}\n logo={\n <DepositLogo\n iconName={iconFor(account_type)}\n institutionGuid={institution_guid ?? ''}\n institutionName={institution_name ?? ''}\n />\n }\n name={account_name}\n stats={stats}\n statusLabel={status_text}\n subtitle={account_type}\n />\n )\n}\n\nexport default DebtsBlock\n"],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { DebtPayoffCardStyleProps } from '../../../components/DebtPayoffCard';
2
+ export declare const debtsBlockVariant: {
3
+ /** Debt Payoff Strategies, one account: balance plus projected payoff / monthly payment / rate rows. */
4
+ readonly ProjectedPayoff: "projected_payoff";
5
+ /** Debt Payoff Strategies, several accounts: one row per debt (balance, rate) and the total owed. */
6
+ readonly DebtSummary: "debt_summary";
7
+ };
8
+ export type DebtsBlockVariant = (typeof debtsBlockVariant)[keyof typeof debtsBlockVariant];
9
+ export interface DebtsBlockLayoutConfig {
10
+ /** Which card the variant draws: the single-account payoff card or the multi-account summary list. */
11
+ card: 'payoff' | 'summary';
12
+ /** Payoff card slot + pill tokens. */
13
+ style?: DebtPayoffCardStyleProps;
14
+ }
15
+ /** `projected_payoff` look: primary-tinted slot and pill. The card story mirrors it from here. */
16
+ export declare const PAYOFF_STYLE: DebtPayoffCardStyleProps;
17
+ export declare const DEBTS_LAYOUT: Record<string, DebtsBlockLayoutConfig>;
@@ -0,0 +1,24 @@
1
+ var r = {
2
+ ProjectedPayoff: "projected_payoff",
3
+ DebtSummary: "debt_summary"
4
+ }, e = {
5
+ bgcolor: "primary.lighter",
6
+ pill: {
7
+ bgcolor: "primary.lighter",
8
+ labelColor: "text.primary"
9
+ }
10
+ }, a = {
11
+ card: "payoff",
12
+ style: e
13
+ }, o = {
14
+ [r.ProjectedPayoff]: a,
15
+ [r.DebtSummary]: { card: "summary" },
16
+ default: a
17
+ };
18
+ export {
19
+ o as DEBTS_LAYOUT,
20
+ e as PAYOFF_STYLE,
21
+ r as debtsBlockVariant
22
+ };
23
+
24
+ //# sourceMappingURL=layout.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/DebtsBlock/layout.ts"],"sourcesContent":["import type { DebtPayoffCardStyleProps } from '../../../components/DebtPayoffCard'\n\nexport const debtsBlockVariant = {\n /** Debt Payoff Strategies, one account: balance plus projected payoff / monthly payment / rate rows. */\n ProjectedPayoff: 'projected_payoff',\n /** Debt Payoff Strategies, several accounts: one row per debt (balance, rate) and the total owed. */\n DebtSummary: 'debt_summary',\n} as const\n\nexport type DebtsBlockVariant = (typeof debtsBlockVariant)[keyof typeof debtsBlockVariant]\n\nexport interface DebtsBlockLayoutConfig {\n /** Which card the variant draws: the single-account payoff card or the multi-account summary list. */\n card: 'payoff' | 'summary'\n /** Payoff card slot + pill tokens. */\n style?: DebtPayoffCardStyleProps\n}\n\n/** `projected_payoff` look: primary-tinted slot and pill. The card story mirrors it from here. */\nexport const PAYOFF_STYLE: DebtPayoffCardStyleProps = {\n bgcolor: 'primary.lighter',\n pill: { bgcolor: 'primary.lighter', labelColor: 'text.primary' },\n}\n\nconst PROJECTED_PAYOFF: DebtsBlockLayoutConfig = { card: 'payoff', style: PAYOFF_STYLE }\n\nexport const DEBTS_LAYOUT: Record<string, DebtsBlockLayoutConfig> = {\n [debtsBlockVariant.ProjectedPayoff]: PROJECTED_PAYOFF,\n [debtsBlockVariant.DebtSummary]: { card: 'summary' },\n // Neutral fallback for an unknown variant: the payoff card. `resolveVariantConfig` warns first.\n default: PROJECTED_PAYOFF,\n}\n"],"mappings":"AAEA,IAAa,IAAoB;AAAA,EAE/B,iBAAiB;AAAA,EAEjB,aAAa;AACf,GAYa,IAAyC;AAAA,EACpD,SAAS;AAAA,EACT,MAAM;AAAA,IAAE,SAAS;AAAA,IAAmB,YAAY;AAAA,EAAe;AACjE,GAEM,IAA2C;AAAA,EAAE,MAAM;AAAA,EAAU,OAAO;AAAa,GAE1E,IAAuD;AAAA,EACjE,CAAA,EAAkB,eAAA,GAAkB;AAAA,EACpC,CAAA,EAAkB,WAAA,GAAc,EAAE,MAAM,UAAU;AAAA,EAEnD,SAAS;AACX"}
@@ -67,7 +67,7 @@ var yo = {}, go = {
67
67
  }
68
68
  await E(m, y);
69
69
  }
70
- }, S = oo[V], a = e.in_description_cta, f = !c && a?.label && a.block ? a : void 0, b = r?.label ?? (f ? void 0 : a?.label), B = !c && !!r?.label, T = !c && !!s?.label, C = I.insights_feed?.general, h = u?.state === "not_refreshable" && !P && !!C;
70
+ }, S = oo[V], a = e.in_description_cta, f = !c && a?.label && a.block ? a : void 0, b = r?.label || (f ? void 0 : a?.label) || void 0, B = !c && !!r?.label, T = !c && !!s?.label, C = I.insights_feed?.general, h = u?.state === "not_refreshable" && !P && !!C;
71
71
  return /* @__PURE__ */ t(X, {
72
72
  value: M,
73
73
  children: /* @__PURE__ */ l(g, {
@@ -1 +1 @@
1
- {"version":3,"file":"BaseLayout.es.js","names":[],"sources":["../../../src/insights-v2/components/BaseLayout.tsx"],"sourcesContent":["import { useMemo } from 'react'\n\nimport { observer } from 'mobx-react-lite'\n\nimport Box from '@mui/material/Box'\nimport Button from '@mui/material/Button'\nimport Card from '@mui/material/Card'\nimport Stack from '@mui/material/Stack'\n\nimport { ChevronRight } from '@mxenabled/mx-icons'\nimport { P, Text } from '@mxenabled/mxui'\n\nimport { blocks } from '../mappings/blocks'\nimport { actionBlocksKey } from '../mappings/actionBlocksKey'\nimport { isContactSupportCtaDisabled } from '../actionBlocks/ContactSupportActionBlock'\nimport { logoFromRef } from './shared/EntityLogo'\n\nimport Footer from './Footer'\nimport Header from './Header'\nimport FeedbackBar from './FeedbackBar'\nimport FeedbackDialog from './FeedbackDialog'\nimport DismissInsightDialog from './DismissInsightDialog'\nimport HiddenConfirmationCard from './HiddenConfirmationCard'\nimport ErrorCard from './ErrorCard'\nimport LoadingCard from './LoadingCard'\nimport { ObsolesceBanner, type ObsolesceBannerState } from './ObsolesceBanner'\nimport { useAppConfig, useGlobalCopyStore, useGlobalStore, useInsightsV2Store } from '../../common'\nimport type { Beat, PrimaryCTA, SecondaryCTA } from '../../core'\nimport { BeatActionsProvider, type BeatActions } from '../beatActions'\nimport { ActionBlockLayer } from '../actionBlocks/ActionBlockLayer'\nimport { reportCtaClick, useBeatCtaActions } from '../ctaActions'\nimport { useBeatFeedbackFlow } from '../hooks/useBeatFeedbackFlow'\n\nexport interface ObsoleteState {\n state: ObsolesceBannerState\n onRefresh: () => void\n onDismiss: () => void\n}\n\ninterface BaseLayoutProps {\n beat: Beat\n beatActions?: BeatActions\n obsolete?: ObsoleteState\n /** Swap only the block slot for a LoadingCard (e.g. while a sampled beat loads). */\n isLoading?: boolean\n /** Replace the entire card with an ErrorCard (e.g. when the sample fails to load). */\n isError?: boolean\n}\n\nconst NO_BEAT_ACTIONS: BeatActions = {}\n\nconst OBSOLETE_OVERLAY_SX = {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n backgroundColor: 'background.default',\n opacity: 0.7,\n zIndex: 1,\n} as const\n\n// Mini CTA label styled like a Button.\nconst MINI_CTA_SX = {\n alignItems: 'center',\n alignSelf: 'flex-start',\n display: 'flex',\n fontWeight: 600,\n height: 44,\n px: 2,\n textTransform: 'none',\n} as const\n\nconst BaseLayout = observer(\n ({\n beat,\n beatActions = NO_BEAT_ACTIONS,\n obsolete,\n isLoading = false,\n isError = false,\n }: BaseLayoutProps) => {\n const copy = useGlobalCopyStore()\n const insightsV2Store = useInsightsV2Store()\n const { config } = useAppConfig()\n const flow = useBeatFeedbackFlow(beat, beatActions)\n\n const stores = useGlobalStore()\n const {\n runCta: handleCtaClick,\n primary: primaryCtaState,\n secondary: secondaryCtaState,\n } = useBeatCtaActions(\n beat,\n beatActions,\n beat.insights_payload?.primary_cta,\n beat.insights_payload?.secondary_cta,\n )\n\n // Guard: payload may not be loaded yet (isLoading/isError states).\n const isMini = beat.insights_payload?.widget_type === 'mini'\n\n // Memoized: an inline object here would change identity every render, making every\n // useAnalyticsEvent() consumer's callback (and its effect deps) unstable too.\n const beatActionsValue = useMemo(\n () => ({ ...flow.wrappedActions, beat }),\n [flow.wrappedActions, beat],\n )\n\n // Error replaces the entire card; loading only swaps the block slot (below).\n if (isError) return <ErrorCard />\n\n const insights_payload = beat.insights_payload\n\n if (!insights_payload) return null\n if (flow.cardState === 'dismissed') return null\n\n const { instance_slot, primary_cta, secondary_cta, sub_title, title, guid, dismissed_at } =\n insights_payload\n const { block } = instance_slot\n\n // Rebuild V1 subtitle shape; sub_title wins if present.\n const subtitle =\n sub_title ??\n (insights_payload.subtitle\n ? {\n logo: logoFromRef(insights_payload.logo),\n text: insights_payload.subtitle,\n }\n : undefined)\n\n // CTAs run via ctaActions; contact_support_block bypasses it.\n const isCtaDisabled = (ctaBlock: string | null | undefined) =>\n isContactSupportCtaDisabled(ctaBlock, config, beatActions.onContactSupport)\n\n const onCtaClick = async (slot: 'primary' | 'secondary', cta: PrimaryCTA | SecondaryCTA) => {\n if (isCtaDisabled(cta.block)) return\n\n if (cta.block === actionBlocksKey.CONTACT_SUPPORT_ACTION_BLOCK) {\n // Bypasses the runner, but still reports the press like any other CTA: the generic\n // press event, and (on a first primary press) FIRST_TIME_PRIMARY_ACTION_SELECTED +\n // cta_clicked_at.\n reportCtaClick({ beat, stores, hostActions: beatActions, slot })\n beatActions.onContactSupport?.()\n return\n }\n\n await handleCtaClick(slot, cta)\n }\n\n const Block = blocks[block as keyof typeof blocks]\n\n const inDescriptionCta = insights_payload.in_description_cta\n // Full card: the envelope's link opens the drawer its block names. A link with no block (mini's\n // \"Make a Transfer\") is the card's action, drawn as the mini label below, never a dead link.\n const envelopeLink =\n !isMini && inDescriptionCta?.label && inDescriptionCta.block ? inDescriptionCta : undefined\n // The card's action label: the primary CTA's, else a block-less envelope link's (ditto ≥ 1.4.3\n // sends mini's action as in_description_cta with no primary_cta). It is a button only on a full\n // card with a primary CTA; otherwise a label, so a tap reaches the host's card handler.\n const ctaLabel = primary_cta?.label ?? (envelopeLink ? undefined : inDescriptionCta?.label)\n const isCtaButton = !isMini && !!primary_cta?.label\n const showSecondaryCta = !isMini && !!secondary_cta?.label\n const obsoleteCopy = copy.insights_feed?.general\n const isObsoleteDimmed =\n obsolete?.state === 'not_refreshable' && !dismissed_at && !!obsoleteCopy\n\n return (\n <BeatActionsProvider value={beatActionsValue}>\n <Stack sx={{ mb: 16 }}>\n {flow.cardState === 'confirming' ? (\n <HiddenConfirmationCard\n onClose={flow.collapseConfirmation}\n onLeaveFeedback={flow.openHideSurvey}\n onUndo={flow.undoDismiss}\n />\n ) : (\n <>\n {obsolete && obsoleteCopy && <ObsolesceBanner {...obsolete} copy={obsoleteCopy} />}\n <Card\n inert={isObsoleteDimmed}\n sx={{\n ...(isObsoleteDimmed && {\n position: 'relative',\n zIndex: 2,\n pointerEvents: 'none',\n }),\n }}\n >\n {isObsoleteDimmed && <Box sx={OBSOLETE_OVERLAY_SX} />}\n <Header isMini={isMini} subtitle={subtitle} title={title ?? ''} />\n {isLoading ? (\n <LoadingCard />\n ) : (\n Block && <Block beatGuid={guid} payload={insights_payload} />\n )}\n\n <Stack sx={{ gap: 6, pb: 16, pt: 12, px: 16 }}>\n <P\n dangerouslySetInnerHTML={{\n __html: insights_payload.description.html_text,\n }}\n variant=\"subtitle2\"\n />\n {/* V2: the envelope's link opens the action block it names. */}\n {envelopeLink && (\n <Button\n endIcon={<ChevronRight />}\n onClick={() =>\n insightsV2Store.openActionDrawer({ guid, trigger: 'inDescriptionCta' })\n }\n sx={{ height: 24, p: 4, width: 'max-content' }}\n >\n {envelopeLink.label}\n </Button>\n )}\n {/* V1: the legacy field, shown for beats that do not send the envelope link. */}\n {!inDescriptionCta?.label && beat?.in_description_cta && (\n <Button\n endIcon={<ChevronRight />}\n onClick={() => {}}\n sx={{ height: 24, p: 4, width: 'max-content' }}\n >\n {beat.in_description_cta}\n </Button>\n )}\n </Stack>\n\n {(ctaLabel || showSecondaryCta) && (\n <Stack sx={{ gap: 8, pb: 16, px: 16 }}>\n {ctaLabel &&\n !isCtaButton && (\n // Mini is a tap target, as in V1: the card, not this label, is the control. The label\n // is deliberately not a button, so a tap on it reaches the host's card handler (Pulse\n // posts `carousel/cta`, the same redirect a V1 mini card sends) instead of opening\n // the action drawer the full card's CTA opens.\n <Text color=\"primary.main\" sx={MINI_CTA_SX} variant=\"button\">\n {ctaLabel}\n </Text>\n )}\n {isCtaButton && primary_cta && (\n <Button\n aria-disabled={isCtaDisabled(primary_cta.block) || primaryCtaState.disabled}\n disabled={primaryCtaState.disabled}\n onClick={() => onCtaClick('primary', primary_cta)}\n sx={{\n ...(isCtaDisabled(primary_cta.block) && { color: 'text.disabled' }),\n }}\n variant=\"outlined\"\n >\n {primary_cta.label}\n </Button>\n )}\n {/* Mini has room for one CTA. */}\n {showSecondaryCta && secondary_cta && (\n <Button\n aria-disabled={\n isCtaDisabled(secondary_cta.block) || secondaryCtaState.disabled\n }\n color=\"secondary\"\n disabled={secondaryCtaState.disabled}\n onClick={() => onCtaClick('secondary', secondary_cta)}\n >\n {secondary_cta.label}\n </Button>\n )}\n </Stack>\n )}\n\n <FeedbackBar onTellUsMore={flow.openRatingSurvey} show={flow.isFeedbackBarShown} />\n </Card>\n </>\n )}\n\n <ActionBlockLayer beat={beat} />\n\n <DismissInsightDialog\n isOpen={flow.isDismissOpen}\n onClose={flow.closeDismissDialog}\n onDismiss={flow.confirmDismiss}\n />\n\n {flow.isSurveyOpen && (\n <FeedbackDialog\n characterLimitLabel={flow.survey.characterLimitLabel}\n closeAriaLabel={flow.survey.closeAriaLabel}\n isOpen={true}\n onBackClick={flow.feedbackDialogCallbacks.onBackClick}\n onClose={flow.closeSurvey}\n onSubmit={flow.submitSurvey}\n onTextInputFocus={flow.feedbackDialogCallbacks.onTextInputFocus}\n options={flow.survey.options}\n primaryText={flow.survey.submitText}\n secondaryText={flow.survey.backText}\n title={flow.survey.title}\n />\n )}\n\n {flow.cardState === 'visible' && insights_payload.footer && (\n <Footer footer={insights_payload.footer} />\n )}\n </Stack>\n </BeatActionsProvider>\n )\n },\n)\n\nexport default BaseLayout\n"],"mappings":"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"}
1
+ {"version":3,"file":"BaseLayout.es.js","names":[],"sources":["../../../src/insights-v2/components/BaseLayout.tsx"],"sourcesContent":["import { useMemo } from 'react'\n\nimport { observer } from 'mobx-react-lite'\n\nimport Box from '@mui/material/Box'\nimport Button from '@mui/material/Button'\nimport Card from '@mui/material/Card'\nimport Stack from '@mui/material/Stack'\n\nimport { ChevronRight } from '@mxenabled/mx-icons'\nimport { P, Text } from '@mxenabled/mxui'\n\nimport { blocks } from '../mappings/blocks'\nimport { actionBlocksKey } from '../mappings/actionBlocksKey'\nimport { isContactSupportCtaDisabled } from '../actionBlocks/ContactSupportActionBlock'\nimport { logoFromRef } from './shared/EntityLogo'\n\nimport Footer from './Footer'\nimport Header from './Header'\nimport FeedbackBar from './FeedbackBar'\nimport FeedbackDialog from './FeedbackDialog'\nimport DismissInsightDialog from './DismissInsightDialog'\nimport HiddenConfirmationCard from './HiddenConfirmationCard'\nimport ErrorCard from './ErrorCard'\nimport LoadingCard from './LoadingCard'\nimport { ObsolesceBanner, type ObsolesceBannerState } from './ObsolesceBanner'\nimport { useAppConfig, useGlobalCopyStore, useGlobalStore, useInsightsV2Store } from '../../common'\nimport type { Beat, PrimaryCTA, SecondaryCTA } from '../../core'\nimport { BeatActionsProvider, type BeatActions } from '../beatActions'\nimport { ActionBlockLayer } from '../actionBlocks/ActionBlockLayer'\nimport { reportCtaClick, useBeatCtaActions } from '../ctaActions'\nimport { useBeatFeedbackFlow } from '../hooks/useBeatFeedbackFlow'\n\nexport interface ObsoleteState {\n state: ObsolesceBannerState\n onRefresh: () => void\n onDismiss: () => void\n}\n\ninterface BaseLayoutProps {\n beat: Beat\n beatActions?: BeatActions\n obsolete?: ObsoleteState\n /** Swap only the block slot for a LoadingCard (e.g. while a sampled beat loads). */\n isLoading?: boolean\n /** Replace the entire card with an ErrorCard (e.g. when the sample fails to load). */\n isError?: boolean\n}\n\nconst NO_BEAT_ACTIONS: BeatActions = {}\n\nconst OBSOLETE_OVERLAY_SX = {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n backgroundColor: 'background.default',\n opacity: 0.7,\n zIndex: 1,\n} as const\n\n// Mini CTA label styled like a Button.\nconst MINI_CTA_SX = {\n alignItems: 'center',\n alignSelf: 'flex-start',\n display: 'flex',\n fontWeight: 600,\n height: 44,\n px: 2,\n textTransform: 'none',\n} as const\n\nconst BaseLayout = observer(\n ({\n beat,\n beatActions = NO_BEAT_ACTIONS,\n obsolete,\n isLoading = false,\n isError = false,\n }: BaseLayoutProps) => {\n const copy = useGlobalCopyStore()\n const insightsV2Store = useInsightsV2Store()\n const { config } = useAppConfig()\n const flow = useBeatFeedbackFlow(beat, beatActions)\n\n const stores = useGlobalStore()\n const {\n runCta: handleCtaClick,\n primary: primaryCtaState,\n secondary: secondaryCtaState,\n } = useBeatCtaActions(\n beat,\n beatActions,\n beat.insights_payload?.primary_cta,\n beat.insights_payload?.secondary_cta,\n )\n\n // Guard: payload may not be loaded yet (isLoading/isError states).\n const isMini = beat.insights_payload?.widget_type === 'mini'\n\n // Memoized: an inline object here would change identity every render, making every\n // useAnalyticsEvent() consumer's callback (and its effect deps) unstable too.\n const beatActionsValue = useMemo(\n () => ({ ...flow.wrappedActions, beat }),\n [flow.wrappedActions, beat],\n )\n\n // Error replaces the entire card; loading only swaps the block slot (below).\n if (isError) return <ErrorCard />\n\n const insights_payload = beat.insights_payload\n\n if (!insights_payload) return null\n if (flow.cardState === 'dismissed') return null\n\n const { instance_slot, primary_cta, secondary_cta, sub_title, title, guid, dismissed_at } =\n insights_payload\n const { block } = instance_slot\n\n // Rebuild V1 subtitle shape; sub_title wins if present.\n const subtitle =\n sub_title ??\n (insights_payload.subtitle\n ? {\n logo: logoFromRef(insights_payload.logo),\n text: insights_payload.subtitle,\n }\n : undefined)\n\n // CTAs run via ctaActions; contact_support_block bypasses it.\n const isCtaDisabled = (ctaBlock: string | null | undefined) =>\n isContactSupportCtaDisabled(ctaBlock, config, beatActions.onContactSupport)\n\n const onCtaClick = async (slot: 'primary' | 'secondary', cta: PrimaryCTA | SecondaryCTA) => {\n if (isCtaDisabled(cta.block)) return\n\n if (cta.block === actionBlocksKey.CONTACT_SUPPORT_ACTION_BLOCK) {\n // Bypasses the runner, but still reports the press like any other CTA: the generic\n // press event, and (on a first primary press) FIRST_TIME_PRIMARY_ACTION_SELECTED +\n // cta_clicked_at.\n reportCtaClick({ beat, stores, hostActions: beatActions, slot })\n beatActions.onContactSupport?.()\n return\n }\n\n await handleCtaClick(slot, cta)\n }\n\n const Block = blocks[block as keyof typeof blocks]\n\n const inDescriptionCta = insights_payload.in_description_cta\n // Full card: the envelope's link opens the drawer its block names. A link with no block (mini's\n // \"Make a Transfer\") is the card's action, drawn as the mini label below, never a dead link.\n const envelopeLink =\n !isMini && inDescriptionCta?.label && inDescriptionCta.block ? inDescriptionCta : undefined\n // The card's action label: the primary CTA's, else a block-less envelope link's (ditto ≥ 1.4.3\n // sends mini's action as in_description_cta). `||`, not `??`: the copy may send the primary label\n // as \"\" rather than omit it, and an empty string must fall through. It is a button only on a full\n // card with a primary CTA; otherwise a label, so a tap reaches the host's card handler.\n const ctaLabel =\n primary_cta?.label || (envelopeLink ? undefined : inDescriptionCta?.label) || undefined\n const isCtaButton = !isMini && !!primary_cta?.label\n const showSecondaryCta = !isMini && !!secondary_cta?.label\n const obsoleteCopy = copy.insights_feed?.general\n const isObsoleteDimmed =\n obsolete?.state === 'not_refreshable' && !dismissed_at && !!obsoleteCopy\n\n return (\n <BeatActionsProvider value={beatActionsValue}>\n <Stack sx={{ mb: 16 }}>\n {flow.cardState === 'confirming' ? (\n <HiddenConfirmationCard\n onClose={flow.collapseConfirmation}\n onLeaveFeedback={flow.openHideSurvey}\n onUndo={flow.undoDismiss}\n />\n ) : (\n <>\n {obsolete && obsoleteCopy && <ObsolesceBanner {...obsolete} copy={obsoleteCopy} />}\n <Card\n inert={isObsoleteDimmed}\n sx={{\n ...(isObsoleteDimmed && {\n position: 'relative',\n zIndex: 2,\n pointerEvents: 'none',\n }),\n }}\n >\n {isObsoleteDimmed && <Box sx={OBSOLETE_OVERLAY_SX} />}\n <Header isMini={isMini} subtitle={subtitle} title={title ?? ''} />\n {isLoading ? (\n <LoadingCard />\n ) : (\n Block && <Block beatGuid={guid} payload={insights_payload} />\n )}\n\n <Stack sx={{ gap: 6, pb: 16, pt: 12, px: 16 }}>\n <P\n dangerouslySetInnerHTML={{\n __html: insights_payload.description.html_text,\n }}\n variant=\"subtitle2\"\n />\n {/* V2: the envelope's link opens the action block it names. */}\n {envelopeLink && (\n <Button\n endIcon={<ChevronRight />}\n onClick={() =>\n insightsV2Store.openActionDrawer({ guid, trigger: 'inDescriptionCta' })\n }\n sx={{ height: 24, p: 4, width: 'max-content' }}\n >\n {envelopeLink.label}\n </Button>\n )}\n {/* V1: the legacy field, shown for beats that do not send the envelope link. */}\n {!inDescriptionCta?.label && beat?.in_description_cta && (\n <Button\n endIcon={<ChevronRight />}\n onClick={() => {}}\n sx={{ height: 24, p: 4, width: 'max-content' }}\n >\n {beat.in_description_cta}\n </Button>\n )}\n </Stack>\n\n {(ctaLabel || showSecondaryCta) && (\n <Stack sx={{ gap: 8, pb: 16, px: 16 }}>\n {ctaLabel &&\n !isCtaButton && (\n // Mini is a tap target, as in V1: the card, not this label, is the control. The label\n // is deliberately not a button, so a tap on it reaches the host's card handler (Pulse\n // posts `carousel/cta`, the same redirect a V1 mini card sends) instead of opening\n // the action drawer the full card's CTA opens.\n <Text color=\"primary.main\" sx={MINI_CTA_SX} variant=\"button\">\n {ctaLabel}\n </Text>\n )}\n {isCtaButton && primary_cta && (\n <Button\n aria-disabled={isCtaDisabled(primary_cta.block) || primaryCtaState.disabled}\n disabled={primaryCtaState.disabled}\n onClick={() => onCtaClick('primary', primary_cta)}\n sx={{\n ...(isCtaDisabled(primary_cta.block) && { color: 'text.disabled' }),\n }}\n variant=\"outlined\"\n >\n {primary_cta.label}\n </Button>\n )}\n {/* Mini has room for one CTA. */}\n {showSecondaryCta && secondary_cta && (\n <Button\n aria-disabled={\n isCtaDisabled(secondary_cta.block) || secondaryCtaState.disabled\n }\n color=\"secondary\"\n disabled={secondaryCtaState.disabled}\n onClick={() => onCtaClick('secondary', secondary_cta)}\n >\n {secondary_cta.label}\n </Button>\n )}\n </Stack>\n )}\n\n <FeedbackBar onTellUsMore={flow.openRatingSurvey} show={flow.isFeedbackBarShown} />\n </Card>\n </>\n )}\n\n <ActionBlockLayer beat={beat} />\n\n <DismissInsightDialog\n isOpen={flow.isDismissOpen}\n onClose={flow.closeDismissDialog}\n onDismiss={flow.confirmDismiss}\n />\n\n {flow.isSurveyOpen && (\n <FeedbackDialog\n characterLimitLabel={flow.survey.characterLimitLabel}\n closeAriaLabel={flow.survey.closeAriaLabel}\n isOpen={true}\n onBackClick={flow.feedbackDialogCallbacks.onBackClick}\n onClose={flow.closeSurvey}\n onSubmit={flow.submitSurvey}\n onTextInputFocus={flow.feedbackDialogCallbacks.onTextInputFocus}\n options={flow.survey.options}\n primaryText={flow.survey.submitText}\n secondaryText={flow.survey.backText}\n title={flow.survey.title}\n />\n )}\n\n {flow.cardState === 'visible' && insights_payload.footer && (\n <Footer footer={insights_payload.footer} />\n )}\n </Stack>\n </BeatActionsProvider>\n )\n },\n)\n\nexport default BaseLayout\n"],"mappings":"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"}
@@ -2,7 +2,7 @@ import C from "./InsightTransactionRow.es.js";
2
2
  import { Fragment as R } from "react";
3
3
  import t from "@mui/material/Stack";
4
4
  import { Text as h } from "@mxenabled/mxui";
5
- import { Fragment as x, jsx as r, jsxs as d } from "react/jsx-runtime";
5
+ import { Fragment as x, jsx as r, jsxs as a } from "react/jsx-runtime";
6
6
  import v from "@mui/material/Box";
7
7
  import p from "@mui/material/Divider";
8
8
  var w = (n) => n === "primary" ? {
@@ -29,9 +29,9 @@ var w = (n) => n === "primary" ? {
29
29
  px: 16,
30
30
  py: 2
31
31
  }
32
- }, H = ({ background: n, footer: l, header: i, rows: m, variant: g = "default", sx: b }) => {
32
+ }, H = ({ background: n, footer: l, header: d, rows: m, variant: g = "default", sx: b }) => {
33
33
  if (m.length === 0) return null;
34
- const e = w(g), a = !!n, o = a ? "8px" : e.radius, s = !!i && !a && e.headerInsideBorder, c = i ? /* @__PURE__ */ r(t, {
34
+ const e = w(g), i = !!n, o = i ? "8px" : e.radius, s = !!d && !i && e.headerInsideBorder, c = d ? /* @__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: i
44
+ children: d
45
45
  })
46
- }) : null, f = l ? /* @__PURE__ */ d(x, { children: [/* @__PURE__ */ r(p, {}), /* @__PURE__ */ d(t, {
46
+ }) : null, f = l ? /* @__PURE__ */ a(x, { children: [/* @__PURE__ */ r(p, {}), /* @__PURE__ */ a(t, {
47
47
  sx: {
48
48
  alignItems: "center",
49
- bgcolor: a ? "background.paper" : "background.default",
49
+ bgcolor: i ? "background.paper" : "background.default",
50
50
  flexDirection: "row",
51
51
  justifyContent: "space-between",
52
52
  minHeight: 40,
@@ -66,14 +66,15 @@ var w = (n) => n === "primary" ? {
66
66
  })] }) : null, B = /* @__PURE__ */ r(t, {
67
67
  role: "list",
68
68
  sx: { width: "100%" },
69
- children: m.map((y, u) => /* @__PURE__ */ d(R, { children: [u > 0 && /* @__PURE__ */ r(p, { role: "presentation" }), /* @__PURE__ */ r(v, {
69
+ children: m.map((y, u) => /* @__PURE__ */ a(R, { children: [u > 0 && /* @__PURE__ */ r(p, { role: "presentation" }), /* @__PURE__ */ r(v, {
70
70
  role: "listitem",
71
71
  children: /* @__PURE__ */ r(C, { ...y })
72
72
  })] }, u))
73
73
  });
74
- return /* @__PURE__ */ d(t, {
74
+ return /* @__PURE__ */ a(t, {
75
+ "data-testid": "transaction-list-card",
75
76
  sx: {
76
- ...a ? {
77
+ ...i ? {
77
78
  background: n,
78
79
  p: 16
79
80
  } : {
@@ -90,21 +91,21 @@ var w = (n) => n === "primary" ? {
90
91
  overflow: "hidden"
91
92
  },
92
93
  children: c
93
- }), /* @__PURE__ */ d(t, {
94
+ }), /* @__PURE__ */ a(t, {
94
95
  sx: {
95
- ...a ? { bgcolor: "background.paper" } : {
96
+ ...i ? { bgcolor: "background.paper" } : {
96
97
  border: "1px solid",
97
98
  borderColor: e.borderColor
98
99
  },
99
100
  borderBottomLeftRadius: o,
100
101
  borderBottomRightRadius: o,
101
- borderTopLeftRadius: s || !i ? o : 0,
102
- borderTopRightRadius: s || !i ? o : 0,
102
+ borderTopLeftRadius: s || !d ? o : 0,
103
+ borderTopRightRadius: s || !d ? o : 0,
103
104
  overflow: "hidden",
104
105
  width: "100%"
105
106
  },
106
107
  children: [
107
- s && /* @__PURE__ */ d(x, { children: [c, /* @__PURE__ */ r(p, {})] }),
108
+ s && /* @__PURE__ */ a(x, { children: [c, /* @__PURE__ */ r(p, {})] }),
108
109
  B,
109
110
  f
110
111
  ]
@@ -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: '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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"}
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 data-testid=\"transaction-list-card\"\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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"}
@@ -5,3 +5,11 @@
5
5
  * `minimal`).
6
6
  */
7
7
  export declare const statusIconName: (guid?: string | null) => string | undefined;
8
+ export type StatusIconPalette = 'error' | 'success' | 'warning';
9
+ /**
10
+ * The theme palette a status icon's `color` names (`success.main` → `success`), for the tinted tile
11
+ * the micro card draws it in. The value is server data that becomes a palette key, so only these
12
+ * three status palettes are accepted; anything else — another palette, a raw colour, a CSS
13
+ * break-out — is the error tint, the tile's original colour.
14
+ */
15
+ export declare const statusIconPalette: (color?: string | null) => StatusIconPalette;
@@ -1,10 +1,15 @@
1
- import { IconList as o } from "@mxenabled/mx-icons";
2
- var n = (e) => {
3
- const t = /^ICO-([a-z0-9_]+)$/.exec(e ?? "")?.[1];
4
- return t && Object.hasOwn(o, t) ? t : void 0;
5
- };
1
+ import { IconList as n } from "@mxenabled/mx-icons";
2
+ var t = (r) => {
3
+ const a = /^ICO-([a-z0-9_]+)$/.exec(r ?? "")?.[1];
4
+ return a && Object.hasOwn(n, a) ? a : void 0;
5
+ }, e = {
6
+ "error.main": "error",
7
+ "success.main": "success",
8
+ "warning.main": "warning"
9
+ }, c = (r) => r && Object.hasOwn(e, r) && e[r] || "error";
6
10
  export {
7
- n as statusIconName
11
+ t as statusIconName,
12
+ c as statusIconPalette
8
13
  };
9
14
 
10
15
  //# sourceMappingURL=statusIcon.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"statusIcon.es.js","names":[],"sources":["../../../src/insights-v2/components/statusIcon.ts"],"sourcesContent":["import { IconList } from '@mxenabled/mx-icons'\n\n/**\n * The mx-icons name an `ICO-<name>` guid carries (`ICO-error` → `error`), or undefined for any other\n * guid, a malformed name, or a name mx-icons does not define — so a caller renders nothing rather\n * than an empty box. ditto names a status icon this way where a block has no entity logo (account_block\n * `minimal`).\n */\nexport const statusIconName = (guid?: string | null): string | undefined => {\n const name = /^ICO-([a-z0-9_]+)$/.exec(guid ?? '')?.[1]\n\n // Own keys only: `in` would also accept inherited names such as `constructor`.\n return name && Object.hasOwn(IconList, name) ? name : undefined\n}\n"],"mappings":";AAQA,IAAa,IAAA,CAAkB,MAA6C;AAC1E,QAAM,IAAO,qBAAqB,KAAK,KAAQ,EAAE,IAAI,CAAA;AAGrD,SAAO,KAAQ,OAAO,OAAO,GAAU,CAAI,IAAI,IAAO;AACxD"}
1
+ {"version":3,"file":"statusIcon.es.js","names":[],"sources":["../../../src/insights-v2/components/statusIcon.ts"],"sourcesContent":["import { IconList } from '@mxenabled/mx-icons'\n\n/**\n * The mx-icons name an `ICO-<name>` guid carries (`ICO-error` → `error`), or undefined for any other\n * guid, a malformed name, or a name mx-icons does not define — so a caller renders nothing rather\n * than an empty box. ditto names a status icon this way where a block has no entity logo (account_block\n * `minimal`).\n */\nexport const statusIconName = (guid?: string | null): string | undefined => {\n const name = /^ICO-([a-z0-9_]+)$/.exec(guid ?? '')?.[1]\n\n // Own keys only: `in` would also accept inherited names such as `constructor`.\n return name && Object.hasOwn(IconList, name) ? name : undefined\n}\n\nexport type StatusIconPalette = 'error' | 'success' | 'warning'\n\nconst STATUS_PALETTES: Record<string, StatusIconPalette> = {\n 'error.main': 'error',\n 'success.main': 'success',\n 'warning.main': 'warning',\n}\n\n/**\n * The theme palette a status icon's `color` names (`success.main` → `success`), for the tinted tile\n * the micro card draws it in. The value is server data that becomes a palette key, so only these\n * three status palettes are accepted; anything else — another palette, a raw colour, a CSS\n * break-out — is the error tint, the tile's original colour.\n */\nexport const statusIconPalette = (color?: string | null): StatusIconPalette =>\n (color && Object.hasOwn(STATUS_PALETTES, color) && STATUS_PALETTES[color]) || 'error'\n"],"mappings":";AAQA,IAAa,IAAA,CAAkB,MAA6C;AAC1E,QAAM,IAAO,qBAAqB,KAAK,KAAQ,EAAE,IAAI,CAAA;AAGrD,SAAO,KAAQ,OAAO,OAAO,GAAU,CAAI,IAAI,IAAO;AACxD,GAIM,IAAqD;AAAA,EACzD,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,gBAAgB;AAClB,GAQa,IAAA,CAAqB,MAC/B,KAAS,OAAO,OAAO,GAAiB,CAAK,KAAK,EAAgB,CAAA,KAAW"}
@@ -1,21 +1,22 @@
1
1
  import { AccountType as u } from "../../core/types/Account.es.js";
2
- import { BEAT_OPERATION_1 as o, BEAT_OPERATION_2 as s } from "../../common/utils/PostMessage.es.js";
3
- var c = (a) => !a.is_hidden && !a.is_deleted && !a.is_closed, i = ({ beat: a, stores: t }) => a.primary_account ?? t.accountStore.accounts.find((n) => n.guid === a.primary_account_guid), l = ({ beat: a, stores: t }) => {
4
- const n = new Set(a.account_guids);
5
- return t.accountStore.accounts.filter((e) => n.has(e.guid) && c(e));
6
- }, d = ({ stores: a }) => a.accountStore.accounts.filter((t) => t.account_type === u.SAVINGS && c(t)), _ = {
7
- SaveAnExtra100Dollars: { primary: () => ({ action: o }) },
2
+ import { BEAT_OPERATION_1 as n, BEAT_OPERATION_2 as s } from "../../common/utils/PostMessage.es.js";
3
+ var r = (a) => !a.is_hidden && !a.is_deleted && !a.is_closed, i = ({ beat: a, stores: t }) => a.primary_account ?? t.accountStore.accounts.find((o) => o.guid === a.primary_account_guid), l = ({ beat: a, stores: t }) => {
4
+ const o = new Set(a.account_guids);
5
+ return t.accountStore.accounts.filter((e) => o.has(e.guid) && r(e));
6
+ }, d = ({ stores: a }) => a.accountStore.accounts.filter((t) => t.account_type === u.SAVINGS && r(t)), _ = {
7
+ SaveAnExtra100Dollars: { primary: () => ({ action: n }) },
8
+ PaydayCashLeftOverStatus: { primary: () => ({ action: n }) },
8
9
  LowAccountBalance: { primary: (a) => {
9
10
  const t = i(a);
10
11
  return t ? {
11
- action: o,
12
+ action: n,
12
13
  payload: { account_guid: t.external_guid }
13
14
  } : null;
14
15
  } },
15
- MonthlyObligationsStatus: { primary: ({ beat: a }) => (a.payload?.total_remaining ?? 0) < 0 ? { action: o } : null },
16
- DesignateEmergencySavingsAccount: { primary: ({ beat: a }) => !a.payload?.emergency_savings_account_guid && !a.account_guids.length ? { action: o } : null },
16
+ MonthlyObligationsStatus: { primary: ({ beat: a }) => (a.payload?.total_remaining ?? 0) < 0 ? { action: n } : null },
17
+ DesignateEmergencySavingsAccount: { primary: ({ beat: a }) => !a.payload?.emergency_savings_account_guid && !a.account_guids.length ? { action: n } : null },
17
18
  ReplenishSavings: { primary: (a) => ({
18
- action: o,
19
+ action: n,
19
20
  payload: {
20
21
  total_amount_withdrawn: a.beat.payload?.total_amount,
21
22
  accounts: l(a).map((t) => ({
@@ -27,15 +28,15 @@ var c = (a) => !a.is_hidden && !a.is_deleted && !a.is_closed, i = ({ beat: a, st
27
28
  SavingsOpportunityV2: { primary: (a) => {
28
29
  const t = i(a);
29
30
  if (!t) return null;
30
- const n = d(a), e = {
31
+ const o = d(a), e = {
31
32
  amount: a.beat.payload?.suggested_savings_amount,
32
33
  source_account_id: t.external_guid
33
34
  };
34
- return n.length ? {
35
- action: o,
35
+ return o.length ? {
36
+ action: n,
36
37
  payload: {
37
38
  ...e,
38
- destination_account_ids: n.map((r) => r.external_guid)
39
+ destination_account_ids: o.map((c) => c.external_guid)
39
40
  }
40
41
  } : {
41
42
  action: s,
@@ -1 +1 @@
1
- {"version":3,"file":"ctaPostMessages.es.js","names":[],"sources":["../../../src/insights-v2/ctaActions/ctaPostMessages.ts"],"sourcesContent":["import { BEAT_OPERATION_1, BEAT_OPERATION_2 } from '../../common/utils/PostMessage'\nimport { AccountType, type Account, type CtaPostMessageMetadata } from '../../core'\nimport type { CtaSlot, CtaStateContext } from './types'\n\n/**\n * Interim per-template post messages, carried over from the pulse beats, for CTAs the backend\n * does not yet describe with `cta.metadata`. Each resolver returns the same shape the backend\n * will send, or `null` for \"no message\" (the default then only opens the drawer for a block).\n * Backend `metadata` always wins, so entries become dead the moment tupac ships the key for\n * their template.\n *\n * Remove once every template here has `metadata` from the backend: delete this file, its test\n * and README section, and the `resolveCtaMetadata` call in `runCtaAction.ts`.\n */\nexport type CtaPostMessageResolver = (ctx: CtaStateContext) => CtaPostMessageMetadata | null\n\ntype BeatContext = Pick<CtaStateContext, 'beat' | 'stores'>\n\nconst isUsable = (account: Account) =>\n !account.is_hidden && !account.is_deleted && !account.is_closed\n\n/** The beat's primary account: from the beat when the host attached it, else the account store. */\nconst primaryAccountOf = ({ beat, stores }: BeatContext): Account | undefined =>\n beat.primary_account ??\n stores.accountStore.accounts.find((account) => account.guid === beat.primary_account_guid)\n\n/** The accounts the beat points at (`account_guids`), as loaded in the account store. */\nconst beatAccountsOf = ({ beat, stores }: BeatContext): Account[] => {\n const guids = new Set<string>(beat.account_guids)\n\n return stores.accountStore.accounts.filter(\n (account) => guids.has(account.guid) && isUsable(account),\n )\n}\n\nconst savingsAccountsOf = ({ stores }: BeatContext): Account[] =>\n stores.accountStore.accounts.filter(\n (account) => account.account_type === AccountType.SAVINGS && isUsable(account),\n )\n\nexport const ctaPostMessages: Record<string, Partial<Record<CtaSlot, CtaPostMessageResolver>>> = {\n /** \"Make Transfer\": the base `beat/cta` op_1, nothing beat-specific. */\n SaveAnExtra100Dollars: {\n primary: () => ({ action: BEAT_OPERATION_1 }),\n },\n\n /** \"Transfer\": op_1 with the primary account's external id. No primary account → default. */\n LowAccountBalance: {\n primary: (ctx) => {\n const account = primaryAccountOf(ctx)\n\n return account\n ? { action: BEAT_OPERATION_1, payload: { account_guid: account.external_guid } }\n : null\n },\n },\n\n /** Posts only while off track (negative remaining); on track the CTA opens the drawer. */\n MonthlyObligationsStatus: {\n primary: ({ beat }) =>\n (beat.payload?.total_remaining ?? 0) < 0 ? { action: BEAT_OPERATION_1 } : null,\n },\n\n /**\n * \"Open savings account\": only when nothing is designated and there is no savings account to\n * pick from. The other states save the pick through an `action_key` (see `ctaConfig.ts`).\n */\n DesignateEmergencySavingsAccount: {\n primary: ({ beat }) =>\n !beat.payload?.emergency_savings_account_guid && !beat.account_guids.length\n ? { action: BEAT_OPERATION_1 }\n : null,\n },\n\n /** op_1 with the withdrawn total and the beat's accounts (external ids). */\n ReplenishSavings: {\n primary: (ctx) => ({\n action: BEAT_OPERATION_1,\n payload: {\n total_amount_withdrawn: ctx.beat.payload?.total_amount,\n accounts: beatAccountsOf(ctx).map((account) => ({\n account_guid: account.external_guid,\n account_name: ctx.beat.payload?.account_name?.default,\n })),\n },\n }),\n },\n\n /** op_1 = transfer into the user's savings accounts; op_2 = open one when there are none. */\n SavingsOpportunityV2: {\n primary: (ctx) => {\n const source = primaryAccountOf(ctx)\n\n if (!source) return null\n\n const savings = savingsAccountsOf(ctx)\n const payload = {\n amount: ctx.beat.payload?.suggested_savings_amount,\n source_account_id: source.external_guid,\n }\n\n return savings.length\n ? {\n action: BEAT_OPERATION_1,\n payload: {\n ...payload,\n destination_account_ids: savings.map((account) => account.external_guid),\n },\n }\n : { action: BEAT_OPERATION_2, payload }\n },\n },\n}\n\n/** Backend `cta.metadata` first, else this template's interim resolver for the slot, else null. */\nexport const resolveCtaMetadata = (ctx: CtaStateContext): CtaPostMessageMetadata | null =>\n ctx.cta.metadata ?? ctaPostMessages[ctx.beat.template]?.[ctx.slot]?.(ctx) ?? null\n"],"mappings":";;AAkBA,IAAM,IAAA,CAAY,MAChB,CAAC,EAAQ,aAAa,CAAC,EAAQ,cAAc,CAAC,EAAQ,WAGlD,IAAA,CAAoB,EAAE,MAAA,GAAM,QAAA,EAAA,MAChC,EAAK,mBACL,EAAO,aAAa,SAAS,KAAA,CAAM,MAAY,EAAQ,SAAS,EAAK,oBAAoB,GAGrF,IAAA,CAAkB,EAAE,MAAA,GAAM,QAAA,EAAA,MAAqC;AACnE,QAAM,IAAQ,IAAI,IAAY,EAAK,aAAa;AAEhD,SAAO,EAAO,aAAa,SAAS,OAAA,CACjC,MAAY,EAAM,IAAI,EAAQ,IAAI,KAAK,EAAS,CAAO,CAC1D;AACF,GAEM,IAAA,CAAqB,EAAE,QAAA,EAAA,MAC3B,EAAO,aAAa,SAAS,OAAA,CAC1B,MAAY,EAAQ,iBAAiB,EAAY,WAAW,EAAS,CAAO,CAC/E,GAEW,IAAoF;AAAA,EAE/F,uBAAuB,EACrB,SAAA,OAAgB,EAAE,QAAQ,EAAiB,GAC7C;AAAA,EAGA,mBAAmB,EACjB,SAAA,CAAU,MAAQ;AAChB,UAAM,IAAU,EAAiB,CAAG;AAEpC,WAAO,IACH;AAAA,MAAE,QAAQ;AAAA,MAAkB,SAAS,EAAE,cAAc,EAAQ,cAAc;AAAA,IAAE,IAC7E;AAAA,EACN,EACF;AAAA,EAGA,0BAA0B,EACxB,SAAA,CAAU,EAAE,MAAA,EAAA,OACT,EAAK,SAAS,mBAAmB,KAAK,IAAI,EAAE,QAAQ,EAAiB,IAAI,KAC9E;AAAA,EAMA,kCAAkC,EAChC,SAAA,CAAU,EAAE,MAAA,EAAA,MACV,CAAC,EAAK,SAAS,kCAAkC,CAAC,EAAK,cAAc,SACjE,EAAE,QAAQ,EAAiB,IAC3B,KACR;AAAA,EAGA,kBAAkB,EAChB,SAAA,CAAU,OAAS;AAAA,IACjB,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,wBAAwB,EAAI,KAAK,SAAS;AAAA,MAC1C,UAAU,EAAe,CAAG,EAAE,IAAA,CAAK,OAAa;AAAA,QAC9C,cAAc,EAAQ;AAAA,QACtB,cAAc,EAAI,KAAK,SAAS,cAAc;AAAA,MAChD,EAAE;AAAA,IACJ;AAAA,EACF,GACF;AAAA,EAGA,sBAAsB,EACpB,SAAA,CAAU,MAAQ;AAChB,UAAM,IAAS,EAAiB,CAAG;AAEnC,QAAI,CAAC,EAAQ,QAAO;AAEpB,UAAM,IAAU,EAAkB,CAAG,GAC/B,IAAU;AAAA,MACd,QAAQ,EAAI,KAAK,SAAS;AAAA,MAC1B,mBAAmB,EAAO;AAAA,IAC5B;AAEA,WAAO,EAAQ,SACX;AAAA,MACE,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,GAAG;AAAA,QACH,yBAAyB,EAAQ,IAAA,CAAK,MAAY,EAAQ,aAAa;AAAA,MACzE;AAAA,IACF,IACA;AAAA,MAAE,QAAQ;AAAA,MAAkB,SAAA;AAAA,IAAQ;AAAA,EAC1C,EACF;AACF,GAGa,IAAA,CAAsB,MACjC,EAAI,IAAI,YAAY,EAAgB,EAAI,KAAK,QAAA,IAAY,EAAI,IAAA,IAAQ,CAAG,KAAK"}
1
+ {"version":3,"file":"ctaPostMessages.es.js","names":[],"sources":["../../../src/insights-v2/ctaActions/ctaPostMessages.ts"],"sourcesContent":["import { BEAT_OPERATION_1, BEAT_OPERATION_2 } from '../../common/utils/PostMessage'\nimport { AccountType, type Account, type CtaPostMessageMetadata } from '../../core'\nimport type { CtaSlot, CtaStateContext } from './types'\n\n/**\n * Interim per-template post messages, carried over from the pulse beats, for CTAs the backend\n * does not yet describe with `cta.metadata`. Each resolver returns the same shape the backend\n * will send, or `null` for \"no message\" (the default then only opens the drawer for a block).\n * Backend `metadata` always wins, so entries become dead the moment tupac ships the key for\n * their template.\n *\n * Remove once every template here has `metadata` from the backend: delete this file, its test\n * and README section, and the `resolveCtaMetadata` call in `runCtaAction.ts`.\n */\nexport type CtaPostMessageResolver = (ctx: CtaStateContext) => CtaPostMessageMetadata | null\n\ntype BeatContext = Pick<CtaStateContext, 'beat' | 'stores'>\n\nconst isUsable = (account: Account) =>\n !account.is_hidden && !account.is_deleted && !account.is_closed\n\n/** The beat's primary account: from the beat when the host attached it, else the account store. */\nconst primaryAccountOf = ({ beat, stores }: BeatContext): Account | undefined =>\n beat.primary_account ??\n stores.accountStore.accounts.find((account) => account.guid === beat.primary_account_guid)\n\n/** The accounts the beat points at (`account_guids`), as loaded in the account store. */\nconst beatAccountsOf = ({ beat, stores }: BeatContext): Account[] => {\n const guids = new Set<string>(beat.account_guids)\n\n return stores.accountStore.accounts.filter(\n (account) => guids.has(account.guid) && isUsable(account),\n )\n}\n\nconst savingsAccountsOf = ({ stores }: BeatContext): Account[] =>\n stores.accountStore.accounts.filter(\n (account) => account.account_type === AccountType.SAVINGS && isUsable(account),\n )\n\nexport const ctaPostMessages: Record<string, Partial<Record<CtaSlot, CtaPostMessageResolver>>> = {\n /** \"Make Transfer\": the base `beat/cta` op_1, nothing beat-specific. */\n SaveAnExtra100Dollars: {\n primary: () => ({ action: BEAT_OPERATION_1 }),\n },\n\n /** \"Transfer to Savings\" / \"Transfer Funds\": the base `beat/cta` op_1 on both variants. */\n PaydayCashLeftOverStatus: {\n primary: () => ({ action: BEAT_OPERATION_1 }),\n },\n\n /** \"Transfer\": op_1 with the primary account's external id. No primary account → default. */\n LowAccountBalance: {\n primary: (ctx) => {\n const account = primaryAccountOf(ctx)\n\n return account\n ? { action: BEAT_OPERATION_1, payload: { account_guid: account.external_guid } }\n : null\n },\n },\n\n /** Posts only while off track (negative remaining); on track the CTA opens the drawer. */\n MonthlyObligationsStatus: {\n primary: ({ beat }) =>\n (beat.payload?.total_remaining ?? 0) < 0 ? { action: BEAT_OPERATION_1 } : null,\n },\n\n /**\n * \"Open savings account\": only when nothing is designated and there is no savings account to\n * pick from. The other states save the pick through an `action_key` (see `ctaConfig.ts`).\n */\n DesignateEmergencySavingsAccount: {\n primary: ({ beat }) =>\n !beat.payload?.emergency_savings_account_guid && !beat.account_guids.length\n ? { action: BEAT_OPERATION_1 }\n : null,\n },\n\n /** op_1 with the withdrawn total and the beat's accounts (external ids). */\n ReplenishSavings: {\n primary: (ctx) => ({\n action: BEAT_OPERATION_1,\n payload: {\n total_amount_withdrawn: ctx.beat.payload?.total_amount,\n accounts: beatAccountsOf(ctx).map((account) => ({\n account_guid: account.external_guid,\n account_name: ctx.beat.payload?.account_name?.default,\n })),\n },\n }),\n },\n\n /** op_1 = transfer into the user's savings accounts; op_2 = open one when there are none. */\n SavingsOpportunityV2: {\n primary: (ctx) => {\n const source = primaryAccountOf(ctx)\n\n if (!source) return null\n\n const savings = savingsAccountsOf(ctx)\n const payload = {\n amount: ctx.beat.payload?.suggested_savings_amount,\n source_account_id: source.external_guid,\n }\n\n return savings.length\n ? {\n action: BEAT_OPERATION_1,\n payload: {\n ...payload,\n destination_account_ids: savings.map((account) => account.external_guid),\n },\n }\n : { action: BEAT_OPERATION_2, payload }\n },\n },\n}\n\n/** Backend `cta.metadata` first, else this template's interim resolver for the slot, else null. */\nexport const resolveCtaMetadata = (ctx: CtaStateContext): CtaPostMessageMetadata | null =>\n ctx.cta.metadata ?? ctaPostMessages[ctx.beat.template]?.[ctx.slot]?.(ctx) ?? null\n"],"mappings":";;AAkBA,IAAM,IAAA,CAAY,MAChB,CAAC,EAAQ,aAAa,CAAC,EAAQ,cAAc,CAAC,EAAQ,WAGlD,IAAA,CAAoB,EAAE,MAAA,GAAM,QAAA,EAAA,MAChC,EAAK,mBACL,EAAO,aAAa,SAAS,KAAA,CAAM,MAAY,EAAQ,SAAS,EAAK,oBAAoB,GAGrF,IAAA,CAAkB,EAAE,MAAA,GAAM,QAAA,EAAA,MAAqC;AACnE,QAAM,IAAQ,IAAI,IAAY,EAAK,aAAa;AAEhD,SAAO,EAAO,aAAa,SAAS,OAAA,CACjC,MAAY,EAAM,IAAI,EAAQ,IAAI,KAAK,EAAS,CAAO,CAC1D;AACF,GAEM,IAAA,CAAqB,EAAE,QAAA,EAAA,MAC3B,EAAO,aAAa,SAAS,OAAA,CAC1B,MAAY,EAAQ,iBAAiB,EAAY,WAAW,EAAS,CAAO,CAC/E,GAEW,IAAoF;AAAA,EAE/F,uBAAuB,EACrB,SAAA,OAAgB,EAAE,QAAQ,EAAiB,GAC7C;AAAA,EAGA,0BAA0B,EACxB,SAAA,OAAgB,EAAE,QAAQ,EAAiB,GAC7C;AAAA,EAGA,mBAAmB,EACjB,SAAA,CAAU,MAAQ;AAChB,UAAM,IAAU,EAAiB,CAAG;AAEpC,WAAO,IACH;AAAA,MAAE,QAAQ;AAAA,MAAkB,SAAS,EAAE,cAAc,EAAQ,cAAc;AAAA,IAAE,IAC7E;AAAA,EACN,EACF;AAAA,EAGA,0BAA0B,EACxB,SAAA,CAAU,EAAE,MAAA,EAAA,OACT,EAAK,SAAS,mBAAmB,KAAK,IAAI,EAAE,QAAQ,EAAiB,IAAI,KAC9E;AAAA,EAMA,kCAAkC,EAChC,SAAA,CAAU,EAAE,MAAA,EAAA,MACV,CAAC,EAAK,SAAS,kCAAkC,CAAC,EAAK,cAAc,SACjE,EAAE,QAAQ,EAAiB,IAC3B,KACR;AAAA,EAGA,kBAAkB,EAChB,SAAA,CAAU,OAAS;AAAA,IACjB,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,wBAAwB,EAAI,KAAK,SAAS;AAAA,MAC1C,UAAU,EAAe,CAAG,EAAE,IAAA,CAAK,OAAa;AAAA,QAC9C,cAAc,EAAQ;AAAA,QACtB,cAAc,EAAI,KAAK,SAAS,cAAc;AAAA,MAChD,EAAE;AAAA,IACJ;AAAA,EACF,GACF;AAAA,EAGA,sBAAsB,EACpB,SAAA,CAAU,MAAQ;AAChB,UAAM,IAAS,EAAiB,CAAG;AAEnC,QAAI,CAAC,EAAQ,QAAO;AAEpB,UAAM,IAAU,EAAkB,CAAG,GAC/B,IAAU;AAAA,MACd,QAAQ,EAAI,KAAK,SAAS;AAAA,MAC1B,mBAAmB,EAAO;AAAA,IAC5B;AAEA,WAAO,EAAQ,SACX;AAAA,MACE,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,GAAG;AAAA,QACH,yBAAyB,EAAQ,IAAA,CAAK,MAAY,EAAQ,aAAa;AAAA,MACzE;AAAA,IACF,IACA;AAAA,MAAE,QAAQ;AAAA,MAAkB,SAAA;AAAA,IAAQ;AAAA,EAC1C,EACF;AACF,GAGa,IAAA,CAAsB,MACjC,EAAI,IAAI,YAAY,EAAgB,EAAI,KAAK,QAAA,IAAY,EAAI,IAAA,IAAQ,CAAG,KAAK"}
@@ -24,15 +24,15 @@ import X from "./components/DirectDepositCard.es.js";
24
24
  import Z from "./blocks/ComponentBlocks/DirectDepositBlock/DirectDepositBlock.es.js";
25
25
  import { BudgetBlock as oo } from "./blocks/ComponentBlocks/BudgetBlock/BudgetBlock.es.js";
26
26
  import to from "./components/DebtPayoffCard.es.js";
27
- import io from "./components/UpcomingBillCard.es.js";
28
- import po from "./blocks/ComponentBlocks/UpcomingBillBlock/UpcomingBillBlock.es.js";
29
- import eo from "./blocks/ComponentBlocks/DebtsBlock/DebtsBlock.es.js";
30
- import co from "./components/SaveAnExtraCard.es.js";
31
- import so from "./blocks/ComponentBlocks/SaveExtraBlock/SaveExtraBlock.es.js";
32
- import Co from "./components/SavingsOpportunityCard.es.js";
33
- import uo from "./blocks/ComponentBlocks/SavingsOpportunityBlock/SavingsOpportunityBlock.es.js";
34
- import So from "./components/InsightTransactionRow.es.js";
35
- import Do from "./components/TransactionListCard.es.js";
27
+ import io from "./components/InsightTransactionRow.es.js";
28
+ import po from "./components/TransactionListCard.es.js";
29
+ import eo from "./components/UpcomingBillCard.es.js";
30
+ import co from "./blocks/ComponentBlocks/UpcomingBillBlock/UpcomingBillBlock.es.js";
31
+ import so from "./blocks/ComponentBlocks/DebtsBlock/DebtsBlock.es.js";
32
+ import Co from "./components/SaveAnExtraCard.es.js";
33
+ import uo from "./blocks/ComponentBlocks/SaveExtraBlock/SaveExtraBlock.es.js";
34
+ import So from "./components/SavingsOpportunityCard.es.js";
35
+ import Do from "./blocks/ComponentBlocks/SavingsOpportunityBlock/SavingsOpportunityBlock.es.js";
36
36
  import { transactionBlockVariant as Ao } from "./blocks/ComponentBlocks/TransactionBlock/layout.es.js";
37
37
  import { TransactionBlock as Io } from "./blocks/ComponentBlocks/TransactionBlock/TransactionBlock.es.js";
38
38
  import vo from "./components/AmountPill.es.js";
@@ -72,7 +72,7 @@ export {
72
72
  k as CompactInsightCard,
73
73
  Go as ConnectionDetailDrillDown,
74
74
  to as DebtPayoffCard,
75
- eo as DebtsBlock,
75
+ so as DebtsBlock,
76
76
  _o as DesignateEmergencySavingsCard,
77
77
  Z as DirectDepositBlock,
78
78
  X as DirectDepositCard,
@@ -88,7 +88,7 @@ export {
88
88
  mr as HiddenConfirmationCard,
89
89
  h as InsightErrorCard,
90
90
  l as InsightOptionsMenu,
91
- So as InsightTransactionRow,
91
+ io as InsightTransactionRow,
92
92
  ar as LoadingCard,
93
93
  Cr as LogoClusterCard,
94
94
  d as LogoFromGuid,
@@ -98,10 +98,10 @@ export {
98
98
  n as OverflowMenu,
99
99
  Sr as P2PLogoStack,
100
100
  Vo as SVGImageBlock,
101
- co as SaveAnExtraCard,
102
- so as SaveExtraBlock,
103
- uo as SavingsOpportunityBlock,
104
- Co as SavingsOpportunityCard,
101
+ Co as SaveAnExtraCard,
102
+ uo as SaveExtraBlock,
103
+ Do as SavingsOpportunityBlock,
104
+ So as SavingsOpportunityCard,
105
105
  g as StatusBadge,
106
106
  lr as StatusMessageCard,
107
107
  r as StatusPill,
@@ -110,10 +110,10 @@ export {
110
110
  Oo as SubscriptionHeroCard,
111
111
  Qo as SurveyModal,
112
112
  Io as TransactionBlock,
113
- Do as TransactionListCard,
113
+ po as TransactionListCard,
114
114
  j as TransferLogoCard,
115
- po as UpcomingBillBlock,
116
- io as UpcomingBillCard,
115
+ co as UpcomingBillBlock,
116
+ eo as UpcomingBillCard,
117
117
  yo as UpcomingSubscriptionBlock,
118
118
  Ro as WithdrawalBlock,
119
119
  Po as WithdrawalCard,