@mx-cartographer/experiences 9.6.2 → 9.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/core/types/Insights.d.ts +20 -0
  3. package/dist/core/types/Insights.es.js.map +1 -1
  4. package/dist/insights-v2/blocks/ComponentBlocks/SavingsOpportunityBlock/SavingsOpportunityBlock.d.ts +18 -0
  5. package/dist/insights-v2/blocks/ComponentBlocks/SavingsOpportunityBlock/SavingsOpportunityBlock.es.js +33 -0
  6. package/dist/insights-v2/blocks/ComponentBlocks/SavingsOpportunityBlock/SavingsOpportunityBlock.es.js.map +1 -0
  7. package/dist/insights-v2/blocks/ComponentBlocks/SavingsOpportunityBlock/index.d.ts +1 -0
  8. package/dist/insights-v2/blocks/ComponentBlocks/SavingsOpportunityBlock/layout.d.ts +18 -0
  9. package/dist/insights-v2/blocks/ComponentBlocks/SavingsOpportunityBlock/layout.es.js +13 -0
  10. package/dist/insights-v2/blocks/ComponentBlocks/SavingsOpportunityBlock/layout.es.js.map +1 -0
  11. package/dist/insights-v2/blocks/ComponentBlocks/UpcomingBillBlock/UpcomingBillBlock.d.ts +53 -0
  12. package/dist/insights-v2/blocks/ComponentBlocks/UpcomingBillBlock/UpcomingBillBlock.es.js +79 -0
  13. package/dist/insights-v2/blocks/ComponentBlocks/UpcomingBillBlock/UpcomingBillBlock.es.js.map +1 -0
  14. package/dist/insights-v2/blocks/ComponentBlocks/UpcomingBillBlock/index.d.ts +1 -0
  15. package/dist/insights-v2/blocks/ComponentBlocks/UpcomingBillBlock/layout.d.ts +13 -0
  16. package/dist/insights-v2/blocks/ComponentBlocks/UpcomingBillBlock/layout.es.js +6 -0
  17. package/dist/insights-v2/blocks/ComponentBlocks/UpcomingBillBlock/layout.es.js.map +1 -0
  18. package/dist/insights-v2/blocks/ComponentBlocks/UpcomingSubscriptionBlock/UpcomingSubscriptionBlock.d.ts +23 -0
  19. package/dist/insights-v2/blocks/ComponentBlocks/UpcomingSubscriptionBlock/UpcomingSubscriptionBlock.es.js +143 -0
  20. package/dist/insights-v2/blocks/ComponentBlocks/UpcomingSubscriptionBlock/UpcomingSubscriptionBlock.es.js.map +1 -0
  21. package/dist/insights-v2/blocks/ComponentBlocks/UpcomingSubscriptionBlock/index.d.ts +1 -0
  22. package/dist/insights-v2/blocks/ComponentBlocks/UpcomingSubscriptionBlock/layout.d.ts +13 -0
  23. package/dist/insights-v2/blocks/ComponentBlocks/UpcomingSubscriptionBlock/layout.es.js +6 -0
  24. package/dist/insights-v2/blocks/ComponentBlocks/UpcomingSubscriptionBlock/layout.es.js.map +1 -0
  25. package/dist/insights-v2/blocks/ComponentBlocks/index.d.ts +3 -0
  26. package/dist/insights-v2/index.es.js +92 -86
  27. package/dist/insights-v2/mappings/blocks.es.js +56 -50
  28. package/dist/insights-v2/mappings/blocks.es.js.map +1 -1
  29. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## [9.6.3] - 10-12-2026
2
+
3
+ - **ADDED** - `upcoming_bill_block`, `savings_opportunity_block` and `upcoming_subscription_block` component blocks, registered through `BlockType`, the `blocks` registry and the shared `createVariantBlock` dispatcher so a beat's `instance_slot.block` resolves to the matching content card inside `BaseLayout`. Each reuses its already-built content component (`UpcomingBillCard`, `SavingsOpportunityCard`, `SubscriptionHeroCard`) unmodified. `SavingsOpportunityBlock` ships all six Figma states (`{generic, savings, specific} × {safety_net_not_set, safety_net_set}`); `SavingsSafetyNetSet` is the only variant without a secondary CTA. `UpcomingSubscriptionBlock`'s `View Details` secondary CTA wires to the already-registered `recurring_transaction_block` drilldown via `primary_repeating_transaction_guid`. Mock payloads, beats fixtures and Storybook stories for each (WEC-1890).
4
+
1
5
  ## [9.6.2] - 10-12-2026
2
6
 
3
7
  - **CHANGED** - `AccountSwitchBlock` reads its per-variant props from a new `layout.ts` keyed by `instance_slot.variant` (`account_connect`, `account_connected`, `switch_direct_deposit`), so Switch Direct Deposit's pending state shares the block with Discovered Accounts. `account_connect` now renders the Figma blue slot gradient; unknown variants fall back to it (WEC-1891)
@@ -222,8 +222,11 @@ export declare const BlockType: {
222
222
  readonly DoubleBarChartBlock: "double_bar_chart_block";
223
223
  readonly DoubleProgressBarBlock: "double_progress_bar_block";
224
224
  readonly SaveExtraBlock: "save_extra_block";
225
+ readonly SavingsOpportunityBlock: "savings_opportunity_block";
225
226
  readonly StepChartBlock: "step_chart_block";
226
227
  readonly SVGImageBlock: "svg_image_block";
228
+ readonly UpcomingBillBlock: "upcoming_bill_block";
229
+ readonly UpcomingSubscriptionBlock: "upcoming_subscription_block";
227
230
  readonly WithdrawalBlock: "withdrawal_block";
228
231
  };
229
232
  export type BlockType = (typeof BlockType)[keyof typeof BlockType];
@@ -278,4 +281,21 @@ export interface InstanceSlot {
278
281
  status_text?: string;
279
282
  institution_guid?: string;
280
283
  institution_name?: string;
284
+ /** Dollar amount (unformatted); the block formats it as currency. */
285
+ amount?: number;
286
+ /** Merchant guid used to render the inline / hero logo via `LogoFromGuid` (`MCH-...`). */
287
+ merchant_guid?: string;
288
+ /** Merchant display name — shown as logo alt text and as the merchant/hero label. */
289
+ merchant_name?: string;
290
+ /** Due date of the projected bill in ISO form (e.g. `2025-10-30`). */
291
+ due_date?: string;
292
+ /** Caption shown above the amount, e.g. `Save an extra` or `Potential savings`. */
293
+ label?: string;
294
+ /**
295
+ * Whether to render the green gradient slot behind the coupon. Defaults to true. Backend sends
296
+ * `false` when the coupon is embedded in a parent surface that supplies its own background.
297
+ */
298
+ slot?: boolean;
299
+ /** Billing cadence word that trails the price, e.g. `month` or `year`. */
300
+ cadence?: string;
281
301
  }
