responsive-system 1.5.4 → 1.6.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.
@@ -0,0 +1,252 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Script de prueba para validar el postinstall.js
5
+ * Simula un proyecto vacío y verifica que todo se genere correctamente
6
+ */
7
+
8
+ import fs from 'fs'
9
+ import path from 'path'
10
+ import { execSync } from 'child_process'
11
+ import { fileURLToPath } from 'url'
12
+
13
+ const __filename = fileURLToPath(import.meta.url)
14
+ const __dirname = path.dirname(__filename)
15
+
16
+ // Crear directorio temporal para pruebas
17
+ const testDir = path.join(__dirname, '..', '.test-project')
18
+ const projectRoot = testDir
19
+
20
+ console.log('🧪 Iniciando pruebas del script postinstall...')
21
+ console.log(` Directorio de prueba: ${testDir}`)
22
+ console.log('')
23
+
24
+ // Limpiar directorio de prueba si existe
25
+ if (fs.existsSync(testDir)) {
26
+ console.log('🧹 Limpiando directorio de prueba anterior...')
27
+ try {
28
+ fs.rmSync(testDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 1000 })
29
+ } catch (error) {
30
+ console.log(' ⚠️ No se pudo limpiar completamente, continuando...')
31
+ // Intentar eliminar solo los archivos importantes
32
+ try {
33
+ const importantFiles = ['package.json', 'src', 'vite.config.ts', 'tailwind.config.js', 'postcss.config.js', 'tsconfig.json', 'tsconfig.node.json', 'index.html']
34
+ importantFiles.forEach(file => {
35
+ const filePath = path.join(testDir, file)
36
+ if (fs.existsSync(filePath)) {
37
+ try {
38
+ fs.rmSync(filePath, { recursive: true, force: true })
39
+ } catch (e) {
40
+ // Ignorar errores individuales
41
+ }
42
+ }
43
+ })
44
+ } catch (e) {
45
+ // Continuar de todas formas
46
+ }
47
+ }
48
+ }
49
+
50
+ // Crear directorio de prueba
51
+ fs.mkdirSync(testDir, { recursive: true })
52
+
53
+ // Crear package.json vacío (simulando proyecto nuevo)
54
+ const testPackageJson = {
55
+ name: 'test-project',
56
+ version: '1.0.0',
57
+ type: 'module',
58
+ dependencies: {
59
+ 'responsive-system': '^1.6.0'
60
+ }
61
+ }
62
+
63
+ fs.writeFileSync(
64
+ path.join(testDir, 'package.json'),
65
+ JSON.stringify(testPackageJson, null, 2)
66
+ )
67
+
68
+ console.log('✅ package.json de prueba creado')
69
+ console.log('')
70
+
71
+ // Cambiar al directorio de prueba
72
+ process.chdir(testDir)
73
+
74
+ // Simular ejecución del postinstall
75
+ console.log('📦 Ejecutando postinstall...')
76
+ console.log('')
77
+
78
+ // Importar y ejecutar el postinstall
79
+ const postinstallPath = path.join(__dirname, 'postinstall.js')
80
+
81
+ // Ejecutar el script con node
82
+ try {
83
+ // Simular variables de entorno de postinstall
84
+ process.env.npm_lifecycle_event = 'postinstall'
85
+
86
+ // Ejecutar el script
87
+ execSync(`node "${postinstallPath}"`, {
88
+ stdio: 'inherit',
89
+ cwd: testDir,
90
+ env: {
91
+ ...process.env,
92
+ npm_lifecycle_event: 'postinstall'
93
+ }
94
+ })
95
+
96
+ console.log('')
97
+ console.log('✅ Postinstall ejecutado')
98
+ console.log('')
99
+ } catch (error) {
100
+ console.error('❌ Error al ejecutar postinstall:', error.message)
101
+ process.exit(1)
102
+ }
103
+
104
+ // Verificaciones
105
+ console.log('🔍 Verificando archivos generados...')
106
+ console.log('')
107
+
108
+ const checks = []
109
+
110
+ // 1. Verificar que main.tsx existe y tiene el layout correcto
111
+ const mainTsxPath = path.join(testDir, 'src', 'main.tsx')
112
+ if (fs.existsSync(mainTsxPath)) {
113
+ const mainTsxContent = fs.readFileSync(mainTsxPath, 'utf8')
114
+
115
+ // Verificar que tiene ResponsiveLayoutProvider con defaultLayout
116
+ if (mainTsxContent.includes('ResponsiveLayoutProvider')) {
117
+ if (mainTsxContent.includes('defaultLayout="default"')) {
118
+ checks.push({ name: 'main.tsx tiene defaultLayout="default"', ok: true })
119
+ } else {
120
+ checks.push({ name: 'main.tsx tiene defaultLayout="default"', ok: false, error: 'No se encontró defaultLayout="default"' })
121
+ }
122
+ } else {
123
+ checks.push({ name: 'main.tsx tiene ResponsiveLayoutProvider', ok: false, error: 'No se encontró ResponsiveLayoutProvider' })
124
+ }
125
+ } else {
126
+ checks.push({ name: 'main.tsx existe', ok: false, error: 'Archivo no encontrado' })
127
+ }
128
+
129
+ // 2. Verificar que App.tsx existe
130
+ const appTsxPath = path.join(testDir, 'src', 'App.tsx')
131
+ if (fs.existsSync(appTsxPath)) {
132
+ checks.push({ name: 'App.tsx existe', ok: true })
133
+ } else {
134
+ checks.push({ name: 'App.tsx existe', ok: false, error: 'Archivo no encontrado' })
135
+ }
136
+
137
+ // 3. Verificar que HomePage.tsx existe
138
+ const homePagePath = path.join(testDir, 'src', 'pages', 'HomePage.tsx')
139
+ if (fs.existsSync(homePagePath)) {
140
+ checks.push({ name: 'HomePage.tsx existe', ok: true })
141
+ } else {
142
+ checks.push({ name: 'HomePage.tsx existe', ok: false, error: 'Archivo no encontrado' })
143
+ }
144
+
145
+ // 4. Verificar que los componentes del layout "default" se generaron
146
+ const navigationPath = path.join(testDir, 'src', 'components', 'layout', 'Navigation.tsx')
147
+ const footerPath = path.join(testDir, 'src', 'components', 'layout', 'Footer.tsx')
148
+ const sidebarPath = path.join(testDir, 'src', 'components', 'layout', 'Sidebar.tsx')
149
+
150
+ if (fs.existsSync(navigationPath)) {
151
+ checks.push({ name: 'Navigation.tsx generado (layout default)', ok: true })
152
+ } else {
153
+ checks.push({ name: 'Navigation.tsx generado (layout default)', ok: false, error: 'Archivo no encontrado' })
154
+ }
155
+
156
+ if (fs.existsSync(footerPath)) {
157
+ checks.push({ name: 'Footer.tsx generado (layout default)', ok: true })
158
+ } else {
159
+ checks.push({ name: 'Footer.tsx generado (layout default)', ok: false, error: 'Archivo no encontrado' })
160
+ }
161
+
162
+ // Verificar que Sidebar NO se generó para layout "default"
163
+ if (!fs.existsSync(sidebarPath)) {
164
+ checks.push({ name: 'Sidebar.tsx NO generado (correcto para default)', ok: true })
165
+ } else {
166
+ checks.push({ name: 'Sidebar.tsx NO generado (correcto para default)', ok: false, error: 'Sidebar.tsx no debería existir para layout default' })
167
+ }
168
+
169
+ // 5. Verificar que useResponsive se copió
170
+ const useResponsivePath = path.join(testDir, 'src', 'hooks', 'useResponsive.ts')
171
+ if (fs.existsSync(useResponsivePath)) {
172
+ checks.push({ name: 'useResponsive.ts copiado', ok: true })
173
+ } else {
174
+ checks.push({ name: 'useResponsive.ts copiado', ok: false, error: 'Archivo no encontrado' })
175
+ }
176
+
177
+ // 6. Verificar que los archivos de configuración existen
178
+ const configFiles = [
179
+ { path: 'vite.config.ts', name: 'vite.config.ts' },
180
+ { path: 'tailwind.config.js', name: 'tailwind.config.js' },
181
+ { path: 'postcss.config.js', name: 'postcss.config.js' },
182
+ { path: 'tsconfig.json', name: 'tsconfig.json' },
183
+ { path: 'tsconfig.node.json', name: 'tsconfig.node.json' },
184
+ { path: 'index.html', name: 'index.html' },
185
+ { path: 'src/index.css', name: 'src/index.css' }
186
+ ]
187
+
188
+ configFiles.forEach(({ path: filePath, name }) => {
189
+ const fullPath = path.join(testDir, filePath)
190
+ if (fs.existsSync(fullPath)) {
191
+ checks.push({ name: `${name} existe`, ok: true })
192
+ } else {
193
+ checks.push({ name: `${name} existe`, ok: false, error: 'Archivo no encontrado' })
194
+ }
195
+ })
196
+
197
+ // 7. Verificar que package.json tiene las dependencias correctas
198
+ const finalPackageJson = JSON.parse(fs.readFileSync(path.join(testDir, 'package.json'), 'utf8'))
199
+ const requiredDeps = ['react', 'react-dom']
200
+ const requiredDevDeps = ['vite', '@vitejs/plugin-react', 'tailwindcss', '@tailwindcss/postcss', 'postcss', 'autoprefixer', 'typescript', '@types/react', '@types/react-dom']
201
+
202
+ requiredDeps.forEach(dep => {
203
+ if (finalPackageJson.dependencies && finalPackageJson.dependencies[dep]) {
204
+ checks.push({ name: `Dependency ${dep} agregada`, ok: true })
205
+ } else {
206
+ checks.push({ name: `Dependency ${dep} agregada`, ok: false, error: 'No encontrada en dependencies' })
207
+ }
208
+ })
209
+
210
+ requiredDevDeps.forEach(dep => {
211
+ if (finalPackageJson.devDependencies && finalPackageJson.devDependencies[dep]) {
212
+ checks.push({ name: `DevDependency ${dep} agregada`, ok: true })
213
+ } else {
214
+ checks.push({ name: `DevDependency ${dep} agregada`, ok: false, error: 'No encontrada en devDependencies' })
215
+ }
216
+ })
217
+
218
+ // Mostrar resultados
219
+ console.log('📊 Resultados de las verificaciones:')
220
+ console.log('')
221
+
222
+ let allPassed = true
223
+ checks.forEach(check => {
224
+ if (check.ok) {
225
+ console.log(` ✅ ${check.name}`)
226
+ } else {
227
+ console.log(` ❌ ${check.name}`)
228
+ if (check.error) {
229
+ console.log(` Error: ${check.error}`)
230
+ }
231
+ allPassed = false
232
+ }
233
+ })
234
+
235
+ console.log('')
236
+
237
+ if (allPassed) {
238
+ console.log('🎉 ¡Todas las verificaciones pasaron!')
239
+ console.log('')
240
+ console.log('💡 El script postinstall está funcionando correctamente.')
241
+ console.log(' Puedes publicar el paquete con confianza.')
242
+ } else {
243
+ console.log('⚠️ Algunas verificaciones fallaron.')
244
+ console.log(' Revisa los errores antes de publicar.')
245
+ process.exit(1)
246
+ }
247
+
248
+ console.log('')
249
+ console.log(`📁 Directorio de prueba: ${testDir}`)
250
+ console.log(' Puedes revisar los archivos generados allí.')
251
+ console.log('')
252
+
@@ -13,7 +13,7 @@ const DefaultLayout: React.FC<DefaultLayoutProps> = ({ children }) => {
13
13
 
14
14
  {/* Main content */}
15
15
  <main className="flex-1">
16
- {children}
16
+ {children}
17
17
  </main>
18
18
 
19
19
  {/* Footer fijo abajo */}
@@ -19,10 +19,7 @@ interface MainLayoutProps {
19
19
  const MainLayout: React.FC<MainLayoutProps> = ({ children, layout: layoutProp }) => {
20
20
  const { layout } = useResponsiveLayout()
21
21
 
22
- // Usar el layout del prop si se proporciona, sino usar el del contexto
23
- const currentLayout = layoutProp || layout.current
24
-
25
- // Seleccionar el layout apropiado basado en el estado del contexto o prop
22
+ // Mapa de layouts disponibles
26
23
  const layouts = {
27
24
  default: DefaultLayout,
28
25
  sidebar: SidebarLayout,
@@ -30,11 +27,15 @@ const MainLayout: React.FC<MainLayoutProps> = ({ children, layout: layoutProp })
30
27
  minimal: MinimalLayout,
31
28
  }
32
29
 
33
- // Validar que el layout sea válido, si no, usar default
34
- const validLayout = (currentLayout && layouts[currentLayout as keyof typeof layouts])
35
- ? currentLayout
30
+ // Determinar qué layout usar: prop > contexto > default
31
+ const layoutToUse = layoutProp || layout.current || 'default'
32
+
33
+ // Validar que el layout sea válido, si no usar default
34
+ const validLayout = (layoutToUse && layouts[layoutToUse as keyof typeof layouts])
35
+ ? layoutToUse
36
36
  : 'default'
37
37
 
38
+ // Obtener el componente de layout
38
39
  const LayoutComponent = layouts[validLayout as keyof typeof layouts] || DefaultLayout
39
40
 
40
41
  return <LayoutComponent>{children}</LayoutComponent>
@@ -14,7 +14,7 @@ const SidebarLayoutContent: React.FC<{ children: React.ReactNode }> = ({ childre
14
14
 
15
15
  {/* Main content */}
16
16
  <main className="flex-1 overflow-auto">
17
- {children}
17
+ {children}
18
18
  </main>
19
19
  </div>
20
20
  )
@@ -32,14 +32,13 @@ const ResponsiveLayoutProviderInner: React.FC<ResponsiveLayoutProviderInnerProps
32
32
  const customResponsive = useResponsiveHook?.()
33
33
  const responsive = customResponsive || internalResponsive
34
34
 
35
- // Inicializar el estado con el defaultLayout usando función inicializadora
35
+ // Inicializar el estado con el layout normalizado usando función inicializadora
36
36
  // Esto asegura que solo se ejecute una vez, incluso con React.StrictMode
37
37
  const [currentLayout, setCurrentLayout] = useState(() => {
38
- // Validar que el defaultLayout sea válido
38
+ // Validar y normalizar el defaultLayout directamente en la función inicializadora
39
39
  if (defaultLayout && typeof defaultLayout === 'string' && LAYOUT_CONFIG[defaultLayout]) {
40
40
  return defaultLayout
41
41
  }
42
- // Si no es válido, usar el layout por defecto
43
42
  return DEFAULT_LAYOUT
44
43
  })
45
44
 
@@ -88,10 +87,15 @@ export const ResponsiveLayoutProvider: React.FC<ResponsiveLayoutProviderProps> =
88
87
  defaultLayout = DEFAULT_LAYOUT,
89
88
  useResponsiveHook
90
89
  }) => {
90
+ // Normalizar el defaultLayout antes de pasarlo al componente interno
91
+ const normalizedDefaultLayout = (defaultLayout && typeof defaultLayout === 'string' && LAYOUT_CONFIG[defaultLayout])
92
+ ? defaultLayout
93
+ : DEFAULT_LAYOUT
94
+
91
95
  return (
92
96
  <ResponsiveProvider>
93
97
  <ResponsiveLayoutProviderInner
94
- defaultLayout={defaultLayout}
98
+ defaultLayout={normalizedDefaultLayout}
95
99
  useResponsiveHook={useResponsiveHook}
96
100
  >
97
101
  {children}