@loofta/pay-sdk 1.0.2 → 1.0.5

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/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # @loofta/pay-sdk
2
2
 
3
- Embeddable **Loofta Pay Button** for React. The button opens **Loofta’s hosted checkout** — your customers pay there, and funds go to the destination wallet, network, and token configured in your organization.
3
+ Embeddable **Loofta Pay Button** for React.
4
+
5
+ - **Repository:** [github.com/loofta/loofta-pay-sdk](https://github.com/loofta/loofta-pay-sdk)
6
+ - **Examples:** [examples/pay-button-demo](https://github.com/loofta/loofta-pay-sdk/tree/master/examples/pay-button-demo)
7
+ - **Live demo:** [pay.loofta.xyz/b2b/demo](https://pay.loofta.xyz/b2b/demo) The button opens **Loofta’s hosted checkout** — your customers pay there, and funds go to the destination wallet, network, and token configured in your organization.
4
8
 
5
9
  ## Requirements
6
10
 
package/dist/index.js CHANGED
@@ -74,14 +74,15 @@ function PayButton({
74
74
  const [isHovered, setIsHovered] = react.useState(false);
75
75
  const effectiveButtonBgColor = buttonBgColor || bgColor;
76
76
  const getCheckoutUrl = react.useCallback(() => {
77
- const defaultBase = "https://pay.loofta.xyz";
77
+ const defaultBase = "https://pay.loofta.com";
78
78
  const base = checkoutBaseUrl != null && checkoutBaseUrl !== "" ? checkoutBaseUrl.replace(/\/$/, "") : defaultBase;
79
79
  const path = base.endsWith("/checkout") ? base : `${base}/checkout`;
80
80
  const params = new URLSearchParams();
81
81
  params.set("organizationId", organizationId);
82
82
  if (amount) params.set("amount", String(amount));
83
83
  if (pageBgColor) params.set("bgColor", encodeURIComponent(pageBgColor));
84
- if (callbackUrl) params.set("callback", encodeURIComponent(callbackUrl));
84
+ const effectiveCallback = callbackUrl ?? (typeof window !== "undefined" ? window.location.href : "");
85
+ if (effectiveCallback) params.set("callback", encodeURIComponent(effectiveCallback));
85
86
  return `${path}?${params.toString()}`;
86
87
  }, [checkoutBaseUrl, organizationId, amount, pageBgColor, callbackUrl]);
87
88
  const handleClick = react.useCallback(() => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/PayButton.tsx"],"names":["jsxs","jsx","useState","useCallback","Fragment"],"mappings":"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","file":"index.js","sourcesContent":["import { useState, useCallback } from 'react';\n\nexport interface PayButtonProps {\n /**\n * Organization ID (required). Must be set up with Loofta — your destination wallet, network, and token are configured in your organization.\n * If you don't have an organization ID, contact Loofta to get one.\n */\n organizationId: string;\n /** Payment amount in USD (optional) */\n amount?: number | string;\n /** Button background color (optional) */\n buttonBgColor?: string;\n /** Checkout page background color (optional - falls back to org settings) */\n pageBgColor?: string;\n /** @deprecated Use buttonBgColor instead */\n bgColor?: string;\n /** Callback URL after payment (optional) */\n callbackUrl?: string;\n /** Callback function after payment (optional) */\n onSuccess?: (paymentId: string) => void;\n /** Button text (optional) */\n buttonText?: string;\n /** Success text shown after payment (optional) */\n successText?: string;\n /** Custom className for button styling */\n className?: string;\n /** Open checkout in new tab vs popup (default: popup) */\n openMode?: 'popup' | 'redirect' | 'tab';\n /** Disable button */\n disabled?: boolean;\n /**\n * Base URL of the Loofta Pay hosted checkout page. Checkout is always Loofta's — this is only needed if the button is embedded on a different domain than the default Loofta Pay app. Usually omit; default is used.\n */\n checkoutBaseUrl?: string;\n}\n\nconst DEFAULT_STYLE: React.CSSProperties = {\n background: 'linear-gradient(to right, #FF0F00, #EAB308)',\n color: '#ffffff',\n border: 'none',\n borderRadius: '12px',\n padding: '12px 24px',\n fontSize: '16px',\n fontWeight: 600,\n cursor: 'pointer',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '8px',\n minWidth: '160px',\n transition: 'transform 0.2s, box-shadow 0.2s',\n boxShadow: '0 4px 14px rgba(255, 15, 0, 0.25)',\n};\n\nconst HOVER_STYLE: React.CSSProperties = {\n transform: 'scale(1.02)',\n boxShadow: '0 6px 20px rgba(255, 15, 0, 0.35)',\n};\n\nfunction LoaderIcon() {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" strokeOpacity={0.25} />\n <path\n d=\"M12 2a10 10 0 0 1 10 10\"\n style={{ transformOrigin: '12px 12px' }}\n >\n <animateTransform\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 12 12\"\n to=\"360 12 12\"\n dur=\"0.8s\"\n repeatCount=\"indefinite\"\n />\n </path>\n </svg>\n );\n}\n\nfunction CheckIcon() {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n );\n}\n\nfunction PayIcon() {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\" />\n </svg>\n );\n}\n\n/**\n * Loofta Pay Button – opens your Loofta Pay checkout (same API as your app).\n */\nexport function PayButton({\n organizationId,\n amount,\n buttonBgColor,\n pageBgColor,\n bgColor,\n callbackUrl,\n onSuccess,\n buttonText = 'Pay with Loofta',\n successText = 'Paid Successfully',\n className,\n openMode = 'popup',\n disabled = false,\n checkoutBaseUrl,\n}: PayButtonProps) {\n const [loading, setLoading] = useState(false);\n const [paid, setPaid] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n\n const effectiveButtonBgColor = buttonBgColor || bgColor;\n\n const getCheckoutUrl = useCallback(() => {\n const defaultBase = 'https://pay.loofta.xyz';\n const base =\n checkoutBaseUrl != null && checkoutBaseUrl !== ''\n ? checkoutBaseUrl.replace(/\\/$/, '')\n : defaultBase;\n\n const path = base.endsWith('/checkout') ? base : `${base}/checkout`;\n const params = new URLSearchParams();\n params.set('organizationId', organizationId);\n if (amount) params.set('amount', String(amount));\n if (pageBgColor) params.set('bgColor', encodeURIComponent(pageBgColor));\n if (callbackUrl) params.set('callback', encodeURIComponent(callbackUrl));\n\n return `${path}?${params.toString()}`;\n }, [checkoutBaseUrl, organizationId, amount, pageBgColor, callbackUrl]);\n\n const handleClick = useCallback(() => {\n if (disabled || loading || paid) return;\n\n setLoading(true);\n const url = getCheckoutUrl();\n\n if (openMode === 'redirect') {\n window.location.href = url;\n return;\n }\n\n if (openMode === 'tab') {\n window.open(url, '_blank', 'noopener,noreferrer');\n setLoading(false);\n return;\n }\n\n const width = 500;\n const height = 700;\n const left = window.screenX + (window.outerWidth - width) / 2;\n const top = window.screenY + (window.outerHeight - height) / 2;\n\n const popup = window.open(\n url,\n 'loofta-pay-checkout',\n `width=${width},height=${height},left=${left},top=${top},scrollbars=yes,resizable=yes`\n );\n\n const handleMessage = (event: MessageEvent) => {\n if (event.data?.type === 'loofta-payment-success') {\n setLoading(false);\n setPaid(true);\n onSuccess?.(event.data.paymentId);\n popup?.close();\n window.removeEventListener('message', handleMessage);\n }\n };\n window.addEventListener('message', handleMessage);\n\n const checkClosed = setInterval(() => {\n if (popup?.closed) {\n clearInterval(checkClosed);\n setLoading(false);\n window.removeEventListener('message', handleMessage);\n }\n }, 500);\n }, [disabled, loading, paid, getCheckoutUrl, openMode, onSuccess]);\n\n const successStyle: React.CSSProperties = {\n ...DEFAULT_STYLE,\n background: 'linear-gradient(to right, #10B981, #059669)',\n boxShadow: '0 4px 14px rgba(16, 185, 129, 0.25)',\n cursor: 'default',\n };\n\n const buttonStyle: React.CSSProperties = {\n ...DEFAULT_STYLE,\n ...(effectiveButtonBgColor ? { background: effectiveButtonBgColor } : {}),\n ...(isHovered && !disabled && !paid ? HOVER_STYLE : {}),\n ...(disabled ? { opacity: 0.6, cursor: 'not-allowed' as const } : {}),\n };\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={disabled || loading || paid}\n className={className}\n style={className ? undefined : paid ? successStyle : buttonStyle}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {paid ? (\n <>\n <CheckIcon />\n {successText}\n </>\n ) : loading ? (\n <>\n <LoaderIcon />\n Processing...\n </>\n ) : (\n <>\n <PayIcon />\n {buttonText}\n </>\n )}\n </button>\n );\n}\n\nexport function generateEmbedCode(props: Partial<PayButtonProps>): string {\n const { organizationId, amount, buttonBgColor, pageBgColor, callbackUrl, buttonText, checkoutBaseUrl } = props;\n\n const propsStr = [\n `organizationId=\"${organizationId || 'your-org-id'}\"`,\n amount ? `amount={${amount}}` : null,\n buttonBgColor ? `buttonBgColor=\"${buttonBgColor}\"` : null,\n pageBgColor ? `pageBgColor=\"${pageBgColor}\"` : null,\n callbackUrl ? `callbackUrl=\"${callbackUrl}\"` : null,\n buttonText ? `buttonText=\"${buttonText}\"` : null,\n checkoutBaseUrl ? `checkoutBaseUrl=\"${checkoutBaseUrl}\"` : null,\n ]\n .filter(Boolean)\n .join('\\n ');\n\n return `import { PayButton } from '@loofta/pay-sdk';\n\n<PayButton\n ${propsStr}\n onSuccess={(paymentId) => {\n console.log('Payment completed:', paymentId);\n }}\n/>`;\n}\n\nexport function generateScriptEmbed(props: Partial<PayButtonProps>): string {\n const { organizationId, amount, buttonBgColor, pageBgColor, callbackUrl, buttonText, checkoutBaseUrl } = props;\n const base = checkoutBaseUrl || 'https://pay.loofta.xyz';\n\n return `<!-- Loofta Pay Button -->\n<script src=\"${base}/sdk/loofta-pay.js\"></script>\n<div \n id=\"loofta-pay-button\"\n data-organization-id=\"${organizationId || 'your-org-id'}\"\n data-checkout-base-url=\"${base}\"\n ${amount ? `data-amount=\"${amount}\"` : ''}\n ${buttonBgColor ? `data-button-bg-color=\"${buttonBgColor}\"` : ''}\n ${pageBgColor ? `data-page-bg-color=\"${pageBgColor}\"` : ''}\n ${buttonText ? `data-button-text=\"${buttonText}\"` : ''}\n ${callbackUrl ? `data-callback=\"${callbackUrl}\"` : ''}\n></div>\n<script>\n LooftaPay.mount('#loofta-pay-button');\n</script>`;\n}\n\nexport default PayButton;\n"]}
1
+ {"version":3,"sources":["../src/PayButton.tsx"],"names":["jsxs","jsx","useState","useCallback","Fragment"],"mappings":"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","file":"index.js","sourcesContent":["import { useState, useCallback } from 'react';\n\nexport interface PayButtonProps {\n /**\n * Organization ID (required). Must be set up with Loofta — your destination wallet, network, and token are configured in your organization.\n * If you don't have an organization ID, contact Loofta to get one.\n */\n organizationId: string;\n /** Payment amount in USD (optional) */\n amount?: number | string;\n /** Button background color (optional) */\n buttonBgColor?: string;\n /** Checkout page background color (optional - falls back to org settings) */\n pageBgColor?: string;\n /** @deprecated Use buttonBgColor instead */\n bgColor?: string;\n /** Callback URL after payment (optional) */\n callbackUrl?: string;\n /** Callback function after payment (optional) */\n onSuccess?: (paymentId: string) => void;\n /** Button text (optional) */\n buttonText?: string;\n /** Success text shown after payment (optional) */\n successText?: string;\n /** Custom className for button styling */\n className?: string;\n /** Open checkout in new tab vs popup (default: popup) */\n openMode?: 'popup' | 'redirect' | 'tab';\n /** Disable button */\n disabled?: boolean;\n /**\n * Base URL of the Loofta Pay hosted checkout page. Checkout is always Loofta's — this is only needed if the button is embedded on a different domain than the default Loofta Pay app. Usually omit; default is used.\n */\n checkoutBaseUrl?: string;\n}\n\nconst DEFAULT_STYLE: React.CSSProperties = {\n background: 'linear-gradient(to right, #FF0F00, #EAB308)',\n color: '#ffffff',\n border: 'none',\n borderRadius: '12px',\n padding: '12px 24px',\n fontSize: '16px',\n fontWeight: 600,\n cursor: 'pointer',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '8px',\n minWidth: '160px',\n transition: 'transform 0.2s, box-shadow 0.2s',\n boxShadow: '0 4px 14px rgba(255, 15, 0, 0.25)',\n};\n\nconst HOVER_STYLE: React.CSSProperties = {\n transform: 'scale(1.02)',\n boxShadow: '0 6px 20px rgba(255, 15, 0, 0.35)',\n};\n\nfunction LoaderIcon() {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" strokeOpacity={0.25} />\n <path\n d=\"M12 2a10 10 0 0 1 10 10\"\n style={{ transformOrigin: '12px 12px' }}\n >\n <animateTransform\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 12 12\"\n to=\"360 12 12\"\n dur=\"0.8s\"\n repeatCount=\"indefinite\"\n />\n </path>\n </svg>\n );\n}\n\nfunction CheckIcon() {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n );\n}\n\nfunction PayIcon() {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\" />\n </svg>\n );\n}\n\n/**\n * Loofta Pay Button – opens your Loofta Pay checkout (same API as your app).\n */\nexport function PayButton({\n organizationId,\n amount,\n buttonBgColor,\n pageBgColor,\n bgColor,\n callbackUrl,\n onSuccess,\n buttonText = 'Pay with Loofta',\n successText = 'Paid Successfully',\n className,\n openMode = 'popup',\n disabled = false,\n checkoutBaseUrl,\n}: PayButtonProps) {\n const [loading, setLoading] = useState(false);\n const [paid, setPaid] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n\n const effectiveButtonBgColor = buttonBgColor || bgColor;\n\n const getCheckoutUrl = useCallback(() => {\n const defaultBase = 'https://pay.loofta.com';\n const base =\n checkoutBaseUrl != null && checkoutBaseUrl !== ''\n ? checkoutBaseUrl.replace(/\\/$/, '')\n : defaultBase;\n\n const path = base.endsWith('/checkout') ? base : `${base}/checkout`;\n const params = new URLSearchParams();\n params.set('organizationId', organizationId);\n if (amount) params.set('amount', String(amount));\n if (pageBgColor) params.set('bgColor', encodeURIComponent(pageBgColor));\n const effectiveCallback = callbackUrl ?? (typeof window !== 'undefined' ? window.location.href : '');\n if (effectiveCallback) params.set('callback', encodeURIComponent(effectiveCallback));\n\n return `${path}?${params.toString()}`;\n }, [checkoutBaseUrl, organizationId, amount, pageBgColor, callbackUrl]);\n\n const handleClick = useCallback(() => {\n if (disabled || loading || paid) return;\n\n setLoading(true);\n const url = getCheckoutUrl();\n\n if (openMode === 'redirect') {\n window.location.href = url;\n return;\n }\n\n if (openMode === 'tab') {\n window.open(url, '_blank', 'noopener,noreferrer');\n setLoading(false);\n return;\n }\n\n const width = 500;\n const height = 700;\n const left = window.screenX + (window.outerWidth - width) / 2;\n const top = window.screenY + (window.outerHeight - height) / 2;\n\n const popup = window.open(\n url,\n 'loofta-pay-checkout',\n `width=${width},height=${height},left=${left},top=${top},scrollbars=yes,resizable=yes`\n );\n\n const handleMessage = (event: MessageEvent) => {\n if (event.data?.type === 'loofta-payment-success') {\n setLoading(false);\n setPaid(true);\n onSuccess?.(event.data.paymentId);\n popup?.close();\n window.removeEventListener('message', handleMessage);\n }\n };\n window.addEventListener('message', handleMessage);\n\n const checkClosed = setInterval(() => {\n if (popup?.closed) {\n clearInterval(checkClosed);\n setLoading(false);\n window.removeEventListener('message', handleMessage);\n }\n }, 500);\n }, [disabled, loading, paid, getCheckoutUrl, openMode, onSuccess]);\n\n const successStyle: React.CSSProperties = {\n ...DEFAULT_STYLE,\n background: 'linear-gradient(to right, #10B981, #059669)',\n boxShadow: '0 4px 14px rgba(16, 185, 129, 0.25)',\n cursor: 'default',\n };\n\n const buttonStyle: React.CSSProperties = {\n ...DEFAULT_STYLE,\n ...(effectiveButtonBgColor ? { background: effectiveButtonBgColor } : {}),\n ...(isHovered && !disabled && !paid ? HOVER_STYLE : {}),\n ...(disabled ? { opacity: 0.6, cursor: 'not-allowed' as const } : {}),\n };\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={disabled || loading || paid}\n className={className}\n style={className ? undefined : paid ? successStyle : buttonStyle}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {paid ? (\n <>\n <CheckIcon />\n {successText}\n </>\n ) : loading ? (\n <>\n <LoaderIcon />\n Processing...\n </>\n ) : (\n <>\n <PayIcon />\n {buttonText}\n </>\n )}\n </button>\n );\n}\n\nexport function generateEmbedCode(props: Partial<PayButtonProps>): string {\n const { organizationId, amount, buttonBgColor, pageBgColor, callbackUrl, buttonText, checkoutBaseUrl } = props;\n\n const propsStr = [\n `organizationId=\"${organizationId || 'your-org-id'}\"`,\n amount ? `amount={${amount}}` : null,\n buttonBgColor ? `buttonBgColor=\"${buttonBgColor}\"` : null,\n pageBgColor ? `pageBgColor=\"${pageBgColor}\"` : null,\n callbackUrl ? `callbackUrl=\"${callbackUrl}\"` : null,\n buttonText ? `buttonText=\"${buttonText}\"` : null,\n checkoutBaseUrl ? `checkoutBaseUrl=\"${checkoutBaseUrl}\"` : null,\n ]\n .filter(Boolean)\n .join('\\n ');\n\n return `import { PayButton } from '@loofta/pay-sdk';\n\n<PayButton\n ${propsStr}\n onSuccess={(paymentId) => {\n console.log('Payment completed:', paymentId);\n }}\n/>`;\n}\n\nexport function generateScriptEmbed(props: Partial<PayButtonProps>): string {\n const { organizationId, amount, buttonBgColor, pageBgColor, callbackUrl, buttonText, checkoutBaseUrl } = props;\n const base = checkoutBaseUrl || 'https://pay.loofta.xyz';\n\n return `<!-- Loofta Pay Button -->\n<script src=\"${base}/sdk/loofta-pay.js\"></script>\n<div \n id=\"loofta-pay-button\"\n data-organization-id=\"${organizationId || 'your-org-id'}\"\n data-checkout-base-url=\"${base}\"\n ${amount ? `data-amount=\"${amount}\"` : ''}\n ${buttonBgColor ? `data-button-bg-color=\"${buttonBgColor}\"` : ''}\n ${pageBgColor ? `data-page-bg-color=\"${pageBgColor}\"` : ''}\n ${buttonText ? `data-button-text=\"${buttonText}\"` : ''}\n ${callbackUrl ? `data-callback=\"${callbackUrl}\"` : ''}\n></div>\n<script>\n LooftaPay.mount('#loofta-pay-button');\n</script>`;\n}\n\nexport default PayButton;\n"]}
package/dist/index.mjs CHANGED
@@ -72,14 +72,15 @@ function PayButton({
72
72
  const [isHovered, setIsHovered] = useState(false);
73
73
  const effectiveButtonBgColor = buttonBgColor || bgColor;
74
74
  const getCheckoutUrl = useCallback(() => {
75
- const defaultBase = "https://pay.loofta.xyz";
75
+ const defaultBase = "https://pay.loofta.com";
76
76
  const base = checkoutBaseUrl != null && checkoutBaseUrl !== "" ? checkoutBaseUrl.replace(/\/$/, "") : defaultBase;
77
77
  const path = base.endsWith("/checkout") ? base : `${base}/checkout`;
78
78
  const params = new URLSearchParams();
79
79
  params.set("organizationId", organizationId);
80
80
  if (amount) params.set("amount", String(amount));
81
81
  if (pageBgColor) params.set("bgColor", encodeURIComponent(pageBgColor));
82
- if (callbackUrl) params.set("callback", encodeURIComponent(callbackUrl));
82
+ const effectiveCallback = callbackUrl ?? (typeof window !== "undefined" ? window.location.href : "");
83
+ if (effectiveCallback) params.set("callback", encodeURIComponent(effectiveCallback));
83
84
  return `${path}?${params.toString()}`;
84
85
  }, [checkoutBaseUrl, organizationId, amount, pageBgColor, callbackUrl]);
85
86
  const handleClick = useCallback(() => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/PayButton.tsx"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import { useState, useCallback } from 'react';\n\nexport interface PayButtonProps {\n /**\n * Organization ID (required). Must be set up with Loofta — your destination wallet, network, and token are configured in your organization.\n * If you don't have an organization ID, contact Loofta to get one.\n */\n organizationId: string;\n /** Payment amount in USD (optional) */\n amount?: number | string;\n /** Button background color (optional) */\n buttonBgColor?: string;\n /** Checkout page background color (optional - falls back to org settings) */\n pageBgColor?: string;\n /** @deprecated Use buttonBgColor instead */\n bgColor?: string;\n /** Callback URL after payment (optional) */\n callbackUrl?: string;\n /** Callback function after payment (optional) */\n onSuccess?: (paymentId: string) => void;\n /** Button text (optional) */\n buttonText?: string;\n /** Success text shown after payment (optional) */\n successText?: string;\n /** Custom className for button styling */\n className?: string;\n /** Open checkout in new tab vs popup (default: popup) */\n openMode?: 'popup' | 'redirect' | 'tab';\n /** Disable button */\n disabled?: boolean;\n /**\n * Base URL of the Loofta Pay hosted checkout page. Checkout is always Loofta's — this is only needed if the button is embedded on a different domain than the default Loofta Pay app. Usually omit; default is used.\n */\n checkoutBaseUrl?: string;\n}\n\nconst DEFAULT_STYLE: React.CSSProperties = {\n background: 'linear-gradient(to right, #FF0F00, #EAB308)',\n color: '#ffffff',\n border: 'none',\n borderRadius: '12px',\n padding: '12px 24px',\n fontSize: '16px',\n fontWeight: 600,\n cursor: 'pointer',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '8px',\n minWidth: '160px',\n transition: 'transform 0.2s, box-shadow 0.2s',\n boxShadow: '0 4px 14px rgba(255, 15, 0, 0.25)',\n};\n\nconst HOVER_STYLE: React.CSSProperties = {\n transform: 'scale(1.02)',\n boxShadow: '0 6px 20px rgba(255, 15, 0, 0.35)',\n};\n\nfunction LoaderIcon() {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" strokeOpacity={0.25} />\n <path\n d=\"M12 2a10 10 0 0 1 10 10\"\n style={{ transformOrigin: '12px 12px' }}\n >\n <animateTransform\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 12 12\"\n to=\"360 12 12\"\n dur=\"0.8s\"\n repeatCount=\"indefinite\"\n />\n </path>\n </svg>\n );\n}\n\nfunction CheckIcon() {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n );\n}\n\nfunction PayIcon() {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\" />\n </svg>\n );\n}\n\n/**\n * Loofta Pay Button – opens your Loofta Pay checkout (same API as your app).\n */\nexport function PayButton({\n organizationId,\n amount,\n buttonBgColor,\n pageBgColor,\n bgColor,\n callbackUrl,\n onSuccess,\n buttonText = 'Pay with Loofta',\n successText = 'Paid Successfully',\n className,\n openMode = 'popup',\n disabled = false,\n checkoutBaseUrl,\n}: PayButtonProps) {\n const [loading, setLoading] = useState(false);\n const [paid, setPaid] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n\n const effectiveButtonBgColor = buttonBgColor || bgColor;\n\n const getCheckoutUrl = useCallback(() => {\n const defaultBase = 'https://pay.loofta.xyz';\n const base =\n checkoutBaseUrl != null && checkoutBaseUrl !== ''\n ? checkoutBaseUrl.replace(/\\/$/, '')\n : defaultBase;\n\n const path = base.endsWith('/checkout') ? base : `${base}/checkout`;\n const params = new URLSearchParams();\n params.set('organizationId', organizationId);\n if (amount) params.set('amount', String(amount));\n if (pageBgColor) params.set('bgColor', encodeURIComponent(pageBgColor));\n if (callbackUrl) params.set('callback', encodeURIComponent(callbackUrl));\n\n return `${path}?${params.toString()}`;\n }, [checkoutBaseUrl, organizationId, amount, pageBgColor, callbackUrl]);\n\n const handleClick = useCallback(() => {\n if (disabled || loading || paid) return;\n\n setLoading(true);\n const url = getCheckoutUrl();\n\n if (openMode === 'redirect') {\n window.location.href = url;\n return;\n }\n\n if (openMode === 'tab') {\n window.open(url, '_blank', 'noopener,noreferrer');\n setLoading(false);\n return;\n }\n\n const width = 500;\n const height = 700;\n const left = window.screenX + (window.outerWidth - width) / 2;\n const top = window.screenY + (window.outerHeight - height) / 2;\n\n const popup = window.open(\n url,\n 'loofta-pay-checkout',\n `width=${width},height=${height},left=${left},top=${top},scrollbars=yes,resizable=yes`\n );\n\n const handleMessage = (event: MessageEvent) => {\n if (event.data?.type === 'loofta-payment-success') {\n setLoading(false);\n setPaid(true);\n onSuccess?.(event.data.paymentId);\n popup?.close();\n window.removeEventListener('message', handleMessage);\n }\n };\n window.addEventListener('message', handleMessage);\n\n const checkClosed = setInterval(() => {\n if (popup?.closed) {\n clearInterval(checkClosed);\n setLoading(false);\n window.removeEventListener('message', handleMessage);\n }\n }, 500);\n }, [disabled, loading, paid, getCheckoutUrl, openMode, onSuccess]);\n\n const successStyle: React.CSSProperties = {\n ...DEFAULT_STYLE,\n background: 'linear-gradient(to right, #10B981, #059669)',\n boxShadow: '0 4px 14px rgba(16, 185, 129, 0.25)',\n cursor: 'default',\n };\n\n const buttonStyle: React.CSSProperties = {\n ...DEFAULT_STYLE,\n ...(effectiveButtonBgColor ? { background: effectiveButtonBgColor } : {}),\n ...(isHovered && !disabled && !paid ? HOVER_STYLE : {}),\n ...(disabled ? { opacity: 0.6, cursor: 'not-allowed' as const } : {}),\n };\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={disabled || loading || paid}\n className={className}\n style={className ? undefined : paid ? successStyle : buttonStyle}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {paid ? (\n <>\n <CheckIcon />\n {successText}\n </>\n ) : loading ? (\n <>\n <LoaderIcon />\n Processing...\n </>\n ) : (\n <>\n <PayIcon />\n {buttonText}\n </>\n )}\n </button>\n );\n}\n\nexport function generateEmbedCode(props: Partial<PayButtonProps>): string {\n const { organizationId, amount, buttonBgColor, pageBgColor, callbackUrl, buttonText, checkoutBaseUrl } = props;\n\n const propsStr = [\n `organizationId=\"${organizationId || 'your-org-id'}\"`,\n amount ? `amount={${amount}}` : null,\n buttonBgColor ? `buttonBgColor=\"${buttonBgColor}\"` : null,\n pageBgColor ? `pageBgColor=\"${pageBgColor}\"` : null,\n callbackUrl ? `callbackUrl=\"${callbackUrl}\"` : null,\n buttonText ? `buttonText=\"${buttonText}\"` : null,\n checkoutBaseUrl ? `checkoutBaseUrl=\"${checkoutBaseUrl}\"` : null,\n ]\n .filter(Boolean)\n .join('\\n ');\n\n return `import { PayButton } from '@loofta/pay-sdk';\n\n<PayButton\n ${propsStr}\n onSuccess={(paymentId) => {\n console.log('Payment completed:', paymentId);\n }}\n/>`;\n}\n\nexport function generateScriptEmbed(props: Partial<PayButtonProps>): string {\n const { organizationId, amount, buttonBgColor, pageBgColor, callbackUrl, buttonText, checkoutBaseUrl } = props;\n const base = checkoutBaseUrl || 'https://pay.loofta.xyz';\n\n return `<!-- Loofta Pay Button -->\n<script src=\"${base}/sdk/loofta-pay.js\"></script>\n<div \n id=\"loofta-pay-button\"\n data-organization-id=\"${organizationId || 'your-org-id'}\"\n data-checkout-base-url=\"${base}\"\n ${amount ? `data-amount=\"${amount}\"` : ''}\n ${buttonBgColor ? `data-button-bg-color=\"${buttonBgColor}\"` : ''}\n ${pageBgColor ? `data-page-bg-color=\"${pageBgColor}\"` : ''}\n ${buttonText ? `data-button-text=\"${buttonText}\"` : ''}\n ${callbackUrl ? `data-callback=\"${callbackUrl}\"` : ''}\n></div>\n<script>\n LooftaPay.mount('#loofta-pay-button');\n</script>`;\n}\n\nexport default PayButton;\n"]}
1
+ {"version":3,"sources":["../src/PayButton.tsx"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import { useState, useCallback } from 'react';\n\nexport interface PayButtonProps {\n /**\n * Organization ID (required). Must be set up with Loofta — your destination wallet, network, and token are configured in your organization.\n * If you don't have an organization ID, contact Loofta to get one.\n */\n organizationId: string;\n /** Payment amount in USD (optional) */\n amount?: number | string;\n /** Button background color (optional) */\n buttonBgColor?: string;\n /** Checkout page background color (optional - falls back to org settings) */\n pageBgColor?: string;\n /** @deprecated Use buttonBgColor instead */\n bgColor?: string;\n /** Callback URL after payment (optional) */\n callbackUrl?: string;\n /** Callback function after payment (optional) */\n onSuccess?: (paymentId: string) => void;\n /** Button text (optional) */\n buttonText?: string;\n /** Success text shown after payment (optional) */\n successText?: string;\n /** Custom className for button styling */\n className?: string;\n /** Open checkout in new tab vs popup (default: popup) */\n openMode?: 'popup' | 'redirect' | 'tab';\n /** Disable button */\n disabled?: boolean;\n /**\n * Base URL of the Loofta Pay hosted checkout page. Checkout is always Loofta's — this is only needed if the button is embedded on a different domain than the default Loofta Pay app. Usually omit; default is used.\n */\n checkoutBaseUrl?: string;\n}\n\nconst DEFAULT_STYLE: React.CSSProperties = {\n background: 'linear-gradient(to right, #FF0F00, #EAB308)',\n color: '#ffffff',\n border: 'none',\n borderRadius: '12px',\n padding: '12px 24px',\n fontSize: '16px',\n fontWeight: 600,\n cursor: 'pointer',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '8px',\n minWidth: '160px',\n transition: 'transform 0.2s, box-shadow 0.2s',\n boxShadow: '0 4px 14px rgba(255, 15, 0, 0.25)',\n};\n\nconst HOVER_STYLE: React.CSSProperties = {\n transform: 'scale(1.02)',\n boxShadow: '0 6px 20px rgba(255, 15, 0, 0.35)',\n};\n\nfunction LoaderIcon() {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" strokeOpacity={0.25} />\n <path\n d=\"M12 2a10 10 0 0 1 10 10\"\n style={{ transformOrigin: '12px 12px' }}\n >\n <animateTransform\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 12 12\"\n to=\"360 12 12\"\n dur=\"0.8s\"\n repeatCount=\"indefinite\"\n />\n </path>\n </svg>\n );\n}\n\nfunction CheckIcon() {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n );\n}\n\nfunction PayIcon() {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\" />\n </svg>\n );\n}\n\n/**\n * Loofta Pay Button – opens your Loofta Pay checkout (same API as your app).\n */\nexport function PayButton({\n organizationId,\n amount,\n buttonBgColor,\n pageBgColor,\n bgColor,\n callbackUrl,\n onSuccess,\n buttonText = 'Pay with Loofta',\n successText = 'Paid Successfully',\n className,\n openMode = 'popup',\n disabled = false,\n checkoutBaseUrl,\n}: PayButtonProps) {\n const [loading, setLoading] = useState(false);\n const [paid, setPaid] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n\n const effectiveButtonBgColor = buttonBgColor || bgColor;\n\n const getCheckoutUrl = useCallback(() => {\n const defaultBase = 'https://pay.loofta.com';\n const base =\n checkoutBaseUrl != null && checkoutBaseUrl !== ''\n ? checkoutBaseUrl.replace(/\\/$/, '')\n : defaultBase;\n\n const path = base.endsWith('/checkout') ? base : `${base}/checkout`;\n const params = new URLSearchParams();\n params.set('organizationId', organizationId);\n if (amount) params.set('amount', String(amount));\n if (pageBgColor) params.set('bgColor', encodeURIComponent(pageBgColor));\n const effectiveCallback = callbackUrl ?? (typeof window !== 'undefined' ? window.location.href : '');\n if (effectiveCallback) params.set('callback', encodeURIComponent(effectiveCallback));\n\n return `${path}?${params.toString()}`;\n }, [checkoutBaseUrl, organizationId, amount, pageBgColor, callbackUrl]);\n\n const handleClick = useCallback(() => {\n if (disabled || loading || paid) return;\n\n setLoading(true);\n const url = getCheckoutUrl();\n\n if (openMode === 'redirect') {\n window.location.href = url;\n return;\n }\n\n if (openMode === 'tab') {\n window.open(url, '_blank', 'noopener,noreferrer');\n setLoading(false);\n return;\n }\n\n const width = 500;\n const height = 700;\n const left = window.screenX + (window.outerWidth - width) / 2;\n const top = window.screenY + (window.outerHeight - height) / 2;\n\n const popup = window.open(\n url,\n 'loofta-pay-checkout',\n `width=${width},height=${height},left=${left},top=${top},scrollbars=yes,resizable=yes`\n );\n\n const handleMessage = (event: MessageEvent) => {\n if (event.data?.type === 'loofta-payment-success') {\n setLoading(false);\n setPaid(true);\n onSuccess?.(event.data.paymentId);\n popup?.close();\n window.removeEventListener('message', handleMessage);\n }\n };\n window.addEventListener('message', handleMessage);\n\n const checkClosed = setInterval(() => {\n if (popup?.closed) {\n clearInterval(checkClosed);\n setLoading(false);\n window.removeEventListener('message', handleMessage);\n }\n }, 500);\n }, [disabled, loading, paid, getCheckoutUrl, openMode, onSuccess]);\n\n const successStyle: React.CSSProperties = {\n ...DEFAULT_STYLE,\n background: 'linear-gradient(to right, #10B981, #059669)',\n boxShadow: '0 4px 14px rgba(16, 185, 129, 0.25)',\n cursor: 'default',\n };\n\n const buttonStyle: React.CSSProperties = {\n ...DEFAULT_STYLE,\n ...(effectiveButtonBgColor ? { background: effectiveButtonBgColor } : {}),\n ...(isHovered && !disabled && !paid ? HOVER_STYLE : {}),\n ...(disabled ? { opacity: 0.6, cursor: 'not-allowed' as const } : {}),\n };\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={disabled || loading || paid}\n className={className}\n style={className ? undefined : paid ? successStyle : buttonStyle}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {paid ? (\n <>\n <CheckIcon />\n {successText}\n </>\n ) : loading ? (\n <>\n <LoaderIcon />\n Processing...\n </>\n ) : (\n <>\n <PayIcon />\n {buttonText}\n </>\n )}\n </button>\n );\n}\n\nexport function generateEmbedCode(props: Partial<PayButtonProps>): string {\n const { organizationId, amount, buttonBgColor, pageBgColor, callbackUrl, buttonText, checkoutBaseUrl } = props;\n\n const propsStr = [\n `organizationId=\"${organizationId || 'your-org-id'}\"`,\n amount ? `amount={${amount}}` : null,\n buttonBgColor ? `buttonBgColor=\"${buttonBgColor}\"` : null,\n pageBgColor ? `pageBgColor=\"${pageBgColor}\"` : null,\n callbackUrl ? `callbackUrl=\"${callbackUrl}\"` : null,\n buttonText ? `buttonText=\"${buttonText}\"` : null,\n checkoutBaseUrl ? `checkoutBaseUrl=\"${checkoutBaseUrl}\"` : null,\n ]\n .filter(Boolean)\n .join('\\n ');\n\n return `import { PayButton } from '@loofta/pay-sdk';\n\n<PayButton\n ${propsStr}\n onSuccess={(paymentId) => {\n console.log('Payment completed:', paymentId);\n }}\n/>`;\n}\n\nexport function generateScriptEmbed(props: Partial<PayButtonProps>): string {\n const { organizationId, amount, buttonBgColor, pageBgColor, callbackUrl, buttonText, checkoutBaseUrl } = props;\n const base = checkoutBaseUrl || 'https://pay.loofta.xyz';\n\n return `<!-- Loofta Pay Button -->\n<script src=\"${base}/sdk/loofta-pay.js\"></script>\n<div \n id=\"loofta-pay-button\"\n data-organization-id=\"${organizationId || 'your-org-id'}\"\n data-checkout-base-url=\"${base}\"\n ${amount ? `data-amount=\"${amount}\"` : ''}\n ${buttonBgColor ? `data-button-bg-color=\"${buttonBgColor}\"` : ''}\n ${pageBgColor ? `data-page-bg-color=\"${pageBgColor}\"` : ''}\n ${buttonText ? `data-button-text=\"${buttonText}\"` : ''}\n ${callbackUrl ? `data-callback=\"${callbackUrl}\"` : ''}\n></div>\n<script>\n LooftaPay.mount('#loofta-pay-button');\n</script>`;\n}\n\nexport default PayButton;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loofta/pay-sdk",
3
- "version": "1.0.2",
3
+ "version": "1.0.5",
4
4
  "description": "Loofta Pay Button SDK - embeddable payment button that opens Loofta Pay checkout",
5
5
  "author": "Loofta",
6
6
  "license": "MIT",
@@ -14,13 +14,11 @@
14
14
  "require": "./dist/index.js"
15
15
  }
16
16
  },
17
- "files": [
18
- "dist",
19
- "README.md"
20
- ],
17
+ "files": ["dist", "README.md"],
21
18
  "scripts": {
22
19
  "build": "tsup",
23
- "dev": "tsup --watch"
20
+ "dev": "tsup --watch",
21
+ "dev:example": "cd examples/pay-button-demo && npm run dev"
24
22
  },
25
23
  "peerDependencies": {
26
24
  "react": ">=18.0.0"
@@ -33,16 +31,13 @@
33
31
  },
34
32
  "repository": {
35
33
  "type": "git",
36
- "url": "git+https://github.com/loofta/loofta-swap.git"
34
+ "url": "git+https://github.com/loofta/loofta-pay-sdk.git"
37
35
  },
38
- "keywords": [
39
- "loofta",
40
- "pay",
41
- "payment",
42
- "checkout",
43
- "crypto",
44
- "multichain"
45
- ],
36
+ "homepage": "https://pay.loofta.xyz/b2b/demo",
37
+ "bugs": {
38
+ "url": "https://github.com/loofta/loofta-pay-sdk/issues"
39
+ },
40
+ "keywords": ["loofta", "pay", "payment", "checkout", "crypto", "multichain"],
46
41
  "publishConfig": {
47
42
  "access": "public"
48
43
  }