Skip to content

Commit 10c4f48

Browse files
committed
feat: implement provide/inject using composition api
1 parent 3107336 commit 10c4f48

File tree

5 files changed

+214
-224
lines changed

5 files changed

+214
-224
lines changed

src/components/StripeElement.vue

Lines changed: 74 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -2,106 +2,95 @@
22
<div ref="mountPoint"></div>
33
</template>
44

5-
<script lang="ts">
6-
import type { StripeElementType } from '@stripe/stripe-js'
7-
import type {
8-
StripeElementsWithoutOverload,
9-
StripeElementOptions,
10-
} from '../../types/vue-stripe'
11-
12-
import { createElement } from '../stripe-elements'
5+
<script setup lang="ts">
6+
import type { StripeElementType, StripeElements } from "@stripe/stripe-js"
137
import {
14-
defineComponent,
8+
defineEmits,
9+
inject,
1510
onBeforeUnmount,
1611
onMounted,
1712
ref,
1813
toRefs,
1914
watch,
20-
} from 'vue'
15+
withDefaults,
16+
} from "vue"
17+
import { createElement } from "../stripe-elements"
18+
import type { StripeElementOptions } from "../stripe-elements"
2119
22-
export default defineComponent({
23-
name: 'StripeElement',
20+
interface Props {
21+
type?: StripeElementType
22+
elements?: StripeElements
23+
options?: StripeElementOptions
24+
}
2425
25-
props: {
26-
// elements object
27-
// https://stripe.com/docs/js/elements_object/create
28-
elements: {
29-
type: Object as () => StripeElementsWithoutOverload,
30-
required: true,
31-
},
32-
// type of the element
33-
// https://stripe.com/docs/js/elements_object/create_element?type=card
34-
type: {
35-
type: String as () => StripeElementType,
36-
default: () => 'card',
37-
},
38-
// element options
39-
// https://stripe.com/docs/js/elements_object/create_element?type=card#elements_create-options
40-
options: {
41-
type: Object as () => StripeElementOptions,
42-
default: () => ({}),
43-
},
44-
},
26+
const props = withDefaults(defineProps<Props>(), {
27+
type: () =>
28+
(inject("providedElements") as StripeElementType) ? "payment" : "card",
29+
elements: () => inject("providedElements") as StripeElements,
30+
})
31+
const { type, elements, options } = toRefs(props)
4532
46-
setup(props, { emit }) {
47-
const domElement = ref(document.createElement('div'))
48-
const stripeElement = ref()
49-
const mountPoint = ref()
50-
const { elements, type, options } = toRefs(props)
33+
// TODO: verify it works
34+
const emit = defineEmits()
5135
52-
onMounted(() => {
53-
const mountElement = () => {
54-
stripeElement.value = createElement(
55-
elements.value,
56-
type.value,
57-
options.value
58-
)
59-
mountPoint.value.appendChild(domElement.value)
60-
stripeElement.value.mount(domElement.value)
61-
}
36+
const domElement = ref(document.createElement("div"))
37+
const stripeElement = ref()
38+
const mountPoint = ref()
6239
63-
// Handle event listeners
64-
const wrapperFn = (t: string, e: Event) => {
65-
emit(t, e)
66-
}
40+
onMounted(() => {
41+
const mountElement = () => {
42+
stripeElement.value = createElement(
43+
elements.value,
44+
type.value,
45+
options.value,
46+
)
47+
mountPoint.value.appendChild(domElement.value)
48+
stripeElement.value?.mount(domElement.value)
49+
}
6750
68-
const handleEvents = () => {
69-
// See stripe element events: https://stripe.com/docs/js/element/events
70-
const eventTypes = [
71-
'change',
72-
'ready',
73-
'focus',
74-
'blur',
75-
'click',
76-
'escape',
77-
]
78-
eventTypes.forEach((t) => {
79-
stripeElement.value.on(t, wrapperFn.bind(null, t))
80-
})
81-
}
51+
// Handle event listeners
52+
const wrapperFn = (t: string, e: Event) => {
53+
emit(t, e)
54+
}
8255
83-
try {
84-
mountElement()
85-
handleEvents()
86-
} catch (error) {
87-
console.error(error)
88-
}
89-
})
56+
const handleEvents = () => {
57+
// See stripe element events: https://stripe.com/docs/js/element/events
58+
const eventTypes = [
59+
"change",
60+
"ready",
61+
"focus",
62+
"blur",
63+
"click",
64+
"escape",
65+
"loaderror",
66+
"loaderstart",
67+
]
9068
91-
onBeforeUnmount(() => {
92-
stripeElement.value?.unmount()
93-
stripeElement.value?.destroy()
94-
})
69+
for (const eventType of eventTypes) {
70+
stripeElement.value?.on(eventType, wrapperFn.bind(null, eventType))
71+
}
72+
}
9573
96-
watch(options, () => {
97-
stripeElement.value?.update(props.options)
98-
})
74+
try {
75+
mountElement()
76+
handleEvents()
77+
} catch (error) {
78+
console.error(error)
79+
}
80+
})
9981
100-
return {
101-
stripeElement,
102-
domElement,
103-
mountPoint,
104-
}
105-
},
82+
onBeforeUnmount(() => {
83+
stripeElement.value?.unmount()
84+
stripeElement.value?.destroy()
85+
})
86+
87+
watch(options, () => {
88+
stripeElement.value?.update(props.options)
89+
})
90+
91+
defineExpose({
92+
stripeElement,
93+
domElement,
94+
mountPoint,
10695
})
10796
</script>

src/components/StripeElements.vue

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,51 @@
11
<template>
22
<div v-if="elementsUsable">
3-
<slot :instance="instance" :elements="elements"></slot>
3+
<slot
4+
:instance="instance"
5+
:elements="elements"
6+
></slot>
47
</div>
58
</template>
69

7-
<script lang="ts">
8-
import { defineComponent, computed, ref, toRefs, onMounted, watch } from 'vue'
9-
import { createElements, initStripe } from '../stripe-elements'
10+
<script setup lang="ts">
11+
import type {
12+
Stripe,
13+
StripeConstructorOptions,
14+
StripeElements,
15+
StripeElementsOptions,
16+
StripeElementsUpdateOptions,
17+
} from "@stripe/stripe-js"
18+
import { computed, onMounted, provide, ref, toRefs, watch } from "vue"
19+
import { createElements, initStripe } from "../stripe-elements.ts"
1020
11-
export default defineComponent({
12-
name: 'StripeElements',
21+
const props = defineProps<{
22+
stripeKey: string
23+
instanceOptions?: StripeConstructorOptions
24+
elementsOptions?: StripeElementsOptions
25+
}>()
1326
14-
props: {
15-
stripeKey: {
16-
type: String,
17-
required: true,
18-
},
19-
instanceOptions: {
20-
type: Object,
21-
default: () => ({}),
22-
},
23-
elementsOptions: {
24-
type: Object,
25-
default: () => ({}),
26-
},
27-
},
27+
const { stripeKey, instanceOptions, elementsOptions } = toRefs(props)
28+
const instance = ref<Stripe>()
29+
const elements = ref<StripeElements>()
30+
const elementsUsable = computed(() => {
31+
return elements.value ? Object.keys(elements.value).length > 0 : false
32+
})
2833
29-
setup(props) {
30-
const { stripeKey, instanceOptions, elementsOptions } = toRefs(props)
31-
const instance = ref()
32-
const elements = ref()
33-
const elementsUsable = computed(() => {
34-
return elements.value ? Object.keys(elements.value).length > 0 : false
35-
})
34+
onMounted(() => {
35+
instance.value = initStripe(stripeKey.value, instanceOptions.value)
36+
elements.value = createElements(instance.value, elementsOptions.value)
37+
})
3638
37-
onMounted(() => {
38-
instance.value = initStripe(stripeKey.value, instanceOptions.value)
39-
elements.value = createElements(instance.value, elementsOptions.value)
40-
})
39+
watch(elementsOptions, () => {
40+
elements.value?.update(elementsOptions.value as StripeElementsUpdateOptions)
41+
})
4142
42-
watch(elementsOptions, () => {
43-
elements.value?.update(elementsOptions.value)
44-
})
43+
provide("providedInstance", instance)
44+
provide("providedElements", elements)
4545
46-
return {
47-
elements,
48-
instance,
49-
elementsUsable,
50-
}
51-
},
46+
defineExpose({
47+
elements,
48+
instance,
49+
elementsUsable,
5250
})
5351
</script>

src/main.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { createElement, createElements, initStripe } from './stripe-elements'
2-
import StripeElement from './components/StripeElement.vue'
3-
import StripeElements from './components/StripeElements.vue'
1+
import StripeElement from "./components/StripeElement.vue"
2+
import StripeElements from "./components/StripeElements.vue"
3+
import { createElement, createElements, initStripe } from "./stripe-elements.ts"
44

55
export {
66
createElement,

0 commit comments

Comments
 (0)