@sonordev/site-kit 1.3.5 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -92,6 +92,12 @@ function getApiConfig() {
92
92
  const apiKey = typeof window !== "undefined" ? window.__SITE_KIT_API_KEY__ || "" : "";
93
93
  return { apiUrl, apiKey };
94
94
  }
95
+ function getApiUrl() {
96
+ return getApiConfig().apiUrl;
97
+ }
98
+ function getApiKey() {
99
+ return getApiConfig().apiKey;
100
+ }
95
101
  async function apiPost(endpoint, body = {}) {
96
102
  const { apiUrl, apiKey } = getApiConfig();
97
103
  if (!apiKey) {
@@ -325,6 +331,29 @@ async function fetchProcessorConfig() {
325
331
  return null;
326
332
  }
327
333
  }
334
+ async function createPaymentIntent(options) {
335
+ const apiUrl = getApiUrl();
336
+ const apiKey = getApiKey();
337
+ const sessionId = typeof sessionStorage !== "undefined" ? sessionStorage.getItem("_uptrade_sid") : null;
338
+ try {
339
+ const response = await fetch(`${apiUrl}/api/public/commerce/create-payment-intent`, {
340
+ method: "POST",
341
+ headers: {
342
+ "Content-Type": "application/json",
343
+ "x-api-key": apiKey
344
+ },
345
+ body: JSON.stringify({
346
+ ...options,
347
+ analyticsSessionId: sessionId
348
+ })
349
+ });
350
+ const data = await response.json();
351
+ if (!response.ok) throw new Error(data.message || "Failed to create payment intent");
352
+ return data;
353
+ } catch (error) {
354
+ return { success: false, error: error?.message || "Network error. Please try again." };
355
+ }
356
+ }
328
357
  async function createCheckoutSession(optionsOrOfferingId, legacyOptions) {
329
358
  const { apiUrl, apiKey } = getApiConfig();
330
359
  const options = typeof optionsOrOfferingId === "string" ? { offeringId: optionsOrOfferingId, ...legacyOptions } : optionsOrOfferingId;
@@ -1295,485 +1324,2413 @@ var tdStyle = {
1295
1324
  borderBottom: "1px solid rgba(128, 128, 128, 0.1)",
1296
1325
  whiteSpace: "nowrap"
1297
1326
  };
1298
- function ProductDetail({
1299
- product: propProduct,
1300
- slug,
1301
- showAddToCart = true,
1302
- showBuyNow = true,
1303
- showQuantity = true,
1304
- showVariants = true,
1305
- showGallery = true,
1306
- showFeatures = true,
1307
- showSpecifications = true,
1308
- successUrl,
1309
- cancelUrl,
1310
- onAddToCart,
1311
- onBuyNow,
1312
- onCheckoutSuccess,
1313
- onCheckoutError,
1314
- className = "",
1315
- style
1316
- }) {
1317
- const [product, setProduct] = useState(propProduct || null);
1318
- const [loading, setLoading] = useState(!propProduct && !!slug);
1319
- const [selectedVariant, setSelectedVariant] = useState();
1320
- const [quantity, setQuantity] = useState(1);
1321
- const [selectedImage, setSelectedImage] = useState(0);
1322
- const [checkingOut, setCheckingOut] = useState(false);
1323
- const analytics = useAnalyticsOptional();
1324
- useEffect(() => {
1325
- if (!product || !analytics) return;
1326
- analytics.trackEvent({
1327
- name: "product_view",
1328
- properties: {
1329
- offering_id: product.id,
1330
- name: product.name,
1331
- price: product.price,
1332
- type: product.type,
1333
- category: product.category?.name
1334
- }
1335
- });
1336
- }, [product?.id, analytics]);
1337
- useEffect(() => {
1338
- if (propProduct) {
1339
- setProduct(propProduct);
1340
- const defaultVariant = propProduct.variants?.find((v) => v.is_default) || propProduct.variants?.[0];
1341
- setSelectedVariant(defaultVariant);
1342
- return;
1343
- }
1344
- if (!slug) return;
1345
- async function load() {
1346
- setLoading(true);
1347
- try {
1348
- const data = await fetchProductBySlug(slug);
1349
- setProduct(data);
1350
- if (data?.variants?.length) {
1351
- const defaultVariant = data.variants.find((v) => v.is_default) || data.variants[0];
1352
- setSelectedVariant(defaultVariant);
1353
- }
1354
- } catch (e) {
1355
- console.error("Failed to load product:", e);
1356
- } finally {
1357
- setLoading(false);
1358
- }
1359
- }
1360
- load();
1361
- }, [propProduct, slug]);
1362
- if (loading) {
1363
- return /* @__PURE__ */ jsxs("div", { className: `site-kit-product-detail site-kit-product-detail--loading ${className}`, style, children: [
1364
- /* @__PURE__ */ jsx("div", { className: "site-kit-product-detail__loader", style: {
1365
- display: "flex",
1366
- justifyContent: "center",
1367
- alignItems: "center",
1368
- minHeight: "400px"
1369
- }, children: /* @__PURE__ */ jsx("div", { style: {
1370
- width: "48px",
1371
- height: "48px",
1372
- border: "3px solid #e5e7eb",
1373
- borderTopColor: "#2563eb",
1374
- borderRadius: "50%",
1375
- animation: "spin 1s linear infinite"
1376
- } }) }),
1377
- /* @__PURE__ */ jsx("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
1378
- ] });
1327
+ var STYLE_BLOCK = `
1328
+ @keyframes skc-spin {
1329
+ to { transform: rotate(360deg); }
1330
+ }
1331
+ @keyframes skc-pulse {
1332
+ 0%, 100% { opacity: 1; }
1333
+ 50% { opacity: 0.6; }
1334
+ }
1335
+ @keyframes skc-fadeIn {
1336
+ from { opacity: 0; transform: translateY(8px); }
1337
+ to { opacity: 1; transform: translateY(0); }
1338
+ }
1339
+ @keyframes skc-slideUp {
1340
+ from { opacity: 0; transform: translateY(100%); }
1341
+ to { opacity: 1; transform: translateY(0); }
1342
+ }
1343
+ @keyframes skc-scaleIn {
1344
+ from { opacity: 0; transform: scale(0.95); }
1345
+ to { opacity: 1; transform: scale(1); }
1346
+ }
1347
+ @keyframes skc-checkmark {
1348
+ 0% { stroke-dashoffset: 24; }
1349
+ 100% { stroke-dashoffset: 0; }
1350
+ }
1351
+
1352
+ .skc-detail {
1353
+ --commerce-bg: transparent;
1354
+ --commerce-surface: #f9fafb;
1355
+ --commerce-surface-hover: #f3f4f6;
1356
+ --commerce-border: #e5e7eb;
1357
+ --commerce-text: #111827;
1358
+ --commerce-text-secondary: #6b7280;
1359
+ --commerce-text-muted: #9ca3af;
1360
+ --commerce-accent: #2563eb;
1361
+ --commerce-accent-hover: #1d4ed8;
1362
+ --commerce-accent-text: #ffffff;
1363
+ --commerce-success: #059669;
1364
+ --commerce-warning: #d97706;
1365
+ --commerce-danger: #dc2626;
1366
+ --commerce-radius: 12px;
1367
+ --commerce-radius-sm: 8px;
1368
+
1369
+ animation: skc-fadeIn 0.3s ease-out;
1370
+ }
1371
+
1372
+ .skc-detail *, .skc-detail *::before, .skc-detail *::after {
1373
+ box-sizing: border-box;
1374
+ }
1375
+
1376
+ .skc-detail-layout {
1377
+ display: grid;
1378
+ grid-template-columns: 1fr 1fr;
1379
+ gap: 2.5rem;
1380
+ align-items: start;
1381
+ }
1382
+
1383
+ @media (max-width: 768px) {
1384
+ .skc-detail-layout {
1385
+ grid-template-columns: 1fr;
1386
+ gap: 1.5rem;
1379
1387
  }
1380
- if (!product) {
1381
- return /* @__PURE__ */ jsx("div", { className: `site-kit-product-detail site-kit-product-detail--not-found ${className}`, style, children: /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: "4rem 2rem", color: "#666" }, children: [
1382
- /* @__PURE__ */ jsx("h2", { style: { margin: 0, fontSize: "1.5rem", color: "#333" }, children: "Product Not Found" }),
1383
- /* @__PURE__ */ jsx("p", { style: { marginTop: "0.5rem" }, children: "The product you're looking for doesn't exist or has been removed." })
1384
- ] }) });
1388
+ .skc-detail-layout.skc-stacked {
1389
+ grid-template-columns: 1fr;
1385
1390
  }
1386
- const currentPrice = selectedVariant?.price ?? product.price ?? 0;
1387
- const compareAtPrice = product.compare_at_price;
1388
- const hasDiscount = compareAtPrice && compareAtPrice > currentPrice;
1389
- const allImages = [
1390
- product.featured_image_url,
1391
- ...product.gallery_images || [],
1392
- ...product.variants?.map((v) => v.image_url).filter(Boolean) || []
1393
- ].filter(Boolean);
1394
- const inventoryCount = selectedVariant?.inventory_count ?? product.inventory_count;
1395
- const isOutOfStock = product.track_inventory && inventoryCount !== void 0 && inventoryCount <= 0;
1396
- const isLowStock = product.track_inventory && inventoryCount !== void 0 && inventoryCount > 0 && inventoryCount <= 5;
1397
- const needsVariantSelection = (product.is_clothing || (product.variants?.length ?? 0) > 0) && !selectedVariant;
1398
- const handleAddToCart = () => {
1399
- analytics?.trackEvent({
1400
- name: "add_to_cart",
1401
- properties: {
1402
- offering_id: product.id,
1403
- variant_id: selectedVariant?.id,
1404
- quantity,
1405
- price: selectedVariant?.price ?? product.price,
1406
- name: product.name
1407
- }
1408
- });
1409
- if (onAddToCart) {
1410
- onAddToCart(product, selectedVariant, quantity);
1411
- }
1391
+ }
1392
+
1393
+ .skc-detail-layout.skc-stacked {
1394
+ grid-template-columns: 1fr;
1395
+ max-width: 640px;
1396
+ }
1397
+
1398
+ /* Gallery */
1399
+ .skc-gallery-main {
1400
+ position: relative;
1401
+ overflow: hidden;
1402
+ border-radius: var(--commerce-radius);
1403
+ background: var(--commerce-surface);
1404
+ cursor: crosshair;
1405
+ aspect-ratio: 1;
1406
+ }
1407
+ .skc-gallery-main img {
1408
+ width: 100%;
1409
+ height: 100%;
1410
+ object-fit: cover;
1411
+ transition: transform 0.15s ease-out;
1412
+ will-change: transform;
1413
+ }
1414
+ .skc-gallery-thumbs {
1415
+ display: flex;
1416
+ gap: 0.5rem;
1417
+ margin-top: 0.75rem;
1418
+ overflow-x: auto;
1419
+ scrollbar-width: thin;
1420
+ -webkit-overflow-scrolling: touch;
1421
+ padding-bottom: 4px;
1422
+ }
1423
+ .skc-gallery-thumb {
1424
+ flex: 0 0 auto;
1425
+ width: 64px;
1426
+ height: 64px;
1427
+ border-radius: var(--commerce-radius-sm);
1428
+ overflow: hidden;
1429
+ border: 2px solid transparent;
1430
+ padding: 0;
1431
+ cursor: pointer;
1432
+ background: var(--commerce-surface);
1433
+ transition: border-color 0.15s ease;
1434
+ }
1435
+ .skc-gallery-thumb:hover {
1436
+ border-color: var(--commerce-text-muted);
1437
+ }
1438
+ .skc-gallery-thumb.skc-active {
1439
+ border-color: var(--commerce-accent);
1440
+ }
1441
+ .skc-gallery-thumb img {
1442
+ width: 100%;
1443
+ height: 100%;
1444
+ object-fit: cover;
1445
+ }
1446
+
1447
+ /* Sticky buy bar */
1448
+ .skc-sticky-bar {
1449
+ position: fixed;
1450
+ bottom: 0;
1451
+ left: 0;
1452
+ right: 0;
1453
+ z-index: 999;
1454
+ background: white;
1455
+ border-top: 1px solid var(--commerce-border);
1456
+ padding: 0.75rem 1rem;
1457
+ display: flex;
1458
+ align-items: center;
1459
+ justify-content: space-between;
1460
+ gap: 1rem;
1461
+ animation: skc-slideUp 0.25s ease-out;
1462
+ box-shadow: 0 -4px 20px rgba(0,0,0,0.08);
1463
+ }
1464
+ @media (min-width: 769px) {
1465
+ .skc-sticky-bar { display: none; }
1466
+ }
1467
+
1468
+ /* Tabs */
1469
+ .skc-tabs-list {
1470
+ display: flex;
1471
+ border-bottom: 1px solid var(--commerce-border);
1472
+ gap: 0;
1473
+ overflow-x: auto;
1474
+ scrollbar-width: none;
1475
+ }
1476
+ .skc-tabs-list::-webkit-scrollbar { display: none; }
1477
+ .skc-tab-btn {
1478
+ padding: 0.75rem 1.25rem;
1479
+ border: none;
1480
+ background: none;
1481
+ font-size: 0.875rem;
1482
+ font-weight: 500;
1483
+ color: var(--commerce-text-secondary);
1484
+ cursor: pointer;
1485
+ border-bottom: 2px solid transparent;
1486
+ white-space: nowrap;
1487
+ transition: color 0.15s ease, border-color 0.15s ease;
1488
+ }
1489
+ .skc-tab-btn:hover {
1490
+ color: var(--commerce-text);
1491
+ }
1492
+ .skc-tab-btn.skc-active {
1493
+ color: var(--commerce-accent);
1494
+ border-bottom-color: var(--commerce-accent);
1495
+ }
1496
+
1497
+ /* Checkout overlay */
1498
+ .skc-checkout-overlay {
1499
+ position: fixed;
1500
+ inset: 0;
1501
+ z-index: 10000;
1502
+ background: rgba(0,0,0,0.5);
1503
+ backdrop-filter: blur(4px);
1504
+ display: flex;
1505
+ align-items: center;
1506
+ justify-content: center;
1507
+ padding: 1rem;
1508
+ animation: skc-fadeIn 0.2s ease-out;
1509
+ }
1510
+ .skc-checkout-panel {
1511
+ position: relative;
1512
+ width: 100%;
1513
+ max-width: 480px;
1514
+ max-height: 90vh;
1515
+ overflow-y: auto;
1516
+ background: white;
1517
+ border-radius: calc(var(--commerce-radius) + 4px);
1518
+ box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25);
1519
+ animation: skc-scaleIn 0.25s ease-out;
1520
+ }
1521
+
1522
+ /* Form inputs */
1523
+ .skc-input {
1524
+ width: 100%;
1525
+ padding: 0.625rem 0.75rem;
1526
+ border-radius: var(--commerce-radius-sm);
1527
+ border: 1px solid var(--commerce-border);
1528
+ font-size: 0.9375rem;
1529
+ color: var(--commerce-text);
1530
+ background: white;
1531
+ transition: border-color 0.15s ease, box-shadow 0.15s ease;
1532
+ outline: none;
1533
+ }
1534
+ .skc-input:focus {
1535
+ border-color: var(--commerce-accent);
1536
+ box-shadow: 0 0 0 3px rgba(37,99,235,0.1);
1537
+ }
1538
+ .skc-input::placeholder {
1539
+ color: var(--commerce-text-muted);
1540
+ }
1541
+
1542
+ /* Primary button */
1543
+ .skc-btn-primary {
1544
+ display: inline-flex;
1545
+ align-items: center;
1546
+ justify-content: center;
1547
+ gap: 0.5rem;
1548
+ width: 100%;
1549
+ padding: 0.875rem 1.5rem;
1550
+ border-radius: var(--commerce-radius-sm);
1551
+ border: none;
1552
+ background: var(--commerce-accent);
1553
+ color: var(--commerce-accent-text);
1554
+ font-size: 1rem;
1555
+ font-weight: 600;
1556
+ cursor: pointer;
1557
+ transition: background-color 0.15s ease, transform 0.1s ease;
1558
+ }
1559
+ .skc-btn-primary:hover:not(:disabled) {
1560
+ background: var(--commerce-accent-hover);
1561
+ }
1562
+ .skc-btn-primary:active:not(:disabled) {
1563
+ transform: scale(0.98);
1564
+ }
1565
+ .skc-btn-primary:disabled {
1566
+ opacity: 0.55;
1567
+ cursor: not-allowed;
1568
+ }
1569
+
1570
+ /* Secondary button */
1571
+ .skc-btn-secondary {
1572
+ display: inline-flex;
1573
+ align-items: center;
1574
+ justify-content: center;
1575
+ gap: 0.5rem;
1576
+ width: 100%;
1577
+ padding: 0.875rem 1.5rem;
1578
+ border-radius: var(--commerce-radius-sm);
1579
+ border: 2px solid var(--commerce-accent);
1580
+ background: transparent;
1581
+ color: var(--commerce-accent);
1582
+ font-size: 1rem;
1583
+ font-weight: 600;
1584
+ cursor: pointer;
1585
+ transition: background-color 0.15s ease;
1586
+ }
1587
+ .skc-btn-secondary:hover:not(:disabled) {
1588
+ background: rgba(37,99,235,0.05);
1589
+ }
1590
+ .skc-btn-secondary:disabled {
1591
+ opacity: 0.55;
1592
+ cursor: not-allowed;
1593
+ }
1594
+
1595
+ /* Low-stock pulse */
1596
+ .skc-pulse {
1597
+ animation: skc-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
1598
+ }
1599
+
1600
+ /* Step indicator */
1601
+ .skc-step-dots {
1602
+ display: flex;
1603
+ align-items: center;
1604
+ justify-content: center;
1605
+ gap: 0.5rem;
1606
+ padding: 1rem 0 0.5rem;
1607
+ }
1608
+ .skc-step-dot {
1609
+ width: 8px;
1610
+ height: 8px;
1611
+ border-radius: 50%;
1612
+ background: var(--commerce-border);
1613
+ transition: background 0.2s ease, transform 0.2s ease;
1614
+ }
1615
+ .skc-step-dot.skc-active {
1616
+ background: var(--commerce-accent);
1617
+ transform: scale(1.3);
1618
+ }
1619
+ .skc-step-dot.skc-done {
1620
+ background: var(--commerce-success);
1621
+ }
1622
+ .skc-step-connector {
1623
+ width: 24px;
1624
+ height: 2px;
1625
+ background: var(--commerce-border);
1626
+ transition: background 0.2s ease;
1627
+ }
1628
+ .skc-step-connector.skc-done {
1629
+ background: var(--commerce-success);
1630
+ }
1631
+ `;
1632
+ function loadSquareSDK(env) {
1633
+ return new Promise((resolve, reject) => {
1634
+ if (typeof window === "undefined") return reject(new Error("No window"));
1635
+ if (window.Square) return resolve();
1636
+ const script = document.createElement("script");
1637
+ script.src = env === "sandbox" ? "https://sandbox.web.squarecdn.com/v1/square.js" : "https://web.squarecdn.com/v1/square.js";
1638
+ script.onload = () => resolve();
1639
+ script.onerror = () => reject(new Error("Failed to load Square SDK"));
1640
+ document.head.appendChild(script);
1641
+ });
1642
+ }
1643
+ function loadStripeSDK() {
1644
+ return new Promise((resolve, reject) => {
1645
+ if (typeof window === "undefined") return reject(new Error("No window"));
1646
+ if (window.Stripe) return resolve();
1647
+ const script = document.createElement("script");
1648
+ script.src = "https://js.stripe.com/v3/";
1649
+ script.onload = () => resolve();
1650
+ script.onerror = () => reject(new Error("Failed to load Stripe"));
1651
+ document.head.appendChild(script);
1652
+ });
1653
+ }
1654
+ var IconLock = () => /* @__PURE__ */ jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1655
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2", ry: "2" }),
1656
+ /* @__PURE__ */ jsx("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })
1657
+ ] });
1658
+ var IconTruck = () => /* @__PURE__ */ jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1659
+ /* @__PURE__ */ jsx("rect", { x: "1", y: "3", width: "15", height: "13" }),
1660
+ /* @__PURE__ */ jsx("polygon", { points: "16 8 20 8 23 11 23 16 16 16 16 8" }),
1661
+ /* @__PURE__ */ jsx("circle", { cx: "5.5", cy: "18.5", r: "2.5" }),
1662
+ /* @__PURE__ */ jsx("circle", { cx: "18.5", cy: "18.5", r: "2.5" })
1663
+ ] });
1664
+ var IconReturn = () => /* @__PURE__ */ jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1665
+ /* @__PURE__ */ jsx("polyline", { points: "1 4 1 10 7 10" }),
1666
+ /* @__PURE__ */ jsx("path", { d: "M3.51 15a9 9 0 1 0 2.13-9.36L1 10" })
1667
+ ] });
1668
+ var IconShield = () => /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }) });
1669
+ var IconChevronLeft = () => /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("polyline", { points: "15 18 9 12 15 6" }) });
1670
+ var IconChevronRight = () => /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("polyline", { points: "9 18 15 12 9 6" }) });
1671
+ var IconCheck = () => /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" }) });
1672
+ var IconAlert = () => /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1673
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
1674
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
1675
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
1676
+ ] });
1677
+ var IconCalendar = () => /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1678
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2", ry: "2" }),
1679
+ /* @__PURE__ */ jsx("line", { x1: "16", y1: "2", x2: "16", y2: "6" }),
1680
+ /* @__PURE__ */ jsx("line", { x1: "8", y1: "2", x2: "8", y2: "6" }),
1681
+ /* @__PURE__ */ jsx("line", { x1: "3", y1: "10", x2: "21", y2: "10" })
1682
+ ] });
1683
+ var IconMapPin = () => /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1684
+ /* @__PURE__ */ jsx("path", { d: "M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" }),
1685
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "10", r: "3" })
1686
+ ] });
1687
+ var IconUsers = () => /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1688
+ /* @__PURE__ */ jsx("path", { d: "M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" }),
1689
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "7", r: "4" }),
1690
+ /* @__PURE__ */ jsx("path", { d: "M23 21v-2a4 4 0 0 0-3-3.87" }),
1691
+ /* @__PURE__ */ jsx("path", { d: "M16 3.13a4 4 0 0 1 0 7.75" })
1692
+ ] });
1693
+ var IconExternalLink = () => /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1694
+ /* @__PURE__ */ jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }),
1695
+ /* @__PURE__ */ jsx("polyline", { points: "15 3 21 3 21 9" }),
1696
+ /* @__PURE__ */ jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })
1697
+ ] });
1698
+ var IconX = () => /* @__PURE__ */ jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1699
+ /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1700
+ /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1701
+ ] });
1702
+ var ICON_MAP = {
1703
+ lock: IconLock,
1704
+ truck: IconTruck,
1705
+ return: IconReturn,
1706
+ shield: IconShield
1707
+ };
1708
+ function ProductGallery({ images, productName, selectedIndex, onSelect }) {
1709
+ const [zoomStyle, setZoomStyle] = useState(null);
1710
+ const [isHovering, setIsHovering] = useState(false);
1711
+ const handleMouseMove = (e) => {
1712
+ const rect = e.currentTarget.getBoundingClientRect();
1713
+ const x = (e.clientX - rect.left) / rect.width * 100;
1714
+ const y = (e.clientY - rect.top) / rect.height * 100;
1715
+ setZoomStyle({ transformOrigin: `${x}% ${y}%`, transform: "scale(2)" });
1412
1716
  };
1413
- const handleBuyNow = async () => {
1414
- analytics?.trackEvent({
1415
- name: "add_to_cart",
1416
- properties: {
1417
- offering_id: product.id,
1418
- variant_id: selectedVariant?.id,
1419
- quantity,
1420
- price: selectedVariant?.price ?? product.price,
1421
- name: product.name
1422
- }
1423
- });
1424
- if (onBuyNow) {
1425
- onBuyNow(product, selectedVariant, quantity);
1426
- return;
1427
- }
1428
- setCheckingOut(true);
1429
- try {
1430
- const result = await createCheckoutSession({
1431
- offeringId: product.id,
1432
- variantId: selectedVariant?.id,
1433
- quantity,
1434
- successUrl: successUrl || `${window.location.origin}/checkout/success`,
1435
- cancelUrl: cancelUrl || window.location.href
1436
- });
1437
- if (result.success && result.checkout_url) {
1438
- onCheckoutSuccess?.(result);
1439
- window.location.href = result.checkout_url;
1440
- } else {
1441
- throw new Error(result.error || "Failed to create checkout");
1442
- }
1443
- } catch (error) {
1444
- console.error("Checkout error:", error);
1445
- onCheckoutError?.(error.message || "Checkout failed");
1446
- } finally {
1447
- setCheckingOut(false);
1448
- }
1717
+ const handlePrev = (e) => {
1718
+ e.stopPropagation();
1719
+ onSelect(selectedIndex === 0 ? images.length - 1 : selectedIndex - 1);
1449
1720
  };
1450
- const handleVariantChange = (variant) => {
1451
- setSelectedVariant(variant);
1452
- if (variant.image_url) {
1453
- const imageIndex = allImages.indexOf(variant.image_url);
1454
- if (imageIndex >= 0) setSelectedImage(imageIndex);
1455
- }
1721
+ const handleNext = (e) => {
1722
+ e.stopPropagation();
1723
+ onSelect(selectedIndex === images.length - 1 ? 0 : selectedIndex + 1);
1456
1724
  };
1457
- return /* @__PURE__ */ jsxs("div", { className: `site-kit-product-detail ${className}`, style: {
1458
- display: "grid",
1459
- gridTemplateColumns: "repeat(auto-fit, minmax(320px, 1fr))",
1460
- gap: "2rem",
1461
- ...style
1462
- }, children: [
1463
- showGallery && allImages.length > 0 && /* @__PURE__ */ jsxs("div", { className: "site-kit-product-detail__gallery", children: [
1464
- /* @__PURE__ */ jsx("div", { className: "site-kit-product-detail__main-image", style: {
1465
- aspectRatio: "1",
1466
- borderRadius: "12px",
1467
- overflow: "hidden",
1468
- backgroundColor: "#f9fafb"
1469
- }, children: /* @__PURE__ */ jsx(
1470
- "img",
1471
- {
1472
- src: allImages[selectedImage],
1473
- alt: product.name,
1474
- style: {
1475
- width: "100%",
1476
- height: "100%",
1477
- objectFit: "cover"
1725
+ if (!images.length) return null;
1726
+ return /* @__PURE__ */ jsxs("div", { children: [
1727
+ /* @__PURE__ */ jsxs(
1728
+ "div",
1729
+ {
1730
+ className: "skc-gallery-main",
1731
+ onMouseMove: handleMouseMove,
1732
+ onMouseEnter: () => setIsHovering(true),
1733
+ onMouseLeave: () => {
1734
+ setIsHovering(false);
1735
+ setZoomStyle(null);
1736
+ },
1737
+ role: "img",
1738
+ "aria-label": `${productName} image ${selectedIndex + 1} of ${images.length}`,
1739
+ children: [
1740
+ /* @__PURE__ */ jsx(
1741
+ "img",
1742
+ {
1743
+ src: images[selectedIndex],
1744
+ alt: `${productName} - Image ${selectedIndex + 1}`,
1745
+ style: isHovering && zoomStyle ? zoomStyle : void 0,
1746
+ draggable: false
1747
+ }
1748
+ ),
1749
+ images.length > 1 && /* @__PURE__ */ jsxs(Fragment, { children: [
1750
+ /* @__PURE__ */ jsx(
1751
+ "button",
1752
+ {
1753
+ onClick: handlePrev,
1754
+ "aria-label": "Previous image",
1755
+ style: {
1756
+ position: "absolute",
1757
+ left: 8,
1758
+ top: "50%",
1759
+ transform: "translateY(-50%)",
1760
+ width: 36,
1761
+ height: 36,
1762
+ borderRadius: "50%",
1763
+ border: "none",
1764
+ background: "rgba(255,255,255,0.9)",
1765
+ cursor: "pointer",
1766
+ display: "flex",
1767
+ alignItems: "center",
1768
+ justifyContent: "center",
1769
+ opacity: isHovering ? 1 : 0,
1770
+ transition: "opacity 0.2s ease",
1771
+ boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
1772
+ },
1773
+ children: /* @__PURE__ */ jsx(IconChevronLeft, {})
1774
+ }
1775
+ ),
1776
+ /* @__PURE__ */ jsx(
1777
+ "button",
1778
+ {
1779
+ onClick: handleNext,
1780
+ "aria-label": "Next image",
1781
+ style: {
1782
+ position: "absolute",
1783
+ right: 8,
1784
+ top: "50%",
1785
+ transform: "translateY(-50%)",
1786
+ width: 36,
1787
+ height: 36,
1788
+ borderRadius: "50%",
1789
+ border: "none",
1790
+ background: "rgba(255,255,255,0.9)",
1791
+ cursor: "pointer",
1792
+ display: "flex",
1793
+ alignItems: "center",
1794
+ justifyContent: "center",
1795
+ opacity: isHovering ? 1 : 0,
1796
+ transition: "opacity 0.2s ease",
1797
+ boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
1798
+ },
1799
+ children: /* @__PURE__ */ jsx(IconChevronRight, {})
1800
+ }
1801
+ )
1802
+ ] }),
1803
+ images.length > 1 && /* @__PURE__ */ jsxs(
1804
+ "div",
1805
+ {
1806
+ style: {
1807
+ position: "absolute",
1808
+ bottom: 8,
1809
+ right: 8,
1810
+ background: "rgba(0,0,0,0.6)",
1811
+ color: "white",
1812
+ fontSize: "0.75rem",
1813
+ padding: "2px 8px",
1814
+ borderRadius: 12
1815
+ },
1816
+ children: [
1817
+ selectedIndex + 1,
1818
+ " / ",
1819
+ images.length
1820
+ ]
1821
+ }
1822
+ )
1823
+ ]
1824
+ }
1825
+ ),
1826
+ images.length > 1 && /* @__PURE__ */ jsx("div", { className: "skc-gallery-thumbs", role: "listbox", "aria-label": "Image thumbnails", children: images.map((img, idx) => /* @__PURE__ */ jsx(
1827
+ "button",
1828
+ {
1829
+ className: `skc-gallery-thumb${idx === selectedIndex ? " skc-active" : ""}`,
1830
+ onClick: () => onSelect(idx),
1831
+ role: "option",
1832
+ "aria-selected": idx === selectedIndex,
1833
+ "aria-label": `View image ${idx + 1}`,
1834
+ children: /* @__PURE__ */ jsx("img", { src: img, alt: `${productName} thumbnail ${idx + 1}`, draggable: false })
1835
+ },
1836
+ idx
1837
+ )) })
1838
+ ] });
1839
+ }
1840
+ function VariantSelector({ variants, selected, isClothing, showInventory, onSelect }) {
1841
+ if (!variants.length) return null;
1842
+ const label = isClothing ? "Size" : "Options";
1843
+ return /* @__PURE__ */ jsxs("div", { style: { marginTop: "1.25rem" }, children: [
1844
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: "0.5rem" }, children: /* @__PURE__ */ jsxs(
1845
+ "label",
1846
+ {
1847
+ style: {
1848
+ fontSize: "0.875rem",
1849
+ fontWeight: 600,
1850
+ color: "var(--commerce-text)"
1851
+ },
1852
+ children: [
1853
+ label,
1854
+ selected && /* @__PURE__ */ jsxs("span", { style: { fontWeight: 400, color: "var(--commerce-text-secondary)", marginLeft: 6 }, children: [
1855
+ "\u2014 ",
1856
+ selected.options?.Size || selected.name
1857
+ ] })
1858
+ ]
1859
+ }
1860
+ ) }),
1861
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: "0.5rem" }, role: "radiogroup", "aria-label": label, children: variants.map((variant) => {
1862
+ const isSelected = selected?.id === variant.id;
1863
+ const variantOutOfStock = variant.track_inventory !== false && (variant.inventory_count ?? 0) <= 0;
1864
+ const isLow = variant.track_inventory !== false && variant.inventory_count != null && variant.inventory_count > 0 && variant.inventory_count <= 5;
1865
+ return /* @__PURE__ */ jsxs(
1866
+ "button",
1867
+ {
1868
+ role: "radio",
1869
+ "aria-checked": isSelected,
1870
+ "aria-label": `${variant.options?.Size || variant.name}${variantOutOfStock ? " - Out of stock" : ""}`,
1871
+ onClick: () => !variantOutOfStock && onSelect(variant),
1872
+ disabled: variantOutOfStock,
1873
+ style: {
1874
+ position: "relative",
1875
+ padding: "0.5rem 1rem",
1876
+ borderRadius: "var(--commerce-radius-sm)",
1877
+ border: isSelected ? "2px solid var(--commerce-accent)" : "1px solid var(--commerce-border)",
1878
+ backgroundColor: isSelected ? "rgba(37,99,235,0.05)" : "white",
1879
+ color: variantOutOfStock ? "var(--commerce-text-muted)" : "var(--commerce-text)",
1880
+ fontSize: "0.875rem",
1881
+ fontWeight: 500,
1882
+ cursor: variantOutOfStock ? "not-allowed" : "pointer",
1883
+ opacity: variantOutOfStock ? 0.5 : 1,
1884
+ transition: "all 0.15s ease",
1885
+ textDecoration: variantOutOfStock ? "line-through" : "none"
1886
+ },
1887
+ children: [
1888
+ variant.options?.Size || variant.name,
1889
+ showInventory && !variantOutOfStock && /* @__PURE__ */ jsx(
1890
+ "span",
1891
+ {
1892
+ style: {
1893
+ position: "absolute",
1894
+ top: -3,
1895
+ right: -3,
1896
+ width: 8,
1897
+ height: 8,
1898
+ borderRadius: "50%",
1899
+ backgroundColor: isLow ? "var(--commerce-warning)" : "var(--commerce-success)",
1900
+ border: "2px solid white"
1901
+ },
1902
+ title: isLow ? `Only ${variant.inventory_count} left` : "In stock"
1903
+ }
1904
+ )
1905
+ ]
1906
+ },
1907
+ variant.id
1908
+ );
1909
+ }) })
1910
+ ] });
1911
+ }
1912
+ function QuantitySelector({ quantity, max, onChange }) {
1913
+ return /* @__PURE__ */ jsxs("div", { style: { marginTop: "1.25rem" }, children: [
1914
+ /* @__PURE__ */ jsx(
1915
+ "label",
1916
+ {
1917
+ style: {
1918
+ display: "block",
1919
+ fontSize: "0.875rem",
1920
+ fontWeight: 600,
1921
+ color: "var(--commerce-text)",
1922
+ marginBottom: "0.5rem"
1923
+ },
1924
+ children: "Quantity"
1925
+ }
1926
+ ),
1927
+ /* @__PURE__ */ jsxs(
1928
+ "div",
1929
+ {
1930
+ style: {
1931
+ display: "inline-flex",
1932
+ alignItems: "center",
1933
+ border: "1px solid var(--commerce-border)",
1934
+ borderRadius: "var(--commerce-radius-sm)",
1935
+ overflow: "hidden"
1936
+ },
1937
+ children: [
1938
+ /* @__PURE__ */ jsx(
1939
+ "button",
1940
+ {
1941
+ onClick: () => onChange(Math.max(1, quantity - 1)),
1942
+ disabled: quantity <= 1,
1943
+ "aria-label": "Decrease quantity",
1944
+ style: {
1945
+ width: 40,
1946
+ height: 40,
1947
+ border: "none",
1948
+ background: "var(--commerce-surface)",
1949
+ fontSize: "1.125rem",
1950
+ cursor: quantity <= 1 ? "not-allowed" : "pointer",
1951
+ opacity: quantity <= 1 ? 0.4 : 1,
1952
+ display: "flex",
1953
+ alignItems: "center",
1954
+ justifyContent: "center",
1955
+ color: "var(--commerce-text)"
1956
+ },
1957
+ children: "-"
1958
+ }
1959
+ ),
1960
+ /* @__PURE__ */ jsx(
1961
+ "input",
1962
+ {
1963
+ type: "number",
1964
+ min: 1,
1965
+ max,
1966
+ value: quantity,
1967
+ onChange: (e) => {
1968
+ const val = parseInt(e.target.value) || 1;
1969
+ onChange(Math.max(1, Math.min(max, val)));
1970
+ },
1971
+ "aria-label": "Quantity",
1972
+ style: {
1973
+ width: 48,
1974
+ height: 40,
1975
+ textAlign: "center",
1976
+ border: "none",
1977
+ borderLeft: "1px solid var(--commerce-border)",
1978
+ borderRight: "1px solid var(--commerce-border)",
1979
+ fontSize: "0.9375rem",
1980
+ fontWeight: 500,
1981
+ color: "var(--commerce-text)",
1982
+ outline: "none",
1983
+ MozAppearance: "textfield",
1984
+ appearance: "textfield"
1985
+ }
1986
+ }
1987
+ ),
1988
+ /* @__PURE__ */ jsx(
1989
+ "button",
1990
+ {
1991
+ onClick: () => onChange(Math.min(max, quantity + 1)),
1992
+ disabled: quantity >= max,
1993
+ "aria-label": "Increase quantity",
1994
+ style: {
1995
+ width: 40,
1996
+ height: 40,
1997
+ border: "none",
1998
+ background: "var(--commerce-surface)",
1999
+ fontSize: "1.125rem",
2000
+ cursor: quantity >= max ? "not-allowed" : "pointer",
2001
+ opacity: quantity >= max ? 0.4 : 1,
2002
+ display: "flex",
2003
+ alignItems: "center",
2004
+ justifyContent: "center",
2005
+ color: "var(--commerce-text)"
2006
+ },
2007
+ children: "+"
2008
+ }
2009
+ )
2010
+ ]
2011
+ }
2012
+ )
2013
+ ] });
2014
+ }
2015
+ var DEFAULT_TRUST_BADGES = [
2016
+ { icon: "lock", label: "Secure Checkout", sublabel: "SSL encrypted" },
2017
+ { icon: "truck", label: "Fast Shipping", sublabel: "Free over $50" },
2018
+ { icon: "return", label: "Easy Returns", sublabel: "30-day policy" }
2019
+ ];
2020
+ function TrustBadges({ badges = DEFAULT_TRUST_BADGES }) {
2021
+ return /* @__PURE__ */ jsx(
2022
+ "div",
2023
+ {
2024
+ style: {
2025
+ marginTop: "1.5rem",
2026
+ display: "grid",
2027
+ gridTemplateColumns: `repeat(${Math.min(badges.length, 3)}, 1fr)`,
2028
+ gap: "0.75rem"
2029
+ },
2030
+ children: badges.map((badge, idx) => {
2031
+ const Icon = badge.icon ? ICON_MAP[badge.icon] : IconShield;
2032
+ return /* @__PURE__ */ jsxs(
2033
+ "div",
2034
+ {
2035
+ style: {
2036
+ display: "flex",
2037
+ flexDirection: "column",
2038
+ alignItems: "center",
2039
+ textAlign: "center",
2040
+ padding: "0.75rem 0.5rem",
2041
+ borderRadius: "var(--commerce-radius-sm)",
2042
+ background: "var(--commerce-surface)"
2043
+ },
2044
+ children: [
2045
+ /* @__PURE__ */ jsx("span", { style: { color: "var(--commerce-text-secondary)", marginBottom: 4 }, children: Icon && /* @__PURE__ */ jsx(Icon, {}) }),
2046
+ /* @__PURE__ */ jsx(
2047
+ "span",
2048
+ {
2049
+ style: {
2050
+ fontSize: "0.75rem",
2051
+ fontWeight: 600,
2052
+ color: "var(--commerce-text)",
2053
+ lineHeight: 1.3
2054
+ },
2055
+ children: badge.label
2056
+ }
2057
+ ),
2058
+ badge.sublabel && /* @__PURE__ */ jsx(
2059
+ "span",
2060
+ {
2061
+ style: {
2062
+ fontSize: "0.6875rem",
2063
+ color: "var(--commerce-text-muted)",
2064
+ lineHeight: 1.3
2065
+ },
2066
+ children: badge.sublabel
2067
+ }
2068
+ )
2069
+ ]
2070
+ },
2071
+ idx
2072
+ );
2073
+ })
2074
+ }
2075
+ );
2076
+ }
2077
+ function ProductTabs({
2078
+ features,
2079
+ specifications,
2080
+ description,
2081
+ showFeatures,
2082
+ showSpecifications,
2083
+ showDescription
2084
+ }) {
2085
+ const tabs = [];
2086
+ if (showFeatures && features?.length) tabs.push({ id: "features", label: "Features" });
2087
+ if (showSpecifications && specifications && Object.keys(specifications).length)
2088
+ tabs.push({ id: "specs", label: "Specifications" });
2089
+ if (showDescription && description) tabs.push({ id: "description", label: "Description" });
2090
+ const [active, setActive] = useState(tabs[0]?.id || "");
2091
+ useEffect(() => {
2092
+ if (tabs.length && !tabs.find((t) => t.id === active)) {
2093
+ setActive(tabs[0].id);
2094
+ }
2095
+ }, [tabs.length]);
2096
+ if (!tabs.length) return null;
2097
+ return /* @__PURE__ */ jsxs("div", { style: { marginTop: "2rem" }, children: [
2098
+ /* @__PURE__ */ jsx("div", { className: "skc-tabs-list", role: "tablist", children: tabs.map((tab) => /* @__PURE__ */ jsx(
2099
+ "button",
2100
+ {
2101
+ className: `skc-tab-btn${active === tab.id ? " skc-active" : ""}`,
2102
+ role: "tab",
2103
+ "aria-selected": active === tab.id,
2104
+ "aria-controls": `skc-tabpanel-${tab.id}`,
2105
+ onClick: () => setActive(tab.id),
2106
+ children: tab.label
2107
+ },
2108
+ tab.id
2109
+ )) }),
2110
+ /* @__PURE__ */ jsxs("div", { style: { padding: "1.25rem 0", animation: "skc-fadeIn 0.2s ease-out" }, children: [
2111
+ active === "features" && features && /* @__PURE__ */ jsx("div", { id: "skc-tabpanel-features", role: "tabpanel", children: /* @__PURE__ */ jsx(
2112
+ "ul",
2113
+ {
2114
+ style: {
2115
+ margin: 0,
2116
+ paddingLeft: "1.25rem",
2117
+ display: "flex",
2118
+ flexDirection: "column",
2119
+ gap: "0.5rem"
2120
+ },
2121
+ children: features.map((f, i) => /* @__PURE__ */ jsx(
2122
+ "li",
2123
+ {
2124
+ style: {
2125
+ color: "var(--commerce-text-secondary)",
2126
+ fontSize: "0.9375rem",
2127
+ lineHeight: 1.6
2128
+ },
2129
+ children: f
2130
+ },
2131
+ i
2132
+ ))
2133
+ }
2134
+ ) }),
2135
+ active === "specs" && specifications && /* @__PURE__ */ jsx("div", { id: "skc-tabpanel-specs", role: "tabpanel", children: /* @__PURE__ */ jsx(
2136
+ "dl",
2137
+ {
2138
+ style: {
2139
+ margin: 0,
2140
+ display: "grid",
2141
+ gridTemplateColumns: "minmax(120px, auto) 1fr",
2142
+ gap: "0.625rem 1.5rem"
2143
+ },
2144
+ children: Object.entries(specifications).map(([key, value]) => /* @__PURE__ */ jsxs(React5.Fragment, { children: [
2145
+ /* @__PURE__ */ jsx(
2146
+ "dt",
2147
+ {
2148
+ style: {
2149
+ fontSize: "0.875rem",
2150
+ color: "var(--commerce-text-muted)",
2151
+ fontWeight: 500
2152
+ },
2153
+ children: key
2154
+ }
2155
+ ),
2156
+ /* @__PURE__ */ jsx(
2157
+ "dd",
2158
+ {
2159
+ style: {
2160
+ margin: 0,
2161
+ fontSize: "0.875rem",
2162
+ color: "var(--commerce-text)"
2163
+ },
2164
+ children: value
2165
+ }
2166
+ )
2167
+ ] }, key))
2168
+ }
2169
+ ) }),
2170
+ active === "description" && description && /* @__PURE__ */ jsx(
2171
+ "div",
2172
+ {
2173
+ id: "skc-tabpanel-description",
2174
+ role: "tabpanel",
2175
+ style: {
2176
+ color: "var(--commerce-text-secondary)",
2177
+ lineHeight: 1.7,
2178
+ fontSize: "0.9375rem"
2179
+ },
2180
+ dangerouslySetInnerHTML: { __html: description }
2181
+ }
2182
+ )
2183
+ ] })
2184
+ ] });
2185
+ }
2186
+ function EventInfoBlock({ product, schedule }) {
2187
+ schedule ? getSpotsRemaining(schedule.capacity, schedule.current_registrations ?? (schedule.capacity != null ? schedule.capacity - (schedule.spots_remaining ?? schedule.capacity) : 0)) : null;
2188
+ const soldOut = schedule ? isEventSoldOut(schedule.capacity, schedule.current_registrations ?? (schedule.capacity != null ? schedule.capacity - (schedule.spots_remaining ?? schedule.capacity) : 0)) : false;
2189
+ return /* @__PURE__ */ jsxs(
2190
+ "div",
2191
+ {
2192
+ style: {
2193
+ marginTop: "1.25rem",
2194
+ padding: "1rem",
2195
+ borderRadius: "var(--commerce-radius-sm)",
2196
+ background: "var(--commerce-surface)",
2197
+ display: "flex",
2198
+ flexDirection: "column",
2199
+ gap: "0.5rem"
2200
+ },
2201
+ children: [
2202
+ schedule && /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, fontSize: "0.875rem", color: "var(--commerce-text-secondary)" }, children: [
2203
+ /* @__PURE__ */ jsx(IconCalendar, {}),
2204
+ /* @__PURE__ */ jsxs("span", { children: [
2205
+ formatDate(schedule.starts_at),
2206
+ " at ",
2207
+ formatTime(schedule.starts_at)
2208
+ ] })
2209
+ ] }),
2210
+ product.location && /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, fontSize: "0.875rem", color: "var(--commerce-text-secondary)" }, children: [
2211
+ /* @__PURE__ */ jsx(IconMapPin, {}),
2212
+ /* @__PURE__ */ jsx("span", { children: product.location })
2213
+ ] }),
2214
+ product.is_virtual && product.virtual_meeting_url && /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, fontSize: "0.875rem", color: "var(--commerce-accent)" }, children: [
2215
+ /* @__PURE__ */ jsx(IconExternalLink, {}),
2216
+ /* @__PURE__ */ jsx("span", { children: "Virtual Event" })
2217
+ ] }),
2218
+ schedule?.capacity != null && /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, fontSize: "0.875rem", color: "var(--commerce-text-secondary)" }, children: [
2219
+ /* @__PURE__ */ jsx(IconUsers, {}),
2220
+ /* @__PURE__ */ jsx("span", { children: soldOut ? /* @__PURE__ */ jsx("span", { style: { color: "var(--commerce-danger)", fontWeight: 600 }, children: "Sold Out" }) : schedule.spots_remaining != null && schedule.spots_remaining <= 10 ? /* @__PURE__ */ jsxs("span", { className: "skc-pulse", style: { color: "var(--commerce-warning)", fontWeight: 600 }, children: [
2221
+ "Only ",
2222
+ schedule.spots_remaining,
2223
+ " spot",
2224
+ schedule.spots_remaining !== 1 ? "s" : "",
2225
+ " left!"
2226
+ ] }) : /* @__PURE__ */ jsxs("span", { children: [
2227
+ schedule.spots_remaining ?? schedule.capacity,
2228
+ " spots available"
2229
+ ] }) })
2230
+ ] })
2231
+ ]
2232
+ }
2233
+ );
2234
+ }
2235
+ function CheckoutStepIndicator({ current, steps }) {
2236
+ const currentIdx = steps.indexOf(current);
2237
+ return /* @__PURE__ */ jsx("div", { className: "skc-step-dots", children: steps.map((step, idx) => /* @__PURE__ */ jsxs(React5.Fragment, { children: [
2238
+ idx > 0 && /* @__PURE__ */ jsx("div", { className: `skc-step-connector${idx <= currentIdx ? " skc-done" : ""}` }),
2239
+ /* @__PURE__ */ jsx(
2240
+ "div",
2241
+ {
2242
+ className: `skc-step-dot${idx === currentIdx ? " skc-active" : idx < currentIdx ? " skc-done" : ""}`,
2243
+ title: step.replace("-", " ")
2244
+ }
2245
+ )
2246
+ ] }, step)) });
2247
+ }
2248
+ function CustomerInfoStep({ customer, onChange, onNext, onBack }) {
2249
+ const handleSubmit = (e) => {
2250
+ e.preventDefault();
2251
+ onNext();
2252
+ };
2253
+ return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, style: { display: "flex", flexDirection: "column", gap: "0.875rem" }, children: [
2254
+ /* @__PURE__ */ jsx("h3", { style: { margin: 0, fontSize: "1.125rem", fontWeight: 600, color: "var(--commerce-text)" }, children: "Contact Information" }),
2255
+ /* @__PURE__ */ jsxs("div", { children: [
2256
+ /* @__PURE__ */ jsx("label", { style: { display: "block", fontSize: "0.8125rem", fontWeight: 500, color: "var(--commerce-text-secondary)", marginBottom: 4 }, children: "Full Name *" }),
2257
+ /* @__PURE__ */ jsx(
2258
+ "input",
2259
+ {
2260
+ className: "skc-input",
2261
+ type: "text",
2262
+ required: true,
2263
+ value: customer.name,
2264
+ onChange: (e) => onChange({ ...customer, name: e.target.value }),
2265
+ placeholder: "Jane Smith",
2266
+ autoFocus: true
2267
+ }
2268
+ )
2269
+ ] }),
2270
+ /* @__PURE__ */ jsxs("div", { children: [
2271
+ /* @__PURE__ */ jsx("label", { style: { display: "block", fontSize: "0.8125rem", fontWeight: 500, color: "var(--commerce-text-secondary)", marginBottom: 4 }, children: "Email Address *" }),
2272
+ /* @__PURE__ */ jsx(
2273
+ "input",
2274
+ {
2275
+ className: "skc-input",
2276
+ type: "email",
2277
+ required: true,
2278
+ value: customer.email,
2279
+ onChange: (e) => onChange({ ...customer, email: e.target.value }),
2280
+ placeholder: "jane@example.com"
2281
+ }
2282
+ )
2283
+ ] }),
2284
+ /* @__PURE__ */ jsxs("div", { children: [
2285
+ /* @__PURE__ */ jsx("label", { style: { display: "block", fontSize: "0.8125rem", fontWeight: 500, color: "var(--commerce-text-secondary)", marginBottom: 4 }, children: "Phone Number" }),
2286
+ /* @__PURE__ */ jsx(
2287
+ "input",
2288
+ {
2289
+ className: "skc-input",
2290
+ type: "tel",
2291
+ value: customer.phone || "",
2292
+ onChange: (e) => onChange({ ...customer, phone: e.target.value }),
2293
+ placeholder: "(555) 123-4567"
2294
+ }
2295
+ )
2296
+ ] }),
2297
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "0.75rem", marginTop: "0.5rem" }, children: [
2298
+ /* @__PURE__ */ jsx(
2299
+ "button",
2300
+ {
2301
+ type: "button",
2302
+ onClick: onBack,
2303
+ style: {
2304
+ padding: "0.75rem 1.25rem",
2305
+ borderRadius: "var(--commerce-radius-sm)",
2306
+ border: "1px solid var(--commerce-border)",
2307
+ background: "white",
2308
+ color: "var(--commerce-text-secondary)",
2309
+ fontSize: "0.875rem",
2310
+ fontWeight: 500,
2311
+ cursor: "pointer"
2312
+ },
2313
+ children: "Back"
2314
+ }
2315
+ ),
2316
+ /* @__PURE__ */ jsx("button", { type: "submit", className: "skc-btn-primary", style: { flex: 1 }, children: "Continue" })
2317
+ ] })
2318
+ ] });
2319
+ }
2320
+ function ShippingAddressStep({ address, onChange, onNext, onBack, loading }) {
2321
+ const handleSubmit = (e) => {
2322
+ e.preventDefault();
2323
+ onNext();
2324
+ };
2325
+ const update = (field, value) => {
2326
+ onChange({ ...address, [field]: value });
2327
+ };
2328
+ return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, style: { display: "flex", flexDirection: "column", gap: "0.875rem" }, children: [
2329
+ /* @__PURE__ */ jsx("h3", { style: { margin: 0, fontSize: "1.125rem", fontWeight: 600, color: "var(--commerce-text)" }, children: "Shipping Address" }),
2330
+ /* @__PURE__ */ jsxs("div", { children: [
2331
+ /* @__PURE__ */ jsx("label", { style: { display: "block", fontSize: "0.8125rem", fontWeight: 500, color: "var(--commerce-text-secondary)", marginBottom: 4 }, children: "Street Address *" }),
2332
+ /* @__PURE__ */ jsx(
2333
+ "input",
2334
+ {
2335
+ className: "skc-input",
2336
+ type: "text",
2337
+ required: true,
2338
+ value: address.street1,
2339
+ onChange: (e) => update("street1", e.target.value),
2340
+ placeholder: "123 Main St",
2341
+ autoFocus: true
2342
+ }
2343
+ )
2344
+ ] }),
2345
+ /* @__PURE__ */ jsxs("div", { children: [
2346
+ /* @__PURE__ */ jsx("label", { style: { display: "block", fontSize: "0.8125rem", fontWeight: 500, color: "var(--commerce-text-secondary)", marginBottom: 4 }, children: "Apt / Suite" }),
2347
+ /* @__PURE__ */ jsx(
2348
+ "input",
2349
+ {
2350
+ className: "skc-input",
2351
+ type: "text",
2352
+ value: address.street2 || "",
2353
+ onChange: (e) => update("street2", e.target.value),
2354
+ placeholder: "Apt 4B"
2355
+ }
2356
+ )
2357
+ ] }),
2358
+ /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "0.75rem" }, children: [
2359
+ /* @__PURE__ */ jsxs("div", { children: [
2360
+ /* @__PURE__ */ jsx("label", { style: { display: "block", fontSize: "0.8125rem", fontWeight: 500, color: "var(--commerce-text-secondary)", marginBottom: 4 }, children: "City *" }),
2361
+ /* @__PURE__ */ jsx(
2362
+ "input",
2363
+ {
2364
+ className: "skc-input",
2365
+ type: "text",
2366
+ required: true,
2367
+ value: address.city,
2368
+ onChange: (e) => update("city", e.target.value),
2369
+ placeholder: "New York"
2370
+ }
2371
+ )
2372
+ ] }),
2373
+ /* @__PURE__ */ jsxs("div", { children: [
2374
+ /* @__PURE__ */ jsx("label", { style: { display: "block", fontSize: "0.8125rem", fontWeight: 500, color: "var(--commerce-text-secondary)", marginBottom: 4 }, children: "State *" }),
2375
+ /* @__PURE__ */ jsx(
2376
+ "input",
2377
+ {
2378
+ className: "skc-input",
2379
+ type: "text",
2380
+ required: true,
2381
+ value: address.state,
2382
+ onChange: (e) => update("state", e.target.value),
2383
+ placeholder: "NY"
2384
+ }
2385
+ )
2386
+ ] })
2387
+ ] }),
2388
+ /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "0.75rem" }, children: [
2389
+ /* @__PURE__ */ jsxs("div", { children: [
2390
+ /* @__PURE__ */ jsx("label", { style: { display: "block", fontSize: "0.8125rem", fontWeight: 500, color: "var(--commerce-text-secondary)", marginBottom: 4 }, children: "ZIP Code *" }),
2391
+ /* @__PURE__ */ jsx(
2392
+ "input",
2393
+ {
2394
+ className: "skc-input",
2395
+ type: "text",
2396
+ required: true,
2397
+ value: address.zip,
2398
+ onChange: (e) => update("zip", e.target.value),
2399
+ placeholder: "10001"
2400
+ }
2401
+ )
2402
+ ] }),
2403
+ /* @__PURE__ */ jsxs("div", { children: [
2404
+ /* @__PURE__ */ jsx("label", { style: { display: "block", fontSize: "0.8125rem", fontWeight: 500, color: "var(--commerce-text-secondary)", marginBottom: 4 }, children: "Country" }),
2405
+ /* @__PURE__ */ jsx(
2406
+ "input",
2407
+ {
2408
+ className: "skc-input",
2409
+ type: "text",
2410
+ value: address.country || "US",
2411
+ onChange: (e) => update("country", e.target.value),
2412
+ placeholder: "US"
2413
+ }
2414
+ )
2415
+ ] })
2416
+ ] }),
2417
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "0.75rem", marginTop: "0.5rem" }, children: [
2418
+ /* @__PURE__ */ jsx(
2419
+ "button",
2420
+ {
2421
+ type: "button",
2422
+ onClick: onBack,
2423
+ style: {
2424
+ padding: "0.75rem 1.25rem",
2425
+ borderRadius: "var(--commerce-radius-sm)",
2426
+ border: "1px solid var(--commerce-border)",
2427
+ background: "white",
2428
+ color: "var(--commerce-text-secondary)",
2429
+ fontSize: "0.875rem",
2430
+ fontWeight: 500,
2431
+ cursor: "pointer"
2432
+ },
2433
+ children: "Back"
2434
+ }
2435
+ ),
2436
+ /* @__PURE__ */ jsx("button", { type: "submit", className: "skc-btn-primary", style: { flex: 1 }, disabled: loading, children: loading ? "Getting rates..." : "Continue to Shipping" })
2437
+ ] })
2438
+ ] });
2439
+ }
2440
+ function ShippingRatesStep({ rates, selected, onSelect, onNext, onBack, loading, currency }) {
2441
+ if (loading) {
2442
+ return /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: "2rem 0" }, children: [
2443
+ /* @__PURE__ */ jsx(
2444
+ "div",
2445
+ {
2446
+ style: {
2447
+ width: 32,
2448
+ height: 32,
2449
+ border: "3px solid var(--commerce-border)",
2450
+ borderTopColor: "var(--commerce-accent)",
2451
+ borderRadius: "50%",
2452
+ animation: "skc-spin 1s linear infinite",
2453
+ margin: "0 auto 1rem"
2454
+ }
2455
+ }
2456
+ ),
2457
+ /* @__PURE__ */ jsx("p", { style: { color: "var(--commerce-text-secondary)", fontSize: "0.875rem", margin: 0 }, children: "Calculating shipping rates..." })
2458
+ ] });
2459
+ }
2460
+ if (!rates.length) {
2461
+ return /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: "1.5rem 0" }, children: [
2462
+ /* @__PURE__ */ jsx("p", { style: { color: "var(--commerce-text-secondary)", fontSize: "0.875rem", margin: "0 0 1rem" }, children: "No shipping rates available for this address. Please check your address and try again." }),
2463
+ /* @__PURE__ */ jsx(
2464
+ "button",
2465
+ {
2466
+ type: "button",
2467
+ onClick: onBack,
2468
+ style: {
2469
+ padding: "0.75rem 1.5rem",
2470
+ borderRadius: "var(--commerce-radius-sm)",
2471
+ border: "1px solid var(--commerce-border)",
2472
+ background: "white",
2473
+ color: "var(--commerce-text-secondary)",
2474
+ fontSize: "0.875rem",
2475
+ fontWeight: 500,
2476
+ cursor: "pointer"
2477
+ },
2478
+ children: "Edit Address"
2479
+ }
2480
+ )
2481
+ ] });
2482
+ }
2483
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.875rem" }, children: [
2484
+ /* @__PURE__ */ jsx("h3", { style: { margin: 0, fontSize: "1.125rem", fontWeight: 600, color: "var(--commerce-text)" }, children: "Shipping Method" }),
2485
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, role: "radiogroup", "aria-label": "Shipping options", children: rates.map((rate, idx) => {
2486
+ const isSelected = selected?.objectId === rate.objectId || selected === null && idx === 0;
2487
+ return /* @__PURE__ */ jsxs(
2488
+ "button",
2489
+ {
2490
+ role: "radio",
2491
+ "aria-checked": isSelected,
2492
+ onClick: () => onSelect(rate),
2493
+ style: {
2494
+ display: "flex",
2495
+ alignItems: "center",
2496
+ justifyContent: "space-between",
2497
+ padding: "0.875rem 1rem",
2498
+ borderRadius: "var(--commerce-radius-sm)",
2499
+ border: isSelected ? "2px solid var(--commerce-accent)" : "1px solid var(--commerce-border)",
2500
+ background: isSelected ? "rgba(37,99,235,0.03)" : "white",
2501
+ cursor: "pointer",
2502
+ textAlign: "left",
2503
+ width: "100%"
2504
+ },
2505
+ children: [
2506
+ /* @__PURE__ */ jsxs("div", { children: [
2507
+ /* @__PURE__ */ jsxs("div", { style: { fontSize: "0.875rem", fontWeight: 600, color: "var(--commerce-text)" }, children: [
2508
+ rate.carrier,
2509
+ " \u2014 ",
2510
+ rate.service
2511
+ ] }),
2512
+ rate.estimatedDays != null && /* @__PURE__ */ jsx("div", { style: { fontSize: "0.8125rem", color: "var(--commerce-text-muted)", marginTop: 2 }, children: rate.estimatedDays === 1 ? "1 business day" : `${rate.estimatedDays} business days` })
2513
+ ] }),
2514
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "0.9375rem", fontWeight: 600, color: "var(--commerce-text)" }, children: formatPrice(parseFloat(rate.amount), rate.currency || currency) })
2515
+ ]
2516
+ },
2517
+ rate.objectId || idx
2518
+ );
2519
+ }) }),
2520
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "0.75rem", marginTop: "0.5rem" }, children: [
2521
+ /* @__PURE__ */ jsx(
2522
+ "button",
2523
+ {
2524
+ type: "button",
2525
+ onClick: onBack,
2526
+ style: {
2527
+ padding: "0.75rem 1.25rem",
2528
+ borderRadius: "var(--commerce-radius-sm)",
2529
+ border: "1px solid var(--commerce-border)",
2530
+ background: "white",
2531
+ color: "var(--commerce-text-secondary)",
2532
+ fontSize: "0.875rem",
2533
+ fontWeight: 500,
2534
+ cursor: "pointer"
2535
+ },
2536
+ children: "Back"
2537
+ }
2538
+ ),
2539
+ /* @__PURE__ */ jsx("button", { type: "button", className: "skc-btn-primary", style: { flex: 1 }, onClick: onNext, children: "Continue to Payment" })
2540
+ ] })
2541
+ ] });
2542
+ }
2543
+ function PaymentStep({
2544
+ processor,
2545
+ config,
2546
+ product,
2547
+ variant,
2548
+ quantity,
2549
+ customer,
2550
+ shippingRate,
2551
+ shippingAddress,
2552
+ needsShipping,
2553
+ onBack,
2554
+ onSuccess,
2555
+ onError,
2556
+ onProcessing,
2557
+ successUrl,
2558
+ cancelUrl
2559
+ }) {
2560
+ const [cardElement, setCardElement] = useState(null);
2561
+ const [stripeInstance, setStripeInstance] = useState(null);
2562
+ const [stripeElements, setStripeElements] = useState(null);
2563
+ const [cardReady, setCardReady] = useState(false);
2564
+ const [error, setError] = useState(null);
2565
+ const [submitting, setSubmitting] = useState(false);
2566
+ const cardContainerRef = useRef(null);
2567
+ const currentPrice = variant?.price ?? product.price ?? 0;
2568
+ const subtotal = currentPrice * quantity;
2569
+ const shippingCost = shippingRate ? parseFloat(shippingRate.amount) : 0;
2570
+ const total = subtotal + shippingCost;
2571
+ useEffect(() => {
2572
+ if (processor !== "square" || !config?.squareAppId) return;
2573
+ let destroyed = false;
2574
+ let card = null;
2575
+ loadSquareSDK(config.squareEnvironment || "production").then(async () => {
2576
+ if (destroyed) return;
2577
+ const payments = window.Square.payments(
2578
+ config.squareAppId,
2579
+ config.squareLocationId
2580
+ );
2581
+ card = await payments.card({
2582
+ style: {
2583
+ ".input-container": { borderRadius: "8px" },
2584
+ ".input-container.is-focus": { borderColor: "#2563eb" },
2585
+ ".input-container.is-error": { borderColor: "#dc2626" }
2586
+ }
2587
+ });
2588
+ if (destroyed) {
2589
+ card.destroy?.();
2590
+ return;
2591
+ }
2592
+ await card.attach("#skc-card-container");
2593
+ setCardElement(card);
2594
+ setCardReady(true);
2595
+ }).catch((err) => {
2596
+ console.error("[Commerce] Square card init failed:", err);
2597
+ setError("Failed to load payment form. Please refresh and try again.");
2598
+ });
2599
+ return () => {
2600
+ destroyed = true;
2601
+ if (card) card.destroy?.().catch(() => {
2602
+ });
2603
+ setCardElement(null);
2604
+ setCardReady(false);
2605
+ };
2606
+ }, [processor, config?.squareAppId]);
2607
+ useEffect(() => {
2608
+ if (processor !== "stripe" || !config?.stripePublishableKey) return;
2609
+ let destroyed = false;
2610
+ (async () => {
2611
+ try {
2612
+ await loadStripeSDK();
2613
+ if (destroyed) return;
2614
+ const checkoutOpts = {
2615
+ offeringId: product.id,
2616
+ variantId: variant?.id,
2617
+ quantity,
2618
+ customer,
2619
+ successUrl: successUrl || window.location.href,
2620
+ cancelUrl: cancelUrl || window.location.href
2621
+ };
2622
+ if (needsShipping && shippingAddress) {
2623
+ checkoutOpts.shippingAddress = shippingAddress;
2624
+ checkoutOpts.shippingCarrier = shippingRate?.carrier;
2625
+ checkoutOpts.shippingService = shippingRate?.service;
2626
+ checkoutOpts.shippingCost = shippingCost;
2627
+ }
2628
+ const piResult = await createPaymentIntent(checkoutOpts);
2629
+ if (destroyed) return;
2630
+ if (!piResult.success || !piResult.clientSecret) {
2631
+ setError(piResult.error || "Failed to initialize payment. Please try again.");
2632
+ return;
2633
+ }
2634
+ const stripe = window.Stripe(config.stripePublishableKey);
2635
+ const elements = stripe.elements({ clientSecret: piResult.clientSecret });
2636
+ const paymentElement = elements.create("payment", {
2637
+ layout: "tabs"
2638
+ });
2639
+ if (destroyed) return;
2640
+ paymentElement.mount("#skc-card-container");
2641
+ paymentElement.on("ready", () => {
2642
+ if (!destroyed) setCardReady(true);
2643
+ });
2644
+ setStripeInstance(stripe);
2645
+ setStripeElements(elements);
2646
+ setCardElement(paymentElement);
2647
+ cardContainerRef.current?.__saleId && delete cardContainerRef.current.__saleId;
2648
+ if (cardContainerRef.current) {
2649
+ ;
2650
+ cardContainerRef.current.__saleId = piResult.saleId;
2651
+ cardContainerRef.current.__confirmationNumber = piResult.confirmationNumber;
2652
+ }
2653
+ } catch (err) {
2654
+ console.error("[Commerce] Stripe init failed:", err);
2655
+ if (!destroyed) setError("Failed to load payment form. Please refresh and try again.");
2656
+ }
2657
+ })();
2658
+ return () => {
2659
+ destroyed = true;
2660
+ setCardElement(null);
2661
+ setStripeInstance(null);
2662
+ setStripeElements(null);
2663
+ setCardReady(false);
2664
+ };
2665
+ }, [processor, config?.stripePublishableKey]);
2666
+ const handleSubmit = async () => {
2667
+ if (!cardReady || submitting) return;
2668
+ setSubmitting(true);
2669
+ setError(null);
2670
+ onProcessing(true);
2671
+ try {
2672
+ if (processor === "square" && cardElement) {
2673
+ const tokenResult = await cardElement.tokenize();
2674
+ if (tokenResult.status !== "OK") {
2675
+ throw new Error(
2676
+ tokenResult.errors?.[0]?.message || "Card verification failed. Please check your card details."
2677
+ );
2678
+ }
2679
+ const checkoutOpts = {
2680
+ offeringId: product.id,
2681
+ variantId: variant?.id,
2682
+ quantity,
2683
+ customer,
2684
+ sourceId: tokenResult.token,
2685
+ successUrl: successUrl || window.location.href,
2686
+ cancelUrl: cancelUrl || window.location.href
2687
+ };
2688
+ if (needsShipping && shippingAddress) {
2689
+ checkoutOpts.shippingAddress = shippingAddress;
2690
+ checkoutOpts.shippingCarrier = shippingRate?.carrier;
2691
+ checkoutOpts.shippingService = shippingRate?.service;
2692
+ checkoutOpts.shippingCost = shippingCost;
2693
+ }
2694
+ const result = await createCheckoutSession(checkoutOpts);
2695
+ if (result.success && !result.payment_url) {
2696
+ onSuccess(result);
2697
+ } else if (result.success && result.payment_url) {
2698
+ window.location.href = result.payment_url;
2699
+ } else {
2700
+ throw new Error(result.error || "Payment failed. Please try again.");
2701
+ }
2702
+ } else if (processor === "stripe" && stripeInstance && stripeElements) {
2703
+ const { error: stripeError, paymentIntent } = await stripeInstance.confirmPayment({
2704
+ elements: stripeElements,
2705
+ confirmParams: {
2706
+ return_url: successUrl || window.location.href
2707
+ },
2708
+ redirect: "if_required"
2709
+ });
2710
+ if (stripeError) {
2711
+ throw new Error(stripeError.message || "Payment failed. Please try again.");
2712
+ }
2713
+ if (paymentIntent && paymentIntent.status === "succeeded") {
2714
+ const saleId = cardContainerRef.current?.__saleId;
2715
+ const confirmationNumber = cardContainerRef.current?.__confirmationNumber;
2716
+ onSuccess({
2717
+ success: true,
2718
+ sale_id: saleId,
2719
+ confirmation_number: confirmationNumber
2720
+ });
2721
+ }
2722
+ } else {
2723
+ const checkoutOpts = {
2724
+ offeringId: product.id,
2725
+ variantId: variant?.id,
2726
+ quantity,
2727
+ customer,
2728
+ successUrl: successUrl || `${window.location.origin}/checkout/success`,
2729
+ cancelUrl: cancelUrl || window.location.href
2730
+ };
2731
+ if (needsShipping && shippingAddress) {
2732
+ checkoutOpts.shippingAddress = shippingAddress;
2733
+ checkoutOpts.shippingCarrier = shippingRate?.carrier;
2734
+ checkoutOpts.shippingService = shippingRate?.service;
2735
+ checkoutOpts.shippingCost = shippingCost;
2736
+ }
2737
+ const result = await createCheckoutSession(checkoutOpts);
2738
+ if (result.success && result.checkout_url) {
2739
+ window.location.href = result.checkout_url;
2740
+ } else {
2741
+ throw new Error(result.error || "Checkout failed.");
2742
+ }
2743
+ }
2744
+ } catch (err) {
2745
+ const msg = err?.message || "Payment failed. Please try again.";
2746
+ setError(msg);
2747
+ onError(msg);
2748
+ } finally {
2749
+ setSubmitting(false);
2750
+ onProcessing(false);
2751
+ }
2752
+ };
2753
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1rem" }, children: [
2754
+ /* @__PURE__ */ jsx("h3", { style: { margin: 0, fontSize: "1.125rem", fontWeight: 600, color: "var(--commerce-text)" }, children: "Payment" }),
2755
+ /* @__PURE__ */ jsxs(
2756
+ "div",
2757
+ {
2758
+ style: {
2759
+ padding: "1rem",
2760
+ borderRadius: "var(--commerce-radius-sm)",
2761
+ background: "var(--commerce-surface)",
2762
+ display: "flex",
2763
+ flexDirection: "column",
2764
+ gap: "0.375rem",
2765
+ fontSize: "0.875rem"
2766
+ },
2767
+ children: [
2768
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", color: "var(--commerce-text-secondary)" }, children: [
2769
+ /* @__PURE__ */ jsxs("span", { children: [
2770
+ product.name,
2771
+ " ",
2772
+ variant ? `(${variant.options?.Size || variant.name})` : "",
2773
+ " x ",
2774
+ quantity
2775
+ ] }),
2776
+ /* @__PURE__ */ jsx("span", { children: formatPrice(subtotal, product.currency) })
2777
+ ] }),
2778
+ shippingRate && /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", color: "var(--commerce-text-secondary)" }, children: [
2779
+ /* @__PURE__ */ jsxs("span", { children: [
2780
+ "Shipping (",
2781
+ shippingRate.carrier,
2782
+ " ",
2783
+ shippingRate.service,
2784
+ ")"
2785
+ ] }),
2786
+ /* @__PURE__ */ jsx("span", { children: formatPrice(shippingCost, shippingRate.currency || product.currency) })
2787
+ ] }),
2788
+ /* @__PURE__ */ jsxs(
2789
+ "div",
2790
+ {
2791
+ style: {
2792
+ display: "flex",
2793
+ justifyContent: "space-between",
2794
+ fontWeight: 700,
2795
+ color: "var(--commerce-text)",
2796
+ fontSize: "1rem",
2797
+ paddingTop: "0.5rem",
2798
+ borderTop: "1px solid var(--commerce-border)",
2799
+ marginTop: "0.25rem"
2800
+ },
2801
+ children: [
2802
+ /* @__PURE__ */ jsx("span", { children: "Total" }),
2803
+ /* @__PURE__ */ jsx("span", { children: formatPrice(total, product.currency) })
2804
+ ]
2805
+ }
2806
+ )
2807
+ ]
2808
+ }
2809
+ ),
2810
+ /* @__PURE__ */ jsxs("div", { children: [
2811
+ /* @__PURE__ */ jsx(
2812
+ "label",
2813
+ {
2814
+ style: {
2815
+ display: "block",
2816
+ fontSize: "0.8125rem",
2817
+ fontWeight: 500,
2818
+ color: "var(--commerce-text-secondary)",
2819
+ marginBottom: 6
2820
+ },
2821
+ children: "Card Details"
2822
+ }
2823
+ ),
2824
+ /* @__PURE__ */ jsx(
2825
+ "div",
2826
+ {
2827
+ id: "skc-card-container",
2828
+ ref: cardContainerRef,
2829
+ style: {
2830
+ minHeight: processor === "stripe" ? 80 : 44,
2831
+ border: "1px solid var(--commerce-border)",
2832
+ borderRadius: "var(--commerce-radius-sm)",
2833
+ padding: processor === "stripe" ? "0.75rem" : "0.5rem 0.75rem",
2834
+ background: "white"
2835
+ }
2836
+ }
2837
+ ),
2838
+ !cardReady && !error && /* @__PURE__ */ jsx("p", { style: { fontSize: "0.75rem", color: "var(--commerce-text-muted)", marginTop: 4, marginBottom: 0 }, children: "Loading secure payment form..." })
2839
+ ] }),
2840
+ error && /* @__PURE__ */ jsxs(
2841
+ "div",
2842
+ {
2843
+ style: {
2844
+ display: "flex",
2845
+ alignItems: "flex-start",
2846
+ gap: 8,
2847
+ padding: "0.75rem",
2848
+ background: "#fef2f2",
2849
+ border: "1px solid #fecaca",
2850
+ borderRadius: "var(--commerce-radius-sm)",
2851
+ color: "var(--commerce-danger)",
2852
+ fontSize: "0.875rem"
2853
+ },
2854
+ children: [
2855
+ /* @__PURE__ */ jsx(IconAlert, {}),
2856
+ /* @__PURE__ */ jsx("span", { children: error })
2857
+ ]
2858
+ }
2859
+ ),
2860
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "0.75rem" }, children: [
2861
+ /* @__PURE__ */ jsx(
2862
+ "button",
2863
+ {
2864
+ type: "button",
2865
+ onClick: onBack,
2866
+ disabled: submitting,
2867
+ style: {
2868
+ padding: "0.75rem 1.25rem",
2869
+ borderRadius: "var(--commerce-radius-sm)",
2870
+ border: "1px solid var(--commerce-border)",
2871
+ background: "white",
2872
+ color: "var(--commerce-text-secondary)",
2873
+ fontSize: "0.875rem",
2874
+ fontWeight: 500,
2875
+ cursor: submitting ? "not-allowed" : "pointer",
2876
+ opacity: submitting ? 0.5 : 1
2877
+ },
2878
+ children: "Back"
2879
+ }
2880
+ ),
2881
+ /* @__PURE__ */ jsx(
2882
+ "button",
2883
+ {
2884
+ type: "button",
2885
+ className: "skc-btn-primary",
2886
+ style: { flex: 1 },
2887
+ onClick: handleSubmit,
2888
+ disabled: !cardReady || submitting,
2889
+ children: submitting ? /* @__PURE__ */ jsxs(Fragment, { children: [
2890
+ /* @__PURE__ */ jsx(
2891
+ "span",
2892
+ {
2893
+ style: {
2894
+ width: 16,
2895
+ height: 16,
2896
+ border: "2px solid rgba(255,255,255,0.3)",
2897
+ borderTopColor: "white",
2898
+ borderRadius: "50%",
2899
+ animation: "skc-spin 0.8s linear infinite",
2900
+ display: "inline-block"
2901
+ }
2902
+ }
2903
+ ),
2904
+ "Processing..."
2905
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
2906
+ /* @__PURE__ */ jsx(IconLock, {}),
2907
+ "Pay ",
2908
+ formatPrice(total, product.currency)
2909
+ ] })
2910
+ }
2911
+ )
2912
+ ] }),
2913
+ processor && /* @__PURE__ */ jsxs(
2914
+ "p",
2915
+ {
2916
+ style: {
2917
+ textAlign: "center",
2918
+ fontSize: "0.6875rem",
2919
+ color: "var(--commerce-text-muted)",
2920
+ margin: "0.25rem 0 0"
2921
+ },
2922
+ children: [
2923
+ "Powered by ",
2924
+ processor === "stripe" ? "Stripe" : "Square"
2925
+ ]
2926
+ }
2927
+ )
2928
+ ] });
2929
+ }
2930
+ function SuccessStep({ result, product, onClose }) {
2931
+ return /* @__PURE__ */ jsxs(
2932
+ "div",
2933
+ {
2934
+ style: {
2935
+ textAlign: "center",
2936
+ padding: "2rem 1rem",
2937
+ animation: "skc-fadeIn 0.3s ease-out"
2938
+ },
2939
+ children: [
2940
+ /* @__PURE__ */ jsx(
2941
+ "div",
2942
+ {
2943
+ style: {
2944
+ width: 64,
2945
+ height: 64,
2946
+ borderRadius: "50%",
2947
+ background: "rgba(5,150,105,0.1)",
2948
+ display: "flex",
2949
+ alignItems: "center",
2950
+ justifyContent: "center",
2951
+ margin: "0 auto 1rem"
2952
+ },
2953
+ children: /* @__PURE__ */ jsx(
2954
+ "svg",
2955
+ {
2956
+ width: "32",
2957
+ height: "32",
2958
+ viewBox: "0 0 24 24",
2959
+ fill: "none",
2960
+ stroke: "var(--commerce-success)",
2961
+ strokeWidth: "2.5",
2962
+ strokeLinecap: "round",
2963
+ strokeLinejoin: "round",
2964
+ children: /* @__PURE__ */ jsx(
2965
+ "polyline",
2966
+ {
2967
+ points: "20 6 9 17 4 12",
2968
+ style: { strokeDasharray: 24, strokeDashoffset: 0, animation: "skc-checkmark 0.5s ease-out" }
2969
+ }
2970
+ )
2971
+ }
2972
+ )
2973
+ }
2974
+ ),
2975
+ /* @__PURE__ */ jsx(
2976
+ "h3",
2977
+ {
2978
+ style: {
2979
+ margin: "0 0 0.5rem",
2980
+ fontSize: "1.375rem",
2981
+ fontWeight: 700,
2982
+ color: "var(--commerce-success)"
2983
+ },
2984
+ children: "Order Confirmed!"
2985
+ }
2986
+ ),
2987
+ /* @__PURE__ */ jsxs("p", { style: { color: "var(--commerce-text-secondary)", margin: "0 0 0.5rem", fontSize: "0.9375rem" }, children: [
2988
+ "Thank you for your purchase of ",
2989
+ product.name,
2990
+ "."
2991
+ ] }),
2992
+ result.confirmation_number && /* @__PURE__ */ jsxs("p", { style: { color: "var(--commerce-text-muted)", margin: "0 0 1rem", fontSize: "0.8125rem" }, children: [
2993
+ "Confirmation: ",
2994
+ /* @__PURE__ */ jsx("strong", { style: { color: "var(--commerce-text)" }, children: result.confirmation_number })
2995
+ ] }),
2996
+ /* @__PURE__ */ jsx("p", { style: { color: "var(--commerce-text-muted)", margin: "0 0 1.5rem", fontSize: "0.875rem" }, children: "A confirmation email has been sent to your inbox." }),
2997
+ /* @__PURE__ */ jsx("button", { className: "skc-btn-primary", onClick: onClose, style: { maxWidth: 240 }, children: "Done" })
2998
+ ]
2999
+ }
3000
+ );
3001
+ }
3002
+ function ProductDetail({
3003
+ product: propProduct,
3004
+ slug,
3005
+ successUrl,
3006
+ cancelUrl,
3007
+ showGallery = true,
3008
+ showVariants = true,
3009
+ showQuantity = true,
3010
+ showSizeChart = true,
3011
+ showFeatures = true,
3012
+ showSpecifications = true,
3013
+ showDescription = true,
3014
+ showTrustBadges = true,
3015
+ showInventory = true,
3016
+ trustBadges,
3017
+ onAddToCart,
3018
+ onCheckoutSuccess,
3019
+ onCheckoutError,
3020
+ className = "",
3021
+ style: customStyle,
3022
+ layout = "horizontal"
3023
+ }) {
3024
+ const [product, setProduct] = useState(propProduct || null);
3025
+ const [loading, setLoading] = useState(!propProduct && !!slug);
3026
+ const [selectedVariant, setSelectedVariant] = useState();
3027
+ const [quantity, setQuantity] = useState(1);
3028
+ const [selectedImage, setSelectedImage] = useState(0);
3029
+ const [checkoutState, setCheckoutState] = useState("browsing");
3030
+ const [customer, setCustomer] = useState({ name: "", email: "", phone: "" });
3031
+ const [shippingAddress, setShippingAddress] = useState({
3032
+ street1: "",
3033
+ city: "",
3034
+ state: "",
3035
+ zip: "",
3036
+ country: "US"
3037
+ });
3038
+ const [shippingRates, setShippingRates] = useState([]);
3039
+ const [selectedShippingRate, setSelectedShippingRate] = useState(null);
3040
+ const [ratesLoading, setRatesLoading] = useState(false);
3041
+ const [processorConfig, setProcessorConfig] = useState(null);
3042
+ const [checkoutResult, setCheckoutResult] = useState(null);
3043
+ const [checkoutError, setCheckoutError] = useState(null);
3044
+ const [showStickyBar, setShowStickyBar] = useState(false);
3045
+ const buyButtonRef = useRef(null);
3046
+ const analytics = useAnalyticsOptional();
3047
+ useEffect(() => {
3048
+ if (propProduct) {
3049
+ setProduct(propProduct);
3050
+ const dv = propProduct.variants?.find((v) => v.is_default) || propProduct.variants?.[0];
3051
+ setSelectedVariant(dv);
3052
+ return;
3053
+ }
3054
+ if (!slug) return;
3055
+ let cancelled = false;
3056
+ setLoading(true);
3057
+ fetchProductBySlug(slug).then((data) => {
3058
+ if (cancelled) return;
3059
+ setProduct(data);
3060
+ if (data?.variants?.length) {
3061
+ setSelectedVariant(data.variants.find((v) => v.is_default) || data.variants[0]);
3062
+ }
3063
+ setLoading(false);
3064
+ }).catch(() => {
3065
+ if (!cancelled) setLoading(false);
3066
+ });
3067
+ return () => {
3068
+ cancelled = true;
3069
+ };
3070
+ }, [propProduct, slug]);
3071
+ useEffect(() => {
3072
+ if (!product || !analytics) return;
3073
+ analytics.trackEvent({
3074
+ name: "product_view",
3075
+ properties: {
3076
+ offering_id: product.id,
3077
+ name: product.name,
3078
+ price: product.price,
3079
+ type: product.type,
3080
+ category: product.category?.name
3081
+ }
3082
+ });
3083
+ }, [product?.id]);
3084
+ useEffect(() => {
3085
+ if (!product) return;
3086
+ fetchProcessorConfig().then((c) => {
3087
+ if (c) setProcessorConfig(c);
3088
+ });
3089
+ }, [product?.id]);
3090
+ useEffect(() => {
3091
+ if (!buyButtonRef.current) return;
3092
+ const observer = new IntersectionObserver(
3093
+ ([entry]) => setShowStickyBar(!entry.isIntersecting),
3094
+ { threshold: 0 }
3095
+ );
3096
+ observer.observe(buyButtonRef.current);
3097
+ return () => observer.disconnect();
3098
+ }, [product?.id, checkoutState]);
3099
+ useEffect(() => {
3100
+ if (checkoutState === "browsing") return;
3101
+ const handleKey = (e) => {
3102
+ if (e.key === "Escape") setCheckoutState("browsing");
3103
+ };
3104
+ document.addEventListener("keydown", handleKey);
3105
+ return () => document.removeEventListener("keydown", handleKey);
3106
+ }, [checkoutState]);
3107
+ useEffect(() => {
3108
+ if (checkoutState !== "browsing" && checkoutState !== "success") {
3109
+ document.body.style.overflow = "hidden";
3110
+ } else {
3111
+ document.body.style.overflow = "";
3112
+ }
3113
+ return () => {
3114
+ document.body.style.overflow = "";
3115
+ };
3116
+ }, [checkoutState]);
3117
+ const allImages = useMemo(() => {
3118
+ if (!product) return [];
3119
+ return [
3120
+ product.featured_image_url,
3121
+ ...product.gallery_images || [],
3122
+ ...product.variants?.map((v) => v.image_url).filter(Boolean) || []
3123
+ ].filter(Boolean);
3124
+ }, [product]);
3125
+ if (!product) {
3126
+ if (loading) {
3127
+ return /* @__PURE__ */ jsxs("div", { className: `skc-detail ${className}`, style: customStyle, children: [
3128
+ /* @__PURE__ */ jsx("style", { children: STYLE_BLOCK }),
3129
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", minHeight: 400 }, children: /* @__PURE__ */ jsx(
3130
+ "div",
3131
+ {
3132
+ style: {
3133
+ width: 48,
3134
+ height: 48,
3135
+ border: "3px solid var(--commerce-border)",
3136
+ borderTopColor: "var(--commerce-accent)",
3137
+ borderRadius: "50%",
3138
+ animation: "skc-spin 1s linear infinite"
3139
+ }
3140
+ }
3141
+ ) })
3142
+ ] });
3143
+ }
3144
+ return /* @__PURE__ */ jsxs("div", { className: `skc-detail ${className}`, style: customStyle, children: [
3145
+ /* @__PURE__ */ jsx("style", { children: STYLE_BLOCK }),
3146
+ /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: "4rem 2rem", color: "var(--commerce-text-secondary)" }, children: [
3147
+ /* @__PURE__ */ jsx("h2", { style: { margin: 0, fontSize: "1.5rem", color: "var(--commerce-text)" }, children: "Product Not Found" }),
3148
+ /* @__PURE__ */ jsx("p", { style: { marginTop: "0.5rem" }, children: "The product you are looking for does not exist or has been removed." })
3149
+ ] })
3150
+ ] });
3151
+ }
3152
+ const currentPrice = selectedVariant?.price ?? product.price ?? 0;
3153
+ const compareAtPrice = product.compare_at_price;
3154
+ const hasDiscount = compareAtPrice != null && compareAtPrice > currentPrice;
3155
+ const discountPercent = hasDiscount ? Math.round((compareAtPrice - currentPrice) / compareAtPrice * 100) : 0;
3156
+ const inventoryCount = selectedVariant?.inventory_count ?? product.inventory_count;
3157
+ const isOutOfStock = product.track_inventory && inventoryCount != null && inventoryCount <= 0;
3158
+ const isLowStock = product.track_inventory && inventoryCount != null && inventoryCount > 0 && inventoryCount <= 5;
3159
+ const needsVariantSelection = (product.is_clothing || (product.variants?.length ?? 0) > 1) && !selectedVariant;
3160
+ const isEvent = product.type === "event";
3161
+ const isService = product.type === "service";
3162
+ const hasExternalUrl = !!product.external_url;
3163
+ const isFree = !product.price || product.price === 0;
3164
+ const needsShipping = !!processorConfig?.shipping_enabled && product.type === "product";
3165
+ const schedule = product.schedules?.[0] || product.next_schedule;
3166
+ const checkoutSteps = useMemo(() => {
3167
+ const steps = ["customer-info"];
3168
+ if (needsShipping) {
3169
+ steps.push("shipping", "rates");
3170
+ }
3171
+ if (!isFree) {
3172
+ steps.push("payment");
3173
+ }
3174
+ return steps;
3175
+ }, [needsShipping, isFree]);
3176
+ const handleVariantChange = (variant) => {
3177
+ setSelectedVariant(variant);
3178
+ if (variant.image_url) {
3179
+ const idx = allImages.indexOf(variant.image_url);
3180
+ if (idx >= 0) setSelectedImage(idx);
3181
+ }
3182
+ };
3183
+ const handleAddToCart = () => {
3184
+ analytics?.trackEvent({
3185
+ name: "add_to_cart",
3186
+ properties: {
3187
+ offering_id: product.id,
3188
+ variant_id: selectedVariant?.id,
3189
+ quantity,
3190
+ price: currentPrice,
3191
+ name: product.name
3192
+ }
3193
+ });
3194
+ onAddToCart?.(product, selectedVariant, quantity);
3195
+ };
3196
+ const handleBuyNow = () => {
3197
+ if (hasExternalUrl) {
3198
+ window.open(product.external_url, "_blank", "noopener");
3199
+ return;
3200
+ }
3201
+ analytics?.trackEvent({
3202
+ name: "begin_checkout",
3203
+ properties: {
3204
+ offering_id: product.id,
3205
+ variant_id: selectedVariant?.id,
3206
+ quantity,
3207
+ price: currentPrice,
3208
+ name: product.name
3209
+ }
3210
+ });
3211
+ setCheckoutError(null);
3212
+ setCheckoutState("customer-info");
3213
+ };
3214
+ const handleCheckoutBack = () => {
3215
+ const currentIdx = checkoutSteps.indexOf(checkoutState);
3216
+ if (currentIdx <= 0) {
3217
+ setCheckoutState("browsing");
3218
+ } else {
3219
+ setCheckoutState(checkoutSteps[currentIdx - 1]);
3220
+ }
3221
+ };
3222
+ const handleCustomerNext = async () => {
3223
+ if (isFree && isEvent && schedule) {
3224
+ setCheckoutState("processing");
3225
+ try {
3226
+ const result = await registerForEvent(product.id, schedule.id, customer);
3227
+ if (result.success) {
3228
+ setCheckoutResult(result);
3229
+ setCheckoutState("success");
3230
+ onCheckoutSuccess?.(result);
3231
+ } else {
3232
+ setCheckoutError(result.error || "Registration failed");
3233
+ setCheckoutState("customer-info");
3234
+ }
3235
+ } catch (err) {
3236
+ setCheckoutError(err?.message || "Registration failed");
3237
+ setCheckoutState("customer-info");
3238
+ }
3239
+ return;
3240
+ }
3241
+ if (needsShipping) {
3242
+ setCheckoutState("shipping");
3243
+ } else if (!isFree) {
3244
+ setCheckoutState("payment");
3245
+ } else {
3246
+ setCheckoutState("processing");
3247
+ try {
3248
+ const result = await createCheckoutSession({
3249
+ offeringId: product.id,
3250
+ variantId: selectedVariant?.id,
3251
+ quantity,
3252
+ customer,
3253
+ successUrl: successUrl || window.location.href,
3254
+ cancelUrl: cancelUrl || window.location.href
3255
+ });
3256
+ if (result.success) {
3257
+ setCheckoutResult(result);
3258
+ setCheckoutState("success");
3259
+ onCheckoutSuccess?.(result);
3260
+ } else {
3261
+ setCheckoutError(result.error || "Checkout failed");
3262
+ setCheckoutState("customer-info");
3263
+ }
3264
+ } catch (err) {
3265
+ setCheckoutError(err?.message || "Checkout failed");
3266
+ setCheckoutState("customer-info");
3267
+ }
3268
+ }
3269
+ };
3270
+ const handleShippingNext = async () => {
3271
+ setRatesLoading(true);
3272
+ setCheckoutState("rates");
3273
+ try {
3274
+ const rates = await fetchShippingRates(shippingAddress, [
3275
+ { offering_id: product.id, quantity }
3276
+ ]);
3277
+ setShippingRates(rates);
3278
+ if (rates.length) setSelectedShippingRate(rates[0]);
3279
+ } catch {
3280
+ setShippingRates([]);
3281
+ } finally {
3282
+ setRatesLoading(false);
3283
+ }
3284
+ };
3285
+ const handleRatesNext = () => {
3286
+ if (!isFree) {
3287
+ setCheckoutState("payment");
3288
+ }
3289
+ };
3290
+ const handlePaymentSuccess = (result) => {
3291
+ setCheckoutResult(result);
3292
+ setCheckoutState("success");
3293
+ analytics?.trackEvent({
3294
+ name: "purchase",
3295
+ properties: {
3296
+ offering_id: product.id,
3297
+ variant_id: selectedVariant?.id,
3298
+ quantity,
3299
+ price: currentPrice,
3300
+ name: product.name,
3301
+ sale_id: result.sale_id
3302
+ }
3303
+ });
3304
+ onCheckoutSuccess?.(result);
3305
+ };
3306
+ const handlePaymentError = (error) => {
3307
+ setCheckoutError(error);
3308
+ onCheckoutError?.(error);
3309
+ };
3310
+ const handleCloseCheckout = () => {
3311
+ setCheckoutState("browsing");
3312
+ if (checkoutResult) {
3313
+ setCustomer({ name: "", email: "", phone: "" });
3314
+ setShippingAddress({ street1: "", city: "", state: "", zip: "", country: "US" });
3315
+ setShippingRates([]);
3316
+ setSelectedShippingRate(null);
3317
+ setCheckoutResult(null);
3318
+ }
3319
+ };
3320
+ const ctaLabel = useMemo(() => {
3321
+ if (isOutOfStock) return "Out of Stock";
3322
+ if (needsVariantSelection) return product.is_clothing ? "Select Size" : "Select Option";
3323
+ if (hasExternalUrl) return product.type === "event" ? "Get Tickets" : "Learn More";
3324
+ if (isEvent) return isFree ? "Register Free" : "Get Tickets";
3325
+ if (isService) return "Book Now";
3326
+ return isFree ? "Get It Free" : "Buy Now";
3327
+ }, [isOutOfStock, needsVariantSelection, hasExternalUrl, isEvent, isService, isFree, product.is_clothing]);
3328
+ return /* @__PURE__ */ jsxs("div", { className: `skc-detail ${className}`, style: customStyle, children: [
3329
+ /* @__PURE__ */ jsx("style", { children: STYLE_BLOCK }),
3330
+ /* @__PURE__ */ jsxs("div", { className: `skc-detail-layout${layout === "stacked" ? " skc-stacked" : ""}`, children: [
3331
+ showGallery && allImages.length > 0 && /* @__PURE__ */ jsx(
3332
+ ProductGallery,
3333
+ {
3334
+ images: allImages,
3335
+ productName: product.name,
3336
+ selectedIndex: selectedImage,
3337
+ onSelect: setSelectedImage
3338
+ }
3339
+ ),
3340
+ /* @__PURE__ */ jsxs("div", { children: [
3341
+ product.category && /* @__PURE__ */ jsx(
3342
+ "div",
3343
+ {
3344
+ style: {
3345
+ fontSize: "0.75rem",
3346
+ fontWeight: 600,
3347
+ color: "var(--commerce-accent)",
3348
+ textTransform: "uppercase",
3349
+ letterSpacing: "0.05em",
3350
+ marginBottom: "0.375rem"
3351
+ },
3352
+ children: product.category.name
3353
+ }
3354
+ ),
3355
+ /* @__PURE__ */ jsx(
3356
+ "h1",
3357
+ {
3358
+ style: {
3359
+ margin: 0,
3360
+ fontSize: "1.875rem",
3361
+ fontWeight: 700,
3362
+ color: "var(--commerce-text)",
3363
+ lineHeight: 1.2
3364
+ },
3365
+ children: product.name
3366
+ }
3367
+ ),
3368
+ product.short_description && /* @__PURE__ */ jsx(
3369
+ "p",
3370
+ {
3371
+ style: {
3372
+ marginTop: "0.625rem",
3373
+ marginBottom: 0,
3374
+ fontSize: "1rem",
3375
+ color: "var(--commerce-text-secondary)",
3376
+ lineHeight: 1.6
3377
+ },
3378
+ children: product.short_description
1478
3379
  }
1479
- }
1480
- ) }),
1481
- allImages.length > 1 && /* @__PURE__ */ jsx("div", { className: "site-kit-product-detail__thumbnails", style: {
1482
- display: "flex",
1483
- gap: "0.5rem",
1484
- marginTop: "0.75rem",
1485
- overflowX: "auto"
1486
- }, children: allImages.map((img, idx) => /* @__PURE__ */ jsx(
1487
- "button",
1488
- {
1489
- onClick: () => setSelectedImage(idx),
1490
- style: {
1491
- flex: "0 0 auto",
1492
- width: "64px",
1493
- height: "64px",
1494
- borderRadius: "8px",
1495
- overflow: "hidden",
1496
- border: idx === selectedImage ? "2px solid #2563eb" : "2px solid transparent",
1497
- padding: 0,
1498
- cursor: "pointer",
1499
- backgroundColor: "#f9fafb"
1500
- },
1501
- children: /* @__PURE__ */ jsx(
1502
- "img",
1503
- {
1504
- src: img,
1505
- alt: `${product.name} ${idx + 1}`,
1506
- style: {
1507
- width: "100%",
1508
- height: "100%",
1509
- objectFit: "cover"
1510
- }
1511
- }
1512
- )
1513
- },
1514
- idx
1515
- )) })
1516
- ] }),
1517
- /* @__PURE__ */ jsxs("div", { className: "site-kit-product-detail__info", children: [
1518
- product.category && /* @__PURE__ */ jsx("div", { className: "site-kit-product-detail__category", style: {
1519
- fontSize: "0.875rem",
1520
- color: "#6b7280",
1521
- marginBottom: "0.5rem",
1522
- textTransform: "uppercase",
1523
- letterSpacing: "0.05em"
1524
- }, children: product.category.name }),
1525
- /* @__PURE__ */ jsx("h1", { className: "site-kit-product-detail__title", style: {
1526
- margin: 0,
1527
- fontSize: "2rem",
1528
- fontWeight: 700,
1529
- color: "#111827",
1530
- lineHeight: 1.2
1531
- }, children: product.name }),
1532
- product.short_description && /* @__PURE__ */ jsx("p", { className: "site-kit-product-detail__short-description", style: {
1533
- marginTop: "0.75rem",
1534
- fontSize: "1rem",
1535
- color: "#4b5563",
1536
- lineHeight: 1.6
1537
- }, children: product.short_description }),
1538
- product.price_is_public && currentPrice !== void 0 && /* @__PURE__ */ jsxs("div", { className: "site-kit-product-detail__price", style: {
1539
- marginTop: "1rem",
1540
- display: "flex",
1541
- alignItems: "baseline",
1542
- gap: "0.75rem"
1543
- }, children: [
1544
- /* @__PURE__ */ jsx("span", { style: {
1545
- fontSize: "1.75rem",
1546
- fontWeight: 700,
1547
- color: hasDiscount ? "#dc2626" : "#111827"
1548
- }, children: formatPrice(currentPrice, product.currency) }),
1549
- hasDiscount && /* @__PURE__ */ jsx("span", { style: {
1550
- fontSize: "1.25rem",
1551
- color: "#9ca3af",
1552
- textDecoration: "line-through"
1553
- }, children: formatPrice(compareAtPrice, product.currency) })
1554
- ] }),
1555
- product.track_inventory && /* @__PURE__ */ jsx("div", { className: "site-kit-product-detail__stock", style: {
1556
- marginTop: "0.75rem",
1557
- fontSize: "0.875rem",
1558
- fontWeight: 500
1559
- }, children: isOutOfStock ? /* @__PURE__ */ jsx("span", { style: { color: "#dc2626" }, children: "Out of Stock" }) : isLowStock ? /* @__PURE__ */ jsxs("span", { style: { color: "#f59e0b" }, children: [
1560
- "Only ",
1561
- inventoryCount,
1562
- " left!"
1563
- ] }) : /* @__PURE__ */ jsx("span", { style: { color: "#10b981" }, children: "In Stock" }) }),
1564
- showVariants && product.variants && (product.variants.length > 1 || product.is_clothing) && /* @__PURE__ */ jsxs("div", { className: "site-kit-product-detail__variants", style: { marginTop: "1.5rem" }, children: [
1565
- /* @__PURE__ */ jsx("label", { style: {
1566
- display: "block",
1567
- fontSize: "0.875rem",
1568
- fontWeight: 600,
1569
- color: "#374151",
1570
- marginBottom: "0.5rem"
1571
- }, children: product.is_clothing ? "Size" : "Options" }),
1572
- /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: "0.5rem" }, children: product.variants.map((variant) => {
1573
- const variantOutOfStock = variant.track_inventory !== false && (variant.inventory_count ?? 0) <= 0;
1574
- return /* @__PURE__ */ jsxs(
3380
+ ),
3381
+ product.price_is_public && currentPrice != null && /* @__PURE__ */ jsxs(
3382
+ "div",
3383
+ {
3384
+ style: {
3385
+ marginTop: "1rem",
3386
+ display: "flex",
3387
+ alignItems: "center",
3388
+ gap: "0.75rem",
3389
+ flexWrap: "wrap"
3390
+ },
3391
+ children: [
3392
+ /* @__PURE__ */ jsx(
3393
+ "span",
3394
+ {
3395
+ style: {
3396
+ fontSize: "1.75rem",
3397
+ fontWeight: 700,
3398
+ color: hasDiscount ? "var(--commerce-danger)" : "var(--commerce-text)"
3399
+ },
3400
+ children: formatPrice(currentPrice, product.currency)
3401
+ }
3402
+ ),
3403
+ hasDiscount && /* @__PURE__ */ jsxs(Fragment, { children: [
3404
+ /* @__PURE__ */ jsx(
3405
+ "span",
3406
+ {
3407
+ style: {
3408
+ fontSize: "1.125rem",
3409
+ color: "var(--commerce-text-muted)",
3410
+ textDecoration: "line-through"
3411
+ },
3412
+ children: formatPrice(compareAtPrice, product.currency)
3413
+ }
3414
+ ),
3415
+ /* @__PURE__ */ jsxs(
3416
+ "span",
3417
+ {
3418
+ style: {
3419
+ fontSize: "0.75rem",
3420
+ fontWeight: 700,
3421
+ color: "var(--commerce-accent-text)",
3422
+ background: "var(--commerce-danger)",
3423
+ padding: "2px 8px",
3424
+ borderRadius: 4
3425
+ },
3426
+ children: [
3427
+ "-",
3428
+ discountPercent,
3429
+ "%"
3430
+ ]
3431
+ }
3432
+ )
3433
+ ] }),
3434
+ product.billing_period && /* @__PURE__ */ jsxs("span", { style: { fontSize: "0.875rem", color: "var(--commerce-text-muted)" }, children: [
3435
+ "/ ",
3436
+ product.billing_period
3437
+ ] })
3438
+ ]
3439
+ }
3440
+ ),
3441
+ product.track_inventory && /* @__PURE__ */ jsx("div", { style: { marginTop: "0.75rem", display: "flex", alignItems: "center", gap: 6 }, children: isOutOfStock ? /* @__PURE__ */ jsxs(
3442
+ "span",
3443
+ {
3444
+ style: {
3445
+ fontSize: "0.8125rem",
3446
+ fontWeight: 600,
3447
+ color: "var(--commerce-danger)",
3448
+ display: "flex",
3449
+ alignItems: "center",
3450
+ gap: 4
3451
+ },
3452
+ children: [
3453
+ /* @__PURE__ */ jsx(IconAlert, {}),
3454
+ " Out of Stock"
3455
+ ]
3456
+ }
3457
+ ) : isLowStock ? /* @__PURE__ */ jsxs(
3458
+ "span",
3459
+ {
3460
+ className: "skc-pulse",
3461
+ style: {
3462
+ fontSize: "0.8125rem",
3463
+ fontWeight: 600,
3464
+ color: "var(--commerce-warning)",
3465
+ display: "flex",
3466
+ alignItems: "center",
3467
+ gap: 4
3468
+ },
3469
+ children: [
3470
+ /* @__PURE__ */ jsx(IconAlert, {}),
3471
+ " Only ",
3472
+ inventoryCount,
3473
+ " left!"
3474
+ ]
3475
+ }
3476
+ ) : /* @__PURE__ */ jsxs(
3477
+ "span",
3478
+ {
3479
+ style: {
3480
+ fontSize: "0.8125rem",
3481
+ fontWeight: 500,
3482
+ color: "var(--commerce-success)",
3483
+ display: "flex",
3484
+ alignItems: "center",
3485
+ gap: 4
3486
+ },
3487
+ children: [
3488
+ /* @__PURE__ */ jsx(IconCheck, {}),
3489
+ " In Stock"
3490
+ ]
3491
+ }
3492
+ ) }),
3493
+ isEvent && schedule && /* @__PURE__ */ jsx(EventInfoBlock, { product, schedule }),
3494
+ showVariants && product.variants && (product.variants.length > 1 || product.is_clothing) && /* @__PURE__ */ jsx(
3495
+ VariantSelector,
3496
+ {
3497
+ variants: product.variants,
3498
+ selected: selectedVariant,
3499
+ isClothing: !!product.is_clothing,
3500
+ showInventory,
3501
+ onSelect: handleVariantChange
3502
+ }
3503
+ ),
3504
+ showSizeChart && product.is_clothing && product.size_chart && /* @__PURE__ */ jsx("div", { style: { marginTop: "0.625rem" }, children: /* @__PURE__ */ jsx(
3505
+ SizeChart,
3506
+ {
3507
+ chart: product.size_chart,
3508
+ selectedSize: selectedVariant?.options?.["Size"]
3509
+ }
3510
+ ) }),
3511
+ showQuantity && !isOutOfStock && !isEvent && !isService && /* @__PURE__ */ jsx(
3512
+ QuantitySelector,
3513
+ {
3514
+ quantity,
3515
+ max: product.track_inventory && inventoryCount != null ? inventoryCount : 99,
3516
+ onChange: setQuantity
3517
+ }
3518
+ ),
3519
+ /* @__PURE__ */ jsxs("div", { style: { marginTop: "1.5rem", display: "flex", flexDirection: "column", gap: "0.625rem" }, children: [
3520
+ /* @__PURE__ */ jsxs(
1575
3521
  "button",
1576
3522
  {
1577
- onClick: () => !variantOutOfStock && handleVariantChange(variant),
1578
- disabled: variantOutOfStock,
1579
- style: {
1580
- padding: "0.5rem 1rem",
1581
- borderRadius: "8px",
1582
- border: selectedVariant?.id === variant.id ? "2px solid #2563eb" : "1px solid #d1d5db",
1583
- backgroundColor: selectedVariant?.id === variant.id ? "#eff6ff" : "white",
1584
- color: variantOutOfStock ? "#9ca3af" : "#374151",
1585
- fontSize: "0.875rem",
1586
- fontWeight: 500,
1587
- cursor: variantOutOfStock ? "not-allowed" : "pointer",
1588
- opacity: variantOutOfStock ? 0.6 : 1,
1589
- transition: "all 0.15s ease"
1590
- },
3523
+ ref: buyButtonRef,
3524
+ className: "skc-btn-primary",
3525
+ onClick: handleBuyNow,
3526
+ disabled: isOutOfStock || needsVariantSelection,
3527
+ "aria-label": ctaLabel,
1591
3528
  children: [
1592
- variant.options?.Size || variant.name,
1593
- variantOutOfStock && " (Out of stock)"
3529
+ hasExternalUrl && /* @__PURE__ */ jsx(IconExternalLink, {}),
3530
+ ctaLabel
1594
3531
  ]
1595
- },
1596
- variant.id
1597
- );
1598
- }) })
1599
- ] }),
1600
- product.is_clothing && product.size_chart && /* @__PURE__ */ jsx("div", { style: { marginTop: "0.75rem" }, children: /* @__PURE__ */ jsx(
1601
- SizeChart,
1602
- {
1603
- chart: product.size_chart,
1604
- selectedSize: selectedVariant?.options?.["Size"]
1605
- }
1606
- ) }),
1607
- showQuantity && !isOutOfStock && /* @__PURE__ */ jsxs("div", { className: "site-kit-product-detail__quantity", style: { marginTop: "1.5rem" }, children: [
1608
- /* @__PURE__ */ jsx("label", { style: {
1609
- display: "block",
1610
- fontSize: "0.875rem",
1611
- fontWeight: 600,
1612
- color: "#374151",
1613
- marginBottom: "0.5rem"
1614
- }, children: "Quantity" }),
1615
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
1616
- /* @__PURE__ */ jsx(
1617
- "button",
1618
- {
1619
- onClick: () => setQuantity(Math.max(1, quantity - 1)),
1620
- disabled: quantity <= 1,
1621
- style: {
1622
- width: "40px",
1623
- height: "40px",
1624
- borderRadius: "8px",
1625
- border: "1px solid #d1d5db",
1626
- backgroundColor: "white",
1627
- fontSize: "1.25rem",
1628
- cursor: quantity <= 1 ? "not-allowed" : "pointer",
1629
- opacity: quantity <= 1 ? 0.5 : 1
1630
- },
1631
- children: "\u2212"
1632
- }
1633
- ),
1634
- /* @__PURE__ */ jsx(
1635
- "input",
1636
- {
1637
- type: "number",
1638
- min: "1",
1639
- max: inventoryCount ?? 99,
1640
- value: quantity,
1641
- onChange: (e) => setQuantity(Math.max(1, parseInt(e.target.value) || 1)),
1642
- style: {
1643
- width: "60px",
1644
- height: "40px",
1645
- textAlign: "center",
1646
- borderRadius: "8px",
1647
- border: "1px solid #d1d5db",
1648
- fontSize: "1rem"
1649
- }
1650
3532
  }
1651
3533
  ),
1652
- /* @__PURE__ */ jsx(
3534
+ onAddToCart && !isEvent && !isService && !hasExternalUrl && /* @__PURE__ */ jsx(
1653
3535
  "button",
1654
3536
  {
1655
- onClick: () => setQuantity(quantity + 1),
1656
- disabled: product.track_inventory && inventoryCount !== void 0 && quantity >= inventoryCount,
1657
- style: {
1658
- width: "40px",
1659
- height: "40px",
1660
- borderRadius: "8px",
1661
- border: "1px solid #d1d5db",
1662
- backgroundColor: "white",
1663
- fontSize: "1.25rem",
1664
- cursor: "pointer"
1665
- },
1666
- children: "+"
3537
+ className: "skc-btn-secondary",
3538
+ onClick: handleAddToCart,
3539
+ disabled: isOutOfStock || needsVariantSelection,
3540
+ children: "Add to Cart"
1667
3541
  }
1668
3542
  )
1669
- ] })
1670
- ] }),
1671
- /* @__PURE__ */ jsxs("div", { className: "site-kit-product-detail__actions", style: {
1672
- marginTop: "1.5rem",
1673
- display: "flex",
1674
- flexDirection: "column",
1675
- gap: "0.75rem"
1676
- }, children: [
1677
- showBuyNow && /* @__PURE__ */ jsx(
1678
- "button",
3543
+ ] }),
3544
+ checkoutError && checkoutState === "browsing" && /* @__PURE__ */ jsxs(
3545
+ "div",
1679
3546
  {
1680
- onClick: handleBuyNow,
1681
- disabled: isOutOfStock || checkingOut || needsVariantSelection,
1682
- className: "site-kit-product-detail__buy-now",
1683
3547
  style: {
1684
- padding: "1rem 2rem",
1685
- borderRadius: "8px",
1686
- border: "none",
1687
- backgroundColor: isOutOfStock ? "#d1d5db" : "#2563eb",
1688
- color: "white",
1689
- fontSize: "1rem",
1690
- fontWeight: 600,
1691
- cursor: isOutOfStock ? "not-allowed" : "pointer",
1692
- transition: "all 0.15s ease"
3548
+ marginTop: "0.75rem",
3549
+ padding: "0.75rem",
3550
+ background: "#fef2f2",
3551
+ border: "1px solid #fecaca",
3552
+ borderRadius: "var(--commerce-radius-sm)",
3553
+ color: "var(--commerce-danger)",
3554
+ fontSize: "0.875rem",
3555
+ display: "flex",
3556
+ alignItems: "flex-start",
3557
+ gap: 8
1693
3558
  },
1694
- children: checkingOut ? "Processing..." : needsVariantSelection ? "Select Size" : isOutOfStock ? "Out of Stock" : "Buy Now"
3559
+ children: [
3560
+ /* @__PURE__ */ jsx(IconAlert, {}),
3561
+ /* @__PURE__ */ jsx("span", { children: checkoutError })
3562
+ ]
1695
3563
  }
1696
3564
  ),
1697
- showAddToCart && onAddToCart && /* @__PURE__ */ jsx(
1698
- "button",
3565
+ showTrustBadges && /* @__PURE__ */ jsx(TrustBadges, { badges: trustBadges }),
3566
+ /* @__PURE__ */ jsx(
3567
+ ProductTabs,
1699
3568
  {
1700
- onClick: handleAddToCart,
1701
- disabled: isOutOfStock || needsVariantSelection,
1702
- className: "site-kit-product-detail__add-to-cart",
1703
- style: {
1704
- padding: "1rem 2rem",
1705
- borderRadius: "8px",
1706
- border: "2px solid #2563eb",
1707
- backgroundColor: "white",
1708
- color: "#2563eb",
1709
- fontSize: "1rem",
1710
- fontWeight: 600,
1711
- cursor: isOutOfStock || needsVariantSelection ? "not-allowed" : "pointer",
1712
- transition: "all 0.15s ease"
1713
- },
1714
- children: needsVariantSelection ? "Select Size" : isOutOfStock ? "Out of Stock" : "Add to Cart"
3569
+ features: product.features,
3570
+ specifications: product.specifications,
3571
+ description: product.long_description,
3572
+ showFeatures,
3573
+ showSpecifications,
3574
+ showDescription
1715
3575
  }
1716
3576
  )
1717
- ] }),
1718
- showFeatures && product.features && product.features.length > 0 && /* @__PURE__ */ jsxs("div", { className: "site-kit-product-detail__features", style: { marginTop: "2rem" }, children: [
1719
- /* @__PURE__ */ jsx("h3", { style: {
1720
- fontSize: "1rem",
1721
- fontWeight: 600,
1722
- color: "#111827",
1723
- marginBottom: "0.75rem"
1724
- }, children: "Features" }),
1725
- /* @__PURE__ */ jsx("ul", { style: {
1726
- margin: 0,
1727
- paddingLeft: "1.25rem",
1728
- display: "flex",
1729
- flexDirection: "column",
1730
- gap: "0.5rem"
1731
- }, children: product.features.map((feature, idx) => /* @__PURE__ */ jsx("li", { style: { color: "#4b5563", fontSize: "0.9375rem" }, children: feature }, idx)) })
1732
- ] }),
1733
- showSpecifications && product.specifications && Object.keys(product.specifications).length > 0 && /* @__PURE__ */ jsxs("div", { className: "site-kit-product-detail__specifications", style: { marginTop: "2rem" }, children: [
1734
- /* @__PURE__ */ jsx("h3", { style: {
1735
- fontSize: "1rem",
1736
- fontWeight: 600,
1737
- color: "#111827",
1738
- marginBottom: "0.75rem"
1739
- }, children: "Specifications" }),
1740
- /* @__PURE__ */ jsx("dl", { style: {
1741
- margin: 0,
1742
- display: "grid",
1743
- gridTemplateColumns: "auto 1fr",
1744
- gap: "0.5rem 1rem"
1745
- }, children: Object.entries(product.specifications).map(([key, value]) => /* @__PURE__ */ jsxs(React5.Fragment, { children: [
1746
- /* @__PURE__ */ jsx("dt", { style: { color: "#6b7280", fontSize: "0.875rem" }, children: key }),
1747
- /* @__PURE__ */ jsx("dd", { style: { margin: 0, color: "#111827", fontSize: "0.875rem" }, children: value })
1748
- ] }, key)) })
1749
3577
  ] })
1750
3578
  ] }),
