create-nextjs-cms 0.5.55 → 0.5.56
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 +2 -2
- package/templates/default/app/(auth)/auth/login/LoginPage.tsx +14 -11
- package/templates/default/app/layout.tsx +5 -3
- package/templates/default/app/providers.tsx +7 -6
- package/templates/default/components/Layout.tsx +2 -2
- package/templates/default/components/NavbarAlt.tsx +5 -5
- package/templates/default/components/Sidebar.tsx +7 -7
- package/templates/default/package.json +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-nextjs-cms",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.56",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"prettier": "^3.3.3",
|
|
27
27
|
"tsx": "^4.20.6",
|
|
28
28
|
"typescript": "^5.9.2",
|
|
29
|
-
"@lzcms/tsconfig": "0.1.0",
|
|
30
29
|
"@lzcms/eslint-config": "0.3.0",
|
|
30
|
+
"@lzcms/tsconfig": "0.1.0",
|
|
31
31
|
"@lzcms/prettier-config": "0.1.0"
|
|
32
32
|
},
|
|
33
33
|
"prettier": "@lzcms/prettier-config",
|
|
@@ -59,7 +59,10 @@ export default function LoginPage() {
|
|
|
59
59
|
useEffect(() => {
|
|
60
60
|
if (session?.status === 'authenticated') {
|
|
61
61
|
const from = searchParams.get('callbackUrl')
|
|
62
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Prevent redirect to the same page to prevent infinite loop
|
|
64
|
+
*/
|
|
65
|
+
if (from && !from.includes('auth/login')) {
|
|
63
66
|
router.push(from)
|
|
64
67
|
} else {
|
|
65
68
|
router.push('/')
|
|
@@ -69,7 +72,7 @@ export default function LoginPage() {
|
|
|
69
72
|
|
|
70
73
|
return (
|
|
71
74
|
<>
|
|
72
|
-
<div className='fixed
|
|
75
|
+
<div className='bg-background text-foreground fixed top-0 left-0 h-full w-full flex-1 flex-col justify-center overflow-auto px-6 py-12 lg:px-8'>
|
|
73
76
|
<div className='flex w-full'>
|
|
74
77
|
<Button
|
|
75
78
|
variant='default'
|
|
@@ -85,18 +88,18 @@ export default function LoginPage() {
|
|
|
85
88
|
</Button>
|
|
86
89
|
</div>
|
|
87
90
|
<div className='text-center sm:mx-auto sm:w-full sm:max-w-sm'>
|
|
88
|
-
<span className='bg-gray-800 px-2 font-bold tracking-tighter text-amber-200 ring-1 ring-sky-500 transition-all duration-150 hover:bg-transparent hover:font-normal hover:tracking-[1em] hover:
|
|
89
|
-
|
|
91
|
+
<span className='hover:text-foreground bg-gray-800 px-2 font-bold tracking-tighter text-amber-200 ring-1 ring-sky-500 transition-all duration-150 hover:bg-transparent hover:font-normal hover:tracking-[1em] hover:ring-0'>
|
|
92
|
+
nextjs-cms
|
|
90
93
|
</span>
|
|
91
|
-
<h2 className='mt-10 text-center text-2xl font-bold
|
|
94
|
+
<h2 className='mt-10 text-center text-2xl leading-9 font-bold tracking-tight'>
|
|
92
95
|
{getString('login_to_your_account')}
|
|
93
96
|
</h2>
|
|
94
97
|
</div>
|
|
95
98
|
|
|
96
|
-
<div className='mx-auto mt-10 w-full max-w-md rounded-lg bg-linear-to-bl from-sky-50 to-green-50 p-12 shadow-lg ring-2 ring-
|
|
99
|
+
<div className='mx-auto mt-10 w-full max-w-md rounded-lg bg-linear-to-bl from-sky-50 to-green-50 p-12 shadow-lg ring-2 ring-sky-400 ring-inset dark:from-neutral-950 dark:to-neutral-800'>
|
|
97
100
|
<form ref={formRef} className='space-y-6'>
|
|
98
101
|
<div>
|
|
99
|
-
<label htmlFor='username' className='block text-sm font-medium
|
|
102
|
+
<label htmlFor='username' className='block text-sm leading-6 font-medium'>
|
|
100
103
|
{getString('username')}
|
|
101
104
|
</label>
|
|
102
105
|
<div>
|
|
@@ -106,13 +109,13 @@ export default function LoginPage() {
|
|
|
106
109
|
type='text'
|
|
107
110
|
placeholder={getString('username')}
|
|
108
111
|
required
|
|
109
|
-
className='block w-full rounded-md border-0
|
|
112
|
+
className='bg-background text-foreground block w-full rounded-md border-0 p-3 shadow-xs ring-1 ring-gray-300 outline-0 ring-inset placeholder:text-gray-400 focus:ring-2 focus:ring-indigo-600 focus:ring-inset sm:text-sm sm:leading-6'
|
|
110
113
|
/>
|
|
111
114
|
</div>
|
|
112
115
|
</div>
|
|
113
116
|
|
|
114
117
|
<div>
|
|
115
|
-
<label htmlFor='password' className='block text-sm font-medium
|
|
118
|
+
<label htmlFor='password' className='block text-sm leading-6 font-medium'>
|
|
116
119
|
{getString('password')}
|
|
117
120
|
</label>
|
|
118
121
|
<div>
|
|
@@ -122,7 +125,7 @@ export default function LoginPage() {
|
|
|
122
125
|
type='password'
|
|
123
126
|
placeholder={getString('password')}
|
|
124
127
|
required
|
|
125
|
-
className='block w-full rounded-md border-0
|
|
128
|
+
className='bg-background text-foreground block w-full rounded-md border-0 p-3 shadow-xs ring-1 ring-sky-300 outline-0 ring-inset placeholder:text-gray-400 focus:ring-2 focus:ring-indigo-600 focus:ring-inset sm:text-sm sm:leading-6'
|
|
126
129
|
/>
|
|
127
130
|
</div>
|
|
128
131
|
<div className='mt-2 text-end'>
|
|
@@ -150,7 +153,7 @@ export default function LoginPage() {
|
|
|
150
153
|
ref={loginButtonRef}
|
|
151
154
|
onClick={handleSubmit}
|
|
152
155
|
type='submit'
|
|
153
|
-
className='flex w-full justify-center rounded-md bg-linear-to-r from-green-400 to-blue-500 font-extrabold hover:to-sky-400 focus-visible:outline-
|
|
156
|
+
className='flex w-full justify-center rounded-md bg-linear-to-r from-green-400 to-blue-500 font-extrabold hover:to-sky-400 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 focus-visible:outline-solid'
|
|
154
157
|
>
|
|
155
158
|
{getString('login')}
|
|
156
159
|
</Button>
|
|
@@ -4,10 +4,11 @@ import type { Metadata } from 'next'
|
|
|
4
4
|
import { cn } from '@/lib/utils'
|
|
5
5
|
import { ThemeProvider } from '@/components/ThemeProvider'
|
|
6
6
|
import Providers from '@/app/providers'
|
|
7
|
+
import auth from 'nextjs-cms/auth'
|
|
7
8
|
|
|
8
9
|
export const metadata: Metadata = {
|
|
9
|
-
title: '
|
|
10
|
-
description: '
|
|
10
|
+
title: 'nextjs-cms',
|
|
11
|
+
description: 'nextjs-cms',
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
const inter = Inter({
|
|
@@ -16,11 +17,12 @@ const inter = Inter({
|
|
|
16
17
|
})
|
|
17
18
|
|
|
18
19
|
export default async function RootLayout({ children }: { children: React.ReactNode }) {
|
|
20
|
+
const session = await auth()
|
|
19
21
|
return (
|
|
20
22
|
<html lang='en' suppressHydrationWarning>
|
|
21
23
|
<body className={cn('bg-background min-h-screen font-sans antialiased', inter.variable)}>
|
|
22
24
|
<ThemeProvider attribute='class' defaultTheme='dark' enableSystem disableTransitionOnChange>
|
|
23
|
-
<Providers>{children}</Providers>
|
|
25
|
+
<Providers session={session}>{children}</Providers>
|
|
24
26
|
</ThemeProvider>
|
|
25
27
|
</body>
|
|
26
28
|
</html>
|
|
@@ -8,6 +8,7 @@ import { httpBatchLink, loggerLink } from '@trpc/client'
|
|
|
8
8
|
import SuperJSON from 'superjson'
|
|
9
9
|
import { useState } from 'react'
|
|
10
10
|
import { getCsrfToken, SessionProvider, refreshTokenLink } from 'nextjs-cms/auth/react'
|
|
11
|
+
import { Session } from 'nextjs-cms/auth'
|
|
11
12
|
|
|
12
13
|
function MakeTrpcClient() {
|
|
13
14
|
const [trpcClient] = useState(() =>
|
|
@@ -94,7 +95,7 @@ function makeQueryClient() {
|
|
|
94
95
|
/**
|
|
95
96
|
* We want to refetch on window focus in development only
|
|
96
97
|
*/
|
|
97
|
-
refetchOnWindowFocus: process.env.NODE_ENV === 'development' ? true : false,
|
|
98
|
+
refetchOnWindowFocus: process.env.NODE_ENV === 'development' ? true : false,
|
|
98
99
|
retry: 1, // default: 3
|
|
99
100
|
},
|
|
100
101
|
dehydrate: {
|
|
@@ -124,7 +125,7 @@ function getQueryClient() {
|
|
|
124
125
|
}
|
|
125
126
|
}
|
|
126
127
|
|
|
127
|
-
export default function Providers({ children }: { children: React.ReactNode }) {
|
|
128
|
+
export default function Providers({ children, session }: { children: React.ReactNode; session: Session | null }) {
|
|
128
129
|
// NOTE: Avoid useState when initializing the query client if you don't
|
|
129
130
|
// have a suspense boundary between this and the code that may
|
|
130
131
|
// suspend because React will throw away the client on the initial
|
|
@@ -137,12 +138,12 @@ export default function Providers({ children }: { children: React.ReactNode }) {
|
|
|
137
138
|
<QueryClientProvider client={queryClient}>
|
|
138
139
|
<trpc.Provider client={trpcClient} queryClient={queryClient}>
|
|
139
140
|
<SessionProvider
|
|
141
|
+
session={session}
|
|
140
142
|
refetchOnWindowFocus={false}
|
|
141
143
|
refetchInterval={0}
|
|
142
|
-
refetchWhenOffline={false}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
</ModalProvider>
|
|
144
|
+
refetchWhenOffline={false}
|
|
145
|
+
>
|
|
146
|
+
<ModalProvider>{children}</ModalProvider>
|
|
146
147
|
</SessionProvider>
|
|
147
148
|
<ReactQueryDevtools initialIsOpen={false} />
|
|
148
149
|
</trpc.Provider>
|
|
@@ -18,7 +18,7 @@ function Layout({ children }: { children: React.ReactNode }) {
|
|
|
18
18
|
return (
|
|
19
19
|
<div
|
|
20
20
|
className={classNames({
|
|
21
|
-
'flex min-h-screen flex-col
|
|
21
|
+
'bg-background text-foreground flex min-h-screen flex-col': true,
|
|
22
22
|
'overflow-hidden': true,
|
|
23
23
|
})}
|
|
24
24
|
>
|
|
@@ -38,7 +38,7 @@ function Layout({ children }: { children: React.ReactNode }) {
|
|
|
38
38
|
{showMobileSidebar && (
|
|
39
39
|
// Display a black transparent div to close the sidebar when clicked outside
|
|
40
40
|
<div
|
|
41
|
-
className='fixed
|
|
41
|
+
className='fixed top-0 left-0 z-15 h-full w-full bg-black/80 md:hidden'
|
|
42
42
|
onClick={() => setShowMobileSidebar(false)}
|
|
43
43
|
></div>
|
|
44
44
|
)}
|
|
@@ -62,7 +62,7 @@ export default function Navbar(props: Props) {
|
|
|
62
62
|
{/* Mobile menu button */}
|
|
63
63
|
<button
|
|
64
64
|
onClick={props.onMenuButtonClick}
|
|
65
|
-
className='relative inline-flex items-center justify-center rounded-md border
|
|
65
|
+
className='border-foreground text-foreground hover:text-foreground/90 relative inline-flex items-center justify-center rounded-md border p-2 focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800 focus:outline-hidden'
|
|
66
66
|
>
|
|
67
67
|
<span className='absolute -inset-0.5' />
|
|
68
68
|
<span className='sr-only'>Open main menu</span>
|
|
@@ -87,7 +87,7 @@ export default function Navbar(props: Props) {
|
|
|
87
87
|
<DropdownMenu>
|
|
88
88
|
<DropdownMenuTrigger
|
|
89
89
|
asChild
|
|
90
|
-
className='
|
|
90
|
+
className='text-foreground hover:text-foreground/90 cursor-pointer'
|
|
91
91
|
>
|
|
92
92
|
<BellIcon className='h-6 w-6' />
|
|
93
93
|
</DropdownMenuTrigger>
|
|
@@ -109,7 +109,7 @@ export default function Navbar(props: Props) {
|
|
|
109
109
|
setTheme(theme === 'dark' ? 'light' : 'dark')
|
|
110
110
|
}}
|
|
111
111
|
type='button'
|
|
112
|
-
className='
|
|
112
|
+
className='text-foreground hover:text-foreground/90 relative rounded-full p-1 focus:outline-hidden'
|
|
113
113
|
>
|
|
114
114
|
<span className='absolute -inset-1.5' />
|
|
115
115
|
<span className='sr-only'>Theme</span>
|
|
@@ -123,7 +123,7 @@ export default function Navbar(props: Props) {
|
|
|
123
123
|
<DropdownMenu>
|
|
124
124
|
<DropdownMenuTrigger
|
|
125
125
|
asChild
|
|
126
|
-
className='relative ms-2 flex max-w-xs cursor-pointer items-center rounded-full bg-gray-800 text-sm hover:ring-3 focus:
|
|
126
|
+
className='relative ms-2 flex max-w-xs cursor-pointer items-center rounded-full bg-gray-800 text-sm hover:ring-3 focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800 focus:outline-hidden'
|
|
127
127
|
>
|
|
128
128
|
<div>
|
|
129
129
|
<span className='absolute -inset-1.5' />
|
|
@@ -145,7 +145,7 @@ export default function Navbar(props: Props) {
|
|
|
145
145
|
height={36}
|
|
146
146
|
width={36}
|
|
147
147
|
alt='profile image'
|
|
148
|
-
className='rounded-full ring-2 ring-
|
|
148
|
+
className='rounded-full ring-2 ring-amber-300 ring-inset'
|
|
149
149
|
/>
|
|
150
150
|
)}
|
|
151
151
|
</div>
|
|
@@ -32,7 +32,7 @@ const Sidebar = (props: SidebarProps) => {
|
|
|
32
32
|
return (
|
|
33
33
|
<div
|
|
34
34
|
className={classNames({
|
|
35
|
-
'fixed z-20 h-full bg-linear-to-br from-indigo-600 to-sky-500 text-zinc-50 dark:from-slate-950 dark:to-pink-950
|
|
35
|
+
'fixed z-20 h-full bg-linear-to-br from-indigo-600 to-sky-500 text-zinc-50 md:translate-x-0 dark:from-slate-950 dark:to-pink-950':
|
|
36
36
|
true,
|
|
37
37
|
'transition-all duration-100 ease-in-out': true,
|
|
38
38
|
'w-[300px] md:w-[275px]': true,
|
|
@@ -52,7 +52,7 @@ const Sidebar = (props: SidebarProps) => {
|
|
|
52
52
|
})}
|
|
53
53
|
>
|
|
54
54
|
<span className='bg-gray-800 px-2 font-bold tracking-tighter text-amber-200 ring-1 ring-sky-500 transition-all duration-150 hover:bg-transparent hover:font-normal hover:tracking-[1em] hover:ring-0'>
|
|
55
|
-
|
|
55
|
+
nextjs-cms
|
|
56
56
|
</span>
|
|
57
57
|
</div>
|
|
58
58
|
<ScrollArea type='always' className='grow'>
|
|
@@ -74,7 +74,7 @@ const Sidebar = (props: SidebarProps) => {
|
|
|
74
74
|
{navItems && (
|
|
75
75
|
<>
|
|
76
76
|
{navItems.fixed_sections && navItems.fixed_sections.length > 0 && (
|
|
77
|
-
<div className='mx-3 flex flex-col border-b
|
|
77
|
+
<div className='border-primary/40 mx-3 flex flex-col border-b py-2'>
|
|
78
78
|
<h2 className='my-2 text-xs text-gray-300'>Main</h2>
|
|
79
79
|
{navItems.fixed_sections.map((item, index) => {
|
|
80
80
|
return (
|
|
@@ -89,7 +89,7 @@ const Sidebar = (props: SidebarProps) => {
|
|
|
89
89
|
)}
|
|
90
90
|
|
|
91
91
|
{navItems.cat_sections && navItems.cat_sections.length > 0 && (
|
|
92
|
-
<div className='mx-3 flex flex-col border-b
|
|
92
|
+
<div className='border-primary/40 mx-3 flex flex-col border-b py-2'>
|
|
93
93
|
<h2 className='my-2 text-xs text-gray-300'>Category Sections</h2>
|
|
94
94
|
{navItems.cat_sections.map((item, index) => {
|
|
95
95
|
return (
|
|
@@ -104,7 +104,7 @@ const Sidebar = (props: SidebarProps) => {
|
|
|
104
104
|
)}
|
|
105
105
|
|
|
106
106
|
{navItems.has_items_sections && navItems.has_items_sections.length > 0 && (
|
|
107
|
-
<div className='mx-3 flex flex-col border-b
|
|
107
|
+
<div className='border-primary/40 mx-3 flex flex-col border-b py-2'>
|
|
108
108
|
<h2 className='my-2 text-xs text-gray-300'>Sections with Items</h2>
|
|
109
109
|
<div className='flex flex-col gap-y-2'>
|
|
110
110
|
{navItems.has_items_sections.map((item, index) => {
|
|
@@ -182,7 +182,7 @@ const Sidebar = (props: SidebarProps) => {
|
|
|
182
182
|
width={40}
|
|
183
183
|
height={40}
|
|
184
184
|
// fill={true}
|
|
185
|
-
className='rounded-full ring-3
|
|
185
|
+
className='ring-foreground rounded-full ring-3'
|
|
186
186
|
/>
|
|
187
187
|
) : (
|
|
188
188
|
<Image
|
|
@@ -190,7 +190,7 @@ const Sidebar = (props: SidebarProps) => {
|
|
|
190
190
|
height={36}
|
|
191
191
|
width={36}
|
|
192
192
|
alt='profile image'
|
|
193
|
-
className='rounded-full ring-2 ring-
|
|
193
|
+
className='rounded-full ring-2 ring-amber-300 ring-inset'
|
|
194
194
|
/>
|
|
195
195
|
)}
|
|
196
196
|
|