@@ -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 StepChartBlock: 'step_chart_block',\n SVGImageBlock: 'svg_image_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}\n"],"mappings":"AA2RA,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 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}\n"],"mappings":"AA8RA,IAAa,IAAA,CACX,GACA,MACkB,IAAO,CAAA"}
@@ -0,0 +1,18 @@
1
+ import { InsightsPayload } from '../../../../core';
2
+ interface SavingsOpportunityBlockProps {
3
+ payload: InsightsPayload;
4
+ beatGuid?: string;
5
+ }
6
+ /**
7
+ * Savings Opportunity component block (Figma frame 1276-45997). Reads `amount`, `label`, and
8
+ * `slot` off `instance_slot` (V2 flat shape — no `instance_slot_data`), and renders the shared
9
+ * `SavingsOpportunityCard` wrapped in the standard content-section padding.
10
+ *
11
+ * Wrapped in `createVariantBlock` so an added design branch is a new registry entry rather than a
12
+ * rewrite of dispatch logic. Six variants are defined today, formed by
13
+ * `{generic, savings, specific} × {safety_net_not_set, safety_net_set}`; copy/CTA differences
14
+ * live in the payload, not here. An unknown variant degrades to the default
15
+ * (`generic_safety_net_not_set`).
16
+ */
17
+ declare const SavingsOpportunityBlock: ({ payload, beatGuid }: SavingsOpportunityBlockProps) => import("react/jsx-runtime").JSX.Element;
18
+ export default SavingsOpportunityBlock;
@@ -0,0 +1,33 @@
1
+ import { formatCurrency as m } from "../../../../core/utils/NumberFormatting.es.js";
2
+ import { createVariantBlock as p } from "../../createVariantBlock.es.js";
3
+ import l from "../../../components/SavingsOpportunityCard.es.js";
4
+ import { savingsOpportunityVariant as c } from "./layout.es.js";
5
+ import v from "@mui/material/Stack";
6
+ import { jsx as o } from "react/jsx-runtime";
7
+ var u = (r) => {
8
+ const { instance_slot: t } = r, { amount: a, label: i, slot: s } = t, e = s ?? !0;
9
+ return /* @__PURE__ */ o(v, {
10
+ sx: { px: 16 },
11
+ children: /* @__PURE__ */ o(l, {
12
+ amount: m(a ?? 0, "0,0.00"),
13
+ label: i ?? "",
14
+ slot: e
15
+ })
16
+ });
17
+ }, n = ({ payload: r }) => u(r), y = ({ payload: r, beatGuid: t }) => {
18
+ const a = r.instance_slot.variant ?? void 0;
19
+ return /* @__PURE__ */ o(f, {
20
+ beatGuid: t,
21
+ payload: r,
22
+ variant: a
23
+ });
24
+ }, f = p({
25
+ variants: Object.fromEntries(Object.values(c).map((r) => [r, n])),
26
+ fallback: n,
27
+ name: "SavingsOpportunityBlock"
28
+ });
29
+ export {
30
+ y as default
31
+ };
32
+
33
+ //# sourceMappingURL=SavingsOpportunityBlock.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SavingsOpportunityBlock.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/SavingsOpportunityBlock/SavingsOpportunityBlock.tsx"],"sourcesContent":["import Stack from '@mui/material/Stack'\n\nimport type { InsightsPayload } from '../../../../core'\nimport { formatCurrency } from '../../../../core/utils/NumberFormatting'\n\nimport SavingsOpportunityCard from '../../../components/SavingsOpportunityCard'\nimport { createVariantBlock } from '../../createVariantBlock'\n\nimport { savingsOpportunityVariant, type SavingsOpportunityVariant } from './layout'\n\ninterface SavingsOpportunityBlockProps {\n payload: InsightsPayload\n beatGuid?: string\n}\n\nconst renderCard = (payload: InsightsPayload) => {\n const { instance_slot } = payload\n const { amount, label, slot } = instance_slot\n\n // Backend-sent `slot` wins; defaults to true so a payload that omits it still shows the gradient.\n const resolvedSlot = slot ?? true\n\n return (\n <Stack sx={{ px: 16 }}>\n <SavingsOpportunityCard\n amount={formatCurrency(amount ?? 0, '0,0.00')}\n label={label ?? ''}\n slot={resolvedSlot}\n />\n </Stack>\n )\n}\n\n// All six variants ({generic, savings, specific} × {safety_net_not_set, safety_net_set}) share\n// identical card visuals — copy/CTA differences live in the payload. We register the same\n// renderer under every key so the dispatcher still fires on each known variant (and a non-\n// registered backend variant hits the fallback with the standard dev warning from createVariantBlock).\nconst SavingsOpportunityVariantCard = ({ payload }: SavingsOpportunityBlockProps) =>\n renderCard(payload)\n\n/**\n * Savings Opportunity component block (Figma frame 1276-45997). Reads `amount`, `label`, and\n * `slot` off `instance_slot` (V2 flat shape — no `instance_slot_data`), and renders the shared\n * `SavingsOpportunityCard` wrapped in the standard content-section padding.\n *\n * Wrapped in `createVariantBlock` so an added design branch is a new registry entry rather than a\n * rewrite of dispatch logic. Six variants are defined today, formed by\n * `{generic, savings, specific} × {safety_net_not_set, safety_net_set}`; copy/CTA differences\n * live in the payload, not here. An unknown variant degrades to the default\n * (`generic_safety_net_not_set`).\n */\nconst SavingsOpportunityBlock = ({ payload, beatGuid }: SavingsOpportunityBlockProps) => {\n const variant = payload.instance_slot.variant ?? undefined\n return <Variants beatGuid={beatGuid} payload={payload} variant={variant} />\n}\n\nconst Variants = createVariantBlock<SavingsOpportunityBlockProps>({\n variants: Object.fromEntries(\n Object.values(savingsOpportunityVariant).map((v) => [v, SavingsOpportunityVariantCard]),\n ) as Record<SavingsOpportunityVariant, typeof SavingsOpportunityVariantCard>,\n fallback: SavingsOpportunityVariantCard,\n name: 'SavingsOpportunityBlock',\n})\n\nexport default SavingsOpportunityBlock\n"],"mappings":";;;;;;AAeA,IAAM,IAAA,CAAc,MAA6B;AAC/C,QAAM,EAAE,eAAA,EAAA,IAAkB,GACpB,EAAE,QAAA,GAAQ,OAAA,GAAO,MAAA,EAAA,IAAS,GAG1B,IAAe,KAAQ;AAE7B,SACE,gBAAA,EAAC,GAAD;AAAA,IAAO,IAAI,EAAE,IAAI,GAAG;AAAA,IAClB,UAAA,gBAAA,EAAC,GAAD;AAAA,MACE,QAAQ,EAAe,KAAU,GAAG,QAAQ;AAAA,MAC5C,OAAO,KAAS;AAAA,MAChB,MAAM;AAAA,IACP,CAAA;AAAA,EACI,CAAA;AAEX,GAMM,IAAA,CAAiC,EAAE,SAAA,EAAA,MACvC,EAAW,CAAO,GAad,IAAA,CAA2B,EAAE,SAAA,GAAS,UAAA,EAAA,MAA6C;AACvF,QAAM,IAAU,EAAQ,cAAc,WAAW;AACjD,SAAO,gBAAA,EAAC,GAAD;AAAA,IAAoB,UAAA;AAAA,IAAmB,SAAA;AAAA,IAAkB,SAAA;AAAA,EAAU,CAAA;AAC5E,GAEM,IAAW,EAAiD;AAAA,EAChE,UAAU,OAAO,YACf,OAAO,OAAO,CAAyB,EAAE,IAAA,CAAK,MAAM,CAAC,GAAG,CAA6B,CAAC,CACxF;AAAA,EACA,UAAU;AAAA,EACV,MAAM;AACR,CAAC"}
@@ -0,0 +1 @@
1
+ export { default as SavingsOpportunityBlock } from './SavingsOpportunityBlock';
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Design branches of the Savings Opportunity component block (Figma frame 1276-45997).
3
+ *
4
+ * Six variants formed by the backend axis `{generic, savings, specific} × {safety_net_not_set,
5
+ * safety_net_set}`. All six share the same card visuals (title, subtitle, label, amount, green
6
+ * gradient slot); the differentiators live in the payload — description text, primary CTA label,
7
+ * and whether a secondary CTA is present. The slot visual is backend-controlled via the flat
8
+ * `slot` field on `instance_slot` (defaults to true), so no per-variant layout map is needed.
9
+ */
10
+ export declare const savingsOpportunityVariant: {
11
+ readonly GenericSafetyNetNotSet: "generic_safety_net_not_set";
12
+ readonly SavingsSafetyNetNotSet: "savings_safety_net_not_set";
13
+ readonly SpecificSafetyNetNotSet: "specific_safety_net_not_set";
14
+ readonly GenericSafetyNetSet: "generic_safety_net_set";
15
+ readonly SavingsSafetyNetSet: "savings_safety_net_set";
16
+ readonly SpecificSafetyNetSet: "specific_safety_net_set";
17
+ };
18
+ export type SavingsOpportunityVariant = (typeof savingsOpportunityVariant)[keyof typeof savingsOpportunityVariant];
@@ -0,0 +1,13 @@
1
+ var e = {
2
+ GenericSafetyNetNotSet: "generic_safety_net_not_set",
3
+ SavingsSafetyNetNotSet: "savings_safety_net_not_set",
4
+ SpecificSafetyNetNotSet: "specific_safety_net_not_set",
5
+ GenericSafetyNetSet: "generic_safety_net_set",
6
+ SavingsSafetyNetSet: "savings_safety_net_set",
7
+ SpecificSafetyNetSet: "specific_safety_net_set"
8
+ };
9
+ export {
10
+ e as savingsOpportunityVariant
11
+ };
12
+
13
+ //# sourceMappingURL=layout.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/SavingsOpportunityBlock/layout.ts"],"sourcesContent":["/**\n * Design branches of the Savings Opportunity component block (Figma frame 1276-45997).\n *\n * Six variants formed by the backend axis `{generic, savings, specific} × {safety_net_not_set,\n * safety_net_set}`. All six share the same card visuals (title, subtitle, label, amount, green\n * gradient slot); the differentiators live in the payload — description text, primary CTA label,\n * and whether a secondary CTA is present. The slot visual is backend-controlled via the flat\n * `slot` field on `instance_slot` (defaults to true), so no per-variant layout map is needed.\n */\nexport const savingsOpportunityVariant = {\n GenericSafetyNetNotSet: 'generic_safety_net_not_set',\n SavingsSafetyNetNotSet: 'savings_safety_net_not_set',\n SpecificSafetyNetNotSet: 'specific_safety_net_not_set',\n GenericSafetyNetSet: 'generic_safety_net_set',\n SavingsSafetyNetSet: 'savings_safety_net_set',\n SpecificSafetyNetSet: 'specific_safety_net_set',\n} as const\n\nexport type SavingsOpportunityVariant =\n (typeof savingsOpportunityVariant)[keyof typeof savingsOpportunityVariant]\n"],"mappings":"AASA,IAAa,IAA4B;AAAA,EACvC,wBAAwB;AAAA,EACxB,wBAAwB;AAAA,EACxB,yBAAyB;AAAA,EACzB,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,sBAAsB;AACxB"}
@@ -0,0 +1,53 @@
1
+ import { InsightsPayload } from '../../../../core';
2
+ import { UpcomingBillDay } from '../../../components/UpcomingBillCard';
3
+ interface UpcomingBillBlockProps {
4
+ payload: InsightsPayload;
5
+ beatGuid?: string;
6
+ }
7
+ type SevenDays = [
8
+ UpcomingBillDay,
9
+ UpcomingBillDay,
10
+ UpcomingBillDay,
11
+ UpcomingBillDay,
12
+ UpcomingBillDay,
13
+ UpcomingBillDay,
14
+ UpcomingBillDay
15
+ ];
16
+ /**
17
+ * Parse an ISO `YYYY-MM-DD` into a local-time Date, dodging the UTC-midnight parse
18
+ * that `new Date('2025-10-30')` performs (which drifts a day in negative offsets).
19
+ * Any other string shape (full ISO datetime) falls through to the native parser.
20
+ *
21
+ * Returns `null` for anything that doesn't resolve to a valid Date — including a
22
+ * `YYYY-MM-DD`-shaped string whose year/month/day segments produce `Invalid Date`
23
+ * (e.g. `'2026-13-40'`) and arbitrary strings the native parser rejects. Callers
24
+ * must handle `null` so a bad backend value cannot propagate `NaN` into the UI
25
+ * via `getDay()` and render `NaN` day numbers.
26
+ */
27
+ export declare const parseDueDate: (iso: string) => Date | null;
28
+ /**
29
+ * Build the Sun→Sat week around a due date with the due day marked `highlighted`.
30
+ * Column index is the local day-of-week (0=Sun..6=Sat) so the strip always lines up
31
+ * under the weekday labels regardless of which weekday the bill lands on.
32
+ */
33
+ export declare const buildWeekStrip: (dueDate: Date) => SevenDays;
34
+ /**
35
+ * Upcoming Bill component block (Figma: "Full | Upcoming Bill"). Reads `due_date`,
36
+ * `amount` and merchant facts off `instance_slot` (V2 flat shape — no
37
+ * `instance_slot_data`), derives the Sun→Sat week around the due date, and renders
38
+ * the shared `UpcomingBillCard`.
39
+ *
40
+ * Wrapped in `createVariantBlock` from day one so an added design branch is a new
41
+ * registry entry, not a rewrite of dispatch logic. Today only
42
+ * `projected_bill_payment` is defined; an unknown variant degrades to it.
43
+ *
44
+ * Degraded-date rendering: if `due_date` is missing or doesn't parse to a valid
45
+ * Date (e.g. `'2026-13-40'`, `''`, an unparseable arbitrary string), the card
46
+ * still renders — merchant row + amount — but with a neutral current-week strip
47
+ * (no highlighted cell). `UpcomingBillCard` requires a 7-tuple `days` prop so we
48
+ * cannot omit the strip without modifying the shared component; the "no highlighted
49
+ * cell" fallback keeps the useful info visible without pretending today is the
50
+ * due day.
51
+ */
52
+ declare const UpcomingBillBlock: ({ payload, beatGuid }: UpcomingBillBlockProps) => import("react/jsx-runtime").JSX.Element;
53
+ export default UpcomingBillBlock;
@@ -0,0 +1,79 @@
1
+ import { formatCurrency as u } from "../../../../core/utils/NumberFormatting.es.js";
2
+ import { createVariantBlock as d } from "../../createVariantBlock.es.js";
3
+ import g from "../../../components/LogoFromGuid.es.js";
4
+ import D from "../../../components/UpcomingBillCard.es.js";
5
+ import { upcomingBillVariant as p } from "./layout.es.js";
6
+ import f from "@mui/material/Stack";
7
+ import { jsx as l } from "react/jsx-runtime";
8
+ var s = [
9
+ "Sun",
10
+ "Mon",
11
+ "Tue",
12
+ "Wed",
13
+ "Thu",
14
+ "Fri",
15
+ "Sat"
16
+ ], h = (t) => {
17
+ const a = /^(\d{4})-(\d{2})-(\d{2})$/.exec(t);
18
+ if (a) {
19
+ const [, o, n, r] = a, i = new Date(Number(o), Number(n) - 1, Number(r));
20
+ return Number.isNaN(i.getTime()) ? null : i;
21
+ }
22
+ const e = new Date(t);
23
+ return Number.isNaN(e.getTime()) ? null : e;
24
+ }, v = (t) => {
25
+ const a = t.getDay(), e = new Date(t);
26
+ return e.setDate(t.getDate() - a), s.map((o, n) => {
27
+ const r = new Date(e);
28
+ r.setDate(e.getDate() + n);
29
+ const i = {
30
+ label: o,
31
+ date: String(r.getDate())
32
+ };
33
+ return n === a && (i.highlighted = !0), i;
34
+ });
35
+ }, y = () => {
36
+ const t = /* @__PURE__ */ new Date(), a = t.getDay(), e = new Date(t);
37
+ return e.setDate(t.getDate() - a), s.map((o, n) => {
38
+ const r = new Date(e);
39
+ return r.setDate(e.getDate() + n), {
40
+ label: o,
41
+ date: String(r.getDate())
42
+ };
43
+ });
44
+ }, m = ({ payload: t }) => {
45
+ const { instance_slot: a } = t, { amount: e, due_date: o, merchant_guid: n, merchant_name: r } = a, i = o ? h(o) : null, c = i ? v(i) : y();
46
+ return /* @__PURE__ */ l(f, {
47
+ sx: { px: 16 },
48
+ children: /* @__PURE__ */ l(D, {
49
+ amount: u(e ?? 0, "0,0.00"),
50
+ days: c,
51
+ logo: n ? /* @__PURE__ */ l(g, {
52
+ logo: {
53
+ alt: r ?? "",
54
+ guid: n
55
+ },
56
+ size: 24
57
+ }) : null,
58
+ merchantName: r ?? ""
59
+ })
60
+ });
61
+ }, P = ({ payload: t, beatGuid: a }) => {
62
+ const e = t.instance_slot.variant ?? void 0;
63
+ return /* @__PURE__ */ l(B, {
64
+ beatGuid: a,
65
+ payload: t,
66
+ variant: e
67
+ });
68
+ }, B = d({
69
+ variants: { [p.ProjectedBillPayment]: m },
70
+ fallback: m,
71
+ name: "UpcomingBillBlock"
72
+ });
73
+ export {
74
+ v as buildWeekStrip,
75
+ P as default,
76
+ h as parseDueDate
77
+ };
78
+
79
+ //# sourceMappingURL=UpcomingBillBlock.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UpcomingBillBlock.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/UpcomingBillBlock/UpcomingBillBlock.tsx"],"sourcesContent":["import Stack from '@mui/material/Stack'\n\nimport type { InsightsPayload } from '../../../../core'\nimport { formatCurrency } from '../../../../core/utils/NumberFormatting'\n\nimport LogoFromGuid from '../../../components/LogoFromGuid'\nimport UpcomingBillCard, { type UpcomingBillDay } from '../../../components/UpcomingBillCard'\nimport { createVariantBlock } from '../../createVariantBlock'\n\nimport { upcomingBillVariant } from './layout'\n\ninterface UpcomingBillBlockProps {\n payload: InsightsPayload\n beatGuid?: string\n}\n\nconst DAY_LABELS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] as const\ntype SevenDays = [\n UpcomingBillDay,\n UpcomingBillDay,\n UpcomingBillDay,\n UpcomingBillDay,\n UpcomingBillDay,\n UpcomingBillDay,\n UpcomingBillDay,\n]\n\n/**\n * Parse an ISO `YYYY-MM-DD` into a local-time Date, dodging the UTC-midnight parse\n * that `new Date('2025-10-30')` performs (which drifts a day in negative offsets).\n * Any other string shape (full ISO datetime) falls through to the native parser.\n *\n * Returns `null` for anything that doesn't resolve to a valid Date — including a\n * `YYYY-MM-DD`-shaped string whose year/month/day segments produce `Invalid Date`\n * (e.g. `'2026-13-40'`) and arbitrary strings the native parser rejects. Callers\n * must handle `null` so a bad backend value cannot propagate `NaN` into the UI\n * via `getDay()` and render `NaN` day numbers.\n */\nexport const parseDueDate = (iso: string): Date | null => {\n const dateOnly = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(iso)\n if (dateOnly) {\n const [, y, m, d] = dateOnly\n const parsed = new Date(Number(y), Number(m) - 1, Number(d))\n return Number.isNaN(parsed.getTime()) ? null : parsed\n }\n const parsed = new Date(iso)\n return Number.isNaN(parsed.getTime()) ? null : parsed\n}\n\n/**\n * Build the Sun→Sat week around a due date with the due day marked `highlighted`.\n * Column index is the local day-of-week (0=Sun..6=Sat) so the strip always lines up\n * under the weekday labels regardless of which weekday the bill lands on.\n */\nexport const buildWeekStrip = (dueDate: Date): SevenDays => {\n const dow = dueDate.getDay()\n const sunday = new Date(dueDate)\n sunday.setDate(dueDate.getDate() - dow)\n\n const days = DAY_LABELS.map((label, idx): UpcomingBillDay => {\n const cell = new Date(sunday)\n cell.setDate(sunday.getDate() + idx)\n const day: UpcomingBillDay = { label, date: String(cell.getDate()) }\n if (idx === dow) day.highlighted = true\n return day\n })\n\n return days as unknown as SevenDays\n}\n\n/**\n * Build the current Sun→Sat week with NO cell highlighted. Used as the degraded\n * strip when `due_date` is missing or unparseable — the card still renders\n * (merchant row with name + amount) but the strip has no \"due day\" callout.\n */\nconst buildUnhighlightedCurrentWeek = (): SevenDays => {\n const base = new Date()\n const dow = base.getDay()\n const sunday = new Date(base)\n sunday.setDate(base.getDate() - dow)\n\n const days = DAY_LABELS.map((label, idx): UpcomingBillDay => {\n const cell = new Date(sunday)\n cell.setDate(sunday.getDate() + idx)\n return { label, date: String(cell.getDate()) }\n })\n\n return days as unknown as SevenDays\n}\n\nconst ProjectedBillPaymentVariant = ({ payload }: UpcomingBillBlockProps) => {\n const { instance_slot } = payload\n const { amount, due_date, merchant_guid, merchant_name } = instance_slot\n\n // Both missing and malformed `due_date` degrade to the same \"no highlighted cell\" case —\n // we never want to silently show today's week as if it were due today. UpcomingBillCard\n // requires a 7-tuple, so we still render a neutral current-week strip so the merchant row\n // (name + amount) stays visible. Returning null would hide the whole insight for just a\n // bad date, which costs the user more information than it saves.\n const parsed = due_date ? parseDueDate(due_date) : null\n const days = parsed ? buildWeekStrip(parsed) : buildUnhighlightedCurrentWeek()\n\n return (\n <Stack sx={{ px: 16 }}>\n <UpcomingBillCard\n amount={formatCurrency(amount ?? 0, '0,0.00')}\n days={days}\n logo={\n merchant_guid ? (\n <LogoFromGuid logo={{ alt: merchant_name ?? '', guid: merchant_guid }} size={24} />\n ) : null\n }\n merchantName={merchant_name ?? ''}\n />\n </Stack>\n )\n}\n\n/**\n * Upcoming Bill component block (Figma: \"Full | Upcoming Bill\"). Reads `due_date`,\n * `amount` and merchant facts off `instance_slot` (V2 flat shape — no\n * `instance_slot_data`), derives the Sun→Sat week around the due date, and renders\n * the shared `UpcomingBillCard`.\n *\n * Wrapped in `createVariantBlock` from day one so an added design branch is a new\n * registry entry, not a rewrite of dispatch logic. Today only\n * `projected_bill_payment` is defined; an unknown variant degrades to it.\n *\n * Degraded-date rendering: if `due_date` is missing or doesn't parse to a valid\n * Date (e.g. `'2026-13-40'`, `''`, an unparseable arbitrary string), the card\n * still renders — merchant row + amount — but with a neutral current-week strip\n * (no highlighted cell). `UpcomingBillCard` requires a 7-tuple `days` prop so we\n * cannot omit the strip without modifying the shared component; the \"no highlighted\n * cell\" fallback keeps the useful info visible without pretending today is the\n * due day.\n */\nconst UpcomingBillBlock = ({ payload, beatGuid }: UpcomingBillBlockProps) => {\n const variant = payload.instance_slot.variant ?? undefined\n return <Variants beatGuid={beatGuid} payload={payload} variant={variant} />\n}\n\nconst Variants = createVariantBlock<UpcomingBillBlockProps>({\n variants: {\n [upcomingBillVariant.ProjectedBillPayment]: ProjectedBillPaymentVariant,\n },\n fallback: ProjectedBillPaymentVariant,\n name: 'UpcomingBillBlock',\n})\n\nexport default UpcomingBillBlock\n"],"mappings":";;;;;;;AAgBA,IAAM,IAAa;AAAA,EAAC;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAK,GAsBtD,IAAA,CAAgB,MAA6B;AACxD,QAAM,IAAW,4BAA4B,KAAK,CAAG;AACrD,MAAI,GAAU;AACZ,UAAM,CAAA,EAAG,GAAG,GAAG,CAAA,IAAK,GACd,IAAS,IAAI,KAAK,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC;AAC3D,WAAO,OAAO,MAAM,EAAO,QAAQ,CAAC,IAAI,OAAO;AAAA,EACjD;AACA,QAAM,IAAS,IAAI,KAAK,CAAG;AAC3B,SAAO,OAAO,MAAM,EAAO,QAAQ,CAAC,IAAI,OAAO;AACjD,GAOa,IAAA,CAAkB,MAA6B;AAC1D,QAAM,IAAM,EAAQ,OAAO,GACrB,IAAS,IAAI,KAAK,CAAO;AAC/B,SAAA,EAAO,QAAQ,EAAQ,QAAQ,IAAI,CAAG,GAEzB,EAAW,IAAA,CAAK,GAAO,MAAyB;AAC3D,UAAM,IAAO,IAAI,KAAK,CAAM;AAC5B,IAAA,EAAK,QAAQ,EAAO,QAAQ,IAAI,CAAG;AACnC,UAAM,IAAuB;AAAA,MAAE,OAAA;AAAA,MAAO,MAAM,OAAO,EAAK,QAAQ,CAAC;AAAA,IAAE;AACnE,WAAI,MAAQ,MAAK,EAAI,cAAc,KAC5B;AAAA,EACT,CAEO;AACT,GAOM,IAAA,MAAiD;AACrD,QAAM,IAAO,oBAAI,KAAK,GAChB,IAAM,EAAK,OAAO,GAClB,IAAS,IAAI,KAAK,CAAI;AAC5B,SAAA,EAAO,QAAQ,EAAK,QAAQ,IAAI,CAAG,GAEtB,EAAW,IAAA,CAAK,GAAO,MAAyB;AAC3D,UAAM,IAAO,IAAI,KAAK,CAAM;AAC5B,WAAA,EAAK,QAAQ,EAAO,QAAQ,IAAI,CAAG,GAC5B;AAAA,MAAE,OAAA;AAAA,MAAO,MAAM,OAAO,EAAK,QAAQ,CAAC;AAAA,IAAE;AAAA,EAC/C,CAEO;AACT,GAEM,IAAA,CAA+B,EAAE,SAAA,EAAA,MAAsC;AAC3E,QAAM,EAAE,eAAA,EAAA,IAAkB,GACpB,EAAE,QAAA,GAAQ,UAAA,GAAU,eAAA,GAAe,eAAA,EAAA,IAAkB,GAOrD,IAAS,IAAW,EAAa,CAAQ,IAAI,MAC7C,IAAO,IAAS,EAAe,CAAM,IAAI,EAA8B;AAE7E,SACE,gBAAA,EAAC,GAAD;AAAA,IAAO,IAAI,EAAE,IAAI,GAAG;AAAA,IAClB,UAAA,gBAAA,EAAC,GAAD;AAAA,MACE,QAAQ,EAAe,KAAU,GAAG,QAAQ;AAAA,MACtC,MAAA;AAAA,MACN,MACE,IACE,gBAAA,EAAC,GAAD;AAAA,QAAc,MAAM;AAAA,UAAE,KAAK,KAAiB;AAAA,UAAI,MAAM;AAAA,QAAc;AAAA,QAAG,MAAM;AAAA,MAAK,CAAA,IAChF;AAAA,MAEN,cAAc,KAAiB;AAAA,IAChC,CAAA;AAAA,EACI,CAAA;AAEX,GAoBM,IAAA,CAAqB,EAAE,SAAA,GAAS,UAAA,EAAA,MAAuC;AAC3E,QAAM,IAAU,EAAQ,cAAc,WAAW;AACjD,SAAO,gBAAA,EAAC,GAAD;AAAA,IAAoB,UAAA;AAAA,IAAmB,SAAA;AAAA,IAAkB,SAAA;AAAA,EAAU,CAAA;AAC5E,GAEM,IAAW,EAA2C;AAAA,EAC1D,UAAU,EAAA,CACP,EAAoB,oBAAA,GAAuB,EAC9C;AAAA,EACA,UAAU;AAAA,EACV,MAAM;AACR,CAAC"}
@@ -0,0 +1 @@
1
+ export { default as UpcomingBillBlock } from './UpcomingBillBlock';
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Design branches of the Upcoming Bill component block.
3
+ *
4
+ * - `ProjectedBillPayment` — the only variant today (Figma: "Full | Upcoming Bill"):
5
+ * week strip + merchant row + amount.
6
+ *
7
+ * Scaffolded through `createVariantBlock` so adding a future design branch is a new
8
+ * registry entry rather than editing dispatch logic.
9
+ */
10
+ export declare const upcomingBillVariant: {
11
+ readonly ProjectedBillPayment: "projected_bill_payment";
12
+ };
13
+ export type UpcomingBillVariant = (typeof upcomingBillVariant)[keyof typeof upcomingBillVariant];
@@ -0,0 +1,6 @@
1
+ var e = { ProjectedBillPayment: "projected_bill_payment" };
2
+ export {
3
+ e as upcomingBillVariant
4
+ };
5
+
6
+ //# sourceMappingURL=layout.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/UpcomingBillBlock/layout.ts"],"sourcesContent":["/**\n * Design branches of the Upcoming Bill component block.\n *\n * - `ProjectedBillPayment` — the only variant today (Figma: \"Full | Upcoming Bill\"):\n * week strip + merchant row + amount.\n *\n * Scaffolded through `createVariantBlock` so adding a future design branch is a new\n * registry entry rather than editing dispatch logic.\n */\nexport const upcomingBillVariant = {\n ProjectedBillPayment: 'projected_bill_payment',\n} as const\n\nexport type UpcomingBillVariant = (typeof upcomingBillVariant)[keyof typeof upcomingBillVariant]\n"],"mappings":"AASA,IAAa,IAAsB,EACjC,sBAAsB,yBACxB"}
@@ -0,0 +1,23 @@
1
+ import { InsightsPayload } from '../../../../core';
2
+ interface UpcomingSubscriptionBlockProps {
3
+ payload: InsightsPayload;
4
+ beatGuid?: string;
5
+ }
6
+ export declare const BACKDROP_TILES: {
7
+ size: number;
8
+ opacity: number;
9
+ left: number;
10
+ top: number;
11
+ }[];
12
+ /**
13
+ * Upcoming Subscription component block (Figma: "Full | Upcoming Subscription"). Reads
14
+ * `amount`, `cadence`, and merchant facts off `instance_slot` (V2 flat shape — no
15
+ * `instance_slot_data`) and renders the shared `SubscriptionHeroCard` with the scattered
16
+ * faded-logo backdrop.
17
+ *
18
+ * Wrapped in `createVariantBlock` from day one so an added design branch is a new registry
19
+ * entry, not a rewrite of dispatch logic. Today only `upcoming_subscription` is defined; an
20
+ * unknown variant degrades to it.
21
+ */
22
+ declare const UpcomingSubscriptionBlock: ({ payload, beatGuid }: UpcomingSubscriptionBlockProps) => import("react/jsx-runtime").JSX.Element;
23
+ export default UpcomingSubscriptionBlock;
@@ -0,0 +1,143 @@
1
+ import { formatCurrency as d } from "../../../../core/utils/NumberFormatting.es.js";
2
+ import { createVariantBlock as y } from "../../createVariantBlock.es.js";
3
+ import l from "../../../components/LogoFromGuid.es.js";
4
+ import g from "../../../components/SubscriptionHeroCard.es.js";
5
+ import { upcomingSubscriptionVariant as b } from "./layout.es.js";
6
+ import x from "@mui/material/Stack";
7
+ import { jsx as o } from "react/jsx-runtime";
8
+ import m from "@mui/material/Box";
9
+ var h = [
10
+ {
11
+ size: 51,
12
+ opacity: 0.5,
13
+ left: 6.9,
14
+ top: -13.7
15
+ },
16
+ {
17
+ size: 51,
18
+ opacity: 0.5,
19
+ left: 82.8,
20
+ top: 75.9
21
+ },
22
+ {
23
+ size: 33,
24
+ opacity: 0.35,
25
+ left: 15.9,
26
+ top: 35.7
27
+ },
28
+ {
29
+ size: 33,
30
+ opacity: 0.35,
31
+ left: -5,
32
+ top: 57.1
33
+ },
34
+ {
35
+ size: 33,
36
+ opacity: 0.35,
37
+ left: 9.3,
38
+ top: 89.8
39
+ },
40
+ {
41
+ size: 33,
42
+ opacity: 0.35,
43
+ left: 96,
44
+ top: 48.8
45
+ },
46
+ {
47
+ size: 33,
48
+ opacity: 0.35,
49
+ left: 69.7,
50
+ top: -9.3
51
+ },
52
+ {
53
+ size: 26,
54
+ opacity: 0.25,
55
+ left: 33.1,
56
+ top: 76.4
57
+ },
58
+ {
59
+ size: 26,
60
+ opacity: 0.25,
61
+ left: 0.6,
62
+ top: 24.8
63
+ },
64
+ {
65
+ size: 26,
66
+ opacity: 0.25,
67
+ left: 94.1,
68
+ top: 5.5
69
+ },
70
+ {
71
+ size: 26,
72
+ opacity: 0.25,
73
+ left: 75.4,
74
+ top: 27.5
75
+ },
76
+ {
77
+ size: 16,
78
+ opacity: 0.1,
79
+ left: 59.7,
80
+ top: 88.8
81
+ },
82
+ {
83
+ size: 16,
84
+ opacity: 0.1,
85
+ left: 72.3,
86
+ top: 57.9
87
+ }
88
+ ], f = ({ payload: i }) => {
89
+ const { instance_slot: a } = i, { amount: p, cadence: r, merchant_guid: c, merchant_name: n } = a, e = c ? {
90
+ alt: n ?? "",
91
+ guid: c
92
+ } : null, s = d(p ?? 0, "0,0.00"), u = r ? `${s} / ${r}` : s, z = e ? /* @__PURE__ */ o(m, {
93
+ "aria-hidden": !0,
94
+ "data-testid": "upcoming-subscription-backdrop",
95
+ children: h.map((t) => /* @__PURE__ */ o(m, {
96
+ sx: {
97
+ alignItems: "center",
98
+ display: "flex",
99
+ height: t.size,
100
+ justifyContent: "center",
101
+ left: `${t.left}%`,
102
+ opacity: t.opacity,
103
+ position: "absolute",
104
+ top: `${t.top}%`,
105
+ width: t.size
106
+ },
107
+ children: /* @__PURE__ */ o(l, {
108
+ logo: e,
109
+ size: t.size
110
+ })
111
+ }, `${t.size}-${t.left}-${t.top}`))
112
+ }) : null;
113
+ return /* @__PURE__ */ o(x, {
114
+ sx: { px: 16 },
115
+ children: /* @__PURE__ */ o(g, {
116
+ backdrop: z,
117
+ logo: e ? /* @__PURE__ */ o(l, {
118
+ logo: e,
119
+ size: 64
120
+ }) : null,
121
+ name: n ?? "",
122
+ price: u,
123
+ sx: { px: 0 }
124
+ })
125
+ });
126
+ }, j = ({ payload: i, beatGuid: a }) => {
127
+ const p = i.instance_slot.variant ?? void 0;
128
+ return /* @__PURE__ */ o(v, {
129
+ beatGuid: a,
130
+ payload: i,
131
+ variant: p
132
+ });
133
+ }, v = y({
134
+ variants: { [b.UpcomingSubscription]: f },
135
+ fallback: f,
136
+ name: "UpcomingSubscriptionBlock"
137
+ });
138
+ export {
139
+ h as BACKDROP_TILES,
140
+ j as default
141
+ };
142
+
143
+ //# sourceMappingURL=UpcomingSubscriptionBlock.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UpcomingSubscriptionBlock.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/UpcomingSubscriptionBlock/UpcomingSubscriptionBlock.tsx"],"sourcesContent":["import Box from '@mui/material/Box'\nimport Stack from '@mui/material/Stack'\n\nimport type { InsightsPayload } from '../../../../core'\nimport { formatCurrency } from '../../../../core/utils/NumberFormatting'\n\nimport LogoFromGuid from '../../../components/LogoFromGuid'\nimport SubscriptionHeroCard from '../../../components/SubscriptionHeroCard'\nimport { createVariantBlock } from '../../createVariantBlock'\n\nimport { upcomingSubscriptionVariant } from './layout'\n\ninterface UpcomingSubscriptionBlockProps {\n payload: InsightsPayload\n beatGuid?: string\n}\n\n// Fixed tile positions for the scattered merchant-logo backdrop. Each cell sits over the\n// 320x182-ish hero slot in CSS percentages; the card's `overflow: hidden` clips any that fall\n// partly off-frame, which matches the Figma design.\nexport const BACKDROP_TILES: { size: number; opacity: number; left: number; top: number }[] = [\n { size: 51, opacity: 0.5, left: 6.9, top: -13.7 },\n { size: 51, opacity: 0.5, left: 82.8, top: 75.9 },\n { size: 33, opacity: 0.35, left: 15.9, top: 35.7 },\n { size: 33, opacity: 0.35, left: -5.0, top: 57.1 },\n { size: 33, opacity: 0.35, left: 9.3, top: 89.8 },\n { size: 33, opacity: 0.35, left: 96.0, top: 48.8 },\n { size: 33, opacity: 0.35, left: 69.7, top: -9.3 },\n { size: 26, opacity: 0.25, left: 33.1, top: 76.4 },\n { size: 26, opacity: 0.25, left: 0.6, top: 24.8 },\n { size: 26, opacity: 0.25, left: 94.1, top: 5.5 },\n { size: 26, opacity: 0.25, left: 75.4, top: 27.5 },\n { size: 16, opacity: 0.1, left: 59.7, top: 88.8 },\n { size: 16, opacity: 0.1, left: 72.3, top: 57.9 },\n]\n\nconst UpcomingSubscriptionVariant = ({ payload }: UpcomingSubscriptionBlockProps) => {\n const { instance_slot } = payload\n const { amount, cadence, merchant_guid, merchant_name } = instance_slot\n\n const logoRef = merchant_guid ? { alt: merchant_name ?? '', guid: merchant_guid } : null\n const amountText = formatCurrency(amount ?? 0, '0,0.00')\n const price = cadence ? `${amountText} / ${cadence}` : amountText\n\n const backdrop = logoRef ? (\n // Defensive: SubscriptionHeroCard already wraps `backdrop` in an aria-hidden container, but\n // we mark the inner cluster aria-hidden too so AT skips the 13 tiles even if the shared\n // card's wrapper is refactored.\n <Box aria-hidden={true} data-testid=\"upcoming-subscription-backdrop\">\n {BACKDROP_TILES.map((t) => (\n <Box\n key={`${t.size}-${t.left}-${t.top}`}\n sx={{\n alignItems: 'center',\n display: 'flex',\n height: t.size,\n justifyContent: 'center',\n left: `${t.left}%`,\n opacity: t.opacity,\n position: 'absolute',\n top: `${t.top}%`,\n width: t.size,\n }}\n >\n <LogoFromGuid logo={logoRef} size={t.size} />\n </Box>\n ))}\n </Box>\n ) : null\n\n return (\n <Stack sx={{ px: 16 }}>\n <SubscriptionHeroCard\n backdrop={backdrop}\n logo={logoRef ? <LogoFromGuid logo={logoRef} size={64} /> : null}\n name={merchant_name ?? ''}\n price={price}\n sx={{ px: 0 }}\n />\n </Stack>\n )\n}\n\n/**\n * Upcoming Subscription component block (Figma: \"Full | Upcoming Subscription\"). Reads\n * `amount`, `cadence`, and merchant facts off `instance_slot` (V2 flat shape — no\n * `instance_slot_data`) and renders the shared `SubscriptionHeroCard` with the scattered\n * faded-logo backdrop.\n *\n * Wrapped in `createVariantBlock` from day one so an added design branch is a new registry\n * entry, not a rewrite of dispatch logic. Today only `upcoming_subscription` is defined; an\n * unknown variant degrades to it.\n */\nconst UpcomingSubscriptionBlock = ({ payload, beatGuid }: UpcomingSubscriptionBlockProps) => {\n const variant = payload.instance_slot.variant ?? undefined\n return <Variants beatGuid={beatGuid} payload={payload} variant={variant} />\n}\n\nconst Variants = createVariantBlock<UpcomingSubscriptionBlockProps>({\n variants: {\n [upcomingSubscriptionVariant.UpcomingSubscription]: UpcomingSubscriptionVariant,\n },\n fallback: UpcomingSubscriptionVariant,\n name: 'UpcomingSubscriptionBlock',\n})\n\nexport default UpcomingSubscriptionBlock\n"],"mappings":";;;;;;;;AAoBA,IAAa,IAAiF;AAAA,EAC5F;AAAA,IAAE,MAAM;AAAA,IAAI,SAAS;AAAA,IAAK,MAAM;AAAA,IAAK,KAAK;AAAA,EAAM;AAAA,EAChD;AAAA,IAAE,MAAM;AAAA,IAAI,SAAS;AAAA,IAAK,MAAM;AAAA,IAAM,KAAK;AAAA,EAAK;AAAA,EAChD;AAAA,IAAE,MAAM;AAAA,IAAI,SAAS;AAAA,IAAM,MAAM;AAAA,IAAM,KAAK;AAAA,EAAK;AAAA,EACjD;AAAA,IAAE,MAAM;AAAA,IAAI,SAAS;AAAA,IAAM,MAAM;AAAA,IAAM,KAAK;AAAA,EAAK;AAAA,EACjD;AAAA,IAAE,MAAM;AAAA,IAAI,SAAS;AAAA,IAAM,MAAM;AAAA,IAAK,KAAK;AAAA,EAAK;AAAA,EAChD;AAAA,IAAE,MAAM;AAAA,IAAI,SAAS;AAAA,IAAM,MAAM;AAAA,IAAM,KAAK;AAAA,EAAK;AAAA,EACjD;AAAA,IAAE,MAAM;AAAA,IAAI,SAAS;AAAA,IAAM,MAAM;AAAA,IAAM,KAAK;AAAA,EAAK;AAAA,EACjD;AAAA,IAAE,MAAM;AAAA,IAAI,SAAS;AAAA,IAAM,MAAM;AAAA,IAAM,KAAK;AAAA,EAAK;AAAA,EACjD;AAAA,IAAE,MAAM;AAAA,IAAI,SAAS;AAAA,IAAM,MAAM;AAAA,IAAK,KAAK;AAAA,EAAK;AAAA,EAChD;AAAA,IAAE,MAAM;AAAA,IAAI,SAAS;AAAA,IAAM,MAAM;AAAA,IAAM,KAAK;AAAA,EAAI;AAAA,EAChD;AAAA,IAAE,MAAM;AAAA,IAAI,SAAS;AAAA,IAAM,MAAM;AAAA,IAAM,KAAK;AAAA,EAAK;AAAA,EACjD;AAAA,IAAE,MAAM;AAAA,IAAI,SAAS;AAAA,IAAK,MAAM;AAAA,IAAM,KAAK;AAAA,EAAK;AAAA,EAChD;AAAA,IAAE,MAAM;AAAA,IAAI,SAAS;AAAA,IAAK,MAAM;AAAA,IAAM,KAAK;AAAA,EAAK;AAClD,GAEM,IAAA,CAA+B,EAAE,SAAA,EAAA,MAA8C;AACnF,QAAM,EAAE,eAAA,EAAA,IAAkB,GACpB,EAAE,QAAA,GAAQ,SAAA,GAAS,eAAA,GAAe,eAAA,EAAA,IAAkB,GAEpD,IAAU,IAAgB;AAAA,IAAE,KAAK,KAAiB;AAAA,IAAI,MAAM;AAAA,EAAc,IAAI,MAC9E,IAAa,EAAe,KAAU,GAAG,QAAQ,GACjD,IAAQ,IAAU,GAAG,CAAA,MAAgB,CAAA,KAAY,GAEjD,IAAW,IAIf,gBAAA,EAAC,GAAD;AAAA,IAAK,eAAa;AAAA,IAAM,eAAY;AAAA,IACjC,UAAA,EAAe,IAAA,CAAK,MACnB,gBAAA,EAAC,GAAD;AAAA,MAEE,IAAI;AAAA,QACF,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,QAAQ,EAAE;AAAA,QACV,gBAAgB;AAAA,QAChB,MAAM,GAAG,EAAE,IAAA;AAAA,QACX,SAAS,EAAE;AAAA,QACX,UAAU;AAAA,QACV,KAAK,GAAG,EAAE,GAAA;AAAA,QACV,OAAO,EAAE;AAAA,MACX;AAAA,MAEA,UAAA,gBAAA,EAAC,GAAD;AAAA,QAAc,MAAM;AAAA,QAAS,MAAM,EAAE;AAAA,MAAO,CAAA;AAAA,IACzC,GAdE,GAAG,EAAE,IAAA,IAAQ,EAAE,IAAA,IAAQ,EAAE,GAAA,EAc3B,CACN;AAAA,EACE,CAAA,IACH;AAEJ,SACE,gBAAA,EAAC,GAAD;AAAA,IAAO,IAAI,EAAE,IAAI,GAAG;AAAA,IAClB,UAAA,gBAAA,EAAC,GAAD;AAAA,MACY,UAAA;AAAA,MACV,MAAM,IAAU,gBAAA,EAAC,GAAD;AAAA,QAAc,MAAM;AAAA,QAAS,MAAM;AAAA,MAAK,CAAA,IAAI;AAAA,MAC5D,MAAM,KAAiB;AAAA,MAChB,OAAA;AAAA,MACP,IAAI,EAAE,IAAI,EAAE;AAAA,IACb,CAAA;AAAA,EACI,CAAA;AAEX,GAYM,IAAA,CAA6B,EAAE,SAAA,GAAS,UAAA,EAAA,MAA+C;AAC3F,QAAM,IAAU,EAAQ,cAAc,WAAW;AACjD,SAAO,gBAAA,EAAC,GAAD;AAAA,IAAoB,UAAA;AAAA,IAAmB,SAAA;AAAA,IAAkB,SAAA;AAAA,EAAU,CAAA;AAC5E,GAEM,IAAW,EAAmD;AAAA,EAClE,UAAU,EAAA,CACP,EAA4B,oBAAA,GAAuB,EACtD;AAAA,EACA,UAAU;AAAA,EACV,MAAM;AACR,CAAC"}
@@ -0,0 +1 @@
1
+ export { default as UpcomingSubscriptionBlock } from './UpcomingSubscriptionBlock';
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Design branches of the Upcoming Subscription component block.
3
+ *
4
+ * - `UpcomingSubscription` — the only variant today (Figma: "Full | Upcoming Subscription"):
5
+ * 64px hero merchant logo + name (h2) + price pill, over a scattered faded-logo backdrop.
6
+ *
7
+ * Scaffolded through `createVariantBlock` so adding a future design branch is a new registry entry
8
+ * rather than editing dispatch logic.
9
+ */
10
+ export declare const upcomingSubscriptionVariant: {
11
+ readonly UpcomingSubscription: "upcoming_subscription";
12
+ };
13
+ export type UpcomingSubscriptionVariant = (typeof upcomingSubscriptionVariant)[keyof typeof upcomingSubscriptionVariant];
@@ -0,0 +1,6 @@
1
+ var i = { UpcomingSubscription: "upcoming_subscription" };
2
+ export {
3
+ i as upcomingSubscriptionVariant
4
+ };
5
+
6
+ //# sourceMappingURL=layout.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/UpcomingSubscriptionBlock/layout.ts"],"sourcesContent":["/**\n * Design branches of the Upcoming Subscription component block.\n *\n * - `UpcomingSubscription` — the only variant today (Figma: \"Full | Upcoming Subscription\"):\n * 64px hero merchant logo + name (h2) + price pill, over a scattered faded-logo backdrop.\n *\n * Scaffolded through `createVariantBlock` so adding a future design branch is a new registry entry\n * rather than editing dispatch logic.\n */\nexport const upcomingSubscriptionVariant = {\n UpcomingSubscription: 'upcoming_subscription',\n} as const\n\nexport type UpcomingSubscriptionVariant =\n (typeof upcomingSubscriptionVariant)[keyof typeof upcomingSubscriptionVariant]\n"],"mappings":"AASA,IAAa,IAA8B,EACzC,sBAAsB,wBACxB"}
@@ -3,5 +3,8 @@ export * from './AccountSwitchBlock';
3
3
  export * from './DirectDepositBlock';
