@usgb/forms 1.0.1 → 1.0.3

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.
Files changed (42) hide show
  1. package/README.md +139 -104
  2. package/dist/forms-manifest.1.0.3.json +439 -0
  3. package/dist/forms-manifest.json +252 -64
  4. package/dist/index.js +747 -670
  5. package/dist/src/contract/createIdempotencyKey.d.ts +2 -0
  6. package/dist/src/contract/createIdempotencyKey.d.ts.map +1 -0
  7. package/dist/src/contract/createStubAdapter.d.ts.map +1 -1
  8. package/dist/src/contract/types.d.ts +21 -25
  9. package/dist/src/contract/types.d.ts.map +1 -1
  10. package/dist/src/definitions/consents.d.ts +63 -20
  11. package/dist/src/definitions/consents.d.ts.map +1 -1
  12. package/dist/src/definitions/index.d.ts +5 -4
  13. package/dist/src/definitions/index.d.ts.map +1 -1
  14. package/dist/src/definitions/manifest.d.ts +14 -1
  15. package/dist/src/definitions/manifest.d.ts.map +1 -1
  16. package/dist/src/definitions/types.d.ts +44 -9
  17. package/dist/src/definitions/types.d.ts.map +1 -1
  18. package/dist/src/form/FormShell.d.ts +2 -1
  19. package/dist/src/form/FormShell.d.ts.map +1 -1
  20. package/dist/src/form/UsgbForm.d.ts +5 -4
  21. package/dist/src/form/UsgbForm.d.ts.map +1 -1
  22. package/dist/src/form/chunkFields.d.ts +1 -1
  23. package/dist/src/form/kinds/LeadKindForm.d.ts +1 -1
  24. package/dist/src/form/kinds/LeadKindForm.d.ts.map +1 -1
  25. package/dist/src/form/kinds/NewsletterKindForm.d.ts +1 -1
  26. package/dist/src/form/kinds/NewsletterKindForm.d.ts.map +1 -1
  27. package/dist/src/form/kinds/types.d.ts +3 -1
  28. package/dist/src/form/kinds/types.d.ts.map +1 -1
  29. package/dist/src/form/useUsgbFormSession.d.ts +7 -8
  30. package/dist/src/form/useUsgbFormSession.d.ts.map +1 -1
  31. package/dist/src/index.d.ts +5 -5
  32. package/dist/src/index.d.ts.map +1 -1
  33. package/dist/src/ui/Button.d.ts.map +1 -1
  34. package/dist/src/ui/ConsentField.d.ts.map +1 -1
  35. package/dist/usgb-forms.1.0.3.js +44 -0
  36. package/dist/usgb-forms.css +98 -15
  37. package/dist/usgb-forms.js +11 -11
  38. package/forms-manifest.json +252 -64
  39. package/package.json +2 -2
  40. package/dist/src/contract/collectContext.d.ts +0 -9
  41. package/dist/src/contract/collectContext.d.ts.map +0 -1
  42. package/dist/usgb-forms.1.0.1.js +0 -44
package/README.md CHANGED
@@ -2,47 +2,76 @@
2
2
 
3
3
  Shared lead and newsletter forms for the **PWA** (React) and **WordPress** (Web Component) hosts.
4
4
 
5
- You pick a predefined `formId`. The package owns fields, validation, consent copy, tracking keys, and layout. You own the submit endpoint, legal-document URLs, heading/subheading/CTA copy, and thank-you behavior.
5
+ You pick a predefined `formId`. The package owns fields, validation, consent copy, and layout. You own the submit endpoint, legal-document URLs, heading/subheading/CTA copy, and thank-you behavior. The backend owns tracking and page-context collection.
6
6
 
7
7
  ## What you get
8
8
 
