@rocapine/react-native-onboarding 1.25.1 → 1.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/evaluateCondition.d.ts.map +1 -1
  2. package/dist/evaluateCondition.js +44 -1
  3. package/dist/evaluateCondition.js.map +1 -1
  4. package/dist/index.d.ts +3 -3
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +6 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/onboarding-example.d.ts +2215 -1976
  9. package/dist/onboarding-example.d.ts.map +1 -1
  10. package/dist/onboarding-example.js +592 -545
  11. package/dist/onboarding-example.js.map +1 -1
  12. package/dist/steps/Carousel/types.d.ts +5 -1
  13. package/dist/steps/Carousel/types.d.ts.map +1 -1
  14. package/dist/steps/Commitment/types.d.ts +5 -1
  15. package/dist/steps/Commitment/types.d.ts.map +1 -1
  16. package/dist/steps/ComposableScreen/elements/ButtonElement.d.ts +5 -1
  17. package/dist/steps/ComposableScreen/elements/ButtonElement.d.ts.map +1 -1
  18. package/dist/steps/ComposableScreen/elements/IconElement.d.ts +4 -0
  19. package/dist/steps/ComposableScreen/elements/IconElement.d.ts.map +1 -1
  20. package/dist/steps/ComposableScreen/elements/IconElement.js +2 -0
  21. package/dist/steps/ComposableScreen/elements/IconElement.js.map +1 -1
  22. package/dist/steps/ComposableScreen/elements/WheelPickerElement.d.ts +124 -0
  23. package/dist/steps/ComposableScreen/elements/WheelPickerElement.d.ts.map +1 -0
  24. package/dist/steps/ComposableScreen/elements/WheelPickerElement.js +96 -0
  25. package/dist/steps/ComposableScreen/elements/WheelPickerElement.js.map +1 -0
  26. package/dist/steps/ComposableScreen/types.d.ts +14 -1
  27. package/dist/steps/ComposableScreen/types.d.ts.map +1 -1
  28. package/dist/steps/ComposableScreen/types.js +13 -1
  29. package/dist/steps/ComposableScreen/types.js.map +1 -1
  30. package/dist/steps/Loader/types.d.ts +5 -1
  31. package/dist/steps/Loader/types.d.ts.map +1 -1
  32. package/dist/steps/MediaContent/types.d.ts +5 -1
  33. package/dist/steps/MediaContent/types.d.ts.map +1 -1
  34. package/dist/steps/Picker/types.d.ts +5 -1
  35. package/dist/steps/Picker/types.d.ts.map +1 -1
  36. package/dist/steps/Question/types.d.ts +5 -1
  37. package/dist/steps/Question/types.d.ts.map +1 -1
  38. package/dist/steps/Ratings/types.d.ts +5 -1
  39. package/dist/steps/Ratings/types.d.ts.map +1 -1
  40. package/dist/steps/common.types.d.ts +30 -4
  41. package/dist/steps/common.types.d.ts.map +1 -1
  42. package/dist/steps/common.types.js +33 -3
  43. package/dist/steps/common.types.js.map +1 -1
  44. package/package.json +2 -2
  45. package/src/__tests__/evaluateCondition.test.ts +35 -0
  46. package/src/evaluateCondition.ts +41 -1
  47. package/src/index.ts +8 -0
  48. package/src/onboarding-example.ts +47 -0
  49. package/src/steps/ComposableScreen/elements/IconElement.ts +4 -0
  50. package/src/steps/ComposableScreen/elements/WheelPickerElement.ts +115 -0
  51. package/src/steps/ComposableScreen/types.ts +17 -0
  52. package/src/steps/common.types.ts +38 -5
@@ -47,8 +47,12 @@ export declare const PickerStepTypeSchema: z.ZodObject<{
47
47
  contains: "contains";
48
48
  in: "in";
49
49
  not_in: "not_in";
50
+ is_empty: "is_empty";
51
+ is_not_empty: "is_not_empty";
52
+ is_null: "is_null";
53
+ is_not_null: "is_not_null";
50
54
  }>;
51
- value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>;
55
+ value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>>;
52
56
  }, z.core.$strip>, z.ZodType<import("../common.types").ConditionGroup, unknown, z.core.$ZodTypeInternals<import("../common.types").ConditionGroup, unknown>>]>>>;
53
57
  targetStepId: z.ZodString;
54
58
  }, z.core.$strip>>>;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/steps/Picker/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,cAAc;;;;;;;;EAQzB,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;iBAIlC,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAI/B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,CAAC;AACrC,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/steps/Picker/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,cAAc;;;;;;;;EAQzB,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;iBAIlC,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAI/B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,CAAC;AACrC,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,CAAC"}
