@poly-x/react 0.1.0-alpha.2 → 0.1.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +97 -61
- package/dist/index.d.cts +19 -2
- package/dist/index.d.mts +19 -2
- package/dist/index.mjs +97 -61
- package/dist/styles.css +274 -0
- package/package.json +8 -5
package/dist/index.cjs
CHANGED
|
@@ -353,11 +353,16 @@ function Protected({ children, fallback = null, loading = null }) {
|
|
|
353
353
|
//#endregion
|
|
354
354
|
//#region src/components/sign-in.tsx
|
|
355
355
|
const DEFAULT_LABELS = {
|
|
356
|
+
heading: "Sign in",
|
|
357
|
+
subheading: "Enter your credentials to continue.",
|
|
356
358
|
emailLabel: "Email",
|
|
359
|
+
emailPlaceholder: "you@company.com",
|
|
357
360
|
passwordLabel: "Password",
|
|
361
|
+
passwordPlaceholder: "••••••••",
|
|
358
362
|
submit: "Sign in",
|
|
359
363
|
submitting: "Signing in…",
|
|
360
364
|
chooseWorkspace: "Choose a workspace",
|
|
365
|
+
chooseWorkspaceSubheading: "You have access to more than one workspace.",
|
|
361
366
|
invalidCredentials: "Invalid email or password.",
|
|
362
367
|
noAccess: "You don't have access to this application.",
|
|
363
368
|
passwordChangeRequired: "You must reset your password before you can sign in.",
|
|
@@ -369,9 +374,13 @@ const DEFAULT_LABELS = {
|
|
|
369
374
|
* runs the credential authorize server-side and seals an httpOnly session — no
|
|
370
375
|
* redirect to a hosted PolyX login page, no tokens or credentials in the browser
|
|
371
376
|
* after submit. Handles the workspace picker (select_tenant) inline.
|
|
377
|
+
*
|
|
378
|
+
* Ships styled: `import "@poly-x/react/styles.css"` once, then theme it by
|
|
379
|
+
* overriding the `--polyx-*` custom properties on any ancestor.
|
|
372
380
|
*/
|
|
373
381
|
function SignIn(props) {
|
|
374
382
|
const action = props.action ?? "/api/polyx/authenticate";
|
|
383
|
+
const variant = props.variant ?? "card";
|
|
375
384
|
const labels = {
|
|
376
385
|
...DEFAULT_LABELS,
|
|
377
386
|
...props.labels
|
|
@@ -426,73 +435,100 @@ function SignIn(props) {
|
|
|
426
435
|
event.preventDefault();
|
|
427
436
|
authenticate();
|
|
428
437
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
438
|
+
const rootClass = [
|
|
439
|
+
"polyx-signin",
|
|
440
|
+
`polyx-signin--${variant}`,
|
|
441
|
+
props.className
|
|
442
|
+
].filter(Boolean).join(" ");
|
|
443
|
+
const picking = tenants !== null;
|
|
444
|
+
const header = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
445
|
+
className: "polyx-signin__header",
|
|
432
446
|
children: [
|
|
433
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
447
|
+
props.logo ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
448
|
+
className: "polyx-signin__logo",
|
|
449
|
+
children: props.logo
|
|
450
|
+
}) : null,
|
|
451
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
|
|
434
452
|
className: "polyx-signin__heading",
|
|
435
|
-
children: labels.chooseWorkspace
|
|
436
|
-
}),
|
|
437
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
438
|
-
className: "polyx-signin__tenants",
|
|
439
|
-
children: tenants.map((tenant) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
440
|
-
type: "button",
|
|
441
|
-
className: "polyx-signin__tenant",
|
|
442
|
-
disabled: submitting,
|
|
443
|
-
onClick: () => void authenticate(tenant.tenantId),
|
|
444
|
-
children: tenant.name ?? tenant.slug ?? tenant.organizationCode ?? tenant.tenantId
|
|
445
|
-
}) }, tenant.tenantId))
|
|
453
|
+
children: picking ? labels.chooseWorkspace : labels.heading
|
|
446
454
|
}),
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
children: error
|
|
451
|
-
}) : null
|
|
452
|
-
]
|
|
453
|
-
});
|
|
454
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
|
|
455
|
-
className: props.className,
|
|
456
|
-
"data-polyx-signin": "credentials",
|
|
457
|
-
onSubmit,
|
|
458
|
-
children: [
|
|
459
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
460
|
-
className: "polyx-signin__field",
|
|
461
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: labels.emailLabel }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
462
|
-
type: "email",
|
|
463
|
-
name: "email",
|
|
464
|
-
autoComplete: "username",
|
|
465
|
-
required: true,
|
|
466
|
-
value: email,
|
|
467
|
-
disabled: submitting,
|
|
468
|
-
onChange: (event) => setEmail(event.target.value)
|
|
469
|
-
})]
|
|
470
|
-
}),
|
|
471
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
472
|
-
className: "polyx-signin__field",
|
|
473
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: labels.passwordLabel }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
474
|
-
type: "password",
|
|
475
|
-
name: "password",
|
|
476
|
-
autoComplete: "current-password",
|
|
477
|
-
required: true,
|
|
478
|
-
value: password,
|
|
479
|
-
disabled: submitting,
|
|
480
|
-
onChange: (event) => setPassword(event.target.value)
|
|
481
|
-
})]
|
|
482
|
-
}),
|
|
483
|
-
error ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
484
|
-
role: "alert",
|
|
485
|
-
className: "polyx-signin__error",
|
|
486
|
-
children: error
|
|
487
|
-
}) : null,
|
|
488
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
489
|
-
type: "submit",
|
|
490
|
-
className: "polyx-signin__submit",
|
|
491
|
-
disabled: submitting,
|
|
492
|
-
children: submitting ? labels.submitting : labels.submit
|
|
455
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
456
|
+
className: "polyx-signin__subheading",
|
|
457
|
+
children: picking ? labels.chooseWorkspaceSubheading : labels.subheading
|
|
493
458
|
})
|
|
494
459
|
]
|
|
495
460
|
});
|
|
461
|
+
const errorNode = error ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
462
|
+
role: "alert",
|
|
463
|
+
className: "polyx-signin__error",
|
|
464
|
+
children: error
|
|
465
|
+
}) : null;
|
|
466
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
467
|
+
className: rootClass,
|
|
468
|
+
"data-polyx-signin": picking ? "select-tenant" : "credentials",
|
|
469
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
470
|
+
className: "polyx-signin__card",
|
|
471
|
+
children: [header, picking ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
472
|
+
className: "polyx-signin__form",
|
|
473
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
474
|
+
className: "polyx-signin__tenants",
|
|
475
|
+
children: tenants.map((tenant) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
476
|
+
type: "button",
|
|
477
|
+
className: "polyx-signin__tenant",
|
|
478
|
+
disabled: submitting,
|
|
479
|
+
onClick: () => void authenticate(tenant.tenantId),
|
|
480
|
+
children: tenant.name ?? tenant.slug ?? tenant.organizationCode ?? tenant.tenantId
|
|
481
|
+
}) }, tenant.tenantId))
|
|
482
|
+
}), errorNode]
|
|
483
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
|
|
484
|
+
className: "polyx-signin__form",
|
|
485
|
+
onSubmit,
|
|
486
|
+
children: [
|
|
487
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
488
|
+
className: "polyx-signin__field",
|
|
489
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
490
|
+
className: "polyx-signin__label",
|
|
491
|
+
children: labels.emailLabel
|
|
492
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
493
|
+
className: "polyx-signin__input",
|
|
494
|
+
type: "email",
|
|
495
|
+
name: "email",
|
|
496
|
+
autoComplete: "username",
|
|
497
|
+
placeholder: labels.emailPlaceholder,
|
|
498
|
+
required: true,
|
|
499
|
+
value: email,
|
|
500
|
+
disabled: submitting,
|
|
501
|
+
onChange: (event) => setEmail(event.target.value)
|
|
502
|
+
})]
|
|
503
|
+
}),
|
|
504
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
505
|
+
className: "polyx-signin__field",
|
|
506
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
507
|
+
className: "polyx-signin__label",
|
|
508
|
+
children: labels.passwordLabel
|
|
509
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
510
|
+
className: "polyx-signin__input",
|
|
511
|
+
type: "password",
|
|
512
|
+
name: "password",
|
|
513
|
+
autoComplete: "current-password",
|
|
514
|
+
placeholder: labels.passwordPlaceholder,
|
|
515
|
+
required: true,
|
|
516
|
+
value: password,
|
|
517
|
+
disabled: submitting,
|
|
518
|
+
onChange: (event) => setPassword(event.target.value)
|
|
519
|
+
})]
|
|
520
|
+
}),
|
|
521
|
+
errorNode,
|
|
522
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
523
|
+
type: "submit",
|
|
524
|
+
className: "polyx-signin__submit",
|
|
525
|
+
disabled: submitting,
|
|
526
|
+
children: submitting ? labels.submitting : labels.submit
|
|
527
|
+
})
|
|
528
|
+
]
|
|
529
|
+
})]
|
|
530
|
+
})
|
|
531
|
+
});
|
|
496
532
|
}
|
|
497
533
|
//#endregion
|
|
498
534
|
//#region src/components/auth-callback.tsx
|
package/dist/index.d.cts
CHANGED
|
@@ -193,24 +193,38 @@ declare function Protected({
|
|
|
193
193
|
//#region src/components/sign-in.d.ts
|
|
194
194
|
/** Every user-facing string, overridable for i18n / white-labelling. */
|
|
195
195
|
interface SignInLabels {
|
|
196
|
+
heading: string;
|
|
197
|
+
subheading: string;
|
|
196
198
|
emailLabel: string;
|
|
199
|
+
emailPlaceholder: string;
|
|
197
200
|
passwordLabel: string;
|
|
201
|
+
passwordPlaceholder: string;
|
|
198
202
|
submit: string;
|
|
199
203
|
submitting: string;
|
|
200
204
|
chooseWorkspace: string;
|
|
205
|
+
chooseWorkspaceSubheading: string;
|
|
201
206
|
invalidCredentials: string;
|
|
202
207
|
noAccess: string;
|
|
203
208
|
passwordChangeRequired: string;
|
|
204
209
|
genericError: string;
|
|
205
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* `card` renders just the card — drop it into your own layout.
|
|
213
|
+
* `page` owns the viewport — a centered card on a full-bleed background.
|
|
214
|
+
*/
|
|
215
|
+
type SignInVariant = "card" | "page";
|
|
206
216
|
interface SignInProps {
|
|
217
|
+
/** Layout preset. Default `card`. */
|
|
218
|
+
variant?: SignInVariant;
|
|
207
219
|
/** BFF endpoint backed by `createAuthHandlers().authenticate`. Default `/api/polyx/authenticate`. */
|
|
208
220
|
action?: string;
|
|
209
221
|
/** Where to send the browser after success. Overrides the server's default redirect. */
|
|
210
222
|
afterSignInPath?: string;
|
|
211
223
|
/** Pre-scope the login to a single organization (skips org discovery). */
|
|
212
224
|
organizationCode?: string;
|
|
213
|
-
/**
|
|
225
|
+
/** Rendered above the heading — your wordmark or logo. */
|
|
226
|
+
logo?: ReactNode;
|
|
227
|
+
/** Appended to the root element's class list, for escape-hatch styling. */
|
|
214
228
|
className?: string;
|
|
215
229
|
labels?: Partial<SignInLabels>;
|
|
216
230
|
/** Fired when the backend requires the user to set a new password before continuing. */
|
|
@@ -222,6 +236,9 @@ interface SignInProps {
|
|
|
222
236
|
* runs the credential authorize server-side and seals an httpOnly session — no
|
|
223
237
|
* redirect to a hosted PolyX login page, no tokens or credentials in the browser
|
|
224
238
|
* after submit. Handles the workspace picker (select_tenant) inline.
|
|
239
|
+
*
|
|
240
|
+
* Ships styled: `import "@poly-x/react/styles.css"` once, then theme it by
|
|
241
|
+
* overriding the `--polyx-*` custom properties on any ancestor.
|
|
225
242
|
*/
|
|
226
243
|
declare function SignIn(props: SignInProps): ReactNode;
|
|
227
244
|
//#endregion
|
|
@@ -243,4 +260,4 @@ declare function AuthCallback({
|
|
|
243
260
|
declare const PACKAGE_NAME = "@poly-x/react";
|
|
244
261
|
declare const version = "0.0.0";
|
|
245
262
|
//#endregion
|
|
246
|
-
export { AuthCallback, type AuthCallbackMessage, type AuthCallbackProps, type AuthChannel, BroadcastAuthChannel, BroadcastChannelSessionChannel, type BrowserBridge, type CallbackParams, type LoginController, type LoginControllerDeps, PACKAGE_NAME, PolyXContext, type PolyXContextValue, PolyXProvider, type PolyXProviderProps, PopupCancelledError, type PopupHandle, Protected, type ProtectedProps, SessionStoragePkceStore, SignIn, type SignInLabels, type SignInOptions, type SignInProps, type UseAuth, WebLocksLock, WindowBrowserBridge, createLoginController, useAuth, useAuthCallback, useSession, useUser, version };
|
|
263
|
+
export { AuthCallback, type AuthCallbackMessage, type AuthCallbackProps, type AuthChannel, BroadcastAuthChannel, BroadcastChannelSessionChannel, type BrowserBridge, type CallbackParams, type LoginController, type LoginControllerDeps, PACKAGE_NAME, PolyXContext, type PolyXContextValue, PolyXProvider, type PolyXProviderProps, PopupCancelledError, type PopupHandle, Protected, type ProtectedProps, SessionStoragePkceStore, SignIn, type SignInLabels, type SignInOptions, type SignInProps, type SignInVariant, type UseAuth, WebLocksLock, WindowBrowserBridge, createLoginController, useAuth, useAuthCallback, useSession, useUser, version };
|
package/dist/index.d.mts
CHANGED
|
@@ -193,24 +193,38 @@ declare function Protected({
|
|
|
193
193
|
//#region src/components/sign-in.d.ts
|
|
194
194
|
/** Every user-facing string, overridable for i18n / white-labelling. */
|
|
195
195
|
interface SignInLabels {
|
|
196
|
+
heading: string;
|
|
197
|
+
subheading: string;
|
|
196
198
|
emailLabel: string;
|
|
199
|
+
emailPlaceholder: string;
|
|
197
200
|
passwordLabel: string;
|
|
201
|
+
passwordPlaceholder: string;
|
|
198
202
|
submit: string;
|
|
199
203
|
submitting: string;
|
|
200
204
|
chooseWorkspace: string;
|
|
205
|
+
chooseWorkspaceSubheading: string;
|
|
201
206
|
invalidCredentials: string;
|
|
202
207
|
noAccess: string;
|
|
203
208
|
passwordChangeRequired: string;
|
|
204
209
|
genericError: string;
|
|
205
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* `card` renders just the card — drop it into your own layout.
|
|
213
|
+
* `page` owns the viewport — a centered card on a full-bleed background.
|
|
214
|
+
*/
|
|
215
|
+
type SignInVariant = "card" | "page";
|
|
206
216
|
interface SignInProps {
|
|
217
|
+
/** Layout preset. Default `card`. */
|
|
218
|
+
variant?: SignInVariant;
|
|
207
219
|
/** BFF endpoint backed by `createAuthHandlers().authenticate`. Default `/api/polyx/authenticate`. */
|
|
208
220
|
action?: string;
|
|
209
221
|
/** Where to send the browser after success. Overrides the server's default redirect. */
|
|
210
222
|
afterSignInPath?: string;
|
|
211
223
|
/** Pre-scope the login to a single organization (skips org discovery). */
|
|
212
224
|
organizationCode?: string;
|
|
213
|
-
/**
|
|
225
|
+
/** Rendered above the heading — your wordmark or logo. */
|
|
226
|
+
logo?: ReactNode;
|
|
227
|
+
/** Appended to the root element's class list, for escape-hatch styling. */
|
|
214
228
|
className?: string;
|
|
215
229
|
labels?: Partial<SignInLabels>;
|
|
216
230
|
/** Fired when the backend requires the user to set a new password before continuing. */
|
|
@@ -222,6 +236,9 @@ interface SignInProps {
|
|
|
222
236
|
* runs the credential authorize server-side and seals an httpOnly session — no
|
|
223
237
|
* redirect to a hosted PolyX login page, no tokens or credentials in the browser
|
|
224
238
|
* after submit. Handles the workspace picker (select_tenant) inline.
|
|
239
|
+
*
|
|
240
|
+
* Ships styled: `import "@poly-x/react/styles.css"` once, then theme it by
|
|
241
|
+
* overriding the `--polyx-*` custom properties on any ancestor.
|
|
225
242
|
*/
|
|
226
243
|
declare function SignIn(props: SignInProps): ReactNode;
|
|
227
244
|
//#endregion
|
|
@@ -243,4 +260,4 @@ declare function AuthCallback({
|
|
|
243
260
|
declare const PACKAGE_NAME = "@poly-x/react";
|
|
244
261
|
declare const version = "0.0.0";
|
|
245
262
|
//#endregion
|
|
246
|
-
export { AuthCallback, type AuthCallbackMessage, type AuthCallbackProps, type AuthChannel, BroadcastAuthChannel, BroadcastChannelSessionChannel, type BrowserBridge, type CallbackParams, type LoginController, type LoginControllerDeps, PACKAGE_NAME, PolyXContext, type PolyXContextValue, PolyXProvider, type PolyXProviderProps, PopupCancelledError, type PopupHandle, Protected, type ProtectedProps, SessionStoragePkceStore, SignIn, type SignInLabels, type SignInOptions, type SignInProps, type UseAuth, WebLocksLock, WindowBrowserBridge, createLoginController, useAuth, useAuthCallback, useSession, useUser, version };
|
|
263
|
+
export { AuthCallback, type AuthCallbackMessage, type AuthCallbackProps, type AuthChannel, BroadcastAuthChannel, BroadcastChannelSessionChannel, type BrowserBridge, type CallbackParams, type LoginController, type LoginControllerDeps, PACKAGE_NAME, PolyXContext, type PolyXContextValue, PolyXProvider, type PolyXProviderProps, PopupCancelledError, type PopupHandle, Protected, type ProtectedProps, SessionStoragePkceStore, SignIn, type SignInLabels, type SignInOptions, type SignInProps, type SignInVariant, type UseAuth, WebLocksLock, WindowBrowserBridge, createLoginController, useAuth, useAuthCallback, useSession, useUser, version };
|
package/dist/index.mjs
CHANGED
|
@@ -352,11 +352,16 @@ function Protected({ children, fallback = null, loading = null }) {
|
|
|
352
352
|
//#endregion
|
|
353
353
|
//#region src/components/sign-in.tsx
|
|
354
354
|
const DEFAULT_LABELS = {
|
|
355
|
+
heading: "Sign in",
|
|
356
|
+
subheading: "Enter your credentials to continue.",
|
|
355
357
|
emailLabel: "Email",
|
|
358
|
+
emailPlaceholder: "you@company.com",
|
|
356
359
|
passwordLabel: "Password",
|
|
360
|
+
passwordPlaceholder: "••••••••",
|
|
357
361
|
submit: "Sign in",
|
|
358
362
|
submitting: "Signing in…",
|
|
359
363
|
chooseWorkspace: "Choose a workspace",
|
|
364
|
+
chooseWorkspaceSubheading: "You have access to more than one workspace.",
|
|
360
365
|
invalidCredentials: "Invalid email or password.",
|
|
361
366
|
noAccess: "You don't have access to this application.",
|
|
362
367
|
passwordChangeRequired: "You must reset your password before you can sign in.",
|
|
@@ -368,9 +373,13 @@ const DEFAULT_LABELS = {
|
|
|
368
373
|
* runs the credential authorize server-side and seals an httpOnly session — no
|
|
369
374
|
* redirect to a hosted PolyX login page, no tokens or credentials in the browser
|
|
370
375
|
* after submit. Handles the workspace picker (select_tenant) inline.
|
|
376
|
+
*
|
|
377
|
+
* Ships styled: `import "@poly-x/react/styles.css"` once, then theme it by
|
|
378
|
+
* overriding the `--polyx-*` custom properties on any ancestor.
|
|
371
379
|
*/
|
|
372
380
|
function SignIn(props) {
|
|
373
381
|
const action = props.action ?? "/api/polyx/authenticate";
|
|
382
|
+
const variant = props.variant ?? "card";
|
|
374
383
|
const labels = {
|
|
375
384
|
...DEFAULT_LABELS,
|
|
376
385
|
...props.labels
|
|
@@ -425,73 +434,100 @@ function SignIn(props) {
|
|
|
425
434
|
event.preventDefault();
|
|
426
435
|
authenticate();
|
|
427
436
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
437
|
+
const rootClass = [
|
|
438
|
+
"polyx-signin",
|
|
439
|
+
`polyx-signin--${variant}`,
|
|
440
|
+
props.className
|
|
441
|
+
].filter(Boolean).join(" ");
|
|
442
|
+
const picking = tenants !== null;
|
|
443
|
+
const header = /* @__PURE__ */ jsxs("div", {
|
|
444
|
+
className: "polyx-signin__header",
|
|
431
445
|
children: [
|
|
432
|
-
/* @__PURE__ */ jsx("
|
|
446
|
+
props.logo ? /* @__PURE__ */ jsx("div", {
|
|
447
|
+
className: "polyx-signin__logo",
|
|
448
|
+
children: props.logo
|
|
449
|
+
}) : null,
|
|
450
|
+
/* @__PURE__ */ jsx("h1", {
|
|
433
451
|
className: "polyx-signin__heading",
|
|
434
|
-
children: labels.chooseWorkspace
|
|
435
|
-
}),
|
|
436
|
-
/* @__PURE__ */ jsx("ul", {
|
|
437
|
-
className: "polyx-signin__tenants",
|
|
438
|
-
children: tenants.map((tenant) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("button", {
|
|
439
|
-
type: "button",
|
|
440
|
-
className: "polyx-signin__tenant",
|
|
441
|
-
disabled: submitting,
|
|
442
|
-
onClick: () => void authenticate(tenant.tenantId),
|
|
443
|
-
children: tenant.name ?? tenant.slug ?? tenant.organizationCode ?? tenant.tenantId
|
|
444
|
-
}) }, tenant.tenantId))
|
|
452
|
+
children: picking ? labels.chooseWorkspace : labels.heading
|
|
445
453
|
}),
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
children: error
|
|
450
|
-
}) : null
|
|
451
|
-
]
|
|
452
|
-
});
|
|
453
|
-
return /* @__PURE__ */ jsxs("form", {
|
|
454
|
-
className: props.className,
|
|
455
|
-
"data-polyx-signin": "credentials",
|
|
456
|
-
onSubmit,
|
|
457
|
-
children: [
|
|
458
|
-
/* @__PURE__ */ jsxs("label", {
|
|
459
|
-
className: "polyx-signin__field",
|
|
460
|
-
children: [/* @__PURE__ */ jsx("span", { children: labels.emailLabel }), /* @__PURE__ */ jsx("input", {
|
|
461
|
-
type: "email",
|
|
462
|
-
name: "email",
|
|
463
|
-
autoComplete: "username",
|
|
464
|
-
required: true,
|
|
465
|
-
value: email,
|
|
466
|
-
disabled: submitting,
|
|
467
|
-
onChange: (event) => setEmail(event.target.value)
|
|
468
|
-
})]
|
|
469
|
-
}),
|
|
470
|
-
/* @__PURE__ */ jsxs("label", {
|
|
471
|
-
className: "polyx-signin__field",
|
|
472
|
-
children: [/* @__PURE__ */ jsx("span", { children: labels.passwordLabel }), /* @__PURE__ */ jsx("input", {
|
|
473
|
-
type: "password",
|
|
474
|
-
name: "password",
|
|
475
|
-
autoComplete: "current-password",
|
|
476
|
-
required: true,
|
|
477
|
-
value: password,
|
|
478
|
-
disabled: submitting,
|
|
479
|
-
onChange: (event) => setPassword(event.target.value)
|
|
480
|
-
})]
|
|
481
|
-
}),
|
|
482
|
-
error ? /* @__PURE__ */ jsx("p", {
|
|
483
|
-
role: "alert",
|
|
484
|
-
className: "polyx-signin__error",
|
|
485
|
-
children: error
|
|
486
|
-
}) : null,
|
|
487
|
-
/* @__PURE__ */ jsx("button", {
|
|
488
|
-
type: "submit",
|
|
489
|
-
className: "polyx-signin__submit",
|
|
490
|
-
disabled: submitting,
|
|
491
|
-
children: submitting ? labels.submitting : labels.submit
|
|
454
|
+
/* @__PURE__ */ jsx("p", {
|
|
455
|
+
className: "polyx-signin__subheading",
|
|
456
|
+
children: picking ? labels.chooseWorkspaceSubheading : labels.subheading
|
|
492
457
|
})
|
|
493
458
|
]
|
|
494
459
|
});
|
|
460
|
+
const errorNode = error ? /* @__PURE__ */ jsx("p", {
|
|
461
|
+
role: "alert",
|
|
462
|
+
className: "polyx-signin__error",
|
|
463
|
+
children: error
|
|
464
|
+
}) : null;
|
|
465
|
+
return /* @__PURE__ */ jsx("div", {
|
|
466
|
+
className: rootClass,
|
|
467
|
+
"data-polyx-signin": picking ? "select-tenant" : "credentials",
|
|
468
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
469
|
+
className: "polyx-signin__card",
|
|
470
|
+
children: [header, picking ? /* @__PURE__ */ jsxs("div", {
|
|
471
|
+
className: "polyx-signin__form",
|
|
472
|
+
children: [/* @__PURE__ */ jsx("ul", {
|
|
473
|
+
className: "polyx-signin__tenants",
|
|
474
|
+
children: tenants.map((tenant) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("button", {
|
|
475
|
+
type: "button",
|
|
476
|
+
className: "polyx-signin__tenant",
|
|
477
|
+
disabled: submitting,
|
|
478
|
+
onClick: () => void authenticate(tenant.tenantId),
|
|
479
|
+
children: tenant.name ?? tenant.slug ?? tenant.organizationCode ?? tenant.tenantId
|
|
480
|
+
}) }, tenant.tenantId))
|
|
481
|
+
}), errorNode]
|
|
482
|
+
}) : /* @__PURE__ */ jsxs("form", {
|
|
483
|
+
className: "polyx-signin__form",
|
|
484
|
+
onSubmit,
|
|
485
|
+
children: [
|
|
486
|
+
/* @__PURE__ */ jsxs("label", {
|
|
487
|
+
className: "polyx-signin__field",
|
|
488
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
489
|
+
className: "polyx-signin__label",
|
|
490
|
+
children: labels.emailLabel
|
|
491
|
+
}), /* @__PURE__ */ jsx("input", {
|
|
492
|
+
className: "polyx-signin__input",
|
|
493
|
+
type: "email",
|
|
494
|
+
name: "email",
|
|
495
|
+
autoComplete: "username",
|
|
496
|
+
placeholder: labels.emailPlaceholder,
|
|
497
|
+
required: true,
|
|
498
|
+
value: email,
|
|
499
|
+
disabled: submitting,
|
|
500
|
+
onChange: (event) => setEmail(event.target.value)
|
|
501
|
+
})]
|
|
502
|
+
}),
|
|
503
|
+
/* @__PURE__ */ jsxs("label", {
|
|
504
|
+
className: "polyx-signin__field",
|
|
505
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
506
|
+
className: "polyx-signin__label",
|
|
507
|
+
children: labels.passwordLabel
|
|
508
|
+
}), /* @__PURE__ */ jsx("input", {
|
|
509
|
+
className: "polyx-signin__input",
|
|
510
|
+
type: "password",
|
|
511
|
+
name: "password",
|
|
512
|
+
autoComplete: "current-password",
|
|
513
|
+
placeholder: labels.passwordPlaceholder,
|
|
514
|
+
required: true,
|
|
515
|
+
value: password,
|
|
516
|
+
disabled: submitting,
|
|
517
|
+
onChange: (event) => setPassword(event.target.value)
|
|
518
|
+
})]
|
|
519
|
+
}),
|
|
520
|
+
errorNode,
|
|
521
|
+
/* @__PURE__ */ jsx("button", {
|
|
522
|
+
type: "submit",
|
|
523
|
+
className: "polyx-signin__submit",
|
|
524
|
+
disabled: submitting,
|
|
525
|
+
children: submitting ? labels.submitting : labels.submit
|
|
526
|
+
})
|
|
527
|
+
]
|
|
528
|
+
})]
|
|
529
|
+
})
|
|
530
|
+
});
|
|
495
531
|
}
|
|
496
532
|
//#endregion
|
|
497
533
|
//#region src/components/auth-callback.tsx
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @poly-x/react — default component styles.
|
|
3
|
+
*
|
|
4
|
+
* Import once, near the root of your app:
|
|
5
|
+
* import "@poly-x/react/styles.css"; // or "@poly-x/next/styles.css"
|
|
6
|
+
*
|
|
7
|
+
* The SDK is a guest in your app: every rule is scoped under a `.polyx-*` class,
|
|
8
|
+
* there are no global element selectors, and nothing here leaks into your own
|
|
9
|
+
* markup. To theme it, override the custom properties below on any ancestor
|
|
10
|
+
* (`:root`, a wrapper div, …) — that is the supported theming surface. Dark mode
|
|
11
|
+
* follows the OS by default and defers to an explicit `.dark` / `[data-theme]`
|
|
12
|
+
* on a host ancestor when one is present.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
.polyx-signin {
|
|
16
|
+
/* Colors */
|
|
17
|
+
--polyx-brand: #4f46e5;
|
|
18
|
+
--polyx-brand-hover: #4338ca;
|
|
19
|
+
--polyx-brand-fg: #ffffff;
|
|
20
|
+
--polyx-bg: #ffffff;
|
|
21
|
+
--polyx-fg: #18181b;
|
|
22
|
+
--polyx-muted-fg: #71717a;
|
|
23
|
+
--polyx-border: #e4e4e7;
|
|
24
|
+
--polyx-input-bg: #ffffff;
|
|
25
|
+
--polyx-ring: #a5b4fc;
|
|
26
|
+
--polyx-danger: #dc2626;
|
|
27
|
+
--polyx-danger-bg: #fef2f2;
|
|
28
|
+
--polyx-page-bg: #fafafa;
|
|
29
|
+
|
|
30
|
+
/* Shape + type */
|
|
31
|
+
--polyx-radius: 0.75rem;
|
|
32
|
+
--polyx-radius-sm: 0.5rem;
|
|
33
|
+
--polyx-font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
34
|
+
--polyx-shadow: 0 1px 3px rgb(0 0 0 / 0.06), 0 10px 30px rgb(0 0 0 / 0.07);
|
|
35
|
+
|
|
36
|
+
font-family: var(--polyx-font);
|
|
37
|
+
color: var(--polyx-fg);
|
|
38
|
+
-webkit-font-smoothing: antialiased;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Scoped box model — applies only inside our own subtree. */
|
|
42
|
+
.polyx-signin,
|
|
43
|
+
.polyx-signin *,
|
|
44
|
+
.polyx-signin *::before,
|
|
45
|
+
.polyx-signin *::after {
|
|
46
|
+
box-sizing: border-box;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* Dark: follow the OS… */
|
|
50
|
+
@media (prefers-color-scheme: dark) {
|
|
51
|
+
.polyx-signin {
|
|
52
|
+
--polyx-brand: #6366f1;
|
|
53
|
+
--polyx-brand-hover: #818cf8;
|
|
54
|
+
--polyx-bg: #18181b;
|
|
55
|
+
--polyx-fg: #fafafa;
|
|
56
|
+
--polyx-muted-fg: #a1a1aa;
|
|
57
|
+
--polyx-border: #3f3f46;
|
|
58
|
+
--polyx-input-bg: #27272a;
|
|
59
|
+
--polyx-ring: #4f46e5;
|
|
60
|
+
--polyx-danger: #f87171;
|
|
61
|
+
--polyx-danger-bg: #2a1616;
|
|
62
|
+
--polyx-page-bg: #09090b;
|
|
63
|
+
--polyx-shadow: 0 1px 3px rgb(0 0 0 / 0.4), 0 10px 30px rgb(0 0 0 / 0.35);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* …but an explicit host theme wins over the OS preference (`:where` keeps
|
|
68
|
+
specificity at 0 so these stay as easy to override as the base rule). */
|
|
69
|
+
:where(.dark, [data-theme="dark"]) .polyx-signin {
|
|
70
|
+
--polyx-brand: #6366f1;
|
|
71
|
+
--polyx-brand-hover: #818cf8;
|
|
72
|
+
--polyx-bg: #18181b;
|
|
73
|
+
--polyx-fg: #fafafa;
|
|
74
|
+
--polyx-muted-fg: #a1a1aa;
|
|
75
|
+
--polyx-border: #3f3f46;
|
|
76
|
+
--polyx-input-bg: #27272a;
|
|
77
|
+
--polyx-ring: #4f46e5;
|
|
78
|
+
--polyx-danger: #f87171;
|
|
79
|
+
--polyx-danger-bg: #2a1616;
|
|
80
|
+
--polyx-page-bg: #09090b;
|
|
81
|
+
--polyx-shadow: 0 1px 3px rgb(0 0 0 / 0.4), 0 10px 30px rgb(0 0 0 / 0.35);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
:where(.light, [data-theme="light"]) .polyx-signin {
|
|
85
|
+
--polyx-brand: #4f46e5;
|
|
86
|
+
--polyx-brand-hover: #4338ca;
|
|
87
|
+
--polyx-bg: #ffffff;
|
|
88
|
+
--polyx-fg: #18181b;
|
|
89
|
+
--polyx-muted-fg: #71717a;
|
|
90
|
+
--polyx-border: #e4e4e7;
|
|
91
|
+
--polyx-input-bg: #ffffff;
|
|
92
|
+
--polyx-ring: #a5b4fc;
|
|
93
|
+
--polyx-danger: #dc2626;
|
|
94
|
+
--polyx-danger-bg: #fef2f2;
|
|
95
|
+
--polyx-page-bg: #fafafa;
|
|
96
|
+
--polyx-shadow: 0 1px 3px rgb(0 0 0 / 0.06), 0 10px 30px rgb(0 0 0 / 0.07);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* --- Variants ------------------------------------------------------------ */
|
|
100
|
+
|
|
101
|
+
/* `page`: owns the viewport — centered card on a full-bleed background. */
|
|
102
|
+
.polyx-signin--page {
|
|
103
|
+
display: grid;
|
|
104
|
+
place-items: center;
|
|
105
|
+
min-height: 100dvh;
|
|
106
|
+
padding: 1.5rem;
|
|
107
|
+
background: var(--polyx-page-bg);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/* `card`: just the card — drop it anywhere in your own layout. */
|
|
111
|
+
.polyx-signin--card {
|
|
112
|
+
display: block;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.polyx-signin__card {
|
|
116
|
+
width: 100%;
|
|
117
|
+
max-width: 24rem;
|
|
118
|
+
margin-inline: auto;
|
|
119
|
+
padding: 2rem;
|
|
120
|
+
background: var(--polyx-bg);
|
|
121
|
+
border: 1px solid var(--polyx-border);
|
|
122
|
+
border-radius: var(--polyx-radius);
|
|
123
|
+
box-shadow: var(--polyx-shadow);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* --- Header -------------------------------------------------------------- */
|
|
127
|
+
|
|
128
|
+
.polyx-signin__header {
|
|
129
|
+
display: flex;
|
|
130
|
+
flex-direction: column;
|
|
131
|
+
gap: 0.375rem;
|
|
132
|
+
margin-bottom: 1.75rem;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.polyx-signin__logo {
|
|
136
|
+
display: flex;
|
|
137
|
+
margin-bottom: 0.75rem;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.polyx-signin__heading {
|
|
141
|
+
margin: 0;
|
|
142
|
+
font-size: 1.375rem;
|
|
143
|
+
font-weight: 600;
|
|
144
|
+
letter-spacing: -0.01em;
|
|
145
|
+
color: var(--polyx-fg);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.polyx-signin__subheading {
|
|
149
|
+
margin: 0;
|
|
150
|
+
font-size: 0.875rem;
|
|
151
|
+
color: var(--polyx-muted-fg);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* --- Form ---------------------------------------------------------------- */
|
|
155
|
+
|
|
156
|
+
.polyx-signin__form {
|
|
157
|
+
display: flex;
|
|
158
|
+
flex-direction: column;
|
|
159
|
+
gap: 1.125rem;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.polyx-signin__field {
|
|
163
|
+
display: flex;
|
|
164
|
+
flex-direction: column;
|
|
165
|
+
gap: 0.4375rem;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.polyx-signin__label {
|
|
169
|
+
font-size: 0.875rem;
|
|
170
|
+
font-weight: 500;
|
|
171
|
+
color: var(--polyx-fg);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.polyx-signin__input {
|
|
175
|
+
width: 100%;
|
|
176
|
+
height: 2.5rem;
|
|
177
|
+
padding: 0 0.75rem;
|
|
178
|
+
font: inherit;
|
|
179
|
+
font-size: 0.875rem;
|
|
180
|
+
color: var(--polyx-fg);
|
|
181
|
+
background: var(--polyx-input-bg);
|
|
182
|
+
border: 1px solid var(--polyx-border);
|
|
183
|
+
border-radius: var(--polyx-radius-sm);
|
|
184
|
+
outline: none;
|
|
185
|
+
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.polyx-signin__input::placeholder {
|
|
189
|
+
color: var(--polyx-muted-fg);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.polyx-signin__input:focus-visible {
|
|
193
|
+
border-color: var(--polyx-brand);
|
|
194
|
+
box-shadow: 0 0 0 3px var(--polyx-ring);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.polyx-signin__input:disabled {
|
|
198
|
+
opacity: 0.6;
|
|
199
|
+
cursor: not-allowed;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/* --- Buttons ------------------------------------------------------------- */
|
|
203
|
+
|
|
204
|
+
.polyx-signin__submit,
|
|
205
|
+
.polyx-signin__tenant {
|
|
206
|
+
display: inline-flex;
|
|
207
|
+
align-items: center;
|
|
208
|
+
justify-content: center;
|
|
209
|
+
width: 100%;
|
|
210
|
+
min-height: 2.5rem;
|
|
211
|
+
padding: 0 1rem;
|
|
212
|
+
font: inherit;
|
|
213
|
+
font-size: 0.875rem;
|
|
214
|
+
font-weight: 500;
|
|
215
|
+
color: var(--polyx-brand-fg);
|
|
216
|
+
background: var(--polyx-brand);
|
|
217
|
+
border: 1px solid transparent;
|
|
218
|
+
border-radius: var(--polyx-radius-sm);
|
|
219
|
+
cursor: pointer;
|
|
220
|
+
transition: background-color 0.15s ease;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.polyx-signin__submit:hover:not(:disabled),
|
|
224
|
+
.polyx-signin__tenant:hover:not(:disabled) {
|
|
225
|
+
background: var(--polyx-brand-hover);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.polyx-signin__submit:focus-visible,
|
|
229
|
+
.polyx-signin__tenant:focus-visible {
|
|
230
|
+
outline: none;
|
|
231
|
+
box-shadow: 0 0 0 3px var(--polyx-ring);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.polyx-signin__submit:disabled,
|
|
235
|
+
.polyx-signin__tenant:disabled {
|
|
236
|
+
opacity: 0.6;
|
|
237
|
+
cursor: not-allowed;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/* --- Error --------------------------------------------------------------- */
|
|
241
|
+
|
|
242
|
+
.polyx-signin__error {
|
|
243
|
+
margin: 0;
|
|
244
|
+
padding: 0.625rem 0.75rem;
|
|
245
|
+
font-size: 0.8125rem;
|
|
246
|
+
color: var(--polyx-danger);
|
|
247
|
+
background: var(--polyx-danger-bg);
|
|
248
|
+
border: 1px solid color-mix(in srgb, var(--polyx-danger) 30%, transparent);
|
|
249
|
+
border-radius: var(--polyx-radius-sm);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/* --- Workspace picker ---------------------------------------------------- */
|
|
253
|
+
|
|
254
|
+
.polyx-signin__tenants {
|
|
255
|
+
display: flex;
|
|
256
|
+
flex-direction: column;
|
|
257
|
+
gap: 0.625rem;
|
|
258
|
+
margin: 0;
|
|
259
|
+
padding: 0;
|
|
260
|
+
list-style: none;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/* The picker's buttons read as choices, not as the primary CTA. */
|
|
264
|
+
.polyx-signin__tenant {
|
|
265
|
+
justify-content: flex-start;
|
|
266
|
+
color: var(--polyx-fg);
|
|
267
|
+
background: var(--polyx-input-bg);
|
|
268
|
+
border-color: var(--polyx-border);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.polyx-signin__tenant:hover:not(:disabled) {
|
|
272
|
+
background: var(--polyx-input-bg);
|
|
273
|
+
border-color: var(--polyx-brand);
|
|
274
|
+
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@poly-x/react",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.3",
|
|
4
4
|
"description": "PolyX SDK for React SPAs - provider, hooks, drop-in auth UI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"sideEffects":
|
|
7
|
+
"sideEffects": [
|
|
8
|
+
"**/*.css"
|
|
9
|
+
],
|
|
8
10
|
"files": [
|
|
9
11
|
"dist"
|
|
10
12
|
],
|
|
@@ -18,13 +20,14 @@
|
|
|
18
20
|
"types": "./dist/index.d.cts",
|
|
19
21
|
"default": "./dist/index.cjs"
|
|
20
22
|
}
|
|
21
|
-
}
|
|
23
|
+
},
|
|
24
|
+
"./styles.css": "./dist/styles.css"
|
|
22
25
|
},
|
|
23
26
|
"main": "./dist/index.cjs",
|
|
24
27
|
"module": "./dist/index.mjs",
|
|
25
28
|
"types": "./dist/index.d.cts",
|
|
26
29
|
"dependencies": {
|
|
27
|
-
"@poly-x/core": "0.1.0-alpha.
|
|
30
|
+
"@poly-x/core": "0.1.0-alpha.3"
|
|
28
31
|
},
|
|
29
32
|
"peerDependencies": {
|
|
30
33
|
"react": ">=18",
|
|
@@ -51,7 +54,7 @@
|
|
|
51
54
|
"react-dom": "^19.2.7"
|
|
52
55
|
},
|
|
53
56
|
"scripts": {
|
|
54
|
-
"build": "tsdown",
|
|
57
|
+
"build": "tsdown && node scripts/copy-styles.mjs",
|
|
55
58
|
"test": "vitest run",
|
|
56
59
|
"lint": "eslint src"
|
|
57
60
|
}
|