9
- | Artifact | Path / export | Who uses it |
10
- | ------------- | --------------------------------------------------------------- | ----------------------------------- |
11
- | React package | `@usgb/forms` → `dist/index.js` | PWA / any React host |
12
- | Stylesheet | `@usgb/forms/usgb-forms.css` | **Required** for React hosts |
13
- | Web Component | `dist/usgb-forms.js` (also versioned `usgb-forms.<version>.js`) | WordPress and other non-React hosts |
14
- | Catalog | `@usgb/forms/manifest` → `forms-manifest.json` | CMS pickers, docs, tooling |
9
+ | Artifact | Path / export | Who uses it |
10
+ | ------------- | ---------------------------------------------------------------------------------------------------------- | ----------------------------------- |
11
+ | React package | `@usgb/forms` → `dist/index.js` | PWA / any React host |
12
+ | Stylesheet | `@usgb/forms/usgb-forms.css` | **Required** for React hosts |
13
+ | Web Component | `dist/usgb-forms.js` (also versioned `usgb-forms.<version>.js`) | WordPress and other non-React hosts |
14
+ | Catalog | `@usgb/forms/manifest` → `forms-manifest.json` (also versioned `forms-manifest.<version>.json` in `dist/`) | CMS pickers, Gutenberg, tooling |
15
15
 
16
16
  The Web Component script injects the same CSS once on load. React hosts must import the stylesheet themselves.
17
17
 
18
18
  ## Mental model
19
19
 
20
- | You pass | Package already decided |
21
- | -------------------------------- | ------------------------------------------------------------------------------------- |
22
- | `formId` | Fields, required/optional rules, consent bundle, tracking set, layout family (`kind`) |
23
- | `adapter.submit` | Where the payload goes (never an attribute or hardcoded URL) |
24
- | `legalUrls` / `*-url` | Hrefs for package-owned consent copy |
25
- | `heading`, `subheading`, `ctaLabel` | Marketing copy around the form |
26
- | `successMessage` or `successUrl` | Thank-you UX after accept |
20
+ | You pass | Package already decided |
21
+ | ----------------------------------- | --------------------------------------------------------------------- |
22
+ | `formId` | Fields, required/optional rules, consent pins, layout family (`kind`) |
23
+ | `adapter.submit` | Where the payload goes (never an attribute or hardcoded URL) |
24
+ | `legalUrls` / `*-url` | Hrefs for package-owned consent copy |
25
+ | `heading`, `subheading`, `ctaLabel` | Marketing copy around the form |
26
+ | `successMessage` or `successUrl` | Thank-you UX after accept |
27
27
 
28
- Hosts **must not** invent field lists, consent wording, or tracking keys. New forms are new catalog entries in this package, not host-built schemas.
28
+ Hosts **must not** invent field lists or consent wording. New forms are new catalog entries in this package, not host-built schemas.
29
29
 
