@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.1496.0",
3
+ "version": "0.1497.0",
4
4
  "type": "module",
5
5
  "description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
6
6
  "keywords": [
@@ -71,5 +71,5 @@
71
71
  "artifactId": "himalaya-cli"
72
72
  }
73
73
  },
74
- "falconPackageHash": "62f2d72e731199e9639b54a6fe134fb94787cad79d777403144183b4"
74
+ "falconPackageHash": "925625adf07883eda7c6afd8a567175e5b7c308d16e8bda935951d9a"
75
75
  }
@@ -36793,6 +36793,398 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
36793
36793
  }
36794
36794
  }
36795
36795
  },
36796
+ {
36797
+ "id": "",
36798
+ "body": {
36799
+ "package": "himalaya",
36800
+ "type": "VStack",
36801
+ "props": {
36802
+ "spacing": 12,
36803
+ "alignment": "leading",
36804
+ "children": [
36805
+ {
36806
+ "id": "",
36807
+ "body": {
36808
+ "package": "himalaya",
36809
+ "type": "Text",
36810
+ "props": {
36811
+ "text": "$service:himiBookingTime.iapPrice",
36812
+ "style": "bodyEmphasis",
36813
+ "collapseWhenEmpty": true
36814
+ }
36815
+ }
36816
+ },
36817
+ {
36818
+ "id": "himi_time.apple.form",
36819
+ "body": {
36820
+ "package": "himalaya",
36821
+ "type": "Grid",
36822
+ "props": {
36823
+ "columns": 1,
36824
+ "spacing": 12,
36825
+ "itemsPath": "$service:himiBookingTime.iapFields",
36826
+ "items": [
36827
+ {
36828
+ "id": "",
36829
+ "body": {
36830
+ "package": "himalaya",
36831
+ "type": "VStack",
36832
+ "props": {
36833
+ "spacing": 8,
36834
+ "alignment": "leading",
36835
+ "children": [
36836
+ {
36837
+ "id": "",
36838
+ "body": {
36839
+ "package": "himalaya",
36840
+ "type": "Text",
36841
+ "props": {
36842
+ "text": "$item.sectionLabel",
36843
+ "style": "bodyEmphasis",
36844
+ "collapseWhenEmpty": true
36845
+ }
36846
+ }
36847
+ },
36848
+ {
36849
+ "id": "",
36850
+ "body": {
36851
+ "package": "himalaya",
36852
+ "type": "Text",
36853
+ "props": {
36854
+ "text": "$item.label",
36855
+ "style": "footnote"
36856
+ }
36857
+ }
36858
+ },
36859
+ {
36860
+ "id": "himi_time.apple.input.$item.id",
36861
+ "body": {
36862
+ "package": "himalaya",
36863
+ "type": "FragmentSlot",
36864
+ "props": {
36865
+ "casePath": "$item.kind",
36866
+ "defaultCase": "text",
36867
+ "cases": [
36868
+ {
36869
+ "id": "text",
36870
+ "content": {
36871
+ "id": "himi_time.apple.field.text.$item.id",
36872
+ "body": {
36873
+ "package": "himalaya",
36874
+ "type": "TextField",
36875
+ "props": {
36876
+ "placeholder": "$item.inputLabel",
36877
+ "value": "$item.value",
36878
+ "onChange": {
36879
+ "actionId": "tier5.himiBookingTime.setIapField",
36880
+ "params": {
36881
+ "id": "$item.fieldId"
36882
+ }
36883
+ },
36884
+ "validation": {},
36885
+ "errorText": "$item.error",
36886
+ "autoCapitalization": "words"
36887
+ }
36888
+ }
36889
+ }
36890
+ },
36891
+ {
36892
+ "id": "requiredText",
36893
+ "content": {
36894
+ "id": "himi_time.apple.field.requiredText.$item.id",
36895
+ "body": {
36896
+ "package": "himalaya",
36897
+ "type": "TextField",
36898
+ "props": {
36899
+ "placeholder": "$item.inputLabel",
36900
+ "value": "$item.value",
36901
+ "onChange": {
36902
+ "actionId": "tier5.himiBookingTime.setIapField",
36903
+ "params": {
36904
+ "id": "$item.fieldId"
36905
+ }
36906
+ },
36907
+ "validation": {
36908
+ "required": true
36909
+ },
36910
+ "errorText": "$item.error",
36911
+ "autoCapitalization": "words"
36912
+ }
36913
+ }
36914
+ }
36915
+ },
36916
+ {
36917
+ "id": "email",
36918
+ "content": {
36919
+ "id": "himi_time.apple.field.email.$item.id",
36920
+ "body": {
36921
+ "package": "himalaya",
36922
+ "type": "TextField",
36923
+ "props": {
36924
+ "placeholder": "$item.inputLabel",
36925
+ "value": "$item.value",
36926
+ "onChange": {
36927
+ "actionId": "tier5.himiBookingTime.setIapField",
36928
+ "params": {
36929
+ "id": "$item.fieldId"
36930
+ }
36931
+ },
36932
+ "validation": {
36933
+ "required": true,
36934
+ "type": "email"
36935
+ },
36936
+ "errorText": "$item.error",
36937
+ "autoCapitalization": "none"
36938
+ }
36939
+ }
36940
+ }
36941
+ },
36942
+ {
36943
+ "id": "number",
36944
+ "content": {
36945
+ "id": "himi_time.apple.field.number.$item.id",
36946
+ "body": {
36947
+ "package": "himalaya",
36948
+ "type": "TextField",
36949
+ "props": {
36950
+ "placeholder": "$item.inputLabel",
36951
+ "value": "$item.value",
36952
+ "onChange": {
36953
+ "actionId": "tier5.himiBookingTime.setIapField",
36954
+ "params": {
36955
+ "id": "$item.fieldId"
36956
+ }
36957
+ },
36958
+ "validation": {
36959
+ "type": "number"
36960
+ },
36961
+ "errorText": "$item.error",
36962
+ "autoCapitalization": "words"
36963
+ }
36964
+ }
36965
+ }
36966
+ },
36967
+ {
36968
+ "id": "choice",
36969
+ "content": {
36970
+ "id": "",
36971
+ "body": {
36972
+ "package": "himalaya",
36973
+ "type": "VStack",
36974
+ "props": {
36975
+ "spacing": 4,
36976
+ "children": [
36977
+ {
36978
+ "id": "himi_time.apple.options.choice",
36979
+ "body": {
36980
+ "package": "himalaya",
36981
+ "type": "Grid",
36982
+ "props": {
36983
+ "columns": 1,
36984
+ "spacing": 8,
36985
+ "itemsPath": "$item.options",
36986
+ "items": [
36987
+ {
36988
+ "id": "himi_time.apple.option.choice.$item.fieldId.$item.id",
36989
+ "body": {
36990
+ "package": "himalaya",
36991
+ "type": "Button",
36992
+ "props": {
36993
+ "title": "$item.displayLabel",
36994
+ "style": "secondary",
36995
+ "fullWidth": true,
36996
+ "action": {
36997
+ "actionId": "tier5.himiBookingTime.setIapField",
36998
+ "params": {
36999
+ "id": "$item.fieldId",
37000
+ "option": "$item.id"
37001
+ }
37002
+ }
37003
+ }
37004
+ }
37005
+ }
37006
+ ]
37007
+ }
37008
+ }
37009
+ },
37010
+ {
37011
+ "id": "",
37012
+ "body": {
37013
+ "package": "himalaya",
37014
+ "type": "FieldError",
37015
+ "props": {
37016
+ "text": "$item.error"
37017
+ }
37018
+ },
37019
+ "modifiers": {
37020
+ "hiddenPath": "$item.errorHidden"
37021
+ }
37022
+ }
37023
+ ]
37024
+ }
37025
+ }
37026
+ }
37027
+ },
37028
+ {
37029
+ "id": "multiple",
37030
+ "content": {
37031
+ "id": "",
37032
+ "body": {
37033
+ "package": "himalaya",
37034
+ "type": "VStack",
37035
+ "props": {
37036
+ "spacing": 4,
37037
+ "children": [
37038
+ {
37039
+ "id": "himi_time.apple.options.multiple",
37040
+ "body": {
37041
+ "package": "himalaya",
37042
+ "type": "Grid",
37043
+ "props": {
37044
+ "columns": 1,
37045
+ "spacing": 8,
37046
+ "itemsPath": "$item.options",
37047
+ "items": [
37048
+ {
37049
+ "id": "himi_time.apple.option.multiple.$item.fieldId.$item.id",
37050
+ "body": {
37051
+ "package": "himalaya",
37052
+ "type": "Button",
37053
+ "props": {
37054
+ "title": "$item.displayLabel",
37055
+ "style": "secondary",
37056
+ "fullWidth": true,
37057
+ "action": {
37058
+ "actionId": "tier5.himiBookingTime.setIapField",
37059
+ "params": {
37060
+ "id": "$item.fieldId",
37061
+ "option": "$item.id"
37062
+ }
37063
+ }
37064
+ }
37065
+ }
37066
+ }
37067
+ ]
37068
+ }
37069
+ }
37070
+ },
37071
+ {
37072
+ "id": "",
37073
+ "body": {
37074
+ "package": "himalaya",
37075
+ "type": "FieldError",
37076
+ "props": {
37077
+ "text": "$item.error"
37078
+ }
37079
+ },
37080
+ "modifiers": {
37081
+ "hiddenPath": "$item.errorHidden"
37082
+ }
37083
+ }
37084
+ ]
37085
+ }
37086
+ }
37087
+ }
37088
+ }
37089
+ ]
37090
+ }
37091
+ }
37092
+ }
37093
+ ]
37094
+ }
37095
+ }
37096
+ }
37097
+ ]
37098
+ }
37099
+ },
37100
+ "modifiers": {
37101
+ "hiddenPath": "$service:himiBookingTime.iapFormHidden"
37102
+ }
37103
+ },
37104
+ {
37105
+ "id": "",
37106
+ "body": {
37107
+ "package": "himalaya",
37108
+ "type": "FieldError",
37109
+ "props": {
37110
+ "text": "",
37111
+ "textPath": "$service:himiBookingTime.iapFormError"
37112
+ }
37113
+ }
37114
+ },
37115
+ {
37116
+ "id": "himi_time.apple.buy",
37117
+ "body": {
37118
+ "package": "himalaya",
37119
+ "type": "Button",
37120
+ "props": {
37121
+ "title": "$service:himiBookingTime.iapBuyLabel",
37122
+ "disabledPath": "$service:himiBookingTime.iapBuyDisabled",
37123
+ "style": "primary",
37124
+ "fullWidth": true,
37125
+ "action": {
37126
+ "actionId": "tier5.himiBookingTime.buyApple"
37127
+ }
37128
+ }
37129
+ }
37130
+ },
37131
+ {
37132
+ "id": "",
37133
+ "body": {
37134
+ "package": "himalaya",
37135
+ "type": "Text",
37136
+ "props": {
37137
+ "text": "$service:himiBookingTime.iapNote",
37138
+ "style": "footnote",
37139
+ "color": "textSecondary",
37140
+ "collapseWhenEmpty": true
37141
+ }
37142
+ }
37143
+ },
37144
+ {
37145
+ "id": "himi_time.apple.signin",
37146
+ "body": {
37147
+ "package": "himalaya",
37148
+ "type": "Button",
37149
+ "props": {
37150
+ "title": "Sign in",
37151
+ "style": "secondary",
37152
+ "action": {
37153
+ "actionId": "himi.open",
37154
+ "params": {
37155
+ "screenId": "himi_account"
37156
+ }
37157
+ }
37158
+ }
37159
+ },
37160
+ "modifiers": {
37161
+ "hiddenPath": "$service:himiBookingTime.iapSignInHidden"
37162
+ }
37163
+ },
37164
+ {
37165
+ "id": "himi_time.apple.retry",
37166
+ "body": {
37167
+ "package": "himalaya",
37168
+ "type": "Button",
37169
+ "props": {
37170
+ "title": "Refresh purchase status",
37171
+ "style": "secondary",
37172
+ "action": {
37173
+ "actionId": "tier5.himiBookingTime.iapRefresh"
37174
+ }
37175
+ }
37176
+ },
37177
+ "modifiers": {
37178
+ "hiddenPath": "$service:himiBookingTime.iapRetryHidden"
37179
+ }
37180
+ }
37181
+ ]
37182
+ }
37183
+ },
37184
+ "modifiers": {
37185
+ "hiddenPath": "$service:himiBookingTime.iapBuyHidden"
37186
+ }
37187
+ },
36796
37188
  {
36797
37189
  "id": "himi_time.book.disabled",
36798
37190
  "body": {
@@ -37091,6 +37483,8 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
37091
37483
  "declaredCapabilities": [
37092
37484
  "wix_api",
37093
37485
  "local_database",
37486
+ "app_info",
37487
+ "iap",
37094
37488
  "wix_cashier",
37095
37489
  "open_url",
37096
37490
  "wix_platform"
@@ -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
+ }