Skip to content

Commit

Permalink
[core] feat(MultiStepDialog): Allow skipping to a specific step in th…
Browse files Browse the repository at this point in the history
…e dialog (#4730)
  • Loading branch information
styu authored May 25, 2021
1 parent 826cbdf commit 061762c
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 9 deletions.
39 changes: 31 additions & 8 deletions packages/core/src/components/dialog/multistepDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,17 @@ export interface IMultistepDialogProps extends DialogProps {
/**
* Whether to reset the dialog state to its initial state on close.
* By default, closing the dialog will reset its state.
*
* @default true
*/
resetOnClose?: boolean;

/**
* A 0 indexed initial step to start off on, to start in the middle of the dialog, for example.
* If the provided index exceeds the number of steps, it defaults to the last step.
* If a negative index is provided, it defaults to the first step.
*/
initialStepIndex?: number;
}

interface IMultistepDialogState {
Expand All @@ -70,21 +79,17 @@ const PADDING_BOTTOM = 0;

const MIN_WIDTH = 800;

const INITIAL_STATE = {
lastViewedIndex: 0,
selectedIndex: 0,
};

@polyfill
export class MultistepDialog extends AbstractPureComponent2<MultistepDialogProps, IMultistepDialogState> {
public static displayName = `${DISPLAYNAME_PREFIX}.MultistepDialog`;

public static defaultProps: Partial<MultistepDialogProps> = {
canOutsideClickClose: true,
isOpen: false,
resetOnClose: true,
};

public state: IMultistepDialogState = INITIAL_STATE;
public state: IMultistepDialogState = this.getInitialIndexFromProps(this.props);

public render() {
return (
Expand All @@ -99,11 +104,11 @@ export class MultistepDialog extends AbstractPureComponent2<MultistepDialogProps

public componentDidUpdate(prevProps: MultistepDialogProps) {
if (
(prevProps.resetOnClose === undefined || prevProps.resetOnClose) &&
(prevProps.resetOnClose || prevProps.initialStepIndex !== this.props.initialStepIndex) &&
!prevProps.isOpen &&
this.props.isOpen
) {
this.setState(INITIAL_STATE);
this.setState(this.getInitialIndexFromProps(this.props));
}
}

Expand Down Expand Up @@ -225,6 +230,24 @@ export class MultistepDialog extends AbstractPureComponent2<MultistepDialogProps
private getDialogStepChildren(props: MultistepDialogProps & { children?: React.ReactNode } = this.props) {
return React.Children.toArray(props.children).filter(isDialogStepElement);
}

private getInitialIndexFromProps(props: MultistepDialogProps) {
if (props.initialStepIndex !== undefined) {
const boundedInitialIndex = Math.max(
0,
Math.min(props.initialStepIndex, this.getDialogStepChildren(props).length - 1),
);
return {
lastViewedIndex: boundedInitialIndex,
selectedIndex: boundedInitialIndex,
};
} else {
return {
lastViewedIndex: 0,
selectedIndex: 0,
};
}
}
}

function isDialogStepElement(child: any): child is DialogStepElement {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import {
ButtonProps,
RadioGroup,
Radio,
NumericInput,
Label,
} from "@blueprintjs/core";
import { Example, handleBooleanChange, handleStringChange, IExampleProps } from "@blueprintjs/docs-theme";

Expand All @@ -41,6 +43,7 @@ export interface IMultistepDialogExampleState {
isOpen: boolean;
usePortal: boolean;
value?: string;
initialStepIndex: number;
}

export class MultistepDialogExample extends React.PureComponent<
Expand All @@ -52,6 +55,7 @@ export class MultistepDialogExample extends React.PureComponent<
canEscapeKeyClose: true,
canOutsideClickClose: true,
enforceFocus: true,
initialStepIndex: 0,
isOpen: false,
usePortal: true,
};
Expand Down Expand Up @@ -100,7 +104,14 @@ export class MultistepDialogExample extends React.PureComponent<
}

private renderOptions() {
const { autoFocus, enforceFocus, canEscapeKeyClose, canOutsideClickClose, usePortal } = this.state;
const {
autoFocus,
enforceFocus,
canEscapeKeyClose,
canOutsideClickClose,
usePortal,
initialStepIndex,
} = this.state;
return (
<>
<H5>Props</H5>
Expand All @@ -115,6 +126,13 @@ export class MultistepDialogExample extends React.PureComponent<
onChange={this.handleOutsideClickChange}
/>
<Switch checked={canEscapeKeyClose} label="Escape key to close" onChange={this.handleEscapeKeyChange} />
<Label>Initial step index (0-indexed)</Label>
<NumericInput
value={initialStepIndex}
onValueChange={this.handleInitialStepIndexChange}
max={2}
min={-1}
/>
</>
);
}
Expand All @@ -124,6 +142,8 @@ export class MultistepDialogExample extends React.PureComponent<
private handleClose = () => this.setState({ isOpen: false });

private handleSelectionChange = handleStringChange(value => this.setState({ value }));

private handleInitialStepIndexChange = (newValue: number) => this.setState({ initialStepIndex: newValue });
}

export interface ISelectPanelProps {
Expand Down

1 comment on commit 061762c

@blueprint-bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[core] feat(MultiStepDialog): Allow skipping to a specific step in the dialog (#4730)

Previews: documentation | landing | table

Please sign in to comment.