@djangocfg/layouts 2.1.479 → 2.1.481
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.481",
|
|
4
4
|
"description": "Simple, straightforward layout components for Next.js - import and use with props",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"layouts",
|
|
@@ -89,12 +89,12 @@
|
|
|
89
89
|
"check": "tsc --noEmit"
|
|
90
90
|
},
|
|
91
91
|
"peerDependencies": {
|
|
92
|
-
"@djangocfg/analytics": "^2.1.
|
|
93
|
-
"@djangocfg/api": "^2.1.
|
|
94
|
-
"@djangocfg/centrifugo": "^2.1.
|
|
95
|
-
"@djangocfg/devtools": "^2.1.
|
|
96
|
-
"@djangocfg/i18n": "^2.1.
|
|
97
|
-
"@djangocfg/ui-core": "^2.1.
|
|
92
|
+
"@djangocfg/analytics": "^2.1.481",
|
|
93
|
+
"@djangocfg/api": "^2.1.481",
|
|
94
|
+
"@djangocfg/centrifugo": "^2.1.481",
|
|
95
|
+
"@djangocfg/devtools": "^2.1.481",
|
|
96
|
+
"@djangocfg/i18n": "^2.1.481",
|
|
97
|
+
"@djangocfg/ui-core": "^2.1.481",
|
|
98
98
|
"@hookform/resolvers": "^5.2.2",
|
|
99
99
|
"consola": "^3.4.2",
|
|
100
100
|
"lucide-react": "^0.545.0",
|
|
@@ -124,14 +124,14 @@
|
|
|
124
124
|
"uuid": "^11.1.1"
|
|
125
125
|
},
|
|
126
126
|
"devDependencies": {
|
|
127
|
-
"@djangocfg/analytics": "^2.1.
|
|
128
|
-
"@djangocfg/api": "^2.1.
|
|
129
|
-
"@djangocfg/centrifugo": "^2.1.
|
|
130
|
-
"@djangocfg/devtools": "^2.1.
|
|
131
|
-
"@djangocfg/i18n": "^2.1.
|
|
132
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
133
|
-
"@djangocfg/ui-core": "^2.1.
|
|
134
|
-
"@djangocfg/ui-tools": "^2.1.
|
|
127
|
+
"@djangocfg/analytics": "^2.1.481",
|
|
128
|
+
"@djangocfg/api": "^2.1.481",
|
|
129
|
+
"@djangocfg/centrifugo": "^2.1.481",
|
|
130
|
+
"@djangocfg/devtools": "^2.1.481",
|
|
131
|
+
"@djangocfg/i18n": "^2.1.481",
|
|
132
|
+
"@djangocfg/typescript-config": "^2.1.481",
|
|
133
|
+
"@djangocfg/ui-core": "^2.1.481",
|
|
134
|
+
"@djangocfg/ui-tools": "^2.1.481",
|
|
135
135
|
"@types/node": "^25.9.5",
|
|
136
136
|
"@types/react": "19.2.15",
|
|
137
137
|
"@types/react-dom": "19.2.3",
|
|
@@ -99,63 +99,8 @@ function PrivateSidebarAccountRaw({ header }: PrivateSidebarAccountProps) {
|
|
|
99
99
|
setSidebarOpen(true);
|
|
100
100
|
}, [setSidebarOpen]);
|
|
101
101
|
|
|
102
|
-
// Hide entirely in production when there's no user (auth still loading or
|
|
103
|
-
// /me failed and the parent guard hasn't redirected yet). In dev keep a
|
|
104
|
-
// placeholder so the footer + Log out are reachable for debugging.
|
|
105
|
-
// NOTE: this early-return must stay AFTER all hooks above to keep hook order stable.
|
|
106
|
-
if (!user && !isDev) return null;
|
|
107
|
-
|
|
108
|
-
const userInitial = (account.displayName.charAt(0) || '?').toUpperCase();
|
|
109
|
-
const secondary = header?.footerSecondaryAction;
|
|
110
|
-
|
|
111
|
-
const triggerClassName = cn(
|
|
112
|
-
'group h-auto w-full gap-3 rounded-lg px-3 py-3 text-left select-none',
|
|
113
|
-
'hover:bg-sidebar-accent/70 hover:text-sidebar-accent-foreground',
|
|
114
|
-
// No focus ring on the menu trigger — the open menu is the affordance.
|
|
115
|
-
'focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0',
|
|
116
|
-
content.isAccountCompact ? 'justify-center px-0 py-2' : 'min-h-[52px]',
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
const secondaryButton = secondary && !content.isAccountCompact ? (
|
|
120
|
-
<SecondaryAction action={secondary} onParentExpand={onSecondaryExpand} />
|
|
121
|
-
) : null;
|
|
122
|
-
|
|
123
|
-
const dropdownContentClass = cn(
|
|
124
|
-
'p-1.5',
|
|
125
|
-
content.isAccountCompact ? 'min-w-60' : 'w-[var(--radix-dropdown-menu-trigger-width)] min-w-60',
|
|
126
|
-
);
|
|
127
|
-
// Always open UPWARD over the avatar (Claude pattern). The footer sits at the
|
|
128
|
-
// bottom of the rail in both expanded and collapsed states, so `top` reads
|
|
129
|
-
// correctly either way (vs. `right`, which floated off to the side).
|
|
130
|
-
const dropdownSide: 'top' = 'top';
|
|
131
|
-
const avatarClass = cn(
|
|
132
|
-
'h-9 w-9 shrink-0 border border-transparent transition-colors',
|
|
133
|
-
'group-hover:border-sidebar-border/70',
|
|
134
|
-
);
|
|
135
|
-
|
|
136
102
|
const headerLabelText = account.email ?? (account.source === 'dev-fallback' ? 'No active session' : null);
|
|
137
103
|
|
|
138
|
-
const expandedMeta = content.isAccountCompact ? null : (
|
|
139
|
-
<>
|
|
140
|
-
<span className="flex min-w-0 flex-1 flex-col text-left">
|
|
141
|
-
<span className="truncate text-sm font-medium leading-tight text-sidebar-foreground">
|
|
142
|
-
{account.displayName}
|
|
143
|
-
</span>
|
|
144
|
-
{account.plan ? (
|
|
145
|
-
<span className="truncate text-xs leading-snug text-sidebar-foreground/60">
|
|
146
|
-
{account.plan}
|
|
147
|
-
</span>
|
|
148
|
-
) : null}
|
|
149
|
-
</span>
|
|
150
|
-
<span className="flex shrink-0 items-center gap-1.5">
|
|
151
|
-
{secondaryButton}
|
|
152
|
-
{header?.accountAction !== 'dialog' ? (
|
|
153
|
-
<ChevronsUpDown className="h-3.5 w-3.5 text-sidebar-foreground/55" aria-hidden />
|
|
154
|
-
) : null}
|
|
155
|
-
</span>
|
|
156
|
-
</>
|
|
157
|
-
);
|
|
158
|
-
|
|
159
104
|
// `accountAction: 'dialog'` opens the global SettingsDialog (mounted in
|
|
160
105
|
// PrivateLayout). Requires `settings` to be passed to PrivateLayout.
|
|
161
106
|
const openSettingsDialog = React.useCallback(() => {
|
|
@@ -239,6 +184,68 @@ function PrivateSidebarAccountRaw({ header }: PrivateSidebarAccountProps) {
|
|
|
239
184
|
return items;
|
|
240
185
|
}, [headerLabelText, t, layoutI18n, accountLinks, signOutLabel, handleLogout]);
|
|
241
186
|
|
|
187
|
+
// Hide entirely in production when there's no user (auth still loading or
|
|
188
|
+
// /me failed and the parent guard hasn't redirected yet). In dev keep a
|
|
189
|
+
// placeholder so the footer + Log out are reachable for debugging.
|
|
190
|
+
//
|
|
191
|
+
// EVERY hook must run above this line. When a terminal 401 clears the session,
|
|
192
|
+
// `user` flips to null and this branch starts returning early — if any hook
|
|
193
|
+
// lived below it, the hook count would drop between renders and React would
|
|
194
|
+
// throw #310 ("rendered more hooks than during the previous render"). That is
|
|
195
|
+
// exactly what happened on my.cmdop.com/private/: two hooks sat below and the
|
|
196
|
+
// dashboard white-screened on the 401 transition. It only reproduced in
|
|
197
|
+
// production because `isDev` makes this guard statically dead in development.
|
|
198
|
+
if (!user && !isDev) return null;
|
|
199
|
+
|
|
200
|
+
const userInitial = (account.displayName.charAt(0) || '?').toUpperCase();
|
|
201
|
+
const secondary = header?.footerSecondaryAction;
|
|
202
|
+
|
|
203
|
+
const triggerClassName = cn(
|
|
204
|
+
'group h-auto w-full gap-3 rounded-lg px-3 py-3 text-left select-none',
|
|
205
|
+
'hover:bg-sidebar-accent/70 hover:text-sidebar-accent-foreground',
|
|
206
|
+
// No focus ring on the menu trigger — the open menu is the affordance.
|
|
207
|
+
'focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0',
|
|
208
|
+
content.isAccountCompact ? 'justify-center px-0 py-2' : 'min-h-[52px]',
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
const secondaryButton = secondary && !content.isAccountCompact ? (
|
|
212
|
+
<SecondaryAction action={secondary} onParentExpand={onSecondaryExpand} />
|
|
213
|
+
) : null;
|
|
214
|
+
|
|
215
|
+
const dropdownContentClass = cn(
|
|
216
|
+
'p-1.5',
|
|
217
|
+
content.isAccountCompact ? 'min-w-60' : 'w-[var(--radix-dropdown-menu-trigger-width)] min-w-60',
|
|
218
|
+
);
|
|
219
|
+
// Always open UPWARD over the avatar (Claude pattern). The footer sits at the
|
|
220
|
+
// bottom of the rail in both expanded and collapsed states, so `top` reads
|
|
221
|
+
// correctly either way (vs. `right`, which floated off to the side).
|
|
222
|
+
const dropdownSide: 'top' = 'top';
|
|
223
|
+
const avatarClass = cn(
|
|
224
|
+
'h-9 w-9 shrink-0 border border-transparent transition-colors',
|
|
225
|
+
'group-hover:border-sidebar-border/70',
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
const expandedMeta = content.isAccountCompact ? null : (
|
|
229
|
+
<>
|
|
230
|
+
<span className="flex min-w-0 flex-1 flex-col text-left">
|
|
231
|
+
<span className="truncate text-sm font-medium leading-tight text-sidebar-foreground">
|
|
232
|
+
{account.displayName}
|
|
233
|
+
</span>
|
|
234
|
+
{account.plan ? (
|
|
235
|
+
<span className="truncate text-xs leading-snug text-sidebar-foreground/60">
|
|
236
|
+
{account.plan}
|
|
237
|
+
</span>
|
|
238
|
+
) : null}
|
|
239
|
+
</span>
|
|
240
|
+
<span className="flex shrink-0 items-center gap-1.5">
|
|
241
|
+
{secondaryButton}
|
|
242
|
+
{header?.accountAction !== 'dialog' ? (
|
|
243
|
+
<ChevronsUpDown className="h-3.5 w-3.5 text-sidebar-foreground/55" aria-hidden />
|
|
244
|
+
) : null}
|
|
245
|
+
</span>
|
|
246
|
+
</>
|
|
247
|
+
);
|
|
248
|
+
|
|
242
249
|
const triggerButton = (
|
|
243
250
|
<Button
|
|
244
251
|
type="button"
|