@mx-cartographer/experiences 9.5.3 → 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 (55) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/common/components/CurrencyDialog.d.ts +10 -2
  3. package/dist/common/components/CurrencyDialog.es.js +56 -50
  4. package/dist/common/components/CurrencyDialog.es.js.map +1 -1
  5. package/dist/core/index.es.js +111 -109
  6. package/dist/core/types/Insights.d.ts +33 -16
  7. package/dist/core/types/Insights.es.js +6 -0
  8. package/dist/core/types/Insights.es.js.map +1 -0
  9. package/dist/core/types/index.d.ts +2 -1
  10. package/dist/core/types/localization/InsightsFeedCopy.d.ts +21 -0
  11. package/dist/core/types/localization/index.d.ts +1 -1
  12. package/dist/insights-v2/actionBlocks/ActionBlockLayer.es.js +31 -25
  13. package/dist/insights-v2/actionBlocks/ActionBlockLayer.es.js.map +1 -1
  14. package/dist/insights-v2/actionBlocks/AmountInputModalBlock/AmountInputModalBlock.d.ts +13 -0
  15. package/dist/insights-v2/actionBlocks/AmountInputModalBlock/AmountInputModalBlock.es.js +128 -0
  16. package/dist/insights-v2/actionBlocks/AmountInputModalBlock/AmountInputModalBlock.es.js.map +1 -0
  17. package/dist/insights-v2/actionBlocks/AmountInputModalBlock/index.d.ts +1 -0
  18. package/dist/insights-v2/actionBlocks/AmountInputModalBlock/layout.d.ts +14 -0
  19. package/dist/insights-v2/actionBlocks/AmountInputModalBlock/layout.es.js +14 -0
  20. package/dist/insights-v2/actionBlocks/AmountInputModalBlock/layout.es.js.map +1 -0
  21. package/dist/insights-v2/blocks/ChartBlocks/DonutChartBlock/utils.d.ts +1 -1
  22. package/dist/insights-v2/blocks/ChartBlocks/DonutChartBlock/utils.es.js.map +1 -1
  23. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/layout.d.ts +1 -1
  24. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/layout.es.js.map +1 -1
  25. package/dist/insights-v2/blocks/ComponentBlocks/AccountBlock/IconComponent.d.ts +1 -1
  26. package/dist/insights-v2/blocks/ComponentBlocks/AccountBlock/IconComponent.es.js.map +1 -1
  27. package/dist/insights-v2/blocks/ComponentBlocks/TransactionBlock/TransactionBlock.d.ts +5 -2
  28. package/dist/insights-v2/blocks/ComponentBlocks/TransactionBlock/TransactionBlock.es.js +36 -35
  29. package/dist/insights-v2/blocks/ComponentBlocks/TransactionBlock/TransactionBlock.es.js.map +1 -1
  30. package/dist/insights-v2/blocks/ComponentBlocks/WithdrawalBlock/WithdrawalBlock.d.ts +2 -2
  31. package/dist/insights-v2/blocks/ComponentBlocks/WithdrawalBlock/WithdrawalBlock.es.js +6 -5
  32. package/dist/insights-v2/blocks/ComponentBlocks/WithdrawalBlock/WithdrawalBlock.es.js.map +1 -1
  33. package/dist/insights-v2/blocks/ImageBlocks/SVGImageBlock/layout.d.ts +1 -1
  34. package/dist/insights-v2/blocks/ImageBlocks/SVGImageBlock/layout.es.js.map +1 -1
  35. package/dist/insights-v2/components/BaseLayout.es.js +22 -22
  36. package/dist/insights-v2/components/CompactInsightCard.d.ts +4 -4
  37. package/dist/insights-v2/components/CompactInsightCard.es.js +50 -46
  38. package/dist/insights-v2/components/CompactInsightCard.es.js.map +1 -1
  39. package/dist/insights-v2/ctaActions/runCtaAction.es.js +10 -10
  40. package/dist/insights-v2/ctaActions/runCtaAction.es.js.map +1 -1
  41. package/dist/insights-v2/index.es.js +17 -17
  42. package/dist/insights-v2/mappings/actionBlocksKey.d.ts +1 -0
  43. package/dist/insights-v2/mappings/actionBlocksKey.es.js +2 -1
  44. package/dist/insights-v2/mappings/actionBlocksKey.es.js.map +1 -1
  45. package/dist/insights-v2/mappings/blocks.d.ts +2 -1
  46. package/dist/insights-v2/mappings/blocks.es.js +62 -62
  47. package/dist/insights-v2/mappings/blocks.es.js.map +1 -1
  48. package/dist/insights-v2/mappings/hasDrawerBlock.d.ts +1 -0
  49. package/dist/insights-v2/mappings/hasDrawerBlock.es.js +13 -0
  50. package/dist/insights-v2/mappings/hasDrawerBlock.es.js.map +1 -0
  51. package/dist/insights-v2/resolveInsightRender.d.ts +8 -5
  52. package/dist/insights-v2/resolveInsightRender.es.js.map +1 -1
  53. package/dist/microinsights/cards/InsightCard.es.js +32 -31
  54. package/dist/microinsights/cards/InsightCard.es.js.map +1 -1
  55. package/package.json +1 -1
@@ -145,6 +145,25 @@ export interface RemainingCashCopy {
145
145
  other_expenses: string;
146
146
  other_expenses_one: string;
147
147
  }
