@followgate/js 0.9.5 → 0.10.0

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/dist/index.d.mts CHANGED
@@ -105,8 +105,9 @@ declare class FollowGateClient {
105
105
  show(): Promise<void>;
106
106
  /**
107
107
  * Hide the modal
108
+ * @param cancelled - If true, redirect to cancelUrl if configured
108
109
  */
109
- hide(): void;
110
+ hide(cancelled?: boolean): void;
110
111
  private injectStyles;
111
112
  private createModal;
112
113
  private getContentElement;
@@ -181,6 +182,10 @@ declare class FollowGateClient {
181
182
  private buildLinkedInUrl;
182
183
  private trackEvent;
183
184
  private emit;
185
+ /**
186
+ * Escape HTML to prevent XSS
187
+ */
188
+ private escapeHtml;
184
189
  }
185
190
  declare const FollowGate: FollowGateClient;
186
191
 
package/dist/index.d.ts CHANGED
@@ -105,8 +105,9 @@ declare class FollowGateClient {
105
105
  show(): Promise<void>;
106
106
  /**
107
107
  * Hide the modal
108
+ * @param cancelled - If true, redirect to cancelUrl if configured
108
109
  */
109
- hide(): void;
110
+ hide(cancelled?: boolean): void;
110
111
  private injectStyles;
111
112
  private createModal;
112
113
  private getContentElement;
@@ -181,6 +182,10 @@ declare class FollowGateClient {
181
182
  private buildLinkedInUrl;
182
183
  private trackEvent;
183
184
  private emit;
185
+ /**
186
+ * Escape HTML to prevent XSS
187
+ */
188
+ private escapeHtml;
184
189
  }
185
190
  declare const FollowGate: FollowGateClient;
186
191
 
package/dist/index.js CHANGED
@@ -585,8 +585,9 @@ var FollowGateClient = class {
585
585
  }
586
586
  /**
587
587
  * Hide the modal
588
+ * @param cancelled - If true, redirect to cancelUrl if configured
588
589
  */
589
- hide() {
590
+ hide(cancelled = false) {
590
591
  if (this.modalElement) {
591
592
  this.modalElement.classList.remove("fg-visible");
592
593
  setTimeout(() => {
@@ -594,6 +595,9 @@ var FollowGateClient = class {
594
595
  this.modalElement = null;
595
596
  }, 300);
596
597
  }
598
+ if (cancelled && this.serverConfig?.cancelUrl) {
599
+ window.location.href = this.serverConfig.cancelUrl;
600
+ }
597
601
  }
598
602
  injectStyles() {
599
603
  if (this.stylesInjected) return;
@@ -643,9 +647,11 @@ var FollowGateClient = class {
643
647
  renderUsernameStep() {
644
648
  const content = this.getContentElement();
645
649
  if (!content) return;
646
- const handle = this.config?.twitter?.handle;
650
+ const handle = this.serverConfig?.targetHandle || this.config?.twitter?.handle;
647
651
  const hasRepost = !!this.config?.twitter?.tweetId;
648
652
  const allowSkip = this.serverConfig?.allowSkip ?? false;
653
+ const welcomeTitle = this.serverConfig?.welcomeTitle || "Unlock Free Access";
654
+ const welcomeMessage = this.serverConfig?.welcomeMessage || "Enter your X username to get started";
649
655
  let explanationText = handle ? `Complete a quick follow${hasRepost ? " & repost" : ""} on X for @${handle} to unlock access.` : `Complete a quick social action to unlock access.`;
650
656
  if (allowSkip) {
651
657
  explanationText += ` You can skip if you prefer, but it helps support the developer.`;
@@ -654,8 +660,8 @@ var FollowGateClient = class {
654
660
  <div class="fg-icon-box">
655
661
  ${ICONS.x}
656
662
  </div>
657
- <h2 class="fg-title">Unlock Free Access</h2>
658
- <p class="fg-subtitle">Enter your X username to get started</p>
663
+ <h2 class="fg-title">${this.escapeHtml(welcomeTitle)}</h2>
664
+ <p class="fg-subtitle">${this.escapeHtml(welcomeMessage)}</p>
659
665
  <div class="fg-info-box" style="margin-bottom: 20px;">
660
666
  <p>${explanationText}</p>
661
667
  </div>
@@ -907,8 +913,11 @@ var FollowGateClient = class {
907
913
  const content = this.getContentElement();
908
914
  if (!content) return;
909
915
  const username = this.currentUser?.username;
916
+ const successTitle = this.serverConfig?.successTitle || "Almost done!";
917
+ const successMessage = this.serverConfig?.successMessage || null;
910
918
  content.innerHTML = `
911
- <h2 class="fg-title">Almost done!</h2>
919
+ <h2 class="fg-title">${this.escapeHtml(successTitle)}</h2>
920
+ ${successMessage ? `<p class="fg-subtitle" style="margin-bottom: 16px;">${this.escapeHtml(successMessage)}</p>` : ""}
912
921
  <div class="fg-verify-box">
913
922
  <div class="fg-verify-box-left">
914
923
  <div class="fg-verify-spinner"></div>
@@ -971,6 +980,9 @@ var FollowGateClient = class {
971
980
  await this.unlock();
972
981
  this.hide();
973
982
  this.config?.onComplete?.();
983
+ if (this.serverConfig?.successUrl) {
984
+ window.location.href = this.serverConfig.successUrl;
985
+ }
974
986
  }
975
987
  renderStepIndicator(currentStep) {
976
988
  return `
@@ -1390,6 +1402,14 @@ var FollowGateClient = class {
1390
1402
  emit(event, data) {
1391
1403
  this.listeners.get(event)?.forEach((callback) => callback(data));
1392
1404
  }
1405
+ /**
1406
+ * Escape HTML to prevent XSS
1407
+ */
1408
+ escapeHtml(text) {
1409
+ const div = document.createElement("div");
1410
+ div.textContent = text;
1411
+ return div.innerHTML;
1412
+ }
1393
1413
  };
1394
1414
  var FollowGate = new FollowGateClient();
1395
1415
  // Annotate the CommonJS export names for ESM import in node:
package/dist/index.mjs CHANGED
@@ -559,8 +559,9 @@ var FollowGateClient = class {
559
559
  }
560
560
  /**
561
561
  * Hide the modal
562
+ * @param cancelled - If true, redirect to cancelUrl if configured
562
563
  */
563
- hide() {
564
+ hide(cancelled = false) {
564
565
  if (this.modalElement) {
565
566
  this.modalElement.classList.remove("fg-visible");
566
567
  setTimeout(() => {
@@ -568,6 +569,9 @@ var FollowGateClient = class {
568
569
  this.modalElement = null;
569
570
  }, 300);
570
571
  }
572
+ if (cancelled && this.serverConfig?.cancelUrl) {
573
+ window.location.href = this.serverConfig.cancelUrl;
574
+ }
571
575
  }
572
576
  injectStyles() {
573
577
  if (this.stylesInjected) return;
@@ -617,9 +621,11 @@ var FollowGateClient = class {
617
621
  renderUsernameStep() {
618
622
  const content = this.getContentElement();
619
623
  if (!content) return;
620
- const handle = this.config?.twitter?.handle;
624
+ const handle = this.serverConfig?.targetHandle || this.config?.twitter?.handle;
621
625
  const hasRepost = !!this.config?.twitter?.tweetId;
622
626
  const allowSkip = this.serverConfig?.allowSkip ?? false;
627
+ const welcomeTitle = this.serverConfig?.welcomeTitle || "Unlock Free Access";
628
+ const welcomeMessage = this.serverConfig?.welcomeMessage || "Enter your X username to get started";
623
629
  let explanationText = handle ? `Complete a quick follow${hasRepost ? " & repost" : ""} on X for @${handle} to unlock access.` : `Complete a quick social action to unlock access.`;
624
630
  if (allowSkip) {
625
631
  explanationText += ` You can skip if you prefer, but it helps support the developer.`;
@@ -628,8 +634,8 @@ var FollowGateClient = class {
628
634
  <div class="fg-icon-box">
629
635
  ${ICONS.x}
630
636
  </div>
631
- <h2 class="fg-title">Unlock Free Access</h2>
632
- <p class="fg-subtitle">Enter your X username to get started</p>
637
+ <h2 class="fg-title">${this.escapeHtml(welcomeTitle)}</h2>
638
+ <p class="fg-subtitle">${this.escapeHtml(welcomeMessage)}</p>
633
639
  <div class="fg-info-box" style="margin-bottom: 20px;">
634
640
  <p>${explanationText}</p>
635
641
  </div>
@@ -881,8 +887,11 @@ var FollowGateClient = class {
881
887
  const content = this.getContentElement();
882
888
  if (!content) return;
883
889
  const username = this.currentUser?.username;
890
+ const successTitle = this.serverConfig?.successTitle || "Almost done!";
891
+ const successMessage = this.serverConfig?.successMessage || null;
884
892
  content.innerHTML = `
885
- <h2 class="fg-title">Almost done!</h2>
893
+ <h2 class="fg-title">${this.escapeHtml(successTitle)}</h2>
894
+ ${successMessage ? `<p class="fg-subtitle" style="margin-bottom: 16px;">${this.escapeHtml(successMessage)}</p>` : ""}
886
895
  <div class="fg-verify-box">
887
896
  <div class="fg-verify-box-left">
888
897
  <div class="fg-verify-spinner"></div>
@@ -945,6 +954,9 @@ var FollowGateClient = class {
945
954
  await this.unlock();
946
955
  this.hide();
947
956
  this.config?.onComplete?.();
957
+ if (this.serverConfig?.successUrl) {
958
+ window.location.href = this.serverConfig.successUrl;
959
+ }
948
960
  }
949
961
  renderStepIndicator(currentStep) {
950
962
  return `
@@ -1364,6 +1376,14 @@ var FollowGateClient = class {
1364
1376
  emit(event, data) {
1365
1377
  this.listeners.get(event)?.forEach((callback) => callback(data));
1366
1378
  }
1379
+ /**
1380
+ * Escape HTML to prevent XSS
1381
+ */
1382
+ escapeHtml(text) {
1383
+ const div = document.createElement("div");
1384
+ div.textContent = text;
1385
+ return div.innerHTML;
1386
+ }
1367
1387
  };
1368
1388
  var FollowGate = new FollowGateClient();
1369
1389
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@followgate/js",
3
- "version": "0.9.5",
3
+ "version": "0.10.0",
4
4
  "description": "FollowGate SDK - Grow your audience with every download. Require social actions (follow, repost) before users can access your app.",
5
5
  "author": "FollowGate <hello@followgate.app>",
6
6
  "homepage": "https://followgate.app",