@create-lft-app/nextjs 3.1.0 → 3.2.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 (128) hide show
  1. package/README.md +549 -549
  2. package/package.json +48 -48
  3. package/template/CLAUDE.md +1239 -279
  4. package/template/drizzle.config.ts +12 -12
  5. package/template/eslint.config.mjs +16 -16
  6. package/template/gitignore +36 -36
  7. package/template/next.config.ts +7 -7
  8. package/template/package.json +86 -86
  9. package/template/postcss.config.mjs +7 -7
  10. package/template/proxy.ts +12 -12
  11. package/template/public/logolft.svg +11 -11
  12. package/template/src/app/(auth)/dashboard/dashboard-content.tsx +124 -124
  13. package/template/src/app/(auth)/dashboard/page.tsx +9 -9
  14. package/template/src/app/(auth)/layout.tsx +7 -7
  15. package/template/src/app/(auth)/users/page.tsx +9 -9
  16. package/template/src/app/(auth)/users/users-content.tsx +26 -26
  17. package/template/src/app/(public)/layout.tsx +7 -7
  18. package/template/src/app/(public)/login/page.tsx +17 -17
  19. package/template/src/app/api/webhooks/route.ts +20 -20
  20. package/template/src/app/globals.css +249 -249
  21. package/template/src/app/layout.tsx +37 -37
  22. package/template/src/app/page.tsx +5 -5
  23. package/template/src/app/providers.tsx +27 -27
  24. package/template/src/components/layout/main-content.tsx +28 -28
  25. package/template/src/components/layout/sidebar-context.tsx +33 -33
  26. package/template/src/components/layout/sidebar.tsx +141 -146
  27. package/template/src/components/tables/data-table-column-header.tsx +68 -68
  28. package/template/src/components/tables/data-table-date-filter.tsx +203 -0
  29. package/template/src/components/tables/data-table-faceted-filter.tsx +185 -0
  30. package/template/src/components/tables/data-table-filters-dropdown.tsx +130 -0
  31. package/template/src/components/tables/data-table-number-filter.tsx +295 -0
  32. package/template/src/components/tables/data-table-pagination.tsx +99 -99
  33. package/template/src/components/tables/data-table-toolbar.tsx +140 -50
  34. package/template/src/components/tables/data-table-view-options.tsx +63 -59
  35. package/template/src/components/tables/data-table.tsx +148 -128
  36. package/template/src/components/tables/index.ts +9 -5
  37. package/template/src/components/ui/accordion.tsx +58 -58
  38. package/template/src/components/ui/alert-dialog.tsx +165 -165
  39. package/template/src/components/ui/alert.tsx +66 -66
  40. package/template/src/components/ui/animations/index.ts +44 -44
  41. package/template/src/components/ui/avatar.tsx +55 -55
  42. package/template/src/components/ui/badge.tsx +50 -50
  43. package/template/src/components/ui/button.tsx +118 -118
  44. package/template/src/components/ui/calendar.tsx +220 -220
  45. package/template/src/components/ui/card.tsx +113 -113
  46. package/template/src/components/ui/checkbox.tsx +38 -38
  47. package/template/src/components/ui/collapsible.tsx +33 -33
  48. package/template/src/components/ui/command.tsx +196 -196
  49. package/template/src/components/ui/dialog.tsx +156 -156
  50. package/template/src/components/ui/dropdown-menu.tsx +280 -280
  51. package/template/src/components/ui/form.tsx +171 -171
  52. package/template/src/components/ui/icons.tsx +167 -167
  53. package/template/src/components/ui/input.tsx +28 -28
  54. package/template/src/components/ui/label.tsx +25 -25
  55. package/template/src/components/ui/motion.tsx +197 -197
  56. package/template/src/components/ui/page-transition.tsx +166 -166
  57. package/template/src/components/ui/popover.tsx +59 -59
  58. package/template/src/components/ui/progress.tsx +32 -32
  59. package/template/src/components/ui/radio-group.tsx +45 -45
  60. package/template/src/components/ui/scroll-area.tsx +63 -63
  61. package/template/src/components/ui/select.tsx +208 -208
  62. package/template/src/components/ui/separator.tsx +28 -28
  63. package/template/src/components/ui/sheet.tsx +170 -170
  64. package/template/src/components/ui/sidebar.tsx +726 -726
  65. package/template/src/components/ui/skeleton.tsx +15 -15
  66. package/template/src/components/ui/slider.tsx +58 -58
  67. package/template/src/components/ui/sonner.tsx +47 -47
  68. package/template/src/components/ui/spinner.tsx +27 -27
  69. package/template/src/components/ui/submit-button.tsx +47 -47
  70. package/template/src/components/ui/switch.tsx +31 -31
  71. package/template/src/components/ui/table.tsx +120 -120
  72. package/template/src/components/ui/tabs.tsx +75 -75
  73. package/template/src/components/ui/textarea.tsx +26 -26
  74. package/template/src/components/ui/tooltip.tsx +70 -70
  75. package/template/src/config/navigation.ts +59 -69
  76. package/template/src/config/roles.ts +27 -0
  77. package/template/src/config/site.ts +12 -12
  78. package/template/src/db/index.ts +12 -12
  79. package/template/src/db/schema/index.ts +1 -1
  80. package/template/src/db/schema/users.ts +16 -16
  81. package/template/src/db/seed.ts +39 -39
  82. package/template/src/hooks/index.ts +3 -3
  83. package/template/src/hooks/use-mobile.ts +21 -21
  84. package/template/src/hooks/useDataTable.ts +82 -82
  85. package/template/src/hooks/useDebounce.ts +49 -49
  86. package/template/src/hooks/useMediaQuery.ts +36 -36
  87. package/template/src/lib/date/config.ts +36 -34
  88. package/template/src/lib/date/formatters.ts +127 -120
  89. package/template/src/lib/date/index.ts +26 -19
  90. package/template/src/lib/excel/exporter.ts +89 -89
  91. package/template/src/lib/excel/index.ts +14 -14
  92. package/template/src/lib/excel/parser.ts +96 -96
  93. package/template/src/lib/query-client.ts +35 -35
  94. package/template/src/lib/supabase/admin.ts +23 -0
  95. package/template/src/lib/supabase/client.ts +11 -11
  96. package/template/src/lib/supabase/proxy.ts +67 -67
  97. package/template/src/lib/supabase/server.ts +38 -38
  98. package/template/src/lib/supabase/types.ts +53 -53
  99. package/template/src/lib/utils.ts +6 -6
  100. package/template/src/lib/validations/common.ts +75 -75
  101. package/template/src/lib/validations/index.ts +20 -20
  102. package/template/src/modules/auth/actions/auth-actions.ts +59 -59
  103. package/template/src/modules/auth/components/login-form.tsx +68 -68
  104. package/template/src/modules/auth/hooks/useAuth.ts +38 -38
  105. package/template/src/modules/auth/hooks/useAuthMutations.ts +43 -43
  106. package/template/src/modules/auth/hooks/useAuthQueries.ts +43 -43
  107. package/template/src/modules/auth/index.ts +12 -12
  108. package/template/src/modules/auth/schemas/auth.schema.ts +32 -32
  109. package/template/src/modules/auth/stores/useAuthStore.ts +37 -37
  110. package/template/src/modules/users/actions/users-actions.ts +166 -94
  111. package/template/src/modules/users/columns.tsx +106 -86
  112. package/template/src/modules/users/components/users-list.tsx +48 -22
  113. package/template/src/modules/users/hooks/useUsers.ts +39 -39
  114. package/template/src/modules/users/hooks/useUsersMutations.ts +55 -55
  115. package/template/src/modules/users/hooks/useUsersQueries.ts +35 -35
  116. package/template/src/modules/users/index.ts +30 -12
  117. package/template/src/modules/users/schemas/users.schema.ts +51 -23
  118. package/template/src/modules/users/stores/useUsersStore.ts +60 -60
  119. package/template/src/modules/users/types/auth-user.types.ts +42 -0
  120. package/template/src/modules/users/utils/user-mapper.ts +32 -0
  121. package/template/src/stores/index.ts +1 -1
  122. package/template/src/stores/useUiStore.ts +55 -55
  123. package/template/src/types/api.ts +28 -28
  124. package/template/src/types/index.ts +2 -2
  125. package/template/src/types/table.ts +34 -34
  126. package/template/supabase/config.toml +94 -94
  127. package/template/tsconfig.json +42 -42
  128. package/template/tsconfig.tsbuildinfo +1 -1
