@rocapine/react-native-onboarding-ui 1.36.2 → 1.37.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 (63) hide show
  1. package/dist/UI/Pages/ComposableScreen/elements/BaseBoxProps.d.ts +26 -0
  2. package/dist/UI/Pages/ComposableScreen/elements/BaseBoxProps.d.ts.map +1 -1
  3. package/dist/UI/Pages/ComposableScreen/elements/BaseBoxProps.js +2 -0
  4. package/dist/UI/Pages/ComposableScreen/elements/BaseBoxProps.js.map +1 -1
  5. package/dist/UI/Pages/ComposableScreen/elements/ButtonElement.d.ts +106 -67
  6. package/dist/UI/Pages/ComposableScreen/elements/ButtonElement.d.ts.map +1 -1
  7. package/dist/UI/Pages/ComposableScreen/elements/ButtonElement.js +11 -59
  8. package/dist/UI/Pages/ComposableScreen/elements/ButtonElement.js.map +1 -1
  9. package/dist/UI/Pages/ComposableScreen/elements/CarouselElement.d.ts +24 -0
  10. package/dist/UI/Pages/ComposableScreen/elements/CarouselElement.d.ts.map +1 -1
  11. package/dist/UI/Pages/ComposableScreen/elements/CheckboxGroupElement.d.ts +24 -0
  12. package/dist/UI/Pages/ComposableScreen/elements/CheckboxGroupElement.d.ts.map +1 -1
  13. package/dist/UI/Pages/ComposableScreen/elements/DatePickerElement.d.ts +24 -0
  14. package/dist/UI/Pages/ComposableScreen/elements/DatePickerElement.d.ts.map +1 -1
  15. package/dist/UI/Pages/ComposableScreen/elements/IconElement.d.ts +24 -0
  16. package/dist/UI/Pages/ComposableScreen/elements/IconElement.d.ts.map +1 -1
  17. package/dist/UI/Pages/ComposableScreen/elements/ImageElement.d.ts +24 -0
  18. package/dist/UI/Pages/ComposableScreen/elements/ImageElement.d.ts.map +1 -1
  19. package/dist/UI/Pages/ComposableScreen/elements/InputElement.d.ts +24 -0
  20. package/dist/UI/Pages/ComposableScreen/elements/InputElement.d.ts.map +1 -1
  21. package/dist/UI/Pages/ComposableScreen/elements/KeyboardAvoidingViewElement.d.ts +24 -0
  22. package/dist/UI/Pages/ComposableScreen/elements/KeyboardAvoidingViewElement.d.ts.map +1 -1
  23. package/dist/UI/Pages/ComposableScreen/elements/LottieElement.d.ts +24 -0
  24. package/dist/UI/Pages/ComposableScreen/elements/LottieElement.d.ts.map +1 -1
  25. package/dist/UI/Pages/ComposableScreen/elements/ProgressIndicatorElement.d.ts +24 -0
  26. package/dist/UI/Pages/ComposableScreen/elements/ProgressIndicatorElement.d.ts.map +1 -1
  27. package/dist/UI/Pages/ComposableScreen/elements/ProgressiveBlurImageElement.d.ts +24 -0
  28. package/dist/UI/Pages/ComposableScreen/elements/ProgressiveBlurImageElement.d.ts.map +1 -1
  29. package/dist/UI/Pages/ComposableScreen/elements/RadioGroupElement.d.ts +24 -0
  30. package/dist/UI/Pages/ComposableScreen/elements/RadioGroupElement.d.ts.map +1 -1
  31. package/dist/UI/Pages/ComposableScreen/elements/RichTextElement.d.ts +24 -0
  32. package/dist/UI/Pages/ComposableScreen/elements/RichTextElement.d.ts.map +1 -1
  33. package/dist/UI/Pages/ComposableScreen/elements/RiveElement.d.ts +24 -0
  34. package/dist/UI/Pages/ComposableScreen/elements/RiveElement.d.ts.map +1 -1
  35. package/dist/UI/Pages/ComposableScreen/elements/SafeAreaViewElement.d.ts +24 -0
  36. package/dist/UI/Pages/ComposableScreen/elements/SafeAreaViewElement.d.ts.map +1 -1
  37. package/dist/UI/Pages/ComposableScreen/elements/ScrollViewElement.d.ts +24 -0
  38. package/dist/UI/Pages/ComposableScreen/elements/ScrollViewElement.d.ts.map +1 -1
  39. package/dist/UI/Pages/ComposableScreen/elements/StackElement.d.ts +24 -0
  40. package/dist/UI/Pages/ComposableScreen/elements/StackElement.d.ts.map +1 -1
  41. package/dist/UI/Pages/ComposableScreen/elements/TextElement.d.ts +25 -1
  42. package/dist/UI/Pages/ComposableScreen/elements/TextElement.d.ts.map +1 -1
  43. package/dist/UI/Pages/ComposableScreen/elements/VideoElement.d.ts +24 -0
  44. package/dist/UI/Pages/ComposableScreen/elements/VideoElement.d.ts.map +1 -1
  45. package/dist/UI/Pages/ComposableScreen/elements/ZStackElement.d.ts +24 -0
  46. package/dist/UI/Pages/ComposableScreen/elements/ZStackElement.d.ts.map +1 -1
  47. package/dist/UI/Pages/ComposableScreen/elements/actions.d.ts +72 -0
  48. package/dist/UI/Pages/ComposableScreen/elements/actions.d.ts.map +1 -0
  49. package/dist/UI/Pages/ComposableScreen/elements/actions.js +24 -0
  50. package/dist/UI/Pages/ComposableScreen/elements/actions.js.map +1 -0
  51. package/dist/UI/Pages/ComposableScreen/elements/renderElement.d.ts.map +1 -1
  52. package/dist/UI/Pages/ComposableScreen/elements/renderElement.js +47 -4
  53. package/dist/UI/Pages/ComposableScreen/elements/renderElement.js.map +1 -1
  54. package/dist/UI/Pages/ComposableScreen/elements/runActions.d.ts +4 -0
  55. package/dist/UI/Pages/ComposableScreen/elements/runActions.d.ts.map +1 -0
  56. package/dist/UI/Pages/ComposableScreen/elements/runActions.js +98 -0
  57. package/dist/UI/Pages/ComposableScreen/elements/runActions.js.map +1 -0
  58. package/package.json +1 -1
  59. package/src/UI/Pages/ComposableScreen/elements/BaseBoxProps.ts +3 -0
  60. package/src/UI/Pages/ComposableScreen/elements/ButtonElement.tsx +15 -91
  61. package/src/UI/Pages/ComposableScreen/elements/actions.ts +53 -0
  62. package/src/UI/Pages/ComposableScreen/elements/renderElement.tsx +59 -4
  63. package/src/UI/Pages/ComposableScreen/elements/runActions.ts +109 -0
