1import { Controller } from "@hotwired/stimulus" 2 3export default class extends Controller { 4 static targets = [ "form" ] 5 static values = { 6 class: {type: String, default: "paddle-billing-checkout"}, 7 customData: String, 8 environment: {type: String, default: "production"}, 9 email: String, 10 transactionId: String, 11 items: Array, 12 clientToken: String, 13 displayMode: {type: String, default: "inline"} 14 } 15 16 async connect() { 17 await this.addScript("https://cdn.paddle.com/paddle/v2/paddle.js") 18 19 // Ensure class for mounting inline checkout is defined 20 this.element.classList.add(this.classValue) 21 22 Paddle.Environment.set(this.environmentValue) 23 Paddle.Initialize({ 24 token: this.clientTokenValue, 25 eventCallback: this.callback.bind(this), 26 checkout: { settings: this.settings } 27 }) 28 29 // Render checkout, otherwise just include the JS to handle ?_ptxn= pages for updating subscriptions 30 if (this.itemsValue.length > 0 || this.transactionId) 31 this.open() 32 } 33 34 disconnect() { 35 delete window.Paddle 36 } 37 38 open() { 39 Paddle.Checkout.open({ 40 customer: { 41 email: this.emailValue 42 }, 43 customData: this.customDataValue, 44 items: this.itemsValue, 45 }); 46 } 47 48 callback(event) { 49 const price = event.data?.recurring_totals 50 if (price) { 51 document.getElementById("recurringTotal").innerHTML = `${price.total} ${event.data.currency_code}` 52 } 53 54 if (event.name == "checkout.completed") { 55 Turbo.visit(`/checkout/return?user_id=${event.data.customer.id}&paddle_billing_transaction_id=${event.data.transaction_id}`) 56 } 57 } 58 59 get settings() { 60 return { 61 allowLogout: false, // Don't allow customer to edit email 62 displayMode: this.displayModeValue, 63 theme: this.theme, 64 frameTarget: this.classValue, 65 frameInitialHeight: 450, 66 frameStyle: 'width:100%; background-color: transparent; border: none;', 67 } 68 } 69 70 get theme() { 71 return document.documentElement.classList.contains("dark") ? "dark" : "light"; 72 } 73 74 addScript(src) { 75 return new Promise((resolve, reject) => { 76 const s = document.createElement('script') 77 78 s.setAttribute('src', src) 79 s.addEventListener('load', resolve) 80 s.addEventListener('error', reject) 81 82 document.body.appendChild(s) 83 }) 84 } 85}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.