responsive-system 1.1.5 → 1.2.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.
- package/package.json +2 -1
- package/scripts/postinstall.js +2 -3
- package/src/App.css +42 -0
- package/src/App.tsx +29 -0
- package/src/assets/react.svg +1 -0
- package/src/components/LayoutSwitcher.tsx +62 -0
- package/src/components/ResponsiveDemo.tsx +282 -0
- package/src/components/layout/Footer.tsx +90 -0
- package/src/components/layout/Header.tsx +105 -0
- package/src/components/layout/Navigation.tsx +96 -0
- package/src/components/layout/Sidebar.tsx +108 -0
- package/src/components/layout/index.ts +4 -0
- package/src/config/layout.ts +61 -0
- package/src/constants/breakpoints.ts +48 -0
- package/src/context/NavigationContext.tsx +32 -0
- package/src/context/ResponsiveLayoutContext.tsx +37 -0
- package/src/context/SidebarContext.tsx +26 -0
- package/src/context/index.ts +4 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/useLayout.ts +27 -0
- package/src/hooks/useResponsive.ts +189 -0
- package/src/hooks/useResponsiveLayout.ts +51 -0
- package/src/index.css +1 -0
- package/src/index.ts +100 -0
- package/src/layouts/DashboardLayout.tsx +76 -0
- package/src/layouts/DefaultLayout.tsx +30 -0
- package/src/layouts/MainLayout.tsx +38 -0
- package/src/layouts/MinimalLayout.tsx +20 -0
- package/src/layouts/SidebarLayout.tsx +36 -0
- package/src/layouts/index.ts +5 -0
- package/src/main.tsx +10 -0
- package/src/pages/ResponsiveTestPage.tsx +400 -0
- package/src/providers/ResponsiveLayoutProvider.tsx +92 -0
- package/src/providers/ResponsiveProvider.tsx +18 -0
- package/src/providers/index.ts +3 -0
- package/src/types/responsive.ts +64 -0
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
import { useResponsiveLayout } from '../hooks'
|
|
2
|
+
import LayoutSwitcher from '../components/LayoutSwitcher'
|
|
3
|
+
|
|
4
|
+
// Componente de indicador de breakpoint
|
|
5
|
+
const BreakpointIndicator = () => {
|
|
6
|
+
const { breakpoint, width, height, orientation, debug } = useResponsiveLayout()
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<div className="fixed bottom-4 left-1/2 transform -translate-x-1/2 z-50">
|
|
10
|
+
<div className="bg-black/90 backdrop-blur-sm text-white rounded-full shadow-xl border border-white/20 px-6 py-3 flex items-center space-x-4 min-w-max">
|
|
11
|
+
<span className="font-bold text-blue-300 text-sm">Breakpoint: {breakpoint}</span>
|
|
12
|
+
<span className="text-green-300 text-sm">{width}×{height}</span>
|
|
13
|
+
<span className="text-purple-300 text-sm">{orientation}</span>
|
|
14
|
+
{debug && <span className="text-yellow-300 font-semibold text-sm">Debug</span>}
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Componente de test de helpers booleanos
|
|
21
|
+
const BooleanHelpersTest = () => {
|
|
22
|
+
const {
|
|
23
|
+
isXs, isSm, isMd, isLg, isXl, is2Xl, is3Xl, is4Xl, is5Xl,
|
|
24
|
+
isMobile, isTablet, isDesktop, isSmall, isLarge, isUltraWide, is4K, is5K
|
|
25
|
+
} = useResponsiveLayout()
|
|
26
|
+
|
|
27
|
+
const helpers = [
|
|
28
|
+
{ name: 'isXs', value: isXs },
|
|
29
|
+
{ name: 'isSm', value: isSm },
|
|
30
|
+
{ name: 'isMd', value: isMd },
|
|
31
|
+
{ name: 'isLg', value: isLg },
|
|
32
|
+
{ name: 'isXl', value: isXl },
|
|
33
|
+
{ name: 'is2Xl', value: is2Xl },
|
|
34
|
+
{ name: 'is3Xl', value: is3Xl },
|
|
35
|
+
{ name: 'is4Xl', value: is4Xl },
|
|
36
|
+
{ name: 'is5Xl', value: is5Xl },
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
const groupedHelpers = [
|
|
40
|
+
{ name: 'isMobile', value: isMobile },
|
|
41
|
+
{ name: 'isTablet', value: isTablet },
|
|
42
|
+
{ name: 'isDesktop', value: isDesktop },
|
|
43
|
+
{ name: 'isSmall', value: isSmall },
|
|
44
|
+
{ name: 'isLarge', value: isLarge },
|
|
45
|
+
{ name: 'isUltraWide', value: isUltraWide },
|
|
46
|
+
{ name: 'is4K', value: is4K },
|
|
47
|
+
{ name: 'is5K', value: is5K },
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<div className="space-y-6">
|
|
52
|
+
<h2 className="text-3xl font-black text-white mb-2 tracking-tight">Boolean Helpers</h2>
|
|
53
|
+
<div className="w-8 h-0.5 bg-cyan-400 mb-4"></div>
|
|
54
|
+
|
|
55
|
+
<div>
|
|
56
|
+
<h4 className="text-sm font-bold mb-3 text-gray-500 tracking-widest uppercase">Specific Breakpoints</h4>
|
|
57
|
+
<div className="grid grid-cols-3 gap-2">
|
|
58
|
+
{helpers.map(helper => (
|
|
59
|
+
<div
|
|
60
|
+
key={helper.name}
|
|
61
|
+
className={`p-4 rounded-lg text-center min-h-[60px] flex flex-col justify-center border transition-all ${
|
|
62
|
+
helper.value
|
|
63
|
+
? 'bg-cyan-500/10 text-cyan-400 border-cyan-500/30'
|
|
64
|
+
: 'bg-black/30 text-gray-600 border-gray-800'
|
|
65
|
+
}`}
|
|
66
|
+
>
|
|
67
|
+
<div className="font-bold break-words text-sm">{helper.name}</div>
|
|
68
|
+
<div className="text-lg font-black mt-1">{helper.value ? '●' : '○'}</div>
|
|
69
|
+
</div>
|
|
70
|
+
))}
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<div>
|
|
75
|
+
<h4 className="text-sm font-bold mb-3 text-gray-500 tracking-widest uppercase">Grouped Helpers</h4>
|
|
76
|
+
<div className="grid grid-cols-2 sm:grid-cols-4 gap-2">
|
|
77
|
+
{groupedHelpers.map(helper => (
|
|
78
|
+
<div
|
|
79
|
+
key={helper.name}
|
|
80
|
+
className={`p-4 rounded-lg text-center min-h-[60px] flex flex-col justify-center border transition-all ${
|
|
81
|
+
helper.value
|
|
82
|
+
? 'bg-cyan-500/10 text-cyan-400 border-cyan-500/30'
|
|
83
|
+
: 'bg-black/30 text-gray-600 border-gray-800'
|
|
84
|
+
}`}
|
|
85
|
+
>
|
|
86
|
+
<div className="font-bold break-words text-sm">{helper.name}</div>
|
|
87
|
+
<div className="text-lg font-black mt-1">{helper.value ? '●' : '○'}</div>
|
|
88
|
+
</div>
|
|
89
|
+
))}
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Componente de test de comparaciones
|
|
97
|
+
const ComparisonTest = () => {
|
|
98
|
+
const {
|
|
99
|
+
isBreakpointUp,
|
|
100
|
+
isBreakpointDown,
|
|
101
|
+
isBreakpointBetween,
|
|
102
|
+
isWidthUp,
|
|
103
|
+
isWidthDown,
|
|
104
|
+
isWidthBetween
|
|
105
|
+
} = useResponsiveLayout()
|
|
106
|
+
|
|
107
|
+
const tests = [
|
|
108
|
+
{ name: 'isBreakpointUp("md")', value: isBreakpointUp('md') },
|
|
109
|
+
{ name: 'isBreakpointDown("lg")', value: isBreakpointDown('lg') },
|
|
110
|
+
{ name: 'isBreakpointBetween("sm", "xl")', value: isBreakpointBetween('sm', 'xl') },
|
|
111
|
+
{ name: 'isWidthUp(1024)', value: isWidthUp(1024) },
|
|
112
|
+
{ name: 'isWidthDown(768)', value: isWidthDown(768) },
|
|
113
|
+
{ name: 'isWidthBetween(500, 1200)', value: isWidthBetween(500, 1200) },
|
|
114
|
+
]
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<div className="space-y-6">
|
|
118
|
+
<h2 className="text-3xl font-black text-white mb-2 tracking-tight">Comparison Functions</h2>
|
|
119
|
+
<div className="w-8 h-0.5 bg-gray-700 mb-4"></div>
|
|
120
|
+
<div className="grid grid-cols-auto-md gap-3">
|
|
121
|
+
{tests.map(test => (
|
|
122
|
+
<div
|
|
123
|
+
key={test.name}
|
|
124
|
+
className={`p-4 rounded-lg border min-h-[80px] flex flex-col justify-center transition-all ${
|
|
125
|
+
test.value
|
|
126
|
+
? 'bg-cyan-500/10 text-cyan-400 border-cyan-500/30'
|
|
127
|
+
: 'bg-black/30 text-gray-600 border-gray-800'
|
|
128
|
+
}`}
|
|
129
|
+
>
|
|
130
|
+
<p className="font-mono text-xs mb-2 break-words">
|
|
131
|
+
{test.name}
|
|
132
|
+
</p>
|
|
133
|
+
<p className="text-lg font-black">{test.value ? 'TRUE' : 'FALSE'}</p>
|
|
134
|
+
</div>
|
|
135
|
+
))}
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Componente de test de utilidades de Tailwind
|
|
142
|
+
const TailwindUtilsTest = () => {
|
|
143
|
+
return (
|
|
144
|
+
<div className="space-y-6">
|
|
145
|
+
<h2 className="text-3xl font-black text-white mb-2 tracking-tight">Auto-Scale Properties</h2>
|
|
146
|
+
<div className="w-8 h-0.5 bg-cyan-400 mb-6"></div>
|
|
147
|
+
|
|
148
|
+
{/* Fila 1: Grid Auto-responsive y Line Height */}
|
|
149
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
150
|
+
|
|
151
|
+
{/* Grid Auto-responsive */}
|
|
152
|
+
<div>
|
|
153
|
+
<h4 className="text-lg font-semibold mb-4 text-cyan-400">Grid Auto-responsive</h4>
|
|
154
|
+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
|
|
155
|
+
{[1, 2, 3, 4, 5, 6].map(i => (
|
|
156
|
+
<div key={i} className="p-4 bg-black/30 rounded-lg text-center text-sm border border-gray-700 hover:border-cyan-500/30 transition-all">
|
|
157
|
+
<p className="text-gray-300 font-medium">Card {i}</p>
|
|
158
|
+
</div>
|
|
159
|
+
))}
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
|
|
163
|
+
{/* Line Height */}
|
|
164
|
+
<div>
|
|
165
|
+
<h4 className="text-lg font-semibold mb-4 text-cyan-400">Line Height (Auto-scale)</h4>
|
|
166
|
+
<div className="space-y-4">
|
|
167
|
+
<div className="bg-black/30 p-4 rounded-lg border border-gray-700">
|
|
168
|
+
<p className="text-base leading-relaxed text-gray-300">
|
|
169
|
+
Este párrafo usa <code className="bg-cyan-500/20 text-cyan-400 px-1 rounded">leading-relaxed</code>.
|
|
170
|
+
El line-height escala automáticamente para mejor legibilidad.
|
|
171
|
+
</p>
|
|
172
|
+
</div>
|
|
173
|
+
<div className="bg-black/30 p-4 rounded-lg border border-gray-700">
|
|
174
|
+
<p className="text-base leading-loose text-gray-300">
|
|
175
|
+
Este párrafo usa <code className="bg-cyan-500/20 text-cyan-400 px-1 rounded">leading-loose</code>.
|
|
176
|
+
Con espaciado mayor que se adapta a cada pantalla.
|
|
177
|
+
</p>
|
|
178
|
+
</div>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
|
|
183
|
+
{/* Fila 2: Letter Spacing y Shadows */}
|
|
184
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
185
|
+
|
|
186
|
+
{/* Letter Spacing */}
|
|
187
|
+
<div>
|
|
188
|
+
<h4 className="text-lg font-semibold mb-4 text-cyan-400">Letter Spacing (Auto-scale)</h4>
|
|
189
|
+
<div className="space-y-3">
|
|
190
|
+
<div className="bg-black/30 p-4 rounded-lg border border-gray-700">
|
|
191
|
+
<p className="text-base tracking-tight text-gray-300">
|
|
192
|
+
<code className="bg-cyan-500/20 text-cyan-400 px-1 rounded">tracking-tight</code> - Texto compacto
|
|
193
|
+
</p>
|
|
194
|
+
</div>
|
|
195
|
+
<div className="bg-black/30 p-4 rounded-lg border border-gray-700">
|
|
196
|
+
<p className="text-base tracking-normal text-gray-300">
|
|
197
|
+
<code className="bg-cyan-500/20 text-cyan-400 px-1 rounded">tracking-normal</code> - Espaciado normal
|
|
198
|
+
</p>
|
|
199
|
+
</div>
|
|
200
|
+
<div className="bg-black/30 p-4 rounded-lg border border-gray-700">
|
|
201
|
+
<p className="text-base tracking-wide text-gray-300">
|
|
202
|
+
<code className="bg-cyan-500/20 text-cyan-400 px-1 rounded">tracking-wide</code> - Espaciado amplio
|
|
203
|
+
</p>
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
</div>
|
|
207
|
+
|
|
208
|
+
{/* Shadows */}
|
|
209
|
+
<div>
|
|
210
|
+
<h4 className="text-lg font-semibold mb-4 text-cyan-400">Shadows (Auto-scale)</h4>
|
|
211
|
+
<div className="grid grid-cols-2 gap-3">
|
|
212
|
+
<div className="p-4 bg-black/30 shadow-sm rounded-lg text-center border border-gray-700">
|
|
213
|
+
<p className="text-sm font-medium text-gray-300">shadow-sm</p>
|
|
214
|
+
</div>
|
|
215
|
+
<div className="p-4 bg-black/30 shadow-md rounded-lg text-center border border-gray-700">
|
|
216
|
+
<p className="text-sm font-medium text-gray-300">shadow-md</p>
|
|
217
|
+
</div>
|
|
218
|
+
<div className="p-4 bg-black/30 shadow-lg rounded-lg text-center border border-gray-700">
|
|
219
|
+
<p className="text-sm font-medium text-gray-300">shadow-lg</p>
|
|
220
|
+
</div>
|
|
221
|
+
<div className="p-4 bg-black/30 shadow-xl rounded-lg text-center border border-gray-700">
|
|
222
|
+
<p className="text-sm font-medium text-gray-300">shadow-xl</p>
|
|
223
|
+
</div>
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
</div>
|
|
227
|
+
|
|
228
|
+
{/* Fila 3: Buttons */}
|
|
229
|
+
<div>
|
|
230
|
+
<h4 className="text-lg font-semibold mb-4 text-cyan-400">Buttons (Auto-scale)</h4>
|
|
231
|
+
<div className="flex flex-wrap gap-4">
|
|
232
|
+
<button className="px-6 py-3 bg-cyan-500 text-white rounded-lg hover:bg-cyan-600 transition-colors font-semibold">
|
|
233
|
+
Button Normal
|
|
234
|
+
</button>
|
|
235
|
+
<button className="px-8 py-4 bg-gray-700 text-white rounded-lg hover:bg-gray-600 transition-colors font-semibold">
|
|
236
|
+
Button Grande
|
|
237
|
+
</button>
|
|
238
|
+
<button className="px-4 py-2 bg-gray-800 text-gray-300 rounded-lg hover:bg-gray-700 transition-colors text-sm">
|
|
239
|
+
Button Pequeño
|
|
240
|
+
</button>
|
|
241
|
+
</div>
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Componente de test de orientación
|
|
248
|
+
const OrientationTest = () => {
|
|
249
|
+
const { orientation, isPortrait, isLandscape } = useResponsiveLayout()
|
|
250
|
+
|
|
251
|
+
return (
|
|
252
|
+
<div className="space-y-4">
|
|
253
|
+
<h2 className="text-3xl font-black text-white mb-2 tracking-tight">Orientation</h2>
|
|
254
|
+
<div className="w-8 h-0.5 bg-cyan-400 mb-6"></div>
|
|
255
|
+
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
|
256
|
+
<div className="p-6 bg-black/30 rounded-lg border border-gray-700 text-center">
|
|
257
|
+
<p className="font-semibold text-cyan-400 text-lg mb-2">Current</p>
|
|
258
|
+
<p className="text-gray-300 text-base">{orientation}</p>
|
|
259
|
+
</div>
|
|
260
|
+
<div className="p-6 bg-black/30 rounded-lg border border-gray-700 text-center">
|
|
261
|
+
<p className="font-semibold text-cyan-400 text-lg mb-2">Portrait</p>
|
|
262
|
+
<p className="text-gray-300 text-base">{isPortrait ? '●' : '○'}</p>
|
|
263
|
+
</div>
|
|
264
|
+
<div className="p-6 bg-black/30 rounded-lg border border-gray-700 text-center">
|
|
265
|
+
<p className="font-semibold text-cyan-400 text-lg mb-2">Landscape</p>
|
|
266
|
+
<p className="text-gray-300 text-base">{isLandscape ? '●' : '○'}</p>
|
|
267
|
+
</div>
|
|
268
|
+
</div>
|
|
269
|
+
</div>
|
|
270
|
+
)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Componente de test de grid
|
|
274
|
+
const GridTest = () => {
|
|
275
|
+
return (
|
|
276
|
+
<div className="space-y-4">
|
|
277
|
+
<h2 className="text-3xl font-black text-white mb-2 tracking-tight">Grid System</h2>
|
|
278
|
+
<div className="w-8 h-0.5 bg-cyan-400 mb-4"></div>
|
|
279
|
+
|
|
280
|
+
<div>
|
|
281
|
+
<h4 className="text-lg font-semibold mb-2 text-gray-700">Auto-responsive Grid</h4>
|
|
282
|
+
<div className="grid grid-cols-auto-sm gap-4">
|
|
283
|
+
{[1, 2, 3, 4, 5, 6].map(i => (
|
|
284
|
+
<div key={i} className="p-6 bg-indigo-100 rounded-lg text-center border border-indigo-200">
|
|
285
|
+
<p className="font-bold text-indigo-800 text-base">Item {i}</p>
|
|
286
|
+
</div>
|
|
287
|
+
))}
|
|
288
|
+
</div>
|
|
289
|
+
</div>
|
|
290
|
+
</div>
|
|
291
|
+
)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Página principal
|
|
295
|
+
const ResponsiveTestPage = () => {
|
|
296
|
+
const { debug } = useResponsiveLayout()
|
|
297
|
+
|
|
298
|
+
return (
|
|
299
|
+
<div>
|
|
300
|
+
<BreakpointIndicator />
|
|
301
|
+
|
|
302
|
+
{/* Contenedor principal */}
|
|
303
|
+
<div className="w-full">
|
|
304
|
+
{/* Header elegante */}
|
|
305
|
+
<header className="text-center mb-6 bg-gradient-to-br from-gray-900 to-black rounded-2xl shadow-2xl p-6 border border-cyan-500/20">
|
|
306
|
+
<div className="inline-block bg-black/50 backdrop-blur-sm border border-cyan-500/30 text-cyan-400 rounded-lg px-4 py-2 mb-4">
|
|
307
|
+
<p className="text-xs font-bold tracking-widest uppercase">Suite de Pruebas</p>
|
|
308
|
+
</div>
|
|
309
|
+
<h1 className="text-4xl font-black text-white mb-4 tracking-tighter leading-none">
|
|
310
|
+
Test del Sistema
|
|
311
|
+
</h1>
|
|
312
|
+
<p className="text-base text-gray-400 mb-3 leading-relaxed tracking-wide">
|
|
313
|
+
Validación completa de propiedades auto-escalables
|
|
314
|
+
</p>
|
|
315
|
+
<div className="flex flex-wrap justify-center gap-2 text-sm">
|
|
316
|
+
<span className="text-gray-500">Tipografía</span>
|
|
317
|
+
<span className="text-gray-700">•</span>
|
|
318
|
+
<span className="text-gray-500">Espaciado</span>
|
|
319
|
+
<span className="text-gray-700">•</span>
|
|
320
|
+
<span className="text-gray-500">Alto de Línea</span>
|
|
321
|
+
<span className="text-gray-700">•</span>
|
|
322
|
+
<span className="text-gray-500">Espaciado de Letras</span>
|
|
323
|
+
<span className="text-gray-700">•</span>
|
|
324
|
+
<span className="text-gray-500">Sombras</span>
|
|
325
|
+
</div>
|
|
326
|
+
{debug && (
|
|
327
|
+
<div className="inline-block bg-yellow-900/30 border border-yellow-600/30 text-yellow-400 rounded-lg font-bold px-4 py-2 mt-4">
|
|
328
|
+
<p className="text-sm tracking-widest uppercase">Modo Debug Activo</p>
|
|
329
|
+
</div>
|
|
330
|
+
)}
|
|
331
|
+
</header>
|
|
332
|
+
|
|
333
|
+
{/* Layout profesional - jerarquía lógica */}
|
|
334
|
+
<div className="mb-6 space-y-6">
|
|
335
|
+
|
|
336
|
+
{/* Fila 1: Boolean Helpers - Ancho completo */}
|
|
337
|
+
<div className="bg-gradient-to-br from-gray-900 to-black rounded-2xl shadow-2xl p-6 border border-cyan-500/20 hover:border-cyan-500/40 transition-all">
|
|
338
|
+
<BooleanHelpersTest />
|
|
339
|
+
</div>
|
|
340
|
+
|
|
341
|
+
{/* Fila 2: Auto-scale Properties - Ancho completo */}
|
|
342
|
+
<div className="bg-gradient-to-br from-gray-900 to-black rounded-2xl shadow-2xl p-6 border border-gray-800 hover:border-gray-700 transition-all">
|
|
343
|
+
<TailwindUtilsTest />
|
|
344
|
+
</div>
|
|
345
|
+
|
|
346
|
+
{/* Fila 3: Orientation - Horizontal */}
|
|
347
|
+
<div className="bg-gradient-to-br from-gray-900 to-black rounded-2xl shadow-2xl p-6 border border-cyan-500/20 hover:border-cyan-500/40 transition-all">
|
|
348
|
+
<OrientationTest />
|
|
349
|
+
</div>
|
|
350
|
+
|
|
351
|
+
{/* Fila 3: Comparaciones y tests principales */}
|
|
352
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
353
|
+
<div className="bg-gradient-to-br from-gray-900 to-black rounded-2xl shadow-2xl p-6 border border-gray-800 hover:border-gray-700 transition-all">
|
|
354
|
+
<ComparisonTest />
|
|
355
|
+
</div>
|
|
356
|
+
|
|
357
|
+
<div className="bg-gradient-to-br from-gray-900 to-black rounded-2xl shadow-2xl p-6 border border-cyan-500/20 hover:border-cyan-500/40 transition-all">
|
|
358
|
+
<GridTest />
|
|
359
|
+
</div>
|
|
360
|
+
</div>
|
|
361
|
+
|
|
362
|
+
</div>
|
|
363
|
+
|
|
364
|
+
{/* Layout Switcher */}
|
|
365
|
+
<div className="mb-6">
|
|
366
|
+
<LayoutSwitcher />
|
|
367
|
+
</div>
|
|
368
|
+
|
|
369
|
+
{/* Footer*/}
|
|
370
|
+
<footer className="bg-gradient-to-br from-gray-900 to-black rounded-2xl shadow-2xl text-center p-6 border border-cyan-500/20">
|
|
371
|
+
<div className="space-y-4">
|
|
372
|
+
<div className="w-12 h-1 bg-gradient-to-r from-transparent via-cyan-400 to-transparent mx-auto"></div>
|
|
373
|
+
<p className="text-2xl font-black text-white leading-none tracking-tighter">
|
|
374
|
+
Sistema en Vivo
|
|
375
|
+
</p>
|
|
376
|
+
<p className="text-base text-gray-400 leading-relaxed tracking-wide max-w-2xl mx-auto">
|
|
377
|
+
Redimensiona tu ventana para observar el comportamiento de escalado automático en tiempo real
|
|
378
|
+
</p>
|
|
379
|
+
<div className="flex justify-center gap-3 flex-wrap mt-4">
|
|
380
|
+
<div className="bg-black/50 backdrop-blur-sm border border-cyan-500/30 px-4 py-2 rounded-lg">
|
|
381
|
+
<p className="text-sm font-bold tracking-widest text-cyan-400 uppercase">5 Propiedades</p>
|
|
382
|
+
</div>
|
|
383
|
+
<div className="bg-black/50 backdrop-blur-sm border border-gray-700 px-4 py-2 rounded-lg">
|
|
384
|
+
<p className="text-sm font-bold tracking-widest text-gray-400 uppercase">9 Breakpoints</p>
|
|
385
|
+
</div>
|
|
386
|
+
<div className="bg-black/50 backdrop-blur-sm border border-gray-700 px-4 py-2 rounded-lg">
|
|
387
|
+
<p className="text-sm font-bold tracking-widest text-gray-400 uppercase">Auto-Escalado</p>
|
|
388
|
+
</div>
|
|
389
|
+
</div>
|
|
390
|
+
<p className="text-xs text-gray-600 mt-4 leading-relaxed tracking-wide">
|
|
391
|
+
Indicador de breakpoint ubicado en la parte inferior central
|
|
392
|
+
</p>
|
|
393
|
+
</div>
|
|
394
|
+
</footer>
|
|
395
|
+
</div>
|
|
396
|
+
</div>
|
|
397
|
+
)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
export default ResponsiveTestPage
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
import { ResponsiveProvider } from './index'
|
|
3
|
+
import { useResponsive } from '../hooks'
|
|
4
|
+
import { ResponsiveLayoutContext } from '../context'
|
|
5
|
+
import { LAYOUT_CONFIG, DEFAULT_LAYOUT } from '../config/layout'
|
|
6
|
+
import type { ResponsiveState } from '../types/responsive'
|
|
7
|
+
|
|
8
|
+
interface ResponsiveLayoutProviderProps {
|
|
9
|
+
children: React.ReactNode
|
|
10
|
+
defaultLayout?: string
|
|
11
|
+
/**
|
|
12
|
+
* Hook responsivo personalizado del proyecto consumidor.
|
|
13
|
+
* Si se proporciona, se usará en lugar del hook interno del paquete.
|
|
14
|
+
* Debe retornar un objeto compatible con ResponsiveState.
|
|
15
|
+
*/
|
|
16
|
+
useResponsiveHook?: () => ResponsiveState
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface ResponsiveLayoutProviderInnerProps {
|
|
20
|
+
children: React.ReactNode
|
|
21
|
+
defaultLayout: string
|
|
22
|
+
useResponsiveHook?: () => ResponsiveState
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const ResponsiveLayoutProviderInner: React.FC<ResponsiveLayoutProviderInnerProps> = ({
|
|
26
|
+
children,
|
|
27
|
+
defaultLayout,
|
|
28
|
+
useResponsiveHook
|
|
29
|
+
}) => {
|
|
30
|
+
// Usar hook personalizado si se proporciona, sino usar el hook interno
|
|
31
|
+
const internalResponsive = useResponsive()
|
|
32
|
+
const customResponsive = useResponsiveHook?.()
|
|
33
|
+
const responsive = customResponsive || internalResponsive
|
|
34
|
+
|
|
35
|
+
const [currentLayout, setCurrentLayout] = useState(defaultLayout)
|
|
36
|
+
|
|
37
|
+
const layoutConfig = LAYOUT_CONFIG[currentLayout] || LAYOUT_CONFIG[DEFAULT_LAYOUT]
|
|
38
|
+
|
|
39
|
+
const layoutUtils = {
|
|
40
|
+
getContainerClass: () => {
|
|
41
|
+
if (responsive.isMobile) return layoutConfig.responsive.mobile
|
|
42
|
+
if (responsive.isTablet) return layoutConfig.responsive.tablet
|
|
43
|
+
return layoutConfig.responsive.desktop
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
getMainClass: () => {
|
|
47
|
+
const baseClass = 'min-h-screen bg-black'
|
|
48
|
+
if (currentLayout === 'sidebar' || currentLayout === 'dashboard') {
|
|
49
|
+
return `${baseClass} flex`
|
|
50
|
+
}
|
|
51
|
+
return baseClass
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
hasSidebar: () => currentLayout === 'sidebar' || currentLayout === 'dashboard',
|
|
55
|
+
hasHeader: () => currentLayout === 'dashboard',
|
|
56
|
+
hasFooter: () => currentLayout === 'default' || currentLayout === 'dashboard',
|
|
57
|
+
hasNavigation: () => currentLayout === 'default',
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const contextValue = {
|
|
61
|
+
responsive,
|
|
62
|
+
layout: {
|
|
63
|
+
current: currentLayout,
|
|
64
|
+
config: layoutConfig,
|
|
65
|
+
setLayout: setCurrentLayout,
|
|
66
|
+
},
|
|
67
|
+
layoutUtils,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<ResponsiveLayoutContext.Provider value={contextValue}>
|
|
72
|
+
{children}
|
|
73
|
+
</ResponsiveLayoutContext.Provider>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const ResponsiveLayoutProvider: React.FC<ResponsiveLayoutProviderProps> = ({
|
|
78
|
+
children,
|
|
79
|
+
defaultLayout = DEFAULT_LAYOUT,
|
|
80
|
+
useResponsiveHook
|
|
81
|
+
}) => {
|
|
82
|
+
return (
|
|
83
|
+
<ResponsiveProvider>
|
|
84
|
+
<ResponsiveLayoutProviderInner
|
|
85
|
+
defaultLayout={defaultLayout}
|
|
86
|
+
useResponsiveHook={useResponsiveHook}
|
|
87
|
+
>
|
|
88
|
+
{children}
|
|
89
|
+
</ResponsiveLayoutProviderInner>
|
|
90
|
+
</ResponsiveProvider>
|
|
91
|
+
)
|
|
92
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import type { ResponsiveProviderProps } from '../types/responsive'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* ResponsiveProvider - Provider simplificado para el sistema responsive
|
|
6
|
+
*
|
|
7
|
+
* Nota: Con el sistema de auto-scaling mediante plugin de Tailwind,
|
|
8
|
+
* este Provider es OPCIONAL y solo se necesita si quieres acceder
|
|
9
|
+
* al hook useResponsive() en tus componentes.
|
|
10
|
+
*/
|
|
11
|
+
export const ResponsiveProvider: React.FC<ResponsiveProviderProps> = ({
|
|
12
|
+
children,
|
|
13
|
+
debug: _debug = false
|
|
14
|
+
}) => {
|
|
15
|
+
// El Provider ahora solo envuelve children sin context
|
|
16
|
+
// El auto-scaling funciona mediante el plugin de Tailwind
|
|
17
|
+
return <>{children}</>
|
|
18
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Tipos para el sistema responsive
|
|
2
|
+
import type React from 'react'
|
|
3
|
+
|
|
4
|
+
export type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl'
|
|
5
|
+
|
|
6
|
+
export type Orientation = 'portrait' | 'landscape'
|
|
7
|
+
|
|
8
|
+
// Estado del hook useResponsive (simplificado)
|
|
9
|
+
export interface ResponsiveState {
|
|
10
|
+
// Breakpoint actual
|
|
11
|
+
breakpoint: Breakpoint
|
|
12
|
+
|
|
13
|
+
// Dimensiones
|
|
14
|
+
width: number
|
|
15
|
+
height: number
|
|
16
|
+
|
|
17
|
+
// Orientación
|
|
18
|
+
orientation: Orientation
|
|
19
|
+
isPortrait: boolean
|
|
20
|
+
isLandscape: boolean
|
|
21
|
+
|
|
22
|
+
// Helpers booleanos específicos
|
|
23
|
+
isXs: boolean
|
|
24
|
+
isSm: boolean
|
|
25
|
+
isMd: boolean
|
|
26
|
+
isLg: boolean
|
|
27
|
+
isXl: boolean
|
|
28
|
+
is2Xl: boolean
|
|
29
|
+
is3Xl: boolean
|
|
30
|
+
is4Xl: boolean
|
|
31
|
+
is5Xl: boolean
|
|
32
|
+
|
|
33
|
+
// Helpers agrupados
|
|
34
|
+
isMobile: boolean
|
|
35
|
+
isTablet: boolean
|
|
36
|
+
isDesktop: boolean
|
|
37
|
+
isSmall: boolean
|
|
38
|
+
isLarge: boolean
|
|
39
|
+
isUltraWide: boolean
|
|
40
|
+
is4K: boolean
|
|
41
|
+
is5K: boolean
|
|
42
|
+
|
|
43
|
+
// Funciones de comparación de breakpoints
|
|
44
|
+
isBreakpointUp: (breakpoint: Breakpoint) => boolean
|
|
45
|
+
isBreakpointDown: (breakpoint: Breakpoint) => boolean
|
|
46
|
+
isBreakpointBetween: (min: Breakpoint, max: Breakpoint) => boolean
|
|
47
|
+
|
|
48
|
+
// Funciones de comparación de dimensiones
|
|
49
|
+
isWidthUp: (width: number) => boolean
|
|
50
|
+
isWidthDown: (width: number) => boolean
|
|
51
|
+
isWidthBetween: (min: number, max: number) => boolean
|
|
52
|
+
isHeightUp: (height: number) => boolean
|
|
53
|
+
isHeightDown: (height: number) => boolean
|
|
54
|
+
isHeightBetween: (min: number, max: number) => boolean
|
|
55
|
+
|
|
56
|
+
// Debug
|
|
57
|
+
debug: boolean
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Configuración del provider (simplificada)
|
|
61
|
+
export interface ResponsiveProviderProps {
|
|
62
|
+
children: React.ReactNode
|
|
63
|
+
debug?: boolean
|
|
64
|
+
}
|