@@ -46,8 +46,12 @@ export declare const QuestionStepTypeSchema: z.ZodObject<{
46
46
  contains: "contains";
47
47
  in: "in";
48
48
  not_in: "not_in";
49
+ is_empty: "is_empty";
50
+ is_not_empty: "is_not_empty";
51
+ is_null: "is_null";
52
+ is_not_null: "is_not_null";
49
53
  }>;
50
- value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>;
54
+ value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>>;
51
55
  }, z.core.$strip>, z.ZodType<import("../common.types").ConditionGroup, unknown, z.core.$ZodTypeInternals<import("../common.types").ConditionGroup, unknown>>]>>>;
52
56
  targetStepId: z.ZodString;
53
57
  }, z.core.$strip>>>;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/steps/Question/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,YAAY;;;;;iBAKvB,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;iBAMpC,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAIjC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/steps/Question/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,YAAY;;;;;iBAKvB,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;iBAMpC,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAIjC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
@@ -35,8 +35,12 @@ export declare const RatingsStepTypeSchema: z.ZodObject<{
35
35
  contains: "contains";
36
36
  in: "in";
37
37
  not_in: "not_in";
38
+ is_empty: "is_empty";
39
+ is_not_empty: "is_not_empty";
40
+ is_null: "is_null";
41
+ is_not_null: "is_not_null";
38
42
  }>;
39
- value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>;
43
+ value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>>;
40
44
  }, z.core.$strip>, z.ZodType<import("../common.types").ConditionGroup, unknown, z.core.$ZodTypeInternals<import("../common.types").ConditionGroup, unknown>>]>>>;
41
45
  targetStepId: z.ZodString;
42
46
  }, z.core.$strip>>>;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/steps/Ratings/types.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,KAAK,CAAC;AAGpB,eAAO,MAAM,wBAAwB;;;;;;;;;iBAKnC,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGhC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/steps/Ratings/types.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,KAAK,CAAC;AAGpB,eAAO,MAAM,wBAAwB;;;;;;;;;iBAKnC,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGhC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
@@ -30,8 +30,18 @@ export declare const ConditionOperatorSchema: z.ZodEnum<{
30
30
  contains: "contains";
31
31
  in: "in";
32
32
  not_in: "not_in";
33
+ is_empty: "is_empty";
34
+ is_not_empty: "is_not_empty";
35
+ is_null: "is_null";
36
+ is_not_null: "is_not_null";
33
37
  }>;
34
38
  export type ConditionOperator = z.infer<typeof ConditionOperatorSchema>;
39
+ /**
40
+ * Operators that test the variable alone and ignore `value`. A LeafCondition
41
+ * using one of these may omit `value`; all other operators require it.
42
+ */
43
+ export declare const UNARY_CONDITION_OPERATORS: readonly ["is_empty", "is_not_empty", "is_null", "is_not_null"];
44
+ export declare const isUnaryConditionOperator: (operator: ConditionOperator) => boolean;
35
45
  export declare const ConditionValueSchema: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>;
36
46
  export type ConditionValue = z.infer<typeof ConditionValueSchema>;
37
47
  export declare const LeafConditionSchema: z.ZodObject<{
@@ -46,8 +56,12 @@ export declare const LeafConditionSchema: z.ZodObject<{
46
56
  contains: "contains";
47
57
  in: "in";
48
58
  not_in: "not_in";
59
+ is_empty: "is_empty";
60
+ is_not_empty: "is_not_empty";
61
+ is_null: "is_null";
62
+ is_not_null: "is_not_null";
49
63
  }>;
50
- value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>;
64
+ value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>>;
51
65
  }, z.core.$strip>;
52
66
  export type LeafCondition = z.infer<typeof LeafConditionSchema>;
53
67
  export type ConditionGroup = {
@@ -68,8 +82,12 @@ export declare const BranchSchema: z.ZodObject<{
68
82
  contains: "contains";
69
83
  in: "in";
70
84
  not_in: "not_in";
85
+ is_empty: "is_empty";
86
+ is_not_empty: "is_not_empty";
87
+ is_null: "is_null";
88
+ is_not_null: "is_not_null";
71
89
  }>;
72
- value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>;
90
+ value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>>;
73
91
  }, z.core.$strip>, z.ZodType<ConditionGroup, unknown, z.core.$ZodTypeInternals<ConditionGroup, unknown>>]>>>;
74
92
  targetStepId: z.ZodString;
75
93
  }, z.core.$strip>;
