@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.
- package/dist/evaluateCondition.d.ts.map +1 -1
- package/dist/evaluateCondition.js +44 -1
- package/dist/evaluateCondition.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/onboarding-example.d.ts +2215 -1976
- package/dist/onboarding-example.d.ts.map +1 -1
- package/dist/onboarding-example.js +592 -545
- package/dist/onboarding-example.js.map +1 -1
- package/dist/steps/Carousel/types.d.ts +5 -1
- package/dist/steps/Carousel/types.d.ts.map +1 -1
- package/dist/steps/Commitment/types.d.ts +5 -1
- package/dist/steps/Commitment/types.d.ts.map +1 -1
- package/dist/steps/ComposableScreen/elements/ButtonElement.d.ts +5 -1
- package/dist/steps/ComposableScreen/elements/ButtonElement.d.ts.map +1 -1
- package/dist/steps/ComposableScreen/elements/IconElement.d.ts +4 -0
- package/dist/steps/ComposableScreen/elements/IconElement.d.ts.map +1 -1
- package/dist/steps/ComposableScreen/elements/IconElement.js +2 -0
- package/dist/steps/ComposableScreen/elements/IconElement.js.map +1 -1
- package/dist/steps/ComposableScreen/elements/WheelPickerElement.d.ts +124 -0
- package/dist/steps/ComposableScreen/elements/WheelPickerElement.d.ts.map +1 -0
- package/dist/steps/ComposableScreen/elements/WheelPickerElement.js +96 -0
- package/dist/steps/ComposableScreen/elements/WheelPickerElement.js.map +1 -0
- package/dist/steps/ComposableScreen/types.d.ts +14 -1
- package/dist/steps/ComposableScreen/types.d.ts.map +1 -1
- package/dist/steps/ComposableScreen/types.js +13 -1
- package/dist/steps/ComposableScreen/types.js.map +1 -1
- package/dist/steps/Loader/types.d.ts +5 -1
- package/dist/steps/Loader/types.d.ts.map +1 -1
- package/dist/steps/MediaContent/types.d.ts +5 -1
- package/dist/steps/MediaContent/types.d.ts.map +1 -1
- package/dist/steps/Picker/types.d.ts +5 -1
- package/dist/steps/Picker/types.d.ts.map +1 -1
- package/dist/steps/Question/types.d.ts +5 -1
- package/dist/steps/Question/types.d.ts.map +1 -1
- package/dist/steps/Ratings/types.d.ts +5 -1
- package/dist/steps/Ratings/types.d.ts.map +1 -1
- package/dist/steps/common.types.d.ts +30 -4
- package/dist/steps/common.types.d.ts.map +1 -1
- package/dist/steps/common.types.js +33 -3
- package/dist/steps/common.types.js.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/evaluateCondition.test.ts +35 -0
- package/src/evaluateCondition.ts +41 -1
- package/src/index.ts +8 -0
- package/src/onboarding-example.ts +47 -0
- package/src/steps/ComposableScreen/elements/IconElement.ts +4 -0
- package/src/steps/ComposableScreen/elements/WheelPickerElement.ts +115 -0
- package/src/steps/ComposableScreen/types.ts +17 -0
- 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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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":";;;AAAA,6BAAwB;AAEX,QAAA,mBAAmB,GAAG,OAAC,CAAC,MAAM,CAAC,OAAC,CAAC,MAAM,EAAE,EAAE,OAAC,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;AAE9D,QAAA,iBAAiB,GAAG,OAAC,CAAC,KAAK,CAAC;IACvC,OAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,OAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,OAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,OAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,OAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC7F,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE;KACxB,CAAC;IACF,OAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,OAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,OAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,OAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,OAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC7F,GAAG,EAAE,OAAC,CAAC,MAAM,EAAE;KAChB,CAAC;CACH,CAAC,CAAC;AAEU,QAAA,iBAAiB,GAAG,OAAC,CAAC,MAAM,CAAC;IACxC,YAAY,EAAE,OAAC,CAAC,MAAM,EAAE;IACxB,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE;IACnB,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE;CACvB,CAAC,CAAC;AAEU,QAAA,aAAa,GAAG,OAAC,CAAC,MAAM,CAAC;IACpC,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE;IACjB,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE;CACpB,CAAC,CAAC;AAEU,QAAA,mBAAmB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC1C,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;CAC3B,CAAC,CAAC;AAEH,gFAAgF;AAEnE,QAAA,uBAAuB,GAAG,OAAC,CAAC,IAAI,CAAC;IAC5C,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,IAAI;IACJ,KAAK;IACL,KAAK;IACL,UAAU;IACV,IAAI;IACJ,QAAQ;
|
|
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.
|
|
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/
|
|
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
|
// ---------------------------------------------------------------------------
|
package/src/evaluateCondition.ts
CHANGED
|
@@ -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(),
|