@djangocfg/layouts 2.1.29 → 2.1.31
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/layouts",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.31",
|
|
4
4
|
"description": "Simple, straightforward layout components for Next.js - import and use with props",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"layouts",
|
|
@@ -92,9 +92,9 @@
|
|
|
92
92
|
"check": "tsc --noEmit"
|
|
93
93
|
},
|
|
94
94
|
"peerDependencies": {
|
|
95
|
-
"@djangocfg/api": "^2.1.
|
|
96
|
-
"@djangocfg/centrifugo": "^2.1.
|
|
97
|
-
"@djangocfg/ui-nextjs": "^2.1.
|
|
95
|
+
"@djangocfg/api": "^2.1.31",
|
|
96
|
+
"@djangocfg/centrifugo": "^2.1.31",
|
|
97
|
+
"@djangocfg/ui-nextjs": "^2.1.31",
|
|
98
98
|
"@hookform/resolvers": "^5.2.0",
|
|
99
99
|
"consola": "^3.4.2",
|
|
100
100
|
"lucide-react": "^0.545.0",
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
"uuid": "^11.1.0"
|
|
115
115
|
},
|
|
116
116
|
"devDependencies": {
|
|
117
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
117
|
+
"@djangocfg/typescript-config": "^2.1.31",
|
|
118
118
|
"@types/node": "^24.7.2",
|
|
119
119
|
"@types/react": "^19.1.0",
|
|
120
120
|
"@types/react-dom": "^19.1.0",
|
|
@@ -104,7 +104,10 @@ export const IdentifierForm: React.FC = () => {
|
|
|
104
104
|
? 'Enter your phone number to receive a verification code via SMS'
|
|
105
105
|
: 'Enter your email address to receive a verification code';
|
|
106
106
|
};
|
|
107
|
-
|
|
107
|
+
|
|
108
|
+
// Check if we have any links for terms/privacy - if not, we don't show the checkbox
|
|
109
|
+
const hasAnyLinks = Boolean(termsUrl || privacyUrl);
|
|
110
|
+
|
|
108
111
|
return (
|
|
109
112
|
<Card className="w-full max-w-md mx-auto shadow-lg border border-border bg-card/50 backdrop-blur-sm">
|
|
110
113
|
<CardHeader className="text-center pb-6">
|
|
@@ -173,44 +176,46 @@ export const IdentifierForm: React.FC = () => {
|
|
|
173
176
|
/>
|
|
174
177
|
</TabsContent>
|
|
175
178
|
|
|
176
|
-
{/* Terms and Conditions */}
|
|
177
|
-
|
|
178
|
-
<
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
<
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
179
|
+
{/* Terms and Conditions - only show if we have links */}
|
|
180
|
+
{hasAnyLinks && (
|
|
181
|
+
<div className="flex items-start gap-3">
|
|
182
|
+
<Checkbox
|
|
183
|
+
id="terms"
|
|
184
|
+
checked={acceptedTerms}
|
|
185
|
+
onCheckedChange={setAcceptedTerms}
|
|
186
|
+
disabled={isLoading}
|
|
187
|
+
className="mt-1"
|
|
188
|
+
/>
|
|
189
|
+
<div className="text-sm text-muted-foreground leading-5">
|
|
190
|
+
<Label htmlFor="terms" className="cursor-pointer">
|
|
191
|
+
I agree to the{' '}
|
|
192
|
+
{termsUrl && (
|
|
193
|
+
<>
|
|
194
|
+
<a
|
|
195
|
+
href={termsUrl}
|
|
196
|
+
target="_blank"
|
|
197
|
+
rel="noopener noreferrer"
|
|
198
|
+
className="text-primary hover:underline font-medium"
|
|
199
|
+
>
|
|
200
|
+
Terms of Service
|
|
201
|
+
</a>
|
|
202
|
+
{privacyUrl && <>{' '}and{' '}</>}
|
|
203
|
+
</>
|
|
204
|
+
)}
|
|
205
|
+
{privacyUrl && (
|
|
190
206
|
<a
|
|
191
|
-
href={
|
|
207
|
+
href={privacyUrl}
|
|
192
208
|
target="_blank"
|
|
193
209
|
rel="noopener noreferrer"
|
|
194
210
|
className="text-primary hover:underline font-medium"
|
|
195
211
|
>
|
|
196
|
-
|
|
197
|
-
</a>
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
{privacyUrl && (
|
|
202
|
-
<a
|
|
203
|
-
href={privacyUrl}
|
|
204
|
-
target="_blank"
|
|
205
|
-
rel="noopener noreferrer"
|
|
206
|
-
className="text-primary hover:underline font-medium"
|
|
207
|
-
>
|
|
208
|
-
Privacy Policy
|
|
209
|
-
</a>
|
|
210
|
-
)}
|
|
211
|
-
</Label>
|
|
212
|
+
Privacy Policy
|
|
213
|
+
</a>
|
|
214
|
+
)}
|
|
215
|
+
</Label>
|
|
216
|
+
</div>
|
|
212
217
|
</div>
|
|
213
|
-
|
|
218
|
+
)}
|
|
214
219
|
|
|
215
220
|
{/* Error Message */}
|
|
216
221
|
{error && (
|
|
@@ -223,7 +228,7 @@ export const IdentifierForm: React.FC = () => {
|
|
|
223
228
|
<Button
|
|
224
229
|
type="submit"
|
|
225
230
|
className="w-full h-11 text-base font-medium"
|
|
226
|
-
disabled={isLoading || !identifier || !acceptedTerms}
|
|
231
|
+
disabled={isLoading || !identifier || (hasAnyLinks && !acceptedTerms)}
|
|
227
232
|
>
|
|
228
233
|
{isLoading ? (
|
|
229
234
|
<div className="flex items-center gap-2">
|
|
@@ -262,44 +267,46 @@ export const IdentifierForm: React.FC = () => {
|
|
|
262
267
|
/>
|
|
263
268
|
</div>
|
|
264
269
|
|
|
265
|
-
{/* Terms and Conditions */}
|
|
266
|
-
|
|
267
|
-
<
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
<
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
270
|
+
{/* Terms and Conditions - only show if we have links */}
|
|
271
|
+
{hasAnyLinks && (
|
|
272
|
+
<div className="flex items-start gap-3">
|
|
273
|
+
<Checkbox
|
|
274
|
+
id="terms-email"
|
|
275
|
+
checked={acceptedTerms}
|
|
276
|
+
onCheckedChange={setAcceptedTerms}
|
|
277
|
+
disabled={isLoading}
|
|
278
|
+
className="mt-1"
|
|
279
|
+
/>
|
|
280
|
+
<div className="text-sm text-muted-foreground leading-5">
|
|
281
|
+
<Label htmlFor="terms-email" className="cursor-pointer">
|
|
282
|
+
I agree to the{' '}
|
|
283
|
+
{termsUrl && (
|
|
284
|
+
<>
|
|
285
|
+
<a
|
|
286
|
+
href={termsUrl}
|
|
287
|
+
target="_blank"
|
|
288
|
+
rel="noopener noreferrer"
|
|
289
|
+
className="text-primary hover:underline font-medium"
|
|
290
|
+
>
|
|
291
|
+
Terms of Service
|
|
292
|
+
</a>
|
|
293
|
+
{privacyUrl && <>{' '}and{' '}</>}
|
|
294
|
+
</>
|
|
295
|
+
)}
|
|
296
|
+
{privacyUrl && (
|
|
279
297
|
<a
|
|
280
|
-
href={
|
|
298
|
+
href={privacyUrl}
|
|
281
299
|
target="_blank"
|
|
282
300
|
rel="noopener noreferrer"
|
|
283
301
|
className="text-primary hover:underline font-medium"
|
|
284
302
|
>
|
|
285
|
-
|
|
286
|
-
</a>
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
{privacyUrl && (
|
|
291
|
-
<a
|
|
292
|
-
href={privacyUrl}
|
|
293
|
-
target="_blank"
|
|
294
|
-
rel="noopener noreferrer"
|
|
295
|
-
className="text-primary hover:underline font-medium"
|
|
296
|
-
>
|
|
297
|
-
Privacy Policy
|
|
298
|
-
</a>
|
|
299
|
-
)}
|
|
300
|
-
</Label>
|
|
303
|
+
Privacy Policy
|
|
304
|
+
</a>
|
|
305
|
+
)}
|
|
306
|
+
</Label>
|
|
307
|
+
</div>
|
|
301
308
|
</div>
|
|
302
|
-
|
|
309
|
+
)}
|
|
303
310
|
|
|
304
311
|
{/* Error Message */}
|
|
305
312
|
{error && (
|
|
@@ -312,7 +319,7 @@ export const IdentifierForm: React.FC = () => {
|
|
|
312
319
|
<Button
|
|
313
320
|
type="submit"
|
|
314
321
|
className="w-full h-11 text-base font-medium"
|
|
315
|
-
disabled={isLoading || !identifier || !acceptedTerms}
|
|
322
|
+
disabled={isLoading || !identifier || (hasAnyLinks && !acceptedTerms)}
|
|
316
323
|
>
|
|
317
324
|
{isLoading ? (
|
|
318
325
|
<div className="flex items-center gap-2">
|
|
@@ -10,13 +10,12 @@ import {
|
|
|
10
10
|
CardDescription,
|
|
11
11
|
CardHeader,
|
|
12
12
|
CardTitle,
|
|
13
|
-
|
|
14
|
-
InputOTPGroup,
|
|
15
|
-
InputOTPSlot,
|
|
13
|
+
OTPInput,
|
|
16
14
|
} from '@djangocfg/ui-nextjs/components';
|
|
17
15
|
|
|
18
16
|
import { useAuthContext } from './AuthContext';
|
|
19
17
|
import { AuthHelp } from './AuthHelp';
|
|
18
|
+
import { config } from '../../utils';
|
|
20
19
|
|
|
21
20
|
export const OTPForm: React.FC = () => {
|
|
22
21
|
const {
|
|
@@ -72,41 +71,24 @@ export const OTPForm: React.FC = () => {
|
|
|
72
71
|
Enter verification code
|
|
73
72
|
</label>
|
|
74
73
|
<div className="flex justify-center">
|
|
75
|
-
<
|
|
74
|
+
<OTPInput
|
|
75
|
+
length={6}
|
|
76
|
+
validationMode="numeric"
|
|
77
|
+
pasteBehavior="clean"
|
|
76
78
|
value={otp}
|
|
77
79
|
onChange={setOtp}
|
|
78
|
-
maxLength={6}
|
|
79
80
|
disabled={isLoading}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
<InputOTPSlot
|
|
84
|
-
index={0}
|
|
85
|
-
className="h-12 w-12 text-lg font-semibold border-2 border-border bg-background rounded-sm shadow-sm"
|
|
86
|
-
/>
|
|
87
|
-
<InputOTPSlot
|
|
88
|
-
index={1}
|
|
89
|
-
className="h-12 w-12 text-lg font-semibold border-2 border-border bg-background rounded-sm shadow-sm"
|
|
90
|
-
/>
|
|
91
|
-
<InputOTPSlot
|
|
92
|
-
index={2}
|
|
93
|
-
className="h-12 w-12 text-lg font-semibold border-2 border-border bg-background rounded-sm shadow-sm"
|
|
94
|
-
/>
|
|
95
|
-
<InputOTPSlot
|
|
96
|
-
index={3}
|
|
97
|
-
className="h-12 w-12 text-lg font-semibold border-2 border-border bg-background rounded-sm shadow-sm"
|
|
98
|
-
/>
|
|
99
|
-
<InputOTPSlot
|
|
100
|
-
index={4}
|
|
101
|
-
className="h-12 w-12 text-lg font-semibold border-2 border-border bg-background rounded-sm shadow-sm"
|
|
102
|
-
/>
|
|
103
|
-
<InputOTPSlot
|
|
104
|
-
index={5}
|
|
105
|
-
className="h-12 w-12 text-lg font-semibold border-2 border-border bg-background rounded-sm shadow-sm"
|
|
106
|
-
/>
|
|
107
|
-
</InputOTPGroup>
|
|
108
|
-
</InputOTP>
|
|
81
|
+
autoFocus={true}
|
|
82
|
+
size="lg"
|
|
83
|
+
/>
|
|
109
84
|
</div>
|
|
85
|
+
|
|
86
|
+
{/* Development Mode Notice */}
|
|
87
|
+
{config.isDevelopment && (
|
|
88
|
+
<div className="text-xs text-amber-600 dark:text-amber-400 bg-amber-50 dark:bg-amber-950/30 p-2 rounded-md border border-amber-200 dark:border-amber-800 text-center">
|
|
89
|
+
🔧 Dev Mode: Any OTP code works
|
|
90
|
+
</div>
|
|
91
|
+
)}
|
|
110
92
|
</div>
|
|
111
93
|
|
|
112
94
|
<div className="space-y-4">
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frontend configuration from environment variables
|
|
3
|
+
*/
|
|
4
|
+
export const config = {
|
|
5
|
+
/**
|
|
6
|
+
* Development mode flag
|
|
7
|
+
* In development mode, any OTP code is accepted for authentication
|
|
8
|
+
*/
|
|
9
|
+
isDevelopment: process.env.NODE_ENV === 'development',
|
|
10
|
+
} as const;
|