create-nextjs-cms 0.5.70 → 0.5.71

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 (47) hide show
  1. package/package.json +3 -3
  2. package/templates/default/app/(rootLayout)/(plugins)/[...slug]/plugin-server-registry.ts +3 -2
  3. package/templates/default/app/(rootLayout)/browse/[section]/[page]/page.tsx +1 -0
  4. package/templates/default/app/(rootLayout)/layout.tsx +3 -1
  5. package/templates/default/app/layout.tsx +12 -6
  6. package/templates/default/cms.config.ts +1 -2
  7. package/templates/default/components/AdminsPage.tsx +6 -7
  8. package/templates/default/components/BarChartBox.tsx +1 -2
  9. package/templates/default/components/BrowsePage.tsx +10 -24
  10. package/templates/default/components/CategorizedSectionPage.tsx +5 -10
  11. package/templates/default/components/EmailsPage.tsx +1 -1
  12. package/templates/default/components/ErrorComponent.tsx +17 -0
  13. package/templates/default/components/GalleryPhoto.tsx +1 -2
  14. package/templates/default/components/InfoCard.tsx +0 -1
  15. package/templates/default/components/ItemEditPage.tsx +26 -30
  16. package/templates/default/components/Layout.tsx +3 -2
  17. package/templates/default/components/LogPage.tsx +0 -1
  18. package/templates/default/components/Modal.tsx +64 -7
  19. package/templates/default/components/Navbar.tsx +170 -17
  20. package/templates/default/components/NewPage.tsx +9 -11
  21. package/templates/default/components/PhotoGallery.tsx +0 -1
  22. package/templates/default/components/SectionItemCard.tsx +1 -1
  23. package/templates/default/components/SectionPage.tsx +8 -8
  24. package/templates/default/components/SelectBox.tsx +62 -77
  25. package/templates/default/components/SettingsPage.tsx +2 -9
  26. package/templates/default/components/Sidebar.tsx +5 -22
  27. package/templates/default/components/SidebarDropdownItem.tsx +2 -2
  28. package/templates/default/components/form/helpers/_section-hot-reload.js +1 -1
  29. package/templates/default/components/ui/alert-dialog.tsx +157 -0
  30. package/templates/default/components/ui/command.tsx +137 -184
  31. package/templates/default/components/ui/custom-alert-dialog.tsx +113 -0
  32. package/templates/default/components/ui/custom-dialog.tsx +123 -0
  33. package/templates/default/components/ui/dialog.tsx +123 -143
  34. package/templates/default/components/ui/popover.tsx +28 -34
  35. package/templates/default/components/ui/sheet.tsx +103 -107
  36. package/templates/default/package.json +4 -10
  37. package/templates/default/public/favicon.ico +0 -0
  38. package/templates/default/public/nextjscms.webp +0 -0
  39. package/templates/default/styles/globals.css +2 -1
  40. package/templates/default/app/(rootLayout)/(plugins)/[...slug]/.plugin-registry.mjs +0 -7
  41. package/templates/default/app/(rootLayout)/advanced/page.tsx +0 -11
  42. package/templates/default/components/AdvancedSettingsPage.tsx +0 -167
  43. package/templates/default/components/NavbarAlt.tsx +0 -182
  44. package/templates/default/components/TempPage.tsx +0 -12
  45. package/templates/default/public/lazemni_logo.png +0 -0
  46. package/templates/default/public/next.svg +0 -1
  47. package/templates/default/public/vercel.svg +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-nextjs-cms",
3
- "version": "0.5.70",
3
+ "version": "0.5.71",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "bin": {
@@ -29,8 +29,8 @@
29
29
  "tsx": "^4.20.6",
30
30
  "typescript": "^5.9.2",
31
31
  "@lzcms/eslint-config": "0.3.0",
32
- "@lzcms/tsconfig": "0.1.0",
33
- "@lzcms/prettier-config": "0.1.0"
32
+ "@lzcms/prettier-config": "0.1.0",
33
+ "@lzcms/tsconfig": "0.1.0"
34
34
  },
35
35
  "prettier": "@lzcms/prettier-config",