4
4
  export * from './BudgetBlock';
5
5
  export * from './SaveExtraBlock';
6
+ export * from './SavingsOpportunityBlock';
6
7
  export * from './TransactionBlock';
8
+ export * from './UpcomingBillBlock';
9
+ export * from './UpcomingSubscriptionBlock';
7
10
  export * from './WithdrawalBlock';
@@ -1,119 +1,125 @@
1
- import o from "./components/StatusPill.es.js";
1
+ import r from "./components/StatusPill.es.js";
2
2
  import { resolveInsightRender as m } from "./resolveInsightRender.es.js";
3
3
  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
- import { InsightOptionsMenu as s } from "./components/InsightOptionsMenu.es.js";
7
- import d, { isLogoGuid as C } from "./components/LogoFromGuid.es.js";
8
- import B from "./components/StatusBadge.es.js";
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";
9
9
  import k from "./components/CompactInsightCard.es.js";
10
10
  import h from "./components/InsightErrorCard.es.js";
11
- import { BAR_CHART_VARIANTS as A, barChartVariant as b, buildChartData as T, buildDataSeries as I } from "./blocks/ChartBlocks/BarchartBlock/utils.es.js";
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
- import { DoubleBarChartBlock as w } from "./blocks/ChartBlocks/DoubleBarChartBlock/DoubleBarChartBlock.es.js";
14
- import O from "./blocks/ChartBlocks/StepChartBlock/StepChartBlock.es.js";
15
- import P from "./blocks/ChartBlocks/DonutChartBlock/DonutChartBlock.es.js";
16
- import y from "./blocks/ChartBlocks/DoubleProgressBarBlock/DoubleProgressBarBlock.es.js";
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";
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";
19
- import N from "./blocks/ComponentBlocks/AccountSwitchBlock/AccountSwitchBlock.es.js";
20
- import U from "./components/AccountHeroCard.es.js";
19
+ import _ from "./blocks/ComponentBlocks/AccountSwitchBlock/AccountSwitchBlock.es.js";
20
+ 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
24
  import Y from "./components/SaveAnExtraCard.es.js";
