kamrify commited on
Commit
8480986
·
1 Parent(s): e3d3deb

Add bring-in-view functionality

Browse files
Files changed (5) hide show
  1. index.html +122 -8
  2. src/driver.ts +3 -1
  3. src/events.ts +5 -3
  4. src/highlight.ts +29 -0
  5. src/popover.ts +12 -0
index.html CHANGED
@@ -19,18 +19,34 @@
19
  -moz-osx-font-smoothing: grayscale;
20
  }
21
 
 
 
 
 
 
 
 
 
 
 
22
  .container {
23
  display: flex;
24
  flex-direction: column;
25
- align-items: center;
26
- justify-content: center;
27
- height: 100vh;
28
- max-width: 1200px;
29
  margin: 0 auto;
 
 
 
 
 
 
 
 
 
 
30
  }
31
 
32
  h1 {
33
- margin: 40px 0 10px;
34
  font-size: 48px;
35
  font-weight: 600;
36
  text-align: center;
@@ -69,12 +85,23 @@
69
  display: block;
70
  cursor: pointer;
71
  }
 
 
 
 
 
 
 
 
 
72
  </style>
73
  </head>
74
  <body>
75
  <div class="container">
76
- <h1>driver.js <sup>next</sup></h1>
77
- <p>Rewritten and enhanced version of driver.js</p>
 
 
78
 
79
  <div class="buttons">
80
  <button id="highlight-btn">Animated Highlight</button>
@@ -93,6 +120,91 @@
93
  <li>No dependencies</li>
94
  <li>MIT Licensed</li>
95
  </ul>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  </div>
97
  <script type="module">
98
  import { driver } from "./src/driver.ts";
@@ -104,7 +216,9 @@
104
  document
105
  .getElementById("simple-highlight-btn")
106
  .addEventListener("click", () => {
107
- driver({ animate: false }).highlight({ element: "ul" });
 
 
108
  });
109
 
110
  document
 
19
  -moz-osx-font-smoothing: grayscale;
20
  }
21
 
22
+ p {
23
+ line-height: 1.5;
24
+ margin-bottom: 15px;
25
+ }
26
+
27
+ .page-header {
28
+ text-align: center;
29
+ margin-bottom: 10px;
30
+ }
31
+
32
  .container {
33
  display: flex;
34
  flex-direction: column;
35
+ max-width: 500px;
 
 
 
36
  margin: 0 auto;
37
+ text-align: left;
38
+ }
39
+
40
+ h1,
41
+ h2,
42
+ h3,
43
+ h4,
44
+ h5,
45
+ h6 {
46
+ margin: 30px 0 10px;
47
  }
48
 
49
  h1 {
 
50
  font-size: 48px;
51
  font-weight: 600;
52
  text-align: center;
 
85
  display: block;
86
  cursor: pointer;
87
  }
88
+
89
+ pre {
90
+ margin-bottom: 20px;
91
+ border: 1px solid #ccc;
92
+ background: whitesmoke;
93
+ border-radius: 5px;
94
+ padding: 10px;
95
+ line-height: 1.75;
96
+ }
97
  </style>
98
  </head>
99
  <body>
100
  <div class="container">
101
+ <div class="page-header">
102
+ <h1>driver.js <sup>next</sup></h1>
103
+ <p>Rewritten and enhanced version of driver.js</p>
104
+ </div>
105
 
106
  <div class="buttons">
107
  <button id="highlight-btn">Animated Highlight</button>
 
120
  <li>No dependencies</li>
121
  <li>MIT Licensed</li>
122
  </ul>
