rivia 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,45 @@
1
+ **Edit a file, create a new file, and clone from Bitbucket in under 2 minutes**
2
+
3
+ When you're done, you can delete the content in this README and update the file with details for others getting started with your repository.
4
+
5
+ *We recommend that you open this README in another tab as you perform the tasks below. You can [watch our video](https://youtu.be/0ocf7u76WSo) for a full demo of all the steps in this tutorial. Open the video in a new tab to avoid leaving Bitbucket.*
6
+
7
+ ---
8
+
9
+ ## Edit a file
10
+
11
+ You’ll start by editing this README file to learn how to edit a file in Bitbucket.
12
+
13
+ 1. Click **Source** on the left side.
14
+ 2. Click the README.md link from the list of files.
15
+ 3. Click the **Edit** button.
16
+ 4. Delete the following text: *Delete this line to make a change to the README from Bitbucket.*
17
+ 5. After making your change, click **Commit** and then **Commit** again in the dialog. The commit page will open and you’ll see the change you just made.
18
+ 6. Go back to the **Source** page.
19
+
20
+ ---
21
+
22
+ ## Create a file
23
+
24
+ Next, you’ll add a new file to this repository.
25
+
26
+ 1. Click the **New file** button at the top of the **Source** page.
27
+ 2. Give the file a filename of **contributors.txt**.
28
+ 3. Enter your name in the empty file space.
29
+ 4. Click **Commit** and then **Commit** again in the dialog.
30
+ 5. Go back to the **Source** page.
31
+
32
+ Before you move on, go ahead and explore the repository. You've already seen the **Source** page, but check out the **Commits**, **Branches**, and **Settings** pages.
33
+
34
+ ---
35
+
36
+ ## Clone a repository
37
+
38
+ Use these steps to clone from SourceTree, our client for using the repository command-line free. Cloning allows you to work on your files locally. If you don't yet have SourceTree, [download and install first](https://www.sourcetreeapp.com/). If you prefer to clone from the command line, see [Clone a repository](https://confluence.atlassian.com/x/4whODQ).
39
+
40
+ 1. You’ll see the clone button under the **Source** heading. Click that button.
41
+ 2. Now click **Check out in SourceTree**. You may need to create a SourceTree account or log in.
42
+ 3. When you see the **Clone New** dialog in SourceTree, update the destination path and name if you’d like to and then click **Clone**.
43
+ 4. Open the directory you just created to see your repository’s files.
44
+
45
+ Now that you're more familiar with your Bitbucket repository, go ahead and add a new file locally. You can [push your change back to Bitbucket with SourceTree](https://confluence.atlassian.com/x/iqyBMg), or you can [add, commit,](https://confluence.atlassian.com/x/8QhODQ) and [push from the command line](https://confluence.atlassian.com/x/NQ0zDQ).
package/dist/index.js ADDED
@@ -0,0 +1,779 @@
1
+ // src/utils/rivia.js
2
+ function slugify(text) {
3
+ return "/" + String(text || "").trim().toLowerCase().replace(/[^a-z0-9\-_\s]/g, "").replace(/\s+/g, "-");
4
+ }
5
+ function Onboarding(topTitle = "Get Started", subtitle, completion = 0, checklistItems = [], cssText = [], targetingData = {}, user_var, checklist_id) {
6
+ let usrn = targetingData?.targeting_data?.usernames ?? "Not Set";
7
+ let inc = targetingData?.targeting_data?.inclusion ?? "Not Set";
8
+ const mymap = /* @__PURE__ */ new Map();
9
+ for (let i2 = 0; i2 < usrn.length; i2++) {
10
+ mymap.set(usrn[i2], true);
11
+ }
12
+ let flag = false;
13
+ let data = {};
14
+ for (let i2 = 0; i2 < sessionStorage.length; i2++) {
15
+ const key = sessionStorage.key(i2);
16
+ data[key] = sessionStorage.getItem(key);
17
+ let j, t = 0;
18
+ if (mymap.get(data[key]) == true && inc == 2) {
19
+ flag = true;
20
+ t = 1;
21
+ break;
22
+ } else if (mymap.get(data[key]) == true && inc == 1) {
23
+ flag = false;
24
+ return;
25
+ }
26
+ }
27
+ if (inc == 0) {
28
+ flag = true;
29
+ }
30
+ let completedPages = [];
31
+ const items = Array.isArray(checklistItems) && checklistItems.length ? checklistItems.map((it, i2) => ({
32
+ id: it.id || `step${i2 + 1}`,
33
+ title: it.heading || `Step ${i2 + 1}`,
34
+ description: it.body || "",
35
+ completionType: it.completionType || "url",
36
+ url: it.url || slugify(it.title || `step-${i2 + 1}`),
37
+ color: it.color || null
38
+ })) : [];
39
+ const cleanUrlItems = items.map(
40
+ (item) => item.url.startsWith("/") ? item.url.slice(1) : item.url
41
+ );
42
+ const defaultTheme = {
43
+ backgroundColor: "#ffffff",
44
+ lowerBackgroundColor: "#ffffff",
45
+ closeBackgroundColor: "#d9534f",
46
+ textColor: "#000000",
47
+ progressBg: "#a0afa2",
48
+ progressFill: "#01a016",
49
+ subtitleColor: "#666666",
50
+ fontFamily: "Arial, sans-serif",
51
+ fontSize: "14px",
52
+ title: "AI Caller",
53
+ subtitle: "Describe the purpose of this checklist...",
54
+ uncheckedBorderColor: "#d1d5db",
55
+ headingColor: "#111827",
56
+ bodyColor: "#6b7280",
57
+ showCloseButton: true,
58
+ lowerBodyColor: "#6b7280",
59
+ lowerHeadingColor: "#111827"
60
+ };
61
+ const cssConfig = Object.assign({}, defaultTheme, cssText || {});
62
+ if (!items.length) return;
63
+ ["route-label", "show-tooltip-btn", "tooltip-close-btn"].forEach((id) => {
64
+ const el = document.getElementById(id);
65
+ if (el) el.remove();
66
+ });
67
+ const visitedPages = {};
68
+ items.forEach((it) => {
69
+ const cleanUrl = it.url.startsWith("/") ? it.url.slice(1) : it.url;
70
+ visitedPages[cleanUrl] = it.id;
71
+ });
72
+ let storedVisited = JSON.parse(
73
+ sessionStorage.getItem("onboardingVisited") || "[]"
74
+ );
75
+ let user_var1 = user_var;
76
+ if (!user_var1) {
77
+ user_var1 = "User_" + Math.random().toString(36).substring(2, 8);
78
+ sessionStorage.setItem(user_var, user_var1);
79
+ }
80
+ const backendUrl = `https://demoapi.rivia.ai/clients/${checklist_id}/${user_var1}`;
81
+ async function getUserProgress2() {
82
+ try {
83
+ const res = await fetch(backendUrl, { credentials: "include" });
84
+ if (!res.ok) throw new Error(`GET failed: ${res.status}`);
85
+ const data2 = await res.json();
86
+ let userData = data2[user_var1];
87
+ if (Array.isArray(userData)) {
88
+ storedVisited = userData;
89
+ } else if (typeof userData === "object" && userData !== null && Array.isArray(userData.completed_items)) {
90
+ storedVisited = userData.completed_items;
91
+ } else {
92
+ storedVisited = [];
93
+ }
94
+ let path;
95
+ return {
96
+ completedPages: storedVisited,
97
+ progress: storedVisited.length,
98
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
99
+ start_date: userData?.start_date || "",
100
+ end_date: userData?.end_date || userData?.end_data || ""
101
+ };
102
+ } catch (err) {
103
+ console.warn("\u26A0\uFE0F No data found or failed to fetch, starting fresh", err);
104
+ const storedVisited2 = [];
105
+ sessionStorage.setItem(
106
+ "onboardingVisited",
107
+ JSON.stringify(storedVisited2)
108
+ );
109
+ return {
110
+ completedPages: [],
111
+ progress: 0,
112
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
113
+ start_date: "",
114
+ end_date: ""
115
+ };
116
+ }
117
+ }
118
+ storedVisited = sessionStorage.getItem("onboardingVisited");
119
+ if (!storedVisited) {
120
+ getUserProgress2().then((progressData) => {
121
+ if (storedVisited.length >= checklistItems.length) {
122
+ return;
123
+ }
124
+ sessionStorage.setItem(
125
+ "onboardingVisited",
126
+ JSON.stringify(progressData.completedPages)
127
+ );
128
+ fetchWithTimeout(
129
+ topTitle,
130
+ subtitle,
131
+ completion,
132
+ checklistItems,
133
+ cssText,
134
+ targetingData,
135
+ user_var,
136
+ checklist_id,
137
+ cssConfig,
138
+ items,
139
+ storedVisited,
140
+ backendUrl,
141
+ progressData,
142
+ visitedPages,
143
+ cleanUrlItems
144
+ );
145
+ });
146
+ } else {
147
+ try {
148
+ storedVisited = storedVisited ? JSON.parse(storedVisited) : [];
149
+ } catch (e) {
150
+ console.warn(
151
+ "Invalid onboardingVisited data, resetting cache:",
152
+ storedVisited
153
+ );
154
+ storedVisited = [];
155
+ }
156
+ if (storedVisited.length >= checklistItems.length) {
157
+ if (sessionStorage.getItem("CompletedAll") != "true") return;
158
+ const label = document.createElement("div");
159
+ label.id = "route-label";
160
+ label.innerText = "\u{1F389} Congrats! You've completed all items!";
161
+ Object.assign(label.style, {
162
+ position: "fixed",
163
+ bottom: "20px",
164
+ left: "20px",
165
+ backgroundColor: "#4CAF50",
166
+ color: "white",
167
+ padding: "10px 20px",
168
+ borderRadius: "10px",
169
+ boxShadow: "0 4px 6px rgba(0,0,0,0.2)",
170
+ fontSize: "16px",
171
+ fontWeight: "bold",
172
+ zIndex: 9999,
173
+ opacity: 0,
174
+ transition: "opacity 0.5s ease"
175
+ });
176
+ document.body.appendChild(label);
177
+ requestAnimationFrame(() => {
178
+ label.style.opacity = 1;
179
+ });
180
+ setTimeout(() => {
181
+ label.style.opacity = 0;
182
+ setTimeout(() => label.remove(), 500);
183
+ }, 3e3);
184
+ sessionStorage.setItem("CompletedAll", "false ");
185
+ return;
186
+ }
187
+ fetchWithTimeout(
188
+ topTitle,
189
+ subtitle,
190
+ completion,
191
+ checklistItems,
192
+ cssText,
193
+ targetingData,
194
+ user_var,
195
+ checklist_id,
196
+ cssConfig,
197
+ items,
198
+ storedVisited,
199
+ backendUrl,
200
+ [],
201
+ visitedPages,
202
+ cleanUrlItems
203
+ );
204
+ }
205
+ }
206
+ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion = 0, checklistItems = [], cssText = [], targetingData = {}, user_var, checklist_id, cssConfig = {}, items = [], storedVisited = [], backendUrl = "", progressData = {}, visitedPages = {}, cleanUrlItems = []) {
207
+ let i = 0;
208
+ const stepsHTML = items.map((it) => {
209
+ const border = it.color || cssConfig.borderColor1;
210
+ const bg = it.color || cssConfig.lowerBackgroundColor;
211
+ return `
212
+ <div id="${it.id}"
213
+ class="onboard-step"
214
+ style="position: relative; margin-bottom:16px; display:flex; align-items:flex-start; cursor:pointer; background-color:${bg}; padding:8px; border-radius:6px;">
215
+
216
+ <!-- left vertical selector bar -->
217
+ <div class="start-select"
218
+ style="position:absolute; top:0; left:-18px; width:10px; height:120%; background:rgba(247,143,7,0.9); border-radius:4px 0 0 4px; display:none;">
219
+ </div>
220
+
221
+ <div class="onboard-circle"
222
+ style="min-width:16px; min-height:16px; width:16px; height:16px; border-radius:50%;
223
+ border:2px solid ${cssConfig.uncheckedBorderColor}; margin-right:10px; box-sizing:border-box;"></div>
224
+
225
+ <div class="onboard-text"
226
+ style=" font-family:${cssConfig.fontFamily}; font-size:${cssConfig.fontSize};">
227
+ <strong style="color:${cssConfig.lowerHeadingColor};">${it.title}</strong><br>
228
+ <small style="color:${cssConfig.lowerBodyColor};">${it.description || ""}</small>
229
+ </div>
230
+ </div>
231
+ ${i++ < items.length - 1 ? '<hr style="color: #9d9d9dff">' : ""}
232
+ `;
233
+ }).join("");
234
+ const labelHTML = `
235
+ <div id="checklistRoot"
236
+ style="max-width:500px; margin:auto; font-family:${cssConfig.fontFamily}; font-size:${cssConfig.fontSize}; color:${cssConfig.textColor}; position: relative;">
237
+
238
+ <!-- Close button -->
239
+ <button id="checklistCloseBtn"
240
+ style="
241
+ position: absolute;
242
+ top: 8px;
243
+ left: 370px;
244
+ background: transparent;
245
+ border: none;
246
+ font-size: 28px;
247
+ cursor: pointer;
248
+ color: ${cssConfig.textColor};
249
+ line-height: 1;
250
+ ">
251
+ &times;
252
+ </button>
253
+
254
+ <div style="background-color:${cssConfig.backgroundColor}; padding:16px; border-radius:8px 8px 0 0;">
255
+ <h3 style="margin:0;">${topTitle}</h3>
256
+ <p style="margin-top:8px;color: ${cssConfig.subtitleColor};">${subtitle}</p>
257
+ <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px;">
258
+ <div id="progressContainer" style="display: flex; gap: 4px; width: 300%; width: 800px; height: 10px;"></div>
259
+ <span id="progressFraction" style="margin-left: 0px; font-size: 13px; color: ${cssConfig.textColor}; min-width: 20px; text-align: right;">0/0 Complete</span>
260
+ </div>
261
+
262
+ </div>
263
+
264
+ <div style="border-top:none; border-radius:0 0 8px 8px; padding:16px; background-color:${cssConfig.lowerBackgroundColor}; max-height:340px; overflow:auto;">
265
+ ${stepsHTML}
266
+ </div>
267
+ </div>
268
+ `;
269
+ const label = document.createElement("div");
270
+ label.id = "route-label";
271
+ label.innerHTML = labelHTML;
272
+ const closeElement = label.querySelector(`#checklistCloseBtn`);
273
+ closeElement.addEventListener("click", (e) => {
274
+ e.stopPropagation();
275
+ label.style.opacity = "0";
276
+ label.style.pointerEvents = "none";
277
+ closeBtn.style.display = "none";
278
+ showBtn.style.display = "block";
279
+ });
280
+ function createSlabs(n) {
281
+ const container = label.querySelector("#progressContainer");
282
+ container.innerHTML = "";
283
+ for (let i2 = 0; i2 < n; i2++) {
284
+ const slab = document.createElement("div");
285
+ slab.classList.add("slab");
286
+ container.appendChild(slab);
287
+ }
288
+ }
289
+ const style = document.createElement("style");
290
+ style.textContent = `
291
+ .slab {
292
+ flex: 1;
293
+ height: 8px;
294
+ background-color: #ccc;
295
+ border-radius: 4px;
296
+ transition: background-color 0.3s;
297
+ }
298
+ .slab.active {
299
+ background-color: #4caf50;
300
+ }
301
+ #progressContainerBtn .slab {
302
+ height: 5px;
303
+ }
304
+ `;
305
+ label.appendChild(style);
306
+ function updateProgress(completed) {
307
+ const slabs = label.querySelectorAll(".slab");
308
+ slabs.forEach((slab, index) => {
309
+ if (index < completed) {
310
+ slab.classList.add("active");
311
+ } else {
312
+ slab.classList.remove("active");
313
+ }
314
+ });
315
+ }
316
+ createSlabs(items.length);
317
+ updateProgress(storedVisited.length);
318
+ Object.assign(label.style, {
319
+ position: "fixed",
320
+ bottom: "80px",
321
+ left: "20px",
322
+ backgroundColor: cssConfig.backgroundColor,
323
+ color: cssConfig.textColor,
324
+ padding: "0px",
325
+ borderRadius: "10px",
326
+ zIndex: 9999,
327
+ fontSize: cssConfig.fontSize,
328
+ fontFamily: cssConfig.fontFamily,
329
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.2)",
330
+ width: "90%",
331
+ maxWidth: "400px",
332
+ maxHeight: "500px",
333
+ lineHeight: "1.5",
334
+ transition: "opacity 0.5s ease-in-out, transform 0.2s",
335
+ opacity: "0",
336
+ cursor: "pointer",
337
+ textAlign: "left",
338
+ display: "none",
339
+ pointerEvents: "none"
340
+ });
341
+ const showBtn = document.createElement("button");
342
+ function createS(n) {
343
+ const container2 = showBtn.querySelector("#progressContainerBtn");
344
+ if (!container2) return;
345
+ container2.innerHTML = "";
346
+ for (let i2 = 0; i2 < n; i2++) {
347
+ const slab2 = document.createElement("div");
348
+ slab2.classList.add("slab");
349
+ container2.appendChild(slab2);
350
+ }
351
+ }
352
+ function updateProgress2(completed) {
353
+ const slab2 = showBtn.querySelectorAll("#progressContainerBtn .slab");
354
+ slab2.forEach((slab, index) => {
355
+ if (index < completed) {
356
+ slab.classList.add("active");
357
+ } else {
358
+ slab.classList.remove("active");
359
+ }
360
+ });
361
+ }
362
+ showBtn.id = "show-tooltip-btn";
363
+ showBtn.innerHTML = `
364
+ <h3 style="margin:0;">${topTitle}</h3>
365
+ <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px;">
366
+ <div id="progressContainerBtn" style="display: flex; gap: 4px; width: 160%; height: 3px;"></div>
367
+ <span id="progressFraction" style="margin-left: 0px; font-size: 13px;width:15px; color: ${cssConfig.textColor}; min-width: 10px; text-align: right;">0/0</span>
368
+ </div>`;
369
+ Object.assign(showBtn.style, {
370
+ position: "fixed",
371
+ bottom: "20px",
372
+ left: "20px",
373
+ width: "150px",
374
+ padding: "10px 16px",
375
+ fontSize: cssConfig.fontSize,
376
+ fontWeight: "bold",
377
+ backgroundColor: cssConfig.backgroundColor,
378
+ color: cssConfig.textColor,
379
+ border: "none",
380
+ borderRadius: "6px",
381
+ cursor: "pointer",
382
+ zIndex: 9999,
383
+ boxShadow: "0 2px 8px rgba(0, 0, 0, 0.2)"
384
+ });
385
+ document.body.appendChild(showBtn);
386
+ document.body.appendChild(label);
387
+ createS(items.length);
388
+ const closeBtn = document.createElement("button");
389
+ closeBtn.id = "tooltip-close-btn";
390
+ closeBtn.innerHTML = "\u2715";
391
+ Object.assign(closeBtn.style, {
392
+ position: "fixed",
393
+ width: "40px",
394
+ height: "40px",
395
+ border: "none",
396
+ backgroundColor: cssConfig.closeBackgroundColor,
397
+ color: cssConfig.textColor,
398
+ borderRadius: "4px",
399
+ cursor: "pointer",
400
+ fontSize: "25px",
401
+ fontWeight: "bold",
402
+ display: "none",
403
+ alignItems: "center",
404
+ justifyContent: "center",
405
+ zIndex: 1e4
406
+ });
407
+ function positionCloseBtn() {
408
+ const rect = label.getBoundingClientRect();
409
+ closeBtn.style.left = `${Math.max(8, rect.left + rect.width / 2 - 170)}px`;
410
+ closeBtn.style.top = `${rect.bottom + 10}px`;
411
+ }
412
+ const user_var2 = user_var;
413
+ const backendUrl22 = `https://demoapi.rivia.ai/clients/${checklist_id}`;
414
+ function uploadVisitedPagesInBackground(completed2, touched = false) {
415
+ try {
416
+ const payload = {
417
+ name: user_var2,
418
+ completed_items: completed2,
419
+ touched
420
+ };
421
+ fetch(backendUrl22, {
422
+ method: "POST",
423
+ headers: { "Content-Type": "application/json" },
424
+ credentials: "include",
425
+ body: JSON.stringify(payload),
426
+ keepalive: true
427
+ }).then((res) => {
428
+ if (!res.ok) throw new Error(`Upload failed: ${res.status}`);
429
+ }).catch((err) => {
430
+ console.error("\u26A0\uFE0F Background PUT upload failed:", err);
431
+ });
432
+ } catch (err) {
433
+ console.error("\u274C Error preparing background upload:", err);
434
+ }
435
+ }
436
+ uploadVisitedPagesInBackground([], false);
437
+ let activeStepId = sessionStorage.getItem("activeStepId") || null;
438
+ function updateUIFromVisited() {
439
+ storedVisited = JSON.parse(
440
+ sessionStorage.getItem("onboardingVisited") || "[]"
441
+ );
442
+ let path;
443
+ storedVisited = sessionStorage.getItem("onboardingVisited");
444
+ if (!storedVisited) {
445
+ getUserProgress().then((progressData2) => {
446
+ let completed2 = progressData2.completedPages;
447
+ completed2.forEach((path2) => {
448
+ const stepId = visitedPages[path2];
449
+ const stepElement = label.querySelector(`#${stepId}`);
450
+ if (!stepElement) return;
451
+ const circle = stepElement.querySelector(".onboard-circle");
452
+ if (circle) {
453
+ circle.innerHTML = `
454
+ <div style="background-color: green; border-radius: 50%; width: 30px; height: 18px; display: flex; align-items: center; justify-content: center;">
455
+ <svg width="16" height="16" viewBox="0 0 512 512" fill="white" xmlns="http://www.w3.org/2000/svg">
456
+ <path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206
457
+ 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998
458
+ 36.204 0L192 312.69 432.095 72.596c9.997-9.997
459
+ 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997
460
+ 9.997 26.206 0 36.204l-294.4 294.401c-9.998
461
+ 9.997-26.207 9.997-36.204-.001z"/>
462
+ </svg>
463
+ </div>
464
+ `;
465
+ circle.style.border = "none";
466
+ circle.style.backgroundColor = "transparent";
467
+ circle.style.display = "flex";
468
+ circle.style.alignItems = "center";
469
+ circle.style.justifyContent = "center";
470
+ circle.style.padding = "1px";
471
+ }
472
+ const textContainer = stepElement.querySelector(".onboard-text");
473
+ const startSelect = stepElement.querySelector(".start-select");
474
+ if (stepId === activeStepId && startSelect) {
475
+ startSelect.style.display = "block";
476
+ }
477
+ if (textContainer) {
478
+ textContainer.style.textDecoration = "line-through";
479
+ textContainer.style.opacity = "0.6";
480
+ }
481
+ });
482
+ const progress2 = Math.min(
483
+ 100,
484
+ Math.round(completed2.length / items.length * 100)
485
+ );
486
+ const percentText2 = `${progress2}%`;
487
+ const labelPercent2 = label.querySelector("#progressFraction");
488
+ const btnPercent2 = showBtn.querySelector("#progressFraction");
489
+ if (labelPercent2) labelPercent2.textContent = percentText2;
490
+ if (btnPercent2) btnPercent2.textContent = percentText2;
491
+ if (labelPercent2) labelPercent2.style.width = `${progress2}%`;
492
+ if (btnPercent2) btnPercent2.style.width = `${progress2}%`;
493
+ const progressFraction2 = label.querySelector("#progressFraction");
494
+ if (progressFraction2) {
495
+ progressFraction2.textContent = `${completed2.length}/${items.length}`;
496
+ }
497
+ const btnFraction2 = showBtn.querySelector("#progressFraction");
498
+ if (btnFraction2) {
499
+ btnFraction2.textContent = `${completed2.length}/${items.length}`;
500
+ }
501
+ storedVisited = completed2;
502
+ updateProgress(completed2.length);
503
+ updateProgress2(completed2.length);
504
+ });
505
+ } else {
506
+ let completed2 = storedVisited;
507
+ if (completed2) {
508
+ try {
509
+ completed2 = JSON.parse(completed2);
510
+ } catch (e) {
511
+ console.error("Failed to parse onboardingVisited:", e);
512
+ completed2 = [];
513
+ }
514
+ } else {
515
+ completed2 = [];
516
+ }
517
+ completed2.forEach((path2) => {
518
+ const stepId = visitedPages[path2];
519
+ const stepElement = label.querySelector(`#${stepId}`);
520
+ if (!stepElement) return;
521
+ const circle = stepElement.querySelector(".onboard-circle");
522
+ if (circle) {
523
+ circle.innerHTML = `
524
+ <div style="background-color: green; border-radius: 50%; width: 30px; height: 18px; display: flex; align-items: center; justify-content: center;">
525
+ <svg width="16" height="16" viewBox="0 0 512 512" fill="white" xmlns="http://www.w3.org/2000/svg">
526
+ <path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206
527
+ 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998
528
+ 36.204 0L192 312.69 432.095 72.596c9.997-9.997
529
+ 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997
530
+ 9.997 26.206 0 36.204l-294.4 294.401c-9.998
531
+ 9.997-26.207 9.997-36.204-.001z"/>
532
+ </svg>
533
+ </div>
534
+ `;
535
+ circle.style.border = "none";
536
+ circle.style.backgroundColor = "transparent";
537
+ circle.style.display = "flex";
538
+ circle.style.alignItems = "center";
539
+ circle.style.justifyContent = "center";
540
+ circle.style.padding = "1px";
541
+ }
542
+ const textContainer = stepElement.querySelector(".onboard-text");
543
+ const startSelect = stepElement.querySelector(".start-select");
544
+ if (stepId === activeStepId && startSelect) {
545
+ startSelect.style.display = "block";
546
+ }
547
+ if (textContainer) {
548
+ textContainer.style.textDecoration = "line-through";
549
+ textContainer.style.opacity = "0.6";
550
+ }
551
+ });
552
+ const progress2 = Math.min(
553
+ 100,
554
+ Math.round(completed2.length / items.length * 100)
555
+ );
556
+ const percentText2 = `${progress2}%`;
557
+ const labelPercent2 = label.querySelector("#progressFraction");
558
+ const btnPercent2 = showBtn.querySelector("#progressFraction");
559
+ if (labelPercent2) labelPercent2.textContent = percentText2;
560
+ if (btnPercent2) btnPercent2.textContent = percentText2;
561
+ if (labelPercent2) labelPercent2.style.width = `${progress2}%`;
562
+ if (btnPercent2) btnPercent2.style.width = `${progress2}%`;
563
+ const progressFraction2 = label.querySelector("#progressFraction");
564
+ if (progressFraction2) {
565
+ progressFraction2.textContent = `${completed2.length}/${items.length}`;
566
+ }
567
+ const btnFraction2 = showBtn.querySelector("#progressFraction");
568
+ if (btnFraction2) {
569
+ btnFraction2.textContent = `${completed2.length}/${items.length} `;
570
+ }
571
+ storedVisited = completed2;
572
+ updateProgress(completed2.length);
573
+ updateProgress2(completed2.length);
574
+ }
575
+ let completed = storedVisited;
576
+ }
577
+ if (completion == 0) {
578
+ items.forEach((it) => {
579
+ if (it.completionType == "url") {
580
+ const stepEl = label.querySelector(`#${it.id}`);
581
+ if (!stepEl) return;
582
+ const startSelect = stepEl.querySelector(".start-select");
583
+ startSelect.style.display = "none";
584
+ stepEl.addEventListener("click", () => {
585
+ items.forEach((inner) => {
586
+ const el = label.querySelector(`#${inner.id}`);
587
+ if (el) {
588
+ const sel = el.querySelector(".start-select");
589
+ if (sel) sel.style.display = "none";
590
+ }
591
+ });
592
+ startSelect.style.display = "block";
593
+ activeStepId = it.id;
594
+ sessionStorage.setItem("activeStepId", activeStepId);
595
+ storedVisited = JSON.parse(
596
+ sessionStorage.getItem("onboardingVisited") || "[]"
597
+ );
598
+ if (!storedVisited) {
599
+ getUserProgress().then((progressData2) => {
600
+ sessionStorage.setItem(
601
+ "onboardingVisited",
602
+ JSON.stringify(progressData2.completedPages)
603
+ );
604
+ });
605
+ }
606
+ storedVisited = JSON.parse(
607
+ sessionStorage.getItem("onboardingVisited") || "[]"
608
+ );
609
+ let path = it.url;
610
+ let cleanUrl = path.startsWith("/") ? path.slice(1) : path;
611
+ if (!storedVisited.includes(cleanUrl) && cleanUrlItems.includes(cleanUrl)) {
612
+ storedVisited.push(cleanUrl);
613
+ sessionStorage.setItem(
614
+ "onboardingVisited",
615
+ JSON.stringify(storedVisited)
616
+ );
617
+ }
618
+ if (storedVisited.length >= checklistItems.length) {
619
+ sessionStorage.setItem("CompletedAll", "true");
620
+ }
621
+ uploadVisitedPagesInBackground(storedVisited, true);
622
+ updateProgress(storedVisited.length);
623
+ updateProgress2(storedVisited.length);
624
+ updateUIFromVisited();
625
+ if (storedVisited.length >= checklistItems.length) {
626
+ sessionStorage.setItem("CompletedAll", "true");
627
+ }
628
+ window.location.href = it.url;
629
+ });
630
+ }
631
+ });
632
+ } else {
633
+ if (!sessionStorage.getItem("c")) sessionStorage.setItem("c", 1);
634
+ let c = parseInt(sessionStorage.getItem("c") || "1");
635
+ items.forEach((it, index) => {
636
+ const stepEl = label.querySelector(`#${it.id}`);
637
+ if (!stepEl) return;
638
+ const startSelect = stepEl.querySelector(".start-select");
639
+ startSelect.style.display = "none";
640
+ stepEl.addEventListener("click", () => {
641
+ if (index < c) {
642
+ alert("You have already completed this step!");
643
+ c--;
644
+ }
645
+ if (index != c) {
646
+ alert("Please complete the previous steps first!");
647
+ return;
648
+ }
649
+ sessionStorage.setItem("c", c + 1);
650
+ items.forEach((inner) => {
651
+ const el = label.querySelector(`#${inner.id}`);
652
+ if (el) {
653
+ const sel = el.querySelector(".start-select");
654
+ if (sel) sel.style.display = "none";
655
+ }
656
+ });
657
+ startSelect.style.display = "block";
658
+ activeStepId = it.id;
659
+ sessionStorage.setItem("activeStepId", activeStepId);
660
+ let path = it.url;
661
+ let cleanUrl = path.startsWith("/") ? path.slice(1) : path;
662
+ if (!storedVisited.includes(cleanUrl) && cleanUrlItems.includes(cleanUrl)) {
663
+ storedVisited.push(cleanUrl);
664
+ sessionStorage.setItem(
665
+ "onboardingVisited",
666
+ JSON.stringify(storedVisited)
667
+ );
668
+ }
669
+ uploadVisitedPagesInBackground(storedVisited, true);
670
+ updateProgress(storedVisited.length);
671
+ updateProgress2(storedVisited.length);
672
+ updateUIFromVisited();
673
+ if (storedVisited.length >= checklistItems.length) {
674
+ sessionStorage.setItem("CompletedAll", "true");
675
+ }
676
+ window.location.href = it.url;
677
+ });
678
+ });
679
+ }
680
+ showBtn.addEventListener("click", (e) => {
681
+ e.stopPropagation();
682
+ label.style.display = "block";
683
+ label.style.pointerEvents = "auto";
684
+ closeBtn.style.display = "flex";
685
+ showBtn.style.display = "none";
686
+ positionCloseBtn();
687
+ requestAnimationFrame(() => {
688
+ label.style.opacity = "1";
689
+ });
690
+ });
691
+ closeBtn.addEventListener("click", (ev) => {
692
+ ev.stopPropagation();
693
+ label.style.opacity = "0";
694
+ label.style.pointerEvents = "none";
695
+ closeBtn.style.display = "none";
696
+ showBtn.style.display = "block";
697
+ });
698
+ label.addEventListener(
699
+ "mouseenter",
700
+ () => label.style.transform = "scale(1.02)"
701
+ );
702
+ label.addEventListener(
703
+ "mouseleave",
704
+ () => label.style.transform = "scale(1)"
705
+ );
706
+ label.addEventListener("click", () => {
707
+ const getStarted = document.querySelector("button#get-started");
708
+ if (getStarted) getStarted.click();
709
+ });
710
+ showBtn.style.display = "block";
711
+ label.style.display = "none";
712
+ label.style.opacity = "0";
713
+ updateUIFromVisited();
714
+ window.addEventListener("resize", () => {
715
+ if (label.style.display !== "none") positionCloseBtn();
716
+ });
717
+ }
718
+ async function OnboardingPopup(checklist_id, user_var) {
719
+ try {
720
+ const cachedData = sessionStorage.getItem(`checklist_${checklist_id}`);
721
+ if (cachedData) {
722
+ const { checklist: checklist2, cssConfig: cssConfig2, targetingData: targetingData2 } = JSON.parse(cachedData);
723
+ Onboarding(
724
+ checklist2.title || "Untitled Checklist",
725
+ checklist2.subtitle || "Describe the purpose of this checklist...",
726
+ checklist2.completion || 0,
727
+ checklist2.items || [],
728
+ cssConfig2 || {},
729
+ targetingData2 || {},
730
+ user_var,
731
+ checklist_id
732
+ );
733
+ return checklist2;
734
+ }
735
+ const res = await fetch(
736
+ `https://demoapi.rivia.ai/checklists2/${checklist_id}`,
737
+ {
738
+ method: "GET",
739
+ headers: { "Content-Type": "application/json" }
740
+ }
741
+ );
742
+ if (!res.ok) {
743
+ console.error("\u274C Failed to fetch checklist");
744
+ return;
745
+ }
746
+ const data = await res.json();
747
+ const checklist = data.checklist || data;
748
+ const title = checklist.title || "Untitled Checklist";
749
+ const subtitle = checklist.subtitle || "Describe the purpose of this checklist...";
750
+ const items = checklist.items || [];
751
+ const completion = checklist.completion || 0;
752
+ const cssConfig = checklist.branding_data || {};
753
+ const targetingData = checklist.targeting_data || {};
754
+ const fullData = { checklist, cssConfig, targetingData };
755
+ sessionStorage.setItem(
756
+ `checklist_${checklist_id}`,
757
+ JSON.stringify(fullData)
758
+ );
759
+ Onboarding(
760
+ title,
761
+ subtitle,
762
+ completion,
763
+ items,
764
+ cssConfig,
765
+ targetingData,
766
+ user_var,
767
+ checklist_id
768
+ );
769
+ return checklist;
770
+ } catch (err) {
771
+ console.error("Error fetching checklist or branding:", err.message);
772
+ throw err;
773
+ }
774
+ }
775
+ var my_onboarding_app_default = OnboardingPopup;
776
+ export {
777
+ OnboardingPopup,
778
+ my_onboarding_app_default as default
779
+ };
package/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ declare function OnboardingPopup(
2
+ checklist_id: string,
3
+ user_var: string
4
+ ): void ;
5
+ export = OnboardingPopup ;
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "rivia",
3
+ "version": "0.0.4",
4
+ "type": "module",
5
+ "main": "dist/index.cjs",
6
+ "module": "dist/index.js",
7
+ "types": "index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "index.d.ts"
18
+ ],
19
+ "scripts": {
20
+ "build": "node build.js"
21
+ },
22
+ "devDependencies": {
23
+ "esbuild": "^0.24.0"
24
+ },
25
+ "dependencies": {
26
+ "express": "^5.1.0",
27
+ "mongodb": "^6.18.0",
28
+ "my-onboarding-app": "^1.0.200"
29
+ }
30
+ }