@huskel/sdk 0.4.7 → 0.4.8

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.
package/dist/index.mjs CHANGED
@@ -56,6 +56,12 @@ var HuskelAPI = class {
56
56
  if (sessionId) {
57
57
  headers["X-Huskel-Session-Id"] = sessionId;
58
58
  }
59
+ if (typeof window !== "undefined") {
60
+ const phone = localStorage.getItem("huskel_user_phone");
61
+ if (phone) {
62
+ headers["X-Huskel-Shopper-Phone"] = phone;
63
+ }
64
+ }
59
65
  const res = await fetch(url, {
60
66
  method: "POST",
61
67
  headers,
@@ -134,6 +140,12 @@ var HuskelAPI = class {
134
140
  if (shopperId) headers["X-Huskel-Shopper-Id"] = shopperId;
135
141
  const sessionId = (_b = this.getSessionId) == null ? void 0 : _b.call(this);
136
142
  if (sessionId) headers["X-Huskel-Session-Id"] = sessionId;
143
+ if (typeof window !== "undefined") {
144
+ const phone = localStorage.getItem("huskel_user_phone");
145
+ if (phone) {
146
+ headers["X-Huskel-Shopper-Phone"] = phone;
147
+ }
148
+ }
137
149
  return headers;
138
150
  }
139
151
  async getCart() {
@@ -1619,7 +1631,12 @@ function ChatModal({
1619
1631
  const [selectedProduct, setSelectedProduct] = useState9(null);
1620
1632
  const bottomRef = useRef10(null);
1621
1633
  const textareaRef = useRef10(null);
1622
- const [phoneInput, setPhoneInput] = useState9("");
1634
+ const [phoneInput, setPhoneInput] = useState9(() => {
1635
+ if (typeof window !== "undefined") {
1636
+ return localStorage.getItem("huskel_user_phone") || "";
1637
+ }
1638
+ return "";
1639
+ });
1623
1640
  const [merchantRef, setMerchantRef] = useState9(null);
1624
1641
  const [paymentPhase, setPaymentPhase] = useState9("idle");
1625
1642
  const { status: pollStatus } = usePaymentPolling({
@@ -1647,7 +1664,10 @@ function ChatModal({
1647
1664
  const handlePhoneSubmit = async () => {
1648
1665
  if (!phoneInput.trim()) return;
1649
1666
  try {
1650
- const res = await client.api.initiatePayment(phoneInput);
1667
+ if (typeof window !== "undefined") {
1668
+ localStorage.setItem("huskel_user_phone", phoneInput.trim());
1669
+ }
1670
+ const res = await client.api.initiatePayment(phoneInput.trim());
1651
1671
  setMerchantRef(res.merchantReference);
1652
1672
  setPaymentPhase("awaiting");
1653
1673
  } catch (e) {
@@ -1737,7 +1757,7 @@ function ChatModal({
1737
1757
  /* @__PURE__ */ jsx6("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx6(SparkleIcon3, {}) }),
1738
1758
  /* @__PURE__ */ jsxs4("div", { className: "hsk-cb-ai-body", children: [
1739
1759
  /* @__PURE__ */ jsx6("div", { className: "hsk-cb-ai-text", children: renderMarkdown(msg.content) }),
1740
- isLast && sources.length > 0 && /* @__PURE__ */ jsx6(
1760
+ isLast && sources.length > 0 && (lastAction == null ? void 0 : lastAction.type) !== "request_phone" && (lastAction == null ? void 0 : lastAction.type) !== "awaiting_payment" && (lastAction == null ? void 0 : lastAction.type) !== "checkout" && /* @__PURE__ */ jsx6(
1741
1761
  SourcesCarousel,
1742
1762
  {
1743
1763
  sources,
@@ -1912,105 +1932,249 @@ import { createPortal as createPortal4 } from "react-dom";
1912
1932
  // src/components/CheckoutModal.tsx
1913
1933
  import { useState as useState10, useEffect as useEffect9 } from "react";
1914
1934
  import { createPortal as createPortal3 } from "react-dom";
1915
- import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
1935
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
1916
1936
  function CheckoutModal({
1917
1937
  onClose,
1918
1938
  theme,
1919
1939
  customStyles,
1920
1940
  hskThemeAttr
1921
1941
  }) {
1922
- var _a, _b, _c, _d;
1923
1942
  const { cart, loading: cartLoading } = useCart();
1924
1943
  const client = useHuskelContext();
1925
1944
  const [config, setConfig] = useState10(null);
1926
- const [loading, setLoading] = useState10(true);
1927
- const [checkingOut, setCheckingOut] = useState10(false);
1928
- const [paymentSuccess, setPaymentSuccess] = useState10(false);
1945
+ const [loadingConfig, setLoadingConfig] = useState10(true);
1946
+ const [phone, setPhone] = useState10(() => {
1947
+ if (typeof window !== "undefined") {
1948
+ return localStorage.getItem("huskel_user_phone") || "";
1949
+ }
1950
+ return "";
1951
+ });
1952
+ const [email, setEmail] = useState10(() => {
1953
+ if (typeof window !== "undefined") {
1954
+ return localStorage.getItem("huskel_user_email") || "";
1955
+ }
1956
+ return "";
1957
+ });
1958
+ const [firstName, setFirstName] = useState10(() => {
1959
+ if (typeof window !== "undefined") {
1960
+ return localStorage.getItem("huskel_user_firstname") || "";
1961
+ }
1962
+ return "";
1963
+ });
1964
+ const [lastName, setLastName] = useState10(() => {
1965
+ if (typeof window !== "undefined") {
1966
+ return localStorage.getItem("huskel_user_lastname") || "";
1967
+ }
1968
+ return "";
1969
+ });
1970
+ const [phase, setPhase] = useState10("idle");
1971
+ const [merchantRef, setMerchantRef] = useState10(null);
1972
+ const [payError, setPayError] = useState10(null);
1973
+ const {} = usePaymentPolling({
1974
+ client: client.api,
1975
+ merchantReference: merchantRef,
1976
+ onSuccess: () => {
1977
+ setPhase("done");
1978
+ setMerchantRef(null);
1979
+ },
1980
+ onFailure: () => {
1981
+ setPhase("failed");
1982
+ setPayError("Payment failed or timed out. Please try again.");
1983
+ setMerchantRef(null);
1984
+ }
1985
+ });
1929
1986
  useEffect9(() => {
1930
- client.api.getCheckoutConfig().then((res) => setConfig(res.payment_methods)).catch((e) => console.error("[Huskel] Failed to fetch checkout config", e)).finally(() => setLoading(false));
1987
+ client.api.getCheckoutConfig().then((res) => setConfig(res.payment_methods)).catch(() => {
1988
+ }).finally(() => setLoadingConfig(false));
1931
1989
  }, [client]);
1932
- const handlePay = async (method) => {
1933
- setCheckingOut(true);
1934
- setTimeout(async () => {
1935
- try {
1936
- const payload = await client.api.checkoutCart();
1937
- if (client.onCheckout) {
1938
- client.onCheckout(payload);
1939
- }
1940
- setPaymentSuccess(true);
1941
- setTimeout(() => {
1942
- onClose();
1943
- }, 3e3);
1944
- } catch (e) {
1945
- console.error("[Huskel] Checkout failed", e);
1946
- setCheckingOut(false);
1990
+ const hasPaymentMethods = config && Object.values(config).some((m) => m.enabled);
1991
+ const handlePay = async (e) => {
1992
+ e.preventDefault();
1993
+ if (!phone.trim()) {
1994
+ setPayError("Phone number is required.");
1995
+ return;
1996
+ }
1997
+ setPayError(null);
1998
+ setPhase("awaiting");
1999
+ try {
2000
+ if (typeof window !== "undefined") {
2001
+ localStorage.setItem("huskel_user_phone", phone.trim());
2002
+ localStorage.setItem("huskel_user_email", email.trim());
2003
+ localStorage.setItem("huskel_user_firstname", firstName.trim());
2004
+ localStorage.setItem("huskel_user_lastname", lastName.trim());
2005
+ }
2006
+ const res = await client.api.initiatePayment(phone.trim(), email, firstName, lastName);
2007
+ if (res == null ? void 0 : res.merchantReference) {
2008
+ setMerchantRef(res.merchantReference);
2009
+ } else {
2010
+ throw new Error("No merchant reference returned.");
1947
2011
  }
1948
- }, 1500);
2012
+ } catch (err) {
2013
+ setPhase("failed");
2014
+ setPayError(err.message || "Could not connect to payment processor.");
2015
+ }
1949
2016
  };
1950
- const hasPaymentMethods = config && Object.values(config).some((m) => m.enabled);
2017
+ const currency = (cart == null ? void 0 : cart.currency) || "KES";
2018
+ const total = (cart == null ? void 0 : cart.total) || 0;
2019
+ const backdropStyle = __spreadProps(__spreadValues({}, customStyles), { fontSize: "15px", fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif', zIndex: 999999 });
1951
2020
  return createPortal3(
1952
2021
  /* @__PURE__ */ jsx8(
1953
2022
  "div",
1954
2023
  {
1955
- className: "hsk-cart-backdrop",
1956
- style: __spreadProps(__spreadValues({}, customStyles), { zIndex: 999999 }),
2024
+ className: "hsk-checkout-backdrop-full",
2025
+ style: backdropStyle,
1957
2026
  "data-hsk-theme": hskThemeAttr,
1958
- onClick: onClose,
1959
2027
  children: /* @__PURE__ */ jsxs5(
1960
2028
  "div",
1961
2029
  {
1962
- className: "hsk-checkout-modal",
2030
+ className: "hsk-checkout-modal-full",
1963
2031
  style: customStyles,
1964
2032
  "data-hsk-theme": hskThemeAttr,
1965
- onClick: (e) => e.stopPropagation(),
1966
2033
  children: [
1967
- /* @__PURE__ */ jsxs5("div", { className: "hsk-checkout-header", children: [
1968
- /* @__PURE__ */ jsx8("h2", { children: "Secure Checkout" }),
1969
- /* @__PURE__ */ jsx8("button", { onClick: onClose, className: "hsk-close-btn", children: "\xD7" })
1970
- ] }),
1971
- /* @__PURE__ */ jsx8("div", { className: "hsk-checkout-content", children: paymentSuccess ? /* @__PURE__ */ jsxs5("div", { className: "hsk-checkout-success", children: [
1972
- /* @__PURE__ */ jsxs5("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "hsk-success-icon", children: [
1973
- /* @__PURE__ */ jsx8("path", { d: "M22 11.08V12a10 10 0 1 1-5.93-9.14" }),
1974
- /* @__PURE__ */ jsx8("polyline", { points: "22 4 12 14.01 9 11.01" })
2034
+ /* @__PURE__ */ jsx8("div", { className: "hsk-checkout-panel-left", children: /* @__PURE__ */ jsxs5("div", { className: "hsk-checkout-left-content", children: [
2035
+ /* @__PURE__ */ jsxs5("button", { onClick: onClose, className: "hsk-checkout-back-btn", disabled: phase !== "idle", children: [
2036
+ /* @__PURE__ */ jsxs5("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
2037
+ /* @__PURE__ */ jsx8("line", { x1: "19", y1: "12", x2: "5", y2: "12" }),
2038
+ /* @__PURE__ */ jsx8("polyline", { points: "12 19 5 12 12 5" })
2039
+ ] }),
2040
+ "Back to store"
1975
2041
  ] }),
1976
- /* @__PURE__ */ jsx8("h3", { children: "Payment Successful!" }),
1977
- /* @__PURE__ */ jsx8("p", { children: "Thank you for your order." })
1978
- ] }) : /* @__PURE__ */ jsxs5("div", { className: "hsk-checkout-split", children: [
1979
- /* @__PURE__ */ jsxs5("div", { className: "hsk-checkout-summary", children: [
1980
- /* @__PURE__ */ jsx8("h3", { children: "Order Summary" }),
1981
- cartLoading || !cart ? /* @__PURE__ */ jsx8("p", { className: "hsk-cart-loading", children: "Loading order..." }) : /* @__PURE__ */ jsxs5(Fragment5, { children: [
1982
- /* @__PURE__ */ jsx8("ul", { className: "hsk-checkout-items", children: cart.items.map((item) => /* @__PURE__ */ jsxs5("li", { children: [
1983
- /* @__PURE__ */ jsxs5("span", { children: [
1984
- item.quantity,
1985
- "x ",
1986
- item.name
1987
- ] }),
1988
- /* @__PURE__ */ jsxs5("span", { children: [
1989
- item.currency,
1990
- " ",
1991
- (item.price_numeric * item.quantity).toLocaleString(void 0, { minimumFractionDigits: 2 })
1992
- ] })
1993
- ] }, item.id)) }),
1994
- /* @__PURE__ */ jsxs5("div", { className: "hsk-checkout-total", children: [
1995
- /* @__PURE__ */ jsx8("span", { children: "Total" }),
1996
- /* @__PURE__ */ jsxs5("span", { children: [
1997
- cart.currency,
1998
- " ",
1999
- cart.total.toLocaleString(void 0, { minimumFractionDigits: 2 })
2000
- ] })
2001
- ] })
2042
+ /* @__PURE__ */ jsx8("div", { className: "hsk-checkout-store-info", children: /* @__PURE__ */ jsx8("h2", { children: "Secure Checkout" }) }),
2043
+ /* @__PURE__ */ jsxs5("div", { className: "hsk-checkout-amount-due", children: [
2044
+ /* @__PURE__ */ jsx8("span", { className: "hsk-checkout-label-muted", children: "Pay total" }),
2045
+ /* @__PURE__ */ jsxs5("div", { className: "hsk-checkout-grand-total", children: [
2046
+ currency,
2047
+ " ",
2048
+ total.toLocaleString(void 0, { minimumFractionDigits: 2 })
2002
2049
  ] })
2003
2050
  ] }),
2004
- /* @__PURE__ */ jsxs5("div", { className: "hsk-checkout-payment", children: [
2005
- /* @__PURE__ */ jsx8("h3", { children: "Payment Method" }),
2006
- loading ? /* @__PURE__ */ jsx8("p", { className: "hsk-cart-loading", children: "Loading secure payment methods..." }) : !hasPaymentMethods ? /* @__PURE__ */ jsx8("p", { className: "hsk-checkout-error", children: "No payment methods are currently available for this store." }) : /* @__PURE__ */ jsxs5("div", { className: "hsk-payment-options", children: [
2007
- ((_a = config == null ? void 0 : config.mpesa) == null ? void 0 : _a.enabled) && /* @__PURE__ */ jsx8("button", { onClick: () => handlePay("mpesa"), disabled: checkingOut, className: "hsk-pay-btn hsk-pay-mpesa", children: checkingOut ? "Processing..." : "Pay with M-Pesa" }),
2008
- ((_b = config == null ? void 0 : config.equity) == null ? void 0 : _b.enabled) && /* @__PURE__ */ jsx8("button", { onClick: () => handlePay("equity"), disabled: checkingOut, className: "hsk-pay-btn hsk-pay-equity", children: checkingOut ? "Processing..." : "Pay with Equity Bank" }),
2009
- ((_c = config == null ? void 0 : config.stripe) == null ? void 0 : _c.enabled) && /* @__PURE__ */ jsx8("button", { onClick: () => handlePay("stripe"), disabled: checkingOut, className: "hsk-pay-btn hsk-pay-stripe", children: checkingOut ? "Processing..." : "Pay with Card (Stripe)" }),
2010
- ((_d = config == null ? void 0 : config.paypal) == null ? void 0 : _d.enabled) && /* @__PURE__ */ jsx8("button", { onClick: () => handlePay("paypal"), disabled: checkingOut, className: "hsk-pay-btn hsk-pay-paypal", children: checkingOut ? "Processing..." : "Pay with PayPal" })
2051
+ cartLoading || !cart ? /* @__PURE__ */ jsx8("p", { className: "hsk-cart-loading", children: "Loading order..." }) : /* @__PURE__ */ jsx8("div", { className: "hsk-checkout-items-list-wrap", children: /* @__PURE__ */ jsx8("ul", { className: "hsk-checkout-items-list", children: cart.items.map((item) => /* @__PURE__ */ jsxs5("li", { className: "hsk-checkout-item-row", children: [
2052
+ /* @__PURE__ */ jsxs5("div", { className: "hsk-checkout-item-img-container", children: [
2053
+ item.image ? /* @__PURE__ */ jsx8("img", { src: item.image, alt: item.name, className: "hsk-checkout-item-img" }) : /* @__PURE__ */ jsx8("div", { className: "hsk-checkout-item-img-placeholder", children: "\u{1F6D2}" }),
2054
+ /* @__PURE__ */ jsx8("span", { className: "hsk-checkout-item-qty-badge", children: item.quantity })
2055
+ ] }),
2056
+ /* @__PURE__ */ jsx8("div", { className: "hsk-checkout-item-details", children: /* @__PURE__ */ jsx8("span", { className: "hsk-checkout-item-name", children: item.name }) }),
2057
+ /* @__PURE__ */ jsxs5("span", { className: "hsk-checkout-item-price", children: [
2058
+ item.currency,
2059
+ " ",
2060
+ (item.price_numeric * item.quantity).toLocaleString(void 0, { minimumFractionDigits: 2 })
2011
2061
  ] })
2062
+ ] }, item.id)) }) })
2063
+ ] }) }),
2064
+ /* @__PURE__ */ jsx8("div", { className: "hsk-checkout-panel-right", children: /* @__PURE__ */ jsx8("div", { className: "hsk-checkout-right-content", children: phase === "done" ? /* @__PURE__ */ jsxs5("div", { className: "hsk-checkout-status-card success", children: [
2065
+ /* @__PURE__ */ jsx8("div", { className: "hsk-status-icon-wrap success", children: "\u2705" }),
2066
+ /* @__PURE__ */ jsx8("h3", { children: "Payment Successful!" }),
2067
+ /* @__PURE__ */ jsx8("p", { children: "Your transaction has been confirmed successfully. Thank you for your order!" }),
2068
+ /* @__PURE__ */ jsx8("button", { onClick: onClose, className: "hsk-pay-btn hsk-btn-primary", style: { marginTop: "1.5rem" }, children: "Continue Shopping" })
2069
+ ] }) : phase === "awaiting" ? /* @__PURE__ */ jsxs5("div", { className: "hsk-checkout-status-card awaiting", children: [
2070
+ /* @__PURE__ */ jsx8("div", { className: "hsk-status-spinner-wrap", children: /* @__PURE__ */ jsx8("div", { className: "hsk-status-spinner" }) }),
2071
+ /* @__PURE__ */ jsx8("h3", { children: "Confirm payment on your phone" }),
2072
+ /* @__PURE__ */ jsxs5("p", { children: [
2073
+ "We've sent an M-Pesa STK push prompt to ",
2074
+ /* @__PURE__ */ jsxs5("strong", { children: [
2075
+ "254",
2076
+ phone
2077
+ ] }),
2078
+ "."
2079
+ ] }),
2080
+ /* @__PURE__ */ jsxs5("div", { className: "hsk-checkout-stk-instructions", children: [
2081
+ /* @__PURE__ */ jsx8("p", { children: "1. Check your phone lockscreen for the M-Pesa prompt." }),
2082
+ /* @__PURE__ */ jsx8("p", { children: "2. Enter your M-Pesa PIN and press OK." }),
2083
+ /* @__PURE__ */ jsx8("p", { children: "3. Wait here; this page will automatically redirect once confirmed." })
2084
+ ] }),
2085
+ /* @__PURE__ */ jsx8(
2086
+ "button",
2087
+ {
2088
+ onClick: () => {
2089
+ setPhase("idle");
2090
+ setMerchantRef(null);
2091
+ },
2092
+ className: "hsk-checkout-cancel-btn",
2093
+ children: "Cancel and change phone number"
2094
+ }
2095
+ )
2096
+ ] }) : phase === "failed" ? /* @__PURE__ */ jsxs5("div", { className: "hsk-checkout-status-card failed", children: [
2097
+ /* @__PURE__ */ jsx8("div", { className: "hsk-status-icon-wrap failed", children: "\u274C" }),
2098
+ /* @__PURE__ */ jsx8("h3", { children: "Payment failed or timed out" }),
2099
+ /* @__PURE__ */ jsx8("p", { className: "hsk-checkout-error-text", children: payError || "Could not verify M-Pesa transaction." }),
2100
+ /* @__PURE__ */ jsx8("button", { onClick: () => {
2101
+ setPhase("idle");
2102
+ setPayError(null);
2103
+ }, className: "hsk-pay-btn hsk-btn-primary", style: { marginTop: "1.5rem" }, children: "Try Again" })
2104
+ ] }) : /* @__PURE__ */ jsxs5("div", { className: "hsk-checkout-payment-form-wrap", children: [
2105
+ /* @__PURE__ */ jsx8("h3", { className: "hsk-checkout-section-title", children: "Payment details" }),
2106
+ loadingConfig ? /* @__PURE__ */ jsx8("p", { className: "hsk-cart-loading", children: "Loading payment configuration..." }) : !hasPaymentMethods ? /* @__PURE__ */ jsx8("p", { className: "hsk-checkout-error", children: "No payment methods configured for this store." }) : /* @__PURE__ */ jsxs5("form", { onSubmit: handlePay, className: "hsk-stripe-checkout-form", children: [
2107
+ /* @__PURE__ */ jsxs5("div", { className: "hsk-form-group", children: [
2108
+ /* @__PURE__ */ jsx8("label", { className: "hsk-form-label", children: "M-Pesa Mobile Number" }),
2109
+ /* @__PURE__ */ jsxs5("div", { className: "hsk-phone-input-container", children: [
2110
+ /* @__PURE__ */ jsx8("span", { className: "hsk-phone-prefix", children: "254" }),
2111
+ /* @__PURE__ */ jsx8(
2112
+ "input",
2113
+ {
2114
+ type: "tel",
2115
+ required: true,
2116
+ placeholder: "712345678",
2117
+ pattern: "[0-9]{9}",
2118
+ maxLength: 9,
2119
+ value: phone,
2120
+ onChange: (e) => setPhone(e.target.value.replace(/\D/g, "")),
2121
+ className: "hsk-phone-input-field"
2122
+ }
2123
+ )
2124
+ ] }),
2125
+ /* @__PURE__ */ jsx8("span", { className: "hsk-form-hint", children: "Enter your 9-digit number (e.g. 712345678)" })
2126
+ ] }),
2127
+ /* @__PURE__ */ jsxs5("div", { className: "hsk-form-group", children: [
2128
+ /* @__PURE__ */ jsx8("label", { className: "hsk-form-label", children: "Email address" }),
2129
+ /* @__PURE__ */ jsx8(
2130
+ "input",
2131
+ {
2132
+ type: "email",
2133
+ placeholder: "john.doe@example.com",
2134
+ value: email,
2135
+ onChange: (e) => setEmail(e.target.value),
2136
+ className: "hsk-form-input"
2137
+ }
2138
+ )
2139
+ ] }),
2140
+ /* @__PURE__ */ jsxs5("div", { className: "hsk-form-row", children: [
2141
+ /* @__PURE__ */ jsxs5("div", { className: "hsk-form-group", children: [
2142
+ /* @__PURE__ */ jsx8("label", { className: "hsk-form-label", children: "First Name" }),
2143
+ /* @__PURE__ */ jsx8(
2144
+ "input",
2145
+ {
2146
+ type: "text",
2147
+ placeholder: "John",
2148
+ value: firstName,
2149
+ onChange: (e) => setFirstName(e.target.value),
2150
+ className: "hsk-form-input"
2151
+ }
2152
+ )
2153
+ ] }),
2154
+ /* @__PURE__ */ jsxs5("div", { className: "hsk-form-group", children: [
2155
+ /* @__PURE__ */ jsx8("label", { className: "hsk-form-label", children: "Last Name" }),
2156
+ /* @__PURE__ */ jsx8(
2157
+ "input",
2158
+ {
2159
+ type: "text",
2160
+ placeholder: "Doe",
2161
+ value: lastName,
2162
+ onChange: (e) => setLastName(e.target.value),
2163
+ className: "hsk-form-input"
2164
+ }
2165
+ )
2166
+ ] })
2167
+ ] }),
2168
+ payError && /* @__PURE__ */ jsx8("div", { className: "hsk-form-error-banner", children: payError }),
2169
+ /* @__PURE__ */ jsxs5("button", { type: "submit", className: "hsk-checkout-submit-btn", children: [
2170
+ "Pay ",
2171
+ currency,
2172
+ " ",
2173
+ total.toLocaleString()
2174
+ ] }),
2175
+ /* @__PURE__ */ jsx8("div", { className: "hsk-checkout-footer-brand", children: /* @__PURE__ */ jsx8("span", { children: "Powered by Huskel AI" }) })
2012
2176
  ] })
2013
- ] }) })
2177
+ ] }) }) })
2014
2178
  ]
2015
2179
  }
2016
2180
  )
@@ -2021,7 +2185,7 @@ function CheckoutModal({
2021
2185
  }
2022
2186
 
2023
2187
  // src/components/CartDrawer.tsx
2024
- import { Fragment as Fragment6, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
2188
+ import { Fragment as Fragment5, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
2025
2189
  function CartDrawer({
2026
2190
  trigger,
2027
2191
  className,
@@ -2055,12 +2219,18 @@ function CartDrawer({
2055
2219
  }, [open]);
2056
2220
  const handleCheckout = async () => {
2057
2221
  if (!cart || cart.items.length === 0) return;
2222
+ const event = new CustomEvent("huskel:trigger_checkout", { cancelable: true });
2223
+ window.dispatchEvent(event);
2224
+ if (event.defaultPrevented) {
2225
+ setOpen(false);
2226
+ return;
2227
+ }
2058
2228
  setShowCheckout(true);
2059
2229
  };
2060
2230
  const isStringTheme = typeof theme === "string";
2061
2231
  const hskThemeAttr = isStringTheme ? theme : void 0;
2062
2232
  const customStyles = !isStringTheme && theme ? __spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues({}, (theme == null ? void 0 : theme.primaryColor) && { "--hsk-primary": theme.primaryColor, "--hsk-primary-color": theme.primaryColor }), (theme == null ? void 0 : theme.backgroundColor) && { "--hsk-bg": theme.backgroundColor }), (theme == null ? void 0 : theme.textColor) && { "--hsk-text": theme.textColor }), (theme == null ? void 0 : theme.fontFamily) && { "--hsk-font": theme.fontFamily }), (theme == null ? void 0 : theme.borderRadius) && { "--hsk-border-radius": theme.borderRadius }) : void 0;
2063
- return /* @__PURE__ */ jsxs6(Fragment6, { children: [
2233
+ return /* @__PURE__ */ jsxs6(Fragment5, { children: [
2064
2234
  /* @__PURE__ */ jsx9("div", { onClick: () => setOpen(true), style: { display: "inline-block" }, children: trigger || /* @__PURE__ */ jsxs6(
2065
2235
  "button",
2066
2236
  {