This repository was archived by the owner on Jan 14, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 231
feat(drawer): add innerRef prop #749
Merged
moog16
merged 11 commits into
material-components:rc0.11.0
from
lucasecdb:feat/drawer-ref
Mar 18, 2019
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
5bde5ba
Upgrade mdcw drawer version to 1.0.1
lucasecdb 8f205ca
Add innerRef prop
lucasecdb c5db14c
Use mount for tests
lucasecdb 19d6574
Avoid passing innerRef to element
lucasecdb 6bf9e7d
Fix tests
lucasecdb a07b633
Fix typings
lucasecdb 1f1d804
Fix some test typings
lucasecdb cec9a08
Fix failing test
lucasecdb 7a80246
Make foundation optional
lucasecdb fb77d32
Update attachRef function
lucasecdb aeddb73
Add innerRef prop to readme
lucasecdb File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,8 +26,7 @@ import { | |
MDCDismissibleDrawerFoundation, | ||
MDCModalDrawerFoundation, | ||
util, | ||
// @ts-ignore no .d.ts file | ||
} from '@material/drawer/dist/mdc.drawer'; | ||
} from '@material/drawer'; | ||
// @ts-ignore no .d.ts file | ||
import {MDCListFoundation} from '@material/list/dist/mdc.list'; | ||
import DrawerHeader from './Header'; | ||
|
@@ -39,6 +38,8 @@ import {FocusTrap} from 'focus-trap'; | |
|
||
const {cssClasses: listCssClasses} = MDCListFoundation; | ||
|
||
type RefCallback<T> = (node: T) => void; | ||
|
||
export interface DrawerProps extends React.HTMLProps<HTMLElement>{ | ||
className?: string; | ||
open?: boolean; | ||
|
@@ -47,15 +48,20 @@ export interface DrawerProps extends React.HTMLProps<HTMLElement>{ | |
tag?: string; | ||
dismissible?: boolean; | ||
modal?: boolean; | ||
innerRef?: RefCallback<HTMLElement> | React.RefObject<HTMLElement>; | ||
}; | ||
|
||
interface DrawerState { | ||
classList: Set<string>; | ||
}; | ||
|
||
const isRefObject = function(ref: DrawerProps['innerRef']): ref is React.RefObject<HTMLElement> { | ||
return typeof ref !== 'function'; | ||
}; | ||
|
||
class Drawer extends React.Component<DrawerProps, DrawerState> { | ||
previousFocus: HTMLElement | null = null; | ||
foundation: MDCDismissibleDrawerFoundation | MDCModalDrawerFoundation; | ||
foundation?: MDCDismissibleDrawerFoundation | MDCModalDrawerFoundation; | ||
focusTrap?: FocusTrap; | ||
drawerElement: React.RefObject<HTMLDivElement> = React.createRef(); | ||
|
||
|
@@ -106,7 +112,7 @@ class Drawer extends React.Component<DrawerProps, DrawerState> { | |
if (changedToModal || changedToDismissible) { | ||
this.initFoundation(); | ||
} | ||
if (open !== prevProps.open) { | ||
if (open !== prevProps.open && this.foundation) { | ||
open ? this.foundation.open() : this.foundation.close(); | ||
} | ||
} | ||
|
@@ -117,7 +123,7 @@ class Drawer extends React.Component<DrawerProps, DrawerState> { | |
} | ||
|
||
private initializeFocusTrap = () => { | ||
this.focusTrap = util.createFocusTrapInstance(this.drawerElement.current); | ||
this.focusTrap = util.createFocusTrapInstance(this.drawerElement.current!); | ||
}; | ||
|
||
get classes() { | ||
|
@@ -184,15 +190,34 @@ class Drawer extends React.Component<DrawerProps, DrawerState> { | |
handleKeyDown = (evt: React.KeyboardEvent<HTMLElement>) => { | ||
this.props.onKeyDown!(evt); | ||
if (!this.foundation) return; | ||
this.foundation.handleKeydown(evt); | ||
this.foundation.handleKeydown(evt.nativeEvent); | ||
}; | ||
|
||
handleTransitionEnd = (evt: React.TransitionEvent<HTMLElement>) => { | ||
this.props.onTransitionEnd!(evt); | ||
if (!this.foundation) return; | ||
this.foundation.handleTransitionEnd(evt); | ||
this.foundation.handleTransitionEnd(evt.nativeEvent); | ||
}; | ||
|
||
attachRef = (node: HTMLElement) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like this pattern - we should actually normalize this across all components. We are doing something similar with textfield but this is a lot cleaner. |
||
const {innerRef} = this.props; | ||
|
||
// https://github.com/facebook/react/issues/13029#issuecomment-410002316 | ||
// @ts-ignore this is acceptable according to the comment above | ||
this.drawerElement.current = node; | ||
|
||
if (!innerRef) { | ||
return; | ||
} | ||
|
||
if (isRefObject(innerRef)) { | ||
// @ts-ignore same as above | ||
innerRef.current = node; | ||
} else { | ||
innerRef(node); | ||
} | ||
} | ||
|
||
render() { | ||
const { | ||
/* eslint-disable no-unused-vars */ | ||
|
@@ -203,9 +228,10 @@ class Drawer extends React.Component<DrawerProps, DrawerState> { | |
dismissible, | ||
children, | ||
className, | ||
innerRef, | ||
modal, | ||
/* eslint-enable no-unused-vars */ | ||
tag: Tag, | ||
modal, | ||
...otherProps | ||
} = this.props; | ||
|
||
|
@@ -215,7 +241,7 @@ class Drawer extends React.Component<DrawerProps, DrawerState> { | |
// @ts-ignore */} | ||
<Tag | ||
className={this.classes} | ||
ref={this.drawerElement} | ||
ref={this.attachRef} | ||
onKeyDown={this.handleKeyDown} | ||
onTransitionEnd={this.handleTransitionEnd} | ||
{...otherProps} | ||
|
@@ -226,11 +252,12 @@ class Drawer extends React.Component<DrawerProps, DrawerState> { | |
</React.Fragment> | ||
); | ||
} | ||
|
||
renderScrim() { | ||
return ( | ||
<div | ||
className='mdc-drawer-scrim' | ||
onClick={() => this.foundation.handleScrimClick()} | ||
onClick={() => (this.foundation as MDCModalDrawerFoundation).handleScrimClick()} | ||
/> | ||
); | ||
} | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.