diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 48bfc9a..263b0c3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,33 +1,35 @@
name: Vue Stripe.js CI
-on: [push, pull_request]
+on:
+ pull_request:
+ push:
+ branches:
+ - main
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
jobs:
- build:
+ ci:
runs-on: ubuntu-latest
- strategy:
- matrix:
- node-version: [16.x]
-
steps:
- - uses: actions/checkout@v2
-
- - name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v2
+ - uses: actions/checkout@v4
+
+ - name: Install pnpm
+ uses: pnpm/action-setup@v4
with:
- node-version: ${{ matrix.node-version }}
+ version: 9
- - name: Cache NPM
- uses: actions/cache@v2
+ - name: Use Node.js
+ uses: actions/setup-node@v4
with:
- path: ~/.npm
- key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
- restore-keys: |
- ${{ runner.os }}-node-
+ node-version: 20
+ cache: 'pnpm'
- name: Install dependencies
- run: yarn
+ run: pnpm install
- - name: Unit Tests
- run: yarn test
+ - name: Run CI
+ run: pnpm run ci
diff --git a/.gitignore b/.gitignore
index d70bb9c..a547bf3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
node_modules
dist
-.DS_Store
+dist-ssr
*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..a7cea0b
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,3 @@
+{
+ "recommendations": ["Vue.volar"]
+}
diff --git a/LICENSE b/LICENSE
index 1d4e7c8..9106f53 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,21 +1,20 @@
MIT License
-Copyright (c) 2021 Oleksandr Bystrikov
+Copyright (c) 2021 - present, Oleksandr Bystrikov
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
index 206ad8d..f5c39d9 100644
--- a/README.md
+++ b/README.md
@@ -1,338 +1,218 @@
-[](https://vshymanskyy.github.io/StandWithUkraine)
-
# Vue Stripe.js
-### [**Become a sponsor** 💜](https://github.com/sponsors/softbeehive)
[](https://github.com/ectoflow/vue-stripe-js/actions)
[](https://www.npmjs.com/package/vue-stripe-js)
[](https://bundlephobia.com/result?p=vue-stripe-js)
[](https://www.npmjs.com/package/vue-stripe-js)
+[](https://vshymanskyy.github.io/StandWithUkraine)
-Flexible and powerful Vue 3 components for Stripe. It's a glue between
-[Stripe.js](https://stripe.com/docs/js) and Vue component lifecycle.
+Vue 3 components for Stripe. Build advanced payment integrations quickly. Easy to start, friendly DX, minimal abstractions, and full control. It's a glue between Stripe.js and Vue component lifecycle.
-# Quickstart
-
-### 1. Install
-
-**npm**
-
-```bash
-npm i vue-stripe-js @stripe/stripe-js
-```
+### [**Become a sponsor** 💜](https://github.com/sponsors/softbeehive)
+Consider supporting efforts to make this project healthy and sustainable. Thank you!
-**yarn**
+## Quickstart ⚡️
-```bash
-yarn add vue-stripe-js @stripe/stripe-js
-```
+### Upgrade
+• [**Upgrade guide**](docs/UPGRADE_V1_TO_V2.md)
+• **[Docs v1](https://github.com/ectoflow/vue-stripe-js/tree/v1.0.4)**
-**pnpm**
+### 1. Install
```bash
-pnpm add vue-stripe-js @stripe/stripe-js
+npm i vue-stripe-js @stripe/stripe-js
```
### 2. Load Stripe.js
-```ts
+```vue
+
```
-> Alternatively, you can load Stripe library by including script tag. Just make
-> sure it's ready before your stripe components mount.
+Alternatively, include a script tag. Make sure Stripe.js is loaded before you mount Vue components.
-```
+```html
```
-### 3. Card payment (default)
+### 3. Payment Element
+
+Based on – [deferred payment guide](https://docs.stripe.com/payments/accept-a-payment-deferred?type=payment)
```vue
-
-
-
-
+
+
+
+
+
-
-```
+const paymentElementOptions = ref({
+ // https://docs.stripe.com/js/elements_object/create_payment_element#payment_element_create-options
+})
+const stripeLoaded = ref(false)
+const clientSecret = ref("")
-### 4. Payment element (requires backend)
+// Define component refs
+const elementsComponent = ref()
+const paymentComponent = ref()
-1. Add server code by following
- [stripe guide](https://docs.stripe.com/payments/quickstart?lang=node)
-1. Grab `clientSecret` from the payment intent
-1. Pass it to `elements-options`
+onBeforeMount(() => {
+ loadStripe(stripeKey.value).then(() => {
+ stripeLoaded.value = true
-```vue
-
-
-
-
-
-```
+ // Good place to call your backend to create PaymentIntent
+ // Skipping to the point when you got client_secret
-```ts
-const elementsOptions = ref({
- clientSecret: "grab_it_from_payment_intent",
- // https://stripe.com/docs/js/elements_object/create#stripe_elements-options
+ // clientSecret.value = client_secret
+ })
})
-```
-#### It works!
-
-
+async function handleSubmit() {
+ // Confirm the PaymentIntent using the details collected by the Payment Element
+ const stripeInstance = elementsComponent.value?.instance
+ const elements = elementsComponent.value?.elements
+
+ if (stripeInstance) {
+ const { error } = await stripeInstance.confirmPayment({
+ elements,
+ clientSecret: clientSecret.value,
+ confirmParams: {
+ return_url: "https://example.com/order/123/complete",
+ },
+ })
-### 5. Use elements like lego
+ if (error) {
+ // This point is only reached if there's an immediate error when
+ // confirming the payment. Show the error to your customer (for example, payment details incomplete)
+ console.log(error)
+ } else {
+ // Your customer is redirected to your `return_url`. For some payment
+ // methods like iDEAL, your customer is redirected to an intermediate
+ // site first to authorize the payment, then redirected to the `return_url`.
+ }
+ }
+}
+
-```vue
-
-
-
-
```
-# Types
+## Examples 🌿
-```ts
-import types {
- initStripe,
- createElements,
- createElement,
- StripeElements,
- StripeElement
-} from 'vue-stripe-js'
-```
+Thanks to the Provider Pattern used in StripeElements, you get minimalist tools with full access to Stripe.js methods and properties. This results in better developer experience (DX), simpler code, and fewer bugs.
-# API Reference
+These examples use Vue Composition API and TypeScript.
-## StripeElements.vue
+- [All](examples/)
+- [Payment](examples/PaymentElementDeferred.vue)
+- [Card](examples/CardElement.vue)
+- [Express Checkout](examples/ExpressCheckoutElement.vue)
-Think of it as of individual group of elements. It creates stripe instance and
-elements object.
+### Screenshot
-```js
-import { StripeElements } from "vue-stripe-js"
-```
+
-### props
-
-```js
-// https://stripe.com/docs/js/initializing#init_stripe_js-options
-stripeKey: {
- type: String,
- required: true,
-},
-// https://stripe.com/docs/js/elements_object/create#stripe_elements-options
-instanceOptions: {
- type: Object,
- default: () => ({}),
-},
-// https://stripe.com/docs/stripe.js#element-options
-elementsOptions: {
- type: Object,
- default: () => ({}),
-},
-```
+## Advanced integration 🏗️
-### data
+All features of Stripe.js are available in two components. The benefits of Vue solution: element is created and destroyed automatically, options are reactive, event listeners are attached to StripeElement. Simple and future-proof.
-You can access `instance` and `elements` by adding ref to StripeElements
-component.
+🥇 **Most important property is type** 🥇
-```js
-// StripeElements.vue exposes
-{
- elements,
- instance,
- elementsUsable,
-}
-```
-
-### default scoped slot
-
-Elegant solution for props. Really handy because you can make stripe `instance`
-and `elements` objects available to all children without adding extra code.
-
-```vue
-
-
-
-
+```html
+
+
```
-## StripeElement.vue
-
-Universal and type agnostic component. Create any element supported by Stripe.
-
-```js
-import { StripeElement } from "vue-stripe-js"
-```
-
-### props
-
-```js
-{
- // elements object
- // https://stripe.com/docs/js/elements_object/create
- elements: {
- type: Object as () => StripeElementsWithoutOverload,
- required: true,
- },
- // type of the element
- // https://stripe.com/docs/js/elements_object/create_element?type=card
- type: {
- type: String as () => StripeElementType,
- default: () => 'card',
- },
- // element options
- // https://stripe.com/docs/js/elements_object/create_element?type=card#elements_create-options
- options: {
- type: Object as () => StripeElementOptions,
- default: () => ({}),
- },
-},
-```
-
-### data
-
-```js
-{
- stripeElement,
- domElement,
- mountPoint,
-}
-```
-
-### options
-
-Element options are reactive. Recommendation: don't use v-model on
-`StripeElement`, instead pass value via options.
+Available types
+```ts
+type StripeElementType =
+ | 'address'
+ | 'affirmMessage'
+ | 'afterpayClearpayMessage'
+ | 'auBankAccount'
+ | 'card'
+ | 'cardNumber'
+ | 'cardExpiry'
+ | 'cardCvc'
+ | 'currencySelector'
+ | 'epsBank'
+ | 'expressCheckout'
+ | 'fpxBank'
+ | 'iban'
+ | 'idealBank'
+ | 'p24Bank'
+ | 'payment'
+ | 'paymentMethodMessaging'
+ | 'paymentRequestButton'
+ | 'linkAuthentication'
+ | 'shippingAddress'
+ | 'issuingCardNumberDisplay'
+ | 'issuingCardCvcDisplay'
+ | 'issuingCardExpiryDisplay'
+ | 'issuingCardPinDisplay'
+ | 'issuingCardCopyButton'
+
+// Check actual element types in @stripe/stripe-js
+```
+
+## Events
-```js
-setup() {
- const elementOptions = ref({
- value: {
- postalCode: '12345'
- }
- })
-
- const changePostalCode = (postalCode) => {
- elementOptions.value.postalCode = postalCode
- }
-},
+```html
+
```
-
-### events
-
Following events are emitted on StripeElement
- change
@@ -341,12 +221,31 @@ Following events are emitted on StripeElement
- blur
- click
- escape
+- loaderror
+- loaderstart
+
+
+## Styling
+
+Add classes to components
```html
-
+
+
+
```
-# Styles
+Style element via options - [read documentation](https://stripe.com/docs/js/appendix/style)
-No base style included. Main reason: overriding it isn't fun. Style as you wish
-via element options: [see details](https://stripe.com/docs/js/appendix/style).
+```ts
+const cardOptions = ref({
+ style: {
+ base: {
+ iconColor: "green",
+ },
+ invalid: {
+ iconColor: "red",
+ },
+ },
+})
+```
diff --git a/babel.config.js b/babel.config.js
deleted file mode 100644
index ca0b4ba..0000000
--- a/babel.config.js
+++ /dev/null
@@ -1,7 +0,0 @@
-module.exports = {
- env: {
- test: {
- presets: ['@babel/preset-env', '@babel/preset-typescript'],
- },
- },
-}
diff --git a/biome.json b/biome.json
new file mode 100644
index 0000000..7fec8e7
--- /dev/null
+++ b/biome.json
@@ -0,0 +1,39 @@
+{
+ "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
+ "vcs": {
+ "enabled": false,
+ "clientKind": "git",
+ "useIgnoreFile": false
+ },
+ "files": {
+ "ignoreUnknown": false,
+ "ignore": ["dist"]
+ },
+ "formatter": {
+ "enabled": true,
+ "indentStyle": "space",
+ "indentWidth": 2,
+ "lineWidth": 80
+ },
+ "organizeImports": {
+ "enabled": true
+ },
+ "linter": {
+ "enabled": true,
+ "rules": {
+ "recommended": true
+ }
+ },
+ "javascript": {
+ "formatter": {
+ "jsxQuoteStyle": "double",
+ "quoteProperties": "asNeeded",
+ "semicolons": "asNeeded",
+ "arrowParentheses": "always",
+ "bracketSpacing": true,
+ "bracketSameLine": false,
+ "quoteStyle": "double",
+ "attributePosition": "multiline"
+ }
+ }
+}
diff --git a/deno.json b/deno.json
deleted file mode 100644
index 3d2db59..0000000
--- a/deno.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "fmt": {
- "lineWidth": 80,
- "indentWidth": 2,
- "semiColons": false
- }
-}
-
diff --git a/docs/UPGRADE_V1_TO_V2.md b/docs/UPGRADE_V1_TO_V2.md
new file mode 100644
index 0000000..679803d
--- /dev/null
+++ b/docs/UPGRADE_V1_TO_V2.md
@@ -0,0 +1,53 @@
+# Upgrade guide
+
+Upgrading your Vue Stripe.js from v1 to v2.
+
+v2.0.0 is a major update that introduces changes in default choices due to the evolution of Stripe.js. It was designed with stability in mind, ensuring that your upgrade should be smooth and simple.
+
+## Breaking changes
+
+ES modules are the de facto standard. Vite is expected to drop CommonJS support in 2025. Do not upgrade if you are using "require" instead of "import."
+
+- Added npm type module
+- Removed CommonJS export
+
+## Features
+
+- Backward-compatible; old implementations should work seamlessly
+- Payment Element is the new default
+- Improved TypeScript support
+- Added new examples for Payment, Card, and Express Checkout
+
+## Upgrade
+
+### Install new version
+```bash
+npm install vue-stripe-js@latest
+```
+
+Test your integration. Major upgrade is finished 🎉
+
+## Optional changes
+
+### Provide explicit type to StripeElement
+
+```diff
+
+-
++
+
+```
+
+### Remove slot props
+Not needed thanks to provide/inject behind the hood
+
+```diff
+
+
+
+```
diff --git a/examples/CardElement.vue b/examples/CardElement.vue
new file mode 100644
index 0000000..75119d1
--- /dev/null
+++ b/examples/CardElement.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
diff --git a/examples/CardOnly.vue b/examples/CardElementLegacy.vue
similarity index 55%
rename from examples/CardOnly.vue
rename to examples/CardElementLegacy.vue
index 71915f5..705a285 100644
--- a/examples/CardOnly.vue
+++ b/examples/CardElementLegacy.vue
@@ -2,24 +2,35 @@
-
+
-
+
diff --git a/examples/ExpressCheckoutElement.vue b/examples/ExpressCheckoutElement.vue
new file mode 100644
index 0000000..e574762
--- /dev/null
+++ b/examples/ExpressCheckoutElement.vue
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
diff --git a/examples/PaymentElementDeferred.vue b/examples/PaymentElementDeferred.vue
new file mode 100644
index 0000000..1aa9c28
--- /dev/null
+++ b/examples/PaymentElementDeferred.vue
@@ -0,0 +1,100 @@
+
+
+
+
+
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 0000000..ffd07d5
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,27 @@
+# Vue Stripe.js
+
+Full power of Stripe.js + beauty of Vue. Build advanced payment integrations quickly. Use examples for easy start with Payment, Card, and Express Checkout.
+
+## Demo
+
+**1. Clone**
+```bash
+git clone git@github.com:ectoflow/vue-stripe-js.git --depth=1 && cd vue-stripe-js
+```
+
+**2. Install**
+
+```bash
+npm install
+```
+
+**3. Run demo**
+```bash
+npm run dev
+```
+
+## Donate
+
+It's an open-source project and completely free to use. Keeping it up-to-date with the Stripe.js API is hard work. Consider supporting my efforts to make vue-stripe-js healthy and sustainable. Thank you!
+
+[**Become a sponsor** 💜](https://github.com/sponsors/softbeehive)
diff --git a/examples/demo.ts b/examples/demo.ts
deleted file mode 100644
index 7e64937..0000000
--- a/examples/demo.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { createApp } from 'vue'
-import CardOnly from './CardOnly.vue'
-
-const app = createApp(CardOnly)
-app.mount('#app')
diff --git a/examples/demo/demo.ts b/examples/demo/demo.ts
new file mode 100644
index 0000000..17af00c
--- /dev/null
+++ b/examples/demo/demo.ts
@@ -0,0 +1,5 @@
+import { createApp } from "vue"
+import DemoApp from "../DemoApp.vue"
+
+const app = createApp(DemoApp)
+app.mount("#app")
diff --git a/examples/demo/demo_screenshort.png b/examples/demo/demo_screenshort.png
new file mode 100644
index 0000000..056cfd4
Binary files /dev/null and b/examples/demo/demo_screenshort.png differ
diff --git a/examples/demo/index.css b/examples/demo/index.css
new file mode 100644
index 0000000..f1d8c73
--- /dev/null
+++ b/examples/demo/index.css
@@ -0,0 +1 @@
+@import "tailwindcss";
diff --git a/index.html b/index.html
index 78c7010..2ab3683 100644
--- a/index.html
+++ b/index.html
@@ -3,10 +3,11 @@
- Try Vue Stripe
+
+ Vue Stripe.js
-
+