@poly-x/react 0.1.0-alpha.14 → 0.1.0-alpha.16
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/dist/index.cjs +51 -2
- package/dist/index.d.cts +64 -1
- package/dist/index.d.mts +64 -1
- package/dist/index.mjs +51 -3
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -433,6 +433,9 @@ var BffSessionStore = class {
|
|
|
433
433
|
status: "signed-out",
|
|
434
434
|
reason: "signed-out"
|
|
435
435
|
});
|
|
436
|
+
if (options?.onSignOut) try {
|
|
437
|
+
await options.onSignOut();
|
|
438
|
+
} catch {}
|
|
436
439
|
window.location.assign(options?.redirectTo ?? "/");
|
|
437
440
|
};
|
|
438
441
|
/** Null by design: under BFF custody the token never reaches the browser (FR-SES-3). */
|
|
@@ -511,6 +514,45 @@ function Protected({ children, fallback = null, loading = null }) {
|
|
|
511
514
|
return isSignedIn ? children : fallback;
|
|
512
515
|
}
|
|
513
516
|
//#endregion
|
|
517
|
+
//#region src/geolocation.ts
|
|
518
|
+
/**
|
|
519
|
+
* Capture the browser's precise location IF the user consented. Resolves to a consent-labelled
|
|
520
|
+
* result and never throws/rejects.
|
|
521
|
+
*/
|
|
522
|
+
async function capturePreciseLocation(consented, opts = {}) {
|
|
523
|
+
if (!consented) return { consent: "denied" };
|
|
524
|
+
const geo = opts.geolocation ?? (typeof navigator !== "undefined" ? navigator.geolocation : void 0);
|
|
525
|
+
if (!geo) return { consent: "denied" };
|
|
526
|
+
const timeoutMs = opts.timeoutMs ?? 8e3;
|
|
527
|
+
return new Promise((resolve) => {
|
|
528
|
+
let settled = false;
|
|
529
|
+
const done = (result) => {
|
|
530
|
+
if (settled) return;
|
|
531
|
+
settled = true;
|
|
532
|
+
resolve(result);
|
|
533
|
+
};
|
|
534
|
+
const timer = setTimeout(() => done({ consent: "denied" }), timeoutMs + 500);
|
|
535
|
+
const finish = (result) => {
|
|
536
|
+
clearTimeout(timer);
|
|
537
|
+
done(result);
|
|
538
|
+
};
|
|
539
|
+
try {
|
|
540
|
+
geo.getCurrentPosition((position) => finish({
|
|
541
|
+
latitude: String(position.coords.latitude),
|
|
542
|
+
longitude: String(position.coords.longitude),
|
|
543
|
+
accuracyMeters: typeof position.coords.accuracy === "number" ? position.coords.accuracy : void 0,
|
|
544
|
+
consent: "granted"
|
|
545
|
+
}), () => finish({ consent: "denied" }), {
|
|
546
|
+
enableHighAccuracy: true,
|
|
547
|
+
timeout: timeoutMs,
|
|
548
|
+
maximumAge: 0
|
|
549
|
+
});
|
|
550
|
+
} catch {
|
|
551
|
+
finish({ consent: "denied" });
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
//#endregion
|
|
514
556
|
//#region src/components/sign-in.tsx
|
|
515
557
|
const DEFAULT_LABELS$3 = {
|
|
516
558
|
heading: "Sign in",
|
|
@@ -670,6 +712,7 @@ function SignIn(props) {
|
|
|
670
712
|
setSubmitting(true);
|
|
671
713
|
setError(null);
|
|
672
714
|
try {
|
|
715
|
+
const geo = props.captureLocation ? await capturePreciseLocation(true) : void 0;
|
|
673
716
|
const body = await (await fetch(action, {
|
|
674
717
|
method: "POST",
|
|
675
718
|
headers: { "content-type": "application/json" },
|
|
@@ -678,6 +721,7 @@ function SignIn(props) {
|
|
|
678
721
|
password,
|
|
679
722
|
organizationCode: props.organizationCode,
|
|
680
723
|
tenantId: options.tenantId,
|
|
724
|
+
...geo ? { geo } : {},
|
|
681
725
|
...options.passwords
|
|
682
726
|
})
|
|
683
727
|
})).json().catch(() => ({}));
|
|
@@ -1684,7 +1728,10 @@ function UserButtonRoot(props) {
|
|
|
1684
1728
|
key: "signOut",
|
|
1685
1729
|
label: labels.signOut,
|
|
1686
1730
|
labelIcon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExitIcon, {}),
|
|
1687
|
-
onClick: () => void signOut({
|
|
1731
|
+
onClick: () => void signOut({
|
|
1732
|
+
redirectTo: props.afterSignOutUrl,
|
|
1733
|
+
onSignOut: props.onSignOut
|
|
1734
|
+
})
|
|
1688
1735
|
});
|
|
1689
1736
|
if (props.showSignOutEverywhere) builtIns.set("signOutEverywhere", {
|
|
1690
1737
|
key: "signOutEverywhere",
|
|
@@ -1692,7 +1739,8 @@ function UserButtonRoot(props) {
|
|
|
1692
1739
|
labelIcon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExitIcon, {}),
|
|
1693
1740
|
onClick: () => void signOut({
|
|
1694
1741
|
scope: "everywhere",
|
|
1695
|
-
redirectTo: props.afterSignOutUrl
|
|
1742
|
+
redirectTo: props.afterSignOutUrl,
|
|
1743
|
+
onSignOut: props.onSignOut
|
|
1696
1744
|
})
|
|
1697
1745
|
});
|
|
1698
1746
|
const items = resolveItems(props.children, builtIns);
|
|
@@ -1878,6 +1926,7 @@ exports.UserAvatar = UserAvatar;
|
|
|
1878
1926
|
exports.UserButton = UserButton;
|
|
1879
1927
|
exports.WebLocksLock = WebLocksLock;
|
|
1880
1928
|
exports.WindowBrowserBridge = WindowBrowserBridge;
|
|
1929
|
+
exports.capturePreciseLocation = capturePreciseLocation;
|
|
1881
1930
|
exports.createLoginController = createLoginController;
|
|
1882
1931
|
exports.initialsFrom = initialsFrom;
|
|
1883
1932
|
exports.resolveSide = resolveSide;
|
package/dist/index.d.cts
CHANGED
|
@@ -24,6 +24,13 @@ interface BffSignOutOptions {
|
|
|
24
24
|
scope?: "device" | "everywhere";
|
|
25
25
|
/** Where to land afterwards. Resolved here, client-side — the server takes no redirect target. */
|
|
26
26
|
redirectTo?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Run consumer cleanup after the session is revoked but BEFORE the post-sign-out
|
|
29
|
+
* redirect (the page is still alive at this point) — e.g. clear app cookies, reset
|
|
30
|
+
* local state, flush a store. Awaited; a thrown/rejected hook is swallowed so a
|
|
31
|
+
* failing callback can never trap the user in a signed-out-but-not-redirected state.
|
|
32
|
+
*/
|
|
33
|
+
onSignOut?: () => void | Promise<void>;
|
|
27
34
|
}
|
|
28
35
|
//#endregion
|
|
29
36
|
//#region src/auth-channel.d.ts
|
|
@@ -255,6 +262,13 @@ interface SignInProps {
|
|
|
255
262
|
* "Forgot password?" link appears under the password field. Omit to hide it.
|
|
256
263
|
*/
|
|
257
264
|
forgotPasswordUrl?: string;
|
|
265
|
+
/**
|
|
266
|
+
* v6 (FR-CNST): capture precise location for security/presence. When enabled, sign-in asks the
|
|
267
|
+
* browser for a position — the browser's own native permission prompt is the consent gate (no
|
|
268
|
+
* in-form checkbox), and it's remembered per-origin after the first choice. A block, denial, or
|
|
269
|
+
* timeout never blocks sign-in (coarse IP fallback). Off by default.
|
|
270
|
+
*/
|
|
271
|
+
captureLocation?: boolean;
|
|
258
272
|
/** Where to send the browser after success. Overrides the server's default redirect. */
|
|
259
273
|
afterSignInPath?: string;
|
|
260
274
|
/** Pre-scope the login to a single organization (skips org discovery). */
|
|
@@ -392,6 +406,49 @@ declare function AuthCallback({
|
|
|
392
406
|
children
|
|
393
407
|
}: AuthCallbackProps): ReactNode;
|
|
394
408
|
//#endregion
|
|
409
|
+
//#region src/geolocation.d.ts
|
|
410
|
+
/**
|
|
411
|
+
* @poly-x/react/geolocation — browser precise-location capture for sign-in (v6, FR-CNST/FR-LOC).
|
|
412
|
+
*
|
|
413
|
+
* The consent-gated bridge to `navigator.geolocation`. It NEVER rejects: a decline, a browser
|
|
414
|
+
* permission denial, a missing API, or a timeout all resolve to `{ consent: "denied" }` with no
|
|
415
|
+
* coordinates, so the caller can always proceed — sign-in must never block on location (D52).
|
|
416
|
+
* The captured value is posted to the BFF, which forwards it to the platform on the token
|
|
417
|
+
* exchange; the platform stores precise only when consent is `granted`, else coarse (IP).
|
|
418
|
+
*/
|
|
419
|
+
/** Minimal shape of the browser Geolocation API we depend on (injectable for testing). */
|
|
420
|
+
interface GeolocationLike {
|
|
421
|
+
getCurrentPosition(success: (position: {
|
|
422
|
+
coords: {
|
|
423
|
+
latitude: number;
|
|
424
|
+
longitude: number;
|
|
425
|
+
accuracy?: number;
|
|
426
|
+
};
|
|
427
|
+
}) => void, error?: (err: unknown) => void, options?: {
|
|
428
|
+
enableHighAccuracy?: boolean;
|
|
429
|
+
timeout?: number;
|
|
430
|
+
maximumAge?: number;
|
|
431
|
+
}): void;
|
|
432
|
+
}
|
|
433
|
+
/** The consent-labelled result of a capture attempt. Coordinates present only when granted. */
|
|
434
|
+
interface CapturedGeo {
|
|
435
|
+
latitude?: string;
|
|
436
|
+
longitude?: string;
|
|
437
|
+
accuracyMeters?: number;
|
|
438
|
+
consent: "granted" | "denied";
|
|
439
|
+
}
|
|
440
|
+
interface CaptureOptions {
|
|
441
|
+
/** Max time to wait for a fix before giving up (coarse fallback). Default 8000ms. */
|
|
442
|
+
timeoutMs?: number;
|
|
443
|
+
/** Override the geolocation source (tests). Defaults to `navigator.geolocation`. */
|
|
444
|
+
geolocation?: GeolocationLike;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Capture the browser's precise location IF the user consented. Resolves to a consent-labelled
|
|
448
|
+
* result and never throws/rejects.
|
|
449
|
+
*/
|
|
450
|
+
declare function capturePreciseLocation(consented: boolean, opts?: CaptureOptions): Promise<CapturedGeo>;
|
|
451
|
+
//#endregion
|
|
395
452
|
//#region src/components/placement.d.ts
|
|
396
453
|
/**
|
|
397
454
|
* Collision-aware placement for the SDK's popovers.
|
|
@@ -463,6 +520,12 @@ interface UserButtonProps {
|
|
|
463
520
|
showName?: boolean;
|
|
464
521
|
/** Where to land after signing out. Default the app root. */
|
|
465
522
|
afterSignOutUrl?: string;
|
|
523
|
+
/**
|
|
524
|
+
* Consumer cleanup run after the session is revoked but before the redirect —
|
|
525
|
+
* clear app cookies, reset local stores, etc. Awaited; errors are swallowed so a
|
|
526
|
+
* failing hook can't trap the user. Applies to both "Sign out" and "Sign out everywhere".
|
|
527
|
+
*/
|
|
528
|
+
onSignOut?: () => void | Promise<void>;
|
|
466
529
|
/**
|
|
467
530
|
* Destination for the "Manage account" entry. Omitted entirely when unset — PolyX has no
|
|
468
531
|
* hosted profile page, so the destination is the consumer's to own.
|
|
@@ -565,4 +628,4 @@ declare function UserAvatar({
|
|
|
565
628
|
declare const PACKAGE_NAME = "@poly-x/react";
|
|
566
629
|
declare const version = "0.0.0";
|
|
567
630
|
//#endregion
|
|
568
|
-
export { type Align, AuthCallback, type AuthCallbackMessage, type AuthCallbackProps, type AuthChannel, BroadcastAuthChannel, BroadcastChannelSessionChannel, type BrowserBridge, type CallbackParams, ForgotPassword, type ForgotPasswordLabels, type ForgotPasswordProps, type LoginController, type LoginControllerDeps, PACKAGE_NAME, PolyXContext, type PolyXContextValue, PolyXProvider, type PolyXProviderProps, PopupCancelledError, type PopupHandle, Protected, type ProtectedProps, ResetPassword, type ResetPasswordLabels, type ResetPasswordProps, SessionStoragePkceStore, type Side, type SideOption, SignIn, type SignInLabels, type SignInOptions, type SignInProps, type SignInVariant, type UseAuth, UserAvatar, type UserAvatarProps, UserButton, type UserButtonActionProps, type UserButtonLabels, type UserButtonLinkProps, type UserButtonProps, type UserButtonSlotProps, WebLocksLock, WindowBrowserBridge, createLoginController, initialsFrom, resolveSide, useAuth, useAuthCallback, useSession, useUser, version };
|
|
631
|
+
export { type Align, AuthCallback, type AuthCallbackMessage, type AuthCallbackProps, type AuthChannel, BroadcastAuthChannel, BroadcastChannelSessionChannel, type BrowserBridge, type CallbackParams, type CaptureOptions, type CapturedGeo, ForgotPassword, type ForgotPasswordLabels, type ForgotPasswordProps, type GeolocationLike, type LoginController, type LoginControllerDeps, PACKAGE_NAME, PolyXContext, type PolyXContextValue, PolyXProvider, type PolyXProviderProps, PopupCancelledError, type PopupHandle, Protected, type ProtectedProps, ResetPassword, type ResetPasswordLabels, type ResetPasswordProps, SessionStoragePkceStore, type Side, type SideOption, SignIn, type SignInLabels, type SignInOptions, type SignInProps, type SignInVariant, type UseAuth, UserAvatar, type UserAvatarProps, UserButton, type UserButtonActionProps, type UserButtonLabels, type UserButtonLinkProps, type UserButtonProps, type UserButtonSlotProps, WebLocksLock, WindowBrowserBridge, capturePreciseLocation, createLoginController, initialsFrom, resolveSide, useAuth, useAuthCallback, useSession, useUser, version };
|
package/dist/index.d.mts
CHANGED
|
@@ -24,6 +24,13 @@ interface BffSignOutOptions {
|
|
|
24
24
|
scope?: "device" | "everywhere";
|
|
25
25
|
/** Where to land afterwards. Resolved here, client-side — the server takes no redirect target. */
|
|
26
26
|
redirectTo?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Run consumer cleanup after the session is revoked but BEFORE the post-sign-out
|
|
29
|
+
* redirect (the page is still alive at this point) — e.g. clear app cookies, reset
|
|
30
|
+
* local state, flush a store. Awaited; a thrown/rejected hook is swallowed so a
|
|
31
|
+
* failing callback can never trap the user in a signed-out-but-not-redirected state.
|
|
32
|
+
*/
|
|
33
|
+
onSignOut?: () => void | Promise<void>;
|
|
27
34
|
}
|
|
28
35
|
//#endregion
|
|
29
36
|
//#region src/auth-channel.d.ts
|
|
@@ -255,6 +262,13 @@ interface SignInProps {
|
|
|
255
262
|
* "Forgot password?" link appears under the password field. Omit to hide it.
|
|
256
263
|
*/
|
|
257
264
|
forgotPasswordUrl?: string;
|
|
265
|
+
/**
|
|
266
|
+
* v6 (FR-CNST): capture precise location for security/presence. When enabled, sign-in asks the
|
|
267
|
+
* browser for a position — the browser's own native permission prompt is the consent gate (no
|
|
268
|
+
* in-form checkbox), and it's remembered per-origin after the first choice. A block, denial, or
|
|
269
|
+
* timeout never blocks sign-in (coarse IP fallback). Off by default.
|
|
270
|
+
*/
|
|
271
|
+
captureLocation?: boolean;
|
|
258
272
|
/** Where to send the browser after success. Overrides the server's default redirect. */
|
|
259
273
|
afterSignInPath?: string;
|
|
260
274
|
/** Pre-scope the login to a single organization (skips org discovery). */
|
|
@@ -392,6 +406,49 @@ declare function AuthCallback({
|
|
|
392
406
|
children
|
|
393
407
|
}: AuthCallbackProps): ReactNode;
|
|
394
408
|
//#endregion
|
|
409
|
+
//#region src/geolocation.d.ts
|
|
410
|
+
/**
|
|
411
|
+
* @poly-x/react/geolocation — browser precise-location capture for sign-in (v6, FR-CNST/FR-LOC).
|
|
412
|
+
*
|
|
413
|
+
* The consent-gated bridge to `navigator.geolocation`. It NEVER rejects: a decline, a browser
|
|
414
|
+
* permission denial, a missing API, or a timeout all resolve to `{ consent: "denied" }` with no
|
|
415
|
+
* coordinates, so the caller can always proceed — sign-in must never block on location (D52).
|
|
416
|
+
* The captured value is posted to the BFF, which forwards it to the platform on the token
|
|
417
|
+
* exchange; the platform stores precise only when consent is `granted`, else coarse (IP).
|
|
418
|
+
*/
|
|
419
|
+
/** Minimal shape of the browser Geolocation API we depend on (injectable for testing). */
|
|
420
|
+
interface GeolocationLike {
|
|
421
|
+
getCurrentPosition(success: (position: {
|
|
422
|
+
coords: {
|
|
423
|
+
latitude: number;
|
|
424
|
+
longitude: number;
|
|
425
|
+
accuracy?: number;
|
|
426
|
+
};
|
|
427
|
+
}) => void, error?: (err: unknown) => void, options?: {
|
|
428
|
+
enableHighAccuracy?: boolean;
|
|
429
|
+
timeout?: number;
|
|
430
|
+
maximumAge?: number;
|
|
431
|
+
}): void;
|
|
432
|
+
}
|
|
433
|
+
/** The consent-labelled result of a capture attempt. Coordinates present only when granted. */
|
|
434
|
+
interface CapturedGeo {
|
|
435
|
+
latitude?: string;
|
|
436
|
+
longitude?: string;
|
|
437
|
+
accuracyMeters?: number;
|
|
438
|
+
consent: "granted" | "denied";
|
|
439
|
+
}
|
|
440
|
+
interface CaptureOptions {
|
|
441
|
+
/** Max time to wait for a fix before giving up (coarse fallback). Default 8000ms. */
|
|
442
|
+
timeoutMs?: number;
|
|
443
|
+
/** Override the geolocation source (tests). Defaults to `navigator.geolocation`. */
|
|
444
|
+
geolocation?: GeolocationLike;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Capture the browser's precise location IF the user consented. Resolves to a consent-labelled
|
|
448
|
+
* result and never throws/rejects.
|
|
449
|
+
*/
|
|
450
|
+
declare function capturePreciseLocation(consented: boolean, opts?: CaptureOptions): Promise<CapturedGeo>;
|
|
451
|
+
//#endregion
|
|
395
452
|
//#region src/components/placement.d.ts
|
|
396
453
|
/**
|
|
397
454
|
* Collision-aware placement for the SDK's popovers.
|
|
@@ -463,6 +520,12 @@ interface UserButtonProps {
|
|
|
463
520
|
showName?: boolean;
|
|
464
521
|
/** Where to land after signing out. Default the app root. */
|
|
465
522
|
afterSignOutUrl?: string;
|
|
523
|
+
/**
|
|
524
|
+
* Consumer cleanup run after the session is revoked but before the redirect —
|
|
525
|
+
* clear app cookies, reset local stores, etc. Awaited; errors are swallowed so a
|
|
526
|
+
* failing hook can't trap the user. Applies to both "Sign out" and "Sign out everywhere".
|
|
527
|
+
*/
|
|
528
|
+
onSignOut?: () => void | Promise<void>;
|
|
466
529
|
/**
|
|
467
530
|
* Destination for the "Manage account" entry. Omitted entirely when unset — PolyX has no
|
|
468
531
|
* hosted profile page, so the destination is the consumer's to own.
|
|
@@ -565,4 +628,4 @@ declare function UserAvatar({
|
|
|
565
628
|
declare const PACKAGE_NAME = "@poly-x/react";
|
|
566
629
|
declare const version = "0.0.0";
|
|
567
630
|
//#endregion
|
|
568
|
-
export { type Align, AuthCallback, type AuthCallbackMessage, type AuthCallbackProps, type AuthChannel, BroadcastAuthChannel, BroadcastChannelSessionChannel, type BrowserBridge, type CallbackParams, ForgotPassword, type ForgotPasswordLabels, type ForgotPasswordProps, type LoginController, type LoginControllerDeps, PACKAGE_NAME, PolyXContext, type PolyXContextValue, PolyXProvider, type PolyXProviderProps, PopupCancelledError, type PopupHandle, Protected, type ProtectedProps, ResetPassword, type ResetPasswordLabels, type ResetPasswordProps, SessionStoragePkceStore, type Side, type SideOption, SignIn, type SignInLabels, type SignInOptions, type SignInProps, type SignInVariant, type UseAuth, UserAvatar, type UserAvatarProps, UserButton, type UserButtonActionProps, type UserButtonLabels, type UserButtonLinkProps, type UserButtonProps, type UserButtonSlotProps, WebLocksLock, WindowBrowserBridge, createLoginController, initialsFrom, resolveSide, useAuth, useAuthCallback, useSession, useUser, version };
|
|
631
|
+
export { type Align, AuthCallback, type AuthCallbackMessage, type AuthCallbackProps, type AuthChannel, BroadcastAuthChannel, BroadcastChannelSessionChannel, type BrowserBridge, type CallbackParams, type CaptureOptions, type CapturedGeo, ForgotPassword, type ForgotPasswordLabels, type ForgotPasswordProps, type GeolocationLike, type LoginController, type LoginControllerDeps, PACKAGE_NAME, PolyXContext, type PolyXContextValue, PolyXProvider, type PolyXProviderProps, PopupCancelledError, type PopupHandle, Protected, type ProtectedProps, ResetPassword, type ResetPasswordLabels, type ResetPasswordProps, SessionStoragePkceStore, type Side, type SideOption, SignIn, type SignInLabels, type SignInOptions, type SignInProps, type SignInVariant, type UseAuth, UserAvatar, type UserAvatarProps, UserButton, type UserButtonActionProps, type UserButtonLabels, type UserButtonLinkProps, type UserButtonProps, type UserButtonSlotProps, WebLocksLock, WindowBrowserBridge, capturePreciseLocation, createLoginController, initialsFrom, resolveSide, useAuth, useAuthCallback, useSession, useUser, version };
|
package/dist/index.mjs
CHANGED
|
@@ -432,6 +432,9 @@ var BffSessionStore = class {
|
|
|
432
432
|
status: "signed-out",
|
|
433
433
|
reason: "signed-out"
|
|
434
434
|
});
|
|
435
|
+
if (options?.onSignOut) try {
|
|
436
|
+
await options.onSignOut();
|
|
437
|
+
} catch {}
|
|
435
438
|
window.location.assign(options?.redirectTo ?? "/");
|
|
436
439
|
};
|
|
437
440
|
/** Null by design: under BFF custody the token never reaches the browser (FR-SES-3). */
|
|
@@ -510,6 +513,45 @@ function Protected({ children, fallback = null, loading = null }) {
|
|
|
510
513
|
return isSignedIn ? children : fallback;
|
|
511
514
|
}
|
|
512
515
|
//#endregion
|
|
516
|
+
//#region src/geolocation.ts
|
|
517
|
+
/**
|
|
518
|
+
* Capture the browser's precise location IF the user consented. Resolves to a consent-labelled
|
|
519
|
+
* result and never throws/rejects.
|
|
520
|
+
*/
|
|
521
|
+
async function capturePreciseLocation(consented, opts = {}) {
|
|
522
|
+
if (!consented) return { consent: "denied" };
|
|
523
|
+
const geo = opts.geolocation ?? (typeof navigator !== "undefined" ? navigator.geolocation : void 0);
|
|
524
|
+
if (!geo) return { consent: "denied" };
|
|
525
|
+
const timeoutMs = opts.timeoutMs ?? 8e3;
|
|
526
|
+
return new Promise((resolve) => {
|
|
527
|
+
let settled = false;
|
|
528
|
+
const done = (result) => {
|
|
529
|
+
if (settled) return;
|
|
530
|
+
settled = true;
|
|
531
|
+
resolve(result);
|
|
532
|
+
};
|
|
533
|
+
const timer = setTimeout(() => done({ consent: "denied" }), timeoutMs + 500);
|
|
534
|
+
const finish = (result) => {
|
|
535
|
+
clearTimeout(timer);
|
|
536
|
+
done(result);
|
|
537
|
+
};
|
|
538
|
+
try {
|
|
539
|
+
geo.getCurrentPosition((position) => finish({
|
|
540
|
+
latitude: String(position.coords.latitude),
|
|
541
|
+
longitude: String(position.coords.longitude),
|
|
542
|
+
accuracyMeters: typeof position.coords.accuracy === "number" ? position.coords.accuracy : void 0,
|
|
543
|
+
consent: "granted"
|
|
544
|
+
}), () => finish({ consent: "denied" }), {
|
|
545
|
+
enableHighAccuracy: true,
|
|
546
|
+
timeout: timeoutMs,
|
|
547
|
+
maximumAge: 0
|
|
548
|
+
});
|
|
549
|
+
} catch {
|
|
550
|
+
finish({ consent: "denied" });
|
|
551
|
+
}
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
//#endregion
|
|
513
555
|
//#region src/components/sign-in.tsx
|
|
514
556
|
const DEFAULT_LABELS$3 = {
|
|
515
557
|
heading: "Sign in",
|
|
@@ -669,6 +711,7 @@ function SignIn(props) {
|
|
|
669
711
|
setSubmitting(true);
|
|
670
712
|
setError(null);
|
|
671
713
|
try {
|
|
714
|
+
const geo = props.captureLocation ? await capturePreciseLocation(true) : void 0;
|
|
672
715
|
const body = await (await fetch(action, {
|
|
673
716
|
method: "POST",
|
|
674
717
|
headers: { "content-type": "application/json" },
|
|
@@ -677,6 +720,7 @@ function SignIn(props) {
|
|
|
677
720
|
password,
|
|
678
721
|
organizationCode: props.organizationCode,
|
|
679
722
|
tenantId: options.tenantId,
|
|
723
|
+
...geo ? { geo } : {},
|
|
680
724
|
...options.passwords
|
|
681
725
|
})
|
|
682
726
|
})).json().catch(() => ({}));
|
|
@@ -1683,7 +1727,10 @@ function UserButtonRoot(props) {
|
|
|
1683
1727
|
key: "signOut",
|
|
1684
1728
|
label: labels.signOut,
|
|
1685
1729
|
labelIcon: /* @__PURE__ */ jsx(ExitIcon, {}),
|
|
1686
|
-
onClick: () => void signOut({
|
|
1730
|
+
onClick: () => void signOut({
|
|
1731
|
+
redirectTo: props.afterSignOutUrl,
|
|
1732
|
+
onSignOut: props.onSignOut
|
|
1733
|
+
})
|
|
1687
1734
|
});
|
|
1688
1735
|
if (props.showSignOutEverywhere) builtIns.set("signOutEverywhere", {
|
|
1689
1736
|
key: "signOutEverywhere",
|
|
@@ -1691,7 +1738,8 @@ function UserButtonRoot(props) {
|
|
|
1691
1738
|
labelIcon: /* @__PURE__ */ jsx(ExitIcon, {}),
|
|
1692
1739
|
onClick: () => void signOut({
|
|
1693
1740
|
scope: "everywhere",
|
|
1694
|
-
redirectTo: props.afterSignOutUrl
|
|
1741
|
+
redirectTo: props.afterSignOutUrl,
|
|
1742
|
+
onSignOut: props.onSignOut
|
|
1695
1743
|
})
|
|
1696
1744
|
});
|
|
1697
1745
|
const items = resolveItems(props.children, builtIns);
|
|
@@ -1861,4 +1909,4 @@ const UserButton = Object.assign(UserButtonRoot, {
|
|
|
1861
1909
|
const PACKAGE_NAME = "@poly-x/react";
|
|
1862
1910
|
const version = "0.0.0";
|
|
1863
1911
|
//#endregion
|
|
1864
|
-
export { AuthCallback, BroadcastAuthChannel, BroadcastChannelSessionChannel, ForgotPassword, PACKAGE_NAME, PolyXContext, PolyXProvider, PopupCancelledError, Protected, ResetPassword, SessionStoragePkceStore, SignIn, UserAvatar, UserButton, WebLocksLock, WindowBrowserBridge, createLoginController, initialsFrom, resolveSide, useAuth, useAuthCallback, useSession, useUser, version };
|
|
1912
|
+
export { AuthCallback, BroadcastAuthChannel, BroadcastChannelSessionChannel, ForgotPassword, PACKAGE_NAME, PolyXContext, PolyXProvider, PopupCancelledError, Protected, ResetPassword, SessionStoragePkceStore, SignIn, UserAvatar, UserButton, WebLocksLock, WindowBrowserBridge, capturePreciseLocation, createLoginController, initialsFrom, resolveSide, useAuth, useAuthCallback, useSession, useUser, version };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@poly-x/react",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.16",
|
|
4
4
|
"description": "PolyX SDK for React SPAs - provider, hooks, drop-in auth UI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"module": "./dist/index.mjs",
|
|
28
28
|
"types": "./dist/index.d.cts",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@poly-x/core": "0.1.0-alpha.
|
|
30
|
+
"@poly-x/core": "0.1.0-alpha.16"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"react": ">=18",
|