├── .eslintrc.js
├── .gitignore
├── .prettierignore
├── .prettierrc
├── README.md
├── dist
├── dist.js
├── dist.min.js
├── index.js
└── src
│ ├── HighlightElement.js
│ ├── InfoElement.js
│ ├── css.js
│ └── utils.js
├── index.html
├── index.ts
├── package-lock.json
├── package.json
├── rollup.config.mjs
├── src
├── HighlightElement.ts
├── InfoElement.ts
├── css.ts
└── utils.ts
└── tsconfig.json
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "env": {
3 | "browser": true,
4 | "es2021": true
5 | },
6 | "extends": "eslint:recommended",
7 | "overrides": [
8 | ],
9 | "parserOptions": {
10 | "parser": 'babel-eslint',
11 | "ecmaVersion": 12,
12 | "sourceType": "module",
13 | "allowImportExportEverywhere": true
14 | },
15 | "rules": {
16 | }
17 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | */.DS_Store
2 | dist
3 | node_modules
4 | *.json
5 | *.md
6 | .eslintrc.js
7 | .prettierignore
8 | .prettierrc
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | semi: false
2 | singleQuote: true
3 | printWidth: 80
4 | trailingComma: 'none'
5 | arrowParens: 'avoid'
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Simple novice guide
2 |
3 | 一个简单的新手引导库。
4 |
5 | # 安装
6 |
7 | ```bash
8 | npm i simple-novice-guide
9 | ```
10 |
11 | # 使用
12 |
13 | ```js
14 | import SimpleNoviceGuide from 'simple-novice-guide'
15 |
16 | new SimpleNoviceGuide({
17 | steps: [
18 | {
19 | element: '#id',
20 | title: '我是标题',
21 | text: '我是信息',
22 | img: '我是图片'
23 | }
24 | ]
25 | }).start()
26 | ```
27 |
28 | 如果要使用`umd`格式的文件,可以安装完后在`node_modules/simple-novice-guide/dist/`目录里选择使用`dist.js`或`dist.min.js`文件。
29 |
30 | # 本地开发
31 |
32 | 1.开启`ts`编译
33 |
34 | ```bash
35 | npm run tsc
36 | ```
37 |
38 | 2.开启打包编译
39 |
40 | ```bash
41 | npm run build
42 | ```
43 |
44 | 3.开启页面服务
45 |
46 | ```bash
47 | npx http-server -e js -c-1
48 | ```
49 |
50 | 访问`[ip][port]/index.html`。
51 |
52 | 然后就可以愉快的修改代码了,不过没有热更新功能哦,所以记得修改后要刷新页面。
53 |
54 | # 文档
55 |
56 | ## 创建实例
57 |
58 | ```js
59 | const noviceGuide = new SimpleNoviceGuide(options)
60 | ```
61 |
62 | ### 参数options
63 |
64 | 对象类型,可以传递以下选项:
65 |
66 | | 属性 | 类型 | 默认值 | 描述 |
67 | | ---------------- | -------- | ------------------ | ------------------------------------------------------------ |
68 | | steps | array | | 步骤数据,必填,信息数据见下表 |
69 | | padding | number | 10 | 高亮元素和信息框元素的内边距,单位`px` |
70 | | margin | number | 10 | 高亮元素和信息框元素之间的间距,单位`px` |
71 | | boxShadowColor | string | rgba(0, 0, 0, 0.5) | 高亮元素的box-shadow颜色 |
72 | | transition | string | all 0.3s ease-out | 高亮元素过渡效果 |
73 | | borderRadius | string | 5px | 高亮元素和信息框元素的圆角 |
74 | | highlightElClass | string | | 要添加到高亮元素上的css类名 |
75 | | backgroundColor | string | \#fff | 信息框元素的背景颜色 |
76 | | infoElClass | string | | 要添加到信息框元素上的css类名 |
77 | | prevText | string | 上一步 | 上一步按钮的文字 |
78 | | nextText | string | 下一步 | 下一步按钮的文字 |
79 | | completeText | string | 完成 | 完成按钮的文字 |
80 | | showIndicator | boolean | true | 是否显示信息框内的指示器 |
81 | | zIndex | number | 9999 | 高亮元素和信息框的z-index |
82 | | useCustomInfo | boolean | false | 是否使用自定义的信息框,如果开启,需要传递getCustomInfoEl选项 |
83 | | getCustomInfoEl | function | null | 返回自定义信息框元素 |
84 |
85 | ### options.steps属性
86 |
87 | `options.steps`属性值需为一个对象数组,对象的结构如下:
88 |
89 | | 属性 | 类型 | 默认值 | 描述 |
90 | | ------- | --------------------- | ------ | ------------------------------------------------------------ |
91 | | element | HTMLElement \| string | | 该步骤需要高亮的`html`元素,可以是一个选择器,也可以是`dom`节点对象,如果当前步骤不需要高亮元素,也可以不传 |
92 | | title | string \| number | | 当前步骤的标题 |
93 | | text | string \| number | | 当前步骤的信息 |
94 | | img | string | | 当前步骤的图片 |
95 |
96 |
97 |
98 | ## 实例属性
99 |
100 | ### noviceGuide.options
101 |
102 | 选项对象。
103 |
104 |
105 |
106 | ### noviceGuide.steps
107 |
108 | 步骤列表数据。
109 |
110 |
111 |
112 | ### noviceGuide.currentStepIndex
113 |
114 | 当前所在步骤的索引。
115 |
116 |
117 |
118 | ## 实例方法
119 |
120 | ### noviceGuide.start()
121 |
122 | 开始。
123 |
124 |
125 |
126 | ### noviceGuide.next()
127 |
128 | 下一步。
129 |
130 |
131 |
132 | ### noviceGuide.prev()
133 |
134 | 上一步。
135 |
136 |
137 |
138 | ### noviceGuide.jump(stepIndex: number)
139 |
140 | 跳转到指定步骤。
141 |
142 |
143 |
144 | ### noviceGuide.done()
145 |
146 | 结束。
147 |
148 |
149 |
150 | ### noviceGuide.isFirstStep()
151 |
152 | 是否是第一步。
153 |
154 |
155 |
156 | ### noviceGuide.isLastStep()
157 |
158 | 是否是最后一步。
159 |
160 |
161 |
162 | ### noviceGuide.on(eventName, (...args) => {})
163 |
164 | 监听事件。
165 |
166 | 事件发送继承的是[eventemitter3](https://github.com/primus/eventemitter3),详细文档可以参考它的文档。
167 |
168 | 实例会发出的事件如下:
169 |
170 | | 事件名 | 回调参数 | 描述 |
171 | | ------------------ | ------------------------- | ------------ |
172 | | before-step-change | stepIndex(当前步骤索引) | 即将切换步骤 |
173 | | after-step-change | stepIndex(当前步骤索引) | 步骤切换完毕 |
174 | | done | | 新手引导结束 |
175 |
176 |
177 |
178 | ### noviceGuide.emit(eventName, ...args)
179 |
180 | 发送事件。
181 |
182 |
183 |
184 | ### noviceGuide.off(eventName, fn?)
185 |
186 | 解除监听事件。
187 |
188 |
189 |
190 | ## 自定义信息框
191 |
192 | 如果内置的信息框无法满足你的需求,也可以自定义信息框,首先实例化时需要传递以下两个参数:
193 |
194 | ```js
195 | const noviceGuide = new SimpleNoviceGuide({
196 | useCustomInfo: true,
197 | getCustomInfoEl: async (step) => {
198 | return document.querySelector('.customInfoBox')
199 | }
200 | })
201 | ```
202 |
203 | `getCustomInfoEl`方法需要返回你自定义的信息框的节点,考虑到可能有异步的操作,所以统一返回一个`Promise`。
204 |
205 | 注意你自定义的信息框元素需要设置绝对定位,`z-index`也是必不可少的:
206 |
207 | ```css
208 | .customInfoBox {
209 | position: absolute;
210 | z-index: 99999;
211 | }
212 | ```
213 |
214 | 然后需要在你的信息框中创建相应的上一步、下一步、完成的按钮,然后手动调用下列方法:
215 |
216 | ```js
217 | noviceGuide.prev()
218 |
219 | noviceGuide.next()
220 |
221 | noviceGuide.done()
222 | ```
223 |
224 | 通常还需要监听`done`事件来删除或隐藏你的自定义信息框:
225 |
226 | ```js
227 | noviceGuide.on('done', () => {
228 | customInfoBoxEl.style.display = 'none'
229 | })
230 | ```
231 |
232 |
--------------------------------------------------------------------------------
/dist/dist.js:
--------------------------------------------------------------------------------
1 | (function (global, factory) {
2 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3 | typeof define === 'function' && define.amd ? define(factory) :
4 | (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.SimpleNoviceGuide = factory());
5 | })(this, (function () { 'use strict';
6 |
7 | var prefix = 'simple-novice-guide-';
8 | var getScrollAncestor = function (el) {
9 | var style = window.getComputedStyle(el);
10 | var isAbsolute = style.position === 'absolute';
11 | var isFixed = style.position === 'fixed';
12 | var reg = /(auto|scroll)/;
13 | if (isFixed)
14 | return document.body;
15 | var parent = el.parentElement;
16 | while (parent) {
17 | style = window.getComputedStyle(parent);
18 | if (!(isAbsolute && style.position === 'static')) {
19 | if (reg.test(style.overflow + style.overflowX + style.overflowY)) {
20 | return parent;
21 | }
22 | }
23 | parent = parent.parentElement;
24 | }
25 | return document.body;
26 | };
27 | var scrollAncestorToElement = function (el) {
28 | var parent = getScrollAncestor(el);
29 | if (parent === document.body)
30 | return;
31 | var parentRect = parent.getBoundingClientRect();
32 | var rect = el.getBoundingClientRect();
33 | parent.scrollTop = parent.scrollTop + rect.top - parentRect.top;
34 | scrollAncestorToElement(parent);
35 | };
36 | var elementIsInView = function (el) {
37 | var rect = el.getBoundingClientRect();
38 | return (rect.top >= 0 &&
39 | rect.left >= 0 &&
40 | rect.bottom <= window.innerHeight &&
41 | rect.right <= window.innerWidth);
42 | };
43 | var loadImage = function (img) {
44 | return new Promise(function (resolve, reject) {
45 | var image = new Image();
46 | image.onload = resolve;
47 | image.onerror = reject;
48 | image.src = img;
49 | });
50 | };
51 |
52 | var HighlightElement$1 = (function () {
53 | function HighlightElement(app) {
54 | this.app = app;
55 | this.app = app;
56 | this.el = null;
57 | }
58 | HighlightElement.prototype.show = function (step) {
59 | if (!this.el) {
60 | this.createEl();
61 | }
62 | var left = 0, top = 0, width = 0, height = 0;
63 | if (step.element) {
64 | var rect = step.element.getBoundingClientRect();
65 | var padding = this.app.options.padding;
66 | left = rect.left + window.pageXOffset - padding;
67 | top = rect.top + window.pageYOffset - padding;
68 | width = rect.width + padding * 2;
69 | height = rect.height + padding * 2;
70 | }
71 | else {
72 | left = window.innerWidth / 2 + window.pageXOffset;
73 | top = window.innerHeight / 2 + window.pageYOffset;
74 | width = 0;
75 | height = 0;
76 | }
77 | this.el.style.left = left + 'px';
78 | this.el.style.top = top + 'px';
79 | this.el.style.width = width + 'px';
80 | this.el.style.height = height + 'px';
81 | };
82 | HighlightElement.prototype.createEl = function () {
83 | var _a = this.app.options, boxShadowColor = _a.boxShadowColor, transition = _a.transition, borderRadius = _a.borderRadius, highlightElClass = _a.highlightElClass, zIndex = _a.zIndex;
84 | this.el = document.createElement('div');
85 | this.el.className = prefix + 'highlight-el';
86 | this.el.style.cssText = "\n box-shadow: 0 0 0 5000px ".concat(boxShadowColor, ";\n border-radius: ").concat(borderRadius, ";\n transition: ").concat(transition, ";\n z-index: ").concat(zIndex, ";\n ");
87 | if (highlightElClass) {
88 | this.el.classList.add(highlightElClass);
89 | }
90 | document.body.appendChild(this.el);
91 | };
92 | HighlightElement.prototype.removeEl = function () {
93 | if (this.el) {
94 | document.body.removeChild(this.el);
95 | this.el = null;
96 | }
97 | };
98 | return HighlightElement;
99 | }());
100 |
101 | var __awaiter$1 = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
102 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
103 | return new (P || (P = Promise))(function (resolve, reject) {
104 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
105 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
106 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
107 | step((generator = generator.apply(thisArg, _arguments || [])).next());
108 | });
109 | };
110 | var __generator$1 = (undefined && undefined.__generator) || function (thisArg, body) {
111 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
112 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
113 | function verb(n) { return function (v) { return step([n, v]); }; }
114 | function step(op) {
115 | if (f) throw new TypeError("Generator is already executing.");
116 | while (g && (g = 0, op[0] && (_ = 0)), _) try {
117 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
118 | if (y = 0, t) op = [op[0] & 2, t.value];
119 | switch (op[0]) {
120 | case 0: case 1: t = op; break;
121 | case 4: _.label++; return { value: op[1], done: false };
122 | case 5: _.label++; y = op[1]; op = [0]; continue;
123 | case 7: op = _.ops.pop(); _.trys.pop(); continue;
124 | default:
125 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
126 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
127 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
128 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
129 | if (t[2]) _.ops.pop();
130 | _.trys.pop(); continue;
131 | }
132 | op = body.call(thisArg, _);
133 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
134 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
135 | }
136 | };
137 | var HighlightElement = (function () {
138 | function HighlightElement(app) {
139 | this.app = app;
140 | this.app = app;
141 | this.el = null;
142 | this.app.on('after-step-change', this.onStepChange.bind(this));
143 | }
144 | HighlightElement.prototype.show = function (step) {
145 | return __awaiter$1(this, void 0, void 0, function () {
146 | var el, res;
147 | return __generator$1(this, function (_a) {
148 | switch (_a.label) {
149 | case 0:
150 | if (!(this.app.options.useCustomInfo && this.app.options.getCustomInfoEl)) return [3, 2];
151 | return [4, this.app.options.getCustomInfoEl(step)];
152 | case 1:
153 | el = _a.sent();
154 | res = this.getInfoRect(step, el);
155 | el.style.left = res.left + 'px';
156 | el.style.top = res.top + 'px';
157 | return [3, 4];
158 | case 2: return [4, this.showInnerInfo(step)];
159 | case 3:
160 | _a.sent();
161 | _a.label = 4;
162 | case 4: return [2];
163 | }
164 | });
165 | });
166 | };
167 | HighlightElement.prototype.showInnerInfo = function (step) {
168 | return __awaiter$1(this, void 0, void 0, function () {
169 | var error_1, res;
170 | return __generator$1(this, function (_a) {
171 | switch (_a.label) {
172 | case 0:
173 | if (!this.el) {
174 | this.createEl();
175 | }
176 | if (!step.img) return [3, 4];
177 | _a.label = 1;
178 | case 1:
179 | _a.trys.push([1, 3, , 4]);
180 | return [4, loadImage(step.img)];
181 | case 2:
182 | _a.sent();
183 | return [3, 4];
184 | case 3:
185 | error_1 = _a.sent();
186 | console.error(error_1);
187 | return [3, 4];
188 | case 4:
189 | this.el.innerHTML = this.createHTML(step);
190 | res = this.getInfoRect(step, this.el);
191 | this.el.style.left = res.left + 'px';
192 | this.el.style.top = res.top + 'px';
193 | return [2];
194 | }
195 | });
196 | });
197 | };
198 | HighlightElement.prototype.getInfoRect = function (step, el) {
199 | if (step.element) {
200 | return this.computeInfoPosition(step, el);
201 | }
202 | else {
203 | var rect = el.getBoundingClientRect();
204 | return {
205 | left: (window.innerWidth - rect.width) / 2 + window.pageXOffset,
206 | top: (window.innerHeight - rect.height) / 2 + window.pageYOffset
207 | };
208 | }
209 | };
210 | HighlightElement.prototype.createHTML = function (step) {
211 | var _this = this;
212 | var _a = this.app.options, prevText = _a.prevText, nextText = _a.nextText, showIndicator = _a.showIndicator;
213 | return "\n
\n
").concat(step.title || '', "
\n
\u00D7
\n
\n \n ").concat(step.img
214 | ? "
.concat(step.img,)
")
215 | : '', "\n
").concat(step.text || '', "
\n
\n \n ").concat(showIndicator
216 | ? this.app.steps
217 | .map(function (_, index) {
218 | return "
");
219 | })
220 | .join('\n')
221 | : '', "\n
\n \n
").concat(prevText, "
\n
").concat(nextText, "
\n
\n ");
222 | };
223 | HighlightElement.prototype.createEl = function () {
224 | var _a = this.app.options, padding = _a.padding, borderRadius = _a.borderRadius, backgroundColor = _a.backgroundColor, infoElClass = _a.infoElClass, zIndex = _a.zIndex;
225 | this.el = document.createElement('div');
226 | this.el.className = prefix + 'info-el';
227 | this.el.style.cssText = "\n background-color: ".concat(backgroundColor, "; \n padding: ").concat(padding, "px;\n border-radius: ").concat(borderRadius, ";\n z-index: ").concat(zIndex, ";\n ");
228 | if (infoElClass) {
229 | this.el.classList.add(infoElClass);
230 | }
231 | document.body.appendChild(this.el);
232 | this.el.addEventListener('click', this.onClick.bind(this));
233 | };
234 | HighlightElement.prototype.onClick = function (e) {
235 | var type = e.target.getAttribute('data-type');
236 | switch (type) {
237 | case 'close':
238 | this.app.done();
239 | break;
240 | case 'prev':
241 | this.app.prev();
242 | break;
243 | case 'next':
244 | this.app.next();
245 | break;
246 | case 'indicator':
247 | var index = e.target.getAttribute('data-index');
248 | if (!Number.isNaN(Number(index))) {
249 | this.app.jump(Number(index));
250 | }
251 | break;
252 | }
253 | };
254 | HighlightElement.prototype.removeEl = function () {
255 | if (this.el) {
256 | document.body.removeChild(this.el);
257 | this.el = null;
258 | }
259 | };
260 | HighlightElement.prototype.onStepChange = function (stepIndex) {
261 | var _a = this.app.options, nextText = _a.nextText, completeText = _a.completeText, useCustomInfo = _a.useCustomInfo;
262 | if (useCustomInfo)
263 | return;
264 | var prevEl = document.querySelector(".".concat(prefix, "info-el-btn-prev"));
265 | var nextEl = document.querySelector(".".concat(prefix, "info-el-btn-next"));
266 | prevEl.classList.remove('disabled');
267 | nextEl.textContent = nextText;
268 | if (this.app.isFirstStep()) {
269 | prevEl.classList.add('disabled');
270 | }
271 | if (this.app.isLastStep()) {
272 | nextEl.textContent = completeText;
273 | }
274 | var indicatorEls = Array.from(document.querySelectorAll(".".concat(prefix, "info-el-indicator-item")));
275 | indicatorEls.forEach(function (item) {
276 | if (item.classList.contains('active')) {
277 | item.classList.remove('active');
278 | }
279 | });
280 | if (indicatorEls[stepIndex]) {
281 | indicatorEls[stepIndex].classList.add('active');
282 | }
283 | };
284 | HighlightElement.prototype.computeInfoPosition = function (step, el) {
285 | var _a = this.app.options, padding = _a.padding, margin = _a.margin;
286 | var windowWidth = window.innerWidth;
287 | var windowHeight = window.innerHeight;
288 | var windowPageXOffset = window.pageXOffset;
289 | var windowPageYOffset = window.pageYOffset;
290 | var rect = step.element.getBoundingClientRect();
291 | var infoRect = el.getBoundingClientRect();
292 | var left = 0;
293 | var top = 0;
294 | var adjustLeft = function () {
295 | if (windowWidth - rect.left - padding >= infoRect.width) {
296 | return rect.left - padding + windowPageXOffset;
297 | }
298 | else if (rect.right + padding >= infoRect.width) {
299 | return rect.right + padding - infoRect.width + windowPageXOffset;
300 | }
301 | else {
302 | return (windowWidth - infoRect.width) / 2 + windowPageXOffset;
303 | }
304 | };
305 | var adjustTop = function () {
306 | if (windowHeight - rect.top - padding >= infoRect.height) {
307 | return rect.top - padding + windowPageYOffset;
308 | }
309 | else if (rect.bottom + padding >= infoRect.height) {
310 | return rect.bottom + padding - infoRect.height + windowPageYOffset;
311 | }
312 | else {
313 | return (windowHeight - infoRect.height) / 2 + windowPageYOffset;
314 | }
315 | };
316 | if (rect.bottom + padding + margin + infoRect.height <= windowHeight &&
317 | infoRect.width <= windowWidth) {
318 | left = adjustLeft();
319 | top = rect.bottom + padding + margin + windowPageYOffset;
320 | }
321 | else if (rect.top - padding - margin >= infoRect.height &&
322 | infoRect.width <= windowWidth) {
323 | left = adjustLeft();
324 | top = rect.top - padding - margin - infoRect.height + windowPageYOffset;
325 | }
326 | else if (rect.left - padding - margin >= infoRect.width &&
327 | infoRect.height <= windowHeight) {
328 | left = rect.left - padding - margin - infoRect.width + windowPageXOffset;
329 | top = adjustTop();
330 | }
331 | else if (rect.right + padding + margin + infoRect.width <= windowWidth &&
332 | infoRect.height <= windowHeight) {
333 | left = rect.right + padding + margin + windowPageXOffset;
334 | top = adjustTop();
335 | }
336 | else {
337 | var totalHeightLessThenWindow = rect.height + padding * 2 + margin + infoRect.height <= windowHeight;
338 | if (totalHeightLessThenWindow &&
339 | Math.max(rect.width + padding * 2, infoRect.width) <= windowWidth) {
340 | var newTop = (windowHeight -
341 | (rect.height + padding * 2 + margin + infoRect.height)) /
342 | 2;
343 | window.scrollBy(0, rect.top - newTop);
344 | }
345 | left = adjustLeft();
346 | top = rect.bottom + padding + margin + windowPageYOffset;
347 | }
348 | return {
349 | left: left,
350 | top: top
351 | };
352 | };
353 | return HighlightElement;
354 | }());
355 |
356 | var styleEl = null;
357 | var addCss = function () {
358 | var cssText = '';
359 | cssText += "\n .".concat(prefix, "highlight-el {\n position: absolute;\n }\n ");
360 | cssText += "\n .".concat(prefix, "info-el {\n position: absolute;\n min-width: 250px;\n max-width: 300px;\n }\n\n .").concat(prefix, "info-el-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .").concat(prefix, "info-el-title {\n font-size: 18px;\n margin: 0;\n padding: 0;\n font-weight: 700;\n }\n\n .").concat(prefix, "info-el-close {\n cursor: pointer;\n color: #616161;\n font-size: 22px;\n font-weight: 700;\n }\n\n .").concat(prefix, "info-el-info {\n padding: 15px 0;\n }\n\n .").concat(prefix, "info-el-info-img {\n width: 100%;\n }\n\n .").concat(prefix, "info-el-info-text {\n\n }\n\n .").concat(prefix, "info-el-indicator {\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 10px;\n }\n\n .").concat(prefix, "info-el-indicator-item {\n width: 6px;\n height: 6px;\n background: #ccc;\n transition: width .1s ease-in;\n border-radius: 10px;\n cursor: pointer;\n margin: 0 2px;\n }\n\n .").concat(prefix, "info-el-indicator-item.active, .").concat(prefix, "info-el-indicator-item:hover {\n width: 15px;\n background: #999;\n }\n\n .").concat(prefix, "info-el-btn-group {\n display: flex;\n align-items: center;\n justify-content: space-between;\n border-top: 1px solid #e0e0e0;\n padding-top: 10px;\n }\n\n .").concat(prefix, "info-el-btn {\n width: 60px;\n height: 35px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 1px solid #bdbdbd;\n text-shadow: 1px 1px 0 #fff;\n font-size: 14px;\n color: #424242;\n white-space: nowrap;\n cursor: pointer;\n background-color: #f4f4f4;\n border-radius: 3px;\n }\n\n .").concat(prefix, "info-el-btn.disabled {\n color: #9e9e9e;\n border-color: #bdbdbd;\n cursor: default;\n background-color: #f4f4f4;\n }\n\n .").concat(prefix, "info-el-btn:hover {\n border-color: #9e9e9e;\n background-color: #e0e0e0;\n color: #212121;\n }\n\n .").concat(prefix, "info-el-btn.disabled:hover {\n color: #9e9e9e;\n border-color: #bdbdbd;\n cursor: default;\n background-color: #f4f4f4;\n }\n ");
361 | styleEl = document.createElement('style');
362 | styleEl.innerHTML = cssText;
363 | document.head.appendChild(styleEl);
364 | };
365 | var removeCss = function () {
366 | if (styleEl) {
367 | document.head.removeChild(styleEl);
368 | }
369 | };
370 |
371 | function createCommonjsModule(fn, module) {
372 | return module = { exports: {} }, fn(module, module.exports), module.exports;
373 | }
374 |
375 | var eventemitter3 = createCommonjsModule(function (module) {
376 |
377 | var has = Object.prototype.hasOwnProperty
378 | , prefix = '~';
379 |
380 | /**
381 | * Constructor to create a storage for our `EE` objects.
382 | * An `Events` instance is a plain object whose properties are event names.
383 | *
384 | * @constructor
385 | * @private
386 | */
387 | function Events() {}
388 |
389 | //
390 | // We try to not inherit from `Object.prototype`. In some engines creating an
391 | // instance in this way is faster than calling `Object.create(null)` directly.
392 | // If `Object.create(null)` is not supported we prefix the event names with a
393 | // character to make sure that the built-in object properties are not
394 | // overridden or used as an attack vector.
395 | //
396 | if (Object.create) {
397 | Events.prototype = Object.create(null);
398 |
399 | //
400 | // This hack is needed because the `__proto__` property is still inherited in
401 | // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
402 | //
403 | if (!new Events().__proto__) prefix = false;
404 | }
405 |
406 | /**
407 | * Representation of a single event listener.
408 | *
409 | * @param {Function} fn The listener function.
410 | * @param {*} context The context to invoke the listener with.
411 | * @param {Boolean} [once=false] Specify if the listener is a one-time listener.
412 | * @constructor
413 | * @private
414 | */
415 | function EE(fn, context, once) {
416 | this.fn = fn;
417 | this.context = context;
418 | this.once = once || false;
419 | }
420 |
421 | /**
422 | * Add a listener for a given event.
423 | *
424 | * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
425 | * @param {(String|Symbol)} event The event name.
426 | * @param {Function} fn The listener function.
427 | * @param {*} context The context to invoke the listener with.
428 | * @param {Boolean} once Specify if the listener is a one-time listener.
429 | * @returns {EventEmitter}
430 | * @private
431 | */
432 | function addListener(emitter, event, fn, context, once) {
433 | if (typeof fn !== 'function') {
434 | throw new TypeError('The listener must be a function');
435 | }
436 |
437 | var listener = new EE(fn, context || emitter, once)
438 | , evt = prefix ? prefix + event : event;
439 |
440 | if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
441 | else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
442 | else emitter._events[evt] = [emitter._events[evt], listener];
443 |
444 | return emitter;
445 | }
446 |
447 | /**
448 | * Clear event by name.
449 | *
450 | * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
451 | * @param {(String|Symbol)} evt The Event name.
452 | * @private
453 | */
454 | function clearEvent(emitter, evt) {
455 | if (--emitter._eventsCount === 0) emitter._events = new Events();
456 | else delete emitter._events[evt];
457 | }
458 |
459 | /**
460 | * Minimal `EventEmitter` interface that is molded against the Node.js
461 | * `EventEmitter` interface.
462 | *
463 | * @constructor
464 | * @public
465 | */
466 | function EventEmitter() {
467 | this._events = new Events();
468 | this._eventsCount = 0;
469 | }
470 |
471 | /**
472 | * Return an array listing the events for which the emitter has registered
473 | * listeners.
474 | *
475 | * @returns {Array}
476 | * @public
477 | */
478 | EventEmitter.prototype.eventNames = function eventNames() {
479 | var names = []
480 | , events
481 | , name;
482 |
483 | if (this._eventsCount === 0) return names;
484 |
485 | for (name in (events = this._events)) {
486 | if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
487 | }
488 |
489 | if (Object.getOwnPropertySymbols) {
490 | return names.concat(Object.getOwnPropertySymbols(events));
491 | }
492 |
493 | return names;
494 | };
495 |
496 | /**
497 | * Return the listeners registered for a given event.
498 | *
499 | * @param {(String|Symbol)} event The event name.
500 | * @returns {Array} The registered listeners.
501 | * @public
502 | */
503 | EventEmitter.prototype.listeners = function listeners(event) {
504 | var evt = prefix ? prefix + event : event
505 | , handlers = this._events[evt];
506 |
507 | if (!handlers) return [];
508 | if (handlers.fn) return [handlers.fn];
509 |
510 | for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
511 | ee[i] = handlers[i].fn;
512 | }
513 |
514 | return ee;
515 | };
516 |
517 | /**
518 | * Return the number of listeners listening to a given event.
519 | *
520 | * @param {(String|Symbol)} event The event name.
521 | * @returns {Number} The number of listeners.
522 | * @public
523 | */
524 | EventEmitter.prototype.listenerCount = function listenerCount(event) {
525 | var evt = prefix ? prefix + event : event
526 | , listeners = this._events[evt];
527 |
528 | if (!listeners) return 0;
529 | if (listeners.fn) return 1;
530 | return listeners.length;
531 | };
532 |
533 | /**
534 | * Calls each of the listeners registered for a given event.
535 | *
536 | * @param {(String|Symbol)} event The event name.
537 | * @returns {Boolean} `true` if the event had listeners, else `false`.
538 | * @public
539 | */
540 | EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
541 | var evt = prefix ? prefix + event : event;
542 |
543 | if (!this._events[evt]) return false;
544 |
545 | var listeners = this._events[evt]
546 | , len = arguments.length
547 | , args
548 | , i;
549 |
550 | if (listeners.fn) {
551 | if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
552 |
553 | switch (len) {
554 | case 1: return listeners.fn.call(listeners.context), true;
555 | case 2: return listeners.fn.call(listeners.context, a1), true;
556 | case 3: return listeners.fn.call(listeners.context, a1, a2), true;
557 | case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
558 | case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
559 | case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
560 | }
561 |
562 | for (i = 1, args = new Array(len -1); i < len; i++) {
563 | args[i - 1] = arguments[i];
564 | }
565 |
566 | listeners.fn.apply(listeners.context, args);
567 | } else {
568 | var length = listeners.length
569 | , j;
570 |
571 | for (i = 0; i < length; i++) {
572 | if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
573 |
574 | switch (len) {
575 | case 1: listeners[i].fn.call(listeners[i].context); break;
576 | case 2: listeners[i].fn.call(listeners[i].context, a1); break;
577 | case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
578 | case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
579 | default:
580 | if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
581 | args[j - 1] = arguments[j];
582 | }
583 |
584 | listeners[i].fn.apply(listeners[i].context, args);
585 | }
586 | }
587 | }
588 |
589 | return true;
590 | };
591 |
592 | /**
593 | * Add a listener for a given event.
594 | *
595 | * @param {(String|Symbol)} event The event name.
596 | * @param {Function} fn The listener function.
597 | * @param {*} [context=this] The context to invoke the listener with.
598 | * @returns {EventEmitter} `this`.
599 | * @public
600 | */
601 | EventEmitter.prototype.on = function on(event, fn, context) {
602 | return addListener(this, event, fn, context, false);
603 | };
604 |
605 | /**
606 | * Add a one-time listener for a given event.
607 | *
608 | * @param {(String|Symbol)} event The event name.
609 | * @param {Function} fn The listener function.
610 | * @param {*} [context=this] The context to invoke the listener with.
611 | * @returns {EventEmitter} `this`.
612 | * @public
613 | */
614 | EventEmitter.prototype.once = function once(event, fn, context) {
615 | return addListener(this, event, fn, context, true);
616 | };
617 |
618 | /**
619 | * Remove the listeners of a given event.
620 | *
621 | * @param {(String|Symbol)} event The event name.
622 | * @param {Function} fn Only remove the listeners that match this function.
623 | * @param {*} context Only remove the listeners that have this context.
624 | * @param {Boolean} once Only remove one-time listeners.
625 | * @returns {EventEmitter} `this`.
626 | * @public
627 | */
628 | EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
629 | var evt = prefix ? prefix + event : event;
630 |
631 | if (!this._events[evt]) return this;
632 | if (!fn) {
633 | clearEvent(this, evt);
634 | return this;
635 | }
636 |
637 | var listeners = this._events[evt];
638 |
639 | if (listeners.fn) {
640 | if (
641 | listeners.fn === fn &&
642 | (!once || listeners.once) &&
643 | (!context || listeners.context === context)
644 | ) {
645 | clearEvent(this, evt);
646 | }
647 | } else {
648 | for (var i = 0, events = [], length = listeners.length; i < length; i++) {
649 | if (
650 | listeners[i].fn !== fn ||
651 | (once && !listeners[i].once) ||
652 | (context && listeners[i].context !== context)
653 | ) {
654 | events.push(listeners[i]);
655 | }
656 | }
657 |
658 | //
659 | // Reset the array, or remove it completely if we have no more listeners.
660 | //
661 | if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
662 | else clearEvent(this, evt);
663 | }
664 |
665 | return this;
666 | };
667 |
668 | /**
669 | * Remove all listeners, or those of the specified event.
670 | *
671 | * @param {(String|Symbol)} [event] The event name.
672 | * @returns {EventEmitter} `this`.
673 | * @public
674 | */
675 | EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
676 | var evt;
677 |
678 | if (event) {
679 | evt = prefix ? prefix + event : event;
680 | if (this._events[evt]) clearEvent(this, evt);
681 | } else {
682 | this._events = new Events();
683 | this._eventsCount = 0;
684 | }
685 |
686 | return this;
687 | };
688 |
689 | //
690 | // Alias methods names because people roll like that.
691 | //
692 | EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
693 | EventEmitter.prototype.addListener = EventEmitter.prototype.on;
694 |
695 | //
696 | // Expose the prefix.
697 | //
698 | EventEmitter.prefixed = prefix;
699 |
700 | //
701 | // Allow `EventEmitter` to be imported as module namespace.
702 | //
703 | EventEmitter.EventEmitter = EventEmitter;
704 |
705 | //
706 | // Expose the module.
707 | //
708 | {
709 | module.exports = EventEmitter;
710 | }
711 | });
712 |
713 | var __extends = (undefined && undefined.__extends) || (function () {
714 | var extendStatics = function (d, b) {
715 | extendStatics = Object.setPrototypeOf ||
716 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
717 | function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
718 | return extendStatics(d, b);
719 | };
720 | return function (d, b) {
721 | if (typeof b !== "function" && b !== null)
722 | throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
723 | extendStatics(d, b);
724 | function __() { this.constructor = d; }
725 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
726 | };
727 | })();
728 | var __assign = (undefined && undefined.__assign) || function () {
729 | __assign = Object.assign || function(t) {
730 | for (var s, i = 1, n = arguments.length; i < n; i++) {
731 | s = arguments[i];
732 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
733 | t[p] = s[p];
734 | }
735 | return t;
736 | };
737 | return __assign.apply(this, arguments);
738 | };
739 | var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
740 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
741 | return new (P || (P = Promise))(function (resolve, reject) {
742 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
743 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
744 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
745 | step((generator = generator.apply(thisArg, _arguments || [])).next());
746 | });
747 | };
748 | var __generator = (undefined && undefined.__generator) || function (thisArg, body) {
749 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
750 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
751 | function verb(n) { return function (v) { return step([n, v]); }; }
752 | function step(op) {
753 | if (f) throw new TypeError("Generator is already executing.");
754 | while (g && (g = 0, op[0] && (_ = 0)), _) try {
755 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
756 | if (y = 0, t) op = [op[0] & 2, t.value];
757 | switch (op[0]) {
758 | case 0: case 1: t = op; break;
759 | case 4: _.label++; return { value: op[1], done: false };
760 | case 5: _.label++; y = op[1]; op = [0]; continue;
761 | case 7: op = _.ops.pop(); _.trys.pop(); continue;
762 | default:
763 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
764 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
765 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
766 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
767 | if (t[2]) _.ops.pop();
768 | _.trys.pop(); continue;
769 | }
770 | op = body.call(thisArg, _);
771 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
772 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
773 | }
774 | };
775 | var defaultOptions = {
776 | padding: 10,
777 | margin: 10,
778 | boxShadowColor: 'rgba(0, 0, 0, 0.5)',
779 | transition: 'all 0.3s ease-out',
780 | borderRadius: '5px',
781 | highlightElClass: '',
782 | backgroundColor: '#fff',
783 | infoElClass: '',
784 | prevText: '上一步',
785 | nextText: '下一步',
786 | completeText: '完成',
787 | showIndicator: true,
788 | zIndex: 9999,
789 | useCustomInfo: false,
790 | getCustomInfoEl: null,
791 | steps: []
792 | };
793 | var NoviceGuide = (function (_super) {
794 | __extends(NoviceGuide, _super);
795 | function NoviceGuide(options) {
796 | var _this = _super.call(this) || this;
797 | _this.options = options;
798 | _this.options = Object.assign(defaultOptions, options);
799 | _this.steps = [];
800 | _this.currentStepIndex = -1;
801 | _this.highlightElement = new HighlightElement$1(_this);
802 | _this.infoElement = new HighlightElement(_this);
803 | _this.initSteps();
804 | return _this;
805 | }
806 | NoviceGuide.prototype.initSteps = function () {
807 | var _this = this;
808 | this.options.steps.forEach(function (step) {
809 | _this.steps.push(__assign({}, step));
810 | });
811 | };
812 | NoviceGuide.prototype.start = function () {
813 | if (this.steps.length <= 0)
814 | return;
815 | if (!this.addedCss) {
816 | addCss();
817 | this.addedCss = true;
818 | }
819 | this.next();
820 | };
821 | NoviceGuide.prototype.next = function () {
822 | this.emit('before-step-change', this.currentStepIndex);
823 | if (this.currentStepIndex + 1 >= this.steps.length) {
824 | return this.done();
825 | }
826 | this.currentStepIndex++;
827 | this.to(this.currentStepIndex);
828 | };
829 | NoviceGuide.prototype.prev = function () {
830 | this.emit('before-step-change', this.currentStepIndex);
831 | if (this.currentStepIndex - 1 < 0) {
832 | return;
833 | }
834 | this.currentStepIndex--;
835 | this.to(this.currentStepIndex);
836 | };
837 | NoviceGuide.prototype.jump = function (stepIndex) {
838 | this.currentStepIndex = stepIndex;
839 | this.to(stepIndex);
840 | };
841 | NoviceGuide.prototype.to = function (stepIndex) {
842 | return __awaiter(this, void 0, void 0, function () {
843 | var currentStep, rect, windowHeight;
844 | return __generator(this, function (_a) {
845 | switch (_a.label) {
846 | case 0:
847 | currentStep = this.steps[stepIndex];
848 | currentStep.element =
849 | typeof currentStep.element === 'string'
850 | ? document.querySelector(currentStep.element)
851 | : currentStep.element;
852 | if (currentStep.element) {
853 | scrollAncestorToElement(currentStep.element);
854 | rect = currentStep.element.getBoundingClientRect();
855 | windowHeight = window.innerHeight;
856 | if (!elementIsInView(currentStep.element)) {
857 | window.scrollBy(0, rect.top - (windowHeight - rect.height) / 2);
858 | }
859 | }
860 | this.highlightElement.show(currentStep);
861 | return [4, this.infoElement.show(currentStep)];
862 | case 1:
863 | _a.sent();
864 | this.emit('after-step-change', stepIndex);
865 | return [2];
866 | }
867 | });
868 | });
869 | };
870 | NoviceGuide.prototype.done = function () {
871 | this.highlightElement.removeEl();
872 | this.infoElement.removeEl();
873 | removeCss();
874 | this.addedCss = false;
875 | this.currentStepIndex = -1;
876 | this.emit('done');
877 | };
878 | NoviceGuide.prototype.isFirstStep = function () {
879 | return this.currentStepIndex <= 0;
880 | };
881 | NoviceGuide.prototype.isLastStep = function () {
882 | return this.currentStepIndex >= this.steps.length - 1;
883 | };
884 | return NoviceGuide;
885 | }(eventemitter3));
886 |
887 | return NoviceGuide;
888 |
889 | }));
890 |
--------------------------------------------------------------------------------
/dist/dist.min.js:
--------------------------------------------------------------------------------
1 | !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).SimpleNoviceGuide=e()}(this,(function(){"use strict";var t="simple-novice-guide-",e=function(t){var n=function(t){var e=window.getComputedStyle(t),n="absolute"===e.position,o=/(auto|scroll)/;if("fixed"===e.position)return document.body;for(var i=t.parentElement;i;){if(e=window.getComputedStyle(i),(!n||"static"!==e.position)&&o.test(e.overflow+e.overflowX+e.overflowY))return i;i=i.parentElement}return document.body}(t);if(n!==document.body){var o=n.getBoundingClientRect(),i=t.getBoundingClientRect();n.scrollTop=n.scrollTop+i.top-o.top,e(n)}},n=function(){function e(t){this.app=t,this.app=t,this.el=null}return e.prototype.show=function(t){this.el||this.createEl();var e=0,n=0,o=0,i=0;if(t.element){var r=t.element.getBoundingClientRect(),s=this.app.options.padding;e=r.left+window.pageXOffset-s,n=r.top+window.pageYOffset-s,o=r.width+2*s,i=r.height+2*s}else e=window.innerWidth/2+window.pageXOffset,n=window.innerHeight/2+window.pageYOffset,o=0,i=0;this.el.style.left=e+"px",this.el.style.top=n+"px",this.el.style.width=o+"px",this.el.style.height=i+"px"},e.prototype.createEl=function(){var e=this.app.options,n=e.boxShadowColor,o=e.transition,i=e.borderRadius,r=e.highlightElClass,s=e.zIndex;this.el=document.createElement("div"),this.el.className=t+"highlight-el",this.el.style.cssText="\n box-shadow: 0 0 0 5000px ".concat(n,";\n border-radius: ").concat(i,";\n transition: ").concat(o,";\n z-index: ").concat(s,";\n "),r&&this.el.classList.add(r),document.body.appendChild(this.el)},e.prototype.removeEl=function(){this.el&&(document.body.removeChild(this.el),this.el=null)},e}(),o=function(t,e,n,o){return new(n||(n=Promise))((function(i,r){function s(t){try{a(o.next(t))}catch(t){r(t)}}function c(t){try{a(o.throw(t))}catch(t){r(t)}}function a(t){var e;t.done?i(t.value):(e=t.value,e instanceof n?e:new n((function(t){t(e)}))).then(s,c)}a((o=o.apply(t,e||[])).next())}))},i=function(t,e){var n,o,i,r,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return r={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(r[Symbol.iterator]=function(){return this}),r;function c(c){return function(a){return function(c){if(n)throw new TypeError("Generator is already executing.");for(;r&&(r=0,c[0]&&(s=0)),s;)try{if(n=1,o&&(i=2&c[0]?o.return:c[0]?o.throw||((i=o.return)&&i.call(o),0):o.next)&&!(i=i.call(o,c[1])).done)return i;switch(o=0,i&&(c=[2&c[0],i.value]),c[0]){case 0:case 1:i=c;break;case 4:return s.label++,{value:c[1],done:!1};case 5:s.label++,o=c[1],c=[0];continue;case 7:c=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==c[0]&&2!==c[0])){s=0;continue}if(3===c[0]&&(!i||c[1]>i[0]&&c[1]