@mx-cartographer/experiences 9.4.64 → 9.4.65
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.
- package/CHANGELOG.md +7 -0
- package/dist/core/stores/InsightsV2Store.d.ts +19 -0
- package/dist/core/stores/InsightsV2Store.es.js +31 -14
- package/dist/core/stores/InsightsV2Store.es.js.map +1 -1
- package/dist/core/types/Insights.d.ts +10 -0
- package/dist/insights-v2/beatActions.d.ts +11 -0
- package/dist/insights-v2/beatActions.es.js.map +1 -1
- package/dist/insights-v2/components/BaseLayout.es.js +84 -80
- package/dist/insights-v2/components/BaseLayout.es.js.map +1 -1
- package/dist/insights-v2/ctaActions/ctaConfig.d.ts +7 -0
- package/dist/insights-v2/ctaActions/ctaConfig.es.js +10 -0
- package/dist/insights-v2/ctaActions/ctaConfig.es.js.map +1 -0
- package/dist/insights-v2/ctaActions/ctaHandlers.d.ts +44 -0
- package/dist/insights-v2/ctaActions/ctaHandlers.es.js +107 -0
- package/dist/insights-v2/ctaActions/ctaHandlers.es.js.map +1 -0
- package/dist/insights-v2/ctaActions/hostActions.d.ts +17 -0
- package/dist/insights-v2/ctaActions/hostActions.es.js +16 -0
- package/dist/insights-v2/ctaActions/hostActions.es.js.map +1 -0
- package/dist/insights-v2/ctaActions/index.d.ts +6 -0
- package/dist/insights-v2/ctaActions/runCtaAction.d.ts +12 -0
- package/dist/insights-v2/ctaActions/runCtaAction.es.js +79 -0
- package/dist/insights-v2/ctaActions/runCtaAction.es.js.map +1 -0
- package/dist/insights-v2/ctaActions/types.d.ts +57 -0
- package/dist/insights-v2/ctaActions/useCtaAction.d.ts +19 -0
- package/dist/insights-v2/ctaActions/useCtaAction.es.js +44 -0
- package/dist/insights-v2/ctaActions/useCtaAction.es.js.map +1 -0
- package/dist/insights-v2/index.d.ts +3 -1
- package/dist/insights-v2/index.es.js +53 -48
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [9.4.65] - 10-08-2026
|
|
2
|
+
|
|
3
|
+
- **ADDED** - Insights V2 CTA action layer (`src/insights-v2/ctaActions`): a card CTA whose backend-named `action_key` (ditto `*_cta_action`, passed through by tupac on `primary_cta` / `secondary_cta`) has a registered step runs that step first: a typed store handler, `onSuccess` effects (`refreshBeat`), a client-only disable (`disabledWhen`), then its drawer or message. No key, or an unknown key, keeps the default (drawer if the CTA has a block, else post). First key: `dismiss_beat` (ConnectDiscoveredAccounts). Per-beat `ctaStatus` and `beatContext` on `InsightsV2Store`; `useBeatCtaActions` for the card and `useCtaHandler` for saves inside a drawer (WEC-1852)
|
|
4
|
+
- **ADDED** - `BeatActions.onCtaAction` so host-owned effects (`HOST_ACTIONS`: `markCtaClicked`, `dismissBeat`, `updateBeat`, `readBeatSummary`, `sendBeatFeedback`, `disableBeatTemplate`, spending plan items) are delegated to the embedding app (WEC-1852)
|
|
5
|
+
- **CHANGED** - `BaseLayout` delegates CTA clicks to the runner, disables CTAs while a handler is pending, and records the first primary click (`cta_clicked_at`) through the host (WEC-1852)
|
|
6
|
+
- **CHANGED** - `BlockType` gains `account_switch_block` and `save_extra_block`, which were already registered blocks (WEC-1852)
|
|
7
|
+
|
|
1
8
|
## [9.4.64] - 10-08-2026
|
|
2
9
|
|
|
3
10
|
- **ADDED** - `SupportPrompt` help component: a "Need more assistance?" text button that reveals an "Open a Case" button on click, used on every clickable Request Support category card and at the end of every help article. Only the reveal callers supply the prompt copy, so the prompt never renders empty. Clicking "Open a Case" opens the contact form with the category or article title as the ticket title. `RequestSupport` accepts a `caseTopic` prop; from an article the panel is not rendered at all and the contact form is the whole surface (WEC-1783)
|
|
@@ -26,6 +26,8 @@ interface OpenActionDrawerArgs {
|
|
|
26
26
|
trigger: ActionDrawerTrigger;
|
|
27
27
|
context?: unknown;
|
|
28
28
|
}
|
|
29
|
+
/** Lifecycle of a beat's CTA action (see insights-v2/ctaActions), keyed by beat guid. */
|
|
30
|
+
export type CtaStatus = 'pending' | 'done' | 'error';
|
|
29
31
|
/**
|
|
30
32
|
* UI state shared across the insights-v2 widget tree. Owns the action drawer so
|
|
31
33
|
* cards, charts, and action blocks coordinate through the store instead of prop
|
|
@@ -35,7 +37,24 @@ interface OpenActionDrawerArgs {
|
|
|
35
37
|
export declare class InsightsV2Store {
|
|
36
38
|
globalStore: GlobalStore;
|
|
37
39
|
actionDrawer: ActionDrawerState;
|
|
40
|
+
/**
|
|
41
|
+
* CTA action status per beat guid. Keyed by guid (not block) so a block shared by many
|
|
42
|
+
* insights never reflects another card's pending or error state.
|
|
43
|
+
*/
|
|
44
|
+
ctaStatus: Record<string, CtaStatus>;
|
|
45
|
+
/**
|
|
46
|
+
* Per-beat scratch input collected on the card or in its blocks (e.g. the account a user
|
|
47
|
+
* picked before pressing Save), keyed by beat guid. Unlike `actionDrawer.context`, which is
|
|
48
|
+
* replaced whenever any drawer session starts, this survives other cards' drawers opening.
|
|
49
|
+
* CTA steps read it via `disabledWhen` and their `params` callback (`beatContextOf`). Ships
|
|
50
|
+
* ahead of its first block writer (Designate's account picker) on purpose: it is the layer's
|
|
51
|
+
* only way to keep a pick alive across other cards' drawer sessions.
|
|
52
|
+
*/
|
|
53
|
+
beatContext: Record<string, Record<string, unknown>>;
|
|
38
54
|
constructor(globalStore: GlobalStore);
|
|
55
|
+
setCtaStatus: (guid: string, status: CtaStatus) => void;
|
|
56
|
+
/** Merges `values` into the beat's scratch input. */
|
|
57
|
+
setBeatContext: (guid: string, values: Record<string, unknown>) => void;
|
|
39
58
|
/**
|
|
40
59
|
* Merges keys into the current drawer session's context bag — it does NOT
|
|
41
60
|
* replace it. A nested drawer (e.g. a row click inside TransactionHistoryBlock
|
|
@@ -1,36 +1,53 @@
|
|
|
1
|
-
import { makeAutoObservable as
|
|
1
|
+
import { makeAutoObservable as r } from "mobx";
|
|
2
2
|
var o = {
|
|
3
3
|
isDrawerOpen: !1,
|
|
4
4
|
trigger: "primaryCta",
|
|
5
5
|
guid: "",
|
|
6
6
|
context: void 0
|
|
7
|
-
},
|
|
7
|
+
}, s = class {
|
|
8
8
|
globalStore;
|
|
9
9
|
actionDrawer = o;
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
ctaStatus = {};
|
|
11
|
+
beatContext = {};
|
|
12
|
+
constructor(t) {
|
|
13
|
+
this.globalStore = t, r(this);
|
|
12
14
|
}
|
|
13
|
-
|
|
15
|
+
setCtaStatus = (t, e) => {
|
|
16
|
+
this.ctaStatus = {
|
|
17
|
+
...this.ctaStatus,
|
|
18
|
+
[t]: e
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
setBeatContext = (t, e) => {
|
|
22
|
+
this.beatContext = {
|
|
23
|
+
...this.beatContext,
|
|
24
|
+
[t]: {
|
|
25
|
+
...this.beatContext[t],
|
|
26
|
+
...e
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
setActionContext = (t) => {
|
|
14
31
|
this.actionDrawer = {
|
|
15
32
|
...this.actionDrawer,
|
|
16
33
|
context: {
|
|
17
34
|
...this.actionDrawer.context,
|
|
18
|
-
...
|
|
35
|
+
...t
|
|
19
36
|
}
|
|
20
37
|
};
|
|
21
38
|
};
|
|
22
|
-
openActionDrawer = ({ guid:
|
|
39
|
+
openActionDrawer = ({ guid: t, trigger: e, context: a }) => {
|
|
23
40
|
this.actionDrawer = {
|
|
24
41
|
isDrawerOpen: !0,
|
|
25
|
-
trigger:
|
|
26
|
-
guid:
|
|
27
|
-
context:
|
|
42
|
+
trigger: e,
|
|
43
|
+
guid: t,
|
|
44
|
+
context: a
|
|
28
45
|
};
|
|
29
46
|
};
|
|
30
|
-
openCtaDrawer = (
|
|
47
|
+
openCtaDrawer = (t, e) => {
|
|
31
48
|
this.openActionDrawer({
|
|
32
|
-
guid:
|
|
33
|
-
trigger:
|
|
49
|
+
guid: t,
|
|
50
|
+
trigger: e
|
|
34
51
|
});
|
|
35
52
|
};
|
|
36
53
|
closeActionDrawer = () => {
|
|
@@ -43,7 +60,7 @@ var o = {
|
|
|
43
60
|
};
|
|
44
61
|
export {
|
|
45
62
|
o as CLOSED_ACTION_DRAWER,
|
|
46
|
-
|
|
63
|
+
s as InsightsV2Store
|
|
47
64
|
};
|
|
48
65
|
|
|
49
66
|
//# sourceMappingURL=InsightsV2Store.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InsightsV2Store.es.js","names":[],"sources":["../../../src/core/stores/InsightsV2Store.ts"],"sourcesContent":["import { makeAutoObservable } from 'mobx'\n\nimport type { GlobalStore } from './GlobalStore'\n\nexport type ActionDrawerTrigger = 'primaryCta' | 'secondaryCta' | 'chartBar'\n\nexport interface ActionDrawerState {\n isDrawerOpen: boolean\n trigger: ActionDrawerTrigger\n guid: string\n /**\n * Block-specific drilldown data for the current drawer SESSION, opaque to the\n * store. Each action block defines and reads its own shape (via\n * useActionContext<T>()). Chart drilldowns put `{ chartBarIndex, tabIndex }`\n * here; CTAs carry none.\n *\n * This is an accumulating bag, not a single owner's value: a nested drawer\n * (e.g. TransactionDetailsBlock opened from a row inside TransactionHistory\n * Block) adds its own key via `setActionContext` ON TOP of whatever the outer\n * drawer already put here, so the outer block's own context survives while the\n * nested block is open. It resets to a clean slate only when a NEW drawer\n * session starts (`openActionDrawer`/`openCtaDrawer`, which fully replace the\n * envelope) — not on every `setActionContext` call.\n */\n context: unknown\n}\n\nexport const CLOSED_ACTION_DRAWER: ActionDrawerState = {\n isDrawerOpen: false,\n trigger: 'primaryCta',\n guid: '',\n context: undefined,\n}\n\ninterface OpenActionDrawerArgs {\n guid: string\n trigger: ActionDrawerTrigger\n context?: unknown\n}\n\n/**\n * UI state shared across the insights-v2 widget tree. Owns the action drawer so\n * cards, charts, and action blocks coordinate through the store instead of prop\n * drilling. The drawer state is a fixed envelope (isDrawerOpen/guid/trigger) plus\n * an opaque `context` bag, so per-block drilldown data never leaks into this shape.\n */\nexport class InsightsV2Store {\n globalStore: GlobalStore\n\n actionDrawer: ActionDrawerState = CLOSED_ACTION_DRAWER\n\n constructor(globalStore: GlobalStore) {\n this.globalStore = globalStore\n\n makeAutoObservable(this)\n }\n\n /**\n * Merges keys into the current drawer session's context bag — it does NOT\n * replace it. A nested drawer (e.g. a row click inside TransactionHistoryBlock\n * opening TransactionDetailsBlock) calls this to layer its own key (e.g.\n * `transaction_guid`) on top of whatever context the outer drawer already set\n * (e.g. `chartBarIndex`), so the outer block keeps reading its own keys via\n * useActionContext while the nested block is open. The bag only returns to a\n * clean slate when a new drawer session starts via `openActionDrawer`/\n * `openCtaDrawer`, which fully replace the envelope.\n */\n setActionContext = (context: Record<string, unknown>) => {\n this.actionDrawer = {\n ...this.actionDrawer,\n context: {\n ...(this.actionDrawer.context as Record<string, unknown> | undefined),\n ...context,\n },\n }\n }\n\n /**\n * Generic drawer opener — the only opener a new action block needs. Pass the\n * beat guid, the CTA/source that triggered it, and (optionally) a block-specific\n * context object the block reads back via useActionContext.\n */\n openActionDrawer = ({ guid, trigger, context }: OpenActionDrawerArgs) => {\n this.actionDrawer = { isDrawerOpen: true, trigger, guid, context }\n }\n\n /** Convenience opener for CTA drawers (no drilldown context). */\n openCtaDrawer = (guid: string, trigger: 'primaryCta' | 'secondaryCta') => {\n this.openActionDrawer({ guid, trigger })\n }\n\n closeActionDrawer = () => {\n // Preserve `trigger` + `context` so the drawer keeps its variant-specific\n // title/content through the slide-out animation (ActionBlockLayer stays\n // mounted while closing). Only flip isDrawerOpen off and clear the beat guid.\n this.actionDrawer = { ...this.actionDrawer, isDrawerOpen: false, guid: '' }\n }\n}\n"],"mappings":";AA2BA,IAAa,IAA0C;AAAA,EACrD,cAAc;AAAA,EACd,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AACX,
|
|
1
|
+
{"version":3,"file":"InsightsV2Store.es.js","names":[],"sources":["../../../src/core/stores/InsightsV2Store.ts"],"sourcesContent":["import { makeAutoObservable } from 'mobx'\n\nimport type { GlobalStore } from './GlobalStore'\n\nexport type ActionDrawerTrigger = 'primaryCta' | 'secondaryCta' | 'chartBar'\n\nexport interface ActionDrawerState {\n isDrawerOpen: boolean\n trigger: ActionDrawerTrigger\n guid: string\n /**\n * Block-specific drilldown data for the current drawer SESSION, opaque to the\n * store. Each action block defines and reads its own shape (via\n * useActionContext<T>()). Chart drilldowns put `{ chartBarIndex, tabIndex }`\n * here; CTAs carry none.\n *\n * This is an accumulating bag, not a single owner's value: a nested drawer\n * (e.g. TransactionDetailsBlock opened from a row inside TransactionHistory\n * Block) adds its own key via `setActionContext` ON TOP of whatever the outer\n * drawer already put here, so the outer block's own context survives while the\n * nested block is open. It resets to a clean slate only when a NEW drawer\n * session starts (`openActionDrawer`/`openCtaDrawer`, which fully replace the\n * envelope) — not on every `setActionContext` call.\n */\n context: unknown\n}\n\nexport const CLOSED_ACTION_DRAWER: ActionDrawerState = {\n isDrawerOpen: false,\n trigger: 'primaryCta',\n guid: '',\n context: undefined,\n}\n\ninterface OpenActionDrawerArgs {\n guid: string\n trigger: ActionDrawerTrigger\n context?: unknown\n}\n\n/** Lifecycle of a beat's CTA action (see insights-v2/ctaActions), keyed by beat guid. */\nexport type CtaStatus = 'pending' | 'done' | 'error'\n\n/**\n * UI state shared across the insights-v2 widget tree. Owns the action drawer so\n * cards, charts, and action blocks coordinate through the store instead of prop\n * drilling. The drawer state is a fixed envelope (isDrawerOpen/guid/trigger) plus\n * an opaque `context` bag, so per-block drilldown data never leaks into this shape.\n */\nexport class InsightsV2Store {\n globalStore: GlobalStore\n\n actionDrawer: ActionDrawerState = CLOSED_ACTION_DRAWER\n\n /**\n * CTA action status per beat guid. Keyed by guid (not block) so a block shared by many\n * insights never reflects another card's pending or error state.\n */\n ctaStatus: Record<string, CtaStatus> = {}\n\n /**\n * Per-beat scratch input collected on the card or in its blocks (e.g. the account a user\n * picked before pressing Save), keyed by beat guid. Unlike `actionDrawer.context`, which is\n * replaced whenever any drawer session starts, this survives other cards' drawers opening.\n * CTA steps read it via `disabledWhen` and their `params` callback (`beatContextOf`). Ships\n * ahead of its first block writer (Designate's account picker) on purpose: it is the layer's\n * only way to keep a pick alive across other cards' drawer sessions.\n */\n beatContext: Record<string, Record<string, unknown>> = {}\n\n constructor(globalStore: GlobalStore) {\n this.globalStore = globalStore\n\n makeAutoObservable(this)\n }\n\n setCtaStatus = (guid: string, status: CtaStatus) => {\n this.ctaStatus = { ...this.ctaStatus, [guid]: status }\n }\n\n /** Merges `values` into the beat's scratch input. */\n setBeatContext = (guid: string, values: Record<string, unknown>) => {\n this.beatContext = { ...this.beatContext, [guid]: { ...this.beatContext[guid], ...values } }\n }\n\n /**\n * Merges keys into the current drawer session's context bag — it does NOT\n * replace it. A nested drawer (e.g. a row click inside TransactionHistoryBlock\n * opening TransactionDetailsBlock) calls this to layer its own key (e.g.\n * `transaction_guid`) on top of whatever context the outer drawer already set\n * (e.g. `chartBarIndex`), so the outer block keeps reading its own keys via\n * useActionContext while the nested block is open. The bag only returns to a\n * clean slate when a new drawer session starts via `openActionDrawer`/\n * `openCtaDrawer`, which fully replace the envelope.\n */\n setActionContext = (context: Record<string, unknown>) => {\n this.actionDrawer = {\n ...this.actionDrawer,\n context: {\n ...(this.actionDrawer.context as Record<string, unknown> | undefined),\n ...context,\n },\n }\n }\n\n /**\n * Generic drawer opener — the only opener a new action block needs. Pass the\n * beat guid, the CTA/source that triggered it, and (optionally) a block-specific\n * context object the block reads back via useActionContext.\n */\n openActionDrawer = ({ guid, trigger, context }: OpenActionDrawerArgs) => {\n this.actionDrawer = { isDrawerOpen: true, trigger, guid, context }\n }\n\n /** Convenience opener for CTA drawers (no drilldown context). */\n openCtaDrawer = (guid: string, trigger: 'primaryCta' | 'secondaryCta') => {\n this.openActionDrawer({ guid, trigger })\n }\n\n closeActionDrawer = () => {\n // Preserve `trigger` + `context` so the drawer keeps its variant-specific\n // title/content through the slide-out animation (ActionBlockLayer stays\n // mounted while closing). Only flip isDrawerOpen off and clear the beat guid.\n this.actionDrawer = { ...this.actionDrawer, isDrawerOpen: false, guid: '' }\n }\n}\n"],"mappings":";AA2BA,IAAa,IAA0C;AAAA,EACrD,cAAc;AAAA,EACd,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AACX,GAiBa,IAAb,MAA6B;AAAA,EAC3B;AAAA,EAEA,eAAkC;AAAA,EAMlC,YAAuC,CAAC;AAAA,EAUxC,cAAuD,CAAC;AAAA,EAExD,YAAY,GAA0B;AACpC,SAAK,cAAc,GAEnB,EAAmB,IAAI;AAAA,EACzB;AAAA,EAEA,eAAA,CAAgB,GAAc,MAAsB;AAClD,SAAK,YAAY;AAAA,MAAE,GAAG,KAAK;AAAA,MAAY,CAAA,CAAA,GAAO;AAAA,IAAO;AAAA,EACvD;AAAA,EAGA,iBAAA,CAAkB,GAAc,MAAoC;AAClE,SAAK,cAAc;AAAA,MAAE,GAAG,KAAK;AAAA,MAAc,CAAA,CAAA,GAAO;AAAA,QAAE,GAAG,KAAK,YAAY,CAAA;AAAA,QAAO,GAAG;AAAA,MAAO;AAAA,IAAE;AAAA,EAC7F;AAAA,EAYA,mBAAA,CAAoB,MAAqC;AACvD,SAAK,eAAe;AAAA,MAClB,GAAG,KAAK;AAAA,MACR,SAAS;AAAA,QACP,GAAI,KAAK,aAAa;AAAA,QACtB,GAAG;AAAA,MACL;AAAA,IACF;AAAA,EACF;AAAA,EAOA,mBAAA,CAAoB,EAAE,MAAA,GAAM,SAAA,GAAS,SAAA,EAAA,MAAoC;AACvE,SAAK,eAAe;AAAA,MAAE,cAAc;AAAA,MAAM,SAAA;AAAA,MAAS,MAAA;AAAA,MAAM,SAAA;AAAA,IAAQ;AAAA,EACnE;AAAA,EAGA,gBAAA,CAAiB,GAAc,MAA2C;AACxE,SAAK,iBAAiB;AAAA,MAAE,MAAA;AAAA,MAAM,SAAA;AAAA,IAAQ,CAAC;AAAA,EACzC;AAAA,EAEA,oBAAA,MAA0B;AAIxB,SAAK,eAAe;AAAA,MAAE,GAAG,KAAK;AAAA,MAAc,cAAc;AAAA,MAAO,MAAM;AAAA,IAAG;AAAA,EAC5E;AACF"}
|
|
@@ -159,11 +159,19 @@ export interface PrimaryCTA {
|
|
|
159
159
|
label: string;
|
|
160
160
|
block: string;
|
|
161
161
|
variant?: string | null;
|
|
162
|
+
/**
|
|
163
|
+
* What pressing the CTA does beyond opening its block, named by the backend (ditto
|
|
164
|
+
* `primary_cta_action`, passed through by tupac). Looked up in `insights-v2/ctaActions`;
|
|
165
|
+
* null / absent / unknown means the CTA only opens its block or posts its message.
|
|
166
|
+
*/
|
|
167
|
+
action_key?: string | null;
|
|
162
168
|
}
|
|
163
169
|
export interface SecondaryCTA {
|
|
164
170
|
label: string;
|
|
165
171
|
block: string;
|
|
166
172
|
variant?: string | null;
|
|
173
|
+
/** See `PrimaryCTA.action_key` (ditto `secondary_cta_action`). */
|
|
174
|
+
action_key?: string | null;
|
|
167
175
|
}
|
|
168
176
|
export interface Footer {
|
|
169
177
|
/** V1: a pre-formatted date string. */
|
|
@@ -182,6 +190,7 @@ export interface Footer {
|
|
|
182
190
|
}
|
|
183
191
|
export declare const BlockType: {
|
|
184
192
|
readonly AccountBlock: "account_block";
|
|
193
|
+
readonly AccountSwitchBlock: "account_switch_block";
|
|
185
194
|
readonly BarChartBlock: "bar_chart_block";
|
|
186
195
|
readonly BudgetBlock: "budget_block";
|
|
187
196
|
readonly ImageBlock: "image_block";
|
|
@@ -189,6 +198,7 @@ export declare const BlockType: {
|
|
|
189
198
|
readonly DonutChartBlock: "donut_chart_block";
|
|
190
199
|
readonly DoubleBarChartBlock: "double_bar_chart_block";
|
|
191
200
|
readonly DoubleProgressBarBlock: "double_progress_bar_block";
|
|
201
|
+
readonly SaveExtraBlock: "save_extra_block";
|
|
192
202
|
readonly StepChartBlock: "step_chart_block";
|
|
193
203
|
readonly SVGImageBlock: "svg_image_block";
|
|
194
204
|
readonly WithdrawalBlock: "withdrawal_block";
|
|
@@ -21,6 +21,16 @@ export interface DismissParams {
|
|
|
21
21
|
beatGuid: string;
|
|
22
22
|
type: DismissType;
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* A CTA side effect the host must perform because experiences cannot (beat-owned endpoints,
|
|
26
|
+
* spending plan items, third-party SDKs). `name` is agreed between the ctaActions table and
|
|
27
|
+
* the host; see insights-v2/ctaActions/README.md for the list.
|
|
28
|
+
*/
|
|
29
|
+
export interface CtaActionParams {
|
|
30
|
+
beatGuid: string;
|
|
31
|
+
name: string;
|
|
32
|
+
params?: Record<string, unknown>;
|
|
33
|
+
}
|
|
24
34
|
/** Host callbacks for a beat card. */
|
|
25
35
|
export interface BeatActions {
|
|
26
36
|
onMenuAction?: MenuActionHandlers;
|
|
@@ -40,6 +50,7 @@ export interface BeatActions {
|
|
|
40
50
|
* renders disabled (see `isContactSupportCtaDisabled`).
|
|
41
51
|
*/
|
|
42
52
|
onContactSupport?: () => void;
|
|
53
|
+
onCtaAction?: (params: CtaActionParams) => Promise<void> | void;
|
|
43
54
|
}
|
|
44
55
|
export declare const BeatActionsProvider: ({ value, children, }: {
|
|
45
56
|
value: BeatActions;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"beatActions.es.js","names":[],"sources":["../../src/insights-v2/beatActions.tsx"],"sourcesContent":["import { createContext, useContext, type ReactNode } from 'react'\n\nimport type { DismissType } from './components/DismissInsightDialog'\nimport type { FeedbackDialogCloseReason } from './components/FeedbackDialog'\n\nexport type InsightMenuAction = 'helpful' | 'not_helpful' | 'hide'\nexport type InsightRating = 'helpful' | 'not_helpful'\n\nexport interface MenuActionHandlers {\n onAction: (action: InsightMenuAction) => void\n onOpen?: () => void\n disabled?: boolean\n}\n\nexport interface UpdateParams {\n beatGuid: string\n}\n\nexport interface FeedbackParams {\n beatGuid: string\n source: InsightRating | 'hide'\n option: string\n detail?: string\n}\n\nexport interface DismissParams {\n beatGuid: string\n type: DismissType\n}\n\n/** Host callbacks for a beat card. */\nexport interface BeatActions {\n onMenuAction?: MenuActionHandlers\n onUpdate?: (params: UpdateParams) => void\n onSubmitFeedback?: (params: FeedbackParams) => void\n onDismissInsight?: (params: DismissParams) => void\n onUndoDismiss?: (params: { beatGuid: string }) => void\n onFeedbackDialogClose?: (reason: FeedbackDialogCloseReason) => void\n onFeedbackDialogBack?: () => void\n onFeedbackTextFocus?: () => void\n /**\n * Opens the host's contact-support flow for a `contact_support_block` CTA. insights-v2 cannot\n * import the help module (hosts that don't ship it stub the import), so the host supplies it:\n * the experiences Help widget wires `RequestSupport`; pulse wires its own. When absent, the CTA\n * renders disabled (see `isContactSupportCtaDisabled`).\n */\n onContactSupport?: () => void\n}\n\nconst BeatActionsContext = createContext<BeatActions>({})\n\nexport const BeatActionsProvider = ({\n value,\n children,\n}: {\n value: BeatActions\n children: ReactNode\n}) => <BeatActionsContext.Provider value={value}>{children}</BeatActionsContext.Provider>\n\nexport const useBeatActions = () => useContext(BeatActionsContext)\n"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"beatActions.es.js","names":[],"sources":["../../src/insights-v2/beatActions.tsx"],"sourcesContent":["import { createContext, useContext, type ReactNode } from 'react'\n\nimport type { DismissType } from './components/DismissInsightDialog'\nimport type { FeedbackDialogCloseReason } from './components/FeedbackDialog'\n\nexport type InsightMenuAction = 'helpful' | 'not_helpful' | 'hide'\nexport type InsightRating = 'helpful' | 'not_helpful'\n\nexport interface MenuActionHandlers {\n onAction: (action: InsightMenuAction) => void\n onOpen?: () => void\n disabled?: boolean\n}\n\nexport interface UpdateParams {\n beatGuid: string\n}\n\nexport interface FeedbackParams {\n beatGuid: string\n source: InsightRating | 'hide'\n option: string\n detail?: string\n}\n\nexport interface DismissParams {\n beatGuid: string\n type: DismissType\n}\n\n/**\n * A CTA side effect the host must perform because experiences cannot (beat-owned endpoints,\n * spending plan items, third-party SDKs). `name` is agreed between the ctaActions table and\n * the host; see insights-v2/ctaActions/README.md for the list.\n */\nexport interface CtaActionParams {\n beatGuid: string\n name: string\n params?: Record<string, unknown>\n}\n\n/** Host callbacks for a beat card. */\nexport interface BeatActions {\n onMenuAction?: MenuActionHandlers\n onUpdate?: (params: UpdateParams) => void\n onSubmitFeedback?: (params: FeedbackParams) => void\n onDismissInsight?: (params: DismissParams) => void\n onUndoDismiss?: (params: { beatGuid: string }) => void\n onFeedbackDialogClose?: (reason: FeedbackDialogCloseReason) => void\n onFeedbackDialogBack?: () => void\n onFeedbackTextFocus?: () => void\n /**\n * Opens the host's contact-support flow for a `contact_support_block` CTA. insights-v2 cannot\n * import the help module (hosts that don't ship it stub the import), so the host supplies it:\n * the experiences Help widget wires `RequestSupport`; pulse wires its own. When absent, the CTA\n * renders disabled (see `isContactSupportCtaDisabled`).\n */\n onContactSupport?: () => void\n onCtaAction?: (params: CtaActionParams) => Promise<void> | void\n}\n\nconst BeatActionsContext = createContext<BeatActions>({})\n\nexport const BeatActionsProvider = ({\n value,\n children,\n}: {\n value: BeatActions\n children: ReactNode\n}) => <BeatActionsContext.Provider value={value}>{children}</BeatActionsContext.Provider>\n\nexport const useBeatActions = () => useContext(BeatActionsContext)\n"],"mappings":";;AA6DA,IAAM,IAAqB,EAA2B,CAAC,CAAC,GAE3C,IAAA,CAAuB,EAClC,OAAA,GACA,UAAA,EAAA,MAII,gBAAA,EAAC,EAAmB,UAApB;AAAA,EAAoC,OAAA;AAAA,EAAQ,UAAA;AAAsC,CAAA,GAE3E,IAAA,MAAuB,EAAW,CAAkB"}
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import { useAppConfig as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import { useBeatFeedbackFlow as
|
|
19
|
-
import { observer as
|
|
20
|
-
import
|
|
21
|
-
import { P as
|
|
22
|
-
import
|
|
23
|
-
import { ChevronRight as
|
|
24
|
-
import { Fragment as
|
|
25
|
-
import
|
|
26
|
-
import
|
|
27
|
-
var
|
|
1
|
+
import { useAppConfig as E, useGlobalCopyStore as N } from "../../common/context/hooks.es.js";
|
|
2
|
+
import { BeatActionsProvider as R } from "../beatActions.es.js";
|
|
3
|
+
import { isContactSupportCtaDisabled as H } from "../actionBlocks/ContactSupportActionBlock.es.js";
|
|
4
|
+
import { logoFromRef as M } from "./shared/EntityLogo.es.js";
|
|
5
|
+
import { actionBlocksKey as P } from "../mappings/actionBlocksKey.es.js";
|
|
6
|
+
import { blocks as U } from "../mappings/blocks.es.js";
|
|
7
|
+
import j from "./Footer.es.js";
|
|
8
|
+
import z from "./Header.es.js";
|
|
9
|
+
import { FeedbackBar as G } from "./FeedbackBar.es.js";
|
|
10
|
+
import K from "./FeedbackDialog.es.js";
|
|
11
|
+
import { DismissInsightDialog as X } from "./DismissInsightDialog.es.js";
|
|
12
|
+
import { HiddenConfirmationCard as V } from "./HiddenConfirmationCard.es.js";
|
|
13
|
+
import { ErrorCard as W } from "./ErrorCard.es.js";
|
|
14
|
+
import { LoadingCard as Y } from "./LoadingCard.es.js";
|
|
15
|
+
import { ObsolesceBanner as q } from "./ObsolesceBanner.es.js";
|
|
16
|
+
import { ActionBlockLayer as J } from "../actionBlocks/ActionBlockLayer.es.js";
|
|
17
|
+
import { useBeatCtaActions as Q } from "../ctaActions/useCtaAction.es.js";
|
|
18
|
+
import { useBeatFeedbackFlow as Z } from "../hooks/useBeatFeedbackFlow.es.js";
|
|
19
|
+
import { observer as $ } from "mobx-react-lite";
|
|
20
|
+
import b from "@mui/material/Stack";
|
|
21
|
+
import { P as oo, Text as io } from "@mxenabled/mxui";
|
|
22
|
+
import y from "@mui/material/Button";
|
|
23
|
+
import { ChevronRight as eo } from "@mxenabled/mx-icons";
|
|
24
|
+
import { Fragment as to, jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
25
|
+
import ro from "@mui/material/Box";
|
|
26
|
+
import ao from "@mui/material/Card";
|
|
27
|
+
var so = {}, no = {
|
|
28
28
|
position: "absolute",
|
|
29
29
|
top: 0,
|
|
30
30
|
left: 0,
|
|
@@ -33,7 +33,7 @@ var co = {}, mo = {
|
|
|
33
33
|
backgroundColor: "background.default",
|
|
34
34
|
opacity: 0.7,
|
|
35
35
|
zIndex: 1
|
|
36
|
-
},
|
|
36
|
+
}, lo = {
|
|
37
37
|
alignItems: "center",
|
|
38
38
|
alignSelf: "flex-start",
|
|
39
39
|
display: "flex",
|
|
@@ -41,63 +41,65 @@ var co = {}, mo = {
|
|
|
41
41
|
height: 44,
|
|
42
42
|
px: 2,
|
|
43
43
|
textTransform: "none"
|
|
44
|
-
},
|
|
45
|
-
const {
|
|
46
|
-
if (_) return /* @__PURE__ */
|
|
47
|
-
const
|
|
48
|
-
if (!
|
|
49
|
-
const { instance_slot:
|
|
50
|
-
logo:
|
|
51
|
-
text:
|
|
52
|
-
} : void 0), l = (
|
|
53
|
-
l(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
44
|
+
}, Ro = $(({ beat: t, beatActions: s = so, obsolete: c, isLoading: x = !1, isError: _ = !1 }) => {
|
|
45
|
+
const v = N(), { config: S } = E(), o = Z(t, s), { runCta: T, primary: C, secondary: g } = Q(t, s, t.insights_payload?.primary_cta, t.insights_payload?.secondary_cta);
|
|
46
|
+
if (_) return /* @__PURE__ */ i(W, {});
|
|
47
|
+
const e = t.insights_payload;
|
|
48
|
+
if (!e || o.cardState === "dismissed") return null;
|
|
49
|
+
const { instance_slot: B, primary_cta: r, secondary_cta: n, sub_title: O, title: D, widget_type: L, guid: I, dismissed_at: F } = e, { block: A } = B, w = O ?? (e.subtitle ? {
|
|
50
|
+
logo: M(e.logo),
|
|
51
|
+
text: e.subtitle
|
|
52
|
+
} : void 0), l = (f) => H(f, S, s.onContactSupport), h = async (f, u) => {
|
|
53
|
+
if (!l(u.block)) {
|
|
54
|
+
if (u.block === P.CONTACT_SUPPORT_ACTION_BLOCK) {
|
|
55
|
+
s.onContactSupport?.();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
await T(f, u);
|
|
59
|
+
}
|
|
60
|
+
}, k = U[A], d = L === "mini", m = v.insights_feed?.general, p = c?.state === "not_refreshable" && !F && !!m;
|
|
61
|
+
return /* @__PURE__ */ i(R, {
|
|
60
62
|
value: o.wrappedActions,
|
|
61
|
-
children: /* @__PURE__ */
|
|
63
|
+
children: /* @__PURE__ */ a(b, {
|
|
62
64
|
sx: { mb: 16 },
|
|
63
65
|
children: [
|
|
64
|
-
o.cardState === "confirming" ? /* @__PURE__ */
|
|
66
|
+
o.cardState === "confirming" ? /* @__PURE__ */ i(V, {
|
|
65
67
|
onClose: o.collapseConfirmation,
|
|
66
68
|
onLeaveFeedback: o.openHideSurvey,
|
|
67
69
|
onUndo: o.undoDismiss
|
|
68
|
-
}) : /* @__PURE__ */
|
|
69
|
-
...
|
|
70
|
-
copy:
|
|
71
|
-
}), /* @__PURE__ */
|
|
72
|
-
inert:
|
|
73
|
-
sx: { ...
|
|
70
|
+
}) : /* @__PURE__ */ a(to, { children: [c && m && /* @__PURE__ */ i(q, {
|
|
71
|
+
...c,
|
|
72
|
+
copy: m
|
|
73
|
+
}), /* @__PURE__ */ a(ao, {
|
|
74
|
+
inert: p,
|
|
75
|
+
sx: { ...p && {
|
|
74
76
|
position: "relative",
|
|
75
77
|
zIndex: 2,
|
|
76
78
|
pointerEvents: "none"
|
|
77
79
|
} },
|
|
78
80
|
children: [
|
|
79
|
-
|
|
80
|
-
/* @__PURE__ */
|
|
81
|
-
isMini:
|
|
82
|
-
subtitle:
|
|
81
|
+
p && /* @__PURE__ */ i(ro, { sx: no }),
|
|
82
|
+
/* @__PURE__ */ i(z, {
|
|
83
|
+
isMini: d,
|
|
84
|
+
subtitle: w,
|
|
83
85
|
title: D ?? ""
|
|
84
86
|
}),
|
|
85
|
-
|
|
86
|
-
beatGuid:
|
|
87
|
-
payload:
|
|
87
|
+
x ? /* @__PURE__ */ i(Y, {}) : k && /* @__PURE__ */ i(k, {
|
|
88
|
+
beatGuid: I,
|
|
89
|
+
payload: e
|
|
88
90
|
}),
|
|
89
|
-
/* @__PURE__ */
|
|
91
|
+
/* @__PURE__ */ a(b, {
|
|
90
92
|
sx: {
|
|
91
93
|
gap: 6,
|
|
92
94
|
pb: 16,
|
|
93
95
|
pt: 12,
|
|
94
96
|
px: 16
|
|
95
97
|
},
|
|
96
|
-
children: [/* @__PURE__ */
|
|
97
|
-
dangerouslySetInnerHTML: { __html:
|
|
98
|
+
children: [/* @__PURE__ */ i(oo, {
|
|
99
|
+
dangerouslySetInnerHTML: { __html: e.description.html_text },
|
|
98
100
|
variant: "subtitle2"
|
|
99
|
-
}), t?.in_description_cta && /* @__PURE__ */
|
|
100
|
-
endIcon: /* @__PURE__ */
|
|
101
|
+
}), t?.in_description_cta && /* @__PURE__ */ i(y, {
|
|
102
|
+
endIcon: /* @__PURE__ */ i(eo, {}),
|
|
101
103
|
onClick: () => {
|
|
102
104
|
},
|
|
103
105
|
sx: {
|
|
@@ -108,43 +110,45 @@ var co = {}, mo = {
|
|
|
108
110
|
children: t.in_description_cta
|
|
109
111
|
})]
|
|
110
112
|
}),
|
|
111
|
-
r?.label && /* @__PURE__ */
|
|
113
|
+
r?.label && /* @__PURE__ */ a(b, {
|
|
112
114
|
sx: {
|
|
113
115
|
gap: 8,
|
|
114
116
|
pb: 16,
|
|
115
117
|
px: 16
|
|
116
118
|
},
|
|
117
|
-
children: [
|
|
119
|
+
children: [d ? /* @__PURE__ */ i(io, {
|
|
118
120
|
color: "primary.main",
|
|
119
|
-
sx:
|
|
121
|
+
sx: lo,
|
|
120
122
|
variant: "button",
|
|
121
123
|
children: r.label
|
|
122
|
-
}) : /* @__PURE__ */
|
|
123
|
-
"aria-disabled": l(r.block),
|
|
124
|
-
|
|
124
|
+
}) : /* @__PURE__ */ i(y, {
|
|
125
|
+
"aria-disabled": l(r.block) || C.disabled,
|
|
126
|
+
disabled: C.disabled,
|
|
127
|
+
onClick: () => h("primary", r),
|
|
125
128
|
sx: { ...l(r.block) && { color: "text.disabled" } },
|
|
126
129
|
variant: "outlined",
|
|
127
130
|
children: r.label
|
|
128
|
-
}), !
|
|
129
|
-
"aria-disabled": l(
|
|
131
|
+
}), !d && n?.label && /* @__PURE__ */ i(y, {
|
|
132
|
+
"aria-disabled": l(n.block) || g.disabled,
|
|
130
133
|
color: "secondary",
|
|
131
|
-
|
|
132
|
-
|
|
134
|
+
disabled: g.disabled,
|
|
135
|
+
onClick: () => h("secondary", n),
|
|
136
|
+
children: n.label
|
|
133
137
|
})]
|
|
134
138
|
}),
|
|
135
|
-
/* @__PURE__ */
|
|
139
|
+
/* @__PURE__ */ i(G, {
|
|
136
140
|
onTellUsMore: o.openRatingSurvey,
|
|
137
141
|
show: o.isFeedbackBarShown
|
|
138
142
|
})
|
|
139
143
|
]
|
|
140
144
|
})] }),
|
|
141
|
-
/* @__PURE__ */
|
|
142
|
-
/* @__PURE__ */
|
|
145
|
+
/* @__PURE__ */ i(J, { beat: t }),
|
|
146
|
+
/* @__PURE__ */ i(X, {
|
|
143
147
|
isOpen: o.isDismissOpen,
|
|
144
148
|
onClose: o.closeDismissDialog,
|
|
145
149
|
onDismiss: o.confirmDismiss
|
|
146
150
|
}),
|
|
147
|
-
o.isSurveyOpen && /* @__PURE__ */
|
|
151
|
+
o.isSurveyOpen && /* @__PURE__ */ i(K, {
|
|
148
152
|
characterLimitLabel: o.survey.characterLimitLabel,
|
|
149
153
|
closeAriaLabel: o.survey.closeAriaLabel,
|
|
150
154
|
isOpen: !0,
|
|
@@ -157,13 +161,13 @@ var co = {}, mo = {
|
|
|
157
161
|
secondaryText: o.survey.backText,
|
|
158
162
|
title: o.survey.title
|
|
159
163
|
}),
|
|
160
|
-
o.cardState === "visible" &&
|
|
164
|
+
o.cardState === "visible" && e.footer && /* @__PURE__ */ i(j, { footer: e.footer })
|
|
161
165
|
]
|
|
162
166
|
})
|
|
163
167
|
});
|
|
164
168
|
});
|
|
165
169
|
export {
|
|
166
|
-
|
|
170
|
+
Ro as default
|
|
167
171
|
};
|
|
168
172
|
|
|
169
173
|
//# sourceMappingURL=BaseLayout.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseLayout.es.js","names":[],"sources":["../../../src/insights-v2/components/BaseLayout.tsx"],"sourcesContent":["import { observer } from 'mobx-react-lite'\n\nimport Box from '@mui/material/Box'\nimport Button from '@mui/material/Button'\nimport Card from '@mui/material/Card'\nimport Stack from '@mui/material/Stack'\n\nimport { ChevronRight } from '@mxenabled/mx-icons'\nimport { P, Text } from '@mxenabled/mxui'\n\nimport { blocks, hasDrawerBlock } from '../mappings/blocks'\nimport { actionBlocksKey } from '../mappings/actionBlocksKey'\nimport { isContactSupportCtaDisabled } from '../actionBlocks/ContactSupportActionBlock'\nimport { logoFromRef } from './shared/EntityLogo'\n\nimport Footer from './Footer'\nimport Header from './Header'\nimport FeedbackBar from './FeedbackBar'\nimport FeedbackDialog from './FeedbackDialog'\nimport DismissInsightDialog from './DismissInsightDialog'\nimport HiddenConfirmationCard from './HiddenConfirmationCard'\nimport ErrorCard from './ErrorCard'\nimport LoadingCard from './LoadingCard'\nimport { ObsolesceBanner, type ObsolesceBannerState } from './ObsolesceBanner'\nimport { useAppConfig, useGlobalCopyStore, useInsightsV2Store } from '../../common'\nimport { sendBeatCta } from '../../common/utils/PostMessage'\nimport type { Beat } from '../../core'\nimport { BeatActionsProvider, type BeatActions } from '../beatActions'\nimport { ActionBlockLayer } from '../actionBlocks/ActionBlockLayer'\nimport { useBeatFeedbackFlow } from '../hooks/useBeatFeedbackFlow'\n\nexport interface ObsoleteState {\n state: ObsolesceBannerState\n onRefresh: () => void\n onDismiss: () => void\n}\n\ninterface BaseLayoutProps {\n beat: Beat\n beatActions?: BeatActions\n obsolete?: ObsoleteState\n /** Swap only the block slot for a LoadingCard (e.g. while a sampled beat loads). */\n isLoading?: boolean\n /** Replace the entire card with an ErrorCard (e.g. when the sample fails to load). */\n isError?: boolean\n}\n\nconst NO_BEAT_ACTIONS: BeatActions = {}\n\nconst OBSOLETE_OVERLAY_SX = {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n backgroundColor: 'background.default',\n opacity: 0.7,\n zIndex: 1,\n} as const\n\n// Figma (Mini | Large Transaction): a left-aligned link under the description. The 2px padding plus\n// the CTA row's 16 lines the label up with the description's 18. The label is not a Button, so it\n// carries the theme's MuiButton look itself: semi-bold, no uppercase (typography.button uppercases),\n// and the medium Button's 44px height with the text centred.\nconst MINI_CTA_SX = {\n alignItems: 'center',\n alignSelf: 'flex-start',\n display: 'flex',\n fontWeight: 600,\n height: 44,\n px: 2,\n textTransform: 'none',\n} as const\n\nconst BaseLayout = observer(\n ({\n beat,\n beatActions = NO_BEAT_ACTIONS,\n obsolete,\n isLoading = false,\n isError = false,\n }: BaseLayoutProps) => {\n const { openCtaDrawer } = useInsightsV2Store()\n const copy = useGlobalCopyStore()\n const { is_mobile_webview, clientConfig, config } = useAppConfig()\n const flow = useBeatFeedbackFlow(beat, beatActions)\n\n // Error replaces the entire card; loading only swaps the block slot (below).\n if (isError) return <ErrorCard />\n\n const insights_payload = beat.insights_payload\n\n if (!insights_payload) return null\n if (flow.cardState === 'dismissed') return null\n\n const {\n instance_slot,\n primary_cta,\n secondary_cta,\n sub_title,\n title,\n widget_type,\n guid,\n user_guid,\n dismissed_at,\n } = insights_payload\n const { block } = instance_slot\n\n // V1 sends `sub_title: { text, logo }`. The V2 envelope flattens it to a `subtitle` string\n // with the logo promoted to a payload-level `LogoRef` (an entity guid or a status icon), so\n // rebuild the shape `Header`/`SubHeader` already render. `sub_title` wins when a beat sends both.\n const subtitle =\n sub_title ??\n (insights_payload.subtitle\n ? {\n logo: logoFromRef(insights_payload.logo),\n text: insights_payload.subtitle,\n }\n : undefined)\n\n // A CTA with a real drilldown `block` opens a drawer; otherwise it notifies\n // the host app via a beat/cta post message (the \"Make a Transfer\" CTA on the\n // Save an extra $100 beat). Mirrors Pulse's SaveAnExtra100Dollars beat.\n //\n // `contact_support_block` is the exception: it is the help module's flow, which insights-v2\n // cannot import (hosts that don't ship the Help widget stub the import), so the host injects it\n // as `beatActions.onContactSupport` and the CTA calls it directly — never a drawer. Without a\n // handler, or with `enable_support_requests` off, the CTA renders disabled and does nothing.\n const isCtaDisabled = (ctaBlock: string | null | undefined) =>\n isContactSupportCtaDisabled(ctaBlock, config, beatActions.onContactSupport)\n\n const handleCtaClick = (\n ctaBlock: string | null | undefined,\n source: 'primaryCta' | 'secondaryCta',\n ) => {\n if (isCtaDisabled(ctaBlock)) return\n\n if (ctaBlock === actionBlocksKey.CONTACT_SUPPORT_ACTION_BLOCK) {\n beatActions.onContactSupport?.()\n } else if (hasDrawerBlock(ctaBlock)) {\n openCtaDrawer(guid, source)\n } else {\n sendBeatCta(beat, {\n isMobileWebview: is_mobile_webview,\n webviewScheme: clientConfig?.master?.ui_message_webview_url_scheme,\n userGuid: user_guid,\n })\n }\n }\n\n const Block = blocks[block as keyof typeof blocks]\n\n const isMini = widget_type === 'mini'\n const obsoleteCopy = copy.insights_feed?.general\n const isObsoleteDimmed =\n obsolete?.state === 'not_refreshable' && !dismissed_at && !!obsoleteCopy\n\n return (\n <BeatActionsProvider value={flow.wrappedActions}>\n <Stack sx={{ mb: 16 }}>\n {flow.cardState === 'confirming' ? (\n <HiddenConfirmationCard\n onClose={flow.collapseConfirmation}\n onLeaveFeedback={flow.openHideSurvey}\n onUndo={flow.undoDismiss}\n />\n ) : (\n <>\n {obsolete && obsoleteCopy && <ObsolesceBanner {...obsolete} copy={obsoleteCopy} />}\n <Card\n inert={isObsoleteDimmed}\n sx={{\n ...(isObsoleteDimmed && {\n position: 'relative',\n zIndex: 2,\n pointerEvents: 'none',\n }),\n }}\n >\n {isObsoleteDimmed && <Box sx={OBSOLETE_OVERLAY_SX} />}\n <Header isMini={isMini} subtitle={subtitle} title={title ?? ''} />\n {isLoading ? (\n <LoadingCard />\n ) : (\n Block && <Block beatGuid={guid} payload={insights_payload} />\n )}\n\n <Stack sx={{ gap: 6, pb: 16, pt: 12, px: 16 }}>\n <P\n dangerouslySetInnerHTML={{\n __html: insights_payload.description.html_text,\n }}\n variant=\"subtitle2\"\n />\n {/* TODO: Migrate to insights_payload.in_description_cta once backend provides it */}\n {beat?.in_description_cta && (\n <Button\n endIcon={<ChevronRight />}\n onClick={() => {}}\n sx={{ height: 24, p: 4, width: 'max-content' }}\n >\n {beat.in_description_cta}\n </Button>\n )}\n </Stack>\n\n {primary_cta?.label && (\n <Stack sx={{ gap: 8, pb: 16, px: 16 }}>\n {isMini ? (\n // Mini is a tap target, as in V1: the card, not this label, is the control. The label\n // is deliberately not a button, so a tap on it reaches the host's card handler (Pulse\n // posts `carousel/cta`, the same redirect a V1 mini card sends) instead of opening\n // the action drawer the full card's CTA opens.\n <Text color=\"primary.main\" sx={MINI_CTA_SX} variant=\"button\">\n {primary_cta.label}\n </Text>\n ) : (\n <Button\n aria-disabled={isCtaDisabled(primary_cta.block)}\n onClick={() => handleCtaClick(primary_cta.block, 'primaryCta')}\n sx={{\n ...(isCtaDisabled(primary_cta.block) && { color: 'text.disabled' }),\n }}\n variant=\"outlined\"\n >\n {primary_cta.label}\n </Button>\n )}\n {/* Mini has room for one CTA. */}\n {!isMini && secondary_cta?.label && (\n <Button\n aria-disabled={isCtaDisabled(secondary_cta.block)}\n color=\"secondary\"\n onClick={() => handleCtaClick(secondary_cta.block, 'secondaryCta')}\n >\n {secondary_cta.label}\n </Button>\n )}\n </Stack>\n )}\n\n <FeedbackBar onTellUsMore={flow.openRatingSurvey} show={flow.isFeedbackBarShown} />\n </Card>\n </>\n )}\n\n <ActionBlockLayer beat={beat} />\n\n <DismissInsightDialog\n isOpen={flow.isDismissOpen}\n onClose={flow.closeDismissDialog}\n onDismiss={flow.confirmDismiss}\n />\n\n {flow.isSurveyOpen && (\n <FeedbackDialog\n characterLimitLabel={flow.survey.characterLimitLabel}\n closeAriaLabel={flow.survey.closeAriaLabel}\n isOpen={true}\n onBackClick={flow.feedbackDialogCallbacks.onBackClick}\n onClose={flow.closeSurvey}\n onSubmit={flow.submitSurvey}\n onTextInputFocus={flow.feedbackDialogCallbacks.onTextInputFocus}\n options={flow.survey.options}\n primaryText={flow.survey.submitText}\n secondaryText={flow.survey.backText}\n title={flow.survey.title}\n />\n )}\n\n {flow.cardState === 'visible' && insights_payload.footer && (\n <Footer footer={insights_payload.footer} />\n )}\n </Stack>\n </BeatActionsProvider>\n )\n },\n)\n\nexport default BaseLayout\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BaseLayout.es.js","names":[],"sources":["../../../src/insights-v2/components/BaseLayout.tsx"],"sourcesContent":["import { observer } from 'mobx-react-lite'\n\nimport Box from '@mui/material/Box'\nimport Button from '@mui/material/Button'\nimport Card from '@mui/material/Card'\nimport Stack from '@mui/material/Stack'\n\nimport { ChevronRight } from '@mxenabled/mx-icons'\nimport { P, Text } from '@mxenabled/mxui'\n\nimport { blocks } from '../mappings/blocks'\nimport { actionBlocksKey } from '../mappings/actionBlocksKey'\nimport { isContactSupportCtaDisabled } from '../actionBlocks/ContactSupportActionBlock'\nimport { logoFromRef } from './shared/EntityLogo'\n\nimport Footer from './Footer'\nimport Header from './Header'\nimport FeedbackBar from './FeedbackBar'\nimport FeedbackDialog from './FeedbackDialog'\nimport DismissInsightDialog from './DismissInsightDialog'\nimport HiddenConfirmationCard from './HiddenConfirmationCard'\nimport ErrorCard from './ErrorCard'\nimport LoadingCard from './LoadingCard'\nimport { ObsolesceBanner, type ObsolesceBannerState } from './ObsolesceBanner'\nimport { useAppConfig, useGlobalCopyStore } from '../../common'\nimport type { Beat, PrimaryCTA, SecondaryCTA } from '../../core'\nimport { BeatActionsProvider, type BeatActions } from '../beatActions'\nimport { ActionBlockLayer } from '../actionBlocks/ActionBlockLayer'\nimport { useBeatCtaActions } from '../ctaActions'\nimport { useBeatFeedbackFlow } from '../hooks/useBeatFeedbackFlow'\n\nexport interface ObsoleteState {\n state: ObsolesceBannerState\n onRefresh: () => void\n onDismiss: () => void\n}\n\ninterface BaseLayoutProps {\n beat: Beat\n beatActions?: BeatActions\n obsolete?: ObsoleteState\n /** Swap only the block slot for a LoadingCard (e.g. while a sampled beat loads). */\n isLoading?: boolean\n /** Replace the entire card with an ErrorCard (e.g. when the sample fails to load). */\n isError?: boolean\n}\n\nconst NO_BEAT_ACTIONS: BeatActions = {}\n\nconst OBSOLETE_OVERLAY_SX = {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n backgroundColor: 'background.default',\n opacity: 0.7,\n zIndex: 1,\n} as const\n\n// Figma (Mini | Large Transaction): a left-aligned link under the description. The 2px padding plus\n// the CTA row's 16 lines the label up with the description's 18. The label is not a Button, so it\n// carries the theme's MuiButton look itself: semi-bold, no uppercase (typography.button uppercases),\n// and the medium Button's 44px height with the text centred.\nconst MINI_CTA_SX = {\n alignItems: 'center',\n alignSelf: 'flex-start',\n display: 'flex',\n fontWeight: 600,\n height: 44,\n px: 2,\n textTransform: 'none',\n} as const\n\nconst BaseLayout = observer(\n ({\n beat,\n beatActions = NO_BEAT_ACTIONS,\n obsolete,\n isLoading = false,\n isError = false,\n }: BaseLayoutProps) => {\n const copy = useGlobalCopyStore()\n const { config } = useAppConfig()\n const flow = useBeatFeedbackFlow(beat, beatActions)\n const {\n runCta: handleCtaClick,\n primary: primaryCtaState,\n secondary: secondaryCtaState,\n } = useBeatCtaActions(\n beat,\n beatActions,\n beat.insights_payload?.primary_cta,\n beat.insights_payload?.secondary_cta,\n )\n\n // Error replaces the entire card; loading only swaps the block slot (below).\n if (isError) return <ErrorCard />\n\n const insights_payload = beat.insights_payload\n\n if (!insights_payload) return null\n if (flow.cardState === 'dismissed') return null\n\n const {\n instance_slot,\n primary_cta,\n secondary_cta,\n sub_title,\n title,\n widget_type,\n guid,\n dismissed_at,\n } = insights_payload\n const { block } = instance_slot\n\n // V1 sends `sub_title: { text, logo }`. The V2 envelope flattens it to a `subtitle` string\n // with the logo promoted to a payload-level `LogoRef` (an entity guid or a status icon), so\n // rebuild the shape `Header`/`SubHeader` already render. `sub_title` wins when a beat sends both.\n const subtitle =\n sub_title ??\n (insights_payload.subtitle\n ? {\n logo: logoFromRef(insights_payload.logo),\n text: insights_payload.subtitle,\n }\n : undefined)\n\n // CTA presses go through the ctaActions runner (../ctaActions): a backend `action_key` runs\n // its step, otherwise a `block` opens its drawer, else the CTA posts its message.\n // `contact_support_block` bypasses the runner: the help flow is host-supplied via\n // `beatActions.onContactSupport`, and the CTA is disabled without it.\n const isCtaDisabled = (ctaBlock: string | null | undefined) =>\n isContactSupportCtaDisabled(ctaBlock, config, beatActions.onContactSupport)\n\n const onCtaClick = async (slot: 'primary' | 'secondary', cta: PrimaryCTA | SecondaryCTA) => {\n if (isCtaDisabled(cta.block)) return\n\n if (cta.block === actionBlocksKey.CONTACT_SUPPORT_ACTION_BLOCK) {\n beatActions.onContactSupport?.()\n return\n }\n\n await handleCtaClick(slot, cta)\n }\n\n const Block = blocks[block as keyof typeof blocks]\n\n const isMini = widget_type === 'mini'\n const obsoleteCopy = copy.insights_feed?.general\n const isObsoleteDimmed =\n obsolete?.state === 'not_refreshable' && !dismissed_at && !!obsoleteCopy\n\n return (\n <BeatActionsProvider value={flow.wrappedActions}>\n <Stack sx={{ mb: 16 }}>\n {flow.cardState === 'confirming' ? (\n <HiddenConfirmationCard\n onClose={flow.collapseConfirmation}\n onLeaveFeedback={flow.openHideSurvey}\n onUndo={flow.undoDismiss}\n />\n ) : (\n <>\n {obsolete && obsoleteCopy && <ObsolesceBanner {...obsolete} copy={obsoleteCopy} />}\n <Card\n inert={isObsoleteDimmed}\n sx={{\n ...(isObsoleteDimmed && {\n position: 'relative',\n zIndex: 2,\n pointerEvents: 'none',\n }),\n }}\n >\n {isObsoleteDimmed && <Box sx={OBSOLETE_OVERLAY_SX} />}\n <Header isMini={isMini} subtitle={subtitle} title={title ?? ''} />\n {isLoading ? (\n <LoadingCard />\n ) : (\n Block && <Block beatGuid={guid} payload={insights_payload} />\n )}\n\n <Stack sx={{ gap: 6, pb: 16, pt: 12, px: 16 }}>\n <P\n dangerouslySetInnerHTML={{\n __html: insights_payload.description.html_text,\n }}\n variant=\"subtitle2\"\n />\n {/* TODO: Migrate to insights_payload.in_description_cta once backend provides it */}\n {beat?.in_description_cta && (\n <Button\n endIcon={<ChevronRight />}\n onClick={() => {}}\n sx={{ height: 24, p: 4, width: 'max-content' }}\n >\n {beat.in_description_cta}\n </Button>\n )}\n </Stack>\n\n {primary_cta?.label && (\n <Stack sx={{ gap: 8, pb: 16, px: 16 }}>\n {isMini ? (\n // Mini is a tap target, as in V1: the card, not this label, is the control. The label\n // is deliberately not a button, so a tap on it reaches the host's card handler (Pulse\n // posts `carousel/cta`, the same redirect a V1 mini card sends) instead of opening\n // the action drawer the full card's CTA opens.\n <Text color=\"primary.main\" sx={MINI_CTA_SX} variant=\"button\">\n {primary_cta.label}\n </Text>\n ) : (\n <Button\n aria-disabled={isCtaDisabled(primary_cta.block) || primaryCtaState.disabled}\n disabled={primaryCtaState.disabled}\n onClick={() => onCtaClick('primary', primary_cta)}\n sx={{\n ...(isCtaDisabled(primary_cta.block) && { color: 'text.disabled' }),\n }}\n variant=\"outlined\"\n >\n {primary_cta.label}\n </Button>\n )}\n {/* Mini has room for one CTA. */}\n {!isMini && secondary_cta?.label && (\n <Button\n aria-disabled={\n isCtaDisabled(secondary_cta.block) || secondaryCtaState.disabled\n }\n color=\"secondary\"\n disabled={secondaryCtaState.disabled}\n onClick={() => onCtaClick('secondary', secondary_cta)}\n >\n {secondary_cta.label}\n </Button>\n )}\n </Stack>\n )}\n\n <FeedbackBar onTellUsMore={flow.openRatingSurvey} show={flow.isFeedbackBarShown} />\n </Card>\n </>\n )}\n\n <ActionBlockLayer beat={beat} />\n\n <DismissInsightDialog\n isOpen={flow.isDismissOpen}\n onClose={flow.closeDismissDialog}\n onDismiss={flow.confirmDismiss}\n />\n\n {flow.isSurveyOpen && (\n <FeedbackDialog\n characterLimitLabel={flow.survey.characterLimitLabel}\n closeAriaLabel={flow.survey.closeAriaLabel}\n isOpen={true}\n onBackClick={flow.feedbackDialogCallbacks.onBackClick}\n onClose={flow.closeSurvey}\n onSubmit={flow.submitSurvey}\n onTextInputFocus={flow.feedbackDialogCallbacks.onTextInputFocus}\n options={flow.survey.options}\n primaryText={flow.survey.submitText}\n secondaryText={flow.survey.backText}\n title={flow.survey.title}\n />\n )}\n\n {flow.cardState === 'visible' && insights_payload.footer && (\n <Footer footer={insights_payload.footer} />\n )}\n </Stack>\n </BeatActionsProvider>\n )\n },\n)\n\nexport default BaseLayout\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,IAAM,KAA+B,CAAC,GAEhC,KAAsB;AAAA,EAC1B,UAAU;AAAA,EACV,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,QAAQ;AACV,GAMM,KAAc;AAAA,EAClB,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,IAAI;AAAA,EACJ,eAAe;AACjB,GAEM,KAAa,EAAA,CAChB,EACC,MAAA,GACA,aAAA,IAAc,IACd,UAAA,GACA,WAAA,IAAY,IACZ,SAAA,IAAU,GAAA,MACW;AACrB,QAAM,IAAO,EAAmB,GAC1B,EAAE,QAAA,EAAA,IAAW,EAAa,GAC1B,IAAO,EAAoB,GAAM,CAAW,GAC5C,EACJ,QAAQ,GACR,SAAS,GACT,WAAW,EAAA,IACT,EACF,GACA,GACA,EAAK,kBAAkB,aACvB,EAAK,kBAAkB,aACzB;AAGA,MAAI,EAAS,QAAO,gBAAA,EAAC,GAAD,CAAY,CAAA;AAEhC,QAAM,IAAmB,EAAK;AAG9B,MADI,CAAC,KACD,EAAK,cAAc,YAAa,QAAO;AAE3C,QAAM,EACJ,eAAA,GACA,aAAA,GACA,eAAA,GACA,WAAA,GACA,OAAA,GACA,aAAA,GACA,MAAA,GACA,cAAA,EAAA,IACE,GACE,EAAE,OAAA,EAAA,IAAU,GAKZ,IACJ,MACC,EAAiB,WACd;AAAA,IACE,MAAM,EAAY,EAAiB,IAAI;AAAA,IACvC,MAAM,EAAiB;AAAA,EACzB,IACA,SAMA,IAAA,CAAiB,MACrB,EAA4B,GAAU,GAAQ,EAAY,gBAAgB,GAEtE,IAAa,OAAO,GAA+B,MAAmC;AAC1F,QAAI,CAAA,EAAc,EAAI,KAAK,GAE3B;AAAA,UAAI,EAAI,UAAU,EAAgB,8BAA8B;AAC9D,QAAA,EAAY,mBAAmB;AAC/B;AAAA,MACF;AAEA,YAAM,EAAe,GAAM,CAAG;AAAA;AAAA,EAChC,GAEM,IAAQ,EAAO,CAAA,GAEf,IAAS,MAAgB,QACzB,IAAe,EAAK,eAAe,SACnC,IACJ,GAAU,UAAU,qBAAqB,CAAC,KAAgB,CAAC,CAAC;AAE9D,SACE,gBAAA,EAAC,GAAD;AAAA,IAAqB,OAAO,EAAK;AAAA,IAC/B,UAAA,gBAAA,EAAC,GAAD;AAAA,MAAO,IAAI,EAAE,IAAI,GAAG;AAAA,MAApB,UAAA;AAAA,QACG,EAAK,cAAc,eAClB,gBAAA,EAAC,GAAD;AAAA,UACE,SAAS,EAAK;AAAA,UACd,iBAAiB,EAAK;AAAA,UACtB,QAAQ,EAAK;AAAA,QACd,CAAA,IAED,gBAAA,EAAA,IAAA,EAAA,UAAA,CACG,KAAY,KAAgB,gBAAA,EAAC,GAAD;AAAA,UAAiB,GAAI;AAAA,UAAU,MAAM;AAAA,QAAe,CAAA,GACjF,gBAAA,EAAC,IAAD;AAAA,UACE,OAAO;AAAA,UACP,IAAI,EACF,GAAI,KAAoB;AAAA,YACtB,UAAU;AAAA,YACV,QAAQ;AAAA,YACR,eAAe;AAAA,UACjB,EACF;AAAA,UARF,UAAA;AAAA,YAUG,KAAoB,gBAAA,EAAC,IAAD,EAAK,IAAI,GAAsB,CAAA;AAAA,YACpD,gBAAA,EAAC,GAAD;AAAA,cAAgB,QAAA;AAAA,cAAkB,UAAA;AAAA,cAAU,OAAO,KAAS;AAAA,YAAK,CAAA;AAAA,YAChE,IACC,gBAAA,EAAC,GAAD,CAAc,CAAA,IAEd,KAAS,gBAAA,EAAC,GAAD;AAAA,cAAO,UAAU;AAAA,cAAM,SAAS;AAAA,YAAmB,CAAA;AAAA,YAG9D,gBAAA,EAAC,GAAD;AAAA,cAAO,IAAI;AAAA,gBAAE,KAAK;AAAA,gBAAG,IAAI;AAAA,gBAAI,IAAI;AAAA,gBAAI,IAAI;AAAA,cAAG;AAAA,cAA5C,UAAA,CACE,gBAAA,EAAC,IAAD;AAAA,gBACE,yBAAyB,EACvB,QAAQ,EAAiB,YAAY,UACvC;AAAA,gBACA,SAAQ;AAAA,cACT,CAAA,GAEA,GAAM,sBACL,gBAAA,EAAC,GAAD;AAAA,gBACE,SAAS,gBAAA,EAAC,IAAD,CAAe,CAAA;AAAA,gBACxB,SAAA,MAAe;AAAA,gBAAC;AAAA,gBAChB,IAAI;AAAA,kBAAE,QAAQ;AAAA,kBAAI,GAAG;AAAA,kBAAG,OAAO;AAAA,gBAAc;AAAA,gBAE5C,UAAA,EAAK;AAAA,cACA,CAAA,CAEL;AAAA;YAEN,GAAa,SACZ,gBAAA,EAAC,GAAD;AAAA,cAAO,IAAI;AAAA,gBAAE,KAAK;AAAA,gBAAG,IAAI;AAAA,gBAAI,IAAI;AAAA,cAAG;AAAA,cAApC,UAAA,CACG,IAKC,gBAAA,EAAC,IAAD;AAAA,gBAAM,OAAM;AAAA,gBAAe,IAAI;AAAA,gBAAa,SAAQ;AAAA,gBACjD,UAAA,EAAY;AAAA,cACT,CAAA,IAEN,gBAAA,EAAC,GAAD;AAAA,gBACE,iBAAe,EAAc,EAAY,KAAK,KAAK,EAAgB;AAAA,gBACnE,UAAU,EAAgB;AAAA,gBAC1B,SAAA,MAAe,EAAW,WAAW,CAAW;AAAA,gBAChD,IAAI,EACF,GAAI,EAAc,EAAY,KAAK,KAAK,EAAE,OAAO,gBAAgB,EACnE;AAAA,gBACA,SAAQ;AAAA,gBAEP,UAAA,EAAY;AAAA,cACP,CAAA,GAGT,CAAC,KAAU,GAAe,SACzB,gBAAA,EAAC,GAAD;AAAA,gBACE,iBACE,EAAc,EAAc,KAAK,KAAK,EAAkB;AAAA,gBAE1D,OAAM;AAAA,gBACN,UAAU,EAAkB;AAAA,gBAC5B,SAAA,MAAe,EAAW,aAAa,CAAa;AAAA,gBAEnD,UAAA,EAAc;AAAA,cACT,CAAA,CAEL;AAAA;YAGT,gBAAA,EAAC,GAAD;AAAA,cAAa,cAAc,EAAK;AAAA,cAAkB,MAAM,EAAK;AAAA,YAAqB,CAAA;AAAA,UAC9E;AAAA,QACN,CAAA,CAAA,EAAA,CAAA;AAAA,QAGJ,gBAAA,EAAC,GAAD,EAAwB,MAAA,EAAO,CAAA;AAAA,QAE/B,gBAAA,EAAC,GAAD;AAAA,UACE,QAAQ,EAAK;AAAA,UACb,SAAS,EAAK;AAAA,UACd,WAAW,EAAK;AAAA,QACjB,CAAA;AAAA,QAEA,EAAK,gBACJ,gBAAA,EAAC,GAAD;AAAA,UACE,qBAAqB,EAAK,OAAO;AAAA,UACjC,gBAAgB,EAAK,OAAO;AAAA,UAC5B,QAAQ;AAAA,UACR,aAAa,EAAK,wBAAwB;AAAA,UAC1C,SAAS,EAAK;AAAA,UACd,UAAU,EAAK;AAAA,UACf,kBAAkB,EAAK,wBAAwB;AAAA,UAC/C,SAAS,EAAK,OAAO;AAAA,UACrB,aAAa,EAAK,OAAO;AAAA,UACzB,eAAe,EAAK,OAAO;AAAA,UAC3B,OAAO,EAAK,OAAO;AAAA,QACpB,CAAA;AAAA,QAGF,EAAK,cAAc,aAAa,EAAiB,UAChD,gBAAA,EAAC,GAAD,EAAQ,QAAQ,EAAiB,OAAS,CAAA;AAAA,MAEvC;AAAA;EACY,CAAA;AAEzB,CACF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CtaStep } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Steps keyed by the backend-named `cta.action_key` (ditto `*_cta_action`, via tupac). No key or
|
|
4
|
+
* an unknown key = default: open the CTA's block drawer, else post its message. A new key is
|
|
5
|
+
* registered in ditto and here in the same change; most CTAs need none. See README.md.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ctaActions: Record<string, CtaStep>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ctaConfig.es.js","names":[],"sources":["../../../src/insights-v2/ctaActions/ctaConfig.ts"],"sourcesContent":["import { HOST_ACTIONS } from './hostActions'\nimport type { CtaStep } from './types'\n\n/**\n * Steps keyed by the backend-named `cta.action_key` (ditto `*_cta_action`, via tupac). No key or\n * an unknown key = default: open the CTA's block drawer, else post its message. A new key is\n * registered in ditto and here in the same change; most CTAs need none. See README.md.\n */\nexport const ctaActions: Record<string, CtaStep> = {\n /** ConnectDiscoveredAccounts \"I don't have any\": dismiss through the host, then stop. */\n dismiss_beat: {\n run: 'delegateToHost',\n params: { hostAction: HOST_ACTIONS.dismissBeat },\n },\n}\n"],"mappings":";AAQA,IAAa,IAAsC,EAEjD,cAAc;AAAA,EACZ,KAAK;AAAA,EACL,QAAQ,EAAE,YAAY,EAAa,YAAY;AACjD,EACF"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { CtaContext } from './types';
|
|
2
|
+
export declare const ctaHandlers: {
|
|
3
|
+
/** `PUT user_insight_profile` (designate emergency savings, thresholds, safety net). */
|
|
4
|
+
updateUserInsightProfile: (ctx: CtaContext) => Promise<void>;
|
|
5
|
+
/** `PUT offers/:guid` flagging a marketing offer as clicked. */
|
|
6
|
+
markOfferClicked: ({ beat, stores }: CtaContext) => Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* `PUT repeating_transactions/:guid` writing `user_response`. Resolves the repeating
|
|
9
|
+
* transaction from `params.repeatingTransactionGuid`, else the beat's primary transaction.
|
|
10
|
+
*/
|
|
11
|
+
updateRepeatingTransactionResponse: (ctx: CtaContext) => Promise<void>;
|
|
12
|
+
/** `PUT accounts/:guid` merging `params.fields`; `params.accountGuid` picks the account, else the beat's primary. */
|
|
13
|
+
updateAccountField: (ctx: CtaContext) => Promise<void>;
|
|
14
|
+
/** `PUT notification_profiles/:guid` setting `threshold` on the named profile. */
|
|
15
|
+
updateNotificationProfileThreshold: (ctx: CtaContext) => Promise<void>;
|
|
16
|
+
/** `POST budgets` for `params.categoryGuid` with `params.amount` (+ optional parentGuid). */
|
|
17
|
+
createBudget: (ctx: CtaContext) => Promise<void>;
|
|
18
|
+
/** `PUT budgets/:guid` setting `amount`. */
|
|
19
|
+
updateBudget: (ctx: CtaContext) => Promise<void>;
|
|
20
|
+
/** `DELETE budgets/:guid`. */
|
|
21
|
+
deleteBudget: (ctx: CtaContext) => Promise<void>;
|
|
22
|
+
/** `POST merchant_budgets`. */
|
|
23
|
+
createMerchantBudget: (ctx: CtaContext) => Promise<void>;
|
|
24
|
+
/** `PUT merchant_budgets/:guid` setting `amount`. */
|
|
25
|
+
updateMerchantBudget: (ctx: CtaContext) => Promise<void>;
|
|
26
|
+
/** `DELETE merchant_budgets/:guid`. */
|
|
27
|
+
deleteMerchantBudget: (ctx: CtaContext) => Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* `PUT transactions/:guid` merging `params.fields` (category_guid, date, memo,
|
|
30
|
+
* description, is_hidden...). Resolves the transaction from `params.transactionGuid`,
|
|
31
|
+
* else the beat's primary transaction guid.
|
|
32
|
+
*/
|
|
33
|
+
updateTransactionField: (ctx: CtaContext) => Promise<void>;
|
|
34
|
+
/** `POST`/`PUT transaction_rules` so `params.categoryGuid` applies to future matches. */
|
|
35
|
+
applyTransactionRule: (ctx: CtaContext) => Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Hands a host-owned effect to the embedding app through `beatActions.onCtaAction`.
|
|
38
|
+
* `params.hostAction` names the effect; remaining params are forwarded untouched.
|
|
39
|
+
* Host action names are documented in README.md.
|
|
40
|
+
*/
|
|
41
|
+
delegateToHost: (ctx: CtaContext) => Promise<void>;
|
|
42
|
+
};
|
|
43
|
+
/** A registered handler name. `CtaStep.run` and `useCtaHandler` accept only these, so a typo fails typecheck. */
|
|
44
|
+
export type CtaHandlerName = keyof typeof ctaHandlers;
|