148
+ /** Copy for one variant of `amount_input_modal_block` (strings with `_1{account_name}` take the account). */
149
+ export interface AmountInputModalVariantCopy {
150
+ /** Body copy; `_1{account_name}` renders bold. */
151
+ description: string;
152
+ /** Body copy once a value is already saved; falls back to `description`. */
153
+ description_edit?: string;
154
+ input_label: string;
155
+ title: string;
156
+ /** Title once a value is already saved; falls back to `title`. */
157
+ title_edit?: string;
158
+ }
159
+ export interface AmountInputModalCopy {
160
+ low_balance_threshold: AmountInputModalVariantCopy;
161
+ safety_net: AmountInputModalVariantCopy;
162
+ /** Validation message for anything but a positive whole-dollar amount. */
163
+ whole_number_error: string;
164
+ /** Shown in the dialog when the save request fails; the value stays so Save can be retried. */
165
+ save_error: string;
166
+ }
148
167
  export interface InsightsFeedCopy {
149
168
  general: GeneralInsightsFeedCopy;
150
169
  settings_menu: SettingsMenuCopy;
@@ -158,5 +177,7 @@ export interface InsightsFeedCopy {
158
177
  feedback: FeedbackCopy;
159
178
  feedback_bar: FeedbackBarCopy;
160
179
  dismiss: DismissInsightCopy;
180
+ /** Optional until the localized-content service ships the namespace. */
181
+ amount_input_modal?: AmountInputModalCopy;
161
182
  }
162
183
  export {};
@@ -13,7 +13,7 @@ export type { DebtsCopy } from './DebtsCopy';
13
13
  export type { FinstrongCopy } from './FinstrongCopy';
14
14
  export type { GoalsCopy } from './GoalsCopy';
15
15
  export type { HelpCopy, HelpByCategoryList } from './HelpCopy';
16
- export type { InsightsFeedCopy, MakeTransferCopy, RemainingCashCopy, OverflowMenuCopy, DismissInsightCopy, DismissInsightOptionCopy, HiddenConfirmationCopy, HideFeedbackCopy, FeedbackCopy, FeedbackBarCopy, } from './InsightsFeedCopy';
16
+ export type { AmountInputModalCopy, AmountInputModalVariantCopy, InsightsFeedCopy, MakeTransferCopy, RemainingCashCopy, OverflowMenuCopy, DismissInsightCopy, DismissInsightOptionCopy, HiddenConfirmationCopy, HideFeedbackCopy, FeedbackCopy, FeedbackBarCopy, } from './InsightsFeedCopy';
17
17
  export type { InvestmentsCopy } from './InvestmentsCopy';
18
18
  export type { MicroInsightsCopy } from './MicroInsightsCopy';
19
19
  export type { NetWorthCopy } from './NetWorthCopy';
@@ -1,37 +1,43 @@
1
- import { useGlobalCopyStore as k, useGlobalUiStore as C, useInsightsV2Store as h } from "../../common/context/hooks.es.js";
2
- import B from "../../common/components/drawer/Drawer.es.js";
3
- import _ from "../../common/components/Loader.es.js";
4
- import { getDynamicCtaBasedOnTriggers as b } from "./util.es.js";
5
- import { actionBlocks as v, hasDrawerBlock as w } from "../mappings/blocks.es.js";
6
- import { observer as D } from "mobx-react-lite";
7
- import L from "@mui/material/Stack";
8
- import { Text as x } from "@mxenabled/mxui";
1
+ import { useGlobalCopyStore as C, useGlobalUiStore as h, useInsightsV2Store as B } from "../../common/context/hooks.es.js";
2
+ import _ from "../../common/components/drawer/Drawer.es.js";
3
+ import b from "../../common/components/Loader.es.js";
4
+ import { getDynamicCtaBasedOnTriggers as v } from "./util.es.js";
5
+ import { hasDrawerBlock as w } from "../mappings/hasDrawerBlock.es.js";
6
+ import { actionBlocks as D } from "../mappings/blocks.es.js";
7
+ import { observer as L } from "mobx-react-lite";
8
+ import x from "@mui/material/Stack";
9
+ import { Text as A } from "@mxenabled/mxui";
9
10
  import { jsx as e } from "react/jsx-runtime";
10
- var A = ({ actionBlock: s, ...o }) => {
11
- const { Component: n, usePrepare: t } = s;
12
- return t(o), /* @__PURE__ */ e(n, { ...o });
13
- }, $ = D(function({ beat: o }) {
14
- const n = k(), t = n.common, { isCopyLoaded: m } = C(), { actionDrawer: c, closeActionDrawer: p } = h();
11
+ var m = ({ actionBlock: s, ...o }) => {
12
+ const { Component: i, usePrepare: n } = s;
13
+ return n(o), /* @__PURE__ */ e(i, { ...o });
14
+ }, q = L(function({ beat: o }) {
15
+ const i = C(), n = i.common, { isCopyLoaded: p } = h(), { actionDrawer: c, closeActionDrawer: u } = B();
15
16
  if (!o.insights_payload) return null;
16
- const { primary_cta: d, secondary_cta: u, guid: f } = o.insights_payload, l = c.isDrawerOpen && c.guid === f;
17
- if (!m) return l ? /* @__PURE__ */ e(_, {}) : null;
18
- const r = b(c, d, u), a = w(r?.block), i = a ? v[r?.block] : void 0, y = i?.title?.(r?.variant, n, o), g = i ? y || r?.label || "" : a ? t.error_heading : r?.label ?? "";
19
- return /* @__PURE__ */ e(B, {
20
- ariaLabelClose: t.close_aria,
21
- isOpen: l,
22
- onClose: p,
17
+ const { primary_cta: d, secondary_cta: f, guid: k } = o.insights_payload, a = c.isDrawerOpen && c.guid === k;
18
+ if (!p) return a ? /* @__PURE__ */ e(b, {}) : null;
19
+ const r = v(c, d, f), l = w(r?.block), t = l ? D[r?.block] : void 0;
20
+ if (t?.presentation === "modal") return a ? /* @__PURE__ */ e(m, {
21
+ actionBlock: t,
22
+ beat: o
23
+ }, r?.block) : null;
24
+ const y = t?.title?.(r?.variant, i, o), g = t ? y || r?.label || "" : l ? n.error_heading : r?.label ?? "";
25
+ return /* @__PURE__ */ e(_, {
26
+ ariaLabelClose: n.close_aria,
27
+ isOpen: a,
28
+ onClose: u,
23
29
  title: g,
24
- children: i ? /* @__PURE__ */ e(A, {
25
- actionBlock: i,
30
+ children: t ? /* @__PURE__ */ e(m, {
31
+ actionBlock: t,
26
32
  beat: o
27
- }, r?.block) : a ? /* @__PURE__ */ e(L, {
33
+ }, r?.block) : l ? /* @__PURE__ */ e(x, {
28
34
  sx: { p: 24 },
29
- children: /* @__PURE__ */ e(x, { children: t.error_message })
35
+ children: /* @__PURE__ */ e(A, { children: n.error_message })
30
36
  }) : null
31
37
  });
32
38
  });
33
39
  export {
34
- $ as ActionBlockLayer
40
+ q as ActionBlockLayer
35
41
  };
36
42
 
37
43
  //# sourceMappingURL=ActionBlockLayer.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ActionBlockLayer.es.js","names":[],"sources":["../../../src/insights-v2/actionBlocks/ActionBlockLayer.tsx"],"sourcesContent":["import Stack from '@mui/material/Stack'\n\nimport { Text } from '@mxenabled/mxui'\nimport { observer } from 'mobx-react-lite'\n\nimport {\n Drawer,\n Loader,\n useGlobalCopyStore,\n useGlobalUiStore,\n useInsightsV2Store,\n} from '../../common'\nimport { type Beat } from '../../core'\nimport {\n actionBlocks,\n hasDrawerBlock,\n type ActionBlockEntry,\n type ActionBlockProps,\n} from '../mappings/blocks'\nimport { getDynamicCtaBasedOnTriggers } from './util'\n\ninterface ActionBlockLayerProps {\n beat: Beat\n}\n\n/**\n * Renders a registered action block. Callers MUST key this per block name — a\n * block with `usePrepare` and one without run a different number of hooks, so\n * reusing the same fiber across a block switch violates the rules of hooks.\n */\nconst ActionBlockRunner = ({\n actionBlock,\n ...blockProps\n}: ActionBlockProps & { actionBlock: ActionBlockEntry }) => {\n const { Component, usePrepare } = actionBlock\n\n usePrepare(blockProps)\n\n return <Component {...blockProps} />\n}\n\n// `observer` is required: this reads `isCopyLoaded` off GlobalUiStore and the\n// action drawer off InsightsV2Store. Without it the component never re-renders\n// and stays stuck on <Loader /> forever.\nexport const ActionBlockLayer = observer(function ActionBlockLayer({\n beat,\n}: ActionBlockLayerProps) {\n const copy = useGlobalCopyStore()\n const commonCopy = copy.common\n const { isCopyLoaded } = useGlobalUiStore()\n const { actionDrawer, closeActionDrawer } = useInsightsV2Store()\n\n // Mirrors BaseLayout's guard — the layer is exported, so callers are not\n // guaranteed to have narrowed this already.\n if (!beat.insights_payload) return null\n\n const { primary_cta, secondary_cta, guid } = beat.insights_payload\n\n // Every card in the feed renders its own layer against the shared store, so\n // this card's drawer only opens when its beat is the one that triggered it.\n const isCurrentBeatOpen = actionDrawer.isDrawerOpen && actionDrawer.guid === guid\n\n if (!isCopyLoaded) return isCurrentBeatOpen ? <Loader /> : null\n\n const currentCta = getDynamicCtaBasedOnTriggers(actionDrawer, primary_cta, secondary_cta)\n\n // A CTA without a real block never opens a drawer (BaseLayout won't trigger it);\n // a real-but-unknown block shows the error (\"oops\") content.\n const blockValid = hasDrawerBlock(currentCta?.block)\n const actionBlock = blockValid\n ? actionBlocks[currentCta?.block as keyof typeof actionBlocks]\n : undefined\n\n const resolvedTitle = actionBlock?.title?.(currentCta?.variant, copy, beat)\n const drawerTitle = actionBlock\n ? resolvedTitle || currentCta?.label || ''\n : blockValid\n ? commonCopy.error_heading\n : (currentCta?.label ?? '')\n\n return (\n <Drawer\n ariaLabelClose={commonCopy.close_aria}\n isOpen={isCurrentBeatOpen}\n onClose={closeActionDrawer}\n title={drawerTitle}\n >\n {actionBlock ? (\n <ActionBlockRunner actionBlock={actionBlock} beat={beat} key={currentCta?.block} />\n ) : blockValid ? (\n <Stack sx={{ p: 24 }}>\n <Text>{commonCopy.error_message}</Text>\n </Stack>\n ) : null}\n </Drawer>\n )\n})\n"],"mappings":";;;;;;;;;AA8BA,IAAM,IAAA,CAAqB,EACzB,aAAA,GACA,GAAG,EAAA,MACuD;AAC1D,QAAM,EAAE,WAAA,GAAW,YAAA,EAAA,IAAe;AAElC,SAAA,EAAW,CAAU,GAEd,gBAAA,EAAC,GAAD,EAAW,GAAI,EAAa,CAAA;AACrC,GAKa,IAAmB,EAAS,SAA0B,EACjE,MAAA,EAAA,GACwB;AACxB,QAAM,IAAO,EAAmB,GAC1B,IAAa,EAAK,QAClB,EAAE,cAAA,EAAA,IAAiB,EAAiB,GACpC,EAAE,cAAA,GAAc,mBAAA,EAAA,IAAsB,EAAmB;AAI/D,MAAI,CAAC,EAAK,iBAAkB,QAAO;AAEnC,QAAM,EAAE,aAAA,GAAa,eAAA,GAAe,MAAA,EAAA,IAAS,EAAK,kBAI5C,IAAoB,EAAa,gBAAgB,EAAa,SAAS;AAE7E,MAAI,CAAC,EAAc,QAAO,IAAoB,gBAAA,EAAC,GAAD,CAAS,CAAA,IAAI;AAE3D,QAAM,IAAa,EAA6B,GAAc,GAAa,CAAa,GAIlF,IAAa,EAAe,GAAY,KAAK,GAC7C,IAAc,IAChB,EAAa,GAAY,KAAA,IACzB,QAEE,IAAgB,GAAa,QAAQ,GAAY,SAAS,GAAM,CAAI,GACpE,IAAc,IAChB,KAAiB,GAAY,SAAS,KACtC,IACE,EAAW,gBACV,GAAY,SAAS;AAE5B,SACE,gBAAA,EAAC,GAAD;AAAA,IACE,gBAAgB,EAAW;AAAA,IAC3B,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,OAAO;AAAA,IAEN,UAAA,IACC,gBAAA,EAAC,GAAD;AAAA,MAAgC,aAAA;AAAA,MAAmB,MAAA;AAAA,IAA+B,GAApB,GAAY,KAAQ,IAChF,IACF,gBAAA,EAAC,GAAD;AAAA,MAAO,IAAI,EAAE,GAAG,GAAG;AAAA,MACjB,UAAA,gBAAA,EAAC,GAAD,EAAA,UAAO,EAAW,cAAoB,CAAA;AAAA,IACjC,CAAA,IACL;AAAA,EACE,CAAA;AAEZ,CAAC"}
1
+ {"version":3,"file":"ActionBlockLayer.es.js","names":[],"sources":["../../../src/insights-v2/actionBlocks/ActionBlockLayer.tsx"],"sourcesContent":["import Stack from '@mui/material/Stack'\n\nimport { Text } from '@mxenabled/mxui'\nimport { observer } from 'mobx-react-lite'\n\nimport {\n Drawer,\n Loader,\n useGlobalCopyStore,\n useGlobalUiStore,\n useInsightsV2Store,\n} from '../../common'\nimport { type Beat } from '../../core'\nimport {\n actionBlocks,\n hasDrawerBlock,\n type ActionBlockEntry,\n type ActionBlockProps,\n} from '../mappings/blocks'\nimport { getDynamicCtaBasedOnTriggers } from './util'\n\ninterface ActionBlockLayerProps {\n beat: Beat\n}\n\n/**\n * Renders a registered action block. Callers MUST key this per block name — a\n * block with `usePrepare` and one without run a different number of hooks, so\n * reusing the same fiber across a block switch violates the rules of hooks.\n */\nconst ActionBlockRunner = ({\n actionBlock,\n ...blockProps\n}: ActionBlockProps & { actionBlock: ActionBlockEntry }) => {\n const { Component, usePrepare } = actionBlock\n\n usePrepare(blockProps)\n\n return <Component {...blockProps} />\n}\n\n// `observer` is required: this reads `isCopyLoaded` off GlobalUiStore and the\n// action drawer off InsightsV2Store. Without it the component never re-renders\n// and stays stuck on <Loader /> forever.\nexport const ActionBlockLayer = observer(function ActionBlockLayer({\n beat,\n}: ActionBlockLayerProps) {\n const copy = useGlobalCopyStore()\n const commonCopy = copy.common\n const { isCopyLoaded } = useGlobalUiStore()\n const { actionDrawer, closeActionDrawer } = useInsightsV2Store()\n\n // Mirrors BaseLayout's guard — the layer is exported, so callers are not\n // guaranteed to have narrowed this already.\n if (!beat.insights_payload) return null\n\n const { primary_cta, secondary_cta, guid } = beat.insights_payload\n\n // Every card in the feed renders its own layer against the shared store, so\n // this card's drawer only opens when its beat is the one that triggered it.\n const isCurrentBeatOpen = actionDrawer.isDrawerOpen && actionDrawer.guid === guid\n\n if (!isCopyLoaded) return isCurrentBeatOpen ? <Loader /> : null\n\n const currentCta = getDynamicCtaBasedOnTriggers(actionDrawer, primary_cta, secondary_cta)\n\n // A CTA without a real block never opens a drawer (BaseLayout won't trigger it);\n // a real-but-unknown block shows the error (\"oops\") content.\n const blockValid = hasDrawerBlock(currentCta?.block)\n const actionBlock = blockValid\n ? actionBlocks[currentCta?.block as keyof typeof actionBlocks]\n : undefined\n\n // A modal block owns its dialog: no drawer behind it, and nothing mounted until it is opened.\n if (actionBlock?.presentation === 'modal') {\n return isCurrentBeatOpen ? (\n <ActionBlockRunner actionBlock={actionBlock} beat={beat} key={currentCta?.block} />\n ) : null\n }\n\n const resolvedTitle = actionBlock?.title?.(currentCta?.variant, copy, beat)\n const drawerTitle = actionBlock\n ? resolvedTitle || currentCta?.label || ''\n : blockValid\n ? commonCopy.error_heading\n : (currentCta?.label ?? '')\n\n return (\n <Drawer\n ariaLabelClose={commonCopy.close_aria}\n isOpen={isCurrentBeatOpen}\n onClose={closeActionDrawer}\n title={drawerTitle}\n >\n {actionBlock ? (\n <ActionBlockRunner actionBlock={actionBlock} beat={beat} key={currentCta?.block} />\n ) : blockValid ? (\n <Stack sx={{ p: 24 }}>\n <Text>{commonCopy.error_message}</Text>\n </Stack>\n ) : null}\n </Drawer>\n )\n})\n"],"mappings":";;;;;;;;;;AA8BA,IAAM,IAAA,CAAqB,EACzB,aAAA,GACA,GAAG,EAAA,MACuD;AAC1D,QAAM,EAAE,WAAA,GAAW,YAAA,EAAA,IAAe;AAElC,SAAA,EAAW,CAAU,GAEd,gBAAA,EAAC,GAAD,EAAW,GAAI,EAAa,CAAA;AACrC,GAKa,IAAmB,EAAS,SAA0B,EACjE,MAAA,EAAA,GACwB;AACxB,QAAM,IAAO,EAAmB,GAC1B,IAAa,EAAK,QAClB,EAAE,cAAA,EAAA,IAAiB,EAAiB,GACpC,EAAE,cAAA,GAAc,mBAAA,EAAA,IAAsB,EAAmB;AAI/D,MAAI,CAAC,EAAK,iBAAkB,QAAO;AAEnC,QAAM,EAAE,aAAA,GAAa,eAAA,GAAe,MAAA,EAAA,IAAS,EAAK,kBAI5C,IAAoB,EAAa,gBAAgB,EAAa,SAAS;AAE7E,MAAI,CAAC,EAAc,QAAO,IAAoB,gBAAA,EAAC,GAAD,CAAS,CAAA,IAAI;AAE3D,QAAM,IAAa,EAA6B,GAAc,GAAa,CAAa,GAIlF,IAAa,EAAe,GAAY,KAAK,GAC7C,IAAc,IAChB,EAAa,GAAY,KAAA,IACzB;AAGJ,MAAI,GAAa,iBAAiB,QAChC,QAAO,IACL,gBAAA,EAAC,GAAD;AAAA,IAAgC,aAAA;AAAA,IAAmB,MAAA;AAAA,EAA+B,GAApB,GAAY,KAAQ,IAChF;AAGN,QAAM,IAAgB,GAAa,QAAQ,GAAY,SAAS,GAAM,CAAI,GACpE,IAAc,IAChB,KAAiB,GAAY,SAAS,KACtC,IACE,EAAW,gBACV,GAAY,SAAS;AAE5B,SACE,gBAAA,EAAC,GAAD;AAAA,IACE,gBAAgB,EAAW;AAAA,IAC3B,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,OAAO;AAAA,IAEN,UAAA,IACC,gBAAA,EAAC,GAAD;AAAA,MAAgC,aAAA;AAAA,MAAmB,MAAA;AAAA,IAA+B,GAApB,GAAY,KAAQ,IAChF,IACF,gBAAA,EAAC,GAAD;AAAA,MAAO,IAAI,EAAE,GAAG,GAAG;AAAA,MACjB,UAAA,gBAAA,EAAC,GAAD,EAAA,UAAO,EAAW,cAAoB,CAAA;AAAA,IACjC,CAAA,IACL;AAAA,EACE,CAAA;AAEZ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { ActionBlockProps } from '../../mappings/blocks';
2
+ /**
3
+ * `amount_input_modal_block`: one whole-dollar setting edited in a dialog (Figma 441:24913 and
4
+ * 5402:34137). The CTA's variant picks what is edited:
5
+ * - `low_balance_threshold`: the `threshold` on the beat account's low-balance alert profile;
6
+ * - `safety_net`: `savings_opportunity_minimum_checking_account_balance` on the insight profile.
7
+ *
8
+ * Registered with `presentation: 'modal'`, so no drawer opens behind it; closing the dialog ends
9
+ * the action-drawer session. `observer` is required: the starting values are read from stores.
10
+ */
11
+ export declare const AmountInputModalBlock: (({ beat, }: ActionBlockProps) => import("react/jsx-runtime").JSX.Element) & {
12
+ displayName: string;
13
+ };
@@ -0,0 +1,128 @@
1
+ import { buildDynamicCopy as F } from "../../../core/utils/Localization.es.js";
2
+ import G from "../../../common/utils/AccountDisplayName.es.js";
3
+ import { useGlobalCopyStore as W, useInsightsV2Store as j, useSettingsStore as z, useUserStore as q } from "../../../common/context/hooks.es.js";
4
+ import J from "../../../common/components/Loader.es.js";
5
+ import K from "../../../common/components/CurrencyDialog.es.js";
6
+ import { useBeatActions as Q } from "../../beatActions.es.js";
7
+ import { getDynamicCtaBasedOnTriggers as X } from "../util.es.js";
8
+ import { useCtaHandler as Y } from "../../ctaActions/useCtaAction.es.js";
9
+ import { AMOUNT_INPUT_VARIANTS as Z, findLowBalanceProfile as oo, isAmountInputVariant as L, isWholeAmount as to, toInputValue as eo } from "./layout.es.js";
10
+ import r from "react";
11
+ import { observer as io } from "mobx-react-lite";
12
+ import T from "@mui/material/Stack";
13
+ import { H3 as no, InstitutionLogo as ro, Text as P } from "@mxenabled/mxui";
14
+ import { Icon as ao } from "@mxenabled/mx-icons";
15
+ import { jsx as e, jsxs as k } from "react/jsx-runtime";
16
+ import so from "@mui/material/Dialog";
17
+ import co from "@mui/material/IconButton";
18
+ var D = ({ children: y, closeAriaLabel: i, heading: o, onClose: l }) => {
19
+ const u = r.useId();
20
+ return /* @__PURE__ */ e(so, {
21
+ "aria-labelledby": o ? u : void 0,
22
+ maxWidth: "xs",
23
+ onClose: l,
24
+ open: !0,
25
+ children: /* @__PURE__ */ k(T, {
26
+ sx: {
27
+ gap: 12,
28
+ p: 24,
29
+ position: "relative"
30
+ },
31
+ children: [
32
+ o && /* @__PURE__ */ e(no, {
33
+ id: u,
34
+ children: o
35
+ }),
36
+ /* @__PURE__ */ e(co, {
37
+ "aria-label": i || "Close",
38
+ onClick: l,
39
+ sx: {
40
+ position: "absolute",
41
+ right: 8,
42
+ top: 18
43
+ },
44
+ children: /* @__PURE__ */ e(ao, {
45
+ name: "close",
46
+ sx: { color: "action.active" }
47
+ })
48
+ }),
49
+ y
50
+ ]
51
+ })
52
+ });
53
+ }, Lo = io(function({ beat: i }) {
54
+ const { common: o, insights_feed: l } = W(), { actionDrawer: u, closeActionDrawer: c } = j(), f = z(), { userInsightProfile: v } = q(), b = Y(i, Q()), { primary_cta: B, secondary_cta: N } = i.insights_payload ?? {}, s = X(u, B, N)?.variant, a = l?.amount_input_modal, t = s === Z.LOW_BALANCE_THRESHOLD, _ = t ? oo(f.notificationProfiles, i.primary_account_guid) : void 0, I = t ? _?.threshold : v?.savings_opportunity_minimum_checking_account_balance, [M, V] = r.useState(t), m = r.useRef(!0);
55
+ r.useEffect(() => (m.current = !0, () => {
56
+ m.current = !1;
57
+ }), []), r.useEffect(() => {
58
+ t && f.loadNotificationProfiles().finally(() => {
59
+ m.current && V(!1);
60
+ });
61
+ }, [t, f]);
62
+ const [E, H] = r.useState(null), [S, A] = r.useState(!1), [O, h] = r.useState(!1), d = E ?? eo(I);
63
+ if (M) return /* @__PURE__ */ e(D, {
64
+ closeAriaLabel: o?.close_aria,
65
+ onClose: c,
66
+ children: /* @__PURE__ */ e(J, {})
67
+ });
68
+ const n = L(s) ? a?.[s] : void 0, x = !!n?.title && !!n.description && !!n.input_label && !!a?.whole_number_error && !!a.save_error && !!o?.save_button && (!t || !!o.cancel_button) && !!o.close_aria;
69
+ if (!a || !n || !x || !(t ? _ : v))
70
+ return console.warn(`amount_input_modal_block: ${a ? L(s) ? x ? t ? "no low-balance profile for the account" : "user insight profile not set by the host" : `copy incomplete for "${s}"` : `unknown variant "${s}"` : "copy namespace missing"}`), /* @__PURE__ */ e(D, {
71
+ closeAriaLabel: o?.close_aria,
72
+ heading: o?.error_heading,
73
+ onClose: c,
74
+ children: /* @__PURE__ */ e(P, { children: o?.error_message })
75
+ });
76
+ const C = !t && !!I, w = i.primary_account ? G(i.primary_account) : "", g = to(d), R = d !== "" && !g, U = async () => {
77
+ if (!g || S) return;
78
+ const p = Number(d);
79
+ A(!0), h(!1);
80
+ const $ = t ? await b("updateNotificationProfileThreshold", {
81
+ profileGuid: _?.guid,
82
+ threshold: p
83
+ }) : await b("updateUserInsightProfile", { fields: { savings_opportunity_minimum_checking_account_balance: p } });
84
+ m.current && (A(!1), $ ? c() : h(!0));
85
+ };
86
+ return /* @__PURE__ */ e(K, {
87
+ closeAriaLabel: o.close_aria,
88
+ content: F(C && n.description_edit || n.description, /* @__PURE__ */ e("strong", { children: w }, "account")),
89
+ errorText: R ? a.whole_number_error : O ? a.save_error : void 0,
90
+ handleInputChange: (p) => {
91
+ H(p), h(!1);
92
+ },
93
+ handleModalClose: c,
94
+ handlePrimaryAction: () => {
95
+ U();
96
+ },
97
+ handleSecondaryAction: c,
98
+ inputLabel: n.input_label,
99
+ inputValue: d,
100
+ isOpen: !0,
101
+ isPrimaryDisabled: S || !g,
102
+ primaryText: o.save_button,
103
+ secondaryText: t ? o.cancel_button : void 0,
104
+ subtitle: t && i.primary_account ? /* @__PURE__ */ k(T, {
105
+ sx: {
106
+ alignItems: "center",
107
+ flexDirection: "row",
108
+ gap: 8
109
+ },
110
+ children: [/* @__PURE__ */ e(ro, {
111
+ alt: "",
112
+ institutionGuid: i.primary_account.institution_guid ?? "",
113
+ size: 16
114
+ }), /* @__PURE__ */ e(P, {
115
+ color: "text.secondary",
116
+ uppercase: !0,
117
+ variant: "body2",
118
+ children: w
119
+ })]
120
+ }) : void 0,
121
+ title: C && n.title_edit || n.title
122
+ });
123
+ });
124
+ export {
125
+ Lo as AmountInputModalBlock
126
+ };
127
+
128
+ //# sourceMappingURL=AmountInputModalBlock.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AmountInputModalBlock.es.js","names":[],"sources":["../../../../src/insights-v2/actionBlocks/AmountInputModalBlock/AmountInputModalBlock.tsx"],"sourcesContent":["import React from 'react'\n\nimport Stack from '@mui/material/Stack'\n\nimport MuiDialog from '@mui/material/Dialog'\nimport IconButton from '@mui/material/IconButton'\n\nimport { Icon } from '@mxenabled/mx-icons'\nimport { H3, InstitutionLogo, Text } from '@mxenabled/mxui'\nimport { observer } from 'mobx-react-lite'\n\nimport {\n CurrencyDialog,\n Loader,\n buildDynamicCopy,\n useGlobalCopyStore,\n useInsightsV2Store,\n useSettingsStore,\n useUserStore,\n} from '../../../common'\nimport getAccountDisplayName from '../../../common/utils/AccountDisplayName'\nimport { useBeatActions } from '../../beatActions'\nimport { useCtaHandler } from '../../ctaActions'\nimport type { ActionBlockProps } from '../../mappings/blocks'\nimport { getDynamicCtaBasedOnTriggers } from '../util'\n\nimport {\n AMOUNT_INPUT_VARIANTS,\n findLowBalanceProfile,\n isAmountInputVariant,\n isWholeAmount,\n toInputValue,\n} from './layout'\n\n/**\n * The dialog frame for the states that have no form: loading, and a non-retriable problem. Named by\n * its heading and closable by button, Esc and backdrop, like the form dialog.\n */\nconst StatusDialog = ({\n children,\n closeAriaLabel,\n heading,\n onClose,\n}: React.PropsWithChildren<{ closeAriaLabel?: string; heading?: string; onClose: () => void }>) => {\n const headingId = React.useId()\n\n return (\n <MuiDialog\n aria-labelledby={heading ? headingId : undefined}\n maxWidth=\"xs\"\n onClose={onClose}\n open={true}\n >\n <Stack sx={{ gap: 12, p: 24, position: 'relative' }}>\n {heading && <H3 id={headingId}>{heading}</H3>}\n <IconButton\n aria-label={closeAriaLabel || 'Close'}\n onClick={onClose}\n sx={{ position: 'absolute', right: 8, top: 18 }}\n >\n <Icon name=\"close\" sx={{ color: 'action.active' }} />\n </IconButton>\n {children}\n </Stack>\n </MuiDialog>\n )\n}\n\n/**\n * `amount_input_modal_block`: one whole-dollar setting edited in a dialog (Figma 441:24913 and\n * 5402:34137). The CTA's variant picks what is edited:\n * - `low_balance_threshold`: the `threshold` on the beat account's low-balance alert profile;\n * - `safety_net`: `savings_opportunity_minimum_checking_account_balance` on the insight profile.\n *\n * Registered with `presentation: 'modal'`, so no drawer opens behind it; closing the dialog ends\n * the action-drawer session. `observer` is required: the starting values are read from stores.\n */\nexport const AmountInputModalBlock = observer(function AmountInputModalBlock({\n beat,\n}: ActionBlockProps) {\n const { common: commonCopy, insights_feed: insightsFeedCopy } = useGlobalCopyStore()\n const { actionDrawer, closeActionDrawer } = useInsightsV2Store()\n const settingsStore = useSettingsStore()\n const { userInsightProfile } = useUserStore()\n const runHandler = useCtaHandler(beat, useBeatActions())\n\n const { primary_cta, secondary_cta } = beat.insights_payload ?? {}\n const variant = getDynamicCtaBasedOnTriggers(actionDrawer, primary_cta, secondary_cta)?.variant\n const copy = insightsFeedCopy?.amount_input_modal\n const isLowBalance = variant === AMOUNT_INPUT_VARIANTS.LOW_BALANCE_THRESHOLD\n\n const lowBalanceProfile = isLowBalance\n ? findLowBalanceProfile(settingsStore.notificationProfiles, beat.primary_account_guid)\n : undefined\n const savedAmount = isLowBalance\n ? lowBalanceProfile?.threshold\n : userInsightProfile?.savings_opportunity_minimum_checking_account_balance\n\n // Mounted only while open (modal presentation), so mounting is the open: profiles are reloaded\n // here on each open, so the threshold prefills as saved now. `SettingsStore` swallows a failed\n // request, which leaves no profile for the account: the missing-profile error below covers it.\n const [isLoadingProfiles, setIsLoadingProfiles] = React.useState(isLowBalance)\n // False once unmounted: a save that resolves after the user closed the dialog must not close\n // (or update) whatever action session is open by then.\n const isMounted = React.useRef(true)\n\n React.useEffect(() => {\n isMounted.current = true\n\n return () => {\n isMounted.current = false\n }\n }, [])\n\n React.useEffect(() => {\n if (!isLowBalance) return\n\n void settingsStore.loadNotificationProfiles().finally(() => {\n if (isMounted.current) setIsLoadingProfiles(false)\n })\n }, [isLowBalance, settingsStore])\n\n // `null` until the user types: the field shows the saved amount until then.\n const [typed, setTyped] = React.useState<string | null>(null)\n const [isSaving, setIsSaving] = React.useState(false)\n const [saveFailed, setSaveFailed] = React.useState(false)\n\n const value = typed ?? toInputValue(savedAmount)\n\n if (isLoadingProfiles) {\n return (\n <StatusDialog closeAriaLabel={commonCopy?.close_aria} onClose={closeActionDrawer}>\n <Loader />\n </StatusDialog>\n )\n }\n\n // Copy ships separately (see the doc's Rollout order), so check every string the form renders:\n // a partial ship falls to the error dialog instead of throwing mid-render.\n const variantCopy = isAmountInputVariant(variant) ? copy?.[variant] : undefined\n const hasCopy =\n !!variantCopy?.title &&\n !!variantCopy.description &&\n !!variantCopy.input_label &&\n !!copy?.whole_number_error &&\n !!copy.save_error &&\n !!commonCopy?.save_button &&\n // Cancel renders for the low-balance variant only.\n (!isLowBalance || !!commonCopy.cancel_button) &&\n !!commonCopy.close_aria\n const hasProfile = isLowBalance ? !!lowBalanceProfile : !!userInsightProfile\n\n if (!copy || !variantCopy || !hasCopy || !hasProfile) {\n // One message to the user; distinct warnings so a rollout problem can be traced to its cause.\n console.warn(\n `amount_input_modal_block: ${\n !copy\n ? 'copy namespace missing'\n : !isAmountInputVariant(variant)\n ? `unknown variant \"${variant}\"`\n : !hasCopy\n ? `copy incomplete for \"${variant}\"`\n : isLowBalance\n ? 'no low-balance profile for the account'\n : 'user insight profile not set by the host'\n }`,\n )\n\n return (\n <StatusDialog\n closeAriaLabel={commonCopy?.close_aria}\n heading={commonCopy?.error_heading}\n onClose={closeActionDrawer}\n >\n <Text>{commonCopy?.error_message}</Text>\n </StatusDialog>\n )\n }\n\n const isEdit = !isLowBalance && !!savedAmount\n const accountName = beat.primary_account ? getAccountDisplayName(beat.primary_account) : ''\n const isValid = isWholeAmount(value)\n const isInvalid = value !== '' && !isValid\n\n const handleSave = async () => {\n // Guarded here too, not only by the disabled button: Enter submits the dialog's form directly.\n if (!isValid || isSaving) return\n\n const amount = Number(value)\n\n setIsSaving(true)\n setSaveFailed(false)\n\n const ok = isLowBalance\n ? await runHandler('updateNotificationProfileThreshold', {\n profileGuid: lowBalanceProfile?.guid,\n threshold: amount,\n })\n : await runHandler('updateUserInsightProfile', {\n fields: { savings_opportunity_minimum_checking_account_balance: amount },\n })\n\n if (!isMounted.current) return\n\n setIsSaving(false)\n\n if (ok) closeActionDrawer()\n else setSaveFailed(true)\n }\n\n return (\n <CurrencyDialog\n closeAriaLabel={commonCopy.close_aria}\n // Only strings and the <strong> go in, so the result is renderable (the helper's type also\n // admits raw DOM nodes).\n content={\n buildDynamicCopy(\n (isEdit && variantCopy.description_edit) || variantCopy.description,\n <strong key=\"account\">{accountName}</strong>,\n ) as React.ReactNode\n }\n errorText={isInvalid ? copy.whole_number_error : saveFailed ? copy.save_error : undefined}\n handleInputChange={(next) => {\n setTyped(next)\n setSaveFailed(false)\n }}\n handleModalClose={closeActionDrawer}\n handlePrimaryAction={() => void handleSave()}\n handleSecondaryAction={closeActionDrawer}\n inputLabel={variantCopy.input_label}\n inputValue={value}\n isOpen={true}\n isPrimaryDisabled={isSaving || !isValid}\n primaryText={commonCopy.save_button}\n secondaryText={isLowBalance ? commonCopy.cancel_button : undefined}\n subtitle={\n isLowBalance && beat.primary_account ? (\n <Stack sx={{ alignItems: 'center', flexDirection: 'row', gap: 8 }}>\n {/* Decorative: the account name is the visible text beside it. */}\n <InstitutionLogo\n alt=\"\"\n institutionGuid={beat.primary_account.institution_guid ?? ''}\n size={16}\n />\n <Text color=\"text.secondary\" uppercase={true} variant=\"body2\">\n {accountName}\n </Text>\n </Stack>\n ) : undefined\n }\n title={(isEdit && variantCopy.title_edit) || variantCopy.title}\n />\n )\n})\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export { AmountInputModalBlock } from './AmountInputModalBlock';
@@ -0,0 +1,14 @@
1
+ import { NotificationProfile } from '../../../core';
2
+ /** CTA variants `amount_input_modal_block` serves (ditto sets one on the beat's CTA). */
3
+ export declare const AMOUNT_INPUT_VARIANTS: {
4
+ readonly LOW_BALANCE_THRESHOLD: "low_balance_threshold";
5
+ readonly SAFETY_NET: "safety_net";
6
+ };
7
+ export type AmountInputVariant = (typeof AMOUNT_INPUT_VARIANTS)[keyof typeof AMOUNT_INPUT_VARIANTS];
8
+ export declare const isAmountInputVariant: (variant?: string | null) => variant is AmountInputVariant;
9
+ /** Whole dollars from 1 to `MAX_AMOUNT`, as pulse v1 accepted for both settings. */
10
+ export declare const isWholeAmount: (value: string) => boolean;
11
+ /** A saved amount as the field's starting text; nothing saved (or zero) starts empty. */
12
+ export declare const toInputValue: (amount?: number | null) => string;
13
+ /** The account's low-balance alert profile, which holds the threshold (as pulse v1 looked it up). */
14
+ export declare const findLowBalanceProfile: (profiles: NotificationProfile[], accountGuid?: string | null) => NotificationProfile | undefined;
@@ -0,0 +1,14 @@
1
+ import { AccountNotificationTypes as o } from "../../../core/types/Notification.es.js";
2
+ var a = {
3
+ LOW_BALANCE_THRESHOLD: "low_balance_threshold",
4
+ SAFETY_NET: "safety_net"
5
+ }, A = (t) => Object.values(a).includes(t ?? ""), i = 1e9, _ = (t) => /^\d+$/.test(t) && Number(t) >= 1 && Number(t) <= i, c = (t) => t ? String(Math.round(t)) : "", N = (t, n) => n ? t.find((e) => e.entity_guid === n && e.notification_type === o.AccountBalanceLow) : void 0;
6
+ export {
7
+ a as AMOUNT_INPUT_VARIANTS,
8
+ N as findLowBalanceProfile,
9
+ A as isAmountInputVariant,
10
+ _ as isWholeAmount,
11
+ c as toInputValue
12
+ };
13
+
14
+ //# sourceMappingURL=layout.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.es.js","names":[],"sources":["../../../../src/insights-v2/actionBlocks/AmountInputModalBlock/layout.ts"],"sourcesContent":["import type { NotificationProfile } from '../../../core'\nimport { AccountNotificationTypes } from '../../../core/types/Notification'\n\n/** CTA variants `amount_input_modal_block` serves (ditto sets one on the beat's CTA). */\nexport const AMOUNT_INPUT_VARIANTS = {\n LOW_BALANCE_THRESHOLD: 'low_balance_threshold',\n SAFETY_NET: 'safety_net',\n} as const\n\nexport type AmountInputVariant = (typeof AMOUNT_INPUT_VARIANTS)[keyof typeof AMOUNT_INPUT_VARIANTS]\n\nexport const isAmountInputVariant = (variant?: string | null): variant is AmountInputVariant =>\n Object.values<string>(AMOUNT_INPUT_VARIANTS).includes(variant ?? '')\n\n/** Pulse v1's upper bound for a safety net; applied to both variants. */\nconst MAX_AMOUNT = 1_000_000_000\n\n/** Whole dollars from 1 to `MAX_AMOUNT`, as pulse v1 accepted for both settings. */\nexport const isWholeAmount = (value: string): boolean =>\n /^\\d+$/.test(value) && Number(value) >= 1 && Number(value) <= MAX_AMOUNT\n\n/** A saved amount as the field's starting text; nothing saved (or zero) starts empty. */\nexport const toInputValue = (amount?: number | null): string =>\n amount ? String(Math.round(amount)) : ''\n\n/** The account's low-balance alert profile, which holds the threshold (as pulse v1 looked it up). */\nexport const findLowBalanceProfile = (\n profiles: NotificationProfile[],\n accountGuid?: string | null,\n): NotificationProfile | undefined =>\n accountGuid\n ? profiles.find(\n (profile) =>\n profile.entity_guid === accountGuid &&\n profile.notification_type === AccountNotificationTypes.AccountBalanceLow,\n )\n : undefined\n"],"mappings":";AAIA,IAAa,IAAwB;AAAA,EACnC,uBAAuB;AAAA,EACvB,YAAY;AACd,GAIa,IAAA,CAAwB,MACnC,OAAO,OAAe,CAAqB,EAAE,SAAS,KAAW,EAAE,GAG/D,IAAa,KAGN,IAAA,CAAiB,MAC5B,QAAQ,KAAK,CAAK,KAAK,OAAO,CAAK,KAAK,KAAK,OAAO,CAAK,KAAK,GAGnD,IAAA,CAAgB,MAC3B,IAAS,OAAO,KAAK,MAAM,CAAM,CAAC,IAAI,IAG3B,IAAA,CACX,GACA,MAEA,IACI,EAAS,KAAA,CACN,MACC,EAAQ,gBAAgB,KACxB,EAAQ,sBAAsB,EAAyB,iBAC3D,IACA"}
@@ -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
  */