@sonordev/site-kit 1.2.7

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 (300) hide show
  1. package/README.md +376 -0
  2. package/dist/SetupWizard-Cki06kB0.d.mts +12 -0
  3. package/dist/SetupWizard-Cki06kB0.d.ts +12 -0
  4. package/dist/analytics/index.d.mts +93 -0
  5. package/dist/analytics/index.d.ts +93 -0
  6. package/dist/analytics/index.js +89 -0
  7. package/dist/analytics/index.js.map +1 -0
  8. package/dist/analytics/index.mjs +71 -0
  9. package/dist/analytics/index.mjs.map +1 -0
  10. package/dist/api-CWtoFJCO.d.mts +137 -0
  11. package/dist/api-CWtoFJCO.d.ts +137 -0
  12. package/dist/blog/index.d.mts +305 -0
  13. package/dist/blog/index.d.ts +305 -0
  14. package/dist/blog/index.js +1578 -0
  15. package/dist/blog/index.js.map +1 -0
  16. package/dist/blog/index.mjs +1562 -0
  17. package/dist/blog/index.mjs.map +1 -0
  18. package/dist/blog/server.d.mts +229 -0
  19. package/dist/blog/server.d.ts +229 -0
  20. package/dist/blog/server.js +692 -0
  21. package/dist/blog/server.js.map +1 -0
  22. package/dist/blog/server.mjs +666 -0
  23. package/dist/blog/server.mjs.map +1 -0
  24. package/dist/chunk-24277A3Q.mjs +968 -0
  25. package/dist/chunk-24277A3Q.mjs.map +1 -0
  26. package/dist/chunk-373TK6TZ.js +321 -0
  27. package/dist/chunk-373TK6TZ.js.map +1 -0
  28. package/dist/chunk-3MYZS6PD.js +30 -0
  29. package/dist/chunk-3MYZS6PD.js.map +1 -0
  30. package/dist/chunk-43GBM4SX.js +283 -0
  31. package/dist/chunk-43GBM4SX.js.map +1 -0
  32. package/dist/chunk-4XPGGLVP.mjs +53 -0
  33. package/dist/chunk-4XPGGLVP.mjs.map +1 -0
  34. package/dist/chunk-622GAQP5.js +2008 -0
  35. package/dist/chunk-622GAQP5.js.map +1 -0
  36. package/dist/chunk-6BIPAKL4.mjs +28 -0
  37. package/dist/chunk-6BIPAKL4.mjs.map +1 -0
  38. package/dist/chunk-6ZCISNAB.mjs +343 -0
  39. package/dist/chunk-6ZCISNAB.mjs.map +1 -0
  40. package/dist/chunk-72MQFHYJ.js +1429 -0
  41. package/dist/chunk-72MQFHYJ.js.map +1 -0
  42. package/dist/chunk-7557OTHW.js +62 -0
  43. package/dist/chunk-7557OTHW.js.map +1 -0
  44. package/dist/chunk-7FUV73JZ.js +981 -0
  45. package/dist/chunk-7FUV73JZ.js.map +1 -0
  46. package/dist/chunk-7RF6PVHA.mjs +324 -0
  47. package/dist/chunk-7RF6PVHA.mjs.map +1 -0
  48. package/dist/chunk-7RYCHO6D.mjs +134 -0
  49. package/dist/chunk-7RYCHO6D.mjs.map +1 -0
  50. package/dist/chunk-7UKPRW25.mjs +1999 -0
  51. package/dist/chunk-7UKPRW25.mjs.map +1 -0
  52. package/dist/chunk-7URAOG2M.js +14864 -0
  53. package/dist/chunk-7URAOG2M.js.map +1 -0
  54. package/dist/chunk-AFAO3TGS.mjs +810 -0
  55. package/dist/chunk-AFAO3TGS.mjs.map +1 -0
  56. package/dist/chunk-BYLIU6XG.js +343 -0
  57. package/dist/chunk-BYLIU6XG.js.map +1 -0
  58. package/dist/chunk-D63MUKZ6.mjs +4423 -0
  59. package/dist/chunk-D63MUKZ6.mjs.map +1 -0
  60. package/dist/chunk-DDKW2FNA.js +390 -0
  61. package/dist/chunk-DDKW2FNA.js.map +1 -0
  62. package/dist/chunk-DQYMKR27.mjs +341 -0
  63. package/dist/chunk-DQYMKR27.mjs.map +1 -0
  64. package/dist/chunk-DW5UJKHH.js +221 -0
  65. package/dist/chunk-DW5UJKHH.js.map +1 -0
  66. package/dist/chunk-EEZCR6E6.js +50 -0
  67. package/dist/chunk-EEZCR6E6.js.map +1 -0
  68. package/dist/chunk-GCJXQ4AG.mjs +59 -0
  69. package/dist/chunk-GCJXQ4AG.mjs.map +1 -0
  70. package/dist/chunk-JGNQK2G6.mjs +14845 -0
  71. package/dist/chunk-JGNQK2G6.mjs.map +1 -0
  72. package/dist/chunk-JTLOJLWQ.mjs +563 -0
  73. package/dist/chunk-JTLOJLWQ.mjs.map +1 -0
  74. package/dist/chunk-K23A4G76.mjs +202 -0
  75. package/dist/chunk-K23A4G76.mjs.map +1 -0
  76. package/dist/chunk-KKU3K7RG.js +336 -0
  77. package/dist/chunk-KKU3K7RG.js.map +1 -0
  78. package/dist/chunk-KUGMH4ZF.js +571 -0
  79. package/dist/chunk-KUGMH4ZF.js.map +1 -0
  80. package/dist/chunk-LBVWVP72.js +110 -0
  81. package/dist/chunk-LBVWVP72.js.map +1 -0
  82. package/dist/chunk-LIVWLY2P.js +138 -0
  83. package/dist/chunk-LIVWLY2P.js.map +1 -0
  84. package/dist/chunk-M2T6R7BA.mjs +1003 -0
  85. package/dist/chunk-M2T6R7BA.mjs.map +1 -0
  86. package/dist/chunk-MV3QN7PW.mjs +47 -0
  87. package/dist/chunk-MV3QN7PW.mjs.map +1 -0
  88. package/dist/chunk-OB7E654K.js +72 -0
  89. package/dist/chunk-OB7E654K.js.map +1 -0
  90. package/dist/chunk-OIIKTGRL.mjs +380 -0
  91. package/dist/chunk-OIIKTGRL.mjs.map +1 -0
  92. package/dist/chunk-P3UWIUJS.mjs +1427 -0
  93. package/dist/chunk-P3UWIUJS.mjs.map +1 -0
  94. package/dist/chunk-PKN27UMH.mjs +136 -0
  95. package/dist/chunk-PKN27UMH.mjs.map +1 -0
  96. package/dist/chunk-QXV4667R.mjs +105 -0
  97. package/dist/chunk-QXV4667R.mjs.map +1 -0
  98. package/dist/chunk-S7FRYNSU.mjs +315 -0
  99. package/dist/chunk-S7FRYNSU.mjs.map +1 -0
  100. package/dist/chunk-TFLQX7K7.mjs +68 -0
  101. package/dist/chunk-TFLQX7K7.mjs.map +1 -0
  102. package/dist/chunk-UWE5PCYJ.mjs +279 -0
  103. package/dist/chunk-UWE5PCYJ.mjs.map +1 -0
  104. package/dist/chunk-UYFDNX2F.js +4469 -0
  105. package/dist/chunk-UYFDNX2F.js.map +1 -0
  106. package/dist/chunk-W4PALSGM.js +350 -0
  107. package/dist/chunk-W4PALSGM.js.map +1 -0
  108. package/dist/chunk-WECQ6KOB.js +1008 -0
  109. package/dist/chunk-WECQ6KOB.js.map +1 -0
  110. package/dist/chunk-XQQWI6WB.js +814 -0
  111. package/dist/chunk-XQQWI6WB.js.map +1 -0
  112. package/dist/chunk-XZJOZJB6.js +140 -0
  113. package/dist/chunk-XZJOZJB6.js.map +1 -0
  114. package/dist/chunk-ZSMWDLMK.js +63 -0
  115. package/dist/chunk-ZSMWDLMK.js.map +1 -0
  116. package/dist/cli/index.js +37243 -0
  117. package/dist/cli/index.js.map +1 -0
  118. package/dist/cli/index.mjs +37209 -0
  119. package/dist/cli/index.mjs.map +1 -0
  120. package/dist/commerce/index.d.mts +170 -0
  121. package/dist/commerce/index.d.ts +170 -0
  122. package/dist/commerce/index.js +174 -0
  123. package/dist/commerce/index.js.map +1 -0
  124. package/dist/commerce/index.mjs +5 -0
  125. package/dist/commerce/index.mjs.map +1 -0
  126. package/dist/commerce/server.d.mts +107 -0
  127. package/dist/commerce/server.d.ts +107 -0
  128. package/dist/commerce/server.js +187 -0
  129. package/dist/commerce/server.js.map +1 -0
  130. package/dist/commerce/server.mjs +177 -0
  131. package/dist/commerce/server.mjs.map +1 -0
  132. package/dist/config/index.d.mts +43 -0
  133. package/dist/config/index.d.ts +43 -0
  134. package/dist/config/index.js +66 -0
  135. package/dist/config/index.js.map +1 -0
  136. package/dist/config/index.mjs +64 -0
  137. package/dist/config/index.mjs.map +1 -0
  138. package/dist/engage/index.d.mts +33 -0
  139. package/dist/engage/index.d.ts +33 -0
  140. package/dist/engage/index.js +22 -0
  141. package/dist/engage/index.js.map +1 -0
  142. package/dist/engage/index.mjs +5 -0
  143. package/dist/engage/index.mjs.map +1 -0
  144. package/dist/forms/index.d.mts +437 -0
  145. package/dist/forms/index.d.ts +437 -0
  146. package/dist/forms/index.js +1168 -0
  147. package/dist/forms/index.js.map +1 -0
  148. package/dist/forms/index.mjs +1142 -0
  149. package/dist/forms/index.mjs.map +1 -0
  150. package/dist/generators-2XKQMPKH.mjs +4 -0
  151. package/dist/generators-2XKQMPKH.mjs.map +1 -0
  152. package/dist/generators-DTMO36DV.js +33 -0
  153. package/dist/generators-DTMO36DV.js.map +1 -0
  154. package/dist/images/index.d.mts +4 -0
  155. package/dist/images/index.d.ts +4 -0
  156. package/dist/images/index.js +46 -0
  157. package/dist/images/index.js.map +1 -0
  158. package/dist/images/index.mjs +5 -0
  159. package/dist/images/index.mjs.map +1 -0
  160. package/dist/images/server.d.mts +69 -0
  161. package/dist/images/server.d.ts +69 -0
  162. package/dist/images/server.js +21 -0
  163. package/dist/images/server.js.map +1 -0
  164. package/dist/images/server.mjs +4 -0
  165. package/dist/images/server.mjs.map +1 -0
  166. package/dist/index.d.mts +846 -0
  167. package/dist/index.d.ts +846 -0
  168. package/dist/index.js +2623 -0
  169. package/dist/index.js.map +1 -0
  170. package/dist/index.mjs +2416 -0
  171. package/dist/index.mjs.map +1 -0
  172. package/dist/layout/index.d.mts +53 -0
  173. package/dist/layout/index.d.ts +53 -0
  174. package/dist/layout/index.js +187 -0
  175. package/dist/layout/index.js.map +1 -0
  176. package/dist/layout/index.mjs +185 -0
  177. package/dist/layout/index.mjs.map +1 -0
  178. package/dist/llms/index.d.mts +448 -0
  179. package/dist/llms/index.d.ts +448 -0
  180. package/dist/llms/index.js +581 -0
  181. package/dist/llms/index.js.map +1 -0
  182. package/dist/llms/index.mjs +529 -0
  183. package/dist/llms/index.mjs.map +1 -0
  184. package/dist/manifest/index.d.mts +62 -0
  185. package/dist/manifest/index.d.ts +62 -0
  186. package/dist/manifest/index.js +85 -0
  187. package/dist/manifest/index.js.map +1 -0
  188. package/dist/manifest/index.mjs +83 -0
  189. package/dist/manifest/index.mjs.map +1 -0
  190. package/dist/middleware/index.d.mts +63 -0
  191. package/dist/middleware/index.d.ts +63 -0
  192. package/dist/middleware/index.js +54 -0
  193. package/dist/middleware/index.js.map +1 -0
  194. package/dist/middleware/index.mjs +51 -0
  195. package/dist/middleware/index.mjs.map +1 -0
  196. package/dist/migrator-2MQHOFDQ.mjs +4 -0
  197. package/dist/migrator-2MQHOFDQ.mjs.map +1 -0
  198. package/dist/migrator-THJCF6MZ.js +37 -0
  199. package/dist/migrator-THJCF6MZ.js.map +1 -0
  200. package/dist/redirects/index.d.mts +78 -0
  201. package/dist/redirects/index.d.ts +78 -0
  202. package/dist/redirects/index.js +26 -0
  203. package/dist/redirects/index.js.map +1 -0
  204. package/dist/redirects/index.mjs +5 -0
  205. package/dist/redirects/index.mjs.map +1 -0
  206. package/dist/reputation/index.d.mts +57 -0
  207. package/dist/reputation/index.d.ts +57 -0
  208. package/dist/reputation/index.js +21 -0
  209. package/dist/reputation/index.js.map +1 -0
  210. package/dist/reputation/index.mjs +4 -0
  211. package/dist/reputation/index.mjs.map +1 -0
  212. package/dist/robots/index.d.mts +38 -0
  213. package/dist/robots/index.d.ts +38 -0
  214. package/dist/robots/index.js +52 -0
  215. package/dist/robots/index.js.map +1 -0
  216. package/dist/robots/index.mjs +50 -0
  217. package/dist/robots/index.mjs.map +1 -0
  218. package/dist/routing-B5XS-6_W.d.mts +118 -0
  219. package/dist/routing-DZYzyDHw.d.ts +118 -0
  220. package/dist/scanner-GAF5PO5F.js +53 -0
  221. package/dist/scanner-GAF5PO5F.js.map +1 -0
  222. package/dist/scanner-LKJKW7IT.mjs +4 -0
  223. package/dist/scanner-LKJKW7IT.mjs.map +1 -0
  224. package/dist/securityHeaders-nwZ6nP4g.d.mts +24 -0
  225. package/dist/securityHeaders-nwZ6nP4g.d.ts +24 -0
  226. package/dist/seo/index.d.mts +600 -0
  227. package/dist/seo/index.d.ts +600 -0
  228. package/dist/seo/index.js +883 -0
  229. package/dist/seo/index.js.map +1 -0
  230. package/dist/seo/index.mjs +773 -0
  231. package/dist/seo/index.mjs.map +1 -0
  232. package/dist/seo/register-sitemap-cli.js +151 -0
  233. package/dist/seo/register-sitemap-cli.js.map +1 -0
  234. package/dist/seo/register-sitemap-cli.mjs +144 -0
  235. package/dist/seo/register-sitemap-cli.mjs.map +1 -0
  236. package/dist/seo/server.d.mts +107 -0
  237. package/dist/seo/server.d.ts +107 -0
  238. package/dist/seo/server.js +207 -0
  239. package/dist/seo/server.js.map +1 -0
  240. package/dist/seo/server.mjs +186 -0
  241. package/dist/seo/server.mjs.map +1 -0
  242. package/dist/server-api-EWXKOQZA.mjs +4 -0
  243. package/dist/server-api-EWXKOQZA.mjs.map +1 -0
  244. package/dist/server-api-GJPNRYUP.js +81 -0
  245. package/dist/server-api-GJPNRYUP.js.map +1 -0
  246. package/dist/setup/client.d.mts +60 -0
  247. package/dist/setup/client.d.ts +60 -0
  248. package/dist/setup/client.js +31 -0
  249. package/dist/setup/client.js.map +1 -0
  250. package/dist/setup/client.mjs +6 -0
  251. package/dist/setup/client.mjs.map +1 -0
  252. package/dist/setup/index.d.mts +5 -0
  253. package/dist/setup/index.d.ts +5 -0
  254. package/dist/setup/index.js +35 -0
  255. package/dist/setup/index.js.map +1 -0
  256. package/dist/setup/index.mjs +6 -0
  257. package/dist/setup/index.mjs.map +1 -0
  258. package/dist/setup/server.d.mts +14 -0
  259. package/dist/setup/server.d.ts +14 -0
  260. package/dist/setup/server.js +13 -0
  261. package/dist/setup/server.js.map +1 -0
  262. package/dist/setup/server.mjs +4 -0
  263. package/dist/setup/server.mjs.map +1 -0
  264. package/dist/site-config/index.d.mts +24 -0
  265. package/dist/site-config/index.d.ts +24 -0
  266. package/dist/site-config/index.js +17 -0
  267. package/dist/site-config/index.js.map +1 -0
  268. package/dist/site-config/index.mjs +4 -0
  269. package/dist/site-config/index.mjs.map +1 -0
  270. package/dist/sitemap/index.d.mts +96 -0
  271. package/dist/sitemap/index.d.ts +96 -0
  272. package/dist/sitemap/index.js +288 -0
  273. package/dist/sitemap/index.js.map +1 -0
  274. package/dist/sitemap/index.mjs +285 -0
  275. package/dist/sitemap/index.mjs.map +1 -0
  276. package/dist/socket-loader-J26QHHOB.js +16 -0
  277. package/dist/socket-loader-J26QHHOB.js.map +1 -0
  278. package/dist/socket-loader-R7S2YJ2J.mjs +14 -0
  279. package/dist/socket-loader-R7S2YJ2J.mjs.map +1 -0
  280. package/dist/types-0dmq3k20.d.mts +168 -0
  281. package/dist/types-0dmq3k20.d.ts +168 -0
  282. package/dist/types-Blb2QNkV.d.mts +263 -0
  283. package/dist/types-Blb2QNkV.d.ts +263 -0
  284. package/dist/types-BnCwwUX3.d.mts +250 -0
  285. package/dist/types-BnCwwUX3.d.ts +250 -0
  286. package/dist/types-CGlnp43R.d.mts +312 -0
  287. package/dist/types-CGlnp43R.d.ts +312 -0
  288. package/dist/types-D08004rU.d.mts +179 -0
  289. package/dist/types-D08004rU.d.ts +179 -0
  290. package/dist/types-DNSYU7qI.d.mts +127 -0
  291. package/dist/types-DNSYU7qI.d.ts +127 -0
  292. package/dist/types-KZP_VWZp.d.mts +266 -0
  293. package/dist/types-KZP_VWZp.d.ts +266 -0
  294. package/dist/useEventModal-BVTx69XE.d.mts +274 -0
  295. package/dist/useEventModal-Dx1dItTJ.d.ts +274 -0
  296. package/dist/web-vitals-444RLW3B.js +252 -0
  297. package/dist/web-vitals-444RLW3B.js.map +1 -0
  298. package/dist/web-vitals-KPICZIEF.mjs +241 -0
  299. package/dist/web-vitals-KPICZIEF.mjs.map +1 -0
  300. package/package.json +192 -0
