@mx-cartographer/experiences 9.4.69 → 9.4.71

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 (42) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/common/utils/PostMessage.d.ts +5 -1
  3. package/dist/common/utils/PostMessage.es.js +26 -24
  4. package/dist/common/utils/PostMessage.es.js.map +1 -1
  5. package/dist/core/types/Insights.d.ts +25 -0
  6. package/dist/core/types/index.d.ts +1 -1
  7. package/dist/insights-v2/blocks/ComponentBlocks/DirectDepositBlock/DirectDepositBlock.d.ts +16 -0
  8. package/dist/insights-v2/blocks/ComponentBlocks/DirectDepositBlock/DirectDepositBlock.es.js +24 -0
  9. package/dist/insights-v2/blocks/ComponentBlocks/DirectDepositBlock/DirectDepositBlock.es.js.map +1 -0
  10. package/dist/insights-v2/blocks/ComponentBlocks/DirectDepositBlock/index.d.ts +1 -0
  11. package/dist/insights-v2/blocks/ComponentBlocks/DirectDepositBlock/layout.d.ts +28 -0
  12. package/dist/insights-v2/blocks/ComponentBlocks/DirectDepositBlock/layout.es.js +63 -0
  13. package/dist/insights-v2/blocks/ComponentBlocks/DirectDepositBlock/layout.es.js.map +1 -0
  14. package/dist/insights-v2/blocks/ComponentBlocks/index.d.ts +1 -0
  15. package/dist/insights-v2/components/AccountHeroCard.d.ts +7 -1
  16. package/dist/insights-v2/components/AccountHeroCard.es.js +6 -7
  17. package/dist/insights-v2/components/AccountHeroCard.es.js.map +1 -1
  18. package/dist/insights-v2/components/BaseLayout.es.js.map +1 -1
  19. package/dist/insights-v2/components/DirectDepositCard.d.ts +48 -0
  20. package/dist/insights-v2/components/DirectDepositCard.es.js +37 -0
  21. package/dist/insights-v2/components/DirectDepositCard.es.js.map +1 -0
  22. package/dist/insights-v2/components/TransferLogoCard.d.ts +5 -0
  23. package/dist/insights-v2/components/TransferLogoCard.es.js +37 -55
  24. package/dist/insights-v2/components/TransferLogoCard.es.js.map +1 -1
  25. package/dist/insights-v2/components/shared/ConfettiOverlay.d.ts +1 -0
  26. package/dist/insights-v2/components/shared/ConfettiOverlay.es.js +27 -0
  27. package/dist/insights-v2/components/shared/ConfettiOverlay.es.js.map +1 -0
  28. package/dist/insights-v2/ctaActions/ctaConfig.d.ts +3 -2
  29. package/dist/insights-v2/ctaActions/ctaConfig.es.js.map +1 -1
  30. package/dist/insights-v2/ctaActions/ctaPostMessages.d.ts +16 -0
  31. package/dist/insights-v2/ctaActions/ctaPostMessages.es.js +51 -0
  32. package/dist/insights-v2/ctaActions/ctaPostMessages.es.js.map +1 -0
  33. package/dist/insights-v2/ctaActions/index.d.ts +1 -0
  34. package/dist/insights-v2/ctaActions/runCtaAction.d.ts +5 -1
  35. package/dist/insights-v2/ctaActions/runCtaAction.es.js +54 -51
  36. package/dist/insights-v2/ctaActions/runCtaAction.es.js.map +1 -1
  37. package/dist/insights-v2/ctaActions/types.d.ts +1 -1
  38. package/dist/insights-v2/index.d.ts +1 -0
  39. package/dist/insights-v2/index.es.js +70 -66
  40. package/dist/insights-v2/mappings/blocks.es.js +34 -32
  41. package/dist/insights-v2/mappings/blocks.es.js.map +1 -1
  42. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [9.4.71] - 10-09-2026
