@djangocfg/layouts 2.1.548 → 2.1.549
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.549",
|
|
4
4
|
"description": "Simple, straightforward layout components for Next.js - import and use with props",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"layouts",
|
|
@@ -90,11 +90,11 @@
|
|
|
90
90
|
"check": "tsc --noEmit"
|
|
91
91
|
},
|
|
92
92
|
"peerDependencies": {
|
|
93
|
-
"@djangocfg/analytics": "^2.1.
|
|
94
|
-
"@djangocfg/api": "^2.1.
|
|
95
|
-
"@djangocfg/devtools": "^2.1.
|
|
96
|
-
"@djangocfg/i18n": "^2.1.
|
|
97
|
-
"@djangocfg/ui-core": "^2.1.
|
|
93
|
+
"@djangocfg/analytics": "^2.1.549",
|
|
94
|
+
"@djangocfg/api": "^2.1.549",
|
|
95
|
+
"@djangocfg/devtools": "^2.1.549",
|
|
96
|
+
"@djangocfg/i18n": "^2.1.549",
|
|
97
|
+
"@djangocfg/ui-core": "^2.1.549",
|
|
98
98
|
"@hookform/resolvers": "^5.2.2",
|
|
99
99
|
"consola": "^3.4.2",
|
|
100
100
|
"lucide-react": "^0.545.0",
|
|
@@ -124,12 +124,12 @@
|
|
|
124
124
|
"uuid": "^11.1.1"
|
|
125
125
|
},
|
|
126
126
|
"devDependencies": {
|
|
127
|
-
"@djangocfg/analytics": "^2.1.
|
|
128
|
-
"@djangocfg/api": "^2.1.
|
|
129
|
-
"@djangocfg/devtools": "^2.1.
|
|
130
|
-
"@djangocfg/i18n": "^2.1.
|
|
131
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
132
|
-
"@djangocfg/ui-core": "^2.1.
|
|
127
|
+
"@djangocfg/analytics": "^2.1.549",
|
|
128
|
+
"@djangocfg/api": "^2.1.549",
|
|
129
|
+
"@djangocfg/devtools": "^2.1.549",
|
|
130
|
+
"@djangocfg/i18n": "^2.1.549",
|
|
131
|
+
"@djangocfg/typescript-config": "^2.1.549",
|
|
132
|
+
"@djangocfg/ui-core": "^2.1.549",
|
|
133
133
|
"@storybook/react-vite": "^10.5.0",
|
|
134
134
|
"@types/node": "^25.9.5",
|
|
135
135
|
"@types/react": "19.2.15",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import React, { memo, useCallback, useMemo, useState } from 'react';
|
|
3
|
+
import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
4
|
|
|
5
5
|
import { useAppT } from '@djangocfg/i18n';
|
|
6
6
|
|
|
@@ -78,6 +78,15 @@ function OTPStepRaw() {
|
|
|
78
78
|
return `${local[0]}${'*'.repeat(Math.min(local.length - 1, 5))}@${domain}`;
|
|
79
79
|
}, [identifier]);
|
|
80
80
|
|
|
81
|
+
const autoSubmitTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
82
|
+
|
|
83
|
+
useEffect(
|
|
84
|
+
() => () => {
|
|
85
|
+
if (autoSubmitTimerRef.current) clearTimeout(autoSubmitTimerRef.current);
|
|
86
|
+
},
|
|
87
|
+
[]
|
|
88
|
+
);
|
|
89
|
+
|
|
81
90
|
// Auto-submit on complete (state machine approach)
|
|
82
91
|
const handleOTPComplete = useCallback(
|
|
83
92
|
async (completedValue: string) => {
|
|
@@ -87,7 +96,11 @@ function OTPStepRaw() {
|
|
|
87
96
|
setSubmitState('submitting');
|
|
88
97
|
const fakeEvent = { preventDefault: () => {} } as React.FormEvent;
|
|
89
98
|
|
|
90
|
-
|
|
99
|
+
// Tracked so leaving the step cancels it. This component unmounts when
|
|
100
|
+
// the user goes back to the identifier, and an uncancelled timer would
|
|
101
|
+
// submit the code they just abandoned.
|
|
102
|
+
autoSubmitTimerRef.current = setTimeout(async () => {
|
|
103
|
+
autoSubmitTimerRef.current = null;
|
|
91
104
|
try {
|
|
92
105
|
await handleOTPSubmit(fakeEvent);
|
|
93
106
|
} finally {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useCallback, useState } from 'react';
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
4
|
|
|
5
5
|
import { AUTH } from '../constants';
|
|
6
6
|
|
|
@@ -18,13 +18,27 @@ export const useCopyToClipboard = (
|
|
|
18
18
|
duration = AUTH.COPY_FEEDBACK_DURATION
|
|
19
19
|
): UseCopyToClipboardResult => {
|
|
20
20
|
const [copied, setCopied] = useState(false);
|
|
21
|
+
// One timer, cleared on unmount. Copying twice in quick succession stacked
|
|
22
|
+
// two, so the first cleared the flag while the second copy was still fresh.
|
|
23
|
+
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
24
|
+
|
|
25
|
+
useEffect(
|
|
26
|
+
() => () => {
|
|
27
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
28
|
+
},
|
|
29
|
+
[]
|
|
30
|
+
);
|
|
21
31
|
|
|
22
32
|
const copy = useCallback(
|
|
23
33
|
async (text: string) => {
|
|
24
34
|
try {
|
|
25
35
|
await navigator.clipboard.writeText(text);
|
|
26
36
|
setCopied(true);
|
|
27
|
-
|
|
37
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
38
|
+
timerRef.current = setTimeout(() => {
|
|
39
|
+
timerRef.current = null;
|
|
40
|
+
setCopied(false);
|
|
41
|
+
}, duration);
|
|
28
42
|
} catch {
|
|
29
43
|
// Clipboard API not available
|
|
30
44
|
console.warn('Clipboard API not available');
|
|
@@ -77,6 +77,7 @@ export const MockAuthFormProvider: React.FC<MockAuthFormProviderProps> = ({
|
|
|
77
77
|
}) => {
|
|
78
78
|
const [step, setStep] = useState<AuthStep>(initialStep);
|
|
79
79
|
const [identifier, setIdentifier] = useState(initialIdentifier);
|
|
80
|
+
const [password, setPassword] = useState('');
|
|
80
81
|
const [otp, setOtp] = useState(initialOtp);
|
|
81
82
|
const [isLoading, setIsLoading] = useState(initialLoading);
|
|
82
83
|
const [acceptedTerms, setAcceptedTerms] = useState(initialAcceptedTerms);
|
|
@@ -100,6 +101,7 @@ export const MockAuthFormProvider: React.FC<MockAuthFormProviderProps> = ({
|
|
|
100
101
|
return {
|
|
101
102
|
// State
|
|
102
103
|
identifier,
|
|
104
|
+
password,
|
|
103
105
|
otp,
|
|
104
106
|
isLoading,
|
|
105
107
|
acceptedTerms,
|
|
@@ -118,6 +120,7 @@ export const MockAuthFormProvider: React.FC<MockAuthFormProviderProps> = ({
|
|
|
118
120
|
|
|
119
121
|
// State handlers
|
|
120
122
|
setIdentifier,
|
|
123
|
+
setPassword,
|
|
121
124
|
setOtp,
|
|
122
125
|
setAcceptedTerms,
|
|
123
126
|
setRememberMe,
|
|
@@ -137,6 +140,7 @@ export const MockAuthFormProvider: React.FC<MockAuthFormProviderProps> = ({
|
|
|
137
140
|
// step never changes from under the storyteller. To preview a
|
|
138
141
|
// different step, render a new story with `step="..."`.
|
|
139
142
|
handleIdentifierSubmit: async (e) => stop(e),
|
|
143
|
+
handlePasswordSubmit: async (e) => stop(e),
|
|
140
144
|
handleOTPSubmit: async (e) => stop(e),
|
|
141
145
|
handleResendOTP: async () => {},
|
|
142
146
|
handleBackToIdentifier: () => setStep('identifier'),
|