@@ -20,120 +20,136 @@ import { Confirm } from '../layout';
2020import { Button , type ButtonProps } from './Button' ;
2121import { humanize , inflect } from 'inflection' ;
2222
23- export const BulkDeleteWithConfirmButton = (
24- inProps : BulkDeleteWithConfirmButtonProps
25- ) => {
26- const props = useThemeProps ( {
27- props : inProps ,
28- name : PREFIX ,
29- } ) ;
30- const {
31- confirmTitle = 'ra.message.bulk_delete_title' ,
32- confirmContent = 'ra.message.bulk_delete_content' ,
33- confirmColor = 'primary' ,
34- icon = defaultIcon ,
35- label = 'ra.action.delete' ,
36- mutationMode = 'pessimistic' ,
37- mutationOptions,
38- onClick,
39- ...rest
40- } = props ;
41- const { selectedIds } = useListContext ( ) ;
42- const { handleDelete, isPending } = useBulkDeleteController ( {
43- mutationMode,
44- ...rest ,
45- mutationOptions : {
46- ...mutationOptions ,
47- onSettled ( ...args ) {
48- // In pessimistic mode, we wait for the mutation to be completed (either successfully or with an error) before closing
49- if ( mutationMode === 'pessimistic' ) {
50- setOpen ( false ) ;
51- }
52- mutationOptions ?. onSettled ?.( ...args ) ;
23+ export const BulkDeleteWithConfirmButton = React . forwardRef (
24+ function BulkDeleteWithConfirmButton (
25+ inProps : BulkDeleteWithConfirmButtonProps ,
26+ ref : React . ForwardedRef < HTMLButtonElement >
27+ ) {
28+ const props = useThemeProps ( {
29+ props : inProps ,
30+ name : PREFIX ,
31+ } ) ;
32+ const {
33+ confirmTitle = 'ra.message.bulk_delete_title' ,
34+ confirmContent = 'ra.message.bulk_delete_content' ,
35+ confirmColor = 'primary' ,
36+ icon = defaultIcon ,
37+ label = 'ra.action.delete' ,
38+ mutationMode = 'pessimistic' ,
39+ mutationOptions,
40+ onClick,
41+ ...rest
42+ } = props ;
43+ const { selectedIds } = useListContext ( ) ;
44+ const { handleDelete, isPending } = useBulkDeleteController ( {
45+ mutationMode,
46+ ...rest ,
47+ mutationOptions : {
48+ ...mutationOptions ,
49+ onSettled ( ...args ) {
50+ // In pessimistic mode, we wait for the mutation to be completed (either successfully or with an error) before closing
51+ if ( mutationMode === 'pessimistic' ) {
52+ setOpen ( false ) ;
53+ }
54+ mutationOptions ?. onSettled ?.( ...args ) ;
55+ } ,
5356 } ,
54- } ,
55- } ) ;
56-
57- const [ isOpen , setOpen ] = useState ( false ) ;
58- const resource = useResourceContext ( props ) ;
59- const translate = useTranslate ( ) ;
60-
61- const handleClick = ( e : React . MouseEvent < HTMLButtonElement > ) => {
62- e . stopPropagation ( ) ;
63- setOpen ( true ) ;
64- } ;
65-
66- const handleDialogClose = ( e : React . MouseEvent ) => {
67- e . stopPropagation ( ) ;
68- setOpen ( false ) ;
69- } ;
70-
71- const handleConfirm = ( e : React . MouseEvent < HTMLButtonElement > ) => {
72- e . stopPropagation ( ) ;
73- // We close the dialog immediately here for optimistic/undoable modes instead of in onSuccess/onError
74- // to avoid reimplementing the default side effects
75- if ( mutationMode !== 'pessimistic' ) {
57+ } ) ;
58+
59+ const [ isOpen , setOpen ] = useState ( false ) ;
60+ const resource = useResourceContext ( props ) ;
61+ const translate = useTranslate ( ) ;
62+
63+ const handleClick = ( e : React . MouseEvent < HTMLButtonElement > ) => {
64+ e . stopPropagation ( ) ;
65+ setOpen ( true ) ;
66+ } ;
67+
68+ const handleDialogClose = ( e : React . MouseEvent ) => {
69+ e . stopPropagation ( ) ;
7670 setOpen ( false ) ;
77- }
78- handleDelete ( ) ;
79-
80- if ( typeof onClick === 'function' ) {
81- onClick ( e ) ;
82- }
83- } ;
84-
85- return (
86- < Fragment >
87- < StyledButton
88- onClick = { handleClick }
89- label = { label }
90- color = "error"
91- { ...sanitizeRestProps ( rest ) }
92- >
93- { icon }
94- </ StyledButton >
95- < Confirm
96- isOpen = { isOpen }
97- loading = { isPending }
98- title = { confirmTitle }
99- content = { confirmContent }
100- confirmColor = { confirmColor }
101- titleTranslateOptions = { {
102- smart_count : selectedIds . length ,
103- name : translate ( `resources.${ resource } .forcedCaseName` , {
71+ } ;
72+
73+ const handleConfirm = ( e : React . MouseEvent < HTMLButtonElement > ) => {
74+ e . stopPropagation ( ) ;
75+ // We close the dialog immediately here for optimistic/undoable modes instead of in onSuccess/onError
76+ // to avoid reimplementing the default side effects
77+ if ( mutationMode !== 'pessimistic' ) {
78+ setOpen ( false ) ;
79+ }
80+ handleDelete ( ) ;
81+
82+ if ( typeof onClick === 'function' ) {
83+ onClick ( e ) ;
84+ }
85+ } ;
86+
87+ return (
88+ < Fragment >
89+ < StyledButton
90+ ref = { ref }
91+ onClick = { handleClick }
92+ label = { label }
93+ color = "error"
94+ { ...sanitizeRestProps ( rest ) }
95+ >
96+ { icon }
97+ </ StyledButton >
98+ < Confirm
99+ isOpen = { isOpen }
100+ loading = { isPending }
101+ title = { confirmTitle }
102+ content = { confirmContent }
103+ confirmColor = { confirmColor }
104+ titleTranslateOptions = { {
104105 smart_count : selectedIds . length ,
105- _ : humanize (
106- translate ( `resources.${ resource } .name` , {
106+ name : translate (
107+ `resources.${ resource } .forcedCaseName` ,
108+ {
107109 smart_count : selectedIds . length ,
108- _ : resource
109- ? inflect ( resource , selectedIds . length )
110- : undefined ,
111- } ) ,
112- true
110+ _ : humanize (
111+ translate ( `resources.${ resource } .name` , {
112+ smart_count : selectedIds . length ,
113+ _ : resource
114+ ? inflect (
115+ resource ,
116+ selectedIds . length
117+ )
118+ : undefined ,
119+ } ) ,
120+ true
121+ ) ,
122+ }
113123 ) ,
114- } ) ,
115- } }
116- contentTranslateOptions = { {
117- smart_count : selectedIds . length ,
118- name : translate ( `resources.${ resource } .forcedCaseName` , {
124+ } }
125+ contentTranslateOptions = { {
119126 smart_count : selectedIds . length ,
120- _ : humanize (
121- translate ( `resources.${ resource } .name` , {
127+ name : translate (
128+ `resources.${ resource } .forcedCaseName` ,
129+ {
122130 smart_count : selectedIds . length ,
123- _ : resource
124- ? inflect ( resource , selectedIds . length )
125- : undefined ,
126- } ) ,
127- true
131+ _ : humanize (
132+ translate ( `resources.${ resource } .name` , {
133+ smart_count : selectedIds . length ,
134+ _ : resource
135+ ? inflect (
136+ resource ,
137+ selectedIds . length
138+ )
139+ : undefined ,
140+ } ) ,
141+ true
142+ ) ,
143+ }
128144 ) ,
129- } ) ,
130- } }
131- onConfirm = { handleConfirm }
132- onClose = { handleDialogClose }
133- / >
134- </ Fragment >
135- ) ;
136- } ;
145+ } }
146+ onConfirm = { handleConfirm }
147+ onClose = { handleDialogClose }
148+ />
149+ </ Fragment >
150+ ) ;
151+ }
152+ ) ;
137153
138154const sanitizeRestProps = ( {
139155 classes,
0 commit comments