@mx-cartographer/experiences 9.4.15 → 9.4.17

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 (37) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/common/components/dialog/Dialog.es.js +36 -36
  3. package/dist/common/components/dialog/Dialog.es.js.map +1 -1
  4. package/dist/core/types/localization/InsightsFeedCopy.d.ts +67 -0
  5. package/dist/core/types/localization/index.d.ts +1 -1
  6. package/dist/insights-v2/beatActions.d.ts +55 -0
  7. package/dist/insights-v2/beatActions.es.js +12 -0
  8. package/dist/insights-v2/beatActions.es.js.map +1 -0
  9. package/dist/insights-v2/components/BaseLayout.d.ts +7 -1
  10. package/dist/insights-v2/components/BaseLayout.es.js +102 -68
  11. package/dist/insights-v2/components/BaseLayout.es.js.map +1 -1
  12. package/dist/insights-v2/components/DismissInsightDialog.d.ts +18 -0
  13. package/dist/insights-v2/components/DismissInsightDialog.es.js +109 -0
  14. package/dist/insights-v2/components/DismissInsightDialog.es.js.map +1 -0
  15. package/dist/insights-v2/components/FeedbackBar.d.ts +20 -0
  16. package/dist/insights-v2/components/FeedbackBar.es.js +64 -0
  17. package/dist/insights-v2/components/FeedbackBar.es.js.map +1 -0
  18. package/dist/insights-v2/components/FeedbackDialog.d.ts +37 -0
  19. package/dist/insights-v2/components/FeedbackDialog.es.js +92 -0
  20. package/dist/insights-v2/components/FeedbackDialog.es.js.map +1 -0
  21. package/dist/insights-v2/components/Header.es.js +23 -33
  22. package/dist/insights-v2/components/Header.es.js.map +1 -1
  23. package/dist/insights-v2/components/HiddenConfirmationCard.d.ts +20 -0
  24. package/dist/insights-v2/components/HiddenConfirmationCard.es.js +123 -0
  25. package/dist/insights-v2/components/HiddenConfirmationCard.es.js.map +1 -0
  26. package/dist/insights-v2/components/InsightOptionsMenu.d.ts +10 -0
  27. package/dist/insights-v2/components/InsightOptionsMenu.es.js +54 -0
  28. package/dist/insights-v2/components/InsightOptionsMenu.es.js.map +1 -0
  29. package/dist/insights-v2/components/OverflowMenu.d.ts +32 -0
  30. package/dist/insights-v2/components/OverflowMenu.es.js +73 -0
  31. package/dist/insights-v2/components/OverflowMenu.es.js.map +1 -0
  32. package/dist/insights-v2/hooks/useBeatFeedbackFlow.d.ts +44 -0
  33. package/dist/insights-v2/hooks/useBeatFeedbackFlow.es.js +73 -0
  34. package/dist/insights-v2/hooks/useBeatFeedbackFlow.es.js.map +1 -0
  35. package/dist/insights-v2/index.d.ts +7 -0
  36. package/dist/insights-v2/index.es.js +71 -57
  37. package/package.json +1 -1
