@mx-cartographer/experiences 9.5.4 → 9.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/core/index.es.js +111 -109
  2. package/dist/core/types/Insights.d.ts +33 -16
  3. package/dist/core/types/Insights.es.js +6 -0
  4. package/dist/core/types/Insights.es.js.map +1 -0
  5. package/dist/core/types/index.d.ts +2 -1
  6. package/dist/insights-v2/blocks/ChartBlocks/DonutChartBlock/utils.d.ts +1 -1
  7. package/dist/insights-v2/blocks/ChartBlocks/DonutChartBlock/utils.es.js.map +1 -1
  8. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/layout.d.ts +1 -1
  9. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/layout.es.js.map +1 -1
  10. package/dist/insights-v2/blocks/ComponentBlocks/AccountBlock/IconComponent.d.ts +1 -1
  11. package/dist/insights-v2/blocks/ComponentBlocks/AccountBlock/IconComponent.es.js.map +1 -1
  12. package/dist/insights-v2/blocks/ComponentBlocks/TransactionBlock/TransactionBlock.d.ts +5 -2
  13. package/dist/insights-v2/blocks/ComponentBlocks/TransactionBlock/TransactionBlock.es.js +36 -35
  14. package/dist/insights-v2/blocks/ComponentBlocks/TransactionBlock/TransactionBlock.es.js.map +1 -1
  15. package/dist/insights-v2/blocks/ComponentBlocks/WithdrawalBlock/WithdrawalBlock.d.ts +2 -2
  16. package/dist/insights-v2/blocks/ComponentBlocks/WithdrawalBlock/WithdrawalBlock.es.js +6 -5
  17. package/dist/insights-v2/blocks/ComponentBlocks/WithdrawalBlock/WithdrawalBlock.es.js.map +1 -1
  18. package/dist/insights-v2/blocks/ImageBlocks/SVGImageBlock/layout.d.ts +1 -1
  19. package/dist/insights-v2/blocks/ImageBlocks/SVGImageBlock/layout.es.js.map +1 -1
  20. package/dist/insights-v2/components/CompactInsightCard.d.ts +4 -4
  21. package/dist/insights-v2/components/CompactInsightCard.es.js +50 -46
  22. package/dist/insights-v2/components/CompactInsightCard.es.js.map +1 -1
  23. package/dist/insights-v2/resolveInsightRender.d.ts +8 -5
  24. package/dist/insights-v2/resolveInsightRender.es.js.map +1 -1
  25. package/dist/microinsights/cards/InsightCard.es.js +32 -31
  26. package/dist/microinsights/cards/InsightCard.es.js.map +1 -1
  27. package/package.json +1 -1
@@ -1,138 +1,140 @@
1
1
  import { LOCALES as r, VALID_LOCALES as t, buildDynamicCopy as i, getLocale as m } from "./utils/Localization.es.js";
2
2
  import { Fetch as p } from "./utils/Fetch.es.js";
3
- import { AccountIcon as a, AccountIconVariants as f, AccountSubType as c, AccountType as s, AccountTypeName as S, ConnectionStatus as A, ConnectionStatusEnums as u, ErrorStatuses as y, MfaStatuses as T, NonConnectedStatuses as l, ProcessingStatuses as g, PropertyType as d, PropertyTypeName as C, StatusName as N } from "./types/Account.es.js";
3
+ import { AccountIcon as f, AccountIconVariants as a, AccountSubType as c, AccountType as s, AccountTypeName as S, ConnectionStatus as A, ConnectionStatusEnums as u, ErrorStatuses as y, MfaStatuses as T, NonConnectedStatuses as l, ProcessingStatuses as g, PropertyType as d, PropertyTypeName as C, StatusName as N } from "./types/Account.es.js";
4
4
  import { UserVerification as b } from "./types/Beat.es.js";
5
5
  import { ExpenseStatus as B, ScheduledPaymentTypes as L } from "./types/Expense.es.js";
6
6
  import { GoalType as E, MetaType as I, TrackType as P } from "./types/Goal.es.js";
7
- import { AccountNotificationTypes as F, BudgetNotificationTypes as H, InsightNotificationTypes as M, NotificationTypes as U } from "./types/Notification.es.js";
8
- import { TransactionStatus as x, TransactionType as O } from "./types/Transaction.es.js";
9
- import { ScreenSize as k } from "./types/ScreenSize.es.js";
10
- import { Frequency as w, RecurrenceStatus as z, RecurrenceType as _, RepeatingType as j } from "./types/RepeatingTransaction.es.js";
11
- import { AccountApi as J } from "./api/AccountApi.es.js";
12
- import { AnalyticsApi as Q } from "./api/AnalyticsApi.es.js";
13
- import { AppDataApi as Y } from "./api/AppDataApi.es.js";
14
- import { BannerApi as $ } from "./api/BannerApi.es.js";
15
- import { BeatApi as ro } from "./api/BeatApi.es.js";
16
- import { BudgetsApi as io } from "./api/BudgetsApi.es.js";
17
- import { CategoryApi as eo } from "./api/CategoryApi.es.js";
18
- import { FinstrongApi as no } from "./api/FinstrongApi.es.js";
19
- import { GlobalCopyApi as fo } from "./api/GlobalCopyApi.es.js";
20
- import { GoalApi as so } from "./api/GoalApi.es.js";
21
- import { HelpApi as Ao } from "./api/HelpApi.es.js";
22
- import { HoldingApi as yo } from "./api/HoldingApi.es.js";
23
- import { MerchantApi as lo } from "./api/MerchantApi.es.js";
24
- import { NotificationApi as Co } from "./api/NotificationApi.es.js";
25
- import { RepeatingTransactionsApi as ho } from "./api/RepeatingTransactionsApi.es.js";
26
- import { ScheduledPaymentsApi as Go } from "./api/ScheduledPaymentsApi.es.js";
27
- import { SettingsApi as Lo } from "./api/SettingsApi.es.js";
28
- import { TransactionApi as Eo } from "./api/TransactionApi.es.js";
29
- import { UserApi as Po } from "./api/UserApi.es.js";
30
- import { WidgetApi as Fo } from "./api/WidgetApi.es.js";
31
- import { AccountStore as Mo } from "./stores/AccountStore.es.js";
32
- import { AppDataStore as Vo } from "./stores/AppDataStore.es.js";
33
- import { AnalyticsStore as Oo } from "./stores/AnalyticsStore.es.js";
34
- import { BeatStore as ko } from "./stores/BeatStore.es.js";
35
- import { BudgetsStore as wo } from "./stores/BudgetsStore.es.js";
36
- import { CashflowStore as _o } from "./stores/CashflowStore.es.js";
37
- import { CategoryStore as vo } from "./stores/CategoryStore.es.js";
38
- import { ConnectStore as Ko } from "./stores/ConnectStore.es.js";
39
- import { DebtsStore as Xo } from "./stores/DebtsStore.es.js";
40
- import { FinstrongStore as Zo } from "./stores/FinstrongStore.es.js";
41
- import { GlobalStore as or } from "./stores/GlobalStore.es.js";
42
- import { GlobalUiStore as tr } from "./stores/GlobalUiStore.es.js";
43
- import { GlobalCopyStore as mr } from "./stores/GlobalCopyStore.es.js";
44
- import { GoalStore as pr } from "./stores/GoalStore.es.js";
45
- import { HelpStore as ar } from "./stores/HelpStore.es.js";
46
- import { HoldingStore as cr } from "./stores/HoldingStore.es.js";
47
- import { InsightsV2Store as Sr } from "./stores/InsightsV2Store.es.js";
48
- import { MerchantStore as ur } from "./stores/MerchantStore.es.js";
49
- import { NetWorthStore as Tr } from "./stores/NetWorthStore.es.js";
50
- import { NotificationStore as gr } from "./stores/NotificationStore.es.js";
51
- import { RecurringTransactionsStore as Cr } from "./stores/RecurringTransactionsStore.es.js";
52
- import { SettingsStore as hr } from "./stores/SettingsStore.es.js";
53
- import { TransactionStore as Gr } from "./stores/TransactionStore.es.js";
54
- import { TrendsStore as Lr } from "./stores/TrendsStore.es.js";
55
- import { UserStore as Er } from "./stores/UserStore.es.js";
7
+ import { slot as F } from "./types/Insights.es.js";
8
+ import { AccountNotificationTypes as M, BudgetNotificationTypes as U, InsightNotificationTypes as V, NotificationTypes as x } from "./types/Notification.es.js";
9
+ import { TransactionStatus as W, TransactionType as k } from "./types/Transaction.es.js";
10
+ import { ScreenSize as w } from "./types/ScreenSize.es.js";
11
+ import { Frequency as _, RecurrenceStatus as j, RecurrenceType as v, RepeatingType as J } from "./types/RepeatingTransaction.es.js";
12
+ import { AccountApi as Q } from "./api/AccountApi.es.js";
13
+ import { AnalyticsApi as Y } from "./api/AnalyticsApi.es.js";
14
+ import { AppDataApi as $ } from "./api/AppDataApi.es.js";
15
+ import { BannerApi as ro } from "./api/BannerApi.es.js";
16
+ import { BeatApi as io } from "./api/BeatApi.es.js";
17
+ import { BudgetsApi as eo } from "./api/BudgetsApi.es.js";
18
+ import { CategoryApi as no } from "./api/CategoryApi.es.js";
19
+ import { FinstrongApi as ao } from "./api/FinstrongApi.es.js";
20
+ import { GlobalCopyApi as so } from "./api/GlobalCopyApi.es.js";
21
+ import { GoalApi as Ao } from "./api/GoalApi.es.js";
22
+ import { HelpApi as yo } from "./api/HelpApi.es.js";
23
+ import { HoldingApi as lo } from "./api/HoldingApi.es.js";
24
+ import { MerchantApi as Co } from "./api/MerchantApi.es.js";
25
+ import { NotificationApi as ho } from "./api/NotificationApi.es.js";
26
+ import { RepeatingTransactionsApi as Go } from "./api/RepeatingTransactionsApi.es.js";
27
+ import { ScheduledPaymentsApi as Lo } from "./api/ScheduledPaymentsApi.es.js";
28
+ import { SettingsApi as Eo } from "./api/SettingsApi.es.js";
29
+ import { TransactionApi as Po } from "./api/TransactionApi.es.js";
30
+ import { UserApi as Fo } from "./api/UserApi.es.js";
31
+ import { WidgetApi as Mo } from "./api/WidgetApi.es.js";
32
+ import { AccountStore as Vo } from "./stores/AccountStore.es.js";
33
+ import { AppDataStore as Oo } from "./stores/AppDataStore.es.js";
34
+ import { AnalyticsStore as ko } from "./stores/AnalyticsStore.es.js";
35
+ import { BeatStore as wo } from "./stores/BeatStore.es.js";
36
+ import { BudgetsStore as _o } from "./stores/BudgetsStore.es.js";
37
+ import { CashflowStore as vo } from "./stores/CashflowStore.es.js";
38
+ import { CategoryStore as Ko } from "./stores/CategoryStore.es.js";
39
+ import { ConnectStore as Xo } from "./stores/ConnectStore.es.js";
40
+ import { DebtsStore as Zo } from "./stores/DebtsStore.es.js";
41
+ import { FinstrongStore as or } from "./stores/FinstrongStore.es.js";
42
+ import { GlobalStore as tr } from "./stores/GlobalStore.es.js";
43
+ import { GlobalUiStore as mr } from "./stores/GlobalUiStore.es.js";
44
+ import { GlobalCopyStore as pr } from "./stores/GlobalCopyStore.es.js";
45
+ import { GoalStore as fr } from "./stores/GoalStore.es.js";
46
+ import { HelpStore as cr } from "./stores/HelpStore.es.js";
47
+ import { HoldingStore as Sr } from "./stores/HoldingStore.es.js";
48
+ import { InsightsV2Store as ur } from "./stores/InsightsV2Store.es.js";
49
+ import { MerchantStore as Tr } from "./stores/MerchantStore.es.js";
50
+ import { NetWorthStore as gr } from "./stores/NetWorthStore.es.js";
51
+ import { NotificationStore as Cr } from "./stores/NotificationStore.es.js";
52
+ import { RecurringTransactionsStore as hr } from "./stores/RecurringTransactionsStore.es.js";
53
+ import { SettingsStore as Gr } from "./stores/SettingsStore.es.js";
54
+ import { TransactionStore as Lr } from "./stores/TransactionStore.es.js";
55
+ import { TrendsStore as Er } from "./stores/TrendsStore.es.js";
56
+ import { UserStore as Pr } from "./stores/UserStore.es.js";
56
57
  export {
57
- J as AccountApi,
58
- a as AccountIcon,
59
- f as AccountIconVariants,
60
- F as AccountNotificationTypes,
61
- Mo as AccountStore,
58
+ Q as AccountApi,
59
+ f as AccountIcon,
60
+ a as AccountIconVariants,
61
+ M as AccountNotificationTypes,
62
+ Vo as AccountStore,
62
63
  c as AccountSubType,
63
64
  s as AccountType,
64
65
  S as AccountTypeName,
65
- Q as AnalyticsApi,
66
- Oo as AnalyticsStore,
67
- Y as AppDataApi,
68
- Vo as AppDataStore,
69
- $ as BannerApi,
70
- ro as BeatApi,
71
- ko as BeatStore,
72
- H as BudgetNotificationTypes,
73
- io as BudgetsApi,
74
- wo as BudgetsStore,
75
- _o as CashflowStore,
76
- eo as CategoryApi,
77
- vo as CategoryStore,
78
- Ko as ConnectStore,
66
+ Y as AnalyticsApi,
67
+ ko as AnalyticsStore,
68
+ $ as AppDataApi,
69
+ Oo as AppDataStore,
70
+ ro as BannerApi,
71
+ io as BeatApi,
72
+ wo as BeatStore,
73
+ U as BudgetNotificationTypes,
74
+ eo as BudgetsApi,
75
+ _o as BudgetsStore,
76
+ vo as CashflowStore,
77
+ no as CategoryApi,
78
+ Ko as CategoryStore,
79
+ Xo as ConnectStore,
79
80
  A as ConnectionStatus,
80
81
  u as ConnectionStatusEnums,
81
- Xo as DebtsStore,
82
+ Zo as DebtsStore,
82
83
  y as ErrorStatuses,
83
84
  B as ExpenseStatus,
84
85
  p as Fetch,
85
- no as FinstrongApi,
86
- Zo as FinstrongStore,
87
- w as Frequency,
88
- fo as GlobalCopyApi,
89
- mr as GlobalCopyStore,
90
- or as GlobalStore,
91
- tr as GlobalUiStore,
92
- so as GoalApi,
93
- pr as GoalStore,
86
+ ao as FinstrongApi,
87
+ or as FinstrongStore,
88
+ _ as Frequency,
89
+ so as GlobalCopyApi,
90
+ pr as GlobalCopyStore,
91
+ tr as GlobalStore,
92
+ mr as GlobalUiStore,
93
+ Ao as GoalApi,
94
+ fr as GoalStore,
94
95
  E as GoalType,
95
- Ao as HelpApi,
96
- ar as HelpStore,
97
- yo as HoldingApi,
98
- cr as HoldingStore,
99
- M as InsightNotificationTypes,
100
- Sr as InsightsV2Store,
96
+ yo as HelpApi,
97
+ cr as HelpStore,
98
+ lo as HoldingApi,
99
+ Sr as HoldingStore,
100
+ V as InsightNotificationTypes,
101
+ ur as InsightsV2Store,
101
102
  r as LOCALES,
102
- lo as MerchantApi,
103
- ur as MerchantStore,
103
+ Co as MerchantApi,
104
+ Tr as MerchantStore,
104
105
  I as MetaType,
105
106
  T as MfaStatuses,
106
- Tr as NetWorthStore,
107
+ gr as NetWorthStore,
107
108
  l as NonConnectedStatuses,
108
- Co as NotificationApi,
109
- gr as NotificationStore,
110
- U as NotificationTypes,
109
+ ho as NotificationApi,
110
+ Cr as NotificationStore,
111
+ x as NotificationTypes,
111
112
  g as ProcessingStatuses,
112
113
  d as PropertyType,
113
114
  C as PropertyTypeName,
114
- z as RecurrenceStatus,
115
- _ as RecurrenceType,
116
- Cr as RecurringTransactionsStore,
117
- ho as RepeatingTransactionsApi,
118
- j as RepeatingType,
115
+ j as RecurrenceStatus,
116
+ v as RecurrenceType,
117
+ hr as RecurringTransactionsStore,
118
+ Go as RepeatingTransactionsApi,
119
+ J as RepeatingType,
119
120
  L as ScheduledPaymentTypes,
120
- Go as ScheduledPaymentsApi,
121
- k as ScreenSize,
122
- Lo as SettingsApi,
123
- hr as SettingsStore,
121
+ Lo as ScheduledPaymentsApi,
122
+ w as ScreenSize,
123
+ Eo as SettingsApi,
124
+ Gr as SettingsStore,
124
125
  N as StatusName,
125
126
  P as TrackType,
126
- Eo as TransactionApi,
127
- x as TransactionStatus,
128
- Gr as TransactionStore,
129
- O as TransactionType,
130
- Lr as TrendsStore,
131
- Po as UserApi,
132
- Er as UserStore,
127
+ Po as TransactionApi,
128
+ W as TransactionStatus,
129
+ Lr as TransactionStore,
130
+ k as TransactionType,
131
+ Er as TrendsStore,
132
+ Fo as UserApi,
133
+ Pr as UserStore,
133
134
  b as UserVerification,
134
135
  t as VALID_LOCALES,
135
- Fo as WidgetApi,
136
+ Mo as WidgetApi,
136
137
  i as buildDynamicCopy,
137
- m as getLocale
138
+ m as getLocale,
139
+ F as slot
138
140
  };