@@ -0,0 +1,4469 @@
1
+ 'use client';
2
+ 'use strict';
3
+
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+ var React5 = require('react');
6
+
7
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
+
9
+ var React5__default = /*#__PURE__*/_interopDefault(React5);
10
+
11
+ // src/commerce/utils.ts
12
+ function formatPrice(amount, currency = "USD") {
13
+ return new Intl.NumberFormat("en-US", {
14
+ style: "currency",
15
+ currency
16
+ }).format(amount);
17
+ }
18
+ function formatDate(dateString) {
19
+ const date = new Date(dateString);
20
+ return new Intl.DateTimeFormat("en-US", {
21
+ weekday: "short",
22
+ month: "short",
23
+ day: "numeric",
24
+ year: "numeric"
25
+ }).format(date);
26
+ }
27
+ function formatDateTime(dateString) {
28
+ const date = new Date(dateString);
29
+ return new Intl.DateTimeFormat("en-US", {
30
+ weekday: "short",
31
+ month: "short",
32
+ day: "numeric",
33
+ year: "numeric",
34
+ hour: "numeric",
35
+ minute: "2-digit"
36
+ }).format(date);
37
+ }
38
+ function formatTime(dateString) {
39
+ const date = new Date(dateString);
40
+ return new Intl.DateTimeFormat("en-US", {
41
+ hour: "numeric",
42
+ minute: "2-digit"
43
+ }).format(date);
44
+ }
45
+ function formatDateRange(startDate, endDate) {
46
+ const start = new Date(startDate);
47
+ const end = endDate ? new Date(endDate) : null;
48
+ const startFormatted = formatDateTime(startDate);
49
+ if (!end) return startFormatted;
50
+ if (start.toDateString() === end.toDateString()) {
51
+ return `${startFormatted} - ${formatTime(endDate)}`;
52
+ }
53
+ return `${startFormatted} - ${formatDateTime(endDate)}`;
54
+ }
55
+ function getRelativeTimeUntil(dateString) {
56
+ const date = new Date(dateString);
57
+ const now = /* @__PURE__ */ new Date();
58
+ const diffMs = date.getTime() - now.getTime();
59
+ const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
60
+ if (diffDays < 0) return "Past";
61
+ if (diffDays === 0) return "Today";
62
+ if (diffDays === 1) return "Tomorrow";
63
+ if (diffDays < 7) return `In ${diffDays} days`;
64
+ if (diffDays < 30) {
65
+ const weeks = Math.floor(diffDays / 7);
66
+ return `In ${weeks} week${weeks > 1 ? "s" : ""}`;
67
+ }
68
+ if (diffDays < 365) {
69
+ const months = Math.floor(diffDays / 30);
70
+ return `In ${months} month${months > 1 ? "s" : ""}`;
71
+ }
72
+ return formatDate(dateString);
73
+ }
74
+ function getSpotsRemaining(capacity, registrations = 0) {
75
+ if (capacity == null) return null;
76
+ return Math.max(0, capacity - registrations);
77
+ }
78
+ function isEventSoldOut(capacity, registrations = 0) {
79
+ const remaining = getSpotsRemaining(capacity, registrations);
80
+ return remaining !== null && remaining <= 0;
81
+ }
82
+ function getOfferingUrl(slug, type, basePaths) {
83
+ const defaults = {
84
+ product: "/shop",
85
+ service: "/services",
86
+ event: "/events",
87
+ class: "/classes"
88
+ };
89
+ const paths = { ...defaults, ...basePaths };
90
+ const base = paths[type] || "/offerings";
91
+ return `${base}/${slug}`;
92
+ }
93
+
94
+ // src/commerce/api.ts
95
+ function getApiConfig() {
96
+ const apiUrl = typeof window !== "undefined" ? window.__SITE_KIT_API_URL__ || "https://api.uptrademedia.com" : "https://api.uptrademedia.com";
97
+ const apiKey = typeof window !== "undefined" ? window.__SITE_KIT_API_KEY__ || "" : "";
98
+ return { apiUrl, apiKey };
99
+ }
100
+ async function apiPost(endpoint, body = {}) {
101
+ const { apiUrl, apiKey } = getApiConfig();
102
+ if (!apiKey) {
103
+ console.error("[Commerce] No API key configured");
104
+ return null;
105
+ }
106
+ try {
107
+ const response = await fetch(`${apiUrl}${endpoint}`, {
108
+ method: "POST",
109
+ headers: {
110
+ "Content-Type": "application/json",
111
+ "x-api-key": apiKey
112
+ },
113
+ body: JSON.stringify(body)
114
+ });
115
+ if (!response.ok) {
116
+ const text = await response.text();
117
+ let body2 = null;
118
+ try {
119
+ body2 = text ? JSON.parse(text) : null;
120
+ } catch {
121
+ body2 = text;
122
+ }
123
+ console.error(`[Commerce] API error:`, response.status, response.statusText || "Unknown", body2);
124
+ return null;
125
+ }
126
+ return await response.json();
127
+ } catch (error) {
128
+ console.error("[Commerce] Network error:", error);
129
+ return null;
130
+ }
131
+ }
132
+ async function fetchOfferings(options = {}) {
133
+ const result = await apiPost(
134
+ "/api/public/commerce/offerings",
135
+ {
136
+ type: options.type,
137
+ category: options.category,
138
+ status: options.status || "active",
139
+ limit: options.limit,
140
+ offset: options.offset,
141
+ orderBy: options.orderBy || "sort_order",
142
+ order: options.order || "asc"
143
+ }
144
+ );
145
+ return result?.offerings || [];
146
+ }
147
+ async function fetchOffering(slug) {
148
+ const result = await apiPost(
149
+ "/api/public/commerce/offering",
150
+ { slug }
151
+ );
152
+ if (!result) return null;
153
+ const offering = result.offering ?? result;
154
+ return offering?.id ? offering : null;
155
+ }
156
+ async function fetchLatestOffering(type, category) {
157
+ if (type === "product") {
158
+ const { products } = await fetchProductsPublic({
159
+ category,
160
+ limit: 1,
161
+ orderBy: "created_at",
162
+ order: "desc"
163
+ });
164
+ return products[0] || null;
165
+ }
166
+ const result = await apiPost(
167
+ "/api/public/commerce/offerings",
168
+ {
169
+ type,
170
+ category,
171
+ status: "active",
172
+ limit: 1,
173
+ orderBy: "created_at",
174
+ order: "desc"
175
+ }
176
+ );
177
+ return result?.offerings?.[0] || null;
178
+ }
179
+ async function fetchUpcomingEvents(options = {}) {
180
+ const result = await apiPost(
181
+ "/api/public/commerce/events",
182
+ {
183
+ type: "event",
184
+ category: options.category,
185
+ limit: options.limit,
186
+ includePast: options.past
187
+ }
188
+ );
189
+ return result?.events || [];
190
+ }
191
+ async function fetchNextEvent(category) {
192
+ const events = await fetchUpcomingEvents({ limit: 1, category });
193
+ return events[0] || null;
194
+ }
195
+ async function fetchProducts(options = {}) {
196
+ const { products } = await fetchProductsPublic({
197
+ category: options.category,
198
+ limit: options.limit,
199
+ offset: options.offset,
200
+ orderBy: options.orderBy || "sort_order",
201
+ order: options.order || "asc",
202
+ search: options.search
203
+ });
204
+ return products;
205
+ }
206
+ async function fetchServices(options = {}) {
207
+ return fetchOfferings({ ...options, type: "service" });
208
+ }
209
+ async function fetchProductsPublic(options = {}) {
210
+ const result = await apiPost(
211
+ "/api/public/commerce/products",
212
+ options
213
+ );
214
+ return {
215
+ products: result?.products || [],
216
+ total: result?.total || 0
217
+ };
218
+ }
219
+ async function fetchProductBySlug(slug) {
220
+ const result = await apiPost(
221
+ "/api/public/commerce/product",
222
+ { slug }
223
+ );
224
+ return result?.product || null;
225
+ }
226
+ async function fetchCategories() {
227
+ const result = await apiPost(
228
+ "/api/public/commerce/categories",
229
+ {}
230
+ );
231
+ return result?.categories || [];
232
+ }
233
+ async function fetchShippingRates(shippingAddress, offerings) {
234
+ const result = await apiPost(
235
+ "/api/public/commerce/shipping-rates",
236
+ {
237
+ shippingAddress: {
238
+ street1: shippingAddress.street1,
239
+ street2: shippingAddress.street2,
240
+ city: shippingAddress.city,
241
+ state: shippingAddress.state,
242
+ zip: shippingAddress.zip,
243
+ country: shippingAddress.country || "US"
244
+ },
245
+ offerings
246
+ }
247
+ );
248
+ return Array.isArray(result) ? result : [];
249
+ }
250
+ async function validateAddress(address) {
251
+ const result = await apiPost(
252
+ "/api/public/commerce/validate-address",
253
+ {
254
+ street1: address.street1,
255
+ street2: address.street2,
256
+ city: address.city,
257
+ state: address.state,
258
+ zip: address.zip,
259
+ country: address.country || "US"
260
+ }
261
+ );
262
+ return result || { isValid: true, messages: [] };
263
+ }
264
+ async function fetchActiveProcessor() {
265
+ const { apiUrl, apiKey } = getApiConfig();
266
+ if (!apiKey) return null;
267
+ try {
268
+ const response = await fetch(`${apiUrl}/api/public/commerce/processor`, {
269
+ method: "POST",
270
+ headers: {
271
+ "Content-Type": "application/json",
272
+ "x-api-key": apiKey
273
+ },
274
+ body: JSON.stringify({})
275
+ });
276
+ if (!response.ok) return null;
277
+ const data = await response.json();
278
+ return data?.processor || null;
279
+ } catch {
280
+ return null;
281
+ }
282
+ }
283
+ async function registerForEvent(eventId, scheduleId, customer) {
284
+ const { apiUrl, apiKey } = getApiConfig();
285
+ const analyticsSessionId = typeof sessionStorage !== "undefined" ? sessionStorage.getItem("_uptrade_sid") : null;
286
+ try {
287
+ const response = await fetch(`${apiUrl}/api/public/commerce/register`, {
288
+ method: "POST",
289
+ headers: {
290
+ "Content-Type": "application/json",
291
+ "x-api-key": apiKey
292
+ },
293
+ body: JSON.stringify({
294
+ offeringId: eventId,
295
+ scheduleId,
296
+ customer,
297
+ analyticsSessionId
298
+ // Pass for conversion tracking
299
+ })
300
+ });
301
+ if (!response.ok) {
302
+ const error = await response.json();
303
+ return { success: false, error: error.message || "Registration failed" };
304
+ }
305
+ const result = await response.json();
306
+ return {
307
+ success: true,
308
+ sale_id: result.sale_id,
309
+ confirmation_number: result.confirmation_number
310
+ };
311
+ } catch (error) {
312
+ return { success: false, error: "Network error. Please try again." };
313
+ }
314
+ }
315
+ async function fetchProcessorConfig() {
316
+ const { apiUrl, apiKey } = getApiConfig();
317
+ if (!apiKey) return null;
318
+ try {
319
+ const response = await fetch(`${apiUrl}/api/public/commerce/processor-config`, {
320
+ method: "POST",
321
+ headers: {
322
+ "Content-Type": "application/json",
323
+ "x-api-key": apiKey
324
+ },
325
+ body: JSON.stringify({})
326
+ });
327
+ if (!response.ok) return null;
328
+ return await response.json();
329
+ } catch {
330
+ return null;
331
+ }
332
+ }
333
+ async function createCheckoutSession(optionsOrOfferingId, legacyOptions) {
334
+ const { apiUrl, apiKey } = getApiConfig();
335
+ const options = typeof optionsOrOfferingId === "string" ? { offeringId: optionsOrOfferingId, ...legacyOptions } : optionsOrOfferingId;
336
+ const analyticsSessionId = typeof sessionStorage !== "undefined" ? sessionStorage.getItem("_uptrade_sid") : null;
337
+ try {
338
+ const response = await fetch(`${apiUrl}/api/public/commerce/checkout`, {
339
+ method: "POST",
340
+ headers: {
341
+ "Content-Type": "application/json",
342
+ "x-api-key": apiKey
343
+ },
344
+ body: JSON.stringify({
345
+ ...options,
346
+ analyticsSessionId,
347
+ // Pass for conversion tracking
348
+ successUrl: options.successUrl || (typeof window !== "undefined" ? window.location.href : ""),
349
+ cancelUrl: options.cancelUrl || (typeof window !== "undefined" ? window.location.href : "")
350
+ })
351
+ });
352
+ if (!response.ok) {
353
+ const text = await response.text();
354
+ let body = {};
355
+ try {
356
+ body = JSON.parse(text);
357
+ } catch {
358
+ }
359
+ const errObj = body?.error && typeof body.error === "object" ? body.error : body;
360
+ const message = (typeof body?.message === "string" ? body.message : null) || (typeof errObj?.message === "string" ? errObj.message : null) || (typeof errObj?.detail === "string" ? errObj.detail : null) || (typeof body?.error === "string" ? body.error : null) || "Payment could not be processed. Please try again or use a different card.";
361
+ if (typeof console !== "undefined" && console.error) {
362
+ console.error("[Commerce] Checkout failed:", response.status, message, body);
363
+ }
364
+ return { success: false, error: message };
365
+ }
366
+ const result = await response.json();
367
+ return {
368
+ success: true,
369
+ payment_url: result.checkout_url,
370
+ checkout_url: result.checkout_url,
371
+ sale_id: result.sale_id,
372
+ confirmation_number: result.confirmation_number
373
+ };
374
+ } catch (error) {
375
+ return { success: false, error: "Network error. Please try again." };
376
+ }
377
+ }
378
+ function OfferingCard({
379
+ offering,
380
+ variant = "card",
381
+ showImage = true,
382
+ showPrice = true,
383
+ showDescription = true,
384
+ showCta = true,
385
+ ctaText,
386
+ onCtaClick,
387
+ className = "",
388
+ imageClassName = "",
389
+ titleClassName = "",
390
+ priceClassName = "",
391
+ descriptionClassName = "",
392
+ ctaClassName = ""
393
+ }) {
394
+ const isEvent = offering.type === "event" || offering.type === "class";
395
+ const nextSchedule = offering.schedules?.[0] || offering.next_schedule;
396
+ const defaultCtaText = {
397
+ product: "Buy Now",
398
+ service: "Book Now",
399
+ class: "Register",
400
+ event: "Get Tickets",
401
+ subscription: "Subscribe"
402
+ }[offering.type] || "View Details";
403
+ const handleClick = () => {
404
+ if (onCtaClick) {
405
+ onCtaClick(offering);
406
+ } else if (typeof window !== "undefined") {
407
+ const basePath = offering.type === "event" ? "/events" : offering.type === "product" ? "/shop" : "/services";
408
+ window.location.href = `${basePath}/${offering.slug}`;
409
+ }
410
+ };
411
+ if (variant === "minimal") {
412
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-offering-minimal ${className}`, children: [
413
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: `site-kit-offering-title ${titleClassName}`, children: offering.name }),
414
+ showPrice && offering.price_is_public && offering.price != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `site-kit-offering-price ${priceClassName}`, children: formatPrice(offering.price, offering.currency) }),
415
+ showCta && /* @__PURE__ */ jsxRuntime.jsx(
416
+ "button",
417
+ {
418
+ onClick: handleClick,
419
+ className: `site-kit-offering-cta ${ctaClassName}`,
420
+ children: ctaText || defaultCtaText
421
+ }
422
+ )
423
+ ] });
424
+ }
425
+ if (variant === "horizontal") {
426
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-offering-horizontal ${className}`, style: {
427
+ display: "flex",
428
+ gap: "1rem",
429
+ alignItems: "flex-start"
430
+ }, children: [
431
+ showImage && offering.featured_image_url && /* @__PURE__ */ jsxRuntime.jsx(
432
+ "img",
433
+ {
434
+ src: offering.featured_image_url,
435
+ alt: offering.name,
436
+ className: `site-kit-offering-image ${imageClassName}`,
437
+ style: {
438
+ width: "120px",
439
+ height: "120px",
440
+ objectFit: "cover",
441
+ borderRadius: "8px"
442
+ }
443
+ }
444
+ ),
445
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1 }, children: [
446
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: `site-kit-offering-title ${titleClassName}`, style: {
447
+ margin: 0,
448
+ fontSize: "1.125rem",
449
+ fontWeight: 600
450
+ }, children: offering.name }),
451
+ isEvent && nextSchedule && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "site-kit-offering-date", style: {
452
+ color: "#666",
453
+ fontSize: "0.875rem",
454
+ marginTop: "0.25rem"
455
+ }, children: [
456
+ formatDate(nextSchedule.starts_at),
457
+ offering.location && ` \u2022 ${offering.location}`
458
+ ] }),
459
+ showDescription && offering.short_description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `site-kit-offering-description ${descriptionClassName}`, style: {
460
+ color: "#666",
461
+ margin: "0.5rem 0",
462
+ fontSize: "0.875rem"
463
+ }, children: offering.short_description }),
464
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "1rem", marginTop: "0.5rem" }, children: [
465
+ showPrice && offering.price_is_public && offering.price != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `site-kit-offering-price ${priceClassName}`, style: {
466
+ fontWeight: 600,
467
+ color: "#333"
468
+ }, children: [
469
+ formatPrice(offering.price, offering.currency),
470
+ offering.compare_at_price && /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
471
+ textDecoration: "line-through",
472
+ color: "#999",
473
+ marginLeft: "0.5rem",
474
+ fontWeight: 400
475
+ }, children: formatPrice(offering.compare_at_price, offering.currency) })
476
+ ] }),
477
+ showCta && /* @__PURE__ */ jsxRuntime.jsx(
478
+ "button",
479
+ {
480
+ onClick: handleClick,
481
+ className: `site-kit-offering-cta ${ctaClassName}`,
482
+ style: {
483
+ padding: "0.5rem 1rem",
484
+ borderRadius: "6px",
485
+ border: "none",
486
+ background: "#2563eb",
487
+ color: "white",
488
+ cursor: "pointer",
489
+ fontWeight: 500
490
+ },
491
+ children: ctaText || defaultCtaText
492
+ }
493
+ )
494
+ ] })
495
+ ] })
496
+ ] });
497
+ }
498
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-offering-card ${className}`, style: {
499
+ borderRadius: "12px",
500
+ overflow: "hidden",
501
+ boxShadow: "0 1px 3px rgba(0,0,0,0.1)",
502
+ background: "white"
503
+ }, children: [
504
+ showImage && offering.featured_image_url && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative" }, children: [
505
+ /* @__PURE__ */ jsxRuntime.jsx(
506
+ "img",
507
+ {
508
+ src: offering.featured_image_url,
509
+ alt: offering.name,
510
+ className: `site-kit-offering-image ${imageClassName}`,
511
+ style: {
512
+ width: "100%",
513
+ height: "200px",
514
+ objectFit: "cover"
515
+ }
516
+ }
517
+ ),
518
+ offering.compare_at_price && offering.price_is_public && /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
519
+ position: "absolute",
520
+ top: "12px",
521
+ right: "12px",
522
+ background: "#ef4444",
523
+ color: "white",
524
+ padding: "4px 8px",
525
+ borderRadius: "4px",
526
+ fontSize: "0.75rem",
527
+ fontWeight: 600
528
+ }, children: "Sale" })
529
+ ] }),
530
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "1rem" }, children: [
531
+ isEvent && nextSchedule && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "site-kit-offering-date", style: {
532
+ color: "#2563eb",
533
+ fontSize: "0.875rem",
534
+ fontWeight: 500,
535
+ marginBottom: "0.25rem"
536
+ }, children: formatDate(nextSchedule.starts_at) }),
537
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: `site-kit-offering-title ${titleClassName}`, style: {
538
+ margin: 0,
539
+ fontSize: "1.125rem",
540
+ fontWeight: 600,
541
+ color: "#111"
542
+ }, children: offering.name }),
543
+ isEvent && offering.location && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { color: "#666", fontSize: "0.875rem", marginTop: "0.25rem" }, children: [
544
+ "\u{1F4CD} ",
545
+ offering.location
546
+ ] }),
547
+ showDescription && offering.short_description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `site-kit-offering-description ${descriptionClassName}`, style: {
548
+ color: "#666",
549
+ margin: "0.75rem 0",
550
+ fontSize: "0.875rem",
551
+ lineHeight: 1.5
552
+ }, children: offering.short_description }),
553
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
554
+ display: "flex",
555
+ alignItems: "center",
556
+ justifyContent: "space-between",
557
+ marginTop: "1rem"
558
+ }, children: [
559
+ showPrice && offering.price_is_public && offering.price != null ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-offering-price ${priceClassName}`, children: [
560
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 600, fontSize: "1.25rem", color: "#111" }, children: formatPrice(offering.price, offering.currency) }),
561
+ offering.compare_at_price && /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
562
+ textDecoration: "line-through",
563
+ color: "#999",
564
+ marginLeft: "0.5rem",
565
+ fontSize: "0.875rem"
566
+ }, children: formatPrice(offering.compare_at_price, offering.currency) })
567
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", {}),
568
+ showCta && /* @__PURE__ */ jsxRuntime.jsx(
569
+ "button",
570
+ {
571
+ onClick: handleClick,
572
+ className: `site-kit-offering-cta ${ctaClassName}`,
573
+ style: {
574
+ padding: "0.625rem 1.25rem",
575
+ borderRadius: "6px",
576
+ border: "none",
577
+ background: "#2563eb",
578
+ color: "white",
579
+ cursor: "pointer",
580
+ fontWeight: 500,
581
+ fontSize: "0.875rem"
582
+ },
583
+ children: ctaText || defaultCtaText
584
+ }
585
+ )
586
+ ] })
587
+ ] })
588
+ ] });
589
+ }
590
+ function OfferingList({
591
+ // Data options
592
+ offerings: propOfferings,
593
+ type,
594
+ category,
595
+ limit,
596
+ status = "active",
597
+ // Display options
598
+ layout = "grid",
599
+ columns = 3,
600
+ cardVariant = "card",
601
+ showFilters = false,
602
+ emptyMessage = "No items found.",
603
+ // Card options
604
+ showImage = true,
605
+ showPrice = true,
606
+ showDescription = true,
607
+ showCta = true,
608
+ ctaText,
609
+ onCtaClick,
610
+ // Styling
611
+ className = "",
612
+ cardClassName = "",
613
+ filterClassName = "",
614
+ // Custom render
615
+ renderCard,
616
+ renderEmpty
617
+ }) {
618
+ const [offerings, setOfferings] = React5.useState(propOfferings || []);
619
+ const [loading, setLoading] = React5.useState(!propOfferings);
620
+ const [error, setError] = React5.useState(null);
621
+ const [activeFilter, setActiveFilter] = React5.useState(null);
622
+ React5.useEffect(() => {
623
+ if (propOfferings) {
624
+ setOfferings(propOfferings);
625
+ return;
626
+ }
627
+ async function load() {
628
+ setLoading(true);
629
+ setError(null);
630
+ try {
631
+ let data;
632
+ if (type === "product" || Array.isArray(type) && type.includes("product")) {
633
+ const { products } = await fetchProductsPublic({ category, limit, orderBy: "sort_order", order: "asc" });
634
+ data = products;
635
+ } else if (type === "event") {
636
+ data = await fetchUpcomingEvents({ category, limit });
637
+ } else {
638
+ data = await fetchOfferings({ type, category, limit, status });
639
+ }
640
+ setOfferings(data);
641
+ } catch (e) {
642
+ console.error("Failed to load offerings:", e);
643
+ setError("Failed to load items.");
644
+ } finally {
645
+ setLoading(false);
646
+ }
647
+ }
648
+ load();
649
+ }, [propOfferings, type, category, limit, status]);
650
+ const categories = React5.useMemo(() => {
651
+ const cats = offerings.filter((o) => o.category).map((o) => o.category);
652
+ return Array.from(new Map(cats.map((c) => [c.id, c])).values());
653
+ }, [offerings]);
654
+ const filteredOfferings = React5.useMemo(() => {
655
+ if (!activeFilter) return offerings;
656
+ return offerings.filter((o) => o.category?.id === activeFilter);
657
+ }, [offerings, activeFilter]);
658
+ if (loading) {
659
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-offerings-loading ${className}`, style: {
660
+ display: "flex",
661
+ justifyContent: "center",
662
+ padding: "2rem"
663
+ }, children: [
664
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
665
+ width: "40px",
666
+ height: "40px",
667
+ border: "3px solid #e5e7eb",
668
+ borderTopColor: "#2563eb",
669
+ borderRadius: "50%",
670
+ animation: "spin 1s linear infinite"
671
+ } }),
672
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
673
+ @keyframes spin {
674
+ to { transform: rotate(360deg); }
675
+ }
676
+ ` })
677
+ ] });
678
+ }
679
+ if (error) {
680
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `site-kit-offerings-error ${className}`, style: {
681
+ textAlign: "center",
682
+ padding: "2rem",
683
+ color: "#ef4444"
684
+ }, children: error });
685
+ }
686
+ if (filteredOfferings.length === 0) {
687
+ if (renderEmpty) {
688
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderEmpty() });
689
+ }
690
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `site-kit-offerings-empty ${className}`, style: {
691
+ textAlign: "center",
692
+ padding: "2rem",
693
+ color: "#666"
694
+ }, children: emptyMessage });
695
+ }
696
+ const gridStyles = layout === "grid" ? {
697
+ display: "grid",
698
+ gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,
699
+ gap: "1.5rem"
700
+ } : {
701
+ display: "flex",
702
+ flexDirection: "column",
703
+ gap: "1rem"
704
+ };
705
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-offerings ${className}`, children: [
706
+ showFilters && categories.length > 1 && /* @__PURE__ */ jsxRuntime.jsxs(
707
+ "div",
708
+ {
709
+ className: `site-kit-offerings-filters ${filterClassName}`,
710
+ style: {
711
+ display: "flex",
712
+ gap: "0.5rem",
713
+ marginBottom: "1.5rem",
714
+ flexWrap: "wrap"
715
+ },
716
+ children: [
717
+ /* @__PURE__ */ jsxRuntime.jsx(
718
+ "button",
719
+ {
720
+ onClick: () => setActiveFilter(null),
721
+ style: {
722
+ padding: "0.5rem 1rem",
723
+ borderRadius: "9999px",
724
+ border: "1px solid",
725
+ borderColor: activeFilter === null ? "#2563eb" : "#e5e7eb",
726
+ background: activeFilter === null ? "#2563eb" : "white",
727
+ color: activeFilter === null ? "white" : "#333",
728
+ cursor: "pointer",
729
+ fontSize: "0.875rem"
730
+ },
731
+ children: "All"
732
+ }
733
+ ),
734
+ categories.map((cat) => /* @__PURE__ */ jsxRuntime.jsx(
735
+ "button",
736
+ {
737
+ onClick: () => setActiveFilter(cat.id),
738
+ style: {
739
+ padding: "0.5rem 1rem",
740
+ borderRadius: "9999px",
741
+ border: "1px solid",
742
+ borderColor: activeFilter === cat.id ? "#2563eb" : "#e5e7eb",
743
+ background: activeFilter === cat.id ? "#2563eb" : "white",
744
+ color: activeFilter === cat.id ? "white" : "#333",
745
+ cursor: "pointer",
746
+ fontSize: "0.875rem"
747
+ },
748
+ children: cat.name
749
+ },
750
+ cat.id
751
+ ))
752
+ ]
753
+ }
754
+ ),
755
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "site-kit-offerings-grid", style: gridStyles, children: filteredOfferings.map((offering) => renderCard ? renderCard(offering) : /* @__PURE__ */ jsxRuntime.jsx(
756
+ OfferingCard,
757
+ {
758
+ offering,
759
+ variant: layout === "list" ? "horizontal" : cardVariant,
760
+ showImage,
761
+ showPrice,
762
+ showDescription,
763
+ showCta,
764
+ ctaText,
765
+ onCtaClick,
766
+ className: cardClassName
767
+ },
768
+ offering.id
769
+ )) })
770
+ ] });
771
+ }
772
+ function EventTile({
773
+ event,
774
+ variant = "standard",
775
+ showDate = true,
776
+ showTime = true,
777
+ showLocation = true,
778
+ showCapacity = true,
779
+ showPrice = true,
780
+ showCta = true,
781
+ ctaText,
782
+ onRegister,
783
+ onCtaClick,
784
+ className = "",
785
+ dateClassName = "",
786
+ titleClassName = "",
787
+ ctaClassName = ""
788
+ }) {
789
+ const [loading, setLoading] = React5.useState(false);
790
+ const schedule = event.schedules?.[0] || event.next_schedule;
791
+ const soldOut = schedule ? isEventSoldOut(schedule.capacity, schedule.current_registrations) : false;
792
+ const spotsRemaining = schedule ? getSpotsRemaining(schedule.capacity, schedule.current_registrations) : null;
793
+ const defaultCtaText = event.price && event.price > 0 ? "Get Tickets" : "Register Free";
794
+ const handleClick = async () => {
795
+ if (onCtaClick) {
796
+ onCtaClick(event);
797
+ return;
798
+ }
799
+ if (!schedule) {
800
+ window.location.href = `/events/${event.slug}`;
801
+ return;
802
+ }
803
+ if (onRegister) {
804
+ onRegister(event, schedule.id);
805
+ return;
806
+ }
807
+ setLoading(true);
808
+ try {
809
+ if (event.price && event.price > 0) {
810
+ const result = await createCheckoutSession(event.id, { scheduleId: schedule.id });
811
+ if (result.payment_url) {
812
+ window.location.href = result.payment_url;
813
+ }
814
+ } else {
815
+ window.location.href = `/events/${event.slug}/register`;
816
+ }
817
+ } catch (e) {
818
+ console.error("Registration error:", e);
819
+ } finally {
820
+ setLoading(false);
821
+ }
822
+ };
823
+ if (variant === "compact") {
824
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-event-tile-compact ${className}`, style: {
825
+ display: "flex",
826
+ alignItems: "center",
827
+ gap: "0.75rem",
828
+ padding: "0.75rem",
829
+ background: "white",
830
+ borderRadius: "8px",
831
+ boxShadow: "0 1px 2px rgba(0,0,0,0.05)"
832
+ }, children: [
833
+ showDate && schedule && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-event-date ${dateClassName}`, style: {
834
+ minWidth: "48px",
835
+ textAlign: "center",
836
+ padding: "0.5rem",
837
+ background: "#f3f4f6",
838
+ borderRadius: "6px"
839
+ }, children: [
840
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "0.75rem", color: "#666", textTransform: "uppercase" }, children: new Date(schedule.starts_at).toLocaleDateString("en-US", { month: "short" }) }),
841
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "1.25rem", fontWeight: 700, color: "#111" }, children: new Date(schedule.starts_at).getDate() })
842
+ ] }),
843
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
844
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: `site-kit-event-title ${titleClassName}`, style: {
845
+ margin: 0,
846
+ fontSize: "0.875rem",
847
+ fontWeight: 600,
848
+ whiteSpace: "nowrap",
849
+ overflow: "hidden",
850
+ textOverflow: "ellipsis"
851
+ }, children: event.name }),
852
+ showTime && schedule && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: "0.75rem", color: "#666" }, children: [
853
+ formatTime(schedule.starts_at),
854
+ showLocation && event.location && ` \u2022 ${event.location}`
855
+ ] })
856
+ ] }),
857
+ showCta && /* @__PURE__ */ jsxRuntime.jsx(
858
+ "button",
859
+ {
860
+ onClick: handleClick,
861
+ disabled: soldOut || loading,
862
+ className: `site-kit-event-cta ${ctaClassName}`,
863
+ style: {
864
+ padding: "0.375rem 0.75rem",
865
+ fontSize: "0.75rem",
866
+ borderRadius: "4px",
867
+ border: "none",
868
+ background: soldOut ? "#e5e7eb" : "#2563eb",
869
+ color: soldOut ? "#666" : "white",
870
+ cursor: soldOut ? "not-allowed" : "pointer",
871
+ fontWeight: 500,
872
+ whiteSpace: "nowrap"
873
+ },
874
+ children: soldOut ? "Sold Out" : loading ? "..." : ctaText || defaultCtaText
875
+ }
876
+ )
877
+ ] });
878
+ }
879
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-event-tile ${className}`, style: {
880
+ background: "white",
881
+ borderRadius: "12px",
882
+ overflow: "hidden",
883
+ boxShadow: "0 1px 3px rgba(0,0,0,0.1)"
884
+ }, children: [
885
+ event.featured_image_url && /* @__PURE__ */ jsxRuntime.jsx(
886
+ "img",
887
+ {
888
+ src: event.featured_image_url,
889
+ alt: event.name,
890
+ style: {
891
+ width: "100%",
892
+ height: "140px",
893
+ objectFit: "cover"
894
+ }
895
+ }
896
+ ),
897
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "1rem" }, children: [
898
+ showDate && schedule && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-event-date ${dateClassName}`, style: {
899
+ display: "flex",
900
+ alignItems: "center",
901
+ gap: "0.5rem",
902
+ marginBottom: "0.5rem"
903
+ }, children: [
904
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
905
+ background: "#dbeafe",
906
+ color: "#1d4ed8",
907
+ padding: "0.25rem 0.5rem",
908
+ borderRadius: "4px",
909
+ fontSize: "0.75rem",
910
+ fontWeight: 600
911
+ }, children: getRelativeTimeUntil(schedule.starts_at) }),
912
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.875rem", color: "#666" }, children: formatDate(schedule.starts_at) })
913
+ ] }),
914
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: `site-kit-event-title ${titleClassName}`, style: {
915
+ margin: "0 0 0.5rem",
916
+ fontSize: "1.125rem",
917
+ fontWeight: 600,
918
+ color: "#111"
919
+ }, children: event.name }),
920
+ showLocation && event.location && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: "0.875rem", color: "#666", marginBottom: "0.5rem" }, children: [
921
+ "\u{1F4CD} ",
922
+ event.location
923
+ ] }),
924
+ showTime && schedule && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: "0.875rem", color: "#666", marginBottom: "0.75rem" }, children: [
925
+ "\u{1F550} ",
926
+ formatTime(schedule.starts_at),
927
+ schedule.ends_at && ` - ${formatTime(schedule.ends_at)}`
928
+ ] }),
929
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
930
+ display: "flex",
931
+ justifyContent: "space-between",
932
+ alignItems: "center",
933
+ marginTop: "0.75rem"
934
+ }, children: [
935
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
936
+ showPrice && event.price_is_public && event.price != null && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 600, color: "#111" }, children: event.price === 0 ? "Free" : `$${event.price}` }),
937
+ showCapacity && spotsRemaining !== null && spotsRemaining <= 10 && !soldOut && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: {
938
+ fontSize: "0.75rem",
939
+ color: "#dc2626",
940
+ marginLeft: "0.5rem"
941
+ }, children: [
942
+ "Only ",
943
+ spotsRemaining,
944
+ " spots left!"
945
+ ] })
946
+ ] }),
947
+ showCta && /* @__PURE__ */ jsxRuntime.jsx(
948
+ "button",
949
+ {
950
+ onClick: handleClick,
951
+ disabled: soldOut || loading,
952
+ className: `site-kit-event-cta ${ctaClassName}`,
953
+ style: {
954
+ padding: "0.5rem 1rem",
955
+ borderRadius: "6px",
956
+ border: "none",
957
+ background: soldOut ? "#e5e7eb" : "#2563eb",
958
+ color: soldOut ? "#666" : "white",
959
+ cursor: soldOut ? "not-allowed" : "pointer",
960
+ fontWeight: 500,
961
+ fontSize: "0.875rem"
962
+ },
963
+ children: soldOut ? "Sold Out" : loading ? "Loading..." : ctaText || defaultCtaText
964
+ }
965
+ )
966
+ ] })
967
+ ] })
968
+ ] });
969
+ }
970
+ function UpcomingEvents({
971
+ events: propEvents,
972
+ limit = 3,
973
+ category,
974
+ variant = "standard",
975
+ layout = "vertical",
976
+ showViewAll = true,
977
+ viewAllUrl = "/events",
978
+ viewAllText = "View All Events",
979
+ emptyMessage = "No upcoming events.",
980
+ title,
981
+ onRegister,
982
+ onCtaClick,
983
+ className = "",
984
+ titleClassName = "",
985
+ eventClassName = ""
986
+ }) {
987
+ const [events, setEvents] = React5.useState(propEvents || []);
988
+ const [loading, setLoading] = React5.useState(!propEvents);
989
+ React5.useEffect(() => {
990
+ if (propEvents) {
991
+ setEvents(propEvents);
992
+ return;
993
+ }
994
+ async function load() {
995
+ setLoading(true);
996
+ try {
997
+ const data = await fetchUpcomingEvents({ limit, category });
998
+ setEvents(data);
999
+ } catch (e) {
1000
+ console.error("Failed to load events:", e);
1001
+ } finally {
1002
+ setLoading(false);
1003
+ }
1004
+ }
1005
+ load();
1006
+ }, [propEvents, limit, category]);
1007
+ if (loading) {
1008
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `site-kit-upcoming-events ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "2rem", textAlign: "center", color: "#666" }, children: "Loading events..." }) });
1009
+ }
1010
+ if (events.length === 0) {
1011
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-upcoming-events ${className}`, children: [
1012
+ title && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: `site-kit-upcoming-events-title ${titleClassName}`, style: {
1013
+ margin: "0 0 1rem",
1014
+ fontSize: "1.5rem",
1015
+ fontWeight: 600
1016
+ }, children: title }),
1017
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "2rem", textAlign: "center", color: "#666" }, children: emptyMessage })
1018
+ ] });
1019
+ }
1020
+ const layoutStyles = layout === "horizontal" ? {
1021
+ display: "flex",
1022
+ gap: "1rem",
1023
+ overflowX: "auto"
1024
+ } : {
1025
+ display: "flex",
1026
+ flexDirection: "column",
1027
+ gap: "1rem"
1028
+ };
1029
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-upcoming-events ${className}`, children: [
1030
+ title && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
1031
+ display: "flex",
1032
+ justifyContent: "space-between",
1033
+ alignItems: "center",
1034
+ marginBottom: "1rem"
1035
+ }, children: [
1036
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: `site-kit-upcoming-events-title ${titleClassName}`, style: {
1037
+ margin: 0,
1038
+ fontSize: "1.5rem",
1039
+ fontWeight: 600
1040
+ }, children: title }),
1041
+ showViewAll && events.length >= limit && /* @__PURE__ */ jsxRuntime.jsxs(
1042
+ "a",
1043
+ {
1044
+ href: viewAllUrl,
1045
+ style: {
1046
+ color: "#2563eb",
1047
+ textDecoration: "none",
1048
+ fontSize: "0.875rem",
1049
+ fontWeight: 500
1050
+ },
1051
+ children: [
1052
+ viewAllText,
1053
+ " \u2192"
1054
+ ]
1055
+ }
1056
+ )
1057
+ ] }),
1058
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: layoutStyles, children: events.map((event) => /* @__PURE__ */ jsxRuntime.jsx(
1059
+ "div",
1060
+ {
1061
+ className: eventClassName,
1062
+ style: layout === "horizontal" ? { minWidth: "280px", flex: "0 0 auto" } : void 0,
1063
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1064
+ EventTile,
1065
+ {
1066
+ event,
1067
+ variant,
1068
+ onRegister,
1069
+ onCtaClick
1070
+ }
1071
+ )
1072
+ },
1073
+ event.id
1074
+ )) }),
1075
+ showViewAll && events.length >= limit && !title && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", marginTop: "1.5rem" }, children: /* @__PURE__ */ jsxRuntime.jsx(
1076
+ "a",
1077
+ {
1078
+ href: viewAllUrl,
1079
+ style: {
1080
+ display: "inline-block",
1081
+ padding: "0.75rem 1.5rem",
1082
+ background: "#f3f4f6",
1083
+ color: "#333",
1084
+ borderRadius: "8px",
1085
+ textDecoration: "none",
1086
+ fontWeight: 500
1087
+ },
1088
+ children: viewAllText
1089
+ }
1090
+ ) })
1091
+ ] });
1092
+ }
1093
+ function ProductEmbed({
1094
+ product: propProduct,
1095
+ slug,
1096
+ mode = "specific",
1097
+ // 'specific', 'latest', 'featured'
1098
+ category,
1099
+ variant = "card",
1100
+ showImage = true,
1101
+ showPrice = true,
1102
+ showDescription = true,
1103
+ showCta = true,
1104
+ ctaText = "Shop Now",
1105
+ onCtaClick,
1106
+ className = ""
1107
+ }) {
1108
+ const [product, setProduct] = React5.useState(propProduct || null);
1109
+ const [loading, setLoading] = React5.useState(!propProduct && !!slug);
1110
+ React5.useEffect(() => {
1111
+ if (propProduct) {
1112
+ setProduct(propProduct);
1113
+ return;
1114
+ }
1115
+ async function load() {
1116
+ setLoading(true);
1117
+ try {
1118
+ let data = null;
1119
+ if (mode === "specific" && slug) {
1120
+ data = await fetchProductBySlug(slug);
1121
+ } else if (mode === "latest" || mode === "featured") {
1122
+ data = await fetchLatestOffering("product", category);
1123
+ }
1124
+ setProduct(data);
1125
+ } catch (e) {
1126
+ console.error("Failed to load product:", e);
1127
+ } finally {
1128
+ setLoading(false);
1129
+ }
1130
+ }
1131
+ load();
1132
+ }, [propProduct, slug, mode, category]);
1133
+ if (loading) {
1134
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-product-embed ${className}`, style: {
1135
+ padding: "2rem",
1136
+ textAlign: "center",
1137
+ background: "#f9fafb",
1138
+ borderRadius: "12px"
1139
+ }, children: [
1140
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
1141
+ width: "40px",
1142
+ height: "40px",
1143
+ margin: "0 auto",
1144
+ border: "3px solid #e5e7eb",
1145
+ borderTopColor: "#2563eb",
1146
+ borderRadius: "50%",
1147
+ animation: "spin 1s linear infinite"
1148
+ } }),
1149
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
1150
+ @keyframes spin {
1151
+ to { transform: rotate(360deg); }
1152
+ }
1153
+ ` })
1154
+ ] });
1155
+ }
1156
+ if (!product) {
1157
+ return null;
1158
+ }
1159
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `site-kit-product-embed ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx(
1160
+ OfferingCard,
1161
+ {
1162
+ offering: product,
1163
+ variant,
1164
+ showImage,
1165
+ showPrice,
1166
+ showDescription,
1167
+ showCta,
1168
+ ctaText,
1169
+ onCtaClick
1170
+ }
1171
+ ) });
1172
+ }
1173
+ function ProductDetail({
1174
+ product: propProduct,
1175
+ slug,
1176
+ showAddToCart = true,
1177
+ showBuyNow = true,
1178
+ showQuantity = true,
1179
+ showVariants = true,
1180
+ showGallery = true,
1181
+ showFeatures = true,
1182
+ showSpecifications = true,
1183
+ successUrl,
1184
+ cancelUrl,
1185
+ onAddToCart,
1186
+ onBuyNow,
1187
+ onCheckoutSuccess,
1188
+ onCheckoutError,
1189
+ className = "",
1190
+ style
1191
+ }) {
1192
+ const [product, setProduct] = React5.useState(propProduct || null);
1193
+ const [loading, setLoading] = React5.useState(!propProduct && !!slug);
1194
+ const [selectedVariant, setSelectedVariant] = React5.useState();
1195
+ const [quantity, setQuantity] = React5.useState(1);
1196
+ const [selectedImage, setSelectedImage] = React5.useState(0);
1197
+ const [checkingOut, setCheckingOut] = React5.useState(false);
1198
+ React5.useEffect(() => {
1199
+ if (propProduct) {
1200
+ setProduct(propProduct);
1201
+ const defaultVariant = propProduct.variants?.find((v) => v.is_default) || propProduct.variants?.[0];
1202
+ setSelectedVariant(defaultVariant);
1203
+ return;
1204
+ }
1205
+ if (!slug) return;
1206
+ async function load() {
1207
+ setLoading(true);
1208
+ try {
1209
+ const data = await fetchProductBySlug(slug);
1210
+ setProduct(data);
1211
+ if (data?.variants?.length) {
1212
+ const defaultVariant = data.variants.find((v) => v.is_default) || data.variants[0];
1213
+ setSelectedVariant(defaultVariant);
1214
+ }
1215
+ } catch (e) {
1216
+ console.error("Failed to load product:", e);
1217
+ } finally {
1218
+ setLoading(false);
1219
+ }
1220
+ }
1221
+ load();
1222
+ }, [propProduct, slug]);
1223
+ if (loading) {
1224
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-product-detail site-kit-product-detail--loading ${className}`, style, children: [
1225
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "site-kit-product-detail__loader", style: {
1226
+ display: "flex",
1227
+ justifyContent: "center",
1228
+ alignItems: "center",
1229
+ minHeight: "400px"
1230
+ }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
1231
+ width: "48px",
1232
+ height: "48px",
1233
+ border: "3px solid #e5e7eb",
1234
+ borderTopColor: "#2563eb",
1235
+ borderRadius: "50%",
1236
+ animation: "spin 1s linear infinite"
1237
+ } }) }),
1238
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
1239
+ ] });
1240
+ }
1241
+ if (!product) {
1242
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `site-kit-product-detail site-kit-product-detail--not-found ${className}`, style, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", padding: "4rem 2rem", color: "#666" }, children: [
1243
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { margin: 0, fontSize: "1.5rem", color: "#333" }, children: "Product Not Found" }),
1244
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { marginTop: "0.5rem" }, children: "The product you're looking for doesn't exist or has been removed." })
1245
+ ] }) });
1246
+ }
1247
+ const currentPrice = selectedVariant?.price ?? product.price ?? 0;
1248
+ const compareAtPrice = product.compare_at_price;
1249
+ const hasDiscount = compareAtPrice && compareAtPrice > currentPrice;
1250
+ const allImages = [
1251
+ product.featured_image_url,
1252
+ ...product.gallery_images || [],
1253
+ ...product.variants?.map((v) => v.image_url).filter(Boolean) || []
1254
+ ].filter(Boolean);
1255
+ const inventoryCount = selectedVariant?.inventory_count ?? product.inventory_count;
1256
+ const isOutOfStock = product.track_inventory && inventoryCount !== void 0 && inventoryCount <= 0;
1257
+ const isLowStock = product.track_inventory && inventoryCount !== void 0 && inventoryCount > 0 && inventoryCount <= 5;
1258
+ const needsVariantSelection = (product.is_clothing || (product.variants?.length ?? 0) > 0) && !selectedVariant;
1259
+ const handleAddToCart = () => {
1260
+ if (onAddToCart) {
1261
+ onAddToCart(product, selectedVariant, quantity);
1262
+ }
1263
+ };
1264
+ const handleBuyNow = async () => {
1265
+ if (onBuyNow) {
1266
+ onBuyNow(product, selectedVariant, quantity);
1267
+ return;
1268
+ }
1269
+ setCheckingOut(true);
1270
+ try {
1271
+ const result = await createCheckoutSession({
1272
+ offeringId: product.id,
1273
+ variantId: selectedVariant?.id,
1274
+ quantity,
1275
+ successUrl: successUrl || `${window.location.origin}/checkout/success`,
1276
+ cancelUrl: cancelUrl || window.location.href
1277
+ });
1278
+ if (result.success && result.checkout_url) {
1279
+ onCheckoutSuccess?.(result);
1280
+ window.location.href = result.checkout_url;
1281
+ } else {
1282
+ throw new Error(result.error || "Failed to create checkout");
1283
+ }
1284
+ } catch (error) {
1285
+ console.error("Checkout error:", error);
1286
+ onCheckoutError?.(error.message || "Checkout failed");
1287
+ } finally {
1288
+ setCheckingOut(false);
1289
+ }
1290
+ };
1291
+ const handleVariantChange = (variant) => {
1292
+ setSelectedVariant(variant);
1293
+ if (variant.image_url) {
1294
+ const imageIndex = allImages.indexOf(variant.image_url);
1295
+ if (imageIndex >= 0) setSelectedImage(imageIndex);
1296
+ }
1297
+ };
1298
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-product-detail ${className}`, style: {
1299
+ display: "grid",
1300
+ gridTemplateColumns: "repeat(auto-fit, minmax(320px, 1fr))",
1301
+ gap: "2rem",
1302
+ ...style
1303
+ }, children: [
1304
+ showGallery && allImages.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "site-kit-product-detail__gallery", children: [
1305
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "site-kit-product-detail__main-image", style: {
1306
+ aspectRatio: "1",
1307
+ borderRadius: "12px",
1308
+ overflow: "hidden",
1309
+ backgroundColor: "#f9fafb"
1310
+ }, children: /* @__PURE__ */ jsxRuntime.jsx(
1311
+ "img",
1312
+ {
1313
+ src: allImages[selectedImage],
1314
+ alt: product.name,
1315
+ style: {
1316
+ width: "100%",
1317
+ height: "100%",
1318
+ objectFit: "cover"
1319
+ }
1320
+ }
1321
+ ) }),
1322
+ allImages.length > 1 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "site-kit-product-detail__thumbnails", style: {
1323
+ display: "flex",
1324
+ gap: "0.5rem",
1325
+ marginTop: "0.75rem",
1326
+ overflowX: "auto"
1327
+ }, children: allImages.map((img, idx) => /* @__PURE__ */ jsxRuntime.jsx(
1328
+ "button",
1329
+ {
1330
+ onClick: () => setSelectedImage(idx),
1331
+ style: {
1332
+ flex: "0 0 auto",
1333
+ width: "64px",
1334
+ height: "64px",
1335
+ borderRadius: "8px",
1336
+ overflow: "hidden",
1337
+ border: idx === selectedImage ? "2px solid #2563eb" : "2px solid transparent",
1338
+ padding: 0,
1339
+ cursor: "pointer",
1340
+ backgroundColor: "#f9fafb"
1341
+ },
1342
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1343
+ "img",
1344
+ {
1345
+ src: img,
1346
+ alt: `${product.name} ${idx + 1}`,
1347
+ style: {
1348
+ width: "100%",
1349
+ height: "100%",
1350
+ objectFit: "cover"
1351
+ }
1352
+ }
1353
+ )
1354
+ },
1355
+ idx
1356
+ )) })
1357
+ ] }),
1358
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "site-kit-product-detail__info", children: [
1359
+ product.category && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "site-kit-product-detail__category", style: {
1360
+ fontSize: "0.875rem",
1361
+ color: "#6b7280",
1362
+ marginBottom: "0.5rem",
1363
+ textTransform: "uppercase",
1364
+ letterSpacing: "0.05em"
1365
+ }, children: product.category.name }),
1366
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "site-kit-product-detail__title", style: {
1367
+ margin: 0,
1368
+ fontSize: "2rem",
1369
+ fontWeight: 700,
1370
+ color: "#111827",
1371
+ lineHeight: 1.2
1372
+ }, children: product.name }),
1373
+ product.short_description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "site-kit-product-detail__short-description", style: {
1374
+ marginTop: "0.75rem",
1375
+ fontSize: "1rem",
1376
+ color: "#4b5563",
1377
+ lineHeight: 1.6
1378
+ }, children: product.short_description }),
1379
+ product.price_is_public && currentPrice !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "site-kit-product-detail__price", style: {
1380
+ marginTop: "1rem",
1381
+ display: "flex",
1382
+ alignItems: "baseline",
1383
+ gap: "0.75rem"
1384
+ }, children: [
1385
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
1386
+ fontSize: "1.75rem",
1387
+ fontWeight: 700,
1388
+ color: hasDiscount ? "#dc2626" : "#111827"
1389
+ }, children: formatPrice(currentPrice, product.currency) }),
1390
+ hasDiscount && /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
1391
+ fontSize: "1.25rem",
1392
+ color: "#9ca3af",
1393
+ textDecoration: "line-through"
1394
+ }, children: formatPrice(compareAtPrice, product.currency) })
1395
+ ] }),
1396
+ product.track_inventory && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "site-kit-product-detail__stock", style: {
1397
+ marginTop: "0.75rem",
1398
+ fontSize: "0.875rem",
1399
+ fontWeight: 500
1400
+ }, children: isOutOfStock ? /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#dc2626" }, children: "Out of Stock" }) : isLowStock ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: "#f59e0b" }, children: [
1401
+ "Only ",
1402
+ inventoryCount,
1403
+ " left!"
1404
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#10b981" }, children: "In Stock" }) }),
1405
+ showVariants && product.variants && (product.variants.length > 1 || product.is_clothing) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "site-kit-product-detail__variants", style: { marginTop: "1.5rem" }, children: [
1406
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: {
1407
+ display: "block",
1408
+ fontSize: "0.875rem",
1409
+ fontWeight: 600,
1410
+ color: "#374151",
1411
+ marginBottom: "0.5rem"
1412
+ }, children: product.is_clothing ? "Size" : "Options" }),
1413
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: "0.5rem" }, children: product.variants.map((variant) => {
1414
+ const variantOutOfStock = variant.track_inventory !== false && (variant.inventory_count ?? 0) <= 0;
1415
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1416
+ "button",
1417
+ {
1418
+ onClick: () => !variantOutOfStock && handleVariantChange(variant),
1419
+ disabled: variantOutOfStock,
1420
+ style: {
1421
+ padding: "0.5rem 1rem",
1422
+ borderRadius: "8px",
1423
+ border: selectedVariant?.id === variant.id ? "2px solid #2563eb" : "1px solid #d1d5db",
1424
+ backgroundColor: selectedVariant?.id === variant.id ? "#eff6ff" : "white",
1425
+ color: variantOutOfStock ? "#9ca3af" : "#374151",
1426
+ fontSize: "0.875rem",
1427
+ fontWeight: 500,
1428
+ cursor: variantOutOfStock ? "not-allowed" : "pointer",
1429
+ opacity: variantOutOfStock ? 0.6 : 1,
1430
+ transition: "all 0.15s ease"
1431
+ },
1432
+ children: [
1433
+ variant.options?.Size || variant.name,
1434
+ variantOutOfStock && " (Out of stock)"
1435
+ ]
1436
+ },
1437
+ variant.id
1438
+ );
1439
+ }) })
1440
+ ] }),
1441
+ showQuantity && !isOutOfStock && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "site-kit-product-detail__quantity", style: { marginTop: "1.5rem" }, children: [
1442
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: {
1443
+ display: "block",
1444
+ fontSize: "0.875rem",
1445
+ fontWeight: 600,
1446
+ color: "#374151",
1447
+ marginBottom: "0.5rem"
1448
+ }, children: "Quantity" }),
1449
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
1450
+ /* @__PURE__ */ jsxRuntime.jsx(
1451
+ "button",
1452
+ {
1453
+ onClick: () => setQuantity(Math.max(1, quantity - 1)),
1454
+ disabled: quantity <= 1,
1455
+ style: {
1456
+ width: "40px",
1457
+ height: "40px",
1458
+ borderRadius: "8px",
1459
+ border: "1px solid #d1d5db",
1460
+ backgroundColor: "white",
1461
+ fontSize: "1.25rem",
1462
+ cursor: quantity <= 1 ? "not-allowed" : "pointer",
1463
+ opacity: quantity <= 1 ? 0.5 : 1
1464
+ },
1465
+ children: "\u2212"
1466
+ }
1467
+ ),
1468
+ /* @__PURE__ */ jsxRuntime.jsx(
1469
+ "input",
1470
+ {
1471
+ type: "number",
1472
+ min: "1",
1473
+ max: inventoryCount ?? 99,
1474
+ value: quantity,
1475
+ onChange: (e) => setQuantity(Math.max(1, parseInt(e.target.value) || 1)),
1476
+ style: {
1477
+ width: "60px",
1478
+ height: "40px",
1479
+ textAlign: "center",
1480
+ borderRadius: "8px",
1481
+ border: "1px solid #d1d5db",
1482
+ fontSize: "1rem"
1483
+ }
1484
+ }
1485
+ ),
1486
+ /* @__PURE__ */ jsxRuntime.jsx(
1487
+ "button",
1488
+ {
1489
+ onClick: () => setQuantity(quantity + 1),
1490
+ disabled: product.track_inventory && inventoryCount !== void 0 && quantity >= inventoryCount,
1491
+ style: {
1492
+ width: "40px",
1493
+ height: "40px",
1494
+ borderRadius: "8px",
1495
+ border: "1px solid #d1d5db",
1496
+ backgroundColor: "white",
1497
+ fontSize: "1.25rem",
1498
+ cursor: "pointer"
1499
+ },
1500
+ children: "+"
1501
+ }
1502
+ )
1503
+ ] })
1504
+ ] }),
1505
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "site-kit-product-detail__actions", style: {
1506
+ marginTop: "1.5rem",
1507
+ display: "flex",
1508
+ flexDirection: "column",
1509
+ gap: "0.75rem"
1510
+ }, children: [
1511
+ showBuyNow && /* @__PURE__ */ jsxRuntime.jsx(
1512
+ "button",
1513
+ {
1514
+ onClick: handleBuyNow,
1515
+ disabled: isOutOfStock || checkingOut || needsVariantSelection,
1516
+ className: "site-kit-product-detail__buy-now",
1517
+ style: {
1518
+ padding: "1rem 2rem",
1519
+ borderRadius: "8px",
1520
+ border: "none",
1521
+ backgroundColor: isOutOfStock ? "#d1d5db" : "#2563eb",
1522
+ color: "white",
1523
+ fontSize: "1rem",
1524
+ fontWeight: 600,
1525
+ cursor: isOutOfStock ? "not-allowed" : "pointer",
1526
+ transition: "all 0.15s ease"
1527
+ },
1528
+ children: checkingOut ? "Processing..." : needsVariantSelection ? "Select Size" : isOutOfStock ? "Out of Stock" : "Buy Now"
1529
+ }
1530
+ ),
1531
+ showAddToCart && onAddToCart && /* @__PURE__ */ jsxRuntime.jsx(
1532
+ "button",
1533
+ {
1534
+ onClick: handleAddToCart,
1535
+ disabled: isOutOfStock || needsVariantSelection,
1536
+ className: "site-kit-product-detail__add-to-cart",
1537
+ style: {
1538
+ padding: "1rem 2rem",
1539
+ borderRadius: "8px",
1540
+ border: "2px solid #2563eb",
1541
+ backgroundColor: "white",
1542
+ color: "#2563eb",
1543
+ fontSize: "1rem",
1544
+ fontWeight: 600,
1545
+ cursor: isOutOfStock || needsVariantSelection ? "not-allowed" : "pointer",
1546
+ transition: "all 0.15s ease"
1547
+ },
1548
+ children: needsVariantSelection ? "Select Size" : isOutOfStock ? "Out of Stock" : "Add to Cart"
1549
+ }
1550
+ )
1551
+ ] }),
1552
+ showFeatures && product.features && product.features.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "site-kit-product-detail__features", style: { marginTop: "2rem" }, children: [
1553
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { style: {
1554
+ fontSize: "1rem",
1555
+ fontWeight: 600,
1556
+ color: "#111827",
1557
+ marginBottom: "0.75rem"
1558
+ }, children: "Features" }),
1559
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { style: {
1560
+ margin: 0,
1561
+ paddingLeft: "1.25rem",
1562
+ display: "flex",
1563
+ flexDirection: "column",
1564
+ gap: "0.5rem"
1565
+ }, children: product.features.map((feature, idx) => /* @__PURE__ */ jsxRuntime.jsx("li", { style: { color: "#4b5563", fontSize: "0.9375rem" }, children: feature }, idx)) })
1566
+ ] }),
1567
+ showSpecifications && product.specifications && Object.keys(product.specifications).length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "site-kit-product-detail__specifications", style: { marginTop: "2rem" }, children: [
1568
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { style: {
1569
+ fontSize: "1rem",
1570
+ fontWeight: 600,
1571
+ color: "#111827",
1572
+ marginBottom: "0.75rem"
1573
+ }, children: "Specifications" }),
1574
+ /* @__PURE__ */ jsxRuntime.jsx("dl", { style: {
1575
+ margin: 0,
1576
+ display: "grid",
1577
+ gridTemplateColumns: "auto 1fr",
1578
+ gap: "0.5rem 1rem"
1579
+ }, children: Object.entries(product.specifications).map(([key, value]) => /* @__PURE__ */ jsxRuntime.jsxs(React5__default.default.Fragment, { children: [
1580
+ /* @__PURE__ */ jsxRuntime.jsx("dt", { style: { color: "#6b7280", fontSize: "0.875rem" }, children: key }),
1581
+ /* @__PURE__ */ jsxRuntime.jsx("dd", { style: { margin: 0, color: "#111827", fontSize: "0.875rem" }, children: value })
1582
+ ] }, key)) })
1583
+ ] })
1584
+ ] }),
1585
+ product.long_description && /* @__PURE__ */ jsxRuntime.jsxs(
1586
+ "div",
1587
+ {
1588
+ className: "site-kit-product-detail__description",
1589
+ style: {
1590
+ gridColumn: "1 / -1",
1591
+ marginTop: "2rem",
1592
+ padding: "2rem",
1593
+ backgroundColor: "#f9fafb",
1594
+ borderRadius: "12px"
1595
+ },
1596
+ children: [
1597
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: {
1598
+ fontSize: "1.25rem",
1599
+ fontWeight: 600,
1600
+ color: "#111827",
1601
+ marginBottom: "1rem"
1602
+ }, children: "About This Product" }),
1603
+ /* @__PURE__ */ jsxRuntime.jsx(
1604
+ "div",
1605
+ {
1606
+ style: { color: "#4b5563", lineHeight: 1.7 },
1607
+ dangerouslySetInnerHTML: { __html: product.long_description }
1608
+ }
1609
+ )
1610
+ ]
1611
+ }
1612
+ )
1613
+ ] });
1614
+ }
1615
+ function ProductGrid({
1616
+ products: propProducts,
1617
+ limit,
1618
+ category: propCategory,
1619
+ showCategoryFilter = false,
1620
+ showSort = true,
1621
+ showSearch = true,
1622
+ columns = 3,
1623
+ skeletonCount = 6,
1624
+ emptyMessage = "No products found",
1625
+ onProductClick,
1626
+ linkToProduct = true,
1627
+ productBasePath = "/shop",
1628
+ className = "",
1629
+ cardVariant = "card",
1630
+ style
1631
+ }) {
1632
+ const [products, setProducts] = React5.useState(propProducts || []);
1633
+ const [total, setTotal] = React5.useState(0);
1634
+ const [loading, setLoading] = React5.useState(!propProducts);
1635
+ const [searchQuery, setSearchQuery] = React5.useState("");
1636
+ const [selectedCategory, setSelectedCategory] = React5.useState(propCategory);
1637
+ const [sortBy, setSortBy] = React5.useState("newest");
1638
+ const categories = React5.useMemo(() => {
1639
+ const categoryMap = /* @__PURE__ */ new Map();
1640
+ products.forEach((p) => {
1641
+ if (p.category) {
1642
+ categoryMap.set(p.category.id, p.category);
1643
+ }
1644
+ });
1645
+ return Array.from(categoryMap.values());
1646
+ }, [products]);
1647
+ React5.useEffect(() => {
1648
+ if (propProducts) {
1649
+ setProducts(propProducts);
1650
+ setTotal(propProducts.length);
1651
+ return;
1652
+ }
1653
+ async function load() {
1654
+ setLoading(true);
1655
+ try {
1656
+ const { products: data, total: count } = await fetchProductsPublic({
1657
+ category: selectedCategory,
1658
+ limit,
1659
+ orderBy: "created_at",
1660
+ order: "desc"
1661
+ });
1662
+ setProducts(data);
1663
+ setTotal(count);
1664
+ } catch (e) {
1665
+ console.error("Failed to load products:", e);
1666
+ } finally {
1667
+ setLoading(false);
1668
+ }
1669
+ }
1670
+ load();
1671
+ }, [propProducts, selectedCategory, limit]);
1672
+ const filteredProducts = React5.useMemo(() => {
1673
+ let filtered = [...products];
1674
+ if (searchQuery) {
1675
+ const query = searchQuery.toLowerCase();
1676
+ filtered = filtered.filter(
1677
+ (p) => p.name.toLowerCase().includes(query) || p.short_description?.toLowerCase().includes(query) || p.tags?.some((tag) => tag.toLowerCase().includes(query))
1678
+ );
1679
+ }
1680
+ if (selectedCategory && !propCategory) {
1681
+ filtered = filtered.filter((p) => p.category_id === selectedCategory);
1682
+ }
1683
+ switch (sortBy) {
1684
+ case "newest":
1685
+ filtered.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
1686
+ break;
1687
+ case "oldest":
1688
+ filtered.sort((a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime());
1689
+ break;
1690
+ case "price-low":
1691
+ filtered.sort((a, b) => (a.price || 0) - (b.price || 0));
1692
+ break;
1693
+ case "price-high":
1694
+ filtered.sort((a, b) => (b.price || 0) - (a.price || 0));
1695
+ break;
1696
+ case "name-az":
1697
+ filtered.sort((a, b) => a.name.localeCompare(b.name));
1698
+ break;
1699
+ case "name-za":
1700
+ filtered.sort((a, b) => b.name.localeCompare(a.name));
1701
+ break;
1702
+ }
1703
+ return filtered;
1704
+ }, [products, searchQuery, selectedCategory, sortBy, propCategory]);
1705
+ const handleProductClick = (product) => {
1706
+ if (onProductClick) {
1707
+ onProductClick(product);
1708
+ } else if (linkToProduct && typeof window !== "undefined") {
1709
+ window.location.href = `${productBasePath}/${product.slug}`;
1710
+ }
1711
+ };
1712
+ const gridColumns = {
1713
+ 2: "repeat(auto-fill, minmax(280px, 1fr))",
1714
+ 3: "repeat(auto-fill, minmax(240px, 1fr))",
1715
+ 4: "repeat(auto-fill, minmax(200px, 1fr))"
1716
+ };
1717
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-product-grid ${className}`, style, children: [
1718
+ (showSearch || showSort || showCategoryFilter) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "site-kit-product-grid__controls", style: {
1719
+ display: "flex",
1720
+ flexWrap: "wrap",
1721
+ gap: "1rem",
1722
+ marginBottom: "1.5rem",
1723
+ alignItems: "center"
1724
+ }, children: [
1725
+ showSearch && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "site-kit-product-grid__search", style: { flex: "1 1 200px" }, children: /* @__PURE__ */ jsxRuntime.jsx(
1726
+ "input",
1727
+ {
1728
+ type: "search",
1729
+ placeholder: "Search products...",
1730
+ value: searchQuery,
1731
+ onChange: (e) => setSearchQuery(e.target.value),
1732
+ style: {
1733
+ width: "100%",
1734
+ padding: "0.625rem 1rem",
1735
+ borderRadius: "8px",
1736
+ border: "1px solid #d1d5db",
1737
+ fontSize: "0.9375rem"
1738
+ }
1739
+ }
1740
+ ) }),
1741
+ showCategoryFilter && categories.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
1742
+ "select",
1743
+ {
1744
+ value: selectedCategory || "",
1745
+ onChange: (e) => setSelectedCategory(e.target.value || void 0),
1746
+ className: "site-kit-product-grid__category-filter",
1747
+ style: {
1748
+ padding: "0.625rem 1rem",
1749
+ borderRadius: "8px",
1750
+ border: "1px solid #d1d5db",
1751
+ fontSize: "0.9375rem",
1752
+ backgroundColor: "white",
1753
+ minWidth: "150px"
1754
+ },
1755
+ children: [
1756
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "All Categories" }),
1757
+ categories.map((cat) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: cat.id, children: cat.name }, cat.id))
1758
+ ]
1759
+ }
1760
+ ),
1761
+ showSort && /* @__PURE__ */ jsxRuntime.jsxs(
1762
+ "select",
1763
+ {
1764
+ value: sortBy,
1765
+ onChange: (e) => setSortBy(e.target.value),
1766
+ className: "site-kit-product-grid__sort",
1767
+ style: {
1768
+ padding: "0.625rem 1rem",
1769
+ borderRadius: "8px",
1770
+ border: "1px solid #d1d5db",
1771
+ fontSize: "0.9375rem",
1772
+ backgroundColor: "white"
1773
+ },
1774
+ children: [
1775
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "newest", children: "Newest First" }),
1776
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "oldest", children: "Oldest First" }),
1777
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "price-low", children: "Price: Low to High" }),
1778
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "price-high", children: "Price: High to Low" }),
1779
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "name-az", children: "Name: A-Z" }),
1780
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "name-za", children: "Name: Z-A" })
1781
+ ]
1782
+ }
1783
+ ),
1784
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "site-kit-product-grid__count", style: {
1785
+ marginLeft: "auto",
1786
+ fontSize: "0.875rem",
1787
+ color: "#6b7280"
1788
+ }, children: [
1789
+ searchQuery ? filteredProducts.length : total,
1790
+ " product",
1791
+ (searchQuery ? filteredProducts.length : total) !== 1 ? "s" : ""
1792
+ ] })
1793
+ ] }),
1794
+ loading && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "site-kit-product-grid__grid", style: {
1795
+ display: "grid",
1796
+ gridTemplateColumns: gridColumns[columns],
1797
+ gap: "1.5rem"
1798
+ }, children: [
1799
+ Array.from({ length: skeletonCount }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "site-kit-product-grid__skeleton", style: {
1800
+ aspectRatio: "1",
1801
+ backgroundColor: "#f3f4f6",
1802
+ borderRadius: "12px",
1803
+ animation: "pulse 2s infinite"
1804
+ } }, i)),
1805
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
1806
+ @keyframes pulse {
1807
+ 0%, 100% { opacity: 1; }
1808
+ 50% { opacity: 0.5; }
1809
+ }
1810
+ ` })
1811
+ ] }),
1812
+ !loading && filteredProducts.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "site-kit-product-grid__grid", style: {
1813
+ display: "grid",
1814
+ gridTemplateColumns: gridColumns[columns],
1815
+ gap: "1.5rem"
1816
+ }, children: filteredProducts.map((product) => /* @__PURE__ */ jsxRuntime.jsx(
1817
+ OfferingCard,
1818
+ {
1819
+ offering: product,
1820
+ variant: cardVariant,
1821
+ showImage: true,
1822
+ showPrice: true,
1823
+ showDescription: true,
1824
+ showCta: true,
1825
+ ctaText: "View Product",
1826
+ onCtaClick: () => handleProductClick(product)
1827
+ },
1828
+ product.id
1829
+ )) }),
1830
+ !loading && filteredProducts.length === 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "site-kit-product-grid__empty", style: {
1831
+ textAlign: "center",
1832
+ padding: "4rem 2rem",
1833
+ backgroundColor: "#f9fafb",
1834
+ borderRadius: "12px"
1835
+ }, children: [
1836
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "3rem", marginBottom: "1rem" }, children: "\u{1F6CD}\uFE0F" }),
1837
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: {
1838
+ margin: 0,
1839
+ color: "#6b7280",
1840
+ fontSize: "1rem"
1841
+ }, children: searchQuery ? `No products match "${searchQuery}"` : emptyMessage }),
1842
+ searchQuery && /* @__PURE__ */ jsxRuntime.jsx(
1843
+ "button",
1844
+ {
1845
+ onClick: () => setSearchQuery(""),
1846
+ style: {
1847
+ marginTop: "1rem",
1848
+ padding: "0.5rem 1rem",
1849
+ borderRadius: "6px",
1850
+ border: "none",
1851
+ backgroundColor: "#2563eb",
1852
+ color: "white",
1853
+ fontSize: "0.875rem",
1854
+ cursor: "pointer"
1855
+ },
1856
+ children: "Clear Search"
1857
+ }
1858
+ )
1859
+ ] })
1860
+ ] });
1861
+ }
1862
+ function ProductPage({
1863
+ product: propProduct,
1864
+ slug,
1865
+ showBreadcrumbs = true,
1866
+ showRelatedProducts = true,
1867
+ relatedProductsLimit = 4,
1868
+ showBackLink = true,
1869
+ shopBasePath = "/shop",
1870
+ successUrl,
1871
+ cancelUrl,
1872
+ onAddToCart,
1873
+ renderBreadcrumbs,
1874
+ renderHead,
1875
+ className = "",
1876
+ style
1877
+ }) {
1878
+ const [product, setProduct] = React5.useState(propProduct || null);
1879
+ const [relatedProducts, setRelatedProducts] = React5.useState([]);
1880
+ const [loading, setLoading] = React5.useState(!propProduct && !!slug);
1881
+ React5.useEffect(() => {
1882
+ if (propProduct) {
1883
+ setProduct(propProduct);
1884
+ return;
1885
+ }
1886
+ if (!slug) return;
1887
+ async function load() {
1888
+ setLoading(true);
1889
+ try {
1890
+ const data = await fetchProductBySlug(slug);
1891
+ setProduct(data);
1892
+ } catch (e) {
1893
+ console.error("Failed to load product:", e);
1894
+ } finally {
1895
+ setLoading(false);
1896
+ }
1897
+ }
1898
+ load();
1899
+ }, [propProduct, slug]);
1900
+ React5.useEffect(() => {
1901
+ if (!product || !showRelatedProducts) return;
1902
+ async function loadRelated() {
1903
+ try {
1904
+ const { products } = await fetchProductsPublic({
1905
+ category: product?.category_id,
1906
+ limit: relatedProductsLimit + 1
1907
+ // Fetch one extra to exclude current
1908
+ });
1909
+ const filtered = products.filter((p) => p.id !== product?.id).slice(0, relatedProductsLimit);
1910
+ setRelatedProducts(filtered);
1911
+ } catch (e) {
1912
+ console.error("Failed to load related products:", e);
1913
+ }
1914
+ }
1915
+ loadRelated();
1916
+ }, [product, showRelatedProducts, relatedProductsLimit]);
1917
+ React5.useEffect(() => {
1918
+ if (product && typeof document !== "undefined") {
1919
+ document.title = product.seo_title || `${product.name} | Shop`;
1920
+ const metaDesc = document.querySelector('meta[name="description"]');
1921
+ if (metaDesc && (product.seo_description || product.short_description)) {
1922
+ metaDesc.setAttribute("content", product.seo_description || product.short_description || "");
1923
+ }
1924
+ }
1925
+ }, [product]);
1926
+ if (loading) {
1927
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-product-page site-kit-product-page--loading ${className}`, style, children: [
1928
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
1929
+ display: "flex",
1930
+ justifyContent: "center",
1931
+ alignItems: "center",
1932
+ minHeight: "60vh"
1933
+ }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
1934
+ width: "48px",
1935
+ height: "48px",
1936
+ border: "3px solid #e5e7eb",
1937
+ borderTopColor: "#2563eb",
1938
+ borderRadius: "50%",
1939
+ animation: "spin 1s linear infinite"
1940
+ } }) }),
1941
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
1942
+ ] });
1943
+ }
1944
+ if (!product) {
1945
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `site-kit-product-page site-kit-product-page--not-found ${className}`, style, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
1946
+ textAlign: "center",
1947
+ padding: "6rem 2rem"
1948
+ }, children: [
1949
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "4rem", marginBottom: "1rem" }, children: "\u{1F50D}" }),
1950
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { style: { margin: 0, fontSize: "2rem", color: "#111827" }, children: "Product Not Found" }),
1951
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { marginTop: "0.75rem", color: "#6b7280" }, children: "The product you're looking for doesn't exist or has been removed." }),
1952
+ /* @__PURE__ */ jsxRuntime.jsx(
1953
+ "a",
1954
+ {
1955
+ href: shopBasePath,
1956
+ style: {
1957
+ display: "inline-block",
1958
+ marginTop: "1.5rem",
1959
+ padding: "0.75rem 1.5rem",
1960
+ borderRadius: "8px",
1961
+ backgroundColor: "#2563eb",
1962
+ color: "white",
1963
+ textDecoration: "none",
1964
+ fontWeight: 600
1965
+ },
1966
+ children: "Back to Shop"
1967
+ }
1968
+ )
1969
+ ] }) });
1970
+ }
1971
+ const defaultBreadcrumbs = /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "site-kit-product-page__breadcrumbs", "aria-label": "Breadcrumb", style: {
1972
+ marginBottom: "1.5rem",
1973
+ fontSize: "0.875rem"
1974
+ }, children: /* @__PURE__ */ jsxRuntime.jsxs("ol", { style: {
1975
+ display: "flex",
1976
+ flexWrap: "wrap",
1977
+ alignItems: "center",
1978
+ gap: "0.5rem",
1979
+ listStyle: "none",
1980
+ margin: 0,
1981
+ padding: 0
1982
+ }, children: [
1983
+ /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: "/", style: { color: "#6b7280", textDecoration: "none" }, children: "Home" }) }),
1984
+ /* @__PURE__ */ jsxRuntime.jsx("li", { style: { color: "#9ca3af" }, children: "/" }),
1985
+ /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: shopBasePath, style: { color: "#6b7280", textDecoration: "none" }, children: "Shop" }) }),
1986
+ product.category && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1987
+ /* @__PURE__ */ jsxRuntime.jsx("li", { style: { color: "#9ca3af" }, children: "/" }),
1988
+ /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
1989
+ "a",
1990
+ {
1991
+ href: `${shopBasePath}?category=${product.category.id}`,
1992
+ style: { color: "#6b7280", textDecoration: "none" },
1993
+ children: product.category.name
1994
+ }
1995
+ ) })
1996
+ ] }),
1997
+ /* @__PURE__ */ jsxRuntime.jsx("li", { style: { color: "#9ca3af" }, children: "/" }),
1998
+ /* @__PURE__ */ jsxRuntime.jsx("li", { style: { color: "#111827", fontWeight: 500 }, children: product.name })
1999
+ ] }) });
2000
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-product-page ${className}`, style, children: [
2001
+ renderHead?.(product),
2002
+ showBackLink && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "site-kit-product-page__back", style: { marginBottom: "1rem" }, children: /* @__PURE__ */ jsxRuntime.jsxs(
2003
+ "a",
2004
+ {
2005
+ href: shopBasePath,
2006
+ style: {
2007
+ display: "inline-flex",
2008
+ alignItems: "center",
2009
+ gap: "0.5rem",
2010
+ color: "#6b7280",
2011
+ textDecoration: "none",
2012
+ fontSize: "0.875rem"
2013
+ },
2014
+ children: [
2015
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u2190" }),
2016
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Back to Shop" })
2017
+ ]
2018
+ }
2019
+ ) }),
2020
+ showBreadcrumbs && (renderBreadcrumbs ? renderBreadcrumbs(product) : defaultBreadcrumbs),
2021
+ /* @__PURE__ */ jsxRuntime.jsx(
2022
+ ProductDetail,
2023
+ {
2024
+ product,
2025
+ showAddToCart: !!onAddToCart,
2026
+ showBuyNow: true,
2027
+ showQuantity: true,
2028
+ showVariants: true,
2029
+ showGallery: true,
2030
+ showFeatures: true,
2031
+ showSpecifications: true,
2032
+ successUrl,
2033
+ cancelUrl,
2034
+ onAddToCart
2035
+ }
2036
+ ),
2037
+ showRelatedProducts && relatedProducts.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "site-kit-product-page__related", style: { marginTop: "4rem" }, children: [
2038
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: {
2039
+ fontSize: "1.5rem",
2040
+ fontWeight: 600,
2041
+ color: "#111827",
2042
+ marginBottom: "1.5rem"
2043
+ }, children: product.category ? `More ${product.category.name}` : "Related Products" }),
2044
+ /* @__PURE__ */ jsxRuntime.jsx(
2045
+ ProductGrid,
2046
+ {
2047
+ products: relatedProducts,
2048
+ showSearch: false,
2049
+ showSort: false,
2050
+ showCategoryFilter: false,
2051
+ columns: 4,
2052
+ productBasePath: shopBasePath
2053
+ }
2054
+ )
2055
+ ] })
2056
+ ] });
2057
+ }
2058
+ function EventEmbed({
2059
+ event: propEvent,
2060
+ slug,
2061
+ mode = "next",
2062
+ // 'specific', 'next'
2063
+ category,
2064
+ variant = "standard",
2065
+ showDate = true,
2066
+ showTime = true,
2067
+ showLocation = true,
2068
+ showCapacity = true,
2069
+ showPrice = true,
2070
+ showCta = true,
2071
+ ctaText,
2072
+ onRegister,
2073
+ onCtaClick,
2074
+ className = ""
2075
+ }) {
2076
+ const [event, setEvent] = React5.useState(propEvent || null);
2077
+ const [loading, setLoading] = React5.useState(!propEvent && (!!slug || mode === "next"));
2078
+ React5.useEffect(() => {
2079
+ if (propEvent) {
2080
+ setEvent(propEvent);
2081
+ return;
2082
+ }
2083
+ async function load() {
2084
+ setLoading(true);
2085
+ try {
2086
+ let data = null;
2087
+ if (mode === "specific" && slug) {
2088
+ data = await fetchOffering(slug);
2089
+ } else if (mode === "next") {
2090
+ data = await fetchNextEvent(category);
2091
+ }
2092
+ setEvent(data);
2093
+ } catch (e) {
2094
+ console.error("Failed to load event:", e);
2095
+ } finally {
2096
+ setLoading(false);
2097
+ }
2098
+ }
2099
+ load();
2100
+ }, [propEvent, slug, mode, category]);
2101
+ if (loading) {
2102
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-event-embed ${className}`, style: {
2103
+ padding: "2rem",
2104
+ textAlign: "center",
2105
+ background: "#f9fafb",
2106
+ borderRadius: "12px"
2107
+ }, children: [
2108
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
2109
+ width: "40px",
2110
+ height: "40px",
2111
+ margin: "0 auto",
2112
+ border: "3px solid #e5e7eb",
2113
+ borderTopColor: "#2563eb",
2114
+ borderRadius: "50%",
2115
+ animation: "spin 1s linear infinite"
2116
+ } }),
2117
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
2118
+ @keyframes spin {
2119
+ to { transform: rotate(360deg); }
2120
+ }
2121
+ ` })
2122
+ ] });
2123
+ }
2124
+ if (!event) {
2125
+ return null;
2126
+ }
2127
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `site-kit-event-embed ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx(
2128
+ EventTile,
2129
+ {
2130
+ event,
2131
+ variant,
2132
+ showDate,
2133
+ showTime,
2134
+ showLocation,
2135
+ showCapacity,
2136
+ showPrice,
2137
+ showCta,
2138
+ ctaText,
2139
+ onRegister,
2140
+ onCtaClick
2141
+ }
2142
+ ) });
2143
+ }
2144
+ function CheckoutForm({
2145
+ offering,
2146
+ scheduleId,
2147
+ variantId,
2148
+ quantity: initialQuantity = 1,
2149
+ mode = "checkout",
2150
+ // 'checkout' | 'register'
2151
+ showQuantity = true,
2152
+ submitText,
2153
+ onSuccess,
2154
+ onError,
2155
+ className = "",
2156
+ formClassName = "",
2157
+ inputClassName = "",
2158
+ buttonClassName = ""
2159
+ }) {
2160
+ const [loading, setLoading] = React5.useState(false);
2161
+ const [error, setError] = React5.useState(null);
2162
+ const [success, setSuccess] = React5.useState(false);
2163
+ const [quantity, setQuantity] = React5.useState(initialQuantity);
2164
+ const [processor, setProcessor] = React5.useState(null);
2165
+ const [shippingEnabled, setShippingEnabled] = React5.useState(false);
2166
+ const [shippingStep, setShippingStep] = React5.useState("address");
2167
+ const [shippingAddress, setShippingAddress] = React5.useState({
2168
+ street1: "",
2169
+ street2: "",
2170
+ city: "",
2171
+ state: "",
2172
+ zip: "",
2173
+ country: "US"
2174
+ });
2175
+ const [shippingRates, setShippingRates] = React5.useState([]);
2176
+ const [selectedRate, setSelectedRate] = React5.useState(null);
2177
+ const [loadingRates, setLoadingRates] = React5.useState(false);
2178
+ const [customer, setCustomer] = React5.useState({
2179
+ email: "",
2180
+ name: "",
2181
+ phone: ""
2182
+ });
2183
+ const isProduct = offering.type === "product";
2184
+ React5.useEffect(() => {
2185
+ fetchProcessorConfig().then((config) => {
2186
+ if (config?.processor) setProcessor(config.processor);
2187
+ if (config?.shipping_enabled && isProduct) setShippingEnabled(true);
2188
+ });
2189
+ }, [isProduct]);
2190
+ const isEvent = offering.type === "event" || offering.type === "class";
2191
+ const isFree = !offering.price || offering.price === 0;
2192
+ const actualMode = isEvent && isFree ? "register" : mode;
2193
+ const defaultSubmitText = actualMode === "register" ? "Register" : isFree ? "Complete Order" : "Continue to Payment";
2194
+ const subtotal = offering.price ? offering.price * quantity : 0;
2195
+ const shippingCost = selectedRate ? parseFloat(selectedRate.amount) : 0;
2196
+ const total = subtotal + shippingCost;
2197
+ const updateShippingAddress = (field, value) => {
2198
+ setShippingAddress((prev) => ({ ...prev, [field]: value }));
2199
+ };
2200
+ const handleGetShippingRates = async () => {
2201
+ if (!shippingAddress.street1 || !shippingAddress.city || !shippingAddress.state || !shippingAddress.zip) {
2202
+ setError("Please fill in all required address fields.");
2203
+ return;
2204
+ }
2205
+ setLoadingRates(true);
2206
+ setError(null);
2207
+ try {
2208
+ const rates = await fetchShippingRates(
2209
+ { ...shippingAddress, name: customer.name, phone: customer.phone },
2210
+ [{ offering_id: offering.id, quantity }]
2211
+ );
2212
+ setShippingRates(rates);
2213
+ if (rates.length > 0) setSelectedRate(rates[0]);
2214
+ setShippingStep("rates");
2215
+ } catch (e) {
2216
+ setError("Failed to get shipping rates. Please check your address.");
2217
+ } finally {
2218
+ setLoadingRates(false);
2219
+ }
2220
+ };
2221
+ const handleSubmit = async (e) => {
2222
+ e.preventDefault();
2223
+ setLoading(true);
2224
+ setError(null);
2225
+ try {
2226
+ if (actualMode === "register" && isEvent && scheduleId) {
2227
+ const result = await registerForEvent(offering.id, scheduleId, customer);
2228
+ if (result.success) {
2229
+ setSuccess(true);
2230
+ onSuccess?.(result);
2231
+ } else {
2232
+ setError(result.error || "Registration failed");
2233
+ onError?.(result.error || "Registration failed");
2234
+ }
2235
+ } else {
2236
+ const checkoutOptions = {
2237
+ variantId,
2238
+ scheduleId,
2239
+ quantity,
2240
+ customer
2241
+ };
2242
+ if (shippingEnabled && shippingAddress.street1 && selectedRate) {
2243
+ checkoutOptions.shippingAddress = {
2244
+ ...shippingAddress,
2245
+ name: customer.name,
2246
+ phone: customer.phone
2247
+ };
2248
+ checkoutOptions.shippingCarrier = selectedRate.carrier;
2249
+ checkoutOptions.shippingService = selectedRate.service;
2250
+ checkoutOptions.shippingCost = parseFloat(selectedRate.amount);
2251
+ }
2252
+ const result = await createCheckoutSession(offering.id, checkoutOptions);
2253
+ if (result.success && result.payment_url) {
2254
+ window.location.href = result.payment_url;
2255
+ } else {
2256
+ setError(result.error || "Checkout failed");
2257
+ onError?.(result.error || "Checkout failed");
2258
+ }
2259
+ }
2260
+ } catch (err) {
2261
+ const message = err instanceof Error ? err.message : "An error occurred";
2262
+ setError(message);
2263
+ onError?.(message);
2264
+ } finally {
2265
+ setLoading(false);
2266
+ }
2267
+ };
2268
+ const updateCustomer = (field, value) => {
2269
+ setCustomer((prev) => ({ ...prev, [field]: value }));
2270
+ };
2271
+ const canProceedToPayment = !shippingEnabled || shippingStep === "rates" && selectedRate;
2272
+ if (success) {
2273
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-checkout-success ${className}`, style: {
2274
+ padding: "2rem",
2275
+ textAlign: "center",
2276
+ background: "#f0fdf4",
2277
+ borderRadius: "12px",
2278
+ border: "1px solid #bbf7d0"
2279
+ }, children: [
2280
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "3rem", marginBottom: "1rem" }, children: "\u{1F389}" }),
2281
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { style: { margin: "0 0 0.5rem", color: "#166534" }, children: actualMode === "register" ? "Registration Complete!" : "Order Confirmed!" }),
2282
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "#15803d", margin: 0 }, children: actualMode === "register" ? `You're registered for ${offering.name}. Check your email for confirmation.` : `Thank you for your order! Check your email for details.` })
2283
+ ] });
2284
+ }
2285
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `site-kit-checkout ${className}`, children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className: formClassName, children: [
2286
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
2287
+ padding: "1rem",
2288
+ background: "#f9fafb",
2289
+ borderRadius: "8px",
2290
+ marginBottom: "1.5rem"
2291
+ }, children: [
2292
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "flex-start" }, children: [
2293
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2294
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { style: { margin: "0 0 0.25rem", fontSize: "1rem" }, children: offering.name }),
2295
+ offering.short_description && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, fontSize: "0.875rem", color: "#666" }, children: offering.short_description })
2296
+ ] }),
2297
+ offering.price_is_public && offering.price != null && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontWeight: 600, fontSize: "1.125rem" }, children: offering.price === 0 ? "Free" : formatPrice(offering.price, offering.currency) })
2298
+ ] }),
2299
+ showQuantity && !isEvent && offering.price && offering.price > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: "1rem", display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
2300
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { fontSize: "0.875rem", color: "#666" }, children: "Quantity:" }),
2301
+ /* @__PURE__ */ jsxRuntime.jsx(
2302
+ "select",
2303
+ {
2304
+ value: quantity,
2305
+ onChange: (e) => setQuantity(Number(e.target.value)),
2306
+ className: inputClassName,
2307
+ style: {
2308
+ padding: "0.375rem 0.75rem",
2309
+ borderRadius: "6px",
2310
+ border: "1px solid #d1d5db",
2311
+ background: "white"
2312
+ },
2313
+ children: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((n) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: n, children: n }, n))
2314
+ }
2315
+ ),
2316
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { marginLeft: "auto", fontWeight: 600 }, children: shippingEnabled && selectedRate ? `Subtotal: ${formatPrice(subtotal, offering.currency)}` : `Total: ${formatPrice(total, offering.currency)}` })
2317
+ ] })
2318
+ ] }),
2319
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1rem" }, children: [
2320
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2321
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { display: "block", fontSize: "0.875rem", fontWeight: 500, marginBottom: "0.25rem" }, children: "Full Name *" }),
2322
+ /* @__PURE__ */ jsxRuntime.jsx(
2323
+ "input",
2324
+ {
2325
+ type: "text",
2326
+ required: true,
2327
+ value: customer.name,
2328
+ onChange: (e) => updateCustomer("name", e.target.value),
2329
+ className: inputClassName,
2330
+ style: {
2331
+ width: "100%",
2332
+ padding: "0.625rem 0.75rem",
2333
+ borderRadius: "6px",
2334
+ border: "1px solid #d1d5db",
2335
+ fontSize: "1rem"
2336
+ }
2337
+ }
2338
+ )
2339
+ ] }),
2340
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2341
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { display: "block", fontSize: "0.875rem", fontWeight: 500, marginBottom: "0.25rem" }, children: "Email Address *" }),
2342
+ /* @__PURE__ */ jsxRuntime.jsx(
2343
+ "input",
2344
+ {
2345
+ type: "email",
2346
+ required: true,
2347
+ value: customer.email,
2348
+ onChange: (e) => updateCustomer("email", e.target.value),
2349
+ className: inputClassName,
2350
+ style: {
2351
+ width: "100%",
2352
+ padding: "0.625rem 0.75rem",
2353
+ borderRadius: "6px",
2354
+ border: "1px solid #d1d5db",
2355
+ fontSize: "1rem"
2356
+ }
2357
+ }
2358
+ )
2359
+ ] }),
2360
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2361
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { display: "block", fontSize: "0.875rem", fontWeight: 500, marginBottom: "0.25rem" }, children: "Phone Number" }),
2362
+ /* @__PURE__ */ jsxRuntime.jsx(
2363
+ "input",
2364
+ {
2365
+ type: "tel",
2366
+ value: customer.phone || "",
2367
+ onChange: (e) => updateCustomer("phone", e.target.value),
2368
+ className: inputClassName,
2369
+ style: {
2370
+ width: "100%",
2371
+ padding: "0.625rem 0.75rem",
2372
+ borderRadius: "6px",
2373
+ border: "1px solid #d1d5db",
2374
+ fontSize: "1rem"
2375
+ }
2376
+ }
2377
+ )
2378
+ ] })
2379
+ ] }),
2380
+ shippingEnabled && !isEvent && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: "1.5rem", paddingTop: "1.5rem", borderTop: "1px solid #e5e7eb" }, children: [
2381
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { style: { margin: "0 0 1rem", fontSize: "1rem" }, children: "Shipping Address" }),
2382
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1rem" }, children: [
2383
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2384
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { display: "block", fontSize: "0.875rem", fontWeight: 500, marginBottom: "0.25rem" }, children: "Street Address *" }),
2385
+ /* @__PURE__ */ jsxRuntime.jsx(
2386
+ "input",
2387
+ {
2388
+ type: "text",
2389
+ required: shippingEnabled,
2390
+ value: shippingAddress.street1,
2391
+ onChange: (e) => updateShippingAddress("street1", e.target.value),
2392
+ className: inputClassName,
2393
+ placeholder: "123 Main St",
2394
+ style: { width: "100%", padding: "0.625rem 0.75rem", borderRadius: "6px", border: "1px solid #d1d5db", fontSize: "1rem" }
2395
+ }
2396
+ )
2397
+ ] }),
2398
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2399
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { display: "block", fontSize: "0.875rem", fontWeight: 500, marginBottom: "0.25rem" }, children: "Apartment, suite, etc." }),
2400
+ /* @__PURE__ */ jsxRuntime.jsx(
2401
+ "input",
2402
+ {
2403
+ type: "text",
2404
+ value: shippingAddress.street2 || "",
2405
+ onChange: (e) => updateShippingAddress("street2", e.target.value),
2406
+ className: inputClassName,
2407
+ style: { width: "100%", padding: "0.625rem 0.75rem", borderRadius: "6px", border: "1px solid #d1d5db", fontSize: "1rem" }
2408
+ }
2409
+ )
2410
+ ] }),
2411
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "1rem" }, children: [
2412
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2413
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { display: "block", fontSize: "0.875rem", fontWeight: 500, marginBottom: "0.25rem" }, children: "City *" }),
2414
+ /* @__PURE__ */ jsxRuntime.jsx(
2415
+ "input",
2416
+ {
2417
+ type: "text",
2418
+ required: shippingEnabled,
2419
+ value: shippingAddress.city,
2420
+ onChange: (e) => updateShippingAddress("city", e.target.value),
2421
+ className: inputClassName,
2422
+ style: { width: "100%", padding: "0.625rem 0.75rem", borderRadius: "6px", border: "1px solid #d1d5db", fontSize: "1rem" }
2423
+ }
2424
+ )
2425
+ ] }),
2426
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2427
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { display: "block", fontSize: "0.875rem", fontWeight: 500, marginBottom: "0.25rem" }, children: "State *" }),
2428
+ /* @__PURE__ */ jsxRuntime.jsx(
2429
+ "input",
2430
+ {
2431
+ type: "text",
2432
+ required: shippingEnabled,
2433
+ value: shippingAddress.state,
2434
+ onChange: (e) => updateShippingAddress("state", e.target.value),
2435
+ className: inputClassName,
2436
+ style: { width: "100%", padding: "0.625rem 0.75rem", borderRadius: "6px", border: "1px solid #d1d5db", fontSize: "1rem" }
2437
+ }
2438
+ )
2439
+ ] })
2440
+ ] }),
2441
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2442
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { display: "block", fontSize: "0.875rem", fontWeight: 500, marginBottom: "0.25rem" }, children: "ZIP Code *" }),
2443
+ /* @__PURE__ */ jsxRuntime.jsx(
2444
+ "input",
2445
+ {
2446
+ type: "text",
2447
+ required: shippingEnabled,
2448
+ value: shippingAddress.zip,
2449
+ onChange: (e) => updateShippingAddress("zip", e.target.value),
2450
+ className: inputClassName,
2451
+ style: { width: "100%", maxWidth: "120px", padding: "0.625rem 0.75rem", borderRadius: "6px", border: "1px solid #d1d5db", fontSize: "1rem" }
2452
+ }
2453
+ )
2454
+ ] })
2455
+ ] }),
2456
+ shippingStep === "address" && /* @__PURE__ */ jsxRuntime.jsx(
2457
+ "button",
2458
+ {
2459
+ type: "button",
2460
+ onClick: handleGetShippingRates,
2461
+ disabled: loadingRates || !shippingAddress.street1 || !shippingAddress.city || !shippingAddress.state || !shippingAddress.zip,
2462
+ style: {
2463
+ marginTop: "1rem",
2464
+ padding: "0.625rem 1.25rem",
2465
+ borderRadius: "6px",
2466
+ border: "1px solid #2563eb",
2467
+ background: "white",
2468
+ color: "#2563eb",
2469
+ fontSize: "0.875rem",
2470
+ fontWeight: 500,
2471
+ cursor: loadingRates ? "not-allowed" : "pointer"
2472
+ },
2473
+ children: loadingRates ? "Getting rates..." : "Get shipping options"
2474
+ }
2475
+ ),
2476
+ shippingStep === "rates" && shippingRates.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: "1rem" }, children: [
2477
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { display: "block", fontSize: "0.875rem", fontWeight: 500, marginBottom: "0.5rem" }, children: "Select shipping method" }),
2478
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: shippingRates.map((rate) => /* @__PURE__ */ jsxRuntime.jsxs(
2479
+ "label",
2480
+ {
2481
+ style: {
2482
+ display: "flex",
2483
+ alignItems: "center",
2484
+ gap: "0.75rem",
2485
+ padding: "0.75rem",
2486
+ borderRadius: "6px",
2487
+ border: `2px solid ${selectedRate === rate ? "#2563eb" : "#e5e7eb"}`,
2488
+ background: selectedRate === rate ? "#eff6ff" : "white",
2489
+ cursor: "pointer"
2490
+ },
2491
+ children: [
2492
+ /* @__PURE__ */ jsxRuntime.jsx(
2493
+ "input",
2494
+ {
2495
+ type: "radio",
2496
+ name: "shipping-rate",
2497
+ checked: selectedRate === rate,
2498
+ onChange: () => setSelectedRate(rate)
2499
+ }
2500
+ ),
2501
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { flex: 1 }, children: [
2502
+ rate.carrier,
2503
+ " - ",
2504
+ rate.service
2505
+ ] }),
2506
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 600 }, children: formatPrice(parseFloat(rate.amount), rate.currency || "USD") }),
2507
+ rate.estimatedDays && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: "0.75rem", color: "#666" }, children: [
2508
+ "(",
2509
+ rate.estimatedDays,
2510
+ " days)"
2511
+ ] })
2512
+ ]
2513
+ },
2514
+ rate.objectId || `${rate.carrier}-${rate.service}`
2515
+ )) }),
2516
+ /* @__PURE__ */ jsxRuntime.jsx(
2517
+ "button",
2518
+ {
2519
+ type: "button",
2520
+ onClick: () => setShippingStep("address"),
2521
+ style: {
2522
+ marginTop: "0.75rem",
2523
+ fontSize: "0.875rem",
2524
+ color: "#6b7280",
2525
+ background: "none",
2526
+ border: "none",
2527
+ cursor: "pointer",
2528
+ textDecoration: "underline"
2529
+ },
2530
+ children: "Change address"
2531
+ }
2532
+ )
2533
+ ] })
2534
+ ] }),
2535
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
2536
+ marginTop: "1rem",
2537
+ padding: "0.75rem",
2538
+ background: "#fef2f2",
2539
+ border: "1px solid #fecaca",
2540
+ borderRadius: "6px",
2541
+ color: "#dc2626",
2542
+ fontSize: "0.875rem"
2543
+ }, children: error }),
2544
+ /* @__PURE__ */ jsxRuntime.jsx(
2545
+ "button",
2546
+ {
2547
+ type: "submit",
2548
+ disabled: loading || !isEvent && !isFree && !canProceedToPayment,
2549
+ className: buttonClassName,
2550
+ style: {
2551
+ width: "100%",
2552
+ marginTop: "1.5rem",
2553
+ padding: "0.875rem",
2554
+ fontSize: "1rem",
2555
+ fontWeight: 600,
2556
+ borderRadius: "8px",
2557
+ border: "none",
2558
+ background: loading ? "#93c5fd" : "#2563eb",
2559
+ color: "white",
2560
+ cursor: loading ? "not-allowed" : "pointer"
2561
+ },
2562
+ children: loading ? "Processing..." : submitText || defaultSubmitText
2563
+ }
2564
+ ),
2565
+ !isFree && /* @__PURE__ */ jsxRuntime.jsx("p", { style: {
2566
+ textAlign: "center",
2567
+ fontSize: "0.75rem",
2568
+ color: "#666",
2569
+ marginTop: "0.75rem"
2570
+ }, children: "You'll be redirected to our secure payment page" }),
2571
+ processor && !isFree && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
2572
+ display: "flex",
2573
+ alignItems: "center",
2574
+ justifyContent: "center",
2575
+ gap: "0.375rem",
2576
+ marginTop: "0.5rem",
2577
+ opacity: 0.5
2578
+ }, children: [
2579
+ processor === "stripe" ? /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M13.976 9.15c-2.172-.806-3.356-1.426-3.356-2.409 0-.831.683-1.305 1.901-1.305 2.227 0 4.515.858 6.09 1.631l.89-5.494C18.252.975 15.697 0 12.165 0 9.667 0 7.589.654 6.104 1.872 4.56 3.147 3.757 4.992 3.757 7.218c0 4.039 2.467 5.76 6.476 7.219 2.585.92 3.445 1.574 3.445 2.583 0 .98-.84 1.545-2.354 1.545-1.875 0-4.965-.921-6.99-2.109l-.9 5.555C5.175 22.99 8.385 24 11.714 24c2.641 0 4.843-.624 6.328-1.813 1.664-1.305 2.525-3.236 2.525-5.732 0-4.128-2.524-5.851-6.591-7.305z", fill: "#635BFF" }) }) : /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
2580
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "24", height: "24", rx: "4", fill: "#3E4348" }),
2581
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "4", y: "4", width: "16", height: "16", rx: "2", fill: "white" })
2582
+ ] }),
2583
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: "0.625rem", color: "#999", letterSpacing: "0.02em" }, children: [
2584
+ "Powered by ",
2585
+ processor === "stripe" ? "Stripe" : "Square"
2586
+ ] })
2587
+ ] })
2588
+ ] }) });
2589
+ }
2590
+ function RegistrationForm({
2591
+ event,
2592
+ scheduleId,
2593
+ title = "Register for Event",
2594
+ submitText = "Register",
2595
+ successMessage,
2596
+ collectPhone = false,
2597
+ additionalFields = [],
2598
+ onSuccess,
2599
+ onError,
2600
+ className = "",
2601
+ formClassName = "",
2602
+ inputClassName = "",
2603
+ buttonClassName = ""
2604
+ }) {
2605
+ const [loading, setLoading] = React5.useState(false);
2606
+ const [error, setError] = React5.useState(null);
2607
+ const [success, setSuccess] = React5.useState(false);
2608
+ const [customer, setCustomer] = React5.useState({
2609
+ email: "",
2610
+ name: "",
2611
+ phone: ""
2612
+ });
2613
+ const [additionalData, setAdditionalData] = React5.useState({});
2614
+ const handleSubmit = async (e) => {
2615
+ e.preventDefault();
2616
+ setLoading(true);
2617
+ setError(null);
2618
+ try {
2619
+ const result = await registerForEvent(event.id, scheduleId, {
2620
+ ...customer,
2621
+ ...additionalData
2622
+ });
2623
+ if (result.success) {
2624
+ setSuccess(true);
2625
+ onSuccess?.(result);
2626
+ } else {
2627
+ setError(result.error || "Registration failed");
2628
+ onError?.(result.error || "Registration failed");
2629
+ }
2630
+ } catch (err) {
2631
+ const message = err instanceof Error ? err.message : "An error occurred";
2632
+ setError(message);
2633
+ onError?.(message);
2634
+ } finally {
2635
+ setLoading(false);
2636
+ }
2637
+ };
2638
+ if (success) {
2639
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-registration-success ${className}`, style: {
2640
+ padding: "2rem",
2641
+ textAlign: "center",
2642
+ background: "#f0fdf4",
2643
+ borderRadius: "12px",
2644
+ border: "1px solid #bbf7d0"
2645
+ }, children: [
2646
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "3rem", marginBottom: "1rem" }, children: "\u{1F389}" }),
2647
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { style: { margin: "0 0 0.5rem", color: "#166534" }, children: "You're Registered!" }),
2648
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "#15803d", margin: 0 }, children: successMessage || `You've been registered for ${event.name}. Check your email for confirmation.` })
2649
+ ] });
2650
+ }
2651
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-registration ${className}`, children: [
2652
+ title && /* @__PURE__ */ jsxRuntime.jsx("h3", { style: { margin: "0 0 1.5rem", fontSize: "1.25rem", fontWeight: 600 }, children: title }),
2653
+ /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className: formClassName, children: [
2654
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1rem" }, children: [
2655
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2656
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { display: "block", fontSize: "0.875rem", fontWeight: 500, marginBottom: "0.25rem" }, children: "Full Name *" }),
2657
+ /* @__PURE__ */ jsxRuntime.jsx(
2658
+ "input",
2659
+ {
2660
+ type: "text",
2661
+ required: true,
2662
+ value: customer.name,
2663
+ onChange: (e) => setCustomer((prev) => ({ ...prev, name: e.target.value })),
2664
+ className: inputClassName,
2665
+ style: {
2666
+ width: "100%",
2667
+ padding: "0.625rem 0.75rem",
2668
+ borderRadius: "6px",
2669
+ border: "1px solid #d1d5db",
2670
+ fontSize: "1rem"
2671
+ }
2672
+ }
2673
+ )
2674
+ ] }),
2675
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2676
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { display: "block", fontSize: "0.875rem", fontWeight: 500, marginBottom: "0.25rem" }, children: "Email Address *" }),
2677
+ /* @__PURE__ */ jsxRuntime.jsx(
2678
+ "input",
2679
+ {
2680
+ type: "email",
2681
+ required: true,
2682
+ value: customer.email,
2683
+ onChange: (e) => setCustomer((prev) => ({ ...prev, email: e.target.value })),
2684
+ className: inputClassName,
2685
+ style: {
2686
+ width: "100%",
2687
+ padding: "0.625rem 0.75rem",
2688
+ borderRadius: "6px",
2689
+ border: "1px solid #d1d5db",
2690
+ fontSize: "1rem"
2691
+ }
2692
+ }
2693
+ )
2694
+ ] }),
2695
+ collectPhone && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2696
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { display: "block", fontSize: "0.875rem", fontWeight: 500, marginBottom: "0.25rem" }, children: "Phone Number" }),
2697
+ /* @__PURE__ */ jsxRuntime.jsx(
2698
+ "input",
2699
+ {
2700
+ type: "tel",
2701
+ value: customer.phone || "",
2702
+ onChange: (e) => setCustomer((prev) => ({ ...prev, phone: e.target.value })),
2703
+ className: inputClassName,
2704
+ style: {
2705
+ width: "100%",
2706
+ padding: "0.625rem 0.75rem",
2707
+ borderRadius: "6px",
2708
+ border: "1px solid #d1d5db",
2709
+ fontSize: "1rem"
2710
+ }
2711
+ }
2712
+ )
2713
+ ] }),
2714
+ additionalFields.map((field) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2715
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { style: { display: "block", fontSize: "0.875rem", fontWeight: 500, marginBottom: "0.25rem" }, children: [
2716
+ field.label,
2717
+ " ",
2718
+ field.required && "*"
2719
+ ] }),
2720
+ field.type === "textarea" ? /* @__PURE__ */ jsxRuntime.jsx(
2721
+ "textarea",
2722
+ {
2723
+ required: field.required,
2724
+ placeholder: field.placeholder,
2725
+ value: additionalData[field.name] || "",
2726
+ onChange: (e) => setAdditionalData((prev) => ({ ...prev, [field.name]: e.target.value })),
2727
+ className: inputClassName,
2728
+ style: {
2729
+ width: "100%",
2730
+ padding: "0.625rem 0.75rem",
2731
+ borderRadius: "6px",
2732
+ border: "1px solid #d1d5db",
2733
+ fontSize: "1rem",
2734
+ minHeight: "80px"
2735
+ }
2736
+ }
2737
+ ) : field.type === "select" && field.options ? /* @__PURE__ */ jsxRuntime.jsxs(
2738
+ "select",
2739
+ {
2740
+ required: field.required,
2741
+ value: additionalData[field.name] || "",
2742
+ onChange: (e) => setAdditionalData((prev) => ({ ...prev, [field.name]: e.target.value })),
2743
+ className: inputClassName,
2744
+ style: {
2745
+ width: "100%",
2746
+ padding: "0.625rem 0.75rem",
2747
+ borderRadius: "6px",
2748
+ border: "1px solid #d1d5db",
2749
+ fontSize: "1rem",
2750
+ background: "white"
2751
+ },
2752
+ children: [
2753
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Select..." }),
2754
+ field.options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: opt.value, children: opt.label }, opt.value))
2755
+ ]
2756
+ }
2757
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
2758
+ "input",
2759
+ {
2760
+ type: field.type || "text",
2761
+ required: field.required,
2762
+ placeholder: field.placeholder,
2763
+ value: additionalData[field.name] || "",
2764
+ onChange: (e) => setAdditionalData((prev) => ({ ...prev, [field.name]: e.target.value })),
2765
+ className: inputClassName,
2766
+ style: {
2767
+ width: "100%",
2768
+ padding: "0.625rem 0.75rem",
2769
+ borderRadius: "6px",
2770
+ border: "1px solid #d1d5db",
2771
+ fontSize: "1rem"
2772
+ }
2773
+ }
2774
+ )
2775
+ ] }, field.name))
2776
+ ] }),
2777
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
2778
+ marginTop: "1rem",
2779
+ padding: "0.75rem",
2780
+ background: "#fef2f2",
2781
+ border: "1px solid #fecaca",
2782
+ borderRadius: "6px",
2783
+ color: "#dc2626",
2784
+ fontSize: "0.875rem"
2785
+ }, children: error }),
2786
+ /* @__PURE__ */ jsxRuntime.jsx(
2787
+ "button",
2788
+ {
2789
+ type: "submit",
2790
+ disabled: loading,
2791
+ className: buttonClassName,
2792
+ style: {
2793
+ width: "100%",
2794
+ marginTop: "1.5rem",
2795
+ padding: "0.875rem",
2796
+ fontSize: "1rem",
2797
+ fontWeight: 600,
2798
+ borderRadius: "8px",
2799
+ border: "none",
2800
+ background: loading ? "#93c5fd" : "#2563eb",
2801
+ color: "white",
2802
+ cursor: loading ? "not-allowed" : "pointer"
2803
+ },
2804
+ children: loading ? "Registering..." : submitText
2805
+ }
2806
+ )
2807
+ ] })
2808
+ ] });
2809
+ }
2810
+ var DAYS_SHORT = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
2811
+ var MONTHS = [
2812
+ "January",
2813
+ "February",
2814
+ "March",
2815
+ "April",
2816
+ "May",
2817
+ "June",
2818
+ "July",
2819
+ "August",
2820
+ "September",
2821
+ "October",
2822
+ "November",
2823
+ "December"
2824
+ ];
2825
+ function formatDateForTooltip(dateStr) {
2826
+ const d = new Date(dateStr);
2827
+ return d.toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric", year: "numeric" });
2828
+ }
2829
+ function CalendarEventCell({
2830
+ item,
2831
+ eventDisplay,
2832
+ eventClassName,
2833
+ onEventClick,
2834
+ formatTime: formatTime2
2835
+ }) {
2836
+ const [hover, setHover] = React5__default.default.useState(false);
2837
+ const { event, schedule } = item;
2838
+ const imageUrl = event.featured_image_url;
2839
+ if (eventDisplay === "image") {
2840
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2841
+ "div",
2842
+ {
2843
+ className: `site-kit-calendar-event-image-wrapper ${eventClassName}`,
2844
+ style: { position: "relative" },
2845
+ onMouseEnter: () => setHover(true),
2846
+ onMouseLeave: () => setHover(false),
2847
+ children: [
2848
+ /* @__PURE__ */ jsxRuntime.jsx(
2849
+ "button",
2850
+ {
2851
+ onClick: onEventClick,
2852
+ className: `site-kit-calendar-event site-kit-calendar-event-image ${eventClassName}`,
2853
+ style: {
2854
+ display: "block",
2855
+ width: "100%",
2856
+ height: "28px",
2857
+ padding: 0,
2858
+ border: "none",
2859
+ borderRadius: "4px",
2860
+ cursor: "pointer",
2861
+ overflow: "hidden",
2862
+ background: imageUrl ? "transparent" : "#dbeafe"
2863
+ },
2864
+ children: imageUrl ? /* @__PURE__ */ jsxRuntime.jsx(
2865
+ "img",
2866
+ {
2867
+ src: imageUrl,
2868
+ alt: event.name,
2869
+ style: {
2870
+ width: "100%",
2871
+ height: "100%",
2872
+ objectFit: "cover"
2873
+ }
2874
+ }
2875
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
2876
+ fontSize: "0.65rem",
2877
+ color: "#1d4ed8",
2878
+ fontWeight: 500,
2879
+ padding: "2px 4px",
2880
+ display: "block",
2881
+ overflow: "hidden",
2882
+ textOverflow: "ellipsis",
2883
+ whiteSpace: "nowrap"
2884
+ }, children: event.name })
2885
+ }
2886
+ ),
2887
+ /* @__PURE__ */ jsxRuntime.jsxs(
2888
+ "div",
2889
+ {
2890
+ className: "site-kit-calendar-event-tooltip",
2891
+ style: {
2892
+ position: "absolute",
2893
+ bottom: "100%",
2894
+ left: "50%",
2895
+ transform: "translateX(-50%) translateY(-4px)",
2896
+ padding: "8px 12px",
2897
+ background: "#1f2937",
2898
+ color: "white",
2899
+ borderRadius: "8px",
2900
+ fontSize: "0.75rem",
2901
+ minWidth: "180px",
2902
+ maxWidth: "220px",
2903
+ boxShadow: "0 4px 12px rgba(0,0,0,0.2)",
2904
+ pointerEvents: "none",
2905
+ opacity: hover ? 1 : 0,
2906
+ visibility: hover ? "visible" : "hidden",
2907
+ transition: "opacity 0.15s, visibility 0.15s",
2908
+ zIndex: 50
2909
+ },
2910
+ children: [
2911
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontWeight: 600, marginBottom: "4px" }, children: event.name }),
2912
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { opacity: 0.9, fontSize: "0.7rem" }, children: [
2913
+ formatDateForTooltip(schedule.starts_at),
2914
+ " \u2022 ",
2915
+ formatTime2(schedule.starts_at)
2916
+ ] }),
2917
+ event.location && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { opacity: 0.8, fontSize: "0.65rem", marginTop: "2px" }, children: event.location })
2918
+ ]
2919
+ }
2920
+ )
2921
+ ]
2922
+ }
2923
+ );
2924
+ }
2925
+ return /* @__PURE__ */ jsxRuntime.jsx(
2926
+ "button",
2927
+ {
2928
+ onClick: onEventClick,
2929
+ className: `site-kit-calendar-event ${eventClassName}`,
2930
+ style: {
2931
+ display: "block",
2932
+ width: "100%",
2933
+ padding: "2px 4px",
2934
+ fontSize: "0.7rem",
2935
+ fontWeight: 500,
2936
+ textAlign: "left",
2937
+ border: "none",
2938
+ borderRadius: "3px",
2939
+ background: "#dbeafe",
2940
+ color: "#1d4ed8",
2941
+ cursor: "pointer",
2942
+ overflow: "hidden",
2943
+ whiteSpace: "nowrap",
2944
+ textOverflow: "ellipsis"
2945
+ },
2946
+ title: `${event.name} - ${formatTime2(schedule.starts_at)}`,
2947
+ children: event.name
2948
+ }
2949
+ );
2950
+ }
2951
+ function CalendarView({
2952
+ events: propEvents,
2953
+ initialDate,
2954
+ category,
2955
+ onEventClick,
2956
+ onDayClick,
2957
+ showNavigation = true,
2958
+ showHeader = true,
2959
+ weekStartsOn = 0,
2960
+ minDate,
2961
+ maxDate,
2962
+ eventDisplay = "image",
2963
+ className = "",
2964
+ headerClassName = "",
2965
+ dayClassName = "",
2966
+ eventClassName = "",
2967
+ todayClassName = ""
2968
+ }) {
2969
+ const [currentDate, setCurrentDate] = React5.useState(initialDate || /* @__PURE__ */ new Date());
2970
+ const [events, setEvents] = React5.useState(propEvents || []);
2971
+ const [loading, setLoading] = React5.useState(!propEvents);
2972
+ React5.useEffect(() => {
2973
+ if (propEvents) {
2974
+ setEvents(propEvents);
2975
+ return;
2976
+ }
2977
+ async function load() {
2978
+ setLoading(true);
2979
+ try {
2980
+ const data = await fetchUpcomingEvents({ limit: 100, category });
2981
+ setEvents(data);
2982
+ } catch (e) {
2983
+ console.error("Failed to load events:", e);
2984
+ } finally {
2985
+ setLoading(false);
2986
+ }
2987
+ }
2988
+ load();
2989
+ }, [propEvents, category]);
2990
+ const calendarDays = React5.useMemo(() => {
2991
+ const year = currentDate.getFullYear();
2992
+ const month = currentDate.getMonth();
2993
+ const firstDay = new Date(year, month, 1);
2994
+ const lastDay = new Date(year, month + 1, 0);
2995
+ const startDate = new Date(firstDay);
2996
+ const dayOfWeek = startDate.getDay();
2997
+ const daysToSubtract = (dayOfWeek - weekStartsOn + 7) % 7;
2998
+ startDate.setDate(startDate.getDate() - daysToSubtract);
2999
+ const endDate = new Date(lastDay);
3000
+ const endDayOfWeek = endDate.getDay();
3001
+ const daysToAdd = (6 - endDayOfWeek + weekStartsOn) % 7;
3002
+ endDate.setDate(endDate.getDate() + daysToAdd);
3003
+ const eventsByDate = /* @__PURE__ */ new Map();
3004
+ events.forEach((event) => {
3005
+ const schedules = event.schedules || [];
3006
+ schedules.forEach((schedule) => {
3007
+ const scheduleDate = new Date(schedule.starts_at);
3008
+ const dateKey = `${scheduleDate.getFullYear()}-${scheduleDate.getMonth()}-${scheduleDate.getDate()}`;
3009
+ if (!eventsByDate.has(dateKey)) {
3010
+ eventsByDate.set(dateKey, []);
3011
+ }
3012
+ eventsByDate.get(dateKey).push({ event, schedule });
3013
+ });
3014
+ });
3015
+ const days = [];
3016
+ const today = /* @__PURE__ */ new Date();
3017
+ const todayKey = `${today.getFullYear()}-${today.getMonth()}-${today.getDate()}`;
3018
+ const current = new Date(startDate);
3019
+ while (current <= endDate) {
3020
+ const dateKey = `${current.getFullYear()}-${current.getMonth()}-${current.getDate()}`;
3021
+ days.push({
3022
+ date: new Date(current),
3023
+ isCurrentMonth: current.getMonth() === month,
3024
+ isToday: dateKey === todayKey,
3025
+ events: eventsByDate.get(dateKey) || []
3026
+ });
3027
+ current.setDate(current.getDate() + 1);
3028
+ }
3029
+ return days;
3030
+ }, [currentDate, events, weekStartsOn]);
3031
+ const goToPreviousMonth = () => {
3032
+ const newDate = new Date(currentDate);
3033
+ newDate.setMonth(newDate.getMonth() - 1);
3034
+ if (!minDate || newDate >= minDate) {
3035
+ setCurrentDate(newDate);
3036
+ }
3037
+ };
3038
+ const goToNextMonth = () => {
3039
+ const newDate = new Date(currentDate);
3040
+ newDate.setMonth(newDate.getMonth() + 1);
3041
+ if (!maxDate || newDate <= maxDate) {
3042
+ setCurrentDate(newDate);
3043
+ }
3044
+ };
3045
+ const goToToday = () => {
3046
+ setCurrentDate(/* @__PURE__ */ new Date());
3047
+ };
3048
+ const dayHeaders = weekStartsOn === 1 ? [...DAYS_SHORT.slice(1), DAYS_SHORT[0]] : DAYS_SHORT;
3049
+ const handleEventClick = (e, event, schedule) => {
3050
+ e.stopPropagation();
3051
+ if (onEventClick) {
3052
+ onEventClick(event, schedule);
3053
+ } else {
3054
+ window.location.href = `/events/${event.slug}`;
3055
+ }
3056
+ };
3057
+ const handleDayClick = (day) => {
3058
+ if (onDayClick) {
3059
+ onDayClick(day.date, day.events);
3060
+ }
3061
+ };
3062
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-calendar ${className}`, style: {
3063
+ background: "white",
3064
+ borderRadius: "12px",
3065
+ overflow: "hidden",
3066
+ boxShadow: "0 1px 3px rgba(0,0,0,0.1)"
3067
+ }, children: [
3068
+ showHeader && /* @__PURE__ */ jsxRuntime.jsxs(
3069
+ "div",
3070
+ {
3071
+ className: `site-kit-calendar-header ${headerClassName}`,
3072
+ style: {
3073
+ display: "flex",
3074
+ alignItems: "center",
3075
+ justifyContent: "space-between",
3076
+ padding: "1rem 1.25rem",
3077
+ borderBottom: "1px solid #e5e7eb"
3078
+ },
3079
+ children: [
3080
+ showNavigation && /* @__PURE__ */ jsxRuntime.jsx(
3081
+ "button",
3082
+ {
3083
+ onClick: goToPreviousMonth,
3084
+ style: {
3085
+ padding: "0.5rem",
3086
+ border: "none",
3087
+ background: "#f3f4f6",
3088
+ borderRadius: "6px",
3089
+ cursor: "pointer",
3090
+ fontSize: "1.25rem",
3091
+ lineHeight: 1
3092
+ },
3093
+ "aria-label": "Previous month",
3094
+ children: "\u2190"
3095
+ }
3096
+ ),
3097
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center" }, children: [
3098
+ /* @__PURE__ */ jsxRuntime.jsxs("h2", { style: { margin: 0, fontSize: "1.25rem", fontWeight: 600 }, children: [
3099
+ MONTHS[currentDate.getMonth()],
3100
+ " ",
3101
+ currentDate.getFullYear()
3102
+ ] }),
3103
+ showNavigation && /* @__PURE__ */ jsxRuntime.jsx(
3104
+ "button",
3105
+ {
3106
+ onClick: goToToday,
3107
+ style: {
3108
+ marginTop: "0.25rem",
3109
+ padding: "0.25rem 0.5rem",
3110
+ fontSize: "0.75rem",
3111
+ border: "none",
3112
+ background: "transparent",
3113
+ color: "#2563eb",
3114
+ cursor: "pointer"
3115
+ },
3116
+ children: "Today"
3117
+ }
3118
+ )
3119
+ ] }),
3120
+ showNavigation && /* @__PURE__ */ jsxRuntime.jsx(
3121
+ "button",
3122
+ {
3123
+ onClick: goToNextMonth,
3124
+ style: {
3125
+ padding: "0.5rem",
3126
+ border: "none",
3127
+ background: "#f3f4f6",
3128
+ borderRadius: "6px",
3129
+ cursor: "pointer",
3130
+ fontSize: "1.25rem",
3131
+ lineHeight: 1
3132
+ },
3133
+ "aria-label": "Next month",
3134
+ children: "\u2192"
3135
+ }
3136
+ )
3137
+ ]
3138
+ }
3139
+ ),
3140
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
3141
+ display: "grid",
3142
+ gridTemplateColumns: "repeat(7, 1fr)",
3143
+ borderBottom: "1px solid #e5e7eb"
3144
+ }, children: dayHeaders.map((day) => /* @__PURE__ */ jsxRuntime.jsx(
3145
+ "div",
3146
+ {
3147
+ style: {
3148
+ padding: "0.75rem 0.5rem",
3149
+ textAlign: "center",
3150
+ fontSize: "0.75rem",
3151
+ fontWeight: 600,
3152
+ color: "#666",
3153
+ textTransform: "uppercase"
3154
+ },
3155
+ children: day
3156
+ },
3157
+ day
3158
+ )) }),
3159
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
3160
+ display: "grid",
3161
+ gridTemplateColumns: "repeat(7, 1fr)"
3162
+ }, children: calendarDays.map((day, index) => /* @__PURE__ */ jsxRuntime.jsxs(
3163
+ "div",
3164
+ {
3165
+ onClick: () => handleDayClick(day),
3166
+ className: `site-kit-calendar-day ${dayClassName} ${day.isToday ? `site-kit-calendar-today ${todayClassName}` : ""}`,
3167
+ style: {
3168
+ minHeight: "100px",
3169
+ padding: "0.5rem",
3170
+ borderRight: (index + 1) % 7 !== 0 ? "1px solid #e5e7eb" : "none",
3171
+ borderBottom: "1px solid #e5e7eb",
3172
+ background: day.isCurrentMonth ? "white" : "#f9fafb",
3173
+ cursor: day.events.length > 0 || onDayClick ? "pointer" : "default"
3174
+ },
3175
+ children: [
3176
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
3177
+ display: "flex",
3178
+ justifyContent: "flex-end",
3179
+ marginBottom: "0.25rem"
3180
+ }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
3181
+ display: "inline-flex",
3182
+ alignItems: "center",
3183
+ justifyContent: "center",
3184
+ width: "28px",
3185
+ height: "28px",
3186
+ borderRadius: "50%",
3187
+ fontSize: "0.875rem",
3188
+ fontWeight: day.isToday ? 600 : 400,
3189
+ color: day.isToday ? "white" : day.isCurrentMonth ? "#111" : "#9ca3af",
3190
+ background: day.isToday ? "#2563eb" : "transparent"
3191
+ }, children: day.date.getDate() }) }),
3192
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "2px" }, children: [
3193
+ day.events.slice(0, 3).map((item) => /* @__PURE__ */ jsxRuntime.jsx(
3194
+ CalendarEventCell,
3195
+ {
3196
+ item,
3197
+ eventDisplay,
3198
+ eventClassName,
3199
+ onEventClick: (e) => handleEventClick(e, item.event, item.schedule),
3200
+ formatTime
3201
+ },
3202
+ `${item.event.id}-${item.schedule.id}`
3203
+ )),
3204
+ day.events.length > 3 && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: {
3205
+ fontSize: "0.65rem",
3206
+ color: "#666",
3207
+ textAlign: "center"
3208
+ }, children: [
3209
+ "+",
3210
+ day.events.length - 3,
3211
+ " more"
3212
+ ] })
3213
+ ] })
3214
+ ]
3215
+ },
3216
+ index
3217
+ )) }),
3218
+ loading && /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
3219
+ position: "absolute",
3220
+ inset: 0,
3221
+ display: "flex",
3222
+ alignItems: "center",
3223
+ justifyContent: "center",
3224
+ background: "rgba(255,255,255,0.8)"
3225
+ }, children: "Loading..." })
3226
+ ] });
3227
+ }
3228
+ function loadSquareSDK(environment) {
3229
+ return new Promise((resolve, reject) => {
3230
+ if (typeof window === "undefined") return reject(new Error("No window"));
3231
+ if (window.Square) return resolve();
3232
+ const script = document.createElement("script");
3233
+ script.src = environment === "sandbox" ? "https://sandbox.web.squarecdn.com/v1/square.js" : "https://web.squarecdn.com/v1/square.js";
3234
+ script.onload = () => resolve();
3235
+ script.onerror = () => reject(new Error("Failed to load Square SDK"));
3236
+ document.head.appendChild(script);
3237
+ });
3238
+ }
3239
+ function EventModal({
3240
+ event,
3241
+ schedule: propSchedule,
3242
+ isOpen,
3243
+ onClose,
3244
+ onSuccess,
3245
+ onError,
3246
+ collectPhone = false,
3247
+ additionalFields = [],
3248
+ className = "",
3249
+ overlayClassName = "",
3250
+ contentClassName = ""
3251
+ }) {
3252
+ const [loading, setLoading] = React5.useState(false);
3253
+ const [error, setError] = React5.useState(null);
3254
+ const [success, setSuccess] = React5.useState(false);
3255
+ const [quantity, setQuantity] = React5.useState(1);
3256
+ const [customer, setCustomer] = React5.useState({
3257
+ email: "",
3258
+ name: "",
3259
+ phone: ""
3260
+ });
3261
+ const [additionalData, setAdditionalData] = React5.useState({});
3262
+ const [processor, setProcessor] = React5.useState(null);
3263
+ const [processorConfig, setProcessorConfig] = React5.useState(null);
3264
+ const [squareCard, setSquareCard] = React5.useState(null);
3265
+ const [cardReady, setCardReady] = React5.useState(false);
3266
+ const cardContainerRef = React5.useRef(null);
3267
+ const schedule = propSchedule || event?.schedules?.[0] || event?.next_schedule;
3268
+ React5.useEffect(() => {
3269
+ if (!isOpen) return;
3270
+ fetchProcessorConfig().then(async (config) => {
3271
+ setProcessorConfig(config);
3272
+ if (config?.processor) setProcessor(config.processor);
3273
+ if (config?.processor === "square" && config.squareAppId && config.squareLocationId) {
3274
+ try {
3275
+ await loadSquareSDK(config.squareEnvironment || "production");
3276
+ const Square = window.Square;
3277
+ const payments = Square.payments(config.squareAppId, config.squareLocationId);
3278
+ const card = await payments.card({
3279
+ style: {
3280
+ ".input-container": {
3281
+ borderColor: "#d1d5db",
3282
+ borderRadius: "6px"
3283
+ },
3284
+ ".input-container.is-focus": {
3285
+ borderColor: "#2563eb"
3286
+ },
3287
+ ".input-container.is-error": {
3288
+ borderColor: "#dc2626"
3289
+ }
3290
+ }
3291
+ });
3292
+ await card.attach("#sq-card-container");
3293
+ setSquareCard(card);
3294
+ setCardReady(true);
3295
+ } catch (err) {
3296
+ console.error("[Commerce] Square card init failed:", err);
3297
+ }
3298
+ }
3299
+ });
3300
+ return () => {
3301
+ setSquareCard((prev) => {
3302
+ if (prev) {
3303
+ prev.destroy?.().catch(() => {
3304
+ });
3305
+ }
3306
+ return null;
3307
+ });
3308
+ setCardReady(false);
3309
+ setProcessorConfig(null);
3310
+ };
3311
+ }, [isOpen]);
3312
+ React5.useEffect(() => {
3313
+ if (isOpen && event) {
3314
+ setError(null);
3315
+ setSuccess(false);
3316
+ setQuantity(1);
3317
+ setCustomer({ email: "", name: "", phone: "" });
3318
+ setAdditionalData({});
3319
+ }
3320
+ }, [isOpen, event?.id]);
3321
+ React5.useEffect(() => {
3322
+ const handleEscape = (e) => {
3323
+ if (e.key === "Escape" && isOpen) {
3324
+ onClose();
3325
+ }
3326
+ };
3327
+ document.addEventListener("keydown", handleEscape);
3328
+ return () => document.removeEventListener("keydown", handleEscape);
3329
+ }, [isOpen, onClose]);
3330
+ React5.useEffect(() => {
3331
+ if (isOpen) {
3332
+ document.body.style.overflow = "hidden";
3333
+ } else {
3334
+ document.body.style.overflow = "";
3335
+ }
3336
+ return () => {
3337
+ document.body.style.overflow = "";
3338
+ };
3339
+ }, [isOpen]);
3340
+ const handleOverlayClick = React5.useCallback((e) => {
3341
+ if (e.target === e.currentTarget) {
3342
+ onClose();
3343
+ }
3344
+ }, [onClose]);
3345
+ if (!isOpen || !event) return null;
3346
+ const isFree = !event.price || event.price === 0;
3347
+ const soldOut = schedule ? isEventSoldOut(schedule.capacity, schedule.current_registrations) : false;
3348
+ const spotsRemaining = schedule ? getSpotsRemaining(schedule.capacity, schedule.current_registrations) : null;
3349
+ const total = event.price ? event.price * quantity : 0;
3350
+ const handleSubmit = async (e) => {
3351
+ e.preventDefault();
3352
+ if (!schedule) {
3353
+ setError("No schedule available for this event");
3354
+ return;
3355
+ }
3356
+ setLoading(true);
3357
+ setError(null);
3358
+ try {
3359
+ if (isFree) {
3360
+ const result = await registerForEvent(event.id, schedule.id, {
3361
+ ...customer,
3362
+ ...additionalData
3363
+ });
3364
+ if (result.success) {
3365
+ setSuccess(true);
3366
+ onSuccess?.(result);
3367
+ } else {
3368
+ setError(result.error || "Registration failed");
3369
+ onError?.(result.error || "Registration failed");
3370
+ }
3371
+ } else {
3372
+ let sourceId;
3373
+ if (squareCard && cardReady) {
3374
+ const tokenResult = await squareCard.tokenize();
3375
+ if (tokenResult.status !== "OK") {
3376
+ const msg = tokenResult.errors?.[0]?.message || "Card verification failed. Please check your card details.";
3377
+ setError(msg);
3378
+ onError?.(msg);
3379
+ setLoading(false);
3380
+ return;
3381
+ }
3382
+ sourceId = tokenResult.token;
3383
+ }
3384
+ const result = await createCheckoutSession({
3385
+ offeringId: event.id,
3386
+ scheduleId: schedule.id,
3387
+ quantity,
3388
+ customer: {
3389
+ ...customer,
3390
+ ...additionalData
3391
+ },
3392
+ sourceId,
3393
+ successUrl: window.location.href + "?registration=success",
3394
+ cancelUrl: window.location.href
3395
+ });
3396
+ if (result.success && !result.payment_url) {
3397
+ setSuccess(true);
3398
+ onSuccess?.(result);
3399
+ } else if (result.success && result.payment_url) {
3400
+ window.location.href = result.payment_url;
3401
+ } else {
3402
+ setError(result.error || "Checkout failed");
3403
+ onError?.(result.error || "Checkout failed");
3404
+ }
3405
+ }
3406
+ } catch (err) {
3407
+ const message = err instanceof Error ? err.message : "An error occurred";
3408
+ setError(message);
3409
+ onError?.(message);
3410
+ } finally {
3411
+ setLoading(false);
3412
+ }
3413
+ };
3414
+ const updateCustomer = (field, value) => {
3415
+ setCustomer((prev) => ({ ...prev, [field]: value }));
3416
+ };
3417
+ return /* @__PURE__ */ jsxRuntime.jsx(
3418
+ "div",
3419
+ {
3420
+ className: `site-kit-modal-overlay ${overlayClassName}`,
3421
+ onClick: handleOverlayClick,
3422
+ style: {
3423
+ position: "fixed",
3424
+ inset: 0,
3425
+ zIndex: 9999,
3426
+ display: "flex",
3427
+ alignItems: "center",
3428
+ justifyContent: "center",
3429
+ padding: "1rem",
3430
+ background: "rgba(0, 0, 0, 0.5)",
3431
+ backdropFilter: "blur(4px)"
3432
+ },
3433
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
3434
+ "div",
3435
+ {
3436
+ className: `site-kit-modal ${className}`,
3437
+ style: {
3438
+ position: "relative",
3439
+ width: "100%",
3440
+ maxWidth: "500px",
3441
+ maxHeight: "90vh",
3442
+ overflow: "auto",
3443
+ background: "white",
3444
+ borderRadius: "16px",
3445
+ boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)"
3446
+ },
3447
+ onClick: (e) => e.stopPropagation(),
3448
+ children: [
3449
+ /* @__PURE__ */ jsxRuntime.jsx(
3450
+ "button",
3451
+ {
3452
+ onClick: onClose,
3453
+ style: {
3454
+ position: "absolute",
3455
+ top: "1rem",
3456
+ right: "1rem",
3457
+ padding: "0.5rem",
3458
+ border: "none",
3459
+ background: "#f3f4f6",
3460
+ borderRadius: "50%",
3461
+ cursor: "pointer",
3462
+ fontSize: "1.25rem",
3463
+ lineHeight: 1,
3464
+ width: "36px",
3465
+ height: "36px",
3466
+ display: "flex",
3467
+ alignItems: "center",
3468
+ justifyContent: "center",
3469
+ zIndex: 10
3470
+ },
3471
+ "aria-label": "Close",
3472
+ children: "\xD7"
3473
+ }
3474
+ ),
3475
+ event.featured_image_url && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative" }, children: [
3476
+ /* @__PURE__ */ jsxRuntime.jsx(
3477
+ "img",
3478
+ {
3479
+ src: event.featured_image_url,
3480
+ alt: event.name,
3481
+ style: {
3482
+ width: "100%",
3483
+ height: "180px",
3484
+ objectFit: "cover",
3485
+ borderRadius: "16px 16px 0 0"
3486
+ }
3487
+ }
3488
+ ),
3489
+ soldOut && /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
3490
+ position: "absolute",
3491
+ top: "1rem",
3492
+ left: "1rem",
3493
+ background: "#ef4444",
3494
+ color: "white",
3495
+ padding: "0.25rem 0.75rem",
3496
+ borderRadius: "4px",
3497
+ fontSize: "0.875rem",
3498
+ fontWeight: 600
3499
+ }, children: "Sold Out" })
3500
+ ] }),
3501
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `site-kit-modal-content ${contentClassName}`, style: { padding: "1.5rem" }, children: success ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", padding: "2rem 0" }, children: [
3502
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "4rem", marginBottom: "1rem" }, children: "\u{1F389}" }),
3503
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { margin: "0 0 0.5rem", color: "#166534" }, children: "You're Registered!" }),
3504
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "#15803d", margin: "0 0 1.5rem" }, children: "Check your email for confirmation details." }),
3505
+ /* @__PURE__ */ jsxRuntime.jsx(
3506
+ "button",
3507
+ {
3508
+ onClick: onClose,
3509
+ style: {
3510
+ padding: "0.75rem 2rem",
3511
+ fontSize: "1rem",
3512
+ fontWeight: 500,
3513
+ border: "none",
3514
+ borderRadius: "8px",
3515
+ background: "#2563eb",
3516
+ color: "white",
3517
+ cursor: "pointer"
3518
+ },
3519
+ children: "Done"
3520
+ }
3521
+ )
3522
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3523
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginBottom: "1.5rem" }, children: [
3524
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { margin: "0 0 0.5rem", fontSize: "1.5rem", fontWeight: 600, paddingRight: "2rem" }, children: event.name }),
3525
+ schedule && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexWrap: "wrap", gap: "1rem", color: "#666", fontSize: "0.9rem" }, children: [
3526
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
3527
+ "\u{1F4C5} ",
3528
+ formatDate(schedule.starts_at)
3529
+ ] }),
3530
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
3531
+ "\u{1F550} ",
3532
+ formatTime(schedule.starts_at)
3533
+ ] }),
3534
+ event.location && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
3535
+ "\u{1F4CD} ",
3536
+ event.location
3537
+ ] })
3538
+ ] }),
3539
+ event.short_description && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: "0.75rem 0 0", color: "#666", fontSize: "0.9rem" }, children: event.short_description }),
3540
+ spotsRemaining !== null && spotsRemaining <= 10 && spotsRemaining > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
3541
+ marginTop: "0.75rem",
3542
+ padding: "0.5rem 0.75rem",
3543
+ background: "#fef3c7",
3544
+ borderRadius: "6px",
3545
+ color: "#92400e",
3546
+ fontSize: "0.875rem"
3547
+ }, children: [
3548
+ "\u26A0\uFE0F Only ",
3549
+ spotsRemaining,
3550
+ " spot",
3551
+ spotsRemaining > 1 ? "s" : "",
3552
+ " remaining!"
3553
+ ] })
3554
+ ] }),
3555
+ soldOut ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
3556
+ padding: "2rem",
3557
+ textAlign: "center",
3558
+ background: "#f3f4f6",
3559
+ borderRadius: "8px"
3560
+ }, children: /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, color: "#666" }, children: "This event is sold out. Check back for future dates!" }) }) : /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, children: [
3561
+ !isFree && event.price_is_public && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
3562
+ padding: "1rem",
3563
+ background: "#f9fafb",
3564
+ borderRadius: "8px",
3565
+ marginBottom: "1rem"
3566
+ }, children: [
3567
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
3568
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3569
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 600, fontSize: "1.25rem" }, children: formatPrice(event.price, event.currency) }),
3570
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#666", fontSize: "0.875rem" }, children: " per ticket" })
3571
+ ] }),
3572
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
3573
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { fontSize: "0.875rem", color: "#666" }, children: "Qty:" }),
3574
+ /* @__PURE__ */ jsxRuntime.jsx(
3575
+ "select",
3576
+ {
3577
+ value: quantity,
3578
+ onChange: (e) => setQuantity(Number(e.target.value)),
3579
+ style: {
3580
+ padding: "0.5rem",
3581
+ borderRadius: "6px",
3582
+ border: "1px solid #d1d5db",
3583
+ background: "white",
3584
+ fontSize: "1rem"
3585
+ },
3586
+ children: [...Array(Math.min(10, spotsRemaining || 10))].map((_, i) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: i + 1, children: i + 1 }, i + 1))
3587
+ }
3588
+ )
3589
+ ] })
3590
+ ] }),
3591
+ quantity > 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
3592
+ marginTop: "0.75rem",
3593
+ paddingTop: "0.75rem",
3594
+ borderTop: "1px solid #e5e7eb",
3595
+ display: "flex",
3596
+ justifyContent: "space-between"
3597
+ }, children: [
3598
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 500 }, children: "Total" }),
3599
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 600, fontSize: "1.125rem" }, children: formatPrice(total, event.currency) })
3600
+ ] })
3601
+ ] }),
3602
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.875rem" }, children: [
3603
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3604
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { display: "block", fontSize: "0.875rem", fontWeight: 500, marginBottom: "0.25rem" }, children: "Full Name *" }),
3605
+ /* @__PURE__ */ jsxRuntime.jsx(
3606
+ "input",
3607
+ {
3608
+ type: "text",
3609
+ required: true,
3610
+ value: customer.name,
3611
+ onChange: (e) => updateCustomer("name", e.target.value),
3612
+ placeholder: "John Smith",
3613
+ style: {
3614
+ width: "100%",
3615
+ padding: "0.625rem 0.75rem",
3616
+ borderRadius: "6px",
3617
+ border: "1px solid #d1d5db",
3618
+ fontSize: "1rem"
3619
+ }
3620
+ }
3621
+ )
3622
+ ] }),
3623
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3624
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { display: "block", fontSize: "0.875rem", fontWeight: 500, marginBottom: "0.25rem" }, children: "Email Address *" }),
3625
+ /* @__PURE__ */ jsxRuntime.jsx(
3626
+ "input",
3627
+ {
3628
+ type: "email",
3629
+ required: true,
3630
+ value: customer.email,
3631
+ onChange: (e) => updateCustomer("email", e.target.value),
3632
+ placeholder: "john@example.com",
3633
+ style: {
3634
+ width: "100%",
3635
+ padding: "0.625rem 0.75rem",
3636
+ borderRadius: "6px",
3637
+ border: "1px solid #d1d5db",
3638
+ fontSize: "1rem"
3639
+ }
3640
+ }
3641
+ )
3642
+ ] }),
3643
+ collectPhone && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3644
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: { display: "block", fontSize: "0.875rem", fontWeight: 500, marginBottom: "0.25rem" }, children: "Phone Number" }),
3645
+ /* @__PURE__ */ jsxRuntime.jsx(
3646
+ "input",
3647
+ {
3648
+ type: "tel",
3649
+ value: customer.phone || "",
3650
+ onChange: (e) => updateCustomer("phone", e.target.value),
3651
+ placeholder: "(555) 123-4567",
3652
+ style: {
3653
+ width: "100%",
3654
+ padding: "0.625rem 0.75rem",
3655
+ borderRadius: "6px",
3656
+ border: "1px solid #d1d5db",
3657
+ fontSize: "1rem"
3658
+ }
3659
+ }
3660
+ )
3661
+ ] }),
3662
+ additionalFields.map((field) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3663
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { style: { display: "block", fontSize: "0.875rem", fontWeight: 500, marginBottom: "0.25rem" }, children: [
3664
+ field.label,
3665
+ " ",
3666
+ field.required && "*"
3667
+ ] }),
3668
+ field.type === "textarea" ? /* @__PURE__ */ jsxRuntime.jsx(
3669
+ "textarea",
3670
+ {
3671
+ required: field.required,
3672
+ placeholder: field.placeholder,
3673
+ value: additionalData[field.name] || "",
3674
+ onChange: (e) => setAdditionalData((prev) => ({ ...prev, [field.name]: e.target.value })),
3675
+ style: {
3676
+ width: "100%",
3677
+ padding: "0.625rem 0.75rem",
3678
+ borderRadius: "6px",
3679
+ border: "1px solid #d1d5db",
3680
+ fontSize: "1rem",
3681
+ minHeight: "80px",
3682
+ resize: "vertical"
3683
+ }
3684
+ }
3685
+ ) : field.type === "select" && field.options ? /* @__PURE__ */ jsxRuntime.jsxs(
3686
+ "select",
3687
+ {
3688
+ required: field.required,
3689
+ value: additionalData[field.name] || "",
3690
+ onChange: (e) => setAdditionalData((prev) => ({ ...prev, [field.name]: e.target.value })),
3691
+ style: {
3692
+ width: "100%",
3693
+ padding: "0.625rem 0.75rem",
3694
+ borderRadius: "6px",
3695
+ border: "1px solid #d1d5db",
3696
+ fontSize: "1rem",
3697
+ background: "white"
3698
+ },
3699
+ children: [
3700
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Select..." }),
3701
+ field.options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: opt.value, children: opt.label }, opt.value))
3702
+ ]
3703
+ }
3704
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
3705
+ "input",
3706
+ {
3707
+ type: field.type || "text",
3708
+ required: field.required,
3709
+ placeholder: field.placeholder,
3710
+ value: additionalData[field.name] || "",
3711
+ onChange: (e) => setAdditionalData((prev) => ({ ...prev, [field.name]: e.target.value })),
3712
+ style: {
3713
+ width: "100%",
3714
+ padding: "0.625rem 0.75rem",
3715
+ borderRadius: "6px",
3716
+ border: "1px solid #d1d5db",
3717
+ fontSize: "1rem"
3718
+ }
3719
+ }
3720
+ )
3721
+ ] }, field.name))
3722
+ ] }),
3723
+ !isFree && processor === "square" && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: "1rem" }, children: [
3724
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: {
3725
+ display: "block",
3726
+ fontSize: "0.875rem",
3727
+ fontWeight: 500,
3728
+ color: "#374151",
3729
+ marginBottom: "0.375rem"
3730
+ }, children: "Card Details *" }),
3731
+ /* @__PURE__ */ jsxRuntime.jsx(
3732
+ "div",
3733
+ {
3734
+ id: "sq-card-container",
3735
+ ref: cardContainerRef,
3736
+ style: {
3737
+ minHeight: "42px",
3738
+ border: "1px solid #d1d5db",
3739
+ borderRadius: "6px",
3740
+ padding: "0.5rem 0.75rem",
3741
+ background: "#fff"
3742
+ }
3743
+ }
3744
+ ),
3745
+ !cardReady && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.75rem", color: "#9ca3af", marginTop: "0.25rem" }, children: "Loading card form..." })
3746
+ ] }),
3747
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
3748
+ marginTop: "1rem",
3749
+ padding: "0.75rem",
3750
+ background: "#fef2f2",
3751
+ border: "1px solid #fecaca",
3752
+ borderRadius: "6px",
3753
+ color: "#dc2626",
3754
+ fontSize: "0.875rem"
3755
+ }, children: error }),
3756
+ /* @__PURE__ */ jsxRuntime.jsx(
3757
+ "button",
3758
+ {
3759
+ type: "submit",
3760
+ disabled: loading || !isFree && processor === "square" && !cardReady,
3761
+ style: {
3762
+ width: "100%",
3763
+ marginTop: "1.25rem",
3764
+ padding: "0.875rem",
3765
+ fontSize: "1rem",
3766
+ fontWeight: 600,
3767
+ borderRadius: "8px",
3768
+ border: "none",
3769
+ background: loading || !isFree && processor === "square" && !cardReady ? "#93c5fd" : "#2563eb",
3770
+ color: "white",
3771
+ cursor: loading || !isFree && processor === "square" && !cardReady ? "not-allowed" : "pointer"
3772
+ },
3773
+ children: loading ? "Processing..." : isFree ? "Register Free" : `Pay ${formatPrice(total, event.currency)}`
3774
+ }
3775
+ ),
3776
+ !isFree && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: {
3777
+ textAlign: "center",
3778
+ fontSize: "0.75rem",
3779
+ color: "#666",
3780
+ margin: "0.75rem 0 0"
3781
+ }, children: [
3782
+ "\u{1F512} Secure checkout via ",
3783
+ processor === "square" ? "Square" : processor === "stripe" ? "Stripe" : "secure payment"
3784
+ ] }),
3785
+ !isFree && processor && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { fontSize: "0.625rem", color: "#999", margin: "0.25rem 0 0", textAlign: "center" }, children: [
3786
+ "Powered by ",
3787
+ processor === "stripe" ? "Stripe" : "Square"
3788
+ ] })
3789
+ ] })
3790
+ ] }) })
3791
+ ]
3792
+ }
3793
+ )
3794
+ }
3795
+ );
3796
+ }
3797
+ function useEventModal() {
3798
+ const [event, setEvent] = React5.useState(null);
3799
+ const [schedule, setSchedule] = React5.useState(null);
3800
+ const [isOpen, setIsOpen] = React5.useState(false);
3801
+ const openModal = React5.useCallback((newEvent, newSchedule) => {
3802
+ setEvent(newEvent);
3803
+ setSchedule(newSchedule || newEvent.schedules?.[0] || null);
3804
+ setIsOpen(true);
3805
+ }, []);
3806
+ const closeModal = React5.useCallback(() => {
3807
+ setIsOpen(false);
3808
+ setTimeout(() => {
3809
+ setEvent(null);
3810
+ setSchedule(null);
3811
+ }, 200);
3812
+ }, []);
3813
+ return {
3814
+ event,
3815
+ schedule,
3816
+ isOpen,
3817
+ openModal,
3818
+ closeModal
3819
+ };
3820
+ }
3821
+ function EventCalendar({
3822
+ onRegistrationSuccess,
3823
+ onRegistrationError,
3824
+ collectPhone = false,
3825
+ additionalFields = [],
3826
+ modalClassName,
3827
+ modalOverlayClassName,
3828
+ modalContentClassName,
3829
+ ...calendarProps
3830
+ }) {
3831
+ const { event, schedule, isOpen, openModal, closeModal } = useEventModal();
3832
+ const handleEventClick = (clickedEvent, clickedSchedule) => {
3833
+ openModal(clickedEvent, clickedSchedule);
3834
+ };
3835
+ const handleSuccess = (result) => {
3836
+ onRegistrationSuccess?.(result);
3837
+ };
3838
+ const handleError = (error) => {
3839
+ onRegistrationError?.(error);
3840
+ };
3841
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3842
+ /* @__PURE__ */ jsxRuntime.jsx(
3843
+ CalendarView,
3844
+ {
3845
+ ...calendarProps,
3846
+ onEventClick: handleEventClick
3847
+ }
3848
+ ),
3849
+ /* @__PURE__ */ jsxRuntime.jsx(
3850
+ EventModal,
3851
+ {
3852
+ event,
3853
+ schedule,
3854
+ isOpen,
3855
+ onClose: closeModal,
3856
+ onSuccess: handleSuccess,
3857
+ onError: handleError,
3858
+ collectPhone,
3859
+ additionalFields,
3860
+ className: modalClassName,
3861
+ overlayClassName: modalOverlayClassName,
3862
+ contentClassName: modalContentClassName
3863
+ }
3864
+ )
3865
+ ] });
3866
+ }
3867
+ var CalendarIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3868
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2", ry: "2" }),
3869
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "16", y1: "2", x2: "16", y2: "6" }),
3870
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", y1: "2", x2: "8", y2: "6" }),
3871
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "10", x2: "21", y2: "10" })
3872
+ ] });
3873
+ var ListIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3874
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", y1: "6", x2: "21", y2: "6" }),
3875
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", y1: "12", x2: "21", y2: "12" }),
3876
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", y1: "18", x2: "21", y2: "18" }),
3877
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "6", x2: "3.01", y2: "6" }),
3878
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "12", x2: "3.01", y2: "12" }),
3879
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "18", x2: "3.01", y2: "18" })
3880
+ ] });
3881
+ var GridIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3882
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "3", width: "7", height: "7" }),
3883
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "14", y: "3", width: "7", height: "7" }),
3884
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "14", y: "14", width: "7", height: "7" }),
3885
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "14", width: "7", height: "7" })
3886
+ ] });
3887
+ var ClockIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3888
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
3889
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "12 6 12 12 16 14" })
3890
+ ] });
3891
+ var LocationIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3892
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" }),
3893
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "10", r: "3" })
3894
+ ] });
3895
+ var DEFAULT_VIEWS = ["list", "grid", "calendar"];
3896
+ function EventsWidget({
3897
+ events: propEvents,
3898
+ defaultView = "list",
3899
+ availableViews = DEFAULT_VIEWS,
3900
+ showViewToggle = true,
3901
+ title,
3902
+ subtitle,
3903
+ category,
3904
+ limit = 10,
3905
+ showViewAll = false,
3906
+ viewAllUrl = "/events",
3907
+ viewAllText = "View All Events",
3908
+ emptyMessage = "No upcoming events scheduled.",
3909
+ showEmptyIcon = true,
3910
+ collectPhone = false,
3911
+ additionalFields = [],
3912
+ onRegistrationSuccess,
3913
+ onRegistrationError,
3914
+ onEventClick,
3915
+ className = "",
3916
+ headerClassName = "",
3917
+ toggleClassName = "",
3918
+ listClassName = "",
3919
+ calendarClassName = "",
3920
+ eventCardClassName = "",
3921
+ modalClassName = ""
3922
+ }) {
3923
+ const views = availableViews.length > 0 ? availableViews : DEFAULT_VIEWS;
3924
+ const resolvedDefault = views.includes(defaultView) ? defaultView : views[0];
3925
+ const [viewMode, setViewMode] = React5.useState(resolvedDefault);
3926
+ const effectiveView = views.includes(viewMode) ? viewMode : views[0];
3927
+ const [events, setEvents] = React5.useState(propEvents || []);
3928
+ const [loading, setLoading] = React5.useState(!propEvents);
3929
+ const [error, setError] = React5.useState(null);
3930
+ const [retryCount, setRetryCount] = React5.useState(0);
3931
+ const { event, schedule, isOpen, openModal, closeModal } = useEventModal();
3932
+ React5.useEffect(() => {
3933
+ if (propEvents) {
3934
+ setEvents(propEvents);
3935
+ return;
3936
+ }
3937
+ async function loadEvents() {
3938
+ const apiUrl = getApiUrl();
3939
+ const apiKey = getApiKey();
3940
+ if (!apiKey) {
3941
+ if (retryCount < 3) {
3942
+ setTimeout(() => setRetryCount((c) => c + 1), 100);
3943
+ return;
3944
+ }
3945
+ console.warn("[EventsWidget] No API key configured. Make sure SiteKitProvider is wrapping your app.");
3946
+ setError(null);
3947
+ setEvents([]);
3948
+ setLoading(false);
3949
+ return;
3950
+ }
3951
+ setLoading(true);
3952
+ setError(null);
3953
+ try {
3954
+ const response = await fetch(`${apiUrl}/api/public/commerce/events`, {
3955
+ method: "POST",
3956
+ headers: {
3957
+ "Content-Type": "application/json",
3958
+ "x-api-key": apiKey
3959
+ },
3960
+ body: JSON.stringify({
3961
+ type: "event",
3962
+ category,
3963
+ limit: limit * 2
3964
+ // Fetch extra for calendar view
3965
+ })
3966
+ });
3967
+ if (!response.ok) {
3968
+ throw new Error("Failed to fetch events");
3969
+ }
3970
+ const data = await response.json();
3971
+ setEvents(data.events || []);
3972
+ } catch (err) {
3973
+ console.error("Error loading events:", err);
3974
+ setError("Unable to load events. Please try again later.");
3975
+ } finally {
3976
+ setLoading(false);
3977
+ }
3978
+ }
3979
+ loadEvents();
3980
+ }, [propEvents, category, limit, retryCount]);
3981
+ const handleEventClick = React5.useCallback((clickedEvent, clickedSchedule) => {
3982
+ onEventClick?.(clickedEvent, clickedSchedule);
3983
+ openModal(clickedEvent, clickedSchedule);
3984
+ }, [onEventClick, openModal]);
3985
+ const handleSuccess = React5.useCallback((result) => {
3986
+ onRegistrationSuccess?.(result);
3987
+ }, [onRegistrationSuccess]);
3988
+ const handleError = React5.useCallback((err) => {
3989
+ onRegistrationError?.(err);
3990
+ }, [onRegistrationError]);
3991
+ if (loading) {
3992
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-events-widget ${className}`, children: [
3993
+ (title || subtitle) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-events-header ${headerClassName}`, style: { marginBottom: "1.5rem" }, children: [
3994
+ title && /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { margin: 0, fontSize: "1.5rem", fontWeight: 600 }, children: title }),
3995
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: "0.5rem 0 0", color: "#666" }, children: subtitle })
3996
+ ] }),
3997
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", padding: "3rem 1rem", color: "#666" }, children: [
3998
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
3999
+ width: "40px",
4000
+ height: "40px",
4001
+ margin: "0 auto 1rem",
4002
+ border: "3px solid #e5e7eb",
4003
+ borderTopColor: "#3b82f6",
4004
+ borderRadius: "50%",
4005
+ animation: "site-kit-spin 1s linear infinite"
4006
+ } }),
4007
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Loading events..." })
4008
+ ] }),
4009
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
4010
+ @keyframes site-kit-spin {
4011
+ to { transform: rotate(360deg); }
4012
+ }
4013
+ ` })
4014
+ ] });
4015
+ }
4016
+ if (error) {
4017
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-events-widget ${className}`, children: [
4018
+ (title || subtitle) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-events-header ${headerClassName}`, style: { marginBottom: "1.5rem" }, children: [
4019
+ title && /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { margin: 0, fontSize: "1.5rem", fontWeight: 600 }, children: title }),
4020
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: "0.5rem 0 0", color: "#666" }, children: subtitle })
4021
+ ] }),
4022
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", padding: "3rem 1rem", color: "#dc2626" }, children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: error }) })
4023
+ ] });
4024
+ }
4025
+ if (events.length === 0) {
4026
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-events-widget ${className}`, children: [
4027
+ (title || subtitle) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-events-header ${headerClassName}`, style: { marginBottom: "1.5rem" }, children: [
4028
+ title && /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { margin: 0, fontSize: "1.5rem", fontWeight: 600 }, children: title }),
4029
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: "0.5rem 0 0", color: "#666" }, children: subtitle })
4030
+ ] }),
4031
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", padding: "3rem 1rem", color: "#666" }, children: [
4032
+ showEmptyIcon && /* @__PURE__ */ jsxRuntime.jsx(
4033
+ "svg",
4034
+ {
4035
+ style: { width: "64px", height: "64px", margin: "0 auto 1rem", color: "#d1d5db" },
4036
+ fill: "none",
4037
+ stroke: "currentColor",
4038
+ viewBox: "0 0 24 24",
4039
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" })
4040
+ }
4041
+ ),
4042
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "1.125rem", fontWeight: 500, margin: 0 }, children: emptyMessage })
4043
+ ] })
4044
+ ] });
4045
+ }
4046
+ const displayEvents = effectiveView === "list" || effectiveView === "grid" ? events.slice(0, limit) : events;
4047
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-events-widget ${className}`, children: [
4048
+ (title || subtitle || showViewToggle) && /* @__PURE__ */ jsxRuntime.jsxs(
4049
+ "div",
4050
+ {
4051
+ className: `site-kit-events-header ${headerClassName}`,
4052
+ style: {
4053
+ display: "flex",
4054
+ justifyContent: "space-between",
4055
+ alignItems: "flex-start",
4056
+ marginBottom: "1.5rem",
4057
+ flexWrap: "wrap",
4058
+ gap: "1rem"
4059
+ },
4060
+ children: [
4061
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
4062
+ title && /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { margin: 0, fontSize: "1.5rem", fontWeight: 600 }, children: title }),
4063
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: "0.5rem 0 0", color: "#666" }, children: subtitle })
4064
+ ] }),
4065
+ showViewToggle && /* @__PURE__ */ jsxRuntime.jsxs(
4066
+ "div",
4067
+ {
4068
+ className: `site-kit-events-toggle ${toggleClassName}`,
4069
+ style: {
4070
+ display: "flex",
4071
+ gap: "0.25rem",
4072
+ background: "#f3f4f6",
4073
+ padding: "0.25rem",
4074
+ borderRadius: "0.5rem"
4075
+ },
4076
+ children: [
4077
+ views.includes("list") && /* @__PURE__ */ jsxRuntime.jsxs(
4078
+ "button",
4079
+ {
4080
+ onClick: () => setViewMode("list"),
4081
+ style: {
4082
+ display: "flex",
4083
+ alignItems: "center",
4084
+ gap: "0.5rem",
4085
+ padding: "0.5rem 1rem",
4086
+ border: "none",
4087
+ borderRadius: "0.375rem",
4088
+ background: viewMode === "list" ? "#fff" : "transparent",
4089
+ color: viewMode === "list" ? "#1f2937" : "#6b7280",
4090
+ fontWeight: 500,
4091
+ fontSize: "0.875rem",
4092
+ cursor: "pointer",
4093
+ boxShadow: viewMode === "list" ? "0 1px 2px rgba(0,0,0,0.05)" : "none",
4094
+ transition: "all 150ms"
4095
+ },
4096
+ children: [
4097
+ /* @__PURE__ */ jsxRuntime.jsx(ListIcon, {}),
4098
+ "List"
4099
+ ]
4100
+ }
4101
+ ),
4102
+ views.includes("grid") && /* @__PURE__ */ jsxRuntime.jsxs(
4103
+ "button",
4104
+ {
4105
+ onClick: () => setViewMode("grid"),
4106
+ style: {
4107
+ display: "flex",
4108
+ alignItems: "center",
4109
+ gap: "0.5rem",
4110
+ padding: "0.5rem 1rem",
4111
+ border: "none",
4112
+ borderRadius: "0.375rem",
4113
+ background: viewMode === "grid" ? "#fff" : "transparent",
4114
+ color: viewMode === "grid" ? "#1f2937" : "#6b7280",
4115
+ fontWeight: 500,
4116
+ fontSize: "0.875rem",
4117
+ cursor: "pointer",
4118
+ boxShadow: viewMode === "grid" ? "0 1px 2px rgba(0,0,0,0.05)" : "none",
4119
+ transition: "all 150ms"
4120
+ },
4121
+ children: [
4122
+ /* @__PURE__ */ jsxRuntime.jsx(GridIcon, {}),
4123
+ "Grid"
4124
+ ]
4125
+ }
4126
+ ),
4127
+ views.includes("calendar") && /* @__PURE__ */ jsxRuntime.jsxs(
4128
+ "button",
4129
+ {
4130
+ onClick: () => setViewMode("calendar"),
4131
+ style: {
4132
+ display: "flex",
4133
+ alignItems: "center",
4134
+ gap: "0.5rem",
4135
+ padding: "0.5rem 1rem",
4136
+ border: "none",
4137
+ borderRadius: "0.375rem",
4138
+ background: viewMode === "calendar" ? "#fff" : "transparent",
4139
+ color: viewMode === "calendar" ? "#1f2937" : "#6b7280",
4140
+ fontWeight: 500,
4141
+ fontSize: "0.875rem",
4142
+ cursor: "pointer",
4143
+ boxShadow: viewMode === "calendar" ? "0 1px 2px rgba(0,0,0,0.05)" : "none",
4144
+ transition: "all 150ms"
4145
+ },
4146
+ children: [
4147
+ /* @__PURE__ */ jsxRuntime.jsx(CalendarIcon, {}),
4148
+ "Calendar"
4149
+ ]
4150
+ }
4151
+ )
4152
+ ]
4153
+ }
4154
+ )
4155
+ ]
4156
+ }
4157
+ ),
4158
+ effectiveView === "list" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-events-list ${listClassName}`, children: [
4159
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: "1rem" }, children: displayEvents.map((eventItem, index) => {
4160
+ const nextSchedule = eventItem.next_schedule || eventItem.schedules?.[0];
4161
+ const isFree = !eventItem.price || eventItem.price === 0;
4162
+ const imageUrl = eventItem.featured_image_url;
4163
+ const uniqueKey = nextSchedule ? `${eventItem.id}-${nextSchedule.id}` : `${eventItem.id}-${index}`;
4164
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4165
+ "div",
4166
+ {
4167
+ className: `site-kit-event-card ${eventCardClassName}`,
4168
+ onClick: () => nextSchedule && handleEventClick(eventItem, nextSchedule),
4169
+ style: {
4170
+ display: "flex",
4171
+ flexDirection: "row",
4172
+ gap: 0,
4173
+ padding: 0,
4174
+ background: "#fff",
4175
+ border: "1px solid #e5e7eb",
4176
+ borderRadius: "0.75rem",
4177
+ cursor: nextSchedule ? "pointer" : "default",
4178
+ transition: "all 150ms",
4179
+ overflow: "hidden"
4180
+ },
4181
+ onMouseEnter: (e) => {
4182
+ if (nextSchedule) {
4183
+ e.currentTarget.style.borderColor = "#3b82f6";
4184
+ e.currentTarget.style.boxShadow = "0 4px 6px -1px rgba(0, 0, 0, 0.1)";
4185
+ }
4186
+ },
4187
+ onMouseLeave: (e) => {
4188
+ e.currentTarget.style.borderColor = "#e5e7eb";
4189
+ e.currentTarget.style.boxShadow = "none";
4190
+ },
4191
+ children: [
4192
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
4193
+ width: "160px",
4194
+ minWidth: "160px",
4195
+ flexShrink: 0,
4196
+ background: "#f3f4f6"
4197
+ }, children: [
4198
+ imageUrl ? /* @__PURE__ */ jsxRuntime.jsx(
4199
+ "img",
4200
+ {
4201
+ src: imageUrl,
4202
+ alt: eventItem.name,
4203
+ crossOrigin: "anonymous",
4204
+ referrerPolicy: "no-referrer",
4205
+ onError: (e) => {
4206
+ const el = e.currentTarget;
4207
+ el.style.display = "none";
4208
+ const placeholder = el.nextElementSibling;
4209
+ if (placeholder) placeholder.style.display = "flex";
4210
+ },
4211
+ style: {
4212
+ width: "100%",
4213
+ height: "100%",
4214
+ minHeight: "120px",
4215
+ objectFit: "cover",
4216
+ display: "block"
4217
+ }
4218
+ }
4219
+ ) : null,
4220
+ /* @__PURE__ */ jsxRuntime.jsx(
4221
+ "div",
4222
+ {
4223
+ style: {
4224
+ width: "100%",
4225
+ minHeight: "120px",
4226
+ display: imageUrl ? "none" : "flex",
4227
+ alignItems: "center",
4228
+ justifyContent: "center",
4229
+ color: "#9ca3af"
4230
+ },
4231
+ "aria-hidden": true,
4232
+ children: /* @__PURE__ */ jsxRuntime.jsx(CalendarIcon, {})
4233
+ }
4234
+ )
4235
+ ] }),
4236
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: "0.75rem", padding: "1.25rem" }, children: [
4237
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: "1rem" }, children: [
4238
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1 }, children: [
4239
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { style: { margin: 0, fontSize: "1.125rem", fontWeight: 600, color: "#1f2937" }, children: eventItem.name }),
4240
+ eventItem.short_description && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: "0.5rem 0 0", color: "#6b7280", fontSize: "0.875rem", lineHeight: 1.5 }, children: eventItem.short_description })
4241
+ ] }),
4242
+ eventItem.price_is_public && /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
4243
+ padding: "0.375rem 0.75rem",
4244
+ background: isFree ? "#dcfce7" : "#dbeafe",
4245
+ color: isFree ? "#166534" : "#1e40af",
4246
+ borderRadius: "9999px",
4247
+ fontSize: "0.875rem",
4248
+ fontWeight: 600,
4249
+ whiteSpace: "nowrap"
4250
+ }, children: isFree ? "Free" : formatPrice(eventItem.price ?? 0, eventItem.currency) })
4251
+ ] }),
4252
+ nextSchedule && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexWrap: "wrap", gap: "1rem", fontSize: "0.875rem", color: "#6b7280" }, children: [
4253
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: "0.375rem" }, children: [
4254
+ /* @__PURE__ */ jsxRuntime.jsx(CalendarIcon, {}),
4255
+ formatDate(nextSchedule.starts_at)
4256
+ ] }),
4257
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: "0.375rem" }, children: [
4258
+ /* @__PURE__ */ jsxRuntime.jsx(ClockIcon, {}),
4259
+ formatTime(nextSchedule.starts_at)
4260
+ ] }),
4261
+ eventItem.location && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: "0.375rem" }, children: [
4262
+ /* @__PURE__ */ jsxRuntime.jsx(LocationIcon, {}),
4263
+ eventItem.location
4264
+ ] }),
4265
+ nextSchedule.spots_remaining !== null && nextSchedule.spots_remaining !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
4266
+ color: nextSchedule.spots_remaining < 5 ? "#dc2626" : "#6b7280",
4267
+ fontWeight: nextSchedule.spots_remaining < 5 ? 500 : 400
4268
+ }, children: nextSchedule.spots_remaining === 0 ? "Sold Out" : `${nextSchedule.spots_remaining} spots left` })
4269
+ ] })
4270
+ ] })
4271
+ ]
4272
+ },
4273
+ uniqueKey
4274
+ );
4275
+ }) }),
4276
+ showViewAll && events.length > limit && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", marginTop: "1.5rem" }, children: /* @__PURE__ */ jsxRuntime.jsx(
4277
+ "a",
4278
+ {
4279
+ href: viewAllUrl,
4280
+ style: {
4281
+ display: "inline-block",
4282
+ padding: "0.75rem 1.5rem",
4283
+ background: "#f3f4f6",
4284
+ color: "#1f2937",
4285
+ borderRadius: "0.5rem",
4286
+ textDecoration: "none",
4287
+ fontWeight: 500,
4288
+ fontSize: "0.875rem",
4289
+ transition: "all 150ms"
4290
+ },
4291
+ children: viewAllText
4292
+ }
4293
+ ) })
4294
+ ] }) : effectiveView === "grid" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `site-kit-events-grid ${listClassName}`, children: [
4295
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
4296
+ display: "grid",
4297
+ gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))",
4298
+ gap: "1.25rem"
4299
+ }, children: displayEvents.map((eventItem, index) => {
4300
+ const nextSchedule = eventItem.next_schedule || eventItem.schedules?.[0];
4301
+ const isFree = !eventItem.price || eventItem.price === 0;
4302
+ const imageUrl = eventItem.featured_image_url;
4303
+ const uniqueKey = nextSchedule ? `${eventItem.id}-${nextSchedule.id}` : `${eventItem.id}-${index}`;
4304
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4305
+ "div",
4306
+ {
4307
+ className: `site-kit-event-card site-kit-event-card--grid ${eventCardClassName}`,
4308
+ onClick: () => nextSchedule && handleEventClick(eventItem, nextSchedule),
4309
+ style: {
4310
+ position: "relative",
4311
+ minHeight: "220px",
4312
+ borderRadius: "0.75rem",
4313
+ overflow: "hidden",
4314
+ cursor: nextSchedule ? "pointer" : "default",
4315
+ transition: "all 150ms",
4316
+ border: "1px solid #e5e7eb"
4317
+ },
4318
+ onMouseEnter: (e) => {
4319
+ if (nextSchedule) {
4320
+ e.currentTarget.style.boxShadow = "0 10px 25px -5px rgba(0, 0, 0, 0.15)";
4321
+ e.currentTarget.style.transform = "translateY(-2px)";
4322
+ }
4323
+ },
4324
+ onMouseLeave: (e) => {
4325
+ e.currentTarget.style.boxShadow = "none";
4326
+ e.currentTarget.style.transform = "none";
4327
+ },
4328
+ children: [
4329
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
4330
+ position: "absolute",
4331
+ inset: 0,
4332
+ background: imageUrl ? `linear-gradient(to top, rgba(0,0,0,0.75) 0%, rgba(0,0,0,0.35) 45%, rgba(0,0,0,0.15) 70%), url(${imageUrl}) center/cover` : "linear-gradient(135deg, #4b5563 0%, #6b7280 100%)"
4333
+ } }),
4334
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
4335
+ position: "relative",
4336
+ height: "100%",
4337
+ display: "flex",
4338
+ flexDirection: "column",
4339
+ justifyContent: "flex-end",
4340
+ padding: "1.25rem",
4341
+ color: "#fff"
4342
+ }, children: [
4343
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { style: { margin: 0, fontSize: "1.125rem", fontWeight: 600, color: "#fff", textShadow: "0 1px 2px rgba(0,0,0,0.5)" }, children: eventItem.name }),
4344
+ eventItem.short_description && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: "0.25rem 0 0", fontSize: "0.8125rem", opacity: 0.95, lineHeight: 1.4, overflow: "hidden", textOverflow: "ellipsis", maxHeight: "2.8em" }, children: eventItem.short_description }),
4345
+ nextSchedule && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexWrap: "wrap", gap: "0.75rem", marginTop: "0.75rem", fontSize: "0.8125rem", opacity: 0.95 }, children: [
4346
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: "0.25rem" }, children: [
4347
+ /* @__PURE__ */ jsxRuntime.jsx(CalendarIcon, {}),
4348
+ formatDate(nextSchedule.starts_at)
4349
+ ] }),
4350
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: "0.25rem" }, children: [
4351
+ /* @__PURE__ */ jsxRuntime.jsx(ClockIcon, {}),
4352
+ formatTime(nextSchedule.starts_at)
4353
+ ] }),
4354
+ nextSchedule.spots_remaining !== null && nextSchedule.spots_remaining !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { children: nextSchedule.spots_remaining === 0 ? "Sold Out" : `${nextSchedule.spots_remaining} spots left` })
4355
+ ] }),
4356
+ eventItem.price_is_public && /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
4357
+ marginTop: "0.5rem",
4358
+ display: "inline-block",
4359
+ padding: "0.25rem 0.5rem",
4360
+ background: "rgba(255,255,255,0.2)",
4361
+ borderRadius: "9999px",
4362
+ fontSize: "0.875rem",
4363
+ fontWeight: 600
4364
+ }, children: isFree ? "Free" : formatPrice(eventItem.price ?? 0, eventItem.currency) })
4365
+ ] })
4366
+ ]
4367
+ },
4368
+ uniqueKey
4369
+ );
4370
+ }) }),
4371
+ showViewAll && events.length > limit && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", marginTop: "1.5rem" }, children: /* @__PURE__ */ jsxRuntime.jsx(
4372
+ "a",
4373
+ {
4374
+ href: viewAllUrl,
4375
+ style: {
4376
+ display: "inline-block",
4377
+ padding: "0.75rem 1.5rem",
4378
+ background: "#f3f4f6",
4379
+ color: "#1f2937",
4380
+ borderRadius: "0.5rem",
4381
+ textDecoration: "none",
4382
+ fontWeight: 500,
4383
+ fontSize: "0.875rem",
4384
+ transition: "all 150ms"
4385
+ },
4386
+ children: viewAllText
4387
+ }
4388
+ ) })
4389
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: `site-kit-events-calendar ${calendarClassName}`, children: /* @__PURE__ */ jsxRuntime.jsx(
4390
+ CalendarView,
4391
+ {
4392
+ events,
4393
+ onEventClick: handleEventClick,
4394
+ showNavigation: true,
4395
+ showHeader: true
4396
+ }
4397
+ ) }),
4398
+ /* @__PURE__ */ jsxRuntime.jsx(
4399
+ EventModal,
4400
+ {
4401
+ event,
4402
+ schedule,
4403
+ isOpen,
4404
+ onClose: closeModal,
4405
+ onSuccess: handleSuccess,
4406
+ onError: handleError,
4407
+ collectPhone,
4408
+ additionalFields,
4409
+ className: modalClassName
4410
+ }
4411
+ )
4412
+ ] });
4413
+ }
4414
+ function getApiUrl() {
4415
+ if (typeof window !== "undefined") {
4416
+ return window.__SITE_KIT_API_URL__ || "https://api.uptrademedia.com";
4417
+ }
4418
+ return "https://api.uptrademedia.com";
4419
+ }
4420
+ function getApiKey() {
4421
+ if (typeof window !== "undefined") {
4422
+ return window.__SITE_KIT_API_KEY__ || "";
4423
+ }
4424
+ return "";
4425
+ }
4426
+
4427
+ exports.CalendarView = CalendarView;
4428
+ exports.CheckoutForm = CheckoutForm;
4429
+ exports.EventCalendar = EventCalendar;
4430
+ exports.EventEmbed = EventEmbed;
4431
+ exports.EventModal = EventModal;
4432
+ exports.EventTile = EventTile;
4433
+ exports.EventsWidget = EventsWidget;
4434
+ exports.OfferingCard = OfferingCard;
4435
+ exports.OfferingList = OfferingList;
4436
+ exports.ProductDetail = ProductDetail;
4437
+ exports.ProductEmbed = ProductEmbed;
4438
+ exports.ProductGrid = ProductGrid;
4439
+ exports.ProductPage = ProductPage;
4440
+ exports.RegistrationForm = RegistrationForm;
4441
+ exports.UpcomingEvents = UpcomingEvents;
4442
+ exports.createCheckoutSession = createCheckoutSession;
4443
+ exports.fetchActiveProcessor = fetchActiveProcessor;
4444
+ exports.fetchCategories = fetchCategories;
4445
+ exports.fetchLatestOffering = fetchLatestOffering;
4446
+ exports.fetchNextEvent = fetchNextEvent;
4447
+ exports.fetchOffering = fetchOffering;
4448
+ exports.fetchOfferings = fetchOfferings;
4449
+ exports.fetchProcessorConfig = fetchProcessorConfig;
4450
+ exports.fetchProductBySlug = fetchProductBySlug;
4451
+ exports.fetchProducts = fetchProducts;
4452
+ exports.fetchProductsPublic = fetchProductsPublic;
4453
+ exports.fetchServices = fetchServices;
4454
+ exports.fetchShippingRates = fetchShippingRates;
4455
+ exports.fetchUpcomingEvents = fetchUpcomingEvents;
4456
+ exports.formatDate = formatDate;
4457
+ exports.formatDateRange = formatDateRange;
4458
+ exports.formatDateTime = formatDateTime;
4459
+ exports.formatPrice = formatPrice;
4460
+ exports.formatTime = formatTime;
4461
+ exports.getOfferingUrl = getOfferingUrl;
4462
+ exports.getRelativeTimeUntil = getRelativeTimeUntil;
4463
+ exports.getSpotsRemaining = getSpotsRemaining;
4464
+ exports.isEventSoldOut = isEventSoldOut;
4465
+ exports.registerForEvent = registerForEvent;
4466
+ exports.useEventModal = useEventModal;
4467
+ exports.validateAddress = validateAddress;
4468
+ //# sourceMappingURL=chunk-UYFDNX2F.js.map
4469
+ //# sourceMappingURL=chunk-UYFDNX2F.js.map