@firstflow/react 0.0.1 → 0.0.101

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
@@ -1,283 +1,124 @@
1
+ import { R as RawIssuesConfig, a as RawFeedbackConfig, E as ExperienceSettings, U as UserContext, A as AudienceMembershipMap, S as SurveySubmitPayload, b as SurveyQuestion, c as SurveyAnswerValue, d as SurveyModulePublic, F as FirstflowInstance$1, C as CreateFirstflowOptions } from './events-DAiGBrYc.mjs';
2
+ export { e as AnalyticsModulePublic, f as AudienceConfig, g as AudienceRule, h as CHAT_MESSAGE_SENT, i as EXPERIENCE_ANALYTICS_TYPE, j as EXPERIENCE_CLICKED, k as EXPERIENCE_SHOWN, l as FirstflowWidgetUi, m as RuleOperator, n as SURVEY_COMPLETED, o as SurveyExperience } from './events-DAiGBrYc.mjs';
1
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
4
  import React, { ReactNode } from 'react';
3
5
 
4
- interface CreateFirstflowOptions {
5
- agentId: string;
6
- apiUrl: string;
7
- /** Jitsu host for analytics; defaults to shared Firstflow Jitsu if omitted */
8
- jitsuHost?: string;
9
- /** Jitsu write key for analytics; defaults to shared key if omitted */
10
- jitsuWriteKey?: string;
11
- /** When set without fetchConfig, seeds message feedback UI (agents.feedback_config shape). */
12
- feedbackConfig?: RawFeedbackConfig | null;
13
- }
14
- /**
15
- * Public API for the issue module only (open, submit, getConfig, destroy).
16
- * Internal wiring (setConfig, setOpenHandler) is not exposed.
17
- */
18
- interface IssueModulePublic {
19
- open(options?: OpenOptions): void;
20
- submit(data: IssueReportData): Promise<void>;
21
- getConfig(): NormalizedConfig;
22
- destroy(): void;
23
- }
24
- /** Analytics API exposed on the platform instance. Used by all feature modules. */
25
- interface AnalyticsModulePublic {
26
- track(eventName: string, properties?: Record<string, unknown>): void;
27
- identify(userId?: string, traits?: Record<string, unknown>): void;
28
- page(name?: string, properties?: Record<string, unknown>): void;
29
- }
30
- /**
31
- * Root platform instance: agent identity, analytics, and feature modules.
32
- * Represents the runtime context for this agent at this API.
33
- */
34
- interface FirstflowInstance {
35
- readonly agentId: string;
36
- readonly apiUrl: string;
37
- analytics: AnalyticsModulePublic;
38
- issue: IssueModulePublic;
39
- feedback: FeedbackModulePublic;
40
- }
41
- /**
42
- * Raw issues config as received from API (e.g. agent.issues_config).
43
- */
44
- interface RawIssueFieldConfig {
45
- id?: string;
46
- allowed?: boolean;
47
- label?: string;
48
- type?: "text" | "textarea" | "select";
49
- required?: boolean;
50
- options?: string[];
51
- }
52
- interface RawIssuesConfig {
53
- enabled?: boolean;
54
- promptText?: string;
55
- fields?: RawIssueFieldConfig[];
56
- }
57
- interface RawFeedbackFormConfig {
58
- tags?: string[];
59
- heading?: string;
60
- placeholder?: string;
61
- showTags?: boolean;
62
- showComment?: boolean;
63
- }
64
- interface RawFeedbackConfig {
65
- enabled?: boolean;
66
- like?: RawFeedbackFormConfig;
67
- dislike?: RawFeedbackFormConfig;
68
- }
69
- interface NormalizedFeedbackFormConfig {
70
- tags: string[];
71
- heading: string;
72
- placeholder: string;
73
- showTags: boolean;
74
- showComment: boolean;
75
- }
76
- interface NormalizedFeedbackConfig {
77
- enabled: boolean;
78
- like: NormalizedFeedbackFormConfig;
79
- dislike: NormalizedFeedbackFormConfig;
80
- }
81
- interface MessageFeedbackSubmitPayload {
82
- conversationId: string;
83
- messageId: string;
84
- rating: "like" | "dislike";
85
- /** Used by MessageFeedback UI only; not included on the Jitsu event. */
86
- tags?: string[];
87
- comment?: string;
88
- /** Mirrors config: whether tags/comment were enabled for this sentiment at submit time. */
89
- showTags?: boolean;
90
- showComment?: boolean;
91
- messagePreview?: string;
92
- /**
93
- * Arbitrary JSON-serializable key/value bag (e.g. locale, page_url, model, experiment_id).
94
- * Sent on the Jitsu event as property `metadata` after JSON round-trip (max ~32KB serialized).
95
- */
96
- metadata?: Record<string, unknown>;
97
- }
98
- interface FeedbackModulePublic {
99
- submit(payload: MessageFeedbackSubmitPayload): Promise<void>;
100
- getConfig(): NormalizedFeedbackConfig;
101
- isEnabled(): boolean;
102
- }
103
6
  /**
104
- * Normalized field config used internally (after filtering allowed, defaulting type/label).
7
+ * Runtime flow returned by `GET /agents/:id/config` (`flow` on each experience).
8
+ * Editor-only fields (viewport, measured, positions, React Flow styles) are omitted server-side.
105
9
  */
