kamrify commited on
Commit
a0a08e9
·
1 Parent(s): beaaaa0

Add highlight hooks and allow reconfiguring driver

Browse files
docs/src/content/guides/configuration.mdx CHANGED
@@ -68,7 +68,7 @@ type Popover = {
68
  // Callbacks for button clicks. You can use
69
  // these to add custom behavior to the buttons.
70
  // Each callback receives the following parameters:
71
- // - element: The target DOM element of the step
72
  // - step: The step object configured for the step
73
  // - options.config: The current configuration options
74
  // - options.state: The current state of the driver
@@ -77,3 +77,155 @@ type Popover = {
77
  onCloseClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void
78
  }
79
  ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  // Callbacks for button clicks. You can use
69
  // these to add custom behavior to the buttons.
70
  // Each callback receives the following parameters:
71
+ // - element: The current DOM element of the step
72
  // - step: The step object configured for the step
73
  // - options.config: The current configuration options
74
  // - options.state: The current state of the driver
 
77
  onCloseClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void
78
  }
79
  ```
80
+
81
+ ## Drive Step Configuration
82
+
83
+ 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.
84
+
85
+ ```typescript
86
+ type DriveStep = {
87
+ // The target element to highlight.
88
+ // This can be a DOM element, or a CSS selector.
89
+ // If this is a selector, the first matching
90
+ // element will be highlighted.
91
+ element: Element | string;
92
+
93
+ // The popover configuration for this step.
94
+ // Look at the Popover Configuration section
95
+ popover?: Popover;
96
+
97
+ // Callback when the current step is deselected,
98
+ // about to be highlighted or highlighted.
99
+ // Each callback receives the following parameters:
100
+ // - element: The current DOM element of the step
101
+ // - step: The step object configured for the step
102
+ // - options.config: The current configuration options
103
+ // - options.state: The current state of the driver
104
+ onDeselected?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;
105
+ onHighlightStarted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;
106
+ onHighlighted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;
107
+ }
108
+ ```
109
+
110
+ ## Global Configuration
111
+
112
+ 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.
113
+
114
+ ```typescript
115
+ type Config = {
116
+ // Array of steps to highlight. You should pass
117
+ // this when you want to setup a product tour.
118
+ steps?: DriveStep[];
119
+
120
+ // Whether to animate the product tour. (default: true)
121
+ animate?: boolean;
122
+ // Overlay color. (default: rgba(0, 0, 0, 0.5))
123
+ // This is useful when you have a dark background
124
+ // and want to highlight elements with a light
125
+ // background color.
126
+ backdropColor?: string;
127
+ // Whether to smooth scroll to the highlighted element. (default: false)
128
+ smoothScroll?: boolean;
129
+ // Whether to allow closing the popover by clicking on the backdrop. (default: true)
130
+ allowClose?: boolean;
131
+ // Opacity of the backdrop. (default: 0.5)
132
+ opacity?: number;
133
+ // Distance between the highlighted element and the cutout. (default: 10)
134
+ stagePadding?: number;
135
+ // Radius of the cutout around the highlighted element. (default: 5)
136
+ stageRadius?: number;
137
+
138
+ // Whether to allow keyboard navigation. (default: true)
139
+ allowKeyboardControl?: boolean;
140
+
141
+ // If you want to add custom class to the popover
142
+ popoverClass?: string;
143
+ // Distance between the popover and the highlighted element. (default: 10)
144
+ popoverOffset?: number;
145
+ // Array of buttons to show in the popover. Defaults to ["next", "previous", "close"]
146
+ // for product tours and [] for single element highlighting.
147
+ showButtons?: AllowedButtons[];
148
+ // Array of buttons to disable. This is useful when you want to show some of the
149
+ // buttons, but disable some of them.
150
+ disableButtons?: AllowedButtons[];
151
+
152
+ // Whether to show the progress text in popover. (default: false)
153
+ showProgress?: boolean;
154
+ // Template for the progress text. You can use the following placeholders in the template:
155
+ // - {{current}}: The current step number
156
+ // - {{total}}: Total number of steps
157
+ progressText?: string;
158
+
159
+ // Text to show in the buttons. `doneBtnText`
160
+ // is used on the last step of a tour.
161
+ nextBtnText?: string;
162
+ prevBtnText?: string;
163
+ doneBtnText?: string;
164
+
165
+ // Called after the popover is rendered.
166
+ // PopoverDOM is an object with references to
167
+ // the popover DOM elements such as buttons
168
+ // title, descriptions, body, container etc.
169
+ onPopoverRendered?: (popover: PopoverDOM) => void;
170
+
171
+ // Hooks to run before and after highlighting
172
+ // each step. Each hook receives the following
173
+ // parameters:
174
+ // - element: The target DOM element of the step
175
+ // - step: The step object configured for the step
176
+ // - options.config: The current configuration options
177
+ // - options.state: The current state of the driver
178
+ onHighlightStarted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
179
+ onHighlighted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
180
+ onDeselected?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
181
+
182
+ // Hooks to run before and after the driver
183
+ // is destroyed. Each hook receives
184
+ // the following parameters:
185
+ // - element: Currently active element
186
+ // - step: The step object configured for the currently active
187
+ // - options.config: The current configuration options
188
+ // - options.state: The current state of the driver
189
+ onDestroyStarted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
190
+ onDestroyed?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
191
+
192
+ // Hooks to run on button clicks. Each hook receives
193
+ // the following parameters:
194
+ // - element: The current DOM element of the step
195
+ // - step: The step object configured for the step
196
+ // - options.config: The current configuration options
197
+ // - options.state: The current state of the driver
198
+ onNextClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
199
+ onPrevClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
200
+ onCloseClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
201
+ };
202
+ ```
203
+
204
+ ## State
205
+
206
+ You can access the current state of the driver by calling the `getState` method. It's also passed to the hooks and callbacks.
207
+
208
+ ```typescript
209
+ type State = {
210
+ // Whether the driver is currently active or not
211
+ isInitialized?: boolean;
212
+
213
+ // Index of the currently active step if using
214
+ // as a product tour and have configured the
215
+ // steps array.
216
+ activeIndex?: number;
217
+ // DOM element of the currently active step
218
+ activeElement?: Element;
219
+ // Step object of the currently active step
220
+ activeStep?: DriveStep;
221
+
222
+ // DOM element that was previously active
223
+ previousElement?: Element;
224
+ // Step object of the previously active step
225
+ previousStep?: DriveStep;
226
+
227
+ // DOM elements for the popover i.e. including
228
+ // container, title, description, buttons etc.
229
+ popover?: PopoverDOM;
230
+ }
231
+ ```
src/driver.ts CHANGED
@@ -9,6 +9,8 @@ import "./driver.css";
9
 
10
  export type DriveStep = {
11
  element?: string | Element;
 
 
12
  onDeselected?: DriverHook;
13
  popover?: Popover;
14
  };
@@ -132,7 +134,6 @@ export function driver(options: Config = {}) {
132
  .replace("{{current}}", `${stepIndex + 1}`)
133
  .replace("{{total}}", `${steps.length}`);
134
 
135
- console.log(showProgress);
136
  highlight({
137
  ...currentStep,
138
  popover: {
@@ -168,7 +169,8 @@ export function driver(options: Config = {}) {
168
  // the hook for when user calls `destroy`, driver will get into infinite loop
169
  // not causing tour to be destroyed.
170
  if (withOnDestroyStartedHook && onDestroyStarted) {
171
- onDestroyStarted(activeElement, activeStep!, {
 
172
  config: getConfig(),
173
  state: getState(),
174
  });
@@ -213,6 +215,9 @@ export function driver(options: Config = {}) {
213
  init();
214
  drive(stepIndex);
215
  },
 
 
 
216
  moveNext,
217
  movePrevious,
218
  hasNextStep: () => {
 
9
 
10
  export type DriveStep = {
11
  element?: string | Element;
12
+ onHighlightStarted?: DriverHook;
13
+ onHighlighted?: DriverHook;
14
  onDeselected?: DriverHook;
15
  popover?: Popover;
16
  };
 
134
  .replace("{{current}}", `${stepIndex + 1}`)
135
  .replace("{{total}}", `${steps.length}`);
136
 
 
137
  highlight({
138
  ...currentStep,
139
  popover: {
 
169
  // the hook for when user calls `destroy`, driver will get into infinite loop
170
  // not causing tour to be destroyed.
171
  if (withOnDestroyStartedHook && onDestroyStarted) {
172
+ const isActiveDummyElement = !activeElement || activeElement?.id === "driver-dummy-element";
173
+ onDestroyStarted(isActiveDummyElement ? undefined : activeElement, activeStep!, {
174
  config: getConfig(),
175
  state: getState(),
176
  });
 
215
  init();
216
  drive(stepIndex);
217
  },
218
+ setConfig: configure,
219
+ getConfig,
220
+ getState,
221
  moveNext,
222
  movePrevious,
223
  hasNextStep: () => {
src/highlight.ts CHANGED
@@ -70,8 +70,8 @@ function transferHighlight(toElement: Element, toStep: DriveStep) {
70
  const isFromDummyElement = fromElement.id === "driver-dummy-element";
71
 
72
  const isAnimatedTour = getConfig("animate");
73
- const highlightStartedHook = getConfig("onHighlightStarted");
74
- const highlightedHook = getConfig("onHighlighted");
75
  const deselectedHook = fromStep?.onDeselected || getConfig("onDeselected");
76
 
77
  const config = getConfig();
 
70
  const isFromDummyElement = fromElement.id === "driver-dummy-element";
71
 
72
  const isAnimatedTour = getConfig("animate");
73
+ const highlightStartedHook = toStep.onHighlightStarted || getConfig("onHighlightStarted");
74
+ const highlightedHook = toStep?.onHighlighted || getConfig("onHighlighted");
75
  const deselectedHook = fromStep?.onDeselected || getConfig("onDeselected");
76
 
77
  const config = getConfig();