@@ -1,69 +1,59 @@
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
- ]
1
+ import { LucideIcon, LayoutDashboard, Users, 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
+
50
+ export const footerNav: NavItem[] = [
51
+ {
52
+ title: 'Términos',
53
+ href: '/terms',
54
+ },
55
+ {
56
+ title: 'Privacidad',
57
+ href: '/privacy',
58
+ },
59
+ ]
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Configuración centralizada de roles de usuario.
3
+ * Modificar aquí para agregar/quitar roles en toda la aplicación.
4
+ */
5
+
6
+ export const USER_ROLES = ['admin', 'user', 'viewer'] as const
7
+
8
+ export type UserRole = (typeof USER_ROLES)[number]
9
+
10
+ export const DEFAULT_ROLE: UserRole = 'user'
11
+
12
+ /**
13
+ * Labels para mostrar en UI (traducidos al español)
14
+ */
15
+ export const ROLE_LABELS: Record<UserRole, string> = {
16
+ admin: 'Administrador',
17
+ user: 'Usuario',
18
+ viewer: 'Visualizador',
19
+ }
20
+
21
+ /**
22
+ * Opciones para selects/filtros de roles
23
+ */
24
+ export const ROLE_OPTIONS = USER_ROLES.map((role) => ({
25
+ value: role,
26
+ label: ROLE_LABELS[role],
27
+ }))
@@ -1,12 +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
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
@@ -1,12 +1,12 @@
1
- import { drizzle } from 'drizzle-orm/postgres-js'
2
- import postgres from 'postgres'
3
- import * as schema from './schema'
4
-
5
- const connectionString = process.env.DATABASE_URL!
6
-
7
- // Disable prefetch as it is not supported for "Transaction" pool mode
8
- const client = postgres(connectionString, { prepare: false })
9
-
10
- export const db = drizzle(client, { schema })
11
-
12
- export type Database = typeof db
1
+ import { drizzle } from 'drizzle-orm/postgres-js'
2
+ import postgres from 'postgres'
3
+ import * as schema from './schema'
4
+
5
+ const connectionString = process.env.DATABASE_URL!
6
+
7
+ // Disable prefetch as it is not supported for "Transaction" pool mode
8
+ const client = postgres(connectionString, { prepare: false })
9
+
10
+ export const db = drizzle(client, { schema })
11
+
12
+ export type Database = typeof db
@@ -1 +1 @@
1
- export * from './users'
1
+ export * from './users'
@@ -1,16 +1,16 @@
1
- import { pgTable, uuid, varchar, text, timestamp, pgEnum } from 'drizzle-orm/pg-core'
2
-
3
- export const userRoleEnum = pgEnum('user_role', ['admin', 'user', 'viewer'])
4
-
5
- export const users = pgTable('users', {
6
- id: uuid('id').primaryKey().defaultRandom(),
7
- email: varchar('email', { length: 255 }).notNull().unique(),
8
- name: varchar('name', { length: 255 }).notNull(),
9
- role: userRoleEnum('role').default('user').notNull(),
10
- avatarUrl: text('avatar_url'),
11
- createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
12
- updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
13
- })
14
-
15
- export type User = typeof users.$inferSelect
16
- export type NewUser = typeof users.$inferInsert
1
+ import { pgTable, uuid, varchar, text, timestamp, pgEnum } from 'drizzle-orm/pg-core'
2
+
3
+ export const userRoleEnum = pgEnum('user_role', ['admin', 'user', 'viewer'])
4
+
5
+ export const users = pgTable('users', {
6
+ id: uuid('id').primaryKey().defaultRandom(),
7
+ email: varchar('email', { length: 255 }).notNull().unique(),
8
+ name: varchar('name', { length: 255 }).notNull(),
9
+ role: userRoleEnum('role').default('user').notNull(),
10
+ avatarUrl: text('avatar_url'),
11
+ createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
12
+ updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
13
+ })
14
+
15
+ export type User = typeof users.$inferSelect
16
+ export type NewUser = typeof users.$inferInsert
@@ -1,39 +1,39 @@
1
- import { db } from './index'
2
- import { users } from './schema'
3
-
4
- async function seed() {
5
- console.log('🌱 Seeding database...')
6
-
7
- // Clear existing data
8
- await db.delete(users)
9
-
10
- // Insert seed data
11
- await db.insert(users).values([
12
- {
13
- email: 'admin@example.com',
14
- name: 'Admin User',
15
- role: 'admin',
16
- },
17
- {
18
- email: 'user@example.com',
19
- name: 'Regular User',
20
- role: 'user',
21
- },
22
- {
23
- email: 'viewer@example.com',
24
- name: 'Viewer User',
25
- role: 'viewer',
26
- },
27
- ])
28
-
29
- console.log('✅ Database seeded successfully!')
30
- }
31
-
32
- seed()
33
- .catch((error) => {
34
- console.error('❌ Seed failed:', error)
35
- process.exit(1)
36
- })
37
- .finally(() => {
38
- process.exit(0)
39
- })
1
+ import { db } from './index'
2
+ import { users } from './schema'
3
+
4
+ async function seed() {
5
+ console.log('🌱 Seeding database...')
6
+
7
+ // Clear existing data
8
+ await db.delete(users)
9
+
10
+ // Insert seed data
11
+ await db.insert(users).values([
12
+ {
13
+ email: 'admin@example.com',
14
+ name: 'Admin User',
15
+ role: 'admin',
16
+ },
17
+ {
18
+ email: 'user@example.com',
19
+ name: 'Regular User',
20
+ role: 'user',
21
+ },
22
+ {
23
+ email: 'viewer@example.com',
24
+ name: 'Viewer User',
25
+ role: 'viewer',
26
+ },
27
+ ])
28
+
29
+ console.log('✅ Database seeded successfully!')
30
+ }
31
+
32
+ seed()
33
+ .catch((error) => {
34
+ console.error('❌ Seed failed:', error)
35
+ process.exit(1)
36
+ })
37
+ .finally(() => {
38
+ process.exit(0)
39
+ })
@@ -1,3 +1,3 @@
1
- export { useMediaQuery, useIsMobile, useIsTablet, useIsDesktop } from './useMediaQuery'
2
- export { useDebounce, useDebouncedCallback } from './useDebounce'
3
- export { useDataTable } from './useDataTable'
1
+ export { useMediaQuery, useIsMobile, useIsTablet, useIsDesktop } from './useMediaQuery'
2
+ export { useDebounce, useDebouncedCallback } from './useDebounce'
3
+ export { useDataTable } from './useDataTable'
@@ -1,21 +1,21 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
-
5
- const MOBILE_BREAKPOINT = 768
6
-
7
- export function useIsMobile() {
8
- const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
9
-
10
- React.useEffect(() => {
11
- const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
12
- const onChange = () => {
13
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
14
- }
15
- mql.addEventListener("change", onChange)
16
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
17
- return () => mql.removeEventListener("change", onChange)
18
- }, [])
19
-
20
- return !!isMobile
21
- }
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+
5
+ const MOBILE_BREAKPOINT = 768
6
+
7
+ export function useIsMobile() {
8
+ const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
9
+
10
+ React.useEffect(() => {
11
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
12
+ const onChange = () => {
13
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
14
+ }
15
+ mql.addEventListener("change", onChange)
16
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
17
+ return () => mql.removeEventListener("change", onChange)
18
+ }, [])
19
+
20
+ return !!isMobile
21
+ }
@@ -1,82 +1,82 @@
1
- 'use client'
2
-
3
- import { useState, useMemo } from 'react'
4
- import {
5
- ColumnDef,
6
- ColumnFiltersState,
7
- SortingState,
8
- VisibilityState,
9
- getCoreRowModel,
10
- getFilteredRowModel,
11
- getPaginationRowModel,
12
- getSortedRowModel,
13
- useReactTable,
14
- TableOptions,
15
- } from '@tanstack/react-table'
16
-
17
- interface UseDataTableOptions<TData> {
18
- data: TData[]
19
- columns: ColumnDef<TData, unknown>[]
20
- initialPageSize?: number
21
- enableRowSelection?: boolean
22
- }
23
-
24
- export function useDataTable<TData>({
25
- data,
26
- columns,
27
- initialPageSize = 10,
28
- enableRowSelection = false,
29
- }: UseDataTableOptions<TData>) {
30
- const [sorting, setSorting] = useState<SortingState>([])
31
- const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([])
32
- const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({})
33
- const [rowSelection, setRowSelection] = useState({})
34
-
35
- const tableOptions: TableOptions<TData> = useMemo(
36
- () => ({
37
- data,
38
- columns,
39
- getCoreRowModel: getCoreRowModel(),
40
- getPaginationRowModel: getPaginationRowModel(),
41
- onSortingChange: setSorting,
42
- getSortedRowModel: getSortedRowModel(),
43
- onColumnFiltersChange: setColumnFilters,
44
- getFilteredRowModel: getFilteredRowModel(),
45
- onColumnVisibilityChange: setColumnVisibility,
46
- onRowSelectionChange: setRowSelection,
47
- enableRowSelection,
48
- state: {
49
- sorting,
50
- columnFilters,
51
- columnVisibility,
52
- rowSelection,
53
- },
54
- initialState: {
55
- pagination: {
56
- pageSize: initialPageSize,
57
- },
58
- },
59
- }),
60
- [data, columns, sorting, columnFilters, columnVisibility, rowSelection, enableRowSelection, initialPageSize]
61
- )
62
-
63
- const table = useReactTable(tableOptions)
64
-
65
- const selectedRows = useMemo(
66
- () => table.getFilteredSelectedRowModel().rows.map((row) => row.original),
67
- [table]
68
- )
69
-
70
- return {
71
- table,
72
- sorting,
73
- columnFilters,
74
- columnVisibility,
75
- rowSelection,
76
- selectedRows,
77
- setSorting,
78
- setColumnFilters,
79
- setColumnVisibility,
80
- setRowSelection,
81
- }
82
- }
1
+ 'use client'
2
+
3
+ import { useState, useMemo } from 'react'
4
+ import {
5
+ ColumnDef,
6
+ ColumnFiltersState,
7
+ SortingState,
8
+ VisibilityState,
9
+ getCoreRowModel,
10
+ getFilteredRowModel,
11
+ getPaginationRowModel,
12
+ getSortedRowModel,
13
+ useReactTable,
14
+ TableOptions,
15
+ } from '@tanstack/react-table'
16
+
17
+ interface UseDataTableOptions<TData> {
18
+ data: TData[]
19
+ columns: ColumnDef<TData, unknown>[]
20
+ initialPageSize?: number
21
+ enableRowSelection?: boolean
22
+ }
23
+
24
+ export function useDataTable<TData>({
25
+ data,
26
+ columns,
27
+ initialPageSize = 10,
28
+ enableRowSelection = false,
29
+ }: UseDataTableOptions<TData>) {
30
+ const [sorting, setSorting] = useState<SortingState>([])
31
+ const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([])
32
+ const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({})
33
+ const [rowSelection, setRowSelection] = useState({})
34
+
35
+ const tableOptions: TableOptions<TData> = useMemo(
36
+ () => ({
37
+ data,
38
+ columns,
39
+ getCoreRowModel: getCoreRowModel(),
40
+ getPaginationRowModel: getPaginationRowModel(),
41
+ onSortingChange: setSorting,
42
+ getSortedRowModel: getSortedRowModel(),
43
+ onColumnFiltersChange: setColumnFilters,
44
+ getFilteredRowModel: getFilteredRowModel(),
45
+ onColumnVisibilityChange: setColumnVisibility,
46
+ onRowSelectionChange: setRowSelection,
47
+ enableRowSelection,
48
+ state: {
49
+ sorting,
50
+ columnFilters,
51
+ columnVisibility,
52
+ rowSelection,
53
+ },
54
+ initialState: {
55
+ pagination: {
56
+ pageSize: initialPageSize,
57
+ },
58
+ },
59
+ }),
60
+ [data, columns, sorting, columnFilters, columnVisibility, rowSelection, enableRowSelection, initialPageSize]
61
+ )
62
+
63
+ const table = useReactTable(tableOptions)
64
+
65
+ const selectedRows = useMemo(
66
+ () => table.getFilteredSelectedRowModel().rows.map((row) => row.original),
67
+ [table]
68
+ )
69
+
70
+ return {
71
+ table,
72
+ sorting,
73
+ columnFilters,
74
+ columnVisibility,
75
+ rowSelection,
76
+ selectedRows,
77
+ setSorting,
78
+ setColumnFilters,
79
+ setColumnVisibility,
80
+ setRowSelection,
81
+ }
82
+ }
@@ -1,49 +1,49 @@
1
- 'use client'
2
-
3
- import { useEffect, useState, useCallback, useRef } from 'react'
4
-
5
- export function useDebounce<T>(value: T, delay: number): T {
6
- const [debouncedValue, setDebouncedValue] = useState<T>(value)
7
-
8
- useEffect(() => {
9
- const timer = setTimeout(() => {
10
- setDebouncedValue(value)
11
- }, delay)
12
-
13
- return () => {
14
- clearTimeout(timer)
15
- }
16
- }, [value, delay])
17
-
18
- return debouncedValue
19
- }
20
-
21
- export function useDebouncedCallback<T extends (...args: Parameters<T>) => ReturnType<T>>(
22
- callback: T,
23
- delay: number
24
- ): T {
25
- const timeoutRef = useRef<NodeJS.Timeout | null>(null)
26
-
27
- const debouncedCallback = useCallback(
28
- (...args: Parameters<T>) => {
29
- if (timeoutRef.current) {
30
- clearTimeout(timeoutRef.current)
31
- }
32
-
33
- timeoutRef.current = setTimeout(() => {
34
- callback(...args)
35
- }, delay)
36
- },
37
- [callback, delay]
38
- ) as T
39
-
40
- useEffect(() => {
41
- return () => {
42
- if (timeoutRef.current) {
43
- clearTimeout(timeoutRef.current)
44
- }
45
- }
46
- }, [])
47
-
48
- return debouncedCallback
49
- }
1
+ 'use client'
2
+
3
+ import { useEffect, useState, useCallback, useRef } from 'react'
4
+
5
+ export function useDebounce<T>(value: T, delay: number): T {
6
+ const [debouncedValue, setDebouncedValue] = useState<T>(value)
7
+
8
+ useEffect(() => {
9
+ const timer = setTimeout(() => {
10
+ setDebouncedValue(value)
11
+ }, delay)
12
+
13
+ return () => {
14
+ clearTimeout(timer)
15
+ }
16
+ }, [value, delay])
17
+
18
+ return debouncedValue
19
+ }
20
+
21
+ export function useDebouncedCallback<T extends (...args: Parameters<T>) => ReturnType<T>>(
22
+ callback: T,
23
+ delay: number
24
+ ): T {
25
+ const timeoutRef = useRef<NodeJS.Timeout | null>(null)
26
+
27
+ const debouncedCallback = useCallback(
28
+ (...args: Parameters<T>) => {
29
+ if (timeoutRef.current) {
30
+ clearTimeout(timeoutRef.current)
31
+ }
32
+
33
+ timeoutRef.current = setTimeout(() => {
34
+ callback(...args)
35
+ }, delay)
36
+ },
37
+ [callback, delay]
38
+ ) as T
39
+
40
+ useEffect(() => {
41
+ return () => {
42
+ if (timeoutRef.current) {
43
+ clearTimeout(timeoutRef.current)
44
+ }
45
+ }
46
+ }, [])
47
+
48
+ return debouncedCallback
49
+ }