106
- interface NormalizedFieldConfig {
10
+ type SdkRuntimeFlowNode = {
107
11
  id: string;
108
- type: "text" | "textarea" | "select";
109
- label: string;
110
- required: boolean;
111
- options?: string[];
112
- }
113
- /**
114
- * Normalized config: single source of truth for the SDK.
115
- */
116
- interface NormalizedConfig {
117
- agentId: string;
118
- apiUrl: string;
119
- enabled: boolean;
120
- promptText: string;
121
- fields: NormalizedFieldConfig[];
122
- }
123
- /**
124
- * Form field values only (keys = field ids). Validated before submit.
125
- * Validation applies to this only.
126
- */
127
- type IssueFormValues = Record<string, string | undefined>;
128
- /**
129
- * Context metadata: set programmatically (e.g. open({ messageId })). Never validated.
130
- * Merged with form values at submit time. Users can add arbitrary JSON-serializable keys/values.
131
- */
132
- type IssueContextMetadata = {
133
- conversationId?: string;
134
- messageId?: string;
135
- sessionId?: string;
136
- agentId?: string;
137
- model?: string;
138
- } & Record<string, unknown>;
139
- /**
140
- * Options passed to open() (e.g. "Report this response").
141
- */
142
- type OpenOptions = IssueContextMetadata;
143
- /**
144
- * Final submission payload: form values + context metadata. Sent to transport.
145
- * Values can be primitives (form fields) or arbitrary JSON-serializable metadata.
146
- */
147
- type IssuePayload = Record<string, unknown>;
148
- /**
149
- * Options for createIssueReporter. Config is optional; when omitted, defaults are used.
150
- * When analytics is omitted, a default analytics instance is created (same Jitsu config).
151
- */
152
- interface CreateIssueReporterOptions {
153
- agentId: string;
154
- apiUrl: string;
155
- config?: Partial<RawIssuesConfig>;
156
- /** Platform analytics; issue module calls analytics.track('issue_submitted', payload). Defaults to createAnalytics({ agentId }) when omitted. */
157
- analytics?: AnalyticsModulePublic;
158
- }
159
- /**
160
- * Validation result.
161
- */
162
- interface ValidationResult {
163
- valid: boolean;
164
- errors?: Record<string, string>;
165
- }
166
- type IssueReportData = Record<string, unknown>;
167
- /**
168
- * Instance returned by createIssueReporter.
169
- * setConfig is used internally when config is loaded asynchronously (e.g. via useCreateFirstflow + fetchConfig).
170
- */
171
- interface IssueReporterInstance {
172
- getConfig(): NormalizedConfig;
173
- setConfig(config: NormalizedConfig): void;
174
- reportIssue(data: IssueReportData): Promise<void>;
175
- open(options?: OpenOptions): void;
176
- setOpenHandler(handler: ((options?: OpenOptions) => void) | undefined): void;
177
- destroy(): void;
178
- }
179
-
180
- /**
181
- * Platform event names. Feature modules use these when calling analytics.track().
182
- * Do not rename existing events (e.g. issue_submitted) to avoid breaking pipelines.
183
- */
184
- /** Issue module — backward compatible */
185
- declare const ISSUE_SUBMITTED = "issue_submitted";
186
- /** Future modules */
187
- declare const FEEDBACK_SUBMITTED = "feedback_submitted";
188
- declare const SURVEY_COMPLETED = "survey_completed";
189
- declare const EXPERIENCE_SHOWN = "experience_shown";
190
- declare const EXPERIENCE_CLICKED = "experience_clicked";
191
- declare const CHAT_MESSAGE_SENT = "chat_message_sent";
192
-
193
- declare function createFirstflow(options: CreateFirstflowOptions): FirstflowInstance;
194
-
12
+ type?: string;
13
+ data?: Record<string, unknown>;
14
+ };
15
+ type SdkRuntimeFlowEdge = {
16
+ id?: string;
17
+ source: string;
18
+ target: string;
19
+ };
20
+ type SdkRuntimeFlow = {
21
+ nodes: SdkRuntimeFlowNode[];
22
+ edges: SdkRuntimeFlowEdge[];
23
+ };
195
24
  /** Active experience row as returned on public agent config (subset of DB). */
196
25
  type SdkAgentConfigExperience = {
197
26
  id?: string;
198
27
  name?: string | null;
199
28
  status?: string | null;
200
- flow?: {
201
- nodes?: unknown[];
202
- edges?: unknown[];
203
- } | null;
29
+ type?: string | null;
30
+ flow?: SdkRuntimeFlow | null;
31
+ settings?: ExperienceSettings | null;
32
+ };
33
+ /** Optional widget branding from the agent record (public config). */
34
+ type SdkAgentWidgetUi = {
35
+ /** Hex (or CSS color) used for announcement CTAs / accents when set. */
36
+ primaryColor?: string;
204
37
  };
205
38
  type SdkAgentConfigPayload = {
206
39
  issues_config?: RawIssuesConfig;
207
40
  feedback_config?: RawFeedbackConfig;
208
- /** Active experiences including saved flow (nodes/edges from canvas). */
41
+ /** Active experiences with runtime flow graphs (SDK-safe shape). */
209
42
  experiences?: SdkAgentConfigExperience[];
43
+ /** From `agent.widget_ui` or top-level `primary_color` when present. */
44
+ widget_ui?: SdkAgentWidgetUi | null;
210
45
  };
211
- declare function fetchSdkAgentConfig(apiUrl: string, agentId: string): Promise<SdkAgentConfigPayload>;
46
+ declare function fetchSdkAgentConfig(apiUrl: string, agentId: string, apiKey?: string): Promise<SdkAgentConfigPayload>;
212
47
 
213
48
  type FirstflowProviderProps = {
214
- firstflow: FirstflowInstance;
49
+ agentId: string;
50
+ apiKey?: string;
215
51
  children: ReactNode;
216
- /** Optional payload from `fetchSdkAgentConfig` / `useCreateFirstflow` (issues, feedback, experiences). */
217
- config?: SdkAgentConfigPayload | null;
52
+ fallback?: ReactNode;
53
+ onError?: (error: Error) => void;
54
+ initialSdkPayload?: SdkAgentConfigPayload | null;
55
+ user?: UserContext | null;
56
+ audienceMembership?: AudienceMembershipMap;
57
+ autoFetchAudienceMembership?: boolean;
218
58
  };
219
- /**
220
- * Provides the platform instance to the tree. Transitional: delegates to
221
- * IssueReporterProvider with the internal issue instance so that
222
- * firstflow.issue.open() opens the modal. This is a migration/composition step;
223
- * the final architecture may use a single provider for multiple feature modules.
224
- */
225
- declare function FirstflowProvider({ firstflow, children, config }: FirstflowProviderProps): react_jsx_runtime.JSX.Element;
226
- declare function useFirstflow(): FirstflowInstance;
227
- /** SDK agent config (including `experiences`) when passed to `FirstflowProvider`; otherwise null. */
228
- declare function useFirstflowConfig(): SdkAgentConfigPayload | null;
59
+ declare function FirstflowProvider({ agentId, apiKey, children, fallback, onError, initialSdkPayload, user, audienceMembership, autoFetchAudienceMembership, }: FirstflowProviderProps): react_jsx_runtime.JSX.Element;
229
60
 