@@ -39,7 +39,7 @@ export interface InsightsPayload {
39
39
  widget_type: WidgetType;
40
40
  instance_slot: InstanceSlot;
41
41
  /**
42
- * V1 only. The v2 contract carries everything a block needs on `instance_slot.data_series` rows,
42
+ * V1 only. The v2 contract carries everything a block needs on `instance_slot.data`,
43
43
  * and omits this key entirely (see the LargeTransactionV2 payload). Blocks that still require it
44
44
  * get it as a required field through `BlockProps`, which re-declares it.
45
45
  */
@@ -237,22 +237,39 @@ export interface InstanceSlotRow {
237
237
  primary_text?: string;
238
238
  secondary_text?: string;
239
239
  }
240
+ /**
241
+ * V2: the slots a block's variant filled, keyed by slot name; ditto owns the names and omits any
242
+ * slot it has no value for (`lib/ditto/blocks/<block>.yml`). Read with `slot()`, which names the
243
+ * kind the caller expects.
244
+ */
245
+ export interface InstanceSlotData {
246
+ [slot: string]: unknown;
247
+ }
248
+ /**
249
+ * Reads one slot off a block's `data`; undefined when ditto did not fill it.
250
+ *
251
+ * The caller names the kind, because the slot's kind lives in the block's ditto schema and not
252
+ * here — a block fills slots with whatever its card needs, so no fixed list of kinds would hold
253
+ * (`account_switch_block` alone carries a boolean and `budget_block` a nested object).
254
+ */
255
+ export declare const slot: <T = unknown>(data: InstanceSlotData | undefined, name: string) => T | undefined;
256
+ /**
257
+ * V2: which block renders this beat's content, and what it renders.
258
+ *
259
+ * `block` is optional: a beat whose template has no ditto config arrives as an empty `{}` and the
260
+ * card renders its copy and CTAs alone, so a reader cannot assume a block is named. One interface
261
+ * with `block` optional rather than a union with `Record<string, never>`, which TypeScript absorbs
262
+ * — that union left `block` reading as required and typed a promise it did not keep.
263
+ *
264
+ * `variant` is optional for the same reason — the empty `{}` carries neither. Every ditto beat
265
+ * file that names a block also names a variant, so a *filled* slot always has one; ditto drops a
266
+ * nil variant rather than sending null, which is why the type is `string | null | undefined`.
267
+ */
240
268
  export interface InstanceSlot {
241
- block: BlockType;
242
- variant: string | null;
243
- /**
244
- * V2: the slot's pre-localized header, sent by tupac's `instance_slot_with_text` /
245
- * `instance_slot_with_header` envelopes (e.g. `"July 26"`, the transaction date).
246
- *
247
- * This is *not* a row field: under `with_header` a row's `secondary_text` is the category, so
248
- * the header has to come from here. Absent on the `logos_only` envelopes (micro/notification).
249
- */
250
- header_text?: string;
251
- /**
252
- * V2 (LargeTransactionV2 onward): rows carried inline on the slot. V1 blocks read their data
253
- * from `InsightsPayload.instance_slot_data` instead and leave this absent.
254
- */
255
- data_series?: InstanceSlotRow[];
269
+ block?: BlockType;
270
+ variant?: string | null;
271
+ /** The slots this block's variant declares in ditto. */
272
+ data?: InstanceSlotData;
256
273
  /** Primary line on the hero card, e.g. "Epic Bank Checking, *1234". */
257
274
  account_name?: string;
258
275
  /** Secondary line beneath the name, e.g. "Checking Account" / "Credit Card". */
@@ -0,0 +1,6 @@
1
+ var t = (o, r) => o?.[r];
2
+ export {
3
+ t as slot
4
+ };
5
+
6
+ //# sourceMappingURL=Insights.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Insights.es.js","names":[],"sources":["../../../src/core/types/Insights.ts"],"sourcesContent":["// ============ Core InsightsV2 Types ============\n\nimport { InsightsInstanceSlotData } from './InsightsInstanceSlotData'\n\nexport interface ThemedSVGImageProps {\n divProps?: React.HTMLAttributes<HTMLDivElement>\n image: React.ComponentType<React.SVGProps<SVGSVGElement>>\n isMini?: boolean\n}\n\n/**\n * Emitted by a block when the user drills into a specific datum (e.g. clicks a\n * chart bar). Named fields rather than positional args so blocks with differing\n * shapes can extend this without the call sites transposing values.\n */\nexport interface DrilldownPayload {\n chartBarIndex: number\n tabIndex?: number\n transaction_guid?: string\n block?: string\n}\n\n/**\n * Which envelope a beat was fetched with. `embedded` (the transaction-row pill + details-drawer\n * card) and `notification` are V2 additions; a surface asks for one with `widget_type=` on the fetch.\n */\nexport type WidgetType = 'full' | 'mini' | 'micro' | 'embedded' | 'notification'\n\n/**\n * V2: the transaction-row tag, its own small section of the `embedded` envelope (the same grammar\n * as `description` / `footer`, with room for a tone or an icon later). Omitted for an insight that\n * tags no transaction row. It deliberately is *not* `short_title`, which stays a per-variant\n * attribute with a second consumer (the bank-holiday sub-header).\n */\nexport interface Pill {\n text: string\n}\n\n/**\n * V2: facts a drilldown shows that the card does not (e.g. the account number for the Transaction\n * Details drawer). A flat hash shared by every CTA of the card, omitted when the insight has none.\n * Never carries copy or user actions (memo, tags, hide, flag come from the transaction store).\n */\nexport type DrilldownData = Record<string, string | number | boolean | null>\n\nexport interface InsightsPayload {\n widget_type: WidgetType\n instance_slot: InstanceSlot\n /**\n * V1 only. The v2 contract carries everything a block needs on `instance_slot.data`,\n * and omits this key entirely (see the LargeTransactionV2 payload). Blocks that still require it\n * get it as a required field through `BlockProps`, which re-declares it.\n */\n instance_slot_data?: InsightsInstanceSlotData\n description: Description\n primary_cta?: PrimaryCTA\n secondary_cta?: SecondaryCTA\n title?: string\n sub_title?: Subtitle\n /**\n * V2 rename of `sub_title`: a flat string, with the logo promoted to the payload-level `logo`\n * field below. `sub_title` wins when both are present.\n */\n subtitle?: string\n /** V2: header logo paired with the flat `subtitle`: an entity guid or a status icon (`LogoRef`). */\n logo?: LogoRef\n /** V2: which design branch the backend picked (e.g. `no_merchant`). */\n variant?: string\n /** V2, `embedded` envelope only: the transaction-row pill. */\n pill?: Pill\n /** V2: drilldown-only facts, e.g. `{ account_number: 'XXXXXXXX043' }`. */\n drilldown_data?: DrilldownData\n footer?: Footer\n // TODO: Add in_description_cta to insights_payload from backend\n guid: string\n user_guid: string\n client_guid?: string\n /** Template name, e.g. `LargeTransactionV2`. */\n template?: string\n revision?: number\n /** Unix seconds. */\n created_at?: number\n /** Unix seconds. */\n updated_at?: number\n /** Unix seconds. */\n active_at?: number\n displayed_at?: number | null\n dismissed_at: number | null\n cta_clicked_at?: number | null\n has_been_displayed?: boolean\n is_dismissed: boolean\n is_deleted?: boolean\n is_hidden_by_system?: boolean\n is_obsolete?: boolean\n is_refreshable?: boolean\n is_sampled?: boolean\n is_zero_state?: boolean\n status?: string | null\n /**\n * V2 (LargeTransactionV2 onward): the entities the beat is about, carried on the payload so\n * action blocks do not have to reach back out to the beat envelope.\n */\n primary_account_guid?: string | null\n primary_transaction_guid?: string | null\n primary_category_guid?: string | null\n primary_merchant_guid?: string | null\n /**\n * V2: the repeating transaction a subscription beat is about (Upcoming Subscription, Subscription\n * Price Increase). Read by `recurring_transaction_block`, see\n * `actionBlocks/RecurringTransactionBlock/subscriptionBeats.ts`.\n */\n primary_repeating_transaction_guid?: string | null\n}\n\nexport interface Legends {\n label: string\n value: number\n additional_value?: number\n additional_value_type?: string\n value_type?: string\n}\n\nexport interface Logo {\n category_guid?: string\n category_name?: string\n institution_guid?: string\n institution_name?: string\n logo_color?: string\n logo_name?: string\n merchant_guid?: string\n merchant_name?: string\n}\n\nexport interface Subtitle {\n logo?: Logo\n text: string\n}\n\n/**\n * A V2 logo, shared by the header (`InsightsPayload.logo`) and every instance-slot row. It takes\n * one of two shapes:\n *\n * - **Entity**: `guid`, whose prefix (`INS-` / `MCH-` / `CAT-`) picks the logo component, plus an\n * optional `fallback_guid` for when that component's asset cannot load. Today that is the\n * category behind an `MCH-` guid, which `MerchantLogo` shows as a tile when the merchant image\n * is missing.\n * - **Status icon**: `icon` (an mx-icons name, e.g. `warning`) and `color` (a theme palette path,\n * e.g. `error.main`), for subheaders that show a state rather than an entity (V1's\n * `logo_name` / `logo_color`).\n *\n * `alt` is the accessible name for either shape. A logo sends one shape; if it sends both, `icon`\n * wins, as `logo_name` does in V1's `SubHeader`.\n */\nexport interface LogoRef {\n alt?: string\n color?: string\n fallback_guid?: string\n guid?: string\n icon?: string\n}\n\nexport interface CategoryLogo {\n category_guid: string\n category_name: string\n}\n\nexport interface MerchantLogo {\n merchant_guid: string\n merchant_name: string\n}\n\nexport interface InstitutionLogo {\n institution_guid: string\n institution_name: string\n}\n\nexport interface Description {\n text: string\n html_text: string\n}\n\n/**\n * Post message a CTA press sends to the host, resolved by the backend for the beat's current\n * state. Absent/null = the backend has not described one: the frontend uses the template's\n * interim `ctaPostMessages` entry if there is one, else sends no message. `payload` carries only\n * beat-specific extras; the frontend always adds `beat_guid`, `beat_template`, `user_guid` and\n * `action_string`.\n */\nexport interface CtaPostMessageMetadata {\n /** Post message event; defaults to `beat/cta`. */\n event?: string | null\n /** Operation the host should perform, e.g. `op_1`, `op_2`, `op_3`. Defaults to `op_1`. */\n action?: string | null\n /** Beat-specific fields merged into the message metadata (account ids, amounts, ...). */\n payload?: Record<string, unknown> | null\n}\n\nexport interface PrimaryCTA {\n label: string\n block: string\n variant?: string | null\n /**\n * What pressing the CTA does beyond opening its block, named by the backend (ditto\n * `primary_cta_action`, passed through by tupac). Looked up in `insights-v2/ctaActions`;\n * null / absent / unknown means the CTA only opens its block or posts its message.\n */\n action_key?: string | null\n metadata?: CtaPostMessageMetadata | null\n}\n\nexport interface SecondaryCTA {\n label: string\n block: string\n variant?: string | null\n /** See `PrimaryCTA.action_key` (ditto `secondary_cta_action`). */\n action_key?: string | null\n metadata?: CtaPostMessageMetadata | null\n}\n\nexport interface Footer {\n /** V1: a pre-formatted date string. */\n date?: string\n /**\n * The account label, on both V1 and V2. The backend resolves the plurality: one account sends\n * its name (e.g. `Epic Bank`), several send a localized count (e.g. `2 Accounts`), none sends\n * nothing. There is deliberately no separate `accounts` key — see tupac's `footer_account_label`.\n */\n account?: string\n /**\n * V2 (LargeTransactionV2 onward): unix seconds, formatted by `Footer` for display.\n * Replaces `date`; `date` wins when a beat somehow sends both.\n */\n timestamp?: number\n}\n\n// ============ Instance Slot Types ============\n// Values are the snake_case block names the backend sends on a beat's instance slot; the PascalCase\n// keys stay as friendly references (e.g. BlockType.BarChartBlock === 'bar_chart_block').\nexport const BlockType = {\n AccountBlock: 'account_block',\n AccountSwitchBlock: 'account_switch_block',\n BarChartBlock: 'bar_chart_block',\n BudgetBlock: 'budget_block',\n ImageBlock: 'image_block',\n TransactionBlock: 'transaction_block',\n DonutChartBlock: 'donut_chart_block',\n DoubleBarChartBlock: 'double_bar_chart_block',\n DoubleProgressBarBlock: 'double_progress_bar_block',\n SaveExtraBlock: 'save_extra_block',\n StepChartBlock: 'step_chart_block',\n SVGImageBlock: 'svg_image_block',\n WithdrawalBlock: 'withdrawal_block',\n} as const\n\nexport type BlockType = (typeof BlockType)[keyof typeof BlockType]\n\n/**\n * A pre-localized row on a V2 instance slot. The backend resolves the copy and formatting; the\n * logo is a `LogoRef` (an entity guid or a status icon, see `logoFromRef`).\n */\nexport interface InstanceSlotRow {\n amount?: number\n logo?: LogoRef\n primary_text?: string\n secondary_text?: string\n}\n\n/**\n * V2: the slots a block's variant filled, keyed by slot name; ditto owns the names and omits any\n * slot it has no value for (`lib/ditto/blocks/<block>.yml`). Read with `slot()`, which names the\n * kind the caller expects.\n */\nexport interface InstanceSlotData {\n [slot: string]: unknown\n}\n\n/**\n * Reads one slot off a block's `data`; undefined when ditto did not fill it.\n *\n * The caller names the kind, because the slot's kind lives in the block's ditto schema and not\n * here — a block fills slots with whatever its card needs, so no fixed list of kinds would hold\n * (`account_switch_block` alone carries a boolean and `budget_block` a nested object).\n */\nexport const slot = <T = unknown>(\n data: InstanceSlotData | undefined,\n name: string,\n): T | undefined => data?.[name] as T | undefined\n\n/**\n * V2: which block renders this beat's content, and what it renders.\n *\n * `block` is optional: a beat whose template has no ditto config arrives as an empty `{}` and the\n * card renders its copy and CTAs alone, so a reader cannot assume a block is named. One interface\n * with `block` optional rather than a union with `Record<string, never>`, which TypeScript absorbs\n * — that union left `block` reading as required and typed a promise it did not keep.\n *\n * `variant` is optional for the same reason — the empty `{}` carries neither. Every ditto beat\n * file that names a block also names a variant, so a *filled* slot always has one; ditto drops a\n * nil variant rather than sending null, which is why the type is `string | null | undefined`.\n */\nexport interface InstanceSlot {\n block?: BlockType\n variant?: string | null\n /** The slots this block's variant declares in ditto. */\n data?: InstanceSlotData\n // Direct Deposit block (Set Up Direct Deposit, Switch Direct Deposit, Missing\n // Interest Rate): account facts carried flat on the slot, beside `data`.\n /** Primary line on the hero card, e.g. \"Epic Bank Checking, *1234\". */\n account_name?: string\n /** Secondary line beneath the name, e.g. \"Checking Account\" / \"Credit Card\". */\n account_type?: string\n /** Status pill label, e.g. \"Direct Deposit Not Set Up\" / \"Interest Rate: 19.99% APR\". */\n status_text?: string\n institution_guid?: string\n institution_name?: string\n}\n"],"mappings":"AA2RA,IAAa,IAAA,CACX,GACA,MACkB,IAAO,CAAA"}
@@ -13,7 +13,8 @@ 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, CtaPostMessageMetadata, SecondaryCTA, Subtitle, Footer, Logo, LogoRef, CategoryLogo, MerchantLogo, InstitutionLogo, Legends, } from './Insights';
16
+ export type { ThemedSVGImageProps, DrilldownData, DrilldownPayload, InsightsPayload, InstanceSlot, InstanceSlotData, Pill, WidgetType, InstanceSlotRow, BlockType, Description, PrimaryCTA, CtaPostMessageMetadata, SecondaryCTA, Subtitle, Footer, Logo, LogoRef, CategoryLogo, MerchantLogo, InstitutionLogo, Legends, } from './Insights';
17
+ export { slot } from './Insights';
17
18
  export type { Goal, MonthlyCashFlowProfile, RetirementGoalAccount } from './Goal';
18
19
  export type { Debt } from './Debt';
19
20
  export type { GlobalCaptureException, GlobalErrorHandler, GlobalEventHandler } from './Handlers';
@@ -1,3 +1,3 @@
1
1
  import { Theme } from '@mui/material/styles';
2
2
  import { InsightsInstanceSlotData } from '../../../../core/types/InsightsInstanceSlotData';
3
- export declare const getDonutChartColors: (variant: string | null, blockData: InsightsInstanceSlotData, theme: Theme) => [string, string];
3
+ export declare const getDonutChartColors: (variant: string | null | undefined, blockData: InsightsInstanceSlotData, theme: Theme) => [string, string];
@@ -1 +1 @@
1
- {"version":3,"file":"utils.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ChartBlocks/DonutChartBlock/utils.ts"],"sourcesContent":["import { type Theme } from '@mui/material/styles'\nimport { getCategoryColor } from '../../../../core/utils/CategoryUtil'\nimport { getLayoutConfig } from './layout'\nimport type { InsightsInstanceSlotData } from '../../../../core/types/InsightsInstanceSlotData'\n\nexport const getDonutChartColors = (\n variant: string | null,\n blockData: InsightsInstanceSlotData,\n theme: Theme,\n): [string, string] => {\n const layouts = getLayoutConfig(theme)\n const variantConfig = layouts[variant as keyof ReturnType<typeof getLayoutConfig>] as\n | { dynamicPrimary: string; secondaryColor: string }\n | { secondaryColor: string }\n | { colors: [string, string] }\n\n if ('dynamicPrimary' in variantConfig && variantConfig.dynamicPrimary === 'creditUtilization') {\n const utilization = Number(blockData.main?.value ?? 0)\n const primaryColor = utilization > 30 ? theme.palette.error.main : theme.palette.warning.main\n return [primaryColor, variantConfig.secondaryColor]\n }\n\n if ('secondaryColor' in variantConfig) {\n const categoryColor = getCategoryColor(blockData.category_guid ?? '', theme)\n return [categoryColor, variantConfig.secondaryColor]\n }\n\n return variantConfig.colors\n}\n"],"mappings":";;AAKA,IAAa,IAAA,CACX,GACA,GACA,MACqB;AAErB,QAAM,IADU,EAAgB,CACV,EAAQ,CAAA;AAK9B,SAAI,oBAAoB,KAAiB,EAAc,mBAAmB,sBAGjE,CAFa,OAAO,EAAU,MAAM,SAAS,CAC/B,IAAc,KAAK,EAAM,QAAQ,MAAM,OAAO,EAAM,QAAQ,QAAQ,MACnE,EAAc,cAAc,IAGhD,oBAAoB,IAEf,CADe,EAAiB,EAAU,iBAAiB,IAAI,CAC9D,GAAe,EAAc,cAAc,IAG9C,EAAc;AACvB"}
1
+ {"version":3,"file":"utils.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ChartBlocks/DonutChartBlock/utils.ts"],"sourcesContent":["import { type Theme } from '@mui/material/styles'\nimport { getCategoryColor } from '../../../../core/utils/CategoryUtil'\nimport { getLayoutConfig } from './layout'\nimport type { InsightsInstanceSlotData } from '../../../../core/types/InsightsInstanceSlotData'\n\nexport const getDonutChartColors = (\n variant: string | null | undefined,\n blockData: InsightsInstanceSlotData,\n theme: Theme,\n): [string, string] => {\n const layouts = getLayoutConfig(theme)\n const variantConfig = layouts[variant as keyof ReturnType<typeof getLayoutConfig>] as\n | { dynamicPrimary: string; secondaryColor: string }\n | { secondaryColor: string }\n | { colors: [string, string] }\n\n if ('dynamicPrimary' in variantConfig && variantConfig.dynamicPrimary === 'creditUtilization') {\n const utilization = Number(blockData.main?.value ?? 0)\n const primaryColor = utilization > 30 ? theme.palette.error.main : theme.palette.warning.main\n return [primaryColor, variantConfig.secondaryColor]\n }\n\n if ('secondaryColor' in variantConfig) {\n const categoryColor = getCategoryColor(blockData.category_guid ?? '', theme)\n return [categoryColor, variantConfig.secondaryColor]\n }\n\n return variantConfig.colors\n}\n"],"mappings":";;AAKA,IAAa,IAAA,CACX,GACA,GACA,MACqB;AAErB,QAAM,IADU,EAAgB,CACV,EAAQ,CAAA;AAK9B,SAAI,oBAAoB,KAAiB,EAAc,mBAAmB,sBAGjE,CAFa,OAAO,EAAU,MAAM,SAAS,CAC/B,IAAc,KAAK,EAAM,QAAQ,MAAM,OAAO,EAAM,QAAQ,QAAQ,MACnE,EAAc,cAAc,IAGhD,oBAAoB,IAEf,CADe,EAAiB,EAAU,iBAAiB,IAAI,CAC9D,GAAe,EAAc,cAAc,IAG9C,EAAc;AACvB"}
@@ -1,5 +1,5 @@
1
1
  import { Theme } from '@mui/material/styles';
