@getrheo/rheo-skill 2.3.0 → 2.4.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;
@@ -7890,115 +8184,52 @@ var ScreenBackgroundImageFillSchema = external_exports.object({
7890
8184
  });
7891
8185
  var ScreenBackgroundVideoFillSchema = external_exports.object({
7892
8186
  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 })
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
7981
8198
  ]);
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
- );
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,6 +8370,57 @@ 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
8425
  var NORMALIZED_SURFACE_OUTCOMES = [
8167
8426
  "purchase_completed",
@@ -8292,6 +8551,8 @@ var migrateLayerInPlace = (layer) => {
8292
8551
  for (const c of l.children) migrateLayerInPlace(c);
8293
8552
  } else if (l.kind === "carousel" && Array.isArray(l.slides)) {
8294
8553
  for (const s of l.slides) migrateLayerInPlace(s);
8554
+ } else if (l.kind === "conditional" && Array.isArray(l.children)) {
8555
+ for (const c of l.children) migrateLayerInPlace(c);
8295
8556
  } else if (l.kind === "button" && Array.isArray(l.children)) {
8296
8557
  for (const c of l.children) migrateLayerInPlace(c);
8297
8558
  } else if (l.kind === "back_button" && Array.isArray(l.children)) {
@@ -8493,8 +8754,8 @@ var refineManifestGraph = (manifest, ctx, jumpTargets) => {
8493
8754
  };
8494
8755
  var refineManifestScreens = (manifest, ctx, jumpTargets, screenIds, allFieldKeys) => {
8495
8756
  const layerIds = /* @__PURE__ */ new Set();
8757
+ const sdkAllow = new Set(manifest.sdkAttributeKeys);
8496
8758
  manifest.screens.forEach((screen, screenIdx) => {
8497
- let inputCount = 0;
8498
8759
  const layerIdsForScreen = /* @__PURE__ */ new Set();
8499
8760
  walkScreenLayers(screen, (l) => {
8500
8761
  layerIdsForScreen.add(l.id);
@@ -8509,7 +8770,6 @@ var refineManifestScreens = (manifest, ctx, jumpTargets, screenIds, allFieldKeys
8509
8770
  }
8510
8771
  layerIds.add(l.id);
8511
8772
  if (isInputLayer2(l)) {
8512
- inputCount += 1;
8513
8773
  if (allFieldKeys.has(l.fieldKey)) {
8514
8774
  ctx.addIssue({
8515
8775
  code: external_exports.ZodIssueCode.custom,
@@ -8534,10 +8794,18 @@ var refineManifestScreens = (manifest, ctx, jumpTargets, screenIds, allFieldKeys
8534
8794
  if (!allFieldKeys.has(fk)) allFieldKeys.set(fk, screen.id);
8535
8795
  }
8536
8796
  });
8537
- if (inputCount > 1) {
8797
+ const inputsOnPath = maxMatchesOnScreenActivePath(screen, isInputLayer2);
8798
+ if (inputsOnPath > 1) {
8799
+ ctx.addIssue({
8800
+ code: external_exports.ZodIssueCode.custom,
8801
+ message: `screen "${screen.id}" can show ${inputsOnPath} input layers at once (max 1 allowed)`,
8802
+ path: ["screens", screenIdx, "regions"]
8803
+ });
8804
+ }
8805
+ for (const v of conditionalFieldScopeViolations(screen)) {
8538
8806
  ctx.addIssue({
8539
8807
  code: external_exports.ZodIssueCode.custom,
8540
- message: `screen "${screen.id}" has ${inputCount} input layers (max 1 allowed)`,
8808
+ message: `conditional "${v.conditionalId}" case "${v.caseId}" reads fieldKey "${v.fieldKey}" that is answered at or after it on the same screen`,
8541
8809
  path: ["screens", screenIdx, "regions"]
8542
8810
  });
8543
8811
  }
@@ -8606,6 +8874,21 @@ var refineManifestScreens = (manifest, ctx, jumpTargets, screenIds, allFieldKeys
8606
8874
  }
8607
8875
  }
8608
8876
  }
8877
+ if (l.kind === "conditional") {
8878
+ validateConditionalCasesAndBindings(l, ctx);
8879
+ for (const c of l.cases) {
8880
+ for (const sk of collectDecisionSdkKeys(c.expression)) {
8881
+ if (isReservedSdkKey(sk)) continue;
8882
+ if (!sdkAllow.has(sk)) {
8883
+ ctx.addIssue({
8884
+ code: external_exports.ZodIssueCode.custom,
8885
+ message: `conditional "${l.id}" case "${c.id}" references sdk key "${sk}" not in sdkAttributeKeys`,
8886
+ path: ["screens", screenIdx]
8887
+ });
8888
+ }
8889
+ }
8890
+ }
8891
+ }
8609
8892
  if (l.kind === "button" && l.action.kind === "go_to_step") {
8610
8893
  if (!jumpTargets.has(l.action.screenId)) {
8611
8894
  ctx.addIssue({
@@ -8757,6 +9040,22 @@ var refineFlowManifest = (manifest, ctx) => {
8757
9040
  }
8758
9041
  }
8759
9042
  });
9043
+ manifest.screens.forEach((screen, screenIdx) => {
9044
+ walkScreenLayers(screen, (l) => {
9045
+ if (l.kind !== "conditional") return;
9046
+ for (const c of l.cases) {
9047
+ for (const fk of collectDecisionFieldKeys2(c.expression)) {
9048
+ if (!allFieldKeys.has(fk)) {
9049
+ ctx.addIssue({
9050
+ code: external_exports.ZodIssueCode.custom,
9051
+ message: `conditional "${l.id}" case "${c.id}" references unknown fieldKey "${fk}"`,
9052
+ path: ["screens", screenIdx, "regions"]
9053
+ });
9054
+ }
9055
+ }
9056
+ }
9057
+ });
9058
+ });
8760
9059
  if (manifest.locales.length > 0 && !manifest.locales.includes(manifest.defaultLocale)) {
8761
9060
  ctx.addIssue({
8762
9061
  code: external_exports.ZodIssueCode.custom,
@@ -8839,7 +9138,10 @@ var FontStyleSchema = external_exports.object({
8839
9138
  label: external_exports.string().max(40).optional(),
8840
9139
  /** MediaAsset id of the uploaded font file. */
8841
9140
  mediaAssetId: external_exports.string().uuid().optional(),
8842
- /** Public URL of the uploaded font file (denormalized for SDK consumption). */
9141
+ /**
9142
+ * Access URL for the uploaded font file (denormalized for SDK consumption).
9143
+ * Freshly signed on SDK resolve and dashboard app reads; do not persist as long-lived.
9144
+ */
8843
9145
  url: external_exports.string().url().optional(),
8844
9146
  /** Original filename — useful for display. */
8845
9147
  filename: external_exports.string().max(200).optional()
@@ -9450,6 +9752,8 @@ var OsPermissionOutcomesSchema4 = external_exports.object({
9450
9752
  }).strict();
9451
9753
  var APP_REVIEW_OUTCOMES4 = ["not_shown", "dismissed"];
9452
9754
  external_exports.enum(APP_REVIEW_OUTCOMES4);
9755
+ var CAROUSEL_ADVANCE_ON_LAST4 = ["noop", "complete"];
9756
+ var CarouselAdvanceOnLastSchema4 = external_exports.enum(CAROUSEL_ADVANCE_ON_LAST4);
9453
9757
  var ButtonActionSchema4 = external_exports.discriminatedUnion("kind", [
9454
9758
  external_exports.object({ kind: external_exports.literal("none") }),
9455
9759
  external_exports.object({ kind: external_exports.literal("continue") }),
@@ -9469,7 +9773,12 @@ var ButtonActionSchema4 = external_exports.discriminatedUnion("kind", [
9469
9773
  kind: external_exports.literal("play_media"),
9470
9774
  targetLayerIds: external_exports.array(external_exports.string().min(1)).min(1)
9471
9775
  }),
9472
- external_exports.object({ kind: external_exports.literal("request_app_review") })
9776
+ external_exports.object({ kind: external_exports.literal("request_app_review") }),
9777
+ external_exports.object({
9778
+ kind: external_exports.literal("advance_carousel"),
9779
+ targetLayerId: external_exports.string().min(1),
9780
+ onLast: CarouselAdvanceOnLastSchema4.optional()
9781
+ })
9473
9782
  ]);
9474
9783
  var TEXT_INPUT_TYPES4 = ["plain", "email", "phone", "url", "number", "multiline"];
9475
9784
  var TextInputTypeSchema4 = external_exports.enum(TEXT_INPUT_TYPES4);
@@ -10212,6 +10521,83 @@ var CarouselLayerSchema4 = external_exports.object({
10212
10521
  styleBreakpoints: CommonStyleBreakpointsSchema4,
10213
10522
  carouselLayoutBreakpoints: CarouselLayoutBreakpointsSchema4
10214
10523
  });
10524
+ var DecisionBuiltinNameSchema4 = external_exports.enum(["locale", "platform"]);
10525
+ var DecisionVariableRefSchema4 = external_exports.discriminatedUnion("kind", [
10526
+ external_exports.object({ kind: external_exports.literal("builtin"), name: DecisionBuiltinNameSchema4 }),
10527
+ external_exports.object({ kind: external_exports.literal("sdk"), key: external_exports.string().min(1).max(128) }),
10528
+ external_exports.object({ kind: external_exports.literal("field"), fieldKey: external_exports.string().min(1).max(128) })
10529
+ ]);
10530
+ var DecisionStringPredicateSchema4 = external_exports.discriminatedUnion("op", [
10531
+ external_exports.object({ op: external_exports.literal("eq"), value: external_exports.string() }),
10532
+ external_exports.object({ op: external_exports.literal("neq"), value: external_exports.string() }),
10533
+ external_exports.object({ op: external_exports.literal("contains"), value: external_exports.string() })
10534
+ ]);
10535
+ var DecisionNumberPredicateSchema4 = external_exports.discriminatedUnion("op", [
10536
+ external_exports.object({ op: external_exports.literal("eq"), value: external_exports.number() }),
10537
+ external_exports.object({ op: external_exports.literal("neq"), value: external_exports.number() }),
10538
+ external_exports.object({ op: external_exports.literal("lt"), value: external_exports.number() }),
10539
+ external_exports.object({ op: external_exports.literal("lte"), value: external_exports.number() }),
10540
+ external_exports.object({ op: external_exports.literal("gt"), value: external_exports.number() }),
10541
+ external_exports.object({ op: external_exports.literal("gte"), value: external_exports.number() })
10542
+ ]);
10543
+ var DecisionChoicePredicateSchema4 = external_exports.discriminatedUnion("op", [
10544
+ external_exports.object({ op: external_exports.literal("eq"), optionId: external_exports.string().min(1) }),
10545
+ external_exports.object({ op: external_exports.literal("one_of"), optionIds: external_exports.array(external_exports.string().min(1)).min(1) })
10546
+ ]);
10547
+ var DecisionMultiPredicateSchema4 = external_exports.discriminatedUnion("op", [
10548
+ external_exports.object({
10549
+ op: external_exports.literal("intersects"),
10550
+ optionIds: external_exports.array(external_exports.string().min(1)).min(1)
10551
+ }),
10552
+ external_exports.object({
10553
+ op: external_exports.literal("contains_all"),
10554
+ optionIds: external_exports.array(external_exports.string().min(1)).min(1)
10555
+ }),
10556
+ external_exports.object({
10557
+ op: external_exports.literal("subset_of"),
10558
+ optionIds: external_exports.array(external_exports.string().min(1)).min(1)
10559
+ })
10560
+ ]);
10561
+ var DecisionBooleanPredicateSchema4 = external_exports.discriminatedUnion("op", [
10562
+ external_exports.object({ op: external_exports.literal("eq"), value: external_exports.boolean() }),
10563
+ external_exports.object({ op: external_exports.literal("neq"), value: external_exports.boolean() })
10564
+ ]);
10565
+ var DecisionPredicatePayloadSchema4 = external_exports.discriminatedUnion("type", [
10566
+ external_exports.object({ type: external_exports.literal("string"), pred: DecisionStringPredicateSchema4 }),
10567
+ external_exports.object({ type: external_exports.literal("number"), pred: DecisionNumberPredicateSchema4 }),
10568
+ external_exports.object({ type: external_exports.literal("boolean"), pred: DecisionBooleanPredicateSchema4 }),
10569
+ external_exports.object({ type: external_exports.literal("choice"), pred: DecisionChoicePredicateSchema4 }),
10570
+ external_exports.object({ type: external_exports.literal("multi"), pred: DecisionMultiPredicateSchema4 })
10571
+ ]);
10572
+ var DecisionExprSchema4 = external_exports.lazy(
10573
+ () => external_exports.discriminatedUnion("kind", [
10574
+ external_exports.object({ kind: external_exports.literal("empty") }),
10575
+ external_exports.object({
10576
+ kind: external_exports.literal("group"),
10577
+ op: external_exports.enum(["and", "or"]),
10578
+ children: external_exports.array(DecisionExprSchema4).min(1)
10579
+ }),
10580
+ external_exports.object({
10581
+ kind: external_exports.literal("predicate"),
10582
+ variable: DecisionVariableRefSchema4,
10583
+ predicate: DecisionPredicatePayloadSchema4
10584
+ })
10585
+ ])
10586
+ );
10587
+ var CONDITIONAL_MAX_CASES4 = 16;
10588
+ var ConditionalCaseSchema4 = external_exports.object({
10589
+ id: external_exports.string().min(1).max(80),
10590
+ name: external_exports.string().min(1).max(80).optional(),
10591
+ expression: DecisionExprSchema4,
10592
+ rootLayerId: LayerIdSchema4
10593
+ });
10594
+ var ConditionalLayerSchema4 = external_exports.object({
10595
+ ...baseLayerShape4,
10596
+ kind: external_exports.literal("conditional"),
10597
+ cases: external_exports.array(ConditionalCaseSchema4).min(1).max(CONDITIONAL_MAX_CASES4),
10598
+ elseRootLayerId: LayerIdSchema4,
10599
+ children: external_exports.lazy(() => external_exports.array(StackLayerSchema4).min(2))
10600
+ });
10215
10601
  layerSchemaStore4.schema = external_exports.lazy(
10216
10602
  () => external_exports.union([
10217
10603
  StackLayerSchema4,
@@ -10238,7 +10624,8 @@ layerSchemaStore4.schema = external_exports.lazy(
10238
10624
  EmailPasswordAuthLayerSchema4,
10239
10625
  EmailPasswordFieldLayerSchema4,
10240
10626
  EmailPasswordSubmitLayerSchema4,
10241
- CarouselLayerSchema4
10627
+ CarouselLayerSchema4,
10628
+ ConditionalLayerSchema4
10242
10629
  ])
10243
10630
  );
10244
10631
  var ScreenBackgroundFitSchema2 = external_exports.enum(["cover", "contain", "fill"]);
@@ -10304,74 +10691,11 @@ var ExternalSurfaceJumpIdSchema24 = external_exports.string().min(1).max(64).reg
10304
10691
  var EXTERNAL_SURFACE_NO_NEXT3 = "__onb_surface_no_next__";
10305
10692
  var ExternalSurfaceTerminalTargetSchema3 = external_exports.literal(EXTERNAL_SURFACE_NO_NEXT3);
10306
10693
  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
10694
  var DecisionCaseSchema3 = external_exports.object({
10371
10695
  id: external_exports.string().min(1).max(80),
10372
10696
  /** Display label in the editor (e.g. “Engaged users”). */
10373
10697
  name: external_exports.string().min(1).max(80).optional(),
10374
- expression: DecisionExprSchema3,
10698
+ expression: DecisionExprSchema4,
10375
10699
  next: FlowJumpTargetSchema3
10376
10700
  });
10377
10701
  external_exports.object({
@@ -10526,6 +10850,7 @@ var walkLayers = (root, fn) => {
10526
10850
  fn(l, depth);
10527
10851
  if (l.kind === "stack") l.children.forEach((c) => visit(c, depth + 1));
10528
10852
  else if (l.kind === "carousel") l.slides.forEach((c) => visit(c, depth + 1));
10853
+ else if (l.kind === "conditional") l.children.forEach((c) => visit(c, depth + 1));
10529
10854
  else if (l.kind === "button") l.children.forEach((c) => visit(c, depth + 1));
10530
10855
  else if (l.kind === "back_button") l.children.forEach((c) => visit(c, depth + 1));
10531
10856
  else if (l.kind === "hyperlink") l.children.forEach((c) => visit(c, depth + 1));
@@ -10721,6 +11046,18 @@ var validatePublishable = (manifest) => {
10721
11046
  code: "screen.unreachable"
10722
11047
  });
10723
11048
  }
11049
+ walkScreen(screen, (l) => {
11050
+ if (l.kind !== "conditional") return;
11051
+ for (const c of l.cases) {
11052
+ if (decisionExprHasPredicate(c.expression)) continue;
11053
+ issues.push({
11054
+ stepId: screen.id,
11055
+ path: ["screens", screen.id, "layers", l.id, "cases", c.id],
11056
+ message: `conditional "${l.name ?? l.id}" branch "${c.name ?? c.id}" needs at least one rule before publishing`,
11057
+ code: "conditional.incomplete_cases"
11058
+ });
11059
+ }
11060
+ });
10724
11061
  }
10725
11062
  for (const sn of manifest.externalSurfaceNodes ?? []) {
10726
11063
  if (manifest.entryScreenId != null && !reachable.has(sn.id)) {
@@ -10803,11 +11140,13 @@ var collectFlowBuilderIssues = (manifest) => {
10803
11140
  const screenLabel = screen.name || screen.id;
10804
11141
  const mediaLayerIds = /* @__PURE__ */ new Set();
10805
11142
  const buttonLayerIds = /* @__PURE__ */ new Set();
11143
+ const carouselLayerIds = /* @__PURE__ */ new Set();
10806
11144
  const shellPlaybackId = screenBackgroundPlaybackId(screen.id);
10807
11145
  const shellFill = screen.containerStyle?.backgroundFill;
10808
11146
  const shellVideoFill = shellFill?.kind === "video" ? shellFill : void 0;
10809
11147
  walkScreen(screen, (l) => {
10810
11148
  if (l.kind === "button") buttonLayerIds.add(l.id);
11149
+ if (l.kind === "carousel") carouselLayerIds.add(l.id);
10811
11150
  });
10812
11151
  if (shellFill?.kind === "image" || shellFill?.kind === "video") {
10813
11152
  if (!shellFill.media?.mediaAssetId) {
@@ -11022,6 +11361,13 @@ var collectFlowBuilderIssues = (manifest) => {
11022
11361
  }
11023
11362
  }
11024
11363
  }
11364
+ if (l.kind === "button" && l.action.kind === "advance_carousel") {
11365
+ if (!carouselLayerIds.has(l.action.targetLayerId)) {
11366
+ issues.push(
11367
+ `Button "${l.name || l.id}" on screen "${screenLabel}" advance-carousel target "${l.action.targetLayerId}" must be a carousel layer on this screen.`
11368
+ );
11369
+ }
11370
+ }
11025
11371
  });
11026
11372
  if (oauthLoginLayerCount > 0 && inputCount > 0) {
11027
11373
  issues.push(
@@ -11926,6 +12272,7 @@ var walkLayers2 = (root, fn) => {
11926
12272
  fn(l, depth);
11927
12273
  if (l.kind === "stack") l.children.forEach((c) => visit(c, depth + 1));
11928
12274
  else if (l.kind === "carousel") l.slides.forEach((c) => visit(c, depth + 1));
12275
+ else if (l.kind === "conditional") l.children.forEach((c) => visit(c, depth + 1));
11929
12276
  else if (l.kind === "button") l.children.forEach((c) => visit(c, depth + 1));
11930
12277
  else if (l.kind === "back_button") l.children.forEach((c) => visit(c, depth + 1));
11931
12278
  else if (l.kind === "hyperlink") l.children.forEach((c) => visit(c, depth + 1));
@@ -12855,7 +13202,7 @@ var analyzeBackgrounds = (files) => {
12855
13202
  };
12856
13203
 
12857
13204
  // 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.";
13205
+ 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
13206
  var CAROUSEL_PATTERNS = [
12860
13207
  [
12861
13208
  /\binfoSteps\b/,
@@ -13949,7 +14296,7 @@ var analyzeRegions = (files) => {
13949
14296
  confidence: "high",
13950
14297
  file: file.path,
13951
14298
  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."
14299
+ 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
14300
  });
13954
14301
  }
13955
14302
  const body = hasAny(file.content, bodyPatterns);
@@ -14218,7 +14565,7 @@ var renderAuditMarkdown = (report) => {
14218
14565
  "- Use high-confidence region findings when choosing `regions.header`, `regions.body`, and `regions.footer`.",
14219
14566
  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
14567
  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.",
14568
+ 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
14569
  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
14570
  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
14571
  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 +14750,12 @@ var ActionObjectSchema = external_exports.discriminatedUnion("kind", [
14403
14750
  blocked: external_exports.string().min(1)
14404
14751
  })
14405
14752
  }),
14406
- external_exports.object({ kind: external_exports.literal("play_media"), targetLayerIds: external_exports.array(external_exports.string().min(1)).min(1) })
14753
+ external_exports.object({ kind: external_exports.literal("play_media"), targetLayerIds: external_exports.array(external_exports.string().min(1)).min(1) }),
14754
+ external_exports.object({
14755
+ kind: external_exports.literal("advance_carousel"),
14756
+ targetLayerId: external_exports.string().min(1),
14757
+ onLast: external_exports.enum(["noop", "complete"]).optional()
14758
+ })
14407
14759
  ]);
14408
14760
  var ButtonActionSpecSchema = external_exports.union([
14409
14761
  external_exports.enum(["none", "continue", "skip", "end_flow", "go_back_one_screen", "request_app_review"]),