@@ -0,0 +1,109 @@
1
+ import { useGlobalCopyStore as m } from "../../common/context/hooks.es.js";
2
+ import u from "../../common/components/dialog/Dialog.es.js";
3
+ import { useEffect as b, useState as f } from "react";
4
+ import { observer as x } from "mobx-react-lite";
5
+ import a from "@mui/material/Stack";
6
+ import { Text as l } from "@mxenabled/mxui";
7
+ import { jsx as r, jsxs as s } from "react/jsx-runtime";
8
+ import g from "@mui/material/FormControlLabel";
9
+ import h from "@mui/material/Radio";
10
+ import y from "@mui/material/RadioGroup";
11
+ var R = x(({ isOpen: i, onClose: d, onDismiss: c }) => {
12
+ const o = m().insights_feed?.dismiss, [t, n] = f("once");
13
+ return b(() => {
14
+ i && n("once");
15
+ }, [i]), o ? /* @__PURE__ */ r(u, {
16
+ copy: {
17
+ title: o.title,
18
+ close_aria: o.close_aria
19
+ },
20
+ isOpen: i,
21
+ onClose: d,
22
+ onPrimaryAction: () => c(t),
23
+ primaryText: o.confirm,
24
+ secondaryText: o.cancel,
25
+ sx: {
26
+ "& .MuiDialogContent-root": { py: 0 },
27
+ "& .MuiDialog-paperScrollPaper > div:first-child": {
28
+ pt: 24,
29
+ pb: 8
30
+ },
31
+ "& .MuiDialog-paperScrollPaper > div:first-child .MuiIconButton-root": { my: -10 },
32
+ "& .MuiDialog-paperScrollPaper": {
33
+ bgcolor: "background.paper",
34
+ border: "1px solid",
35
+ borderColor: "divider",
36
+ boxShadow: "none"
37
+ },
38
+ "&:focus-visible": {
39
+ outline: "2px solid",
40
+ outlineColor: "primary.main"
41
+ },
42
+ "& .MuiDialog-paper:focus-visible": {
43
+ outline: "2px solid",
44
+ outlineColor: "primary.main"
45
+ },
46
+ "& .MuiButton-outlined": {
47
+ border: "none",
48
+ "&:hover": {
49
+ bgcolor: "transparent",
50
+ border: "none"
51
+ }
52
+ }
53
+ },
54
+ children: /* @__PURE__ */ s(a, {
55
+ sx: { gap: 24 },
56
+ children: [/* @__PURE__ */ r(l, {
57
+ variant: "subtitle1",
58
+ children: o.description
59
+ }), /* @__PURE__ */ r(y, {
60
+ "aria-label": o.title,
61
+ name: "dismiss-type",
62
+ onChange: (e) => n(e.target.value),
63
+ sx: {
64
+ m: 0,
65
+ p: 0
66
+ },
67
+ value: t,
68
+ children: /* @__PURE__ */ r(a, {
69
+ sx: { gap: 16 },
70
+ children: ["once", "always"].map((e) => /* @__PURE__ */ r(g, {
71
+ value: e,
72
+ control: /* @__PURE__ */ r(h, { inputProps: { "aria-label": o[e].headline } }),
73
+ labelPlacement: "start",
74
+ label: /* @__PURE__ */ s(a, {
75
+ sx: {
76
+ gap: 4,
77
+ flexGrow: 1
78
+ },
79
+ children: [/* @__PURE__ */ r(l, {
80
+ bold: !0,
81
+ variant: "body1",
82
+ children: o[e].headline
83
+ }), /* @__PURE__ */ r(l, {
84
+ variant: "subtitle2",
85
+ children: o[e].description
86
+ })]
87
+ }),
88
+ sx: {
89
+ alignItems: "center",
90
+ borderRadius: "8px",
91
+ justifyContent: "space-between",
92
+ m: 0,
93
+ minHeight: 72,
94
+ px: 16,
95
+ py: 0,
96
+ boxShadow: (p) => t === e ? `inset 0 0 0 2px ${p.palette.primary.main}` : `inset 0 0 0 1px ${p.palette.divider}`
97
+ }
98
+ }, e))
99
+ })
100
+ })]
101
+ })
102
+ }) : null;
103
+ });
104
+ export {
105
+ R as DismissInsightDialog,
106
+ R as default
107
+ };
108
+
109
+ //# sourceMappingURL=DismissInsightDialog.es.js.map
@@ -0,0 +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":";;;;;;;;;;AA6BA,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;AAO5D,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,IAIpB,IAAI;AAAA,MAEF,4BAA4B,EAAE,IAAI,EAAE;AAAA,MAEpC,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,MAGA,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,cAEJ,WAAA,CAAY,MACV,MAAa,IACT,mBAAmB,EAAM,QAAQ,QAAQ,IAAA,KACzC,mBAAmB,EAAM,QAAQ,OAAA;AAAA,YACzC;AAAA,UACD,GA1BM,CA0BN,CACF;AAAA,QACI,CAAA;AAAA,MACG,CAAA,CACP;AAAA;EACD,CAAA,IArFQ;AAuFpB,CACF"}
@@ -0,0 +1,20 @@
1
+ export interface FeedbackBarProps {
2
+ /** Controls the Grow transition; the host owns visibility. */
3
+ show: boolean;
4
+ /** Invoked when the user taps the follow-up survey action. */
5
+ onTellUsMore: () => void;
6
+ }
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
+ */
17
+ export declare const FeedbackBar: (({ show, onTellUsMore }: FeedbackBarProps) => import("react/jsx-runtime").JSX.Element | null) & {
18
+ displayName: string;
19
+ };
20
+ export default FeedbackBar;
@@ -0,0 +1,64 @@
1
+ import { useGlobalCopyStore as i } from "../../common/context/hooks.es.js";
2
+ import { observer as l } from "mobx-react-lite";
3
+ import { Text as n } from "@mxenabled/mxui";
4
+ import c from "@mui/material/Button";
5
+ import { CheckCircle as s } from "@mxenabled/mx-icons";
6
+ import { jsx as e } from "react/jsx-runtime";
7
+ import a from "@mui/material/Box";
8
+ import m from "@mui/material/Alert";
9
+ import p from "@mui/material/Grow";
10
+ var v = l(({ show: o, onTellUsMore: t }) => {
11
+ const r = i().insights_feed?.feedback_bar;
12
+ return r ? /* @__PURE__ */ e(p, {
13
+ appear: !0,
14
+ in: o,
15
+ unmountOnExit: !0,
16
+ children: /* @__PURE__ */ e(a, {
17
+ sx: {
18
+ pb: 16,
19
+ px: 16
20
+ },
21
+ children: /* @__PURE__ */ e(m, {
22
+ action: /* @__PURE__ */ e(c, {
23
+ "aria-label": r.tell_us_more,
24
+ color: "inherit",
25
+ onClick: t,
26
+ sx: {
27
+ color: "common.white",
28
+ fontWeight: 600,
29
+ lineHeight: "20px",
30
+ ":hover": { bgcolor: "grey.600" }
31
+ },
32
+ children: r.tell_us_more
33
+ }),
34
+ icon: /* @__PURE__ */ e(s, {
35
+ filled: !0,
36
+ sx: { color: "success.light" }
37
+ }),
38
+ severity: "success",
39
+ sx: {
40
+ alignItems: "center",
41
+ bgcolor: "grey.700",
42
+ border: "none",
43
+ display: "flex",
44
+ height: 56,
45
+ justifyContent: "space-between",
46
+ "& .MuiAlert-action": { height: 44 }
47
+ },
48
+ children: /* @__PURE__ */ e(n, {
49
+ "aria-live": "assertive",
50
+ color: "white",
51
+ sx: { lineHeight: "20px" },
52
+ truncate: !1,
53
+ children: r.feedback_sent
54
+ })
55
+ })
56
+ })
57
+ }) : null;
58
+ });
59
+ export {
60
+ v as FeedbackBar,
61
+ v as default
62
+ };
63
+
64
+ //# sourceMappingURL=FeedbackBar.es.js.map
@@ -0,0 +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"}
@@ -0,0 +1,37 @@
1
+ export interface FeedbackDialogProps {
2
+ /** Dialog title. */
3
+ title: string;
4
+ /** Available feedback reasons. The last option reveals the detail field. */
5
+ options: string[];
6
+ /** Max characters for the detail text field (enforced on the input). */
7
+ characterLimit?: number;
8
+ /** Localized helper text shown under the detail field (e.g. "250 Character Limit"). */
9
+ characterLimitLabel?: string;
10
+ /** Whether the dialog is open. */
11
+ isOpen: boolean;
12
+ /** Invoked on primary action (Submit); parent owns analytics + dispatch. */
13
+ onSubmit: (option: string, detail?: string) => void;
14
+ /** Invoked on close (X, Cancel, or Submit); parent clears dialog state. */
15
+ onClose: () => void;
16
+ /** Button text for secondary (Back/Cancel) action. */
17
+ secondaryText: string;
18
+ /** Button text for primary (Submit) action. */
19
+ primaryText: string;
20
+ /** ARIA label for close button. */
21
+ closeAriaLabel: string;
22
+ }
23
+ /**
24
+ * Generic feedback survey dialog for collecting reasons and optional detail.
25
+ * Presentational — the parent owns all copy, option definitions, and callback logic.
26
+ *
27
+ * This component can be used by any feature that needs to ask users for feedback.
28
+ * Examples: rating an insight, dismissing a notification, rating a recommendation.
29
+ *
30
+ * The dialog is a single-select radio list of reasons; selecting the last option
31
+ * ("Other") reveals a multiline text field. Submit is disabled until a valid
32
+ * answer exists.
33
+ *
34
+ * Figma: 287:20484 (options only) / 287:20566 (with text field).
35
+ */
36
+ declare const FeedbackDialog: ({ isOpen, onClose, onSubmit, title, options, characterLimit, characterLimitLabel, secondaryText, primaryText, closeAriaLabel, }: FeedbackDialogProps) => import("react/jsx-runtime").JSX.Element | null;
37
+ export default FeedbackDialog;
@@ -0,0 +1,92 @@
1
+ import S from "../../common/components/dialog/Dialog.es.js";
2
+ import { useState as c } from "react";
3
+ import y from "@mui/material/Stack";
4
+ import { Text as D } from "@mxenabled/mxui";
5
+ import { jsx as e, jsxs as d } from "react/jsx-runtime";
6
+ import M from "@mui/material/FormControlLabel";
7
+ import F from "@mui/material/TextField";
8
+ import R from "@mui/material/Radio";
9
+ import k from "@mui/material/FormControl";
10
+ import I from "@mui/material/RadioGroup";
11
+ var P = 250, W = ({ isOpen: p, onClose: g, onSubmit: b, title: i, options: r, characterLimit: f = P, characterLimitLabel: n, secondaryText: h, primaryText: x, closeAriaLabel: v }) => {
12
+ const [t, m] = c(""), [l, s] = c("");
13
+ if (r.length === 0) return null;
14
+ const a = t === r[r.length - 1], C = !t || a && !l.trim(), u = () => {
15
+ m(""), s("");
16
+ };
17
+ return /* @__PURE__ */ d(S, {
18
+ copy: {
19
+ title: i,
20
+ close_aria: v
21
+ },
22
+ disablePrimaryButton: C,
23
+ isOpen: p,
24
+ onClose: () => {
25
+ u(), g();
26
+ },
27
+ onPrimaryAction: () => {
28
+ b(t, a ? l.trim() : void 0), u();
29
+ },
30
+ primaryText: x,
31
+ secondaryText: h,
32
+ sx: {
33
+ "& .MuiDialogContent-root": { py: 0 },
34
+ "& .MuiDialog-paperScrollPaper": { bgcolor: "background.paper" },
35
+ "& .MuiDialog-paper": {
36
+ outline: "none",
37
+ "&:focus-visible": {
38
+ outline: "2px solid",
39
+ outlineColor: "primary.main"
40
+ }
41
+ },
42
+ "& .MuiButton-outlined": {
43
+ border: "none",
44
+ "&:hover": {
45
+ bgcolor: "transparent",
46
+ border: "none"
47
+ }
48
+ }
49
+ },
50
+ children: [/* @__PURE__ */ e(k, { children: /* @__PURE__ */ e(I, {
51
+ "aria-label": i,
52
+ name: "feedback-radio-group",
53
+ onChange: (o) => m(o.target.value),
54
+ value: t,
55
+ children: r.map((o) => /* @__PURE__ */ e(M, {
56
+ control: /* @__PURE__ */ e(R, { sx: { "& .MuiSvgIcon-root": { fontSize: 22 } } }),
57
+ label: o,
58
+ sx: { "& .MuiFormControlLabel-label": {
59
+ color: "text.primary",
60
+ fontSize: 15
61
+ } },
62
+ value: o
63
+ }, o))
64
+ }) }), a && /* @__PURE__ */ d(y, {
65
+ sx: {
66
+ gap: 3,
67
+ mt: 4
68
+ },
69
+ children: [/* @__PURE__ */ e(F, {
70
+ autoFocus: !0,
71
+ maxRows: 4,
72
+ minRows: 4,
73
+ multiline: !0,
74
+ onChange: (o) => s(o.target.value),
75
+ slotProps: { htmlInput: { maxLength: f } },
76
+ value: l
77
+ }), n && /* @__PURE__ */ e(D, {
78
+ sx: {
79
+ color: "text.secondary",
80
+ fontWeight: 400
81
+ },
82
+ variant: "subtitle2",
83
+ children: n
84
+ })]
85
+ })]
86
+ });
87
+ };
88
+ export {
89
+ W as default
90
+ };
91
+
92
+ //# sourceMappingURL=FeedbackDialog.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FeedbackDialog.es.js","names":[],"sources":["../../../src/insights-v2/components/FeedbackDialog.tsx"],"sourcesContent":["import { useState } from 'react'\n\nimport FormControl from '@mui/material/FormControl'\nimport FormControlLabel from '@mui/material/FormControlLabel'\nimport Radio from '@mui/material/Radio'\nimport RadioGroup from '@mui/material/RadioGroup'\nimport Stack from '@mui/material/Stack'\nimport TextField from '@mui/material/TextField'\n\nimport { Text } from '@mxenabled/mxui'\n\nimport { Dialog } from '../../common'\n\nconst CHARACTER_LIMIT = 250\n\nexport interface FeedbackDialogProps {\n /** Dialog title. */\n title: string\n /** Available feedback reasons. The last option reveals the detail field. */\n options: string[]\n /** Max characters for the detail text field (enforced on the input). */\n characterLimit?: number\n /** Localized helper text shown under the detail field (e.g. \"250 Character Limit\"). */\n characterLimitLabel?: string\n /** Whether the dialog is open. */\n isOpen: boolean\n /** Invoked on primary action (Submit); parent owns analytics + dispatch. */\n onSubmit: (option: string, detail?: string) => void\n /** Invoked on close (X, Cancel, or Submit); parent clears dialog state. */\n onClose: () => void\n /** Button text for secondary (Back/Cancel) action. */\n secondaryText: string\n /** Button text for primary (Submit) action. */\n primaryText: string\n /** ARIA label for close button. */\n closeAriaLabel: string\n}\n\n/**\n * Generic feedback survey dialog for collecting reasons and optional detail.\n * Presentational — the parent owns all copy, option definitions, and callback logic.\n *\n * This component can be used by any feature that needs to ask users for feedback.\n * Examples: rating an insight, dismissing a notification, rating a recommendation.\n *\n * The dialog is a single-select radio list of reasons; selecting the last option\n * (\"Other\") reveals a multiline text field. Submit is disabled until a valid\n * answer exists.\n *\n * Figma: 287:20484 (options only) / 287:20566 (with text field).\n */\nconst FeedbackDialog = ({\n isOpen,\n onClose,\n onSubmit,\n title,\n options,\n characterLimit = CHARACTER_LIMIT,\n characterLimitLabel,\n secondaryText,\n primaryText,\n closeAriaLabel,\n}: FeedbackDialogProps) => {\n const [selected, setSelected] = useState('')\n const [detail, setDetail] = useState('')\n\n if (options.length === 0) return null\n\n const isOther = selected === options[options.length - 1]\n const isSubmitDisabled = !selected || (isOther && !detail.trim())\n\n const reset = () => {\n setSelected('')\n setDetail('')\n }\n\n const handleClose = () => {\n reset()\n onClose()\n }\n\n const handleSubmit = () => {\n onSubmit(selected, isOther ? detail.trim() : undefined)\n reset()\n }\n\n return (\n <Dialog\n copy={{ title, close_aria: closeAriaLabel }}\n disablePrimaryButton={isSubmitDisabled}\n isOpen={isOpen}\n onClose={handleClose}\n onPrimaryAction={handleSubmit}\n primaryText={primaryText}\n secondaryText={secondaryText}\n sx={{\n // Radio section has no vertical padding per Figma; keep horizontal.\n '& .MuiDialogContent-root': { py: 0 },\n // White surface, overriding the shared Dialog's default grey\n // (background.default) for this dialog only — the shared component is untouched.\n '& .MuiDialog-paperScrollPaper': { bgcolor: 'background.paper' },\n // Paper receives focus on open; hide the browser's default outline\n // while keeping focus for keyboard / screen-reader accessibility.\n '& .MuiDialog-paper': {\n outline: 'none',\n '&:focus-visible': { outline: '2px solid', outlineColor: 'primary.main' },\n },\n // The shared Dialog footer defaults the secondary (Back) button to\n // variant=\"outlined\"; Figma shows it as a plain text button.\n '& .MuiButton-outlined': {\n border: 'none',\n '&:hover': { bgcolor: 'transparent', border: 'none' },\n },\n }}\n >\n <FormControl>\n <RadioGroup\n aria-label={title}\n name=\"feedback-radio-group\"\n onChange={(e) => setSelected(e.target.value)}\n value={selected}\n >\n {options.map((option) => (\n <FormControlLabel\n control={<Radio sx={{ '& .MuiSvgIcon-root': { fontSize: 22 } }} />}\n key={option}\n label={option}\n sx={{\n '& .MuiFormControlLabel-label': {\n color: 'text.primary',\n fontSize: 15,\n },\n }}\n value={option}\n />\n ))}\n </RadioGroup>\n </FormControl>\n\n {isOther && (\n <Stack sx={{ gap: 3, mt: 4 }}>\n <TextField\n autoFocus\n maxRows={4}\n minRows={4}\n multiline={true}\n onChange={(e) => setDetail(e.target.value)}\n slotProps={{ htmlInput: { maxLength: characterLimit } }}\n value={detail}\n />\n {characterLimitLabel && (\n <Text sx={{ color: 'text.secondary', fontWeight: 400 }} variant=\"subtitle2\">\n {characterLimitLabel}\n </Text>\n )}\n </Stack>\n )}\n </Dialog>\n )\n}\n\nexport default FeedbackDialog\n"],"mappings":";;;;;;;;;;AAaA,IAAM,IAAkB,KAsClB,IAAA,CAAkB,EACtB,QAAA,GACA,SAAA,GACA,UAAA,GACA,OAAA,GACA,SAAA,GACA,gBAAA,IAAiB,GACjB,qBAAA,GACA,eAAA,GACA,aAAA,GACA,gBAAA,EAAA,MACyB;AACzB,QAAM,CAAC,GAAU,CAAA,IAAe,EAAS,EAAE,GACrC,CAAC,GAAQ,CAAA,IAAa,EAAS,EAAE;AAEvC,MAAI,EAAQ,WAAW,EAAG,QAAO;AAEjC,QAAM,IAAU,MAAa,EAAQ,EAAQ,SAAS,CAAA,GAChD,IAAmB,CAAC,KAAa,KAAW,CAAC,EAAO,KAAK,GAEzD,IAAA,MAAc;AAClB,IAAA,EAAY,EAAE,GACd,EAAU,EAAE;AAAA,EACd;AAYA,SACE,gBAAA,EAAC,GAAD;AAAA,IACE,MAAM;AAAA,MAAE,OAAA;AAAA,MAAO,YAAY;AAAA,IAAe;AAAA,IAC1C,sBAAsB;AAAA,IACd,QAAA;AAAA,IACR,SAfE,MAAoB;AACxB,MAAA,EAAM,GACN,EAAQ;AAAA,IACV;AAAA,IAaI,iBAXE,MAAqB;AACzB,MAAA,EAAS,GAAU,IAAU,EAAO,KAAK,IAAI,MAAS,GACtD,EAAM;AAAA,IACR;AAAA,IASiB,aAAA;AAAA,IACE,eAAA;AAAA,IACf,IAAI;AAAA,MAEF,4BAA4B,EAAE,IAAI,EAAE;AAAA,MAGpC,iCAAiC,EAAE,SAAS,mBAAmB;AAAA,MAG/D,sBAAsB;AAAA,QACpB,SAAS;AAAA,QACT,mBAAmB;AAAA,UAAE,SAAS;AAAA,UAAa,cAAc;AAAA,QAAe;AAAA,MAC1E;AAAA,MAGA,yBAAyB;AAAA,QACvB,QAAQ;AAAA,QACR,WAAW;AAAA,UAAE,SAAS;AAAA,UAAe,QAAQ;AAAA,QAAO;AAAA,MACtD;AAAA,IACF;AAAA,IA1BF,UAAA,CA4BE,gBAAA,EAAC,GAAD,EAAA,UACE,gBAAA,EAAC,GAAD;AAAA,MACE,cAAY;AAAA,MACZ,MAAK;AAAA,MACL,UAAA,CAAW,MAAM,EAAY,EAAE,OAAO,KAAK;AAAA,MAC3C,OAAO;AAAA,MAEN,UAAA,EAAQ,IAAA,CAAK,MACZ,gBAAA,EAAC,GAAD;AAAA,QACE,SAAS,gBAAA,EAAC,GAAD,EAAO,IAAI,EAAE,sBAAsB,EAAE,UAAU,GAAG,EAAE,EAAI,CAAA;AAAA,QAEjE,OAAO;AAAA,QACP,IAAI,EACF,gCAAgC;AAAA,UAC9B,OAAO;AAAA,UACP,UAAU;AAAA,QACZ,EACF;AAAA,QACA,OAAO;AAAA,MACR,GATM,CASN,CACF;AAAA,IACS,CAAA,EACD,CAAA,GAEZ,KACC,gBAAA,EAAC,GAAD;AAAA,MAAO,IAAI;AAAA,QAAE,KAAK;AAAA,QAAG,IAAI;AAAA,MAAE;AAAA,MAA3B,UAAA,CACE,gBAAA,EAAC,GAAD;AAAA,QACE,WAAA;AAAA,QACA,SAAS;AAAA,QACT,SAAS;AAAA,QACT,WAAW;AAAA,QACX,UAAA,CAAW,MAAM,EAAU,EAAE,OAAO,KAAK;AAAA,QACzC,WAAW,EAAE,WAAW,EAAE,WAAW,EAAe,EAAE;AAAA,QACtD,OAAO;AAAA,MACR,CAAA,GACA,KACC,gBAAA,EAAC,GAAD;AAAA,QAAM,IAAI;AAAA,UAAE,OAAO;AAAA,UAAkB,YAAY;AAAA,QAAI;AAAA,QAAG,SAAQ;AAAA,QAC7D,UAAA;AAAA,MACG,CAAA,CAEH;AAAA,IAEH,CAAA,CAAA;AAAA;AAEZ"}
@@ -1,41 +1,31 @@
1
- import p from "./SubHeader.es.js";
2
- import o from "@mui/material/Stack";
3
- import { H3 as a } from "@mxenabled/mxui";
4
- import { MoreHoriz as m } from "@mxenabled/mx-icons";
5
- import { jsx as r, jsxs as t } from "react/jsx-runtime";
6
- import s from "@mui/material/IconButton";
7
- var H = ({ isMini: i, subtitle: e, title: n }) => /* @__PURE__ */ t(o, {
8
- sx: {
9
- gap: 4,
10
- pb: 12,
11
- pl: 16,
12
- pr: 16,
13
- pt: 16
14
- },
15
- children: [/* @__PURE__ */ t(o, {
1
+ import m from "./SubHeader.es.js";
2
+ import { useBeatActions as s } from "../beatActions.es.js";
3
+ import { InsightOptionsMenu as a } from "./InsightOptionsMenu.es.js";
4
+ import t from "@mui/material/Stack";
5
+ import { H3 as c } from "@mxenabled/mxui";
6
+ import { jsx as r, jsxs as o } from "react/jsx-runtime";
7
+ var g = ({ isMini: n, subtitle: e, title: i }) => {
8
+ const { onMenuAction: p } = s();
9
+ return /* @__PURE__ */ o(t, {
16
10
  sx: {
17
- alignItems: "center",
18
- flexDirection: "row",
19
- justifyContent: "space-between"
11
+ gap: 4,
12
+ pb: 12,
13
+ pl: 16,
14
+ pr: 16,
15
+ pt: 16
20
16
  },
21
- children: [/* @__PURE__ */ r(a, { children: n }), !i && /* @__PURE__ */ r(s, {
22
- "aria-label": "More Options",
23
- onClick: () => {
24
- },
17
+ children: [/* @__PURE__ */ o(t, {
25
18
  sx: {
26
- minHeight: 24,
27
- p: 0,
28
- minWidth: 24
19
+ alignItems: "center",
20
+ flexDirection: "row",
21
+ justifyContent: "space-between"
29
22
  },
30
- children: /* @__PURE__ */ r(m, {
31
- size: 24,
32
- sx: { color: "neutral.dark" }
33
- })
34
- })]
35
- }), e && /* @__PURE__ */ r(p, { subtitle: e })]
36
- });
23
+ children: [/* @__PURE__ */ r(c, { children: i }), !n && p && /* @__PURE__ */ r(a, {})]
24
+ }), e && /* @__PURE__ */ r(m, { subtitle: e })]
25
+ });
26
+ };
37
27
  export {
38
- H as default
28
+ g as default
39
29
  };
