responsive-system 1.1.4 → 1.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 (36) hide show
  1. package/package.json +5 -1
  2. package/scripts/postinstall.js +8 -1
  3. package/src/App.css +42 -0
  4. package/src/App.tsx +29 -0
  5. package/src/assets/react.svg +1 -0
  6. package/src/components/LayoutSwitcher.tsx +62 -0
  7. package/src/components/ResponsiveDemo.tsx +282 -0
  8. package/src/components/layout/Footer.tsx +90 -0
  9. package/src/components/layout/Header.tsx +105 -0
  10. package/src/components/layout/Navigation.tsx +96 -0
  11. package/src/components/layout/Sidebar.tsx +108 -0
  12. package/src/components/layout/index.ts +4 -0
  13. package/src/config/layout.ts +61 -0
  14. package/src/constants/breakpoints.ts +48 -0
  15. package/src/context/NavigationContext.tsx +32 -0
  16. package/src/context/ResponsiveLayoutContext.tsx +37 -0
  17. package/src/context/SidebarContext.tsx +26 -0
  18. package/src/context/index.ts +4 -0
  19. package/src/hooks/index.ts +4 -0
  20. package/src/hooks/useLayout.ts +27 -0
  21. package/src/hooks/useResponsive.ts +189 -0
  22. package/src/hooks/useResponsiveLayout.ts +51 -0
  23. package/src/index.css +1 -0
  24. package/src/index.ts +100 -0
  25. package/src/layouts/DashboardLayout.tsx +76 -0
  26. package/src/layouts/DefaultLayout.tsx +30 -0
  27. package/src/layouts/MainLayout.tsx +38 -0
  28. package/src/layouts/MinimalLayout.tsx +20 -0
  29. package/src/layouts/SidebarLayout.tsx +36 -0
  30. package/src/layouts/index.ts +5 -0
  31. package/src/main.tsx +10 -0
  32. package/src/pages/ResponsiveTestPage.tsx +400 -0
  33. package/src/providers/ResponsiveLayoutProvider.tsx +92 -0
  34. package/src/providers/ResponsiveProvider.tsx +18 -0
  35. package/src/providers/index.ts +3 -0
  36. package/src/types/responsive.ts +64 -0
