@wix/himalaya-cli 0.1496.0 → 0.1497.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/attendance-classifier.d.ts +37 -0
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/catalog-pricing-contract.d.ts +1 -1
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/index.d.ts +2 -1
  4. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/wix-payments-contract.d.ts +11 -3
  5. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/apple-iap-contract.d.ts +27 -3
  6. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/commerce-contract.d.ts +1 -0
  7. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/iap-verticals/attendance.d.ts +10 -0
  8. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/iap-verticals/index.d.ts +1 -0
  9. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/index.d.ts +1 -1
  10. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/events/src/index.d.ts +33 -2
  11. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/iap-checkout.mjs +346 -26
  12. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/iap.mjs +132 -3
  13. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/screens.mjs +366 -48
  14. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-events.mjs +5 -0
  15. package/dist/cli.mjs +816 -666
  16. package/guides/iap-products.md +7 -1
  17. package/guides/sdk-reference.json +376 -27
  18. package/package.json +2 -2
  19. package/templates/beauty-salon/dev/index.ts +394 -0
  20. package/templates/beauty-salon/tier5-src/_shared/iap-attendance-form.ts +106 -0
  21. package/templates/beauty-salon/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  22. package/templates/beauty-salon/tier5-src/_shared/iap-attendance.ts +38 -0
  23. package/templates/beauty-salon/tier5-src/himi-booking-time/index.ts +52 -7
  24. package/templates/branded-lite/dev/index.ts +1073 -284
  25. package/templates/branded-lite/tier5-src/_shared/iap-attendance-form.ts +106 -0
  26. package/templates/branded-lite/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  27. package/templates/branded-lite/tier5-src/_shared/iap-attendance.ts +38 -0
  28. package/templates/branded-lite/tier5-src/himi-booking-time/index.ts +52 -7
  29. package/templates/branded-lite/tier5-src/himi-events-detail/index.ts +112 -21
  30. package/templates/community-club/dev/index.ts +397 -2
  31. package/templates/community-club/tier5-src/_shared/iap-attendance-form.ts +106 -0
  32. package/templates/community-club/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  33. package/templates/community-club/tier5-src/_shared/iap-attendance.ts +38 -0
  34. package/templates/community-club/tier5-src/himi-events-detail/index.ts +112 -21
  35. package/templates/events-meetups/dev/index.ts +397 -2
  36. package/templates/events-meetups/tier5-src/_shared/iap-attendance-form.ts +106 -0
  37. package/templates/events-meetups/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  38. package/templates/events-meetups/tier5-src/_shared/iap-attendance.ts +38 -0
  39. package/templates/events-meetups/tier5-src/himi-events-detail/index.ts +112 -21
  40. package/templates/gym-fitness/dev/index.ts +828 -39
  41. package/templates/gym-fitness/tier5-src/_shared/iap-attendance-form.ts +106 -0
  42. package/templates/gym-fitness/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  43. package/templates/gym-fitness/tier5-src/_shared/iap-attendance.ts +38 -0
  44. package/templates/gym-fitness/tier5-src/himi-booking-time/index.ts +52 -7
  45. package/templates/gym-fitness/tier5-src/himi-events-detail/index.ts +112 -21
  46. package/templates/nonprofit-cause/dev/index.ts +397 -2
  47. package/templates/nonprofit-cause/tier5-src/_shared/iap-attendance-form.ts +106 -0
  48. package/templates/nonprofit-cause/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  49. package/templates/nonprofit-cause/tier5-src/_shared/iap-attendance.ts +38 -0
  50. package/templates/nonprofit-cause/tier5-src/himi-events-detail/index.ts +112 -21
  51. package/templates/podcast-creator/dev/index.ts +397 -2
  52. package/templates/podcast-creator/tier5-src/_shared/iap-attendance-form.ts +106 -0
  53. package/templates/podcast-creator/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  54. package/templates/podcast-creator/tier5-src/_shared/iap-attendance.ts +38 -0
  55. package/templates/podcast-creator/tier5-src/himi-events-detail/index.ts +112 -21
  56. package/templates/portfolio-creative/dev/index.ts +397 -2
  57. package/templates/portfolio-creative/tier5-src/_shared/iap-attendance-form.ts +106 -0
  58. package/templates/portfolio-creative/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  59. package/templates/portfolio-creative/tier5-src/_shared/iap-attendance.ts +38 -0
  60. package/templates/portfolio-creative/tier5-src/himi-events-detail/index.ts +112 -21
  61. package/templates/restaurant/dev/index.ts +397 -2
  62. package/templates/restaurant/tier5-src/_shared/iap-attendance-form.ts +106 -0
  63. package/templates/restaurant/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  64. package/templates/restaurant/tier5-src/_shared/iap-attendance.ts +38 -0
  65. package/templates/restaurant/tier5-src/himi-events-detail/index.ts +112 -21
  66. package/templates/yoga-studio/dev/index.ts +828 -39
  67. package/templates/yoga-studio/tier5-src/_shared/iap-attendance-form.ts +106 -0
  68. package/templates/yoga-studio/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
  69. package/templates/yoga-studio/tier5-src/_shared/iap-attendance.ts +38 -0
  70. package/templates/yoga-studio/tier5-src/himi-booking-time/index.ts +52 -7
  71. package/templates/yoga-studio/tier5-src/himi-events-detail/index.ts +112 -21
