create-nextjs-cms 0.8.10 → 0.9.1

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 (36) hide show
  1. package/package.json +2 -2
  2. package/templates/default/app/(auth)/auth/login/LoginPage.tsx +9 -9
  3. package/templates/default/app/(auth)/auth-language-provider.tsx +34 -0
  4. package/templates/default/app/(auth)/layout.tsx +10 -10
  5. package/templates/default/app/(rootLayout)/edit/[section]/[itemId]/page.tsx +4 -1
  6. package/templates/default/app/(rootLayout)/layout.tsx +5 -5
  7. package/templates/default/app/(rootLayout)/section/[section]/page.tsx +4 -1
  8. package/templates/default/app/api/auth/route.ts +2 -2
  9. package/templates/default/app/api/submit/section/item/[slug]/route.ts +32 -3
  10. package/templates/default/app/api/submit/section/simple/route.ts +32 -3
  11. package/templates/default/app/globals.css +9 -0
  12. package/templates/default/cms.config.ts +4 -4
  13. package/templates/default/components/ItemEditPage.tsx +82 -2
  14. package/templates/default/components/LocaleSwitcher.tsx +89 -0
  15. package/templates/default/components/Navbar.tsx +5 -5
  16. package/templates/default/components/NewPage.tsx +1 -0
  17. package/templates/default/components/SectionPage.tsx +81 -1
  18. package/templates/default/components/form/ContentLocaleContext.tsx +11 -0
  19. package/templates/default/components/form/Form.tsx +48 -5
  20. package/templates/default/components/form/FormInputs.tsx +16 -7
  21. package/templates/default/components/form/helpers/_section-hot-reload.js +1 -1
  22. package/templates/default/components/form/inputs/NumberFormInput.tsx +2 -1
  23. package/templates/default/components/form/inputs/PhotoFormInput.tsx +168 -112
  24. package/templates/default/components/form/inputs/RichTextFormInput.tsx +3 -0
  25. package/templates/default/components/form/inputs/SelectFormInput.tsx +1 -1
  26. package/templates/default/components/form/inputs/TagsFormInput.tsx +6 -2
  27. package/templates/default/components/form/inputs/TextFormInput.tsx +3 -0
  28. package/templates/default/components/form/inputs/TextareaFormInput.tsx +3 -0
  29. package/templates/default/components/{locale-dropdown.tsx → language-dropdown.tsx} +74 -74
  30. package/templates/default/components/{locale-picker.tsx → language-picker.tsx} +85 -85
  31. package/templates/default/components/login-language-dropdown.tsx +46 -0
  32. package/templates/default/components/ui/alert.tsx +2 -1
  33. package/templates/default/dynamic-schemas/schema.ts +475 -448
  34. package/templates/default/package.json +1 -1
  35. package/templates/default/app/(auth)/auth-locale-provider.tsx +0 -34
  36. package/templates/default/components/login-locale-dropdown.tsx +0 -46
