@benji-money/connect-sdk 1.1.4-beta.1 → 1.1.4-beta.11

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
@@ -2,6 +2,8 @@
2
2
 
3
3
  A JavaScript Github Package SDK for integrating Benji Connect, Benji's authentication and verification services.
4
4
 
5
+ LOGIN mode (surfaces, timers, host API): [docs/login-mode.md](./docs/login-mode.md).
6
+
5
7
  ## Installation
6
8
 
7
9
  ```bash
@@ -87,12 +89,22 @@ The SDK accepts the following configuration options:
87
89
  - `environment` (required): One of `local`, `development`, `sandbox`, or `production`
88
90
  - `token` (required): Your API connect token
89
91
  - `mode` (optional): `BenjiConnectMode` — `CONNECT` (default), `TRANSFER`, `REDEEM`, or `LOGIN`
90
- - `authType` (optional): `PartnerIntegrationType` — LOGIN only; omit or set `DUMMY` for the visible modal iframe; set to your partner type (1–6) for popup-only auth. Prefer `tokenData.authType` when using `tokenData`.
91
- - `tokenData` (optional): `BenjiConnectTokenData` — LOGIN only; pass `partnerAuthLink` (Auth Service `connect_url`) and `authType` so the SDK opens the partner auth URL synchronously in the popup on `open()` instead of `about:blank` + loading HTML
92
+ - `authType` (optional): `PartnerIntegrationType` — LOGIN only; omit or set `DUMMY` for the visible modal iframe; set to your partner type (1–6) for the embedded sign-in button. Prefer `tokenData.authType` when using `tokenData`.
93
+ - `login` (optional): `BenjiConnectLoginConfig` — LOGIN-only options:
94
+ - `container`: `HTMLElement | string` — **required** for the embedded LOGIN button. The element the visible Benji Connect iframe mounts into. The SDK never appends to `document.body` for this surface; a missing container reports through `onError`.
95
+ - `surface`: `BenjiConnectLoginSurface` — `EMBEDDED_BUTTON` (default for non-DUMMY LOGIN) or `MODAL` (default for DUMMY). Override only when a partner on a real integration type needs the modal.
96
+ - `windowTarget`: `BenjiConnectLoginWindowTarget` — LOGIN non-DUMMY only; `tab` (default) or `popup`. Forwarded to Benji Connect, which opens the window.
97
+ - `buttonText`: host-owned label. Omitted or empty → Connect paints `Login`.
98
+ - `buttonTheme`: resolved CSS values for the in-iframe button (fill, hover, type, radius).
99
+ - `tokenData` (optional): `BenjiConnectTokenData` — LOGIN only; pass `partnerAuthLink` (Auth Service `connect_url`), `configToken` (mint `config_token`, used as OAuth `state`), and `authType`. Benji Connect resolves the auth link at iframe load, before any click.
92
100
  - `onSuccess` (optional): Callback function called when connect completed successfully
93
101
  - `onError` (optional): Callback function called when error occurs in the connect flow
94
102
  - `onExit` (optional): Callback function called when the user exits the connect flow
95
103
  - `onEvent` (optional): Callback function for handling various events
104
+ - `onLoginDisplayed` (optional): Embedded LOGIN button only — Connect painted themed chrome (first visual handoff); prefer this for dropping the host skeleton/cover. Requires Benji Connect [BEN-2572] to emit `LOGIN_DISPLAYED`; do not rely on this callback until Connect is deployed.
105
+ - `onLoginReady` (optional, deprecated for cover handoff): Embedded LOGIN button only — Connect resolved the auth link and rendered the button (session-ready). Prefer `onLoginDisplayed` for skeleton/cover removal.
106
+ - `onLoginHover` (optional): Embedded LOGIN button only — pointer or focus entered the in-iframe button, for a host-owned tooltip
107
+ - `onLoginClicked` (optional): Embedded LOGIN button only — the button was pressed, before the tab opens, for a host-owned pending state
96
108
  - `anchor` (optional): Live anchor binding — `HTMLElement`, CSS selector, getter `() => HTMLElement | null`, or ref `{ value: HTMLElement | null }`. Re-resolved on every layout pass. Falls back to centered when missing or invalid. See [Placement](#placement)
97
109
  - `placement` (optional): Placement relative to `anchor` — see [Placement](#placement) below
98
110
  - `offset` (optional): Pixel gap after placement — `{ top?: number; left?: number }` (default `{ top: 0, left: 0 }`)
@@ -103,7 +115,7 @@ The SDK accepts the following configuration options:
103
115
  | ---- | ---------- | ----- |
104
116
  | **CONNECT** (default) | Centered or anchored modal iframe | No `authType`; standard connect / verify flow |
105
117
  | **LOGIN + DUMMY / no `authType`** | Same visible modal iframe | Partner auth runs in a nested iframe inside Benji Connect |
106
- | **LOGIN + non-DUMMY** | Partner popup only | Pass `authType` (or `tokenData.authType`); Benji Connect iframe is headless — popup opens partner auth immediately when `tokenData.partnerAuthLink` is set, otherwise shows loading UI until Benji Connect navigates — see [LOGIN popup example](#login-popup-example) below |
118
+ | **LOGIN + non-DUMMY** | **Embedded sign-in button** plus a partner auth tab | Pass `authType` (or `tokenData.authType`) and `login.container`. Benji Connect renders the button inside a visible iframe and opens the partner tab itself, on every device. See [embedded LOGIN button example](#embedded-login-button-example) below. |
107
119
 
108
120
  ### Placement
109
121
 
@@ -118,7 +130,7 @@ Placement uses [Floating UI](https://floating-ui.com/docs/computePosition#placem
118
130
  **What `anchor` positions:**
119
131
 
120
132
  - **CONNECT, TRANSFER, REDEEM, and LOGIN + DUMMY:** the modal iframe
121
- - **LOGIN + non-DUMMY:** the partner-auth popup window (modal iframe stays headless)
133
+ - **LOGIN + non-DUMMY:** nothing. The embedded button takes its box from `login.container`, so omit `anchor` / `placement` / `offset`.
122
134
 
123
135
  **Defaults:**
124
136
 
@@ -145,15 +157,18 @@ Prefer selector, ref, or getter when the anchor can re-render (e.g. disabled/loa
145
157
  - **Anchored** popovers use the full design size when width and height checks pass; otherwise they fall back to a scaled centered modal
146
158
  - Scroll, resize, and visual viewport changes while open recompute placement and size
147
159
 
148
- #### LOGIN popup example
160
+ #### Embedded LOGIN button example
161
+
162
+ Reserve a box in your own layout, hand it to the SDK, and let Benji Connect render the button inside it:
149
163
 
150
- Popup below a top-right login button; pass `authType` for non-DUMMY partners:
164
+ ```html
165
+ <div id="benji-login" style="width: 140px; height: 40px"></div>
166
+ ```
151
167
 
152
168
  ```typescript