123
+
124
+ <h2>Yet another Tour Library?</h2>
125
+ <p>
126
+ No, it is not. Tours are just one of the many use-cases. Driver.js can
127
+ be used wherever you need some sort of overlay for the page; some common
128
+ usecases could be: e.g. dimming the background when user is interacting
129
+ with some component, using it as a focus shifter to bring user's
130
+ attention to some component on page, or using it to simulate those "Turn
131
+ off the Lights" widgets that you might have seen on video players
132
+ online, etc.
133
+ </p>
134
+ <p>
135
+ Driver.js is written in Vanilla JS, has zero dependencies and is highly
136
+ customizable. It has several options allowing you to manipulate how it
137
+ behaves and also provides you the hooks to manipulate the elements as
138
+ they are highlighted, about to be highlighted, or deselected.
139
+ </p>
140
+
141
+ <h2>Installation</h2>
142
+ <p>You can install it using yarn or npm, whatever you prefer.</p>
143
+
144
+ <pre>
145
+ yarn add driver.js
146
+ npm install driver.js</pre
147
+ >
148
+
149
+ <p>
150
+ Or include it using CDN — put the version as [email protected] in the name
151
+ </p>
152
+
153
+ <pre>https://unpkg.com/driver.js/dist/driver.min.js</pre>
154
+
155
+ <h2>Usage and Demo</h2>
156
+
157
+ <p id="large-paragraph-text">
158
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi
159
+ blanditiis consectetur ea eligendi id in inventore ipsa iure laudantium
160
+ libero, minus molestias necessitatibus nesciunt non omnis, quasi
161
+ recusandae tempore voluptates! Lorem ipsum dolor sit amet, consectetur
162
+ adipisicing elit. Animi blanditiis consectetur ea eligendi id in
163
+ inventore ipsa iure laudantium libero, minus molestias necessitatibus
164
+ nesciunt non omnis, quasi recusandae tempore voluptates!
165
+ </p>
166
+ <p>
167
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi
168
+ blanditiis consectetur ea eligendi id in inventore ipsa iure laudantium
169
+ libero, minus molestias necessitatibus nesciunt non omnis, quasi
170
+ recusandae tempore voluptates!
171
+ </p>
172
+ <p>
173
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi
174
+ blanditiis consectetur ea eligendi id in inventore ipsa iure laudantium
175
+ libero, minus molestias necessitatibus nesciunt non omnis, quasi
176
+ recusandae tempore voluptates!
177
+ </p>
178
+ <p>
179
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi
180
+ blanditiis consectetur ea eligendi id in inventore ipsa iure laudantium
181
+ libero, minus molestias necessitatibus nesciunt non omnis, quasi
182
+ recusandae tempore voluptates!
183
+ </p>
184
+ <p>
185
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi
186
+ blanditiis consectetur ea eligendi id in inventore ipsa iure laudantium
187
+ libero, minus molestias necessitatibus nesciunt non omnis, quasi
188
+ recusandae tempore voluptates!
189
+ </p>
190
+ <p>
191
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi
192
+ blanditiis consectetur ea eligendi id in inventore ipsa iure laudantium
193
+ libero, minus molestias necessitatibus nesciunt non omnis, quasi
194
+ recusandae tempore voluptates!
195
+ </p>
196
+ <p>
197
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi
198
+ blanditiis consectetur ea eligendi id in inventore ipsa iure laudantium
199
+ libero, minus molestias necessitatibus nesciunt non omnis, quasi
200
+ recusandae tempore voluptates!
201
+ </p>
202
+ <p>
203
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi
204
+ blanditiis consectetur ea eligendi id in inventore ipsa iure laudantium
205
+ libero, minus molestias necessitatibus nesciunt non omnis, quasi
206
+ recusandae tempore voluptates!
207
+ </p>
208
  </div>
209
  <script type="module">
210
  import { driver } from "./src/driver.ts";
 
216
  document
217
  .getElementById("simple-highlight-btn")
218
  .addEventListener("click", () => {
219
+ driver({ animate: false }).highlight({
220
+ element: "#large-paragraph-text",
221
+ });
222
  });
223
 
224
  document
src/driver.ts CHANGED
@@ -1,13 +1,15 @@
 
1
  import { destroyStage } from "./stage";
2
  import { destroyEvents, initEvents } from "./events";
3
  import { Config, configure, getConfig } from "./config";
4
  import { destroyHighlight, highlight } from "./highlight";
 
5
 
6
  import "./style.css";
7
- import { destroyHooks, register } from "./hooks";
8
 
9
  export type DriveStep = {
10
  element?: string | Element;
 
11
  };
12
 
13
  let isInitialized = false;
 
1
+ import { Popover } from "./popover";
2
  import { destroyStage } from "./stage";
3
  import { destroyEvents, initEvents } from "./events";
4
  import { Config, configure, getConfig } from "./config";
5
  import { destroyHighlight, highlight } from "./highlight";
6
+ import { destroyHooks, register } from "./hooks";
7
 
8
  import "./style.css";
 
9
 
10
  export type DriveStep = {
11
  element?: string | Element;
12
+ popover?: Popover;
13
  };
14
 
15
  let isInitialized = false;
