@mx-cartographer/experiences 9.6.6 → 9.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## [9.6.7] - 10-13-2026
2
+
3
+ - **ADDED** - `debts_block` component block for the Debt Payoff Strategies beat, registered through `BlockType` and the `blocks` registry. Renders the new presentational `DebtPayoffCard` (account row with an optional strategy pill, current balance, and projected payoff / monthly payment / interest rate rows) from facts carried flat on `instance_slot`: `payoff_date`, `monthly_payment` and `interest_rate` are new optional `InstanceSlot` fields beside the shared `amount`, `account_*`, `institution_*` and `status_text`. One look for now (`instance_slot.variant` is not read until a second design branch exists); the logo falls back to a card glyph for credit-card debt and the bank glyph otherwise. Row labels come from a new `insights_feed.debts_block` copy namespace; until a host ships it, the card renders the account row only and warns once (`debts_block: copy namespace missing`), and a slot with no `amount` renders no balance rather than `$0.00`. Mock payloads, beats fixtures, stories and tests (WEC-1298)
4
+
1
5
  ## [9.6.6] - 10-13-2026
2
6
 
3
7
  - **ADDED** - Beat contract test for the **Subscription Price Increase** insight (`SubscriptionPriceIncreaseContract.test.tsx`), one case per acceptance criterion: the `double_progress_bar_block` previous-vs-new card, opening the Expense Details drawer from the primary CTA, resolving the subscription from `primary_repeating_transaction_guid` on the envelope (transaction walk as the fallback), the no-activity state, and closing back to the feed. The `SubscriptionPriceIncrease` mock payload now names `double_progress_bar_block` and the beat fixture carries `primary_repeating_transaction_guid`, the `DoubleProgressBarBlock` story drives off that shared fixture, and `docs/action-blocks/recurring-transaction-block.md` records the beat and its open questions (MEW2-3308)
