@djangocfg/layouts 2.1.226 → 2.1.228

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.
Files changed (97) hide show
  1. package/README.md +3 -17
  2. package/package.json +18 -18
  3. package/src/components/errors/ErrorLayout.tsx +2 -2
  4. package/src/components/errors/ErrorsTracker/index.ts +1 -0
  5. package/src/components/errors/ErrorsTracker/utils/formatters.ts +23 -1
  6. package/src/hooks/useLogout.ts +9 -12
  7. package/src/layouts/AppLayout/AppLayout.tsx +20 -8
  8. package/src/layouts/AppLayout/BaseApp.tsx +5 -28
  9. package/src/layouts/AuthLayout/AuthLayout.tsx +51 -22
  10. package/src/layouts/AuthLayout/README.md +78 -0
  11. package/src/layouts/AuthLayout/components/shared/AuthDivider.tsx +2 -2
  12. package/src/layouts/AuthLayout/components/shared/AuthError.tsx +10 -2
  13. package/src/layouts/AuthLayout/components/shared/AuthFooter.tsx +2 -2
  14. package/src/layouts/AuthLayout/components/shared/AuthHeader.tsx +3 -2
  15. package/src/layouts/AuthLayout/components/shared/AuthOTPInput.tsx +4 -1
  16. package/src/layouts/AuthLayout/components/shared/TermsCheckbox.tsx +2 -2
  17. package/src/layouts/AuthLayout/components/shared/index.ts +0 -2
  18. package/src/layouts/AuthLayout/components/steps/IdentifierStep.tsx +25 -80
  19. package/src/layouts/AuthLayout/components/steps/OTPStep.tsx +8 -13
  20. package/src/layouts/AuthLayout/components/steps/SetupStep/SetupComplete.tsx +2 -2
  21. package/src/layouts/AuthLayout/components/steps/SetupStep/SetupLoading.tsx +2 -2
  22. package/src/layouts/AuthLayout/components/steps/SetupStep/SetupQRCode.tsx +2 -2
  23. package/src/layouts/AuthLayout/components/steps/TwoFactorStep.tsx +61 -42
  24. package/src/layouts/AuthLayout/context.tsx +0 -2
  25. package/src/layouts/AuthLayout/index.ts +9 -6
  26. package/src/layouts/AuthLayout/styles/auth.css +265 -120
  27. package/src/layouts/AuthLayout/types.ts +60 -7
  28. package/src/layouts/ProfileLayout/.claude/.sidecar/activity.jsonl +2 -0
  29. package/src/layouts/ProfileLayout/.claude/.sidecar/history/2026-03-15.md +35 -0
  30. package/src/layouts/ProfileLayout/.claude/.sidecar/review.md +35 -0
  31. package/src/layouts/ProfileLayout/.claude/.sidecar/scan.log +3 -0
  32. package/src/layouts/ProfileLayout/.claude/.sidecar/tasks/T-001.md +18 -0
  33. package/src/layouts/ProfileLayout/.claude/.sidecar/tasks/T-002.md +19 -0
  34. package/src/layouts/ProfileLayout/.claude/.sidecar/tasks/T-003.md +18 -0
  35. package/src/layouts/ProfileLayout/.claude/.sidecar/tasks/T-004.md +18 -0
  36. package/src/layouts/ProfileLayout/.claude/.sidecar/tasks/T-005.md +18 -0
  37. package/src/layouts/ProfileLayout/.claude/.sidecar/usage.json +5 -0
  38. package/src/layouts/ProfileLayout/ProfileLayout.tsx +52 -403
  39. package/src/layouts/ProfileLayout/components/ActionButton.tsx +38 -0
  40. package/src/layouts/ProfileLayout/components/DeleteAccountSection.tsx +109 -148
  41. package/src/layouts/ProfileLayout/components/EditableField.tsx +119 -0
  42. package/src/layouts/ProfileLayout/components/Section.tsx +22 -0
  43. package/src/layouts/ProfileLayout/components/index.ts +4 -1
  44. package/src/layouts/ProfileLayout/context.tsx +31 -0
  45. package/src/layouts/PublicLayout/components/PublicMobileDrawer.tsx +2 -2
  46. package/src/layouts/PublicLayout/components/PublicNavigation.tsx +2 -2
  47. package/src/layouts/_components/UserMenu.tsx +2 -2
  48. package/src/layouts/types/README.md +0 -20
  49. package/src/layouts/types/index.ts +2 -2
  50. package/src/layouts/types/layout.types.ts +2 -5
  51. package/src/layouts/types/providers.types.ts +0 -27
  52. package/src/snippets/AuthDialog/AuthDialog.tsx +2 -2
  53. package/src/snippets/Breadcrumbs.tsx +2 -2
  54. package/src/snippets/index.ts +0 -67
  55. package/src/layouts/AuthLayout/components/shared/ChannelToggle.tsx +0 -56
  56. package/src/snippets/McpChat/README.md +0 -441
  57. package/src/snippets/McpChat/components/AIChatWidget.tsx +0 -361
  58. package/src/snippets/McpChat/components/AskAIButton.tsx +0 -92
  59. package/src/snippets/McpChat/components/ChatMessages.tsx +0 -138
  60. package/src/snippets/McpChat/components/ChatPanel.tsx +0 -131
  61. package/src/snippets/McpChat/components/ChatSidebar.tsx +0 -156
  62. package/src/snippets/McpChat/components/ChatWidget.tsx +0 -115
  63. package/src/snippets/McpChat/components/MessageBubble.tsx +0 -142
  64. package/src/snippets/McpChat/components/MessageInput.tsx +0 -140
  65. package/src/snippets/McpChat/components/index.ts +0 -24
  66. package/src/snippets/McpChat/config.ts +0 -94
  67. package/src/snippets/McpChat/context/AIChatContext.tsx +0 -327
  68. package/src/snippets/McpChat/context/ChatContext.tsx +0 -361
  69. package/src/snippets/McpChat/context/index.ts +0 -7
  70. package/src/snippets/McpChat/hooks/index.ts +0 -6
  71. package/src/snippets/McpChat/hooks/useAIChat.ts +0 -503
  72. package/src/snippets/McpChat/hooks/useChatLayout.ts +0 -442
  73. package/src/snippets/McpChat/hooks/useMcpChat.ts +0 -90
  74. package/src/snippets/McpChat/index.ts +0 -79
  75. package/src/snippets/McpChat/types.ts +0 -189
  76. package/src/snippets/PWAInstall/@docs/README.md +0 -92
  77. package/src/snippets/PWAInstall/@docs/research/ios-android-install-flows.md +0 -576
  78. package/src/snippets/PWAInstall/README.md +0 -235
  79. package/src/snippets/PWAInstall/components/A2HSHint.tsx +0 -236
  80. package/src/snippets/PWAInstall/components/DesktopGuide.tsx +0 -234
  81. package/src/snippets/PWAInstall/components/IOSGuide.tsx +0 -29
  82. package/src/snippets/PWAInstall/components/IOSGuideDrawer.tsx +0 -103
  83. package/src/snippets/PWAInstall/components/IOSGuideModal.tsx +0 -103
  84. package/src/snippets/PWAInstall/components/PWAPageResumeManager.tsx +0 -33
  85. package/src/snippets/PWAInstall/context/InstallContext.tsx +0 -102
  86. package/src/snippets/PWAInstall/hooks/useInstallPrompt.ts +0 -168
  87. package/src/snippets/PWAInstall/hooks/useIsPWA.ts +0 -116
  88. package/src/snippets/PWAInstall/hooks/usePWAPageResume.ts +0 -163
  89. package/src/snippets/PWAInstall/index.ts +0 -80
  90. package/src/snippets/PWAInstall/types/components.ts +0 -95
  91. package/src/snippets/PWAInstall/types/config.ts +0 -29
  92. package/src/snippets/PWAInstall/types/index.ts +0 -26
  93. package/src/snippets/PWAInstall/types/install.ts +0 -38
  94. package/src/snippets/PWAInstall/types/platform.ts +0 -29
  95. package/src/snippets/PWAInstall/utils/localStorage.ts +0 -181
  96. package/src/snippets/PWAInstall/utils/logger.ts +0 -149
  97. package/src/snippets/PWAInstall/utils/platform.ts +0 -151