@@ -1,8 +1,10 @@
1
1
  import React from "react";
2
+ import { Pressable } from "react-native";
2
3
  import { evaluateCondition } from "@rocapine/react-native-onboarding";
3
4
  import { UIElement } from "../types";
4
5
  import { BaseBoxProps } from "./BaseBoxProps";
5
6
  import { RenderContext } from "./shared";
7
+ import { runActions } from "./runActions";
6
8
  import { StackElementComponent } from "./StackElement";
7
9
  import { TextElementComponent } from "./TextElement";
8
10
  import { RichTextElementComponent } from "./RichTextElement";
@@ -26,6 +28,19 @@ import { KeyboardAvoidingViewElementComponent } from "./KeyboardAvoidingViewElem
26
28
  import { ProgressIndicatorElementComponent } from "./ProgressIndicatorElement";
27
29
  import { AnimatedBox } from "./AnimatedBox";
28
30
 
31
+ // Element types that own their own press / focus / scroll handling. The generic
32
+ // `onPress` (BaseBoxProps) is NOT wired for these — Button/RadioGroup/Checkbox/
33
+ // DatePicker already dispatch actions or selections; Input/WheelPicker would have
34
+ // their focus / scroll-selection intercepted by an outer Pressable.
35
+ const PRESS_HANDLED_TYPES = new Set<UIElement["type"]>([
36
+ "Button",
37
+ "RadioGroup",
38
+ "CheckboxGroup",
39
+ "DatePicker",
40
+ "Input",
41
+ "WheelPicker",
42
+ ]);
43
+
29
44
  export const renderElement = (
30
45
  element: UIElement,
31
46
  ctx: RenderContext,
@@ -128,12 +143,52 @@ export const renderElement = (
128
143
  return null;
129
144
  })();
