@create-lft-app/nextjs 1.0.2 → 3.0.0

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 (81) hide show
  1. package/package.json +9 -3
  2. package/template/CLAUDE.md +279 -0
  3. package/template/drizzle.config.ts +12 -0
  4. package/template/package.json +31 -6
  5. package/template/proxy.ts +12 -0
  6. package/template/src/app/(auth)/dashboard/dashboard-content.tsx +124 -0
  7. package/template/src/app/(auth)/dashboard/page.tsx +9 -0
  8. package/template/src/app/(auth)/layout.tsx +7 -0
  9. package/template/src/app/(auth)/users/page.tsx +9 -0
  10. package/template/src/app/(auth)/users/users-content.tsx +26 -0
  11. package/template/src/app/(public)/layout.tsx +7 -0
  12. package/template/src/app/(public)/login/page.tsx +17 -0
  13. package/template/src/app/api/webhooks/route.ts +20 -0
  14. package/template/src/app/layout.tsx +13 -12
  15. package/template/src/app/providers.tsx +27 -0
  16. package/template/src/components/layout/{midday-sidebar.tsx → sidebar.tsx} +2 -7
  17. package/template/src/components/tables/data-table-column-header.tsx +68 -0
  18. package/template/src/components/tables/data-table-pagination.tsx +99 -0
  19. package/template/src/components/tables/data-table-toolbar.tsx +50 -0
  20. package/template/src/components/tables/data-table-view-options.tsx +59 -0
  21. package/template/src/components/tables/data-table.tsx +128 -0
  22. package/template/src/components/tables/index.ts +5 -0
  23. package/template/src/components/ui/animations/index.ts +44 -0
  24. package/template/src/components/ui/button.tsx +50 -21
  25. package/template/src/components/ui/card.tsx +27 -3
  26. package/template/src/components/ui/dialog.tsx +38 -35
  27. package/template/src/components/ui/motion.tsx +197 -0
  28. package/template/src/components/ui/page-transition.tsx +166 -0
  29. package/template/src/components/ui/sheet.tsx +65 -41
  30. package/template/src/config/navigation.ts +69 -0
  31. package/template/src/config/site.ts +12 -0
  32. package/template/src/db/index.ts +12 -0
  33. package/template/src/db/schema/index.ts +1 -0
  34. package/template/src/db/schema/users.ts +16 -0
  35. package/template/src/db/seed.ts +39 -0
  36. package/template/src/hooks/index.ts +3 -0
  37. package/template/src/hooks/useDataTable.ts +82 -0
  38. package/template/src/hooks/useDebounce.ts +49 -0
  39. package/template/src/hooks/useMediaQuery.ts +36 -0
  40. package/template/src/lib/date/config.ts +34 -0
  41. package/template/src/lib/date/formatters.ts +120 -0
  42. package/template/src/lib/date/index.ts +19 -0
  43. package/template/src/lib/excel/exporter.ts +89 -0
  44. package/template/src/lib/excel/index.ts +14 -0
  45. package/template/src/lib/excel/parser.ts +96 -0
  46. package/template/src/lib/query-client.ts +35 -0
  47. package/template/src/lib/supabase/client.ts +5 -2
  48. package/template/src/lib/supabase/proxy.ts +67 -0
  49. package/template/src/lib/supabase/server.ts +6 -4
  50. package/template/src/lib/supabase/types.ts +53 -0
  51. package/template/src/lib/validations/common.ts +75 -0
  52. package/template/src/lib/validations/index.ts +20 -0
  53. package/template/src/modules/auth/actions/auth-actions.ts +51 -4
  54. package/template/src/modules/auth/components/login-form.tsx +68 -0
  55. package/template/src/modules/auth/hooks/useAuth.ts +38 -0
  56. package/template/src/modules/auth/hooks/useAuthMutations.ts +43 -0
  57. package/template/src/modules/auth/hooks/useAuthQueries.ts +43 -0
  58. package/template/src/modules/auth/index.ts +12 -0
  59. package/template/src/modules/auth/schemas/auth.schema.ts +32 -0
  60. package/template/src/modules/auth/stores/useAuthStore.ts +37 -0
  61. package/template/src/modules/users/actions/users-actions.ts +94 -0
  62. package/template/src/modules/users/columns.tsx +86 -0
  63. package/template/src/modules/users/components/users-list.tsx +22 -0
  64. package/template/src/modules/users/hooks/useUsers.ts +39 -0
  65. package/template/src/modules/users/hooks/useUsersMutations.ts +55 -0
  66. package/template/src/modules/users/hooks/useUsersQueries.ts +35 -0
  67. package/template/src/modules/users/index.ts +12 -0
  68. package/template/src/modules/users/schemas/users.schema.ts +23 -0
  69. package/template/src/modules/users/stores/useUsersStore.ts +60 -0
  70. package/template/src/stores/index.ts +1 -0
  71. package/template/src/stores/useUiStore.ts +55 -0
  72. package/template/src/types/api.ts +28 -0
  73. package/template/src/types/index.ts +2 -0
  74. package/template/src/types/table.ts +34 -0
  75. package/template/supabase/config.toml +94 -0
  76. package/template/tsconfig.json +2 -1
  77. package/template/tsconfig.tsbuildinfo +1 -0
  78. package/template/next-env.d.ts +0 -6
  79. package/template/package-lock.json +0 -8454
  80. package/template/src/app/dashboard/page.tsx +0 -111
  81. package/template/src/components/dashboard/widget.tsx +0 -113
