@djangocfg/layouts 2.1.334 → 2.1.335

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
@@ -54,10 +54,30 @@ Use `BaseApp` directly when you don't need route-based layout switching — see
54
54
  |---|---|---|
55
55
  | **`PublicLayout`** | Marketing / docs. Slots for navbar (`Floating`/`Flush`/`Minimal`) + footer + locale + auth controls. | [README](./src/layouts/PublicLayout/README.md) |
56
56
  | **`PrivateLayout`** | Authenticated app shell — sidebar (collapsible icon rail, accordion groups, rail/featured/CTA slots) + popover account footer. | [README](./src/layouts/PrivateLayout/README.md) |
57
- | **`AuthLayout`** | Sign-in / sign-up flows. | [README](./src/layouts/AuthLayout/README.md) |
57
+ | **`AuthLayout`** | Sign-in / sign-up flows. Shell-based: `centered` (default) or `split` (two-column desktop). | [README](./src/layouts/AuthLayout/README.md) |
58
58
  | **`AdminLayout`** | Admin console. | — |
59
59
  | **`ProfileLayout`** | Profile page — see below. | |
60
60
 
61
+ ### `AuthLayout` shells
62
+
63
+ Two visual variants, switchable via the `variant` prop:
64
+
65
+ - **`centered`** — Apple HIG-style: frameless, centered form, animated glow background.
66
+ - **`split`** — Two-column card on desktop (form left, customizable sidebar right); single-column on mobile. Background image/gradient with overlay + blur via the `background` prop.
67
+
68
+ ```tsx
69
+ // Split variant with background image and testimonial sidebar
70
+ <AuthLayout
71
+ variant="split"
72
+ background={{ imageUrl: '/bg.jpg', overlay: 'hsl(var(--background) / 0.6)', blur: '8px' }}
73
+ sidebar={<Testimonial />}
74
+ >
75
+ {/* optional custom header, shown only on identifier step */}
76
+ </AuthLayout>
77
+ ```
78
+
79
+ Architecture: `AuthShell` orchestrator dispatches to `CenteredShell` or `SplitShell`. Add new variants by extending `AuthShellVariant` and creating a new shell component.
80
+
61
81
  ### `ProfileLayout`
62
82
 