1751
- product.long_description && /* @__PURE__ */ jsxs(
3579
+ showStickyBar && checkoutState === "browsing" && !isOutOfStock && !needsVariantSelection && /* @__PURE__ */ jsxs("div", { className: "skc-sticky-bar", children: [
3580
+ /* @__PURE__ */ jsxs("div", { children: [
3581
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 600, fontSize: "0.875rem", color: "var(--commerce-text)", lineHeight: 1.2 }, children: product.name }),
3582
+ product.price_is_public && currentPrice != null && /* @__PURE__ */ jsx("div", { style: { fontWeight: 700, fontSize: "1rem", color: hasDiscount ? "var(--commerce-danger)" : "var(--commerce-text)" }, children: formatPrice(currentPrice, product.currency) })
3583
+ ] }),
3584
+ /* @__PURE__ */ jsx(
3585
+ "button",
3586
+ {
3587
+ className: "skc-btn-primary",
3588
+ onClick: handleBuyNow,
3589
+ style: { width: "auto", padding: "0.625rem 1.5rem", fontSize: "0.875rem" },
3590
+ children: ctaLabel
3591
+ }
3592
+ )
3593
+ ] }),
3594
+ checkoutState !== "browsing" && /* @__PURE__ */ jsx(
1752
3595
  "div",
1753
3596
  {
1754
- className: "site-kit-product-detail__description",
1755
- style: {
1756
- gridColumn: "1 / -1",
1757
- marginTop: "2rem",
1758
- padding: "2rem",
1759
- backgroundColor: "#f9fafb",
1760
- borderRadius: "12px"
3597
+ className: "skc-checkout-overlay",
3598
+ onClick: (e) => {
3599
+ if (e.target === e.currentTarget && checkoutState !== "processing") {
3600
+ handleCloseCheckout();
3601
+ }
1761
3602
  },
1762
- children: [
1763
- /* @__PURE__ */ jsx("h2", { style: {
1764
- fontSize: "1.25rem",
1765
- fontWeight: 600,
1766
- color: "#111827",
1767
- marginBottom: "1rem"
1768
- }, children: "About This Product" }),
1769
- /* @__PURE__ */ jsx(
1770
- "div",
1771
- {
1772
- style: { color: "#4b5563", lineHeight: 1.7 },
1773
- dangerouslySetInnerHTML: { __html: product.long_description }
1774
- }
1775
- )
1776
- ]
3603
+ role: "dialog",
3604
+ "aria-modal": "true",
3605
+ "aria-label": "Checkout",
3606
+ children: /* @__PURE__ */ jsxs(
3607
+ "div",
3608
+ {
3609
+ className: "skc-checkout-panel",
3610
+ onClick: (e) => e.stopPropagation(),
3611
+ children: [
3612
+ checkoutState !== "processing" && /* @__PURE__ */ jsx(
3613
+ "button",
3614
+ {
3615
+ onClick: handleCloseCheckout,
3616
+ "aria-label": "Close checkout",
3617
+ style: {
3618
+ position: "absolute",
3619
+ top: 12,
3620
+ right: 12,
3621
+ width: 32,
3622
+ height: 32,
3623
+ borderRadius: "50%",
3624
+ border: "none",
3625
+ background: "var(--commerce-surface)",
3626
+ cursor: "pointer",
3627
+ display: "flex",
3628
+ alignItems: "center",
3629
+ justifyContent: "center",
3630
+ zIndex: 10,
3631
+ color: "var(--commerce-text-secondary)"
3632
+ },
3633
+ children: /* @__PURE__ */ jsx(IconX, {})
3634
+ }
3635
+ ),
3636
+ /* @__PURE__ */ jsxs("div", { style: { padding: "1.5rem" }, children: [
3637
+ checkoutState !== "success" && checkoutState !== "processing" && /* @__PURE__ */ jsx(CheckoutStepIndicator, { current: checkoutState, steps: checkoutSteps }),
3638
+ checkoutState === "processing" && /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: "3rem 0" }, children: [
3639
+ /* @__PURE__ */ jsx(
3640
+ "div",
3641
+ {
3642
+ style: {
3643
+ width: 48,
3644
+ height: 48,
3645
+ border: "3px solid var(--commerce-border)",
3646
+ borderTopColor: "var(--commerce-accent)",
3647
+ borderRadius: "50%",
3648
+ animation: "skc-spin 0.8s linear infinite",
3649
+ margin: "0 auto 1.5rem"
3650
+ }
3651
+ }
3652
+ ),
3653
+ /* @__PURE__ */ jsx("p", { style: { color: "var(--commerce-text-secondary)", fontSize: "0.9375rem", margin: 0 }, children: "Processing your order..." })
3654
+ ] }),
3655
+ checkoutState === "success" && checkoutResult && /* @__PURE__ */ jsx(SuccessStep, { result: checkoutResult, product, onClose: handleCloseCheckout }),
3656
+ checkoutState === "customer-info" && /* @__PURE__ */ jsx(
3657
+ CustomerInfoStep,
3658
+ {
3659
+ customer,
3660
+ onChange: setCustomer,
3661
+ onNext: handleCustomerNext,
3662
+ onBack: handleCloseCheckout
3663
+ }
3664
+ ),
3665
+ checkoutState === "shipping" && /* @__PURE__ */ jsx(
3666
+ ShippingAddressStep,
3667
+ {
3668
+ address: shippingAddress,
3669
+ onChange: setShippingAddress,
3670
+ onNext: handleShippingNext,
3671
+ onBack: handleCheckoutBack,
3672
+ loading: ratesLoading
3673
+ }
3674
+ ),
3675
+ checkoutState === "rates" && /* @__PURE__ */ jsx(
3676
+ ShippingRatesStep,
3677
+ {
3678
+ rates: shippingRates,
3679
+ selected: selectedShippingRate,
3680
+ onSelect: setSelectedShippingRate,
3681
+ onNext: handleRatesNext,
3682
+ onBack: handleCheckoutBack,
3683
+ loading: ratesLoading,
3684
+ currency: product.currency
3685
+ }
3686
+ ),
3687
+ checkoutState === "payment" && /* @__PURE__ */ jsx(
3688
+ PaymentStep,
3689
+ {
3690
+ processor: processorConfig?.processor || null,
3691
+ config: processorConfig,
3692
+ product,
3693
+ variant: selectedVariant,
3694
+ quantity,
3695
+ customer,
3696
+ shippingRate: selectedShippingRate,
3697
+ shippingAddress: needsShipping ? shippingAddress : null,
3698
+ needsShipping,
3699
+ onBack: handleCheckoutBack,
3700
+ onSuccess: handlePaymentSuccess,
3701
+ onError: handlePaymentError,
3702
+ onProcessing: (p) => {
3703
+ if (p) setCheckoutState("processing");
3704
+ },
3705
+ successUrl,
3706
+ cancelUrl
3707
+ }
3708
+ ),
3709
+ checkoutError && checkoutState !== "payment" && checkoutState !== "processing" && checkoutState !== "success" && /* @__PURE__ */ jsxs(
3710
+ "div",
3711
+ {
3712
+ style: {
3713
+ marginTop: "0.75rem",
3714
+ padding: "0.75rem",
3715
+ background: "#fef2f2",
3716
+ border: "1px solid #fecaca",
3717
+ borderRadius: "var(--commerce-radius-sm)",
3718
+ color: "var(--commerce-danger)",
3719
+ fontSize: "0.875rem",
3720
+ display: "flex",
3721
+ alignItems: "flex-start",
3722
+ gap: 8
3723
+ },
3724
+ children: [
3725
+ /* @__PURE__ */ jsx(IconAlert, {}),
3726
+ /* @__PURE__ */ jsx("span", { children: checkoutError })
3727
+ ]
3728
+ }
3729
+ )
3730
+ ] })
3731
+ ]
3732
+ }
3733
+ )
1777
3734
  }
