@mx-cartographer/experiences 9.7.98 → 9.7.99-alpha-ram-cs-1

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 (40) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/core/types/Insights.d.ts +26 -119
  3. package/dist/core/types/Insights.es.js.map +1 -1
  4. package/dist/insights-v2/actionBlocks/AmountInputModalBlock/AmountInputModalBlock.d.ts +2 -7
  5. package/dist/insights-v2/actionBlocks/AmountInputModalBlock/AmountInputModalBlock.es.js +79 -72
  6. package/dist/insights-v2/actionBlocks/AmountInputModalBlock/AmountInputModalBlock.es.js.map +1 -1
  7. package/dist/insights-v2/actionBlocks/AmountInputModalBlock/CreateBudgetDialog.d.ts +5 -0
  8. package/dist/insights-v2/actionBlocks/AmountInputModalBlock/CreateBudgetDialog.es.js +61 -0
  9. package/dist/insights-v2/actionBlocks/AmountInputModalBlock/CreateBudgetDialog.es.js.map +1 -0
  10. package/dist/insights-v2/actionBlocks/AmountInputModalBlock/layout.d.ts +2 -6
  11. package/dist/insights-v2/actionBlocks/AmountInputModalBlock/layout.es.js +13 -12
  12. package/dist/insights-v2/actionBlocks/AmountInputModalBlock/layout.es.js.map +1 -1
  13. package/dist/insights-v2/actionBlocks/BudgetDetailsBlock/BudgetDetailsBlock.es.js +166 -113
  14. package/dist/insights-v2/actionBlocks/BudgetDetailsBlock/BudgetDetailsBlock.es.js.map +1 -1
  15. package/dist/insights-v2/actionBlocks/BudgetDetailsBlock/BudgetSummary.es.js +4 -4
  16. package/dist/insights-v2/actionBlocks/BudgetDetailsBlock/layout.d.ts +5 -1
  17. package/dist/insights-v2/actionBlocks/BudgetDetailsBlock/layout.es.js +39 -26
  18. package/dist/insights-v2/actionBlocks/BudgetDetailsBlock/layout.es.js.map +1 -1
  19. package/dist/insights-v2/actionBlocks/TransactionHistoryBlock/TransactionDrillDown.es.js +42 -55
  20. package/dist/insights-v2/actionBlocks/TransactionHistoryBlock/TransactionDrillDown.es.js.map +1 -1
  21. package/dist/insights-v2/actionBlocks/TransactionListBlock/layout.d.ts +8 -6
  22. package/dist/insights-v2/actionBlocks/TransactionListBlock/layout.es.js +23 -17
  23. package/dist/insights-v2/actionBlocks/TransactionListBlock/layout.es.js.map +1 -1
  24. package/dist/insights-v2/actionBlocks/util.d.ts +2 -11
  25. package/dist/insights-v2/actionBlocks/util.es.js +14 -7
  26. package/dist/insights-v2/actionBlocks/util.es.js.map +1 -1
  27. package/dist/insights-v2/analytics/analyticsEventsConfig.d.ts +16 -0
  28. package/dist/insights-v2/analytics/analyticsEventsConfig.es.js +19 -2
  29. package/dist/insights-v2/analytics/analyticsEventsConfig.es.js.map +1 -1
  30. package/dist/insights-v2/blocks/ChartBlocks/BarchartBlock/BarchartBlock.es.js +30 -29
  31. package/dist/insights-v2/blocks/ChartBlocks/BarchartBlock/BarchartBlock.es.js.map +1 -1
  32. package/dist/insights-v2/blocks/ChartBlocks/BarchartBlock/layout.d.ts +1 -0
  33. package/dist/insights-v2/blocks/ChartBlocks/BarchartBlock/layout.es.js +4 -3
  34. package/dist/insights-v2/blocks/ChartBlocks/BarchartBlock/layout.es.js.map +1 -1
  35. package/dist/insights-v2/components/ExportCsvButton.d.ts +9 -0
  36. package/dist/insights-v2/components/ExportCsvButton.es.js +25 -0
  37. package/dist/insights-v2/components/ExportCsvButton.es.js.map +1 -0
  38. package/dist/insights-v2/mappings/blocks.es.js +151 -146
  39. package/dist/insights-v2/mappings/blocks.es.js.map +1 -1
  40. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## [9.7.100] - 11-04-2026
2
+
3
+ - **ADDED** - Category Spending on Insights 2.0: Create a Budget modal, Budget Details month view with Export CSV, Try Again on failed budget changes, budget analytics, and bar clicks that open Spending History in every state (WEC-2215)
4
+
5
+ ## [9.7.99] - 11-04-2026
6
+
7
+ - **CHANGED** - The `transaction_list_block` drilldown title is driven by the CTA variant (via a variant-to-title map): the `generic_list` variant drawer is titled "Transactions" (`copy.transactions.transactions_title`), while `summary_header`, `standard` and variant-less drawers keep the beat's own title. Weekly New Merchants V3's drawer (CTA variant `generic_list`) now reads "Transactions" instead of the card's "Purchases for Review" (WEC-2189)
8
+
1
9
  ## [9.7.98] - 11-04-2026
2
10
 
3
11
  - **FIXED** - Celebrate Credit Card Payoff card spacing matches Figma (WEC-2170)
@@ -4,59 +4,37 @@ export interface ThemedSVGImageProps {
4
4
  image: React.ComponentType<React.SVGProps<SVGSVGElement>>;
5
5
  isMini?: boolean;
6
6
  }
7
- /**
8
- * Emitted by a block when the user drills into a specific datum (e.g. clicks a
9
- * chart bar). Named fields rather than positional args so blocks with differing
10
- * shapes can extend this without the call sites transposing values.
11
- */
7
+ /** Emitted when the user drills into a datum (e.g. a chart bar click). */
12
8
  export interface DrilldownPayload {
13
9
  chartBarIndex: number;
14
10
  tabIndex?: number;
15
11
  transaction_guid?: string;
16
12
  block?: string;
13
+ /** Drawer variant the bar names itself, used when no CTA names its block. */
14
+ variant?: string;
17
15
  }