@@ -22246,6 +22246,398 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
22246
22246
  "hiddenPath": "$service:himiEventDetail.hideTierPicker"
22247
22247
  }
22248
22248
  },
22249
+ {
22250
+ "id": "",
22251
+ "body": {
22252
+ "package": "himalaya",
22253
+ "type": "VStack",
22254
+ "props": {
22255
+ "spacing": 12,
22256
+ "alignment": "leading",
22257
+ "children": [
22258
+ {
22259
+ "id": "",
22260
+ "body": {
22261
+ "package": "himalaya",
22262
+ "type": "Text",
22263
+ "props": {
22264
+ "text": "$service:himiEventDetail.iapPrice",
22265
+ "style": "bodyEmphasis",
22266
+ "collapseWhenEmpty": true
22267
+ }
22268
+ }
22269
+ },
22270
+ {
22271
+ "id": "himi_event.apple.form",
22272
+ "body": {
22273
+ "package": "himalaya",
22274
+ "type": "Grid",
22275
+ "props": {
22276
+ "columns": 1,
22277
+ "spacing": 12,
22278
+ "itemsPath": "$service:himiEventDetail.iapFields",
22279
+ "items": [
22280
+ {
22281
+ "id": "",
22282
+ "body": {
22283
+ "package": "himalaya",
22284
+ "type": "VStack",
22285
+ "props": {
22286
+ "spacing": 8,
22287
+ "alignment": "leading",
22288
+ "children": [
22289
+ {
22290
+ "id": "",
22291
+ "body": {
22292
+ "package": "himalaya",
22293
+ "type": "Text",
22294
+ "props": {
22295
+ "text": "$item.sectionLabel",
22296
+ "style": "bodyEmphasis",
22297
+ "collapseWhenEmpty": true
22298
+ }
22299
+ }
22300
+ },
22301
+ {
22302
+ "id": "",
22303
+ "body": {
22304
+ "package": "himalaya",
22305
+ "type": "Text",
22306
+ "props": {
22307
+ "text": "$item.label",
22308
+ "style": "footnote"
22309
+ }
22310
+ }
22311
+ },
22312
+ {
22313
+ "id": "himi_event.apple.input.$item.id",
22314
+ "body": {
22315
+ "package": "himalaya",
22316
+ "type": "FragmentSlot",
22317
+ "props": {
22318
+ "casePath": "$item.kind",
22319
+ "defaultCase": "text",
22320
+ "cases": [
22321
+ {
22322
+ "id": "text",
22323
+ "content": {
22324
+ "id": "himi_event.apple.field.text.$item.id",
22325
+ "body": {
22326
+ "package": "himalaya",
22327
+ "type": "TextField",
22328
+ "props": {
22329
+ "placeholder": "$item.inputLabel",
22330
+ "value": "$item.value",
22331
+ "onChange": {
22332
+ "actionId": "tier5.himiEventDetail.setIapField",
22333
+ "params": {
22334
+ "id": "$item.fieldId"
22335
+ }
22336
+ },
22337
+ "validation": {},
22338
+ "errorText": "$item.error",
22339
+ "autoCapitalization": "words"
22340
+ }
22341
+ }
22342
+ }
22343
+ },
22344
+ {
22345
+ "id": "requiredText",
22346
+ "content": {
22347
+ "id": "himi_event.apple.field.requiredText.$item.id",
22348
+ "body": {
22349
+ "package": "himalaya",
22350
+ "type": "TextField",
22351
+ "props": {
22352
+ "placeholder": "$item.inputLabel",
22353
+ "value": "$item.value",
22354
+ "onChange": {
22355
+ "actionId": "tier5.himiEventDetail.setIapField",
22356
+ "params": {
22357
+ "id": "$item.fieldId"
22358
+ }
22359
+ },
22360
+ "validation": {
22361
+ "required": true
22362
+ },
22363
+ "errorText": "$item.error",
22364
+ "autoCapitalization": "words"
22365
+ }
22366
+ }
22367
+ }
22368
+ },
22369
+ {
22370
+ "id": "email",
22371
+ "content": {
22372
+ "id": "himi_event.apple.field.email.$item.id",
22373
+ "body": {
22374
+ "package": "himalaya",
22375
+ "type": "TextField",
22376
+ "props": {
22377
+ "placeholder": "$item.inputLabel",
22378
+ "value": "$item.value",
22379
+ "onChange": {
22380
+ "actionId": "tier5.himiEventDetail.setIapField",
22381
+ "params": {
22382
+ "id": "$item.fieldId"
22383
+ }
22384
+ },
22385
+ "validation": {
22386
+ "required": true,
22387
+ "type": "email"
22388
+ },
22389
+ "errorText": "$item.error",
22390
+ "autoCapitalization": "none"
22391
+ }
22392
+ }
22393
+ }
22394
+ },
22395
+ {
22396
+ "id": "number",
22397
+ "content": {
22398
+ "id": "himi_event.apple.field.number.$item.id",
22399
+ "body": {
22400
+ "package": "himalaya",
22401
+ "type": "TextField",
22402
+ "props": {
22403
+ "placeholder": "$item.inputLabel",
22404
+ "value": "$item.value",
22405
+ "onChange": {
22406
+ "actionId": "tier5.himiEventDetail.setIapField",
22407
+ "params": {
22408
+ "id": "$item.fieldId"
22409
+ }
22410
+ },
22411
+ "validation": {
22412
+ "type": "number"
22413
+ },
22414
+ "errorText": "$item.error",
22415
+ "autoCapitalization": "words"
22416
+ }
22417
+ }
22418
+ }
22419
+ },
22420
+ {
22421
+ "id": "choice",
22422
+ "content": {
22423
+ "id": "",
22424
+ "body": {
22425
+ "package": "himalaya",
22426
+ "type": "VStack",
22427
+ "props": {
22428
+ "spacing": 4,
22429
+ "children": [
22430
+ {
22431
+ "id": "himi_event.apple.options.choice",
22432
+ "body": {
22433
+ "package": "himalaya",
22434
+ "type": "Grid",
22435
+ "props": {
22436
+ "columns": 1,
22437
+ "spacing": 8,
22438
+ "itemsPath": "$item.options",
22439
+ "items": [
22440
+ {
22441
+ "id": "himi_event.apple.option.choice.$item.fieldId.$item.id",
22442
+ "body": {
22443
+ "package": "himalaya",
22444
+ "type": "Button",
22445
+ "props": {
22446
+ "title": "$item.displayLabel",
22447
+ "style": "secondary",
22448
+ "fullWidth": true,
22449
+ "action": {
22450
+ "actionId": "tier5.himiEventDetail.setIapField",
22451
+ "params": {
22452
+ "id": "$item.fieldId",
22453
+ "option": "$item.id"
22454
+ }
22455
+ }
22456
+ }
22457
+ }
22458
+ }
22459
+ ]
22460
+ }
22461
+ }
22462
+ },
22463
+ {
22464
+ "id": "",
22465
+ "body": {
22466
+ "package": "himalaya",
22467
+ "type": "FieldError",
22468
+ "props": {
22469
+ "text": "$item.error"
22470
+ }
22471
+ },
22472
+ "modifiers": {
22473
+ "hiddenPath": "$item.errorHidden"
22474
+ }
22475
+ }
22476
+ ]
22477
+ }
22478
+ }
22479
+ }
22480
+ },
22481
+ {
22482
+ "id": "multiple",
22483
+ "content": {
22484
+ "id": "",
22485
+ "body": {
22486
+ "package": "himalaya",
22487
+ "type": "VStack",
22488
+ "props": {
22489
+ "spacing": 4,
22490
+ "children": [
22491
+ {
22492
+ "id": "himi_event.apple.options.multiple",
22493
+ "body": {
22494
+ "package": "himalaya",
22495
+ "type": "Grid",
22496
+ "props": {
22497
+ "columns": 1,
22498
+ "spacing": 8,
22499
+ "itemsPath": "$item.options",
22500
+ "items": [
22501
+ {
22502
+ "id": "himi_event.apple.option.multiple.$item.fieldId.$item.id",
22503
+ "body": {
22504
+ "package": "himalaya",
22505
+ "type": "Button",
22506
+ "props": {
22507
+ "title": "$item.displayLabel",
22508
+ "style": "secondary",
22509
+ "fullWidth": true,
22510
+ "action": {
22511
+ "actionId": "tier5.himiEventDetail.setIapField",
22512
+ "params": {
22513
+ "id": "$item.fieldId",
22514
+ "option": "$item.id"
22515
+ }
22516
+ }
22517
+ }
22518
+ }
22519
+ }
22520
+ ]
22521
+ }
22522
+ }
22523
+ },
22524
+ {
22525
+ "id": "",
22526
+ "body": {
22527
+ "package": "himalaya",
22528
+ "type": "FieldError",
22529
+ "props": {
22530
+ "text": "$item.error"
22531
+ }
22532
+ },
22533
+ "modifiers": {
22534
+ "hiddenPath": "$item.errorHidden"
22535
+ }
22536
+ }
22537
+ ]
22538
+ }
22539
+ }
22540
+ }
22541
+ }
22542
+ ]
22543
+ }
22544
+ }
22545
+ }
22546
+ ]
22547
+ }
22548
+ }
22549
+ }
22550
+ ]
22551
+ }
22552
+ },
22553
+ "modifiers": {
22554
+ "hiddenPath": "$service:himiEventDetail.iapFormHidden"
22555
+ }
22556
+ },
22557
+ {
22558
+ "id": "",
22559
+ "body": {
22560
+ "package": "himalaya",
22561
+ "type": "FieldError",
22562
+ "props": {
22563
+ "text": "",
22564
+ "textPath": "$service:himiEventDetail.iapFormError"
22565
+ }
22566
+ }
22567
+ },
22568
+ {
22569
+ "id": "himi_event.apple.buy",
22570
+ "body": {
22571
+ "package": "himalaya",
22572
+ "type": "Button",
22573
+ "props": {
22574
+ "title": "$service:himiEventDetail.iapBuyLabel",
22575
+ "disabledPath": "$service:himiEventDetail.iapBuyDisabled",
22576
+ "style": "primary",
22577
+ "fullWidth": true,
22578
+ "action": {
22579
+ "actionId": "tier5.himiEventDetail.buyApple"
22580
+ }
22581
+ }
22582
+ }
22583
+ },
22584
+ {
22585
+ "id": "",
22586
+ "body": {
22587
+ "package": "himalaya",
22588
+ "type": "Text",
22589
+ "props": {
22590
+ "text": "$service:himiEventDetail.iapNote",
22591
+ "style": "footnote",
22592
+ "color": "textSecondary",
22593
+ "collapseWhenEmpty": true
22594
+ }
22595
+ }
22596
+ },
22597
+ {
22598
+ "id": "himi_event.apple.signin",
22599
+ "body": {
22600
+ "package": "himalaya",
22601
+ "type": "Button",
22602
+ "props": {
22603
+ "title": "Sign in to purchase",
22604
+ "style": "secondary",
22605
+ "action": {
22606
+ "actionId": "himi.open",
22607
+ "params": {
22608
+ "screenId": "himi_account"
22609
+ }
22610
+ }
22611
+ }
22612
+ },
22613
+ "modifiers": {
22614
+ "hiddenPath": "$service:himiEventDetail.iapSignInHidden"
22615
+ }
22616
+ },
22617
+ {
22618
+ "id": "himi_event.apple.retry",
22619
+ "body": {
22620
+ "package": "himalaya",
22621
+ "type": "Button",
22622
+ "props": {
22623
+ "title": "Refresh purchase status",
22624
+ "style": "secondary",
22625
+ "action": {
22626
+ "actionId": "tier5.himiEventDetail.iapRefresh"
22627
+ }
22628
+ }
22629
+ },
22630
+ "modifiers": {
22631
+ "hiddenPath": "$service:himiEventDetail.iapRetryHidden"
22632
+ }
22633
+ }
22634
+ ]
22635
+ }
22636
+ },
22637
+ "modifiers": {
22638
+ "hiddenPath": "$service:himiEventDetail.iapBuyHidden"
22639
+ }
22640
+ },
22249
22641
  {
22250
22642
  "id": "himi_event.tickets",
22251
22643
  "body": {
@@ -22255,6 +22647,7 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
22255
22647
  "title": "Get tickets",
22256
22648
  "style": "primary",
22257
22649
  "fullWidth": true,
22650
+ "disabledPath": "$service:himiEventDetail.ticketPurchaseBlocked",
22258
22651
  "action": {
22259
22652
  "actionId": "tier5.himiEventDetail.openRegistration"
22260
22653
  }
@@ -22264,7 +22657,7 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
22264
22657
  "cornerRadius": 8,
22265
22658
  "pressFeedback": "scale",
22266
22659
  "haptic": "medium",
22267
- "hiddenPath": "$service:himiEventDetail.hideTickets"
22660
+ "hiddenPath": "$service:himiEventDetail.regularTicketsHidden"
22268
22661
  }
22269
22662
  },
