@mx-cartographer/experiences 9.4.19-alpha.al4 → 9.4.19

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 (41) hide show
  1. package/CHANGELOG.md +16 -7
  2. package/dist/common/components/dialog/Dialog.d.ts +1 -1
  3. package/dist/common/components/dialog/Dialog.es.js.map +1 -1
  4. package/dist/core/types/AppData.d.ts +0 -2
  5. package/dist/core/types/localization/InsightsFeedCopy.d.ts +6 -0
  6. package/dist/insights-v2/beatActions.d.ts +5 -19
  7. package/dist/insights-v2/beatActions.es.js.map +1 -1
  8. package/dist/insights-v2/components/BaseLayout.d.ts +8 -3
  9. package/dist/insights-v2/components/BaseLayout.es.js +105 -80
  10. package/dist/insights-v2/components/BaseLayout.es.js.map +1 -1
  11. package/dist/insights-v2/components/DismissInsightDialog.d.ts +1 -8
  12. package/dist/insights-v2/components/DismissInsightDialog.es.js.map +1 -1
  13. package/dist/insights-v2/components/FeedbackBar.d.ts +1 -12
  14. package/dist/insights-v2/components/FeedbackBar.es.js.map +1 -1
  15. package/dist/insights-v2/components/FeedbackDialog.d.ts +7 -25
  16. package/dist/insights-v2/components/FeedbackDialog.es.js +54 -42
  17. package/dist/insights-v2/components/FeedbackDialog.es.js.map +1 -1
  18. package/dist/insights-v2/components/HiddenConfirmationCard.d.ts +1 -11
  19. package/dist/insights-v2/components/HiddenConfirmationCard.es.js.map +1 -1
  20. package/dist/insights-v2/components/InsightOptionsMenu.d.ts +1 -6
  21. package/dist/insights-v2/components/InsightOptionsMenu.es.js.map +1 -1
  22. package/dist/insights-v2/components/ObsolesceBanner.d.ts +26 -0
  23. package/dist/insights-v2/components/ObsolesceBanner.es.js +119 -0
  24. package/dist/insights-v2/components/ObsolesceBanner.es.js.map +1 -0
  25. package/dist/insights-v2/hooks/useBeatFeedbackFlow.d.ts +8 -15
  26. package/dist/insights-v2/hooks/useBeatFeedbackFlow.es.js +35 -25
  27. package/dist/insights-v2/hooks/useBeatFeedbackFlow.es.js.map +1 -1
  28. package/dist/insights-v2/index.d.ts +2 -1
  29. package/dist/insights-v2/index.es.js +32 -30
  30. package/package.json +1 -9
  31. package/dist/rum/RumRedaction.d.ts +0 -1
  32. package/dist/rum/RumRedaction.es.js +0 -6
  33. package/dist/rum/RumRedaction.es.js.map +0 -1
  34. package/dist/rum/beforeSend.d.ts +0 -31
  35. package/dist/rum/beforeSend.es.js +0 -15
  36. package/dist/rum/beforeSend.es.js.map +0 -1
  37. package/dist/rum/errorBuffer.d.ts +0 -9
  38. package/dist/rum/errorBuffer.es.js +0 -27
  39. package/dist/rum/errorBuffer.es.js.map +0 -1
  40. package/dist/rum/index.d.ts +0 -3
  41. package/dist/rum/index.es.js +0 -9
package/CHANGELOG.md CHANGED
@@ -1,10 +1,19 @@
1
- ## [9.4.19] - 09-11-2026
2
-
3
- - **ADDED** - DataDog RUM for Pulse and MDB
4
-
5
- ## [9.4.18] - 09-10-2026
6
-
7
- - **ADDED** - `offer_guid` and `user_guid` to messaging insight metadata (MEW2-3270)
1
+ ## [9.4.19] - TBD
2
+
3
+ - **ADDED** - insights-v2 `ObsolesceBanner` component: presentational banner displaying beat obsolescence states (refresh_available, refreshing, updated, not_refreshable, hidden) with smooth Collapse animation, proper ARIA labels, and state-appropriate icons (Sync/CheckCircle/Cancel) and actions (Update/Dismiss buttons). Exported from insights-v2 with full TypeScript types (`ObsolesceBannerProps`, `ObsolesceBannerState`, `ObsolesceBannerCopy`). Component accepts state + callbacks + copy as props; host owns data logic (WEC-1766)
4
+ - **CHANGED** - `ObsolesceBanner` reuses existing `insights_feed.general` copy keys (`dismiss`, `insight_no_longer_applicable`, `insight_updated`, `new_information_available`, `update`, `updating`) rather than introducing a dedicated copy section — matches the copy already consumed by the legacy `ObsoleteManager` and defined in mrs_content, avoiding duplicate keys and translations. `GeneralInsightsFeedCopy` extended with these keys; `BaseLayout` passes `copy.insights_feed.general` straight through (WEC-1766)
5
+ - **CHANGED** - `BaseLayout` now accepts optional `obsolete` prop (`ObsoleteState` with `state`, `onRefresh`, `onDismiss`) and renders `ObsolesceBanner` above the Card when provided. When state is `not_refreshable` (and the beat is not dismissed) the Card gets a non-interactive semi-transparent overlay to dim its content without letting the banner show through. Follows the same optional-prop pattern as feedback UI; host supplies obsolescence state + callbacks (WEC-1766)
6
+ - **ADDED** - Comprehensive test coverage: 20 `ObsolesceBanner` tests (all 5 states, button interactions, copy variations, state transitions, callback isolation) plus `BaseLayout` obsolete tests (banner render, dimming overlay, click blocking, callbacks) (WEC-1766)
7
+ - **ADDED** - Storybook stories for `ObsolesceBanner`: 5 static state stories plus 1 interactive state-machine story with debug panel and automatic transitions (WEC-1766)
8
+
9
+ ## [9.4.18] - TBD
10
+
11
+ - **CHANGED** - insights-v2 feedback UI cleanup: removed verbose comments and section dividers from `BaseLayout`, `FeedbackDialog`, `FeedbackBar`, `HiddenConfirmationCard`, `DismissInsightDialog`, `InsightOptionsMenu`, and `useBeatFeedbackFlow`; code is now self-documenting with brief one-line descriptions only where complexity warrants explanation. Minimal comment philosophy applied throughout (WEC-1766)
12
+ - **CHANGED** - insights-v2 dismiss flow simplified: replaced controlled `dismissState` prop with direct `beat.is_dismissed` observation paired with local `hasClosedConfirmation` state in `useBeatFeedbackFlow`; `cardState` now derived via `useMemo` from these two sources. Eliminates need for parent-managed dismiss state while maintaining clean separation: Pulse owns persistence (`is_dismissed` property), experiences owns transient UI state (confirmation visibility). Survives navigation and handles API failures gracefully (WEC-1766)
13
+ - **CHANGED** - `beatActions` interface extended with MUI-native dialog close reason vocabulary: `onFeedbackDialogClose` now receives `'closeButton' | 'backdropClick' | 'escapeKeyDown'` instead of custom translated values, eliminating unnecessary abstraction layer and improving clarity (WEC-1766)
14
+ - **FIXED** - `BaseLayout` feedback state management: added `setFeedbackRating(null)` to `undoDismiss` handler to clear any pending rating when user undos a dismissal, preventing stale feedback UI state (WEC-1766)
15
+ - **FIXED** - `FeedbackDialog` props made non-optional: `primaryText`, `secondaryText`, and `closeAriaLabel` are now required (previously optional), and `multiline={true}` is now explicit on the TextField. All callers (BaseLayout, stories, tests) updated to provide required props (WEC-1766)
16
+ - **FIXED** - `DismissInsightDialog` spacing restored: `sx` overrides for content padding and header alignment re-added after being accidentally removed during refactor (WEC-1766)
8
17
 
9
18
  ## [9.4.17] - 09-04-2026
10
19
 