18
- /**
19
- * Which envelope a beat was fetched with. `embedded` (the transaction-row pill + details-drawer
20
- * card) and `notification` are V2 additions; a surface asks for one with `widget_type=` on the fetch.
21
- */
16
+ /** The envelope a beat was fetched with; a surface asks with `widget_type=`. */
22
17
  export type WidgetType = 'full' | 'mini' | 'micro' | 'embedded' | 'notification';
23
- /**
24
- * V2: the transaction-row tag, its own small section of the `embedded` envelope (the same grammar
25
- * as `description` / `footer`, with room for a tone or an icon later). Omitted for an insight that
26
- * tags no transaction row. It deliberately is *not* `short_title`, which stays a per-variant
27
- * attribute with a second consumer (the bank-holiday sub-header).
28
- */
18
+ /** V2: the transaction-row tag, from the `embedded` envelope. Not `short_title`. */
29
19
  export interface Pill {
30
20
  text: string;
31
21
  }
32
22
  /**
33
- * V2: facts a drilldown shows that the card does not. On the payload: what every CTA of the card
34
- * shares (e.g. the account number for the Transaction Details drawer, or the guid list a list drawer
35
- * shows, `transaction_guids`). On a CTA: the figures that CTA's own drilldown renders (the Transaction
36
- * List summary header's `amount`, `start_date` / `end_date` and `count`, see `readSummary`). Scalars
37
- * or string lists, omitted when the insight has none. Never carries copy or user actions (memo,
38
- * tags, hide, flag come from the transaction store). Values come from the server, so a reader still
39
- * checks each value's runtime shape.
23
+ * V2: facts a drilldown shows that the card doesn't (scalars or string lists, never copy).
24
+ * Server values, so readers still check each value's shape.
40
25
  */
41
26
  export type DrilldownData = Record<string, string | number | boolean | null | string[]>;