63
83
  ```tsx
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djangocfg/layouts",
3
- "version": "2.1.334",
3
+ "version": "2.1.335",
4
4
  "description": "Simple, straightforward layout components for Next.js - import and use with props",
5
5
  "keywords": [
6
6
  "layouts",
@@ -84,13 +84,13 @@
84
84
  "check": "tsc --noEmit"
85
85
  },
86
86
  "peerDependencies": {
87
- "@djangocfg/api": "^2.1.334",
88
- "@djangocfg/centrifugo": "^2.1.334",
89
- "@djangocfg/debuger": "^2.1.334",
90
- "@djangocfg/i18n": "^2.1.334",
91
- "@djangocfg/monitor": "^2.1.334",
92
- "@djangocfg/ui-core": "^2.1.334",
93
- "@djangocfg/ui-nextjs": "^2.1.334",
87
+ "@djangocfg/api": "^2.1.335",
88
+ "@djangocfg/centrifugo": "^2.1.335",
89
+ "@djangocfg/debuger": "^2.1.335",
90
+ "@djangocfg/i18n": "^2.1.335",
91
+ "@djangocfg/monitor": "^2.1.335",
92
+ "@djangocfg/ui-core": "^2.1.335",
93
+ "@djangocfg/ui-nextjs": "^2.1.335",
94
94
  "@hookform/resolvers": "^5.2.2",
95
95
  "consola": "^3.4.2",
96
96
  "lucide-react": "^0.545.0",
@@ -120,15 +120,15 @@
120
120
  "uuid": "^11.1.0"
121
121
  },
122
122
  "devDependencies": {
123
- "@djangocfg/api": "^2.1.334",
124
- "@djangocfg/centrifugo": "^2.1.334",
125
- "@djangocfg/debuger": "^2.1.334",
126
- "@djangocfg/i18n": "^2.1.334",
127
- "@djangocfg/monitor": "^2.1.334",
128
- "@djangocfg/typescript-config": "^2.1.334",
129
- "@djangocfg/ui-core": "^2.1.334",
130
- "@djangocfg/ui-nextjs": "^2.1.334",
131
- "@djangocfg/ui-tools": "^2.1.334",
123
+ "@djangocfg/api": "^2.1.335",
124
+ "@djangocfg/centrifugo": "^2.1.335",
125
+ "@djangocfg/debuger": "^2.1.335",
126
+ "@djangocfg/i18n": "^2.1.335",
127
+ "@djangocfg/monitor": "^2.1.335",
128
+ "@djangocfg/typescript-config": "^2.1.335",
129
+ "@djangocfg/ui-core": "^2.1.335",
130
+ "@djangocfg/ui-nextjs": "^2.1.335",
131
+ "@djangocfg/ui-tools": "^2.1.335",
132
132
  "@types/node": "^24.7.2",
133
133
  "@types/react": "^19.1.0",
134
134
  "@types/react-dom": "^19.1.0",
@@ -0,0 +1,101 @@
1
+ /**
2
+ * AuthLayout configurator defaults, presets, and image catalogue.
3
+ */
4
+
5
+ import type { AuthPlaygroundConfig, AuthCenteredConfig, AuthSplitConfig } from './types';
6
+
7
+ export const BG_IMAGES = [
8
+ {
9
+ label: 'Mountains',
10
+ value: 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=1920&q=80',
11
+ },
12
+ {
13
+ label: 'Night City',
14
+ value: 'https://images.unsplash.com/photo-1519501025264-65ba15a82390?w=1920&q=80',
15
+ },
16
+ {
17
+ label: 'Abstract Mesh',
18
+ value: 'https://images.unsplash.com/photo-1550684848-fac1c5b4e853?w=1920&q=80',
19
+ },
20
+ {
21
+ label: 'Ocean Waves',
22
+ value: 'https://images.unsplash.com/photo-1505118380757-91f5f5632de0?w=1920&q=80',
23
+ },
24
+ {
25
+ label: 'Forest Fog',
26
+ value: 'https://images.unsplash.com/photo-1448375240586-882707db888b?w=1920&q=80',
27
+ },
28
+ ] as const;
29
+
30
+ export const defaultCenteredConfig: AuthCenteredConfig = {
31
+ background: {
32
+ enabled: false,
33
+ imageUrl: BG_IMAGES[0].value,
34
+ gradient: 'linear-gradient(135deg, hsl(var(--primary) / 0.08) 0%, hsl(var(--background)) 100%)',
35
+ overlay: 'hsl(var(--background) / 0.6)',
36
+ blur: '8px',
37
+ },
38
+ form: {
39
+ showLogo: true,
40
+ showTerms: true,
41
+ showGithub: true,
42
+ showSupport: true,
43
+ },
44
+ };
45
+
46
+ export const defaultSplitConfig: AuthSplitConfig = {
47
+ background: {
48
+ enabled: true,
49
+ imageUrl: BG_IMAGES[0].value,
50
+ gradient: '',
51
+ overlay: 'hsl(var(--background) / 0.6)',
52
+ blur: '8px',
53
+ },
54
+ sidebar: {
55
+ enabled: true,
56
+ showQuote: true,
57
+ showAuthor: true,
58
+ },
59
+ form: {
60
+ showLogo: true,
61
+ showTerms: true,
62
+ showGithub: true,
63
+ showSupport: true,
64
+ },
65
+ };
66
+
67
+ /** Full config used when the caller still needs a single object (e.g. URL encode). */
68
+ export const defaultConfig: AuthPlaygroundConfig = {
69
+ variant: 'centered',
70
+ ...defaultCenteredConfig,
71
+ sidebar: { enabled: false, showQuote: true, showAuthor: true },
72
+ };
73
+
74
+ export const presets = {
75
+ centered: defaultCenteredConfig,
76
+ split: defaultSplitConfig,
77
+ } as const;
78
+
79
+ export function detectPreset(config: AuthPlaygroundConfig): 'centered' | 'split' | 'custom' {
80
+ if (deepEqual(config, { variant: 'centered', ...defaultCenteredConfig, sidebar: { enabled: false, showQuote: true, showAuthor: true } })) {
81
+ return 'centered';
82
+ }
83
+ if (deepEqual(config, { variant: 'split', ...defaultSplitConfig })) {
84
+ return 'split';
85
+ }
86
+ return 'custom';
87
+ }
88
+
89
+ function deepEqual(a: unknown, b: unknown): boolean {
90
+ if (a === b) return true;
91
+ if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false;
92
+ const ak = Object.keys(a as Record<string, unknown>);
93
+ const bk = Object.keys(b as Record<string, unknown>);
94
+ if (ak.length !== bk.length) return false;
95
+ for (const k of ak) {
96
+ if (!deepEqual((a as Record<string, unknown>)[k], (b as Record<string, unknown>)[k])) {
97
+ return false;
98
+ }
99
+ }
100
+ return true;
101
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * AuthLayout configurator — schemas, defaults, and presets.
3
+ *
4
+ * Two independent schemas are provided:
5
+ * - `authCenteredSchema` + `authCenteredUiSchema` — Apple-style frameless
6
+ * - `authSplitSchema` + `authSplitUiSchema` — two-column card with sidebar
7
+ *
8
+ * Use `defaultCenteredConfig` / `defaultSplitConfig` as safe initial values.
9
+ */
10
+
11
+ export type {
12
+ AuthPlaygroundConfig,
13
+ AuthCenteredConfig,
14
+ AuthSplitConfig,
15
+ AuthShellVariant,
16
+ PresetKind,
17
+ AuthBackgroundConfig,
18
+ AuthSidebarConfig,
19
+ AuthFormConfig,
20
+ } from './types';
21
+
22
+ export {
23
+ BG_IMAGES,
24
+ defaultCenteredConfig,
25
+ defaultSplitConfig,
26
+ defaultConfig,
27
+ presets,
28
+ detectPreset,
29
+ } from './defaults';
30
+
31
+ export {
32
+ authCenteredSchema,
33
+ authCenteredUiSchema,
34
+ authSplitSchema,
35
+ authSplitUiSchema,
36
+ } from './schema';
@@ -0,0 +1,205 @@
1
+ /**
2
+ * JSON Schema + uiSchema for an AuthLayout configurator UI.
3
+ *
4
+ * Two independent schemas are exported:
5
+ * - `authCenteredSchema` / `authCenteredUiSchema` — Apple-style frameless shell
6
+ * - `authSplitSchema` / `authSplitUiSchema` — two-column card with sidebar
7
+ *
8
+ * Pair with `<JsonSchemaForm density="compact" schema={...} uiSchema={...}>`
9
+ * from `@djangocfg/ui-tools` to get a ready-made sidebar configurator.
10
+ */
11
+
12
+ import type { CustomJsonSchema7, CustomJsonUiSchema7 } from '@djangocfg/ui-core/lib';
13
+
14
+ // ─────────────────────────────────────────────────────────────────────────────
15
+ // Centered variant
16
+ // ─────────────────────────────────────────────────────────────────────────────
17
+
18
+ export const authCenteredSchema: CustomJsonSchema7 = {
19
+ type: 'object',
20
+ properties: {
21
+ background: {
22
+ type: 'object',
23
+ title: 'Background',
24
+ properties: {
25
+ enabled: {
26
+ type: 'boolean',
27
+ title: 'Enable custom background',
28
+ description: 'When off, uses the default GlowBackground.',
29
+ },
30
+ imageUrl: {
31
+ type: 'string',
32
+ title: 'Image',
33
+ enum: [
34
+ 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=1920&q=80',
35
+ 'https://images.unsplash.com/photo-1519501025264-65ba15a82390?w=1920&q=80',
36
+ 'https://images.unsplash.com/photo-1550684848-fac1c5b4e853?w=1920&q=80',
37
+ 'https://images.unsplash.com/photo-1505118380757-91f5f5632de0?w=1920&q=80',
38
+ 'https://images.unsplash.com/photo-1448375240586-882707db888b?w=1920&q=80',
39
+ ],
40
+ enumNames: ['Mountains', 'Night City', 'Abstract Mesh', 'Ocean Waves', 'Forest Fog'],
41
+ description: 'Full-bleed background image (loaded via useImageLoader).',
42
+ },
43
+ gradient: {
44
+ type: 'string',
45
+ title: 'CSS gradient',
46
+ description: 'Fallback when no image or image fails to load.',
47
+ },
48
+ overlay: {
49
+ type: 'string',
50
+ title: 'Overlay color',
51
+ description: 'e.g. hsl(var(--background) / 0.6)',
52
+ },
53
+ blur: {
54
+ type: 'string',
55
+ title: 'Backdrop blur',
56
+ description: 'e.g. 8px, 12px',
57
+ },
58
+ },
59
+ },
60
+ form: {
61
+ type: 'object',
62
+ title: 'Form options',
63
+ properties: {
64
+ showLogo: { type: 'boolean', title: 'Logo on success screen' },
65
+ showTerms: { type: 'boolean', title: 'Terms checkbox' },
66
+ showGithub: { type: 'boolean', title: 'GitHub OAuth button' },
67
+ showSupport: { type: 'boolean', title: 'Support link in footer' },
68
+ },
69
+ },
70
+ },
71
+ };
72
+
73
+ export const authCenteredUiSchema: CustomJsonUiSchema7 = {
74
+ background: {
75
+ 'ui:collapsible': true,
76
+ 'ui:groups': [
77
+ { title: 'Toggle', fields: ['enabled'], defaultOpen: true },
78
+ { title: 'Style', fields: ['imageUrl', 'gradient', 'overlay', 'blur'], defaultOpen: true },
79
+ ],
80
+ enabled: { 'ui:widget': 'switch' },
81
+ imageUrl: {
82
+ 'ui:widget': 'select',
83
+ 'ui:disabledWhen': { path: 'background.enabled', eq: false },
84
+ },
85
+ gradient: { 'ui:disabledWhen': { path: 'background.enabled', eq: false } },
86
+ overlay: { 'ui:disabledWhen': { path: 'background.enabled', eq: false } },
87
+ blur: { 'ui:disabledWhen': { path: 'background.enabled', eq: false } },
88
+ },
89
+ form: {
90
+ 'ui:collapsible': true,
91
+ showLogo: { 'ui:widget': 'switch' },
92
+ showTerms: { 'ui:widget': 'switch' },
93
+ showGithub: { 'ui:widget': 'switch' },
94
+ showSupport: { 'ui:widget': 'switch' },
95
+ },
96
+ };
97
+
98
+ // ─────────────────────────────────────────────────────────────────────────────
99
+ // Split variant
100
+ // ─────────────────────────────────────────────────────────────────────────────
101
+
102
+ export const authSplitSchema: CustomJsonSchema7 = {
103
+ type: 'object',
104
+ properties: {
105
+ background: {
106
+ type: 'object',
107
+ title: 'Background',
108
+ properties: {
109
+ enabled: {
110
+ type: 'boolean',
111
+ title: 'Enable custom background',
112
+ description: 'When off, uses plain background.',
113
+ },
114
+ imageUrl: {
115
+ type: 'string',
116
+ title: 'Image',
117
+ enum: [
118
+ 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=1920&q=80',
119
+ 'https://images.unsplash.com/photo-1519501025264-65ba15a82390?w=1920&q=80',
120
+ 'https://images.unsplash.com/photo-1550684848-fac1c5b4e853?w=1920&q=80',
121
+ 'https://images.unsplash.com/photo-1505118380757-91f5f5632de0?w=1920&q=80',
122
+ 'https://images.unsplash.com/photo-1448375240586-882707db888b?w=1920&q=80',
123
+ ],
124
+ enumNames: ['Mountains', 'Night City', 'Abstract Mesh', 'Ocean Waves', 'Forest Fog'],
125
+ description: 'Full-bleed background image (loaded via useImageLoader).',
126
+ },
127
+ gradient: {
128
+ type: 'string',
129
+ title: 'CSS gradient',
130
+ description: 'Fallback when no image or image fails to load.',
131
+ },
132
+ overlay: {
133
+ type: 'string',
134
+ title: 'Overlay color',
135
+ description: 'e.g. hsl(var(--background) / 0.6)',
136
+ },
137
+ blur: {
138
+ type: 'string',
139
+ title: 'Backdrop blur',
140
+ description: 'e.g. 8px, 12px',
141
+ },
142
+ },
143
+ },
144
+ sidebar: {
145
+ type: 'object',
146
+ title: 'Sidebar',
147
+ properties: {
148
+ enabled: {
149
+ type: 'boolean',
150
+ title: 'Show sidebar',
151
+ description: 'Right column content — visible on desktop only.',
152
+ },
153
+ showQuote: { type: 'boolean', title: 'Show quote' },
154
+ showAuthor: { type: 'boolean', title: 'Show author' },
155
+ },
156
+ },
157
+ form: {
158
+ type: 'object',
159
+ title: 'Form options',
160
+ properties: {
161
+ showLogo: { type: 'boolean', title: 'Logo on success screen' },
162
+ showTerms: { type: 'boolean', title: 'Terms checkbox' },
163
+ showGithub: { type: 'boolean', title: 'GitHub OAuth button' },
164
+ showSupport: { type: 'boolean', title: 'Support link in footer' },
165
+ },
166
+ },
167
+ },
168
+ };
169
+
170
+ export const authSplitUiSchema: CustomJsonUiSchema7 = {
171
+ background: {
172
+ 'ui:collapsible': true,
173
+ 'ui:groups': [
174
+ { title: 'Toggle', fields: ['enabled'], defaultOpen: true },
175
+ { title: 'Style', fields: ['imageUrl', 'gradient', 'overlay', 'blur'], defaultOpen: true },
176
+ ],
177
+ enabled: { 'ui:widget': 'switch' },
178
+ imageUrl: {
179
+ 'ui:widget': 'select',
180
+ 'ui:disabledWhen': { path: 'background.enabled', eq: false },
181
+ },
182
+ gradient: { 'ui:disabledWhen': { path: 'background.enabled', eq: false } },
183
+ overlay: { 'ui:disabledWhen': { path: 'background.enabled', eq: false } },
184
+ blur: { 'ui:disabledWhen': { path: 'background.enabled', eq: false } },
185
+ },
186
+ sidebar: {
187
+ 'ui:collapsible': true,
188
+ enabled: { 'ui:widget': 'switch' },
189
+ showQuote: {
190
+ 'ui:widget': 'switch',
191
+ 'ui:disabledWhen': { path: 'sidebar.enabled', eq: false },
192
+ },
193
+ showAuthor: {
194
+ 'ui:widget': 'switch',
195
+ 'ui:disabledWhen': { path: 'sidebar.enabled', eq: false },
196
+ },
197
+ },
198
+ form: {
199
+ 'ui:collapsible': true,
200
+ showLogo: { 'ui:widget': 'switch' },
201
+ showTerms: { 'ui:widget': 'switch' },
202
+ showGithub: { 'ui:widget': 'switch' },
203
+ showSupport: { 'ui:widget': 'switch' },
204
+ },
205
+ };
@@ -0,0 +1,48 @@
1
+ /**
2
+ * AuthLayout configurator types
3
+ */
4
+
5
+ export type AuthShellVariant = 'centered' | 'split';
6
+ export type PresetKind = 'centered' | 'split' | 'custom';
7
+
8
+ export interface AuthBackgroundConfig {
9
+ enabled: boolean;
10
+ imageUrl: string;
11
+ gradient: string;
12
+ overlay: string;
13
+ blur: string;
14
+ }
15
+
16
+ export interface AuthSidebarConfig {
17
+ enabled: boolean;
18
+ showQuote: boolean;
19
+ showAuthor: boolean;
20
+ }
21
+
22
+ export interface AuthFormConfig {
23
+ showLogo: boolean;
24
+ showTerms: boolean;
25
+ showGithub: boolean;
26
+ showSupport: boolean;
27
+ }
28
+
29
+ /** Full config used by the playground and embed page. */
30
+ export interface AuthPlaygroundConfig {
31
+ variant: AuthShellVariant;
32
+ background: AuthBackgroundConfig;
33
+ sidebar: AuthSidebarConfig;
34
+ form: AuthFormConfig;
35
+ }
36
+
37
+ /** Centered-only subset (no sidebar). */
38
+ export interface AuthCenteredConfig {
39
+ background: AuthBackgroundConfig;
40
+ form: AuthFormConfig;
41
+ }
42
+
43
+ /** Split-only subset (always has sidebar + background). */
44
+ export interface AuthSplitConfig {
45
+ background: AuthBackgroundConfig;
46
+ sidebar: AuthSidebarConfig;
47
+ form: AuthFormConfig;
48
+ }
@@ -6,9 +6,11 @@
6
6
  *
7
7
  * Public surface today:
8
8
  * - `private` — `PrivateLayout` configurator (shell + sidebar + header)
9
+ * - `auth` — `AuthLayout` configurator (centered / split variants)
9
10
  *
10
11
  * Public + theme configurators are not exported yet — they currently live in
11
12
  * the demo app while the schema shape is iterated on.
12
13
  */
13
14
 
14
15
  export * from './private';
16
+ export * from './auth';
@@ -192,7 +192,8 @@ export function BaseApp({
192
192
  <AuthDialog authPath={auth?.routes?.auth} />
193
193
 
194
194
  {/* Debug Panel — auto in dev, ?debug=1 in prod, disable with debug={{ enabled: false }} */}
195
- <DebugButton enabled={debugEnabled} {...debugProps} />
195
+ {/* eslint-disable-next-line @typescript-eslint/no-explicit-any */}
196
+ <DebugButton enabled={debugEnabled} {...(debugProps as any)} />
196
197
  </ErrorTrackingProvider>
197
198
  </PwaProvider>
198
199
  </CentrifugoProvider>
@@ -1,30 +1,33 @@
1
1
  /**
2
- * Auth Layout - Apple Style
2
+ * Auth Layout
3
+ *
4
+ * Shell-based authentication layout with two variants:
5
+ * - `centered` (default) — Apple-style frameless, centered, glow background
6
+ * - `split` — Two-column on desktop (form + sidebar), single-column on mobile
3
7
  *
4
- * Minimal, clean authentication layout with smooth animations.
5
8
  * Supports: email/phone OTP, OAuth (GitHub), 2FA (TOTP + backup codes)
6
9
  */
7
10
 
8
11
  'use client';
9
12
 
10
- import React, { createContext, useContext, useEffect, useState } from 'react';
13
+ import React, { createContext, useContext } from 'react';
11
14
 
12
15
  import { useCfgRouter } from '@djangocfg/api/auth';
13
16
  import { useAppT } from '@djangocfg/i18n';
14
17
 
15
- import { GlowBackground } from '@djangocfg/ui-core/components';
16
-
17
18
  import { Suspense } from '../../components';
18
19
  import { OAuthCallback } from './components/oauth';
19
20
  import { IdentifierStep, OTPStep, SetupStep, TwoFactorStep } from './components/steps';
20
21
  import { AUTH } from './constants';
21
22
  import { AuthFormProvider, useAuthFormContext } from './context';
23
+ import { AuthShell } from './shells';
22
24
 
23
25
  import './styles/auth.css';
26
+ import './styles/centered-shell.css';
27
+ import './styles/split-shell.css';
24
28
 
25
29
  import type { AuthLayoutProps } from './types';
26
30
 
27
-
28
31
  // ─── Layout-level context (header suppression, etc.) ─────────────────────────
29
32
 
30
33
  interface AuthLayoutContextValue {
@@ -39,8 +42,19 @@ export const useAuthLayoutContext = (): AuthLayoutContextValue => useContext(Aut
39
42
  // ─── Layout ──────────────────────────────────────────────────────────────────
40
43
 
41
44
  export const AuthLayout: React.FC<AuthLayoutProps> = (props) => {
42
- const { enableGithubAuth, redirectUrl = AUTH.DEFAULT_REDIRECT, onOAuthSuccess, onError, className } = props;
43
- const hideHeader = Boolean(props.children);
45
+ const {
46
+ variant = 'centered',
47
+ background,
48
+ sidebar,
49
+ enableGithubAuth,
50
+ redirectUrl = AUTH.DEFAULT_REDIRECT,
51
+ onOAuthSuccess,
52
+ onError,
53
+ className,
54
+ children,
55
+ } = props;
56
+
57
+ const hideHeader = Boolean(children);
44
58
 
45
59
  return (
46
60
  <Suspense>
@@ -49,26 +63,21 @@ export const AuthLayout: React.FC<AuthLayoutProps> = (props) => {
49
63
  {/* Full-screen success overlay */}
50
64
  <AuthSuccessOverlay />
51
65
 
52
- <div className={`auth-layout ${className || ''}`}>
53
- <GlowBackground />
54
-
55
- {/* Content layer above glow */}
56
- <div style={{ position: 'relative', zIndex: 1, width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
57
- {/* Handle OAuth callback when GitHub auth is enabled */}
58
- {enableGithubAuth && (
59
- <Suspense fallback={null}>
60
- <OAuthCallback
61
- redirectUrl={redirectUrl}
62
- onSuccess={onOAuthSuccess ? (user, isNewUser) => onOAuthSuccess(user, isNewUser, 'github') : undefined}
63
- onError={onError}
64
- />
65
- </Suspense>
66
- )}
67
-
68
- <AuthHeaderSlot>{props.children}</AuthHeaderSlot>
69
- <AuthContent />
70
- </div>
71
- </div>
66
+ <AuthShell variant={variant} background={background} sidebar={sidebar} className={className}>
67
+ {/* Handle OAuth callback when GitHub auth is enabled */}
68
+ {enableGithubAuth && (
69
+ <Suspense fallback={null}>
70
+ <OAuthCallback
71
+ redirectUrl={redirectUrl}
72
+ onSuccess={onOAuthSuccess ? (user, isNewUser) => onOAuthSuccess(user, isNewUser, 'github') : undefined}
73
+ onError={onError}
74
+ />
75
+ </Suspense>
76
+ )}
77
+
78
+ <AuthHeaderSlot>{children}</AuthHeaderSlot>
79
+ <AuthContent />
80
+ </AuthShell>
72
81
  </AuthLayoutContext.Provider>
73
82
  </AuthFormProvider>
74
83
  </Suspense>
@@ -131,11 +140,11 @@ const AuthSuccess: React.FC<AuthSuccessInlineProps> = ({
131
140
  }) => {
132
141
  const router = useCfgRouter();
133
142
  const t = useAppT();
134
- const [isVisible, setIsVisible] = useState(false);
143
+ const [isVisible, setIsVisible] = React.useState(false);
135
144
 
136
145
  const successMessage = React.useMemo(() => t('layouts.auth.success.message'), [t]);
137
146
 
138
- useEffect(() => {
147
+ React.useEffect(() => {
139
148
  const animTimer = setTimeout(() => setIsVisible(true), AUTH.ANIMATION_START_DELAY);
140
149
  const redirectTimer = setTimeout(() => {
141
150
  const finalUrl = redirectUrl || AUTH.DEFAULT_REDIRECT;