@djangocfg/layouts 1.2.22 → 1.2.24

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": "1.2.22",
3
+ "version": "1.2.24",
4
4
  "description": "Layout system and components for Unrealon applications",
5
5
  "author": {
6
6
  "name": "DjangoCFG",
@@ -53,9 +53,9 @@
53
53
  "check": "tsc --noEmit"
54
54
  },
55
55
  "peerDependencies": {
56
- "@djangocfg/api": "^1.2.22",
57
- "@djangocfg/og-image": "^1.2.22",
58
- "@djangocfg/ui": "^1.2.22",
56
+ "@djangocfg/api": "^1.2.24",
57
+ "@djangocfg/og-image": "^1.2.24",
58
+ "@djangocfg/ui": "^1.2.24",
59
59
  "@hookform/resolvers": "^5.2.0",
60
60
  "consola": "^3.4.2",
61
61
  "lucide-react": "^0.468.0",
@@ -76,7 +76,7 @@
76
76
  "vidstack": "0.6.15"
77
77
  },
78
78
  "devDependencies": {
79
- "@djangocfg/typescript-config": "^1.2.22",
79
+ "@djangocfg/typescript-config": "^1.2.24",
80
80
  "@types/node": "^24.7.2",
81
81
  "@types/react": "19.2.2",
82
82
  "@types/react-dom": "19.2.1",
@@ -16,36 +16,36 @@ export interface PackageInfo {
16
16
  /**
17
17
  * Package versions registry
18
18
  * Auto-synced from package.json files
19
- * Last updated: 2025-11-03T06:46:24.174Z
19
+ * Last updated: 2025-11-04T07:41:20.959Z
20
20
  */
21
21
  const PACKAGE_VERSIONS: PackageInfo[] = [
22
22
  {
23
23
  "name": "@djangocfg/ui",
24
- "version": "1.2.22"
24
+ "version": "1.2.24"
25
25
  },
26
26
  {
27
27
  "name": "@djangocfg/api",
28
- "version": "1.2.22"
28
+ "version": "1.2.24"
29
29
  },
30
30
  {
31
31
  "name": "@djangocfg/layouts",
32
- "version": "1.2.22"
32
+ "version": "1.2.24"
33
33
  },
34
34
  {
35
35
  "name": "@djangocfg/markdown",
36
- "version": "1.2.22"
36
+ "version": "1.2.24"
37
37
  },
38
38
  {
39
39
  "name": "@djangocfg/og-image",
40
- "version": "1.2.22"
40
+ "version": "1.2.24"
41
41
  },
42
42
  {
43
43
  "name": "@djangocfg/eslint-config",
44
- "version": "1.2.22"
44
+ "version": "1.2.24"
45
45
  },
46
46
  {
47
47
  "name": "@djangocfg/typescript-config",
48
- "version": "1.2.22"
48
+ "version": "1.2.24"
49
49
  }
50
50
  ];
51
51
 
@@ -83,8 +83,8 @@ export function AdminLayout({
83
83
  enableParentSync = true
84
84
  }: AdminLayoutProps) {
85
85
  const [isMounted, setIsMounted] = React.useState(false);
86
- const { user, isLoading, loadCurrentProfile } = useAuth();
87
- // console.log('[AdminLayout] Rendering with user:', user, 'isLoading:', isLoading);
86
+ const { user, isLoading, isAuthenticated, loadCurrentProfile } = useAuth();
87
+ // console.log('[AdminLayout] Rendering with user:', user, 'isLoading:', isLoading, 'isAuthenticated:', isAuthenticated);
88
88
 
89
89
  // Track mount state to prevent hydration mismatch
90
90
  React.useEffect(() => {
@@ -117,33 +117,44 @@ export function AdminLayout({
117
117
 
118
118
  // console.log('[AdminLayout] isEmbedded:', isEmbedded);
119
119
 
120
+ // Minimalist loading component
121
+ const LoadingState = () => (
122
+ <div className="min-h-screen flex items-center justify-center bg-background">
123
+ <div className="flex items-center gap-2 text-muted-foreground">
124
+ <div className="w-2 h-2 bg-current rounded-full animate-pulse" style={{ animationDelay: '0ms' }} />
125
+ <div className="w-2 h-2 bg-current rounded-full animate-pulse" style={{ animationDelay: '150ms' }} />
126
+ <div className="w-2 h-2 bg-current rounded-full animate-pulse" style={{ animationDelay: '300ms' }} />
127
+ <span className="ml-2">Loading...</span>
128
+ </div>
129
+ </div>
130
+ );
131
+
120
132
  // During SSR and initial render, show loading to prevent hydration mismatch
121
133
  if (!isMounted) {
122
- return (
123
- <div className="min-h-screen flex items-center justify-center bg-background">
124
- <div className="text-muted-foreground">Loading admin panel...</div>
125
- </div>
126
- );
134
+ return <LoadingState />;
127
135
  }
128
136
 
129
137
  // Show loading while auth is initializing (waiting for tokens from parent or profile loading)
130
- if (isLoading) {
131
- // console.log('[AdminLayout] Showing loading state - isLoading:', isLoading);
132
- return (
133
- <div className="min-h-screen flex items-center justify-center bg-background">
134
- <div className="text-muted-foreground">Loading admin panel...</div>
135
- </div>
136
- );
138
+ // OR if user object is not loaded yet (null/undefined)
139
+ // OR if authentication status is not yet determined
140
+ if (isLoading || !user || !isAuthenticated) {
141
+ // console.log('[AdminLayout] Showing loading state - isLoading:', isLoading, 'user:', user, 'isAuthenticated:', isAuthenticated);
142
+ return <LoadingState />;
137
143
  }
138
144
 
139
145
  // Check if user has staff or superuser privileges
140
- const hasAdminAccess = user?.is_staff || user?.is_superuser;
141
- // console.log('[AdminLayout] user:', user, 'hasAdminAccess:', hasAdminAccess, 'is_staff:', user?.is_staff, 'is_superuser:', user?.is_superuser);
142
-
143
- // Only render AdminLayout features for staff/superuser
146
+ // At this point, we KNOW that:
147
+ // 1. User is loaded (not null)
148
+ // 2. User is authenticated
149
+ // 3. Auth process is complete
150
+ const hasAdminAccess = user.is_staff || user.is_superuser;
151
+ // console.log('[AdminLayout] user:', user, 'hasAdminAccess:', hasAdminAccess, 'is_staff:', user.is_staff, 'is_superuser:', user.is_superuser);
152
+
153
+ // Only show "Access Denied" when we are CERTAIN user doesn't have permissions
154
+ // This prevents showing the message during auth/loading states
144
155
  if (!hasAdminAccess) {
145
- console.warn('[AdminLayout] Access denied - user does not have admin access');
146
- // console.log('[AdminLayout] User details:', JSON.stringify(user, null, 2));
156
+ // Only show this when user is fully authenticated but lacks permissions
157
+ // console.log('[AdminLayout] Authenticated user lacks admin permissions');
147
158
  return (
148
159
  <div className="min-h-screen flex items-center justify-center bg-background">
149
160
  <div className="text-center space-y-4 p-8">
@@ -5,6 +5,7 @@
5
5
  import React from 'react';
6
6
  import {
7
7
  Button,
8
+ DownloadButton,
8
9
  Input,
9
10
  Checkbox,
10
11
  Label,
@@ -73,6 +74,106 @@ export const FORM_COMPONENTS: ComponentConfig[] = [
73
74
  </div>
74
75
  ),
75
76
  },
77
+ {
78
+ name: 'DownloadButton',
79
+ category: 'forms',
80
+ description: 'Button with download functionality, status indicators, and authentication support',
81
+ importPath: `import { DownloadButton } from '@djangocfg/ui';`,
82
+ example: `// Simple download
83
+ <DownloadButton
84
+ url="/api/files/report.pdf"
85
+ filename="monthly-report.pdf"
86
+ >
87
+ Download Report
88
+ </DownloadButton>
89
+
90
+ // With callbacks
91
+ <DownloadButton
92
+ url="/api/export/users"
93
+ method="POST"
94
+ body={{ format: "csv" }}
95
+ onDownloadStart={() => console.log("Starting...")}
96
+ onDownloadComplete={(filename) => console.log("Done:", filename)}
97
+ onDownloadError={(error) => console.error("Error:", error)}
98
+ >
99
+ Export Users
100
+ </DownloadButton>
101
+
102
+ // Different variants
103
+ <DownloadButton url="/api/data" variant="outline" size="sm">
104
+ Download Data
105
+ </DownloadButton>`,
106
+ preview: (
107
+ <div className="space-y-4">
108
+ {/* Basic example */}
109
+ <div className="space-y-2">
110
+ <p className="text-sm font-medium">Basic Download:</p>
111
+ <DownloadButton
112
+ url="https://jsonplaceholder.typicode.com/posts/1"
113
+ filename="example-data.json"
114
+ >
115
+ Download Example
116
+ </DownloadButton>
117
+ </div>
118
+
119
+ {/* Variants */}
120
+ <div className="space-y-2">
121
+ <p className="text-sm font-medium">Variants:</p>
122
+ <div className="flex flex-wrap gap-2">
123
+ <DownloadButton
124
+ url="https://jsonplaceholder.typicode.com/posts/1"
125
+ filename="data.json"
126
+ variant="default"
127
+ >
128
+ Default
129
+ </DownloadButton>
130
+ <DownloadButton
131
+ url="https://jsonplaceholder.typicode.com/posts/1"
132
+ filename="data.json"
133
+ variant="outline"
134
+ >
135
+ Outline
136
+ </DownloadButton>
137
+ <DownloadButton
138
+ url="https://jsonplaceholder.typicode.com/posts/1"
139
+ filename="data.json"
140
+ variant="secondary"
141
+ >
142
+ Secondary
143
+ </DownloadButton>
144
+ </div>
145
+ </div>
146
+
147
+ {/* Sizes */}
148
+ <div className="space-y-2">
149
+ <p className="text-sm font-medium">Sizes:</p>
150
+ <div className="flex flex-wrap items-center gap-2">
151
+ <DownloadButton
152
+ url="https://jsonplaceholder.typicode.com/posts/1"
153
+ filename="data.json"
154
+ size="sm"
155
+ >
156
+ Small
157
+ </DownloadButton>
158
+ <DownloadButton
159
+ url="https://jsonplaceholder.typicode.com/posts/1"
160
+ filename="data.json"
161
+ size="default"
162
+ >
163
+ Default
164
+ </DownloadButton>
165
+ <DownloadButton
166
+ url="https://jsonplaceholder.typicode.com/posts/1"
167
+ filename="data.json"
168
+ size="lg"
169
+ >
170
+ Large
171
+ </DownloadButton>
172
+ </div>
173
+ </div>
174
+ </div>
175
+ ),
176
+ },
76
177
  {
77
178
  name: 'Input',
78
179
  category: 'forms',
@@ -318,25 +318,28 @@ export const NAVIGATION_COMPONENTS: ComponentConfig[] = [
318
318
  category: 'navigation',
319
319
  description: 'Client-side pagination component for static builds with callback support',
320
320
  importPath: `import { StaticPagination } from '@djangocfg/ui';`,
321
- example: `const [currentPage, setCurrentPage] = useState(1);
321
+ example: `import { useDRFPagination } from '@djangocfg/ui';
322
+
323
+ const pagination = useDRFPagination(1, 10);
324
+ const { data } = useMyAPI(pagination.params);
322
325
 
323
326
  <StaticPagination
324
- currentPage={currentPage}
325
- totalPages={10}
326
- totalItems={100}
327
- itemsPerPage={10}
328
- hasNextPage={currentPage < 10}
329
- hasPreviousPage={currentPage > 1}
330
- onPageChange={(page) => setCurrentPage(page)}
327
+ data={data}
328
+ onPageChange={pagination.setPage}
331
329
  />`,
332
330
  preview: (
333
331
  <StaticPagination
334
- currentPage={2}
335
- totalPages={10}
336
- totalItems={100}
337
- itemsPerPage={10}
338
- hasNextPage={true}
339
- hasPreviousPage={true}
332
+ data={{
333
+ count: 100,
334
+ page: 2,
335
+ pages: 10,
336
+ page_size: 10,
337
+ has_next: true,
338
+ has_previous: true,
339
+ next_page: 3,
340
+ previous_page: 1,
341
+ results: [],
342
+ }}
340
343
  onPageChange={(page) => console.log('Page changed to:', page)}
341
344
  />
342
345
  ),