@benji-money/connect-sdk 1.0.10 → 1.1.0-beta.2
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 +63 -0
- package/dist/connect-sdk.umd.global.js +361 -31
- package/dist/connect-sdk.umd.global.js.map +1 -1
- package/dist/index.cjs +377 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +46 -4
- package/dist/index.d.ts +46 -4
- package/dist/index.js +375 -37
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -90,6 +90,69 @@ The SDK accepts the following configuration options:
|
|
|
90
90
|
- `onError` (optional): Callback function called when error occurs in the connect flow
|
|
91
91
|
- `onExit` (optional): Callback function called when the user exits the connect flow
|
|
92
92
|
- `onEvent` (optional): Callback function for handling various events
|
|
93
|
+
- `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)
|
|
94
|
+
- `placement` (optional): Placement relative to `anchor` — see [Placement](#placement) below
|
|
95
|
+
- `offset` (optional): Pixel gap after placement — `{ top?: number; left?: number }` (default `{ top: 0, left: 0 }`)
|
|
96
|
+
|
|
97
|
+
### Placement
|
|
98
|
+
|
|
99
|
+
Placement uses [Floating UI](https://floating-ui.com/docs/computePosition#placement) / CSS logical naming (`start` / `end`). In **LTR** layouts:
|
|
100
|
+
|
|
101
|
+
| Value | Meaning |
|
|
102
|
+
| ----- | ------- |
|
|
103
|
+
| `center` (default) | Full-viewport backdrop with iframe centered |
|
|
104
|
+
| `bottom-end` | Below the anchor, right edge aligned with anchor's right edge |
|
|
105
|
+
| `bottom-start` | Below the anchor, left edge aligned with anchor's left edge |
|
|
106
|
+
|
|
107
|
+
**Defaults:**
|
|
108
|
+
|
|
109
|
+
- No `anchor` → centered modal (unchanged behavior for existing integrations)
|
|
110
|
+
- `anchor` set, no `placement` → `bottom-end`
|
|
111
|
+
- If the anchor is missing or invalid on **initial open**, there is not enough viewport space below, or the viewport is narrower than the iframe (400px + padding), the SDK falls back to centered
|
|
112
|
+
- While the modal is **already open**, a temporarily hidden or detached anchor (e.g. crossing a responsive layout breakpoint) keeps the last anchored position instead of jumping to center; when the anchor becomes visible again, placement re-anchors automatically
|
|
113
|
+
|
|
114
|
+
**Live anchor bindings** (re-resolved on scroll, resize, and visual viewport changes):
|
|
115
|
+
|
|
116
|
+
| Form | Example | When to use |
|
|
117
|
+
| ---- | ------- | ----------- |
|
|
118
|
+
| CSS selector | `'#login-btn'` | Stable id on the anchor element |
|
|
119
|
+
| Ref object | `loginButtonRef` (Vue `{ value: el }`) | Anchor may re-render after async work |
|
|
120
|
+
| Getter | `() => document.querySelector('#login-btn')` | Custom lookup |
|
|
121
|
+
| `HTMLElement` | Snapshot at click time | Only when the node will not be replaced before `open()` |
|
|
122
|
+
|
|
123
|
+
Prefer selector, ref, or getter when the anchor can re-render (e.g. disabled/loading state) before the modal opens. A stale `HTMLElement` snapshot falls back to a centered modal on open instead of clipping to the top-left; while open, resize across breakpoints preserves the last anchored position until the anchor is visible again or the modal is closed.
|
|
124
|
+
|
|
125
|
+
**Viewport sizing:**
|
|
126
|
+
|
|
127
|
+
- Design size is **400×645** px (`IFRAME_WIDTH` / `IFRAME_HEIGHT`)
|
|
128
|
+
- **Centered** modals (default, explicit, or fallback) scale down proportionally when the viewport is smaller than the design size so the modal fits with 8px padding on each side
|
|
129
|
+
- **Anchored** popovers use the full design size when width and height checks pass; otherwise they fall back to a scaled centered modal
|
|
130
|
+
- Scroll, resize, and visual viewport changes while open recompute placement and size
|
|
131
|
+
|
|
132
|
+
**LOGIN popover example** (dropdown under a top-right button):
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import {
|
|
136
|
+
ConnectSDK,
|
|
137
|
+
BenjiConnectMode,
|
|
138
|
+
BenjiConnectPlacement,
|
|
139
|
+
} from "@benji-money/connect-sdk";
|
|
140
|
+
|
|
141
|
+
// Prefer a live binding (selector or ref) when the button may re-render before open()
|
|
142
|
+
const sdk = new ConnectSDK({
|
|
143
|
+
environment: "sandbox",
|
|
144
|
+
token: connectToken,
|
|
145
|
+
mode: BenjiConnectMode.LOGIN,
|
|
146
|
+
anchor: "#login-btn",
|
|
147
|
+
placement: BenjiConnectPlacement.BOTTOM_END,
|
|
148
|
+
offset: { top: 8 },
|
|
149
|
+
onSuccess: (token) => { /* ... */ },
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
await sdk.open();
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
> **`bottom-end`** opens below the anchor with the modal's right edge aligned to the anchor's right edge — matching a dropdown under a top-right LOGIN button.
|
|
93
156
|
|
|
94
157
|
### Environments
|
|
95
158
|
|
|
@@ -110,7 +110,7 @@ var ConnectSDK = (() => {
|
|
|
110
110
|
// src/utils/config.ts
|
|
111
111
|
var buildContext = () => ({
|
|
112
112
|
namespace: "benji-connect-sdk" ? "benji-connect-sdk" : "benji-connect-sdk",
|
|
113
|
-
version: "1.0.
|
|
113
|
+
version: "1.1.0-beta.2" ? String("1.1.0-beta.2") : "0.0.0"
|
|
114
114
|
});
|
|
115
115
|
function isBenjiConnectEnvironment(environment) {
|
|
116
116
|
return environment === "local" /* LOCAL */ || environment === "development" /* DEVELOPMENT */ || environment === "sandbox" /* SANDBOX */ || environment === "production" /* PRODUCTION */;
|
|
@@ -130,11 +130,312 @@ var ConnectSDK = (() => {
|
|
|
130
130
|
return defaultEnvironment;
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
// src/utils/placement.ts
|
|
134
|
+
var IFRAME_WIDTH = 400;
|
|
135
|
+
var IFRAME_HEIGHT = 645;
|
|
136
|
+
var IFRAME_STATIC_STYLE = {
|
|
137
|
+
border: "none",
|
|
138
|
+
borderRadius: "20px",
|
|
139
|
+
overflow: "hidden"
|
|
140
|
+
};
|
|
141
|
+
var CONTAINER_BASE_STYLE = {
|
|
142
|
+
position: "fixed",
|
|
143
|
+
top: "0",
|
|
144
|
+
left: "0",
|
|
145
|
+
width: "100%",
|
|
146
|
+
height: "100%",
|
|
147
|
+
backgroundColor: "rgba(0,0,0,0.5)",
|
|
148
|
+
zIndex: "9999"
|
|
149
|
+
};
|
|
150
|
+
var VIEWPORT_PADDING = 8;
|
|
151
|
+
function isPreservableAnchoredLayout(layout) {
|
|
152
|
+
return layout != null && layout.placement !== "center" /* CENTER */;
|
|
153
|
+
}
|
|
154
|
+
function clampPreservedAnchoredLayout(layout, viewport) {
|
|
155
|
+
const maxLeft = viewport.width - layout.width - VIEWPORT_PADDING;
|
|
156
|
+
const maxTop = viewport.height - layout.height - VIEWPORT_PADDING;
|
|
157
|
+
const minLeft = VIEWPORT_PADDING;
|
|
158
|
+
const minTop = VIEWPORT_PADDING;
|
|
159
|
+
return {
|
|
160
|
+
...layout,
|
|
161
|
+
left: maxLeft < minLeft ? minLeft : Math.min(Math.max(layout.left, minLeft), maxLeft),
|
|
162
|
+
top: maxTop < minTop ? minTop : Math.min(Math.max(layout.top, minTop), maxTop)
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function preservedAnchoredLayoutOrCenter(viewport, options) {
|
|
166
|
+
const { preserveAnchoredLayout } = options;
|
|
167
|
+
if (isPreservableAnchoredLayout(preserveAnchoredLayout)) {
|
|
168
|
+
return clampPreservedAnchoredLayout(preserveAnchoredLayout, viewport);
|
|
169
|
+
}
|
|
170
|
+
return centerLayout(viewport);
|
|
171
|
+
}
|
|
172
|
+
function isRefLikeAnchor(anchor) {
|
|
173
|
+
return typeof anchor === "object" && anchor !== null && !(anchor instanceof HTMLElement) && "value" in anchor;
|
|
174
|
+
}
|
|
175
|
+
function resolveAnchor(anchor) {
|
|
176
|
+
if (!anchor) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
if (typeof anchor === "string") {
|
|
180
|
+
return document.querySelector(anchor);
|
|
181
|
+
}
|
|
182
|
+
if (typeof anchor === "function") {
|
|
183
|
+
const resolved = anchor();
|
|
184
|
+
return resolved instanceof HTMLElement ? resolved : null;
|
|
185
|
+
}
|
|
186
|
+
if (isRefLikeAnchor(anchor)) {
|
|
187
|
+
const el = anchor.value;
|
|
188
|
+
return el instanceof HTMLElement ? el : null;
|
|
189
|
+
}
|
|
190
|
+
return anchor instanceof HTMLElement ? anchor : null;
|
|
191
|
+
}
|
|
192
|
+
function isAnchorVisible(el) {
|
|
193
|
+
if (!el.isConnected) {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
const style = window.getComputedStyle(el);
|
|
197
|
+
if (style.display === "none" || style.visibility === "hidden") {
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
const rect = el.getBoundingClientRect();
|
|
201
|
+
return rect.width > 0 || rect.height > 0;
|
|
202
|
+
}
|
|
203
|
+
function resolveEffectivePlacement(config) {
|
|
204
|
+
var _a;
|
|
205
|
+
if (!config.anchor) {
|
|
206
|
+
return "center" /* CENTER */;
|
|
207
|
+
}
|
|
208
|
+
return (_a = config.placement) != null ? _a : "bottom-end" /* BOTTOM_END */;
|
|
209
|
+
}
|
|
210
|
+
function defaultOffset(offset) {
|
|
211
|
+
var _a, _b;
|
|
212
|
+
return {
|
|
213
|
+
top: (_a = offset == null ? void 0 : offset.top) != null ? _a : 0,
|
|
214
|
+
left: (_b = offset == null ? void 0 : offset.left) != null ? _b : 0
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function resolveIframeDimensions(viewport) {
|
|
218
|
+
const maxW = viewport.width - 2 * VIEWPORT_PADDING;
|
|
219
|
+
const maxH = viewport.height - 2 * VIEWPORT_PADDING;
|
|
220
|
+
const scale = Math.min(1, maxW / IFRAME_WIDTH, maxH / IFRAME_HEIGHT);
|
|
221
|
+
return {
|
|
222
|
+
width: Math.floor(IFRAME_WIDTH * scale),
|
|
223
|
+
height: Math.floor(IFRAME_HEIGHT * scale)
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function iframeFitsHorizontally(viewportWidth, iframeWidth = IFRAME_WIDTH) {
|
|
227
|
+
return viewportWidth >= iframeWidth + 2 * VIEWPORT_PADDING;
|
|
228
|
+
}
|
|
229
|
+
function centerLayout(viewport) {
|
|
230
|
+
const { width, height } = resolveIframeDimensions(viewport);
|
|
231
|
+
return {
|
|
232
|
+
top: 0,
|
|
233
|
+
left: 0,
|
|
234
|
+
width,
|
|
235
|
+
height,
|
|
236
|
+
placement: "center" /* CENTER */
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
function fitsBelow(anchorBottom, offsetTop, viewportHeight, iframeHeight = IFRAME_HEIGHT) {
|
|
240
|
+
const top = anchorBottom + offsetTop;
|
|
241
|
+
const bottom = top + iframeHeight;
|
|
242
|
+
return top >= VIEWPORT_PADDING && bottom <= viewportHeight - VIEWPORT_PADDING;
|
|
243
|
+
}
|
|
244
|
+
function clampHorizontal(left, viewportWidth) {
|
|
245
|
+
const min = VIEWPORT_PADDING;
|
|
246
|
+
const max = viewportWidth - IFRAME_WIDTH - VIEWPORT_PADDING;
|
|
247
|
+
if (max < min) {
|
|
248
|
+
return min;
|
|
249
|
+
}
|
|
250
|
+
return Math.min(Math.max(left, min), max);
|
|
251
|
+
}
|
|
252
|
+
function warnInvalidAnchor(message) {
|
|
253
|
+
console.warn(`[Benji Connect SDK] ${message}`);
|
|
254
|
+
}
|
|
255
|
+
function computeIframeRect(anchorElement, placement, offset, viewport, options = {}) {
|
|
256
|
+
const { warnOnInvalidAnchor = false } = options;
|
|
257
|
+
const resolvedOffset = defaultOffset(offset);
|
|
258
|
+
if (placement === "center" /* CENTER */) {
|
|
259
|
+
return centerLayout(viewport);
|
|
260
|
+
}
|
|
261
|
+
if (!isAnchorVisible(anchorElement)) {
|
|
262
|
+
if (isPreservableAnchoredLayout(options.preserveAnchoredLayout)) {
|
|
263
|
+
return clampPreservedAnchoredLayout(
|
|
264
|
+
options.preserveAnchoredLayout,
|
|
265
|
+
viewport
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
if (warnOnInvalidAnchor) {
|
|
269
|
+
warnInvalidAnchor(
|
|
270
|
+
"anchor is hidden or detached; falling back to centered modal"
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
return centerLayout(viewport);
|
|
274
|
+
}
|
|
275
|
+
const rect = anchorElement.getBoundingClientRect();
|
|
276
|
+
if (!fitsBelow(rect.bottom, resolvedOffset.top, viewport.height)) {
|
|
277
|
+
return centerLayout(viewport);
|
|
278
|
+
}
|
|
279
|
+
if (!iframeFitsHorizontally(viewport.width)) {
|
|
280
|
+
return centerLayout(viewport);
|
|
281
|
+
}
|
|
282
|
+
const top = rect.bottom + resolvedOffset.top;
|
|
283
|
+
const idealLeft = placement === "bottom-end" /* BOTTOM_END */ ? rect.right - IFRAME_WIDTH + resolvedOffset.left : rect.left + resolvedOffset.left;
|
|
284
|
+
if (idealLeft < VIEWPORT_PADDING) {
|
|
285
|
+
if (warnOnInvalidAnchor) {
|
|
286
|
+
warnInvalidAnchor(
|
|
287
|
+
"anchor rect is unusable for placement; falling back to centered modal"
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
return centerLayout(viewport);
|
|
291
|
+
}
|
|
292
|
+
const left = clampHorizontal(idealLeft, viewport.width);
|
|
293
|
+
return {
|
|
294
|
+
top,
|
|
295
|
+
left,
|
|
296
|
+
width: IFRAME_WIDTH,
|
|
297
|
+
height: IFRAME_HEIGHT,
|
|
298
|
+
placement
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
function resolveIframeLayout(config, viewport = {
|
|
302
|
+
width: window.innerWidth,
|
|
303
|
+
height: window.innerHeight
|
|
304
|
+
}, options = {}) {
|
|
305
|
+
const { warnOnInvalidAnchor = true } = options;
|
|
306
|
+
const placement = resolveEffectivePlacement(config);
|
|
307
|
+
const anchorElement = resolveAnchor(config.anchor);
|
|
308
|
+
if (warnOnInvalidAnchor && placement !== "center" /* CENTER */ && !anchorElement) {
|
|
309
|
+
warnInvalidAnchor("anchor not found; falling back to centered modal");
|
|
310
|
+
return preservedAnchoredLayoutOrCenter(viewport, options);
|
|
311
|
+
}
|
|
312
|
+
if (placement === "center" /* CENTER */) {
|
|
313
|
+
return centerLayout(viewport);
|
|
314
|
+
}
|
|
315
|
+
if (!anchorElement) {
|
|
316
|
+
return preservedAnchoredLayoutOrCenter(viewport, options);
|
|
317
|
+
}
|
|
318
|
+
return computeIframeRect(
|
|
319
|
+
anchorElement,
|
|
320
|
+
placement,
|
|
321
|
+
config.offset,
|
|
322
|
+
viewport,
|
|
323
|
+
options
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
function applyOverlayBaseStyle(container) {
|
|
327
|
+
Object.assign(container.style, CONTAINER_BASE_STYLE);
|
|
328
|
+
}
|
|
329
|
+
function getVisualViewportOffset() {
|
|
330
|
+
const vv = window.visualViewport;
|
|
331
|
+
if (!vv) {
|
|
332
|
+
return { top: 0, left: 0 };
|
|
333
|
+
}
|
|
334
|
+
return { top: vv.offsetTop, left: vv.offsetLeft };
|
|
335
|
+
}
|
|
336
|
+
function getRepositionScrollTargets(anchor) {
|
|
337
|
+
const targets = /* @__PURE__ */ new Set([window]);
|
|
338
|
+
const anchorElement = resolveAnchor(anchor);
|
|
339
|
+
if (!anchorElement) {
|
|
340
|
+
return [...targets];
|
|
341
|
+
}
|
|
342
|
+
targets.add(anchorElement);
|
|
343
|
+
let parent = anchorElement.parentElement;
|
|
344
|
+
while (parent) {
|
|
345
|
+
const { overflow, overflowX, overflowY } = window.getComputedStyle(parent);
|
|
346
|
+
const overflowValue = `${overflow} ${overflowX} ${overflowY}`;
|
|
347
|
+
if (/(auto|scroll|overlay)/.test(overflowValue)) {
|
|
348
|
+
targets.add(parent);
|
|
349
|
+
}
|
|
350
|
+
parent = parent.parentElement;
|
|
351
|
+
}
|
|
352
|
+
return [...targets];
|
|
353
|
+
}
|
|
354
|
+
function applyIframeLayoutToElements(config, container, iframe, state, options = { warnOnInvalidAnchor: false }) {
|
|
355
|
+
state.layout = resolveIframeLayout(config, void 0, {
|
|
356
|
+
...options,
|
|
357
|
+
preserveAnchoredLayout: state.lastValidAnchoredLayout
|
|
358
|
+
});
|
|
359
|
+
if (state.layout.placement !== "center" /* CENTER */) {
|
|
360
|
+
state.lastValidAnchoredLayout = state.layout;
|
|
361
|
+
}
|
|
362
|
+
const iframeStyle = {
|
|
363
|
+
...IFRAME_STATIC_STYLE,
|
|
364
|
+
width: `${state.layout.width}px`,
|
|
365
|
+
height: `${state.layout.height}px`
|
|
366
|
+
};
|
|
367
|
+
if (state.layout.placement === "center" /* CENTER */) {
|
|
368
|
+
Object.assign(container.style, {
|
|
369
|
+
display: "flex",
|
|
370
|
+
alignItems: "center",
|
|
371
|
+
justifyContent: "center",
|
|
372
|
+
overflow: "auto"
|
|
373
|
+
});
|
|
374
|
+
Object.assign(iframe.style, iframeStyle, {
|
|
375
|
+
position: "relative",
|
|
376
|
+
top: "",
|
|
377
|
+
left: ""
|
|
378
|
+
});
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
Object.assign(container.style, {
|
|
382
|
+
display: "block",
|
|
383
|
+
overflow: "auto"
|
|
384
|
+
});
|
|
385
|
+
const viewportOffset = getVisualViewportOffset();
|
|
386
|
+
Object.assign(iframe.style, iframeStyle, {
|
|
387
|
+
position: "fixed",
|
|
388
|
+
top: `${state.layout.top + viewportOffset.top}px`,
|
|
389
|
+
left: `${state.layout.left + viewportOffset.left}px`
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
function attachRepositionListeners(config, onReposition) {
|
|
393
|
+
const repositionHandler = onReposition;
|
|
394
|
+
const repositionScrollTargets = getRepositionScrollTargets(config.anchor);
|
|
395
|
+
repositionScrollTargets.forEach((target) => {
|
|
396
|
+
target.addEventListener("scroll", repositionHandler, { passive: true });
|
|
397
|
+
});
|
|
398
|
+
window.addEventListener("resize", repositionHandler);
|
|
399
|
+
const visualViewport = window.visualViewport;
|
|
400
|
+
visualViewport == null ? void 0 : visualViewport.addEventListener("resize", repositionHandler);
|
|
401
|
+
visualViewport == null ? void 0 : visualViewport.addEventListener("scroll", repositionHandler);
|
|
402
|
+
return {
|
|
403
|
+
remove() {
|
|
404
|
+
repositionScrollTargets.forEach((target) => {
|
|
405
|
+
target.removeEventListener("scroll", repositionHandler);
|
|
406
|
+
});
|
|
407
|
+
window.removeEventListener("resize", repositionHandler);
|
|
408
|
+
visualViewport == null ? void 0 : visualViewport.removeEventListener("resize", repositionHandler);
|
|
409
|
+
visualViewport == null ? void 0 : visualViewport.removeEventListener("scroll", repositionHandler);
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// src/types/event.ts
|
|
415
|
+
var BenjiConnectEventType = /* @__PURE__ */ ((BenjiConnectEventType2) => {
|
|
416
|
+
BenjiConnectEventType2["AUTH_SUCCESS"] = "AUTH_SUCCESS";
|
|
417
|
+
BenjiConnectEventType2["FLOW_EXIT"] = "FLOW_EXIT";
|
|
418
|
+
BenjiConnectEventType2["FLOW_SUCCESS"] = "FLOW_SUCCESS";
|
|
419
|
+
BenjiConnectEventType2["EVENT"] = "EVENT";
|
|
420
|
+
BenjiConnectEventType2["ERROR"] = "ERROR";
|
|
421
|
+
return BenjiConnectEventType2;
|
|
422
|
+
})(BenjiConnectEventType || {});
|
|
423
|
+
|
|
133
424
|
// src/utils/auth.ts
|
|
425
|
+
var CONNECT_MESSAGE_TYPES = new Set(Object.values(BenjiConnectEventType));
|
|
426
|
+
function isConnectMessageType(data2) {
|
|
427
|
+
if (!data2 || typeof data2 !== "object") return false;
|
|
428
|
+
const type = data2.type;
|
|
429
|
+
return typeof type === "string" && CONNECT_MESSAGE_TYPES.has(type);
|
|
430
|
+
}
|
|
134
431
|
var extractAccessToken = (token) => {
|
|
135
432
|
var _a;
|
|
136
433
|
return typeof token === "string" ? token : (_a = token == null ? void 0 : token.access_token) != null ? _a : "";
|
|
137
434
|
};
|
|
435
|
+
var extractExchangeToken = (token) => {
|
|
436
|
+
var _a;
|
|
437
|
+
return typeof token === "string" ? token : (_a = token == null ? void 0 : token.exchange_token) != null ? _a : "";
|
|
438
|
+
};
|
|
138
439
|
var mapEventToConnectToken = (data2) => {
|
|
139
440
|
var _a, _b, _c;
|
|
140
441
|
return {
|
|
@@ -202,7 +503,7 @@ var ConnectSDK = (() => {
|
|
|
202
503
|
};
|
|
203
504
|
};
|
|
204
505
|
var mapToOnSuccessData = (data2) => {
|
|
205
|
-
const token = extractAccessToken(data2.token);
|
|
506
|
+
const token = data2.action === "login" /* Login */ ? extractExchangeToken(data2.token) : extractAccessToken(data2.token);
|
|
206
507
|
let metadata = {
|
|
207
508
|
context: buildContext(),
|
|
208
509
|
action: data2.action,
|
|
@@ -249,6 +550,9 @@ var ConnectSDK = (() => {
|
|
|
249
550
|
this.onEvent = config.onEvent;
|
|
250
551
|
this.close = config.close;
|
|
251
552
|
}
|
|
553
|
+
static setMode(mode) {
|
|
554
|
+
this.mode = mode;
|
|
555
|
+
}
|
|
252
556
|
static addEventListeners() {
|
|
253
557
|
if (this.configuredListeners) return;
|
|
254
558
|
window.addEventListener("error", this.errorEventHandler);
|
|
@@ -261,6 +565,7 @@ var ConnectSDK = (() => {
|
|
|
261
565
|
window.removeEventListener("unhandledrejection", this.errorEventHandler);
|
|
262
566
|
window.removeEventListener("message", this.messageEventHandler);
|
|
263
567
|
this.configuredListeners = false;
|
|
568
|
+
this.mode = 1 /* CONNECT */;
|
|
264
569
|
}
|
|
265
570
|
static handleErrorMessage(event) {
|
|
266
571
|
switch (event.type) {
|
|
@@ -281,8 +586,8 @@ var ConnectSDK = (() => {
|
|
|
281
586
|
}
|
|
282
587
|
}
|
|
283
588
|
static handleMessage(event) {
|
|
284
|
-
var _a, _b, _c, _d, _e, _f;
|
|
285
|
-
|
|
589
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
590
|
+
if (!isConnectMessageType(event.data)) return;
|
|
286
591
|
const expectedOrigin = new URL(Endpoints.benji_connect_auth_url).origin;
|
|
287
592
|
if (!event || event.origin !== expectedOrigin) {
|
|
288
593
|
console.warn("[Benji Connect SDK] Skipped message, received event from unexpected origin", event.origin, expectedOrigin);
|
|
@@ -312,18 +617,21 @@ var ConnectSDK = (() => {
|
|
|
312
617
|
const connectMessage = message;
|
|
313
618
|
const callbackData = BenjiConnectCallbackMapperMap.FLOW_SUCCESS(connectMessage.data);
|
|
314
619
|
(_d = this.onSuccess) == null ? void 0 : _d.call(this, callbackData.token, callbackData.metadata);
|
|
620
|
+
if (this.mode === 5 /* LOGIN */) {
|
|
621
|
+
(_e = this.close) == null ? void 0 : _e.call(this);
|
|
622
|
+
}
|
|
315
623
|
break;
|
|
316
624
|
}
|
|
317
625
|
case "ERROR" /* ERROR */: {
|
|
318
626
|
const connectMessage = message;
|
|
319
627
|
const callbackData = BenjiConnectCallbackMapperMap.ERROR(connectMessage.data);
|
|
320
|
-
(
|
|
628
|
+
(_f = this.onError) == null ? void 0 : _f.call(this, callbackData.error, callbackData.error_id, callbackData.metadata);
|
|
321
629
|
break;
|
|
322
630
|
}
|
|
323
|
-
|
|
324
|
-
const
|
|
325
|
-
const callbackData = mapToOnEventData(
|
|
326
|
-
(
|
|
631
|
+
case "EVENT" /* EVENT */: {
|
|
632
|
+
const connectMessage = message;
|
|
633
|
+
const callbackData = mapToOnEventData(connectMessage, connectMessage.data);
|
|
634
|
+
(_g = this.onEvent) == null ? void 0 : _g.call(this, callbackData.type, callbackData.metadata);
|
|
327
635
|
break;
|
|
328
636
|
}
|
|
329
637
|
}
|
|
@@ -332,6 +640,7 @@ var ConnectSDK = (() => {
|
|
|
332
640
|
}
|
|
333
641
|
};
|
|
334
642
|
_MessageRouter.configuredListeners = false;
|
|
643
|
+
_MessageRouter.mode = 1 /* CONNECT */;
|
|
335
644
|
_MessageRouter.errorEventHandler = (event) => {
|
|
336
645
|
return _MessageRouter.handleErrorMessage(event);
|
|
337
646
|
};
|
|
@@ -345,6 +654,17 @@ var ConnectSDK = (() => {
|
|
|
345
654
|
constructor(config) {
|
|
346
655
|
this.iframe = null;
|
|
347
656
|
this.container = null;
|
|
657
|
+
this.layoutState = {
|
|
658
|
+
layout: {
|
|
659
|
+
top: 0,
|
|
660
|
+
left: 0,
|
|
661
|
+
width: IFRAME_WIDTH,
|
|
662
|
+
height: IFRAME_HEIGHT,
|
|
663
|
+
placement: "center" /* CENTER */
|
|
664
|
+
},
|
|
665
|
+
lastValidAnchoredLayout: null
|
|
666
|
+
};
|
|
667
|
+
this.repositionListeners = null;
|
|
348
668
|
this.sdkConfig = config;
|
|
349
669
|
if (!this.sdkConfig.environment) throw new Error("Environment is required");
|
|
350
670
|
if (!this.sdkConfig.token) throw new Error("Connect token is required");
|
|
@@ -362,44 +682,48 @@ var ConnectSDK = (() => {
|
|
|
362
682
|
});
|
|
363
683
|
}
|
|
364
684
|
async open() {
|
|
685
|
+
var _a;
|
|
365
686
|
await this.initialize();
|
|
366
687
|
this.openUI();
|
|
688
|
+
MessageRouter.setMode((_a = this.sdkConfig.mode) != null ? _a : 1 /* CONNECT */);
|
|
367
689
|
MessageRouter.addEventListeners();
|
|
368
690
|
}
|
|
369
691
|
openUI() {
|
|
370
692
|
if (this.iframe) return;
|
|
371
693
|
this.container = document.createElement("div");
|
|
372
|
-
|
|
373
|
-
position: "fixed",
|
|
374
|
-
top: "0",
|
|
375
|
-
left: "0",
|
|
376
|
-
width: "100%",
|
|
377
|
-
height: "100%",
|
|
378
|
-
backgroundColor: "rgba(0,0,0,0.5)",
|
|
379
|
-
zIndex: "9999",
|
|
380
|
-
display: "flex",
|
|
381
|
-
alignItems: "center",
|
|
382
|
-
justifyContent: "center",
|
|
383
|
-
overflow: "auto"
|
|
384
|
-
});
|
|
694
|
+
applyOverlayBaseStyle(this.container);
|
|
385
695
|
console.debug("[Connect SDK] endpoints", Endpoints);
|
|
386
696
|
console.log("[Connect SDK] opeining URL", Endpoints.benji_connect_auth_url);
|
|
387
697
|
const url = new URL(Endpoints.benji_connect_auth_url);
|
|
388
698
|
const connectToken = this.sdkConfig.token;
|
|
389
699
|
url.searchParams.set("connect_token", connectToken);
|
|
390
700
|
url.searchParams.set("t", String(Date.now()));
|
|
701
|
+
if (this.sdkConfig.mode != null) {
|
|
702
|
+
url.searchParams.set("mode", String(this.sdkConfig.mode));
|
|
703
|
+
}
|
|
391
704
|
this.iframe = document.createElement("iframe");
|
|
392
|
-
Object.assign(this.iframe.style, {
|
|
393
|
-
position: "relative",
|
|
394
|
-
width: "400px",
|
|
395
|
-
height: "645px",
|
|
396
|
-
border: "none",
|
|
397
|
-
borderRadius: "20px",
|
|
398
|
-
overflow: "hidden"
|
|
399
|
-
});
|
|
400
705
|
this.iframe.src = url.toString();
|
|
401
706
|
this.container.appendChild(this.iframe);
|
|
402
707
|
document.body.appendChild(this.container);
|
|
708
|
+
applyIframeLayoutToElements(
|
|
709
|
+
this.sdkConfig,
|
|
710
|
+
this.container,
|
|
711
|
+
this.iframe,
|
|
712
|
+
this.layoutState,
|
|
713
|
+
{ warnOnInvalidAnchor: true }
|
|
714
|
+
);
|
|
715
|
+
this.repositionListeners = attachRepositionListeners(
|
|
716
|
+
this.sdkConfig,
|
|
717
|
+
() => {
|
|
718
|
+
if (!this.iframe || !this.container) return;
|
|
719
|
+
applyIframeLayoutToElements(
|
|
720
|
+
this.sdkConfig,
|
|
721
|
+
this.container,
|
|
722
|
+
this.iframe,
|
|
723
|
+
this.layoutState
|
|
724
|
+
);
|
|
725
|
+
}
|
|
726
|
+
);
|
|
403
727
|
this.container.addEventListener("click", (e) => {
|
|
404
728
|
var _a, _b;
|
|
405
729
|
if (e.target === this.container) {
|
|
@@ -412,8 +736,14 @@ var ConnectSDK = (() => {
|
|
|
412
736
|
});
|
|
413
737
|
}
|
|
414
738
|
close() {
|
|
739
|
+
var _a, _b;
|
|
415
740
|
if (!this.iframe) return;
|
|
416
|
-
|
|
741
|
+
(_a = this.repositionListeners) == null ? void 0 : _a.remove();
|
|
742
|
+
this.repositionListeners = null;
|
|
743
|
+
this.layoutState.lastValidAnchoredLayout = null;
|
|
744
|
+
if ((_b = this.container) == null ? void 0 : _b.parentNode) {
|
|
745
|
+
this.container.parentNode.removeChild(this.container);
|
|
746
|
+
}
|
|
417
747
|
MessageRouter.removeEventListeners();
|
|
418
748
|
this.iframe = null;
|
|
419
749
|
this.container = null;
|