rivia 0.0.108 → 0.0.110

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.
Files changed (2) hide show
  1. package/dist/index.js +1157 -185
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  function slugify(text) {
3
3
  return "/" + String(text || "").trim().toLowerCase().replace(/[^a-z0-9\-_\s]/g, "").replace(/\s+/g, "-");
4
4
  }
5
- function Onboarding(topTitle = "Get Started", subtitle, completion = 0, checklistItems = [], cssText = [], targetingData = {}, customCSS = "", user_var, checklist_id) {
5
+ function Onboarding(topTitle = "Get Started", subtitle, completion = 0, checklistItems = [], cssText = [], targetingData = {}, customCSS = "", user_var, checklist_id, congratulatory_message, button_text = "Get Started", redirect_url = "", button_present = false) {
6
6
  if (sessionStorage.getItem(`dismissedChecklist${checklist_id}`) == "true")
7
7
  return;
8
8
  let usrn = targetingData?.targeting_data?.usernames ?? "Not Set";
@@ -62,6 +62,132 @@ function Onboarding(topTitle = "Get Started", subtitle, completion = 0, checklis
62
62
  lowerHeadingColor: "#111827"
63
63
  };
64
64
  const cssConfig = Object.assign({}, defaultTheme, cssText || {});
65
+ const completionButtonPresent = button_present;
66
+ const completionCssConfig = cssConfig;
67
+ const completionTopTitle = topTitle;
68
+ const completionCongratulatoryMessage = congratulatory_message;
69
+ const completionButtonText = button_text;
70
+ const completionRedirectUrl = redirect_url;
71
+ window.renderCompletionCard = (config = {}) => {
72
+ const completionConfig = {
73
+ button_present,
74
+ cssConfig,
75
+ topTitle,
76
+ congratulatory_message,
77
+ button_text,
78
+ redirect_url,
79
+ ...config
80
+ };
81
+ const completionTheme = completionConfig.cssConfig || {};
82
+ const shouldShowGoButton = completionConfig.button_present === true || completionConfig.button_present === "true" || completionConfig.button_present === 1 || completionConfig.button_present === "1";
83
+ const {
84
+ completion_height = "auto",
85
+ completion_width = "300px",
86
+ completion_background_color = "#ffffff",
87
+ completion_text_color = completion_background_color === "#ffffff" ? completionTheme.textColor || "#111827" : "#000000",
88
+ completion_font_size = completionTheme.fontSize || "16px",
89
+ completion_subtitle_color = completionTheme.subtitleColor || completion_text_color,
90
+ completion_title_font_family = completionTheme.fontFamily || "Arial, sans-serif",
91
+ completion_title_font_size = "18px",
92
+ completion_button_bg_color = completionTheme.button_background_color || "#ffffff",
93
+ completion_button_text_color = completionTheme.button_text_color || "#4CAF50",
94
+ completion_button_font_family = completionTheme.fontFamily || "Arial, sans-serif",
95
+ completion_button_font_size = completionTheme.button_font_size || "14px",
96
+ completion_dismiss_background_color = "#f44336",
97
+ completion_dismiss_text_color = "#ffffff"
98
+ } = completionTheme;
99
+ const completionTitle = completionConfig.topTitle || "Checklist Complete";
100
+ const completionSubtitle = completionConfig.congratulatory_message || "\u{1F389}Congratulations! You have completed the checklist.";
101
+ const label = document.createElement("div");
102
+ label.id = "route-label";
103
+ Object.assign(label.style, {
104
+ position: "fixed",
105
+ top: "50%",
106
+ left: "50%",
107
+ transform: "translate(-50%, -50%)",
108
+ alignItems: "center",
109
+ width: completion_width,
110
+ height: completion_height,
111
+ backgroundColor: completion_background_color,
112
+ color: completion_text_color,
113
+ padding: "15px",
114
+ borderRadius: "12px",
115
+ boxShadow: "0 6px 12px rgba(0,0,0,0.2)",
116
+ fontSize: completion_font_size,
117
+ fontFamily: completionTheme.fontFamily || "Arial, sans-serif",
118
+ zIndex: 9999,
119
+ display: "flex",
120
+ flexDirection: "column",
121
+ gap: "10px"
122
+ });
123
+ const title = document.createElement("div");
124
+ title.innerText = completionTitle;
125
+ Object.assign(title.style, {
126
+ color: completion_text_color,
127
+ fontFamily: completion_title_font_family,
128
+ fontSize: completion_title_font_size,
129
+ fontWeight: "bold",
130
+ lineHeight: "1.3"
131
+ });
132
+ const message = document.createElement("div");
133
+ message.innerText = completionSubtitle;
134
+ Object.assign(message.style, {
135
+ color: completion_subtitle_color,
136
+ fontSize: completion_font_size,
137
+ lineHeight: "1.5",
138
+ textAlign: "center"
139
+ });
140
+ const btnContainer = document.createElement("div");
141
+ Object.assign(btnContainer.style, {
142
+ display: "flex",
143
+ justifyContent: shouldShowGoButton ? "space-between" : "flex-end",
144
+ gap: "10px",
145
+ marginTop: "4px"
146
+ });
147
+ const goBtn = document.createElement("button");
148
+ goBtn.innerText = completionConfig.button_text || "Get Started";
149
+ Object.assign(goBtn.style, {
150
+ padding: "8px 12px",
151
+ border: "none",
152
+ borderRadius: "6px",
153
+ cursor: "pointer",
154
+ backgroundColor: completion_button_bg_color,
155
+ color: completion_button_text_color,
156
+ fontFamily: completion_button_font_family,
157
+ fontSize: completion_button_font_size,
158
+ fontWeight: "bold"
159
+ });
160
+ goBtn.onclick = () => {
161
+ sessionStorage.setItem("CompletedAll", "false");
162
+ window.open(completionConfig.redirect_url || "/dashboard", "_blank");
163
+ };
164
+ const closeBtn = document.createElement("button");
165
+ closeBtn.innerText = "Dismiss";
166
+ Object.assign(closeBtn.style, {
167
+ padding: "8px 12px",
168
+ border: "none",
169
+ borderRadius: "6px",
170
+ cursor: "pointer",
171
+ backgroundColor: completion_dismiss_background_color,
172
+ color: completion_dismiss_text_color,
173
+ fontFamily: completion_button_font_family,
174
+ fontSize: completion_button_font_size
175
+ });
176
+ closeBtn.onclick = () => {
177
+ label.style.opacity = 0;
178
+ sessionStorage.setItem("CompletedAll", "false");
179
+ setTimeout(() => label.remove(), 500);
180
+ };
181
+ if (shouldShowGoButton) {
182
+ btnContainer.appendChild(goBtn);
183
+ }
184
+ btnContainer.appendChild(closeBtn);
185
+ if (completionSubtitle) {
186
+ label.appendChild(message);
187
+ }
188
+ label.appendChild(btnContainer);
189
+ document.body.appendChild(label);
190
+ };
65
191
  if (!items.length) return;
66
192
  ["route-label", "show-tooltip-btn", "tooltip-close-btn"].forEach((id) => {
67
193
  const el = document.getElementById(id);
@@ -75,10 +201,10 @@ function Onboarding(topTitle = "Get Started", subtitle, completion = 0, checklis
75
201
  visitedPages[it.event_name] = it.id;
76
202
  }
77
203
  });
78
- let storedVisited2 = JSON.parse(
204
+ let storedVisited = JSON.parse(
79
205
  sessionStorage.getItem("onboardingVisited") || "[]"
80
206
  );
81
- if (!Array.isArray(storedVisited2)) storedVisited2 = [];
207
+ if (!Array.isArray(storedVisited)) storedVisited = [];
82
208
  let user_var1 = user_var;
83
209
  if (!user_var1) {
84
210
  user_var1 = "User_" + Math.random().toString(36).substring(2, 8);
@@ -93,16 +219,16 @@ function Onboarding(topTitle = "Get Started", subtitle, completion = 0, checklis
93
219
  const data2 = await res.json();
94
220
  let userData = data2[user_var1];
95
221
  if (Array.isArray(userData)) {
96
- storedVisited2 = userData;
222
+ storedVisited = userData;
97
223
  } else if (typeof userData === "object" && userData !== null && Array.isArray(userData.completed_items)) {
98
- storedVisited2 = userData.completed_items;
224
+ storedVisited = userData.completed_items;
99
225
  } else {
100
- storedVisited2 = [];
226
+ storedVisited = [];
101
227
  }
102
228
  let path;
103
229
  return {
104
- completedPages: storedVisited2,
105
- progress: storedVisited2.length,
230
+ completedPages: storedVisited,
231
+ progress: storedVisited.length,
106
232
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
107
233
  start_date: userData?.start_date || "",
108
234
  end_date: userData?.end_date || userData?.end_data || ""
@@ -112,7 +238,7 @@ function Onboarding(topTitle = "Get Started", subtitle, completion = 0, checklis
112
238
  "\u26A0\uFE0F Invalid checklist Id",
113
239
  err
114
240
  );
115
- const storedVisited22 = [];
241
+ const storedVisited2 = [];
116
242
  return {
117
243
  completedPages: [],
118
244
  progress: 0,
@@ -122,7 +248,7 @@ function Onboarding(topTitle = "Get Started", subtitle, completion = 0, checklis
122
248
  };
123
249
  }
124
250
  }
125
- storedVisited2 = sessionStorage.getItem("onboardingVisited");
251
+ storedVisited = sessionStorage.getItem("onboardingVisited");
126
252
  async function getUserProgress22() {
127
253
  const backendUrl2 = `https://demoapi.rivia.ai/clients/${checklist_id}/${user_var1}`;
128
254
  try {
@@ -131,16 +257,16 @@ function Onboarding(topTitle = "Get Started", subtitle, completion = 0, checklis
131
257
  const data2 = await res.json();
132
258
  let userData = data2[user_var1];
133
259
  if (Array.isArray(userData)) {
134
- storedVisited2 = userData;
260
+ storedVisited = userData;
135
261
  } else if (typeof userData === "object" && userData !== null && Array.isArray(userData.completed_items)) {
136
- storedVisited2 = userData.completed_items;
262
+ storedVisited = userData.completed_items;
137
263
  } else {
138
- storedVisited2 = [];
264
+ storedVisited = [];
139
265
  }
140
266
  let path;
141
267
  return {
142
- completedPages: storedVisited2,
143
- progress: storedVisited2.length,
268
+ completedPages: storedVisited,
269
+ progress: storedVisited.length,
144
270
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
145
271
  start_date: userData?.start_date || "",
146
272
  end_date: userData?.end_date || userData?.end_data || ""
@@ -186,9 +312,11 @@ function Onboarding(topTitle = "Get Started", subtitle, completion = 0, checklis
186
312
  };
187
313
  }
188
314
  }
189
- if (!storedVisited2 || storedVisited2 == "[]") {
315
+ if (!storedVisited || storedVisited == "[]") {
190
316
  getUserProgress22().then((progressData) => {
191
- if (storedVisited2 && storedVisited2.length >= checklistItems.length) {
317
+ if (storedVisited && storedVisited.length >= checklistItems.length) {
318
+ if (sessionStorage.getItem("CompletedAll") != "true") return;
319
+ window.renderCompletionCard();
192
320
  return;
193
321
  }
194
322
  sessionStorage.setItem(
@@ -206,53 +334,31 @@ function Onboarding(topTitle = "Get Started", subtitle, completion = 0, checklis
206
334
  checklist_id,
207
335
  cssConfig,
208
336
  items,
209
- storedVisited2,
337
+ storedVisited,
210
338
  backendUrl,
211
339
  progressData,
212
340
  visitedPages,
213
341
  cleanUrlItems,
214
- customCSS
342
+ customCSS,
343
+ congratulatory_message,
344
+ button_text,
345
+ completionRedirectUrl,
346
+ button_present
215
347
  );
216
348
  });
217
349
  } else {
218
350
  try {
219
- storedVisited2 = storedVisited2 ? JSON.parse(storedVisited2) : [];
351
+ storedVisited = storedVisited ? JSON.parse(storedVisited) : [];
220
352
  } catch (e) {
221
353
  console.warn(
222
354
  "Invalid onboardingVisited data, resetting cache:",
223
- storedVisited2
355
+ storedVisited
224
356
  );
225
- storedVisited2 = [];
357
+ storedVisited = [];
226
358
  }
227
- if (storedVisited2 && storedVisited2.length >= checklistItems.length) {
359
+ if (storedVisited && storedVisited.length >= checklistItems.length) {
228
360
  if (sessionStorage.getItem("CompletedAll") != "true") return;
229
- const label = document.createElement("div");
230
- label.id = "route-label";
231
- label.innerText = "\u{1F389} Congrats! You've completed all items!";
232
- Object.assign(label.style, {
233
- position: "fixed",
234
- bottom: "20px",
235
- left: "20px",
236
- backgroundColor: "#4CAF50",
237
- color: "white",
238
- padding: "10px 20px",
239
- borderRadius: "10px",
240
- boxShadow: "0 4px 6px rgba(0,0,0,0.2)",
241
- fontSize: "16px",
242
- fontWeight: "bold",
243
- zIndex: 9999,
244
- opacity: 0,
245
- transition: "opacity 0.5s ease"
246
- });
247
- document.body.appendChild(label);
248
- requestAnimationFrame(() => {
249
- label.style.opacity = 1;
250
- });
251
- setTimeout(() => {
252
- label.style.opacity = 0;
253
- setTimeout(() => label.remove(), 500);
254
- }, 3e3);
255
- sessionStorage.setItem("CompletedAll", "false ");
361
+ window.renderCompletionCard();
256
362
  return;
257
363
  }
258
364
  fetchWithTimeout(
@@ -266,16 +372,20 @@ function Onboarding(topTitle = "Get Started", subtitle, completion = 0, checklis
266
372
  checklist_id,
267
373
  cssConfig,
268
374
  items,
269
- storedVisited2,
375
+ storedVisited,
270
376
  backendUrl,
271
377
  [],
272
378
  visitedPages,
273
379
  cleanUrlItems,
274
- customCSS
380
+ customCSS,
381
+ congratulatory_message,
382
+ button_text,
383
+ completionRedirectUrl,
384
+ button_present
275
385
  );
276
386
  }
277
387
  }
278
- async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion = 0, checklistItems = [], cssText = [], targetingData = {}, user_var, checklist_id, cssConfig = {}, items = [], storedVisited2 = [], backendUrl = "", progressData = {}, visitedPages = {}, cleanUrlItems = [], custom_css = "") {
388
+ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion = 0, checklistItems = [], cssText = [], targetingData = {}, user_var, checklist_id, cssConfig = {}, items = [], storedVisited = [], backendUrl = "", progressData = {}, visitedPages = {}, cleanUrlItems = [], custom_css = "", congratulatory_message = "", button_text = "Get Started", redirect_url = "", button_present = false) {
279
389
  console.log("inside fetchWithTimeout", user_var);
280
390
  if (!user_var)
281
391
  return;
@@ -660,7 +770,7 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
660
770
  }
661
771
  }
662
772
  createSlabs(items.length);
663
- if (storedVisited2) updateProgress(storedVisited2.length);
773
+ if (storedVisited) updateProgress(storedVisited.length);
664
774
  Object.assign(label.style, {
665
775
  position: "fixed",
666
776
  bottom: "80px",
@@ -782,8 +892,16 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
782
892
  window.updateUIFromVisited = updateUIFromVisited;
783
893
  window.updateProgress = updateProgress;
784
894
  window.updateProgress2 = updateProgress2;
785
- window.storedVisited = storedVisited2;
895
+ window.storedVisited = storedVisited;
786
896
  window.uploadVisitedPagesInBackground = uploadVisitedPagesInBackground;
897
+ window.completionCardConfig = {
898
+ button_present,
899
+ cssConfig,
900
+ topTitle,
901
+ congratulatory_message,
902
+ button_text,
903
+ redirect_url
904
+ };
787
905
  window.items = items;
788
906
  window.label = label;
789
907
  window.showBtn = showBtn;
@@ -842,7 +960,7 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
842
960
  return false;
843
961
  }
844
962
  visitedSet.add(cleanUrl);
845
- storedVisited2 = [...visitedSet];
963
+ storedVisited = [...visitedSet];
846
964
  persistVisited();
847
965
  try {
848
966
  uploadVisitedPagesInBackground([...visitedSet], true);
@@ -881,7 +999,7 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
881
999
  check = 1;
882
1000
  const path = it.url || "";
883
1001
  const cleanUrl = path.startsWith("/") ? path.slice(1) : path;
884
- if (storedVisited2.length >= checklistItems.length) {
1002
+ if (storedVisited.length >= checklistItems.length) {
885
1003
  (() => {
886
1004
  if (label2 && label2.parentNode) label2.remove();
887
1005
  if (showBtn && showBtn.parentNode) showBtn.remove();
@@ -907,7 +1025,7 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
907
1025
  })();
908
1026
  }
909
1027
  handleVisit(cleanUrl, { source: "click" });
910
- if (storedVisited2.length >= checklistItems.length) {
1028
+ if (storedVisited.length >= checklistItems.length) {
911
1029
  (() => {
912
1030
  if (label && label.parentNode) label.remove();
913
1031
  if (showBtn && showBtn.parentNode) showBtn.remove();
@@ -977,12 +1095,12 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
977
1095
  }
978
1096
  let activeStepId = sessionStorage.getItem("activeStepId") || null;
979
1097
  function updateUIFromVisited() {
980
- storedVisited2 = JSON.parse(
1098
+ storedVisited = JSON.parse(
981
1099
  sessionStorage.getItem("onboardingVisited") || "[]"
982
1100
  );
983
1101
  let path;
984
- storedVisited2 = sessionStorage.getItem("onboardingVisited");
985
- if (!storedVisited2 || storedVisited2 == "[]") {
1102
+ storedVisited = sessionStorage.getItem("onboardingVisited");
1103
+ if (!storedVisited || storedVisited == "[]") {
986
1104
  async function getUserProgress22() {
987
1105
  const backendUrl2 = `https://demoapi.rivia.ai/clients/${checklist_id}/${user_var}`;
988
1106
  try {
@@ -991,16 +1109,16 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
991
1109
  const data2 = await res.json();
992
1110
  let userData = data2[user_var];
993
1111
  if (Array.isArray(userData)) {
994
- storedVisited2 = userData;
1112
+ storedVisited = userData;
995
1113
  } else if (typeof userData === "object" && userData !== null && Array.isArray(userData.completed_items)) {
996
- storedVisited2 = userData.completed_items;
1114
+ storedVisited = userData.completed_items;
997
1115
  } else {
998
- storedVisited2 = [];
1116
+ storedVisited = [];
999
1117
  }
1000
1118
  let path2;
1001
1119
  return {
1002
- completedPages: storedVisited2,
1003
- progress: storedVisited2.length,
1120
+ completedPages: storedVisited,
1121
+ progress: storedVisited.length,
1004
1122
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1005
1123
  start_date: userData?.start_date || "",
1006
1124
  end_date: userData?.end_date || userData?.end_data || ""
@@ -1011,7 +1129,7 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
1011
1129
  err
1012
1130
  );
1013
1131
  uploadVisitedPagesInBackground([], false);
1014
- const storedVisited22 = [];
1132
+ const storedVisited2 = [];
1015
1133
  return {
1016
1134
  completedPages: [],
1017
1135
  progress: 0,
@@ -1075,12 +1193,12 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
1075
1193
  if (btnFraction2) {
1076
1194
  btnFraction2.textContent = `${completed2.length}/${items.length}`;
1077
1195
  }
1078
- storedVisited2 = completed2;
1196
+ storedVisited = completed2;
1079
1197
  updateProgress(completed2.length);
1080
1198
  updateProgress2(completed2.length);
1081
1199
  });
1082
1200
  } else {
1083
- let completed2 = storedVisited2;
1201
+ let completed2 = storedVisited;
1084
1202
  if (completed2) {
1085
1203
  try {
1086
1204
  completed2 = JSON.parse(completed2);
@@ -1144,11 +1262,11 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
1144
1262
  if (btnFraction2) {
1145
1263
  btnFraction2.textContent = `${completed2.length}/${items.length} `;
1146
1264
  }
1147
- storedVisited2 = completed2;
1265
+ storedVisited = completed2;
1148
1266
  updateProgress(completed2.length);
1149
1267
  updateProgress2(completed2.length);
1150
1268
  }
1151
- let completed = storedVisited2;
1269
+ let completed = storedVisited;
1152
1270
  }
1153
1271
  if (completion == 0) {
1154
1272
  items.forEach((it) => {
@@ -1168,10 +1286,10 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
1168
1286
  startSelect.style.display = "block";
1169
1287
  activeStepId = it.id;
1170
1288
  sessionStorage.setItem("activeStepId", activeStepId);
1171
- storedVisited2 = JSON.parse(
1289
+ storedVisited = JSON.parse(
1172
1290
  sessionStorage.getItem("onboardingVisited") || "[]"
1173
1291
  );
1174
- if (!storedVisited2 || storedVisited2 == "[]") {
1292
+ if (!storedVisited || storedVisited == "[]") {
1175
1293
  getUserProgress2().then((progressData2) => {
1176
1294
  sessionStorage.setItem(
1177
1295
  "onboardingVisited",
@@ -1179,26 +1297,26 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
1179
1297
  );
1180
1298
  });
1181
1299
  }
1182
- storedVisited2 = JSON.parse(
1300
+ storedVisited = JSON.parse(
1183
1301
  sessionStorage.getItem("onboardingVisited") || "[]"
1184
1302
  );
1185
1303
  let path = it.url;
1186
1304
  let cleanUrl = path.startsWith("/") ? path.slice(1) : path;
1187
- if (!storedVisited2.includes(cleanUrl) && cleanUrlItems.includes(cleanUrl)) {
1188
- storedVisited2.push(cleanUrl);
1305
+ if (!storedVisited.includes(cleanUrl) && cleanUrlItems.includes(cleanUrl)) {
1306
+ storedVisited.push(cleanUrl);
1189
1307
  sessionStorage.setItem(
1190
1308
  "onboardingVisited",
1191
- JSON.stringify(storedVisited2)
1309
+ JSON.stringify(storedVisited)
1192
1310
  );
1193
1311
  }
1194
- if (storedVisited2.length >= checklistItems.length) {
1312
+ if (storedVisited.length >= checklistItems.length) {
1195
1313
  sessionStorage.setItem("CompletedAll", "true");
1196
1314
  }
1197
- uploadVisitedPagesInBackground(storedVisited2, true);
1198
- updateProgress(storedVisited2.length);
1199
- updateProgress2(storedVisited2.length);
1315
+ uploadVisitedPagesInBackground(storedVisited, true);
1316
+ updateProgress(storedVisited.length);
1317
+ updateProgress2(storedVisited.length);
1200
1318
  updateUIFromVisited();
1201
- if (storedVisited2.length >= checklistItems.length) {
1319
+ if (storedVisited.length >= checklistItems.length) {
1202
1320
  sessionStorage.setItem("CompletedAll", "true");
1203
1321
  }
1204
1322
  }
@@ -1235,18 +1353,18 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
1235
1353
  sessionStorage.setItem("activeStepId", activeStepId);
1236
1354
  let path = it.url;
1237
1355
  let cleanUrl = path.startsWith("/") ? path.slice(1) : path;
1238
- if (!storedVisited2.includes(cleanUrl) && cleanUrlItems.includes(cleanUrl)) {
1239
- storedVisited2.push(cleanUrl);
1356
+ if (!storedVisited.includes(cleanUrl) && cleanUrlItems.includes(cleanUrl)) {
1357
+ storedVisited.push(cleanUrl);
1240
1358
  sessionStorage.setItem(
1241
1359
  "onboardingVisited",
1242
- JSON.stringify(storedVisited2)
1360
+ JSON.stringify(storedVisited)
1243
1361
  );
1244
1362
  }
1245
- uploadVisitedPagesInBackground(storedVisited2, true);
1246
- updateProgress(storedVisited2.length);
1247
- updateProgress2(storedVisited2.length);
1363
+ uploadVisitedPagesInBackground(storedVisited, true);
1364
+ updateProgress(storedVisited.length);
1365
+ updateProgress2(storedVisited.length);
1248
1366
  updateUIFromVisited();
1249
- if (storedVisited2.length >= checklistItems.length) {
1367
+ if (storedVisited.length >= checklistItems.length) {
1250
1368
  sessionStorage.setItem("CompletedAll", "true");
1251
1369
  }
1252
1370
  window.location.href = it.url;
@@ -1454,9 +1572,13 @@ async function Checklist(workspace_id, obj) {
1454
1572
  subtitle = "Describe the purpose of this checklist...",
1455
1573
  items = [],
1456
1574
  completion = 0,
1575
+ congratulatory_message = "Congrats! You've completed all items!",
1576
+ button_text = "Get Started",
1457
1577
  branding_data: cssConfig = {},
1458
1578
  targeting_data: targetingData = {},
1459
- customCSS = ""
1579
+ url = "",
1580
+ customCSS = "",
1581
+ button_present = false
1460
1582
  } = matchedChecklist;
1461
1583
  const fullData = {
1462
1584
  checklist: matchedChecklist,
@@ -1464,6 +1586,7 @@ async function Checklist(workspace_id, obj) {
1464
1586
  targetingData,
1465
1587
  customCSS
1466
1588
  };
1589
+ const redirectUrl = url;
1467
1590
  sessionStorage.removeItem("onboardingVisited");
1468
1591
  Onboarding(
1469
1592
  title,
@@ -1474,7 +1597,11 @@ async function Checklist(workspace_id, obj) {
1474
1597
  targetingData,
1475
1598
  customCSS,
1476
1599
  user_var,
1477
- checklist_id
1600
+ checklist_id,
1601
+ congratulatory_message,
1602
+ button_text,
1603
+ redirectUrl,
1604
+ button_present
1478
1605
  );
1479
1606
  return matchedChecklist;
1480
1607
  } catch (err) {
@@ -1573,17 +1700,25 @@ var RIVIA_TOUR = function() {
1573
1700
  card_footer = true,
1574
1701
  card_back_button = false,
1575
1702
  card_next_button = true,
1576
- card_skip_button = false
1703
+ card_skip_button = false,
1704
+ preview_width = null,
1705
+ preview_height = null,
1706
+ buttons = [],
1707
+ stepIndex = null
1577
1708
  }) {
1578
1709
  const anchor = await findBySelector(selector);
1579
1710
  if (!anchor) return null;
1580
1711
  const tip = document.createElement("div");
1581
1712
  tip.dataset.riviaTipId = id;
1713
+ const parsedPreviewWidth = Number.parseInt(preview_width, 10);
1714
+ const parsedPreviewHeight = Number.parseInt(preview_height, 10);
1715
+ const resolvedPreviewWidth = Number.isInteger(parsedPreviewWidth) && parsedPreviewWidth > 0 ? parsedPreviewWidth : null;
1716
+ const resolvedPreviewHeight = Number.isInteger(parsedPreviewHeight) && parsedPreviewHeight > 0 ? parsedPreviewHeight : null;
1582
1717
  const tipStyle = isPreview ? `
1583
1718
  position: absolute;
1584
- min-width: 360px;
1719
+ ${resolvedPreviewWidth ? `width: ${resolvedPreviewWidth}px;` : "min-width: 360px;"}
1585
1720
  max-width: 420px;
1586
- min-height: 120px;
1721
+ ${resolvedPreviewHeight ? `height: ${resolvedPreviewHeight}px;` : "min-height: 120px;"}
1587
1722
  padding: 18px 20px;
1588
1723
  background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
1589
1724
  color: #1a202c;
@@ -1697,6 +1832,10 @@ var RIVIA_TOUR = function() {
1697
1832
  }
1698
1833
  tip.appendChild(contentWrapper);
1699
1834
  tip.appendChild(controls);
1835
+ if (Array.isArray(buttons) && buttons.length > 0) {
1836
+ const buttonsSection = createCardButtonsSection({ buttons }, stepIndex ?? STATE.tourIndex, tip);
1837
+ tip.appendChild(buttonsSection);
1838
+ }
1700
1839
  tip.appendChild(arrow);
1701
1840
  document.body.appendChild(tip);
1702
1841
  positionTooltip(anchor, tip, arrow, placement);
@@ -1843,6 +1982,119 @@ var RIVIA_TOUR = function() {
1843
1982
  displayText: isAvailable ? "\u2713 On this page" : `\u{1F4CD} Go to: ${targetUrl}`
1844
1983
  };
1845
1984
  }
1985
+ function resolveConfiguredStepIndex(rawValue, fallbackIndex = null) {
1986
+ const parsed = Number.parseInt(rawValue, 10);
1987
+ if (Number.isInteger(parsed) && parsed >= 0 && parsed < STATE.tips.length) {
1988
+ return parsed;
1989
+ }
1990
+ if (Number.isInteger(fallbackIndex) && fallbackIndex >= 0 && fallbackIndex < STATE.tips.length) {
1991
+ return fallbackIndex;
1992
+ }
1993
+ return null;
1994
+ }
1995
+ async function goToStepIndex(targetIndex, isPreviewMode = STATE.isPreviewMode) {
1996
+ const resolvedIndex = resolveConfiguredStepIndex(targetIndex);
1997
+ if (resolvedIndex === null) {
1998
+ return false;
1999
+ }
2000
+ const targetStep = STATE.tips[resolvedIndex];
2001
+ if (!targetStep) {
2002
+ return false;
2003
+ }
2004
+ const targetUrlInfo = getStepUrlInfo(targetStep);
2005
+ if (targetUrlInfo && !targetUrlInfo.isAvailable && targetStep.targetUrl) {
2006
+ STATE.tourIndex = resolvedIndex;
2007
+ sessionStorage.setItem("rivia_tour_state", JSON.stringify({
2008
+ tourIndex: resolvedIndex,
2009
+ tourId: STATE.tour_id,
2010
+ user_var1,
2011
+ isPreviewMode,
2012
+ tips: STATE.tips,
2013
+ title: STATE.title || "Untitled Tour",
2014
+ publish: STATE.publish
2015
+ }));
2016
+ const navUrl = addTourParamsToUrl(targetStep.targetUrl, STATE.tour_id);
2017
+ window.location.href = navUrl;
2018
+ return true;
2019
+ }
2020
+ document.querySelectorAll("[data-rivia-tip-id]").forEach((node) => node.remove());
2021
+ STATE.tourIndex = resolvedIndex;
2022
+ cleanupAllOverlays();
2023
+ await showStep(resolvedIndex, isPreviewMode);
2024
+ return true;
2025
+ }
2026
+ function createCardButtonsSection(step, stepIndex, hostElement = null) {
2027
+ const clamp = (value, min, max) => Math.min(max, Math.max(min, value));
2028
+ const buttons = Array.isArray(step?.buttons) ? step.buttons.slice().sort((a, b) => (a.position ?? 0) - (b.position ?? 0)) : [];
2029
+ const buttonsSection = document.createElement("div");
2030
+ buttonsSection.className = "rivia-step-buttons-section";
2031
+ buttonsSection.style.cssText = `
2032
+ position: absolute;
2033
+ inset: 0;
2034
+ pointer-events: none;
2035
+ z-index: 30;
2036
+ `;
2037
+ if (!buttons.length) {
2038
+ return buttonsSection;
2039
+ }
2040
+ const buttonsList = document.createElement("div");
2041
+ buttonsList.style.cssText = `
2042
+ position: absolute;
2043
+ inset: 0;
2044
+ width: 100%;
2045
+ height: 100%;
2046
+ `;
2047
+ buttonsSection.appendChild(buttonsList);
2048
+ const hostRect = hostElement?.getBoundingClientRect() || buttonsSection.getBoundingClientRect();
2049
+ const width = Math.max(1, hostRect.width);
2050
+ const height = Math.max(1, hostRect.height);
2051
+ buttons.forEach((buttonData) => {
2052
+ const hasExplicitWidth = Number.isInteger(buttonData.width) && buttonData.width > 0;
2053
+ const hasExplicitHeight = Number.isInteger(buttonData.height) && buttonData.height > 0;
2054
+ const xPercentRaw = Number.parseFloat(buttonData.x_percent);
2055
+ const yPercentRaw = Number.parseFloat(buttonData.y_percent);
2056
+ const fallbackX = Number.parseFloat(buttonData.x);
2057
+ const fallbackY = Number.parseFloat(buttonData.y);
2058
+ const normalizedX = Number.isFinite(xPercentRaw) ? xPercentRaw : Number.isFinite(fallbackX) ? fallbackX / width * 100 : 50;
2059
+ const normalizedY = Number.isFinite(yPercentRaw) ? yPercentRaw : Number.isFinite(fallbackY) ? fallbackY / height * 100 : 50;
2060
+ const clampedX = clamp(normalizedX, 4, 96);
2061
+ const clampedY = clamp(normalizedY, 6, 94);
2062
+ const button = document.createElement("button");
2063
+ button.type = "button";
2064
+ button.textContent = buttonData.text || buttonData.name || "Button";
2065
+ button.style.cssText = `
2066
+ position: absolute;
2067
+ left: ${clampedX}%;
2068
+ top: ${clampedY}%;
2069
+ transform: translate(-50%, -50%);
2070
+ pointer-events: auto;
2071
+ z-index: 31;
2072
+ ${hasExplicitWidth ? `width: ${buttonData.width}px;` : "padding: 8px 16px;"}
2073
+ ${hasExplicitHeight ? `height: ${buttonData.height}px;` : ""}
2074
+ display: inline-flex;
2075
+ align-items: center;
2076
+ justify-content: center;
2077
+ border: none;
2078
+ border-radius: 999px;
2079
+ background: ${buttonData.color || "#2563eb"};
2080
+ color: #ffffff;
2081
+ font-size: 13px;
2082
+ font-weight: 600;
2083
+ cursor: pointer;
2084
+ box-shadow: 0 8px 18px rgba(15, 23, 42, 0.18);
2085
+ white-space: nowrap;
2086
+ `;
2087
+ button.onclick = async (event) => {
2088
+ event.stopPropagation();
2089
+ const targetIndex = resolveConfiguredStepIndex(buttonData.go_to_step_index, stepIndex + 1);
2090
+ if (targetIndex !== null) {
2091
+ await goToStepIndex(targetIndex, true);
2092
+ }
2093
+ };
2094
+ buttonsList.appendChild(button);
2095
+ });
2096
+ return buttonsSection;
2097
+ }
1846
2098
  async function showStep(i, isPreview = true) {
1847
2099
  uploadVisitedPagesInBackground(STATE.tour_id, user_var1, i);
1848
2100
  console.log("Showing step", i, "of", STATE.tips.length);
@@ -1984,7 +2236,7 @@ var RIVIA_TOUR = function() {
1984
2236
  }
1985
2237
  }
1986
2238
  setTimeout(async () => {
1987
- const tip2 = await createTooltip({ ...step, isPreview });
2239
+ const tip2 = await createTooltip({ ...step, isPreview, stepIndex: i });
1988
2240
  if (tip2) {
1989
2241
  await attachNavigationButtons(tip2, i, isPreview);
1990
2242
  try {
@@ -2016,7 +2268,7 @@ var RIVIA_TOUR = function() {
2016
2268
  el.style.backgroundColor = "rgba(37, 99, 235, 0.1)";
2017
2269
  }
2018
2270
  }
2019
- const tip = await createTooltip({ ...step, isPreview });
2271
+ const tip = await createTooltip({ ...step, isPreview, stepIndex: i });
2020
2272
  console.log("nextUrl for step", step.nextUrl);
2021
2273
  if (!tip) {
2022
2274
  const stepUrlInfo = getStepUrlInfo(step);
@@ -2554,6 +2806,7 @@ var RIVIA_TOUR = function() {
2554
2806
  modal.id = "rivia-welcome-preview-modal";
2555
2807
  const bgColor = step.welcome_bg_color || "#ffffff";
2556
2808
  modal.style.cssText = `
2809
+ position: relative;
2557
2810
  background: ${bgColor};
2558
2811
  border-radius: 12px;
2559
2812
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
@@ -2596,6 +2849,7 @@ var RIVIA_TOUR = function() {
2596
2849
  const footerTextColor = step.welcome_footer_text_color || "#333333";
2597
2850
  const footerHeight = step.welcome_footer_height || 60;
2598
2851
  contentSection.style.cssText = `
2852
+ position: relative;
2599
2853
  padding: ${footerPadding}px 30px;
2600
2854
  text-align: center;
2601
2855
  background: ${footerBgColor};
@@ -2619,6 +2873,8 @@ var RIVIA_TOUR = function() {
2619
2873
  `;
2620
2874
  contentSection.appendChild(descriptionText);
2621
2875
  modal.appendChild(contentSection);
2876
+ const welcomeButtonsSection = createCardButtonsSection(step, stepIndex, contentSection);
2877
+ contentSection.appendChild(welcomeButtonsSection);
2622
2878
  const buttonSection = document.createElement("div");
2623
2879
  buttonSection.style.cssText = `
2624
2880
  display: flex;
@@ -2688,7 +2944,14 @@ var RIVIA_TOUR = function() {
2688
2944
  "rivia-welcome-preview-backdrop"
2689
2945
  );
2690
2946
  if (backdropOverlay) backdropOverlay.remove();
2691
- if (advanceAction === "next button") {
2947
+ if (advanceAction === "go to step") {
2948
+ const targetIndex = resolveConfiguredStepIndex(step.go_to_step_index, stepIndex + 1);
2949
+ if (targetIndex !== null) {
2950
+ await goToStepIndex(targetIndex, true);
2951
+ } else {
2952
+ endTour();
2953
+ }
2954
+ } else if (advanceAction === "next button") {
2692
2955
  STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
2693
2956
  if (STATE.tourIndex < STATE.tips.length) {
2694
2957
  showStep(STATE.tourIndex, true);
@@ -2797,6 +3060,7 @@ var RIVIA_TOUR = function() {
2797
3060
  const accentColor = step.modal_accent_color || "#10b981";
2798
3061
  modal.style.cssText = `
2799
3062
  pointer-events: auto;
3063
+ position: relative;
2800
3064
  background: ${modalBgColor};
2801
3065
  border-radius: 12px;
2802
3066
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
@@ -2819,6 +3083,7 @@ var RIVIA_TOUR = function() {
2819
3083
  const contentSection = document.createElement("div");
2820
3084
  contentSection.style.cssText = `
2821
3085
  flex: 1;
3086
+ position: relative;
2822
3087
  padding: 30px;
2823
3088
  color: ${modalTextColor};
2824
3089
  overflow-y: auto;
@@ -2827,6 +3092,8 @@ var RIVIA_TOUR = function() {
2827
3092
  `;
2828
3093
  contentSection.textContent = step.content || "Type your content here.";
2829
3094
  modal.appendChild(contentSection);
3095
+ const modalButtonsSection = createCardButtonsSection(step, stepIndex, contentSection);
3096
+ contentSection.appendChild(modalButtonsSection);
2830
3097
  const footerSection = document.createElement("div");
2831
3098
  footerSection.style.cssText = `
2832
3099
  background: ${modalFooterBgColor};
@@ -2889,7 +3156,14 @@ var RIVIA_TOUR = function() {
2889
3156
  "rivia-modal-dialog-preview-backdrop"
2890
3157
  );
2891
3158
  if (backdropOverlay) backdropOverlay.remove();
2892
- if (advanceAction === "next button") {
3159
+ if (advanceAction === "go to step") {
3160
+ const targetIndex = resolveConfiguredStepIndex(step.go_to_step_index, stepIndex + 1);
3161
+ if (targetIndex !== null) {
3162
+ await goToStepIndex(targetIndex, true);
3163
+ } else {
3164
+ endTour();
3165
+ }
3166
+ } else if (advanceAction === "next button") {
2893
3167
  STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
2894
3168
  if (STATE.tourIndex < STATE.tips.length) {
2895
3169
  showStep(STATE.tourIndex, true);
@@ -3036,7 +3310,18 @@ var RIVIA_TOUR = function() {
3036
3310
  if (isPreview)
3037
3311
  next.style.background = "linear-gradient(135deg, rgba(37, 99, 235, 0.9) 0%, rgba(37, 99, 235, 0.8) 100%)";
3038
3312
  };
3039
- next.onclick = () => i === STATE.tips.length - 1 ? endTour() : nextStep();
3313
+ next.onclick = async () => {
3314
+ if (advanceAction === "go to step") {
3315
+ const targetIndex = resolveConfiguredStepIndex(step.go_to_step_index, i + 1);
3316
+ if (targetIndex !== null) {
3317
+ await goToStepIndex(targetIndex, isPreview);
3318
+ } else {
3319
+ endTour();
3320
+ }
3321
+ } else {
3322
+ i === STATE.tips.length - 1 ? endTour() : nextStep();
3323
+ }
3324
+ };
3040
3325
  nav.appendChild(next);
3041
3326
  }
3042
3327
  if (card_skip_button) {
@@ -3428,6 +3713,7 @@ var RIVIA_TOUR = function() {
3428
3713
  modal.id = "rivia-feedback-preview-modal";
3429
3714
  const bgColor = step.feedback_bg_color || "#ffffff";
3430
3715
  modal.style.cssText = `
3716
+ position: relative;
3431
3717
  background: ${bgColor};
3432
3718
  border-radius: 12px;
3433
3719
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
@@ -3470,6 +3756,7 @@ var RIVIA_TOUR = function() {
3470
3756
  const footerTextColor = step.feedback_footer_text_color || "#333333";
3471
3757
  const footerHeight = step.feedback_footer_height || 60;
3472
3758
  contentSection.style.cssText = `
3759
+ position: relative;
3473
3760
  padding: ${footerPadding}px 30px;
3474
3761
  text-align: center;
3475
3762
  background: ${footerBgColor};
@@ -3546,6 +3833,8 @@ var RIVIA_TOUR = function() {
3546
3833
  });
3547
3834
  contentSection.appendChild(emojiContainer);
3548
3835
  modal.appendChild(contentSection);
3836
+ const feedbackButtonsSection = createCardButtonsSection(step, stepIndex, contentSection);
3837
+ contentSection.appendChild(feedbackButtonsSection);
3549
3838
  const buttonSection = document.createElement("div");
3550
3839
  buttonSection.style.cssText = `
3551
3840
  display: flex;
@@ -3616,7 +3905,14 @@ var RIVIA_TOUR = function() {
3616
3905
  if (STATE.tour_id) putTips();
3617
3906
  else saveTips();
3618
3907
  }
3619
- if (advanceAction === "next button") {
3908
+ if (advanceAction === "go to step") {
3909
+ const targetIndex = resolveConfiguredStepIndex(step.go_to_step_index, stepIndex + 1);
3910
+ if (targetIndex !== null) {
3911
+ await goToStepIndex(targetIndex, true);
3912
+ } else {
3913
+ endTour();
3914
+ }
3915
+ } else if (advanceAction === "next button") {
3620
3916
  STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
3621
3917
  if (STATE.tourIndex < STATE.tips.length) {
3622
3918
  showStep(STATE.tourIndex, true);
@@ -3750,10 +4046,446 @@ function evaluateRules2(rules, context) {
3750
4046
  }
3751
4047
  return finalResult;
3752
4048
  }
4049
+ function findAnchorForParallelStep(selector) {
4050
+ if (!selector || typeof document === "undefined") {
4051
+ return null;
4052
+ }
4053
+ try {
4054
+ const element = document.querySelector(selector);
4055
+ if (element) {
4056
+ return element;
4057
+ }
4058
+ } catch {
4059
+ }
4060
+ const idMatch = selector.match(/#([\w-]+)/);
4061
+ if (idMatch) {
4062
+ const byId = document.getElementById(idMatch[1]);
4063
+ if (byId) {
4064
+ return byId;
4065
+ }
4066
+ }
4067
+ const classMatch = selector.match(/\.([\w-]+)/);
4068
+ if (classMatch) {
4069
+ const byClass = document.querySelector(`.${classMatch[1]}`);
4070
+ if (byClass) {
4071
+ return byClass;
4072
+ }
4073
+ }
4074
+ return null;
4075
+ }
4076
+ function removeParallelTourUi(tourId) {
4077
+ if (typeof document === "undefined") {
4078
+ return;
4079
+ }
4080
+ document.querySelectorAll(`[data-rivia-parallel-tour-id="${tourId}"]`).forEach((node) => {
4081
+ node.remove();
4082
+ });
4083
+ }
4084
+ function positionParallelTooltip(anchor, tooltip, slotIndex = 0) {
4085
+ if (!tooltip || typeof window === "undefined") {
4086
+ return;
4087
+ }
4088
+ if (anchor) {
4089
+ const rect = anchor.getBoundingClientRect();
4090
+ const tipRect = tooltip.getBoundingClientRect();
4091
+ let left = rect.right + 12;
4092
+ let top = rect.top + window.scrollY;
4093
+ if (left + tipRect.width > window.innerWidth - 8) {
4094
+ left = rect.left - tipRect.width - 12;
4095
+ }
4096
+ if (left < 8) {
4097
+ left = 8;
4098
+ }
4099
+ top = Math.max(8 + window.scrollY, Math.min(top, window.scrollY + window.innerHeight - tipRect.height - 8));
4100
+ tooltip.style.left = `${left + window.scrollX}px`;
4101
+ tooltip.style.top = `${top}px`;
4102
+ return;
4103
+ }
4104
+ tooltip.style.left = `${window.scrollX + Math.max(12, window.innerWidth - 350)}px`;
4105
+ tooltip.style.top = `${window.scrollY + 20 + slotIndex * 160}px`;
4106
+ }
4107
+ function syncParallelTourProgress(tourId, userId, index, isCompleted = false) {
4108
+ if (!tourId || !userId) {
4109
+ return;
4110
+ }
4111
+ fetch(`https://demoapi.rivia.ai/tours_clients/${tourId}`, {
4112
+ method: "POST",
4113
+ headers: { "Content-Type": "application/json" },
4114
+ credentials: "include",
4115
+ body: JSON.stringify({
4116
+ name: userId,
4117
+ tourIndex: index,
4118
+ is_completed: isCompleted
4119
+ }),
4120
+ keepalive: true
4121
+ }).catch(() => {
4122
+ });
4123
+ }
4124
+ function applyParallelHighlight(runtime, element) {
4125
+ if (!runtime || !element) {
4126
+ return;
4127
+ }
4128
+ if (runtime.highlightedElement && runtime.highlightedElement !== element) {
4129
+ runtime.highlightedElement.style.outline = runtime.highlightSnapshot?.outline || "";
4130
+ runtime.highlightedElement.style.outlineOffset = runtime.highlightSnapshot?.outlineOffset || "";
4131
+ runtime.highlightedElement.style.backgroundColor = runtime.highlightSnapshot?.backgroundColor || "";
4132
+ }
4133
+ runtime.highlightedElement = element;
4134
+ runtime.highlightSnapshot = {
4135
+ outline: element.style.outline,
4136
+ outlineOffset: element.style.outlineOffset,
4137
+ backgroundColor: element.style.backgroundColor
4138
+ };
4139
+ element.style.outline = "3px solid #2563eb";
4140
+ element.style.outlineOffset = "2px";
4141
+ element.style.backgroundColor = "rgba(37, 99, 235, 0.1)";
4142
+ }
4143
+ function clearParallelHighlight(runtime) {
4144
+ if (!runtime?.highlightedElement) {
4145
+ return;
4146
+ }
4147
+ runtime.highlightedElement.style.outline = runtime.highlightSnapshot?.outline || "";
4148
+ runtime.highlightedElement.style.outlineOffset = runtime.highlightSnapshot?.outlineOffset || "";
4149
+ runtime.highlightedElement.style.backgroundColor = runtime.highlightSnapshot?.backgroundColor || "";
4150
+ runtime.highlightedElement = null;
4151
+ runtime.highlightSnapshot = null;
4152
+ }
4153
+ function advanceParallelTour(runtime) {
4154
+ const isLastStep = runtime.index >= runtime.steps.length - 1;
4155
+ if (isLastStep) {
4156
+ syncParallelTourProgress(runtime.tourId, runtime.userId, runtime.index, true);
4157
+ clearParallelHighlight(runtime);
4158
+ removeParallelTourUi(runtime.tourId);
4159
+ if (window.__riviaParallelTourRuntimes) {
4160
+ delete window.__riviaParallelTourRuntimes[runtime.tourId];
4161
+ }
4162
+ return;
4163
+ }
4164
+ runtime.index += 1;
4165
+ syncParallelTourProgress(runtime.tourId, runtime.userId, runtime.index, false);
4166
+ renderParallelTourStep(runtime);
4167
+ }
4168
+ function renderParallelWelcomeCard(runtime, step) {
4169
+ const overlay2 = document.createElement("div");
4170
+ overlay2.dataset.riviaParallelTourId = runtime.tourId;
4171
+ overlay2.style.cssText = `
4172
+ position: fixed;
4173
+ inset: 0;
4174
+ background: rgba(0, 0, 0, 0.5);
4175
+ display: flex;
4176
+ align-items: center;
4177
+ justify-content: center;
4178
+ z-index: 2147483644;
4179
+ `;
4180
+ const modal = document.createElement("div");
4181
+ modal.dataset.riviaParallelTourId = runtime.tourId;
4182
+ modal.style.cssText = `
4183
+ position: relative;
4184
+ background: ${step.welcome_bg_color || "#ffffff"};
4185
+ border-radius: 12px;
4186
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
4187
+ max-width: 700px;
4188
+ width: 90%;
4189
+ max-height: 80vh;
4190
+ overflow-y: auto;
4191
+ padding: 0;
4192
+ `;
4193
+ const header = document.createElement("div");
4194
+ const headerHeight = step.welcome_header_height || 80;
4195
+ header.style.cssText = `
4196
+ background: ${step.welcome_header_bg_color || "#667eea"};
4197
+ padding: ${headerHeight / 2}px 30px;
4198
+ color: ${step.welcome_header_text_color || "#ffffff"};
4199
+ border-radius: 12px 12px 0 0;
4200
+ text-align: center;
4201
+ min-height: ${headerHeight}px;
4202
+ display: flex;
4203
+ align-items: center;
4204
+ justify-content: center;
4205
+ `;
4206
+ const title = document.createElement("h1");
4207
+ title.textContent = step.title || runtime.title || "Welcome!";
4208
+ title.style.cssText = `
4209
+ margin: 0;
4210
+ font-size: 32px;
4211
+ font-weight: bold;
4212
+ color: ${step.welcome_header_text_color || "#ffffff"};
4213
+ font-family: inherit;
4214
+ `;
4215
+ header.appendChild(title);
4216
+ modal.appendChild(header);
4217
+ const content = document.createElement("div");
4218
+ const footerHeight = step.welcome_footer_height || 60;
4219
+ const footerPadding = step.welcome_footer_padding || 20;
4220
+ content.style.cssText = `
4221
+ padding: ${footerPadding}px 30px;
4222
+ text-align: center;
4223
+ background: ${step.welcome_footer_bg_color || "#ffffff"};
4224
+ color: ${step.welcome_footer_text_color || "#333333"};
4225
+ min-height: ${footerHeight}px;
4226
+ display: flex;
4227
+ align-items: center;
4228
+ justify-content: center;
4229
+ `;
4230
+ const description = document.createElement("p");
4231
+ description.textContent = step.content || "Welcome message";
4232
+ description.style.cssText = `
4233
+ margin: 0;
4234
+ font-size: 14px;
4235
+ line-height: 1.6;
4236
+ color: ${step.welcome_footer_text_color || "#333333"};
4237
+ white-space: pre-wrap;
4238
+ word-wrap: break-word;
4239
+ font-family: inherit;
4240
+ `;
4241
+ content.appendChild(description);
4242
+ modal.appendChild(content);
4243
+ const buttonSection = document.createElement("div");
4244
+ buttonSection.style.cssText = `
4245
+ display: flex;
4246
+ gap: 12px;
4247
+ padding: 20px 30px;
4248
+ border-top: 1px solid #e5e7eb;
4249
+ justify-content: flex-end;
4250
+ `;
4251
+ const skipBtn = document.createElement("button");
4252
+ skipBtn.textContent = step.welcome_skip_label || "Skip";
4253
+ skipBtn.style.cssText = `
4254
+ padding: 8px 16px;
4255
+ border: 1px solid #d1d5db;
4256
+ border-radius: 6px;
4257
+ background: white;
4258
+ color: #6b7280;
4259
+ cursor: pointer;
4260
+ font-size: 14px;
4261
+ font-weight: 500;
4262
+ `;
4263
+ skipBtn.onclick = () => {
4264
+ syncParallelTourProgress(runtime.tourId, runtime.userId, runtime.index, true);
4265
+ clearParallelHighlight(runtime);
4266
+ removeParallelTourUi(runtime.tourId);
4267
+ if (window.__riviaParallelTourRuntimes) {
4268
+ delete window.__riviaParallelTourRuntimes[runtime.tourId];
4269
+ }
4270
+ };
4271
+ buttonSection.appendChild(skipBtn);
4272
+ const nextBtn = document.createElement("button");
4273
+ nextBtn.textContent = step.welcome_next_label || (runtime.index >= runtime.steps.length - 1 ? "Finish \u2713" : "Next");
4274
+ nextBtn.style.cssText = `
4275
+ padding: 8px 16px;
4276
+ border: none;
4277
+ border-radius: 6px;
4278
+ background: #2563eb;
4279
+ color: white;
4280
+ cursor: pointer;
4281
+ font-size: 14px;
4282
+ font-weight: 500;
4283
+ `;
4284
+ nextBtn.onclick = () => {
4285
+ advanceParallelTour(runtime);
4286
+ };
4287
+ buttonSection.appendChild(nextBtn);
4288
+ modal.appendChild(buttonSection);
4289
+ overlay2.appendChild(modal);
4290
+ document.body.appendChild(overlay2);
4291
+ overlay2.onclick = (e) => {
4292
+ if (e.target === overlay2) {
4293
+ removeParallelTourUi(runtime.tourId);
4294
+ renderParallelTourStep(runtime);
4295
+ }
4296
+ };
4297
+ }
4298
+ function renderParallelTourStep(runtime) {
4299
+ if (!runtime || !runtime.steps?.length || typeof document === "undefined") {
4300
+ return;
4301
+ }
4302
+ removeParallelTourUi(runtime.tourId);
4303
+ const step = runtime.steps[runtime.index];
4304
+ if (!step) {
4305
+ return;
4306
+ }
4307
+ if (step.card_type === "welcome") {
4308
+ renderParallelWelcomeCard(runtime, step);
4309
+ return;
4310
+ }
4311
+ const anchor = findAnchorForParallelStep(step.selector);
4312
+ if (anchor) {
4313
+ applyParallelHighlight(runtime, anchor);
4314
+ }
4315
+ const tooltip = document.createElement("div");
4316
+ tooltip.dataset.riviaParallelTourId = runtime.tourId;
4317
+ tooltip.style.cssText = `
4318
+ position: absolute;
4319
+ min-width: 360px;
4320
+ max-width: 420px;
4321
+ min-height: 120px;
4322
+ padding: 18px 20px;
4323
+ background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
4324
+ color: #1a202c;
4325
+ border-radius: 14px;
4326
+ border: 1px solid rgba(37, 99, 235, 0.2);
4327
+ box-shadow: 0 12px 40px rgba(37, 99, 235, 0.15), 0 0 1px rgba(0, 0, 0, 0.1);
4328
+ z-index: 2147483647;
4329
+ font: 14px/1.45 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
4330
+ font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
4331
+ `;
4332
+ const title = document.createElement("div");
4333
+ title.style.cssText = "font-weight:700; margin-bottom:10px; font-size:16px; color: #1a202c;";
4334
+ title.textContent = step.title || runtime.title || "Tour Step";
4335
+ tooltip.appendChild(title);
4336
+ const content = document.createElement("div");
4337
+ content.style.cssText = "font-size:13px; line-height:1.6; color: #4a5568; margin-bottom: 10px;";
4338
+ content.textContent = step.content || "";
4339
+ tooltip.appendChild(content);
4340
+ const arrow = document.createElement("div");
4341
+ arrow.style.cssText = `
4342
+ position: absolute;
4343
+ width: 12px;
4344
+ height: 12px;
4345
+ background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
4346
+ border: 1px solid rgba(37, 99, 235, 0.2);
4347
+ transform: rotate(45deg);
4348
+ left: -6px;
4349
+ top: 18px;
4350
+ `;
4351
+ tooltip.appendChild(arrow);
4352
+ const footer = document.createElement("div");
4353
+ footer.style.cssText = "display: flex; align-items: center; justify-content: flex-end; gap: 8px; margin-top: 10px;";
4354
+ const actions = document.createElement("div");
4355
+ actions.style.cssText = "display: flex; gap: 6px;";
4356
+ const prevBtn = document.createElement("button");
4357
+ prevBtn.type = "button";
4358
+ prevBtn.textContent = "\u2190 Back";
4359
+ prevBtn.disabled = runtime.index === 0;
4360
+ prevBtn.style.cssText = `
4361
+ border: 1px solid rgba(37, 99, 235, 0.3);
4362
+ background: ${runtime.index === 0 ? "rgba(37, 99, 235, 0.08)" : "rgba(37, 99, 235, 0.1)"};
4363
+ color: #2563eb;
4364
+ border-radius: 6px;
4365
+ padding: 8px 12px;
4366
+ font-size: 12px;
4367
+ font-weight: 500;
4368
+ cursor: ${runtime.index === 0 ? "not-allowed" : "pointer"};
4369
+ `;
4370
+ prevBtn.onclick = () => {
4371
+ if (runtime.index === 0) {
4372
+ return;
4373
+ }
4374
+ runtime.index -= 1;
4375
+ syncParallelTourProgress(runtime.tourId, runtime.userId, runtime.index, false);
4376
+ renderParallelTourStep(runtime);
4377
+ };
4378
+ actions.appendChild(prevBtn);
4379
+ const nextBtn = document.createElement("button");
4380
+ nextBtn.type = "button";
4381
+ const isLastStep = runtime.index >= runtime.steps.length - 1;
4382
+ nextBtn.textContent = isLastStep ? "Finish \u2713" : "Next \u2192";
4383
+ nextBtn.style.cssText = `
4384
+ border: none;
4385
+ background: linear-gradient(135deg, rgba(37, 99, 235, 0.9) 0%, rgba(37, 99, 235, 0.8) 100%);
4386
+ color: #ffffff;
4387
+ border-radius: 6px;
4388
+ padding: 8px 12px;
4389
+ font-size: 12px;
4390
+ font-weight: 600;
4391
+ cursor: pointer;
4392
+ `;
4393
+ nextBtn.onclick = () => {
4394
+ advanceParallelTour(runtime);
4395
+ };
4396
+ actions.appendChild(nextBtn);
4397
+ const skipBtn = document.createElement("button");
4398
+ skipBtn.type = "button";
4399
+ skipBtn.textContent = "Skip";
4400
+ skipBtn.style.cssText = `
4401
+ border: 1px solid rgba(168, 85, 247, 0.3);
4402
+ background: rgba(168, 85, 247, 0.1);
4403
+ color: #a855f7;
4404
+ border-radius: 6px;
4405
+ padding: 8px 12px;
4406
+ font-size: 12px;
4407
+ font-weight: 500;
4408
+ cursor: pointer;
4409
+ `;
4410
+ skipBtn.onclick = () => {
4411
+ syncParallelTourProgress(runtime.tourId, runtime.userId, runtime.index, true);
4412
+ clearParallelHighlight(runtime);
4413
+ removeParallelTourUi(runtime.tourId);
4414
+ if (window.__riviaParallelTourRuntimes) {
4415
+ delete window.__riviaParallelTourRuntimes[runtime.tourId];
4416
+ }
4417
+ };
4418
+ actions.appendChild(skipBtn);
4419
+ footer.appendChild(actions);
4420
+ tooltip.appendChild(footer);
4421
+ const stepIndicator = document.createElement("div");
4422
+ stepIndicator.style.cssText = `
4423
+ position: absolute;
4424
+ top: 8px;
4425
+ right: 12px;
4426
+ font-size: 11px;
4427
+ color: rgba(37, 99, 235, 0.6);
4428
+ font-weight: 500;
4429
+ `;
4430
+ stepIndicator.textContent = `Step ${runtime.index + 1} of ${runtime.steps.length}`;
4431
+ tooltip.appendChild(stepIndicator);
4432
+ document.body.appendChild(tooltip);
4433
+ positionParallelTooltip(anchor, tooltip, runtime.slotIndex || 0);
4434
+ }
4435
+ async function fetchTourStepsForParallel(tourId) {
4436
+ const res = await fetch(`https://demoapi.rivia.ai/tours2/${tourId}`, {
4437
+ method: "GET",
4438
+ headers: { "Content-Type": "application/json" }
4439
+ });
4440
+ if (!res.ok) {
4441
+ return [];
4442
+ }
4443
+ const data = await res.json();
4444
+ return Array.isArray(data?.tour?.steps) ? data.tour.steps : [];
4445
+ }
4446
+ async function startTourInParallelMode(tourDef, userId, slotIndex = 0) {
4447
+ if (typeof window === "undefined") {
4448
+ return;
4449
+ }
4450
+ const tourId = tourDef?.tour_id;
4451
+ if (!tourId) {
4452
+ return;
4453
+ }
4454
+ if (!window.__riviaParallelTourRuntimes) {
4455
+ window.__riviaParallelTourRuntimes = {};
4456
+ }
4457
+ if (window.__riviaParallelTourRuntimes[tourId]) {
4458
+ renderParallelTourStep(window.__riviaParallelTourRuntimes[tourId]);
4459
+ return;
4460
+ }
4461
+ const steps = await fetchTourStepsForParallel(tourId);
4462
+ if (!steps.length) {
4463
+ return;
4464
+ }
4465
+ const runtime = {
4466
+ tourId,
4467
+ title: tourDef?.title || `Tour ${tourId}`,
4468
+ steps,
4469
+ index: 0,
4470
+ userId,
4471
+ slotIndex,
4472
+ highlightedElement: null,
4473
+ highlightSnapshot: null
4474
+ };
4475
+ window.__riviaParallelTourRuntimes[tourId] = runtime;
4476
+ syncParallelTourProgress(tourId, userId, 0, false);
4477
+ renderParallelTourStep(runtime);
4478
+ }
3753
4479
  async function Tours(workspace_id, obj) {
3754
4480
  if (!sessionStorage.getItem("rivia_tour_state")) {
3755
- window.userId = obj.userid;
3756
- let userId = obj.userid;
4481
+ const currentUserId = obj?.userid || "Guest_User";
4482
+ window.userId = currentUserId;
4483
+ window.current_username = currentUserId;
4484
+ window.user_var = currentUserId;
4485
+ sessionStorage.setItem("current_username", currentUserId);
4486
+ sessionStorage.setItem("user_var", currentUserId);
4487
+ sessionStorage.setItem("rivia_user_name", currentUserId);
4488
+ let userId = currentUserId;
3757
4489
  window.sign_up_at = obj.sign_up_at;
3758
4490
  window.role = obj.role;
3759
4491
  window.email = obj.email;
@@ -3799,49 +4531,92 @@ async function Tours(workspace_id, obj) {
3799
4531
  const tours = data.tour || [];
3800
4532
  if (!Array.isArray(tours) || tours.length === 0) return;
3801
4533
  const currentPath = window.location.href;
3802
- const matchedTour = tours.find((chk) => {
3803
- const routes = chk?.url;
4534
+ console.log("userid", obj.userid);
4535
+ const context = buildContext2(obj);
4536
+ const eligibleTours = tours.filter((tourDef) => {
4537
+ const routes = tourDef?.url;
3804
4538
  console.log("Checking tour:", window.location.href, "with routes:", routes);
3805
- if (!chk?.publish && !chk?.published)
4539
+ if (!tourDef?.publish && !tourDef?.published) {
3806
4540
  return false;
3807
- return doesRouteMatch2(routes, currentPath);
4541
+ }
4542
+ if (!doesRouteMatch2(routes, currentPath)) {
4543
+ return false;
4544
+ }
4545
+ const rules = tourDef?.targeting_data?.custom_rules || [];
4546
+ return evaluateRules2(rules, context);
3808
4547
  });
3809
- if (!matchedTour) {
4548
+ if (!eligibleTours.length) {
3810
4549
  console.log("No tour applicable for this route");
3811
4550
  return;
3812
4551
  }
3813
- console.log("userid", obj.userid);
3814
- console.log("matched ch", matchedTour);
3815
- const rules = matchedTour?.targeting_data?.custom_rules || [];
3816
- console.log("rules", rules);
3817
- const context = buildContext2(obj);
3818
- const shouldShow = evaluateRules2(rules, context);
3819
- if (!shouldShow) {
3820
- console.log("User does not meet targeting rules for this tour");
3821
- return;
3822
- }
3823
- const {
3824
- tour_id,
3825
- title = "Untitled Tour",
3826
- subtitle = "Describe the purpose of this tour...",
3827
- items = [],
3828
- completion = 0,
3829
- branding_data: cssConfig = {},
3830
- targeting_data: targetingData = {},
3831
- customCSS = ""
3832
- } = matchedTour;
3833
- const fullData = {
3834
- tour: matchedTour,
3835
- cssConfig,
3836
- targetingData,
3837
- customCSS
4552
+ const queuePendingTour = (pendingTour) => {
4553
+ if (!Array.isArray(window.__riviaPendingTours)) {
4554
+ window.__riviaPendingTours = [];
4555
+ }
4556
+ window.__riviaPendingTours = window.__riviaPendingTours.filter(
4557
+ (tour) => tour.tourId !== pendingTour.tourId
4558
+ );
4559
+ window.__riviaPendingTours.push(pendingTour);
4560
+ window.__riviaStartPendingTourByEvent = async (message) => {
4561
+ const incomingEvent = typeof message === "string" ? message.trim().toLowerCase() : "";
4562
+ if (!incomingEvent || !Array.isArray(window.__riviaPendingTours) || !window.__riviaPendingTours.length) {
4563
+ return false;
4564
+ }
4565
+ let startedAnyTour = false;
4566
+ const remainingTours = [];
4567
+ for (const pending of window.__riviaPendingTours) {
4568
+ if (pending.eventName === incomingEvent) {
4569
+ await pending.start();
4570
+ startedAnyTour = true;
4571
+ } else {
4572
+ remainingTours.push(pending);
4573
+ }
4574
+ }
4575
+ window.__riviaPendingTours = remainingTours;
4576
+ return startedAnyTour;
4577
+ };
3838
4578
  };
3839
- RIVIA_TOUR.loadTips(tour_id, userId).then(() => {
3840
- try {
3841
- RIVIA_TOUR.playTour();
3842
- } catch (err) {
4579
+ const startTourDefinition = async (tourDef, forceStart = false, useParallelMode = false, slotIndex = 0) => {
4580
+ const tourId = tourDef?.tour_id;
4581
+ if (!tourId) {
4582
+ return;
3843
4583
  }
3844
- });
4584
+ const startMatchedTour = async () => {
4585
+ if (useParallelMode) {
4586
+ await startTourInParallelMode(tourDef, userId, slotIndex);
4587
+ return;
4588
+ }
4589
+ try {
4590
+ if (window.__riviaStartedTourId === tourId) {
4591
+ return;
4592
+ }
4593
+ await RIVIA_TOUR.loadTips(tourId, userId);
4594
+ RIVIA_TOUR.playTour();
4595
+ window.__riviaStartedTourId = tourId;
4596
+ } catch {
4597
+ }
4598
+ };
4599
+ const rawEventName = tourDef?.event_name;
4600
+ const normalizedEventName = typeof rawEventName === "string" ? rawEventName.trim().toLowerCase() : "";
4601
+ const shouldStartInstantly = forceStart || !normalizedEventName || normalizedEventName === "url";
4602
+ if (shouldStartInstantly) {
4603
+ await startMatchedTour();
4604
+ return;
4605
+ }
4606
+ queuePendingTour({
4607
+ eventName: normalizedEventName,
4608
+ tourId,
4609
+ start: startMatchedTour
4610
+ });
4611
+ };
4612
+ if (eligibleTours.length > 1) {
4613
+ for (let index = 0; index < eligibleTours.length; index += 1) {
4614
+ const tourDef = eligibleTours[index];
4615
+ await startTourDefinition(tourDef, false, true, index);
4616
+ }
4617
+ return;
4618
+ }
4619
+ await startTourDefinition(eligibleTours[0], false);
3845
4620
  } catch (err) {
3846
4621
  console.warn("Tour error:", err.message);
3847
4622
  throw err;
@@ -3849,17 +4624,79 @@ async function Tours(workspace_id, obj) {
3849
4624
  }
3850
4625
  }
3851
4626
  var rivia_tour_default = Tours;
4627
+ function resolveCurrentUsername() {
4628
+ if (typeof window === "undefined") {
4629
+ return "Guest_User";
4630
+ }
4631
+ return window.user_var || window.current_username || window.sessionStorage.getItem("rivia_user_name") || window.sessionStorage.getItem("current_username") || window.sessionStorage.getItem("user_var") || "Guest_User";
4632
+ }
4633
+ async function restartTourById(tourId, userName = resolveCurrentUsername()) {
4634
+ if (!tourId) {
4635
+ throw new Error("Tour ID is required to restart a tour.");
4636
+ }
4637
+ const currentUserName = typeof userName === "string" && userName.trim() ? userName.trim() : resolveCurrentUsername();
4638
+ const backendUrl = `https://demoapi.rivia.ai/tours_clients/${tourId}`;
4639
+ const response = await fetch(backendUrl, {
4640
+ method: "POST",
4641
+ headers: { "Content-Type": "application/json" },
4642
+ credentials: "include",
4643
+ body: JSON.stringify({
4644
+ name: currentUserName,
4645
+ tourIndex: 0,
4646
+ is_completed: false
4647
+ }),
4648
+ keepalive: true
4649
+ });
4650
+ if (!response.ok) {
4651
+ throw new Error(`Failed to restart tour ${tourId}: ${response.status}`);
4652
+ }
4653
+ if (typeof window !== "undefined") {
4654
+ window.sessionStorage.removeItem("rivia_tour_state");
4655
+ window.__riviaStartedTourId = null;
4656
+ window.__riviaPendingTour = null;
4657
+ window.location.reload();
4658
+ }
4659
+ return response;
4660
+ }
4661
+ if (typeof window !== "undefined") {
4662
+ window.__riviaRestartTourById = restartTourById;
4663
+ }
4664
+ if (typeof document !== "undefined" && typeof window !== "undefined") {
4665
+ if (!window.__riviaRestartTourListenerAttached) {
4666
+ window.__riviaRestartTourListenerAttached = true;
4667
+ document.addEventListener("click", async (event) => {
4668
+ const target = event.target instanceof Element ? event.target.closest("[rivia-restart-tour]") : null;
4669
+ if (!target) {
4670
+ return;
4671
+ }
4672
+ const tourId = target.getAttribute("rivia-restart-tour");
4673
+ if (!tourId) {
4674
+ return;
4675
+ }
4676
+ try {
4677
+ await restartTourById(tourId, resolveCurrentUsername());
4678
+ } catch (error) {
4679
+ console.error("Tour restart failed:", error);
4680
+ }
4681
+ });
4682
+ }
4683
+ }
3852
4684
 
3853
4685
  // src/utils/banner.js
3854
4686
  function injectBanner(banner = {}, opts = {}, userId, bannerId) {
3855
4687
  try {
3856
- let uploadVisitedPagesInBackground2 = function(bannerId2) {
3857
- console.log("Uploading visited pages in background for banner ID: and user_var:", userId);
4688
+ let uploadVisitedPagesInBackground2 = function(currentBannerId) {
4689
+ console.log("Uploading visited pages in background", { bannerId: currentBannerId, userId });
3858
4690
  let user_var2 = userId;
3859
- const backendUrl22 = `https://demoapi.rivia.ai/banners_clients/${bannerId2}`;
4691
+ if (!currentBannerId) {
4692
+ console.error("\u26A0\uFE0F Background upload skipped: missing banner id");
4693
+ return;
4694
+ }
4695
+ const backendUrl22 = `https://demoapi.rivia.ai/banners_clients/${currentBannerId}`;
3860
4696
  try {
3861
4697
  const payload = {
3862
4698
  name: user_var2,
4699
+ user_id: user_var2,
3863
4700
  is_completed: true
3864
4701
  };
3865
4702
  fetch(backendUrl22, {
@@ -3872,15 +4709,19 @@ function injectBanner(banner = {}, opts = {}, userId, bannerId) {
3872
4709
  if (res.status === 404) {
3873
4710
  throw new Error("Invalid banner id");
3874
4711
  }
3875
- throw new Error(`Upload failed: ${res.status}`);
4712
+ if (!res.ok) {
4713
+ throw new Error(`Upload failed: ${res.status}`);
4714
+ }
4715
+ return res;
3876
4716
  }).catch((err) => {
3877
- console.error("\u26A0\uFE0F Background PUT upload failed:", err);
4717
+ console.error("\u26A0\uFE0F Background POST upload failed:", err);
3878
4718
  });
3879
4719
  } catch (err) {
3880
4720
  console.error("\u274C Error preparing background upload:", err);
3881
4721
  }
3882
4722
  };
3883
4723
  var uploadVisitedPagesInBackground = uploadVisitedPagesInBackground2;
4724
+ const resolvedBannerId = bannerId || banner?.banner_id || banner?.id || banner?._id;
3884
4725
  const prefix = opts.idPrefix || "rivia";
3885
4726
  const id = `${prefix}-banner`;
3886
4727
  const old = document.getElementById(id);
@@ -3971,7 +4812,7 @@ function injectBanner(banner = {}, opts = {}, userId, bannerId) {
3971
4812
  } else {
3972
4813
  a.onclick = () => {
3973
4814
  container.remove();
3974
- uploadVisitedPagesInBackground2(bannerId);
4815
+ uploadVisitedPagesInBackground2(resolvedBannerId);
3975
4816
  };
3976
4817
  }
3977
4818
  if (btn.border) {
@@ -4002,7 +4843,7 @@ function injectBanner(banner = {}, opts = {}, userId, bannerId) {
4002
4843
  closeBtn.style.marginLeft = "auto";
4003
4844
  closeBtn.onclick = () => {
4004
4845
  container.remove();
4005
- uploadVisitedPagesInBackground2(bannerId);
4846
+ uploadVisitedPagesInBackground2(resolvedBannerId);
4006
4847
  };
4007
4848
  box.appendChild(closeBtn);
4008
4849
  }
@@ -4020,7 +4861,7 @@ function injectBanner(banner = {}, opts = {}, userId, bannerId) {
4020
4861
  closeBtn.style.color = banner.background.text_color || "#fff";
4021
4862
  closeBtn.onclick = () => {
4022
4863
  container.remove();
4023
- uploadVisitedPagesInBackground2(bannerId);
4864
+ uploadVisitedPagesInBackground2(resolvedBannerId);
4024
4865
  };
4025
4866
  box.appendChild(closeBtn);
4026
4867
  }
@@ -4043,7 +4884,7 @@ function injectBanner(banner = {}, opts = {}, userId, bannerId) {
4043
4884
  closeBtn.style.marginLeft = "auto";
4044
4885
  closeBtn.onclick = () => {
4045
4886
  container.remove();
4046
- uploadVisitedPagesInBackground2(bannerId);
4887
+ uploadVisitedPagesInBackground2(resolvedBannerId);
4047
4888
  };
4048
4889
  box.appendChild(closeBtn);
4049
4890
  }
@@ -4145,7 +4986,29 @@ async function Banner(workspace_id, obj) {
4145
4986
  window.email = obj.email;
4146
4987
  console.log("");
4147
4988
  try {
4148
- let doesRouteMatch2 = function(routes) {
4989
+ let isBannerCompletedForUser2 = function(chk, userId) {
4990
+ if (!chk || !userId) return false;
4991
+ if (chk.user_id === userId && chk.is_completed === true) {
4992
+ return true;
4993
+ }
4994
+ const userData = chk.user_data;
4995
+ if (!userData) return false;
4996
+ if (Array.isArray(userData)) {
4997
+ return userData.some(
4998
+ (entry) => entry && entry.is_completed === true && (entry.user_id === userId || entry.userid === userId || entry.name === userId || entry.id === userId)
4999
+ );
5000
+ }
5001
+ if (typeof userData === "object") {
5002
+ const direct = userData[userId];
5003
+ if (direct && direct.is_completed === true) {
5004
+ return true;
5005
+ }
5006
+ return Object.values(userData).some(
5007
+ (entry) => entry && typeof entry === "object" && entry.is_completed === true && (entry.user_id === userId || entry.userid === userId || entry.name === userId || entry.id === userId)
5008
+ );
5009
+ }
5010
+ return false;
5011
+ }, doesRouteMatch2 = function(routes) {
4149
5012
  if (!Array.isArray(routes)) return true;
4150
5013
  const currentPath2 = window.location.pathname.toLowerCase();
4151
5014
  console.log("Current Path:", currentPath2);
@@ -4174,7 +5037,7 @@ async function Banner(workspace_id, obj) {
4174
5037
  last_name: obj2.last_name
4175
5038
  };
4176
5039
  };
4177
- var doesRouteMatch = doesRouteMatch2, escapeRegex = escapeRegex2, buildContext = buildContext2;
5040
+ var isBannerCompletedForUser = isBannerCompletedForUser2, doesRouteMatch = doesRouteMatch2, escapeRegex = escapeRegex2, buildContext = buildContext2;
4178
5041
  const res = await fetch(
4179
5042
  `https://demoapi.rivia.ai/banner_by_workspace2/${workspace_id}`,
4180
5043
  {
@@ -4192,6 +5055,9 @@ async function Banner(workspace_id, obj) {
4192
5055
  const currentPath = window.location.pathname;
4193
5056
  const matchedbanner = banners.find((chk) => {
4194
5057
  const routes = chk?.targeting_data?.routes;
5058
+ if (isBannerCompletedForUser2(chk, obj.userid)) {
5059
+ return false;
5060
+ }
4195
5061
  if (!chk?.publish)
4196
5062
  return false;
4197
5063
  if (!chk?.targeting_data?.display)
@@ -4262,57 +5128,152 @@ var banner_default = Banner;
4262
5128
 
4263
5129
  // src/utils/trigger-event.js
4264
5130
  var triggerEvent = async (message) => {
5131
+ const normalizedMessage = typeof message === "string" ? message.trim().toLowerCase() : "";
5132
+ if (typeof window.__riviaStartPendingTourByEvent === "function") {
5133
+ try {
5134
+ await window.__riviaStartPendingTourByEvent(message);
5135
+ } catch (tourErr) {
5136
+ console.warn("Tour trigger event handling failed:", tourErr);
5137
+ }
5138
+ }
5139
+ const renderFallbackCompletionCard = (config = {}) => {
5140
+ const completionConfig = window.completionCardConfig || {};
5141
+ const mergedConfig = { ...completionConfig, ...config };
5142
+ const {
5143
+ topTitle = "Checklist Complete",
5144
+ congratulatory_message = "\u{1F389}Congratulations! You have completed the checklist.",
5145
+ button_text = "Get Started",
5146
+ redirect_url = "/dashboard",
5147
+ button_present = false,
5148
+ cssConfig = {}
5149
+ } = mergedConfig;
5150
+ const shouldShowGoButton = button_present === true || button_present === "true" || button_present === 1 || button_present === "1";
5151
+ const completionHeight = cssConfig.completion_height || "auto";
5152
+ const completionWidth = cssConfig.completion_width || "300px";
5153
+ const completionBackground = cssConfig.completion_background_color || "#ffffff";
5154
+ const completionTextColor = cssConfig.completion_text_color || (completionBackground === "#ffffff" ? cssConfig.textColor || "#111827" : "#100d0d");
5155
+ const completionFontSize = cssConfig.completion_font_size || cssConfig.fontSize || "16px";
5156
+ const completionSubtitleColor = cssConfig.completion_subtitle_color || cssConfig.subtitleColor || completionTextColor;
5157
+ const completionTitleFontFamily = cssConfig.completion_title_font_family || cssConfig.fontFamily || "Arial, sans-serif";
5158
+ const completionTitleFontSize = cssConfig.completion_title_font_size || "18px";
5159
+ const completionButtonBgColor = cssConfig.completion_button_bg_color || cssConfig.button_background_color || "#ffffff";
5160
+ const completionButtonTextColor = cssConfig.completion_button_text_color || cssConfig.button_text_color || "#4CAF50";
5161
+ const completionButtonFontFamily = cssConfig.completion_button_font_family || cssConfig.fontFamily || "Arial, sans-serif";
5162
+ const completionButtonFontSize = cssConfig.completion_button_font_size || cssConfig.button_font_size || "14px";
5163
+ const completionDismissBackgroundColor = cssConfig.completion_dismiss_background_color || "#f44336";
5164
+ const completionDismissTextColor = cssConfig.completion_dismiss_text_color || "#ffffff";
5165
+ const existingCard = document.getElementById("route-label");
5166
+ if (existingCard) existingCard.remove();
5167
+ const label = document.createElement("div");
5168
+ label.id = "route-label";
5169
+ Object.assign(label.style, {
5170
+ position: "fixed",
5171
+ top: "50%",
5172
+ left: "50%",
5173
+ transform: "translate(-50%, -50%)",
5174
+ alignItems: "center",
5175
+ width: completionWidth,
5176
+ height: completionHeight,
5177
+ backgroundColor: completionBackground,
5178
+ color: completionTextColor,
5179
+ padding: "15px",
5180
+ borderRadius: "12px",
5181
+ boxShadow: "0 6px 12px rgba(0,0,0,0.2)",
5182
+ fontSize: completionFontSize,
5183
+ fontFamily: cssConfig.fontFamily || "Arial, sans-serif",
5184
+ zIndex: 9999,
5185
+ display: "flex",
5186
+ flexDirection: "column",
5187
+ gap: "10px"
5188
+ });
5189
+ const message2 = document.createElement("div");
5190
+ message2.innerText = congratulatory_message;
5191
+ Object.assign(message2.style, {
5192
+ color: completionSubtitleColor,
5193
+ fontSize: completionFontSize,
5194
+ lineHeight: "1.5",
5195
+ textAlign: "center"
5196
+ });
5197
+ const btnContainer = document.createElement("div");
5198
+ Object.assign(btnContainer.style, {
5199
+ display: "flex",
5200
+ justifyContent: shouldShowGoButton ? "space-between" : "flex-end",
5201
+ gap: "10px",
5202
+ marginTop: "4px"
5203
+ });
5204
+ if (shouldShowGoButton) {
5205
+ const goBtn = document.createElement("button");
5206
+ goBtn.innerText = button_text;
5207
+ Object.assign(goBtn.style, {
5208
+ padding: "8px 12px",
5209
+ border: "none",
5210
+ borderRadius: "6px",
5211
+ cursor: "pointer",
5212
+ backgroundColor: completionButtonBgColor,
5213
+ color: completionButtonTextColor,
5214
+ fontFamily: completionButtonFontFamily,
5215
+ fontSize: completionButtonFontSize,
5216
+ fontWeight: "bold"
5217
+ });
5218
+ goBtn.onclick = () => {
5219
+ sessionStorage.setItem("CompletedAll", "false");
5220
+ window.open(completionConfig.redirect_url || "/dashboard", "_blank");
5221
+ };
5222
+ btnContainer.appendChild(goBtn);
5223
+ }
5224
+ const closeBtn = document.createElement("button");
5225
+ closeBtn.innerText = "Dismiss";
5226
+ Object.assign(closeBtn.style, {
5227
+ padding: "8px 12px",
5228
+ border: "none",
5229
+ borderRadius: "6px",
5230
+ cursor: "pointer",
5231
+ backgroundColor: completionDismissBackgroundColor,
5232
+ color: completionDismissTextColor,
5233
+ fontFamily: completionButtonFontFamily,
5234
+ fontSize: completionButtonFontSize
5235
+ });
5236
+ closeBtn.onclick = () => {
5237
+ label.style.opacity = 0;
5238
+ sessionStorage.setItem("CompletedAll", "false");
5239
+ setTimeout(() => label.remove(), 500);
5240
+ };
5241
+ if (congratulatory_message) {
5242
+ label.appendChild(message2);
5243
+ }
5244
+ btnContainer.appendChild(closeBtn);
5245
+ label.appendChild(btnContainer);
5246
+ document.body.appendChild(label);
5247
+ };
4265
5248
  try {
4266
5249
  let checklist_id = window.checklist_id;
4267
5250
  let user_name = window.user_var;
4268
5251
  for (let item of window.items) {
5252
+ const itemEventName = typeof item.event_name === "string" ? item.event_name.trim().toLowerCase() : "";
4269
5253
  console.log("Comparing:", item.event_name, "with", message);
4270
- if (item.event_name === message) {
5254
+ if (itemEventName && itemEventName === normalizedMessage) {
4271
5255
  let clean_item = item.url.startsWith("/") ? item.url.slice(1) : item.url;
4272
5256
  if (!window.storedVisited.includes(item.event_name)) {
4273
5257
  window.storedVisited.push(item.event_name);
4274
5258
  }
4275
5259
  sessionStorage.setItem("onboardingVisited", JSON.stringify(window.storedVisited));
4276
- window.updateProgress(window.storedVisited);
4277
- window.updateProgress2(window.storedVisited);
5260
+ window.updateProgress(window.storedVisited.length);
5261
+ window.updateProgress2(window.storedVisited.length);
4278
5262
  window.updateUIFromVisited();
4279
5263
  window.uploadVisitedPagesInBackground(window.storedVisited);
4280
- if (storedVisited.length === window.items.length) {
5264
+ if (window.storedVisited.length >= window.items.length) {
5265
+ sessionStorage.setItem("CompletedAll", "true");
4281
5266
  if (window.showBtn && window.showBtn.parentNode) {
4282
5267
  window.showBtn.remove();
4283
5268
  }
4284
5269
  if (window.label && window.label.parentNode) {
4285
5270
  window.label.remove();
4286
5271
  }
4287
- (() => {
4288
- const ll2 = document.createElement("div");
4289
- ll2.id = "route-labe";
4290
- ll2.innerText = "\u{1F389} Congrats! You've completed all items!";
4291
- Object.assign(ll2.style, {
4292
- position: "fixed",
4293
- bottom: "20px",
4294
- left: "20px",
4295
- backgroundColor: "#4CAF50",
4296
- color: "white",
4297
- padding: "10px 20px",
4298
- borderRadius: "10px",
4299
- boxShadow: "0 4px 6px rgba(0,0,0,0.2)",
4300
- fontSize: "16px",
4301
- fontWeight: "bold",
4302
- zIndex: 9999,
4303
- opacity: 0,
4304
- transition: "opacity 0.5s ease"
4305
- });
4306
- document.body.appendChild(ll2);
4307
- console.log("ll2");
4308
- requestAnimationFrame(() => {
4309
- ll2.style.opacity = 1;
4310
- });
4311
- setTimeout(() => {
4312
- ll2.style.opacity = 0;
4313
- setTimeout(() => ll2.remove(), 500);
4314
- }, 3e3);
4315
- })();
5272
+ if (typeof window.renderCompletionCard === "function") {
5273
+ window.renderCompletionCard(window.completionCardConfig || {});
5274
+ } else {
5275
+ renderFallbackCompletionCard(window.completionCardConfig || {});
5276
+ }
4316
5277
  }
4317
5278
  }
4318
5279
  }
@@ -4646,19 +5607,20 @@ var ProductManagement = /* @__PURE__ */ function() {
4646
5607
  if (i > 3) return;
4647
5608
  const div = document.createElement("div");
4648
5609
  div.className = "pm-lite-item";
4649
- const date = it.created_at ? new Date(it.created_at).toLocaleDateString() : "";
4650
5610
  div.style.cursor = "pointer";
4651
5611
  div.addEventListener("click", () => {
4652
5612
  const baseUrl = `https://${state.config.workspace}.rivia.ai/users/changelog`;
4653
5613
  const params = new URLSearchParams({
4654
5614
  changelogId: it.changelog_id || it.id || "",
4655
- // adjust based on your API
4656
5615
  pm_user_id: state.pmUserId || ""
4657
5616
  });
4658
- console.log("it.id", it.id);
4659
5617
  const finalUrl = `${baseUrl}?${params.toString()}`;
4660
5618
  window.open(finalUrl, "_blank");
4661
5619
  });
5620
+ const topRow = document.createElement("div");
5621
+ topRow.style.display = "flex";
5622
+ topRow.style.alignItems = "center";
5623
+ topRow.style.width = "100%";
4662
5624
  if (it.label) {
4663
5625
  const tag = document.createElement("span");
4664
5626
  tag.className = "pm-lite-tags";
@@ -4671,8 +5633,18 @@ var ProductManagement = /* @__PURE__ */ function() {
4671
5633
  tag.style.backgroundColor = "rgb(220, 252, 231)";
4672
5634
  tag.style.color = "rgb(22, 101, 52)";
4673
5635
  tag.style.border = "1px solid rgb(187, 247, 208)";
4674
- div.appendChild(tag);
5636
+ topRow.appendChild(tag);
5637
+ }
5638
+ if (it.publish_time) {
5639
+ const dateEl = document.createElement("span");
5640
+ dateEl.innerText = new Date(it.publish_time).toLocaleDateString();
5641
+ dateEl.style.fontSize = "11px";
5642
+ dateEl.style.color = "#777";
5643
+ dateEl.style.marginLeft = "auto";
5644
+ dateEl.style.fontFamily = "Verdana, sans-serif";
5645
+ topRow.appendChild(dateEl);
4675
5646
  }
5647
+ div.appendChild(topRow);
4676
5648
  const header = document.createElement("div");
4677
5649
  header.className = "pm-lite-item-header";
4678
5650
  header.style.fontWeight = "600";