40
30
 
41
31
  //# sourceMappingURL=Header.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Header.es.js","names":[],"sources":["../../../src/insights-v2/components/Header.tsx"],"sourcesContent":["import IconButton from '@mui/material/IconButton'\nimport Stack from '@mui/material/Stack'\n\nimport { H3 } from '@mxenabled/mxui'\nimport { MoreHoriz } from '@mxenabled/mx-icons'\n\nimport SubHeader from './SubHeader'\nimport type { Subtitle } from '../../core'\n\ninterface HeaderProps {\n isMini: boolean\n subtitle?: Subtitle\n title: string\n}\n\nconst Header = ({ isMini, subtitle, title }: HeaderProps) => {\n const handleMoreOptions = () => {}\n\n return (\n <Stack sx={{ gap: 4, pb: 12, pl: 16, pr: 16, pt: 16 }}>\n <Stack sx={{ alignItems: 'center', flexDirection: 'row', justifyContent: 'space-between' }}>\n <H3>{title}</H3>\n {!isMini && (\n <IconButton\n aria-label=\"More Options\" // TODO: Localize\n onClick={handleMoreOptions}\n sx={{ minHeight: 24, p: 0, minWidth: 24 }}\n >\n <MoreHoriz size={24} sx={{ color: 'neutral.dark' }} />\n </IconButton>\n )}\n </Stack>\n\n {/* Sub Header */}\n {subtitle && <SubHeader subtitle={subtitle} />}\n </Stack>\n )\n}\n\nexport default Header\n"],"mappings":";;;;;;AAeA,IAAM,IAAA,CAAU,EAAE,QAAA,GAAQ,UAAA,GAAU,OAAA,EAAA,MAIhC,gBAAA,EAAC,GAAD;AAAA,EAAO,IAAI;AAAA,IAAE,KAAK;AAAA,IAAG,IAAI;AAAA,IAAI,IAAI;AAAA,IAAI,IAAI;AAAA,IAAI,IAAI;AAAA,EAAG;AAAA,EAApD,UAAA,CACE,gBAAA,EAAC,GAAD;AAAA,IAAO,IAAI;AAAA,MAAE,YAAY;AAAA,MAAU,eAAe;AAAA,MAAO,gBAAgB;AAAA,IAAgB;AAAA,IAAzF,UAAA,CACE,gBAAA,EAAC,GAAD,EAAA,UAAK,EAAU,CAAA,GACd,CAAC,KACA,gBAAA,EAAC,GAAD;AAAA,MACE,cAAW;AAAA,MACX,SATJ,MAA0B;AAAA,MAAC;AAAA,MAUvB,IAAI;AAAA,QAAE,WAAW;AAAA,QAAI,GAAG;AAAA,QAAG,UAAU;AAAA,MAAG;AAAA,MAExC,UAAA,gBAAA,EAAC,GAAD;AAAA,QAAW,MAAM;AAAA,QAAI,IAAI,EAAE,OAAO,eAAe;AAAA,MAAI,CAAA;AAAA,IAC3C,CAAA,CAET;AAAA,EAGN,CAAA,GAAA,KAAY,gBAAA,EAAC,GAAD,EAAqB,UAAA,EAAW,CAAA,CACxC"}