36
36
  "scripts": {
@@ -1,8 +1,9 @@
1
1
  import dynamic from 'next/dynamic'
2
- import { _pluginNamesMap } from './.plugin-registry.mjs'
3
2
 
4
3
  export const pluginNamesMap: Record<string, string> = {
5
- ..._pluginNamesMap,
4
+ 'cpanel-dashboard': '@nextjs-cms-plugins/cpanel-dashboard/server',
5
+ 'cpanel-emails': '@nextjs-cms-plugins/cpanel-emails/server',
6
+ 'google-analytics': '@nextjs-cms-plugins/google-analytics/server',
6
7
  // A workaround to avoid importing error if no plugins are installed
7
8
  blank: 'nextjs-cms/plugins/blank-component',
8
9
  }
@@ -7,6 +7,7 @@ export default async function Page(props: { params: Params; searchParams: Search
7
7
  const searchParams = await props.searchParams
8
8
  const { q } = searchParams
9
9
  const { section, page } = params
10
+
10
11
  await api.hasItemsSections.listItems.prefetch({
11
12
  sectionName: section,
12
13
  page: parseInt(page) ?? 1,
@@ -1,12 +1,14 @@
1
1
  import Layout from '@/components/Layout'
2
2
  import { api, HydrateClient } from 'nextjs-cms/api/trpc/server'
3
+ import { getCMSConfig } from 'nextjs-cms/core'
3
4
 
4
5
  export default async function CMSLayout({ children }: { children: React.ReactNode }) {
5
6
  await api.navigation.getSidebar.prefetch()
7
+ const cmsConfig = await getCMSConfig()
6
8
 
7
9
  return (
8
10
  <HydrateClient>
9
- <Layout>{children}</Layout>
11
+ <Layout logoUrlPath={cmsConfig.ui.logo}>{children}</Layout>
10
12
  </HydrateClient>
11
13
  )
12
14
  }
@@ -5,23 +5,29 @@ import { cn } from '@/lib/utils'
5
5
  import { ThemeProvider } from '@/components/ThemeProvider'
6
6
  import Providers from '@/app/providers'
7
7
  import auth from 'nextjs-cms/auth'
8
-
9
- export const metadata: Metadata = {
10
- title: 'nextjs-cms',
11
- description: 'nextjs-cms',
12
- }
8
+ import { getCMSConfig } from 'nextjs-cms/core'
13
9
 
14
10
  const inter = Inter({
15
11
  subsets: ['latin'],
16
12
  variable: '--font-sans',
17
13
  })
18
14
 
15
+
16
+ export async function generateMetadata(): Promise<Metadata> {
17
+ const cmsConfig = await getCMSConfig()
18
+ return {
19
+ title: cmsConfig.ui.title,
20
+ description: 'nextjs-cms',
21
+ }
22
+ }
23
+
19
24
  export default async function RootLayout({ children }: { children: React.ReactNode }) {
20
25
  const session = await auth()
26
+ const cmsConfig = await getCMSConfig()
21
27
  return (
22
28
  <html lang='en' suppressHydrationWarning>
23
29
  <body className={cn('bg-background min-h-screen font-sans antialiased', inter.variable)}>
24
- <ThemeProvider attribute='class' defaultTheme='dark' enableSystem disableTransitionOnChange>
30
+ <ThemeProvider attribute='class' defaultTheme={cmsConfig.ui.defaultTheme} enableSystem disableTransitionOnChange>
25
31
  <Providers session={session ?? undefined}>{children}</Providers>
26
32
  </ThemeProvider>
27
33
  </body>
@@ -3,9 +3,8 @@ import process from 'process'
3
3
  import { resolve } from 'path'
4
4
 
5
5
  export const config: CMSConfig = {
6
- title: 'NEXT CMS Admin',
6
+ title: 'NEXTJS CMS',
7
7
  defaultTheme: 'dark',
8
- logo: '/logo.svg',
9
8
  },
10
9
  debug: true,
11
10
  sections: {
@@ -4,12 +4,16 @@ import AdminCard from '@/components/AdminCard'
4
4
  import getString from 'nextjs-cms/translations'
5
5
  import NewAdminForm from '@/components/NewAdminForm'
6
6
  import ContainerBox from '@/components/ContainerBox'
7
- import LoadingSpinners from '@/components/LoadingSpinners'
8
7
  import { trpc } from '@/app/_trpc/client'
8
+ import ErrorComponent from './ErrorComponent'
9
9
 
10
10
  const AdminsPage = () => {
11
- const { isLoading, isError, data, error, refetch } = trpc.admins.list.useQuery()
11
+ const [data, {refetch}] = trpc.admins.list.useSuspenseQuery()
12
12
 
13
+ if (data.error) {
14
+ return <ErrorComponent message={data.error.message} />
15
+ }
16
+
13
17
  return (
14
18
  <div className='w-full'>
15
19
  <div className='bg-linear-to-r from-sky-200 via-emerald-300 to-blue-600 p-8 font-extrabold text-foreground dark:from-blue-800 dark:via-amber-700 dark:to-rose-900'>
@@ -21,11 +25,6 @@ const AdminsPage = () => {
21
25
  {data && data.privileges && <NewAdminForm action={() => refetch()} privileges={data.privileges} />}
22
26
  </ContainerBox>
23
27
 
24
- {isLoading && (
25
- <div>
26
- <LoadingSpinners />
27
- </div>
28
- )}
29
28
  {data && data.admins && data.admins.length > 0 && (
30
29
  <ContainerBox title={getString('admins_list')}>
31
30
  <div className='mt-2 grid w-full grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3'>
@@ -1,6 +1,5 @@
1
- import React from 'react'
2
1
  import ContainerBox from '@/components/ContainerBox'
3
- import { BarChart, Bar, Rectangle, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'
2
+ import { BarChart, Bar, XAxis, YAxis, ResponsiveContainer } from 'recharts'
4
3
  import { BarChartDataItem } from 'nextjs-cms/core/types'
5
4
  import LoadingSpinners from '@/components/LoadingSpinners'
6
5
 
@@ -1,9 +1,8 @@
1
1
  'use client'
2
2
 
3
- import React, { useEffect, useRef } from 'react'
3
+ import { useRef } from 'react'
4
4
  import getString from 'nextjs-cms/translations'
5
5
  import SectionItemCard from '@/components/SectionItemCard'
6
- import LoadingSpinners from '@/components/LoadingSpinners'
7
6
  import ContainerBox from '@/components/ContainerBox'
8
7
  import Pagination from '@/components/pagination/Pagination'
9
8
  import { Alert, AlertDescription } from '@/components/ui/alert'
@@ -12,8 +11,8 @@ import { Input } from './ui/input'
12
11
  import { Button } from './ui/button'
13
12
  import { useRouter, useSearchParams } from 'next/navigation'
14
13
  import { trpc } from '@/app/_trpc/client'
15
- import { ExclamationTriangleIcon } from '@radix-ui/react-icons'
16
14
  import { capitalizeWords } from 'nextjs-cms/utils'
15
+ import ErrorComponent from '@/components/ErrorComponent'
17
16
 
18
17
  export default function BrowsePage({ section, page }: { section: string; page: string }) {
19
18
  const pageInt = parseInt(page) ?? 1
@@ -21,13 +20,15 @@ export default function BrowsePage({ section, page }: { section: string; page: s
21
20
  const router = useRouter()
22
21
  const q = params.get('q') ?? ''
23
22
  const searchInputRef = useRef<HTMLInputElement>(null)
24
- const { isLoading, isError, data, error, refetch } = trpc.hasItemsSections.listItems.useQuery({
23
+ const [data, {refetch}] = trpc.hasItemsSections.listItems.useSuspenseQuery({
25
24
  sectionName: section,
26
25
  page: pageInt,
27
26
  q,
28
27
  })
29
28
 
30
- useEffect(() => {}, [])
29
+ if (data.error) {
30
+ return <ErrorComponent message={data.error.message} />
31
+ }
31
32
 
32
33
  return (
33
34
  <div>
@@ -67,23 +68,9 @@ export default function BrowsePage({ section, page }: { section: string; page: s
67
68
  </Card>
68
69
  ) : null}
69
70
  <ContainerBox title={getString('browse')}>
70
- {isLoading ? (
71
- <div>
72
- <LoadingSpinners />
73
- </div>
74
- ) : null}
75
-
76
- {data ? (
77
- <>
78
- {data.error ? (
79
- <Alert variant='destructive' className='my-8'>
80
- <AlertDescription className='text-md font-bold'>
81
- <div className='flex items-center gap-1.5'>
82
- <ExclamationTriangleIcon className='h-5 w-5' /> {data.error.message}
83
- </div>
84
- </AlertDescription>
85
- </Alert>
86
- ) : data.items && data.items.length > 0 ? (
71
+
72
+
73
+ { data.items && data.items.length > 0 ? (
87
74
  <div className='mt-2 grid w-full grid-cols-1 gap-8 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4'>
88
75
  {data.items.map((item, index: number) => (
89
76
  <SectionItemCard
@@ -99,8 +86,7 @@ export default function BrowsePage({ section, page }: { section: string; page: s
99
86
  <AlertDescription className='font-bold'>{getString('noItems')}</AlertDescription>
100
87
  </Alert>
101
88
  )}
102
- </>
103
- ) : null}
89
+
104
90
  </ContainerBox>
105
91
  {data?.totalCount && data?.totalCount > 0 ? (
106
92
  <Pagination
@@ -1,16 +1,17 @@
1
1
  'use client'
2
2
 
3
- import React, { useEffect } from 'react'
4
- import LoadingSpinners from '@/components/LoadingSpinners'
5
3
  import { trpc } from '@/app/_trpc/client'
6
4
  import CategorySectionSelectInput from '@/components/CategorySectionSelectInput'
5
+ import ErrorComponent from '@/components/ErrorComponent'
7
6
 
8
7
  export default function CategorizedSectionPage({ section }: { section: string }) {
9
- const { isLoading, isError, data, error, refetch } = trpc.categorySections.get.useQuery({
8
+ const [data, {refetch}] = trpc.categorySections.get.useSuspenseQuery({
10
9
  sectionName: section,
11
10
  })
12
11
 
13
- useEffect(() => {}, [])
12
+ if (data.error) {
13
+ return <ErrorComponent message={data.error.message} />
14
+ }
14
15
 
15
16
  return (
16
17
  <div>
@@ -21,12 +22,6 @@ export default function CategorizedSectionPage({ section }: { section: string })
21
22
  </div>
22
23
  <div className='flex w-full flex-col'>
23
24
  <div className='rounded-xl p-4 shadow-sm'>
24
- {isLoading && (
25
- <div>
26
- <LoadingSpinners />
27
- </div>
28
- )}
29
-
30
25
  {data && data.data ? <CategorySectionSelectInput refetch={refetch} input={data.data} /> : null}
31
26
  </div>
32
27
  </div>
@@ -1,6 +1,6 @@
1
1
  'use client'
2
2
 
3
- import React, { useEffect } from 'react'
3
+ import { useEffect } from 'react'
4
4
  import { EmailItem } from 'nextjs-cms/core/types'
5
5
  import getString from 'nextjs-cms/translations'
6
6
  import ContainerBox from '@/components/ContainerBox'
@@ -0,0 +1,17 @@
1
+ import { Alert, AlertDescription } from './ui/alert'
2
+ import { ExclamationTriangleIcon } from '@radix-ui/react-icons'
3
+
4
+ export default function ErrorComponent({ message }: { message: string }) {
5
+ return (
6
+ <div className='px-4'>
7
+ <Alert variant='info' className='my-8'>
8
+ <AlertDescription className='text-md font-bold'>
9
+ <div className='flex items-center gap-1.5'>
10
+ <ExclamationTriangleIcon className='size-5' /> {message}
11
+ </div>
12
+ </AlertDescription>
13
+ </Alert>
14
+ </div>
15
+ )
16
+
17
+ }
@@ -2,13 +2,12 @@ import { PhotoGalleryItem } from 'nextjs-cms/core/types'
2
2
  import getString from 'nextjs-cms/translations'
3
3
  import { MinusIcon } from '@radix-ui/react-icons'
4
4
  import ProtectedImage from '@/components/ProtectedImage'
5
- import React from 'react'
6
5
  import useModal from '@/hooks/useModal'
7
6
  import { useToast } from '@/components/ui/use-toast'
8
7
  import { trpc } from '@/app/_trpc/client'
9
8
 
10
9
  const GalleryPhoto = ({ item, sectionName, action }: { item: PhotoGalleryItem; sectionName: string; action?: any }) => {
11
- const { setModal, modal, modalResponse, setModalResponse } = useModal()
10
+ const { setModal, setModalResponse } = useModal()
12
11
  const deleteMutation = trpc.gallery.deletePhoto.useMutation({
13
12
  onError: (error) => {
14
13
  toast({
@@ -1,7 +1,6 @@
1
1
  'use client'
2
2
 
3
3
  import Link from 'next/link'
4
- import React from 'react'
5
4
  import { CheckCircle, OctagonIcon, TriangleIcon } from 'lucide-react'
6
5
 
7
6
  type result = {
@@ -1,19 +1,19 @@
1
1
  'use client'
2
2
 
3
3
  import { useAxiosPrivate } from 'nextjs-cms/auth/hooks'
4
- import React, { RefObject, useEffect, useRef, useState } from 'react'
4
+ import { RefObject, useEffect, useRef, useState } from 'react'
5
5
  import { SectionType } from 'nextjs-cms/core/types'
6
6
  import getString from 'nextjs-cms/translations'
7
7
  import useModal from '@/hooks/useModal'
8
8
  import { AxiosError } from 'axios'
9
9
  import InfoCard from '@/components/InfoCard'
10
10
  import { useRouter } from 'next/navigation'
11
- import LoadingSpinners from '@/components/LoadingSpinners'
12
11
  import { useToast } from '@/components/ui/use-toast'
13
12
  import { DropzoneHandles } from '@/components/Dropzone'
14
13
  import { VariantHandles } from '@/components/NewVariantComponent'
15
14
  import { trpc } from '@/app/_trpc/client'
16
15
  import Form from '@/components/form/Form'
16
+ import ErrorComponent from '@/components/ErrorComponent'
17
17
 
18
18
  export default function ItemEditPage({
19
19
  section,
@@ -42,7 +42,7 @@ export default function ItemEditPage({
42
42
  const router = useRouter()
43
43
  const dropzoneRef: RefObject<DropzoneHandles | null> = useRef(null)
44
44
  const variantRef: RefObject<VariantHandles[]> = useRef([])
45
- const { isLoading, isError, data, error, refetch } = trpc.hasItemsSections.editItem.useQuery({
45
+ const [data, {refetch}] = trpc.hasItemsSections.editItem.useSuspenseQuery({
46
46
  sectionName: section,
47
47
  sectionItemId: itemId,
48
48
  })
@@ -182,36 +182,32 @@ export default function ItemEditPage({
182
182
  }
183
183
  }, [])
184
184
 
185
+ if (data.error) {
186
+ return <ErrorComponent message={data.error.message} />
187
+ }
188
+
185
189
  return (
186
190
  <div className='flex w-full flex-col overflow-hidden'>
187
- {isLoading ? (
188
- <div>
189
- <LoadingSpinners />
190
- </div>
191
- ) : null}
192
- {isError ? <div>{error?.message}</div> : null}
193
- {data ? (
194
- <div className='flex w-full flex-col'>
195
- <div className='relative z-1 border-b-2 p-8 pt-12 font-extrabold text-foreground'>
196
- <div className='absolute left-0 top-0 z-2 h-4 w-full bg-linear-to-r from-emerald-800 via-emerald-400 to-sky-600'></div>
197
- <h1 className='pb-4 text-4xl'>{data.section?.title.section}</h1>
198
- <span>
199
- /{getString('edit')} {data.section?.title.singular}
200
- </span>
201
- </div>
202
- <Form
203
- formType='edit'
204
- progressVariant={progressVariant}
205
- response={response}
206
- progress={progress}
207
- data={data}
208
- dropzoneRef={dropzoneRef}
209
- variantRef={variantRef}
210
- handleSubmit={handleSubmit}
211
- isSubmitting={isSubmitting}
212
- />
191
+ <div className='flex w-full flex-col'>
192
+ <div className='relative z-1 border-b-2 p-8 pt-12 font-extrabold text-foreground'>
193
+ <div className='absolute left-0 top-0 z-2 h-4 w-full bg-linear-to-r from-emerald-800 via-emerald-400 to-sky-600'></div>
194
+ <h1 className='pb-4 text-4xl'>{data.section?.title.section}</h1>
195
+ <span>
196
+ /{getString('edit')} {data.section?.title.singular}
197
+ </span>
213
198
  </div>
214
- ) : null}
199
+ <Form
200
+ formType='edit'
201
+ progressVariant={progressVariant}
202
+ response={response}
203
+ progress={progress}
204
+ data={data}
205
+ dropzoneRef={dropzoneRef}
206
+ variantRef={variantRef}
207
+ handleSubmit={handleSubmit}
208
+ isSubmitting={isSubmitting}
209
+ />
210
+ </div>
215
211
  </div>
216
212
  )
217
213
  }
@@ -2,14 +2,14 @@
2
2
 
3
3
  import classNames from 'classnames'
4
4
  import React, { useState } from 'react'
5
- import Navbar from '@/components/NavbarAlt'
5
+ import Navbar from '@/components/Navbar'
6
6
  import Sidebar from '@/components/Sidebar'
7
7
  import Modal from '@/components/Modal'
8
8
  import { Toaster } from '@/components/ui/toaster'
9
9
  import { useSession } from 'nextjs-cms/auth/react'
10
10
  import LoadingSpinners from '@/components/LoadingSpinners'
11
11
 
12
- function Layout({ children }: { children: React.ReactNode }) {
12
+ function Layout({ children, logoUrlPath }: { children: React.ReactNode, logoUrlPath: string }) {
13
13
  const [showMobileSidebar, setShowMobileSidebar] = useState(false)
14
14
  const session = useSession({
15
15
  required: true,
@@ -34,6 +34,7 @@ function Layout({ children }: { children: React.ReactNode }) {
34
34
  setShowMobileSidebar(false)
35
35
  }}
36
36
  mobileSidebar={showMobileSidebar}
37
+ logoUrlPath={logoUrlPath}
37
38
  />
38
39
  {showMobileSidebar && (
39
40
  // Display a black transparent div to close the sidebar when clicked outside
@@ -1,7 +1,6 @@
1
1
  'use client'
2
2
 
3
3
  import getString from 'nextjs-cms/translations'
4
- import React from 'react'
5
4
 
6
5
  export default function LogPage() {
7
6
  return (
@@ -1,16 +1,22 @@
1
1
  'use client'
2
2
 
3
- import React, { Fragment, useEffect, useRef } from 'react'
4
- import { Dialog, Transition } from '@headlessui/react'
3
+ import { useEffect, useRef, useState } from 'react'
5
4
  import useModal from '@/hooks/useModal'
6
5
  import classNames from 'classnames'
7
6
  import { X } from 'lucide-react'
8
7
 
8
+ import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/custom-dialog'
9
+
9
10
  function Modal() {
10
11
  const { setModal, modal, modalResponse, setModalResponse } = useModal()
12
+ const [open, setOpen] = useState(false)
11
13
 
12
14
  const handleClose = () => {
13
- setModal(null)
15
+ setOpen(false)
16
+ // Close after 100ms
17
+ setTimeout(() => {
18
+ setModal(null)
19
+ }, 200)
14
20
  }
15
21
 
16
22
  const cancelButtonRef = useRef(null)
@@ -18,9 +24,59 @@ function Modal() {
18
24
  useEffect(() => {
19
25
  if (!modal) {
20
26
  setModalResponse(null)
27
+ } else {
28
+ setOpen(true)
21
29
  }
22
30
  }, [modal])
23
31
 
32
+ if (!modal) return null
33
+
34
+ return (
35
+ <Dialog open={open} onOpenChange={handleClose}>
36
+ <DialogContent
37
+ showCloseButton={false}
38
+ onOpenAutoFocus={(e) => e.preventDefault()}
39
+ onInteractOutside={(e) => e.preventDefault()}
40
+ onPointerDownOutside={(e) => e.preventDefault()}
41
+ className={classNames({
42
+ 'bg-background w-full rounded-lg p-0 text-start': true,
43
+ 'max-w-lg': modal?.size === 'sm' || modal?.size === undefined,
44
+ 'max-w-2xl': modal?.size === 'md',
45
+ 'max-w-4xl': modal?.size === 'lg',
46
+ 'max-w-6xl': modal?.size === 'xl',
47
+ })}
48
+ >
49
+ <DialogHeader>
50
+ <DialogTitle
51
+ className={`flex items-center rounded-t-lg text-xl leading-6 font-semibold ${modal?.titleColor} p-6 pt-5 pb-4 md:pe-20 ${modal?.headerColor}`}
52
+ >
53
+ <div>{modal?.title || ''}</div>
54
+ <X
55
+ className={`absolute ${
56
+ modal?.lang === 'ar' ? 'left-5' : 'right-5'
57
+ } size-4 cursor-pointer rounded bg-white text-gray-500 hover:opacity-90 md:block lg:size-6`}
58
+ onClick={handleClose}
59
+ ref={cancelButtonRef}
60
+ />
61
+ </DialogTitle>
62
+ </DialogHeader>
63
+ <div className='max-h-[calc(90vh-120px)] min-h-0 flex-1 overflow-y-auto'>
64
+ <div className='flex flex-col gap-1'>
65
+ <div className='w-full overflow-hidden'>
66
+ <div className='flex w-full flex-col font-semibold'>
67
+ <div className='text-foreground w-full'>{modal?.body}</div>
68
+ <div className='w-full'>
69
+ {modalResponse && <div className={`w-full p-3`}>{modalResponse.message}</div>}
70
+ </div>
71
+ </div>
72
+ </div>
73
+ </div>
74
+ </div>
75
+ </DialogContent>
76
+ </Dialog>
77
+ )
78
+
79
+ /*
24
80
  return (
25
81
  <Transition.Root show={modal !== null} as={Fragment}>
26
82
  <Dialog as='div' className='relative z-50' initialFocus={cancelButtonRef} onClose={handleClose}>
@@ -49,7 +105,7 @@ function Modal() {
49
105
  >
50
106
  <Dialog.Panel
51
107
  className={classNames({
52
- 'relative w-full rounded-lg bg-background text-start shadow-xl transition-all sm:my-8':
108
+ 'bg-background relative w-full rounded-lg text-start shadow-xl transition-all sm:my-8':
53
109
  true,
54
110
  'max-w-lg': modal?.size === 'sm' || modal?.size === undefined,
55
111
  'max-w-2xl': modal?.size === 'md',
@@ -57,12 +113,12 @@ function Modal() {
57
113
  'max-w-6xl': modal?.size === 'xl',
58
114
  })}
59
115
  >
60
- <div className='rounded-lg bg-background'>
116
+ <div className='bg-background rounded-lg'>
61
117
  {modal && (
62
118
  <div className='flex flex-col gap-1'>
63
119
  <div className='w-full overflow-hidden rounded'>
64
120
  <div
65
- className={`flex items-center rounded-t-lg text-xl font-semibold leading-6 ${modal.titleColor} p-6 pb-4 pt-5 md:pe-20 ${modal.headerColor}`}
121
+ className={`flex items-center rounded-t-lg text-xl leading-6 font-semibold ${modal.titleColor} p-6 pt-5 pb-4 md:pe-20 ${modal.headerColor}`}
66
122
  >
67
123
  <Dialog.Title as='h3' className='pe-5'>
68
124
  {modal.title}
@@ -76,7 +132,7 @@ function Modal() {
76
132
  />
77
133
  </div>
78
134
  <div className='flex w-full flex-col font-semibold'>
79
- <div className='w-full text-foreground'>{modal.body}</div>
135
+ <div className='text-foreground w-full'>{modal.body}</div>
80
136
  <div className='w-full'>
81
137
  {modalResponse && (
82
138
  <div className={`w-full p-3`}>{modalResponse.message}</div>
@@ -94,6 +150,7 @@ function Modal() {
94
150
  </Dialog>
95
151
  </Transition.Root>
96
152
  )
153
+ */
97
154
  }
98
155
 
99
156
  export default Modal