create-nextjs-cms 0.9.30 → 0.9.32
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 +1 -1
- 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)/(plugins)/[...slug]/error.tsx +64 -0
- package/templates/default/app/(rootLayout)/(plugins)/[...slug]/page.tsx +59 -47
- package/templates/default/app/(rootLayout)/(plugins)/[...slug]/plugin-server-registry.ts +14 -16
- 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 +68 -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 +5 -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 +11 -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 +225 -75
- 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,17 +1,17 @@
|
|
|
1
|
-
let configLastUpdated: number = 0
|
|
2
|
-
|
|
3
|
-
// Use new Function to bypass next.js dynamic import restriction
|
|
4
|
-
const loadHotReloadFile = async () => {
|
|
5
|
-
try {
|
|
6
|
-
// This approach completely bypasses next.js dynamic import restriction
|
|
7
|
-
const importFn = new Function('path', 'return import(path)')
|
|
8
|
-
const sectionInfo = await importFn('./_section-hot-reload.js')
|
|
9
|
-
configLastUpdated = sectionInfo?.configLastUpdated ?? 0
|
|
10
|
-
} catch {
|
|
11
|
-
configLastUpdated = 0
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
loadHotReloadFile()
|
|
16
|
-
|
|
17
|
-
export { configLastUpdated }
|
|
1
|
+
let configLastUpdated: number = 0
|
|
2
|
+
|
|
3
|
+
// Use new Function to bypass next.js dynamic import restriction
|
|
4
|
+
const loadHotReloadFile = async () => {
|
|
5
|
+
try {
|
|
6
|
+
// This approach completely bypasses next.js dynamic import restriction
|
|
7
|
+
const importFn = new Function('path', 'return import(path)')
|
|
8
|
+
const sectionInfo = await importFn('./_section-hot-reload.js')
|
|
9
|
+
configLastUpdated = sectionInfo?.configLastUpdated ?? 0
|
|
10
|
+
} catch {
|
|
11
|
+
configLastUpdated = 0
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
loadHotReloadFile()
|
|
16
|
+
|
|
17
|
+
export { configLastUpdated }
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import FormInputElement from '@/components/form/form-input-element'
|
|
3
|
-
import { CheckboxFieldClientConfig } from 'nextjs-cms/core/fields'
|
|
4
|
-
import { useController, useFormContext } from 'react-hook-form'
|
|
5
|
-
import { Switch } from '@/components/ui/switch'
|
|
6
|
-
|
|
7
|
-
function toChecked(value: unknown): boolean {
|
|
8
|
-
if (value === true) return true
|
|
9
|
-
if (value === 1) return true
|
|
10
|
-
if (value === '1') return true
|
|
11
|
-
if (value === 'true') return true
|
|
12
|
-
if (value === 'on') return true
|
|
13
|
-
return false
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export default function CheckboxFormInput({ input }: { input: CheckboxFieldClientConfig }) {
|
|
17
|
-
const { control } = useFormContext()
|
|
18
|
-
const initialValue =
|
|
19
|
-
input.value !== undefined && input.value !== null ? toChecked(input.value) : toChecked(input.defaultValue)
|
|
20
|
-
|
|
21
|
-
const {
|
|
22
|
-
field,
|
|
23
|
-
fieldState: { error },
|
|
24
|
-
} = useController({
|
|
25
|
-
name: input.name,
|
|
26
|
-
control,
|
|
27
|
-
defaultValue: initialValue,
|
|
28
|
-
})
|
|
29
|
-
return (
|
|
30
|
-
<FormInputElement
|
|
31
|
-
validationError={error}
|
|
32
|
-
value={initialValue}
|
|
33
|
-
readonly={input.readonly}
|
|
34
|
-
label={input.label}
|
|
35
|
-
required={input.required}
|
|
36
|
-
>
|
|
37
|
-
<Switch
|
|
38
|
-
ref={field.ref}
|
|
39
|
-
onCheckedChange={field.onChange}
|
|
40
|
-
checked={toChecked(field.value)}
|
|
41
|
-
name={field.name}
|
|
42
|
-
disabled={input.readonly}
|
|
43
|
-
/>
|
|
44
|
-
</FormInputElement>
|
|
45
|
-
)
|
|
46
|
-
}
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import FormInputElement from '@/components/form/form-input-element'
|
|
3
|
+
import { CheckboxFieldClientConfig } from 'nextjs-cms/core/fields'
|
|
4
|
+
import { useController, useFormContext } from 'react-hook-form'
|
|
5
|
+
import { Switch } from '@/components/ui/switch'
|
|
6
|
+
|
|
7
|
+
function toChecked(value: unknown): boolean {
|
|
8
|
+
if (value === true) return true
|
|
9
|
+
if (value === 1) return true
|
|
10
|
+
if (value === '1') return true
|
|
11
|
+
if (value === 'true') return true
|
|
12
|
+
if (value === 'on') return true
|
|
13
|
+
return false
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default function CheckboxFormInput({ input }: { input: CheckboxFieldClientConfig }) {
|
|
17
|
+
const { control } = useFormContext()
|
|
18
|
+
const initialValue =
|
|
19
|
+
input.value !== undefined && input.value !== null ? toChecked(input.value) : toChecked(input.defaultValue)
|
|
20
|
+
|
|
21
|
+
const {
|
|
22
|
+
field,
|
|
23
|
+
fieldState: { error },
|
|
24
|
+
} = useController({
|
|
25
|
+
name: input.name,
|
|
26
|
+
control,
|
|
27
|
+
defaultValue: initialValue,
|
|
28
|
+
})
|
|
29
|
+
return (
|
|
30
|
+
<FormInputElement
|
|
31
|
+
validationError={error}
|
|
32
|
+
value={initialValue}
|
|
33
|
+
readonly={input.readonly}
|
|
34
|
+
label={input.label}
|
|
35
|
+
required={input.required}
|
|
36
|
+
>
|
|
37
|
+
<Switch
|
|
38
|
+
ref={field.ref}
|
|
39
|
+
onCheckedChange={field.onChange}
|
|
40
|
+
checked={toChecked(field.value)}
|
|
41
|
+
name={field.name}
|
|
42
|
+
disabled={input.readonly}
|
|
43
|
+
/>
|
|
44
|
+
</FormInputElement>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import FormInputElement from '@/components/form/form-input-element'
|
|
3
|
-
import { ColorFieldClientConfig } from 'nextjs-cms/core/fields'
|
|
4
|
-
import { useController, useFormContext } from 'react-hook-form'
|
|
5
|
-
|
|
6
|
-
export default function ColorFormInput({ input }: { input: ColorFieldClientConfig }) {
|
|
7
|
-
const { control } = useFormContext()
|
|
8
|
-
const {
|
|
9
|
-
field,
|
|
10
|
-
fieldState: { invalid, isTouched, isDirty, error },
|
|
11
|
-
} = useController({
|
|
12
|
-
name: input.name,
|
|
13
|
-
control,
|
|
14
|
-
defaultValue: input.value ?? '#000000',
|
|
15
|
-
disabled: input.readonly,
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
const colorSpan = (
|
|
19
|
-
<>
|
|
20
|
-
<span style={{ padding: '2px 40px', backgroundColor: input.value }}></span>
|
|
21
|
-
</>
|
|
22
|
-
)
|
|
23
|
-
return (
|
|
24
|
-
<FormInputElement
|
|
25
|
-
validationError={error}
|
|
26
|
-
value={colorSpan}
|
|
27
|
-
readonly={input.readonly}
|
|
28
|
-
label={input.label}
|
|
29
|
-
required={input.required}
|
|
30
|
-
>
|
|
31
|
-
<input
|
|
32
|
-
type='color'
|
|
33
|
-
readOnly={input.readonly}
|
|
34
|
-
disabled={field.disabled}
|
|
35
|
-
name={field.name}
|
|
36
|
-
onChange={field.onChange}
|
|
37
|
-
onBlur={field.onBlur}
|
|
38
|
-
value={field.value}
|
|
39
|
-
ref={field.ref}
|
|
40
|
-
className='h-10 w-full rounded bg-input p-1 text-foreground shadow-xs outline-0 ring-2 ring-blue-300 focus:ring-blue-500'
|
|
41
|
-
/>
|
|
42
|
-
</FormInputElement>
|
|
43
|
-
)
|
|
44
|
-
}
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import FormInputElement from '@/components/form/form-input-element'
|
|
3
|
+
import { ColorFieldClientConfig } from 'nextjs-cms/core/fields'
|
|
4
|
+
import { useController, useFormContext } from 'react-hook-form'
|
|
5
|
+
|
|
6
|
+
export default function ColorFormInput({ input }: { input: ColorFieldClientConfig }) {
|
|
7
|
+
const { control } = useFormContext()
|
|
8
|
+
const {
|
|
9
|
+
field,
|
|
10
|
+
fieldState: { invalid, isTouched, isDirty, error },
|
|
11
|
+
} = useController({
|
|
12
|
+
name: input.name,
|
|
13
|
+
control,
|
|
14
|
+
defaultValue: input.value ?? '#000000',
|
|
15
|
+
disabled: input.readonly,
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
const colorSpan = (
|
|
19
|
+
<>
|
|
20
|
+
<span style={{ padding: '2px 40px', backgroundColor: input.value }}></span>
|
|
21
|
+
</>
|
|
22
|
+
)
|
|
23
|
+
return (
|
|
24
|
+
<FormInputElement
|
|
25
|
+
validationError={error}
|
|
26
|
+
value={colorSpan}
|
|
27
|
+
readonly={input.readonly}
|
|
28
|
+
label={input.label}
|
|
29
|
+
required={input.required}
|
|
30
|
+
>
|
|
31
|
+
<input
|
|
32
|
+
type='color'
|
|
33
|
+
readOnly={input.readonly}
|
|
34
|
+
disabled={field.disabled}
|
|
35
|
+
name={field.name}
|
|
36
|
+
onChange={field.onChange}
|
|
37
|
+
onBlur={field.onBlur}
|
|
38
|
+
value={field.value}
|
|
39
|
+
ref={field.ref}
|
|
40
|
+
className='h-10 w-full rounded bg-input p-1 text-foreground shadow-xs outline-0 ring-2 ring-blue-300 focus:ring-blue-500'
|
|
41
|
+
/>
|
|
42
|
+
</FormInputElement>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import dayjs from 'dayjs'
|
|
3
|
-
import FormInputElement from '@/components/form/form-input-element'
|
|
4
|
-
import { Button } from '@/components/ui/button'
|
|
5
|
-
import { Calendar } from '@/components/ui/calendar'
|
|
6
|
-
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
|
|
7
|
-
import { CalendarIcon, ChevronDownIcon } from '@radix-ui/react-icons'
|
|
8
|
-
import { useI18n } from 'nextjs-cms/translations/client'
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import dayjs from 'dayjs'
|
|
3
|
+
import FormInputElement from '@/components/form/form-input-element'
|
|
4
|
+
import { Button } from '@/components/ui/button'
|
|
5
|
+
import { Calendar } from '@/components/ui/calendar'
|
|
6
|
+
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
|
|
7
|
+
import { CalendarIcon, ChevronDownIcon } from '@radix-ui/react-icons'
|
|
8
|
+
import { useI18n } from 'nextjs-cms/translations/client'
|
|
9
9
|
import type { DateFieldClientConfig } from 'nextjs-cms/core/fields'
|
|
10
10
|
import { useController, useFormContext } from 'react-hook-form'
|
|
11
11
|
import { Input } from '@/components/ui/input'
|
|
12
12
|
import { Clock2Icon } from 'lucide-react'
|
|
13
|
-
|
|
14
|
-
const seasonEmoji: Record<string, string> = {
|
|
15
|
-
winter: '⛄️',
|
|
16
|
-
spring: '🌸',
|
|
17
|
-
summer: '🌻',
|
|
18
|
-
autumn: '🍂',
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const getSeason = (month: Date): string => {
|
|
22
|
-
const monthNumber = month.getMonth()
|
|
23
|
-
if (monthNumber >= 0 && monthNumber < 3) return 'winter'
|
|
24
|
-
if (monthNumber >= 3 && monthNumber < 6) return 'spring'
|
|
25
|
-
if (monthNumber >= 6 && monthNumber < 9) return 'summer'
|
|
26
|
-
else return 'autumn'
|
|
27
|
-
}
|
|
28
|
-
|
|
13
|
+
|
|
14
|
+
const seasonEmoji: Record<string, string> = {
|
|
15
|
+
winter: '⛄️',
|
|
16
|
+
spring: '🌸',
|
|
17
|
+
summer: '🌻',
|
|
18
|
+
autumn: '🍂',
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const getSeason = (month: Date): string => {
|
|
22
|
+
const monthNumber = month.getMonth()
|
|
23
|
+
if (monthNumber >= 0 && monthNumber < 3) return 'winter'
|
|
24
|
+
if (monthNumber >= 3 && monthNumber < 6) return 'spring'
|
|
25
|
+
if (monthNumber >= 6 && monthNumber < 9) return 'summer'
|
|
26
|
+
else return 'autumn'
|
|
27
|
+
}
|
|
28
|
+
|
|
29
29
|
const formatCaption = (month: Date) => {
|
|
30
30
|
const season = getSeason(month)
|
|
31
31
|
return seasonEmoji[season] + ' ' + dayjs(month).format('MMMM')
|
|
@@ -89,50 +89,50 @@ export default function DateFormInput({ input }: { input: DateFieldClientConfig
|
|
|
89
89
|
field,
|
|
90
90
|
fieldState: { error },
|
|
91
91
|
} = useController({
|
|
92
|
-
name: input.name,
|
|
93
|
-
control,
|
|
94
|
-
defaultValue: input.value
|
|
95
|
-
? dayjs(input.value).isValid()
|
|
96
|
-
? dayjs(input.value).toDate()
|
|
97
|
-
: undefined
|
|
98
|
-
: undefined,
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
const [date, setDate] = React.useState<Date | undefined>(
|
|
102
|
-
input.value ? (dayjs(input.value).isValid() ? dayjs(input.value).toDate() : undefined) : undefined,
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
return (
|
|
106
|
-
<FormInputElement
|
|
107
|
-
validationError={error}
|
|
108
|
-
value={input.value}
|
|
109
|
-
readonly={input.readonly}
|
|
110
|
-
label={input.label}
|
|
111
|
-
required={input.required}
|
|
112
|
-
>
|
|
113
|
-
<input
|
|
114
|
-
type='hidden'
|
|
115
|
-
disabled={field.disabled}
|
|
92
|
+
name: input.name,
|
|
93
|
+
control,
|
|
94
|
+
defaultValue: input.value
|
|
95
|
+
? dayjs(input.value).isValid()
|
|
96
|
+
? dayjs(input.value).toDate()
|
|
97
|
+
: undefined
|
|
98
|
+
: undefined,
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
const [date, setDate] = React.useState<Date | undefined>(
|
|
102
|
+
input.value ? (dayjs(input.value).isValid() ? dayjs(input.value).toDate() : undefined) : undefined,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<FormInputElement
|
|
107
|
+
validationError={error}
|
|
108
|
+
value={input.value}
|
|
109
|
+
readonly={input.readonly}
|
|
110
|
+
label={input.label}
|
|
111
|
+
required={input.required}
|
|
112
|
+
>
|
|
113
|
+
<input
|
|
114
|
+
type='hidden'
|
|
115
|
+
disabled={field.disabled}
|
|
116
116
|
name={field.name}
|
|
117
117
|
onBlur={field.onBlur}
|
|
118
118
|
value={formatHiddenValue(date, input.format)}
|
|
119
119
|
ref={field.ref}
|
|
120
120
|
className='rounded border p-2'
|
|
121
121
|
/>
|
|
122
|
-
|
|
123
|
-
<div className='flex flex-row items-start gap-2'>
|
|
124
|
-
<div>
|
|
125
|
-
<Popover open={open} onOpenChange={setOpen}>
|
|
126
|
-
<PopoverTrigger asChild>
|
|
127
|
-
<Button variant='outline' id='date' className='justify-between font-normal'>
|
|
128
|
-
<div className='flex items-center gap-2'>
|
|
129
|
-
<CalendarIcon />
|
|
130
|
-
{date ? dayjs(date).format('MMMM D, YYYY') : <span>Pick a date</span>}
|
|
131
|
-
</div>
|
|
132
|
-
<ChevronDownIcon />
|
|
133
|
-
</Button>
|
|
134
|
-
</PopoverTrigger>
|
|
135
|
-
<PopoverContent className='w-auto overflow-hidden p-0' align='start'>
|
|
122
|
+
|
|
123
|
+
<div className='flex flex-row items-start gap-2'>
|
|
124
|
+
<div>
|
|
125
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
126
|
+
<PopoverTrigger asChild>
|
|
127
|
+
<Button variant='outline' id='date' className='justify-between font-normal'>
|
|
128
|
+
<div className='flex items-center gap-2'>
|
|
129
|
+
<CalendarIcon />
|
|
130
|
+
{date ? dayjs(date).format('MMMM D, YYYY') : <span>Pick a date</span>}
|
|
131
|
+
</div>
|
|
132
|
+
<ChevronDownIcon />
|
|
133
|
+
</Button>
|
|
134
|
+
</PopoverTrigger>
|
|
135
|
+
<PopoverContent className='w-auto overflow-hidden p-0' align='start'>
|
|
136
136
|
<Calendar
|
|
137
137
|
startMonth={toCalendarDay(minDate)}
|
|
138
138
|
endMonth={toCalendarDay(maxDate) ?? new Date(2099, 11)}
|
|
@@ -164,17 +164,17 @@ export default function DateFormInput({ input }: { input: DateFieldClientConfig
|
|
|
164
164
|
}}
|
|
165
165
|
autoFocus
|
|
166
166
|
className='rounded-lg border'
|
|
167
|
-
formatters={{ formatCaption }}
|
|
168
|
-
/>
|
|
169
|
-
</PopoverContent>
|
|
170
|
-
</Popover>
|
|
171
|
-
</div>
|
|
172
|
-
|
|
173
|
-
{input.format !== 'date' ? (
|
|
174
|
-
<div className='relative flex items-center gap-2'>
|
|
175
|
-
<Clock2Icon className='text-muted-foreground pointer-events-none absolute left-2.5 size-4 select-none' />
|
|
176
|
-
<Input
|
|
177
|
-
type='time'
|
|
167
|
+
formatters={{ formatCaption }}
|
|
168
|
+
/>
|
|
169
|
+
</PopoverContent>
|
|
170
|
+
</Popover>
|
|
171
|
+
</div>
|
|
172
|
+
|
|
173
|
+
{input.format !== 'date' ? (
|
|
174
|
+
<div className='relative flex items-center gap-2'>
|
|
175
|
+
<Clock2Icon className='text-muted-foreground pointer-events-none absolute left-2.5 size-4 select-none' />
|
|
176
|
+
<Input
|
|
177
|
+
type='time'
|
|
178
178
|
step='1'
|
|
179
179
|
defaultValue={'--:--:--'}
|
|
180
180
|
value={date ? dayjs(date).format('HH:mm:ss') : '--:--:--'}
|
|
@@ -192,23 +192,23 @@ export default function DateFormInput({ input }: { input: DateFieldClientConfig
|
|
|
192
192
|
}
|
|
193
193
|
}}
|
|
194
194
|
className='appearance-none pl-8 [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none'
|
|
195
|
-
/>
|
|
196
|
-
</div>
|
|
197
|
-
) : null}
|
|
198
|
-
|
|
199
|
-
<Button
|
|
200
|
-
className='px-1.5'
|
|
201
|
-
onClick={() => {
|
|
202
|
-
setDate(undefined)
|
|
203
|
-
field.onChange(undefined)
|
|
204
|
-
}}
|
|
205
|
-
variant='default'
|
|
206
|
-
type='button'
|
|
207
|
-
size='default'
|
|
208
|
-
>
|
|
209
|
-
{t('unset')}
|
|
210
|
-
</Button>
|
|
211
|
-
</div>
|
|
212
|
-
</FormInputElement>
|
|
213
|
-
)
|
|
214
|
-
}
|
|
195
|
+
/>
|
|
196
|
+
</div>
|
|
197
|
+
) : null}
|
|
198
|
+
|
|
199
|
+
<Button
|
|
200
|
+
className='px-1.5'
|
|
201
|
+
onClick={() => {
|
|
202
|
+
setDate(undefined)
|
|
203
|
+
field.onChange(undefined)
|
|
204
|
+
}}
|
|
205
|
+
variant='default'
|
|
206
|
+
type='button'
|
|
207
|
+
size='default'
|
|
208
|
+
>
|
|
209
|
+
{t('unset')}
|
|
210
|
+
</Button>
|
|
211
|
+
</div>
|
|
212
|
+
</FormInputElement>
|
|
213
|
+
)
|
|
214
|
+
}
|