130
145
 
146
+ // Cast to BaseBoxProps: not every element's props type extends it (e.g.
147
+ // WheelPicker), but the onPress/animation/transform/flex/alignSelf fields are
148
+ // all optional BaseBoxProps members and simply read as undefined when absent.
149
+ const p = element.props as BaseBoxProps;
150
+
151
+ // Generic onPress: make any non-pressable element tappable, dispatching the
152
+ // same action list as Button via runActions. Skipped for PRESS_HANDLED_TYPES.
153
+ // A Pressable around a scroll/carousel keeps inner scrolling working — RN's
154
+ // gesture responder gives the scroll the touch when it pans.
155
+ let content: React.ReactNode = node;
156
+ if (
157
+ content !== null &&
158
+ p.onPress &&
159
+ p.onPress.length > 0 &&
160
+ !PRESS_HANDLED_TYPES.has(element.type)
161
+ ) {
162
+ const onPress = p.onPress;
163
+ // The Pressable must be layout-transparent (like AnimatedBox): forward the
164
+ // element's flex sizing so the wrapper participates in its parent's flex
165
+ // context exactly as the element would. Without this, the style-less
166
+ // Pressable sizes to content while the element's `flex`/`flexShrink` sit on
167
+ // the inner node — breaking row splits (cards overflow) and column flow.
168
+ // Mirror StackElement's `parentType === "XStack"` flexShrink:1 default.
169
+ content = (
170
+ <Pressable
171
+ key={element.id}
172
+ onPress={() => {
173
+ void runActions(onPress, ctx);
174
+ }}
175
+ style={{
176
+ flex: p.flex,
177
+ flexGrow: p.flexGrow,
178
+ flexShrink: p.flexShrink ?? (parentType === "XStack" ? 1 : undefined),
179
+ alignSelf: p.alignSelf,
180
+ }}
181
+ >
182
+ {content}
183
+ </Pressable>
184
+ );
185
+ }
186
+
131
187
  // Wrap only when motion is requested — zero overhead (no extra view) otherwise.
132
188
  // Cast to BaseBoxProps: not every element's props type extends it (e.g.
133
189
  // WheelPicker), but the animation/transform/flex/alignSelf fields are all
134
190
  // optional BaseBoxProps members and simply read as undefined when absent.
