@getrheo/rheo-skill 2.3.0 → 2.5.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.
@@ -4421,6 +4421,8 @@ var OsPermissionOutcomesSchema = external_exports.object({
4421
4421
  }).strict();
4422
4422
  var APP_REVIEW_OUTCOMES = ["not_shown", "dismissed"];
4423
4423
  var AppReviewOutcomeSchema = external_exports.enum(APP_REVIEW_OUTCOMES);
4424
+ var CAROUSEL_ADVANCE_ON_LAST = ["noop", "complete"];
4425
+ var CarouselAdvanceOnLastSchema = external_exports.enum(CAROUSEL_ADVANCE_ON_LAST);
4424
4426
  var ButtonActionSchema = external_exports.discriminatedUnion("kind", [
4425
4427
  external_exports.object({ kind: external_exports.literal("none") }),
4426
4428
  external_exports.object({ kind: external_exports.literal("continue") }),
@@ -4440,7 +4442,12 @@ var ButtonActionSchema = external_exports.discriminatedUnion("kind", [
4440
4442
  kind: external_exports.literal("play_media"),
4441
4443
  targetLayerIds: external_exports.array(external_exports.string().min(1)).min(1)
4442
4444
  }),
4443
- external_exports.object({ kind: external_exports.literal("request_app_review") })
4445
+ external_exports.object({ kind: external_exports.literal("request_app_review") }),
4446
+ external_exports.object({
4447
+ kind: external_exports.literal("advance_carousel"),
4448
+ targetLayerId: external_exports.string().min(1),
4449
+ onLast: CarouselAdvanceOnLastSchema.optional()
4450
+ })
4444
4451
  ]);
4445
4452
  var TEXT_INPUT_TYPES = ["plain", "email", "phone", "url", "number", "multiline"];
4446
4453
  var TextInputTypeSchema = external_exports.enum(TEXT_INPUT_TYPES);
@@ -5183,6 +5190,83 @@ var CarouselLayerSchema = external_exports.object({
5183
5190
  styleBreakpoints: CommonStyleBreakpointsSchema,
5184
5191
  carouselLayoutBreakpoints: CarouselLayoutBreakpointsSchema
5185
5192
  });