2
- export declare const getLayoutConfig: (theme: Theme, variant: string | null) => {
2
+ export declare const getLayoutConfig: (theme: Theme, variant?: string | null) => {
3
3
  color: string[];
4
4
  } | {
5
5
  color: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"layout.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/layout.ts"],"sourcesContent":["import type { Theme } from '@mui/material/styles'\n\nexport const getLayoutConfig = (theme: Theme, variant: string | null) => {\n const config = {\n SpendToIncome: {\n color: [theme.palette.categories.billsUtilities, theme.palette.chart.chart1] as string[],\n },\n DebtToIncome: {\n color: [theme.palette.chart.chart5, theme.palette.chart.chart1] as string[],\n },\n SavingsToIncome: {\n color: [theme.palette.chartMono.chartMono5, theme.palette.chartMono.chartMono3] as string[],\n },\n }\n return config[variant as keyof typeof config]\n}\n"],"mappings":"AAEA,IAAa,IAAA,CAAmB,GAAc,OAYrC;AAAA,EAVL,eAAe,EACb,OAAO,CAAC,EAAM,QAAQ,WAAW,gBAAgB,EAAM,QAAQ,MAAM,MAAM,EAC7E;AAAA,EACA,cAAc,EACZ,OAAO,CAAC,EAAM,QAAQ,MAAM,QAAQ,EAAM,QAAQ,MAAM,MAAM,EAChE;AAAA,EACA,iBAAiB,EACf,OAAO,CAAC,EAAM,QAAQ,UAAU,YAAY,EAAM,QAAQ,UAAU,UAAU,EAChF;AAEK,GAAO,CAAA"}
1
+ {"version":3,"file":"layout.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/layout.ts"],"sourcesContent":["import type { Theme } from '@mui/material/styles'\n\nexport const getLayoutConfig = (theme: Theme, variant?: string | null) => {\n const config = {\n SpendToIncome: {\n color: [theme.palette.categories.billsUtilities, theme.palette.chart.chart1] as string[],\n },\n DebtToIncome: {\n color: [theme.palette.chart.chart5, theme.palette.chart.chart1] as string[],\n },\n SavingsToIncome: {\n color: [theme.palette.chartMono.chartMono5, theme.palette.chartMono.chartMono3] as string[],\n },\n }\n return config[variant as keyof typeof config]\n}\n"],"mappings":"AAEA,IAAa,IAAA,CAAmB,GAAc,OAYrC;AAAA,EAVL,eAAe,EACb,OAAO,CAAC,EAAM,QAAQ,WAAW,gBAAgB,EAAM,QAAQ,MAAM,MAAM,EAC7E;AAAA,EACA,cAAc,EACZ,OAAO,CAAC,EAAM,QAAQ,MAAM,QAAQ,EAAM,QAAQ,MAAM,MAAM,EAChE;AAAA,EACA,iBAAiB,EACf,OAAO,CAAC,EAAM,QAAQ,UAAU,YAAY,EAAM,QAAQ,UAAU,UAAU,EAChF;AAEK,GAAO,CAAA"}
@@ -1,7 +1,7 @@
1
1
  import { InsightsInstanceSlotData } from '../../../../core/types/InsightsInstanceSlotData';
2
2
  interface IconComponentProps {
3
3
  blockData: InsightsInstanceSlotData;
4
- variant: string | null;
4
+ variant?: string | null;
5
5
  }
6
6
  export declare const IconComponent: ({ blockData, variant }: IconComponentProps) => import("react/jsx-runtime").JSX.Element | null;