2
+
3
+ - **CHANGED** - `DirectDepositVariant` (`DirectDepositBlock/layout.ts`) is now a single `directDepositVariant` const object used both as the runtime value and as the source for the derived `DirectDepositVariant` type, so a variant name only needs to change in one place; `getLayoutConfig`'s keys are computed properties off that object instead of retyped literals (WEC-1875)
4
+ - **FIXED** - `DirectDepositBlockBeats.ts` fixture typed its `insights_payload` per-JSON-literal, which broke `primary_cta` access for the `DirectDepositComplete` variant (no CTA on that beat) with a `TS2339` typecheck error; `insights_payload` is now cast to the real `InsightsPayload` type (matching `TransactionBlockBeats.ts`'s pattern), which already models `primary_cta` as optional (WEC-1875)
5
+ - **CHANGED** - `DirectDepositBlockPayload.json` fixture's `instance_slot.variant` values switched to snake_case (WEC-1875)
6
+ - **CHANGED** - Extracted `ConfettiOverlay` (`src/insights-v2/components/shared/ConfettiOverlay.tsx`) as a shared component, used by both `DirectDepositCard` and `TransferLogoCard` instead of each defining its own (WEC-1875)
7
+
8
+ ## [9.4.70] - 10-09-2026
9
+
10
+ - **ADDED** - `PrimaryCTA` / `SecondaryCTA` accept a backend-described `metadata` object (`event`, `action`, `payload`); on press the CTA runner posts that message to the host after the step's handler and effects succeed, so per-insight post messages no longer need frontend code (WEC-1852)
11
+ - **CHANGED** - A CTA press posts a message only when one resolves (`cta.metadata`, else `ctaPostMessages`); the previous fallback that posted a base `beat/cta` `op_1` for every block-less CTA is removed (WEC-1852)
12
+ - **CHANGED** - `sendBeatCta` accepts an `event` override and `extras` merged into the message metadata (WEC-1852)
13
+ - **ADDED** - `ctaPostMessages`: interim per-template CTA post messages (SaveAnExtra100Dollars, LowAccountBalance, MonthlyObligationsStatus, DesignateEmergencySavingsAccount, ReplenishSavings, SavingsOpportunityV2) carried over from pulse, used only when the backend sends no `cta.metadata` (WEC-1852)
14
+
1
15
  ## [9.4.69] - 10-09-2026
2
16
 
3
17
  - **ADDED** - `remaining_cash_block` (Remaining Cash) action block for the Payday Cash Left Over Status beat: summary card (remaining until payday, days, cash on hand, upcoming expenses) plus cash accounts and recurring expenses before payday, each capped at two rows with an "Other (#)" row. Store-driven from `CashflowStore`; loads through `useRecurringTransactionPrepare` with an `ErrorCard` retry on failure (WEC-1880)
@@ -52,10 +52,14 @@ export interface SendBeatCtaOptions {
52
52
  userGuid?: string;
53
53
  /** Operation string sent with the CTA (defaults to op_1). */
54
54
  op?: string;
55
+ /** Post message event name (defaults to `beat/cta`). */
56
+ event?: string;
57
+ /** Beat-specific fields merged into the metadata after the base payload and `user_guid`. */
58
+ extras?: Record<string, unknown>;
55
59
  }
56
60
  /**
57
61
  * Send a beat CTA to the host: builds the payload, adds `user_guid`, then either
58
62
  * posts a message to the host or navigates the webview. Mirrors the behaviour of
59
63
  * Pulse's `postMessages` epic (minus the RxJS buffering).
60
64
  */
61
- export declare function sendBeatCta(beat: BeatCtaSource, { isMobileWebview, webviewScheme, userGuid, op }?: SendBeatCtaOptions): void;
65
+ export declare function sendBeatCta(beat: BeatCtaSource, { isMobileWebview, webviewScheme, userGuid, op, event, extras }?: SendBeatCtaOptions): void;
@@ -1,62 +1,64 @@
1
- function c() {
1
+ function f() {
2
2
  return window.opener && window.opener.location ? window.opener.location.toString() : document.referrer;
3
3
  }
4
4
  function a(e) {
5
- const n = c().replace(/([^:]+:\/\/[^\/]+).*/, "$1"), t = window.parent || window.opener || !1;
5
+ const n = f().replace(/([^:]+:\/\/[^\/]+).*/, "$1"), t = window.parent || window.opener || !1;
6
6
  return t && t.postMessage && n ? (t.postMessage(e, n), !0) : !1;
7
7
  }
8
- function w(e) {
8
+ function T(e) {
9
9
  return a({
10
10
  metadata: { beat_guid: e },
11
11
  mx: !0,
12
12
  type: "mx/moneyDashboard/insightOnTransaction"
13
13
  });
14
14
  }
15
- function m(e) {
15
+ function y(e) {
16
16
  return a({
17
17
  metadata: { template: e },
18
18
  mx: !0,
19
19
  type: "mx/pulse/client_configured_cta"
20
20
  });
21
21
  }
22
- var d = "beat/cta", p = "op_1";
23
- function f(e, n = p) {
22
+ var l = "beat/cta", g = "op_1", x = "op_2";
23
+ function w(e, n = g) {
24
24
  const t = {
25
25
  action: n,
26
26
  beat_guid: e.guid,
27
27
  beat_template: e.template
28
28
  };
29
- return e?.payload?.action_string && (t.action_string = e.payload.action_string), [d, t];
29
+ return e?.payload?.action_string && (t.action_string = e.payload.action_string), [l, t];
30
30
  }
31
- function l(e, n, t = "mx/pulse") {
31
+ function m(e, n, t = "mx/pulse") {
32
32
  return window.self === window.top ? !1 : a({
33
33
  metadata: n,
34
34
  mx: !0,
35
35
  type: `${t}/${e}`
36
36
  });
37
37
  }
38
- function g(e, n, t = "mx") {
38
+ function _(e, n, t = "mx") {
39
39
  let o = `${t}://pulse/${e}`;
40
40
  n && (o += "?metadata=" + encodeURIComponent(JSON.stringify(n))), window.location.href = o;
41
41
  }
42
- function _(e, { isMobileWebview: n, webviewScheme: t, userGuid: o, op: s } = {}) {
43
- const [r, u] = f(e, s), i = {
44
- ...u,
45
- ...o ? { user_guid: o } : {}
46
- };
47
- n ? g(r, i, t) : l(r, i);
42
+ function E(e, { isMobileWebview: n, webviewScheme: t, userGuid: o, op: s, event: u, extras: c } = {}) {
43
+ const [d, p] = w(e, s), r = {
44
+ ...p,
45
+ ...o ? { user_guid: o } : {},
46
+ ...c
47
+ }, i = u || d;
48
+ n ? _(i, r, t) : m(i, r);
48
49
  }
49
50
  export {
50
- d as BEAT_CTA_EVENT,
51
- p as BEAT_OPERATION_1,
52
- f as getBaseCtaPostMessage,
53
- c as getReferrer,
54
- m as postClientConfiguredCta,
55
- w as postInsightOnTransaction,
51
+ l as BEAT_CTA_EVENT,
52
+ g as BEAT_OPERATION_1,
53
+ x as BEAT_OPERATION_2,
54
+ w as getBaseCtaPostMessage,
55
+ f as getReferrer,
56
+ y as postClientConfiguredCta,
57
+ T as postInsightOnTransaction,
56
58
  a as postMessageToParent,
57
- _ as sendBeatCta,
58
- l as sendBeatPostMessage,
59
- g as setWebviewURL
59
+ E as sendBeatCta,
60
+ m as sendBeatPostMessage,
61
+ _ as setWebviewURL
60
62
  };
61
63
 
62
64
  //# sourceMappingURL=PostMessage.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PostMessage.es.js","names":[],"sources":["../../../src/common/utils/PostMessage.ts"],"sourcesContent":["export function getReferrer(): string {\n if (window.opener && window.opener.location) {\n return window.opener.location.toString()\n } else {\n return document.referrer\n }\n}\n\nexport interface PostMessageData {\n metadata?: Record<string, any>\n mx: boolean\n type: string\n [key: string]: any\n}\n\nexport function postMessageToParent(message: PostMessageData): boolean {\n const postUrl = getReferrer().replace(/([^:]+:\\/\\/[^\\/]+).*/, '$1') // eslint-disable-line\n const otherWindow = window.parent || window.opener || false\n\n if (otherWindow && otherWindow.postMessage && postUrl) {\n otherWindow.postMessage(message, postUrl)\n return true\n }\n\n return false\n}\n\nexport function postInsightOnTransaction(beatGuid: string): boolean {\n const message: PostMessageData = {\n metadata: { beat_guid: beatGuid },\n mx: true,\n type: 'mx/moneyDashboard/insightOnTransaction',\n }\n\n return postMessageToParent(message)\n}\n\nexport function postClientConfiguredCta(template: string): boolean {\n const message: PostMessageData = {\n metadata: { template: template },\n mx: true,\n type: 'mx/pulse/client_configured_cta',\n }\n\n return postMessageToParent(message)\n}\n\n// ============================================================================\n// Beat CTA post messages (ported from Pulse: src/utils/PostMessage.js +\n// src/constants/PostMessage.js + src/epics/PostMessage.js).\n//\n// Scope: currently only the Save an extra $100 beat uses this. When a beat CTA\n// has no drilldown drawer, clicking it notifies the host app via a beat/cta\n// post message instead of opening a drawer. Native (mobile webview) hosts can't\n// receive post messages, so we navigate the webview to a custom-scheme URL.\n// ============================================================================\n\nexport const BEAT_CTA_EVENT = 'beat/cta'\nexport const BEAT_OPERATION_1 = 'op_1'\nexport const BEAT_OPERATION_2 = 'op_2'\nexport const BEAT_OPERATION_3 = 'op_3'\n\n/** Minimal beat shape needed to build a CTA post message. */\nexport interface BeatCtaSource {\n guid: string\n template: string\n payload?: { action_string?: string } | null\n}\n\nexport interface BeatCtaPayload {\n action: string\n beat_guid: string\n beat_template: string\n action_string?: string\n [key: string]: unknown\n}\n\n/**\n * Build the `[event, payload]` tuple for a beat CTA post message.\n * Mirrors Pulse's `getBaseCtaPostMessage`.\n */\nexport function getBaseCtaPostMessage(\n beat: BeatCtaSource,\n op: string = BEAT_OPERATION_1,\n): [string, BeatCtaPayload] {\n const payload: BeatCtaPayload = {\n action: op,\n beat_guid: beat.guid,\n beat_template: beat.template,\n }\n\n if (beat?.payload?.action_string) {\n payload.action_string = beat.payload.action_string\n }\n\n return [BEAT_CTA_EVENT, payload]\n}\n\n/**\n * Send a beat post message to the parent window. Only posts when embedded in an\n * iframe (`window.self !== window.top`), mirroring Pulse's `sendPostMessage`\n * (default scheme `mx/pulse`). Returns false when not embedded or no target.\n */\nexport function sendBeatPostMessage(\n event: string,\n data: Record<string, unknown>,\n scheme = 'mx/pulse',\n): boolean {\n if (window.self === window.top) {\n return false\n }\n\n const message: PostMessageData = {\n metadata: data,\n mx: true,\n type: `${scheme}/${event}`,\n }\n\n return postMessageToParent(message)\n}\n\n/**\n * Navigate a mobile webview to a custom-scheme URL instead of posting a message.\n * Mirrors Pulse's `setWebviewURL` (default scheme `mx`).\n */\nexport function setWebviewURL(event: string, data?: Record<string, unknown>, scheme = 'mx'): void {\n let webviewUrl = `${scheme}://pulse/${event}`\n\n if (data) {\n webviewUrl += '?metadata=' + encodeURIComponent(JSON.stringify(data))\n }\n\n window.location.href = webviewUrl\n}\n\nexport interface SendBeatCtaOptions {\n /** True when running inside a native mobile webview. */\n isMobileWebview?: boolean\n /** Custom URL scheme for webview navigation (from client config). */\n webviewScheme?: string\n /** Current user guid, added to the metadata like the Pulse epic does. */\n userGuid?: string\n /** Operation string sent with the CTA (defaults to op_1). */\n op?: string\n}\n\n/**\n * Send a beat CTA to the host: builds the payload, adds `user_guid`, then either\n * posts a message to the host or navigates the webview. Mirrors the behaviour of\n * Pulse's `postMessages` epic (minus the RxJS buffering).\n */\nexport function sendBeatCta(\n beat: BeatCtaSource,\n { isMobileWebview, webviewScheme, userGuid, op }: SendBeatCtaOptions = {},\n): void {\n const [event, basePayload] = getBaseCtaPostMessage(beat, op)\n const metadata: BeatCtaPayload = {\n ...basePayload,\n ...(userGuid ? { user_guid: userGuid } : {}),\n }\n\n if (isMobileWebview) {\n setWebviewURL(event, metadata, webviewScheme)\n } else {\n sendBeatPostMessage(event, metadata)\n }\n}\n"],"mappings":"AAAA,SAAgB,IAAsB;AACpC,SAAI,OAAO,UAAU,OAAO,OAAO,WAC1B,OAAO,OAAO,SAAS,SAAS,IAEhC,SAAS;AAEpB;AASA,SAAgB,EAAoB,GAAmC;AACrE,QAAM,IAAU,EAAY,EAAE,QAAQ,wBAAwB,IAAI,GAC5D,IAAc,OAAO,UAAU,OAAO,UAAU;AAEtD,SAAI,KAAe,EAAY,eAAe,KAC5C,EAAY,YAAY,GAAS,CAAO,GACjC,MAGF;AACT;AAEA,SAAgB,EAAyB,GAA2B;AAOlE,SAAO,EAAoB;AAAA,IALzB,UAAU,EAAE,WAAW,EAAS;AAAA,IAChC,IAAI;AAAA,IACJ,MAAM;AAAA,EAGmB,CAAO;AACpC;AAEA,SAAgB,EAAwB,GAA2B;AAOjE,SAAO,EAAoB;AAAA,IALzB,UAAU,EAAY,UAAA,EAAS;AAAA,IAC/B,IAAI;AAAA,IACJ,MAAM;AAAA,EAGmB,CAAO;AACpC;AAYA,IAAa,IAAiB,YACjB,IAAmB;AAuBhC,SAAgB,EACd,GACA,IAAa,GACa;AAC1B,QAAM,IAA0B;AAAA,IAC9B,QAAQ;AAAA,IACR,WAAW,EAAK;AAAA,IAChB,eAAe,EAAK;AAAA,EACtB;AAEA,SAAI,GAAM,SAAS,kBACjB,EAAQ,gBAAgB,EAAK,QAAQ,gBAGhC,CAAC,GAAgB,CAAO;AACjC;AAOA,SAAgB,EACd,GACA,GACA,IAAS,YACA;AACT,SAAI,OAAO,SAAS,OAAO,MAClB,KASF,EAAoB;AAAA,IALzB,UAAU;AAAA,IACV,IAAI;AAAA,IACJ,MAAM,GAAG,CAAA,IAAU,CAAA;AAAA,EAGM,CAAO;AACpC;AAMA,SAAgB,EAAc,GAAe,GAAgC,IAAS,MAAY;AAChG,MAAI,IAAa,GAAG,CAAA,YAAkB,CAAA;AAEtC,EAAI,MACF,KAAc,eAAe,mBAAmB,KAAK,UAAU,CAAI,CAAC,IAGtE,OAAO,SAAS,OAAO;AACzB;AAkBA,SAAgB,EACd,GACA,EAAE,iBAAA,GAAiB,eAAA,GAAe,UAAA,GAAU,IAAA,EAAA,IAA2B,CAAC,GAClE;AACN,QAAM,CAAC,GAAO,CAAA,IAAe,EAAsB,GAAM,CAAE,GACrD,IAA2B;AAAA,IAC/B,GAAG;AAAA,IACH,GAAI,IAAW,EAAE,WAAW,EAAS,IAAI,CAAC;AAAA,EAC5C;AAEA,EAAI,IACF,EAAc,GAAO,GAAU,CAAa,IAE5C,EAAoB,GAAO,CAAQ;AAEvC"}
1
+ {"version":3,"file":"PostMessage.es.js","names":[],"sources":["../../../src/common/utils/PostMessage.ts"],"sourcesContent":["export function getReferrer(): string {\n if (window.opener && window.opener.location) {\n return window.opener.location.toString()\n } else {\n return document.referrer\n }\n}\n\nexport interface PostMessageData {\n metadata?: Record<string, any>\n mx: boolean\n type: string\n [key: string]: any\n}\n\nexport function postMessageToParent(message: PostMessageData): boolean {\n const postUrl = getReferrer().replace(/([^:]+:\\/\\/[^\\/]+).*/, '$1') // eslint-disable-line\n const otherWindow = window.parent || window.opener || false\n\n if (otherWindow && otherWindow.postMessage && postUrl) {\n otherWindow.postMessage(message, postUrl)\n return true\n }\n\n return false\n}\n\nexport function postInsightOnTransaction(beatGuid: string): boolean {\n const message: PostMessageData = {\n metadata: { beat_guid: beatGuid },\n mx: true,\n type: 'mx/moneyDashboard/insightOnTransaction',\n }\n\n return postMessageToParent(message)\n}\n\nexport function postClientConfiguredCta(template: string): boolean {\n const message: PostMessageData = {\n metadata: { template: template },\n mx: true,\n type: 'mx/pulse/client_configured_cta',\n }\n\n return postMessageToParent(message)\n}\n\n// ============================================================================\n// Beat CTA post messages (ported from Pulse: src/utils/PostMessage.js +\n// src/constants/PostMessage.js + src/epics/PostMessage.js).\n//\n// Scope: currently only the Save an extra $100 beat uses this. When a beat CTA\n// has no drilldown drawer, clicking it notifies the host app via a beat/cta\n// post message instead of opening a drawer. Native (mobile webview) hosts can't\n// receive post messages, so we navigate the webview to a custom-scheme URL.\n// ============================================================================\n\nexport const BEAT_CTA_EVENT = 'beat/cta'\nexport const BEAT_OPERATION_1 = 'op_1'\nexport const BEAT_OPERATION_2 = 'op_2'\nexport const BEAT_OPERATION_3 = 'op_3'\n\n/** Minimal beat shape needed to build a CTA post message. */\nexport interface BeatCtaSource {\n guid: string\n template: string\n payload?: { action_string?: string } | null\n}\n\nexport interface BeatCtaPayload {\n action: string\n beat_guid: string\n beat_template: string\n action_string?: string\n [key: string]: unknown\n}\n\n/**\n * Build the `[event, payload]` tuple for a beat CTA post message.\n * Mirrors Pulse's `getBaseCtaPostMessage`.\n */\nexport function getBaseCtaPostMessage(\n beat: BeatCtaSource,\n op: string = BEAT_OPERATION_1,\n): [string, BeatCtaPayload] {\n const payload: BeatCtaPayload = {\n action: op,\n beat_guid: beat.guid,\n beat_template: beat.template,\n }\n\n if (beat?.payload?.action_string) {\n payload.action_string = beat.payload.action_string\n }\n\n return [BEAT_CTA_EVENT, payload]\n}\n\n/**\n * Send a beat post message to the parent window. Only posts when embedded in an\n * iframe (`window.self !== window.top`), mirroring Pulse's `sendPostMessage`\n * (default scheme `mx/pulse`). Returns false when not embedded or no target.\n */\nexport function sendBeatPostMessage(\n event: string,\n data: Record<string, unknown>,\n scheme = 'mx/pulse',\n): boolean {\n if (window.self === window.top) {\n return false\n }\n\n const message: PostMessageData = {\n metadata: data,\n mx: true,\n type: `${scheme}/${event}`,\n }\n\n return postMessageToParent(message)\n}\n\n/**\n * Navigate a mobile webview to a custom-scheme URL instead of posting a message.\n * Mirrors Pulse's `setWebviewURL` (default scheme `mx`).\n */\nexport function setWebviewURL(event: string, data?: Record<string, unknown>, scheme = 'mx'): void {\n let webviewUrl = `${scheme}://pulse/${event}`\n\n if (data) {\n webviewUrl += '?metadata=' + encodeURIComponent(JSON.stringify(data))\n }\n\n window.location.href = webviewUrl\n}\n\nexport interface SendBeatCtaOptions {\n /** True when running inside a native mobile webview. */\n isMobileWebview?: boolean\n /** Custom URL scheme for webview navigation (from client config). */\n webviewScheme?: string\n /** Current user guid, added to the metadata like the Pulse epic does. */\n userGuid?: string\n /** Operation string sent with the CTA (defaults to op_1). */\n op?: string\n /** Post message event name (defaults to `beat/cta`). */\n event?: string\n /** Beat-specific fields merged into the metadata after the base payload and `user_guid`. */\n extras?: Record<string, unknown>\n}\n\n/**\n * Send a beat CTA to the host: builds the payload, adds `user_guid`, then either\n * posts a message to the host or navigates the webview. Mirrors the behaviour of\n * Pulse's `postMessages` epic (minus the RxJS buffering).\n */\nexport function sendBeatCta(\n beat: BeatCtaSource,\n { isMobileWebview, webviewScheme, userGuid, op, event, extras }: SendBeatCtaOptions = {},\n): void {\n const [defaultEvent, basePayload] = getBaseCtaPostMessage(beat, op)\n const metadata: BeatCtaPayload = {\n ...basePayload,\n ...(userGuid ? { user_guid: userGuid } : {}),\n ...extras,\n }\n const eventName = event || defaultEvent\n\n if (isMobileWebview) {\n setWebviewURL(eventName, metadata, webviewScheme)\n } else {\n sendBeatPostMessage(eventName, metadata)\n }\n}\n"],"mappings":"AAAA,SAAgB,IAAsB;AACpC,SAAI,OAAO,UAAU,OAAO,OAAO,WAC1B,OAAO,OAAO,SAAS,SAAS,IAEhC,SAAS;AAEpB;AASA,SAAgB,EAAoB,GAAmC;AACrE,QAAM,IAAU,EAAY,EAAE,QAAQ,wBAAwB,IAAI,GAC5D,IAAc,OAAO,UAAU,OAAO,UAAU;AAEtD,SAAI,KAAe,EAAY,eAAe,KAC5C,EAAY,YAAY,GAAS,CAAO,GACjC,MAGF;AACT;AAEA,SAAgB,EAAyB,GAA2B;AAOlE,SAAO,EAAoB;AAAA,IALzB,UAAU,EAAE,WAAW,EAAS;AAAA,IAChC,IAAI;AAAA,IACJ,MAAM;AAAA,EAGmB,CAAO;AACpC;AAEA,SAAgB,EAAwB,GAA2B;AAOjE,SAAO,EAAoB;AAAA,IALzB,UAAU,EAAY,UAAA,EAAS;AAAA,IAC/B,IAAI;AAAA,IACJ,MAAM;AAAA,EAGmB,CAAO;AACpC;AAYA,IAAa,IAAiB,YACjB,IAAmB,QACnB,IAAmB;AAsBhC,SAAgB,EACd,GACA,IAAa,GACa;AAC1B,QAAM,IAA0B;AAAA,IAC9B,QAAQ;AAAA,IACR,WAAW,EAAK;AAAA,IAChB,eAAe,EAAK;AAAA,EACtB;AAEA,SAAI,GAAM,SAAS,kBACjB,EAAQ,gBAAgB,EAAK,QAAQ,gBAGhC,CAAC,GAAgB,CAAO;AACjC;AAOA,SAAgB,EACd,GACA,GACA,IAAS,YACA;AACT,SAAI,OAAO,SAAS,OAAO,MAClB,KASF,EAAoB;AAAA,IALzB,UAAU;AAAA,IACV,IAAI;AAAA,IACJ,MAAM,GAAG,CAAA,IAAU,CAAA;AAAA,EAGM,CAAO;AACpC;AAMA,SAAgB,EAAc,GAAe,GAAgC,IAAS,MAAY;AAChG,MAAI,IAAa,GAAG,CAAA,YAAkB,CAAA;AAEtC,EAAI,MACF,KAAc,eAAe,mBAAmB,KAAK,UAAU,CAAI,CAAC,IAGtE,OAAO,SAAS,OAAO;AACzB;AAsBA,SAAgB,EACd,GACA,EAAE,iBAAA,GAAiB,eAAA,GAAe,UAAA,GAAU,IAAA,GAAI,OAAA,GAAO,QAAA,EAAA,IAA+B,CAAC,GACjF;AACN,QAAM,CAAC,GAAc,CAAA,IAAe,EAAsB,GAAM,CAAE,GAC5D,IAA2B;AAAA,IAC/B,GAAG;AAAA,IACH,GAAI,IAAW,EAAE,WAAW,EAAS,IAAI,CAAC;AAAA,IAC1C,GAAG;AAAA,EACL,GACM,IAAY,KAAS;AAE3B,EAAI,IACF,EAAc,GAAW,GAAU,CAAa,IAEhD,EAAoB,GAAW,CAAQ;AAE3C"}
@@ -161,6 +161,21 @@ export interface Description {
161
161
  text: string;
162
162
  html_text: string;
163
163
  }
164
+ /**
165
+ * Post message a CTA press sends to the host, resolved by the backend for the beat's current
166
+ * state. Absent/null = the backend has not described one: the frontend uses the template's
167
+ * interim `ctaPostMessages` entry if there is one, else sends no message. `payload` carries only
168
+ * beat-specific extras; the frontend always adds `beat_guid`, `beat_template`, `user_guid` and
169
+ * `action_string`.
170
+ */
171
+ export interface CtaPostMessageMetadata {
172
+ /** Post message event; defaults to `beat/cta`. */
173
+ event?: string | null;
174
+ /** Operation the host should perform, e.g. `op_1`, `op_2`, `op_3`. Defaults to `op_1`. */
175
+ action?: string | null;
176
+ /** Beat-specific fields merged into the message metadata (account ids, amounts, ...). */
177
+ payload?: Record<string, unknown> | null;
178
+ }
164
179
  export interface PrimaryCTA {
165
180
  label: string;
166
181
  block: string;
@@ -171,6 +186,7 @@ export interface PrimaryCTA {
171
186
  * null / absent / unknown means the CTA only opens its block or posts its message.
172
187
  */
173
188
  action_key?: string | null;
189
+ metadata?: CtaPostMessageMetadata | null;
174
190
  }
175
191
  export interface SecondaryCTA {
176
192
  label: string;
@@ -178,6 +194,7 @@ export interface SecondaryCTA {
178
194
  variant?: string | null;
179
195
  /** See `PrimaryCTA.action_key` (ditto `secondary_cta_action`). */
180
196
  action_key?: string | null;
197
+ metadata?: CtaPostMessageMetadata | null;
181
198
  }
182
199
  export interface Footer {
183
200
  /** V1: a pre-formatted date string. */
@@ -236,4 +253,12 @@ export interface InstanceSlot {
236
253
  * from `InsightsPayload.instance_slot_data` instead and leave this absent.
237
254
  */
238
255
  data_series?: InstanceSlotRow[];
256
+ /** Primary line on the hero card, e.g. "Epic Bank Checking, *1234". */
257
+ account_name?: string;
258
+ /** Secondary line beneath the name, e.g. "Checking Account" / "Credit Card". */
259
+ account_type?: string;
260
+ /** Status pill label, e.g. "Direct Deposit Not Set Up" / "Interest Rate: 19.99% APR". */
261
+ status_text?: string;
262
+ institution_guid?: string;
263
+ institution_name?: string;
239
264
  }
@@ -13,7 +13,7 @@ export type { Expense } from './Expense';
13
13
  export { ExpenseStatus, ScheduledPaymentTypes } from './Expense';
14
14
  export type { DynamicCopyElement, GlobalCopy } from './GlobalCopy';
15
15
  export { GoalType, MetaType, TrackType } from './Goal';
16
- export type { ThemedSVGImageProps, DrilldownData, DrilldownPayload, InsightsPayload, InstanceSlot, Pill, WidgetType, InstanceSlotRow, BlockType, Description, PrimaryCTA, SecondaryCTA, Subtitle, Footer, Logo, LogoRef, CategoryLogo, MerchantLogo, InstitutionLogo, Legends, } from './Insights';
16
+ export type { ThemedSVGImageProps, DrilldownData, DrilldownPayload, InsightsPayload, InstanceSlot, Pill, WidgetType, InstanceSlotRow, BlockType, Description, PrimaryCTA, CtaPostMessageMetadata, SecondaryCTA, Subtitle, Footer, Logo, LogoRef, CategoryLogo, MerchantLogo, InstitutionLogo, Legends, } from './Insights';
17
17
  export type { Goal, MonthlyCashFlowProfile, RetirementGoalAccount } from './Goal';
18
18
  export type { Debt } from './Debt';
19
19
  export type { GlobalCaptureException, GlobalErrorHandler, GlobalEventHandler } from './Handlers';
@@ -0,0 +1,16 @@
1
+ import { InsightsPayload } from '../../../../core';
2
+ interface DirectDepositBlockProps {
3
+ payload: InsightsPayload;
4
+ beatGuid?: string;
5
+ }
6
+ /**
7
+ * Direct Deposit component block — the shared hero visual for the Set Up
8
+ * Direct Deposit, Switch Direct Deposit, and Missing Interest Rate beats.
9
+ *
10
+ * The backend picks the design branch via `instance_slot.variant` and carries
11
+ * the account facts flat on `instance_slot` (V2 contract — no
12
+ * `instance_slot_data`). Everything variant-specific is flat on the layout
13
+ * config (`./layout.ts`); `DirectDepositCard` is a variant-agnostic hero.
14
+ */
15
+ declare const DirectDepositBlock: ({ payload }: DirectDepositBlockProps) => import("react/jsx-runtime").JSX.Element;
16
+ export default DirectDepositBlock;
@@ -0,0 +1,24 @@
1
+ import { DepositLogo as f } from "../../../components/ComponentBlocks/DepositLogo.es.js";
2
+ import { directDepositVariant as l, getLayoutConfig as D } from "./layout.es.js";
3
+ import g from "../../../components/DirectDepositCard.es.js";
4
+ import { jsx as o } from "react/jsx-runtime";
5
+ import { useTheme as _ } from "@mui/material/styles";
6
+ var L = ({ payload: i }) => {
7
+ const e = _(), { instance_slot: n } = i, { account_name: a, account_type: s, institution_guid: r, institution_name: c, status_text: m, variant: u } = n, t = D(e), p = t[u] ?? t[l.SetUpDirectDeposit];
8
+ return /* @__PURE__ */ o(g, {
9
+ ...p,
10
+ logo: /* @__PURE__ */ o(f, {
11
+ iconName: "account_balance",
12
+ institutionName: c ?? "",
13
+ institutionGuid: r ?? ""
14
+ }),
15
+ name: a,
16
+ statusLabel: m,
17
+ subtitle: s
18
+ });
19
+ };
20
+ export {
21
+ L as default
22
+ };
23
+
24
+ //# sourceMappingURL=DirectDepositBlock.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DirectDepositBlock.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/DirectDepositBlock/DirectDepositBlock.tsx"],"sourcesContent":["import { useTheme } from '@mui/material/styles'\n\nimport type { InsightsPayload } from '../../../../core'\n\nimport DirectDepositCard from '../../../components/DirectDepositCard'\n\nimport { directDepositVariant, getLayoutConfig, type DirectDepositVariant } from './layout'\nimport DepositLogo from '../../../components/ComponentBlocks/DepositLogo'\n\ninterface DirectDepositBlockProps {\n payload: InsightsPayload\n beatGuid?: string\n}\n\n/**\n * Direct Deposit component block — the shared hero visual for the Set Up\n * Direct Deposit, Switch Direct Deposit, and Missing Interest Rate beats.\n *\n * The backend picks the design branch via `instance_slot.variant` and carries\n * the account facts flat on `instance_slot` (V2 contract — no\n * `instance_slot_data`). Everything variant-specific is flat on the layout\n * config (`./layout.ts`); `DirectDepositCard` is a variant-agnostic hero.\n */\nconst DirectDepositBlock = ({ payload }: DirectDepositBlockProps) => {\n const theme = useTheme()\n const { instance_slot } = payload\n const { account_name, account_type, institution_guid, institution_name, status_text, variant } =\n instance_slot\n\n const layoutConfig = getLayoutConfig(theme)\n // Unknown backend variants degrade to the pending setup styling rather than\n // crashing (mirrors createVariantBlock's fallback philosophy).\n const config =\n layoutConfig[variant as DirectDepositVariant] ??\n layoutConfig[directDepositVariant.SetUpDirectDeposit]\n\n return (\n <DirectDepositCard\n {...config}\n logo={\n <DepositLogo\n iconName=\"account_balance\"\n institutionName={institution_name ?? ''}\n institutionGuid={institution_guid ?? ''}\n />\n }\n name={account_name}\n statusLabel={status_text}\n subtitle={account_type}\n />\n )\n}\n\nexport default DirectDepositBlock\n"],"mappings":";;;;;AAuBA,IAAM,IAAA,CAAsB,EAAE,SAAA,EAAA,MAAuC;AACnE,QAAM,IAAQ,EAAS,GACjB,EAAE,eAAA,EAAA,IAAkB,GACpB,EAAE,cAAA,GAAc,cAAA,GAAc,kBAAA,GAAkB,kBAAA,GAAkB,aAAA,GAAa,SAAA,EAAA,IACnF,GAEI,IAAe,EAAgB,CAAK,GAGpC,IACJ,EAAa,CAAA,KACb,EAAa,EAAqB,kBAAA;AAEpC,SACE,gBAAA,EAAC,GAAD;AAAA,IACE,GAAI;AAAA,IACJ,MACE,gBAAA,EAAC,GAAD;AAAA,MACE,UAAS;AAAA,MACT,iBAAiB,KAAoB;AAAA,MACrC,iBAAiB,KAAoB;AAAA,IACtC,CAAA;AAAA,IAEH,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EACX,CAAA;AAEL"}
@@ -0,0 +1 @@
1
+ export { default as DirectDepositBlock } from './DirectDepositBlock';
@@ -0,0 +1,28 @@
1
+ import { Theme } from '@mui/material/styles';
2
+ import { DirectDepositCardStyleProps, DirectDepositPillConfig } from '../../../components/DirectDepositCard';
3
+ /**
4
+ * Design branches of the Direct Deposit component block (Figma: "Direct
5
+ * Deposit" — Detailed Primary / Detailed Success / Deposit Completed):
6
+ *
7
+ * - `SetUpDirectDeposit` — pending setup: flat `primary.lighter` slot, neutral pill
8
+ * ("Direct Deposit Not Set Up").
9
+ * - `DirectDepositComplete` — Set Up / Switch Direct Deposit success: celebration wash +
10
+ * confetti, solid success pill with a check_circle glyph ("Direct Deposit Complete").
11
+ * - `MissingInterestRate` — pending rate: blue gradient slot, primary-tinted pill
12
+ * ("Unknown Interest Rate (APR)%").
13
+ * - `InterestRateAdded` — rate added: green gradient slot, solid success pill
14
+ * ("Interest Rate: 19.99% APR").
15
+ */
16
+ export declare const directDepositVariant: {
17
+ readonly SetUpDirectDeposit: "set_up_direct_deposit";
18
+ readonly DirectDepositComplete: "direct_deposit_complete";
19
+ readonly MissingInterestRate: "missing_interest_rate";
20
+ readonly InterestRateAdded: "interest_rate_added";
21
+ };
22
+ export type DirectDepositVariant = (typeof directDepositVariant)[keyof typeof directDepositVariant];
23
+ export declare const NEUTRAL_PILL: DirectDepositPillConfig;
24
+ /**
25
+ * Per-variant style props for `DirectDepositCard`, keyed by the backend
26
+ * `instance_slot.variant` (mirrors AccountBlock's `getLayoutConfig`).
27
+ */
28
+ export declare const getLayoutConfig: (theme: Theme) => Record<DirectDepositVariant, DirectDepositCardStyleProps>;
@@ -0,0 +1,63 @@
1
+ import { WARM_LIME_ACCENT_GRADIENT as o } from "../../../components/celebrationGradients.es.js";
2
+ var e = {
3
+ SetUpDirectDeposit: "set_up_direct_deposit",
4
+ DirectDepositComplete: "direct_deposit_complete",
5
+ MissingInterestRate: "missing_interest_rate",
6
+ InterestRateAdded: "interest_rate_added"
7
+ }, i = {
8
+ light: "linear-gradient(180deg, #A0B9F8 0%, #2C64EF 100%)",
9
+ dark: "linear-gradient(180deg, #1F46A7 0%, #6B92F4 100%)"
10
+ }, l = {
11
+ light: "linear-gradient(180deg, #94C9B7 0%, #12875E 100%)",
12
+ dark: "linear-gradient(180deg, #0D5F42 0%, #59AB8E 100%)"
13
+ }, n = {
14
+ bgcolor: "grey.200",
15
+ borderColor: "grey.200",
16
+ labelColor: "text.primary"
17
+ }, d = {
18
+ bgcolor: "primary.lighter",
19
+ borderColor: "primary.lighter",
20
+ labelColor: "text.primary"
21
+ }, t = {
22
+ bgcolor: "success.main",
23
+ borderColor: "success.main",
24
+ labelColor: "success.contrastText"
25
+ }, c = (a) => {
26
+ const r = a.palette.mode;
27
+ return {
28
+ [e.SetUpDirectDeposit]: {
29
+ bgcolor: "primary.lighter",
30
+ nameVariant: "body2",
31
+ pill: n
32
+ },
33
+ [e.DirectDepositComplete]: {
34
+ backgroundImage: o,
35
+ bgcolor: "background.paper",
36
+ nameVariant: "body2",
37
+ pill: {
38
+ ...t,
39
+ icon: "check_circle"
40
+ },
41
+ showConfetti: !0
42
+ },
43
+ [e.MissingInterestRate]: {
44
+ backgroundImage: i[r],
45
+ bgcolor: "background.paper",
46
+ nameVariant: "body1",
47
+ pill: d
48
+ },
49
+ [e.InterestRateAdded]: {
50
+ backgroundImage: l[r],
51
+ bgcolor: "background.paper",
52
+ nameVariant: "body1",
53
+ pill: t
54
+ }
55
+ };
56
+ };
57
+ export {
58
+ n as NEUTRAL_PILL,
59
+ e as directDepositVariant,
60
+ c as getLayoutConfig
61
+ };
62
+
63
+ //# sourceMappingURL=layout.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/DirectDepositBlock/layout.ts"],"sourcesContent":["import type { Theme } from '@mui/material/styles'\n\nimport { WARM_LIME_ACCENT_GRADIENT } from '../../../components/celebrationGradients'\nimport type {\n DirectDepositCardStyleProps,\n DirectDepositPillConfig,\n} from '../../../components/DirectDepositCard'\n\n/**\n * Design branches of the Direct Deposit component block (Figma: \"Direct\n * Deposit\" — Detailed Primary / Detailed Success / Deposit Completed):\n *\n * - `SetUpDirectDeposit` — pending setup: flat `primary.lighter` slot, neutral pill\n * (\"Direct Deposit Not Set Up\").\n * - `DirectDepositComplete` — Set Up / Switch Direct Deposit success: celebration wash +\n * confetti, solid success pill with a check_circle glyph (\"Direct Deposit Complete\").\n * - `MissingInterestRate` — pending rate: blue gradient slot, primary-tinted pill\n * (\"Unknown Interest Rate (APR)%\").\n * - `InterestRateAdded` — rate added: green gradient slot, solid success pill\n * (\"Interest Rate: 19.99% APR\").\n */\nexport const directDepositVariant = {\n SetUpDirectDeposit: 'set_up_direct_deposit',\n DirectDepositComplete: 'direct_deposit_complete',\n MissingInterestRate: 'missing_interest_rate',\n InterestRateAdded: 'interest_rate_added',\n} as const\n\nexport type DirectDepositVariant = (typeof directDepositVariant)[keyof typeof directDepositVariant]\n\n// Figma slot gradients (opaque, vertical). Light/dark pairs are taken from the\n// light and dark pages of the Missing Interest Rates frame — they are bespoke\n// blends with no theme token, so they stay literal hexes keyed by palette mode.\nconst MISSING_RATE_GRADIENTS = {\n light: 'linear-gradient(180deg, #A0B9F8 0%, #2C64EF 100%)',\n dark: 'linear-gradient(180deg, #1F46A7 0%, #6B92F4 100%)',\n} as const\n\nconst RATE_ADDED_GRADIENTS = {\n light: 'linear-gradient(180deg, #94C9B7 0%, #12875E 100%)',\n dark: 'linear-gradient(180deg, #0D5F42 0%, #59AB8E 100%)',\n} as const\n\n// Figma light-mode references: neutral pill #ececec, primary-tinted pill\n// #dfe8fd (`primary.lighter`), solid success pill #12875e (`success.main`).\nexport const NEUTRAL_PILL: DirectDepositPillConfig = {\n bgcolor: 'grey.200',\n borderColor: 'grey.200',\n labelColor: 'text.primary',\n}\n\nconst PRIMARY_TINT_PILL: DirectDepositPillConfig = {\n bgcolor: 'primary.lighter',\n borderColor: 'primary.lighter',\n labelColor: 'text.primary',\n}\n\nconst SUCCESS_PILL: DirectDepositPillConfig = {\n bgcolor: 'success.main',\n borderColor: 'success.main',\n labelColor: 'success.contrastText',\n}\n\n/**\n * Per-variant style props for `DirectDepositCard`, keyed by the backend\n * `instance_slot.variant` (mirrors AccountBlock's `getLayoutConfig`).\n */\nexport const getLayoutConfig = (\n theme: Theme,\n): Record<DirectDepositVariant, DirectDepositCardStyleProps> => {\n const mode = theme.palette.mode\n\n return {\n [directDepositVariant.SetUpDirectDeposit]: {\n bgcolor: 'primary.lighter',\n nameVariant: 'body2',\n pill: NEUTRAL_PILL,\n },\n [directDepositVariant.DirectDepositComplete]: {\n backgroundImage: WARM_LIME_ACCENT_GRADIENT,\n bgcolor: 'background.paper',\n nameVariant: 'body2',\n // Figma 1941:192796: 16px check_circle inside the complete pill.\n pill: { ...SUCCESS_PILL, icon: 'check_circle' },\n showConfetti: true,\n },\n [directDepositVariant.MissingInterestRate]: {\n backgroundImage: MISSING_RATE_GRADIENTS[mode],\n bgcolor: 'background.paper',\n nameVariant: 'body1',\n pill: PRIMARY_TINT_PILL,\n },\n [directDepositVariant.InterestRateAdded]: {\n backgroundImage: RATE_ADDED_GRADIENTS[mode],\n bgcolor: 'background.paper',\n nameVariant: 'body1',\n pill: SUCCESS_PILL,\n },\n }\n}\n"],"mappings":";AAqBA,IAAa,IAAuB;AAAA,EAClC,oBAAoB;AAAA,EACpB,uBAAuB;AAAA,EACvB,qBAAqB;AAAA,EACrB,mBAAmB;AACrB,GAOM,IAAyB;AAAA,EAC7B,OAAO;AAAA,EACP,MAAM;AACR,GAEM,IAAuB;AAAA,EAC3B,OAAO;AAAA,EACP,MAAM;AACR,GAIa,IAAwC;AAAA,EACnD,SAAS;AAAA,EACT,aAAa;AAAA,EACb,YAAY;AACd,GAEM,IAA6C;AAAA,EACjD,SAAS;AAAA,EACT,aAAa;AAAA,EACb,YAAY;AACd,GAEM,IAAwC;AAAA,EAC5C,SAAS;AAAA,EACT,aAAa;AAAA,EACb,YAAY;AACd,GAMa,IAAA,CACX,MAC8D;AAC9D,QAAM,IAAO,EAAM,QAAQ;AAE3B,SAAO;AAAA,IACJ,CAAA,EAAqB,kBAAA,GAAqB;AAAA,MACzC,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM;AAAA,IACR;AAAA,IACC,CAAA,EAAqB,qBAAA,GAAwB;AAAA,MAC5C,iBAAiB;AAAA,MACjB,SAAS;AAAA,MACT,aAAa;AAAA,MAEb,MAAM;AAAA,QAAE,GAAG;AAAA,QAAc,MAAM;AAAA,MAAe;AAAA,MAC9C,cAAc;AAAA,IAChB;AAAA,IACC,CAAA,EAAqB,mBAAA,GAAsB;AAAA,MAC1C,iBAAiB,EAAuB,CAAA;AAAA,MACxC,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM;AAAA,IACR;AAAA,IACC,CAAA,EAAqB,iBAAA,GAAoB;AAAA,MACxC,iBAAiB,EAAqB,CAAA;AAAA,MACtC,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM;AAAA,IACR;AAAA,EACF;AACF"}
@@ -1,5 +1,6 @@
1
1
  export * from './AccountBlock';
2
2
  export * from './AccountSwitchBlock';
3
+ export * from './DirectDepositBlock';
3
4
  export * from './BudgetBlock';
4
5
  export * from './SaveExtraBlock';
5
6
  export * from './TransactionBlock';
@@ -7,6 +7,12 @@ interface AccountHeroCardProps {
7
7
  name: ReactNode;
8
8
  /** Optional secondary line beneath the name, e.g. "Checking Account". */
9
9
  subtitle?: ReactNode;
10
+ /**
11
+ * Name typography. Figma: Set Up/Switch Direct Deposit use body2 metrics
12
+ * (13px / lh 16, default); Missing Interest Rate uses body1 (15px / lh 20).
13
+ * Both render at weight 600.
14
+ */
15
+ nameVariant?: 'body1' | 'body2';
10
16
  /** Status element beneath the text (e.g. a `<StatusPill>`). */
11
17
  status?: ReactNode;
12
18
  /** Decorative backdrop behind the card (e.g. a `<Confetti>` burst). */
@@ -31,5 +37,5 @@ interface AccountHeroCardProps {
31
37
  * Figma: Set Up Direct Deposit (default + complete) and Switch Direct Deposit
32
38
  * (complete) Content. Scope is the Content section only.
33
39
  */
34
- declare const AccountHeroCard: ({ backdrop, backgroundImage, bgcolor, logo, name, status, subtitle, sx, }: AccountHeroCardProps) => import("react/jsx-runtime").JSX.Element;
40
+ declare const AccountHeroCard: ({ backdrop, backgroundImage, bgcolor, logo, name, nameVariant, status, subtitle, sx, }: AccountHeroCardProps) => import("react/jsx-runtime").JSX.Element;
35
41
  export default AccountHeroCard;
@@ -1,22 +1,21 @@
1
- import { getLogoElevation as h } from "./logoShadow.es.js";
1
+ import { getLogoElevation as m } from "./logoShadow.es.js";
2
2
  import r from "@mui/material/Stack";
3
3
  import { Text as d } from "@mxenabled/mxui";
4
4
  import { jsx as t, jsxs as e } from "react/jsx-runtime";
5
5
  import i from "@mui/material/Box";
6
- var w = ({ backdrop: n, backgroundImage: o, bgcolor: s = "primary.lighter", logo: p, name: c, status: a, subtitle: l, sx: x }) => /* @__PURE__ */ e(i, {
6
+ var v = ({ backdrop: n, backgroundImage: o, bgcolor: s = "primary.lighter", logo: p, name: c, nameVariant: x = "body2", status: a, subtitle: l, sx: h }) => /* @__PURE__ */ e(i, {
7
7
  sx: {
8
8
  alignItems: "center",
9
9
  bgcolor: s,
10
10
  ...o && { backgroundImage: o },
11
11
  display: "flex",
12
12
  flexDirection: "column",
13
- overflow: "hidden",
14
13
  pb: 16,
15
14
  position: "relative",
16
15
  pt: 41,
17
16
  px: 16,
18
17
  width: "100%",
19
- ...x
18
+ ...h
20
19
  },
21
20
  children: [n && /* @__PURE__ */ t(i, {
22
21
  "aria-hidden": !0,
@@ -31,7 +30,7 @@ var w = ({ backdrop: n, backgroundImage: o, bgcolor: s = "primary.lighter", logo
31
30
  alignItems: "center",
32
31
  bgcolor: "background.paper",
33
32
  borderRadius: "8px",
34
- boxShadow: h,
33
+ boxShadow: m,
35
34
  gap: 16,
36
35
  pb: 16,
37
36
  position: "relative",
@@ -65,7 +64,7 @@ var w = ({ backdrop: n, backgroundImage: o, bgcolor: s = "primary.lighter", logo
65
64
  children: [/* @__PURE__ */ t(d, {
66
65
  sx: { fontWeight: 600 },
67
66
  truncate: !0,
68
- variant: "body2",
67
+ variant: x,
69
68
  children: c
70
69
  }), l && /* @__PURE__ */ t(d, {
71
70
  color: "text.secondary",
@@ -85,7 +84,7 @@ var w = ({ backdrop: n, backgroundImage: o, bgcolor: s = "primary.lighter", logo
85
84
  })]
86
85
  });
87
86
  export {
88
- w as default
87
+ v as default
89
88
  };
90
89
 
91
90
  //# sourceMappingURL=AccountHeroCard.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AccountHeroCard.es.js","names":[],"sources":["../../../src/insights-v2/components/AccountHeroCard.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\n\nimport Box from '@mui/material/Box'\nimport Stack from '@mui/material/Stack'\nimport type { SxProps } from '@mui/material/styles'\n\nimport { Text } from '@mxenabled/mxui'\n\nimport { getLogoElevation } from './logoShadow'\n\n// Figma: the logo overhangs the white card's top edge by 25px and the slot pads\n// 16px above that overhang (so `pt = overhang + 16`).\nconst LOGO_OVERHANG = 25\n\ninterface AccountHeroCardProps {\n /** Central account/institution logo, rendered overhanging the card's top edge. */\n logo: ReactNode\n /** Primary line, e.g. \"Epic Bank Checking, *1234\". */\n name: ReactNode\n /** Optional secondary line beneath the name, e.g. \"Checking Account\". */\n subtitle?: ReactNode\n /** Status element beneath the text (e.g. a `<StatusPill>`). */\n status?: ReactNode\n /** Decorative backdrop behind the card (e.g. a `<Confetti>` burst). */\n backdrop?: ReactNode\n /** Slot surface color token. Default `primary.lighter` (Figma's tinted slot,\n * theme-aware: light-blue in light mode, navy in dark). */\n bgcolor?: string\n /**\n * Optional decorative wash layered over `bgcolor` (e.g. a celebration\n * gradient). Figma's gradient is ~20% opacity over a white base, so this is a\n * `backgroundImage` on top of `bgcolor`, not a replacement — pass\n * `bgcolor=\"background.paper\"` with it for the complete state.\n */\n backgroundImage?: string\n sx?: SxProps\n}\n\n/**\n * A centered account hero: an overhanging institution logo above a white card\n * with a name, optional subtitle, and a status slot, over a tinted (or\n * gradient + confetti) slot.\n *\n * Figma: Set Up Direct Deposit (default + complete) and Switch Direct Deposit\n * (complete) Content. Scope is the Content section only.\n */\nconst AccountHeroCard = ({\n backdrop,\n backgroundImage,\n bgcolor = 'primary.lighter',\n logo,\n name,\n status,\n subtitle,\n sx,\n}: AccountHeroCardProps) => (\n <Box\n sx={{\n alignItems: 'center',\n bgcolor,\n ...(backgroundImage && { backgroundImage }),\n display: 'flex',\n flexDirection: 'column',\n overflow: 'hidden',\n pb: 16,\n position: 'relative',\n pt: LOGO_OVERHANG + 16,\n px: 16,\n width: '100%',\n ...sx,\n }}\n >\n {backdrop && (\n <Box aria-hidden={true} sx={{ inset: 0, position: 'absolute', zIndex: 0 }}>\n {backdrop}\n </Box>\n )}\n <Stack\n sx={{\n alignItems: 'center',\n // Theme-aware card surface (white in light, dark surface in dark) — not\n // `common.white`, which stays white and breaks dark mode.\n bgcolor: 'background.paper',\n borderRadius: '8px',\n // Figma: soft card drop-shadow (0 2px 8px rgba(0,0,0,0.12)).\n boxShadow: getLogoElevation,\n gap: 16,\n pb: 16,\n position: 'relative',\n pt: 36,\n px: 16,\n width: '100%',\n zIndex: 1,\n }}\n >\n <Box\n sx={{\n display: 'flex',\n left: '50%',\n position: 'absolute',\n top: -LOGO_OVERHANG,\n transform: 'translateX(-50%)',\n }}\n >\n {logo}\n </Box>\n <Stack sx={{ alignItems: 'center', gap: 12, minWidth: 0, width: '100%' }}>\n <Stack sx={{ alignItems: 'center', minWidth: 0, width: '100%' }}>\n {/* Figma name style: body2 metrics (13px / lineHeight 16) at weight\n 600. MXUI `bold` renders 700, so set fontWeight explicitly. */}\n <Text sx={{ fontWeight: 600 }} truncate={true} variant=\"body2\">\n {name}\n </Text>\n {subtitle && (\n <Text color=\"text.secondary\" truncate={true} variant=\"caption\">\n {subtitle}\n </Text>\n )}\n </Stack>\n {/* Center the status regardless of its own alignment (StatusPill\n defaults to `alignSelf: flex-start` for left-aligned contexts). */}\n {status && (\n <Box sx={{ display: 'flex', justifyContent: 'center', width: '100%' }}>{status}</Box>\n )}\n </Stack>\n </Stack>\n </Box>\n)\n\nexport default AccountHeroCard\n"],"mappings":";;;;;AA8CA,IAAM,IAAA,CAAmB,EACvB,UAAA,GACA,iBAAA,GACA,SAAA,IAAU,mBACV,MAAA,GACA,MAAA,GACA,QAAA,GACA,UAAA,GACA,IAAA,EAAA,MAEA,gBAAA,EAAC,GAAD;AAAA,EACE,IAAI;AAAA,IACF,YAAY;AAAA,IACZ,SAAA;AAAA,IACA,GAAI,KAAmB,EAAE,iBAAA,EAAgB;AAAA,IACzC,SAAS;AAAA,IACT,eAAe;AAAA,IACf,UAAU;AAAA,IACV,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,GAAG;AAAA,EACL;AAAA,EAdF,UAAA,CAgBG,KACC,gBAAA,EAAC,GAAD;AAAA,IAAK,eAAa;AAAA,IAAM,IAAI;AAAA,MAAE,OAAO;AAAA,MAAG,UAAU;AAAA,MAAY,QAAQ;AAAA,IAAE;AAAA,IACrE,UAAA;AAAA,EACE,CAAA,GAEP,gBAAA,EAAC,GAAD;AAAA,IACE,IAAI;AAAA,MACF,YAAY;AAAA,MAGZ,SAAS;AAAA,MACT,cAAc;AAAA,MAEd,WAAW;AAAA,MACX,KAAK;AAAA,MACL,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,QAAQ;AAAA,IACV;AAAA,IAhBF,UAAA,CAkBE,gBAAA,EAAC,GAAD;AAAA,MACE,IAAI;AAAA,QACF,SAAS;AAAA,QACT,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,WAAW;AAAA,MACb;AAAA,MAEC,UAAA;AAAA,IACE,CAAA,GACL,gBAAA,EAAC,GAAD;AAAA,MAAO,IAAI;AAAA,QAAE,YAAY;AAAA,QAAU,KAAK;AAAA,QAAI,UAAU;AAAA,QAAG,OAAO;AAAA,MAAO;AAAA,MAAvE,UAAA,CACE,gBAAA,EAAC,GAAD;AAAA,QAAO,IAAI;AAAA,UAAE,YAAY;AAAA,UAAU,UAAU;AAAA,UAAG,OAAO;AAAA,QAAO;AAAA,QAA9D,UAAA,CAGE,gBAAA,EAAC,GAAD;AAAA,UAAM,IAAI,EAAE,YAAY,IAAI;AAAA,UAAG,UAAU;AAAA,UAAM,SAAQ;AAAA,UACpD,UAAA;AAAA,QACG,CAAA,GACL,KACC,gBAAA,EAAC,GAAD;AAAA,UAAM,OAAM;AAAA,UAAiB,UAAU;AAAA,UAAM,SAAQ;AAAA,UAClD,UAAA;AAAA,QACG,CAAA,CAEH;AAAA,MAGN,CAAA,GAAA,KACC,gBAAA,EAAC,GAAD;AAAA,QAAK,IAAI;AAAA,UAAE,SAAS;AAAA,UAAQ,gBAAgB;AAAA,UAAU,OAAO;AAAA,QAAO;AAAA,QAAI,UAAA;AAAA,MAAY,CAAA,CAEjF;AAAA,IACF,CAAA,CAAA;AAAA,EACJ,CAAA,CAAA"}
1
+ {"version":3,"file":"AccountHeroCard.es.js","names":[],"sources":["../../../src/insights-v2/components/AccountHeroCard.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\n\nimport Box from '@mui/material/Box'\nimport Stack from '@mui/material/Stack'\nimport type { SxProps } from '@mui/material/styles'\n\nimport { Text } from '@mxenabled/mxui'\n\nimport { getLogoElevation } from './logoShadow'\n\n// Figma: the logo overhangs the white card's top edge by 25px and the slot pads\n// 16px above that overhang (so `pt = overhang + 16`).\nconst LOGO_OVERHANG = 25\n\ninterface AccountHeroCardProps {\n /** Central account/institution logo, rendered overhanging the card's top edge. */\n logo: ReactNode\n /** Primary line, e.g. \"Epic Bank Checking, *1234\". */\n name: ReactNode\n /** Optional secondary line beneath the name, e.g. \"Checking Account\". */\n subtitle?: ReactNode\n /**\n * Name typography. Figma: Set Up/Switch Direct Deposit use body2 metrics\n * (13px / lh 16, default); Missing Interest Rate uses body1 (15px / lh 20).\n * Both render at weight 600.\n */\n nameVariant?: 'body1' | 'body2'\n /** Status element beneath the text (e.g. a `<StatusPill>`). */\n status?: ReactNode\n /** Decorative backdrop behind the card (e.g. a `<Confetti>` burst). */\n backdrop?: ReactNode\n /** Slot surface color token. Default `primary.lighter` (Figma's tinted slot,\n * theme-aware: light-blue in light mode, navy in dark). */\n bgcolor?: string\n /**\n * Optional decorative wash layered over `bgcolor` (e.g. a celebration\n * gradient). Figma's gradient is ~20% opacity over a white base, so this is a\n * `backgroundImage` on top of `bgcolor`, not a replacement — pass\n * `bgcolor=\"background.paper\"` with it for the complete state.\n */\n backgroundImage?: string\n sx?: SxProps\n}\n\n/**\n * A centered account hero: an overhanging institution logo above a white card\n * with a name, optional subtitle, and a status slot, over a tinted (or\n * gradient + confetti) slot.\n *\n * Figma: Set Up Direct Deposit (default + complete) and Switch Direct Deposit\n * (complete) Content. Scope is the Content section only.\n */\nconst AccountHeroCard = ({\n backdrop,\n backgroundImage,\n bgcolor = 'primary.lighter',\n logo,\n name,\n nameVariant = 'body2',\n status,\n subtitle,\n sx,\n}: AccountHeroCardProps) => (\n <Box\n sx={{\n alignItems: 'center',\n bgcolor,\n ...(backgroundImage && { backgroundImage }),\n display: 'flex',\n flexDirection: 'column',\n pb: 16,\n position: 'relative',\n pt: LOGO_OVERHANG + 16,\n px: 16,\n width: '100%',\n ...sx,\n }}\n >\n {backdrop && (\n <Box aria-hidden={true} sx={{ inset: 0, position: 'absolute', zIndex: 0 }}>\n {backdrop}\n </Box>\n )}\n <Stack\n sx={{\n alignItems: 'center',\n // Theme-aware card surface (white in light, dark surface in dark) — not\n // `common.white`, which stays white and breaks dark mode.\n bgcolor: 'background.paper',\n borderRadius: '8px',\n // Figma: soft card drop-shadow (0 2px 8px rgba(0,0,0,0.12)).\n boxShadow: getLogoElevation,\n gap: 16,\n pb: 16,\n position: 'relative',\n pt: 36,\n px: 16,\n width: '100%',\n zIndex: 1,\n }}\n >\n <Box\n sx={{\n display: 'flex',\n left: '50%',\n position: 'absolute',\n top: -LOGO_OVERHANG,\n transform: 'translateX(-50%)',\n }}\n >\n {logo}\n </Box>\n <Stack sx={{ alignItems: 'center', gap: 12, minWidth: 0, width: '100%' }}>\n <Stack sx={{ alignItems: 'center', minWidth: 0, width: '100%' }}>\n {/* Figma name style: body2 (13/16) or body1 (15/20) metrics at weight\n 600. MXUI `bold` renders 700, so set fontWeight explicitly. */}\n <Text sx={{ fontWeight: 600 }} truncate={true} variant={nameVariant}>\n {name}\n </Text>\n {subtitle && (\n <Text color=\"text.secondary\" truncate={true} variant=\"caption\">\n {subtitle}\n </Text>\n )}\n </Stack>\n {/* Center the status regardless of its own alignment (StatusPill\n defaults to `alignSelf: flex-start` for left-aligned contexts). */}\n {status && (\n <Box sx={{ display: 'flex', justifyContent: 'center', width: '100%' }}>{status}</Box>\n )}\n </Stack>\n </Stack>\n </Box>\n)\n\nexport default AccountHeroCard\n"],"mappings":";;;;;AAoDA,IAAM,IAAA,CAAmB,EACvB,UAAA,GACA,iBAAA,GACA,SAAA,IAAU,mBACV,MAAA,GACA,MAAA,GACA,aAAA,IAAc,SACd,QAAA,GACA,UAAA,GACA,IAAA,EAAA,MAEA,gBAAA,EAAC,GAAD;AAAA,EACE,IAAI;AAAA,IACF,YAAY;AAAA,IACZ,SAAA;AAAA,IACA,GAAI,KAAmB,EAAE,iBAAA,EAAgB;AAAA,IACzC,SAAS;AAAA,IACT,eAAe;AAAA,IACf,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,GAAG;AAAA,EACL;AAAA,EAbF,UAAA,CAeG,KACC,gBAAA,EAAC,GAAD;AAAA,IAAK,eAAa;AAAA,IAAM,IAAI;AAAA,MAAE,OAAO;AAAA,MAAG,UAAU;AAAA,MAAY,QAAQ;AAAA,IAAE;AAAA,IACrE,UAAA;AAAA,EACE,CAAA,GAEP,gBAAA,EAAC,GAAD;AAAA,IACE,IAAI;AAAA,MACF,YAAY;AAAA,MAGZ,SAAS;AAAA,MACT,cAAc;AAAA,MAEd,WAAW;AAAA,MACX,KAAK;AAAA,MACL,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,QAAQ;AAAA,IACV;AAAA,IAhBF,UAAA,CAkBE,gBAAA,EAAC,GAAD;AAAA,MACE,IAAI;AAAA,QACF,SAAS;AAAA,QACT,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,WAAW;AAAA,MACb;AAAA,MAEC,UAAA;AAAA,IACE,CAAA,GACL,gBAAA,EAAC,GAAD;AAAA,MAAO,IAAI;AAAA,QAAE,YAAY;AAAA,QAAU,KAAK;AAAA,QAAI,UAAU;AAAA,QAAG,OAAO;AAAA,MAAO;AAAA,MAAvE,UAAA,CACE,gBAAA,EAAC,GAAD;AAAA,QAAO,IAAI;AAAA,UAAE,YAAY;AAAA,UAAU,UAAU;AAAA,UAAG,OAAO;AAAA,QAAO;AAAA,QAA9D,UAAA,CAGE,gBAAA,EAAC,GAAD;AAAA,UAAM,IAAI,EAAE,YAAY,IAAI;AAAA,UAAG,UAAU;AAAA,UAAM,SAAS;AAAA,UACrD,UAAA;AAAA,QACG,CAAA,GACL,KACC,gBAAA,EAAC,GAAD;AAAA,UAAM,OAAM;AAAA,UAAiB,UAAU;AAAA,UAAM,SAAQ;AAAA,UAClD,UAAA;AAAA,QACG,CAAA,CAEH;AAAA,MAGN,CAAA,GAAA,KACC,gBAAA,EAAC,GAAD;AAAA,QAAK,IAAI;AAAA,UAAE,SAAS;AAAA,UAAQ,gBAAgB;AAAA,UAAU,OAAO;AAAA,QAAO;AAAA,QAAI,UAAA;AAAA,MAAY,CAAA,CAEjF;AAAA,IACF,CAAA,CAAA;AAAA,EACJ,CAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"BaseLayout.es.js","names":[],"sources":["../../../src/insights-v2/components/BaseLayout.tsx"],"sourcesContent":["import { observer } from 'mobx-react-lite'\n\nimport Box from '@mui/material/Box'\nimport Button from '@mui/material/Button'\nimport Card from '@mui/material/Card'\nimport Stack from '@mui/material/Stack'\n\nimport { ChevronRight } from '@mxenabled/mx-icons'\nimport { P, Text } from '@mxenabled/mxui'\n\nimport { blocks } from '../mappings/blocks'\nimport { actionBlocksKey } from '../mappings/actionBlocksKey'\nimport { isContactSupportCtaDisabled } from '../actionBlocks/ContactSupportActionBlock'\nimport { logoFromRef } from './shared/EntityLogo'\n\nimport Footer from './Footer'\nimport Header from './Header'\nimport FeedbackBar from './FeedbackBar'\nimport FeedbackDialog from './FeedbackDialog'\nimport DismissInsightDialog from './DismissInsightDialog'\nimport HiddenConfirmationCard from './HiddenConfirmationCard'\nimport ErrorCard from './ErrorCard'\nimport LoadingCard from './LoadingCard'\nimport { ObsolesceBanner, type ObsolesceBannerState } from './ObsolesceBanner'\nimport { useAppConfig, useGlobalCopyStore } from '../../common'\nimport type { Beat, PrimaryCTA, SecondaryCTA } from '../../core'\nimport { BeatActionsProvider, type BeatActions } from '../beatActions'\nimport { ActionBlockLayer } from '../actionBlocks/ActionBlockLayer'\nimport { useBeatCtaActions } from '../ctaActions'\nimport { useBeatFeedbackFlow } from '../hooks/useBeatFeedbackFlow'\n\nexport interface ObsoleteState {\n state: ObsolesceBannerState\n onRefresh: () => void\n onDismiss: () => void\n}\n\ninterface BaseLayoutProps {\n beat: Beat\n beatActions?: BeatActions\n obsolete?: ObsoleteState\n /** Swap only the block slot for a LoadingCard (e.g. while a sampled beat loads). */\n isLoading?: boolean\n /** Replace the entire card with an ErrorCard (e.g. when the sample fails to load). */\n isError?: boolean\n}\n\nconst NO_BEAT_ACTIONS: BeatActions = {}\n\nconst OBSOLETE_OVERLAY_SX = {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n backgroundColor: 'background.default',\n opacity: 0.7,\n zIndex: 1,\n} as const\n\n// Figma (Mini | Large Transaction): a left-aligned link under the description. The 2px padding plus\n// the CTA row's 16 lines the label up with the description's 18. The label is not a Button, so it\n// carries the theme's MuiButton look itself: semi-bold, no uppercase (typography.button uppercases),\n// and the medium Button's 44px height with the text centred.\nconst MINI_CTA_SX = {\n alignItems: 'center',\n alignSelf: 'flex-start',\n display: 'flex',\n fontWeight: 600,\n height: 44,\n px: 2,\n textTransform: 'none',\n} as const\n\nconst BaseLayout = observer(\n ({\n beat,\n beatActions = NO_BEAT_ACTIONS,\n obsolete,\n isLoading = false,\n isError = false,\n }: BaseLayoutProps) => {\n const copy = useGlobalCopyStore()\n const { config } = useAppConfig()\n const flow = useBeatFeedbackFlow(beat, beatActions)\n const {\n runCta: handleCtaClick,\n primary: primaryCtaState,\n secondary: secondaryCtaState,\n } = useBeatCtaActions(\n beat,\n beatActions,\n beat.insights_payload?.primary_cta,\n beat.insights_payload?.secondary_cta,\n )\n\n // Error replaces the entire card; loading only swaps the block slot (below).\n if (isError) return <ErrorCard />\n\n const insights_payload = beat.insights_payload\n\n if (!insights_payload) return null\n if (flow.cardState === 'dismissed') return null\n\n const {\n instance_slot,\n primary_cta,\n secondary_cta,\n sub_title,\n title,\n widget_type,\n guid,\n dismissed_at,\n } = insights_payload\n const { block } = instance_slot\n\n // V1 sends `sub_title: { text, logo }`. The V2 envelope flattens it to a `subtitle` string\n // with the logo promoted to a payload-level `LogoRef` (an entity guid or a status icon), so\n // rebuild the shape `Header`/`SubHeader` already render. `sub_title` wins when a beat sends both.\n const subtitle =\n sub_title ??\n (insights_payload.subtitle\n ? {\n logo: logoFromRef(insights_payload.logo),\n text: insights_payload.subtitle,\n }\n : undefined)\n\n // CTA presses go through the ctaActions runner (../ctaActions): a backend `action_key` runs\n // its step, otherwise a `block` opens its drawer, else the CTA posts its message.\n // `contact_support_block` bypasses the runner: the help flow is host-supplied via\n // `beatActions.onContactSupport`, and the CTA is disabled without it.\n const isCtaDisabled = (ctaBlock: string | null | undefined) =>\n isContactSupportCtaDisabled(ctaBlock, config, beatActions.onContactSupport)\n\n const onCtaClick = async (slot: 'primary' | 'secondary', cta: PrimaryCTA | SecondaryCTA) => {\n if (isCtaDisabled(cta.block)) return\n\n if (cta.block === actionBlocksKey.CONTACT_SUPPORT_ACTION_BLOCK) {\n beatActions.onContactSupport?.()\n return\n }\n\n await handleCtaClick(slot, cta)\n }\n\n const Block = blocks[block as keyof typeof blocks]\n\n const isMini = widget_type === 'mini'\n const obsoleteCopy = copy.insights_feed?.general\n const isObsoleteDimmed =\n obsolete?.state === 'not_refreshable' && !dismissed_at && !!obsoleteCopy\n\n return (\n <BeatActionsProvider value={flow.wrappedActions}>\n <Stack sx={{ mb: 16 }}>\n {flow.cardState === 'confirming' ? (\n <HiddenConfirmationCard\n onClose={flow.collapseConfirmation}\n onLeaveFeedback={flow.openHideSurvey}\n onUndo={flow.undoDismiss}\n />\n ) : (\n <>\n {obsolete && obsoleteCopy && <ObsolesceBanner {...obsolete} copy={obsoleteCopy} />}\n <Card\n inert={isObsoleteDimmed}\n sx={{\n ...(isObsoleteDimmed && {\n position: 'relative',\n zIndex: 2,\n pointerEvents: 'none',\n }),\n }}\n >\n {isObsoleteDimmed && <Box sx={OBSOLETE_OVERLAY_SX} />}\n <Header isMini={isMini} subtitle={subtitle} title={title ?? ''} />\n {isLoading ? (\n <LoadingCard />\n ) : (\n Block && <Block beatGuid={guid} payload={insights_payload} />\n )}\n\n <Stack sx={{ gap: 6, pb: 16, pt: 12, px: 16 }}>\n <P\n dangerouslySetInnerHTML={{\n __html: insights_payload.description.html_text,\n }}\n variant=\"subtitle2\"\n />\n {/* TODO: Migrate to insights_payload.in_description_cta once backend provides it */}\n {beat?.in_description_cta && (\n <Button\n endIcon={<ChevronRight />}\n onClick={() => {}}\n sx={{ height: 24, p: 4, width: 'max-content' }}\n >\n {beat.in_description_cta}\n </Button>\n )}\n </Stack>\n\n {primary_cta?.label && (\n <Stack sx={{ gap: 8, pb: 16, px: 16 }}>\n {isMini ? (\n // Mini is a tap target, as in V1: the card, not this label, is the control. The label\n // is deliberately not a button, so a tap on it reaches the host's card handler (Pulse\n // posts `carousel/cta`, the same redirect a V1 mini card sends) instead of opening\n // the action drawer the full card's CTA opens.\n <Text color=\"primary.main\" sx={MINI_CTA_SX} variant=\"button\">\n {primary_cta.label}\n </Text>\n ) : (\n <Button\n aria-disabled={isCtaDisabled(primary_cta.block) || primaryCtaState.disabled}\n disabled={primaryCtaState.disabled}\n onClick={() => onCtaClick('primary', primary_cta)}\n sx={{\n ...(isCtaDisabled(primary_cta.block) && { color: 'text.disabled' }),\n }}\n variant=\"outlined\"\n >\n {primary_cta.label}\n </Button>\n )}\n {/* Mini has room for one CTA. */}\n {!isMini && secondary_cta?.label && (\n <Button\n aria-disabled={\n isCtaDisabled(secondary_cta.block) || secondaryCtaState.disabled\n }\n color=\"secondary\"\n disabled={secondaryCtaState.disabled}\n onClick={() => onCtaClick('secondary', secondary_cta)}\n >\n {secondary_cta.label}\n </Button>\n )}\n </Stack>\n )}\n\n <FeedbackBar onTellUsMore={flow.openRatingSurvey} show={flow.isFeedbackBarShown} />\n </Card>\n </>\n )}\n\n <ActionBlockLayer beat={beat} />\n\n <DismissInsightDialog\n isOpen={flow.isDismissOpen}\n onClose={flow.closeDismissDialog}\n onDismiss={flow.confirmDismiss}\n />\n\n {flow.isSurveyOpen && (\n <FeedbackDialog\n characterLimitLabel={flow.survey.characterLimitLabel}\n closeAriaLabel={flow.survey.closeAriaLabel}\n isOpen={true}\n onBackClick={flow.feedbackDialogCallbacks.onBackClick}\n onClose={flow.closeSurvey}\n onSubmit={flow.submitSurvey}\n onTextInputFocus={flow.feedbackDialogCallbacks.onTextInputFocus}\n options={flow.survey.options}\n primaryText={flow.survey.submitText}\n secondaryText={flow.survey.backText}\n title={flow.survey.title}\n />\n )}\n\n {flow.cardState === 'visible' && insights_payload.footer && (\n <Footer footer={insights_payload.footer} />\n )}\n </Stack>\n </BeatActionsProvider>\n )\n },\n)\n\nexport default BaseLayout\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,IAAM,KAA+B,CAAC,GAEhC,KAAsB;AAAA,EAC1B,UAAU;AAAA,EACV,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,QAAQ;AACV,GAMM,KAAc;AAAA,EAClB,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,IAAI;AAAA,EACJ,eAAe;AACjB,GAEM,KAAa,EAAA,CAChB,EACC,MAAA,GACA,aAAA,IAAc,IACd,UAAA,GACA,WAAA,IAAY,IACZ,SAAA,IAAU,GAAA,MACW;AACrB,QAAM,IAAO,EAAmB,GAC1B,EAAE,QAAA,EAAA,IAAW,EAAa,GAC1B,IAAO,EAAoB,GAAM,CAAW,GAC5C,EACJ,QAAQ,GACR,SAAS,GACT,WAAW,EAAA,IACT,EACF,GACA,GACA,EAAK,kBAAkB,aACvB,EAAK,kBAAkB,aACzB;AAGA,MAAI,EAAS,QAAO,gBAAA,EAAC,GAAD,CAAY,CAAA;AAEhC,QAAM,IAAmB,EAAK;AAG9B,MADI,CAAC,KACD,EAAK,cAAc,YAAa,QAAO;AAE3C,QAAM,EACJ,eAAA,GACA,aAAA,GACA,eAAA,GACA,WAAA,GACA,OAAA,GACA,aAAA,GACA,MAAA,GACA,cAAA,EAAA,IACE,GACE,EAAE,OAAA,EAAA,IAAU,GAKZ,IACJ,MACC,EAAiB,WACd;AAAA,IACE,MAAM,EAAY,EAAiB,IAAI;AAAA,IACvC,MAAM,EAAiB;AAAA,EACzB,IACA,SAMA,IAAA,CAAiB,MACrB,EAA4B,GAAU,GAAQ,EAAY,gBAAgB,GAEtE,IAAa,OAAO,GAA+B,MAAmC;AAC1F,QAAI,CAAA,EAAc,EAAI,KAAK,GAE3B;AAAA,UAAI,EAAI,UAAU,EAAgB,8BAA8B;AAC9D,QAAA,EAAY,mBAAmB;AAC/B;AAAA,MACF;AAEA,YAAM,EAAe,GAAM,CAAG;AAAA;AAAA,EAChC,GAEM,IAAQ,EAAO,CAAA,GAEf,IAAS,MAAgB,QACzB,IAAe,EAAK,eAAe,SACnC,IACJ,GAAU,UAAU,qBAAqB,CAAC,KAAgB,CAAC,CAAC;AAE9D,SACE,gBAAA,EAAC,GAAD;AAAA,IAAqB,OAAO,EAAK;AAAA,IAC/B,UAAA,gBAAA,EAAC,GAAD;AAAA,MAAO,IAAI,EAAE,IAAI,GAAG;AAAA,MAApB,UAAA;AAAA,QACG,EAAK,cAAc,eAClB,gBAAA,EAAC,GAAD;AAAA,UACE,SAAS,EAAK;AAAA,UACd,iBAAiB,EAAK;AAAA,UACtB,QAAQ,EAAK;AAAA,QACd,CAAA,IAED,gBAAA,EAAA,IAAA,EAAA,UAAA,CACG,KAAY,KAAgB,gBAAA,EAAC,GAAD;AAAA,UAAiB,GAAI;AAAA,UAAU,MAAM;AAAA,QAAe,CAAA,GACjF,gBAAA,EAAC,IAAD;AAAA,UACE,OAAO;AAAA,UACP,IAAI,EACF,GAAI,KAAoB;AAAA,YACtB,UAAU;AAAA,YACV,QAAQ;AAAA,YACR,eAAe;AAAA,UACjB,EACF;AAAA,UARF,UAAA;AAAA,YAUG,KAAoB,gBAAA,EAAC,IAAD,EAAK,IAAI,GAAsB,CAAA;AAAA,YACpD,gBAAA,EAAC,GAAD;AAAA,cAAgB,QAAA;AAAA,cAAkB,UAAA;AAAA,cAAU,OAAO,KAAS;AAAA,YAAK,CAAA;AAAA,YAChE,IACC,gBAAA,EAAC,GAAD,CAAc,CAAA,IAEd,KAAS,gBAAA,EAAC,GAAD;AAAA,cAAO,UAAU;AAAA,cAAM,SAAS;AAAA,YAAmB,CAAA;AAAA,YAG9D,gBAAA,EAAC,GAAD;AAAA,cAAO,IAAI;AAAA,gBAAE,KAAK;AAAA,gBAAG,IAAI;AAAA,gBAAI,IAAI;AAAA,gBAAI,IAAI;AAAA,cAAG;AAAA,cAA5C,UAAA,CACE,gBAAA,EAAC,IAAD;AAAA,gBACE,yBAAyB,EACvB,QAAQ,EAAiB,YAAY,UACvC;AAAA,gBACA,SAAQ;AAAA,cACT,CAAA,GAEA,GAAM,sBACL,gBAAA,EAAC,GAAD;AAAA,gBACE,SAAS,gBAAA,EAAC,IAAD,CAAe,CAAA;AAAA,gBACxB,SAAA,MAAe;AAAA,gBAAC;AAAA,gBAChB,IAAI;AAAA,kBAAE,QAAQ;AAAA,kBAAI,GAAG;AAAA,kBAAG,OAAO;AAAA,gBAAc;AAAA,gBAE5C,UAAA,EAAK;AAAA,cACA,CAAA,CAEL;AAAA;YAEN,GAAa,SACZ,gBAAA,EAAC,GAAD;AAAA,cAAO,IAAI;AAAA,gBAAE,KAAK;AAAA,gBAAG,IAAI;AAAA,gBAAI,IAAI;AAAA,cAAG;AAAA,cAApC,UAAA,CACG,IAKC,gBAAA,EAAC,IAAD;AAAA,gBAAM,OAAM;AAAA,gBAAe,IAAI;AAAA,gBAAa,SAAQ;AAAA,gBACjD,UAAA,EAAY;AAAA,cACT,CAAA,IAEN,gBAAA,EAAC,GAAD;AAAA,gBACE,iBAAe,EAAc,EAAY,KAAK,KAAK,EAAgB;AAAA,gBACnE,UAAU,EAAgB;AAAA,gBAC1B,SAAA,MAAe,EAAW,WAAW,CAAW;AAAA,gBAChD,IAAI,EACF,GAAI,EAAc,EAAY,KAAK,KAAK,EAAE,OAAO,gBAAgB,EACnE;AAAA,gBACA,SAAQ;AAAA,gBAEP,UAAA,EAAY;AAAA,cACP,CAAA,GAGT,CAAC,KAAU,GAAe,SACzB,gBAAA,EAAC,GAAD;AAAA,gBACE,iBACE,EAAc,EAAc,KAAK,KAAK,EAAkB;AAAA,gBAE1D,OAAM;AAAA,gBACN,UAAU,EAAkB;AAAA,gBAC5B,SAAA,MAAe,EAAW,aAAa,CAAa;AAAA,gBAEnD,UAAA,EAAc;AAAA,cACT,CAAA,CAEL;AAAA;YAGT,gBAAA,EAAC,GAAD;AAAA,cAAa,cAAc,EAAK;AAAA,cAAkB,MAAM,EAAK;AAAA,YAAqB,CAAA;AAAA,UAC9E;AAAA,QACN,CAAA,CAAA,EAAA,CAAA;AAAA,QAGJ,gBAAA,EAAC,GAAD,EAAwB,MAAA,EAAO,CAAA;AAAA,QAE/B,gBAAA,EAAC,GAAD;AAAA,UACE,QAAQ,EAAK;AAAA,UACb,SAAS,EAAK;AAAA,UACd,WAAW,EAAK;AAAA,QACjB,CAAA;AAAA,QAEA,EAAK,gBACJ,gBAAA,EAAC,GAAD;AAAA,UACE,qBAAqB,EAAK,OAAO;AAAA,UACjC,gBAAgB,EAAK,OAAO;AAAA,UAC5B,QAAQ;AAAA,UACR,aAAa,EAAK,wBAAwB;AAAA,UAC1C,SAAS,EAAK;AAAA,UACd,UAAU,EAAK;AAAA,UACf,kBAAkB,EAAK,wBAAwB;AAAA,UAC/C,SAAS,EAAK,OAAO;AAAA,UACrB,aAAa,EAAK,OAAO;AAAA,UACzB,eAAe,EAAK,OAAO;AAAA,UAC3B,OAAO,EAAK,OAAO;AAAA,QACpB,CAAA;AAAA,QAGF,EAAK,cAAc,aAAa,EAAiB,UAChD,gBAAA,EAAC,GAAD,EAAQ,QAAQ,EAAiB,OAAS,CAAA;AAAA,MAEvC;AAAA;EACY,CAAA;AAEzB,CACF"}
1
+ {"version":3,"file":"BaseLayout.es.js","names":[],"sources":["../../../src/insights-v2/components/BaseLayout.tsx"],"sourcesContent":["import { observer } from 'mobx-react-lite'\n\nimport Box from '@mui/material/Box'\nimport Button from '@mui/material/Button'\nimport Card from '@mui/material/Card'\nimport Stack from '@mui/material/Stack'\n\nimport { ChevronRight } from '@mxenabled/mx-icons'\nimport { P, Text } from '@mxenabled/mxui'\n\nimport { blocks } from '../mappings/blocks'\nimport { actionBlocksKey } from '../mappings/actionBlocksKey'\nimport { isContactSupportCtaDisabled } from '../actionBlocks/ContactSupportActionBlock'\nimport { logoFromRef } from './shared/EntityLogo'\n\nimport Footer from './Footer'\nimport Header from './Header'\nimport FeedbackBar from './FeedbackBar'\nimport FeedbackDialog from './FeedbackDialog'\nimport DismissInsightDialog from './DismissInsightDialog'\nimport HiddenConfirmationCard from './HiddenConfirmationCard'\nimport ErrorCard from './ErrorCard'\nimport LoadingCard from './LoadingCard'\nimport { ObsolesceBanner, type ObsolesceBannerState } from './ObsolesceBanner'\nimport { useAppConfig, useGlobalCopyStore } from '../../common'\nimport type { Beat, PrimaryCTA, SecondaryCTA } from '../../core'\nimport { BeatActionsProvider, type BeatActions } from '../beatActions'\nimport { ActionBlockLayer } from '../actionBlocks/ActionBlockLayer'\nimport { useBeatCtaActions } from '../ctaActions'\nimport { useBeatFeedbackFlow } from '../hooks/useBeatFeedbackFlow'\n\nexport interface ObsoleteState {\n state: ObsolesceBannerState\n onRefresh: () => void\n onDismiss: () => void\n}\n\ninterface BaseLayoutProps {\n beat: Beat\n beatActions?: BeatActions\n obsolete?: ObsoleteState\n /** Swap only the block slot for a LoadingCard (e.g. while a sampled beat loads). */\n isLoading?: boolean\n /** Replace the entire card with an ErrorCard (e.g. when the sample fails to load). */\n isError?: boolean\n}\n\nconst NO_BEAT_ACTIONS: BeatActions = {}\n\nconst OBSOLETE_OVERLAY_SX = {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n backgroundColor: 'background.default',\n opacity: 0.7,\n zIndex: 1,\n} as const\n\n// Figma (Mini | Large Transaction): a left-aligned link under the description. The 2px padding plus\n// the CTA row's 16 lines the label up with the description's 18. The label is not a Button, so it\n// carries the theme's MuiButton look itself: semi-bold, no uppercase (typography.button uppercases),\n// and the medium Button's 44px height with the text centred.\nconst MINI_CTA_SX = {\n alignItems: 'center',\n alignSelf: 'flex-start',\n display: 'flex',\n fontWeight: 600,\n height: 44,\n px: 2,\n textTransform: 'none',\n} as const\n\nconst BaseLayout = observer(\n ({\n beat,\n beatActions = NO_BEAT_ACTIONS,\n obsolete,\n isLoading = false,\n isError = false,\n }: BaseLayoutProps) => {\n const copy = useGlobalCopyStore()\n const { config } = useAppConfig()\n const flow = useBeatFeedbackFlow(beat, beatActions)\n const {\n runCta: handleCtaClick,\n primary: primaryCtaState,\n secondary: secondaryCtaState,\n } = useBeatCtaActions(\n beat,\n beatActions,\n beat.insights_payload?.primary_cta,\n beat.insights_payload?.secondary_cta,\n )\n\n // Error replaces the entire card; loading only swaps the block slot (below).\n if (isError) return <ErrorCard />\n\n const insights_payload = beat.insights_payload\n\n if (!insights_payload) return null\n if (flow.cardState === 'dismissed') return null\n\n const {\n instance_slot,\n primary_cta,\n secondary_cta,\n sub_title,\n title,\n widget_type,\n guid,\n dismissed_at,\n } = insights_payload\n const { block } = instance_slot\n\n // V1 sends `sub_title: { text, logo }`. The V2 envelope flattens it to a `subtitle` string\n // with the logo promoted to a payload-level `LogoRef` (an entity guid or a status icon), so\n // rebuild the shape `Header`/`SubHeader` already render. `sub_title` wins when a beat sends both.\n const subtitle =\n sub_title ??\n (insights_payload.subtitle\n ? {\n logo: logoFromRef(insights_payload.logo),\n text: insights_payload.subtitle,\n }\n : undefined)\n\n // CTA presses go through the ctaActions runner (../ctaActions): a backend `action_key` runs\n // its step, a `block` opens its drawer, and a resolved message (backend `metadata`, else the\n // template's `ctaPostMessages` entry) is posted. `contact_support_block` bypasses the runner:\n // the help flow is host-supplied via `beatActions.onContactSupport`, disabled without it.\n const isCtaDisabled = (ctaBlock: string | null | undefined) =>\n isContactSupportCtaDisabled(ctaBlock, config, beatActions.onContactSupport)\n\n const onCtaClick = async (slot: 'primary' | 'secondary', cta: PrimaryCTA | SecondaryCTA) => {\n if (isCtaDisabled(cta.block)) return\n\n if (cta.block === actionBlocksKey.CONTACT_SUPPORT_ACTION_BLOCK) {\n beatActions.onContactSupport?.()\n return\n }\n\n await handleCtaClick(slot, cta)\n }\n\n const Block = blocks[block as keyof typeof blocks]\n\n const isMini = widget_type === 'mini'\n const obsoleteCopy = copy.insights_feed?.general\n const isObsoleteDimmed =\n obsolete?.state === 'not_refreshable' && !dismissed_at && !!obsoleteCopy\n\n return (\n <BeatActionsProvider value={flow.wrappedActions}>\n <Stack sx={{ mb: 16 }}>\n {flow.cardState === 'confirming' ? (\n <HiddenConfirmationCard\n onClose={flow.collapseConfirmation}\n onLeaveFeedback={flow.openHideSurvey}\n onUndo={flow.undoDismiss}\n />\n ) : (\n <>\n {obsolete && obsoleteCopy && <ObsolesceBanner {...obsolete} copy={obsoleteCopy} />}\n <Card\n inert={isObsoleteDimmed}\n sx={{\n ...(isObsoleteDimmed && {\n position: 'relative',\n zIndex: 2,\n pointerEvents: 'none',\n }),\n }}\n >\n {isObsoleteDimmed && <Box sx={OBSOLETE_OVERLAY_SX} />}\n <Header isMini={isMini} subtitle={subtitle} title={title ?? ''} />\n {isLoading ? (\n <LoadingCard />\n ) : (\n Block && <Block beatGuid={guid} payload={insights_payload} />\n )}\n\n <Stack sx={{ gap: 6, pb: 16, pt: 12, px: 16 }}>\n <P\n dangerouslySetInnerHTML={{\n __html: insights_payload.description.html_text,\n }}\n variant=\"subtitle2\"\n />\n {/* TODO: Migrate to insights_payload.in_description_cta once backend provides it */}\n {beat?.in_description_cta && (\n <Button\n endIcon={<ChevronRight />}\n onClick={() => {}}\n sx={{ height: 24, p: 4, width: 'max-content' }}\n >\n {beat.in_description_cta}\n </Button>\n )}\n </Stack>\n\n {primary_cta?.label && (\n <Stack sx={{ gap: 8, pb: 16, px: 16 }}>\n {isMini ? (\n // Mini is a tap target, as in V1: the card, not this label, is the control. The label\n // is deliberately not a button, so a tap on it reaches the host's card handler (Pulse\n // posts `carousel/cta`, the same redirect a V1 mini card sends) instead of opening\n // the action drawer the full card's CTA opens.\n <Text color=\"primary.main\" sx={MINI_CTA_SX} variant=\"button\">\n {primary_cta.label}\n </Text>\n ) : (\n <Button\n aria-disabled={isCtaDisabled(primary_cta.block) || primaryCtaState.disabled}\n disabled={primaryCtaState.disabled}\n onClick={() => onCtaClick('primary', primary_cta)}\n sx={{\n ...(isCtaDisabled(primary_cta.block) && { color: 'text.disabled' }),\n }}\n variant=\"outlined\"\n >\n {primary_cta.label}\n </Button>\n )}\n {/* Mini has room for one CTA. */}\n {!isMini && secondary_cta?.label && (\n <Button\n aria-disabled={\n isCtaDisabled(secondary_cta.block) || secondaryCtaState.disabled\n }\n color=\"secondary\"\n disabled={secondaryCtaState.disabled}\n onClick={() => onCtaClick('secondary', secondary_cta)}\n >\n {secondary_cta.label}\n </Button>\n )}\n </Stack>\n )}\n\n <FeedbackBar onTellUsMore={flow.openRatingSurvey} show={flow.isFeedbackBarShown} />\n </Card>\n </>\n )}\n\n <ActionBlockLayer beat={beat} />\n\n <DismissInsightDialog\n isOpen={flow.isDismissOpen}\n onClose={flow.closeDismissDialog}\n onDismiss={flow.confirmDismiss}\n />\n\n {flow.isSurveyOpen && (\n <FeedbackDialog\n characterLimitLabel={flow.survey.characterLimitLabel}\n closeAriaLabel={flow.survey.closeAriaLabel}\n isOpen={true}\n onBackClick={flow.feedbackDialogCallbacks.onBackClick}\n onClose={flow.closeSurvey}\n onSubmit={flow.submitSurvey}\n onTextInputFocus={flow.feedbackDialogCallbacks.onTextInputFocus}\n options={flow.survey.options}\n primaryText={flow.survey.submitText}\n secondaryText={flow.survey.backText}\n title={flow.survey.title}\n />\n )}\n\n {flow.cardState === 'visible' && insights_payload.footer && (\n <Footer footer={insights_payload.footer} />\n )}\n </Stack>\n </BeatActionsProvider>\n )\n },\n)\n\nexport default BaseLayout\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,IAAM,KAA+B,CAAC,GAEhC,KAAsB;AAAA,EAC1B,UAAU;AAAA,EACV,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,QAAQ;AACV,GAMM,KAAc;AAAA,EAClB,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,IAAI;AAAA,EACJ,eAAe;AACjB,GAEM,KAAa,EAAA,CAChB,EACC,MAAA,GACA,aAAA,IAAc,IACd,UAAA,GACA,WAAA,IAAY,IACZ,SAAA,IAAU,GAAA,MACW;AACrB,QAAM,IAAO,EAAmB,GAC1B,EAAE,QAAA,EAAA,IAAW,EAAa,GAC1B,IAAO,EAAoB,GAAM,CAAW,GAC5C,EACJ,QAAQ,GACR,SAAS,GACT,WAAW,EAAA,IACT,EACF,GACA,GACA,EAAK,kBAAkB,aACvB,EAAK,kBAAkB,aACzB;AAGA,MAAI,EAAS,QAAO,gBAAA,EAAC,GAAD,CAAY,CAAA;AAEhC,QAAM,IAAmB,EAAK;AAG9B,MADI,CAAC,KACD,EAAK,cAAc,YAAa,QAAO;AAE3C,QAAM,EACJ,eAAA,GACA,aAAA,GACA,eAAA,GACA,WAAA,GACA,OAAA,GACA,aAAA,GACA,MAAA,GACA,cAAA,EAAA,IACE,GACE,EAAE,OAAA,EAAA,IAAU,GAKZ,IACJ,MACC,EAAiB,WACd;AAAA,IACE,MAAM,EAAY,EAAiB,IAAI;AAAA,IACvC,MAAM,EAAiB;AAAA,EACzB,IACA,SAMA,IAAA,CAAiB,MACrB,EAA4B,GAAU,GAAQ,EAAY,gBAAgB,GAEtE,IAAa,OAAO,GAA+B,MAAmC;AAC1F,QAAI,CAAA,EAAc,EAAI,KAAK,GAE3B;AAAA,UAAI,EAAI,UAAU,EAAgB,8BAA8B;AAC9D,QAAA,EAAY,mBAAmB;AAC/B;AAAA,MACF;AAEA,YAAM,EAAe,GAAM,CAAG;AAAA;AAAA,EAChC,GAEM,IAAQ,EAAO,CAAA,GAEf,IAAS,MAAgB,QACzB,IAAe,EAAK,eAAe,SACnC,IACJ,GAAU,UAAU,qBAAqB,CAAC,KAAgB,CAAC,CAAC;AAE9D,SACE,gBAAA,EAAC,GAAD;AAAA,IAAqB,OAAO,EAAK;AAAA,IAC/B,UAAA,gBAAA,EAAC,GAAD;AAAA,MAAO,IAAI,EAAE,IAAI,GAAG;AAAA,MAApB,UAAA;AAAA,QACG,EAAK,cAAc,eAClB,gBAAA,EAAC,GAAD;AAAA,UACE,SAAS,EAAK;AAAA,UACd,iBAAiB,EAAK;AAAA,UACtB,QAAQ,EAAK;AAAA,QACd,CAAA,IAED,gBAAA,EAAA,IAAA,EAAA,UAAA,CACG,KAAY,KAAgB,gBAAA,EAAC,GAAD;AAAA,UAAiB,GAAI;AAAA,UAAU,MAAM;AAAA,QAAe,CAAA,GACjF,gBAAA,EAAC,IAAD;AAAA,UACE,OAAO;AAAA,UACP,IAAI,EACF,GAAI,KAAoB;AAAA,YACtB,UAAU;AAAA,YACV,QAAQ;AAAA,YACR,eAAe;AAAA,UACjB,EACF;AAAA,UARF,UAAA;AAAA,YAUG,KAAoB,gBAAA,EAAC,IAAD,EAAK,IAAI,GAAsB,CAAA;AAAA,YACpD,gBAAA,EAAC,GAAD;AAAA,cAAgB,QAAA;AAAA,cAAkB,UAAA;AAAA,cAAU,OAAO,KAAS;AAAA,YAAK,CAAA;AAAA,YAChE,IACC,gBAAA,EAAC,GAAD,CAAc,CAAA,IAEd,KAAS,gBAAA,EAAC,GAAD;AAAA,cAAO,UAAU;AAAA,cAAM,SAAS;AAAA,YAAmB,CAAA;AAAA,YAG9D,gBAAA,EAAC,GAAD;AAAA,cAAO,IAAI;AAAA,gBAAE,KAAK;AAAA,gBAAG,IAAI;AAAA,gBAAI,IAAI;AAAA,gBAAI,IAAI;AAAA,cAAG;AAAA,cAA5C,UAAA,CACE,gBAAA,EAAC,IAAD;AAAA,gBACE,yBAAyB,EACvB,QAAQ,EAAiB,YAAY,UACvC;AAAA,gBACA,SAAQ;AAAA,cACT,CAAA,GAEA,GAAM,sBACL,gBAAA,EAAC,GAAD;AAAA,gBACE,SAAS,gBAAA,EAAC,IAAD,CAAe,CAAA;AAAA,gBACxB,SAAA,MAAe;AAAA,gBAAC;AAAA,gBAChB,IAAI;AAAA,kBAAE,QAAQ;AAAA,kBAAI,GAAG;AAAA,kBAAG,OAAO;AAAA,gBAAc;AAAA,gBAE5C,UAAA,EAAK;AAAA,cACA,CAAA,CAEL;AAAA;YAEN,GAAa,SACZ,gBAAA,EAAC,GAAD;AAAA,cAAO,IAAI;AAAA,gBAAE,KAAK;AAAA,gBAAG,IAAI;AAAA,gBAAI,IAAI;AAAA,cAAG;AAAA,cAApC,UAAA,CACG,IAKC,gBAAA,EAAC,IAAD;AAAA,gBAAM,OAAM;AAAA,gBAAe,IAAI;AAAA,gBAAa,SAAQ;AAAA,gBACjD,UAAA,EAAY;AAAA,cACT,CAAA,IAEN,gBAAA,EAAC,GAAD;AAAA,gBACE,iBAAe,EAAc,EAAY,KAAK,KAAK,EAAgB;AAAA,gBACnE,UAAU,EAAgB;AAAA,gBAC1B,SAAA,MAAe,EAAW,WAAW,CAAW;AAAA,gBAChD,IAAI,EACF,GAAI,EAAc,EAAY,KAAK,KAAK,EAAE,OAAO,gBAAgB,EACnE;AAAA,gBACA,SAAQ;AAAA,gBAEP,UAAA,EAAY;AAAA,cACP,CAAA,GAGT,CAAC,KAAU,GAAe,SACzB,gBAAA,EAAC,GAAD;AAAA,gBACE,iBACE,EAAc,EAAc,KAAK,KAAK,EAAkB;AAAA,gBAE1D,OAAM;AAAA,gBACN,UAAU,EAAkB;AAAA,gBAC5B,SAAA,MAAe,EAAW,aAAa,CAAa;AAAA,gBAEnD,UAAA,EAAc;AAAA,cACT,CAAA,CAEL;AAAA;YAGT,gBAAA,EAAC,GAAD;AAAA,cAAa,cAAc,EAAK;AAAA,cAAkB,MAAM,EAAK;AAAA,YAAqB,CAAA;AAAA,UAC9E;AAAA,QACN,CAAA,CAAA,EAAA,CAAA;AAAA,QAGJ,gBAAA,EAAC,GAAD,EAAwB,MAAA,EAAO,CAAA;AAAA,QAE/B,gBAAA,EAAC,GAAD;AAAA,UACE,QAAQ,EAAK;AAAA,UACb,SAAS,EAAK;AAAA,UACd,WAAW,EAAK;AAAA,QACjB,CAAA;AAAA,QAEA,EAAK,gBACJ,gBAAA,EAAC,GAAD;AAAA,UACE,qBAAqB,EAAK,OAAO;AAAA,UACjC,gBAAgB,EAAK,OAAO;AAAA,UAC5B,QAAQ;AAAA,UACR,aAAa,EAAK,wBAAwB;AAAA,UAC1C,SAAS,EAAK;AAAA,UACd,UAAU,EAAK;AAAA,UACf,kBAAkB,EAAK,wBAAwB;AAAA,UAC/C,SAAS,EAAK,OAAO;AAAA,UACrB,aAAa,EAAK,OAAO;AAAA,UACzB,eAAe,EAAK,OAAO;AAAA,UAC3B,OAAO,EAAK,OAAO;AAAA,QACpB,CAAA;AAAA,QAGF,EAAK,cAAc,aAAa,EAAiB,UAChD,gBAAA,EAAC,GAAD,EAAQ,QAAQ,EAAiB,OAAS,CAAA;AAAA,MAEvC;AAAA;EACY,CAAA;AAEzB,CACF"}
@@ -0,0 +1,48 @@
1
+ import { ReactNode } from 'react';
2
+ export interface DirectDepositPillConfig {
3
+ /** Pill background color token. */
4
+ bgcolor: string;
5
+ /** Pill border color token. */
6
+ borderColor: string;
7
+ /** Pill label color token. */
8
+ labelColor: string;
9
+ /** Optional mx-icons glyph rendered before the label (e.g. `check_circle`). */
10
+ icon?: string;
11
+ }
12
+ /**
13
+ * Style props for the card. Variant-specific values live in the Direct Deposit
14
+ * block's `layout.ts` (`getLayoutConfig`) — the card itself is variant-agnostic.
15
+ */
16
+ export interface DirectDepositCardStyleProps {
17
+ /** Slot surface token behind the white hero card. Default `primary.lighter`. */
18
+ bgcolor?: string;
19
+ /** Decorative wash layered over `bgcolor` (celebration/gradient slots). */
20
+ backgroundImage?: string;
21
+ /** Confetti burst behind the hero card (complete states). */
22
+ showConfetti?: boolean;
23
+ /** Hero name typography. Default `body2` (13/16); rate variants use `body1` (15/20). */
24
+ nameVariant?: 'body1' | 'body2';
25
+ /** Status pill color tokens + optional leading glyph. */
26
+ pill?: DirectDepositPillConfig;
27
+ }
28
+ interface DirectDepositCardProps extends DirectDepositCardStyleProps {
29
+ /** Institution/account logo, rendered overhanging the hero card's top edge. */
30
+ logo: ReactNode;
31
+ /** Primary line, e.g. "Epic Bank Checking, *1234". */
32
+ name: ReactNode;
33
+ /** Optional secondary line, e.g. "Checking Account" / "Credit Card". */
34
+ subtitle?: ReactNode;
35
+ /** Optional status pill label, e.g. "Direct Deposit Not Set Up". */
36
+ statusLabel?: ReactNode;
37
+ }
38
+ /**
39
+ * The basic Direct Deposit hero card: an overhanging logo above a white card
40
+ * with a name, optional subtitle, and a status pill, over a tinted/gradient
41
+ * slot with an optional confetti backdrop.
42
+ *
43
+ * Purely presentational — it knows nothing about beats or variants. The Direct
44
+ * Deposit block resolves `instance_slot.variant` to these style props via its
45
+ * `layout.ts` (`getLayoutConfig`).
46
+ */
47
+ declare const DirectDepositCard: ({ backgroundImage, bgcolor, logo, name, nameVariant, pill, showConfetti, statusLabel, subtitle, }: DirectDepositCardProps) => import("react/jsx-runtime").JSX.Element;
48
+ export default DirectDepositCard;