@getrheo/rheo-skill 2.1.0 → 2.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getrheo/rheo-skill",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "type": "module",
5
5
  "description": "Rheo agent skill — SDK install guidance and flow manifest import tooling.",
6
6
  "main": "./src/index.ts",
@@ -9,8 +9,8 @@
9
9
  ".": "./src/index.ts"
10
10
  },
11
11
  "dependencies": {
12
- "@getrheo/contracts": "2.1.0",
13
- "@getrheo/flow-runtime": "2.1.0",
12
+ "@getrheo/contracts": "2.2.0",
13
+ "@getrheo/flow-runtime": "2.2.0",
14
14
  "zod": "^3.23.8"
15
15
  },
16
16
  "devDependencies": {
@@ -19,8 +19,8 @@
19
19
  "tsx": "^4.19.2",
20
20
  "typescript": "^5.6.3",
21
21
  "vitest": "^3.2.6",
22
- "@rheo/contracts-fixtures": "0.0.0",
23
- "@rheo/config": "0.1.0"
22
+ "@rheo/config": "0.1.0",
23
+ "@rheo/contracts-fixtures": "0.0.0"
24
24
  },
25
25
  "files": [
26
26
  "README.md",
package/rheo/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: rheo
3
3
  description: Work with Rheo, the headless onboarding/paywall flow engine for mobile apps. Use when a user wants to install or wire the Rheo SDK (React Native, Expo, or SwiftUI), follow Rheo SDK best practices, configure integrations (RevenueCat, AppsFlyer), wire auth/permissions/terminal callbacks, OR import/migrate an existing mobile flow into a compliant Rheo FlowManifest and validate it. Routes to the `rheo-best-practices` and `rheo-flow-import` sub-skills.
4
4
  compatibility: Requires Node.js 20+. rheo-flow-import scripts are fully self-contained (no install step). Internet access fetches the latest Manifest Agent Profile; a bundled fallback works offline.
5
5
  metadata:
6
- rheo-version: "2.1.0"
6
+ rheo-version: "2.2.0"
7
7
  manifest-schema-version: "7"
8
8
  ---
9
9
 
@@ -60,8 +60,8 @@ Valid `action.kind` values on `button` layers:
60
60
  - `play_media`
61
61
  - `request_app_review`
62
62
 
63
- - `go_to_step` requires `screenId`.
64
- - `go_back_one_screen` accepts optional `fallbackScreenId`.
63
+ - `FlowGraphNodeJumpTarget` (`scr_*` | `dec_*` | `surf_*`): `go_to_step.screenId`, choice `branching.conditions[].goTo`, loader/lottie/video `onComplete` when mode is `screen`, and `request_os_permission` outcomes (except `continue`/`end`).
64
+ - `go_back_one_screen` and `back_button` accept optional `fallbackScreenId` (`scr_*` only).
65
65
  - `request_os_permission` requires `permissionKey` and `outcomes` (`granted`/`denied`/`blocked`).
66
66
  - `play_media` requires `targetLayerIds` (≥1) pointing at Lottie/video layers on the same screen.
67
67
  - `back_button` takes **no** `action` (back navigation is built in).
@@ -89,8 +89,8 @@ enum automatically.
89
89
 
90
90
  Action shorthands: `"none"`, `"continue"`, `"skip"`, `"end_flow"`,
91
91
  `"go_back_one_screen"`, `"request_app_review"`. Object forms:
92
- `{ "kind": "go_to_step", "screenId": "scr_x" }`,
93
- `{ "kind": "request_os_permission", "permissionKey": "…", "outcomes": { "granted": "scr_a", "denied": "scr_b", "blocked": "scr_c" } }`,
92
+ `{ "kind": "go_to_step", "screenId": "scr_x" }` (or `dec_*` / `surf_*`),
93
+ `{ "kind": "request_os_permission", "permissionKey": "…", "outcomes": { "granted": "scr_a", "denied": "dec_b", "blocked": "surf_c" } }` (targets may be `scr_*`, `dec_*`, `surf_*`, `"continue"`, or `"end"`),
94
94
  `{ "kind": "play_media", "targetLayerIds": ["lyr_video"] }`.
95
95
 
96
96
  ### Stacks (layout)
@@ -127,6 +127,7 @@ Map unselected chrome to `style` and selected chrome to `selectedStyle` per opti
127
127
 
128
128
  `multiple_choice` adds optional `minSelections`/`maxSelections`. To branch per
129
129
  option, set `branching: { "enabled": true, "conditions": [{ "choiceId": "male", "goTo": "scr_x" }] }`.
130
+ `goTo` may be any `FlowGraphNodeJumpTarget` (`scr_*`, `dec_*`, or `surf_*`).
130
131
 
131
132
  ### Inputs
132
133
 
@@ -182,6 +183,7 @@ No buttons inside a carousel — paging is swipe-only ([carousel-import.md](caro
182
183
  { "kind": "progress", "fillColor": "#6D5DF6", "trackColor": "#E5E7EB" }
183
184
  { "kind": "counter", "startValue": 0, "endValue": 1000, "durationMs": 1200 }
184
185
  { "kind": "loader", "variant": "circular", "targetPercent": 100, "onComplete": { "mode": "next" } }
186
+ { "kind": "loader", "onComplete": { "mode": "screen", "screenId": "dec_next" } } // screenId: scr_* | dec_* | surf_*
185
187
  ```
186
188
 
187
189
  ## Decisions and external surfaces
@@ -50,7 +50,7 @@ Use only: `stack`, `text`, `image`, `lottie`, `video`, `icon`, `button`, `back_b
50
50
  - Text copy goes in `text.default`.
51
51
  - Button labels are nested text layers.
52
52
  - `button` / `back_button` `variant` must be `primary`, `secondary`, `ghost`, or `destructive` (map source `outline`/`text`/`link` — do not copy). `back_button` has no `action`.
53
- - `single_choice` / `multiple_choice` require `fieldKey`, `children`, `optionBindings`, and `branching` — never `"options"` arrays.
53
+ - `single_choice` / `multiple_choice` require `fieldKey`, `children`, `optionBindings`, and `branching` — never `"options"` arrays. `branching.conditions[].goTo` may target `scr_*`, `dec_*`, or `surf_*`.
54
54
  - Use `regions.header` for top chrome such as back buttons and progress, `regions.body` for main content, and `regions.footer` for sticky bottom CTAs.
55
55
  - Inspect theme/style/token files, StyleSheet, and Tailwind classes before using black-and-white defaults.
56
56
  - Set `style.color` on text for dark/saturated screen backgrounds.
@@ -29,7 +29,7 @@ These mirror `apps/web/src/features/builder/validateFlow.ts` and API `preflightP
29
29
  | **Continue button** | `text_input`, `multiple_choice`, or `scale_input` without a `button` with `action.kind: "continue"`. |
30
30
  | **One input per screen** | Multiple inputs, or OAuth/email-password combined with inputs. |
31
31
  | **fieldKey** | Missing or non–snake_case on input layers. |
32
- | **Graph targets** | `go_to_step`, choice `goTo`, permission outcomes, fallbacks point at missing ids. |
32
+ | **Graph targets** | `go_to_step`, choice `goTo`, loader/lottie/video `onComplete` (screen mode), permission outcomes, and fallbacks point at missing `scr_*` / `dec_*` / `surf_*` ids. |
33
33
  | **Media triggers** | Lottie/video with `autoPlay: false` needs a `play_media` button targeting that layer. |
34
34
  | **Screen backgrounds** | Image/video fills need `mediaAssetId`; manual background video needs trigger wiring. |
35
35
 
@@ -4196,9 +4196,10 @@ var ThemedColorModesSchema = external_exports.object({
4196
4196
  message: "at least one of light or dark is required"
4197
4197
  });
4198
4198
  var ThemedColorSchema = external_exports.union([external_exports.string().min(1), ThemedColorModesSchema]);
4199
- var WIDTH_PRESETS = ["auto", "full", "1/2", "1/3", "2/3", "1/4", "3/4"];
4199
+ var LAYOUT_FRACTION_PRESETS = ["1/2", "1/3", "2/3", "1/4", "3/4"];
4200
+ var WIDTH_PRESETS = ["auto", "full", ...LAYOUT_FRACTION_PRESETS];
4200
4201
  var WidthValueSchema = external_exports.union([external_exports.enum(WIDTH_PRESETS), external_exports.number().int().min(0).max(2e3)]);
4201
- var HEIGHT_PRESETS = ["auto", "full", "fill"];
4202
+ var HEIGHT_PRESETS = ["auto", "full", "fill", ...LAYOUT_FRACTION_PRESETS];
4202
4203
  var CommonLayoutHeightSchema = external_exports.union([
4203
4204
  external_exports.enum(HEIGHT_PRESETS),
4204
4205
  external_exports.number().int().min(0).max(2e3)
@@ -4238,7 +4239,7 @@ var CommonStyleSchema = external_exports.object({
4238
4239
  zIndex: external_exports.number().int().min(-999).max(999).optional(),
4239
4240
  /** Static rotation in degrees (CSS `rotate`); not timeline animation. */
4240
4241
  rotate: external_exports.number().min(-360).max(360).optional(),
4241
- /** Cross-axis size: `auto` (hug), `full`/`fill` (parent height), or fixed px. No fractions. */
4242
+ /** Cross-axis size: `auto` (hug), `full`/`fill` (parent height), fractions, or fixed px. */
4242
4243
  height: CommonLayoutHeightSchema.optional(),
4243
4244
  /** Stroke thickness in px for layers that render a stroke primitive (e.g. loader ring). */
4244
4245
  strokeWidth: external_exports.number().int().min(0).max(64).optional()
@@ -4330,6 +4331,11 @@ var ButtonLayoutBreakpointsSchema = external_exports.object({
4330
4331
  xl: ButtonLayoutBreakpointPatchSchema.optional(),
4331
4332
  "2xl": ButtonLayoutBreakpointPatchSchema.optional()
4332
4333
  }).partial().optional();
4334
+ var DecisionNodeJumpIdSchema = external_exports.string().min(1).max(64).regex(/^dec_[a-z0-9_]+$/i);
4335
+ var ExternalSurfaceJumpIdSchema = external_exports.string().min(1).max(64).regex(/^surf_[a-z0-9_]+$/i);
4336
+ var FlowGraphNodeJumpTargetSchema = ScreenIdSchema.or(DecisionNodeJumpIdSchema).or(
4337
+ ExternalSurfaceJumpIdSchema
4338
+ );
4333
4339
  var OS_PERMISSION_KEYS = [
4334
4340
  "notifications",
4335
4341
  "camera",
@@ -4359,11 +4365,9 @@ var PERMISSION_OUTCOME_VALUES = ["granted", "denied", "blocked"];
4359
4365
  var PermissionOutcomeSchema = external_exports.enum(PERMISSION_OUTCOME_VALUES);
4360
4366
  var OS_PERMISSION_OUTCOME_CONTINUE = "continue";
4361
4367
  var OS_PERMISSION_OUTCOME_END = "end";
4362
- var OsPermissionOutcomeBranchTargetSchema = external_exports.union([
4363
- ScreenIdSchema,
4364
- external_exports.literal(OS_PERMISSION_OUTCOME_CONTINUE),
4365
- external_exports.literal(OS_PERMISSION_OUTCOME_END)
4366
- ]);
4368
+ var OsPermissionOutcomeBranchTargetSchema = FlowGraphNodeJumpTargetSchema.or(
4369
+ external_exports.literal(OS_PERMISSION_OUTCOME_CONTINUE)
4370
+ ).or(external_exports.literal(OS_PERMISSION_OUTCOME_END));
4367
4371
  var OsPermissionOutcomesSchema = external_exports.object({
4368
4372
  granted: OsPermissionOutcomeBranchTargetSchema,
4369
4373
  denied: OsPermissionOutcomeBranchTargetSchema,
@@ -4380,7 +4384,7 @@ var ButtonActionSchema = external_exports.discriminatedUnion("kind", [
4380
4384
  kind: external_exports.literal("go_back_one_screen"),
4381
4385
  fallbackScreenId: ScreenIdSchema.optional()
4382
4386
  }),
4383
- external_exports.object({ kind: external_exports.literal("go_to_step"), screenId: ScreenIdSchema }),
4387
+ external_exports.object({ kind: external_exports.literal("go_to_step"), screenId: FlowGraphNodeJumpTargetSchema }),
4384
4388
  external_exports.object({
4385
4389
  kind: external_exports.literal("request_os_permission"),
4386
4390
  permissionKey: OsPermissionKeySchema,
@@ -4462,7 +4466,7 @@ var ProgressLayerSchema = external_exports.object({
4462
4466
  var LoaderOnCompleteSchema = external_exports.discriminatedUnion("mode", [
4463
4467
  external_exports.object({ mode: external_exports.literal("none") }),
4464
4468
  external_exports.object({ mode: external_exports.literal("next") }),
4465
- external_exports.object({ mode: external_exports.literal("screen"), screenId: ScreenIdSchema })
4469
+ external_exports.object({ mode: external_exports.literal("screen"), screenId: FlowGraphNodeJumpTargetSchema })
4466
4470
  ]);
4467
4471
  var LoaderLayerSchema = external_exports.object({
4468
4472
  ...baseLayerShape,
@@ -4943,7 +4947,7 @@ var ChoiceOptionBindingSchema = external_exports.object({
4943
4947
  });
4944
4948
  var BranchConditionSchema = external_exports.object({
4945
4949
  choiceId: external_exports.string().min(1),
4946
- goTo: ScreenIdSchema
4950
+ goTo: FlowGraphNodeJumpTargetSchema
4947
4951
  });
4948
4952
  var ChoiceBranchingSchema = external_exports.object({
4949
4953
  enabled: external_exports.boolean(),
@@ -5242,9 +5246,10 @@ var ThemedColorModesSchema2 = external_exports.object({
5242
5246
  message: "at least one of light or dark is required"
5243
5247
  });
5244
5248
  var ThemedColorSchema2 = external_exports.union([external_exports.string().min(1), ThemedColorModesSchema2]);
5245
- var WIDTH_PRESETS2 = ["auto", "full", "1/2", "1/3", "2/3", "1/4", "3/4"];
5249
+ var LAYOUT_FRACTION_PRESETS2 = ["1/2", "1/3", "2/3", "1/4", "3/4"];
5250
+ var WIDTH_PRESETS2 = ["auto", "full", ...LAYOUT_FRACTION_PRESETS2];
5246
5251
  var WidthValueSchema2 = external_exports.union([external_exports.enum(WIDTH_PRESETS2), external_exports.number().int().min(0).max(2e3)]);
5247
- var HEIGHT_PRESETS2 = ["auto", "full", "fill"];
5252
+ var HEIGHT_PRESETS2 = ["auto", "full", "fill", ...LAYOUT_FRACTION_PRESETS2];
5248
5253
  var CommonLayoutHeightSchema2 = external_exports.union([
5249
5254
  external_exports.enum(HEIGHT_PRESETS2),
5250
5255
  external_exports.number().int().min(0).max(2e3)
@@ -5284,7 +5289,7 @@ var CommonStyleSchema2 = external_exports.object({
5284
5289
  zIndex: external_exports.number().int().min(-999).max(999).optional(),
5285
5290
  /** Static rotation in degrees (CSS `rotate`); not timeline animation. */
5286
5291
  rotate: external_exports.number().min(-360).max(360).optional(),
5287
- /** Cross-axis size: `auto` (hug), `full`/`fill` (parent height), or fixed px. No fractions. */
5292
+ /** Cross-axis size: `auto` (hug), `full`/`fill` (parent height), fractions, or fixed px. */
5288
5293
  height: CommonLayoutHeightSchema2.optional(),
5289
5294
  /** Stroke thickness in px for layers that render a stroke primitive (e.g. loader ring). */
5290
5295
  strokeWidth: external_exports.number().int().min(0).max(64).optional()
@@ -5376,6 +5381,11 @@ var ButtonLayoutBreakpointsSchema2 = external_exports.object({
5376
5381
  xl: ButtonLayoutBreakpointPatchSchema2.optional(),
5377
5382
  "2xl": ButtonLayoutBreakpointPatchSchema2.optional()
5378
5383
  }).partial().optional();
5384
+ var DecisionNodeJumpIdSchema2 = external_exports.string().min(1).max(64).regex(/^dec_[a-z0-9_]+$/i);
5385
+ var ExternalSurfaceJumpIdSchema2 = external_exports.string().min(1).max(64).regex(/^surf_[a-z0-9_]+$/i);
5386
+ var FlowGraphNodeJumpTargetSchema2 = ScreenIdSchema2.or(DecisionNodeJumpIdSchema2).or(
5387
+ ExternalSurfaceJumpIdSchema2
5388
+ );
5379
5389
  var OS_PERMISSION_KEYS2 = [
5380
5390
  "notifications",
5381
5391
  "camera",
@@ -5405,11 +5415,9 @@ var PERMISSION_OUTCOME_VALUES2 = ["granted", "denied", "blocked"];
5405
5415
  external_exports.enum(PERMISSION_OUTCOME_VALUES2);
5406
5416
  var OS_PERMISSION_OUTCOME_CONTINUE2 = "continue";
5407
5417
  var OS_PERMISSION_OUTCOME_END2 = "end";
5408
- var OsPermissionOutcomeBranchTargetSchema2 = external_exports.union([
5409
- ScreenIdSchema2,
5410
- external_exports.literal(OS_PERMISSION_OUTCOME_CONTINUE2),
5411
- external_exports.literal(OS_PERMISSION_OUTCOME_END2)
5412
- ]);
5418
+ var OsPermissionOutcomeBranchTargetSchema2 = FlowGraphNodeJumpTargetSchema2.or(
5419
+ external_exports.literal(OS_PERMISSION_OUTCOME_CONTINUE2)
5420
+ ).or(external_exports.literal(OS_PERMISSION_OUTCOME_END2));
5413
5421
  var OsPermissionOutcomesSchema2 = external_exports.object({
5414
5422
  granted: OsPermissionOutcomeBranchTargetSchema2,
5415
5423
  denied: OsPermissionOutcomeBranchTargetSchema2,
@@ -5426,7 +5434,7 @@ var ButtonActionSchema2 = external_exports.discriminatedUnion("kind", [
5426
5434
  kind: external_exports.literal("go_back_one_screen"),
5427
5435
  fallbackScreenId: ScreenIdSchema2.optional()
5428
5436
  }),
5429
- external_exports.object({ kind: external_exports.literal("go_to_step"), screenId: ScreenIdSchema2 }),
5437
+ external_exports.object({ kind: external_exports.literal("go_to_step"), screenId: FlowGraphNodeJumpTargetSchema2 }),
5430
5438
  external_exports.object({
5431
5439
  kind: external_exports.literal("request_os_permission"),
5432
5440
  permissionKey: OsPermissionKeySchema2,
@@ -5508,7 +5516,7 @@ var ProgressLayerSchema2 = external_exports.object({
5508
5516
  var LoaderOnCompleteSchema2 = external_exports.discriminatedUnion("mode", [
5509
5517
  external_exports.object({ mode: external_exports.literal("none") }),
5510
5518
  external_exports.object({ mode: external_exports.literal("next") }),
5511
- external_exports.object({ mode: external_exports.literal("screen"), screenId: ScreenIdSchema2 })
5519
+ external_exports.object({ mode: external_exports.literal("screen"), screenId: FlowGraphNodeJumpTargetSchema2 })
5512
5520
  ]);
5513
5521
  var LoaderLayerSchema2 = external_exports.object({
5514
5522
  ...baseLayerShape2,
@@ -5989,7 +5997,7 @@ var ChoiceOptionBindingSchema2 = external_exports.object({
5989
5997
  });
5990
5998
  var BranchConditionSchema2 = external_exports.object({
5991
5999
  choiceId: external_exports.string().min(1),
5992
- goTo: ScreenIdSchema2
6000
+ goTo: FlowGraphNodeJumpTargetSchema2
5993
6001
  });
5994
6002
  var ChoiceBranchingSchema2 = external_exports.object({
5995
6003
  enabled: external_exports.boolean(),
@@ -6137,10 +6145,10 @@ layerSchemaStore2.schema = external_exports.lazy(
6137
6145
  ])
6138
6146
  );
6139
6147
  var DecisionNodeIdSchema = external_exports.string().min(1).max(64).regex(/^dec_[a-z0-9_]+$/i, "decision node id must look like dec_<id>");
6140
- var ExternalSurfaceJumpIdSchema = external_exports.string().min(1).max(64).regex(/^surf_[a-z0-9_]+$/i, "external surface node id must look like surf_<id>");
6148
+ var ExternalSurfaceJumpIdSchema22 = external_exports.string().min(1).max(64).regex(/^surf_[a-z0-9_]+$/i, "external surface node id must look like surf_<id>");
6141
6149
  var EXTERNAL_SURFACE_NO_NEXT = "__onb_surface_no_next__";
6142
6150
  var ExternalSurfaceTerminalTargetSchema = external_exports.literal(EXTERNAL_SURFACE_NO_NEXT);
6143
- var FlowJumpTargetSchema = ScreenIdSchema2.or(DecisionNodeIdSchema).or(ExternalSurfaceJumpIdSchema).or(ExternalSurfaceTerminalTargetSchema).nullable();
6151
+ var FlowJumpTargetSchema = ScreenIdSchema2.or(DecisionNodeIdSchema).or(ExternalSurfaceJumpIdSchema22).or(ExternalSurfaceTerminalTargetSchema).nullable();
6144
6152
  var DecisionBuiltinNameSchema = external_exports.enum(["locale", "platform"]);
6145
6153
  var DecisionVariableRefSchema = external_exports.discriminatedUnion("kind", [
6146
6154
  external_exports.object({ kind: external_exports.literal("builtin"), name: DecisionBuiltinNameSchema }),
@@ -6407,9 +6415,10 @@ var ThemedColorModesSchema3 = external_exports.object({
6407
6415
  message: "at least one of light or dark is required"
6408
6416
  });
6409
6417
  var ThemedColorSchema3 = external_exports.union([external_exports.string().min(1), ThemedColorModesSchema3]);
6410
- var WIDTH_PRESETS3 = ["auto", "full", "1/2", "1/3", "2/3", "1/4", "3/4"];
6418
+ var LAYOUT_FRACTION_PRESETS3 = ["1/2", "1/3", "2/3", "1/4", "3/4"];
6419
+ var WIDTH_PRESETS3 = ["auto", "full", ...LAYOUT_FRACTION_PRESETS3];
6411
6420
  var WidthValueSchema3 = external_exports.union([external_exports.enum(WIDTH_PRESETS3), external_exports.number().int().min(0).max(2e3)]);
6412
- var HEIGHT_PRESETS3 = ["auto", "full", "fill"];
6421
+ var HEIGHT_PRESETS3 = ["auto", "full", "fill", ...LAYOUT_FRACTION_PRESETS3];
6413
6422
  var CommonLayoutHeightSchema3 = external_exports.union([
6414
6423
  external_exports.enum(HEIGHT_PRESETS3),
6415
6424
  external_exports.number().int().min(0).max(2e3)
@@ -6449,7 +6458,7 @@ var CommonStyleSchema3 = external_exports.object({
6449
6458
  zIndex: external_exports.number().int().min(-999).max(999).optional(),
6450
6459
  /** Static rotation in degrees (CSS `rotate`); not timeline animation. */
6451
6460
  rotate: external_exports.number().min(-360).max(360).optional(),
6452
- /** Cross-axis size: `auto` (hug), `full`/`fill` (parent height), or fixed px. No fractions. */
6461
+ /** Cross-axis size: `auto` (hug), `full`/`fill` (parent height), fractions, or fixed px. */
6453
6462
  height: CommonLayoutHeightSchema3.optional(),
6454
6463
  /** Stroke thickness in px for layers that render a stroke primitive (e.g. loader ring). */
6455
6464
  strokeWidth: external_exports.number().int().min(0).max(64).optional()
@@ -6541,6 +6550,11 @@ var ButtonLayoutBreakpointsSchema3 = external_exports.object({
6541
6550
  xl: ButtonLayoutBreakpointPatchSchema3.optional(),
6542
6551
  "2xl": ButtonLayoutBreakpointPatchSchema3.optional()
6543
6552
  }).partial().optional();
6553
+ var DecisionNodeJumpIdSchema3 = external_exports.string().min(1).max(64).regex(/^dec_[a-z0-9_]+$/i);
6554
+ var ExternalSurfaceJumpIdSchema3 = external_exports.string().min(1).max(64).regex(/^surf_[a-z0-9_]+$/i);
6555
+ var FlowGraphNodeJumpTargetSchema3 = ScreenIdSchema3.or(DecisionNodeJumpIdSchema3).or(
6556
+ ExternalSurfaceJumpIdSchema3
6557
+ );
6544
6558
  var OS_PERMISSION_KEYS3 = [
6545
6559
  "notifications",
6546
6560
  "camera",
@@ -6572,11 +6586,9 @@ var PERMISSION_OUTCOME_VALUES3 = ["granted", "denied", "blocked"];
6572
6586
  var PermissionOutcomeSchema2 = external_exports.enum(PERMISSION_OUTCOME_VALUES3);
6573
6587
  var OS_PERMISSION_OUTCOME_CONTINUE3 = "continue";
6574
6588
  var OS_PERMISSION_OUTCOME_END3 = "end";
6575
- var OsPermissionOutcomeBranchTargetSchema3 = external_exports.union([
6576
- ScreenIdSchema3,
6577
- external_exports.literal(OS_PERMISSION_OUTCOME_CONTINUE3),
6578
- external_exports.literal(OS_PERMISSION_OUTCOME_END3)
6579
- ]);
6589
+ var OsPermissionOutcomeBranchTargetSchema3 = FlowGraphNodeJumpTargetSchema3.or(
6590
+ external_exports.literal(OS_PERMISSION_OUTCOME_CONTINUE3)
6591
+ ).or(external_exports.literal(OS_PERMISSION_OUTCOME_END3));
6580
6592
  var OsPermissionOutcomesSchema3 = external_exports.object({
6581
6593
  granted: OsPermissionOutcomeBranchTargetSchema3,
6582
6594
  denied: OsPermissionOutcomeBranchTargetSchema3,
@@ -6593,7 +6605,7 @@ var ButtonActionSchema3 = external_exports.discriminatedUnion("kind", [
6593
6605
  kind: external_exports.literal("go_back_one_screen"),
6594
6606
  fallbackScreenId: ScreenIdSchema3.optional()
6595
6607
  }),
6596
- external_exports.object({ kind: external_exports.literal("go_to_step"), screenId: ScreenIdSchema3 }),
6608
+ external_exports.object({ kind: external_exports.literal("go_to_step"), screenId: FlowGraphNodeJumpTargetSchema3 }),
6597
6609
  external_exports.object({
6598
6610
  kind: external_exports.literal("request_os_permission"),
6599
6611
  permissionKey: OsPermissionKeySchema3,
@@ -6675,7 +6687,7 @@ var ProgressLayerSchema3 = external_exports.object({
6675
6687
  var LoaderOnCompleteSchema3 = external_exports.discriminatedUnion("mode", [
6676
6688
  external_exports.object({ mode: external_exports.literal("none") }),
6677
6689
  external_exports.object({ mode: external_exports.literal("next") }),
6678
- external_exports.object({ mode: external_exports.literal("screen"), screenId: ScreenIdSchema3 })
6690
+ external_exports.object({ mode: external_exports.literal("screen"), screenId: FlowGraphNodeJumpTargetSchema3 })
6679
6691
  ]);
6680
6692
  var LoaderLayerSchema3 = external_exports.object({
6681
6693
  ...baseLayerShape3,
@@ -7153,7 +7165,7 @@ var ChoiceOptionBindingSchema3 = external_exports.object({
7153
7165
  });
7154
7166
  var BranchConditionSchema3 = external_exports.object({
7155
7167
  choiceId: external_exports.string().min(1),
7156
- goTo: ScreenIdSchema3
7168
+ goTo: FlowGraphNodeJumpTargetSchema3
7157
7169
  });
7158
7170
  var ChoiceBranchingSchema3 = external_exports.object({
7159
7171
  enabled: external_exports.boolean(),
@@ -7560,10 +7572,10 @@ var ScreenContainerStyleBreakpointsSchema = external_exports.object({
7560
7572
  "2xl": ScreenContainerBreakpointPatchSchema.optional()
7561
7573
  }).partial().optional();
7562
7574
  var DecisionNodeIdSchema2 = external_exports.string().min(1).max(64).regex(/^dec_[a-z0-9_]+$/i, "decision node id must look like dec_<id>");
7563
- var ExternalSurfaceJumpIdSchema2 = external_exports.string().min(1).max(64).regex(/^surf_[a-z0-9_]+$/i, "external surface node id must look like surf_<id>");
7575
+ var ExternalSurfaceJumpIdSchema23 = external_exports.string().min(1).max(64).regex(/^surf_[a-z0-9_]+$/i, "external surface node id must look like surf_<id>");
7564
7576
  var EXTERNAL_SURFACE_NO_NEXT2 = "__onb_surface_no_next__";
7565
7577
  var ExternalSurfaceTerminalTargetSchema2 = external_exports.literal(EXTERNAL_SURFACE_NO_NEXT2);
7566
- var FlowJumpTargetSchema2 = ScreenIdSchema3.or(DecisionNodeIdSchema2).or(ExternalSurfaceJumpIdSchema2).or(ExternalSurfaceTerminalTargetSchema2).nullable();
7578
+ var FlowJumpTargetSchema2 = ScreenIdSchema3.or(DecisionNodeIdSchema2).or(ExternalSurfaceJumpIdSchema23).or(ExternalSurfaceTerminalTargetSchema2).nullable();
7567
7579
  var DecisionBuiltinNameSchema2 = external_exports.enum(["locale", "platform"]);
7568
7580
  var DecisionVariableRefSchema2 = external_exports.discriminatedUnion("kind", [
7569
7581
  external_exports.object({ kind: external_exports.literal("builtin"), name: DecisionBuiltinNameSchema2 }),
@@ -8223,7 +8235,7 @@ var refineManifestScreens = (manifest, ctx, jumpTargets, screenIds, allFieldKeys
8223
8235
  );
8224
8236
  const knownOptionIds = new Set(l.optionBindings.map((b) => b.optionId));
8225
8237
  for (const cond of l.branching.conditions) {
8226
- if (!screenIds.has(cond.goTo)) {
8238
+ if (!jumpTargets.has(cond.goTo)) {
8227
8239
  ctx.addIssue({
8228
8240
  code: external_exports.ZodIssueCode.custom,
8229
8241
  message: `screen "${screen.id}" branch condition "${cond.choiceId}" -> "${cond.goTo}" not found`,
@@ -8240,7 +8252,7 @@ var refineManifestScreens = (manifest, ctx, jumpTargets, screenIds, allFieldKeys
8240
8252
  }
8241
8253
  }
8242
8254
  if (l.kind === "button" && l.action.kind === "go_to_step") {
8243
- if (!screenIds.has(l.action.screenId)) {
8255
+ if (!jumpTargets.has(l.action.screenId)) {
8244
8256
  ctx.addIssue({
8245
8257
  code: external_exports.ZodIssueCode.custom,
8246
8258
  message: `screen "${screen.id}" button action go_to_step "${l.action.screenId}" not found`,
@@ -8280,6 +8292,24 @@ var refineManifestScreens = (manifest, ctx, jumpTargets, screenIds, allFieldKeys
8280
8292
  }
8281
8293
  }
8282
8294
  }
8295
+ if (l.kind === "loader" && l.onComplete?.mode === "screen") {
8296
+ if (!jumpTargets.has(l.onComplete.screenId)) {
8297
+ ctx.addIssue({
8298
+ code: external_exports.ZodIssueCode.custom,
8299
+ message: `screen "${screen.id}" loader "${l.id}" onComplete targets missing destination "${l.onComplete.screenId}"`,
8300
+ path: ["screens", screenIdx]
8301
+ });
8302
+ }
8303
+ }
8304
+ if ((l.kind === "lottie" || l.kind === "video") && l.onComplete?.mode === "screen") {
8305
+ if (!jumpTargets.has(l.onComplete.screenId)) {
8306
+ ctx.addIssue({
8307
+ code: external_exports.ZodIssueCode.custom,
8308
+ message: `screen "${screen.id}" ${l.kind} "${l.id}" onComplete targets missing destination "${l.onComplete.screenId}"`,
8309
+ path: ["screens", screenIdx]
8310
+ });
8311
+ }
8312
+ }
8283
8313
  if (l.kind === "back_button" && l.fallbackScreenId && !screenIds.has(l.fallbackScreenId)) {
8284
8314
  ctx.addIssue({
8285
8315
  code: external_exports.ZodIssueCode.custom,
@@ -8829,9 +8859,10 @@ var ThemedColorModesSchema4 = external_exports.object({
8829
8859
  message: "at least one of light or dark is required"
8830
8860
  });
8831
8861
  var ThemedColorSchema4 = external_exports.union([external_exports.string().min(1), ThemedColorModesSchema4]);
8832
- var WIDTH_PRESETS4 = ["auto", "full", "1/2", "1/3", "2/3", "1/4", "3/4"];
8862
+ var LAYOUT_FRACTION_PRESETS4 = ["1/2", "1/3", "2/3", "1/4", "3/4"];
8863
+ var WIDTH_PRESETS4 = ["auto", "full", ...LAYOUT_FRACTION_PRESETS4];
8833
8864
  var WidthValueSchema4 = external_exports.union([external_exports.enum(WIDTH_PRESETS4), external_exports.number().int().min(0).max(2e3)]);
8834
- var HEIGHT_PRESETS4 = ["auto", "full", "fill"];
8865
+ var HEIGHT_PRESETS4 = ["auto", "full", "fill", ...LAYOUT_FRACTION_PRESETS4];
8835
8866
  var CommonLayoutHeightSchema4 = external_exports.union([
8836
8867
  external_exports.enum(HEIGHT_PRESETS4),
8837
8868
  external_exports.number().int().min(0).max(2e3)
@@ -8871,7 +8902,7 @@ var CommonStyleSchema4 = external_exports.object({
8871
8902
  zIndex: external_exports.number().int().min(-999).max(999).optional(),
8872
8903
  /** Static rotation in degrees (CSS `rotate`); not timeline animation. */
8873
8904
  rotate: external_exports.number().min(-360).max(360).optional(),
8874
- /** Cross-axis size: `auto` (hug), `full`/`fill` (parent height), or fixed px. No fractions. */
8905
+ /** Cross-axis size: `auto` (hug), `full`/`fill` (parent height), fractions, or fixed px. */
8875
8906
  height: CommonLayoutHeightSchema4.optional(),
8876
8907
  /** Stroke thickness in px for layers that render a stroke primitive (e.g. loader ring). */
8877
8908
  strokeWidth: external_exports.number().int().min(0).max(64).optional()
@@ -8963,6 +8994,11 @@ var ButtonLayoutBreakpointsSchema4 = external_exports.object({
8963
8994
  xl: ButtonLayoutBreakpointPatchSchema4.optional(),
8964
8995
  "2xl": ButtonLayoutBreakpointPatchSchema4.optional()
8965
8996
  }).partial().optional();
8997
+ var DecisionNodeJumpIdSchema4 = external_exports.string().min(1).max(64).regex(/^dec_[a-z0-9_]+$/i);
8998
+ var ExternalSurfaceJumpIdSchema4 = external_exports.string().min(1).max(64).regex(/^surf_[a-z0-9_]+$/i);
8999
+ var FlowGraphNodeJumpTargetSchema4 = ScreenIdSchema4.or(DecisionNodeJumpIdSchema4).or(
9000
+ ExternalSurfaceJumpIdSchema4
9001
+ );
8966
9002
  var OS_PERMISSION_KEYS4 = [
8967
9003
  "notifications",
8968
9004
  "camera",
@@ -8992,11 +9028,9 @@ var PERMISSION_OUTCOME_VALUES4 = ["granted", "denied", "blocked"];
8992
9028
  external_exports.enum(PERMISSION_OUTCOME_VALUES4);
8993
9029
  var OS_PERMISSION_OUTCOME_CONTINUE4 = "continue";
8994
9030
  var OS_PERMISSION_OUTCOME_END4 = "end";
8995
- var OsPermissionOutcomeBranchTargetSchema4 = external_exports.union([
8996
- ScreenIdSchema4,
8997
- external_exports.literal(OS_PERMISSION_OUTCOME_CONTINUE4),
8998
- external_exports.literal(OS_PERMISSION_OUTCOME_END4)
8999
- ]);
9031
+ var OsPermissionOutcomeBranchTargetSchema4 = FlowGraphNodeJumpTargetSchema4.or(
9032
+ external_exports.literal(OS_PERMISSION_OUTCOME_CONTINUE4)
9033
+ ).or(external_exports.literal(OS_PERMISSION_OUTCOME_END4));
9000
9034
  var OsPermissionOutcomesSchema4 = external_exports.object({
9001
9035
  granted: OsPermissionOutcomeBranchTargetSchema4,
9002
9036
  denied: OsPermissionOutcomeBranchTargetSchema4,
@@ -9013,7 +9047,7 @@ var ButtonActionSchema4 = external_exports.discriminatedUnion("kind", [
9013
9047
  kind: external_exports.literal("go_back_one_screen"),
9014
9048
  fallbackScreenId: ScreenIdSchema4.optional()
9015
9049
  }),
9016
- external_exports.object({ kind: external_exports.literal("go_to_step"), screenId: ScreenIdSchema4 }),
9050
+ external_exports.object({ kind: external_exports.literal("go_to_step"), screenId: FlowGraphNodeJumpTargetSchema4 }),
9017
9051
  external_exports.object({
9018
9052
  kind: external_exports.literal("request_os_permission"),
9019
9053
  permissionKey: OsPermissionKeySchema4,
@@ -9095,7 +9129,7 @@ var ProgressLayerSchema4 = external_exports.object({
9095
9129
  var LoaderOnCompleteSchema4 = external_exports.discriminatedUnion("mode", [
9096
9130
  external_exports.object({ mode: external_exports.literal("none") }),
9097
9131
  external_exports.object({ mode: external_exports.literal("next") }),
9098
- external_exports.object({ mode: external_exports.literal("screen"), screenId: ScreenIdSchema4 })
9132
+ external_exports.object({ mode: external_exports.literal("screen"), screenId: FlowGraphNodeJumpTargetSchema4 })
9099
9133
  ]);
9100
9134
  var LoaderLayerSchema4 = external_exports.object({
9101
9135
  ...baseLayerShape4,
@@ -9576,7 +9610,7 @@ var ChoiceOptionBindingSchema4 = external_exports.object({
9576
9610
  });
9577
9611
  var BranchConditionSchema4 = external_exports.object({
9578
9612
  choiceId: external_exports.string().min(1),
9579
- goTo: ScreenIdSchema4
9613
+ goTo: FlowGraphNodeJumpTargetSchema4
9580
9614
  });
9581
9615
  var ChoiceBranchingSchema4 = external_exports.object({
9582
9616
  enabled: external_exports.boolean(),
@@ -9782,10 +9816,10 @@ var ScreenContainerStyleBreakpointsSchema2 = external_exports.object({
9782
9816
  "2xl": ScreenContainerBreakpointPatchSchema2.optional()
9783
9817
  }).partial().optional();
9784
9818
  var DecisionNodeIdSchema3 = external_exports.string().min(1).max(64).regex(/^dec_[a-z0-9_]+$/i, "decision node id must look like dec_<id>");
9785
- var ExternalSurfaceJumpIdSchema3 = external_exports.string().min(1).max(64).regex(/^surf_[a-z0-9_]+$/i, "external surface node id must look like surf_<id>");
9819
+ var ExternalSurfaceJumpIdSchema24 = external_exports.string().min(1).max(64).regex(/^surf_[a-z0-9_]+$/i, "external surface node id must look like surf_<id>");
9786
9820
  var EXTERNAL_SURFACE_NO_NEXT3 = "__onb_surface_no_next__";
9787
9821
  var ExternalSurfaceTerminalTargetSchema3 = external_exports.literal(EXTERNAL_SURFACE_NO_NEXT3);
9788
- var FlowJumpTargetSchema3 = ScreenIdSchema4.or(DecisionNodeIdSchema3).or(ExternalSurfaceJumpIdSchema3).or(ExternalSurfaceTerminalTargetSchema3).nullable();
9822
+ var FlowJumpTargetSchema3 = ScreenIdSchema4.or(DecisionNodeIdSchema3).or(ExternalSurfaceJumpIdSchema24).or(ExternalSurfaceTerminalTargetSchema3).nullable();
9789
9823
  var DecisionBuiltinNameSchema3 = external_exports.enum(["locale", "platform"]);
9790
9824
  var DecisionVariableRefSchema3 = external_exports.discriminatedUnion("kind", [
9791
9825
  external_exports.object({ kind: external_exports.literal("builtin"), name: DecisionBuiltinNameSchema3 }),
@@ -10365,18 +10399,32 @@ var collectFlowBuilderIssues = (manifest) => {
10365
10399
  }
10366
10400
  if (l.kind === "single_choice" || l.kind === "multiple_choice") {
10367
10401
  for (const cond of l.branching.conditions) {
10368
- if (!screenIds.has(cond.goTo)) {
10402
+ if (!jumpTargetIds.has(cond.goTo)) {
10369
10403
  issues.push(
10370
- `Screen "${label}" branches choice "${cond.choiceId}" to a missing screen "${cond.goTo}".`
10404
+ `Screen "${label}" branches choice "${cond.choiceId}" to a missing destination "${cond.goTo}".`
10371
10405
  );
10372
10406
  }
10373
10407
  }
10374
10408
  }
10375
10409
  }
10376
10410
  if (l.kind === "button" && l.action.kind === "go_to_step") {
10377
- if (!screenIds.has(l.action.screenId)) {
10411
+ if (!jumpTargetIds.has(l.action.screenId)) {
10412
+ issues.push(
10413
+ `Button "${l.name || l.id}" on screen "${screen.name || screen.id}" targets a missing destination "${l.action.screenId}".`
10414
+ );
10415
+ }
10416
+ }
10417
+ if (l.kind === "loader" && l.onComplete?.mode === "screen") {
10418
+ if (!jumpTargetIds.has(l.onComplete.screenId)) {
10419
+ issues.push(
10420
+ `Loader "${l.name || l.id}" on screen "${screen.name || screen.id}" onComplete targets a missing destination "${l.onComplete.screenId}".`
10421
+ );
10422
+ }
10423
+ }
10424
+ if ((l.kind === "lottie" || l.kind === "video") && l.onComplete?.mode === "screen") {
10425
+ if (!jumpTargetIds.has(l.onComplete.screenId)) {
10378
10426
  issues.push(
10379
- `Button "${l.name || l.id}" on screen "${screen.name || screen.id}" targets a missing screen "${l.action.screenId}".`
10427
+ `${l.kind === "video" ? "Video" : "Lottie"} "${l.name || l.id}" on screen "${screen.name || screen.id}" onComplete targets a missing destination "${l.onComplete.screenId}".`
10380
10428
  );
10381
10429
  }
10382
10430
  }
@@ -10404,16 +10452,16 @@ var collectFlowBuilderIssues = (manifest) => {
10404
10452
  if (def == null) {
10405
10453
  continue;
10406
10454
  }
10407
- if (!screenIds.has(def) && !manifest.decisionNodes?.some((d) => d.id === def)) {
10455
+ if (!jumpTargetIds.has(def)) {
10408
10456
  issues.push(
10409
10457
  `Button "${l.name || l.id}" on screen "${screen.name || screen.id}" (${slot}) continues to missing target "${def}".`
10410
10458
  );
10411
10459
  }
10412
10460
  continue;
10413
10461
  }
10414
- if (!screenIds.has(sid)) {
10462
+ if (!jumpTargetIds.has(sid)) {
10415
10463
  issues.push(
10416
- `Button "${l.name || l.id}" on screen "${screen.name || screen.id}" (${slot}) targets a missing screen "${sid}".`
10464
+ `Button "${l.name || l.id}" on screen "${screen.name || screen.id}" (${slot}) targets a missing destination "${sid}".`
10417
10465
  );
10418
10466
  }
10419
10467
  }