30
- Use `listFormDefinitions()` (or the manifest) when a CMS needs a picker of available `formId`s. Deeper catalog rules: [`src/definitions/context.md`](src/definitions/context.md).
30
+ Use `listFormDefinitions()` (or the manifest) when a CMS needs a picker of available `formId`s, and `listEditorOptions(formId)` for the settings that picker may expose (see [Editor options](#editor-options)).
31
31
 
32
32
  ## Available forms
33
33
 
34
- | `formId` | Kind | Fields | Consent | Variants |
35
- | -------------------- | ------------ | --------------------------------------------------------- | ------------------------------ | ------------------------------------------------------- |
36
- | `main-investors-kit` | `lead` | First name, last name, email (required); phone (optional) | TCPA checkbox (`lead-tcpa` v1) | `dense`, `large`, `sidebar`, plus optional `two-column` |
37
- | `newsletter` | `newsletter` | Email only | None | None — omit `variants` / `variant` |
34
+ | `formId` | Kind | Fields | Consent | Size/layout |
35
+ | --------------------------- | ------------ | --------------------------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------ |
36
+ | `magento-fik` | `lead` | First name, last name, email (required); phone (optional) | Optional TCPA (v1), marketing SMS, and terms/privacy checkboxes | `dense`, `large`, or `sidebar`; optional two-column name row |
37
+ | `magento-ira-kick-article` | `lead` | First name, last name, email, phone (all required) | Optional TCPA checkbox (v2, links terms and privacy) | `dense`, `large`, or `sidebar`; optional two-column name row |
38
+ | `magento-fik-blog-rail` | `lead` | First name, last name, email, phone (all required) | Optional TCPA checkbox (v2, links terms and privacy) | `dense`, `large`, or `sidebar`; optional two-column name row |
39
+ | `main-investors-kit-notice` | `lead` | Same as `magento-fik` | Clickwrap notice only (`lead-clickwrap` v2) | `dense`, `large`, or `sidebar`; optional two-column name row |
40
+ | `newsletter` | `newsletter` | Email only | None | None — omit `variant` and `twoColumn` / `two-column` |
38
41
 
39
- Appearances for both: `on-light` | `on-dark`. Appearance only recolors the form for readability on a light or dark host background — it never sets a background, padding, or radius. The host container owns those.
42
+ Appearances for every catalog form: `on-light` | `on-dark`. Appearance only recolors the form for readability on a light or dark host background — it never sets a background, padding, or radius. The host container owns those.
40
43
 
41
44
  `kind` is the layout family (lead grid vs inline newsletter row). The root exposes `data-kind` for CSS. Several catalog forms can share one kind (e.g. another lead kit that reuses the lead layout).
42
45
 
43
- ## Install
46
+ ### Editor options
47
+
48
+ `editorOptions` in the manifest lists every host-owned setting an editor may apply, and each form's `editor.options` lists the ones that form accepts. A CMS panel should build its controls from those two lists instead of hardcoding prop names:
49
+
50
+ | Option | Control | React prop | Attribute | Applies to |
51
+ | ---------------- | --------- | ---------------- | ---------------------------------------- | ------------------------------------------------ |
52
+ | `appearance` | select | `appearance` | `appearance` | All forms — values in `supportedAppearances` |
53
+ | `variant` | select | `variant` | `variant` | Lead forms — values in `supportedVariants` |
54
+ | `twoColumn` | checkbox | `twoColumn` | `two-column` | Lead forms — independent of the size variant |
55
+ | `heading` | text | `heading` | `heading` | All forms |
56
+ | `subheading` | text | `subheading` | `subheading` | All forms |
57
+ | `ctaLabel` | text | `ctaLabel` | `cta` | All forms — default is the form's `ctaLabel` |
58
+ | `legalUrls` | url group | `legalUrls` | `*-url` (see `attributes` on the option) | Forms with consent — keys in `requiredLegalUrls` |
59
+ | `successMessage` | text | `successMessage` | `success-message` | All forms |
60
+ | `successUrl` | url | `successUrl` | `success-url` | All forms |
61
+
62
+ Only `legalUrls` is required, and only for the keys a form's consents name — the form does not render when one is missing. Everything else is optional.
44
63
 
45
- Registry package name, scope, and CDN base URL are **TBD** — examples below use the working package name `@usgb/forms` and a placeholder CDN host. Replace them when publishing is finalized.
64
+ `listEditorOptions(formId)` returns those options already resolved for one form (allowed values, effective default, React prop, and attribute), so a Gutenberg panel does not have to follow the `valuesFrom` / `defaultFrom` pointers itself:
65
+
66
+ ```ts
67
+ import { listEditorOptions } from '@usgb/forms'
68
+
69
+ listEditorOptions('newsletter')
70
+ // [{ key: 'appearance', control: 'select', values: ['on-light', 'on-dark'], defaultValue: 'on-light', … }, …]
71
+ // `variant`, `twoColumn`, and `legalUrls` are absent — newsletter takes none.
72
+ ```
73
+
74
+ ## Install
46
75
 
47
76
  ### npm (React / PWA)
48
77
 
@@ -63,15 +92,13 @@ Peer dependency: `react` and `react-dom` `^18` or `^19`.
63
92
 
64
93
  ### CDN (Web Component / WordPress)
65
94
 
66
- Load the built IIFE (styles inject themselves):
95
+ Load the built script for a release (styles inject themselves):
67
96
 
68
97
  ```html
69
- <script src="https://cdn.example.com/usgb-forms/usgb-forms.1.0.0.js"></script>
98
+ <script src="https://forms.usgoldbureau.com/usgb-forms.1.0.3.js"></script>
70
99
  ```
71
100
 
72
- Exact CDN hostname, path, and versioning scheme are **TBD**. Prefer a versioned filename (`usgb-forms.<version>.js`) so hosts can pin releases.
73
-
74
- Until the package is published, you can still develop against a local checkout (`yarn add file:../usgb-forms` or `yarn link`).
101
+ Pin the script and the catalog together: `usgb-forms.<version>.js` and `forms-manifest.<version>.json` on `https://forms.usgoldbureau.com/`. Gutenberg should load that matching manifest when listing `formId`s.
75
102
 
76
103
  ## React (PWA)
77
104
 
@@ -79,14 +106,13 @@ Until the package is published, you can still develop against a local checkout (
79
106
  import { UsgbForm, createStubAdapter, PWA_LEGAL_URLS } from '@usgb/forms'
80
107
  import '@usgb/forms/usgb-forms.css'
81
108
  ;<UsgbForm
82
- formId="main-investors-kit"
109
+ formId="magento-fik"
83
110
  appearance="on-dark"
84
- variants={['large', 'two-column']}
111
+ variant="large"
112
+ twoColumn
85
113
  heading="Get My Free Guide"
86
114
  subheading="Enter your details to receive the Main Investors Kit."
87
115
  ctaLabel="GET MY FREE GUIDE"
88
- source="cms-home"
89
- campaign="spring-kit"
90
116
  legalUrls={PWA_LEGAL_URLS}
91
117
  successMessage="Thanks — we will send your kit shortly."
92
118
  adapter={yourHostAdapter}
@@ -99,7 +125,7 @@ import '@usgb/forms/usgb-forms.css'
99
125
  />
100
126
  ```
101
127
 
102
- Newsletter (no consent, no variants):
128
+ Newsletter (no consent or lead layout options):
103
129
 
104
130
  ```tsx
105
131
  <UsgbForm
@@ -113,42 +139,51 @@ Newsletter (no consent, no variants):
113
139
 
114
140
  ### React props
115
141
 
116
- | Prop | Required | Role |
117
- | ------------------------- | -------------------------- | --------------------------------------------------------------------------------------------------- |
118
- | `formId` | yes | Catalog key (`main-investors-kit`, `newsletter`, …) |
119
- | `adapter` | yes | `HostAdapter` with `host`, `getTrackingHints()`, `submit()` |
120
- | `appearance` | no | `on-light` (default) or `on-dark` |
121
- | `variants` | no | Lead only. Default `['dense']`. One of `dense` \| `large` \| `sidebar`, optionally add `two-column` |
122
- | `heading` / `subheading` | no | Title and supporting copy |
123
- | `ctaLabel` | no | Submit button label. Falls back to the catalog `ctaLabel` for that `formId` |
124
- | `source` / `campaign` | no | Placement / campaign context in the payload |
125
- | `legalUrls` | when consent requires them | Host CMS paths for legal links in consent copy |
126
- | `successMessage` | no | Inline thank-you when `successUrl` is omitted |
127
- | `successUrl` | no | Redirect after accept (analytics / `onAccepted` are invoked first; see Success behavior) |
128
- | `analytics` | no | `(event) => void` for view / validation / submit / success / failure |
129
- | `className` | no | Extra class on `.usgb-form` |
130
- | `onAccepted` / `onFailed` | no | Callbacks with the submission payload |
142
+ | Prop | Required | Role |
143
+ | ------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
144
+ | `formId` | yes | Catalog key (`magento-fik`, `newsletter`, …) |
145
+ | `adapter` | yes | `HostAdapter` with `host` and `submit()` |
146
+ | `appearance` | no | `on-light` (default) or `on-dark` |
147
+ | `variant` | no | Lead only. Default `dense`. Exactly one of `dense` \| `large` \| `sidebar` |
148
+ | `twoColumn` | no | Lead only. Places grouped name fields in two columns when space allows |
149
+ | `heading` / `subheading` | no | Title and supporting copy |
150
+ | `ctaLabel` | no | Submit button label. Falls back to the catalog `ctaLabel` for that `formId` |
151
+ | `legalUrls` | when consent requires them | Host CMS paths. Keys: `clientAgreement`, `privacyPolicy`, `userAgreement`, `marketLossPolicy`, `electronicDisclaimer`, `termsOfSale` (see Consent and legal URLs) |
152
+ | `successMessage` | no | Inline thank-you when `successUrl` is omitted |
153
+ | `successUrl` | no | Redirect after accept (analytics / `onAccepted` are invoked first; see Success behavior) |
154
+ | `analytics` | no | `(event) => void`. Event `type`: `view` \| `validation_failure` \| `submit_attempt` \| `success` \| `failure`. React-only — the Web Component has no equivalent |
155
+ | `className` | no | Extra class on `.usgb-form`. React-only — put classes on the host page around `<usgb-form>` |
156
+ | `onAccepted` / `onFailed` | no | Callbacks with the submission payload. Web Component: `usgb-form:success` / `usgb-form:failure` |
131
157
 
132
158
  ## Web Component (WordPress)
133
159
 
134
160
  Load one script. Styles are injected automatically.
135
161
 
136
- ````html
137
- <script src="https://cdn.example.com/usgb-forms/usgb-forms.1.0.0.js"></script>
162
+ ```html
163
+ <script src="https://forms.usgoldbureau.com/usgb-forms.1.0.3.js"></script>
138
164
  <usgb-form
139
- ```
140
- form-id="main-investors-kit"
165
+ form-id="magento-fik"
141
166
  appearance="on-dark"
142
- variant="large two-column"
167
+ variant="large"
168
+ two-column
143
169
  heading="Get My Free Guide"
144
170
  subheading="Enter your details to receive the Main Investors Kit."
145
171
  cta="GET MY FREE GUIDE"
146
- source="cms-home"
147
- client-agreement-url="/client-agreement/"
172
+ user-agreement-url="/user-agreement/"
148
173
  privacy-policy-url="/privacy-policy/"
149
174
  success-message="Thanks — we will send your kit shortly."
150
175
  ></usgb-form>
151
- ````
176
+ ```
177
+
178
+ Clickwrap kit (`main-investors-kit-notice`) needs the two notice URLs:
179
+
180
+ ```html
181
+ <usgb-form
182
+ form-id="main-investors-kit-notice"
183
+ privacy-policy-url="/privacy-policy/"
184
+ user-agreement-url="/user-agreement/"
185
+ ></usgb-form>
186
+ ```
152
187
 
153
188
  Submit is **not** an attribute. Markup alone uses a stub adapter. Assign a real `HostAdapter` in script:
154
189
 
@@ -157,10 +192,6 @@ Submit is **not** an attribute. Markup alone uses a stub adapter. Assign a real
157
192
  const el = document.querySelector('usgb-form')
158
193
  el.adapter = {
159
194
  host: 'wordpress',
160
- getTrackingHints() {
161
- // Cookies, UTMs, click ids — keys must match the package tracking registry
162
- return {}
163
- },
164
195
  async submit(payload) {
165
196
  const res = await fetch('/your-form-submit', {
166
197
  method: 'POST',
@@ -183,48 +214,71 @@ Submit is **not** an attribute. Markup alone uses a stub adapter. Assign a real
183
214
 
184
215
  ### Attribute map
185
216
 
186
- | Attribute | React prop |
187
- | ----------------------------------------------- | ------------------------------------------------------------- |
188
- | `form-id` | `formId` |
189
- | `appearance` | `appearance` |
190
- | `variant` | `variants` (space-separated) |
191
- | `heading` / `subheading` | `heading` / `subheading` |
192
- | `cta` | `ctaLabel` |
193
- | `source` / `campaign` | `source` / `campaign` |
194
- | `success-message` / `success-url` | `successMessage` / `successUrl` |
195
- | `client-agreement-url`, `privacy-policy-url`, … | `legalUrls.*` |
196
- | `host` | Used only for the stub adapter before you assign `el.adapter` |
217
+ `form-id` defaults to `magento-fik`, `appearance` to `on-light`, `variant` to `dense`, and `host` to `wordpress`. `two-column` is a boolean attribute and is off when omitted. There is no `version` attribute — `definitionVersion` comes from the catalog.
218
+
219
+ | Attribute | React prop |
220
+ | --------------------------- | ------------------------------------------------------------- |
221
+ | `form-id` | `formId` |
222
+ | `appearance` | `appearance` |
223
+ | `variant` | `variant` |
224
+ | `two-column` | `twoColumn` |
225
+ | `heading` / `subheading` | `heading` / `subheading` |
226
+ | `cta` | `ctaLabel` |
227
+ | `success-message` | `successMessage` |
228
+ | `success-url` | `successUrl` |
229
+ | `client-agreement-url` | `legalUrls.clientAgreement` |
230
+ | `privacy-policy-url` | `legalUrls.privacyPolicy` |
231
+ | `user-agreement-url` | `legalUrls.userAgreement` |
232
+ | `market-loss-policy-url` | `legalUrls.marketLossPolicy` |
233
+ | `electronic-disclaimer-url` | `legalUrls.electronicDisclaimer` |
234
+ | `terms-of-sale-url` | `legalUrls.termsOfSale` |
235
+ | `host` | Used only for the stub adapter before you assign `el.adapter` |
236
+
237
+ Same names are exported as `LEGAL_URL_ATTRS` (`legalUrls` key → attribute). Gutenberg and other generators should use that map instead of hard-coding strings.
238
+
239
+ ### Properties and events
240
+
241
+ | Surface | Role |
242
+ | ------------------- | --------------------------------------------------------------------------------------- |
243
+ | `el.adapter` | Assign a `HostAdapter`. Not an attribute. Markup without this uses `createStubAdapter`. |
244
+ | `usgb-form:success` | `e.detail` is `SubmissionPayload` (same as React `onAccepted`) |
245
+ | `usgb-form:failure` | `e.detail` is `{ payload, message }` (same as React `onFailed`) |
246
+
247
+ The Web Component does not expose `analytics` or `className`. Listen for the events above, or wrap the element for layout.
197
248
 
198
249
  ## Host adapter
199
250
 
200
251
  ```ts
201
252
  interface HostAdapter {
202
253
  host: 'pwa' | 'wordpress'
203
- getTrackingHints(): Partial<Record<TrackingKey, string | undefined>>
204
254
  submit(payload: SubmissionPayload): Promise<SubmitResult>
205
255
  }
206
256
  ```
207
257
 
208
258
  - `submit` must return `{ status: 'accepted' }` or `{ status: 'failed', message?: string }`.
209
- - The package never embeds Workato, Magento, or WordPress endpoints.
210
- - `createStubAdapter('pwa' | 'wordpress')` accepts every payload (playground / markup-only WC).
211
- - Tracking keys and destination names live in `forms-manifest.json`. Hosts may supply values for registered keys; they must not invent new ones.
259
+ - The package does not choose a submit URL.
260
+ - `createStubAdapter('pwa' | 'wordpress')` accepts every payload (markup-only Web Component).
261
+ - Tracking, UTMs, page URL, referrer, and similar context are collected by the backend. This package does not send a `context` object.
212
262
 
213
263
  ### Payload shape (summary)
214
264
 
215
- Successful submits send a nested envelope: `formId`, `definitionVersion`, `submissionContractVersion`, `idempotencyKey`, `data` (field values), optional `consent`, and `context` (`host`, `source`, `campaign`, `page`, `tracking`). Exact field and tracking sets come from the form’s catalog entry.
265
+ Successful submits send `formId`, `definitionVersion`, `submissionContractVersion`, `idempotencyKey`, `data` (field values), and optional `consents` (grant booleans, opt-in dates, and `*_consent_language` strings). Exact field sets come from the form’s catalog entry.
216
266
 
217
267
  ## Consent and legal URLs
218
268
 
219
- Consent bundles are versioned and package-owned (checkboxes and/or clickwrap notices). Hosts only supply document **hrefs**.
220
-
221
- - `main-investors-kit` uses `lead-tcpa` v1 and requires `clientAgreement` and `privacyPolicy`.
222
- - PWA Magento defaults: `PWA_LEGAL_URLS` → `/content/client-agreement`, `/content/privacy-policy`.
223
- - WordPress must pass every URL required by the selected consent. A consent form with a missing required URL **does not render**.
224
- - Checkbox values land in `consent.values` (and mirrored in `data`). Notices have no boolean field; the payload still records consent definition id/version.
225
- - Distinct legal wording requires a new consent id/version in this package — not freeform copy from the host.
269
+ Consent policies are versioned and package-owned (checkboxes and/or clickwrap notices). Forms list zero or more pins (`definitionId` + `definitionVersion` + optional `required` for checkboxes). Hosts only supply document **hrefs**.
226
270
 
227
- `LEAD_CLICKWRAP_V1` (“By clicking the button…”) is in the catalog and needs five legal URLs (`privacyPolicy`, `userAgreement`, `marketLossPolicy`, `electronicDisclaimer`, `termsOfSale`). It is not attached to a `formId` until that recipe is chosen.
271
+ - `magento-fik` pins `lead-tcpa`, `lead-sms`, and `lead-tospp` (all v1, optional checkboxes). Required URLs: `userAgreement`, `privacyPolicy` (`user-agreement-url`, `privacy-policy-url`).
272
+ - `magento-ira-kick-article` and `magento-fik-blog-rail` pin `lead-tcpa` v2 only (optional checkbox). Unlike v1, v2 links the terms and privacy policy, so required URLs: `userAgreement`, `privacyPolicy`.
273
+ - `main-investors-kit-notice` pins `lead-clickwrap` v2 (notice only: Privacy Policy, Terms & Conditions, and text/call consent). Required URLs: `privacyPolicy`, `userAgreement`. It shares the v1 payload key `clickwrap_consent_language`. `lead-clickwrap` v1 (five document links) stays in the catalog and is not pinned.
274
+ - `newsletter` has no consents and needs no legal URLs.
275
+ - `LEGAL_URL_ATTRS` lists every host-owned slot, including `clientAgreement` / `client-agreement-url`. No current catalog consent requires `clientAgreement`; it is still valid on `legalUrls` / the attribute (PWA Magento ships it in `PWA_LEGAL_URLS`).
276
+ - PWA Magento defaults (`PWA_LEGAL_URLS`): `/content/client-agreement`, `/content/privacy-policy`, `/content/user-agreement`, `/content/market-loss-policy`, `/content/electronic-disclaimer`, `/content/terms-of-sale`.
277
+ - WordPress must pass every URL required by the selected consents. A form with a missing required URL **does not render**. CMS pickers can compute the list with `getFormDefinition`, `resolveFormConsents`, and `collectRequiredLegalUrls`, then map keys through `LEGAL_URL_ATTRS`.
278
+ - `isCompleteLegalUrls(legalUrls, requiredKeys)` is the same check the renderer uses.
279
+ - Checkbox grants land in `consents` only (`tcpa_form_consent_granted`, `sms_form_consent_granted`, `tospp_form_consent_granted`). The exact copy shown is `tcpa_consent_language` (and the matching keys for other policies), even when unchecked.
280
+ - Checking the TCPA box also adds `tcpa_form_opt_in_date` (YYYY-MM-DD). The notice form only sends `clickwrap_consent_language`.
281
+ - Hosts supply document hrefs only. Consent wording stays in this package.
228
282
 
229
283
  ## Success behavior
230
284
 
@@ -280,25 +334,6 @@ Appearance never paints a card. Put the form on a dark host surface and pass `ap
280
334
 
281
335
  ```html
282
336
  <div style="background: #001f3d; padding: 2rem; border-radius: 0.75rem">
283
- <usgb-form form-id="main-investors-kit" appearance="on-dark" …></usgb-form>
337
+ <usgb-form form-id="magento-fik" appearance="on-dark" …></usgb-form>
284
338
  </div>
285
339
  ```
286
-
287
- Visual styles are a ported snapshot of the PWA form kit. When PWA form styles change, update this package and bump the version.
288
-
289
- ## Develop (package maintainers)
290
-
291
- ```bash
292
- yarn install
293
- yarn dev # Vite playground (tries :5174)
294
- yarn build
295
- yarn typecheck
296
- yarn lint
297
- yarn format
298
- ```
299
-
300
- Prettier and ESLint match magento-frontend (4-space indent, single quotes, no semicolons, print width 80).
301
-
302
- ## Git
303
-
304
- Local repo only. Connect a GitHub remote later when ready to publish.