@namiml/web-sdk
Version:
Subscription monetization infrastructure — drop-in SDK with no-code paywalls, onboarding flows, A/B testing for web
619 lines (585 loc) • 21.3 kB
TypeScript
import { PaywallState, IPaywall, NamiPaywallLaunchContext, NamiCampaign, TPaywallContext, TBaseComponent, TSpacerComponent, TSemverObj, TButtonContainer, THeaderFooter, TTextComponent, TSymbolComponent, TContainer, TProductContainer, TImageComponent, TSegmentPicker, TSegmentPickerItem, TVideoComponent, TCollapseContainer, TResponsiveGrid, TRepeatingGrid, TCarouselContainer, TVolumeButton, TPlayPauseButton, TStack, TPaywallLaunchContext, NamiFlow, TQRCodeComponent, TToggleSwitch, TRadioButton, TProgressIndicatorComponent, TToggleButtonComponent, TCountdownTimerTextComponent, TProgressBarComponent, TTextInputComponent } from '@namiml/sdk-core';
export { CustomerJourneyState, DeviceProfile, LaunchCampaignError, LogLevel, Nami, NamiAnonymousCampaign, NamiCampaign, NamiCampaignManager, NamiCampaignRuleType, NamiCampaignSegment, NamiConfiguration, NamiCustomerManager, NamiEntitlement, NamiEntitlementManager, NamiFlowCampaign, NamiFlowEventHandler, NamiFlowHandoffStepHandler, NamiFlowManager, NamiHandoffAttributeValue, NamiHandoffComplete, NamiHandoffOutcome, NamiHandoffTag, NamiInitialConfig, NamiLanguageCodes, NamiLogLevel, NamiLoginSuccess, NamiPaywallAction, NamiPaywallActionHandler, NamiPaywallComponentChange, NamiPaywallEvent, NamiPaywallEventVideoMetadata, NamiPaywallLaunchContext, NamiPaywallManager, NamiPaywallManagerEvents, NamiPermissionOutcome, NamiProductDetails, NamiProductOffer, NamiPurchase, NamiPurchaseDetails, NamiPurchaseManager, NamiPurchaseSuccess, NamiPurchasesState, NamiSKU, NamiSKUType, NamiSubscriptionInterval, NamiSubscriptionPeriod, NamiUserDataEnvelope, _internal, isNamiFlowCampaign } from '@namiml/sdk-core';
import * as lit from 'lit';
import { ReactiveController, ReactiveControllerHost, LitElement, CSSResultGroup, CSSResult, PropertyValueMap, TemplateResult, PropertyValues } from 'lit';
import * as lit_html from 'lit-html';
import Swiper from 'swiper';
/**
* Web-specific extension of PaywallState that integrates with Lit's
* reactive rendering system.
*
* PaywallState (from @namiml/sdk-core) contains ALL platform-agnostic
* business logic: setPaywall, setCurrentGroupData, setFlow, setState,
* setCustomerAttribute, selectedProducts, getSelectedCampaign,
* getPaywallActionEventData, setOpenHeaderIds, setPurchase, etc.
*
* This subclass adds only web-specific concerns:
* - Lit ReactiveController integration (host.requestUpdate on state change)
* - Dynamic state getters that read from the DOM (tvQuality, viewport dims)
* - Type-safe static method overrides returning PaywallContextProvider
*/
declare class PaywallContextProvider extends PaywallState implements ReactiveController {
host: ReactiveControllerHost | null;
static create(paywall: IPaywall, context: NamiPaywallLaunchContext, campaign: NamiCampaign): PaywallContextProvider;
static remove(provider: PaywallContextProvider): void;
static get currentProvider(): PaywallContextProvider | undefined;
constructor(paywall: IPaywall, context: NamiPaywallLaunchContext, campaign: NamiCampaign);
hostConnected(): void;
hostDisconnected(): void;
/**
* Called by PaywallState.setState() after every state mutation.
* Re-attaches DOM-dependent computed getters and triggers a Lit re-render.
*/
protected onStateChanged(): void;
/**
* Attaches computed getters to `this.state` for properties that depend
* on the browser DOM (window dimensions, device pixel ratio).
* Must be called after every setState() since setState replaces the
* state object, losing the previous getters.
*/
private defineDynamicStateProps;
private getTVQuality;
private getViewportWidth;
private getViewportHeight;
}
declare class ContextConsumer implements ReactiveController {
private host;
state: TPaywallContext;
contextProvider: PaywallContextProvider;
constructor(host: ReactiveControllerHost, contextProvider: PaywallContextProvider);
handleStateChange(): void;
hostConnected(): void;
hostDisconnected(): void;
}
declare class NamiElementBase extends LitElement {
static styles: CSSResultGroup;
contextConsumer: ContextConsumer;
contextProvider: PaywallContextProvider;
private _instanceStyleSheet?;
private _instanceStyleElement?;
constructor();
protected styles(): CSSResult;
createRenderRoot(): HTMLElement | DocumentFragment;
protected shouldUpdate(): boolean;
protected willUpdate(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void;
disconnectedCallback(): void;
protected getInstanceStyles(): CSSResult[];
private ensureInstanceStyleTarget;
private applyInstanceStyles;
}
declare abstract class NamiElement<C extends TBaseComponent = TBaseComponent> extends NamiElementBase {
static styles: CSSResultGroup;
contextConsumer: ContextConsumer;
contextProvider: PaywallContextProvider;
abstract component: C;
protected willUpdate(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void;
private applyTestId;
private applySpeechLabel;
protected animationStyles(): CSSResult;
protected getInstanceStyles(): CSSResult[];
}
declare class NamiSpacer extends NamiElement {
component: TSpacerComponent;
inFocusedState: boolean;
scaleFactor: number;
minSDKVersion: TSemverObj;
protected styles(): CSSResult;
render(): TemplateResult;
}
declare class NamiButton extends NamiElement {
component: TButtonContainer;
inFocusedState: boolean;
scaleFactor: number;
minSDKVersion: TSemverObj;
private defaultFocused;
private readonly _boundHandleFocus;
private readonly _boundHandleBlur;
constructor();
firstTextValue(): string | undefined;
connectedCallback(): void;
disconnectedCallback(): void;
protected updated(changedProperties: PropertyValueMap<this>): void;
private _handleFocus;
private _handleBlur;
private _dispatchFocusChange;
private _dispatchPageChange;
private _handleKeyDown;
private _handleKeyUp;
private _handleClick;
protected styles(): CSSResult;
render(): any[] | lit_html.TemplateResult<1>;
}
declare class NamiHeader extends NamiElementBase {
components: THeaderFooter;
zIndex: string;
inFullScreen: boolean;
inFocusedState: boolean;
scaleFactor: number;
minSDKVersion: TSemverObj;
private formFactor;
protected styles(): CSSResult;
render(): any[];
}
declare class NamiFooter extends NamiElementBase {
components: THeaderFooter;
zIndex: string;
inFocusedState: boolean;
scaleFactor: number;
minSDKVersion: TSemverObj;
protected styles(): CSSResult;
render(): any[];
}
declare class NamiText extends NamiElement {
component: TTextComponent;
inFocusedState: boolean;
scaleFactor: number;
minSDKVersion: TSemverObj;
protected styles(): CSSResult;
render(): TemplateResult;
}
declare class NamiSymbol extends NamiElement {
component: TSymbolComponent;
inFocusedState: boolean;
scaleFactor: number;
previousSymbolName: string;
protected styles(): CSSResult;
protected updated(): void;
private shouldRenderCurrentIcon;
private renderSvgIcon;
render(): TemplateResult;
}
declare class NamiContainer extends NamiElement {
component: TContainer | TProductContainer;
inFocusedState: boolean;
scaleFactor: number;
minSDKVersion: TSemverObj;
private readonly handleFocusIn;
private readonly handleFocusOut;
private readonly handleFocusChanged;
constructor();
disconnectedCallback(): void;
protected styles(): CSSResult;
render(): any[];
private setFocusState;
}
declare class NamiProductContainer extends NamiElement {
component: TProductContainer;
inFocusedState: boolean;
scaleFactor: number;
minSDKVersion: TSemverObj;
private currentGroupId;
protected styles(): CSSResult;
updated(): void;
render(): any[][];
}
declare class NamiImage extends NamiElement {
component: TImageComponent;
inFocusedState: boolean;
scaleFactor: number;
protected styles(): CSSResult;
protected render(): TemplateResult;
}
declare class NamiBackgroundContainer extends NamiElement {
component: TContainer;
fullscreen: boolean;
inFocusedState: boolean;
scaleFactor: number;
minSDKVersion: TSemverObj;
connectedCallback(): void;
protected styles(): CSSResult;
protected updated(): void;
render(): any[];
}
declare class NamiContentContainer extends NamiElement {
component: TContainer;
zIndex: number;
inFocusedState: boolean;
scaleFactor: number;
minSDKVersion: TSemverObj;
protected styles(): CSSResult;
firstUpdated(): void;
render(): any[];
}
declare class NamiSegmentPicker extends NamiElement {
component: TSegmentPicker;
inFocusedState: boolean;
scaleFactor: number;
minSDKVersion: TSemverObj;
/** Whether any item in this picker is currently focused (television form factor only). */
private _anyItemFocused;
private get _isTv();
constructor();
firstUpdated(changedProperties: PropertyValues): void;
disconnectedCallback(): void;
private _handleClick;
private _handleFocusIn;
private _handleFocusOut;
protected styles(): CSSResult;
render(): lit_html.TemplateResult<1>;
}
declare class NamiSegmentPickerItem extends NamiElement {
component: TSegmentPickerItem;
inFocusedState: boolean;
scaleFactor: number;
private _isActive;
private _isFocused;
private get _isTv();
connectedCallback(): void;
disconnectedCallback(): void;
private _handleFocus;
private _handleBlur;
private _handleKeyDown;
private _moveFocusToSibling;
private _getParentPicker;
private _getParentFormId;
private _updateFormState;
private _handleClick;
private _handleHover;
updated(changedProperties: PropertyValues): void;
protected styles(): CSSResult;
render(): lit_html.TemplateResult<1>;
}
declare class NamiVideo extends NamiElement {
component: TVideoComponent;
inFocusedState: boolean;
scaleFactor: number;
private bgVideo;
disconnectedCallback(): void;
protected styles(): CSSResult;
loadMediaSrc(video: HTMLVideoElement): void;
updated(): void;
protected render(): TemplateResult;
}
declare class NamiCollapseContainer extends NamiElement {
component: TCollapseContainer;
inFocusedState: boolean;
height: number;
scaleFactor: number;
minSDKVersion: TSemverObj;
private isCollapsed;
private _handleClick;
protected styles(): CSSResult;
render(): lit_html.TemplateResult<1>;
}
declare class NamiResponsiveGrid extends NamiElement {
component: TResponsiveGrid;
inFocusedState: boolean;
scaleFactor: number;
minSDKVersion: TSemverObj;
private timelineDots;
private railHeight;
private timelineResizeObserver?;
private mouseDown;
private startX;
scrollLeft: any;
connectedCallback(): void;
disconnectedCallback(): void;
startDragging: (e: any) => void;
stopDragging: () => void;
move: (e: any) => void;
private isGroupedHorizontal;
private isTimelineActive;
protected styles(): CSSResult;
render(): lit_html.TemplateResult<1> | any[][] | lit_html.TemplateResult<1>[];
protected updated(): void;
private measureTimeline;
private readTimelineGeometry;
private _rowMouseDown;
private _rowStartX;
private _rowStartDragging;
private _rowStopDragging;
private _rowMove;
}
declare class NamiRepeatingGrid extends NamiElement {
component: TRepeatingGrid;
inFocusedState: boolean;
scaleFactor: number;
minSDKVersion: TSemverObj;
protected styles(): CSSResult;
render(): lit_html.TemplateResult<1>[];
}
declare class NamiCarouselContainer extends NamiElement {
component: TCarouselContainer;
inFocusedState: boolean;
scaleFactor: number;
minSDKVersion: TSemverObj;
swiperInstance: Swiper;
slideSpacing: number;
connectedCallback(): void;
disconnectedCallback(): void;
updateSpacing: (e: CustomEvent) => void;
protected styles(): CSSResult;
protected updated(): void;
private handleSlideChange;
private getCarouselOnChange;
private getCarouselSlides;
render(): lit_html.TemplateResult<1>;
}
declare class NamiVolumeButton extends NamiElement {
component: TVolumeButton;
inFocusedState: boolean;
scaleFactor: number;
minSDKVersion: TSemverObj;
private muted;
constructor();
private _handleFocus;
private _handleBlur;
private _handleKeyDown;
private _handleClick;
updated(): void;
protected styles(): CSSResult;
render(): any[];
}
declare class NamiPlayPauseButton extends NamiElement {
component: TPlayPauseButton;
inFocusedState: boolean;
scaleFactor: number;
minSDKVersion: TSemverObj;
private playing;
constructor();
private _handleFocus;
private _handleBlur;
private _handleKeyDown;
private _handleClick;
updated(): void;
protected styles(): CSSResult;
render(): any[];
}
declare class NamiStack extends NamiElement {
component: TStack;
inFocusedState: boolean;
scaleFactor: number;
minSDKVersion: TSemverObj;
protected styles(): lit.CSSResult;
protected render(): any[];
}
declare class NamiPaywallScreen extends LitElement {
paywall: IPaywall;
campaign: NamiCampaign;
context: TPaywallLaunchContext;
active: boolean;
private contextProvider;
private contextConsumer;
private minSDKVersion;
timeSpentOnPaywall: number;
flow?: NamiFlow;
private teardownEvent;
private activeTemplate;
private footerResizeObserver?;
static styles: lit.CSSResult;
connectedCallback(): void;
disconnectedCallback(): void;
private userInteractionListener;
firstUpdated(): void;
protected updated(): void;
private updateActiveRenderRoot;
private observeFooterHeight;
private postImpression;
private postPaywallScreenData;
private getTemplate;
render(): lit_html.TemplateResult<1>;
}
declare class NamiQRCode extends NamiElement {
component: TQRCodeComponent;
scaleFactor: number;
protected styles(): lit.CSSResult;
private renderQr;
firstUpdated(): void;
protected updated(changedProps: Map<string, unknown>): void;
private get computedSize();
render(): lit_html.TemplateResult<1>;
}
declare class NamiToggleSwitch extends NamiElement {
component: TToggleSwitch;
inFocusedState: boolean;
scaleFactor: number;
isActive: boolean;
constructor();
connectedCallback(): void;
disconnectedCallback(): void;
private _handleKeyDown;
private _handleClick;
protected styles(): CSSResult;
private applyPlateStyles;
private applyHandleStyles;
render(): lit_html.TemplateResult<1>;
}
declare class NamiRadioButton extends NamiElement {
component: TRadioButton;
inFocusedState: boolean;
scaleFactor: number;
constructor();
protected styles(): CSSResult;
private get isActive();
render(): lit_html.TemplateResult<1>;
}
declare class NamiProgressIndicator extends NamiElement {
component: TProgressIndicatorComponent;
scaleFactor: number;
inFocusedState: boolean;
minSDKVersion: TSemverObj;
currentWidth: number;
private hasInitialized;
connectedCallback(): void;
firstUpdated(changedProperties: any): void;
updated(changedProperties: any): void;
protected styles(): CSSResult;
private getProgressPercentage;
private animateProgress;
render(): TemplateResult;
}
declare class NamiToggleButton extends NamiElement {
component: TToggleButtonComponent;
inFocusedState: boolean;
scaleFactor: number;
minSDKVersion: TSemverObj;
isActive: boolean;
connectedCallback(): void;
disconnectedCallback(): void;
private _handleFocus;
private _handleKeyDown;
private _handleClick;
updated(): void;
protected styles(): CSSResult;
render(): any[];
}
declare class NamiCountdownTimerText extends NamiElement {
component: TCountdownTimerTextComponent;
inFocusedState: boolean;
scaleFactor: number;
minSDKVersion: TSemverObj;
private timer;
private startTime;
private initialDuration;
private hasEmittedCompletion;
private timerState;
private static readonly DEFAULT_LABELS;
private static readonly DEFAULT_UNITS;
private static readonly SECONDS_PER_DAY;
private static readonly SECONDS_PER_HOUR;
private static readonly SECONDS_PER_MINUTE;
private static readonly TIMER_INTERVAL_MS;
protected firstUpdated(): void;
disconnectedCallback(): void;
private getTimerId;
private loadTimerState;
private saveTimerState;
private getSavedTimerState;
private startTimer;
private initializeTimerState;
private restoreTimerFromState;
private resetTimerState;
private onTimerTick;
private clearTimer;
private calculateTimeValues;
private calculateTotalRemainingSeconds;
private calculateDurationRemainingSeconds;
private calculateTargetDateTimeRemainingSeconds;
private calculateCurrentRemainingSeconds;
private convertSecondsToTimeUnits;
private formatValue;
private emitCompletionEvent;
updated(changedProperties: PropertyValues): void;
private updateAccessibilityAttributes;
private handleComponentChange;
protected styles(): CSSResult;
render(): lit_html.TemplateResult<1>;
private buildUnitsToRender;
private normalizeLabelPosition;
private shouldDisplayLabels;
private getLabel;
private renderTimerUnits;
private renderUnit;
}
declare class NamiProgressBar extends NamiElement {
component: TProgressBarComponent;
scaleFactor: number;
inFocusedState: boolean;
minSDKVersion: TSemverObj;
private currentProgress;
private isAnimating;
private screenreaderAnnouncement;
private hasInitialized;
private delayTimeoutId;
private animationFrameId;
private animationStartTime;
private startPercentage;
connectedCallback(): void;
disconnectedCallback(): void;
firstUpdated(changedProperties: any): void;
updated(changedProperties: any): void;
private cleanup;
private getResolvedDuration;
private startAnimation;
private beginAnimation;
private animateDeterminate;
private getActiveWidthCss;
private isActiveWidthPercent;
protected styles(): CSSResult;
render(): TemplateResult;
}
declare class NamiTextInput extends NamiElement<TTextInputComponent> {
component: TTextInputComponent;
inFocusedState: boolean;
scaleFactor: number;
/** Live (non-reactive) buffer of the input value; mirrors PaywallState. */
private _value;
/** Whether the input currently holds DOM focus. */
private _focused;
constructor();
connectedCallback(): void;
private get isTelevision();
/** Map the wire `type` to the validator's `TTextInputType`. */
private validatorType;
private validator;
private get currentError();
private _handleInput;
private _handleFocus;
private _handleBlur;
protected styles(): CSSResult;
private resolvedSpacing;
private resolvedBorderWidth;
private applyLabelStyles;
/**
* 4-state styling: error > focused > filled > empty. Errors and focus override
* the resting border/fill/radius. Filled vs empty share the resting style; the
* distinction exists for parity with the native ports and future theming.
*/
private applyInputStyles;
private applyErrorStyles;
render(): lit_html.TemplateResult<1>;
}
declare global {
interface HTMLElementTagNameMap {
"nami-spacer": NamiSpacer;
"nami-button": NamiButton;
"nami-text": NamiText;
"nami-segment-picker": NamiSegmentPicker;
"nami-segment-picker-item": NamiSegmentPickerItem;
"nami-header": NamiHeader;
"nami-footer": NamiFooter;
"nami-container": NamiContainer;
"nami-product-container": NamiProductContainer;
"nami-image": NamiImage;
"nami-background-container": NamiBackgroundContainer;
"nami-content-container": NamiContentContainer;
"nami-symbol": NamiSymbol;
"nami-video": NamiVideo;
"nami-collapse-container": NamiCollapseContainer;
"nami-responsive-grid": NamiResponsiveGrid;
"nami-repeating-grid": NamiRepeatingGrid;
"nami-carousel-container": NamiCarouselContainer;
"nami-volume-button": NamiVolumeButton;
"nami-play-pause-button": NamiPlayPauseButton;
"nami-stack": NamiStack;
"nami-paywall-screen": NamiPaywallScreen;
"nami-qr-code": NamiQRCode;
"nami-toggle-switch": NamiToggleSwitch;
"nami-radio-button": NamiRadioButton;
"nami-progress-indicator": NamiProgressIndicator;
"nami-toggle-button": NamiToggleButton;
"nami-countdown-timer-text": NamiCountdownTimerText;
"nami-progress-bar": NamiProgressBar;
"nami-text-input": NamiTextInput;
}
}