Skip to content

Commit 3c13519

Browse files
committed
refactor: drop dinero.js — native money formatting
1 parent 09dc8ed commit 3c13519

6 files changed

Lines changed: 48 additions & 55 deletions

File tree

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,6 @@
338338
"tailwind-merge": "^3.6.0",
339339
"tailwind-variants": "^3.2.2",
340340
"vaul-svelte": "1.0.0-next.7",
341-
"dinero.js": "^2.0.2",
342341
"@stripe/stripe-js": "^9.8.0"
343342
},
344343
"devDependencies": {

src/lib/blocks/alert-modal/AlertModal.svelte

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
}}
5454
>
5555
{#if alertModal.loading}<Spinner />{/if}
56-
{alertModal.loading ? 'Please wait...' : alertModal.actionLabel}
5756
</AlertDialog.Action>
5857
</AlertDialog.Footer>
5958
{/if}

src/lib/format/money.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,2 @@
1-
import { dinero, toDecimal } from 'dinero.js';
2-
import { USD } from 'dinero.js/currencies';
3-
41
export const formatUSD = (cents: number): string =>
5-
toDecimal(dinero({ amount: cents, currency: USD }), ({ value }) =>
6-
new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(Number(value)));
2+
new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(cents / 100);

src/lib/stripe/StripePaymentField.svelte

Lines changed: 44 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -37,48 +37,6 @@
3737
let submitting = $state(false);
3838
let loading = $state(true);
3939
40-
// untrack pins the setup to once-per-mount: the callback props are usually inline arrows,
41-
// so their identity changes on every parent render and must not re-create the setup intent.
42-
const mountPayment: Attachment<HTMLDivElement> = (node) => {
43-
let paymentEl: { unmount(): void } | null = null;
44-
untrack(() =>
45-
Promise.all([createSetupIntent(), loadStripe(stripeKey)])
46-
.then(([{ clientSecret, customerSessionClientSecret }, s]) => {
47-
if (!s || !clientSecret) throw new Error('Failed to initialize payment');
48-
const isDark = document.documentElement.classList.contains('dark');
49-
stripe = s;
50-
elements = s.elements({
51-
clientSecret,
52-
customerSessionClientSecret,
53-
appearance: {
54-
theme: isDark ? 'night' : 'stripe',
55-
variables: {
56-
colorPrimary: isDark ? 'hsl(41, 69%, 62%)' : 'hsl(40, 91%, 45%)',
57-
tabIconColor: isDark ? '#a3a3a3' : '#737373',
58-
tabIconHoverColor: isDark ? '#ffffff' : '#000000',
59-
tabIconSelectedColor: '#1f1f1f',
60-
colorBackground: isDark ? 'hsl(80 2.1% 12.4%)' : '#ffffff',
61-
logoColor: isDark ? 'light' : 'dark',
62-
},
63-
},
64-
});
65-
const el = elements.create('payment', {
66-
defaultValues: {
67-
billingDetails: {
68-
name: billingName || undefined,
69-
email: email || undefined,
70-
},
71-
},
72-
});
73-
el.mount(node);
74-
el.on('ready', () => (loading = false));
75-
paymentEl = el;
76-
})
77-
.catch(() => (loading = false)),
78-
);
79-
return () => paymentEl?.unmount();
80-
};
81-
8240
const submit = () => {
8341
if (!stripe || !elements) return;
8442
submitting = true;
@@ -104,7 +62,50 @@
10462
{#if title}
10563
<h3 class="text-base font-medium mb-4">{title}</h3>
10664
{/if}
107-
<div {@attach mountPayment} class="w-full"></div>
65+
<div
66+
{@attach (node) => {
67+
// untrack pins the setup to once-per-mount: the callback props are usually inline arrows,
68+
// so their identity changes on every parent render and must not re-create the setup intent.
69+
let paymentEl: { unmount(): void } | null = null;
70+
untrack(() =>
71+
Promise.all([createSetupIntent(), loadStripe(stripeKey)])
72+
.then(([{ clientSecret, customerSessionClientSecret }, s]) => {
73+
if (!s || !clientSecret) throw new Error('Failed to initialize payment');
74+
const isDark = document.documentElement.classList.contains('dark');
75+
stripe = s;
76+
elements = s.elements({
77+
clientSecret,
78+
customerSessionClientSecret,
79+
appearance: {
80+
theme: isDark ? 'night' : 'stripe',
81+
variables: {
82+
colorPrimary: isDark ? 'hsl(41, 69%, 62%)' : 'hsl(40, 91%, 45%)',
83+
tabIconColor: isDark ? '#a3a3a3' : '#737373',
84+
tabIconHoverColor: isDark ? '#ffffff' : '#000000',
85+
tabIconSelectedColor: '#1f1f1f',
86+
colorBackground: isDark ? 'hsl(80 2.1% 12.4%)' : '#ffffff',
87+
logoColor: isDark ? 'light' : 'dark',
88+
},
89+
},
90+
});
91+
const el = elements.create('payment', {
92+
defaultValues: {
93+
billingDetails: {
94+
name: billingName || undefined,
95+
email: email || undefined,
96+
},
97+
},
98+
});
99+
el.mount(node);
100+
el.on('ready', () => (loading = false));
101+
paymentEl = el;
102+
})
103+
.catch(() => (loading = false)),
104+
);
105+
return () => paymentEl?.unmount();
106+
}}
107+
class="w-full">
108+
</div>
108109
<div class="flex justify-end gap-2 mt-4">
109110
{#if oncancel}
110111
<Button variant="outline" disabled={submitting} onclick={oncancel}>Cancel</Button>

tsconfig.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
"strict": true,
1414
// Inherit base's plugins/options, but keep this component lib's prior strictness profile:
1515
// base enables noUncheckedIndexedAccess, which the vendored UI components aren't written for.
16-
"noUncheckedIndexedAccess": false,
17-
"declarationMap": true
16+
"noUncheckedIndexedAccess": false
1817
},
1918
"include": ["src/lib"],
2019
"exclude": ["dist"]

vite.config.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,12 @@ export default defineConfig({
1414
// Path is relative to the generated .svelte-kit/tsconfig.json.
1515
typescript: {
1616
config: (c) => {
17-
c.extends = '../../../../tsconfig.base.json';
17+
c.extends = '../../../../tsconfig.json';
1818
},
1919
},
2020
// Force runes mode for the project, except for libraries. Can be removed in svelte 6.
2121
vitePlugin: {
22-
dynamicCompileOptions: ({ filename }) =>
23-
filename.split(/[/\\]/).includes('node_modules') ? undefined : { runes: true },
22+
dynamicCompileOptions: ({ filename }) => (filename.split(/[/\\]/).includes('node_modules') ? undefined : { runes: true }),
2423
},
2524
}),
2625
],

0 commit comments

Comments
 (0)