@@ -0,0 +1,105 @@
1
+ import { useResponsiveLayout } from '../../hooks'
2
+ import { useNavigation, useSidebar } from '../../context'
3
+
4
+ const Header = () => {
5
+ const { isMobile } = useResponsiveLayout()
6
+ const { currentPage, setCurrentPage } = useNavigation()
7
+ const { sidebarOpen, setSidebarOpen } = useSidebar()
8
+
9
+ const menuItems = [
10
+ { id: 'test', label: 'Suite de Test' },
11
+ { id: 'demo', label: 'Demo' },
12
+ ]
13
+
14
+ return (
15
+ <div className="sticky top-0 z-50">
16
+ <header className="bg-gradient-to-r from-gray-900 via-black to-gray-900 border-b border-cyan-500/20 shadow-2xl relative">
17
+ <div className="w-full">
18
+ <div className="px-4 py-4">
19
+ <div className="flex items-center justify-between">
20
+ <div className="flex items-center space-x-2">
21
+ {/* Hamburger button para móvil - A LA IZQUIERDA */}
22
+ {isMobile && (
23
+ <button
24
+ onClick={() => setSidebarOpen(true)}
25
+ className="p-2 rounded-lg text-gray-300 hover:text-cyan-400 hover:bg-cyan-500/10 transition-colors"
26
+ >
27
+ <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
28
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
29
+ </svg>
30
+ </button>
31
+ )}
32
+
33
+ <div className="flex items-center space-x-2">
34
+ <div className="w-1.5 h-1.5 bg-cyan-400 rounded-full shadow-lg shadow-cyan-400/50 animate-pulse"></div>
35
+ <h3 className="text-base font-black text-white tracking-tight">
36
+ Sistema Responsivo
37
+ </h3>
38
+ </div>
39
+ <div className="px-2 py-0.5 text-cyan-400 font-mono bg-black/50 border border-cyan-500/30 rounded text-xs font-bold tracking-widest">
40
+ DASHBOARD
41
+ </div>
42
+ </div>
43
+
44
+ <div className="flex items-center space-x-2">
45
+ {/* Botones visibles solo en desktop */}
46
+ {!isMobile && menuItems.map((page) => (
47
+ <button
48
+ key={page.id}
49
+ onClick={() => setCurrentPage(page.id as 'demo' | 'test')}
50
+ className={`px-3 py-1.5 rounded-lg transition-all font-bold text-xs tracking-wide border ${
51
+ currentPage === page.id
52
+ ? 'bg-cyan-500/20 text-cyan-400 border-cyan-500/50'
53
+ : 'bg-black/50 text-gray-400 hover:text-gray-300 border-gray-700 hover:border-gray-600'
54
+ }`}
55
+ >
56
+ {page.label}
57
+ </button>
58
+ ))}
59
+ </div>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ </header>
64
+
65
+ {/* Sidebar móvil desplegable */}
66
+ {isMobile && sidebarOpen && (
67
+ <div className="fixed inset-0 z-40 bg-black/50" onClick={() => setSidebarOpen(false)}>
68
+ <div className="fixed top-0 left-0 w-64 h-full bg-gradient-to-b from-gray-900 to-black border-r border-cyan-500/20">
69
+ <div className="p-6 flex flex-col h-full pt-20">
70
+ {/* Logo */}
71
+ <div className="flex items-center space-x-3 mb-8">
72
+ <div className="w-8 h-8 bg-cyan-500 rounded-lg flex items-center justify-center">
73
+ <span className="text-white font-bold text-sm">RS</span>
74
+ </div>
75
+ <span className="text-white font-bold text-lg">Sistema Responsivo</span>
76
+ </div>
77
+
78
+ {/* Navigation */}
79
+ <nav className="space-y-2">
80
+ {menuItems.map((item) => (
81
+ <button
82
+ key={item.id}
83
+ onClick={() => {
84
+ setCurrentPage(item.id as 'demo' | 'test')
85
+ setSidebarOpen(false)
86
+ }}
87
+ className={`w-full flex items-center px-4 py-3 rounded-lg transition-all group text-left ${
88
+ currentPage === item.id
89
+ ? 'bg-cyan-500/20 text-cyan-400 border border-cyan-500/50'
90
+ : 'text-gray-300 hover:text-cyan-400 hover:bg-cyan-500/10'
91
+ }`}
92
+ >
93
+ <span className="font-medium">{item.label}</span>
94
+ </button>
95
+ ))}
96
+ </nav>
97
+ </div>
98
+ </div>
99
+ </div>
100
+ )}
101
+ </div>
102
+ )
103
+ }
104
+
105
+ export default Header
@@ -0,0 +1,96 @@
1
+ import { useState } from 'react'
2
+ import { useResponsiveLayout } from '../../hooks'
3
+ import { useNavigation } from '../../context'
4
+
5
+ const Navigation = () => {
6
+ const { isMobile, breakpoint } = useResponsiveLayout()
7
+ const { currentPage, setCurrentPage } = useNavigation()
8
+ const [sidebarOpen, setSidebarOpen] = useState(false)
9
+
10
+ const pages = [
11
+ { id: 'demo', name: 'Demo' },
12
+ { id: 'test', name: 'Suite de Test' }
13
+ ]
14
+
15
+ return (
16
+ <div className="sticky top-0 z-50">
17
+ <nav className="bg-gradient-to-r from-gray-900 via-black to-gray-900 border-b border-cyan-500/20 shadow-2xl relative">
18
+ <div className="w-full">
19
+ <div className="px-4 py-4">
20
+ <div className="flex items-center justify-between">
21
+ <div className="flex items-center space-x-2">
22
+ <div className="flex items-center space-x-2">
23
+ <div className="w-1.5 h-1.5 bg-cyan-400 rounded-full shadow-lg shadow-cyan-400/50 animate-pulse"></div>
24
+ <h3 className="text-base font-black text-white tracking-tight">
25
+ Sistema Responsivo
26
+ </h3>
27
+ </div>
28
+ <div className="px-2 py-0.5 text-cyan-400 font-mono bg-black/50 border border-cyan-500/30 rounded text-xs font-bold tracking-widest">
29
+ {breakpoint.toUpperCase()}
30
+ </div>
31
+ </div>
32
+
33
+ <div className="flex items-center space-x-2">
34
+ {/* Botones visibles solo en desktop */}
35
+ {!isMobile && pages.map(page => (
36
+ <button
37
+ key={page.id}
38
+ onClick={() => setCurrentPage(page.id as 'demo' | 'test')}
39
+ className={`px-3 py-1.5 rounded-lg transition-all font-bold text-xs tracking-wide border ${
40
+ currentPage === page.id
41
+ ? 'bg-cyan-500/20 text-cyan-400 border-cyan-500/50'
42
+ : 'bg-black/50 text-gray-400 hover:text-gray-300 border-gray-700 hover:border-gray-600'
43
+ }`}
44
+ >
45
+ {page.name}
46
+ </button>
47
+ ))}
48
+
49
+ {/* Menú hamburguesa para móvil - A LA DERECHA */}
50
+ {isMobile && (
51
+ <button
52
+ onClick={() => setSidebarOpen(!sidebarOpen)}
53
+ className="p-2 rounded-lg text-gray-300 hover:text-cyan-400 hover:bg-cyan-500/10 transition-colors"
54
+ >
55
+ <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
56
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
57
+ </svg>
58
+ </button>
59
+ )}
60
+ </div>
61
+ </div>
62
+ </div>
63
+ </div>
64
+
65
+ {/* Menú móvil desplegable - TRADICIONAL */}
66
+ {isMobile && sidebarOpen && (
67
+ <div className="absolute top-full left-0 right-0 bg-gradient-to-r from-gray-900 via-black to-gray-900 border-b border-cyan-500/20 shadow-2xl z-50">
68
+ <div className="p-4">
69
+ {/* Navigation - VERTICAL como menú tradicional */}
70
+ <nav className="space-y-2">
71
+ {pages.map((page) => (
72
+ <button
73
+ key={page.id}
74
+ onClick={() => {
75
+ setCurrentPage(page.id as 'demo' | 'test')
76
+ setSidebarOpen(false)
77
+ }}
78
+ className={`w-full text-left px-4 py-3 rounded-lg transition-all font-bold text-sm tracking-wide border ${
79
+ currentPage === page.id
80
+ ? 'bg-cyan-500/20 text-cyan-400 border-cyan-500/50'
81
+ : 'bg-black/50 text-gray-400 hover:text-gray-300 border-gray-700 hover:border-gray-600'
82
+ }`}
83
+ >
84
+ {page.name}
85
+ </button>
86
+ ))}
87
+ </nav>
88
+ </div>
89
+ </div>
90
+ )}
91
+ </nav>
92
+ </div>
93
+ )
94
+ }
95
+
96
+ export default Navigation
@@ -0,0 +1,108 @@
1
+ import { useResponsiveLayout } from '../../hooks'
2
+ import { useNavigation, useSidebar } from '../../context'
3
+
4
+ const Sidebar = () => {
5
+ const { isMobile, isTablet, breakpoint } = useResponsiveLayout()
6
+ const { currentPage, setCurrentPage } = useNavigation()
7
+ const { sidebarOpen, setSidebarOpen } = useSidebar()
8
+
9
+ const menuItems = [
10
+ { id: 'test', label: 'Suite de Test' },
11
+ { id: 'demo', label: 'Demo' },
12
+ ]
13
+
14
+ return (
15
+ <>
16
+ {/* Hamburger button para móvil */}
17
+ {isMobile && (
18
+ <button
19
+ onClick={() => setSidebarOpen(true)}
20
+ className="fixed top-4 left-4 z-50 p-2 rounded-lg text-gray-300 hover:text-cyan-400 hover:bg-cyan-500/10 transition-colors bg-black/50 border border-gray-700"
21
+ >
22
+ <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
23
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
24
+ </svg>
25
+ </button>
26
+ )}
27
+
28
+ {/* Sidebar desktop */}
29
+ <aside className={`
30
+ bg-gradient-to-b from-gray-900 to-black border-r border-cyan-500/20
31
+ ${isMobile ? 'hidden' : 'w-64 flex-shrink-0'}
32
+ ${isTablet ? 'w-56' : 'w-64'}
33
+ `}>
34
+ <div className="p-6 flex flex-col h-full">
35
+ {/* Logo y Breakpoint */}
36
+ <div className="flex items-center space-x-3 mb-8">
37
+ <div className="w-8 h-8 bg-cyan-500 rounded-lg flex items-center justify-center">
38
+ <span className="text-white font-bold text-sm">RS</span>
39
+ </div>
40
+ <div>
41
+ <span className="text-white font-bold text-lg">Sistema Responsivo</span>
42
+ <div className="px-2 py-0.5 text-cyan-400 font-mono bg-black/50 border border-cyan-500/30 rounded text-xs font-bold tracking-widest mt-1">
43
+ {breakpoint.toUpperCase()}
44
+ </div>
45
+ </div>
46
+ </div>
47
+
48
+ {/* Navigation */}
49
+ <nav className="space-y-2">
50
+ {menuItems.map((item) => (
51
+ <button
52
+ key={item.id}
53
+ onClick={() => setCurrentPage(item.id as 'demo' | 'test')}
54
+ className={`w-full flex items-center px-4 py-3 rounded-lg transition-all group text-left ${
55
+ currentPage === item.id
56
+ ? 'bg-cyan-500/20 text-cyan-400 border border-cyan-500/50'
57
+ : 'text-gray-300 hover:text-cyan-400 hover:bg-cyan-500/10'
58
+ }`}
59
+ >
60
+ <span className="font-medium">{item.label}</span>
61
+ </button>
62
+ ))}
63
+ </nav>
64
+
65
+ </div>
66
+ </aside>
67
+
68
+ {/* Sidebar móvil desplegable */}
69
+ {isMobile && sidebarOpen && (
70
+ <div className="fixed inset-0 z-40 bg-black/50" onClick={() => setSidebarOpen(false)}>
71
+ <div className="fixed top-0 left-0 w-64 h-full bg-gradient-to-b from-gray-900 to-black border-r border-cyan-500/20">
72
+ <div className="p-6 flex flex-col h-full pt-20">
73
+ {/* Logo */}
74
+ <div className="flex items-center space-x-3 mb-8">
75
+ <div className="w-8 h-8 bg-cyan-500 rounded-lg flex items-center justify-center">
76
+ <span className="text-white font-bold text-sm">RS</span>
77
+ </div>
78
+ <span className="text-white font-bold text-lg">Sistema Responsivo</span>
79
+ </div>
80
+
81
+ {/* Navigation */}
82
+ <nav className="space-y-2">
83
+ {menuItems.map((item) => (
84
+ <button
85
+ key={item.id}
86
+ onClick={() => {
87
+ setCurrentPage(item.id as 'demo' | 'test')
88
+ setSidebarOpen(false)
89
+ }}
90
+ className={`w-full flex items-center px-4 py-3 rounded-lg transition-all group text-left ${
91
+ currentPage === item.id
92
+ ? 'bg-cyan-500/20 text-cyan-400 border border-cyan-500/50'
93
+ : 'text-gray-300 hover:text-cyan-400 hover:bg-cyan-500/10'
94
+ }`}
95
+ >
96
+ <span className="font-medium">{item.label}</span>
97
+ </button>
98
+ ))}
99
+ </nav>
100
+ </div>
101
+ </div>
102
+ </div>
103
+ )}
104
+ </>
105
+ )
106
+ }
107
+
108
+ export default Sidebar
@@ -0,0 +1,4 @@
1
+ export { default as Header } from './Header'
2
+ export { default as Sidebar } from './Sidebar'
3
+ export { default as Footer } from './Footer'
4
+ export { default as Navigation } from './Navigation'
@@ -0,0 +1,61 @@
1
+ export interface LayoutConfig {
2
+ name: string
3
+ description: string
4
+ components: string[]
5
+ spacing: string
6
+ responsive: {
7
+ mobile: string
8
+ tablet: string
9
+ desktop: string
10
+ }
11
+ }
12
+
13
+ export const LAYOUT_CONFIG: Record<string, LayoutConfig> = {
14
+ default: {
15
+ name: 'Default',
16
+ description: 'Navbar arriba, body central, footer abajo',
17
+ components: ['Navigation', 'Footer'],
18
+ spacing: 'p-4 md:p-6 lg:p-8',
19
+ responsive: {
20
+ mobile: 'p-4',
21
+ tablet: 'p-6',
22
+ desktop: 'p-8'
23
+ }
24
+ },
25
+ sidebar: {
26
+ name: 'Sidebar',
27
+ description: 'Sidebar izquierda, contenido principal',
28
+ components: ['Sidebar'],
29
+ spacing: 'p-4 md:p-6',
30
+ responsive: {
31
+ mobile: 'p-4',
32
+ tablet: 'p-6',
33
+ desktop: 'p-6'
34
+ }
35
+ },
36
+ dashboard: {
37
+ name: 'Dashboard',
38
+ description: 'Header + Sidebar + Main + Footer',
39
+ components: ['Header', 'Sidebar', 'Footer'],
40
+ spacing: 'p-4 md:p-6 lg:p-8',
41
+ responsive: {
42
+ mobile: 'p-4',
43
+ tablet: 'p-6',
44
+ desktop: 'p-8'
45
+ }
46
+ },
47
+ minimal: {
48
+ name: 'Minimal',
49
+ description: 'Solo contenido, sin navegación',
50
+ components: [],
51
+ spacing: 'p-4 md:p-6',
52
+ responsive: {
53
+ mobile: 'p-4',
54
+ tablet: 'p-6',
55
+ desktop: 'p-6'
56
+ }
57
+ }
58
+ }
59
+
60
+ export const DEFAULT_LAYOUT = 'default'
61
+ export const AVAILABLE_LAYOUTS = Object.keys(LAYOUT_CONFIG)
@@ -0,0 +1,48 @@
1
+ import type { Breakpoint } from '../types/responsive'
2
+
3
+ /**
4
+ * Default breakpoint values
5
+ * Deben coincidir con tailwind.config.js
6
+ */
7
+ export const DEFAULT_BREAKPOINTS: Record<Breakpoint, number> = {
8
+ xs: 475,
9
+ sm: 640,
10
+ md: 768,
11
+ lg: 1024,
12
+ xl: 1280,
13
+ '2xl': 1536,
14
+ '3xl': 1920,
15
+ '4xl': 2560,
16
+ '5xl': 3840
17
+ }
18
+
19
+ /**
20
+ * Get current breakpoint based on window width
21
+ */
22
+ export const getCurrentBreakpoint = (width: number): Breakpoint => {
23
+ if (width >= DEFAULT_BREAKPOINTS['5xl']) return '5xl'
24
+ if (width >= DEFAULT_BREAKPOINTS['4xl']) return '4xl'
25
+ if (width >= DEFAULT_BREAKPOINTS['3xl']) return '3xl'
26
+ if (width >= DEFAULT_BREAKPOINTS['2xl']) return '2xl'
27
+ if (width >= DEFAULT_BREAKPOINTS.xl) return 'xl'
28
+ if (width >= DEFAULT_BREAKPOINTS.lg) return 'lg'
29
+ if (width >= DEFAULT_BREAKPOINTS.md) return 'md'
30
+ if (width >= DEFAULT_BREAKPOINTS.sm) return 'sm'
31
+ return 'xs'
32
+ }
33
+
34
+ /**
35
+ * Get breakpoint index (for comparisons)
36
+ */
37
+ export const getBreakpointIndex = (breakpoint: Breakpoint): number => {
38
+ const breakpoints: Breakpoint[] = ['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl', '5xl']
39
+ return breakpoints.indexOf(breakpoint)
40
+ }
41
+
42
+ /**
43
+ * Get breakpoint value in pixels
44
+ */
45
+ export const getBreakpointValue = (breakpoint: Breakpoint): number => {
46
+ return DEFAULT_BREAKPOINTS[breakpoint]
47
+ }
48
+
@@ -0,0 +1,32 @@
1
+ import React, { createContext, useContext, useState } from 'react'
2
+
3
+ interface NavigationContextType {
4
+ currentPage: 'demo' | 'test'
5
+ setCurrentPage: (page: 'demo' | 'test') => void
6
+ }
7
+
8
+ const NavigationContext = createContext<NavigationContextType>({
9
+ currentPage: 'test',
10
+ setCurrentPage: () => {}
11
+ })
12
+
13
+ export const useNavigation = () => useContext(NavigationContext)
14
+
15
+ interface NavigationProviderProps {
16
+ children: React.ReactNode
17
+ defaultPage?: 'demo' | 'test'
18
+ }
19
+
20
+ export const NavigationProvider: React.FC<NavigationProviderProps> = ({
21
+ children,
22
+ defaultPage = 'test'
23
+ }) => {
24
+ const [currentPage, setCurrentPage] = useState<'demo' | 'test'>(defaultPage)
25
+
26
+ return (
27
+ <NavigationContext.Provider value={{ currentPage, setCurrentPage }}>
28
+ {children}
29
+ </NavigationContext.Provider>
30
+ )
31
+ }
32
+
@@ -0,0 +1,37 @@
1
+ import { createContext, useContext } from 'react'
2
+ import type { ResponsiveState } from '../types/responsive'
3
+ import type { LayoutConfig } from '../config/layout'
4
+
5
+ export interface ResponsiveLayoutState {
6
+ // Estado del sistema responsivo
7
+ responsive: ResponsiveState
8
+
9
+ // Estado del layout
10
+ layout: {
11
+ current: string
12
+ config: LayoutConfig
13
+ setLayout: (layout: string) => void
14
+ }
15
+
16
+ // Utilidades de layout
17
+ layoutUtils: {
18
+ getContainerClass: () => string
19
+ getMainClass: () => string
20
+ hasSidebar: () => boolean
21
+ hasHeader: () => boolean
22
+ hasFooter: () => boolean
23
+ hasNavigation: () => boolean
24
+ }
25
+ }
26
+
27
+ const ResponsiveLayoutContext = createContext<ResponsiveLayoutState | undefined>(undefined)
28
+
29
+ export const useResponsiveLayoutContext = () => {
30
+ const context = useContext(ResponsiveLayoutContext)
31
+ if (!context) {
32
+ throw new Error('useResponsiveLayoutContext must be used within a ResponsiveLayoutProvider')
33
+ }
34
+ return context
35
+ }
36
+
37
+ export { ResponsiveLayoutContext }
@@ -0,0 +1,26 @@
1
+ import React, { createContext, useContext, useState } from 'react'
2
+
3
+ interface SidebarContextType {
4
+ sidebarOpen: boolean
5
+ setSidebarOpen: (open: boolean) => void
6
+ }
7
+
8
+ const SidebarContext = createContext<SidebarContextType | undefined>(undefined)
9
+
10
+ export const SidebarProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
11
+ const [sidebarOpen, setSidebarOpen] = useState(false)
12
+
13
+ return (
14
+ <SidebarContext.Provider value={{ sidebarOpen, setSidebarOpen }}>
15
+ {children}
16
+ </SidebarContext.Provider>
17
+ )
18
+ }
19
+
20
+ export const useSidebar = () => {
21
+ const context = useContext(SidebarContext)
22
+ if (!context) {
23
+ throw new Error('useSidebar must be used within a SidebarProvider')
24
+ }
25
+ return context
26
+ }
@@ -0,0 +1,4 @@
1
+ export { ResponsiveLayoutContext, useResponsiveLayoutContext } from './ResponsiveLayoutContext'
2
+ export { SidebarProvider, useSidebar } from './SidebarContext'
3
+ export { NavigationProvider, useNavigation } from './NavigationContext'
4
+
@@ -0,0 +1,4 @@
1
+ export { useResponsive } from './useResponsive'
2
+ export { useResponsiveLayout } from './useResponsiveLayout'
3
+ export { useLayout } from './useLayout'
4
+
@@ -0,0 +1,27 @@
1
+ import { useResponsiveLayout } from './index'
2
+
3
+ export const useLayout = () => {
4
+ const responsiveLayout = useResponsiveLayout()
5
+
6
+ return {
7
+ // Layout actual
8
+ current: responsiveLayout.layout.current,
9
+ config: responsiveLayout.layout.config,
10
+ setLayout: responsiveLayout.layout.setLayout,
11
+
12
+ // Utilidades
13
+ ...responsiveLayout.layoutUtils,
14
+
15
+ // Helpers específicos
16
+ isDefaultLayout: responsiveLayout.isDefaultLayout(),
17
+ isSidebarLayout: responsiveLayout.isSidebarLayout(),
18
+ isDashboardLayout: responsiveLayout.isDashboardLayout(),
19
+ isMinimalLayout: responsiveLayout.isMinimalLayout(),
20
+
21
+ // Grid helpers
22
+ grid: responsiveLayout.grid,
23
+
24
+ // Spacing helpers
25
+ spacing: responsiveLayout.spacing,
26
+ }
27
+ }