@encatch/react-native-sdk 1.0.0-beta.1 → 1.0.0-beta.3

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 CHANGED
@@ -21,3 +21,4 @@ For the full API reference, configuration options, and usage examples, visit the
21
21
  ## License
22
22
 
23
23
  MIT
24
+
package/dist/index.d.mts CHANGED
@@ -39,6 +39,8 @@ interface ShowFormInterceptorPayload {
39
39
  prefillResponses: Record<string, unknown>;
40
40
  locale?: string;
41
41
  theme?: Theme;
42
+ /** Serialized caller context (Dates already converted to ISO strings) */
43
+ context?: Record<string, string | number | boolean>;
42
44
  }
43
45
  interface StartSessionOptions {
44
46
  /** When true, do not call the immediate ping (30s ping interval still runs) */
@@ -75,12 +77,23 @@ type Theme = 'light' | 'dark' | 'system';
75
77
  * - 'never': Never clear form data (preserve user's previous answers)
76
78
  */
77
79
  type ResetMode = 'always' | 'on-complete' | 'never';
80
+ /**
81
+ * Context values that can be attached to a form submission.
82
+ * Date values are automatically serialized to ISO strings before being sent.
83
+ */
84
+ type ContextValue = string | number | Date | boolean;
78
85
  interface ShowFormOptions {
79
86
  /**
80
87
  * Controls when form data should be cleared.
81
88
  * @default 'always'
82
89
  */
83
90
  reset?: ResetMode;
91
+ /**
92
+ * Arbitrary key-value pairs attached to the form submission.
93
+ * Useful for passing caller-side metadata (e.g. plan tier, feature flag states).
94
+ * Date values are automatically serialized to ISO 8601 strings.
95
+ */
96
+ context?: Record<string, ContextValue>;
84
97
  }
85
98
  type EventType = 'form:show' | 'form:started' | 'form:submit' | 'form:complete' | 'form:close' | 'form:dismissed' | 'form:error' | 'form:section:change' | 'form:answered';
86
99
  interface EventPayload {
@@ -112,8 +125,6 @@ interface ShowFormResponse {
112
125
  formConfiguration?: Record<string, unknown>;
113
126
  questionnaireFields?: any;
114
127
  otherConfigurationProperties?: any;
115
- welcomeScreenProperties?: any;
116
- endScreenProperties?: any;
117
128
  appearanceProperties?: any;
118
129
  partialResponseEnabled?: boolean;
119
130
  pingAgainIn?: number;
@@ -136,6 +147,7 @@ interface RefineTextResponse {
136
147
  pingOnNextPageVisit?: boolean;
137
148
  $feedbackTransactions?: string;
138
149
  }
150
+ type QuestionType = 'rating' | 'single_choice' | 'nps' | 'nested_selection' | 'multiple_choice_multiple' | 'short_answer' | 'long_text' | 'annotation' | 'welcome' | 'thank_you' | 'message_panel' | 'yes_no' | 'rating_matrix' | 'matrix_single_choice' | 'matrix_multiple_choice' | 'exit_form';
139
151
  interface QuestionAnswer {
140
152
  nps?: number;
141
153
  rating?: number;
@@ -151,10 +163,14 @@ interface QuestionAnswer {
151
163
  fileData?: string;
152
164
  fileName?: string;
153
165
  };
166
+ yesNo?: boolean;
167
+ ratingMatrix?: Record<string, number | string>;
168
+ matrixSingleChoice?: Record<string, string>;
169
+ matrixMultipleChoice?: Record<string, string[]>;
154
170
  }
155
171
  interface QuestionResponse {
156
172
  questionId: string;
157
- type?: string;
173
+ type?: QuestionType;
158
174
  answer?: QuestionAnswer;
159
175
  }
160
176
  interface FormDetails {
@@ -166,6 +182,10 @@ interface FormDetails {
166
182
  questions?: QuestionResponse[];
167
183
  };
168
184
  completionTimeInSeconds?: number;
185
+ /** Caller-provided metadata attached to this submission (Dates already serialized to ISO strings) */
186
+ context?: Record<string, string | number | boolean>;
187
+ /** IDs of questions the user actually navigated to, in order. Used for drop-off analysis. */
188
+ visitedQuestionIds?: string[];
169
189
  }
170
190
  interface SubmitFormRequest {
171
191
  triggerType?: 'automatic' | 'manual';
@@ -233,6 +253,12 @@ declare class EncatchSDK {
233
253
  private _showFormById;
234
254
  dismissForm(formConfigurationId?: string): Promise<void>;
235
255
  private _pendingResponses;
256
+ /**
257
+ * Pre-fills a response before showing a form.
258
+ * @param questionId - The ID or slug of the question to prepopulate. When a slug
259
+ * is provided the form engine resolves it to the matching question ID automatically.
260
+ * @param value - The value to set
261
+ */
236
262
  addToResponse(questionId: string, value: unknown): void;
237
263
  getPendingResponses(): Record<string, unknown>;
238
264
  clearPendingResponses(): void;
@@ -308,7 +334,7 @@ interface EncatchContextValue {
308
334
  showForm: (formId: string, options?: ShowFormOptions) => void;
309
335
  /** Call Encatch.dismissForm */
310
336
  dismissForm: (formConfigurationId?: string) => void;
311
- /** Call Encatch.addToResponse */
337
+ /** Call Encatch.addToResponse. Accepts a question ID or slug. */
312
338
  addToResponse: (questionId: string, value: unknown) => void;
313
339
  /** Call Encatch.resetUser */
314
340
  resetUser: () => void;
package/dist/index.d.ts CHANGED
@@ -39,6 +39,8 @@ interface ShowFormInterceptorPayload {
39
39
  prefillResponses: Record<string, unknown>;
40
40
  locale?: string;
41
41
  theme?: Theme;
42
+ /** Serialized caller context (Dates already converted to ISO strings) */
43
+ context?: Record<string, string | number | boolean>;
42
44
  }
43
45
  interface StartSessionOptions {
44
46
  /** When true, do not call the immediate ping (30s ping interval still runs) */
@@ -75,12 +77,23 @@ type Theme = 'light' | 'dark' | 'system';
75
77
  * - 'never': Never clear form data (preserve user's previous answers)
76
78
  */
77
79
  type ResetMode = 'always' | 'on-complete' | 'never';
80
+ /**
81
+ * Context values that can be attached to a form submission.
82
+ * Date values are automatically serialized to ISO strings before being sent.
83
+ */
84
+ type ContextValue = string | number | Date | boolean;
78
85
  interface ShowFormOptions {
79
86
  /**
80
87
  * Controls when form data should be cleared.
81
88
  * @default 'always'
82
89
  */
83
90
  reset?: ResetMode;
91
+ /**
92
+ * Arbitrary key-value pairs attached to the form submission.
93
+ * Useful for passing caller-side metadata (e.g. plan tier, feature flag states).
94
+ * Date values are automatically serialized to ISO 8601 strings.
95
+ */
96
+ context?: Record<string, ContextValue>;
84
97
  }
85
98
  type EventType = 'form:show' | 'form:started' | 'form:submit' | 'form:complete' | 'form:close' | 'form:dismissed' | 'form:error' | 'form:section:change' | 'form:answered';
86
99
  interface EventPayload {
@@ -112,8 +125,6 @@ interface ShowFormResponse {
112
125
  formConfiguration?: Record<string, unknown>;
113
126
  questionnaireFields?: any;
114
127
  otherConfigurationProperties?: any;
115
- welcomeScreenProperties?: any;
116
- endScreenProperties?: any;
117
128
  appearanceProperties?: any;
118
129
  partialResponseEnabled?: boolean;
119
130
  pingAgainIn?: number;
@@ -136,6 +147,7 @@ interface RefineTextResponse {
136
147
  pingOnNextPageVisit?: boolean;
137
148
  $feedbackTransactions?: string;
138
149
  }
150
+ type QuestionType = 'rating' | 'single_choice' | 'nps' | 'nested_selection' | 'multiple_choice_multiple' | 'short_answer' | 'long_text' | 'annotation' | 'welcome' | 'thank_you' | 'message_panel' | 'yes_no' | 'rating_matrix' | 'matrix_single_choice' | 'matrix_multiple_choice' | 'exit_form';
139
151
  interface QuestionAnswer {
140
152
  nps?: number;
141
153
  rating?: number;
@@ -151,10 +163,14 @@ interface QuestionAnswer {
151
163
  fileData?: string;
152
164
  fileName?: string;
153
165
  };
166
+ yesNo?: boolean;
167
+ ratingMatrix?: Record<string, number | string>;
168
+ matrixSingleChoice?: Record<string, string>;
169
+ matrixMultipleChoice?: Record<string, string[]>;
154
170
  }
155
171
  interface QuestionResponse {
156
172
  questionId: string;
157
- type?: string;
173
+ type?: QuestionType;
158
174
  answer?: QuestionAnswer;
159
175
  }
160
176
  interface FormDetails {
@@ -166,6 +182,10 @@ interface FormDetails {
166
182
  questions?: QuestionResponse[];
167
183
  };
168
184
  completionTimeInSeconds?: number;
185
+ /** Caller-provided metadata attached to this submission (Dates already serialized to ISO strings) */
186
+ context?: Record<string, string | number | boolean>;
187
+ /** IDs of questions the user actually navigated to, in order. Used for drop-off analysis. */
188
+ visitedQuestionIds?: string[];
169
189
  }
170
190
  interface SubmitFormRequest {
171
191
  triggerType?: 'automatic' | 'manual';
@@ -233,6 +253,12 @@ declare class EncatchSDK {
233
253
  private _showFormById;
234
254
  dismissForm(formConfigurationId?: string): Promise<void>;
235
255
  private _pendingResponses;
256
+ /**
257
+ * Pre-fills a response before showing a form.
258
+ * @param questionId - The ID or slug of the question to prepopulate. When a slug
259
+ * is provided the form engine resolves it to the matching question ID automatically.
260
+ * @param value - The value to set
261
+ */
236
262
  addToResponse(questionId: string, value: unknown): void;
237
263
  getPendingResponses(): Record<string, unknown>;
238
264
  clearPendingResponses(): void;
@@ -308,7 +334,7 @@ interface EncatchContextValue {
308
334
  showForm: (formId: string, options?: ShowFormOptions) => void;
309
335
  /** Call Encatch.dismissForm */
310
336
  dismissForm: (formConfigurationId?: string) => void;
311
- /** Call Encatch.addToResponse */
337
+ /** Call Encatch.addToResponse. Accepts a question ID or slug. */
312
338
  addToResponse: (questionId: string, value: unknown) => void;
313
339
  /** Call Encatch.resetUser */
314
340
  resetUser: () => void;
package/dist/index.js CHANGED
@@ -553,7 +553,8 @@ var EncatchSDK = class {
553
553
  // ============================================================================
554
554
  // Form response helpers
555
555
  // ============================================================================
556
- // Pre-filled responses stored by addToResponse, sent with sdk:prefillResponses
556
+ // Pre-filled responses stored by addToResponse, sent with sdk:prefillResponses.
557
+ // Keys may be question IDs or slugs; the form engine resolves slugs to IDs.
557
558
  this._pendingResponses = {};
558
559
  }
559
560
  // ============================================================================
@@ -787,6 +788,13 @@ var EncatchSDK = class {
787
788
  var _a, _b, _c, _d, _e, _f, _g;
788
789
  const resetMode = (_a = options == null ? void 0 : options.reset) != null ? _a : "always";
789
790
  const triggerType = (_b = options == null ? void 0 : options.triggerType) != null ? _b : "manual";
791
+ const serializedContext = (options == null ? void 0 : options.context) ? Object.entries(options.context).reduce(
792
+ (acc, [key, value]) => {
793
+ acc[key] = value instanceof Date ? value.toISOString() : value;
794
+ return acc;
795
+ },
796
+ {}
797
+ ) : void 0;
790
798
  const deviceInfo = await this._buildDeviceInfo();
791
799
  const req = {
792
800
  formSlugOrId: formId,
@@ -811,7 +819,8 @@ var EncatchSDK = class {
811
819
  triggerType,
812
820
  prefillResponses,
813
821
  locale: (_f = this._locale) != null ? _f : void 0,
814
- theme: this._theme
822
+ theme: this._theme,
823
+ context: serializedContext
815
824
  };
816
825
  if (this._onBeforeShowForm) {
817
826
  const allow = await Promise.resolve(this._onBeforeShowForm(payload));
@@ -827,7 +836,8 @@ var EncatchSDK = class {
827
836
  triggerType,
828
837
  prefillResponses: Object.keys(prefillResponses).length > 0 ? prefillResponses : void 0,
829
838
  locale: (_g = this._locale) != null ? _g : void 0,
830
- theme: this._theme
839
+ theme: this._theme,
840
+ context: serializedContext
831
841
  });
832
842
  this._isFormVisible = true;
833
843
  } catch (err) {
@@ -864,6 +874,12 @@ var EncatchSDK = class {
864
874
  }
865
875
  this.emitEvent("form:dismissed", { formId: formConfigurationId != null ? formConfigurationId : "" });
866
876
  }
877
+ /**
878
+ * Pre-fills a response before showing a form.
879
+ * @param questionId - The ID or slug of the question to prepopulate. When a slug
880
+ * is provided the form engine resolves it to the matching question ID automatically.
881
+ * @param value - The value to set
882
+ */
867
883
  addToResponse(questionId, value) {
868
884
  this._pendingResponses[questionId] = value;
869
885
  }
@@ -1626,11 +1642,12 @@ var EncatchWebView = () => {
1626
1642
  switch (type) {
1627
1643
  case "form:ready": {
1628
1644
  if (!formPayload) return;
1629
- const { formConfig, resetMode, triggerType, prefillResponses, locale, theme } = formPayload;
1645
+ const { formConfig, resetMode, triggerType, prefillResponses, locale, theme, context } = formPayload;
1630
1646
  injectSDKMessage({
1631
1647
  type: "sdk:formConfig",
1632
1648
  data: __spreadProps(__spreadValues({}, formConfig), {
1633
- triggerType
1649
+ triggerType,
1650
+ context
1634
1651
  })
1635
1652
  });
1636
1653
  if (resetMode === "always") {
@@ -1681,7 +1698,9 @@ var EncatchWebView = () => {
1681
1698
  feedbackIdentifier: data.feedbackIdentifier,
1682
1699
  responseLanguageCode: data.responseLanguageCode,
1683
1700
  response: data.response,
1684
- completionTimeInSeconds: data.completionTimeInSeconds
1701
+ completionTimeInSeconds: data.completionTimeInSeconds,
1702
+ context: data.context,
1703
+ visitedQuestionIds: data.visitedQuestionIds
1685
1704
  },
1686
1705
  $feedbackTransactions: void 0
1687
1706
  };
package/dist/index.mjs CHANGED
@@ -522,7 +522,8 @@ var EncatchSDK = class {
522
522
  // ============================================================================
523
523
  // Form response helpers
524
524
  // ============================================================================
525
- // Pre-filled responses stored by addToResponse, sent with sdk:prefillResponses
525
+ // Pre-filled responses stored by addToResponse, sent with sdk:prefillResponses.
526
+ // Keys may be question IDs or slugs; the form engine resolves slugs to IDs.
526
527
  this._pendingResponses = {};
527
528
  }
528
529
  // ============================================================================
@@ -756,6 +757,13 @@ var EncatchSDK = class {
756
757
  var _a, _b, _c, _d, _e, _f, _g;
757
758
  const resetMode = (_a = options == null ? void 0 : options.reset) != null ? _a : "always";
758
759
  const triggerType = (_b = options == null ? void 0 : options.triggerType) != null ? _b : "manual";
760
+ const serializedContext = (options == null ? void 0 : options.context) ? Object.entries(options.context).reduce(
761
+ (acc, [key, value]) => {
762
+ acc[key] = value instanceof Date ? value.toISOString() : value;
763
+ return acc;
764
+ },
765
+ {}
766
+ ) : void 0;
759
767
  const deviceInfo = await this._buildDeviceInfo();
760
768
  const req = {
761
769
  formSlugOrId: formId,
@@ -780,7 +788,8 @@ var EncatchSDK = class {
780
788
  triggerType,
781
789
  prefillResponses,
782
790
  locale: (_f = this._locale) != null ? _f : void 0,
783
- theme: this._theme
791
+ theme: this._theme,
792
+ context: serializedContext
784
793
  };
785
794
  if (this._onBeforeShowForm) {
786
795
  const allow = await Promise.resolve(this._onBeforeShowForm(payload));
@@ -796,7 +805,8 @@ var EncatchSDK = class {
796
805
  triggerType,
797
806
  prefillResponses: Object.keys(prefillResponses).length > 0 ? prefillResponses : void 0,
798
807
  locale: (_g = this._locale) != null ? _g : void 0,
799
- theme: this._theme
808
+ theme: this._theme,
809
+ context: serializedContext
800
810
  });
801
811
  this._isFormVisible = true;
802
812
  } catch (err) {
@@ -833,6 +843,12 @@ var EncatchSDK = class {
833
843
  }
834
844
  this.emitEvent("form:dismissed", { formId: formConfigurationId != null ? formConfigurationId : "" });
835
845
  }
846
+ /**
847
+ * Pre-fills a response before showing a form.
848
+ * @param questionId - The ID or slug of the question to prepopulate. When a slug
849
+ * is provided the form engine resolves it to the matching question ID automatically.
850
+ * @param value - The value to set
851
+ */
836
852
  addToResponse(questionId, value) {
837
853
  this._pendingResponses[questionId] = value;
838
854
  }
@@ -1615,11 +1631,12 @@ var EncatchWebView = () => {
1615
1631
  switch (type) {
1616
1632
  case "form:ready": {
1617
1633
  if (!formPayload) return;
1618
- const { formConfig, resetMode, triggerType, prefillResponses, locale, theme } = formPayload;
1634
+ const { formConfig, resetMode, triggerType, prefillResponses, locale, theme, context } = formPayload;
1619
1635
  injectSDKMessage({
1620
1636
  type: "sdk:formConfig",
1621
1637
  data: __spreadProps(__spreadValues({}, formConfig), {
1622
- triggerType
1638
+ triggerType,
1639
+ context
1623
1640
  })
1624
1641
  });
1625
1642
  if (resetMode === "always") {
@@ -1670,7 +1687,9 @@ var EncatchWebView = () => {
1670
1687
  feedbackIdentifier: data.feedbackIdentifier,
1671
1688
  responseLanguageCode: data.responseLanguageCode,
1672
1689
  response: data.response,
1673
- completionTimeInSeconds: data.completionTimeInSeconds
1690
+ completionTimeInSeconds: data.completionTimeInSeconds,
1691
+ context: data.context,
1692
+ visitedQuestionIds: data.visitedQuestionIds
1674
1693
  },
1675
1694
  $feedbackTransactions: void 0
1676
1695
  };
package/package.json CHANGED
@@ -12,15 +12,10 @@
12
12
  "main": "dist/index.js",
13
13
  "module": "dist/index.mjs",
14
14
  "types": "dist/index.d.ts",
15
- "version": "1.0.0-beta.1",
15
+ "version": "1.0.0-beta.3",
16
16
  "files": [
17
17
  "dist"
18
18
  ],
19
- "scripts": {
20
- "build": "tsup",
21
- "build:watch": "tsup --watch",
22
- "clean": "rm -rf dist"
23
- },
24
19
  "peerDependencies": {
25
20
  "react": ">=18.0.0",
26
21
  "react-native": ">=0.73.0",
@@ -67,5 +62,10 @@
67
62
  "react-native": "0.84.1",
68
63
  "typescript": "~5.9.3",
69
64
  "tsup": "^8.5.1"
65
+ },
66
+ "scripts": {
67
+ "build": "tsup",
68
+ "build:watch": "tsup --watch",
69
+ "clean": "rm -rf dist"
70
70
  }
71
- }
71
+ }