@guidelytech/react-native 0.0.0-stage → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +119 -2
- package/dist/index.cjs +4490 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +718 -0
- package/dist/index.d.ts +718 -0
- package/dist/index.js +4451 -0
- package/dist/index.js.map +1 -0
- package/package.json +69 -3
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,718 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { SelectorStrategy, MessengerConfig, MessengerMessage, MessengerConversation, SdkArticlesResponse, ResourceCenterArticle, PublishedGuide, ProjectTheme, GuideStep, SdkConfigResponse, ChecklistTask, SdkEvent, TargetingContext, StepButton, ResourceCenterConfig, Placement } from '@guidelytech/shared';
|
|
4
|
+
export { GuideStep, PublishedGuide, SdkConfigResponse } from '@guidelytech/shared';
|
|
5
|
+
import { KeyValueStore, ChecklistProgressState, GuidelyEnvironment, ConsentState, GuidelyUser, GuidelyAccount, GuideLocalState, SessionState } from '@guidelytech/sdk-core/headless';
|
|
6
|
+
export { ChecklistProgressState, ConsentState, GuidelyAccount, GuidelyEnvironment, GuidelyUser } from '@guidelytech/sdk-core/headless';
|
|
7
|
+
import { ViewProps, StyleProp, ViewStyle, View, GestureResponderEvent } from 'react-native';
|
|
8
|
+
|
|
9
|
+
interface Rect {
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
width: number;
|
|
13
|
+
height: number;
|
|
14
|
+
}
|
|
15
|
+
/** A mounted `<GuidelyTarget>`; `measure` returns its frame in window coordinates. */
|
|
16
|
+
interface TargetHandle {
|
|
17
|
+
measure(): Promise<Rect | null>;
|
|
18
|
+
/**
|
|
19
|
+
* Screen the view lives on (from `GuidelyScreenScope`). Navigators keep inactive screens mounted
|
|
20
|
+
* and laid out, so a target on another screen would otherwise measure as visible.
|
|
21
|
+
*/
|
|
22
|
+
screen?: string | null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The Guidely ids a step target can match on mobile, in order: `guidely-id` and `id` strategies
|
|
26
|
+
* by value, CSS / data-attribute strategies when they name a single id (`#x`, `[data-guidely-id=x]`).
|
|
27
|
+
*/
|
|
28
|
+
declare function targetIdsFor(selectors: SelectorStrategy[]): string[];
|
|
29
|
+
/** Registry of mounted targets. One per client; `<GuidelyTarget>` registers itself on mount. */
|
|
30
|
+
declare class TargetRegistry {
|
|
31
|
+
private readonly targets;
|
|
32
|
+
private readonly changeListeners;
|
|
33
|
+
private readonly tapListeners;
|
|
34
|
+
private viewport;
|
|
35
|
+
private screen;
|
|
36
|
+
register(id: string, handle: TargetHandle): () => void;
|
|
37
|
+
/** Window size used for the on-screen check. */
|
|
38
|
+
setViewport(width: number, height: number): void;
|
|
39
|
+
/** The current screen; targets scoped to other screens are treated as hidden. */
|
|
40
|
+
setScreen(name: string | null): void;
|
|
41
|
+
has(id: string): boolean;
|
|
42
|
+
ids(): string[];
|
|
43
|
+
/** Call when a target's layout may have changed (onLayout, scroll). */
|
|
44
|
+
changed(): void;
|
|
45
|
+
onChange(cb: () => void): () => void;
|
|
46
|
+
tapped(id: string): void;
|
|
47
|
+
onTap(cb: (id: string) => void): () => void;
|
|
48
|
+
/** Frame of a visible target (the most recently mounted visible one when an id is used twice), else null. */
|
|
49
|
+
measure(id: string): Promise<Rect | null>;
|
|
50
|
+
private measureHandle;
|
|
51
|
+
/** First of `ids` that is mounted and visible. */
|
|
52
|
+
resolve(ids: string[]): Promise<{
|
|
53
|
+
id: string;
|
|
54
|
+
rect: Rect;
|
|
55
|
+
} | null>;
|
|
56
|
+
/** Resolves when one of `ids` is visible; `timeoutMs` 0 waits forever. Re-checks on registry changes and every 300ms. */
|
|
57
|
+
waitFor(ids: string[], options: {
|
|
58
|
+
timeoutMs: number;
|
|
59
|
+
signal?: AbortSignal;
|
|
60
|
+
}): Promise<{
|
|
61
|
+
id: string;
|
|
62
|
+
rect: Rect;
|
|
63
|
+
}>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
type GuideStatus = "idle" | "running" | "waiting_url" | "waiting_target" | "ended";
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Scout messenger for React Native: the transport of `@guidelytech/sdk-core`'s messenger-api plus
|
|
70
|
+
* the conversation state the web widget keeps, as a headless store the overlay renders.
|
|
71
|
+
*/
|
|
72
|
+
type MessengerTab = "home" | "messages" | "help";
|
|
73
|
+
type MessengerView = {
|
|
74
|
+
kind: "tab";
|
|
75
|
+
tab: MessengerTab;
|
|
76
|
+
} | {
|
|
77
|
+
kind: "thread";
|
|
78
|
+
conversationId: string | null;
|
|
79
|
+
} | {
|
|
80
|
+
kind: "article";
|
|
81
|
+
articleId: string;
|
|
82
|
+
from: MessengerView;
|
|
83
|
+
};
|
|
84
|
+
interface MessengerThread {
|
|
85
|
+
conversation: MessengerConversation | null;
|
|
86
|
+
messages: MessengerMessage[];
|
|
87
|
+
/** Reply text streamed so far, by message id (before the final `done` message arrives). */
|
|
88
|
+
streaming: Record<string, string>;
|
|
89
|
+
sending: boolean;
|
|
90
|
+
error: string | null;
|
|
91
|
+
/** Text to pre-fill in the composer (`showNewMessage(text)`). */
|
|
92
|
+
draft: string;
|
|
93
|
+
}
|
|
94
|
+
interface MessengerSnapshot {
|
|
95
|
+
config: MessengerConfig;
|
|
96
|
+
open: boolean;
|
|
97
|
+
view: MessengerView;
|
|
98
|
+
conversations: MessengerConversation[];
|
|
99
|
+
thread: MessengerThread | null;
|
|
100
|
+
/** Conversations with unread replies. */
|
|
101
|
+
unread: number;
|
|
102
|
+
articles: SdkArticlesResponse | null;
|
|
103
|
+
article: ResourceCenterArticle | null;
|
|
104
|
+
}
|
|
105
|
+
/** Incremental `text/event-stream` parser: `event:` + single-line JSON `data:`, `:` comments ignored. */
|
|
106
|
+
declare function createSseParser(onEvent: (event: string, data: unknown) => void): {
|
|
107
|
+
feed(chunk: string): void;
|
|
108
|
+
end(): void;
|
|
109
|
+
};
|
|
110
|
+
interface HttpResult {
|
|
111
|
+
status: number;
|
|
112
|
+
/** JSON body when the server answered with JSON. */
|
|
113
|
+
json: unknown;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* POST that streams server-sent events as they arrive. React Native's `fetch` cannot read a body
|
|
117
|
+
* incrementally, but its `XMLHttpRequest` reports partial `responseText` on progress events.
|
|
118
|
+
*/
|
|
119
|
+
type StreamPost = (url: string, headers: Record<string, string>, body: unknown, onChunk: (text: string) => void) => Promise<HttpResult & {
|
|
120
|
+
streamed: boolean;
|
|
121
|
+
}>;
|
|
122
|
+
interface MessengerDeps {
|
|
123
|
+
baseUrl: string;
|
|
124
|
+
publicKey: string;
|
|
125
|
+
store: KeyValueStore;
|
|
126
|
+
fetch: typeof fetch;
|
|
127
|
+
streamPost: StreamPost;
|
|
128
|
+
anonymousId: () => string;
|
|
129
|
+
userId: () => string | null;
|
|
130
|
+
/** Screen path to attach to new conversations (omitted when URL collection is off). */
|
|
131
|
+
pageUrl: () => string | undefined;
|
|
132
|
+
onOpen: () => void;
|
|
133
|
+
onMessage: (message: MessengerMessage, conversation: MessengerConversation) => void;
|
|
134
|
+
onStartGuide: (key: string) => void;
|
|
135
|
+
onError: (err: unknown) => void;
|
|
136
|
+
/** Poll intervals (ms): open thread, and unread badge otherwise. */
|
|
137
|
+
pollMs?: {
|
|
138
|
+
thread: number;
|
|
139
|
+
background: number;
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
declare class Messenger {
|
|
143
|
+
private readonly deps;
|
|
144
|
+
private snapshot;
|
|
145
|
+
private readonly listeners;
|
|
146
|
+
private threadTimer;
|
|
147
|
+
private backgroundTimer;
|
|
148
|
+
private foreground;
|
|
149
|
+
private destroyed;
|
|
150
|
+
private readonly poll;
|
|
151
|
+
constructor(config: MessengerConfig, deps: MessengerDeps);
|
|
152
|
+
getSnapshot(): MessengerSnapshot;
|
|
153
|
+
subscribe(cb: () => void): () => void;
|
|
154
|
+
private set;
|
|
155
|
+
private setThread;
|
|
156
|
+
updateConfig(config: MessengerConfig): void;
|
|
157
|
+
private stored;
|
|
158
|
+
private remember;
|
|
159
|
+
private tokenFor;
|
|
160
|
+
/** Forgets every conversation (logout). */
|
|
161
|
+
forgetAll(): void;
|
|
162
|
+
private url;
|
|
163
|
+
private headers;
|
|
164
|
+
private request;
|
|
165
|
+
open(tab?: MessengerTab): void;
|
|
166
|
+
close(): void;
|
|
167
|
+
setTab(tab: MessengerTab): void;
|
|
168
|
+
private onView;
|
|
169
|
+
/** Opens a new thread (optionally pre-filling the composer). */
|
|
170
|
+
showNewMessage(text?: string): void;
|
|
171
|
+
openConversation(id: string): Promise<void>;
|
|
172
|
+
back(): void;
|
|
173
|
+
private upsertConversation;
|
|
174
|
+
private markRead;
|
|
175
|
+
refreshConversations(): Promise<void>;
|
|
176
|
+
/** Sends the composer text: starts a conversation or posts to the open one. Streams Scout's reply. */
|
|
177
|
+
send(text: string): Promise<void>;
|
|
178
|
+
private addMessage;
|
|
179
|
+
handoff(): Promise<void>;
|
|
180
|
+
rate(rating: number): Promise<void>;
|
|
181
|
+
startGuide(key: string): void;
|
|
182
|
+
loadArticles(): Promise<void>;
|
|
183
|
+
openArticle(id: string): Promise<void>;
|
|
184
|
+
search(q: string): Promise<ResourceCenterArticle[]>;
|
|
185
|
+
/** Called with app foreground/background changes; polling only runs in the foreground. */
|
|
186
|
+
setForeground(active: boolean): void;
|
|
187
|
+
private startBackgroundPolling;
|
|
188
|
+
private scheduleThreadPoll;
|
|
189
|
+
private stopThreadPolling;
|
|
190
|
+
private pollThread;
|
|
191
|
+
destroy(): void;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* AsyncStorage-compatible key/value storage (`@react-native-async-storage/async-storage`,
|
|
196
|
+
* `expo-secure-store` wrappers, MMKV adapters…). Synchronous implementations work too.
|
|
197
|
+
*/
|
|
198
|
+
interface GuidelyStorage {
|
|
199
|
+
getItem(key: string): Promise<string | null> | string | null;
|
|
200
|
+
setItem(key: string, value: string): Promise<void> | void;
|
|
201
|
+
removeItem(key: string): Promise<void> | void;
|
|
202
|
+
}
|
|
203
|
+
/** Device facts the engine needs. The provider fills these in from React Native APIs. */
|
|
204
|
+
interface DeviceEnvironment {
|
|
205
|
+
platform: "ios" | "android";
|
|
206
|
+
deviceType: "mobile" | "tablet";
|
|
207
|
+
locale?: string;
|
|
208
|
+
appVersion?: string;
|
|
209
|
+
}
|
|
210
|
+
interface GuidelyOptions {
|
|
211
|
+
/** Environment public key, e.g. `pk_dev_…`. Not a secret. */
|
|
212
|
+
projectId: string;
|
|
213
|
+
environment?: GuidelyEnvironment;
|
|
214
|
+
/** Base URL of your Guidely deployment, e.g. `https://guidelytech.com`. */
|
|
215
|
+
apiUrl?: string;
|
|
216
|
+
/**
|
|
217
|
+
* Where identity, cached config and queued events are persisted. Pass AsyncStorage
|
|
218
|
+
* (`@react-native-async-storage/async-storage`); without it state lasts only for the app session.
|
|
219
|
+
*/
|
|
220
|
+
storage?: GuidelyStorage;
|
|
221
|
+
debug?: boolean;
|
|
222
|
+
/** Send analytics events (default `true`). Guides still render when disabled. */
|
|
223
|
+
analytics?: boolean;
|
|
224
|
+
consent?: ConsentState;
|
|
225
|
+
/** Host app version for `app.version` targeting rules. */
|
|
226
|
+
appVersion?: string;
|
|
227
|
+
/** How often to refresh the published config (default 5 minutes). */
|
|
228
|
+
configRefreshMs?: number;
|
|
229
|
+
/** Overrides for the project theme. */
|
|
230
|
+
theme?: Partial<ProjectTheme>;
|
|
231
|
+
/** Identify this user as soon as the client initialises. */
|
|
232
|
+
user?: GuidelyUser;
|
|
233
|
+
/** Handles relative and custom-scheme URLs from buttons, links and tasks (deep links, in-app routes). Return `true` when handled. */
|
|
234
|
+
onNavigate?: (url: string) => boolean | void;
|
|
235
|
+
onError?: (error: Error) => void;
|
|
236
|
+
/** Custom fetch (tests / polyfills). */
|
|
237
|
+
fetch?: typeof fetch;
|
|
238
|
+
/** Show the floating checklist launcher (default `true`). */
|
|
239
|
+
showChecklistLauncher?: boolean;
|
|
240
|
+
/** Show a floating resource-center launcher (default `false`; call `openResourceCenter()` instead). */
|
|
241
|
+
showResourceCenterLauncher?: boolean;
|
|
242
|
+
/** Show the Scout chat bubble when the messenger is on for this platform (default `true`). */
|
|
243
|
+
showMessengerLauncher?: boolean;
|
|
244
|
+
}
|
|
245
|
+
interface GuideStepInfo {
|
|
246
|
+
guide: PublishedGuide;
|
|
247
|
+
stepId: string;
|
|
248
|
+
stepIndex: number;
|
|
249
|
+
}
|
|
250
|
+
interface GuidelyEvents {
|
|
251
|
+
ready: (config: SdkConfigResponse) => void;
|
|
252
|
+
config: (config: SdkConfigResponse) => void;
|
|
253
|
+
"guide:start": (guide: PublishedGuide) => void;
|
|
254
|
+
"guide:step": (info: GuideStepInfo) => void;
|
|
255
|
+
"guide:complete": (guide: PublishedGuide) => void;
|
|
256
|
+
"guide:dismiss": (guide: PublishedGuide) => void;
|
|
257
|
+
"guide:skip": (guide: PublishedGuide) => void;
|
|
258
|
+
"checklist:task": (info: {
|
|
259
|
+
guide: PublishedGuide;
|
|
260
|
+
task: ChecklistTask;
|
|
261
|
+
progress: ChecklistProgressState;
|
|
262
|
+
}) => void;
|
|
263
|
+
"checklist:complete": (guide: PublishedGuide) => void;
|
|
264
|
+
"survey:submit": (info: {
|
|
265
|
+
guide: PublishedGuide;
|
|
266
|
+
answers: Record<string, unknown>;
|
|
267
|
+
responseId: string;
|
|
268
|
+
}) => void;
|
|
269
|
+
"resource-center:open": () => void;
|
|
270
|
+
/** The Scout messenger opened. */
|
|
271
|
+
"messenger:open": () => void;
|
|
272
|
+
/** Scout or a teammate replied in a conversation. */
|
|
273
|
+
"conversation:message": (info: {
|
|
274
|
+
message: MessengerMessage;
|
|
275
|
+
conversation: MessengerConversation;
|
|
276
|
+
}) => void;
|
|
277
|
+
error: (error: Error) => void;
|
|
278
|
+
track: (event: SdkEvent) => void;
|
|
279
|
+
identify: (info: {
|
|
280
|
+
userId: string | null;
|
|
281
|
+
anonymousId: string;
|
|
282
|
+
}) => void;
|
|
283
|
+
}
|
|
284
|
+
type GuidelyEventName = keyof GuidelyEvents;
|
|
285
|
+
/** A rendered step, as the overlay sees it. */
|
|
286
|
+
interface StepView {
|
|
287
|
+
/** Stable per rendered step; changes when the step changes. */
|
|
288
|
+
key: string;
|
|
289
|
+
guide: PublishedGuide;
|
|
290
|
+
step: GuideStep;
|
|
291
|
+
index: number;
|
|
292
|
+
total: number;
|
|
293
|
+
canGoBack: boolean;
|
|
294
|
+
/** Guidely id of the resolved target, or null for unanchored / fallback-to-modal steps. */
|
|
295
|
+
targetId: string | null;
|
|
296
|
+
asModal: boolean;
|
|
297
|
+
/** Hotspots render collapsed until tapped. */
|
|
298
|
+
expanded: boolean;
|
|
299
|
+
}
|
|
300
|
+
interface ChecklistView {
|
|
301
|
+
guide: PublishedGuide;
|
|
302
|
+
progress: ChecklistProgressState;
|
|
303
|
+
open: boolean;
|
|
304
|
+
}
|
|
305
|
+
interface SurveyView {
|
|
306
|
+
key: string;
|
|
307
|
+
guide: PublishedGuide;
|
|
308
|
+
submitted: boolean;
|
|
309
|
+
}
|
|
310
|
+
/** Everything the overlay renders. Immutable snapshots; a new object on every change. */
|
|
311
|
+
interface UiState {
|
|
312
|
+
steps: StepView[];
|
|
313
|
+
checklists: ChecklistView[];
|
|
314
|
+
survey: SurveyView | null;
|
|
315
|
+
resourceCenterOpen: boolean;
|
|
316
|
+
theme: Partial<ProjectTheme>;
|
|
317
|
+
/** Scout is on for this platform; the overlay renders the messenger (see `client.getMessenger()`). */
|
|
318
|
+
messenger: boolean;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
declare const SDK_NAME = "@guidelytech/react-native";
|
|
322
|
+
declare const SDK_VERSION = "0.4.1";
|
|
323
|
+
declare const DEFAULT_API_URL = "https://guidelytech.com";
|
|
324
|
+
/** Host-platform services the engine needs; the provider supplies React Native implementations. */
|
|
325
|
+
interface PlatformBridge {
|
|
326
|
+
device: DeviceEnvironment;
|
|
327
|
+
/** Opens an external URL (React Native `Linking.openURL`). */
|
|
328
|
+
openExternal(url: string): void;
|
|
329
|
+
}
|
|
330
|
+
/** Mobile sessions persist across launches and expire after the configured inactivity timeout. */
|
|
331
|
+
interface MobileSession extends SessionState {
|
|
332
|
+
lastActiveAt: string;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* The React Native Guidely client: the web SDK's engine (config, identity, events, triggers,
|
|
336
|
+
* frequency, checklists, surveys) with screens instead of URLs and `<GuidelyTarget>` views instead
|
|
337
|
+
* of DOM elements. The overlay renders whatever {@link getUiState} describes.
|
|
338
|
+
*/
|
|
339
|
+
declare class GuidelyClient {
|
|
340
|
+
readonly options: Readonly<GuidelyOptions & {
|
|
341
|
+
environment: NonNullable<GuidelyOptions["environment"]>;
|
|
342
|
+
apiUrl: string;
|
|
343
|
+
analytics: boolean;
|
|
344
|
+
configRefreshMs: number;
|
|
345
|
+
debug: boolean;
|
|
346
|
+
}>;
|
|
347
|
+
readonly targets: TargetRegistry;
|
|
348
|
+
private readonly bridge;
|
|
349
|
+
private readonly api;
|
|
350
|
+
private readonly store;
|
|
351
|
+
private readonly emitter;
|
|
352
|
+
private queue;
|
|
353
|
+
private config;
|
|
354
|
+
private configFetchedAt;
|
|
355
|
+
private etag;
|
|
356
|
+
private anonymousId;
|
|
357
|
+
private user;
|
|
358
|
+
private state;
|
|
359
|
+
private session;
|
|
360
|
+
private consent;
|
|
361
|
+
private readyPromise;
|
|
362
|
+
private hydrated;
|
|
363
|
+
private pending;
|
|
364
|
+
private isReady;
|
|
365
|
+
private destroyed;
|
|
366
|
+
private active;
|
|
367
|
+
private activeSurvey;
|
|
368
|
+
private queued;
|
|
369
|
+
private flows;
|
|
370
|
+
private checklists;
|
|
371
|
+
private expanded;
|
|
372
|
+
private surveyView;
|
|
373
|
+
private resourceCenterOpen;
|
|
374
|
+
private cleanups;
|
|
375
|
+
private timers;
|
|
376
|
+
private visibilityWatchers;
|
|
377
|
+
private firedDelays;
|
|
378
|
+
private firstVisit;
|
|
379
|
+
private screenName;
|
|
380
|
+
private lastAudiences;
|
|
381
|
+
private backgroundedAt;
|
|
382
|
+
private messenger;
|
|
383
|
+
private ui;
|
|
384
|
+
private uiListeners;
|
|
385
|
+
private readonly customListeners;
|
|
386
|
+
private readonly eventBus;
|
|
387
|
+
constructor(options: GuidelyOptions, bridge: PlatformBridge);
|
|
388
|
+
/** Loads persisted state and config, identifies the stored user and evaluates triggers. Idempotent. */
|
|
389
|
+
init(): Promise<void>;
|
|
390
|
+
ready(): Promise<void>;
|
|
391
|
+
private bootstrap;
|
|
392
|
+
private whenHydrated;
|
|
393
|
+
private fetchConfig;
|
|
394
|
+
private wireTimers;
|
|
395
|
+
/** Re-fetches the published config and re-evaluates triggers. */
|
|
396
|
+
refresh(): Promise<void>;
|
|
397
|
+
/** Called by the provider with React Native `AppState` changes. */
|
|
398
|
+
setAppState(state: "active" | "background" | "inactive" | string): void;
|
|
399
|
+
private sessionExpired;
|
|
400
|
+
/** Tears everything down. Create a new client to start again. */
|
|
401
|
+
destroy(): void;
|
|
402
|
+
/** Identifies the end user and loads server-held state (audiences, guide history, checklist progress). */
|
|
403
|
+
identify(userId: string, traits?: Record<string, unknown>, account?: GuidelyAccount): Promise<void>;
|
|
404
|
+
private syncIdentify;
|
|
405
|
+
private mergeServerState;
|
|
406
|
+
/** Sets or replaces the account (company / organisation) for the current user. */
|
|
407
|
+
setAccount(account: GuidelyAccount): Promise<void>;
|
|
408
|
+
/** Merges additional traits into the current user. */
|
|
409
|
+
updateTraits(traits: Record<string, unknown>): Promise<void>;
|
|
410
|
+
/** Forgets the user (call on logout): new anonymous id, cleared guide/checklist state, new session. */
|
|
411
|
+
reset(): void;
|
|
412
|
+
/** Updates consent at runtime (`granted` flushes buffered events; `denied` drops them). */
|
|
413
|
+
setConsent(consent: ConsentState): void;
|
|
414
|
+
private analyticsEnabled;
|
|
415
|
+
private collectUrls;
|
|
416
|
+
private currentUrl;
|
|
417
|
+
private enqueue;
|
|
418
|
+
/** Tracks a custom event. Events drive `event` triggers, `advanceOn: "event"` steps and checklist tasks. */
|
|
419
|
+
track(name: string, properties?: Record<string, unknown>): void;
|
|
420
|
+
/**
|
|
421
|
+
* Records a screen view (the mobile equivalent of a page view) and re-evaluates triggers. URL
|
|
422
|
+
* patterns, `url_match` triggers, multi-screen steps and `url_visited` tasks match `/<name>`.
|
|
423
|
+
*/
|
|
424
|
+
screen(name: string, properties?: Record<string, unknown>): void;
|
|
425
|
+
/** The current screen name (last value passed to `screen()`). */
|
|
426
|
+
getScreen(): string;
|
|
427
|
+
private handleTap;
|
|
428
|
+
/** Builds the targeting context for the current moment. */
|
|
429
|
+
getContext(): TargetingContext;
|
|
430
|
+
private isTargeted;
|
|
431
|
+
private isEligible;
|
|
432
|
+
private triggerFires;
|
|
433
|
+
private evaluate;
|
|
434
|
+
private armVisibility;
|
|
435
|
+
private setTimer;
|
|
436
|
+
private isShowing;
|
|
437
|
+
private hasExclusive;
|
|
438
|
+
private tryShow;
|
|
439
|
+
private drainQueue;
|
|
440
|
+
private findGuide;
|
|
441
|
+
private guideState;
|
|
442
|
+
private recordImpression;
|
|
443
|
+
private recordEnd;
|
|
444
|
+
private syncGuideState;
|
|
445
|
+
private show;
|
|
446
|
+
private showFlow;
|
|
447
|
+
private showChecklist;
|
|
448
|
+
private showSurvey;
|
|
449
|
+
private finishSurvey;
|
|
450
|
+
/** Theme for a guide: project theme ← app overrides ← guide appearance. */
|
|
451
|
+
themeFor(guide?: PublishedGuide): Partial<ProjectTheme> & {
|
|
452
|
+
dark?: "light" | "dark" | "auto";
|
|
453
|
+
overlayOpacity?: number;
|
|
454
|
+
};
|
|
455
|
+
/**
|
|
456
|
+
* Opens a URL from a button, link or task: the app's `onNavigate` handler first (deep links and
|
|
457
|
+
* in-app routes), then http(s) and custom-scheme URLs through the OS.
|
|
458
|
+
*/
|
|
459
|
+
navigate(url: string): void;
|
|
460
|
+
getUiState(): UiState;
|
|
461
|
+
subscribeUi(cb: () => void): () => void;
|
|
462
|
+
private notify;
|
|
463
|
+
private flowFor;
|
|
464
|
+
/** A step button was pressed in the overlay. */
|
|
465
|
+
pressButton(guideId: string, button: StepButton): void;
|
|
466
|
+
/** The close (×) button of a step. */
|
|
467
|
+
closeStep(guideId: string): void;
|
|
468
|
+
/** The dimmed backdrop behind a step was tapped. */
|
|
469
|
+
backdropPressed(guideId: string): void;
|
|
470
|
+
/** Hotspot dot tapped: show (or hide) its card. */
|
|
471
|
+
toggleHotspot(guideId: string): void;
|
|
472
|
+
setChecklistOpen(guideId: string, open: boolean): void;
|
|
473
|
+
checklistTaskPressed(guideId: string, taskId: string): void;
|
|
474
|
+
dismissChecklist(guideId: string): void;
|
|
475
|
+
submitSurvey(guideId: string, answers: Record<string, unknown>): void;
|
|
476
|
+
closeSurvey(guideId: string): void;
|
|
477
|
+
getResourceCenter(): ResourceCenterConfig | null;
|
|
478
|
+
searchResourceCenter(q: string): Promise<ResourceCenterArticle[]>;
|
|
479
|
+
articleViewed(article: ResourceCenterArticle): void;
|
|
480
|
+
getChecklistProgress(idOrKey: string): ChecklistProgressState;
|
|
481
|
+
completeChecklistTask(idOrKey: string, taskId: string): void;
|
|
482
|
+
private markTaskDone;
|
|
483
|
+
private completeChecklistTasksBy;
|
|
484
|
+
openChecklist(idOrKey: string): void;
|
|
485
|
+
closeChecklist(idOrKey: string): void;
|
|
486
|
+
/** Starts a guide by id or key, bypassing targeting and frequency rules. */
|
|
487
|
+
startGuide(idOrKey: string, options?: {
|
|
488
|
+
stepId?: string;
|
|
489
|
+
}): boolean;
|
|
490
|
+
/** Stops the active guide silently (no dismiss event). */
|
|
491
|
+
stopGuide(): void;
|
|
492
|
+
/** Dismisses the active guide (records a dismissal). */
|
|
493
|
+
dismissGuide(): void;
|
|
494
|
+
getActiveGuide(): PublishedGuide | null;
|
|
495
|
+
getGuides(): ReadonlyArray<PublishedGuide>;
|
|
496
|
+
isGuideCompleted(idOrKey: string): boolean;
|
|
497
|
+
/** Impressions, completion and dismissal for a guide. */
|
|
498
|
+
getGuideState(idOrKey: string): GuideLocalState;
|
|
499
|
+
openResourceCenter(): void;
|
|
500
|
+
closeResourceCenter(): void;
|
|
501
|
+
/** Creates or removes the messenger to match the config (on only when enabled for this platform). */
|
|
502
|
+
private syncMessenger;
|
|
503
|
+
/** The Scout messenger store when Scout is on for this platform (rendered by the overlay). */
|
|
504
|
+
getMessenger(): Messenger | null;
|
|
505
|
+
/** Opens the Scout messenger, optionally on a tab. No-op when Scout is off for this platform. */
|
|
506
|
+
openMessenger(tab?: MessengerTab): void;
|
|
507
|
+
closeMessenger(): void;
|
|
508
|
+
/** Opens a new messenger conversation, optionally pre-filling the message. */
|
|
509
|
+
showNewMessage(text?: string): void;
|
|
510
|
+
on<K extends keyof GuidelyEvents>(event: K, cb: GuidelyEvents[K]): () => void;
|
|
511
|
+
off<K extends keyof GuidelyEvents>(event: K, cb: GuidelyEvents[K]): void;
|
|
512
|
+
isClientReady(): boolean;
|
|
513
|
+
/** Snapshot for debugging. */
|
|
514
|
+
getState(): {
|
|
515
|
+
ready: boolean;
|
|
516
|
+
destroyed: boolean;
|
|
517
|
+
anonymousId: string;
|
|
518
|
+
user: GuidelyUser | null;
|
|
519
|
+
consent: ConsentState;
|
|
520
|
+
screen: string;
|
|
521
|
+
configVersion: number | null;
|
|
522
|
+
guides: {
|
|
523
|
+
id: string;
|
|
524
|
+
key: string;
|
|
525
|
+
kind: "tooltip" | "modal" | "banner" | "checklist" | "survey" | "flow" | "announcement";
|
|
526
|
+
}[];
|
|
527
|
+
activeGuide: {
|
|
528
|
+
status: GuideStatus;
|
|
529
|
+
stepId: string | null;
|
|
530
|
+
stepIndex: number;
|
|
531
|
+
total: number;
|
|
532
|
+
id: string;
|
|
533
|
+
key: string;
|
|
534
|
+
} | {
|
|
535
|
+
id: string;
|
|
536
|
+
key: string;
|
|
537
|
+
} | null;
|
|
538
|
+
queued: string[];
|
|
539
|
+
widgets: string[];
|
|
540
|
+
guideState: Record<string, GuideLocalState>;
|
|
541
|
+
checklists: Record<string, ChecklistProgressState>;
|
|
542
|
+
audienceIds: string[];
|
|
543
|
+
session: MobileSession;
|
|
544
|
+
pendingEvents: number;
|
|
545
|
+
targets: string[];
|
|
546
|
+
};
|
|
547
|
+
private persistState;
|
|
548
|
+
private persistSession;
|
|
549
|
+
private reportError;
|
|
550
|
+
private log;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
type Side = "top" | "bottom" | "left" | "right";
|
|
554
|
+
interface Insets {
|
|
555
|
+
top: number;
|
|
556
|
+
bottom: number;
|
|
557
|
+
left: number;
|
|
558
|
+
right: number;
|
|
559
|
+
}
|
|
560
|
+
interface CardPosition {
|
|
561
|
+
x: number;
|
|
562
|
+
y: number;
|
|
563
|
+
side: Side;
|
|
564
|
+
/** Arrow centre along the card edge facing the target (px from the card's left/top). */
|
|
565
|
+
arrow: number;
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Places a card of `size` next to `target` inside `viewport` minus `insets`, honouring the step's
|
|
569
|
+
* placement when it fits and flipping (then falling back to below/above) when it does not.
|
|
570
|
+
*/
|
|
571
|
+
declare function positionCard(target: Rect, size: {
|
|
572
|
+
width: number;
|
|
573
|
+
height: number;
|
|
574
|
+
}, viewport: {
|
|
575
|
+
width: number;
|
|
576
|
+
height: number;
|
|
577
|
+
}, insets: Insets, placement: Placement, offset: number): CardPosition;
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* Declares which screen its children are on, so targets on screens that are mounted but not
|
|
581
|
+
* visible (inactive tabs, screens under a stack) are never used. `name` must match what you pass
|
|
582
|
+
* to `screen()`. With React Navigation, use {@link guidelyScreenLayout} instead of wrapping by hand.
|
|
583
|
+
*/
|
|
584
|
+
declare function GuidelyScreenScope({ name, children }: {
|
|
585
|
+
name: string;
|
|
586
|
+
children?: ReactNode;
|
|
587
|
+
}): react.JSX.Element;
|
|
588
|
+
/**
|
|
589
|
+
* React Navigation 7 `screenLayout`: scopes every screen of a navigator to its route name.
|
|
590
|
+
* `<Tab.Navigator screenLayout={guidelyScreenLayout}>`.
|
|
591
|
+
*/
|
|
592
|
+
declare function guidelyScreenLayout({ route, children }: {
|
|
593
|
+
route: {
|
|
594
|
+
name: string;
|
|
595
|
+
};
|
|
596
|
+
children: ReactNode;
|
|
597
|
+
}): react.JSX.Element;
|
|
598
|
+
/**
|
|
599
|
+
* Props to spread on an existing view so guides can point at it, without adding a wrapper:
|
|
600
|
+
* `const target = useGuidelyTarget("new-deal-button"); <Pressable {...target}>…</Pressable>`.
|
|
601
|
+
* Taps are observed, never intercepted.
|
|
602
|
+
*/
|
|
603
|
+
declare function useGuidelyTarget(id: string): {
|
|
604
|
+
ref: react.RefObject<View | null>;
|
|
605
|
+
collapsable: false;
|
|
606
|
+
onLayout: () => void | undefined;
|
|
607
|
+
onTouchStart: (e: GestureResponderEvent) => void;
|
|
608
|
+
onTouchEnd: (e: GestureResponderEvent) => void;
|
|
609
|
+
};
|
|
610
|
+
interface GuidelyTargetProps extends ViewProps {
|
|
611
|
+
/** The Guidely id guides use to find this view (`data-guidely-id` on the web). */
|
|
612
|
+
id: string;
|
|
613
|
+
children?: ReactNode;
|
|
614
|
+
style?: StyleProp<ViewStyle>;
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Marks a view as a guide target. Wraps children in a `View`; give it `style={{ alignSelf: "flex-start" }}`
|
|
618
|
+
* (or use {@link useGuidelyTarget}) when the wrapper should not stretch to its parent's width.
|
|
619
|
+
*/
|
|
620
|
+
declare function GuidelyTarget({ id, children, onLayout, onTouchStart, onTouchEnd, ...rest }: GuidelyTargetProps): react.JSX.Element;
|
|
621
|
+
|
|
622
|
+
interface OverlayProps {
|
|
623
|
+
client: GuidelyClient;
|
|
624
|
+
insets?: Partial<Insets>;
|
|
625
|
+
/** Distance of the checklist launcher above the bottom inset (clears tab bars). */
|
|
626
|
+
launcherOffset: number;
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Draws everything the client wants on screen, above the app. `pointerEvents="box-none"` keeps the
|
|
630
|
+
* app fully interactive except where guide UI (or a modal backdrop) is shown.
|
|
631
|
+
*/
|
|
632
|
+
declare function GuidelyOverlay({ client, insets: insetsProp, launcherOffset }: OverlayProps): react.JSX.Element;
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Tiny, tolerant HTML → rich-text converter for guide bodies (already sanitized server-side).
|
|
636
|
+
* Supports p, div, br, strong/b, em/i, u, a, code, ul/ol/li, h1–h6 and blockquote; every other tag
|
|
637
|
+
* is reduced to its text. Output is plain data so it can be unit-tested without React Native.
|
|
638
|
+
*/
|
|
639
|
+
interface TextRun {
|
|
640
|
+
text: string;
|
|
641
|
+
bold?: boolean;
|
|
642
|
+
italic?: boolean;
|
|
643
|
+
underline?: boolean;
|
|
644
|
+
code?: boolean;
|
|
645
|
+
href?: string;
|
|
646
|
+
}
|
|
647
|
+
interface TextBlock {
|
|
648
|
+
kind: "paragraph" | "heading" | "list-item" | "quote";
|
|
649
|
+
/** Heading level 1–3, list nesting depth from 1. */
|
|
650
|
+
level: number;
|
|
651
|
+
/** For list items: the bullet ("•") or number ("1.") to show. */
|
|
652
|
+
marker?: string;
|
|
653
|
+
runs: TextRun[];
|
|
654
|
+
}
|
|
655
|
+
declare function parseHtml(html: string): TextBlock[];
|
|
656
|
+
/** Plain-text rendering of an HTML body (accessibility labels, previews). */
|
|
657
|
+
declare function htmlToText(html: string): string;
|
|
658
|
+
|
|
659
|
+
interface GuidelyProviderProps extends Omit<GuidelyOptions, "user"> {
|
|
660
|
+
/** Identify this user once the client is ready; changing to `null` resets the identity (logout). */
|
|
661
|
+
user?: GuidelyUser | null;
|
|
662
|
+
/** Safe-area insets for banners, launchers and sheets. Pass `useSafeAreaInsets()` from react-native-safe-area-context for exact values. */
|
|
663
|
+
insets?: Partial<Insets>;
|
|
664
|
+
/** How far above the bottom inset the checklist launcher sits, to clear tab bars (default 72). */
|
|
665
|
+
launcherOffset?: number;
|
|
666
|
+
children?: ReactNode;
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Creates one Guidely client for the app and renders guide UI above `children`. Place it at the
|
|
670
|
+
* root of the app (outside navigators) so the overlay covers every screen.
|
|
671
|
+
*/
|
|
672
|
+
declare function GuidelyProvider({ children, user, insets, launcherOffset, ...options }: GuidelyProviderProps): react.JSX.Element;
|
|
673
|
+
/** A client that ignores every call; returned by `useGuidely()` before the provider has created one. */
|
|
674
|
+
declare const noopClient: GuidelyClient;
|
|
675
|
+
/** The Guidely client (a no-op stand-in until the provider has created it). */
|
|
676
|
+
declare function useGuidely(): GuidelyClient;
|
|
677
|
+
/** True once config is loaded and triggers have been evaluated. */
|
|
678
|
+
declare function useGuidelyReady(): boolean;
|
|
679
|
+
/** Identifies the user whenever the id or traits change. */
|
|
680
|
+
declare function useGuidelyIdentify(userId: string | null | undefined, traits?: Record<string, unknown>, account?: GuidelyAccount): void;
|
|
681
|
+
/** Subscribes to a Guidely event for the lifetime of the component. */
|
|
682
|
+
declare function useGuidelyEvent<K extends keyof GuidelyEvents>(event: K, handler: GuidelyEvents[K]): void;
|
|
683
|
+
/** Records a screen view while the component is mounted (and when `name` changes). */
|
|
684
|
+
declare function useGuidelyScreen(name: string | null | undefined, properties?: Record<string, unknown>): void;
|
|
685
|
+
interface NavigationRefLike {
|
|
686
|
+
getCurrentRoute(): {
|
|
687
|
+
name: string;
|
|
688
|
+
} | undefined | null;
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* React Navigation integration: spread the result on `<NavigationContainer>` and every route
|
|
692
|
+
* change becomes a Guidely screen view named after the route.
|
|
693
|
+
*
|
|
694
|
+
* ```tsx
|
|
695
|
+
* const ref = useNavigationContainerRef();
|
|
696
|
+
* <NavigationContainer ref={ref} {...useGuidelyNavigation(ref)}>
|
|
697
|
+
* ```
|
|
698
|
+
*/
|
|
699
|
+
declare function useGuidelyNavigation(navigationRef: NavigationRefLike, options?: {
|
|
700
|
+
screenName?: (route: {
|
|
701
|
+
name: string;
|
|
702
|
+
}) => string;
|
|
703
|
+
}): {
|
|
704
|
+
onReady: () => void;
|
|
705
|
+
onStateChange: () => void;
|
|
706
|
+
};
|
|
707
|
+
/** Live progress of a checklist guide (by id or key). */
|
|
708
|
+
declare function useChecklistProgress(idOrKey: string): ChecklistProgressState;
|
|
709
|
+
/** Live impressions / completion / dismissal of a guide (by id or key). */
|
|
710
|
+
declare function useGuideState(idOrKey: string): {
|
|
711
|
+
impressions: number;
|
|
712
|
+
completed: boolean;
|
|
713
|
+
dismissed: boolean;
|
|
714
|
+
};
|
|
715
|
+
/** The guide currently running exclusively (flow, modal, survey…), or null. */
|
|
716
|
+
declare function useActiveGuide(): PublishedGuide | null;
|
|
717
|
+
|
|
718
|
+
export { type ChecklistView, DEFAULT_API_URL, type DeviceEnvironment, type GuideStepInfo, GuidelyClient, type GuidelyEventName, type GuidelyEvents, type GuidelyOptions, GuidelyOverlay, GuidelyProvider, type GuidelyProviderProps, GuidelyScreenScope, type GuidelyStorage, GuidelyTarget, type GuidelyTargetProps, type Insets, Messenger, type MessengerSnapshot, type MessengerTab, type MessengerThread, type MessengerView, type PlatformBridge, SDK_NAME, SDK_VERSION, type StepView, type SurveyView, TargetRegistry, type UiState, createSseParser, guidelyScreenLayout, htmlToText, noopClient, parseHtml, positionCard, targetIdsFor, useActiveGuide, useChecklistProgress, useGuideState, useGuidely, useGuidelyEvent, useGuidelyIdentify, useGuidelyNavigation, useGuidelyReady, useGuidelyScreen, useGuidelyTarget };
|