22270
22663
  {
@@ -22424,7 +22817,9 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
22424
22817
  "share",
22425
22818
  "wix_cashier",
22426
22819
  "local_database",
22427
- "wix_platform"
22820
+ "wix_platform",
22821
+ "app_info",
22822
+ "iap"
22428
22823
  ],
22429
22824
  "minBinaryVersion": "0.1.0",
22430
22825
  "bundleVersion": "0.0.1"
@@ -0,0 +1,106 @@
1
+ import { copyParam } from "./himi-copy.js";
2
+
3
+ export interface AttendanceField {
4
+ id: string;
5
+ label: string;
6
+ kind: string;
7
+ required: boolean;
8
+ value: string;
9
+ selectedIds: string[];
10
+ options: { id: string; label: string }[];
11
+ error: string;
12
+ maxLength?: number;
13
+ maxSize?: number;
14
+ }
15
+
16
+ const object = (v: unknown): Record<string, unknown> => v !== null && typeof v === "object" && !Array.isArray(v) ? v as Record<string, unknown> : {};
17
+ const text = (v: unknown): string => typeof v === "string" ? v : "";
18
+ const EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
19
+
20
+ export function createAttendanceForm(prefix: string) {
21
+ let fields: AttendanceField[] = [];
22
+ let supported = false;
23
+ const label = (name: string) => copyParam(`${prefix}.${name}Label`, name === "firstName" ? "First name" : name === "lastName" ? "Last name" : "Email");
24
+ const field = (scope: string, name: string, input: Record<string, unknown> = {}): AttendanceField => ({
25
+ id: `${scope}:${name}`, label: text(input.label) || label(name), required: input.mandatory === true,
26
+ kind: name === "email" ? "email" : input.type === "NUMBER" ? "number" : input.type === "TEXT_ARRAY" ? "multiple" : Array.isArray(input.options) && input.options.length ? "choice" : "text",
27
+ value: "", selectedIds: [], error: "",
28
+ options: Array.isArray(input.options) ? input.options.filter((o): o is string => typeof o === "string").map((o) => ({ id: o, label: o })) : [],
29
+ ...(typeof input.maxLength === "number" ? { maxLength: input.maxLength } : {}),
30
+ ...(typeof input.maxSize === "number" ? { maxSize: input.maxSize } : {}),
31
+ });
32
+ const contact = (scope: string) => ["firstName", "lastName", "email"].map((name) => field(scope, name, { mandatory: true }));
33
+
34
+ function event(raw: unknown): void {
35
+ fields = contact("buyer");
36
+ const controls = object(raw).controls;
37
+ supported = Array.isArray(controls) && controls.length > 0;
38
+ const names = new Set<string>();
39
+ for (const control of Array.isArray(controls) ? controls : []) {
40
+ const c = object(control);
41
+ if (c.deleted === true) continue;
42
+ if (!Array.isArray(c.inputs) || !c.inputs.length) { supported = false; continue; }
43
+ for (const rawInput of c.inputs) {
44
+ const input = object(rawInput);
45
+ const name = text(input.name);
46
+ if (!name || names.has(name) || !["TEXT", "NUMBER", "TEXT_ARRAY"].includes(text(input.type)) || (input.type === "TEXT_ARRAY" && (!Array.isArray(input.options) || !input.options.length))) { supported = false; continue; }
47
+ names.add(name);
48
+ fields.push(field("guest", name, { ...input, mandatory: input.mandatory === true || ["firstName", "lastName", "email"].includes(name) }));
49
+ }
50
+ }
51
+ if (!["firstName", "lastName", "email"].every((name) => names.has(name))) supported = false;
52
+ }
53
+
54
+ function booking(service: unknown): void {
55
+ fields = contact("buyer");
56
+ const id = text(object(object(service).form).id);
57
+ // Custom intake schemas need their own reader; never silently omit their required fields.
58
+ supported = id === "00000000-0000-0000-0000-000000000000";
59
+ }
60
+
61
+ function change(arg: unknown): void {
62
+ const a = object(arg);
63
+ const f = fields.find((candidate) => candidate.id === a.id);
64
+ if (!f) return;
65
+ if (typeof a.option === "string") {
66
+ if (f.kind === "multiple") f.selectedIds = f.selectedIds.includes(a.option) ? f.selectedIds.filter((v) => v !== a.option) : [...f.selectedIds, a.option];
67
+ else f.value = a.option;
68
+ f.error = "";
69
+ return;
70
+ }
71
+ f.value = text(a.value ?? a.text ?? a.selectedId);
72
+ f.selectedIds = Array.isArray(a.selectedIds) ? a.selectedIds.filter((v): v is string => typeof v === "string") : [];
73
+ f.error = "";
74
+ }
75
+
76
+ function valid(f: AttendanceField): boolean {
77
+ const value = f.value.trim();
78
+ const values = f.kind === "multiple" ? f.selectedIds : value ? [value] : [];
79
+ if (!values.length) return !f.required;
80
+ if (f.options.length && values.some((v) => !f.options.some((o) => o.id === v))) return false;
81
+ if (f.maxSize !== undefined && values.length > f.maxSize) return false;
82
+ if (f.maxLength !== undefined && values.some((v) => v.length > f.maxLength!)) return false;
83
+ return f.kind === "email" ? EMAIL.test(value) : f.kind !== "number" || /^-?\d+(?:\.\d+)?$/.test(value);
84
+ }
85
+
86
+ function validate(): boolean {
87
+ for (const f of fields) f.error = valid(f) ? "" : copyParam(`${prefix}.formInvalidText`, "Check this field.");
88
+ return supported && fields.every((f) => !f.error);
89
+ }
90
+
91
+ function buyer(): Record<string, string> {
92
+ return Object.fromEntries(fields.filter((f) => f.id.startsWith("buyer:")).map((f) => [f.id.slice(6), f.value.trim()]));
93
+ }
94
+
95
+ function ticket(definitionId: string) {
96
+ const inputValues = fields.filter((f) => f.id.startsWith("guest:") && (f.value.trim() || f.selectedIds.length)).map((f) => ({ inputName: f.id.slice(6), ...(f.kind === "multiple" ? { values: f.selectedIds.slice() } : { value: f.value.trim() }) }));
97
+ return { buyer: buyer(), guests: [{ ticketDefinitionId: definitionId, form: { inputValues } }] };
98
+ }
99
+
100
+ return {
101
+ event, booking, change, validate, buyer, ticket,
102
+ supported: () => supported,
103
+ rows: () => fields.map((f) => ({ ...f, selectedIds: f.selectedIds.slice(), kind: f.kind === "text" && f.required ? "requiredText" : f.kind })),
104
+ clear: () => { for (const f of fields) { f.value = ""; f.selectedIds = []; f.error = ""; } },
105
+ };
106
+ }