@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
@@ -30754,6 +30754,398 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
30754
30754
  "hiddenPath": "$service:himiEventDetail.hideTierPicker"
30755
30755
  }
30756
30756
  },
30757
+ {
30758
+ "id": "",
30759
+ "body": {
30760
+ "package": "himalaya",
30761
+ "type": "VStack",
30762
+ "props": {
30763
+ "spacing": 12,
30764
+ "alignment": "leading",
30765
+ "children": [
30766
+ {
30767
+ "id": "",
30768
+ "body": {
30769
+ "package": "himalaya",
30770
+ "type": "Text",
30771
+ "props": {
30772
+ "text": "$service:himiEventDetail.iapPrice",
30773
+ "style": "bodyEmphasis",
30774
+ "collapseWhenEmpty": true
30775
+ }
30776
+ }
30777
+ },
30778
+ {
30779
+ "id": "himi_event.apple.form",
30780
+ "body": {
30781
+ "package": "himalaya",
30782
+ "type": "Grid",
30783
+ "props": {
30784
+ "columns": 1,
30785
+ "spacing": 12,
30786
+ "itemsPath": "$service:himiEventDetail.iapFields",
30787
+ "items": [
30788
+ {
30789
+ "id": "",
30790
+ "body": {
30791
+ "package": "himalaya",
30792
+ "type": "VStack",
30793
+ "props": {
30794
+ "spacing": 8,
30795
+ "alignment": "leading",
30796
+ "children": [
30797
+ {
30798
+ "id": "",
30799
+ "body": {
30800
+ "package": "himalaya",
30801
+ "type": "Text",
30802
+ "props": {
30803
+ "text": "$item.sectionLabel",
30804
+ "style": "bodyEmphasis",
30805
+ "collapseWhenEmpty": true
30806
+ }
30807
+ }
30808
+ },
30809
+ {
30810
+ "id": "",
30811
+ "body": {
30812
+ "package": "himalaya",
30813
+ "type": "Text",
30814
+ "props": {
30815
+ "text": "$item.label",
30816
+ "style": "footnote"
30817
+ }
30818
+ }
30819
+ },
30820
+ {
30821
+ "id": "himi_event.apple.input.$item.id",
30822
+ "body": {
30823
+ "package": "himalaya",
30824
+ "type": "FragmentSlot",
30825
+ "props": {
30826
+ "casePath": "$item.kind",
30827
+ "defaultCase": "text",
30828
+ "cases": [
30829
+ {
30830
+ "id": "text",
30831
+ "content": {
30832
+ "id": "himi_event.apple.field.text.$item.id",
30833
+ "body": {
30834
+ "package": "himalaya",
30835
+ "type": "TextField",
30836
+ "props": {
30837
+ "placeholder": "$item.inputLabel",
30838
+ "value": "$item.value",
30839
+ "onChange": {
30840
+ "actionId": "tier5.himiEventDetail.setIapField",
30841
+ "params": {
30842
+ "id": "$item.fieldId"
30843
+ }
30844
+ },
30845
+ "validation": {},
30846
+ "errorText": "$item.error",
30847
+ "autoCapitalization": "words"
30848
+ }
30849
+ }
30850
+ }
30851
+ },
30852
+ {
30853
+ "id": "requiredText",
30854
+ "content": {
30855
+ "id": "himi_event.apple.field.requiredText.$item.id",
30856
+ "body": {
30857
+ "package": "himalaya",
30858
+ "type": "TextField",
30859
+ "props": {
30860
+ "placeholder": "$item.inputLabel",
30861
+ "value": "$item.value",
30862
+ "onChange": {
30863
+ "actionId": "tier5.himiEventDetail.setIapField",
30864
+ "params": {
30865
+ "id": "$item.fieldId"
30866
+ }
30867
+ },
30868
+ "validation": {
30869
+ "required": true
30870
+ },
30871
+ "errorText": "$item.error",
30872
+ "autoCapitalization": "words"
30873
+ }
30874
+ }
30875
+ }
30876
+ },
30877
+ {
30878
+ "id": "email",
30879
+ "content": {
30880
+ "id": "himi_event.apple.field.email.$item.id",
30881
+ "body": {
30882
+ "package": "himalaya",
30883
+ "type": "TextField",
30884
+ "props": {
30885
+ "placeholder": "$item.inputLabel",
30886
+ "value": "$item.value",
30887
+ "onChange": {
30888
+ "actionId": "tier5.himiEventDetail.setIapField",
30889
+ "params": {
30890
+ "id": "$item.fieldId"
30891
+ }
30892
+ },
30893
+ "validation": {
30894
+ "required": true,
30895
+ "type": "email"
30896
+ },
30897
+ "errorText": "$item.error",
30898
+ "autoCapitalization": "none"
30899
+ }
30900
+ }
30901
+ }
30902
+ },
30903
+ {
30904
+ "id": "number",
30905
+ "content": {
30906
+ "id": "himi_event.apple.field.number.$item.id",
30907
+ "body": {
30908
+ "package": "himalaya",
30909
+ "type": "TextField",
30910
+ "props": {
30911
+ "placeholder": "$item.inputLabel",
30912
+ "value": "$item.value",
30913
+ "onChange": {
30914
+ "actionId": "tier5.himiEventDetail.setIapField",
30915
+ "params": {
30916
+ "id": "$item.fieldId"
30917
+ }
30918
+ },
30919
+ "validation": {
30920
+ "type": "number"
30921
+ },
30922
+ "errorText": "$item.error",
30923
+ "autoCapitalization": "words"
30924
+ }
30925
+ }
30926
+ }
30927
+ },
30928
+ {
30929
+ "id": "choice",
30930
+ "content": {
30931
+ "id": "",
30932
+ "body": {
30933
+ "package": "himalaya",
30934
+ "type": "VStack",
30935
+ "props": {
30936
+ "spacing": 4,
30937
+ "children": [
30938
+ {
30939
+ "id": "himi_event.apple.options.choice",
30940
+ "body": {
30941
+ "package": "himalaya",
30942
+ "type": "Grid",
30943
+ "props": {
30944
+ "columns": 1,
30945
+ "spacing": 8,
30946
+ "itemsPath": "$item.options",
30947
+ "items": [
30948
+ {
30949
+ "id": "himi_event.apple.option.choice.$item.fieldId.$item.id",
30950
+ "body": {
30951
+ "package": "himalaya",
30952
+ "type": "Button",
30953
+ "props": {
30954
+ "title": "$item.displayLabel",
30955
+ "style": "secondary",
30956
+ "fullWidth": true,
30957
+ "action": {
30958
+ "actionId": "tier5.himiEventDetail.setIapField",
30959
+ "params": {
30960
+ "id": "$item.fieldId",
30961
+ "option": "$item.id"
30962
+ }
30963
+ }
30964
+ }
30965
+ }
30966
+ }
30967
+ ]
30968
+ }
30969
+ }
30970
+ },
30971
+ {
30972
+ "id": "",
30973
+ "body": {
30974
+ "package": "himalaya",
30975
+ "type": "FieldError",
30976
+ "props": {
30977
+ "text": "$item.error"
30978
+ }
30979
+ },
30980
+ "modifiers": {
30981
+ "hiddenPath": "$item.errorHidden"
30982
+ }
30983
+ }
30984
+ ]
30985
+ }
30986
+ }
30987
+ }
30988
+ },
30989
+ {
30990
+ "id": "multiple",
30991
+ "content": {
30992
+ "id": "",
30993
+ "body": {
30994
+ "package": "himalaya",
30995
+ "type": "VStack",
30996
+ "props": {
30997
+ "spacing": 4,
30998
+ "children": [
30999
+ {
31000
+ "id": "himi_event.apple.options.multiple",
31001
+ "body": {
31002
+ "package": "himalaya",
31003
+ "type": "Grid",
31004
+ "props": {
31005
+ "columns": 1,
31006
+ "spacing": 8,
31007
+ "itemsPath": "$item.options",
31008
+ "items": [
31009
+ {
31010
+ "id": "himi_event.apple.option.multiple.$item.fieldId.$item.id",
31011
+ "body": {
31012
+ "package": "himalaya",
31013
+ "type": "Button",
31014
+ "props": {
31015
+ "title": "$item.displayLabel",
31016
+ "style": "secondary",
31017
+ "fullWidth": true,
31018
+ "action": {
31019
+ "actionId": "tier5.himiEventDetail.setIapField",
31020
+ "params": {
31021
+ "id": "$item.fieldId",
31022
+ "option": "$item.id"
31023
+ }
31024
+ }
31025
+ }
31026
+ }
31027
+ }
31028
+ ]
31029
+ }
31030
+ }
31031
+ },
31032
+ {
31033
+ "id": "",
31034
+ "body": {
31035
+ "package": "himalaya",
31036
+ "type": "FieldError",
31037
+ "props": {
31038
+ "text": "$item.error"
31039
+ }
31040
+ },
31041
+ "modifiers": {
31042
+ "hiddenPath": "$item.errorHidden"
31043
+ }
31044
+ }
31045
+ ]
31046
+ }
31047
+ }
31048
+ }
31049
+ }
31050
+ ]
31051
+ }
31052
+ }
31053
+ }
31054
+ ]
31055
+ }
31056
+ }
31057
+ }
31058
+ ]
31059
+ }
31060
+ },
31061
+ "modifiers": {
31062
+ "hiddenPath": "$service:himiEventDetail.iapFormHidden"
31063
+ }
31064
+ },
31065
+ {
31066
+ "id": "",
31067
+ "body": {
31068
+ "package": "himalaya",
31069
+ "type": "FieldError",
31070
+ "props": {
31071
+ "text": "",
31072
+ "textPath": "$service:himiEventDetail.iapFormError"
31073
+ }
31074
+ }
31075
+ },
31076
+ {
31077
+ "id": "himi_event.apple.buy",
31078
+ "body": {
31079
+ "package": "himalaya",
31080
+ "type": "Button",
31081
+ "props": {
31082
+ "title": "$service:himiEventDetail.iapBuyLabel",
31083
+ "disabledPath": "$service:himiEventDetail.iapBuyDisabled",
31084
+ "style": "primary",
31085
+ "fullWidth": true,
31086
+ "action": {
31087
+ "actionId": "tier5.himiEventDetail.buyApple"
31088
+ }
31089
+ }
31090
+ }
31091
+ },
31092
+ {
31093
+ "id": "",
31094
+ "body": {
31095
+ "package": "himalaya",
31096
+ "type": "Text",
31097
+ "props": {
31098
+ "text": "$service:himiEventDetail.iapNote",
31099
+ "style": "footnote",
31100
+ "color": "textSecondary",
31101
+ "collapseWhenEmpty": true
31102
+ }
31103
+ }
31104
+ },
31105
+ {
31106
+ "id": "himi_event.apple.signin",
31107
+ "body": {
31108
+ "package": "himalaya",
31109
+ "type": "Button",
31110
+ "props": {
31111
+ "title": "Sign in to purchase",
31112
+ "style": "secondary",
31113
+ "action": {
31114
+ "actionId": "himi.open",
31115
+ "params": {
31116
+ "screenId": "himi_account"
31117
+ }
31118
+ }
31119
+ }
31120
+ },
31121
+ "modifiers": {
31122
+ "hiddenPath": "$service:himiEventDetail.iapSignInHidden"
31123
+ }
31124
+ },
31125
+ {
31126
+ "id": "himi_event.apple.retry",
31127
+ "body": {
31128
+ "package": "himalaya",
31129
+ "type": "Button",
31130
+ "props": {
31131
+ "title": "Refresh purchase status",
31132
+ "style": "secondary",
31133
+ "action": {
31134
+ "actionId": "tier5.himiEventDetail.iapRefresh"
31135
+ }
31136
+ }
31137
+ },
31138
+ "modifiers": {
31139
+ "hiddenPath": "$service:himiEventDetail.iapRetryHidden"
31140
+ }
31141
+ }
31142
+ ]
31143
+ }
31144
+ },
31145
+ "modifiers": {
31146
+ "hiddenPath": "$service:himiEventDetail.iapBuyHidden"
31147
+ }
31148
+ },
30757
31149
  {
30758
31150
  "id": "himi_event.tickets",
30759
31151
  "body": {
@@ -30763,6 +31155,7 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
30763
31155
  "title": "Get tickets",
30764
31156
  "style": "primary",
30765
31157
  "fullWidth": true,
31158
+ "disabledPath": "$service:himiEventDetail.ticketPurchaseBlocked",
30766
31159
  "action": {
30767
31160
  "actionId": "tier5.himiEventDetail.openRegistration"
30768
31161
  }
@@ -30772,7 +31165,7 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
30772
31165
  "cornerRadius": 8,
30773
31166
  "pressFeedback": "scale",
30774
31167
  "haptic": "medium",
30775
- "hiddenPath": "$service:himiEventDetail.hideTickets"
31168
+ "hiddenPath": "$service:himiEventDetail.regularTicketsHidden"
30776
31169
  }
30777
31170
  },
30778
31171
  {
@@ -30932,7 +31325,9 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
30932
31325
  "share",
30933
31326
  "wix_cashier",
30934
31327
  "local_database",
30935
- "wix_platform"
31328
+ "wix_platform",
31329
+ "app_info",
31330
+ "iap"
30936
31331
  ],
30937
31332
  "minBinaryVersion": "0.1.0",
30938
31333
  "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
+ }