@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 +40 -1
- package/package.json +19 -18
- package/src/layouts/AuthLayout/components/steps/SetupStep/index.tsx +50 -6
- package/src/layouts/ProfileLayout/ProfileLayout.tsx +190 -230
- package/src/layouts/ProfileLayout/components/AvatarSection.tsx +2 -3
- package/src/layouts/ProfileLayout/components/EditableField.tsx +15 -10
- package/src/layouts/ProfileLayout/components/Section.tsx +1 -1
- package/src/layouts/ProfileLayout/components/TwoFactorSection.tsx +255 -215
- package/src/layouts/ProfileLayout/context.tsx +110 -10
- package/src/layouts/ProfileLayout/index.ts +1 -1
- package/src/layouts/ProfileLayout/.claude/.sidecar/activity.jsonl +0 -2
- package/src/layouts/ProfileLayout/.claude/.sidecar/history/2026-03-15.md +0 -35
- package/src/layouts/ProfileLayout/.claude/.sidecar/review.md +0 -35
- package/src/layouts/ProfileLayout/.claude/.sidecar/scan.log +0 -3
- package/src/layouts/ProfileLayout/.claude/.sidecar/tasks/T-001.md +0 -18
- package/src/layouts/ProfileLayout/.claude/.sidecar/tasks/T-002.md +0 -19
- package/src/layouts/ProfileLayout/.claude/.sidecar/tasks/T-003.md +0 -18
- package/src/layouts/ProfileLayout/.claude/.sidecar/tasks/T-004.md +0 -18
- package/src/layouts/ProfileLayout/.claude/.sidecar/tasks/T-005.md +0 -18
- package/src/layouts/ProfileLayout/.claude/.sidecar/usage.json +0 -5
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
|
|
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.
|
|
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.
|
|
78
|
-
"@djangocfg/centrifugo": "^2.1.
|
|
79
|
-
"@djangocfg/i18n": "^2.1.
|
|
80
|
-
"@djangocfg/monitor": "^2.1.
|
|
81
|
-
"@djangocfg/debuger": "^2.1.
|
|
82
|
-
"@djangocfg/ui-core": "^2.1.
|
|
83
|
-
"@djangocfg/ui-nextjs": "^2.1.
|
|
84
|
-
"@djangocfg/ui-tools": "^2.1.
|
|
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.
|
|
113
|
-
"@djangocfg/i18n": "^2.1.
|
|
114
|
-
"@djangocfg/centrifugo": "^2.1.
|
|
115
|
-
"@djangocfg/monitor": "^2.1.
|
|
116
|
-
"@djangocfg/debuger": "^2.1.
|
|
117
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
118
|
-
"@djangocfg/ui-core": "^2.1.
|
|
119
|
-
"@djangocfg/ui-nextjs": "^2.1.
|
|
120
|
-
"@djangocfg/ui-tools": "^2.1.
|
|
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
|
+
};
|