@@ -221,6 +221,7 @@ export declare const BlockType: {
221
221
  readonly DonutChartBlock: "donut_chart_block";
222
222
  readonly DoubleBarChartBlock: "double_bar_chart_block";
223
223
  readonly DoubleProgressBarBlock: "double_progress_bar_block";
224
+ readonly DebtsBlock: "debts_block";
224
225
  readonly SaveExtraBlock: "save_extra_block";
225
226
  readonly SavingsOpportunityBlock: "savings_opportunity_block";
226
227
  readonly StepChartBlock: "step_chart_block";
@@ -306,4 +307,10 @@ export interface InstanceSlot {
306
307
  icon_name?: string;
307
308
  /** Category guid used to render the deposit-card logo fallback. */
308
309
  category_guid?: string;
310
+ /** Projected payoff date in ISO form (e.g. `2027-03-01`); the block formats it as month + year. */
311
+ payoff_date?: string;
312
+ /** Monthly payment toward the debt (unformatted); the block formats it as currency. */
313
+ monthly_payment?: number;
314
+ /** Annual interest rate as a percentage (e.g. `19.99`); the block formats it as a percent. */
315
+ interest_rate?: number;
309
316
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Insights.es.js","names":[],"sources":["../../../src/core/types/Insights.ts"],"sourcesContent":["// ============ Core InsightsV2 Types ============\n\nimport { InsightsInstanceSlotData } from './InsightsInstanceSlotData'\n\nexport interface ThemedSVGImageProps {\n divProps?: React.HTMLAttributes<HTMLDivElement>\n image: React.ComponentType<React.SVGProps<SVGSVGElement>>\n isMini?: boolean\n}\n\n/**\n * Emitted by a block when the user drills into a specific datum (e.g. clicks a\n * chart bar). Named fields rather than positional args so blocks with differing\n * shapes can extend this without the call sites transposing values.\n */\nexport interface DrilldownPayload {\n chartBarIndex: number\n tabIndex?: number\n transaction_guid?: string\n block?: string\n}\n\n/**\n * Which envelope a beat was fetched with. `embedded` (the transaction-row pill + details-drawer\n * card) and `notification` are V2 additions; a surface asks for one with `widget_type=` on the fetch.\n */\nexport type WidgetType = 'full' | 'mini' | 'micro' | 'embedded' | 'notification'\n\n/**\n * V2: the transaction-row tag, its own small section of the `embedded` envelope (the same grammar\n * as `description` / `footer`, with room for a tone or an icon later). Omitted for an insight that\n * tags no transaction row. It deliberately is *not* `short_title`, which stays a per-variant\n * attribute with a second consumer (the bank-holiday sub-header).\n */\nexport interface Pill {\n text: string\n}\n\n/**\n * V2: facts a drilldown shows that the card does not (e.g. the account number for the Transaction\n * Details drawer). A flat hash shared by every CTA of the card, omitted when the insight has none.\n * Never carries copy or user actions (memo, tags, hide, flag come from the transaction store).\n */\nexport type DrilldownData = Record<string, string | number | boolean | null>\n\nexport interface InsightsPayload {\n widget_type: WidgetType\n instance_slot: InstanceSlot\n /**\n * V1 only. The v2 contract carries everything a block needs on `instance_slot.data`,\n * and omits this key entirely (see the LargeTransactionV2 payload). Blocks that still require it\n * get it as a required field through `BlockProps`, which re-declares it.\n */\n instance_slot_data?: InsightsInstanceSlotData\n description: Description\n primary_cta?: PrimaryCTA\n secondary_cta?: SecondaryCTA\n title?: string\n sub_title?: Subtitle\n /**\n * V2 rename of `sub_title`: a flat string, with the logo promoted to the payload-level `logo`\n * field below. `sub_title` wins when both are present.\n */\n subtitle?: string\n /** V2: header logo paired with the flat `subtitle`: an entity guid or a status icon (`LogoRef`). */\n logo?: LogoRef\n /** V2: which design branch the backend picked (e.g. `no_merchant`). */\n variant?: string\n /** V2, `embedded` envelope only: the transaction-row pill. */\n pill?: Pill\n /** V2: drilldown-only facts, e.g. `{ account_number: 'XXXXXXXX043' }`. */\n drilldown_data?: DrilldownData\n footer?: Footer\n // TODO: Add in_description_cta to insights_payload from backend\n guid: string\n user_guid: string\n client_guid?: string\n /** Template name, e.g. `LargeTransactionV2`. */\n template?: string\n revision?: number\n /** Unix seconds. */\n created_at?: number\n /** Unix seconds. */\n updated_at?: number\n /** Unix seconds. */\n active_at?: number\n displayed_at?: number | null\n dismissed_at: number | null\n cta_clicked_at?: number | null\n has_been_displayed?: boolean\n is_dismissed: boolean\n is_deleted?: boolean\n is_hidden_by_system?: boolean\n is_obsolete?: boolean\n is_refreshable?: boolean\n is_sampled?: boolean\n is_zero_state?: boolean\n status?: string | null\n /**\n * V2 (LargeTransactionV2 onward): the entities the beat is about, carried on the payload so\n * action blocks do not have to reach back out to the beat envelope.\n */\n primary_account_guid?: string | null\n primary_transaction_guid?: string | null\n primary_category_guid?: string | null\n primary_merchant_guid?: string | null\n /**\n * V2: the repeating transaction a subscription beat is about (Upcoming Subscription, Subscription\n * Price Increase). Read by `recurring_transaction_block`, see\n * `actionBlocks/RecurringTransactionBlock/subscriptionBeats.ts`.\n */\n primary_repeating_transaction_guid?: string | null\n}\n\nexport interface Legends {\n label: string\n value: number\n additional_value?: number\n additional_value_type?: string\n value_type?: string\n}\n\nexport interface Logo {\n category_guid?: string\n category_name?: string\n institution_guid?: string\n institution_name?: string\n logo_color?: string\n logo_name?: string\n merchant_guid?: string\n merchant_name?: string\n}\n\nexport interface Subtitle {\n logo?: Logo\n text: string\n}\n\n/**\n * A V2 logo, shared by the header (`InsightsPayload.logo`) and every instance-slot row. It takes\n * one of two shapes:\n *\n * - **Entity**: `guid`, whose prefix (`INS-` / `MCH-` / `CAT-`) picks the logo component, plus an\n * optional `fallback_guid` for when that component's asset cannot load. Today that is the\n * category behind an `MCH-` guid, which `MerchantLogo` shows as a tile when the merchant image\n * is missing.\n * - **Status icon**: `icon` (an mx-icons name, e.g. `warning`) and `color` (a theme palette path,\n * e.g. `error.main`), for subheaders that show a state rather than an entity (V1's\n * `logo_name` / `logo_color`).\n *\n * `alt` is the accessible name for either shape. A logo sends one shape; if it sends both, `icon`\n * wins, as `logo_name` does in V1's `SubHeader`.\n */\nexport interface LogoRef {\n alt?: string\n color?: string\n fallback_guid?: string\n guid?: string\n icon?: string\n}\n\nexport interface CategoryLogo {\n category_guid: string\n category_name: string\n}\n\nexport interface MerchantLogo {\n merchant_guid: string\n merchant_name: string\n}\n\nexport interface InstitutionLogo {\n institution_guid: string\n institution_name: string\n}\n\nexport interface Description {\n text: string\n html_text: string\n}\n\n/**\n * Post message a CTA press sends to the host, resolved by the backend for the beat's current\n * state. Absent/null = the backend has not described one: the frontend uses the template's\n * interim `ctaPostMessages` entry if there is one, else sends no message. `payload` carries only\n * beat-specific extras; the frontend always adds `beat_guid`, `beat_template`, `user_guid` and\n * `action_string`.\n */\nexport interface CtaPostMessageMetadata {\n /** Post message event; defaults to `beat/cta`. */\n event?: string | null\n /** Operation the host should perform, e.g. `op_1`, `op_2`, `op_3`. Defaults to `op_1`. */\n action?: string | null\n /** Beat-specific fields merged into the message metadata (account ids, amounts, ...). */\n payload?: Record<string, unknown> | null\n}\n\nexport interface PrimaryCTA {\n label: string\n block: string\n variant?: string | null\n /**\n * What pressing the CTA does beyond opening its block, named by the backend (ditto\n * `primary_cta_action`, passed through by tupac). Looked up in `insights-v2/ctaActions`;\n * null / absent / unknown means the CTA only opens its block or posts its message.\n */\n action_key?: string | null\n metadata?: CtaPostMessageMetadata | null\n}\n\nexport interface SecondaryCTA {\n label: string\n block: string\n variant?: string | null\n /** See `PrimaryCTA.action_key` (ditto `secondary_cta_action`). */\n action_key?: string | null\n metadata?: CtaPostMessageMetadata | null\n}\n\nexport interface Footer {\n /** V1: a pre-formatted date string. */\n date?: string\n /**\n * The account label, on both V1 and V2. The backend resolves the plurality: one account sends\n * its name (e.g. `Epic Bank`), several send a localized count (e.g. `2 Accounts`), none sends\n * nothing. There is deliberately no separate `accounts` key — see tupac's `footer_account_label`.\n */\n account?: string\n /**\n * V2 (LargeTransactionV2 onward): unix seconds, formatted by `Footer` for display.\n * Replaces `date`; `date` wins when a beat somehow sends both.\n */\n timestamp?: number\n}\n\n// ============ Instance Slot Types ============\n// Values are the snake_case block names the backend sends on a beat's instance slot; the PascalCase\n// keys stay as friendly references (e.g. BlockType.BarChartBlock === 'bar_chart_block').\nexport const BlockType = {\n AccountBlock: 'account_block',\n AccountSwitchBlock: 'account_switch_block',\n BarChartBlock: 'bar_chart_block',\n BudgetBlock: 'budget_block',\n ImageBlock: 'image_block',\n TransactionBlock: 'transaction_block',\n DonutChartBlock: 'donut_chart_block',\n DoubleBarChartBlock: 'double_bar_chart_block',\n DoubleProgressBarBlock: 'double_progress_bar_block',\n SaveExtraBlock: 'save_extra_block',\n SavingsOpportunityBlock: 'savings_opportunity_block',\n StepChartBlock: 'step_chart_block',\n SVGImageBlock: 'svg_image_block',\n UpcomingBillBlock: 'upcoming_bill_block',\n UpcomingSubscriptionBlock: 'upcoming_subscription_block',\n WithdrawalBlock: 'withdrawal_block',\n} as const\n\nexport type BlockType = (typeof BlockType)[keyof typeof BlockType]\n\n/**\n * A pre-localized row on a V2 instance slot. The backend resolves the copy and formatting; the\n * logo is a `LogoRef` (an entity guid or a status icon, see `logoFromRef`).\n */\nexport interface InstanceSlotRow {\n amount?: number\n logo?: LogoRef\n primary_text?: string\n secondary_text?: string\n}\n\n/**\n * V2: the slots a block's variant filled, keyed by slot name; ditto owns the names and omits any\n * slot it has no value for (`lib/ditto/blocks/<block>.yml`). Read with `slot()`, which names the\n * kind the caller expects.\n */\nexport interface InstanceSlotData {\n [slot: string]: unknown\n}\n\n/**\n * Reads one slot off a block's `data`; undefined when ditto did not fill it.\n *\n * The caller names the kind, because the slot's kind lives in the block's ditto schema and not\n * here — a block fills slots with whatever its card needs, so no fixed list of kinds would hold\n * (`account_switch_block` alone carries a boolean and `budget_block` a nested object).\n */\nexport const slot = <T = unknown>(\n data: InstanceSlotData | undefined,\n name: string,\n): T | undefined => data?.[name] as T | undefined\n\n/**\n * V2: which block renders this beat's content, and what it renders.\n *\n * `block` is optional: a beat whose template has no ditto config arrives as an empty `{}` and the\n * card renders its copy and CTAs alone, so a reader cannot assume a block is named. One interface\n * with `block` optional rather than a union with `Record<string, never>`, which TypeScript absorbs\n * — that union left `block` reading as required and typed a promise it did not keep.\n *\n * `variant` is optional for the same reason — the empty `{}` carries neither. Every ditto beat\n * file that names a block also names a variant, so a *filled* slot always has one; ditto drops a\n * nil variant rather than sending null, which is why the type is `string | null | undefined`.\n */\nexport interface InstanceSlot {\n block?: BlockType\n variant?: string | null\n /** The slots this block's variant declares in ditto. */\n data?: InstanceSlotData\n // Direct Deposit block (Set Up Direct Deposit, Switch Direct Deposit, Missing\n // Interest Rate): account facts carried flat on the slot, beside `data`.\n /** Primary line on the hero card, e.g. \"Epic Bank Checking, *1234\". */\n account_name?: string\n /** Secondary line beneath the name, e.g. \"Checking Account\" / \"Credit Card\". */\n account_type?: string\n /** Status pill label, e.g. \"Direct Deposit Not Set Up\" / \"Interest Rate: 19.99% APR\". */\n status_text?: string\n institution_guid?: string\n institution_name?: string\n // Shared across multiple V2 component blocks:\n // `amount` — UpcomingBillBlock (projected bill), SavingsOpportunityBlock (coupon),\n // UpcomingSubscriptionBlock (price per cadence).\n // `merchant_guid` / `merchant_name` — UpcomingBillBlock (bill row logo + name),\n // UpcomingSubscriptionBlock (hero logo + name).\n /** Dollar amount (unformatted); the block formats it as currency. */\n amount?: number\n /** Merchant guid used to render the inline / hero logo via `LogoFromGuid` (`MCH-...`). */\n merchant_guid?: string\n /** Merchant display name — shown as logo alt text and as the merchant/hero label. */\n merchant_name?: string\n // Upcoming Bill block (Projected Bill Payment): the block derives the Sun→Sat week strip\n // around `due_date` at render time.\n /** Due date of the projected bill in ISO form (e.g. `2025-10-30`). */\n due_date?: string\n // Savings Opportunity block (Save An Extra, Potential Savings, Embedded): purely data-driven\n // coupon card. Backend sends the caption and the amount, plus `slot` to toggle the green\n // gradient background when the card is embedded in a parent surface that supplies its own.\n /** Caption shown above the amount, e.g. `Save an extra` or `Potential savings`. */\n label?: string\n /**\n * Whether to render the green gradient slot behind the coupon. Defaults to true. Backend sends\n * `false` when the coupon is embedded in a parent surface that supplies its own background.\n */\n slot?: boolean\n // Upcoming Subscription block: billing cadence for the price pill (`${amount} / ${cadence}`).\n /** Billing cadence word that trails the price, e.g. `month` or `year`. */\n cadence?: string\n // Account block (status on/off-track, deposit, payoff variants): card content carried flat on\n // the slot (the V2 contract drops `instance_slot_data`). `amount`, `label`, `merchant_guid`,\n // `merchant_name`, `institution_guid`, `institution_name` are shared fields declared above.\n /** Secondary line beneath the amount on the standard card, e.g. \"Remaining after expenses\". */\n sub_text?: string\n /** Header bar text (standard card) or the colored category strip label (deposit cards). */\n header_text?: string\n /** Generic-tile icon name used when no merchant/institution logo is available. */\n icon_name?: string\n /** Category guid used to render the deposit-card logo fallback. */\n category_guid?: string\n}\n"],"mappings":"AA8RA,IAAa,IAAA,CACX,GACA,MACkB,IAAO,CAAA"}
1
+ {"version":3,"file":"Insights.es.js","names":[],"sources":["../../../src/core/types/Insights.ts"],"sourcesContent":["// ============ Core InsightsV2 Types ============\n\nimport { InsightsInstanceSlotData } from './InsightsInstanceSlotData'\n\nexport interface ThemedSVGImageProps {\n divProps?: React.HTMLAttributes<HTMLDivElement>\n image: React.ComponentType<React.SVGProps<SVGSVGElement>>\n isMini?: boolean\n}\n\n/**\n * Emitted by a block when the user drills into a specific datum (e.g. clicks a\n * chart bar). Named fields rather than positional args so blocks with differing\n * shapes can extend this without the call sites transposing values.\n */\nexport interface DrilldownPayload {\n chartBarIndex: number\n tabIndex?: number\n transaction_guid?: string\n block?: string\n}\n\n/**\n * Which envelope a beat was fetched with. `embedded` (the transaction-row pill + details-drawer\n * card) and `notification` are V2 additions; a surface asks for one with `widget_type=` on the fetch.\n */\nexport type WidgetType = 'full' | 'mini' | 'micro' | 'embedded' | 'notification'\n\n/**\n * V2: the transaction-row tag, its own small section of the `embedded` envelope (the same grammar\n * as `description` / `footer`, with room for a tone or an icon later). Omitted for an insight that\n * tags no transaction row. It deliberately is *not* `short_title`, which stays a per-variant\n * attribute with a second consumer (the bank-holiday sub-header).\n */\nexport interface Pill {\n text: string\n}\n\n/**\n * V2: facts a drilldown shows that the card does not (e.g. the account number for the Transaction\n * Details drawer). A flat hash shared by every CTA of the card, omitted when the insight has none.\n * Never carries copy or user actions (memo, tags, hide, flag come from the transaction store).\n */\nexport type DrilldownData = Record<string, string | number | boolean | null>\n\nexport interface InsightsPayload {\n widget_type: WidgetType\n instance_slot: InstanceSlot\n /**\n * V1 only. The v2 contract carries everything a block needs on `instance_slot.data`,\n * and omits this key entirely (see the LargeTransactionV2 payload). Blocks that still require it\n * get it as a required field through `BlockProps`, which re-declares it.\n */\n instance_slot_data?: InsightsInstanceSlotData\n description: Description\n primary_cta?: PrimaryCTA\n secondary_cta?: SecondaryCTA\n title?: string\n sub_title?: Subtitle\n /**\n * V2 rename of `sub_title`: a flat string, with the logo promoted to the payload-level `logo`\n * field below. `sub_title` wins when both are present.\n */\n subtitle?: string\n /** V2: header logo paired with the flat `subtitle`: an entity guid or a status icon (`LogoRef`). */\n logo?: LogoRef\n /** V2: which design branch the backend picked (e.g. `no_merchant`). */\n variant?: string\n /** V2, `embedded` envelope only: the transaction-row pill. */\n pill?: Pill\n /** V2: drilldown-only facts, e.g. `{ account_number: 'XXXXXXXX043' }`. */\n drilldown_data?: DrilldownData\n footer?: Footer\n // TODO: Add in_description_cta to insights_payload from backend\n guid: string\n user_guid: string\n client_guid?: string\n /** Template name, e.g. `LargeTransactionV2`. */\n template?: string\n revision?: number\n /** Unix seconds. */\n created_at?: number\n /** Unix seconds. */\n updated_at?: number\n /** Unix seconds. */\n active_at?: number\n displayed_at?: number | null\n dismissed_at: number | null\n cta_clicked_at?: number | null\n has_been_displayed?: boolean\n is_dismissed: boolean\n is_deleted?: boolean\n is_hidden_by_system?: boolean\n is_obsolete?: boolean\n is_refreshable?: boolean\n is_sampled?: boolean\n is_zero_state?: boolean\n status?: string | null\n /**\n * V2 (LargeTransactionV2 onward): the entities the beat is about, carried on the payload so\n * action blocks do not have to reach back out to the beat envelope.\n */\n primary_account_guid?: string | null\n primary_transaction_guid?: string | null\n primary_category_guid?: string | null\n primary_merchant_guid?: string | null\n /**\n * V2: the repeating transaction a subscription beat is about (Upcoming Subscription, Subscription\n * Price Increase). Read by `recurring_transaction_block`, see\n * `actionBlocks/RecurringTransactionBlock/subscriptionBeats.ts`.\n */\n primary_repeating_transaction_guid?: string | null\n}\n\nexport interface Legends {\n label: string\n value: number\n additional_value?: number\n additional_value_type?: string\n value_type?: string\n}\n\nexport interface Logo {\n category_guid?: string\n category_name?: string\n institution_guid?: string\n institution_name?: string\n logo_color?: string\n logo_name?: string\n merchant_guid?: string\n merchant_name?: string\n}\n\nexport interface Subtitle {\n logo?: Logo\n text: string\n}\n\n/**\n * A V2 logo, shared by the header (`InsightsPayload.logo`) and every instance-slot row. It takes\n * one of two shapes:\n *\n * - **Entity**: `guid`, whose prefix (`INS-` / `MCH-` / `CAT-`) picks the logo component, plus an\n * optional `fallback_guid` for when that component's asset cannot load. Today that is the\n * category behind an `MCH-` guid, which `MerchantLogo` shows as a tile when the merchant image\n * is missing.\n * - **Status icon**: `icon` (an mx-icons name, e.g. `warning`) and `color` (a theme palette path,\n * e.g. `error.main`), for subheaders that show a state rather than an entity (V1's\n * `logo_name` / `logo_color`).\n *\n * `alt` is the accessible name for either shape. A logo sends one shape; if it sends both, `icon`\n * wins, as `logo_name` does in V1's `SubHeader`.\n */\nexport interface LogoRef {\n alt?: string\n color?: string\n fallback_guid?: string\n guid?: string\n icon?: string\n}\n\nexport interface CategoryLogo {\n category_guid: string\n category_name: string\n}\n\nexport interface MerchantLogo {\n merchant_guid: string\n merchant_name: string\n}\n\nexport interface InstitutionLogo {\n institution_guid: string\n institution_name: string\n}\n\nexport interface Description {\n text: string\n html_text: string\n}\n\n/**\n * Post message a CTA press sends to the host, resolved by the backend for the beat's current\n * state. Absent/null = the backend has not described one: the frontend uses the template's\n * interim `ctaPostMessages` entry if there is one, else sends no message. `payload` carries only\n * beat-specific extras; the frontend always adds `beat_guid`, `beat_template`, `user_guid` and\n * `action_string`.\n */\nexport interface CtaPostMessageMetadata {\n /** Post message event; defaults to `beat/cta`. */\n event?: string | null\n /** Operation the host should perform, e.g. `op_1`, `op_2`, `op_3`. Defaults to `op_1`. */\n action?: string | null\n /** Beat-specific fields merged into the message metadata (account ids, amounts, ...). */\n payload?: Record<string, unknown> | null\n}\n\nexport interface PrimaryCTA {\n label: string\n block: string\n variant?: string | null\n /**\n * What pressing the CTA does beyond opening its block, named by the backend (ditto\n * `primary_cta_action`, passed through by tupac). Looked up in `insights-v2/ctaActions`;\n * null / absent / unknown means the CTA only opens its block or posts its message.\n */\n action_key?: string | null\n metadata?: CtaPostMessageMetadata | null\n}\n\nexport interface SecondaryCTA {\n label: string\n block: string\n variant?: string | null\n /** See `PrimaryCTA.action_key` (ditto `secondary_cta_action`). */\n action_key?: string | null\n metadata?: CtaPostMessageMetadata | null\n}\n\nexport interface Footer {\n /** V1: a pre-formatted date string. */\n date?: string\n /**\n * The account label, on both V1 and V2. The backend resolves the plurality: one account sends\n * its name (e.g. `Epic Bank`), several send a localized count (e.g. `2 Accounts`), none sends\n * nothing. There is deliberately no separate `accounts` key — see tupac's `footer_account_label`.\n */\n account?: string\n /**\n * V2 (LargeTransactionV2 onward): unix seconds, formatted by `Footer` for display.\n * Replaces `date`; `date` wins when a beat somehow sends both.\n */\n timestamp?: number\n}\n\n// ============ Instance Slot Types ============\n// Values are the snake_case block names the backend sends on a beat's instance slot; the PascalCase\n// keys stay as friendly references (e.g. BlockType.BarChartBlock === 'bar_chart_block').\nexport const BlockType = {\n AccountBlock: 'account_block',\n AccountSwitchBlock: 'account_switch_block',\n BarChartBlock: 'bar_chart_block',\n BudgetBlock: 'budget_block',\n ImageBlock: 'image_block',\n TransactionBlock: 'transaction_block',\n DonutChartBlock: 'donut_chart_block',\n DoubleBarChartBlock: 'double_bar_chart_block',\n DoubleProgressBarBlock: 'double_progress_bar_block',\n DebtsBlock: 'debts_block',\n SaveExtraBlock: 'save_extra_block',\n SavingsOpportunityBlock: 'savings_opportunity_block',\n StepChartBlock: 'step_chart_block',\n SVGImageBlock: 'svg_image_block',\n UpcomingBillBlock: 'upcoming_bill_block',\n UpcomingSubscriptionBlock: 'upcoming_subscription_block',\n WithdrawalBlock: 'withdrawal_block',\n} as const\n\nexport type BlockType = (typeof BlockType)[keyof typeof BlockType]\n\n/**\n * A pre-localized row on a V2 instance slot. The backend resolves the copy and formatting; the\n * logo is a `LogoRef` (an entity guid or a status icon, see `logoFromRef`).\n */\nexport interface InstanceSlotRow {\n amount?: number\n logo?: LogoRef\n primary_text?: string\n secondary_text?: string\n}\n\n/**\n * V2: the slots a block's variant filled, keyed by slot name; ditto owns the names and omits any\n * slot it has no value for (`lib/ditto/blocks/<block>.yml`). Read with `slot()`, which names the\n * kind the caller expects.\n */\nexport interface InstanceSlotData {\n [slot: string]: unknown\n}\n\n/**\n * Reads one slot off a block's `data`; undefined when ditto did not fill it.\n *\n * The caller names the kind, because the slot's kind lives in the block's ditto schema and not\n * here — a block fills slots with whatever its card needs, so no fixed list of kinds would hold\n * (`account_switch_block` alone carries a boolean and `budget_block` a nested object).\n */\nexport const slot = <T = unknown>(\n data: InstanceSlotData | undefined,\n name: string,\n): T | undefined => data?.[name] as T | undefined\n\n/**\n * V2: which block renders this beat's content, and what it renders.\n *\n * `block` is optional: a beat whose template has no ditto config arrives as an empty `{}` and the\n * card renders its copy and CTAs alone, so a reader cannot assume a block is named. One interface\n * with `block` optional rather than a union with `Record<string, never>`, which TypeScript absorbs\n * — that union left `block` reading as required and typed a promise it did not keep.\n *\n * `variant` is optional for the same reason — the empty `{}` carries neither. Every ditto beat\n * file that names a block also names a variant, so a *filled* slot always has one; ditto drops a\n * nil variant rather than sending null, which is why the type is `string | null | undefined`.\n */\nexport interface InstanceSlot {\n block?: BlockType\n variant?: string | null\n /** The slots this block's variant declares in ditto. */\n data?: InstanceSlotData\n // Direct Deposit block (Set Up Direct Deposit, Switch Direct Deposit, Missing\n // Interest Rate): account facts carried flat on the slot, beside `data`.\n /** Primary line on the hero card, e.g. \"Epic Bank Checking, *1234\". */\n account_name?: string\n /** Secondary line beneath the name, e.g. \"Checking Account\" / \"Credit Card\". */\n account_type?: string\n /** Status pill label, e.g. \"Direct Deposit Not Set Up\" / \"Interest Rate: 19.99% APR\". */\n status_text?: string\n institution_guid?: string\n institution_name?: string\n // Shared across multiple V2 component blocks:\n // `amount` — UpcomingBillBlock (projected bill), SavingsOpportunityBlock (coupon),\n // UpcomingSubscriptionBlock (price per cadence).\n // `merchant_guid` / `merchant_name` — UpcomingBillBlock (bill row logo + name),\n // UpcomingSubscriptionBlock (hero logo + name).\n /** Dollar amount (unformatted); the block formats it as currency. */\n amount?: number\n /** Merchant guid used to render the inline / hero logo via `LogoFromGuid` (`MCH-...`). */\n merchant_guid?: string\n /** Merchant display name — shown as logo alt text and as the merchant/hero label. */\n merchant_name?: string\n // Upcoming Bill block (Projected Bill Payment): the block derives the Sun→Sat week strip\n // around `due_date` at render time.\n /** Due date of the projected bill in ISO form (e.g. `2025-10-30`). */\n due_date?: string\n // Savings Opportunity block (Save An Extra, Potential Savings, Embedded): purely data-driven\n // coupon card. Backend sends the caption and the amount, plus `slot` to toggle the green\n // gradient background when the card is embedded in a parent surface that supplies its own.\n /** Caption shown above the amount, e.g. `Save an extra` or `Potential savings`. */\n label?: string\n /**\n * Whether to render the green gradient slot behind the coupon. Defaults to true. Backend sends\n * `false` when the coupon is embedded in a parent surface that supplies its own background.\n */\n slot?: boolean\n // Upcoming Subscription block: billing cadence for the price pill (`${amount} / ${cadence}`).\n /** Billing cadence word that trails the price, e.g. `month` or `year`. */\n cadence?: string\n // Account block (status on/off-track, deposit, payoff variants): card content carried flat on\n // the slot (the V2 contract drops `instance_slot_data`). `amount`, `label`, `merchant_guid`,\n // `merchant_name`, `institution_guid`, `institution_name` are shared fields declared above.\n /** Secondary line beneath the amount on the standard card, e.g. \"Remaining after expenses\". */\n sub_text?: string\n /** Header bar text (standard card) or the colored category strip label (deposit cards). */\n header_text?: string\n /** Generic-tile icon name used when no merchant/institution logo is available. */\n icon_name?: string\n /** Category guid used to render the deposit-card logo fallback. */\n category_guid?: string\n // Debts block: `amount` is the current balance; the shared account/institution fields above.\n /** Projected payoff date in ISO form (e.g. `2027-03-01`); the block formats it as month + year. */\n payoff_date?: string\n /** Monthly payment toward the debt (unformatted); the block formats it as currency. */\n monthly_payment?: number\n /** Annual interest rate as a percentage (e.g. `19.99`); the block formats it as a percent. */\n interest_rate?: number\n}\n"],"mappings":"AA+RA,IAAa,IAAA,CACX,GACA,MACkB,IAAO,CAAA"}
@@ -245,6 +245,13 @@ export interface AmountInputModalCopy {
245
245
  /** Shown in the dialog when the save request fails; the value stays so Save can be retried. */
246
246
  save_error: string;
247
247
  }
248
+ /** Labels for the Debts component block; the values come pre-formatted off `instance_slot`. */
249
+ export interface DebtsBlockCopy {
250
+ balance_label: string;
251
+ payoff_date_label: string;
252
+ monthly_payment_label: string;
253
+ interest_rate_label: string;
254
+ }
248
255
  export interface InsightsFeedCopy {
249
256
  general: GeneralInsightsFeedCopy;
250
257
  settings_menu: SettingsMenuCopy;
@@ -266,5 +273,7 @@ export interface InsightsFeedCopy {
266
273
  dismiss: DismissInsightCopy;
267
274
  /** Optional until the localized-content service ships the namespace. */
268
275
  amount_input_modal?: AmountInputModalCopy;
276
+ /** Optional until the localized-content service ships the namespace. */
277
+ debts_block?: DebtsBlockCopy;
269
278
  }
270
279
  export {};
@@ -0,0 +1,24 @@
1
+ import { InsightsPayload } from '../../../../core';
2
+ import { DebtPayoffCardStyleProps } from '../../../components/DebtPayoffCard';
3
+ interface DebtsBlockProps {
4
+ payload: InsightsPayload;
5
+ beatGuid?: string;
6
+ }
7
+ /** `projected_payoff` look: primary-tinted slot and pill. The card story mirrors it from here. */
8
+ export declare const PAYOFF_STYLE: DebtPayoffCardStyleProps;
9
+ /**
10
+ * Debts component block — the content card for the Debt Payoff Strategies beat.
11
+ *
12
+ * The debt account's facts arrive flat on `instance_slot` (V2 contract — no `instance_slot_data`):
13
+ * the balance (`amount`), `payoff_date`, `monthly_payment`, `interest_rate`, plus the shared
14
+ * account/institution fields. Row labels come from `insights_feed.debts_block` copy, which
15
+ * ships separately: until it has, the card shows the account row only (never an unlabelled number)
16
+ * and warns once per mount so the rollout gap is traceable.
17
+ *
18
+ * `instance_slot.variant` is not read yet: the architecture doc's other Debts branches (Debt
19
+ * Summary, Interest Summary) have no design, so there is one look. Introduce a per-variant
20
+ * registry (`createVariantBlock` + a `layout.ts` table, as `AccountBlock` does) with the second
21
+ * variant, not before.
22
+ */
23
+ declare const DebtsBlock: ({ payload }: DebtsBlockProps) => import("react/jsx-runtime").JSX.Element;
24
+ export default DebtsBlock;
@@ -0,0 +1,56 @@
1
+ import { DATE_FORMATS_INTL as y, formatDate as h } from "../../../../core/constants/DateFormats.es.js";
2
+ import { useGlobalCopyStore as v } from "../../../../common/context/hooks.es.js";
3
+ import { formatCurrency as _, formatPercentage as g } from "../../../../core/utils/NumberFormatting.es.js";
4
+ import { DepositLogo as D } from "../../../components/ComponentBlocks/DepositLogo.es.js";
5
+ import T from "../../../components/DebtPayoffCard.es.js";
6
+ import { parseDueDate as C } from "../UpcomingBillBlock/UpcomingBillBlock.es.js";
7
+ import L from "react";
8
+ import { jsx as b } from "react/jsx-runtime";
9
+ var A = {
10
+ bgcolor: "primary.lighter",
11
+ pill: {
12
+ bgcolor: "primary.lighter",
13
+ labelColor: "text.primary"
14
+ }
15
+ }, E = /* @__PURE__ */ new Set([
16
+ "credit card",
17
+ "credit_card",
18
+ "creditcard"
19
+ ]), R = (e) => E.has((e ?? "").trim().toLowerCase()) ? "credit_card" : "account_balance", S = (e) => !!e?.balance_label && !!e.payoff_date_label && !!e.monthly_payment_label && !!e.interest_rate_label, B = ({ payload: e }) => {
20
+ const a = v().insights_feed?.debts_block, t = S(a) ? a : void 0, { account_name: u, account_type: l, amount: r, institution_guid: f, institution_name: p, interest_rate: n, monthly_payment: i, payoff_date: s, status_text: d } = e.instance_slot;
21
+ L.useEffect(() => {
22
+ t || console.warn(`debts_block: ${a ? "copy incomplete" : "copy namespace missing"}; rendering the account row only`);
23
+ }, [a, t]);
24
+ const c = s ? C(s) : null, o = [];
25
+ t && c && o.push({
26
+ label: t.payoff_date_label,
27
+ value: h(c, y.MONTH_SHORT_YEAR)
28
+ }), t && i != null && o.push({
29
+ label: t.monthly_payment_label,
30
+ value: _(i, "0,0.00")
31
+ }), t && n != null && o.push({
32
+ label: t.interest_rate_label,
33
+ value: g(n / 100)
34
+ });
35
+ const m = t !== void 0 && r != null;
36
+ return /* @__PURE__ */ b(T, {
37
+ ...A,
38
+ balance: m ? _(r, "0,0.00") : void 0,
39
+ balanceLabel: m ? t.balance_label : void 0,
40
+ logo: /* @__PURE__ */ b(D, {
41
+ iconName: R(l),
42
+ institutionGuid: f ?? "",
43
+ institutionName: p ?? ""
44
+ }),
45
+ name: u,
46
+ stats: o,
47
+ statusLabel: d,
48
+ subtitle: l
49
+ });
50
+ };
51
+ export {
52
+ A as PAYOFF_STYLE,
53
+ B as default
54
+ };
55
+
56
+ //# sourceMappingURL=DebtsBlock.es.js.map
@@ -0,0 +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"}
@@ -0,0 +1 @@
1
+ export { default as DebtsBlock } from './DebtsBlock';
@@ -2,6 +2,7 @@ export * from './AccountBlock';
2
2
  export * from './AccountSwitchBlock';
3
3
  export * from './DirectDepositBlock';
4
4
  export * from './BudgetBlock';
5
+ export * from './DebtsBlock';
5
6
  export * from './SaveExtraBlock';
6
7
  export * from './SavingsOpportunityBlock';
7
8
  export * from './TransactionBlock';
@@ -0,0 +1,48 @@
1
+ import { ReactNode } from 'react';
2
+ export interface DebtPayoffStat {
3
+ /** Row label, e.g. "Projected payoff". */
4
+ label: ReactNode;
5
+ /** Pre-formatted row value, e.g. "Mar 2027". */
6
+ value: ReactNode;
7
+ }
8
+ export interface DebtPayoffPillConfig {
9
+ /** Pill background color token. The pill is borderless. */
10
+ bgcolor: string;
11
+ /** Pill label color token. */
12
+ labelColor: string;
13
+ }
14
+ /**
15
+ * Style props for the card. The Debts block supplies them for its look; the card itself
16
+ * is variant-agnostic. Only what a caller sets today is here; add a knob with its first caller.
17
+ */
18
+ export interface DebtPayoffCardStyleProps {
19
+ /** Slot surface token behind the white card. Default `background.default`. */
20
+ bgcolor?: string;
21
+ /** Status pill color tokens. */
22
+ pill?: DebtPayoffPillConfig;
23
+ }
24
+ interface DebtPayoffCardProps extends DebtPayoffCardStyleProps {
25
+ /** Institution/account logo rendered beside the account name. */
26
+ logo: ReactNode;
27
+ /** Primary line, e.g. "Epic Bank Credit *0987". */
28
+ name: ReactNode;
29
+ /** Optional secondary line beneath the name, e.g. "Credit Card". */
30
+ subtitle?: ReactNode;
31
+ /** Caption above the balance, e.g. "Current balance". Rendered only together with `balance`. */
32
+ balanceLabel?: ReactNode;
33
+ /** Pre-formatted balance, e.g. "$4,500.00". Omitted (with its caption) when unknown. */
34
+ balance?: ReactNode;
35
+ /** Label/value rows beneath the balance (payoff date, monthly payment, rate). */
36
+ stats?: DebtPayoffStat[];
37
+ /** Optional status pill label beside the account, e.g. the payoff strategy name. */
38
+ statusLabel?: ReactNode;
39
+ }
40
+ /**
41
+ * A debt account card: logo + account name row (with an optional status pill), the current
42
+ * balance, and a divided list of label/value payoff stats, on a tinted slot.
43
+ *
44
+ * Purely presentational — it knows nothing about beats or variants; the Debts block passes
45
+ * the style props for its look.
46
+ */
47
+ declare const DebtPayoffCard: ({ balance, balanceLabel, bgcolor, logo, name, pill, stats, statusLabel, subtitle, }: DebtPayoffCardProps) => import("react/jsx-runtime").JSX.Element;
48
+ export default DebtPayoffCard;
@@ -0,0 +1,132 @@
1
+ import u from "./StatusPill.es.js";
2
+ import e from "@mui/material/Stack";
3
+ import { Text as o } from "@mxenabled/mxui";
4
+ import { Fragment as v, jsx as r, jsxs as t } from "react/jsx-runtime";
5
+ import x from "@mui/material/Box";
6
+ import y from "@mui/material/Divider";
7
+ var w = {
8
+ bgcolor: "grey.200",
9
+ labelColor: "text.primary"
10
+ }, h = (i) => typeof i == "string" ? i : void 0, I = ({ balance: i, balanceLabel: l, bgcolor: m = "background.default", logo: s, name: d, pill: a = w, stats: c = [], statusLabel: p, subtitle: n }) => /* @__PURE__ */ r(e, {
11
+ sx: {
12
+ px: 16,
13
+ width: "100%"
14
+ },
15
+ children: /* @__PURE__ */ r(x, {
16
+ sx: {
17
+ bgcolor: m,
18
+ borderRadius: "8px",
19
+ p: 16,
20
+ width: "100%"
21
+ },
22
+ children: /* @__PURE__ */ t(e, {
23
+ sx: {
24
+ bgcolor: "background.paper",
25
+ border: "1px solid",
26
+ borderColor: "divider",
27
+ borderRadius: "8px",
28
+ gap: 12,
29
+ p: 16,
30
+ width: "100%"
31
+ },
32
+ children: [
33
+ /* @__PURE__ */ t(e, {
34
+ sx: {
35
+ alignItems: "center",
36
+ flexDirection: "row",
37
+ gap: 12
38
+ },
39
+ children: [
40
+ /* @__PURE__ */ r(x, {
41
+ sx: {
42
+ borderRadius: "4px",
43
+ display: "flex",
44
+ flexShrink: 0,
45
+ height: 40,
46
+ overflow: "hidden",
47
+ width: 40
48
+ },
49
+ children: s
50
+ }),
51
+ /* @__PURE__ */ t(e, {
52
+ sx: {
53
+ flexGrow: 1,
54
+ minWidth: 0
55
+ },
56
+ children: [/* @__PURE__ */ r(o, {
57
+ sx: { fontWeight: 600 },
58
+ title: h(d),
59
+ truncate: !0,
60
+ variant: "body2",
61
+ children: d
62
+ }), n && /* @__PURE__ */ r(o, {
63
+ color: "text.secondary",
64
+ title: h(n),
65
+ truncate: !0,
66
+ variant: "caption",
67
+ children: n
68
+ })]
69
+ }),
70
+ p && /* @__PURE__ */ r(u, {
71
+ bgcolor: a.bgcolor,
72
+ label: p,
73
+ labelColor: a.labelColor,
74
+ labelVariant: "caption",
75
+ sx: {
76
+ alignSelf: "center",
77
+ border: "none",
78
+ flexShrink: 0,
79
+ px: 12
80
+ }
81
+ })
82
+ ]
83
+ }),
84
+ i != null && l != null && /* @__PURE__ */ t(e, { children: [/* @__PURE__ */ r(o, {
85
+ color: "text.secondary",
86
+ variant: "caption",
87
+ children: l
88
+ }), /* @__PURE__ */ r(o, {
89
+ bold: !0,
90
+ color: "text.primary",
91
+ component: "p",
92
+ variant: "h2",
93
+ children: i
94
+ })] }),
95
+ c.length > 0 && /* @__PURE__ */ t(v, { children: [/* @__PURE__ */ r(y, {}), /* @__PURE__ */ r(e, {
96
+ component: "dl",
97
+ sx: {
98
+ gap: 8,
99
+ m: 0
100
+ },
101
+ children: c.map(({ label: f, value: g }, b) => /* @__PURE__ */ t(e, {
102
+ sx: {
103
+ alignItems: "baseline",
104
+ flexDirection: "row",
105
+ gap: 12,
106
+ justifyContent: "space-between"
107
+ },
108
+ children: [/* @__PURE__ */ r(o, {
109
+ color: "text.secondary",
110
+ component: "dt",
111
+ variant: "caption",
112
+ children: f
113
+ }), /* @__PURE__ */ r(o, {
114
+ component: "dd",
115
+ sx: {
116
+ fontWeight: 600,
117
+ m: 0
118
+ },
119
+ variant: "body2",
120
+ children: g
121
+ })]
122
+ }, b))
123
+ })] })
124
+ ]
125
+ })
126
+ })
127
+ });
128
+ export {
129
+ I as default
130
+ };
131
+
132
+ //# sourceMappingURL=DebtPayoffCard.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DebtPayoffCard.es.js","names":[],"sources":["../../../src/insights-v2/components/DebtPayoffCard.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\n\nimport Box from '@mui/material/Box'\nimport Divider from '@mui/material/Divider'\nimport Stack from '@mui/material/Stack'\n\nimport { Text } from '@mxenabled/mxui'\n\nimport StatusPill from './StatusPill'\n\nexport interface DebtPayoffStat {\n /** Row label, e.g. \"Projected payoff\". */\n label: ReactNode\n /** Pre-formatted row value, e.g. \"Mar 2027\". */\n value: ReactNode\n}\n\nexport interface DebtPayoffPillConfig {\n /** Pill background color token. The pill is borderless. */\n bgcolor: string\n /** Pill label color token. */\n labelColor: string\n}\n\n/**\n * Style props for the card. The Debts block supplies them for its look; the card itself\n * is variant-agnostic. Only what a caller sets today is here; add a knob with its first caller.\n */\nexport interface DebtPayoffCardStyleProps {\n /** Slot surface token behind the white card. Default `background.default`. */\n bgcolor?: string\n /** Status pill color tokens. */\n pill?: DebtPayoffPillConfig\n}\n\ninterface DebtPayoffCardProps extends DebtPayoffCardStyleProps {\n /** Institution/account logo rendered beside the account name. */\n logo: ReactNode\n /** Primary line, e.g. \"Epic Bank Credit *0987\". */\n name: ReactNode\n /** Optional secondary line beneath the name, e.g. \"Credit Card\". */\n subtitle?: ReactNode\n /** Caption above the balance, e.g. \"Current balance\". Rendered only together with `balance`. */\n balanceLabel?: ReactNode\n /** Pre-formatted balance, e.g. \"$4,500.00\". Omitted (with its caption) when unknown. */\n balance?: ReactNode\n /** Label/value rows beneath the balance (payoff date, monthly payment, rate). */\n stats?: DebtPayoffStat[]\n /** Optional status pill label beside the account, e.g. the payoff strategy name. */\n statusLabel?: ReactNode\n}\n\nconst NEUTRAL_PILL: DebtPayoffPillConfig = { bgcolor: 'grey.200', labelColor: 'text.primary' }\n\n/** Native tooltip with the full value for a truncated line, when the value is plain text. */\nconst titleOf = (value: ReactNode) => (typeof value === 'string' ? value : undefined)\n\n/**\n * A debt account card: logo + account name row (with an optional status pill), the current\n * balance, and a divided list of label/value payoff stats, on a tinted slot.\n *\n * Purely presentational — it knows nothing about beats or variants; the Debts block passes\n * the style props for its look.\n */\nconst DebtPayoffCard = ({\n balance,\n balanceLabel,\n bgcolor = 'background.default',\n logo,\n name,\n pill = NEUTRAL_PILL,\n stats = [],\n statusLabel,\n subtitle,\n}: DebtPayoffCardProps) => (\n <Stack sx={{ px: 16, width: '100%' }}>\n <Box sx={{ bgcolor, borderRadius: '8px', p: 16, width: '100%' }}>\n <Stack\n sx={{\n bgcolor: 'background.paper',\n border: '1px solid',\n borderColor: 'divider',\n borderRadius: '8px',\n gap: 12,\n p: 16,\n width: '100%',\n }}\n >\n <Stack sx={{ alignItems: 'center', flexDirection: 'row', gap: 12 }}>\n <Box\n sx={{\n borderRadius: '4px',\n display: 'flex',\n flexShrink: 0,\n height: 40,\n overflow: 'hidden',\n width: 40,\n }}\n >\n {logo}\n </Box>\n <Stack sx={{ flexGrow: 1, minWidth: 0 }}>\n <Text sx={{ fontWeight: 600 }} title={titleOf(name)} truncate={true} variant=\"body2\">\n {name}\n </Text>\n {subtitle && (\n <Text\n color=\"text.secondary\"\n title={titleOf(subtitle)}\n truncate={true}\n variant=\"caption\"\n >\n {subtitle}\n </Text>\n )}\n </Stack>\n {statusLabel && (\n <StatusPill\n bgcolor={pill.bgcolor}\n label={statusLabel}\n labelColor={pill.labelColor}\n labelVariant=\"caption\"\n sx={{ alignSelf: 'center', border: 'none', flexShrink: 0, px: 12 }}\n />\n )}\n </Stack>\n\n {balance != null && balanceLabel != null && (\n <Stack>\n <Text color=\"text.secondary\" variant=\"caption\">\n {balanceLabel}\n </Text>\n {/* Display-size figure, not a heading: the feed owns the heading outline. */}\n <Text bold={true} color=\"text.primary\" component=\"p\" variant=\"h2\">\n {balance}\n </Text>\n </Stack>\n )}\n\n {stats.length > 0 && (\n <>\n <Divider />\n <Stack component=\"dl\" sx={{ gap: 8, m: 0 }}>\n {stats.map(({ label, value }, index) => (\n <Stack\n key={index}\n sx={{\n alignItems: 'baseline',\n flexDirection: 'row',\n gap: 12,\n justifyContent: 'space-between',\n }}\n >\n <Text color=\"text.secondary\" component=\"dt\" variant=\"caption\">\n {label}\n </Text>\n <Text component=\"dd\" sx={{ fontWeight: 600, m: 0 }} variant=\"body2\">\n {value}\n </Text>\n </Stack>\n ))}\n </Stack>\n </>\n )}\n </Stack>\n </Box>\n </Stack>\n)\n\nexport default DebtPayoffCard\n"],"mappings":";;;;;;AAoDA,IAAM,IAAqC;AAAA,EAAE,SAAS;AAAA,EAAY,YAAY;AAAe,GAGvF,IAAA,CAAW,MAAsB,OAAO,KAAU,WAAW,IAAQ,QASrE,IAAA,CAAkB,EACtB,SAAA,GACA,cAAA,GACA,SAAA,IAAU,sBACV,MAAA,GACA,MAAA,GACA,MAAA,IAAO,GACP,OAAA,IAAQ,CAAC,GACT,aAAA,GACA,UAAA,EAAA,MAEA,gBAAA,EAAC,GAAD;AAAA,EAAO,IAAI;AAAA,IAAE,IAAI;AAAA,IAAI,OAAO;AAAA,EAAO;AAAA,EACjC,UAAA,gBAAA,EAAC,GAAD;AAAA,IAAK,IAAI;AAAA,MAAE,SAAA;AAAA,MAAS,cAAc;AAAA,MAAO,GAAG;AAAA,MAAI,OAAO;AAAA,IAAO;AAAA,IAC5D,UAAA,gBAAA,EAAC,GAAD;AAAA,MACE,IAAI;AAAA,QACF,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,cAAc;AAAA,QACd,KAAK;AAAA,QACL,GAAG;AAAA,QACH,OAAO;AAAA,MACT;AAAA,MATF,UAAA;AAAA,QAWE,gBAAA,EAAC,GAAD;AAAA,UAAO,IAAI;AAAA,YAAE,YAAY;AAAA,YAAU,eAAe;AAAA,YAAO,KAAK;AAAA,UAAG;AAAA,UAAjE,UAAA;AAAA,YACE,gBAAA,EAAC,GAAD;AAAA,cACE,IAAI;AAAA,gBACF,cAAc;AAAA,gBACd,SAAS;AAAA,gBACT,YAAY;AAAA,gBACZ,QAAQ;AAAA,gBACR,UAAU;AAAA,gBACV,OAAO;AAAA,cACT;AAAA,cAEC,UAAA;AAAA,YACE,CAAA;AAAA,YACL,gBAAA,EAAC,GAAD;AAAA,cAAO,IAAI;AAAA,gBAAE,UAAU;AAAA,gBAAG,UAAU;AAAA,cAAE;AAAA,cAAtC,UAAA,CACE,gBAAA,EAAC,GAAD;AAAA,gBAAM,IAAI,EAAE,YAAY,IAAI;AAAA,gBAAG,OAAO,EAAQ,CAAI;AAAA,gBAAG,UAAU;AAAA,gBAAM,SAAQ;AAAA,gBAC1E,UAAA;AAAA,cACG,CAAA,GACL,KACC,gBAAA,EAAC,GAAD;AAAA,gBACE,OAAM;AAAA,gBACN,OAAO,EAAQ,CAAQ;AAAA,gBACvB,UAAU;AAAA,gBACV,SAAQ;AAAA,gBAEP,UAAA;AAAA,cACG,CAAA,CAEH;AAAA;YACN,KACC,gBAAA,EAAC,GAAD;AAAA,cACE,SAAS,EAAK;AAAA,cACd,OAAO;AAAA,cACP,YAAY,EAAK;AAAA,cACjB,cAAa;AAAA,cACb,IAAI;AAAA,gBAAE,WAAW;AAAA,gBAAU,QAAQ;AAAA,gBAAQ,YAAY;AAAA,gBAAG,IAAI;AAAA,cAAG;AAAA,YAClE,CAAA;AAAA,UAEE;AAAA;QAEN,KAAW,QAAQ,KAAgB,QAClC,gBAAA,EAAC,GAAD,EAAA,UAAA,CACE,gBAAA,EAAC,GAAD;AAAA,UAAM,OAAM;AAAA,UAAiB,SAAQ;AAAA,UAClC,UAAA;AAAA,QACG,CAAA,GAEN,gBAAA,EAAC,GAAD;AAAA,UAAM,MAAM;AAAA,UAAM,OAAM;AAAA,UAAe,WAAU;AAAA,UAAI,SAAQ;AAAA,UAC1D,UAAA;AAAA,QACG,CAAA,CACD,EAAA,CAAA;AAAA,QAGR,EAAM,SAAS,KACd,gBAAA,EAAA,GAAA,EAAA,UAAA,CACE,gBAAA,EAAC,GAAD,CAAU,CAAA,GACV,gBAAA,EAAC,GAAD;AAAA,UAAO,WAAU;AAAA,UAAK,IAAI;AAAA,YAAE,KAAK;AAAA,YAAG,GAAG;AAAA,UAAE;AAAA,UACtC,UAAA,EAAM,IAAA,CAAK,EAAE,OAAA,GAAO,OAAA,EAAA,GAAS,MAC5B,gBAAA,EAAC,GAAD;AAAA,YAEE,IAAI;AAAA,cACF,YAAY;AAAA,cACZ,eAAe;AAAA,cACf,KAAK;AAAA,cACL,gBAAgB;AAAA,YAClB;AAAA,YAPF,UAAA,CASE,gBAAA,EAAC,GAAD;AAAA,cAAM,OAAM;AAAA,cAAiB,WAAU;AAAA,cAAK,SAAQ;AAAA,cACjD,UAAA;AAAA,YACG,CAAA,GACN,gBAAA,EAAC,GAAD;AAAA,cAAM,WAAU;AAAA,cAAK,IAAI;AAAA,gBAAE,YAAY;AAAA,gBAAK,GAAG;AAAA,cAAE;AAAA,cAAG,SAAQ;AAAA,cACzD,UAAA;AAAA,YACG,CAAA,CACD;AAAA,UAdA,GAAA,CAcA,CACR;AAAA,QACI,CAAA,CACP,EAAA,CAAA;AAAA,MAEC;AAAA;EACJ,CAAA;AACA,CAAA"}
@@ -2,6 +2,7 @@ export * from './blocks';
2
2
  export { default as AccountHeroCard } from './components/AccountHeroCard';
3
3
  export { default as ConnectionDetailDrillDown, type ConnectionDetailContent, } from './components/ConnectionDetailDrillDown';
4
4
  export { default as DirectDepositCard, type DirectDepositCardStyleProps, type DirectDepositPillConfig, } from './components/DirectDepositCard';
5
+ export { default as DebtPayoffCard, type DebtPayoffCardStyleProps, type DebtPayoffPillConfig, type DebtPayoffStat, } from './components/DebtPayoffCard';
5
6
  export { default as AmountPill } from './components/AmountPill';
6
7
  export { default as BadgedTile } from './components/BadgedTile';
7
8
  export { default as StatusBadge, type StatusTone } from './components/StatusBadge';
@@ -4,15 +4,15 @@ import { useBeatActions as a } from "./beatActions.es.js";
4
4
  import f from "./components/BadgedTile.es.js";
5
5
  import { OverflowMenu as n } from "./components/OverflowMenu.es.js";
6
6
  import { InsightOptionsMenu as l } from "./components/InsightOptionsMenu.es.js";
7
- import d, { isLogoGuid as g } from "./components/LogoFromGuid.es.js";
8
- import C from "./components/StatusBadge.es.js";
7
+ import d, { isLogoGuid as B } from "./components/LogoFromGuid.es.js";
8
+ import g from "./components/StatusBadge.es.js";
9
9
  import k from "./components/CompactInsightCard.es.js";
10
10
  import h from "./components/InsightErrorCard.es.js";
11
11
  import { BAR_CHART_VARIANTS as b, barChartVariant as A, buildChartData as T, buildDataSeries as I } from "./blocks/ChartBlocks/BarchartBlock/utils.es.js";
12
12
  import { BarchartBlock as v } from "./blocks/ChartBlocks/BarchartBlock/BarchartBlock.es.js";
13
13
  import { DoubleBarChartBlock as O } from "./blocks/ChartBlocks/DoubleBarChartBlock/DoubleBarChartBlock.es.js";
14
- import M from "./blocks/ChartBlocks/StepChartBlock/StepChartBlock.es.js";
15
- import E from "./blocks/ChartBlocks/DonutChartBlock/DonutChartBlock.es.js";
14
+ import y from "./blocks/ChartBlocks/StepChartBlock/StepChartBlock.es.js";
15
+ import P from "./blocks/ChartBlocks/DonutChartBlock/DonutChartBlock.es.js";
16
16
  import R from "./blocks/ChartBlocks/DoubleProgressBarBlock/DoubleProgressBarBlock.es.js";
17
17
  import V from "./blocks/ComponentBlocks/AccountBlock/AccountBlock.es.js";
18
18
  import G from "./components/TransferLogoCard.es.js";
@@ -21,105 +21,109 @@ import W from "./components/AccountHeroCard.es.js";
21
21
  import q from "./components/DirectDepositCard.es.js";
22
22
  import J from "./blocks/ComponentBlocks/DirectDepositBlock/DirectDepositBlock.es.js";
23
23
  import { BudgetBlock as Q } from "./blocks/ComponentBlocks/BudgetBlock/BudgetBlock.es.js";
24
- import Y from "./components/SaveAnExtraCard.es.js";
25
- import $ from "./blocks/ComponentBlocks/SaveExtraBlock/SaveExtraBlock.es.js";
26
- import ro from "./components/SavingsOpportunityCard.es.js";
27
- import mo from "./blocks/ComponentBlocks/SavingsOpportunityBlock/SavingsOpportunityBlock.es.js";
28
- import ao from "./components/InsightTransactionRow.es.js";
29
- import fo from "./components/TransactionListCard.es.js";
30
- import { transactionBlockVariant as no } from "./blocks/ComponentBlocks/TransactionBlock/layout.es.js";
31
- import { TransactionBlock as lo } from "./blocks/ComponentBlocks/TransactionBlock/TransactionBlock.es.js";
32
- import go from "./components/UpcomingBillCard.es.js";
33
- import Co from "./blocks/ComponentBlocks/UpcomingBillBlock/UpcomingBillBlock.es.js";
34
- import ko from "./components/AmountPill.es.js";
35
- import ho from "./components/SubscriptionHeroCard.es.js";
36
- import bo from "./blocks/ComponentBlocks/UpcomingSubscriptionBlock/UpcomingSubscriptionBlock.es.js";
37
- import To from "./components/WithdrawalCard.es.js";
38
- import Lo from "./blocks/ComponentBlocks/WithdrawalBlock/WithdrawalBlock.es.js";
39
- import { SVGImageBlock as Ho } from "./blocks/ImageBlocks/SVGImageBlock/SVGImageBlock.es.js";
40
- import wo from "./components/ConnectionDetailDrillDown.es.js";
41
- import yo from "./components/DesignateEmergencySavingsCard.es.js";
42
- import Po from "./components/shared/StatusSnackbar.es.js";
43
- import Fo from "./components/FeedbackDialog.es.js";
44
- import xo from "./components/FeedbackModal.es.js";
45
- import Uo from "./components/SurveyModal.es.js";
46
- import { ErrorCard as No } from "./components/ErrorCard.es.js";
47
- import { HOST_ACTIONS as jo } from "./ctaActions/hostActions.es.js";
48
- import { useBeatCtaActions as zo, useCtaHandler as Jo } from "./ctaActions/useCtaAction.es.js";
49
- import { FeedbackBar as Qo } from "./components/FeedbackBar.es.js";
50
- import { DismissInsightDialog as Yo } from "./components/DismissInsightDialog.es.js";
51
- import { HiddenConfirmationCard as $o } from "./components/HiddenConfirmationCard.es.js";
52
- import { LoadingCard as rr } from "./components/LoadingCard.es.js";
53
- import { ObsolesceBanner as mr } from "./components/ObsolesceBanner.es.js";
54
- import ar from "./components/BaseLayout.es.js";
55
- import fr from "./components/StatusMessageCard.es.js";
56
- import nr from "./components/LogoTile.es.js";
57
- import lr from "./components/LogoClusterCard.es.js";
58
- import dr from "./components/MerchantHighlightCard.es.js";
59
- import Br from "./components/P2PLogoStack.es.js";
24
+ import Y from "./components/DebtPayoffCard.es.js";
25
+ import $ from "./components/UpcomingBillCard.es.js";
26
+ import ro from "./blocks/ComponentBlocks/UpcomingBillBlock/UpcomingBillBlock.es.js";
27
+ import mo from "./blocks/ComponentBlocks/DebtsBlock/DebtsBlock.es.js";
28
+ import ao from "./components/SaveAnExtraCard.es.js";
29
+ import fo from "./blocks/ComponentBlocks/SaveExtraBlock/SaveExtraBlock.es.js";
30
+ import no from "./components/SavingsOpportunityCard.es.js";
31
+ import lo from "./blocks/ComponentBlocks/SavingsOpportunityBlock/SavingsOpportunityBlock.es.js";
32
+ import Bo from "./components/InsightTransactionRow.es.js";
33
+ import go from "./components/TransactionListCard.es.js";
34
+ import { transactionBlockVariant as ko } from "./blocks/ComponentBlocks/TransactionBlock/layout.es.js";
35
+ import { TransactionBlock as ho } from "./blocks/ComponentBlocks/TransactionBlock/TransactionBlock.es.js";
36
+ import bo from "./components/AmountPill.es.js";
37
+ import To from "./components/SubscriptionHeroCard.es.js";
38
+ import Lo from "./blocks/ComponentBlocks/UpcomingSubscriptionBlock/UpcomingSubscriptionBlock.es.js";
39
+ import Ho from "./components/WithdrawalCard.es.js";
40
+ import wo from "./blocks/ComponentBlocks/WithdrawalBlock/WithdrawalBlock.es.js";
41
+ import { SVGImageBlock as Mo } from "./blocks/ImageBlocks/SVGImageBlock/SVGImageBlock.es.js";
42
+ import Eo from "./components/ConnectionDetailDrillDown.es.js";
43
+ import Fo from "./components/DesignateEmergencySavingsCard.es.js";
44
+ import xo from "./components/shared/StatusSnackbar.es.js";
45
+ import Uo from "./components/FeedbackDialog.es.js";
46
+ import No from "./components/FeedbackModal.es.js";
47
+ import jo from "./components/SurveyModal.es.js";
48
+ import { ErrorCard as zo } from "./components/ErrorCard.es.js";
49
+ import { HOST_ACTIONS as Ko } from "./ctaActions/hostActions.es.js";
50
+ import { useBeatCtaActions as Xo, useCtaHandler as Yo } from "./ctaActions/useCtaAction.es.js";
51
+ import { FeedbackBar as $o } from "./components/FeedbackBar.es.js";
52
+ import { DismissInsightDialog as rr } from "./components/DismissInsightDialog.es.js";
53
+ import { HiddenConfirmationCard as mr } from "./components/HiddenConfirmationCard.es.js";
54
+ import { LoadingCard as ar } from "./components/LoadingCard.es.js";
55
+ import { ObsolesceBanner as fr } from "./components/ObsolesceBanner.es.js";
56
+ import nr from "./components/BaseLayout.es.js";
57
+ import lr from "./components/StatusMessageCard.es.js";
58
+ import dr from "./components/LogoTile.es.js";
59
+ import Cr from "./components/LogoClusterCard.es.js";
60
+ import ur from "./components/MerchantHighlightCard.es.js";
61
+ import Sr from "./components/P2PLogoStack.es.js";
60
62
  export {
61
63
  V as AccountBlock,
62
64
  W as AccountHeroCard,
63
65
  _ as AccountSwitchBlock,
64
- ko as AmountPill,
66
+ bo as AmountPill,
65
67
  b as BAR_CHART_VARIANTS,
66
68
  f as BadgedTile,
67
69
  v as BarchartBlock,
68
- ar as BaseLayout,
70
+ nr as BaseLayout,
69
71
  Q as BudgetBlock,
70
72
  k as CompactInsightCard,
71
- wo as ConnectionDetailDrillDown,
72
- yo as DesignateEmergencySavingsCard,
73
+ Eo as ConnectionDetailDrillDown,
74
+ Y as DebtPayoffCard,
75
+ mo as DebtsBlock,
76
+ Fo as DesignateEmergencySavingsCard,
73
77
  J as DirectDepositBlock,
74
78
  q as DirectDepositCard,
75
- Yo as DismissInsightDialog,
76
- E as DonutChartBlock,
79
+ rr as DismissInsightDialog,
80
+ P as DonutChartBlock,
77
81
  O as DoubleBarChartBlock,
78
82
  R as DoubleProgressBarBlock,
79
- No as ErrorCard,
80
- Qo as FeedbackBar,
81
- Fo as FeedbackDialog,
82
- xo as FeedbackModal,
83
- jo as HOST_ACTIONS,
84
- $o as HiddenConfirmationCard,
83
+ zo as ErrorCard,
84
+ $o as FeedbackBar,
85
+ Uo as FeedbackDialog,
86
+ No as FeedbackModal,
87
+ Ko as HOST_ACTIONS,
88
+ mr as HiddenConfirmationCard,
85
89
  h as InsightErrorCard,
86
90
  l as InsightOptionsMenu,
87
- ao as InsightTransactionRow,
88
- rr as LoadingCard,
89
- lr as LogoClusterCard,
91
+ Bo as InsightTransactionRow,
92
+ ar as LoadingCard,
93
+ Cr as LogoClusterCard,
90
94
  d as LogoFromGuid,
91
- nr as LogoTile,
92
- dr as MerchantHighlightCard,
93
- mr as ObsolesceBanner,
95
+ dr as LogoTile,
96
+ ur as MerchantHighlightCard,
97
+ fr as ObsolesceBanner,
94
98
  n as OverflowMenu,
95
- Br as P2PLogoStack,
96
- Ho as SVGImageBlock,
97
- Y as SaveAnExtraCard,
98
- $ as SaveExtraBlock,
99
- mo as SavingsOpportunityBlock,
100
- ro as SavingsOpportunityCard,
101
- C as StatusBadge,
102
- fr as StatusMessageCard,
99
+ Sr as P2PLogoStack,
100
+ Mo as SVGImageBlock,
101
+ ao as SaveAnExtraCard,
102
+ fo as SaveExtraBlock,
103
+ lo as SavingsOpportunityBlock,
104
+ no as SavingsOpportunityCard,
105
+ g as StatusBadge,
106
+ lr as StatusMessageCard,
103
107
  r as StatusPill,
104
- Po as StatusSnackbar,
105
- M as StepChartBlock,
106
- ho as SubscriptionHeroCard,
107
- Uo as SurveyModal,
108
- lo as TransactionBlock,
109
- fo as TransactionListCard,
108
+ xo as StatusSnackbar,
109
+ y as StepChartBlock,
110
+ To as SubscriptionHeroCard,
111
+ jo as SurveyModal,
112
+ ho as TransactionBlock,
113
+ go as TransactionListCard,
110
114
  G as TransferLogoCard,
111
- Co as UpcomingBillBlock,
112
- go as UpcomingBillCard,
113
- bo as UpcomingSubscriptionBlock,
114
- Lo as WithdrawalBlock,
115
- To as WithdrawalCard,
115
+ ro as UpcomingBillBlock,
116
+ $ as UpcomingBillCard,
117
+ Lo as UpcomingSubscriptionBlock,
118
+ wo as WithdrawalBlock,
119
+ Ho as WithdrawalCard,
116
120
  A as barChartVariant,
117
121
  T as buildChartData,
118
122
  I as buildDataSeries,
119
- g as isLogoGuid,
123
+ B as isLogoGuid,
120
124
  m as resolveInsightRender,
121
- no as transactionBlockVariant,
125
+ ko as transactionBlockVariant,
122
126
  a as useBeatActions,
123
- zo as useBeatCtaActions,
124
- Jo as useCtaHandler
127
+ Xo as useBeatCtaActions,
128
+ Yo as useCtaHandler
125
129
  };
@@ -1,4 +1,4 @@
1
- import { ContactSupportActionBlock as c } from "../actionBlocks/ContactSupportActionBlock.es.js";
1
+ import { ContactSupportActionBlock as n } from "../actionBlocks/ContactSupportActionBlock.es.js";
2
2
  import { actionBlocksKey as o } from "./actionBlocksKey.es.js";
3
3
  import { BarchartBlock as m } from "../blocks/ChartBlocks/BarchartBlock/BarchartBlock.es.js";
4
4
  import { DoubleBarChartBlock as l } from "../blocks/ChartBlocks/DoubleBarChartBlock/DoubleBarChartBlock.es.js";
@@ -9,120 +9,122 @@ import C from "../blocks/ComponentBlocks/AccountBlock/AccountBlock.es.js";
9
9
  import k from "../blocks/ComponentBlocks/AccountSwitchBlock/AccountSwitchBlock.es.js";
10
10
  import B from "../blocks/ComponentBlocks/DirectDepositBlock/DirectDepositBlock.es.js";
11
11
  import { BudgetBlock as T } from "../blocks/ComponentBlocks/BudgetBlock/BudgetBlock.es.js";
12
- import A from "../blocks/ComponentBlocks/SaveExtraBlock/SaveExtraBlock.es.js";
13
- import u from "../blocks/ComponentBlocks/SavingsOpportunityBlock/SavingsOpportunityBlock.es.js";
14
- import { TransactionBlock as O } from "../blocks/ComponentBlocks/TransactionBlock/TransactionBlock.es.js";
15
- import f from "../blocks/ComponentBlocks/UpcomingBillBlock/UpcomingBillBlock.es.js";
12
+ import A from "../blocks/ComponentBlocks/UpcomingBillBlock/UpcomingBillBlock.es.js";
13
+ import u from "../blocks/ComponentBlocks/DebtsBlock/DebtsBlock.es.js";
14
+ import O from "../blocks/ComponentBlocks/SaveExtraBlock/SaveExtraBlock.es.js";
15
+ import f from "../blocks/ComponentBlocks/SavingsOpportunityBlock/SavingsOpportunityBlock.es.js";
16
+ import { TransactionBlock as b } from "../blocks/ComponentBlocks/TransactionBlock/TransactionBlock.es.js";
16
17
  import N from "../blocks/ComponentBlocks/UpcomingSubscriptionBlock/UpcomingSubscriptionBlock.es.js";
17
- import b from "../blocks/ComponentBlocks/WithdrawalBlock/WithdrawalBlock.es.js";
18
- import I from "../blocks/ImageBlocks/ImageBlock.es.js";
19
- import { SVGImageBlock as d } from "../blocks/ImageBlocks/SVGImageBlock/SVGImageBlock.es.js";
20
- import { FeedbackModalActionBlock as g } from "../actionBlocks/FeedbackModalActionBlock.es.js";
21
- import { ConnectionDetailActionBlock as L } from "../actionBlocks/ConnectionDetailActionBlock.es.js";
22
- import { ConnectWidgetActionBlock as D } from "../actionBlocks/ConnectWidgetActionBlock.es.js";
23
- import { SurveyModalActionBlock as P } from "../actionBlocks/SurveyModalActionBlock.es.js";
24
- import { PlaceholderActionBlock as h } from "../actionBlocks/PlaceholderActionBlock.es.js";
25
- import { getMakeTransferDrawerTitle as S } from "../actionBlocks/MakeTransferActionBlock/layout.es.js";
26
- import { MakeTransferActionBlockLayer as R } from "../actionBlocks/MakeTransferActionBlock/MakeTransferActionBlockLayer.es.js";
27
- import { getDrawerHeaderTitle as K } from "../actionBlocks/TransactionHistoryBlock/utils.es.js";
28
- import { TransactionDetailsBlock as E } from "../actionBlocks/TransactionDetailsBlock/TransactionDetailsBlock.es.js";
18
+ import I from "../blocks/ComponentBlocks/WithdrawalBlock/WithdrawalBlock.es.js";
19
+ import d from "../blocks/ImageBlocks/ImageBlock.es.js";
20
+ import { SVGImageBlock as g } from "../blocks/ImageBlocks/SVGImageBlock/SVGImageBlock.es.js";
21
+ import { FeedbackModalActionBlock as L } from "../actionBlocks/FeedbackModalActionBlock.es.js";
22
+ import { ConnectionDetailActionBlock as D } from "../actionBlocks/ConnectionDetailActionBlock.es.js";
23
+ import { ConnectWidgetActionBlock as P } from "../actionBlocks/ConnectWidgetActionBlock.es.js";
24
+ import { SurveyModalActionBlock as h } from "../actionBlocks/SurveyModalActionBlock.es.js";
25
+ import { PlaceholderActionBlock as S } from "../actionBlocks/PlaceholderActionBlock.es.js";
26
+ import { getMakeTransferDrawerTitle as R } from "../actionBlocks/MakeTransferActionBlock/layout.es.js";
27
+ import { MakeTransferActionBlockLayer as K } from "../actionBlocks/MakeTransferActionBlock/MakeTransferActionBlockLayer.es.js";
28
+ import { getDrawerHeaderTitle as E } from "../actionBlocks/TransactionHistoryBlock/utils.es.js";
29
+ import { TransactionDetailsBlock as v } from "../actionBlocks/TransactionDetailsBlock/TransactionDetailsBlock.es.js";
29
30
  import { useTransactionDetailsPrepare as i } from "../actionBlocks/TransactionDetailsBlock/useTransactionDetailsPrepare.es.js";
30
- import { TransactionHistoryBlock as v } from "../actionBlocks/TransactionHistoryBlock/TransactionHistoryBlock.es.js";
31
+ import { TransactionHistoryBlock as M } from "../actionBlocks/TransactionHistoryBlock/TransactionHistoryBlock.es.js";
31
32
  import { useRecurringTransactionPrepare as a } from "../actionBlocks/RecurringTransactionBlock/useRecurringTransactionPrepare.es.js";
32
- import { RecurringTransactionBlock as M } from "../actionBlocks/RecurringTransactionBlock/RecurringTransactionBlock.es.js";
33
- import { TransactionListBlock as w } from "../actionBlocks/TransactionListBlock/TransactionListBlock.es.js";
34
- import { RemainingCashBlock as y } from "../actionBlocks/RemainingCashBlock/RemainingCashBlock.es.js";
35
- import { hasDrawerBlock as fo } from "./hasDrawerBlock.es.js";
36
- import { AmountInputModalBlock as U } from "../actionBlocks/AmountInputModalBlock/AmountInputModalBlock.es.js";
33
+ import { RecurringTransactionBlock as w } from "../actionBlocks/RecurringTransactionBlock/RecurringTransactionBlock.es.js";
34
+ import { TransactionListBlock as y } from "../actionBlocks/TransactionListBlock/TransactionListBlock.es.js";
35
+ import { RemainingCashBlock as U } from "../actionBlocks/RemainingCashBlock/RemainingCashBlock.es.js";
36
+ import { hasDrawerBlock as No } from "./hasDrawerBlock.es.js";
37
+ import { AmountInputModalBlock as H } from "../actionBlocks/AmountInputModalBlock/AmountInputModalBlock.es.js";
37
38
  var r = (e) => {
38
- }, bo = {
39
+ }, go = {
39
40
  [o.PLACEHOLDER_ACTION_BLOCK]: {
40
- Component: h,
41
+ Component: S,
41
42
  usePrepare: r,
42
43
  title: () => "Action Block Layer Drilldown"
43
44
  },
44
45
  [o.MAKE_TRANSFER_ACTION_BLOCK]: {
45
- Component: R,
46
+ Component: K,
46
47
  usePrepare: r,
47
- title: S
48
+ title: R
48
49
  },
49
50
  [o.TRANSCATION_HISTORY_ACTION_BLOCK]: {
50
- Component: v,
51
+ Component: M,
51
52
  usePrepare: r,
52
- title: K
53
+ title: E
53
54
  },
54
55
  [o.TRANSACTION_DETAILS_ACTION_BLOCK]: {
55
- Component: E,
56
+ Component: v,
56
57
  usePrepare: i,
57
58
  title: () => "Transaction Details"
58
59
  },
59
60
  [o.RECURRING_TRANSACTION_ACTION_BLOCK]: {
60
- Component: M,
61
+ Component: w,
61
62
  usePrepare: a,
62
63
  title: (e, t) => t.recurring?.expense_details ?? ""
63
64
  },
64
65
  [o.REMAINING_CASH_ACTION_BLOCK]: {
65
- Component: y,
66
+ Component: U,
66
67
  usePrepare: a,
67
68
  title: (e, t) => t.insights_feed?.remaining_cash?.title ?? ""
68
69
  },
69
70
  [o.CONTACT_SUPPORT_ACTION_BLOCK]: {
70
- Component: c,
71
+ Component: n,
71
72
  usePrepare: r,
72
73
  title: (e, t) => t.help?.request_support ?? ""
73
74
  },
74
75
  [o.FEEDBACK_MODAL_ACTION_BLOCK]: {
75
- Component: g,
76
+ Component: L,
76
77
  usePrepare: r,
77
78
  presentation: "modal"
78
79
  },
79
80
  [o.CONNECTION_DETAIL_ACTION_BLOCK]: {
80
- Component: L,
81
+ Component: D,
81
82
  usePrepare: r,
82
83
  title: (e, t) => t.insights_feed?.connection_details?.connection_details_drawer_title ?? ""
83
84
  },
84
85
  [o.CONNECT_WIDGET_ACTION_BLOCK]: {
85
- Component: D,
86
+ Component: P,
86
87
  usePrepare: r
87
88
  },
88
89
  [o.SURVEY_MODAL_ACTION_BLOCK]: {
89
- Component: P,
90
+ Component: h,
90
91
  usePrepare: r,
91
92
  presentation: "modal"
92
93
  },
93
94
  [o.TRANSACTION_LIST_ACTION_BLOCK]: {
94
- Component: w,
95
+ Component: y,
95
96
  usePrepare: i,
96
- title: (e, t, n) => n?.insights_payload?.title ?? ""
97
+ title: (e, t, c) => c?.insights_payload?.title ?? ""
97
98
  },
98
99
  [o.AMOUNT_INPUT_MODAL_ACTION_BLOCK]: {
99
- Component: U,
100
+ Component: H,
100
101
  presentation: "modal",
101
102
  usePrepare: r
102
103
  }
103
- }, Io = {
104
+ }, Lo = {
104
105
  account_block: C,
105
106
  account_switch_block: k,
106
107
  direct_deposit_block: B,
107
108
  bar_chart_block: m,
108
109
  budget_block: T,
110
+ debts_block: u,
109
111
  donut_chart_block: _,
110
112
  double_bar_chart_block: l,
111
113
  double_progress_bar_block: s,
112
- image_block: I,
113
- save_extra_block: A,
114
- savings_opportunity_block: u,
114
+ image_block: d,
115
+ save_extra_block: O,
116
+ savings_opportunity_block: f,
115
117
  step_chart_block: p,
116
- svg_image_block: d,
117
- upcoming_bill_block: f,
118
+ svg_image_block: g,
119
+ upcoming_bill_block: A,
118
120
  upcoming_subscription_block: N,
119
- withdrawal_block: b,
120
- transaction_block: O
121
+ withdrawal_block: I,
122
+ transaction_block: b
121
123
  };
122
124
  export {
123
- bo as actionBlocks,
124
- Io as blocks,
125
- fo as hasDrawerBlock
125
+ go as actionBlocks,
126
+ Lo as blocks,
127
+ No as hasDrawerBlock
126
128
  };
127
129
 
128
130
  //# sourceMappingURL=blocks.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"blocks.es.js","names":[],"sources":["../../../src/insights-v2/mappings/blocks.ts"],"sourcesContent":["import {\n AccountBlock,\n AccountSwitchBlock,\n DirectDepositBlock,\n BarchartBlock,\n BudgetBlock,\n DonutChartBlock,\n DoubleBarChartBlock,\n DoubleProgressBarBlock,\n SaveExtraBlock,\n SavingsOpportunityBlock,\n SVGImageBlock,\n UpcomingBillBlock,\n UpcomingSubscriptionBlock,\n WithdrawalBlock,\n TransactionBlock,\n} from '../blocks'\nimport StepChartBlock from '../blocks/ChartBlocks/StepChartBlock'\nimport ImageBlock from '../blocks/ImageBlocks/ImageBlock'\n\nimport type { Beat, GlobalCopy, InsightsPayload } from '../../core'\nimport { ContactSupportActionBlock } from '../actionBlocks/ContactSupportActionBlock'\nimport { FeedbackModalActionBlock } from '../actionBlocks/FeedbackModalActionBlock'\nimport { ConnectionDetailActionBlock } from '../actionBlocks/ConnectionDetailActionBlock'\nimport { ConnectWidgetActionBlock } from '../actionBlocks/ConnectWidgetActionBlock'\nimport { SurveyModalActionBlock } from '../actionBlocks/SurveyModalActionBlock'\nimport { PlaceholderActionBlock } from '../actionBlocks/PlaceholderActionBlock'\nimport { MakeTransferActionBlockLayer } from '../actionBlocks/MakeTransferActionBlock/MakeTransferActionBlockLayer'\nimport { getMakeTransferDrawerTitle } from '../actionBlocks/MakeTransferActionBlock/layout'\nimport { TransactionHistoryBlock } from '../actionBlocks/TransactionHistoryBlock/TransactionHistoryBlock'\nimport { getDrawerHeaderTitle } from '../actionBlocks/TransactionHistoryBlock/utils'\nimport {\n TransactionDetailsBlock,\n useTransactionDetailsPrepare,\n} from '../actionBlocks/TransactionDetailsBlock'\nimport {\n RecurringTransactionBlock,\n useRecurringTransactionPrepare,\n} from '../actionBlocks/RecurringTransactionBlock'\nimport { TransactionListBlock } from '../actionBlocks/TransactionListBlock'\nimport { RemainingCashBlock } from '../actionBlocks/RemainingCashBlock'\nimport { AmountInputModalBlock } from '../actionBlocks/AmountInputModalBlock'\n// Keys live in ./actionBlocksKey (imported directly by chart blocks/tests too) to avoid a\n// circular import between this module and the chart blocks — see that file for details.\nimport { actionBlocksKey } from './actionBlocksKey'\n\n// Drilldown indexes are not passed down: action blocks read them from\n// InsightsV2Store (useInsightsV2Store().actionDrawer).\nexport interface ActionBlockProps {\n beat: Beat\n}\n\nconst noop = (_: ActionBlockProps) => {}\n\n// Re-exported so existing `hasDrawerBlock` imports from this module keep working.\nexport { hasDrawerBlock } from './hasDrawerBlock'\n\nexport interface ActionBlockEntry {\n Component: React.ComponentType<ActionBlockProps>\n usePrepare: (props: ActionBlockProps) => void // required; default to noop in each entry\n // Resolves the drawer title from the clicked CTA's variant + copy, with the beat available\n // for blocks that title from beat fields (e.g. transaction-list reads insights_payload.title).\n // Falls back to the CTA label when the resolver returns an empty string / is absent.\n title?: (variant: string | null | undefined, copy: GlobalCopy, beat?: Beat) => string\n // 'drawer' (default) or 'modal' (component renders its own dialog, no Drawer wrapper).\n presentation?: 'drawer' | 'modal'\n}\n\n// Registry of drawer drilldowns, keyed by the `block` name the backend sends\n// on a beat's CTA. To add one: create a component taking ActionBlockProps,\n// read the clicked indexes from useInsightsV2Store().actionDrawer, and\n// register it here. Add\n// `usePrepare` when the block needs to load data before rendering.\n\nexport const actionBlocks = {\n [actionBlocksKey.PLACEHOLDER_ACTION_BLOCK]: {\n Component: PlaceholderActionBlock,\n usePrepare: noop,\n title: () => 'Action Block Layer Drilldown',\n },\n [actionBlocksKey.MAKE_TRANSFER_ACTION_BLOCK]: {\n Component: MakeTransferActionBlockLayer,\n usePrepare: noop,\n title: getMakeTransferDrawerTitle,\n },\n [actionBlocksKey.TRANSCATION_HISTORY_ACTION_BLOCK]: {\n Component: TransactionHistoryBlock,\n usePrepare: noop,\n title: getDrawerHeaderTitle,\n },\n [actionBlocksKey.TRANSACTION_DETAILS_ACTION_BLOCK]: {\n Component: TransactionDetailsBlock,\n usePrepare: useTransactionDetailsPrepare,\n title: () => 'Transaction Details',\n },\n // Expense Details for one recurring subscription. Which subscription a beat names is resolved in\n // `RecurringTransactionBlock/subscriptionBeats.ts`, not through this registry.\n [actionBlocksKey.RECURRING_TRANSACTION_ACTION_BLOCK]: {\n Component: RecurringTransactionBlock,\n usePrepare: useRecurringTransactionPrepare,\n title: (_variant, copy) => copy.recurring?.expense_details ?? '',\n },\n // Remaining Cash for the Payday Cash Left Over Status beat. Store-driven: reuses the recurring\n // loader, which also loads accounts and categories, so CashflowStore's computeds are ready.\n [actionBlocksKey.REMAINING_CASH_ACTION_BLOCK]: {\n Component: RemainingCashBlock,\n usePrepare: useRecurringTransactionPrepare,\n title: (_variant, copy) => copy.insights_feed?.remaining_cash?.title ?? '',\n },\n // The block renders its own drawer (the help module's RequestSupport) on top of the action\n // drawer, so the action drawer's title is the CTA label.\n [actionBlocksKey.CONTACT_SUPPORT_ACTION_BLOCK]: {\n Component: ContactSupportActionBlock,\n usePrepare: noop,\n title: (_variant, copy) => copy.help?.request_support ?? '',\n },\n [actionBlocksKey.FEEDBACK_MODAL_ACTION_BLOCK]: {\n Component: FeedbackModalActionBlock,\n usePrepare: noop,\n presentation: 'modal',\n },\n [actionBlocksKey.CONNECTION_DETAIL_ACTION_BLOCK]: {\n Component: ConnectionDetailActionBlock,\n usePrepare: noop,\n title: (_variant, copy) =>\n copy.insights_feed?.connection_details?.connection_details_drawer_title ?? '',\n },\n // Boots MX's Connect widget (web-widget-sdk iframe) inside the action\n // drawer; the drawer title falls back to the CTA label.\n [actionBlocksKey.CONNECT_WIDGET_ACTION_BLOCK]: {\n Component: ConnectWidgetActionBlock,\n usePrepare: noop,\n },\n [actionBlocksKey.SURVEY_MODAL_ACTION_BLOCK]: {\n Component: SurveyModalActionBlock,\n usePrepare: noop,\n presentation: 'modal',\n },\n [actionBlocksKey.TRANSACTION_LIST_ACTION_BLOCK]: {\n Component: TransactionListBlock,\n usePrepare: useTransactionDetailsPrepare,\n title: (_variant, _copy, beat) => beat?.insights_payload?.title ?? '',\n },\n // One whole-dollar setting in a dialog; the CTA variant picks which (low-balance threshold or\n // safety net). A modal: no drawer, so no drawer title.\n [actionBlocksKey.AMOUNT_INPUT_MODAL_ACTION_BLOCK]: {\n Component: AmountInputModalBlock,\n presentation: 'modal',\n // Loads inside the block: it mounts only while open, so mounting is the open-time load.\n usePrepare: noop,\n },\n} as Record<string, ActionBlockEntry>\n\nexport const blocks = {\n account_block: AccountBlock,\n account_switch_block: AccountSwitchBlock,\n direct_deposit_block: DirectDepositBlock,\n bar_chart_block: BarchartBlock,\n budget_block: BudgetBlock,\n donut_chart_block: DonutChartBlock,\n double_bar_chart_block: DoubleBarChartBlock,\n double_progress_bar_block: DoubleProgressBarBlock,\n image_block: ImageBlock,\n save_extra_block: SaveExtraBlock,\n savings_opportunity_block: SavingsOpportunityBlock,\n step_chart_block: StepChartBlock,\n svg_image_block: SVGImageBlock,\n upcoming_bill_block: UpcomingBillBlock,\n upcoming_subscription_block: UpcomingSubscriptionBlock,\n withdrawal_block: WithdrawalBlock,\n transaction_block: TransactionBlock,\n} as Record<string, React.ComponentType<{ payload: InsightsPayload; beatGuid?: string }>>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDA,IAAM,IAAA,CAAQ,MAAwB;AAAC,GAsB1B,KAAe;AAAA,EACzB,CAAA,EAAgB,wBAAA,GAA2B;AAAA,IAC1C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,MAAa;AAAA,EACf;AAAA,EACC,CAAA,EAAgB,0BAAA,GAA6B;AAAA,IAC5C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAO;AAAA,EACT;AAAA,EACC,CAAA,EAAgB,gCAAA,GAAmC;AAAA,IAClD,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAO;AAAA,EACT;AAAA,EACC,CAAA,EAAgB,gCAAA,GAAmC;AAAA,IAClD,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,MAAa;AAAA,EACf;AAAA,EAGC,CAAA,EAAgB,kCAAA,GAAqC;AAAA,IACpD,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,CAAQ,GAAU,MAAS,EAAK,WAAW,mBAAmB;AAAA,EAChE;AAAA,EAGC,CAAA,EAAgB,2BAAA,GAA8B;AAAA,IAC7C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,CAAQ,GAAU,MAAS,EAAK,eAAe,gBAAgB,SAAS;AAAA,EAC1E;AAAA,EAGC,CAAA,EAAgB,4BAAA,GAA+B;AAAA,IAC9C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,CAAQ,GAAU,MAAS,EAAK,MAAM,mBAAmB;AAAA,EAC3D;AAAA,EACC,CAAA,EAAgB,2BAAA,GAA8B;AAAA,IAC7C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,cAAc;AAAA,EAChB;AAAA,EACC,CAAA,EAAgB,8BAAA,GAAiC;AAAA,IAChD,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,CAAQ,GAAU,MAChB,EAAK,eAAe,oBAAoB,mCAAmC;AAAA,EAC/E;AAAA,EAGC,CAAA,EAAgB,2BAAA,GAA8B;AAAA,IAC7C,WAAW;AAAA,IACX,YAAY;AAAA,EACd;AAAA,EACC,CAAA,EAAgB,yBAAA,GAA4B;AAAA,IAC3C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,cAAc;AAAA,EAChB;AAAA,EACC,CAAA,EAAgB,6BAAA,GAAgC;AAAA,IAC/C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,CAAQ,GAAU,GAAO,MAAS,GAAM,kBAAkB,SAAS;AAAA,EACrE;AAAA,EAGC,CAAA,EAAgB,+BAAA,GAAkC;AAAA,IACjD,WAAW;AAAA,IACX,cAAc;AAAA,IAEd,YAAY;AAAA,EACd;AACF,GAEa,KAAS;AAAA,EACpB,eAAe;AAAA,EACf,sBAAsB;AAAA,EACtB,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,wBAAwB;AAAA,EACxB,2BAA2B;AAAA,EAC3B,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,2BAA2B;AAAA,EAC3B,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,6BAA6B;AAAA,EAC7B,kBAAkB;AAAA,EAClB,mBAAmB;AACrB"}
1
+ {"version":3,"file":"blocks.es.js","names":[],"sources":["../../../src/insights-v2/mappings/blocks.ts"],"sourcesContent":["import {\n AccountBlock,\n AccountSwitchBlock,\n DirectDepositBlock,\n BarchartBlock,\n BudgetBlock,\n DebtsBlock,\n DonutChartBlock,\n DoubleBarChartBlock,\n DoubleProgressBarBlock,\n SaveExtraBlock,\n SavingsOpportunityBlock,\n SVGImageBlock,\n UpcomingBillBlock,\n UpcomingSubscriptionBlock,\n WithdrawalBlock,\n TransactionBlock,\n} from '../blocks'\nimport StepChartBlock from '../blocks/ChartBlocks/StepChartBlock'\nimport ImageBlock from '../blocks/ImageBlocks/ImageBlock'\n\nimport type { Beat, GlobalCopy, InsightsPayload } from '../../core'\nimport { ContactSupportActionBlock } from '../actionBlocks/ContactSupportActionBlock'\nimport { FeedbackModalActionBlock } from '../actionBlocks/FeedbackModalActionBlock'\nimport { ConnectionDetailActionBlock } from '../actionBlocks/ConnectionDetailActionBlock'\nimport { ConnectWidgetActionBlock } from '../actionBlocks/ConnectWidgetActionBlock'\nimport { SurveyModalActionBlock } from '../actionBlocks/SurveyModalActionBlock'\nimport { PlaceholderActionBlock } from '../actionBlocks/PlaceholderActionBlock'\nimport { MakeTransferActionBlockLayer } from '../actionBlocks/MakeTransferActionBlock/MakeTransferActionBlockLayer'\nimport { getMakeTransferDrawerTitle } from '../actionBlocks/MakeTransferActionBlock/layout'\nimport { TransactionHistoryBlock } from '../actionBlocks/TransactionHistoryBlock/TransactionHistoryBlock'\nimport { getDrawerHeaderTitle } from '../actionBlocks/TransactionHistoryBlock/utils'\nimport {\n TransactionDetailsBlock,\n useTransactionDetailsPrepare,\n} from '../actionBlocks/TransactionDetailsBlock'\nimport {\n RecurringTransactionBlock,\n useRecurringTransactionPrepare,\n} from '../actionBlocks/RecurringTransactionBlock'\nimport { TransactionListBlock } from '../actionBlocks/TransactionListBlock'\nimport { RemainingCashBlock } from '../actionBlocks/RemainingCashBlock'\nimport { AmountInputModalBlock } from '../actionBlocks/AmountInputModalBlock'\n// Keys live in ./actionBlocksKey (imported directly by chart blocks/tests too) to avoid a\n// circular import between this module and the chart blocks — see that file for details.\nimport { actionBlocksKey } from './actionBlocksKey'\n\n// Drilldown indexes are not passed down: action blocks read them from\n// InsightsV2Store (useInsightsV2Store().actionDrawer).\nexport interface ActionBlockProps {\n beat: Beat\n}\n\nconst noop = (_: ActionBlockProps) => {}\n\n// Re-exported so existing `hasDrawerBlock` imports from this module keep working.\nexport { hasDrawerBlock } from './hasDrawerBlock'\n\nexport interface ActionBlockEntry {\n Component: React.ComponentType<ActionBlockProps>\n usePrepare: (props: ActionBlockProps) => void // required; default to noop in each entry\n // Resolves the drawer title from the clicked CTA's variant + copy, with the beat available\n // for blocks that title from beat fields (e.g. transaction-list reads insights_payload.title).\n // Falls back to the CTA label when the resolver returns an empty string / is absent.\n title?: (variant: string | null | undefined, copy: GlobalCopy, beat?: Beat) => string\n // 'drawer' (default) or 'modal' (component renders its own dialog, no Drawer wrapper).\n presentation?: 'drawer' | 'modal'\n}\n\n// Registry of drawer drilldowns, keyed by the `block` name the backend sends\n// on a beat's CTA. To add one: create a component taking ActionBlockProps,\n// read the clicked indexes from useInsightsV2Store().actionDrawer, and\n// register it here. Add\n// `usePrepare` when the block needs to load data before rendering.\n\nexport const actionBlocks = {\n [actionBlocksKey.PLACEHOLDER_ACTION_BLOCK]: {\n Component: PlaceholderActionBlock,\n usePrepare: noop,\n title: () => 'Action Block Layer Drilldown',\n },\n [actionBlocksKey.MAKE_TRANSFER_ACTION_BLOCK]: {\n Component: MakeTransferActionBlockLayer,\n usePrepare: noop,\n title: getMakeTransferDrawerTitle,\n },\n [actionBlocksKey.TRANSCATION_HISTORY_ACTION_BLOCK]: {\n Component: TransactionHistoryBlock,\n usePrepare: noop,\n title: getDrawerHeaderTitle,\n },\n [actionBlocksKey.TRANSACTION_DETAILS_ACTION_BLOCK]: {\n Component: TransactionDetailsBlock,\n usePrepare: useTransactionDetailsPrepare,\n title: () => 'Transaction Details',\n },\n // Expense Details for one recurring subscription. Which subscription a beat names is resolved in\n // `RecurringTransactionBlock/subscriptionBeats.ts`, not through this registry.\n [actionBlocksKey.RECURRING_TRANSACTION_ACTION_BLOCK]: {\n Component: RecurringTransactionBlock,\n usePrepare: useRecurringTransactionPrepare,\n title: (_variant, copy) => copy.recurring?.expense_details ?? '',\n },\n // Remaining Cash for the Payday Cash Left Over Status beat. Store-driven: reuses the recurring\n // loader, which also loads accounts and categories, so CashflowStore's computeds are ready.\n [actionBlocksKey.REMAINING_CASH_ACTION_BLOCK]: {\n Component: RemainingCashBlock,\n usePrepare: useRecurringTransactionPrepare,\n title: (_variant, copy) => copy.insights_feed?.remaining_cash?.title ?? '',\n },\n // The block renders its own drawer (the help module's RequestSupport) on top of the action\n // drawer, so the action drawer's title is the CTA label.\n [actionBlocksKey.CONTACT_SUPPORT_ACTION_BLOCK]: {\n Component: ContactSupportActionBlock,\n usePrepare: noop,\n title: (_variant, copy) => copy.help?.request_support ?? '',\n },\n [actionBlocksKey.FEEDBACK_MODAL_ACTION_BLOCK]: {\n Component: FeedbackModalActionBlock,\n usePrepare: noop,\n presentation: 'modal',\n },\n [actionBlocksKey.CONNECTION_DETAIL_ACTION_BLOCK]: {\n Component: ConnectionDetailActionBlock,\n usePrepare: noop,\n title: (_variant, copy) =>\n copy.insights_feed?.connection_details?.connection_details_drawer_title ?? '',\n },\n // Boots MX's Connect widget (web-widget-sdk iframe) inside the action\n // drawer; the drawer title falls back to the CTA label.\n [actionBlocksKey.CONNECT_WIDGET_ACTION_BLOCK]: {\n Component: ConnectWidgetActionBlock,\n usePrepare: noop,\n },\n [actionBlocksKey.SURVEY_MODAL_ACTION_BLOCK]: {\n Component: SurveyModalActionBlock,\n usePrepare: noop,\n presentation: 'modal',\n },\n [actionBlocksKey.TRANSACTION_LIST_ACTION_BLOCK]: {\n Component: TransactionListBlock,\n usePrepare: useTransactionDetailsPrepare,\n title: (_variant, _copy, beat) => beat?.insights_payload?.title ?? '',\n },\n // One whole-dollar setting in a dialog; the CTA variant picks which (low-balance threshold or\n // safety net). A modal: no drawer, so no drawer title.\n [actionBlocksKey.AMOUNT_INPUT_MODAL_ACTION_BLOCK]: {\n Component: AmountInputModalBlock,\n presentation: 'modal',\n // Loads inside the block: it mounts only while open, so mounting is the open-time load.\n usePrepare: noop,\n },\n} as Record<string, ActionBlockEntry>\n\nexport const blocks = {\n account_block: AccountBlock,\n account_switch_block: AccountSwitchBlock,\n direct_deposit_block: DirectDepositBlock,\n bar_chart_block: BarchartBlock,\n budget_block: BudgetBlock,\n debts_block: DebtsBlock,\n donut_chart_block: DonutChartBlock,\n double_bar_chart_block: DoubleBarChartBlock,\n double_progress_bar_block: DoubleProgressBarBlock,\n image_block: ImageBlock,\n save_extra_block: SaveExtraBlock,\n savings_opportunity_block: SavingsOpportunityBlock,\n step_chart_block: StepChartBlock,\n svg_image_block: SVGImageBlock,\n upcoming_bill_block: UpcomingBillBlock,\n upcoming_subscription_block: UpcomingSubscriptionBlock,\n withdrawal_block: WithdrawalBlock,\n transaction_block: TransactionBlock,\n} as Record<string, React.ComponentType<{ payload: InsightsPayload; beatGuid?: string }>>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDA,IAAM,IAAA,CAAQ,MAAwB;AAAC,GAsB1B,KAAe;AAAA,EACzB,CAAA,EAAgB,wBAAA,GAA2B;AAAA,IAC1C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,MAAa;AAAA,EACf;AAAA,EACC,CAAA,EAAgB,0BAAA,GAA6B;AAAA,IAC5C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAO;AAAA,EACT;AAAA,EACC,CAAA,EAAgB,gCAAA,GAAmC;AAAA,IAClD,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAO;AAAA,EACT;AAAA,EACC,CAAA,EAAgB,gCAAA,GAAmC;AAAA,IAClD,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,MAAa;AAAA,EACf;AAAA,EAGC,CAAA,EAAgB,kCAAA,GAAqC;AAAA,IACpD,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,CAAQ,GAAU,MAAS,EAAK,WAAW,mBAAmB;AAAA,EAChE;AAAA,EAGC,CAAA,EAAgB,2BAAA,GAA8B;AAAA,IAC7C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,CAAQ,GAAU,MAAS,EAAK,eAAe,gBAAgB,SAAS;AAAA,EAC1E;AAAA,EAGC,CAAA,EAAgB,4BAAA,GAA+B;AAAA,IAC9C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,CAAQ,GAAU,MAAS,EAAK,MAAM,mBAAmB;AAAA,EAC3D;AAAA,EACC,CAAA,EAAgB,2BAAA,GAA8B;AAAA,IAC7C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,cAAc;AAAA,EAChB;AAAA,EACC,CAAA,EAAgB,8BAAA,GAAiC;AAAA,IAChD,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,CAAQ,GAAU,MAChB,EAAK,eAAe,oBAAoB,mCAAmC;AAAA,EAC/E;AAAA,EAGC,CAAA,EAAgB,2BAAA,GAA8B;AAAA,IAC7C,WAAW;AAAA,IACX,YAAY;AAAA,EACd;AAAA,EACC,CAAA,EAAgB,yBAAA,GAA4B;AAAA,IAC3C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,cAAc;AAAA,EAChB;AAAA,EACC,CAAA,EAAgB,6BAAA,GAAgC;AAAA,IAC/C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,CAAQ,GAAU,GAAO,MAAS,GAAM,kBAAkB,SAAS;AAAA,EACrE;AAAA,EAGC,CAAA,EAAgB,+BAAA,GAAkC;AAAA,IACjD,WAAW;AAAA,IACX,cAAc;AAAA,IAEd,YAAY;AAAA,EACd;AACF,GAEa,KAAS;AAAA,EACpB,eAAe;AAAA,EACf,sBAAsB;AAAA,EACtB,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,aAAa;AAAA,EACb,mBAAmB;AAAA,EACnB,wBAAwB;AAAA,EACxB,2BAA2B;AAAA,EAC3B,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,2BAA2B;AAAA,EAC3B,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,6BAA6B;AAAA,EAC7B,kBAAkB;AAAA,EAClB,mBAAmB;AACrB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mx-cartographer/experiences",
3
- "version": "9.6.6",
3
+ "version": "9.6.7",
4
4
  "description": "Library containing experience widgets",
5
5
  "author": "MX",
6
6
  "license": "MIT",