1
+ {"version":3,"file":"Header.es.js","names":[],"sources":["../../../src/insights-v2/components/Header.tsx"],"sourcesContent":["import Stack from '@mui/material/Stack'\n\nimport { H3 } from '@mxenabled/mxui'\n\nimport SubHeader from './SubHeader'\nimport InsightOptionsMenu from './InsightOptionsMenu'\nimport { useBeatActions } from '../beatActions'\nimport type { Subtitle } from '../../core'\n\ninterface HeaderProps {\n isMini: boolean\n subtitle?: Subtitle\n title: string\n}\n\nconst Header = ({ isMini, subtitle, title }: HeaderProps) => {\n // The overflow menu appears only when the host wired a menu handler and this\n // isn't the compact/mini layout. Handlers are delivered via context.\n const { onMenuAction } = useBeatActions()\n\n return (\n <Stack sx={{ gap: 4, pb: 12, pl: 16, pr: 16, pt: 16 }}>\n <Stack sx={{ alignItems: 'center', flexDirection: 'row', justifyContent: 'space-between' }}>\n <H3>{title}</H3>\n {!isMini && onMenuAction && <InsightOptionsMenu />}\n </Stack>\n\n {/* Sub Header */}\n {subtitle && <SubHeader subtitle={subtitle} />}\n </Stack>\n )\n}\n\nexport default Header\n"],"mappings":";;;;;;AAeA,IAAM,IAAA,CAAU,EAAE,QAAA,GAAQ,UAAA,GAAU,OAAA,EAAA,MAAyB;AAG3D,QAAM,EAAE,cAAA,EAAA,IAAiB,EAAe;AAExC,SACE,gBAAA,EAAC,GAAD;AAAA,IAAO,IAAI;AAAA,MAAE,KAAK;AAAA,MAAG,IAAI;AAAA,MAAI,IAAI;AAAA,MAAI,IAAI;AAAA,MAAI,IAAI;AAAA,IAAG;AAAA,IAApD,UAAA,CACE,gBAAA,EAAC,GAAD;AAAA,MAAO,IAAI;AAAA,QAAE,YAAY;AAAA,QAAU,eAAe;AAAA,QAAO,gBAAgB;AAAA,MAAgB;AAAA,MAAzF,UAAA,CACE,gBAAA,EAAC,GAAD,EAAA,UAAK,EAAU,CAAA,GACd,CAAC,KAAU,KAAgB,gBAAA,EAAC,GAAD,CAAqB,CAAA,CAC5C;AAAA,IAGN,CAAA,GAAA,KAAY,gBAAA,EAAC,GAAD,EAAqB,UAAA,EAAW,CAAA,CACxC;AAAA;AAEX"}
@@ -0,0 +1,20 @@
1
+ export interface HiddenConfirmationCardProps {
2
+ onClose: () => void;
3
+ onUndo: () => void;
4
+ onLeaveFeedback: () => void;
5
+ }
6
+ /**
7
+ * Inline card that replaces a beat once it has been hidden, prompting the user
8
+ * to undo or leave feedback. Presentational — the host owns visibility and
9
+ * wires the callbacks. Copy comes from `insights_feed.hidden_confirmation`.
10
+ *
11
+ * The close IconButton is absolutely positioned in the top-right corner (top: 4
12
+ * + a 40px button centers its icon on the title line), and the action row is
13
+ * indented under the text column.
14
+ *
15
+ * Figma: 287:20383 — "Template | Hidden Card".
16
+ */
17
+ export declare const HiddenConfirmationCard: (({ onClose, onUndo, onLeaveFeedback }: HiddenConfirmationCardProps) => import("react/jsx-runtime").JSX.Element | null) & {
18
+ displayName: string;
19
+ };
20
+ export default HiddenConfirmationCard;
@@ -0,0 +1,123 @@
1
+ import { useGlobalCopyStore as c } from "../../common/context/hooks.es.js";
2
+ import { observer as x } from "mobx-react-lite";
3
+ import t from "@mui/material/Stack";
4
+ import { P as o, Text as n } from "@mxenabled/mxui";
5
+ import l from "@mui/material/Button";
6
+ import { Close as p, VisibilityOff as m } from "@mxenabled/mx-icons";
7
+ import { jsx as i, jsxs as r } from "react/jsx-runtime";
8
+ import h from "@mui/material/Box";
9
+ import f from "@mui/material/IconButton";
10
+ import b from "@mui/material/Card";
11
+ var _ = x(({ onClose: a, onUndo: s, onLeaveFeedback: d }) => {
12
+ const e = c().insights_feed?.hidden_confirmation;
13
+ return e ? /* @__PURE__ */ r(b, {
14
+ elevation: 1,
15
+ sx: {
16
+ position: "relative",
17
+ bgcolor: "action.disabledBackground",
18
+ borderRadius: 2,
19
+ pt: 16,
20
+ px: 16,
21
+ pb: 8
22
+ },
23
+ children: [/* @__PURE__ */ i(f, {
24
+ "aria-label": e.close_aria,
25
+ onClick: a,
26
+ sx: {
27
+ minHeight: 40,
28
+ minWidth: 40,
29
+ position: "absolute",
30
+ right: 4,
31
+ top: 4
32
+ },
33
+ children: /* @__PURE__ */ i(p, {
34
+ size: 20,
35
+ sx: { color: "text.secondary" }
36
+ })
37
+ }), /* @__PURE__ */ r(t, {
38
+ sx: { gap: 6 },
39
+ children: [/* @__PURE__ */ r(t, {
40
+ sx: {
41
+ flexDirection: "row",
42
+ gap: 12
43
+ },
44
+ children: [/* @__PURE__ */ i(h, {
45
+ sx: {
46
+ flexShrink: 0,
47
+ width: 32,
48
+ height: 32,
49
+ borderRadius: 1,
50
+ bgcolor: "grey.300",
51
+ display: "flex",
52
+ alignItems: "center",
53
+ justifyContent: "center"
54
+ },
55
+ children: /* @__PURE__ */ i(m, {
56
+ size: 20,
57
+ sx: { color: "text.secondary" }
58
+ })
59
+ }), /* @__PURE__ */ r(t, {
60
+ sx: { gap: 6 },
61
+ children: [/* @__PURE__ */ i(o, {
62
+ "aria-live": "assertive",
63
+ bold: !0,
64
+ sx: { lineHeight: "16px" },
65
+ variant: "body1",
66
+ children: e.title
67
+ }), /* @__PURE__ */ i(o, {
68
+ sx: {
69
+ color: "text.primary",
70
+ fontSize: 13,
71
+ lineHeight: "20px"
72
+ },
73
+ variant: "subtitle2",
74
+ children: e.description
75
+ })]
76
+ })]
77
+ }), /* @__PURE__ */ r(t, {
78
+ sx: {
79
+ alignItems: "center",
80
+ flexDirection: "row",
81
+ gap: 4,
82
+ height: 28,
83
+ pb: 6,
84
+ pl: 36
85
+ },
86
+ children: [/* @__PURE__ */ i(l, {
87
+ onClick: s,
88
+ size: "small",
89
+ sx: {
90
+ minWidth: 0,
91
+ px: 8
92
+ },
93
+ variant: "text",
94
+ children: /* @__PURE__ */ i(n, {
95
+ bold: !0,
96
+ variant: "body2",
97
+ children: e.undo
98
+ })
99
+ }), /* @__PURE__ */ i(l, {
100
+ onClick: d,
101
+ size: "small",
102
+ sx: {
103
+ minWidth: 0,
104
+ px: 8
105
+ },
106
+ variant: "text",
107
+ children: /* @__PURE__ */ i(n, {
108
+ bold: !0,
109
+ sx: { color: "text.secondary" },
110
+ variant: "body2",
111
+ children: e.leave_feedback
112
+ })
113
+ })]
114
+ })]
115
+ })]
116
+ }) : null;
117
+ });
118
+ export {
119
+ _ as HiddenConfirmationCard,
120
+ _ as default
121
+ };
122
+
123
+ //# sourceMappingURL=HiddenConfirmationCard.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HiddenConfirmationCard.es.js","names":[],"sources":["../../../src/insights-v2/components/HiddenConfirmationCard.tsx"],"sourcesContent":["import Box from '@mui/material/Box'\nimport Button from '@mui/material/Button'\nimport Card from '@mui/material/Card'\nimport IconButton from '@mui/material/IconButton'\nimport Stack from '@mui/material/Stack'\n\nimport { observer } from 'mobx-react-lite'\n\nimport { Close, VisibilityOff } from '@mxenabled/mx-icons'\nimport { P, Text } from '@mxenabled/mxui'\n\nimport { useGlobalCopyStore } from '../../common'\n\nexport interface HiddenConfirmationCardProps {\n onClose: () => void\n onUndo: () => void\n onLeaveFeedback: () => void\n}\n\n/**\n * Inline card that replaces a beat once it has been hidden, prompting the user\n * to undo or leave feedback. Presentational — the host owns visibility and\n * wires the callbacks. Copy comes from `insights_feed.hidden_confirmation`.\n *\n * The close IconButton is absolutely positioned in the top-right corner (top: 4\n * + a 40px button centers its icon on the title line), and the action row is\n * indented under the text column.\n *\n * Figma: 287:20383 — \"Template | Hidden Card\".\n */\nexport const HiddenConfirmationCard = observer(\n ({ onClose, onUndo, onLeaveFeedback }: HiddenConfirmationCardProps) => {\n const copy = useGlobalCopyStore().insights_feed?.hidden_confirmation\n\n if (!copy) return null\n\n return (\n <Card\n elevation={1}\n sx={{\n position: 'relative',\n bgcolor: 'action.disabledBackground',\n borderRadius: 2,\n pt: 16,\n px: 16,\n pb: 8,\n }}\n >\n <IconButton\n aria-label={copy.close_aria}\n onClick={onClose}\n sx={{ minHeight: 40, minWidth: 40, position: 'absolute', right: 4, top: 4 }}\n >\n <Close size={20} sx={{ color: 'text.secondary' }} />\n </IconButton>\n\n <Stack sx={{ gap: 6 }}>\n {/* Icon + title/description */}\n <Stack sx={{ flexDirection: 'row', gap: 12 }}>\n <Box\n sx={{\n flexShrink: 0,\n width: 32,\n height: 32,\n borderRadius: 1,\n bgcolor: 'grey.300',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <VisibilityOff size={20} sx={{ color: 'text.secondary' }} />\n </Box>\n\n <Stack sx={{ gap: 6 }}>\n <P aria-live=\"assertive\" bold sx={{ lineHeight: '16px' }} variant=\"body1\">\n {copy.title}\n </P>\n\n <P\n sx={{ color: 'text.primary', fontSize: 13, lineHeight: '20px' }}\n variant=\"subtitle2\"\n >\n {copy.description}\n </P>\n </Stack>\n </Stack>\n\n {/* Actions — indented under the text column via pl: 36 (avatar 32 + gap\n 12), so the first label sits flush under the title/description.\n Gap 4 between buttons per Figma. */}\n <Stack\n sx={{\n alignItems: 'center',\n flexDirection: 'row',\n gap: 4,\n height: 28,\n pb: 6,\n pl: 36,\n }}\n >\n <Button onClick={onUndo} size=\"small\" sx={{ minWidth: 0, px: 8 }} variant=\"text\">\n <Text bold variant=\"body2\">\n {copy.undo}\n </Text>\n </Button>\n <Button\n onClick={onLeaveFeedback}\n size=\"small\"\n sx={{ minWidth: 0, px: 8 }}\n variant=\"text\"\n >\n <Text bold sx={{ color: 'text.secondary' }} variant=\"body2\">\n {copy.leave_feedback}\n </Text>\n </Button>\n </Stack>\n </Stack>\n </Card>\n )\n },\n)\n\nexport default HiddenConfirmationCard\n"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The insight card's "…" overflow menu. This repo owns the item set — order,
3
+ * icons, and labels (from `insights_feed.overflow_menu` copy) — while the host
4
+ * supplies the action handler via `beatActions.onMenuAction` (read from
5
+ * context). Renders nothing without a handler or before copy resolves.
6
+ */
7
+ export declare const InsightOptionsMenu: (() => import("react/jsx-runtime").JSX.Element | null) & {
8
+ displayName: string;
9
+ };
10
+ export default InsightOptionsMenu;