web-push-notifications 3.62.12 → 3.63.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.
@@ -1,19 +1,80 @@
1
+ import { type IWebPopupsPublicApi, type WebPopupsPublicState } from './types';
1
2
  import { type Pushwoosh } from '../../core/Pushwoosh';
2
- export declare class WebPopupsWidget {
3
+ export declare class WebPopupsWidget implements IWebPopupsPublicApi {
3
4
  private readonly pw;
4
5
  private isRecurringVisitor;
5
- private readonly loadedPopups;
6
- private readonly pendingTimers;
6
+ /** Every popup the server returned, keyed by code. Never pruned. */
7
+ private readonly entries;
8
+ /** Codes whose delay has elapsed, waiting for the display slot. */
9
+ private readonly queue;
10
+ /** The single popup on screen, if any. */
11
+ private visible;
12
+ private drainTimeoutId;
13
+ private autoShowEnabled;
7
14
  private isNavigationSubscribed;
8
15
  private openPopupsCount;
9
16
  private bodyOverflowBeforeLock;
10
- private lockBodyScroll;
11
- private unlockBodyScroll;
17
+ private readyResolve;
18
+ private readonly readyPromise;
12
19
  constructor(pw: Pushwoosh);
13
20
  run(): Promise<void>;
14
- private loadWebPopup;
21
+ /**
22
+ * Show a popup immediately, ignoring EVERY display condition: delay, page
23
+ * rules, device_type, visitors_type, frequency capping and trigger_type.
24
+ * An already visible popup is closed to make room.
25
+ *
26
+ * Stats and frequency bookkeeping are recorded exactly as for an automatic
27
+ * display. Never rejects: resolves false and logs the reason on failure.
28
+ */
29
+ show(code: string): Promise<boolean>;
30
+ /**
31
+ * Hide the visible popup, optionally only if it is the given one.
32
+ * Returns false when nothing was hidden.
33
+ */
34
+ hide(code?: string): boolean;
35
+ /**
36
+ * Hide the visible popup and dismiss everything still pending for this page
37
+ * load. show() keeps working afterwards.
38
+ */
39
+ hideAll(): boolean;
40
+ isVisible(code?: string): boolean;
41
+ getVisibleCode(): string | null;
42
+ getAvailableCodes(): Array<string>;
43
+ getState(): WebPopupsPublicState;
44
+ /**
45
+ * Resolve the entry's renderable content, fetching it at most once. A failed
46
+ * fetch clears the memo so a later show() can retry.
47
+ */
48
+ private ensureContent;
49
+ private loadContent;
50
+ private loadedCodes;
15
51
  private renderForCurrentPage;
16
- private cancelPendingForUnmatchedPages;
52
+ private canAutoDisplay;
53
+ private isAutoTrigger;
54
+ private armDelay;
55
+ /**
56
+ * VISIT is reported once per page load, when the popup is armed for the
57
+ * current page — the same moment as before the queue existed.
58
+ */
59
+ private recordVisit;
60
+ /** Ordering: shorter delay first, then the order the server returned them. */
61
+ private insertIntoQueue;
62
+ /**
63
+ * Release popups whose page rules stopped matching, both the ones still
64
+ * waiting out their delay and the ones already queued. They return to `idle`
65
+ * and are re-armed with a full delay if the visitor comes back.
66
+ */
67
+ private releaseUnmatchedPending;
68
+ /** Clear an entry's armed timer and queue slot, leaving its state to the caller. */
69
+ private detachFromAutoPipeline;
70
+ /** Show the head of the queue if the display slot is free. */
71
+ private drain;
72
+ private scheduleDrain;
73
+ private cancelScheduledDrain;
74
+ private present;
75
+ private renderSubscriptionForm;
76
+ private lockBodyScroll;
77
+ private unlockBodyScroll;
17
78
  private subscribeToNavigation;
18
79
  private checkStrongCondition;
19
80
  private checkSoftCondition;
@@ -24,6 +85,4 @@ export declare class WebPopupsWidget {
24
85
  private checkCanBeShownByVisitorsTypeCondition;
25
86
  private markAsShown;
26
87
  private getSessionStorageKey;
27
- private addToQueue;
28
- private renderSubscriptionForm;
29
88
  }
@@ -1,5 +1,7 @@
1
1
  export declare const WEB_POPUPS_WIDGET_NAMESPACE = "pushwoosh-web-popups";
2
+ export declare const WEB_POPUPS_LOG_PREFIX = "[WebPopups]";
2
3
  export declare const POPUP_HOST_Z_INDEX = 2147483647;
4
+ export declare const QUEUE_GAP_MS = 400;
3
5
  export declare const SUBSCRIPTION_FORMS_WIDGET_URL = "https://cdn.pushwoosh.com/subscription-forms/widget.js";
4
6
  export declare const SUBSCRIPTION_FORMS_WIDGET_TAG = "pushwoosh-subscribe-widget";
5
7
  export declare const SUBSCRIPTION_FORMS_API_URL = "https://subscription-form.svc-nue.pushwoosh.com/api/v1";
@@ -14,3 +14,9 @@ export declare const parseWebPopupContent: (json: string) => WebPopupParams | nu
14
14
  * submit through the subscription-form service.
15
15
  */
16
16
  export declare const renderWebPopup: (container: HTMLElement, params: WebPopupParams, onRequestClose: () => void) => void;
17
+ /**
18
+ * Unmount a popup rendered by `renderWebPopup`. Dropping the host element alone
19
+ * leaves the tree mounted on a detached node, so component cleanup never runs —
20
+ * harmless for a popup shown once, not harmless now that popups cycle.
21
+ */
22
+ export declare const unmountWebPopup: (container: HTMLElement) => void;
@@ -1,11 +1,22 @@
1
+ import { type WebPopupParams } from 'smart-blocks-utils';
1
2
  export type IWebPopupsConfig = {
2
3
  enable: boolean;
4
+ /**
5
+ * `false` turns off automatic display entirely: the SDK still loads the
6
+ * popups but never shows one by itself, leaving the site to drive everything
7
+ * through `Pushwoosh.moduleRegistry.webPopups.show(code)`. Defaults to `true`.
8
+ *
9
+ * This is the site-wide switch; the per-popup equivalent is the dashboard's
10
+ * trigger setting (`WebPopup.trigger_type`).
11
+ */
12
+ autoShow?: boolean;
3
13
  };
4
14
  export type PageRuleOperator = 'EQUALS' | 'STARTS_WITH' | (string & {});
5
15
  export type PageRule = {
6
16
  path: string;
7
17
  operator: PageRuleOperator;
8
18
  };
19
+ export type WebPopupTriggerType = 'PAGE_LOAD' | 'API' | (string & {});
9
20
  export type WebPopup = {
10
21
  code: string;
11
22
  popup_form_content_code?: string;
@@ -17,9 +28,75 @@ export type WebPopup = {
17
28
  excluded_pages?: PageRule[];
18
29
  delay: number;
19
30
  frequency: 'ONCE' | 'ONCE_PER_SESSION' | 'EVERY_VISIT';
31
+ trigger_type?: WebPopupTriggerType;
20
32
  };
21
33
  export type WebPopupContent = {
22
34
  code: string;
23
35
  json: string;
24
36
  html: string | null;
25
37
  };
38
+ /** Renderable popup payload: either parsed content or a hosted form code. */
39
+ export type WebPopupContentBundle = {
40
+ kind: 'content';
41
+ parsed: WebPopupParams;
42
+ } | {
43
+ kind: 'subscription-form';
44
+ formCode: string;
45
+ };
46
+ /**
47
+ * Where a popup is in the automatic display pipeline for the current page load.
48
+ *
49
+ * `idle` -> `waiting` (delay timer armed) -> `queued` (delay served, waiting for
50
+ * the display slot) -> `visible` -> `done`. Navigation can send a `waiting` or
51
+ * `queued` popup back to `idle` when its page rules stop matching.
52
+ */
53
+ export type WebPopupEntryState = 'idle' | 'waiting' | 'queued' | 'visible' | 'done';
54
+ /** Everything the widget knows about one popup, for the whole page load. */
55
+ export type WebPopupEntry = {
56
+ popup: WebPopup;
57
+ /** Index in the server response — the ordering tiebreaker after `delay`. */
58
+ order: number;
59
+ state: WebPopupEntryState;
60
+ /** Renderable content; null until fetched, or if the fetch/parse failed. */
61
+ content: WebPopupContentBundle | null;
62
+ /** In-flight fetch, memoised so run() and show() never duplicate a request. */
63
+ loading: Promise<WebPopupContentBundle | null> | null;
64
+ /** device_type + visitors_type + frequency, evaluated exactly once in run(). */
65
+ passedStrongConditions: boolean;
66
+ /** Armed delay timer while state === 'waiting'. */
67
+ timeoutId: number | null;
68
+ /** VISIT already reported for this page load. */
69
+ visitRecorded: boolean;
70
+ };
71
+ export type WebPopupHideReason = 'user' | 'api' | 'preempted';
72
+ export type WebPopupShowTrigger = 'auto' | 'api';
73
+ /** Handle to the single popup currently on screen. */
74
+ export type VisibleWebPopup = {
75
+ code: string;
76
+ host: HTMLElement;
77
+ modal: boolean;
78
+ /** Idempotent teardown. */
79
+ close: (reason: WebPopupHideReason) => void;
80
+ };
81
+ export type WebPopupsPublicState = {
82
+ /** Code of the popup on screen, if any. */
83
+ visible: string | null;
84
+ /** Delay served, waiting for the display slot. */
85
+ queued: string[];
86
+ /** Delay timer armed for the current page. */
87
+ waiting: string[];
88
+ /** Every code the server returned for this device. */
89
+ available: string[];
90
+ };
91
+ /**
92
+ * The programmatic surface exposed as `Pushwoosh.moduleRegistry.webPopups`.
93
+ */
94
+ export interface IWebPopupsPublicApi {
95
+ show(code: string): Promise<boolean>;
96
+ hide(code?: string): boolean;
97
+ hideAll(): boolean;
98
+ isVisible(code?: string): boolean;
99
+ getVisibleCode(): string | null;
100
+ getAvailableCodes(): string[];
101
+ getState(): WebPopupsPublicState;
102
+ }