src/events.ts CHANGED
@@ -2,7 +2,7 @@ import { refreshActiveHighlight } from "./highlight";
2
 
3
  let resizeTimeout: number;
4
 
5
- function onResize() {
6
  if (resizeTimeout) {
7
  window.cancelAnimationFrame(resizeTimeout);
8
  }
@@ -64,9 +64,11 @@ export function onDriverClick(
64
  }
65
 
66
  export function initEvents() {
67
- window.addEventListener("resize", onResize);
 
68
  }
69
 
70
  export function destroyEvents() {
71
- window.removeEventListener("resize", onResize);
 
72
  }
 
2
 
3
  let resizeTimeout: number;
4
 
5
+ function requireRefresh() {
6
  if (resizeTimeout) {
7
  window.cancelAnimationFrame(resizeTimeout);
8
  }
 
64
  }
65
 
66
  export function initEvents() {
67
+ window.addEventListener("resize", requireRefresh);
68
+ window.addEventListener("scroll", requireRefresh);
69
  }
70
 
71
  export function destroyEvents() {
72
+ window.removeEventListener("resize", requireRefresh);
73
+ window.removeEventListener("scroll", requireRefresh);
74
  }
src/highlight.ts CHANGED
@@ -1,6 +1,7 @@
1
  import { DriveStep } from "./driver";
2
  import { refreshStage, trackActiveElement, transitionStage } from "./stage";
3
  import { getConfig } from "./config";
 
4
 
5
  let previousHighlight: Element | undefined;
6
  let activeHighlight: Element | undefined;
@@ -47,11 +48,15 @@ function transferHighlight(from: Element, to: Element) {
47
  if (getConfig("animate") && elapsed < duration) {
48
  transitionStage(elapsed, duration, from, to);
49
  } else {
 
50
  trackActiveElement(to);
 
 
51
  currentTransitionCallback = undefined;
52
  }
53
 
54
  refreshStage();
 
55
  window.requestAnimationFrame(animate);
56
  };
57
 
@@ -62,6 +67,30 @@ function transferHighlight(from: Element, to: Element) {
62
  to.classList.add("driver-active-element");
63
  }
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  export function destroyHighlight() {
66
  activeHighlight = undefined;
67
  currentTransitionCallback = undefined;
 
1
  import { DriveStep } from "./driver";
2
  import { refreshStage, trackActiveElement, transitionStage } from "./stage";
3
  import { getConfig } from "./config";
4
+ import { refreshPopover, renderPopover } from "./popover";
5
 
6
  let previousHighlight: Element | undefined;
7
  let activeHighlight: Element | undefined;
 
48
  if (getConfig("animate") && elapsed < duration) {
49
  transitionStage(elapsed, duration, from, to);
50
  } else {
51
+ bringInView(to);
52
  trackActiveElement(to);
53
+ renderPopover(to);
54
+
55
  currentTransitionCallback = undefined;
56
  }
57
 
58
  refreshStage();
59
+ refreshPopover();
60
  window.requestAnimationFrame(animate);
61
  };
62
 
 
67
  to.classList.add("driver-active-element");
68
  }
69
 
70
+ function bringInView(element: Element) {
71
+ if (!element || isElementInView(element)) {
72
+ return;
73
+ }
74
+
75
+ element.scrollIntoView({
76
+ behavior: "smooth",
77
+ inline: "center",
78
+ block: "center",
79
+ });
80
+ }
81
+
82
+ function isElementInView(element: Element) {
83
+ const rect = element.getBoundingClientRect();
84
+
85
+ return (
86
+ rect.top >= 0 &&
87
+ rect.left >= 0 &&
88
+ rect.bottom <=
89
+ (window.innerHeight || document.documentElement.clientHeight) &&
90
+ rect.right <= (window.innerWidth || document.documentElement.clientWidth)
91
+ );
92
+ }
93
+
94
  export function destroyHighlight() {
95
  activeHighlight = undefined;
96
  currentTransitionCallback = undefined;
src/popover.ts ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export type Popover = {
2
+ title?: string;
3
+ description: string;
4
+ preferredPosition?: "top" | "right" | "bottom" | "left";
5
+ align?: "start" | "center" | "end";
6
+ };
7
+
8
+ export function renderPopover(element: Element) {
9
+ console.log("rendering", element);
10
+ }
11
+
12
+ export function refreshPopover() {}