@tesouro/embedded-components-react 0.2.270 → 0.2.272

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/README.md CHANGED
@@ -186,13 +186,13 @@ listed here.
186
186
 
187
187
  ### AcceptDisclosuresWidget
188
188
 
189
- A self-contained widget for reviewing and accepting required banking disclosures. Renders an inline bordered card with disclosure links, an agreement checkbox, and an Accept action. You supply the four bank-issued document URLs via `disclosureLinks`; the provider attribution and agreement copy come from the widget init tenant identity.
189
+ A self-contained widget for reviewing and accepting required banking disclosures. Fetches the caller's disclosure document set (title/url pairs, in presentation order) from `GET /identity/v1/disclosures` and renders an inline bordered card with those links, an agreement checkbox, and an Accept action. The host supplies no document URLs — the document set, its titles, and its order are entirely backend configuration for the bank partner's program. The provider attribution and agreement copy come from the widget init tenant identity.
190
190
 
191
191
  **Two flows, one surface.** In the **pre-auth invite flow**, pass `invitationToken` and `userId` from the invite link. For an **already-active user who owes a re-acceptance** — a new disclosure version was published, so widget init reports `disclosuresRequired: 'REQUIRED'` with `disclosuresAccepted: false` — pass neither: they hold no invite, and the widget token identifies them on both calls. Read those two init fields rather than `status` to decide whether to mount this widget, because an active user can owe an acceptance while never being invited again.
192
192
 
193
- Accept posts `POST /api/widget-gateway/disclosure-acceptance` after reading the disclosure version in force from `GET /identity/v1/disclosures` (hosts rewrite that onto `/api/widget-gateway/proxy/identity/v1/disclosures` the same way as other identity calls — do not call the generated catch-all proxy helper, which percent-encodes path slashes and surfaces as a browser CORS error). `version` may be `null` when the org's requirement is `NOT_REQUIRED`; that value is posted through and ignored by the gateway so invitees in those orgs can still activate. When you pass the invite credential, the disclosures lookup can reject a revoked/expired invite before activation. The accept is one transaction: it activates the invitee and records disclosure acceptance together, so a failed second hop cannot leave an `ACTIVE` user with no acceptance on record. After accept succeeds, the widget awaits any async `onAccepted` continuation, then kicks a widget-init refresh so host gates keyed on `INVITED` — or on the disclosure flags — can clear. Accept and `onAccepted` failures are handled separately — a rejected host continuation does not look like (or re-run) a failed gateway accept. The refresh is fire-and-forget and runs only after `onAccepted` settles — hosts that unmount this widget when status leaves `INVITED` would otherwise hide a rejected continuation. Auth uses the normal `widgetToken` provider contract — **never** pass an application (APP) / M2M bearer as `widgetToken`. In the invite flow, the host passes `invitationToken` and `userId` from the invite link; this widget does not read URL search params.
193
+ Accept posts `POST /api/widget-gateway/disclosure-acceptance` with the version that was on screen, after a second `GET /identity/v1/disclosures` confirms that version is still in force (hosts rewrite that onto `/api/widget-gateway/proxy/identity/v1/disclosures` the same way as other identity calls — do not call the generated catch-all proxy helper, which percent-encodes path slashes and surfaces as a browser CORS error). If a newer version was published while the caller was reading, accept is refused (no POST) and the widget refetches so they can review the documents that are now in force. `version` may be `null` when the org's requirement is `NOT_REQUIRED`; that value is posted through and ignored by the gateway so invitees in those orgs can still activate. When you pass the invite credential, the disclosures lookup can reject a revoked/expired invite before activation. The accept is one transaction: it activates the invitee and records disclosure acceptance together, so a failed second hop cannot leave an `ACTIVE` user with no acceptance on record. After accept succeeds, the widget awaits any async `onAccepted` continuation, then kicks a widget-init refresh so host gates keyed on `INVITED` — or on the disclosure flags — can clear. Accept and `onAccepted` failures are handled separately — a rejected host continuation does not look like (or re-run) a failed gateway accept. The refresh is fire-and-forget and runs only after `onAccepted` settles — hosts that unmount this widget when status leaves `INVITED` would otherwise hide a rejected continuation. Auth uses the normal `widgetToken` provider contract — **never** pass an application (APP) / M2M bearer as `widgetToken`. In the invite flow, the host passes `invitationToken` and `userId` from the invite link; this widget does not read URL search params.
194
194
 
195
- The widget carries no document URLs of its own — disclosures are bank-issued legal instruments whose hosting is yours to control, and an embeddable library must not depend on infrastructure your content-security policy cannot see. It renders nothing until `disclosureLinks` is supplied and init resolves a `bankName`; it never substitutes another tenant's legal copy. If init omits `vspName`, provider attribution falls back to the bank name so the sentence remains complete.
195
+ A failed disclosures fetch renders an error surface with retry instead of a blank INVITED screen. The widget otherwise renders nothing until the disclosures fetch resolves **and** init resolves a `bankName` — it never substitutes another tenant's legal copy, and never falls back to a Tesouro-hosted document (a published embeddable library must not depend on infrastructure a consumer's content-security policy cannot see). An empty document list (`requirement: NOT_REQUIRED`, `version: null`) is a resolved payload, not missing data: the widget still renders Accept so those invitees can activate. Agreement copy names the returned document titles, in backend order, so the sentence cannot list instruments the links do not show. If init omits `vspName`, provider attribution falls back to the bank name so the sentence remains complete.
196
196
 
197
197
  Once the atomic accept _and_ any async `onAccepted` continuation succeed, the checkbox and Accept control stay disabled, so a legal acceptance is never posted twice even if the host does not navigate away. A failed accept or rejected `onAccepted` shows an inline error and leaves the control usable for a retry; a successful accept is skipped on retry after a later failure. Init refresh is kicked only after `onAccepted` succeeds.
198
198
 
@@ -203,11 +203,11 @@ Once the atomic accept _and_ any async `onAccepted` continuation succeed, the ch
203
203
  | `invitationToken` | `string` | `undefined` | Invitation token from the invite link (`code` query param). Bound into the disclosures lookup before activation. |
204
204
  | `userId` | `string` | `undefined` | Invited user id from the invite link (`userId` query param). Paired with `invitationToken`. |
205
205
 
206
- | Prop | Type | Default | Description |
207
- | ----------------- | ---------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
208
- | `disclosureLinks` | `AcceptDisclosuresLinks` | — | URLs of the four disclosure documents. Required to render — the widget ships none of its own. |
209
- | `labels` | `Partial<AcceptDisclosuresWidgetLabels>` | — | Override shell copy (title, Accept, link labels, attribution/agreement templates). |
210
- | `onAccepted` | `() => void \| Promise<void>` | — | Called after the atomic accept succeeds and before init refresh; awaited before the widget locks. Reject to surface an error and keep Accept retryable. |
206
+ | Prop | Type | Default | Description |
207
+ | ----------------- | ---------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
208
+ | `labels` | `Partial<AcceptDisclosuresWidgetLabels>` | — | Override shell copy (title, Accept, agreement/attribution templates). `{documents}` in `agreementTextTemplate` is replaced with the backend-returned titles; a template that omits `{documents}` still has those titles appended. When the backend returns no documents, `noDocumentsTitle` / `noDocumentsAgreementTextTemplate` / `noDocumentsAgreementCheckboxAriaLabel` replace the disclosures copy (including the checkbox `aria-label`). Document titles themselves are not overridable. |
209
+ | `onAccepted` | `() => void \| Promise<void>` | — | Called after the atomic accept succeeds and before init refresh; awaited before the widget locks. Reject to surface an error and keep Accept retryable. |
210
+ | `disclosureLinks` | `AcceptDisclosuresLinks` | — | **Deprecated.** Ignored. Documents come from `GET /identity/v1/disclosures`. Kept so existing hosts continue to typecheck until a breaking release. |
211
211
 
212
212
  ### BankAccountsWidget
213
213
 
@@ -619,23 +619,6 @@ interface WidgetProviderProps extends WidgetProviderBaseProps {
619
619
  onError?: (error: unknown, info: ErrorInfo) => void;
620
620
  }
621
621
 
622
- /**
623
- * The four disclosure documents a host supplies. Keyed rather than a free-form
624
- * array because `agreementTextTemplate` names exactly these four instruments —
625
- * an arbitrary-length list would let the rendered links and the text the user
626
- * agrees to disagree with each other.
627
- *
628
- * URLs are host-supplied on purpose: they are bank-issued legal documents whose
629
- * hosting is the integrator's concern, and a published package must not carry a
630
- * Tesouro infrastructure URL a consumer's CSP can block (PLAT-1179).
631
- */
632
- interface AcceptDisclosuresLinks {
633
- termsOfUseUrl: string;
634
- privacyPolicyUrl: string;
635
- electronicCommunicationsAgreementUrl: string;
636
- usaPatriotActUrl: string;
637
- }
638
-
639
622
  /**
640
623
  * The sections the suite can offer, declared in the default menu order
641
624
  * (EMBD-4875). Order here is documentation only — the suite renders whatever
@@ -741,14 +724,6 @@ interface WidgetSuiteDisclosureLabels {
741
724
  body: string;
742
725
  retryButton: string;
743
726
  };
744
- /**
745
- * Acceptance is owed and the host supplied no documents to accept. A host
746
- * misconfiguration, so it names no cause the user could act on.
747
- */
748
- unavailableState: {
749
- title: string;
750
- body: string;
751
- };
752
727
  }