5193
+ var DecisionBuiltinNameSchema = external_exports.enum(["locale", "platform"]);
5194
+ var DecisionVariableRefSchema = external_exports.discriminatedUnion("kind", [
5195
+ external_exports.object({ kind: external_exports.literal("builtin"), name: DecisionBuiltinNameSchema }),
5196
+ external_exports.object({ kind: external_exports.literal("sdk"), key: external_exports.string().min(1).max(128) }),
5197
+ external_exports.object({ kind: external_exports.literal("field"), fieldKey: external_exports.string().min(1).max(128) })
5198
+ ]);
5199
+ var DecisionStringPredicateSchema = external_exports.discriminatedUnion("op", [
5200
+ external_exports.object({ op: external_exports.literal("eq"), value: external_exports.string() }),
5201
+ external_exports.object({ op: external_exports.literal("neq"), value: external_exports.string() }),
5202
+ external_exports.object({ op: external_exports.literal("contains"), value: external_exports.string() })
5203
+ ]);
5204
+ var DecisionNumberPredicateSchema = external_exports.discriminatedUnion("op", [
5205
+ external_exports.object({ op: external_exports.literal("eq"), value: external_exports.number() }),
5206
+ external_exports.object({ op: external_exports.literal("neq"), value: external_exports.number() }),
5207
+ external_exports.object({ op: external_exports.literal("lt"), value: external_exports.number() }),
5208
+ external_exports.object({ op: external_exports.literal("lte"), value: external_exports.number() }),
5209
+ external_exports.object({ op: external_exports.literal("gt"), value: external_exports.number() }),
5210
+ external_exports.object({ op: external_exports.literal("gte"), value: external_exports.number() })
5211
+ ]);
5212
+ var DecisionChoicePredicateSchema = external_exports.discriminatedUnion("op", [
5213
+ external_exports.object({ op: external_exports.literal("eq"), optionId: external_exports.string().min(1) }),
5214
+ external_exports.object({ op: external_exports.literal("one_of"), optionIds: external_exports.array(external_exports.string().min(1)).min(1) })
5215
+ ]);
5216
+ var DecisionMultiPredicateSchema = external_exports.discriminatedUnion("op", [
5217
+ external_exports.object({
5218
+ op: external_exports.literal("intersects"),
5219
+ optionIds: external_exports.array(external_exports.string().min(1)).min(1)
5220
+ }),
5221
+ external_exports.object({
5222
+ op: external_exports.literal("contains_all"),
5223
+ optionIds: external_exports.array(external_exports.string().min(1)).min(1)
5224
+ }),
5225
+ external_exports.object({
5226
+ op: external_exports.literal("subset_of"),
5227
+ optionIds: external_exports.array(external_exports.string().min(1)).min(1)
5228
+ })
5229
+ ]);
5230
+ var DecisionBooleanPredicateSchema = external_exports.discriminatedUnion("op", [
5231
+ external_exports.object({ op: external_exports.literal("eq"), value: external_exports.boolean() }),
5232
+ external_exports.object({ op: external_exports.literal("neq"), value: external_exports.boolean() })
5233
+ ]);
5234
+ var DecisionPredicatePayloadSchema = external_exports.discriminatedUnion("type", [
5235
+ external_exports.object({ type: external_exports.literal("string"), pred: DecisionStringPredicateSchema }),
5236
+ external_exports.object({ type: external_exports.literal("number"), pred: DecisionNumberPredicateSchema }),
5237
+ external_exports.object({ type: external_exports.literal("boolean"), pred: DecisionBooleanPredicateSchema }),
5238
+ external_exports.object({ type: external_exports.literal("choice"), pred: DecisionChoicePredicateSchema }),
5239
+ external_exports.object({ type: external_exports.literal("multi"), pred: DecisionMultiPredicateSchema })
5240
+ ]);
5241
+ var DecisionExprSchema = external_exports.lazy(
5242
+ () => external_exports.discriminatedUnion("kind", [
5243
+ external_exports.object({ kind: external_exports.literal("empty") }),
5244
+ external_exports.object({
5245
+ kind: external_exports.literal("group"),
5246
+ op: external_exports.enum(["and", "or"]),
5247
+ children: external_exports.array(DecisionExprSchema).min(1)
5248
+ }),
5249
+ external_exports.object({
5250
+ kind: external_exports.literal("predicate"),
5251
+ variable: DecisionVariableRefSchema,
5252
+ predicate: DecisionPredicatePayloadSchema
5253
+ })
5254
+ ])
5255
+ );
5256
+ var CONDITIONAL_MAX_CASES = 16;
5257
+ var ConditionalCaseSchema = external_exports.object({
5258
+ id: external_exports.string().min(1).max(80),
5259
+ name: external_exports.string().min(1).max(80).optional(),
5260
+ expression: DecisionExprSchema,
5261
+ rootLayerId: LayerIdSchema
5262
+ });
5263
+ var ConditionalLayerSchema = external_exports.object({
5264
+ ...baseLayerShape,
5265
+ kind: external_exports.literal("conditional"),
5266
+ cases: external_exports.array(ConditionalCaseSchema).min(1).max(CONDITIONAL_MAX_CASES),
5267
+ elseRootLayerId: LayerIdSchema,
5268
+ children: external_exports.lazy(() => external_exports.array(StackLayerSchema).min(2))
5269
+ });
5186
5270
  layerSchemaStore.schema = external_exports.lazy(
5187
5271
  () => external_exports.union([
5188
5272
  StackLayerSchema,
@@ -5209,7 +5293,8 @@ layerSchemaStore.schema = external_exports.lazy(
5209
5293
  EmailPasswordAuthLayerSchema,
5210
5294
  EmailPasswordFieldLayerSchema,
5211
5295
  EmailPasswordSubmitLayerSchema,
5212
- CarouselLayerSchema
5296
+ CarouselLayerSchema,
5297
+ ConditionalLayerSchema
5213
5298
  ])
5214
5299
  );
5215
5300
  var LayerSchema = layerSchemaStore.schema;
@@ -5589,6 +5674,8 @@ var OsPermissionOutcomesSchema2 = external_exports.object({
5589
5674
  }).strict();
5590
5675
  var APP_REVIEW_OUTCOMES2 = ["not_shown", "dismissed"];
5591
5676
  external_exports.enum(APP_REVIEW_OUTCOMES2);
5677
+ var CAROUSEL_ADVANCE_ON_LAST2 = ["noop", "complete"];
5678
+ var CarouselAdvanceOnLastSchema2 = external_exports.enum(CAROUSEL_ADVANCE_ON_LAST2);
5592
5679
  var ButtonActionSchema2 = external_exports.discriminatedUnion("kind", [
5593
5680
  external_exports.object({ kind: external_exports.literal("none") }),
5594
5681
  external_exports.object({ kind: external_exports.literal("continue") }),
@@ -5608,7 +5695,12 @@ var ButtonActionSchema2 = external_exports.discriminatedUnion("kind", [
5608
5695
  kind: external_exports.literal("play_media"),
5609
5696
  targetLayerIds: external_exports.array(external_exports.string().min(1)).min(1)
5610
5697
  }),
5611
- external_exports.object({ kind: external_exports.literal("request_app_review") })
5698
+ external_exports.object({ kind: external_exports.literal("request_app_review") }),
5699
+ external_exports.object({
5700
+ kind: external_exports.literal("advance_carousel"),
5701
+ targetLayerId: external_exports.string().min(1),
5702
+ onLast: CarouselAdvanceOnLastSchema2.optional()
5703
+ })
5612
5704
  ]);
5613
5705
  var TEXT_INPUT_TYPES2 = ["plain", "email", "phone", "url", "number", "multiline"];
5614
5706
  var TextInputTypeSchema2 = external_exports.enum(TEXT_INPUT_TYPES2);
@@ -6351,52 +6443,18 @@ var CarouselLayerSchema2 = external_exports.object({
6351
6443
  styleBreakpoints: CommonStyleBreakpointsSchema2,
6352
6444
  carouselLayoutBreakpoints: CarouselLayoutBreakpointsSchema2
6353
6445
  });
6354
- layerSchemaStore2.schema = external_exports.lazy(
6355
- () => external_exports.union([
6356
- StackLayerSchema2,
6357
- TextLayerSchema2,
6358
- HyperlinkLayerSchema2,
6359
- ImageLayerSchema2,
6360
- LottieLayerSchema2,
6361
- VideoLayerSchema2,
6362
- IconLayerSchema2,
6363
- ButtonLayerSchema2,
6364
- BackButtonLayerSchema2,
6365
- ProgressLayerSchema2,
6366
- LoaderLayerSchema2,
6367
- CounterLayerSchema2,
6368
- CheckboxLayerSchema2,
6369
- SingleChoiceLayerSchema2,
6370
- MultipleChoiceLayerSchema2,
6371
- TextInputLayerSchema2,
6372
- ScaleInputLayerSchema2,
6373
- WheelPickerLayerSchema2,
6374
- OAuthLoginLayerSchema2,
6375
- OAuthProviderPresetLayerSchema2,
6376
- OAuthProviderCustomLayerSchema2,
6377
- EmailPasswordAuthLayerSchema2,
6378
- EmailPasswordFieldLayerSchema2,
6379
- EmailPasswordSubmitLayerSchema2,
6380
- CarouselLayerSchema2
6381
- ])
6382
- );
6383
- var DecisionNodeIdSchema = external_exports.string().min(1).max(64).regex(/^dec_[a-z0-9_]+$/i, "decision node id must look like dec_<id>");
6384
- var ExternalSurfaceJumpIdSchema22 = external_exports.string().min(1).max(64).regex(/^surf_[a-z0-9_]+$/i, "external surface node id must look like surf_<id>");
6385
- var EXTERNAL_SURFACE_NO_NEXT = "__onb_surface_no_next__";
6386
- var ExternalSurfaceTerminalTargetSchema = external_exports.literal(EXTERNAL_SURFACE_NO_NEXT);
6387
- var FlowJumpTargetSchema = ScreenIdSchema2.or(DecisionNodeIdSchema).or(ExternalSurfaceJumpIdSchema22).or(ExternalSurfaceTerminalTargetSchema).nullable();
6388
- var DecisionBuiltinNameSchema = external_exports.enum(["locale", "platform"]);
6389
- var DecisionVariableRefSchema = external_exports.discriminatedUnion("kind", [
6390
- external_exports.object({ kind: external_exports.literal("builtin"), name: DecisionBuiltinNameSchema }),
6446
+ var DecisionBuiltinNameSchema2 = external_exports.enum(["locale", "platform"]);
6447
+ var DecisionVariableRefSchema2 = external_exports.discriminatedUnion("kind", [
6448
+ external_exports.object({ kind: external_exports.literal("builtin"), name: DecisionBuiltinNameSchema2 }),
6391
6449
  external_exports.object({ kind: external_exports.literal("sdk"), key: external_exports.string().min(1).max(128) }),
6392
6450
  external_exports.object({ kind: external_exports.literal("field"), fieldKey: external_exports.string().min(1).max(128) })
6393
6451
  ]);
6394
- var DecisionStringPredicateSchema = external_exports.discriminatedUnion("op", [
6452
+ var DecisionStringPredicateSchema2 = external_exports.discriminatedUnion("op", [
6395
6453
  external_exports.object({ op: external_exports.literal("eq"), value: external_exports.string() }),
6396
6454
  external_exports.object({ op: external_exports.literal("neq"), value: external_exports.string() }),
6397
6455
  external_exports.object({ op: external_exports.literal("contains"), value: external_exports.string() })
6398
6456
  ]);
6399
- var DecisionNumberPredicateSchema = external_exports.discriminatedUnion("op", [
6457
+ var DecisionNumberPredicateSchema2 = external_exports.discriminatedUnion("op", [
6400
6458
  external_exports.object({ op: external_exports.literal("eq"), value: external_exports.number() }),
6401
6459
  external_exports.object({ op: external_exports.literal("neq"), value: external_exports.number() }),
6402
6460
  external_exports.object({ op: external_exports.literal("lt"), value: external_exports.number() }),
@@ -6404,11 +6462,11 @@ var DecisionNumberPredicateSchema = external_exports.discriminatedUnion("op", [
6404
6462
  external_exports.object({ op: external_exports.literal("gt"), value: external_exports.number() }),
6405
6463
  external_exports.object({ op: external_exports.literal("gte"), value: external_exports.number() })
6406
6464
  ]);
6407
- var DecisionChoicePredicateSchema = external_exports.discriminatedUnion("op", [
6465
+ var DecisionChoicePredicateSchema2 = external_exports.discriminatedUnion("op", [
6408
6466
  external_exports.object({ op: external_exports.literal("eq"), optionId: external_exports.string().min(1) }),
6409
6467
  external_exports.object({ op: external_exports.literal("one_of"), optionIds: external_exports.array(external_exports.string().min(1)).min(1) })
6410
6468
  ]);
6411
- var DecisionMultiPredicateSchema = external_exports.discriminatedUnion("op", [
6469
+ var DecisionMultiPredicateSchema2 = external_exports.discriminatedUnion("op", [
6412
6470
  external_exports.object({
6413
6471
  op: external_exports.literal("intersects"),
6414
6472
  optionIds: external_exports.array(external_exports.string().min(1)).min(1)
@@ -6422,45 +6480,32 @@ var DecisionMultiPredicateSchema = external_exports.discriminatedUnion("op", [
6422
6480
  optionIds: external_exports.array(external_exports.string().min(1)).min(1)
6423
6481
  })
6424
6482
  ]);
6425
- var DecisionBooleanPredicateSchema = external_exports.discriminatedUnion("op", [
6483
+ var DecisionBooleanPredicateSchema2 = external_exports.discriminatedUnion("op", [
6426
6484
  external_exports.object({ op: external_exports.literal("eq"), value: external_exports.boolean() }),
6427
6485
  external_exports.object({ op: external_exports.literal("neq"), value: external_exports.boolean() })
6428
6486
  ]);
6429
- var DecisionPredicatePayloadSchema = external_exports.discriminatedUnion("type", [
6430
- external_exports.object({ type: external_exports.literal("string"), pred: DecisionStringPredicateSchema }),
6431
- external_exports.object({ type: external_exports.literal("number"), pred: DecisionNumberPredicateSchema }),
6432
- external_exports.object({ type: external_exports.literal("boolean"), pred: DecisionBooleanPredicateSchema }),
6433
- external_exports.object({ type: external_exports.literal("choice"), pred: DecisionChoicePredicateSchema }),
6434
- external_exports.object({ type: external_exports.literal("multi"), pred: DecisionMultiPredicateSchema })
6487
+ var DecisionPredicatePayloadSchema2 = external_exports.discriminatedUnion("type", [
6488
+ external_exports.object({ type: external_exports.literal("string"), pred: DecisionStringPredicateSchema2 }),
6489
+ external_exports.object({ type: external_exports.literal("number"), pred: DecisionNumberPredicateSchema2 }),
6490
+ external_exports.object({ type: external_exports.literal("boolean"), pred: DecisionBooleanPredicateSchema2 }),
6491
+ external_exports.object({ type: external_exports.literal("choice"), pred: DecisionChoicePredicateSchema2 }),
6492
+ external_exports.object({ type: external_exports.literal("multi"), pred: DecisionMultiPredicateSchema2 })
6435
6493
  ]);
6436
- var DecisionExprSchema = external_exports.lazy(
6494
+ var DecisionExprSchema2 = external_exports.lazy(
6437
6495
  () => external_exports.discriminatedUnion("kind", [
6438
6496
  external_exports.object({ kind: external_exports.literal("empty") }),
6439
6497
  external_exports.object({
6440
6498
  kind: external_exports.literal("group"),
6441
6499
  op: external_exports.enum(["and", "or"]),
6442
- children: external_exports.array(DecisionExprSchema).min(1)
6500
+ children: external_exports.array(DecisionExprSchema2).min(1)
6443
6501
  }),
6444
6502
  external_exports.object({
6445
6503
  kind: external_exports.literal("predicate"),
6446
- variable: DecisionVariableRefSchema,
6447
- predicate: DecisionPredicatePayloadSchema
6504
+ variable: DecisionVariableRefSchema2,
6505
+ predicate: DecisionPredicatePayloadSchema2
6448
6506
  })
6449
6507
  ])
6450
6508
  );
6451
- var DecisionCaseSchema = external_exports.object({
6452
- id: external_exports.string().min(1).max(80),
6453
- /** Display label in the editor (e.g. “Engaged users”). */
6454
- name: external_exports.string().min(1).max(80).optional(),
6455
- expression: DecisionExprSchema,
6456
- next: FlowJumpTargetSchema
6457
- });
6458
- var DecisionNodeSchema = external_exports.object({
6459
- id: DecisionNodeIdSchema,
6460
- name: external_exports.string().min(1).max(80).optional(),
6461
- cases: external_exports.array(DecisionCaseSchema).min(1).max(16),
6462
- elseNext: FlowJumpTargetSchema
6463
- });
6464
6509
  var collectDecisionFieldKeys = (expr) => {
6465
6510
  const out = [];
6466
6511
  const walk = (e) => {
@@ -6474,6 +6519,73 @@ var collectDecisionFieldKeys = (expr) => {
6474
6519
  walk(expr);
6475
6520
  return out;
6476
6521
  };
6522
+ var decisionExprHasPredicate = (expr) => {
6523
+ if (expr.kind === "empty") return false;
6524
+ if (expr.kind === "predicate") return true;
6525
+ return expr.children.some(decisionExprHasPredicate);
6526
+ };
6527
+ var CONDITIONAL_MAX_CASES2 = 16;
6528
+ var ConditionalCaseSchema2 = external_exports.object({
6529
+ id: external_exports.string().min(1).max(80),
6530
+ name: external_exports.string().min(1).max(80).optional(),
6531
+ expression: DecisionExprSchema2,
6532
+ rootLayerId: LayerIdSchema2
6533
+ });
6534
+ var ConditionalLayerSchema2 = external_exports.object({
6535
+ ...baseLayerShape2,
6536
+ kind: external_exports.literal("conditional"),
6537
+ cases: external_exports.array(ConditionalCaseSchema2).min(1).max(CONDITIONAL_MAX_CASES2),
6538
+ elseRootLayerId: LayerIdSchema2,
6539
+ children: external_exports.lazy(() => external_exports.array(StackLayerSchema2).min(2))
6540
+ });
6541
+ layerSchemaStore2.schema = external_exports.lazy(
6542
+ () => external_exports.union([
6543
+ StackLayerSchema2,
6544
+ TextLayerSchema2,
6545
+ HyperlinkLayerSchema2,
6546
+ ImageLayerSchema2,
6547
+ LottieLayerSchema2,
6548
+ VideoLayerSchema2,
6549
+ IconLayerSchema2,
6550
+ ButtonLayerSchema2,
6551
+ BackButtonLayerSchema2,
6552
+ ProgressLayerSchema2,
6553
+ LoaderLayerSchema2,
6554
+ CounterLayerSchema2,
6555
+ CheckboxLayerSchema2,
6556
+ SingleChoiceLayerSchema2,
6557
+ MultipleChoiceLayerSchema2,
6558
+ TextInputLayerSchema2,
6559
+ ScaleInputLayerSchema2,
6560
+ WheelPickerLayerSchema2,
6561
+ OAuthLoginLayerSchema2,
6562
+ OAuthProviderPresetLayerSchema2,
6563
+ OAuthProviderCustomLayerSchema2,
6564
+ EmailPasswordAuthLayerSchema2,
6565
+ EmailPasswordFieldLayerSchema2,
6566
+ EmailPasswordSubmitLayerSchema2,
6567
+ CarouselLayerSchema2,
6568
+ ConditionalLayerSchema2
6569
+ ])
6570
+ );
6571
+ var DecisionNodeIdSchema = external_exports.string().min(1).max(64).regex(/^dec_[a-z0-9_]+$/i, "decision node id must look like dec_<id>");
6572
+ var ExternalSurfaceJumpIdSchema22 = external_exports.string().min(1).max(64).regex(/^surf_[a-z0-9_]+$/i, "external surface node id must look like surf_<id>");
6573
+ var EXTERNAL_SURFACE_NO_NEXT = "__onb_surface_no_next__";
6574
+ var ExternalSurfaceTerminalTargetSchema = external_exports.literal(EXTERNAL_SURFACE_NO_NEXT);
6575
+ var FlowJumpTargetSchema = ScreenIdSchema2.or(DecisionNodeIdSchema).or(ExternalSurfaceJumpIdSchema22).or(ExternalSurfaceTerminalTargetSchema).nullable();
6576
+ var DecisionCaseSchema = external_exports.object({
6577
+ id: external_exports.string().min(1).max(80),
6578
+ /** Display label in the editor (e.g. “Engaged users”). */
6579
+ name: external_exports.string().min(1).max(80).optional(),
6580
+ expression: DecisionExprSchema2,
6581
+ next: FlowJumpTargetSchema
6582
+ });
6583
+ var DecisionNodeSchema = external_exports.object({
6584
+ id: DecisionNodeIdSchema,
6585
+ name: external_exports.string().min(1).max(80).optional(),
6586
+ cases: external_exports.array(DecisionCaseSchema).min(1).max(16),
6587
+ elseNext: FlowJumpTargetSchema
6588
+ });
6477
6589
  var collectDecisionFieldKeysFromNode = (node) => {
6478
6590
  const seen = /* @__PURE__ */ new Set();
6479
6591
  for (const c of node.cases) {
@@ -6878,6 +6990,8 @@ var OsPermissionOutcomesSchema3 = external_exports.object({
6878
6990
  }).strict();
6879
6991
  var APP_REVIEW_OUTCOMES3 = ["not_shown", "dismissed"];
6880
6992
  var AppReviewOutcomeSchema2 = external_exports.enum(APP_REVIEW_OUTCOMES3);
6993
+ var CAROUSEL_ADVANCE_ON_LAST3 = ["noop", "complete"];
6994
+ var CarouselAdvanceOnLastSchema3 = external_exports.enum(CAROUSEL_ADVANCE_ON_LAST3);
6881
6995
  var ButtonActionSchema3 = external_exports.discriminatedUnion("kind", [
6882
6996
  external_exports.object({ kind: external_exports.literal("none") }),
6883
6997
  external_exports.object({ kind: external_exports.literal("continue") }),
@@ -6897,7 +7011,12 @@ var ButtonActionSchema3 = external_exports.discriminatedUnion("kind", [
6897
7011
  kind: external_exports.literal("play_media"),
6898
7012
  targetLayerIds: external_exports.array(external_exports.string().min(1)).min(1)
6899
7013
  }),
6900
- external_exports.object({ kind: external_exports.literal("request_app_review") })
7014
+ external_exports.object({ kind: external_exports.literal("request_app_review") }),
7015
+ external_exports.object({
7016
+ kind: external_exports.literal("advance_carousel"),
7017
+ targetLayerId: external_exports.string().min(1),
7018
+ onLast: CarouselAdvanceOnLastSchema3.optional()
7019
+ })
6901
7020
  ]);
6902
7021
  var TEXT_INPUT_TYPES3 = ["plain", "email", "phone", "url", "number", "multiline"];
6903
7022
  var TextInputTypeSchema3 = external_exports.enum(TEXT_INPUT_TYPES3);
@@ -7685,6 +7804,154 @@ var CarouselLayerSchema3 = external_exports.object({
7685
7804
  styleBreakpoints: CommonStyleBreakpointsSchema3,
7686
7805
  carouselLayoutBreakpoints: CarouselLayoutBreakpointsSchema3
7687
7806
  });
7807
+ var DecisionBuiltinNameSchema3 = external_exports.enum(["locale", "platform"]);
7808
+ var DecisionVariableRefSchema3 = external_exports.discriminatedUnion("kind", [
7809
+ external_exports.object({ kind: external_exports.literal("builtin"), name: DecisionBuiltinNameSchema3 }),
7810
+ external_exports.object({ kind: external_exports.literal("sdk"), key: external_exports.string().min(1).max(128) }),
7811
+ external_exports.object({ kind: external_exports.literal("field"), fieldKey: external_exports.string().min(1).max(128) })
7812
+ ]);
7813
+ var DecisionStringPredicateSchema3 = external_exports.discriminatedUnion("op", [
7814
+ external_exports.object({ op: external_exports.literal("eq"), value: external_exports.string() }),
7815
+ external_exports.object({ op: external_exports.literal("neq"), value: external_exports.string() }),
7816
+ external_exports.object({ op: external_exports.literal("contains"), value: external_exports.string() })
7817
+ ]);
7818
+ var DecisionNumberPredicateSchema3 = external_exports.discriminatedUnion("op", [
7819
+ external_exports.object({ op: external_exports.literal("eq"), value: external_exports.number() }),
7820
+ external_exports.object({ op: external_exports.literal("neq"), value: external_exports.number() }),
7821
+ external_exports.object({ op: external_exports.literal("lt"), value: external_exports.number() }),
7822
+ external_exports.object({ op: external_exports.literal("lte"), value: external_exports.number() }),
7823
+ external_exports.object({ op: external_exports.literal("gt"), value: external_exports.number() }),
7824
+ external_exports.object({ op: external_exports.literal("gte"), value: external_exports.number() })
7825
+ ]);
7826
+ var DecisionChoicePredicateSchema3 = external_exports.discriminatedUnion("op", [
7827
+ external_exports.object({ op: external_exports.literal("eq"), optionId: external_exports.string().min(1) }),
7828
+ external_exports.object({ op: external_exports.literal("one_of"), optionIds: external_exports.array(external_exports.string().min(1)).min(1) })
7829
+ ]);
7830
+ var DecisionMultiPredicateSchema3 = external_exports.discriminatedUnion("op", [
7831
+ external_exports.object({
7832
+ op: external_exports.literal("intersects"),
7833
+ optionIds: external_exports.array(external_exports.string().min(1)).min(1)
7834
+ }),
7835
+ external_exports.object({
7836
+ op: external_exports.literal("contains_all"),
7837
+ optionIds: external_exports.array(external_exports.string().min(1)).min(1)
7838
+ }),
7839
+ external_exports.object({
7840
+ op: external_exports.literal("subset_of"),
7841
+ optionIds: external_exports.array(external_exports.string().min(1)).min(1)
7842
+ })
7843
+ ]);
7844
+ var DecisionBooleanPredicateSchema3 = external_exports.discriminatedUnion("op", [
7845
+ external_exports.object({ op: external_exports.literal("eq"), value: external_exports.boolean() }),
7846
+ external_exports.object({ op: external_exports.literal("neq"), value: external_exports.boolean() })
7847
+ ]);
7848
+ var DecisionPredicatePayloadSchema3 = external_exports.discriminatedUnion("type", [
7849
+ external_exports.object({ type: external_exports.literal("string"), pred: DecisionStringPredicateSchema3 }),
7850
+ external_exports.object({ type: external_exports.literal("number"), pred: DecisionNumberPredicateSchema3 }),
7851
+ external_exports.object({ type: external_exports.literal("boolean"), pred: DecisionBooleanPredicateSchema3 }),
7852
+ external_exports.object({ type: external_exports.literal("choice"), pred: DecisionChoicePredicateSchema3 }),
7853
+ external_exports.object({ type: external_exports.literal("multi"), pred: DecisionMultiPredicateSchema3 })
7854
+ ]);
7855
+ var DecisionExprSchema3 = external_exports.lazy(
7856
+ () => external_exports.discriminatedUnion("kind", [
7857
+ external_exports.object({ kind: external_exports.literal("empty") }),
7858
+ external_exports.object({
7859
+ kind: external_exports.literal("group"),
7860
+ op: external_exports.enum(["and", "or"]),
7861
+ children: external_exports.array(DecisionExprSchema3).min(1)
7862
+ }),
7863
+ external_exports.object({
7864
+ kind: external_exports.literal("predicate"),
7865
+ variable: DecisionVariableRefSchema3,
7866
+ predicate: DecisionPredicatePayloadSchema3
7867
+ })
7868
+ ])
7869
+ );
7870
+ var collectDecisionSdkKeys = (expr) => {
7871
+ const out = [];
7872
+ const walk = (e) => {
7873
+ if (e.kind === "empty") return;
7874
+ if (e.kind === "predicate") {
7875
+ if (e.variable.kind === "sdk") out.push(e.variable.key);
7876
+ return;
7877
+ }
7878
+ for (const c of e.children) walk(c);
7879
+ };
7880
+ walk(expr);
7881
+ return out;
7882
+ };
7883
+ var collectDecisionFieldKeys2 = (expr) => {
7884
+ const out = [];
7885
+ const walk = (e) => {
7886
+ if (e.kind === "empty") return;
7887
+ if (e.kind === "predicate") {
7888
+ if (e.variable.kind === "field") out.push(e.variable.fieldKey);
7889
+ return;
7890
+ }
7891
+ for (const c of e.children) walk(c);
7892
+ };
7893
+ walk(expr);
7894
+ return out;
7895
+ };
7896
+ var CONDITIONAL_MAX_CASES3 = 16;
7897
+ var ConditionalCaseSchema3 = external_exports.object({
7898
+ id: external_exports.string().min(1).max(80),
7899
+ name: external_exports.string().min(1).max(80).optional(),
7900
+ expression: DecisionExprSchema3,
7901
+ rootLayerId: LayerIdSchema3
7902
+ });
7903
+ var ConditionalLayerSchema3 = external_exports.object({
7904
+ ...baseLayerShape3,
7905
+ kind: external_exports.literal("conditional"),
7906
+ cases: external_exports.array(ConditionalCaseSchema3).min(1).max(CONDITIONAL_MAX_CASES3),
7907
+ elseRootLayerId: LayerIdSchema3,
7908
+ children: external_exports.lazy(() => external_exports.array(StackLayerSchema3).min(2))
7909
+ });
7910
+ var validateConditionalCasesAndBindings = (data, ctx) => {
7911
+ const childIds = new Set(data.children.map((c) => c.id));
7912
+ const boundRootIds = /* @__PURE__ */ new Set();
7913
+ const caseIds = /* @__PURE__ */ new Set();
7914
+ const claimRoot = (rootLayerId, path) => {
7915
+ if (!childIds.has(rootLayerId)) {
7916
+ ctx.addIssue({
7917
+ code: external_exports.ZodIssueCode.custom,
7918
+ message: `conditional rootLayerId "${rootLayerId}" does not match any direct child stack`,
7919
+ path
7920
+ });
7921
+ return;
7922
+ }
7923
+ if (boundRootIds.has(rootLayerId)) {
7924
+ ctx.addIssue({
7925
+ code: external_exports.ZodIssueCode.custom,
7926
+ message: `conditional child stack "${rootLayerId}" is bound to more than one branch`,
7927
+ path
7928
+ });
7929
+ return;
7930
+ }
7931
+ boundRootIds.add(rootLayerId);
7932
+ };
7933
+ data.cases.forEach((c, idx) => {
7934
+ if (caseIds.has(c.id)) {
7935
+ ctx.addIssue({
7936
+ code: external_exports.ZodIssueCode.custom,
7937
+ message: `duplicate conditional case id "${c.id}"`,
7938
+ path: ["cases", idx, "id"]
7939
+ });
7940
+ }
7941
+ caseIds.add(c.id);
7942
+ claimRoot(c.rootLayerId, ["cases", idx, "rootLayerId"]);
7943
+ });
7944
+ claimRoot(data.elseRootLayerId, ["elseRootLayerId"]);
7945
+ for (const child of data.children) {
7946
+ if (!boundRootIds.has(child.id)) {
7947
+ ctx.addIssue({
7948
+ code: external_exports.ZodIssueCode.custom,
7949
+ message: `conditional child stack "${child.id}" is not bound to a case or the else branch`,
7950
+ path: ["children"]
7951
+ });
7952
+ }
7953
+ }
7954
+ };
7688
7955
  layerSchemaStore3.schema = external_exports.lazy(
7689
7956
  () => external_exports.union([
7690
7957
  StackLayerSchema3,
@@ -7711,11 +7978,38 @@ layerSchemaStore3.schema = external_exports.lazy(
7711
7978
  EmailPasswordAuthLayerSchema3,
7712
7979
  EmailPasswordFieldLayerSchema3,
7713
7980
  EmailPasswordSubmitLayerSchema3,
7714
- CarouselLayerSchema3
7981
+ CarouselLayerSchema3,
7982
+ ConditionalLayerSchema3
7715
7983
  ])
7716
7984
  );
7717
7985
  var LayerSchema2 = layerSchemaStore3.schema;
7718
7986
  var STYLE_BREAKPOINT_KEYS = ["sm", "md", "lg", "xl", "2xl"];
7987
+ var layerChildren = (layer) => {
7988
+ switch (layer.kind) {
7989
+ case "stack":
7990
+ case "conditional":
7991
+ case "button":
7992
+ case "back_button":
7993
+ case "hyperlink":
7994
+ case "single_choice":
7995
+ case "multiple_choice":
7996
+ case "oauth_login":
7997
+ case "email_password_auth":
7998
+ case "email_password_submit":
7999
+ return layer.children;
8000
+ case "carousel":
8001
+ return layer.slides;
8002
+ case "text_input":
8003
+ case "scale_input":
8004
+ case "wheel_picker":
8005
+ case "email_password_field":
8006
+ return layer.children ?? [];
8007
+ case "oauth_provider":
8008
+ return layer.variant === "custom" ? layer.children : [];
8009
+ default:
8010
+ return [];
8011
+ }
8012
+ };
7719
8013
  var commonStyleHasAbsolutePosition = (style, breakpoints) => {
7720
8014
  if (style?.position === "absolute") return true;
7721
8015
  if (!breakpoints) return false;
@@ -7888,117 +8182,54 @@ var ScreenBackgroundImageFillSchema = external_exports.object({
7888
8182
  kind: external_exports.literal("image"),
7889
8183
  ...screenBackgroundMediaShape
7890
8184
  });
7891
- var ScreenBackgroundVideoFillSchema = external_exports.object({
7892
- kind: external_exports.literal("video"),
7893
- ...screenBackgroundMediaShape,
7894
- loop: external_exports.boolean().optional(),
7895
- autoPlay: external_exports.boolean().optional(),
7896
- triggerLayerId: external_exports.string().min(1).optional(),
7897
- onComplete: LoaderOnCompleteSchema3.optional(),
7898
- audioEnabled: external_exports.boolean().optional()
7899
- });
7900
- var ScreenBackgroundFillSchema = external_exports.discriminatedUnion("kind", [
7901
- ScreenBackgroundColorFillSchema,
7902
- ScreenBackgroundImageFillSchema,
7903
- ScreenBackgroundVideoFillSchema
7904
- ]);
7905
- var ScreenBackgroundFillPatchSchema = external_exports.object({
7906
- color: ThemedColorSchema3.optional(),
7907
- fit: ScreenBackgroundFitSchema.optional(),
7908
- opacity: external_exports.number().min(0).max(1).optional(),
7909
- scrim: ScreenBackgroundScrimSchema.optional(),
7910
- loop: external_exports.boolean().optional(),
7911
- autoPlay: external_exports.boolean().optional(),
7912
- triggerLayerId: external_exports.string().min(1).optional(),
7913
- onComplete: LoaderOnCompleteSchema3.optional(),
7914
- audioEnabled: external_exports.boolean().optional()
7915
- }).partial();
7916
- var ScreenContainerBreakpointPatchSchema = external_exports.object({
7917
- padding: PaddingSchema3.optional(),
7918
- margin: PaddingSchema3.optional(),
7919
- insetSafeArea: external_exports.boolean().optional(),
7920
- backgroundFillPatch: ScreenBackgroundFillPatchSchema.optional()
7921
- }).partial();
7922
- var ScreenContainerStyleBreakpointsSchema = external_exports.object({
7923
- sm: ScreenContainerBreakpointPatchSchema.optional(),
7924
- md: ScreenContainerBreakpointPatchSchema.optional(),
7925
- lg: ScreenContainerBreakpointPatchSchema.optional(),
7926
- xl: ScreenContainerBreakpointPatchSchema.optional(),
7927
- "2xl": ScreenContainerBreakpointPatchSchema.optional()
7928
- }).partial().optional();
7929
- var DecisionNodeIdSchema2 = external_exports.string().min(1).max(64).regex(/^dec_[a-z0-9_]+$/i, "decision node id must look like dec_<id>");
7930
- var ExternalSurfaceJumpIdSchema23 = external_exports.string().min(1).max(64).regex(/^surf_[a-z0-9_]+$/i, "external surface node id must look like surf_<id>");
7931
- var EXTERNAL_SURFACE_NO_NEXT2 = "__onb_surface_no_next__";
7932
- var ExternalSurfaceTerminalTargetSchema2 = external_exports.literal(EXTERNAL_SURFACE_NO_NEXT2);
7933
- var FlowJumpTargetSchema2 = ScreenIdSchema3.or(DecisionNodeIdSchema2).or(ExternalSurfaceJumpIdSchema23).or(ExternalSurfaceTerminalTargetSchema2).nullable();
7934
- var DecisionBuiltinNameSchema2 = external_exports.enum(["locale", "platform"]);
7935
- var DecisionVariableRefSchema2 = external_exports.discriminatedUnion("kind", [
7936
- external_exports.object({ kind: external_exports.literal("builtin"), name: DecisionBuiltinNameSchema2 }),
7937
- external_exports.object({ kind: external_exports.literal("sdk"), key: external_exports.string().min(1).max(128) }),
7938
- external_exports.object({ kind: external_exports.literal("field"), fieldKey: external_exports.string().min(1).max(128) })
7939
- ]);
7940
- var DecisionStringPredicateSchema2 = external_exports.discriminatedUnion("op", [
7941
- external_exports.object({ op: external_exports.literal("eq"), value: external_exports.string() }),
7942
- external_exports.object({ op: external_exports.literal("neq"), value: external_exports.string() }),
7943
- external_exports.object({ op: external_exports.literal("contains"), value: external_exports.string() })
7944
- ]);
7945
- var DecisionNumberPredicateSchema2 = external_exports.discriminatedUnion("op", [
7946
- external_exports.object({ op: external_exports.literal("eq"), value: external_exports.number() }),
7947
- external_exports.object({ op: external_exports.literal("neq"), value: external_exports.number() }),
7948
- external_exports.object({ op: external_exports.literal("lt"), value: external_exports.number() }),
7949
- external_exports.object({ op: external_exports.literal("lte"), value: external_exports.number() }),
7950
- external_exports.object({ op: external_exports.literal("gt"), value: external_exports.number() }),
7951
- external_exports.object({ op: external_exports.literal("gte"), value: external_exports.number() })
7952
- ]);
7953
- var DecisionChoicePredicateSchema2 = external_exports.discriminatedUnion("op", [
7954
- external_exports.object({ op: external_exports.literal("eq"), optionId: external_exports.string().min(1) }),
7955
- external_exports.object({ op: external_exports.literal("one_of"), optionIds: external_exports.array(external_exports.string().min(1)).min(1) })
7956
- ]);
7957
- var DecisionMultiPredicateSchema2 = external_exports.discriminatedUnion("op", [
7958
- external_exports.object({
7959
- op: external_exports.literal("intersects"),
7960
- optionIds: external_exports.array(external_exports.string().min(1)).min(1)
7961
- }),
7962
- external_exports.object({
7963
- op: external_exports.literal("contains_all"),
7964
- optionIds: external_exports.array(external_exports.string().min(1)).min(1)
7965
- }),
7966
- external_exports.object({
7967
- op: external_exports.literal("subset_of"),
7968
- optionIds: external_exports.array(external_exports.string().min(1)).min(1)
7969
- })
7970
- ]);
7971
- var DecisionBooleanPredicateSchema2 = external_exports.discriminatedUnion("op", [
7972
- external_exports.object({ op: external_exports.literal("eq"), value: external_exports.boolean() }),
7973
- external_exports.object({ op: external_exports.literal("neq"), value: external_exports.boolean() })
7974
- ]);
7975
- var DecisionPredicatePayloadSchema2 = external_exports.discriminatedUnion("type", [
7976
- external_exports.object({ type: external_exports.literal("string"), pred: DecisionStringPredicateSchema2 }),
7977
- external_exports.object({ type: external_exports.literal("number"), pred: DecisionNumberPredicateSchema2 }),
7978
- external_exports.object({ type: external_exports.literal("boolean"), pred: DecisionBooleanPredicateSchema2 }),
7979
- external_exports.object({ type: external_exports.literal("choice"), pred: DecisionChoicePredicateSchema2 }),
7980
- external_exports.object({ type: external_exports.literal("multi"), pred: DecisionMultiPredicateSchema2 })
7981
- ]);
7982
- var DecisionExprSchema2 = external_exports.lazy(
7983
- () => external_exports.discriminatedUnion("kind", [
7984
- external_exports.object({ kind: external_exports.literal("empty") }),
7985
- external_exports.object({
7986
- kind: external_exports.literal("group"),
7987
- op: external_exports.enum(["and", "or"]),
7988
- children: external_exports.array(DecisionExprSchema2).min(1)
7989
- }),
7990
- external_exports.object({
7991
- kind: external_exports.literal("predicate"),
7992
- variable: DecisionVariableRefSchema2,
7993
- predicate: DecisionPredicatePayloadSchema2
7994
- })
7995
- ])
7996
- );
8185
+ var ScreenBackgroundVideoFillSchema = external_exports.object({
8186
+ kind: external_exports.literal("video"),
8187
+ ...screenBackgroundMediaShape,
8188
+ loop: external_exports.boolean().optional(),
8189
+ autoPlay: external_exports.boolean().optional(),
8190
+ triggerLayerId: external_exports.string().min(1).optional(),
8191
+ onComplete: LoaderOnCompleteSchema3.optional(),
8192
+ audioEnabled: external_exports.boolean().optional()
8193
+ });
8194
+ var ScreenBackgroundFillSchema = external_exports.discriminatedUnion("kind", [
8195
+ ScreenBackgroundColorFillSchema,
8196
+ ScreenBackgroundImageFillSchema,
8197
+ ScreenBackgroundVideoFillSchema
8198
+ ]);
8199
+ var ScreenBackgroundFillPatchSchema = external_exports.object({
8200
+ color: ThemedColorSchema3.optional(),
8201
+ fit: ScreenBackgroundFitSchema.optional(),
8202
+ opacity: external_exports.number().min(0).max(1).optional(),
8203
+ scrim: ScreenBackgroundScrimSchema.optional(),
8204
+ loop: external_exports.boolean().optional(),
8205
+ autoPlay: external_exports.boolean().optional(),
8206
+ triggerLayerId: external_exports.string().min(1).optional(),
8207
+ onComplete: LoaderOnCompleteSchema3.optional(),
8208
+ audioEnabled: external_exports.boolean().optional()
8209
+ }).partial();
8210
+ var ScreenContainerBreakpointPatchSchema = external_exports.object({
8211
+ padding: PaddingSchema3.optional(),
8212
+ margin: PaddingSchema3.optional(),
8213
+ insetSafeArea: external_exports.boolean().optional(),
8214
+ backgroundFillPatch: ScreenBackgroundFillPatchSchema.optional()
8215
+ }).partial();
8216
+ var ScreenContainerStyleBreakpointsSchema = external_exports.object({
8217
+ sm: ScreenContainerBreakpointPatchSchema.optional(),
8218
+ md: ScreenContainerBreakpointPatchSchema.optional(),
8219
+ lg: ScreenContainerBreakpointPatchSchema.optional(),
8220
+ xl: ScreenContainerBreakpointPatchSchema.optional(),
8221
+ "2xl": ScreenContainerBreakpointPatchSchema.optional()
8222
+ }).partial().optional();
8223
+ var DecisionNodeIdSchema2 = external_exports.string().min(1).max(64).regex(/^dec_[a-z0-9_]+$/i, "decision node id must look like dec_<id>");
8224
+ var ExternalSurfaceJumpIdSchema23 = external_exports.string().min(1).max(64).regex(/^surf_[a-z0-9_]+$/i, "external surface node id must look like surf_<id>");
8225
+ var EXTERNAL_SURFACE_NO_NEXT2 = "__onb_surface_no_next__";
8226
+ var ExternalSurfaceTerminalTargetSchema2 = external_exports.literal(EXTERNAL_SURFACE_NO_NEXT2);
8227
+ var FlowJumpTargetSchema2 = ScreenIdSchema3.or(DecisionNodeIdSchema2).or(ExternalSurfaceJumpIdSchema23).or(ExternalSurfaceTerminalTargetSchema2).nullable();
7997
8228
  var DecisionCaseSchema2 = external_exports.object({
7998
8229
  id: external_exports.string().min(1).max(80),
7999
8230
  /** Display label in the editor (e.g. “Engaged users”). */
8000
8231
  name: external_exports.string().min(1).max(80).optional(),
8001
- expression: DecisionExprSchema2,
8232
+ expression: DecisionExprSchema3,
8002
8233
  next: FlowJumpTargetSchema2
8003
8234
  });
8004
8235
  var DecisionNodeSchema2 = external_exports.object({
@@ -8028,32 +8259,6 @@ var migrateLegacyDecisionNodeInPlace = (node) => {
8028
8259
  ];
8029
8260
  node.elseNext = onFalse;
8030
8261
  };
8031
- var collectDecisionSdkKeys = (expr) => {
8032
- const out = [];
8033
- const walk = (e) => {
8034
- if (e.kind === "empty") return;
8035
- if (e.kind === "predicate") {
8036
- if (e.variable.kind === "sdk") out.push(e.variable.key);
8037
- return;
8038
- }
8039
- for (const c of e.children) walk(c);
8040
- };
8041
- walk(expr);
8042
- return out;
8043
- };
8044
- var collectDecisionFieldKeys2 = (expr) => {
8045
- const out = [];
8046
- const walk = (e) => {
8047
- if (e.kind === "empty") return;
8048
- if (e.kind === "predicate") {
8049
- if (e.variable.kind === "field") out.push(e.variable.fieldKey);
8050
- return;
8051
- }
8052
- for (const c of e.children) walk(c);
8053
- };
8054
- walk(expr);
8055
- return out;
8056
- };
8057
8262
  var collectDecisionFieldKeysFromNode2 = (node) => {
8058
8263
  const seen = /* @__PURE__ */ new Set();
8059
8264
  for (const c of node.cases) {
@@ -8102,6 +8307,8 @@ var walkScreenLayersWithLayoutContext = (screen, fn) => {
8102
8307
  for (const c of l.children) visit(c, childCtx());
8103
8308
  } else if (l.kind === "carousel") {
8104
8309
  for (const s of l.slides) visit(s, childCtx());
8310
+ } else if (l.kind === "conditional") {
8311
+ for (const c of l.children) visit(c, childCtx());
8105
8312
  } else if (l.kind === "button" || l.kind === "back_button") {
8106
8313
  for (const c of l.children) visit(c, childCtx());
8107
8314
  } else if (l.kind === "hyperlink") {
@@ -8139,6 +8346,7 @@ var walkScreenLayers = (screen, fn) => {
8139
8346
  fn(l);
8140
8347
  if (l.kind === "stack") l.children.forEach(visit);
8141
8348
  else if (l.kind === "carousel") l.slides.forEach(visit);
8349
+ else if (l.kind === "conditional") l.children.forEach(visit);
8142
8350
  else if (l.kind === "button") l.children.forEach(visit);
8143
8351
  else if (l.kind === "back_button") l.children.forEach(visit);
8144
8352
  else if (l.kind === "hyperlink") l.children.forEach(visit);
@@ -8162,16 +8370,72 @@ var walkScreenLayers = (screen, fn) => {
8162
8370
  visit(screen.regions.body);
8163
8371
  if (screen.regions.footer) visit(screen.regions.footer);
8164
8372
  };
8373
+ var maxMatchesOnActivePath = (root, match) => {
8374
+ const self = match(root) ? 1 : 0;
8375
+ if (root.kind === "conditional") {
8376
+ let widest = 0;
8377
+ for (const branch of root.children) {
8378
+ widest = Math.max(widest, maxMatchesOnActivePath(branch, match));
8379
+ }
8380
+ return self + widest;
8381
+ }
8382
+ let total = 0;
8383
+ for (const child of layerChildren(root)) {
8384
+ total += maxMatchesOnActivePath(child, match);
8385
+ }
8386
+ return self + total;
8387
+ };
8388
+ var maxMatchesOnScreenActivePath = (screen, match) => {
8389
+ const { header, body, footer } = screen.regions;
8390
+ return (header ? maxMatchesOnActivePath(header, match) : 0) + maxMatchesOnActivePath(body, match) + (footer ? maxMatchesOnActivePath(footer, match) : 0);
8391
+ };
8392
+ var answerFieldKeyOf = (l) => {
8393
+ if (isInputLayer2(l)) return l.fieldKey;
8394
+ if (l.kind === "checkbox") return l.fieldKey;
8395
+ if (l.kind === "email_password_auth") return l.fieldKey;
8396
+ return null;
8397
+ };
8398
+ var conditionalFieldScopeViolations = (screen) => {
8399
+ const fieldOrderOnScreen = /* @__PURE__ */ new Map();
8400
+ const conditionals = [];
8401
+ let order = 0;
8402
+ walkScreenLayers(screen, (l) => {
8403
+ const fieldKey = answerFieldKeyOf(l);
8404
+ if (fieldKey != null && !fieldOrderOnScreen.has(fieldKey)) {
8405
+ fieldOrderOnScreen.set(fieldKey, order);
8406
+ }
8407
+ if (l.kind === "conditional") conditionals.push({ layer: l, order });
8408
+ order += 1;
8409
+ });
8410
+ const violations = [];
8411
+ for (const { layer, order: conditionalOrder } of conditionals) {
8412
+ layer.cases.forEach((c, caseIndex) => {
8413
+ for (const fieldKey of collectDecisionFieldKeys2(c.expression)) {
8414
+ const declaredAt = fieldOrderOnScreen.get(fieldKey);
8415
+ if (declaredAt === void 0) continue;
8416
+ if (declaredAt >= conditionalOrder) {
8417
+ violations.push({ conditionalId: layer.id, caseId: c.id, caseIndex, fieldKey });
8418
+ }
8419
+ }
8420
+ });
8421
+ }
8422
+ return violations;
8423
+ };
8165
8424
  var ExternalSurfaceNodeIdSchema = external_exports.string().min(1).max(64).regex(/^surf_[a-z0-9_]+$/i, "external surface node id must look like surf_<id>");
8166
- var NORMALIZED_SURFACE_OUTCOMES = [
8425
+ var IAP_SURFACE_OUTCOMES = [
8167
8426
  "purchase_completed",
8168
8427
  "purchase_cancelled",
8169
8428
  "dismissed",
8170
8429
  "failed",
8171
8430
  "restore_completed"
8172
8431
  ];
8432
+ var NORMALIZED_SURFACE_OUTCOMES = [
8433
+ ...IAP_SURFACE_OUTCOMES,
8434
+ "completed",
8435
+ "back"
8436
+ ];
8173
8437
  var NormalizedSurfaceOutcomeSchema = external_exports.enum(NORMALIZED_SURFACE_OUTCOMES);
8174
- var SurfaceProviderSchema = external_exports.enum(["unspecified", "revenuecat"]);
8438
+ var SurfaceProviderSchema = external_exports.enum(["unspecified", "revenuecat", "headless"]);
8175
8439
  var UnspecifiedExternalSurfaceConfigSchema = external_exports.object({
8176
8440
  provider: external_exports.literal("unspecified")
8177
8441
  });
@@ -8182,16 +8446,28 @@ var RevenueCatSurfaceConfigSchema = external_exports.object({
8182
8446
  placementId: external_exports.string().min(1).max(128).optional(),
8183
8447
  presentation: RevenueCatSurfacePresentationSchema.optional()
8184
8448
  });
8449
+ var ExternalSurfaceHostKeySchema = external_exports.string().min(1).max(64).regex(
8450
+ /^[a-zA-Z][a-zA-Z0-9_]*$/,
8451
+ "host key must start with a letter and contain only letters, digits, or underscores"
8452
+ );
8453
+ var HeadlessExternalSurfaceConfigSchema = external_exports.object({
8454
+ provider: external_exports.literal("headless"),
8455
+ /** Registry key for `Flow` / `FlowView` `externalSurfaces`. Defaults to the node id. */
8456
+ hostKey: ExternalSurfaceHostKeySchema.optional()
8457
+ });
8185
8458
  var ExternalSurfaceConfigSchema = external_exports.discriminatedUnion("provider", [
8186
8459
  UnspecifiedExternalSurfaceConfigSchema,
8187
- RevenueCatSurfaceConfigSchema
8460
+ RevenueCatSurfaceConfigSchema,
8461
+ HeadlessExternalSurfaceConfigSchema
8188
8462
  ]);
8189
8463
  var ExternalSurfaceOutcomesMapSchema = external_exports.object({
8190
8464
  purchase_completed: FlowJumpTargetSchema2.optional(),
8191
8465
  purchase_cancelled: FlowJumpTargetSchema2.optional(),
8192
8466
  dismissed: FlowJumpTargetSchema2.optional(),
8193
8467
  failed: FlowJumpTargetSchema2.optional(),
8194
- restore_completed: FlowJumpTargetSchema2.optional()
8468
+ restore_completed: FlowJumpTargetSchema2.optional(),
8469
+ completed: FlowJumpTargetSchema2.optional(),
8470
+ back: FlowJumpTargetSchema2.optional()
8195
8471
  }).strict();
8196
8472
  var ExternalSurfaceNodeSchema = external_exports.object({
8197
8473
  id: ExternalSurfaceNodeIdSchema,
@@ -8202,6 +8478,12 @@ var ExternalSurfaceNodeSchema = external_exports.object({
8202
8478
  /** Required: used for any outcome not in `outcomes` (e.g. provider quirks, unmapped events). */
8203
8479
  fallback: FlowJumpTargetSchema2
8204
8480
  });
8481
+ var resolveExternalSurfaceHostKey = (node) => {
8482
+ if (node.config.provider === "headless" && node.config.hostKey) {
8483
+ return node.config.hostKey;
8484
+ }
8485
+ return node.id;
8486
+ };
8205
8487
  var RESERVED_RC_SDK_KEYS = [
8206
8488
  /** Last RC event observed by the SDK (e.g. `purchase_completed`, `purchase_cancelled`). */
8207
8489
  "onb_rc_last_event",
@@ -8292,6 +8574,8 @@ var migrateLayerInPlace = (layer) => {
8292
8574
  for (const c of l.children) migrateLayerInPlace(c);
8293
8575
  } else if (l.kind === "carousel" && Array.isArray(l.slides)) {
8294
8576
  for (const s of l.slides) migrateLayerInPlace(s);
8577
+ } else if (l.kind === "conditional" && Array.isArray(l.children)) {
8578
+ for (const c of l.children) migrateLayerInPlace(c);
8295
8579
  } else if (l.kind === "button" && Array.isArray(l.children)) {
8296
8580
  for (const c of l.children) migrateLayerInPlace(c);
8297
8581
  } else if (l.kind === "back_button" && Array.isArray(l.children)) {
@@ -8449,6 +8733,7 @@ var refineManifestGraph = (manifest, ctx, jumpTargets) => {
8449
8733
  }
8450
8734
  });
8451
8735
  const seenSurfaceId = /* @__PURE__ */ new Set();
8736
+ const seenHostKey = /* @__PURE__ */ new Set();
8452
8737
  manifest.externalSurfaceNodes.forEach((sn, si) => {
8453
8738
  if (seenSurfaceId.has(sn.id)) {
8454
8739
  ctx.addIssue({
@@ -8472,6 +8757,17 @@ var refineManifestGraph = (manifest, ctx, jumpTargets) => {
8472
8757
  path: ["externalSurfaceNodes", si]
8473
8758
  });
8474
8759
  }
8760
+ if (sn.config.provider === "headless") {
8761
+ const hostKey = resolveExternalSurfaceHostKey(sn);
8762
+ if (seenHostKey.has(hostKey)) {
8763
+ ctx.addIssue({
8764
+ code: external_exports.ZodIssueCode.custom,
8765
+ message: `duplicate external surface host key "${hostKey}"`,
8766
+ path: ["externalSurfaceNodes", si, "config", "hostKey"]
8767
+ });
8768
+ }
8769
+ seenHostKey.add(hostKey);
8770
+ }
8475
8771
  for (const [outcome, target] of Object.entries(sn.outcomes)) {
8476
8772
  if (target != null && !jumpTargets.has(target)) {
8477
8773
  ctx.addIssue({
@@ -8493,8 +8789,8 @@ var refineManifestGraph = (manifest, ctx, jumpTargets) => {
8493
8789
  };
8494
8790
  var refineManifestScreens = (manifest, ctx, jumpTargets, screenIds, allFieldKeys) => {
8495
8791
  const layerIds = /* @__PURE__ */ new Set();
8792
+ const sdkAllow = new Set(manifest.sdkAttributeKeys);
8496
8793
  manifest.screens.forEach((screen, screenIdx) => {
8497
- let inputCount = 0;
8498
8794
  const layerIdsForScreen = /* @__PURE__ */ new Set();
8499
8795
  walkScreenLayers(screen, (l) => {
8500
8796
  layerIdsForScreen.add(l.id);
@@ -8509,7 +8805,6 @@ var refineManifestScreens = (manifest, ctx, jumpTargets, screenIds, allFieldKeys
8509
8805
  }
8510
8806
  layerIds.add(l.id);
8511
8807
  if (isInputLayer2(l)) {
8512
- inputCount += 1;
8513
8808
  if (allFieldKeys.has(l.fieldKey)) {
8514
8809
  ctx.addIssue({
8515
8810
  code: external_exports.ZodIssueCode.custom,
@@ -8534,10 +8829,18 @@ var refineManifestScreens = (manifest, ctx, jumpTargets, screenIds, allFieldKeys
8534
8829
  if (!allFieldKeys.has(fk)) allFieldKeys.set(fk, screen.id);
8535
8830
  }
8536
8831
  });
8537
- if (inputCount > 1) {
8832
+ const inputsOnPath = maxMatchesOnScreenActivePath(screen, isInputLayer2);
8833
+ if (inputsOnPath > 1) {
8834
+ ctx.addIssue({
8835
+ code: external_exports.ZodIssueCode.custom,
8836
+ message: `screen "${screen.id}" can show ${inputsOnPath} input layers at once (max 1 allowed)`,
8837
+ path: ["screens", screenIdx, "regions"]
8838
+ });
8839
+ }
8840
+ for (const v of conditionalFieldScopeViolations(screen)) {
8538
8841
  ctx.addIssue({
8539
8842
  code: external_exports.ZodIssueCode.custom,
8540
- message: `screen "${screen.id}" has ${inputCount} input layers (max 1 allowed)`,
8843
+ message: `conditional "${v.conditionalId}" case "${v.caseId}" reads fieldKey "${v.fieldKey}" that is answered at or after it on the same screen`,
8541
8844
  path: ["screens", screenIdx, "regions"]
8542
8845
  });
8543
8846
  }
@@ -8606,6 +8909,21 @@ var refineManifestScreens = (manifest, ctx, jumpTargets, screenIds, allFieldKeys
8606
8909
  }
8607
8910
  }
8608
8911
  }
8912
+ if (l.kind === "conditional") {
8913
+ validateConditionalCasesAndBindings(l, ctx);
8914
+ for (const c of l.cases) {
8915
+ for (const sk of collectDecisionSdkKeys(c.expression)) {
8916
+ if (isReservedSdkKey(sk)) continue;
8917
+ if (!sdkAllow.has(sk)) {
8918
+ ctx.addIssue({
8919
+ code: external_exports.ZodIssueCode.custom,
8920
+ message: `conditional "${l.id}" case "${c.id}" references sdk key "${sk}" not in sdkAttributeKeys`,
8921
+ path: ["screens", screenIdx]
8922
+ });
8923
+ }
8924
+ }
8925
+ }
8926
+ }
8609
8927
  if (l.kind === "button" && l.action.kind === "go_to_step") {
8610
8928
  if (!jumpTargets.has(l.action.screenId)) {
8611
8929
  ctx.addIssue({
@@ -8757,6 +9075,22 @@ var refineFlowManifest = (manifest, ctx) => {
8757
9075
  }
8758
9076
  }
8759
9077
  });
9078
+ manifest.screens.forEach((screen, screenIdx) => {
9079
+ walkScreenLayers(screen, (l) => {
9080
+ if (l.kind !== "conditional") return;
9081
+ for (const c of l.cases) {
9082
+ for (const fk of collectDecisionFieldKeys2(c.expression)) {
9083
+ if (!allFieldKeys.has(fk)) {
9084
+ ctx.addIssue({
9085
+ code: external_exports.ZodIssueCode.custom,
9086
+ message: `conditional "${l.id}" case "${c.id}" references unknown fieldKey "${fk}"`,
9087
+ path: ["screens", screenIdx, "regions"]
9088
+ });
9089
+ }
9090
+ }
9091
+ }
9092
+ });
9093
+ });
8760
9094
  if (manifest.locales.length > 0 && !manifest.locales.includes(manifest.defaultLocale)) {
8761
9095
  ctx.addIssue({
8762
9096
  code: external_exports.ZodIssueCode.custom,
@@ -8839,7 +9173,10 @@ var FontStyleSchema = external_exports.object({
8839
9173
  label: external_exports.string().max(40).optional(),
8840
9174
  /** MediaAsset id of the uploaded font file. */
8841
9175
  mediaAssetId: external_exports.string().uuid().optional(),
8842
- /** Public URL of the uploaded font file (denormalized for SDK consumption). */
9176
+ /**
9177
+ * Access URL for the uploaded font file (denormalized for SDK consumption).
9178
+ * Freshly signed on SDK resolve and dashboard app reads; do not persist as long-lived.
9179
+ */
8843
9180
  url: external_exports.string().url().optional(),
8844
9181
  /** Original filename — useful for display. */
8845
9182
  filename: external_exports.string().max(200).optional()
@@ -9450,6 +9787,8 @@ var OsPermissionOutcomesSchema4 = external_exports.object({
9450
9787
  }).strict();
9451
9788
  var APP_REVIEW_OUTCOMES4 = ["not_shown", "dismissed"];
9452
9789
  external_exports.enum(APP_REVIEW_OUTCOMES4);
9790
+ var CAROUSEL_ADVANCE_ON_LAST4 = ["noop", "complete"];
9791
+ var CarouselAdvanceOnLastSchema4 = external_exports.enum(CAROUSEL_ADVANCE_ON_LAST4);
9453
9792
  var ButtonActionSchema4 = external_exports.discriminatedUnion("kind", [
9454
9793
  external_exports.object({ kind: external_exports.literal("none") }),
9455
9794
  external_exports.object({ kind: external_exports.literal("continue") }),
@@ -9469,7 +9808,12 @@ var ButtonActionSchema4 = external_exports.discriminatedUnion("kind", [
9469
9808
  kind: external_exports.literal("play_media"),
9470
9809
  targetLayerIds: external_exports.array(external_exports.string().min(1)).min(1)
9471
9810
  }),
9472
- external_exports.object({ kind: external_exports.literal("request_app_review") })
9811
+ external_exports.object({ kind: external_exports.literal("request_app_review") }),
9812
+ external_exports.object({
9813
+ kind: external_exports.literal("advance_carousel"),
9814
+ targetLayerId: external_exports.string().min(1),
9815
+ onLast: CarouselAdvanceOnLastSchema4.optional()
9816
+ })
9473
9817
  ]);
9474
9818
  var TEXT_INPUT_TYPES4 = ["plain", "email", "phone", "url", "number", "multiline"];
9475
9819
  var TextInputTypeSchema4 = external_exports.enum(TEXT_INPUT_TYPES4);
@@ -10212,6 +10556,83 @@ var CarouselLayerSchema4 = external_exports.object({
10212
10556
  styleBreakpoints: CommonStyleBreakpointsSchema4,
10213
10557
  carouselLayoutBreakpoints: CarouselLayoutBreakpointsSchema4
10214
10558
  });
10559
+ var DecisionBuiltinNameSchema4 = external_exports.enum(["locale", "platform"]);
10560
+ var DecisionVariableRefSchema4 = external_exports.discriminatedUnion("kind", [
10561
+ external_exports.object({ kind: external_exports.literal("builtin"), name: DecisionBuiltinNameSchema4 }),
10562
+ external_exports.object({ kind: external_exports.literal("sdk"), key: external_exports.string().min(1).max(128) }),
10563
+ external_exports.object({ kind: external_exports.literal("field"), fieldKey: external_exports.string().min(1).max(128) })
10564
+ ]);
10565
+ var DecisionStringPredicateSchema4 = external_exports.discriminatedUnion("op", [
10566
+ external_exports.object({ op: external_exports.literal("eq"), value: external_exports.string() }),
10567
+ external_exports.object({ op: external_exports.literal("neq"), value: external_exports.string() }),
10568
+ external_exports.object({ op: external_exports.literal("contains"), value: external_exports.string() })
10569
+ ]);
10570
+ var DecisionNumberPredicateSchema4 = external_exports.discriminatedUnion("op", [
10571
+ external_exports.object({ op: external_exports.literal("eq"), value: external_exports.number() }),
10572
+ external_exports.object({ op: external_exports.literal("neq"), value: external_exports.number() }),
10573
+ external_exports.object({ op: external_exports.literal("lt"), value: external_exports.number() }),
10574
+ external_exports.object({ op: external_exports.literal("lte"), value: external_exports.number() }),
10575
+ external_exports.object({ op: external_exports.literal("gt"), value: external_exports.number() }),
10576
+ external_exports.object({ op: external_exports.literal("gte"), value: external_exports.number() })
10577
+ ]);
10578
+ var DecisionChoicePredicateSchema4 = external_exports.discriminatedUnion("op", [
10579
+ external_exports.object({ op: external_exports.literal("eq"), optionId: external_exports.string().min(1) }),
10580
+ external_exports.object({ op: external_exports.literal("one_of"), optionIds: external_exports.array(external_exports.string().min(1)).min(1) })
10581
+ ]);
10582
+ var DecisionMultiPredicateSchema4 = external_exports.discriminatedUnion("op", [
10583
+ external_exports.object({
10584
+ op: external_exports.literal("intersects"),
10585
+ optionIds: external_exports.array(external_exports.string().min(1)).min(1)
10586
+ }),
10587
+ external_exports.object({
10588
+ op: external_exports.literal("contains_all"),
10589
+ optionIds: external_exports.array(external_exports.string().min(1)).min(1)
10590
+ }),
10591
+ external_exports.object({
10592
+ op: external_exports.literal("subset_of"),
10593
+ optionIds: external_exports.array(external_exports.string().min(1)).min(1)
10594
+ })
10595
+ ]);
10596
+ var DecisionBooleanPredicateSchema4 = external_exports.discriminatedUnion("op", [
10597
+ external_exports.object({ op: external_exports.literal("eq"), value: external_exports.boolean() }),
10598
+ external_exports.object({ op: external_exports.literal("neq"), value: external_exports.boolean() })
10599
+ ]);
10600
+ var DecisionPredicatePayloadSchema4 = external_exports.discriminatedUnion("type", [
10601
+ external_exports.object({ type: external_exports.literal("string"), pred: DecisionStringPredicateSchema4 }),
10602
+ external_exports.object({ type: external_exports.literal("number"), pred: DecisionNumberPredicateSchema4 }),
10603
+ external_exports.object({ type: external_exports.literal("boolean"), pred: DecisionBooleanPredicateSchema4 }),
10604
+ external_exports.object({ type: external_exports.literal("choice"), pred: DecisionChoicePredicateSchema4 }),
10605
+ external_exports.object({ type: external_exports.literal("multi"), pred: DecisionMultiPredicateSchema4 })
10606
+ ]);
10607
+ var DecisionExprSchema4 = external_exports.lazy(
10608
+ () => external_exports.discriminatedUnion("kind", [
10609
+ external_exports.object({ kind: external_exports.literal("empty") }),
10610
+ external_exports.object({
10611
+ kind: external_exports.literal("group"),
10612
+ op: external_exports.enum(["and", "or"]),
10613
+ children: external_exports.array(DecisionExprSchema4).min(1)
10614
+ }),
10615
+ external_exports.object({
10616
+ kind: external_exports.literal("predicate"),
10617
+ variable: DecisionVariableRefSchema4,
10618
+ predicate: DecisionPredicatePayloadSchema4
10619
+ })
10620
+ ])
10621
+ );
10622
+ var CONDITIONAL_MAX_CASES4 = 16;
10623
+ var ConditionalCaseSchema4 = external_exports.object({
10624
+ id: external_exports.string().min(1).max(80),
10625
+ name: external_exports.string().min(1).max(80).optional(),
10626
+ expression: DecisionExprSchema4,
10627
+ rootLayerId: LayerIdSchema4
10628
+ });
10629
+ var ConditionalLayerSchema4 = external_exports.object({
10630
+ ...baseLayerShape4,
10631
+ kind: external_exports.literal("conditional"),
10632
+ cases: external_exports.array(ConditionalCaseSchema4).min(1).max(CONDITIONAL_MAX_CASES4),
10633
+ elseRootLayerId: LayerIdSchema4,
10634
+ children: external_exports.lazy(() => external_exports.array(StackLayerSchema4).min(2))
10635
+ });
10215
10636
  layerSchemaStore4.schema = external_exports.lazy(
10216
10637
  () => external_exports.union([
10217
10638
  StackLayerSchema4,
@@ -10238,7 +10659,8 @@ layerSchemaStore4.schema = external_exports.lazy(
10238
10659
  EmailPasswordAuthLayerSchema4,
10239
10660
  EmailPasswordFieldLayerSchema4,
10240
10661
  EmailPasswordSubmitLayerSchema4,
10241
- CarouselLayerSchema4
10662
+ CarouselLayerSchema4,
10663
+ ConditionalLayerSchema4
10242
10664
  ])
10243
10665
  );
10244
10666
  var ScreenBackgroundFitSchema2 = external_exports.enum(["cover", "contain", "fill"]);
@@ -10304,74 +10726,11 @@ var ExternalSurfaceJumpIdSchema24 = external_exports.string().min(1).max(64).reg
10304
10726
  var EXTERNAL_SURFACE_NO_NEXT3 = "__onb_surface_no_next__";
10305
10727
  var ExternalSurfaceTerminalTargetSchema3 = external_exports.literal(EXTERNAL_SURFACE_NO_NEXT3);
10306
10728
  var FlowJumpTargetSchema3 = ScreenIdSchema4.or(DecisionNodeIdSchema3).or(ExternalSurfaceJumpIdSchema24).or(ExternalSurfaceTerminalTargetSchema3).nullable();
10307
- var DecisionBuiltinNameSchema3 = external_exports.enum(["locale", "platform"]);
10308
- var DecisionVariableRefSchema3 = external_exports.discriminatedUnion("kind", [
10309
- external_exports.object({ kind: external_exports.literal("builtin"), name: DecisionBuiltinNameSchema3 }),
10310
- external_exports.object({ kind: external_exports.literal("sdk"), key: external_exports.string().min(1).max(128) }),
10311
- external_exports.object({ kind: external_exports.literal("field"), fieldKey: external_exports.string().min(1).max(128) })
10312
- ]);
10313
- var DecisionStringPredicateSchema3 = external_exports.discriminatedUnion("op", [
10314
- external_exports.object({ op: external_exports.literal("eq"), value: external_exports.string() }),
10315
- external_exports.object({ op: external_exports.literal("neq"), value: external_exports.string() }),
10316
- external_exports.object({ op: external_exports.literal("contains"), value: external_exports.string() })
10317
- ]);
10318
- var DecisionNumberPredicateSchema3 = external_exports.discriminatedUnion("op", [
10319
- external_exports.object({ op: external_exports.literal("eq"), value: external_exports.number() }),
10320
- external_exports.object({ op: external_exports.literal("neq"), value: external_exports.number() }),
10321
- external_exports.object({ op: external_exports.literal("lt"), value: external_exports.number() }),
10322
- external_exports.object({ op: external_exports.literal("lte"), value: external_exports.number() }),
10323
- external_exports.object({ op: external_exports.literal("gt"), value: external_exports.number() }),
10324
- external_exports.object({ op: external_exports.literal("gte"), value: external_exports.number() })
10325
- ]);
10326
- var DecisionChoicePredicateSchema3 = external_exports.discriminatedUnion("op", [
10327
- external_exports.object({ op: external_exports.literal("eq"), optionId: external_exports.string().min(1) }),
10328
- external_exports.object({ op: external_exports.literal("one_of"), optionIds: external_exports.array(external_exports.string().min(1)).min(1) })
10329
- ]);
10330
- var DecisionMultiPredicateSchema3 = external_exports.discriminatedUnion("op", [
10331
- external_exports.object({
10332
- op: external_exports.literal("intersects"),
10333
- optionIds: external_exports.array(external_exports.string().min(1)).min(1)
10334
- }),
10335
- external_exports.object({
10336
- op: external_exports.literal("contains_all"),
10337
- optionIds: external_exports.array(external_exports.string().min(1)).min(1)
10338
- }),
10339
- external_exports.object({
10340
- op: external_exports.literal("subset_of"),
10341
- optionIds: external_exports.array(external_exports.string().min(1)).min(1)
10342
- })
10343
- ]);
10344
- var DecisionBooleanPredicateSchema3 = external_exports.discriminatedUnion("op", [
10345
- external_exports.object({ op: external_exports.literal("eq"), value: external_exports.boolean() }),
10346
- external_exports.object({ op: external_exports.literal("neq"), value: external_exports.boolean() })
10347
- ]);
10348
- var DecisionPredicatePayloadSchema3 = external_exports.discriminatedUnion("type", [
10349
- external_exports.object({ type: external_exports.literal("string"), pred: DecisionStringPredicateSchema3 }),
10350
- external_exports.object({ type: external_exports.literal("number"), pred: DecisionNumberPredicateSchema3 }),
10351
- external_exports.object({ type: external_exports.literal("boolean"), pred: DecisionBooleanPredicateSchema3 }),
10352
- external_exports.object({ type: external_exports.literal("choice"), pred: DecisionChoicePredicateSchema3 }),
10353
- external_exports.object({ type: external_exports.literal("multi"), pred: DecisionMultiPredicateSchema3 })
10354
- ]);
10355
- var DecisionExprSchema3 = external_exports.lazy(
10356
- () => external_exports.discriminatedUnion("kind", [
10357
- external_exports.object({ kind: external_exports.literal("empty") }),
10358
- external_exports.object({
10359
- kind: external_exports.literal("group"),
10360
- op: external_exports.enum(["and", "or"]),
10361
- children: external_exports.array(DecisionExprSchema3).min(1)
10362
- }),
10363
- external_exports.object({
10364
- kind: external_exports.literal("predicate"),
10365
- variable: DecisionVariableRefSchema3,
10366
- predicate: DecisionPredicatePayloadSchema3
10367
- })
10368
- ])
10369
- );
10370
10729
  var DecisionCaseSchema3 = external_exports.object({
10371
10730
  id: external_exports.string().min(1).max(80),
10372
10731
  /** Display label in the editor (e.g. “Engaged users”). */
10373
10732
  name: external_exports.string().min(1).max(80).optional(),
10374
- expression: DecisionExprSchema3,
10733
+ expression: DecisionExprSchema4,
10375
10734
  next: FlowJumpTargetSchema3
10376
10735
  });
10377
10736
  external_exports.object({
@@ -10526,6 +10885,7 @@ var walkLayers = (root, fn) => {
10526
10885
  fn(l, depth);
10527
10886
  if (l.kind === "stack") l.children.forEach((c) => visit(c, depth + 1));
10528
10887
  else if (l.kind === "carousel") l.slides.forEach((c) => visit(c, depth + 1));
10888
+ else if (l.kind === "conditional") l.children.forEach((c) => visit(c, depth + 1));
10529
10889
  else if (l.kind === "button") l.children.forEach((c) => visit(c, depth + 1));
10530
10890
  else if (l.kind === "back_button") l.children.forEach((c) => visit(c, depth + 1));
10531
10891
  else if (l.kind === "hyperlink") l.children.forEach((c) => visit(c, depth + 1));
@@ -10721,6 +11081,18 @@ var validatePublishable = (manifest) => {
10721
11081
  code: "screen.unreachable"
10722
11082
  });
10723
11083
  }
11084
+ walkScreen(screen, (l) => {
11085
+ if (l.kind !== "conditional") return;
11086
+ for (const c of l.cases) {
11087
+ if (decisionExprHasPredicate(c.expression)) continue;
11088
+ issues.push({
11089
+ stepId: screen.id,
11090
+ path: ["screens", screen.id, "layers", l.id, "cases", c.id],
11091
+ message: `conditional "${l.name ?? l.id}" branch "${c.name ?? c.id}" needs at least one rule before publishing`,
11092
+ code: "conditional.incomplete_cases"
11093
+ });
11094
+ }
11095
+ });
10724
11096
  }
10725
11097
  for (const sn of manifest.externalSurfaceNodes ?? []) {
10726
11098
  if (manifest.entryScreenId != null && !reachable.has(sn.id)) {
@@ -10803,11 +11175,13 @@ var collectFlowBuilderIssues = (manifest) => {
10803
11175
  const screenLabel = screen.name || screen.id;
10804
11176
  const mediaLayerIds = /* @__PURE__ */ new Set();
10805
11177
  const buttonLayerIds = /* @__PURE__ */ new Set();
11178
+ const carouselLayerIds = /* @__PURE__ */ new Set();
10806
11179
  const shellPlaybackId = screenBackgroundPlaybackId(screen.id);
10807
11180
  const shellFill = screen.containerStyle?.backgroundFill;
10808
11181
  const shellVideoFill = shellFill?.kind === "video" ? shellFill : void 0;
10809
11182
  walkScreen(screen, (l) => {
10810
11183
  if (l.kind === "button") buttonLayerIds.add(l.id);
11184
+ if (l.kind === "carousel") carouselLayerIds.add(l.id);
10811
11185
  });
10812
11186
  if (shellFill?.kind === "image" || shellFill?.kind === "video") {
10813
11187
  if (!shellFill.media?.mediaAssetId) {
@@ -11022,6 +11396,13 @@ var collectFlowBuilderIssues = (manifest) => {
11022
11396
  }
11023
11397
  }
11024
11398
  }
11399
+ if (l.kind === "button" && l.action.kind === "advance_carousel") {
11400
+ if (!carouselLayerIds.has(l.action.targetLayerId)) {
11401
+ issues.push(
11402
+ `Button "${l.name || l.id}" on screen "${screenLabel}" advance-carousel target "${l.action.targetLayerId}" must be a carousel layer on this screen.`
11403
+ );
11404
+ }
11405
+ }
11025
11406
  });
11026
11407
  if (oauthLoginLayerCount > 0 && inputCount > 0) {
11027
11408
  issues.push(
@@ -11926,6 +12307,7 @@ var walkLayers2 = (root, fn) => {
11926
12307
  fn(l, depth);
11927
12308
  if (l.kind === "stack") l.children.forEach((c) => visit(c, depth + 1));
11928
12309
  else if (l.kind === "carousel") l.slides.forEach((c) => visit(c, depth + 1));
12310
+ else if (l.kind === "conditional") l.children.forEach((c) => visit(c, depth + 1));
11929
12311
  else if (l.kind === "button") l.children.forEach((c) => visit(c, depth + 1));
11930
12312
  else if (l.kind === "back_button") l.children.forEach((c) => visit(c, depth + 1));
11931
12313
  else if (l.kind === "hyperlink") l.children.forEach((c) => visit(c, depth + 1));
@@ -12088,7 +12470,7 @@ var fixForBuilderMessage = (message) => {
12088
12470
  return "Set externalSurfaceNodes[].config.provider to a real provider (e.g. revenuecat), not unspecified.";
12089
12471
  }
12090
12472
  if (message.includes("Fallback edge")) {
12091
- return "Connect every external surface fallback to the next screen/decision/surface when the paywall dismisses or fails.";
12473
+ return "Connect every external surface fallback to the next screen/decision/surface when no specific outcome is mapped.";
12092
12474
  }
12093
12475
  return `Resolve builder publish rule: ${message}`;
12094
12476
  };
@@ -12102,7 +12484,7 @@ var collectIntegrationIssues = (manifest, integrations) => {
12102
12484
  }
12103
12485
  if (node.fallback == null) {
12104
12486
  issues.push(
12105
- `External surface "${node.name ?? node.id}" needs a connected Fallback edge \u2014 every paywall must route somewhere when no specific outcome is mapped.`
12487
+ `External surface "${node.name ?? node.id}" needs a connected Fallback edge \u2014 every external surface must route somewhere when no specific outcome is mapped.`
12106
12488
  );
12107
12489
  }
12108
12490
  if (node.config.provider === "revenuecat" && !integrations.revenuecat.enabled) {
@@ -12855,7 +13237,7 @@ var analyzeBackgrounds = (files) => {
12855
13237
  };
12856
13238
 
12857
13239
  // src/audit/analyzers/carouselAnalyzer.ts
12858
- var CAROUSEL_NO_DUPLICATE_FOOTER = "Carousels are swipe-only (optional pageControl dots). Do not add regions.footer or body buttons for in-pager paging. Use regions.footer only for CTAs that advance the next screen in the flow, or single-slide carousels.";
13240
+ var CAROUSEL_NO_DUPLICATE_FOOTER = 'Carousels swipe by default (optional pageControl dots). Do not add buttons that only mimic paging; when the source has an explicit Next control, give it action.kind "advance_carousel" targeting that carousel. Use regions.footer for CTAs that advance the next screen in the flow, or single-slide carousels.';
12859
13241
  var CAROUSEL_PATTERNS = [
12860
13242
  [
12861
13243
  /\binfoSteps\b/,
@@ -13949,7 +14331,7 @@ var analyzeRegions = (files) => {
13949
14331
  confidence: "high",
13950
14332
  file: file.path,
13951
14333
  evidence: `Footer/sticky CTA marker: ${footer}`,
13952
- recommendation: carouselPager ? "If this footer only advances in-screen pager pages (infoSteps/currentInfoStep), do not map it to regions.footer \u2014 use a swipe-only carousel layer. Use regions.footer only for CTAs that advance the next screen in the flow." : "Use regions.footer for sticky bottom CTAs instead of placing them at the end of body."
14334
+ recommendation: carouselPager ? 'If this footer only advances in-screen pager pages (infoSteps/currentInfoStep), either drop it (swipe already pages the carousel) or keep it as a button with action.kind "advance_carousel" targeting that carousel. Use regions.footer for CTAs that advance the next screen in the flow.' : "Use regions.footer for sticky bottom CTAs instead of placing them at the end of body."
13953
14335
  });
13954
14336
  }
13955
14337
  const body = hasAny(file.content, bodyPatterns);
@@ -14218,7 +14600,7 @@ var renderAuditMarkdown = (report) => {
14218
14600
  "- Use high-confidence region findings when choosing `regions.header`, `regions.body`, and `regions.footer`.",
14219
14601
  hasStyle ? "- Populate `manifest.theme` and per-layer `style` from style-token evidence. Set `style.color` on text for colored screens." : "- No style-token evidence found \u2014 ask the user for theme sources before using black-and-white defaults.",
14220
14602
  hasGradient ? "- Apply gradient evidence to `screen.containerStyle.backgroundFill.color` using `linear-gradient(...)` CSS strings." : "- Map screen-level background findings before adding generic body layers.",
14221
- hasCarousel ? '- **Carousel required:** emit `kind: "carousel"` with one slide stack per pager page. Swipe-only \u2014 no in-pager buttons. Bundle every slide asset.' : "- No carousel markers detected \u2014 still verify multi-slide routes manually.",
14603
+ hasCarousel ? '- **Carousel required:** emit `kind: "carousel"` with one slide stack per pager page. Swipe by default \u2014 only add a paging button when the source has an explicit Next control, using `action.kind: "advance_carousel"`. Bundle every slide asset.' : "- No carousel markers detected \u2014 still verify multi-slide routes manually.",
14222
14604
  hasFonts ? "- **Fonts required:** copy `.ttf`/`.otf`/`.woff`/`.woff2` under `assets/fonts/`, add `rheo-import.fonts.json`, set `manifest.theme.fontFamily`. **Never** put font files in `rheo-import.assets.json` (see `references/font-import.md`)." : "- If custom fonts appear later in review, bundle them in `rheo-import.fonts.json` only \u2014 never in `rheo-import.assets.json`.",
14223
14605
  hasChoiceStates ? "- **Choice selected state:** each option stack needs `style` (default) and `selectedStyle` (selected), including border/background/text colors." : "- Verify single_choice / multiple_choice option stacks for `selectedStyle` when source uses selected ternaries.",
14224
14606
  hasAnimation ? "- **Motion (intake Q6=yes + Grow+ plan):** apply `screen.animations`, `screen.stagger`, and conservative `restingMotion` from animation audit findings. Use `--suggest-animations` JSON for clip shapes. Omit unmapped springs/gestures." : "- **Motion:** if intake Q6=yes, re-scan entry scope; if Q6=no or plan lacks animations, omit all `animations`, `stagger`, and `restingMotion` fields.",
@@ -14403,7 +14785,12 @@ var ActionObjectSchema = external_exports.discriminatedUnion("kind", [
14403
14785
  blocked: external_exports.string().min(1)
14404
14786
  })
14405
14787
  }),
14406
- external_exports.object({ kind: external_exports.literal("play_media"), targetLayerIds: external_exports.array(external_exports.string().min(1)).min(1) })
14788
+ external_exports.object({ kind: external_exports.literal("play_media"), targetLayerIds: external_exports.array(external_exports.string().min(1)).min(1) }),
14789
+ external_exports.object({
14790
+ kind: external_exports.literal("advance_carousel"),
14791
+ targetLayerId: external_exports.string().min(1),
14792
+ onLast: external_exports.enum(["noop", "complete"]).optional()
14793
+ })
14407
14794
  ]);
14408
14795
  var ButtonActionSpecSchema = external_exports.union([
14409
14796
  external_exports.enum(["none", "continue", "skip", "end_flow", "go_back_one_screen", "request_app_review"]),
@@ -14652,16 +15039,19 @@ var ScreenSpecSchema = external_exports.object({
14652
15039
  var ExternalSurfaceSpecSchema = external_exports.object({
14653
15040
  id: external_exports.string().min(1).max(64),
14654
15041
  name: external_exports.string().min(1).max(80).optional(),
14655
- provider: external_exports.enum(["revenuecat", "unspecified"]),
15042
+ provider: external_exports.enum(["revenuecat", "headless", "unspecified"]),
14656
15043
  offeringId: external_exports.string().min(1).max(128).optional(),
14657
15044
  placementId: external_exports.string().min(1).max(128).optional(),
14658
15045
  presentation: external_exports.enum(["paywall", "paywall_if_needed"]).optional(),
15046
+ hostKey: external_exports.string().min(1).max(64).regex(/^[a-zA-Z][a-zA-Z0-9_]*$/).optional(),
14659
15047
  outcomes: external_exports.object({
14660
15048
  purchase_completed: external_exports.string().min(1).nullable().optional(),
14661
15049
  purchase_cancelled: external_exports.string().min(1).nullable().optional(),
14662
15050
  dismissed: external_exports.string().min(1).nullable().optional(),
14663
15051
  failed: external_exports.string().min(1).nullable().optional(),
14664
- restore_completed: external_exports.string().min(1).nullable().optional()
15052
+ restore_completed: external_exports.string().min(1).nullable().optional(),
15053
+ completed: external_exports.string().min(1).nullable().optional(),
15054
+ back: external_exports.string().min(1).nullable().optional()
14665
15055
  }).optional(),
14666
15056
  fallback: external_exports.string().min(1).nullable()
14667
15057
  });
@@ -15166,6 +15556,9 @@ var buildExternalSurface = (surface) => {
15166
15556
  ...surface.offeringId ? { offeringId: surface.offeringId } : {},
15167
15557
  ...surface.placementId ? { placementId: surface.placementId } : {},
15168
15558
  ...surface.presentation ? { presentation: surface.presentation } : {}
15559
+ } : surface.provider === "headless" ? {
15560
+ provider: "headless",
15561
+ ...surface.hostKey ? { hostKey: surface.hostKey } : {}
15169
15562
  } : { provider: "unspecified" };
15170
15563
  const outcomes = {};
15171
15564
  for (const [key, value] of Object.entries(surface.outcomes ?? {})) {