230
- type UseCreateFirstflowOptions = {
231
- fetchConfig?: boolean;
61
+ type AudienceOverrides = {
62
+ blockedExperiences: string[];
63
+ forcedExperiences: string[];
232
64
  };
233
- type UseCreateFirstflowResult = {
234
- firstflow: FirstflowInstance | null;
235
- loading: boolean;
236
- error: Error | null;
237
- /** Full SDK config from `GET /agents/:id/config` when `fetchConfig: true`; otherwise null. */
238
- config: SdkAgentConfigPayload | null;
65
+
66
+ type NormalizedExperienceRow = {
67
+ experienceId: string;
68
+ name?: string | null;
69
+ status: string | null;
70
+ type?: string | null;
71
+ settings?: ExperienceSettings | null;
72
+ flow?: {
73
+ nodes?: unknown[];
74
+ edges?: unknown[];
75
+ } | null;
76
+ };
77
+
78
+ type FirstflowRuntimeSnapshot = {
79
+ version: number;
80
+ user: UserContext | null;
81
+ audienceMembership: AudienceMembershipMap;
82
+ overrides: AudienceOverrides;
83
+ experienceRows: NormalizedExperienceRow[];
239
84
  };
240
- declare function useCreateFirstflow(agentId: string, apiUrl: string, options?: UseCreateFirstflowOptions): UseCreateFirstflowResult;
241
85
 
242
- type UseFeedbackMessageResult = {
243
- rating: 'like' | 'dislike' | null;
244
- selectedTags: string[];
245
- comment: string;
86
+ declare function useFirstflowSelector<T>(selector: (snapshot: FirstflowRuntimeSnapshot) => T): T;
87
+
88
+ type UseFirstflowSurveyOptions = {
89
+ experienceId: string;
90
+ conversationId?: string;
91
+ metadata?: Record<string, unknown>;
92
+ mapSubmit?: (payload: SurveySubmitPayload) => SurveySubmitPayload;
93
+ };
94
+ type UseFirstflowSurveyResult = {
95
+ surveyId: string;
96
+ questions: SurveyQuestion[];
97
+ currentIndex: number;
98
+ currentQuestion: SurveyQuestion | null;
99
+ answers: Record<string, SurveyAnswerValue>;
100
+ setAnswer: (questionId: string, value: SurveyAnswerValue) => void;
101
+ next: () => void;
102
+ prev: () => void;
103
+ goTo: (index: number) => void;
104
+ canSubmit: boolean;
105
+ isEnabled: boolean;
246
106
  submitting: boolean;
247
107
  submitted: boolean;
248
108
  error: string | null;
249
- setRating: (r: 'like' | 'dislike') => void;
250
- toggleTag: (tag: string) => void;
251
- setComment: (c: string) => void;
252
109
  submit: () => Promise<void>;
253
110
  clearError: () => void;
254
- isEnabled: boolean;
255
- config: NormalizedFeedbackConfig | null;
256
- sideConfig: NormalizedFeedbackFormConfig | null;
257
111
  };
258
- type UseFeedbackMessageOptions = {
259
- conversationId: string;
260
- messageId: string;
261
- messagePreview: string;
262
- metadata?: Record<string, unknown>;
263
- };
264
- /**
265
- * **Module mode** — `useFeedback()`
266
- * Returns `firstflow.feedback`: programmatic `submit(payload)`, `getConfig()`, `isEnabled()` (e.g. Thread slot, one-off submits).
267
- *
268
- * **Message mode** — `useFeedback({ conversationId, messageId, messagePreview, metadata? })`
269
- * Headless per-message state: rating, tags, comment, `submit()`, localStorage.
270
- */
271
- declare function useFeedback(): FeedbackModulePublic;
272
- declare function useFeedback(options: UseFeedbackMessageOptions): UseFeedbackMessageResult;
112
+ declare function useFirstflowSurvey(): SurveyModulePublic;
113
+ declare function useFirstflowSurvey(options: UseFirstflowSurveyOptions): UseFirstflowSurveyResult;
114
+
115
+ declare function useExperienceEligibility(experienceId: string): boolean;
273
116
 
274
117
  /**
275
118
  * Runtime types for experience "Message" flow nodes (aligned with dashboard CardData.config).
276
119
  * @see blocksVersion — increment when block union or order semantics change.
277
120
  */
278
- type FlowMessageStyle = 'message'
279
- /** @deprecated Dashboard now saves `message`; kept for older flows */
280
- | 'inline' | 'card' | 'carousel' | 'quick_replies' | 'rich_card';
121
+ type FlowMessageStyle = 'message' | 'inline' | 'card' | 'carousel' | 'quick_replies' | 'rich_card';
281
122
  /** Canonical style for analytics / UI (`inline` → `message`). */
282
123
  declare function normalizeFlowMessageStyle(style: FlowMessageStyle | undefined): FlowMessageStyle | undefined;
283
124
  type FlowMessageCtaType = 'none' | 'button' | 'link' | 'dismiss' | 'button_dismiss';
@@ -288,6 +129,18 @@ type FlowQuickReplyItem = {
288
129
  };
289
130
  declare function normalizeFlowQuickReplyItem(entry: unknown): FlowQuickReplyItem;
290
131
  declare function normalizeFlowQuickReplyList(raw: unknown): FlowQuickReplyItem[];
132
+ /** Optional pills above the title (future dashboard or custom JSON). */
133
+ type FlowRichCardTag = {
134
+ label: string;
135
+ bg?: string;
136
+ color?: string;
137
+ };
138
+ /** Optional meta row under the description (e.g. date, duration). */
139
+ type FlowRichCardMetaItem = {
140
+ label: string;
141
+ icon?: string;
142
+ };
143
+ type FlowRichCardMediaType = 'image' | 'emoji';
291
144
  type FlowCarouselCard = {
292
145
  id: string;
293
146
  title: string;
@@ -319,6 +172,16 @@ type FlowMessageNodeConfig = {
319
172
  /** Legacy flows may use `string[]`; normalize with `normalizeFlowQuickReplyList`. */
320
173
  quickReplies?: Array<string | FlowQuickReplyItem>;
321
174
  carouselCards?: FlowCarouselCard[];
175
+ /** Rich card: hero image URL (http/https). */
176
+ richCardImageUrl?: string;
177
+ /** Rich card: headline (defaults to first line of `messageContent`). */
178
+ richCardTitle?: string;
179
+ /** Rich card: hero mode — `image` uses URL when valid; `emoji` uses placeholder with `richCardEmoji`. */
180
+ richCardMediaType?: FlowRichCardMediaType;
181
+ /** Rich card: shown in hero when there is no image or media type is `emoji`. */
182
+ richCardEmoji?: string;
183
+ richCardTags?: FlowRichCardTag[];
184
+ richCardMeta?: FlowRichCardMetaItem[];
322
185
  };
323
186
  type ExperienceMessageBlock = {
324
187
  type: 'text';
@@ -388,6 +251,14 @@ type ExperienceMessageUi = {
388
251
  */
389
252
  declare function buildExperienceMessageBlocks(config: FlowMessageNodeConfig): ExperienceMessageBlock[];
390
253
  declare function buildExperienceMessageUi(blocks: ExperienceMessageBlock[], messageStyle: FlowMessageStyle | undefined): ExperienceMessageUi;
254
+ /**
255
+ * Returns a safe http(s) URL for rich-card images, or `undefined` if invalid.
256
+ */
257
+ declare function tryParseHttpImageUrl(raw: string | undefined): string | undefined;
258
+ /**
259
+ * Coerces dashboard / runtime JSON into `FlowMessageNodeConfig` for slot rendering and hooks.
260
+ */
261
+ declare function parseFlowMessageNodeConfig(raw: Record<string, unknown>): FlowMessageNodeConfig;
391
262
  /**
392
263
  * Builds the `carousel_cta` action payload from node config (prompt vs link per button).
393
264
  * Host apps should open `linkUrl` or send `promptText` / `label` as the user message — same rules as the dashboard preview.
@@ -396,6 +267,121 @@ declare function buildExperienceCarouselCtaAction(config: FlowMessageNodeConfig,
396
267
  kind: 'carousel_cta';
397
268
  }>;
398
269
 
270
+ /**
271
+ * Runtime types for experience "Announcement" flow nodes (aligned with dashboard CardData.config).
272
+ * @see blocksVersion — increment when content/ui semantics change.
273
+ */
274
+ type FlowAnnouncementStyle = 'chat_bubble' | 'card' | 'banner' | 'tooltip' | 'spotlight';
275
+ type FlowAnnouncementTheme = 'info' | 'success' | 'warning' | 'promo' | 'neutral';
276
+ type FlowAnnouncementPosition = 'top' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center';
277
+ type FlowAnnouncementNodeConfig = {
278
+ announcementStyle?: FlowAnnouncementStyle;
279
+ announcementTheme?: FlowAnnouncementTheme;
280
+ announcementTitle?: string;
281
+ announcementBody?: string;
282
+ announcementEmoji?: string;
283
+ /** Hero image (http/https); when absent, emoji placeholder is used. */
284
+ announcementImageUrl?: string;
285
+ /** Optional pill label (e.g. “What’s new”); defaults from theme when empty. */
286
+ announcementBadge?: string;
287
+ /** Small icon/emoji before badge text (e.g. ★). */
288
+ announcementBadgeIcon?: string;
289
+ ctaText?: string;
290
+ ctaUrl?: string;
291
+ announcementDismissible?: boolean;
292
+ announcementAutoHide?: boolean;
293
+ announcementAutoHideDelay?: number;
294
+ announcementPosition?: FlowAnnouncementPosition;
295
+ };
296
+ type ExperienceAnnouncementAction = {
297
+ kind: 'cta_click';
298
+ label: string;
299
+ url?: string;
300
+ } | {
301
+ kind: 'dismiss';
302
+ } | {
303
+ kind: 'auto_hidden';
304
+ };
305
+ /** Maps action kind → analytics `action` property (single source of truth). */
306
+ declare const EXPERIENCE_ANNOUNCEMENT_ANALYTICS_ACTION: Record<ExperienceAnnouncementAction['kind'], string>;
307
+ declare const EXPERIENCE_ANNOUNCEMENT_BLOCKS_VERSION: 1;
308
+ /** Trimmed display fields; omit keys when empty. */
309
+ type ExperienceAnnouncementContent = {
310
+ title?: string;
311
+ body?: string;
312
+ emoji?: string;
313
+ ctaLabel?: string;
314
+ ctaUrl?: string;
315
+ };
316
+ type ExperienceAnnouncementUi = {
317
+ hasTitle: boolean;
318
+ hasBody: boolean;
319
+ hasEmoji: boolean;
320
+ hasCta: boolean;
321
+ isDismissible: boolean;
322
+ autoHide: boolean;
323
+ autoHideDelay: number;
324
+ position: FlowAnnouncementPosition | undefined;
325
+ style: FlowAnnouncementStyle | undefined;
326
+ theme: FlowAnnouncementTheme | undefined;
327
+ };
328
+ /**
329
+ * Maps raw dashboard/API config to a safe `FlowAnnouncementNodeConfig`.
330
+ */
331
+ declare function normalizeFlowAnnouncementNodeConfig(raw: Record<string, unknown> | FlowAnnouncementNodeConfig | undefined | null): FlowAnnouncementNodeConfig;
332
+ declare function buildExperienceAnnouncementContent(config: FlowAnnouncementNodeConfig): ExperienceAnnouncementContent;
333
+ declare function buildExperienceAnnouncementUi(config: FlowAnnouncementNodeConfig, content: ExperienceAnnouncementContent): ExperienceAnnouncementUi;
334
+
335
+ type SlotCandidateType = 'survey' | 'message' | 'announcement';
336
+ type SlotCandidateSurvey = {
337
+ type: 'survey';
338
+ experienceId: string;
339
+ settings: ExperienceSettings | null;
340
+ };
341
+ type SlotTourMessageStep = {
342
+ nodeId: string;
343
+ config: Record<string, unknown>;
344
+ };
345
+ type SlotCandidateMessage = {
346
+ type: 'message';
347
+ experienceId: string;
348
+ nodeId: string;
349
+ config: Record<string, unknown>;
350
+ settings: ExperienceSettings | null;
351
+ /** Tour flows: walk these in order before the slot marks the experience consumed. */
352
+ tourSteps?: SlotTourMessageStep[];
353
+ };
354
+ type SlotCandidateAnnouncement = {
355
+ type: 'announcement';
356
+ experienceId: string;
357
+ nodeId: string;
358
+ config: Record<string, unknown>;
359
+ settings: ExperienceSettings | null;
360
+ };
361
+ type NormalizedSlotCandidate = SlotCandidateSurvey | SlotCandidateMessage | SlotCandidateAnnouncement;
362
+ /** Matches survey/card theming (`light` / `dark` / system `auto`). */
363
+ type ExperienceSlotAppearance = 'light' | 'dark' | 'auto';
364
+ /** Props for `ExperienceSlot` (implementation typically under `src/components`). */
365
+ type ExperienceSlotProps = {
366
+ mode?: 'single' | 'queue';
367
+ typeFilter?: SlotCandidateType[];
368
+ conversationId?: string;
369
+ metadata?: Record<string, unknown>;
370
+ showInlineFeedback?: boolean;
371
+ onShow?: (experienceId: string, type: SlotCandidateType) => void;
372
+ onQueueEmpty?: () => void;
373
+ renderCandidate?: (candidate: NormalizedSlotCandidate, advance: () => void) => ReactNode;
374
+ className?: string;
375
+ /** Applied to `Survey` and message card experiences. */
376
+ appearance?: ExperienceSlotAppearance;
377
+ /** Fired for message card CTAs after internal analytics; use for chat prompts or host UX. */
378
+ onExperienceMessageAction?: (action: ExperienceMessageAction) => void;
379
+ /** Fired for announcement actions after internal analytics. */
380
+ onExperienceAnnouncementAction?: (action: ExperienceAnnouncementAction) => void;
381
+ };
382
+
383
+ declare function useFirstflowResolveExperience(experienceId: string): NormalizedSlotCandidate | null;
384
+
399
385
  type UseExperienceMessageNodeOptions = {
400
386
  config: FlowMessageNodeConfig;
401
387
  nodeId: string;
@@ -464,65 +450,6 @@ type UseExperienceMessageNodeResult = {
464
450
  */
465
451
  declare function useExperienceMessageNode(options: UseExperienceMessageNodeOptions): UseExperienceMessageNodeResult;
466
452
 
467
- /**
468
- * Runtime types for experience "Announcement" flow nodes (aligned with dashboard CardData.config).
469
- * @see blocksVersion — increment when content/ui semantics change.
470
- */
471
- type FlowAnnouncementStyle = 'chat_bubble' | 'card' | 'banner' | 'tooltip' | 'spotlight';
472
- type FlowAnnouncementTheme = 'info' | 'success' | 'warning' | 'promo' | 'neutral';
473
- type FlowAnnouncementPosition = 'top' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center';
474
- type FlowAnnouncementNodeConfig = {
475
- announcementStyle?: FlowAnnouncementStyle;
476
- announcementTheme?: FlowAnnouncementTheme;
477
- announcementTitle?: string;
478
- announcementBody?: string;
479
- announcementEmoji?: string;
480
- ctaText?: string;
481
- ctaUrl?: string;
482
- announcementDismissible?: boolean;
483
- announcementAutoHide?: boolean;
484
- announcementAutoHideDelay?: number;
485
- announcementPosition?: FlowAnnouncementPosition;
486
- };
487
- type ExperienceAnnouncementAction = {
488
- kind: 'cta_click';
489
- label: string;
490
- url?: string;
491
- } | {
492
- kind: 'dismiss';
493
- } | {
494
- kind: 'auto_hidden';
495
- };
496
- /** Maps action kind → analytics `action` property (single source of truth). */
497
- declare const EXPERIENCE_ANNOUNCEMENT_ANALYTICS_ACTION: Record<ExperienceAnnouncementAction['kind'], string>;
498
- declare const EXPERIENCE_ANNOUNCEMENT_BLOCKS_VERSION: 1;
499
- /** Trimmed display fields; omit keys when empty. */
500
- type ExperienceAnnouncementContent = {
501
- title?: string;
502
- body?: string;
503
- emoji?: string;
504
- ctaLabel?: string;
505
- ctaUrl?: string;
506
- };
507
- type ExperienceAnnouncementUi = {
508
- hasTitle: boolean;
509
- hasBody: boolean;
510
- hasEmoji: boolean;
511
- hasCta: boolean;
512
- isDismissible: boolean;
513
- autoHide: boolean;
514
- autoHideDelay: number;
515
- position: FlowAnnouncementPosition | undefined;
516
- style: FlowAnnouncementStyle | undefined;
517
- theme: FlowAnnouncementTheme | undefined;
518
- };
519
- /**
520
- * Maps raw dashboard/API config to a safe `FlowAnnouncementNodeConfig`.
521
- */
522
- declare function normalizeFlowAnnouncementNodeConfig(raw: Record<string, unknown> | FlowAnnouncementNodeConfig | undefined | null): FlowAnnouncementNodeConfig;
523
- declare function buildExperienceAnnouncementContent(config: FlowAnnouncementNodeConfig): ExperienceAnnouncementContent;
524
- declare function buildExperienceAnnouncementUi(config: FlowAnnouncementNodeConfig, content: ExperienceAnnouncementContent): ExperienceAnnouncementUi;
525
-
526
453
  type UseExperienceAnnouncementNodeOptions = {
527
454
  config: FlowAnnouncementNodeConfig | Record<string, unknown>;
528
455
  nodeId: string;
@@ -555,114 +482,148 @@ type UseExperienceAnnouncementNodeResult = {
555
482
  */
556
483
  declare function useExperienceAnnouncementNode(options: UseExperienceAnnouncementNodeOptions): UseExperienceAnnouncementNodeResult;
557
484
 
558
- type UseIssueFormResult = {
559
- /** Current field values (ids from config). */
560
- values: IssueFormValues;
561
- setValue: (fieldId: string, value: string) => void;
562
- setValues: (next: IssueFormValues) => void;
563
- errors: Record<string, string>;
564
- submitting: boolean;
565
- submitted: boolean;
566
- submitError: string | null;
567
- /** Validate only; sets `errors`. Returns whether valid. */
568
- validate: () => boolean;
569
- /** Validate, then `reportIssue` with merged `open()` context (messageId, etc.). */
570
- submit: () => Promise<void>;
571
- /** Clear values to empty, errors, submit state. */
572
- reset: () => void;
573
- clearSubmitError: () => void;
574
- isEnabled: boolean;
575
- config: NormalizedConfig;
576
- fields: NormalizedFieldConfig[];
577
- promptText: string;
485
+ type FreqRecord = {
486
+ count: number;
487
+ window_start: string;
578
488
  };
489
+ type StorageScope = "local" | "session";
490
+ interface StorageAdapter {
491
+ get(experienceId: string, scope: StorageScope): FreqRecord | null;
492
+ set(experienceId: string, rec: FreqRecord, scope: StorageScope): void;
493
+ clear(experienceId: string, scope: StorageScope): void;
494
+ }
495
+ declare function createStorageAdapter(): StorageAdapter;
496
+ declare function clearFrequencyRecords(): void;
497
+ declare function markExperienceShown(experienceId: string, frequency: ExperienceSettings["frequency"], storage: StorageAdapter, now?: number): void;
498
+
579
499
  /**
580
- * Headless issue form: same validation + submit as {@link FormEngine} / {@link InlineIssueForm}.
581
- * Build any UI; merge context from `open({ messageId, conversationId, … })` on submit.
500
+ * Fixed backend base URL for all Firstflow SDK HTTP calls (config, audience, overrides).
501
+ * Not configurable by consumers.
582
502
  */
583
- declare function useIssueForm(): UseIssueFormResult;
584
-
585
- type MessageFeedbackProps = {
586
- conversationId: string;
587
- messageId: string;
588
- messagePreview: string;
589
- className?: string;
590
- /** Merged into each Jitsu `feedback_submitted` event as `metadata` (JSON-serializable). */
591
- metadata?: Record<string, unknown>;
592
- /**
593
- * `inline` — thumbs beside the message; tag/comment form full width below when a rating is chosen.
594
- * `default` — full card with preview + thumbs.
595
- */
596
- variant?: 'default' | 'inline';
597
- /** Styling for the expanded form when `variant="inline"` (thumbs stay unchanged). */
598
- inlineFormSurface?: 'light' | 'dark';
599
- };
600
- declare function MessageFeedback({ conversationId, messageId, messagePreview, className, metadata, variant, inlineFormSurface, }: MessageFeedbackProps): react_jsx_runtime.JSX.Element | null;
503
+ declare const FIRSTFLOW_PUBLIC_API_BASE_URL = "http://localhost:3002";
601
504
 
602
505
  /**
603
506
  * DOM adapter only: renders the React tree into target. No business logic.
604
- * Renders FirstflowProvider + InlineIssueForm so firstflow.issue.open() works after mount.
507
+ * Renders FirstflowProvider with declarative bootstrap options.
605
508
  */
606
- declare function mount(firstflow: FirstflowInstance, target: HTMLElement): () => void;
509
+ declare function mount(options: {
510
+ agentId: string;
511
+ apiKey?: string;
512
+ initialSdkPayload?: SdkAgentConfigPayload | null;
513
+ }, target: HTMLElement): () => void;
607
514
 
608
- declare function useIssueReporter(): {
609
- reporter: IssueReporterInstance;
610
- open: (options?: OpenOptions) => void;
611
- reportIssue: (data: IssueReportData) => Promise<void>;
612
- submit: (data: IssueReportData) => Promise<void>;
613
- config: NormalizedConfig;
614
- isModalOpen: boolean;
615
- closeModal: () => void;
515
+ declare function ExperienceSlot({ mode, typeFilter, conversationId, metadata, onShow, onQueueEmpty, renderCandidate, className, appearance, onExperienceMessageAction, onExperienceAnnouncementAction, }: ExperienceSlotProps): react_jsx_runtime.JSX.Element | null;
516
+
517
+ type SurveyAppearance = "light" | "dark" | "auto";
518
+ type SurveyProps = {
519
+ experienceId: string;
520
+ layout?: "paginated" | "all";
521
+ appearance?: SurveyAppearance;
522
+ conversationId?: string;
523
+ metadata?: Record<string, unknown>;
524
+ onSubmit?: (answers: Record<string, SurveyAnswerValue>) => void;
525
+ onSubmitted?: () => void;
526
+ onError?: (error: string) => void;
527
+ /** `layout="all"` Skip only. Paginated Skip advances to the next question. */
528
+ onDismissed?: () => void;
529
+ className?: string;
530
+ classNames?: {
531
+ root?: string;
532
+ question?: string;
533
+ nav?: string;
534
+ error?: string;
535
+ success?: string;
536
+ };
616
537
  };
538
+ declare function Survey({ experienceId, layout, appearance, conversationId, metadata, onSubmit, onSubmitted, onError, onDismissed, className, classNames: classNameMap, }: SurveyProps): react_jsx_runtime.JSX.Element;
617
539
 
618
- declare function InlineIssueForm(): react_jsx_runtime.JSX.Element | null;
540
+ type ExperienceMessageCardProps = {
541
+ experienceId: string;
542
+ nodeId: string;
543
+ config: FlowMessageNodeConfig;
544
+ conversationId?: string;
545
+ metadata?: Record<string, unknown>;
546
+ /** Called after exit animation so the slot can advance. */
547
+ onComplete: () => void;
548
+ appearance?: SurveyAppearance;
549
+ className?: string;
550
+ /** Host hook for prompts / side effects (analytics still run inside the message hook). */
551
+ onMessageAction?: (action: ExperienceMessageAction) => void;
552
+ };
553
+ declare function ExperienceMessageCard({ experienceId, nodeId, config, conversationId, metadata, onComplete, appearance, className, onMessageAction, }: ExperienceMessageCardProps): react_jsx_runtime.JSX.Element;
619
554
 
620
- declare function IssueModal(): React.ReactPortal | null;
555
+ type ExperienceMessageRichCardProps = {
556
+ experienceId: string;
557
+ nodeId: string;
558
+ config: FlowMessageNodeConfig;
559
+ conversationId?: string;
560
+ metadata?: Record<string, unknown>;
561
+ onComplete: () => void;
562
+ appearance?: SurveyAppearance;
563
+ className?: string;
564
+ onMessageAction?: (action: ExperienceMessageAction) => void;
565
+ };
566
+ declare function ExperienceMessageRichCard({ experienceId, nodeId, config, conversationId, metadata, onComplete, appearance, className, onMessageAction, }: ExperienceMessageRichCardProps): react_jsx_runtime.JSX.Element;
621
567
 
622
- type FormEngineProps = {
623
- onSubmitSuccess?: () => void;
624
- onCancel?: () => void;
625
- submitLabel?: string;
626
- cancelLabel?: string;
568
+ type ExperienceMessageCarouselProps = {
569
+ experienceId: string;
570
+ nodeId: string;
571
+ config: FlowMessageNodeConfig;
572
+ conversationId?: string;
573
+ metadata?: Record<string, unknown>;
574
+ onComplete: () => void;
575
+ appearance?: SurveyAppearance;
576
+ className?: string;
577
+ onMessageAction?: (action: ExperienceMessageAction) => void;
627
578
  };
628
- declare function FormEngine({ onSubmitSuccess, onCancel, submitLabel, cancelLabel, }: FormEngineProps): react_jsx_runtime.JSX.Element | null;
579
+ declare function ExperienceMessageCarousel({ experienceId, nodeId, config, conversationId, metadata, onComplete, appearance, className, onMessageAction, }: ExperienceMessageCarouselProps): react_jsx_runtime.JSX.Element | null;
629
580
 
630
- /**
631
- * Issue module types. Use the Issue namespace so the root package stays platform-first.
632
- */
581
+ type ExperienceMessageInlineProps = {
582
+ experienceId: string;
583
+ nodeId: string;
584
+ config: FlowMessageNodeConfig;
585
+ conversationId?: string;
586
+ metadata?: Record<string, unknown>;
587
+ onComplete: () => void;
588
+ appearance?: SurveyAppearance;
589
+ className?: string;
590
+ onMessageAction?: (action: ExperienceMessageAction) => void;
591
+ };
592
+ declare function ExperienceMessageInline({ experienceId, nodeId, config, conversationId, metadata, onComplete, appearance, className, onMessageAction, }: ExperienceMessageInlineProps): react_jsx_runtime.JSX.Element;
633
593
 
634
- type issue_IssueContextMetadata = IssueContextMetadata;
635
- type issue_NormalizedConfig = NormalizedConfig;
636
- type issue_NormalizedFieldConfig = NormalizedFieldConfig;
637
- type issue_OpenOptions = OpenOptions;
638
- type issue_RawIssueFieldConfig = RawIssueFieldConfig;
639
- type issue_RawIssuesConfig = RawIssuesConfig;
640
- type issue_ValidationResult = ValidationResult;
641
- declare namespace issue {
642
- export type { IssueFormValues as FormValues, issue_IssueContextMetadata as IssueContextMetadata, issue_NormalizedConfig as NormalizedConfig, issue_NormalizedFieldConfig as NormalizedFieldConfig, issue_OpenOptions as OpenOptions, IssuePayload as Payload, issue_RawIssueFieldConfig as RawIssueFieldConfig, issue_RawIssuesConfig as RawIssuesConfig, issue_ValidationResult as ValidationResult };
643
- }
594
+ type ExperienceAnnouncementCardProps = {
595
+ experienceId: string;
596
+ nodeId: string;
597
+ config: FlowAnnouncementNodeConfig | Record<string, unknown>;
598
+ conversationId?: string;
599
+ metadata?: Record<string, unknown>;
600
+ onComplete: () => void;
601
+ appearance?: SurveyAppearance;
602
+ className?: string;
603
+ onAnnouncementAction?: (action: ExperienceAnnouncementAction) => void;
604
+ };
605
+ declare function ExperienceAnnouncementCard({ experienceId, nodeId, config: configInput, conversationId, metadata, onComplete, appearance, className, onAnnouncementAction, }: ExperienceAnnouncementCardProps): react_jsx_runtime.JSX.Element;
644
606
 
645
- type IssueReporterContextValue = {
646
- reporter: IssueReporterInstance;
647
- isModalOpen: boolean;
648
- openModal: (options?: OpenOptions) => void;
649
- closeModal: () => void;
650
- openOptionsRef: React.MutableRefObject<OpenOptions | undefined>;
651
- };
652
- type IssueReporterProviderProps = {
653
- reporter: IssueReporterInstance;
654
- children: ReactNode;
607
+ type WidgetSlotProps = Omit<ExperienceSlotProps, "conversationId" | "metadata">;
608
+ type FirstflowWidgetProps = {
609
+ children: React.ReactNode;
610
+ conversationId?: string;
611
+ metadata?: Record<string, unknown>;
612
+ experiencePlacement?: "stack" | "overlay";
613
+ className?: string;
614
+ classNames?: {
615
+ root?: string;
616
+ chat?: string;
617
+ overlayLayer?: string;
618
+ overlayCard?: string;
619
+ };
620
+ experienceSlotProps?: WidgetSlotProps;
655
621
  };
656
- /**
657
- * Provides React bindings and modal state only. Config lifecycle and submission stay in the reporter instance.
658
- */
659
- declare function IssueReporterProvider({ reporter, children, }: IssueReporterProviderProps): react_jsx_runtime.JSX.Element;
660
- declare function useIssueReporterContext(): IssueReporterContextValue;
622
+ declare function FirstflowWidget({ children, conversationId, metadata, experiencePlacement, className, classNames: classNameMap, experienceSlotProps, }: FirstflowWidgetProps): react_jsx_runtime.JSX.Element;
661
623
 
662
- /**
663
- * Factory: returns an instance. No global state; callback ref from Provider for open().
664
- * Issue events are sent via the platform analytics layer only (no direct Jitsu/backend calls).
665
- */
666
- declare function createIssueReporter(options: CreateIssueReporterOptions): IssueReporterInstance;
624
+ /** Public platform instance (issue + message-feedback modules omitted from typings until re-enabled on the main export). */
625
+ type FirstflowInstance = Omit<FirstflowInstance$1, "issue" | "feedback">;
626
+ declare function createFirstflow(options: CreateFirstflowOptions): FirstflowInstance;
627
+ declare function useFirstflow(): FirstflowInstance;
667
628
 
668
- export { type AnalyticsModulePublic, CHAT_MESSAGE_SENT, type CreateFirstflowOptions, type CreateIssueReporterOptions, EXPERIENCE_ANNOUNCEMENT_ANALYTICS_ACTION, EXPERIENCE_ANNOUNCEMENT_BLOCKS_VERSION, EXPERIENCE_CLICKED, EXPERIENCE_MESSAGE_ANALYTICS_ACTION, EXPERIENCE_MESSAGE_BLOCKS_VERSION, EXPERIENCE_SHOWN, type ExperienceAnnouncementAction, type ExperienceAnnouncementContent, type ExperienceAnnouncementUi, type ExperienceMessageAction, type ExperienceMessageBlock, type ExperienceMessageUi, FEEDBACK_SUBMITTED, type FeedbackModulePublic, type FirstflowInstance, FirstflowProvider, type FlowAnnouncementNodeConfig, type FlowAnnouncementPosition, type FlowAnnouncementStyle, type FlowAnnouncementTheme, type FlowCarouselCard, type FlowCarouselCardButtonAction, type FlowMessageCtaType, type FlowMessageNodeConfig, type FlowMessageStyle, type FlowQuickReplyItem, FormEngine, type FormEngineProps, ISSUE_SUBMITTED, InlineIssueForm, issue as Issue, type IssueContextMetadata, type IssueFormValues, IssueModal, type IssueModulePublic, type IssuePayload, type IssueReporterInstance, IssueReporterProvider, MessageFeedback, type MessageFeedbackProps, type MessageFeedbackSubmitPayload, type NormalizedConfig, type NormalizedFeedbackConfig, type NormalizedFieldConfig, type OpenOptions, type RawFeedbackConfig, type RawIssueFieldConfig, type RawIssuesConfig, SURVEY_COMPLETED, type SdkAgentConfigExperience, type SdkAgentConfigPayload, type UseCreateFirstflowOptions, type UseCreateFirstflowResult, type UseExperienceAnnouncementNodeHandlers, type UseExperienceAnnouncementNodeOptions, type UseExperienceAnnouncementNodeResult, type UseExperienceMessageNodeHandlers, type UseExperienceMessageNodeOptions, type UseExperienceMessageNodeResult, type UseFeedbackMessageOptions, type UseFeedbackMessageResult, type UseIssueFormResult, type ValidationResult, buildExperienceAnnouncementContent, buildExperienceAnnouncementUi, buildExperienceCarouselCtaAction, buildExperienceMessageBlocks, buildExperienceMessageUi, createFirstflow, createIssueReporter, fetchSdkAgentConfig, mount, normalizeFlowAnnouncementNodeConfig, normalizeFlowMessageStyle, normalizeFlowQuickReplyItem, normalizeFlowQuickReplyList, useCreateFirstflow, useExperienceAnnouncementNode, useExperienceMessageNode, useFeedback, useFirstflow, useFirstflowConfig, useIssueForm, useIssueReporter, useIssueReporterContext };
629
+ export { AudienceMembershipMap, type AudienceOverrides, CreateFirstflowOptions, EXPERIENCE_ANNOUNCEMENT_ANALYTICS_ACTION, EXPERIENCE_ANNOUNCEMENT_BLOCKS_VERSION, EXPERIENCE_MESSAGE_ANALYTICS_ACTION, EXPERIENCE_MESSAGE_BLOCKS_VERSION, type ExperienceAnnouncementAction, ExperienceAnnouncementCard, type ExperienceAnnouncementCardProps, type ExperienceAnnouncementContent, type ExperienceAnnouncementUi, type ExperienceMessageAction, type ExperienceMessageBlock, ExperienceMessageCard, type ExperienceMessageCardProps, ExperienceMessageCarousel, type ExperienceMessageCarouselProps, ExperienceMessageInline, type ExperienceMessageInlineProps, ExperienceMessageRichCard, type ExperienceMessageRichCardProps, type ExperienceMessageUi, ExperienceSlot, type ExperienceSlotAppearance, type ExperienceSlotProps, FIRSTFLOW_PUBLIC_API_BASE_URL, type FirstflowInstance, FirstflowProvider, FirstflowWidget, type FirstflowWidgetProps, type FlowAnnouncementNodeConfig, type FlowAnnouncementPosition, type FlowAnnouncementStyle, type FlowAnnouncementTheme, type FlowCarouselCard, type FlowCarouselCardButtonAction, type FlowMessageCtaType, type FlowMessageNodeConfig, type FlowMessageStyle, type FlowQuickReplyItem, type FlowRichCardMediaType, type FlowRichCardMetaItem, type FlowRichCardTag, type NormalizedSlotCandidate, type SdkAgentConfigExperience, type SdkAgentConfigPayload, type SdkAgentWidgetUi, type SdkRuntimeFlow, type SdkRuntimeFlowEdge, type SdkRuntimeFlowNode, type SlotCandidateAnnouncement, type SlotCandidateMessage, type SlotCandidateSurvey, type SlotCandidateType, type SlotTourMessageStep, Survey, SurveyAnswerValue, type SurveyAppearance, SurveyModulePublic, type SurveyProps, SurveyQuestion, SurveySubmitPayload, type UseExperienceAnnouncementNodeHandlers, type UseExperienceAnnouncementNodeOptions, type UseExperienceAnnouncementNodeResult, type UseExperienceMessageNodeHandlers, type UseExperienceMessageNodeOptions, type UseExperienceMessageNodeResult, type UseFirstflowSurveyOptions, type UseFirstflowSurveyResult, UserContext, buildExperienceAnnouncementContent, buildExperienceAnnouncementUi, buildExperienceCarouselCtaAction, buildExperienceMessageBlocks, buildExperienceMessageUi, clearFrequencyRecords, createFirstflow, createStorageAdapter, fetchSdkAgentConfig, markExperienceShown, mount, normalizeFlowAnnouncementNodeConfig, normalizeFlowMessageStyle, normalizeFlowQuickReplyItem, normalizeFlowQuickReplyList, parseFlowMessageNodeConfig, tryParseHttpImageUrl, useExperienceAnnouncementNode, useExperienceEligibility, useExperienceMessageNode, useFirstflow, useFirstflowResolveExperience, useFirstflowSelector, useFirstflowSurvey };