42
27
  export interface InsightsPayload {
43
28
  widget_type: WidgetType;
44
29
  instance_slot: InstanceSlot;
45
- /**
46
- * V1 only. The v2 contract carries everything a block needs on `instance_slot.data`,
47
- * and omits this key entirely (see the LargeTransactionV2 payload). Blocks that still require it
48
- * get it as a required field through `BlockProps`, which re-declares it.
49
- */
30
+ /** V1 only; V2 sends `instance_slot.data` instead. */
50
31
  instance_slot_data?: InsightsInstanceSlotData;
51
32
  description: Description;
52
33
  primary_cta?: PrimaryCTA;
53
34
  secondary_cta?: SecondaryCTA;
54
35
  title?: string;
55
36
  sub_title?: Subtitle;
56
- /**
57
- * V2 rename of `sub_title`: a flat string, with the logo promoted to the payload-level `logo`
58
- * field below. `sub_title` wins when both are present.
59
- */
37
+ /** V2 rename of `sub_title`; `sub_title` wins when both are present. */
60
38
  subtitle?: string;
61
39
  /** V2: header logo paired with the flat `subtitle`: an entity guid or a status icon (`LogoRef`). */
62
40
  logo?: LogoRef;
@@ -64,17 +42,10 @@ export interface InsightsPayload {
64
42
  variant?: string;
65
43
  /** V2, `embedded` envelope only: the transaction-row pill. */
66
44
  pill?: Pill;
67
- /**
68
- * V2: drilldown-only facts, e.g. `{ account_number: 'XXXXXXXX043' }`, or the guid list a list
69
- * drawer shows (`{ transaction_guids: [...] }`).
70
- */
45
+ /** V2: drilldown-only facts, e.g. `{ account_number }` or `{ transaction_guids }`. */
71
46
  drilldown_data?: DrilldownData;
72
47
  footer?: Footer;
73
- /**
74
- * V2: the link inside the description: on the full card a drawer of its own (Low Account
75
- * Balance's "Transactions ›"); on mini and micro the card's action, sent instead of `primary_cta`.
76
- * Absent when the beat has no link.
77
- */
48
+ /** V2: the description link; on mini and micro it's the card's action. */
78
49
  in_description_cta?: InDescriptionCTA;
79
50
  guid: string;
80
51
  user_guid: string;
@@ -100,19 +71,12 @@ export interface InsightsPayload {
100
71
  is_sampled?: boolean;
101
72
  is_zero_state?: boolean;
102
73
  status?: string | null;
103
- /**
104
- * V2 (LargeTransactionV2 onward): the entities the beat is about, carried on the payload so
105
- * action blocks do not have to reach back out to the beat envelope.
106
- */
74
+ /** V2: the entities the beat is about, so action blocks needn't read the beat. */
107
75
  primary_account_guid?: string | null;
108
76
  primary_transaction_guid?: string | null;
109
77
  primary_category_guid?: string | null;
110
78
  primary_merchant_guid?: string | null;
111
- /**
112
- * V2: the repeating transaction a subscription beat is about (Upcoming Subscription, Subscription
113
- * Price Increase). Read by `recurring_transaction_block`, see
114
- * `actionBlocks/RecurringTransactionBlock/subscriptionBeats.ts`.
115
- */
79
+ /** V2: the subscription beat's repeating transaction (read by `recurring_transaction_block`). */
116
80
  primary_repeating_transaction_guid?: string | null;
117
81
  }
118
82
  export interface Legends {
@@ -139,19 +103,8 @@ export interface Subtitle {
139
103
  text: string;
140
104
  }
141
105
  /**
142
- * A V2 logo, shared by the header (`InsightsPayload.logo`) and every instance-slot row. It takes
143
- * one of two shapes:
144
- *
145
- * - **Entity**: `guid`, whose prefix (`INS-` / `MCH-` / `CAT-`) picks the logo component, plus an
146
- * optional `fallback_guid` for when that component's asset cannot load. Today that is the
147
- * category behind an `MCH-` guid, which `MerchantLogo` shows as a tile when the merchant image
148
- * is missing.
149
- * - **Status icon**: `icon` (an mx-icons name, e.g. `warning`) and `color` (a theme palette path,
150
- * e.g. `error.main`), for subheaders that show a state rather than an entity (V1's
151
- * `logo_name` / `logo_color`).
152
- *
153
- * `alt` is the accessible name for either shape. A logo sends one shape; if it sends both, `icon`
154
- * wins, as `logo_name` does in V1's `SubHeader`.
106
+ * A V2 logo: an entity `guid` (`INS-`/`MCH-`/`CAT-`, optional `fallback_guid`) or a status
107
+ * `icon` + `color`. `alt` names either; `icon` wins if both are sent.
155
108
  */
156
109
  export interface LogoRef {
157
110
  alt?: string;
@@ -176,13 +129,7 @@ export interface Description {
176
129
  text: string;
177
130
  html_text: string;
178
131
  }
179
- /**
180
- * Post message a CTA press sends to the host, resolved by the backend for the beat's current
181
- * state. Absent/null = the backend has not described one: the frontend uses the template's
182
- * interim `ctaPostMessages` entry if there is one, else sends no message. `payload` carries only
183
- * beat-specific extras; the frontend always adds `beat_guid`, `beat_template`, `user_guid` and
184
- * `action_string`.
185
- */
132
+ /** Post message a CTA press sends to the host; absent means use `ctaPostMessages` or send none. */
186
133
  export interface CtaPostMessageMetadata {
187
134
  /** Post message event; defaults to `beat/cta`. */
188
135
  event?: string | null;
@@ -195,11 +142,7 @@ export interface PrimaryCTA {
195
142
  label: string;
196
143
  block: string;
197
144
  variant?: string | null;
198
- /**
199
- * What pressing the CTA does beyond opening its block, named by the backend (ditto
200
- * `primary_cta_action`, passed through by tupac). Looked up in `insights-v2/ctaActions`;
201
- * null / absent / unknown means the CTA only opens its block or posts its message.
202
- */
145
+ /** Backend-named behaviour beyond opening `block` (see `ctaActions`); absent means just open it. */
203
146
  action_key?: string | null;
204
147
  metadata?: CtaPostMessageMetadata | null;
205
148
  /** Figures this CTA's drilldown renders (e.g. a summary header's amount/dates/count). */
@@ -207,10 +150,7 @@ export interface PrimaryCTA {
207
150
  }
208
151
  export interface SecondaryCTA {
209
152
  label: string;
210
- /**
211
- * Drawer block to open. `null` when the CTA opens nothing (ditto `secondary_cta_block: null`,
212
- * e.g. Fee Detected's "Contact Support"): the press posts its message to the host instead.
213
- */
153
+ /** Drawer block to open; `null` means the press only posts its message. */
214
154
  block: string | null;
215
155
  variant?: string | null;
216
156
  /** See `PrimaryCTA.action_key` (ditto `secondary_cta_action`). */
@@ -219,11 +159,7 @@ export interface SecondaryCTA {
219
159
  /** Figures this CTA's drilldown renders (e.g. a summary header's amount/dates/count). */
220
160
  drilldown_data?: DrilldownData;
221
161
  }
222
- /**
223
- * The description link: its label, the action block it opens and, like a CTA's, the variant that
224
- * tells that block what to show (ditto's `in_description_cta_variant`, e.g. `low_balance`). On mini
225
- * and micro it words the card's action; `block` is empty when that action opens no drawer.
226
- */
162
+ /** The description link: label, the block it opens and that block's variant. */
227
163
  export interface InDescriptionCTA {
228
164
  label: string;
229
165
  block?: string;
@@ -239,17 +175,9 @@ export interface InDescriptionCTA {
239
175
  export interface Footer {
240
176
  /** V1: a pre-formatted date string. */
241
177
  date?: string;
242
- /**
243
- * The account label, on both V1 and V2. The backend resolves the plurality: one account sends
244
- * its name (e.g. `Epic Bank`), several send a localized count (e.g. `2 Accounts`), none sends
245
- * `null` (tupac's `footer_account_label` returns nil for a beat with no accounts, as Payday Cash
246
- * Left Over Status does). There is deliberately no separate `accounts` key.
247
- */
178
+ /** Account label as sent: a name, a localized "N Accounts", or `null`. */
248
179
  account?: string | null;
249
- /**
250
- * V2 (LargeTransactionV2 onward): unix seconds, formatted by `Footer` for display.
251
- * Replaces `date`; `date` wins when a beat somehow sends both.
252
- */
180
+ /** V2: unix seconds, formatted by `Footer`; `date` wins if both are sent. */
253
181
  timestamp?: number;
254
182
  }
255
183
  export declare const BlockType: {
@@ -277,43 +205,22 @@ export declare const BlockType: {
277
205
  readonly WithdrawalBlock: "withdrawal_block";
278
206
  };
279
207
  export type BlockType = (typeof BlockType)[keyof typeof BlockType];
280
- /**
281
- * A pre-localized row on a V2 instance slot. The backend resolves the copy and formatting; the
282
- * logo is a `LogoRef` (an entity guid or a status icon, see `logoFromRef`).
283
- */
208
+ /** A pre-localized V2 slot row; the logo is a `LogoRef`. */
284
209
  export interface InstanceSlotRow {
285
210
  amount?: number;
286
211
  logo?: LogoRef;
287
212
  primary_text?: string;
288
213
  secondary_text?: string;
289
214
  }
290
- /**
291
- * V2: the slots a block's variant filled, keyed by slot name; ditto owns the names and omits any
292
- * slot it has no value for (`lib/ditto/blocks/<block>.yml`). Read with `slot()`, which names the
293
- * kind the caller expects.
294
- */
215
+ /** V2 slots keyed by name; ditto owns the names and omits empty ones. Read with `slot()`. */
295
216
  export interface InstanceSlotData {
296
217
  [slot: string]: unknown;
297
218
  }
298
- /**
299
- * Reads one slot off a block's `data`; undefined when ditto did not fill it.
300
- *
301
- * The caller names the kind, because the slot's kind lives in the block's ditto schema and not
302
- * here — a block fills slots with whatever its card needs, so no fixed list of kinds would hold
303
- * (`account_switch_block` alone carries a boolean and `budget_block` a nested object).
304
- */
219
+ /** Reads one slot off a block's `data`; the caller names its kind (ditto owns the schema). */
305
220
  export declare const slot: <T = unknown>(data: InstanceSlotData | undefined, name: string) => T | undefined;
306
221
  /**
307
- * V2: which block renders this beat's content, and what it renders.
308
- *
309
- * `block` is optional: a beat whose template has no ditto config arrives as an empty `{}` and the
310
- * card renders its copy and CTAs alone, so a reader cannot assume a block is named. One interface
311
- * with `block` optional rather than a union with `Record<string, never>`, which TypeScript absorbs
312
- * — that union left `block` reading as required and typed a promise it did not keep.
313
- *
314
- * `variant` is optional for the same reason — the empty `{}` carries neither. Every ditto beat
315
- * file that names a block also names a variant, so a *filled* slot always has one; ditto drops a
316
- * nil variant rather than sending null, which is why the type is `string | null | undefined`.
222
+ * V2: which block renders the beat. `block` and `variant` are optional: a template with no ditto
223
+ * config sends `{}`, and the card renders copy and CTAs alone.
317
224
  */
318
225
  export interface InstanceSlot {
319
226
  block?: BlockType;
@@ -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. On the payload: what every CTA of the card\n * shares (e.g. the account number for the Transaction Details drawer, or the guid list a list drawer\n * shows, `transaction_guids`). On a CTA: the figures that CTA's own drilldown renders (the Transaction\n * List summary header's `amount`, `start_date` / `end_date` and `count`, see `readSummary`). Scalars\n * or string lists, omitted when the insight has none. Never carries copy or user actions (memo,\n * tags, hide, flag come from the transaction store). Values come from the server, so a reader still\n * checks each value's runtime shape.\n */\nexport type DrilldownData = Record<string, string | number | boolean | null | string[]>\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 /**\n * V2: drilldown-only facts, e.g. `{ account_number: 'XXXXXXXX043' }`, or the guid list a list\n * drawer shows (`{ transaction_guids: [...] }`).\n */\n drilldown_data?: DrilldownData\n footer?: Footer\n /**\n * V2: the link inside the description: on the full card a drawer of its own (Low Account\n * Balance's \"Transactions ›\"); on mini and micro the card's action, sent instead of `primary_cta`.\n * Absent when the beat has no link.\n */\n in_description_cta?: InDescriptionCTA\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 /** Draw the `logo_name` icon filled (V2 `ICO-` logos). */\n logo_fill?: boolean\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 /** Figures this CTA's drilldown renders (e.g. a summary header's amount/dates/count). */\n drilldown_data?: DrilldownData\n}\n\nexport interface SecondaryCTA {\n label: string\n /**\n * Drawer block to open. `null` when the CTA opens nothing (ditto `secondary_cta_block: null`,\n * e.g. Fee Detected's \"Contact Support\"): the press posts its message to the host instead.\n */\n block: string | null\n variant?: string | null\n /** See `PrimaryCTA.action_key` (ditto `secondary_cta_action`). */\n action_key?: string | null\n metadata?: CtaPostMessageMetadata | null\n /** Figures this CTA's drilldown renders (e.g. a summary header's amount/dates/count). */\n drilldown_data?: DrilldownData\n}\n\n/**\n * The description link: its label, the action block it opens and, like a CTA's, the variant that\n * tells that block what to show (ditto's `in_description_cta_variant`, e.g. `low_balance`). On mini\n * and micro it words the card's action; `block` is empty when that action opens no drawer.\n */\nexport interface InDescriptionCTA {\n label: string\n block?: string\n variant?: string | null\n action_key?: string | null\n /** tupac's flat host message for the link (`action` plus fields), e.g. Switch's op_1. */\n post_message_metadata?: ({ action?: string | null } & Record<string, unknown>) | null\n /** Figures this CTA's drilldown renders (e.g. a summary header's amount/dates/count). */\n drilldown_data?: DrilldownData\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 * `null` (tupac's `footer_account_label` returns nil for a beat with no accounts, as Payday Cash\n * Left Over Status does). There is deliberately no separate `accounts` key.\n */\n account?: string | null\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 DirectDepositBlock: 'direct_deposit_block',\n ImageBlock: 'image_block',\n MerchantBlock: 'merchant_block',\n TransactionBlock: 'transaction_block',\n DonutChartBlock: 'donut_chart_block',\n DoubleBarChartBlock: 'double_bar_chart_block',\n DoubleProgressBarBlock: 'double_progress_bar_block',\n DebtsBlock: 'debts_block',\n GoalsBlock: 'goals_block',\n NoSpendDaysBlock: 'no_spend_days_block',\n RepeatingTransactionBlock: 'repeating_transaction_block',\n SaveExtraBlock: 'save_extra_block',\n SavingsAmountBlock: 'savings_amount_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), UpcomingSubscriptionBlock (price per cadence).\n // (SavingsOpportunityBlock now reads `amount` off `instance_slot.data`, not this flat field.)\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 // Withdrawal block (Emergency Fund Withdrawal): one row flat on the slot - `amount` above is the\n // withdrawal, shown with its date line \"{amount_label} {withdrawal_date}\" over the balance row.\n /** Pre-localized lead-in for the date line, e.g. \"Withdrawn on\". */\n amount_label?: string\n /** The withdrawal's calendar day, `YYYY-MM-DD` (e.g. `2026-10-20`); the card formats it. */\n withdrawal_date?: string\n /** Account balance after the withdrawal (unformatted); the card formats it as currency. */\n balance?: number\n /** Pre-localized label for the balance row, e.g. \"Balance\". */\n balance_label?: string\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 // Account block (confetti tile): V1 flat fallback for the label line when `instance_slot.data` is\n // absent — `AccountBlock` reads `data.sub_text` first, then this. (The Savings Opportunity coupon\n // now reads `primary_text`/`amount` off `data`, so it no longer reads this flat field.)\n /** Caption/label line for the confetti tile (V1 fallback). */\n label?: string\n // Upcoming Subscription block: billing cadence for the price pill (`${amount} / ${cadence}`).\n /** Billing cadence word that trails the price, e.g. `month` or `year`. */\n cadence?: string\n // Account block (status on/off-track, deposit, payoff variants): card content carried flat on\n // the slot (the V2 contract drops `instance_slot_data`). `amount`, `label`, `merchant_guid`,\n // `merchant_name`, `institution_guid`, `institution_name` are shared fields declared above.\n /** Secondary line beneath the amount on the standard card, e.g. \"Remaining after expenses\". */\n sub_text?: string\n /** Header bar text (standard card) or the colored category strip label (deposit cards). */\n header_text?: string\n /** Generic-tile icon name used when no merchant/institution logo is available. */\n icon_name?: string\n /** Category guid used to render the deposit-card logo fallback. */\n category_guid?: string\n // Debts block: `amount` is the current balance; the shared account/institution fields above.\n /** Projected payoff date in ISO form (e.g. `2027-03-01`); the block formats it as month + year. */\n payoff_date?: string\n /** Monthly payment toward the debt (unformatted); the block formats it as currency. */\n monthly_payment?: number\n /** Annual interest rate as a percentage (e.g. `19.99`); the block formats it as a percent. */\n interest_rate?: number\n start_date?: string\n no_spend_days?: string[]\n}\n"],"mappings":"AA2UA,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/** Emitted when the user drills into a datum (e.g. a chart bar click). */\nexport interface DrilldownPayload {\n chartBarIndex: number\n tabIndex?: number\n transaction_guid?: string\n block?: string\n /** Drawer variant the bar names itself, used when no CTA names its block. */\n variant?: string\n}\n\n/** The envelope a beat was fetched with; a surface asks with `widget_type=`. */\nexport type WidgetType = 'full' | 'mini' | 'micro' | 'embedded' | 'notification'\n\n/** V2: the transaction-row tag, from the `embedded` envelope. Not `short_title`. */\nexport interface Pill {\n text: string\n}\n\n/**\n * V2: facts a drilldown shows that the card doesn't (scalars or string lists, never copy).\n * Server values, so readers still check each value's shape.\n */\nexport type DrilldownData = Record<string, string | number | boolean | null | string[]>\n\nexport interface InsightsPayload {\n widget_type: WidgetType\n instance_slot: InstanceSlot\n /** V1 only; V2 sends `instance_slot.data` instead. */\n instance_slot_data?: InsightsInstanceSlotData\n description: Description\n primary_cta?: PrimaryCTA\n secondary_cta?: SecondaryCTA\n title?: string\n sub_title?: Subtitle\n /** V2 rename of `sub_title`; `sub_title` wins when both are present. */\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 }` or `{ transaction_guids }`. */\n drilldown_data?: DrilldownData\n footer?: Footer\n /** V2: the description link; on mini and micro it's the card's action. */\n in_description_cta?: InDescriptionCTA\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 /** V2: the entities the beat is about, so action blocks needn't read the beat. */\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 /** V2: the subscription beat's repeating transaction (read by `recurring_transaction_block`). */\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 /** Draw the `logo_name` icon filled (V2 `ICO-` logos). */\n logo_fill?: boolean\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: an entity `guid` (`INS-`/`MCH-`/`CAT-`, optional `fallback_guid`) or a status\n * `icon` + `color`. `alt` names either; `icon` wins if both are sent.\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/** Post message a CTA press sends to the host; absent means use `ctaPostMessages` or send none. */\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 /** Backend-named behaviour beyond opening `block` (see `ctaActions`); absent means just open it. */\n action_key?: string | null\n metadata?: CtaPostMessageMetadata | null\n /** Figures this CTA's drilldown renders (e.g. a summary header's amount/dates/count). */\n drilldown_data?: DrilldownData\n}\n\nexport interface SecondaryCTA {\n label: string\n /** Drawer block to open; `null` means the press only posts its message. */\n block: string | null\n variant?: string | null\n /** See `PrimaryCTA.action_key` (ditto `secondary_cta_action`). */\n action_key?: string | null\n metadata?: CtaPostMessageMetadata | null\n /** Figures this CTA's drilldown renders (e.g. a summary header's amount/dates/count). */\n drilldown_data?: DrilldownData\n}\n\n/** The description link: label, the block it opens and that block's variant. */\nexport interface InDescriptionCTA {\n label: string\n block?: string\n variant?: string | null\n action_key?: string | null\n /** tupac's flat host message for the link (`action` plus fields), e.g. Switch's op_1. */\n post_message_metadata?: ({ action?: string | null } & Record<string, unknown>) | null\n /** Figures this CTA's drilldown renders (e.g. a summary header's amount/dates/count). */\n drilldown_data?: DrilldownData\n}\n\nexport interface Footer {\n /** V1: a pre-formatted date string. */\n date?: string\n /** Account label as sent: a name, a localized \"N Accounts\", or `null`. */\n account?: string | null\n /** V2: unix seconds, formatted by `Footer`; `date` wins if both are sent. */\n timestamp?: number\n}\n\n// Instance slot types: values are the snake_case block names the backend sends.\nexport const BlockType = {\n AccountBlock: 'account_block',\n AccountSwitchBlock: 'account_switch_block',\n BarChartBlock: 'bar_chart_block',\n BudgetBlock: 'budget_block',\n DirectDepositBlock: 'direct_deposit_block',\n ImageBlock: 'image_block',\n MerchantBlock: 'merchant_block',\n TransactionBlock: 'transaction_block',\n DonutChartBlock: 'donut_chart_block',\n DoubleBarChartBlock: 'double_bar_chart_block',\n DoubleProgressBarBlock: 'double_progress_bar_block',\n DebtsBlock: 'debts_block',\n GoalsBlock: 'goals_block',\n NoSpendDaysBlock: 'no_spend_days_block',\n RepeatingTransactionBlock: 'repeating_transaction_block',\n SaveExtraBlock: 'save_extra_block',\n SavingsAmountBlock: 'savings_amount_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/** A pre-localized V2 slot row; the logo is a `LogoRef`. */\nexport interface InstanceSlotRow {\n amount?: number\n logo?: LogoRef\n primary_text?: string\n secondary_text?: string\n}\n\n/** V2 slots keyed by name; ditto owns the names and omits empty ones. Read with `slot()`. */\nexport interface InstanceSlotData {\n [slot: string]: unknown\n}\n\n/** Reads one slot off a block's `data`; the caller names its kind (ditto owns the schema). */\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 the beat. `block` and `variant` are optional: a template with no ditto\n * config sends `{}`, and the card renders copy and CTAs alone.\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: account facts carried flat on the slot.\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 by UpcomingBillBlock and UpcomingSubscriptionBlock.\n /** Dollar amount (unformatted); the block formats it as currency. */\n amount?: number\n // Withdrawal block: one flat row; `amount` above is the withdrawal.\n /** Pre-localized lead-in for the date line, e.g. \"Withdrawn on\". */\n amount_label?: string\n /** The withdrawal's calendar day, `YYYY-MM-DD` (e.g. `2026-10-20`); the card formats it. */\n withdrawal_date?: string\n /** Account balance after the withdrawal (unformatted); the card formats it as currency. */\n balance?: number\n /** Pre-localized label for the balance row, e.g. \"Balance\". */\n balance_label?: string\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: the week strip is derived from `due_date`.\n /** Due date of the projected bill in ISO form (e.g. `2025-10-30`). */\n due_date?: string\n // Account block (confetti tile): V1 fallback for the label when `data.sub_text` is absent.\n /** Caption/label line for the confetti tile (V1 fallback). */\n label?: string\n // Upcoming Subscription block: billing cadence for the price pill (`${amount} / ${cadence}`).\n /** Billing cadence word that trails the price, e.g. `month` or `year`. */\n cadence?: string\n // Account block (status, deposit, payoff variants): card content flat on the slot.\n /** Secondary line beneath the amount on the standard card, e.g. \"Remaining after expenses\". */\n sub_text?: string\n /** Header bar text (standard card) or the colored category strip label (deposit cards). */\n header_text?: string\n /** Generic-tile icon name used when no merchant/institution logo is available. */\n icon_name?: string\n /** Category guid used to render the deposit-card logo fallback. */\n category_guid?: string\n // Debts block: `amount` is the current balance; the shared account/institution fields above.\n /** Projected payoff date in ISO form (e.g. `2027-03-01`); the block formats it as month + year. */\n payoff_date?: string\n /** Monthly payment toward the debt (unformatted); the block formats it as currency. */\n monthly_payment?: number\n /** Annual interest rate as a percentage (e.g. `19.99`); the block formats it as a percent. */\n interest_rate?: number\n start_date?: string\n no_spend_days?: string[]\n}\n"],"mappings":"AAoPA,IAAa,IAAA,CACX,GACA,MACkB,IAAO,CAAA"}
@@ -1,12 +1,7 @@
1
1
  import { ActionBlockProps } from '../../mappings/blocks';
2
2
  /**
3
- * `amount_input_modal_block`: one whole-dollar setting edited in a dialog (Figma 441:24913 and
4
- * 5402:34137). The CTA's variant picks what is edited:
5
- * - `low_balance_threshold`: the `threshold` on the beat account's low-balance alert profile;
6
- * - `safety_net`: `savings_opportunity_minimum_checking_account_balance` on the insight profile.
7
- *
8
- * Registered with `presentation: 'modal'`, so no drawer opens behind it; closing the dialog ends
9
- * the action-drawer session. `observer` is required: the starting values are read from stores.
3
+ * `amount_input_modal_block`: one whole-dollar setting in a modal, picked by the CTA variant
4
+ * (low-balance threshold, safety net or create budget).
10
5
  */
11
6
  export declare const AmountInputModalBlock: (({ beat, }: ActionBlockProps) => import("react/jsx-runtime").JSX.Element) & {
12
7
  displayName: string;
@@ -1,133 +1,140 @@
1
- import { buildDynamicCopy as z } from "../../../core/utils/Localization.es.js";
2
- import q from "../../../common/utils/AccountDisplayName.es.js";
3
- import { useGlobalCopyStore as J, useInsightsV2Store as K, useSettingsStore as Q, useUserStore as X } from "../../../common/context/hooks.es.js";
4
- import Z from "../../../common/components/Loader.es.js";
5
- import oo from "../../../common/components/CurrencyDialog.es.js";
6
- import { useBeatActions as to } from "../../beatActions.es.js";
7
- import { ANALYTICS_EVENTS_CONFIG as c } from "../../analytics/analyticsEventsConfig.es.js";
8
- import { useCtaHandler as eo } from "../../ctaActions/useCtaAction.es.js";
9
- import { useAnalyticsEvent as io } from "../../analytics/useAnalyticsEvent.es.js";
10
- import { getDynamicCtaBasedOnTriggers as no } from "../util.es.js";
11
- import { AMOUNT_INPUT_VARIANTS as ro, findLowBalanceProfile as ao, isAmountInputVariant as x, isWholeAmount as so, resolveAmountInputVariant as co, toInputValue as lo } from "./layout.es.js";
12
- import r from "react";
13
- import { observer as uo } from "mobx-react-lite";
14
- import P from "@mui/material/Stack";
15
- import { H3 as mo, InstitutionLogo as po, Text as H } from "@mxenabled/mxui";
16
- import { Icon as _o } from "@mxenabled/mx-icons";
17
- import { jsx as e, jsxs as k } from "react/jsx-runtime";
18
- import fo from "@mui/material/Dialog";
19
- import ho from "@mui/material/IconButton";
20
- var w = ({ children: I, closeAriaLabel: i, heading: o, onClose: l }) => {
21
- const u = r.useId();
22
- return /* @__PURE__ */ e(fo, {
23
- "aria-labelledby": o ? u : void 0,
1
+ import { buildDynamicCopy as W } from "../../../core/utils/Localization.es.js";
2
+ import Y from "../../../common/utils/AccountDisplayName.es.js";
3
+ import { useGlobalCopyStore as j, useInsightsV2Store as w, useSettingsStore as z, useUserStore as q } from "../../../common/context/hooks.es.js";
4
+ import J from "../../../common/components/Loader.es.js";
5
+ import K from "../../../common/components/CurrencyDialog.es.js";
6
+ import { useBeatActions as Q } from "../../beatActions.es.js";
7
+ import { ANALYTICS_EVENTS_CONFIG as m } from "../../analytics/analyticsEventsConfig.es.js";
8
+ import { useCtaHandler as X } from "../../ctaActions/useCtaAction.es.js";
9
+ import { useAnalyticsEvent as Z } from "../../analytics/useAnalyticsEvent.es.js";
10
+ import { getDynamicCtaBasedOnTriggers as oo } from "../util.es.js";
11
+ import { CreateBudgetDialog as to } from "./CreateBudgetDialog.es.js";
12
+ import { AMOUNT_INPUT_VARIANTS as eo, findLowBalanceProfile as io, isAmountInputVariant as L, isWholeAmount as no, resolveAmountInputVariant as ro, toInputValue as ao } from "./layout.es.js";
13
+ import a from "react";
14
+ import { observer as P } from "mobx-react-lite";
15
+ import B from "@mui/material/Stack";
16
+ import { H3 as so, InstitutionLogo as co, Text as x } from "@mxenabled/mxui";
17
+ import { Icon as lo } from "@mxenabled/mx-icons";
18
+ import { jsx as e, jsxs as V } from "react/jsx-runtime";
19
+ import uo from "@mui/material/Dialog";
20
+ import mo from "@mui/material/IconButton";
21
+ var H = ({ children: f, closeAriaLabel: i, heading: n, onClose: o }) => {
22
+ const c = a.useId();
23
+ return /* @__PURE__ */ e(uo, {
24
+ "aria-labelledby": n ? c : void 0,
24
25
  maxWidth: "xs",
25
- onClose: l,
26
+ onClose: o,
26
27
  open: !0,
27
- children: /* @__PURE__ */ k(P, {
28
+ children: /* @__PURE__ */ V(B, {
28
29
  sx: {
29
30
  gap: 12,
30
31
  p: 24,
31
32
  position: "relative"
32
33
  },
33
34
  children: [
34
- o && /* @__PURE__ */ e(mo, {
35
- id: u,
36
- children: o
35
+ n && /* @__PURE__ */ e(so, {
36
+ id: c,
37
+ children: n
37
38
  }),
38
- /* @__PURE__ */ e(ho, {
39
+ /* @__PURE__ */ e(mo, {
39
40
  "aria-label": i || "Close",
40
- onClick: l,
41
+ onClick: o,
41
42
  sx: {
42
43
  position: "absolute",
43
44
  right: 8,
44
45
  top: 18
45
46
  },
46
- children: /* @__PURE__ */ e(_o, {
47
+ children: /* @__PURE__ */ e(lo, {
47
48
  name: "close",
48
49
  sx: { color: "action.active" }
49
50
  })
50
51
  }),
51
- I
52
+ f
52
53
  ]
53
54
  })
54
55
  });
55
- }, Bo = uo(function({ beat: i }) {
56
- const { common: o, insights_feed: l } = J(), { actionDrawer: u, closeActionDrawer: m } = K(), f = Q(), { userInsightProfile: v } = X(), S = eo(i, to()), T = io(), { primary_cta: V, secondary_cta: B, in_description_cta: O } = i.insights_payload ?? {}, G = no(u, V, B, O), s = co(G), a = l?.amount_input_modal, t = s === ro.LOW_BALANCE_THRESHOLD, h = t ? ao(f.notificationProfiles, i.primary_account_guid) : void 0, A = t ? h?.threshold : v?.savings_opportunity_minimum_checking_account_balance, [R, F] = r.useState(t), d = r.useRef(!0);
57
- r.useEffect(() => (d.current = !0, () => {
56
+ }, Vo = P(function({ beat: i }) {
57
+ const { actionDrawer: n } = w(), { primary_cta: o, secondary_cta: c, in_description_cta: l } = i.insights_payload ?? {}, [u] = a.useState(() => ro(oo(n, o, c, l)));
58
+ return u === "create_budget" ? /* @__PURE__ */ e(to, { beat: i }) : /* @__PURE__ */ e(po, {
59
+ beat: i,
60
+ variant: u
61
+ });
62
+ }), po = P(function({ beat: i, variant: n }) {
63
+ const { common: o, insights_feed: c } = j(), { closeActionDrawer: l } = w(), u = z(), { userInsightProfile: I } = q(), S = X(i, Q()), A = Z(), s = c?.amount_input_modal, t = n === eo.LOW_BALANCE_THRESHOLD, g = t ? io(u.notificationProfiles, i.primary_account_guid) : void 0, T = t ? g?.threshold : I?.savings_opportunity_minimum_checking_account_balance, [k, O] = a.useState(t), d = a.useRef(!0);
64
+ a.useEffect(() => (d.current = !0, () => {
58
65
  d.current = !1;
59
- }), []), r.useEffect(() => {
60
- t && f.loadNotificationProfiles().finally(() => {
61
- d.current && F(!1);
66
+ }), []), a.useEffect(() => {
67
+ t && u.loadNotificationProfiles().finally(() => {
68
+ d.current && O(!1);
62
69
  });
63
- }, [t, f]);
64
- const [M, U] = r.useState(null), [E, C] = r.useState(!1), [$, y] = r.useState(!1), p = M ?? lo(A);
65
- if (R) return /* @__PURE__ */ e(w, {
70
+ }, [t, u]);
71
+ const [R, G] = a.useState(null), [E, v] = a.useState(!1), [F, h] = a.useState(!1), p = R ?? ao(T);
72
+ if (k) return /* @__PURE__ */ e(H, {
66
73
  closeAriaLabel: o?.close_aria,
67
- onClose: m,
68
- children: /* @__PURE__ */ e(Z, {})
74
+ onClose: l,
75
+ children: /* @__PURE__ */ e(J, {})
69
76
  });
70
- const n = x(s) ? a?.[s] : void 0, b = !!n?.title && !!n.description && !!n.input_label && !!a?.whole_number_error && !!a.save_error && !!o?.save_button && (!t || !!o.cancel_button) && !!o.close_aria;
71
- if (!a || !n || !b || !(t ? h : v))
72
- return console.warn(`amount_input_modal_block: ${a ? x(s) ? b ? t ? "no low-balance profile for the account" : "user insight profile not set by the host" : `copy incomplete for "${s}"` : `unknown variant "${s}"` : "copy namespace missing"}`), /* @__PURE__ */ e(w, {
77
+ const r = L(n) ? s?.[n] : void 0, D = !!r?.title && !!r.description && !!r.input_label && !!s?.whole_number_error && !!s.save_error && !!o?.save_button && (!t || !!o.cancel_button) && !!o.close_aria;
78
+ if (!s || !r || !D || !(t ? g : I))
79
+ return console.warn(`amount_input_modal_block: ${s ? L(n) ? D ? t ? "no low-balance profile for the account" : "user insight profile not set by the host" : `copy incomplete for "${n}"` : `unknown variant "${n}"` : "copy namespace missing"}`), /* @__PURE__ */ e(H, {
73
80
  closeAriaLabel: o?.close_aria,
74
81
  heading: o?.error_heading,
75
- onClose: m,
76
- children: /* @__PURE__ */ e(H, { children: o?.error_message })
82
+ onClose: l,
83
+ children: /* @__PURE__ */ e(x, { children: o?.error_message })
77
84
  });
78
- const D = () => {
79
- T(t ? c.EDIT_INSIGHT_THRESHOLD_CANCELED : c.EDIT_SAFETY_NET_CANCEL), m();
80
- }, L = !t && !!A, N = i.primary_account ? q(i.primary_account) : "", g = so(p), W = p !== "" && !g, Y = async () => {
81
- if (!g || E) return;
85
+ const C = () => {
86
+ A(t ? m.EDIT_INSIGHT_THRESHOLD_CANCELED : m.EDIT_SAFETY_NET_CANCEL), l();
87
+ }, b = !t && !!T, N = i.primary_account ? Y(i.primary_account) : "", y = no(p), M = p !== "" && !y, U = async () => {
88
+ if (!y || E) return;
82
89
  const _ = Number(p);
83
- C(!0), y(!1);
84
- const j = t ? await S("updateNotificationProfileThreshold", {
85
- profileGuid: h?.guid,
90
+ v(!0), h(!1);
91
+ const $ = t ? await S("updateNotificationProfileThreshold", {
92
+ profileGuid: g?.guid,
86
93
  threshold: _
87
- }, { analytics: c.EDIT_INSIGHT_THRESHOLD_SAVE }) : await S("updateUserInsightProfile", { fields: { savings_opportunity_minimum_checking_account_balance: _ } }, { analytics: c.EDIT_SAFETY_NET_SAVE });
88
- d.current && (C(!1), j ? m() : y(!0));
94
+ }, { analytics: m.EDIT_INSIGHT_THRESHOLD_SAVE }) : await S("updateUserInsightProfile", { fields: { savings_opportunity_minimum_checking_account_balance: _ } }, { analytics: m.EDIT_SAFETY_NET_SAVE });
95
+ d.current && (v(!1), $ ? l() : h(!0));
89
96
  };
90
- return /* @__PURE__ */ e(oo, {
97
+ return /* @__PURE__ */ e(K, {
91
98
  closeAriaLabel: o.close_aria,
92
- content: z(L && n.description_edit || n.description, /* @__PURE__ */ e("strong", { children: N }, "account")),
93
- errorText: W ? a.whole_number_error : $ ? a.save_error : void 0,
99
+ content: W(b && r.description_edit || r.description, /* @__PURE__ */ e("strong", { children: N }, "account")),
100
+ errorText: M ? s.whole_number_error : F ? s.save_error : void 0,
94
101
  handleInputChange: (_) => {
95
- U(_), y(!1);
102
+ G(_), h(!1);
96
103
  },
97
- handleInputClick: t ? () => T(c.EDIT_INSIGHT_THRESHOLD_INPUT_SELECTED) : void 0,
98
- handleModalClose: D,
104
+ handleInputClick: t ? () => A(m.EDIT_INSIGHT_THRESHOLD_INPUT_SELECTED) : void 0,
105
+ handleModalClose: C,
99
106
  handlePrimaryAction: () => {
100
- Y();
107
+ U();
101
108
  },
102
- handleSecondaryAction: D,
103
- inputLabel: n.input_label,
109
+ handleSecondaryAction: C,
110
+ inputLabel: r.input_label,
104
111
  inputValue: p,
105
112
  isOpen: !0,
106
- isPrimaryDisabled: E || !g,
113
+ isPrimaryDisabled: E || !y,
107
114
  primaryText: o.save_button,
108
115
  secondaryText: t ? o.cancel_button : void 0,
109
- subtitle: t && i.primary_account ? /* @__PURE__ */ k(P, {
116
+ subtitle: t && i.primary_account ? /* @__PURE__ */ V(B, {
110
117
  sx: {
111
118
  alignItems: "center",
112
119
  flexDirection: "row",
113
120
  gap: 8
114
121
  },
115
- children: [/* @__PURE__ */ e(po, {
122
+ children: [/* @__PURE__ */ e(co, {
116
123
  alt: "",
117
124
  institutionGuid: i.primary_account.institution_guid ?? "",
118
125
  size: 16
119
- }), /* @__PURE__ */ e(H, {
126
+ }), /* @__PURE__ */ e(x, {
120
127
  color: "text.secondary",
121
128
  uppercase: !0,
122
129
  variant: "body2",
123
130
  children: N
124
131
  })]
125
132
  }) : void 0,
126
- title: L && n.title_edit || n.title
133
+ title: b && r.title_edit || r.title
127
134
  });
128
135
  });
129
136
  export {
130
- Bo as AmountInputModalBlock
137
+ Vo as AmountInputModalBlock
131
138
  };
132
139
 
133
140
  //# sourceMappingURL=AmountInputModalBlock.es.js.map