-
Notifications
You must be signed in to change notification settings - Fork 0
Fix: Vite issues #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughReplaces html2pdf.js with html2canvas-pro + jspdf, updates dependencies and registry entries, restructures payment-widget context into index/provider/hook, adjusts component imports, changes receipt PDF generation logic, adds an env guard for RN_API_URL, tightens TypeScript typings in utils, tweaks receipt padding, and removes html2pdf typings. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant PaymentSuccess as PaymentSuccess component
participant DOM as Receipt DOM Element
participant Canvas as html2canvas-pro
participant PDF as jsPDF
participant Browser
User->>PaymentSuccess: Click "Download receipt"
PaymentSuccess->>DOM: Select hidden receipt element
PaymentSuccess->>Canvas: render(element, { scale:2, useCORS:true, background:"white" })
Canvas-->>PaymentSuccess: HTMLCanvasElement
PaymentSuccess->>PDF: new jsPDF('p','mm','a4')
PaymentSuccess->>PDF: addImage(canvas PNG, width=210mm, preserve aspect)
PaymentSuccess->>Browser: save("<receipt-number>.pdf")
note over PaymentSuccess,PDF: New flow replacing html2pdf.js
sequenceDiagram
autonumber
participant App
participant Provider as PaymentWidgetProvider
participant ComponentA as Component A
participant ComponentB as Component B
participant Ctx as PaymentWidgetContext
App->>Provider: Render with props
Provider->>Ctx: Provide value (config, wallet, callbacks)
ComponentA->>Ctx: usePaymentWidgetContext()
Ctx-->>ComponentA: Context value
ComponentB->>Ctx: usePaymentWidgetContext()
Ctx-->>ComponentB: Context value
note over ComponentA,ComponentB: Hook throws if no Provider present
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
registry/default/payment-widget/context/payment-widget-context/payment-widget-provider.tsx (1)
41-45
: Fix fallback for connectedWalletAddress when walletAccount lacks an addressIf a custom WalletClient is provided without
account.address
,connectedWalletAddress
becomesundefined
. Prior context used a fallback toaddress
fromwagmi
. Use nullish coalescing.Apply:
- const isWalletOverride = walletAccount !== undefined; - const connectedWalletAddress = walletAccount - ? walletAccount.account?.address - : address; + const isWalletOverride = walletAccount !== undefined; + const connectedWalletAddress = + walletAccount?.account?.address ?? address;
🧹 Nitpick comments (15)
package.json (1)
22-23
: Switch to html2canvas-pro + jsPDF looks good.No functional concerns from this diff. Ensure you tree‑shake unused jsPDF plugins to keep bundles lean.
registry/default/payment-widget/utils/wagmi.ts (1)
1-1
: Nice typing hardening for connectors.Importing CreateConnectorFn and typing connectors removes the any escape hatch. Looks good.
Minor: mark the array const for clearer intent:
- const connectors: CreateConnectorFn[] = [ + const connectors: readonly CreateConnectorFn[] = [Also applies to: 19-19, 41-41
registry/default/payment-widget/utils/payment.ts (2)
55-62
: Type guard is safer withunknown
+ null check.Good improvement. Consider also asserting the inner
error
is anError
for downstream consistency.export const isPaymentError = (error: unknown): error is PaymentError => { return ( error !== null && typeof error === "object" && "type" in error && - "error" in error + "error" in error && + (error as any).error instanceof Error ); };
200-207
: Normalize unknown throws toError
before wrapping.Some runtimes throw strings or plain objects; normalize for consistency with your
PaymentError
contract.} catch (error) { console.error("Error in payment flow:", error); if (isPaymentError(error)) { throw error; } else { - throw { type: "unknown", error: error as Error } as PaymentError; + const err = error instanceof Error ? error : new Error(String(error)); + throw { type: "unknown", error: err } as PaymentError; } }registry/default/payment-widget/constants.ts (1)
2-3
: Guard preventsprocess
reference errors, but Vite env isn’t read.Vite uses
import.meta.env.VITE_*
. Add a non‑crashing fallback to read that too.-export const RN_API_URL = - (typeof process !== "undefined" && process.env.NEXT_PUBLIC_REQUEST_API_URL) || - "https://api.request.network"; +// Prefer Next.js env, then Vite's import.meta.env, then default. +const viteUrl = + // `import.meta` exists in ESM; `.env` will be undefined outside Vite. + (import.meta as any)?.env?.VITE_REQUEST_API_URL as string | undefined; +export const RN_API_URL = + (typeof process !== "undefined" + ? process.env?.NEXT_PUBLIC_REQUEST_API_URL + : undefined) || + viteUrl || + "https://api.request.network";Please confirm this file is transpiled as ESM (so
import.meta
parses). If not, we can gate with a try/catch or a typeof check via a helper.registry/default/payment-widget/context/payment-widget-context/index.ts (1)
5-31
: Tighten address types with viem’sAddress
.Use the
Address
branded type to prevent invalid hex strings at compile time.-import type { TransactionReceipt, WalletClient } from "viem"; +import type { Address, TransactionReceipt, WalletClient } from "viem"; export interface PaymentWidgetContextValue { amountInUsd: string; - recipientWallet: string; + recipientWallet: Address; walletAccount?: WalletClient; - connectedWalletAddress?: string; + connectedWalletAddress?: Address; isWalletOverride: boolean;Ensure callers pass checksummed/0x‑prefixed addresses; otherwise add a runtime guard where the context is populated.
registry/default/payment-widget/components/currency-select.tsx (2)
3-3
: Nit: include useMemo for derived arrays.Avoid recomputing on every render.
-import { useState } from "react"; +import { useMemo, useState } from "react";
63-66
: Nit: memoize lowerCaseSupportedCurrencies.Minor render perf tidy‑up.
- const lowerCaseSupportedCurrencies = supportedCurrencies.map((currency) => - currency.toLowerCase(), - ); + const lowerCaseSupportedCurrencies = useMemo( + () => supportedCurrencies.map((c) => c.toLowerCase()), + [supportedCurrencies], + );registry/default/payment-widget/components/payment-modal.tsx (1)
69-74
: Reset txHash when resetting modal state.Prevents stale hash on subsequent payments after a success close.
const reset = () => { setActiveStep("currency-select"); setSelectedCurrency(null); setBuyerInfo(receiptInfo.buyerInfo || undefined); setRequestId(""); + setTxHash(""); };
registry/default/payment-widget/payment-widget.tsx (1)
24-38
: Simplify disabled logic; keep errors.Cleaner derivation without mutable flag.
- let isButtonDisabled = false; - - if (!rnApiClientId || rnApiClientId === "") { - console.error("PaymentWidget: rnApiClientId is required in paymentConfig"); - - isButtonDisabled = true; - } - - if (supportedCurrencies.length === 0) { - console.error( - "PaymentWidget: supportedCurrencies is required in paymentConfig", - ); - - isButtonDisabled = true; - } + const missingClientId = !rnApiClientId || rnApiClientId === ""; + const missingCurrencies = supportedCurrencies.length === 0; + if (missingClientId) { + console.error("PaymentWidget: rnApiClientId is required in paymentConfig"); + } + if (missingCurrencies) { + console.error( + "PaymentWidget: supportedCurrencies is required in paymentConfig", + ); + } + const isButtonDisabled = missingClientId || missingCurrencies;registry/default/payment-widget/components/payment-confirmation.tsx (2)
49-53
: Guard UX: show an actionable error when wallet not connected.Early return is silent; inform the user.
- if (!connectedWalletAddress) return; + if (!connectedWalletAddress) { + setLocalError("Please connect your wallet to continue."); + return; + }
178-185
: Disable Pay when wallet not connected.Prevents a no-op click path.
- <Button + <Button type="button" onClick={handleExecutePayment} className="flex-1" - disabled={isExecuting} + disabled={isExecuting || !connectedWalletAddress} >registry/default/payment-widget/components/payment-success.tsx (2)
75-83
: Improve canvas quality safely.Use devicePixelRatio (capped) and silence logs.
- const canvas = await html2canvas(element, { - scale: 2, + const canvas = await html2canvas(element, { + scale: Math.min(2, window.devicePixelRatio || 1), useCORS: true, + logging: false, backgroundColor: "#ffffff", width: element.scrollWidth, height: element.scrollHeight, windowWidth: element.scrollWidth, windowHeight: element.scrollHeight, });
97-98
: Optional: replace alert with toast.Use your UI toast for non‑blocking feedback.
registry/default/payment-widget/context/payment-widget-context/payment-widget-provider.tsx (1)
66-81
: Optional: simplify deps; reduce maintenance riskTracking individual nested fields is brittle. If parent props are stable, consider depending on the objects instead (or pre‑memoize them in parent). If not, keep as is.
Possible tweak:
- [ - amountInUsd, - recipientWallet, - walletAccount, - connectedWalletAddress, - isWalletOverride, - paymentConfig.rnApiClientId, - paymentConfig.feeInfo, - paymentConfig.supportedCurrencies, - uiConfig?.showReceiptDownload, - uiConfig?.showRequestScanUrl, - receiptInfo, - onSuccess, - onError, - ], + [ + amountInUsd, + recipientWallet, + walletAccount, + connectedWalletAddress, + isWalletOverride, + paymentConfig, + uiConfig, + receiptInfo, + onSuccess, + onError, + ],
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.json
is excluded by!**/package-lock.json
📒 Files selected for processing (16)
package.json
(2 hunks)public/r/registry.json
(2 hunks)registry.json
(2 hunks)registry/default/payment-widget/components/currency-select.tsx
(1 hunks)registry/default/payment-widget/components/payment-confirmation.tsx
(1 hunks)registry/default/payment-widget/components/payment-modal.tsx
(1 hunks)registry/default/payment-widget/components/payment-success.tsx
(4 hunks)registry/default/payment-widget/components/receipt/styles.css
(1 hunks)registry/default/payment-widget/constants.ts
(1 hunks)registry/default/payment-widget/context/payment-widget-context/index.ts
(1 hunks)registry/default/payment-widget/context/payment-widget-context/payment-widget-provider.tsx
(1 hunks)registry/default/payment-widget/context/payment-widget-context/use-payment-widget-context.ts
(1 hunks)registry/default/payment-widget/payment-widget.tsx
(1 hunks)registry/default/payment-widget/types/html2pdf.d.ts
(0 hunks)registry/default/payment-widget/utils/payment.ts
(3 hunks)registry/default/payment-widget/utils/wagmi.ts
(3 hunks)
💤 Files with no reviewable changes (1)
- registry/default/payment-widget/types/html2pdf.d.ts
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-09-17T12:08:58.198Z
Learnt from: bassgeta
PR: RequestNetwork/ui-registry#1
File: registry/default/payment-widget/components/payment-confirmation.tsx:31-41
Timestamp: 2025-09-17T12:08:58.198Z
Learning: In the payment widget context (registry/default/payment-widget/context/payment-widget-context.tsx), connectedWalletAddress is properly derived as `walletAccount?.account?.address || address` which handles both custom WalletClient scenarios and wagmi-managed wallets, so components should use connectedWalletAddress from context rather than address from usePayment hook.
Applied to files:
registry/default/payment-widget/context/payment-widget-context/use-payment-widget-context.ts
registry/default/payment-widget/context/payment-widget-context/index.ts
registry/default/payment-widget/components/currency-select.tsx
registry/default/payment-widget/components/payment-modal.tsx
registry/default/payment-widget/utils/wagmi.ts
registry/default/payment-widget/components/payment-confirmation.tsx
registry/default/payment-widget/payment-widget.tsx
registry/default/payment-widget/components/payment-success.tsx
registry.json
public/r/registry.json
registry/default/payment-widget/context/payment-widget-context/payment-widget-provider.tsx
📚 Learning: 2025-09-17T12:08:58.198Z
Learnt from: bassgeta
PR: RequestNetwork/ui-registry#1
File: registry/default/payment-widget/components/payment-confirmation.tsx:31-41
Timestamp: 2025-09-17T12:08:58.198Z
Learning: In the payment widget context (registry/default/payment-widget/context/payment-widget-context.tsx), connectedWalletAddress is properly derived as `walletAccount ? walletAccount.account?.address : address` which handles both custom WalletClient scenarios and wagmi-managed wallets, so components should use connectedWalletAddress from context rather than address from usePayment hook.
Applied to files:
registry/default/payment-widget/context/payment-widget-context/use-payment-widget-context.ts
registry/default/payment-widget/context/payment-widget-context/index.ts
registry/default/payment-widget/components/currency-select.tsx
registry/default/payment-widget/components/payment-modal.tsx
registry/default/payment-widget/utils/wagmi.ts
registry/default/payment-widget/components/payment-confirmation.tsx
registry/default/payment-widget/payment-widget.tsx
registry/default/payment-widget/components/payment-success.tsx
registry.json
public/r/registry.json
registry/default/payment-widget/context/payment-widget-context/payment-widget-provider.tsx
📚 Learning: 2025-09-17T15:33:04.220Z
Learnt from: bassgeta
PR: RequestNetwork/ui-registry#1
File: app/components/payment-widget-wrapper.tsx:15-18
Timestamp: 2025-09-17T15:33:04.220Z
Learning: In the payment widget, walletConnectProjectId is optional and can be empty, but rnApiClientId is required. The PaymentWidgetInner component already disables the button when rnApiClientId is missing, providing existing validation.
Applied to files:
registry/default/payment-widget/context/payment-widget-context/index.ts
📚 Learning: 2025-09-17T09:30:27.515Z
Learnt from: bassgeta
PR: RequestNetwork/ui-registry#1
File: app/components/viem-account-demo.tsx:45-46
Timestamp: 2025-09-17T09:30:27.515Z
Learning: Wagmi v2 useConnect hook returns isPending (derived from TanStack Query mutation status) and connectors have .uid property as shown in official documentation at https://wagmi.sh/react/guides/connect-wallet
Applied to files:
registry/default/payment-widget/utils/wagmi.ts
🧬 Code graph analysis (3)
registry/default/payment-widget/context/payment-widget-context/use-payment-widget-context.ts (1)
registry/default/payment-widget/context/payment-widget-context/index.ts (2)
PaymentWidgetContextValue
(5-31)PaymentWidgetContext
(33-34)
registry/default/payment-widget/context/payment-widget-context/index.ts (1)
registry/default/payment-widget/types/index.ts (3)
FeeInfo
(1-4)ReceiptInfo
(67-73)PaymentError
(8-11)
registry/default/payment-widget/utils/payment.ts (1)
registry/default/payment-widget/types/index.ts (1)
PaymentError
(8-11)
🔇 Additional comments (18)
registry/default/payment-widget/components/receipt/styles.css (1)
3-3
: Padding increase acknowledged.The 32px padding should still fit within the 800px canvas width used during PDF capture. No issues.
If you notice clipping on narrow viewports when rendering to canvas, consider setting a fixed inner wrapper width (e.g., 736px) to match 800px − 2×32px.
registry/default/payment-widget/utils/payment.ts (1)
1-1
: Type‑only import is correct.This reduces emitted JS and tightens typings.
public/r/registry.json (2)
24-26
: Dependency mapping updated.html2canvas-pro + jsPDF entries align with package.json.
34-47
: New context module exports registered correctly.Paths and targets look consistent with the new foldered context structure.
Run a quick smoke test with
shadcn add payment-widget
into a Vite app to ensure these entries resolve correctly on install.registry.json (2)
24-26
: Mirrored dependency updates match public/r.Keeps both registries in sync.
34-47
: Context split registered here as well.Good consistency with public/r/registry.json. No issues.
registry/default/payment-widget/components/currency-select.tsx (1)
13-13
: Path update LGTM.Importing the hook from the new context module is consistent with the refactor.
registry/default/payment-widget/components/payment-modal.tsx (2)
19-19
: Path update LGTM.Hook import aligns with the new context structure.
79-86
: Confirm intended UX for early closes.Currently state resets only when closing from "payment-success". If the user closes earlier, the step/buyer info persist. Confirm that this is desired.
registry/default/payment-widget/payment-widget.tsx (1)
8-12
: Path updates LGTM.Provider and hook imports match the refactor.
registry/default/payment-widget/components/payment-confirmation.tsx (1)
13-13
: Path update LGTM.Hook import matches the new context module.
registry/default/payment-widget/context/payment-widget-context/use-payment-widget-context.ts (1)
1-14
: Hook implementation LGTM.Correctly enforces provider presence and returns typed context.
registry/default/payment-widget/components/payment-success.tsx (4)
14-14
: Path update LGTM.Hook import aligns with the refactor.
75-83
: Cross‑origin assets caveat.If logos/images in the receipt come from a CDN, ensure those
tags have crossOrigin="anonymous" and the server sends CORS headers, or html2canvas will taint the canvas.
126-134
: Good: hidden render target with fixed width and white bg.This stabilizes layout and color for capture.
Confirm that 800px corresponds to the intended A4 scaling after the fit‑to‑page change above; adjust if text looks too small.
48-48
: Type check: receipt amount shape — OK (string)PaymentInfo.amount (and therefore CreateReceiptParams.payment.amount) is declared as string in registry/default/payment-widget/utils/receipt.ts; amountInUsd is a string in the widget/context, so no coercion required.
registry/default/payment-widget/context/payment-widget-context/payment-widget-provider.tsx (2)
83-87
: Provider wiring looks goodMemoized value, stable shape, and defaults for UI flags are sensible.
41-61
: Resolved — consumers handle undefined connectedWalletAddressconnectedWalletAddress is provided by payment-widget-provider and is only consumed in:
- registry/default/payment-widget/components/payment-confirmation.tsx — guarded (if (!connectedWalletAddress) return) and Back button disabled when missing.
- registry/default/payment-widget/components/payment-success.tsx — coalesced with
|| ""
when used.No unguarded string/property operations on connectedWalletAddress were found.
Problem
When testing the widget on a fresh Vite app I've encountered multiple difficulties.
The most jarring one was the fact that when you initialize ShadCN, it creates a tailwind config with
okch
colours, which breakshtml2pdf.js
🤯Solution
Make rendering of PDFs done with
jsPDF
and html2canvas-pro, which has oklch support.And just generally reconfigured everything so that the linter isn't angry when you are using vite.
Changes
html2canvas-pro
andjsPDF
instead ofhtml2pdf.js
Summary by CodeRabbit