7
7
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"IconComponent.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/AccountBlock/IconComponent.tsx"],"sourcesContent":["import { Stack } from '@mui/material'\nimport { Icon } from '@mxenabled/mx-icons'\nimport { InstitutionLogo } from '@mxenabled/mxui'\nimport { IconBacking } from '../../../../common'\nimport { getLayoutConfig } from './layout'\nimport { useTheme } from '@mui/material/styles'\nimport type { InsightsInstanceSlotData } from '../../../../core/types/InsightsInstanceSlotData'\n\ninterface IconComponentProps {\n blockData: InsightsInstanceSlotData\n variant: string | null\n}\n\nexport const IconComponent = ({ blockData, variant }: IconComponentProps) => {\n const theme = useTheme()\n const layoutConfig = getLayoutConfig(theme)[variant as keyof ReturnType<typeof getLayoutConfig>]\n\n if (blockData.institution_guid) {\n return (\n <Stack sx={{ alignItems: 'center', flexDirection: 'row', position: 'relative' }}>\n <InstitutionLogo\n alt={`${blockData.institution_name}`}\n institutionGuid={`${blockData.institution_guid}`}\n size={48}\n />\n <IconBacking size={20} sx={{ position: 'absolute', right: -8, top: -8 }}>\n <Icon\n color=\"error\"\n fill={true}\n name=\"error\"\n size={20}\n sx={{ gridColumn: 1, gridRow: 1, zIndex: 2 }}\n />\n </IconBacking>\n </Stack>\n )\n }\n\n if (blockData.icon_name) {\n return (\n <Stack\n sx={{\n alignItems: 'center',\n bgcolor: layoutConfig.logo_bGcolor,\n borderRadius: '6px',\n height: 48,\n justifyContent: 'center',\n width: 48,\n ...(layoutConfig.logo_border_color && {\n borderColor: layoutConfig.logo_border_color,\n borderStyle: 'solid',\n borderWidth: 1.5,\n }),\n }}\n >\n <Icon\n name={blockData.icon_name}\n size={24}\n sx={{\n color: layoutConfig.logo_color,\n }}\n />\n </Stack>\n )\n }\n\n return null\n}\n"],"mappings":";;;;;;;AAaA,IAAa,IAAA,CAAiB,EAAE,WAAA,GAAW,SAAA,EAAA,MAAkC;AAC3E,QAAM,IAAQ,EAAS,GACjB,IAAe,EAAgB,CAAK,EAAE,CAAA;AAE5C,SAAI,EAAU,mBAEV,gBAAA,EAAC,GAAD;AAAA,IAAO,IAAI;AAAA,MAAE,YAAY;AAAA,MAAU,eAAe;AAAA,MAAO,UAAU;AAAA,IAAW;AAAA,IAA9E,UAAA,CACE,gBAAA,EAAC,GAAD;AAAA,MACE,KAAK,GAAG,EAAU,gBAAA;AAAA,MAClB,iBAAiB,GAAG,EAAU,gBAAA;AAAA,MAC9B,MAAM;AAAA,IACP,CAAA,GACD,gBAAA,EAAC,GAAD;AAAA,MAAa,MAAM;AAAA,MAAI,IAAI;AAAA,QAAE,UAAU;AAAA,QAAY,OAAO;AAAA,QAAI,KAAK;AAAA,MAAG;AAAA,MACpE,UAAA,gBAAA,EAAC,GAAD;AAAA,QACE,OAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAK;AAAA,QACL,MAAM;AAAA,QACN,IAAI;AAAA,UAAE,YAAY;AAAA,UAAG,SAAS;AAAA,UAAG,QAAQ;AAAA,QAAE;AAAA,MAC5C,CAAA;AAAA,IACU,CAAA,CACR;AAAA,OAIP,EAAU,YAEV,gBAAA,EAAC,GAAD;AAAA,IACE,IAAI;AAAA,MACF,YAAY;AAAA,MACZ,SAAS,EAAa;AAAA,MACtB,cAAc;AAAA,MACd,QAAQ;AAAA,MACR,gBAAgB;AAAA,MAChB,OAAO;AAAA,MACP,GAAI,EAAa,qBAAqB;AAAA,QACpC,aAAa,EAAa;AAAA,QAC1B,aAAa;AAAA,QACb,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IAEA,UAAA,gBAAA,EAAC,GAAD;AAAA,MACE,MAAM,EAAU;AAAA,MAChB,MAAM;AAAA,MACN,IAAI,EACF,OAAO,EAAa,WACtB;AAAA,IACD,CAAA;AAAA,EACI,CAAA,IAIJ;AACT"}
1
+ {"version":3,"file":"IconComponent.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/AccountBlock/IconComponent.tsx"],"sourcesContent":["import { Stack } from '@mui/material'\nimport { Icon } from '@mxenabled/mx-icons'\nimport { InstitutionLogo } from '@mxenabled/mxui'\nimport { IconBacking } from '../../../../common'\nimport { getLayoutConfig } from './layout'\nimport { useTheme } from '@mui/material/styles'\nimport type { InsightsInstanceSlotData } from '../../../../core/types/InsightsInstanceSlotData'\n\ninterface IconComponentProps {\n blockData: InsightsInstanceSlotData\n variant?: string | null\n}\n\nexport const IconComponent = ({ blockData, variant }: IconComponentProps) => {\n const theme = useTheme()\n const layoutConfig = getLayoutConfig(theme)[variant as keyof ReturnType<typeof getLayoutConfig>]\n\n if (blockData.institution_guid) {\n return (\n <Stack sx={{ alignItems: 'center', flexDirection: 'row', position: 'relative' }}>\n <InstitutionLogo\n alt={`${blockData.institution_name}`}\n institutionGuid={`${blockData.institution_guid}`}\n size={48}\n />\n <IconBacking size={20} sx={{ position: 'absolute', right: -8, top: -8 }}>\n <Icon\n color=\"error\"\n fill={true}\n name=\"error\"\n size={20}\n sx={{ gridColumn: 1, gridRow: 1, zIndex: 2 }}\n />\n </IconBacking>\n </Stack>\n )\n }\n\n if (blockData.icon_name) {\n return (\n <Stack\n sx={{\n alignItems: 'center',\n bgcolor: layoutConfig.logo_bGcolor,\n borderRadius: '6px',\n height: 48,\n justifyContent: 'center',\n width: 48,\n ...(layoutConfig.logo_border_color && {\n borderColor: layoutConfig.logo_border_color,\n borderStyle: 'solid',\n borderWidth: 1.5,\n }),\n }}\n >\n <Icon\n name={blockData.icon_name}\n size={24}\n sx={{\n color: layoutConfig.logo_color,\n }}\n />\n </Stack>\n )\n }\n\n return null\n}\n"],"mappings":";;;;;;;AAaA,IAAa,IAAA,CAAiB,EAAE,WAAA,GAAW,SAAA,EAAA,MAAkC;AAC3E,QAAM,IAAQ,EAAS,GACjB,IAAe,EAAgB,CAAK,EAAE,CAAA;AAE5C,SAAI,EAAU,mBAEV,gBAAA,EAAC,GAAD;AAAA,IAAO,IAAI;AAAA,MAAE,YAAY;AAAA,MAAU,eAAe;AAAA,MAAO,UAAU;AAAA,IAAW;AAAA,IAA9E,UAAA,CACE,gBAAA,EAAC,GAAD;AAAA,MACE,KAAK,GAAG,EAAU,gBAAA;AAAA,MAClB,iBAAiB,GAAG,EAAU,gBAAA;AAAA,MAC9B,MAAM;AAAA,IACP,CAAA,GACD,gBAAA,EAAC,GAAD;AAAA,MAAa,MAAM;AAAA,MAAI,IAAI;AAAA,QAAE,UAAU;AAAA,QAAY,OAAO;AAAA,QAAI,KAAK;AAAA,MAAG;AAAA,MACpE,UAAA,gBAAA,EAAC,GAAD;AAAA,QACE,OAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAK;AAAA,QACL,MAAM;AAAA,QACN,IAAI;AAAA,UAAE,YAAY;AAAA,UAAG,SAAS;AAAA,UAAG,QAAQ;AAAA,QAAE;AAAA,MAC5C,CAAA;AAAA,IACU,CAAA,CACR;AAAA,OAIP,EAAU,YAEV,gBAAA,EAAC,GAAD;AAAA,IACE,IAAI;AAAA,MACF,YAAY;AAAA,MACZ,SAAS,EAAa;AAAA,MACtB,cAAc;AAAA,MACd,QAAQ;AAAA,MACR,gBAAgB;AAAA,MAChB,OAAO;AAAA,MACP,GAAI,EAAa,qBAAqB;AAAA,QACpC,aAAa,EAAa;AAAA,QAC1B,aAAa;AAAA,QACb,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IAEA,UAAA,gBAAA,EAAC,GAAD;AAAA,MACE,MAAM,EAAU;AAAA,MAChB,MAAM;AAAA,MACN,IAAI,EACF,OAAO,EAAa,WACtB;AAAA,IACD,CAAA;AAAA,EACI,CAAA,IAIJ;AACT"}
@@ -15,11 +15,14 @@ export declare const TransactionBlockVariant: {
15
15
  /**
16
16
  * The `transaction_block` (ditto `blocks.name` for LargeTransactionV2).
17
17
  *
18
- * Renders rows the backend already localized and carried inline on `instance_slot.data_series`
18
+ * Renders rows the backend already localized and carried inline on `instance_slot.data.series`
19
19
  * (`logo`, `primary_text`, `secondary_text`, `amount`). Only the amount is formatted here,
20
20
  * because the contract sends it as a number.
21
21
  *
22
- * Under `with_header` the card header comes from `instance_slot.header_text`, which tupac sends
22
+ * This is the full/mini shape. The reduced widgets (micro, embedded) resolve to the row logo
23
+ * alone, carried flat on `data.logo` with no `series`, and are drawn by `CompactInsightCard`.
24
+ *
25
+ * Under `with_header` the card header comes from `instance_slot.data.header_text`, which tupac sends
23
26
  * as the transaction date. It deliberately does *not* come from the first row: on a `with_merchant`
24
27
  * card a row's `secondary_text` is the category, so reading it here rendered the category twice
25
28
  * and dropped the date entirely.
@@ -1,72 +1,73 @@
1
- import { useCategoryStore as u } from "../../../../common/context/hooks.es.js";
2
- import { formatCurrency as c } from "../../../../core/utils/NumberFormatting.es.js";
3
- import { logoFromRef as g } from "../../../components/shared/EntityLogo.es.js";
4
- import l from "../../../components/TransactionListCard.es.js";
5
- import { observer as _ } from "mobx-react-lite";
6
- import { CategoryIcon as f, InstitutionLogo as h, MerchantLogo as p } from "@mxenabled/mxui";
7
- import { Icon as y } from "@mxenabled/mx-icons";
8
- import { jsx as o } from "react/jsx-runtime";
9
- import m from "@mui/material/Box";
10
- var x = {
1
+ import { useCategoryStore as g } from "../../../../common/context/hooks.es.js";
2
+ import { slot as c } from "../../../../core/types/Insights.es.js";
3
+ import { formatCurrency as l } from "../../../../core/utils/NumberFormatting.es.js";
4
+ import { logoFromRef as _ } from "../../../components/shared/EntityLogo.es.js";
5
+ import f from "../../../components/TransactionListCard.es.js";
6
+ import { observer as h } from "mobx-react-lite";
7
+ import { CategoryIcon as y, InstitutionLogo as p, MerchantLogo as x } from "@mxenabled/mxui";
8
+ import { Icon as v } from "@mxenabled/mx-icons";
9
+ import { jsx as r } from "react/jsx-runtime";
10
+ import d from "@mui/material/Box";
11
+ var I = {
11
12
  WithHeader: "with_header",
12
13
  NoHeader: "no_header"
13
- }, r = 32, v = Math.round(r * 0.625), I = (i, n) => {
14
- const t = g(i.logo, i.primary_text);
14
+ }, o = 32, G = Math.round(o * 0.625), C = (i, n) => {
15
+ const t = _(i.logo, i.primary_text);
15
16
  if (t) {
16
- if (t.logo_name) return /* @__PURE__ */ o(m, {
17
+ if (t.logo_name) return /* @__PURE__ */ r(d, {
17
18
  sx: {
18
19
  alignItems: "center",
19
20
  display: "flex",
20
- height: r,
21
+ height: o,
21
22
  justifyContent: "center",
22
- width: r
23
+ width: o
23
24
  },
24
- children: /* @__PURE__ */ o(y, {
25
+ children: /* @__PURE__ */ r(v, {
25
26
  name: t.logo_name,
26
- size: v,
27
+ size: G,
27
28
  sx: { color: t.logo_color }
28
29
  })
29
30
  });
30
- if (t.merchant_guid) return /* @__PURE__ */ o(p, {
31
+ if (t.merchant_guid) return /* @__PURE__ */ r(x, {
31
32
  alt: t.merchant_name ?? "",
32
33
  categoryGuid: t.category_guid ? n(t.category_guid) : "",
33
34
  merchantGuid: t.merchant_guid,
34
- size: r
35
+ size: o
35
36
  });
36
- if (t.institution_guid) return /* @__PURE__ */ o(h, {
37
+ if (t.institution_guid) return /* @__PURE__ */ r(p, {
37
38
  alt: t.institution_name ?? "",
38
39
  institutionGuid: t.institution_guid,
39
- size: r
40
+ size: o
40
41
  });
41
42
  if (t.category_guid) {
42
43
  const a = n(t.category_guid);
43
- return /* @__PURE__ */ o(m, {
44
+ return /* @__PURE__ */ r(d, {
44
45
  "data-testid": `category-icon-${a}`,
45
46
  sx: { display: "flex" },
46
- children: /* @__PURE__ */ o(f, {
47
+ children: /* @__PURE__ */ r(y, {
47
48
  categoryGuid: a,
48
- size: r
49
+ size: o
49
50
  })
50
51
  });
51
52
  }
52
53
  }
53
- }, H = _(({ payload: i }) => {
54
- const { getTopLevelCategoryGuid: n } = u(), { data_series: t, header_text: a, variant: s } = i.instance_slot;
55
- if (!t?.length) return null;
56
- const d = s === x.WithHeader ? a : void 0;
57
- return /* @__PURE__ */ o(l, {
58
- header: d,
59
- rows: t.map((e) => ({
60
- amount: typeof e.amount == "number" ? c(e.amount, "0,0.00") : "",
61
- leading: I(e, n),
54
+ }, j = h(({ payload: i }) => {
55
+ const { getTopLevelCategoryGuid: n } = g(), { data: t, variant: a } = i.instance_slot, s = c(t, "series"), m = c(t, "header_text");
56
+ if (!Array.isArray(s) || !s.length) return null;
57
+ const u = a === I.WithHeader && typeof m == "string" ? m : void 0;
58
+ return /* @__PURE__ */ r(f, {
59
+ header: u,
60
+ rows: s.map((e) => ({
61
+ amount: typeof e.amount == "number" ? l(e.amount, "0,0.00") : "",
62
+ leading: C(e, n),
62
63
  subtitle: e.secondary_text ?? "",
63
64
  title: e.primary_text ?? ""
64
65
  }))
65
66
  });
66
67
  });
67
68
  export {
68
- H as TransactionBlock,
69
- x as TransactionBlockVariant
69
+ j as TransactionBlock,
70
+ I as TransactionBlockVariant
70
71
  };
71
72
 
72
73
  //# sourceMappingURL=TransactionBlock.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TransactionBlock.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/TransactionBlock/TransactionBlock.tsx"],"sourcesContent":["import { observer } from 'mobx-react-lite'\n\nimport Box from '@mui/material/Box'\n\nimport { CategoryIcon, InstitutionLogo, MerchantLogo } from '@mxenabled/mxui'\nimport { Icon } from '@mxenabled/mx-icons'\n\nimport { useCategoryStore } from '../../../../common'\nimport type { InsightsPayload, InstanceSlotRow } from '../../../../core'\nimport { formatCurrency } from '../../../../core/utils/NumberFormatting'\n\nimport TransactionListCard from '../../../components/TransactionListCard'\nimport { logoFromRef } from '../../../components/shared/EntityLogo'\n\ninterface TransactionBlockProps {\n payload: InsightsPayload\n beatGuid?: string\n}\n\n/**\n * Variants from ditto `lib/ditto/beats/large_transaction_v2.yml`:\n * - `with_header` — transaction row under a date header (the `with_merchant` card).\n * - `no_header` — the row alone (the `no_merchant` card).\n */\nexport const TransactionBlockVariant = {\n WithHeader: 'with_header',\n NoHeader: 'no_header',\n} as const\n\nconst ROW_LOGO_SIZE = 32\n// Same glyph-to-tile ratio mxui's `CategoryIcon` uses, so a status icon sits like the other logos.\nconst ROW_ICON_SIZE = Math.round(ROW_LOGO_SIZE * 0.625)\n\n/**\n * Renders the row's leading logo from its `LogoRef`: a status icon, or an entity guid whose prefix\n * names the entity. An unrecognized prefix renders no logo rather than guessing.\n *\n * `resolveTopLevelCategory`: mxui's `CategoryIcon` only knows the top-level category guids and\n * silently falls back to the Uncategorized icon for a sub-category. The details drawer avoids\n * this by passing `transaction.top_level_category_guid`; the row only has the raw guid, so it is\n * walked up to its parent here (identity until categories load). That applies both to a `CAT-`\n * row logo and to a merchant's `fallback_guid`, which `MerchantLogo` draws through the same\n * `CategoryIcon` when the merchant image fails to load.\n */\nconst renderRowLogo = (row: InstanceSlotRow, resolveTopLevelCategory: (guid: string) => string) => {\n const logo = logoFromRef(row.logo, row.primary_text)\n\n if (!logo) return undefined\n\n if (logo.logo_name) {\n // A fixed box the size of the other logos keeps the row's text column aligned.\n return (\n <Box\n sx={{\n alignItems: 'center',\n display: 'flex',\n height: ROW_LOGO_SIZE,\n justifyContent: 'center',\n width: ROW_LOGO_SIZE,\n }}\n >\n <Icon name={logo.logo_name} size={ROW_ICON_SIZE} sx={{ color: logo.logo_color }} />\n </Box>\n )\n }\n\n if (logo.merchant_guid) {\n return (\n <MerchantLogo\n alt={logo.merchant_name ?? ''}\n categoryGuid={logo.category_guid ? resolveTopLevelCategory(logo.category_guid) : ''}\n merchantGuid={logo.merchant_guid}\n size={ROW_LOGO_SIZE}\n />\n )\n }\n\n if (logo.institution_guid) {\n return (\n <InstitutionLogo\n alt={logo.institution_name ?? ''}\n institutionGuid={logo.institution_guid}\n size={ROW_LOGO_SIZE}\n />\n )\n }\n\n if (logo.category_guid) {\n const topLevelGuid = resolveTopLevelCategory(logo.category_guid)\n return (\n <Box data-testid={`category-icon-${topLevelGuid}`} sx={{ display: 'flex' }}>\n <CategoryIcon categoryGuid={topLevelGuid} size={ROW_LOGO_SIZE} />\n </Box>\n )\n }\n\n return undefined\n}\n\n/**\n * The `transaction_block` (ditto `blocks.name` for LargeTransactionV2).\n *\n * Renders rows the backend already localized and carried inline on `instance_slot.data_series`\n * (`logo`, `primary_text`, `secondary_text`, `amount`). Only the amount is formatted here,\n * because the contract sends it as a number.\n *\n * Under `with_header` the card header comes from `instance_slot.header_text`, which tupac sends\n * as the transaction date. It deliberately does *not* come from the first row: on a `with_merchant`\n * card a row's `secondary_text` is the category, so reading it here rendered the category twice\n * and dropped the date entirely.\n */\nexport const TransactionBlock = observer(({ payload }: TransactionBlockProps) => {\n const { getTopLevelCategoryGuid } = useCategoryStore()\n const { data_series: rows, header_text, variant } = payload.instance_slot\n\n if (!rows?.length) return null\n\n const header = variant === TransactionBlockVariant.WithHeader ? header_text : undefined\n\n return (\n <TransactionListCard\n header={header}\n rows={rows.map((row) => ({\n amount: typeof row.amount === 'number' ? formatCurrency(row.amount, '0,0.00') : '',\n leading: renderRowLogo(row, getTopLevelCategoryGuid),\n subtitle: row.secondary_text ?? '',\n title: row.primary_text ?? '',\n }))}\n />\n )\n})\n"],"mappings":";;;;;;;;;AAwBA,IAAa,IAA0B;AAAA,EACrC,YAAY;AAAA,EACZ,UAAU;AACZ,GAEM,IAAgB,IAEhB,IAAgB,KAAK,MAAM,IAAgB,KAAK,GAahD,IAAA,CAAiB,GAAsB,MAAsD;AACjG,QAAM,IAAO,EAAY,EAAI,MAAM,EAAI,YAAY;AAEnD,MAAK,GAEL;AAAA,QAAI,EAAK,UAEP,QACE,gBAAA,EAAC,GAAD;AAAA,MACE,IAAI;AAAA,QACF,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,gBAAgB;AAAA,QAChB,OAAO;AAAA,MACT;AAAA,MAEA,UAAA,gBAAA,EAAC,GAAD;AAAA,QAAM,MAAM,EAAK;AAAA,QAAW,MAAM;AAAA,QAAe,IAAI,EAAE,OAAO,EAAK,WAAW;AAAA,MAAI,CAAA;AAAA,IAC/E,CAAA;AAIT,QAAI,EAAK,cACP,QACE,gBAAA,EAAC,GAAD;AAAA,MACE,KAAK,EAAK,iBAAiB;AAAA,MAC3B,cAAc,EAAK,gBAAgB,EAAwB,EAAK,aAAa,IAAI;AAAA,MACjF,cAAc,EAAK;AAAA,MACnB,MAAM;AAAA,IACP,CAAA;AAIL,QAAI,EAAK,iBACP,QACE,gBAAA,EAAC,GAAD;AAAA,MACE,KAAK,EAAK,oBAAoB;AAAA,MAC9B,iBAAiB,EAAK;AAAA,MACtB,MAAM;AAAA,IACP,CAAA;AAIL,QAAI,EAAK,eAAe;AACtB,YAAM,IAAe,EAAwB,EAAK,aAAa;AAC/D,aACE,gBAAA,EAAC,GAAD;AAAA,QAAK,eAAa,iBAAiB,CAAA;AAAA,QAAgB,IAAI,EAAE,SAAS,OAAO;AAAA,QACvE,UAAA,gBAAA,EAAC,GAAD;AAAA,UAAc,cAAc;AAAA,UAAc,MAAM;AAAA,QAAgB,CAAA;AAAA,MAC7D,CAAA;AAAA,IAET;AAAA;AAGF,GAca,IAAmB,EAAA,CAAU,EAAE,SAAA,EAAA,MAAqC;AAC/E,QAAM,EAAE,yBAAA,EAAA,IAA4B,EAAiB,GAC/C,EAAE,aAAa,GAAM,aAAA,GAAa,SAAA,EAAA,IAAY,EAAQ;AAE5D,MAAI,CAAC,GAAM,OAAQ,QAAO;AAE1B,QAAM,IAAS,MAAY,EAAwB,aAAa,IAAc;AAE9E,SACE,gBAAA,EAAC,GAAD;AAAA,IACU,QAAA;AAAA,IACR,MAAM,EAAK,IAAA,CAAK,OAAS;AAAA,MACvB,QAAQ,OAAO,EAAI,UAAW,WAAW,EAAe,EAAI,QAAQ,QAAQ,IAAI;AAAA,MAChF,SAAS,EAAc,GAAK,CAAuB;AAAA,MACnD,UAAU,EAAI,kBAAkB;AAAA,MAChC,OAAO,EAAI,gBAAgB;AAAA,IAC7B,EAAE;AAAA,EACH,CAAA;AAEL,CAAC"}
1
+ {"version":3,"file":"TransactionBlock.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/TransactionBlock/TransactionBlock.tsx"],"sourcesContent":["import { observer } from 'mobx-react-lite'\n\nimport Box from '@mui/material/Box'\n\nimport { CategoryIcon, InstitutionLogo, MerchantLogo } from '@mxenabled/mxui'\nimport { Icon } from '@mxenabled/mx-icons'\n\nimport { useCategoryStore } from '../../../../common'\nimport { slot } from '../../../../core'\nimport type { InsightsPayload, InstanceSlotRow } from '../../../../core'\nimport { formatCurrency } from '../../../../core/utils/NumberFormatting'\n\nimport TransactionListCard from '../../../components/TransactionListCard'\nimport { logoFromRef } from '../../../components/shared/EntityLogo'\n\ninterface TransactionBlockProps {\n payload: InsightsPayload\n beatGuid?: string\n}\n\n/**\n * Variants from ditto `lib/ditto/beats/large_transaction_v2.yml`:\n * - `with_header` — transaction row under a date header (the `with_merchant` card).\n * - `no_header` — the row alone (the `no_merchant` card).\n */\nexport const TransactionBlockVariant = {\n WithHeader: 'with_header',\n NoHeader: 'no_header',\n} as const\n\nconst ROW_LOGO_SIZE = 32\n// Same glyph-to-tile ratio mxui's `CategoryIcon` uses, so a status icon sits like the other logos.\nconst ROW_ICON_SIZE = Math.round(ROW_LOGO_SIZE * 0.625)\n\n/**\n * Renders the row's leading logo from its `LogoRef`: a status icon, or an entity guid whose prefix\n * names the entity. An unrecognized prefix renders no logo rather than guessing.\n *\n * `resolveTopLevelCategory`: mxui's `CategoryIcon` only knows the top-level category guids and\n * silently falls back to the Uncategorized icon for a sub-category. The details drawer avoids\n * this by passing `transaction.top_level_category_guid`; the row only has the raw guid, so it is\n * walked up to its parent here (identity until categories load). That applies both to a `CAT-`\n * row logo and to a merchant's `fallback_guid`, which `MerchantLogo` draws through the same\n * `CategoryIcon` when the merchant image fails to load.\n */\nconst renderRowLogo = (row: InstanceSlotRow, resolveTopLevelCategory: (guid: string) => string) => {\n const logo = logoFromRef(row.logo, row.primary_text)\n\n if (!logo) return undefined\n\n if (logo.logo_name) {\n // A fixed box the size of the other logos keeps the row's text column aligned.\n return (\n <Box\n sx={{\n alignItems: 'center',\n display: 'flex',\n height: ROW_LOGO_SIZE,\n justifyContent: 'center',\n width: ROW_LOGO_SIZE,\n }}\n >\n <Icon name={logo.logo_name} size={ROW_ICON_SIZE} sx={{ color: logo.logo_color }} />\n </Box>\n )\n }\n\n if (logo.merchant_guid) {\n return (\n <MerchantLogo\n alt={logo.merchant_name ?? ''}\n categoryGuid={logo.category_guid ? resolveTopLevelCategory(logo.category_guid) : ''}\n merchantGuid={logo.merchant_guid}\n size={ROW_LOGO_SIZE}\n />\n )\n }\n\n if (logo.institution_guid) {\n return (\n <InstitutionLogo\n alt={logo.institution_name ?? ''}\n institutionGuid={logo.institution_guid}\n size={ROW_LOGO_SIZE}\n />\n )\n }\n\n if (logo.category_guid) {\n const topLevelGuid = resolveTopLevelCategory(logo.category_guid)\n return (\n <Box data-testid={`category-icon-${topLevelGuid}`} sx={{ display: 'flex' }}>\n <CategoryIcon categoryGuid={topLevelGuid} size={ROW_LOGO_SIZE} />\n </Box>\n )\n }\n\n return undefined\n}\n\n/**\n * The `transaction_block` (ditto `blocks.name` for LargeTransactionV2).\n *\n * Renders rows the backend already localized and carried inline on `instance_slot.data.series`\n * (`logo`, `primary_text`, `secondary_text`, `amount`). Only the amount is formatted here,\n * because the contract sends it as a number.\n *\n * This is the full/mini shape. The reduced widgets (micro, embedded) resolve to the row logo\n * alone, carried flat on `data.logo` with no `series`, and are drawn by `CompactInsightCard`.\n *\n * Under `with_header` the card header comes from `instance_slot.data.header_text`, which tupac sends\n * as the transaction date. It deliberately does *not* come from the first row: on a `with_merchant`\n * card a row's `secondary_text` is the category, so reading it here rendered the category twice\n * and dropped the date entirely.\n */\nexport const TransactionBlock = observer(({ payload }: TransactionBlockProps) => {\n const { getTopLevelCategoryGuid } = useCategoryStore()\n const { data, variant } = payload.instance_slot\n const series = slot<InstanceSlotRow[]>(data, 'series')\n const headerText = slot<string>(data, 'header_text')\n\n if (!Array.isArray(series) || !series.length) return null\n\n const header =\n variant === TransactionBlockVariant.WithHeader && typeof headerText === 'string'\n ? headerText\n : undefined\n\n return (\n <TransactionListCard\n header={header}\n rows={series.map((row) => ({\n amount: typeof row.amount === 'number' ? formatCurrency(row.amount, '0,0.00') : '',\n leading: renderRowLogo(row, getTopLevelCategoryGuid),\n subtitle: row.secondary_text ?? '',\n title: row.primary_text ?? '',\n }))}\n />\n )\n})\n"],"mappings":";;;;;;;;;;AAyBA,IAAa,IAA0B;AAAA,EACrC,YAAY;AAAA,EACZ,UAAU;AACZ,GAEM,IAAgB,IAEhB,IAAgB,KAAK,MAAM,IAAgB,KAAK,GAahD,IAAA,CAAiB,GAAsB,MAAsD;AACjG,QAAM,IAAO,EAAY,EAAI,MAAM,EAAI,YAAY;AAEnD,MAAK,GAEL;AAAA,QAAI,EAAK,UAEP,QACE,gBAAA,EAAC,GAAD;AAAA,MACE,IAAI;AAAA,QACF,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,gBAAgB;AAAA,QAChB,OAAO;AAAA,MACT;AAAA,MAEA,UAAA,gBAAA,EAAC,GAAD;AAAA,QAAM,MAAM,EAAK;AAAA,QAAW,MAAM;AAAA,QAAe,IAAI,EAAE,OAAO,EAAK,WAAW;AAAA,MAAI,CAAA;AAAA,IAC/E,CAAA;AAIT,QAAI,EAAK,cACP,QACE,gBAAA,EAAC,GAAD;AAAA,MACE,KAAK,EAAK,iBAAiB;AAAA,MAC3B,cAAc,EAAK,gBAAgB,EAAwB,EAAK,aAAa,IAAI;AAAA,MACjF,cAAc,EAAK;AAAA,MACnB,MAAM;AAAA,IACP,CAAA;AAIL,QAAI,EAAK,iBACP,QACE,gBAAA,EAAC,GAAD;AAAA,MACE,KAAK,EAAK,oBAAoB;AAAA,MAC9B,iBAAiB,EAAK;AAAA,MACtB,MAAM;AAAA,IACP,CAAA;AAIL,QAAI,EAAK,eAAe;AACtB,YAAM,IAAe,EAAwB,EAAK,aAAa;AAC/D,aACE,gBAAA,EAAC,GAAD;AAAA,QAAK,eAAa,iBAAiB,CAAA;AAAA,QAAgB,IAAI,EAAE,SAAS,OAAO;AAAA,QACvE,UAAA,gBAAA,EAAC,GAAD;AAAA,UAAc,cAAc;AAAA,UAAc,MAAM;AAAA,QAAgB,CAAA;AAAA,MAC7D,CAAA;AAAA,IAET;AAAA;AAGF,GAiBa,IAAmB,EAAA,CAAU,EAAE,SAAA,EAAA,MAAqC;AAC/E,QAAM,EAAE,yBAAA,EAAA,IAA4B,EAAiB,GAC/C,EAAE,MAAA,GAAM,SAAA,EAAA,IAAY,EAAQ,eAC5B,IAAS,EAAwB,GAAM,QAAQ,GAC/C,IAAa,EAAa,GAAM,aAAa;AAEnD,MAAI,CAAC,MAAM,QAAQ,CAAM,KAAK,CAAC,EAAO,OAAQ,QAAO;AAErD,QAAM,IACJ,MAAY,EAAwB,cAAc,OAAO,KAAe,WACpE,IACA;AAEN,SACE,gBAAA,EAAC,GAAD;AAAA,IACU,QAAA;AAAA,IACR,MAAM,EAAO,IAAA,CAAK,OAAS;AAAA,MACzB,QAAQ,OAAO,EAAI,UAAW,WAAW,EAAe,EAAI,QAAQ,QAAQ,IAAI;AAAA,MAChF,SAAS,EAAc,GAAK,CAAuB;AAAA,MACnD,UAAU,EAAI,kBAAkB;AAAA,MAChC,OAAO,EAAI,gBAAgB;AAAA,IAC7B,EAAE;AAAA,EACH,CAAA;AAEL,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { BlockProps } from '../../types';
2
- /** The Withdrawal row on `instance_slot.data_series`. */
2
+ /** The Withdrawal row on `instance_slot.data.series`. */
3
3
  export interface WithdrawalRow {
4
4
  amount?: number;
5
5
  amount_label?: string;
@@ -9,7 +9,7 @@ export interface WithdrawalRow {
9
9
  }
10
10
  /**
11
11
  * The `withdrawal_block` (Highlight Withdrawal), reading one row on
12
- * `instance_slot.data_series`. Text (`amount_label`, `withdrawal_date`,
12
+ * `instance_slot.data.series`. Text (`amount_label`, `withdrawal_date`,
13
13
  * `balance_label`) renders as sent; `amount` and `balance` are numbers and are formatted by the
14
14
  * card. Renders nothing unless the row carries both numbers.
15
15
  */
@@ -1,11 +1,12 @@
1
- import l from "../../../components/WithdrawalCard.es.js";
1
+ import { slot as l } from "../../../../core/types/Insights.es.js";
2
+ import o from "../../../components/WithdrawalCard.es.js";
2
3
  import n from "@mui/material/Stack";
3
4
  import { jsx as t } from "react/jsx-runtime";
4
- var s = ({ payload: e }) => {
5
- const r = e.instance_slot.data_series, [a] = Array.isArray(r) ? r : [];
5
+ var c = ({ payload: e }) => {
6
+ const r = l(e.instance_slot.data, "series"), [a] = Array.isArray(r) ? r : [];
6
7
  return !Number.isFinite(a?.amount) || !Number.isFinite(a?.balance) ? null : /* @__PURE__ */ t(n, {
7
8
  sx: { px: 16 },
8
- children: /* @__PURE__ */ t(l, {
9
+ children: /* @__PURE__ */ t(o, {
9
10
  amount: a.amount,
10
11
  amountLabel: a.amount_label,
11
12
  balance: a.balance,
@@ -15,7 +16,7 @@ var s = ({ payload: e }) => {
15
16
  });
16
17
  };
17
18
  export {
18
- s as default
19
+ c as default
19
20
  };
20
21
 
21
22
  //# sourceMappingURL=WithdrawalBlock.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"WithdrawalBlock.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/WithdrawalBlock/WithdrawalBlock.tsx"],"sourcesContent":["import Stack from '@mui/material/Stack'\n\nimport WithdrawalCard from '../../../components/WithdrawalCard'\nimport type { BlockProps } from '../../types'\n\n/** The Withdrawal row on `instance_slot.data_series`. */\nexport interface WithdrawalRow {\n amount?: number\n amount_label?: string\n balance?: number\n balance_label?: string\n withdrawal_date?: string\n}\n\n/**\n * The `withdrawal_block` (Highlight Withdrawal), reading one row on\n * `instance_slot.data_series`. Text (`amount_label`, `withdrawal_date`,\n * `balance_label`) renders as sent; `amount` and `balance` are numbers and are formatted by the\n * card. Renders nothing unless the row carries both numbers.\n */\nconst WithdrawalBlock = ({ payload }: BlockProps) => {\n const rows = payload.instance_slot.data_series\n const [row] = (Array.isArray(rows) ? rows : []) as WithdrawalRow[]\n\n if (!Number.isFinite(row?.amount) || !Number.isFinite(row?.balance)) return null\n\n return (\n <Stack sx={{ px: 16 }}>\n <WithdrawalCard\n amount={row.amount as number}\n amountLabel={row.amount_label}\n balance={row.balance as number}\n balanceLabel={row.balance_label}\n withdrawalDate={row.withdrawal_date}\n />\n </Stack>\n )\n}\n\nexport default WithdrawalBlock\n"],"mappings":";;;AAoBA,IAAM,IAAA,CAAmB,EAAE,SAAA,EAAA,MAA0B;AACnD,QAAM,IAAO,EAAQ,cAAc,aAC7B,CAAC,CAAA,IAAQ,MAAM,QAAQ,CAAI,IAAI,IAAO,CAAC;AAE7C,SAAI,CAAC,OAAO,SAAS,GAAK,MAAM,KAAK,CAAC,OAAO,SAAS,GAAK,OAAO,IAAU,OAG1E,gBAAA,EAAC,GAAD;AAAA,IAAO,IAAI,EAAE,IAAI,GAAG;AAAA,IAClB,UAAA,gBAAA,EAAC,GAAD;AAAA,MACE,QAAQ,EAAI;AAAA,MACZ,aAAa,EAAI;AAAA,MACjB,SAAS,EAAI;AAAA,MACb,cAAc,EAAI;AAAA,MAClB,gBAAgB,EAAI;AAAA,IACrB,CAAA;AAAA,EACI,CAAA;AAEX"}
1
+ {"version":3,"file":"WithdrawalBlock.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/WithdrawalBlock/WithdrawalBlock.tsx"],"sourcesContent":["import Stack from '@mui/material/Stack'\n\nimport { slot } from '../../../../core'\nimport WithdrawalCard from '../../../components/WithdrawalCard'\nimport type { BlockProps } from '../../types'\n\n/** The Withdrawal row on `instance_slot.data.series`. */\nexport interface WithdrawalRow {\n amount?: number\n amount_label?: string\n balance?: number\n balance_label?: string\n withdrawal_date?: string\n}\n\n/**\n * The `withdrawal_block` (Highlight Withdrawal), reading one row on\n * `instance_slot.data.series`. Text (`amount_label`, `withdrawal_date`,\n * `balance_label`) renders as sent; `amount` and `balance` are numbers and are formatted by the\n * card. Renders nothing unless the row carries both numbers.\n */\nconst WithdrawalBlock = ({ payload }: BlockProps) => {\n const rows = slot<WithdrawalRow[]>(payload.instance_slot.data, 'series')\n const [row] = Array.isArray(rows) ? rows : []\n\n if (!Number.isFinite(row?.amount) || !Number.isFinite(row?.balance)) return null\n\n return (\n <Stack sx={{ px: 16 }}>\n <WithdrawalCard\n amount={row.amount as number}\n amountLabel={row.amount_label}\n balance={row.balance as number}\n balanceLabel={row.balance_label}\n withdrawalDate={row.withdrawal_date}\n />\n </Stack>\n )\n}\n\nexport default WithdrawalBlock\n"],"mappings":";;;;AAqBA,IAAM,IAAA,CAAmB,EAAE,SAAA,EAAA,MAA0B;AACnD,QAAM,IAAO,EAAsB,EAAQ,cAAc,MAAM,QAAQ,GACjE,CAAC,CAAA,IAAO,MAAM,QAAQ,CAAI,IAAI,IAAO,CAAC;AAE5C,SAAI,CAAC,OAAO,SAAS,GAAK,MAAM,KAAK,CAAC,OAAO,SAAS,GAAK,OAAO,IAAU,OAG1E,gBAAA,EAAC,GAAD;AAAA,IAAO,IAAI,EAAE,IAAI,GAAG;AAAA,IAClB,UAAA,gBAAA,EAAC,GAAD;AAAA,MACE,QAAQ,EAAI;AAAA,MACZ,aAAa,EAAI;AAAA,MACjB,SAAS,EAAI;AAAA,MACb,cAAc,EAAI;AAAA,MAClB,gBAAgB,EAAI;AAAA,IACrB,CAAA;AAAA,EACI,CAAA;AAEX"}
@@ -1,4 +1,4 @@
1
- export declare const getLayoutConfig: (variant: string | null, isCibc?: boolean) => {
1
+ export declare const getLayoutConfig: (variant?: string | null, isCibc?: boolean) => {
2
2
  image: import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
3
3
  } | {
4
4
  image: import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
@@ -1 +1 @@
1
- {"version":3,"file":"layout.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ImageBlocks/SVGImageBlock/layout.ts"],"sourcesContent":["// SVGs to be moved to S3 and imported from there.\nimport { ReactComponent as UpcomingTaxDeadline } from './images/UpcomingTaxDeadlineAlert.svg'\nimport { ReactComponent as UpcomingTaxDeadlineCIBC } from './images/UpcomingTaxDeadlineAlertCIBC.svg'\n\nimport { ReactComponent as FederalBankHoliday } from './images/FederalBankHoliday.svg'\nimport { ReactComponent as FederalBankHolidayCIBC } from './images/FederalBankHolidayCibc.svg'\n\nimport { ReactComponent as DesignateEmergencySavingsAccount } from './images/DesignateEmergencySavingsAccount.svg'\n\nexport const getLayoutConfig = (variant: string | null, isCibc: boolean = false) => {\n const config = {\n Holiday: {\n image: isCibc ? FederalBankHolidayCIBC : FederalBankHoliday,\n },\n Reminder: {\n image: isCibc ? UpcomingTaxDeadlineCIBC : UpcomingTaxDeadline,\n },\n Savings: {\n image: DesignateEmergencySavingsAccount,\n },\n }\n return config[variant as keyof typeof config]\n}\n"],"mappings":";;;;;AASA,IAAa,IAAA,CAAmB,GAAwB,IAAkB,QAYjE;AAAA,EAVL,SAAS,EACP,OAAO,IAAS,IAAyB,EAC3C;AAAA,EACA,UAAU,EACR,OAAO,IAAS,IAA0B,EAC5C;AAAA,EACA,SAAS,EACP,OAAO,EACT;AAEK,GAAO,CAAA"}
1
+ {"version":3,"file":"layout.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ImageBlocks/SVGImageBlock/layout.ts"],"sourcesContent":["// SVGs to be moved to S3 and imported from there.\nimport { ReactComponent as UpcomingTaxDeadline } from './images/UpcomingTaxDeadlineAlert.svg'\nimport { ReactComponent as UpcomingTaxDeadlineCIBC } from './images/UpcomingTaxDeadlineAlertCIBC.svg'\n\nimport { ReactComponent as FederalBankHoliday } from './images/FederalBankHoliday.svg'\nimport { ReactComponent as FederalBankHolidayCIBC } from './images/FederalBankHolidayCibc.svg'\n\nimport { ReactComponent as DesignateEmergencySavingsAccount } from './images/DesignateEmergencySavingsAccount.svg'\n\nexport const getLayoutConfig = (variant?: string | null, isCibc: boolean = false) => {\n const config = {\n Holiday: {\n image: isCibc ? FederalBankHolidayCIBC : FederalBankHoliday,\n },\n Reminder: {\n image: isCibc ? UpcomingTaxDeadlineCIBC : UpcomingTaxDeadline,\n },\n Savings: {\n image: DesignateEmergencySavingsAccount,\n },\n }\n return config[variant as keyof typeof config]\n}\n"],"mappings":";;;;;AASA,IAAa,IAAA,CAAmB,GAAyB,IAAkB,QAYlE;AAAA,EAVL,SAAS,EACP,OAAO,IAAS,IAAyB,EAC3C;AAAA,EACA,UAAU,EACR,OAAO,IAAS,IAA0B,EAC5C;AAAA,EACA,SAAS,EACP,OAAO,EACT;AAEK,GAAO,CAAA"}
@@ -19,13 +19,13 @@ export interface CompactInsightCardProps {
19
19
  * The one compact renderer the micro and embedded envelopes share (`insights_v2.2.md` §8.3).
20
20
  *
21
21
  * Figma 1941:111897 (Embedded | Large Transaction): a title row with the overflow slot, the HTML
22
- * description with the primary CTA under it, and on the right the first slot row's logo in a
23
- * `<BadgedTile>`. Under ditto's `embedded` variant the tile takes a status badge; micro sends no
24
- * variant and draws the logo alone. The card lays out from the envelope alone and never reads
22
+ * description with the primary CTA under it, and on the right the slot's `logo` in a
23
+ * `<BadgedTile>`. Under ditto's `with_warning_badge` variant the tile takes a status badge; under
24
+ * `minimal` it draws the logo alone. The card lays out from the envelope alone and never reads
25
25
  * `widget_type`.
26
26
  *
27
27
  * The icon falls back to the neutral insight glyph **here**, not in `LogoFromGuid`, when the slot
28
- * has no row. The `pill` on the same envelope is the transaction row's, not the card's.
28
+ * carries no logo. The `pill` on the same envelope is the transaction row's, not the card's.
29
29
  */
30
30
  declare const CompactInsightCard: ({ isCtaDisabled, onCtaClick, onTap, payload, }: CompactInsightCardProps) => import("react/jsx-runtime").JSX.Element;
31
31
  export default CompactInsightCard;
@@ -1,57 +1,61 @@
1
- import { createVariantBlock as b } from "../blocks/createVariantBlock.es.js";
2
- import c from "./BadgedTile.es.js";
3
- import { InsightOptionsMenu as y } from "./InsightOptionsMenu.es.js";
4
- import k from "./LogoFromGuid.es.js";
5
- import I from "./StatusBadge.es.js";
1
+ import { slot as y } from "../../core/types/Insights.es.js";
2
+ import { createVariantBlock as k } from "../blocks/createVariantBlock.es.js";
3
+ import m from "./BadgedTile.es.js";
4
+ import { InsightOptionsMenu as I } from "./InsightOptionsMenu.es.js";
5
+ import w from "./LogoFromGuid.es.js";
6
+ import v from "./StatusBadge.es.js";
6
7
  import l from "@mui/material/Stack";
7
- import { P as v, Text as w } from "@mxenabled/mxui";
8
- import C from "@mui/material/Button";
9
- import { Icon as S } from "@mxenabled/mx-icons";
8
+ import { P as C, Text as _ } from "@mxenabled/mxui";
9
+ import S from "@mui/material/Button";
10
+ import { Icon as B } from "@mxenabled/mx-icons";
10
11
  import { jsx as t, jsxs as n } from "react/jsx-runtime";
11
- import d from "@mui/material/Box";
12
- import _ from "@mui/material/Card";
13
- var e = 44, m = ({ logo: r }) => r ? /* @__PURE__ */ t(k, {
12
+ import p from "@mui/material/Box";
13
+ import z from "@mui/material/Card";
14
+ var a = 44, d = ({ logo: r }) => r ? /* @__PURE__ */ t(w, {
14
15
  logo: r,
15
- size: e
16
- }) : /* @__PURE__ */ t(d, {
16
+ size: a
17
+ }) : /* @__PURE__ */ t(p, {
17
18
  "data-testid": "compact-insight-card-fallback-icon",
18
19
  sx: {
19
20
  alignItems: "center",
20
21
  bgcolor: "primary.lighter",
21
22
  display: "flex",
22
- height: e,
23
+ height: a,
23
24
  justifyContent: "center",
24
- width: e
25
+ width: a
25
26
  },
26
- children: /* @__PURE__ */ t(S, {
27
+ children: /* @__PURE__ */ t(B, {
27
28
  color: "primary",
28
29
  fill: !0,
29
30
  name: "lightbulb",
30
31
  size: 24
31
32
  })
32
- }), z = ({ logo: r }) => /* @__PURE__ */ t(c, {
33
- center: /* @__PURE__ */ t(m, { logo: r }),
34
- size: e,
33
+ }), c = ({ logo: r }) => /* @__PURE__ */ t(m, {
34
+ center: /* @__PURE__ */ t(d, { logo: r }),
35
+ size: a,
35
36
  sx: { flexShrink: 0 }
36
- }), B = ({ logo: r }) => /* @__PURE__ */ t(c, {
37
- center: /* @__PURE__ */ t(m, { logo: r }),
38
- size: e,
37
+ }), P = ({ logo: r }) => /* @__PURE__ */ t(m, {
38
+ center: /* @__PURE__ */ t(d, { logo: r }),
39
+ size: a,
39
40
  sx: { flexShrink: 0 },
40
- topRight: /* @__PURE__ */ t(I, { tone: "warning" })
41
- }), P = b({
42
- variants: { embedded: B },
43
- fallback: z,
41
+ topRight: /* @__PURE__ */ t(v, { tone: "warning" })
42
+ }), V = k({
43
+ variants: {
44
+ minimal: c,
45
+ with_warning_badge: P
46
+ },
47
+ fallback: c,
44
48
  name: "InsightVisual"
45
- }), V = (r) => r.stopPropagation(), T = ({ isCtaDisabled: r = !1, onCtaClick: p, onTap: a, payload: f }) => {
46
- const { description: g, instance_slot: s, primary_cta: o, title: h } = f, x = s.data_series?.[0]?.logo, u = (i) => {
47
- i.stopPropagation(), !(r || !o) && p?.(o);
49
+ }), j = (r) => r.stopPropagation(), $ = ({ isCtaDisabled: r = !1, onCtaClick: g, onTap: e, payload: f }) => {
50
+ const { description: h, instance_slot: s, primary_cta: o, title: x } = f, u = y(s.data, "logo"), b = (i) => {
51
+ i.stopPropagation(), !(r || !o) && g?.(o);
48
52
  };
49
- return /* @__PURE__ */ n(_, {
53
+ return /* @__PURE__ */ n(z, {
50
54
  "data-testid": "compact-insight-card",
51
- ...a ? {
52
- onClick: a,
55
+ ...e ? {
56
+ onClick: e,
53
57
  onKeyDown: (i) => {
54
- i.target === i.currentTarget && (i.key === "Enter" || i.key === " ") && (i.preventDefault(), a?.());
58
+ i.target === i.currentTarget && (i.key === "Enter" || i.key === " ") && (i.preventDefault(), e?.());
55
59
  },
56
60
  role: "button",
57
61
  tabIndex: 0
@@ -62,7 +66,7 @@ var e = 44, m = ({ logo: r }) => r ? /* @__PURE__ */ t(k, {
62
66
  pl: 8,
63
67
  pr: 16,
64
68
  pt: 8,
65
- ...a && { cursor: "pointer" }
69
+ ...e && { cursor: "pointer" }
66
70
  },
67
71
  children: [/* @__PURE__ */ n(l, {
68
72
  sx: {
@@ -73,14 +77,14 @@ var e = 44, m = ({ logo: r }) => r ? /* @__PURE__ */ t(k, {
73
77
  pl: 8,
74
78
  pt: 4
75
79
  },
76
- children: [/* @__PURE__ */ t(w, {
80
+ children: [/* @__PURE__ */ t(_, {
77
81
  bold: !0,
78
82
  variant: "body1",
79
- children: h ?? ""
80
- }), /* @__PURE__ */ t(d, {
81
- onClick: V,
83
+ children: x ?? ""
84
+ }), /* @__PURE__ */ t(p, {
85
+ onClick: j,
82
86
  sx: { display: "flex" },
83
- children: /* @__PURE__ */ t(y, {})
87
+ children: /* @__PURE__ */ t(I, {})
84
88
  })]
85
89
  }), /* @__PURE__ */ n(l, {
86
90
  sx: {
@@ -95,13 +99,13 @@ var e = 44, m = ({ logo: r }) => r ? /* @__PURE__ */ t(k, {
95
99
  gap: 8,
96
100
  minWidth: 0
97
101
  },
98
- children: [/* @__PURE__ */ t(v, {
99
- dangerouslySetInnerHTML: { __html: g.html_text },
102
+ children: [/* @__PURE__ */ t(C, {
103
+ dangerouslySetInnerHTML: { __html: h.html_text },
100
104
  "data-testid": "compact-insight-card-description",
101
105
  variant: "subtitle2"
102
- }), o?.label && /* @__PURE__ */ t(C, {
106
+ }), o?.label && /* @__PURE__ */ t(S, {
103
107
  "aria-disabled": r,
104
- onClick: u,
108
+ onClick: b,
105
109
  size: "small",
106
110
  sx: {
107
111
  alignSelf: "flex-start",
@@ -115,15 +119,15 @@ var e = 44, m = ({ logo: r }) => r ? /* @__PURE__ */ t(k, {
115
119
  variant: "text",
116
120
  children: o.label
117
121
  })]
118
- }), /* @__PURE__ */ t(P, {
119
- logo: x,
122
+ }), /* @__PURE__ */ t(V, {
123
+ logo: u,
120
124
  variant: s.variant
121
125
  })]
122
126
  })]
123
127
  });
124
128
  };
125
129
  export {
126
- T as default
130
+ $ as default
127
131
  };
128
132
 
129
133
  //# sourceMappingURL=CompactInsightCard.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CompactInsightCard.es.js","names":[],"sources":["../../../src/insights-v2/components/CompactInsightCard.tsx"],"sourcesContent":["import type { KeyboardEvent, MouseEvent } from 'react'\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 { Icon } from '@mxenabled/mx-icons'\nimport { P, Text } from '@mxenabled/mxui'\n\nimport type { InsightsPayload, LogoRef, PrimaryCTA } from '../../core'\nimport { createVariantBlock } from '../blocks/createVariantBlock'\nimport BadgedTile from './BadgedTile'\nimport InsightOptionsMenu from './InsightOptionsMenu'\nimport LogoFromGuid from './LogoFromGuid'\nimport StatusBadge from './StatusBadge'\n\n/** Figma 1941:111897: the tile the logo fills is 44px (rows are 32, the notification row 33). */\nconst ICON_SIZE = 44\n\ninterface InsightVisualProps {\n /** The first slot row's logo, when the envelope carries a row. */\n logo?: LogoRef | null\n}\n\n/** The row's logo, or the neutral insight glyph when the slot has no row. */\nconst LogoOrFallback = ({ logo }: InsightVisualProps) =>\n logo ? (\n <LogoFromGuid logo={logo} size={ICON_SIZE} />\n ) : (\n <Box\n data-testid=\"compact-insight-card-fallback-icon\"\n sx={{\n alignItems: 'center',\n bgcolor: 'primary.lighter',\n display: 'flex',\n height: ICON_SIZE,\n justifyContent: 'center',\n width: ICON_SIZE,\n }}\n >\n <Icon color=\"primary\" fill={true} name=\"lightbulb\" size={24} />\n </Box>\n )\n\n/** Micro, and any variant not registered below: the logo alone. */\nconst PlainVisual = ({ logo }: InsightVisualProps) => (\n <BadgedTile center={<LogoOrFallback logo={logo} />} size={ICON_SIZE} sx={{ flexShrink: 0 }} />\n)\n\n/** ditto `embedded`: the logo badged with a status glyph (Figma 1941:111897). */\nconst EmbeddedVisual = ({ logo }: InsightVisualProps) => (\n <BadgedTile\n center={<LogoOrFallback logo={logo} />}\n size={ICON_SIZE}\n sx={{ flexShrink: 0 }}\n topRight={<StatusBadge tone=\"warning\" />}\n />\n)\n\n/**\n * The card's right-hand visual, one component per ditto layout variant.\n *\n * A variant names a rendering *shape*, not an insight — `with_header` already serves both Large\n * Transaction and Fee Detected — so an insight wanting the badged logo reuses `embedded`. Only a\n * genuinely different visual registers a new entry, and existing ones are never touched.\n */\nconst InsightVisual = createVariantBlock<InsightVisualProps>({\n variants: { embedded: EmbeddedVisual },\n fallback: PlainVisual,\n name: 'InsightVisual',\n})\n\nexport interface CompactInsightCardProps {\n /** A `micro` or `embedded` envelope. */\n payload: InsightsPayload\n /**\n * Makes the whole card the tap target. What a tap does is the host's decision (post to the\n * host app, open a drawer, …); the card never opens anything itself. Omit for a static card.\n */\n onTap?: () => void\n /** Receives the primary CTA when tapped. The card does not resolve the CTA's block itself. */\n onCtaClick?: (cta: PrimaryCTA) => void\n /**\n * Renders the CTA disabled — label shown, `aria-disabled`, not tappable — for a host that cannot\n * honour it (e.g. `contact_support_block` when the client's `enable_support_requests` is off).\n */\n isCtaDisabled?: boolean\n}\n\nconst stopPropagation = (event: MouseEvent) => event.stopPropagation()\n\n/**\n * The one compact renderer the micro and embedded envelopes share (`insights_v2.2.md` §8.3).\n *\n * Figma 1941:111897 (Embedded | Large Transaction): a title row with the overflow slot, the HTML\n * description with the primary CTA under it, and on the right the first slot row's logo in a\n * `<BadgedTile>`. Under ditto's `embedded` variant the tile takes a status badge; micro sends no\n * variant and draws the logo alone. The card lays out from the envelope alone and never reads\n * `widget_type`.\n *\n * The icon falls back to the neutral insight glyph **here**, not in `LogoFromGuid`, when the slot\n * has no row. The `pill` on the same envelope is the transaction row's, not the card's.\n */\nconst CompactInsightCard = ({\n isCtaDisabled = false,\n onCtaClick,\n onTap,\n payload,\n}: CompactInsightCardProps) => {\n const { description, instance_slot, primary_cta, title } = payload\n const rowLogo = instance_slot.data_series?.[0]?.logo\n\n const handleCtaClick = (event: MouseEvent<HTMLButtonElement>) => {\n event.stopPropagation()\n if (isCtaDisabled || !primary_cta) return\n onCtaClick?.(primary_cta)\n }\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n // Only the card itself: Enter on the CTA button is the button's own click.\n if (event.target !== event.currentTarget) return\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n onTap?.()\n }\n }\n\n const interactiveProps = onTap\n ? { onClick: onTap, onKeyDown: handleKeyDown, role: 'button', tabIndex: 0 }\n : {}\n\n return (\n <Card\n data-testid=\"compact-insight-card\"\n {...interactiveProps}\n sx={{ minWidth: 288, pb: 12, pl: 8, pr: 16, pt: 8, ...(onTap && { cursor: 'pointer' }) }}\n >\n <Stack\n sx={{\n alignItems: 'center',\n flexDirection: 'row',\n gap: 8,\n justifyContent: 'space-between',\n pl: 8,\n pt: 4,\n }}\n >\n <Text bold={true} variant=\"body1\">\n {title ?? ''}\n </Text>\n {/* The menu renders only when the host wired `onMenuAction` (BeatActionsProvider). */}\n <Box onClick={stopPropagation} sx={{ display: 'flex' }}>\n <InsightOptionsMenu />\n </Box>\n </Stack>\n\n <Stack sx={{ flexDirection: 'row', gap: 16, pl: 8, pt: 4 }}>\n <Stack sx={{ flex: 1, gap: 8, minWidth: 0 }}>\n {/* `html_text` is rendered server-side by mrs_content from the ditto copy template (bold\n amount / merchant), not user-authored input; painted the same way `BaseLayout` paints\n the full card's description. */}\n <P\n dangerouslySetInnerHTML={{ __html: description.html_text }}\n data-testid=\"compact-insight-card-description\"\n variant=\"subtitle2\"\n />\n {primary_cta?.label && (\n <Button\n aria-disabled={isCtaDisabled}\n onClick={handleCtaClick}\n size=\"small\"\n sx={{\n alignSelf: 'flex-start',\n // Figma 1941:111897 lines the CTA label up with the description's left edge. The\n // column already pads 8, so the button's own 8 is pulled back out — padding kept so\n // the tap target does not shrink.\n ml: -8,\n px: 8,\n ...(isCtaDisabled && { color: 'text.disabled', cursor: 'default' }),\n }}\n variant=\"text\"\n >\n {primary_cta.label}\n </Button>\n )}\n </Stack>\n\n <InsightVisual logo={rowLogo} variant={instance_slot.variant} />\n </Stack>\n </Card>\n )\n}\n\nexport default CompactInsightCard\n"],"mappings":"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"}
1
+ {"version":3,"file":"CompactInsightCard.es.js","names":[],"sources":["../../../src/insights-v2/components/CompactInsightCard.tsx"],"sourcesContent":["import type { KeyboardEvent, MouseEvent } from 'react'\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 { Icon } from '@mxenabled/mx-icons'\nimport { P, Text } from '@mxenabled/mxui'\n\nimport { slot } from '../../core'\nimport type { InsightsPayload, LogoRef, PrimaryCTA } from '../../core'\nimport { createVariantBlock } from '../blocks/createVariantBlock'\nimport BadgedTile from './BadgedTile'\nimport InsightOptionsMenu from './InsightOptionsMenu'\nimport LogoFromGuid from './LogoFromGuid'\nimport StatusBadge from './StatusBadge'\n\n/** Figma 1941:111897: the tile the logo fills is 44px (rows are 32, the notification row 33). */\nconst ICON_SIZE = 44\n\ninterface InsightVisualProps {\n /** The slot's `logo`, when ditto's variant declares and fills one. */\n logo?: LogoRef | null\n}\n\n/** The slot's logo, or the neutral insight glyph when the slot carries none. */\nconst LogoOrFallback = ({ logo }: InsightVisualProps) =>\n logo ? (\n <LogoFromGuid logo={logo} size={ICON_SIZE} />\n ) : (\n <Box\n data-testid=\"compact-insight-card-fallback-icon\"\n sx={{\n alignItems: 'center',\n bgcolor: 'primary.lighter',\n display: 'flex',\n height: ICON_SIZE,\n justifyContent: 'center',\n width: ICON_SIZE,\n }}\n >\n <Icon color=\"primary\" fill={true} name=\"lightbulb\" size={24} />\n </Box>\n )\n\n/** Micro, and any variant not registered below: the logo alone. */\nconst PlainVisual = ({ logo }: InsightVisualProps) => (\n <BadgedTile center={<LogoOrFallback logo={logo} />} size={ICON_SIZE} sx={{ flexShrink: 0 }} />\n)\n\n/** ditto `with_warning_badge`: the logo badged with a status glyph (Figma 1941:111897). */\nconst WarningBadgeVisual = ({ logo }: InsightVisualProps) => (\n <BadgedTile\n center={<LogoOrFallback logo={logo} />}\n size={ICON_SIZE}\n sx={{ flexShrink: 0 }}\n topRight={<StatusBadge tone=\"warning\" />}\n />\n)\n\n/**\n * The card's right-hand visual, one component per ditto layout variant.\n *\n * A variant names a rendering *shape*, not an insight or a surface — `with_header` already serves\n * both Large Transaction and Fee Detected — so an insight wanting the badged logo reuses\n * `with_warning_badge`. Only a genuinely different visual registers a new entry, and existing ones\n * are never touched.\n *\n * `minimal` draws the plain logo and is registered explicitly even though it matches the fallback:\n * micro and notification resolve it on every render, and an unregistered variant warns. The\n * fallback is for variants we genuinely do not know.\n */\nconst InsightVisual = createVariantBlock<InsightVisualProps>({\n variants: { minimal: PlainVisual, with_warning_badge: WarningBadgeVisual },\n fallback: PlainVisual,\n name: 'InsightVisual',\n})\n\nexport interface CompactInsightCardProps {\n /** A `micro` or `embedded` envelope. */\n payload: InsightsPayload\n /**\n * Makes the whole card the tap target. What a tap does is the host's decision (post to the\n * host app, open a drawer, …); the card never opens anything itself. Omit for a static card.\n */\n onTap?: () => void\n /** Receives the primary CTA when tapped. The card does not resolve the CTA's block itself. */\n onCtaClick?: (cta: PrimaryCTA) => void\n /**\n * Renders the CTA disabled — label shown, `aria-disabled`, not tappable — for a host that cannot\n * honour it (e.g. `contact_support_block` when the client's `enable_support_requests` is off).\n */\n isCtaDisabled?: boolean\n}\n\nconst stopPropagation = (event: MouseEvent) => event.stopPropagation()\n\n/**\n * The one compact renderer the micro and embedded envelopes share (`insights_v2.2.md` §8.3).\n *\n * Figma 1941:111897 (Embedded | Large Transaction): a title row with the overflow slot, the HTML\n * description with the primary CTA under it, and on the right the slot's `logo` in a\n * `<BadgedTile>`. Under ditto's `with_warning_badge` variant the tile takes a status badge; under\n * `minimal` it draws the logo alone. The card lays out from the envelope alone and never reads\n * `widget_type`.\n *\n * The icon falls back to the neutral insight glyph **here**, not in `LogoFromGuid`, when the slot\n * carries no logo. The `pill` on the same envelope is the transaction row's, not the card's.\n */\nconst CompactInsightCard = ({\n isCtaDisabled = false,\n onCtaClick,\n onTap,\n payload,\n}: CompactInsightCardProps) => {\n const { description, instance_slot, primary_cta, title } = payload\n // Reduced variants (`minimal`, `with_warning_badge`) declare a bare `logo` slot.\n const rowLogo = slot<LogoRef>(instance_slot.data, 'logo')\n\n const handleCtaClick = (event: MouseEvent<HTMLButtonElement>) => {\n event.stopPropagation()\n if (isCtaDisabled || !primary_cta) return\n onCtaClick?.(primary_cta)\n }\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n // Only the card itself: Enter on the CTA button is the button's own click.\n if (event.target !== event.currentTarget) return\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n onTap?.()\n }\n }\n\n const interactiveProps = onTap\n ? { onClick: onTap, onKeyDown: handleKeyDown, role: 'button', tabIndex: 0 }\n : {}\n\n return (\n <Card\n data-testid=\"compact-insight-card\"\n {...interactiveProps}\n sx={{\n minWidth: 288,\n pb: 12,\n pl: 8,\n pr: 16,\n pt: 8,\n ...(onTap && { cursor: 'pointer' }),\n }}\n >\n <Stack\n sx={{\n alignItems: 'center',\n flexDirection: 'row',\n gap: 8,\n justifyContent: 'space-between',\n pl: 8,\n pt: 4,\n }}\n >\n <Text bold={true} variant=\"body1\">\n {title ?? ''}\n </Text>\n {/* The menu renders only when the host wired `onMenuAction` (BeatActionsProvider). */}\n <Box onClick={stopPropagation} sx={{ display: 'flex' }}>\n <InsightOptionsMenu />\n </Box>\n </Stack>\n\n <Stack sx={{ flexDirection: 'row', gap: 16, pl: 8, pt: 4 }}>\n <Stack sx={{ flex: 1, gap: 8, minWidth: 0 }}>\n {/* `html_text` is rendered server-side by mrs_content from the ditto copy template (bold\n amount / merchant), not user-authored input; painted the same way `BaseLayout` paints\n the full card's description. */}\n <P\n dangerouslySetInnerHTML={{ __html: description.html_text }}\n data-testid=\"compact-insight-card-description\"\n variant=\"subtitle2\"\n />\n {primary_cta?.label && (\n <Button\n aria-disabled={isCtaDisabled}\n onClick={handleCtaClick}\n size=\"small\"\n sx={{\n alignSelf: 'flex-start',\n // Figma 1941:111897 lines the CTA label up with the description's left edge. The\n // column already pads 8, so the button's own 8 is pulled back out — padding kept so\n // the tap target does not shrink.\n ml: -8,\n px: 8,\n ...(isCtaDisabled && {\n color: 'text.disabled',\n cursor: 'default',\n }),\n }}\n variant=\"text\"\n >\n {primary_cta.label}\n </Button>\n )}\n </Stack>\n\n <InsightVisual logo={rowLogo} variant={instance_slot.variant} />\n </Stack>\n </Card>\n )\n}\n\nexport default CompactInsightCard\n"],"mappings":"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"}
@@ -21,10 +21,13 @@ export type InsightRender = 'legacy' | 'v2' | 'error';
21
21
  * no block, no logo and no footer, and the failure would never surface. An absent flag (older firefly,
22
22
  * cortex) renders the legacy path unchanged.
23
23
  *
24
- * An envelope counts as present only when it carries both an `instance_slot` and a `description`: a
25
- * bare `{}` is a half-built envelope, every V2 renderer reads `instance_slot.block` first, and all
26
- * three — `BaseLayout`, `CompactInsightCard` and the micro `InsightCard` — paint
27
- * `description.html_text` unguarded, so a half-built envelope has to resolve to `error` rather than
28
- * throw inside the renderer.
24
+ * The gate checks only that `instance_slot` is an object and `description` is present. It does not
25
+ * look inside the slot: an empty `{}` is a valid envelope and resolves to `v2`, because a beat
26
+ * whose template has no ditto config names no block, and the card renders its copy and CTAs alone.
27
+ * So `block` is optional on `InstanceSlot` and a renderer must not dereference it unguarded.
28
+ *
29
+ * A payload missing `description` resolves to `error` instead: all three renderers — `BaseLayout`,
30
+ * `CompactInsightCard` and the micro `InsightCard` — paint `description.html_text` unguarded, so
31
+ * that one would throw.
29
32
  */
30
33
  export declare const resolveInsightRender: (beat?: Beat | null) => InsightRender;
@@ -1 +1 @@
1
- {"version":3,"file":"resolveInsightRender.es.js","names":[],"sources":["../../src/insights-v2/resolveInsightRender.ts"],"sourcesContent":["import type { Beat } from '../core'\n\n/**\n * Which renderer draws a beat:\n * - `legacy` — the per-template legacy component (feed, mini, micro) or the legacy caption / embedded\n * `switch` (transaction row, details drawer).\n * - `v2` — `BaseLayout` (full, mini) or `CompactInsightCard` (micro, embedded) from `insights_payload`.\n * - `error` — `InsightErrorCard`: the beat is flagged but its envelope is missing.\n */\nexport type InsightRender = 'legacy' | 'v2' | 'error'\n\n/**\n * The single gate every surface calls. Two facts decide: `beat.is_insights_v2` (written by firefly\n * when the insight's Insights 2.0 flag is on) and whether the envelope is present.\n *\n * | `is_insights_v2` | envelope | result |\n * | false / absent | any | `legacy` |\n * | true | non-empty | `v2` |\n * | true | empty | `error` |\n *\n * `error` is never downgraded to `legacy`: a flagged insight's legacy copy fields are filled from the\n * same V2 copy block, so a failed envelope would otherwise render a plausible legacy-looking card with\n * no block, no logo and no footer, and the failure would never surface. An absent flag (older firefly,\n * cortex) renders the legacy path unchanged.\n *\n * An envelope counts as present only when it carries both an `instance_slot` and a `description`: a\n * bare `{}` is a half-built envelope, every V2 renderer reads `instance_slot.block` first, and all\n * three — `BaseLayout`, `CompactInsightCard` and the micro `InsightCard` — paint\n * `description.html_text` unguarded, so a half-built envelope has to resolve to `error` rather than\n * throw inside the renderer.\n */\nexport const resolveInsightRender = (beat?: Beat | null): InsightRender => {\n if (!beat?.is_insights_v2) return 'legacy'\n\n const payload = beat.insights_payload\n\n return payload?.instance_slot && payload.description ? 'v2' : 'error'\n}\n"],"mappings":"AA+BA,IAAa,IAAA,CAAwB,MAAsC;AACzE,MAAI,CAAC,GAAM,eAAgB,QAAO;AAElC,QAAM,IAAU,EAAK;AAErB,SAAO,GAAS,iBAAiB,EAAQ,cAAc,OAAO;AAChE"}
1
+ {"version":3,"file":"resolveInsightRender.es.js","names":[],"sources":["../../src/insights-v2/resolveInsightRender.ts"],"sourcesContent":["import type { Beat } from '../core'\n\n/**\n * Which renderer draws a beat:\n * - `legacy` — the per-template legacy component (feed, mini, micro) or the legacy caption / embedded\n * `switch` (transaction row, details drawer).\n * - `v2` — `BaseLayout` (full, mini) or `CompactInsightCard` (micro, embedded) from `insights_payload`.\n * - `error` — `InsightErrorCard`: the beat is flagged but its envelope is missing.\n */\nexport type InsightRender = 'legacy' | 'v2' | 'error'\n\n/**\n * The single gate every surface calls. Two facts decide: `beat.is_insights_v2` (written by firefly\n * when the insight's Insights 2.0 flag is on) and whether the envelope is present.\n *\n * | `is_insights_v2` | envelope | result |\n * | false / absent | any | `legacy` |\n * | true | non-empty | `v2` |\n * | true | empty | `error` |\n *\n * `error` is never downgraded to `legacy`: a flagged insight's legacy copy fields are filled from the\n * same V2 copy block, so a failed envelope would otherwise render a plausible legacy-looking card with\n * no block, no logo and no footer, and the failure would never surface. An absent flag (older firefly,\n * cortex) renders the legacy path unchanged.\n *\n * The gate checks only that `instance_slot` is an object and `description` is present. It does not\n * look inside the slot: an empty `{}` is a valid envelope and resolves to `v2`, because a beat\n * whose template has no ditto config names no block, and the card renders its copy and CTAs alone.\n * So `block` is optional on `InstanceSlot` and a renderer must not dereference it unguarded.\n *\n * A payload missing `description` resolves to `error` instead: all three renderers — `BaseLayout`,\n * `CompactInsightCard` and the micro `InsightCard` — paint `description.html_text` unguarded, so\n * that one would throw.\n */\nexport const resolveInsightRender = (beat?: Beat | null): InsightRender => {\n if (!beat?.is_insights_v2) return 'legacy'\n\n const payload = beat.insights_payload\n\n return payload?.instance_slot && payload.description ? 'v2' : 'error'\n}\n"],"mappings":"AAkCA,IAAa,IAAA,CAAwB,MAAsC;AACzE,MAAI,CAAC,GAAM,eAAgB,QAAO;AAElC,QAAM,IAAU,EAAK;AAErB,SAAO,GAAS,iBAAiB,EAAQ,cAAc,OAAO;AAChE"}
@@ -1,26 +1,27 @@
1
- import { resolveInsightRender as k } from "../../insights-v2/resolveInsightRender.es.js";
2
- import x from "../../insights-v2/components/LogoFromGuid.es.js";
3
- import B from "../../insights-v2/components/InsightErrorCard.es.js";
4
- import { ON_CLICK_EVENT as M, ON_VIEW_EVENT as R, ON_VIEW_FIRST_TIME_EVENT as W } from "../constants/Analytics.es.js";
5
- import S from "../beaticons/BeatMaterialIcon.es.js";
6
- import { BeatIcon as F } from "../beaticons/BeatIcon.es.js";
7
- import { useCopyStore as O, useEvent as P, useInsightsMicroWidgetStore as A } from "../context/hooks.es.js";
1
+ import { slot as k } from "../../core/types/Insights.es.js";
2
+ import { resolveInsightRender as x } from "../../insights-v2/resolveInsightRender.es.js";
3
+ import B from "../../insights-v2/components/LogoFromGuid.es.js";
4
+ import M from "../../insights-v2/components/InsightErrorCard.es.js";
5
+ import { ON_CLICK_EVENT as R, ON_VIEW_EVENT as W, ON_VIEW_FIRST_TIME_EVENT as S } from "../constants/Analytics.es.js";
6
+ import F from "../beaticons/BeatMaterialIcon.es.js";
7
+ import { BeatIcon as O } from "../beaticons/BeatIcon.es.js";
8
+ import { useCopyStore as P, useEvent as A, useInsightsMicroWidgetStore as j } from "../context/hooks.es.js";
8
9
  import E from "../MicroCardTemplate.es.js";
9
10
  import { useEffect as I } from "react";
10
11
  import { jsx as r } from "react/jsx-runtime";
11
- import { alpha as j, useTheme as v } from "@mui/material/styles";
12
- import w from "@mui/material/Box";
13
- import { useInView as z } from "react-intersection-observer";
14
- var G = 32, ei = ({ ariaLabel: l, beat: i, elevation: g, index: s, isActiveCard: c, onCardClick: u, posthog: o, widthOverrides: m, variant: f, showIcon: h, heightOverrides: a }) => {
15
- const { ref: _, inView: n } = z({ threshold: 1 }), C = v(), { cardsCopy: T } = O(), { onEvent: d } = P(), { updateBeat: N, updateOffer: V } = A();
12
+ import { alpha as v, useTheme as w } from "@mui/material/styles";
13
+ import z from "@mui/material/Box";
14
+ import { useInView as G } from "react-intersection-observer";
15
+ var K = 32, ti = ({ ariaLabel: l, beat: i, elevation: g, index: c, isActiveCard: s, onCardClick: u, posthog: o, widthOverrides: m, variant: f, showIcon: h, heightOverrides: a }) => {
16
+ const { ref: _, inView: n } = G({ threshold: 1 }), C = w(), { cardsCopy: T } = P(), { onEvent: d } = A(), { updateBeat: N, updateOffer: V } = j();
16
17
  I(() => {
17
- n && (i.has_been_displayed ? d(R(i.template)) : (i.guid.startsWith("OFR") ? V({
18
+ n && (i.has_been_displayed ? d(W(i.template)) : (i.guid.startsWith("OFR") ? V({
18
19
  ...i,
19
20
  has_been_displayed: !0
20
21
  }) : N({
21
22
  ...i,
22
23
  has_been_displayed: !0
23
- }), d(W(i.template))));
24
+ }), d(S(i.template))));
24
25
  }, [n]), I(() => {
25
26
  if (n && i) if (i.template === "MarketingOffer") {
26
27
  const e = i;
@@ -34,15 +35,15 @@ var G = 32, ei = ({ ariaLabel: l, beat: i, elevation: g, index: s, isActiveCard:
34
35
  } else o?.capture("viewed_insight", {
35
36
  beat_guid: i.guid,
36
37
  template: i.template,
37
- position: s
38
+ position: c
38
39
  });
39
40
  }, [
40
41
  i,
41
- s,
42
+ c,
42
43
  n
43
44
  ]);
44
45
  const p = () => {
45
- if (u && u(i), d(M(i.template)), i.template === "MarketingOffer") {
46
+ if (u && u(i), d(R(i.template)), i.template === "MarketingOffer") {
46
47
  const e = i;
47
48
  o?.capture("clicked_messaging_insight", {
48
49
  template: i.template,
@@ -54,11 +55,11 @@ var G = 32, ei = ({ ariaLabel: l, beat: i, elevation: g, index: s, isActiveCard:
54
55
  } else o?.capture("clicked_insight", {
55
56
  beat_guid: i.guid,
56
57
  template: i.template,
57
- position: s
58
+ position: c
58
59
  });
59
- }, y = k(i), t = y === "v2" ? i.insights_payload : void 0;
60
- if (y === "error") return /* @__PURE__ */ r(w, {
61
- "aria-hidden": !c,
60
+ }, y = x(i), t = y === "v2" ? i.insights_payload : void 0;
61
+ if (y === "error") return /* @__PURE__ */ r(z, {
62
+ "aria-hidden": !s,
62
63
  "aria-label": l,
63
64
  "aria-roledescription": "slide",
64
65
  ref: _,
@@ -68,24 +69,24 @@ var G = 32, ei = ({ ariaLabel: l, beat: i, elevation: g, index: s, isActiveCard:
68
69
  minWidth: m ? `${m}px` : "100%",
69
70
  my: 1
70
71
  },
71
- children: /* @__PURE__ */ r(B, { beat: i })
72
+ children: /* @__PURE__ */ r(M, { beat: i })
72
73
  });
73
74
  if (t) {
74
- const e = t.instance_slot.data_series?.[0]?.logo;
75
+ const e = k(t.instance_slot.data, "logo");
75
76
  return /* @__PURE__ */ r(E, {
76
77
  "aria-roledescription": "slide",
77
78
  ariaLabel: l,
78
79
  description: t.description.html_text,
79
80
  elevation: g,
80
81
  heightOverrides: a,
81
- icon: h && (e ? /* @__PURE__ */ r(x, {
82
+ icon: h && (e ? /* @__PURE__ */ r(B, {
82
83
  logo: e,
83
- size: G
84
- }) : /* @__PURE__ */ r(S, {
85
- bgColor: j(C.palette.primary.main, 0.15),
84
+ size: K
85
+ }) : /* @__PURE__ */ r(F, {
86
+ bgColor: v(C.palette.primary.main, 0.15),
86
87
  name: "lightbulb"
87
88
  })),
88
- isActiveCard: c,
89
+ isActiveCard: s,
89
90
  onCardClick: p,
90
91
  onPrimaryAction: p,
91
92
  primaryActionText: t.primary_cta?.label,
@@ -101,8 +102,8 @@ var G = 32, ei = ({ ariaLabel: l, beat: i, elevation: g, index: s, isActiveCard:
101
102
  description: i?.html_micro_description && i?.html_micro_description.length > 0 ? i.html_micro_description : i.html_description || "",
102
103
  elevation: g,
103
104
  heightOverrides: a,
104
- icon: h && /* @__PURE__ */ r(F, { beat: i }),
105
- isActiveCard: c,
105
+ icon: h && /* @__PURE__ */ r(O, { beat: i }),
106
+ isActiveCard: s,
106
107
  onCardClick: p,
107
108
  onPrimaryAction: p,
108
109
  primaryActionText: i.micro_call_to_action || T?.micro_card_cta,
@@ -113,7 +114,7 @@ var G = 32, ei = ({ ariaLabel: l, beat: i, elevation: g, index: s, isActiveCard:
113
114
  });
114
115
  };
115
116
  export {
116
- ei as InsightCard
117
+ ti as InsightCard
117
118
  };
118
119
 
119
120
  //# sourceMappingURL=InsightCard.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"InsightCard.es.js","names":[],"sources":["../../../src/microinsights/cards/InsightCard.tsx"],"sourcesContent":["import React, { useEffect } from 'react'\nimport { useInView } from 'react-intersection-observer'\n\nimport Box from '@mui/material/Box'\nimport { alpha, useTheme } from '@mui/material/styles'\n\nimport { BeatIcon } from '../beaticons'\nimport BeatMaterialIcon from '../beaticons/BeatMaterialIcon'\n\nimport { useCopyStore, useEvent, useInsightsMicroWidgetStore } from '../context/hooks'\n\nimport { ON_CLICK_EVENT, ON_VIEW_EVENT, ON_VIEW_FIRST_TIME_EVENT } from '../constants/Analytics'\nimport { VIEW_THRESHOLD } from '../constants/App'\n\nimport type { BeatLikeOffer, MicroInsightCardProps } from '../interfaces'\nimport type { Beat } from '../../core/types/Beat'\nimport MicroCardTemplate from '../MicroCardTemplate'\n// Leaf imports on purpose: the `insights-v2` barrel pulls in `mappings/blocks` and its charts.\nimport InsightErrorCard from '../../insights-v2/components/InsightErrorCard'\nimport LogoFromGuid from '../../insights-v2/components/LogoFromGuid'\nimport { resolveInsightRender } from '../../insights-v2/resolveInsightRender'\n\n/** The legacy micro card's icon tile size (BeatMaterialIcon). */\nconst ICON_SIZE = 32\n\nexport interface InsightCardProps extends MicroInsightCardProps {\n beat: Beat | BeatLikeOffer\n index?: number\n}\n\nexport const InsightCard: React.FC<InsightCardProps> = ({\n ariaLabel,\n beat,\n elevation,\n index,\n isActiveCard,\n onCardClick,\n posthog,\n widthOverrides,\n variant,\n showIcon,\n heightOverrides,\n}) => {\n const { ref, inView } = useInView({\n threshold: VIEW_THRESHOLD,\n })\n\n const theme = useTheme()\n\n // *************** Context functions *********************\n const { cardsCopy } = useCopyStore()\n const { onEvent } = useEvent()\n const { updateBeat, updateOffer } = useInsightsMicroWidgetStore()\n\n // ************** Use Effects Hooks **********************\n useEffect(() => {\n if (inView) {\n if (!beat.has_been_displayed) {\n if (beat.guid.startsWith('OFR')) {\n updateOffer({\n ...beat,\n has_been_displayed: true,\n })\n } else {\n updateBeat({\n ...beat,\n has_been_displayed: true,\n })\n }\n onEvent(ON_VIEW_FIRST_TIME_EVENT(beat.template))\n } else {\n onEvent(ON_VIEW_EVENT(beat.template))\n }\n }\n }, [inView])\n\n useEffect(() => {\n if (inView && beat) {\n if (beat.template === 'MarketingOffer') {\n const offerBeat = beat as BeatLikeOffer\n posthog?.capture('viewed_messaging_insight', {\n template: beat.template,\n campaign_guid: offerBeat.campaign_guid,\n campaign_name: offerBeat.pulse_campaign_name,\n offer_guid: offerBeat.guid,\n user_guid: offerBeat.user_guid,\n })\n } else {\n posthog?.capture('viewed_insight', {\n beat_guid: beat.guid,\n template: beat.template,\n position: index,\n })\n }\n }\n }, [beat, index, inView])\n\n // *************** Click handlers ************************\n const handleClick = () => {\n /* eslint-disable no-unused-expressions */\n onCardClick && onCardClick(beat)\n onEvent(ON_CLICK_EVENT(beat.template))\n\n if (beat.template === 'MarketingOffer') {\n const offerBeat = beat as BeatLikeOffer\n posthog?.capture('clicked_messaging_insight', {\n template: beat.template,\n campaign_guid: offerBeat.campaign_guid,\n campaign_name: offerBeat.pulse_campaign_name,\n offer_guid: offerBeat.guid,\n user_guid: offerBeat.user_guid,\n })\n } else {\n posthog?.capture('clicked_insight', {\n beat_guid: beat.guid,\n template: beat.template,\n position: index,\n })\n }\n }\n\n const insightRender = resolveInsightRender(beat as Beat)\n const v2Payload = insightRender === 'v2' ? beat.insights_payload : undefined\n\n if (insightRender === 'error') {\n // Keeps the carousel's slot sizing; the error card does not know about it.\n return (\n <Box\n aria-hidden={!isActiveCard}\n aria-label={ariaLabel}\n aria-roledescription=\"slide\"\n ref={ref}\n role=\"group\"\n sx={{\n height: heightOverrides ? '100%' : 120,\n minWidth: widthOverrides ? `${widthOverrides}px` : '100%',\n my: 1,\n }}\n >\n <InsightErrorCard beat={beat} />\n </Box>\n )\n }\n\n if (v2Payload) {\n // Figma (Micro Widget | Large Transaction) is the legacy micro card's layout fed from the envelope:\n // the first slot row's logo on the left (merchant, or the category without one), title, description,\n // and the primary CTA as a link. The logo falls back to the insight glyph when the slot has no row.\n const rowLogo = v2Payload.instance_slot.data_series?.[0]?.logo\n\n return (\n <MicroCardTemplate\n aria-roledescription=\"slide\"\n ariaLabel={ariaLabel}\n description={v2Payload.description.html_text}\n elevation={elevation}\n heightOverrides={heightOverrides}\n icon={\n showIcon &&\n (rowLogo ? (\n <LogoFromGuid logo={rowLogo} size={ICON_SIZE} />\n ) : (\n <BeatMaterialIcon bgColor={alpha(theme.palette.primary.main, 0.15)} name=\"lightbulb\" />\n ))\n }\n isActiveCard={isActiveCard}\n onCardClick={handleClick}\n onPrimaryAction={handleClick}\n primaryActionText={v2Payload.primary_cta?.label}\n ref={ref}\n title={v2Payload.title ?? ''}\n variant={variant}\n widthOverrides={widthOverrides}\n />\n )\n }\n\n return (\n <MicroCardTemplate\n aria-roledescription=\"slide\"\n ariaLabel={ariaLabel}\n description={\n beat?.html_micro_description && beat?.html_micro_description.length > 0\n ? beat.html_micro_description\n : beat.html_description || ''\n }\n elevation={elevation}\n heightOverrides={heightOverrides}\n icon={showIcon && <BeatIcon beat={beat} />}\n isActiveCard={isActiveCard}\n onCardClick={handleClick}\n onPrimaryAction={handleClick}\n primaryActionText={beat.micro_call_to_action || cardsCopy?.micro_card_cta}\n ref={ref}\n title={beat.micro_title && beat.micro_title.length > 0 ? beat.micro_title : beat.title}\n variant={variant}\n widthOverrides={widthOverrides}\n />\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"InsightCard.es.js","names":[],"sources":["../../../src/microinsights/cards/InsightCard.tsx"],"sourcesContent":["import React, { useEffect } from 'react'\nimport { useInView } from 'react-intersection-observer'\n\nimport Box from '@mui/material/Box'\nimport { alpha, useTheme } from '@mui/material/styles'\n\nimport { BeatIcon } from '../beaticons'\nimport BeatMaterialIcon from '../beaticons/BeatMaterialIcon'\n\nimport { useCopyStore, useEvent, useInsightsMicroWidgetStore } from '../context/hooks'\n\nimport { ON_CLICK_EVENT, ON_VIEW_EVENT, ON_VIEW_FIRST_TIME_EVENT } from '../constants/Analytics'\nimport { VIEW_THRESHOLD } from '../constants/App'\n\nimport type { BeatLikeOffer, MicroInsightCardProps } from '../interfaces'\nimport type { Beat } from '../../core/types/Beat'\n// Leaf imports, not the `core` barrel: that pulls GlobalStore and every feature store into the\n// micro bundle, and through `core/stores` it reintroduces a circular path this module avoids.\nimport { slot } from '../../core/types/Insights'\nimport type { LogoRef } from '../../core/types/Insights'\nimport MicroCardTemplate from '../MicroCardTemplate'\n// Leaf imports on purpose: the `insights-v2` barrel pulls in `mappings/blocks` and its charts.\nimport InsightErrorCard from '../../insights-v2/components/InsightErrorCard'\nimport LogoFromGuid from '../../insights-v2/components/LogoFromGuid'\nimport { resolveInsightRender } from '../../insights-v2/resolveInsightRender'\n\n/** The legacy micro card's icon tile size (BeatMaterialIcon). */\nconst ICON_SIZE = 32\n\nexport interface InsightCardProps extends MicroInsightCardProps {\n beat: Beat | BeatLikeOffer\n index?: number\n}\n\nexport const InsightCard: React.FC<InsightCardProps> = ({\n ariaLabel,\n beat,\n elevation,\n index,\n isActiveCard,\n onCardClick,\n posthog,\n widthOverrides,\n variant,\n showIcon,\n heightOverrides,\n}) => {\n const { ref, inView } = useInView({\n threshold: VIEW_THRESHOLD,\n })\n\n const theme = useTheme()\n\n // *************** Context functions *********************\n const { cardsCopy } = useCopyStore()\n const { onEvent } = useEvent()\n const { updateBeat, updateOffer } = useInsightsMicroWidgetStore()\n\n // ************** Use Effects Hooks **********************\n useEffect(() => {\n if (inView) {\n if (!beat.has_been_displayed) {\n if (beat.guid.startsWith('OFR')) {\n updateOffer({\n ...beat,\n has_been_displayed: true,\n })\n } else {\n updateBeat({\n ...beat,\n has_been_displayed: true,\n })\n }\n onEvent(ON_VIEW_FIRST_TIME_EVENT(beat.template))\n } else {\n onEvent(ON_VIEW_EVENT(beat.template))\n }\n }\n }, [inView])\n\n useEffect(() => {\n if (inView && beat) {\n if (beat.template === 'MarketingOffer') {\n const offerBeat = beat as BeatLikeOffer\n posthog?.capture('viewed_messaging_insight', {\n template: beat.template,\n campaign_guid: offerBeat.campaign_guid,\n campaign_name: offerBeat.pulse_campaign_name,\n offer_guid: offerBeat.guid,\n user_guid: offerBeat.user_guid,\n })\n } else {\n posthog?.capture('viewed_insight', {\n beat_guid: beat.guid,\n template: beat.template,\n position: index,\n })\n }\n }\n }, [beat, index, inView])\n\n // *************** Click handlers ************************\n const handleClick = () => {\n /* eslint-disable no-unused-expressions */\n onCardClick && onCardClick(beat)\n onEvent(ON_CLICK_EVENT(beat.template))\n\n if (beat.template === 'MarketingOffer') {\n const offerBeat = beat as BeatLikeOffer\n posthog?.capture('clicked_messaging_insight', {\n template: beat.template,\n campaign_guid: offerBeat.campaign_guid,\n campaign_name: offerBeat.pulse_campaign_name,\n offer_guid: offerBeat.guid,\n user_guid: offerBeat.user_guid,\n })\n } else {\n posthog?.capture('clicked_insight', {\n beat_guid: beat.guid,\n template: beat.template,\n position: index,\n })\n }\n }\n\n const insightRender = resolveInsightRender(beat as Beat)\n const v2Payload = insightRender === 'v2' ? beat.insights_payload : undefined\n\n if (insightRender === 'error') {\n // Keeps the carousel's slot sizing; the error card does not know about it.\n return (\n <Box\n aria-hidden={!isActiveCard}\n aria-label={ariaLabel}\n aria-roledescription=\"slide\"\n ref={ref}\n role=\"group\"\n sx={{\n height: heightOverrides ? '100%' : 120,\n minWidth: widthOverrides ? `${widthOverrides}px` : '100%',\n my: 1,\n }}\n >\n <InsightErrorCard beat={beat} />\n </Box>\n )\n }\n\n if (v2Payload) {\n // Figma (Micro Widget | Large Transaction) is the legacy micro card's layout fed from the envelope:\n // the slot's logo on the left (merchant, or the category without one), title, description, and the\n // primary CTA as a link. The logo falls back to the insight glyph when the slot carries none.\n const rowLogo = slot<LogoRef>(v2Payload.instance_slot.data, 'logo')\n\n return (\n <MicroCardTemplate\n aria-roledescription=\"slide\"\n ariaLabel={ariaLabel}\n description={v2Payload.description.html_text}\n elevation={elevation}\n heightOverrides={heightOverrides}\n icon={\n showIcon &&\n (rowLogo ? (\n <LogoFromGuid logo={rowLogo} size={ICON_SIZE} />\n ) : (\n <BeatMaterialIcon bgColor={alpha(theme.palette.primary.main, 0.15)} name=\"lightbulb\" />\n ))\n }\n isActiveCard={isActiveCard}\n onCardClick={handleClick}\n onPrimaryAction={handleClick}\n primaryActionText={v2Payload.primary_cta?.label}\n ref={ref}\n title={v2Payload.title ?? ''}\n variant={variant}\n widthOverrides={widthOverrides}\n />\n )\n }\n\n return (\n <MicroCardTemplate\n aria-roledescription=\"slide\"\n ariaLabel={ariaLabel}\n description={\n beat?.html_micro_description && beat?.html_micro_description.length > 0\n ? beat.html_micro_description\n : beat.html_description || ''\n }\n elevation={elevation}\n heightOverrides={heightOverrides}\n icon={showIcon && <BeatIcon beat={beat} />}\n isActiveCard={isActiveCard}\n onCardClick={handleClick}\n onPrimaryAction={handleClick}\n primaryActionText={beat.micro_call_to_action || cardsCopy?.micro_card_cta}\n ref={ref}\n title={beat.micro_title && beat.micro_title.length > 0 ? beat.micro_title : beat.title}\n variant={variant}\n widthOverrides={widthOverrides}\n />\n )\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mx-cartographer/experiences",
3
- "version": "9.5.4",
3
+ "version": "9.6.0",
4
4
  "description": "Library containing experience widgets",
5
5
  "author": "MX",
6
6
  "license": "MIT",