@@ -9,7 +9,7 @@ export interface DialogProps extends Omit<MuiDialogProps, 'open'> {
9
9
  copy: CopyObject;
10
10
  disablePrimaryButton?: boolean;
11
11
  isOpen: boolean;
12
- onClose: () => void;
12
+ onClose: (event?: unknown, reason?: string) => void;
13
13
  onPrimaryAction?: () => void;
14
14
  onSecondaryAction?: () => void;
15
15
  primaryColor?: 'primary' | 'inherit' | 'secondary' | 'success' | 'error' | 'info' | 'warning';
@@ -1 +1 @@
1
- {"version":3,"file":"Dialog.es.js","names":[],"sources":["../../../../src/common/components/dialog/Dialog.tsx"],"sourcesContent":["import React from 'react'\n\nimport MuiDialog from '@mui/material/Dialog'\nimport { DialogProps as MuiDialogProps } from '@mui/material/Dialog'\nimport DialogContent from '@mui/material/DialogContent'\nimport type { SxProps } from '@mui/material/styles'\n\nimport { DialogFooter, DialogHeader } from '@mxenabled/mxui'\nimport { useScreenSize } from '../../hooks'\n\nexport type CopyObject = {\n close_aria?: string\n title: string\n}\n\nexport interface DialogProps extends Omit<MuiDialogProps, 'open'> {\n className?: string\n copy: CopyObject\n disablePrimaryButton?: boolean\n isOpen: boolean\n onClose: () => void\n onPrimaryAction?: () => void\n onSecondaryAction?: () => void\n primaryColor?: 'primary' | 'inherit' | 'secondary' | 'success' | 'error' | 'info' | 'warning'\n primaryText?: string\n secondaryColor?: 'primary' | 'inherit' | 'secondary' | 'success' | 'error' | 'info' | 'warning'\n secondaryText?: string\n}\n\nconst Dialog: React.FC<React.PropsWithChildren<DialogProps>> = ({\n className,\n copy,\n disablePrimaryButton = false,\n isOpen = false,\n onClose,\n onPrimaryAction,\n primaryColor = 'primary',\n primaryText = 'Confirm',\n onSecondaryAction,\n secondaryColor = 'primary',\n secondaryText = 'Cancel',\n children,\n ...rest\n}) => {\n // Extract sx from rest to merge with Dialog's own styles instead of overwriting\n const { sx: restSx, ...restProps } = rest\n const title = copy?.title ?? ''\n const closeAria = copy?.close_aria ?? 'Close'\n\n const { isSmallMobile } = useScreenSize()\n\n const handlePrimaryAction = () => {\n onPrimaryAction?.()\n onClose()\n }\n\n const handleSecondaryAction = () => {\n if (onSecondaryAction) {\n onSecondaryAction()\n }\n onClose()\n }\n\n return (\n <div className={`mx-cmn-dialog ${className}`}>\n <MuiDialog\n aria-label={title}\n aria-labelledby={undefined}\n maxWidth=\"xs\"\n onClose={onClose}\n open={isOpen}\n slotProps={{\n paper: { 'aria-label': title },\n }}\n sx={\n [\n {\n '& .MuiDialog-paperScrollPaper': { backgroundColor: 'background.default' },\n ...(isSmallMobile && { '& .MuiDialog-paper': { minWidth: '100%' } }),\n height: '100%',\n },\n ...(restSx ? [restSx] : []),\n ] as SxProps\n }\n {...restProps}\n >\n <DialogHeader copy={{ title, close_aria: closeAria }} onClose={onClose} truncate={true} />\n\n <DialogContent sx={{ lineHeight: 1.5 }}>{children}</DialogContent>\n\n <DialogFooter\n isPrimaryDisabled={disablePrimaryButton}\n onPrimaryAction={handlePrimaryAction}\n onSecondaryAction={handleSecondaryAction}\n primaryColor={primaryColor}\n primaryText={primaryText}\n secondaryColor={secondaryColor}\n secondaryText={secondaryText}\n />\n </MuiDialog>\n </div>\n )\n}\n\nexport default Dialog\n"],"mappings":";;;;;;AA6BA,IAAM,IAAA,CAA0D,EAC9D,WAAA,GACA,MAAA,GACA,sBAAA,IAAuB,IACvB,QAAA,IAAS,IACT,SAAA,GACA,iBAAA,GACA,cAAA,IAAe,WACf,aAAA,IAAc,WACd,mBAAA,GACA,gBAAA,IAAiB,WACjB,eAAA,IAAgB,UAChB,UAAA,GACA,GAAG,EAAA,MACC;AAEJ,QAAM,EAAE,IAAI,GAAQ,GAAG,EAAA,IAAc,GAC/B,IAAQ,GAAM,SAAS,IACvB,IAAY,GAAM,cAAc,SAEhC,EAAE,eAAA,EAAA,IAAkB,EAAc,GAElC,IAAA,MAA4B;AAChC,IAAA,IAAkB,GAClB,EAAQ;AAAA,EACV,GAEM,IAAA,MAA8B;AAClC,IAAI,KACF,EAAkB,GAEpB,EAAQ;AAAA,EACV;AAEA,SACE,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAW,iBAAiB,CAAA;AAAA,IAC/B,UAAA,gBAAA,EAAC,GAAD;AAAA,MACE,cAAY;AAAA,MACZ,mBAAiB;AAAA,MACjB,UAAS;AAAA,MACA,SAAA;AAAA,MACT,MAAM;AAAA,MACN,WAAW,EACT,OAAO,EAAE,cAAc,EAAM,EAC/B;AAAA,MACA,IACE,CACE;AAAA,QACE,iCAAiC,EAAE,iBAAiB,qBAAqB;AAAA,QACzE,GAAI,KAAiB,EAAE,sBAAsB,EAAE,UAAU,OAAO,EAAE;AAAA,QAClE,QAAQ;AAAA,MACV,GACA,GAAI,IAAS,CAAC,CAAM,IAAI,CAAC,CAC3B;AAAA,MAEF,GAAI;AAAA,MAnBN,UAAA;AAAA,QAqBE,gBAAA,EAAC,GAAD;AAAA,UAAc,MAAM;AAAA,YAAE,OAAA;AAAA,YAAO,YAAY;AAAA,UAAU;AAAA,UAAY,SAAA;AAAA,UAAS,UAAU;AAAA,QAAO,CAAA;AAAA,QAEzF,gBAAA,EAAC,GAAD;AAAA,UAAe,IAAI,EAAE,YAAY,IAAI;AAAA,UAAI,UAAA;AAAA,QAAwB,CAAA;AAAA,QAEjE,gBAAA,EAAC,GAAD;AAAA,UACE,mBAAmB;AAAA,UACnB,iBAAiB;AAAA,UACjB,mBAAmB;AAAA,UACL,cAAA;AAAA,UACD,aAAA;AAAA,UACG,gBAAA;AAAA,UACD,eAAA;AAAA,QAChB,CAAA;AAAA,MACQ;AAAA;EACR,CAAA;AAET"}
1
+ {"version":3,"file":"Dialog.es.js","names":[],"sources":["../../../../src/common/components/dialog/Dialog.tsx"],"sourcesContent":["import React from 'react'\n\nimport MuiDialog from '@mui/material/Dialog'\nimport { DialogProps as MuiDialogProps } from '@mui/material/Dialog'\nimport DialogContent from '@mui/material/DialogContent'\nimport type { SxProps } from '@mui/material/styles'\n\nimport { DialogFooter, DialogHeader } from '@mxenabled/mxui'\nimport { useScreenSize } from '../../hooks'\n\nexport type CopyObject = {\n close_aria?: string\n title: string\n}\n\nexport interface DialogProps extends Omit<MuiDialogProps, 'open'> {\n className?: string\n copy: CopyObject\n disablePrimaryButton?: boolean\n isOpen: boolean\n onClose: (event?: unknown, reason?: string) => void\n onPrimaryAction?: () => void\n onSecondaryAction?: () => void\n primaryColor?: 'primary' | 'inherit' | 'secondary' | 'success' | 'error' | 'info' | 'warning'\n primaryText?: string\n secondaryColor?: 'primary' | 'inherit' | 'secondary' | 'success' | 'error' | 'info' | 'warning'\n secondaryText?: string\n}\n\nconst Dialog: React.FC<React.PropsWithChildren<DialogProps>> = ({\n className,\n copy,\n disablePrimaryButton = false,\n isOpen = false,\n onClose,\n onPrimaryAction,\n primaryColor = 'primary',\n primaryText = 'Confirm',\n onSecondaryAction,\n secondaryColor = 'primary',\n secondaryText = 'Cancel',\n children,\n ...rest\n}) => {\n // Extract sx from rest to merge with Dialog's own styles instead of overwriting\n const { sx: restSx, ...restProps } = rest\n const title = copy?.title ?? ''\n const closeAria = copy?.close_aria ?? 'Close'\n\n const { isSmallMobile } = useScreenSize()\n\n const handlePrimaryAction = () => {\n onPrimaryAction?.()\n onClose()\n }\n\n const handleSecondaryAction = () => {\n if (onSecondaryAction) {\n onSecondaryAction()\n }\n onClose()\n }\n\n return (\n <div className={`mx-cmn-dialog ${className}`}>\n <MuiDialog\n aria-label={title}\n aria-labelledby={undefined}\n maxWidth=\"xs\"\n onClose={onClose}\n open={isOpen}\n slotProps={{\n paper: { 'aria-label': title },\n }}\n sx={\n [\n {\n '& .MuiDialog-paperScrollPaper': { backgroundColor: 'background.default' },\n ...(isSmallMobile && { '& .MuiDialog-paper': { minWidth: '100%' } }),\n height: '100%',\n },\n ...(restSx ? [restSx] : []),\n ] as SxProps\n }\n {...restProps}\n >\n <DialogHeader copy={{ title, close_aria: closeAria }} onClose={onClose} truncate={true} />\n\n <DialogContent sx={{ lineHeight: 1.5 }}>{children}</DialogContent>\n\n <DialogFooter\n isPrimaryDisabled={disablePrimaryButton}\n onPrimaryAction={handlePrimaryAction}\n onSecondaryAction={handleSecondaryAction}\n primaryColor={primaryColor}\n primaryText={primaryText}\n secondaryColor={secondaryColor}\n secondaryText={secondaryText}\n />\n </MuiDialog>\n </div>\n )\n}\n\nexport default Dialog\n"],"mappings":";;;;;;AA6BA,IAAM,IAAA,CAA0D,EAC9D,WAAA,GACA,MAAA,GACA,sBAAA,IAAuB,IACvB,QAAA,IAAS,IACT,SAAA,GACA,iBAAA,GACA,cAAA,IAAe,WACf,aAAA,IAAc,WACd,mBAAA,GACA,gBAAA,IAAiB,WACjB,eAAA,IAAgB,UAChB,UAAA,GACA,GAAG,EAAA,MACC;AAEJ,QAAM,EAAE,IAAI,GAAQ,GAAG,EAAA,IAAc,GAC/B,IAAQ,GAAM,SAAS,IACvB,IAAY,GAAM,cAAc,SAEhC,EAAE,eAAA,EAAA,IAAkB,EAAc,GAElC,IAAA,MAA4B;AAChC,IAAA,IAAkB,GAClB,EAAQ;AAAA,EACV,GAEM,IAAA,MAA8B;AAClC,IAAI,KACF,EAAkB,GAEpB,EAAQ;AAAA,EACV;AAEA,SACE,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAW,iBAAiB,CAAA;AAAA,IAC/B,UAAA,gBAAA,EAAC,GAAD;AAAA,MACE,cAAY;AAAA,MACZ,mBAAiB;AAAA,MACjB,UAAS;AAAA,MACA,SAAA;AAAA,MACT,MAAM;AAAA,MACN,WAAW,EACT,OAAO,EAAE,cAAc,EAAM,EAC/B;AAAA,MACA,IACE,CACE;AAAA,QACE,iCAAiC,EAAE,iBAAiB,qBAAqB;AAAA,QACzE,GAAI,KAAiB,EAAE,sBAAsB,EAAE,UAAU,OAAO,EAAE;AAAA,QAClE,QAAQ;AAAA,MACV,GACA,GAAI,IAAS,CAAC,CAAM,IAAI,CAAC,CAC3B;AAAA,MAEF,GAAI;AAAA,MAnBN,UAAA;AAAA,QAqBE,gBAAA,EAAC,GAAD;AAAA,UAAc,MAAM;AAAA,YAAE,OAAA;AAAA,YAAO,YAAY;AAAA,UAAU;AAAA,UAAY,SAAA;AAAA,UAAS,UAAU;AAAA,QAAO,CAAA;AAAA,QAEzF,gBAAA,EAAC,GAAD;AAAA,UAAe,IAAI,EAAE,YAAY,IAAI;AAAA,UAAI,UAAA;AAAA,QAAwB,CAAA;AAAA,QAEjE,gBAAA,EAAC,GAAD;AAAA,UACE,mBAAmB;AAAA,UACnB,iBAAiB;AAAA,UACjB,mBAAmB;AAAA,UACL,cAAA;AAAA,UACD,aAAA;AAAA,UACG,gBAAA;AAAA,UACD,eAAA;AAAA,QAChB,CAAA;AAAA,MACQ;AAAA;EACR,CAAA;AAET"}
@@ -18,8 +18,6 @@ export interface AppConfig {
18
18
  clientConfig?: ClientConfig;
19
19
  clientStyleProfile: ClientStyleProfile;
20
20
  config: Config;
21
- datadogRumApplicationIdMd?: string;
22
- datadogRumClientTokenMd?: string;
23
21
  honeyBadgerPublicKey?: string;
24
22
  is_mobile_webview?: boolean;
25
23
  options: Options;
@@ -4,13 +4,19 @@ interface DynamicKeyValue {
4
4
  }
5
5
  interface GeneralInsightsFeedCopy {
6
6
  decreased_text: string;
7
+ dismiss: string;
7
8
  embedded_description: string;
8
9
  increased_text: string;
10
+ insight_no_longer_applicable: string;
11
+ insight_updated: string;
9
12
  monthly_amount: string;
13
+ new_information_available: string;
10
14
  tip_section_message: string;
11
15
  tip_section_title: string;
12
16
  transaction_history_title: string;
13
17
  trend: string;
18
+ update: string;
19
+ updating: string;
14
20
  }
15
21
  interface SettingsMenuCopy {
16
22
  close: string;
@@ -1,15 +1,11 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { DismissType } from './components/DismissInsightDialog';
3
- /** Overflow-menu action keys emitted to the host. */
3
+ import { FeedbackDialogCloseReason } from './components/FeedbackDialog';
4
4
  export type InsightMenuAction = 'helpful' | 'not_helpful' | 'hide';
5
- /** How the user rated the insight (drives the feedback survey's options). */
6
5
  export type InsightRating = 'helpful' | 'not_helpful';
7
6
  export interface MenuActionHandlers {
8
- /** Invoked with the chosen overflow-menu action key. */
9
7
  onAction: (action: InsightMenuAction) => void;
10
- /** Called when the overflow menu opens (e.g. analytics). */
11
8
  onOpen?: () => void;
12
- /** Disables the overflow menu trigger (e.g. an obsolete beat). */
13
9
  disabled?: boolean;
14
10
  }
15
11
  export interface UpdateParams {
@@ -17,39 +13,29 @@ export interface UpdateParams {
17
13
  }
18
14
  export interface FeedbackParams {
19
15
  beatGuid: string;
20
- /** What prompted the survey — a rating (helpful/not-helpful) or a hide. */
21
16
  source: InsightRating | 'hide';
22
- /** The chosen reason option. */
23
17
  option: string;
24
- /** Free-text detail, present only when "Other" was chosen. */
25
18
  detail?: string;
26
19
  }
27
20
  export interface DismissParams {
28
21
  beatGuid: string;
29
- /** Whether the user chose to hide once or always. */
30
22
  type: DismissType;
31
23
  }
32
- /**
33
- * Host callbacks for a beat card, grouped under one prop and delivered via
34
- * context so any descendant (header menu, blocks, variants) can reach the
35
- * handler it needs without prop drilling. Each concern is its own typed slot —
36
- * add new callbacks here as they arise.
37
- */
24
+ /** Host callbacks for a beat card. */
38
25
  export interface BeatActions {
39
26
  onMenuAction?: MenuActionHandlers;
40
27
  onUpdate?: (params: UpdateParams) => void;
41
- /** Receives the completed feedback survey (helpful / not-helpful / hide). */
42
28
  onSubmitFeedback?: (params: FeedbackParams) => void;
43
- /** Performs the actual hide once the user confirms in the dismiss dialog. */
44
29
  onDismissInsight?: (params: DismissParams) => void;
45
- /** Reverses a hide when the user taps "Undo" on the confirmation card. */
46
30
  onUndoDismiss?: (params: {
47
31
  beatGuid: string;
48
32
  }) => void;
33
+ onFeedbackDialogClose?: (reason: FeedbackDialogCloseReason) => void;
34
+ onFeedbackDialogBack?: () => void;
35
+ onFeedbackTextFocus?: () => void;
49
36
  }
50
37
  export declare const BeatActionsProvider: ({ value, children, }: {
51
38
  value: BeatActions;
52
39
  children: ReactNode;
53
40
  }) => import("react/jsx-runtime").JSX.Element;
54
- /** Read the host callbacks for the current beat card. */
55
41
  export declare const useBeatActions: () => 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'\n\n/** Overflow-menu action keys emitted to the host. */\nexport type InsightMenuAction = 'helpful' | 'not_helpful' | 'hide'\n\n/** How the user rated the insight (drives the feedback survey's options). */\nexport type InsightRating = 'helpful' | 'not_helpful'\n\nexport interface MenuActionHandlers {\n /** Invoked with the chosen overflow-menu action key. */\n onAction: (action: InsightMenuAction) => void\n /** Called when the overflow menu opens (e.g. analytics). */\n onOpen?: () => void\n /** Disables the overflow menu trigger (e.g. an obsolete beat). */\n disabled?: boolean\n}\n\nexport interface UpdateParams {\n beatGuid: string\n // …extend with whatever the host's updateBeat needs.\n}\n\nexport interface FeedbackParams {\n beatGuid: string\n /** What prompted the survey — a rating (helpful/not-helpful) or a hide. */\n source: InsightRating | 'hide'\n /** The chosen reason option. */\n option: string\n /** Free-text detail, present only when \"Other\" was chosen. */\n detail?: string\n}\n\nexport interface DismissParams {\n beatGuid: string\n /** Whether the user chose to hide once or always. */\n type: DismissType\n}\n\n/**\n * Host callbacks for a beat card, grouped under one prop and delivered via\n * context so any descendant (header menu, blocks, variants) can reach the\n * handler it needs without prop drilling. Each concern is its own typed slot —\n * add new callbacks here as they arise.\n */\nexport interface BeatActions {\n onMenuAction?: MenuActionHandlers\n onUpdate?: (params: UpdateParams) => void\n /** Receives the completed feedback survey (helpful / not-helpful / hide). */\n onSubmitFeedback?: (params: FeedbackParams) => void\n /** Performs the actual hide once the user confirms in the dismiss dialog. */\n onDismissInsight?: (params: DismissParams) => void\n /** Reverses a hide when the user taps \"Undo\" on the confirmation card. */\n onUndoDismiss?: (params: { beatGuid: string }) => 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\n/** Read the host callbacks for the current beat card. */\nexport const useBeatActions = () => useContext(BeatActionsContext)\n"],"mappings":";;AAyDA,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,GAG3E,IAAA,MAAuB,EAAW,CAAkB"}
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\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":";;AA0CA,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,12 +1,17 @@
1
+ import { ObsolesceBannerState } from './ObsolesceBanner';
1
2
  import { Beat } from '../../core';
2
3
  import { BeatActions } from '../beatActions';
4
+ export interface ObsoleteState {
5
+ state: ObsolesceBannerState;
6
+ onRefresh: () => void;
7
+ onDismiss: () => void;
8
+ }
3
9
  interface BaseLayoutProps {
4
10
  beat: Beat;
5
- /** Host callbacks (menu actions, updateBeat, …) delivered to the card subtree
6
- * via context, so blocks/variants can reach them without prop drilling. */
7
11
  beatActions?: BeatActions;
12
+ obsolete?: ObsoleteState;
8
13
  }
9
- declare const BaseLayout: (({ beat, beatActions }: BaseLayoutProps) => import("react/jsx-runtime").JSX.Element | null) & {
14
+ declare const BaseLayout: (({ beat, beatActions, obsolete }: BaseLayoutProps) => import("react/jsx-runtime").JSX.Element | null) & {
10
15
  displayName: string;
11
16
  };
12
17
  export default BaseLayout;
@@ -1,111 +1,136 @@
1
- import { useInsightsV2Store as v } from "../../common/context/hooks.es.js";
2
- import { blocks as b } from "../mappings/blocks.es.js";
3
- import g from "./Footer.es.js";
4
- import { BeatActionsProvider as k } from "../beatActions.es.js";
5
- import C from "./Header.es.js";
6
- import { FeedbackBar as _ } from "./FeedbackBar.es.js";
7
- import S from "./FeedbackDialog.es.js";
8
- import { DismissInsightDialog as x } from "./DismissInsightDialog.es.js";
9
- import { HiddenConfirmationCard as L } from "./HiddenConfirmationCard.es.js";
10
- import { ActionBlockLayer as D } from "../actionBlocks/ActionBlockLayer.es.js";
11
- import { useBeatFeedbackFlow as B } from "../hooks/useBeatFeedbackFlow.es.js";
12
- import { observer as w } from "mobx-react-lite";
13
- import a from "@mui/material/Stack";
14
- import l from "@mui/material/Button";
15
- import { ChevronRight as T } from "@mxenabled/mx-icons";
16
- import { jsx as i, jsxs as t } from "react/jsx-runtime";
17
- import A from "@mui/material/Card";
18
- var F = {}, W = w(({ beat: r, beatActions: p = F }) => {
19
- const { openCtaDrawer: c } = v(), o = B(r, p), e = r.insights_payload;
20
- if (!e || o.cardState === "dismissed") return null;
21
- const { instance_slot: u, primary_cta: s, secondary_cta: n, subtitle: f, widget_type: y } = e, { block: h } = u, m = b[h], d = y === "mini";
22
- return /* @__PURE__ */ i(k, {
1
+ import { useGlobalCopyStore as C, useInsightsV2Store as x } from "../../common/context/hooks.es.js";
2
+ import { blocks as _ } from "../mappings/blocks.es.js";
3
+ import S from "./Footer.es.js";
4
+ import { BeatActionsProvider as B } from "../beatActions.es.js";
5
+ import D from "./Header.es.js";
6
+ import { FeedbackBar as L } from "./FeedbackBar.es.js";
7
+ import O from "./FeedbackDialog.es.js";
8
+ import { DismissInsightDialog as T } from "./DismissInsightDialog.es.js";
9
+ import { HiddenConfirmationCard as F } from "./HiddenConfirmationCard.es.js";
10
+ import { ObsolesceBanner as w } from "./ObsolesceBanner.es.js";
11
+ import { ActionBlockLayer as I } from "../actionBlocks/ActionBlockLayer.es.js";
12
+ import { useBeatFeedbackFlow as A } from "../hooks/useBeatFeedbackFlow.es.js";
13
+ import { observer as E } from "mobx-react-lite";
14
+ import m from "@mui/material/Stack";
15
+ import d from "@mui/material/Button";
16
+ import { ChevronRight as H } from "@mxenabled/mx-icons";
17
+ import { Fragment as M, jsx as e, jsxs as t } from "react/jsx-runtime";
18
+ import R from "@mui/material/Box";
19
+ import j from "@mui/material/Card";
20
+ var z = {}, G = {
21
+ position: "absolute",
22
+ top: 0,
23
+ left: 0,
24
+ width: "100%",
25
+ height: "100%",
26
+ backgroundColor: "background.default",
27
+ opacity: 0.7,
28
+ zIndex: 1
29
+ }, no = E(({ beat: i, beatActions: y = z, obsolete: s }) => {
30
+ const { openCtaDrawer: p } = x(), h = C(), o = A(i, y), r = i.insights_payload;
31
+ if (!r || o.cardState === "dismissed") return null;
32
+ const { instance_slot: b, primary_cta: n, secondary_cta: a, subtitle: g, widget_type: k } = r, { block: v } = b, u = _[v], f = k === "mini", l = h.insights_feed?.general, c = s?.state === "not_refreshable" && !i.dismissed_at && !!l;
33
+ return /* @__PURE__ */ e(B, {
23
34
  value: o.wrappedActions,
24
- children: /* @__PURE__ */ t(a, {
35
+ children: /* @__PURE__ */ t(m, {
25
36
  sx: { mb: 16 },
26
37
  children: [
27
- o.cardState === "confirming" ? /* @__PURE__ */ i(L, {
38
+ o.cardState === "confirming" ? /* @__PURE__ */ e(F, {
28
39
  onClose: o.collapseConfirmation,
29
40
  onLeaveFeedback: o.openHideSurvey,
30
41
  onUndo: o.undoDismiss
31
- }) : /* @__PURE__ */ t(A, { children: [
32
- /* @__PURE__ */ i(C, {
33
- isMini: d,
34
- subtitle: f,
35
- title: r.title
36
- }),
37
- m && /* @__PURE__ */ i(m, {
38
- beatGuid: r.guid,
39
- payload: e
40
- }),
41
- /* @__PURE__ */ t(a, {
42
- sx: {
43
- gap: 6,
44
- pb: 16,
45
- pl: 12,
46
- pr: 16,
47
- pt: 12
48
- },
49
- children: [/* @__PURE__ */ i("div", {
50
- dangerouslySetInnerHTML: { __html: r.html_description },
51
- style: { paddingLeft: 4 }
52
- }), r?.in_description_cta && /* @__PURE__ */ i(l, {
53
- endIcon: /* @__PURE__ */ i(T, {}),
54
- onClick: () => {
42
+ }) : /* @__PURE__ */ t(M, { children: [s && l && /* @__PURE__ */ e(w, {
43
+ ...s,
44
+ copy: l
45
+ }), /* @__PURE__ */ t(j, {
46
+ inert: c,
47
+ sx: { ...c && {
48
+ position: "relative",
49
+ zIndex: 2,
50
+ pointerEvents: "none"
51
+ } },
52
+ children: [
53
+ c && /* @__PURE__ */ e(R, { sx: G }),
54
+ /* @__PURE__ */ e(D, {
55
+ isMini: f,
56
+ subtitle: g,
57
+ title: i.title
58
+ }),
59
+ u && /* @__PURE__ */ e(u, {
60
+ beatGuid: i.guid,
61
+ payload: r
62
+ }),
63
+ /* @__PURE__ */ t(m, {
64
+ sx: {
65
+ gap: 6,
66
+ pb: 16,
67
+ pl: 12,
68
+ pr: 16,
69
+ pt: 12
55
70
  },
71
+ children: [/* @__PURE__ */ e("div", {
72
+ dangerouslySetInnerHTML: { __html: i.html_description },
73
+ style: { paddingLeft: 4 }
74
+ }), i?.in_description_cta && /* @__PURE__ */ e(d, {
75
+ endIcon: /* @__PURE__ */ e(H, {}),
76
+ onClick: () => {
77
+ },
78
+ sx: {
79
+ height: 24,
80
+ p: 4,
81
+ width: "max-content"
82
+ },
83
+ children: i.in_description_cta
84
+ })]
85
+ }),
86
+ !f && n?.label && /* @__PURE__ */ t(m, {
56
87
  sx: {
57
- height: 24,
58
- p: 4,
59
- width: "max-content"
88
+ gap: 8,
89
+ pb: 16,
90
+ px: 16
60
91
  },
61
- children: r.in_description_cta
62
- })]
63
- }),
64
- !d && s?.label && /* @__PURE__ */ t(a, {
65
- sx: {
66
- gap: 8,
67
- pb: 16,
68
- px: 16
69
- },
70
- children: [/* @__PURE__ */ i(l, {
71
- onClick: () => s.block && c(r.guid, "primaryCta"),
72
- variant: "outlined",
73
- children: s.label
74
- }), n?.label && /* @__PURE__ */ i(l, {
75
- color: "secondary",
76
- onClick: () => n.block && c(r.guid, "secondaryCta"),
77
- children: n.label
78
- })]
79
- }),
80
- /* @__PURE__ */ i(_, {
81
- onTellUsMore: o.openRatingSurvey,
82
- show: o.isFeedbackBarShown
83
- })
84
- ] }),
85
- /* @__PURE__ */ i(D, { beat: r }),
86
- /* @__PURE__ */ i(x, {
92
+ children: [/* @__PURE__ */ e(d, {
93
+ onClick: () => n.block && p(i.guid, "primaryCta"),
94
+ variant: "outlined",
95
+ children: n.label
96
+ }), a?.label && /* @__PURE__ */ e(d, {
97
+ color: "secondary",
98
+ onClick: () => a.block && p(i.guid, "secondaryCta"),
99
+ children: a.label
100
+ })]
101
+ }),
102
+ /* @__PURE__ */ e(L, {
103
+ onTellUsMore: o.openRatingSurvey,
104
+ show: o.isFeedbackBarShown
105
+ })
106
+ ]
107
+ })] }),
108
+ /* @__PURE__ */ e(I, { beat: i }),
109
+ /* @__PURE__ */ e(T, {
87
110
  isOpen: o.isDismissOpen,
88
111
  onClose: o.closeDismissDialog,
89
112
  onDismiss: o.confirmDismiss
90
113
  }),
91
- o.isSurveyOpen && /* @__PURE__ */ i(S, {
114
+ o.isSurveyOpen && /* @__PURE__ */ e(O, {
92
115
  characterLimitLabel: o.survey.characterLimitLabel,
93
116
  closeAriaLabel: o.survey.closeAriaLabel,
94
117
  isOpen: !0,
118
+ onBackClick: o.feedbackDialogCallbacks.onBackClick,
95
119
  onClose: o.closeSurvey,
96
120
  onSubmit: o.submitSurvey,
121
+ onTextInputFocus: o.feedbackDialogCallbacks.onTextInputFocus,
97
122
  options: o.survey.options,
98
123
  primaryText: o.survey.submitText,
99
124
  secondaryText: o.survey.backText,
100
125
  title: o.survey.title
101
126
  }),
102
- o.cardState === "visible" && e.footer && /* @__PURE__ */ i(g, { footer: e.footer })
127
+ o.cardState === "visible" && r.footer && /* @__PURE__ */ e(S, { footer: r.footer })
103
128
  ]
104
129
  })
105
130
  });
106
131
  });
107
132
  export {
108
- W as default
133
+ no as default
109
134
  };
110
135
 
111
136
  //# 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 Button from '@mui/material/Button'\nimport Card from '@mui/material/Card'\nimport Stack from '@mui/material/Stack'\n\nimport { ChevronRight } from '@mxenabled/mx-icons'\n\nimport { blocks } from '../mappings/blocks'\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 { useInsightsV2Store } from '../../common'\nimport type { Beat } from '../../core'\nimport { BeatActionsProvider, type BeatActions } from '../beatActions'\nimport { ActionBlockLayer } from '../actionBlocks/ActionBlockLayer'\nimport { useBeatFeedbackFlow } from '../hooks/useBeatFeedbackFlow'\n\ninterface BaseLayoutProps {\n beat: Beat\n /** Host callbacks (menu actions, updateBeat, …) delivered to the card subtree\n * via context, so blocks/variants can reach them without prop drilling. */\n beatActions?: BeatActions\n}\n\n// Stable default so an omitted prop doesn't create a new context value each\n// render (which would re-render every consumer).\nconst NO_BEAT_ACTIONS: BeatActions = {}\n\nconst BaseLayout = observer(({ beat, beatActions = NO_BEAT_ACTIONS }: BaseLayoutProps) => {\n const { openCtaDrawer } = useInsightsV2Store()\n\n // All post-action UI (feedback bar, dismiss dialog, hidden card, survey) lives\n // in this hook so BaseLayout stays focused on layout.\n const flow = useBeatFeedbackFlow(beat, beatActions)\n\n const insights_payload = beat.insights_payload\n\n if (!insights_payload) {\n return null\n }\n\n // Confirmation dismissed (via close or after leaving feedback): render nothing.\n // The beat stays hidden — the host drops it on the next feed refresh.\n if (flow.cardState === 'dismissed') {\n return null\n }\n\n const { instance_slot, primary_cta, secondary_cta, subtitle, widget_type } = insights_payload\n const { block } = instance_slot\n\n const Block = blocks[block as keyof typeof blocks]\n\n const isMini = widget_type === 'mini'\n\n return (\n <BeatActionsProvider value={flow.wrappedActions}>\n <Stack sx={{ mb: 16 }}>\n {flow.cardState === 'confirming' ? (\n // Once hidden, the card is replaced by a confirmation prompt. Undo\n // reverses the hide; Close collapses the prompt (beat stays hidden);\n // Leave Feedback opens the hide survey.\n <HiddenConfirmationCard\n onClose={flow.collapseConfirmation}\n onLeaveFeedback={flow.openHideSurvey}\n onUndo={flow.undoDismiss}\n />\n ) : (\n <Card>\n {/* Header */}\n <Header isMini={isMini} subtitle={subtitle} title={beat.title} />\n\n {/* Instance Slot */}\n {Block && <Block beatGuid={beat.guid} payload={insights_payload} />}\n\n {/* Body */}\n <Stack sx={{ gap: 6, pb: 16, pl: 12, pr: 16, pt: 12 }}>\n <div\n dangerouslySetInnerHTML={{\n __html: beat.html_description as string,\n }}\n style={{ paddingLeft: 4 }}\n />\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 {/* CTA. A CTA without a real `block` doesn't open a drawer (it may trigger\n a postMessage etc.) — restrict the drawer to CTAs that carry a block. */}\n {!isMini && primary_cta?.label && (\n <Stack sx={{ gap: 8, pb: 16, px: 16 }}>\n <Button\n onClick={() => primary_cta.block && openCtaDrawer(beat.guid, 'primaryCta')}\n variant=\"outlined\"\n >\n {primary_cta.label}\n </Button>\n {secondary_cta?.label && (\n <Button\n color=\"secondary\"\n onClick={() => secondary_cta.block && openCtaDrawer(beat.guid, 'secondaryCta')}\n >\n {secondary_cta.label}\n </Button>\n )}\n </Stack>\n )}\n\n {/* Feedback bar — shown below the action buttons once the insight is\n rated; \"Tell us more\" opens the survey dialog. Kept mounted so the\n Grow transition can play out when the rating clears. */}\n <FeedbackBar onTellUsMore={flow.openRatingSurvey} show={flow.isFeedbackBarShown} />\n </Card>\n )}\n\n {/* Always mounted: the drawer's slide in/out animation only plays when\n MUI sees isOpen CHANGE on a mounted Drawer — conditionally mounting\n it here made it snap open and vanish on close. */}\n <ActionBlockLayer beat={beat} />\n\n {/* Hide confirmation dialog — pick once / always, then confirm. */}\n <DismissInsightDialog\n isOpen={flow.isDismissOpen}\n onClose={flow.closeDismissDialog}\n onDismiss={flow.confirmDismiss}\n />\n\n {/* Survey dialog — opened from the feedback bar (rating) or the hidden\n card's \"Leave Feedback\" (hide). FeedbackDialog is generic; the flow\n hook resolves the copy for the active variant.\n Conditionally mounted (unlike DismissInsightDialog, which toggles\n isOpen): its title + options are variant-driven and closing clears\n the variant, so keeping it mounted would flip the content to the\n default variant mid close-transition. Mounting per-open trades the\n fade-out for correct content. */}\n {flow.isSurveyOpen && (\n <FeedbackDialog\n characterLimitLabel={flow.survey.characterLimitLabel}\n closeAriaLabel={flow.survey.closeAriaLabel}\n isOpen={true}\n onClose={flow.closeSurvey}\n onSubmit={flow.submitSurvey}\n options={flow.survey.options}\n primaryText={flow.survey.submitText}\n secondaryText={flow.survey.backText}\n title={flow.survey.title}\n />\n )}\n\n {/* Footer */}\n {flow.cardState === 'visible' && insights_payload.footer && (\n <Footer footer={insights_payload.footer} />\n )}\n </Stack>\n </BeatActionsProvider>\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'\n\nimport { blocks } from '../mappings/blocks'\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 { ObsolesceBanner, type ObsolesceBannerState } from './ObsolesceBanner'\nimport { useGlobalCopyStore, useInsightsV2Store } from '../../common'\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}\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\nconst BaseLayout = observer(\n ({ beat, beatActions = NO_BEAT_ACTIONS, obsolete }: BaseLayoutProps) => {\n const { openCtaDrawer } = useInsightsV2Store()\n const copy = useGlobalCopyStore()\n const flow = useBeatFeedbackFlow(beat, beatActions)\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 { instance_slot, primary_cta, secondary_cta, subtitle, widget_type } = insights_payload\n const { block } = instance_slot\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' && !beat.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={beat.title} />\n {Block && <Block beatGuid={beat.guid} payload={insights_payload} />}\n\n <Stack sx={{ gap: 6, pb: 16, pl: 12, pr: 16, pt: 12 }}>\n <div\n dangerouslySetInnerHTML={{\n __html: beat.html_description as string,\n }}\n style={{ paddingLeft: 4 }}\n />\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 {!isMini && primary_cta?.label && (\n <Stack sx={{ gap: 8, pb: 16, px: 16 }}>\n <Button\n onClick={() => primary_cta.block && openCtaDrawer(beat.guid, 'primaryCta')}\n variant=\"outlined\"\n >\n {primary_cta.label}\n </Button>\n {secondary_cta?.label && (\n <Button\n color=\"secondary\"\n onClick={() =>\n secondary_cta.block && openCtaDrawer(beat.guid, 'secondaryCta')\n }\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,17 +1,10 @@
1
- /** How the user chose to hide the insight. */
2
1
  export type DismissType = 'once' | 'always';
3
2
  export interface DismissInsightDialogProps {
4
3
  isOpen: boolean;
5
4
  onClose: () => void;
6
- /** Emits the chosen dismiss type on confirm; the host performs the actual hide. */
7
5
  onDismiss: (type: DismissType) => void;
8
6
  }
9
- /**
10
- * Confirmation dialog for hiding an insight: pick "Hide Once" vs "Always Hide",
11
- * then Confirm. Presentational — it owns only the local radio selection; the host
12
- * controls `isOpen` and performs the hide via `onDismiss`. Built on the shared
13
- * `Dialog` shell, which closes itself after either footer action.
14
- */
7
+ /** Confirmation dialog for hiding an insight. */
15
8
  export declare const DismissInsightDialog: (({ isOpen, onClose, onDismiss }: DismissInsightDialogProps) => import("react/jsx-runtime").JSX.Element | null) & {
16
9
  displayName: string;
17
10
  };
@@ -1 +1 @@
1
- {"version":3,"file":"DismissInsightDialog.es.js","names":[],"sources":["../../../src/insights-v2/components/DismissInsightDialog.tsx"],"sourcesContent":["import { useEffect, useState } from 'react'\n\nimport FormControlLabel from '@mui/material/FormControlLabel'\nimport Radio from '@mui/material/Radio'\nimport RadioGroup from '@mui/material/RadioGroup'\nimport Stack from '@mui/material/Stack'\n\nimport { observer } from 'mobx-react-lite'\n\nimport { Text } from '@mxenabled/mxui'\n\nimport { Dialog, useGlobalCopyStore } from '../../common'\n\n/** How the user chose to hide the insight. */\nexport type DismissType = 'once' | 'always'\n\nexport interface DismissInsightDialogProps {\n isOpen: boolean\n onClose: () => void\n /** Emits the chosen dismiss type on confirm; the host performs the actual hide. */\n onDismiss: (type: DismissType) => void\n}\n\n/**\n * Confirmation dialog for hiding an insight: pick \"Hide Once\" vs \"Always Hide\",\n * then Confirm. Presentational — it owns only the local radio selection; the host\n * controls `isOpen` and performs the hide via `onDismiss`. Built on the shared\n * `Dialog` shell, which closes itself after either footer action.\n */\nexport const DismissInsightDialog = observer(\n ({ isOpen, onClose, onDismiss }: DismissInsightDialogProps) => {\n const copy = useGlobalCopyStore().insights_feed?.dismiss\n const [selected, setSelected] = useState<DismissType>('once')\n\n // Reset to the safer default when the dialog opens.\n useEffect(() => {\n if (isOpen) setSelected('once')\n }, [isOpen])\n\n if (!copy) return null\n\n return (\n <Dialog\n copy={{ title: copy.title, close_aria: copy.close_aria }}\n isOpen={isOpen}\n onClose={onClose}\n onPrimaryAction={() => onDismiss(selected)}\n primaryText={copy.confirm}\n secondaryText={copy.cancel}\n // Figma design: white surface, 1px divider border, no elevation shadow, no\n // focus outline. The bgcolor overrides the shared Dialog's default grey\n // (background.default) for this dialog only — the shared component is untouched.\n sx={{\n // DialogContent: remove only vertical padding (keep horizontal)\n '& .MuiDialogContent-root': { py: 0 },\n // Figma header is 56px (pt 24 / title 24 / pb 8). Override DialogHeader's default py:14.\n '& .MuiDialog-paperScrollPaper > div:first-child': { pt: 24, pb: 8 },\n '& .MuiDialog-paperScrollPaper > div:first-child .MuiIconButton-root': { my: -10 },\n '& .MuiDialog-paperScrollPaper': {\n bgcolor: 'background.paper',\n border: '1px solid',\n borderColor: 'divider',\n boxShadow: 'none',\n },\n '&:focus-visible': {\n outline: '2px solid',\n outlineColor: 'primary.main',\n },\n '& .MuiDialog-paper:focus-visible': {\n outline: '2px solid',\n outlineColor: 'primary.main',\n },\n // Figma shows Cancel as a plain text button; the shared DialogFooter\n // defaults the secondary action to variant=\"outlined\".\n '& .MuiButton-outlined': {\n border: 'none',\n '&:hover': { bgcolor: 'transparent', border: 'none' },\n },\n }}\n >\n <Stack sx={{ gap: 24 }}>\n <Text variant=\"subtitle1\">{copy.description}</Text>\n\n <RadioGroup\n aria-label={copy.title}\n name=\"dismiss-type\"\n onChange={(e) => setSelected(e.target.value as DismissType)}\n sx={{ m: 0, p: 0 }}\n value={selected}\n >\n <Stack sx={{ gap: 16 }}>\n {(['once', 'always'] as const).map((k) => (\n <FormControlLabel\n key={k}\n value={k}\n control={<Radio inputProps={{ 'aria-label': copy[k].headline }} />}\n labelPlacement=\"start\"\n label={\n <Stack sx={{ gap: 4, flexGrow: 1 }}>\n <Text bold={true} variant=\"body1\">\n {copy[k].headline}\n </Text>\n <Text variant=\"subtitle2\">{copy[k].description}</Text>\n </Stack>\n }\n sx={{\n alignItems: 'center',\n borderRadius: '8px',\n justifyContent: 'space-between',\n m: 0,\n minHeight: 72,\n px: 16,\n py: 0,\n // inset shadow instead of border → the 1px→2px selected change adds no layout shift\n boxShadow: (theme) =>\n selected === k\n ? `inset 0 0 0 2px ${theme.palette.primary.main}`\n : `inset 0 0 0 1px ${theme.palette.divider}`,\n }}\n />\n ))}\n </Stack>\n </RadioGroup>\n </Stack>\n </Dialog>\n )\n },\n)\n\nexport default DismissInsightDialog\n"],"mappings":"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"}
1
+ {"version":3,"file":"DismissInsightDialog.es.js","names":[],"sources":["../../../src/insights-v2/components/DismissInsightDialog.tsx"],"sourcesContent":["import { useEffect, useState } from 'react'\n\nimport FormControlLabel from '@mui/material/FormControlLabel'\nimport Radio from '@mui/material/Radio'\nimport RadioGroup from '@mui/material/RadioGroup'\nimport Stack from '@mui/material/Stack'\n\nimport { observer } from 'mobx-react-lite'\n\nimport { Text } from '@mxenabled/mxui'\n\nimport { Dialog, useGlobalCopyStore } from '../../common'\n\nexport type DismissType = 'once' | 'always'\n\nexport interface DismissInsightDialogProps {\n isOpen: boolean\n onClose: () => void\n onDismiss: (type: DismissType) => void\n}\n\n/** Confirmation dialog for hiding an insight. */\nexport const DismissInsightDialog = observer(\n ({ isOpen, onClose, onDismiss }: DismissInsightDialogProps) => {\n const copy = useGlobalCopyStore().insights_feed?.dismiss\n const [selected, setSelected] = useState<DismissType>('once')\n\n useEffect(() => {\n if (isOpen) setSelected('once')\n }, [isOpen])\n\n if (!copy) return null\n\n return (\n <Dialog\n copy={{ title: copy.title, close_aria: copy.close_aria }}\n isOpen={isOpen}\n onClose={onClose}\n onPrimaryAction={() => onDismiss(selected)}\n primaryText={copy.confirm}\n secondaryText={copy.cancel}\n sx={{\n '& .MuiDialogContent-root': { py: 0 },\n '& .MuiDialog-paperScrollPaper > div:first-child': { pt: 24, pb: 8 },\n '& .MuiDialog-paperScrollPaper > div:first-child .MuiIconButton-root': { my: -10 },\n '& .MuiDialog-paperScrollPaper': {\n bgcolor: 'background.paper',\n border: '1px solid',\n borderColor: 'divider',\n boxShadow: 'none',\n },\n '&:focus-visible': {\n outline: '2px solid',\n outlineColor: 'primary.main',\n },\n '& .MuiDialog-paper:focus-visible': {\n outline: '2px solid',\n outlineColor: 'primary.main',\n },\n '& .MuiButton-outlined': {\n border: 'none',\n '&:hover': { bgcolor: 'transparent', border: 'none' },\n },\n }}\n >\n <Stack sx={{ gap: 24 }}>\n <Text variant=\"subtitle1\">{copy.description}</Text>\n\n <RadioGroup\n aria-label={copy.title}\n name=\"dismiss-type\"\n onChange={(e) => setSelected(e.target.value as DismissType)}\n sx={{ m: 0, p: 0 }}\n value={selected}\n >\n <Stack sx={{ gap: 16 }}>\n {(['once', 'always'] as const).map((k) => (\n <FormControlLabel\n key={k}\n value={k}\n control={<Radio inputProps={{ 'aria-label': copy[k].headline }} />}\n labelPlacement=\"start\"\n label={\n <Stack sx={{ gap: 4, flexGrow: 1 }}>\n <Text bold={true} variant=\"body1\">\n {copy[k].headline}\n </Text>\n <Text variant=\"subtitle2\">{copy[k].description}</Text>\n </Stack>\n }\n sx={{\n alignItems: 'center',\n borderRadius: '8px',\n justifyContent: 'space-between',\n m: 0,\n minHeight: 72,\n px: 16,\n py: 0,\n boxShadow: (theme) =>\n selected === k\n ? `inset 0 0 0 2px ${theme.palette.primary.main}`\n : `inset 0 0 0 1px ${theme.palette.divider}`,\n }}\n />\n ))}\n </Stack>\n </RadioGroup>\n </Stack>\n </Dialog>\n )\n },\n)\n\nexport default DismissInsightDialog\n"],"mappings":";;;;;;;;;;AAsBA,IAAa,IAAuB,EAAA,CACjC,EAAE,QAAA,GAAQ,SAAA,GAAS,WAAA,EAAA,MAA2C;AAC7D,QAAM,IAAO,EAAmB,EAAE,eAAe,SAC3C,CAAC,GAAU,CAAA,IAAe,EAAsB,MAAM;AAM5D,SAJA,EAAA,MAAgB;AACd,IAAI,KAAQ,EAAY,MAAM;AAAA,EAChC,GAAG,CAAC,CAAM,CAAC,GAEN,IAGH,gBAAA,EAAC,GAAD;AAAA,IACE,MAAM;AAAA,MAAE,OAAO,EAAK;AAAA,MAAO,YAAY,EAAK;AAAA,IAAW;AAAA,IAC/C,QAAA;AAAA,IACC,SAAA;AAAA,IACT,iBAAA,MAAuB,EAAU,CAAQ;AAAA,IACzC,aAAa,EAAK;AAAA,IAClB,eAAe,EAAK;AAAA,IACpB,IAAI;AAAA,MACF,4BAA4B,EAAE,IAAI,EAAE;AAAA,MACpC,mDAAmD;AAAA,QAAE,IAAI;AAAA,QAAI,IAAI;AAAA,MAAE;AAAA,MACnE,uEAAuE,EAAE,IAAI,IAAI;AAAA,MACjF,iCAAiC;AAAA,QAC/B,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA,mBAAmB;AAAA,QACjB,SAAS;AAAA,QACT,cAAc;AAAA,MAChB;AAAA,MACA,oCAAoC;AAAA,QAClC,SAAS;AAAA,QACT,cAAc;AAAA,MAChB;AAAA,MACA,yBAAyB;AAAA,QACvB,QAAQ;AAAA,QACR,WAAW;AAAA,UAAE,SAAS;AAAA,UAAe,QAAQ;AAAA,QAAO;AAAA,MACtD;AAAA,IACF;AAAA,IAEA,UAAA,gBAAA,EAAC,GAAD;AAAA,MAAO,IAAI,EAAE,KAAK,GAAG;AAAA,MAArB,UAAA,CACE,gBAAA,EAAC,GAAD;AAAA,QAAM,SAAQ;AAAA,QAAa,UAAA,EAAK;AAAA,MAAkB,CAAA,GAElD,gBAAA,EAAC,GAAD;AAAA,QACE,cAAY,EAAK;AAAA,QACjB,MAAK;AAAA,QACL,UAAA,CAAW,MAAM,EAAY,EAAE,OAAO,KAAoB;AAAA,QAC1D,IAAI;AAAA,UAAE,GAAG;AAAA,UAAG,GAAG;AAAA,QAAE;AAAA,QACjB,OAAO;AAAA,QAEP,UAAA,gBAAA,EAAC,GAAD;AAAA,UAAO,IAAI,EAAE,KAAK,GAAG;AAAA,UACjB,UAAA,CAAC,QAAQ,QAAQ,EAAY,IAAA,CAAK,MAClC,gBAAA,EAAC,GAAD;AAAA,YAEE,OAAO;AAAA,YACP,SAAS,gBAAA,EAAC,GAAD,EAAO,YAAY,EAAE,cAAc,EAAK,CAAA,EAAG,SAAS,EAAI,CAAA;AAAA,YACjE,gBAAe;AAAA,YACf,OACE,gBAAA,EAAC,GAAD;AAAA,cAAO,IAAI;AAAA,gBAAE,KAAK;AAAA,gBAAG,UAAU;AAAA,cAAE;AAAA,cAAjC,UAAA,CACE,gBAAA,EAAC,GAAD;AAAA,gBAAM,MAAM;AAAA,gBAAM,SAAQ;AAAA,gBACvB,UAAA,EAAK,CAAA,EAAG;AAAA,cACL,CAAA,GACN,gBAAA,EAAC,GAAD;AAAA,gBAAM,SAAQ;AAAA,gBAAa,UAAA,EAAK,CAAA,EAAG;AAAA,cAAkB,CAAA,CAChD;AAAA;YAET,IAAI;AAAA,cACF,YAAY;AAAA,cACZ,cAAc;AAAA,cACd,gBAAgB;AAAA,cAChB,GAAG;AAAA,cACH,WAAW;AAAA,cACX,IAAI;AAAA,cACJ,IAAI;AAAA,cACJ,WAAA,CAAY,MACV,MAAa,IACT,mBAAmB,EAAM,QAAQ,QAAQ,IAAA,KACzC,mBAAmB,EAAM,QAAQ,OAAA;AAAA,YACzC;AAAA,UACD,GAzBM,CAyBN,CACF;AAAA,QACI,CAAA;AAAA,MACG,CAAA,CACP;AAAA;EACD,CAAA,IA7EQ;AA+EpB,CACF"}
@@ -1,19 +1,8 @@
1
1
  export interface FeedbackBarProps {
2
- /** Controls the Grow transition; the host owns visibility. */
3
2
  show: boolean;
4
- /** Invoked when the user taps the follow-up survey action. */
5
3
  onTellUsMore: () => void;
6
4
  }
7
- /**
8
- * Confirmation bar shown after a user submits feedback on an insight. A success
9
- * Alert that grows into view with a "Tell us more?" survey action.
10
- *
11
- * Presentational — the host owns `show` and handles the follow-up via
12
- * `onTellUsMore`. Copy comes from `insights_feed.feedback_bar`.
13
- *
14
- * Kept mounted so the Grow transition plays on both enter and exit; the padded
15
- * wrapper animates with it and `unmountOnExit` reclaims the space once hidden.
16
- */
5
+ /** Confirmation bar shown after rating an insight. */
17
6
  export declare const FeedbackBar: (({ show, onTellUsMore }: FeedbackBarProps) => import("react/jsx-runtime").JSX.Element | null) & {
18
7
  displayName: string;
19
8
  };
@@ -1 +1 @@
1
- {"version":3,"file":"FeedbackBar.es.js","names":[],"sources":["../../../src/insights-v2/components/FeedbackBar.tsx"],"sourcesContent":["import Alert from '@mui/material/Alert'\nimport Box from '@mui/material/Box'\nimport Button from '@mui/material/Button'\nimport Grow from '@mui/material/Grow'\n\nimport { observer } from 'mobx-react-lite'\n\nimport { CheckCircle } from '@mxenabled/mx-icons'\nimport { Text } from '@mxenabled/mxui'\n\nimport { useGlobalCopyStore } from '../../common'\n\nexport interface FeedbackBarProps {\n /** Controls the Grow transition; the host owns visibility. */\n show: boolean\n /** Invoked when the user taps the follow-up survey action. */\n onTellUsMore: () => void\n}\n\n/**\n * Confirmation bar shown after a user submits feedback on an insight. A success\n * Alert that grows into view with a \"Tell us more?\" survey action.\n *\n * Presentational — the host owns `show` and handles the follow-up via\n * `onTellUsMore`. Copy comes from `insights_feed.feedback_bar`.\n *\n * Kept mounted so the Grow transition plays on both enter and exit; the padded\n * wrapper animates with it and `unmountOnExit` reclaims the space once hidden.\n */\nexport const FeedbackBar = observer(({ show, onTellUsMore }: FeedbackBarProps) => {\n const copy = useGlobalCopyStore().insights_feed?.feedback_bar\n\n if (!copy) return null\n\n return (\n <Grow appear in={show} unmountOnExit>\n <Box sx={{ pb: 16, px: 16 }}>\n <Alert\n action={\n <Button\n aria-label={copy.tell_us_more}\n color=\"inherit\"\n onClick={onTellUsMore}\n sx={{\n color: 'common.white',\n fontWeight: 600,\n lineHeight: '20px',\n ':hover': { bgcolor: 'grey.600' },\n }}\n >\n {copy.tell_us_more}\n </Button>\n }\n icon={<CheckCircle filled sx={{ color: 'success.light' }} />}\n severity=\"success\"\n sx={{\n alignItems: 'center',\n bgcolor: 'grey.700',\n border: 'none',\n display: 'flex',\n height: 56,\n justifyContent: 'space-between',\n '& .MuiAlert-action': { height: 44 },\n }}\n >\n <Text aria-live=\"assertive\" color=\"white\" sx={{ lineHeight: '20px' }} truncate={false}>\n {copy.feedback_sent}\n </Text>\n </Alert>\n </Box>\n </Grow>\n )\n})\n\nexport default FeedbackBar\n"],"mappings":";;;;;;;;;AA6BA,IAAa,IAAc,EAAA,CAAU,EAAE,MAAA,GAAM,cAAA,EAAA,MAAqC;AAChF,QAAM,IAAO,EAAmB,EAAE,eAAe;AAEjD,SAAK,IAGH,gBAAA,EAAC,GAAD;AAAA,IAAM,QAAA;AAAA,IAAO,IAAI;AAAA,IAAM,eAAA;AAAA,IACrB,UAAA,gBAAA,EAAC,GAAD;AAAA,MAAK,IAAI;AAAA,QAAE,IAAI;AAAA,QAAI,IAAI;AAAA,MAAG;AAAA,MACxB,UAAA,gBAAA,EAAC,GAAD;AAAA,QACE,QACE,gBAAA,EAAC,GAAD;AAAA,UACE,cAAY,EAAK;AAAA,UACjB,OAAM;AAAA,UACN,SAAS;AAAA,UACT,IAAI;AAAA,YACF,OAAO;AAAA,YACP,YAAY;AAAA,YACZ,YAAY;AAAA,YACZ,UAAU,EAAE,SAAS,WAAW;AAAA,UAClC;AAAA,UAEC,UAAA,EAAK;AAAA,QACA,CAAA;AAAA,QAEV,MAAM,gBAAA,EAAC,GAAD;AAAA,UAAa,QAAA;AAAA,UAAO,IAAI,EAAE,OAAO,gBAAgB;AAAA,QAAI,CAAA;AAAA,QAC3D,UAAS;AAAA,QACT,IAAI;AAAA,UACF,YAAY;AAAA,UACZ,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,gBAAgB;AAAA,UAChB,sBAAsB,EAAE,QAAQ,GAAG;AAAA,QACrC;AAAA,QAEA,UAAA,gBAAA,EAAC,GAAD;AAAA,UAAM,aAAU;AAAA,UAAY,OAAM;AAAA,UAAQ,IAAI,EAAE,YAAY,OAAO;AAAA,UAAG,UAAU;AAAA,UAC7E,UAAA,EAAK;AAAA,QACF,CAAA;AAAA,MACD,CAAA;AAAA,IACJ,CAAA;AAAA,EACD,CAAA,IAtCU;AAwCpB,CAAC"}
1
+ {"version":3,"file":"FeedbackBar.es.js","names":[],"sources":["../../../src/insights-v2/components/FeedbackBar.tsx"],"sourcesContent":["import Alert from '@mui/material/Alert'\nimport Box from '@mui/material/Box'\nimport Button from '@mui/material/Button'\nimport Grow from '@mui/material/Grow'\n\nimport { observer } from 'mobx-react-lite'\n\nimport { CheckCircle } from '@mxenabled/mx-icons'\nimport { Text } from '@mxenabled/mxui'\n\nimport { useGlobalCopyStore } from '../../common'\n\nexport interface FeedbackBarProps {\n show: boolean\n onTellUsMore: () => void\n}\n\n/** Confirmation bar shown after rating an insight. */\nexport const FeedbackBar = observer(({ show, onTellUsMore }: FeedbackBarProps) => {\n const copy = useGlobalCopyStore().insights_feed?.feedback_bar\n\n if (!copy) return null\n\n return (\n <Grow appear in={show} unmountOnExit>\n <Box sx={{ pb: 16, px: 16 }}>\n <Alert\n action={\n <Button\n aria-label={copy.tell_us_more}\n color=\"inherit\"\n onClick={onTellUsMore}\n sx={{\n color: 'common.white',\n fontWeight: 600,\n lineHeight: '20px',\n ':hover': { bgcolor: 'grey.600' },\n }}\n >\n {copy.tell_us_more}\n </Button>\n }\n icon={<CheckCircle filled sx={{ color: 'success.light' }} />}\n severity=\"success\"\n sx={{\n alignItems: 'center',\n bgcolor: 'grey.700',\n border: 'none',\n display: 'flex',\n height: 56,\n justifyContent: 'space-between',\n '& .MuiAlert-action': { height: 44 },\n }}\n >\n <Text aria-live=\"assertive\" color=\"white\" sx={{ lineHeight: '20px' }} truncate={false}>\n {copy.feedback_sent}\n </Text>\n </Alert>\n </Box>\n </Grow>\n )\n})\n\nexport default FeedbackBar\n"],"mappings":";;;;;;;;;AAkBA,IAAa,IAAc,EAAA,CAAU,EAAE,MAAA,GAAM,cAAA,EAAA,MAAqC;AAChF,QAAM,IAAO,EAAmB,EAAE,eAAe;AAEjD,SAAK,IAGH,gBAAA,EAAC,GAAD;AAAA,IAAM,QAAA;AAAA,IAAO,IAAI;AAAA,IAAM,eAAA;AAAA,IACrB,UAAA,gBAAA,EAAC,GAAD;AAAA,MAAK,IAAI;AAAA,QAAE,IAAI;AAAA,QAAI,IAAI;AAAA,MAAG;AAAA,MACxB,UAAA,gBAAA,EAAC,GAAD;AAAA,QACE,QACE,gBAAA,EAAC,GAAD;AAAA,UACE,cAAY,EAAK;AAAA,UACjB,OAAM;AAAA,UACN,SAAS;AAAA,UACT,IAAI;AAAA,YACF,OAAO;AAAA,YACP,YAAY;AAAA,YACZ,YAAY;AAAA,YACZ,UAAU,EAAE,SAAS,WAAW;AAAA,UAClC;AAAA,UAEC,UAAA,EAAK;AAAA,QACA,CAAA;AAAA,QAEV,MAAM,gBAAA,EAAC,GAAD;AAAA,UAAa,QAAA;AAAA,UAAO,IAAI,EAAE,OAAO,gBAAgB;AAAA,QAAI,CAAA;AAAA,QAC3D,UAAS;AAAA,QACT,IAAI;AAAA,UACF,YAAY;AAAA,UACZ,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,gBAAgB;AAAA,UAChB,sBAAsB,EAAE,QAAQ,GAAG;AAAA,QACrC;AAAA,QAEA,UAAA,gBAAA,EAAC,GAAD;AAAA,UAAM,aAAU;AAAA,UAAY,OAAM;AAAA,UAAQ,IAAI,EAAE,YAAY,OAAO;AAAA,UAAG,UAAU;AAAA,UAC7E,UAAA,EAAK;AAAA,QACF,CAAA;AAAA,MACD,CAAA;AAAA,IACJ,CAAA;AAAA,EACD,CAAA,IAtCU;AAwCpB,CAAC"}