@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
import PropTypes from 'prop-types' ;
3
3
import Button from '@mui/material/Button' ;
4
4
import Divider from '@mui/material/Divider' ;
5
- import { styled , alpha , ThemeProvider } from '@mui/material/styles' ;
5
+ import { styled , alpha , ThemeProvider , Theme } from '@mui/material/styles' ;
6
6
import List from '@mui/material/List' ;
7
7
import Drawer from '@mui/material/Drawer' ;
8
8
import Typography from '@mui/material/Typography' ;
@@ -21,17 +21,18 @@ import DoneRounded from '@mui/icons-material/DoneRounded';
21
21
import LogoWithCopyMenu from 'docs/src/components/action/LogoWithCopyMenu' ;
22
22
import AppNavDrawerItem from 'docs/src/modules/components/AppNavDrawerItem' ;
23
23
import { pageToTitleI18n } from 'docs/src/modules/utils/helpers' ;
24
- import PageContext from 'docs/src/modules/components/PageContext' ;
24
+ import PageContext , { ProductVersion } from 'docs/src/modules/components/PageContext' ;
25
25
import { useTranslate } from '@mui/docs/i18n' ;
26
26
import MuiProductSelector from 'docs/src/modules/components/MuiProductSelector' ;
27
+ import { MuiPage } from 'docs/src/MuiPage' ;
27
28
28
29
// TODO: Collapse should expose an API to customize the duration based on the height.
29
- function transitionTheme ( theme ) {
30
+ function transitionTheme ( theme : Theme ) {
30
31
return {
31
32
...theme ,
32
33
transitions : {
33
34
...theme . transitions ,
34
- getAutoHeightDuration : ( height ) => {
35
+ getAutoHeightDuration : ( height : number ) => {
35
36
if ( ! height ) {
36
37
return 0 ;
37
38
}
@@ -45,9 +46,9 @@ function transitionTheme(theme) {
45
46
} ;
46
47
}
47
48
48
- const savedScrollTop = { } ;
49
+ const savedScrollTop : Record < string , number > = { } ;
49
50
50
- const customButtonStyles = ( theme ) => ( {
51
+ const customButtonStyles = ( theme : Theme ) => ( {
51
52
pl : 1 ,
52
53
pr : '6px' ,
53
54
height : 26 ,
@@ -56,22 +57,26 @@ const customButtonStyles = (theme) => ({
56
57
letterSpacing : '0.01rem' ,
57
58
} ) ;
58
59
59
- function ProductDrawerButton ( props ) {
60
+ interface ProductDrawerButtonProps {
61
+ productName : string ;
62
+ }
63
+
64
+ function ProductDrawerButton ( props : ProductDrawerButtonProps ) {
60
65
const [ open , setOpen ] = React . useState ( false ) ;
61
- const anchorRef = React . useRef ( null ) ;
66
+ const anchorRef = React . useRef < HTMLButtonElement > ( null ) ;
62
67
63
68
const handleToggle = ( ) => {
64
69
setOpen ( ( prevOpen ) => ! prevOpen ) ;
65
70
} ;
66
71
67
- const handleClose = ( event ) => {
68
- if ( anchorRef . current && anchorRef . current . contains ( event . target ) ) {
72
+ const handleClose = ( event : MouseEvent | TouchEvent ) => {
73
+ if ( anchorRef . current && anchorRef . current . contains ( event . target as Node ) ) {
69
74
return ;
70
75
}
71
76
setOpen ( false ) ;
72
77
} ;
73
78
74
- function handleListKeyDown ( event ) {
79
+ function handleListKeyDown ( event : React . KeyboardEvent < HTMLDivElement > ) {
75
80
if ( event . key === 'Tab' ) {
76
81
event . preventDefault ( ) ;
77
82
setOpen ( false ) ;
@@ -138,7 +143,13 @@ ProductDrawerButton.propTypes = {
138
143
productName : PropTypes . string ,
139
144
} ;
140
145
141
- function ProductIdentifier ( props ) {
146
+ interface ProductIdentifierProps {
147
+ name : string ;
148
+ metadata : string ;
149
+ versionSelector : React . ReactNode ;
150
+ }
151
+
152
+ function ProductIdentifier ( props : ProductIdentifierProps ) {
142
153
const { name, metadata, versionSelector } = props ;
143
154
return (
144
155
< Box sx = { { flexGrow : 1 } } >
@@ -171,13 +182,19 @@ ProductIdentifier.propTypes = {
171
182
// To match scrollMarginBottom
172
183
const browserUrlPreviewMarge = 120 ;
173
184
174
- function PersistScroll ( props ) {
185
+ interface PersistScrollProps {
186
+ children : React . ReactNode ;
187
+ enabled : boolean ;
188
+ slot : string ;
189
+ }
190
+
191
+ function PersistScroll ( props : PersistScrollProps ) {
175
192
const { slot, children, enabled } = props ;
176
- const rootRef = React . useRef ( ) ;
193
+ const rootRef = React . useRef < HTMLDivElement > ( null ) ;
177
194
178
195
useEnhancedEffect ( ( ) => {
179
196
const scrollContainer = rootRef . current ? rootRef . current . parentElement : null ;
180
- const activeDrawerLink = scrollContainer . querySelector ( '.app-drawer-active' ) ;
197
+ const activeDrawerLink = scrollContainer ? .querySelector ( '.app-drawer-active' ) ;
181
198
182
199
if ( ! enabled || ! scrollContainer || ! activeDrawerLink || ! activeDrawerLink . scrollIntoView ) {
183
200
return undefined ;
@@ -235,24 +252,38 @@ const AppNavPaperComponent = styled('div')(() => {
235
252
width : 'var(--MuiDocs-navDrawer-width)' ,
236
253
boxShadow : 'none' ,
237
254
border : '0 !important' , // TODO add a Paper slot
238
- overflowY : 'unset !important' , // TODO add a Paper slot
255
+ overflowY : 'unset !important' as 'unset' , // TODO add a Paper slot
239
256
boxSizing : 'border-box' , // TODO have CssBaseline in the Next.js layout
240
257
} ;
241
258
} ) ;
242
259
243
- function renderNavItems ( options ) {
260
+ interface RenderNavItemsOptions {
261
+ onClose : ( ) => void ;
262
+ pages : MuiPage [ ] ;
263
+ activePageParents : MuiPage [ ] ;
264
+ depth : number ;
265
+ t : ( key : string ) => string ;
266
+ }
267
+
268
+ function renderNavItems ( options : RenderNavItemsOptions ) {
244
269
const { pages, ...params } = options ;
245
270
246
271
return (
247
- < List > { pages . reduce ( ( items , page ) => reduceChildRoutes ( { items, page, ...params } ) , [ ] ) } </ List >
272
+ < List >
273
+ { pages . reduce (
274
+ ( items , page ) => reduceChildRoutes ( { items, page, ...params } ) ,
275
+ [ ] as React . ReactNode [ ] ,
276
+ ) }
277
+ </ List >
248
278
) ;
249
279
}
250
280
251
- /**
252
- * @param {object } context
253
- * @param {import('docs/src/pages').MuiPage } context.page
254
- */
255
- function reduceChildRoutes ( context ) {
281
+ interface ReduceChildRoutesContext extends Omit < RenderNavItemsOptions , 'pages' > {
282
+ items : React . ReactNode [ ] ;
283
+ page : MuiPage ;
284
+ }
285
+
286
+ function reduceChildRoutes ( context : ReduceChildRoutesContext ) : React . ReactNode [ ] {
256
287
const { onClose, activePageParents, items, depth, t } = context ;
257
288
const { page } = context ;
258
289
if ( page . inSideNav === false ) {
@@ -339,18 +370,26 @@ function reduceChildRoutes(context) {
339
370
// So: <SwipeableDrawer disableBackdropTransition={false} />
340
371
const iOS = typeof navigator !== 'undefined' && / i P a d | i P h o n e | i P o d / . test ( navigator . userAgent ) ;
341
372
342
- export default function AppNavDrawer ( props ) {
373
+ export interface AppNavDrawerProps {
374
+ className ?: string ;
375
+ disablePermanent : boolean ;
376
+ mobileOpen : boolean ;
377
+ onClose : ( ) => void ;
378
+ onOpen : ( ) => void ;
379
+ }
380
+
381
+ export default function AppNavDrawer ( props : AppNavDrawerProps ) {
343
382
const { className, disablePermanent, mobileOpen, onClose, onOpen } = props ;
344
383
const { activePageParents, pages, productIdentifier } = React . useContext ( PageContext ) ;
345
- const [ anchorEl , setAnchorEl ] = React . useState ( null ) ;
384
+ const [ anchorEl , setAnchorEl ] = React . useState < HTMLButtonElement | null > ( null ) ;
346
385
const t = useTranslate ( ) ;
347
386
const mobile = useMediaQuery ( ( theme ) => theme . breakpoints . down ( 'lg' ) ) ;
348
387
const swipeableDrawer = disablePermanent || mobile ;
349
388
350
389
const drawer = React . useMemo ( ( ) => {
351
390
const navItems = renderNavItems ( { onClose, pages, activePageParents, depth : 0 , t } ) ;
352
391
353
- const renderVersionSelector = ( versions ) => {
392
+ const renderVersionSelector = ( versions : ProductVersion [ ] ) => {
354
393
if ( ! versions ?. length ) {
355
394
return null ;
356
395
}
0 commit comments