@@ -2,8 +2,8 @@
2
2
 
3
3
  import * as React from "react"
4
4
  import * as DialogPrimitive from "@radix-ui/react-dialog"
5
+ import { motion, AnimatePresence } from "framer-motion"
5
6
  import { XIcon } from "lucide-react"
6
-
7
7
  import { cn } from "@/lib/utils"
8
8
 
9
9
  function Dialog({
@@ -30,50 +30,52 @@ function DialogClose({
30
30
  return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
31
31
  }
32
32
 
33
- function DialogOverlay({
34
- className,
35
- ...props
36
- }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
37
- return (
38
- <DialogPrimitive.Overlay
33
+ const DialogOverlay = React.forwardRef<
34
+ React.ElementRef<typeof DialogPrimitive.Overlay>,
35
+ React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
36
+ >(({ className, ...props }, ref) => (
37
+ <DialogPrimitive.Overlay ref={ref} asChild {...props}>
38
+ <motion.div
39
39
  data-slot="dialog-overlay"
40
+ initial={{ opacity: 0 }}
41
+ animate={{ opacity: 1 }}
42
+ exit={{ opacity: 0 }}
43
+ transition={{ duration: 0.2 }}
40
44
  className={cn(
41
45
  "fixed inset-0 z-50",
42
- "bg-[#f6f6f3]/60 dark:bg-[#0C0C0C]/80",
43
- "data-[state=open]:animate-in data-[state=closed]:animate-out",
44
- "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
46
+ "bg-black/60 backdrop-blur-sm",
45
47
  className
46
48
  )}
47
- {...props}
48
49
  />
49
- )
50
- }
50
+ </DialogPrimitive.Overlay>
51
+ ))
52
+ DialogOverlay.displayName = "DialogOverlay"
51
53
 
52
- function DialogContent({
53
- className,
54
- children,
55
- showCloseButton = true,
56
- ...props
57
- }: React.ComponentProps<typeof DialogPrimitive.Content> & {
58
- showCloseButton?: boolean
59
- }) {
60
- return (
61
- <DialogPortal data-slot="dialog-portal">
62
- <DialogOverlay />
63
- <DialogPrimitive.Content
54
+ const DialogContent = React.forwardRef<
55
+ React.ElementRef<typeof DialogPrimitive.Content>,
56
+ React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> & {
57
+ showCloseButton?: boolean
58
+ }
59
+ >(({ className, children, showCloseButton = true, ...props }, ref) => (
60
+ <DialogPortal>
61
+ <DialogOverlay />
62
+ <DialogPrimitive.Content ref={ref} asChild {...props}>
63
+ <motion.div
64
64
  data-slot="dialog-content"
65
+ initial={{ opacity: 0, scale: 0.95, y: -10 }}
66
+ animate={{ opacity: 1, scale: 1, y: 0 }}
67
+ exit={{ opacity: 0, scale: 0.95, y: -10 }}
68
+ transition={{
69
+ type: "spring",
70
+ stiffness: 300,
71
+ damping: 30,
72
+ }}
65
73
  className={cn(
66
74
  "fixed left-[50%] top-[50%] z-50",
67
75
  "translate-x-[-50%] translate-y-[-50%]",
68
76
  "grid w-full max-w-xl gap-4 border bg-background p-6",
69
- "duration-200",
70
- "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
71
- "data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
72
- "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
73
- "data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]",
74
77
  className
75
78
  )}
76
- {...props}
77
79
  >
78
80
  {children}
79
81
  {showCloseButton && (
@@ -85,10 +87,11 @@ function DialogContent({
85
87
  <span className="sr-only">Close</span>
86
88
  </DialogPrimitive.Close>
87
89
  )}
88
- </DialogPrimitive.Content>
89
- </DialogPortal>
90
- )
91
- }
90
+ </motion.div>
91
+ </DialogPrimitive.Content>
92
+ </DialogPortal>
93
+ ))
94
+ DialogContent.displayName = "DialogContent"
92
95
 
93
96
  function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
94
97
  return (
@@ -0,0 +1,197 @@
1
+ 'use client'
2
+
3
+ import { motion, type HTMLMotionProps, type Variants } from 'framer-motion'
4
+ import { forwardRef } from 'react'
5
+
6
+ // Variantes de animación reutilizables
7
+ export const fadeIn: Variants = {
8
+ hidden: { opacity: 0 },
9
+ visible: { opacity: 1 },
10
+ }
11
+
12
+ export const fadeInUp: Variants = {
13
+ hidden: { opacity: 0, y: 20 },
14
+ visible: { opacity: 1, y: 0 },
15
+ }
16
+
17
+ export const fadeInDown: Variants = {
18
+ hidden: { opacity: 0, y: -20 },
19
+ visible: { opacity: 1, y: 0 },
20
+ }
21
+
22
+ export const fadeInLeft: Variants = {
23
+ hidden: { opacity: 0, x: -20 },
24
+ visible: { opacity: 1, x: 0 },
25
+ }
26
+
27
+ export const fadeInRight: Variants = {
28
+ hidden: { opacity: 0, x: 20 },
29
+ visible: { opacity: 1, x: 0 },
30
+ }
31
+
32
+ export const scaleIn: Variants = {
33
+ hidden: { opacity: 0, scale: 0.95 },
34
+ visible: { opacity: 1, scale: 1 },
35
+ }
36
+
37
+ export const slideInFromBottom: Variants = {
38
+ hidden: { y: '100%' },
39
+ visible: { y: 0 },
40
+ }
41
+
42
+ export const slideInFromTop: Variants = {
43
+ hidden: { y: '-100%' },
44
+ visible: { y: 0 },
45
+ }
46
+
47
+ export const staggerContainer: Variants = {
48
+ hidden: { opacity: 0 },
49
+ visible: {
50
+ opacity: 1,
51
+ transition: {
52
+ staggerChildren: 0.1,
53
+ },
54
+ },
55
+ }
56
+
57
+ export const staggerItem: Variants = {
58
+ hidden: { opacity: 0, y: 20 },
59
+ visible: { opacity: 1, y: 0 },
60
+ }
61
+
62
+ // Transiciones predefinidas
63
+ export const springTransition = {
64
+ type: 'spring',
65
+ stiffness: 300,
66
+ damping: 30,
67
+ }
68
+
69
+ export const easeTransition = {
70
+ duration: 0.3,
71
+ ease: [0.25, 0.1, 0.25, 1],
72
+ }
73
+
74
+ export const smoothTransition = {
75
+ duration: 0.4,
76
+ ease: 'easeInOut',
77
+ }
78
+
79
+ // Componentes de animación base
80
+ export const MotionDiv = motion.div
81
+ export const MotionSpan = motion.span
82
+ export const MotionButton = motion.button
83
+ export const MotionUl = motion.ul
84
+ export const MotionLi = motion.li
85
+ export const MotionNav = motion.nav
86
+ export const MotionSection = motion.section
87
+ export const MotionArticle = motion.article
88
+ export const MotionHeader = motion.header
89
+ export const MotionFooter = motion.footer
90
+ export const MotionMain = motion.main
91
+ export const MotionAside = motion.aside
92
+
93
+ // Componente FadeIn genérico
94
+ interface FadeInProps extends HTMLMotionProps<'div'> {
95
+ direction?: 'up' | 'down' | 'left' | 'right' | 'none'
96
+ delay?: number
97
+ duration?: number
98
+ }
99
+
100
+ export const FadeIn = forwardRef<HTMLDivElement, FadeInProps>(
101
+ ({ children, direction = 'up', delay = 0, duration = 0.4, ...props }, ref) => {
102
+ const variants: Record<string, Variants> = {
103
+ up: fadeInUp,
104
+ down: fadeInDown,
105
+ left: fadeInLeft,
106
+ right: fadeInRight,
107
+ none: fadeIn,
108
+ }
109
+
110
+ return (
111
+ <motion.div
112
+ ref={ref}
113
+ initial="hidden"
114
+ animate="visible"
115
+ variants={variants[direction]}
116
+ transition={{ duration, delay, ease: 'easeOut' }}
117
+ {...props}
118
+ >
119
+ {children}
120
+ </motion.div>
121
+ )
122
+ }
123
+ )
124
+ FadeIn.displayName = 'FadeIn'
125
+
126
+ // Componente ScaleIn
127
+ interface ScaleInProps extends HTMLMotionProps<'div'> {
128
+ delay?: number
129
+ duration?: number
130
+ }
131
+
132
+ export const ScaleIn = forwardRef<HTMLDivElement, ScaleInProps>(
133
+ ({ children, delay = 0, duration = 0.3, ...props }, ref) => {
134
+ return (
135
+ <motion.div
136
+ ref={ref}
137
+ initial="hidden"
138
+ animate="visible"
139
+ variants={scaleIn}
140
+ transition={{ duration, delay, ...springTransition }}
141
+ {...props}
142
+ >
143
+ {children}
144
+ </motion.div>
145
+ )
146
+ }
147
+ )
148
+ ScaleIn.displayName = 'ScaleIn'
149
+
150
+ // Componente para listas con stagger
151
+ interface StaggerListProps extends HTMLMotionProps<'ul'> {
152
+ staggerDelay?: number
153
+ }
154
+
155
+ export const StaggerList = forwardRef<HTMLUListElement, StaggerListProps>(
156
+ ({ children, staggerDelay = 0.1, ...props }, ref) => {
157
+ return (
158
+ <motion.ul
159
+ ref={ref}
160
+ initial="hidden"
161
+ animate="visible"
162
+ variants={{
163
+ hidden: { opacity: 0 },
164
+ visible: {
165
+ opacity: 1,
166
+ transition: {
167
+ staggerChildren: staggerDelay,
168
+ },
169
+ },
170
+ }}
171
+ {...props}
172
+ >
173
+ {children}
174
+ </motion.ul>
175
+ )
176
+ }
177
+ )
178
+ StaggerList.displayName = 'StaggerList'
179
+
180
+ export const StaggerItem = forwardRef<HTMLLIElement, HTMLMotionProps<'li'>>(
181
+ ({ children, ...props }, ref) => {
182
+ return (
183
+ <motion.li
184
+ ref={ref}
185
+ variants={staggerItem}
186
+ transition={easeTransition}
187
+ {...props}
188
+ >
189
+ {children}
190
+ </motion.li>
191
+ )
192
+ }
193
+ )
194
+ StaggerItem.displayName = 'StaggerItem'
195
+
196
+ // Componente de presencia animada para entradas/salidas
197
+ export { AnimatePresence } from 'framer-motion'
@@ -0,0 +1,166 @@
1
+ 'use client'
2
+
3
+ import { motion, type HTMLMotionProps } from 'framer-motion'
4
+ import { cn } from '@/lib/utils'
5
+
6
+ const pageVariants = {
7
+ initial: {
8
+ opacity: 0,
9
+ y: 20,
10
+ },
11
+ enter: {
12
+ opacity: 1,
13
+ y: 0,
14
+ transition: {
15
+ duration: 0.4,
16
+ ease: [0.25, 0.1, 0.25, 1],
17
+ when: 'beforeChildren',
18
+ staggerChildren: 0.1,
19
+ },
20
+ },
21
+ exit: {
22
+ opacity: 0,
23
+ y: -20,
24
+ transition: {
25
+ duration: 0.3,
26
+ },
27
+ },
28
+ }
29
+
30
+ const childVariants = {
31
+ initial: {
32
+ opacity: 0,
33
+ y: 20,
34
+ },
35
+ enter: {
36
+ opacity: 1,
37
+ y: 0,
38
+ },
39
+ exit: {
40
+ opacity: 0,
41
+ y: -20,
42
+ },
43
+ }
44
+
45
+ interface PageTransitionProps extends HTMLMotionProps<'div'> {
46
+ children: React.ReactNode
47
+ }
48
+
49
+ export function PageTransition({
50
+ children,
51
+ className,
52
+ ...props
53
+ }: PageTransitionProps) {
54
+ return (
55
+ <motion.div
56
+ initial="initial"
57
+ animate="enter"
58
+ exit="exit"
59
+ variants={pageVariants}
60
+ className={cn('w-full', className)}
61
+ {...props}
62
+ >
63
+ {children}
64
+ </motion.div>
65
+ )
66
+ }
67
+
68
+ interface PageSectionProps extends HTMLMotionProps<'section'> {
69
+ children: React.ReactNode
70
+ delay?: number
71
+ }
72
+
73
+ export function PageSection({
74
+ children,
75
+ className,
76
+ delay = 0,
77
+ ...props
78
+ }: PageSectionProps) {
79
+ return (
80
+ <motion.section
81
+ variants={childVariants}
82
+ transition={{
83
+ duration: 0.4,
84
+ delay,
85
+ ease: [0.25, 0.1, 0.25, 1],
86
+ }}
87
+ className={className}
88
+ {...props}
89
+ >
90
+ {children}
91
+ </motion.section>
92
+ )
93
+ }
94
+
95
+ interface PageHeaderProps extends HTMLMotionProps<'header'> {
96
+ children: React.ReactNode
97
+ }
98
+
99
+ export function PageHeader({
100
+ children,
101
+ className,
102
+ ...props
103
+ }: PageHeaderProps) {
104
+ return (
105
+ <motion.header
106
+ initial={{ opacity: 0, y: -20 }}
107
+ animate={{ opacity: 1, y: 0 }}
108
+ transition={{
109
+ duration: 0.4,
110
+ ease: [0.25, 0.1, 0.25, 1],
111
+ }}
112
+ className={cn('mb-6', className)}
113
+ {...props}
114
+ >
115
+ {children}
116
+ </motion.header>
117
+ )
118
+ }
119
+
120
+ interface PageTitleProps extends HTMLMotionProps<'h1'> {
121
+ children: React.ReactNode
122
+ }
123
+
124
+ export function PageTitle({ children, className, ...props }: PageTitleProps) {
125
+ return (
126
+ <motion.h1
127
+ initial={{ opacity: 0, x: -20 }}
128
+ animate={{ opacity: 1, x: 0 }}
129
+ transition={{
130
+ duration: 0.4,
131
+ delay: 0.1,
132
+ ease: [0.25, 0.1, 0.25, 1],
133
+ }}
134
+ className={cn('text-2xl font-bold tracking-tight', className)}
135
+ {...props}
136
+ >
137
+ {children}
138
+ </motion.h1>
139
+ )
140
+ }
141
+
142
+ interface PageDescriptionProps extends HTMLMotionProps<'p'> {
143
+ children: React.ReactNode
144
+ }
145
+
146
+ export function PageDescription({
147
+ children,
148
+ className,
149
+ ...props
150
+ }: PageDescriptionProps) {
151
+ return (
152
+ <motion.p
153
+ initial={{ opacity: 0 }}
154
+ animate={{ opacity: 1 }}
155
+ transition={{
156
+ duration: 0.4,
157
+ delay: 0.2,
158
+ ease: [0.25, 0.1, 0.25, 1],
159
+ }}
160
+ className={cn('text-muted-foreground', className)}
161
+ {...props}
162
+ >
163
+ {children}
164
+ </motion.p>
165
+ )
166
+ }
@@ -2,8 +2,8 @@
2
2
 
3
3
  import * as React from "react"
4
4
  import * as SheetPrimitive from "@radix-ui/react-dialog"
5
+ import { motion } from "framer-motion"
5
6
  import { XIcon } from "lucide-react"
6
-
7
7
  import { cn } from "@/lib/utils"
8
8
 
9
9
  function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
@@ -28,65 +28,89 @@ function SheetPortal({
28
28
  return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />
29
29
  }
30
30
 
31
- function SheetOverlay({
32
- className,
33
- ...props
34
- }: React.ComponentProps<typeof SheetPrimitive.Overlay>) {
35
- return (
36
- <SheetPrimitive.Overlay
31
+ const SheetOverlay = React.forwardRef<
32
+ React.ElementRef<typeof SheetPrimitive.Overlay>,
33
+ React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
34
+ >(({ className, ...props }, ref) => (
35
+ <SheetPrimitive.Overlay ref={ref} asChild {...props}>
36
+ <motion.div
37
37
  data-slot="sheet-overlay"
38
+ initial={{ opacity: 0 }}
39
+ animate={{ opacity: 1 }}
40
+ exit={{ opacity: 0 }}
41
+ transition={{ duration: 0.2 }}
38
42
  className={cn(
39
43
  "fixed inset-0 z-50",
40
- "bg-[#f6f6f3]/60 dark:bg-[#0C0C0C]/80",
41
- "data-[state=open]:animate-in data-[state=closed]:animate-out",
42
- "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
44
+ "bg-black/60 backdrop-blur-sm",
43
45
  className
44
46
  )}
45
- {...props}
46
47
  />
47
- )
48
+ </SheetPrimitive.Overlay>
49
+ ))
50
+ SheetOverlay.displayName = "SheetOverlay"
51
+
52
+ const slideVariants = {
53
+ right: {
54
+ initial: { x: "100%" },
55
+ animate: { x: 0 },
56
+ exit: { x: "100%" },
57
+ },
58
+ left: {
59
+ initial: { x: "-100%" },
60
+ animate: { x: 0 },
61
+ exit: { x: "-100%" },
62
+ },
63
+ top: {
64
+ initial: { y: "-100%" },
65
+ animate: { y: 0 },
66
+ exit: { y: "-100%" },
67
+ },
68
+ bottom: {
69
+ initial: { y: "100%" },
70
+ animate: { y: 0 },
71
+ exit: { y: "100%" },
72
+ },
48
73
  }
49
74
 
50
- function SheetContent({
51
- className,
52
- children,
53
- side = "right",
54
- ...props
55
- }: React.ComponentProps<typeof SheetPrimitive.Content> & {
56
- side?: "top" | "right" | "bottom" | "left"
57
- }) {
58
- return (
59
- <SheetPortal>
60
- <SheetOverlay />
61
- <SheetPrimitive.Content
75
+ const SheetContent = React.forwardRef<
76
+ React.ElementRef<typeof SheetPrimitive.Content>,
77
+ React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content> & {
78
+ side?: "top" | "right" | "bottom" | "left"
79
+ }
80
+ >(({ className, children, side = "right", ...props }, ref) => (
81
+ <SheetPortal>
82
+ <SheetOverlay />
83
+ <SheetPrimitive.Content ref={ref} asChild {...props}>
84
+ <motion.div
62
85
  data-slot="sheet-content"
86
+ initial={slideVariants[side].initial}
87
+ animate={slideVariants[side].animate}
88
+ exit={slideVariants[side].exit}
89
+ transition={{
90
+ type: "spring",
91
+ stiffness: 300,
92
+ damping: 30,
93
+ }}
63
94
  className={cn(
64
95
  "fixed z-50 gap-4 p-6",
65
- "bg-[#FAFAF9] dark:bg-[#0C0C0C]",
66
- "transition ease-in-out",
67
- "data-[state=open]:animate-in data-[state=closed]:animate-out",
68
- "data-[state=open]:duration-300 data-[state=closed]:duration-200",
69
- side === "right" &&
70
- "inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-[520px] data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right",
71
- side === "left" &&
72
- "inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-[520px] data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left",
73
- side === "top" &&
74
- "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
75
- side === "bottom" &&
76
- "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
96
+ "bg-background border",
97
+ side === "right" && "inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-[520px]",
98
+ side === "left" && "inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-[520px]",
99
+ side === "top" && "inset-x-0 top-0 border-b",
100
+ side === "bottom" && "inset-x-0 bottom-0 border-t",
77
101
  className
78
102
  )}
79
- {...props}
80
103
  >
81
104
  {children}
82
105
  <SheetPrimitive.Close className="absolute right-6 top-6 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none disabled:pointer-events-none">
83
106
  <XIcon className="h-4 w-4" />
84
107
  <span className="sr-only">Close</span>
85
108
  </SheetPrimitive.Close>
86
- </SheetPrimitive.Content>
87
- </SheetPortal>
88
- )
89
- }
109
+ </motion.div>
110
+ </SheetPrimitive.Content>
111
+ </SheetPortal>
112
+ ))
113
+ SheetContent.displayName = "SheetContent"
90
114
 
91
115
  function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
92
116
  return (
@@ -0,0 +1,69 @@
1
+ import { LucideIcon, LayoutDashboard, Users, Settings, FileText } from 'lucide-react'
2
+
3
+ export interface NavItem {
4
+ title: string
5
+ href: string
6
+ icon?: LucideIcon
7
+ disabled?: boolean
8
+ external?: boolean
9
+ badge?: string
10
+ }
11
+
12
+ export interface NavSection {
13
+ title?: string
14
+ items: NavItem[]
15
+ }
16
+
17
+ export const mainNav: NavItem[] = [
18
+ {
19
+ title: 'Dashboard',
20
+ href: '/dashboard',
21
+ },
22
+ {
23
+ title: 'Usuarios',
24
+ href: '/users',
25
+ },
26
+ ]
27
+
28
+ export const sidebarNav: NavSection[] = [
29
+ {
30
+ items: [
31
+ {
32
+ title: 'Dashboard',
33
+ href: '/dashboard',
34
+ icon: LayoutDashboard,
35
+ },
36
+ {
37
+ title: 'Usuarios',
38
+ href: '/users',
39
+ icon: Users,
40
+ },
41
+ {
42
+ title: 'Reportes',
43
+ href: '/reports',
44
+ icon: FileText,
45
+ },
46
+ ],
47
+ },
48
+ {
49
+ title: 'Configuración',
50
+ items: [
51
+ {
52
+ title: 'Ajustes',
53
+ href: '/settings',
54
+ icon: Settings,
55
+ },
56
+ ],
57
+ },
58
+ ]
59
+
60
+ export const footerNav: NavItem[] = [
61
+ {
62
+ title: 'Términos',
63
+ href: '/terms',
64
+ },
65
+ {
66
+ title: 'Privacidad',
67
+ href: '/privacy',
68
+ },
69
+ ]
@@ -0,0 +1,12 @@
1
+ export const siteConfig = {
2
+ name: 'LFT App',
3
+ description: 'Next.js application with LFT stack',
4
+ url: process.env.NEXT_PUBLIC_APP_URL ?? 'http://localhost:3000',
5
+ ogImage: '/og.png',
6
+ links: {
7
+ github: 'https://github.com',
8
+ },
9
+ creator: 'LFT Team',
10
+ }
11
+
12
+ export type SiteConfig = typeof siteConfig