create-nextjs-cms 0.9.28 → 0.9.30
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/LICENSE +21 -21
- package/README.md +71 -71
- package/dist/helpers/utils.js +16 -16
- package/dist/lib/section-creators.js +166 -166
- package/package.json +2 -2
- package/templates/default/.eslintrc.json +5 -5
- package/templates/default/.prettierignore +7 -7
- package/templates/default/.prettierrc.json +27 -27
- package/templates/default/CHANGELOG.md +140 -140
- package/templates/default/_gitignore +57 -57
- package/templates/default/app/(auth)/auth/login/LoginPage.tsx +192 -192
- package/templates/default/app/(auth)/auth/login/page.tsx +11 -11
- package/templates/default/app/(auth)/auth-language-provider.tsx +34 -34
- package/templates/default/app/(auth)/layout.tsx +81 -81
- package/templates/default/app/(rootLayout)/admins/page.tsx +10 -10
- package/templates/default/app/(rootLayout)/browse/[section]/[page]/page.tsx +22 -22
- package/templates/default/app/(rootLayout)/categorized/[section]/page.tsx +15 -15
- package/templates/default/app/(rootLayout)/dashboard/page.tsx +70 -70
- package/templates/default/app/(rootLayout)/edit/[section]/[itemId]/page.tsx +20 -20
- package/templates/default/app/(rootLayout)/layout.tsx +81 -81
- package/templates/default/app/(rootLayout)/loading.tsx +10 -10
- package/templates/default/app/(rootLayout)/log/page.tsx +7 -7
- package/templates/default/app/(rootLayout)/new/[section]/page.tsx +15 -15
- package/templates/default/app/(rootLayout)/section/[section]/page.tsx +19 -19
- package/templates/default/app/(rootLayout)/settings/page.tsx +13 -13
- package/templates/default/app/api/auth/csrf/route.ts +25 -25
- package/templates/default/app/api/auth/refresh/route.ts +10 -10
- package/templates/default/app/api/auth/route.ts +49 -49
- package/templates/default/app/api/auth/session/route.ts +20 -20
- package/templates/default/app/api/document/route.ts +165 -165
- package/templates/default/app/api/editor/photo/route.ts +49 -49
- package/templates/default/app/api/photo/route.ts +27 -27
- package/templates/default/app/api/submit/section/item/[slug]/route.ts +95 -95
- package/templates/default/app/api/submit/section/item/route.ts +56 -56
- package/templates/default/app/api/submit/section/simple/route.ts +86 -86
- package/templates/default/app/api/video/route.ts +174 -174
- package/templates/default/app/globals.css +236 -236
- package/templates/default/cms.config.ts +56 -56
- package/templates/default/components/admin/admin-card.tsx +165 -165
- package/templates/default/components/admin/admin-edit-page.tsx +124 -124
- package/templates/default/components/admin/admin-privilege-card.tsx +184 -184
- package/templates/default/components/admin/new-admin-form.tsx +172 -172
- package/templates/default/components/container-box.tsx +24 -24
- package/templates/default/components/dnd-kit/draggable.tsx +21 -21
- package/templates/default/components/dnd-kit/droppable.tsx +20 -20
- package/templates/default/components/dnd-kit/sortable-item.tsx +18 -18
- package/templates/default/components/feedback/error-component.tsx +16 -16
- package/templates/default/components/feedback/info-card.tsx +93 -93
- package/templates/default/components/feedback/loading-spinners.tsx +67 -67
- package/templates/default/components/feedback/modal.tsx +166 -166
- package/templates/default/components/feedback/progress-bar.tsx +48 -48
- package/templates/default/components/feedback/tooltip-component.tsx +27 -27
- package/templates/default/components/form/form-input-element.tsx +70 -70
- package/templates/default/components/form/helpers/_section-hot-reload.js +1 -1
- package/templates/default/components/form/helpers/util.ts +17 -17
- package/templates/default/components/form/inputs/checkbox-form-input.tsx +46 -46
- package/templates/default/components/form/inputs/color-form-input.tsx +44 -44
- package/templates/default/components/form/inputs/date-form-input.tsx +93 -93
- package/templates/default/components/form/inputs/map-form-input.tsx +141 -141
- package/templates/default/components/form/inputs/multiple-select-form-input.tsx +85 -85
- package/templates/default/components/form/inputs/number-form-input.tsx +43 -43
- package/templates/default/components/form/inputs/password-form-input.tsx +47 -47
- package/templates/default/components/form/inputs/photo-form-input.tsx +279 -279
- package/templates/default/components/form/inputs/rich-text-form-input.tsx +148 -148
- package/templates/default/components/form/inputs/select-form-input.tsx +159 -159
- package/templates/default/components/form/inputs/slug-form-input.tsx +131 -131
- package/templates/default/components/form/inputs/tags-form-input.tsx +255 -255
- package/templates/default/components/form/inputs/text-form-input.tsx +61 -61
- package/templates/default/components/form/inputs/textarea-form-input.tsx +61 -61
- package/templates/default/components/layout/default-nav-items.tsx +3 -3
- package/templates/default/components/layout/layout.tsx +84 -84
- package/templates/default/components/layout/navbar.tsx +258 -258
- package/templates/default/components/layout/sidebar-dropdown-item.tsx +83 -83
- package/templates/default/components/layout/sidebar-item.tsx +24 -24
- package/templates/default/components/layout/sidebar.tsx +229 -229
- package/templates/default/components/layout/theme-provider.tsx +8 -8
- package/templates/default/components/layout/theme-toggle.tsx +39 -39
- package/templates/default/components/locale/locale-switcher.tsx +98 -98
- package/templates/default/components/media/dropzone.tsx +154 -154
- package/templates/default/components/media/protected-document.tsx +44 -44
- package/templates/default/components/media/protected-image.tsx +143 -143
- package/templates/default/components/media/protected-video.tsx +76 -76
- package/templates/default/components/multi-select.tsx +1150 -1150
- package/templates/default/components/pages/admins-page.tsx +43 -43
- package/templates/default/components/pages/browse-page.tsx +106 -106
- package/templates/default/components/pages/categorized-section-page.tsx +31 -31
- package/templates/default/components/pages/dashboard-page-alt.tsx +45 -45
- package/templates/default/components/pages/item-edit-page.tsx +267 -267
- package/templates/default/components/pages/log-page.tsx +107 -107
- package/templates/default/components/pages/new-page.tsx +183 -183
- package/templates/default/components/pages/section-page.tsx +203 -203
- package/templates/default/components/pages/settings-page.tsx +232 -232
- package/templates/default/components/pagination/pagination-buttons.tsx +147 -147
- package/templates/default/components/pagination/pagination.tsx +36 -36
- package/templates/default/components/sections/category-delete-confirm-page.tsx +130 -130
- package/templates/default/components/sections/category-section-select-input.tsx +139 -139
- package/templates/default/components/sections/conditional-fields.tsx +49 -49
- package/templates/default/components/sections/section-icon.tsx +8 -8
- package/templates/default/components/sections/section-item-card.tsx +143 -143
- package/templates/default/components/sections/section-item-status-badge.tsx +17 -17
- package/templates/default/components/sections/select-input-buttons.tsx +125 -125
- package/templates/default/components/select-box.tsx +98 -98
- package/templates/default/components/ui/accordion.tsx +53 -53
- package/templates/default/components/ui/alert-dialog.tsx +113 -113
- package/templates/default/components/ui/alert.tsx +47 -47
- package/templates/default/components/ui/badge.tsx +38 -38
- package/templates/default/components/ui/card.tsx +43 -43
- package/templates/default/components/ui/command.tsx +137 -137
- package/templates/default/components/ui/custom-alert-dialog.tsx +113 -113
- package/templates/default/components/ui/custom-dialog.tsx +123 -123
- package/templates/default/components/ui/dialog.tsx +123 -123
- package/templates/default/components/ui/direction.tsx +22 -22
- package/templates/default/components/ui/dropdown-menu.tsx +182 -182
- package/templates/default/components/ui/input-group.tsx +54 -54
- package/templates/default/components/ui/input.tsx +22 -22
- package/templates/default/components/ui/label.tsx +19 -19
- package/templates/default/components/ui/popover.tsx +42 -42
- package/templates/default/components/ui/progress.tsx +31 -31
- package/templates/default/components/ui/scroll-area.tsx +42 -42
- package/templates/default/components/ui/select.tsx +165 -165
- package/templates/default/components/ui/separator.tsx +28 -28
- package/templates/default/components/ui/sheet.tsx +103 -103
- package/templates/default/components/ui/spinner.tsx +16 -16
- package/templates/default/components/ui/switch.tsx +29 -29
- package/templates/default/components/ui/table.tsx +83 -83
- package/templates/default/components/ui/tabs.tsx +55 -55
- package/templates/default/components/ui/toast.tsx +113 -113
- package/templates/default/components/ui/toaster.tsx +35 -35
- package/templates/default/components/ui/tooltip.tsx +30 -30
- package/templates/default/components/ui/use-toast.ts +187 -187
- package/templates/default/drizzle.config.ts +4 -4
- package/templates/default/dynamic-schemas/schema.ts +75 -225
- package/templates/default/env/env.ts +46 -46
- package/templates/default/envConfig.ts +4 -4
- package/templates/default/lib/postinstall.js +14 -14
- package/templates/default/lib/utils.ts +6 -6
- package/templates/default/next-env.d.ts +6 -6
- package/templates/default/next.config.ts +24 -24
- package/templates/default/package.json +1 -1
- package/templates/default/postcss.config.mjs +6 -6
- package/templates/default/proxy.ts +32 -32
- package/templates/default/tsconfig.json +48 -48
|
@@ -1,166 +1,166 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import { Suspense, useEffect, useRef, useState } from 'react'
|
|
4
|
-
import { useModal } from '@/components/feedback/modal-context'
|
|
5
|
-
import classNames from 'classnames'
|
|
6
|
-
import { X, Loader2 } from 'lucide-react'
|
|
7
|
-
|
|
8
|
-
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/custom-dialog'
|
|
9
|
-
|
|
10
|
-
function ModalLoadingFallback() {
|
|
11
|
-
return (
|
|
12
|
-
<div className='flex min-h-[200px] items-center justify-center p-8'>
|
|
13
|
-
<Loader2 className='h-8 w-8 animate-spin text-muted-foreground' />
|
|
14
|
-
</div>
|
|
15
|
-
)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function Modal() {
|
|
19
|
-
const { setModal, modal, modalResponse, setModalResponse } = useModal()
|
|
20
|
-
const [open, setOpen] = useState(false)
|
|
21
|
-
|
|
22
|
-
const handleClose = () => {
|
|
23
|
-
setOpen(false)
|
|
24
|
-
// Close after 100ms
|
|
25
|
-
setTimeout(() => {
|
|
26
|
-
setModal(null)
|
|
27
|
-
}, 200)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const cancelButtonRef = useRef(null)
|
|
31
|
-
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
if (!modal) {
|
|
34
|
-
setModalResponse(null)
|
|
35
|
-
} else {
|
|
36
|
-
setOpen(true)
|
|
37
|
-
}
|
|
38
|
-
}, [modal])
|
|
39
|
-
|
|
40
|
-
if (!modal) return null
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<Dialog open={open} onOpenChange={handleClose}>
|
|
44
|
-
<DialogContent
|
|
45
|
-
showCloseButton={false}
|
|
46
|
-
onOpenAutoFocus={(e) => e.preventDefault()}
|
|
47
|
-
onInteractOutside={(e) => e.preventDefault()}
|
|
48
|
-
onPointerDownOutside={(e) => e.preventDefault()}
|
|
49
|
-
className={classNames({
|
|
50
|
-
'bg-background w-full rounded-lg p-0 text-start': true,
|
|
51
|
-
'max-w-lg': modal?.size === 'sm' || modal?.size === undefined,
|
|
52
|
-
'max-w-2xl': modal?.size === 'md',
|
|
53
|
-
'max-w-4xl': modal?.size === 'lg',
|
|
54
|
-
'max-w-6xl': modal?.size === 'xl',
|
|
55
|
-
})}
|
|
56
|
-
>
|
|
57
|
-
<DialogHeader>
|
|
58
|
-
<DialogTitle
|
|
59
|
-
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}`}
|
|
60
|
-
>
|
|
61
|
-
<div>{modal?.title || ''}</div>
|
|
62
|
-
<X
|
|
63
|
-
className={`absolute end-5 size-6 cursor-pointer rounded bg-white text-gray-500 hover:opacity-90 md:block`}
|
|
64
|
-
onClick={handleClose}
|
|
65
|
-
ref={cancelButtonRef}
|
|
66
|
-
/>
|
|
67
|
-
</DialogTitle>
|
|
68
|
-
</DialogHeader>
|
|
69
|
-
<div className='max-h-[calc(90vh-120px)] min-h-0 flex-1 overflow-y-auto'>
|
|
70
|
-
<div className='flex flex-col gap-1'>
|
|
71
|
-
<div className='w-full overflow-hidden'>
|
|
72
|
-
<div className='flex w-full flex-col font-semibold'>
|
|
73
|
-
<div className='text-foreground w-full'>
|
|
74
|
-
<Suspense fallback={<ModalLoadingFallback />}>
|
|
75
|
-
{modal?.body}
|
|
76
|
-
</Suspense>
|
|
77
|
-
</div>
|
|
78
|
-
<div className='w-full'>
|
|
79
|
-
{modalResponse && <div className={`w-full p-3`}>{modalResponse.message}</div>}
|
|
80
|
-
</div>
|
|
81
|
-
</div>
|
|
82
|
-
</div>
|
|
83
|
-
</div>
|
|
84
|
-
</div>
|
|
85
|
-
</DialogContent>
|
|
86
|
-
</Dialog>
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
/*
|
|
90
|
-
return (
|
|
91
|
-
<Transition.Root show={modal !== null} as={Fragment}>
|
|
92
|
-
<Dialog as='div' className='relative z-50' initialFocus={cancelButtonRef} onClose={handleClose}>
|
|
93
|
-
<Transition.Child
|
|
94
|
-
as={Fragment}
|
|
95
|
-
enter='ease-out duration-300'
|
|
96
|
-
enterFrom='opacity-0'
|
|
97
|
-
enterTo='opacity-100'
|
|
98
|
-
leave='ease-in duration-200'
|
|
99
|
-
leaveFrom='opacity-100'
|
|
100
|
-
leaveTo='opacity-0'
|
|
101
|
-
>
|
|
102
|
-
<div className='fixed inset-0 bg-gray-500/50 backdrop-blur-md transition-opacity' />
|
|
103
|
-
</Transition.Child>
|
|
104
|
-
|
|
105
|
-
<div className='fixed inset-0 z-10 overflow-y-auto'>
|
|
106
|
-
<div className='flex min-h-full items-end justify-center p-4 text-start sm:items-start sm:p-0'>
|
|
107
|
-
<Transition.Child
|
|
108
|
-
as={Fragment}
|
|
109
|
-
enter='ease-out duration-300'
|
|
110
|
-
enterFrom='opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95'
|
|
111
|
-
enterTo='opacity-100 translate-y-0 sm:scale-100'
|
|
112
|
-
leave='ease-in duration-200'
|
|
113
|
-
leaveFrom='opacity-100 translate-y-0 sm:scale-100'
|
|
114
|
-
leaveTo='opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95'
|
|
115
|
-
>
|
|
116
|
-
<Dialog.Panel
|
|
117
|
-
className={classNames({
|
|
118
|
-
'bg-background relative w-full rounded-lg text-start shadow-xl transition-all sm:my-8':
|
|
119
|
-
true,
|
|
120
|
-
'max-w-lg': modal?.size === 'sm' || modal?.size === undefined,
|
|
121
|
-
'max-w-2xl': modal?.size === 'md',
|
|
122
|
-
'max-w-4xl': modal?.size === 'lg',
|
|
123
|
-
'max-w-6xl': modal?.size === 'xl',
|
|
124
|
-
})}
|
|
125
|
-
>
|
|
126
|
-
<div className='bg-background rounded-lg'>
|
|
127
|
-
{modal && (
|
|
128
|
-
<div className='flex flex-col gap-1'>
|
|
129
|
-
<div className='w-full overflow-hidden rounded'>
|
|
130
|
-
<div
|
|
131
|
-
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}`}
|
|
132
|
-
>
|
|
133
|
-
<Dialog.Title as='h3' className='pe-5'>
|
|
134
|
-
{modal.title}
|
|
135
|
-
</Dialog.Title>
|
|
136
|
-
<X
|
|
137
|
-
className={`absolute ${
|
|
138
|
-
modal.lang === 'ar' ? 'left-5' : 'right-5'
|
|
139
|
-
} hidden h-7 w-7 cursor-pointer rounded bg-white text-gray-500 hover:opacity-90 md:block`}
|
|
140
|
-
onClick={handleClose}
|
|
141
|
-
ref={cancelButtonRef}
|
|
142
|
-
/>
|
|
143
|
-
</div>
|
|
144
|
-
<div className='flex w-full flex-col font-semibold'>
|
|
145
|
-
<div className='text-foreground w-full'>{modal.body}</div>
|
|
146
|
-
<div className='w-full'>
|
|
147
|
-
{modalResponse && (
|
|
148
|
-
<div className={`w-full p-3`}>{modalResponse.message}</div>
|
|
149
|
-
)}
|
|
150
|
-
</div>
|
|
151
|
-
</div>
|
|
152
|
-
</div>
|
|
153
|
-
</div>
|
|
154
|
-
)}
|
|
155
|
-
</div>
|
|
156
|
-
</Dialog.Panel>
|
|
157
|
-
</Transition.Child>
|
|
158
|
-
</div>
|
|
159
|
-
</div>
|
|
160
|
-
</Dialog>
|
|
161
|
-
</Transition.Root>
|
|
162
|
-
)
|
|
163
|
-
*/
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
export default Modal
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { Suspense, useEffect, useRef, useState } from 'react'
|
|
4
|
+
import { useModal } from '@/components/feedback/modal-context'
|
|
5
|
+
import classNames from 'classnames'
|
|
6
|
+
import { X, Loader2 } from 'lucide-react'
|
|
7
|
+
|
|
8
|
+
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/custom-dialog'
|
|
9
|
+
|
|
10
|
+
function ModalLoadingFallback() {
|
|
11
|
+
return (
|
|
12
|
+
<div className='flex min-h-[200px] items-center justify-center p-8'>
|
|
13
|
+
<Loader2 className='h-8 w-8 animate-spin text-muted-foreground' />
|
|
14
|
+
</div>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function Modal() {
|
|
19
|
+
const { setModal, modal, modalResponse, setModalResponse } = useModal()
|
|
20
|
+
const [open, setOpen] = useState(false)
|
|
21
|
+
|
|
22
|
+
const handleClose = () => {
|
|
23
|
+
setOpen(false)
|
|
24
|
+
// Close after 100ms
|
|
25
|
+
setTimeout(() => {
|
|
26
|
+
setModal(null)
|
|
27
|
+
}, 200)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const cancelButtonRef = useRef(null)
|
|
31
|
+
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (!modal) {
|
|
34
|
+
setModalResponse(null)
|
|
35
|
+
} else {
|
|
36
|
+
setOpen(true)
|
|
37
|
+
}
|
|
38
|
+
}, [modal])
|
|
39
|
+
|
|
40
|
+
if (!modal) return null
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<Dialog open={open} onOpenChange={handleClose}>
|
|
44
|
+
<DialogContent
|
|
45
|
+
showCloseButton={false}
|
|
46
|
+
onOpenAutoFocus={(e) => e.preventDefault()}
|
|
47
|
+
onInteractOutside={(e) => e.preventDefault()}
|
|
48
|
+
onPointerDownOutside={(e) => e.preventDefault()}
|
|
49
|
+
className={classNames({
|
|
50
|
+
'bg-background w-full rounded-lg p-0 text-start': true,
|
|
51
|
+
'max-w-lg': modal?.size === 'sm' || modal?.size === undefined,
|
|
52
|
+
'max-w-2xl': modal?.size === 'md',
|
|
53
|
+
'max-w-4xl': modal?.size === 'lg',
|
|
54
|
+
'max-w-6xl': modal?.size === 'xl',
|
|
55
|
+
})}
|
|
56
|
+
>
|
|
57
|
+
<DialogHeader>
|
|
58
|
+
<DialogTitle
|
|
59
|
+
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}`}
|
|
60
|
+
>
|
|
61
|
+
<div>{modal?.title || ''}</div>
|
|
62
|
+
<X
|
|
63
|
+
className={`absolute end-5 size-6 cursor-pointer rounded bg-white text-gray-500 hover:opacity-90 md:block`}
|
|
64
|
+
onClick={handleClose}
|
|
65
|
+
ref={cancelButtonRef}
|
|
66
|
+
/>
|
|
67
|
+
</DialogTitle>
|
|
68
|
+
</DialogHeader>
|
|
69
|
+
<div className='max-h-[calc(90vh-120px)] min-h-0 flex-1 overflow-y-auto'>
|
|
70
|
+
<div className='flex flex-col gap-1'>
|
|
71
|
+
<div className='w-full overflow-hidden'>
|
|
72
|
+
<div className='flex w-full flex-col font-semibold'>
|
|
73
|
+
<div className='text-foreground w-full'>
|
|
74
|
+
<Suspense fallback={<ModalLoadingFallback />}>
|
|
75
|
+
{modal?.body}
|
|
76
|
+
</Suspense>
|
|
77
|
+
</div>
|
|
78
|
+
<div className='w-full'>
|
|
79
|
+
{modalResponse && <div className={`w-full p-3`}>{modalResponse.message}</div>}
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
</DialogContent>
|
|
86
|
+
</Dialog>
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
/*
|
|
90
|
+
return (
|
|
91
|
+
<Transition.Root show={modal !== null} as={Fragment}>
|
|
92
|
+
<Dialog as='div' className='relative z-50' initialFocus={cancelButtonRef} onClose={handleClose}>
|
|
93
|
+
<Transition.Child
|
|
94
|
+
as={Fragment}
|
|
95
|
+
enter='ease-out duration-300'
|
|
96
|
+
enterFrom='opacity-0'
|
|
97
|
+
enterTo='opacity-100'
|
|
98
|
+
leave='ease-in duration-200'
|
|
99
|
+
leaveFrom='opacity-100'
|
|
100
|
+
leaveTo='opacity-0'
|
|
101
|
+
>
|
|
102
|
+
<div className='fixed inset-0 bg-gray-500/50 backdrop-blur-md transition-opacity' />
|
|
103
|
+
</Transition.Child>
|
|
104
|
+
|
|
105
|
+
<div className='fixed inset-0 z-10 overflow-y-auto'>
|
|
106
|
+
<div className='flex min-h-full items-end justify-center p-4 text-start sm:items-start sm:p-0'>
|
|
107
|
+
<Transition.Child
|
|
108
|
+
as={Fragment}
|
|
109
|
+
enter='ease-out duration-300'
|
|
110
|
+
enterFrom='opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95'
|
|
111
|
+
enterTo='opacity-100 translate-y-0 sm:scale-100'
|
|
112
|
+
leave='ease-in duration-200'
|
|
113
|
+
leaveFrom='opacity-100 translate-y-0 sm:scale-100'
|
|
114
|
+
leaveTo='opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95'
|
|
115
|
+
>
|
|
116
|
+
<Dialog.Panel
|
|
117
|
+
className={classNames({
|
|
118
|
+
'bg-background relative w-full rounded-lg text-start shadow-xl transition-all sm:my-8':
|
|
119
|
+
true,
|
|
120
|
+
'max-w-lg': modal?.size === 'sm' || modal?.size === undefined,
|
|
121
|
+
'max-w-2xl': modal?.size === 'md',
|
|
122
|
+
'max-w-4xl': modal?.size === 'lg',
|
|
123
|
+
'max-w-6xl': modal?.size === 'xl',
|
|
124
|
+
})}
|
|
125
|
+
>
|
|
126
|
+
<div className='bg-background rounded-lg'>
|
|
127
|
+
{modal && (
|
|
128
|
+
<div className='flex flex-col gap-1'>
|
|
129
|
+
<div className='w-full overflow-hidden rounded'>
|
|
130
|
+
<div
|
|
131
|
+
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}`}
|
|
132
|
+
>
|
|
133
|
+
<Dialog.Title as='h3' className='pe-5'>
|
|
134
|
+
{modal.title}
|
|
135
|
+
</Dialog.Title>
|
|
136
|
+
<X
|
|
137
|
+
className={`absolute ${
|
|
138
|
+
modal.lang === 'ar' ? 'left-5' : 'right-5'
|
|
139
|
+
} hidden h-7 w-7 cursor-pointer rounded bg-white text-gray-500 hover:opacity-90 md:block`}
|
|
140
|
+
onClick={handleClose}
|
|
141
|
+
ref={cancelButtonRef}
|
|
142
|
+
/>
|
|
143
|
+
</div>
|
|
144
|
+
<div className='flex w-full flex-col font-semibold'>
|
|
145
|
+
<div className='text-foreground w-full'>{modal.body}</div>
|
|
146
|
+
<div className='w-full'>
|
|
147
|
+
{modalResponse && (
|
|
148
|
+
<div className={`w-full p-3`}>{modalResponse.message}</div>
|
|
149
|
+
)}
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
)}
|
|
155
|
+
</div>
|
|
156
|
+
</Dialog.Panel>
|
|
157
|
+
</Transition.Child>
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
160
|
+
</Dialog>
|
|
161
|
+
</Transition.Root>
|
|
162
|
+
)
|
|
163
|
+
*/
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export default Modal
|
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import { useTheme } from 'next-themes'
|
|
4
|
-
import { Progress } from '@/components/ui/progress'
|
|
5
|
-
|
|
6
|
-
export default function ProgressBar({ value, variant }: { value: number; variant?: 'determinate' | 'query' }) {
|
|
7
|
-
const { theme } = useTheme()
|
|
8
|
-
const isDark = theme === 'dark'
|
|
9
|
-
|
|
10
|
-
// Colors that match the original Material-UI version exactly
|
|
11
|
-
const bgColor = isDark ? '#424242' : '#eeeeee' // grey[800] : grey[200]
|
|
12
|
-
const progressColor = isDark ? '#308fe8' : '#1a90ff'
|
|
13
|
-
|
|
14
|
-
// Query variant shows indeterminate animation
|
|
15
|
-
const shouldShowIndeterminate = variant === 'query'
|
|
16
|
-
|
|
17
|
-
if (shouldShowIndeterminate) {
|
|
18
|
-
return (
|
|
19
|
-
<div
|
|
20
|
-
className='relative h-[10px] w-full overflow-hidden rounded-[5px]'
|
|
21
|
-
style={{ backgroundColor: bgColor }}
|
|
22
|
-
>
|
|
23
|
-
<div
|
|
24
|
-
className='h-full rounded-[5px]'
|
|
25
|
-
style={{
|
|
26
|
-
backgroundColor: progressColor,
|
|
27
|
-
width: '30%',
|
|
28
|
-
animation: 'progress-indeterminate 1.5s ease-in-out infinite',
|
|
29
|
-
}}
|
|
30
|
-
/>
|
|
31
|
-
</div>
|
|
32
|
-
)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return (
|
|
36
|
-
<div
|
|
37
|
-
className='progress-bar-custom relative w-full'
|
|
38
|
-
style={
|
|
39
|
-
{
|
|
40
|
-
'--progress-bg': bgColor,
|
|
41
|
-
'--progress-fg': progressColor,
|
|
42
|
-
} as React.CSSProperties
|
|
43
|
-
}
|
|
44
|
-
>
|
|
45
|
-
<Progress value={value} className='h-[10px] rounded-[5px] border-0 p-0' />
|
|
46
|
-
</div>
|
|
47
|
-
)
|
|
48
|
-
}
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useTheme } from 'next-themes'
|
|
4
|
+
import { Progress } from '@/components/ui/progress'
|
|
5
|
+
|
|
6
|
+
export default function ProgressBar({ value, variant }: { value: number; variant?: 'determinate' | 'query' }) {
|
|
7
|
+
const { theme } = useTheme()
|
|
8
|
+
const isDark = theme === 'dark'
|
|
9
|
+
|
|
10
|
+
// Colors that match the original Material-UI version exactly
|
|
11
|
+
const bgColor = isDark ? '#424242' : '#eeeeee' // grey[800] : grey[200]
|
|
12
|
+
const progressColor = isDark ? '#308fe8' : '#1a90ff'
|
|
13
|
+
|
|
14
|
+
// Query variant shows indeterminate animation
|
|
15
|
+
const shouldShowIndeterminate = variant === 'query'
|
|
16
|
+
|
|
17
|
+
if (shouldShowIndeterminate) {
|
|
18
|
+
return (
|
|
19
|
+
<div
|
|
20
|
+
className='relative h-[10px] w-full overflow-hidden rounded-[5px]'
|
|
21
|
+
style={{ backgroundColor: bgColor }}
|
|
22
|
+
>
|
|
23
|
+
<div
|
|
24
|
+
className='h-full rounded-[5px]'
|
|
25
|
+
style={{
|
|
26
|
+
backgroundColor: progressColor,
|
|
27
|
+
width: '30%',
|
|
28
|
+
animation: 'progress-indeterminate 1.5s ease-in-out infinite',
|
|
29
|
+
}}
|
|
30
|
+
/>
|
|
31
|
+
</div>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<div
|
|
37
|
+
className='progress-bar-custom relative w-full'
|
|
38
|
+
style={
|
|
39
|
+
{
|
|
40
|
+
'--progress-bg': bgColor,
|
|
41
|
+
'--progress-fg': progressColor,
|
|
42
|
+
} as React.CSSProperties
|
|
43
|
+
}
|
|
44
|
+
>
|
|
45
|
+
<Progress value={value} className='h-[10px] rounded-[5px] border-0 p-0' />
|
|
46
|
+
</div>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
|
2
|
-
export default function TooltipComponent({
|
|
3
|
-
children,
|
|
4
|
-
content,
|
|
5
|
-
delayDuration = 200,
|
|
6
|
-
}: {
|
|
7
|
-
children: React.ReactNode
|
|
8
|
-
content: React.ReactNode
|
|
9
|
-
delayDuration?: number
|
|
10
|
-
}) {
|
|
11
|
-
if (!content) return children
|
|
12
|
-
return (
|
|
13
|
-
<TooltipProvider delayDuration={delayDuration}>
|
|
14
|
-
<Tooltip>
|
|
15
|
-
<TooltipTrigger
|
|
16
|
-
onClick={(e) => {
|
|
17
|
-
e.preventDefault()
|
|
18
|
-
e.stopPropagation()
|
|
19
|
-
}}
|
|
20
|
-
>
|
|
21
|
-
{children}
|
|
22
|
-
</TooltipTrigger>
|
|
23
|
-
<TooltipContent>{content}</TooltipContent>
|
|
24
|
-
</Tooltip>
|
|
25
|
-
</TooltipProvider>
|
|
26
|
-
)
|
|
27
|
-
}
|
|
1
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
|
2
|
+
export default function TooltipComponent({
|
|
3
|
+
children,
|
|
4
|
+
content,
|
|
5
|
+
delayDuration = 200,
|
|
6
|
+
}: {
|
|
7
|
+
children: React.ReactNode
|
|
8
|
+
content: React.ReactNode
|
|
9
|
+
delayDuration?: number
|
|
10
|
+
}) {
|
|
11
|
+
if (!content) return children
|
|
12
|
+
return (
|
|
13
|
+
<TooltipProvider delayDuration={delayDuration}>
|
|
14
|
+
<Tooltip>
|
|
15
|
+
<TooltipTrigger
|
|
16
|
+
onClick={(e) => {
|
|
17
|
+
e.preventDefault()
|
|
18
|
+
e.stopPropagation()
|
|
19
|
+
}}
|
|
20
|
+
>
|
|
21
|
+
{children}
|
|
22
|
+
</TooltipTrigger>
|
|
23
|
+
<TooltipContent>{content}</TooltipContent>
|
|
24
|
+
</Tooltip>
|
|
25
|
+
</TooltipProvider>
|
|
26
|
+
)
|
|
27
|
+
}
|
|
@@ -1,70 +1,70 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import classNames from 'classnames'
|
|
3
|
-
import { Badge } from '@/components/ui/badge'
|
|
4
|
-
import { FieldError } from 'react-hook-form'
|
|
5
|
-
import { useI18n } from 'nextjs-cms/translations/client'
|
|
6
|
-
|
|
7
|
-
export default function FormInputElement({
|
|
8
|
-
label,
|
|
9
|
-
required = false,
|
|
10
|
-
readonly = false,
|
|
11
|
-
classes = '',
|
|
12
|
-
direction = 'row',
|
|
13
|
-
value,
|
|
14
|
-
children,
|
|
15
|
-
validationError,
|
|
16
|
-
}: {
|
|
17
|
-
label: string
|
|
18
|
-
required: boolean | string
|
|
19
|
-
readonly?: boolean
|
|
20
|
-
classes?: string
|
|
21
|
-
direction?: 'row' | 'col'
|
|
22
|
-
value?: any
|
|
23
|
-
children: React.ReactNode
|
|
24
|
-
validationError: FieldError | undefined
|
|
25
|
-
}) {
|
|
26
|
-
const t = useI18n()
|
|
27
|
-
return (
|
|
28
|
-
<div
|
|
29
|
-
className={classNames({
|
|
30
|
-
'items-center py-2': true,
|
|
31
|
-
'flex flex-col': direction === 'col',
|
|
32
|
-
'items-center px-3 md-sidebar:grid md-sidebar:grid-cols-10': direction === 'row',
|
|
33
|
-
classes: classes,
|
|
34
|
-
})}
|
|
35
|
-
>
|
|
36
|
-
<label
|
|
37
|
-
className={classNames({
|
|
38
|
-
'block pe-3 font-bold text-foreground': true,
|
|
39
|
-
'w-full text-start': direction === 'col',
|
|
40
|
-
'col-span-10 pb-1 md-sidebar:col-span-2 md-sidebar:pb-0 md-sidebar:text-end': direction === 'row',
|
|
41
|
-
})}
|
|
42
|
-
>
|
|
43
|
-
{label} {['true', 1, true].includes(required) ? '*' : null}
|
|
44
|
-
{readonly ? (
|
|
45
|
-
<>
|
|
46
|
-
{' '}
|
|
47
|
-
<Badge variant={'primary'}>{t('readonly')}</Badge>
|
|
48
|
-
</>
|
|
49
|
-
) : null}
|
|
50
|
-
</label>
|
|
51
|
-
<div
|
|
52
|
-
className={classNames({
|
|
53
|
-
'col-span-8': direction === 'row',
|
|
54
|
-
'w-full': direction === 'col',
|
|
55
|
-
})}
|
|
56
|
-
>
|
|
57
|
-
{readonly ? (
|
|
58
|
-
<div className='w-full rounded bg-input p-3 text-foreground shadow-xs outline-0'>{value}</div>
|
|
59
|
-
) : (
|
|
60
|
-
<>
|
|
61
|
-
{children}
|
|
62
|
-
{validationError ? (
|
|
63
|
-
<div className='mt-1 text-sm text-red-500'>{validationError.message}</div>
|
|
64
|
-
) : null}
|
|
65
|
-
</>
|
|
66
|
-
)}
|
|
67
|
-
</div>
|
|
68
|
-
</div>
|
|
69
|
-
)
|
|
70
|
-
}
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import classNames from 'classnames'
|
|
3
|
+
import { Badge } from '@/components/ui/badge'
|
|
4
|
+
import { FieldError } from 'react-hook-form'
|
|
5
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
6
|
+
|
|
7
|
+
export default function FormInputElement({
|
|
8
|
+
label,
|
|
9
|
+
required = false,
|
|
10
|
+
readonly = false,
|
|
11
|
+
classes = '',
|
|
12
|
+
direction = 'row',
|
|
13
|
+
value,
|
|
14
|
+
children,
|
|
15
|
+
validationError,
|
|
16
|
+
}: {
|
|
17
|
+
label: string
|
|
18
|
+
required: boolean | string
|
|
19
|
+
readonly?: boolean
|
|
20
|
+
classes?: string
|
|
21
|
+
direction?: 'row' | 'col'
|
|
22
|
+
value?: any
|
|
23
|
+
children: React.ReactNode
|
|
24
|
+
validationError: FieldError | undefined
|
|
25
|
+
}) {
|
|
26
|
+
const t = useI18n()
|
|
27
|
+
return (
|
|
28
|
+
<div
|
|
29
|
+
className={classNames({
|
|
30
|
+
'items-center py-2': true,
|
|
31
|
+
'flex flex-col': direction === 'col',
|
|
32
|
+
'items-center px-3 md-sidebar:grid md-sidebar:grid-cols-10': direction === 'row',
|
|
33
|
+
classes: classes,
|
|
34
|
+
})}
|
|
35
|
+
>
|
|
36
|
+
<label
|
|
37
|
+
className={classNames({
|
|
38
|
+
'block pe-3 font-bold text-foreground': true,
|
|
39
|
+
'w-full text-start': direction === 'col',
|
|
40
|
+
'col-span-10 pb-1 md-sidebar:col-span-2 md-sidebar:pb-0 md-sidebar:text-end': direction === 'row',
|
|
41
|
+
})}
|
|
42
|
+
>
|
|
43
|
+
{label} {['true', 1, true].includes(required) ? '*' : null}
|
|
44
|
+
{readonly ? (
|
|
45
|
+
<>
|
|
46
|
+
{' '}
|
|
47
|
+
<Badge variant={'primary'}>{t('readonly')}</Badge>
|
|
48
|
+
</>
|
|
49
|
+
) : null}
|
|
50
|
+
</label>
|
|
51
|
+
<div
|
|
52
|
+
className={classNames({
|
|
53
|
+
'col-span-8': direction === 'row',
|
|
54
|
+
'w-full': direction === 'col',
|
|
55
|
+
})}
|
|
56
|
+
>
|
|
57
|
+
{readonly ? (
|
|
58
|
+
<div className='w-full rounded bg-input p-3 text-foreground shadow-xs outline-0'>{value}</div>
|
|
59
|
+
) : (
|
|
60
|
+
<>
|
|
61
|
+
{children}
|
|
62
|
+
{validationError ? (
|
|
63
|
+
<div className='mt-1 text-sm text-red-500'>{validationError.message}</div>
|
|
64
|
+
) : null}
|
|
65
|
+
</>
|
|
66
|
+
)}
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
)
|
|
70
|
+
}
|