135
- const p = element.props as BaseBoxProps;
136
- if (node !== null && (p.animation || p.transform)) {
191
+ if (content !== null && (p.animation || p.transform)) {
137
192
  return (
138
193
  <AnimatedBox
139
194
  key={element.id}
@@ -142,10 +197,10 @@ export const renderElement = (
142
197
  flex={p.flex}
143
198
  alignSelf={p.alignSelf}
144
199
  >
145
- {node}
200
+ {content}
146
201
  </AnimatedBox>
147
202
  );
148
203
  }
149
204
 
150
- return node;
205
+ return content;
151
206
  };
@@ -0,0 +1,109 @@
1
+ import type {
2
+ ComposableVariableEntry,
3
+ ComposableVariableKind,
4
+ } from "@rocapine/react-native-onboarding";
5
+ import type { ButtonAction } from "./actions";
6
+ import type { RenderContext } from "./shared";
7
+ import { evaluateSetVariableExpression } from "./expression";
8
+
9
+ // Decode a multi-select variable's stored value (JSON-encoded string[], as
10
+ // written by CheckboxGroup) into a string array. Tolerates undefined / non-array
11
+ // / unparseable input by returning [].
12
+ function decodeArrayValue(raw: string | undefined): string[] {
13
+ if (!raw) return [];
14
+ try {
15
+ const parsed = JSON.parse(raw);
16
+ return Array.isArray(parsed) ? parsed.map(String) : [];
17
+ } catch {
18
+ return [];
19
+ }
20
+ }
21
+
22
+ // Sequentially runs a list of press actions against the render context. Shared
23
+ // by `Button` (its `actions`) and the generic `onPress` on every UIElement
24
+ // (wired centrally in renderElement.tsx). Semantics:
25
+ // - "continue" → advance the onboarding; terminal (stops the loop).
26
+ // - {setVariable} → write a variable (expression-evaluated when valueMode === "expression").
27
+ // - {custom} → invoke the host-registered customAction with the requested
28
+ // variables; warns if unregistered, aborts the loop on throw.
29
+ export async function runActions(
30
+ actions: ButtonAction[],
31
+ ctx: RenderContext
32
+ ): Promise<void> {
33
+ const { onContinue, setVariable, customActions, variables } = ctx;
34
+
35
+ for (const act of actions) {
36
+ if (act === "continue") {
37
+ onContinue();
38
+ return;
39
+ }
40
+ if (act.type === "setVariable") {
41
+ let value: string;
42
+ let kind: ComposableVariableKind | undefined;
43
+ if (act.valueMode === "expression") {
44
+ const computed = evaluateSetVariableExpression(act.value, variables);
45
+ value = computed.value;
46
+ kind = computed.kind;
47
+ } else {
48
+ value = act.value;
49
+ kind = act.kind;
50
+ }
51
+
52
+ if (act.arrayOp) {
53
+ // Multi-select set operation on the JSON-encoded string[] used by
54
+ // CheckboxGroup. value/label are the single member being added/removed.
55
+ const entry = variables[act.name];
56
+ const curValues = decodeArrayValue(entry?.value);
57
+ const curLabels = entry?.label ? entry.label.split(", ") : [];
58
+ const memberLabel = act.label ?? value;
59
+ const idx = curValues.indexOf(value);
60
+ const present = idx !== -1;
61
+ const add =
62
+ act.arrayOp === "append" || (act.arrayOp === "toggle" && !present);
63
+
64
+ let nextValues: string[];
65
+ let nextLabels: string[];
66
+ if (add) {
67
+ // Dedup: appending an already-present member is a no-op.
68
+ nextValues = present ? curValues : [...curValues, value];
69
+ nextLabels = present ? curLabels : [...curLabels, memberLabel];
70
+ } else {
71
+ // remove, or toggle-when-present
72
+ nextValues = curValues.filter((_, i) => i !== idx);
73
+ nextLabels =
74
+ present && idx < curLabels.length
75
+ ? curLabels.filter((_, i) => i !== idx)
76
+ : curLabels.filter((l) => l !== memberLabel);
77
+ }
78
+
79
+ setVariable(act.name, {
80
+ value: JSON.stringify(nextValues),
81
+ label: nextLabels.join(", "),
82
+ });
83
+ continue;
84
+ }
85
+
86
+ setVariable(act.name, { value, label: act.label, kind });
87
+ continue;
88
+ }
89
+ const handler = customActions[act.function];
90
+ if (!handler) {
91
+ console.warn(
92
+ `[ComposableScreen] No customAction registered for "${act.function}"`
93
+ );
94
+ continue;
95
+ }
96
+ const requested = act.variables ?? [];
97
+ const vars: Record<string, ComposableVariableEntry | undefined> = {};
98
+ for (const name of requested) vars[name] = variables[name];
99
+ try {
100
+ await handler({ variables: vars });
101
+ } catch (err) {
102
+ console.error(
103
+ `[ComposableScreen] customAction "${act.function}" threw:`,
104
+ err
105
+ );
106
+ return;
107
+ }
108
+ }
109
+ }