Skip to content

Commit

Permalink
Fixes #214 - Correct type and callbacks for transition handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
iamhosseindhv committed Feb 23, 2020
2 parents d22ae1e + 20327b5 commit d0979b7
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 12 deletions.
11 changes: 9 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
Thanks to all contributers who improved notistack by opening an issue/PR.

### `[email protected].8`
### `[email protected].9`
###### to be published
* **@pctestjfarz**: Add swipe to dismiss feature [#138](https://github.com/iamhosseindhv/notistack/issues/138)
* **@molynerd**: Add support to update content of snackbar in place [#50](https://github.com/iamhosseindhv/notistack/issues/50)
* **@david-chau**: Allow `asc`, `desc` or custom sort order of snackbars [#160](https://github.com/iamhosseindhv/notistack/issues/160)
* **@madaz**: Add higher priority to Snackbar styles [#202](https://github.com/iamhosseindhv/notistack/issues/202)


<br />


### `[email protected]`
###### Feb 23, 2020
* **@svish**: Correct enqueueSnackbar typing [#217](https://github.com/iamhosseindhv/notistack/issues/217)
* **@dgczhh**: Make sure `onClose` callback that's been passed through options parameter of `enqueueSnackbar` gets called when snackbar is closed using `closeSnackbar` function [#220](https://github.com/iamhosseindhv/notistack/issues/220)
* **@JoseLion**: Add snackbar key to transition handler parameters. Fix transition handler callback types [#214](https://github.com/iamhosseindhv/notistack/issues/214)


<br />
Expand Down
16 changes: 16 additions & 0 deletions src/SnackbarItem/SnackbarItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,21 @@ class SnackbarItem extends Component {
}, 125);
}

get unusedCallbacks() {
return ['onEnter', 'onEntering', 'onExit', 'onExiting'].reduce((acc, cbName) => ({
...acc,
[cbName]: (...args) => {
const { snack } = this.props;
if (typeof snack[cbName] === 'function') {
snack[cbName](...args, snack.key);
}
if (typeof this.props[cbName] === 'function') {
this.props[cbName](...args, snack.key);
}
},
}), {});
}

render() {
const {
classes,
Expand Down Expand Up @@ -136,6 +151,7 @@ class SnackbarItem extends Component {
classes={getSnackbarClasses(classes)}
onClose={this.handleClose(key)}
onEntered={this.handleEntered(key)}
{...this.unusedCallbacks}
>
{snackContent || (
<SnackbarContent
Expand Down
7 changes: 4 additions & 3 deletions src/SnackbarProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,10 @@ class SnackbarProvider extends Component {
// call individual snackbar onClose callback passed through options parameter
const toBeClosed = this.state.snacks.find(item => item.key === key);
if (toBeClosed && toBeClosed.onClose) {
toBeClosed.onClose(null, null, key);
toBeClosed.onClose(null, REASONS.INSTRUCTED, key);
}

this.handleCloseSnack(null, null, key);
this.handleCloseSnack(null, REASONS.INSTRUCTED, key);
}

/**
Expand Down Expand Up @@ -378,7 +378,8 @@ SnackbarProvider.propTypes = {
*
* @param {object} event The event source of the callback
* @param {string} reason Can be:`"timeout"` (`autoHideDuration` expired) or: `"clickaway"`
* or: `"maxsnack"` (snackbar is closed because `maxSnack` has reached.)
* or: `"maxsnack"` (snackbar was closed because `maxSnack` has reached) or: `"instructed"`
* (snackbar was closed programmatically)
* @param {string|number} key key of a Snackbar
*/
onClose: PropTypes.func,
Expand Down
31 changes: 24 additions & 7 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,32 @@ import { SnackbarContentProps } from '@material-ui/core/SnackbarContent';

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
type ClassNameMap<ClassKey extends string = string> = Record<ClassKey, string>;
type Modify<T, R> = Pick<T, Exclude<keyof T, keyof R>> & R

type RemovedAttributes = 'open' | 'message' | 'classes';
export type SnackbarKey = string | number;
export type VariantType = 'default' | 'error' | 'success' | 'warning' | 'info';

export type SnackbarMessage = string | React.ReactNode;
export type SnackbarAction = SnackbarContentProps['action'] | ((key: OptionsObject['key']) => React.ReactNode);
export type SnackbarContent = React.ReactNode | ((key: OptionsObject['key'], message: SnackbarMessage) => React.ReactNode);
export type SnackbarAction = SnackbarContentProps['action'] | ((key: SnackbarKey) => React.ReactNode);
export type SnackbarContent = React.ReactNode | ((key: SnackbarKey, message: SnackbarMessage) => React.ReactNode);

export interface OptionsObject extends Omit<SnackbarProps, 'open' | 'message' | 'classes'> {
key?: string | number;
export type CloseReason = 'timeout' | 'clickaway' | 'maxsnack' | 'instructed';
export type TransitionCloseHandler = (event: React.SyntheticEvent<any> | null, reason: CloseReason, key: SnackbarKey) => void;
export type TransitionEnterHandler = (node: HTMLElement, isAppearing: boolean, key: SnackbarKey) => void;
export type TransitionHandler = (node: HTMLElement, key: SnackbarKey) => void;
export type TransitionHandlerProps = {
onClose?: TransitionCloseHandler;
onEnter?: TransitionHandler;
onEntering?: TransitionHandler;
onEntered?: TransitionEnterHandler;
onExit?: TransitionHandler;
onExiting?: TransitionHandler;
onExited?: TransitionHandler;
}

export interface OptionsObject extends Modify<Omit<SnackbarProps, RemovedAttributes>, TransitionHandlerProps> {
key?: SnackbarKey;
variant?: VariantType;
persist?: boolean;
preventDuplicate?: boolean;
Expand All @@ -33,8 +50,8 @@ export type VariantClassKey = 'variantSuccess' | 'variantError' | 'variantInfo'
export type CombinedClassKey = VariantClassKey | ContainerClassKey | SnackbarClassKey;

export interface WithSnackbarProps {
enqueueSnackbar: (message: SnackbarMessage, options?: OptionsObject) => OptionsObject['key'];
closeSnackbar: (key?: OptionsObject['key']) => void;
enqueueSnackbar: (message: SnackbarMessage, options?: OptionsObject) => SnackbarKey;
closeSnackbar: (key?: SnackbarKey) => void;
}

export function withSnackbar<P extends WithSnackbarProps>(component: React.ComponentType<P>):
Expand All @@ -44,7 +61,7 @@ export function withSnackbar<P extends WithSnackbarProps>(component: React.Compo
export function useSnackbar(): WithSnackbarProps;

// all material-ui props, including class keys for notistack and material-ui with additional notistack props
export interface SnackbarProviderProps extends Omit<SnackbarProps, 'open' | 'message' | 'classes'> {
export interface SnackbarProviderProps extends Modify<Omit<SnackbarProps, RemovedAttributes>, TransitionHandlerProps> {
classes?: Partial<ClassNameMap<CombinedClassKey>>;
maxSnack?: number;
iconVariant?: Partial<Record<VariantType, React.ReactNode>>;
Expand Down
1 change: 1 addition & 0 deletions src/utils/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,5 @@ export const originKeyExtractor = anchor => `${capitalise(anchor.vertical)}${cap
export const REASONS = {
CLICKAWAY: 'clickaway',
MAXSNACK: 'maxsnack',
INSTRUCTED: 'instructed',
};

0 comments on commit d0979b7

Please sign in to comment.