@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,24 +0,0 @@
1
- 'use client';
2
-
3
- export { ChatWidget } from './ChatWidget';
4
- export type { ChatWidgetProps } from './ChatWidget';
5
-
6
- export { AIChatWidget } from './AIChatWidget';
7
- export type { AIChatWidgetProps } from './AIChatWidget';
8
-
9
- export { ChatPanel } from './ChatPanel';
10
-
11
- export { ChatMessages } from './ChatMessages';
12
- export type { ChatMessagesProps, ChatMessagesHandle } from './ChatMessages';
13
-
14
- export { MessageBubble } from './MessageBubble';
15
- export type { MessageBubbleProps } from './MessageBubble';
16
-
17
- export { AIMessageInput } from './MessageInput';
18
- export type { AIMessageInputProps } from './MessageInput';
19
-
20
- export { ChatSidebar } from './ChatSidebar';
21
- export type { ChatSidebarProps } from './ChatSidebar';
22
-
23
- export { AskAIButton } from './AskAIButton';
24
- export type { AskAIButtonProps } from './AskAIButton';
@@ -1,94 +0,0 @@
1
- /**
2
- * McpChat configuration
3
- * Environment-aware configuration for MCP server endpoints
4
- */
5
-
6
- // Hosts
7
- const PROD_HOST = 'https://mcp.djangocfg.com';
8
- const DEV_HOST = 'http://localhost:3002';
9
-
10
- /**
11
- * Get host based on auto-detect flag
12
- * @param autoDetect - If true, auto-detect based on NODE_ENV. If false, always use PROD_HOST
13
- */
14
- function getHost(autoDetect: boolean = false): string {
15
- if (autoDetect && process.env.NODE_ENV === 'development') {
16
- return DEV_HOST;
17
- }
18
- return PROD_HOST;
19
- }
20
-
21
- /**
22
- * Get MCP Server endpoints
23
- * @param autoDetect - If true, auto-detect environment. If false (default), always use production
24
- */
25
- export function getMcpEndpoints(autoDetect: boolean = false) {
26
- const HOST = getHost(autoDetect);
27
- return {
28
- /** Base URL */
29
- baseUrl: HOST,
30
- /** Chat API endpoint */
31
- chat: `${HOST}/api/chat`,
32
- /** Search API endpoint */
33
- search: `${HOST}/api/search`,
34
- /** Conversations API endpoint */
35
- conversations: `${HOST}/api/conversations`,
36
- /** Health check endpoint */
37
- health: `${HOST}/health`,
38
- /** MCP protocol endpoint (Streamable HTTP) */
39
- mcp: `${HOST}/mcp`,
40
- /** SSE endpoint for legacy clients */
41
- sse: `${HOST}/mcp/sse`,
42
- };
43
- }
44
-
45
- /**
46
- * MCP Server endpoints (always production by default)
47
- */
48
- export const mcpEndpoints = getMcpEndpoints(false);
49
-
50
- // Export defaults for backwards compatibility
51
- export const DEFAULT_CHAT_API_ENDPOINT = PROD_HOST + '/api/chat';
52
- export const DEFAULT_MCP_BASE_URL = PROD_HOST;
53
-
54
- /**
55
- * Chat sidebar layout configuration
56
- */
57
- export const sidebarConfig = {
58
- /** Minimum sidebar width in pixels */
59
- minWidth: 320,
60
- /** Maximum sidebar width in pixels */
61
- maxWidth: 600,
62
- /** Default sidebar width in pixels */
63
- defaultWidth: 400,
64
- /** Z-index for chat elements */
65
- zIndex: 300,
66
- /** Animation duration in milliseconds */
67
- animationDuration: 200,
68
- };
69
-
70
- /**
71
- * Chat FAB (Floating Action Button) configuration
72
- */
73
- export const fabConfig = {
74
- /** Bottom offset in pixels */
75
- bottom: 24,
76
- /** Right offset in pixels */
77
- right: 24,
78
- /** Size of FAB button in pixels */
79
- size: 56,
80
- };
81
-
82
- /**
83
- * LocalStorage keys for chat state persistence
84
- */
85
- export const storageKeys = {
86
- /** Display mode (closed, floating, sidebar) */
87
- mode: 'djangocfg-chat-mode',
88
- /** User ID for conversation tracking */
89
- userId: 'djangocfg-chat-user-id',
90
- /** Chat messages history */
91
- messages: 'djangocfg-chat-messages',
92
- /** Sidebar width */
93
- sidebarWidth: 'djangocfg-chat-sidebar-width',
94
- };
@@ -1,327 +0,0 @@
1
- 'use client';
2
-
3
- import {
4
- createContext, ReactNode, useCallback, useContext, useEffect, useMemo, useRef, useState
5
- } from 'react';
6
-
7
- import { useIsMobile, useLocalStorage } from '@djangocfg/ui-core/hooks';
8
-
9
- import { useAIChat } from '../hooks/useAIChat';
10
- import { AIChatMessage, ChatDisplayMode, ChatWidgetConfig, mcpEndpoints} from '../types';
11
-
12
- const STORAGE_KEY_MODE = 'djangocfg-ai-chat-mode';
13
-
14
- /**
15
- * AI Chat context state
16
- */
17
- export interface AIChatContextState {
18
- /** All chat messages */
19
- messages: AIChatMessage[];
20
- /** Whether a request is in progress */
21
- isLoading: boolean;
22
- /** Last error if any */
23
- error: Error | null;
24
- /** Whether chat panel is open */
25
- isOpen: boolean;
26
- /** Whether chat is minimized */
27
- isMinimized: boolean;
28
- /** Configuration */
29
- config: ChatWidgetConfig;
30
- /** Current display mode */
31
- displayMode: ChatDisplayMode;
32
- /** Is on mobile device */
33
- isMobile: boolean;
34
- /** Thread ID for conversation */
35
- threadId: string;
36
- /** User ID for conversation */
37
- userId: string;
38
- }
39
-
40
- /**
41
- * AI Chat context actions
42
- */
43
- export interface AIChatContextActions {
44
- /** Send a message */
45
- sendMessage: (content: string) => Promise<void>;
46
- /** Clear all messages */
47
- clearMessages: () => void;
48
- /** Open chat panel */
49
- openChat: () => void;
50
- /** Close chat panel */
51
- closeChat: () => void;
52
- /** Toggle chat panel */
53
- toggleChat: () => void;
54
- /** Minimize/restore chat */
55
- toggleMinimize: () => void;
56
- /** Set display mode */
57
- setDisplayMode: (mode: ChatDisplayMode) => void;
58
- /** Stop streaming response */
59
- stopStreaming: () => void;
60
- }
61
-
62
- export type AIChatContextValue = AIChatContextState & AIChatContextActions;
63
-
64
- const AIChatContext = createContext<AIChatContextValue | null>(null);
65
-
66
- /**
67
- * AI Chat provider props
68
- */
69
- export interface AIChatProviderProps {
70
- children: ReactNode;
71
- /** API endpoint for AI chat (default: /api/ai/chat) */
72
- apiEndpoint?: string;
73
- /** Widget configuration */
74
- config?: Partial<ChatWidgetConfig>;
75
- /** Callback on error */
76
- onError?: (error: Error) => void;
77
- /** Enable streaming (default: true) */
78
- enableStreaming?: boolean;
79
- }
80
-
81
- /**
82
- * AI Chat provider component
83
- * Uses useAIChat hook with server-side persistence
84
- */
85
- export function AIChatProvider({
86
- children,
87
- apiEndpoint = mcpEndpoints.chat,
88
- config: userConfig = {},
89
- onError,
90
- enableStreaming = true,
91
- }: AIChatProviderProps) {
92
- // Use AI chat hook
93
- const {
94
- messages,
95
- isLoading,
96
- error,
97
- threadId,
98
- userId,
99
- sendMessage: sendAIMessage,
100
- clearMessages: clearAIMessages,
101
- stopStreaming,
102
- } = useAIChat({
103
- apiEndpoint,
104
- onError,
105
- enableStreaming,
106
- });
107
-
108
- const [isMinimized, setIsMinimized] = useState(false);
109
-
110
- // Display mode with localStorage persistence
111
- const [storedMode, setStoredMode] = useLocalStorage<ChatDisplayMode>(STORAGE_KEY_MODE, 'closed');
112
-
113
- const isMobile = useIsMobile();
114
-
115
- // On mobile, sidebar mode is not available - fallback to floating
116
- const displayMode: ChatDisplayMode = useMemo(() => {
117
- if (isMobile && storedMode === 'sidebar') {
118
- return 'floating';
119
- }
120
- return storedMode;
121
- }, [isMobile, storedMode]);
122
-
123
- // Derived state: isOpen is true when not in 'closed' mode
124
- const isOpen = displayMode !== 'closed';
125
-
126
- // Track isOpen in a ref for event handler
127
- const isOpenRef = useRef(isOpen);
128
- useEffect(() => {
129
- isOpenRef.current = isOpen;
130
- }, [isOpen]);
131
-
132
- // Track last active mode (non-closed) to restore when reopening
133
- const lastActiveModeRef = useRef<Exclude<ChatDisplayMode, 'closed'>>('floating');
134
- useEffect(() => {
135
- if (displayMode !== 'closed') {
136
- lastActiveModeRef.current = displayMode;
137
- }
138
- }, [displayMode]);
139
-
140
- const config: ChatWidgetConfig = useMemo(
141
- () => ({
142
- apiEndpoint,
143
- title: 'DjangoCFG AI',
144
- placeholder: 'Ask about DjangoCFG...',
145
- greeting:
146
- "Hi! I'm your DjangoCFG AI assistant powered by GPT. Ask me anything about configuration, features, or how to use the library.",
147
- position: 'bottom-right',
148
- variant: 'default',
149
- ...userConfig,
150
- }),
151
- [apiEndpoint, userConfig]
152
- );
153
-
154
- const sendMessage = useCallback(
155
- async (content: string) => {
156
- await sendAIMessage(content);
157
- },
158
- [sendAIMessage]
159
- );
160
-
161
- const clearMessages = useCallback(() => {
162
- clearAIMessages();
163
- }, [clearAIMessages]);
164
-
165
- const openChat = useCallback(() => {
166
- // Restore last active mode instead of always opening in floating
167
- setStoredMode(lastActiveModeRef.current);
168
- setIsMinimized(false);
169
- }, [setStoredMode]);
170
-
171
- const closeChat = useCallback(() => {
172
- setStoredMode('closed');
173
- setIsMinimized(false);
174
- }, [setStoredMode]);
175
-
176
- const toggleChat = useCallback(() => {
177
- if (displayMode === 'closed') {
178
- setStoredMode('floating');
179
- setIsMinimized(false);
180
- } else {
181
- setStoredMode('closed');
182
- }
183
- }, [displayMode, setStoredMode]);
184
-
185
- const toggleMinimize = useCallback(() => {
186
- setIsMinimized((prev) => !prev);
187
- }, []);
188
-
189
- const setDisplayMode = useCallback(
190
- (mode: ChatDisplayMode) => {
191
- // On mobile, sidebar is not available
192
- if (isMobile && mode === 'sidebar') {
193
- setStoredMode('floating');
194
- } else {
195
- setStoredMode(mode);
196
- }
197
- setIsMinimized(false);
198
- },
199
- [isMobile, setStoredMode]
200
- );
201
-
202
- const value = useMemo<AIChatContextValue>(
203
- () => ({
204
- messages,
205
- isLoading,
206
- error,
207
- isOpen,
208
- isMinimized,
209
- config,
210
- displayMode,
211
- isMobile,
212
- threadId,
213
- userId,
214
- sendMessage,
215
- clearMessages,
216
- openChat,
217
- closeChat,
218
- toggleChat,
219
- toggleMinimize,
220
- setDisplayMode,
221
- stopStreaming,
222
- }),
223
- [
224
- messages,
225
- isLoading,
226
- error,
227
- isOpen,
228
- isMinimized,
229
- config,
230
- displayMode,
231
- isMobile,
232
- threadId,
233
- userId,
234
- sendMessage,
235
- clearMessages,
236
- openChat,
237
- closeChat,
238
- toggleChat,
239
- toggleMinimize,
240
- setDisplayMode,
241
- stopStreaming,
242
- ]
243
- );
244
-
245
- // =============================================================================
246
- // Global Chat Event Listener
247
- // =============================================================================
248
-
249
- /**
250
- * Listen for mcp:chat:send events from useMcpChat hook
251
- * This allows any component to trigger chat from anywhere in the app
252
- */
253
- useEffect(() => {
254
- // Register chat as available
255
- if (typeof window !== 'undefined') {
256
- (window as any).__MCP_CHAT_AVAILABLE__ = true;
257
- }
258
-
259
- const handleChatEvent = (event: Event) => {
260
- const customEvent = event as CustomEvent<import('../types').McpChatEventDetail>;
261
- const { message, context, autoSend = true, displayMode: requestedMode } = customEvent.detail;
262
-
263
- // Send confirmation that event was handled
264
- window.dispatchEvent(new CustomEvent('mcp:chat:handled'));
265
-
266
- // Format message with context if provided
267
- let fullMessage = message;
268
- if (context) {
269
- if (context.type) {
270
- fullMessage = `[${context.type.toUpperCase()}] ${message}`;
271
- }
272
- if (context.data) {
273
- fullMessage += `\n\n**Context:**\n\`\`\`json\n${JSON.stringify(context.data, null, 2)}\n\`\`\``;
274
- }
275
- if (context.source) {
276
- fullMessage += `\n\n_Source: ${context.source}_`;
277
- }
278
- }
279
-
280
- // Open chat in requested mode, or keep current mode if already open
281
- if (requestedMode) {
282
- setDisplayMode(requestedMode);
283
- } else if (!isOpenRef.current) {
284
- // Only open if chat is currently closed
285
- openChat();
286
- }
287
- // If already open, keep current mode
288
-
289
- // Auto-send message if requested
290
- if (autoSend) {
291
- // Small delay to ensure chat is open and ready
292
- setTimeout(() => {
293
- sendMessage(fullMessage);
294
- }, 100);
295
- }
296
- };
297
-
298
- window.addEventListener('mcp:chat:send', handleChatEvent);
299
-
300
- return () => {
301
- window.removeEventListener('mcp:chat:send', handleChatEvent);
302
- if (typeof window !== 'undefined') {
303
- (window as any).__MCP_CHAT_AVAILABLE__ = false;
304
- }
305
- };
306
- }, [sendMessage, setDisplayMode, openChat]);
307
-
308
- return <AIChatContext.Provider value={value}>{children}</AIChatContext.Provider>;
309
- }
310
-
311
- /**
312
- * Hook to access AI chat context
313
- */
314
- export function useAIChatContext(): AIChatContextValue {
315
- const context = useContext(AIChatContext);
316
- if (!context) {
317
- throw new Error('useAIChatContext must be used within an AIChatProvider');
318
- }
319
- return context;
320
- }
321
-
322
- /**
323
- * Hook to check if AI chat context is available
324
- */
325
- export function useAIChatContextOptional(): AIChatContextValue | null {
326
- return useContext(AIChatContext);
327
- }