25
25
  import $ from "./blocks/ComponentBlocks/SaveExtraBlock/SaveExtraBlock.es.js";
26
- import or from "./components/InsightTransactionRow.es.js";
27
- import mr from "./components/TransactionListCard.es.js";
28
- import { transactionBlockVariant as ar } from "./blocks/ComponentBlocks/TransactionBlock/layout.es.js";
29
- import { TransactionBlock as fr } from "./blocks/ComponentBlocks/TransactionBlock/TransactionBlock.es.js";
30
- import nr from "./components/WithdrawalCard.es.js";
31
- import sr from "./blocks/ComponentBlocks/WithdrawalBlock/WithdrawalBlock.es.js";
32
- import { SVGImageBlock as dr } from "./blocks/ImageBlocks/SVGImageBlock/SVGImageBlock.es.js";
33
- import gr from "./components/ConnectionDetailDrillDown.es.js";
34
- import ur from "./components/AmountPill.es.js";
35
- import Sr from "./components/DesignateEmergencySavingsCard.es.js";
36
- import Dr from "./components/shared/StatusSnackbar.es.js";
37
- import br from "./components/FeedbackDialog.es.js";
38
- import Ir from "./components/FeedbackModal.es.js";
39
- import vr from "./components/SurveyModal.es.js";
40
- import { ErrorCard as wr } from "./components/ErrorCard.es.js";
41
- import { HOST_ACTIONS as Or } from "./ctaActions/hostActions.es.js";
42
- import { useBeatCtaActions as Pr, useCtaHandler as Rr } from "./ctaActions/useCtaAction.es.js";
43
- import { FeedbackBar as Fr } from "./components/FeedbackBar.es.js";
44
- import { DismissInsightDialog as xr } from "./components/DismissInsightDialog.es.js";
45
- import { HiddenConfirmationCard as _r } from "./components/HiddenConfirmationCard.es.js";
46
- import { LoadingCard as Wr } from "./components/LoadingCard.es.js";
47
- import { ObsolesceBanner as jr } from "./components/ObsolesceBanner.es.js";
48
- import zr from "./components/BaseLayout.es.js";
49
- import Kr from "./components/StatusMessageCard.es.js";
50
- import Xr from "./components/LogoTile.es.js";
51
- import Zr from "./components/LogoClusterCard.es.js";
52
- import ro from "./components/MerchantHighlightCard.es.js";
53
- import to from "./components/P2PLogoStack.es.js";
54
- import io from "./components/SavingsOpportunityCard.es.js";
55
- import po from "./components/SubscriptionHeroCard.es.js";
56
- import eo from "./components/UpcomingBillCard.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";
57
60
  export {
58
61
  V as AccountBlock,
59
- U as AccountHeroCard,
60
- N as AccountSwitchBlock,
61
- ur as AmountPill,
62
- A as BAR_CHART_VARIANTS,
62
+ W as AccountHeroCard,
63
+ _ as AccountSwitchBlock,
64
+ ko as AmountPill,
65
+ b as BAR_CHART_VARIANTS,
63
66
  f as BadgedTile,
64
67
  v as BarchartBlock,
65
- zr as BaseLayout,
68
+ ar as BaseLayout,
66
69
  Q as BudgetBlock,
67
70
  k as CompactInsightCard,
68
- gr as ConnectionDetailDrillDown,
69
- Sr as DesignateEmergencySavingsCard,
71
+ wo as ConnectionDetailDrillDown,
72
+ yo as DesignateEmergencySavingsCard,
70
73
  J as DirectDepositBlock,
71
74
  q as DirectDepositCard,
72
- xr as DismissInsightDialog,
73
- P as DonutChartBlock,
74
- w as DoubleBarChartBlock,
75
- y as DoubleProgressBarBlock,
76
- wr as ErrorCard,
77
- Fr as FeedbackBar,
78
- br as FeedbackDialog,
79
- Ir as FeedbackModal,
80
- Or as HOST_ACTIONS,
81
- _r as HiddenConfirmationCard,
75
+ Yo as DismissInsightDialog,
76
+ E as DonutChartBlock,
77
+ O as DoubleBarChartBlock,
78
+ 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,
82
85
  h as InsightErrorCard,
83
- s as InsightOptionsMenu,
84
- or as InsightTransactionRow,
85
- Wr as LoadingCard,
86
- Zr as LogoClusterCard,
86
+ l as InsightOptionsMenu,
87
+ ao as InsightTransactionRow,
88
+ rr as LoadingCard,
89
+ lr as LogoClusterCard,
87
90
  d as LogoFromGuid,
88
- Xr as LogoTile,
89
- ro as MerchantHighlightCard,
90
- jr as ObsolesceBanner,
91
+ nr as LogoTile,
92
+ dr as MerchantHighlightCard,
93
+ mr as ObsolesceBanner,
91
94
  n as OverflowMenu,
92
- to as P2PLogoStack,
93
- dr as SVGImageBlock,
95
+ Br as P2PLogoStack,
96
+ Ho as SVGImageBlock,
94
97
  Y as SaveAnExtraCard,
95
98
  $ as SaveExtraBlock,
96
- io as SavingsOpportunityCard,
97
- B as StatusBadge,
98
- Kr as StatusMessageCard,
99
- o as StatusPill,
100
- Dr as StatusSnackbar,
101
- O as StepChartBlock,
102
- po as SubscriptionHeroCard,
103
- vr as SurveyModal,
104
- fr as TransactionBlock,
105
- mr as TransactionListCard,
99
+ mo as SavingsOpportunityBlock,
100
+ ro as SavingsOpportunityCard,
101
+ C as StatusBadge,
102
+ fr as StatusMessageCard,
103
+ 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,
106
110
  G as TransferLogoCard,
107
- eo as UpcomingBillCard,
108
- sr as WithdrawalBlock,
109
- nr as WithdrawalCard,
110
- b as barChartVariant,
111
+ Co as UpcomingBillBlock,
112
+ go as UpcomingBillCard,
113
+ bo as UpcomingSubscriptionBlock,
114
+ Lo as WithdrawalBlock,
115
+ To as WithdrawalCard,
116
+ A as barChartVariant,
111
117
  T as buildChartData,
112
118
  I as buildDataSeries,
113
- C as isLogoGuid,
119
+ g as isLogoGuid,
114
120
  m as resolveInsightRender,
115
- ar as transactionBlockVariant,
121
+ no as transactionBlockVariant,
116
122
  a as useBeatActions,
117
- Pr as useBeatCtaActions,
118
- Rr as useCtaHandler
123
+ zo as useBeatCtaActions,
124
+ Jo as useCtaHandler
119
125
  };
