@djangocfg/layouts 2.1.264 → 2.1.266

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
@@ -124,10 +124,49 @@ import { AppLayout } from '@djangocfg/layouts';
124
124
  | **PrivateLayout** | App shell — sidebar + header |
125
125
  | **AuthLayout** | Sign-in flows |
126
126
  | **AdminLayout** | Admin console |
127
- | **ProfileLayout** | Profile + 2FA |
127
+ | **ProfileLayout** | Profile page with avatar, editable fields, 2FA, and slot/tab system |
128
128
 
129
129
  **Brand:** `ThemeBrandMark` / **`ThemeBrandMarkImg`** for logo slots.
130
130
 
131
+ ### ProfileLayout — slots & tabs
132
+
133
+ ```tsx
134
+ import { ProfileLayout } from '@djangocfg/layouts';
135
+ import type { ProfileTab, ProfileSlots } from '@djangocfg/layouts';
136
+
137
+ const tabs: ProfileTab[] = [
138
+ {
139
+ value: 'billing',
140
+ label: 'Billing',
141
+ content: <BillingSection />,
142
+ },
143
+ ];
144
+
145
+ const slots: ProfileSlots = {
146
+ headerBadge: <Badge>Pro</Badge>, // next to user name
147
+ headerMenuItems: <DropdownMenuItem>…</DropdownMenuItem>, // in ⋯ menu
148
+ headerAfter: <OnboardingBanner />, // below avatar, above tabs
149
+ footer: <LinkedAccounts />, // below all tab content
150
+ };
151
+
152
+ <ProfileLayout
153
+ enable2FA
154
+ enableDeleteAccount
155
+ tabs={tabs}
156
+ slots={slots}
157
+ />
158
+ ```
159
+
160
+ | Prop | Type | Description |
161
+ |------|------|-------------|
162
+ | `enable2FA` | `boolean` | Show Security tab with 2FA management |
163
+ | `enableDeleteAccount` | `boolean` | Show Delete account in `⋯` menu |
164
+ | `tabs` | `ProfileTab[]` | Extra tabs appended after built-in ones |
165
+ | `slots.headerBadge` | `ReactNode` | Rendered next to the user name (plan, role…) |
166
+ | `slots.headerMenuItems` | `ReactNode` | Extra `DropdownMenuItem`s in the `⋯` menu |
167
+ | `slots.headerAfter` | `ReactNode` | Below avatar row, above tabs |
168
+ | `slots.footer` | `ReactNode` | Below all tab content |
169
+
131
170
  ---
132
171
 
133
172
  ## i18n on AppLayout
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djangocfg/layouts",
3
- "version": "2.1.264",
3
+ "version": "2.1.266",
4
4
  "description": "Simple, straightforward layout components for Next.js - import and use with props",
5
5
  "keywords": [
6
6
  "layouts",
@@ -74,14 +74,14 @@
74
74
  "check": "tsc --noEmit"
75
75
  },
76
76
  "peerDependencies": {
77
- "@djangocfg/api": "^2.1.264",
78
- "@djangocfg/centrifugo": "^2.1.264",
79
- "@djangocfg/i18n": "^2.1.264",
80
- "@djangocfg/monitor": "^2.1.264",
81
- "@djangocfg/debuger": "^2.1.264",
82
- "@djangocfg/ui-core": "^2.1.264",
83
- "@djangocfg/ui-nextjs": "^2.1.264",
84
- "@djangocfg/ui-tools": "^2.1.264",
77
+ "@djangocfg/api": "^2.1.266",
78
+ "@djangocfg/centrifugo": "^2.1.266",
79
+ "@djangocfg/i18n": "^2.1.266",
80
+ "@djangocfg/monitor": "^2.1.266",
81
+ "@djangocfg/debuger": "^2.1.266",
82
+ "@djangocfg/ui-core": "^2.1.266",
83
+ "@djangocfg/ui-nextjs": "^2.1.266",
84
+ "@djangocfg/ui-tools": "^2.1.266",
85
85
  "@hookform/resolvers": "^5.2.2",
86
86
  "consola": "^3.4.2",
87
87
  "lucide-react": "^0.545.0",
@@ -103,21 +103,22 @@
103
103
  }
104
104
  },