153
169
  import {
154
170
  ConnectSDK,
155
171
  BenjiConnectMode,
156
- BenjiConnectPlacement,
157
172
  PartnerIntegrationType,
158
173
  } from "@benji-money/connect-sdk";
159
174
 
@@ -161,22 +176,29 @@ const sdk = new ConnectSDK({
161
176
  environment: "sandbox",
162
177
  token: connectToken,
163
178
  mode: BenjiConnectMode.LOGIN,
179
+ login: { container: "#benji-login" },
164
180
  tokenData: {
165
181
  authType: PartnerIntegrationType.OAUTH_PKCE,
166
182
  partnerAuthLink: connectUrl, // from Auth Service connect_url
183
+ configToken: configToken, // from GET /connect/token — OAuth state
167
184
  },
168
- anchor: "#login-btn",
169
- placement: BenjiConnectPlacement.BOTTOM_END,
170
- offset: { top: 8 },
185
+ onLoginDisplayed: () => { /* hide your skeleton */ },
186
+ onLoginHover: () => { /* show your tooltip */ },
187
+ onLoginClicked: () => { /* show your pending state */ },
171
188
  onSuccess: (token) => { /* ... */ },
172
- onError: (error) => { /* popup blocked, etc. */ },
173
- onExit: (metadata) => { /* POPUP_CLOSED when user dismisses popup */ },
189
+ onError: (error) => { /* sign-in window blocked, etc. */ },
190
+ onExit: (metadata) => { /* toast: WINDOW_CLOSE_DETECTED; the button stays mounted */ },
174
191
  });
175
192
 
193
+ // Mount on page load, not on click — the iframe resolves the partner auth link
194
+ // while the user is still reading the page.
176
195
  await sdk.open();
196
+
197
+ // Later, when your token refresh timer fires:
198
+ sdk.updateConfig({ token: freshConnectToken, tokenData: { configToken: freshConfigToken } });
177
199
  ```
178
200
 
179
- > **`bottom-end`** positions the **partner popup** below the anchor with its right edge aligned to the anchor's right edge. The Benji Connect iframe stays headless (not visible). When `tokenData.partnerAuthLink` is set, the popup navigates to partner auth immediately on `open()`. Otherwise the pre-opened popup shows generic loading UI (`Loading sign-in…`) until Benji Connect sends the partner auth URL.
201
+ > **Why the button lives in the iframe.** `window.open` needs transient user activation, and activation belongs to the document the click happened in. Because the click lands in Benji Connect's document, **Connect** opens the partner tab, so that tab's `opener` is the Connect iframe — same-origin with Connect's OAuth callback. That is what removes the host-side auth relay, the message queues, and the iOS-only same-tab redirect that earlier versions needed. Reserve the box in your own CSS: the SDK's iframe fills the container at 100% × 100% and contributes no geometry of its own.
180
202
 
181
203
  ### Environments
182
204