1778
3735
  )
1779
3736
  ] });
@@ -2188,8 +4145,6 @@ function ProductPage({
2188
4145
  ProductDetail,
2189
4146
  {
2190
4147
  product,
2191
- showAddToCart: !!onAddToCart,
2192
- showBuyNow: true,
2193
4148
  showQuantity: true,
2194
4149
  showVariants: true,
2195
4150
  showGallery: true,
@@ -3400,7 +5355,7 @@ function CalendarView({
3400
5355
  }, children: "Loading..." })
3401
5356
  ] });
3402
5357
  }
3403
- function loadSquareSDK(environment) {
5358
+ function loadSquareSDK2(environment) {
3404
5359
  return new Promise((resolve, reject) => {
3405
5360
  if (typeof window === "undefined") return reject(new Error("No window"));
3406
5361
  if (window.Square) return resolve();
@@ -3447,7 +5402,7 @@ function EventModal({
3447
5402
  if (config?.processor) setProcessor(config.processor);
3448
5403
  if (config?.processor === "square" && config.squareAppId && config.squareLocationId) {
3449
5404
  try {
3450
- await loadSquareSDK(config.squareEnvironment || "production");
5405
+ await loadSquareSDK2(config.squareEnvironment || "production");
3451
5406
  const Square = window.Square;
3452
5407
  const payments = Square.payments(config.squareAppId, config.squareLocationId);
3453
5408
  const card = await payments.card({
@@ -4110,8 +6065,8 @@ function EventsWidget({
4110
6065
  return;
4111
6066
  }
4112
6067
  async function loadEvents() {
4113
- const apiUrl = getApiUrl();
4114
- const apiKey = getApiKey();
6068
+ const apiUrl = getApiUrl2();
6069
+ const apiKey = getApiKey2();
4115
6070
  if (!apiKey) {
4116
6071
  if (retryCount < 3) {
4117
6072
  setTimeout(() => setRetryCount((c) => c + 1), 100);
@@ -4586,19 +6541,19 @@ function EventsWidget({
4586
6541
  )
4587
6542
  ] });
4588
6543
  }
4589
- function getApiUrl() {
6544
+ function getApiUrl2() {
4590
6545
  if (typeof window !== "undefined") {
4591
6546
  return window.__SITE_KIT_API_URL__ || "https://api.sonor.io";
4592
6547
  }
4593
6548
  return "https://api.sonor.io";
4594
6549
  }
4595
- function getApiKey() {
6550
+ function getApiKey2() {
4596
6551
  if (typeof window !== "undefined") {
4597
6552
  return window.__SITE_KIT_API_KEY__ || "";
4598
6553
  }
4599
6554
  return "";
4600
6555
  }
4601
6556
 
4602
- export { CalendarView, CheckoutForm, EventCalendar, EventEmbed, EventModal, EventTile, EventsWidget, OfferingCard, OfferingList, ProductDetail, ProductEmbed, ProductGrid, ProductPage, RegistrationForm, SizeChart, UpcomingEvents, createCheckoutSession, fetchActiveProcessor, fetchCategories, fetchLatestOffering, fetchNextEvent, fetchOffering, fetchOfferings, fetchProcessorConfig, fetchProductBySlug, fetchProducts, fetchProductsPublic, fetchServices, fetchShippingRates, fetchUpcomingEvents, formatDate, formatDateRange, formatDateTime, formatPrice, formatTime, getOfferingUrl, getRelativeTimeUntil, getSpotsRemaining, isEventSoldOut, registerForEvent, useEventModal, validateAddress };
4603
- //# sourceMappingURL=chunk-IZZ7XJYN.mjs.map
4604
- //# sourceMappingURL=chunk-IZZ7XJYN.mjs.map
6557
+ export { CalendarView, CheckoutForm, EventCalendar, EventEmbed, EventModal, EventTile, EventsWidget, OfferingCard, OfferingList, ProductDetail, ProductEmbed, ProductGrid, ProductPage, RegistrationForm, SizeChart, UpcomingEvents, createCheckoutSession, createPaymentIntent, fetchActiveProcessor, fetchCategories, fetchLatestOffering, fetchNextEvent, fetchOffering, fetchOfferings, fetchProcessorConfig, fetchProductBySlug, fetchProducts, fetchProductsPublic, fetchServices, fetchShippingRates, fetchUpcomingEvents, formatDate, formatDateRange, formatDateTime, formatPrice, formatTime, getOfferingUrl, getRelativeTimeUntil, getSpotsRemaining, isEventSoldOut, registerForEvent, useEventModal, validateAddress };
6558
+ //# sourceMappingURL=chunk-ULAQCW4X.mjs.map
6559
+ //# sourceMappingURL=chunk-ULAQCW4X.mjs.map