105
105
  "dependencies": {
106
+ "libphonenumber-js": "^1.12.24",
106
107
  "nextjs-toploader": "^3.9.17",
107
108
  "qrcode.react": "^4.2.0",
108
109
  "react-ga4": "^2.1.0",
109
110
  "uuid": "^11.1.0"
110
111
  },
111
112
  "devDependencies": {
112
- "@djangocfg/api": "^2.1.264",
113
- "@djangocfg/i18n": "^2.1.264",
114
- "@djangocfg/centrifugo": "^2.1.264",
115
- "@djangocfg/monitor": "^2.1.264",
116
- "@djangocfg/debuger": "^2.1.264",
117
- "@djangocfg/typescript-config": "^2.1.264",
118
- "@djangocfg/ui-core": "^2.1.264",
119
- "@djangocfg/ui-nextjs": "^2.1.264",
120
- "@djangocfg/ui-tools": "^2.1.264",
113
+ "@djangocfg/api": "^2.1.266",
114
+ "@djangocfg/i18n": "^2.1.266",
115
+ "@djangocfg/centrifugo": "^2.1.266",
116
+ "@djangocfg/monitor": "^2.1.266",
117
+ "@djangocfg/debuger": "^2.1.266",
118
+ "@djangocfg/typescript-config": "^2.1.266",
119
+ "@djangocfg/ui-core": "^2.1.266",
120
+ "@djangocfg/ui-nextjs": "^2.1.266",
121
+ "@djangocfg/ui-tools": "^2.1.266",
121
122
  "@types/node": "^24.7.2",
122
123
  "@types/react": "^19.1.0",
123
124
  "@types/react-dom": "^19.1.0",
@@ -15,12 +15,8 @@ export interface SetupStepProps {
15
15
  }
16
16
 
17
17
  /**
18
- * SetupStep - Orchestrator for 2FA setup flow
19
- *
20
- * Delegates rendering to focused sub-components:
21
- * - SetupLoading: Initial loading state
22
- * - SetupQRCode: QR code scanning
23
- * - SetupComplete: Backup codes display
18
+ * SetupStep - Orchestrator for 2FA setup flow (requires AuthFormContext).
19
+ * For use outside AuthLayout use SetupStepStandalone.
24
20
  */
25
21
  export const SetupStep: React.FC<SetupStepProps> = ({ onComplete, onSkip }) => {
26
22
  const { setStep } = useAuthFormContext();
@@ -89,3 +85,51 @@ export const SetupStep: React.FC<SetupStepProps> = ({ onComplete, onSkip }) => {
89
85
  // Fallback to loading
90
86
  return <SetupLoading />;
91
87
  };
88
+
89
+ /**
90
+ * SetupStepStandalone — same flow as SetupStep but without AuthFormContext.
91
+ * Use this inside ProfileLayout or any page outside AuthLayout.
92
+ */
93
+ export const SetupStepStandalone: React.FC<SetupStepProps> = ({ onComplete, onSkip }) => {
94
+ const {
95
+ isLoading,
96
+ error,
97
+ setupData,
98
+ backupCodes,
99
+ backupCodesWarning,
100
+ setupStep,
101
+ startSetup,
102
+ confirmSetup,
103
+ } = useTwoFactorSetup({ onComplete, onError: () => {} });
104
+
105
+ React.useEffect(() => {
106
+ if (setupStep === 'idle') startSetup();
107
+ }, [setupStep, startSetup]);
108
+
109
+ if (isLoading && !setupData) return <SetupLoading />;
110
+
111
+ if (setupStep === 'complete' && backupCodes) {
112
+ return (
113
+ <SetupComplete
114
+ backupCodes={backupCodes}
115
+ backupCodesWarning={backupCodesWarning}
116
+ onDone={() => onComplete?.()}
117
+ />
118
+ );
119
+ }
120
+
121
+ if (setupData) {
122
+ return (
123
+ <SetupQRCode
124
+ provisioningUri={setupData.provisioningUri}
125
+ secret={setupData.secret}
126
+ isLoading={isLoading}
127
+ error={error}
128
+ onConfirm={confirmSetup}
129
+ onSkip={onSkip}
130
+ />
131
+ );
132
+ }
133
+
134
+ return <SetupLoading />;
135
+ };