@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
@@ -17852,6 +17852,398 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
17852
17852
  "hiddenPath": "$service:himiEventDetail.hideTierPicker"
17853
17853
  }
17854
17854
  },
17855
+ {
17856
+ "id": "",
17857
+ "body": {
17858
+ "package": "himalaya",
17859
+ "type": "VStack",
17860
+ "props": {
17861
+ "spacing": 12,
17862
+ "alignment": "leading",
17863
+ "children": [
17864
+ {
17865
+ "id": "",
17866
+ "body": {
17867
+ "package": "himalaya",
17868
+ "type": "Text",
17869
+ "props": {
17870
+ "text": "$service:himiEventDetail.iapPrice",
17871
+ "style": "bodyEmphasis",
17872
+ "collapseWhenEmpty": true
17873
+ }
17874
+ }
17875
+ },
17876
+ {
17877
+ "id": "himi_event.apple.form",
17878
+ "body": {
17879
+ "package": "himalaya",
17880
+ "type": "Grid",
17881
+ "props": {
17882
+ "columns": 1,
17883
+ "spacing": 12,
17884
+ "itemsPath": "$service:himiEventDetail.iapFields",
17885
+ "items": [
17886
+ {
17887
+ "id": "",
17888
+ "body": {
17889
+ "package": "himalaya",
17890
+ "type": "VStack",
17891
+ "props": {
17892
+ "spacing": 8,
17893
+ "alignment": "leading",
17894
+ "children": [
17895
+ {
17896
+ "id": "",
17897
+ "body": {
17898
+ "package": "himalaya",
17899
+ "type": "Text",
17900
+ "props": {
17901
+ "text": "$item.sectionLabel",
17902
+ "style": "bodyEmphasis",
17903
+ "collapseWhenEmpty": true
17904
+ }
17905
+ }
17906
+ },
17907
+ {
17908
+ "id": "",
17909
+ "body": {
17910
+ "package": "himalaya",
17911
+ "type": "Text",
17912
+ "props": {
17913
+ "text": "$item.label",
17914
+ "style": "footnote"
17915
+ }
17916
+ }
17917
+ },
17918
+ {
17919
+ "id": "himi_event.apple.input.$item.id",
17920
+ "body": {
17921
+ "package": "himalaya",
17922
+ "type": "FragmentSlot",
17923
+ "props": {
17924
+ "casePath": "$item.kind",
17925
+ "defaultCase": "text",
17926
+ "cases": [
17927
+ {
17928
+ "id": "text",
17929
+ "content": {
17930
+ "id": "himi_event.apple.field.text.$item.id",
17931
+ "body": {
17932
+ "package": "himalaya",
17933
+ "type": "TextField",
17934
+ "props": {
17935
+ "placeholder": "$item.inputLabel",
17936
+ "value": "$item.value",
17937
+ "onChange": {
17938
+ "actionId": "tier5.himiEventDetail.setIapField",
17939
+ "params": {
17940
+ "id": "$item.fieldId"
17941
+ }
17942
+ },
17943
+ "validation": {},
17944
+ "errorText": "$item.error",
17945
+ "autoCapitalization": "words"
17946
+ }
17947
+ }
17948
+ }
17949
+ },
17950
+ {
17951
+ "id": "requiredText",
17952
+ "content": {
17953
+ "id": "himi_event.apple.field.requiredText.$item.id",
17954
+ "body": {
17955
+ "package": "himalaya",
17956
+ "type": "TextField",
17957
+ "props": {
17958
+ "placeholder": "$item.inputLabel",
17959
+ "value": "$item.value",
17960
+ "onChange": {
17961
+ "actionId": "tier5.himiEventDetail.setIapField",
17962
+ "params": {
17963
+ "id": "$item.fieldId"
17964
+ }
17965
+ },
17966
+ "validation": {
17967
+ "required": true
17968
+ },
17969
+ "errorText": "$item.error",
17970
+ "autoCapitalization": "words"
17971
+ }
17972
+ }
17973
+ }
17974
+ },
17975
+ {
17976
+ "id": "email",
17977
+ "content": {
17978
+ "id": "himi_event.apple.field.email.$item.id",
17979
+ "body": {
17980
+ "package": "himalaya",
17981
+ "type": "TextField",
17982
+ "props": {
17983
+ "placeholder": "$item.inputLabel",
17984
+ "value": "$item.value",
17985
+ "onChange": {
17986
+ "actionId": "tier5.himiEventDetail.setIapField",
17987
+ "params": {
17988
+ "id": "$item.fieldId"
17989
+ }
17990
+ },
17991
+ "validation": {
17992
+ "required": true,
17993
+ "type": "email"
17994
+ },
17995
+ "errorText": "$item.error",
17996
+ "autoCapitalization": "none"
17997
+ }
17998
+ }
17999
+ }
18000
+ },
18001
+ {
18002
+ "id": "number",
18003
+ "content": {
18004
+ "id": "himi_event.apple.field.number.$item.id",
18005
+ "body": {
18006
+ "package": "himalaya",
18007
+ "type": "TextField",
18008
+ "props": {
18009
+ "placeholder": "$item.inputLabel",
18010
+ "value": "$item.value",
18011
+ "onChange": {
18012
+ "actionId": "tier5.himiEventDetail.setIapField",
18013
+ "params": {
18014
+ "id": "$item.fieldId"
18015
+ }
18016
+ },
18017
+ "validation": {
18018
+ "type": "number"
18019
+ },
18020
+ "errorText": "$item.error",
18021
+ "autoCapitalization": "words"
18022
+ }
18023
+ }
18024
+ }
18025
+ },
18026
+ {
18027
+ "id": "choice",
18028
+ "content": {
18029
+ "id": "",
18030
+ "body": {
18031
+ "package": "himalaya",
18032
+ "type": "VStack",
18033
+ "props": {
18034
+ "spacing": 4,
18035
+ "children": [
18036
+ {
18037
+ "id": "himi_event.apple.options.choice",
18038
+ "body": {
18039
+ "package": "himalaya",
18040
+ "type": "Grid",
18041
+ "props": {
18042
+ "columns": 1,
18043
+ "spacing": 8,
18044
+ "itemsPath": "$item.options",
18045
+ "items": [
18046
+ {
18047
+ "id": "himi_event.apple.option.choice.$item.fieldId.$item.id",
18048
+ "body": {
18049
+ "package": "himalaya",
18050
+ "type": "Button",
18051
+ "props": {
18052
+ "title": "$item.displayLabel",
18053
+ "style": "secondary",
18054
+ "fullWidth": true,
18055
+ "action": {
18056
+ "actionId": "tier5.himiEventDetail.setIapField",
18057
+ "params": {
18058
+ "id": "$item.fieldId",
18059
+ "option": "$item.id"
18060
+ }
18061
+ }
18062
+ }
18063
+ }
18064
+ }
18065
+ ]
18066
+ }
18067
+ }
18068
+ },
18069
+ {
18070
+ "id": "",
18071
+ "body": {
18072
+ "package": "himalaya",
18073
+ "type": "FieldError",
18074
+ "props": {
18075
+ "text": "$item.error"
18076
+ }
18077
+ },
18078
+ "modifiers": {
18079
+ "hiddenPath": "$item.errorHidden"
18080
+ }
18081
+ }
18082
+ ]
18083
+ }
18084
+ }
18085
+ }
18086
+ },
18087
+ {
18088
+ "id": "multiple",
18089
+ "content": {
18090
+ "id": "",
18091
+ "body": {
18092
+ "package": "himalaya",
18093
+ "type": "VStack",
18094
+ "props": {
18095
+ "spacing": 4,
18096
+ "children": [
18097
+ {
18098
+ "id": "himi_event.apple.options.multiple",
18099
+ "body": {
18100
+ "package": "himalaya",
18101
+ "type": "Grid",
18102
+ "props": {
18103
+ "columns": 1,
18104
+ "spacing": 8,
18105
+ "itemsPath": "$item.options",
18106
+ "items": [
18107
+ {
18108
+ "id": "himi_event.apple.option.multiple.$item.fieldId.$item.id",
18109
+ "body": {
18110
+ "package": "himalaya",
18111
+ "type": "Button",
18112
+ "props": {
18113
+ "title": "$item.displayLabel",
18114
+ "style": "secondary",
18115
+ "fullWidth": true,
18116
+ "action": {
18117
+ "actionId": "tier5.himiEventDetail.setIapField",
18118
+ "params": {
18119
+ "id": "$item.fieldId",
18120
+ "option": "$item.id"
18121
+ }
18122
+ }
18123
+ }
18124
+ }
18125
+ }
18126
+ ]
18127
+ }
18128
+ }
18129
+ },
18130
+ {
18131
+ "id": "",
18132
+ "body": {
18133
+ "package": "himalaya",
18134
+ "type": "FieldError",
18135
+ "props": {
18136
+ "text": "$item.error"
18137
+ }
18138
+ },
18139
+ "modifiers": {
18140
+ "hiddenPath": "$item.errorHidden"
18141
+ }
18142
+ }
18143
+ ]
18144
+ }
18145
+ }
18146
+ }
18147
+ }
18148
+ ]
18149
+ }
18150
+ }
18151
+ }
18152
+ ]
18153
+ }
18154
+ }
18155
+ }
18156
+ ]
18157
+ }
18158
+ },
18159
+ "modifiers": {
18160
+ "hiddenPath": "$service:himiEventDetail.iapFormHidden"
18161
+ }
18162
+ },
18163
+ {
18164
+ "id": "",
18165
+ "body": {
18166
+ "package": "himalaya",
18167
+ "type": "FieldError",
18168
+ "props": {
18169
+ "text": "",
18170
+ "textPath": "$service:himiEventDetail.iapFormError"
18171
+ }
18172
+ }
18173
+ },
18174
+ {
18175
+ "id": "himi_event.apple.buy",
18176
+ "body": {
18177
+ "package": "himalaya",
18178
+ "type": "Button",
18179
+ "props": {
18180
+ "title": "$service:himiEventDetail.iapBuyLabel",
18181
+ "disabledPath": "$service:himiEventDetail.iapBuyDisabled",
18182
+ "style": "primary",
18183
+ "fullWidth": true,
18184
+ "action": {
18185
+ "actionId": "tier5.himiEventDetail.buyApple"
18186
+ }
18187
+ }
18188
+ }
18189
+ },
18190
+ {
18191
+ "id": "",
18192
+ "body": {
18193
+ "package": "himalaya",
18194
+ "type": "Text",
18195
+ "props": {
18196
+ "text": "$service:himiEventDetail.iapNote",
18197
+ "style": "footnote",
18198
+ "color": "textSecondary",
18199
+ "collapseWhenEmpty": true
18200
+ }
18201
+ }
18202
+ },
18203
+ {
18204
+ "id": "himi_event.apple.signin",
18205
+ "body": {
18206
+ "package": "himalaya",
18207
+ "type": "Button",
18208
+ "props": {
18209
+ "title": "Sign in to purchase",
18210
+ "style": "secondary",
18211
+ "action": {
18212
+ "actionId": "himi.open",
18213
+ "params": {
18214
+ "screenId": "himi_account"
18215
+ }
18216
+ }
18217
+ }
18218
+ },
18219
+ "modifiers": {
18220
+ "hiddenPath": "$service:himiEventDetail.iapSignInHidden"
18221
+ }
18222
+ },
18223
+ {
18224
+ "id": "himi_event.apple.retry",
18225
+ "body": {
18226
+ "package": "himalaya",
18227
+ "type": "Button",
18228
+ "props": {
18229
+ "title": "Refresh purchase status",
18230
+ "style": "secondary",
18231
+ "action": {
18232
+ "actionId": "tier5.himiEventDetail.iapRefresh"
18233
+ }
18234
+ }
18235
+ },
18236
+ "modifiers": {
18237
+ "hiddenPath": "$service:himiEventDetail.iapRetryHidden"
18238
+ }
18239
+ }
18240
+ ]
18241
+ }
18242
+ },
18243
+ "modifiers": {
18244
+ "hiddenPath": "$service:himiEventDetail.iapBuyHidden"
18245
+ }
18246
+ },
17855
18247
  {
17856
18248
  "id": "himi_event.tickets",
17857
18249
  "body": {
@@ -17861,6 +18253,7 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
17861
18253
  "title": "Get tickets",
17862
18254
  "style": "primary",
17863
18255
  "fullWidth": true,
18256
+ "disabledPath": "$service:himiEventDetail.ticketPurchaseBlocked",
17864
18257
  "action": {
17865
18258
  "actionId": "tier5.himiEventDetail.openRegistration"
17866
18259
  }
@@ -17870,7 +18263,7 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
17870
18263
  "cornerRadius": 8,
17871
18264
  "pressFeedback": "scale",
17872
18265
  "haptic": "medium",
17873
- "hiddenPath": "$service:himiEventDetail.hideTickets"
18266
+ "hiddenPath": "$service:himiEventDetail.regularTicketsHidden"
17874
18267
  }
17875
18268
  },
17876
18269
  {
@@ -18030,7 +18423,9 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
18030
18423
  "share",
18031
18424
  "wix_cashier",
18032
18425
  "local_database",
18033
- "wix_platform"
18426
+ "wix_platform",
18427
+ "app_info",
18428
+ "iap"
18034
18429
  ],
18035
18430
  "minBinaryVersion": "0.1.0",
18036
18431
  "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
+ }