Add highlight hooks and allow reconfiguring driver

This commit is contained in:
Kamran Ahmed
2023-07-01 10:45:26 +01:00
parent beaaaa01b2
commit a0a08e9fa3
3 changed files with 162 additions and 5 deletions
+153 -1
View File
@@ -68,7 +68,7 @@ type Popover = {
// Callbacks for button clicks. You can use
// these to add custom behavior to the buttons.
// Each callback receives the following parameters:
// - element: The target DOM element of the step
// - element: The current DOM element of the step
// - step: The step object configured for the step
// - options.config: The current configuration options
// - options.state: The current state of the driver
@@ -77,3 +77,155 @@ type Popover = {
onCloseClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void
}
```
## Drive Step Configuration
Drive step is the configuration object passed to the `highlight` method or the `steps` array of the `drive` method. You can configure the popover and the target element for each step. Given below are some of the available configuration options.
```typescript
type DriveStep = {
// The target element to highlight.
// This can be a DOM element, or a CSS selector.
// If this is a selector, the first matching
// element will be highlighted.
element: Element | string;
// The popover configuration for this step.
// Look at the Popover Configuration section
popover?: Popover;
// Callback when the current step is deselected,
// about to be highlighted or highlighted.
// Each callback receives the following parameters:
// - element: The current DOM element of the step
// - step: The step object configured for the step
// - options.config: The current configuration options
// - options.state: The current state of the driver
onDeselected?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;
onHighlightStarted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;
onHighlighted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;
}
```
## Global Configuration
You can configure the driver globally by passing the configuration object to the `driver` call or by using the `setConfig` method. Given below are some of the available configuration options.
```typescript
type Config = {
// Array of steps to highlight. You should pass
// this when you want to setup a product tour.
steps?: DriveStep[];
// Whether to animate the product tour. (default: true)
animate?: boolean;
// Overlay color. (default: rgba(0, 0, 0, 0.5))
// This is useful when you have a dark background
// and want to highlight elements with a light
// background color.
backdropColor?: string;
// Whether to smooth scroll to the highlighted element. (default: false)
smoothScroll?: boolean;
// Whether to allow closing the popover by clicking on the backdrop. (default: true)
allowClose?: boolean;
// Opacity of the backdrop. (default: 0.5)
opacity?: number;
// Distance between the highlighted element and the cutout. (default: 10)
stagePadding?: number;
// Radius of the cutout around the highlighted element. (default: 5)
stageRadius?: number;
// Whether to allow keyboard navigation. (default: true)
allowKeyboardControl?: boolean;
// If you want to add custom class to the popover
popoverClass?: string;
// Distance between the popover and the highlighted element. (default: 10)
popoverOffset?: number;
// Array of buttons to show in the popover. Defaults to ["next", "previous", "close"]
// for product tours and [] for single element highlighting.
showButtons?: AllowedButtons[];
// Array of buttons to disable. This is useful when you want to show some of the
// buttons, but disable some of them.
disableButtons?: AllowedButtons[];
// Whether to show the progress text in popover. (default: false)
showProgress?: boolean;
// Template for the progress text. You can use the following placeholders in the template:
// - {{current}}: The current step number
// - {{total}}: Total number of steps
progressText?: string;
// Text to show in the buttons. `doneBtnText`
// is used on the last step of a tour.
nextBtnText?: string;
prevBtnText?: string;
doneBtnText?: string;
// Called after the popover is rendered.
// PopoverDOM is an object with references to
// the popover DOM elements such as buttons
// title, descriptions, body, container etc.
onPopoverRendered?: (popover: PopoverDOM) => void;
// Hooks to run before and after highlighting
// each step. Each hook receives the following
// parameters:
// - element: The target DOM element of the step
// - step: The step object configured for the step
// - options.config: The current configuration options
// - options.state: The current state of the driver
onHighlightStarted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
onHighlighted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
onDeselected?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
// Hooks to run before and after the driver
// is destroyed. Each hook receives
// the following parameters:
// - element: Currently active element
// - step: The step object configured for the currently active
// - options.config: The current configuration options
// - options.state: The current state of the driver
onDestroyStarted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
onDestroyed?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
// Hooks to run on button clicks. Each hook receives
// the following parameters:
// - element: The current DOM element of the step
// - step: The step object configured for the step
// - options.config: The current configuration options
// - options.state: The current state of the driver
onNextClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
onPrevClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
onCloseClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
};
```
## State
You can access the current state of the driver by calling the `getState` method. It's also passed to the hooks and callbacks.
```typescript
type State = {
// Whether the driver is currently active or not
isInitialized?: boolean;
// Index of the currently active step if using
// as a product tour and have configured the
// steps array.
activeIndex?: number;
// DOM element of the currently active step
activeElement?: Element;
// Step object of the currently active step
activeStep?: DriveStep;
// DOM element that was previously active
previousElement?: Element;
// Step object of the previously active step
previousStep?: DriveStep;
// DOM elements for the popover i.e. including
// container, title, description, buttons etc.
popover?: PopoverDOM;
}
```
+7 -2
View File
@@ -9,6 +9,8 @@ import "./driver.css";
export type DriveStep = {
element?: string | Element;
onHighlightStarted?: DriverHook;
onHighlighted?: DriverHook;
onDeselected?: DriverHook;
popover?: Popover;
};
@@ -132,7 +134,6 @@ export function driver(options: Config = {}) {
.replace("{{current}}", `${stepIndex + 1}`)
.replace("{{total}}", `${steps.length}`);
console.log(showProgress);
highlight({
...currentStep,
popover: {
@@ -168,7 +169,8 @@ export function driver(options: Config = {}) {
// the hook for when user calls `destroy`, driver will get into infinite loop
// not causing tour to be destroyed.
if (withOnDestroyStartedHook && onDestroyStarted) {
onDestroyStarted(activeElement, activeStep!, {
const isActiveDummyElement = !activeElement || activeElement?.id === "driver-dummy-element";
onDestroyStarted(isActiveDummyElement ? undefined : activeElement, activeStep!, {
config: getConfig(),
state: getState(),
});
@@ -213,6 +215,9 @@ export function driver(options: Config = {}) {
init();
drive(stepIndex);
},
setConfig: configure,
getConfig,
getState,
moveNext,
movePrevious,
hasNextStep: () => {
+2 -2
View File
@@ -70,8 +70,8 @@ function transferHighlight(toElement: Element, toStep: DriveStep) {
const isFromDummyElement = fromElement.id === "driver-dummy-element";
const isAnimatedTour = getConfig("animate");
const highlightStartedHook = getConfig("onHighlightStarted");
const highlightedHook = getConfig("onHighlighted");
const highlightStartedHook = toStep.onHighlightStarted || getConfig("onHighlightStarted");
const highlightedHook = toStep?.onHighlighted || getConfig("onHighlighted");
const deselectedHook = fromStep?.onDeselected || getConfig("onDeselected");
const config = getConfig();