@@ -89,8 +107,12 @@ export declare const NextStepSchema: z.ZodDefault<z.ZodNullable<z.ZodObject<{
89
107
  contains: "contains";
90
108
  in: "in";
91
109
  not_in: "not_in";
110
+ is_empty: "is_empty";
111
+ is_not_empty: "is_not_empty";
112
+ is_null: "is_null";
113
+ is_not_null: "is_not_null";
92
114
  }>;
93
- value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>;
115
+ value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>>;
94
116
  }, z.core.$strip>, z.ZodType<ConditionGroup, unknown, z.core.$ZodTypeInternals<ConditionGroup, unknown>>]>>>;
95
117
  targetStepId: z.ZodString;
96
118
  }, z.core.$strip>>>;
@@ -122,8 +144,12 @@ export declare const BaseStepTypeSchema: z.ZodObject<{
122
144
  contains: "contains";
123
145
  in: "in";
124
146
  not_in: "not_in";
147
+ is_empty: "is_empty";
148
+ is_not_empty: "is_not_empty";
149
+ is_null: "is_null";
150
+ is_not_null: "is_not_null";
125
151
  }>;
126
- value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>;
152
+ value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>>;
127
153
  }, z.core.$strip>, z.ZodType<ConditionGroup, unknown, z.core.$ZodTypeInternals<ConditionGroup, unknown>>]>>>;
128
154
  targetStepId: z.ZodString;
129
155
  }, z.core.$strip>>>;
