@adia-ai/web-modules 0.8.36 → 0.8.37
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/CHANGELOG.md +17 -0
- package/README.md +3 -3
- package/agent-admin/admin-roster/admin-roster.js +1 -1
- package/agent-admin/admin-settings/admin-settings.js +1 -1
- package/agent-admin/agent-admin/agent-admin.js +1 -1
- package/billing/billing-overview/billing-overview.a2ui.json +281 -0
- package/billing/billing-overview/billing-overview.class.js +838 -0
- package/billing/billing-overview/billing-overview.css +223 -0
- package/billing/billing-overview/billing-overview.js +16 -0
- package/billing/billing-overview/billing-overview.yaml +441 -0
- package/billing/index.js +21 -0
- package/billing/invoice-detail/invoice-detail.a2ui.json +276 -0
- package/billing/invoice-detail/invoice-detail.class.js +711 -0
- package/billing/invoice-detail/invoice-detail.css +305 -0
- package/billing/invoice-detail/invoice-detail.js +16 -0
- package/billing/invoice-detail/invoice-detail.yaml +411 -0
- package/billing/invoice-history/invoice-history.a2ui.json +315 -0
- package/billing/invoice-history/invoice-history.class.js +672 -0
- package/billing/invoice-history/invoice-history.css +130 -0
- package/billing/invoice-history/invoice-history.js +16 -0
- package/billing/invoice-history/invoice-history.yaml +398 -0
- package/billing/payment-method-form/payment-method-form.a2ui.json +310 -0
- package/billing/payment-method-form/payment-method-form.class.js +886 -0
- package/billing/payment-method-form/payment-method-form.css +149 -0
- package/billing/payment-method-form/payment-method-form.js +16 -0
- package/billing/payment-method-form/payment-method-form.yaml +430 -0
- package/billing/payment-method-list/payment-method-list.a2ui.json +283 -0
- package/billing/payment-method-list/payment-method-list.class.js +705 -0
- package/billing/payment-method-list/payment-method-list.css +128 -0
- package/billing/payment-method-list/payment-method-list.js +16 -0
- package/billing/payment-method-list/payment-method-list.yaml +355 -0
- package/billing/plan-picker/plan-picker.a2ui.json +349 -0
- package/billing/plan-picker/plan-picker.class.js +635 -0
- package/billing/plan-picker/plan-picker.css +227 -0
- package/billing/plan-picker/plan-picker.js +16 -0
- package/billing/plan-picker/plan-picker.yaml +453 -0
- package/chat/README.md +1 -1
- package/chat/chat-composer/chat-composer.js +2 -2
- package/chat/chat-empty/chat-empty.js +2 -2
- package/chat/chat-shell/chat-shell.js +4 -4
- package/chat/chat-sidebar/chat-sidebar.js +2 -2
- package/chat/chat-surfaces/chat-surfaces.js +2 -2
- package/chat/chat-thread/chat-thread.js +2 -2
- package/dashboard/dashboard-layout/dashboard-layout.a2ui.json +254 -0
- package/dashboard/dashboard-layout/dashboard-layout.css +190 -0
- package/dashboard/dashboard-layout/dashboard-layout.js +289 -0
- package/dashboard/dashboard-layout/dashboard-layout.yaml +374 -0
- package/dashboard/date-range-selector/date-range-selector.a2ui.json +236 -0
- package/dashboard/date-range-selector/date-range-selector.css +84 -0
- package/dashboard/date-range-selector/date-range-selector.js +686 -0
- package/dashboard/date-range-selector/date-range-selector.yaml +358 -0
- package/dashboard/index.js +14 -0
- package/dist/everything.min.js +1 -1
- package/editor/editor-canvas/editor-canvas.js +2 -2
- package/editor/editor-shell/editor-shell.js +2 -2
- package/editor/editor-sidebar/editor-sidebar.js +2 -2
- package/editor/editor-toolbar/editor-toolbar.js +2 -2
- package/feedback/confirm-dialog/confirm-dialog.a2ui.json +206 -0
- package/feedback/confirm-dialog/confirm-dialog.css +157 -0
- package/feedback/confirm-dialog/confirm-dialog.js +383 -0
- package/feedback/confirm-dialog/confirm-dialog.yaml +297 -0
- package/feedback/index.js +10 -0
- package/form/form-popover/form-popover.js +1 -1
- package/generative/index.d.ts +1 -1
- package/generative/index.js +2 -2
- package/onboarding/index.js +1 -0
- package/onboarding/onboarding-checklist/onboarding-checklist.a2ui.json +263 -0
- package/onboarding/onboarding-checklist/onboarding-checklist.css +157 -0
- package/onboarding/onboarding-checklist/onboarding-checklist.js +428 -0
- package/onboarding/onboarding-checklist/onboarding-checklist.yaml +236 -0
- package/package.json +99 -6
- package/runtime/a2ui-root/a2ui-root.js +3 -3
- package/runtime/gen-root/gen-root.js +5 -5
- package/settings/index.js +12 -0
- package/settings/integrations-page/integrations-page.a2ui.json +274 -0
- package/settings/integrations-page/integrations-page.css +177 -0
- package/settings/integrations-page/integrations-page.d.ts +77 -0
- package/settings/integrations-page/integrations-page.js +413 -0
- package/settings/integrations-page/integrations-page.yaml +317 -0
- package/settings/notification-preferences/notification-preferences.a2ui.json +245 -0
- package/settings/notification-preferences/notification-preferences.css +204 -0
- package/settings/notification-preferences/notification-preferences.js +622 -0
- package/settings/notification-preferences/notification-preferences.yaml +358 -0
- package/shell/admin-command/admin-command.js +2 -2
- package/shell/admin-shell/admin-shell.js +2 -2
- package/shell/admin-sidebar/admin-sidebar.js +2 -2
- package/shell/embed-shell/embed-shell.js +3 -3
- package/simple/simple-shell/simple-shell.js +1 -1
- package/theme/theme-panel/theme-panel.js +2 -2
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/* ═══════════════════════════════════════════════════════════════
|
|
2
|
+
<payment-method-form-ui> — Form-participating payment-method composite.
|
|
3
|
+
|
|
4
|
+
Stamps a grid of <field-ui> + <input-ui> + <select-ui> sub-controls
|
|
5
|
+
for collecting card number, expiry, CVC, name, billing address, and
|
|
6
|
+
country. Form chrome + structured validation; tokenization is the
|
|
7
|
+
consumer's job (Stripe Elements / Braintree / Adyen).
|
|
8
|
+
|
|
9
|
+
SPEC: docs/specs/implementation-ready/SPEC-009-payment-method-form.md
|
|
10
|
+
Two-block @scope pattern per docs/specs/component-token-contract.md.
|
|
11
|
+
Zero raw color values (repo hard rule); rem only.
|
|
12
|
+
═══════════════════════════════════════════════════════════════ */
|
|
13
|
+
|
|
14
|
+
/* ── Block 1: TOKEN DECLARATIONS ───────────────────────────────── */
|
|
15
|
+
|
|
16
|
+
payment-method-form-ui {
|
|
17
|
+
--payment-method-form-gap: var(--a-space-3);
|
|
18
|
+
--payment-method-form-grid-template: "name name" "card card" "expiry cvc" "country postal";
|
|
19
|
+
--payment-method-form-grid-template-billing:
|
|
20
|
+
"name name" "card card" "expiry cvc" "address1 address1" "address2 address2" "country postal";
|
|
21
|
+
|
|
22
|
+
--payment-method-form-brand-icon-size: 1.25em;
|
|
23
|
+
|
|
24
|
+
--payment-method-form-alert-mb: var(--a-space-3);
|
|
25
|
+
|
|
26
|
+
--payment-method-form-summary-bg: var(--a-bg-muted);
|
|
27
|
+
--payment-method-form-summary-border: 1px solid var(--md-sys-color-neutral-outline);
|
|
28
|
+
--payment-method-form-summary-radius: var(--a-radius-md);
|
|
29
|
+
--payment-method-form-summary-px: var(--a-space-4);
|
|
30
|
+
--payment-method-form-summary-py: var(--a-space-3);
|
|
31
|
+
|
|
32
|
+
--payment-method-form-legal-fg: var(--a-fg-muted);
|
|
33
|
+
--payment-method-form-legal-size: var(--a-text-xs, 0.75rem);
|
|
34
|
+
|
|
35
|
+
--payment-method-form-disabled-opacity: var(--a-opacity-disabled, 0.5);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* ── Block 2: SCOPED LAYOUT ────────────────────────────────────── */
|
|
39
|
+
|
|
40
|
+
@scope (payment-method-form-ui) {
|
|
41
|
+
|
|
42
|
+
:scope {
|
|
43
|
+
display: flex;
|
|
44
|
+
flex-direction: column;
|
|
45
|
+
gap: var(--payment-method-form-gap);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* ── Host-level error alert ── */
|
|
49
|
+
:scope > [data-alert] {
|
|
50
|
+
margin-block-end: var(--payment-method-form-alert-mb);
|
|
51
|
+
}
|
|
52
|
+
:scope > [data-alert][hidden] {
|
|
53
|
+
display: none;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* ── Saved-card summary row ── */
|
|
57
|
+
:scope > [data-summary] {
|
|
58
|
+
display: flex;
|
|
59
|
+
align-items: center;
|
|
60
|
+
gap: var(--a-space-3);
|
|
61
|
+
background: var(--payment-method-form-summary-bg);
|
|
62
|
+
border: var(--payment-method-form-summary-border);
|
|
63
|
+
border-radius: var(--payment-method-form-summary-radius);
|
|
64
|
+
padding-inline: var(--payment-method-form-summary-px);
|
|
65
|
+
padding-block: var(--payment-method-form-summary-py);
|
|
66
|
+
}
|
|
67
|
+
:scope > [data-summary][hidden] {
|
|
68
|
+
display: none;
|
|
69
|
+
}
|
|
70
|
+
:scope > [data-summary] > [data-summary-icon] {
|
|
71
|
+
--a-icon-size: 1.25rem;
|
|
72
|
+
color: var(--a-fg-muted);
|
|
73
|
+
flex-shrink: 0;
|
|
74
|
+
}
|
|
75
|
+
:scope > [data-summary] > [data-summary-text] {
|
|
76
|
+
flex: 1;
|
|
77
|
+
color: var(--md-sys-color-neutral-on-surface);
|
|
78
|
+
font-size: var(--a-text-sm, 0.875rem);
|
|
79
|
+
}
|
|
80
|
+
:scope > [data-summary] > [data-summary-edit] {
|
|
81
|
+
flex-shrink: 0;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* ── Field grid ── */
|
|
85
|
+
:scope > [data-grid] {
|
|
86
|
+
display: grid;
|
|
87
|
+
grid-template-columns: 1fr 1fr;
|
|
88
|
+
grid-template-areas: var(--payment-method-form-grid-template);
|
|
89
|
+
gap: var(--payment-method-form-gap);
|
|
90
|
+
}
|
|
91
|
+
:scope > [data-grid][hidden] {
|
|
92
|
+
display: none;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
:scope[require-billing-address] > [data-grid] {
|
|
96
|
+
grid-template-areas: var(--payment-method-form-grid-template-billing);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* Hidden rows (address lines when require-billing-address is unset)
|
|
100
|
+
collapse out of the grid without affecting sibling cell flow. */
|
|
101
|
+
:scope > [data-grid] > field-ui[hidden] {
|
|
102
|
+
display: none;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* ── Brand badge in card-number trailing slot ── */
|
|
106
|
+
:scope [data-brand-badge] {
|
|
107
|
+
display: inline-flex;
|
|
108
|
+
align-items: center;
|
|
109
|
+
font-size: var(--payment-method-form-brand-icon-size);
|
|
110
|
+
color: var(--a-fg-muted);
|
|
111
|
+
letter-spacing: 0.025em;
|
|
112
|
+
text-transform: uppercase;
|
|
113
|
+
}
|
|
114
|
+
:scope [data-brand-badge] > [data-brand] {
|
|
115
|
+
font-weight: var(--a-weight-semibold, 600);
|
|
116
|
+
color: var(--md-sys-color-neutral-on-surface);
|
|
117
|
+
font-size: var(--a-text-xs, 0.75rem);
|
|
118
|
+
padding-inline: var(--a-space-2);
|
|
119
|
+
padding-block: var(--a-space-1);
|
|
120
|
+
border-radius: var(--a-radius-sm);
|
|
121
|
+
background: var(--a-bg-muted);
|
|
122
|
+
}
|
|
123
|
+
:scope [data-brand-badge] > [data-brand="visa"] { color: var(--a-info-fg, var(--md-sys-color-neutral-on-surface)); }
|
|
124
|
+
:scope [data-brand-badge] > [data-brand="mastercard"] { color: var(--a-warning-fg, var(--md-sys-color-neutral-on-surface)); }
|
|
125
|
+
:scope [data-brand-badge] > [data-brand="amex"] { color: var(--a-primary-fg, var(--md-sys-color-neutral-on-surface)); }
|
|
126
|
+
:scope [data-brand-badge] > [data-brand="discover"] { color: var(--a-success-fg, var(--md-sys-color-neutral-on-surface)); }
|
|
127
|
+
|
|
128
|
+
/* ── Slotted legal copy ── */
|
|
129
|
+
:scope > [data-legal] {
|
|
130
|
+
color: var(--payment-method-form-legal-fg);
|
|
131
|
+
font-size: var(--payment-method-form-legal-size);
|
|
132
|
+
line-height: 1.5;
|
|
133
|
+
}
|
|
134
|
+
:scope > [data-legal]:empty {
|
|
135
|
+
display: none;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* ── Disabled state ── */
|
|
139
|
+
:scope[disabled] {
|
|
140
|
+
opacity: var(--payment-method-form-disabled-opacity);
|
|
141
|
+
pointer-events: none;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/* ── Focus-within outline (group-level affordance) ── */
|
|
145
|
+
:scope:focus-within {
|
|
146
|
+
/* Visually delegated to per-field controls; the host-level outline
|
|
147
|
+
would double-up against field-ui's focus styling. */
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<payment-method-form-ui>` — auto-registers the tag on import.
|
|
3
|
+
*
|
|
4
|
+
* For a non-side-effect class import (test isolation, tag override),
|
|
5
|
+
* use the class export from `./payment-method-form.class.js`:
|
|
6
|
+
*
|
|
7
|
+
* import { UIPaymentMethodForm } from '@adia-ai/web-modules/billing/payment-method-form/class';
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { UIPaymentMethodForm } from './payment-method-form.class.js';
|
|
11
|
+
|
|
12
|
+
if (!customElements.get('payment-method-form-ui')) {
|
|
13
|
+
customElements.define('payment-method-form-ui', UIPaymentMethodForm);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { UIPaymentMethodForm };
|
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
# Edit this file; run `npm run build:components` to regenerate a2ui.json.
|
|
2
|
+
$schema: ../../../../scripts/schemas/component.yaml.schema.json
|
|
3
|
+
name: UIPaymentMethodForm
|
|
4
|
+
tag: payment-method-form-ui
|
|
5
|
+
status: experimental
|
|
6
|
+
component: PaymentMethodForm
|
|
7
|
+
category: input
|
|
8
|
+
version: 1
|
|
9
|
+
description: |
|
|
10
|
+
Form-participating composite for capturing a payment method —
|
|
11
|
+
card number, expiry, CVC, name on card, billing address (optional),
|
|
12
|
+
and country. The form chrome + structured validation + a single
|
|
13
|
+
normalized emit event; it does NOT integrate with Stripe Elements
|
|
14
|
+
or a tokenization SDK directly (consumer responsibility).
|
|
15
|
+
|
|
16
|
+
Each sub-field is a <field-ui> wrapper around an <input-ui> (or
|
|
17
|
+
<select-ui> for country). Card number is Luhn-validated; expiry is
|
|
18
|
+
parsed as MM/YY with month + year bounds; CVC is 3-4 digits.
|
|
19
|
+
Brand detection (visa / mastercard / amex / discover) runs against
|
|
20
|
+
a small regex map and surfaces via the `change` event detail.
|
|
21
|
+
|
|
22
|
+
Form value is a JSON-encoded payload of normalized field values
|
|
23
|
+
serialized through ElementInternals under [name] (default
|
|
24
|
+
"paymentMethod"). On submit, the host fires
|
|
25
|
+
`submit-payment-method` with a flat detail
|
|
26
|
+
`{ token, last4, brand, expMonth, expYear, name, country }`.
|
|
27
|
+
`token` is a synthetic local-mode token (sha-like opaque string);
|
|
28
|
+
consumers integrating with a real processor handle tokenization
|
|
29
|
+
in their own submit listener using `last4` / `brand` / etc.
|
|
30
|
+
|
|
31
|
+
Spec: .claude/docs/specs/implementation-ready/SPEC-009-payment-method-form.md.
|
|
32
|
+
|
|
33
|
+
# Per ADR-0027 — composites do NOT auto-import the primitives they
|
|
34
|
+
# stamp in connected()/render(). The consumer (or this primitive's
|
|
35
|
+
# .html demo shell) must explicitly side-effect-import each one.
|
|
36
|
+
composes:
|
|
37
|
+
- field-ui
|
|
38
|
+
- input-ui
|
|
39
|
+
- select-ui
|
|
40
|
+
- alert-ui
|
|
41
|
+
- icon-ui
|
|
42
|
+
- button-ui
|
|
43
|
+
|
|
44
|
+
props:
|
|
45
|
+
name:
|
|
46
|
+
description: |
|
|
47
|
+
Form field name. The composite's serialized form value lives
|
|
48
|
+
under this key in any wrapping <form>. Defaults to
|
|
49
|
+
"paymentMethod".
|
|
50
|
+
type: string
|
|
51
|
+
default: "paymentMethod"
|
|
52
|
+
reflect: true
|
|
53
|
+
|
|
54
|
+
value:
|
|
55
|
+
description: |
|
|
56
|
+
Resolved payment-method token. Read-only externally — the
|
|
57
|
+
composite writes it after a successful tokenize() call. Setting
|
|
58
|
+
this to a non-empty string is treated as "prefilled from a
|
|
59
|
+
saved payment method" and renders the form in
|
|
60
|
+
read-only-summary mode (last4 + brand + expiry shown).
|
|
61
|
+
type: string
|
|
62
|
+
default: ""
|
|
63
|
+
reflect: true
|
|
64
|
+
dynamic: true
|
|
65
|
+
|
|
66
|
+
prefill:
|
|
67
|
+
description: |
|
|
68
|
+
JSON-encoded prefill payload `{last4, brand, expMonth, expYear,
|
|
69
|
+
name, country}`. When set, the summary row renders with the
|
|
70
|
+
saved-card chrome and the rest of the form is hidden behind an
|
|
71
|
+
"Edit card" button. Useful for "update saved payment method"
|
|
72
|
+
flows.
|
|
73
|
+
type: string
|
|
74
|
+
default: ""
|
|
75
|
+
attribute: prefill
|
|
76
|
+
|
|
77
|
+
countries:
|
|
78
|
+
description: |
|
|
79
|
+
Allowed billing countries, ISO 3166-1 alpha-2 codes. Drives
|
|
80
|
+
the <select-ui> dropdown's options. Empty array uses a
|
|
81
|
+
default short list (US, CA, GB, DE, FR, AU).
|
|
82
|
+
type: array
|
|
83
|
+
default: []
|
|
84
|
+
dynamic: true
|
|
85
|
+
|
|
86
|
+
default-country:
|
|
87
|
+
description: |
|
|
88
|
+
Default selected country (ISO 3166-1 alpha-2). Falls back to
|
|
89
|
+
the first entry in `countries` (or "US" when empty).
|
|
90
|
+
type: string
|
|
91
|
+
default: "US"
|
|
92
|
+
reflect: true
|
|
93
|
+
attribute: default-country
|
|
94
|
+
|
|
95
|
+
require-billing-address:
|
|
96
|
+
description: |
|
|
97
|
+
When set, renders the billing-address sub-fields (address line
|
|
98
|
+
1, optional line 2, postal code). When unset, only postal code
|
|
99
|
+
+ country are collected for the address-verification check.
|
|
100
|
+
type: boolean
|
|
101
|
+
default: false
|
|
102
|
+
reflect: true
|
|
103
|
+
attribute: require-billing-address
|
|
104
|
+
|
|
105
|
+
disabled:
|
|
106
|
+
description: |
|
|
107
|
+
Forwarded to every sub-control. Pointer-events:none on the
|
|
108
|
+
composite host as a belt-and-suspenders.
|
|
109
|
+
type: boolean
|
|
110
|
+
default: false
|
|
111
|
+
reflect: true
|
|
112
|
+
dynamic: true
|
|
113
|
+
|
|
114
|
+
required:
|
|
115
|
+
description: |
|
|
116
|
+
Form-validation gate. When set, an empty composite fails
|
|
117
|
+
checkValidity() with "Payment method required.".
|
|
118
|
+
type: boolean
|
|
119
|
+
default: false
|
|
120
|
+
reflect: true
|
|
121
|
+
|
|
122
|
+
error:
|
|
123
|
+
description: |
|
|
124
|
+
Externally-set error message (e.g. server-rejected card). When
|
|
125
|
+
non-empty, the composite renders an <alert-ui variant="danger">
|
|
126
|
+
at the top of the form and sets aria-invalid=true on the host.
|
|
127
|
+
type: string
|
|
128
|
+
default: ""
|
|
129
|
+
reflect: true
|
|
130
|
+
dynamic: true
|
|
131
|
+
|
|
132
|
+
tokenizing:
|
|
133
|
+
description: |
|
|
134
|
+
tokenize() in flight — set internally by the composite (and
|
|
135
|
+
cleared on settle), same read-only-externally convention as
|
|
136
|
+
`value`. Declared here (mirroring the `states:` entry below) so
|
|
137
|
+
the in-flight visual state is representable in authored/generated
|
|
138
|
+
markup for documentation and storyboard fixtures.
|
|
139
|
+
type: boolean
|
|
140
|
+
default: false
|
|
141
|
+
reflect: true
|
|
142
|
+
|
|
143
|
+
autofocus:
|
|
144
|
+
description: |
|
|
145
|
+
When set, the first sub-field (Name on card) receives focus on
|
|
146
|
+
first connect. Convention parity with native form elements.
|
|
147
|
+
type: boolean
|
|
148
|
+
default: false
|
|
149
|
+
reflect: true
|
|
150
|
+
|
|
151
|
+
events:
|
|
152
|
+
submit-payment-method:
|
|
153
|
+
description: |
|
|
154
|
+
Fired when tokenize() resolves — either via an outer <form>
|
|
155
|
+
submission or an explicit tokenize() call. Detail carries the
|
|
156
|
+
normalized payload that downstream code POSTs to the billing
|
|
157
|
+
service. Bubbles.
|
|
158
|
+
detail:
|
|
159
|
+
token:
|
|
160
|
+
type: string
|
|
161
|
+
description: Synthetic local-mode token (sha-like opaque string).
|
|
162
|
+
last4:
|
|
163
|
+
type: string
|
|
164
|
+
description: Last 4 digits of the card number.
|
|
165
|
+
brand:
|
|
166
|
+
type: string
|
|
167
|
+
description: Detected brand — `visa`, `mastercard`, `amex`, `discover`, or `unknown`.
|
|
168
|
+
expMonth:
|
|
169
|
+
type: integer
|
|
170
|
+
description: Expiry month (1-12).
|
|
171
|
+
expYear:
|
|
172
|
+
type: integer
|
|
173
|
+
description: Expiry year (4-digit).
|
|
174
|
+
name:
|
|
175
|
+
type: string
|
|
176
|
+
description: Name on card.
|
|
177
|
+
country:
|
|
178
|
+
type: string
|
|
179
|
+
description: ISO 3166-1 alpha-2 billing country.
|
|
180
|
+
|
|
181
|
+
payment-method-error:
|
|
182
|
+
description: |
|
|
183
|
+
Fired when tokenize() fails — either constraint validation
|
|
184
|
+
surfaced one or more field errors, or a Luhn / expiry / CVC
|
|
185
|
+
check failed. Bubbles.
|
|
186
|
+
detail:
|
|
187
|
+
message:
|
|
188
|
+
type: string
|
|
189
|
+
description: Human-readable error message.
|
|
190
|
+
code:
|
|
191
|
+
type: string
|
|
192
|
+
description: Error code — one of `validation-failed`, `card-invalid`, `expired`, `cvc-invalid`.
|
|
193
|
+
field:
|
|
194
|
+
type: string
|
|
195
|
+
description: Field name that surfaced the error (`cardNumber` / `expiry` / `cvc` / `name` / `postalCode` / `country` / null).
|
|
196
|
+
|
|
197
|
+
change:
|
|
198
|
+
description: |
|
|
199
|
+
Fired on every sub-field input. Detail carries a snapshot of
|
|
200
|
+
the current form validity + detected card brand. Bubbles.
|
|
201
|
+
detail:
|
|
202
|
+
valid:
|
|
203
|
+
type: boolean
|
|
204
|
+
description: Whether the form currently passes all constraints.
|
|
205
|
+
brand:
|
|
206
|
+
type: string
|
|
207
|
+
description: Detected brand (`visa` / `mastercard` / `amex` / `discover` / `unknown`).
|
|
208
|
+
|
|
209
|
+
slots:
|
|
210
|
+
legal:
|
|
211
|
+
description: |
|
|
212
|
+
Optional content rendered below the form fields — typically a
|
|
213
|
+
terms-of-storage acknowledgement string with link(s).
|
|
214
|
+
|
|
215
|
+
states:
|
|
216
|
+
- name: idle
|
|
217
|
+
description: Default; ready for input.
|
|
218
|
+
- name: tokenizing
|
|
219
|
+
description: tokenize() in flight.
|
|
220
|
+
attribute: tokenizing
|
|
221
|
+
- name: error
|
|
222
|
+
description: A field-level or host-level error is present.
|
|
223
|
+
attribute: error
|
|
224
|
+
- name: prefilled
|
|
225
|
+
description: A saved payment method is displayed; form is hidden.
|
|
226
|
+
attribute: prefilled
|
|
227
|
+
- name: disabled
|
|
228
|
+
description: All sub-fields non-interactive.
|
|
229
|
+
attribute: disabled
|
|
230
|
+
|
|
231
|
+
traits: []
|
|
232
|
+
|
|
233
|
+
tokens:
|
|
234
|
+
--payment-method-form-gap:
|
|
235
|
+
description: Gap between rows of the form grid.
|
|
236
|
+
default: var(--a-space-3)
|
|
237
|
+
--payment-method-form-grid-template:
|
|
238
|
+
description: |
|
|
239
|
+
Grid-template-areas for the field layout. Defaults to a
|
|
240
|
+
4-row template — name spans both columns, card number spans
|
|
241
|
+
both, expiry + cvc share row 3, country + postal share row 4.
|
|
242
|
+
Address rows append when `require-billing-address` is set.
|
|
243
|
+
default: '"name name" "card card" "expiry cvc" "country postal"'
|
|
244
|
+
--payment-method-form-brand-icon-size:
|
|
245
|
+
description: Inline brand-badge icon size in the card-number suffix.
|
|
246
|
+
default: 1.25em
|
|
247
|
+
--payment-method-form-alert-mb:
|
|
248
|
+
description: Margin-block-end on the host-level error alert.
|
|
249
|
+
default: var(--a-space-3)
|
|
250
|
+
--payment-method-form-summary-bg:
|
|
251
|
+
description: Background of the saved-card summary row.
|
|
252
|
+
default: var(--a-bg-muted)
|
|
253
|
+
--payment-method-form-summary-border:
|
|
254
|
+
description: Border on the saved-card summary row.
|
|
255
|
+
default: 1px solid var(--a-border)
|
|
256
|
+
--payment-method-form-summary-radius:
|
|
257
|
+
description: Corner radius on the saved-card summary row.
|
|
258
|
+
default: var(--a-radius-md)
|
|
259
|
+
--payment-method-form-summary-px:
|
|
260
|
+
description: Horizontal padding inside the saved-card summary row.
|
|
261
|
+
default: var(--a-space-4)
|
|
262
|
+
--payment-method-form-summary-py:
|
|
263
|
+
description: Vertical padding inside the saved-card summary row.
|
|
264
|
+
default: var(--a-space-3)
|
|
265
|
+
--payment-method-form-legal-fg:
|
|
266
|
+
description: Foreground color of the slotted legal copy.
|
|
267
|
+
default: var(--a-fg-muted)
|
|
268
|
+
--payment-method-form-legal-size:
|
|
269
|
+
description: Font size of the slotted legal copy.
|
|
270
|
+
default: var(--a-text-xs, 0.75rem)
|
|
271
|
+
--payment-method-form-disabled-opacity:
|
|
272
|
+
description: Opacity applied to the host when [disabled].
|
|
273
|
+
default: var(--a-opacity-disabled, 0.5)
|
|
274
|
+
|
|
275
|
+
requiredIcons:
|
|
276
|
+
- credit-card
|
|
277
|
+
- lock-key
|
|
278
|
+
- warning-circle
|
|
279
|
+
|
|
280
|
+
a2ui:
|
|
281
|
+
rules:
|
|
282
|
+
- >-
|
|
283
|
+
PaymentMethodForm SHOULD be wrapped in a <Form> so its
|
|
284
|
+
form-value (the resolved token) is delivered on submission.
|
|
285
|
+
Standalone use requires the consumer wire `tokenize()` from a
|
|
286
|
+
custom submit handler.
|
|
287
|
+
- >-
|
|
288
|
+
PaymentMethodForm MUST NOT receive a `value` prop carrying raw
|
|
289
|
+
card digits. The form value is the tokenized output; raw card
|
|
290
|
+
digits live only inside the form's sub-fields and are never
|
|
291
|
+
mirrored to `value`.
|
|
292
|
+
- >-
|
|
293
|
+
PaymentMethodForm SHOULD only be used in test / demo / non-PCI
|
|
294
|
+
surfaces. Production card-capture flows MUST tokenize via a
|
|
295
|
+
real payment processor (Stripe Elements, Braintree, Adyen)
|
|
296
|
+
and consume only the resulting token — this primitive is the
|
|
297
|
+
form chrome + structured validation, not a tokenization
|
|
298
|
+
provider.
|
|
299
|
+
- >-
|
|
300
|
+
Wrapping PaymentMethodForm inside <Field> duplicates the label
|
|
301
|
+
and corrupts the grid layout. PaymentMethodForm IS a field
|
|
302
|
+
group; the host carries `aria-label` directly.
|
|
303
|
+
- >-
|
|
304
|
+
`countries` SHOULD list every ISO 3166-1 alpha-2 code your
|
|
305
|
+
product accepts. Empty arrays fall back to a default short
|
|
306
|
+
list (US, CA, GB, DE, FR, AU) suitable for early-stage demos
|
|
307
|
+
only — production deployments should set this explicitly.
|
|
308
|
+
|
|
309
|
+
anti_patterns:
|
|
310
|
+
- wrong: |
|
|
311
|
+
<payment-method-form-ui value="4242 4242 4242 4242"></payment-method-form-ui>
|
|
312
|
+
why: |
|
|
313
|
+
Raw card digits in `value`. The composite's value is the
|
|
314
|
+
tokenized output, never the input. Raw digits leak through
|
|
315
|
+
reflection back to the attribute and end up in DOM snapshots /
|
|
316
|
+
browser history / analytics.
|
|
317
|
+
fix: |
|
|
318
|
+
<payment-method-form-ui name="paymentMethod" required></payment-method-form-ui>
|
|
319
|
+
- wrong: |
|
|
320
|
+
<field-ui label="Card details">
|
|
321
|
+
<payment-method-form-ui></payment-method-form-ui>
|
|
322
|
+
</field-ui>
|
|
323
|
+
why: |
|
|
324
|
+
PaymentMethodForm IS itself a labeled field group; nesting in
|
|
325
|
+
Field duplicates the label and breaks the internal grid
|
|
326
|
+
layout. Field's auto-id stamping confuses the composite's
|
|
327
|
+
first-focusable lookup.
|
|
328
|
+
fix: |
|
|
329
|
+
<payment-method-form-ui aria-label="Card details"></payment-method-form-ui>
|
|
330
|
+
- wrong: |
|
|
331
|
+
<form>
|
|
332
|
+
<payment-method-form-ui></payment-method-form-ui>
|
|
333
|
+
<button-ui type="submit" text="Save"></button-ui>
|
|
334
|
+
</form>
|
|
335
|
+
<script>
|
|
336
|
+
form.addEventListener('submit', (e) => fetch('/charge', { body: new FormData(form) }));
|
|
337
|
+
</script>
|
|
338
|
+
why: |
|
|
339
|
+
Posting the form's serialized token directly to /charge skips
|
|
340
|
+
tokenization — the synthetic local-mode token is opaque but
|
|
341
|
+
NOT a real payment token. A real processor must mint the
|
|
342
|
+
token before the charge call.
|
|
343
|
+
fix: |
|
|
344
|
+
<form>
|
|
345
|
+
<payment-method-form-ui id="pm"></payment-method-form-ui>
|
|
346
|
+
<button-ui type="submit" text="Save"></button-ui>
|
|
347
|
+
</form>
|
|
348
|
+
<script>
|
|
349
|
+
form.addEventListener('submit', async (e) => {
|
|
350
|
+
e.preventDefault();
|
|
351
|
+
const detail = await pm.tokenize();
|
|
352
|
+
// Hand `detail.last4` / `detail.brand` to your processor SDK
|
|
353
|
+
// to mint a real token; POST the resulting token to /charge.
|
|
354
|
+
});
|
|
355
|
+
</script>
|
|
356
|
+
|
|
357
|
+
examples:
|
|
358
|
+
- name: default
|
|
359
|
+
description: Empty form, all sub-fields visible, required.
|
|
360
|
+
a2ui: |
|
|
361
|
+
[
|
|
362
|
+
{
|
|
363
|
+
"id": "pm-1",
|
|
364
|
+
"component": "PaymentMethodForm",
|
|
365
|
+
"name": "paymentMethod",
|
|
366
|
+
"required": true
|
|
367
|
+
}
|
|
368
|
+
]
|
|
369
|
+
- name: prefilled-saved-card
|
|
370
|
+
description: |
|
|
371
|
+
Edit-saved-card flow — summary row renders with the saved
|
|
372
|
+
card; "Edit card" CTA reveals the full form.
|
|
373
|
+
a2ui: |
|
|
374
|
+
[
|
|
375
|
+
{
|
|
376
|
+
"id": "pm-2",
|
|
377
|
+
"component": "PaymentMethodForm",
|
|
378
|
+
"name": "paymentMethod",
|
|
379
|
+
"prefill": "{\"last4\":\"4242\",\"brand\":\"visa\",\"expMonth\":12,\"expYear\":2027,\"name\":\"Pat Doe\",\"country\":\"US\"}"
|
|
380
|
+
}
|
|
381
|
+
]
|
|
382
|
+
- name: with-billing-address
|
|
383
|
+
description: |
|
|
384
|
+
Full form including billing address lines + postal + country.
|
|
385
|
+
a2ui: |
|
|
386
|
+
[
|
|
387
|
+
{
|
|
388
|
+
"id": "pm-3",
|
|
389
|
+
"component": "PaymentMethodForm",
|
|
390
|
+
"name": "paymentMethod",
|
|
391
|
+
"requireBillingAddress": true,
|
|
392
|
+
"countries": ["US", "CA", "GB", "DE"]
|
|
393
|
+
}
|
|
394
|
+
]
|
|
395
|
+
|
|
396
|
+
keywords:
|
|
397
|
+
- payment-method
|
|
398
|
+
- card
|
|
399
|
+
- billing
|
|
400
|
+
- checkout
|
|
401
|
+
- card-capture
|
|
402
|
+
- payment
|
|
403
|
+
- credit-card
|
|
404
|
+
- debit-card
|
|
405
|
+
- save-payment-method
|
|
406
|
+
- update-payment-method
|
|
407
|
+
- add-card
|
|
408
|
+
|
|
409
|
+
synonyms:
|
|
410
|
+
payment-method:
|
|
411
|
+
- card
|
|
412
|
+
- card-on-file
|
|
413
|
+
- billing
|
|
414
|
+
card:
|
|
415
|
+
- payment-card
|
|
416
|
+
- credit-card
|
|
417
|
+
- debit-card
|
|
418
|
+
billing:
|
|
419
|
+
- billing-info
|
|
420
|
+
- payment-method
|
|
421
|
+
- card
|
|
422
|
+
|
|
423
|
+
related:
|
|
424
|
+
- Form
|
|
425
|
+
- Field
|
|
426
|
+
- Input
|
|
427
|
+
- Select
|
|
428
|
+
- Alert
|
|
429
|
+
- PlanPicker
|
|
430
|
+
- Button
|