@alfadocs/ui-kit-debug 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{combobox-DCNXqbC7.js → combobox-BLWruOxK.js} +74 -75
- package/dist/_chunks/combobox-BLWruOxK.js.map +1 -0
- package/dist/_chunks/{freemium-paywall-CnvceDav.js → freemium-paywall-CrVefV0M.js} +2 -2
- package/dist/_chunks/{freemium-paywall-CnvceDav.js.map → freemium-paywall-CrVefV0M.js.map} +1 -1
- package/dist/_chunks/{link-8QmFjIz2.js → link-BcYW1eNM.js} +48 -32
- package/dist/_chunks/link-BcYW1eNM.js.map +1 -0
- package/dist/_chunks/{message-card-ChCX9Iv6.js → message-card-DjvsB_3U.js} +12 -12
- package/dist/_chunks/message-card-DjvsB_3U.js.map +1 -0
- package/dist/_chunks/{message-tray-n8q9ITXI.js → message-tray-BbnAzlLH.js} +23 -23
- package/dist/_chunks/{message-tray-n8q9ITXI.js.map → message-tray-BbnAzlLH.js.map} +1 -1
- package/dist/_chunks/{notification-card-hBlPN1-c.js → notification-card-uTPEvAQS.js} +21 -21
- package/dist/_chunks/notification-card-uTPEvAQS.js.map +1 -0
- package/dist/_chunks/{notification-tray-C5cnXbl9.js → notification-tray-PGtMqXbP.js} +56 -56
- package/dist/_chunks/{notification-tray-C5cnXbl9.js.map → notification-tray-PGtMqXbP.js.map} +1 -1
- package/dist/_chunks/{payment-form-C3vT_npe.js → payment-form-B_BdHwjb.js} +21 -21
- package/dist/_chunks/{payment-form-C3vT_npe.js.map → payment-form-B_BdHwjb.js.map} +1 -1
- package/dist/_chunks/transaction-chip-DE6DITun.js +196 -0
- package/dist/_chunks/transaction-chip-DE6DITun.js.map +1 -0
- package/dist/agent-catalog.json +15 -1
- package/dist/components/combobox/combobox.d.ts.map +1 -1
- package/dist/components/combobox/index.js +1 -1
- package/dist/components/freemium-paywall/index.js +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/link/index.js +1 -1
- package/dist/components/link/link.d.ts +1 -0
- package/dist/components/link/link.d.ts.map +1 -1
- package/dist/components/message-card/index.js +1 -1
- package/dist/components/message-card/message-card.d.ts.map +1 -1
- package/dist/components/message-tray/index.js +1 -1
- package/dist/components/message-tray/message-tray.d.ts.map +1 -1
- package/dist/components/notification-card/index.js +1 -1
- package/dist/components/notification-card/notification-card.d.ts.map +1 -1
- package/dist/components/notification-tray/index.js +1 -1
- package/dist/components/notification-tray/notification-tray.d.ts.map +1 -1
- package/dist/components/payment-form/index.js +1 -1
- package/dist/components/transaction-chip/index.d.ts +3 -0
- package/dist/components/transaction-chip/index.d.ts.map +1 -0
- package/dist/components/transaction-chip/index.js +5 -0
- package/dist/components/transaction-chip/index.js.map +1 -0
- package/dist/components/transaction-chip/transaction-chip.d.ts +30 -0
- package/dist/components/transaction-chip/transaction-chip.d.ts.map +1 -0
- package/dist/i18n/config.js +36 -0
- package/dist/i18n/config.js.map +1 -1
- package/dist/i18n/resources.d.ts +36 -0
- package/dist/i18n/resources.d.ts.map +1 -1
- package/dist/index.js +33 -31
- package/dist/index.js.map +1 -1
- package/dist/locales/de.json +12 -0
- package/dist/locales/en.json +12 -0
- package/dist/locales/it.json +12 -0
- package/dist/tokens.css +1 -1
- package/package.json +1 -1
- package/dist/_chunks/combobox-DCNXqbC7.js.map +0 -1
- package/dist/_chunks/link-8QmFjIz2.js.map +0 -1
- package/dist/_chunks/message-card-ChCX9Iv6.js.map +0 -1
- package/dist/_chunks/notification-card-hBlPN1-c.js.map +0 -1
|
@@ -82,7 +82,7 @@ function be(r, n) {
|
|
|
82
82
|
i.disconnect(), a.removeEventListener("change", e), f.removeEventListener("change", e);
|
|
83
83
|
};
|
|
84
84
|
}
|
|
85
|
-
const
|
|
85
|
+
const ye = {
|
|
86
86
|
id: "payment-form",
|
|
87
87
|
capabilities: ["submit"],
|
|
88
88
|
state: {},
|
|
@@ -108,7 +108,7 @@ const ge = {
|
|
|
108
108
|
description: "Sourced from the id prop."
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
|
-
},
|
|
111
|
+
}, ge = /* @__PURE__ */ new Set([
|
|
112
112
|
"BIF",
|
|
113
113
|
"CLP",
|
|
114
114
|
"DJF",
|
|
@@ -128,7 +128,7 @@ const ge = {
|
|
|
128
128
|
"XPF"
|
|
129
129
|
]);
|
|
130
130
|
function $(r, n, s) {
|
|
131
|
-
const e = n.toUpperCase(), i =
|
|
131
|
+
const e = n.toUpperCase(), i = ge.has(e) ? r : r / 100;
|
|
132
132
|
try {
|
|
133
133
|
return new Intl.NumberFormat(s, {
|
|
134
134
|
style: "currency",
|
|
@@ -233,9 +233,9 @@ function xe(r) {
|
|
|
233
233
|
returnUrl: a,
|
|
234
234
|
onSuccess: f,
|
|
235
235
|
onError: N
|
|
236
|
-
} = r, { t: o } = q(), k = le(), S = me(),
|
|
237
|
-
() => `pay-${
|
|
238
|
-
[
|
|
236
|
+
} = r, { t: o } = q(), k = le(), S = me(), g = oe(), b = j(
|
|
237
|
+
() => `pay-${g.replace(/[^a-zA-Z0-9-_]/g, "")}`,
|
|
238
|
+
[g]
|
|
239
239
|
), F = `${b}-payment`, L = `${b}-address`, v = `${b}-error`, [u, h] = E(!1), [A, P] = E(!1), [w, x] = E(null), [U, d] = E(""), c = V(f), l = V(N);
|
|
240
240
|
R(() => {
|
|
241
241
|
c.current = f, l.current = N;
|
|
@@ -254,22 +254,22 @@ function xe(r) {
|
|
|
254
254
|
return;
|
|
255
255
|
}
|
|
256
256
|
try {
|
|
257
|
-
const
|
|
257
|
+
const y = await k.confirmPayment({
|
|
258
258
|
elements: S,
|
|
259
259
|
confirmParams: C ? { return_url: C } : {},
|
|
260
260
|
redirect: "if_required"
|
|
261
261
|
});
|
|
262
|
-
if (
|
|
263
|
-
const M =
|
|
262
|
+
if (y.error) {
|
|
263
|
+
const M = y.error.code ?? "generic", I = he(M), te = X(y.error.message ?? "");
|
|
264
264
|
x(I), d(o(I)), (H = l.current) == null || H.call(l, {
|
|
265
265
|
code: M,
|
|
266
266
|
translatedMessage: te || o(I)
|
|
267
267
|
});
|
|
268
268
|
return;
|
|
269
269
|
}
|
|
270
|
-
|
|
271
|
-
} catch (
|
|
272
|
-
const M =
|
|
270
|
+
y.paymentIntent && ((O = c.current) == null || O.call(c, y.paymentIntent.id));
|
|
271
|
+
} catch (y) {
|
|
272
|
+
const M = y instanceof Error ? y.message : "", I = X(M);
|
|
273
273
|
x("payment.error.generic"), d(o("payment.error.generic")), (K = l.current) == null || K.call(l, {
|
|
274
274
|
code: "unexpected",
|
|
275
275
|
translatedMessage: I || o("payment.error.generic")
|
|
@@ -441,13 +441,13 @@ const ke = se(
|
|
|
441
441
|
locale: o,
|
|
442
442
|
ariaLabel: k,
|
|
443
443
|
returnUrl: S,
|
|
444
|
-
stripePromise:
|
|
444
|
+
stripePromise: g,
|
|
445
445
|
className: b
|
|
446
446
|
}, F) => {
|
|
447
|
-
const { i18n: L } = q(), v = Ne(o ?? L.language ?? "en"), [u, h] = E(
|
|
447
|
+
const { i18n: L } = q(), v = Ne(o ?? L.language ?? "en"), [u, h] = E(g ?? null);
|
|
448
448
|
R(() => {
|
|
449
|
-
if (
|
|
450
|
-
h(
|
|
449
|
+
if (g !== void 0) {
|
|
450
|
+
h(g);
|
|
451
451
|
return;
|
|
452
452
|
}
|
|
453
453
|
if (!s) {
|
|
@@ -455,7 +455,7 @@ const ke = se(
|
|
|
455
455
|
return;
|
|
456
456
|
}
|
|
457
457
|
h(de(s));
|
|
458
|
-
}, [
|
|
458
|
+
}, [g, s]);
|
|
459
459
|
const [A, P] = E(
|
|
460
460
|
() => B()
|
|
461
461
|
);
|
|
@@ -477,7 +477,7 @@ const ke = se(
|
|
|
477
477
|
}),
|
|
478
478
|
[]
|
|
479
479
|
);
|
|
480
|
-
ae(F, () => w.current, []), fe(
|
|
480
|
+
ae(F, () => w.current, []), fe(ye, x, r);
|
|
481
481
|
const U = j(
|
|
482
482
|
() => ({
|
|
483
483
|
clientSecret: n,
|
|
@@ -551,7 +551,7 @@ function Se(r) {
|
|
|
551
551
|
}
|
|
552
552
|
)
|
|
553
553
|
] }),
|
|
554
|
-
i ? /* @__PURE__ */ m("div", { className: T(), children: [
|
|
554
|
+
i ? /* @__PURE__ */ m("div", { className: T(), "data-testid": "payment-address", children: [
|
|
555
555
|
/* @__PURE__ */ t("span", { className: _(), children: a("payment.billingAddress") }),
|
|
556
556
|
/* @__PURE__ */ t(
|
|
557
557
|
"div",
|
|
@@ -584,7 +584,7 @@ export {
|
|
|
584
584
|
X as b,
|
|
585
585
|
he as c,
|
|
586
586
|
$ as f,
|
|
587
|
-
|
|
587
|
+
ye as p,
|
|
588
588
|
ee as s
|
|
589
589
|
};
|
|
590
|
-
//# sourceMappingURL=payment-form-
|
|
590
|
+
//# sourceMappingURL=payment-form-B_BdHwjb.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payment-form-C3vT_npe.js","sources":["../../src/tokens/themes/bridges/stripe-appearance.ts","../../src/components/payment-form/payment-form.agent.ts","../../src/components/payment-form/payment-form.tsx"],"sourcesContent":["import type { Appearance } from '@stripe/stripe-js';\n\n/**\n * Reads the current design-system tokens from a theme-root element and maps\n * them to Stripe Elements' Appearance API. `root` defaults to\n * `document.documentElement` but consumers can pass a scoped theme wrapper\n * (e.g. a modal with its own `.theme-accessible` override) so that Stripe\n * iframes pick up the right token set.\n *\n * Tokens referenced: --primary, --background, --foreground, --muted,\n * --muted-foreground, --border, --destructive, --radius-md, --font-sans,\n * --font-size-base, --spacing-sm, --animation-duration, --focus-ring-width,\n * --ring.\n *\n * No hex / rgb / hsl literals — every value flows from the token layer.\n */\n\nfunction isBrowser(): boolean {\n return typeof document !== 'undefined' && typeof window !== 'undefined';\n}\n\nexport function getStripeAppearance(root?: HTMLElement): Appearance {\n if (!isBrowser()) {\n return { theme: 'stripe' };\n }\n\n const target = root ?? document.documentElement;\n const styles = getComputedStyle(target);\n const read = (token: string) => styles.getPropertyValue(token).trim();\n const isDark = target.classList.contains('theme-dark');\n\n return {\n theme: isDark ? 'night' : 'stripe',\n variables: {\n colorPrimary: read('--primary'),\n colorBackground: read('--background'),\n colorText: read('--foreground'),\n colorDanger: read('--destructive'),\n colorTextSecondary: read('--muted-foreground'),\n colorTextPlaceholder: read('--muted-foreground'),\n borderRadius: read('--radius-md'),\n fontFamily: read('--font-sans'),\n fontSizeBase: read('--font-size-base'),\n // Stripe multiplies spacingUnit throughout every Element; --spacing-sm\n // gives readable density. Keep this in sync with the JSDoc above.\n spacingUnit: read('--spacing-sm'),\n },\n rules: {\n '.Input': {\n backgroundColor: read('--background'),\n border: `1px solid ${read('--border')}`,\n color: read('--foreground'),\n padding: read('--spacing-sm'),\n transition: `border-color ${read('--animation-duration')} ease-out`,\n },\n '.Input:focus': {\n borderColor: read('--primary'),\n boxShadow: `0 0 0 ${read('--focus-ring-width')} ${read('--ring')}`,\n outline: 'none',\n },\n '.Input--invalid': {\n borderColor: read('--destructive'),\n color: read('--foreground'),\n },\n '.Label': {\n color: read('--foreground'),\n fontWeight: read('--font-weight-medium'),\n fontSize: read('--font-size-sm'),\n },\n '.Error': {\n color: read('--destructive'),\n fontSize: read('--font-size-sm'),\n },\n '.Tab': {\n border: `1px solid ${read('--border')}`,\n backgroundColor: read('--background'),\n color: read('--foreground'),\n },\n '.Tab--selected': {\n borderColor: read('--primary'),\n backgroundColor: read('--background'),\n color: read('--primary'),\n },\n },\n };\n}\n\n/**\n * Calls `onChange(getStripeAppearance(root))` whenever the theme root's\n * class list mutates (theme switch) or the user toggles\n * `prefers-color-scheme` / `prefers-reduced-motion`. Returns an\n * unsubscribe function.\n */\nexport function subscribeStripeAppearance(\n onChange: (next: Appearance) => void,\n root?: HTMLElement,\n): () => void {\n if (!isBrowser()) return () => undefined;\n\n const target = root ?? document.documentElement;\n const emit = () => onChange(getStripeAppearance(root));\n\n const observer = new MutationObserver(emit);\n observer.observe(target, {\n attributes: true,\n attributeFilter: ['class', 'dir', 'lang'],\n });\n\n const schemeMql = window.matchMedia('(prefers-color-scheme: dark)');\n const motionMql = window.matchMedia('(prefers-reduced-motion: reduce)');\n schemeMql.addEventListener('change', emit);\n motionMql.addEventListener('change', emit);\n\n return () => {\n observer.disconnect();\n schemeMql.removeEventListener('change', emit);\n motionMql.removeEventListener('change', emit);\n };\n}\n","import type { AgentAdapter } from '../../agent/types';\nimport type { PaymentFormHandle } from './payment-form';\n\nexport const paymentFormAgent: AgentAdapter<PaymentFormHandle> = {\n id: 'payment-form',\n capabilities: ['submit'],\n state: {},\n actions: {\n submit: {\n safety: 'destructive',\n description:\n 'Submit the payment. Charges the configured payment method — irreversible.',\n invoke: (handle) => handle.submit(),\n },\n reset: {\n safety: 'destructive',\n description:\n 'Reset the form to its initial state. Loses any in-progress input.',\n invoke: (handle) => {\n handle.reset();\n },\n },\n },\n domHooks: {\n root: { attr: 'data-component', value: 'payment-form' },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n};\n","/* ------------------------------------------------------------------ */\n/* PaymentForm — Stripe Elements wrapper (PCI DSS SAQ-A). */\n/* */\n/* - Library: `@stripe/react-stripe-js` + `@stripe/stripe-js` (see */\n/* `src/docs/08-third-party.mdx §Payments`). Card number, expiry, */\n/* CVC, and postal code all live inside Stripe-hosted iframes on */\n/* `js.stripe.com` — raw PAN never touches our origin, keeping us */\n/* inside PCI DSS SAQ-A scope. */\n/* */\n/* - Theming: the `stripe-appearance` bridge snapshots our tokens into */\n/* Stripe's Appearance API (`variables`, `rules`). A */\n/* `MutationObserver` on `<html class>` re-runs the snapshot when */\n/* the user flips theme so the embedded iframes repaint. */\n/* */\n/* - Security invariants enforced in this file: */\n/* 1. No `<input type=\"tel\" name=\"card\">` anywhere. */\n/* 2. Error strings are sanitised via `stripCardLikeDigits` before */\n/* forwarding to `onError` (replaces any `\\b\\d{4,}\\b` with */\n/* `****`). */\n/* 3. Element change events are never logged; any dev-only logging */\n/* is gated behind `import.meta.env.DEV` — never runs in prod. */\n/* */\n/* TODO: */\n/* - Stripe's `direction: 'rtl'` is not part of the current */\n/* `Appearance` TypeScript type; we rely on CSS mirroring of our */\n/* chrome via logical properties and let Stripe lay out the iframe */\n/* ltr for now. Revisit when @stripe/stripe-js publishes the type. */\n/* - No `<CardNumberElement>` / split-fields story — `PaymentElement` */\n/* handles accordion + card-only modes via its own `layout` option.*/\n/* ------------------------------------------------------------------ */\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type FormEvent,\n} from 'react';\nimport { cva } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Spinner } from '../spinner';\nimport { Alert } from '../alert';\nimport {\n loadStripe,\n type Stripe,\n type Appearance,\n type StripeElementLocale,\n} from '@stripe/stripe-js';\nimport {\n Elements,\n PaymentElement,\n AddressElement,\n useElements,\n useStripe,\n} from '@stripe/react-stripe-js';\n\nimport {\n getStripeAppearance,\n subscribeStripeAppearance,\n} from '../../tokens/themes/bridges/stripe-appearance';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { paymentFormAgent } from './payment-form.agent';\n\n/* ------------------------------------------------------------------ */\n/* Public types */\n/* ------------------------------------------------------------------ */\n\nexport type PaymentCurrency = string; // ISO-4217\n\nexport interface PaymentFormProps {\n /** Opaque instance id — emitted as `data-component-id` for the agent registry. */\n id?: string;\n /** Required — from your server, created via the PaymentIntents API. */\n clientSecret: string;\n /** Stripe publishable key (`pk_test_…` / `pk_live_…`). */\n publishableKey: string;\n /** ISO-4217 currency code (e.g. 'EUR', 'USD', 'JPY'). */\n currency: PaymentCurrency;\n /** Amount in the currency's smallest unit (cents for EUR/USD, yen for JPY). */\n amount: number;\n /** Called with the PaymentIntent id on successful confirmation. */\n onSuccess?: (paymentIntentId: string) => void;\n /** Called with a sanitised error (no PAN digits, no Stripe English strings). */\n onError?: (error: { code: string; translatedMessage: string }) => void;\n /** Show the billing-address collector below the payment fields. */\n billingAddress?: boolean;\n /** Locale override — defaults to the active i18next locale. */\n locale?: string;\n /** Accessible label for the form. */\n ariaLabel?: string;\n /** URL Stripe redirects to when a payment method requires it. */\n returnUrl?: string;\n /** Pre-injected Stripe instance — used by tests + stories to bypass the network. */\n stripePromise?: Promise<Stripe | null> | null;\n className?: string;\n}\n\nexport interface PaymentFormHandle {\n /** Programmatically submit the form (same flow as the Pay button). */\n submit: () => Promise<void>;\n /** Reset the form to its initial state. */\n reset: () => void;\n}\n\n/* ------------------------------------------------------------------ */\n/* Currency helpers */\n/* ------------------------------------------------------------------ */\n\n/**\n * Currencies that Stripe bills in their base unit (no decimals). Source:\n * https://stripe.com/docs/currencies#zero-decimal — list pinned per\n * 08-third-party.mdx.\n */\nconst ZERO_DECIMAL_CURRENCIES = new Set<string>([\n 'BIF',\n 'CLP',\n 'DJF',\n 'GNF',\n 'IDR',\n 'JPY',\n 'KMF',\n 'KRW',\n 'MGA',\n 'PYG',\n 'RWF',\n 'UGX',\n 'VND',\n 'VUV',\n 'XAF',\n 'XOF',\n 'XPF',\n]);\n\nexport function formatPaymentAmount(\n amount: number,\n currency: string,\n locale: string,\n): string {\n const iso = currency.toUpperCase();\n const major = ZERO_DECIMAL_CURRENCIES.has(iso) ? amount : amount / 100;\n try {\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency: iso,\n }).format(major);\n } catch {\n // Invalid locale/currency pair — fall back to a safe format so we\n // never leak raw amount integers into the UI.\n return new Intl.NumberFormat('en', {\n style: 'currency',\n currency: iso,\n }).format(major);\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Return URL validation */\n/* ------------------------------------------------------------------ */\n\n/**\n * Resolve `returnUrl` against the current origin. Accepts:\n * - absolute URLs on the same origin as `window.location`\n * - relative paths (resolved against the current origin)\n * Rejects (returns `null`):\n * - cross-origin URLs — would leak `payment_intent_client_secret`\n * - `javascript:` / `data:` / `file:` / `blob:` schemes\n * - SSR contexts (no `window`) — the submit path requires a browser\n * anyway, so rejecting here is the safer default.\n * See security-hardening.mdx.\n */\nexport function validateReturnUrl(\n returnUrl: string | undefined,\n): string | null {\n if (returnUrl === undefined) return null;\n const raw = returnUrl.trim();\n if (raw === '') return null;\n if (typeof window === 'undefined') return null;\n try {\n const resolved = new URL(raw, window.location.href);\n const allowedSchemes = new Set(['http:', 'https:']);\n if (!allowedSchemes.has(resolved.protocol)) return null;\n if (resolved.origin !== window.location.origin) return null;\n return resolved.toString();\n } catch {\n return null;\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Error sanitisation */\n/* ------------------------------------------------------------------ */\n\n/**\n * Replace any run of 4+ consecutive digits with `****`. Called before any\n * error text leaves the wrapper. Defensive: even though Stripe's error\n * strings don't normally contain PANs, a future SDK change could, and we\n * want a hard guarantee that `console` / analytics / Sentry breadcrumbs\n * stay clear of anything that looks like card data.\n */\nexport function stripCardLikeDigits(message: string): string {\n if (!message) return message;\n // Deliberately no word boundaries: a PAN run embedded between word\n // characters (e.g. \"CARD4242424242424242DECLINED\") must still be masked.\n return message.replace(/\\d{4,}/g, '****');\n}\n\n/**\n * Map a Stripe error code (e.g. `card_declined`, `incorrect_number`) to a\n * translation key under `payment.error.*`. Unknown codes fall through to\n * `payment.error.generic`.\n */\nexport function stripeErrorCodeToI18nKey(code: string | undefined): string {\n switch (code) {\n case 'incorrect_number':\n case 'invalid_number':\n return 'payment.error.cardNumber';\n case 'invalid_expiry_month':\n case 'invalid_expiry_year':\n case 'expired_card':\n return 'payment.error.expiry';\n case 'invalid_cvc':\n case 'incorrect_cvc':\n return 'payment.error.cvc';\n case 'incorrect_zip':\n case 'invalid_zip':\n return 'payment.error.postalCode';\n case 'card_declined':\n case 'do_not_honor':\n case 'generic_decline':\n return 'payment.error.declined';\n case 'network_error':\n case 'api_connection_error':\n return 'payment.error.network';\n default:\n return 'payment.error.generic';\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst formVariants = cva(\n [\n 'ds:payment-form-alfadocs ds:flex ds:flex-col',\n 'ds:gap-[var(--spacing-md)]',\n 'ds:bg-[var(--background)] ds:text-[var(--foreground)]',\n 'ds:rounded-[var(--radius-md)] ds:border ds:border-[color:var(--border)]',\n 'ds:p-[var(--spacing-md)]',\n 'ds:aria-disabled:opacity-[var(--opacity-50)] ds:aria-disabled:cursor-not-allowed',\n ].join(' '),\n);\n\nconst fieldLabelVariants = cva(\n ['ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]'].join(' '),\n);\n\nconst labelTextVariants = cva(\n ['type-label', 'ds:text-[var(--foreground)]'].join(' '),\n);\n\nconst amountSummaryVariants = cva(\n [\n 'ds:flex ds:items-baseline ds:justify-between',\n 'ds:gap-[var(--spacing-sm)]',\n 'ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)]',\n 'ds:pt-[var(--spacing-xs)] ds:pb-[var(--spacing-xs)]',\n 'ds:bg-[var(--muted)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:text-[var(--foreground)]',\n ].join(' '),\n);\n\nconst submitButtonVariants = cva(\n [\n 'ds:inline-flex ds:items-center ds:justify-center ds:gap-[var(--spacing-xs)]',\n 'ds:min-block-size-[var(--min-target-size)]',\n 'ds:min-inline-size-[var(--min-target-size)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:bg-[var(--primary)] ds:text-[var(--primary-foreground)]',\n 'ds:text-[length:var(--font-size-base)] ds:font-medium',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:hover:bg-[var(--primary-hover)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[var(--ring)]',\n 'ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n 'ds:aria-disabled:opacity-[var(--opacity-50)] ds:aria-disabled:cursor-not-allowed',\n 'ds:aria-busy:cursor-wait',\n ].join(' '),\n);\n\n/* ------------------------------------------------------------------ */\n/* Inner form — lives inside the <Elements> provider */\n/* ------------------------------------------------------------------ */\n\ninterface InnerPaymentFormProps {\n amount: number;\n currency: string;\n locale: string;\n billingAddress: boolean;\n returnUrl: string | undefined;\n onSuccess: PaymentFormProps['onSuccess'];\n onError: PaymentFormProps['onError'];\n}\n\nfunction InnerPaymentForm(props: InnerPaymentFormProps): JSX.Element {\n const {\n amount,\n currency,\n locale,\n billingAddress,\n returnUrl,\n onSuccess,\n onError,\n } = props;\n\n const { t } = useTranslation();\n const stripe = useStripe();\n const elements = useElements();\n\n const rawId = useId();\n const idSafe = useMemo(\n () => `pay-${rawId.replace(/[^a-zA-Z0-9-_]/g, '')}`,\n [rawId],\n );\n const paymentFieldId = `${idSafe}-payment`;\n const addressFieldId = `${idSafe}-address`;\n const errorId = `${idSafe}-error`;\n\n const [processing, setProcessing] = useState(false);\n const [elementComplete, setElementComplete] = useState(false);\n const [errorKey, setErrorKey] = useState<string | null>(null);\n const [errorMessage, setErrorMessage] = useState<string>('');\n\n const onSuccessRef = useRef(onSuccess);\n const onErrorRef = useRef(onError);\n useEffect(() => {\n onSuccessRef.current = onSuccess;\n onErrorRef.current = onError;\n }, [onSuccess, onError]);\n\n const handleSubmit = useCallback(\n async (event?: FormEvent<HTMLFormElement>): Promise<void> => {\n if (event) event.preventDefault();\n if (!stripe || !elements) return;\n if (processing) return;\n\n setProcessing(true);\n setErrorKey(null);\n setErrorMessage('');\n\n // Validate returnUrl at the boundary so even a careless consumer\n // cannot leak payment_intent_client_secret to a third-party origin.\n const safeReturnUrl = validateReturnUrl(returnUrl);\n if (returnUrl !== undefined && safeReturnUrl === null) {\n setErrorKey('payment.error.invalidReturnUrl');\n setErrorMessage(t('payment.error.invalidReturnUrl'));\n onErrorRef.current?.({\n code: 'invalid_return_url',\n translatedMessage: t('payment.error.invalidReturnUrl'),\n });\n setProcessing(false);\n return;\n }\n try {\n const result = await stripe.confirmPayment({\n elements,\n confirmParams: safeReturnUrl ? { return_url: safeReturnUrl } : {},\n redirect: 'if_required',\n });\n\n if (result.error) {\n const code = result.error.code ?? 'generic';\n const key = stripeErrorCodeToI18nKey(code);\n // CRITICAL: sanitise before storing OR forwarding.\n const safe = stripCardLikeDigits(result.error.message ?? '');\n setErrorKey(key);\n setErrorMessage(t(key));\n onErrorRef.current?.({\n code,\n translatedMessage: safe || t(key),\n });\n return;\n }\n\n // Success path — only the PaymentIntent id leaves the wrapper.\n if (result.paymentIntent) {\n onSuccessRef.current?.(result.paymentIntent.id);\n }\n } catch (err: unknown) {\n const raw = err instanceof Error ? err.message : '';\n const safe = stripCardLikeDigits(raw);\n setErrorKey('payment.error.generic');\n setErrorMessage(t('payment.error.generic'));\n onErrorRef.current?.({\n code: 'unexpected',\n translatedMessage: safe || t('payment.error.generic'),\n });\n } finally {\n setProcessing(false);\n }\n },\n [stripe, elements, processing, returnUrl, t],\n );\n\n // Imperative submit hook used by the outer component's ref handle.\n useEffect(() => {\n const host = document.getElementById(idSafe);\n if (!host) return;\n const submitter = () => {\n void handleSubmit();\n };\n host.addEventListener('payment-form:submit', submitter);\n return () => host.removeEventListener('payment-form:submit', submitter);\n }, [idSafe, handleSubmit]);\n\n const submitDisabled = !stripe || !elements || !elementComplete || processing;\n\n return (\n <form\n id={idSafe}\n onSubmit={handleSubmit}\n aria-label={t('payment.ariaLabel')}\n aria-busy={processing || undefined}\n noValidate\n >\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <div className={amountSummaryVariants()}>\n <span className={labelTextVariants()}>\n {t('payment.amountLabel')}\n </span>\n <span className=\"type-title-card\" data-testid=\"payment-amount\">\n {formatPaymentAmount(amount, currency, locale)}\n </span>\n </div>\n\n <label\n htmlFor={paymentFieldId}\n className={fieldLabelVariants()}\n data-testid=\"payment-field\"\n >\n <span className={labelTextVariants()}>\n {t('payment.fields.card')}\n </span>\n <PaymentElement\n id={paymentFieldId}\n options={{\n layout: { type: 'accordion', defaultCollapsed: false },\n }}\n onChange={(ev) => {\n // NOTE: never log `ev` — change events may include hints\n // about field contents. Keep only the boolean completeness.\n setElementComplete(ev.complete === true);\n if (ev.complete) {\n setErrorKey(null);\n setErrorMessage('');\n }\n }}\n />\n </label>\n\n {billingAddress ? (\n <label\n htmlFor={addressFieldId}\n className={fieldLabelVariants()}\n data-testid=\"payment-address\"\n >\n <span className={labelTextVariants()}>\n {t('payment.billingAddress')}\n </span>\n <AddressElement id={addressFieldId} options={{ mode: 'billing' }} />\n </label>\n ) : null}\n\n {errorKey ? (\n <Alert\n id={errorId}\n variant=\"error\"\n live=\"polite\"\n data-testid=\"payment-error\"\n >\n <Alert.Description>{errorMessage}</Alert.Description>\n </Alert>\n ) : null}\n\n <button\n type=\"submit\"\n aria-disabled={submitDisabled || undefined}\n aria-busy={processing || undefined}\n aria-describedby={errorKey ? errorId : undefined}\n className={submitButtonVariants()}\n data-testid=\"payment-submit\"\n >\n {processing ? (\n <>\n <Spinner size=\"sm\" label={t('payment.processing')} />\n <span>{t('payment.processing')}</span>\n </>\n ) : (\n <span>\n {t('payment.submit', {\n amount: formatPaymentAmount(amount, currency, locale),\n })}\n </span>\n )}\n </button>\n </div>\n </form>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* PaymentForm — outer wrapper */\n/* ------------------------------------------------------------------ */\n\n/**\n * Stripe ships a closed union of supported locales; anything outside it\n * must fall through to `'auto'` (Stripe picks the best match from the\n * browser). We also normalise the legacy `cn` code to `zh` per\n * `src/docs/06-i18n.mdx`.\n */\nconst STRIPE_LOCALES = new Set<StripeElementLocale>([\n 'auto',\n 'ar',\n 'bg',\n 'cs',\n 'da',\n 'de',\n 'el',\n 'en',\n 'en-AU',\n 'en-CA',\n 'en-NZ',\n 'en-GB',\n 'es',\n 'es-ES',\n 'es-419',\n 'et',\n 'fi',\n 'fil',\n 'fr',\n 'fr-CA',\n 'fr-FR',\n 'he',\n 'hu',\n 'hr',\n 'id',\n 'it',\n 'it-IT',\n 'ja',\n 'ko',\n 'lt',\n 'lv',\n 'ms',\n 'mt',\n 'nb',\n 'nl',\n 'no',\n 'pl',\n 'pt',\n 'pt-BR',\n 'ro',\n 'ru',\n 'sk',\n 'sl',\n 'sv',\n 'th',\n 'tr',\n 'vi',\n 'zh',\n 'zh-HK',\n 'zh-TW',\n]);\n\nfunction normaliseLocale(input: string): StripeElementLocale {\n if (!input) return 'auto';\n const candidate = input === 'cn' ? 'zh' : input;\n if ((STRIPE_LOCALES as Set<string>).has(candidate)) {\n return candidate as StripeElementLocale;\n }\n // Try stripping region (\"en-US\" → \"en\") before giving up.\n const base = candidate.split('-')[0];\n if ((STRIPE_LOCALES as Set<string>).has(base)) {\n return base as StripeElementLocale;\n }\n return 'auto';\n}\n\nexport const PaymentForm = forwardRef<HTMLDivElement, PaymentFormProps>(\n (\n {\n id,\n clientSecret,\n publishableKey,\n currency,\n amount,\n onSuccess,\n onError,\n billingAddress = false,\n locale,\n ariaLabel,\n returnUrl,\n stripePromise: injectedStripe,\n className,\n },\n ref,\n ) => {\n const { i18n } = useTranslation();\n const activeLocale = normaliseLocale(locale ?? i18n.language ?? 'en');\n\n // Stripe instance — pre-injected (tests/stories) or lazily loaded.\n const [stripeInstance, setStripeInstance] =\n useState<Promise<Stripe | null> | null>(injectedStripe ?? null);\n\n useEffect(() => {\n if (injectedStripe !== undefined) {\n setStripeInstance(injectedStripe);\n return;\n }\n if (!publishableKey) {\n setStripeInstance(null);\n return;\n }\n // `loadStripe` is cached by the SDK — safe to call per mount.\n setStripeInstance(loadStripe(publishableKey));\n }, [injectedStripe, publishableKey]);\n\n // Appearance bridge — snapshot + subscribe.\n const [appearance, setAppearance] = useState<Appearance>(() =>\n getStripeAppearance(),\n );\n useEffect(() => {\n setAppearance(getStripeAppearance());\n const unsubscribe = subscribeStripeAppearance(setAppearance);\n return unsubscribe;\n }, []);\n\n // Imperative handle — dispatch a custom event at the inner form so we\n // can trigger the same submit path as the button without leaking refs\n // through the Stripe `<Elements>` provider (which owns its own tree).\n const hostRef = useRef<HTMLDivElement>(null);\n\n const agentHandle = useMemo<PaymentFormHandle>(\n () => ({\n submit: async () => {\n const form = hostRef.current?.querySelector('form');\n if (form) {\n form.dispatchEvent(\n new CustomEvent('payment-form:submit', { bubbles: true }),\n );\n }\n },\n reset: () => {\n const form = hostRef.current?.querySelector('form');\n if (form instanceof HTMLFormElement) {\n form.reset();\n }\n },\n }),\n [],\n );\n useImperativeHandle(ref, () => hostRef.current as HTMLDivElement, []);\n useAgentRegistration(paymentFormAgent, agentHandle, id);\n\n const elementsOptions = useMemo(\n () => ({\n clientSecret,\n appearance,\n locale: activeLocale,\n }),\n [clientSecret, appearance, activeLocale],\n );\n\n return (\n <div\n ref={hostRef}\n aria-label={ariaLabel}\n className={[formVariants(), className].filter(Boolean).join(' ')}\n data-component=\"payment-form\"\n data-component-id={id}\n data-testid=\"payment-form-root\"\n >\n {stripeInstance && clientSecret ? (\n <Elements\n stripe={stripeInstance}\n options={elementsOptions}\n key={clientSecret}\n >\n <InnerPaymentForm\n amount={amount}\n currency={currency}\n locale={activeLocale}\n billingAddress={billingAddress}\n returnUrl={returnUrl}\n onSuccess={onSuccess}\n onError={onError}\n />\n </Elements>\n ) : (\n <PaymentFormSkeleton\n amount={amount}\n currency={currency}\n locale={activeLocale}\n billingAddress={billingAddress}\n />\n )}\n </div>\n );\n },\n);\n\nPaymentForm.displayName = 'PaymentForm';\n\n/* ------------------------------------------------------------------ */\n/* Skeleton — visual chrome when Stripe hasn't loaded yet */\n/* ------------------------------------------------------------------ */\n\ninterface PaymentFormSkeletonProps {\n amount: number;\n currency: string;\n locale: string;\n billingAddress: boolean;\n}\n\nfunction PaymentFormSkeleton(props: PaymentFormSkeletonProps): JSX.Element {\n const { amount, currency, locale, billingAddress } = props;\n const { t } = useTranslation();\n\n return (\n <div\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\"\n data-testid=\"payment-skeleton\"\n aria-busy=\"true\"\n >\n <div className={amountSummaryVariants()}>\n <span className={labelTextVariants()}>{t('payment.amountLabel')}</span>\n <span className=\"type-title-card\">\n {formatPaymentAmount(amount, currency, locale)}\n </span>\n </div>\n <div className={fieldLabelVariants()}>\n <span className={labelTextVariants()}>{t('payment.fields.card')}</span>\n <div\n className=\"ds:min-block-size-[var(--min-target-size)] ds:rounded-[var(--radius-sm)] ds:border ds:border-[color:var(--border)] ds:bg-[var(--muted)]\"\n aria-hidden=\"true\"\n />\n </div>\n {billingAddress ? (\n <div className={fieldLabelVariants()}>\n <span className={labelTextVariants()}>\n {t('payment.billingAddress')}\n </span>\n <div\n className=\"ds:min-block-size-[calc(var(--min-target-size)*2)] ds:rounded-[var(--radius-sm)] ds:border ds:border-[color:var(--border)] ds:bg-[var(--muted)]\"\n aria-hidden=\"true\"\n />\n </div>\n ) : null}\n <button\n type=\"button\"\n aria-disabled=\"true\"\n className={submitButtonVariants()}\n disabled\n >\n <Spinner size=\"sm\" label={t('payment.processing')} />\n <span>{t('payment.processing')}</span>\n </button>\n </div>\n );\n}\n\nexport {\n formVariants as paymentFormVariants,\n submitButtonVariants as paymentSubmitButtonVariants,\n};\n"],"names":["isBrowser","getStripeAppearance","root","target","styles","read","token","subscribeStripeAppearance","onChange","emit","observer","schemeMql","motionMql","paymentFormAgent","handle","ZERO_DECIMAL_CURRENCIES","formatPaymentAmount","amount","currency","locale","iso","major","validateReturnUrl","returnUrl","raw","resolved","stripCardLikeDigits","message","stripeErrorCodeToI18nKey","code","formVariants","cva","fieldLabelVariants","labelTextVariants","amountSummaryVariants","submitButtonVariants","InnerPaymentForm","props","billingAddress","onSuccess","onError","t","useTranslation","stripe","useStripe","elements","useElements","rawId","useId","idSafe","useMemo","paymentFieldId","addressFieldId","errorId","processing","setProcessing","useState","elementComplete","setElementComplete","errorKey","setErrorKey","errorMessage","setErrorMessage","onSuccessRef","useRef","onErrorRef","useEffect","handleSubmit","useCallback","event","safeReturnUrl","_a","result","key","safe","_b","_c","err","_d","host","submitter","submitDisabled","jsx","jsxs","PaymentElement","ev","AddressElement","Alert","Fragment","Spinner","STRIPE_LOCALES","normaliseLocale","input","candidate","base","PaymentForm","forwardRef","id","clientSecret","publishableKey","ariaLabel","injectedStripe","className","ref","i18n","activeLocale","stripeInstance","setStripeInstance","loadStripe","appearance","setAppearance","hostRef","agentHandle","form","useImperativeHandle","useAgentRegistration","elementsOptions","Elements","PaymentFormSkeleton"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"payment-form-B_BdHwjb.js","sources":["../../src/tokens/themes/bridges/stripe-appearance.ts","../../src/components/payment-form/payment-form.agent.ts","../../src/components/payment-form/payment-form.tsx"],"sourcesContent":["import type { Appearance } from '@stripe/stripe-js';\n\n/**\n * Reads the current design-system tokens from a theme-root element and maps\n * them to Stripe Elements' Appearance API. `root` defaults to\n * `document.documentElement` but consumers can pass a scoped theme wrapper\n * (e.g. a modal with its own `.theme-accessible` override) so that Stripe\n * iframes pick up the right token set.\n *\n * Tokens referenced: --primary, --background, --foreground, --muted,\n * --muted-foreground, --border, --destructive, --radius-md, --font-sans,\n * --font-size-base, --spacing-sm, --animation-duration, --focus-ring-width,\n * --ring.\n *\n * No hex / rgb / hsl literals — every value flows from the token layer.\n */\n\nfunction isBrowser(): boolean {\n return typeof document !== 'undefined' && typeof window !== 'undefined';\n}\n\nexport function getStripeAppearance(root?: HTMLElement): Appearance {\n if (!isBrowser()) {\n return { theme: 'stripe' };\n }\n\n const target = root ?? document.documentElement;\n const styles = getComputedStyle(target);\n const read = (token: string) => styles.getPropertyValue(token).trim();\n const isDark = target.classList.contains('theme-dark');\n\n return {\n theme: isDark ? 'night' : 'stripe',\n variables: {\n colorPrimary: read('--primary'),\n colorBackground: read('--background'),\n colorText: read('--foreground'),\n colorDanger: read('--destructive'),\n colorTextSecondary: read('--muted-foreground'),\n colorTextPlaceholder: read('--muted-foreground'),\n borderRadius: read('--radius-md'),\n fontFamily: read('--font-sans'),\n fontSizeBase: read('--font-size-base'),\n // Stripe multiplies spacingUnit throughout every Element; --spacing-sm\n // gives readable density. Keep this in sync with the JSDoc above.\n spacingUnit: read('--spacing-sm'),\n },\n rules: {\n '.Input': {\n backgroundColor: read('--background'),\n border: `1px solid ${read('--border')}`,\n color: read('--foreground'),\n padding: read('--spacing-sm'),\n transition: `border-color ${read('--animation-duration')} ease-out`,\n },\n '.Input:focus': {\n borderColor: read('--primary'),\n boxShadow: `0 0 0 ${read('--focus-ring-width')} ${read('--ring')}`,\n outline: 'none',\n },\n '.Input--invalid': {\n borderColor: read('--destructive'),\n color: read('--foreground'),\n },\n '.Label': {\n color: read('--foreground'),\n fontWeight: read('--font-weight-medium'),\n fontSize: read('--font-size-sm'),\n },\n '.Error': {\n color: read('--destructive'),\n fontSize: read('--font-size-sm'),\n },\n '.Tab': {\n border: `1px solid ${read('--border')}`,\n backgroundColor: read('--background'),\n color: read('--foreground'),\n },\n '.Tab--selected': {\n borderColor: read('--primary'),\n backgroundColor: read('--background'),\n color: read('--primary'),\n },\n },\n };\n}\n\n/**\n * Calls `onChange(getStripeAppearance(root))` whenever the theme root's\n * class list mutates (theme switch) or the user toggles\n * `prefers-color-scheme` / `prefers-reduced-motion`. Returns an\n * unsubscribe function.\n */\nexport function subscribeStripeAppearance(\n onChange: (next: Appearance) => void,\n root?: HTMLElement,\n): () => void {\n if (!isBrowser()) return () => undefined;\n\n const target = root ?? document.documentElement;\n const emit = () => onChange(getStripeAppearance(root));\n\n const observer = new MutationObserver(emit);\n observer.observe(target, {\n attributes: true,\n attributeFilter: ['class', 'dir', 'lang'],\n });\n\n const schemeMql = window.matchMedia('(prefers-color-scheme: dark)');\n const motionMql = window.matchMedia('(prefers-reduced-motion: reduce)');\n schemeMql.addEventListener('change', emit);\n motionMql.addEventListener('change', emit);\n\n return () => {\n observer.disconnect();\n schemeMql.removeEventListener('change', emit);\n motionMql.removeEventListener('change', emit);\n };\n}\n","import type { AgentAdapter } from '../../agent/types';\nimport type { PaymentFormHandle } from './payment-form';\n\nexport const paymentFormAgent: AgentAdapter<PaymentFormHandle> = {\n id: 'payment-form',\n capabilities: ['submit'],\n state: {},\n actions: {\n submit: {\n safety: 'destructive',\n description:\n 'Submit the payment. Charges the configured payment method — irreversible.',\n invoke: (handle) => handle.submit(),\n },\n reset: {\n safety: 'destructive',\n description:\n 'Reset the form to its initial state. Loses any in-progress input.',\n invoke: (handle) => {\n handle.reset();\n },\n },\n },\n domHooks: {\n root: { attr: 'data-component', value: 'payment-form' },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n};\n","/* ------------------------------------------------------------------ */\n/* PaymentForm — Stripe Elements wrapper (PCI DSS SAQ-A). */\n/* */\n/* - Library: `@stripe/react-stripe-js` + `@stripe/stripe-js` (see */\n/* `src/docs/08-third-party.mdx §Payments`). Card number, expiry, */\n/* CVC, and postal code all live inside Stripe-hosted iframes on */\n/* `js.stripe.com` — raw PAN never touches our origin, keeping us */\n/* inside PCI DSS SAQ-A scope. */\n/* */\n/* - Theming: the `stripe-appearance` bridge snapshots our tokens into */\n/* Stripe's Appearance API (`variables`, `rules`). A */\n/* `MutationObserver` on `<html class>` re-runs the snapshot when */\n/* the user flips theme so the embedded iframes repaint. */\n/* */\n/* - Security invariants enforced in this file: */\n/* 1. No `<input type=\"tel\" name=\"card\">` anywhere. */\n/* 2. Error strings are sanitised via `stripCardLikeDigits` before */\n/* forwarding to `onError` (replaces any `\\b\\d{4,}\\b` with */\n/* `****`). */\n/* 3. Element change events are never logged; any dev-only logging */\n/* is gated behind `import.meta.env.DEV` — never runs in prod. */\n/* */\n/* TODO: */\n/* - Stripe's `direction: 'rtl'` is not part of the current */\n/* `Appearance` TypeScript type; we rely on CSS mirroring of our */\n/* chrome via logical properties and let Stripe lay out the iframe */\n/* ltr for now. Revisit when @stripe/stripe-js publishes the type. */\n/* - No `<CardNumberElement>` / split-fields story — `PaymentElement` */\n/* handles accordion + card-only modes via its own `layout` option.*/\n/* ------------------------------------------------------------------ */\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type FormEvent,\n} from 'react';\nimport { cva } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Spinner } from '../spinner';\nimport { Alert } from '../alert';\nimport {\n loadStripe,\n type Stripe,\n type Appearance,\n type StripeElementLocale,\n} from '@stripe/stripe-js';\nimport {\n Elements,\n PaymentElement,\n AddressElement,\n useElements,\n useStripe,\n} from '@stripe/react-stripe-js';\n\nimport {\n getStripeAppearance,\n subscribeStripeAppearance,\n} from '../../tokens/themes/bridges/stripe-appearance';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { paymentFormAgent } from './payment-form.agent';\n\n/* ------------------------------------------------------------------ */\n/* Public types */\n/* ------------------------------------------------------------------ */\n\nexport type PaymentCurrency = string; // ISO-4217\n\nexport interface PaymentFormProps {\n /** Opaque instance id — emitted as `data-component-id` for the agent registry. */\n id?: string;\n /** Required — from your server, created via the PaymentIntents API. */\n clientSecret: string;\n /** Stripe publishable key (`pk_test_…` / `pk_live_…`). */\n publishableKey: string;\n /** ISO-4217 currency code (e.g. 'EUR', 'USD', 'JPY'). */\n currency: PaymentCurrency;\n /** Amount in the currency's smallest unit (cents for EUR/USD, yen for JPY). */\n amount: number;\n /** Called with the PaymentIntent id on successful confirmation. */\n onSuccess?: (paymentIntentId: string) => void;\n /** Called with a sanitised error (no PAN digits, no Stripe English strings). */\n onError?: (error: { code: string; translatedMessage: string }) => void;\n /** Show the billing-address collector below the payment fields. */\n billingAddress?: boolean;\n /** Locale override — defaults to the active i18next locale. */\n locale?: string;\n /** Accessible label for the form. */\n ariaLabel?: string;\n /** URL Stripe redirects to when a payment method requires it. */\n returnUrl?: string;\n /** Pre-injected Stripe instance — used by tests + stories to bypass the network. */\n stripePromise?: Promise<Stripe | null> | null;\n className?: string;\n}\n\nexport interface PaymentFormHandle {\n /** Programmatically submit the form (same flow as the Pay button). */\n submit: () => Promise<void>;\n /** Reset the form to its initial state. */\n reset: () => void;\n}\n\n/* ------------------------------------------------------------------ */\n/* Currency helpers */\n/* ------------------------------------------------------------------ */\n\n/**\n * Currencies that Stripe bills in their base unit (no decimals). Source:\n * https://stripe.com/docs/currencies#zero-decimal — list pinned per\n * 08-third-party.mdx.\n */\nconst ZERO_DECIMAL_CURRENCIES = new Set<string>([\n 'BIF',\n 'CLP',\n 'DJF',\n 'GNF',\n 'IDR',\n 'JPY',\n 'KMF',\n 'KRW',\n 'MGA',\n 'PYG',\n 'RWF',\n 'UGX',\n 'VND',\n 'VUV',\n 'XAF',\n 'XOF',\n 'XPF',\n]);\n\nexport function formatPaymentAmount(\n amount: number,\n currency: string,\n locale: string,\n): string {\n const iso = currency.toUpperCase();\n const major = ZERO_DECIMAL_CURRENCIES.has(iso) ? amount : amount / 100;\n try {\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency: iso,\n }).format(major);\n } catch {\n // Invalid locale/currency pair — fall back to a safe format so we\n // never leak raw amount integers into the UI.\n return new Intl.NumberFormat('en', {\n style: 'currency',\n currency: iso,\n }).format(major);\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Return URL validation */\n/* ------------------------------------------------------------------ */\n\n/**\n * Resolve `returnUrl` against the current origin. Accepts:\n * - absolute URLs on the same origin as `window.location`\n * - relative paths (resolved against the current origin)\n * Rejects (returns `null`):\n * - cross-origin URLs — would leak `payment_intent_client_secret`\n * - `javascript:` / `data:` / `file:` / `blob:` schemes\n * - SSR contexts (no `window`) — the submit path requires a browser\n * anyway, so rejecting here is the safer default.\n * See security-hardening.mdx.\n */\nexport function validateReturnUrl(\n returnUrl: string | undefined,\n): string | null {\n if (returnUrl === undefined) return null;\n const raw = returnUrl.trim();\n if (raw === '') return null;\n if (typeof window === 'undefined') return null;\n try {\n const resolved = new URL(raw, window.location.href);\n const allowedSchemes = new Set(['http:', 'https:']);\n if (!allowedSchemes.has(resolved.protocol)) return null;\n if (resolved.origin !== window.location.origin) return null;\n return resolved.toString();\n } catch {\n return null;\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Error sanitisation */\n/* ------------------------------------------------------------------ */\n\n/**\n * Replace any run of 4+ consecutive digits with `****`. Called before any\n * error text leaves the wrapper. Defensive: even though Stripe's error\n * strings don't normally contain PANs, a future SDK change could, and we\n * want a hard guarantee that `console` / analytics / Sentry breadcrumbs\n * stay clear of anything that looks like card data.\n */\nexport function stripCardLikeDigits(message: string): string {\n if (!message) return message;\n // Deliberately no word boundaries: a PAN run embedded between word\n // characters (e.g. \"CARD4242424242424242DECLINED\") must still be masked.\n return message.replace(/\\d{4,}/g, '****');\n}\n\n/**\n * Map a Stripe error code (e.g. `card_declined`, `incorrect_number`) to a\n * translation key under `payment.error.*`. Unknown codes fall through to\n * `payment.error.generic`.\n */\nexport function stripeErrorCodeToI18nKey(code: string | undefined): string {\n switch (code) {\n case 'incorrect_number':\n case 'invalid_number':\n return 'payment.error.cardNumber';\n case 'invalid_expiry_month':\n case 'invalid_expiry_year':\n case 'expired_card':\n return 'payment.error.expiry';\n case 'invalid_cvc':\n case 'incorrect_cvc':\n return 'payment.error.cvc';\n case 'incorrect_zip':\n case 'invalid_zip':\n return 'payment.error.postalCode';\n case 'card_declined':\n case 'do_not_honor':\n case 'generic_decline':\n return 'payment.error.declined';\n case 'network_error':\n case 'api_connection_error':\n return 'payment.error.network';\n default:\n return 'payment.error.generic';\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst formVariants = cva(\n [\n 'ds:payment-form-alfadocs ds:flex ds:flex-col',\n 'ds:gap-[var(--spacing-md)]',\n 'ds:bg-[var(--background)] ds:text-[var(--foreground)]',\n 'ds:rounded-[var(--radius-md)] ds:border ds:border-[color:var(--border)]',\n 'ds:p-[var(--spacing-md)]',\n 'ds:aria-disabled:opacity-[var(--opacity-50)] ds:aria-disabled:cursor-not-allowed',\n ].join(' '),\n);\n\nconst fieldLabelVariants = cva(\n ['ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]'].join(' '),\n);\n\nconst labelTextVariants = cva(\n ['type-label', 'ds:text-[var(--foreground)]'].join(' '),\n);\n\nconst amountSummaryVariants = cva(\n [\n 'ds:flex ds:items-baseline ds:justify-between',\n 'ds:gap-[var(--spacing-sm)]',\n 'ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)]',\n 'ds:pt-[var(--spacing-xs)] ds:pb-[var(--spacing-xs)]',\n 'ds:bg-[var(--muted)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:text-[var(--foreground)]',\n ].join(' '),\n);\n\nconst submitButtonVariants = cva(\n [\n 'ds:inline-flex ds:items-center ds:justify-center ds:gap-[var(--spacing-xs)]',\n 'ds:min-block-size-[var(--min-target-size)]',\n 'ds:min-inline-size-[var(--min-target-size)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:bg-[var(--primary)] ds:text-[var(--primary-foreground)]',\n 'ds:text-[length:var(--font-size-base)] ds:font-medium',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:hover:bg-[var(--primary-hover)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[var(--ring)]',\n 'ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n 'ds:aria-disabled:opacity-[var(--opacity-50)] ds:aria-disabled:cursor-not-allowed',\n 'ds:aria-busy:cursor-wait',\n ].join(' '),\n);\n\n/* ------------------------------------------------------------------ */\n/* Inner form — lives inside the <Elements> provider */\n/* ------------------------------------------------------------------ */\n\ninterface InnerPaymentFormProps {\n amount: number;\n currency: string;\n locale: string;\n billingAddress: boolean;\n returnUrl: string | undefined;\n onSuccess: PaymentFormProps['onSuccess'];\n onError: PaymentFormProps['onError'];\n}\n\nfunction InnerPaymentForm(props: InnerPaymentFormProps): JSX.Element {\n const {\n amount,\n currency,\n locale,\n billingAddress,\n returnUrl,\n onSuccess,\n onError,\n } = props;\n\n const { t } = useTranslation();\n const stripe = useStripe();\n const elements = useElements();\n\n const rawId = useId();\n const idSafe = useMemo(\n () => `pay-${rawId.replace(/[^a-zA-Z0-9-_]/g, '')}`,\n [rawId],\n );\n const paymentFieldId = `${idSafe}-payment`;\n const addressFieldId = `${idSafe}-address`;\n const errorId = `${idSafe}-error`;\n\n const [processing, setProcessing] = useState(false);\n const [elementComplete, setElementComplete] = useState(false);\n const [errorKey, setErrorKey] = useState<string | null>(null);\n const [errorMessage, setErrorMessage] = useState<string>('');\n\n const onSuccessRef = useRef(onSuccess);\n const onErrorRef = useRef(onError);\n useEffect(() => {\n onSuccessRef.current = onSuccess;\n onErrorRef.current = onError;\n }, [onSuccess, onError]);\n\n const handleSubmit = useCallback(\n async (event?: FormEvent<HTMLFormElement>): Promise<void> => {\n if (event) event.preventDefault();\n if (!stripe || !elements) return;\n if (processing) return;\n\n setProcessing(true);\n setErrorKey(null);\n setErrorMessage('');\n\n // Validate returnUrl at the boundary so even a careless consumer\n // cannot leak payment_intent_client_secret to a third-party origin.\n const safeReturnUrl = validateReturnUrl(returnUrl);\n if (returnUrl !== undefined && safeReturnUrl === null) {\n setErrorKey('payment.error.invalidReturnUrl');\n setErrorMessage(t('payment.error.invalidReturnUrl'));\n onErrorRef.current?.({\n code: 'invalid_return_url',\n translatedMessage: t('payment.error.invalidReturnUrl'),\n });\n setProcessing(false);\n return;\n }\n try {\n const result = await stripe.confirmPayment({\n elements,\n confirmParams: safeReturnUrl ? { return_url: safeReturnUrl } : {},\n redirect: 'if_required',\n });\n\n if (result.error) {\n const code = result.error.code ?? 'generic';\n const key = stripeErrorCodeToI18nKey(code);\n // CRITICAL: sanitise before storing OR forwarding.\n const safe = stripCardLikeDigits(result.error.message ?? '');\n setErrorKey(key);\n setErrorMessage(t(key));\n onErrorRef.current?.({\n code,\n translatedMessage: safe || t(key),\n });\n return;\n }\n\n // Success path — only the PaymentIntent id leaves the wrapper.\n if (result.paymentIntent) {\n onSuccessRef.current?.(result.paymentIntent.id);\n }\n } catch (err: unknown) {\n const raw = err instanceof Error ? err.message : '';\n const safe = stripCardLikeDigits(raw);\n setErrorKey('payment.error.generic');\n setErrorMessage(t('payment.error.generic'));\n onErrorRef.current?.({\n code: 'unexpected',\n translatedMessage: safe || t('payment.error.generic'),\n });\n } finally {\n setProcessing(false);\n }\n },\n [stripe, elements, processing, returnUrl, t],\n );\n\n // Imperative submit hook used by the outer component's ref handle.\n useEffect(() => {\n const host = document.getElementById(idSafe);\n if (!host) return;\n const submitter = () => {\n void handleSubmit();\n };\n host.addEventListener('payment-form:submit', submitter);\n return () => host.removeEventListener('payment-form:submit', submitter);\n }, [idSafe, handleSubmit]);\n\n const submitDisabled = !stripe || !elements || !elementComplete || processing;\n\n return (\n <form\n id={idSafe}\n onSubmit={handleSubmit}\n aria-label={t('payment.ariaLabel')}\n aria-busy={processing || undefined}\n noValidate\n >\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <div className={amountSummaryVariants()}>\n <span className={labelTextVariants()}>\n {t('payment.amountLabel')}\n </span>\n <span className=\"type-title-card\" data-testid=\"payment-amount\">\n {formatPaymentAmount(amount, currency, locale)}\n </span>\n </div>\n\n <label\n htmlFor={paymentFieldId}\n className={fieldLabelVariants()}\n data-testid=\"payment-field\"\n >\n <span className={labelTextVariants()}>\n {t('payment.fields.card')}\n </span>\n <PaymentElement\n id={paymentFieldId}\n options={{\n layout: { type: 'accordion', defaultCollapsed: false },\n }}\n onChange={(ev) => {\n // NOTE: never log `ev` — change events may include hints\n // about field contents. Keep only the boolean completeness.\n setElementComplete(ev.complete === true);\n if (ev.complete) {\n setErrorKey(null);\n setErrorMessage('');\n }\n }}\n />\n </label>\n\n {billingAddress ? (\n <label\n htmlFor={addressFieldId}\n className={fieldLabelVariants()}\n data-testid=\"payment-address\"\n >\n <span className={labelTextVariants()}>\n {t('payment.billingAddress')}\n </span>\n <AddressElement id={addressFieldId} options={{ mode: 'billing' }} />\n </label>\n ) : null}\n\n {errorKey ? (\n <Alert\n id={errorId}\n variant=\"error\"\n live=\"polite\"\n data-testid=\"payment-error\"\n >\n <Alert.Description>{errorMessage}</Alert.Description>\n </Alert>\n ) : null}\n\n <button\n type=\"submit\"\n aria-disabled={submitDisabled || undefined}\n aria-busy={processing || undefined}\n aria-describedby={errorKey ? errorId : undefined}\n className={submitButtonVariants()}\n data-testid=\"payment-submit\"\n >\n {processing ? (\n <>\n <Spinner size=\"sm\" label={t('payment.processing')} />\n <span>{t('payment.processing')}</span>\n </>\n ) : (\n <span>\n {t('payment.submit', {\n amount: formatPaymentAmount(amount, currency, locale),\n })}\n </span>\n )}\n </button>\n </div>\n </form>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* PaymentForm — outer wrapper */\n/* ------------------------------------------------------------------ */\n\n/**\n * Stripe ships a closed union of supported locales; anything outside it\n * must fall through to `'auto'` (Stripe picks the best match from the\n * browser). We also normalise the legacy `cn` code to `zh` per\n * `src/docs/06-i18n.mdx`.\n */\nconst STRIPE_LOCALES = new Set<StripeElementLocale>([\n 'auto',\n 'ar',\n 'bg',\n 'cs',\n 'da',\n 'de',\n 'el',\n 'en',\n 'en-AU',\n 'en-CA',\n 'en-NZ',\n 'en-GB',\n 'es',\n 'es-ES',\n 'es-419',\n 'et',\n 'fi',\n 'fil',\n 'fr',\n 'fr-CA',\n 'fr-FR',\n 'he',\n 'hu',\n 'hr',\n 'id',\n 'it',\n 'it-IT',\n 'ja',\n 'ko',\n 'lt',\n 'lv',\n 'ms',\n 'mt',\n 'nb',\n 'nl',\n 'no',\n 'pl',\n 'pt',\n 'pt-BR',\n 'ro',\n 'ru',\n 'sk',\n 'sl',\n 'sv',\n 'th',\n 'tr',\n 'vi',\n 'zh',\n 'zh-HK',\n 'zh-TW',\n]);\n\nfunction normaliseLocale(input: string): StripeElementLocale {\n if (!input) return 'auto';\n const candidate = input === 'cn' ? 'zh' : input;\n if ((STRIPE_LOCALES as Set<string>).has(candidate)) {\n return candidate as StripeElementLocale;\n }\n // Try stripping region (\"en-US\" → \"en\") before giving up.\n const base = candidate.split('-')[0];\n if ((STRIPE_LOCALES as Set<string>).has(base)) {\n return base as StripeElementLocale;\n }\n return 'auto';\n}\n\nexport const PaymentForm = forwardRef<HTMLDivElement, PaymentFormProps>(\n (\n {\n id,\n clientSecret,\n publishableKey,\n currency,\n amount,\n onSuccess,\n onError,\n billingAddress = false,\n locale,\n ariaLabel,\n returnUrl,\n stripePromise: injectedStripe,\n className,\n },\n ref,\n ) => {\n const { i18n } = useTranslation();\n const activeLocale = normaliseLocale(locale ?? i18n.language ?? 'en');\n\n // Stripe instance — pre-injected (tests/stories) or lazily loaded.\n const [stripeInstance, setStripeInstance] =\n useState<Promise<Stripe | null> | null>(injectedStripe ?? null);\n\n useEffect(() => {\n if (injectedStripe !== undefined) {\n setStripeInstance(injectedStripe);\n return;\n }\n if (!publishableKey) {\n setStripeInstance(null);\n return;\n }\n // `loadStripe` is cached by the SDK — safe to call per mount.\n setStripeInstance(loadStripe(publishableKey));\n }, [injectedStripe, publishableKey]);\n\n // Appearance bridge — snapshot + subscribe.\n const [appearance, setAppearance] = useState<Appearance>(() =>\n getStripeAppearance(),\n );\n useEffect(() => {\n setAppearance(getStripeAppearance());\n const unsubscribe = subscribeStripeAppearance(setAppearance);\n return unsubscribe;\n }, []);\n\n // Imperative handle — dispatch a custom event at the inner form so we\n // can trigger the same submit path as the button without leaking refs\n // through the Stripe `<Elements>` provider (which owns its own tree).\n const hostRef = useRef<HTMLDivElement>(null);\n\n const agentHandle = useMemo<PaymentFormHandle>(\n () => ({\n submit: async () => {\n const form = hostRef.current?.querySelector('form');\n if (form) {\n form.dispatchEvent(\n new CustomEvent('payment-form:submit', { bubbles: true }),\n );\n }\n },\n reset: () => {\n const form = hostRef.current?.querySelector('form');\n if (form instanceof HTMLFormElement) {\n form.reset();\n }\n },\n }),\n [],\n );\n useImperativeHandle(ref, () => hostRef.current as HTMLDivElement, []);\n useAgentRegistration(paymentFormAgent, agentHandle, id);\n\n const elementsOptions = useMemo(\n () => ({\n clientSecret,\n appearance,\n locale: activeLocale,\n }),\n [clientSecret, appearance, activeLocale],\n );\n\n return (\n <div\n ref={hostRef}\n aria-label={ariaLabel}\n className={[formVariants(), className].filter(Boolean).join(' ')}\n data-component=\"payment-form\"\n data-component-id={id}\n data-testid=\"payment-form-root\"\n >\n {stripeInstance && clientSecret ? (\n <Elements\n stripe={stripeInstance}\n options={elementsOptions}\n key={clientSecret}\n >\n <InnerPaymentForm\n amount={amount}\n currency={currency}\n locale={activeLocale}\n billingAddress={billingAddress}\n returnUrl={returnUrl}\n onSuccess={onSuccess}\n onError={onError}\n />\n </Elements>\n ) : (\n <PaymentFormSkeleton\n amount={amount}\n currency={currency}\n locale={activeLocale}\n billingAddress={billingAddress}\n />\n )}\n </div>\n );\n },\n);\n\nPaymentForm.displayName = 'PaymentForm';\n\n/* ------------------------------------------------------------------ */\n/* Skeleton — visual chrome when Stripe hasn't loaded yet */\n/* ------------------------------------------------------------------ */\n\ninterface PaymentFormSkeletonProps {\n amount: number;\n currency: string;\n locale: string;\n billingAddress: boolean;\n}\n\nfunction PaymentFormSkeleton(props: PaymentFormSkeletonProps): JSX.Element {\n const { amount, currency, locale, billingAddress } = props;\n const { t } = useTranslation();\n\n return (\n <div\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\"\n data-testid=\"payment-skeleton\"\n aria-busy=\"true\"\n >\n <div className={amountSummaryVariants()}>\n <span className={labelTextVariants()}>{t('payment.amountLabel')}</span>\n <span className=\"type-title-card\">\n {formatPaymentAmount(amount, currency, locale)}\n </span>\n </div>\n <div className={fieldLabelVariants()}>\n <span className={labelTextVariants()}>{t('payment.fields.card')}</span>\n <div\n className=\"ds:min-block-size-[var(--min-target-size)] ds:rounded-[var(--radius-sm)] ds:border ds:border-[color:var(--border)] ds:bg-[var(--muted)]\"\n aria-hidden=\"true\"\n />\n </div>\n {billingAddress ? (\n <div className={fieldLabelVariants()} data-testid=\"payment-address\">\n <span className={labelTextVariants()}>\n {t('payment.billingAddress')}\n </span>\n <div\n className=\"ds:min-block-size-[calc(var(--min-target-size)*2)] ds:rounded-[var(--radius-sm)] ds:border ds:border-[color:var(--border)] ds:bg-[var(--muted)]\"\n aria-hidden=\"true\"\n />\n </div>\n ) : null}\n <button\n type=\"button\"\n aria-disabled=\"true\"\n className={submitButtonVariants()}\n disabled\n >\n <Spinner size=\"sm\" label={t('payment.processing')} />\n <span>{t('payment.processing')}</span>\n </button>\n </div>\n );\n}\n\nexport {\n formVariants as paymentFormVariants,\n submitButtonVariants as paymentSubmitButtonVariants,\n};\n"],"names":["isBrowser","getStripeAppearance","root","target","styles","read","token","subscribeStripeAppearance","onChange","emit","observer","schemeMql","motionMql","paymentFormAgent","handle","ZERO_DECIMAL_CURRENCIES","formatPaymentAmount","amount","currency","locale","iso","major","validateReturnUrl","returnUrl","raw","resolved","stripCardLikeDigits","message","stripeErrorCodeToI18nKey","code","formVariants","cva","fieldLabelVariants","labelTextVariants","amountSummaryVariants","submitButtonVariants","InnerPaymentForm","props","billingAddress","onSuccess","onError","t","useTranslation","stripe","useStripe","elements","useElements","rawId","useId","idSafe","useMemo","paymentFieldId","addressFieldId","errorId","processing","setProcessing","useState","elementComplete","setElementComplete","errorKey","setErrorKey","errorMessage","setErrorMessage","onSuccessRef","useRef","onErrorRef","useEffect","handleSubmit","useCallback","event","safeReturnUrl","_a","result","key","safe","_b","_c","err","_d","host","submitter","submitDisabled","jsx","jsxs","PaymentElement","ev","AddressElement","Alert","Fragment","Spinner","STRIPE_LOCALES","normaliseLocale","input","candidate","base","PaymentForm","forwardRef","id","clientSecret","publishableKey","ariaLabel","injectedStripe","className","ref","i18n","activeLocale","stripeInstance","setStripeInstance","loadStripe","appearance","setAppearance","hostRef","agentHandle","form","useImperativeHandle","useAgentRegistration","elementsOptions","Elements","PaymentFormSkeleton"],"mappings":"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"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { jsxs as z, jsx as s } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as N } from "react";
|
|
3
|
+
import { c as l } from "./index-D2ZczOXr.js";
|
|
4
|
+
import { useTranslation as T } from "react-i18next";
|
|
5
|
+
import { C as M } from "./check-DPdL_Sm7.js";
|
|
6
|
+
import { c as t } from "./createLucideIcon-CrFbzy84.js";
|
|
7
|
+
import { F as _ } from "./file-text-DSNuv2B8.js";
|
|
8
|
+
/**
|
|
9
|
+
* @license lucide-react v1.8.0 - ISC
|
|
10
|
+
*
|
|
11
|
+
* This source code is licensed under the ISC license.
|
|
12
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
13
|
+
*/
|
|
14
|
+
const I = [
|
|
15
|
+
["path", { d: "M17 7 7 17", key: "15tmo1" }],
|
|
16
|
+
["path", { d: "M17 17H7V7", key: "1org7z" }]
|
|
17
|
+
], C = t("arrow-down-left", I);
|
|
18
|
+
/**
|
|
19
|
+
* @license lucide-react v1.8.0 - ISC
|
|
20
|
+
*
|
|
21
|
+
* This source code is licensed under the ISC license.
|
|
22
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
23
|
+
*/
|
|
24
|
+
const A = [
|
|
25
|
+
["path", { d: "M7 7h10v10", key: "1tivn9" }],
|
|
26
|
+
["path", { d: "M7 17 17 7", key: "1vkiza" }]
|
|
27
|
+
], E = t("arrow-up-right", A);
|
|
28
|
+
/**
|
|
29
|
+
* @license lucide-react v1.8.0 - ISC
|
|
30
|
+
*
|
|
31
|
+
* This source code is licensed under the ISC license.
|
|
32
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
33
|
+
*/
|
|
34
|
+
const L = [
|
|
35
|
+
["path", { d: "M16 14v2.2l1.6 1", key: "fo4ql5" }],
|
|
36
|
+
["path", { d: "M16 2v4", key: "4m81vk" }],
|
|
37
|
+
["path", { d: "M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5", key: "1osxxc" }],
|
|
38
|
+
["path", { d: "M3 10h5", key: "r794hk" }],
|
|
39
|
+
["path", { d: "M8 2v4", key: "1cmpym" }],
|
|
40
|
+
["circle", { cx: "16", cy: "16", r: "6", key: "qoo3c4" }]
|
|
41
|
+
], R = t("calendar-clock", L), S = {
|
|
42
|
+
debt: "debt",
|
|
43
|
+
credit: "credit",
|
|
44
|
+
"to-invoice": "toInvoice",
|
|
45
|
+
"to-deliver": "toDeliver",
|
|
46
|
+
settled: "settled"
|
|
47
|
+
}, V = {
|
|
48
|
+
debt: C,
|
|
49
|
+
credit: E,
|
|
50
|
+
"to-invoice": _,
|
|
51
|
+
"to-deliver": R,
|
|
52
|
+
settled: M
|
|
53
|
+
}, F = {
|
|
54
|
+
debt: "−",
|
|
55
|
+
credit: "+",
|
|
56
|
+
"to-invoice": "",
|
|
57
|
+
"to-deliver": "",
|
|
58
|
+
settled: ""
|
|
59
|
+
}, D = {
|
|
60
|
+
debt: -1,
|
|
61
|
+
credit: 1,
|
|
62
|
+
"to-invoice": 1,
|
|
63
|
+
"to-deliver": 1,
|
|
64
|
+
settled: 1
|
|
65
|
+
}, U = "EUR", j = l(
|
|
66
|
+
[
|
|
67
|
+
"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]",
|
|
68
|
+
"ds:rounded-[var(--radius-full)] ds:border",
|
|
69
|
+
"ds:whitespace-nowrap ds:align-middle",
|
|
70
|
+
"ds:focus-visible:outline-none",
|
|
71
|
+
"ds:focus-visible:ring-[length:var(--focus-ring-width)]",
|
|
72
|
+
"ds:focus-visible:ring-[color:var(--ring)]",
|
|
73
|
+
"ds:focus-visible:ring-offset-[length:var(--focus-ring-offset)]"
|
|
74
|
+
].join(" "),
|
|
75
|
+
{
|
|
76
|
+
variants: {
|
|
77
|
+
state: {
|
|
78
|
+
// Text uses the deeper `*-foreground` token (matching Badge / Tag) so
|
|
79
|
+
// small chip text clears WCAG AA (4.5:1) against the 10% tinted
|
|
80
|
+
// background. The surface and border use the lighter alias.
|
|
81
|
+
debt: "ds:bg-destructive/10 ds:text-[color:var(--error-foreground)] ds:border-destructive/20",
|
|
82
|
+
credit: "ds:bg-success/10 ds:text-[color:var(--success-foreground)] ds:border-success/20",
|
|
83
|
+
// The orange "to-invoice" tint has no kit-wide semantic alias — see
|
|
84
|
+
// src/tokens/index.css §Transaction-chip-scoped tokens. The component
|
|
85
|
+
// owns the alias because the customer-anchored "Da fatturare" orange
|
|
86
|
+
// is distinct from `--warning` (yellow) and from `--destructive`.
|
|
87
|
+
"to-invoice": "ds:bg-transaction-chip-to-invoice/10 ds:text-[color:var(--transaction-chip-to-invoice-foreground)] ds:border-transaction-chip-to-invoice/20",
|
|
88
|
+
"to-deliver": "ds:bg-info/10 ds:text-[color:var(--info-foreground)] ds:border-info/20",
|
|
89
|
+
settled: "ds:bg-muted/30 ds:text-muted-foreground ds:border-muted/40"
|
|
90
|
+
},
|
|
91
|
+
size: {
|
|
92
|
+
// Heights tuned for table-cell density (sm), default app surfaces (md),
|
|
93
|
+
// and header / summary cards (lg). `--type-eyebrow-size` flows into the
|
|
94
|
+
// optional label span, keeping its typography in step with the chip.
|
|
95
|
+
sm: "ds:h-5 ds:ps-[var(--spacing-xs)] ds:pe-[var(--spacing-sm)] ds:text-[length:var(--font-size-2xs)] ds:[--type-eyebrow-size:var(--font-size-2xs)]",
|
|
96
|
+
md: "ds:h-6 ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:text-[length:var(--font-size-xs)] ds:[--type-eyebrow-size:var(--font-size-2xs)]",
|
|
97
|
+
lg: "ds:h-7 ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-md)] ds:text-[length:var(--font-size-sm)] ds:[--type-eyebrow-size:var(--font-size-xs)]"
|
|
98
|
+
},
|
|
99
|
+
bold: {
|
|
100
|
+
// `settled` is the terminal resting state — see compound variant below.
|
|
101
|
+
true: "ds:font-semibold",
|
|
102
|
+
false: "ds:font-medium"
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
defaultVariants: {
|
|
106
|
+
state: "debt",
|
|
107
|
+
size: "md",
|
|
108
|
+
bold: !0
|
|
109
|
+
},
|
|
110
|
+
compoundVariants: [
|
|
111
|
+
// `settled` always renders at the lighter weight, regardless of the
|
|
112
|
+
// resolved default. Mirrors PR #523's follow-up where the resting branch
|
|
113
|
+
// dropped from bold to medium to recede visually.
|
|
114
|
+
{ state: "settled", class: "ds:font-medium" }
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
), $ = l(
|
|
118
|
+
"ds:shrink-0 ds:[&>svg]:block ds:rtl:[&>svg]:-scale-x-100",
|
|
119
|
+
{
|
|
120
|
+
variants: {
|
|
121
|
+
size: {
|
|
122
|
+
sm: "ds:[&>svg]:size-3",
|
|
123
|
+
md: "ds:[&>svg]:size-3.5",
|
|
124
|
+
lg: "ds:[&>svg]:size-4"
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
defaultVariants: { size: "md" }
|
|
128
|
+
}
|
|
129
|
+
), q = N(
|
|
130
|
+
({
|
|
131
|
+
state: e,
|
|
132
|
+
amount: v,
|
|
133
|
+
currency: o = U,
|
|
134
|
+
locale: m,
|
|
135
|
+
size: r = "md",
|
|
136
|
+
showLabel: p = !1,
|
|
137
|
+
className: f,
|
|
138
|
+
"aria-label": u,
|
|
139
|
+
...g
|
|
140
|
+
}, h) => {
|
|
141
|
+
const { t: a, i18n: b } = T(), i = m ?? b.language ?? "en", y = V[e], n = F[e], d = Math.abs(v), x = new Intl.NumberFormat(i, {
|
|
142
|
+
style: "currency",
|
|
143
|
+
currency: o,
|
|
144
|
+
signDisplay: "never"
|
|
145
|
+
}).format(d), c = a(`ui.financial.state.${S[e]}`), k = new Intl.NumberFormat(i, {
|
|
146
|
+
style: "currency",
|
|
147
|
+
currency: o,
|
|
148
|
+
signDisplay: e === "debt" ? "always" : "auto"
|
|
149
|
+
}).format(d * D[e]), w = u ?? a("ui.financial.aria.label", {
|
|
150
|
+
state: c,
|
|
151
|
+
amount: k
|
|
152
|
+
});
|
|
153
|
+
return /* @__PURE__ */ z(
|
|
154
|
+
"span",
|
|
155
|
+
{
|
|
156
|
+
ref: h,
|
|
157
|
+
role: "img",
|
|
158
|
+
"aria-label": w,
|
|
159
|
+
"data-component": "transaction-chip",
|
|
160
|
+
"data-state": e,
|
|
161
|
+
className: j({
|
|
162
|
+
state: e,
|
|
163
|
+
size: r,
|
|
164
|
+
bold: e !== "settled",
|
|
165
|
+
className: f
|
|
166
|
+
}),
|
|
167
|
+
...g,
|
|
168
|
+
children: [
|
|
169
|
+
/* @__PURE__ */ s("span", { "aria-hidden": "true", className: $({ size: r }), children: /* @__PURE__ */ s(y, {}) }),
|
|
170
|
+
p && /* @__PURE__ */ s("span", { "aria-hidden": "true", className: "type-eyebrow", children: c }),
|
|
171
|
+
n && /* @__PURE__ */ s(
|
|
172
|
+
"span",
|
|
173
|
+
{
|
|
174
|
+
"aria-hidden": "true",
|
|
175
|
+
className: "ds:[font-variant-numeric:var(--font-feature-tabular)]",
|
|
176
|
+
children: n
|
|
177
|
+
}
|
|
178
|
+
),
|
|
179
|
+
/* @__PURE__ */ s(
|
|
180
|
+
"span",
|
|
181
|
+
{
|
|
182
|
+
"aria-hidden": "true",
|
|
183
|
+
className: "ds:[font-variant-numeric:var(--font-feature-tabular)]",
|
|
184
|
+
children: x
|
|
185
|
+
}
|
|
186
|
+
)
|
|
187
|
+
]
|
|
188
|
+
}
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
);
|
|
192
|
+
q.displayName = "TransactionChip";
|
|
193
|
+
export {
|
|
194
|
+
q as T
|
|
195
|
+
};
|
|
196
|
+
//# sourceMappingURL=transaction-chip-DE6DITun.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction-chip-DE6DITun.js","sources":["../../node_modules/lucide-react/dist/esm/icons/arrow-down-left.js","../../node_modules/lucide-react/dist/esm/icons/arrow-up-right.js","../../node_modules/lucide-react/dist/esm/icons/calendar-clock.js","../../src/components/transaction-chip/transaction-chip.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M17 7 7 17\", key: \"15tmo1\" }],\n [\"path\", { d: \"M17 17H7V7\", key: \"1org7z\" }]\n];\nconst ArrowDownLeft = createLucideIcon(\"arrow-down-left\", __iconNode);\n\nexport { __iconNode, ArrowDownLeft as default };\n//# sourceMappingURL=arrow-down-left.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M7 7h10v10\", key: \"1tivn9\" }],\n [\"path\", { d: \"M7 17 17 7\", key: \"1vkiza\" }]\n];\nconst ArrowUpRight = createLucideIcon(\"arrow-up-right\", __iconNode);\n\nexport { __iconNode, ArrowUpRight as default };\n//# sourceMappingURL=arrow-up-right.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M16 14v2.2l1.6 1\", key: \"fo4ql5\" }],\n [\"path\", { d: \"M16 2v4\", key: \"4m81vk\" }],\n [\"path\", { d: \"M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5\", key: \"1osxxc\" }],\n [\"path\", { d: \"M3 10h5\", key: \"r794hk\" }],\n [\"path\", { d: \"M8 2v4\", key: \"1cmpym\" }],\n [\"circle\", { cx: \"16\", cy: \"16\", r: \"6\", key: \"qoo3c4\" }]\n];\nconst CalendarClock = createLucideIcon(\"calendar-clock\", __iconNode);\n\nexport { __iconNode, CalendarClock as default };\n//# sourceMappingURL=calendar-clock.js.map\n","import { forwardRef, type HTMLAttributes } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport {\n ArrowDownLeft,\n ArrowUpRight,\n CalendarClock,\n Check,\n FileText,\n type LucideIcon,\n} from 'lucide-react';\n\n/* ------------------------------------------------------------------ */\n/* State vocabulary */\n/* ------------------------------------------------------------------ */\n\nexport type TransactionState =\n | 'debt'\n | 'credit'\n | 'to-invoice'\n | 'to-deliver'\n | 'settled';\n\n// State → translation-key segment. Hyphenated state names are flattened to\n// camelCase so the i18next bundle stays consistent with the rest of `ui.*`.\nconst STATE_KEY: Record<TransactionState, string> = {\n debt: 'debt',\n credit: 'credit',\n 'to-invoice': 'toInvoice',\n 'to-deliver': 'toDeliver',\n settled: 'settled',\n};\n\nconst STATE_ICON: Record<TransactionState, LucideIcon> = {\n debt: ArrowDownLeft,\n credit: ArrowUpRight,\n 'to-invoice': FileText,\n 'to-deliver': CalendarClock,\n settled: Check,\n};\n\n// U+2212 MINUS SIGN — matches PR alfadocs/platform#523's typographic minus.\n// Hyphen-minus would render visually narrower next to the currency glyph.\nconst STATE_SIGN: Record<TransactionState, '' | '+' | '−'> = {\n debt: '−',\n credit: '+',\n 'to-invoice': '',\n 'to-deliver': '',\n settled: '',\n};\n\n// Multiplier used when composing the screen-reader announcement so SR users\n// hear the signed amount Intl produces (\"minus one thousand…\") rather than\n// the magnitude plus a separate sign glyph.\nconst SIGN_MULTIPLIER: Record<TransactionState, -1 | 1> = {\n debt: -1,\n credit: 1,\n 'to-invoice': 1,\n 'to-deliver': 1,\n settled: 1,\n};\n\nconst DEFAULT_CURRENCY = 'EUR';\n\n/* ------------------------------------------------------------------ */\n/* CVA — chip root */\n/* ------------------------------------------------------------------ */\n\nconst chipVariants = cva(\n [\n 'ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]',\n 'ds:rounded-[var(--radius-full)] ds:border',\n 'ds:whitespace-nowrap ds:align-middle',\n 'ds:focus-visible:outline-none',\n 'ds:focus-visible:ring-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:ring-[color:var(--ring)]',\n 'ds:focus-visible:ring-offset-[length:var(--focus-ring-offset)]',\n ].join(' '),\n {\n variants: {\n state: {\n // Text uses the deeper `*-foreground` token (matching Badge / Tag) so\n // small chip text clears WCAG AA (4.5:1) against the 10% tinted\n // background. The surface and border use the lighter alias.\n debt:\n 'ds:bg-destructive/10 ds:text-[color:var(--error-foreground)] ds:border-destructive/20',\n credit:\n 'ds:bg-success/10 ds:text-[color:var(--success-foreground)] ds:border-success/20',\n // The orange \"to-invoice\" tint has no kit-wide semantic alias — see\n // src/tokens/index.css §Transaction-chip-scoped tokens. The component\n // owns the alias because the customer-anchored \"Da fatturare\" orange\n // is distinct from `--warning` (yellow) and from `--destructive`.\n 'to-invoice':\n 'ds:bg-transaction-chip-to-invoice/10 ds:text-[color:var(--transaction-chip-to-invoice-foreground)] ds:border-transaction-chip-to-invoice/20',\n 'to-deliver':\n 'ds:bg-info/10 ds:text-[color:var(--info-foreground)] ds:border-info/20',\n settled:\n 'ds:bg-muted/30 ds:text-muted-foreground ds:border-muted/40',\n },\n size: {\n // Heights tuned for table-cell density (sm), default app surfaces (md),\n // and header / summary cards (lg). `--type-eyebrow-size` flows into the\n // optional label span, keeping its typography in step with the chip.\n sm: 'ds:h-5 ds:ps-[var(--spacing-xs)] ds:pe-[var(--spacing-sm)] ds:text-[length:var(--font-size-2xs)] ds:[--type-eyebrow-size:var(--font-size-2xs)]',\n md: 'ds:h-6 ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:text-[length:var(--font-size-xs)] ds:[--type-eyebrow-size:var(--font-size-2xs)]',\n lg: 'ds:h-7 ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-md)] ds:text-[length:var(--font-size-sm)] ds:[--type-eyebrow-size:var(--font-size-xs)]',\n },\n bold: {\n // `settled` is the terminal resting state — see compound variant below.\n true: 'ds:font-semibold',\n false: 'ds:font-medium',\n },\n },\n defaultVariants: {\n state: 'debt',\n size: 'md',\n bold: true,\n },\n compoundVariants: [\n // `settled` always renders at the lighter weight, regardless of the\n // resolved default. Mirrors PR #523's follow-up where the resting branch\n // dropped from bold to medium to recede visually.\n { state: 'settled', class: 'ds:font-medium' },\n ],\n },\n);\n\n/* ------------------------------------------------------------------ */\n/* CVA — icon wrapper */\n/* ------------------------------------------------------------------ */\n\n// `ArrowDownLeft` (debt) and `ArrowUpRight` (credit) are direction-encoded\n// glyphs — their physical orientation carries the semantic (\"money coming\n// in\" / \"money going out\"). PRS §05 RTL: directional icons flip in RTL.\n// The non-directional glyphs (FileText, CalendarClock, Check) are unaffected.\nconst iconWrapperVariants = cva(\n 'ds:shrink-0 ds:[&>svg]:block ds:rtl:[&>svg]:-scale-x-100',\n {\n variants: {\n size: {\n sm: 'ds:[&>svg]:size-3',\n md: 'ds:[&>svg]:size-3.5',\n lg: 'ds:[&>svg]:size-4',\n },\n },\n defaultVariants: { size: 'md' },\n },\n);\n\n/* ------------------------------------------------------------------ */\n/* Props */\n/* ------------------------------------------------------------------ */\n\nexport interface TransactionChipProps\n extends Omit<HTMLAttributes<HTMLSpanElement>, 'children'>,\n Pick<VariantProps<typeof chipVariants>, 'size'> {\n /** Financial state — drives colour, icon, sign, and label. */\n state: TransactionState;\n /**\n * Magnitude of the amount as a non-negative number. The sign is rendered\n * separately based on `state` — callers must never pass a negative value.\n */\n amount: number;\n /**\n * ISO 4217 currency code. Defaults to `EUR` for the Italian-anchored\n * release. Required at the type level so consumers can't silently render\n * a different currency than they intended.\n */\n currency?: string;\n /** BCP 47 locale override. Defaults to the active i18next language. */\n locale?: string;\n /** Render the state label (e.g. \"Da incassare\") before the amount. */\n showLabel?: boolean;\n}\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport const TransactionChip = forwardRef<HTMLSpanElement, TransactionChipProps>(\n (\n {\n state,\n amount,\n currency = DEFAULT_CURRENCY,\n locale,\n size = 'md',\n showLabel = false,\n className,\n 'aria-label': ariaLabelProp,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n const activeLocale = locale ?? i18n.language ?? 'en';\n\n const StateIcon = STATE_ICON[state];\n const sign = STATE_SIGN[state];\n const magnitude = Math.abs(amount);\n\n // The visible amount is rendered without a sign; the leading sign glyph\n // (or its absence) is owned by the state, not the formatter.\n const formattedAmount = new Intl.NumberFormat(activeLocale, {\n style: 'currency',\n currency,\n signDisplay: 'never',\n }).format(magnitude);\n\n // The accessible name uses Intl's own signed output so screen readers\n // announce the locale-correct \"minus\" / \"negative\" phrasing instead of\n // skipping the U+2212 glyph or speaking it as \"hyphen\".\n const stateLabel = t(`ui.financial.state.${STATE_KEY[state]}`);\n const signedAmountForSR = new Intl.NumberFormat(activeLocale, {\n style: 'currency',\n currency,\n signDisplay: state === 'debt' ? 'always' : 'auto',\n }).format(magnitude * SIGN_MULTIPLIER[state]);\n const ariaLabel =\n ariaLabelProp ??\n t('ui.financial.aria.label', {\n state: stateLabel,\n amount: signedAmountForSR,\n });\n\n return (\n <span\n ref={ref}\n role=\"img\"\n aria-label={ariaLabel}\n data-component=\"transaction-chip\"\n data-state={state}\n className={chipVariants({\n state,\n size,\n bold: state !== 'settled',\n className,\n })}\n {...rest}\n >\n <span aria-hidden=\"true\" className={iconWrapperVariants({ size })}>\n <StateIcon />\n </span>\n {showLabel && (\n <span aria-hidden=\"true\" className=\"type-eyebrow\">\n {stateLabel}\n </span>\n )}\n {sign && (\n <span\n aria-hidden=\"true\"\n className=\"ds:[font-variant-numeric:var(--font-feature-tabular)]\"\n >\n {sign}\n </span>\n )}\n <span\n aria-hidden=\"true\"\n className=\"ds:[font-variant-numeric:var(--font-feature-tabular)]\"\n >\n {formattedAmount}\n </span>\n </span>\n );\n },\n);\n\nTransactionChip.displayName = 'TransactionChip';\n"],"names":["__iconNode","ArrowDownLeft","createLucideIcon","ArrowUpRight","CalendarClock","STATE_KEY","STATE_ICON","FileText","Check","STATE_SIGN","SIGN_MULTIPLIER","DEFAULT_CURRENCY","chipVariants","cva","iconWrapperVariants","TransactionChip","forwardRef","state","amount","currency","locale","size","showLabel","className","ariaLabelProp","rest","ref","t","i18n","useTranslation","activeLocale","StateIcon","sign","magnitude","formattedAmount","stateLabel","signedAmountForSR","ariaLabel","jsxs","jsx"],"mappings":"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","x_google_ignoreList":[0,1,2]}
|
package/dist/agent-catalog.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"packageVersion": "0.2.
|
|
3
|
+
"packageVersion": "0.2.1",
|
|
4
4
|
"components": [
|
|
5
5
|
{
|
|
6
6
|
"kind": "component",
|
|
@@ -3773,6 +3773,20 @@
|
|
|
3773
3773
|
}
|
|
3774
3774
|
}
|
|
3775
3775
|
},
|
|
3776
|
+
{
|
|
3777
|
+
"kind": "component",
|
|
3778
|
+
"id": "transaction-chip",
|
|
3779
|
+
"capabilities": [],
|
|
3780
|
+
"state": [],
|
|
3781
|
+
"actions": [],
|
|
3782
|
+
"domHooks": {
|
|
3783
|
+
"root": {
|
|
3784
|
+
"attr": "data-component",
|
|
3785
|
+
"value": "transaction-chip",
|
|
3786
|
+
"description": "Marks the element as a kit TransactionChip."
|
|
3787
|
+
}
|
|
3788
|
+
}
|
|
3789
|
+
},
|
|
3776
3790
|
{
|
|
3777
3791
|
"kind": "component",
|
|
3778
3792
|
"id": "transcript-panel",
|