@libreapps/checkout 2.0.1
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/.turbo/turbo-build.log +4 -0
- package/CHANGELOG.md +24 -0
- package/LICENSE.md +21 -0
- package/README.md +211 -0
- package/client.ts +318 -0
- package/dist/client.d.ts +80 -0
- package/dist/client.js +229 -0
- package/dist/client.js.map +1 -0
- package/dist/elements/checkout-form.d.ts +14 -0
- package/dist/elements/checkout-form.js +112 -0
- package/dist/elements/checkout-form.js.map +1 -0
- package/dist/elements/index.d.ts +7 -0
- package/dist/elements/index.js +7 -0
- package/dist/elements/index.js.map +1 -0
- package/dist/embed/index.d.ts +6 -0
- package/dist/embed/index.js +7 -0
- package/dist/embed/index.js.map +1 -0
- package/dist/embed/libreapps-checkout.d.ts +32 -0
- package/dist/embed/libreapps-checkout.js +131 -0
- package/dist/embed/libreapps-checkout.js.map +1 -0
- package/dist/hooks/index.d.ts +5 -0
- package/dist/hooks/index.js +5 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/use-checkout.d.ts +42 -0
- package/dist/hooks/use-checkout.js +168 -0
- package/dist/hooks/use-checkout.js.map +1 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +219 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/elements/checkout-form.tsx +543 -0
- package/elements/index.ts +8 -0
- package/embed/index.ts +7 -0
- package/embed/libreapps-checkout.ts +172 -0
- package/hooks/index.ts +6 -0
- package/hooks/use-checkout.tsx +244 -0
- package/index.ts +70 -0
- package/package.json +57 -0
- package/tsconfig.json +15 -0
- package/types.ts +301 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @libreapps/checkout - Embed Script
|
|
3
|
+
*
|
|
4
|
+
* Drop-in checkout button/widget for any website
|
|
5
|
+
* Similar to Stripe's checkout.js
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* <script src="https://js.libreapps.com/checkout.js"></script>
|
|
9
|
+
* <button data-libreapps-checkout data-libreapps-key="pk_live_xxx" data-libreapps-amount="1999" data-libreapps-currency="usd">
|
|
10
|
+
* Pay $19.99
|
|
11
|
+
* </button>
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { LibreAppsCheckout } from '../client'
|
|
15
|
+
import type { CheckoutOptions, CreateSessionParams } from '../types'
|
|
16
|
+
|
|
17
|
+
interface LibreAppsCheckoutEmbed {
|
|
18
|
+
/** Initialize with API key */
|
|
19
|
+
init: (apiKey: string, options?: Partial<CheckoutOptions>) => void
|
|
20
|
+
|
|
21
|
+
/** Create checkout session and redirect */
|
|
22
|
+
checkout: (params: CreateSessionParams) => Promise<void>
|
|
23
|
+
|
|
24
|
+
/** Open checkout in popup */
|
|
25
|
+
popup: (params: CreateSessionParams) => Promise<Window | null>
|
|
26
|
+
|
|
27
|
+
/** Create checkout client */
|
|
28
|
+
createClient: (options: CheckoutOptions) => LibreAppsCheckout
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
declare global {
|
|
32
|
+
interface Window {
|
|
33
|
+
LibreAppsCheckout: LibreAppsCheckoutEmbed
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Global state
|
|
38
|
+
let globalClient: LibreAppsCheckout | null = null
|
|
39
|
+
let globalApiKey: string | null = null
|
|
40
|
+
let globalOptions: Partial<CheckoutOptions> = {}
|
|
41
|
+
|
|
42
|
+
const LibreAppsCheckoutEmbed: LibreAppsCheckoutEmbed = {
|
|
43
|
+
init(apiKey: string, options: Partial<CheckoutOptions> = {}) {
|
|
44
|
+
globalApiKey = apiKey
|
|
45
|
+
globalOptions = options
|
|
46
|
+
globalClient = new LibreAppsCheckout({ apiKey, ...options })
|
|
47
|
+
|
|
48
|
+
// Auto-bind buttons with data attributes
|
|
49
|
+
if (typeof document !== 'undefined') {
|
|
50
|
+
document.addEventListener('DOMContentLoaded', bindCheckoutButtons)
|
|
51
|
+
// Also bind immediately if DOM is ready
|
|
52
|
+
if (document.readyState !== 'loading') {
|
|
53
|
+
bindCheckoutButtons()
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
async checkout(params: CreateSessionParams) {
|
|
59
|
+
if (!globalClient) {
|
|
60
|
+
throw new Error('LibreAppsCheckout not initialized. Call LibreAppsCheckout.init(apiKey) first.')
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const session = await globalClient.createSession(params)
|
|
64
|
+
globalClient.redirectToCheckout(session.id)
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
async popup(params: CreateSessionParams) {
|
|
68
|
+
if (!globalClient) {
|
|
69
|
+
throw new Error('LibreAppsCheckout not initialized. Call LibreAppsCheckout.init(apiKey) first.')
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const session = await globalClient.createSession(params)
|
|
73
|
+
return globalClient.openPopup(session.id)
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
createClient(options: CheckoutOptions) {
|
|
77
|
+
return new LibreAppsCheckout(options)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Bind click handlers to elements with data-libreapps-checkout attribute
|
|
83
|
+
*/
|
|
84
|
+
function bindCheckoutButtons() {
|
|
85
|
+
const buttons = document.querySelectorAll('[data-libreapps-checkout]')
|
|
86
|
+
|
|
87
|
+
buttons.forEach(button => {
|
|
88
|
+
if (button.getAttribute('data-libreapps-bound')) return
|
|
89
|
+
button.setAttribute('data-libreapps-bound', 'true')
|
|
90
|
+
|
|
91
|
+
button.addEventListener('click', async (e) => {
|
|
92
|
+
e.preventDefault()
|
|
93
|
+
|
|
94
|
+
const el = e.currentTarget as HTMLElement
|
|
95
|
+
|
|
96
|
+
// Get config from data attributes
|
|
97
|
+
const apiKey = el.getAttribute('data-libreapps-key') || globalApiKey
|
|
98
|
+
if (!apiKey) {
|
|
99
|
+
console.error('LibreAppsCheckout: No API key provided')
|
|
100
|
+
return
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Parse line items from data attributes
|
|
104
|
+
const amount = parseInt(el.getAttribute('data-libreapps-amount') || '0', 10)
|
|
105
|
+
const currency = el.getAttribute('data-libreapps-currency') || 'usd'
|
|
106
|
+
const name = el.getAttribute('data-libreapps-name') || 'Purchase'
|
|
107
|
+
const description = el.getAttribute('data-libreapps-description') || undefined
|
|
108
|
+
const imageUrl = el.getAttribute('data-libreapps-image') || undefined
|
|
109
|
+
const productId = el.getAttribute('data-libreapps-product') || undefined
|
|
110
|
+
const sku = el.getAttribute('data-libreapps-sku') || undefined
|
|
111
|
+
const quantity = parseInt(el.getAttribute('data-libreapps-quantity') || '1', 10)
|
|
112
|
+
|
|
113
|
+
// Success/cancel URLs
|
|
114
|
+
const successUrl = el.getAttribute('data-libreapps-success-url') || undefined
|
|
115
|
+
const cancelUrl = el.getAttribute('data-libreapps-cancel-url') || undefined
|
|
116
|
+
|
|
117
|
+
// Popup mode
|
|
118
|
+
const usePopup = el.hasAttribute('data-libreapps-popup')
|
|
119
|
+
|
|
120
|
+
// Create or use existing client
|
|
121
|
+
const client = globalClient || new LibreAppsCheckout({
|
|
122
|
+
apiKey,
|
|
123
|
+
...globalOptions
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
// Disable button
|
|
128
|
+
el.setAttribute('disabled', 'true')
|
|
129
|
+
const originalText = el.textContent
|
|
130
|
+
el.textContent = 'Loading...'
|
|
131
|
+
|
|
132
|
+
const session = await client.createSession({
|
|
133
|
+
lineItems: [{
|
|
134
|
+
productId,
|
|
135
|
+
sku,
|
|
136
|
+
name,
|
|
137
|
+
description,
|
|
138
|
+
imageUrl,
|
|
139
|
+
quantity,
|
|
140
|
+
unitPrice: amount,
|
|
141
|
+
currency
|
|
142
|
+
}],
|
|
143
|
+
successUrl,
|
|
144
|
+
cancelUrl,
|
|
145
|
+
currency
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
if (usePopup) {
|
|
149
|
+
client.openPopup(session.id)
|
|
150
|
+
el.removeAttribute('disabled')
|
|
151
|
+
el.textContent = originalText
|
|
152
|
+
} else {
|
|
153
|
+
client.redirectToCheckout(session.id)
|
|
154
|
+
}
|
|
155
|
+
} catch (error) {
|
|
156
|
+
console.error('LibreAppsCheckout error:', error)
|
|
157
|
+
el.removeAttribute('disabled')
|
|
158
|
+
el.textContent = 'Error - Try Again'
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Export for bundler usage
|
|
165
|
+
export { LibreAppsCheckoutEmbed }
|
|
166
|
+
|
|
167
|
+
// Attach to window for script tag usage
|
|
168
|
+
if (typeof window !== 'undefined') {
|
|
169
|
+
window.LibreAppsCheckout = LibreAppsCheckoutEmbed
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export default LibreAppsCheckoutEmbed
|
package/hooks/index.ts
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @libreapps/checkout - useCheckout hook
|
|
5
|
+
*
|
|
6
|
+
* React hook for managing checkout state
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { useState, useCallback, useEffect, createContext, useContext } from 'react'
|
|
10
|
+
import type { ReactNode } from 'react'
|
|
11
|
+
import { LibreAppsCheckout } from '../client'
|
|
12
|
+
import type {
|
|
13
|
+
CheckoutOptions,
|
|
14
|
+
CheckoutSession,
|
|
15
|
+
CheckoutState,
|
|
16
|
+
CheckoutStep,
|
|
17
|
+
CheckoutAddress,
|
|
18
|
+
CheckoutResult,
|
|
19
|
+
CheckoutError,
|
|
20
|
+
CreateSessionParams
|
|
21
|
+
} from '../types'
|
|
22
|
+
|
|
23
|
+
interface CheckoutContextValue extends CheckoutState {
|
|
24
|
+
/** Checkout client instance */
|
|
25
|
+
checkout: LibreAppsCheckout | null
|
|
26
|
+
|
|
27
|
+
/** Create a new session */
|
|
28
|
+
createSession: (params: CreateSessionParams) => Promise<CheckoutSession>
|
|
29
|
+
|
|
30
|
+
/** Load existing session */
|
|
31
|
+
loadSession: (sessionId: string) => Promise<CheckoutSession>
|
|
32
|
+
|
|
33
|
+
/** Update shipping address */
|
|
34
|
+
updateShipping: (address: CheckoutAddress) => Promise<void>
|
|
35
|
+
|
|
36
|
+
/** Update billing address */
|
|
37
|
+
updateBilling: (address: CheckoutAddress) => Promise<void>
|
|
38
|
+
|
|
39
|
+
/** Apply promo code */
|
|
40
|
+
applyPromo: (code: string) => Promise<void>
|
|
41
|
+
|
|
42
|
+
/** Confirm payment */
|
|
43
|
+
confirmPayment: (paymentMethod: Parameters<LibreAppsCheckout['confirmPayment']>[1]) => Promise<CheckoutResult>
|
|
44
|
+
|
|
45
|
+
/** Cancel checkout */
|
|
46
|
+
cancel: () => Promise<void>
|
|
47
|
+
|
|
48
|
+
/** Go to step */
|
|
49
|
+
goToStep: (step: CheckoutStep) => void
|
|
50
|
+
|
|
51
|
+
/** Go to next step */
|
|
52
|
+
nextStep: () => void
|
|
53
|
+
|
|
54
|
+
/** Go to previous step */
|
|
55
|
+
prevStep: () => void
|
|
56
|
+
|
|
57
|
+
/** Redirect to hosted checkout */
|
|
58
|
+
redirectToHosted: () => void
|
|
59
|
+
|
|
60
|
+
/** Open popup checkout */
|
|
61
|
+
openPopup: () => Window | null
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const CheckoutContext = createContext<CheckoutContextValue | null>(null)
|
|
65
|
+
|
|
66
|
+
const STEP_ORDER: CheckoutStep[] = ['cart', 'shipping', 'payment', 'confirmation']
|
|
67
|
+
|
|
68
|
+
export interface CheckoutProviderProps {
|
|
69
|
+
/** Checkout options */
|
|
70
|
+
options: CheckoutOptions
|
|
71
|
+
|
|
72
|
+
/** Initial session ID to load */
|
|
73
|
+
sessionId?: string
|
|
74
|
+
|
|
75
|
+
/** Children */
|
|
76
|
+
children: ReactNode
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function CheckoutProvider({ options, sessionId, children }: CheckoutProviderProps) {
|
|
80
|
+
const [checkout] = useState(() => new LibreAppsCheckout(options))
|
|
81
|
+
const [state, setState] = useState<CheckoutState>({
|
|
82
|
+
step: 'cart',
|
|
83
|
+
session: null,
|
|
84
|
+
isLoading: false,
|
|
85
|
+
error: null,
|
|
86
|
+
isProcessing: false
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
// Load session on mount if sessionId provided
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
if (sessionId) {
|
|
92
|
+
loadSession(sessionId)
|
|
93
|
+
}
|
|
94
|
+
}, [sessionId])
|
|
95
|
+
|
|
96
|
+
const createSession = useCallback(async (params: CreateSessionParams) => {
|
|
97
|
+
setState(s => ({ ...s, isLoading: true, error: null }))
|
|
98
|
+
try {
|
|
99
|
+
const session = await checkout.createSession(params)
|
|
100
|
+
setState(s => ({ ...s, session, isLoading: false }))
|
|
101
|
+
return session
|
|
102
|
+
} catch (err) {
|
|
103
|
+
const error = err as CheckoutError
|
|
104
|
+
setState(s => ({ ...s, error, isLoading: false }))
|
|
105
|
+
throw error
|
|
106
|
+
}
|
|
107
|
+
}, [checkout])
|
|
108
|
+
|
|
109
|
+
const loadSession = useCallback(async (id: string) => {
|
|
110
|
+
setState(s => ({ ...s, isLoading: true, error: null }))
|
|
111
|
+
try {
|
|
112
|
+
const session = await checkout.retrieveSession(id)
|
|
113
|
+
setState(s => ({ ...s, session, isLoading: false }))
|
|
114
|
+
return session
|
|
115
|
+
} catch (err) {
|
|
116
|
+
const error = err as CheckoutError
|
|
117
|
+
setState(s => ({ ...s, error, isLoading: false }))
|
|
118
|
+
throw error
|
|
119
|
+
}
|
|
120
|
+
}, [checkout])
|
|
121
|
+
|
|
122
|
+
const updateShipping = useCallback(async (address: CheckoutAddress) => {
|
|
123
|
+
if (!state.session) throw new Error('No session')
|
|
124
|
+
setState(s => ({ ...s, isLoading: true, error: null }))
|
|
125
|
+
try {
|
|
126
|
+
const session = await checkout.updateShipping(state.session.id, address)
|
|
127
|
+
setState(s => ({ ...s, session, isLoading: false }))
|
|
128
|
+
} catch (err) {
|
|
129
|
+
const error = err as CheckoutError
|
|
130
|
+
setState(s => ({ ...s, error, isLoading: false }))
|
|
131
|
+
throw error
|
|
132
|
+
}
|
|
133
|
+
}, [checkout, state.session])
|
|
134
|
+
|
|
135
|
+
const updateBilling = useCallback(async (address: CheckoutAddress) => {
|
|
136
|
+
if (!state.session) throw new Error('No session')
|
|
137
|
+
setState(s => ({ ...s, isLoading: true, error: null }))
|
|
138
|
+
try {
|
|
139
|
+
const session = await checkout.updateBilling(state.session.id, address)
|
|
140
|
+
setState(s => ({ ...s, session, isLoading: false }))
|
|
141
|
+
} catch (err) {
|
|
142
|
+
const error = err as CheckoutError
|
|
143
|
+
setState(s => ({ ...s, error, isLoading: false }))
|
|
144
|
+
throw error
|
|
145
|
+
}
|
|
146
|
+
}, [checkout, state.session])
|
|
147
|
+
|
|
148
|
+
const applyPromo = useCallback(async (code: string) => {
|
|
149
|
+
if (!state.session) throw new Error('No session')
|
|
150
|
+
setState(s => ({ ...s, isLoading: true, error: null }))
|
|
151
|
+
try {
|
|
152
|
+
const session = await checkout.applyPromoCode(state.session.id, code)
|
|
153
|
+
setState(s => ({ ...s, session, isLoading: false }))
|
|
154
|
+
} catch (err) {
|
|
155
|
+
const error = err as CheckoutError
|
|
156
|
+
setState(s => ({ ...s, error, isLoading: false }))
|
|
157
|
+
throw error
|
|
158
|
+
}
|
|
159
|
+
}, [checkout, state.session])
|
|
160
|
+
|
|
161
|
+
const confirmPayment = useCallback(async (paymentMethod: Parameters<LibreAppsCheckout['confirmPayment']>[1]) => {
|
|
162
|
+
if (!state.session) throw new Error('No session')
|
|
163
|
+
setState(s => ({ ...s, isProcessing: true, error: null }))
|
|
164
|
+
try {
|
|
165
|
+
const result = await checkout.confirmPayment(state.session.id, paymentMethod)
|
|
166
|
+
setState(s => ({ ...s, isProcessing: false, step: 'confirmation' }))
|
|
167
|
+
return result
|
|
168
|
+
} catch (err) {
|
|
169
|
+
const error = err as CheckoutError
|
|
170
|
+
setState(s => ({ ...s, error, isProcessing: false }))
|
|
171
|
+
throw error
|
|
172
|
+
}
|
|
173
|
+
}, [checkout, state.session])
|
|
174
|
+
|
|
175
|
+
const cancel = useCallback(async () => {
|
|
176
|
+
if (!state.session) return
|
|
177
|
+
await checkout.cancelSession(state.session.id)
|
|
178
|
+
setState(s => ({ ...s, session: null, step: 'cart' }))
|
|
179
|
+
}, [checkout, state.session])
|
|
180
|
+
|
|
181
|
+
const goToStep = useCallback((step: CheckoutStep) => {
|
|
182
|
+
setState(s => ({ ...s, step }))
|
|
183
|
+
}, [])
|
|
184
|
+
|
|
185
|
+
const nextStep = useCallback(() => {
|
|
186
|
+
const currentIndex = STEP_ORDER.indexOf(state.step)
|
|
187
|
+
if (currentIndex < STEP_ORDER.length - 1) {
|
|
188
|
+
setState(s => ({ ...s, step: STEP_ORDER[currentIndex + 1] }))
|
|
189
|
+
}
|
|
190
|
+
}, [state.step])
|
|
191
|
+
|
|
192
|
+
const prevStep = useCallback(() => {
|
|
193
|
+
const currentIndex = STEP_ORDER.indexOf(state.step)
|
|
194
|
+
if (currentIndex > 0) {
|
|
195
|
+
setState(s => ({ ...s, step: STEP_ORDER[currentIndex - 1] }))
|
|
196
|
+
}
|
|
197
|
+
}, [state.step])
|
|
198
|
+
|
|
199
|
+
const redirectToHosted = useCallback(() => {
|
|
200
|
+
if (state.session) {
|
|
201
|
+
checkout.redirectToCheckout(state.session.id)
|
|
202
|
+
}
|
|
203
|
+
}, [checkout, state.session])
|
|
204
|
+
|
|
205
|
+
const openPopup = useCallback(() => {
|
|
206
|
+
if (state.session) {
|
|
207
|
+
return checkout.openPopup(state.session.id)
|
|
208
|
+
}
|
|
209
|
+
return null
|
|
210
|
+
}, [checkout, state.session])
|
|
211
|
+
|
|
212
|
+
const value: CheckoutContextValue = {
|
|
213
|
+
...state,
|
|
214
|
+
checkout,
|
|
215
|
+
createSession,
|
|
216
|
+
loadSession,
|
|
217
|
+
updateShipping,
|
|
218
|
+
updateBilling,
|
|
219
|
+
applyPromo,
|
|
220
|
+
confirmPayment,
|
|
221
|
+
cancel,
|
|
222
|
+
goToStep,
|
|
223
|
+
nextStep,
|
|
224
|
+
prevStep,
|
|
225
|
+
redirectToHosted,
|
|
226
|
+
openPopup
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return (
|
|
230
|
+
<CheckoutContext.Provider value={value}>
|
|
231
|
+
{children}
|
|
232
|
+
</CheckoutContext.Provider>
|
|
233
|
+
)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export function useCheckout(): CheckoutContextValue {
|
|
237
|
+
const context = useContext(CheckoutContext)
|
|
238
|
+
if (!context) {
|
|
239
|
+
throw new Error('useCheckout must be used within a CheckoutProvider')
|
|
240
|
+
}
|
|
241
|
+
return context
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export default useCheckout
|
package/index.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @libreapps/checkout
|
|
3
|
+
*
|
|
4
|
+
* Embeddable checkout widget for LibreApps Commerce
|
|
5
|
+
* Similar to Stripe Checkout
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
*
|
|
9
|
+
* 1. React Integration:
|
|
10
|
+
* ```tsx
|
|
11
|
+
* import { CheckoutProvider, CheckoutForm, useCheckout } from '@libreapps/checkout'
|
|
12
|
+
*
|
|
13
|
+
* function App() {
|
|
14
|
+
* return (
|
|
15
|
+
* <CheckoutProvider options={{ apiKey: 'pk_live_xxx' }}>
|
|
16
|
+
* <CheckoutForm />
|
|
17
|
+
* </CheckoutProvider>
|
|
18
|
+
* )
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* 2. Vanilla JS / Redirect:
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { createCheckout } from '@libreapps/checkout'
|
|
25
|
+
*
|
|
26
|
+
* const checkout = createCheckout({ apiKey: 'pk_live_xxx' })
|
|
27
|
+
* const session = await checkout.createSession({
|
|
28
|
+
* lineItems: [{ name: 'Product', unitPrice: 1999, quantity: 1 }]
|
|
29
|
+
* })
|
|
30
|
+
* checkout.redirectToCheckout(session.id)
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* 3. Embed Script (no build step):
|
|
34
|
+
* ```html
|
|
35
|
+
* <script src="https://js.libreapps.com/checkout.js"></script>
|
|
36
|
+
* <button data-libreapps-checkout data-libreapps-key="pk_live_xxx" data-libreapps-amount="1999">
|
|
37
|
+
* Pay $19.99
|
|
38
|
+
* </button>
|
|
39
|
+
* <script>
|
|
40
|
+
* LibreAppsCheckout.init('pk_live_xxx')
|
|
41
|
+
* </script>
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
// Types
|
|
46
|
+
export type {
|
|
47
|
+
CheckoutOptions,
|
|
48
|
+
CheckoutAppearance,
|
|
49
|
+
CheckoutSession,
|
|
50
|
+
CheckoutLineItem,
|
|
51
|
+
CheckoutCustomer,
|
|
52
|
+
CheckoutAddress,
|
|
53
|
+
CheckoutPaymentMethod,
|
|
54
|
+
CheckoutResult,
|
|
55
|
+
CheckoutError,
|
|
56
|
+
CreateSessionParams,
|
|
57
|
+
ElementsOptions,
|
|
58
|
+
CheckoutStep,
|
|
59
|
+
CheckoutState
|
|
60
|
+
} from './types'
|
|
61
|
+
|
|
62
|
+
// Client
|
|
63
|
+
export { LibreAppsCheckout, createCheckout } from './client'
|
|
64
|
+
|
|
65
|
+
// Hooks
|
|
66
|
+
export { CheckoutProvider, useCheckout } from './hooks'
|
|
67
|
+
export type { CheckoutProviderProps } from './hooks'
|
|
68
|
+
|
|
69
|
+
// Elements
|
|
70
|
+
export { CheckoutForm } from './elements'
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@libreapps/checkout",
|
|
3
|
+
"version": "2.0.1",
|
|
4
|
+
"description": "Embeddable checkout widget for LibreApps Commerce - Stripe-like checkout experience",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"registry": "https://registry.npmjs.org/",
|
|
7
|
+
"access": "public",
|
|
8
|
+
"scope": "@libreapps"
|
|
9
|
+
},
|
|
10
|
+
"author": "LibreApps Contributors",
|
|
11
|
+
"license": "BSD-3-Clause",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/libre-apps/UI.git",
|
|
15
|
+
"directory": "pkg/checkout"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"checkout",
|
|
19
|
+
"payments",
|
|
20
|
+
"commerce",
|
|
21
|
+
"ecommerce",
|
|
22
|
+
"libreapps",
|
|
23
|
+
"libreapps",
|
|
24
|
+
"stripe",
|
|
25
|
+
"widget"
|
|
26
|
+
],
|
|
27
|
+
"main": "index.ts",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": "./index.ts",
|
|
30
|
+
"./embed": "./embed/index.ts",
|
|
31
|
+
"./elements": "./elements/index.ts",
|
|
32
|
+
"./hooks": "./hooks/index.ts"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"lucide-react": ">=0.456.0",
|
|
37
|
+
"mobx": "^6.12.3",
|
|
38
|
+
"mobx-react-lite": "^4.0.7",
|
|
39
|
+
"next": ">=14.2.16",
|
|
40
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
41
|
+
"react-dom": "^18.0.0 || ^19.0.0",
|
|
42
|
+
"@libreapps/auth": "3.0.1",
|
|
43
|
+
"@libreapps/commerce": "7.5.1",
|
|
44
|
+
"@libreapps/ui": "5.4.1"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/react": "^19.0.0",
|
|
48
|
+
"@types/react-dom": "^19.0.0",
|
|
49
|
+
"typescript": "5.6.3"
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"lat": "npm show @libreapps/checkout version",
|
|
53
|
+
"pub": "npm publish",
|
|
54
|
+
"tc": "tsc",
|
|
55
|
+
"build": "tsc --outDir dist --declaration --emitDeclarationOnly false --module ESNext --esModuleInterop true --skipLibCheck true --sourceMap true"
|
|
56
|
+
}
|
|
57
|
+
}
|