753
728
  /** Named as the shipped white-label header names them. */
754
729
  declare const WIDGET_SUITE_SECTION_LABELS_EN: WidgetSuiteSectionLabels;
@@ -770,21 +745,6 @@ interface WidgetSuiteProps extends WidgetProviderProps {
770
745
  * this is the host's ceiling rather than a promise of what renders.
771
746
  */
772
747
  sections: readonly WidgetSuiteSectionId[];
773
- /**
774
- * URLs of the bank-issued disclosure documents, for the acceptance state.
775
- *
776
- * Required only to *render* that state, and only reached when the session owes
777
- * an acceptance — an organization whose requirement is `NOT_REQUIRED` never
778
- * needs this. Host-supplied for the same reason `AcceptDisclosuresWidget` takes
779
- * them: they are bank-issued legal instruments whose hosting is the
780
- * integrator's to control, and a published package must not carry a URL a
781
- * consumer's content-security policy can block (PLAT-1179).
782
- *
783
- * A session that owes an acceptance with none of these supplied gets the
784
- * unavailable notice, not the suite — the gate is never dropped because the
785
- * host under-configured it.
786
- */
787
- disclosureLinks?: AcceptDisclosuresLinks;
788
748
  /** Overrides for the shell's own copy — the nav landmark name, empty state. */
789
749
  labels?: PartialDeep<WidgetSuiteShellLabels>;
790
750
  /** Overrides for the section names in the menu. */
@@ -800,8 +760,8 @@ interface WidgetSuiteProps extends WidgetProviderProps {
800
760
  */
801
761
  contentLabels?: PartialDeep<WidgetSuiteContentLabels>;
802
762
  /**
803
- * Overrides for the copy the disclosure gate owns: its refresh-failure recovery
804
- * and its unavailable notice. The acceptance surface carries its own labels.
763
+ * Overrides for the copy the disclosure gate owns: its init-failure and
764
+ * refresh-failure recovery. The acceptance surface carries its own labels.
805
765
  */
806
766
  disclosureLabels?: PartialDeep<WidgetSuiteDisclosureLabels>;
807
767
  /**
@@ -844,4 +804,4 @@ interface WidgetSuiteProps extends WidgetProviderProps {
844
804
  declare function WidgetSuite({ baseUrl, widgetToken, organizationId, configClient, gatewayRouting, linkComponent, implementation, uiFramework, errorFallback, onError, analytics, ...innerProps }: WidgetSuiteProps): React.JSX.Element;
845
805
 
846
806
  export { WIDGET_SUITE_CONTENT_LABELS_EN, WIDGET_SUITE_DEFAULT_SECTIONS, WIDGET_SUITE_DISCLOSURE_LABELS_EN, WIDGET_SUITE_SECTION_LABELS_EN, WIDGET_SUITE_SECTION_TITLE_LABELS_EN, WIDGET_SUITE_SHELL_LABELS_EN, WidgetSuite, WidgetSuiteSectionId };
847
- export type { AcceptDisclosuresLinks, PartialDeep, WidgetSuiteContentLabels, WidgetSuiteDisclosureLabels, WidgetSuiteProps, WidgetSuiteSectionLabels, WidgetSuiteSectionTitleLabels, WidgetSuiteShellLabels };
807
+ export type { PartialDeep, WidgetSuiteContentLabels, WidgetSuiteDisclosureLabels, WidgetSuiteProps, WidgetSuiteSectionLabels, WidgetSuiteSectionTitleLabels, WidgetSuiteShellLabels };
@@ -619,23 +619,6 @@ interface WidgetProviderProps extends WidgetProviderBaseProps {
619
619
  onError?: (error: unknown, info: ErrorInfo) => void;
620
620
  }
621
621
 
622
- /**
623
- * The four disclosure documents a host supplies. Keyed rather than a free-form
624
- * array because `agreementTextTemplate` names exactly these four instruments —
625
- * an arbitrary-length list would let the rendered links and the text the user
626
- * agrees to disagree with each other.
627
- *
628
- * URLs are host-supplied on purpose: they are bank-issued legal documents whose
629
- * hosting is the integrator's concern, and a published package must not carry a
630
- * Tesouro infrastructure URL a consumer's CSP can block (PLAT-1179).
631
- */
632
- interface AcceptDisclosuresLinks {
633
- termsOfUseUrl: string;
634
- privacyPolicyUrl: string;
635
- electronicCommunicationsAgreementUrl: string;
636
- usaPatriotActUrl: string;
637
- }
638
-
639
622
  /**
640
623
  * The sections the suite can offer, declared in the default menu order
641
624
  * (EMBD-4875). Order here is documentation only — the suite renders whatever
@@ -741,14 +724,6 @@ interface WidgetSuiteDisclosureLabels {
741
724
  body: string;
742
725
  retryButton: string;
743
726
  };
744
- /**
745
- * Acceptance is owed and the host supplied no documents to accept. A host
746
- * misconfiguration, so it names no cause the user could act on.
747
- */
748
- unavailableState: {
749
- title: string;
750
- body: string;
751
- };
752
727
  }
753
728
  /** Named as the shipped white-label header names them. */
754
729
  declare const WIDGET_SUITE_SECTION_LABELS_EN: WidgetSuiteSectionLabels;
@@ -770,21 +745,6 @@ interface WidgetSuiteProps extends WidgetProviderProps {
770
745
  * this is the host's ceiling rather than a promise of what renders.
771
746
  */
772
747
  sections: readonly WidgetSuiteSectionId[];
773
- /**
774
- * URLs of the bank-issued disclosure documents, for the acceptance state.
775
- *
776
- * Required only to *render* that state, and only reached when the session owes
777
- * an acceptance — an organization whose requirement is `NOT_REQUIRED` never
778
- * needs this. Host-supplied for the same reason `AcceptDisclosuresWidget` takes
779
- * them: they are bank-issued legal instruments whose hosting is the
780
- * integrator's to control, and a published package must not carry a URL a
781
- * consumer's content-security policy can block (PLAT-1179).
782
- *
783
- * A session that owes an acceptance with none of these supplied gets the
784
- * unavailable notice, not the suite — the gate is never dropped because the
785
- * host under-configured it.
786
- */
787
- disclosureLinks?: AcceptDisclosuresLinks;
788
748
  /** Overrides for the shell's own copy — the nav landmark name, empty state. */
789
749
  labels?: PartialDeep<WidgetSuiteShellLabels>;
790
750
  /** Overrides for the section names in the menu. */
@@ -800,8 +760,8 @@ interface WidgetSuiteProps extends WidgetProviderProps {
800
760
  */
801
761
  contentLabels?: PartialDeep<WidgetSuiteContentLabels>;
802
762
  /**
803
- * Overrides for the copy the disclosure gate owns: its refresh-failure recovery
804
- * and its unavailable notice. The acceptance surface carries its own labels.
763
+ * Overrides for the copy the disclosure gate owns: its init-failure and
764
+ * refresh-failure recovery. The acceptance surface carries its own labels.
805
765
  */
806
766
  disclosureLabels?: PartialDeep<WidgetSuiteDisclosureLabels>;
807
767
  /**
@@ -844,4 +804,4 @@ interface WidgetSuiteProps extends WidgetProviderProps {
844
804
  declare function WidgetSuite({ baseUrl, widgetToken, organizationId, configClient, gatewayRouting, linkComponent, implementation, uiFramework, errorFallback, onError, analytics, ...innerProps }: WidgetSuiteProps): React.JSX.Element;
845
805
 
846
806
  export { WIDGET_SUITE_CONTENT_LABELS_EN, WIDGET_SUITE_DEFAULT_SECTIONS, WIDGET_SUITE_DISCLOSURE_LABELS_EN, WIDGET_SUITE_SECTION_LABELS_EN, WIDGET_SUITE_SECTION_TITLE_LABELS_EN, WIDGET_SUITE_SHELL_LABELS_EN, WidgetSuite, WidgetSuiteSectionId };
847
- export type { AcceptDisclosuresLinks, PartialDeep, WidgetSuiteContentLabels, WidgetSuiteDisclosureLabels, WidgetSuiteProps, WidgetSuiteSectionLabels, WidgetSuiteSectionTitleLabels, WidgetSuiteShellLabels };
807
+ export type { PartialDeep, WidgetSuiteContentLabels, WidgetSuiteDisclosureLabels, WidgetSuiteProps, WidgetSuiteSectionLabels, WidgetSuiteSectionTitleLabels, WidgetSuiteShellLabels };
package/dist/index.d.ts CHANGED
@@ -12,19 +12,82 @@ interface AcceptDisclosuresWidgetLabels {
12
12
  agreementCheckboxAriaLabel: string;
13
13
  /** Fallback when the accept API fails without a usable message. */
14
14
  acceptErrorFallback: string;
15
- /** Use `{bankName}` as the bank display-name placeholder. */
15
+ /**
16
+ * Use `{bankName}` for the bank display name and `{documents}` for the
17
+ * conjunction list of titles the backend returned (same order as the links).
18
+ * A legacy override that omits `{documents}` still has those titles appended
19
+ * so consent copy cannot disagree with the linked documents.
20
+ */
16
21
  agreementTextTemplate: string;
17
22
  providerAttributionPrefix: string;
18
23
  providerAttributionMiddle: string;
19
24
  providerAttributionSuffix: string;
25
+ /**
26
+ * @deprecated Ignored. Document titles come from
27
+ * `GET /identity/v1/disclosures`. Kept so hosts that implement the full
28
+ * published `AcceptDisclosuresWidgetLabels` interface continue to typecheck.
29
+ */
20
30
  linkLabels: {
21
31
  termsOfUse: string;
22
32
  privacyPolicy: string;
23
33
  electronicCommunications: string;
24
34
  patriotAct: string;
25
35
  };
36
+ /** Title when the backend returned no documents (`NOT_REQUIRED`). */
37
+ noDocumentsTitle?: string;
38
+ /** Use `{bankName}` when the backend returned no documents. */
39
+ noDocumentsAgreementTextTemplate?: string;
40
+ /**
41
+ * Checkbox `aria-label` when the backend returned no documents. Use
42
+ * `{bankName}`. Must not say the user is agreeing to disclosures.
43
+ */
44
+ noDocumentsAgreementCheckboxAriaLabel?: string;
45
+ /**
46
+ * Two-item document list. Use `{first}` and `{second}` for the titles.
47
+ */
48
+ documentListPairTemplate?: string;
49
+ /** Separator between titles in a list of three or more (before the last). */
50
+ documentListSeparator?: string;
51
+ /** Conjunction before the last title in a list of three or more. */
52
+ documentListLastConjunction?: string;
53
+ /** Heading when the disclosures query fails. */
54
+ loadErrorTitle?: string;
55
+ /** Fallback when the disclosures query fails without a usable message. */
56
+ loadErrorFallback?: string;
57
+ /** Retry control on the disclosures-query error surface. */
58
+ loadErrorRetryLabel?: string;
59
+ /**
60
+ * Shown when accept is refused because a newer disclosure version is in
61
+ * force than the documents the invitee agreed to.
62
+ */
63
+ disclosuresUpdatedFallback?: string;
26
64
  }
27
- declare const ACCEPT_DISCLOSURES_WIDGET_LABELS_EN: AcceptDisclosuresWidgetLabels;
65
+ declare const ACCEPT_DISCLOSURES_WIDGET_LABELS_EN: {
66
+ title: string;
67
+ acceptButton: string;
68
+ agreementCheckboxAriaLabel: string;
69
+ acceptErrorFallback: string;
70
+ agreementTextTemplate: string;
71
+ providerAttributionPrefix: string;
72
+ providerAttributionMiddle: string;
73
+ providerAttributionSuffix: string;
74
+ linkLabels: {
75
+ termsOfUse: string;
76
+ privacyPolicy: string;
77
+ electronicCommunications: string;
78
+ patriotAct: string;
79
+ };
80
+ noDocumentsTitle: string;
81
+ noDocumentsAgreementTextTemplate: string;
82
+ noDocumentsAgreementCheckboxAriaLabel: string;
83
+ documentListPairTemplate: string;
84
+ documentListSeparator: string;
85
+ documentListLastConjunction: string;
86
+ loadErrorTitle: string;
87
+ loadErrorFallback: string;
88
+ loadErrorRetryLabel: string;
89
+ disclosuresUpdatedFallback: string;
90
+ };
28
91
 
29
92
  interface DisclosureLink {
30
93
  label: string;
@@ -1365,14 +1428,11 @@ type CardStatus = CreditCardStatus;
1365
1428
  type CardType = CreditCardType;
1366
1429
 
1367
1430
  /**
1368
- * The four disclosure documents a host supplies. Keyed rather than a free-form
1369
- * array because `agreementTextTemplate` names exactly these four instruments —
1370
- * an arbitrary-length list would let the rendered links and the text the user
1371
- * agrees to disagree with each other.
1431
+ * Host-supplied URLs for the four disclosure documents.
1372
1432
  *
1373
- * URLs are host-supplied on purpose: they are bank-issued legal documents whose
1374
- * hosting is the integrator's concern, and a published package must not carry a
1375
- * Tesouro infrastructure URL a consumer's CSP can block (PLAT-1179).
1433
+ * @deprecated The widget fetches title/url pairs from
1434
+ * `GET /identity/v1/disclosures`. This type remains exported so existing
1435
+ * consumers continue to typecheck until a coordinated breaking release.
1376
1436
  */
1377
1437
  interface AcceptDisclosuresLinks {
1378
1438
  termsOfUseUrl: string;
@@ -1400,13 +1460,6 @@ type InnerProps = Omit<AcceptDisclosuresWidgetProps$1, UiOwnedProps> & {
1400
1460
  * invite flow.
1401
1461
  */
1402
1462
  userId?: string;
1403
- /**
1404
- * URLs of the four bank-issued disclosure documents. Required to render along
1405
- * with a bank name from widget init: the widget carries no document URLs of its
1406
- * own and never invents a tenant's legal copy, so it renders nothing until the
1407
- * host supplies the document set.
1408
- */
1409
- disclosureLinks?: AcceptDisclosuresLinks;
1410
1463
  /**
1411
1464
  * Called after the atomic accept succeeds and before init refresh is kicked.
1412
1465
  * May return a promise — the widget awaits it before locking controls and
@@ -1414,22 +1467,35 @@ type InnerProps = Omit<AcceptDisclosuresWidgetProps$1, UiOwnedProps> & {
1414
1467
  * Accept retryable (and the host gate stays mounted).
1415
1468
  */
1416
1469
  onAccepted?: () => void | Promise<void>;
1470
+ /**
1471
+ * @deprecated Ignored. Documents come from `GET /identity/v1/disclosures`.
1472
+ * Kept so existing hosts that still pass this continue to typecheck until a
1473
+ * coordinated breaking release.
1474
+ */
1475
+ disclosureLinks?: AcceptDisclosuresLinks;
1417
1476
  };
1418
1477
  type AcceptDisclosuresWidgetProps = WidgetProviderProps & InnerProps;
1419
1478
  /**
1420
- * Self-contained AcceptDisclosures widget.
1421
- * Posts `POST /api/widget-gateway/disclosure-acceptance` (after reading the
1422
- * disclosure version in force via the widget-gateway proxy), which activates
1423
- * the invitee and records acceptance in one transaction, then awaits any
1424
- * `onAccepted` continuation and kicks a widget-init refresh so host gates
1425
- * keyed on `INVITED` can clear. Auth uses the normal WidgetToken provider
1426
- * contract — never an APP/M2M bearer.
1479
+ * Self-contained AcceptDisclosures widget. Fetches the caller's disclosure
1480
+ * document set (title/url pairs, in presentation order) from
1481
+ * `GET /identity/v1/disclosures` and renders it directly — the host supplies
1482
+ * no document URLs. An empty document list (`NOT_REQUIRED`) still renders
1483
+ * Accept so those invitees can activate. Posts
1484
+ * `POST /api/widget-gateway/disclosure-acceptance` with the version that was
1485
+ * on screen after confirming that version is still in force (and the invite
1486
+ * still valid, when one was supplied) via the widget-gateway proxy. A newer
1487
+ * published version is refused rather than accepted unseen. The POST
1488
+ * activates the invitee and records acceptance in one transaction, then
1489
+ * awaits any `onAccepted` continuation and kicks a widget-init refresh so
1490
+ * host gates keyed on `INVITED` — or on the disclosure flags — can clear.
1491
+ * Auth uses the normal WidgetToken provider contract — never an APP/M2M
1492
+ * bearer.
1427
1493
  *
1428
1494
  * Two flows, one surface: the pre-auth invite flow passes `invitationToken` +
1429
- * `userId`; an already-active user who owes a re-acceptance (widget init reports
1430
- * `disclosuresRequired: 'REQUIRED'` with `disclosuresAccepted: false`) passes
1431
- * neither, and the same init refresh clears the gate that mounted this. See
1432
- * `WidgetSuite`, which mounts it as its acceptance state.
1495
+ * `userId`; an already-active user who owes a re-acceptance (widget init
1496
+ * reports `disclosuresRequired: 'REQUIRED'` with `disclosuresAccepted: false`)
1497
+ * passes neither, and the same init refresh clears the gate that mounted this.
1498
+ * See `WidgetSuite`, which mounts it as its acceptance state.
1433
1499
  */
1434
1500
  declare function AcceptDisclosuresWidget({ baseUrl, widgetToken, organizationId, configClient, gatewayRouting, linkComponent, implementation, uiFramework, errorFallback, onError, analytics, ...innerProps }: AcceptDisclosuresWidgetProps): React.JSX.Element;
1435
1501
 
@@ -11,19 +11,82 @@ interface AcceptDisclosuresWidgetLabels {
11
11
  agreementCheckboxAriaLabel: string;
12
12
  /** Fallback when the accept API fails without a usable message. */
13
13
  acceptErrorFallback: string;
14
- /** Use `{bankName}` as the bank display-name placeholder. */
14
+ /**
15
+ * Use `{bankName}` for the bank display name and `{documents}` for the
16
+ * conjunction list of titles the backend returned (same order as the links).
17
+ * A legacy override that omits `{documents}` still has those titles appended
18
+ * so consent copy cannot disagree with the linked documents.
19
+ */
15
20
  agreementTextTemplate: string;
16
21
  providerAttributionPrefix: string;
17
22
  providerAttributionMiddle: string;
18
23
  providerAttributionSuffix: string;
24
+ /**
25
+ * @deprecated Ignored. Document titles come from
26
+ * `GET /identity/v1/disclosures`. Kept so hosts that implement the full
27
+ * published `AcceptDisclosuresWidgetLabels` interface continue to typecheck.
28
+ */
19
29
  linkLabels: {
20
30
  termsOfUse: string;
21
31
  privacyPolicy: string;
22
32
  electronicCommunications: string;
23
33
  patriotAct: string;
24
34
  };
35
+ /** Title when the backend returned no documents (`NOT_REQUIRED`). */
36
+ noDocumentsTitle?: string;
37
+ /** Use `{bankName}` when the backend returned no documents. */
38
+ noDocumentsAgreementTextTemplate?: string;
39
+ /**
40
+ * Checkbox `aria-label` when the backend returned no documents. Use
41
+ * `{bankName}`. Must not say the user is agreeing to disclosures.
42
+ */
43
+ noDocumentsAgreementCheckboxAriaLabel?: string;
44
+ /**
45
+ * Two-item document list. Use `{first}` and `{second}` for the titles.
46
+ */
47
+ documentListPairTemplate?: string;
48
+ /** Separator between titles in a list of three or more (before the last). */
49
+ documentListSeparator?: string;
50
+ /** Conjunction before the last title in a list of three or more. */
51
+ documentListLastConjunction?: string;
52
+ /** Heading when the disclosures query fails. */
53
+ loadErrorTitle?: string;
54
+ /** Fallback when the disclosures query fails without a usable message. */
55
+ loadErrorFallback?: string;
56
+ /** Retry control on the disclosures-query error surface. */
57
+ loadErrorRetryLabel?: string;
58
+ /**
59
+ * Shown when accept is refused because a newer disclosure version is in
60
+ * force than the documents the invitee agreed to.
61
+ */
62
+ disclosuresUpdatedFallback?: string;
25
63
  }
26
- declare const ACCEPT_DISCLOSURES_WIDGET_LABELS_EN: AcceptDisclosuresWidgetLabels;
64
+ declare const ACCEPT_DISCLOSURES_WIDGET_LABELS_EN: {
65
+ title: string;
66
+ acceptButton: string;
67
+ agreementCheckboxAriaLabel: string;
68
+ acceptErrorFallback: string;
69
+ agreementTextTemplate: string;
70
+ providerAttributionPrefix: string;
71
+ providerAttributionMiddle: string;
72
+ providerAttributionSuffix: string;
73
+ linkLabels: {
74
+ termsOfUse: string;
75
+ privacyPolicy: string;
76
+ electronicCommunications: string;
77
+ patriotAct: string;
78
+ };
79
+ noDocumentsTitle: string;
80
+ noDocumentsAgreementTextTemplate: string;
81
+ noDocumentsAgreementCheckboxAriaLabel: string;
82
+ documentListPairTemplate: string;
83
+ documentListSeparator: string;
84
+ documentListLastConjunction: string;
85
+ loadErrorTitle: string;
86
+ loadErrorFallback: string;
87
+ loadErrorRetryLabel: string;
88
+ disclosuresUpdatedFallback: string;
89
+ };
27
90
 
28
91
  interface DisclosureLink {
29
92
  label: string;
@@ -643,14 +706,11 @@ interface WidgetProviderProps extends WidgetProviderBaseProps {
643
706
  }
644
707
 
645
708
  /**
646
- * The four disclosure documents a host supplies. Keyed rather than a free-form
647
- * array because `agreementTextTemplate` names exactly these four instruments —
648
- * an arbitrary-length list would let the rendered links and the text the user
649
- * agrees to disagree with each other.
709
+ * Host-supplied URLs for the four disclosure documents.
650
710
  *
651
- * URLs are host-supplied on purpose: they are bank-issued legal documents whose
652
- * hosting is the integrator's concern, and a published package must not carry a
653
- * Tesouro infrastructure URL a consumer's CSP can block (PLAT-1179).
711
+ * @deprecated The widget fetches title/url pairs from
712
+ * `GET /identity/v1/disclosures`. This type remains exported so existing
713
+ * consumers continue to typecheck until a coordinated breaking release.
654
714
  */
655
715
  interface AcceptDisclosuresLinks {
656
716
  termsOfUseUrl: string;
@@ -678,13 +738,6 @@ type InnerProps = Omit<AcceptDisclosuresWidgetProps$1, UiOwnedProps> & {
678
738
  * invite flow.
679
739
  */
680
740
  userId?: string;
681
- /**
682
- * URLs of the four bank-issued disclosure documents. Required to render along
683
- * with a bank name from widget init: the widget carries no document URLs of its
684
- * own and never invents a tenant's legal copy, so it renders nothing until the
685
- * host supplies the document set.
686
- */
687
- disclosureLinks?: AcceptDisclosuresLinks;
688
741
  /**
689
742
  * Called after the atomic accept succeeds and before init refresh is kicked.
690
743
  * May return a promise — the widget awaits it before locking controls and
@@ -692,22 +745,35 @@ type InnerProps = Omit<AcceptDisclosuresWidgetProps$1, UiOwnedProps> & {
692
745
  * Accept retryable (and the host gate stays mounted).
693
746
  */
694
747
  onAccepted?: () => void | Promise<void>;
748
+ /**
749
+ * @deprecated Ignored. Documents come from `GET /identity/v1/disclosures`.
750
+ * Kept so existing hosts that still pass this continue to typecheck until a
751
+ * coordinated breaking release.
752
+ */
753
+ disclosureLinks?: AcceptDisclosuresLinks;
695
754
  };
696
755
  type AcceptDisclosuresWidgetProps = WidgetProviderProps & InnerProps;
697
756
  /**
698
- * Self-contained AcceptDisclosures widget.
699
- * Posts `POST /api/widget-gateway/disclosure-acceptance` (after reading the
700
- * disclosure version in force via the widget-gateway proxy), which activates
701
- * the invitee and records acceptance in one transaction, then awaits any
702
- * `onAccepted` continuation and kicks a widget-init refresh so host gates
703
- * keyed on `INVITED` can clear. Auth uses the normal WidgetToken provider
704
- * contract — never an APP/M2M bearer.
757
+ * Self-contained AcceptDisclosures widget. Fetches the caller's disclosure
758
+ * document set (title/url pairs, in presentation order) from
759
+ * `GET /identity/v1/disclosures` and renders it directly — the host supplies
760
+ * no document URLs. An empty document list (`NOT_REQUIRED`) still renders
761
+ * Accept so those invitees can activate. Posts
762
+ * `POST /api/widget-gateway/disclosure-acceptance` with the version that was
763
+ * on screen after confirming that version is still in force (and the invite
764
+ * still valid, when one was supplied) via the widget-gateway proxy. A newer
765
+ * published version is refused rather than accepted unseen. The POST
766
+ * activates the invitee and records acceptance in one transaction, then
767
+ * awaits any `onAccepted` continuation and kicks a widget-init refresh so
768
+ * host gates keyed on `INVITED` — or on the disclosure flags — can clear.
769
+ * Auth uses the normal WidgetToken provider contract — never an APP/M2M
770
+ * bearer.
705
771
  *
706
772
  * Two flows, one surface: the pre-auth invite flow passes `invitationToken` +
707
- * `userId`; an already-active user who owes a re-acceptance (widget init reports
708
- * `disclosuresRequired: 'REQUIRED'` with `disclosuresAccepted: false`) passes
709
- * neither, and the same init refresh clears the gate that mounted this. See
710
- * `WidgetSuite`, which mounts it as its acceptance state.
773
+ * `userId`; an already-active user who owes a re-acceptance (widget init
774
+ * reports `disclosuresRequired: 'REQUIRED'` with `disclosuresAccepted: false`)
775
+ * passes neither, and the same init refresh clears the gate that mounted this.
776
+ * See `WidgetSuite`, which mounts it as its acceptance state.
711
777
  */
712
778
  declare function AcceptDisclosuresWidget({ baseUrl, widgetToken, organizationId, configClient, gatewayRouting, linkComponent, implementation, uiFramework, errorFallback, onError, analytics, ...innerProps }: AcceptDisclosuresWidgetProps): React.JSX.Element;
713
779
 
@@ -1,2 +1,3 @@
1
1
  import { useAcceptWidgetDisclosures as e } from "./index2.js";
2
- export { e as useAcceptWidgetDisclosures };
2
+ import { useDisclosuresQuery as t } from "./index3.js";
3
+ export { e as useAcceptWidgetDisclosures, t as useDisclosuresQuery };
@@ -7,28 +7,34 @@ import { getDisclosures as t, postApiWidgetGatewayDisclosureAcceptance as n } fr
7
7
  import "../../../shared/data-access/dist/index.js";
8
8
  import { useMutation as r } from "@tanstack/react-query";
9
9
  //#region ../../libs/tesouro-embedded-components-react/accept-disclosures-widget/data-access/dist/index2.js
10
- function i() {
11
- let { client: i, widgetToken: a } = e();
12
- return r({ mutationFn: async ({ invitationToken: e, userId: r } = {}) => {
13
- if (!a) throw Error("Widget token is required to accept disclosures");
14
- let { data: o } = await t({
15
- client: i,
16
- headers: { "X-Widget-Token": a },
10
+ var i = class extends Error {
11
+ constructor() {
12
+ super("Displayed disclosure version is no longer in force"), this.name = "DisclosuresVersionChangedError";
13
+ }
14
+ };
15
+ function a() {
16
+ let { client: a, widgetToken: o } = e();
17
+ return r({ mutationFn: async ({ invitationToken: e, userId: r, displayedVersion: s }) => {
18
+ if (!o) throw Error("Widget token is required to accept disclosures");
19
+ let { data: c } = await t({
20
+ client: a,
21
+ headers: { "X-Widget-Token": o },
17
22
  ...e && r ? { query: {
18
23
  invitationToken: e,
19
24
  userId: r
20
25
  } } : {},
21
26
  throwOnError: !0
22
27
  });
23
- if (!o) throw Error("Unexpected disclosures response from widget gateway");
24
- let { data: s } = await n({
25
- client: i,
26
- headers: { "X-Widget-Token": a },
27
- body: { version: o.version },
28
+ if (!c) throw Error("Unexpected disclosures response from widget gateway");
29
+ if (c.version !== s) throw new i();
30
+ let { data: l } = await n({
31
+ client: a,
32
+ headers: { "X-Widget-Token": o },
33
+ body: { version: s },
28
34
  throwOnError: !0
29
35
  });
30
- return s;
36
+ return l;
31
37
  } });
32
38
  }
33
39
  //#endregion
34
- export { i as useAcceptWidgetDisclosures };
40
+ export { i as DisclosuresVersionChangedError, a as useAcceptWidgetDisclosures };
@@ -0,0 +1,58 @@
1
+ "use client";
2
+ "use client";
3
+ "use client";
4
+ "use client";
5
+ import { useEmbedApi as e } from "../../../shared/data-access/dist/lib/EmbedApiContext.js";
6
+ import { getDisclosures as t } from "../../../shared/data-access/dist/lib/rest/sdk.gen.js";
7
+ import { withAuthEpoch as n } from "../../../shared/data-access/dist/lib/withAuthEpoch.js";
8
+ import "../../../shared/data-access/dist/index.js";
9
+ import { useQuery as r } from "@tanstack/react-query";
10
+ //#region ../../libs/tesouro-embedded-components-react/accept-disclosures-widget/data-access/dist/index3.js
11
+ function i(e) {
12
+ let t = 2166136261;
13
+ for (let n = 0; n < e.length; n += 1) t ^= e.charCodeAt(n), t = Math.imul(t, 16777619);
14
+ return (t >>> 0).toString(16);
15
+ }
16
+ function a(e, t) {
17
+ return JSON.stringify(e.slice(0, -1)) === JSON.stringify(t);
18
+ }
19
+ var o = [];
20
+ function s(e, t) {
21
+ if (e !== void 0 && t !== void 0 && a(t.queryKey, o)) return e;
22
+ }
23
+ function c({ invitationToken: a, userId: c, enabled: l } = {}) {
24
+ let { client: u, widgetToken: d, authEpoch: f } = e(), p = a && c ? {
25
+ invitationToken: a,
26
+ userId: c
27
+ } : void 0, m = async ({ signal: e }) => {
28
+ let { data: n } = await t({
29
+ client: u,
30
+ headers: { "X-Widget-Token": d ?? "" },
31
+ ...p ? { query: p } : {},
32
+ signal: e,
33
+ throwOnError: !0
34
+ });
35
+ if (!n) throw Error("Unexpected disclosures response from widget gateway");
36
+ return n;
37
+ }, h = ["getDisclosures", {
38
+ baseUrl: u.getConfig().baseUrl,
39
+ ...p ? {
40
+ userId: p.userId,
41
+ invitationTokenFingerprint: i(p.invitationToken)
42
+ } : {}
43
+ }];
44
+ o = h;
45
+ let { queryKey: g } = n({
46
+ queryKey: h,
47
+ queryFn: m,
48
+ placeholderData: void 0
49
+ }, f);
50
+ return r({
51
+ queryKey: g,
52
+ queryFn: m,
53
+ placeholderData: s,
54
+ enabled: !!d && (l === !0 || l === void 0)
55
+ });
56
+ }
57
+ //#endregion
58
+ export { c as useDisclosuresQuery };
@@ -1,43 +1,29 @@
1
- import { ACCEPT_DISCLOSURES_WIDGET_LABELS_EN as e } from "../../ui/dist/lib/AcceptDisclosuresWidget/labels.js";
1
+ import { mergeAcceptDisclosuresWidgetLabels as e } from "../../ui/dist/lib/AcceptDisclosuresWidget/labels.js";
2
2
  import "../../ui/dist/index.js";
3
3
  //#region ../../libs/tesouro-embedded-components-react/accept-disclosures-widget/feature/dist/index3.js
4
- function t(t) {
5
- return {
6
- ...e,
7
- ...t,
8
- linkLabels: {
9
- ...e.linkLabels,
10
- ...t?.linkLabels
11
- }
12
- };
4
+ function t(e, t) {
5
+ return e.length === 0 ? "" : e.length === 1 ? e[0] ?? "" : e.length === 2 ? t.documentListPairTemplate.replaceAll("{first}", e[0] ?? "").replaceAll("{second}", e[1] ?? "") : `${e.slice(0, -1).join(t.documentListSeparator)}${t.documentListLastConjunction}${e[e.length - 1]}`;
6
+ }
7
+ var n = "{documents}";
8
+ function r(e, r, i, a) {
9
+ let o = t(i, a), s = e.replaceAll("{bankName}", r);
10
+ return e.includes(n) ? s.replaceAll(n, o) : i.length === 0 ? s : `${s.trimEnd().replace(/\.$/, "")}. ${o}.`;
13
11
  }
14
- function n(e) {
15
- let n = e?.disclosureLinks, r = e?.vspName?.trim() ?? "", i = e?.bankName?.trim() ?? "";
16
- if (!n || !i) return null;
17
- let a = t(e?.labels), o = a.linkLabels;
12
+ function i(t) {
13
+ let n = t?.documents, i = t?.vspName?.trim() ?? "", a = t?.bankName?.trim() ?? "";
14
+ if (n === void 0 || !a) return null;
15
+ let o = e(t?.labels), s = n.map((e) => e.title), c = s.length > 0, l = c ? r(o.agreementTextTemplate, a, s, o) : o.noDocumentsAgreementTextTemplate.replaceAll("{bankName}", a);
18
16
  return {
19
- vspName: r || i,
20
- bankName: i,
21
- disclosureLinks: [
22
- {
23
- label: o.termsOfUse,
24
- href: n.termsOfUseUrl
25
- },
26
- {
27
- label: o.privacyPolicy,
28
- href: n.privacyPolicyUrl
29
- },
30
- {
31
- label: o.electronicCommunications,
32
- href: n.electronicCommunicationsAgreementUrl
33
- },
34
- {
35
- label: o.patriotAct,
36
- href: n.usaPatriotActUrl
37
- }
38
- ],
39
- agreementText: a.agreementTextTemplate.replaceAll("{bankName}", i)
17
+ vspName: i || a,
18
+ bankName: a,
19
+ title: c ? o.title : o.noDocumentsTitle,
20
+ disclosureLinks: n.map((e) => ({
21
+ label: e.title,
22
+ href: e.url
23
+ })),
24
+ agreementText: l,
25
+ agreementCheckboxAriaLabel: c ? o.agreementCheckboxAriaLabel : o.noDocumentsAgreementCheckboxAriaLabel.replaceAll("{bankName}", a)
40
26
  };
41
27
  }
42
28
  //#endregion
43
- export { n as resolveAcceptDisclosuresContent };
29
+ export { i as resolveAcceptDisclosuresContent };
@@ -3,118 +3,136 @@
3
3
  "use client";
4
4
  "use client";
5
5
  import { AcceptDisclosuresWidgetAnalyticsEvent as e, WIDGET_NAME as t } from "./index2.js";
6
- import { ACCEPT_DISCLOSURES_WIDGET_LABELS_EN as n } from "../../ui/dist/lib/AcceptDisclosuresWidget/labels.js";
6
+ import { mergeAcceptDisclosuresWidgetLabels as n } from "../../ui/dist/lib/AcceptDisclosuresWidget/labels.js";
7
7
  import { AcceptDisclosuresWidget as r } from "../../ui/dist/lib/AcceptDisclosuresWidget/AcceptDisclosuresWidget.js";
8
8
  import "../../ui/dist/index.js";
9
9
  import { resolveAcceptDisclosuresContent as i } from "./index3.js";
10
10
  import { useAcceptWidgetDisclosures as a } from "../../data-access/dist/index2.js";
11
+ import { useDisclosuresQuery as o } from "../../data-access/dist/index3.js";
11
12
  import "../../data-access/dist/index.js";
12
- import { useAnalyticsTrack as o } from "../../../shared/feature/dist/lib/analytics/hooks.js";
13
- import { WidgetProvider as s } from "../../../shared/feature/dist/lib/WidgetProvider/WidgetProvider.js";
14
- import { extractApiErrorMessage as c } from "../../../shared/util/dist/lib/apiErrors.js";
15
- import { useRefetchWidget as l, useWidgetConfig as u, useWidgetInitStaleForToken as d } from "../../../shared/feature/dist/lib/WidgetProvider/hooks.js";
13
+ import { ErrorState as s } from "../../../shared/ui/dist/lib/ErrorState/ErrorState.js";
14
+ import "../../../shared/ui/dist/index.js";
15
+ import { useAnalyticsTrack as c } from "../../../shared/feature/dist/lib/analytics/hooks.js";
16
+ import { WidgetProvider as l } from "../../../shared/feature/dist/lib/WidgetProvider/WidgetProvider.js";
17
+ import { extractApiErrorMessage as u } from "../../../shared/util/dist/lib/apiErrors.js";
18
+ import { useRefetchWidget as d, useWidgetConfig as f, useWidgetInitStaleForToken as p } from "../../../shared/feature/dist/lib/WidgetProvider/hooks.js";
16
19
  import "../../../shared/feature/dist/index.js";
17
- import { useCallback as f, useEffect as p, useRef as m, useState as h } from "react";
18
- import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
20
+ import { useCallback as m, useEffect as h, useRef as g, useState as _ } from "react";
21
+ import { Fragment as v, jsx as y, jsxs as b } from "react/jsx-runtime";
19
22
  //#region ../../libs/tesouro-embedded-components-react/accept-disclosures-widget/feature/dist/index4.js
20
- function y(e) {
21
- return {
22
- ...n,
23
- ...e,
24
- linkLabels: {
25
- ...n.linkLabels,
26
- ...e?.linkLabels
27
- }
28
- };
29
- }
30
- function b(e, t, n) {
31
- return /* @__PURE__ */ v(g, { children: [
23
+ function x(e, t, n) {
24
+ return /* @__PURE__ */ b(v, { children: [
32
25
  n.providerAttributionPrefix,
33
- /* @__PURE__ */ _("strong", { children: e }),
26
+ /* @__PURE__ */ y("strong", { children: e }),
34
27
  n.providerAttributionMiddle,
35
28
  t,
36
29
  n.providerAttributionSuffix
37
30
  ] });
38
31
  }
39
- function x({ invitationToken: t, userId: n, disclosureLinks: r, labels: a, onAccepted: s }) {
40
- let c = o(), { initResponse: l } = u(), f = d(), m = y(a);
41
- p(() => {
42
- c(e.Mounted);
43
- }, [c]);
44
- let h = i({
45
- disclosureLinks: r,
46
- vspName: l?.vspName,
47
- bankName: l?.bankName,
32
+ function S({ invitationToken: t, userId: r, labels: a, onAccepted: l }) {
33
+ let d = c(), { initResponse: m } = f(), g = p(), _ = n(a), { data: v, isError: b, error: x, refetch: S } = o({
34
+ invitationToken: t,
35
+ userId: r
36
+ });
37
+ if (h(() => {
38
+ d(e.Mounted);
39
+ }, [d]), b) return /* @__PURE__ */ y(s, {
40
+ title: _.loadErrorTitle,
41
+ description: u(x) ?? _.loadErrorFallback,
42
+ retryLabel: _.loadErrorRetryLabel,
43
+ onRetry: () => {
44
+ S();
45
+ },
46
+ testId: "accept-disclosures-load-error"
47
+ });
48
+ let w = i({
49
+ documents: v?.documents,
50
+ vspName: m?.vspName,
51
+ bankName: m?.bankName,
48
52
  labels: a
49
53
  });
50
- if (!h) return null;
51
- let g = !!(t && n);
52
- if (!g && f) return null;
53
- let v = `${g ? `invite:${t}:${n}` : `user:${l?.userId ?? ""}`}:${h.vspName}:${h.bankName}:${h.agreementText}:${h.disclosureLinks.map((e) => e.href).join("|")}`;
54
- return /* @__PURE__ */ _(S, {
54
+ if (!w) return null;
55
+ let T = v?.version ?? null, E = !!(t && r);
56
+ if (!E && g) return null;
57
+ let D = `${E ? `invite:${t}:${r}` : `user:${m?.userId ?? ""}`}:${T}:${w.vspName}:${w.bankName}:${w.agreementText}:${w.disclosureLinks.map((e) => e.href).join("|")}`;
58
+ return /* @__PURE__ */ y(C, {
55
59
  invitationToken: t,
56
- userId: n,
60
+ userId: r,
61
+ displayedVersion: T,
57
62
  labelOverrides: a,
58
- content: h,
59
- labels: m,
60
- onAccepted: s
61
- }, v);
63
+ content: w,
64
+ labels: _,
65
+ onAccepted: l,
66
+ onDisclosuresVersionChanged: S
67
+ }, D);
62
68
  }
63
- function S({ invitationToken: e, userId: t, labelOverrides: n, content: i, labels: o, onAccepted: s }) {
64
- let [u, d] = h(!1), [p, g] = h(), [v, y] = h(!1), [x, S] = h(!1), C = m(!1), { mutateAsync: w } = a(), T = l(), E = f((e) => {
65
- g(void 0), d(e);
66
- }, []), D = f(async () => {
67
- if (!(!u || v || x)) {
68
- g(void 0), y(!0);
69
+ function C({ invitationToken: e, userId: t, displayedVersion: n, labelOverrides: i, content: o, labels: s, onAccepted: c, onDisclosuresVersionChanged: l }) {
70
+ let [f, p] = _(!1), [h, v] = _(), [b, S] = _(!1), [C, w] = _(!1), T = g(!1), { mutateAsync: E } = a(), D = d(), O = m((e) => {
71
+ v(void 0), p(e);
72
+ }, []), k = m(async () => {
73
+ if (!(!f || b || C)) {
74
+ v(void 0), S(!0);
69
75
  try {
70
- if (!C.current) try {
71
- await w({
76
+ if (!T.current) try {
77
+ await E({
72
78
  invitationToken: e,
73
- userId: t
74
- }), C.current = !0;
79
+ userId: t,
80
+ displayedVersion: n
81
+ }), T.current = !0;
75
82
  } catch (e) {
76
- g(c(e) ?? o.acceptErrorFallback);
83
+ if (e instanceof Error && e.name === "DisclosuresVersionChangedError") {
84
+ v(s.disclosuresUpdatedFallback), l();
85
+ return;
86
+ }
87
+ v(u(e) ?? s.acceptErrorFallback);
77
88
  return;
78
89
  }
79
90
  try {
80
- await s?.();
91
+ await c?.();
81
92
  } catch (e) {
82
- g(c(e) ?? o.acceptErrorFallback);
93
+ v(u(e) ?? s.acceptErrorFallback);
83
94
  return;
84
95
  }
85
- T(), S(!0);
96
+ D(), w(!0);
86
97
  } finally {
87
- y(!1);
98
+ S(!1);
88
99
  }
89
100
  }
90
101
  }, [
91
- w,
92
- x,
102
+ E,
103
+ n,
104
+ C,
93
105
  e,
94
- u,
95
- v,
96
- o.acceptErrorFallback,
97
- s,
98
- T,
106
+ f,
107
+ b,
108
+ s.acceptErrorFallback,
109
+ s.disclosuresUpdatedFallback,
110
+ c,
111
+ l,
112
+ D,
99
113
  t
100
114
  ]);
101
- return /* @__PURE__ */ _(r, {
102
- labels: n,
103
- providerAttribution: b(i.vspName, i.bankName, o),
104
- agreementText: i.agreementText,
105
- disclosureLinks: i.disclosureLinks,
106
- isAgreed: u,
107
- onAgreedChange: E,
115
+ return /* @__PURE__ */ y(r, {
116
+ labels: {
117
+ ...i,
118
+ title: o.title,
119
+ agreementCheckboxAriaLabel: o.agreementCheckboxAriaLabel
120
+ },
121
+ providerAttribution: x(o.vspName, o.bankName, s),
122
+ agreementText: o.agreementText,
123
+ disclosureLinks: o.disclosureLinks,
124
+ isAgreed: f,
125
+ onAgreedChange: O,
108
126
  onAccept: () => {
109
- D();
127
+ k();
110
128
  },
111
- isSubmitting: v,
112
- isAccepted: x,
113
- errorMessage: p
129
+ isSubmitting: b,
130
+ isAccepted: C,
131
+ errorMessage: h
114
132
  });
115
133
  }
116
- function C({ baseUrl: e, widgetToken: n, organizationId: r, configClient: i, gatewayRouting: a, linkComponent: o, implementation: c, uiFramework: l, errorFallback: u, onError: d, analytics: f, ...p }) {
117
- return /* @__PURE__ */ _(s, {
134
+ function w({ baseUrl: e, widgetToken: n, organizationId: r, configClient: i, gatewayRouting: a, linkComponent: o, implementation: s, uiFramework: c, errorFallback: u, onError: d, analytics: f, ...p }) {
135
+ return /* @__PURE__ */ y(l, {
118
136
  widgetName: t,
119
137
  baseUrl: e,
120
138
  widgetToken: n,
@@ -122,13 +140,13 @@ function C({ baseUrl: e, widgetToken: n, organizationId: r, configClient: i, gat
122
140
  configClient: i,
123
141
  gatewayRouting: a,
124
142
  linkComponent: o,
125
- implementation: c,
126
- uiFramework: l,
143
+ implementation: s,
144
+ uiFramework: c,
127
145
  errorFallback: u,
128
146
  onError: d,
129
147
  analytics: f,
130
- children: /* @__PURE__ */ _(x, { ...p })
148
+ children: /* @__PURE__ */ y(S, { ...p })
131
149
  });
132
150
  }
133
151
  //#endregion
134
- export { C as AcceptDisclosuresWidget };
152
+ export { w as AcceptDisclosuresWidget };
@@ -1,3 +1,3 @@
1
- import { ACCEPT_DISCLOSURES_WIDGET_LABELS_EN as e } from "./lib/AcceptDisclosuresWidget/labels.js";
2
- import { AcceptDisclosuresWidget as t } from "./lib/AcceptDisclosuresWidget/AcceptDisclosuresWidget.js";
3
- export { e as ACCEPT_DISCLOSURES_WIDGET_LABELS_EN, t as AcceptDisclosuresWidget };
1
+ import { ACCEPT_DISCLOSURES_WIDGET_LABELS_EN as e, mergeAcceptDisclosuresWidgetLabels as t } from "./lib/AcceptDisclosuresWidget/labels.js";
2
+ import { AcceptDisclosuresWidget as n } from "./lib/AcceptDisclosuresWidget/AcceptDisclosuresWidget.js";
3
+ export { e as ACCEPT_DISCLOSURES_WIDGET_LABELS_EN, n as AcceptDisclosuresWidget, t as mergeAcceptDisclosuresWidgetLabels };
@@ -1,17 +1,10 @@
1
- import { ACCEPT_DISCLOSURES_WIDGET_LABELS_EN as e } from "./labels.js";
1
+ import { mergeAcceptDisclosuresWidgetLabels as e } from "./labels.js";
2
2
  import { Button as t, Checkbox as n } from "../../../../../../../packages/shared-ui-shadcn/dist/index.js";
3
3
  import { useId as r } from "react";
4
4
  import { jsx as i, jsxs as a } from "react/jsx-runtime";
5
5
  //#region ../../libs/tesouro-embedded-components-react/accept-disclosures-widget/ui/dist/lib/AcceptDisclosuresWidget/AcceptDisclosuresWidget.js
6
6
  function o({ providerAttribution: o, agreementText: s, disclosureLinks: c, isAgreed: l, onAgreedChange: u, onAccept: d, isSubmitting: f = !1, isAccepted: p = !1, errorMessage: m, labels: h }) {
7
- let g = f || p, _ = {
8
- ...e,
9
- ...h,
10
- linkLabels: {
11
- ...e.linkLabels,
12
- ...h?.linkLabels
13
- }
14
- }, v = r(), y = `${v}-agree`, b = `${v}-agree-description`, x = `${v}-accept-error`;
7
+ let g = f || p, _ = e(h), v = r(), y = `${v}-agree`, b = `${v}-agree-description`, x = `${v}-accept-error`;
15
8
  return /* @__PURE__ */ a("div", {
16
9
  "data-testid": "accept-disclosures-widget-root",
17
10
  className: "ttw:block ttw:w-full ttw:rounded-lg ttw:border ttw:border-border ttw:bg-background ttw:p-6",
@@ -25,7 +18,7 @@ function o({ providerAttribution: o, agreementText: s, disclosureLinks: c, isAgr
25
18
  className: "ttw:mb-4 ttw:text-sm ttw:text-foreground",
26
19
  children: o
27
20
  }),
28
- /* @__PURE__ */ i("ul", {
21
+ c.length > 0 ? /* @__PURE__ */ i("ul", {
29
22
  "data-testid": "accept-disclosures-links",
30
23
  className: "ttw:mb-4 ttw:list-disc ttw:space-y-2 ttw:pl-5",
31
24
  children: c.map((e) => /* @__PURE__ */ i("li", {
@@ -38,7 +31,7 @@ function o({ providerAttribution: o, agreementText: s, disclosureLinks: c, isAgr
38
31
  children: e.label
39
32
  })
40
33
  }, e.href))
41
- }),
34
+ }) : null,
42
35
  /* @__PURE__ */ a("div", {
43
36
  className: "ttw:mb-4 ttw:flex ttw:items-start ttw:gap-3",
44
37
  children: [/* @__PURE__ */ i(n, {
@@ -77,4 +70,4 @@ function o({ providerAttribution: o, agreementText: s, disclosureLinks: c, isAgr
77
70
  });
78
71
  }
79
72
  //#endregion
80
- export { e as ACCEPT_DISCLOSURES_WIDGET_LABELS_EN, o as AcceptDisclosuresWidget };
73
+ export { o as AcceptDisclosuresWidget, e as mergeAcceptDisclosuresWidgetLabels };
@@ -4,7 +4,7 @@ var e = {
4
4
  acceptButton: "Accept",
5
5
  agreementCheckboxAriaLabel: "Agree to banking disclosures",
6
6
  acceptErrorFallback: "Failed to accept disclosures",
7
- agreementTextTemplate: "I agree to {bankName}'s Terms of Use and Privacy Policy, consent to receive electronic communications about my accounts and services, and acknowledge receipt of the USA PATRIOT Act Disclosure.",
7
+ agreementTextTemplate: "I agree to {bankName}'s {documents}.",
8
8
  providerAttributionPrefix: "Banking services for ",
9
9
  providerAttributionMiddle: " are provided by ",
10
10
  providerAttributionSuffix: ", Member FDIC.",
@@ -13,7 +13,27 @@ var e = {
13
13
  privacyPolicy: "Privacy Policy",
14
14
  electronicCommunications: "Electronic Communications Agreement",
15
15
  patriotAct: "USA PATRIOT Act Disclosure"
16
- }
16
+ },
17
+ noDocumentsTitle: "Accept to continue",
18
+ noDocumentsAgreementTextTemplate: "I agree to continue with {bankName}.",
19
+ noDocumentsAgreementCheckboxAriaLabel: "Agree to continue with {bankName}",
20
+ documentListPairTemplate: "{first} and {second}",
21
+ documentListSeparator: ", ",
22
+ documentListLastConjunction: ", and ",
23
+ loadErrorTitle: "Unable to load disclosures",
24
+ loadErrorFallback: "Failed to load disclosures",
25
+ loadErrorRetryLabel: "Try again",
26
+ disclosuresUpdatedFallback: "These disclosures have been updated. Review the new documents and accept again."
17
27
  };
28
+ function t(t) {
29
+ return {
30
+ ...e,
31
+ ...t,
32
+ linkLabels: {
33
+ ...e.linkLabels,
34
+ ...t?.linkLabels
35
+ }
36
+ };
37
+ }
18
38
  //#endregion
19
- export { e as ACCEPT_DISCLOSURES_WIDGET_LABELS_EN };
39
+ export { e as ACCEPT_DISCLOSURES_WIDGET_LABELS_EN, t as mergeAcceptDisclosuresWidgetLabels };
@@ -1,5 +1,5 @@
1
1
  //#region ../../libs/tesouro-embedded-components-react/shared/feature/dist/lib/analytics/build-info.js
2
- var e = "@tesouro/embedded-components-react", t = "0.2.270", n = "6bf6a363553cdcc2d4ec7362b4f41707e7a20462", r = Object.freeze({
2
+ var e = "@tesouro/embedded-components-react", t = "0.2.272", n = "1d93289f62e822c5d71a073df8a4f6ed6c3ac630", r = Object.freeze({
3
3
  library_name: e,
4
4
  library_version: t,
5
5
  library_sha: n
@@ -22,10 +22,6 @@ var e = {
22
22
  title: "We couldn't finish loading this page",
23
23
  body: "Your disclosure acceptance was saved, so you won't need to accept again.",
24
24
  retryButton: "Try again"
25
- },
26
- unavailableState: {
27
- title: "This account needs to accept disclosures",
28
- body: "The documents are not available right now. Please contact support to continue."
29
25
  }
30
26
  };
31
27
  //#endregion
@@ -24,102 +24,90 @@ import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
24
24
  //#region ../../libs/tesouro-embedded-components-react/widget-suite/feature/dist/index6.js
25
25
  var E = {
26
26
  initFailed: "widget-suite-init-failed",
27
- disclosuresRefreshFailed: "widget-suite-disclosures-refresh-failed",
28
- disclosuresUnavailable: "widget-suite-disclosures-unavailable"
27
+ disclosuresRefreshFailed: "widget-suite-disclosures-refresh-failed"
29
28
  };
30
- function D({ sections: r, disclosureLinks: m, labels: D, sectionLabels: O, sectionTitleLabels: k, contentLabels: A, disclosureLabels: j, showSectionTitle: M = !0 }) {
31
- let N = n();
29
+ function D({ sections: r, labels: m, sectionLabels: D, sectionTitleLabels: O, contentLabels: k, disclosureLabels: A, showSectionTitle: j = !0 }) {
30
+ let M = n();
32
31
  b(() => {
33
- N(h.Mounted);
34
- }, [N]);
35
- let P = {
32
+ M(h.Mounted);
33
+ }, [M]);
34
+ let N = {
36
35
  ...d,
37
- ...O
38
- }, { initResponse: F } = a(), I = o(), L = s(), R = F?.scopes, z = x(() => ({
36
+ ...D
37
+ }, { initResponse: P } = a(), F = o(), I = s(), L = P?.scopes, R = x(() => ({
39
38
  creditCards: {
40
39
  ...l.creditCards,
41
- ...A?.creditCards
40
+ ...k?.creditCards
42
41
  },
43
42
  debitCards: {
44
43
  ...l.debitCards,
45
- ...A?.debitCards
44
+ ...k?.debitCards
46
45
  },
47
46
  expensePlaceholders: {
48
47
  ...l.expensePlaceholders,
49
- ...A?.expensePlaceholders
48
+ ...k?.expensePlaceholders
50
49
  }
51
- }), [A]), [B, V] = S(r[0] ?? ""), H = i(), [U, W] = S(!1), G = y(() => W(!0), []), K = g(F), q = {
50
+ }), [k]), [z, B] = S(r[0] ?? ""), V = i(), [H, U] = S(!1), W = y(() => U(!0), []), G = g(P), K = {
52
51
  ...u,
53
- ...j,
52
+ ...A,
54
53
  initFailedState: {
55
54
  ...u.initFailedState,
56
- ...j?.initFailedState
55
+ ...A?.initFailedState
57
56
  },
58
57
  refreshFailedState: {
59
58
  ...u.refreshFailedState,
60
- ...j?.refreshFailedState
61
- },
62
- unavailableState: {
63
- ...u.unavailableState,
64
- ...j?.unavailableState
59
+ ...A?.refreshFailedState
65
60
  }
66
61
  };
67
62
  b(() => {
68
- !K && U && W(!1);
69
- }, [U, K]);
70
- let J = !!(F && L);
71
- if (!F && !I || J && !I) return /* @__PURE__ */ w(_, {
63
+ !G && H && U(!1);
64
+ }, [H, G]);
65
+ let q = !!(P && I);
66
+ if (!P && !F || q && !F) return /* @__PURE__ */ w(_, {
72
67
  isLoading: !0,
73
68
  sections: [],
74
69
  selectedSectionId: "",
75
- onSectionChange: V,
76
- labels: D
70
+ onSectionChange: B,
71
+ labels: m
77
72
  });
78
- if ((!F || J) && I) return /* @__PURE__ */ w(t, {
79
- title: q.initFailedState.title,
80
- description: q.initFailedState.body,
81
- retryLabel: q.initFailedState.retryButton,
82
- onRetry: H,
73
+ if ((!P || q) && F) return /* @__PURE__ */ w(t, {
74
+ title: K.initFailedState.title,
75
+ description: K.initFailedState.body,
76
+ retryLabel: K.initFailedState.retryButton,
77
+ onRetry: V,
83
78
  testId: E.initFailed
84
79
  });
85
- if (K) return U && I ? /* @__PURE__ */ w(t, {
86
- title: q.refreshFailedState.title,
87
- description: q.refreshFailedState.body,
88
- retryLabel: q.refreshFailedState.retryButton,
89
- onRetry: H,
80
+ if (G) return H && F ? /* @__PURE__ */ w(t, {
81
+ title: K.refreshFailedState.title,
82
+ description: K.refreshFailedState.body,
83
+ retryLabel: K.refreshFailedState.retryButton,
84
+ onRetry: V,
90
85
  testId: E.disclosuresRefreshFailed
91
- }) : m ? /* @__PURE__ */ w(c, {
92
- disclosureLinks: m,
93
- onAccepted: G
94
- }) : /* @__PURE__ */ w(t, {
95
- title: q.unavailableState.title,
96
- description: q.unavailableState.body,
97
- testId: E.disclosuresUnavailable
98
- });
99
- let Y = F?.bankName?.trim(), X = Y ? {
86
+ }) : /* @__PURE__ */ w(c, { onAccepted: W });
87
+ let J = P?.bankName?.trim(), Y = J ? {
100
88
  ...f,
101
- ...k
102
- }.bankTagline.replaceAll("{bankName}", Y) : void 0, Z = r.flatMap((t) => {
89
+ ...O
90
+ }.bankTagline.replaceAll("{bankName}", J) : void 0, X = r.flatMap((t) => {
103
91
  let n = p[t];
104
- if (!n || n.anyOfScopes && !e(R, n.anyOfScopes)) return [];
105
- let r = P[t], i = n.render({
106
- grantedScopes: R,
107
- labels: z
92
+ if (!n || n.anyOfScopes && !e(L, n.anyOfScopes)) return [];
93
+ let r = N[t], i = n.render({
94
+ grantedScopes: L,
95
+ labels: R
108
96
  });
109
97
  return [{
110
98
  id: t,
111
99
  label: r,
112
- content: M && !n.rendersOwnTitle ? /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ w(v, {
100
+ content: j && !n.rendersOwnTitle ? /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ w(v, {
113
101
  title: r,
114
- bankTagline: X
102
+ bankTagline: Y
115
103
  }), i] }) : i
116
104
  }];
117
- }), Q = Z.some((e) => e.id === B) ? B : Z[0]?.id ?? "";
105
+ }), Z = X.some((e) => e.id === z) ? z : X[0]?.id ?? "";
118
106
  return /* @__PURE__ */ w(_, {
119
- sections: Z,
120
- selectedSectionId: Q,
121
- onSectionChange: V,
122
- labels: D
107
+ sections: X,
108
+ selectedSectionId: Z,
109
+ onSectionChange: B,
110
+ labels: m
123
111
  });
124
112
  }
125
113
  function O({ baseUrl: e, widgetToken: t, organizationId: n, configClient: i, gatewayRouting: a, linkComponent: o, implementation: s, uiFramework: c, errorFallback: l, onError: u, analytics: d, ...f }) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tesouro/embedded-components-react",
3
- "version": "0.2.270",
3
+ "version": "0.2.272",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "packageDepSync": {