@@ -2,65 +2,68 @@ import { ContactSupportActionBlock as c } from "../actionBlocks/ContactSupportAc
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";
5
- import _ from "../blocks/ChartBlocks/StepChartBlock/StepChartBlock.es.js";
6
- import p from "../blocks/ChartBlocks/DonutChartBlock/DonutChartBlock.es.js";
5
+ import p from "../blocks/ChartBlocks/StepChartBlock/StepChartBlock.es.js";
6
+ import _ from "../blocks/ChartBlocks/DonutChartBlock/DonutChartBlock.es.js";
7
7
  import s from "../blocks/ChartBlocks/DoubleProgressBarBlock/DoubleProgressBarBlock.es.js";
8
8
  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
12
  import A from "../blocks/ComponentBlocks/SaveExtraBlock/SaveExtraBlock.es.js";
13
+ import u from "../blocks/ComponentBlocks/SavingsOpportunityBlock/SavingsOpportunityBlock.es.js";
13
14
  import { TransactionBlock as O } from "../blocks/ComponentBlocks/TransactionBlock/TransactionBlock.es.js";
14
- import f from "../blocks/ComponentBlocks/WithdrawalBlock/WithdrawalBlock.es.js";
15
- import u from "../blocks/ImageBlocks/ImageBlock.es.js";
16
- import { SVGImageBlock as N } from "../blocks/ImageBlocks/SVGImageBlock/SVGImageBlock.es.js";
17
- import { FeedbackModalActionBlock as I } from "../actionBlocks/FeedbackModalActionBlock.es.js";
18
- import { ConnectionDetailActionBlock as d } from "../actionBlocks/ConnectionDetailActionBlock.es.js";
19
- import { ConnectWidgetActionBlock as b } from "../actionBlocks/ConnectWidgetActionBlock.es.js";
20
- import { SurveyModalActionBlock as L } from "../actionBlocks/SurveyModalActionBlock.es.js";
21
- import { PlaceholderActionBlock as D } from "../actionBlocks/PlaceholderActionBlock.es.js";
22
- import { getMakeTransferDrawerTitle as P } from "../actionBlocks/MakeTransferActionBlock/layout.es.js";
23
- import { MakeTransferActionBlockLayer as g } from "../actionBlocks/MakeTransferActionBlock/MakeTransferActionBlockLayer.es.js";
24
- import { getDrawerHeaderTitle as h } from "../actionBlocks/TransactionHistoryBlock/utils.es.js";
25
- import { TransactionDetailsBlock as R } from "../actionBlocks/TransactionDetailsBlock/TransactionDetailsBlock.es.js";
26
- import { useTransactionDetailsPrepare as a } from "../actionBlocks/TransactionDetailsBlock/useTransactionDetailsPrepare.es.js";
27
- import { TransactionHistoryBlock as S } from "../actionBlocks/TransactionHistoryBlock/TransactionHistoryBlock.es.js";
28
- import { useRecurringTransactionPrepare as i } from "../actionBlocks/RecurringTransactionBlock/useRecurringTransactionPrepare.es.js";
29
- import { RecurringTransactionBlock as K } from "../actionBlocks/RecurringTransactionBlock/RecurringTransactionBlock.es.js";
30
- import { TransactionListBlock as E } from "../actionBlocks/TransactionListBlock/TransactionListBlock.es.js";
31
- import { RemainingCashBlock as v } from "../actionBlocks/RemainingCashBlock/RemainingCashBlock.es.js";
32
- import { hasDrawerBlock as ko } from "./hasDrawerBlock.es.js";
33
- import { AmountInputModalBlock as M } from "../actionBlocks/AmountInputModalBlock/AmountInputModalBlock.es.js";
15
+ import f from "../blocks/ComponentBlocks/UpcomingBillBlock/UpcomingBillBlock.es.js";
16
+ 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";
29
+ import { useTransactionDetailsPrepare as i } from "../actionBlocks/TransactionDetailsBlock/useTransactionDetailsPrepare.es.js";
30
+ import { TransactionHistoryBlock as v } from "../actionBlocks/TransactionHistoryBlock/TransactionHistoryBlock.es.js";
31
+ 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";
34
37
  var r = (e) => {
35
- }, To = {
38
+ }, bo = {
36
39
  [o.PLACEHOLDER_ACTION_BLOCK]: {
37
- Component: D,
40
+ Component: h,
38
41
  usePrepare: r,
39
42
  title: () => "Action Block Layer Drilldown"
40
43
  },
41
44
  [o.MAKE_TRANSFER_ACTION_BLOCK]: {
42
- Component: g,
45
+ Component: R,
43
46
  usePrepare: r,
44
- title: P
47
+ title: S
45
48
  },
46
49
  [o.TRANSCATION_HISTORY_ACTION_BLOCK]: {
47
- Component: S,
50
+ Component: v,
48
51
  usePrepare: r,
49
- title: h
52
+ title: K
50
53
  },
51
54
  [o.TRANSACTION_DETAILS_ACTION_BLOCK]: {
52
- Component: R,
53
- usePrepare: a,
55
+ Component: E,
56
+ usePrepare: i,
54
57
  title: () => "Transaction Details"
55
58
  },
56
59
  [o.RECURRING_TRANSACTION_ACTION_BLOCK]: {
57
- Component: K,
58
- usePrepare: i,
60
+ Component: M,
61
+ usePrepare: a,
59
62
  title: (e, t) => t.recurring?.expense_details ?? ""
60
63
  },
61
64
  [o.REMAINING_CASH_ACTION_BLOCK]: {
62
- Component: v,
63
- usePrepare: i,
65
+ Component: y,
66
+ usePrepare: a,
64
67
  title: (e, t) => t.insights_feed?.remaining_cash?.title ?? ""
65
68
  },
66
69
  [o.CONTACT_SUPPORT_ACTION_BLOCK]: {
@@ -69,54 +72,57 @@ var r = (e) => {
69
72
  title: (e, t) => t.help?.request_support ?? ""
70
73
  },
71
74
  [o.FEEDBACK_MODAL_ACTION_BLOCK]: {
72
- Component: I,
75
+ Component: g,
73
76
  usePrepare: r,
74
77
  presentation: "modal"
75
78
  },
76
79
  [o.CONNECTION_DETAIL_ACTION_BLOCK]: {
77
- Component: d,
80
+ Component: L,
78
81
  usePrepare: r,
79
82
  title: (e, t) => t.insights_feed?.connection_details?.connection_details_drawer_title ?? ""
80
83
  },
81
84
  [o.CONNECT_WIDGET_ACTION_BLOCK]: {
82
- Component: b,
85
+ Component: D,
83
86
  usePrepare: r
84
87
  },
85
88
  [o.SURVEY_MODAL_ACTION_BLOCK]: {
86
- Component: L,
89
+ Component: P,
87
90
  usePrepare: r,
88
91
  presentation: "modal"
89
92
  },
90
93
  [o.TRANSACTION_LIST_ACTION_BLOCK]: {
91
- Component: E,
92
- usePrepare: a,
94
+ Component: w,
95
+ usePrepare: i,
93
96
  title: (e, t, n) => n?.insights_payload?.title ?? ""
94
97
  },
95
98
  [o.AMOUNT_INPUT_MODAL_ACTION_BLOCK]: {
96
- Component: M,
99
+ Component: U,
97
100
  presentation: "modal",
98
101
  usePrepare: r
99
102
  }
100
- }, Ao = {
103
+ }, Io = {
101
104
  account_block: C,
102
105
  account_switch_block: k,
103
106
  direct_deposit_block: B,
104
107
  bar_chart_block: m,
105
108
  budget_block: T,
106
- donut_chart_block: p,
109
+ donut_chart_block: _,
107
110
  double_bar_chart_block: l,
108
111
  double_progress_bar_block: s,
109
- image_block: u,
112
+ image_block: I,
110
113
  save_extra_block: A,
111
- step_chart_block: _,
112
- svg_image_block: N,
113
- withdrawal_block: f,
114
+ savings_opportunity_block: u,
115
+ step_chart_block: p,
116
+ svg_image_block: d,
117
+ upcoming_bill_block: f,
118
+ upcoming_subscription_block: N,
119
+ withdrawal_block: b,
114
120
  transaction_block: O
115
121
  };
116
122
  export {
117
- To as actionBlocks,
118
- Ao as blocks,
119
- ko as hasDrawerBlock
123
+ bo as actionBlocks,
124
+ Io as blocks,
125
+ fo as hasDrawerBlock
120
126
  };
121
127
 
122
128
  //# 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 SVGImageBlock,\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 step_chart_block: StepChartBlock,\n svg_image_block: SVGImageBlock,\n withdrawal_block: WithdrawalBlock,\n transaction_block: TransactionBlock,\n} as Record<string, React.ComponentType<{ payload: InsightsPayload; beatGuid?: string }>>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,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,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,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 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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mx-cartographer/experiences",
3
- "version": "9.6.2",
3
+ "version": "9.6.4",
4
4
  "description": "Library containing experience widgets",
5
5
  "author": "MX",
6
6
  "license": "MIT",