@12-apps/ui 6.53.0 → 6.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_internal/components/data-display/AlertDialog/AlertDialog.js +2 -1
- package/dist/_internal/components/data-display/AlertDialog/AlertDialog.parts.js +9 -0
- package/dist/_internal/components/data-display/AlertDialog/AlertDialog.parts.js.map +1 -0
- package/dist/_internal/components/data-display/CardKit/use-remove-confirm.js +7 -6
- package/dist/_internal/components/data-display/CardKit/use-row-confirm.js +7 -6
- package/dist/_internal/components/data-display/DataViews/DataViewsTableBase.js +9 -8
- package/dist/_internal/components/data-display/DataViews/ManageViewsDialog.js +7 -6
- package/dist/_internal/components/data-display/DataViews/data-views-table-parts.js +8 -7
- package/dist/_internal/components/data-display/index.js +2 -1
- package/dist/_internal/components/feedback/ConfirmAction/ConfirmAction.js +4 -3
- package/dist/_internal/components/feedback/ConfirmAction/ConfirmAction.parts.js +3 -2
- package/dist/_internal/components/feedback/ConfirmAction/ConfirmButton.js +5 -4
- package/dist/_internal/components/feedback/ConfirmAction/with-confirmation.js +4 -3
- package/dist/_internal/components/feedback/index.js +6 -5
- package/dist/_internal/components/index.js +6 -5
- package/dist/{chunk-QOLIBVGS.js → chunk-3CIIB74Y.js} +2 -2
- package/dist/{chunk-OG6LYQ7C.js → chunk-4PFKMNLP.js} +8 -68
- package/dist/chunk-4PFKMNLP.js.map +1 -0
- package/dist/{chunk-OT3KFZRE.js → chunk-7WWPKA7Y.js} +2 -2
- package/dist/{chunk-JUHNEYCH.js → chunk-GCH7CLM4.js} +2 -2
- package/dist/{chunk-HCEJT65A.js → chunk-HKD4TDZP.js} +2 -2
- package/dist/{chunk-3GVMUASU.js → chunk-HV7HIMMY.js} +2 -2
- package/dist/chunk-IQQX3NDO.js +96 -0
- package/dist/chunk-IQQX3NDO.js.map +1 -0
- package/dist/{chunk-4WCDMCIS.js → chunk-PI3GPLE2.js} +2 -2
- package/dist/{chunk-FWPFCK4D.js → chunk-S6G3CJFP.js} +2 -2
- package/dist/{chunk-BJZOBG24.js → chunk-UJHXEOU3.js} +2 -2
- package/dist/{chunk-U4QUDFPJ.js → chunk-VKVOP4OK.js} +2 -2
- package/dist/data-display/AlertDialog.js +2 -1
- package/dist/data-display/CardKit.js +8 -7
- package/dist/data-display/DataViews.js +9 -8
- package/dist/feedback/ConfirmAction.js +6 -5
- package/dist/types/components/data-display/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/types/components/data-display/AlertDialog/AlertDialog.parts.d.ts +13 -0
- package/dist/types/components/data-display/AlertDialog/AlertDialog.parts.d.ts.map +1 -0
- package/dist/types/components/data-display/AlertDialog/AlertDialog.types.d.ts +16 -3
- package/dist/types/components/data-display/AlertDialog/AlertDialog.types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/data-display/AlertDialog/AlertDialog.md +30 -0
- package/src/components/data-display/AlertDialog/AlertDialog.parts.tsx +180 -0
- package/src/components/data-display/AlertDialog/AlertDialog.tsx +5 -85
- package/src/components/data-display/AlertDialog/AlertDialog.types.ts +17 -3
- package/dist/chunk-OG6LYQ7C.js.map +0 -1
- /package/dist/{chunk-QOLIBVGS.js.map → chunk-3CIIB74Y.js.map} +0 -0
- /package/dist/{chunk-OT3KFZRE.js.map → chunk-7WWPKA7Y.js.map} +0 -0
- /package/dist/{chunk-JUHNEYCH.js.map → chunk-GCH7CLM4.js.map} +0 -0
- /package/dist/{chunk-HCEJT65A.js.map → chunk-HKD4TDZP.js.map} +0 -0
- /package/dist/{chunk-3GVMUASU.js.map → chunk-HV7HIMMY.js.map} +0 -0
- /package/dist/{chunk-4WCDMCIS.js.map → chunk-PI3GPLE2.js.map} +0 -0
- /package/dist/{chunk-FWPFCK4D.js.map → chunk-S6G3CJFP.js.map} +0 -0
- /package/dist/{chunk-BJZOBG24.js.map → chunk-UJHXEOU3.js.map} +0 -0
- /package/dist/{chunk-U4QUDFPJ.js.map → chunk-VKVOP4OK.js.map} +0 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import {
|
|
2
|
+
rem
|
|
3
|
+
} from "./chunk-YKCAJ2TN.js";
|
|
4
|
+
|
|
5
|
+
// src/components/data-display/AlertDialog/AlertDialog.parts.tsx
|
|
6
|
+
import Button from "@mui/material/Button/index.js";
|
|
7
|
+
import CircularProgress from "@mui/material/CircularProgress/index.js";
|
|
8
|
+
import DialogActions from "@mui/material/DialogActions/index.js";
|
|
9
|
+
import { styled, useTheme } from "@mui/material/styles/index.js";
|
|
10
|
+
import { jsx } from "react/jsx-runtime";
|
|
11
|
+
var StyledDialogActions = styled(DialogActions, {
|
|
12
|
+
shouldForwardProp: (prop) => prop !== "fill"
|
|
13
|
+
})(({ theme, fill }) => ({
|
|
14
|
+
padding: theme.spacing(2, 3, 3, 3),
|
|
15
|
+
flexWrap: "wrap-reverse",
|
|
16
|
+
columnGap: theme.spacing(2),
|
|
17
|
+
rowGap: theme.spacing(1),
|
|
18
|
+
...fill && { "& > .MuiButton-root": { flexGrow: 1 } }
|
|
19
|
+
}));
|
|
20
|
+
var confirmButtonColor = (variant) => variant === "destructive" ? "error" : "primary";
|
|
21
|
+
var buttonLooks = (emphasis, variant) => emphasis === "cancel" ? {
|
|
22
|
+
cancel: { variant: "contained", color: "primary" },
|
|
23
|
+
confirm: { variant: "outlined", color: "inherit" }
|
|
24
|
+
} : {
|
|
25
|
+
cancel: { variant: "outlined", color: "inherit" },
|
|
26
|
+
confirm: { variant: "contained", color: confirmButtonColor(variant) }
|
|
27
|
+
};
|
|
28
|
+
var effectiveEmphasis = (emphasis, showCancel) => emphasis === "cancel" && showCancel ? "cancel" : "confirm";
|
|
29
|
+
var focusesCancel = (initialFocus, emphasis) => (initialFocus ?? emphasis) === "cancel";
|
|
30
|
+
var inSlotOrder = (emphasis, cancel, confirm) => emphasis === "cancel" ? [confirm, cancel] : [cancel, confirm];
|
|
31
|
+
function AlertDialogFooter({
|
|
32
|
+
variant,
|
|
33
|
+
cancelText = "Cancel",
|
|
34
|
+
confirmText = "Confirm",
|
|
35
|
+
showCancel = true,
|
|
36
|
+
loading = false,
|
|
37
|
+
confirmDisabled = false,
|
|
38
|
+
initialFocus,
|
|
39
|
+
emphasis: asked,
|
|
40
|
+
onCancel,
|
|
41
|
+
onConfirm,
|
|
42
|
+
dataTestId
|
|
43
|
+
}) {
|
|
44
|
+
const theme = useTheme();
|
|
45
|
+
const emphasis = effectiveEmphasis(asked, showCancel);
|
|
46
|
+
const look = buttonLooks(emphasis, variant);
|
|
47
|
+
const cancelFocused = focusesCancel(initialFocus, emphasis);
|
|
48
|
+
const cancel = showCancel && /* @__PURE__ */ jsx(
|
|
49
|
+
Button,
|
|
50
|
+
{
|
|
51
|
+
onClick: onCancel,
|
|
52
|
+
variant: look.cancel.variant,
|
|
53
|
+
color: look.cancel.color,
|
|
54
|
+
disabled: loading,
|
|
55
|
+
autoFocus: cancelFocused,
|
|
56
|
+
"data-testid": `${dataTestId}-cancel-button`,
|
|
57
|
+
children: cancelText
|
|
58
|
+
},
|
|
59
|
+
"cancel"
|
|
60
|
+
);
|
|
61
|
+
const confirm = /* @__PURE__ */ jsx(
|
|
62
|
+
Button,
|
|
63
|
+
{
|
|
64
|
+
onClick: onConfirm,
|
|
65
|
+
variant: look.confirm.variant,
|
|
66
|
+
color: look.confirm.color,
|
|
67
|
+
disabled: confirmDisabled || loading,
|
|
68
|
+
startIcon: loading ? /* @__PURE__ */ jsx(
|
|
69
|
+
CircularProgress,
|
|
70
|
+
{
|
|
71
|
+
size: rem(theme, 16),
|
|
72
|
+
color: "inherit",
|
|
73
|
+
"data-testid": `${dataTestId}-loading-spinner`
|
|
74
|
+
}
|
|
75
|
+
) : void 0,
|
|
76
|
+
autoFocus: !cancelFocused,
|
|
77
|
+
"data-testid": `${dataTestId}-confirm-button`,
|
|
78
|
+
children: confirmText
|
|
79
|
+
},
|
|
80
|
+
"confirm"
|
|
81
|
+
);
|
|
82
|
+
return /* @__PURE__ */ jsx(
|
|
83
|
+
StyledDialogActions,
|
|
84
|
+
{
|
|
85
|
+
disableSpacing: true,
|
|
86
|
+
fill: emphasis === "cancel",
|
|
87
|
+
"data-testid": `${dataTestId}-actions`,
|
|
88
|
+
children: inSlotOrder(emphasis, cancel, confirm)
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export {
|
|
94
|
+
AlertDialogFooter
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=chunk-IQQX3NDO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/data-display/AlertDialog/AlertDialog.parts.tsx"],"sourcesContent":["/**\n * The AlertDialog's action row, kept apart from the dialog shell so each stays\n * inside the complexity budget: which button is filled, where each one sits,\n * and how the row wraps.\n */\nimport type { ButtonProps } from '@mui/material/Button/index.js';\nimport Button from '@mui/material/Button/index.js';\nimport CircularProgress from '@mui/material/CircularProgress/index.js';\nimport DialogActions from '@mui/material/DialogActions/index.js';\nimport { styled, useTheme } from '@mui/material/styles/index.js';\nimport React from 'react';\n\nimport { rem } from '../../../tokens/relative';\n\nimport type { AlertDialogProps } from './AlertDialog.types';\n\n/**\n * The action row WRAPS WHOLE BUTTONS; it never breaks a label inside one. A pair\n * that did not fit side by side used to squeeze the longer label onto two\n * lines, so one button stood twice as tall as its neighbour. Now the row breaks\n * instead. `wrap-reverse` puts the LAST button — the primary, whichever\n * `emphasis` picks — on top when it stacks, the same slot it holds on the right\n * when the row fits. A pair that fits is laid out exactly as before: natural\n * widths, pushed to the right.\n *\n * `fill` — set only by `emphasis=\"cancel\"` — lets the buttons grow to share the\n * row, and so to take the full width of their line once it stacks. It is not\n * the default because growing also stretches a pair that fits, which would\n * redraw every existing dialog's footer.\n *\n * Rendered with `disableSpacing`: MUI's own spacing is a left margin on every\n * button after the first, which would indent a button that wrapped onto a line\n * of its own. The gaps below replace it, at the same 16px across.\n */\nconst StyledDialogActions = styled(DialogActions, {\n shouldForwardProp: (prop) => prop !== 'fill',\n})<{ fill: boolean }>(({ theme, fill }) => ({\n padding: theme.spacing(2, 3, 3, 3),\n flexWrap: 'wrap-reverse',\n columnGap: theme.spacing(2),\n rowGap: theme.spacing(1),\n ...(fill && { '& > .MuiButton-root': { flexGrow: 1 } }),\n}));\n\nconst confirmButtonColor = (variant: AlertDialogProps['variant']): 'error' | 'primary' =>\n variant === 'destructive' ? 'error' : 'primary';\n\ninterface ButtonLook {\n variant: ButtonProps['variant'];\n color: ButtonProps['color'];\n}\n\n/**\n * How each button is drawn, by `emphasis`: the emphasised one is filled, the\n * other a NEUTRAL outline. Primary / neutral both ways round — a confirm that\n * steps down drops the variant's colour too, so the one filled button is the\n * only coloured thing in the row and the eye has a single place to land.\n */\nconst buttonLooks = (\n emphasis: AlertDialogProps['emphasis'],\n variant: AlertDialogProps['variant'],\n): { cancel: ButtonLook; confirm: ButtonLook } =>\n emphasis === 'cancel'\n ? {\n cancel: { variant: 'contained', color: 'primary' },\n confirm: { variant: 'outlined', color: 'inherit' },\n }\n : {\n cancel: { variant: 'outlined', color: 'inherit' },\n confirm: { variant: 'contained', color: confirmButtonColor(variant) },\n };\n\n/**\n * The emphasis that applies: `cancel` only while the cancel is shown. A hidden\n * cancel with the confirm stepped down would leave a dialog with no primary.\n */\nconst effectiveEmphasis = (\n emphasis: AlertDialogProps['emphasis'],\n showCancel: boolean,\n): NonNullable<AlertDialogProps['emphasis']> =>\n emphasis === 'cancel' && showCancel ? 'cancel' : 'confirm';\n\n/**\n * Whether the cancel owns focus on open: what `initialFocus` says, and when it\n * says nothing, the emphasised button — so Enter on a steered question keeps\n * the work instead of completing the loss.\n */\nconst focusesCancel = (\n initialFocus: AlertDialogProps['initialFocus'],\n emphasis: NonNullable<AlertDialogProps['emphasis']>,\n): boolean => (initialFocus ?? emphasis) === 'cancel';\n\n/** The two buttons in slot order: the emphasised one LAST, the primary slot. */\nconst inSlotOrder = (\n emphasis: AlertDialogProps['emphasis'],\n cancel: React.ReactNode,\n confirm: React.ReactNode,\n): React.ReactNode[] => (emphasis === 'cancel' ? [confirm, cancel] : [cancel, confirm]);\n\n/**\n * Action row: the optional cancel button and the (variant-coloured) confirm,\n * with the emphasised one LAST — the primary slot, on the right or, once the\n * row stacks, on top. DOM order is the tab order, so it follows the same rule.\n */\nexport function AlertDialogFooter({\n variant,\n cancelText = 'Cancel',\n confirmText = 'Confirm',\n showCancel = true,\n loading = false,\n confirmDisabled = false,\n initialFocus,\n emphasis: asked,\n onCancel,\n onConfirm,\n dataTestId,\n}: Pick<\n AlertDialogProps,\n | 'variant'\n | 'cancelText'\n | 'confirmText'\n | 'showCancel'\n | 'loading'\n | 'confirmDisabled'\n | 'initialFocus'\n | 'emphasis'\n> & {\n onCancel: () => void;\n onConfirm: () => void;\n dataTestId: string;\n}): React.ReactElement {\n const theme = useTheme();\n const emphasis = effectiveEmphasis(asked, showCancel);\n const look = buttonLooks(emphasis, variant);\n const cancelFocused = focusesCancel(initialFocus, emphasis);\n const cancel = showCancel && (\n <Button\n key=\"cancel\"\n onClick={onCancel}\n variant={look.cancel.variant}\n color={look.cancel.color}\n disabled={loading}\n autoFocus={cancelFocused}\n data-testid={`${dataTestId}-cancel-button`}\n >\n {cancelText}\n </Button>\n );\n const confirm = (\n <Button\n key=\"confirm\"\n onClick={onConfirm}\n variant={look.confirm.variant}\n color={look.confirm.color}\n disabled={confirmDisabled || loading}\n startIcon={\n loading ? (\n <CircularProgress\n size={rem(theme, 16)}\n color=\"inherit\"\n data-testid={`${dataTestId}-loading-spinner`}\n />\n ) : undefined\n }\n autoFocus={!cancelFocused}\n data-testid={`${dataTestId}-confirm-button`}\n >\n {confirmText}\n </Button>\n );\n return (\n <StyledDialogActions\n disableSpacing\n fill={emphasis === 'cancel'}\n data-testid={`${dataTestId}-actions`}\n >\n {inSlotOrder(emphasis, cancel, confirm)}\n </StyledDialogActions>\n );\n}\n"],"mappings":";;;;;AAMA,OAAO,YAAY;AACnB,OAAO,sBAAsB;AAC7B,OAAO,mBAAmB;AAC1B,SAAS,QAAQ,gBAAgB;AA+H7B;AAtGJ,IAAM,sBAAsB,OAAO,eAAe;AAAA,EAChD,mBAAmB,CAAC,SAAS,SAAS;AACxC,CAAC,EAAqB,CAAC,EAAE,OAAO,KAAK,OAAO;AAAA,EAC1C,SAAS,MAAM,QAAQ,GAAG,GAAG,GAAG,CAAC;AAAA,EACjC,UAAU;AAAA,EACV,WAAW,MAAM,QAAQ,CAAC;AAAA,EAC1B,QAAQ,MAAM,QAAQ,CAAC;AAAA,EACvB,GAAI,QAAQ,EAAE,uBAAuB,EAAE,UAAU,EAAE,EAAE;AACvD,EAAE;AAEF,IAAM,qBAAqB,CAAC,YAC1B,YAAY,gBAAgB,UAAU;AAaxC,IAAM,cAAc,CAClB,UACA,YAEA,aAAa,WACT;AAAA,EACE,QAAQ,EAAE,SAAS,aAAa,OAAO,UAAU;AAAA,EACjD,SAAS,EAAE,SAAS,YAAY,OAAO,UAAU;AACnD,IACA;AAAA,EACE,QAAQ,EAAE,SAAS,YAAY,OAAO,UAAU;AAAA,EAChD,SAAS,EAAE,SAAS,aAAa,OAAO,mBAAmB,OAAO,EAAE;AACtE;AAMN,IAAM,oBAAoB,CACxB,UACA,eAEA,aAAa,YAAY,aAAa,WAAW;AAOnD,IAAM,gBAAgB,CACpB,cACA,cACa,gBAAgB,cAAc;AAG7C,IAAM,cAAc,CAClB,UACA,QACA,YACuB,aAAa,WAAW,CAAC,SAAS,MAAM,IAAI,CAAC,QAAQ,OAAO;AAO9E,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA,aAAa;AAAA,EACb,cAAc;AAAA,EACd,aAAa;AAAA,EACb,UAAU;AAAA,EACV,kBAAkB;AAAA,EAClB;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AACF,GAcuB;AACrB,QAAM,QAAQ,SAAS;AACvB,QAAM,WAAW,kBAAkB,OAAO,UAAU;AACpD,QAAM,OAAO,YAAY,UAAU,OAAO;AAC1C,QAAM,gBAAgB,cAAc,cAAc,QAAQ;AAC1D,QAAM,SAAS,cACb;AAAA,IAAC;AAAA;AAAA,MAEC,SAAS;AAAA,MACT,SAAS,KAAK,OAAO;AAAA,MACrB,OAAO,KAAK,OAAO;AAAA,MACnB,UAAU;AAAA,MACV,WAAW;AAAA,MACX,eAAa,GAAG,UAAU;AAAA,MAEzB;AAAA;AAAA,IARG;AAAA,EASN;AAEF,QAAM,UACJ;AAAA,IAAC;AAAA;AAAA,MAEC,SAAS;AAAA,MACT,SAAS,KAAK,QAAQ;AAAA,MACtB,OAAO,KAAK,QAAQ;AAAA,MACpB,UAAU,mBAAmB;AAAA,MAC7B,WACE,UACE;AAAA,QAAC;AAAA;AAAA,UACC,MAAM,IAAI,OAAO,EAAE;AAAA,UACnB,OAAM;AAAA,UACN,eAAa,GAAG,UAAU;AAAA;AAAA,MAC5B,IACE;AAAA,MAEN,WAAW,CAAC;AAAA,MACZ,eAAa,GAAG,UAAU;AAAA,MAEzB;AAAA;AAAA,IAjBG;AAAA,EAkBN;AAEF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,gBAAc;AAAA,MACd,MAAM,aAAa;AAAA,MACnB,eAAa,GAAG,UAAU;AAAA,MAEzB,sBAAY,UAAU,QAAQ,OAAO;AAAA;AAAA,EACxC;AAEJ;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ConfirmActionDialog
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UJHXEOU3.js";
|
|
4
4
|
import {
|
|
5
5
|
useConfirmAction
|
|
6
6
|
} from "./chunk-EMYESBIT.js";
|
|
@@ -40,4 +40,4 @@ function withConfirmation(Wrapped, defaults) {
|
|
|
40
40
|
export {
|
|
41
41
|
withConfirmation
|
|
42
42
|
};
|
|
43
|
-
//# sourceMappingURL=chunk-
|
|
43
|
+
//# sourceMappingURL=chunk-PI3GPLE2.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ConfirmActionDialog
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UJHXEOU3.js";
|
|
4
4
|
import {
|
|
5
5
|
useConfirmAction
|
|
6
6
|
} from "./chunk-EMYESBIT.js";
|
|
@@ -23,4 +23,4 @@ ConfirmAction.displayName = "ConfirmAction";
|
|
|
23
23
|
export {
|
|
24
24
|
ConfirmAction
|
|
25
25
|
};
|
|
26
|
-
//# sourceMappingURL=chunk-
|
|
26
|
+
//# sourceMappingURL=chunk-S6G3CJFP.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AlertDialog
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4PFKMNLP.js";
|
|
4
4
|
|
|
5
5
|
// src/components/feedback/ConfirmAction/ConfirmAction.parts.tsx
|
|
6
6
|
import Alert from "@mui/material/Alert/index.js";
|
|
@@ -104,4 +104,4 @@ function ConfirmActionDialog({
|
|
|
104
104
|
export {
|
|
105
105
|
ConfirmActionDialog
|
|
106
106
|
};
|
|
107
|
-
//# sourceMappingURL=chunk-
|
|
107
|
+
//# sourceMappingURL=chunk-UJHXEOU3.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ConfirmActionDialog
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UJHXEOU3.js";
|
|
4
4
|
import {
|
|
5
5
|
useConfirmAction
|
|
6
6
|
} from "./chunk-EMYESBIT.js";
|
|
@@ -43,4 +43,4 @@ function useRowConfirm({
|
|
|
43
43
|
export {
|
|
44
44
|
useRowConfirm
|
|
45
45
|
};
|
|
46
|
-
//# sourceMappingURL=chunk-
|
|
46
|
+
//# sourceMappingURL=chunk-VKVOP4OK.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useRemoveConfirm
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-3CIIB74Y.js";
|
|
4
4
|
import {
|
|
5
5
|
rowActionsToMenuItems
|
|
6
6
|
} from "../chunk-ZBXG6RVJ.js";
|
|
@@ -20,21 +20,22 @@ import {
|
|
|
20
20
|
} from "../chunk-2NIQSL7M.js";
|
|
21
21
|
import {
|
|
22
22
|
useRowConfirm
|
|
23
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-VKVOP4OK.js";
|
|
24
24
|
import "../chunk-WVML3ENZ.js";
|
|
25
25
|
import "../chunk-U3DBQXPI.js";
|
|
26
26
|
import "../chunk-XCBQXSTR.js";
|
|
27
|
-
import "../chunk-
|
|
28
|
-
import "../chunk-
|
|
29
|
-
import "../chunk-
|
|
30
|
-
import "../chunk-
|
|
27
|
+
import "../chunk-HV7HIMMY.js";
|
|
28
|
+
import "../chunk-S6G3CJFP.js";
|
|
29
|
+
import "../chunk-PI3GPLE2.js";
|
|
30
|
+
import "../chunk-UJHXEOU3.js";
|
|
31
31
|
import "../chunk-EMYESBIT.js";
|
|
32
32
|
import "../chunk-NUGT7LMR.js";
|
|
33
33
|
import "../chunk-AUHYR7ID.js";
|
|
34
34
|
import "../chunk-MO47Y26B.js";
|
|
35
35
|
import "../chunk-L7VH6IMR.js";
|
|
36
36
|
import "../chunk-2IBFEHIX.js";
|
|
37
|
-
import "../chunk-
|
|
37
|
+
import "../chunk-4PFKMNLP.js";
|
|
38
|
+
import "../chunk-IQQX3NDO.js";
|
|
38
39
|
import "../chunk-P2UIXDEG.js";
|
|
39
40
|
import "../chunk-6DPAWXZ3.js";
|
|
40
41
|
import "../chunk-BA4RHQ3B.js";
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "../chunk-UNEJ4MUR.js";
|
|
4
4
|
import {
|
|
5
5
|
DataViewsTableBase
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-7WWPKA7Y.js";
|
|
7
7
|
import "../chunk-67LNVBFO.js";
|
|
8
8
|
import {
|
|
9
9
|
DataViewsGrid
|
|
@@ -48,9 +48,9 @@ import "../chunk-EIY5EYO3.js";
|
|
|
48
48
|
import "../chunk-I32M7WNL.js";
|
|
49
49
|
import "../chunk-QZY5NG5N.js";
|
|
50
50
|
import "../chunk-O5UGAL2V.js";
|
|
51
|
-
import "../chunk-
|
|
51
|
+
import "../chunk-HKD4TDZP.js";
|
|
52
52
|
import "../chunk-4E4MSUY5.js";
|
|
53
|
-
import "../chunk-
|
|
53
|
+
import "../chunk-GCH7CLM4.js";
|
|
54
54
|
import "../chunk-5M4TYFR3.js";
|
|
55
55
|
import "../chunk-IM5SR7G2.js";
|
|
56
56
|
import "../chunk-X3DVZNZH.js";
|
|
@@ -158,10 +158,10 @@ import "../chunk-JU3FRRO2.js";
|
|
|
158
158
|
import "../chunk-C3UKR3NT.js";
|
|
159
159
|
import "../chunk-D6KL74KI.js";
|
|
160
160
|
import "../chunk-XCBQXSTR.js";
|
|
161
|
-
import "../chunk-
|
|
162
|
-
import "../chunk-
|
|
163
|
-
import "../chunk-
|
|
164
|
-
import "../chunk-
|
|
161
|
+
import "../chunk-HV7HIMMY.js";
|
|
162
|
+
import "../chunk-S6G3CJFP.js";
|
|
163
|
+
import "../chunk-PI3GPLE2.js";
|
|
164
|
+
import "../chunk-UJHXEOU3.js";
|
|
165
165
|
import "../chunk-EMYESBIT.js";
|
|
166
166
|
import "../chunk-KFJKOVDD.js";
|
|
167
167
|
import "../chunk-MQ277OLB.js";
|
|
@@ -190,7 +190,8 @@ import "../chunk-AUHYR7ID.js";
|
|
|
190
190
|
import "../chunk-MO47Y26B.js";
|
|
191
191
|
import "../chunk-L7VH6IMR.js";
|
|
192
192
|
import "../chunk-2IBFEHIX.js";
|
|
193
|
-
import "../chunk-
|
|
193
|
+
import "../chunk-4PFKMNLP.js";
|
|
194
|
+
import "../chunk-IQQX3NDO.js";
|
|
194
195
|
import "../chunk-3UIDKLML.js";
|
|
195
196
|
import "../chunk-PYC4CWCQ.js";
|
|
196
197
|
import "../chunk-P2UIXDEG.js";
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import "../chunk-XCBQXSTR.js";
|
|
2
2
|
import {
|
|
3
3
|
createConfirmButton
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-HV7HIMMY.js";
|
|
5
5
|
import {
|
|
6
6
|
ConfirmAction
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-S6G3CJFP.js";
|
|
8
8
|
import {
|
|
9
9
|
withConfirmation
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-PI3GPLE2.js";
|
|
11
11
|
import {
|
|
12
12
|
ConfirmActionDialog
|
|
13
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-UJHXEOU3.js";
|
|
14
14
|
import {
|
|
15
15
|
useConfirmAction
|
|
16
16
|
} from "../chunk-EMYESBIT.js";
|
|
17
17
|
import "../chunk-2IBFEHIX.js";
|
|
18
|
-
import "../chunk-
|
|
18
|
+
import "../chunk-4PFKMNLP.js";
|
|
19
|
+
import "../chunk-IQQX3NDO.js";
|
|
19
20
|
import "../chunk-BA4RHQ3B.js";
|
|
20
21
|
import "../chunk-RIZRF5XR.js";
|
|
21
22
|
import "../chunk-LTE2QHBH.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AlertDialog.d.ts","sourceRoot":"","sources":["../../../../../src/components/data-display/AlertDialog/AlertDialog.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AlertDialog.d.ts","sourceRoot":"","sources":["../../../../../src/components/data-display/AlertDialog/AlertDialog.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAmN5D,eAAO,MAAM,WAAW,sGA6EvB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { AlertDialogProps } from './AlertDialog.types';
|
|
3
|
+
/**
|
|
4
|
+
* Action row: the optional cancel button and the (variant-coloured) confirm,
|
|
5
|
+
* with the emphasised one LAST — the primary slot, on the right or, once the
|
|
6
|
+
* row stacks, on top. DOM order is the tab order, so it follows the same rule.
|
|
7
|
+
*/
|
|
8
|
+
export declare function AlertDialogFooter({ variant, cancelText, confirmText, showCancel, loading, confirmDisabled, initialFocus, emphasis: asked, onCancel, onConfirm, dataTestId, }: Pick<AlertDialogProps, 'variant' | 'cancelText' | 'confirmText' | 'showCancel' | 'loading' | 'confirmDisabled' | 'initialFocus' | 'emphasis'> & {
|
|
9
|
+
onCancel: () => void;
|
|
10
|
+
onConfirm: () => void;
|
|
11
|
+
dataTestId: string;
|
|
12
|
+
}): React.ReactElement;
|
|
13
|
+
//# sourceMappingURL=AlertDialog.parts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AlertDialog.parts.d.ts","sourceRoot":"","sources":["../../../../../src/components/data-display/AlertDialog/AlertDialog.parts.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAqF5D;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,UAAqB,EACrB,WAAuB,EACvB,UAAiB,EACjB,OAAe,EACf,eAAuB,EACvB,YAAY,EACZ,QAAQ,EAAE,KAAK,EACf,QAAQ,EACR,SAAS,EACT,UAAU,GACX,EAAE,IAAI,CACL,gBAAgB,EACd,SAAS,GACT,YAAY,GACZ,aAAa,GACb,YAAY,GACZ,SAAS,GACT,iBAAiB,GACjB,cAAc,GACd,UAAU,CACb,GAAG;IACF,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,KAAK,CAAC,YAAY,CAiDrB"}
|
|
@@ -54,11 +54,24 @@ export interface AlertDialogProps extends Omit<MuiDialogProps, 'variant'> {
|
|
|
54
54
|
*/
|
|
55
55
|
confirmDisabled?: boolean;
|
|
56
56
|
/**
|
|
57
|
-
* Which button owns focus when the dialog opens. Defaults to
|
|
58
|
-
*
|
|
59
|
-
*
|
|
57
|
+
* Which button owns focus when the dialog opens. Defaults to the emphasised
|
|
58
|
+
* one — `confirm`, unless `emphasis="cancel"` — which is right for an
|
|
59
|
+
* acknowledgement; a destructive dialog should pass `cancel` so a stray Enter
|
|
60
|
+
* on the trigger cannot complete the action.
|
|
60
61
|
*/
|
|
61
62
|
initialFocus?: 'confirm' | 'cancel';
|
|
63
|
+
/**
|
|
64
|
+
* Which button is the filled, primary one. Defaults to `confirm`. Pass
|
|
65
|
+
* `cancel` when backing out is the action to steer toward — a "discard what
|
|
66
|
+
* you wrote?" question, where the confirm is the loss: cancel is then filled
|
|
67
|
+
* and takes the primary slot (right, or on top once the row stacks), and the
|
|
68
|
+
* confirm steps down to the neutral outline cancel normally wears — primary
|
|
69
|
+
* and neutral, whatever the variant. The two buttons then grow to share the
|
|
70
|
+
* row, so once it stacks each takes its full width; focus opens on the cancel
|
|
71
|
+
* unless `initialFocus` says otherwise. With `showCancel={false}` it has no
|
|
72
|
+
* effect: the confirm keeps its default, filled look.
|
|
73
|
+
*/
|
|
74
|
+
emphasis?: 'confirm' | 'cancel';
|
|
62
75
|
/**
|
|
63
76
|
* Optional data-testid attribute for testing
|
|
64
77
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AlertDialog.types.d.ts","sourceRoot":"","sources":["../../../../../src/components/data-display/AlertDialog/AlertDialog.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,IAAI,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACnF,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC;IACvE;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,aAAa,GAAG,OAAO,CAAC;IAE9C;;OAEG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE9B;;OAEG;IACH,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAEvB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAEtB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IAEvB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B
|
|
1
|
+
{"version":3,"file":"AlertDialog.types.d.ts","sourceRoot":"","sources":["../../../../../src/components/data-display/AlertDialog/AlertDialog.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,IAAI,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACnF,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC;IACvE;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,aAAa,GAAG,OAAO,CAAC;IAE9C;;OAEG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE9B;;OAEG;IACH,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAEvB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAEtB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IAEvB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAEpC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAEhC;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB"}
|
package/package.json
CHANGED
|
@@ -34,6 +34,7 @@ The AlertDialog component provides a modal dialog for alerts, confirmations, and
|
|
|
34
34
|
| `showCancel` | `boolean` | true | Whether to show the cancel button |
|
|
35
35
|
| `confirmDisabled` | `boolean` | false | Whether the confirm button is disabled |
|
|
36
36
|
| `loading` | `boolean` | false | Shows loading state on confirm button |
|
|
37
|
+
| `emphasis` | `'confirm' \| 'cancel'` | 'confirm' | Which button is filled and takes the primary slot (right, or top when the row stacks). Use `cancel` when the confirm is the loss, e.g. "discard what you wrote?": the confirm becomes the neutral outline, both buttons grow to share the row, and focus opens on the cancel. Ignored when `showCancel` is false |
|
|
37
38
|
|
|
38
39
|
### Visual Props
|
|
39
40
|
|
|
@@ -124,6 +125,35 @@ function DeleteConfirmation() {
|
|
|
124
125
|
/>
|
|
125
126
|
```
|
|
126
127
|
|
|
128
|
+
### Steering Toward Cancel
|
|
129
|
+
|
|
130
|
+
When confirming throws work away, make keeping it the primary action: the
|
|
131
|
+
filled cancel takes the primary slot and the confirm becomes the neutral
|
|
132
|
+
outline — primary and neutral, even on the destructive variant.
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
<AlertDialog
|
|
136
|
+
open={open}
|
|
137
|
+
variant="destructive"
|
|
138
|
+
emphasis="cancel"
|
|
139
|
+
initialFocus="cancel"
|
|
140
|
+
title="Discard this order?"
|
|
141
|
+
description="You have already written 3 items."
|
|
142
|
+
confirmText="Discard"
|
|
143
|
+
cancelText="Keep writing"
|
|
144
|
+
onConfirm={handleDiscard}
|
|
145
|
+
onCancel={() => setOpen(false)}
|
|
146
|
+
onClose={() => setOpen(false)}
|
|
147
|
+
/>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Button Layout
|
|
151
|
+
|
|
152
|
+
The action row wraps whole buttons and never breaks a label inside one. A pair
|
|
153
|
+
that fits keeps its natural widths, pushed to the right; a pair that does not
|
|
154
|
+
stacks, with the primary on top. With `emphasis="cancel"` the two buttons also
|
|
155
|
+
grow to share the row, so stacked they take its full width.
|
|
156
|
+
|
|
127
157
|
### Without Cancel Button
|
|
128
158
|
|
|
129
159
|
```tsx
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The AlertDialog's action row, kept apart from the dialog shell so each stays
|
|
3
|
+
* inside the complexity budget: which button is filled, where each one sits,
|
|
4
|
+
* and how the row wraps.
|
|
5
|
+
*/
|
|
6
|
+
import type { ButtonProps } from '@mui/material/Button/index.js';
|
|
7
|
+
import Button from '@mui/material/Button/index.js';
|
|
8
|
+
import CircularProgress from '@mui/material/CircularProgress/index.js';
|
|
9
|
+
import DialogActions from '@mui/material/DialogActions/index.js';
|
|
10
|
+
import { styled, useTheme } from '@mui/material/styles/index.js';
|
|
11
|
+
import React from 'react';
|
|
12
|
+
|
|
13
|
+
import { rem } from '../../../tokens/relative';
|
|
14
|
+
|
|
15
|
+
import type { AlertDialogProps } from './AlertDialog.types';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The action row WRAPS WHOLE BUTTONS; it never breaks a label inside one. A pair
|
|
19
|
+
* that did not fit side by side used to squeeze the longer label onto two
|
|
20
|
+
* lines, so one button stood twice as tall as its neighbour. Now the row breaks
|
|
21
|
+
* instead. `wrap-reverse` puts the LAST button — the primary, whichever
|
|
22
|
+
* `emphasis` picks — on top when it stacks, the same slot it holds on the right
|
|
23
|
+
* when the row fits. A pair that fits is laid out exactly as before: natural
|
|
24
|
+
* widths, pushed to the right.
|
|
25
|
+
*
|
|
26
|
+
* `fill` — set only by `emphasis="cancel"` — lets the buttons grow to share the
|
|
27
|
+
* row, and so to take the full width of their line once it stacks. It is not
|
|
28
|
+
* the default because growing also stretches a pair that fits, which would
|
|
29
|
+
* redraw every existing dialog's footer.
|
|
30
|
+
*
|
|
31
|
+
* Rendered with `disableSpacing`: MUI's own spacing is a left margin on every
|
|
32
|
+
* button after the first, which would indent a button that wrapped onto a line
|
|
33
|
+
* of its own. The gaps below replace it, at the same 16px across.
|
|
34
|
+
*/
|
|
35
|
+
const StyledDialogActions = styled(DialogActions, {
|
|
36
|
+
shouldForwardProp: (prop) => prop !== 'fill',
|
|
37
|
+
})<{ fill: boolean }>(({ theme, fill }) => ({
|
|
38
|
+
padding: theme.spacing(2, 3, 3, 3),
|
|
39
|
+
flexWrap: 'wrap-reverse',
|
|
40
|
+
columnGap: theme.spacing(2),
|
|
41
|
+
rowGap: theme.spacing(1),
|
|
42
|
+
...(fill && { '& > .MuiButton-root': { flexGrow: 1 } }),
|
|
43
|
+
}));
|
|
44
|
+
|
|
45
|
+
const confirmButtonColor = (variant: AlertDialogProps['variant']): 'error' | 'primary' =>
|
|
46
|
+
variant === 'destructive' ? 'error' : 'primary';
|
|
47
|
+
|
|
48
|
+
interface ButtonLook {
|
|
49
|
+
variant: ButtonProps['variant'];
|
|
50
|
+
color: ButtonProps['color'];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* How each button is drawn, by `emphasis`: the emphasised one is filled, the
|
|
55
|
+
* other a NEUTRAL outline. Primary / neutral both ways round — a confirm that
|
|
56
|
+
* steps down drops the variant's colour too, so the one filled button is the
|
|
57
|
+
* only coloured thing in the row and the eye has a single place to land.
|
|
58
|
+
*/
|
|
59
|
+
const buttonLooks = (
|
|
60
|
+
emphasis: AlertDialogProps['emphasis'],
|
|
61
|
+
variant: AlertDialogProps['variant'],
|
|
62
|
+
): { cancel: ButtonLook; confirm: ButtonLook } =>
|
|
63
|
+
emphasis === 'cancel'
|
|
64
|
+
? {
|
|
65
|
+
cancel: { variant: 'contained', color: 'primary' },
|
|
66
|
+
confirm: { variant: 'outlined', color: 'inherit' },
|
|
67
|
+
}
|
|
68
|
+
: {
|
|
69
|
+
cancel: { variant: 'outlined', color: 'inherit' },
|
|
70
|
+
confirm: { variant: 'contained', color: confirmButtonColor(variant) },
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* The emphasis that applies: `cancel` only while the cancel is shown. A hidden
|
|
75
|
+
* cancel with the confirm stepped down would leave a dialog with no primary.
|
|
76
|
+
*/
|
|
77
|
+
const effectiveEmphasis = (
|
|
78
|
+
emphasis: AlertDialogProps['emphasis'],
|
|
79
|
+
showCancel: boolean,
|
|
80
|
+
): NonNullable<AlertDialogProps['emphasis']> =>
|
|
81
|
+
emphasis === 'cancel' && showCancel ? 'cancel' : 'confirm';
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Whether the cancel owns focus on open: what `initialFocus` says, and when it
|
|
85
|
+
* says nothing, the emphasised button — so Enter on a steered question keeps
|
|
86
|
+
* the work instead of completing the loss.
|
|
87
|
+
*/
|
|
88
|
+
const focusesCancel = (
|
|
89
|
+
initialFocus: AlertDialogProps['initialFocus'],
|
|
90
|
+
emphasis: NonNullable<AlertDialogProps['emphasis']>,
|
|
91
|
+
): boolean => (initialFocus ?? emphasis) === 'cancel';
|
|
92
|
+
|
|
93
|
+
/** The two buttons in slot order: the emphasised one LAST, the primary slot. */
|
|
94
|
+
const inSlotOrder = (
|
|
95
|
+
emphasis: AlertDialogProps['emphasis'],
|
|
96
|
+
cancel: React.ReactNode,
|
|
97
|
+
confirm: React.ReactNode,
|
|
98
|
+
): React.ReactNode[] => (emphasis === 'cancel' ? [confirm, cancel] : [cancel, confirm]);
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Action row: the optional cancel button and the (variant-coloured) confirm,
|
|
102
|
+
* with the emphasised one LAST — the primary slot, on the right or, once the
|
|
103
|
+
* row stacks, on top. DOM order is the tab order, so it follows the same rule.
|
|
104
|
+
*/
|
|
105
|
+
export function AlertDialogFooter({
|
|
106
|
+
variant,
|
|
107
|
+
cancelText = 'Cancel',
|
|
108
|
+
confirmText = 'Confirm',
|
|
109
|
+
showCancel = true,
|
|
110
|
+
loading = false,
|
|
111
|
+
confirmDisabled = false,
|
|
112
|
+
initialFocus,
|
|
113
|
+
emphasis: asked,
|
|
114
|
+
onCancel,
|
|
115
|
+
onConfirm,
|
|
116
|
+
dataTestId,
|
|
117
|
+
}: Pick<
|
|
118
|
+
AlertDialogProps,
|
|
119
|
+
| 'variant'
|
|
120
|
+
| 'cancelText'
|
|
121
|
+
| 'confirmText'
|
|
122
|
+
| 'showCancel'
|
|
123
|
+
| 'loading'
|
|
124
|
+
| 'confirmDisabled'
|
|
125
|
+
| 'initialFocus'
|
|
126
|
+
| 'emphasis'
|
|
127
|
+
> & {
|
|
128
|
+
onCancel: () => void;
|
|
129
|
+
onConfirm: () => void;
|
|
130
|
+
dataTestId: string;
|
|
131
|
+
}): React.ReactElement {
|
|
132
|
+
const theme = useTheme();
|
|
133
|
+
const emphasis = effectiveEmphasis(asked, showCancel);
|
|
134
|
+
const look = buttonLooks(emphasis, variant);
|
|
135
|
+
const cancelFocused = focusesCancel(initialFocus, emphasis);
|
|
136
|
+
const cancel = showCancel && (
|
|
137
|
+
<Button
|
|
138
|
+
key="cancel"
|
|
139
|
+
onClick={onCancel}
|
|
140
|
+
variant={look.cancel.variant}
|
|
141
|
+
color={look.cancel.color}
|
|
142
|
+
disabled={loading}
|
|
143
|
+
autoFocus={cancelFocused}
|
|
144
|
+
data-testid={`${dataTestId}-cancel-button`}
|
|
145
|
+
>
|
|
146
|
+
{cancelText}
|
|
147
|
+
</Button>
|
|
148
|
+
);
|
|
149
|
+
const confirm = (
|
|
150
|
+
<Button
|
|
151
|
+
key="confirm"
|
|
152
|
+
onClick={onConfirm}
|
|
153
|
+
variant={look.confirm.variant}
|
|
154
|
+
color={look.confirm.color}
|
|
155
|
+
disabled={confirmDisabled || loading}
|
|
156
|
+
startIcon={
|
|
157
|
+
loading ? (
|
|
158
|
+
<CircularProgress
|
|
159
|
+
size={rem(theme, 16)}
|
|
160
|
+
color="inherit"
|
|
161
|
+
data-testid={`${dataTestId}-loading-spinner`}
|
|
162
|
+
/>
|
|
163
|
+
) : undefined
|
|
164
|
+
}
|
|
165
|
+
autoFocus={!cancelFocused}
|
|
166
|
+
data-testid={`${dataTestId}-confirm-button`}
|
|
167
|
+
>
|
|
168
|
+
{confirmText}
|
|
169
|
+
</Button>
|
|
170
|
+
);
|
|
171
|
+
return (
|
|
172
|
+
<StyledDialogActions
|
|
173
|
+
disableSpacing
|
|
174
|
+
fill={emphasis === 'cancel'}
|
|
175
|
+
data-testid={`${dataTestId}-actions`}
|
|
176
|
+
>
|
|
177
|
+
{inSlotOrder(emphasis, cancel, confirm)}
|
|
178
|
+
</StyledDialogActions>
|
|
179
|
+
);
|
|
180
|
+
}
|