@@ -6,23 +6,24 @@ import FocusBounder from 'react-focus-bounder'
66import { useTranslation } from 'react-i18next'
77
88import ClassNames from 'classnames'
9- // @ts -expect-error No types available
10- import * as VelocityReact from 'velocity-react'
119import { logger } from './logging'
1210import * as _ from 'underscore'
1311import { withTranslation } from 'react-i18next'
1412import { Translated } from './ReactMeteorData/ReactMeteorData'
1513import { EditAttribute , EditAttributeType , IEditAttributeBaseProps } from './EditAttribute'
1614import { Settings } from '../lib/Settings'
1715
16+ import Modal from 'react-bootstrap/Modal'
17+ import Button from 'react-bootstrap/Button'
18+
1819interface IModalDialogAttributes {
1920 show ?: boolean
2021 title : string
2122 secondaryText ?: string
2223 acceptText : string
2324 onAccept ?: ( e : SomeEvent , inputResult : ModalInputResult ) => void
24- onSecondary ?: ( e : SomeEvent , inputResult : ModalInputResult ) => void
25- onDiscard ?: ( e : SomeEvent , inputResult : ModalInputResult ) => void
25+ onSecondary ?: ( e : SomeEvent | undefined , inputResult : ModalInputResult ) => void
26+ onDiscard ?: ( e : SomeEvent | undefined , inputResult : ModalInputResult ) => void
2627 inputs ?: { [ attribute : string ] : ModalInput }
2728 warning ?: boolean
2829 actions ?: ModalAction [ ]
@@ -74,15 +75,15 @@ export function ModalDialog({
7475 onAccept ?.( e , inputResult . current )
7576 }
7677
77- function handleDiscard ( e : SomeEvent ) {
78+ function handleDiscard ( e ? : SomeEvent ) {
7879 if ( onDiscard ) {
7980 onDiscard ( e , inputResult . current )
8081 return
8182 }
8283 handleSecondary ( e )
8384 }
8485
85- function handleSecondary ( e : SomeEvent ) {
86+ function handleSecondary ( e : SomeEvent | undefined ) {
8687 onSecondary ?.( e , inputResult . current )
8788 }
8889
@@ -101,16 +102,16 @@ export function ModalDialog({
101102 e . currentTarget . click ( )
102103 }
103104
104- function onDialogKeyDown ( e : React . KeyboardEvent < HTMLDialogElement > ) {
105- if ( ! ( e . target instanceof HTMLDialogElement ) ) return
105+ function onDialogKeyDown ( e : React . KeyboardEvent < HTMLDivElement > ) {
106+ if ( ! ( e . target instanceof HTMLDivElement ) ) return
106107 if ( ! isAcceptKey ( e . code ) && ! isDismissKey ( e . code ) ) return
107108
108109 e . preventDefault ( )
109110 e . stopPropagation ( )
110111 }
111112
112- function onDialogKeyUp ( e : React . KeyboardEvent < HTMLDialogElement > ) {
113- if ( ! ( e . target instanceof HTMLDialogElement ) ) return
113+ function onDialogKeyUp ( e : React . KeyboardEvent < HTMLDivElement > ) {
114+ if ( ! ( e . target instanceof HTMLDivElement ) ) return
114115 if ( ! isAcceptKey ( e . code ) && ! isDismissKey ( e . code ) ) return
115116 e . preventDefault ( )
116117 e . stopPropagation ( )
@@ -141,135 +142,106 @@ export function ModalDialog({
141142
142143 return (
143144 < Escape to = "viewport" >
144- < VelocityReact . VelocityTransitionGroup
145- enter = { { animation : 'fadeIn' , easing : 'ease-out' , duration : 250 } }
146- runOnMount = { true }
147- >
148- < div className = "glass-pane" >
149- < FocusBounder >
150- < div className = "glass-pane-content" >
151- < VelocityReact . VelocityTransitionGroup
152- enter = { {
153- animation : {
154- translateY : [ 0 , 100 ] ,
155- opacity : [ 1 , 0 ] ,
145+ < FocusBounder >
146+ < div onKeyDown = { onDialogKeyDown } onKeyUp = { onDialogKeyUp } >
147+ < Modal
148+ show = { show }
149+ onHide = { handleDiscard }
150+ onEscapeKeyDown = { handleDiscard }
151+ backdrop = "static"
152+ keyboard
153+ className = { className }
154+ scrollable
155+ >
156+ < Modal . Header closeVariant = "white" className = { warning ? 'modal-header-warn' : 'modal-header-info' } >
157+ < Modal . Title className = { 'grid-buttons-right w-100' } >
158+ < h2 > { title } </ h2 >
159+
160+ < button
161+ className = "action-btn"
162+ onClick = { handleDiscard }
163+ onKeyDown = { preventClickOnEnter }
164+ onKeyUp = { emulateClick }
165+ aria-label = { t ( 'Dismiss' ) }
166+ >
167+ < CoreIcons . NrkClose />
168+ </ button >
169+ </ Modal . Title >
170+ </ Modal . Header >
171+ < Modal . Body > { children } </ Modal . Body >
172+ < Modal . Footer >
173+ { inputs ? (
174+ < div className = "title-box-inputs" >
175+ { _ . map ( inputs , ( input : ModalInput , attribute : string ) => {
176+ return (
177+ < div className = "title-box-input" key = { attribute } >
178+ { input . text }
179+ < EditAttribute
180+ type = { input . type }
181+ label = { input . label }
182+ options = { input . options }
183+ overrideDisplayValue = { input . defaultValue }
184+ attribute = { attribute }
185+ updateFunction = { updateInput }
186+ />
187+ </ div >
188+ )
189+ } ) }
190+ </ div >
191+ ) : null }
192+ < div
193+ className = { ClassNames (
194+ {
195+ 'text-end' : ! secondaryText ,
156196 } ,
157- easing : 'spring' ,
158- duration : 250 ,
159- } }
160- runOnMount = { true }
197+ 'modal-dialog-actions'
198+ ) }
161199 >
162- < dialog
163- open = { true }
164- className = { 'border-box overlay-m ' + className || '' }
165- role = "alertdialog"
166- onKeyUp = { onDialogKeyUp }
167- onKeyDown = { onDialogKeyDown }
168- >
169- < div className = { 'flex-row ' + ( warning ? 'warn' : 'info' ) + ' vertical-align-stretch tight-s' } >
170- < div className = "flex-col c12" >
171- < h2 > { title } </ h2 >
172- </ div >
173- < div className = "flex-col horizontal-align-right vertical-align-middle" >
174- < p >
175- < button
176- className = "action-btn"
177- onClick = { handleDiscard }
178- onKeyDown = { preventClickOnEnter }
179- onKeyUp = { emulateClick }
180- aria-label = { t ( 'Dismiss' ) }
181- >
182- < CoreIcons . NrkClose />
183- </ button >
184- </ p >
185- </ div >
186- </ div >
187- < div className = "title-box-content" > { children } </ div >
188- { inputs ? (
189- < div className = "title-box-inputs" >
190- { _ . map ( inputs , ( input : ModalInput , attribute : string ) => {
191- return (
192- < div className = "title-box-input" key = { attribute } >
193- { input . text }
194- < EditAttribute
195- type = { input . type }
196- label = { input . label }
197- options = { input . options }
198- overrideDisplayValue = { input . defaultValue }
199- attribute = { attribute }
200- updateFunction = { updateInput }
201- />
202- </ div >
203- )
204- } ) }
205- </ div >
206- ) : null }
207- < div
208- className = { ClassNames (
209- 'mod' ,
210- {
211- 'text-end' : ! secondaryText ,
212- } ,
213- 'modal-dialog-actions'
214- ) }
200+ { secondaryText && (
201+ < Button
202+ variant = { discardAsPrimary ? ( warning ? 'warn' : 'primary' ) : 'outline-secondary' }
203+ className = { 'discard-btn' }
204+ autoFocus = { discardAsPrimary }
205+ onClick = { handleSecondary }
206+ onKeyDown = { preventClickOnEnter }
207+ onKeyUp = { emulateClick }
215208 >
216- { secondaryText && (
217- < button
218- className = { ClassNames (
219- 'btn' ,
220- discardAsPrimary ? 'btn-primary' : 'btn-secondary' ,
221- 'discard-btn' ,
222- { 'btn-warn' : discardAsPrimary && warning }
223- ) }
224- autoFocus = { discardAsPrimary }
225- onClick = { handleSecondary }
226- onKeyDown = { preventClickOnEnter }
227- onKeyUp = { emulateClick }
228- >
229- { secondaryText }
230- </ button >
231- ) }
232- { _ . compact (
233- _ . map ( actions || [ ] , ( action : ModalAction , i ) => {
234- if ( ! action ) return null
235- return (
236- < button
237- key = { i }
238- className = { ClassNames (
239- 'btn right mrs' ,
240- {
241- 'btn-secondary' : ! ( action . classNames || '' ) . match ( / b t n - / ) ,
242- } ,
243- action . classNames
244- ) }
245- onClick = { ( e ) => handleAction ( e , action . on ) }
246- onKeyDown = { preventClickOnEnter }
247- onKeyUp = { emulateClick }
248- >
249- { action . label }
250- </ button >
251- )
252- } )
253- ) }
254- < button
255- className = { ClassNames ( 'btn' , ! discardAsPrimary ? 'btn-primary' : 'btn-secondary' , {
256- right : secondaryText !== undefined ,
257- 'btn-warn' : ! discardAsPrimary && warning ,
258- } ) }
259- autoFocus = { ! discardAsPrimary }
260- onClick = { handleAccept }
209+ { secondaryText }
210+ </ Button >
211+ ) }
212+ { actions ?. map ( ( action , i ) => {
213+ if ( ! action ) return null
214+
215+ return (
216+ < Button
217+ key = { i }
218+ variant = { ! ( action . classNames || '' ) . match ( / b t n - / ) ? 'outline-secondary' : undefined }
219+ className = { ClassNames ( 'right mrs' , action . classNames ) }
220+ onClick = { ( e ) => handleAction ( e , action . on ) }
261221 onKeyDown = { preventClickOnEnter }
262222 onKeyUp = { emulateClick }
263223 >
264- { acceptText }
265- </ button >
266- </ div >
267- </ dialog >
268- </ VelocityReact . VelocityTransitionGroup >
269- </ div >
270- </ FocusBounder >
224+ { action . label }
225+ </ Button >
226+ )
227+ } ) }
228+ < Button
229+ variant = { ! discardAsPrimary ? ( warning ? 'warn' : 'primary' ) : 'outline-secondary' }
230+ className = { ClassNames ( {
231+ right : secondaryText !== undefined ,
232+ } ) }
233+ autoFocus = { ! discardAsPrimary }
234+ onClick = { handleAccept }
235+ onKeyDown = { preventClickOnEnter }
236+ onKeyUp = { emulateClick }
237+ >
238+ { acceptText }
239+ </ Button >
240+ </ div >
241+ </ Modal . Footer >
242+ </ Modal >
271243 </ div >
272- </ VelocityReact . VelocityTransitionGroup >
244+ </ FocusBounder >
273245 </ Escape >
274246 )
275247}
0 commit comments