@@ -1,167 +1,128 @@
1
1
  'use client';
2
2
 
3
- import { AlertTriangle, Loader2, Trash2 } from 'lucide-react';
4
- import React, { useState } from 'react';
3
+ import { AlertTriangle, ChevronLeft, Loader2, Trash2 } from 'lucide-react';
4
+ import React, { useMemo, useState } from 'react';
5
5
 
6
6
  import { useAuth, useDeleteAccount } from '@djangocfg/api/auth';
7
- import {
8
- Alert,
9
- AlertDescription,
10
- Button,
11
- Card,
12
- CardContent,
13
- CardDescription,
14
- CardHeader,
15
- CardTitle,
16
- Dialog,
17
- DialogContent,
18
- DialogDescription,
19
- DialogFooter,
20
- DialogHeader,
21
- DialogTitle,
22
- Input,
23
- } from '@djangocfg/ui-core/components';
24
-
25
- const CONFIRMATION_TEXT = 'DELETE';
26
-
27
- /**
28
- * Delete Account section for ProfileLayout.
29
- * Allows users to permanently delete their account.
30
- */
7
+ import { useAppT } from '@djangocfg/i18n';
8
+ import { Alert, AlertDescription, Button, Input } from '@djangocfg/ui-core/components';
9
+
10
+ import { useProfileContext } from '../context';
11
+ import { ActionButton } from './ActionButton';
12
+
13
+ // ─── Entry point: single action row on main screen ───────────────────────────
14
+
31
15
  export const DeleteAccountSection: React.FC = () => {
32
- const [showDeleteDialog, setShowDeleteDialog] = useState(false);
33
- const [confirmationInput, setConfirmationInput] = useState('');
16
+ const { setStep } = useProfileContext();
17
+ const t = useAppT();
18
+
19
+ return (
20
+ <ActionButton
21
+ icon={<Trash2 className="w-4 h-4 text-destructive" />}
22
+ label={<span className="text-destructive">{t('layouts.profilePage.deleteAccount')}</span>}
23
+ onClick={() => setStep('delete-account')}
24
+ />
25
+ );
26
+ };
27
+
28
+ // ─── Full delete screen ───────────────────────────────────────────────────────
29
+
30
+ export const DeleteAccountScreen: React.FC = () => {
31
+ const { back } = useProfileContext();
34
32
  const { logout } = useAuth();
33
+ const [confirmationInput, setConfirmationInput] = useState('');
34
+ const t = useAppT();
35
35
 
36
- const {
37
- isLoading,
38
- error,
39
- deleteAccount,
40
- clearError,
41
- } = useDeleteAccount();
36
+ const { isLoading, error, deleteAccount, clearError } = useDeleteAccount();
42
37
 
43
- const handleDeleteClick = () => {
44
- setShowDeleteDialog(true);
45
- setConfirmationInput('');
46
- clearError();
47
- };
38
+ const confirmationWord = t('layouts.profilePage.confirmationWord');
39
+ const isValid = confirmationInput.toUpperCase() === confirmationWord.toUpperCase();
40
+
41
+ const labels = useMemo(() => ({
42
+ back: t('layouts.navigation.back'),
43
+ title: t('layouts.profilePage.deleteAccountTitle'),
44
+ desc: t('layouts.profilePage.deleteAccountDesc'),
45
+ typeToConfirm: t('layouts.profilePage.typeToConfirm').replace('{word}', confirmationWord),
46
+ deleting: t('layouts.profilePage.deleting'),
47
+ deleteAccount: t('layouts.profilePage.deleteAccount'),
48
+ cancel: t('layouts.profilePage.cancel'),
49
+ }), [t, confirmationWord]);
48
50
 
49
- const handleDeleteConfirm = async () => {
51
+ const handleDelete = async () => {
52
+ clearError();
50
53
  const result = await deleteAccount();
51
- if (result.success) {
52
- setShowDeleteDialog(false);
53
- // Perform logout after successful deletion (no confirmation needed since user already confirmed deletion)
54
- logout();
55
- }
54
+ if (result.success) logout();
56
55
  };
57
56
 
58
- const handleDeleteCancel = () => {
59
- setShowDeleteDialog(false);
60
- setConfirmationInput('');
57
+ const handleBack = () => {
61
58
  clearError();
59
+ setConfirmationInput('');
60
+ back();
62
61
  };
63
62
 
64
- const isConfirmationValid = confirmationInput.toUpperCase() === CONFIRMATION_TEXT;
65
-
66
63
  return (
67
- <>
68
- <Card className="bg-card/50 backdrop-blur-sm border-red-200 dark:border-red-800/50">
69
- <CardHeader>
70
- <CardTitle className="flex items-center gap-2 text-red-600 dark:text-red-400">
71
- <Trash2 className="w-5 h-5" />
72
- Delete Account
73
- </CardTitle>
74
- <CardDescription>
75
- Permanently delete your account and all associated data
76
- </CardDescription>
77
- </CardHeader>
78
-
79
- <CardContent className="space-y-4">
80
- <Alert variant="destructive" className="bg-red-50 dark:bg-red-900/20 border-red-200 dark:border-red-800">
81
- <AlertTriangle className="w-4 h-4" />
82
- <AlertDescription>
83
- This action is irreversible. Your account will be deactivated and your personal data will be anonymized.
84
- </AlertDescription>
64
+ <div className="container mx-auto px-4 py-12 max-w-md">
65
+ {/* Back */}
66
+ <button
67
+ type="button"
68
+ onClick={handleBack}
69
+ className="flex items-center gap-1 text-sm text-muted-foreground mb-8 hover:text-foreground transition-colors"
70
+ >
71
+ <ChevronLeft className="w-4 h-4" />
72
+ {labels.back}
73
+ </button>
74
+
75
+ {/* Header */}
76
+ <div className="flex items-center gap-3 mb-2">
77
+ <div className="w-10 h-10 rounded-full bg-destructive/10 flex items-center justify-center">
78
+ <AlertTriangle className="w-5 h-5 text-destructive" />
79
+ </div>
80
+ <h1 className="text-xl font-semibold">{labels.title}</h1>
81
+ </div>
82
+ <p className="text-sm text-muted-foreground mb-8">{labels.desc}</p>
83
+
84
+ {/* Confirmation */}
85
+ <div className="space-y-3">
86
+ {error && (
87
+ <Alert variant="destructive">
88
+ <AlertDescription>{error}</AlertDescription>
85
89
  </Alert>
86
-
87
- <div className="flex items-center justify-between p-4 bg-muted/50 rounded-lg">
88
- <div>
89
- <p className="font-medium">Delete your account</p>
90
- <p className="text-sm text-muted-foreground">
91
- You will lose access to all your data and workspaces
92
- </p>
93
- </div>
94
- <Button
95
- variant="destructive"
96
- onClick={handleDeleteClick}
97
- disabled={isLoading}
98
- >
99
- Delete Account
100
- </Button>
101
- </div>
102
- </CardContent>
103
- </Card>
104
-
105
- {/* Delete Account Dialog */}
106
- <Dialog open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
107
- <DialogContent>
108
- <DialogHeader>
109
- <DialogTitle className="flex items-center gap-2 text-red-600">
110
- <AlertTriangle className="w-5 h-5" />
111
- Delete Account
112
- </DialogTitle>
113
- <DialogDescription>
114
- This action cannot be undone. This will permanently deactivate your account
115
- and anonymize your personal data.
116
- </DialogDescription>
117
- </DialogHeader>
118
-
119
- <div className="py-4 space-y-4">
120
- {error && (
121
- <Alert variant="destructive">
122
- <AlertDescription>{error}</AlertDescription>
123
- </Alert>
124
- )}
125
-
126
- <div className="space-y-2">
127
- <p className="text-sm text-muted-foreground">
128
- To confirm, type <span className="font-mono font-bold">{CONFIRMATION_TEXT}</span> below:
129
- </p>
130
- <Input
131
- value={confirmationInput}
132
- onChange={(e) => setConfirmationInput(e.target.value)}
133
- placeholder={CONFIRMATION_TEXT}
134
- disabled={isLoading}
135
- autoComplete="off"
136
- />
137
- </div>
138
- </div>
139
-
140
- <DialogFooter>
141
- <Button
142
- variant="outline"
143
- onClick={handleDeleteCancel}
144
- disabled={isLoading}
145
- >
146
- Cancel
147
- </Button>
148
- <Button
149
- variant="destructive"
150
- onClick={handleDeleteConfirm}
151
- disabled={isLoading || !isConfirmationValid}
152
- >
153
- {isLoading ? (
154
- <>
155
- <Loader2 className="mr-2 h-4 w-4 animate-spin" />
156
- Deleting...
157
- </>
158
- ) : (
159
- 'Delete Account'
160
- )}
161
- </Button>
162
- </DialogFooter>
163
- </DialogContent>
164
- </Dialog>
165
- </>
90
+ )}
91
+
92
+ <p className="text-sm text-muted-foreground">{labels.typeToConfirm}</p>
93
+
94
+ <Input
95
+ value={confirmationInput}
96
+ onChange={(e) => setConfirmationInput(e.target.value)}
97
+ placeholder={confirmationWord}
98
+ disabled={isLoading}
99
+ autoFocus
100
+ autoComplete="off"
101
+ className="font-mono"
102
+ />
103
+
104
+ <Button
105
+ variant="destructive"
106
+ className="w-full"
107
+ onClick={handleDelete}
108
+ disabled={isLoading || !isValid}
109
+ >
110
+ {isLoading ? (
111
+ <><Loader2 className="mr-2 h-4 w-4 animate-spin" />{labels.deleting}</>
112
+ ) : (
113
+ labels.deleteAccount
114
+ )}
115
+ </Button>
116
+
117
+ <Button
118
+ variant="ghost"
119
+ className="w-full"
120
+ onClick={handleBack}
121
+ disabled={isLoading}
122
+ >
123
+ {labels.cancel}
124
+ </Button>
125
+ </div>
126
+ </div>
166
127
  );
167
128
  };
@@ -0,0 +1,119 @@
1
+ 'use client';
2
+
3
+ import React, { useEffect, useMemo, useState } from 'react';
4
+
5
+ import { useAppT } from '@djangocfg/i18n';
6
+ import { Button, Input, PhoneInput } from '@djangocfg/ui-core/components';
7
+ import { cn } from '@djangocfg/ui-core/lib';
8
+
9
+ interface EditableFieldProps {
10
+ label: string;
11
+ value: string;
12
+ placeholder: string;
13
+ onSave: (value: string) => Promise<void>;
14
+ disabled?: boolean;
15
+ type?: 'text' | 'phone';
16
+ }
17
+
18
+ export const EditableField = ({
19
+ label,
20
+ value,
21
+ placeholder,
22
+ onSave,
23
+ disabled,
24
+ type = 'text',
25
+ }: EditableFieldProps) => {
26
+ const t = useAppT();
27
+ const [isEditing, setIsEditing] = useState(false);
28
+ const [editValue, setEditValue] = useState(value);
29
+ const [isSaving, setIsSaving] = useState(false);
30
+
31
+ const labels = useMemo(() => ({
32
+ save: t('layouts.profilePage.save'),
33
+ saving: t('layouts.profilePage.saving'),
34
+ cancel: t('layouts.profilePage.cancel'),
35
+ }), [t]);
36
+
37
+ useEffect(() => {
38
+ setEditValue(value);
39
+ }, [value]);
40
+
41
+ const handleSave = async () => {
42
+ if (editValue === value) {
43
+ setIsEditing(false);
44
+ return;
45
+ }
46
+ setIsSaving(true);
47
+ try {
48
+ await onSave(editValue);
49
+ setIsEditing(false);
50
+ } finally {
51
+ setIsSaving(false);
52
+ }
53
+ };
54
+
55
+ const handleCancel = () => {
56
+ setEditValue(value);
57
+ setIsEditing(false);
58
+ };
59
+
60
+ const handleKeyDown = (e: React.KeyboardEvent) => {
61
+ if (e.key === 'Enter') handleSave();
62
+ else if (e.key === 'Escape') handleCancel();
63
+ };
64
+
65
+ if (isEditing) {
66
+ return (
67
+ <div className="py-4 border-b border-border/50 last:border-0">
68
+ <label className="block text-[13px] text-muted-foreground mb-1.5">{label}</label>
69
+ {type === 'phone' ? (
70
+ <div className="space-y-2">
71
+ <PhoneInput
72
+ value={editValue}
73
+ onChange={(val) => setEditValue(val ?? '')}
74
+ placeholder={placeholder}
75
+ disabled={isSaving}
76
+ />
77
+ <div className="flex gap-2">
78
+ <Button size="sm" onClick={handleSave} disabled={isSaving}>
79
+ {isSaving ? labels.saving : labels.save}
80
+ </Button>
81
+ <Button size="sm" variant="ghost" onClick={handleCancel} disabled={isSaving}>
82
+ {labels.cancel}
83
+ </Button>
84
+ </div>
85
+ </div>
86
+ ) : (
87
+ <Input
88
+ value={editValue}
89
+ onChange={(e) => setEditValue(e.target.value)}
90
+ onKeyDown={handleKeyDown}
91
+ onBlur={handleSave}
92
+ placeholder={placeholder}
93
+ autoFocus
94
+ disabled={isSaving}
95
+ className="h-9 text-[15px]"
96
+ />
97
+ )}
98
+ </div>
99
+ );
100
+ }
101
+
102
+ return (
103
+ <button
104
+ type="button"
105
+ onClick={() => !disabled && setIsEditing(true)}
106
+ disabled={disabled}
107
+ className={cn(
108
+ 'w-full py-4 border-b border-border/50 last:border-0 text-left',
109
+ 'transition-colors hover:bg-muted/30',
110
+ disabled && 'cursor-default hover:bg-transparent'
111
+ )}
112
+ >
113
+ <div className="text-[13px] text-muted-foreground mb-0.5">{label}</div>
114
+ <div className={cn('text-[15px]', value ? 'text-foreground' : 'text-muted-foreground/60')}>
115
+ {value || placeholder}
116
+ </div>
117
+ </button>
118
+ );
119
+ };
@@ -0,0 +1,22 @@
1
+ 'use client';
2
+
3
+ import React from 'react';
4
+
5
+ import { cn } from '@djangocfg/ui-core/lib';
6
+
7
+ interface SectionProps {
8
+ title?: string;
9
+ children: React.ReactNode;
10
+ className?: string;
11
+ }
12
+
13
+ export const Section = ({ title, children, className }: SectionProps) => (
14
+ <div className={cn('mb-10', className)}>
15
+ {title && (
16
+ <h2 className="text-[11px] font-medium text-muted-foreground uppercase tracking-wider mb-2 px-1">
17
+ {title}
18
+ </h2>
19
+ )}
20
+ <div className="bg-card rounded-xl px-4">{children}</div>
21
+ </div>
22
+ );
@@ -1,5 +1,8 @@
1
+ export { ActionButton } from './ActionButton';
1
2
  export { AvatarSection } from './AvatarSection';
3
+ export { DeleteAccountSection, DeleteAccountScreen } from './DeleteAccountSection';
4
+ export { EditableField } from './EditableField';
2
5
  export { ProfileForm } from './ProfileForm';
6
+ export { Section } from './Section';
3
7
  export { TwoFactorSection } from './TwoFactorSection';
4
- export { DeleteAccountSection } from './DeleteAccountSection';
5
8
 
@@ -0,0 +1,31 @@
1
+ 'use client';
2
+
3
+ import React, { createContext, useCallback, useContext, useState } from 'react';
4
+
5
+ export type ProfileStep = 'main' | 'delete-account';
6
+
7
+ interface ProfileContextValue {
8
+ step: ProfileStep;
9
+ setStep: (step: ProfileStep) => void;
10
+ back: () => void;
11
+ }
12
+
13
+ const ProfileContext = createContext<ProfileContextValue>({
14
+ step: 'main',
15
+ setStep: () => {},
16
+ back: () => {},
17
+ });
18
+
19
+ export const ProfileProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
20
+ const [step, setStep] = useState<ProfileStep>('main');
21
+
22
+ const back = useCallback(() => setStep('main'), []);
23
+
24
+ return (
25
+ <ProfileContext.Provider value={{ step, setStep, back }}>
26
+ {children}
27
+ </ProfileContext.Provider>
28
+ );
29
+ };
30
+
31
+ export const useProfileContext = () => useContext(ProfileContext);
@@ -11,7 +11,7 @@ import Link from 'next/link';
11
11
  import React, { useMemo } from 'react';
12
12
 
13
13
  import { useAuth } from '@djangocfg/api/auth';
14
- import { useTypedT, type I18nTranslations } from '@djangocfg/i18n';
14
+ import { useAppT } from '@djangocfg/i18n';
15
15
  import {
16
16
  Drawer, DrawerClose, DrawerContent, DrawerHeader, DrawerTitle
17
17
  } from '@djangocfg/ui-core/components';
@@ -39,7 +39,7 @@ export function PublicMobileDrawer({
39
39
  userMenu,
40
40
  }: PublicMobileDrawerProps) {
41
41
  const { isAuthenticated: _isAuthenticated } = useAuth();
42
- const t = useTypedT<I18nTranslations>();
42
+ const t = useAppT();
43
43
 
44
44
  const labels = useMemo(() => ({
45
45
  closeMenu: t('layouts.mobile.closeMenu'),
@@ -11,7 +11,7 @@ import Link from 'next/link';
11
11
  import React, { useMemo } from 'react';
12
12
 
13
13
  import { useAuth } from '@djangocfg/api/auth';
14
- import { useTypedT, type I18nTranslations } from '@djangocfg/i18n';
14
+ import { useAppT } from '@djangocfg/i18n';
15
15
  import { Button } from '@djangocfg/ui-core/components';
16
16
  // useIsMobile is used for conditional rendering
17
17
  import { useIsMobile } from '@djangocfg/ui-core/hooks';
@@ -45,7 +45,7 @@ export function PublicNavigation({
45
45
  }: PublicNavigationProps) {
46
46
  const { isAuthenticated: _isAuthenticated } = useAuth();
47
47
  const isMobile = useIsMobile();
48
- const t = useTypedT<I18nTranslations>();
48
+ const t = useAppT();
49
49
 
50
50
  const toggleMobileLabel = useMemo(() => t('layouts.navigation.toggleMobile'), [t]);
51
51
 
@@ -35,7 +35,7 @@ import Link from 'next/link';
35
35
  import React, { useMemo } from 'react';
36
36
 
37
37
  import { useAuth } from '@djangocfg/api/auth';
38
- import { useTypedT, type I18nTranslations } from '@djangocfg/i18n';
38
+ import { useAppT } from '@djangocfg/i18n';
39
39
 
40
40
  import { useLogout } from '../../hooks';
41
41
  import {
@@ -63,7 +63,7 @@ export function UserMenu({
63
63
  const { user, isAuthenticated } = useAuth();
64
64
  const handleLogout = useLogout();
65
65
  const [mounted, setMounted] = React.useState(false);
66
- const t = useTypedT<I18nTranslations>();
66
+ const t = useAppT();
67
67
 
68
68
  const labels = useMemo(() => ({
69
69
  signIn: t('layouts.profile.login'),
@@ -15,7 +15,6 @@ This module provides shared TypeScript types used across all layout components i
15
15
  - **`ErrorTrackingConfig`** - Error tracking settings
16
16
  - **`ErrorBoundaryConfig`** - Error boundary options
17
17
  - **`SWRConfigOptions`** - SWR data fetching configuration
18
- - **`McpChatConfig`** - MCP AI chat widget settings
19
18
 
20
19
  ### Layout Component Types
21
20
 
@@ -34,7 +33,6 @@ This module provides shared TypeScript types used across all layout components i
34
33
  ```typescript
35
34
  import type {
36
35
  BaseLayoutProps,
37
- McpChatConfig,
38
36
  ThemeConfig,
39
37
  FooterConfig,
40
38
  } from '@djangocfg/layouts';
@@ -50,24 +48,6 @@ interface MyCustomLayoutProps extends BaseLayoutProps {
50
48
  }
51
49
  ```
52
50
 
53
- ### MCP Chat Configuration
54
-
55
- ```typescript
56
- import { AppLayout } from '@djangocfg/layouts';
57
-
58
- <AppLayout
59
- mcpChat={{
60
- enabled: true,
61
- autoDetectEnvironment: true,
62
- title: 'My AI Assistant',
63
- position: 'bottom-right',
64
- enableStreaming: true,
65
- }}
66
- >
67
- {children}
68
- </AppLayout>
69
- ```
70
-
71
51
  ## Benefits
72
52
 
73
53
  1. **No Duplication** - Define types once, use everywhere
@@ -10,11 +10,11 @@
10
10
  // ============================================================================
11
11
 
12
12
  // Local provider configs
13
- export type { ThemeConfig, SWRConfigOptions, McpChatConfig, CentrifugoConfig } from './providers.types';
13
+ export type { ThemeConfig, SWRConfigOptions, CentrifugoConfig } from './providers.types';
14
14
 
15
15
  // External provider configs (re-export for convenience)
16
16
  export type { AnalyticsConfig } from '../../snippets/Analytics/types';
17
- export type { PwaInstallConfig } from '../../snippets/PWAInstall/types';
17
+ export type { PwaInstallConfig } from '@djangocfg/ui-nextjs/pwa';
18
18
  export type {
19
19
  ErrorBoundaryConfig,
20
20
  ErrorTrackingConfig,
@@ -10,11 +10,11 @@ import type { AuthConfig } from '@djangocfg/api/auth';
10
10
  // Import provider configs from their modules
11
11
  import type { DebugButtonProps } from '@djangocfg/debuger';
12
12
  import type { AnalyticsConfig } from '../../snippets/Analytics/types';
13
- import type { PwaInstallConfig } from '../../snippets/PWAInstall/types';
13
+ import type { PwaInstallConfig } from '@djangocfg/ui-nextjs/pwa';
14
14
  import type { ErrorBoundaryConfig, ErrorTrackingConfig } from '../../components/errors/types';
15
15
 
16
16
  // Import local provider configs
17
- import type { ThemeConfig, SWRConfigOptions, McpChatConfig, CentrifugoConfig } from './providers.types';
17
+ import type { ThemeConfig, SWRConfigOptions, CentrifugoConfig } from './providers.types';
18
18
  import type { MonitorConfig } from '@djangocfg/monitor';
19
19
 
20
20
  // ============================================================================
@@ -54,9 +54,6 @@ export interface BaseLayoutProps {
54
54
  /** Error boundary configuration (from components/errors, enabled by default) */
55
55
  errorBoundary?: ErrorBoundaryConfig;
56
56
 
57
- /** MCP chat configuration */
58
- mcpChat?: McpChatConfig;
59
-
60
57
  /** PWA Install configuration (from snippets/PWAInstall) */
61
58
  pwaInstall?: PwaInstallConfig;
62
59
 
@@ -24,33 +24,6 @@ export interface SWRConfigOptions {
24
24
  dedupingInterval?: number;
25
25
  }
26
26
 
27
- // ============================================================================
28
- // MCP Chat Configuration
29
- // ============================================================================
30
-
31
- export interface McpChatConfig {
32
- /** Enable MCP chat widget */
33
- enabled?: boolean;
34
- /** API endpoint for chat */
35
- apiEndpoint?: string;
36
- /** Chat widget title */
37
- title?: string;
38
- /** Input placeholder */
39
- placeholder?: string;
40
- /** Greeting message */
41
- greeting?: string;
42
- /** Widget position */
43
- position?: 'bottom-right' | 'bottom-left';
44
- /** Widget variant */
45
- variant?: 'default' | 'minimal';
46
- /** Enable streaming responses */
47
- enableStreaming?: boolean;
48
- /** Auto-detect environment (dev/prod) */
49
- autoDetectEnvironment?: boolean;
50
- /** Custom class name */
51
- className?: string;
52
- }
53
-
54
27
  // ============================================================================
55
28
  // Centrifugo Configuration
56
29
  // ============================================================================
@@ -4,7 +4,7 @@ import { LogIn } from 'lucide-react';
4
4
  import React, { useMemo, useState } from 'react';
5
5
 
6
6
  import { useCfgRouter } from '@djangocfg/api/auth';
7
- import { useTypedT, type I18nTranslations } from '@djangocfg/i18n';
7
+ import { useAppT } from '@djangocfg/i18n';
8
8
  import {
9
9
  Button, Dialog, DialogContent, DialogHeader, DialogTitle
10
10
  } from '@djangocfg/ui-core/components';
@@ -28,7 +28,7 @@ export const AuthDialog: React.FC<AuthDialogProps> = ({
28
28
  authPath = '/auth'
29
29
  }) => {
30
30
  const [open, setOpen] = useState(false);
31
- const t = useTypedT<I18nTranslations>();
31
+ const t = useAppT();
32
32
 
33
33
  const labels = useMemo(() => ({
34
34
  authRequired: t('layouts.auth.authRequired'),
@@ -4,7 +4,7 @@ import Link from 'next/link';
4
4
  import { usePathname } from 'next/navigation';
5
5
  import React, { useMemo } from 'react';
6
6
 
7
- import { useTypedT, type I18nTranslations } from '@djangocfg/i18n';
7
+ import { useAppT } from '@djangocfg/i18n';
8
8
 
9
9
  export interface BreadcrumbItem {
10
10
  path: string;
@@ -19,7 +19,7 @@ interface BreadcrumbsProps {
19
19
 
20
20
  const Breadcrumbs: React.FC<BreadcrumbsProps> = ({ items, className = "" }) => {
21
21
  const pathname = usePathname();
22
- const t = useTypedT<I18nTranslations>();
22
+ const t = useAppT();
23
23
 
24
24
  const labels = useMemo(() => ({
25
25
  home: t('layouts.navigation.home'),