@@ -1,85 +1,85 @@
1
- 'use client'
2
-
3
- import { Languages } from 'lucide-react'
4
- import {
5
- DropdownMenu,
6
- DropdownMenuContent,
7
- DropdownMenuItem,
8
- DropdownMenuTrigger,
9
- } from '@/components/ui/dropdown-menu'
10
- import { Spinner } from '@/components/ui/spinner'
11
- import { RTL_LOCALES } from 'nextjs-cms/translations'
12
-
13
- const LOCALE_DISPLAY_NAMES: Record<string, string> = {
14
- en: 'English',
15
- ar: 'العربية',
16
- }
17
-
18
- function displayName(code: string): string {
19
- return LOCALE_DISPLAY_NAMES[code] ?? code
20
- }
21
-
22
- export interface LocalePickerProps {
23
- supportedLanguages: readonly string[]
24
- currentLocale: string
25
- onLocaleChange: (locale: string) => void
26
- disabled?: boolean
27
- loading?: boolean
28
- ariaLabel: string
29
- }
30
-
31
- /**
32
- * Shared locale dropdown UI. Use in Navbar (app) or Login page.
33
- * Parent controls data source and onSelect behavior (tRPC + refresh vs cookie + refresh).
34
- */
35
- export default function LocalePicker({
36
- supportedLanguages,
37
- currentLocale,
38
- onLocaleChange,
39
- disabled = false,
40
- loading = false,
41
- ariaLabel,
42
- }: LocalePickerProps) {
43
- if (supportedLanguages.length < 2) return null
44
-
45
- const isRTL = RTL_LOCALES.has(currentLocale)
46
-
47
- return (
48
- <DropdownMenu>
49
- <DropdownMenuTrigger
50
- asChild
51
- className='text-foreground hover:text-foreground/90 relative rounded-full focus:outline-hidden cursor-pointer'
52
- >
53
- <button
54
- type='button'
55
- className='flex h-10 items-center justify-center'
56
- aria-label={ariaLabel}
57
- disabled={disabled}
58
- >
59
- {loading ? (
60
- <Spinner className='size-5' />
61
- ) : (
62
- <Languages className='h-5 w-5' aria-hidden='true' />
63
- )}
64
- </button>
65
- </DropdownMenuTrigger>
66
- <DropdownMenuContent
67
- align={'end'}
68
- sideOffset={12}
69
- className='ring-1 ring-sky-400/80 dark:ring-amber-900'
70
- >
71
- {supportedLanguages.map((code) => (
72
- <DropdownMenuItem
73
- key={code}
74
- onClick={() => onLocaleChange(code)}
75
- disabled={disabled}
76
- className='cursor-pointer'
77
- >
78
- {displayName(code)}
79
- {code === currentLocale ? ' ✓' : ''}
80
- </DropdownMenuItem>
81
- ))}
82
- </DropdownMenuContent>
83
- </DropdownMenu>
84
- )
85
- }
1
+ 'use client'
2
+
3
+ import { Languages } from 'lucide-react'
4
+ import {
5
+ DropdownMenu,
6
+ DropdownMenuContent,
7
+ DropdownMenuItem,
8
+ DropdownMenuTrigger,
9
+ } from '@/components/ui/dropdown-menu'
10
+ import { Spinner } from '@/components/ui/spinner'
11
+ import { RTL_LANGUAGES } from 'nextjs-cms/translations'
12
+
13
+ const LANGUAGE_DISPLAY_NAMES: Record<string, string> = {
14
+ en: 'English',
15
+ ar: 'العربية',
16
+ }
17
+
18
+ function displayName(code: string): string {
19
+ return LANGUAGE_DISPLAY_NAMES[code] ?? code
20
+ }
21
+
22
+ export interface LanguagePickerProps {
23
+ supportedLanguages: readonly string[]
24
+ currentLanguage: string
25
+ onLanguageChange: (language: string) => void
26
+ disabled?: boolean
27
+ loading?: boolean
28
+ ariaLabel: string
29
+ }
30
+
31
+ /**
32
+ * Shared language dropdown UI. Use in Navbar (app) or Login page.
33
+ * Parent controls data source and onSelect behavior (tRPC + refresh vs cookie + refresh).
34
+ */
35
+ export default function LanguagePicker({
36
+ supportedLanguages,
37
+ currentLanguage,
38
+ onLanguageChange,
39
+ disabled = false,
40
+ loading = false,
41
+ ariaLabel,
42
+ }: LanguagePickerProps) {
43
+ if (supportedLanguages.length < 2) return null
44
+
45
+ const isRTL = RTL_LANGUAGES.has(currentLanguage)
46
+
47
+ return (
48
+ <DropdownMenu>
49
+ <DropdownMenuTrigger
50
+ asChild
51
+ className='text-foreground hover:text-foreground/90 relative rounded-full focus:outline-hidden cursor-pointer'
52
+ >
53
+ <button
54
+ type='button'
55
+ className='flex h-10 items-center justify-center'
56
+ aria-label={ariaLabel}
57
+ disabled={disabled}
58
+ >
59
+ {loading ? (
60
+ <Spinner className='size-5' />
61
+ ) : (
62
+ <Languages className='h-5 w-5' aria-hidden='true' />
63
+ )}
64
+ </button>
65
+ </DropdownMenuTrigger>
66
+ <DropdownMenuContent
67
+ align={'end'}
68
+ sideOffset={12}
69
+ className='ring-1 ring-sky-400/80 dark:ring-amber-900'
70
+ >
71
+ {supportedLanguages.map((code) => (
72
+ <DropdownMenuItem
73
+ key={code}
74
+ onClick={() => onLanguageChange(code)}
75
+ disabled={disabled}
76
+ className='cursor-pointer'
77
+ >
78
+ {displayName(code)}
79
+ {code === currentLanguage ? ' ✓' : ''}
80
+ </DropdownMenuItem>
81
+ ))}
82
+ </DropdownMenuContent>
83
+ </DropdownMenu>
84
+ )
85
+ }
@@ -0,0 +1,46 @@
1
+ 'use client'
2
+
3
+ import { useCallback } from 'react'
4
+ import { useRouter } from 'next/navigation'
5
+ import { useI18n } from 'nextjs-cms/translations/client'
6
+ import { setLoginPageLanguageCookie, markLanguageChangedOnLogin } from 'nextjs-cms/translations'
7
+ import LanguagePicker from './language-picker'
8
+
9
+ export interface LoginLanguageDropdownProps {
10
+ supportedLanguages: readonly string[]
11
+ fallbackLanguage: string
12
+ initialLanguage: string
13
+ }
14
+
15
+ /**
16
+ * Language dropdown for the login page (unauthenticated).
17
+ * Persists via nextjs-cms-locale cookie; auth layout reads it when no session.
18
+ */
19
+ export default function LoginLanguageDropdown({
20
+ supportedLanguages,
21
+ fallbackLanguage,
22
+ initialLanguage,
23
+ }: LoginLanguageDropdownProps) {
24
+ const t = useI18n()
25
+ const router = useRouter()
26
+ const currentLanguage = initialLanguage || fallbackLanguage
27
+
28
+ const handleSelect = useCallback(
29
+ (language: string) => {
30
+ if (language === currentLanguage) return
31
+ setLoginPageLanguageCookie(language)
32
+ markLanguageChangedOnLogin()
33
+ router.refresh()
34
+ },
35
+ [currentLanguage, router],
36
+ )
37
+
38
+ return (
39
+ <LanguagePicker
40
+ supportedLanguages={supportedLanguages}
41
+ currentLanguage={currentLanguage}
42
+ onLanguageChange={handleSelect}
43
+ ariaLabel={t('language')}
44
+ />
45
+ )
46
+ }
@@ -12,7 +12,8 @@ const alertVariants = cva(
12
12
  destructive:
13
13
  'border-destructive/90 bg-destructive/10 text-destructive dark:border-destructive [&>svg]:text-destructive',
14
14
  light: 'bg-gray-100 text-gray-900 dark:bg-gray-950 dark:text-gray-100',
15
- info: 'bg-info text-info dark:bg-info dark:text-info',
15
+ info: 'border-info bg-info/10 text-info-foreground [&>svg]:text-info',
16
+ warning: 'bg-warning text-warning dark:bg-warning dark:text-warning',
16
17
  },
17
18
  },
18
19
  defaultVariants: {