@@ -1 +1 @@
1
- {"version":3,"file":"common.types.d.ts","sourceRoot":"","sources":["../../src/steps/common.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,mBAAmB,kEAA0C,CAAC;AAE3E,eAAO,MAAM,iBAAiB;;;;;;mBAS5B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;iBAI5B,CAAC;AAEH,eAAO,MAAM,aAAa;;;iBAGxB,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;iBAG9B,CAAC;AAIH,eAAO,MAAM,uBAAuB;;;;;;;;;;EAUlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,oBAAoB,0IAK/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;iBAI9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,KAAK,CAAC,aAAa,GAAG,cAAc,CAAC,CAAC;CACnD,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,CAAC,CAAC,OAAO,CAAC,cAAc,CAO1D,CAAC;AAEF,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;iBAGvB,CAAC;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;mBAMX,CAAC;AACjB,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAItD,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAS7B,CAAC"}
1
+ {"version":3,"file":"common.types.d.ts","sourceRoot":"","sources":["../../src/steps/common.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,mBAAmB,kEAA0C,CAAC;AAE3E,eAAO,MAAM,iBAAiB;;;;;;mBAS5B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;iBAI5B,CAAC;AAEH,eAAO,MAAM,aAAa;;;iBAGxB,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;iBAG9B,CAAC;AAIH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;EAiBlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;;GAGG;AACH,eAAO,MAAM,yBAAyB,iEAKW,CAAC;AAIlD,eAAO,MAAM,wBAAwB,GAAI,UAAU,iBAAiB,KAAG,OACrC,CAAC;AAEnC,eAAO,MAAM,oBAAoB,0IAK/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;iBAc5B,CAAC;AACL,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,KAAK,CAAC,aAAa,GAAG,cAAc,CAAC,CAAC;CACnD,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,CAAC,CAAC,OAAO,CAAC,cAAc,CAO1D,CAAC;AAEF,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;iBAGvB,CAAC;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;mBAMX,CAAC;AACjB,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAItD,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAS7B,CAAC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BaseStepTypeSchema = exports.NextStepSchema = exports.BranchSchema = exports.ConditionGroupSchema = exports.LeafConditionSchema = exports.ConditionValueSchema = exports.ConditionOperatorSchema = exports.ButtonSectionSchema = exports.InfoBoxSchema = exports.SocialProofSchema = exports.MediaSourceSchema = exports.CustomPayloadSchema = void 0;
3
+ exports.BaseStepTypeSchema = exports.NextStepSchema = exports.BranchSchema = exports.ConditionGroupSchema = exports.LeafConditionSchema = exports.ConditionValueSchema = exports.isUnaryConditionOperator = exports.UNARY_CONDITION_OPERATORS = exports.ConditionOperatorSchema = exports.ButtonSectionSchema = exports.InfoBoxSchema = exports.SocialProofSchema = exports.MediaSourceSchema = exports.CustomPayloadSchema = void 0;
4
4
  const zod_1 = require("zod");
5
5
  exports.CustomPayloadSchema = zod_1.z.record(zod_1.z.string(), zod_1.z.any()).nullish();
6
6
  exports.MediaSourceSchema = zod_1.z.union([
@@ -37,17 +37,47 @@ exports.ConditionOperatorSchema = zod_1.z.enum([
37
37
  "contains",
38
38
  "in",
39
39
  "not_in",
40
+ // Unary presence operators — no `value` required. `empty` is type-aware
41
+ // (empty string / empty array / null|undefined); `null` is strictly
42
+ // null|undefined (a set-but-empty value is "not null" yet "is empty").
43
+ "is_empty",
44
+ "is_not_empty",
45
+ "is_null",
46
+ "is_not_null",
40
47
  ]);
48
+ /**
49
+ * Operators that test the variable alone and ignore `value`. A LeafCondition
50
+ * using one of these may omit `value`; all other operators require it.
51
+ */
52
+ exports.UNARY_CONDITION_OPERATORS = [
53
+ "is_empty",
54
+ "is_not_empty",
55
+ "is_null",
56
+ "is_not_null",
57
+ ];
58
+ const UNARY_OPERATOR_SET = new Set(exports.UNARY_CONDITION_OPERATORS);
59
+ const isUnaryConditionOperator = (operator) => UNARY_OPERATOR_SET.has(operator);
60
+ exports.isUnaryConditionOperator = isUnaryConditionOperator;
41
61
  exports.ConditionValueSchema = zod_1.z.union([
42
62
  zod_1.z.string(),
43
63
  zod_1.z.number(),
44
64
  zod_1.z.boolean(),
45
65
  zod_1.z.array(zod_1.z.union([zod_1.z.string(), zod_1.z.number(), zod_1.z.boolean()])),
46
66
  ]);
47
- exports.LeafConditionSchema = zod_1.z.object({
67
+ exports.LeafConditionSchema = zod_1.z
68
+ .object({
48
69
  variable: zod_1.z.string().min(1),
49
70
  operator: exports.ConditionOperatorSchema,
50
- value: exports.ConditionValueSchema,
71
+ value: exports.ConditionValueSchema.optional(),
72
+ })
73
+ .superRefine((data, ctx) => {
74
+ if (!(0, exports.isUnaryConditionOperator)(data.operator) && data.value === undefined) {
75
+ ctx.addIssue({
76
+ code: zod_1.z.ZodIssueCode.custom,
77
+ message: `operator "${data.operator}" requires a value`,
78
+ path: ["value"],
79
+ });
80
+ }
51
81
  });
52
82
  exports.ConditionGroupSchema = zod_1.z.lazy(() => zod_1.z.object({
53
83
  logic: zod_1.z.enum(["and", "or"]),
@@ -1 +1 @@
1
- {"version":3,"file":"common.types.js","sourceRoot":"","sources":["../../src/steps/common.types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"common.types.js","sourceRoot":"","sources":["../../src/steps/common.types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rocapine/react-native-onboarding",
3
- "version": "1.25.1",
3
+ "version": "1.27.0",
4
4
  "description": "Headless React Native SDK for Rocapine Onboarding Studio - Data fetching, state management, and hooks",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -51,7 +51,7 @@
51
51
  ],
52
52
  "repository": {
53
53
  "type": "git",
54
- "url": "https://github.com/rocapine/react-native-onboarding-studio.git",
54
+ "url": "https://github.com/Rocapine/react-native-onboarding.git",
55
55
  "directory": "packages/onboarding"
56
56
  }
57
57
  }
@@ -76,6 +76,41 @@ describe("evaluateLeaf — unknown operator", () => {
76
76
  it("returns false for unknown operator", () => expect(evaluateLeaf({ variable: "x", operator: "xor" as any, value: "y" }, { x: "y" })).toBe(false));
77
77
  });
78
78
 
79
+ describe("evaluateLeaf — unary is_empty / is_not_empty", () => {
80
+ it("empty string is empty", () => expect(evaluateLeaf({ variable: "x", operator: "is_empty" }, { x: "" })).toBe(true));
81
+ it("whitespace string is empty", () => expect(evaluateLeaf({ variable: "x", operator: "is_empty" }, { x: " " })).toBe(true));
82
+ it("unset variable is empty", () => expect(evaluateLeaf({ variable: "x", operator: "is_empty" }, {})).toBe(true));
83
+ it("empty array is empty", () => expect(evaluateLeaf({ variable: "x", operator: "is_empty" }, { x: [] })).toBe(true));
84
+ it("non-empty string is not empty", () => expect(evaluateLeaf({ variable: "x", operator: "is_not_empty" }, { x: "Paul" })).toBe(true));
85
+ it("zero-string is not empty (0 is a value)", () => expect(evaluateLeaf({ variable: "x", operator: "is_not_empty" }, { x: "0" })).toBe(true));
86
+ it("populated array is not empty", () => expect(evaluateLeaf({ variable: "x", operator: "is_not_empty" }, { x: ["a"] })).toBe(true));
87
+ it("is_not_empty is the negation of is_empty", () => expect(evaluateLeaf({ variable: "x", operator: "is_not_empty" }, { x: "" })).toBe(false));
88
+ });
89
+
90
+ describe("evaluateLeaf — unary is_null / is_not_null", () => {
91
+ it("unset variable is null", () => expect(evaluateLeaf({ variable: "x", operator: "is_null" }, {})).toBe(true));
92
+ it("explicit null is null", () => expect(evaluateLeaf({ variable: "x", operator: "is_null" }, { x: null })).toBe(true));
93
+ it("set-but-empty string is NOT null", () => expect(evaluateLeaf({ variable: "x", operator: "is_not_null" }, { x: "" })).toBe(true));
94
+ it("set value is not null", () => expect(evaluateLeaf({ variable: "x", operator: "is_not_null" }, { x: "Paul" })).toBe(true));
95
+ it("unset variable is_not_null is false", () => expect(evaluateLeaf({ variable: "x", operator: "is_not_null" }, {})).toBe(false));
96
+ });
97
+
98
+ describe("evaluateLeaf — JSON-array-encoded variable values (CheckboxGroup)", () => {
99
+ // Multi-select stores its value as a JSON string; "[]" is an empty selection.
100
+ it('empty "[]" reads as empty', () => expect(evaluateLeaf({ variable: "tags", operator: "is_empty" }, { tags: "[]" })).toBe(true));
101
+ it('empty "[]" is_not_empty is false (gated element falls back on deselect)', () =>
102
+ expect(evaluateLeaf({ variable: "tags", operator: "is_not_empty" }, { tags: "[]" })).toBe(false));
103
+ it('non-empty "[\\"a\\"]" is not empty', () => expect(evaluateLeaf({ variable: "tags", operator: "is_not_empty" }, { tags: '["a"]' })).toBe(true));
104
+ it("contains uses real array membership on encoded value", () =>
105
+ expect(evaluateLeaf({ variable: "tags", operator: "contains", value: "sport" }, { tags: '["health","sport"]' })).toBe(true));
106
+ it("contains is false when element absent from encoded array", () =>
107
+ expect(evaluateLeaf({ variable: "tags", operator: "contains", value: "music" }, { tags: '["health","sport"]' })).toBe(false));
108
+ it("a plain string that is not a JSON array is left untouched", () =>
109
+ expect(evaluateLeaf({ variable: "x", operator: "is_not_empty" }, { x: "[oops" })).toBe(true));
110
+ it("a numeric-looking string is not coerced to empty", () =>
111
+ expect(evaluateLeaf({ variable: "x", operator: "is_not_empty" }, { x: "5" })).toBe(true));
112
+ });
113
+
79
114
  // ---------------------------------------------------------------------------
80
115
  // evaluateCondition — logic groups
81
116
  // ---------------------------------------------------------------------------
@@ -10,8 +10,40 @@ function coerceToNumber(v: unknown): number {
10
10
  return typeof v === "string" ? parseFloat(v) : Number(v);
11
11
  }
12
12
 
13
+ // Multi-select elements (e.g. CheckboxGroup) store their value as a JSON-encoded
14
+ // string[] to fit the string-based variable system, so an empty selection is the
15
+ // literal string "[]". Decode such strings back to an array before evaluating so
16
+ // array-aware operators (is_empty / is_not_empty / contains / in / not_in) see the
17
+ // real collection — otherwise "[]" reads as a non-empty 2-char string. Only strings
18
+ // that parse to an actual array are coerced; scalars and plain text are untouched.
19
+ function decodeArrayValue(raw: unknown): unknown {
20
+ if (typeof raw !== "string") return raw;
21
+ const trimmed = raw.trim();
22
+ if (!(trimmed.startsWith("[") && trimmed.endsWith("]"))) return raw;
23
+ try {
24
+ const parsed = JSON.parse(trimmed);
25
+ return Array.isArray(parsed) ? parsed : raw;
26
+ } catch {
27
+ return raw;
28
+ }
29
+ }
30
+
31
+ // `null`-ness: only null / undefined. A set-but-empty value (e.g. "") is NOT null.
32
+ function isNullish(v: unknown): boolean {
33
+ return v === null || v === undefined;
34
+ }
35
+
36
+ // Type-aware emptiness: null|undefined, empty/whitespace string, or empty array.
37
+ // Numbers and booleans are never "empty" (0 / false are meaningful values).
38
+ function isEmpty(v: unknown): boolean {
39
+ if (isNullish(v)) return true;
40
+ if (typeof v === "string") return v.trim() === "";
41
+ if (Array.isArray(v)) return v.length === 0;
42
+ return false;
43
+ }
44
+
13
45
  export function evaluateLeaf(condition: LeafCondition, variables: Record<string, unknown>): boolean {
14
- const raw = variables[condition.variable];
46
+ const raw = decodeArrayValue(variables[condition.variable]);
15
47
  const { operator, value } = condition;
16
48
 
17
49
  switch (operator) {
@@ -35,6 +67,14 @@ export function evaluateLeaf(condition: LeafCondition, variables: Record<string,
35
67
  return Array.isArray(value) ? value.includes(String(raw)) : false;
36
68
  case "not_in":
37
69
  return Array.isArray(value) ? !value.includes(String(raw)) : true;
70
+ case "is_empty":
71
+ return isEmpty(raw);
72
+ case "is_not_empty":
73
+ return !isEmpty(raw);
74
+ case "is_null":
75
+ return isNullish(raw);
76
+ case "is_not_null":
77
+ return !isNullish(raw);
38
78
  default:
39
79
  return false;
40
80
  }
package/src/index.ts CHANGED
@@ -8,10 +8,16 @@ export type {
8
8
  CustomButtonAction,
9
9
  ComposableVariableEntry,
10
10
  ComposableVariableKind,
11
+ WheelPickerElementProps,
12
+ WheelPickerItem,
13
+ WheelPickerRange,
11
14
  } from "./steps/ComposableScreen/types";
12
15
  export {
13
16
  ButtonActionSchema,
14
17
  CustomButtonActionSchema,
18
+ WheelPickerElementPropsSchema,
19
+ generateWheelPickerRangeItems,
20
+ resolveWheelPickerItems,
15
21
  } from "./steps/ComposableScreen/types";
16
22
  // Hooks and providers
17
23
  export * from "./infra";
@@ -35,4 +41,6 @@ export {
35
41
  NextStepSchema,
36
42
  ConditionOperatorSchema,
37
43
  ConditionValueSchema,
44
+ UNARY_CONDITION_OPERATORS,
45
+ isUnaryConditionOperator,
38
46
  } from "./steps/common.types";
@@ -110,6 +110,11 @@ export const onboardingExample = {
110
110
  type: "SafeAreaView",
111
111
  props: { flex: 1, edges: ["top", "bottom"] },
112
112
  children: [
113
+ {
114
+ id: "scroll-root",
115
+ type: "ScrollView",
116
+ props: { flex: 1, showsVerticalScrollIndicator: false },
117
+ children: [
113
118
  {
114
119
  id: "root",
115
120
  type: "YStack",
@@ -153,6 +158,8 @@ export const onboardingExample = {
153
158
  name: "Star",
154
159
  size: 48,
155
160
  color: "#007AFF",
161
+ fill: "#007AFF",
162
+ fillOpacity: 0.2,
156
163
  marginVertical: 8,
157
164
  },
158
165
  },
@@ -187,6 +194,21 @@ export const onboardingExample = {
187
194
  },
188
195
  ],
189
196
  },
197
+ {
198
+ // Only shown once `name` has a non-empty value — demonstrates
199
+ // the unary `is_not_empty` condition operator.
200
+ id: "name-greeting",
201
+ type: "Text",
202
+ renderWhen: { variable: "name", operator: "is_not_empty" },
203
+ props: {
204
+ content: "Nice to meet you, {{name}}!",
205
+ mode: "expression",
206
+ fontSize: 14,
207
+ textAlign: "center",
208
+ opacity: 0.6,
209
+ marginVertical: 4,
210
+ },
211
+ },
190
212
  {
191
213
  id: "scroll-demo",
192
214
  type: "ScrollView",
@@ -429,6 +451,29 @@ export const onboardingExample = {
429
451
  marginVertical: 4,
430
452
  },
431
453
  },
454
+ {
455
+ id: "hero-weight-wheel",
456
+ type: "WheelPicker",
457
+ props: {
458
+ variableName: "weight",
459
+ defaultValue: "70",
460
+ range: { min: 40, max: 200, step: 1, unit: "kg" },
461
+ height: 180,
462
+ marginVertical: 8,
463
+ },
464
+ },
465
+ {
466
+ id: "weight-display",
467
+ type: "Text",
468
+ props: {
469
+ content: "Weight: {{weight}}",
470
+ mode: "expression",
471
+ fontSize: 14,
472
+ textAlign: "center",
473
+ opacity: 0.6,
474
+ marginVertical: 4,
475
+ },
476
+ },
432
477
  {
433
478
  id: "hero-carousel",
434
479
  type: "Carousel",
@@ -737,6 +782,8 @@ export const onboardingExample = {
737
782
  },
738
783
  },
739
784
  ],
785
+ },
786
+ ],
740
787
  },
741
788
  ],
742
789
  },
@@ -6,6 +6,8 @@ export type IconElementProps = BaseBoxProps & {
6
6
  size?: number;
7
7
  color?: string;
8
8
  strokeWidth?: number;
9
+ fill?: string;
10
+ fillOpacity?: number;
9
11
  backgroundColor?: string;
10
12
  };
11
13
 
@@ -14,5 +16,7 @@ export const IconElementPropsSchema = BaseBoxPropsSchema.extend({
14
16
  size: z.number().nonnegative().optional(),
15
17
  color: z.string().optional(),
16
18
  strokeWidth: z.number().nonnegative().optional(),
19
+ fill: z.string().optional(),
20
+ fillOpacity: z.number().min(0).max(1).optional(),
17
21
  backgroundColor: z.string().optional(),
18
22
  });
@@ -0,0 +1,115 @@
1
+ import { z } from "zod";
2
+ import { BaseBoxProps, BaseBoxPropsSchema } from "./BaseBoxProps";
3
+
4
+ export type WheelPickerItem = { label: string; value: string };
5
+
6
+ export type WheelPickerRange = {
7
+ min: number;
8
+ max: number;
9
+ step?: number;
10
+ unit?: string;
11
+ };
12
+
13
+ export type WheelPickerElementProps = BaseBoxProps & {
14
+ variableName?: string;
15
+ defaultValue?: string;
16
+ /** Explicit option list. Mutually exclusive with `range`. */
17
+ items?: WheelPickerItem[];
18
+ /** Numeric range that auto-generates options. Mutually exclusive with `items`. */
19
+ range?: WheelPickerRange;
20
+ /** Text color of the wheel items. */
21
+ itemColor?: string;
22
+ /** Font size of the wheel items (iOS `itemStyle`). */
23
+ itemFontSize?: number;
24
+ /** Font family of the wheel items (iOS `itemStyle`). */
25
+ itemFontFamily?: string;
26
+ };
27
+
28
+ // Hard cap on generated range items — guards against runaway ranges
29
+ // (e.g. min 0 / max 1e9 / step 0.01) producing millions of <Picker.Item>.
30
+ const RANGE_MAX_ITEMS = 1000;
31
+
32
+ /**
33
+ * Expand a numeric `range` into wheel items. Shared by the UI renderer,
34
+ * default-collection, and schema validation so all three agree on the exact
35
+ * generated value set (and its string formatting).
36
+ */
37
+ export function generateWheelPickerRangeItems(range: WheelPickerRange): WheelPickerItem[] {
38
+ const step = range.step ?? 1;
39
+ const items: WheelPickerItem[] = [];
40
+ if (!(step > 0) || range.max < range.min) return items;
41
+ for (let i = 0; i < RANGE_MAX_ITEMS; i++) {
42
+ const raw = range.min + i * step;
43
+ if (raw > range.max + 1e-9) break;
44
+ // Trim float accumulation noise (e.g. 0.30000000000000004 → 0.3).
45
+ const value = Math.round(raw * 1e6) / 1e6;
46
+ const valueStr = String(value);
47
+ const label = range.unit ? `${valueStr} ${range.unit}` : valueStr;
48
+ items.push({ label, value: valueStr });
49
+ }
50
+ return items;
51
+ }
52
+
53
+ /**
54
+ * Resolve the effective item list for a WheelPicker: explicit `items` win,
55
+ * otherwise the numeric `range` is expanded. Returns `[]` when neither is set.
56
+ */
57
+ export function resolveWheelPickerItems(props: WheelPickerElementProps): WheelPickerItem[] {
58
+ if (props.items && props.items.length > 0) return props.items;
59
+ if (props.range) return generateWheelPickerRangeItems(props.range);
60
+ return [];
61
+ }
62
+
63
+ const WheelPickerItemSchema = z.object({
64
+ label: z.string().trim().min(1, "item label must not be empty"),
65
+ value: z.string().trim().min(1, "item value must not be empty"),
66
+ });
67
+
68
+ const WheelPickerRangeSchema = z.object({
69
+ min: z.number(),
70
+ max: z.number(),
71
+ step: z.number().positive().optional(),
72
+ unit: z.string().optional(),
73
+ });
74
+
75
+ export const WheelPickerElementPropsSchema = BaseBoxPropsSchema.extend({
76
+ variableName: z.string().optional(),
77
+ defaultValue: z.string().optional(),
78
+ items: z.array(WheelPickerItemSchema).min(1, "items must not be empty").optional(),
79
+ range: WheelPickerRangeSchema.optional(),
80
+ itemColor: z.string().optional(),
81
+ itemFontSize: z.number().optional(),
82
+ itemFontFamily: z.string().optional(),
83
+ }).superRefine((data, ctx) => {
84
+ const hasItems = data.items !== undefined;
85
+ const hasRange = data.range !== undefined;
86
+ // Exactly one source must be present — both or neither is ambiguous.
87
+ if (hasItems === hasRange) {
88
+ ctx.addIssue({
89
+ code: z.ZodIssueCode.custom,
90
+ message: "provide exactly one of `items` or `range`",
91
+ path: hasItems ? ["range"] : ["items"],
92
+ });
93
+ return;
94
+ }
95
+ if (hasRange && data.range!.max < data.range!.min) {
96
+ ctx.addIssue({
97
+ code: z.ZodIssueCode.custom,
98
+ message: "range.max must be >= range.min",
99
+ path: ["range", "max"],
100
+ });
101
+ return;
102
+ }
103
+ const values = resolveWheelPickerItems(data as WheelPickerElementProps).map((i) => i.value);
104
+ const unique = new Set(values);
105
+ if (hasItems && unique.size !== values.length) {
106
+ ctx.addIssue({ code: z.ZodIssueCode.custom, message: "item values must be unique", path: ["items"] });
107
+ }
108
+ if (data.defaultValue !== undefined && !unique.has(data.defaultValue)) {
109
+ ctx.addIssue({
110
+ code: z.ZodIssueCode.custom,
111
+ message: "defaultValue must match one of the available values",
112
+ path: ["defaultValue"],
113
+ });
114
+ }
115
+ });
@@ -18,6 +18,7 @@ import { type ButtonElementProps, ButtonElementPropsSchema } from "./elements/Bu
18
18
  import { type RadioGroupElementProps, RadioGroupElementPropsSchema } from "./elements/RadioGroupElement";
19
19
  import { type CheckboxGroupElementProps, CheckboxGroupElementPropsSchema } from "./elements/CheckboxGroupElement";
20
20
  import { type DatePickerElementProps, DatePickerElementPropsSchema } from "./elements/DatePickerElement";
21
+ import { type WheelPickerElementProps, WheelPickerElementPropsSchema } from "./elements/WheelPickerElement";
21
22
  import { type CarouselElementProps, CarouselElementPropsSchema } from "./elements/CarouselElement";
22
23
  import { type ZStackElementProps, ZStackElementPropsSchema } from "./elements/ZStackElement";
23
24
  import { type SafeAreaViewElementProps, SafeAreaViewElementPropsSchema } from "./elements/SafeAreaViewElement";
@@ -42,6 +43,8 @@ export { ButtonActionSchema, CustomButtonActionSchema } from "./elements/ButtonE
42
43
  export type { RadioGroupElementProps } from "./elements/RadioGroupElement";
43
44
  export type { CheckboxGroupElementProps } from "./elements/CheckboxGroupElement";
44
45
  export type { DatePickerElementProps } from "./elements/DatePickerElement";
46
+ export type { WheelPickerElementProps, WheelPickerItem, WheelPickerRange } from "./elements/WheelPickerElement";
47
+ export { WheelPickerElementPropsSchema, generateWheelPickerRangeItems, resolveWheelPickerItems } from "./elements/WheelPickerElement";
45
48
  export type { CarouselElementProps } from "./elements/CarouselElement";
46
49
  export type { ZStackElementProps } from "./elements/ZStackElement";
47
50
  export type { SafeAreaViewElementProps, SafeAreaEdge, SafeAreaEdgeMode } from "./elements/SafeAreaViewElement";
@@ -156,6 +159,13 @@ type UIElement =
156
159
  type: "DatePicker";
157
160
  props: DatePickerElementProps;
158
161
  }
162
+ | {
163
+ id: string;
164
+ name?: string;
165
+ renderWhen?: LeafCondition | ConditionGroup;
166
+ type: "WheelPicker";
167
+ props: WheelPickerElementProps;
168
+ }
159
169
  | {
160
170
  id: string;
161
171
  name?: string;
@@ -284,6 +294,13 @@ const UIElementSchema: z.ZodType<UIElement> = z.lazy(() =>
284
294
  type: z.literal("DatePicker"),
285
295
  props: DatePickerElementPropsSchema,
286
296
  }),
297
+ z.object({
298
+ id: z.string(),
299
+ name: z.string().optional(),
300
+ renderWhen: z.union([LeafConditionSchema, ConditionGroupSchema]).optional(),
301
+ type: z.literal("WheelPicker"),
302
+ props: WheelPickerElementPropsSchema,
303
+ }),
287
304
  z.object({
288
305
  id: z.string(),
289
306
  name: z.string().optional(),